Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/dtor/input.git manually

Some manual fixups required due to clashes with the PF_FREEZE cleanups.
diff --git a/CREDITS b/CREDITS
index 9bd099d..3b7a154 100644
--- a/CREDITS
+++ b/CREDITS
@@ -1880,6 +1880,13 @@
 S: D-91080 Uttenreuth
 S: Germany
 
+N: Jaya Kumar
+E: jayalk@intworks.biz
+W: http://www.intworks.biz
+D: Arc monochrome LCD framebuffer driver, x86 reboot fixups
+S: Gurgaon, India
+S: Kuala Lumpur, Malaysia
+
 N: Gabor Kuti
 M: seasons@falcon.sch.bme.hu
 M: seasons@makosteszta.sote.hu
@@ -2373,9 +2380,10 @@
 D: bug fixes, documentation, minor hackery
 
 N: James Morris
-E: jmorris@intercode.com.au
+E: jmorris@redhat.com
 W: http://www.intercode.com.au/jmorris/
-D: Netfilter, Linux Security Modules (LSM).
+D: Netfilter, Linux Security Modules (LSM), SELinux, IPSec,
+D: Crypto API, general networking, miscellaneous.
 S: PO Box 707
 S: Spit Junction NSW 2088
 S: Australia
@@ -2475,13 +2483,9 @@
 S: USA
 
 N: Dave Neuer
-E: dneuer@innovation-charter.com
-E: mr_fred_smoothie@yahoo.com
+E: dave.neuer@pobox.com
 D: Helped implement support for Compaq's H31xx series iPAQs
 D: Other mostly minor tweaks & bugfixes
-S: 325 E. Main St., Suite 3
-S: Carnegie, PA 15105
-S: USA
 
 N: Michael Neuffer
 E: mike@i-Connect.Net
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
index 8de8a01..f28a24e 100644
--- a/Documentation/00-INDEX
+++ b/Documentation/00-INDEX
@@ -138,6 +138,8 @@
 	- info on the in-kernel binary support for Java(tm).
 kbuild/
 	- directory with info about the kernel build process.
+kdumpt.txt
+       - mini HowTo on getting the crash dump code to work.
 kernel-doc-nano-HOWTO.txt
 	- mini HowTo on generation and location of kernel documentation files.
 kernel-docs.txt
diff --git a/Documentation/Changes b/Documentation/Changes
index 57542bc..b376007 100644
--- a/Documentation/Changes
+++ b/Documentation/Changes
@@ -63,7 +63,7 @@
 o  isdn4k-utils           3.1pre1                 # isdnctrl 2>&1|grep version
 o  nfs-utils              1.0.5                   # showmount --version
 o  procps                 3.2.0                   # ps --version
-o  oprofile               0.5.3                   # oprofiled --version
+o  oprofile               0.9                     # oprofiled --version
 
 Kernel compilation
 ==================
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index e69b3d2..fa3e29a 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -8,7 +8,7 @@
 
 DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
 	    kernel-hacking.xml kernel-locking.xml deviceiobook.xml \
-	    procfs-guide.xml writing_usb_driver.xml scsidrivers.xml \
+	    procfs-guide.xml writing_usb_driver.xml \
 	    sis900.xml kernel-api.xml journal-api.xml lsm.xml usb.xml \
 	    gadget.xml libata.xml mtdnand.xml librs.xml
 
@@ -49,7 +49,7 @@
 KERNELDOC = scripts/kernel-doc
 DOCPROC   = scripts/basic/docproc
 
-XMLTOFLAGS = -m Documentation/DocBook/stylesheet.xsl
+XMLTOFLAGS = -m $(srctree)/Documentation/DocBook/stylesheet.xsl
 #XMLTOFLAGS += --skip-validation
 
 ###
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 757cef8..d650ce3 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -266,7 +266,7 @@
   <chapter id="hardware">
      <title>Hardware Interfaces</title>
      <sect1><title>Interrupt Handling</title>
-!Iarch/i386/kernel/irq.c
+!Ikernel/irq/manage.c
      </sect1>
 
      <sect1><title>Resources Management</title>
@@ -338,7 +338,6 @@
 X!Iinclude/linux/device.h
 -->
 !Edrivers/base/driver.c
-!Edrivers/base/class_simple.c
 !Edrivers/base/core.c
 !Edrivers/base/firmware_class.c
 !Edrivers/base/transport_class.c
diff --git a/Documentation/DocBook/scsidrivers.tmpl b/Documentation/DocBook/scsidrivers.tmpl
deleted file mode 100644
index d058e65..0000000
--- a/Documentation/DocBook/scsidrivers.tmpl
+++ /dev/null
@@ -1,193 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
-	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
-
-<book id="scsidrivers">
- <bookinfo>
-  <title>SCSI Subsystem Interfaces</title>
-  
-  <authorgroup>
-   <author>
-    <firstname>Douglas</firstname>
-    <surname>Gilbert</surname>
-    <affiliation>
-     <address>
-      <email>dgilbert@interlog.com</email>
-     </address>
-    </affiliation>
-   </author>
-  </authorgroup>
-  <pubdate>2003-08-11</pubdate>
-
-  <copyright>
-   <year>2002</year>
-   <year>2003</year>
-   <holder>Douglas Gilbert</holder>
-  </copyright>
-
-  <legalnotice>
-   <para>
-     This documentation 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.
-   </para>
-      
-   <para>
-     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.
-   </para>
-      
-   <para>
-     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
-   </para>
-      
-   <para>
-     For more details see the file COPYING in the source
-     distribution of Linux.
-   </para>
-  </legalnotice>
-
- </bookinfo>
-
-<toc></toc>
-
-  <chapter id="intro">
-      <title>Introduction</title>
-  <para>
-This document outlines the interface between the Linux scsi mid level
-and lower level drivers. Lower level drivers are variously called HBA
-(host bus adapter) drivers, host drivers (HD) or pseudo adapter drivers.
-The latter alludes to the fact that a lower level driver may be a
-bridge to another IO subsystem (and the "ide-scsi" driver is an example
-of this). There can be many lower level drivers active in a running
-system, but only one per hardware type. For example, the aic7xxx driver
-controls adaptec controllers based on the 7xxx chip series. Most lower
-level drivers can control one or more scsi hosts (a.k.a. scsi initiators).
-  </para>
-<para>
-This document can been found in an ASCII text file in the linux kernel 
-source: <filename>Documentation/scsi/scsi_mid_low_api.txt</filename> .
-It currently hold a little more information than this document. The
-<filename>drivers/scsi/hosts.h</filename> and <filename>
-drivers/scsi/scsi.h</filename> headers contain descriptions of members
-of important structures for the scsi subsystem.
-</para>
-  </chapter>
-
-  <chapter id="driver-struct">
-      <title>Driver structure</title>
-  <para>
-Traditionally a lower level driver for the scsi subsystem has been
-at least two files in the drivers/scsi directory. For example, a
-driver called "xyz" has a header file "xyz.h" and a source file
-"xyz.c". [Actually there is no good reason why this couldn't all
-be in one file.] Some drivers that have been ported to several operating
-systems (e.g. aic7xxx which has separate  files for generic and
-OS-specific code) have more than two files. Such drivers tend to have
-their own directory under the drivers/scsi directory.
-  </para>
-  <para>
-scsi_module.c is normally included at the end of a lower
-level driver. For it to work a declaration like this is needed before
-it is included:
-<programlisting>
-    static Scsi_Host_Template driver_template = DRIVER_TEMPLATE;
-    /* DRIVER_TEMPLATE should contain pointers to supported interface
-       functions. Scsi_Host_Template is defined hosts.h */
-    #include "scsi_module.c"
-</programlisting>
-  </para>
-  <para>
-The scsi_module.c assumes the name "driver_template" is appropriately
-defined. It contains 2 functions:
-<orderedlist>
-<listitem><para>
-     init_this_scsi_driver() called during builtin and module driver
-     initialization: invokes mid level's scsi_register_host()
-</para></listitem>
-<listitem><para>
-     exit_this_scsi_driver() called during closedown: invokes
-     mid level's scsi_unregister_host()
-</para></listitem>
-</orderedlist>
-  </para>
-<para>
-When a new, lower level driver is being added to Linux, the following 
-files (all found in the drivers/scsi directory) will need some attention: 
-Makefile, Config.help and Config.in . It is probably best to look at what 
-an existing lower level driver does in this regard.
-</para>
-  </chapter>
-
-  <chapter id="intfunctions">
-     <title>Interface Functions</title>
-!EDocumentation/scsi/scsi_mid_low_api.txt
-  </chapter>
-
-  <chapter id="locks">
-     <title>Locks</title>
-<para>
-Each Scsi_Host instance has a spin_lock called Scsi_Host::default_lock
-which is initialized in scsi_register() [found in hosts.c]. Within the
-same function the Scsi_Host::host_lock pointer is initialized to point
-at default_lock with the scsi_assign_lock() function. Thereafter
-lock and unlock operations performed by the mid level use the
-Scsi_Host::host_lock pointer.
-</para>
-<para>
-Lower level drivers can override the use of Scsi_Host::default_lock by
-using scsi_assign_lock(). The earliest opportunity to do this would
-be in the detect() function after it has invoked scsi_register(). It
-could be replaced by a coarser grain lock (e.g. per driver) or a
-lock of equal granularity (i.e. per host). Using finer grain locks
-(e.g. per scsi device) may be possible by juggling locks in
-queuecommand().
-</para>
-  </chapter>
-
-  <chapter id="changes">
-     <title>Changes since lk 2.4 series</title>
-<para>
-io_request_lock has been replaced by several finer grained locks. The lock
-relevant to lower level drivers is Scsi_Host::host_lock and there is one
-per scsi host.
-</para>
-<para>
-The older error handling mechanism has been removed. This means the
-lower level interface functions abort() and reset() have been removed.
-</para>
-<para>
-In the 2.4 series the scsi subsystem configuration descriptions were
-aggregated with the configuration descriptions from all other Linux
-subsystems in the Documentation/Configure.help file. In the 2.5 series,
-the scsi subsystem now has its own (much smaller) drivers/scsi/Config.help
-file.
-</para>
-  </chapter>
-
-  <chapter id="credits">
-     <title>Credits</title>
-<para>
-The following people have contributed to this document:
-<orderedlist>
-<listitem><para>
-Mike Anderson <email>andmike@us.ibm.com</email>
-</para></listitem>
-<listitem><para>
-James Bottomley <email>James.Bottomley@steeleye.com</email>
-</para></listitem>
-<listitem><para>
-Patrick Mansfield <email>patmans@us.ibm.com</email>
-</para></listitem>
-</orderedlist>
-</para>
-  </chapter>
-
-</book>
diff --git a/Documentation/DocBook/stylesheet.xsl b/Documentation/DocBook/stylesheet.xsl
index e14c21d..64be9f7 100644
--- a/Documentation/DocBook/stylesheet.xsl
+++ b/Documentation/DocBook/stylesheet.xsl
@@ -2,4 +2,5 @@
 <stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0">
 <param name="chunk.quietly">1</param>
 <param name="funcsynopsis.style">ansi</param>
+<param name="funcsynopsis.tabular.threshold">80</param>
 </stylesheet>
diff --git a/Documentation/IPMI.txt b/Documentation/IPMI.txt
index 90d10e7..84d3d4d 100644
--- a/Documentation/IPMI.txt
+++ b/Documentation/IPMI.txt
@@ -25,9 +25,10 @@
 Configuration
 -------------
 
-The LinuxIPMI driver is modular, which means you have to pick several
+The Linux IPMI driver is modular, which means you have to pick several
 things to have it work right depending on your hardware.  Most of
-these are available in the 'Character Devices' menu.
+these are available in the 'Character Devices' menu then the IPMI
+menu.
 
 No matter what, you must pick 'IPMI top-level message handler' to use
 IPMI.  What you do beyond that depends on your needs and hardware.
@@ -35,33 +36,30 @@
 The message handler does not provide any user-level interfaces.
 Kernel code (like the watchdog) can still use it.  If you need access
 from userland, you need to select 'Device interface for IPMI' if you
-want access through a device driver.  Another interface is also
-available, you may select 'IPMI sockets' in the 'Networking Support'
-main menu.  This provides a socket interface to IPMI.  You may select
-both of these at the same time, they will both work together.
+want access through a device driver.
 
-The driver interface depends on your hardware.  If you have a board
-with a standard interface (These will generally be either "KCS",
-"SMIC", or "BT", consult your hardware manual), choose the 'IPMI SI
-handler' option.  A driver also exists for direct I2C access to the
-IPMI management controller.  Some boards support this, but it is
-unknown if it will work on every board.  For this, choose 'IPMI SMBus
-handler', but be ready to try to do some figuring to see if it will
-work.
-
-There is also a KCS-only driver interface supplied, but it is
-depracated in favor of the SI interface.
+The driver interface depends on your hardware.  If your system
+properly provides the SMBIOS info for IPMI, the driver will detect it
+and just work.  If you have a board with a standard interface (These
+will generally be either "KCS", "SMIC", or "BT", consult your hardware
+manual), choose the 'IPMI SI handler' option.  A driver also exists
+for direct I2C access to the IPMI management controller.  Some boards
+support this, but it is unknown if it will work on every board.  For
+this, choose 'IPMI SMBus handler', but be ready to try to do some
+figuring to see if it will work on your system if the SMBIOS/APCI
+information is wrong or not present.  It is fairly safe to have both
+these enabled and let the drivers auto-detect what is present.
 
 You should generally enable ACPI on your system, as systems with IPMI
-should have ACPI tables describing them.
+can have ACPI tables describing them.
 
 If you have a standard interface and the board manufacturer has done
 their job correctly, the IPMI controller should be automatically
-detect (via ACPI or SMBIOS tables) and should just work.  Sadly, many
-boards do not have this information.  The driver attempts standard
-defaults, but they may not work.  If you fall into this situation, you
-need to read the section below named 'The SI Driver' on how to
-hand-configure your system.
+detected (via ACPI or SMBIOS tables) and should just work.  Sadly,
+many boards do not have this information.  The driver attempts
+standard defaults, but they may not work.  If you fall into this
+situation, you need to read the section below named 'The SI Driver' or
+"The SMBus Driver" on how to hand-configure your system.
 
 IPMI defines a standard watchdog timer.  You can enable this with the
 'IPMI Watchdog Timer' config option.  If you compile the driver into
@@ -73,6 +71,18 @@
 Cards' menu, enable 'Watchdog Timer Support', and enable the option
 'Disable watchdog shutdown on close'.
 
+IPMI systems can often be powered off using IPMI commands.  Select
+'IPMI Poweroff' to do this.  The driver will auto-detect if the system
+can be powered off by IPMI.  It is safe to enable this even if your
+system doesn't support this option.  This works on ATCA systems, the
+Radisys CPI1 card, and any IPMI system that supports standard chassis
+management commands.
+
+If you want the driver to put an event into the event log on a panic,
+enable the 'Generate a panic event to all BMCs on a panic' option.  If
+you want the whole panic string put into the event log using OEM
+events, enable the 'Generate OEM events containing the panic string'
+option.
 
 Basic Design
 ------------
@@ -80,7 +90,7 @@
 The Linux IPMI driver is designed to be very modular and flexible, you
 only need to take the pieces you need and you can use it in many
 different ways.  Because of that, it's broken into many chunks of
-code.  These chunks are:
+code.  These chunks (by module name) are:
 
 ipmi_msghandler - This is the central piece of software for the IPMI
 system.  It handles all messages, message timing, and responses.  The
@@ -93,18 +103,26 @@
 driver, each open file for this device ties in to the message handler
 as an IPMI user.
 
-ipmi_si - A driver for various system interfaces.  This supports
-KCS, SMIC, and may support BT in the future.  Unless you have your own
-custom interface, you probably need to use this.
+ipmi_si - A driver for various system interfaces.  This supports KCS,
+SMIC, and BT interfaces.  Unless you have an SMBus interface or your
+own custom interface, you probably need to use this.
 
 ipmi_smb - A driver for accessing BMCs on the SMBus. It uses the
 I2C kernel driver's SMBus interfaces to send and receive IPMI messages
 over the SMBus.
 
-af_ipmi - A network socket interface to IPMI.  This doesn't take up
-a character device in your system.
+ipmi_watchdog - IPMI requires systems to have a very capable watchdog
+timer.  This driver implements the standard Linux watchdog timer
+interface on top of the IPMI message handler.
 
-Note that the KCS-only interface ahs been removed.
+ipmi_poweroff - Some systems support the ability to be turned off via
+IPMI commands.
+
+These are all individually selectable via configuration options.
+
+Note that the KCS-only interface has been removed.  The af_ipmi driver
+is no longer supported and has been removed because it was impossible
+to do 32 bit emulation on 64-bit kernels with it.
 
 Much documentation for the interface is in the include files.  The
 IPMI include files are:
@@ -424,7 +442,7 @@
   modprobe ipmi_smb.o
 	addr=<adapter1>,<i2caddr1>[,<adapter2>,<i2caddr2>[,...]]
 	dbg=<flags1>,<flags2>...
-	[defaultprobe=0] [dbg_probe=1]
+	[defaultprobe=1] [dbg_probe=1]
 
 The addresses are specified in pairs, the first is the adapter ID and the
 second is the I2C address on that adapter.
@@ -532,3 +550,67 @@
 device to close it, or the timer will not stop.  This is a new semantic
 for the driver, but makes it consistent with the rest of the watchdog
 drivers in Linux.
+
+
+Panic Timeouts
+--------------
+
+The OpenIPMI driver supports the ability to put semi-custom and custom
+events in the system event log if a panic occurs.  if you enable the
+'Generate a panic event to all BMCs on a panic' option, you will get
+one event on a panic in a standard IPMI event format.  If you enable
+the 'Generate OEM events containing the panic string' option, you will
+also get a bunch of OEM events holding the panic string.
+
+
+The field settings of the events are:
+* Generator ID: 0x21 (kernel)
+* EvM Rev: 0x03 (this event is formatting in IPMI 1.0 format)
+* Sensor Type: 0x20 (OS critical stop sensor)
+* Sensor #: The first byte of the panic string (0 if no panic string)
+* Event Dir | Event Type: 0x6f (Assertion, sensor-specific event info)
+* Event Data 1: 0xa1 (Runtime stop in OEM bytes 2 and 3)
+* Event data 2: second byte of panic string
+* Event data 3: third byte of panic string
+See the IPMI spec for the details of the event layout.  This event is
+always sent to the local management controller.  It will handle routing
+the message to the right place
+
+Other OEM events have the following format:
+Record ID (bytes 0-1): Set by the SEL.
+Record type (byte 2): 0xf0 (OEM non-timestamped)
+byte 3: The slave address of the card saving the panic
+byte 4: A sequence number (starting at zero)
+The rest of the bytes (11 bytes) are the panic string.  If the panic string
+is longer than 11 bytes, multiple messages will be sent with increasing
+sequence numbers.
+
+Because you cannot send OEM events using the standard interface, this
+function will attempt to find an SEL and add the events there.  It
+will first query the capabilities of the local management controller.
+If it has an SEL, then they will be stored in the SEL of the local
+management controller.  If not, and the local management controller is
+an event generator, the event receiver from the local management
+controller will be queried and the events sent to the SEL on that
+device.  Otherwise, the events go nowhere since there is nowhere to
+send them.
+
+
+Poweroff
+--------
+
+If the poweroff capability is selected, the IPMI driver will install
+a shutdown function into the standard poweroff function pointer.  This
+is in the ipmi_poweroff module.  When the system requests a powerdown,
+it will send the proper IPMI commands to do this.  This is supported on
+several platforms.
+
+There is a module parameter named "poweroff_control" that may either be zero
+(do a power down) or 2 (do a power cycle, power the system off, then power
+it on in a few seconds).  Setting ipmi_poweroff.poweroff_control=x will do
+the same thing on the kernel command line.  The parameter is also available
+via the proc filesystem in /proc/ipmi/poweroff_control.  Note that if the
+system does not support power cycling, it will always to the power off.
+
+Note that if you have ACPI enabled, the system will prefer using ACPI to
+power off.
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 9838d32..4d1f41b 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -132,21 +132,6 @@
 usually be sent first to linux-kernel.  Only after the patch is
 discussed should the patch then be submitted to Linus.
 
-For small patches you may want to CC the Trivial Patch Monkey
-trivial@rustcorp.com.au set up by Rusty Russell; which collects "trivial"
-patches. Trivial patches must qualify for one of the following rules:
- Spelling fixes in documentation
- Spelling fixes which could break grep(1).
- Warning fixes (cluttering with useless warnings is bad)
- Compilation fixes (only if they are actually correct)
- Runtime fixes (only if they actually fix things)
- Removing use of deprecated functions/macros (eg. check_region).
- Contact detail and documentation fixes
- Non-portable code replaced by portable code (even in arch-specific,
- since people copy, as long as it's trivial)
- Any fix by the author/maintainer of the file. (ie. patch monkey
- in re-transmission mode)
-
 
 
 5) Select your CC (e-mail carbon copy) list.
@@ -271,7 +256,7 @@
 pass it on as a open-source patch.  The rules are pretty simple: if you
 can certify the below:
 
-        Developer's Certificate of Origin 1.0
+        Developer's Certificate of Origin 1.1
 
         By making a contribution to this project, I certify that:
 
@@ -291,9 +276,15 @@
             person who certified (a), (b) or (c) and I have not modified
             it.
 
+	(d) I understand and agree that this project and the contribution
+	    are public and that a record of the contribution (including all
+	    personal information I submit with it, including my sign-off) is
+	    maintained indefinitely and may be redistributed consistent with
+	    this project or the open source license(s) involved.
+
 then you just add a line saying
 
-	Signed-off-by: Random J Developer <random@developer.org>
+	Signed-off-by: Random J Developer <random@developer.example.org>
 
 Some people also put extra tags at the end.  They'll just be ignored for
 now, but you can do this to mark internal company procedures or just
diff --git a/Documentation/basic_profiling.txt b/Documentation/basic_profiling.txt
index 65e3dc2..8764e9f 100644
--- a/Documentation/basic_profiling.txt
+++ b/Documentation/basic_profiling.txt
@@ -27,9 +27,13 @@
 
 Oprofile
 --------
-Get the source (I use 0.8) from http://oprofile.sourceforge.net/
-and add "idle=poll" to the kernel command line
+
+Get the source (see Changes for required version) from
+http://oprofile.sourceforge.net/ and add "idle=poll" to the kernel command
+line.
+
 Configure with CONFIG_PROFILING=y and CONFIG_OPROFILE=y & reboot on new kernel
+
 ./configure --with-kernel-support
 make install
 
@@ -46,7 +50,7 @@
 stop		opcontrol --stop
 dump output	opreport >  output_file
 
-To only report on the kernel, run opreport /boot/vmlinux > output_file
+To only report on the kernel, run opreport -l /boot/vmlinux > output_file
 
 A reset is needed to clear old statistics, which survive a reboot.
 
diff --git a/Documentation/block/ioprio.txt b/Documentation/block/ioprio.txt
new file mode 100644
index 0000000..96ccf68
--- /dev/null
+++ b/Documentation/block/ioprio.txt
@@ -0,0 +1,176 @@
+Block io priorities
+===================
+
+
+Intro
+-----
+
+With the introduction of cfq v3 (aka cfq-ts or time sliced cfq), basic io
+priorities is supported for reads on files. This enables users to io nice
+processes or process groups, similar to what has been possible to cpu
+scheduling for ages. This document mainly details the current possibilites
+with cfq, other io schedulers do not support io priorities so far.
+
+Scheduling classes
+------------------
+
+CFQ implements three generic scheduling classes that determine how io is
+served for a process.
+
+IOPRIO_CLASS_RT: This is the realtime io class. This scheduling class is given
+higher priority than any other in the system, processes from this class are
+given first access to the disk every time. Thus it needs to be used with some
+care, one io RT process can starve the entire system. Within the RT class,
+there are 8 levels of class data that determine exactly how much time this
+process needs the disk for on each service. In the future this might change
+to be more directly mappable to performance, by passing in a wanted data
+rate instead.
+
+IOPRIO_CLASS_BE: This is the best-effort scheduling class, which is the default
+for any process that hasn't set a specific io priority. The class data
+determines how much io bandwidth the process will get, it's directly mappable
+to the cpu nice levels just more coarsely implemented. 0 is the highest
+BE prio level, 7 is the lowest. The mapping between cpu nice level and io
+nice level is determined as: io_nice = (cpu_nice + 20) / 5.
+
+IOPRIO_CLASS_IDLE: This is the idle scheduling class, processes running at this
+level only get io time when no one else needs the disk. The idle class has no
+class data, since it doesn't really apply here.
+
+Tools
+-----
+
+See below for a sample ionice tool. Usage:
+
+# ionice -c<class> -n<level> -p<pid>
+
+If pid isn't given, the current process is assumed. IO priority settings
+are inherited on fork, so you can use ionice to start the process at a given
+level:
+
+# ionice -c2 -n0 /bin/ls
+
+will run ls at the best-effort scheduling class at the highest priority.
+For a running process, you can give the pid instead:
+
+# ionice -c1 -n2 -p100
+
+will change pid 100 to run at the realtime scheduling class, at priority 2.
+
+---> snip ionice.c tool <---
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <sys/ptrace.h>
+#include <asm/unistd.h>
+
+extern int sys_ioprio_set(int, int, int);
+extern int sys_ioprio_get(int, int);
+
+#if defined(__i386__)
+#define __NR_ioprio_set		289
+#define __NR_ioprio_get		290
+#elif defined(__ppc__)
+#define __NR_ioprio_set		273
+#define __NR_ioprio_get		274
+#elif defined(__x86_64__)
+#define __NR_ioprio_set		251
+#define __NR_ioprio_get		252
+#elif defined(__ia64__)
+#define __NR_ioprio_set		1274
+#define __NR_ioprio_get		1275
+#else
+#error "Unsupported arch"
+#endif
+
+_syscall3(int, ioprio_set, int, which, int, who, int, ioprio);
+_syscall2(int, ioprio_get, int, which, int, who);
+
+enum {
+	IOPRIO_CLASS_NONE,
+	IOPRIO_CLASS_RT,
+	IOPRIO_CLASS_BE,
+	IOPRIO_CLASS_IDLE,
+};
+
+enum {
+	IOPRIO_WHO_PROCESS = 1,
+	IOPRIO_WHO_PGRP,
+	IOPRIO_WHO_USER,
+};
+
+#define IOPRIO_CLASS_SHIFT	13
+
+const char *to_prio[] = { "none", "realtime", "best-effort", "idle", };
+
+int main(int argc, char *argv[])
+{
+	int ioprio = 4, set = 0, ioprio_class = IOPRIO_CLASS_BE;
+	int c, pid = 0;
+
+	while ((c = getopt(argc, argv, "+n:c:p:")) != EOF) {
+		switch (c) {
+		case 'n':
+			ioprio = strtol(optarg, NULL, 10);
+			set = 1;
+			break;
+		case 'c':
+			ioprio_class = strtol(optarg, NULL, 10);
+			set = 1;
+			break;
+		case 'p':
+			pid = strtol(optarg, NULL, 10);
+			break;
+		}
+	}
+
+	switch (ioprio_class) {
+		case IOPRIO_CLASS_NONE:
+			ioprio_class = IOPRIO_CLASS_BE;
+			break;
+		case IOPRIO_CLASS_RT:
+		case IOPRIO_CLASS_BE:
+			break;
+		case IOPRIO_CLASS_IDLE:
+			ioprio = 7;
+			break;
+		default:
+			printf("bad prio class %d\n", ioprio_class);
+			return 1;
+	}
+
+	if (!set) {
+		if (!pid && argv[optind])
+			pid = strtol(argv[optind], NULL, 10);
+
+		ioprio = ioprio_get(IOPRIO_WHO_PROCESS, pid);
+
+		printf("pid=%d, %d\n", pid, ioprio);
+
+		if (ioprio == -1)
+			perror("ioprio_get");
+		else {
+			ioprio_class = ioprio >> IOPRIO_CLASS_SHIFT;
+			ioprio = ioprio & 0xff;
+			printf("%s: prio %d\n", to_prio[ioprio_class], ioprio);
+		}
+	} else {
+		if (ioprio_set(IOPRIO_WHO_PROCESS, pid, ioprio | ioprio_class << IOPRIO_CLASS_SHIFT) == -1) {
+			perror("ioprio_set");
+			return 1;
+		}
+
+		if (argv[optind])
+			execvp(argv[optind], &argv[optind]);
+	}
+
+	return 0;
+}
+
+---> snip ionice.c tool <---
+
+
+March 11 2005, Jens Axboe <axboe@suse.de>
diff --git a/Documentation/cdrom/sbpcd b/Documentation/cdrom/sbpcd
index d1825df..b3ba63f 100644
--- a/Documentation/cdrom/sbpcd
+++ b/Documentation/cdrom/sbpcd
@@ -419,6 +419,7 @@
  */
 #include <stdio.h>
 #include <sys/ioctl.h>
+#include <sys/types.h>
 #include <linux/cdrom.h>
 
 static struct cdrom_tochdr hdr;
@@ -429,7 +430,7 @@
 static int i, j, limit, track, err;
 static char filename[32];
 
-main(int argc, char *argv[])
+int main(int argc, char *argv[])
 {
 /*
  * open /dev/cdrom
@@ -516,6 +517,7 @@
 	}
       arg.addr.lba++;
     }
+    return 0;
 }
 /*===================== end program ========================================*/
 
@@ -564,15 +566,16 @@
 #include <stdio.h>
 #include <malloc.h>
 #include <sys/ioctl.h>
+#include <sys/types.h>
 #include <linux/cdrom.h>
 
 #ifdef AZT_PRIVATE_IOCTLS
 #include <linux/../../drivers/cdrom/aztcd.h>
-#endif AZT_PRIVATE_IOCTLS
+#endif /* AZT_PRIVATE_IOCTLS */
 #ifdef SBP_PRIVATE_IOCTLS
 #include <linux/../../drivers/cdrom/sbpcd.h>
 #include <linux/fs.h>
-#endif SBP_PRIVATE_IOCTLS
+#endif /* SBP_PRIVATE_IOCTLS */
 
 struct cdrom_tochdr hdr;
 struct cdrom_tochdr tocHdr;
@@ -590,7 +593,7 @@
 	struct cdrom_msf msf;
 	unsigned char buf[CD_FRAMESIZE_RAW];
 } azt;
-#endif AZT_PRIVATE_IOCTLS
+#endif /* AZT_PRIVATE_IOCTLS */
 int i, i1, i2, i3, j, k;
 unsigned char sequence=0;
 unsigned char command[80];
@@ -738,7 +741,7 @@
 	} 
 } 
 
-main(int argc, char *argv[])
+int main(int argc, char *argv[])
 {
 	printf("\nTesting tool for a CDROM driver's audio functions V0.1\n");
 	printf("(C) 1995 Eberhard Moenkeberg <emoenke@gwdg.de>\n");
@@ -1046,12 +1049,13 @@
 			rc=ioctl(drive,CDROMAUDIOBUFSIZ,j);
 			printf("%d frames granted.\n",rc);
 			break;
-#endif SBP_PRIVATE_IOCTLS
+#endif /* SBP_PRIVATE_IOCTLS */
 		default:
 			printf("unknown command: \"%s\".\n",command);
 			break;
 		}
 	}
+	return 0;
 }
 /*==========================================================================*/
 
diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt
index b85481a..933fae7 100644
--- a/Documentation/cpu-freq/governors.txt
+++ b/Documentation/cpu-freq/governors.txt
@@ -9,6 +9,7 @@
 
 
 		    Dominik Brodowski  <linux@brodo.de>
+            some additions and corrections by Nico Golde <nico@ngolde.de>
 
 
 
@@ -25,6 +26,7 @@
 2.1  Performance
 2.2  Powersave
 2.3  Userspace
+2.4  Ondemand
 
 3.   The Governor Interface in the CPUfreq Core
 
@@ -86,7 +88,7 @@
 scaling_max_freq.
 
 
-2.1 Powersave
+2.2 Powersave
 -------------
 
 The CPUfreq governor "powersave" sets the CPU statically to the
@@ -94,7 +96,7 @@
 scaling_max_freq.
 
 
-2.2 Userspace
+2.3 Userspace
 -------------
 
 The CPUfreq governor "userspace" allows the user, or any userspace
@@ -103,6 +105,14 @@
 directory.
 
 
+2.4 Ondemand
+------------
+
+The CPUfreq govenor "ondemand" sets the CPU depending on the
+current usage. To do this the CPU must have the capability to
+switch the frequency very fast.
+
+
 
 3. The Governor Interface in the CPUfreq Core
 =============================================
diff --git a/Documentation/cpusets.txt b/Documentation/cpusets.txt
index 2f8f24e..ad944c0 100644
--- a/Documentation/cpusets.txt
+++ b/Documentation/cpusets.txt
@@ -51,6 +51,14 @@
 
 If a cpuset is cpu or mem exclusive, no other cpuset, other than a direct
 ancestor or descendent, may share any of the same CPUs or Memory Nodes.
+A cpuset that is cpu exclusive has a sched domain associated with it.
+The sched domain consists of all cpus in the current cpuset that are not
+part of any exclusive child cpusets.
+This ensures that the scheduler load balacing code only balances
+against the cpus that are in the sched domain as defined above and not
+all of the cpus in the system. This removes any overhead due to
+load balancing code trying to pull tasks outside of the cpu exclusive
+cpuset only to be prevented by the tasks' cpus_allowed mask.
 
 User level code may create and destroy cpusets by name in the cpuset
 virtual file system, manage the attributes and permissions of these
@@ -84,6 +92,9 @@
       and a database), or
     * NUMA systems running large HPC applications with demanding
       performance characteristics.
+    * Also cpu_exclusive cpusets are useful for servers running orthogonal
+      workloads such as RT applications requiring low latency and HPC
+      applications that are throughput sensitive
 
 These subsets, or "soft partitions" must be able to be dynamically
 adjusted, as the job mix changes, without impacting other concurrently
@@ -125,6 +136,8 @@
  - A cpuset may be marked exclusive, which ensures that no other
    cpuset (except direct ancestors and descendents) may contain
    any overlapping CPUs or Memory Nodes.
+   Also a cpu_exclusive cpuset would be associated with a sched
+   domain.
  - You can list all the tasks (by pid) attached to any cpuset.
 
 The implementation of cpusets requires a few, simple hooks
@@ -136,6 +149,9 @@
    allowed in that tasks cpuset.
  - in sched.c migrate_all_tasks(), to keep migrating tasks within
    the CPUs allowed by their cpuset, if possible.
+ - in sched.c, a new API partition_sched_domains for handling
+   sched domain changes associated with cpu_exclusive cpusets
+   and related changes in both sched.c and arch/ia64/kernel/domain.c
  - in the mbind and set_mempolicy system calls, to mask the requested
    Memory Nodes by what's allowed in that tasks cpuset.
  - in page_alloc, to restrict memory to allowed nodes.
diff --git a/Documentation/devices.txt b/Documentation/devices.txt
index bb67cf2..0f51517 100644
--- a/Documentation/devices.txt
+++ b/Documentation/devices.txt
@@ -94,6 +94,7 @@
 		  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
diff --git a/Documentation/dontdiff b/Documentation/dontdiff
index 9a33bb9..d4fda25 100644
--- a/Documentation/dontdiff
+++ b/Documentation/dontdiff
@@ -111,6 +111,7 @@
 mktables
 modpost
 modversions.h*
+offset.h
 offsets.h
 oui.c*
 parse.c*
diff --git a/Documentation/driver-model/device.txt b/Documentation/driver-model/device.txt
index 58cc5dc..a05ec50 100644
--- a/Documentation/driver-model/device.txt
+++ b/Documentation/driver-model/device.txt
@@ -76,6 +76,14 @@
 
 platform_data: Platform data specific to the device.
 
+	       Example:  for devices on custom boards, as typical of embedded
+	       and SOC based hardware, Linux often uses platform_data to point
+	       to board-specific structures describing devices and how they
+	       are wired.  That can include what ports are available, chip
+	       variants, which GPIO pins act in what additional roles, and so
+	       on.  This shrinks the "Board Support Packages" (BSPs) and
+	       minimizes board-specific #ifdefs in drivers.
+
 current_state: Current power state of the device.
 
 saved_state:   Pointer to saved state of the device. This is usable by
diff --git a/Documentation/driver-model/driver.txt b/Documentation/driver-model/driver.txt
index 6031a68..fabaca1 100644
--- a/Documentation/driver-model/driver.txt
+++ b/Documentation/driver-model/driver.txt
@@ -5,21 +5,17 @@
         char                    * name;
         struct bus_type         * bus;
 
-        rwlock_t                lock;
-        atomic_t                refcount;
-
-        list_t                  bus_list;
+        struct completion	unloaded;
+        struct kobject		kobj;
         list_t                  devices;
 
-        struct driver_dir_entry dir;
+        struct module		*owner;
 
         int     (*probe)        (struct device * dev);
         int     (*remove)       (struct device * dev);
 
         int     (*suspend)      (struct device * dev, pm_message_t state, u32 level);
         int     (*resume)       (struct device * dev, u32 level);
-
-        void    (*release)      (struct device_driver * drv);
 };
 
 
@@ -51,7 +47,6 @@
 static struct device_driver eepro100_driver = {
        .name		= "eepro100",
        .bus		= &pci_bus_type,
-       .devclass	= &ethernet_devclass,	/* when it's implemented */
        
        .probe		= eepro100_probe,
        .remove		= eepro100_remove,
@@ -85,7 +80,6 @@
        .driver	       = {
 		.name		= "eepro100",
 		.bus		= &pci_bus_type,
-		.devclass	= &ethernet_devclass,	/* when it's implemented */
 		.probe		= eepro100_probe,
 		.remove		= eepro100_remove,
 		.suspend	= eepro100_suspend,
@@ -166,27 +160,32 @@
 
 	int	(*probe)	(struct device * dev);
 
-probe is called to verify the existence of a certain type of
-hardware. This is called during the driver binding process, after the
-bus has verified that the device ID of a device matches one of the
-device IDs supported by the driver. 
+The probe() entry is called in task context, with the bus's rwsem locked
+and the driver partially bound to the device.  Drivers commonly use
+container_of() to convert "dev" to a bus-specific type, both in probe()
+and other routines.  That type often provides device resource data, such
+as pci_dev.resource[] or platform_device.resources, which is used in
+addition to dev->platform_data to initialize the driver.
 
-This callback only verifies that there actually is supported hardware
-present. It may allocate a driver-specific structure, but it should
-not do any initialization of the hardware itself. The device-specific
-structure may be stored in the device's driver_data field. 
+This callback holds the driver-specific logic to bind the driver to a
+given device.  That includes verifying that the device is present, that
+it's a version the driver can handle, that driver data structures can
+be allocated and initialized, and that any hardware can be initialized.
+Drivers often store a pointer to their state with dev_set_drvdata().
+When the driver has successfully bound itself to that device, then probe()
+returns zero and the driver model code will finish its part of binding
+the driver to that device.
 
-	int	(*init)		(struct device * dev);
-
-init is called during the binding stage. It is called after probe has
-successfully returned and the device has been registered with its
-class. It is responsible for initializing the hardware.
+A driver's probe() may return a negative errno value to indicate that
+the driver did not bind to this device, in which case it should have
+released all reasources it allocated.
 
 	int 	(*remove)	(struct device * dev);
 
-remove is called to dissociate a driver with a device. This may be
+remove is called to unbind a driver from a device. This may be
 called if a device is physically removed from the system, if the
-driver module is being unloaded, or during a reboot sequence. 
+driver module is being unloaded, during a reboot sequence, or
+in other cases.
 
 It is up to the driver to determine if the device is present or
 not. It should free any resources allocated specifically for the
diff --git a/Documentation/dvb/README.dibusb b/Documentation/dvb/README.dibusb
deleted file mode 100644
index 7a9e958..0000000
--- a/Documentation/dvb/README.dibusb
+++ /dev/null
@@ -1,285 +0,0 @@
-Documentation for dib3000* frontend drivers and dibusb device driver
-====================================================================
-
-Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de),
-
-dibusb and dib3000mb/mc drivers based on GPL code, which has
-
-Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.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, version 2.
-
-
-Supported devices USB1.1
-========================
-
-Produced and reselled by Twinhan:
----------------------------------
-- TwinhanDTV USB-Ter DVB-T Device (VP7041)
-	http://www.twinhan.com/product_terrestrial_3.asp
-
-- TwinhanDTV Magic Box (VP7041e)
-	http://www.twinhan.com/product_terrestrial_4.asp
-
-- HAMA DVB-T USB device
-	http://www.hama.de/portal/articleId*110620/action*2598
-
-- CTS Portable (Chinese Television System) (2)
-	http://www.2cts.tv/ctsportable/
-
-- Unknown USB DVB-T device with vendor ID Hyper-Paltek
-
-
-Produced and reselled by KWorld:
---------------------------------
-- KWorld V-Stream XPERT DTV DVB-T USB
-	http://www.kworld.com.tw/en/product/DVBT-USB/DVBT-USB.html
-
-- JetWay DTV DVB-T USB
-	http://www.jetway.com.tw/evisn/product/lcd-tv/DVT-USB/dtv-usb.htm
-
-- ADSTech Instant TV DVB-T USB
-	http://www.adstech.com/products/PTV-333/intro/PTV-333_intro.asp?pid=PTV-333
-
-
-Others:
--------
-- Ultima Electronic/Artec T1 USB TVBOX (AN2135, AN2235, AN2235 with Panasonic Tuner)
-	http://82.161.246.249/products-tvbox.html
-
-- Compro Videomate DVB-U2000 - DVB-T USB (2)
-	http://www.comprousa.com/products/vmu2000.htm
-
-- Grandtec USB DVB-T
-	http://www.grand.com.tw/
-
-- Avermedia AverTV DVBT USB (2)
-	http://www.avermedia.com/
-
-- DiBcom USB DVB-T reference device (non-public)
-
-
-Supported devices USB2.0
-========================
-- Twinhan MagicBox II (2)
-	http://www.twinhan.com/product_terrestrial_7.asp
-
-- Hanftek UMT-010 (1)
-	http://www.globalsources.com/si/6008819757082/ProductDetail/Digital-TV/product_id-100046529
-
-- Typhoon/Yakumo/HAMA DVB-T mobile USB2.0 (1)
-	http://www.yakumo.de/produkte/index.php?pid=1&ag=DVB-T
-
-- Artec T1 USB TVBOX (FX2) (2)
-
-- Hauppauge WinTV NOVA-T USB2
-	http://www.hauppauge.com/
-
-- KWorld/ADSTech Instant DVB-T USB2.0 (DiB3000M-B)
-
-- DiBcom USB2.0 DVB-T reference device (non-public)
-
-1) It is working almost.
-2) No test reports received yet.
-
-
-0. NEWS:
-  2005-02-11 - added support for the KWorld/ADSTech Instant DVB-T USB2.0. Thanks a lot to Joachim von Caron
-  2005-02-02 - added support for the Hauppauge Win-TV Nova-T USB2
-  2005-01-31 - distorted streaming is finally gone for USB1.1 devices
-  2005-01-13 - moved the mirrored pid_filter_table back to dvb-dibusb
-             - first almost working version for HanfTek UMT-010
-             - found out, that Yakumo/HAMA/Typhoon are predessors of the HanfTek UMT-010
-  2005-01-10 - refactoring completed, now everything is very delightful
-             - tuner quirks for some weird devices (Artec T1 AN2235 device has sometimes a
-               Panasonic Tuner assembled). Tunerprobing implemented. Thanks a lot to Gunnar Wittich.
-  2004-12-29 - after several days of struggling around bug of no returning URBs fixed.
-  2004-12-26 - refactored the dibusb-driver, splitted into separate files
-             - i2c-probing enabled
-  2004-12-06 - possibility for demod i2c-address probing
-             - new usb IDs (Compro,Artec)
-  2004-11-23 - merged changes from DiB3000MC_ver2.1
-             - revised the debugging
-             - possibility to deliver the complete TS for USB2.0
-  2004-11-21 - first working version of the dib3000mc/p frontend driver.
-  2004-11-12 - added additional remote control keys. Thanks to Uwe Hanke.
-  2004-11-07 - added remote control support. Thanks to David Matthews.
-  2004-11-05 - added support for a new devices (Grandtec/Avermedia/Artec)
-             - merged my changes (for dib3000mb/dibusb) to the FE_REFACTORING, because it became HEAD
-             - moved transfer control (pid filter, fifo control) from usb driver to frontend, it seems
-               better settled there (added xfer_ops-struct)
-             - created a common files for frontends (mc/p/mb)
-  2004-09-28 - added support for a new device (Unkown, vendor ID is Hyper-Paltek)
-  2004-09-20 - added support for a new device (Compro DVB-U2000), thanks
-               to Amaury Demol for reporting
-             - changed usb TS transfer method (several urbs, stopping transfer
-               before setting a new pid)
-  2004-09-13 - added support for a new device (Artec T1 USB TVBOX), thanks
-               to Christian Motschke for reporting
-  2004-09-05 - released the dibusb device and dib3000mb-frontend driver
-
-  (old news for vp7041.c)
-  2004-07-15 - found out, by accident, that the device has a TUA6010XS for
-               PLL
-  2004-07-12 - figured out, that the driver should also work with the
-               CTS Portable (Chinese Television System)
-  2004-07-08 - firmware-extraction-2.422-problem solved, driver is now working
-               properly with firmware extracted from 2.422
-			 - #if for 2.6.4 (dvb), compile issue
-			 - changed firmware handling, see vp7041.txt sec 1.1
-  2004-07-02 - some tuner modifications, v0.1, cleanups, first public
-  2004-06-28 - now using the dvb_dmx_swfilter_packets, everything
-               runs fine now
-  2004-06-27 - able to watch and switching channels (pre-alpha)
-             - no section filtering yet
-  2004-06-06 - first TS received, but kernel oops :/
-  2004-05-14 - firmware loader is working
-  2004-05-11 - start writing the driver
-
-1. How to use?
-NOTE: This driver was developed using Linux 2.6.6.,
-it is working with 2.6.7 and above.
-
-Linux 2.4.x support is not planned, but patches are very welcome.
-
-NOTE: I'm using Debian testing, so the following explaination (especially
-the hotplug-path) needn't match your system, but probably it will :).
-
-The driver is included in the kernel since Linux 2.6.10.
-
-1.1. Firmware
-
-The USB driver needs to download a firmware to start working.
-
-You can either use "get_dvb_firmware dibusb" to download the firmware or you
-can get it directly via
-
-for USB1.1 (AN2135)
-http://www.linuxtv.org/downloads/firmware/dvb-dibusb-5.0.0.11.fw
-
-for USB1.1 (AN2235) (a few Artec T1 devices)
-http://www.linuxtv.org/downloads/firmware/dvb-dibusb-an2235-1.fw
-
-for USB2.0 (FX2) Hauppauge, DiBcom
-http://www.linuxtv.org/downloads/firmware/dvb-dibusb-6.0.0.5.fw
-
-for USB2.0 ADSTech/Kworld USB2.0
-http://www.linuxtv.org/downloads/firmware/dvb-dibusb-adstech-usb2-1.fw
-
-for USB2.0 HanfTek
-http://www.linuxtv.org/downloads/firmware/dvb-dibusb-an2235-1.fw
-
-
-1.2. Compiling
-
-Since the driver is in the linux kernel, activating the driver in
-your favorite config-environment should sufficient. I recommend
-to compile the driver as module. Hotplug does the rest.
-
-1.3. Loading the drivers
-
-Hotplug is able to load the driver, when it is needed (because you plugged
-in the device).
-
-If you want to enable debug output, you have to load the driver manually and
-from withing the dvb-kernel cvs repository.
-
-first have a look, which debug level are available:
-
-modinfo dib3000mb
-modinfo dib3000-common
-modinfo dib3000mc
-modinfo dvb-dibusb
-
-modprobe dib3000-common debug=<level>
-modprobe dib3000mb debug=<level>
-modprobe dib3000mc debug=<level>
-modprobe dvb-dibusb debug=<level>
-
-should do the trick.
-
-When the driver is loaded successfully, the firmware file was in
-the right place and the device is connected, the "Power"-LED should be
-turned on.
-
-At this point you should be able to start a dvb-capable application. For myself
-I used mplayer, dvbscan, tzap and kaxtv, they are working. Using the device
-in vdr is working now also.
-
-2. Known problems and bugs
-
-- Don't remove the USB device while running an DVB application, your system will die.
-
-2.1. Adding support for devices
-
-It is not possible to determine the range of devices based on the DiBcom
-reference designs. This is because the reference design of DiBcom can be sold
-to thirds, without telling DiBcom (so done with the Twinhan VP7041 and
-the HAMA device).
-
-When you think you have a device like this and the driver does not recognizes it,
-please send the ****load*.inf and the ****cap*.inf of the Windows driver to me.
-
-Sometimes the Vendor or Product ID is identical to the ones of Twinhan, even
-though it is not a Twinhan device (e.g. HAMA), then please send me the name
-of the device. I will add it to this list in order to make this clear to
-others.
-
-If you are familar with C you can also add the VID and PID of the device to
-the dvb-dibusb-core.c-file and create a patch and send it over to me or to
-the linux-dvb mailing list, _after_ you have tried compiling and modprobing
-it.
-
-2.2. USB1.1 Bandwidth limitation
-
-Most of the currently supported devices are USB1.1 and thus they have a
-maximum bandwidth of about 5-6 MBit/s when connected to a USB2.0 hub.
-This is not enough for receiving the complete transport stream of a
-DVB-T channel (which can be about 16 MBit/s). Normally this is not a
-problem, if you only want to watch TV (this does not apply for HDTV),
-but watching a channel while recording another channel on the same
-frequency simply does not work very well. This applies to all USB1.1
-DVB-T devices, not just dibusb)
-
-Update: For the USB1.1 and VDR some work has been done (patches and comments
-are still very welcome). Maybe the problem is solved in the meantime because I
-now use the dmx_sw_filter function instead of dmx_sw_filter_packet. I hope the
-linux-dvb software filter is able to get the best of the garbled TS.
-
-The bug, where the TS is distorted by a heavy usage of the device is gone
-definitely. All dibusb-devices I was using (Twinhan, Kworld, DiBcom) are
-working like charm now with VDR. Sometimes I even was able to record a channel
-and watch another one.
-
-2.3. Comments
-
-Patches, comments and suggestions are very very welcome.
-
-3. Acknowledgements
-	Amaury Demol (ademol@dibcom.fr) and Francois Kanounnikoff from DiBcom for
-    providing specs, code and help, on which the dvb-dibusb, dib3000mb and
-    dib3000mc are based.
-
-   David Matthews for identifying a new device type (Artec T1 with AN2235)
-    and for extending dibusb with remote control event handling. Thank you.
-
-   Alex Woods for frequently answering question about usb and dvb
-    stuff, a big thank you.
-
-   Bernd Wagner for helping with huge bug reports and discussions.
-
-   Gunnar Wittich and Joachim von Caron for their trust for giving me
-    root-shells on their machines to implement support for new devices.
-
-   Some guys on the linux-dvb mailing list for encouraging me
-
-   Peter Schildmann >peter.schildmann-nospam-at-web.de< for his
-    user-level firmware loader, which saves a lot of time
-    (when writing the vp7041 driver)
-
-   Ulf Hermenau for helping me out with traditional chinese.
-
-   André Smoktun and Christian Frömmel for supporting me with
-    hardware and listening to my problems very patient
diff --git a/Documentation/dvb/README.dvb-usb b/Documentation/dvb/README.dvb-usb
new file mode 100644
index 0000000..c7ed01b
--- /dev/null
+++ b/Documentation/dvb/README.dvb-usb
@@ -0,0 +1,308 @@
+Documentation for dvb-usb-framework module and its devices
+
+Idea behind the dvb-usb-framework
+=================================
+
+In March 2005 I got the new Twinhan USB2.0 DVB-T device. They provided specs and a firmware.
+
+Quite keen I wanted to put the driver (with some quirks of course) into dibusb.
+After reading some specs and doing some USB snooping, it realized, that the
+dibusb-driver would be a complete mess afterwards. So I decided to do it in a
+different way: With the help of a dvb-usb-framework.
+
+The framework provides generic functions (mostly kernel API calls), such as:
+
+- Transport Stream URB handling in conjunction with dvb-demux-feed-control
+  (bulk and isoc (TODO) are supported)
+- registering the device for the DVB-API
+- registering an I2C-adapter if applicable
+- remote-control/input-device handling
+- firmware requesting and loading (currently just for the Cypress USB
+  controller)
+- other functions/methods which can be shared by several drivers (such as
+  functions for bulk-control-commands)
+
+The source code of the particular DVB USB devices does just the communication
+with the device via the bus. The connection between the DVB-API-functionality
+is done via callbacks, assigned in a static device-description (struct
+dvb_usb_device) each device-driver has to have.
+
+For an example have a look in drivers/media/dvb/dvb-usb/vp7045*.
+
+Objective is to migrate all the usb-devices (dibusb, cinergyT2, maybe the
+ttusb; flexcop-usb already benefits from the generic flexcop-device) to use
+the dvb-usb-lib.
+
+TODO: dynamic enabling and disabling of the pid-filter in regard to number of
+feeds requested.
+
+Supported devices USB1.1
+========================
+
+Produced and reselled by Twinhan:
+---------------------------------
+- TwinhanDTV USB-Ter DVB-T Device (VP7041)
+	http://www.twinhan.com/product_terrestrial_3.asp
+
+- TwinhanDTV Magic Box (VP7041e)
+	http://www.twinhan.com/product_terrestrial_4.asp
+
+- HAMA DVB-T USB device
+	http://www.hama.de/portal/articleId*110620/action*2598
+
+- CTS Portable (Chinese Television System) (2)
+	http://www.2cts.tv/ctsportable/
+
+- Unknown USB DVB-T device with vendor ID Hyper-Paltek
+
+
+Produced and reselled by KWorld:
+--------------------------------
+- KWorld V-Stream XPERT DTV DVB-T USB
+	http://www.kworld.com.tw/en/product/DVBT-USB/DVBT-USB.html
+
+- JetWay DTV DVB-T USB
+	http://www.jetway.com.tw/evisn/product/lcd-tv/DVT-USB/dtv-usb.htm
+
+- ADSTech Instant TV DVB-T USB
+	http://www.adstech.com/products/PTV-333/intro/PTV-333_intro.asp?pid=PTV-333
+
+
+Others:
+-------
+- Ultima Electronic/Artec T1 USB TVBOX (AN2135, AN2235, AN2235 with Panasonic Tuner)
+	http://82.161.246.249/products-tvbox.html
+
+- Compro Videomate DVB-U2000 - DVB-T USB (2)
+	http://www.comprousa.com/products/vmu2000.htm
+
+- Grandtec USB DVB-T
+	http://www.grand.com.tw/
+
+- AVerMedia AverTV DVBT USB
+	http://www.avermedia.com/
+
+- DiBcom USB DVB-T reference device (non-public)
+
+
+Supported devices USB2.0-only
+=============================
+- Twinhan MagicBox II
+	http://www.twinhan.com/product_terrestrial_7.asp
+
+- TwinhanDTV Alpha
+	http://www.twinhan.com/product_terrestrial_8.asp
+
+- DigitalNow TinyUSB 2 DVB-t Receiver
+	http://www.digitalnow.com.au/DigitalNow%20tinyUSB2%20Specifications.html
+
+- Hanftek UMT-010
+	http://www.globalsources.com/si/6008819757082/ProductDetail/Digital-TV/product_id-100046529
+
+
+Supported devices USB2.0 and USB1.1
+=============================
+- Typhoon/Yakumo/HAMA/Yuan DVB-T mobile USB2.0
+	http://www.yakumo.de/produkte/index.php?pid=1&ag=DVB-T
+	http://www.yuan.com.tw/en/products/vdo_ub300.html
+	http://www.hama.de/portal/articleId*114663/action*2563
+	http://www.anubisline.com/english/articlec.asp?id=50502&catid=002
+
+- Artec T1 USB TVBOX (FX2) (2)
+
+- Hauppauge WinTV NOVA-T USB2
+	http://www.hauppauge.com/
+
+- KWorld/ADSTech Instant DVB-T USB2.0 (DiB3000M-B)
+
+- DiBcom USB2.0 DVB-T reference device (non-public)
+
+- AVerMedia AverTV A800 DVB-T USB2.0
+
+1) It is working almost - work-in-progress.
+2) No test reports received yet.
+
+0. History & News:
+  2005-04-17 - all dibusb devices ported to make use of the dvb-usb-framework
+  2005-04-02 - re-enabled and improved remote control code.
+  2005-03-31 - ported the Yakumo/Hama/Typhoon DVB-T USB2.0 device to dvb-usb.
+  2005-03-30 - first commit of the dvb-usb-module based on the dibusb-source. First device is a new driver for the
+               TwinhanDTV Alpha / MagicBox II USB2.0-only DVB-T device.
+
+  (change from dvb-dibusb to dvb-usb)
+  2005-03-28 - added support for the AVerMedia AverTV DVB-T USB2.0 device (Thanks to Glen Harris and Jiun-Kuei Jung, AVerMedia)
+  2005-03-14 - added support for the Typhoon/Yakumo/HAMA DVB-T mobile USB2.0
+  2005-02-11 - added support for the KWorld/ADSTech Instant DVB-T USB2.0. Thanks a lot to Joachim von Caron
+  2005-02-02 - added support for the Hauppauge Win-TV Nova-T USB2
+  2005-01-31 - distorted streaming is gone for USB1.1 devices
+  2005-01-13 - moved the mirrored pid_filter_table back to dvb-dibusb
+             - first almost working version for HanfTek UMT-010
+             - found out, that Yakumo/HAMA/Typhoon are predessors of the HanfTek UMT-010
+  2005-01-10 - refactoring completed, now everything is very delightful
+             - tuner quirks for some weird devices (Artec T1 AN2235 device has sometimes a
+               Panasonic Tuner assembled). Tunerprobing implemented. Thanks a lot to Gunnar Wittich.
+  2004-12-29 - after several days of struggling around bug of no returning URBs fixed.
+  2004-12-26 - refactored the dibusb-driver, splitted into separate files
+             - i2c-probing enabled
+  2004-12-06 - possibility for demod i2c-address probing
+             - new usb IDs (Compro, Artec)
+  2004-11-23 - merged changes from DiB3000MC_ver2.1
+             - revised the debugging
+             - possibility to deliver the complete TS for USB2.0
+  2004-11-21 - first working version of the dib3000mc/p frontend driver.
+  2004-11-12 - added additional remote control keys. Thanks to Uwe Hanke.
+  2004-11-07 - added remote control support. Thanks to David Matthews.
+  2004-11-05 - added support for a new devices (Grandtec/Avermedia/Artec)
+             - merged my changes (for dib3000mb/dibusb) to the FE_REFACTORING, because it became HEAD
+             - moved transfer control (pid filter, fifo control) from usb driver to frontend, it seems
+               better settled there (added xfer_ops-struct)
+             - created a common files for frontends (mc/p/mb)
+  2004-09-28 - added support for a new device (Unkown, vendor ID is Hyper-Paltek)
+  2004-09-20 - added support for a new device (Compro DVB-U2000), thanks
+               to Amaury Demol for reporting
+             - changed usb TS transfer method (several urbs, stopping transfer
+               before setting a new pid)
+  2004-09-13 - added support for a new device (Artec T1 USB TVBOX), thanks
+               to Christian Motschke for reporting
+  2004-09-05 - released the dibusb device and dib3000mb-frontend driver
+
+  (old news for vp7041.c)
+  2004-07-15 - found out, by accident, that the device has a TUA6010XS for
+               PLL
+  2004-07-12 - figured out, that the driver should also work with the
+               CTS Portable (Chinese Television System)
+  2004-07-08 - firmware-extraction-2.422-problem solved, driver is now working
+               properly with firmware extracted from 2.422
+             - #if for 2.6.4 (dvb), compile issue
+             - changed firmware handling, see vp7041.txt sec 1.1
+  2004-07-02 - some tuner modifications, v0.1, cleanups, first public
+  2004-06-28 - now using the dvb_dmx_swfilter_packets, everything
+               runs fine now
+  2004-06-27 - able to watch and switching channels (pre-alpha)
+             - no section filtering yet
+  2004-06-06 - first TS received, but kernel oops :/
+  2004-05-14 - firmware loader is working
+  2004-05-11 - start writing the driver
+
+1. How to use?
+1.1. Firmware
+
+Most of the USB drivers need to download a firmware to start working.
+
+for USB1.1 (AN2135) you need: dvb-usb-dibusb-5.0.0.11.fw
+for USB2.0 HanfTek: dvb-usb-umt-010-02.fw
+for USB2.0 DiBcom: dvb-usb-dibusb-6.0.0.8.fw
+for USB2.0 AVerMedia AverTV DVB-T USB2: dvb-usb-avertv-a800-01.fw
+for USB2.0 TwinhanDTV Alpha/MagicBox II: dvb-usb-vp7045-01.fw
+
+The files can be found on http://www.linuxtv.org/download/firmware/ .
+
+We do not have the permission (yet) to publish the following firmware-files.
+You'll need to extract them from the windows drivers.
+
+You should be able to use "get_dvb_firmware dvb-usb" to get the firmware:
+
+for USB1.1 (AN2235) (a few Artec T1 devices): dvb-usb-dibusb-an2235-01.fw
+for USB2.0 Hauppauge: dvb-usb-nova-t-usb2-01.fw
+for USB2.0 ADSTech/Kworld USB2.0: dvb-usb-adstech-usb2-01.fw
+for USB2.0 Yakumo/Typhoon/Hama: dvb-usb-dtt200u-01.fw
+
+1.2. Compiling
+
+Since the driver is in the linux kernel, activating the driver in
+your favorite config-environment should sufficient. I recommend
+to compile the driver as module. Hotplug does the rest.
+
+If you use dvb-kernel enter the build-2.6 directory run 'make' and 'insmod.sh
+load' afterwards.
+
+1.3. Loading the drivers
+
+Hotplug is able to load the driver, when it is needed (because you plugged
+in the device).
+
+If you want to enable debug output, you have to load the driver manually and
+from withing the dvb-kernel cvs repository.
+
+first have a look, which debug level are available:
+
+modinfo dvb-usb
+modinfo dvb-usb-vp7045
+etc.
+
+modprobe dvb-usb debug=<level>
+modprobe dvb-usb-vp7045 debug=<level>
+etc.
+
+should do the trick.
+
+When the driver is loaded successfully, the firmware file was in
+the right place and the device is connected, the "Power"-LED should be
+turned on.
+
+At this point you should be able to start a dvb-capable application. I'm use
+(t|s)zap, mplayer and dvbscan to test the basics. VDR-xine provides the
+long-term test scenario.
+
+2. Known problems and bugs
+
+- Don't remove the USB device while running an DVB application, your system
+  will go crazy or die most likely.
+
+2.1. Adding support for devices
+
+TODO
+
+2.2. USB1.1 Bandwidth limitation
+
+A lot of the currently supported devices are USB1.1 and thus they have a
+maximum bandwidth of about 5-6 MBit/s when connected to a USB2.0 hub.
+This is not enough for receiving the complete transport stream of a
+DVB-T channel (which is about 16 MBit/s). Normally this is not a
+problem, if you only want to watch TV (this does not apply for HDTV),
+but watching a channel while recording another channel on the same
+frequency simply does not work very well. This applies to all USB1.1
+DVB-T devices, not just the dvb-usb-devices)
+
+The bug, where the TS is distorted by a heavy usage of the device is gone
+definitely. All dvb-usb-devices I was using (Twinhan, Kworld, DiBcom) are
+working like charm now with VDR. Sometimes I even was able to record a channel
+and watch another one.
+
+2.3. Comments
+
+Patches, comments and suggestions are very very welcome.
+
+3. Acknowledgements
+   Amaury Demol (ademol@dibcom.fr) and Francois Kanounnikoff from DiBcom for
+    providing specs, code and help, on which the dvb-dibusb, dib3000mb and
+    dib3000mc are based.
+
+   David Matthews for identifying a new device type (Artec T1 with AN2235)
+    and for extending dibusb with remote control event handling. Thank you.
+
+   Alex Woods for frequently answering question about usb and dvb
+    stuff, a big thank you.
+
+   Bernd Wagner for helping with huge bug reports and discussions.
+
+   Gunnar Wittich and Joachim von Caron for their trust for providing
+    root-shells on their machines to implement support for new devices.
+
+   Glen Harris for bringing up, that there is a new dibusb-device and Jiun-Kuei
+    Jung from AVerMedia who kindly provided a special firmware to get the device
+    up and running in Linux.
+
+   Jennifer Chen, Jeff and Jack from Twinhan for kindly supporting by
+	writing the vp7045-driver.
+
+   Some guys on the linux-dvb mailing list for encouraging me
+
+   Peter Schildmann >peter.schildmann-nospam-at-web.de< for his
+    user-level firmware loader, which saves a lot of time
+    (when writing the vp7041 driver)
+
+   Ulf Hermenau for helping me out with traditional chinese.
+
+   André Smoktun and Christian Frömmel for supporting me with
+    hardware and listening to my problems very patient.
diff --git a/Documentation/dvb/bt8xx.txt b/Documentation/dvb/bt8xx.txt
index d64430b..3a32607 100644
--- a/Documentation/dvb/bt8xx.txt
+++ b/Documentation/dvb/bt8xx.txt
@@ -44,26 +44,23 @@
    $ modprobe dst
 
 The value 0x71 will override the PCI type detection for dvb-bt8xx,
-which  is necessary for TwinHan cards.
+which is necessary for TwinHan cards.
 
 If you're having an older card (blue color circuit) and card=0x71 locks
 your machine, try using 0x68, too. If that does not work, ask on the
 mailing list.
 
-The DST module takes a couple of useful parameters.
+The DST module takes a couple of useful parameters:
 
-verbose takes values 0 to 5. These values control the verbosity level.
+a. verbose takes values 0 to 5. These values control the verbosity level.
+b. debug takes values 0 and 1. You can either disable or enable debugging.
+c. dst_addons takes values 0 and 0x20:
+- A value of 0 means it is a FTA card.
+- A value of 0x20 means it has a Conditional Access slot.
 
-debug takes values 0 and 1. You can either disable or enable debugging.
-
-dst_addons takes values 0 and 0x20. A value of 0 means it is a FTA card.
-0x20 means it has a Conditional Access slot.
-
-The autodected values are determined bythe cards 'response
-string' which you can see in your logs e.g.
-
-dst_get_device_id: Recognise [DSTMCI]
-
+The autodetected values are determined by the "response string"
+of the card, which you can see in your logs:
+e.g.: dst_get_device_id: Recognize [DSTMCI]
 
 --
-Authors: Richard Walker, Jamie Honan, Michael Hunold, Manu Abraham
+Authors: Richard Walker, Jamie Honan, Michael Hunold, Manu Abraham, Uwe Bugla
diff --git a/Documentation/fb/intelfb.txt b/Documentation/fb/intelfb.txt
new file mode 100644
index 0000000..c12d39a
--- /dev/null
+++ b/Documentation/fb/intelfb.txt
@@ -0,0 +1,135 @@
+Intel 830M/845G/852GM/855GM/865G/915G Framebuffer driver
+================================================================
+
+A. Introduction
+	This is a framebuffer driver for various Intel 810/815 compatible
+graphics devices.  These would include:
+
+	Intel 830M
+	Intel 810E845G
+	Intel 852GM
+	Intel 855GM
+	Intel 865G
+	Intel 915G
+
+B.  List of available options
+
+   a. "video=intelfb"
+	enables the intelfb driver
+
+	Recommendation: required
+
+   b. "mode=<xres>x<yres>[-<bpp>][@<refresh>]"
+	select mode
+
+	Recommendation: user preference
+	(default = 1024x768-32@70)
+
+   c. "vram=<value>"
+	select amount of system RAM in MB to allocate for the video memory
+	if not enough RAM was already allocated by the BIOS.
+
+	Recommendation: 1 - 4 MB.
+	(default = 4 MB)
+
+   d. "voffset=<value>"
+        select at what offset in MB of the logical memory to allocate the
+	framebuffer memory.  The intent is to avoid the memory blocks
+	used by standard graphics applications (XFree86). Depending on your
+        usage, adjust the value up or down, (0 for maximum usage, 63/127 MB
+        for the least amount).  Note, an arbitrary setting may conflict
+        with XFree86.
+
+	Recommendation: do not set
+	(default = 48 MB)
+
+   e. "accel"
+	enable text acceleration.  This can be enabled/reenabled anytime
+	by using 'fbset -accel true/false'.
+
+	Recommendation: enable
+	(default = set)
+
+   f. "hwcursor"
+	enable cursor acceleration.
+
+	Recommendation: enable
+	(default = set)
+
+   g. "mtrr"
+	enable MTRR.  This allows data transfers to the framebuffer memory
+	to occur in bursts which can significantly increase performance.
+	Not very helpful with the intel chips because of 'shared memory'.
+
+	Recommendation: set
+	(default = set)
+
+   h. "fixed"
+	disable mode switching.
+
+	Recommendation: do not set
+	(default = not set)
+
+   The binary parameters can be unset with a "no" prefix, example "noaccel".
+   The default parameter (not named) is the mode.
+
+C. Kernel booting
+
+Separate each option/option-pair by commas (,) and the option from its value
+with an equals sign (=) as in the following:
+
+video=i810fb:option1,option2=value2
+
+Sample Usage
+------------
+
+In /etc/lilo.conf, add the line:
+
+append="video=intelfb:800x600-32@75,accel,hwcursor,vram=8"
+
+This will initialize the framebuffer to 800x600 at 32bpp and 75Hz. The
+framebuffer will use 8 MB of System RAM. hw acceleration of text and cursor
+will be enabled.
+
+D.  Module options
+
+	The module parameters are essentially similar to the kernel
+parameters. The main difference is that you need to include a Boolean value
+(1 for TRUE, and 0 for FALSE) for those options which don't need a value.
+
+Example, to enable MTRR, include "mtrr=1".
+
+Sample Usage
+------------
+
+Using the same setup as described above, load the module like this:
+
+	modprobe intelfb mode=800x600-32@75 vram=8 accel=1 hwcursor=1
+
+Or just add the following to /etc/modprobe.conf
+
+	options intelfb mode=800x600-32@75 vram=8 accel=1 hwcursor=1
+
+and just do a
+
+	modprobe intelfb
+
+
+E.  Acknowledgment:
+
+	1.  Geert Uytterhoeven - his excellent howto and the virtual
+                                 framebuffer driver code made this possible.
+
+	2.  Jeff Hartmann for his agpgart code.
+
+	3.  David Dawes for his original kernel 2.4 code.
+
+	4.  The X developers.  Insights were provided just by reading the
+	    XFree86 source code.
+
+	5.  Antonino A. Daplas for his inspiring i810fb driver.
+
+	6.  Andrew Morton for his kernel patches maintenance.
+
+###########################
+Sylvain
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index b9eb209..1d227ee 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -43,6 +43,14 @@
 
 ---------------------------
 
+What:	RAW driver (CONFIG_RAW_DRIVER)
+When:	December 2005
+Why:	declared obsolete since kernel 2.6.3
+	O_DIRECT can be used instead
+Who:	Adrian Bunk <bunk@stusta.de>
+
+---------------------------
+
 What:	register_ioctl32_conversion() / unregister_ioctl32_conversion()
 When:	April 2005
 Why:	Replaced by ->compat_ioctl in file_operations and other method
@@ -66,6 +74,14 @@
 
 ---------------------------
 
+What:	remove verify_area()
+When:	July 2006
+Files:	Various uaccess.h headers.
+Why:	Deprecated and redundant. access_ok() should be used instead.
+Who:	Jesper Juhl <juhl-lkml@dif.dk>
+
+---------------------------
+
 What:	IEEE1394 Audio and Music Data Transmission Protocol driver,
 	Connection Management Procedures driver
 When:	November 2005
@@ -83,3 +99,23 @@
 	more efficient.  You should really be using libraw1394 for raw1394
 	access anyway.
 Who:	Jody McIntyre <scjody@steamballoon.com>
+
+---------------------------
+
+What:	register_serial/unregister_serial
+When:	December 2005
+Why:	This interface does not allow serial ports to be registered against
+	a struct device, and as such does not allow correct power management
+	of such ports.  8250-based ports should use serial8250_register_port
+	and serial8250_unregister_port instead.
+Who:	Russell King <rmk@arm.linux.org.uk>
+
+---------------------------
+
+What:	i2c sysfs name change: in1_ref, vid deprecated in favour of cpu0_vid
+When:	November 2005
+Files:	drivers/i2c/chips/adm1025.c, drivers/i2c/chips/adm1026.c
+Why:	Match the other drivers' name for the same function, duplicate names
+	will be available until removal of old names.
+Who:	Grant Coady <gcoady@gmail.com>
+
diff --git a/Documentation/filesystems/ext2.txt b/Documentation/filesystems/ext2.txt
index b5cb911..d16334e 100644
--- a/Documentation/filesystems/ext2.txt
+++ b/Documentation/filesystems/ext2.txt
@@ -58,6 +58,8 @@
 
 nobh				Do not attach buffer_heads to file pagecache.
 
+xip				Use execute in place (no caching) if possible
+
 grpquota,noquota,quota,usrquota	Quota options are silently ignored by ext2.
 
 
diff --git a/Documentation/filesystems/isofs.txt b/Documentation/filesystems/isofs.txt
index f64a105..424585f 100644
--- a/Documentation/filesystems/isofs.txt
+++ b/Documentation/filesystems/isofs.txt
@@ -26,7 +26,11 @@
   mode=xxx      Sets the permissions on files to xxx
   nojoliet      Ignore Joliet extensions if they are present.
   norock        Ignore Rock Ridge extensions if they are present.
-  unhide        Show hidden files.
+  hide		Completely strip hidden files from the file system.
+  showassoc	Show files marked with the 'associated' bit
+  unhide	Deprecated; showing hidden files is now default;
+		If given, it is a synonym for 'showassoc' which will
+		recreate previous unhide behavior
   session=x     Select number of session on multisession CD
   sbsector=xxx  Session begins from sector xxx
 
diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt
index 60f6c2c..dc27659 100644
--- a/Documentation/filesystems/sysfs.txt
+++ b/Documentation/filesystems/sysfs.txt
@@ -214,7 +214,7 @@
 
 A very simple (and naive) implementation of a device attribute is:
 
-static ssize_t show_name(struct device * dev, char * buf)
+static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
 {
         return sprintf(buf,"%s\n",dev->name);
 }
diff --git a/Documentation/filesystems/tmpfs.txt b/Documentation/filesystems/tmpfs.txt
index 417e309..0d783c5 100644
--- a/Documentation/filesystems/tmpfs.txt
+++ b/Documentation/filesystems/tmpfs.txt
@@ -71,8 +71,8 @@
 to limit this tmpfs instance to that percentage of your physical RAM:
 the default, when neither size nor nr_blocks is specified, is size=50%
 
-If both nr_blocks (or size) and nr_inodes are set to 0, neither blocks
-nor inodes will be limited in that instance.  It is generally unwise to
+If nr_blocks=0 (or size=0), blocks will not be limited in that instance;
+if nr_inodes=0, inodes will not be limited.  It is generally unwise to
 mount with such options, since it allows any user with write access to
 use up all the memory on the machine; but enhances the scalability of
 that instance in a system with many cpus making intensive use of it.
@@ -97,4 +97,4 @@
 Author:
    Christoph Rohland <cr@sap.com>, 1.12.01
 Updated:
-   Hugh Dickins <hugh@veritas.com>, 01 September 2004
+   Hugh Dickins <hugh@veritas.com>, 13 March 2005
diff --git a/Documentation/filesystems/xip.txt b/Documentation/filesystems/xip.txt
new file mode 100644
index 0000000..6c0cef1
--- /dev/null
+++ b/Documentation/filesystems/xip.txt
@@ -0,0 +1,67 @@
+Execute-in-place for file mappings
+----------------------------------
+
+Motivation
+----------
+File mappings are performed by mapping page cache pages to userspace. In
+addition, read&write type file operations also transfer data from/to the page
+cache.
+
+For memory backed storage devices that use the block device interface, the page
+cache pages are in fact copies of the original storage. Various approaches
+exist to work around the need for an extra copy. The ramdisk driver for example
+does read the data into the page cache, keeps a reference, and discards the
+original data behind later on.
+
+Execute-in-place solves this issue the other way around: instead of keeping
+data in the page cache, the need to have a page cache copy is eliminated
+completely. With execute-in-place, read&write type operations are performed
+directly from/to the memory backed storage device. For file mappings, the
+storage device itself is mapped directly into userspace.
+
+This implementation was initialy written for shared memory segments between
+different virtual machines on s390 hardware to allow multiple machines to
+share the same binaries and libraries.
+
+Implementation
+--------------
+Execute-in-place is implemented in three steps: block device operation,
+address space operation, and file operations.
+
+A block device operation named direct_access is used to retrieve a
+reference (pointer) to a block on-disk. The reference is supposed to be
+cpu-addressable, physical address and remain valid until the release operation
+is performed. A struct block_device reference is used to address the device,
+and a sector_t argument is used to identify the individual block. As an
+alternative, memory technology devices can be used for this.
+
+The block device operation is optional, these block devices support it as of
+today:
+- dcssblk: s390 dcss block device driver
+
+An address space operation named get_xip_page is used to retrieve reference
+to a struct page. To address the target page, a reference to an address_space,
+and a sector number is provided. A 3rd argument indicates whether the
+function should allocate blocks if needed.
+
+This address space operation is mutually exclusive with readpage&writepage that
+do page cache read/write operations.
+The following filesystems support it as of today:
+- ext2: the second extended filesystem, see Documentation/filesystems/ext2.txt
+
+A set of file operations that do utilize get_xip_page can be found in
+mm/filemap_xip.c . The following file operation implementations are provided:
+- aio_read/aio_write
+- readv/writev
+- sendfile
+
+The generic file operations do_sync_read/do_sync_write can be used to implement
+classic synchronous IO calls.
+
+Shortcomings
+------------
+This implementation is limited to storage devices that are cpu addressable at
+all times (no highmem or such). It works well on rom/ram, but enhancements are
+needed to make it work with flash in read+write mode.
+Putting the Linux kernel and/or its modules on a xip filesystem does not mean
+they are not copied.
diff --git a/Documentation/i2c/busses/i2c-sis69x b/Documentation/i2c/busses/i2c-sis69x
index 5be4876..b88953d 100644
--- a/Documentation/i2c/busses/i2c-sis69x
+++ b/Documentation/i2c/busses/i2c-sis69x
@@ -42,7 +42,7 @@
 chipsets as well: 635, and 635T. If anyone owns a board with those chips
 AND is willing to risk crashing & burning an otherwise well-behaved kernel
 in the name of progress... please contact me at <mhoffman@lightlink.com> or
-via the project's mailing list: <sensors@stimpy.netroedge.com>.  Please
+via the project's mailing list: <lm-sensors@lm-sensors.org>.  Please
 send bug reports and/or success stories as well.
 
 
diff --git a/Documentation/i2c/chips/adm1021 b/Documentation/i2c/chips/adm1021
new file mode 100644
index 0000000..03d02bf
--- /dev/null
+++ b/Documentation/i2c/chips/adm1021
@@ -0,0 +1,111 @@
+Kernel driver adm1021
+=====================
+
+Supported chips:
+  * Analog Devices ADM1021
+    Prefix: 'adm1021'
+    Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+    Datasheet: Publicly available at the Analog Devices website
+  * Analog Devices ADM1021A/ADM1023
+    Prefix: 'adm1023'
+    Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+    Datasheet: Publicly available at the Analog Devices website
+  * Genesys Logic GL523SM
+    Prefix: 'gl523sm'
+    Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+    Datasheet:
+  * Intel Xeon Processor
+    Prefix: - any other - may require 'force_adm1021' parameter
+    Addresses scanned: none
+    Datasheet: Publicly available at Intel website
+  * Maxim MAX1617
+    Prefix: 'max1617'
+    Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+    Datasheet: Publicly available at the Maxim website
+  * Maxim MAX1617A
+    Prefix: 'max1617a'
+    Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+    Datasheet: Publicly available at the Maxim website
+  * National Semiconductor LM84
+    Prefix: 'lm84'
+    Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+    Datasheet: Publicly available at the National Semiconductor website
+  * Philips NE1617
+    Prefix: 'max1617' (probably detected as a max1617)
+    Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+    Datasheet: Publicly available at the Philips website
+  * Philips NE1617A
+    Prefix: 'max1617' (probably detected as a max1617)
+    Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+    Datasheet: Publicly available at the Philips website
+  * TI THMC10
+    Prefix: 'thmc10'
+    Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+    Datasheet: Publicly available at the TI website
+  * Onsemi MC1066
+    Prefix: 'mc1066'
+    Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
+    Datasheet: Publicly available at the Onsemi website
+
+
+Authors:
+        Frodo Looijaard <frodol@dds.nl>,
+        Philip Edelbrock <phil@netroedge.com>
+
+Module Parameters
+-----------------
+
+* read_only: int
+  Don't set any values, read only mode
+
+
+Description
+-----------
+
+The chips supported by this driver are very similar. The Maxim MAX1617 is
+the oldest; it has the problem that it is not very well detectable. The
+MAX1617A solves that. The ADM1021 is a straight clone of the MAX1617A.
+Ditto for the THMC10. From here on, we will refer to all these chips as
+ADM1021-clones.
+
+The ADM1021 and MAX1617A reports a die code, which is a sort of revision
+code. This can help us pinpoint problems; it is not very useful
+otherwise.
+
+ADM1021-clones implement two temperature sensors. One of them is internal,
+and measures the temperature of the chip itself; the other is external and
+is realised in the form of a transistor-like device. A special alarm
+indicates whether the remote sensor is connected.
+
+Each sensor has its own low and high limits. When they are crossed, the
+corresponding alarm is set and remains on as long as the temperature stays
+out of range. Temperatures are measured in degrees Celsius. Measurements
+are possible between -65 and +127 degrees, with a resolution of one degree.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may already
+have disappeared!
+
+This driver only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values. It is possible to make
+ADM1021-clones do faster measurements, but there is really no good reason
+for that.
+
+Xeon support
+------------
+
+Some Xeon processors have real max1617, adm1021, or compatible chips
+within them, with two temperature sensors.
+
+Other Xeons have chips with only one sensor.
+
+If you have a Xeon, and the adm1021 module loads, and both temperatures
+appear valid, then things are good.
+
+If the adm1021 module doesn't load, you should try this:
+	modprobe adm1021 force_adm1021=BUS,ADDRESS
+	ADDRESS can only be 0x18, 0x1a, 0x29, 0x2b, 0x4c, or 0x4e.
+
+If you have dual Xeons you may have appear to have two separate
+adm1021-compatible chips, or two single-temperature sensors, at distinct
+addresses.
diff --git a/Documentation/i2c/chips/adm1025 b/Documentation/i2c/chips/adm1025
new file mode 100644
index 0000000..39d2b78
--- /dev/null
+++ b/Documentation/i2c/chips/adm1025
@@ -0,0 +1,51 @@
+Kernel driver adm1025
+=====================
+
+Supported chips:
+  * Analog Devices ADM1025, ADM1025A
+    Prefix: 'adm1025'
+    Addresses scanned: I2C 0x2c - 0x2e
+    Datasheet: Publicly available at the Analog Devices website
+  * Philips NE1619
+    Prefix: 'ne1619'
+    Addresses scanned: I2C 0x2c - 0x2d
+    Datasheet: Publicly available at the Philips website
+
+The NE1619 presents some differences with the original ADM1025:
+  * Only two possible addresses (0x2c - 0x2d).
+  * No temperature offset register, but we don't use it anyway.
+  * No INT mode for pin 16. We don't play with it anyway.
+
+Authors:
+        Chen-Yuan Wu <gwu@esoft.com>,
+        Jean Delvare <khali@linux-fr.org>
+
+Description
+-----------
+
+(This is from Analog Devices.) The ADM1025 is a complete system hardware
+monitor for microprocessor-based systems, providing measurement and limit
+comparison of various system parameters. Five voltage measurement inputs
+are provided, for monitoring +2.5V, +3.3V, +5V and +12V power supplies and
+the processor core voltage. The ADM1025 can monitor a sixth power-supply
+voltage by measuring its own VCC. One input (two pins) is dedicated to a
+remote temperature-sensing diode and an on-chip temperature sensor allows
+ambient temperature to be monitored.
+
+One specificity of this chip is that the pin 11 can be hardwired in two
+different manners. It can act as the +12V power-supply voltage analog
+input, or as the a fifth digital entry for the VID reading (bit 4). It's
+kind of strange since both are useful, and the reason for designing the
+chip that way is obscure at least to me. The bit 5 of the configuration
+register can be used to define how the chip is hardwired. Please note that
+it is not a choice you have to make as the user. The choice was already
+made by your motherboard's maker. If the configuration bit isn't set
+properly, you'll have a wrong +12V reading or a wrong VID reading. The way
+the driver handles that is to preserve this bit through the initialization
+process, assuming that the BIOS set it up properly beforehand. If it turns
+out not to be true in some cases, we'll provide a module parameter to force
+modes.
+
+This driver also supports the ADM1025A, which differs from the ADM1025
+only in that it has "open-drain VID inputs while the ADM1025 has on-chip
+100k pull-ups on the VID inputs". It doesn't make any difference for us.
diff --git a/Documentation/i2c/chips/adm1026 b/Documentation/i2c/chips/adm1026
new file mode 100644
index 0000000..473c689
--- /dev/null
+++ b/Documentation/i2c/chips/adm1026
@@ -0,0 +1,93 @@
+Kernel driver adm1026
+=====================
+
+Supported chips:
+  * Analog Devices ADM1026
+    Prefix: 'adm1026'
+    Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+    Datasheet: Publicly available at the Analog Devices website
+               http://www.analog.com/en/prod/0,,766_825_ADM1026,00.html
+
+Authors:
+        Philip Pokorny <ppokorny@penguincomputing.com> for Penguin Computing
+        Justin Thiessen <jthiessen@penguincomputing.com>
+
+Module Parameters
+-----------------
+
+* gpio_input: int array (min = 1, max = 17)
+  List of GPIO pins (0-16) to program as inputs
+* gpio_output: int array (min = 1, max = 17)
+  List of GPIO pins (0-16) to program as outputs
+* gpio_inverted: int array (min = 1, max = 17)
+  List of GPIO pins (0-16) to program as inverted
+* gpio_normal: int array (min = 1, max = 17)
+  List of GPIO pins (0-16) to program as normal/non-inverted
+* gpio_fan: int array (min = 1, max = 8)
+  List of GPIO pins (0-7) to program as fan tachs
+
+
+Description
+-----------
+
+This driver implements support for the Analog Devices ADM1026. Analog
+Devices calls it a "complete thermal system management controller."
+
+The ADM1026 implements three (3) temperature sensors, 17 voltage sensors,
+16 general purpose digital I/O lines, eight (8) fan speed sensors (8-bit),
+an analog output and a PWM output along with limit, alarm and mask bits for
+all of the above. There is even 8k bytes of EEPROM memory on chip.
+
+Temperatures are measured in degrees Celsius. There are two external
+sensor inputs and one internal sensor. Each sensor has a high and low
+limit. If the limit is exceeded, an interrupt (#SMBALERT) can be
+generated. The interrupts can be masked. In addition, there are over-temp
+limits for each sensor. If this limit is exceeded, the #THERM output will
+be asserted. The current temperature and limits have a resolution of 1
+degree.
+
+Fan rotation speeds are reported in RPM (rotations per minute) but measured
+in counts of a 22.5kHz internal clock. Each fan has a high limit which
+corresponds to a minimum fan speed. If the limit is exceeded, an interrupt
+can be generated. Each fan can be programmed to divide the reference clock
+by 1, 2, 4 or 8. Not all RPM values can accurately be represented, so some
+rounding is done. With a divider of 8, the slowest measurable speed of a
+two pulse per revolution fan is 661 RPM.
+
+There are 17 voltage sensors. An alarm is triggered if the voltage has
+crossed a programmable minimum or maximum limit. Note that minimum in this
+case always means 'closest to zero'; this is important for negative voltage
+measurements. Several inputs have integrated attenuators so they can measure
+higher voltages directly. 3.3V, 5V, 12V, -12V and battery voltage all have
+dedicated inputs. There are several inputs scaled to 0-3V full-scale range
+for SCSI terminator power. The remaining inputs are not scaled and have
+a 0-2.5V full-scale range. A 2.5V or 1.82V reference voltage is provided
+for negative voltage measurements.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may already
+have disappeared! Note that in the current implementation, all hardware
+registers are read whenever any data is read (unless it is less than 2.0
+seconds since the last update). This means that you can easily miss
+once-only alarms.
+
+The ADM1026 measures continuously. Analog inputs are measured about 4
+times a second. Fan speed measurement time depends on fan speed and
+divisor. It can take as long as 1.5 seconds to measure all fan speeds.
+
+The ADM1026 has the ability to automatically control fan speed based on the
+temperature sensor inputs. Both the PWM output and the DAC output can be
+used to control fan speed. Usually only one of these two outputs will be
+used. Write the minimum PWM or DAC value to the appropriate control
+register. Then set the low temperature limit in the tmin values for each
+temperature sensor. The range of control is fixed at 20 °C, and the
+largest difference between current and tmin of the temperature sensors sets
+the control output. See the datasheet for several example circuits for
+controlling fan speed with the PWM and DAC outputs. The fan speed sensors
+do not have PWM compensation, so it is probably best to control the fan
+voltage from the power lead rather than on the ground lead.
+
+The datasheet shows an example application with VID signals attached to
+GPIO lines. Unfortunately, the chip may not be connected to the VID lines
+in this way. The driver assumes that the chips *is* connected this way to
+get a VID voltage.
diff --git a/Documentation/i2c/chips/adm1031 b/Documentation/i2c/chips/adm1031
new file mode 100644
index 0000000..130a383
--- /dev/null
+++ b/Documentation/i2c/chips/adm1031
@@ -0,0 +1,35 @@
+Kernel driver adm1031
+=====================
+
+Supported chips:
+  * Analog Devices ADM1030
+    Prefix: 'adm1030'
+    Addresses scanned: I2C 0x2c to 0x2e
+    Datasheet: Publicly available at the Analog Devices website
+               http://products.analog.com/products/info.asp?product=ADM1030
+
+  * Analog Devices ADM1031
+    Prefix: 'adm1031'
+    Addresses scanned: I2C 0x2c to 0x2e
+    Datasheet: Publicly available at the Analog Devices website
+               http://products.analog.com/products/info.asp?product=ADM1031
+
+Authors:
+        Alexandre d'Alton <alex@alexdalton.org>
+        Jean Delvare <khali@linux-fr.org>
+
+Description
+-----------
+
+The ADM1030 and ADM1031 are digital temperature sensors and fan controllers.
+They sense their own temperature as well as the temperature of up to one
+(ADM1030) or two (ADM1031) external diodes.
+
+All temperature values are given in degrees Celsius. Resolution is 0.5
+degree for the local temperature, 0.125 degree for the remote temperatures.
+
+Each temperature channel has its own high and low limits, plus a critical
+limit.
+
+The ADM1030 monitors a single fan speed, while the ADM1031 monitors up to
+two. Each fan channel has its own low speed limit.
diff --git a/Documentation/i2c/chips/adm9240 b/Documentation/i2c/chips/adm9240
new file mode 100644
index 0000000..35f618f
--- /dev/null
+++ b/Documentation/i2c/chips/adm9240
@@ -0,0 +1,177 @@
+Kernel driver adm9240
+=====================
+
+Supported chips:
+  * Analog Devices ADM9240
+    Prefix: 'adm9240'
+    Addresses scanned: I2C 0x2c - 0x2f
+    Datasheet: Publicly available at the Analog Devices website
+    http://www.analog.com/UploadedFiles/Data_Sheets/79857778ADM9240_0.pdf
+
+  * Dallas Semiconductor DS1780
+    Prefix: 'ds1780'
+    Addresses scanned: I2C 0x2c - 0x2f
+    Datasheet: Publicly available at the Dallas Semiconductor (Maxim) website
+    http://pdfserv.maxim-ic.com/en/ds/DS1780.pdf
+
+  * National Semiconductor LM81
+    Prefix: 'lm81'
+    Addresses scanned: I2C 0x2c - 0x2f
+    Datasheet: Publicly available at the National Semiconductor website
+    http://www.national.com/ds.cgi/LM/LM81.pdf
+
+Authors:
+    Frodo Looijaard <frodol@dds.nl>,
+    Philip Edelbrock <phil@netroedge.com>,
+    Michiel Rook <michiel@grendelproject.nl>,
+    Grant Coady <gcoady@gmail.com> with guidance
+        from Jean Delvare <khali@linux-fr.org>
+
+Interface
+---------
+The I2C addresses listed above assume BIOS has not changed the
+chip MSB 5-bit address. Each chip reports a unique manufacturer
+identification code as well as the chip revision/stepping level.
+
+Description
+-----------
+[From ADM9240] The ADM9240 is a complete system hardware monitor for
+microprocessor-based systems, providing measurement and limit comparison
+of up to four power supplies and two processor core voltages, plus
+temperature, two fan speeds and chassis intrusion. Measured values can
+be read out via an I2C-compatible serial System Management Bus, and values
+for limit comparisons can be programmed in over the same serial bus. The
+high speed successive approximation ADC allows frequent sampling of all
+analog channels to ensure a fast interrupt response to any out-of-limit
+measurement.
+
+The ADM9240, DS1780 and LM81 are register compatible, the following
+details are common to the three chips. Chip differences are described
+after this section.
+
+
+Measurements
+------------
+The measurement cycle
+
+The adm9240 driver will take a measurement reading no faster than once
+each two seconds. User-space may read sysfs interface faster than the
+measurement update rate and will receive cached data from the most
+recent measurement.
+
+ADM9240 has a very fast 320us temperature and voltage measurement cycle
+with independent fan speed measurement cycles counting alternating rising
+edges of the fan tacho inputs.
+
+DS1780 measurement cycle is about once per second including fan speed.
+
+LM81 measurement cycle is about once per 400ms including fan speed.
+The LM81 12-bit extended temperature measurement mode is not supported.
+
+Temperature
+-----------
+On chip temperature is reported as degrees Celsius as 9-bit signed data
+with resolution of 0.5 degrees Celsius. High and low temperature limits
+are 8-bit signed data with resolution of one degree Celsius.
+
+Temperature alarm is asserted once the temperature exceeds the high limit,
+and is cleared when the temperature falls below the temp1_max_hyst value.
+
+Fan Speed
+---------
+Two fan tacho inputs are provided, the ADM9240 gates an internal 22.5kHz
+clock via a divider to an 8-bit counter. Fan speed (rpm) is calculated by:
+
+rpm = (22500 * 60) / (count * divider)
+
+Automatic fan clock divider
+
+  * User sets 0 to fan_min limit
+    - low speed alarm is disabled
+    - fan clock divider not changed
+    - auto fan clock adjuster enabled for valid fan speed reading
+
+  * User sets fan_min limit too low
+    - low speed alarm is enabled
+    - fan clock divider set to max
+    - fan_min set to register value 254 which corresponds
+      to 664 rpm on adm9240
+    - low speed alarm will be asserted if fan speed is
+      less than minimum measurable speed
+    - auto fan clock adjuster disabled
+
+  * User sets reasonable fan speed
+    - low speed alarm is enabled
+    - fan clock divider set to suit fan_min
+    - auto fan clock adjuster enabled: adjusts fan_min
+
+  * User sets unreasonably high low fan speed limit
+    - resolution of the low speed limit may be reduced
+    - alarm will be asserted
+    - auto fan clock adjuster enabled: adjusts fan_min
+
+    * fan speed may be displayed as zero until the auto fan clock divider
+      adjuster brings fan speed clock divider back into chip measurement
+      range, this will occur within a few measurement cycles.
+
+Analog Output
+-------------
+An analog output provides a 0 to 1.25 volt signal intended for an external
+fan speed amplifier circuit. The analog output is set to maximum value on
+power up or reset. This doesn't do much on the test Intel SE440BX-2.
+
+Voltage Monitor
+
+Voltage (IN) measurement is internally scaled:
+
+    nr  label       nominal     maximum   resolution
+                      mV          mV         mV
+    0   +2.5V        2500        3320       13.0
+    1   Vccp1        2700        3600       14.1
+    2   +3.3V        3300        4380       17.2
+    3     +5V        5000        6640       26.0
+    4    +12V       12000       15940       62.5
+    5   Vccp2        2700        3600       14.1
+
+The reading is an unsigned 8-bit value, nominal voltage measurement is
+represented by a reading of 192, being 3/4 of the measurement range.
+
+An alarm is asserted for any voltage going below or above the set limits.
+
+The driver reports and accepts voltage limits scaled to the above table.
+
+VID Monitor
+-----------
+The chip has five inputs to read the 5-bit VID and reports the mV value
+based on detected CPU type.
+
+Chassis Intrusion
+-----------------
+An alarm is asserted when the CI pin goes active high. The ADM9240
+Datasheet has an example of an external temperature sensor driving
+this pin. On an Intel SE440BX-2 the Chassis Intrusion header is
+connected to a normally open switch.
+
+The ADM9240 provides an internal open drain on this line, and may output
+a 20 ms active low pulse to reset an external Chassis Intrusion latch.
+
+Clear the CI latch by writing value 1 to the sysfs chassis_clear file.
+
+Alarm flags reported as 16-bit word
+
+    bit     label               comment
+    ---     -------------       --------------------------
+     0      +2.5 V_Error        high or low limit exceeded
+     1      VCCP_Error          high or low limit exceeded
+     2      +3.3 V_Error        high or low limit exceeded
+     3      +5 V_Error          high or low limit exceeded
+     4      Temp_Error          temperature error
+     6      FAN1_Error          fan low limit exceeded
+     7      FAN2_Error          fan low limit exceeded
+     8      +12 V_Error         high or low limit exceeded
+     9      VCCP2_Error         high or low limit exceeded
+    12      Chassis_Error       CI pin went high
+
+Remaining bits are reserved and thus undefined. It is important to note
+that alarm bits may be cleared on read, user-space may latch alarms and
+provide the end-user with a method to clear alarm memory.
diff --git a/Documentation/i2c/chips/asb100 b/Documentation/i2c/chips/asb100
new file mode 100644
index 0000000..ab7365e
--- /dev/null
+++ b/Documentation/i2c/chips/asb100
@@ -0,0 +1,72 @@
+Kernel driver asb100
+====================
+
+Supported Chips:
+  * Asus ASB100 and ASB100-A "Bach"
+    Prefix: 'asb100'
+    Addresses scanned: I2C 0x2d
+    Datasheet: none released
+
+Author: Mark M. Hoffman <mhoffman@lightlink.com>
+
+Description
+-----------
+
+This driver implements support for the Asus ASB100 and ASB100-A "Bach".
+These are custom ASICs available only on Asus mainboards. Asus refuses to
+supply a datasheet for these chips. Thanks go to many people who helped
+investigate their hardware, including:
+
+Vitaly V. Bursov
+Alexander van Kaam (author of MBM for Windows)
+Bertrik Sikken
+
+The ASB100 implements seven voltage sensors, three fan rotation speed
+sensors, four temperature sensors, VID lines and alarms. In addition to
+these, the ASB100-A also implements a single PWM controller for fans 2 and
+3 (i.e. one setting controls both.) If you have a plain ASB100, the PWM
+controller will simply not work (or maybe it will for you... it doesn't for
+me).
+
+Temperatures are measured and reported in degrees Celsius.
+
+Fan speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit.
+
+Voltage sensors (also known as IN sensors) report values in volts.
+
+The VID lines encode the core voltage value: the voltage level your
+processor should work with. This is hardcoded by the mainboard and/or
+processor itself. It is a value in volts.
+
+Alarms: (TODO question marks indicate may or may not work)
+
+0x0001 => in0 (?)
+0x0002 => in1 (?)
+0x0004 => in2
+0x0008 => in3
+0x0010 => temp1 (1)
+0x0020 => temp2
+0x0040 => fan1
+0x0080 => fan2
+0x0100 => in4
+0x0200 => in5 (?) (2)
+0x0400 => in6 (?) (2)
+0x0800 => fan3
+0x1000 => chassis switch
+0x2000 => temp3
+
+Alarm Notes:
+
+(1) This alarm will only trigger if the hysteresis value is 127C.
+I.e. it behaves the same as w83781d.
+
+(2) The min and max registers for these values appear to
+be read-only or otherwise stuck at 0x00.
+
+TODO:
+* Experiment with fan divisors > 8.
+* Experiment with temp. sensor types.
+* Are there really 13 voltage inputs? Probably not...
+* Cleanups, no doubt...
+
diff --git a/Documentation/i2c/chips/ds1621 b/Documentation/i2c/chips/ds1621
new file mode 100644
index 0000000..1fee6f1
--- /dev/null
+++ b/Documentation/i2c/chips/ds1621
@@ -0,0 +1,108 @@
+Kernel driver ds1621
+====================
+
+Supported chips:
+  * Dallas Semiconductor DS1621
+    Prefix: 'ds1621'
+    Addresses scanned: I2C 0x48 - 0x4f
+    Datasheet: Publicly available at the Dallas Semiconductor website
+               http://www.dalsemi.com/
+  * Dallas Semiconductor DS1625
+    Prefix: 'ds1621'
+    Addresses scanned: I2C 0x48 - 0x4f
+    Datasheet: Publicly available at the Dallas Semiconductor website
+               http://www.dalsemi.com/
+
+Authors:
+        Christian W. Zuckschwerdt <zany@triq.net>
+        valuable contributions by Jan M. Sendler <sendler@sendler.de>
+        ported to 2.6 by Aurelien Jarno <aurelien@aurel32.net>
+        with the help of Jean Delvare <khali@linux-fr.org>
+
+Module Parameters
+------------------
+
+* polarity int
+  Output's polarity: 0 = active high, 1 = active low
+
+Description
+-----------
+
+The DS1621 is a (one instance) digital thermometer and thermostat. It has
+both high and low temperature limits which can be user defined (i.e.
+programmed into non-volatile on-chip registers). Temperature range is -55
+degree Celsius to +125 in 0.5 increments. You may convert this into a
+Fahrenheit range of -67 to +257 degrees with 0.9 steps. If polarity
+parameter is not provided, original value is used.
+
+As for the thermostat, behavior can also be programmed using the polarity
+toggle. On the one hand ("heater"), the thermostat output of the chip,
+Tout, will trigger when the low limit temperature is met or underrun and
+stays high until the high limit is met or exceeded. On the other hand
+("cooler"), vice versa. That way "heater" equals "active low", whereas
+"conditioner" equals "active high". Please note that the DS1621 data sheet
+is somewhat misleading in this point since setting the polarity bit does
+not simply invert Tout.
+
+A second thing is that, during extensive testing, Tout showed a tolerance
+of up to +/- 0.5 degrees even when compared against precise temperature
+readings. Be sure to have a high vs. low temperature limit gap of al least
+1.0 degree Celsius to avoid Tout "bouncing", though!
+
+As for alarms, you can read the alarm status of the DS1621 via the 'alarms'
+/sys file interface. The result consists mainly of bit 6 and 5 of the
+configuration register of the chip; bit 6 (0x40 or 64) is the high alarm
+bit and bit 5 (0x20 or 32) the low one. These bits are set when the high or
+low limits are met or exceeded and are reset by the module as soon as the
+respective temperature ranges are left.
+
+The alarm registers are in no way suitable to find out about the actual
+status of Tout. They will only tell you about its history, whether or not
+any of the limits have ever been met or exceeded since last power-up or
+reset. Be aware: When testing, it showed that the status of Tout can change
+with neither of the alarms set.
+
+Temperature conversion of the DS1621 takes up to 1000ms; internal access to
+non-volatile registers may last for 10ms or below.
+
+High Accuracy Temperature Reading
+---------------------------------
+
+As said before, the temperature issued via the 9-bit i2c-bus data is
+somewhat arbitrary. Internally, the temperature conversion is of a
+different kind that is explained (not so...) well in the DS1621 data sheet.
+To cut the long story short: Inside the DS1621 there are two oscillators,
+both of them biassed by a temperature coefficient.
+
+Higher resolution of the temperature reading can be achieved using the
+internal projection, which means taking account of REG_COUNT and REG_SLOPE
+(the driver manages them):
+
+Taken from Dallas Semiconductors App Note 068: 'Increasing Temperature
+Resolution on the DS1620' and App Note 105: 'High Resolution Temperature
+Measurement with Dallas Direct-to-Digital Temperature Sensors'
+
+- Read the 9-bit temperature and strip the LSB (Truncate the .5 degs)
+- The resulting value is TEMP_READ.
+- Then, read REG_COUNT.
+- And then, REG_SLOPE.
+
+      TEMP = TEMP_READ - 0.25 + ((REG_SLOPE - REG_COUNT) / REG_SLOPE)
+
+Note that this is what the DONE bit in the DS1621 configuration register is
+good for: Internally, one temperature conversion takes up to 1000ms. Before
+that conversion is complete you will not be able to read valid things out
+of REG_COUNT and REG_SLOPE. The DONE bit, as you may have guessed by now,
+tells you whether the conversion is complete ("done", in plain English) and
+thus, whether the values you read are good or not.
+
+The DS1621 has two modes of operation: "Continuous" conversion, which can
+be understood as the default stand-alone mode where the chip gets the
+temperature and controls external devices via its Tout pin or tells other
+i2c's about it if they care. The other mode is called "1SHOT", that means
+that it only figures out about the temperature when it is explicitly told
+to do so; this can be seen as power saving mode.
+
+Now if you want to read REG_COUNT and REG_SLOPE, you have to either stop
+the continuous conversions until the contents of these registers are valid,
+or, in 1SHOT mode, you have to have one conversion made.
diff --git a/Documentation/i2c/chips/eeprom b/Documentation/i2c/chips/eeprom
new file mode 100644
index 0000000..f7e8104
--- /dev/null
+++ b/Documentation/i2c/chips/eeprom
@@ -0,0 +1,96 @@
+Kernel driver eeprom
+====================
+
+Supported chips:
+  * Any EEPROM chip in the designated address range
+    Prefix: 'eeprom'
+    Addresses scanned: I2C 0x50 - 0x57
+    Datasheets: Publicly available from:
+                Atmel (www.atmel.com),
+                Catalyst (www.catsemi.com),
+                Fairchild (www.fairchildsemi.com),
+                Microchip (www.microchip.com),
+                Philips (www.semiconductor.philips.com),
+                Rohm (www.rohm.com),
+                ST (www.st.com),
+                Xicor (www.xicor.com),
+                and others.
+
+        Chip     Size (bits)    Address
+        24C01     1K            0x50 (shadows at 0x51 - 0x57)
+        24C01A    1K            0x50 - 0x57 (Typical device on DIMMs)
+        24C02     2K            0x50 - 0x57
+        24C04     4K            0x50, 0x52, 0x54, 0x56
+                                (additional data at 0x51, 0x53, 0x55, 0x57)
+        24C08     8K            0x50, 0x54 (additional data at 0x51, 0x52,
+                                0x53, 0x55, 0x56, 0x57)
+        24C16    16K            0x50 (additional data at 0x51 - 0x57)
+        Sony      2K            0x57
+
+        Atmel     34C02B  2K    0x50 - 0x57, SW write protect at 0x30-37
+        Catalyst  34FC02  2K    0x50 - 0x57, SW write protect at 0x30-37
+        Catalyst  34RC02  2K    0x50 - 0x57, SW write protect at 0x30-37
+        Fairchild 34W02   2K    0x50 - 0x57, SW write protect at 0x30-37
+        Microchip 24AA52  2K    0x50 - 0x57, SW write protect at 0x30-37
+        ST        M34C02  2K    0x50 - 0x57, SW write protect at 0x30-37
+
+
+Authors:
+        Frodo Looijaard <frodol@dds.nl>,
+        Philip Edelbrock <phil@netroedge.com>,
+        Jean Delvare <khali@linux-fr.org>,
+        Greg Kroah-Hartman <greg@kroah.com>,
+        IBM Corp.
+
+Description
+-----------
+
+This is a simple EEPROM module meant to enable reading the first 256 bytes
+of an EEPROM (on a SDRAM DIMM for example). However, it will access serial
+EEPROMs on any I2C adapter. The supported devices are generically called
+24Cxx, and are listed above; however the numbering for these
+industry-standard devices may vary by manufacturer.
+
+This module was a programming exercise to get used to the new project
+organization laid out by Frodo, but it should be at least completely
+effective for decoding the contents of EEPROMs on DIMMs.
+
+DIMMS will typically contain a 24C01A or 24C02, or the 34C02 variants.
+The other devices will not be found on a DIMM because they respond to more
+than one address.
+
+DDC Monitors may contain any device. Often a 24C01, which responds to all 8
+addresses, is found.
+
+Recent Sony Vaio laptops have an EEPROM at 0x57. We couldn't get the
+specification, so it is guess work and far from being complete.
+
+The Microchip 24AA52/24LCS52, ST M34C02, and others support an additional
+software write protect register at 0x30 - 0x37 (0x20 less than the memory
+location). The chip responds to "write quick" detection at this address but
+does not respond to byte reads. If this register is present, the lower 128
+bytes of the memory array are not write protected. Any byte data write to
+this address will write protect the memory array permanently, and the
+device will no longer respond at the 0x30-37 address. The eeprom driver
+does not support this register.
+
+Lacking functionality:
+
+* Full support for larger devices (24C04, 24C08, 24C16). These are not
+typically found on a PC. These devices will appear as separate devices at
+multiple addresses.
+
+* Support for really large devices (24C32, 24C64, 24C128, 24C256, 24C512).
+These devices require two-byte address fields and are not supported.
+
+* Enable Writing. Again, no technical reason why not, but making it easy
+to change the contents of the EEPROMs (on DIMMs anyway) also makes it easy
+to disable the DIMMs (potentially preventing the computer from booting)
+until the values are restored somehow.
+
+Use:
+
+After inserting the module (and any other required SMBus/i2c modules), you
+should have some EEPROM directories in /sys/bus/i2c/devices/* of names such
+as "0-0050". Inside each of these is a series of files, the eeprom file
+contains the binary data from EEPROM.
diff --git a/Documentation/i2c/chips/fscher b/Documentation/i2c/chips/fscher
new file mode 100644
index 0000000..6403165
--- /dev/null
+++ b/Documentation/i2c/chips/fscher
@@ -0,0 +1,169 @@
+Kernel driver fscher
+====================
+
+Supported chips:
+  * Fujitsu-Siemens Hermes chip
+    Prefix: 'fscher'
+    Addresses scanned: I2C 0x73
+
+Authors:
+        Reinhard Nissl <rnissl@gmx.de> based on work
+        from Hermann Jung <hej@odn.de>,
+        Frodo Looijaard <frodol@dds.nl>,
+        Philip Edelbrock <phil@netroedge.com>
+
+Description
+-----------
+
+This driver implements support for the Fujitsu-Siemens Hermes chip. It is
+described in the 'Register Set Specification BMC Hermes based Systemboard'
+from Fujitsu-Siemens.
+
+The Hermes chip implements a hardware-based system management, e.g. for
+controlling fan speed and core voltage. There is also a watchdog counter on
+the chip which can trigger an alarm and even shut the system down.
+
+The chip provides three temperature values (CPU, motherboard and
+auxiliary), three voltage values (+12V, +5V and battery) and three fans
+(power supply, CPU and auxiliary).
+
+Temperatures are measured in degrees Celsius. The resolution is 1 degree.
+
+Fan rotation speeds are reported in RPM (rotations per minute). The value
+can be divided by a programmable divider (1, 2 or 4) which is stored on
+the chip.
+
+Voltage sensors (also known as "in" sensors) report their values in volts.
+
+All values are reported as final values from the driver. There is no need
+for further calculations.
+
+
+Detailed description
+--------------------
+
+Below you'll find a single line description of all the bit values. With
+this information, you're able to decode e. g. alarms, wdog, etc. To make
+use of the watchdog, you'll need to set the watchdog time and enable the
+watchdog. After that it is necessary to restart the watchdog time within
+the specified period of time, or a system reset will occur.
+
+* revision
+  READING & 0xff = 0x??: HERMES revision identification
+
+* alarms
+  READING & 0x80 = 0x80: CPU throttling active
+  READING & 0x80 = 0x00: CPU running at full speed
+
+  READING & 0x10 = 0x10: software event (see control:1)
+  READING & 0x10 = 0x00: no software event
+
+  READING & 0x08 = 0x08: watchdog event (see wdog:2)
+  READING & 0x08 = 0x00: no watchdog event
+
+  READING & 0x02 = 0x02: thermal event (see temp*:1)
+  READING & 0x02 = 0x00: no thermal event
+
+  READING & 0x01 = 0x01: fan event (see fan*:1)
+  READING & 0x01 = 0x00: no fan event
+
+  READING & 0x13 ! 0x00: ALERT LED is flashing
+
+* control
+  READING & 0x01 = 0x01: software event
+  READING & 0x01 = 0x00: no software event
+
+  WRITING & 0x01 = 0x01: set software event
+  WRITING & 0x01 = 0x00: clear software event
+
+* watchdog_control
+  READING & 0x80 = 0x80: power off on watchdog event while thermal event
+  READING & 0x80 = 0x00: watchdog power off disabled (just system reset enabled)
+
+  READING & 0x40 = 0x40: watchdog timebase 60 seconds (see also wdog:1)
+  READING & 0x40 = 0x00: watchdog timebase  2 seconds
+
+  READING & 0x10 = 0x10: watchdog enabled
+  READING & 0x10 = 0x00: watchdog disabled
+
+  WRITING & 0x80 = 0x80: enable "power off on watchdog event while thermal event"
+  WRITING & 0x80 = 0x00: disable "power off on watchdog event while thermal event"
+
+  WRITING & 0x40 = 0x40: set watchdog timebase to 60 seconds
+  WRITING & 0x40 = 0x00: set watchdog timebase to  2 seconds
+
+  WRITING & 0x20 = 0x20: disable watchdog
+
+  WRITING & 0x10 = 0x10: enable watchdog / restart watchdog time
+
+* watchdog_state
+  READING & 0x02 = 0x02: watchdog system reset occurred
+  READING & 0x02 = 0x00: no watchdog system reset occurred
+
+  WRITING & 0x02 = 0x02: clear watchdog event
+
+* watchdog_preset
+  READING & 0xff = 0x??: configured watch dog time in units (see wdog:3 0x40)
+
+  WRITING & 0xff = 0x??: configure watch dog time in units
+
+* in*     (0: +5V, 1: +12V, 2: onboard 3V battery)
+  READING: actual voltage value
+
+* temp*_status   (1: CPU sensor, 2: onboard sensor, 3: auxiliary sensor)
+  READING & 0x02 = 0x02: thermal event (overtemperature)
+  READING & 0x02 = 0x00: no thermal event
+
+  READING & 0x01 = 0x01: sensor is working
+  READING & 0x01 = 0x00: sensor is faulty
+
+  WRITING & 0x02 = 0x02: clear thermal event
+
+* temp*_input   (1: CPU sensor, 2: onboard sensor, 3: auxiliary sensor)
+  READING: actual temperature value
+
+* fan*_status   (1: power supply fan, 2: CPU fan, 3: auxiliary fan)
+  READING & 0x04 = 0x04: fan event (fan fault)
+  READING & 0x04 = 0x00: no fan event
+
+  WRITING & 0x04 = 0x04: clear fan event
+
+* fan*_div (1: power supply fan, 2: CPU fan, 3: auxiliary fan)
+  	Divisors 2,4 and 8 are supported, both for reading and writing
+
+* fan*_pwm   (1: power supply fan, 2: CPU fan, 3: auxiliary fan)
+  READING & 0xff = 0x00: fan may be switched off
+  READING & 0xff = 0x01: fan must run at least at minimum speed (supply: 6V)
+  READING & 0xff = 0xff: fan must run at maximum speed (supply: 12V)
+  READING & 0xff = 0x??: fan must run at least at given speed (supply: 6V..12V)
+
+  WRITING & 0xff = 0x00: fan may be switched off
+  WRITING & 0xff = 0x01: fan must run at least at minimum speed (supply: 6V)
+  WRITING & 0xff = 0xff: fan must run at maximum speed (supply: 12V)
+  WRITING & 0xff = 0x??: fan must run at least at given speed (supply: 6V..12V)
+
+* fan*_input   (1: power supply fan, 2: CPU fan, 3: auxiliary fan)
+  READING: actual RPM value
+
+
+Limitations
+-----------
+
+* Measuring fan speed
+It seems that the chip counts "ripples" (typical fans produce 2 ripples per
+rotation while VERAX fans produce 18) in a 9-bit register. This register is
+read out every second, then the ripple prescaler (2, 4 or 8) is applied and
+the result is stored in the 8 bit output register. Due to the limitation of
+the counting register to 9 bits, it is impossible to measure a VERAX fan
+properly (even with a prescaler of 8). At its maximum speed of 3500 RPM the
+fan produces 1080 ripples per second which causes the counting register to
+overflow twice, leading to only 186 RPM.
+
+* Measuring input voltages
+in2 ("battery") reports the voltage of the onboard lithium battery and not
++3.3V from the power supply.
+
+* Undocumented features
+Fujitsu-Siemens Computers has not documented all features of the chip so
+far. Their software, System Guard, shows that there are a still some
+features which cannot be controlled by this implementation.
diff --git a/Documentation/i2c/chips/gl518sm b/Documentation/i2c/chips/gl518sm
new file mode 100644
index 0000000..ce088188
--- /dev/null
+++ b/Documentation/i2c/chips/gl518sm
@@ -0,0 +1,74 @@
+Kernel driver gl518sm
+=====================
+
+Supported chips:
+  * Genesys Logic GL518SM release 0x00
+    Prefix: 'gl518sm'
+    Addresses scanned: I2C 0x2c and 0x2d
+    Datasheet: http://www.genesyslogic.com/pdf
+  * Genesys Logic GL518SM release 0x80
+    Prefix: 'gl518sm'
+    Addresses scanned: I2C 0x2c and 0x2d
+    Datasheet: http://www.genesyslogic.com/pdf
+
+Authors:
+        Frodo Looijaard <frodol@dds.nl>,
+        Kyösti Mälkki <kmalkki@cc.hut.fi>
+        Hong-Gunn Chew <hglinux@gunnet.org>
+        Jean Delvare <khali@linux-fr.org>
+
+Description
+-----------
+
+IMPORTANT:
+
+For the revision 0x00 chip, the in0, in1, and in2  values (+5V, +3V,
+and +12V) CANNOT be read. This is a limitation of the chip, not the driver.
+
+This driver supports the Genesys Logic GL518SM chip. There are at least
+two revision of this chip, which we call revision 0x00 and 0x80. Revision
+0x80 chips support the reading of all voltages and revision 0x00 only
+for VIN3.
+
+The GL518SM implements one temperature sensor, two fan rotation speed
+sensors, and four voltage sensors. It can report alarms through the
+computer speakers.
+
+Temperatures are measured in degrees Celsius. An alarm goes off while the
+temperature is above the over temperature limit, and has not yet dropped
+below the hysteresis limit. The alarm always reflects the current
+situation. Measurements are guaranteed between -10 degrees and +110
+degrees, with a accuracy of +/-3 degrees.
+
+Rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. In
+case when you have selected to turn fan1 off, no fan1 alarm is triggered.
+
+Fan readings can be divided by a programmable divider (1, 2, 4 or 8) to
+give the readings more range or accuracy.  Not all RPM values can
+accurately be represented, so some rounding is done. With a divider
+of 2, the lowest representable value is around 1900 RPM.
+
+Voltage sensors (also known as VIN sensors) report their values in volts.
+An alarm is triggered if the voltage has crossed a programmable minimum or
+maximum limit. Note that minimum in this case always means 'closest to
+zero'; this is important for negative voltage measurements. The VDD input
+measures voltages between 0.000 and 5.865 volt, with a resolution of 0.023
+volt. The other inputs measure voltages between 0.000 and 4.845 volt, with
+a resolution of 0.019 volt. Note that revision 0x00 chips do not support
+reading the current voltage of any input except for VIN3; limit setting and
+alarms work fine, though.
+
+When an alarm is triggered, 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.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once (except for temperature alarms). This means that the
+cause for the alarm may already have disappeared! Note that in the current
+implementation, all hardware registers are read whenever any data is read
+(unless it is less than 1.5 seconds since the last update). This means that
+you can easily miss once-only alarms.
+
+The GL518SM only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values.
diff --git a/Documentation/i2c/chips/it87 b/Documentation/i2c/chips/it87
new file mode 100644
index 0000000..0d01950
--- /dev/null
+++ b/Documentation/i2c/chips/it87
@@ -0,0 +1,96 @@
+Kernel driver it87
+==================
+
+Supported chips:
+  * IT8705F
+    Prefix: 'it87'
+    Addresses scanned: from Super I/O config space, or default ISA 0x290 (8 I/O ports)
+    Datasheet: Publicly available at the ITE website
+               http://www.ite.com.tw/
+  * IT8712F
+    Prefix: 'it8712'
+    Addresses scanned: I2C 0x28 - 0x2f
+                       from Super I/O config space, or default ISA 0x290 (8 I/O ports)
+    Datasheet: Publicly available at the ITE website
+               http://www.ite.com.tw/
+  * SiS950   [clone of IT8705F]
+    Prefix: 'sis950'
+    Addresses scanned: from Super I/O config space, or default ISA 0x290 (8 I/O ports)
+    Datasheet: No longer be available
+
+Author: Christophe Gauthron <chrisg@0-in.com>
+
+
+Module Parameters
+-----------------
+
+* update_vbat: int
+
+  0 if vbat should report power on value, 1 if vbat should be updated after
+  each read. Default is 0. On some boards the battery voltage is provided
+  by either the battery or the onboard power supply. Only the first reading
+  at power on will be the actual battery voltage (which the chip does
+  automatically). On other boards the battery voltage is always fed to
+  the chip so can be read at any time. Excessive reading may decrease
+  battery life but no information is given in the datasheet.
+
+* fix_pwm_polarity int
+
+  Force PWM polarity to active high (DANGEROUS). Some chips are
+  misconfigured by BIOS - PWM values would be inverted. This option tries
+  to fix this. Please contact your BIOS manufacturer and ask him for fix.
+
+Description
+-----------
+
+This driver implements support for the IT8705F, IT8712F and SiS950 chips.
+
+This driver also supports IT8712F, which adds SMBus access, and a VID
+input, used to report the Vcore voltage of the Pentium processor.
+The IT8712F additionally features VID inputs.
+
+These chips are 'Super I/O chips', supporting floppy disks, infrared ports,
+joysticks and other miscellaneous stuff. For hardware monitoring, they
+include an 'environment controller' with 3 temperature sensors, 3 fan
+rotation speed sensors, 8 voltage sensors, and associated alarms.
+
+Temperatures are measured in degrees Celsius. An alarm is triggered once
+when the Overtemperature Shutdown limit is crossed.
+
+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 or 8) to give the
+readings more range or accuracy. Not all RPM values can accurately be
+represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+Voltage sensors (also known as IN sensors) report their values in volts. An
+alarm is triggered if the voltage has crossed a programmable minimum or
+maximum limit. Note that minimum in this case always means 'closest to
+zero'; this is important for negative voltage measurements. All voltage
+inputs can measure voltages between 0 and 4.08 volts, with a resolution of
+0.016 volt. The battery voltage in8 does not have limit registers.
+
+The VID lines (IT8712F only) encode the core voltage value: the voltage
+level your processor should work with. This is hardcoded by the mainboard
+and/or processor itself. It is a value in volts.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may already
+have disappeared! Note that in the current implementation, all hardware
+registers are read whenever any data is read (unless it is less than 1.5
+seconds since the last update). This means that you can easily miss
+once-only alarms.
+
+The IT87xx only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values.
+
+To change sensor N to a thermistor, 'echo 2 > tempN_type' where N is 1, 2,
+or 3. To change sensor N to a thermal diode, 'echo 3 > tempN_type'.
+Give 0 for unused sensor. Any other value is invalid. To configure this at
+startup, consult lm_sensors's /etc/sensors.conf. (2 = thermistor;
+3 = thermal diode)
+
+The fan speed control features are limited to manual PWM mode. Automatic
+"Smart Guardian" mode control handling is not implemented. However
+if you want to go for "manual mode" just write 1 to pwmN_enable.
diff --git a/Documentation/i2c/chips/lm63 b/Documentation/i2c/chips/lm63
new file mode 100644
index 0000000..31660bf
--- /dev/null
+++ b/Documentation/i2c/chips/lm63
@@ -0,0 +1,57 @@
+Kernel driver lm63
+==================
+
+Supported chips:
+  * National Semiconductor LM63
+    Prefix: 'lm63'
+    Addresses scanned: I2C 0x4c
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/pf/LM/LM63.html
+
+Author: Jean Delvare <khali@linux-fr.org>
+
+Thanks go to Tyan and especially Alex Buckingham for setting up a remote
+access to their S4882 test platform for this driver.
+  http://www.tyan.com/
+
+Description
+-----------
+
+The LM63 is a digital temperature sensor with integrated fan monitoring
+and control.
+
+The LM63 is basically an LM86 with fan speed monitoring and control
+capabilities added. It misses some of the LM86 features though:
+ - No low limit for local temperature.
+ - No critical limit for local temperature.
+ - Critical limit for remote temperature can be changed only once. We
+   will consider that the critical limit is read-only.
+
+The datasheet isn't very clear about what the tachometer reading is.
+
+An explanation from National Semiconductor: The two lower bits of the read
+value have to be masked out. The value is still 16 bit in width.
+
+All temperature values are given in degrees Celsius. Resolution is 1.0
+degree for the local temperature, 0.125 degree for the remote temperature.
+
+The fan speed is measured using a tachometer. Contrary to most chips which
+store the value in an 8-bit register and have a selectable clock divider
+to make sure that the result will fit in the register, the LM63 uses 16-bit
+value for measuring the speed of the fan. It can measure fan speeds down to
+83 RPM, at least in theory.
+
+Note that the pin used for fan monitoring is shared with an alert out
+function. Depending on how the board designer wanted to use the chip, fan
+speed monitoring will or will not be possible. The proper chip configuration
+is left to the BIOS, and the driver will blindly trust it.
+
+A PWM output can be used to control the speed of the fan. The LM63 has two
+PWM modes: manual and automatic. Automatic mode is not fully implemented yet
+(you cannot define your custom PWM/temperature curve), and mode change isn't
+supported either.
+
+The lm63 driver will not update its values more frequently than every
+second; reading them more often will do no harm, but will return 'old'
+values.
+
diff --git a/Documentation/i2c/chips/lm75 b/Documentation/i2c/chips/lm75
new file mode 100644
index 0000000..8e6356f
--- /dev/null
+++ b/Documentation/i2c/chips/lm75
@@ -0,0 +1,65 @@
+Kernel driver lm75
+==================
+
+Supported chips:
+  * National Semiconductor LM75
+    Prefix: 'lm75'
+    Addresses scanned: I2C 0x48 - 0x4f
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/
+  * Dallas Semiconductor DS75
+    Prefix: 'lm75'
+    Addresses scanned: I2C 0x48 - 0x4f
+    Datasheet: Publicly available at the Dallas Semiconductor website
+               http://www.maxim-ic.com/
+  * Dallas Semiconductor DS1775
+    Prefix: 'lm75'
+    Addresses scanned: I2C 0x48 - 0x4f
+    Datasheet: Publicly available at the Dallas Semiconductor website
+               http://www.maxim-ic.com/
+  * Maxim MAX6625, MAX6626
+    Prefix: 'lm75'
+    Addresses scanned: I2C 0x48 - 0x4b
+    Datasheet: Publicly available at the Maxim website
+               http://www.maxim-ic.com/
+  * Microchip (TelCom) TCN75
+    Prefix: 'lm75'
+    Addresses scanned: I2C 0x48 - 0x4f
+    Datasheet: Publicly available at the Microchip website
+               http://www.microchip.com/
+
+Author: Frodo Looijaard <frodol@dds.nl>
+
+Description
+-----------
+
+The LM75 implements one temperature sensor. Limits can be set through the
+Overtemperature Shutdown register and Hysteresis register. Each value can be
+set and read to half-degree accuracy.
+An alarm is issued (usually to a connected LM78) when the temperature
+gets higher then the Overtemperature Shutdown value; it stays on until
+the temperature falls below the Hysteresis value.
+All temperatures are in degrees Celsius, and are guaranteed within a
+range of -55 to +125 degrees.
+
+The LM75 only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values.
+
+The LM75 is usually used in combination with LM78-like chips, to measure
+the temperature of the processor(s).
+
+The DS75, DS1775, MAX6625, and MAX6626 are supported as well.
+They are not distinguished from an LM75. While most of these chips
+have three additional bits of accuracy (12 vs. 9 for the LM75),
+the additional bits are not supported. Not only that, but these chips will
+not be detected if not in 9-bit precision mode (use the force parameter if
+needed).
+
+The TCN75 is supported as well, and is not distinguished from an LM75.
+
+The LM75 is essentially an industry standard; there may be other
+LM75 clones not listed here, with or without various enhancements,
+that are supported.
+
+The LM77 is not supported, contrary to what we pretended for a long time.
+Both chips are simply not compatible, value encoding differs.
diff --git a/Documentation/i2c/chips/lm77 b/Documentation/i2c/chips/lm77
new file mode 100644
index 0000000..57c3a46
--- /dev/null
+++ b/Documentation/i2c/chips/lm77
@@ -0,0 +1,22 @@
+Kernel driver lm77
+==================
+
+Supported chips:
+  * National Semiconductor LM77
+    Prefix: 'lm77'
+    Addresses scanned: I2C 0x48 - 0x4b
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/
+
+Author: Andras BALI <drewie@freemail.hu>
+
+Description
+-----------
+
+The LM77 implements one temperature sensor. The temperature
+sensor incorporates a band-gap type temperature sensor,
+10-bit ADC, and a digital comparator with user-programmable upper
+and lower limit values.
+
+Limits can be set through the Overtemperature Shutdown register and
+Hysteresis register.
diff --git a/Documentation/i2c/chips/lm78 b/Documentation/i2c/chips/lm78
new file mode 100644
index 0000000..357086e
--- /dev/null
+++ b/Documentation/i2c/chips/lm78
@@ -0,0 +1,82 @@
+Kernel driver lm78
+==================
+
+Supported chips:
+  * National Semiconductor LM78
+    Prefix: 'lm78'
+    Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/
+  * National Semiconductor LM78-J
+    Prefix: 'lm78-j'
+    Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/
+  * National Semiconductor LM79
+    Prefix: 'lm79'
+    Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/
+
+Author: Frodo Looijaard <frodol@dds.nl>
+
+Description
+-----------
+
+This driver implements support for the National Semiconductor LM78, LM78-J
+and LM79. They are described as 'Microprocessor System Hardware Monitors'.
+
+There is almost no difference between the three supported chips. Functionally,
+the LM78 and LM78-J are exactly identical. The LM79 has one more VID line,
+which is used to report the lower voltages newer Pentium processors use.
+From here on, LM7* means either of these three types.
+
+The LM7* implements one temperature sensor, three fan rotation speed sensors,
+seven voltage sensors, VID lines, alarms, and some miscellaneous stuff.
+
+Temperatures are measured in degrees Celsius. An alarm is triggered once
+when the Overtemperature Shutdown limit is crossed; it is triggered again
+as soon as it drops below the Hysteresis value. A more useful behavior
+can be found by setting the Hysteresis value to +127 degrees Celsius; in
+this case, alarms are issued during all the time when the actual temperature
+is above the Overtemperature Shutdown value. Measurements are guaranteed
+between -55 and +125 degrees, with a resolution of 1 degree.
+
+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 or 8) to give
+the readings more range or accuracy. Not all RPM values can accurately be
+represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+Voltage sensors (also known as IN sensors) report their values in volts.
+An alarm is triggered if the voltage has crossed a programmable minimum
+or maximum limit. Note that minimum in this case always means 'closest to
+zero'; this is important for negative voltage measurements. All voltage
+inputs can measure voltages between 0 and 4.08 volts, with a resolution
+of 0.016 volt.
+
+The VID lines encode the core voltage value: the voltage level your processor
+should work with. This is hardcoded by the mainboard and/or processor itself.
+It is a value in volts. When it is unconnected, you will often find the
+value 3.50 V here.
+
+In addition to the alarms described above, there are a couple of additional
+ones. There is a BTI alarm, which gets triggered when an external chip has
+crossed its limits. Usually, this is connected to all LM75 chips; if at
+least one crosses its limits, this bit gets set. The CHAS alarm triggers
+if your computer case is open. The FIFO alarms should never trigger; it
+indicates an internal error. The SMI_IN alarm indicates some other chip
+has triggered an SMI interrupt. As we do not use SMI interrupts at all,
+this condition usually indicates there is a problem with some other
+device.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may
+already have disappeared! Note that in the current implementation, all
+hardware registers are read whenever any data is read (unless it is less
+than 1.5 seconds since the last update). This means that you can easily
+miss once-only alarms.
+
+The LM7* only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values.
diff --git a/Documentation/i2c/chips/lm80 b/Documentation/i2c/chips/lm80
new file mode 100644
index 0000000..cb5b407
--- /dev/null
+++ b/Documentation/i2c/chips/lm80
@@ -0,0 +1,56 @@
+Kernel driver lm80
+==================
+
+Supported chips:
+  * National Semiconductor LM80
+    Prefix: 'lm80'
+    Addresses scanned: I2C 0x28 - 0x2f
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/
+
+Authors:
+        Frodo Looijaard <frodol@dds.nl>,
+        Philip Edelbrock <phil@netroedge.com>
+
+Description
+-----------
+
+This driver implements support for the National Semiconductor LM80.
+It is described as a 'Serial Interface ACPI-Compatible Microprocessor
+System Hardware Monitor'.
+
+The LM80 implements one temperature sensor, two fan rotation speed sensors,
+seven voltage sensors, alarms, and some miscellaneous stuff.
+
+Temperatures are measured in degrees Celsius. There are two sets of limits
+which operate independently. When the HOT Temperature Limit is crossed,
+this will cause an alarm that will be reasserted until the temperature
+drops below the HOT Hysteresis. The Overtemperature Shutdown (OS) limits
+should work in the same way (but this must be checked; the datasheet
+is unclear about this). Measurements are guaranteed between -55 and
++125 degrees. The current temperature measurement has a resolution of
+0.0625 degrees; the limits have a resolution of 1 degree.
+
+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 or 8) to give
+the readings more range or accuracy. Not all RPM values can accurately be
+represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+Voltage sensors (also known as IN sensors) report their values in volts.
+An alarm is triggered if the voltage has crossed a programmable minimum
+or maximum limit. Note that minimum in this case always means 'closest to
+zero'; this is important for negative voltage measurements. All voltage
+inputs can measure voltages between 0 and 2.55 volts, with a resolution
+of 0.01 volt.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may
+already have disappeared! Note that in the current implementation, all
+hardware registers are read whenever any data is read (unless it is less
+than 2.0 seconds since the last update). This means that you can easily
+miss once-only alarms.
+
+The LM80 only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values.
diff --git a/Documentation/i2c/chips/lm83 b/Documentation/i2c/chips/lm83
new file mode 100644
index 0000000..061d9ed
--- /dev/null
+++ b/Documentation/i2c/chips/lm83
@@ -0,0 +1,76 @@
+Kernel driver lm83
+==================
+
+Supported chips:
+  * National Semiconductor LM83
+    Prefix: 'lm83'
+    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
+
+
+Author: Jean Delvare <khali@linux-fr.org>
+
+Description
+-----------
+
+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.
+
+Using the adm1021 driver for a LM83 should work, but only two temperatures
+will be reported instead of four.
+
+The LM83 is only found on a handful of motherboards. Both a confirmed
+list and an unconfirmed list follow. If you can confirm or infirm the
+fact that any of these motherboards do actually have an LM83, please
+contact us. Note that the LM90 can easily be misdetected as a LM83.
+
+Confirmed motherboards:
+    SBS         P014
+
+Unconfirmed motherboards:
+    Gigabyte    GA-8IK1100
+    Iwill       MPX2
+    Soltek      SL-75DRV5
+
+The driver has been successfully tested by Magnus Forsström, who I'd
+like to thank here. More testers will be of course welcome.
+
+The fact that the LM83 is only scarcely used can be easily explained.
+Most motherboards come with more than just temperature sensors for
+health monitoring. They also have voltage and fan rotation speed
+sensors. This means that temperature-only chips are usually used as
+secondary chips coupled with another chip such as an IT8705F or similar
+chip, which provides more features. Since systems usually need three
+temperature sensors (motherboard, processor, power supply) and primary
+chips provide some temperature sensors, the secondary chip, if needed,
+won't have to handle more than two temperatures. Thus, ADM1021 clones
+are sufficient, and there is no need for a four temperatures sensor
+chip such as the LM83. The only case where using an LM83 would make
+sense is on SMP systems, such as the above-mentioned Iwill MPX2,
+because you want an additional temperature sensor for each additional
+CPU.
+
+On the SBS P014, this is different, since the LM83 is the only hardware
+monitoring chipset. One temperature sensor is used for the motherboard
+(actually measuring the LM83's own temperature), one is used for the
+CPU. The two other sensors must be used to measure the temperature of
+two other points of the motherboard. We suspect these points to be the
+north and south bridges, but this couldn't be confirmed.
+
+All temperature values are given in degrees Celsius. Local temperature
+is given within a range of 0 to +85 degrees. Remote temperatures are
+given within a range of 0 to +125 degrees. Resolution is 1.0 degree,
+accuracy is guaranteed to 3.0 degrees (see the datasheet for more
+details).
+
+Each sensor has its own high limit, but the critical limit is common to
+all four sensors. There is no hysteresis mechanism as found on most
+recent temperature sensors.
+
+The lm83 driver will not update its values more frequently than every
+other second; reading them more often will do no harm, but will return
+'old' values.
diff --git a/Documentation/i2c/chips/lm85 b/Documentation/i2c/chips/lm85
new file mode 100644
index 0000000..9549237
--- /dev/null
+++ b/Documentation/i2c/chips/lm85
@@ -0,0 +1,221 @@
+Kernel driver lm85
+==================
+
+Supported chips:
+  * National Semiconductor LM85 (B and C versions)
+    Prefix: 'lm85'
+    Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+    Datasheet: http://www.national.com/pf/LM/LM85.html
+  * Analog Devices ADM1027
+    Prefix: 'adm1027'
+    Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+    Datasheet: http://www.analog.com/en/prod/0,,766_825_ADM1027,00.html
+  * Analog Devices ADT7463
+    Prefix: 'adt7463'
+    Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+    Datasheet: http://www.analog.com/en/prod/0,,766_825_ADT7463,00.html
+  * SMSC EMC6D100, SMSC EMC6D101
+    Prefix: 'emc6d100'
+    Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+    Datasheet: http://www.smsc.com/main/tools/discontinued/6d100.pdf
+  * SMSC EMC6D102
+    Prefix: 'emc6d102'
+    Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+    Datasheet: http://www.smsc.com/main/catalog/emc6d102.html
+
+Authors:
+        Philip Pokorny <ppokorny@penguincomputing.com>,
+        Frodo Looijaard <frodol@dds.nl>,
+        Richard Barrington <rich_b_nz@clear.net.nz>,
+        Margit Schubert-While <margitsw@t-online.de>,
+        Justin Thiessen <jthiessen@penguincomputing.com>
+
+Description
+-----------
+
+This driver implements support for the National Semiconductor LM85 and
+compatible chips including the Analog Devices ADM1027, ADT7463 and
+SMSC EMC6D10x chips family.
+
+The LM85 uses the 2-wire interface compatible with the SMBUS 2.0
+specification. Using an analog to digital converter it measures three (3)
+temperatures and five (5) voltages. It has four (4) 16-bit counters for
+measuring fan speed. Five (5) digital inputs are provided for sampling the
+VID signals from the processor to the VRM. Lastly, there are three (3) PWM
+outputs that can be used to control fan speed.
+
+The voltage inputs have internal scaling resistors so that the following
+voltage can be measured without external resistors:
+
+  2.5V, 3.3V, 5V, 12V, and CPU core voltage (2.25V)
+
+The temperatures measured are one internal diode, and two remote diodes.
+Remote 1 is generally the CPU temperature. These inputs are designed to
+measure a thermal diode like the one in a Pentium 4 processor in a socket
+423 or socket 478 package. They can also measure temperature using a
+transistor like the 2N3904.
+
+A sophisticated control system for the PWM outputs is designed into the
+LM85 that allows fan speed to be adjusted automatically based on any of the
+three temperature sensors. Each PWM output is individually adjustable and
+programmable. Once configured, the LM85 will adjust the PWM outputs in
+response to the measured temperatures without further host intervention.
+This feature can also be disabled for manual control of the PWM's.
+
+Each of the measured inputs (voltage, temperature, fan speed) has
+corresponding high/low limit values. The LM85 will signal an ALARM if any
+measured value exceeds either limit.
+
+The LM85 samples all inputs continuously. The lm85 driver will not read
+the registers more often than once a second. Further, configuration data is
+only read once each 5 minutes. There is twice as much config data as
+measurements, so this would seem to be a worthwhile optimization.
+
+Special Features
+----------------
+
+The LM85 has four fan speed monitoring modes. The ADM1027 has only two.
+Both have special circuitry to compensate for PWM interactions with the
+TACH signal from the fans. The ADM1027 can be configured to measure the
+speed of a two wire fan, but the input conditioning circuitry is different
+for 3-wire and 2-wire mode. For this reason, the 2-wire fan modes are not
+exposed to user control. The BIOS should initialize them to the correct
+mode. If you've designed your own ADM1027, you'll have to modify the
+init_client function and add an insmod parameter to set this up.
+
+To smooth the response of fans to changes in temperature, the LM85 has an
+optional filter for smoothing temperatures. The ADM1027 has the same
+config option but uses it to rate limit the changes to fan speed instead.
+
+The ADM1027 and ADT7463 have a 10-bit ADC and can therefore measure
+temperatures with 0.25 degC resolution. They also provide an offset to the
+temperature readings that is automatically applied during measurement.
+This offset can be used to zero out any errors due to traces and placement.
+The documentation says that the offset is in 0.25 degC steps, but in
+initial testing of the ADM1027 it was 1.00 degC steps. Analog Devices has
+confirmed this "bug". The ADT7463 is reported to work as described in the
+documentation. The current lm85 driver does not show the offset register.
+
+The ADT7463 has a THERM asserted counter. This counter has a 22.76ms
+resolution and a range of 5.8 seconds. The driver implements a 32-bit
+accumulator of the counter value to extend the range to over a year. The
+counter will stay at it's max value until read.
+
+See the vendor datasheets for more information. There is application note
+from National (AN-1260) with some additional information about the LM85.
+The Analog Devices datasheet is very detailed and describes a procedure for
+determining an optimal configuration for the automatic PWM control.
+
+The SMSC EMC6D100 & EMC6D101 monitor external voltages, temperatures, and
+fan speeds. They use this monitoring capability to alert the system to out
+of limit conditions and can automatically control the speeds of multiple
+fans in a PC or embedded system. The EMC6D101, available in a 24-pin SSOP
+package, and the EMC6D100, available in a 28-pin SSOP package, are designed
+to be register compatible. The EMC6D100 offers all the features of the
+EMC6D101 plus additional voltage monitoring and system control features.
+Unfortunately it is not possible to distinguish between the package
+versions on register level so these additional voltage inputs may read
+zero. The EMC6D102 features addtional ADC bits thus extending precision
+of voltage and temperature channels.
+
+
+Hardware Configurations
+-----------------------
+
+The LM85 can be jumpered for 3 different SMBus addresses. There are
+no other hardware configuration options for the LM85.
+
+The lm85 driver detects both LM85B and LM85C revisions of the chip. See the
+datasheet for a complete description of the differences. Other than
+identifying the chip, the driver behaves no differently with regard to
+these two chips. The LM85B is recommended for new designs.
+
+The ADM1027 and ADT7463 chips have an optional SMBALERT output that can be
+used to signal the chipset in case a limit is exceeded or the temperature
+sensors fail. Individual sensor interrupts can be masked so they won't
+trigger SMBALERT. The SMBALERT output if configured replaces one of the other
+functions (PWM2 or IN0). This functionality is not implemented in current
+driver.
+
+The ADT7463 also has an optional THERM output/input which can be connected
+to the processor PROC_HOT output. If available, the autofan control
+dynamic Tmin feature can be enabled to keep the system temperature within
+spec (just?!) with the least possible fan noise.
+
+Configuration Notes
+-------------------
+
+Besides standard interfaces driver adds following:
+
+* Temperatures and Zones
+
+Each temperature sensor is associated with a Zone. There are three
+sensors and therefore three zones (# 1, 2 and 3). Each zone has the following
+temperature configuration points:
+
+* temp#_auto_temp_off - temperature below which fans should be off or spinning very low.
+* temp#_auto_temp_min - temperature over which fans start to spin.
+* temp#_auto_temp_max - temperature when fans spin at full speed.
+* temp#_auto_temp_crit - temperature when all fans will run full speed.
+
+* PWM Control
+
+There are three PWM outputs. The LM85 datasheet suggests that the
+pwm3 output control both fan3 and fan4. Each PWM can be individually
+configured and assigned to a zone for it's control value. Each PWM can be
+configured individually according to the following options.
+
+* pwm#_auto_pwm_min - this specifies the PWM value for temp#_auto_temp_off
+                      temperature. (PWM value from 0 to 255)
+
+* pwm#_auto_pwm_freq - select base frequency of PWM output. You can select
+                       in range of 10.0 to 94.0 Hz in .1 Hz units.
+		       (Values 100 to 940).
+
+The pwm#_auto_pwm_freq can be set to one of the following 8 values. Setting the
+frequency to a value not on this list, will result in the next higher frequency
+being selected. The actual device frequency may vary slightly from this
+specification as designed by the manufacturer. Consult the datasheet for more
+details. (PWM Frequency values:  100, 150, 230, 300, 380, 470, 620, 940)
+
+* pwm#_auto_pwm_minctl - this flags selects for temp#_auto_temp_off temperature
+                         the bahaviour of fans. Write 1 to let fans spinning at
+			 pwm#_auto_pwm_min or write 0 to let them off.
+
+NOTE: It has been reported that there is a bug in the LM85 that causes the flag
+to be associated with the zones not the PWMs. This contradicts all the
+published documentation. Setting pwm#_min_ctl in this case actually affects all
+PWMs controlled by zone '#'.
+
+* PWM Controlling Zone selection
+
+* pwm#_auto_channels - controls zone that is associated with PWM
+
+Configuration choices:
+
+   Value     Meaning
+  ------  ------------------------------------------------
+      1    Controlled by Zone 1
+      2    Controlled by Zone 2
+      3    Controlled by Zone 3
+     23    Controlled by higher temp of Zone 2 or 3
+    123    Controlled by highest temp of Zone 1, 2 or 3
+      0    PWM always 0%  (off)
+     -1    PWM always 100%  (full on)
+     -2    Manual control (write to 'pwm#' to set)
+
+The National LM85's have two vendor specific configuration
+features. Tach. mode and Spinup Control. For more details on these,
+see the LM85 datasheet or Application Note AN-1260.
+
+The Analog Devices ADM1027 has several vendor specific enhancements.
+The number of pulses-per-rev of the fans can be set, Tach monitoring
+can be optimized for PWM operation, and an offset can be applied to
+the temperatures to compensate for systemic errors in the
+measurements.
+
+In addition to the ADM1027 features, the ADT7463 also has Tmin control
+and THERM asserted counts. Automatic Tmin control acts to adjust the
+Tmin value to maintain the measured temperature sensor at a specified
+temperature. There isn't much documentation on this feature in the
+ADT7463 data sheet. This is not supported by current driver.
diff --git a/Documentation/i2c/chips/lm87 b/Documentation/i2c/chips/lm87
new file mode 100644
index 0000000..c952c57
--- /dev/null
+++ b/Documentation/i2c/chips/lm87
@@ -0,0 +1,73 @@
+Kernel driver lm87
+==================
+
+Supported chips:
+  * National Semiconductor LM87
+    Prefix: 'lm87'
+    Addresses scanned: I2C 0x2c - 0x2f
+    Datasheet: http://www.national.com/pf/LM/LM87.html
+
+Authors:
+        Frodo Looijaard <frodol@dds.nl>,
+        Philip Edelbrock <phil@netroedge.com>,
+        Mark Studebaker <mdsxyz123@yahoo.com>,
+        Stephen Rousset <stephen.rousset@rocketlogix.com>,
+        Dan Eaton <dan.eaton@rocketlogix.com>,
+        Jean Delvare <khali@linux-fr.org>,
+        Original 2.6 port Jeff Oliver
+
+Description
+-----------
+
+This driver implements support for the National Semiconductor LM87.
+
+The LM87 implements up to three temperature sensors, up to two fan
+rotation speed sensors, up to seven voltage sensors, alarms, and some
+miscellaneous stuff.
+
+Temperatures are measured in degrees Celsius. Each input has a high
+and low alarm settings. A high limit produces an alarm when the value
+goes above it, and an alarm is also produced when the value goes below
+the low limit.
+
+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 or 8) to give
+the readings more range or accuracy. Not all RPM values can accurately be
+represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+Voltage sensors (also known as IN sensors) report their values in
+volts. An alarm is triggered if the voltage has crossed a programmable
+minimum or maximum limit. Note that minimum in this case always means
+'closest to zero'; this is important for negative voltage measurements.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may
+already have disappeared! Note that in the current implementation, all
+hardware registers are read whenever any data is read (unless it is less
+than 1.0 seconds since the last update). This means that you can easily
+miss once-only alarms.
+
+The lm87 driver only updates its values each 1.0 seconds; reading it more
+often will do no harm, but will return 'old' values.
+
+
+Hardware Configurations
+-----------------------
+
+The LM87 has four pins which can serve one of two possible functions,
+depending on the hardware configuration.
+
+Some functions share pins, so not all functions are available at the same
+time. Which are depends on the hardware setup. This driver assumes that
+the BIOS configured the chip correctly. In that respect, it differs from
+the original driver (from lm_sensors for Linux 2.4), which would force the
+LM87 to an arbitrary, compile-time chosen mode, regardless of the actual
+chipset wiring.
+
+For reference, here is the list of exclusive functions:
+ - in0+in5 (default) or temp3
+ - fan1 (default) or in6
+ - fan2 (default) or in7
+ - VID lines (default) or IRQ lines (not handled by this driver)
diff --git a/Documentation/i2c/chips/lm90 b/Documentation/i2c/chips/lm90
new file mode 100644
index 0000000..2c4cf39
--- /dev/null
+++ b/Documentation/i2c/chips/lm90
@@ -0,0 +1,121 @@
+Kernel driver lm90
+==================
+
+Supported chips:
+  * National Semiconductor LM90
+    Prefix: 'lm90'
+    Addresses scanned: I2C 0x4c
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/pf/LM/LM90.html
+  * National Semiconductor LM89
+    Prefix: 'lm99'
+    Addresses scanned: I2C 0x4c and 0x4d
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/pf/LM/LM89.html
+  * National Semiconductor LM99
+    Prefix: 'lm99'
+    Addresses scanned: I2C 0x4c and 0x4d
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/pf/LM/LM99.html
+  * National Semiconductor LM86
+    Prefix: 'lm86'
+    Addresses scanned: I2C 0x4c
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/pf/LM/LM86.html
+  * Analog Devices ADM1032
+    Prefix: 'adm1032'
+    Addresses scanned: I2C 0x4c
+    Datasheet: Publicly available at the Analog Devices website
+               http://products.analog.com/products/info.asp?product=ADM1032
+  * Analog Devices ADT7461
+    Prefix: 'adt7461'
+    Addresses scanned: I2C 0x4c
+    Datasheet: Publicly available at the Analog Devices website
+               http://products.analog.com/products/info.asp?product=ADT7461
+    Note: Only if in ADM1032 compatibility mode
+  * Maxim MAX6657
+    Prefix: 'max6657'
+    Addresses scanned: I2C 0x4c
+    Datasheet: Publicly available at the Maxim website
+               http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2578
+  * Maxim MAX6658
+    Prefix: 'max6657'
+    Addresses scanned: I2C 0x4c
+    Datasheet: Publicly available at the Maxim website
+               http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2578
+  * Maxim MAX6659
+    Prefix: 'max6657'
+    Addresses scanned: I2C 0x4c, 0x4d (unsupported 0x4e)
+    Datasheet: Publicly available at the Maxim website
+               http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2578
+
+
+Author: Jean Delvare <khali@linux-fr.org>
+
+
+Description
+-----------
+
+The LM90 is a digital temperature sensor. It senses its own temperature as
+well as the temperature of up to one external diode. It is compatible
+with many other devices such as the LM86, the LM89, the LM99, the ADM1032,
+the MAX6657, MAX6658 and the MAX6659 all of which are supported by this driver.
+Note that there is no easy way to differentiate between the last three
+variants. The extra address and features of the MAX6659 are not supported by
+this driver. Additionally, the ADT7461 is supported if found in ADM1032
+compatibility mode.
+
+The specificity of this family of chipsets over the ADM1021/LM84
+family is that it features critical limits with hysteresis, and an
+increased resolution of the remote temperature measurement.
+
+The different chipsets of the family are not strictly identical, although
+very similar. This driver doesn't handle any specific feature for now,
+but could if there ever was a need for it. For reference, here comes a
+non-exhaustive list of specific features:
+
+LM90:
+  * Filter and alert configuration register at 0xBF.
+  * ALERT is triggered by temperatures over critical limits.
+
+LM86 and LM89:
+  * Same as LM90
+  * Better external channel accuracy
+
+LM99:
+  * Same as LM89
+  * External temperature shifted by 16 degrees down
+
+ADM1032:
+  * Consecutive alert register at 0x22.
+  * Conversion averaging.
+  * Up to 64 conversions/s.
+  * ALERT is triggered by open remote sensor.
+
+ADT7461
+  * Extended temperature range (breaks compatibility)
+  * Lower resolution for remote temperature
+
+MAX6657 and MAX6658:
+  * Remote sensor type selection
+
+MAX6659
+  * Selectable address
+  * Second critical temperature limit
+  * Remote sensor type selection
+
+All temperature values are given in degrees Celsius. Resolution
+is 1.0 degree for the local temperature, 0.125 degree for the remote
+temperature.
+
+Each sensor has its own high and low limits, plus a critical limit.
+Additionally, there is a relative hysteresis value common to both critical
+values. To make life easier to user-space applications, two absolute values
+are exported, one for each channel, but these values are of course linked.
+Only the local hysteresis can be set from user-space, and the same delta
+applies to the remote hysteresis.
+
+The lm90 driver will not update its values more frequently than every
+other second; reading them more often will do no harm, but will return
+'old' values.
+
diff --git a/Documentation/i2c/chips/lm92 b/Documentation/i2c/chips/lm92
new file mode 100644
index 0000000..7705bfa
--- /dev/null
+++ b/Documentation/i2c/chips/lm92
@@ -0,0 +1,37 @@
+Kernel driver lm92
+==================
+
+Supported chips:
+  * National Semiconductor LM92
+    Prefix: 'lm92'
+    Addresses scanned: I2C 0x48 - 0x4b
+    Datasheet: http://www.national.com/pf/LM/LM92.html
+  * National Semiconductor LM76
+    Prefix: 'lm92'
+    Addresses scanned: none, force parameter needed
+    Datasheet: http://www.national.com/pf/LM/LM76.html
+  * Maxim MAX6633/MAX6634/MAX6635
+    Prefix: 'lm92'
+    Addresses scanned: I2C 0x48 - 0x4b
+    MAX6633 with address in 0x40 - 0x47, 0x4c - 0x4f needs force parameter
+    and MAX6634 with address in 0x4c - 0x4f needs force parameter
+    Datasheet: http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3074
+
+Authors:
+        Abraham van der Merwe <abraham@2d3d.co.za>
+        Jean Delvare <khali@linux-fr.org>
+
+
+Description
+-----------
+
+This driver implements support for the National Semiconductor LM92
+temperature sensor.
+
+Each LM92 temperature sensor supports a single temperature sensor. There are
+alarms for high, low, and critical thresholds. There's also an hysteresis to
+control the thresholds for resetting alarms.
+
+Support was added later for the LM76 and Maxim MAX6633/MAX6634/MAX6635,
+which are mostly compatible. They have not all been tested, so you
+may need to use the force parameter.
diff --git a/Documentation/i2c/chips/max1619 b/Documentation/i2c/chips/max1619
new file mode 100644
index 0000000..d6f8d9c
--- /dev/null
+++ b/Documentation/i2c/chips/max1619
@@ -0,0 +1,29 @@
+Kernel driver max1619
+=====================
+
+Supported chips:
+  * Maxim MAX1619
+    Prefix: 'max1619'
+    Addresses scanned: I2C 0x18-0x1a, 0x29-0x2b, 0x4c-0x4e
+    Datasheet: Publicly available at the Maxim website
+               http://pdfserv.maxim-ic.com/en/ds/MAX1619.pdf
+
+Authors:
+        Alexey Fisher <fishor@mail.ru>,
+        Jean Delvare <khali@linux-fr.org>
+
+Description
+-----------
+
+The MAX1619 is a digital temperature sensor. It senses its own temperature as
+well as the temperature of up to one external diode.
+
+All temperature values are given in degrees Celsius. Resolution
+is 1.0 degree for the local temperature and for the remote temperature.
+
+Only the external sensor has high and low limits.
+
+The max1619 driver will not update its values more frequently than every
+other second; reading them more often will do no harm, but will return
+'old' values.
+
diff --git a/Documentation/i2c/chips/max6875 b/Documentation/i2c/chips/max6875
new file mode 100644
index 0000000..b4fb49b
--- /dev/null
+++ b/Documentation/i2c/chips/max6875
@@ -0,0 +1,54 @@
+Kernel driver max6875
+=====================
+
+Supported chips:
+  * Maxim max6874, max6875
+    Prefixes: 'max6875'
+    Addresses scanned: 0x50, 0x52
+    Datasheets:
+        http://pdfserv.maxim-ic.com/en/ds/MAX6874-MAX6875.pdf
+
+Author: Ben Gardner <bgardner@wabtec.com>
+
+
+Module Parameters
+-----------------
+
+* allow_write int
+  Set to non-zero to enable write permission:
+  *0: Read only
+   1: Read and write
+
+
+Description
+-----------
+
+The MAXIM max6875 is a EEPROM-programmable power-supply sequencer/supervisor.
+It provides timed outputs that can be used as a watchdog, if properly wired.
+It also provides 512 bytes of user EEPROM.
+
+At reset, the max6875 reads the configuration eeprom into its configuration
+registers.  The chip then begins to operate according to the values in the
+registers.
+
+See the datasheet for details on how to program the EEPROM.
+
+
+Sysfs entries
+-------------
+
+eeprom_user   - 512 bytes of user-defined EEPROM space. Only writable if
+                allow_write was set and register 0x43 is 0.
+
+eeprom_config - 70 bytes of config EEPROM. Note that changes will not get
+                loaded into register space until a power cycle or device reset.
+
+reg_config    - 70 bytes of register space. Any changes take affect immediately.
+
+
+General Remarks
+---------------
+
+A typical application will require that the EEPROMs be programmed once and
+never altered afterwards.
+
diff --git a/Documentation/i2c/chips/pc87360 b/Documentation/i2c/chips/pc87360
new file mode 100644
index 0000000..89a8fcf
--- /dev/null
+++ b/Documentation/i2c/chips/pc87360
@@ -0,0 +1,189 @@
+Kernel driver pc87360
+=====================
+
+Supported chips:
+  * National Semiconductor PC87360, PC87363, PC87364, PC87365 and PC87366
+    Prefixes: 'pc87360', 'pc87363', 'pc87364', 'pc87365', 'pc87366'
+    Addresses scanned: none, address read from Super I/O config space
+    Datasheets:
+        http://www.national.com/pf/PC/PC87360.html
+        http://www.national.com/pf/PC/PC87363.html
+        http://www.national.com/pf/PC/PC87364.html
+        http://www.national.com/pf/PC/PC87365.html
+        http://www.national.com/pf/PC/PC87366.html
+
+Authors: Jean Delvare <khali@linux-fr.org>
+
+Thanks to Sandeep Mehta, Tonko de Rooy and Daniel Ceregatti for testing.
+Thanks to Rudolf Marek for helping me investigate conversion issues.
+
+
+Module Parameters
+-----------------
+
+* init int
+  Chip initialization level:
+   0: None
+  *1: Forcibly enable internal voltage and temperature channels, except in9
+   2: Forcibly enable all voltage and temperature channels, except in9
+   3: Forcibly enable all voltage and temperature channels, including in9
+
+Note that this parameter has no effect for the PC87360, PC87363 and PC87364
+chips.
+
+Also note that for the PC87366, initialization levels 2 and 3 don't enable
+all temperature channels, because some of them share pins with each other,
+so they can't be used at the same time.
+
+
+Description
+-----------
+
+The National Semiconductor PC87360 Super I/O chip contains monitoring and
+PWM control circuitry for two fans. The PC87363 chip is similar, and the
+PC87364 chip has monitoring and PWM control for a third fan.
+
+The National Semiconductor PC87365 and PC87366 Super I/O chips are complete
+hardware monitoring chipsets, not only controlling and monitoring three fans,
+but also monitoring eleven voltage inputs and two (PC87365) or up to four
+(PC87366) temperatures.
+
+  Chip        #vin    #fan    #pwm    #temp   devid
+
+  PC87360     -       2       2       -       0xE1
+  PC87363     -       2       2       -       0xE8
+  PC87364     -       3       3       -       0xE4
+  PC87365     11      3       3       2       0xE5
+  PC87366     11      3       3       3-4     0xE9
+
+The driver assumes that no more than one chip is present, and one of the
+standard Super I/O addresses is used (0x2E/0x2F or 0x4E/0x4F)
+
+Fan Monitoring
+--------------
+
+Fan rotation speeds are reported in RPM (revolutions per minute). An alarm
+is triggered if the rotation speed has dropped below a programmable limit.
+A different alarm is triggered if the fan speed is too low to be measured.
+
+Fan readings are affected by a programmable clock divider, giving the
+readings more range or accuracy. Usually, users have to learn how it works,
+but this driver implements dynamic clock divider selection, so you don't
+have to care no more.
+
+For reference, here are a few values about clock dividers:
+
+                slowest         accuracy        highest
+                measurable      around 3000     accurate
+    divider     speed (RPM)     RPM (RPM)       speed (RPM)
+         1        1882              18           6928
+         2         941              37           4898
+         4         470              74           3464
+         8         235             150           2449
+
+For the curious, here is how the values above were computed:
+ * slowest measurable speed: clock/(255*divider)
+ * accuracy around 3000 RPM: 3000^2/clock
+ * highest accurate speed: sqrt(clock*100)
+The clock speed for the PC87360 family is 480 kHz. I arbitrarily chose 100
+RPM as the lowest acceptable accuracy.
+
+As mentioned above, you don't have to care about this no more.
+
+Note that not all RPM values can be represented, even when the best clock
+divider is selected. This is not only true for the measured speeds, but
+also for the programmable low limits, so don't be surprised if you try to
+set, say, fan1_min to 2900 and it finally reads 2909.
+
+
+Fan Control
+-----------
+
+PWM (pulse width modulation) values range from 0 to 255, with 0 meaning
+that the fan is stopped, and 255 meaning that the fan goes at full speed.
+
+Be extremely careful when changing PWM values. Low PWM values, even
+non-zero, can stop the fan, which may cause irreversible damage to your
+hardware if temperature increases too much. When changing PWM values, go
+step by step and keep an eye on temperatures.
+
+One user reported problems with PWM. Changing PWM values would break fan
+speed readings. No explanation nor fix could be found.
+
+
+Temperature Monitoring
+----------------------
+
+Temperatures are reported in degrees Celsius. Each temperature measured has
+associated low, high and overtemperature limits, each of which triggers an
+alarm when crossed.
+
+The first two temperature channels are external. The third one (PC87366
+only) is internal.
+
+The PC87366 has three additional temperature channels, based on
+thermistors (as opposed to thermal diodes for the first three temperature
+channels). For technical reasons, these channels are held by the VLM
+(voltage level monitor) logical device, not the TMS (temperature
+measurement) one. As a consequence, these temperatures are exported as
+voltages, and converted into temperatures in user-space.
+
+Note that these three additional channels share their pins with the
+external thermal diode channels, so you (physically) can't use them all at
+the same time. Although it should be possible to mix the two sensor types,
+the documents from National Semiconductor suggest that motherboard
+manufacturers should choose one type and stick to it. So you will more
+likely have either channels 1 to 3 (thermal diodes) or 3 to 6 (internal
+thermal diode, and thermistors).
+
+
+Voltage Monitoring
+------------------
+
+Voltages are reported relatively to a reference voltage, either internal or
+external. Some of them (in7:Vsb, in8:Vdd and in10:AVdd) are divided by two
+internally, you will have to compensate in sensors.conf. Others (in0 to in6)
+are likely to be divided externally. The meaning of each of these inputs as
+well as the values of the resistors used for division is left to the
+motherboard manufacturers, so you will have to document yourself and edit
+sensors.conf accordingly. National Semiconductor has a document with
+recommended resistor values for some voltages, but this still leaves much
+room for per motherboard specificities, unfortunately. Even worse,
+motherboard manufacturers don't seem to care about National Semiconductor's
+recommendations.
+
+Each voltage measured has associated low and high limits, each of which
+triggers an alarm when crossed.
+
+When available, VID inputs are used to provide the nominal CPU Core voltage.
+The driver will default to VRM 9.0, but this can be changed from user-space.
+The chipsets can handle two sets of VID inputs (on dual-CPU systems), but
+the driver will only export one for now. This may change later if there is
+a need.
+
+
+General Remarks
+---------------
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may already
+have disappeared! Note that all hardware registers are read whenever any
+data is read (unless it is less than 2 seconds since the last update, in
+which case cached values are returned instead). As a consequence, when
+a once-only alarm triggers, it may take 2 seconds for it to show, and 2
+more seconds for it to disappear.
+
+Monitoring of in9 isn't enabled at lower init levels (<3) because that
+channel measures the battery voltage (Vbat). It is a known fact that
+repeatedly sampling the battery voltage reduces its lifetime. National
+Semiconductor smartly designed their chipset so that in9 is sampled only
+once every 1024 sampling cycles (that is every 34 minutes at the default
+sampling rate), so the effect is attenuated, but still present.
+
+
+Limitations
+-----------
+
+The datasheets suggests that some values (fan mins, fan dividers)
+shouldn't be changed once the monitoring has started, but we ignore that
+recommendation. We'll reconsider if it actually causes trouble.
diff --git a/Documentation/i2c/chips/pca9539 b/Documentation/i2c/chips/pca9539
new file mode 100644
index 0000000..c4fce6a
--- /dev/null
+++ b/Documentation/i2c/chips/pca9539
@@ -0,0 +1,47 @@
+Kernel driver pca9539
+=====================
+
+Supported chips:
+  * Philips PCA9539
+    Prefix: 'pca9539'
+    Addresses scanned: 0x74 - 0x77
+    Datasheet:
+        http://www.semiconductors.philips.com/acrobat/datasheets/PCA9539_2.pdf
+
+Author: Ben Gardner <bgardner@wabtec.com>
+
+
+Description
+-----------
+
+The Philips PCA9539 is a 16 bit low power I/O device.
+All 16 lines can be individually configured as an input or output.
+The input sense can also be inverted.
+The 16 lines are split between two bytes.
+
+
+Sysfs entries
+-------------
+
+Each is a byte that maps to the 8 I/O bits.
+A '0' suffix is for bits 0-7, while '1' is for bits 8-15.
+
+input[01]     - read the current value
+output[01]    - sets the output value
+direction[01] - direction of each bit: 1=input, 0=output
+invert[01]    - toggle the input bit sense
+
+input reads the actual state of the line and is always available.
+The direction defaults to input for all channels.
+
+
+General Remarks
+---------------
+
+Note that each output, direction, and invert entry controls 8 lines.
+You should use the read, modify, write sequence.
+For example. to set output bit 0 of 1.
+  val=$(cat output0)
+  val=$(( $val | 1 ))
+  echo $val > output0
+
diff --git a/Documentation/i2c/chips/pcf8574 b/Documentation/i2c/chips/pcf8574
new file mode 100644
index 0000000..2752c8c
--- /dev/null
+++ b/Documentation/i2c/chips/pcf8574
@@ -0,0 +1,69 @@
+Kernel driver pcf8574
+=====================
+
+Supported chips:
+  * Philips PCF8574
+    Prefix: 'pcf8574'
+    Addresses scanned: I2C 0x20 - 0x27
+    Datasheet: Publicly available at the Philips Semiconductors website
+               http://www.semiconductors.philips.com/pip/PCF8574P.html
+
+ * Philips PCF8574A
+    Prefix: 'pcf8574a'
+    Addresses scanned: I2C 0x38 - 0x3f
+    Datasheet: Publicly available at the Philips Semiconductors website
+               http://www.semiconductors.philips.com/pip/PCF8574P.html
+
+Authors:
+        Frodo Looijaard <frodol@dds.nl>,
+        Philip Edelbrock <phil@netroedge.com>,
+        Dan Eaton <dan.eaton@rocketlogix.com>,
+        Aurelien Jarno <aurelien@aurel32.net>,
+        Jean Delvare <khali@linux-fr.org>,
+
+
+Description
+-----------
+The PCF8574(A) is an 8-bit I/O expander for the I2C bus produced by Philips
+Semiconductors. It is designed to provide a byte I2C interface to up to 16
+separate devices (8 x PCF8574 and 8 x PCF8574A).
+
+This device consists of a quasi-bidirectional port. Each of the eight I/Os
+can be independently used as an input or output. To setup an I/O as an
+input, you have to write a 1 to the corresponding output.
+
+For more informations see the datasheet.
+
+
+Accessing PCF8574(A) via /sys interface
+-------------------------------------
+
+! Be careful !
+The PCF8574(A) is plainly impossible to detect ! Stupid chip.
+So every chip with address in the interval [20..27] and [38..3f] are
+detected as PCF8574(A). If you have other chips in this address
+range, the workaround is to load this module after the one
+for your others chips.
+
+On detection (i.e. insmod, modprobe et al.), directories are being
+created for each detected PCF8574(A):
+
+/sys/bus/i2c/devices/<0>-<1>/
+where <0> is the bus the chip was detected on (e. g. i2c-0)
+and <1> the chip address ([20..27] or [38..3f]):
+
+(example: /sys/bus/i2c/devices/1-0020/)
+
+Inside these directories, there are two files each:
+read and write (and one file with chip name).
+
+The read file is read-only. Reading gives you the current I/O input
+if the corresponding output is set as 1, otherwise the current output
+value, that is to say 0.
+
+The write file is read/write. Writing a value outputs it on the I/O
+port. Reading returns the last written value.
+
+On module initialization the chip is configured as eight inputs (all
+outputs to 1), so you can connect any circuit to the PCF8574(A) without
+being afraid of short-circuit.
diff --git a/Documentation/i2c/chips/pcf8591 b/Documentation/i2c/chips/pcf8591
new file mode 100644
index 0000000..5628fcf
--- /dev/null
+++ b/Documentation/i2c/chips/pcf8591
@@ -0,0 +1,90 @@
+Kernel driver pcf8591
+=====================
+
+Supported chips:
+  * Philips PCF8591
+    Prefix: 'pcf8591'
+    Addresses scanned: I2C 0x48 - 0x4f
+    Datasheet: Publicly available at the Philips Semiconductor website
+               http://www.semiconductors.philips.com/pip/PCF8591P.html
+
+Authors:
+        Aurelien Jarno <aurelien@aurel32.net>
+        valuable contributions by Jan M. Sendler <sendler@sendler.de>,
+        Jean Delvare <khali@linux-fr.org>
+
+
+Description
+-----------
+The PCF8591 is an 8-bit A/D and D/A converter (4 analog inputs and one
+analog output) for the I2C bus produced by Philips Semiconductors. It
+is designed to provide a byte I2C interface to up to 4 separate devices.
+
+The PCF8591 has 4 analog inputs programmable as single-ended or
+differential inputs :
+- mode 0 : four single ended inputs
+        Pins AIN0 to AIN3 are single ended inputs for channels 0 to 3
+
+- mode 1 : three differential inputs
+        Pins AIN3 is the common negative differential input
+        Pins AIN0 to AIN2 are positive differential inputs for channels 0 to 2
+
+- mode 2 : single ended and differential mixed
+        Pins AIN0 and AIN1 are single ended inputs for channels 0 and 1
+        Pins AIN2 is the positive differential input for channel 3
+        Pins AIN3 is the negative differential input for channel 3
+
+- mode 3 : two differential inputs
+        Pins AIN0 is the positive differential input for channel 0
+        Pins AIN1 is the negative differential input for channel 0
+        Pins AIN2 is the positive differential input for channel 1
+        Pins AIN3 is the negative differential input for channel 1
+
+See the datasheet for details.
+
+Module parameters
+-----------------
+
+* input_mode int
+
+    Analog input mode:
+         0 = four single ended inputs
+         1 = three differential inputs
+         2 = single ended and differential mixed
+         3 = two differential inputs
+
+
+Accessing PCF8591 via /sys interface
+-------------------------------------
+
+! Be careful !
+The PCF8591 is plainly impossible to detect ! Stupid chip.
+So every chip with address in the interval [48..4f] is
+detected as PCF8591. If you have other chips in this address
+range, the workaround is to load this module after the one
+for your others chips.
+
+On detection (i.e. insmod, modprobe et al.), directories are being
+created for each detected PCF8591:
+
+/sys/bus/devices/<0>-<1>/
+where <0> is the bus the chip was detected on (e. g. i2c-0)
+and <1> the chip address ([48..4f])
+
+Inside these directories, there are such files:
+in0, in1, in2, in3, out0_enable, out0_output, name
+
+Name contains chip name.
+
+The in0, in1, in2 and in3 files are RO. Reading gives the value of the
+corresponding channel. Depending on the current analog inputs configuration,
+files in2 and/or in3 do not exist. Values range are from 0 to 255 for single
+ended inputs and -128 to +127 for differential inputs (8-bit ADC).
+
+The out0_enable file is RW. Reading gives "1" for analog output enabled and
+"0" for analog output disabled. Writing accepts "0" and "1" accordingly.
+
+The out0_output file is RW. Writing a number between 0 and 255 (8-bit DAC), send
+the value to the digital-to-analog converter. Note that a voltage will
+only appears on AOUT pin if aout0_enable equals 1. Reading returns the last
+value written.
diff --git a/Documentation/i2c/chips/sis5595 b/Documentation/i2c/chips/sis5595
new file mode 100644
index 0000000..b7ae36b
--- /dev/null
+++ b/Documentation/i2c/chips/sis5595
@@ -0,0 +1,106 @@
+Kernel driver sis5595
+=====================
+
+Supported chips:
+  * Silicon Integrated Systems Corp. SiS5595 Southbridge Hardware Monitor
+    Prefix: 'sis5595'
+    Addresses scanned: ISA in PCI-space encoded address
+    Datasheet: Publicly available at the Silicon Integrated Systems Corp. site.
+
+Authors:
+        Kyösti Mälkki <kmalkki@cc.hut.fi>,
+        Mark D. Studebaker <mdsxyz123@yahoo.com>,
+        Aurelien Jarno <aurelien@aurel32.net> 2.6 port
+
+   SiS southbridge has a LM78-like chip integrated on the same IC.
+   This driver is a customized copy of lm78.c
+
+   Supports following revisions:
+       Version         PCI ID          PCI Revision
+       1               1039/0008       AF or less
+       2               1039/0008       B0 or greater
+
+   Note: these chips contain a 0008 device which is incompatible with the
+        5595. We recognize these by the presence of the listed
+        "blacklist" PCI ID and refuse to load.
+
+   NOT SUPPORTED       PCI ID          BLACKLIST PCI ID
+        540            0008            0540
+        550            0008            0550
+       5513            0008            5511
+       5581            0008            5597
+       5582            0008            5597
+       5597            0008            5597
+        630            0008            0630
+        645            0008            0645
+        730            0008            0730
+        735            0008            0735
+
+
+Module Parameters
+-----------------
+force_addr=0xaddr	Set the I/O base address. Useful for boards
+			that don't set the address in the BIOS. Does not do a
+			PCI force; the device must still be present in lspci.
+			Don't use this unless the driver complains that the
+			base address is not set.
+			Example: 'modprobe sis5595 force_addr=0x290'
+
+
+Description
+-----------
+
+The SiS5595 southbridge has integrated hardware monitor functions. It also
+has an I2C bus, but this driver only supports the hardware monitor. For the
+I2C bus driver see i2c-sis5595.
+
+The SiS5595 implements zero or one temperature sensor, two fan speed
+sensors, four or five voltage sensors, and alarms.
+
+On the first version of the chip, there are four voltage sensors and one
+temperature sensor.
+
+On the second version of the chip, the temperature sensor (temp) and the
+fifth voltage sensor (in4) share a pin which is configurable, but not
+through the driver. Sorry. The driver senses the configuration of the pin,
+which was hopefully set by the BIOS.
+
+Temperatures are measured in degrees Celsius. An alarm is triggered once
+when the max is crossed; it is also triggered when it drops below the min
+value. Measurements are guaranteed between -55 and +125 degrees, with a
+resolution of 1 degree.
+
+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 or 8) to give
+the readings more range or accuracy. Not all RPM values can accurately be
+represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+Voltage sensors (also known as IN sensors) report their values in volts. An
+alarm is triggered if the voltage has crossed a programmable minimum or
+maximum limit. Note that minimum in this case always means 'closest to
+zero'; this is important for negative voltage measurements. All voltage
+inputs can measure voltages between 0 and 4.08 volts, with a resolution of
+0.016 volt.
+
+In addition to the alarms described above, there is a BTI alarm, which gets
+triggered when an external chip has crossed its limits. Usually, this is
+connected to some LM75-like chip; if at least one crosses its limits, this
+bit gets set.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may already
+have disappeared! Note that in the current implementation, all hardware
+registers are read whenever any data is read (unless it is less than 1.5
+seconds since the last update). This means that you can easily miss
+once-only alarms.
+
+The SiS5595 only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values.
+
+Problems
+--------
+Some chips refuse to be enabled. We don't know why.
+The driver will recognize this and print a message in dmesg.
+
diff --git a/Documentation/i2c/chips/smsc47b397 b/Documentation/i2c/chips/smsc47b397
new file mode 100644
index 0000000..da9d80c
--- /dev/null
+++ b/Documentation/i2c/chips/smsc47b397
@@ -0,0 +1,158 @@
+Kernel driver smsc47b397
+========================
+
+Supported chips:
+  * SMSC LPC47B397-NC
+    Prefix: 'smsc47b397'
+    Addresses scanned: none, address read from Super I/O config space
+    Datasheet: In this file
+
+Authors: Mark M. Hoffman <mhoffman@lightlink.com>
+         Utilitek Systems, Inc.
+
+November 23, 2004
+
+The following specification describes the SMSC LPC47B397-NC sensor chip
+(for which there is no public datasheet available). This document was
+provided by Craig Kelly (In-Store Broadcast Network) and edited/corrected
+by Mark M. Hoffman <mhoffman@lightlink.com>.
+
+* * * * *
+
+Methods for detecting the HP SIO and reading the thermal data on a dc7100.
+
+The thermal information on the dc7100 is contained in the SIO Hardware Monitor
+(HWM). The information is accessed through an index/data pair. The index/data
+pair is located at the HWM Base Address + 0 and the HWM Base Address + 1. The
+HWM Base address can be obtained from Logical Device 8, registers 0x60 (MSB)
+and 0x61 (LSB). Currently we are using 0x480 for the HWM Base Address and
+0x480 and 0x481 for the index/data pair.
+
+Reading temperature information.
+The temperature information is located in the following registers:
+Temp1		0x25	(Currently, this reflects the CPU temp on all systems).
+Temp2		0x26
+Temp3		0x27
+Temp4		0x80
+
+Programming Example
+The following is an example of how to read the HWM temperature registers:
+MOV	DX,480H
+MOV	AX,25H
+OUT	DX,AL
+MOV	DX,481H
+IN	AL,DX
+
+AL contains the data in hex, the temperature in Celsius is the decimal
+equivalent.
+
+Ex: If AL contains 0x2A, the temperature is 42 degrees C.
+
+Reading tach information.
+The fan speed information is located in the following registers:
+		LSB	MSB
+Tach1		0x28	0x29	(Currently, this reflects the CPU
+				fan speed on all systems).
+Tach2		0x2A	0x2B
+Tach3		0x2C	0x2D
+Tach4		0x2E	0x2F
+
+Important!!!
+Reading the tach LSB locks the tach MSB.
+The LSB Must be read first.
+
+How to convert the tach reading to RPM.
+The tach reading (TCount) is given by: (Tach MSB * 256) + (Tach LSB)
+The SIO counts the number of 90kHz (11.111us) pulses per revolution.
+RPM = 60/(TCount * 11.111us)
+
+Example:
+Reg 0x28 = 0x9B
+Reg 0x29 = 0x08
+
+TCount = 0x89B = 2203
+
+RPM = 60 / (2203 * 11.11111 E-6) = 2451 RPM
+
+Obtaining the SIO version.
+
+CONFIGURATION SEQUENCE
+To program the configuration registers, the following sequence must be followed:
+1. Enter Configuration Mode
+2. Configure the Configuration Registers
+3. Exit Configuration Mode.
+
+Enter Configuration Mode
+To place the chip into the Configuration State The config key (0x55) is written
+to the CONFIG PORT (0x2E).
+
+Configuration Mode
+In configuration mode, the INDEX PORT is located at the CONFIG PORT address and
+the DATA PORT is at INDEX PORT address + 1.
+
+The desired configuration registers are accessed in two steps:
+a.	Write the index of the Logical Device Number Configuration Register
+	(i.e., 0x07) to the INDEX PORT and then write the number of the
+	desired logical device to the DATA PORT.
+
+b.	Write the address of the desired configuration register within the
+	logical device to the INDEX PORT and then write or read the config-
+	uration register through the DATA PORT.
+
+Note: If accessing the Global Configuration Registers, step (a) is not required.
+
+Exit Configuration Mode
+To exit the Configuration State the write 0xAA to the CONFIG PORT (0x2E).
+The chip returns to the RUN State.  (This is important).
+
+Programming Example
+The following is an example of how to read the SIO Device ID located at 0x20
+
+; ENTER CONFIGURATION MODE
+MOV	DX,02EH
+MOV	AX,055H
+OUT	DX,AL
+; GLOBAL CONFIGURATION  REGISTER
+MOV	DX,02EH
+MOV	AL,20H
+OUT	DX,AL
+; READ THE DATA
+MOV	DX,02FH
+IN	AL,DX
+; EXIT CONFIGURATION MODE
+MOV	DX,02EH
+MOV	AX,0AAH
+OUT	DX,AL
+
+The registers of interest for identifying the SIO on the dc7100 are Device ID
+(0x20) and Device Rev  (0x21).
+
+The Device ID will read 0X6F
+The Device Rev currently reads 0x01
+
+Obtaining the HWM Base Address.
+The following is an example of how to read the HWM Base Address located in
+Logical Device 8.
+
+; ENTER CONFIGURATION MODE
+MOV	DX,02EH
+MOV	AX,055H
+OUT	DX,AL
+; CONFIGURE REGISTER CRE0,
+; LOGICAL DEVICE 8
+MOV	DX,02EH
+MOV	AL,07H
+OUT	DX,AL ;Point to LD# Config Reg
+MOV	DX,02FH
+MOV	AL, 08H
+OUT	DX,AL;Point to Logical Device 8
+;
+MOV	DX,02EH
+MOV	AL,60H
+OUT	DX,AL	; Point to HWM Base Addr MSB
+MOV	DX,02FH
+IN	AL,DX	; Get MSB of HWM Base Addr
+; EXIT CONFIGURATION MODE
+MOV	DX,02EH
+MOV	AX,0AAH
+OUT	DX,AL
diff --git a/Documentation/i2c/chips/smsc47b397.txt b/Documentation/i2c/chips/smsc47b397.txt
deleted file mode 100644
index 389edae..0000000
--- a/Documentation/i2c/chips/smsc47b397.txt
+++ /dev/null
@@ -1,146 +0,0 @@
-November 23, 2004
-
-The following specification describes the SMSC LPC47B397-NC sensor chip
-(for which there is no public datasheet available).  This document was
-provided by Craig Kelly (In-Store Broadcast Network) and edited/corrected
-by Mark M. Hoffman <mhoffman@lightlink.com>.
-
-* * * * *
-
-Methods for detecting the HP SIO and reading the thermal data on a dc7100.
-
-The thermal information on the dc7100 is contained in the SIO Hardware Monitor
-(HWM).  The information is accessed through an index/data pair.  The index/data
-pair is located at the HWM Base Address + 0 and the HWM Base Address + 1.  The
-HWM Base address can be obtained from Logical Device 8, registers 0x60 (MSB)
-and 0x61 (LSB).  Currently we are using 0x480 for the HWM Base Address and
-0x480 and 0x481 for the index/data pair.
-
-Reading temperature information.
-The temperature information is located in the following registers:
-Temp1		0x25	(Currently, this reflects the CPU temp on all systems).
-Temp2		0x26
-Temp3		0x27
-Temp4		0x80
-
-Programming Example
-The following is an example of how to read the HWM temperature registers:
-MOV	DX,480H
-MOV	AX,25H
-OUT	DX,AL
-MOV	DX,481H
-IN	AL,DX
-
-AL contains the data in hex, the temperature in Celsius is the decimal
-equivalent.
-
-Ex: If AL contains 0x2A, the temperature is 42 degrees C.
-
-Reading tach information.
-The fan speed information is located in the following registers:
-		LSB	MSB
-Tach1		0x28	0x29	(Currently, this reflects the CPU
-				fan speed on all systems).
-Tach2		0x2A	0x2B
-Tach3		0x2C	0x2D
-Tach4		0x2E	0x2F
-
-Important!!!
-Reading the tach LSB locks the tach MSB.
-The LSB Must be read first.
-
-How to convert the tach reading to RPM.
-The tach reading (TCount) is given by:  (Tach MSB * 256) + (Tach LSB)
-The SIO counts the number of 90kHz (11.111us) pulses per revolution.
-RPM = 60/(TCount * 11.111us)
-
-Example:
-Reg 0x28 = 0x9B
-Reg 0x29 = 0x08
-
-TCount = 0x89B = 2203
-
-RPM = 60 / (2203 * 11.11111 E-6) = 2451 RPM
-
-Obtaining the SIO version.
-
-CONFIGURATION SEQUENCE
-To program the configuration registers, the following sequence must be followed:
-1. Enter Configuration Mode
-2. Configure the Configuration Registers
-3. Exit Configuration Mode.
-
-Enter Configuration Mode
-To place the chip into the Configuration State The config key (0x55) is written
-to the CONFIG PORT (0x2E). 
-
-Configuration Mode
-In configuration mode, the INDEX PORT is located at the CONFIG PORT address and
-the DATA PORT is at INDEX PORT address + 1.
-
-The desired configuration registers are accessed in two steps: 
-a.	Write the index of the Logical Device Number Configuration Register
-	(i.e., 0x07) to the INDEX PORT and then write the number of the
-	desired logical device to the DATA PORT.
-
-b.	Write the address of the desired configuration register within the
-	logical device to the INDEX PORT and then write or read the config-
-	uration register through the DATA PORT.  
-
-Note: If accessing the Global Configuration Registers, step (a) is not required.
-
-Exit Configuration Mode
-To exit the Configuration State the write 0xAA to the CONFIG PORT (0x2E).
-The chip returns to the RUN State.  (This is important).
-
-Programming Example
-The following is an example of how to read the SIO Device ID located at 0x20
-
-; ENTER CONFIGURATION MODE   
-MOV	DX,02EH
-MOV	AX,055H
-OUT	DX,AL
-; GLOBAL CONFIGURATION  REGISTER 
-MOV	DX,02EH
-MOV	AL,20H
-OUT	DX,AL 
-; READ THE DATA
-MOV	DX,02FH
-IN	AL,DX
-; EXIT CONFIGURATION MODE     
-MOV	DX,02EH
-MOV	AX,0AAH
-OUT	DX,AL
-
-The registers of interest for identifying the SIO on the dc7100 are Device ID
-(0x20) and Device Rev  (0x21).
-
-The Device ID will read 0X6F
-The Device Rev currently reads 0x01
-
-Obtaining the HWM Base Address.
-The following is an example of how to read the HWM Base Address located in
-Logical Device 8.
-
-; ENTER CONFIGURATION MODE   
-MOV	DX,02EH
-MOV	AX,055H
-OUT	DX,AL
-; CONFIGURE REGISTER CRE0,   
-; LOGICAL DEVICE 8           
-MOV	DX,02EH
-MOV	AL,07H
-OUT	DX,AL ;Point to LD# Config Reg
-MOV	DX,02FH
-MOV	AL, 08H
-OUT	DX,AL;Point to Logical Device 8
-;
-MOV	DX,02EH 
-MOV	AL,60H
-OUT	DX,AL	; Point to HWM Base Addr MSB
-MOV	DX,02FH
-IN	AL,DX	; Get MSB of HWM Base Addr
-; EXIT CONFIGURATION MODE     
-MOV	DX,02EH
-MOV	AX,0AAH
-OUT	DX,AL
diff --git a/Documentation/i2c/chips/smsc47m1 b/Documentation/i2c/chips/smsc47m1
new file mode 100644
index 0000000..34e6478
--- /dev/null
+++ b/Documentation/i2c/chips/smsc47m1
@@ -0,0 +1,52 @@
+Kernel driver smsc47m1
+======================
+
+Supported chips:
+  * SMSC LPC47B27x, LPC47M10x, LPC47M13x, LPC47M14x, LPC47M15x and LPC47M192
+    Addresses scanned: none, address read from Super I/O config space
+    Prefix: 'smsc47m1'
+    Datasheets:
+        http://www.smsc.com/main/datasheets/47b27x.pdf
+        http://www.smsc.com/main/datasheets/47m10x.pdf
+        http://www.smsc.com/main/tools/discontinued/47m13x.pdf
+        http://www.smsc.com/main/datasheets/47m14x.pdf
+        http://www.smsc.com/main/tools/discontinued/47m15x.pdf
+        http://www.smsc.com/main/datasheets/47m192.pdf
+
+Authors:
+        Mark D. Studebaker <mdsxyz123@yahoo.com>,
+        With assistance from Bruce Allen <ballen@uwm.edu>, and his
+        fan.c program: http://www.lsc-group.phys.uwm.edu/%7Eballen/driver/
+        Gabriele Gorla <gorlik@yahoo.com>,
+        Jean Delvare <khali@linux-fr.org>
+
+Description
+-----------
+
+The Standard Microsystems Corporation (SMSC) 47M1xx Super I/O chips
+contain monitoring and PWM control circuitry for two fans.
+
+The 47M15x and 47M192 chips contain a full 'hardware monitoring block'
+in addition to the fan monitoring and control. The hardware monitoring
+block is not supported by the driver.
+
+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 or 8) to give
+the readings more range or accuracy. Not all RPM values can accurately be
+represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+PWM values are from 0 to 255.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may
+already have disappeared! Note that in the current implementation, all
+hardware registers are read whenever any data is read (unless it is less
+than 1.5 seconds since the last update). This means that you can easily
+miss once-only alarms.
+
+
+**********************
+The lm_sensors project gratefully acknowledges the support of
+Intel in the development of this driver.
diff --git a/Documentation/i2c/chips/via686a b/Documentation/i2c/chips/via686a
new file mode 100644
index 0000000..b82014c
--- /dev/null
+++ b/Documentation/i2c/chips/via686a
@@ -0,0 +1,65 @@
+Kernel driver via686a
+=====================
+
+Supported chips:
+  * Via VT82C686A, VT82C686B  Southbridge Integrated Hardware Monitor
+    Prefix: 'via686a'
+    Addresses scanned: ISA in PCI-space encoded address
+    Datasheet: On request through web form (http://www.via.com.tw/en/support/datasheets/)
+
+Authors:
+        Kyösti Mälkki <kmalkki@cc.hut.fi>,
+        Mark D. Studebaker <mdsxyz123@yahoo.com>
+        Bob Dougherty <bobd@stanford.edu>
+        (Some conversion-factor data were contributed by
+        Jonathan Teh Soon Yew <j.teh@iname.com>
+        and Alex van Kaam <darkside@chello.nl>.)
+
+Module Parameters
+-----------------
+
+force_addr=0xaddr       Set the I/O base address. Useful for Asus A7V boards
+                        that don't set the address in the BIOS. Does not do a
+                        PCI force; the via686a must still be present in lspci.
+                        Don't use this unless the driver complains that the
+                        base address is not set.
+                        Example: 'modprobe via686a force_addr=0x6000'
+
+Description
+-----------
+
+The driver does not distinguish between the chips and reports
+all as a 686A.
+
+The Via 686a southbridge has integrated hardware monitor functionality.
+It also has an I2C bus, but this driver only supports the hardware monitor.
+For the I2C bus driver, see <file:Documentation/i2c/busses/i2c-viapro>
+
+The Via 686a implements three temperature sensors, two fan rotation speed
+sensors, five voltage sensors and alarms.
+
+Temperatures are measured in degrees Celsius. An alarm is triggered once
+when the Overtemperature Shutdown limit is crossed; it is triggered again
+as soon as it drops 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 or 8) to give
+the readings more range or accuracy. Not all RPM values can accurately be
+represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+Voltage sensors (also known as IN sensors) report their values in volts.
+An alarm is triggered if the voltage has crossed a programmable minimum
+or maximum limit. Voltages are internally scalled, so each voltage channel
+has a different resolution and range.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may
+already have disappeared! Note that in the current implementation, all
+hardware registers are read whenever any data is read (unless it is less
+than 1.5 seconds since the last update). This means that you can easily
+miss once-only alarms.
+
+The driver only updates its values each 1.5 seconds; reading it more often
+will do no harm, but will return 'old' values.
diff --git a/Documentation/i2c/chips/w83627hf b/Documentation/i2c/chips/w83627hf
new file mode 100644
index 0000000..78f37c2
--- /dev/null
+++ b/Documentation/i2c/chips/w83627hf
@@ -0,0 +1,66 @@
+Kernel driver w83627hf
+======================
+
+Supported chips:
+  * Winbond W83627HF (ISA accesses ONLY)
+    Prefix: 'w83627hf'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: http://www.winbond.com/PDF/sheet/w83627hf.pdf
+  * Winbond W83627THF
+    Prefix: 'w83627thf'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: http://www.winbond.com/PDF/sheet/w83627thf.pdf
+  * Winbond W83697HF
+    Prefix: 'w83697hf'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: http://www.winbond.com/PDF/sheet/697hf.pdf
+  * Winbond W83637HF
+    Prefix: 'w83637hf'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: http://www.winbond.com/PDF/sheet/w83637hf.pdf
+
+Authors:
+        Frodo Looijaard <frodol@dds.nl>,
+        Philip Edelbrock <phil@netroedge.com>,
+        Mark Studebaker <mdsxyz123@yahoo.com>,
+        Bernhard C. Schrenk <clemy@clemy.org>
+
+Module Parameters
+-----------------
+
+* force_addr: int
+  Initialize the ISA address of the sensors
+* force_i2c: int
+  Initialize the I2C address of the sensors
+* init: int
+  (default is 1)
+  Use 'init=0' to bypass initializing the chip.
+  Try this if your computer crashes when you load the module.
+
+Description
+-----------
+
+This driver implements support for ISA accesses *only* for
+the Winbond W83627HF, W83627THF, W83697HF and W83637HF Super I/O chips.
+We will refer to them collectively as Winbond chips.
+
+This driver supports ISA accesses, which should be more reliable
+than i2c accesses. Also, for Tyan boards which contain both a
+Super I/O chip and a second i2c-only Winbond chip (often a W83782D),
+using this driver will avoid i2c address conflicts and complex
+initialization that were required in the w83781d driver.
+
+If you really want i2c accesses for these Super I/O chips,
+use the w83781d driver. However this is not the preferred method
+now that this ISA driver has been developed.
+
+Technically, the w83627thf does not support a VID reading. However, it's
+possible or even likely that your mainboard maker has routed these signals
+to a specific set of general purpose IO pins (the Asus P4C800-E is one such
+board). The w83627thf driver now interprets these as VID. If the VID on
+your board doesn't work, first see doc/vid in the lm_sensors package. If
+that still doesn't help, email us at lm-sensors@lm-sensors.org.
+
+For further information on this driver see the w83781d driver
+documentation.
+
diff --git a/Documentation/i2c/chips/w83781d b/Documentation/i2c/chips/w83781d
new file mode 100644
index 0000000..e545933
--- /dev/null
+++ b/Documentation/i2c/chips/w83781d
@@ -0,0 +1,402 @@
+Kernel driver w83781d
+=====================
+
+Supported chips:
+  * Winbond W83781D
+    Prefix: 'w83781d'
+    Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
+    Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/w83781d.pdf
+  * Winbond W83782D
+    Prefix: 'w83782d'
+    Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
+    Datasheet: http://www.winbond.com/PDF/sheet/w83782d.pdf
+  * Winbond W83783S
+    Prefix: 'w83783s'
+    Addresses scanned: I2C 0x2d
+    Datasheet: http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/w83783s.pdf
+  * Winbond W83627HF
+    Prefix: 'w83627hf'
+    Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
+    Datasheet: http://www.winbond.com/PDF/sheet/w83627hf.pdf
+  * Asus AS99127F
+    Prefix: 'as99127f'
+    Addresses scanned: I2C 0x28 - 0x2f
+    Datasheet: Unavailable from Asus
+
+Authors:
+        Frodo Looijaard <frodol@dds.nl>,
+        Philip Edelbrock <phil@netroedge.com>,
+        Mark Studebaker <mdsxyz123@yahoo.com>
+
+Module parameters
+-----------------
+
+* init int
+  (default 1)
+  Use 'init=0' to bypass initializing the chip.
+  Try this if your computer crashes when you load the module.
+
+force_subclients=bus,caddr,saddr,saddr
+  This is used to force the i2c addresses for subclients of
+  a certain chip. Typical usage is `force_subclients=0,0x2d,0x4a,0x4b'
+  to force the subclients of chip 0x2d on bus 0 to i2c addresses
+  0x4a and 0x4b. This parameter is useful for certain Tyan boards.
+
+Description
+-----------
+
+This driver implements support for the Winbond W83781D, W83782D, W83783S,
+W83627HF chips, and the Asus AS99127F chips. We will refer to them
+collectively as W8378* chips.
+
+There is quite some difference between these chips, but they are similar
+enough that it was sensible to put them together in one driver.
+The W83627HF chip is assumed to be identical to the ISA W83782D.
+The Asus chips are similar to an I2C-only W83782D.
+
+Chip        #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
+as99127f    7       3       0       3       0x31    0x12c3  yes     no
+as99127f rev.2 (type_name = as99127f)       0x31    0x5ca3  yes     no
+w83781d     7       3       0       3       0x10-1  0x5ca3  yes     yes
+w83627hf    9       3       2       3       0x21    0x5ca3  yes     yes(LPC)
+w83782d     9       3       2-4     3       0x30    0x5ca3  yes     yes
+w83783s     5-6     3       2       1-2     0x40    0x5ca3  yes     no
+
+Detection of these chips can sometimes be foiled because they can be in
+an internal state that allows no clean access. If you know the address
+of the chip, use a 'force' parameter; this will put them into a more
+well-behaved state first.
+
+The W8378* implements temperature sensors (three on the W83781D and W83782D,
+two on the W83783S), three fan rotation speed sensors, voltage sensors
+(seven on the W83781D, nine on the W83782D and six on the W83783S), VID
+lines, alarms with beep warnings, and some miscellaneous stuff.
+
+Temperatures are measured in degrees Celsius. There is always one main
+temperature sensor, and one (W83783S) or two (W83781D and W83782D) other
+sensors. An alarm is triggered for the main sensor once when the
+Overtemperature Shutdown limit is crossed; it is triggered again as soon as
+it drops below the Hysteresis value. A more useful behavior
+can be found by setting the Hysteresis value to +127 degrees Celsius; in
+this case, alarms are issued during all the time when the actual temperature
+is above the Overtemperature Shutdown value. The driver sets the
+hysteresis value for temp1 to 127 at initialization.
+
+For the other temperature sensor(s), an alarm is triggered when the
+temperature gets higher then the Overtemperature Shutdown value; it stays
+on until the temperature falls below the Hysteresis value. But on the
+W83781D, there is only one alarm that functions for both other sensors!
+Temperatures are guaranteed within a range of -55 to +125 degrees. The
+main temperature sensors has a resolution of 1 degree; the other sensor(s)
+of 0.5 degree.
+
+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 or 8 for the
+W83781D; 1, 2, 4, 8, 16, 32, 64 or 128 for the others) to give
+the readings more range or accuracy. Not all RPM values can accurately
+be represented, so some rounding is done. With a divider of 2, the lowest
+representable value is around 2600 RPM.
+
+Voltage sensors (also known as IN sensors) report their values in volts.
+An alarm is triggered if the voltage has crossed a programmable minimum
+or maximum limit. Note that minimum in this case always means 'closest to
+zero'; this is important for negative voltage measurements. All voltage
+inputs can measure voltages between 0 and 4.08 volts, with a resolution
+of 0.016 volt.
+
+The VID lines encode the core voltage value: the voltage level your processor
+should work with. This is hardcoded by the mainboard and/or processor itself.
+It is a value in volts. When it is unconnected, you will often find the
+value 3.50 V here.
+
+The W83782D and W83783S temperature conversion machine understands about
+several kinds of temperature probes. You can program the so-called
+beta value in the sensor files. '1' is the PII/Celeron diode, '2' is the
+TN3904 transistor, and 3435 the default thermistor value. Other values
+are (not yet) supported.
+
+In addition to the alarms described above, there is a CHAS alarm on the
+chips which triggers if your computer case is open.
+
+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.
+
+If an alarm triggers, it will remain triggered until the hardware register
+is read at least once. This means that the cause for the alarm may
+already have disappeared! Note that in the current implementation, all
+hardware registers are read whenever any data is read (unless it is less
+than 1.5 seconds since the last update). This means that you can easily
+miss once-only alarms.
+
+The chips only update values each 1.5 seconds; reading them more often
+will do no harm, but will return 'old' values.
+
+AS99127F PROBLEMS
+-----------------
+The as99127f support was developed without the benefit of a datasheet.
+In most cases it is treated as a w83781d (although revision 2 of the
+AS99127F looks more like a w83782d).
+This support will be BETA until a datasheet is released.
+One user has reported problems with fans stopping
+occasionally.
+
+Note that the individual beep bits are inverted from the other chips.
+The driver now takes care of this so that user-space applications
+don't have to know about it.
+
+Known problems:
+	- Problems with diode/thermistor settings (supported?)
+	- One user reports fans stopping under high server load.
+	- Revision 2 seems to have 2 PWM registers but we don't know
+	  how to handle them. More details below.
+
+These will not be fixed unless we get a datasheet.
+If you have problems, please lobby Asus to release a datasheet.
+Unfortunately several others have without success.
+Please do not send mail to us asking for better as99127f support.
+We have done the best we can without a datasheet.
+Please do not send mail to the author or the sensors group asking for
+a datasheet or ideas on how to convince Asus. We can't help.
+
+
+NOTES:
+-----
+  783s has no in1 so that in[2-6] are compatible with the 781d/782d.
+
+  783s pin is programmable for -5V or temp1; defaults to -5V,
+       no control in driver so temp1 doesn't work.
+
+  782d and 783s datasheets differ on which is pwm1 and which is pwm2.
+       We chose to follow 782d.
+
+  782d and 783s pin is programmable for fan3 input or pwm2 output;
+       defaults to fan3 input.
+       If pwm2 is enabled (with echo 255 1 > pwm2), then
+       fan3 will report 0.
+
+  782d has pwm1-2 for ISA, pwm1-4 for i2c. (pwm3-4 share pins with
+       the ISA pins)
+
+Data sheet updates:
+------------------
+	- PWM clock registers:
+
+		000: master /  512
+		001: master / 1024
+		010: master / 2048
+		011: master / 4096
+		100: master / 8192
+
+
+Answers from Winbond tech support
+---------------------------------
+>
+> 1) In the W83781D data sheet section 7.2 last paragraph, it talks about
+>    reprogramming the R-T table if the Beta of the thermistor is not
+>    3435K. The R-T table is described briefly in section 8.20.
+>    What formulas do I use to program a new R-T table for a given Beta?
+>
+	We are sorry that the calculation for R-T table value is
+confidential. If you have another Beta value of thermistor, we can help
+to calculate the R-T table for you. But you should give us real R-T
+Table which can be gotten by thermistor vendor. Therefore we will calculate
+them and obtain 32-byte data, and you can fill the 32-byte data to the
+register in Bank0.CR51 of W83781D.
+
+
+> 2) In the W83782D data sheet, it mentions that pins 38, 39, and 40 are
+>    programmable to be either thermistor or Pentium II diode inputs.
+>    How do I program them for diode inputs? I can't find any register
+>    to program these to be diode inputs.
+ --> You may program Bank0 CR[5Dh] and CR[59h] registers.
+
+ 	CR[5Dh]    		bit 1(VTIN1)    bit 2(VTIN2)   bit 3(VTIN3)
+
+      	thermistor                0		 0		0
+ 	diode 		          1		 1		1
+
+
+(error) CR[59h] 		bit 4(VTIN1)	bit 2(VTIN2)   bit 3(VTIN3)
+(right) CR[59h] 		bit 4(VTIN1)	bit 5(VTIN2)   bit 6(VTIN3)
+
+ 	PII thermal diode         1		 1		1
+ 	2N3904	diode	          0		 0		0
+
+
+Asus Clones
+-----------
+
+We have no datasheets for the Asus clones (AS99127F and ASB100 Bach).
+Here are some very useful information that were given to us by Alex Van
+Kaam about how to detect these chips, and how to read their values. He
+also gives advice for another Asus chipset, the Mozart-2 (which we
+don't support yet). Thanks Alex!
+I reworded some parts and added personal comments.
+
+# Detection:
+
+AS99127F rev.1, AS99127F rev.2 and ASB100:
+- I2C address range: 0x29 - 0x2F
+- If register 0x58 holds 0x31 then we have an Asus (either ASB100 or
+  AS99127F)
+- Which one depends on register 0x4F (manufacturer ID):
+  0x06 or 0x94: ASB100
+  0x12 or 0xC3: AS99127F rev.1
+  0x5C or 0xA3: AS99127F rev.2
+  Note that 0x5CA3 is Winbond's ID (WEC), which let us think Asus get their
+  AS99127F rev.2 direct from Winbond. The other codes mean ATT and DVC,
+  respectively. ATT could stand for Asustek something (although it would be
+  very badly chosen IMHO), I don't know what DVC could stand for. Maybe
+  these codes simply aren't meant to be decoded that way.
+
+Mozart-2:
+- I2C address: 0x77
+- If register 0x58 holds 0x56 or 0x10 then we have a Mozart-2
+- Of the Mozart there are 3 types:
+  0x58=0x56, 0x4E=0x94, 0x4F=0x36: Asus ASM58 Mozart-2
+  0x58=0x56, 0x4E=0x94, 0x4F=0x06: Asus AS2K129R Mozart-2
+  0x58=0x10, 0x4E=0x5C, 0x4F=0xA3: Asus ??? Mozart-2
+  You can handle all 3 the exact same way :)
+
+# Temperature sensors:
+
+ASB100:
+- sensor 1: register 0x27
+- sensor 2 & 3 are the 2 LM75's on the SMBus
+- sensor 4: register 0x17
+Remark: I noticed that on Intel boards sensor 2 is used for the CPU
+  and 4 is ignored/stuck, on AMD boards sensor 4 is the CPU and sensor 2 is
+  either ignored or a socket temperature.
+
+AS99127F (rev.1 and 2 alike):
+- sensor 1: register 0x27
+- sensor 2 & 3 are the 2 LM75's on the SMBus
+Remark: Register 0x5b is suspected to be temperature type selector. Bit 1
+  would control temp1, bit 3 temp2 and bit 5 temp3.
+
+Mozart-2:
+- sensor 1: register 0x27
+- sensor 2: register 0x13
+
+# Fan sensors:
+
+ASB100, AS99127F (rev.1 and 2 alike):
+- 3 fans, identical to the W83781D
+
+Mozart-2:
+- 2 fans only, 1350000/RPM/div
+- fan 1: register 0x28,  divisor on register 0xA1 (bits 4-5)
+- fan 2: register 0x29,  divisor on register 0xA1 (bits 6-7)
+
+# Voltages:
+
+This is where there is a difference between AS99127F rev.1 and 2.
+Remark: The difference is similar to the difference between
+  W83781D and W83782D.
+
+ASB100:
+in0=r(0x20)*0.016
+in1=r(0x21)*0.016
+in2=r(0x22)*0.016
+in3=r(0x23)*0.016*1.68
+in4=r(0x24)*0.016*3.8
+in5=r(0x25)*(-0.016)*3.97
+in6=r(0x26)*(-0.016)*1.666
+
+AS99127F rev.1:
+in0=r(0x20)*0.016
+in1=r(0x21)*0.016
+in2=r(0x22)*0.016
+in3=r(0x23)*0.016*1.68
+in4=r(0x24)*0.016*3.8
+in5=r(0x25)*(-0.016)*3.97
+in6=r(0x26)*(-0.016)*1.503
+
+AS99127F rev.2:
+in0=r(0x20)*0.016
+in1=r(0x21)*0.016
+in2=r(0x22)*0.016
+in3=r(0x23)*0.016*1.68
+in4=r(0x24)*0.016*3.8
+in5=(r(0x25)*0.016-3.6)*5.14+3.6
+in6=(r(0x26)*0.016-3.6)*3.14+3.6
+
+Mozart-2:
+in0=r(0x20)*0.016
+in1=255
+in2=r(0x22)*0.016
+in3=r(0x23)*0.016*1.68
+in4=r(0x24)*0.016*4
+in5=255
+in6=255
+
+
+# PWM
+
+Additional info about PWM on the AS99127F (may apply to other Asus
+chips as well) by Jean Delvare as of 2004-04-09:
+
+AS99127F revision 2 seems to have two PWM registers at 0x59 and 0x5A,
+and a temperature sensor type selector at 0x5B (which basically means
+that they swapped registers 0x59 and 0x5B when you compare with Winbond
+chips).
+Revision 1 of the chip also has the temperature sensor type selector at
+0x5B, but PWM registers have no effect.
+
+We don't know exactly how the temperature sensor type selection works.
+Looks like bits 1-0 are for temp1, bits 3-2 for temp2 and bits 5-4 for
+temp3, although it is possible that only the most significant bit matters
+each time. So far, values other than 0 always broke the readings.
+
+PWM registers seem to be split in two parts: bit 7 is a mode selector,
+while the other bits seem to define a value or threshold.
+
+When bit 7 is clear, bits 6-0 seem to hold a threshold value. If the value
+is below a given limit, the fan runs at low speed. If the value is above
+the limit, the fan runs at full speed. We have no clue as to what the limit
+represents. Note that there seem to be some inertia in this mode, speed
+changes may need some time to trigger. Also, an hysteresis mechanism is
+suspected since walking through all the values increasingly and then
+decreasingly led to slightly different limits.
+
+When bit 7 is set, bits 3-0 seem to hold a threshold value, while bits 6-4
+would not be significant. If the value is below a given limit, the fan runs
+at full speed, while if it is above the limit it runs at low speed (so this
+is the contrary of the other mode, in a way). Here again, we don't know
+what the limit is supposed to represent.
+
+One remarkable thing is that the fans would only have two or three
+different speeds (transitional states left apart), not a whole range as
+you usually get with PWM.
+
+As a conclusion, you can write 0x00 or 0x8F to the PWM registers to make
+fans run at low speed, and 0x7F or 0x80 to make them run at full speed.
+
+Please contact us if you can figure out how it is supposed to work. As
+long as we don't know more, the w83781d driver doesn't handle PWM on
+AS99127F chips at all.
+
+Additional info about PWM on the AS99127F rev.1 by Hector Martin:
+
+I've been fiddling around with the (in)famous 0x59 register and
+found out the following values do work as a form of coarse pwm:
+
+0x80 - seems to turn fans off after some time(1-2 minutes)... might be
+some form of auto-fan-control based on temp? hmm (Qfan? this mobo is an
+old ASUS, it isn't marketed as Qfan. Maybe some beta pre-attemp at Qfan
+that was dropped at the BIOS)
+0x81 - off
+0x82 - slightly "on-ner" than off, but my fans do not get to move. I can
+hear the high-pitched PWM sound that motors give off at too-low-pwm.
+0x83 - now they do move. Estimate about 70% speed or so.
+0x84-0x8f - full on
+
+Changing the high nibble doesn't seem to do much except the high bit
+(0x80) must be set for PWM to work, else the current pwm doesn't seem to
+change.
+
+My mobo is an ASUS A7V266-E. This behavior is similar to what I got
+with speedfan under Windows, where 0-15% would be off, 15-2x% (can't
+remember the exact value) would be 70% and higher would be full on.
diff --git a/Documentation/i2c/chips/w83l785ts b/Documentation/i2c/chips/w83l785ts
new file mode 100644
index 0000000..1841ced
--- /dev/null
+++ b/Documentation/i2c/chips/w83l785ts
@@ -0,0 +1,39 @@
+Kernel driver w83l785ts
+=======================
+
+Supported chips:
+  * Winbond W83L785TS-S
+    Prefix: 'w83l785ts'
+    Addresses scanned: I2C 0x2e
+    Datasheet: Publicly available at the Winbond USA website
+               http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83L785TS-S.pdf
+
+Authors:
+        Jean Delvare <khali@linux-fr.org>
+
+Description
+-----------
+
+The W83L785TS-S is a digital temperature sensor. It senses the
+temperature of a single external diode. The high limit is
+theoretically defined as 85 or 100 degrees C through a combination
+of external resistors, so the user cannot change it. Values seen so
+far suggest that the two possible limits are actually 95 and 110
+degrees C. The datasheet is rather poor and obviously inaccurate
+on several points including this one.
+
+All temperature values are given in degrees Celsius. Resolution
+is 1.0 degree. See the datasheet for details.
+
+The w83l785ts driver will not update its values more frequently than
+every other second; reading them more often will do no harm, but will
+return 'old' values.
+
+Known Issues
+------------
+
+On some systems (Asus), the BIOS is known to interfere with the driver
+and cause read errors. The driver will retry a given number of times
+(5 by default) and then give up, returning the old value (or 0 if
+there is no old value). It seems to work well enough so that you should
+not notice anything. Thanks to James Bolt for helping test this feature.
diff --git a/Documentation/i2c/porting-clients b/Documentation/i2c/porting-clients
index 5640491..a7adbdd 100644
--- a/Documentation/i2c/porting-clients
+++ b/Documentation/i2c/porting-clients
@@ -57,7 +57,7 @@
   Documentation/i2c/sysfs-interface for the individual files. Also
   convert the units these files read and write to the specified ones.
   If you need to add a new type of file, please discuss it on the
-  sensors mailing list <sensors@stimpy.netroedge.com> by providing a
+  sensors mailing list <lm-sensors@lm-sensors.org> by providing a
   patch to the Documentation/i2c/sysfs-interface file.
 
 * [Attach] For I2C drivers, the attach function should make sure
diff --git a/Documentation/i2c/userspace-tools b/Documentation/i2c/userspace-tools
new file mode 100644
index 0000000..2622aac
--- /dev/null
+++ b/Documentation/i2c/userspace-tools
@@ -0,0 +1,39 @@
+Introduction
+------------
+
+Most mainboards have sensor chips to monitor system health (like temperatures,
+voltages, fans speed). They are often connected through an I2C bus, but some
+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.
+
+Lm-sensors
+----------
+
+Core set of utilites 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.
+
+General hints to get things working:
+
+0) get lm-sensors userspace utils
+1) compile all drivers in I2C section 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
+--------------
+
+If you want some graphical indicators of system health look for applications
+like: gkrellm, ksensors, xsensors, wmtemp, wmsensors, wmgtemp, ksysguardd,
+hardware-monitor
+
+If you are server administrator you can try snmpd or mrtgutils.
diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
index ad27511..f482dae 100644
--- a/Documentation/i2c/writing-clients
+++ b/Documentation/i2c/writing-clients
@@ -171,45 +171,31 @@
 
   normal_i2c: filled in by the module writer. 
      A list of I2C addresses which should normally be examined.
-   normal_i2c_range: filled in by the module writer.
-     A list of pairs of I2C addresses, each pair being an inclusive range of
-     addresses which should normally be examined.
    probe: insmod parameter. 
      A list of pairs. The first value is a bus number (-1 for any I2C bus), 
      the second is the address. These addresses are also probed, as if they 
      were in the 'normal' list.
-   probe_range: insmod parameter. 
-     A list of triples. The first value is a bus number (-1 for any I2C bus), 
-     the second and third are addresses.  These form an inclusive range of 
-     addresses that are also probed, as if they were in the 'normal' list.
    ignore: insmod parameter.
      A list of pairs. The first value is a bus number (-1 for any I2C bus), 
      the second is the I2C address. These addresses are never probed. 
      This parameter overrules 'normal' and 'probe', but not the 'force' lists.
-   ignore_range: insmod parameter. 
-     A list of triples. The first value is a bus number (-1 for any I2C bus), 
-     the second and third are addresses. These form an inclusive range of 
-     I2C addresses that are never probed.
-     This parameter overrules 'normal' and 'probe', but not the 'force' lists.
    force: insmod parameter. 
      A list of pairs. The first value is a bus number (-1 for any I2C bus),
      the second is the I2C address. A device is blindly assumed to be on
      the given address, no probing is done. 
 
-Fortunately, as a module writer, you just have to define the `normal' 
-and/or `normal_range' parameters. The complete declaration could look
-like this:
+Fortunately, as a module writer, you just have to define the `normal_i2c' 
+parameter. The complete declaration could look like this:
 
-  /* Scan 0x20 to 0x2f, 0x37, and 0x40 to 0x4f */
-  static unsigned short normal_i2c[] = { 0x37,I2C_CLIENT_END }; 
-  static unsigned short normal_i2c_range[] = { 0x20, 0x2f, 0x40, 0x4f, 
-                                               I2C_CLIENT_END };
+  /* Scan 0x37, and 0x48 to 0x4f */
+  static unsigned short normal_i2c[] = { 0x37, 0x48, 0x49, 0x4a, 0x4b, 0x4c,
+                                         0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
 
   /* Magic definition of all other variables and things */
   I2C_CLIENT_INSMOD;
 
-Note that you *have* to call the two defined variables `normal_i2c' and
-`normal_i2c_range', without any prefix!
+Note that you *have* to call the defined variable `normal_i2c',
+without any prefix!
 
 
 Probing classes (sensors)
@@ -223,39 +209,17 @@
 
    normal_i2c: filled in by the module writer. Terminated by SENSORS_I2C_END.
      A list of I2C addresses which should normally be examined.
-   normal_i2c_range: filled in by the module writer. Terminated by 
-     SENSORS_I2C_END
-     A list of pairs of I2C addresses, each pair being an inclusive range of
-     addresses which should normally be examined.
    normal_isa: filled in by the module writer. Terminated by SENSORS_ISA_END.
      A list of ISA addresses which should normally be examined.
-   normal_isa_range: filled in by the module writer. Terminated by 
-     SENSORS_ISA_END
-     A list of triples. The first two elements are ISA addresses, being an
-     range of addresses which should normally be examined. The third is the
-     modulo parameter: only addresses which are 0 module this value relative
-     to the first address of the range are actually considered.
    probe: insmod parameter. Initialize this list with SENSORS_I2C_END values.
      A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
      the ISA bus, -1 for any I2C bus), the second is the address. These
      addresses are also probed, as if they were in the 'normal' list.
-   probe_range: insmod parameter. Initialize this list with SENSORS_I2C_END 
-     values.
-     A list of triples. The first value is a bus number (SENSORS_ISA_BUS for
-     the ISA bus, -1 for any I2C bus), the second and third are addresses. 
-     These form an inclusive range of addresses that are also probed, as
-     if they were in the 'normal' list.
    ignore: insmod parameter. Initialize this list with SENSORS_I2C_END values.
      A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
      the ISA bus, -1 for any I2C bus), the second is the I2C address. These
      addresses are never probed. This parameter overrules 'normal' and 
      'probe', but not the 'force' lists.
-   ignore_range: insmod parameter. Initialize this list with SENSORS_I2C_END 
-      values.
-     A list of triples. The first value is a bus number (SENSORS_ISA_BUS for
-     the ISA bus, -1 for any I2C bus), the second and third are addresses. 
-     These form an inclusive range of I2C addresses that are never probed.
-     This parameter overrules 'normal' and 'probe', but not the 'force' lists.
 
 Also used is a list of pointers to sensors_force_data structures:
    force_data: insmod parameters. A list, ending with an element of which
@@ -269,16 +233,14 @@
 So we have a generic insmod variabled `force', and chip-specific variables
 `force_CHIPNAME'.
 
-Fortunately, as a module writer, you just have to define the `normal' 
-and/or `normal_range' parameters, and define what chip names are used. 
+Fortunately, as a module writer, you just have to define the `normal_i2c' 
+and `normal_isa' parameters, and define what chip names are used. 
 The complete declaration could look like this:
-  /* Scan i2c addresses 0x20 to 0x2f, 0x37, and 0x40 to 0x4f
-  static unsigned short normal_i2c[] = {0x37,SENSORS_I2C_END};
-  static unsigned short normal_i2c_range[] = {0x20,0x2f,0x40,0x4f,
-                                              SENSORS_I2C_END};
+  /* Scan i2c addresses 0x37, and 0x48 to 0x4f */
+  static unsigned short normal_i2c[] = { 0x37, 0x48, 0x49, 0x4a, 0x4b, 0x4c,
+                                         0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
   /* Scan ISA address 0x290 */
   static unsigned int normal_isa[] = {0x0290,SENSORS_ISA_END};
-  static unsigned int normal_isa_range[] = {SENSORS_ISA_END};
 
   /* Define chips foo and bar, as well as all module parameters and things */
   SENSORS_INSMOD_2(foo,bar);
diff --git a/Documentation/kdump/gdbmacros.txt b/Documentation/kdump/gdbmacros.txt
new file mode 100644
index 0000000..bc1b9eb
--- /dev/null
+++ b/Documentation/kdump/gdbmacros.txt
@@ -0,0 +1,179 @@
+#
+# This file contains a few gdb macros (user defined commands) to extract
+# useful information from kernel crashdump (kdump) like stack traces of
+# all the processes or a particular process and trapinfo.
+#
+# These macros can be used by copying this file in .gdbinit (put in home
+# directory or current directory) or by invoking gdb command with
+# --command=<command-file-name> option
+#
+# Credits:
+# Alexander Nyberg <alexn@telia.com>
+# V Srivatsa <vatsa@in.ibm.com>
+# Maneesh Soni <maneesh@in.ibm.com>
+#
+
+define bttnobp
+	set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
+	set $pid_off=((size_t)&((struct task_struct *)0)->pids[1].pid_list.next)
+	set $init_t=&init_task
+	set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
+	while ($next_t != $init_t)
+		set $next_t=(struct task_struct *)$next_t
+		printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm
+		printf "===================\n"
+		set var $stackp = $next_t.thread.esp
+		set var $stack_top = ($stackp & ~4095) + 4096
+
+		while ($stackp < $stack_top)
+			if (*($stackp) > _stext && *($stackp) < _sinittext)
+				info symbol *($stackp)
+			end
+			set $stackp += 4
+		end
+		set $next_th=(((char *)$next_t->pids[1].pid_list.next) - $pid_off)
+		while ($next_th != $next_t)
+			set $next_th=(struct task_struct *)$next_th
+			printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm
+			printf "===================\n"
+			set var $stackp = $next_t.thread.esp
+			set var $stack_top = ($stackp & ~4095) + 4096
+
+			while ($stackp < $stack_top)
+				if (*($stackp) > _stext && *($stackp) < _sinittext)
+					info symbol *($stackp)
+				end
+				set $stackp += 4
+			end
+			set $next_th=(((char *)$next_th->pids[1].pid_list.next) - $pid_off)
+		end
+		set $next_t=(char *)($next_t->tasks.next) - $tasks_off
+	end
+end
+document bttnobp
+	dump all thread stack traces on a kernel compiled with !CONFIG_FRAME_POINTER
+end
+
+define btt
+	set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
+	set $pid_off=((size_t)&((struct task_struct *)0)->pids[1].pid_list.next)
+	set $init_t=&init_task
+	set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
+	while ($next_t != $init_t)
+		set $next_t=(struct task_struct *)$next_t
+		printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm
+		printf "===================\n"
+		set var $stackp = $next_t.thread.esp
+		set var $stack_top = ($stackp & ~4095) + 4096
+		set var $stack_bot = ($stackp & ~4095)
+
+		set $stackp = *($stackp)
+		while (($stackp < $stack_top) && ($stackp > $stack_bot))
+			set var $addr = *($stackp + 4)
+			info symbol $addr
+			set $stackp = *($stackp)
+		end
+
+		set $next_th=(((char *)$next_t->pids[1].pid_list.next) - $pid_off)
+		while ($next_th != $next_t)
+			set $next_th=(struct task_struct *)$next_th
+			printf "\npid %d; comm %s:\n", $next_t.pid, $next_t.comm
+			printf "===================\n"
+			set var $stackp = $next_t.thread.esp
+			set var $stack_top = ($stackp & ~4095) + 4096
+			set var $stack_bot = ($stackp & ~4095)
+
+			set $stackp = *($stackp)
+			while (($stackp < $stack_top) && ($stackp > $stack_bot))
+				set var $addr = *($stackp + 4)
+				info symbol $addr
+				set $stackp = *($stackp)
+			end
+			set $next_th=(((char *)$next_th->pids[1].pid_list.next) - $pid_off)
+		end
+		set $next_t=(char *)($next_t->tasks.next) - $tasks_off
+	end
+end
+document btt
+	dump all thread stack traces on a kernel compiled with CONFIG_FRAME_POINTER
+end
+
+define btpid
+	set var $pid = $arg0
+	set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
+	set $pid_off=((size_t)&((struct task_struct *)0)->pids[1].pid_list.next)
+	set $init_t=&init_task
+	set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
+	set var $pid_task = 0
+
+	while ($next_t != $init_t)
+		set $next_t=(struct task_struct *)$next_t
+
+		if ($next_t.pid == $pid)
+			set $pid_task = $next_t
+		end
+
+		set $next_th=(((char *)$next_t->pids[1].pid_list.next) - $pid_off)
+		while ($next_th != $next_t)
+			set $next_th=(struct task_struct *)$next_th
+			if ($next_th.pid == $pid)
+				set $pid_task = $next_th
+			end
+			set $next_th=(((char *)$next_th->pids[1].pid_list.next) - $pid_off)
+		end
+		set $next_t=(char *)($next_t->tasks.next) - $tasks_off
+	end
+
+	printf "\npid %d; comm %s:\n", $pid_task.pid, $pid_task.comm
+	printf "===================\n"
+	set var $stackp = $pid_task.thread.esp
+	set var $stack_top = ($stackp & ~4095) + 4096
+	set var $stack_bot = ($stackp & ~4095)
+
+	set $stackp = *($stackp)
+	while (($stackp < $stack_top) && ($stackp > $stack_bot))
+		set var $addr = *($stackp + 4)
+		info symbol $addr
+		set $stackp = *($stackp)
+	end
+end
+document btpid
+	backtrace of pid
+end
+
+
+define trapinfo
+	set var $pid = $arg0
+	set $tasks_off=((size_t)&((struct task_struct *)0)->tasks)
+	set $pid_off=((size_t)&((struct task_struct *)0)->pids[1].pid_list.next)
+	set $init_t=&init_task
+	set $next_t=(((char *)($init_t->tasks).next) - $tasks_off)
+	set var $pid_task = 0
+
+	while ($next_t != $init_t)
+		set $next_t=(struct task_struct *)$next_t
+
+		if ($next_t.pid == $pid)
+			set $pid_task = $next_t
+		end
+
+		set $next_th=(((char *)$next_t->pids[1].pid_list.next) - $pid_off)
+		while ($next_th != $next_t)
+			set $next_th=(struct task_struct *)$next_th
+			if ($next_th.pid == $pid)
+				set $pid_task = $next_th
+			end
+			set $next_th=(((char *)$next_th->pids[1].pid_list.next) - $pid_off)
+		end
+		set $next_t=(char *)($next_t->tasks.next) - $tasks_off
+	end
+
+	printf "Trapno %ld, cr2 0x%lx, error_code %ld\n", $pid_task.thread.trap_no, \
+				$pid_task.thread.cr2, $pid_task.thread.error_code
+
+end
+document trapinfo
+	Run info threads and lookup pid of thread #1
+	'trapinfo <pid>' will tell you by which trap & possibly
+	addresthe kernel paniced.
+end
diff --git a/Documentation/kdump/kdump.txt b/Documentation/kdump/kdump.txt
new file mode 100644
index 0000000..7ff213f
--- /dev/null
+++ b/Documentation/kdump/kdump.txt
@@ -0,0 +1,141 @@
+Documentation for kdump - the kexec-based crash dumping solution
+================================================================
+
+DESIGN
+======
+
+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.
+
+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=.
+
+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.
+
+In the second kernel, "old memory" can be accessed in two ways.
+
+- 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.
+
+- 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).
+
+SETUP
+=====
+
+1) Download http://www.xmission.com/~ebiederm/files/kexec/kexec-tools-1.101.tar.gz
+   and apply http://lse.sourceforge.net/kdump/patches/kexec-tools-1.101-kdump.patch
+   and after that build the source.
+
+2) Download and build the appropriate (latest) kexec/kdump (-mm) kernel
+   patchset and apply it to the vanilla kernel tree.
+
+   Two kernels need to be built in order to get this feature working.
+
+  A) First kernel:
+   a) Enable "kexec system call" feature (in Processor type and features).
+	CONFIG_KEXEC=y
+   b) This kernel's physical load address should be the default value of
+      0x100000 (0x100000, 1 MB) (in Processor type and features).
+	CONFIG_PHYSICAL_START=0x100000
+   c) Enable "sysfs file system support" (in Pseudo filesystems).
+	CONFIG_SYSFS=y
+   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".
+
+  B) Second kernel:
+   a) Enable "kernel crash dumps" feature (in Processor type and features).
+	CONFIG_CRASH_DUMP=y
+   b) Specify a suitable value for "Physical address where the kernel is
+      loaded" (in Processor type and features). Typically this value
+      should be same as X (See option d) above, e.g., 16 MB or 0x1000000.
+	CONFIG_PHYSICAL_START=0x1000000
+   c) Enable "/proc/vmcore support" (Optional, in Pseudo filesystems).
+	CONFIG_PROC_VMCORE=y
+   d) Disable SMP support and build a UP kernel (Until it is fixed).
+   	CONFIG_SMP=n
+   e) Enable "Local APIC support on uniprocessors".
+   	CONFIG_X86_UP_APIC=y
+   f) Enable "IO-APIC support on uniprocessors"
+   	CONFIG_X86_UP_IOAPIC=y
+
+  Note:   i) Options a) and b) depend upon "Configure standard kernel features
+	     (for small systems)" (under General setup).
+	 ii) Option a) also depends on CONFIG_HIGHMEM (under Processor
+		type and features).
+	iii) Both option a) and b) are under "Processor type and features".
+
+3) Boot into the first kernel. You are now ready to try out kexec-based crash
+   dumps.
+
+4) Load the second kernel to be booted using:
+
+   kexec -p <second-kernel> --crash-dump --args-linux --append="root=<root-dev>
+   init 1 irqpoll"
+
+   Note: i) <second-kernel> has to be a vmlinux image. bzImage will not work,
+	    as of now.
+	ii) By default ELF headers are stored in ELF32 format (for i386). This
+	    is sufficient to represent the physical memory up to 4GB. To store
+	    headers in ELF64 format, specifiy "--elf64-core-headers" on the
+	    kexec command line additionally.
+       iii) Specify "irqpoll" as command line parameter. This reduces driver
+            initialization failures in second kernel due to shared interrupts.
+
+5) System reboots into the second kernel when a panic occurs. A module can be
+   written to force the panic or "ALT-SysRq-c" can be used initiate a crash
+   dump for testing purposes.
+
+6) Write out the dump file using
+
+   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:
+
+   mknod /dev/oldmem c 1 12
+
+   Use "dd" with suitable options for count, bs and skip to access specific
+   portions of the dump.
+
+   Entire memory:  dd if=/dev/oldmem of=oldmem.001
+
+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>
+
+Stack trace for the task on processor 0, register display, memory display
+work fine.
+
+Note: gdb cannot analyse core files generated in ELF64 format for i386.
+
+TODO
+====
+
+1) Provide a kernel pages filtering mechanism so that core file size is not
+   insane on systems having huge memory banks.
+2) Modify "crash" tool to make it recognize this dump.
+
+CONTACT
+=======
+
+Vivek Goyal (vgoyal@in.ibm.com)
+Maneesh Soni (maneesh@in.ibm.com)
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 1a50d03..89cd417 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -358,6 +358,10 @@
 	cpia_pp=	[HW,PPT]
 			Format: { parport<nr> | auto | none }
 
+	crashkernel=nn[KMG]@ss[KMG]
+			[KNL] Reserve a chunk of physical memory to
+			hold a kernel to switch to with kexec on panic.
+
 	cs4232=		[HW,OSS]
 			Format: <io>,<irq>,<dma>,<dma2>,<mpuio>,<mpuirq>
 
@@ -447,6 +451,10 @@
 			Format: {"as"|"cfq"|"deadline"|"noop"}
 			See Documentation/block/as-iosched.txt
 			and Documentation/block/deadline-iosched.txt for details.
+	elfcorehdr=	[IA-32]
+			Specifies physical address of start of kernel core image
+			elf header.
+			See Documentation/kdump.txt for details.
 
 	enforcing	[SELINUX] Set initial enforcing status.
 			Format: {"0" | "1"}
@@ -548,6 +556,9 @@
 
 	i810=		[HW,DRM]
 
+	i8k.ignore_dmi	[HW] Continue probing hardware even if DMI data
+			indicates that the driver is running on unsupported
+			hardware.
 	i8k.force	[HW] Activate i8k driver even if SMM BIOS signature
 			does not match list of supported models.
 	i8k.power_status
diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index 36d80ae..0321ded 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -22,6 +22,7 @@
 	- New procfs files
 	- Userspace system call interface
 	- Kernel services
+	- Notes on accessing payload contents
 	- Defining a key type
 	- Request-key callback service
 	- Key access filesystem
@@ -45,27 +46,26 @@
 	- State.
 
 
- (*) Each key is issued a serial number of type key_serial_t that is unique
-     for the lifetime of that key. All serial numbers are positive non-zero
-     32-bit integers.
+ (*) Each key is issued a serial number of type key_serial_t that is unique for
+     the lifetime of that key. All serial numbers are positive non-zero 32-bit
+     integers.
 
      Userspace programs can use a key's serial numbers as a way to gain access
      to it, subject to permission checking.
 
  (*) Each key is of a defined "type". Types must be registered inside the
-     kernel by a kernel service (such as a filesystem) before keys of that
-     type can be added or used. Userspace programs cannot define new types
-     directly.
+     kernel by a kernel service (such as a filesystem) before keys of that type
+     can be added or used. Userspace programs cannot define new types directly.
 
-     Key types are represented in the kernel by struct key_type. This defines
-     a number of operations that can be performed on a key of that type.
+     Key types are represented in the kernel by struct key_type. This defines a
+     number of operations that can be performed on a key of that type.
 
      Should a type be removed from the system, all the keys of that type will
      be invalidated.
 
  (*) Each key has a description. This should be a printable string. The key
-     type provides an operation to perform a match between the description on
-     a key and a criterion string.
+     type provides an operation to perform a match between the description on a
+     key and a criterion string.
 
  (*) Each key has an owner user ID, a group ID and a permissions mask. These
      are used to control what a process may do to a key from userspace, and
@@ -74,10 +74,10 @@
  (*) Each key can be set to expire at a specific time by the key type's
      instantiation function. Keys can also be immortal.
 
- (*) Each key can have a payload. This is a quantity of data that represent
-     the actual "key". In the case of a keyring, this is a list of keys to
-     which the keyring links; in the case of a user-defined key, it's an
-     arbitrary blob of data.
+ (*) Each key can have a payload. This is a quantity of data that represent the
+     actual "key". In the case of a keyring, this is a list of keys to which
+     the keyring links; in the case of a user-defined key, it's an arbitrary
+     blob of data.
 
      Having a payload is not required; and the payload can, in fact, just be a
      value stored in the struct key itself.
@@ -92,8 +92,8 @@
 
  (*) Each key can be in one of a number of basic states:
 
-     (*) Uninstantiated. The key exists, but does not have any data
-	 attached. Keys being requested from userspace will be in this state.
+     (*) Uninstantiated. The key exists, but does not have any data attached.
+     	 Keys being requested from userspace will be in this state.
 
      (*) Instantiated. This is the normal state. The key is fully formed, and
 	 has data attached.
@@ -140,10 +140,10 @@
      clone, fork, vfork or execve occurs. A new keyring is created only when
      required.
 
-     The process-specific keyring is replaced with an empty one in the child
-     on clone, fork, vfork unless CLONE_THREAD is supplied, in which case it
-     is shared. execve also discards the process's process keyring and creates
-     a new one.
+     The process-specific keyring is replaced with an empty one in the child on
+     clone, fork, vfork unless CLONE_THREAD is supplied, in which case it is
+     shared. execve also discards the process's process keyring and creates a
+     new one.
 
      The session-specific keyring is persistent across clone, fork, vfork and
      execve, even when the latter executes a set-UID or set-GID binary. A
@@ -177,11 +177,11 @@
      If a system call that modifies a key or keyring in some way would put the
      user over quota, the operation is refused and error EDQUOT is returned.
 
- (*) There's a system call interface by which userspace programs can create
-     and manipulate keys and keyrings.
+ (*) There's a system call interface by which userspace programs can create and
+     manipulate keys and keyrings.
 
- (*) There's a kernel interface by which services can register types and
-     search for keys.
+ (*) There's a kernel interface by which services can register types and search
+     for keys.
 
  (*) There's a way for the a search done from the kernel to call back to
      userspace to request a key that can't be found in a process's keyrings.
@@ -194,9 +194,9 @@
 KEY ACCESS PERMISSIONS
 ======================
 
-Keys have an owner user ID, a group access ID, and a permissions mask. The
-mask has up to eight bits each for user, group and other access. Only five of
-each set of eight bits are defined. These permissions granted are:
+Keys have an owner user ID, a group access ID, and a permissions mask. The mask
+has up to eight bits each for user, group and other access. Only five of each
+set of eight bits are defined. These permissions granted are:
 
  (*) View
 
@@ -210,8 +210,8 @@
 
  (*) Write
 
-     This permits a key's payload to be instantiated or updated, or it allows
-     a link to be added to or removed from a keyring.
+     This permits a key's payload to be instantiated or updated, or it allows a
+     link to be added to or removed from a keyring.
 
  (*) Search
 
@@ -238,8 +238,8 @@
  (*) /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:
+     type, description and permissions. The payload of the key is not available
+     this way:
 
 	SERIAL   FLAGS  USAGE EXPY PERM   UID   GID   TYPE      DESCRIPTION: SUMMARY
 	00000001 I-----    39 perm 1f0000     0     0 keyring   _uid_ses.0: 1/4
@@ -318,21 +318,21 @@
      If a key of the same type and description as that proposed already exists
      in the keyring, this will try to update it with the given payload, or it
      will return error EEXIST if that function is not supported by the key
-     type. The process must also have permission to write to the key to be
-     able to update it. The new key will have all user permissions granted and
-     no group or third party permissions.
+     type. The process must also have permission to write to the key to be able
+     to update it. The new key will have all user permissions granted and no
+     group or third party permissions.
 
-     Otherwise, this will attempt to create a new key of the specified type
-     and description, and to instantiate it with the supplied payload and
-     attach it to the keyring. In this case, an error will be generated if the
-     process does not have permission to write to the keyring.
+     Otherwise, this will attempt to create a new key of the specified type and
+     description, and to instantiate it with the supplied payload and attach it
+     to the keyring. In this case, an error will be generated if the process
+     does not have permission to write to the keyring.
 
      The payload is optional, and the pointer can be NULL if not required by
      the type. The payload is plen in size, and plen can be zero for an empty
      payload.
 
-     A new keyring can be generated by setting type "keyring", the keyring
-     name as the description (or NULL) and setting the payload to NULL.
+     A new keyring can be generated by setting type "keyring", the keyring name
+     as the description (or NULL) and setting the payload to NULL.
 
      User defined keys can be created by specifying type "user". It is
      recommended that a user defined key's description by prefixed with a type
@@ -369,9 +369,9 @@
 	key_serial_t keyctl(KEYCTL_GET_KEYRING_ID, key_serial_t id,
 			    int create);
 
-     The special key specified by "id" is looked up (with the key being
-     created if necessary) and the ID of the key or keyring thus found is
-     returned if it exists.
+     The special key specified by "id" is looked up (with the key being created
+     if necessary) and the ID of the key or keyring thus found is returned if
+     it exists.
 
      If the key does not yet exist, the key will be created if "create" is
      non-zero; and the error ENOKEY will be returned if "create" is zero.
@@ -402,8 +402,8 @@
 
      This will try to update the specified key with the given payload, or it
      will return error EOPNOTSUPP if that function is not supported by the key
-     type. The process must also have permission to write to the key to be
-     able to update it.
+     type. The process must also have permission to write to the key to be able
+     to update it.
 
      The payload is of length plen, and may be absent or empty as for
      add_key().
@@ -422,8 +422,8 @@
 
 	long keyctl(KEYCTL_CHOWN, key_serial_t key, uid_t uid, gid_t gid);
 
-     This function permits a key's owner and group ID to be changed. Either
-     one of uid or gid can be set to -1 to suppress that change.
+     This function permits a key's owner and group ID to be changed. Either one
+     of uid or gid can be set to -1 to suppress that change.
 
      Only the superuser can change a key's owner to something other than the
      key's current owner. Similarly, only the superuser can change a key's
@@ -484,12 +484,12 @@
 
 	long keyctl(KEYCTL_LINK, key_serial_t keyring, key_serial_t key);
 
-     This function creates a link from the keyring to the key. The process
-     must have write permission on the keyring and must have link permission
-     on the key.
+     This function creates a link from the keyring to the key. The process must
+     have write permission on the keyring and must have link permission on the
+     key.
 
-     Should the keyring not be a keyring, error ENOTDIR will result; and if
-     the keyring is full, error ENFILE will result.
+     Should the keyring not be a keyring, error ENOTDIR will result; and if the
+     keyring is full, error ENFILE will result.
 
      The link procedure checks the nesting of the keyrings, returning ELOOP if
      it appears to deep or EDEADLK if the link would introduce a cycle.
@@ -503,8 +503,8 @@
      specified key, and removes it if found. Subsequent links to that key are
      ignored. The process must have write permission on the keyring.
 
-     If the keyring is not a keyring, error ENOTDIR will result; and if the
-     key is not present, error ENOENT will be the result.
+     If the keyring is not a keyring, error ENOTDIR will result; and if the key
+     is not present, error ENOENT will be the result.
 
 
  (*) Search a keyring tree for a key:
@@ -513,9 +513,9 @@
 			    const char *type, const char *description,
 			    key_serial_t dest_keyring);
 
-     This searches the keyring tree headed by the specified keyring until a
-     key is found that matches the type and description criteria. Each keyring
-     is checked for keys before recursion into its children occurs.
+     This searches the keyring tree headed by the specified keyring until a key
+     is found that matches the type and description criteria. Each keyring is
+     checked for keys before recursion into its children occurs.
 
      The process must have search permission on the top level keyring, or else
      error EACCES will result. Only keyrings that the process has search
@@ -549,8 +549,8 @@
      As much of the data as can be fitted into the buffer will be copied to
      userspace if the buffer pointer is not NULL.
 
-     On a successful return, the function will always return the amount of
-     data available rather than the amount copied.
+     On a successful return, the function will always return the amount of data
+     available rather than the amount copied.
 
 
  (*) Instantiate a partially constructed key.
@@ -568,8 +568,8 @@
      it, and the key must be uninstantiated.
 
      If a keyring is specified (non-zero), the key will also be linked into
-     that keyring, however all the constraints applying in KEYCTL_LINK apply
-     in this case too.
+     that keyring, however all the constraints applying in KEYCTL_LINK apply in
+     this case too.
 
      The payload and plen arguments describe the payload data as for add_key().
 
@@ -587,8 +587,39 @@
      it, and the key must be uninstantiated.
 
      If a keyring is specified (non-zero), the key will also be linked into
-     that keyring, however all the constraints applying in KEYCTL_LINK apply
-     in this case too.
+     that keyring, however all the constraints applying in KEYCTL_LINK apply in
+     this case too.
+
+
+ (*) Set the default request-key destination keyring.
+
+	long keyctl(KEYCTL_SET_REQKEY_KEYRING, int reqkey_defl);
+
+     This sets the default keyring to which implicitly requested keys will be
+     attached for this thread. reqkey_defl should be one of these constants:
+
+	CONSTANT				VALUE	NEW DEFAULT KEYRING
+	======================================	======	=======================
+	KEY_REQKEY_DEFL_NO_CHANGE		-1	No change
+	KEY_REQKEY_DEFL_DEFAULT			0	Default[1]
+	KEY_REQKEY_DEFL_THREAD_KEYRING		1	Thread keyring
+	KEY_REQKEY_DEFL_PROCESS_KEYRING		2	Process keyring
+	KEY_REQKEY_DEFL_SESSION_KEYRING		3	Session keyring
+	KEY_REQKEY_DEFL_USER_KEYRING		4	User keyring
+	KEY_REQKEY_DEFL_USER_SESSION_KEYRING	5	User session keyring
+	KEY_REQKEY_DEFL_GROUP_KEYRING		6	Group keyring
+
+     The old default will be returned if successful and error EINVAL will be
+     returned if reqkey_defl is not one of the above values.
+
+     The default keyring can be overridden by the keyring indicated to the
+     request_key() system call.
+
+     Note that this setting is inherited across fork/exec.
+
+     [1] The default default is: the thread keyring if there is one, otherwise
+     the process keyring if there is one, otherwise the session keyring if
+     there is one, otherwise the user default session keyring.
 
 
 ===============
@@ -601,17 +632,14 @@
 Dealing with keys is fairly straightforward. Firstly, the kernel service
 registers its type, then it searches for a key of that type. It should retain
 the key as long as it has need of it, and then it should release it. For a
-filesystem or device file, a search would probably be performed during the
-open call, and the key released upon close. How to deal with conflicting keys
-due to two different users opening the same file is left to the filesystem
-author to solve.
+filesystem or device file, a search would probably be performed during the open
+call, and the key released upon close. How to deal with conflicting keys due to
+two different users opening the same file is left to the filesystem author to
+solve.
 
-When accessing a key's payload data, key->lock should be at least read locked,
-or else the data may be changed by an update being performed from userspace
-whilst the driver or filesystem is trying to access it. If no update method is
-supplied, then the key's payload may be accessed without holding a lock as
-there is no way to change it, provided it can be guaranteed that the key's
-type definition won't go away.
+When accessing a key's payload contents, certain precautions must be taken to
+prevent access vs modification races. See the section "Notes on accessing
+payload contents" for more information.
 
 (*) To search for a key, call:
 
@@ -629,6 +657,9 @@
     Should the function fail error ENOKEY, EKEYEXPIRED or EKEYREVOKED will be
     returned.
 
+    If successful, the key will have been attached to the default keyring for
+    implicitly obtained request-key keys, as set by KEYCTL_SET_REQKEY_KEYRING.
+
 
 (*) When it is no longer required, the key should be released using:
 
@@ -690,6 +721,54 @@
 	void unregister_key_type(struct key_type *type);
 
 
+===================================
+NOTES ON ACCESSING PAYLOAD CONTENTS
+===================================
+
+The simplest payload is just a number in key->payload.value. In this case,
+there's no need to indulge in RCU or locking when accessing the payload.
+
+More complex payload contents must be allocated and a pointer to them set in
+key->payload.data. One of the following ways must be selected to access the
+data:
+
+ (1) Unmodifyable key type.
+
+     If the key type does not have a modify method, then the key's payload can
+     be accessed without any form of locking, provided that it's known to be
+     instantiated (uninstantiated keys cannot be "found").
+
+ (2) The key's semaphore.
+
+     The semaphore could be used to govern access to the payload and to control
+     the payload pointer. It must be write-locked for modifications and would
+     have to be read-locked for general access. The disadvantage of doing this
+     is that the accessor may be required to sleep.
+
+ (3) RCU.
+
+     RCU must be used when the semaphore isn't already held; if the semaphore
+     is held then the contents can't change under you unexpectedly as the
+     semaphore must still be used to serialise modifications to the key. The
+     key management code takes care of this for the key type.
+
+     However, this means using:
+
+	rcu_read_lock() ... rcu_dereference() ... rcu_read_unlock()
+
+     to read the pointer, and:
+
+	rcu_dereference() ... rcu_assign_pointer() ... call_rcu()
+
+     to set the pointer and dispose of the old contents after a grace period.
+     Note that only the key type should ever modify a key's payload.
+
+     Furthermore, an RCU controlled payload must hold a struct rcu_head for the
+     use of call_rcu() and, if the payload is of variable size, the length of
+     the payload. key->datalen cannot be relied upon to be consistent with the
+     payload just dereferenced if the key's semaphore is not held.
+
+
 ===================
 DEFINING A KEY TYPE
 ===================
@@ -717,15 +796,15 @@
 
 	int key_payload_reserve(struct key *key, size_t datalen);
 
-     With the revised data length. Error EDQUOT will be returned if this is
-     not viable.
+     With the revised data length. Error EDQUOT will be returned if this is not
+     viable.
 
 
  (*) int (*instantiate)(struct key *key, const void *data, size_t datalen);
 
      This method is called to attach a payload to a key during construction.
-     The payload attached need not bear any relation to the data passed to
-     this function.
+     The payload attached need not bear any relation to the data passed to this
+     function.
 
      If the amount of data attached to the key differs from the size in
      keytype->def_datalen, then key_payload_reserve() should be called.
@@ -734,38 +813,47 @@
      The fact that KEY_FLAG_INSTANTIATED is not set in key->flags prevents
      anything else from gaining access to the key.
 
-     This method may sleep if it wishes.
+     It is safe to sleep in this method.
 
 
  (*) int (*duplicate)(struct key *key, const struct key *source);
 
      If this type of key can be duplicated, then this method should be
-     provided. It is called to copy the payload attached to the source into
-     the new key. The data length on the new key will have been updated and
-     the quota adjusted already.
+     provided. It is called to copy the payload attached to the source into the
+     new key. The data length on the new key will have been updated and the
+     quota adjusted already.
 
      This method will be called with the source key's semaphore read-locked to
-     prevent its payload from being changed. It is safe to sleep here.
+     prevent its payload from being changed, thus RCU constraints need not be
+     applied to the source key.
+
+     This method does not have to lock the destination key in order to attach a
+     payload. The fact that KEY_FLAG_INSTANTIATED is not set in key->flags
+     prevents anything else from gaining access to the key.
+
+     It is safe to sleep in this method.
 
 
  (*) int (*update)(struct key *key, const void *data, size_t datalen);
 
-     If this type of key can be updated, then this method should be
-     provided. It is called to update a key's payload from the blob of data
-     provided.
+     If this type of key can be updated, then this method should be provided.
+     It is called to update a key's payload from the blob of data provided.
 
      key_payload_reserve() should be called if the data length might change
-     before any changes are actually made. Note that if this succeeds, the
-     type is committed to changing the key because it's already been altered,
-     so all memory allocation must be done first.
+     before any changes are actually made. Note that if this succeeds, the type
+     is committed to changing the key because it's already been altered, so all
+     memory allocation must be done first.
 
-     key_payload_reserve() should be called with the key->lock write locked,
-     and the changes to the key's attached payload should be made before the
-     key is locked.
+     The key will have its semaphore write-locked before this method is called,
+     but this only deters other writers; any changes to the key's payload must
+     be made under RCU conditions, and call_rcu() must be used to dispose of
+     the old payload.
 
-     The key will have its semaphore write-locked before this method is
-     called. Any changes to the key should be made with the key's rwlock
-     write-locked also. It is safe to sleep here.
+     key_payload_reserve() should be called before the changes are made, but
+     after all allocations and other potentially failing function calls are
+     made.
+
+     It is safe to sleep in this method.
 
 
  (*) int (*match)(const struct key *key, const void *desc);
@@ -782,12 +870,12 @@
 
  (*) void (*destroy)(struct key *key);
 
-     This method is optional. It is called to discard the payload data on a
-     key when it is being destroyed.
+     This method is optional. It is called to discard the payload data on a key
+     when it is being destroyed.
 
-     This method does not need to lock the key; it can consider the key as
-     being inaccessible. Note that the key's type may have changed before this
-     function is called.
+     This method does not need to lock the key to access the payload; it can
+     consider the key as being inaccessible at this time. Note that the key's
+     type may have been changed before this function is called.
 
      It is not safe to sleep in this method; the caller may hold spinlocks.
 
@@ -797,26 +885,31 @@
      This method is optional. It is called during /proc/keys reading to
      summarise a key's description and payload in text form.
 
-     This method will be called with the key's rwlock read-locked. This will
-     prevent the key's payload and state changing; also the description should
-     not change. This also means it is not safe to sleep in this method.
+     This method will be called with the RCU read lock held. rcu_dereference()
+     should be used to read the payload pointer if the payload is to be
+     accessed. key->datalen cannot be trusted to stay consistent with the
+     contents of the payload.
+
+     The description will not change, though the key's state may.
+
+     It is not safe to sleep in this method; the RCU read lock is held by the
+     caller.
 
 
  (*) long (*read)(const struct key *key, char __user *buffer, size_t buflen);
 
      This method is optional. It is called by KEYCTL_READ to translate the
-     key's payload into something a blob of data for userspace to deal
-     with. Ideally, the blob should be in the same format as that passed in to
-     the instantiate and update methods.
+     key's payload into something a blob of data for userspace to deal with.
+     Ideally, the blob should be in the same format as that passed in to the
+     instantiate and update methods.
 
      If successful, the blob size that could be produced should be returned
      rather than the size copied.
 
-     This method will be called with the key's semaphore read-locked. This
-     will prevent the key's payload changing. It is not necessary to also
-     read-lock key->lock when accessing the key's payload. It is safe to sleep
-     in this method, such as might happen when the userspace buffer is
-     accessed.
+     This method will be called with the key's semaphore read-locked. This will
+     prevent the key's payload changing. It is not necessary to use RCU locking
+     when accessing the key's payload. It is safe to sleep in this method, such
+     as might happen when the userspace buffer is accessed.
 
 
 ============================
@@ -853,8 +946,8 @@
 be marked as being negative, it will be added to the session keyring, and an
 error will be returned to the key requestor.
 
-Supplementary information may be provided from whoever or whatever invoked
-this service. This will be passed as the <callout_info> parameter. If no such
+Supplementary information may be provided from whoever or whatever invoked this
+service. This will be passed as the <callout_info> parameter. If no such
 information was made available, then "-" will be passed as this parameter
 instead.
 
diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX
index 834993d..5b01d5c 100644
--- a/Documentation/networking/00-INDEX
+++ b/Documentation/networking/00-INDEX
@@ -114,9 +114,7 @@
 vortex.txt
 	- info on using 3Com Vortex (3c590, 3c592, 3c595, 3c597) Ethernet cards.
 wan-router.txt
-	- Wan router documentation
-wanpipe.txt
-	- WANPIPE(tm) Multiprotocol WAN Driver for Linux WAN Router
+	- WAN router documentation
 wavelan.txt
 	- AT&T GIS (nee NCR) WaveLAN card: An Ethernet-like radio transceiver
 x25.txt
diff --git a/Documentation/networking/dmfe.txt b/Documentation/networking/dmfe.txt
index c0e8398..0463635 100644
--- a/Documentation/networking/dmfe.txt
+++ b/Documentation/networking/dmfe.txt
@@ -1,59 +1,65 @@
-  dmfe.c: Version 1.28        01/18/2000
+Davicom DM9102(A)/DM9132/DM9801 fast ethernet driver for Linux.
 
-        A Davicom DM9102(A)/DM9132/DM9801 fast ethernet driver for Linux. 
-        Copyright (C) 1997  Sten Wang
+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.
-
-        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.
+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.
 
 
-  A. Compiler command:
+This driver provides kernel support for Davicom DM9102(A)/DM9132/DM9801 ethernet cards ( CNET
+10/100 ethernet cards uses Davicom chipset too, so this driver supports CNET cards too ).If you
+didn't compile this driver as a module, it will automatically load itself on boot and print a
+line similar to :
 
-     A-1: For normal single or multiple processor kernel
-          "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall 
-            -Wstrict-prototypes -O6 -c dmfe.c"
+	dmfe: Davicom DM9xxx net driver, version 1.36.4 (2002-01-17)
 
-     A-2: For single or multiple processor with kernel module version function
-          "gcc -DMODULE -DMODVERSIONS -D__KERNEL__ -I/usr/src/linux/net/inet 
-            -Wall -Wstrict-prototypes -O6 -c dmfe.c"
+If you compiled this driver as a module, you have to load it on boot.You can load it with command :
+
+	insmod dmfe
+
+This way it will autodetect the device mode.This is the suggested way to load the module.Or you can pass
+a mode= setting to module while loading, like :
+
+	insmod dmfe mode=0 # Force 10M Half Duplex
+	insmod dmfe mode=1 # Force 100M Half Duplex
+	insmod dmfe mode=4 # Force 10M Full Duplex
+	insmod dmfe mode=5 # Force 100M Full Duplex
+
+Next you should configure your network interface with a command similar to :
+
+	ifconfig eth0 172.22.3.18
+                      ^^^^^^^^^^^
+		     Your IP Adress
+
+Then you may have to modify the default routing table with command :
+
+	route add default eth0
 
 
-  B. The following steps teach you how to activate a DM9102 board:
-
-        1. Used the upper compiler command to compile dmfe.c
-
-        2. Insert dmfe module into kernel
-           "insmod dmfe"        ;;Auto Detection Mode (Suggest)
-           "insmod dmfe mode=0" ;;Force 10M Half Duplex
-           "insmod dmfe mode=1" ;;Force 100M Half Duplex
-           "insmod dmfe mode=4" ;;Force 10M Full Duplex
-           "insmod dmfe mode=5" ;;Force 100M Full Duplex
-
-        3. Config a dm9102 network interface
-           "ifconfig eth0 172.22.3.18"
-                          ^^^^^^^^^^^ Your IP address
-
-        4. Activate the IP routing table. For some distributions, it is not
-           necessary. You can type "route" to check.
-
-           "route add default eth0"
+Now your ethernet card should be up and running.
 
 
-        5. Well done. Your DM9102 adapter is now activated.
+TODO:
+
+Implement pci_driver::suspend() and pci_driver::resume() power management methods.
+Check on 64 bit boxes.
+Check and fix on big endian boxes.
+Test and make sure PCI latency is now correct for all cases.
 
 
-   C. Object files description:
-        1. dmfe_rh61.o:       	For Redhat 6.1
+Authors:
 
-        If you can make sure your kernel version, you can rename
-        to dmfe.o and directly use it without re-compiling.
+Sten Wang <sten_wang@davicom.com.tw >   : Original Author
+Tobias Ringstrom <tori@unhappy.mine.nu> : Current Maintainer
 
+Contributors:
 
-  Author: Sten Wang, 886-3-5798797-8517, E-mail: sten_wang@davicom.com.tw
+Marcelo Tosatti <marcelo@conectiva.com.br>
+Alan Cox <alan@redhat.com>
+Jeff Garzik <jgarzik@pobox.com>
+Vojtech Pavlik <vojtech@suse.cz>
diff --git a/Documentation/networking/generic-hdlc.txt b/Documentation/networking/generic-hdlc.txt
index 7d1dc6b..31bc8b7 100644
--- a/Documentation/networking/generic-hdlc.txt
+++ b/Documentation/networking/generic-hdlc.txt
@@ -1,21 +1,21 @@
 Generic HDLC layer
 Krzysztof Halasa <khc@pm.waw.pl>
-January, 2003
 
 
 Generic HDLC layer currently supports:
-- Frame Relay (ANSI, CCITT and no LMI), with ARP support (no InARP).
-  Normal (routed) and Ethernet-bridged (Ethernet device emulation)
-  interfaces can share a single PVC.
-- raw HDLC - either IP (IPv4) interface or Ethernet device emulation.
-- Cisco HDLC,
-- PPP (uses syncppp.c),
-- X.25 (uses X.25 routines).
+1. Frame Relay (ANSI, CCITT, Cisco and no LMI).
+   - Normal (routed) and Ethernet-bridged (Ethernet device emulation)
+     interfaces can share a single PVC.
+   - ARP support (no InARP support in the kernel - there is an
+     experimental InARP user-space daemon available on:
+     http://www.kernel.org/pub/linux/utils/net/hdlc/).
+2. raw HDLC - either IP (IPv4) interface or Ethernet device emulation.
+3. Cisco HDLC.
+4. PPP (uses syncppp.c).
+5. X.25 (uses X.25 routines).
 
-There are hardware drivers for the following cards:
-- C101 by Moxa Technologies Co., Ltd.
-- RISCom/N2 by SDL Communications Inc.
-- and others, some not in the official kernel.
+Generic HDLC is a protocol driver only - it needs a low-level driver
+for your particular hardware.
 
 Ethernet device emulation (using HDLC or Frame-Relay PVC) is compatible
 with IEEE 802.1Q (VLANs) and 802.1D (Ethernet bridging).
@@ -24,7 +24,7 @@
 Make sure the hdlc.o and the hardware driver are loaded. It should
 create a number of "hdlc" (hdlc0 etc) network devices, one for each
 WAN port. You'll need the "sethdlc" utility, get it from:
-	http://hq.pm.waw.pl/hdlc/
+	http://www.kernel.org/pub/linux/utils/net/hdlc/
 
 Compile sethdlc.c utility:
 	gcc -O2 -Wall -o sethdlc sethdlc.c
@@ -52,12 +52,12 @@
 * v35 | rs232 | x21 | t1 | e1 - sets physical interface for a given port
                                 if the card has software-selectable interfaces
   loopback - activate hardware loopback (for testing only)
-* clock ext - external clock (uses DTE RX and TX clock)
-* clock int - internal clock (provides clock signal on DCE clock output)
-* clock txint - TX internal, RX external (provides TX clock on DCE output)
-* clock txfromrx - TX clock derived from RX clock (TX clock on DCE output)
-* rate - sets clock rate in bps (not required for external clock or
-                                 for txfromrx)
+* clock ext - both RX clock and TX clock external
+* clock int - both RX clock and TX clock internal
+* clock txint - RX clock external, TX clock internal
+* clock txfromrx - RX clock external, TX clock derived from RX clock
+* rate - sets clock rate in bps (for "int" or "txint" clock only)
+
 
 Setting protocol:
 
@@ -79,7 +79,7 @@
 * x25 - sets X.25 mode
 
 * fr - Frame Relay mode
-  lmi ansi / ccitt / none - LMI (link management) type
+  lmi ansi / ccitt / cisco / none - LMI (link management) type
   dce - Frame Relay DCE (network) side LMI instead of default DTE (user).
   It has nothing to do with clocks!
   t391 - link integrity verification polling timer (in seconds) - user
@@ -119,13 +119,14 @@
 
 
 
-If you have a problem with N2 or C101 card, you can issue the "private"
-command to see port's packet descriptor rings (in kernel logs):
+If you have a problem with N2, C101 or PLX200SYN card, you can issue the
+"private" command to see port's packet descriptor rings (in kernel logs):
 
 	sethdlc hdlc0 private
 
-The hardware driver has to be build with CONFIG_HDLC_DEBUG_RINGS.
+The hardware driver has to be build with #define DEBUG_RINGS.
 Attaching this info to bug reports would be helpful. Anyway, let me know
 if you have problems using this.
 
-For patches and other info look at http://hq.pm.waw.pl/hdlc/
+For patches and other info look at:
+<http://www.kernel.org/pub/linux/utils/net/hdlc/>.
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index a2c893a..ab65714 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -304,57 +304,6 @@
 	changed would be a Beowulf compute cluster.
 	Default: 0
 
-tcp_westwood - BOOLEAN
-        Enable TCP Westwood+ congestion control algorithm.
-	TCP Westwood+ is a sender-side only modification of the TCP Reno 
-	protocol stack that optimizes the performance of TCP congestion 
-	control. It is based on end-to-end bandwidth estimation to set 
-	congestion window and slow start threshold after a congestion 
-	episode. Using this estimation, TCP Westwood+ adaptively sets a 
-	slow start threshold and a congestion window which takes into 
-	account the bandwidth used  at the time congestion is experienced. 
-	TCP Westwood+ significantly increases fairness wrt TCP Reno in 
-	wired networks and throughput over wireless links.   
-        Default: 0
-
-tcp_vegas_cong_avoid - BOOLEAN
-	Enable TCP Vegas congestion avoidance algorithm.
-	TCP Vegas is a sender-side only change to TCP that anticipates
-	the onset of congestion by estimating the bandwidth. TCP Vegas
-	adjusts the sending rate by modifying the congestion
-	window. TCP Vegas should provide less packet loss, but it is
-	not as aggressive as TCP Reno.
-	Default:0
-
-tcp_bic - BOOLEAN
-	Enable BIC TCP congestion control algorithm.
-	BIC-TCP is a sender-side only change that ensures a linear RTT
-	fairness under large windows while offering both scalability and
-	bounded TCP-friendliness. The protocol combines two schemes
-	called additive increase and binary search increase. When the
-	congestion window is large, additive increase with a large
-	increment ensures linear RTT fairness as well as good
-	scalability. Under small congestion windows, binary search
-	increase provides TCP friendliness.
-	Default: 0
-
-tcp_bic_low_window - INTEGER
-	Sets the threshold window (in packets) where BIC TCP starts to
-	adjust the congestion window. Below this threshold BIC TCP behaves
-	the same as the default TCP Reno. 
-	Default: 14
-
-tcp_bic_fast_convergence - BOOLEAN
-	Forces BIC TCP to more quickly respond to changes in congestion
-	window. Allows two flows sharing the same connection to converge
-	more rapidly.
-	Default: 1
-
-tcp_default_win_scale - INTEGER
-	Sets the minimum window scale TCP will negotiate for on all
-	conections.
-	Default: 7
-
 tcp_tso_win_divisor - INTEGER
        This allows control over what percentage of the congestion window
        can be consumed by a single TSO frame.
@@ -368,6 +317,11 @@
 	where packet loss is typically due to random radio interference
 	rather than intermediate router congestion.
 
+tcp_congestion_control - STRING
+	Set the congestion control algorithm to be used for new
+	connections. The algorithm "reno" is always available, but
+	additional choices may be available based on kernel configuration.
+
 somaxconn - INTEGER
 	Limit of socket listen() backlog, known in userspace as SOMAXCONN.
 	Defaults to 128.  See also tcp_max_syn_backlog for additional tuning
diff --git a/Documentation/networking/multicast.txt b/Documentation/networking/multicast.txt
index 5049a64..b06c8c6 100644
--- a/Documentation/networking/multicast.txt
+++ b/Documentation/networking/multicast.txt
@@ -47,7 +47,6 @@
 ni65		YES		YES		YES		Software(#)
 seeq		NO		NO		NO		N/A
 sgiseek		<------------------ Buggy ------------------>
-sk_g16		NO		NO		YES		N/A
 smc-ultra	YES		YES		YES		Hardware
 sunlance	YES		YES		YES		Hardware
 tulip		YES		YES		YES		Hardware
diff --git a/Documentation/networking/net-modules.txt b/Documentation/networking/net-modules.txt
index 3830a83..0b27863 100644
--- a/Documentation/networking/net-modules.txt
+++ b/Documentation/networking/net-modules.txt
@@ -284,9 +284,6 @@
 seeq8005.c: *Not modularized*
 	(Probes ports: 0x300, 0x320, 0x340, 0x360)
 
-sk_g16.c: *Not modularized*
-	(Probes ports: 0x100, 0x180, 0x208, 0x220m 0x288, 0x320, 0x328, 0x390)
-
 skeleton.c: *Skeleton*
 
 slhc.c:
diff --git a/Documentation/networking/tcp.txt b/Documentation/networking/tcp.txt
index 7174900..0fa3004 100644
--- a/Documentation/networking/tcp.txt
+++ b/Documentation/networking/tcp.txt
@@ -1,5 +1,72 @@
-How the new TCP output machine [nyi] works.
+TCP protocol
+============
 
+Last updated: 21 June 2005
+
+Contents
+========
+
+- Congestion control
+- How the new TCP output machine [nyi] works
+
+Congestion control
+==================
+
+The following variables are used in the tcp_sock for congestion control:
+snd_cwnd		The size of the congestion window
+snd_ssthresh		Slow start threshold. We are in slow start if
+			snd_cwnd is less than this.
+snd_cwnd_cnt		A counter used to slow down the rate of increase
+			once we exceed slow start threshold.
+snd_cwnd_clamp		This is the maximum size that snd_cwnd can grow to.
+snd_cwnd_stamp		Timestamp for when congestion window last validated.
+snd_cwnd_used		Used as a highwater mark for how much of the
+			congestion window is in use. It is used to adjust
+			snd_cwnd down when the link is limited by the
+			application rather than the network.
+
+As of 2.6.13, Linux supports pluggable congestion control algorithms.
+A congestion control mechanism can be registered through functions in
+tcp_cong.c. The functions used by the congestion control mechanism are
+registered via passing a tcp_congestion_ops struct to
+tcp_register_congestion_control. As a minimum name, ssthresh,
+cong_avoid, min_cwnd must be valid.
+
+Private data for a congestion control mechanism is stored in tp->ca_priv.
+tcp_ca(tp) returns a pointer to this space.  This is preallocated space - it
+is important to check the size of your private data will fit this space, or
+alternatively space could be allocated elsewhere and a pointer to it could
+be stored here.
+
+There are three kinds of congestion control algorithms currently: The
+simplest ones are derived from TCP reno (highspeed, scalable) and just
+provide an alternative the congestion window calculation. More complex
+ones like BIC try to look at other events to provide better
+heuristics.  There are also round trip time based algorithms like
+Vegas and Westwood+.
+
+Good TCP congestion control is a complex problem because the algorithm
+needs to maintain fairness and performance. Please review current
+research and RFC's before developing new modules.
+
+The method that is used to determine which congestion control mechanism is
+determined by the setting of the sysctl net.ipv4.tcp_congestion_control.
+The default congestion control will be the last one registered (LIFO);
+so if you built everything as modules. the default will be reno. If you
+build with the default's from Kconfig, then BIC will be builtin (not a module)
+and it will end up the default.
+
+If you really want a particular default value then you will need
+to set it with the sysctl.  If you use a sysctl, the module will be autoloaded
+if needed and you will get the expected protocol. If you ask for an
+unknown congestion method, then the sysctl attempt will fail.
+
+If you remove a tcp congestion control module, then you will get the next
+available one. Since reno can not be built as a module, and can not be
+deleted, it will always be available.
+
+How the new TCP output machine [nyi] works.
+===========================================
 
 Data is kept on a single queue. The skb->users flag tells us if the frame is
 one that has been queued already. To add a frame we throw it on the end. Ack
diff --git a/Documentation/networking/vortex.txt b/Documentation/networking/vortex.txt
index fa12a9e..80e1cb1 100644
--- a/Documentation/networking/vortex.txt
+++ b/Documentation/networking/vortex.txt
@@ -12,7 +12,7 @@
 Please report problems to one or more of:
 
   Andrew Morton <andrewm@uow.edu.au>
-  Netdev mailing list <netdev@oss.sgi.com>
+  Netdev mailing list <netdev@vger.kernel.org>
   Linux kernel mailing list <linux-kernel@vger.kernel.org>
 
 Please note the 'Reporting and Diagnosing Problems' section at the end
diff --git a/Documentation/networking/wanpipe.txt b/Documentation/networking/wanpipe.txt
deleted file mode 100644
index aea20cd..0000000
--- a/Documentation/networking/wanpipe.txt
+++ /dev/null
@@ -1,622 +0,0 @@
-------------------------------------------------------------------------------
-Linux WAN Router Utilities Package
-------------------------------------------------------------------------------
-Version 2.2.1 
-Mar 28, 2001
-Author: Nenad Corbic <ncorbic@sangoma.com>
-Copyright (c) 1995-2001 Sangoma Technologies Inc.
-------------------------------------------------------------------------------
-
-INTRODUCTION
-
-Wide Area Networks (WANs) are used to interconnect Local Area Networks (LANs)
-and/or stand-alone hosts over vast distances with data transfer rates
-significantly higher than those achievable with commonly used dial-up
-connections.
-
-Usually an external device called `WAN router' sitting on your local network
-or connected to your machine's serial port provides physical connection to
-WAN.  Although router's job may be as simple as taking your local network
-traffic, converting it to WAN format and piping it through the WAN link, these
-devices are notoriously expensive, with prices as much as 2 - 5 times higher
-then the price of a typical PC box.
-
-Alternatively, considering robustness and multitasking capabilities of Linux,
-an internal router can be built (most routers use some sort of stripped down
-Unix-like operating system anyway). With a number of relatively inexpensive WAN
-interface cards available on the market, a perfectly usable router can be
-built for less than half a price of an external router.  Yet a Linux box
-acting as a router can still be used for other purposes, such as fire-walling,
-running FTP, WWW or DNS server, etc.
-
-This kernel module introduces the notion of a WAN Link Driver (WLD) to Linux
-operating system and provides generic hardware-independent services for such
-drivers.  Why can existing Linux network device interface not be used for
-this purpose?  Well, it can.  However, there are a few key differences between
-a typical network interface (e.g. Ethernet) and a WAN link.
-
-Many WAN protocols, such as X.25 and frame relay, allow for multiple logical
-connections (known as `virtual circuits' in X.25 terminology) over a single
-physical link.  Each such virtual circuit may (and almost always does) lead
-to a different geographical location and, therefore, different network.  As a
-result, it is the virtual circuit, not the physical link, that represents a
-route and, therefore, a network interface in Linux terms.
-
-To further complicate things, virtual circuits are usually volatile in nature
-(excluding so called `permanent' virtual circuits or PVCs).  With almost no
-time required to set up and tear down a virtual circuit, it is highly desirable
-to implement on-demand connections in order to minimize network charges.  So
-unlike a typical network driver, the WAN driver must be able to handle multiple
-network interfaces and cope as multiple virtual circuits come into existence
-and go away dynamically.
- 
-Last, but not least, WAN configuration is much more complex than that of say
-Ethernet and may well amount to several dozens of parameters.  Some of them
-are "link-wide"  while others are virtual circuit-specific.  The same holds
-true for WAN statistics which is by far more extensive and extremely useful
-when troubleshooting WAN connections.  Extending the ifconfig utility to suit
-these needs may be possible, but does not seem quite reasonable.  Therefore, a
-WAN configuration utility and corresponding application programmer's interface
-is needed for this purpose.
-
-Most of these problems are taken care of by this module.  Its goal is to
-provide a user with more-or-less standard look and feel for all WAN devices and
-assist a WAN device driver writer by providing common services, such as:
-
- o User-level interface via /proc file system
- o Centralized configuration
- o Device management (setup, shutdown, etc.)
- o Network interface management (dynamic creation/destruction)
- o Protocol encapsulation/decapsulation
-
-To ba able to use the Linux WAN Router you will also need a WAN Tools package
-available from
-
-	ftp.sangoma.com/pub/linux/current_wanpipe/wanpipe-X.Y.Z.tgz
-
-where vX.Y.Z represent the wanpipe version number.
-
-For technical questions and/or comments please e-mail to ncorbic@sangoma.com.
-For general inquiries please contact Sangoma Technologies Inc. by
-
-	Hotline:	1-800-388-2475	(USA and Canada, toll free)
-	Phone:		(905) 474-1990  ext: 106
-	Fax:		(905) 474-9223
-	E-mail:		dm@sangoma.com	(David Mandelstam)
-	WWW:		http://www.sangoma.com
-
-
-INSTALLATION
-
-Please read the WanpipeForLinux.pdf manual on how to 
-install the WANPIPE tools and drivers properly. 
-
-
-After installing wanpipe package: /usr/local/wanrouter/doc. 
-On the ftp.sangoma.com : /linux/current_wanpipe/doc
-
-
-COPYRIGHT AND LICENSING INFORMATION
-
-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.
-
-
-
-ACKNOWLEDGEMENTS
-
-This product is based on the WANPIPE(tm) Multiprotocol WAN Router developed
-by Sangoma Technologies Inc. for Linux 2.0.x and 2.2.x.  Success of the WANPIPE
-together with the next major release of Linux kernel in summer 1996 commanded
-adequate changes to the WANPIPE code to take full advantage of new Linux
-features.
-
-Instead of continuing developing proprietary interface tied to Sangoma WAN
-cards, we decided to separate all hardware-independent code into a separate
-module and defined two levels of interfaces - one for user-level applications
-and another for kernel-level WAN drivers.  WANPIPE is now implemented as a
-WAN driver compliant with the WAN Link Driver interface.  Also a general
-purpose WAN configuration utility and a set of shell scripts was developed to 
-support WAN router at the user level.
-
-Many useful ideas concerning hardware-independent interface implementation
-were given by Mike McLagan <mike.mclagan@linux.org> and his implementation
-of the Frame Relay router and drivers for Sangoma cards (dlci/sdla).
-
-With the new implementation of the APIs being incorporated into the WANPIPE,
-a special thank goes to Alan Cox in providing insight into BSD sockets.
-
-Special thanks to all the WANPIPE users who performed field-testing, reported
-bugs and made valuable comments and suggestions that help us to improve this
-product.
-
-
-
-NEW IN THIS RELEASE
-
-	o Updated the WANCFG utility
-		Calls the pppconfig to configure the PPPD
-		for async connections.
-
-	o Added the PPPCONFIG utility
-		Used to configure the PPPD dameon for the
-		WANPIPE Async PPP and standard serial port.
-		The wancfg calls the pppconfig to configure
-		the pppd.
-
-	o Fixed the PCI autodetect feature.  
-		The SLOT 0 was used as an autodetect option
-		however, some high end PC's slot numbers start
-		from 0. 
-
-	o This release has been tested with the new backupd
-	  daemon release.
-	
-
-PRODUCT COMPONENTS AND RELATED FILES
-
-/etc: (or user defined)
-	wanpipe1.conf	default router configuration file
-
-/lib/modules/X.Y.Z/misc:
-	wanrouter.o	router kernel loadable module
-	af_wanpipe.o	wanpipe api socket module
-
-/lib/modules/X.Y.Z/net:
-	sdladrv.o	Sangoma SDLA support module
-	wanpipe.o	Sangoma WANPIPE(tm) driver module
-
-/proc/net/wanrouter
-	Config		reads current router configuration
-	Status		reads current router status
-	{name}		reads WAN driver statistics
-
-/usr/sbin:
-	wanrouter	wanrouter start-up script
-	wanconfig	wanrouter configuration utility
-	sdladump	WANPIPE adapter memory dump utility
-        fpipemon        Monitor for Frame Relay
-        cpipemon        Monitor for Cisco HDLC
-	ppipemon 	Monitor for PPP
-	xpipemon 	Monitor for X25
-	wpkbdmon        WANPIPE keyboard led monitor/debugger
-
-/usr/local/wanrouter:
-	README		this file
-	COPYING		GNU General Public License
-	Setup		installation script
-	Filelist	distribution definition file
-	wanrouter.rc	meta-configuration file 
-			(used by the Setup and wanrouter script)
-
-/usr/local/wanrouter/doc:
-	wanpipeForLinux.pdf 	WAN Router User's Manual
-
-/usr/local/wanrouter/patches:
-	wanrouter-v2213.gz  	patch for Linux kernels 2.2.11 up to 2.2.13.
-	wanrouter-v2214.gz	patch for Linux kernel 2.2.14. 
-	wanrouter-v2215.gz	patch for Linux kernels 2.2.15 to 2.2.17.
-	wanrouter-v2218.gz	patch for Linux kernels 2.2.18 and up.
-	wanrouter-v240.gz	patch for Linux kernel 2.4.0.  
-	wanrouter-v242.gz	patch for Linux kernel 2.4.2 and up.
-	wanrouter-v2034.gz	patch for Linux kernel 2.0.34
-	wanrouter-v2036.gz 	patch for Linux kernel 2.0.36 and up. 
-
-/usr/local/wanrouter/patches/kdrivers:
-	Sources of the latest WANPIPE device drivers.
-	These are used to UPGRADE the linux kernel to the newest
-	version if the kernel source has already been pathced with
-	WANPIPE drivers.
-
-/usr/local/wanrouter/samples:
-	interface	sample interface configuration file
-	wanpipe1.cpri 	CHDLC primary port
-     	wanpipe2.csec 	CHDLC secondary port
-     	wanpipe1.fr   	Frame Relay protocol
-     	wanpipe1.ppp  	PPP protocol ) 
-	wanpipe1.asy	CHDLC ASYNC protocol
-	wanpipe1.x25	X25 protocol
-	wanpipe1.stty	Sync TTY driver (Used by Kernel PPPD daemon)
-	wanpipe1.atty	Async TTY driver (Used by Kernel PPPD daemon)
-	wanrouter.rc	sample meta-configuration file
-
-/usr/local/wanrouter/util:
-	*		wan-tools utilities source code
-
-/usr/local/wanrouter/api/x25:
-	*		x25 api sample programs.
-/usr/local/wanrouter/api/chdlc:
-	*		chdlc api sample programs.
-/usr/local/wanrouter/api/fr:
-	*		fr api sample programs.
-/usr/local/wanrouter/config/wancfg:
-	wancfg		WANPIPE GUI configuration program.
-                        Creates wanpipe#.conf files. 
-/usr/local/wanrouter/config/cfgft1:
-	cfgft1		GUI CSU/DSU configuration program.
-
-/usr/include/linux:
-	wanrouter.h	router API definitions
-	wanpipe.h	WANPIPE API definitions
-	sdladrv.h	SDLA support module API definitions
-	sdlasfm.h	SDLA firmware module definitions
-	if_wanpipe.h	WANPIPE Socket definitions
-	if_wanpipe_common.h	WANPIPE Socket/Driver common definitions.
-	sdlapci.h	WANPIPE PCI definitions
-	
-
-/usr/src/linux/net/wanrouter:
-	*		wanrouter source code
-
-/var/log:
-	wanrouter	wanrouter start-up log (created by the Setup script)
-
-/var/lock:  (or /var/lock/subsys for RedHat)
-	wanrouter	wanrouter lock file (created by the Setup script)
-
-/usr/local/wanrouter/firmware:
-	fr514.sfm	Frame relay firmware for Sangoma S508/S514 card
-	cdual514.sfm	Dual Port Cisco HDLC firmware for Sangoma S508/S514 card
-	ppp514.sfm      PPP Firmware for Sangoma S508 and S514 cards
-	x25_508.sfm	X25 Firmware for Sangoma S508 card.
-
-
-REVISION HISTORY
-
-1.0.0	December 31, 1996	Initial version
-
-1.0.1	January 30, 1997	Status and statistics can be read via /proc
-				filesystem entries.
-
-1.0.2   April 30, 1997          Added UDP management via monitors.
-
-1.0.3	June 3, 1997		UDP management for multiple boards using Frame
-				Relay and PPP
-				Enabled continuous transmission of Configure 
-				Request Packet for PPP (for 508 only)
-				Connection Timeout for PPP changed from 900 to 0
-				Flow Control Problem fixed for Frame Relay
-
-1.0.4	July 10, 1997		S508/FT1 monitoring capability in fpipemon and
-				ppipemon utilities.
-				Configurable TTL for UDP packets.
-				Multicast and Broadcast IP source addresses are
-				silently discarded.
-
-1.0.5	July 28, 1997		Configurable T391,T392,N391,N392,N393 for Frame
-				Relay in router.conf.
-				Configurable Memory Address through router.conf 
-				for Frame Relay, PPP and X.25. (commenting this
- 				out enables auto-detection).
-				Fixed freeing up received buffers using kfree()
- 				for Frame Relay and X.25.
-				Protect sdla_peek() by calling save_flags(),
-				cli() and restore_flags().
-				Changed number of Trace elements from 32 to 20
-				Added DLCI specific data monitoring in FPIPEMON. 
-2.0.0	Nov 07, 1997		Implemented protection of RACE conditions by 
-				critical flags for FRAME RELAY and PPP.
-				DLCI List interrupt mode implemented.
-				IPX support in FRAME RELAY and PPP.
-				IPX Server Support (MARS)
-				More driver specific stats included in FPIPEMON
-				and PIPEMON.
-
-2.0.1	Nov 28, 1997		Bug Fixes for version 2.0.0.
-				Protection of "enable_irq()" while 
-				"disable_irq()" has been enabled from any other
-				routine (for Frame Relay, PPP and X25).
-				Added additional Stats for Fpipemon and Ppipemon
-				Improved Load Sharing for multiple boards
-
-2.0.2	Dec 09, 1997		Support for PAP and CHAP for ppp has been
-				implemented.
-
-2.0.3	Aug 15, 1998		New release supporting Cisco HDLC, CIR for Frame
-				relay, Dynamic IP assignment for PPP and Inverse
-				Arp support for Frame-relay.  Man Pages are 
-				included for better support and a new utility
-				for configuring FT1 cards.
-
-2.0.4	Dec 09, 1998	        Dual Port support for Cisco HDLC.
-				Support for HDLC (LAPB) API.
-				Supports BiSync Streaming code for S502E 
-				and S503 cards.
-				Support for Streaming HDLC API.
-				Provides a BSD socket interface for 
-				creating applications using BiSync
-   				streaming.        
-
-2.0.5   Aug 04, 1999 		CHDLC initializatin bug fix.
-				PPP interrupt driven driver: 
-  				Fix to the PPP line hangup problem.
-				New PPP firmware
-				Added comments to the startup SYSTEM ERROR messages
-				Xpipemon debugging application for the X25 protocol
-				New USER_MANUAL.txt
-				Fixed the odd boundary 4byte writes to the board.
-				BiSync Streaming code has been taken out.  
-				 Available as a patch.
-				Streaming HDLC API has been taken out.  
-				 Available as a patch.                 
-
-2.0.6   Aug 17, 1999		Increased debugging in statup scripts
-				Fixed insallation bugs from 2.0.5
-				Kernel patch works for both 2.2.10 and 2.2.11 kernels.
-				There is no functional difference between the two packages         
-
-2.0.7   Aug 26, 1999		o  Merged X25API code into WANPIPE.
-				o  Fixed a memeory leak for X25API
-				o  Updated the X25API code for 2.2.X kernels.
-				o  Improved NEM handling.   
-
-2.1.0	Oct 25, 1999		o New code for S514 PCI Card
-				o New CHDLC and Frame Relay drivers
-				o PPP and X25 are not supported in this release    
-
-2.1.1	Nov 30, 1999		o PPP support for S514 PCI Cards
-
-2.1.3   Apr 06, 2000		o Socket based x25api 
-				o Socket based chdlc api
-				o Socket based fr api
-				o Dual Port Receive only CHDLC support.
-				o Asynchronous CHDLC support (Secondary Port)
-				o cfgft1 GUI csu/dsu configurator
-				o wancfg GUI configuration file 
-				  configurator.
-				o Architectual directory changes.
-
-beta-2.1.4 Jul 2000		o Dynamic interface configuration:
-					Network interfaces reflect the state
-					of protocol layer.  If the protocol becomes
-					disconnected, driver will bring down
-					the interface.  Once the protocol reconnects
-					the interface will be brought up. 
-					
-					Note: This option is turned off by default.
-
-				o Dynamic wanrouter setup using 'wanconfig':
-					wanconfig utility can be used to
-					shutdown,restart,start or reconfigure 
-					a virtual circuit dynamically.
-				     
-					Frame Relay:  Each DLCI can be: 
-						      created,stopped,restarted and reconfigured
-						      dynamically using wanconfig.
-					
-						      ex: wanconfig card wanpipe1 dev wp1_fr16 up
-				  
-				o Wanrouter startup via command line arguments:
-					wanconfig also supports wanrouter startup via command line
-					arguments.  Thus, there is no need to create a wanpipe#.conf
-					configuration file.  
-
-				o Socket based x25api update/bug fixes.
-					Added support for LCN numbers greater than 255.
-					Option to pass up modem messages.
-					Provided a PCI IRQ check, so a single S514
-					card is guaranteed to have a non-sharing interrupt.
-
-				o Fixes to the wancfg utility.
-				o New FT1 debugging support via *pipemon utilities.
-				o Frame Relay ARP support Enabled.
-
-beta3-2.1.4 Jul 2000		o X25 M_BIT Problem fix.
-				o Added the Multi-Port PPP
-				  Updated utilites for the Multi-Port PPP.
-
-2.1.4	Aut 2000
-				o In X25API:
-					Maximum packet an application can send
-					to the driver has been extended to 4096 bytes.
-
-					Fixed the x25 startup bug. Enable 
-					communications only after all interfaces
-					come up.  HIGH SVC/PVC is used to calculate
-					the number of channels.
-					Enable protocol only after all interfaces
-					are enabled.
-
-				o Added an extra state to the FT1 config, kernel module.
-				o Updated the pipemon debuggers.
-
-				o Blocked the Multi-Port PPP from running on kernels
-				  2.2.16 or greater, due to syncppp kernel module
-				  change. 
-	  
-beta1-2.1.5 	Nov 15 2000
-				o Fixed the MulitPort PPP Support for kernels 2.2.16 and above.
-				  2.2.X kernels only
-
-				o Secured the driver UDP debugging calls
-					- All illegal netowrk debugging calls are reported to
-					  the log.
-					- Defined a set of allowed commands, all other denied.
-					
-				o Cpipemon
-					- Added set FT1 commands to the cpipemon. Thus CSU/DSU
-					  configuraiton can be performed using cpipemon.
-					  All systems that cannot run cfgft1 GUI utility should
-					  use cpipemon to configure the on board CSU/DSU.
-
-
-				o Keyboard Led Monitor/Debugger
-					- A new utilty /usr/sbin/wpkbdmon uses keyboard leds
-					  to convey operatinal statistic information of the 
-					  Sangoma WANPIPE cards.
-					NUM_LOCK    = Line State  (On=connected,    Off=disconnected)
-					CAPS_LOCK   = Tx data     (On=transmitting, Off=no tx data)
-					SCROLL_LOCK = Rx data     (On=receiving,    Off=no rx data
-					
-				o Hardware probe on module load and dynamic device allocation
-					- During WANPIPE module load, all Sangoma cards are probed
-					  and found information is printed in the /var/log/messages.
-					- If no cards are found, the module load fails.
-					- Appropriate number of devices are dynamically loaded 
-					  based on the number of Sangoma cards found.
-
-					  Note: The kernel configuraiton option 
-						CONFIG_WANPIPE_CARDS has been taken out.
-					
-				o Fixed the Frame Relay and Chdlc network interfaces so they are
-				  compatible with libpcap libraries.  Meaning, tcpdump, snort,
-				  ethereal, and all other packet sniffers and debuggers work on
-				  all WANPIPE netowrk interfaces.
-					- Set the network interface encoding type to ARPHRD_PPP.
-					  This tell the sniffers that data obtained from the
-					  network interface is in pure IP format.
-				  Fix for 2.2.X kernels only.
-				
-				o True interface encoding option for Frame Relay and CHDLC
-					- The above fix sets the network interface encoding
-					  type to ARPHRD_PPP, however some customers use
-					  the encoding interface type to determine the
-					  protocol running.  Therefore, the TURE ENCODING
-					  option will set the interface type back to the
-					  original value.  
-
-					  NOTE: If this option is used with Frame Relay and CHDLC
-						libpcap library support will be broken.  
-						i.e. tcpdump will not work.
-					Fix for 2.2.x Kernels only.
-						
-				o Ethernet Bridgind over Frame Relay
-					- The Frame Relay bridging has been developed by 
-					  Kristian Hoffmann and Mark Wells.  
-					- The Linux kernel bridge is used to send ethernet 
-					  data over the frame relay links.
-					For 2.2.X Kernels only.
-
-				o Added extensive 2.0.X support. Most new features of
-				  2.1.5 for protocols Frame Relay, PPP and CHDLC are
-				  supported under 2.0.X kernels. 
-
-beta1-2.2.0 	Dec 30 2000
-				o Updated drivers for 2.4.X kernels.
-				o Updated drivers for SMP support.
-				o X25API is now able to share PCI interrupts.
-				o Took out a general polling routine that was used
-				  only by X25API. 
-				o Added appropriate locks to the dynamic reconfiguration
-				  code.
-				o Fixed a bug in the keyboard debug monitor.
-
-beta2-2.2.0	Jan 8 2001
-				o Patches for 2.4.0 kernel
-				o Patches for 2.2.18 kernel
-				o Minor updates to PPP and CHLDC drivers.
-				  Note: No functinal difference. 
-
-beta3-2.2.9	Jan 10 2001
-				o I missed the 2.2.18 kernel patches in beta2-2.2.0
-				  release.  They are included in this release.
-
-Stable Release
-2.2.0		Feb 01 2001
-				o Bug fix in wancfg GUI configurator.
-					The edit function didn't work properly.
-
-
-bata1-2.2.1	Feb 09 2001
-			o WANPIPE TTY Driver emulation. 
-			  Two modes of operation Sync and Async.
-				Sync: Using the PPPD daemon, kernel SyncPPP layer
-				      and the Wanpipe sync TTY driver: a PPP protocol 
-				      connection can be established via Sangoma adapter, over
-				      a T1 leased line.
-			
-				      The 2.4.0 kernel PPP layer supports MULTILINK
-				      protocol, that can be used to bundle any number of Sangoma
-				      adapters (T1 lines) into one, under a single IP address.
-				      Thus, efficiently obtaining multiple T1 throughput. 
-
-				      NOTE: The remote side must also implement MULTILINK PPP
-					    protocol.
-
-				Async:Using the PPPD daemon, kernel AsyncPPP layer
-				      and the WANPIPE async TTY driver: a PPP protocol
-				      connection can be established via Sangoma adapter and
-				      a modem, over a telephone line.
-
-				      Thus, the WANPIPE async TTY driver simulates a serial
-				      TTY driver that would normally be used to interface the 
-				      MODEM to the linux kernel.
-				
-			o WANPIPE PPP Backup Utility
-				This utility will monitor the state of the PPP T1 line.
-				In case of failure, a dial up connection will be established
-				via pppd daemon, ether via a serial tty driver (serial port), 
-				or a WANPIPE async TTY driver (in case serial port is unavailable).
-				
-				Furthermore, while in dial up mode, the primary PPP T1 link
-				will be monitored for signs of life.  
-
-				If the PPP T1 link comes back to life, the dial up connection
-				will be shutdown and T1 line re-established.
-			
-
-			o New Setup installation script.
-				Option to UPGRADE device drivers if the kernel source has
-				already been patched with WANPIPE.
-
-				Option to COMPILE WANPIPE modules against the currently 
-				running kernel, thus no need for manual kernel and module
-				re-compilatin.
-			
-			o Updates and Bug Fixes to wancfg utility.
-
-bata2-2.2.1	Feb 20 2001
-
-			o Bug fixes to the CHDLC device drivers.
-				The driver had compilation problems under kernels
-				2.2.14 or lower.
-
-			o Bug fixes to the Setup installation script.
-				The device drivers compilation options didn't work
-				properly.
-
-			o Update to the wpbackupd daemon.  
-				Optimized the cross-over times, between the primary
-				link and the backup dialup.
-
-beta3-2.2.1	Mar 02 2001
-			o Patches for 2.4.2 kernel.
-
-			o Bug fixes to util/ make files.
-			o Bug fixes to the Setup installation script.
-
-			o Took out the backupd support and made it into
-			  as separate package.
-			  
-beta4-2.2.1     Mar 12 2001
-
-		o Fix to the Frame Relay Device driver.
-			IPSAC sends a packet of zero length
-			header to the frame relay driver.  The
-			driver tries to push its own 2 byte header
-			into the packet, which causes the driver to
-			crash.
-
-		o Fix the WANPIPE re-configuration code.
-			Bug was found by trying to run  the cfgft1 while the
-			interface was already running.  
-
-		o Updates to cfgft1.
-			Writes a wanpipe#.cfgft1 configuration file
-			once the CSU/DSU is configured. This file can
-			holds the current CSU/DSU configuration.
-
-
-
->>>>>> END OF README <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
-
-
diff --git a/Documentation/power/kernel_threads.txt b/Documentation/power/kernel_threads.txt
index 60b5481..fb57784 100644
--- a/Documentation/power/kernel_threads.txt
+++ b/Documentation/power/kernel_threads.txt
@@ -12,8 +12,7 @@
 	do {
 		hub_events();
 		wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list));
-		if (current->flags & PF_FREEZE)
-			refrigerator(PF_FREEZE);
+		try_to_freeze();
 	} while (!signal_pending(current));
 
 from drivers/usb/core/hub.c::hub_thread()
diff --git a/Documentation/power/pci.txt b/Documentation/power/pci.txt
index 35b1a7d..6fc9d51 100644
--- a/Documentation/power/pci.txt
+++ b/Documentation/power/pci.txt
@@ -291,6 +291,44 @@
 pci_enable_wake (one for both D3hot and D3cold).
 
 
+A reference implementation
+-------------------------
+.suspend()
+{
+	/* driver specific operations */
+
+	/* Disable IRQ */
+	free_irq();
+	/* If using MSI */
+	pci_disable_msi();
+
+	pci_save_state();
+	pci_enable_wake();
+	/* Disable IO/bus master/irq router */
+	pci_disable_device();
+	pci_set_power_state(pci_choose_state());
+}
+
+.resume()
+{
+	pci_set_power_state(PCI_D0);
+	pci_restore_state();
+	/* device's irq possibly is changed, driver should take care */
+	pci_enable_device();
+	pci_set_master();
+
+	/* if using MSI, device's vector possibly is changed */
+	pci_enable_msi();
+
+	request_irq();
+	/* driver specific operations; */
+}
+
+This is a typical implementation. Drivers can slightly change the order
+of the operations in the implementation, ignore some operations or add
+more deriver specific operations in it, but drivers should do something like
+this on the whole.
+
 5. Resources
 ~~~~~~~~~~~~
 
diff --git a/Documentation/power/swsusp.txt b/Documentation/power/swsusp.txt
index c7c3459..7a6b789 100644
--- a/Documentation/power/swsusp.txt
+++ b/Documentation/power/swsusp.txt
@@ -164,11 +164,11 @@
 should be held at that point and it must be safe to sleep there), and
 add:
 
-            if (current->flags & PF_FREEZE)
-                    refrigerator(PF_FREEZE);
+       try_to_freeze();
 
 If the thread is needed for writing the image to storage, you should
-instead set the PF_NOFREEZE process flag when creating the thread.
+instead set the PF_NOFREEZE process flag when creating the thread (and
+be very carefull).
 
 
 Q: What is the difference between between "platform", "shutdown" and
@@ -233,3 +233,81 @@
 cat `cat /proc/[0-9]*/maps | grep / | sed 's:.* /:/:' | sort -u` > /dev/null
 
 after resume. swapoff -a; swapon -a may also be usefull.
+
+Q: What happens to devices during swsusp? They seem to be resumed
+during system suspend?
+
+A: That's correct. We need to resume them if we want to write image to
+disk. Whole sequence goes like
+
+      Suspend part
+      ~~~~~~~~~~~~
+      running system, user asks for suspend-to-disk
+
+      user processes are stopped
+
+      suspend(PMSG_FREEZE): devices are frozen so that they don't interfere
+      		      with state snapshot
+
+      state snapshot: copy of whole used memory is taken with interrupts disabled
+
+      resume(): devices are woken up so that we can write image to swap
+
+      write image to swap
+
+      suspend(PMSG_SUSPEND): suspend devices so that we can power off
+
+      turn the power off
+
+      Resume part
+      ~~~~~~~~~~~
+      (is actually pretty similar)
+
+      running system, user asks for suspend-to-disk
+
+      user processes are stopped (in common case there are none, but with resume-from-initrd, noone knows)
+
+      read image from disk
+
+      suspend(PMSG_FREEZE): devices are frozen so that they don't interfere
+      		      with image restoration
+
+      image restoration: rewrite memory with image
+
+      resume(): devices are woken up so that system can continue
+
+      thaw all user processes
+
+Q: What is this 'Encrypt suspend image' for?
+
+A: First of all: it is not a replacement for dm-crypt encrypted swap.
+It cannot protect your computer while it is suspended. Instead it does
+protect from leaking sensitive data after resume from suspend.
+
+Think of the following: you suspend while an application is running
+that keeps sensitive data in memory. The application itself prevents
+the data from being swapped out. Suspend, however, must write these
+data to swap to be able to resume later on. Without suspend encryption
+your sensitive data are then stored in plaintext on disk.  This means
+that after resume your sensitive data are accessible to all
+applications having direct access to the swap device which was used
+for suspend. If you don't need swap after resume these data can remain
+on disk virtually forever. Thus it can happen that your system gets
+broken in weeks later and sensitive data which you thought were
+encrypted and protected are retrieved and stolen from the swap device.
+To prevent this situation you should use 'Encrypt suspend image'.
+
+During suspend a temporary key is created and this key is used to
+encrypt the data written to disk. When, during resume, the data was
+read back into memory the temporary key is destroyed which simply
+means that all data written to disk during suspend are then
+inaccessible so they can't be stolen later on.  The only thing that
+you must then take care of is that you call 'mkswap' for the swap
+partition used for suspend as early as possible during regular
+boot. This asserts that any temporary key from an oopsed suspend or
+from a failed or aborted resume is erased from the swap device.
+
+As a rule of thumb use encrypted swap to protect your data while your
+system is shut down or suspended. Additionally use the encrypted
+suspend image to prevent sensitive data from being stolen after
+resume.
diff --git a/Documentation/power/video.txt b/Documentation/power/video.txt
index 6873435..881a37e 100644
--- a/Documentation/power/video.txt
+++ b/Documentation/power/video.txt
@@ -83,8 +83,10 @@
 Compaq Evo N620c		vga=normal, s3_bios (2)
 Dell 600m, ATI R250 Lf		none (1), but needs xorg-x11-6.8.1.902-1
 Dell D600, ATI RV250            vga=normal and X, or try vbestate (6)
+Dell D610			vga=normal and X (possibly vbestate (6) too, but not tested)
 Dell Inspiron 4000		??? (*)
 Dell Inspiron 500m		??? (*)
+Dell Inspiron 510m		???
 Dell Inspiron 600m		??? (*)
 Dell Inspiron 8200		??? (*)
 Dell Inspiron 8500		??? (*)
@@ -123,6 +125,7 @@
 Toshiba Satellite 4080XCDT      s3_mode (3)
 Toshiba Satellite 4090XCDT      ??? (*)
 Toshiba Satellite P10-554       s3_bios,s3_mode (4)(****)
+Toshiba M30                     (2) xor X with nvidia driver using internal AGP
 Uniwill 244IIO			??? (*)
 
 
diff --git a/Documentation/power/video_extension.txt b/Documentation/power/video_extension.txt
index 8e33d7c..b2f9b15 100644
--- a/Documentation/power/video_extension.txt
+++ b/Documentation/power/video_extension.txt
@@ -1,13 +1,16 @@
-This driver implement the ACPI Extensions For Display Adapters
-for integrated graphics devices on motherboard, as specified in
-ACPI 2.0 Specification, Appendix B, allowing to perform some basic
-control like defining the video POST device, retrieving EDID information
-or to setup a video output, etc.  Note that this is an ref. implementation only.
-It may or may not work for your integrated video device.
+ACPI video extensions
+~~~~~~~~~~~~~~~~~~~~~
+
+This driver implement the ACPI Extensions For Display Adapters for
+integrated graphics devices on motherboard, as specified in ACPI 2.0
+Specification, Appendix B, allowing to perform some basic control like
+defining the video POST device, retrieving EDID information or to
+setup a video output, etc.  Note that this is an ref. implementation
+only.  It may or may not work for your integrated video device.
 
 Interfaces exposed to userland through /proc/acpi/video:
 
-VGA/info : display the supported video bus device capability like ,Video ROM, CRT/LCD/TV.
+VGA/info : display the supported video bus device capability like Video ROM, CRT/LCD/TV.
 VGA/ROM :  Used to get a copy of the display devices' ROM data (up to 4k).
 VGA/POST_info : Used to determine what options are implemented.
 VGA/POST : Used to get/set POST device.
@@ -15,7 +18,7 @@
 	Please refer ACPI spec B.4.1 _DOS
 VGA/CRT : CRT output
 VGA/LCD : LCD output
-VGA/TV : TV output 
+VGA/TVO : TV output
 VGA/*/brightness : Used to get/set brightness of output device
 
 Notify event through /proc/acpi/event:
diff --git a/Documentation/s390/CommonIO b/Documentation/s390/CommonIO
index a831d9a..59d1166 100644
--- a/Documentation/s390/CommonIO
+++ b/Documentation/s390/CommonIO
@@ -30,7 +30,7 @@
   device numbers (0xabcd or abcd, for 2.4 backward compatibility).
   You can use the 'all' keyword to ignore all devices.
   The '!' operator will cause the I/O-layer to _not_ ignore a device.
-  The order on the command line is not important.
+  The command line is parsed from left to right.
 
   For example, 
 	cio_ignore=0.0.0023-0.0.0042,0.0.4711
@@ -72,13 +72,14 @@
   /proc/cio_ignore; "add <device range>, <device range>, ..." will ignore the
   specified devices.
 
-  Note: Already known devices cannot be ignored.
+  Note: While already known devices can be added to the list of devices to be
+        ignored, there will be no effect on then. However, if such a device
+        disappears and then reappeares, it will then be ignored.
 
-  For example, if device 0.0.abcd is already known and all other devices
-  0.0.a000-0.0.afff are not known,
+  For example,
 	"echo add 0.0.a000-0.0.accc, 0.0.af00-0.0.afff > /proc/cio_ignore"
-  will add 0.0.a000-0.0.abcc, 0.0.abce-0.0.accc and 0.0.af00-0.0.afff to the
-  list of ignored devices and skip 0.0.abcd.
+  will add 0.0.a000-0.0.accc and 0.0.af00-0.0.afff to the list of ignored
+  devices.
 
   The devices can be specified either by bus id (0.0.abcd) or, for 2.4 backward
   compatibilty, by the device number in hexadecimal (0xabcd or abcd).
@@ -98,7 +99,8 @@
 
   - /proc/s390dbf/cio_trace/hex_ascii
     Logs the calling of functions in the common I/O-layer and, if applicable, 
-    which subchannel they were called for.
+    which subchannel they were called for, as well as dumps of some data
+    structures (like irb in an error case).
 
   The level of logging can be changed to be more or less verbose by piping to 
   /proc/s390dbf/cio_*/level a number between 0 and 6; see the documentation on
diff --git a/Documentation/s390/s390dbf.txt b/Documentation/s390/s390dbf.txt
index 2d1cd93..e24fdea 100644
--- a/Documentation/s390/s390dbf.txt
+++ b/Documentation/s390/s390dbf.txt
@@ -12,8 +12,8 @@
 One purpose of this is to inspect the debug logs after a production system crash
 in order to analyze the reason for the crash.
 If the system still runs but only a subcomponent which uses dbf failes,
-it is possible to look at the debug logs on a live system via the Linux proc
-filesystem.
+it is possible to look at the debug logs on a live system via the Linux
+debugfs filesystem.
 The debug feature may also very useful for kernel and driver development.
 
 Design:
@@ -52,16 +52,18 @@
 - Flag, if entry is an exception or not
 
 The debug logs can be inspected in a live system through entries in
-the proc-filesystem. Under the path /proc/s390dbf there is 
+the debugfs-filesystem. Under the toplevel directory "s390dbf" there is
 a directory for each registered component, which is named like the
-corresponding component.
+corresponding component. The debugfs normally should be mounted to
+/sys/kernel/debug therefore the debug feature can be accessed unter
+/sys/kernel/debug/s390dbf.
 
 The content of the directories are files which represent different views
 to the debug log. Each component can decide which views should be
 used through registering them with the function debug_register_view().
 Predefined views for hex/ascii, sprintf and raw binary data are provided.
 It is also possible to define other views. The content of
-a view can be inspected simply by reading the corresponding proc file.
+a view can be inspected simply by reading the corresponding debugfs file.
 
 All debug logs have an an actual debug level (range from 0 to 6).
 The default level is 3. Event and Exception functions have a 'level'
@@ -69,14 +71,14 @@
 than the actual level are written to the log. This means, when
 writing events, high priority log entries should have a low level
 value whereas low priority entries should have a high one.
-The actual debug level can be changed with the help of the proc-filesystem 
-through writing a number string "x" to the 'level' proc file which is
+The actual debug level can be changed with the help of the debugfs-filesystem
+through writing a number string "x" to the 'level' debugfs file which is
 provided for every debug log. Debugging can be switched off completely
-by using "-" on the 'level' proc file.
+by using "-" on the 'level' debugfs file.
 
 Example:
 
-> echo "-" > /proc/s390dbf/dasd/level
+> echo "-" > /sys/kernel/debug/s390dbf/dasd/level
 
 It is also possible to deactivate the debug feature globally for every
 debug log. You can change the behavior using  2 sysctl parameters in
@@ -99,11 +101,11 @@
 ------------------
 
 ----------------------------------------------------------------------------
-debug_info_t *debug_register(char *name, int pages_index, int nr_areas,
+debug_info_t *debug_register(char *name, int pages, int nr_areas,
                              int buf_size);
 
-Parameter:    name:        Name of debug log (e.g. used for proc entry) 
-              pages_index: 2^pages_index pages will be allocated per area
+Parameter:    name:        Name of debug log (e.g. used for debugfs entry)
+              pages:       number of pages, which will be allocated per area
               nr_areas:    number of debug areas
               buf_size:    size of data area in each debug entry
 
@@ -134,7 +136,7 @@
 Description:   Sets new actual debug level if new_level is valid. 
 
 ---------------------------------------------------------------------------
-+void debug_stop_all(void);
+void debug_stop_all(void);
 
 Parameter:     none
 
@@ -270,7 +272,7 @@
 Return Value:  0  : ok 
                < 0: Error 
 
-Description:   registers new debug view and creates proc dir entry 
+Description:   registers new debug view and creates debugfs dir entry
 
 ---------------------------------------------------------------------------
 int debug_unregister_view (debug_info_t * id, struct debug_view *view); 
@@ -281,7 +283,7 @@
 Return Value:  0  : ok 
                < 0: Error 
 
-Description:   unregisters debug view and removes proc dir entry 
+Description:   unregisters debug view and removes debugfs dir entry
 
 
 
@@ -308,7 +310,7 @@
 {
     /* register 4 debug areas with one page each and 4 byte data field */
 
-    debug_info = debug_register ("test", 0, 4, 4 );
+    debug_info = debug_register ("test", 1, 4, 4 );
     debug_register_view(debug_info,&debug_hex_ascii_view);
     debug_register_view(debug_info,&debug_raw_view);
 
@@ -343,7 +345,7 @@
     /* register 4 debug areas with one page each and data field for */
     /* format string pointer + 2 varargs (= 3 * sizeof(long))       */
 
-    debug_info = debug_register ("test", 0, 4, sizeof(long) * 3);
+    debug_info = debug_register ("test", 1, 4, sizeof(long) * 3);
     debug_register_view(debug_info,&debug_sprintf_view);
 
     debug_sprintf_event(debug_info, 2 , "first event in %s:%i\n",__FILE__,__LINE__);
@@ -362,16 +364,16 @@
 
 
 
-ProcFS Interface
+Debugfs Interface
 ----------------
 Views to the debug logs can be investigated through reading the corresponding 
-proc-files:
+debugfs-files:
 
 Example:
 
-> ls /proc/s390dbf/dasd
-flush  hex_ascii  level      raw 
-> cat /proc/s390dbf/dasd/hex_ascii | sort +1
+> ls /sys/kernel/debug/s390dbf/dasd
+flush  hex_ascii  level pages raw
+> cat /sys/kernel/debug/s390dbf/dasd/hex_ascii | sort +1
 00 00974733272:680099 2 - 02 0006ad7e  07 ea 4a 90 | ....
 00 00974733272:682210 2 - 02 0006ade6  46 52 45 45 | FREE
 00 00974733272:682213 2 - 02 0006adf6  07 ea 4a 90 | ....
@@ -391,25 +393,36 @@
 Example:
 
 
-> cat /proc/s390dbf/dasd/level
+> cat /sys/kernel/debug/s390dbf/dasd/level
 3
-> echo "5" > /proc/s390dbf/dasd/level
-> cat /proc/s390dbf/dasd/level
+> echo "5" > /sys/kernel/debug/s390dbf/dasd/level
+> cat /sys/kernel/debug/s390dbf/dasd/level
 5
 
 Flushing debug areas
 --------------------
 Debug areas can be flushed with piping the number of the desired
-area (0...n) to the proc file "flush". When using "-" all debug areas
+area (0...n) to the debugfs file "flush". When using "-" all debug areas
 are flushed.
 
 Examples:
 
 1. Flush debug area 0:
-> echo "0" > /proc/s390dbf/dasd/flush  
+> echo "0" > /sys/kernel/debug/s390dbf/dasd/flush
 
 2. Flush all debug areas:
-> echo "-" > /proc/s390dbf/dasd/flush
+> echo "-" > /sys/kernel/debug/s390dbf/dasd/flush
+
+Changing the size of debug areas
+------------------------------------
+It is possible the change the size of debug areas through piping
+the number of pages to the debugfs file "pages". The resize request will
+also flush the debug areas.
+
+Example:
+
+Define 4 pages for the debug areas of debug feature "dasd":
+> echo "4" > /sys/kernel/debug/s390dbf/dasd/pages
 
 Stooping the debug feature
 --------------------------
@@ -491,7 +504,7 @@
 --------------
 
 Views are specified with the 'debug_view' structure. There are defined
-callback functions which are used for reading and writing the proc files:
+callback functions which are used for reading and writing the debugfs files:
 
 struct debug_view {
         char name[DEBUG_MAX_PROCF_LEN];  
@@ -525,7 +538,7 @@
 The "private_data" member can be used as pointer to view specific data.
 It is not used by the debug feature itself.
 
-The output when reading a debug-proc file is structured like this:
+The output when reading a debugfs file is structured like this:
 
 "prolog_proc output"
 
@@ -534,13 +547,13 @@
 "header_proc output 3"  "format_proc output 3"
 ...
 
-When a view is read from the proc fs, the Debug Feature calls the 
+When a view is read from the debugfs, the Debug Feature calls the
 'prolog_proc' once for writing the prolog.
 Then 'header_proc' and 'format_proc' are called for each 
 existing debug entry.
 
 The input_proc can be used to implement functionality when it is written to 
-the view (e.g. like with 'echo "0" > /proc/s390dbf/dasd/level).
+the view (e.g. like with 'echo "0" > /sys/kernel/debug/s390dbf/dasd/level).
 
 For header_proc there can be used the default function
 debug_dflt_header_fn() which is defined in in debug.h.
@@ -602,7 +615,7 @@
 debug_register_view(debug_info, &debug_test_view);
 for(i = 0; i < 10; i ++) debug_int_event(debug_info, 1, i);
 
-> cat /proc/s390dbf/test/myview
+> cat /sys/kernel/debug/s390dbf/test/myview
 00 00964419734:611402 1 - 00 88042ca   This error...........
 00 00964419734:611405 1 - 00 88042ca   That error...........
 00 00964419734:611408 1 - 00 88042ca   Problem..............
diff --git a/Documentation/scsi/ChangeLog.megaraid b/Documentation/scsi/ChangeLog.megaraid
index a9356c6..5331d91 100644
--- a/Documentation/scsi/ChangeLog.megaraid
+++ b/Documentation/scsi/ChangeLog.megaraid
@@ -1,3 +1,69 @@
+Release Date	: Mon Mar 07 12:27:22 EST 2005 - Seokmann Ju <sju@lsil.com>
+Current Version : 2.20.4.6 (scsi module), 2.20.2.6 (cmm module)
+Older Version	: 2.20.4.5 (scsi module), 2.20.2.5 (cmm module)
+
+1.	Added IOCTL backward compatibility.
+	Convert megaraid_mm driver to new compat_ioctl entry points.
+	I don't have easy access to hardware, so only compile tested.
+		- Signed-off-by:Andi Kleen <ak@muc.de>
+
+2.	megaraid_mbox fix: wrong order of arguments in memset()
+	That, BTW, shows why cross-builds are useful-the only indication of
+	problem had been a new warning showing up in sparse output on alpha
+	build (number of exceeding 256 got truncated).
+		- Signed-off-by: Al Viro
+		<viro@parcelfarce.linux.theplanet.co.uk>
+
+3.	Convert pci_module_init to pci_register_driver
+	Convert from pci_module_init to pci_register_driver
+	(from:http://kerneljanitors.org/TODO)
+		- Signed-off-by: Domen Puncer <domen@coderock.org>
+
+4.	Use the pre defined DMA mask constants from dma-mapping.h
+	Use the DMA_{64,32}BIT_MASK constants from dma-mapping.h when calling
+	pci_set_dma_mask() or pci_set_consistend_dma_mask(). See
+	http://marc.theaimsgroup.com/?t=108001993000001&r=1&w=2 for more
+	details.
+		Signed-off-by: Tobias Klauser <tklauser@nuerscht.ch>
+		Signed-off-by: Domen Puncer <domen@coderock.org>
+
+5.	Remove SSID checking for Dobson, Lindsay, and Verde based products.
+	Checking the SSVID/SSID for controllers which have Dobson, Lindsay,
+	and Verde is unnecessary because device ID has been assigned by LSI
+	and it is unique value. So, all controllers with these IOPs have to be
+	supported by the driver regardless SSVID/SSID.
+
+6.	Date Thu, 27 Jan 2005 04:31:09 +0100 
+	From Herbert Poetzl <> 
+	Subject RFC: assert_spin_locked() for 2.6 
+
+	Greetings!
+
+	overcautious programming will kill your kernel ;)
+	ever thought about checking a spin_lock or even
+	asserting that it must be held (maybe just for
+	spinlock debugging?) ...
+
+	there are several checks present in the kernel
+	where somebody does a variation on the following:
+
+	  BUG_ON(!spin_is_locked(&some_lock));
+
+	so what's wrong about that? nothing, unless you
+	compile the code with CONFIG_DEBUG_SPINLOCK but 
+	without CONFIG_SMP ... in which case the BUG()
+	will kill your kernel ...
+
+	maybe it's not advised to make such assertions, 
+	but here is a solution which works for me ...
+	(compile tested for sh, x86_64 and x86, boot/run
+	tested for x86 only)
+
+	best,
+	Herbert
+
+		- Herbert Poetzl <herbert@13thfloor.at>, Thu, 27 Jan 2005
+
 Release Date	: Thu Feb 03 12:27:22 EST 2005 - Seokmann Ju <sju@lsil.com>
 Current Version	: 2.20.4.5 (scsi module), 2.20.2.5 (cmm module)
 Older Version	: 2.20.4.4 (scsi module), 2.20.2.4 (cmm module)
diff --git a/Documentation/scsi/scsi-changer.txt b/Documentation/scsi/scsi-changer.txt
new file mode 100644
index 0000000..c132687
--- /dev/null
+++ b/Documentation/scsi/scsi-changer.txt
@@ -0,0 +1,180 @@
+
+README for the SCSI media changer driver
+========================================
+
+This is a driver for SCSI Medium Changer devices, which are listed
+with "Type: Medium Changer" in /proc/scsi/scsi.
+
+This is for *real* Jukeboxes.  It is *not* supported to work with
+common small CD-ROM changers, neither one-lun-per-slot SCSI changers
+nor IDE drives.
+
+Userland tools available from here:
+	http://linux.bytesex.org/misc/changer.html
+
+
+General Information
+-------------------
+
+First some words about how changers work: A changer has 2 (possibly
+more) SCSI ID's. One for the changer device which controls the robot,
+and one for the device which actually reads and writes the data. The
+later may be anything, a MOD, a CD-ROM, a tape or whatever. For the
+changer device this is a "don't care", he *only* shuffles around the
+media, nothing else.
+
+
+The SCSI changer model is complex, compared to - for example - IDE-CD
+changers. But it allows to handle nearly all possible cases. It knows
+4 different types of changer elements:
+
+  media transport - this one shuffles around the media, i.e. the
+                    transport arm.  Also known as "picker".
+  storage         - a slot which can hold a media.
+  import/export   - the same as above, but is accessable from outside,
+                    i.e. there the operator (you !) can use this to
+                    fill in and remove media from the changer.
+		    Sometimes named "mailslot".
+  data transfer   - this is the device which reads/writes, i.e. the
+		    CD-ROM / Tape / whatever drive.
+
+None of these is limited to one: A huge Jukebox could have slots for
+123 CD-ROM's, 5 CD-ROM readers (and therefore 6 SCSI ID's: the changer
+and each CD-ROM) and 2 transport arms. No problem to handle.
+
+
+How it is implemented
+---------------------
+
+I implemented the driver as character device driver with a NetBSD-like
+ioctl interface. Just grabbed NetBSD's header file and one of the
+other linux SCSI device drivers as starting point. The interface
+should be source code compatible with NetBSD. So if there is any
+software (anybody knows ???) which supports a BSDish changer driver,
+it should work with this driver too.
+
+Over time a few more ioctls where added, volume tag support for example
+wasn't covered by the NetBSD ioctl API.
+
+
+Current State
+-------------
+
+Support for more than one transport arm is not implemented yet (and
+nobody asked for it so far...).
+
+I test and use the driver myself with a 35 slot cdrom jukebox from
+Grundig.  I got some reports telling it works ok with tape autoloaders
+(Exabyte, HP and DEC).  Some People use this driver with amanda.  It
+works fine with small (11 slots) and a huge (4 MOs, 88 slots)
+magneto-optical Jukebox.  Probably with lots of other changers too, most
+(but not all :-) people mail me only if it does *not* work...
+
+I don't have any device lists, neither black-list nor white-list.  Thus
+it is quite useless to ask me whenever a specific device is supported or
+not.  In theory every changer device which supports the SCSI-2 media
+changer command set should work out-of-the-box with this driver.  If it
+doesn't, it is a bug.  Either within the driver or within the firmware
+of the changer device.
+
+
+Using it
+--------
+
+This is a character device with major number is 86, so use
+"mknod /dev/sch0 c 86 0" to create the special file for the driver.
+
+If the module finds the changer, it prints some messages about the
+device [ try "dmesg" if you don't see anything ] and should show up in
+/proc/devices. If not....  some changers use ID ? / LUN 0 for the
+device and ID ? / LUN 1 for the robot mechanism. But Linux does *not*
+look for LUN's other than 0 as default, becauce there are to many
+broken devices. So you can try:
+
+  1) echo "scsi add-single-device 0 0 ID 1" > /proc/scsi/scsi
+     (replace ID with the SCSI-ID of the device)
+  2) boot the kernel with "max_scsi_luns=1" on the command line
+     (append="max_scsi_luns=1" in lilo.conf should do the trick)
+
+
+Trouble?
+--------
+
+If you insmod the driver with "insmod debug=1", it will be verbose and
+prints a lot of stuff to the syslog.  Compiling the kernel with
+CONFIG_SCSI_CONSTANTS=y improves the quality of the error messages alot
+because the kernel will translate the error codes into human-readable
+strings then.
+
+You can display these messages with the dmesg command (or check the
+logfiles).  If you email me some question becauce of a problem with the
+driver, please include these messages.
+
+
+Insmod options
+--------------
+
+debug=0/1
+	Enable debug messages (see above, default: 0).
+
+verbose=0/1
+	Be verbose (default: 1).
+
+init=0/1
+	Send INITIALIZE ELEMENT STATUS command to the changer
+	at insmod time (default: 1).
+
+timeout_init=<seconds>
+	timeout for the INITIALIZE ELEMENT STATUS command
+	(default: 3600).
+
+timeout_move=<seconds>
+	timeout for all other commands (default: 120).
+
+dt_id=<id1>,<id2>,...
+dt_lun=<lun1>,<lun2>,...
+	These two allow to specify the SCSI ID and LUN for the data
+	transfer elements.  You likely don't need this as the jukebox
+	should provide this information.  But some devices don't ...
+
+vendor_firsts=
+vendor_counts=
+vendor_labels=
+	These insmod options can be used to tell the driver that there
+	are some vendor-specific element types.  Grundig for example
+	does this.  Some jukeboxes have a printer to label fresh burned
+	CDs, which is addressed as element 0xc000 (type 5).  To tell the
+	driver about this vendor-specific element, use this:
+		$ insmod ch			\
+			vendor_firsts=0xc000	\
+			vendor_counts=1		\
+			vendor_labels=printer
+	All three insmod options accept up to four comma-separated
+	values, this way you can configure the element types 5-8.
+	You likely need the SCSI specs for the device in question to
+	find the correct values as they are not covered by the SCSI-2
+	standard.
+
+
+Credits
+-------
+
+I wrote this driver using the famous mailing-patches-around-the-world
+method.  With (more or less) help from:
+
+	Daniel Moehwald <moehwald@hdg.de>
+	Dane Jasper <dane@sonic.net>
+	R. Scott Bailey <sbailey@dsddi.eds.com>
+	Jonathan Corbet <corbet@lwn.net>
+
+Special thanks go to
+	Martin Kuehne <martin.kuehne@bnbt.de>
+for a old, second-hand (but full functional) cdrom jukebox which I use
+to develop/test driver and tools now.
+
+Have fun,
+
+   Gerd
+
+-- 
+Gerd Knorr <kraxel@bytesex.org>
diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt
index e41703d..da176c9 100644
--- a/Documentation/scsi/scsi_mid_low_api.txt
+++ b/Documentation/scsi/scsi_mid_low_api.txt
@@ -936,8 +936,7 @@
  *
  *      Returns SUCCESS if command aborted else FAILED
  *
- *      Locks: struct Scsi_Host::host_lock held (with irqsave) on entry 
- *      and assumed to be held on return.
+ *      Locks: None held
  *
  *      Calling context: kernel thread
  *
@@ -955,8 +954,7 @@
  *
  *      Returns SUCCESS if command aborted else FAILED
  *
- *      Locks: struct Scsi_Host::host_lock held (with irqsave) on entry 
- *      and assumed to be held on return.
+ *      Locks: None held
  *
  *      Calling context: kernel thread
  *
@@ -974,8 +972,7 @@
  *
  *      Returns SUCCESS if command aborted else FAILED
  *
- *      Locks: struct Scsi_Host::host_lock held (with irqsave) on entry
- *      and assumed to be held on return.
+ *      Locks: None held
  *
  *      Calling context: kernel thread
  *
@@ -993,8 +990,7 @@
  *
  *      Returns SUCCESS if command aborted else FAILED
  *
- *      Locks: struct Scsi_Host::host_lock held (with irqsave) on entry
- *      and assumed to be held on return.
+ *      Locks: None held
  *
  *      Calling context: kernel thread
  *
diff --git a/Documentation/sgi-ioc4.txt b/Documentation/sgi-ioc4.txt
new file mode 100644
index 0000000..876c96a
--- /dev/null
+++ b/Documentation/sgi-ioc4.txt
@@ -0,0 +1,45 @@
+The SGI IOC4 PCI device is a bit of a strange beast, so some notes on
+it are in order.
+
+First, even though the IOC4 performs multiple functions, such as an
+IDE controller, a serial controller, a PS/2 keyboard/mouse controller,
+and an external interrupt mechanism, it's not implemented as a
+multifunction device.  The consequence of this from a software
+standpoint is that all these functions share a single IRQ, and
+they can't all register to own the same PCI device ID.  To make
+matters a bit worse, some of the register blocks (and even registers
+themselves) present in IOC4 are mixed-purpose between these several
+functions, meaning that there's no clear "owning" device driver.
+
+The solution is to organize the IOC4 driver into several independent
+drivers, "ioc4", "sgiioc4", and "ioc4_serial".  Note that there is no
+PS/2 controller driver as this functionality has never been wired up
+on a shipping IO card.
+
+ioc4
+====
+This is the core (or shim) driver for IOC4.  It is responsible for
+initializing the basic functionality of the chip, and allocating
+the PCI resources that are shared between the IOC4 functions.
+
+This driver also provides registration functions that the other
+IOC4 drivers can call to make their presence known.  Each driver
+needs to provide a probe and remove function, which are invoked
+by the core driver at appropriate times.  The interface of these
+IOC4 function probe and remove operations isn't precisely the same
+as PCI device probe and remove operations, but is logically the
+same operation.
+
+sgiioc4
+=======
+This is the IDE driver for IOC4.  Its name isn't very descriptive
+simply for historical reasons (it used to be the only IOC4 driver
+component).  There's not much to say about it other than it hooks
+up to the ioc4 driver via the appropriate registration, probe, and
+remove functions.
+
+ioc4_serial
+===========
+This is the serial driver for IOC4.  There's not much to say about it
+other than it hooks up to the ioc4 driver via the appropriate registration,
+probe, and remove functions.
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 71ef049..104a994 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -615,9 +615,11 @@
   Module snd-hda-intel
   --------------------
 
-    Module for Intel HD Audio (ICH6, ICH6M, ICH7)
+    Module for Intel HD Audio (ICH6, ICH6M, ICH7), ATI SB450,
+	       VIA VT8251/VT8237A
 
     model	- force the model name
+    position_fix - Fix DMA pointer (0 = FIFO size, 1 = none, 2 = POSBUF)
 
     Module supports up to 8 cards.
 
@@ -635,6 +637,10 @@
 	  5stack	5-jack in back, 2-jack in front
 	  5stack-digout	5-jack in back, 2-jack in front, a SPDIF out
 	  w810		3-jack
+	  z71v		3-jack (HP shared SPDIF)
+	  asus		3-jack
+	  uniwill	3-jack
+	  F1734		2-jack
 
 	CMI9880
 	  minimal	3-jack in back
@@ -642,6 +648,15 @@
 	  full		6-jack in back, 2-jack in front
 	  full_dig	6-jack in back, 2-jack in front, SPDIF I/O
 	  allout	5-jack in back, 2-jack in front, SPDIF out
+	  auto		auto-config reading BIOS (default)
+
+    Note 2: If you get click noises on output, try the module option
+	    position_fix=1 or 2.  position_fix=1 will use the SD_LPIB
+	    register value without FIFO size correction as the current
+	    DMA pointer.  position_fix=2 will make the driver to use
+	    the position buffer instead of reading SD_LPIB register.
+	    (Usually SD_LPLIB register is more accurate than the
+	    position buffer.)
 
   Module snd-hdsp
   ---------------
@@ -660,7 +675,19 @@
           module did formerly.  It will allocate the buffers in advance
           when any HDSP cards are found.  To make the buffer
           allocation sure, load snd-page-alloc module in the early
-          stage of boot sequence.
+          stage of boot sequence.  See "Early Buffer Allocation"
+	  section.
+
+  Module snd-hdspm
+  ----------------
+
+    Module for RME HDSP MADI board.
+
+    precise_ptr		- Enable precise pointer, or disable.
+    line_outs_monitor	- Send playback streams to analog outs by default.
+    enable_monitor	- Enable Analog Out on Channel 63/64 by default.
+
+    See hdspm.txt for details.
 
   Module snd-ice1712
   ------------------
@@ -677,15 +704,19 @@
                         * TerraTec EWS 88D
                         * TerraTec EWX 24/96
                         * TerraTec DMX 6Fire
+			* TerraTec Phase 88
                         * Hoontech SoundTrack DSP 24
                         * Hoontech SoundTrack DSP 24 Value
                         * Hoontech SoundTrack DSP 24 Media 7.1
+			* Event Electronics, EZ8
                         * Digigram VX442
+			* Lionstracs, Mediastaton
 
     model       - Use the given board model, one of the following:
 		  delta1010, dio2496, delta66, delta44, audiophile, delta410,
 		  delta1010lt, vx442, ewx2496, ews88mt, ews88mt_new, ews88d,
-		  dmx6fire, dsp24, dsp24_value, dsp24_71, ez8
+		  dmx6fire, dsp24, dsp24_value, dsp24_71, ez8,
+		  phase88, mediastation
     omni	- Omni I/O support for MidiMan M-Audio Delta44/66
     cs8427_timeout - reset timeout for the CS8427 chip (S/PDIF transciever)
                      in msec resolution, default value is 500 (0.5 sec)
@@ -694,20 +725,46 @@
     is not used with all Envy24 based cards (for example in the MidiMan Delta
     serie).
 
+    Note: The supported board is detected by reading EEPROM or PCI
+	  SSID (if EEPROM isn't available).  You can override the
+	  model by passing "model" module option in case that the
+	  driver isn't configured properly or you want to try another
+	  type for testing.
+
   Module snd-ice1724
   ------------------
 
-    Module for Envy24HT (VT/ICE1724) based PCI sound cards.
+    Module for Envy24HT (VT/ICE1724), Envy24PT (VT1720) based PCI sound cards.
 			* MidiMan M Audio Revolution 7.1
 			* AMP Ltd AUDIO2000
-			* TerraTec Aureon Sky-5.1, Space-7.1
+			* TerraTec Aureon 5.1 Sky
+			* TerraTec Aureon 7.1 Space
+			* TerraTec Aureon 7.1 Universe
+			* TerraTec Phase 22
+			* TerraTec Phase 28
+			* AudioTrak Prodigy 7.1
+			* AudioTrak Prodigy 192
+			* Pontis MS300
+			* Albatron K8X800 Pro II 
+			* Chaintech ZNF3-150
+			* Chaintech ZNF3-250
+			* Chaintech 9CJS
+			* Chaintech AV-710
+			* Shuttle SN25P
 
     model       - Use the given board model, one of the following:
-		  revo71, amp2000, prodigy71, aureon51, aureon71,
-		  k8x800
+		  revo71, amp2000, prodigy71, prodigy192, aureon51,
+		  aureon71, universe, k8x800, phase22, phase28, ms300,
+		  av710
 
     Module supports up to 8 cards and autoprobe.
 
+    Note: The supported board is detected by reading EEPROM or PCI
+	  SSID (if EEPROM isn't available).  You can override the
+	  model by passing "model" module option in case that the
+	  driver isn't configured properly or you want to try another
+	  type for testing.
+
   Module snd-intel8x0
   -------------------
 
@@ -1026,7 +1083,8 @@
           module did formerly.  It will allocate the buffers in advance
           when any RME9652 cards are found.  To make the buffer
           allocation sure, load snd-page-alloc module in the early
-          stage of boot sequence.
+          stage of boot sequence.  See "Early Buffer Allocation"
+	  section.
 
   Module snd-sa11xx-uda1341 (on arm only)
   ---------------------------------------
@@ -1211,16 +1269,18 @@
   ------------------
 
     Module for AC'97 motherboards based on VIA 82C686A/686B, 8233,
-    8233A, 8233C, 8235 (south) bridge.
+    8233A, 8233C, 8235, 8237 (south) bridge.
 
     mpu_port	- 0x300,0x310,0x320,0x330, otherwise obtain BIOS setup
 		  [VIA686A/686B only]
     joystick	- Enable joystick (default off) [VIA686A/686B only]
     ac97_clock	- AC'97 codec clock base (default 48000Hz)
     dxs_support	- support DXS channels,
-		  0 = auto (defalut), 1 = enable, 2 = disable,
-		  3 = 48k only, 4 = no VRA
-		  [VIA8233/C,8235 only]
+		  0 = auto (default), 1 = enable, 2 = disable,
+		  3 = 48k only, 4 = no VRA, 5 = enable any sample
+		  rate and different sample rates on different
+		  channels
+		  [VIA8233/C, 8235, 8237 only]
     ac97_quirk  - AC'97 workaround for strange hardware
                   See the description of intel8x0 module for details.
 
@@ -1232,18 +1292,23 @@
           default value 1.4.  Then the interrupt number will be
           assigned under 15. You might also upgrade your BIOS.
     
-    Note: VIA8233/5 (not VIA8233A) can support DXS (direct sound)
+    Note: VIA8233/5/7 (not VIA8233A) can support DXS (direct sound)
 	  channels as the first PCM.  On these channels, up to 4
-	  streams can be played at the same time.
+	  streams can be played at the same time, and the controller
+	  can perform sample rate conversion with separate rates for
+	  each channel.
 	  As default (dxs_support = 0), 48k fixed rate is chosen
 	  except for the known devices since the output is often
 	  noisy except for 48k on some mother boards due to the
 	  bug of BIOS.
-	  Please try once dxs_support=1 and if it works on other
+	  Please try once dxs_support=5 and if it works on other
 	  sample rates (e.g. 44.1kHz of mp3 playback), please let us
 	  know the PCI subsystem vendor/device id's (output of
 	  "lspci -nv").
-	  If it doesn't work, try dxs_support=4.  If it still doesn't
+	  If dxs_support=5 does not work, try dxs_support=4; if it
+	  doesn't work too, try dxs_support=1.  (dxs_support=1 is
+	  usually for old motherboards.  The correct implementated
+	  board should work with 4 or 5.)  If it still doesn't
 	  work and the default setting is ok, dxs_support=3 is the
 	  right choice.  If the default setting doesn't work at all,
 	  try dxs_support=2 to disable the DXS channels.
@@ -1497,6 +1562,36 @@
 	   echo "rvplayer 0 0 block" > /proc/asound/card0/pcm0p/oss
 
 
+Early Buffer Allocation
+=======================
+
+Some drivers (e.g. hdsp) require the large contiguous buffers, and
+sometimes it's too late to find such spaces when the driver module is
+actually loaded due to memory fragmentation.  You can pre-allocate the
+PCM buffers by loading snd-page-alloc module and write commands to its
+proc file in prior, for example, in the early boot stage like
+/etc/init.d/*.local scripts.
+
+Reading the proc file /proc/drivers/snd-page-alloc shows the current
+usage of page allocation.  In writing, you can send the following
+commands to the snd-page-alloc driver:
+
+  - add VENDOR DEVICE MASK SIZE BUFFERS
+
+    VENDOR and DEVICE are PCI vendor and device IDs.  They take
+    integer numbers (0x prefix is needed for the hex).
+    MASK is the PCI DMA mask.  Pass 0 if not restricted.
+    SIZE is the size of each buffer to allocate.  You can pass
+    k and m suffix for KB and MB.  The max number is 16MB.
+    BUFFERS is the number of buffers to allocate.  It must be greater
+    than 0.  The max number is 4.
+
+  - erase
+
+    This will erase the all pre-allocated buffers which are not in
+    use.
+
+
 Links
 =====
 
diff --git a/Documentation/sound/alsa/CMIPCI.txt b/Documentation/sound/alsa/CMIPCI.txt
index 4a7df77..1872e24 100644
--- a/Documentation/sound/alsa/CMIPCI.txt
+++ b/Documentation/sound/alsa/CMIPCI.txt
@@ -89,19 +89,22 @@
 
 There are some control switchs affecting to the speaker connections:
 
-"Line-In As Rear"	- As mentioned above, the line-in jack is used
-	for the rear (3th and 4th channels) output.
-"Line-In As Bass"	- The line-in jack is used for the bass (5th
-	and 6th channels) output.
-"Mic As Center/LFE"	- The mic jack is used for the bass output.
-	If this switch is on, you cannot use a microphone as a capture
-	source, of course.
-
+"Line-In Mode"	- an enum control to change the behavior of line-in
+	jack.  Either "Line-In", "Rear Output" or "Bass Output" can
+	be selected.  The last item is available only with model 039
+	or newer. 
+	When "Rear Output" is chosen, the surround channels 3 and 4
+	are output to line-in jack.
+"Mic-In Mode"	- an enum control to change the behavior of mic-in
+	jack.  Either "Mic-In" or "Center/LFE Output" can be
+	selected. 
+	When "Center/LFE Output" is chosen, the center and bass
+	channels (channels 5 and 6) are output to mic-in jack. 
 
 Digital I/O
 -----------
 
-The CM8x38 provides the excellent SPDIF capability with very chip
+The CM8x38 provides the excellent SPDIF capability with very cheap
 price (yes, that's the reason I bought the card :)
 
 The SPDIF playback and capture are done via the third PCM device
@@ -122,8 +125,9 @@
 simultaneously.
 
 To enable SPDIF output, you need to turn on "IEC958 Output Switch"
-control via mixer or alsactl.  Then you'll see the red light on from
-the card so you know that's working obviously :)
+control via mixer or alsactl ("IEC958" is the official name of
+so-called S/PDIF).  Then you'll see the red light on from the card so
+you know that's working obviously :)
 The SPDIF input is always enabled, so you can hear SPDIF input data
 from line-out with "IEC958 In Monitor" switch at any time (see
 below).
@@ -205,9 +209,10 @@
 MIDI CONTROLLER
 ---------------
 
-The MPU401-UART interface is enabled as default only for the first
-(CMIPCI) card.  You need to set module option "midi_port" properly
-for the 2nd (CMIPCI) card.
+The MPU401-UART interface is disabled as default.  You need to set
+module option "mpu_port" with a valid I/O port address to enable the
+MIDI support.  The valid I/O ports are 0x300, 0x310, 0x320 and 0x330.
+Choose the value which doesn't conflict with other cards.
 
 There is _no_ hardware wavetable function on this chip (except for
 OPL3 synth below).
@@ -229,9 +234,11 @@
 Joystick and Modem
 ------------------
 
-The joystick and modem should be available by enabling the control
-switch "Joystick" and "Modem" respectively.  But I myself have never
-tested them yet.
+The legacy joystick is supported.  To enable the joystick support, pass
+joystick_port=1 module option.  The value 1 means the auto-detection.
+If the auto-detection fails, try to pass the exact I/O address.
+
+The modem is enabled dynamically via a card control switch "Modem".
 
 
 Debugging Information
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index e789475..db0b7d2 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -371,7 +371,7 @@
           <listitem><para>create <function>probe()</function> callback.</para></listitem>
           <listitem><para>create <function>remove()</function> callback.</para></listitem>
           <listitem><para>create pci_driver table which contains the three pointers above.</para></listitem>
-          <listitem><para>create <function>init()</function> function just calling <function>pci_module_init()</function> to register the pci_driver table defined above.</para></listitem>
+          <listitem><para>create <function>init()</function> function just calling <function>pci_register_driver()</function> to register the pci_driver table defined above.</para></listitem>
           <listitem><para>create <function>exit()</function> function to call <function>pci_unregister_driver()</function> function.</para></listitem>
         </itemizedlist>
       </para>
@@ -1198,7 +1198,7 @@
   /* initialization of the module */
   static int __init alsa_card_mychip_init(void)
   {
-          return pci_module_init(&driver);
+          return pci_register_driver(&driver);
   }
 
   /* clean up the module */
@@ -1654,7 +1654,7 @@
 <![CDATA[
   static int __init alsa_card_mychip_init(void)
   {
-          return pci_module_init(&driver);
+          return pci_register_driver(&driver);
   }
 
   static void __exit alsa_card_mychip_exit(void)
diff --git a/Documentation/sound/alsa/emu10k1-jack.txt b/Documentation/sound/alsa/emu10k1-jack.txt
new file mode 100644
index 0000000..751d450
--- /dev/null
+++ b/Documentation/sound/alsa/emu10k1-jack.txt
@@ -0,0 +1,74 @@
+This document is a guide to using the emu10k1 based devices with JACK for low
+latency, multichannel recording functionality.  All of my recent work to allow
+Linux users to use the full capabilities of their hardware has been inspired 
+by the kX Project.  Without their work I never would have discovered the true
+power of this hardware.
+
+	http://www.kxproject.com
+						- Lee Revell, 2005.03.30
+
+Low latency, multichannel audio with JACK and the emu10k1/emu10k2
+-----------------------------------------------------------------
+
+Until recently, emu10k1 users on Linux did not have access to the same low
+latency, multichannel features offered by the "kX ASIO" feature of their
+Windows driver.  As of ALSA 1.0.9 this is no more!
+
+For those unfamiliar with kX ASIO, this consists of 16 capture and 16 playback
+channels.  With a post 2.6.9 Linux kernel, latencies down to 64 (1.33 ms) or
+even 32 (0.66ms) frames should work well.
+
+The configuration is slightly more involved than on Windows, as you have to
+select the correct device for JACK to use.  Actually, for qjackctl users it's
+fairly self explanatory - select Duplex, then for capture and playback select
+the multichannel devices, set the in and out channels to 16, and the sample
+rate to 48000Hz.  The command line looks like this:
+
+/usr/local/bin/jackd -R -dalsa -r48000 -p64 -n2 -D -Chw:0,2 -Phw:0,3 -S
+
+This will give you 16 input ports and 16 output ports.
+
+The 16 output ports map onto the 16 FX buses (or the first 16 of 64, for the
+Audigy).  The mapping from FX bus to physical output is described in
+SB-Live-mixer.txt (or Audigy-mixer.txt).
+
+The 16 input ports are connected to the 16 physical inputs.  Contrary to
+popular belief, all emu10k1 cards are multichannel cards.  Which of these
+input channels have physical inputs connected to them depends on the card
+model.  Trial and error is highly recommended; the pinout diagrams
+for the card have been reverse engineered by some enterprising kX users and are 
+available on the internet.  Meterbridge is helpful here, and the kX forums are
+packed with useful information.
+
+Each input port will either correspond to a digital (SPDIF) input, an analog
+input, or nothing.  The one exception is the SBLive! 5.1.  On these devices,
+the second and third input ports are wired to the center/LFE output.  You will
+still see 16 capture channels, but only 14 are available for recording inputs.
+
+This chart, borrowed from kxfxlib/da_asio51.cpp, describes the mapping of JACK
+ports to FXBUS2 (multitrack recording input) and EXTOUT (physical output)
+channels.
+
+/*JACK (& ASIO) mappings on 10k1 5.1 SBLive cards:
+--------------------------------------------
+JACK		Epilog		FXBUS2(nr)
+--------------------------------------------
+capture_1	asio14		FXBUS2(0xe)
+capture_2	asio15		FXBUS2(0xf)
+capture_3	asio0		FXBUS2(0x0)	
+~capture_4	Center		EXTOUT(0x11)	// mapped to by Center
+~capture_5	LFE		EXTOUT(0x12)	// mapped to by LFE
+capture_6	asio3		FXBUS2(0x3)
+capture_7	asio4		FXBUS2(0x4)
+capture_8	asio5		FXBUS2(0x5)
+capture_9	asio6		FXBUS2(0x6)
+capture_10	asio7		FXBUS2(0x7)
+capture_11	asio8		FXBUS2(0x8)
+capture_12	asio9		FXBUS2(0x9)
+capture_13	asio10		FXBUS2(0xa)
+capture_14	asio11		FXBUS2(0xb)
+capture_15	asio12		FXBUS2(0xc)
+capture_16	asio13		FXBUS2(0xd)
+*/
+
+TODO: describe use of ld10k1/qlo10k1 in conjunction with JACK
diff --git a/Documentation/sound/alsa/hdspm.txt b/Documentation/sound/alsa/hdspm.txt
new file mode 100644
index 0000000..7a67ff7
--- /dev/null
+++ b/Documentation/sound/alsa/hdspm.txt
@@ -0,0 +1,362 @@
+Software Interface ALSA-DSP MADI Driver 
+
+(translated from German, so no good English ;-), 
+2004 - winfried ritsch
+
+
+
+ Full functionality has been added to the driver. Since some of
+ the Controls and startup-options  are ALSA-Standard and only the
+ special Controls are described and discussed below.
+
+
+ hardware functionality:
+
+   
+   Audio transmission:
+
+     number of channels --  depends on transmission mode
+
+		The number of channels chosen is from 1..Nmax. The reason to
+		use for a lower number of channels is only resource allocation,
+		since unused DMA channels are disabled and less memory is
+		allocated. So also the throughput of the PCI system can be
+		scaled. (Only important for low performance boards).
+
+       Single Speed -- 1..64 channels 
+
+		 (Note: Choosing the 56channel mode for transmission or as
+		 receiver, only 56 are transmitted/received over the MADI, but
+		 all 64 channels are available for the mixer, so channel count
+		 for the driver)
+
+       Double Speed -- 1..32 channels
+
+		 Note: Choosing the 56-channel mode for
+		 transmission/receive-mode , only 28 are transmitted/received
+		 over the MADI, but all 32 channels are available for the mixer,
+		 so channel count for the driver
+
+
+       Quad Speed -- 1..16 channels 
+
+		 Note: Choosing the 56-channel mode for
+		 transmission/receive-mode , only 14 are transmitted/received
+		 over the MADI, but all 16 channels are available for the mixer,
+		 so channel count for the driver
+
+     Format -- signed 32 Bit Little Endian (SNDRV_PCM_FMTBIT_S32_LE)
+
+     Sample Rates --
+
+       Single Speed -- 32000, 44100, 48000
+
+       Double Speed -- 64000, 88200, 96000 (untested)
+
+       Quad Speed -- 128000, 176400, 192000 (untested)
+
+     access-mode -- MMAP (memory mapped), Not interleaved
+     (PCM_NON-INTERLEAVED)
+
+     buffer-sizes -- 64,128,256,512,1024,2048,8192 Samples
+
+     fragments -- 2
+
+     Hardware-pointer -- 2 Modi
+
+
+		 The Card supports the readout of the actual Buffer-pointer,
+		 where DMA reads/writes. Since of the bulk mode of PCI it is only
+		 64 Byte accurate. SO it is not really usable for the
+		 ALSA-mid-level functions (here the buffer-ID gives a better
+		 result), but if MMAP is used by the application. Therefore it
+		 can be configured at load-time with the parameter
+		 precise-pointer.
+
+
+		 (Hint: Experimenting I found that the pointer is maximum 64 to
+		 large never to small. So if you subtract 64 you always have a
+		 safe pointer for writing, which is used on this mode inside
+		 ALSA. In theory now you can get now a latency as low as 16
+		 Samples, which is a quarter of the interrupt possibilities.)
+
+       Precise Pointer -- off
+					interrupt used for pointer-calculation
+
+       Precise Pointer -- on
+					hardware pointer used.
+
+   Controller:
+
+
+	  Since DSP-MADI-Mixer has 8152 Fader, it does not make sense to
+	  use the standard mixer-controls, since this would break most of
+	  (especially graphic) ALSA-Mixer GUIs. So Mixer control has be
+	  provided by a 2-dimensional controller using the
+	  hwdep-interface. 
+
+     Also all 128+256 Peak and RMS-Meter can be accessed via the
+     hwdep-interface. Since it could be a performance problem always
+     copying and converting Peak and RMS-Levels even if you just need
+     one, I decided to export the hardware structure, so that of
+     needed some driver-guru can implement a memory-mapping of mixer
+     or peak-meters over ioctl, or also to do only copying and no
+     conversion. A test-application shows the usage of the controller.
+
+    Latency Controls --- not implemented !!!
+
+
+	   Note: Within the windows-driver the latency is accessible of a
+	   control-panel, but buffer-sizes are controlled with ALSA from
+	   hwparams-calls and should not be changed in run-state, I did not
+	   implement it here.
+
+
+    System Clock -- suspended !!!!
+
+        Name -- "System Clock Mode"
+
+        Access -- Read Write
+
+        Values -- "Master" "Slave"
+
+
+		  !!!! This is a hardware-function but is in conflict with the
+		  Clock-source controller, which is a kind of ALSA-standard. I
+		  makes sense to set the card to a special mode (master at some
+		  frequency or slave), since even not using an Audio-application
+		  a studio should have working synchronisations setup. So use
+		  Clock-source-controller instead !!!!
+
+    Clock Source  
+
+       Name -- "Sample Clock Source"
+
+       Access -- Read Write
+
+       Values -- "AutoSync", "Internal 32.0 kHz", "Internal 44.1 kHz",
+       "Internal 48.0 kHz", "Internal 64.0 kHz", "Internal 88.2 kHz",
+       "Internal 96.0 kHz"
+
+		 Choose between Master at a specific Frequency and so also the
+		 Speed-mode or Slave (Autosync). Also see  "Preferred Sync Ref"
+
+
+       !!!! This is no pure hardware function but was implemented by
+       ALSA by some ALSA-drivers before, so I use it also. !!!
+
+
+    Preferred Sync Ref
+
+       Name -- "Preferred Sync Reference"
+
+       Access -- Read Write
+
+       Values -- "Word" "MADI"
+
+
+		 Within the Auto-sync-Mode the preferred Sync Source can be
+		 chosen. If it is not available another is used if possible.
+
+		 Note: Since MADI has a much higher bit-rate than word-clock, the
+		 card should synchronise better in MADI Mode. But since the
+		 RME-PLL is very good, there are almost no problems with
+		 word-clock too. I never found a difference.
+
+
+    TX 64 channel --- 
+
+       Name -- "TX 64 channels mode"
+
+       Access -- Read Write
+
+       Values -- 0 1
+
+		 Using 64-channel-modus (1) or 56-channel-modus for
+		 MADI-transmission (0).
+
+
+		 Note: This control is for output only. Input-mode is detected
+		 automatically from hardware sending MADI.
+
+
+    Clear TMS ---
+
+       Name -- "Clear Track Marker"
+
+       Access -- Read Write
+
+       Values -- 0 1
+
+
+		 Don't use to lower 5 Audio-bits on AES as additional Bits.
+        
+
+    Safe Mode oder Auto Input --- 
+
+       Name -- "Safe Mode"
+
+       Access -- Read Write
+
+       Values -- 0 1
+
+       (default on)
+
+		 If on (1), then if either the optical or coaxial connection
+		 has a failure, there is a takeover to the working one, with no
+		 sample failure. Its only useful if you use the second as a
+		 backup connection.
+
+    Input --- 
+
+       Name -- "Input Select"
+
+       Access -- Read Write
+
+       Values -- optical coaxial
+
+
+		 Choosing the Input, optical or coaxial. If Safe-mode is active,
+		 this is the preferred Input.
+
+-------------- Mixer ----------------------
+
+    Mixer
+
+       Name -- "Mixer"
+
+       Access -- Read Write
+
+       Values - <channel-number 0-127> <Value 0-65535>
+
+
+		 Here as a first value the channel-index is taken to get/set the
+		 corresponding mixer channel, where 0-63 are the input to output
+		 fader and 64-127 the playback to outputs fader. Value 0
+		 is channel muted 0 and 32768 an amplification of  1.
+
+    Chn 1-64
+
+       fast mixer for the ALSA-mixer utils. The diagonal of the
+       mixer-matrix is implemented from playback to output.
+       
+
+    Line Out
+
+       Name  -- "Line Out"
+
+       Access -- Read Write
+
+       Values -- 0 1
+
+		 Switching on and off the analog out, which has nothing to do
+		 with mixing or routing. the analog outs reflects channel 63,64.
+
+
+--- information (only read access):
+ 
+    Sample Rate
+
+       Name -- "System Sample Rate"
+
+       Access -- Read-only
+
+		 getting the sample rate.
+
+
+    External Rate measured
+
+       Name -- "External Rate"
+
+       Access -- Read only
+
+
+		 Should be "Autosync Rate", but Name used is
+		 ALSA-Scheme. External Sample frequency liked used on Autosync is
+		 reported.
+
+
+    MADI Sync Status
+
+       Name -- "MADI Sync Lock Status"
+
+       Access -- Read
+
+       Values -- 0,1,2
+
+       MADI-Input is 0=Unlocked, 1=Locked, or 2=Synced.
+
+
+    Word Clock Sync Status
+
+       Name -- "Word Clock Lock Status"
+
+       Access -- Read
+
+       Values -- 0,1,2
+
+       Word Clock Input is 0=Unlocked, 1=Locked, or 2=Synced.
+
+    AutoSync
+
+       Name -- "AutoSync Reference"
+
+       Access -- Read
+
+       Values -- "WordClock", "MADI", "None"
+
+		 Sync-Reference is either "WordClock", "MADI" or none.
+
+   RX 64ch --- noch nicht implementiert
+
+       MADI-Receiver is in 64 channel mode oder 56 channel mode.
+
+
+   AB_inp   --- not tested 
+
+		 Used input for Auto-Input.
+
+
+   actual Buffer Position --- not implemented
+
+	   !!! this is a ALSA internal function, so no control is used !!!
+
+
+
+Calling Parameter:
+
+   index int array (min = 1, max = 8), 
+     "Index value for RME HDSPM interface." card-index within ALSA
+
+     note: ALSA-standard
+
+   id string array (min = 1, max = 8), 
+     "ID string for RME HDSPM interface."
+
+     note: ALSA-standard
+
+   enable int array (min = 1, max = 8), 
+     "Enable/disable specific HDSPM sound-cards."
+
+     note: ALSA-standard
+
+   precise_ptr int array (min = 1, max = 8), 
+     "Enable precise pointer, or disable."
+
+     note: Use only when the application supports this (which is a special case).
+
+   line_outs_monitor int array (min = 1, max = 8), 
+     "Send playback streams to analog outs by default."
+
+
+	  note: each playback channel is mixed to the same numbered output
+	  channel (routed). This is against the ALSA-convention, where all
+	  channels have to be muted on after loading the driver, but was
+	  used before on other cards, so i historically use it again)
+
+
+
+   enable_monitor int array (min = 1, max = 8), 
+     "Enable Analog Out on Channel 63/64 by default."
+
+      note: here the analog output is enabled (but not routed).
\ No newline at end of file
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 3515917..9f11d36 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -49,6 +49,7 @@
 - shmmax                      [ sysv ipc ]
 - shmmni
 - stop-a                      [ SPARC only ]
+- suid_dumpable
 - sysrq                       ==> Documentation/sysrq.txt
 - tainted
 - threads-max
@@ -300,6 +301,25 @@
 
 ==============================================================
 
+suid_dumpable:
+
+This value can be used to query and set the core dump mode for setuid
+or otherwise protected/tainted binaries. The modes are
+
+0 - (default) - traditional behaviour. Any process which has changed
+	privilege levels or is execute only will not be dumped
+1 - (debug) - all processes dump core when possible. The core dump is
+	owned by the current user and no security is applied. This is
+	intended for system debugging situations only. Ptrace is unchecked.
+2 - (suidsafe) - any binary which normally would not be dumped is dumped
+	readable by root only. This allows the end user to remove
+	such a dump but not access it directly. For security reasons
+	core dumps in this mode will not overwrite one another or
+	other files. This mode is appropriate when adminstrators are
+	attempting to debug problems in a normal environment.
+
+==============================================================
+
 tainted: 
 
 Non-zero if the kernel has been tainted.  Numeric values, which
diff --git a/Documentation/sysrq.txt b/Documentation/sysrq.txt
index f98c2e3..136d817 100644
--- a/Documentation/sysrq.txt
+++ b/Documentation/sysrq.txt
@@ -72,6 +72,8 @@
 'b'     - Will immediately reboot the system without syncing or unmounting
           your disks.
 
+'c'	- Will perform a kexec reboot in order to take a crashdump.
+
 'o'     - Will shut your system off (if configured and supported).
 
 's'     - Will attempt to sync all mounted filesystems.
@@ -122,6 +124,9 @@
 re'B'oot is good when you're unable to shut down. But you should also 'S'ync
 and 'U'mount first.
 
+'C'rashdump can be used to manually trigger a crashdump when the system is hung.
+The kernel needs to have been built with CONFIG_KEXEC enabled.
+
 'S'ync is great when your system is locked up, it allows you to sync your
 disks and will certainly lessen the chance of data loss and fscking. Note
 that the sync hasn't taken place until you see the "OK" and "Done" appear
diff --git a/Documentation/tty.txt b/Documentation/tty.txt
index 3958cf7..8ff7bc2 100644
--- a/Documentation/tty.txt
+++ b/Documentation/tty.txt
@@ -22,7 +22,7 @@
 discipline even with the same data or your computer again will be eaten by
 demons.
 
-In order to remove a line discipline call tty_register_ldisc passing NULL.
+In order to remove a line discipline call tty_unregister_ldisc().
 In ancient times this always worked. In modern times the function will
 return -EBUSY if the ldisc is currently in use. Since the ldisc referencing
 code manages the module counts this should not usually be a concern.
diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv
index e46761c..aeeafec 100644
--- a/Documentation/video4linux/CARDLIST.bttv
+++ b/Documentation/video4linux/CARDLIST.bttv
@@ -119,3 +119,17 @@
 card=118 - LMLBT4
 card=119 - Tekram M205 PRO
 card=120 - Conceptronic CONTVFMi
+card=121 - Euresys Picolo Tetra
+card=122 - Spirit TV Tuner
+card=123 - AVerMedia AVerTV DVB-T 771
+card=124 - AverMedia AverTV DVB-T 761
+card=125 - MATRIX Vision Sigma-SQ
+card=126 - MATRIX Vision Sigma-SLC
+card=127 - APAC Viewcomp 878(AMAX)
+card=128 - DVICO FusionHDTV DVB-T Lite
+card=129 - V-Gear MyVCD
+card=130 - Super TV Tuner
+card=131 - Tibet Systems 'Progress DVR' CS16
+card=132 - Kodicom 4400R (master)
+card=133 - Kodicom 4400R (slave)
+card=134 - Adlink RTV24
diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88
new file mode 100644
index 0000000..216f705
--- /dev/null
+++ b/Documentation/video4linux/CARDLIST.cx88
@@ -0,0 +1,29 @@
+card=0 - UNKNOWN/GENERIC
+card=1 - Hauppauge WinTV 34xxx models
+card=2 - GDI Black Gold
+card=3 - PixelView
+card=4 - ATI TV Wonder Pro
+card=5 - Leadtek Winfast 2000XP Expert
+card=6 - AverTV Studio 303 (M126)
+card=7 - MSI TV-@nywhere Master
+card=8 - Leadtek Winfast DV2000
+card=9 - Leadtek PVR 2000
+card=10 - IODATA GV-VCP3/PCI
+card=11 - Prolink PlayTV PVR
+card=12 - ASUS PVR-416
+card=13 - MSI TV-@nywhere
+card=14 - KWorld/VStream XPert DVB-T
+card=15 - DVICO FusionHDTV DVB-T1
+card=16 - KWorld LTV883RF
+card=17 - DViCO - FusionHDTV 3 Gold
+card=18 - Hauppauge Nova-T DVB-T
+card=19 - Conexant DVB-T reference design
+card=20 - Provideo PV259
+card=21 - DVICO FusionHDTV DVB-T Plus
+card=22 - digitalnow DNTV Live! DVB-T
+card=23 - pcHDTV HD3000 HDTV
+card=24 - Hauppauge WinTV 28xxx (Roslyn) models
+card=25 - Digital-Logic MICROSPACE Entertainment Center (MEC)
+card=26 - IODATA GV/BCTV7E
+card=27 - PixelView PlayTV Ultra Pro (Stereo)
+card=28 - DViCO - FusionHDTV 3 Gold-T
diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134
index a6c82fa..d5ed95d 100644
--- a/Documentation/video4linux/CARDLIST.saa7134
+++ b/Documentation/video4linux/CARDLIST.saa7134
@@ -20,16 +20,37 @@
  19 -> Compro VideoMate TV                      [185b:c100]
  20 -> Matrox CronosPlus                        [102B:48d0]
  21 -> 10MOONS PCI TV CAPTURE CARD              [1131:2001]
- 22 -> Medion 2819/ AverMedia M156              [1461:a70b,1461:2115]
+ 22 -> AverMedia M156 / Medion 2819             [1461:a70b]
  23 -> BMK MPEX Tuner
  24 -> KNC One TV-Station DVR                   [1894:a006]
  25 -> ASUS TV-FM 7133                          [1043:4843]
  26 -> Pinnacle PCTV Stereo (saa7134)           [11bd:002b]
- 27 -> Manli MuchTV M-TV002
- 28 -> Manli MuchTV M-TV001
+ 27 -> Manli MuchTV M-TV002/Behold TV 403 FM
+ 28 -> Manli MuchTV M-TV001/Behold TV 401
  29 -> Nagase Sangyo TransGear 3000TV           [1461:050c]
  30 -> Elitegroup ECS TVP3XP FM1216 Tuner Card(PAL-BG,FM)  [1019:4cb4]
  31 -> Elitegroup ECS TVP3XP FM1236 Tuner Card (NTSC,FM) [1019:4cb5]
  32 -> AVACS SmartTV
  33 -> AVerMedia DVD EZMaker                    [1461:10ff]
- 34 -> LifeView FlyTV Platinum33 mini           [5168:0212]
+ 34 -> Noval Prime TV 7133
+ 35 -> AverMedia AverTV Studio 305              [1461:2115]
+ 37 -> Items MuchTV Plus / IT-005
+ 38 -> Terratec Cinergy 200 TV                  [153B:1152]
+ 39 -> LifeView FlyTV Platinum Mini             [5168:0212]
+ 40 -> Compro VideoMate TV PVR/FM               [185b:c100]
+ 41 -> Compro VideoMate TV Gold+                [185b:c100]
+ 42 -> Sabrent SBT-TVFM (saa7130)
+ 43 -> :Zolid Xpert TV7134
+ 44 -> Empire PCI TV-Radio LE
+ 45 -> Avermedia AVerTV Studio 307              [1461:9715]
+ 46 -> AVerMedia Cardbus TV/Radio               [1461:d6ee]
+ 47 -> Terratec Cinergy 400 mobile              [153b:1162]
+ 48 -> Terratec Cinergy 600 TV MK3              [153B:1158]
+ 49 -> Compro VideoMate Gold+ Pal               [185b:c200]
+ 50 -> Pinnacle PCTV 300i DVB-T + PAL           [11bd:002d]
+ 51 -> ProVideo PV952                           [1540:9524]
+ 52 -> AverMedia AverTV/305                     [1461:2108]
+ 54 -> LifeView FlyTV Platinum FM               [5168:0214,1489:0214]
+ 55 -> LifeView FlyDVB-T DUO                    [5168:0306]
+ 56 -> Avermedia AVerTV 307                     [1461:a70a]
+ 57 -> Avermedia AVerTV GO 007 FM               [1461:f31f]
diff --git a/Documentation/video4linux/CARDLIST.tuner b/Documentation/video4linux/CARDLIST.tuner
index f7bafe8..aeb8df8 100644
--- a/Documentation/video4linux/CARDLIST.tuner
+++ b/Documentation/video4linux/CARDLIST.tuner
@@ -44,3 +44,18 @@
 tuner=43 - Philips NTSC MK3 (FM1236MK3 or FM1236/F)
 tuner=44 - Philips 4 in 1 (ATI TV Wonder Pro/Conexant)
 tuner=45 - Microtune 4049 FM5
+tuner=46 - Panasonic VP27s/ENGE4324D
+tuner=47 - LG NTSC (TAPE series)
+tuner=48 - Tenna TNF 8831 BGFF)
+tuner=49 - Microtune 4042 FI5 ATSC/NTSC dual in
+tuner=50 - TCL 2002N
+tuner=51 - Philips PAL/SECAM_D (FM 1256 I-H3)
+tuner=52 - Thomson DDT 7610 (ATSC/NTSC)
+tuner=53 - Philips FQ1286
+tuner=54 - tda8290+75
+tuner=55 - LG PAL (TAPE series)
+tuner=56 - Philips PAL/SECAM multi (FQ1216AME MK4)
+tuner=57 - Philips FQ1236A MK4
+tuner=58 - Ymec TVision TVF-8531MF
+tuner=59 - Ymec TVision TVF-5533MF
+tuner=60 - Thomson DDT 7611 (ATSC/NTSC)
diff --git a/Documentation/video4linux/hauppauge-wintv-cx88-ir.txt b/Documentation/video4linux/hauppauge-wintv-cx88-ir.txt
new file mode 100644
index 0000000..93fec32
--- /dev/null
+++ b/Documentation/video4linux/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/lifeview.txt b/Documentation/video4linux/lifeview.txt
new file mode 100644
index 0000000..b07ea79
--- /dev/null
+++ b/Documentation/video4linux/lifeview.txt
@@ -0,0 +1,42 @@
+collecting data about the lifeview models and the config coding on
+gpio pins 0-9 ...
+==================================================================
+
+bt878:
+ LR50 rev. Q ("PARTS: 7031505116), Tuner wurde als Nr. 5 erkannt, Eingänge
+ SVideo, TV, Composite, Audio, Remote. CP9..1=100001001 (1: 0-Ohm-Widerstand
+ gegen GND unbestückt; 0: bestückt)
+
+------------------------------------------------------------------------------
+
+saa7134:
+                /* LifeView FlyTV Platinum FM (LR214WF) */
+                /* "Peter Missel <peter.missel@onlinehome.de> */
+                .name           = "LifeView FlyTV Platinum FM",
+                /*      GP27    MDT2005 PB4 pin 10 */
+                /*      GP26    MDT2005 PB3 pin 9 */
+                /*      GP25    MDT2005 PB2 pin 8 */
+                /*      GP23    MDT2005 PB1 pin 7 */
+                /*      GP22    MDT2005 PB0 pin 6 */
+                /*      GP21    MDT2005 PB5 pin 11 */
+                /*      GP20    MDT2005 PB6 pin 12 */
+                /*      GP19    MDT2005 PB7 pin 13 */
+                /*      nc      MDT2005 PA3 pin 2 */
+                /*      Remote  MDT2005 PA2 pin 1 */
+                /*      GP18    MDT2005 PA1 pin 18 */
+                /*      nc      MDT2005 PA0 pin 17 strap low */
+
+                /*      GP17    Strap "GP7"=High */
+                /*      GP16    Strap "GP6"=High
+                                0=Radio 1=TV
+                                Drives SA630D ENCH1 and HEF4052 A1 pins
+                                to do FM radio through SIF input */
+                /*      GP15    nc */
+                /*      GP14    nc */
+                /*      GP13    nc */
+                /*      GP12    Strap "GP5" = High */
+                /*      GP11    Strap "GP4" = High */
+                /*      GP10    Strap "GP3" = High */
+                /*      GP09    Strap "GP2" = Low */
+                /*      GP08    Strap "GP1" = Low */
+                /*      GP07.00 nc */
diff --git a/Documentation/video4linux/not-in-cx2388x-datasheet.txt b/Documentation/video4linux/not-in-cx2388x-datasheet.txt
new file mode 100644
index 0000000..96b638b
--- /dev/null
+++ b/Documentation/video4linux/not-in-cx2388x-datasheet.txt
@@ -0,0 +1,37 @@
+=================================================================================
+MO_OUTPUT_FORMAT (0x310164)
+
+  Previous default from DScaler: 0x1c1f0008
+  Digit 8: 31-28
+  28: PREVREMOD = 1
+
+  Digit 7: 27-24 (0xc = 12 = b1100 )
+  27: COMBALT = 1
+  26: PAL_INV_PHASE
+    (DScaler apparently set this to 1, resulted in sucky picture)
+
+  Digits 6,5: 23-16
+  25-16: COMB_RANGE = 0x1f [default] (9 bits -> max 512)
+
+  Digit 4: 15-12
+  15: DISIFX = 0
+  14: INVCBF = 0
+  13: DISADAPT = 0
+  12: NARROWADAPT = 0
+
+  Digit 3: 11-8
+  11: FORCE2H
+  10: FORCEREMD
+  9: NCHROMAEN
+  8: NREMODEN
+
+  Digit 2: 7-4
+  7-6: YCORE
+  5-4: CCORE
+
+  Digit 1: 3-0
+  3: RANGE = 1
+  2: HACTEXT
+  1: HSFMT
+
+=================================================================================
diff --git a/Documentation/w1/w1.generic b/Documentation/w1/w1.generic
index eace304..f937fbe 100644
--- a/Documentation/w1/w1.generic
+++ b/Documentation/w1/w1.generic
@@ -1,19 +1,92 @@
-Any w1 device must be connected to w1 bus master device - for example
-ds9490 usb device or w1-over-GPIO or RS232 converter.
-Driver for w1 bus master must provide several functions(you can find
-them in struct w1_bus_master definition in w1.h) which then will be
-called by w1 core to send various commands over w1 bus(by default it is
-reset and search commands). When some device is found on the bus, w1 core
-checks if driver for it's family is loaded.
-If driver is loaded w1 core creates new w1_slave object and registers it
-in the system(creates some generic sysfs files(struct w1_family_ops in
-w1_family.h), notifies any registered listener and so on...).
-It is device driver's business to provide any communication method
-upstream.
-For example w1_therm driver(ds18?20 thermal sensor family driver)
-provides temperature reading function which is bound to ->rbin() method
-of the above w1_family_ops structure.
-w1_smem - driver for simple 64bit memory cell provides ID reading
-method.
+The 1-wire (w1) subsystem
+------------------------------------------------------------------
+The 1-wire bus is a simple master-slave bus that communicates via a single
+signal wire (plus ground, so two wires).
+
+Devices communicate on the bus by pulling the signal to ground via an open
+drain output and by sampling the logic level of the signal line.
+
+The w1 subsystem provides the framework for managing w1 masters and
+communication with slaves.
+
+All w1 slave devices must be connected to a w1 bus master device.
+
+Example w1 master devices:
+    DS9490 usb device
+    W1-over-GPIO
+    DS2482 (i2c to w1 bridge)
+    Emulated devices, such as a RS232 converter, parallel port adapter, etc
+
+
+What does the w1 subsystem do?
+------------------------------------------------------------------
+When a w1 master driver registers with the w1 subsystem, the following occurs:
+
+ - sysfs entries for that w1 master are created
+ - the w1 bus is periodically searched for new slave devices
+
+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.
+
+
+W1 device families
+------------------------------------------------------------------
+Slave devices are handled by a driver written for a family of w1 devices.
+
+A family driver populates a struct w1_family_ops (see w1_family.h) and
+registers with the w1 subsystem.
+
+Current family drivers:
+w1_therm - (ds18?20 thermal sensor family driver)
+    provides temperature reading function which is bound to ->rbin() method
+    of the above w1_family_ops structure.
+
+w1_smem - driver for simple 64bit memory cell provides ID reading method.
 
 You can call above methods by reading appropriate sysfs files.
+
+
+What does a w1 master driver need to implement?
+------------------------------------------------------------------
+
+The driver for w1 bus master must provide at minimum two functions.
+
+Emulated devices must provide the ability to set the output signal level
+(write_bit) and sample the signal level (read_bit).
+
+Devices that support the 1-wire natively must provide the ability to write and
+sample a bit (touch_bit) and reset the bus (reset_bus).
+
+Most hardware provides higher-level functions that offload w1 handling.
+See struct w1_bus_master definition in w1.h for details.
+
+
+w1 master sysfs interface
+------------------------------------------------------------------
+<xx-xxxxxxxxxxxxx> - a directory for a found device. The format is family-serial
+bus                - (standard) symlink to the w1 bus
+driver             - (standard) symlink to the w1 driver
+w1_master_attempts - the number of times a search was attempted
+w1_master_max_slave_count
+                   - the maximum slaves that may be attached to a master
+w1_master_name     - the name of the device (w1_bus_masterX)
+w1_master_search   - the number of searches left to do, -1=continual (default)
+w1_master_slave_count
+                   - the number of slaves found
+w1_master_slaves   - the names of the slaves, one per line
+w1_master_timeout  - the delay in seconds between searches
+
+If you have a w1 bus that never changes (you don't add or remove devices),
+you can set w1_master_search to a positive value to disable searches.
+
+
+w1 slave sysfs interface
+------------------------------------------------------------------
+bus                - (standard) symlink to the w1 bus
+driver             - (standard) symlink to the w1 driver
+name               - the device name, usually the same as the directory name
+w1_slave           - (optional) a binary file whose meaning depends on the
+                     family driver
+
diff --git a/MAINTAINERS b/MAINTAINERS
index 65ad825..a0b0d59 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -73,7 +73,7 @@
 3C359 NETWORK DRIVER
 P:	Mike Phillips
 M:	mikep@linuxtr.net
-L:	netdev@oss.sgi.com
+L:	netdev@vger.kernel.org
 L:	linux-tr@linuxtr.net
 W:	http://www.linuxtr.net
 S:	Maintained
@@ -81,13 +81,13 @@
 3C505 NETWORK DRIVER
 P:	Philip Blundell
 M:	philb@gnu.org
-L:	netdev@oss.sgi.com
+L:	netdev@vger.kernel.org
 S:	Maintained
 
 3CR990 NETWORK DRIVER
 P:	David Dillow
 M:	dave@thedillows.org
-L:	netdev@oss.sgi.com
+L:	netdev@vger.kernel.org
 S:	Maintained
 
 3W-XXXX ATA-RAID CONTROLLER DRIVER
@@ -130,7 +130,7 @@
 8169 10/100/1000 GIGABIT ETHERNET DRIVER
 P:	Francois Romieu
 M:	romieu@fr.zoreil.com
-L:	netdev@oss.sgi.com
+L:	netdev@vger.kernel.org
 S:	Maintained
 
 8250/16?50 (AND CLONE UARTS) SERIAL DRIVER
@@ -143,7 +143,7 @@
 8390 NETWORK DRIVERS [WD80x3/SMC-ELITE, SMC-ULTRA, NE2000, 3C503, etc.]
 P:	Paul Gortmaker
 M:	p_gortmaker@yahoo.com
-L:	netdev@oss.sgi.com
+L:	netdev@vger.kernel.org
 S:	Maintained
 
 A2232 SERIAL BOARD DRIVER
@@ -194,7 +194,7 @@
 ADM1025 HARDWARE MONITOR DRIVER
 P:	Jean Delvare
 M:	khali@linux-fr.org
-L:	sensors@stimpy.netroedge.com
+L:	lm-sensors@lm-sensors.org
 S:	Maintained
 
 ADT746X FAN DRIVER
@@ -242,7 +242,7 @@
 ALI1563 I2C DRIVER
 P:	Rudolf Marek
 M:	r.marek@sh.cvut.cz
-L:	sensors@stimpy.netroedge.com
+L:	lm-sensors@lm-sensors.org
 S:	Maintained
 
 ALPHA PORT
@@ -265,6 +265,11 @@
 M:	acme@conectiva.com.br
 S:	Maintained
 
+ARC FRAMEBUFFER DRIVER
+P:	Jaya Kumar
+M:	jayalk@intworks.biz
+S:	Maintained
+
 ARM26 ARCHITECTURE
 P:	Ian Molton
 M:	spyro@f2s.com
@@ -299,7 +304,7 @@
 ARM/PT DIGITAL BOARD PORT
 P:	Stefan Eletzhofer
 M:	stefan.eletzhofer@eletztrick.de
-L:	linux-arm-kernel@lists.arm.linux.org.uk
+L:	linux-arm-kernel@lists.arm.linux.org.uk	(subscribers-only)
 W:	http://www.arm.linux.org.uk/
 S:	Maintained
 
@@ -312,27 +317,27 @@
 ARM/STRONGARM110 PORT
 P:	Russell King
 M:	rmk@arm.linux.org.uk
-L:	linux-arm-kernel@lists.arm.linux.org.uk
+L:	linux-arm-kernel@lists.arm.linux.org.uk	(subscribers-only)
 W:	http://www.arm.linux.org.uk/
 S:	Maintained
 
 ARM/S3C2410 ARM ARCHITECTURE
 P:	Ben Dooks
 M:	ben-s3c2410@fluff.org
-L:	linux-arm-kernel@lists.arm.linux.org.uk
+L:	linux-arm-kernel@lists.arm.linux.org.uk	(subscribers-only)
 W:	http://www.fluff.org/ben/linux/
 S:	Maintained
 
 ARM/S3C2440 ARM ARCHITECTURE
 P:	Ben Dooks
 M:	ben-s3c2440@fluff.org
-L:	linux-arm-kernel@lists.arm.linux.org.uk
+L:	linux-arm-kernel@lists.arm.linux.org.uk	(subscribers-only)
 W:	http://www.fluff.org/ben/linux/
 S:	Maintained
 
 ARPD SUPPORT
 P:	Jonathan Layes
-L:	netdev@oss.sgi.com
+L:	netdev@vger.kernel.org
 S:	Maintained
 
 ASUS ACPI EXTRAS DRIVER
@@ -499,6 +504,13 @@
 W:   http://sourceforge.net/projects/bonding/
 S:   Supported
 
+BROADBAND PROCESSOR ARCHITECTURE
+P:	Arnd Bergmann
+M:	arnd@arndb.de
+L:	linuxppc64-dev@ozlabs.org
+W:	http://linuxppc64.org
+S:	Supported
+
 BTTV VIDEO4LINUX DRIVER
 P:	Gerd Knorr
 M:	kraxel@bytesex.org
@@ -564,10 +576,9 @@
 
 COMPUTONE INTELLIPORT MULTIPORT CARD
 P:	Michael H. Warfield
-M:	Michael H. Warfield <mhw@wittsend.com>
+M:	mhw@wittsend.com
 W:	http://www.wittsend.com/computone.html
-L:	linux-computone@lazuli.wittsend.com
-S:	Orphaned
+S:	Maintained
 
 COSA/SRP SYNC SERIAL DRIVER
 P:	Jan "Yenya" Kasprzak
@@ -706,7 +717,7 @@
 
 DIGI RIGHTSWITCH NETWORK DRIVER
 P:	Rick Richardson
-L:	netdev@oss.sgi.com
+L:	netdev@vger.kernel.org
 W:	http://www.digi.com
 S:	Orphaned
 
@@ -736,6 +747,11 @@
 L:	linux-kernel@vger.kernel.org
 S:	Maintained
 
+DOCBOOK FOR DOCUMENTATION
+P:	Martin Waitz
+M:	tali@admingilde.org
+S:	Maintained
+
 DOUBLETALK DRIVER
 P:	James R. Van Zandt
 M:	jrv@vanzandt.mv.com
@@ -812,7 +828,7 @@
 ETHEREXPRESS-16 NETWORK DRIVER
 P:	Philip Blundell
 M:	philb@gnu.org
-L:	netdev@oss.sgi.com
+L:	netdev@vger.kernel.org
 S:	Maintained
 
 ETHERNET BRIDGE
@@ -875,7 +891,7 @@
 FRAME RELAY DLCI/FRAD (Sangoma drivers too)
 P:	Mike McLagan
 M:	mike.mclagan@linux.org
-L:	netdev@oss.sgi.com
+L:	netdev@vger.kernel.org
 S:	Maintained
 
 FREEVXFS FILESYSTEM
@@ -992,7 +1008,7 @@
 M:	greg@kroah.com
 P:	Jean Delvare
 M:	khali@linux-fr.org
-L:	sensors@stimpy.netroedge.com
+L:	lm-sensors@lm-sensors.org
 W:	http://www.lm-sensors.nu/
 S:	Maintained
 
@@ -1215,7 +1231,7 @@
 IPX NETWORK LAYER
 P:	Arnaldo Carvalho de Melo
 M:	acme@conectiva.com.br
-L:	netdev@oss.sgi.com
+L:	netdev@vger.kernel.org
 S:	Maintained
 
 IRDA SUBSYSTEM
@@ -1313,6 +1329,16 @@
 L:	linux-kernel@vger.kernel.org
 S:	Maintained
 
+KEXEC
+P:	Eric Biederman
+P:	Randy Dunlap
+M:	ebiederm@xmission.com
+M:	rddunlap@osdl.org
+W:	http://www.xmission.com/~ebiederm/files/kexec/
+L:	linux-kernel@vger.kernel.org
+L:	fastboot@osdl.org
+S:	Maintained
+
 LANMEDIA WAN CARD DRIVER
 P:	Andrew Stanley-Jones
 M:	asj@lanmedia.com
@@ -1420,13 +1446,13 @@
 LM83 HARDWARE MONITOR DRIVER
 P:	Jean Delvare
 M:	khali@linux-fr.org
-L:	sensors@stimpy.netroedge.com
+L:	lm-sensors@lm-sensors.org
 S:	Maintained
 
 LM90 HARDWARE MONITOR DRIVER
 P:	Jean Delvare
 M:	khali@linux-fr.org
-L:	sensors@stimpy.netroedge.com
+L:	lm-sensors@lm-sensors.org
 S:	Maintained
 
 LOGICAL DISK MANAGER SUPPORT (LDM, Windows 2000/XP Dynamic Disks)
@@ -1482,7 +1508,7 @@
 P:	Manish Lachwani
 M:	Manish_Lachwani@pmc-sierra.com
 L:	linux-mips@linux-mips.org
-L:	netdev@oss.sgi.com
+L:	netdev@vger.kernel.org
 S:	Supported
 
 MATROX FRAMEBUFFER DRIVER
@@ -1592,13 +1618,13 @@
 M:	akpm@osdl.org
 P:	Jeff Garzik
 M:	jgarzik@pobox.com
-L:	netdev@oss.sgi.com
+L:	netdev@vger.kernel.org
 S:	Maintained
 
 NETWORKING [GENERAL]
 P:	Networking Team
-M:	netdev@oss.sgi.com
-L:	netdev@oss.sgi.com
+M:	netdev@vger.kernel.org
+L:	netdev@vger.kernel.org
 S:	Maintained
 
 NETWORKING [IPv4/IPv6]
@@ -1614,7 +1640,7 @@
 M:	yoshfuji@linux-ipv6.org
 P:	Patrick McHardy
 M:	kaber@coreworks.de
-L:	netdev@oss.sgi.com
+L:	netdev@vger.kernel.org
 S:	Maintained
 
 IPVS
@@ -1634,7 +1660,7 @@
 P:	Jan-Pascal van Best and Andreas Mohr
 M:	Jan-Pascal van Best <jvbest@qv3pluto.leidenuniv.nl>
 M:	Andreas Mohr <100.30936@germany.net>
-L:	netdev@oss.sgi.com
+L:	netdev@vger.kernel.org
 S:	Maintained
 
 NINJA SCSI-3 / NINJA SCSI-32Bi (16bit/CardBus) PCMCIA SCSI HOST ADAPTER DRIVER
@@ -1676,7 +1702,7 @@
 M:	p2@ace.ulyssis.student.kuleuven.ac.be
 P:	Mike Phillips
 M:	mikep@linuxtr.net 
-L:	netdev@oss.sgi.com
+L:	netdev@vger.kernel.org
 L:	linux-tr@linuxtr.net
 W:	http://www.linuxtr.net
 S:	Maintained
@@ -1783,7 +1809,7 @@
 PCNET32 NETWORK DRIVER
 P:	Thomas Bogendörfer
 M:	tsbogend@alpha.franken.de
-L:	netdev@oss.sgi.com
+L:	netdev@vger.kernel.org
 S:	Maintained
 
 PHRAM MTD DRIVER
@@ -1795,7 +1821,7 @@
 POSIX CLOCKS and TIMERS
 P:	George Anzinger
 M:	george@mvista.com
-L:	netdev@oss.sgi.com
+L:	netdev@vger.kernel.org
 S:	Supported
 
 PNP SUPPORT
@@ -1830,7 +1856,7 @@
 PRISM54 WIRELESS DRIVER
 P:	Prism54 Development Team
 M:	prism54-private@prism54.org
-L:	netdev@oss.sgi.com
+L:	netdev@vger.kernel.org
 W:	http://prism54.org
 S:	Maintained
 
@@ -1843,7 +1869,7 @@
 PXA2xx SUPPORT
 P:	Nicolas Pitre
 M:	nico@cam.org
-L:	linux-arm-kernel@lists.arm.linux.org.uk
+L:	linux-arm-kernel@lists.arm.linux.org.uk	(subscribers-only)
 S:	Maintained
 
 QLOGIC QLA2XXX FC-SCSI DRIVER
@@ -2047,7 +2073,7 @@
 P:	Daniele Venzano
 M:	venza@brownhat.org
 W:	http://www.brownhat.org/sis900.html
-L:	netdev@oss.sgi.com
+L:	netdev@vger.kernel.org
 S:	Maintained
 
 SIS FRAMEBUFFER DRIVER
@@ -2065,7 +2091,7 @@
 SMSC47M1 HARDWARE MONITOR DRIVER
 P:	Jean Delvare
 M:	khali@linux-fr.org
-L:	sensors@stimpy.netroedge.com
+L:	lm-sensors@lm-sensors.org
 S:	Odd Fixes
 
 SMB FILESYSTEM
@@ -2098,15 +2124,13 @@
 SOFTWARE SUSPEND:
 P:	Pavel Machek
 M:	pavel@suse.cz
-M:	pavel@ucw.cz
-L:	http://lister.fornax.hu/mailman/listinfo/swsusp
-W:	http://swsusp.sf.net/
+L:	linux-pm@osdl.org
 S:	Maintained
 
 SONIC NETWORK DRIVER
 P:	Thomas Bogendoerfer
 M:	tsbogend@alpha.franken.de
-L:	netdev@oss.sgi.com
+L:	netdev@vger.kernel.org
 S:	Maintained
 
 SONY VAIO CONTROL DEVICE DRIVER
@@ -2128,6 +2152,11 @@
 L:	tpmdd-devel@lists.sourceforge.net
 S:	Maintained
 
+TENSILICA XTENSA PORT (xtensa):
+P:	Chris Zankel
+M:	chris@zankel.net
+S:	Maintained
+
 UltraSPARC (sparc64):
 P:	David S. Miller
 M:	davem@davemloft.net
@@ -2145,7 +2174,7 @@
 P:	Marc Singer
 M:	elf@buici.com
 W:	http://projects.buici.com/arm
-L:	linux-arm-kernel@lists.arm.linux.org.uk
+L:	linux-arm-kernel@lists.arm.linux.org.uk	(subscribers-only)
 S:	Maintained
 
 SPARC (sparc32):
@@ -2163,7 +2192,7 @@
 SPX NETWORK LAYER
 P:	Jay Schulist
 M:	jschlst@samba.org
-L:	netdev@oss.sgi.com
+L:	netdev@vger.kernel.org
 S:	Supported
 
 SRM (Alpha) environment access
@@ -2242,7 +2271,7 @@
 TOKEN-RING NETWORK DRIVER
 P:	Mike Phillips
 M:	mikep@linuxtr.net
-L:	netdev@oss.sgi.com
+L:	netdev@vger.kernel.org
 L:	linux-tr@linuxtr.net
 W:	http://www.linuxtr.net
 S:	Maintained
@@ -2572,7 +2601,7 @@
 P:	D. Jeff Dionne (created first uClinux port)
 M:	jeff@uclinux.org
 W:	http://www.uclinux.org/
-L:	uclinux-dev@uclinux.org
+L:	uclinux-dev@uclinux.org  (subscribers-only)
 S:	Maintained
 
 UCLINUX FOR NEC V850
@@ -2604,7 +2633,7 @@
 W1 DALLAS'S 1-WIRE BUS
 P:	Evgeniy Polyakov
 M:	johnpol@2ka.mipt.ru
-L:	sensors@stimpy.netroedge.com
+L:	lm-sensors@lm-sensors.org
 S:	Maintained
 
 W83L51xD SD/MMC CARD INTERFACE DRIVER
@@ -2617,7 +2646,7 @@
 W83L785TS HARDWARE MONITOR DRIVER
 P:	Jean Delvare
 M:	khali@linux-fr.org
-L:	sensors@stimpy.netroedge.com
+L:	lm-sensors@lm-sensors.org
 S:	Odd Fixes
 
 WAN ROUTER & SANGOMA WANPIPE DRIVERS & API (X.25, FRAME RELAY, PPP, CISCO HDLC)
diff --git a/Makefile b/Makefile
index c11a317..1fdace7 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 12
-EXTRAVERSION =-rc5
+EXTRAVERSION =
 NAME=Woozy Numbat
 
 # *DOCUMENTATION*
@@ -281,7 +281,7 @@
 # See documentation in Documentation/kbuild/makefiles.txt
 
 # cc-option
-# Usage: cflags-y += $(call gcc-option, -march=winchip-c6, -march=i586)
+# Usage: cflags-y += $(call cc-option, -march=winchip-c6, -march=i586)
 
 cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
              > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
@@ -518,7 +518,7 @@
 CFLAGS		+= $(call add-align,CONFIG_CC_ALIGN_JUMPS,-jumps)
 
 ifdef CONFIG_FRAME_POINTER
-CFLAGS		+= -fno-omit-frame-pointer
+CFLAGS		+= -fno-omit-frame-pointer $(call cc-option,-fno-optimize-sibling-calls,)
 else
 CFLAGS		+= -fomit-frame-pointer
 endif
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index f7c9663..c5739d6 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -509,7 +509,7 @@
 	depends on SMP
 	default "64"
 
-config DISCONTIGMEM
+config ARCH_DISCONTIGMEM_ENABLE
 	bool "Discontiguous Memory Support (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
 	help
@@ -518,6 +518,8 @@
 	  or have huge holes in the physical address space for other reasons.
 	  See <file:Documentation/vm/numa> for more.
 
+source "mm/Kconfig"
+
 config NUMA
 	bool "NUMA Support (EXPERIMENTAL)"
 	depends on DISCONTIGMEM
diff --git a/arch/alpha/defconfig b/arch/alpha/defconfig
index 5e39b7a..6da9c3d 100644
--- a/arch/alpha/defconfig
+++ b/arch/alpha/defconfig
@@ -96,7 +96,7 @@
 CONFIG_ALPHA_BROKEN_IRQ_MASK=y
 CONFIG_EISA=y
 # CONFIG_SMP is not set
-# CONFIG_DISCONTIGMEM is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
 CONFIG_VERBOSE_MCHECK=y
 CONFIG_VERBOSE_MCHECK_ON=1
 CONFIG_PCI_LEGACY_PROC=y
diff --git a/arch/alpha/mm/numa.c b/arch/alpha/mm/numa.c
index ba81c44..c7481d5 100644
--- a/arch/alpha/mm/numa.c
+++ b/arch/alpha/mm/numa.c
@@ -327,8 +327,6 @@
 	extern char _text, _etext, _data, _edata;
 	extern char __init_begin, __init_end;
 	unsigned long nid, i;
-	struct page * lmem_map;
-
 	high_memory = (void *) __va(max_low_pfn << PAGE_SHIFT);
 
 	reservedpages = 0;
@@ -338,10 +336,10 @@
 		 */
 		totalram_pages += free_all_bootmem_node(NODE_DATA(nid));
 
-		lmem_map = node_mem_map(nid);
 		pfn = NODE_DATA(nid)->node_start_pfn;
 		for (i = 0; i < node_spanned_pages(nid); i++, pfn++)
-			if (page_is_ram(pfn) && PageReserved(lmem_map+i))
+			if (page_is_ram(pfn) &&
+			    PageReserved(nid_page_nr(nid, i)))
 				reservedpages++;
 	}
 
@@ -373,18 +371,18 @@
 	show_free_areas();
 	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
 	for_each_online_node(nid) {
-		struct page * lmem_map = node_mem_map(nid);
 		i = node_spanned_pages(nid);
 		while (i-- > 0) {
+			struct page *page = nid_page_nr(nid, i);
 			total++;
-			if (PageReserved(lmem_map+i))
+			if (PageReserved(page))
 				reserved++;
-			else if (PageSwapCache(lmem_map+i))
+			else if (PageSwapCache(page))
 				cached++;
-			else if (!page_count(lmem_map+i))
+			else if (!page_count(page))
 				free++;
 			else
-				shared += page_count(lmem_map + i) - 1;
+				shared += page_count(page) - 1;
 		}
 	}
 	printk("%ld pages of RAM\n",total);
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index bf397a9..c8d94dc 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -67,10 +67,6 @@
 config GENERIC_ISA_DMA
 	bool
 
-config GENERIC_IOMAP
-	bool
-	default y
-
 config FIQ
 	bool
 
@@ -161,7 +157,7 @@
 config ARCH_SA1100
 	bool "SA1100-based"
 	select ISA
-	select DISCONTIGMEM
+	select ARCH_DISCONTIGMEM_ENABLE
 
 config ARCH_S3C2410
 	bool "Samsung S3C2410"
@@ -202,6 +198,11 @@
 	help
 	  This enables support for systems based on the Hynix HMS720x
 
+config ARCH_AAEC2000
+	bool "Agilent AAEC-2000 based"
+	help
+	  This enables support for systems based on the Agilent AAEC-2000
+
 endchoice
 
 source "arch/arm/mach-clps711x/Kconfig"
@@ -234,6 +235,8 @@
 
 source "arch/arm/mach-versatile/Kconfig"
 
+source "arch/arm/mach-aaec2000/Kconfig"
+
 # Definitions to make life easier
 config ARCH_ACORN
 	bool
@@ -277,7 +280,7 @@
 	default y
 
 config PCI
-	bool "PCI support" if ARCH_INTEGRATOR_AP
+	bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB
 	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
@@ -343,7 +346,22 @@
 	  Say Y here if you are building a kernel for a desktop, embedded
 	  or real-time system.  Say N if you are unsure.
 
-config DISCONTIGMEM
+config NO_IDLE_HZ
+	bool "Dynamic tick timer"
+	help
+	  Select this option if you want to disable continuous timer ticks
+	  and have them programmed to occur as required. This option saves
+	  power as the system can remain in idle state for longer.
+
+	  By default dynamic tick is disabled during the boot, and can be
+	  manually enabled with:
+
+	    echo 1 > /sys/devices/system/timer/timer0/dyn_tick
+
+	  Alternatively, if you want dynamic tick automatically enabled
+	  during boot, pass "dyntick=enable" via the kernel command string.
+
+config ARCH_DISCONTIGMEM_ENABLE
 	bool
 	default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM)
 	help
@@ -352,6 +370,8 @@
 	  or have huge holes in the physical address space for other reasons.
 	  See <file:Documentation/vm/numa> for more.
 
+source "mm/Kconfig"
+
 config LEDS
 	bool "Timer and CPU usage LEDs"
 	depends on ARCH_CDB89712 || ARCH_CO285 || ARCH_EBSA110 || \
@@ -497,7 +517,7 @@
 
 config CPU_FREQ_SA1100
 	bool
-	depends on CPU_FREQ && (SA1100_LART || SA1100_PLEB)
+	depends on CPU_FREQ && (SA1100_H3100 || SA1100_H3600 || SA1100_H3800 || SA1100_LART || SA1100_PLEB || SA1100_BADGE4 || SA1100_HACKKIT)
 	default y
 
 config CPU_FREQ_SA1110
@@ -689,7 +709,9 @@
 
 source "drivers/acorn/block/Kconfig"
 
-if ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX || ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE
+if PCMCIA || ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX \
+	|| ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \
+	|| ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE
 source "drivers/ide/Kconfig"
 endif
 
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 2277e3d..8330495 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -97,6 +97,7 @@
  machine-$(CONFIG_ARCH_VERSATILE)  := versatile
  machine-$(CONFIG_ARCH_IMX)	   := imx
  machine-$(CONFIG_ARCH_H720X)	   := h720x
+ machine-$(CONFIG_ARCH_AAEC2000)   := aaec2000
 
 ifeq ($(CONFIG_ARCH_EBSA110),y)
 # This is what happens if you forget the IOCS16 line.
diff --git a/arch/arm/boot/compressed/head-xscale.S b/arch/arm/boot/compressed/head-xscale.S
index 665bd2c..d3fe253 100644
--- a/arch/arm/boot/compressed/head-xscale.S
+++ b/arch/arm/boot/compressed/head-xscale.S
@@ -47,3 +47,10 @@
                orr     r7, r7, #(MACH_TYPE_GTWX5715 & 0xff00)
 #endif
 
+#ifdef CONFIG_ARCH_IXP2000
+		mov	r1, #-1
+		mov	r0, #0xd6000000
+		str	r1, [r0, #0x14]
+		str	r1, [r0, #0x18]
+#endif
+
diff --git a/arch/arm/boot/install.sh b/arch/arm/boot/install.sh
index 935bb27..9f9bed2 100644
--- a/arch/arm/boot/install.sh
+++ b/arch/arm/boot/install.sh
@@ -21,8 +21,8 @@
 #
 
 # User may have a custom install script
-if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi
-if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi
+if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi
+if [ -x /sbin/${CROSS_COMPILE}installkernel ]; then exec /sbin/${CROSS_COMPILE}installkernel "$@"; fi
 
 if [ "$(basename $2)" = "zImage" ]; then
 # Compressed install
diff --git a/arch/arm/common/amba.c b/arch/arm/common/amba.c
index a0507f8..c6beb75 100644
--- a/arch/arm/common/amba.c
+++ b/arch/arm/common/amba.c
@@ -169,7 +169,7 @@
 }
 
 #define amba_attr(name,fmt,arg...)				\
-static ssize_t show_##name(struct device *_dev, char *buf)	\
+static ssize_t show_##name(struct device *_dev, struct device_attribute *attr, char *buf)	\
 {								\
 	struct amba_device *dev = to_amba_device(_dev);		\
 	return sprintf(buf, fmt, arg);				\
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 5797b1b..cbf2165 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -30,6 +30,8 @@
 #include <linux/dmapool.h>
 #include <linux/list.h>
 
+#include <asm/cacheflush.h>
+
 #undef DEBUG
 
 #undef STATS
@@ -91,15 +93,12 @@
 static inline struct dmabounce_device_info *
 find_dmabounce_dev(struct device *dev)
 {
-	struct list_head *entry;
+	struct dmabounce_device_info *d;
 
-	list_for_each(entry, &dmabounce_devs) {
-		struct dmabounce_device_info *d =
-			list_entry(entry, struct dmabounce_device_info, node);
-
+	list_for_each_entry(d, &dmabounce_devs, node)
 		if (d->dev == dev)
 			return d;
-	}
+
 	return NULL;
 }
 
@@ -170,15 +169,11 @@
 static inline struct safe_buffer *
 find_safe_buffer(struct dmabounce_device_info *device_info, dma_addr_t safe_dma_addr)
 {
-	struct list_head *entry;
+	struct safe_buffer *b;
 
-	list_for_each(entry, &device_info->safe_buffers) {
-		struct safe_buffer *b =
-			list_entry(entry, struct safe_buffer, node);
-
+	list_for_each_entry(b, &device_info->safe_buffers, node)
 		if (b->safe_dma_addr == safe_dma_addr)
 			return b;
-	}
 
 	return NULL;
 }
@@ -299,15 +294,26 @@
 			__func__, buf->ptr, (void *) virt_to_dma(dev, buf->ptr),
 			buf->safe, (void *) buf->safe_dma_addr);
 
-
 		DO_STATS ( device_info->bounce_count++ );
 
-		if ((dir == DMA_FROM_DEVICE) ||
-		    (dir == DMA_BIDIRECTIONAL)) {
+		if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) {
+			unsigned long ptr;
+
 			dev_dbg(dev,
 				"%s: copy back safe %p to unsafe %p size %d\n",
 				__func__, buf->safe, buf->ptr, size);
 			memcpy(buf->ptr, buf->safe, size);
+
+			/*
+			 * DMA buffers must have the same cache properties
+			 * as if they were really used for DMA - which means
+			 * data must be written back to RAM.  Note that
+			 * we don't use dmac_flush_range() here for the
+			 * bidirectional case because we know the cache
+			 * lines will be coherent with the data written.
+			 */
+			ptr = (unsigned long)buf->ptr;
+			dmac_clean_range(ptr, ptr + size);
 		}
 		free_safe_buffer(device_info, buf);
 	}
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 21fce34..38c2eb6 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -721,16 +721,17 @@
 	return ret;
 }
 
+static int sa1111_remove_one(struct device *dev, void *data)
+{
+	device_unregister(dev);
+	return 0;
+}
+
 static void __sa1111_remove(struct sa1111 *sachip)
 {
-	struct list_head *l, *n;
 	void __iomem *irqbase = sachip->base + SA1111_INTC;
 
-	list_for_each_safe(l, n, &sachip->dev->children) {
-		struct device *d = list_to_dev(l);
-
-		device_unregister(d);
-	}
+	device_for_each_child(sachip->dev, NULL, sa1111_remove_one);
 
 	/* disable all IRQs */
 	sa1111_writel(0, irqbase + SA1111_INTEN0);
diff --git a/arch/arm/common/sharpsl_param.c b/arch/arm/common/sharpsl_param.c
index c2c557a..c94864c 100644
--- a/arch/arm/common/sharpsl_param.c
+++ b/arch/arm/common/sharpsl_param.c
@@ -22,7 +22,7 @@
  * them early in the boot process, then pass them to the appropriate drivers.
  * Not all devices use all paramaters but the format is common to all.
  */
-#ifdef ARCH_SA1100
+#ifdef CONFIG_ARCH_SA1100
 #define PARAM_BASE	0xe8ffc000
 #else
 #define PARAM_BASE	0xa0000a00
diff --git a/arch/arm/configs/badge4_defconfig b/arch/arm/configs/badge4_defconfig
index 2b4059d..5d92af9 100644
--- a/arch/arm/configs/badge4_defconfig
+++ b/arch/arm/configs/badge4_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sat Mar 26 21:32:26 2005
+# Linux kernel version: 2.6.12-rc6-git3
+# Thu Jun  9 19:00:50 2005
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
@@ -16,6 +16,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -34,6 +35,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=y
@@ -109,7 +112,6 @@
 CONFIG_CPU_CACHE_V4WB=y
 CONFIG_CPU_CACHE_VIVT=y
 CONFIG_CPU_TLB_V4WB=y
-CONFIG_CPU_MINICACHE=y
 
 #
 # Processor Features
@@ -122,6 +124,7 @@
 # Bus support
 #
 CONFIG_ISA=y
+CONFIG_ISA_DMA_API=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -131,6 +134,7 @@
 #
 # Kernel Features
 #
+# CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
 CONFIG_DISCONTIGMEM=y
 # CONFIG_LEDS is not set
@@ -152,12 +156,14 @@
 # CONFIG_CPU_FREQ_DEBUG is not set
 CONFIG_CPU_FREQ_STAT=y
 # CONFIG_CPU_FREQ_STAT_DETAILS is not set
-CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
 # CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
-# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
 # CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_SA1100=y
 
 #
 # Floating point emulation
@@ -294,7 +300,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
@@ -428,7 +433,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
@@ -526,6 +530,7 @@
 # CONFIG_SMC_IRCC_FIR is not set
 # CONFIG_ALI_FIR is not set
 CONFIG_SA1100_FIR=y
+# CONFIG_VIA_FIR is not set
 CONFIG_BT=m
 CONFIG_BT_L2CAP=m
 # CONFIG_BT_SCO is not set
@@ -618,7 +623,6 @@
 #
 # CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -687,7 +691,6 @@
 #
 # TPM devices
 #
-# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -736,6 +739,7 @@
 # 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_SMSC47B397 is not set
@@ -747,6 +751,7 @@
 #
 # Other I2C Chip support
 #
+# CONFIG_SENSORS_DS1337 is not set
 # CONFIG_SENSORS_EEPROM is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCF8591 is not set
@@ -871,7 +876,6 @@
 #
 CONFIG_USB_STORAGE=y
 CONFIG_USB_STORAGE_DEBUG=y
-# CONFIG_USB_STORAGE_RW_DETECT is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
@@ -954,9 +958,11 @@
 #
 CONFIG_USB_SERIAL=m
 CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME 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 is not set
 CONFIG_USB_SERIAL_EMPEG=m
 CONFIG_USB_SERIAL_FTDI_SIO=m
@@ -985,6 +991,7 @@
 # CONFIG_USB_SERIAL_KOBIL_SCT is not set
 CONFIG_USB_SERIAL_MCT_U232=m
 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=m
diff --git a/arch/arm/configs/enp2611_defconfig b/arch/arm/configs/enp2611_defconfig
index e8f9fcc..b8c51ee 100644
--- a/arch/arm/configs/enp2611_defconfig
+++ b/arch/arm/configs/enp2611_defconfig
@@ -1,14 +1,13 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 22:08:24 2005
+# Linux kernel version: 2.6.12-git6
+# Sat Jun 25 00:57:29 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
@@ -16,6 +15,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -35,6 +35,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=y
@@ -50,7 +52,13 @@
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+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
 
 #
 # System Type
@@ -76,6 +84,7 @@
 # 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_SUPPORTS_BIG_ENDIAN=y
 
 #
@@ -90,6 +99,7 @@
 # CONFIG_ARCH_IXDP2800 is not set
 # CONFIG_ARCH_IXDP2401 is not set
 # CONFIG_ARCH_IXDP2801 is not set
+# CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO is not set
 
 #
 # Processor Type
@@ -100,7 +110,6 @@
 CONFIG_CPU_ABRT_EV5T=y
 CONFIG_CPU_CACHE_VIVT=y
 CONFIG_CPU_TLB_V4WBI=y
-CONFIG_CPU_MINICACHE=y
 
 #
 # Processor Features
@@ -112,9 +121,11 @@
 #
 # Bus support
 #
+CONFIG_ISA_DMA_API=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -124,7 +135,15 @@
 #
 # Kernel Features
 #
+# CONFIG_SMP is not set
 # CONFIG_PREEMPT 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_ALIGNMENT_TRAP=y
 
 #
@@ -263,7 +282,6 @@
 #
 # 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
@@ -302,6 +320,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -323,10 +342,11 @@
 #
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
 CONFIG_IP_PNP=y
@@ -343,6 +363,17 @@
 # CONFIG_INET_TUNNEL is not set
 # CONFIG_IP_TCPDIAG is not set
 # CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
 # CONFIG_IPV6 is not set
 # CONFIG_NETFILTER is not set
 
@@ -398,6 +429,7 @@
 # CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
 
 #
 # Tulip family network device support
@@ -434,9 +466,11 @@
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
+# CONFIG_SKGE 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)
@@ -458,6 +492,7 @@
 # Wan interfaces
 #
 CONFIG_WAN=y
+# CONFIG_DSCC4 is not set
 # CONFIG_LANMEDIA is not set
 # CONFIG_SYNCLINK_SYNCPPP is not set
 CONFIG_HDLC=y
@@ -520,7 +555,6 @@
 #
 # CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -541,6 +575,7 @@
 #
 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
@@ -607,17 +642,18 @@
 # 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 is not set
 # CONFIG_I2C_IXP2000 is not set
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 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
+# CONFIG_I2C_STUB is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
@@ -631,7 +667,9 @@
 # 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_FSCHER is not set
 # CONFIG_SENSORS_FSCPOS is not set
@@ -647,6 +685,7 @@
 # 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_SMSC47B397 is not set
@@ -656,14 +695,19 @@
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
 
 #
 # Other 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_RTC8564 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
@@ -717,6 +761,7 @@
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 # 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=y
@@ -757,7 +802,6 @@
 #
 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
@@ -795,12 +839,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
@@ -885,3 +931,4 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
+# CONFIG_TEXTSEARCH is not set
diff --git a/arch/arm/configs/h3600_defconfig b/arch/arm/configs/h3600_defconfig
index b4e297d..b9de07d 100644
--- a/arch/arm/configs/h3600_defconfig
+++ b/arch/arm/configs/h3600_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Mon Mar 28 00:02:26 2005
+# Linux kernel version: 2.6.12-rc4
+# Thu Jun  9 01:59:03 2005
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
@@ -16,6 +16,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -33,6 +34,8 @@
 # CONFIG_EMBEDDED is not set
 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
@@ -120,6 +123,7 @@
 # Bus support
 #
 CONFIG_ISA=y
+CONFIG_ISA_DMA_API=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -138,6 +142,7 @@
 #
 # Kernel Features
 #
+# CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
 CONFIG_DISCONTIGMEM=y
 # CONFIG_LEDS is not set
@@ -159,12 +164,13 @@
 # CONFIG_CPU_FREQ_DEBUG is not set
 CONFIG_CPU_FREQ_STAT=y
 # CONFIG_CPU_FREQ_STAT_DETAILS is not set
-CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
-CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+# CONFIG_CPU_FREQ_GOV_PERFORMANCE is not set
 # CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
-# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
 # CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+CONFIG_CPU_FREQ_SA1100=y
 
 #
 # Floating point emulation
@@ -298,7 +304,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=m
@@ -379,7 +384,6 @@
 # Networking options
 #
 # CONFIG_PACKET is not set
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -476,6 +480,7 @@
 # CONFIG_SMC_IRCC_FIR is not set
 # CONFIG_ALI_FIR is not set
 CONFIG_SA1100_FIR=m
+# CONFIG_VIA_FIR is not set
 # CONFIG_BT is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
@@ -647,7 +652,6 @@
 #
 # TPM devices
 #
-# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -676,9 +680,11 @@
 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_SA1100=y
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
diff --git a/arch/arm/configs/hackkit_defconfig b/arch/arm/configs/hackkit_defconfig
index 6987c8c..fb41a36 100644
--- a/arch/arm/configs/hackkit_defconfig
+++ b/arch/arm/configs/hackkit_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Mon Mar 28 00:22:34 2005
+# Linux kernel version: 2.6.12-rc6-git3
+# Thu Jun  9 20:58:58 2005
 #
 CONFIG_ARM=y
 CONFIG_MMU=y
@@ -16,6 +16,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -34,6 +35,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=y
@@ -109,7 +112,6 @@
 CONFIG_CPU_CACHE_V4WB=y
 CONFIG_CPU_CACHE_VIVT=y
 CONFIG_CPU_TLB_V4WB=y
-CONFIG_CPU_MINICACHE=y
 
 #
 # Processor Features
@@ -119,6 +121,7 @@
 # Bus support
 #
 CONFIG_ISA=y
+CONFIG_ISA_DMA_API=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -128,6 +131,7 @@
 #
 # Kernel Features
 #
+# CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
 CONFIG_DISCONTIGMEM=y
 CONFIG_LEDS=y
@@ -151,12 +155,14 @@
 # CONFIG_CPU_FREQ_DEBUG is not set
 CONFIG_CPU_FREQ_STAT=y
 # CONFIG_CPU_FREQ_STAT_DETAILS is not set
-CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
 # CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
-# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
 # CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
+# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_SA1100=y
 
 #
 # Floating point emulation
@@ -280,7 +286,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
@@ -338,7 +343,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
@@ -484,7 +488,6 @@
 CONFIG_SERIO_SERPORT=y
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -533,7 +536,6 @@
 #
 # TPM devices
 #
-# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
diff --git a/arch/arm/configs/ixdp2400_defconfig b/arch/arm/configs/ixdp2400_defconfig
index 4fd663e..3cfbe2e 100644
--- a/arch/arm/configs/ixdp2400_defconfig
+++ b/arch/arm/configs/ixdp2400_defconfig
@@ -1,14 +1,13 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 21:13:38 2005
+# Linux kernel version: 2.6.12-git6
+# Sat Jun 25 00:58:38 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
@@ -16,6 +15,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -35,6 +35,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=y
@@ -50,7 +52,13 @@
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+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
 
 #
 # System Type
@@ -76,6 +84,7 @@
 # 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_SUPPORTS_BIG_ENDIAN=y
 
 #
@@ -91,6 +100,7 @@
 CONFIG_ARCH_IXDP2X00=y
 # CONFIG_ARCH_IXDP2401 is not set
 # CONFIG_ARCH_IXDP2801 is not set
+# CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO is not set
 
 #
 # Processor Type
@@ -101,7 +111,6 @@
 CONFIG_CPU_ABRT_EV5T=y
 CONFIG_CPU_CACHE_VIVT=y
 CONFIG_CPU_TLB_V4WBI=y
-CONFIG_CPU_MINICACHE=y
 
 #
 # Processor Features
@@ -113,9 +122,11 @@
 #
 # Bus support
 #
+CONFIG_ISA_DMA_API=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -125,7 +136,15 @@
 #
 # Kernel Features
 #
+# CONFIG_SMP is not set
 # CONFIG_PREEMPT 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_ALIGNMENT_TRAP=y
 
 #
@@ -264,7 +283,6 @@
 #
 # 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
@@ -303,6 +321,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -324,10 +343,11 @@
 #
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
 CONFIG_IP_PNP=y
@@ -344,6 +364,17 @@
 # CONFIG_INET_TUNNEL is not set
 # CONFIG_IP_TCPDIAG is not set
 # CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
 # CONFIG_IPV6 is not set
 # CONFIG_NETFILTER is not set
 
@@ -399,6 +430,7 @@
 # CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
 
 #
 # Tulip family network device support
@@ -435,9 +467,11 @@
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
+# CONFIG_SKGE 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)
@@ -459,6 +493,7 @@
 # Wan interfaces
 #
 CONFIG_WAN=y
+# CONFIG_DSCC4 is not set
 # CONFIG_LANMEDIA is not set
 # CONFIG_SYNCLINK_SYNCPPP is not set
 CONFIG_HDLC=y
@@ -521,7 +556,6 @@
 #
 # CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -542,6 +576,7 @@
 #
 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
@@ -608,17 +643,18 @@
 # 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 is not set
 # CONFIG_I2C_IXP2000 is not set
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 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
+# CONFIG_I2C_STUB is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
@@ -632,7 +668,9 @@
 # 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_FSCHER is not set
 # CONFIG_SENSORS_FSCPOS is not set
@@ -648,6 +686,7 @@
 # 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_SMSC47B397 is not set
@@ -657,14 +696,19 @@
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
 
 #
 # Other 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_RTC8564 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
@@ -718,6 +762,7 @@
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 # 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=y
@@ -758,7 +803,6 @@
 #
 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
@@ -796,12 +840,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
@@ -886,3 +932,4 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
+# CONFIG_TEXTSEARCH is not set
diff --git a/arch/arm/configs/ixdp2401_defconfig b/arch/arm/configs/ixdp2401_defconfig
index 6f51c98..5c87e8e 100644
--- a/arch/arm/configs/ixdp2401_defconfig
+++ b/arch/arm/configs/ixdp2401_defconfig
@@ -1,14 +1,13 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 21:53:55 2005
+# Linux kernel version: 2.6.12-git6
+# Sat Jun 25 00:59:35 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
@@ -16,6 +15,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -35,6 +35,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=y
@@ -50,7 +52,13 @@
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+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
 
 #
 # System Type
@@ -76,6 +84,7 @@
 # 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_SUPPORTS_BIG_ENDIAN=y
 
 #
@@ -91,6 +100,7 @@
 CONFIG_ARCH_IXDP2401=y
 # CONFIG_ARCH_IXDP2801 is not set
 CONFIG_ARCH_IXDP2X01=y
+# CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO is not set
 
 #
 # Processor Type
@@ -101,7 +111,6 @@
 CONFIG_CPU_ABRT_EV5T=y
 CONFIG_CPU_CACHE_VIVT=y
 CONFIG_CPU_TLB_V4WBI=y
-CONFIG_CPU_MINICACHE=y
 
 #
 # Processor Features
@@ -113,9 +122,11 @@
 #
 # Bus support
 #
+CONFIG_ISA_DMA_API=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -125,7 +136,15 @@
 #
 # Kernel Features
 #
+# CONFIG_SMP is not set
 # CONFIG_PREEMPT 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_ALIGNMENT_TRAP=y
 
 #
@@ -264,7 +283,6 @@
 #
 # 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
@@ -303,6 +321,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -324,10 +343,11 @@
 #
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
 CONFIG_IP_PNP=y
@@ -344,6 +364,17 @@
 # CONFIG_INET_TUNNEL is not set
 CONFIG_IP_TCPDIAG=y
 # CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
 # CONFIG_IPV6 is not set
 # CONFIG_NETFILTER is not set
 
@@ -399,6 +430,7 @@
 # CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
 
 #
 # Tulip family network device support
@@ -436,9 +468,11 @@
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
+# CONFIG_SKGE 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)
@@ -460,6 +494,7 @@
 # Wan interfaces
 #
 CONFIG_WAN=y
+# CONFIG_DSCC4 is not set
 # CONFIG_LANMEDIA is not set
 # CONFIG_SYNCLINK_SYNCPPP is not set
 CONFIG_HDLC=y
@@ -522,7 +557,6 @@
 #
 # CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -543,6 +577,7 @@
 #
 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
@@ -609,17 +644,18 @@
 # 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 is not set
 # CONFIG_I2C_IXP2000 is not set
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 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
+# CONFIG_I2C_STUB is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
@@ -633,7 +669,9 @@
 # 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_FSCHER is not set
 # CONFIG_SENSORS_FSCPOS is not set
@@ -649,6 +687,7 @@
 # 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_SMSC47B397 is not set
@@ -658,14 +697,19 @@
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
 
 #
 # Other 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_RTC8564 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
@@ -719,6 +763,7 @@
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 # 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=y
@@ -759,7 +804,6 @@
 #
 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
@@ -797,12 +841,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
@@ -887,3 +933,4 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
+# CONFIG_TEXTSEARCH is not set
diff --git a/arch/arm/configs/ixdp2800_defconfig b/arch/arm/configs/ixdp2800_defconfig
index 7be3521..3cb561a 100644
--- a/arch/arm/configs/ixdp2800_defconfig
+++ b/arch/arm/configs/ixdp2800_defconfig
@@ -1,14 +1,13 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 22:15:23 2005
+# Linux kernel version: 2.6.12-git6
+# Sat Jun 25 01:00:27 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
@@ -16,6 +15,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -35,6 +35,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=y
@@ -50,7 +52,13 @@
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+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
 
 #
 # System Type
@@ -76,6 +84,7 @@
 # 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_SUPPORTS_BIG_ENDIAN=y
 
 #
@@ -91,6 +100,7 @@
 CONFIG_ARCH_IXDP2X00=y
 # CONFIG_ARCH_IXDP2401 is not set
 # CONFIG_ARCH_IXDP2801 is not set
+# CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO is not set
 
 #
 # Processor Type
@@ -101,7 +111,6 @@
 CONFIG_CPU_ABRT_EV5T=y
 CONFIG_CPU_CACHE_VIVT=y
 CONFIG_CPU_TLB_V4WBI=y
-CONFIG_CPU_MINICACHE=y
 
 #
 # Processor Features
@@ -113,9 +122,11 @@
 #
 # Bus support
 #
+CONFIG_ISA_DMA_API=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -125,7 +136,15 @@
 #
 # Kernel Features
 #
+# CONFIG_SMP is not set
 # CONFIG_PREEMPT 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_ALIGNMENT_TRAP=y
 
 #
@@ -264,7 +283,6 @@
 #
 # 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
@@ -303,6 +321,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -324,10 +343,11 @@
 #
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
 CONFIG_IP_PNP=y
@@ -344,6 +364,17 @@
 # CONFIG_INET_TUNNEL is not set
 # CONFIG_IP_TCPDIAG is not set
 # CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
 # CONFIG_IPV6 is not set
 # CONFIG_NETFILTER is not set
 
@@ -399,6 +430,7 @@
 # CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
 
 #
 # Tulip family network device support
@@ -435,9 +467,11 @@
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
+# CONFIG_SKGE 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)
@@ -459,6 +493,7 @@
 # Wan interfaces
 #
 CONFIG_WAN=y
+# CONFIG_DSCC4 is not set
 # CONFIG_LANMEDIA is not set
 # CONFIG_SYNCLINK_SYNCPPP is not set
 CONFIG_HDLC=y
@@ -521,7 +556,6 @@
 #
 # CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -542,6 +576,7 @@
 #
 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
@@ -608,17 +643,18 @@
 # 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 is not set
 # CONFIG_I2C_IXP2000 is not set
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 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
+# CONFIG_I2C_STUB is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
@@ -632,7 +668,9 @@
 # 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_FSCHER is not set
 # CONFIG_SENSORS_FSCPOS is not set
@@ -648,6 +686,7 @@
 # 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_SMSC47B397 is not set
@@ -657,14 +696,19 @@
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
 
 #
 # Other 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_RTC8564 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
@@ -718,6 +762,7 @@
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 # 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=y
@@ -758,7 +803,6 @@
 #
 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
@@ -796,12 +840,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
@@ -886,3 +932,4 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
+# CONFIG_TEXTSEARCH is not set
diff --git a/arch/arm/configs/ixdp2801_defconfig b/arch/arm/configs/ixdp2801_defconfig
index cd84a20..b1e162f 100644
--- a/arch/arm/configs/ixdp2801_defconfig
+++ b/arch/arm/configs/ixdp2801_defconfig
@@ -1,14 +1,13 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 22:39:19 2005
+# Linux kernel version: 2.6.12-git6
+# Sat Jun 25 01:01:18 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
@@ -16,6 +15,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -35,6 +35,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=y
@@ -50,7 +52,13 @@
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+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
 
 #
 # System Type
@@ -76,6 +84,7 @@
 # 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_SUPPORTS_BIG_ENDIAN=y
 
 #
@@ -91,6 +100,7 @@
 # CONFIG_ARCH_IXDP2401 is not set
 CONFIG_ARCH_IXDP2801=y
 CONFIG_ARCH_IXDP2X01=y
+# CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO is not set
 
 #
 # Processor Type
@@ -101,7 +111,6 @@
 CONFIG_CPU_ABRT_EV5T=y
 CONFIG_CPU_CACHE_VIVT=y
 CONFIG_CPU_TLB_V4WBI=y
-CONFIG_CPU_MINICACHE=y
 
 #
 # Processor Features
@@ -113,9 +122,11 @@
 #
 # Bus support
 #
+CONFIG_ISA_DMA_API=y
 CONFIG_PCI=y
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -125,7 +136,15 @@
 #
 # Kernel Features
 #
+# CONFIG_SMP is not set
 # CONFIG_PREEMPT 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_ALIGNMENT_TRAP=y
 
 #
@@ -264,7 +283,6 @@
 #
 # 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
@@ -303,6 +321,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -324,10 +343,11 @@
 #
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
 CONFIG_IP_PNP=y
@@ -344,6 +364,17 @@
 # CONFIG_INET_TUNNEL is not set
 # CONFIG_IP_TCPDIAG is not set
 # CONFIG_IP_TCPDIAG_IPV6 is not set
+
+#
+# TCP congestion control
+#
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
 # CONFIG_IPV6 is not set
 # CONFIG_NETFILTER is not set
 
@@ -399,6 +430,7 @@
 # CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
 
 #
 # Tulip family network device support
@@ -436,9 +468,11 @@
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
+# CONFIG_SKGE 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)
@@ -460,6 +494,7 @@
 # Wan interfaces
 #
 CONFIG_WAN=y
+# CONFIG_DSCC4 is not set
 # CONFIG_LANMEDIA is not set
 # CONFIG_SYNCLINK_SYNCPPP is not set
 CONFIG_HDLC=y
@@ -522,7 +557,6 @@
 #
 # CONFIG_SERIO is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -543,6 +577,7 @@
 #
 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
@@ -609,17 +644,18 @@
 # 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 is not set
 # CONFIG_I2C_IXP2000 is not set
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 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
+# CONFIG_I2C_STUB is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
@@ -633,7 +669,9 @@
 # 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_FSCHER is not set
 # CONFIG_SENSORS_FSCPOS is not set
@@ -649,6 +687,7 @@
 # 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_SMSC47B397 is not set
@@ -658,14 +697,19 @@
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
 # CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
 
 #
 # Other 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_RTC8564 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
@@ -719,6 +763,7 @@
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 # 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=y
@@ -759,7 +804,6 @@
 #
 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
@@ -797,12 +841,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
@@ -887,3 +933,4 @@
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
+# CONFIG_TEXTSEARCH is not set
diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig
index 2a63fb2..98b72ff 100644
--- a/arch/arm/configs/s3c2410_defconfig
+++ b/arch/arm/configs/s3c2410_defconfig
@@ -1,14 +1,13 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc1-bk2
-# Sun Mar 27 17:47:45 2005
+# Linux kernel version: 2.6.12-git4
+# Wed Jun 22 15:56:42 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
@@ -17,6 +16,7 @@
 # CONFIG_CLEAN_COMPILE is not set
 CONFIG_BROKEN=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -35,6 +35,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=y
@@ -81,6 +83,7 @@
 # CONFIG_ARCH_VERSATILE is not set
 # CONFIG_ARCH_IMX is not set
 # CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_AAEC2000 is not set
 
 #
 # S3C24XX Implementations
@@ -134,6 +137,7 @@
 #
 # Bus support
 #
+CONFIG_ISA_DMA_API=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -143,7 +147,9 @@
 #
 # Kernel Features
 #
+# CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
+# CONFIG_DISCONTIGMEM is not set
 CONFIG_ALIGNMENT_TRAP=y
 
 #
@@ -297,7 +303,6 @@
 #
 # Block devices
 #
-# CONFIG_BLK_DEV_FD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
@@ -359,6 +364,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -378,10 +384,11 @@
 # Networking options
 #
 # CONFIG_PACKET is not set
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_FIB_TRIE is not set
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
 CONFIG_IP_PNP=y
@@ -443,8 +450,9 @@
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
+CONFIG_MII=m
 # CONFIG_SMC91X is not set
+CONFIG_DM9000=m
 
 #
 # Ethernet (1000 Mbit)
@@ -521,7 +529,6 @@
 CONFIG_SERIO_LIBPS2=y
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
@@ -605,7 +612,6 @@
 #
 # TPM devices
 #
-# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -654,6 +660,7 @@
 CONFIG_SENSORS_LM85=m
 # 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_SMSC47B397 is not set
@@ -665,6 +672,7 @@
 #
 # Other I2C Chip support
 #
+# CONFIG_SENSORS_DS1337 is not set
 CONFIG_SENSORS_EEPROM=m
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCF8591 is not set
@@ -696,8 +704,10 @@
 # CONFIG_FB_CFB_COPYAREA is not set
 # CONFIG_FB_CFB_IMAGEBLIT is not set
 # CONFIG_FB_SOFT_CURSOR is not set
+# CONFIG_FB_MACMODES is not set
 CONFIG_FB_MODE_HELPERS=y
 # CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -782,7 +792,6 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
 # CONFIG_DEVPTS_FS_XATTR is not set
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLBFS is not set
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 4a2af55..3e1b032 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -6,7 +6,7 @@
 
 # Object file lists.
 
-obj-y		:= arch.o compat.o dma.o entry-armv.o entry-common.o irq.o   \
+obj-y		:= compat.o dma.o entry-armv.o entry-common.o irq.o \
 		   process.o ptrace.o semaphore.o setup.o signal.o sys_arm.o \
 		   time.o traps.o
 
diff --git a/arch/arm/kernel/arch.c b/arch/arm/kernel/arch.c
deleted file mode 100644
index 4e02fbe..0000000
--- a/arch/arm/kernel/arch.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *  linux/arch/arm/kernel/arch.c
- *
- *  Architecture specific fixups.
- */
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/types.h>
-
-#include <asm/elf.h>
-#include <asm/page.h>
-#include <asm/setup.h>
-#include <asm/mach/arch.h>
-
-unsigned int vram_size;
-
-#ifdef CONFIG_ARCH_ACORN
-
-unsigned int memc_ctrl_reg;
-unsigned int number_mfm_drives;
-
-static int __init parse_tag_acorn(const struct tag *tag)
-{
-	memc_ctrl_reg = tag->u.acorn.memc_control_reg;
-	number_mfm_drives = tag->u.acorn.adfsdrives;
-
-	switch (tag->u.acorn.vram_pages) {
-	case 512:
-		vram_size += PAGE_SIZE * 256;
-	case 256:
-		vram_size += PAGE_SIZE * 256;
-	default:
-		break;
-	}
-#if 0
-	if (vram_size) {
-		desc->video_start = 0x02000000;
-		desc->video_end   = 0x02000000 + vram_size;
-	}
-#endif
-	return 0;
-}
-
-__tagtable(ATAG_ACORN, parse_tag_acorn);
-
-#endif
diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
index 3dc15b1..6540db6 100644
--- a/arch/arm/kernel/ecard.c
+++ b/arch/arm/kernel/ecard.c
@@ -866,19 +866,19 @@
 	return ec;
 }
 
-static ssize_t ecard_show_irq(struct device *dev, char *buf)
+static ssize_t ecard_show_irq(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct expansion_card *ec = ECARD_DEV(dev);
 	return sprintf(buf, "%u\n", ec->irq);
 }
 
-static ssize_t ecard_show_dma(struct device *dev, char *buf)
+static ssize_t ecard_show_dma(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct expansion_card *ec = ECARD_DEV(dev);
 	return sprintf(buf, "%u\n", ec->dma);
 }
 
-static ssize_t ecard_show_resources(struct device *dev, char *buf)
+static ssize_t ecard_show_resources(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct expansion_card *ec = ECARD_DEV(dev);
 	char *str = buf;
@@ -893,19 +893,19 @@
 	return str - buf;
 }
 
-static ssize_t ecard_show_vendor(struct device *dev, char *buf)
+static ssize_t ecard_show_vendor(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct expansion_card *ec = ECARD_DEV(dev);
 	return sprintf(buf, "%u\n", ec->cid.manufacturer);
 }
 
-static ssize_t ecard_show_device(struct device *dev, char *buf)
+static ssize_t ecard_show_device(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct expansion_card *ec = ECARD_DEV(dev);
 	return sprintf(buf, "%u\n", ec->cid.product);
 }
 
-static ssize_t ecard_show_type(struct device *dev, char *buf)
+static ssize_t ecard_show_type(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct expansion_card *ec = ECARD_DEV(dev);
 	return sprintf(buf, "%s\n", ec->type == ECARD_EASI ? "EASI" : "IOC");
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 4eb3615..39a6c1b 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -24,48 +24,91 @@
 #include "entry-header.S"
 
 /*
+ * Interrupt handling.  Preserves r7, r8, r9
+ */
+	.macro	irq_handler
+1:	get_irqnr_and_base r0, r6, r5, lr
+	movne	r1, sp
+	@
+	@ routine called with r0 = irq number, r1 = struct pt_regs *
+	@
+	adrne	lr, 1b
+	bne	asm_do_IRQ
+
+#ifdef CONFIG_SMP
+	/*
+	 * XXX
+	 *
+	 * this macro assumes that irqstat (r6) and base (r5) are
+	 * preserved from get_irqnr_and_base above
+	 */
+	test_for_ipi r0, r6, r5, lr
+	movne	r0, sp
+	adrne	lr, 1b
+	bne	do_IPI
+#endif
+
+	.endm
+
+/*
  * Invalid mode handlers
  */
-	.macro	inv_entry, sym, reason
-	sub	sp, sp, #S_FRAME_SIZE		@ Allocate frame size in one go
-	stmia	sp, {r0 - lr}			@ Save XXX r0 - lr
-	ldr	r4, .LC\sym
+	.macro	inv_entry, reason
+	sub	sp, sp, #S_FRAME_SIZE
+	stmib	sp, {r1 - lr}
 	mov	r1, #\reason
 	.endm
 
 __pabt_invalid:
-	inv_entry abt, BAD_PREFETCH
-	b	1f
+	inv_entry BAD_PREFETCH
+	b	common_invalid
 
 __dabt_invalid:
-	inv_entry abt, BAD_DATA
-	b	1f
+	inv_entry BAD_DATA
+	b	common_invalid
 
 __irq_invalid:
-	inv_entry irq, BAD_IRQ
-	b	1f
+	inv_entry BAD_IRQ
+	b	common_invalid
 
 __und_invalid:
-	inv_entry und, BAD_UNDEFINSTR
+	inv_entry BAD_UNDEFINSTR
 
-1:	zero_fp
-	ldmia	r4, {r5 - r7}			@ Get XXX pc, cpsr, old_r0
-	add	r4, sp, #S_PC
-	stmia	r4, {r5 - r7}			@ Save XXX pc, cpsr, old_r0
+	@
+	@ XXX fall through to common_invalid
+	@
+
+@
+@ common_invalid - generic code for failed exception (re-entrant version of handlers)
+@
+common_invalid:
+	zero_fp
+
+	ldmia	r0, {r4 - r6}
+	add	r0, sp, #S_PC		@ here for interlock avoidance
+	mov	r7, #-1			@  ""   ""    ""        ""
+	str	r4, [sp]		@ save preserved r0
+	stmia	r0, {r5 - r7}		@ lr_<exception>,
+					@ cpsr_<exception>, "old_r0"
+
 	mov	r0, sp
-	and	r2, r6, #31			@ int mode
+	and	r2, r6, #0x1f
 	b	bad_mode
 
 /*
  * SVC mode handlers
  */
-	.macro	svc_entry, sym
+	.macro	svc_entry
 	sub	sp, sp, #S_FRAME_SIZE
-	stmia	sp, {r0 - r12}			@ save r0 - r12
-	ldr	r2, .LC\sym
-	add	r0, sp, #S_FRAME_SIZE
-	ldmia	r2, {r2 - r4}			@ get pc, cpsr
-	add	r5, sp, #S_SP
+	stmib	sp, {r1 - r12}
+
+	ldmia	r0, {r1 - r3}
+	add	r5, sp, #S_SP		@ here for interlock avoidance
+	mov	r4, #-1			@  ""  ""      ""       ""
+	add	r0, sp, #S_FRAME_SIZE   @  ""  ""      ""       ""
+	str	r1, [sp]		@ save the "real" r0 copied
+					@ from the exception stack
+
 	mov	r1, lr
 
 	@
@@ -82,7 +125,7 @@
 
 	.align	5
 __dabt_svc:
-	svc_entry abt
+	svc_entry
 
 	@
 	@ get ready to re-enable interrupts if appropriate
@@ -129,28 +172,24 @@
 
 	.align	5
 __irq_svc:
-	svc_entry irq
+	svc_entry
+
 #ifdef CONFIG_PREEMPT
-	get_thread_info r8
-	ldr	r9, [r8, #TI_PREEMPT]		@ get preempt count
-	add	r7, r9, #1			@ increment it
-	str	r7, [r8, #TI_PREEMPT]
+	get_thread_info tsk
+	ldr	r8, [tsk, #TI_PREEMPT]		@ get preempt count
+	add	r7, r8, #1			@ increment it
+	str	r7, [tsk, #TI_PREEMPT]
 #endif
-1:	get_irqnr_and_base r0, r6, r5, lr
-	movne	r1, sp
-	@
-	@ routine called with r0 = irq number, r1 = struct pt_regs *
-	@
-	adrne	lr, 1b
-	bne	asm_do_IRQ
+
+	irq_handler
 #ifdef CONFIG_PREEMPT
-	ldr	r0, [r8, #TI_FLAGS]		@ get flags
+	ldr	r0, [tsk, #TI_FLAGS]		@ get flags
 	tst	r0, #_TIF_NEED_RESCHED
 	blne	svc_preempt
 preempt_return:
-	ldr	r0, [r8, #TI_PREEMPT]		@ read preempt value
+	ldr	r0, [tsk, #TI_PREEMPT]		@ read preempt value
+	str	r8, [tsk, #TI_PREEMPT]		@ restore preempt count
 	teq	r0, r7
-	str	r9, [r8, #TI_PREEMPT]		@ restore preempt count
 	strne	r0, [r0, -r0]			@ bug()
 #endif
 	ldr	r0, [sp, #S_PSR]		@ irqs are already disabled
@@ -161,7 +200,7 @@
 
 #ifdef CONFIG_PREEMPT
 svc_preempt:
-	teq	r9, #0				@ was preempt count = 0
+	teq	r8, #0				@ was preempt count = 0
 	ldreq	r6, .LCirq_stat
 	movne	pc, lr				@ no
 	ldr	r0, [r6, #4]			@ local_irq_count
@@ -169,9 +208,9 @@
 	adds	r0, r0, r1
 	movne	pc, lr
 	mov	r7, #0				@ preempt_schedule_irq
-	str	r7, [r8, #TI_PREEMPT]		@ expects preempt_count == 0
+	str	r7, [tsk, #TI_PREEMPT]		@ expects preempt_count == 0
 1:	bl	preempt_schedule_irq		@ irq en/disable is done inside
-	ldr	r0, [r8, #TI_FLAGS]		@ get new tasks TI_FLAGS
+	ldr	r0, [tsk, #TI_FLAGS]		@ get new tasks TI_FLAGS
 	tst	r0, #_TIF_NEED_RESCHED
 	beq	preempt_return			@ go again
 	b	1b
@@ -179,7 +218,7 @@
 
 	.align	5
 __und_svc:
-	svc_entry und
+	svc_entry
 
 	@
 	@ call emulation code, which returns using r9 if it has emulated
@@ -209,7 +248,7 @@
 
 	.align	5
 __pabt_svc:
-	svc_entry abt
+	svc_entry
 
 	@
 	@ re-enable interrupts if appropriate
@@ -242,12 +281,8 @@
 	ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
 
 	.align	5
-.LCirq:
-	.word	__temp_irq
-.LCund:
-	.word	__temp_und
-.LCabt:
-	.word	__temp_abt
+.LCcralign:
+	.word	cr_alignment
 #ifdef MULTI_ABORT
 .LCprocfns:
 	.word	processor
@@ -262,14 +297,18 @@
 /*
  * User mode handlers
  */
-	.macro	usr_entry, sym
-	sub	sp, sp, #S_FRAME_SIZE		@ Allocate frame size in one go
-	stmia	sp, {r0 - r12}			@ save r0 - r12
-	ldr	r7, .LC\sym
-	add	r5, sp, #S_PC
-	ldmia	r7, {r2 - r4}			@ Get USR pc, cpsr
+	.macro	usr_entry
+	sub	sp, sp, #S_FRAME_SIZE
+	stmib	sp, {r1 - r12}
 
-#if __LINUX_ARM_ARCH__ < 6
+	ldmia	r0, {r1 - r3}
+	add	r0, sp, #S_PC		@ here for interlock avoidance
+	mov	r4, #-1			@  ""  ""     ""        ""
+
+	str	r1, [sp]		@ save the "real" r0 copied
+					@ from the exception stack
+
+#if __LINUX_ARM_ARCH__ < 6 && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
 	@ make sure our user space atomic helper is aborted
 	cmp	r2, #VIRT_OFFSET
 	bichs	r3, r3, #PSR_Z_BIT
@@ -284,13 +323,13 @@
 	@
 	@ Also, separately save sp_usr and lr_usr
 	@
-	stmia	r5, {r2 - r4}
-	stmdb	r5, {sp, lr}^
+	stmia	r0, {r2 - r4}
+	stmdb	r0, {sp, lr}^
 
 	@
 	@ Enable the alignment trap while in kernel mode
 	@
-	alignment_trap r7, r0, __temp_\sym
+	alignment_trap r0
 
 	@
 	@ Clear FP to mark the first stack frame
@@ -300,7 +339,7 @@
 
 	.align	5
 __dabt_usr:
-	usr_entry abt
+	usr_entry
 
 	@
 	@ Call the processor-specific abort handler:
@@ -329,30 +368,23 @@
 
 	.align	5
 __irq_usr:
-	usr_entry irq
+	usr_entry
 
-#ifdef CONFIG_PREEMPT
-	get_thread_info r8
-	ldr	r9, [r8, #TI_PREEMPT]		@ get preempt count
-	add	r7, r9, #1			@ increment it
-	str	r7, [r8, #TI_PREEMPT]
-#endif
-1:	get_irqnr_and_base r0, r6, r5, lr
-	movne	r1, sp
-	adrne	lr, 1b
-	@
-	@ routine called with r0 = irq number, r1 = struct pt_regs *
-	@
-	bne	asm_do_IRQ
-#ifdef CONFIG_PREEMPT
-	ldr	r0, [r8, #TI_PREEMPT]
-	teq	r0, r7
-	str	r9, [r8, #TI_PREEMPT]
-	strne	r0, [r0, -r0]
-	mov	tsk, r8
-#else
 	get_thread_info tsk
+#ifdef CONFIG_PREEMPT
+	ldr	r8, [tsk, #TI_PREEMPT]		@ get preempt count
+	add	r7, r8, #1			@ increment it
+	str	r7, [tsk, #TI_PREEMPT]
 #endif
+
+	irq_handler
+#ifdef CONFIG_PREEMPT
+	ldr	r0, [tsk, #TI_PREEMPT]
+	str	r8, [tsk, #TI_PREEMPT]
+	teq	r0, r7
+	strne	r0, [r0, -r0]
+#endif
+
 	mov	why, #0
 	b	ret_to_user
 
@@ -360,7 +392,7 @@
 
 	.align	5
 __und_usr:
-	usr_entry und
+	usr_entry
 
 	tst	r3, #PSR_T_BIT			@ Thumb mode?
 	bne	fpundefinstr			@ ignore FP
@@ -476,7 +508,7 @@
 
 	.align	5
 __pabt_usr:
-	usr_entry abt
+	usr_entry
 
 	enable_irq				@ Enable interrupts
 	mov	r0, r2				@ address (pc)
@@ -616,11 +648,17 @@
 
 __kuser_cmpxchg:				@ 0xffff0fc0
 
-#if __LINUX_ARM_ARCH__ < 6
+#if defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
 
-#ifdef CONFIG_SMP  /* sanity check */
-#error "CONFIG_SMP on a machine supporting pre-ARMv6 processors?"
-#endif
+	/*
+	 * Poor you.  No fast solution possible...
+	 * The kernel itself must perform the operation.
+	 * A special ghost syscall is used for that (see traps.c).
+	 */
+	swi	#0x9ffff0
+	mov	pc, lr
+
+#elif __LINUX_ARM_ARCH__ < 6
 
 	/*
 	 * Theory of operation:
@@ -735,29 +773,41 @@
  *
  * Common stub entry macro:
  *   Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
+ *
+ * SP points to a minimal amount of processor-private memory, the address
+ * of which is copied into r0 for the mode specific abort handler.
  */
-	.macro	vector_stub, name, sym, correction=0
+	.macro	vector_stub, name, correction=0
 	.align	5
 
 vector_\name:
-	ldr	r13, .LCs\sym
 	.if \correction
 	sub	lr, lr, #\correction
 	.endif
-	str	lr, [r13]			@ save lr_IRQ
-	mrs	lr, spsr
-	str	lr, [r13, #4]			@ save spsr_IRQ
-	@
-	@ now branch to the relevant MODE handling routine
-	@
-	mrs	r13, cpsr
-	bic	r13, r13, #MODE_MASK
-	orr	r13, r13, #SVC_MODE
-	msr	spsr_cxsf, r13			@ switch to SVC_32 mode
 
-	and	lr, lr, #15
+	@
+	@ Save r0, lr_<exception> (parent PC) and spsr_<exception>
+	@ (parent CPSR)
+	@
+	stmia	sp, {r0, lr}		@ save r0, lr
+	mrs	lr, spsr
+	str	lr, [sp, #8]		@ save spsr
+
+	@
+	@ Prepare for SVC32 mode.  IRQs remain disabled.
+	@
+	mrs	r0, cpsr
+	bic	r0, r0, #MODE_MASK
+	orr	r0, r0, #SVC_MODE
+	msr	spsr_cxsf, r0
+
+	@
+	@ the branch table must immediately follow this code
+	@
+	mov	r0, sp
+	and	lr, lr, #0x0f
 	ldr	lr, [pc, lr, lsl #2]
-	movs	pc, lr				@ Changes mode and branches
+	movs	pc, lr			@ branch to handler in SVC mode
 	.endm
 
 	.globl	__stubs_start
@@ -765,7 +815,7 @@
 /*
  * Interrupt dispatcher
  */
-	vector_stub	irq, irq, 4
+	vector_stub	irq, 4
 
 	.long	__irq_usr			@  0  (USR_26 / USR_32)
 	.long	__irq_invalid			@  1  (FIQ_26 / FIQ_32)
@@ -788,7 +838,7 @@
  * Data abort dispatcher
  * Enter in ABT mode, spsr = USR CPSR, lr = USR PC
  */
-	vector_stub	dabt, abt, 8
+	vector_stub	dabt, 8
 
 	.long	__dabt_usr			@  0  (USR_26 / USR_32)
 	.long	__dabt_invalid			@  1  (FIQ_26 / FIQ_32)
@@ -811,7 +861,7 @@
  * Prefetch abort dispatcher
  * Enter in ABT mode, spsr = USR CPSR, lr = USR PC
  */
-	vector_stub	pabt, abt, 4
+	vector_stub	pabt, 4
 
 	.long	__pabt_usr			@  0 (USR_26 / USR_32)
 	.long	__pabt_invalid			@  1 (FIQ_26 / FIQ_32)
@@ -834,7 +884,7 @@
  * Undef instr entry dispatcher
  * Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
  */
-	vector_stub	und, und
+	vector_stub	und
 
 	.long	__und_usr			@  0 (USR_26 / USR_32)
 	.long	__und_invalid			@  1 (FIQ_26 / FIQ_32)
@@ -888,13 +938,6 @@
 .LCvswi:
 	.word	vector_swi
 
-.LCsirq:
-	.word	__temp_irq
-.LCsund:
-	.word	__temp_und
-.LCsabt:
-	.word	__temp_abt
-
 	.globl	__stubs_end
 __stubs_end:
 
@@ -916,23 +959,6 @@
 
 	.data
 
-/*
- * Do not reorder these, and do not insert extra data between...
- */
-
-__temp_irq:
-	.word	0				@ saved lr_irq
-	.word	0				@ saved spsr_irq
-	.word	-1				@ old_r0
-__temp_und:
-	.word	0				@ Saved lr_und
-	.word	0				@ Saved spsr_und
-	.word	-1				@ old_r0
-__temp_abt:
-	.word	0				@ Saved lr_abt
-	.word	0				@ Saved spsr_abt
-	.word	-1				@ old_r0
-
 	.globl	cr_alignment
 	.globl	cr_no_alignment
 cr_alignment:
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index a3d40a0..afef212 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -59,11 +59,10 @@
 	mov	\rd, \rd, lsl #13
 	.endm
 
-	.macro	alignment_trap, rbase, rtemp, sym
+	.macro	alignment_trap, rtemp
 #ifdef CONFIG_ALIGNMENT_TRAP
-#define OFF_CR_ALIGNMENT(x)	cr_alignment - x
-
-	ldr	\rtemp, [\rbase, #OFF_CR_ALIGNMENT(\sym)]
+	ldr	\rtemp, .LCcralign
+	ldr	\rtemp, [\rtemp]
 	mcr	p15, 0, \rtemp, c1, c0
 #endif
 	.endm
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 4733877..bd4823c 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -2,6 +2,8 @@
  *  linux/arch/arm/kernel/head.S
  *
  *  Copyright (C) 1994-2002 Russell King
+ *  Copyright (c) 2003 ARM Limited
+ *  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 version 2 as
@@ -165,6 +167,48 @@
 	stmia	r6, {r0, r4}			@ Save control register values
 	b	start_kernel
 
+#if defined(CONFIG_SMP)
+	.type   secondary_startup, #function
+ENTRY(secondary_startup)
+	/*
+	 * Common entry point for secondary CPUs.
+	 *
+	 * Ensure that we're in SVC mode, and IRQs are disabled.  Lookup
+	 * 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
+	bl	__lookup_processor_type
+	movs	r10, r5				@ invalid processor?
+	moveq	r0, #'p'			@ yes, error 'p'
+	beq	__error
+
+	/*
+	 * Use the page tables supplied from  __cpu_up.
+	 */
+	adr	r4, __secondary_data
+	ldmia	r4, {r5, r6, r13}		@ address to jump to after
+	sub	r4, r4, r5			@ mmu has been enabled
+	ldr	r4, [r6, r4]			@ get secondary_data.pgdir
+	adr	lr, __enable_mmu		@ return address
+	add	pc, r10, #12			@ initialise processor
+						@ (return control reg)
+
+	/*
+	 * r6  = &secondary_data
+	 */
+ENTRY(__secondary_switched)
+	ldr	sp, [r6, #4]			@ get secondary_data.stack
+	mov	fp, #0
+	b	secondary_start_kernel
+
+	.type	__secondary_data, %object
+__secondary_data:
+	.long	.
+	.long	secondary_data
+	.long	__secondary_switched
+#endif /* defined(CONFIG_SMP) */
+
 
 
 /*
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index ff187f4..395137a 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -4,6 +4,10 @@
  *  Copyright (C) 1992 Linus Torvalds
  *  Modifications for ARM processor Copyright (C) 1995-2000 Russell King.
  *
+ *  Support for Dynamic Tick Timer Copyright (C) 2004-2005 Nokia Corporation.
+ *  Dynamic Tick Timer written by Tony Lindgren <tony@atomide.com> and
+ *  Tuukka Tikkanen <tuukka.tikkanen@elektrobit.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.
@@ -37,6 +41,7 @@
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/mach/irq.h>
+#include <asm/mach/time.h>
 
 /*
  * Maximum IRQ count.  Currently, this is arbitary.  However, it should
@@ -329,6 +334,15 @@
 
 	spin_unlock(&irq_controller_lock);
 
+#ifdef CONFIG_NO_IDLE_HZ
+	if (!(action->flags & SA_TIMER) && system_timer->dyn_tick != NULL) {
+		write_seqlock(&xtime_lock);
+		if (system_timer->dyn_tick->state & DYN_TICK_ENABLED)
+			system_timer->dyn_tick->handler(irq, 0, regs);
+		write_sequnlock(&xtime_lock);
+	}
+#endif
+
 	if (!(action->flags & SA_INTERRUPT))
 		local_irq_enable();
 
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index c2a7da3..8cf733d 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -92,6 +92,14 @@
 struct cpu_cache_fns cpu_cache;
 #endif
 
+struct stack {
+	u32 irq[3];
+	u32 abt[3];
+	u32 und[3];
+} ____cacheline_aligned;
+
+static struct stack stacks[NR_CPUS];
+
 char elf_platform[ELF_PLATFORM_SIZE];
 EXPORT_SYMBOL(elf_platform);
 
@@ -307,8 +315,6 @@
 	       cpu_name, processor_id, (int)processor_id & 15,
 	       proc_arch[cpu_architecture()]);
 
-	dump_cpu_info(smp_processor_id());
-
 	sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS);
 	sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
 	elf_hwcap = list->elf_hwcap;
@@ -316,6 +322,46 @@
 	cpu_proc_init();
 }
 
+/*
+ * cpu_init - initialise one CPU.
+ *
+ * cpu_init dumps the cache information, initialises SMP specific
+ * information, and sets up the per-CPU stacks.
+ */
+void cpu_init(void)
+{
+	unsigned int cpu = smp_processor_id();
+	struct stack *stk = &stacks[cpu];
+
+	if (cpu >= NR_CPUS) {
+		printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);
+		BUG();
+	}
+
+	dump_cpu_info(cpu);
+
+	/*
+	 * setup stacks for re-entrant exception handlers
+	 */
+	__asm__ (
+	"msr	cpsr_c, %1\n\t"
+	"add	sp, %0, %2\n\t"
+	"msr	cpsr_c, %3\n\t"
+	"add	sp, %0, %4\n\t"
+	"msr	cpsr_c, %5\n\t"
+	"add	sp, %0, %6\n\t"
+	"msr	cpsr_c, %7"
+	    :
+	    : "r" (stk),
+	      "I" (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
+	      "I" (offsetof(struct stack, irq[0])),
+	      "I" (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
+	      "I" (offsetof(struct stack, abt[0])),
+	      "I" (PSR_F_BIT | PSR_I_BIT | UND_MODE),
+	      "I" (offsetof(struct stack, und[0])),
+	      "I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE));
+}
+
 static struct machine_desc * __init setup_machine(unsigned int nr)
 {
 	struct machine_desc *list;
@@ -349,6 +395,20 @@
 }
 __early_param("initrd=", early_initrd);
 
+static void __init add_memory(unsigned long start, unsigned long size)
+{
+	/*
+	 * Ensure that start/size are aligned to a page boundary.
+	 * Size is appropriately rounded down, start is rounded up.
+	 */
+	size -= start & ~PAGE_MASK;
+
+	meminfo.bank[meminfo.nr_banks].start = PAGE_ALIGN(start);
+	meminfo.bank[meminfo.nr_banks].size  = size & PAGE_MASK;
+	meminfo.bank[meminfo.nr_banks].node  = PHYS_TO_NID(start);
+	meminfo.nr_banks += 1;
+}
+
 /*
  * Pick out the memory size.  We look for mem=size@start,
  * where start and size are "size[KkMm]"
@@ -373,10 +433,7 @@
 	if (**p == '@')
 		start = memparse(*p + 1, p);
 
-	meminfo.bank[meminfo.nr_banks].start = start;
-	meminfo.bank[meminfo.nr_banks].size  = size;
-	meminfo.bank[meminfo.nr_banks].node  = PHYS_TO_NID(start);
-	meminfo.nr_banks += 1;
+	add_memory(start, size);
 }
 __early_param("mem=", early_mem);
 
@@ -518,11 +575,7 @@
 			tag->u.mem.start, tag->u.mem.size / 1024);
 		return -EINVAL;
 	}
-	meminfo.bank[meminfo.nr_banks].start = tag->u.mem.start;
-	meminfo.bank[meminfo.nr_banks].size  = tag->u.mem.size;
-	meminfo.bank[meminfo.nr_banks].node  = PHYS_TO_NID(tag->u.mem.start);
-	meminfo.nr_banks += 1;
-
+	add_memory(tag->u.mem.start, tag->u.mem.size);
 	return 0;
 }
 
@@ -715,6 +768,8 @@
 	paging_init(&meminfo, mdesc);
 	request_standard_resources(&meminfo, mdesc);
 
+	cpu_init();
+
 	/*
 	 * Set up various architecture-specific pointers
 	 */
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 931919f..5e435e4 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -19,6 +19,7 @@
 #include <asm/unistd.h>
 
 #include "ptrace.h"
+#include "signal.h"
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
@@ -35,7 +36,7 @@
 #define SWI_THUMB_SIGRETURN	(0xdf00 << 16 | 0x2700 | (__NR_sigreturn - __NR_SYSCALL_BASE))
 #define SWI_THUMB_RT_SIGRETURN	(0xdf00 << 16 | 0x2700 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE))
 
-static const unsigned long retcodes[4] = {
+const unsigned long sigreturn_codes[4] = {
 	SWI_SYS_SIGRETURN,	SWI_THUMB_SIGRETURN,
 	SWI_SYS_RT_SIGRETURN,	SWI_THUMB_RT_SIGRETURN
 };
@@ -500,17 +501,25 @@
 		if (ka->sa.sa_flags & SA_SIGINFO)
 			idx += 2;
 
-		if (__put_user(retcodes[idx], rc))
+		if (__put_user(sigreturn_codes[idx], rc))
 			return 1;
 
-		/*
-		 * Ensure that the instruction cache sees
-		 * the return code written onto the stack.
-		 */
-		flush_icache_range((unsigned long)rc,
-				   (unsigned long)(rc + 1));
+		if (cpsr & MODE32_BIT) {
+			/*
+			 * 32-bit code can use the new high-page
+			 * signal return code support.
+			 */
+			retcode = KERN_SIGRETURN_CODE + (idx << 2) + thumb;
+		} else {
+			/*
+			 * Ensure that the instruction cache sees
+			 * the return code written onto the stack.
+			 */
+			flush_icache_range((unsigned long)rc,
+					   (unsigned long)(rc + 1));
 
-		retcode = ((unsigned long)rc) + thumb;
+			retcode = ((unsigned long)rc) + thumb;
+		}
 	}
 
 	regs->ARM_r0 = usig;
@@ -688,7 +697,7 @@
 	if (!user_mode(regs))
 		return 0;
 
-	if (try_to_freeze(0))
+	if (try_to_freeze())
 		goto no_signal;
 
 	if (current->ptrace & PT_SINGLESTEP)
diff --git a/arch/arm/kernel/signal.h b/arch/arm/kernel/signal.h
new file mode 100644
index 0000000..91d26fa
--- /dev/null
+++ b/arch/arm/kernel/signal.h
@@ -0,0 +1,12 @@
+/*
+ *  linux/arch/arm/kernel/signal.h
+ *
+ *  Copyright (C) 2005 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.
+ */
+#define KERN_SIGRETURN_CODE	0xffff0500
+
+extern const unsigned long sigreturn_codes[4];
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index ecc8c33..3489275 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -24,6 +24,9 @@
 #include <asm/atomic.h>
 #include <asm/cacheflush.h>
 #include <asm/cpu.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
 #include <asm/processor.h>
 #include <asm/tlbflush.h>
 #include <asm/ptrace.h>
@@ -37,6 +40,13 @@
 cpumask_t cpu_online_map;
 
 /*
+ * as from 2.5, kernels no longer have an init_tasks structure
+ * so we need some other way of telling a new secondary core
+ * where to place its SVC stack
+ */
+struct secondary_data secondary_data;
+
+/*
  * structures for inter-processor calls
  * - A collection of single bit ipi messages.
  */
@@ -71,6 +81,8 @@
 int __init __cpu_up(unsigned int cpu)
 {
 	struct task_struct *idle;
+	pgd_t *pgd;
+	pmd_t *pmd;
 	int ret;
 
 	/*
@@ -84,11 +96,57 @@
 	}
 
 	/*
+	 * Allocate initial page tables to allow the new CPU to
+	 * enable the MMU safely.  This essentially means a set
+	 * of our "standard" page tables, with the addition of
+	 * a 1:1 mapping for the physical address of the kernel.
+	 */
+	pgd = pgd_alloc(&init_mm);
+	pmd = pmd_offset(pgd, PHYS_OFFSET);
+	*pmd = __pmd((PHYS_OFFSET & PGDIR_MASK) |
+		     PMD_TYPE_SECT | PMD_SECT_AP_WRITE);
+
+	/*
+	 * We need to tell the secondary core where to find
+	 * its stack and the page tables.
+	 */
+	secondary_data.stack = (void *)idle->thread_info + THREAD_SIZE - 8;
+	secondary_data.pgdir = virt_to_phys(pgd);
+	wmb();
+
+	/*
 	 * Now bring the CPU into our world.
 	 */
 	ret = boot_secondary(cpu, idle);
+	if (ret == 0) {
+		unsigned long timeout;
+
+		/*
+		 * CPU was successfully started, wait for it
+		 * to come online or time out.
+		 */
+		timeout = jiffies + HZ;
+		while (time_before(jiffies, timeout)) {
+			if (cpu_online(cpu))
+				break;
+
+			udelay(10);
+			barrier();
+		}
+
+		if (!cpu_online(cpu))
+			ret = -EIO;
+	}
+
+	secondary_data.stack = 0;
+	secondary_data.pgdir = 0;
+
+	*pmd_offset(pgd, PHYS_OFFSET) = __pmd(0);
+	pgd_free(pgd);
+
 	if (ret) {
-		printk(KERN_CRIT "cpu_up: processor %d failed to boot\n", cpu);
+		printk(KERN_CRIT "CPU%u: processor failed to boot\n", cpu);
+
 		/*
 		 * FIXME: We need to clean up the new idle thread. --rmk
 		 */
@@ -98,6 +156,56 @@
 }
 
 /*
+ * This is the secondary CPU boot entry.  We're using this CPUs
+ * idle thread stack, but a set of temporary page tables.
+ */
+asmlinkage void __init secondary_start_kernel(void)
+{
+	struct mm_struct *mm = &init_mm;
+	unsigned int cpu = smp_processor_id();
+
+	printk("CPU%u: Booted secondary processor\n", cpu);
+
+	/*
+	 * All kernel threads share the same mm context; grab a
+	 * reference and switch to it.
+	 */
+	atomic_inc(&mm->mm_users);
+	atomic_inc(&mm->mm_count);
+	current->active_mm = mm;
+	cpu_set(cpu, mm->cpu_vm_mask);
+	cpu_switch_mm(mm->pgd, mm);
+	enter_lazy_tlb(mm, current);
+
+	cpu_init();
+
+	/*
+	 * Give the platform a chance to do its own initialisation.
+	 */
+	platform_secondary_init(cpu);
+
+	/*
+	 * Enable local interrupts.
+	 */
+	local_irq_enable();
+	local_fiq_enable();
+
+	calibrate_delay();
+
+	smp_store_cpu_info(cpu);
+
+	/*
+	 * OK, now it's safe to let the boot CPU continue
+	 */
+	cpu_set(cpu, cpu_online_map);
+
+	/*
+	 * OK, it's off to the idle thread for us
+	 */
+	cpu_idle();
+}
+
+/*
  * Called by both boot and secondaries to move global data into
  * per-processor storage.
  */
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index c232f24..06054c9 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -381,6 +381,95 @@
 	.resume		= timer_resume,
 };
 
+#ifdef CONFIG_NO_IDLE_HZ
+static int timer_dyn_tick_enable(void)
+{
+	struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick;
+	unsigned long flags;
+	int ret = -ENODEV;
+
+	if (dyn_tick) {
+		write_seqlock_irqsave(&xtime_lock, flags);
+		ret = 0;
+		if (!(dyn_tick->state & DYN_TICK_ENABLED)) {
+			ret = dyn_tick->enable();
+
+			if (ret == 0)
+				dyn_tick->state |= DYN_TICK_ENABLED;
+		}
+		write_sequnlock_irqrestore(&xtime_lock, flags);
+	}
+
+	return ret;
+}
+
+static int timer_dyn_tick_disable(void)
+{
+	struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick;
+	unsigned long flags;
+	int ret = -ENODEV;
+
+	if (dyn_tick) {
+		write_seqlock_irqsave(&xtime_lock, flags);
+		ret = 0;
+		if (dyn_tick->state & DYN_TICK_ENABLED) {
+			ret = dyn_tick->disable();
+
+			if (ret == 0)
+				dyn_tick->state &= ~DYN_TICK_ENABLED;
+		}
+		write_sequnlock_irqrestore(&xtime_lock, flags);
+	}
+
+	return ret;
+}
+
+void timer_dyn_reprogram(void)
+{
+	struct dyn_tick_timer *dyn_tick = system_timer->dyn_tick;
+	unsigned long flags;
+
+	write_seqlock_irqsave(&xtime_lock, flags);
+	if (dyn_tick->state & DYN_TICK_ENABLED)
+		dyn_tick->reprogram(next_timer_interrupt() - jiffies);
+	write_sequnlock_irqrestore(&xtime_lock, flags);
+}
+
+static ssize_t timer_show_dyn_tick(struct sys_device *dev, char *buf)
+{
+	return sprintf(buf, "%i\n",
+		       (system_timer->dyn_tick->state & DYN_TICK_ENABLED) >> 1);
+}
+
+static ssize_t timer_set_dyn_tick(struct sys_device *dev, const char *buf,
+				  size_t count)
+{
+	unsigned int enable = simple_strtoul(buf, NULL, 2);
+
+	if (enable)
+		timer_dyn_tick_enable();
+	else
+		timer_dyn_tick_disable();
+
+	return count;
+}
+static SYSDEV_ATTR(dyn_tick, 0644, timer_show_dyn_tick, timer_set_dyn_tick);
+
+/*
+ * dyntick=enable|disable
+ */
+static char dyntick_str[4] __initdata = "";
+
+static int __init dyntick_setup(char *str)
+{
+	if (str)
+		strlcpy(dyntick_str, str, sizeof(dyntick_str));
+	return 1;
+}
+
+__setup("dyntick=", dyntick_setup);
+#endif
+
 static int __init timer_init_sysfs(void)
 {
 	int ret = sysdev_class_register(&timer_sysclass);
@@ -388,6 +477,20 @@
 		system_timer->dev.cls = &timer_sysclass;
 		ret = sysdev_register(&system_timer->dev);
 	}
+
+#ifdef CONFIG_NO_IDLE_HZ
+	if (ret == 0 && system_timer->dyn_tick) {
+		ret = sysdev_create_file(&system_timer->dev, &attr_dyn_tick);
+
+		/*
+		 * Turn on dynamic tick after calibrate delay
+		 * for correct bogomips
+		 */
+		if (ret == 0 && dyntick_str[0] == 'e')
+			ret = timer_dyn_tick_enable();
+	}
+#endif
+
 	return ret;
 }
 
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 14df16b..2fb0a4c 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -30,6 +30,7 @@
 #include <asm/traps.h>
 
 #include "ptrace.h"
+#include "signal.h"
 
 const char *processor_modes[]=
 { "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
@@ -464,6 +465,55 @@
 #endif
 		return 0;
 
+#ifdef CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG
+	/*
+	 * Atomically store r1 in *r2 if *r2 is equal to r0 for user space.
+	 * Return zero in r0 if *MEM was changed or non-zero if no exchange
+	 * happened.  Also set the user C flag accordingly.
+	 * If access permissions have to be fixed up then non-zero is
+	 * returned and the operation has to be re-attempted.
+	 *
+	 * *NOTE*: This is a ghost syscall private to the kernel.  Only the
+	 * __kuser_cmpxchg code in entry-armv.S should be aware of its
+	 * existence.  Don't ever use this from user code.
+	 */
+	case 0xfff0:
+	{
+		extern void do_DataAbort(unsigned long addr, unsigned int fsr,
+					 struct pt_regs *regs);
+		unsigned long val;
+		unsigned long addr = regs->ARM_r2;
+		struct mm_struct *mm = current->mm;
+		pgd_t *pgd; pmd_t *pmd; pte_t *pte;
+
+		regs->ARM_cpsr &= ~PSR_C_BIT;
+		spin_lock(&mm->page_table_lock);
+		pgd = pgd_offset(mm, addr);
+		if (!pgd_present(*pgd))
+			goto bad_access;
+		pmd = pmd_offset(pgd, addr);
+		if (!pmd_present(*pmd))
+			goto bad_access;
+		pte = pte_offset_map(pmd, addr);
+		if (!pte_present(*pte) || !pte_write(*pte))
+			goto bad_access;
+		val = *(unsigned long *)addr;
+		val -= regs->ARM_r0;
+		if (val == 0) {
+			*(unsigned long *)addr = regs->ARM_r1;
+			regs->ARM_cpsr |= PSR_C_BIT;
+		}
+		spin_unlock(&mm->page_table_lock);
+		return val;
+
+		bad_access:
+		spin_unlock(&mm->page_table_lock);
+		/* simulate a read access fault */
+		do_DataAbort(addr, 15 + (1 << 11), regs);
+		return -1;
+	}
+#endif
+
 	default:
 		/* Calls 9f00xx..9f07ff are defined to return -ENOSYS
 		   if not implemented, rather than raising SIGILL.  This
@@ -634,6 +684,14 @@
 	memcpy((void *)0xffff0000, __vectors_start, __vectors_end - __vectors_start);
 	memcpy((void *)0xffff0200, __stubs_start, __stubs_end - __stubs_start);
 	memcpy((void *)0xffff1000 - kuser_sz, __kuser_helper_start, kuser_sz);
+
+	/*
+	 * Copy signal return handlers into the vector page, and
+	 * set sigreturn to be a pointer to these.
+	 */
+	memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes,
+	       sizeof(sigreturn_codes));
+
 	flush_icache_range(0xffff0000, 0xffff0000 + PAGE_SIZE);
 	modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
 }
diff --git a/arch/arm/lib/ashldi3.c b/arch/arm/lib/ashldi3.c
index 130f5a8..b62875c 100644
--- a/arch/arm/lib/ashldi3.c
+++ b/arch/arm/lib/ashldi3.c
@@ -31,31 +31,26 @@
 
 #include "gcclib.h"
 
-DItype
-__ashldi3 (DItype u, word_type b)
+s64 __ashldi3(s64 u, int b)
 {
-  DIunion w;
-  word_type bm;
-  DIunion uu;
+	DIunion w;
+	int bm;
+	DIunion uu;
 
-  if (b == 0)
-    return u;
+	if (b == 0)
+		return u;
 
-  uu.ll = u;
+	uu.ll = u;
 
-  bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
-  if (bm <= 0)
-    {
-      w.s.low = 0;
-      w.s.high = (USItype)uu.s.low << -bm;
-    }
-  else
-    {
-      USItype carries = (USItype)uu.s.low >> bm;
-      w.s.low = (USItype)uu.s.low << b;
-      w.s.high = ((USItype)uu.s.high << b) | carries;
-    }
+	bm = (sizeof(s32) * BITS_PER_UNIT) - b;
+	if (bm <= 0) {
+		w.s.low = 0;
+		w.s.high = (u32) uu.s.low << -bm;
+	} else {
+		u32 carries = (u32) uu.s.low >> bm;
+		w.s.low = (u32) uu.s.low << b;
+		w.s.high = ((u32) uu.s.high << b) | carries;
+	}
 
-  return w.ll;
+	return w.ll;
 }
-
diff --git a/arch/arm/lib/ashrdi3.c b/arch/arm/lib/ashrdi3.c
index 71625d2..9a8600a 100644
--- a/arch/arm/lib/ashrdi3.c
+++ b/arch/arm/lib/ashrdi3.c
@@ -31,31 +31,27 @@
 
 #include "gcclib.h"
 
-DItype
-__ashrdi3 (DItype u, word_type b)
+s64 __ashrdi3(s64 u, int b)
 {
-  DIunion w;
-  word_type bm;
-  DIunion uu;
+	DIunion w;
+	int bm;
+	DIunion uu;
 
-  if (b == 0)
-    return u;
+	if (b == 0)
+		return u;
 
-  uu.ll = u;
+	uu.ll = u;
 
-  bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
-  if (bm <= 0)
-    {
-      /* w.s.high = 1..1 or 0..0 */
-      w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
-      w.s.low = uu.s.high >> -bm;
-    }
-  else
-    {
-      USItype carries = (USItype)uu.s.high << bm;
-      w.s.high = uu.s.high >> b;
-      w.s.low = ((USItype)uu.s.low >> b) | carries;
-    }
+	bm = (sizeof(s32) * BITS_PER_UNIT) - b;
+	if (bm <= 0) {
+		/* w.s.high = 1..1 or 0..0 */
+		w.s.high = uu.s.high >> (sizeof(s32) * BITS_PER_UNIT - 1);
+		w.s.low = uu.s.high >> -bm;
+	} else {
+		u32 carries = (u32) uu.s.high << bm;
+		w.s.high = uu.s.high >> b;
+		w.s.low = ((u32) uu.s.low >> b) | carries;
+	}
 
-  return w.ll;
+	return w.ll;
 }
diff --git a/arch/arm/lib/gcclib.h b/arch/arm/lib/gcclib.h
index 65314a3..8b6dcc6 100644
--- a/arch/arm/lib/gcclib.h
+++ b/arch/arm/lib/gcclib.h
@@ -1,25 +1,22 @@
 /* gcclib.h -- definitions for various functions 'borrowed' from gcc-2.95.3 */
 /* I Molton     29/07/01 */
 
-#define BITS_PER_UNIT  8
-#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
+#include <linux/types.h>
 
-typedef unsigned int UQItype    __attribute__ ((mode (QI)));
-typedef          int SItype     __attribute__ ((mode (SI)));
-typedef unsigned int USItype    __attribute__ ((mode (SI)));
-typedef          int DItype     __attribute__ ((mode (DI)));
-typedef          int word_type 	__attribute__ ((mode (__word__)));
-typedef unsigned int UDItype    __attribute__ ((mode (DI)));
+#define BITS_PER_UNIT	8
+#define SI_TYPE_SIZE	(sizeof(s32) * BITS_PER_UNIT)
 
 #ifdef __ARMEB__
-  struct DIstruct {SItype high, low;};
+struct DIstruct {
+	s32 high, low;
+};
 #else
-  struct DIstruct {SItype low, high;};
+struct DIstruct {
+	s32 low, high;
+};
 #endif
 
-typedef union
-{
-  struct DIstruct s;
-  DItype ll;
+typedef union {
+	struct DIstruct s;
+	s64 ll;
 } DIunion;
-
diff --git a/arch/arm/lib/io-writesw-armv4.S b/arch/arm/lib/io-writesw-armv4.S
index 6d1d7c2..5e240e4 100644
--- a/arch/arm/lib/io-writesw-armv4.S
+++ b/arch/arm/lib/io-writesw-armv4.S
@@ -87,9 +87,9 @@
 		subs	r2, r2, #2
 		orr	ip, ip, r3, push_hbyte1
 		strh	ip, [r0]
-		bpl	2b
+		bpl	1b
 
-3:		tst	r2, #1
-2:		movne	ip, r3, lsr #8
+		tst	r2, #1
+3:		movne	ip, r3, lsr #8
 		strneh	ip, [r0]
 		mov	pc, lr
diff --git a/arch/arm/lib/longlong.h b/arch/arm/lib/longlong.h
index 179eea4..90ae647 100644
--- a/arch/arm/lib/longlong.h
+++ b/arch/arm/lib/longlong.h
@@ -26,18 +26,18 @@
 
 #define __BITS4 (SI_TYPE_SIZE / 4)
 #define __ll_B (1L << (SI_TYPE_SIZE / 2))
-#define __ll_lowpart(t) ((USItype) (t) % __ll_B)
-#define __ll_highpart(t) ((USItype) (t) / __ll_B)
+#define __ll_lowpart(t) ((u32) (t) % __ll_B)
+#define __ll_highpart(t) ((u32) (t) / __ll_B)
 
 /* Define auxiliary asm macros.
 
    1) umul_ppmm(high_prod, low_prod, multipler, multiplicand)
-   multiplies two USItype integers MULTIPLER and MULTIPLICAND,
-   and generates a two-part USItype product in HIGH_PROD and
+   multiplies two u32 integers MULTIPLER and MULTIPLICAND,
+   and generates a two-part u32 product in HIGH_PROD and
    LOW_PROD.
 
-   2) __umulsidi3(a,b) multiplies two USItype integers A and B,
-   and returns a UDItype product.  This is just a variant of umul_ppmm.
+   2) __umulsidi3(a,b) multiplies two u32 integers A and B,
+   and returns a u64 product.  This is just a variant of umul_ppmm.
 
    3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
    denominator) divides a two-word unsigned integer, composed by the
@@ -77,23 +77,23 @@
 #define add_ssaaaa(sh, sl, ah, al, bh, bl) \
   __asm__ ("adds	%1, %4, %5					\n\
 	adc	%0, %2, %3"						\
-	   : "=r" ((USItype) (sh)),					\
-	     "=&r" ((USItype) (sl))					\
-	   : "%r" ((USItype) (ah)),					\
-	     "rI" ((USItype) (bh)),					\
-	     "%r" ((USItype) (al)),					\
-	     "rI" ((USItype) (bl)))
+	   : "=r" ((u32) (sh)),					\
+	     "=&r" ((u32) (sl))					\
+	   : "%r" ((u32) (ah)),					\
+	     "rI" ((u32) (bh)),					\
+	     "%r" ((u32) (al)),					\
+	     "rI" ((u32) (bl)))
 #define sub_ddmmss(sh, sl, ah, al, bh, bl) \
   __asm__ ("subs	%1, %4, %5					\n\
 	sbc	%0, %2, %3"						\
-	   : "=r" ((USItype) (sh)),					\
-	     "=&r" ((USItype) (sl))					\
-	   : "r" ((USItype) (ah)),					\
-	     "rI" ((USItype) (bh)),					\
-	     "r" ((USItype) (al)),					\
-	     "rI" ((USItype) (bl)))
+	   : "=r" ((u32) (sh)),					\
+	     "=&r" ((u32) (sl))					\
+	   : "r" ((u32) (ah)),					\
+	     "rI" ((u32) (bh)),					\
+	     "r" ((u32) (al)),					\
+	     "rI" ((u32) (bl)))
 #define umul_ppmm(xh, xl, a, b) \
-{register USItype __t0, __t1, __t2;					\
+{register u32 __t0, __t1, __t2;					\
   __asm__ ("%@ Inlined umul_ppmm					\n\
 	mov	%2, %5, lsr #16						\n\
 	mov	%0, %6, lsr #16						\n\
@@ -107,14 +107,14 @@
 	addcs	%0, %0, #65536						\n\
 	adds	%1, %1, %3, lsl #16					\n\
 	adc	%0, %0, %3, lsr #16"					\
-	   : "=&r" ((USItype) (xh)),					\
-	     "=r" ((USItype) (xl)),					\
+	   : "=&r" ((u32) (xh)),					\
+	     "=r" ((u32) (xl)),					\
 	     "=&r" (__t0), "=&r" (__t1), "=r" (__t2)			\
-	   : "r" ((USItype) (a)),					\
-	     "r" ((USItype) (b)));}
+	   : "r" ((u32) (a)),					\
+	     "r" ((u32) (b)));}
 #define UMUL_TIME 20
 #define UDIV_TIME 100
-#endif /* __arm__ */
+#endif				/* __arm__ */
 
 #define __umulsidi3(u, v) \
   ({DIunion __w;							\
@@ -123,14 +123,14 @@
 
 #define __udiv_qrnnd_c(q, r, n1, n0, d) \
   do {									\
-    USItype __d1, __d0, __q1, __q0;					\
-    USItype __r1, __r0, __m;						\
+    u32 __d1, __d0, __q1, __q0;					\
+    u32 __r1, __r0, __m;						\
     __d1 = __ll_highpart (d);						\
     __d0 = __ll_lowpart (d);						\
 									\
     __r1 = (n1) % __d1;							\
     __q1 = (n1) / __d1;							\
-    __m = (USItype) __q1 * __d0;					\
+    __m = (u32) __q1 * __d0;					\
     __r1 = __r1 * __ll_B | __ll_highpart (n0);				\
     if (__r1 < __m)							\
       {									\
@@ -143,7 +143,7 @@
 									\
     __r0 = __r1 % __d1;							\
     __q0 = __r1 / __d1;							\
-    __m = (USItype) __q0 * __d0;					\
+    __m = (u32) __q0 * __d0;					\
     __r0 = __r0 * __ll_B | __ll_lowpart (n0);				\
     if (__r0 < __m)							\
       {									\
@@ -154,7 +154,7 @@
       }									\
     __r0 -= __m;							\
 									\
-    (q) = (USItype) __q1 * __ll_B | __q0;				\
+    (q) = (u32) __q1 * __ll_B | __q0;				\
     (r) = __r0;								\
   } while (0)
 
@@ -163,14 +163,14 @@
 
 #define count_leading_zeros(count, x) \
   do {									\
-    USItype __xr = (x);							\
-    USItype __a;							\
+    u32 __xr = (x);							\
+    u32 __a;							\
 									\
     if (SI_TYPE_SIZE <= 32)						\
       {									\
-	__a = __xr < ((USItype)1<<2*__BITS4)				\
-	  ? (__xr < ((USItype)1<<__BITS4) ? 0 : __BITS4)		\
-	  : (__xr < ((USItype)1<<3*__BITS4) ?  2*__BITS4 : 3*__BITS4);	\
+	__a = __xr < ((u32)1<<2*__BITS4)				\
+	  ? (__xr < ((u32)1<<__BITS4) ? 0 : __BITS4)		\
+	  : (__xr < ((u32)1<<3*__BITS4) ?  2*__BITS4 : 3*__BITS4);	\
       }									\
     else								\
       {									\
diff --git a/arch/arm/lib/lshrdi3.c b/arch/arm/lib/lshrdi3.c
index b666f1b..3681f49 100644
--- a/arch/arm/lib/lshrdi3.c
+++ b/arch/arm/lib/lshrdi3.c
@@ -31,31 +31,26 @@
 
 #include "gcclib.h"
 
-DItype
-__lshrdi3 (DItype u, word_type b)
+s64 __lshrdi3(s64 u, int b)
 {
-  DIunion w;
-  word_type bm;
-  DIunion uu;
+	DIunion w;
+	int bm;
+	DIunion uu;
 
-  if (b == 0)
-    return u;
+	if (b == 0)
+		return u;
 
-  uu.ll = u;
+	uu.ll = u;
 
-  bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
-  if (bm <= 0)
-    {
-      w.s.high = 0;
-      w.s.low = (USItype)uu.s.high >> -bm;
-    }
-  else
-    {
-      USItype carries = (USItype)uu.s.high << bm;
-      w.s.high = (USItype)uu.s.high >> b;
-      w.s.low = ((USItype)uu.s.low >> b) | carries;
-    }
+	bm = (sizeof(s32) * BITS_PER_UNIT) - b;
+	if (bm <= 0) {
+		w.s.high = 0;
+		w.s.low = (u32) uu.s.high >> -bm;
+	} else {
+		u32 carries = (u32) uu.s.high << bm;
+		w.s.high = (u32) uu.s.high >> b;
+		w.s.low = ((u32) uu.s.low >> b) | carries;
+	}
 
-  return w.ll;
+	return w.ll;
 }
-
diff --git a/arch/arm/lib/muldi3.c b/arch/arm/lib/muldi3.c
index 44d611b..0a3b933 100644
--- a/arch/arm/lib/muldi3.c
+++ b/arch/arm/lib/muldi3.c
@@ -32,7 +32,7 @@
 #include "gcclib.h"
 
 #define umul_ppmm(xh, xl, a, b) \
-{register USItype __t0, __t1, __t2;                                     \
+{register u32 __t0, __t1, __t2;                                     \
   __asm__ ("%@ Inlined umul_ppmm					\n\
         mov     %2, %5, lsr #16						\n\
         mov     %0, %6, lsr #16						\n\
@@ -46,32 +46,27 @@
         addcs   %0, %0, #65536						\n\
         adds    %1, %1, %3, lsl #16					\n\
         adc     %0, %0, %3, lsr #16"                                    \
-           : "=&r" ((USItype) (xh)),                                    \
-             "=r" ((USItype) (xl)),                                     \
+           : "=&r" ((u32) (xh)),                                    \
+             "=r" ((u32) (xl)),                                     \
              "=&r" (__t0), "=&r" (__t1), "=r" (__t2)                    \
-           : "r" ((USItype) (a)),                                       \
-             "r" ((USItype) (b)));}
-
+           : "r" ((u32) (a)),                                       \
+             "r" ((u32) (b)));}
 
 #define __umulsidi3(u, v) \
   ({DIunion __w;                                                        \
     umul_ppmm (__w.s.high, __w.s.low, u, v);                            \
     __w.ll; })
 
-
-DItype
-__muldi3 (DItype u, DItype v)
+s64 __muldi3(s64 u, s64 v)
 {
-  DIunion w;
-  DIunion uu, vv;
+	DIunion w;
+	DIunion uu, vv;
 
-  uu.ll = u,
-  vv.ll = v;
+	uu.ll = u, vv.ll = v;
 
-  w.ll = __umulsidi3 (uu.s.low, vv.s.low);
-  w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
-               + (USItype) uu.s.high * (USItype) vv.s.low);
+	w.ll = __umulsidi3(uu.s.low, vv.s.low);
+	w.s.high += ((u32) uu.s.low * (u32) vv.s.high
+		     + (u32) uu.s.high * (u32) vv.s.low);
 
-  return w.ll;
+	return w.ll;
 }
-
diff --git a/arch/arm/lib/ucmpdi2.c b/arch/arm/lib/ucmpdi2.c
index 6c6ae63..57f3f2d 100644
--- a/arch/arm/lib/ucmpdi2.c
+++ b/arch/arm/lib/ucmpdi2.c
@@ -31,21 +31,19 @@
 
 #include "gcclib.h"
 
-word_type
-__ucmpdi2 (DItype a, DItype b)
+int __ucmpdi2(s64 a, s64 b)
 {
-  DIunion au, bu;
+	DIunion au, bu;
 
-  au.ll = a, bu.ll = b;
+	au.ll = a, bu.ll = b;
 
-  if ((USItype) au.s.high < (USItype) bu.s.high)
-    return 0;
-  else if ((USItype) au.s.high > (USItype) bu.s.high)
-    return 2;
-  if ((USItype) au.s.low < (USItype) bu.s.low)
-    return 0;
-  else if ((USItype) au.s.low > (USItype) bu.s.low)
-    return 2;
-  return 1;
+	if ((u32) au.s.high < (u32) bu.s.high)
+		return 0;
+	else if ((u32) au.s.high > (u32) bu.s.high)
+		return 2;
+	if ((u32) au.s.low < (u32) bu.s.low)
+		return 0;
+	else if ((u32) au.s.low > (u32) bu.s.low)
+		return 2;
+	return 1;
 }
-
diff --git a/arch/arm/lib/udivdi3.c b/arch/arm/lib/udivdi3.c
index d25195f..e343be4 100644
--- a/arch/arm/lib/udivdi3.c
+++ b/arch/arm/lib/udivdi3.c
@@ -32,211 +32,191 @@
 #include "gcclib.h"
 #include "longlong.h"
 
-static const UQItype __clz_tab[] =
-{
-  0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-  6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-  7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-  8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+static const u8 __clz_tab[] = {
+	0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
+	    5, 5, 5, 5, 5, 5, 5, 5,
+	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+	    6, 6, 6, 6, 6, 6, 6, 6,
+	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+	    7, 7, 7, 7, 7, 7, 7, 7,
+	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+	    7, 7, 7, 7, 7, 7, 7, 7,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+	    8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+	    8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+	    8, 8, 8, 8, 8, 8, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+	    8, 8, 8, 8, 8, 8, 8, 8,
 };
 
-UDItype
-__udivmoddi4 (UDItype n, UDItype d, UDItype *rp)
+u64 __udivmoddi4(u64 n, u64 d, u64 * rp)
 {
-  DIunion ww;
-  DIunion nn, dd;
-  DIunion rr;
-  USItype d0, d1, n0, n1, n2;
-  USItype q0, q1;
-  USItype b, bm;
+	DIunion ww;
+	DIunion nn, dd;
+	DIunion rr;
+	u32 d0, d1, n0, n1, n2;
+	u32 q0, q1;
+	u32 b, bm;
 
-  nn.ll = n;
-  dd.ll = d;
+	nn.ll = n;
+	dd.ll = d;
 
-  d0 = dd.s.low;
-  d1 = dd.s.high;
-  n0 = nn.s.low;
-  n1 = nn.s.high;
+	d0 = dd.s.low;
+	d1 = dd.s.high;
+	n0 = nn.s.low;
+	n1 = nn.s.high;
 
-  if (d1 == 0)
-    {
-      if (d0 > n1)
-        {
-          /* 0q = nn / 0D */
+	if (d1 == 0) {
+		if (d0 > n1) {
+			/* 0q = nn / 0D */
 
-          count_leading_zeros (bm, d0);
+			count_leading_zeros(bm, d0);
 
-          if (bm != 0)
-            {
-              /* Normalize, i.e. make the most significant bit of the
-                 denominator set.  */
+			if (bm != 0) {
+				/* Normalize, i.e. make the most significant bit of the
+				   denominator set.  */
 
-              d0 = d0 << bm;
-              n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
-              n0 = n0 << bm;
-            }
+				d0 = d0 << bm;
+				n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
+				n0 = n0 << bm;
+			}
 
-          udiv_qrnnd (q0, n0, n1, n0, d0);
-          q1 = 0;
+			udiv_qrnnd(q0, n0, n1, n0, d0);
+			q1 = 0;
 
-          /* Remainder in n0 >> bm.  */
-        }
-      else
-        {
-          /* qq = NN / 0d */
+			/* Remainder in n0 >> bm.  */
+		} else {
+			/* qq = NN / 0d */
 
-          if (d0 == 0)
-            d0 = 1 / d0;        /* Divide intentionally by zero.  */
+			if (d0 == 0)
+				d0 = 1 / d0;	/* Divide intentionally by zero.  */
 
-          count_leading_zeros (bm, d0);
+			count_leading_zeros(bm, d0);
 
-          if (bm == 0)
-            {
-              /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
-                 conclude (the most significant bit of n1 is set) /\ (the
-                 leading quotient digit q1 = 1).
+			if (bm == 0) {
+				/* From (n1 >= d0) /\ (the most significant bit of d0 is set),
+				   conclude (the most significant bit of n1 is set) /\ (the
+				   leading quotient digit q1 = 1).
 
-                 This special case is necessary, not an optimization.
-                 (Shifts counts of SI_TYPE_SIZE are undefined.)  */
+				   This special case is necessary, not an optimization.
+				   (Shifts counts of SI_TYPE_SIZE are undefined.)  */
 
-              n1 -= d0;
-              q1 = 1;
-            }
-          else
-            {
-              /* Normalize.  */
+				n1 -= d0;
+				q1 = 1;
+			} else {
+				/* Normalize.  */
 
-              b = SI_TYPE_SIZE - bm;
+				b = SI_TYPE_SIZE - bm;
 
-              d0 = d0 << bm;
-              n2 = n1 >> b;
-              n1 = (n1 << bm) | (n0 >> b);
-              n0 = n0 << bm;
+				d0 = d0 << bm;
+				n2 = n1 >> b;
+				n1 = (n1 << bm) | (n0 >> b);
+				n0 = n0 << bm;
 
-              udiv_qrnnd (q1, n1, n2, n1, d0);
-            }
+				udiv_qrnnd(q1, n1, n2, n1, d0);
+			}
 
-          /* n1 != d0...  */
+			/* n1 != d0...  */
 
-          udiv_qrnnd (q0, n0, n1, n0, d0);
+			udiv_qrnnd(q0, n0, n1, n0, d0);
 
-          /* Remainder in n0 >> bm.  */
-        }
+			/* Remainder in n0 >> bm.  */
+		}
 
-      if (rp != 0)
-        {
-          rr.s.low = n0 >> bm;
-          rr.s.high = 0;
-          *rp = rr.ll;
-        }
-    }
-  else
-    {
-      if (d1 > n1)
-        {
-          /* 00 = nn / DD */
+		if (rp != 0) {
+			rr.s.low = n0 >> bm;
+			rr.s.high = 0;
+			*rp = rr.ll;
+		}
+	} else {
+		if (d1 > n1) {
+			/* 00 = nn / DD */
 
-          q0 = 0;
-          q1 = 0;
+			q0 = 0;
+			q1 = 0;
 
-          /* Remainder in n1n0.  */
-          if (rp != 0)
-            {
-              rr.s.low = n0;
-              rr.s.high = n1;
-              *rp = rr.ll;
-            }
-        }
-      else
-        {
-          /* 0q = NN / dd */
+			/* Remainder in n1n0.  */
+			if (rp != 0) {
+				rr.s.low = n0;
+				rr.s.high = n1;
+				*rp = rr.ll;
+			}
+		} else {
+			/* 0q = NN / dd */
 
-          count_leading_zeros (bm, d1);
-          if (bm == 0)
-            {
-              /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
-                 conclude (the most significant bit of n1 is set) /\ (the
-                 quotient digit q0 = 0 or 1).
+			count_leading_zeros(bm, d1);
+			if (bm == 0) {
+				/* From (n1 >= d1) /\ (the most significant bit of d1 is set),
+				   conclude (the most significant bit of n1 is set) /\ (the
+				   quotient digit q0 = 0 or 1).
 
-                 This special case is necessary, not an optimization.  */
+				   This special case is necessary, not an optimization.  */
 
-              /* The condition on the next line takes advantage of that
-                 n1 >= d1 (true due to program flow).  */
-              if (n1 > d1 || n0 >= d0)
-                {
-                  q0 = 1;
-                  sub_ddmmss (n1, n0, n1, n0, d1, d0);
-                }
-              else
-                q0 = 0;
+				/* The condition on the next line takes advantage of that
+				   n1 >= d1 (true due to program flow).  */
+				if (n1 > d1 || n0 >= d0) {
+					q0 = 1;
+					sub_ddmmss(n1, n0, n1, n0, d1, d0);
+				} else
+					q0 = 0;
 
-              q1 = 0;
+				q1 = 0;
 
-              if (rp != 0)
-                {
-                  rr.s.low = n0;
-                  rr.s.high = n1;
-                  *rp = rr.ll;
-                }
-            }
-          else
-            {
-              USItype m1, m0;
-              /* Normalize.  */
+				if (rp != 0) {
+					rr.s.low = n0;
+					rr.s.high = n1;
+					*rp = rr.ll;
+				}
+			} else {
+				u32 m1, m0;
+				/* Normalize.  */
 
-              b = SI_TYPE_SIZE - bm;
+				b = SI_TYPE_SIZE - bm;
 
-              d1 = (d1 << bm) | (d0 >> b);
-              d0 = d0 << bm;
-              n2 = n1 >> b;
-              n1 = (n1 << bm) | (n0 >> b);
-              n0 = n0 << bm;
+				d1 = (d1 << bm) | (d0 >> b);
+				d0 = d0 << bm;
+				n2 = n1 >> b;
+				n1 = (n1 << bm) | (n0 >> b);
+				n0 = n0 << bm;
 
-              udiv_qrnnd (q0, n1, n2, n1, d1);
-              umul_ppmm (m1, m0, q0, d0);
+				udiv_qrnnd(q0, n1, n2, n1, d1);
+				umul_ppmm(m1, m0, q0, d0);
 
-              if (m1 > n1 || (m1 == n1 && m0 > n0))
-                {
-                  q0--;
-                  sub_ddmmss (m1, m0, m1, m0, d1, d0);
-                }
+				if (m1 > n1 || (m1 == n1 && m0 > n0)) {
+					q0--;
+					sub_ddmmss(m1, m0, m1, m0, d1, d0);
+				}
 
-              q1 = 0;
+				q1 = 0;
 
-              /* Remainder in (n1n0 - m1m0) >> bm.  */
-              if (rp != 0)
-                {
-                  sub_ddmmss (n1, n0, n1, n0, m1, m0);
-                  rr.s.low = (n1 << b) | (n0 >> bm);
-                  rr.s.high = n1 >> bm;
-                  *rp = rr.ll;
-                }
-            }
-        }
-    }
+				/* Remainder in (n1n0 - m1m0) >> bm.  */
+				if (rp != 0) {
+					sub_ddmmss(n1, n0, n1, n0, m1, m0);
+					rr.s.low = (n1 << b) | (n0 >> bm);
+					rr.s.high = n1 >> bm;
+					*rp = rr.ll;
+				}
+			}
+		}
+	}
 
-  ww.s.low = q0;
-  ww.s.high = q1;
-  return ww.ll;
+	ww.s.low = q0;
+	ww.s.high = q1;
+	return ww.ll;
 }
 
-UDItype
-__udivdi3 (UDItype n, UDItype d)
+u64 __udivdi3(u64 n, u64 d)
 {
-  return __udivmoddi4 (n, d, (UDItype *) 0);
+	return __udivmoddi4(n, d, (u64 *) 0);
 }
 
-UDItype
-__umoddi3 (UDItype u, UDItype v)
+u64 __umoddi3(u64 u, u64 v)
 {
-  UDItype w;
+	u64 w;
 
-  (void) __udivmoddi4 (u ,v, &w);
+	(void)__udivmoddi4(u, v, &w);
 
-  return w;
+	return w;
 }
-
diff --git a/arch/arm/mach-aaec2000/Kconfig b/arch/arm/mach-aaec2000/Kconfig
new file mode 100644
index 0000000..5e4bef9
--- /dev/null
+++ b/arch/arm/mach-aaec2000/Kconfig
@@ -0,0 +1,11 @@
+if ARCH_AAEC2000
+
+menu "Agilent AAEC-2000 Implementations"
+
+config MACH_AAED2000
+	bool "Agilent AAED-2000 Development Platform"
+	select CPU_ARM920T
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-aaec2000/Makefile b/arch/arm/mach-aaec2000/Makefile
new file mode 100644
index 0000000..20ec838
--- /dev/null
+++ b/arch/arm/mach-aaec2000/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Common support (must be linked before board specific support)
+obj-y += core.o
+
+# Specific board support
+obj-$(CONFIG_MACH_AAED2000) += aaed2000.o
diff --git a/arch/arm/mach-aaec2000/aaed2000.c b/arch/arm/mach-aaec2000/aaed2000.c
new file mode 100644
index 0000000..5417ca3
--- /dev/null
+++ b/arch/arm/mach-aaec2000/aaed2000.c
@@ -0,0 +1,48 @@
+/*
+ *  linux/arch/arm/mach-aaec2000/aaed2000.c
+ *
+ *  Support for the Agilent AAED-2000 Development Platform.
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  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/device.h>
+#include <linux/major.h>
+#include <linux/interrupt.h>
+
+#include <asm/setup.h>
+#include <asm/memory.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include "core.h"
+
+static void __init aaed2000_init_irq(void)
+{
+	aaec2000_init_irq();
+}
+
+static void __init aaed2000_map_io(void)
+{
+	aaec2000_map_io();
+}
+
+MACHINE_START(AAED2000, "Agilent AAED-2000 Development Platform")
+	MAINTAINER("Nicolas Bellido Y Ortega")
+	BOOT_MEM(0xf0000000, PIO_BASE, VIO_BASE)
+	MAPIO(aaed2000_map_io)
+	INITIRQ(aaed2000_init_irq)
+	.timer		= &aaec2000_timer,
+MACHINE_END
diff --git a/arch/arm/mach-aaec2000/core.c b/arch/arm/mach-aaec2000/core.c
new file mode 100644
index 0000000..aece0cd
--- /dev/null
+++ b/arch/arm/mach-aaec2000/core.c
@@ -0,0 +1,157 @@
+/*
+ *  linux/arch/arm/mach-aaec2000/core.c
+ *
+ *  Code common to all AAEC-2000 machines
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  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/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/signal.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
+
+/*
+ * Common I/O mapping:
+ *
+ * Static virtual address mappings are as follow:
+ *
+ * 0xf8000000-0xf8001ffff: Devices connected to APB bus
+ * 0xf8002000-0xf8003ffff: Devices connected to AHB bus
+ *
+ * Below 0xe8000000 is reserved for vm allocation.
+ *
+ * The machine specific code must provide the extra mapping beside the
+ * default mapping provided here.
+ */
+static struct map_desc standard_io_desc[] __initdata = {
+ /* virtual         physical       length           type */
+  { VIO_APB_BASE,   PIO_APB_BASE,  IO_APB_LENGTH,   MT_DEVICE },
+  { VIO_AHB_BASE,   PIO_AHB_BASE,  IO_AHB_LENGTH,   MT_DEVICE }
+};
+
+void __init aaec2000_map_io(void)
+{
+	iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
+}
+
+/*
+ * Interrupt handling routines
+ */
+static void aaec2000_int_ack(unsigned int irq)
+{
+	IRQ_INTSR = 1 << irq;
+}
+
+static void aaec2000_int_mask(unsigned int irq)
+{
+	IRQ_INTENC |= (1 << irq);
+}
+
+static void aaec2000_int_unmask(unsigned int irq)
+{
+	IRQ_INTENS |= (1 << irq);
+}
+
+static struct irqchip aaec2000_irq_chip = {
+	.ack	= aaec2000_int_ack,
+	.mask	= aaec2000_int_mask,
+	.unmask	= aaec2000_int_unmask,
+};
+
+void __init aaec2000_init_irq(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < NR_IRQS; i++) {
+		set_irq_handler(i, do_level_IRQ);
+		set_irq_chip(i, &aaec2000_irq_chip);
+		set_irq_flags(i, IRQF_VALID);
+	}
+
+	/* Disable all interrupts */
+	IRQ_INTENC = 0xffffffff;
+
+	/* Clear any pending interrupts */
+	IRQ_INTSR = IRQ_INTSR;
+}
+
+/*
+ * Time keeping
+ */
+/* IRQs are disabled before entering here from do_gettimeofday() */
+static unsigned long aaec2000_gettimeoffset(void)
+{
+	unsigned long ticks_to_match, elapsed, usec;
+
+	/* Get ticks before next timer match */
+	ticks_to_match = TIMER1_LOAD - TIMER1_VAL;
+
+	/* We need elapsed ticks since last match */
+	elapsed = LATCH - ticks_to_match;
+
+	/* Now, convert them to usec */
+	usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
+
+	return usec;
+}
+
+/* We enter here with IRQs enabled */
+static irqreturn_t
+aaec2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	/* TODO: Check timer accuracy */
+	write_seqlock(&xtime_lock);
+
+	timer_tick(regs);
+	TIMER1_CLEAR = 1;
+
+	write_sequnlock(&xtime_lock);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction aaec2000_timer_irq = {
+	.name		= "AAEC-2000 Timer Tick",
+	.flags		= SA_INTERRUPT | SA_TIMER,
+	.handler	= aaec2000_timer_interrupt,
+};
+
+static void __init aaec2000_timer_init(void)
+{
+	/* Disable timer 1 */
+	TIMER1_CTRL = 0;
+
+	/* We have somehow to generate a 100Hz clock.
+	 * We then use the 508KHz timer in periodic mode.
+	 */
+	TIMER1_LOAD = LATCH;
+	TIMER1_CLEAR = 1; /* Clear interrupt */
+
+	setup_irq(INT_TMR1_OFL, &aaec2000_timer_irq);
+
+	TIMER1_CTRL = TIMER_CTRL_ENABLE |
+	                TIMER_CTRL_PERIODIC |
+	                TIMER_CTRL_CLKSEL_508K;
+}
+
+struct sys_timer aaec2000_timer = {
+	.init		= aaec2000_timer_init,
+	.offset		= aaec2000_gettimeoffset,
+};
+
diff --git a/arch/arm/mach-aaec2000/core.h b/arch/arm/mach-aaec2000/core.h
new file mode 100644
index 0000000..91893d8
--- /dev/null
+++ b/arch/arm/mach-aaec2000/core.h
@@ -0,0 +1,16 @@
+/*
+ *  linux/arch/arm/mach-aaec2000/core.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  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.
+ *
+ */
+
+struct sys_timer;
+
+extern struct sys_timer aaec2000_timer;
+extern void __init aaec2000_map_io(void);
+extern void __init aaec2000_init_irq(void);
diff --git a/arch/arm/mach-clps711x/Kconfig b/arch/arm/mach-clps711x/Kconfig
index 45c930c..0793dcf 100644
--- a/arch/arm/mach-clps711x/Kconfig
+++ b/arch/arm/mach-clps711x/Kconfig
@@ -28,7 +28,7 @@
 config ARCH_EDB7211
 	bool "EDB7211"
 	select ISA
-	select DISCONTIGMEM
+	select ARCH_DISCONTIGMEM_ENABLE
 	help
 	  Say Y here if you intend to run this kernel on a Cirrus Logic EDB-7211
 	  evaluation board.
diff --git a/arch/arm/mach-clps711x/time.c b/arch/arm/mach-clps711x/time.c
index 383d4e0..1a23f0d 100644
--- a/arch/arm/mach-clps711x/time.c
+++ b/arch/arm/mach-clps711x/time.c
@@ -57,8 +57,8 @@
 
 static struct irqaction clps711x_timer_irq = {
 	.name		= "CLPS711x Timer Tick",
-	.flags		= SA_INTERRUPT,
-	.handler	= p720t_timer_interrupt
+	.flags		= SA_INTERRUPT | SA_TIMER,
+	.handler	= p720t_timer_interrupt,
 };
 
 static void __init clps711x_timer_init(void)
diff --git a/arch/arm/mach-clps7500/core.c b/arch/arm/mach-clps7500/core.c
index fdfeded..90e85f4 100644
--- a/arch/arm/mach-clps7500/core.c
+++ b/arch/arm/mach-clps7500/core.c
@@ -26,6 +26,8 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
+unsigned int vram_size;
+
 static void cl7500_ack_irq_a(unsigned int irq)
 {
 	unsigned int val, mask;
@@ -296,8 +298,8 @@
 
 static struct irqaction clps7500_timer_irq = {
 	.name		= "CLPS7500 Timer Tick",
-	.flags		= SA_INTERRUPT,
-	.handler	= clps7500_timer_interrupt
+	.flags		= SA_INTERRUPT | SA_TIMER,
+	.handler	= clps7500_timer_interrupt,
 };
 
 /*
diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c
index ef362d4..86ffdbb 100644
--- a/arch/arm/mach-ebsa110/core.c
+++ b/arch/arm/mach-ebsa110/core.c
@@ -173,8 +173,8 @@
 
 static struct irqaction ebsa110_timer_irq = {
 	.name		= "EBSA110 Timer Tick",
-	.flags		= SA_INTERRUPT,
-	.handler	= ebsa110_timer_interrupt
+	.flags		= SA_INTERRUPT | SA_TIMER,
+	.handler	= ebsa110_timer_interrupt,
 };
 
 /*
diff --git a/arch/arm/mach-epxa10db/time.c b/arch/arm/mach-epxa10db/time.c
index 1b991f3..4b1084d 100644
--- a/arch/arm/mach-epxa10db/time.c
+++ b/arch/arm/mach-epxa10db/time.c
@@ -56,8 +56,8 @@
 
 static struct irqaction epxa10db_timer_irq = {
 	.name		= "Excalibur Timer Tick",
-	.flags		= SA_INTERRUPT,
-	.handler	= epxa10db_timer_interrupt
+	.flags		= SA_INTERRUPT | SA_TIMER,
+	.handler	= epxa10db_timer_interrupt,
 };
 
 /*
diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c
index da5b9b7..14a62d6 100644
--- a/arch/arm/mach-footbridge/dc21285-timer.c
+++ b/arch/arm/mach-footbridge/dc21285-timer.c
@@ -43,7 +43,7 @@
 static struct irqaction footbridge_timer_irq = {
 	.name		= "Timer1 timer tick",
 	.handler	= timer1_interrupt,
-	.flags		= SA_INTERRUPT,
+	.flags		= SA_INTERRUPT | SA_TIMER,
 };
 
 /*
diff --git a/arch/arm/mach-footbridge/isa-timer.c b/arch/arm/mach-footbridge/isa-timer.c
index a4fefa0..c1d74f7 100644
--- a/arch/arm/mach-footbridge/isa-timer.c
+++ b/arch/arm/mach-footbridge/isa-timer.c
@@ -72,7 +72,7 @@
 static struct irqaction isa_timer_irq = {
 	.name		= "ISA timer tick",
 	.handler	= isa_timer_interrupt,
-	.flags		= SA_INTERRUPT,
+	.flags		= SA_INTERRUPT | SA_TIMER,
 };
 
 static void __init isa_timer_init(void)
diff --git a/arch/arm/mach-h720x/cpu-h7201.c b/arch/arm/mach-h720x/cpu-h7201.c
index 7436568..af9e4a5 100644
--- a/arch/arm/mach-h720x/cpu-h7201.c
+++ b/arch/arm/mach-h720x/cpu-h7201.c
@@ -41,8 +41,8 @@
 
 static struct irqaction h7201_timer_irq = {
 	.name		= "h7201 Timer Tick",
-	.flags		= SA_INTERRUPT,
-	.handler	= h7201_timer_interrupt
+	.flags		= SA_INTERRUPT | SA_TIMER,
+	.handler	= h7201_timer_interrupt,
 };
 
 /*
diff --git a/arch/arm/mach-h720x/cpu-h7202.c b/arch/arm/mach-h720x/cpu-h7202.c
index 21b8fb6..593b6a2 100644
--- a/arch/arm/mach-h720x/cpu-h7202.c
+++ b/arch/arm/mach-h720x/cpu-h7202.c
@@ -171,8 +171,8 @@
 
 static struct irqaction h7202_timer_irq = {
 	.name		= "h7202 Timer Tick",
-	.flags		= SA_INTERRUPT,
-	.handler	= h7202_timer_interrupt
+	.flags		= SA_INTERRUPT | SA_TIMER,
+	.handler	= h7202_timer_interrupt,
 };
 
 /*
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index 11f1e56..ea805bf 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -72,8 +72,8 @@
 
 static struct irqaction imx_timer_irq = {
 	.name		= "i.MX Timer Tick",
-	.flags		= SA_INTERRUPT,
-	.handler	= imx_timer_interrupt
+	.flags		= SA_INTERRUPT | SA_TIMER,
+	.handler	= imx_timer_interrupt,
 };
 
 /*
diff --git a/arch/arm/mach-integrator/Makefile b/arch/arm/mach-integrator/Makefile
index 158daaf..ebb255b 100644
--- a/arch/arm/mach-integrator/Makefile
+++ b/arch/arm/mach-integrator/Makefile
@@ -12,3 +12,4 @@
 obj-$(CONFIG_PCI)			+= pci_v3.o pci.o
 obj-$(CONFIG_CPU_FREQ_INTEGRATOR)	+= cpu.o
 obj-$(CONFIG_INTEGRATOR_IMPD1)		+= impd1.o
+obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c
index bd17b51..9222e57 100644
--- a/arch/arm/mach-integrator/core.c
+++ b/arch/arm/mach-integrator/core.c
@@ -14,6 +14,7 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 
 #include <asm/hardware.h>
 #include <asm/irq.h>
@@ -221,7 +222,23 @@
 	 */
 	timer1->TimerClear = 1;
 
-	timer_tick(regs);
+	/*
+	 * the clock tick routines are only processed on the
+	 * primary CPU
+	 */
+	if (hard_smp_processor_id() == 0) {
+		timer_tick(regs);
+#ifdef CONFIG_SMP
+		smp_send_timer();
+#endif
+	}
+
+#ifdef CONFIG_SMP
+	/*
+	 * this is the ARM equivalent of the APIC timer interrupt
+	 */
+	update_process_times(user_mode(regs));
+#endif /* CONFIG_SMP */
 
 	write_sequnlock(&xtime_lock);
 
@@ -230,8 +247,8 @@
 
 static struct irqaction integrator_timer_irq = {
 	.name		= "Integrator Timer Tick",
-	.flags		= SA_INTERRUPT,
-	.handler	= integrator_timer_interrupt
+	.flags		= SA_INTERRUPT | SA_TIMER,
+	.handler	= integrator_timer_interrupt,
 };
 
 /*
diff --git a/arch/arm/mach-integrator/headsmp.S b/arch/arm/mach-integrator/headsmp.S
new file mode 100644
index 0000000..ceaa88e
--- /dev/null
+++ b/arch/arm/mach-integrator/headsmp.S
@@ -0,0 +1,37 @@
+/*
+ *  linux/arch/arm/mach-integrator/headsmp.S
+ *
+ *  Copyright (c) 2003 ARM Limited
+ *  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 version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+	__INIT
+
+/*
+ * Integrator specific entry point for secondary CPUs.  This provides
+ * a "holding pen" into which all secondary cores are held until we're
+ * ready for them to initialise.
+ */
+ENTRY(integrator_secondary_startup)
+	adr	r4, 1f
+	ldmia	r4, {r5, r6}
+	sub	r4, r4, r5
+	ldr	r6, [r6, r4]
+pen:	ldr	r7, [r6]
+	cmp	r7, r0
+	bne	pen
+
+	/*
+	 * we've been released from the holding pen: secondary_stack
+	 * should now contain the SVC stack for this core
+	 */
+	b	secondary_startup
+
+1:	.long	.
+	.long	phys_pen_release
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 3b948e8..e0a01ee 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -83,7 +83,6 @@
  { IO_ADDRESS(INTEGRATOR_UART1_BASE), INTEGRATOR_UART1_BASE, SZ_4K,  MT_DEVICE },
  { IO_ADDRESS(INTEGRATOR_DBG_BASE),   INTEGRATOR_DBG_BASE,   SZ_4K,  MT_DEVICE },
  { IO_ADDRESS(INTEGRATOR_GPIO_BASE),  INTEGRATOR_GPIO_BASE,  SZ_4K,  MT_DEVICE },
- { 0xfc900000, 0xc9000000, SZ_4K, MT_DEVICE },
  { 0xfca00000, 0xca000000, SZ_4K, MT_DEVICE },
  { 0xfcb00000, 0xcb000000, SZ_4K, MT_DEVICE },
 };
diff --git a/arch/arm/mach-integrator/leds.c b/arch/arm/mach-integrator/leds.c
index d2c0ab2..f1436e6 100644
--- a/arch/arm/mach-integrator/leds.c
+++ b/arch/arm/mach-integrator/leds.c
@@ -22,6 +22,8 @@
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/spinlock.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
@@ -85,4 +87,4 @@
 	return 0;
 }
 
-__initcall(leds_init);
+core_initcall(leds_init);
diff --git a/arch/arm/mach-integrator/platsmp.c b/arch/arm/mach-integrator/platsmp.c
new file mode 100644
index 0000000..ead15df
--- /dev/null
+++ b/arch/arm/mach-integrator/platsmp.c
@@ -0,0 +1,192 @@
+/*
+ *  linux/arch/arm/mach-cintegrator/platsmp.c
+ *
+ *  Copyright (C) 2002 ARM Ltd.
+ *  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 version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+
+#include <asm/atomic.h>
+#include <asm/delay.h>
+#include <asm/mmu_context.h>
+#include <asm/procinfo.h>
+#include <asm/ptrace.h>
+#include <asm/smp.h>
+
+extern void integrator_secondary_startup(void);
+
+/*
+ * control for which core is the next to come out of the secondary
+ * boot "holding pen"
+ */
+volatile int __initdata pen_release = -1;
+unsigned long __initdata phys_pen_release = 0;
+
+static DEFINE_SPINLOCK(boot_lock);
+
+void __init platform_secondary_init(unsigned int cpu)
+{
+	/*
+	 * the primary core may have used a "cross call" soft interrupt
+	 * to get this processor out of WFI in the BootMonitor - make
+	 * sure that we are no longer being sent this soft interrupt
+	 */
+	smp_cross_call_done(cpumask_of_cpu(cpu));
+
+	/*
+	 * if any interrupts are already enabled for the primary
+	 * core (e.g. timer irq), then they will not have been enabled
+	 * for us: do so
+	 */
+	secondary_scan_irqs();
+
+	/*
+	 * let the primary processor know we're out of the
+	 * pen, then head off into the C entry point
+	 */
+	pen_release = -1;
+
+	/*
+	 * Synchronise with the boot thread.
+	 */
+	spin_lock(&boot_lock);
+	spin_unlock(&boot_lock);
+}
+
+int __init boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	unsigned long timeout;
+
+	/*
+	 * set synchronisation state between this boot processor
+	 * and the secondary one
+	 */
+	spin_lock(&boot_lock);
+
+	/*
+	 * The secondary processor is waiting to be released from
+	 * the holding pen - release it, then wait for it to flag
+	 * that it has been released by resetting pen_release.
+	 *
+	 * Note that "pen_release" is the hardware CPU ID, whereas
+	 * "cpu" is Linux's internal ID.
+	 */
+	pen_release = cpu;
+
+	/*
+	 * XXX
+	 *
+	 * This is a later addition to the booting protocol: the
+	 * bootMonitor now puts secondary cores into WFI, so
+	 * poke_milo() no longer gets the cores moving; we need
+	 * to send a soft interrupt to wake the secondary core.
+	 * Use smp_cross_call() for this, since there's little
+	 * point duplicating the code here
+	 */
+	smp_cross_call(cpumask_of_cpu(cpu));
+
+	timeout = jiffies + (1 * HZ);
+	while (time_before(jiffies, timeout)) {
+		if (pen_release == -1)
+			break;
+
+		udelay(10);
+	}
+
+	/*
+	 * now the secondary core is starting up let it run its
+	 * calibrations, then wait for it to finish
+	 */
+	spin_unlock(&boot_lock);
+
+	return pen_release != -1 ? -ENOSYS : 0;
+}
+
+static void __init poke_milo(void)
+{
+	extern void secondary_startup(void);
+
+	/* nobody is to be released from the pen yet */
+	pen_release = -1;
+
+	phys_pen_release = virt_to_phys(&pen_release);
+
+	/*
+	 * write the address of secondary startup into the system-wide
+	 * flags register, then clear the bottom two bits, which is what
+	 * BootMonitor is waiting for
+	 */
+#if 1
+#define CINTEGRATOR_HDR_FLAGSS_OFFSET 0x30
+	__raw_writel(virt_to_phys(integrator_secondary_startup),
+		     (IO_ADDRESS(INTEGRATOR_HDR_BASE) +
+		      CINTEGRATOR_HDR_FLAGSS_OFFSET));
+#define CINTEGRATOR_HDR_FLAGSC_OFFSET 0x34
+	__raw_writel(3,
+		     (IO_ADDRESS(INTEGRATOR_HDR_BASE) +
+		      CINTEGRATOR_HDR_FLAGSC_OFFSET));
+#endif
+
+	mb();
+}
+
+void __init smp_prepare_cpus(unsigned int max_cpus)
+{
+	unsigned int ncores = get_core_count();
+	unsigned int cpu = smp_processor_id();
+	int i;
+
+	/* sanity check */
+	if (ncores == 0) {
+		printk(KERN_ERR
+		       "Integrator/CP: strange CM count of 0? Default to 1\n");
+
+		ncores = 1;
+	}
+
+	if (ncores > NR_CPUS) {
+		printk(KERN_WARNING
+		       "Integrator/CP: no. of cores (%d) greater than configured "
+		       "maximum of %d - clipping\n",
+		       ncores, NR_CPUS);
+		ncores = NR_CPUS;
+	}
+
+	/*
+	 * start with some more config for the Boot CPU, now that
+	 * the world is a bit more alive (which was not the case
+	 * when smp_prepare_boot_cpu() was called)
+	 */
+	smp_store_cpu_info(cpu);
+
+	/*
+	 * are we trying to boot more cores than exist?
+	 */
+	if (max_cpus > ncores)
+		max_cpus = ncores;
+
+	/*
+	 * Initialise the present mask - this tells us which CPUs should
+	 * be present.
+	 */
+	for (i = 0; i < max_cpus; i++) {
+		cpu_set(i, cpu_present_mask);
+	}
+
+	/*
+	 * Do we need any more CPUs? If so, then let them know where
+	 * to start. Note that, on modern versions of MILO, the "poke"
+	 * doesn't actually do anything until each individual core is
+	 * sent a soft interrupt to get it out of WFI
+	 */
+	if (max_cpus > 1)
+		poke_milo();
+}
diff --git a/arch/arm/mach-iop3xx/iop321-time.c b/arch/arm/mach-iop3xx/iop321-time.c
index 9b7dd64..d53af16 100644
--- a/arch/arm/mach-iop3xx/iop321-time.c
+++ b/arch/arm/mach-iop3xx/iop321-time.c
@@ -86,7 +86,7 @@
 static struct irqaction iop321_timer_irq = {
 	.name		= "IOP321 Timer Tick",
 	.handler	= iop321_timer_interrupt,
-	.flags		= SA_INTERRUPT
+	.flags		= SA_INTERRUPT | SA_TIMER,
 };
 
 static void __init iop321_timer_init(void)
diff --git a/arch/arm/mach-iop3xx/iop331-time.c b/arch/arm/mach-iop3xx/iop331-time.c
index e016967..1a6d9d6 100644
--- a/arch/arm/mach-iop3xx/iop331-time.c
+++ b/arch/arm/mach-iop3xx/iop331-time.c
@@ -83,7 +83,7 @@
 static struct irqaction iop331_timer_irq = {
 	.name		= "IOP331 Timer Tick",
 	.handler	= iop331_timer_interrupt,
-	.flags		= SA_INTERRUPT
+	.flags		= SA_INTERRUPT | SA_TIMER,
 };
 
 static void __init iop331_timer_init(void)
diff --git a/arch/arm/mach-ixp2000/Kconfig b/arch/arm/mach-ixp2000/Kconfig
index 9361e05..ecb58d8 100644
--- a/arch/arm/mach-ixp2000/Kconfig
+++ b/arch/arm/mach-ixp2000/Kconfig
@@ -54,6 +54,14 @@
 	depends on ARCH_IXDP2401 || ARCH_IXDP2801
 	default y	
 
+config IXP2000_SUPPORT_BROKEN_PCI_IO
+	bool "Support broken PCI I/O on older IXP2000s"
+	default y
+	help
+	  Say 'N' here if you only intend to run your kernel on an
+	  IXP2000 B0 or later model and do not need the PCI I/O
+	  byteswap workaround.  Say 'Y' otherwise.
+
 endmenu
 
 endif
diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c
index 4f3c3d5..4b9d841 100644
--- a/arch/arm/mach-ixp2000/core.c
+++ b/arch/arm/mach-ixp2000/core.c
@@ -40,6 +40,8 @@
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
 
+#include <asm/arch/gpio.h>
+
 static DEFINE_SPINLOCK(ixp2000_slowport_lock);
 static unsigned long ixp2000_slowport_irq_flags;
 
@@ -101,6 +103,11 @@
 		.length		= IXP2000_PCI_CSR_SIZE,
 		.type		= MT_DEVICE
 	}, {
+		.virtual	= IXP2000_MSF_VIRT_BASE,
+		.physical	= IXP2000_MSF_PHYS_BASE,
+		.length		= IXP2000_MSF_SIZE,
+		.type		= MT_DEVICE
+	}, {
 		.virtual	= IXP2000_PCI_IO_VIRT_BASE,
 		.physical	= IXP2000_PCI_IO_PHYS_BASE,
 		.length		= IXP2000_PCI_IO_SIZE,
@@ -162,12 +169,13 @@
 static unsigned ticks_per_jiffy;
 static unsigned ticks_per_usec;
 static unsigned next_jiffy_time;
+static volatile unsigned long *missing_jiffy_timer_csr;
 
 unsigned long ixp2000_gettimeoffset (void)
 {
  	unsigned long offset;
 
-	offset = next_jiffy_time - *IXP2000_T4_CSR;
+	offset = next_jiffy_time - *missing_jiffy_timer_csr;
 
 	return offset / ticks_per_usec;
 }
@@ -178,8 +186,8 @@
 
 	/* clear timer 1 */
 	ixp2000_reg_write(IXP2000_T1_CLR, 1);
-	
-	while ((next_jiffy_time - *IXP2000_T4_CSR) > ticks_per_jiffy) {
+
+	while ((next_jiffy_time - *missing_jiffy_timer_csr) > ticks_per_jiffy) {
 		timer_tick(regs);
 		next_jiffy_time -= ticks_per_jiffy;
 	}
@@ -191,26 +199,43 @@
 
 static struct irqaction ixp2000_timer_irq = {
 	.name		= "IXP2000 Timer Tick",
-	.flags		= SA_INTERRUPT,
-	.handler	= ixp2000_timer_interrupt
+	.flags		= SA_INTERRUPT | SA_TIMER,
+	.handler	= ixp2000_timer_interrupt,
 };
 
 void __init ixp2000_init_time(unsigned long tick_rate)
 {
-	ixp2000_reg_write(IXP2000_T1_CLR, 0);
-	ixp2000_reg_write(IXP2000_T4_CLR, 0);
-
 	ticks_per_jiffy = (tick_rate + HZ/2) / HZ;
 	ticks_per_usec = tick_rate / 1000000;
 
+	/*
+	 * We use timer 1 as our timer interrupt.
+	 */
+	ixp2000_reg_write(IXP2000_T1_CLR, 0);
 	ixp2000_reg_write(IXP2000_T1_CLD, ticks_per_jiffy - 1);
 	ixp2000_reg_write(IXP2000_T1_CTL, (1 << 7));
 
 	/*
-	 * We use T4 as a monotonic counter to track missed jiffies
+	 * We use a second timer as a monotonic counter for tracking
+	 * missed jiffies.  The IXP2000 has four timers, but if we're
+	 * on an A-step IXP2800, timer 2 and 3 don't work, so on those
+	 * chips we use timer 4.  Timer 4 is the only timer that can
+	 * be used for the watchdog, so we use timer 2 if we're on a
+	 * non-buggy chip.
 	 */
-	ixp2000_reg_write(IXP2000_T4_CLD, -1);
-	ixp2000_reg_write(IXP2000_T4_CTL, (1 << 7));
+	if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) {
+		printk(KERN_INFO "Enabling IXP2800 erratum #25 workaround\n");
+
+		ixp2000_reg_write(IXP2000_T4_CLR, 0);
+		ixp2000_reg_write(IXP2000_T4_CLD, -1);
+		ixp2000_reg_write(IXP2000_T4_CTL, (1 << 7));
+		missing_jiffy_timer_csr = IXP2000_T4_CSR;
+	} else {
+		ixp2000_reg_write(IXP2000_T2_CLR, 0);
+		ixp2000_reg_write(IXP2000_T2_CLD, -1);
+		ixp2000_reg_write(IXP2000_T2_CTL, (1 << 7));
+		missing_jiffy_timer_csr = IXP2000_T2_CSR;
+	}
  	next_jiffy_time = 0xffffffff;
 
 	/* register for interrupt */
@@ -220,35 +245,40 @@
 /*************************************************************************
  * GPIO helpers
  *************************************************************************/
-static unsigned long GPIO_IRQ_rising_edge;
 static unsigned long GPIO_IRQ_falling_edge;
+static unsigned long GPIO_IRQ_rising_edge;
 static unsigned long GPIO_IRQ_level_low;
 static unsigned long GPIO_IRQ_level_high;
 
-void gpio_line_config(int line, int style)
+static void update_gpio_int_csrs(void)
+{
+	ixp2000_reg_write(IXP2000_GPIO_FEDR, GPIO_IRQ_falling_edge);
+	ixp2000_reg_write(IXP2000_GPIO_REDR, GPIO_IRQ_rising_edge);
+	ixp2000_reg_write(IXP2000_GPIO_LSLR, GPIO_IRQ_level_low);
+	ixp2000_reg_write(IXP2000_GPIO_LSHR, GPIO_IRQ_level_high);
+}
+
+void gpio_line_config(int line, int direction)
 {
 	unsigned long flags;
 
 	local_irq_save(flags);
+	if (direction == GPIO_OUT) {
+		irq_desc[line + IRQ_IXP2000_GPIO0].valid = 0;
 
-	if(style == GPIO_OUT) {
 		/* if it's an output, it ain't an interrupt anymore */
-		ixp2000_reg_write(IXP2000_GPIO_PDSR, (1 << line));
 		GPIO_IRQ_falling_edge &= ~(1 << line);
 		GPIO_IRQ_rising_edge &= ~(1 << line);
 		GPIO_IRQ_level_low &= ~(1 << line);
 		GPIO_IRQ_level_high &= ~(1 << line);
-		ixp2000_reg_write(IXP2000_GPIO_FEDR, GPIO_IRQ_falling_edge);
-		ixp2000_reg_write(IXP2000_GPIO_REDR, GPIO_IRQ_rising_edge);
-		ixp2000_reg_write(IXP2000_GPIO_LSHR, GPIO_IRQ_level_high);
-		ixp2000_reg_write(IXP2000_GPIO_LSLR, GPIO_IRQ_level_low);
-		irq_desc[line+IRQ_IXP2000_GPIO0].valid = 0;
-	} else if(style == GPIO_IN) {
-		ixp2000_reg_write(IXP2000_GPIO_PDCR, (1 << line));
+		update_gpio_int_csrs();
+
+		ixp2000_reg_write(IXP2000_GPIO_PDSR, 1 << line);
+	} else if (direction == GPIO_IN) {
+		ixp2000_reg_write(IXP2000_GPIO_PDCR, 1 << line);
 	}
-		
 	local_irq_restore(flags);
-}	
+}
 
 
 /*************************************************************************
@@ -267,9 +297,50 @@
 	}
 }
 
+static int ixp2000_GPIO_irq_type(unsigned int irq, unsigned int type)
+{
+	int line = irq - IRQ_IXP2000_GPIO0;
+
+	/*
+	 * First, configure this GPIO line as an input.
+	 */
+	ixp2000_reg_write(IXP2000_GPIO_PDCR, 1 << line);
+
+	/*
+	 * Then, set the proper trigger type.
+	 */
+	if (type & IRQT_FALLING)
+		GPIO_IRQ_falling_edge |= 1 << line;
+	else
+		GPIO_IRQ_falling_edge &= ~(1 << line);
+	if (type & IRQT_RISING)
+		GPIO_IRQ_rising_edge |= 1 << line;
+	else
+		GPIO_IRQ_rising_edge &= ~(1 << line);
+	if (type & IRQT_LOW)
+		GPIO_IRQ_level_low |= 1 << line;
+	else
+		GPIO_IRQ_level_low &= ~(1 << line);
+	if (type & IRQT_HIGH)
+		GPIO_IRQ_level_high |= 1 << line;
+	else
+		GPIO_IRQ_level_high &= ~(1 << line);
+	update_gpio_int_csrs();
+
+	/*
+	 * Finally, mark the corresponding IRQ as valid.
+	 */
+	irq_desc[irq].valid = 1;
+
+	return 0;
+}
+
 static void ixp2000_GPIO_irq_mask_ack(unsigned int irq)
 {
 	ixp2000_reg_write(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0)));
+
+	ixp2000_reg_write(IXP2000_GPIO_EDSR, (1 << (irq - IRQ_IXP2000_GPIO0)));
+	ixp2000_reg_write(IXP2000_GPIO_LDSR, (1 << (irq - IRQ_IXP2000_GPIO0)));
 	ixp2000_reg_write(IXP2000_GPIO_INST, (1 << (irq - IRQ_IXP2000_GPIO0)));
 }
 
@@ -284,6 +355,7 @@
 }
 
 static struct irqchip ixp2000_GPIO_irq_chip = {
+	.type	= ixp2000_GPIO_irq_type,
 	.ack	= ixp2000_GPIO_irq_mask_ack,
 	.mask	= ixp2000_GPIO_irq_mask,
 	.unmask	= ixp2000_GPIO_irq_unmask
@@ -320,7 +392,7 @@
 
 static void ixp2000_irq_unmask(unsigned int irq)
 {
-	ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET,  (1 << irq));
+	ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << irq));
 }
 
 static struct irqchip ixp2000_irq_chip = {
@@ -357,16 +429,16 @@
 	 * our mask/unmask code much simpler.
 	 */
 	for (irq = IRQ_IXP2000_SOFT_INT; irq <= IRQ_IXP2000_THDB3; irq++) {
-		if((1 << irq) & IXP2000_VALID_IRQ_MASK) {
+		if ((1 << irq) & IXP2000_VALID_IRQ_MASK) {
 			set_irq_chip(irq, &ixp2000_irq_chip);
 			set_irq_handler(irq, do_level_IRQ);
 			set_irq_flags(irq, IRQF_VALID);
 		} else set_irq_flags(irq, 0);
 	}
-	
+
 	/*
 	 * GPIO IRQs are invalid until someone sets the interrupt mode
-	 * by calling gpio_line_set();
+	 * by calling set_irq_type().
 	 */
 	for (irq = IRQ_IXP2000_GPIO0; irq <= IRQ_IXP2000_GPIO7; irq++) {
 		set_irq_chip(irq, &ixp2000_GPIO_irq_chip);
diff --git a/arch/arm/mach-ixp2000/enp2611.c b/arch/arm/mach-ixp2000/enp2611.c
index 04b38bc..f3a291b 100644
--- a/arch/arm/mach-ixp2000/enp2611.c
+++ b/arch/arm/mach-ixp2000/enp2611.c
@@ -197,8 +197,23 @@
 	.resource	= &enp2611_flash_resource,
 };
 
+static struct ixp2000_i2c_pins enp2611_i2c_gpio_pins = {
+	.sda_pin	= ENP2611_GPIO_SDA,
+	.scl_pin	= ENP2611_GPIO_SCL,
+};
+
+static struct platform_device enp2611_i2c_controller = {
+	.name		= "IXP2000-I2C",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &enp2611_i2c_gpio_pins
+	},
+	.num_resources	= 0
+};
+
 static struct platform_device *enp2611_devices[] __initdata = {
-	&enp2611_flash
+	&enp2611_flash,
+	&enp2611_i2c_controller
 };
 
 static void __init enp2611_init_machine(void)
diff --git a/arch/arm/mach-ixp2000/ixdp2800.c b/arch/arm/mach-ixp2000/ixdp2800.c
index aec13c7..468a4bb 100644
--- a/arch/arm/mach-ixp2000/ixdp2800.c
+++ b/arch/arm/mach-ixp2000/ixdp2800.c
@@ -42,12 +42,6 @@
 #include <asm/mach/flash.h>
 #include <asm/mach/arch.h>
 
-
-void ixdp2400_init_irq(void)
-{
-	ixdp2x00_init_irq(IXDP2800_CPLD_INT_STAT, IXDP2800_CPLD_INT_MASK, IXDP2400_NR_IRQS);
-}
-
 /*************************************************************************
  * IXDP2800 timer tick
  *************************************************************************/
diff --git a/arch/arm/mach-ixp2000/ixdp2x00.c b/arch/arm/mach-ixp2000/ixdp2x00.c
index 21c41fe..5e43807 100644
--- a/arch/arm/mach-ixp2000/ixdp2x00.c
+++ b/arch/arm/mach-ixp2000/ixdp2x00.c
@@ -42,6 +42,9 @@
 #include <asm/mach/flash.h>
 #include <asm/mach/arch.h>
 
+#include <asm/arch/gpio.h>
+
+
 /*************************************************************************
  * IXDP2x00 IRQ Initialization
  *************************************************************************/
diff --git a/arch/arm/mach-ixp2000/pci.c b/arch/arm/mach-ixp2000/pci.c
index 5ff2f27..0788fb2 100644
--- a/arch/arm/mach-ixp2000/pci.c
+++ b/arch/arm/mach-ixp2000/pci.c
@@ -198,6 +198,19 @@
 void __init
 ixp2000_pci_preinit(void)
 {
+#ifndef CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO
+	/*
+	 * Configure the PCI unit to properly byteswap I/O transactions,
+	 * and verify that it worked.
+	 */
+	ixp2000_reg_write(IXP2000_PCI_CONTROL,
+			  (*IXP2000_PCI_CONTROL | PCI_CONTROL_IEE));
+
+	if ((*IXP2000_PCI_CONTROL & PCI_CONTROL_IEE) == 0)
+		panic("IXP2000: PCI I/O is broken on this ixp model, and "
+			"the needed workaround has not been configured in");
+#endif
+
 	hook_fault_code(16+6, ixp2000_pci_abort_handler, SIGBUS,
 				"PCI config cycle to non-existent device");
 }
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 267ba02..04490a9 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -141,7 +141,15 @@
 		.physical	= IXP4XX_PCI_CFG_BASE_PHYS,
 		.length		= IXP4XX_PCI_CFG_REGION_SIZE,
 		.type		= MT_DEVICE
+	},
+#ifdef CONFIG_DEBUG_LL
+	{	/* Debug UART mapping */
+		.virtual	= IXP4XX_DEBUG_UART_BASE_VIRT,
+		.physical	= IXP4XX_DEBUG_UART_BASE_PHYS,
+		.length		= IXP4XX_DEBUG_UART_REGION_SIZE,
+		.type		= MT_DEVICE
 	}
+#endif
 };
 
 void __init ixp4xx_map_io(void)
@@ -290,8 +298,8 @@
 
 static struct irqaction ixp4xx_timer_irq = {
 	.name		= "IXP4xx Timer Tick",
-	.flags		= SA_INTERRUPT,
-	.handler	= ixp4xx_timer_interrupt
+	.flags		= SA_INTERRUPT | SA_TIMER,
+	.handler	= ixp4xx_timer_interrupt,
 };
 
 static void __init ixp4xx_timer_init(void)
diff --git a/arch/arm/mach-lh7a40x/time.c b/arch/arm/mach-lh7a40x/time.c
index 51e1c81..be377e3 100644
--- a/arch/arm/mach-lh7a40x/time.c
+++ b/arch/arm/mach-lh7a40x/time.c
@@ -53,8 +53,8 @@
 
 static struct irqaction lh7a40x_timer_irq = {
 	.name		= "LHA740x Timer Tick",
-	.flags		= SA_INTERRUPT,
-	.handler	= lh7a40x_timer_interrupt
+	.flags		= SA_INTERRUPT | SA_TIMER,
+	.handler	= lh7a40x_timer_interrupt,
 };
 
 static void __init lh7a40x_timer_init(void)
diff --git a/arch/arm/mach-omap/time.c b/arch/arm/mach-omap/time.c
index 4205fdc..589e8b2 100644
--- a/arch/arm/mach-omap/time.c
+++ b/arch/arm/mach-omap/time.c
@@ -188,8 +188,8 @@
 
 static struct irqaction omap_mpu_timer_irq = {
 	.name		= "mpu timer",
-	.flags		= SA_INTERRUPT,
-	.handler	= omap_mpu_timer_interrupt
+	.flags		= SA_INTERRUPT | SA_TIMER,
+	.handler	= omap_mpu_timer_interrupt,
 };
 
 static unsigned long omap_mpu_timer1_overflows;
@@ -203,7 +203,7 @@
 static struct irqaction omap_mpu_timer1_irq = {
 	.name		= "mpu timer1 overflow",
 	.flags		= SA_INTERRUPT,
-	.handler	= omap_mpu_timer1_interrupt
+	.handler	= omap_mpu_timer1_interrupt,
 };
 
 static __init void omap_init_mpu_timer(void)
@@ -349,8 +349,8 @@
 
 static struct irqaction omap_32k_timer_irq = {
 	.name		= "32KHz timer",
-	.flags		= SA_INTERRUPT,
-	.handler	= omap_32k_timer_interrupt
+	.flags		= SA_INTERRUPT | SA_TIMER,
+	.handler	= omap_32k_timer_interrupt,
 };
 
 static __init void omap_init_32k_timer(void)
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index dd012d6..f2c9e0d 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/device.h>
+#include <linux/sysdev.h>
 #include <linux/major.h>
 #include <linux/fb.h>
 #include <linux/interrupt.h>
@@ -106,6 +107,35 @@
 	set_irq_type(IRQ_GPIO(0), IRQT_FALLING);
 }
 
+#ifdef CONFIG_PM
+
+static int lubbock_irq_resume(struct sys_device *dev)
+{
+	LUB_IRQ_MASK_EN = lubbock_irq_enabled;
+	return 0;
+}
+
+static struct sysdev_class lubbock_irq_sysclass = {
+	set_kset_name("cpld_irq"),
+	.resume = lubbock_irq_resume,
+};
+
+static struct sys_device lubbock_irq_device = {
+	.cls = &lubbock_irq_sysclass,
+};
+
+static int __init lubbock_irq_device_init(void)
+{
+	int ret = sysdev_class_register(&lubbock_irq_sysclass);
+	if (ret == 0)
+		ret = sysdev_register(&lubbock_irq_device);
+	return ret;
+}
+
+device_initcall(lubbock_irq_device_init);
+
+#endif
+
 static int lubbock_udc_is_connected(void)
 {
 	return (LUB_MISC_RD & (1 << 9)) == 0;
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index 3f95223..9896afc 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -15,6 +15,7 @@
 
 #include <linux/init.h>
 #include <linux/device.h>
+#include <linux/sysdev.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <linux/bitops.h>
@@ -62,7 +63,6 @@
 	.unmask		= mainstone_unmask_irq,
 };
 
-
 static void mainstone_irq_handler(unsigned int irq, struct irqdesc *desc,
 				  struct pt_regs *regs)
 {
@@ -100,6 +100,35 @@
 	set_irq_type(IRQ_GPIO(0), IRQT_FALLING);
 }
 
+#ifdef CONFIG_PM
+
+static int mainstone_irq_resume(struct sys_device *dev)
+{
+	MST_INTMSKENA = mainstone_irq_enabled;
+	return 0;
+}
+
+static struct sysdev_class mainstone_irq_sysclass = {
+	set_kset_name("cpld_irq"),
+	.resume = mainstone_irq_resume,
+};
+
+static struct sys_device mainstone_irq_device = {
+	.cls = &mainstone_irq_sysclass,
+};
+
+static int __init mainstone_irq_device_init(void)
+{
+	int ret = sysdev_class_register(&mainstone_irq_sysclass);
+	if (ret == 0)
+		ret = sysdev_register(&mainstone_irq_device);
+	return ret;
+}
+
+device_initcall(mainstone_irq_device_init);
+
+#endif
+
 
 static struct resource smc91x_resources[] = {
 	[0] = {
@@ -304,6 +333,15 @@
 	PWER  = 0xC0000002;
 	PRER  = 0x00000002;
 	PFER  = 0x00000002;
+ 	/*	for use I SRAM as framebuffer.	*/
+ 	PSLR |= 0xF04;
+ 	PCFR = 0x66;
+ 	/*	For Keypad wakeup.	*/
+ 	KPC &=~KPC_ASACT;
+ 	KPC |=KPC_AS;
+ 	PKWR  = 0x000FD000;
+ 	/*	Need read PKWR back after set it.	*/
+ 	PKWR;
 }
 
 MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c
index 82a4bf3..ac4dd43 100644
--- a/arch/arm/mach-pxa/pm.c
+++ b/arch/arm/mach-pxa/pm.c
@@ -29,9 +29,6 @@
  */
 #undef DEBUG
 
-extern void pxa_cpu_suspend(void);
-extern void pxa_cpu_resume(void);
-
 #define SAVE(x)		sleep_save[SLEEP_SAVE_##x] = x
 #define RESTORE(x)	x = sleep_save[SLEEP_SAVE_##x]
 
@@ -63,6 +60,12 @@
 	SLEEP_SAVE_ICMR,
 	SLEEP_SAVE_CKEN,
 
+#ifdef CONFIG_PXA27x
+ 	SLEEP_SAVE_MDREFR,
+ 	SLEEP_SAVE_PWER, SLEEP_SAVE_PCFR, SLEEP_SAVE_PRER,
+ 	SLEEP_SAVE_PFER, SLEEP_SAVE_PKWR,
+#endif
+
 	SLEEP_SAVE_CKSUM,
 
 	SLEEP_SAVE_SIZE
@@ -75,9 +78,7 @@
 	unsigned long checksum = 0;
 	struct timespec delta, rtc;
 	int i;
-
-	if (state != PM_SUSPEND_MEM)
-		return -EINVAL;
+	extern void pxa_cpu_pm_enter(suspend_state_t state);
 
 #ifdef CONFIG_IWMMXT
 	/* force any iWMMXt context to ram **/
@@ -100,16 +101,17 @@
 	SAVE(GAFR2_L); SAVE(GAFR2_U);
 
 #ifdef CONFIG_PXA27x
+	SAVE(MDREFR);
 	SAVE(GPLR3); SAVE(GPDR3); SAVE(GRER3); SAVE(GFER3); SAVE(PGSR3);
 	SAVE(GAFR3_L); SAVE(GAFR3_U);
+	SAVE(PWER); SAVE(PCFR); SAVE(PRER);
+	SAVE(PFER); SAVE(PKWR);
 #endif
 
 	SAVE(ICMR);
 	ICMR = 0;
 
 	SAVE(CKEN);
-	CKEN = 0;
-
 	SAVE(PSTR);
 
 	/* Note: wake up source are set up in each machine specific files */
@@ -123,16 +125,15 @@
 	/* Clear sleep reset status */
 	RCSR = RCSR_SMR;
 
-	/* set resume return address */
-	PSPR = virt_to_phys(pxa_cpu_resume);
-
 	/* before sleeping, calculate and save a checksum */
 	for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++)
 		checksum += sleep_save[i];
 	sleep_save[SLEEP_SAVE_CKSUM] = checksum;
 
 	/* *** go zzz *** */
-	pxa_cpu_suspend();
+	pxa_cpu_pm_enter(state);
+
+	cpu_init();
 
 	/* after sleeping, validate the checksum */
 	checksum = 0;
@@ -145,7 +146,7 @@
 		LUB_HEXLED = 0xbadbadc5;
 #endif
 		while (1)
-			pxa_cpu_suspend();
+			pxa_cpu_pm_enter(state);
 	}
 
 	/* ensure not to come back here if it wasn't intended */
@@ -162,8 +163,11 @@
 	RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2);
 
 #ifdef CONFIG_PXA27x
+	RESTORE(MDREFR);
 	RESTORE(GAFR3_L); RESTORE(GAFR3_U); RESTORE_GPLEVEL(3);
 	RESTORE(GPDR3); RESTORE(GRER3); RESTORE(GFER3); RESTORE(PGSR3);
+	RESTORE(PWER); RESTORE(PCFR); RESTORE(PRER);
+	RESTORE(PFER); RESTORE(PKWR);
 #endif
 
 	PSSR = PSSR_RDH | PSSR_PH;
@@ -197,7 +201,9 @@
  */
 static int pxa_pm_prepare(suspend_state_t state)
 {
-	return 0;
+	extern int pxa_cpu_pm_prepare(suspend_state_t state);
+
+	return pxa_cpu_pm_prepare(state);
 }
 
 /*
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index e887b71..7869c3b 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -16,6 +16,7 @@
  * initialization stuff for PXA machines which can be overridden later if
  * need be.
  */
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -102,3 +103,35 @@
 }
 
 EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
+
+#ifdef CONFIG_PM
+
+int pxa_cpu_pm_prepare(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_MEM:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+void pxa_cpu_pm_enter(suspend_state_t state)
+{
+	extern void pxa_cpu_suspend(unsigned int);
+	extern void pxa_cpu_resume(void);
+
+	CKEN = 0;
+
+	switch (state) {
+	case PM_SUSPEND_MEM:
+		/* set resume return address */
+		PSPR = virt_to_phys(pxa_cpu_resume);
+		pxa_cpu_suspend(3);
+		break;
+	}
+}
+
+#endif
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 7e863af..893964f 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -120,6 +120,42 @@
 EXPORT_SYMBOL(get_memclk_frequency_10khz);
 EXPORT_SYMBOL(get_lcdclk_frequency_10khz);
 
+#ifdef CONFIG_PM
+
+int pxa_cpu_pm_prepare(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_MEM:
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+void pxa_cpu_pm_enter(suspend_state_t state)
+{
+	extern void pxa_cpu_standby(void);
+	extern void pxa_cpu_suspend(unsigned int);
+	extern void pxa_cpu_resume(void);
+
+	CKEN = CKEN22_MEMC | CKEN9_OSTIMER;
+
+	/* ensure voltage-change sequencer not initiated, which hangs */
+	PCFR &= ~PCFR_FVC;
+
+	/* Clear edge-detect status register. */
+	PEDR = 0xDF12FE1B;
+
+	switch (state) {
+	case PM_SUSPEND_MEM:
+		/* set resume return address */
+		PSPR = virt_to_phys(pxa_cpu_resume);
+		pxa_cpu_suspend(3);
+		break;
+	}
+}
+
+#endif
 
 /*
  * device registration specific to PXA27x.
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index 473fb61..6e52021 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -105,8 +105,8 @@
 
 static struct irqaction pxa_timer_irq = {
 	.name		= "PXA Timer Tick",
-	.flags		= SA_INTERRUPT,
-	.handler	= pxa_timer_interrupt
+	.flags		= SA_INTERRUPT | SA_TIMER,
+	.handler	= pxa_timer_interrupt,
 };
 
 static void __init pxa_timer_init(void)
diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c
index 815c532..4371068 100644
--- a/arch/arm/mach-rpc/riscpc.c
+++ b/arch/arm/mach-rpc/riscpc.c
@@ -32,10 +32,7 @@
 
 extern void rpc_init_irq(void);
 
-extern unsigned int vram_size;
-
-#if 0
-
+unsigned int vram_size;
 unsigned int memc_ctrl_reg;
 unsigned int number_mfm_drives;
 
@@ -63,8 +60,6 @@
 
 __tagtable(ATAG_ACORN, parse_tag_acorn);
 
-#endif
-
 static struct map_desc rpc_io_desc[] __initdata = {
  { SCREEN_BASE,	SCREEN_START,	2*1048576, MT_DEVICE }, /* VRAM		*/
  { (u32)IO_BASE, IO_START,	IO_SIZE	 , MT_DEVICE }, /* IO space	*/
diff --git a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c
index bc229fa..c7c2889 100644
--- a/arch/arm/mach-s3c2410/dma.c
+++ b/arch/arm/mach-s3c2410/dma.c
@@ -785,6 +785,10 @@
 	chan->client = NULL;
 	chan->in_use = 0;
 
+	if (chan->irq_claimed)
+		free_irq(chan->irq, (void *)chan);
+	chan->irq_claimed = 0;
+
 	local_irq_restore(flags);
 
 	return 0;
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index 3bb97eb..f3e9700 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -26,6 +26,7 @@
  *     03-Mar-2005 BJD  Ensured that bast-cpld.h is included
  *     10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
  *     14-Mar-2006 BJD  Updated for __iomem changes
+ *     22-Jun-2006 BJD  Added DM9000 platform information
 */
 
 #include <linux/kernel.h>
@@ -35,6 +36,7 @@
 #include <linux/timer.h>
 #include <linux/init.h>
 #include <linux/device.h>
+#include <linux/dm9000.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -53,6 +55,7 @@
 #include <asm/arch/regs-serial.h>
 #include <asm/arch/regs-gpio.h>
 #include <asm/arch/regs-mem.h>
+#include <asm/arch/regs-lcd.h>
 #include <asm/arch/nand.h>
 
 #include <linux/mtd/mtd.h>
@@ -112,7 +115,6 @@
   { VA_C2(BAST_VA_ISAMEM),  PA_CS2(BAST_PA_ISAMEM),   SZ_16M, MT_DEVICE },
   { VA_C2(BAST_VA_ASIXNET), PA_CS3(BAST_PA_ASIXNET),  SZ_1M,  MT_DEVICE },
   { VA_C2(BAST_VA_SUPERIO), PA_CS2(BAST_PA_SUPERIO),  SZ_1M,  MT_DEVICE },
-  { VA_C2(BAST_VA_DM9000),  PA_CS2(BAST_PA_DM9000),   SZ_1M,  MT_DEVICE },
   { VA_C2(BAST_VA_IDEPRI),  PA_CS3(BAST_PA_IDEPRI),   SZ_1M,  MT_DEVICE },
   { VA_C2(BAST_VA_IDESEC),  PA_CS3(BAST_PA_IDESEC),   SZ_1M,  MT_DEVICE },
   { VA_C2(BAST_VA_IDEPRIAUX), PA_CS3(BAST_PA_IDEPRIAUX), SZ_1M, MT_DEVICE },
@@ -123,7 +125,6 @@
   { VA_C3(BAST_VA_ISAMEM),  PA_CS3(BAST_PA_ISAMEM),   SZ_16M, MT_DEVICE },
   { VA_C3(BAST_VA_ASIXNET), PA_CS3(BAST_PA_ASIXNET),  SZ_1M,  MT_DEVICE },
   { VA_C3(BAST_VA_SUPERIO), PA_CS3(BAST_PA_SUPERIO),  SZ_1M,  MT_DEVICE },
-  { VA_C3(BAST_VA_DM9000),  PA_CS3(BAST_PA_DM9000),   SZ_1M,  MT_DEVICE },
   { VA_C3(BAST_VA_IDEPRI),  PA_CS3(BAST_PA_IDEPRI),   SZ_1M,  MT_DEVICE },
   { VA_C3(BAST_VA_IDESEC),  PA_CS3(BAST_PA_IDESEC),   SZ_1M,  MT_DEVICE },
   { VA_C3(BAST_VA_IDEPRIAUX), PA_CS3(BAST_PA_IDEPRIAUX), SZ_1M, MT_DEVICE },
@@ -134,7 +135,6 @@
   { VA_C4(BAST_VA_ISAMEM),  PA_CS4(BAST_PA_ISAMEM),   SZ_16M, MT_DEVICE },
   { VA_C4(BAST_VA_ASIXNET), PA_CS5(BAST_PA_ASIXNET),  SZ_1M,  MT_DEVICE },
   { VA_C4(BAST_VA_SUPERIO), PA_CS4(BAST_PA_SUPERIO),  SZ_1M,  MT_DEVICE },
-  { VA_C4(BAST_VA_DM9000),  PA_CS4(BAST_PA_DM9000),   SZ_1M,  MT_DEVICE },
   { VA_C4(BAST_VA_IDEPRI),  PA_CS5(BAST_PA_IDEPRI),   SZ_1M,  MT_DEVICE },
   { VA_C4(BAST_VA_IDESEC),  PA_CS5(BAST_PA_IDESEC),   SZ_1M,  MT_DEVICE },
   { VA_C4(BAST_VA_IDEPRIAUX), PA_CS5(BAST_PA_IDEPRIAUX), SZ_1M, MT_DEVICE },
@@ -145,7 +145,6 @@
   { VA_C5(BAST_VA_ISAMEM),  PA_CS5(BAST_PA_ISAMEM),   SZ_16M, MT_DEVICE },
   { VA_C5(BAST_VA_ASIXNET), PA_CS5(BAST_PA_ASIXNET),  SZ_1M,  MT_DEVICE },
   { VA_C5(BAST_VA_SUPERIO), PA_CS5(BAST_PA_SUPERIO),  SZ_1M,  MT_DEVICE },
-  { VA_C5(BAST_VA_DM9000),  PA_CS5(BAST_PA_DM9000),   SZ_1M,  MT_DEVICE },
   { VA_C5(BAST_VA_IDEPRI),  PA_CS5(BAST_PA_IDEPRI),   SZ_1M,  MT_DEVICE },
   { VA_C5(BAST_VA_IDESEC),  PA_CS5(BAST_PA_IDESEC),   SZ_1M,  MT_DEVICE },
   { VA_C5(BAST_VA_IDEPRIAUX), PA_CS5(BAST_PA_IDEPRIAUX), SZ_1M, MT_DEVICE },
@@ -313,6 +312,45 @@
 	.select_chip	= bast_nand_select,
 };
 
+/* DM9000 */
+
+static struct resource bast_dm9k_resource[] = {
+	[0] = {
+		.start = S3C2410_CS5 + BAST_PA_DM9000,
+		.end   = S3C2410_CS5 + BAST_PA_DM9000 + 3,
+		.flags = IORESOURCE_MEM
+	},
+	[1] = {
+		.start = S3C2410_CS5 + BAST_PA_DM9000 + 0x40,
+		.end   = S3C2410_CS5 + BAST_PA_DM9000 + 0x40 + 0x3f,
+		.flags = IORESOURCE_MEM
+	},
+	[2] = {
+		.start = IRQ_DM9000,
+		.end   = IRQ_DM9000,
+		.flags = IORESOURCE_IRQ
+	}
+
+};
+
+/* for the moment we limit ourselves to 16bit IO until some
+ * better IO routines can be written and tested
+*/
+
+struct dm9000_plat_data bast_dm9k_platdata = {
+	.flags		= DM9000_PLATF_16BITONLY
+};
+
+static struct platform_device bast_device_dm9k = {
+	.name		= "dm9000",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(bast_dm9k_resource),
+	.resource	= bast_dm9k_resource,
+	.dev		= {
+		.platform_data = &bast_dm9k_platdata,
+	}
+};
+
 
 /* Standard BAST devices */
 
@@ -324,7 +362,8 @@
 	&s3c_device_iis,
  	&s3c_device_rtc,
 	&s3c_device_nand,
-	&bast_device_nor
+	&bast_device_nor,
+	&bast_device_dm9k,
 };
 
 static struct clk *bast_clocks[] = {
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index 5512146..76be074 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -27,6 +27,7 @@
  *     10-Feb-2005 BJD  Added power-off capability
  *     10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
  *     14-Mar-2006 BJD  void __iomem fixes
+ *     22-Jun-2006 BJD  Added DM9000 platform information
 */
 
 #include <linux/kernel.h>
@@ -35,6 +36,7 @@
 #include <linux/list.h>
 #include <linux/timer.h>
 #include <linux/init.h>
+#include <linux/dm9000.h>
 
 #include <linux/serial.h>
 #include <linux/tty.h>
@@ -98,28 +100,24 @@
    * are only 8bit */
 
   /* slow, byte */
-  { VA_C2(VR1000_VA_DM9000),  PA_CS2(VR1000_PA_DM9000),	  SZ_1M,  MT_DEVICE },
   { VA_C2(VR1000_VA_IDEPRI),  PA_CS3(VR1000_PA_IDEPRI),	  SZ_1M,  MT_DEVICE },
   { VA_C2(VR1000_VA_IDESEC),  PA_CS3(VR1000_PA_IDESEC),	  SZ_1M,  MT_DEVICE },
   { VA_C2(VR1000_VA_IDEPRIAUX), PA_CS3(VR1000_PA_IDEPRIAUX), SZ_1M, MT_DEVICE },
   { VA_C2(VR1000_VA_IDESECAUX), PA_CS3(VR1000_PA_IDESECAUX), SZ_1M, MT_DEVICE },
 
   /* slow, word */
-  { VA_C3(VR1000_VA_DM9000),  PA_CS3(VR1000_PA_DM9000),	  SZ_1M,  MT_DEVICE },
   { VA_C3(VR1000_VA_IDEPRI),  PA_CS3(VR1000_PA_IDEPRI),	  SZ_1M,  MT_DEVICE },
   { VA_C3(VR1000_VA_IDESEC),  PA_CS3(VR1000_PA_IDESEC),	  SZ_1M,  MT_DEVICE },
   { VA_C3(VR1000_VA_IDEPRIAUX), PA_CS3(VR1000_PA_IDEPRIAUX), SZ_1M, MT_DEVICE },
   { VA_C3(VR1000_VA_IDESECAUX), PA_CS3(VR1000_PA_IDESECAUX), SZ_1M, MT_DEVICE },
 
   /* fast, byte */
-  { VA_C4(VR1000_VA_DM9000),  PA_CS4(VR1000_PA_DM9000),	  SZ_1M,  MT_DEVICE },
   { VA_C4(VR1000_VA_IDEPRI),  PA_CS5(VR1000_PA_IDEPRI),	  SZ_1M,  MT_DEVICE },
   { VA_C4(VR1000_VA_IDESEC),  PA_CS5(VR1000_PA_IDESEC),	  SZ_1M,  MT_DEVICE },
   { VA_C4(VR1000_VA_IDEPRIAUX), PA_CS5(VR1000_PA_IDEPRIAUX), SZ_1M, MT_DEVICE },
   { VA_C4(VR1000_VA_IDESECAUX), PA_CS5(VR1000_PA_IDESECAUX), SZ_1M, MT_DEVICE },
 
   /* fast, word */
-  { VA_C5(VR1000_VA_DM9000),  PA_CS5(VR1000_PA_DM9000),	  SZ_1M,  MT_DEVICE },
   { VA_C5(VR1000_VA_IDEPRI),  PA_CS5(VR1000_PA_IDEPRI),	  SZ_1M,  MT_DEVICE },
   { VA_C5(VR1000_VA_IDESEC),  PA_CS5(VR1000_PA_IDESEC),	  SZ_1M,  MT_DEVICE },
   { VA_C5(VR1000_VA_IDEPRIAUX), PA_CS5(VR1000_PA_IDEPRIAUX), SZ_1M, MT_DEVICE },
@@ -246,6 +244,74 @@
 	.resource	= vr1000_nor_resource,
 };
 
+/* DM9000 ethernet devices */
+
+static struct resource vr1000_dm9k0_resource[] = {
+	[0] = {
+		.start = S3C2410_CS5 + VR1000_PA_DM9000,
+		.end   = S3C2410_CS5 + VR1000_PA_DM9000 + 3,
+		.flags = IORESOURCE_MEM
+	},
+	[1] = {
+		.start = S3C2410_CS5 + VR1000_PA_DM9000 + 0x40,
+		.end   = S3C2410_CS5 + VR1000_PA_DM9000 + 0x7f,
+		.flags = IORESOURCE_MEM
+	},
+	[2] = {
+		.start = IRQ_VR1000_DM9000A,
+		.end   = IRQ_VR1000_DM9000A,
+		.flags = IORESOURCE_IRQ
+	}
+
+};
+
+static struct resource vr1000_dm9k1_resource[] = {
+	[0] = {
+		.start = S3C2410_CS5 + VR1000_PA_DM9000 + 0x80,
+		.end   = S3C2410_CS5 + VR1000_PA_DM9000 + 0x83,
+		.flags = IORESOURCE_MEM
+	},
+	[1] = {
+		.start = S3C2410_CS5 + VR1000_PA_DM9000 + 0xC0,
+		.end   = S3C2410_CS5 + VR1000_PA_DM9000 + 0xFF,
+		.flags = IORESOURCE_MEM
+	},
+	[2] = {
+		.start = IRQ_VR1000_DM9000N,
+		.end   = IRQ_VR1000_DM9000N,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+/* for the moment we limit ourselves to 16bit IO until some
+ * better IO routines can be written and tested
+*/
+
+struct dm9000_plat_data vr1000_dm9k_platdata = {
+	.flags		= DM9000_PLATF_16BITONLY,
+};
+
+static struct platform_device vr1000_dm9k0 = {
+	.name		= "dm9000",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(vr1000_dm9k0_resource),
+	.resource	= vr1000_dm9k0_resource,
+	.dev		= {
+		.platform_data = &vr1000_dm9k_platdata,
+	}
+};
+
+static struct platform_device vr1000_dm9k1 = {
+	.name		= "dm9000",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(vr1000_dm9k1_resource),
+	.resource	= vr1000_dm9k1_resource,
+	.dev		= {
+		.platform_data = &vr1000_dm9k_platdata,
+	}
+};
+
+/* devices for this board */
 
 static struct platform_device *vr1000_devices[] __initdata = {
 	&s3c_device_usb,
@@ -253,8 +319,11 @@
 	&s3c_device_wdt,
 	&s3c_device_i2c,
 	&s3c_device_iis,
+	&s3c_device_adc,
 	&serial_device,
 	&vr1000_nor,
+	&vr1000_dm9k0,
+	&vr1000_dm9k1
 };
 
 static struct clk *vr1000_clocks[] = {
diff --git a/arch/arm/mach-s3c2410/time.c b/arch/arm/mach-s3c2410/time.c
index 179f0e0..765a3a9 100644
--- a/arch/arm/mach-s3c2410/time.c
+++ b/arch/arm/mach-s3c2410/time.c
@@ -137,8 +137,8 @@
 
 static struct irqaction s3c2410_timer_irq = {
 	.name		= "S3C2410 Timer Tick",
-	.flags		= SA_INTERRUPT,
-	.handler	= s3c2410_timer_interrupt
+	.flags		= SA_INTERRUPT | SA_TIMER,
+	.handler	= s3c2410_timer_interrupt,
 };
 
 /*
diff --git a/arch/arm/mach-sa1100/Kconfig b/arch/arm/mach-sa1100/Kconfig
index 50cde57..6923316 100644
--- a/arch/arm/mach-sa1100/Kconfig
+++ b/arch/arm/mach-sa1100/Kconfig
@@ -150,7 +150,7 @@
 
 config H3600_SLEEVE
 	tristate "Compaq iPAQ Handheld sleeve support"
-	depends on SA1100_H3600
+	depends on SA1100_H3100 || SA1100_H3600
 	help
 	  Choose this option to enable support for extension packs (sleeves)
 	  for the Compaq iPAQ H3XXX series of handheld computers.  This option
diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c
index 84c8654..65dbe99 100644
--- a/arch/arm/mach-sa1100/h3600.c
+++ b/arch/arm/mach-sa1100/h3600.c
@@ -727,7 +727,7 @@
 static struct irqaction h3800_irq = {
 	.name		= "h3800_asic",
 	.handler	= h3800_IRQ_demux,
-	.flags		= SA_INTERRUPT,
+	.flags		= SA_INTERRUPT | SA_TIMER,
 };
 
 u32 kpio_int_shadow = 0;
diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c
index 379ea5e..59c7964 100644
--- a/arch/arm/mach-sa1100/pm.c
+++ b/arch/arm/mach-sa1100/pm.c
@@ -88,6 +88,8 @@
 	/* go zzz */
 	sa1100_cpu_suspend();
 
+	cpu_init();
+
 	/*
 	 * Ensure not to come back here if it wasn't intended
 	 */
diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c
index 19b0c0f..0eeb361 100644
--- a/arch/arm/mach-sa1100/time.c
+++ b/arch/arm/mach-sa1100/time.c
@@ -99,8 +99,8 @@
 
 static struct irqaction sa1100_timer_irq = {
 	.name		= "SA11xx Timer Tick",
-	.flags		= SA_INTERRUPT,
-	.handler	= sa1100_timer_interrupt
+	.flags		= SA_INTERRUPT | SA_TIMER,
+	.handler	= sa1100_timer_interrupt,
 };
 
 static void __init sa1100_timer_init(void)
diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c
index a9bc5d0..aa0e2f6 100644
--- a/arch/arm/mach-shark/core.c
+++ b/arch/arm/mach-shark/core.c
@@ -84,8 +84,8 @@
 
 static struct irqaction shark_timer_irq = {
 	.name		= "Shark Timer Tick",
-	.flags		= SA_INTERRUPT,
-	.handler	= shark_timer_interrupt
+	.flags		= SA_INTERRUPT | SA_TIMER,
+	.handler	= shark_timer_interrupt,
 };
 
 /*
diff --git a/arch/arm/mach-versatile/Makefile b/arch/arm/mach-versatile/Makefile
index 5d60883..ba81e70 100644
--- a/arch/arm/mach-versatile/Makefile
+++ b/arch/arm/mach-versatile/Makefile
@@ -5,3 +5,4 @@
 obj-y					:= core.o clock.o
 obj-$(CONFIG_ARCH_VERSATILE_PB)		+= versatile_pb.o
 obj-$(CONFIG_MACH_VERSATILE_AB)		+= versatile_ab.o
+obj-$(CONFIG_PCI)			+= pci.o
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 554e1bd..9d1f225 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -196,11 +196,15 @@
 #ifdef CONFIG_DEBUG_LL
  { IO_ADDRESS(VERSATILE_UART0_BASE), VERSATILE_UART0_BASE, SZ_4K,      MT_DEVICE },
 #endif
-#ifdef FIXME
- { PCI_MEMORY_VADDR,		     PHYS_PCI_MEM_BASE,    SZ_16M,     MT_DEVICE },
- { PCI_CONFIG_VADDR,		     PHYS_PCI_CONFIG_BASE, SZ_16M,     MT_DEVICE },
- { PCI_V3_VADDR,		     PHYS_PCI_V3_BASE,     SZ_512K,    MT_DEVICE },
- { PCI_IO_VADDR,		     PHYS_PCI_IO_BASE,     SZ_64K,     MT_DEVICE },
+#ifdef CONFIG_PCI
+ { IO_ADDRESS(VERSATILE_PCI_CORE_BASE), VERSATILE_PCI_CORE_BASE, SZ_4K, MT_DEVICE },
+ { VERSATILE_PCI_VIRT_BASE,          VERSATILE_PCI_BASE,   VERSATILE_PCI_BASE_SIZE, MT_DEVICE },
+ { VERSATILE_PCI_CFG_VIRT_BASE,      VERSATILE_PCI_CFG_BASE, VERSATILE_PCI_CFG_BASE_SIZE, MT_DEVICE },
+#if 0
+ { VERSATILE_PCI_VIRT_MEM_BASE0,     VERSATILE_PCI_MEM_BASE0, SZ_16M,  MT_DEVICE },
+ { VERSATILE_PCI_VIRT_MEM_BASE1,     VERSATILE_PCI_MEM_BASE1, SZ_16M,  MT_DEVICE },
+ { VERSATILE_PCI_VIRT_MEM_BASE2,     VERSATILE_PCI_MEM_BASE2, SZ_16M,  MT_DEVICE },
+#endif
 #endif
 };
 
@@ -543,7 +547,7 @@
 		val |= SYS_CLCD_MODE_5551;
 		break;
 	case 6:
-		val |= SYS_CLCD_MODE_565_BLSB;
+		val |= SYS_CLCD_MODE_565_RLSB;
 		break;
 	case 8:
 		val |= SYS_CLCD_MODE_888;
@@ -871,8 +875,8 @@
 
 static struct irqaction versatile_timer_irq = {
 	.name		= "Versatile Timer Tick",
-	.flags		= SA_INTERRUPT,
-	.handler	= versatile_timer_interrupt
+	.flags		= SA_INTERRUPT | SA_TIMER,
+	.handler	= versatile_timer_interrupt,
 };
 
 /*
diff --git a/arch/arm/mach-versatile/pci.c b/arch/arm/mach-versatile/pci.c
new file mode 100644
index 0000000..d1565e8
--- /dev/null
+++ b/arch/arm/mach-versatile/pci.c
@@ -0,0 +1,360 @@
+/*
+ *  linux/arch/arm/mach-versatile/pci.c
+ *
+ * (C) Copyright Koninklijke Philips Electronics NV 2004. All rights reserved.
+ * You can redistribute and/or modify this software under the terms of version 2
+ * of the GNU General Public License as published by the Free Software Foundation.
+ * THIS SOFTWARE IS PROVIDED "AS IS" 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.
+ * Koninklijke Philips Electronics nor its subsidiaries is obligated to provide any support for this software.
+ *
+ * ARM Versatile PCI driver.
+ *
+ * 14/04/2005 Initial version, colin.king@philips.com
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+/*
+ * these spaces are mapped using the following base registers:
+ *
+ * Usage Local Bus Memory         Base/Map registers used
+ *
+ * Mem   50000000 - 5FFFFFFF      LB_BASE0/LB_MAP0,  non prefetch
+ * Mem   60000000 - 6FFFFFFF      LB_BASE1/LB_MAP1,  prefetch
+ * IO    44000000 - 4FFFFFFF      LB_BASE2/LB_MAP2,  IO
+ * Cfg   42000000 - 42FFFFFF	  PCI config
+ *
+ */
+#define SYS_PCICTL			IO_ADDRESS(VERSATILE_SYS_PCICTL)
+#define PCI_IMAP0			IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x0)
+#define PCI_IMAP1			IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x4)
+#define PCI_IMAP2			IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x8)
+#define PCI_SMAP0			IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x10)
+#define PCI_SMAP1			IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x14)
+#define PCI_SMAP2			IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x18)
+#define PCI_SELFID			IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0xc)
+
+#define DEVICE_ID_OFFSET		0x00
+#define CSR_OFFSET			0x04
+#define CLASS_ID_OFFSET			0x08
+
+#define VP_PCI_DEVICE_ID		0x030010ee
+#define VP_PCI_CLASS_ID			0x0b400000
+
+static unsigned long pci_slot_ignore = 0;
+
+static int __init versatile_pci_slot_ignore(char *str)
+{
+	int retval;
+	int slot;
+
+	while ((retval = get_option(&str,&slot))) {
+		if ((slot < 0) || (slot > 31)) {
+			printk("Illegal slot value: %d\n",slot);
+		} else {
+			pci_slot_ignore |= (1 << slot);
+		}
+	}
+	return 1;
+}
+
+__setup("pci_slot_ignore=", versatile_pci_slot_ignore);
+
+
+static unsigned long __pci_addr(struct pci_bus *bus,
+				unsigned int devfn, int offset)
+{
+	unsigned int busnr = bus->number;
+
+	/*
+	 * Trap out illegal values
+	 */
+	if (offset > 255)
+		BUG();
+	if (busnr > 255)
+		BUG();
+	if (devfn > 255)
+		BUG();
+
+	return (VERSATILE_PCI_CFG_VIRT_BASE | (busnr << 16) |
+		(PCI_SLOT(devfn) << 11) | (PCI_FUNC(devfn) << 8) | offset);
+}
+
+static int versatile_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+				 int size, u32 *val)
+{
+	unsigned long addr = __pci_addr(bus, devfn, where);
+	u32 v;
+	int slot = PCI_SLOT(devfn);
+
+	if (pci_slot_ignore & (1 << slot)) {
+		/* Ignore this slot */
+		switch (size) {
+		case 1:
+			v = 0xff;
+			break;
+		case 2:
+			v = 0xffff;
+			break;
+		default:
+			v = 0xffffffff;
+		}
+	} else {
+		switch (size) {
+		case 1:
+			addr &= ~3;
+			v = __raw_readb(addr);
+			break;
+
+		case 2:
+			v = __raw_readl(addr & ~3);
+			if (addr & 2) v >>= 16;
+ 			v &= 0xffff;
+			break;
+
+		default:
+			addr &= ~3;
+			v = __raw_readl(addr);
+			break;
+		}
+	}
+
+	*val = v;
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int versatile_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+				  int size, u32 val)
+{
+	unsigned long addr = __pci_addr(bus, devfn, where);
+	int slot = PCI_SLOT(devfn);
+
+	if (pci_slot_ignore & (1 << slot)) {
+		return PCIBIOS_SUCCESSFUL;
+	}
+
+	switch (size) {
+	case 1:
+		__raw_writeb((u8)val, addr);
+		break;
+
+	case 2:
+		__raw_writew((u16)val, addr);
+		break;
+
+	case 4:
+		__raw_writel(val, addr);
+		break;
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops pci_versatile_ops = {
+	.read	= versatile_read_config,
+	.write	= versatile_write_config,
+};
+
+static struct resource io_mem = {
+	.name	= "PCI I/O space",
+	.start	= VERSATILE_PCI_MEM_BASE0,
+	.end	= VERSATILE_PCI_MEM_BASE0+VERSATILE_PCI_MEM_BASE0_SIZE-1,
+	.flags	= IORESOURCE_IO,
+};
+
+static struct resource non_mem = {
+	.name	= "PCI non-prefetchable",
+	.start	= VERSATILE_PCI_MEM_BASE1,
+	.end	= VERSATILE_PCI_MEM_BASE1+VERSATILE_PCI_MEM_BASE1_SIZE-1,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct resource pre_mem = {
+	.name	= "PCI prefetchable",
+	.start	= VERSATILE_PCI_MEM_BASE2,
+	.end	= VERSATILE_PCI_MEM_BASE2+VERSATILE_PCI_MEM_BASE2_SIZE-1,
+	.flags	= IORESOURCE_MEM | IORESOURCE_PREFETCH,
+};
+
+static int __init pci_versatile_setup_resources(struct resource **resource)
+{
+	int ret = 0;
+
+	ret = request_resource(&iomem_resource, &io_mem);
+	if (ret) {
+		printk(KERN_ERR "PCI: unable to allocate I/O "
+		       "memory region (%d)\n", ret);
+		goto out;
+	}
+	ret = request_resource(&iomem_resource, &non_mem);
+	if (ret) {
+		printk(KERN_ERR "PCI: unable to allocate non-prefetchable "
+		       "memory region (%d)\n", ret);
+		goto release_io_mem;
+	}
+	ret = request_resource(&iomem_resource, &pre_mem);
+	if (ret) {
+		printk(KERN_ERR "PCI: unable to allocate prefetchable "
+		       "memory region (%d)\n", ret);
+		goto release_non_mem;
+	}
+
+	/*
+	 * bus->resource[0] is the IO resource for this bus
+	 * bus->resource[1] is the mem resource for this bus
+	 * bus->resource[2] is the prefetch mem resource for this bus
+	 */
+	resource[0] = &io_mem;
+	resource[1] = &non_mem;
+	resource[2] = &pre_mem;
+
+	goto out;
+
+ release_non_mem:
+	release_resource(&non_mem);
+ release_io_mem:
+	release_resource(&io_mem);
+ out:
+	return ret;
+}
+
+int __init pci_versatile_setup(int nr, struct pci_sys_data *sys)
+{
+	int ret = 0;
+        int i;
+        int myslot = -1;
+	unsigned long val;
+
+	if (nr == 0) {
+		sys->mem_offset = 0;
+		ret = pci_versatile_setup_resources(sys->resource);
+		if (ret < 0) {
+			printk("pci_versatile_setup: resources... oops?\n");
+			goto out;
+		}
+	} else {
+		printk("pci_versatile_setup: resources... nr == 0??\n");
+		goto out;
+	}
+
+	__raw_writel(VERSATILE_PCI_MEM_BASE0 >> 28,PCI_IMAP0);
+	__raw_writel(VERSATILE_PCI_MEM_BASE1 >> 28,PCI_IMAP1);
+	__raw_writel(VERSATILE_PCI_MEM_BASE2 >> 28,PCI_IMAP2);
+
+	__raw_writel(1, SYS_PCICTL);
+
+	val = __raw_readl(SYS_PCICTL);
+	if (!(val & 1)) {
+		printk("Not plugged into PCI backplane!\n");
+		ret = -EIO;
+		goto out;
+	}
+
+	/*
+	 *  We need to discover the PCI core first to configure itself
+	 *  before the main PCI probing is performed
+	 */
+	for (i=0; i<32; i++) {
+		if ((__raw_readl(VERSATILE_PCI_VIRT_BASE+(i<<11)+DEVICE_ID_OFFSET) == VP_PCI_DEVICE_ID) &&
+		    (__raw_readl(VERSATILE_PCI_VIRT_BASE+(i<<11)+CLASS_ID_OFFSET) == VP_PCI_CLASS_ID)) {
+			myslot = i;
+
+			__raw_writel(myslot, PCI_SELFID);
+			val = __raw_readl(VERSATILE_PCI_CFG_VIRT_BASE+(myslot<<11)+CSR_OFFSET);
+			val |= (1<<2);
+			__raw_writel(val, VERSATILE_PCI_CFG_VIRT_BASE+(myslot<<11)+CSR_OFFSET);
+			break;
+		}
+	}
+
+	if (myslot == -1) {
+		printk("Cannot find PCI core!\n");
+		ret = -EIO;
+	} else {
+		printk("PCI core found (slot %d)\n",myslot);
+		/* Do not to map Versatile FPGA PCI device
+		   into memory space as we are short of
+		   mappable memory */
+		pci_slot_ignore |= (1 << myslot);
+		ret = 1;
+	}
+
+ out:
+	return ret;
+}
+
+
+struct pci_bus *pci_versatile_scan_bus(int nr, struct pci_sys_data *sys)
+{
+	return pci_scan_bus(sys->busnr, &pci_versatile_ops, sys);
+}
+
+/*
+ * V3_LB_BASE? - local bus address
+ * V3_LB_MAP?  - pci bus address
+ */
+void __init pci_versatile_preinit(void)
+{
+}
+
+void __init pci_versatile_postinit(void)
+{
+}
+
+
+/*
+ * map the specified device/slot/pin to an IRQ.   Different backplanes may need to modify this.
+ */
+static int __init versatile_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int irq;
+	int devslot = PCI_SLOT(dev->devfn);
+
+	/* slot,  pin,  irq
+	    24	  1	27
+	    25    1	28	untested
+	    26	  1	29
+	    27    1	30	untested
+	*/
+
+	irq = 27 + ((slot + pin + 2) % 3);	/* Fudged */
+
+	printk("map irq: slot %d, pin %d, devslot %d, irq: %d\n",slot,pin,devslot,irq);
+
+	return irq;
+}
+
+static struct hw_pci versatile_pci __initdata = {
+	.swizzle		= NULL,
+	.map_irq		= versatile_map_irq,
+	.nr_controllers		= 1,
+	.setup			= pci_versatile_setup,
+	.scan			= pci_versatile_scan_bus,
+	.preinit		= pci_versatile_preinit,
+	.postinit		= pci_versatile_postinit,
+};
+
+static int __init versatile_pci_init(void)
+{
+	pci_common_init(&versatile_pci);
+	return 0;
+}
+
+subsys_initcall(versatile_pci_init);
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 48bac7d..95606b4 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -62,7 +62,7 @@
 # ARM920T
 config CPU_ARM920T
 	bool "Support ARM920T processor" if !ARCH_S3C2410
-	depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX
+	depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000
 	default y if ARCH_S3C2410
 	select CPU_32v4
 	select CPU_ABRT_EV4T
@@ -228,7 +228,6 @@
 	select CPU_CACHE_V4WB
 	select CPU_CACHE_VIVT
 	select CPU_TLB_V4WB
-	select CPU_MINICACHE
 
 # XScale
 config CPU_XSCALE
@@ -239,7 +238,6 @@
 	select CPU_ABRT_EV5T
 	select CPU_CACHE_VIVT
 	select CPU_TLB_V4WBI
-	select CPU_MINICACHE
 
 # ARMv6
 config CPU_V6
@@ -345,11 +343,6 @@
 config CPU_TLB_V6
 	bool
 
-config CPU_MINICACHE
-	bool
-	help
-	  Processor has a minicache.
-
 comment "Processor Features"
 
 config ARM_THUMB
@@ -429,3 +422,11 @@
 	  assume directly accessing that register and always obtain the
 	  expected value only on ARMv7 and above.
 
+config NEEDS_SYSCALL_FOR_CMPXCHG
+	bool
+	default y if SMP && (CPU_32v5 || CPU_32v4 || CPU_32v3)
+	help
+	  SMP on a pre-ARMv6 processor?  Well OK then.
+	  Forget about fast user space cmpxchg support.
+	  It is just not possible.
+
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index ccf316c..59f47d4 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -31,8 +31,6 @@
 obj-$(CONFIG_CPU_SA1100)	+= copypage-v4mc.o
 obj-$(CONFIG_CPU_XSCALE)	+= copypage-xscale.o
 
-obj-$(CONFIG_CPU_MINICACHE)	+= minicache.o
-
 obj-$(CONFIG_CPU_TLB_V3)	+= tlb-v3.o
 obj-$(CONFIG_CPU_TLB_V4WT)	+= tlb-v4.o
 obj-$(CONFIG_CPU_TLB_V4WB)	+= tlb-v4wb.o
diff --git a/arch/arm/mm/copypage-v6.c b/arch/arm/mm/copypage-v6.c
index a8c0023..27d0415 100644
--- a/arch/arm/mm/copypage-v6.c
+++ b/arch/arm/mm/copypage-v6.c
@@ -30,8 +30,6 @@
 
 static DEFINE_SPINLOCK(v6_lock);
 
-#define DCACHE_COLOUR(vaddr) ((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
-
 /*
  * Copy the user page.  No aliasing to deal with so we can just
  * attack the kernel's existing mapping of these pages.
@@ -55,7 +53,7 @@
  */
 void v6_copy_user_page_aliasing(void *kto, const void *kfrom, unsigned long vaddr)
 {
-	unsigned int offset = DCACHE_COLOUR(vaddr);
+	unsigned int offset = CACHE_COLOUR(vaddr);
 	unsigned long from, to;
 
 	/*
@@ -95,7 +93,7 @@
  */
 void v6_clear_user_page_aliasing(void *kaddr, unsigned long vaddr)
 {
-	unsigned int offset = DCACHE_COLOUR(vaddr);
+	unsigned int offset = CACHE_COLOUR(vaddr);
 	unsigned long to = to_address + (offset << PAGE_SHIFT);
 
 	/*
diff --git a/arch/arm/mm/copypage-xscale.S b/arch/arm/mm/copypage-xscale.S
deleted file mode 100644
index bb27731..0000000
--- a/arch/arm/mm/copypage-xscale.S
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- *  linux/arch/arm/lib/copypage-xscale.S
- *
- *  Copyright (C) 2001 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.
- */
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <asm/constants.h>
-
-/*
- * General note:
- *  We don't really want write-allocate cache behaviour for these functions
- *  since that will just eat through 8K of the cache.
- */
-
-	.text
-	.align	5
-/*
- * XScale optimised copy_user_page
- *  r0 = destination
- *  r1 = source
- *  r2 = virtual user address of ultimate destination page
- *
- * The source page may have some clean entries in the cache already, but we
- * can safely ignore them - break_cow() will flush them out of the cache
- * if we eventually end up using our copied page.
- *
- * What we could do is use the mini-cache to buffer reads from the source
- * page.  We rely on the mini-cache being smaller than one page, so we'll
- * cycle through the complete cache anyway.
- */
-ENTRY(xscale_mc_copy_user_page)
-	stmfd	sp!, {r4, r5, lr}
-	mov	r5, r0
-	mov	r0, r1
-	bl	map_page_minicache
-	mov	r1, r5
-	mov	lr, #PAGE_SZ/64-1
-
-	/*
-	 * Strangely enough, best performance is achieved
-	 * when prefetching destination as well.  (NP)
-	 */
-	pld	[r0, #0]
-	pld	[r0, #32]
-	pld	[r1, #0]
-	pld	[r1, #32]
-
-1:	pld	[r0, #64]
-	pld	[r0, #96]
-	pld	[r1, #64]
-	pld	[r1, #96]
-
-2:	ldrd	r2, [r0], #8
-	ldrd	r4, [r0], #8
-	mov	ip, r1
-	strd	r2, [r1], #8
-	ldrd	r2, [r0], #8
-	strd	r4, [r1], #8
-	ldrd	r4, [r0], #8
-	strd	r2, [r1], #8
-	strd	r4, [r1], #8
-	mcr	p15, 0, ip, c7, c10, 1		@ clean D line
-	ldrd	r2, [r0], #8
-	mcr	p15, 0, ip, c7, c6, 1		@ invalidate D line
-	ldrd	r4, [r0], #8
-	mov	ip, r1
-	strd	r2, [r1], #8
-	ldrd	r2, [r0], #8
-	strd	r4, [r1], #8
-	ldrd	r4, [r0], #8
-	strd	r2, [r1], #8
-	strd	r4, [r1], #8
-	mcr	p15, 0, ip, c7, c10, 1		@ clean D line
-	subs	lr, lr, #1
-	mcr	p15, 0, ip, c7, c6, 1		@ invalidate D line
-	bgt	1b
-	beq	2b
-
-	ldmfd	sp!, {r4, r5, pc}
-
-	.align	5
-/*
- * XScale optimised clear_user_page
- *  r0 = destination
- *  r1 = virtual user address of ultimate destination page
- */
-ENTRY(xscale_mc_clear_user_page)
-	mov	r1, #PAGE_SZ/32
-	mov	r2, #0
-	mov	r3, #0
-1:	mov	ip, r0
-	strd	r2, [r0], #8
-	strd	r2, [r0], #8
-	strd	r2, [r0], #8
-	strd	r2, [r0], #8
-	mcr	p15, 0, ip, c7, c10, 1		@ clean D line
-	subs	r1, r1, #1
-	mcr	p15, 0, ip, c7, c6, 1		@ invalidate D line
-	bne	1b
-	mov	pc, lr
-
-	__INITDATA
-
-	.type	xscale_mc_user_fns, #object
-ENTRY(xscale_mc_user_fns)
-	.long	xscale_mc_clear_user_page
-	.long	xscale_mc_copy_user_page
-	.size	xscale_mc_user_fns, . - xscale_mc_user_fns
diff --git a/arch/arm/mm/copypage-xscale.c b/arch/arm/mm/copypage-xscale.c
new file mode 100644
index 0000000..42a6ee2
--- /dev/null
+++ b/arch/arm/mm/copypage-xscale.c
@@ -0,0 +1,131 @@
+/*
+ *  linux/arch/arm/lib/copypage-xscale.S
+ *
+ *  Copyright (C) 1995-2005 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.
+ *
+ * This handles the mini data cache, as found on SA11x0 and XScale
+ * processors.  When we copy a user page page, we map it in such a way
+ * that accesses to this page will not touch the main data cache, but
+ * will be cached in the mini data cache.  This prevents us thrashing
+ * the main data cache on page faults.
+ */
+#include <linux/init.h>
+#include <linux/mm.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+
+/*
+ * 0xffff8000 to 0xffffffff is reserved for any ARM architecture
+ * specific hacks for copying pages efficiently.
+ */
+#define COPYPAGE_MINICACHE	0xffff8000
+
+#define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
+				  L_PTE_CACHEABLE)
+
+#define TOP_PTE(x)	pte_offset_kernel(top_pmd, x)
+
+static DEFINE_SPINLOCK(minicache_lock);
+
+/*
+ * XScale mini-dcache optimised copy_user_page
+ *
+ * We flush the destination cache lines just before we write the data into the
+ * corresponding address.  Since the Dcache is read-allocate, this removes the
+ * Dcache aliasing issue.  The writes will be forwarded to the write buffer,
+ * and merged as appropriate.
+ */
+static void __attribute__((naked))
+mc_copy_user_page(void *from, void *to)
+{
+	/*
+	 * Strangely enough, best performance is achieved
+	 * when prefetching destination as well.  (NP)
+	 */
+	asm volatile(
+	"stmfd	sp!, {r4, r5, lr}		\n\
+	mov	lr, %2				\n\
+	pld	[r0, #0]			\n\
+	pld	[r0, #32]			\n\
+	pld	[r1, #0]			\n\
+	pld	[r1, #32]			\n\
+1:	pld	[r0, #64]			\n\
+	pld	[r0, #96]			\n\
+	pld	[r1, #64]			\n\
+	pld	[r1, #96]			\n\
+2:	ldrd	r2, [r0], #8			\n\
+	ldrd	r4, [r0], #8			\n\
+	mov	ip, r1				\n\
+	strd	r2, [r1], #8			\n\
+	ldrd	r2, [r0], #8			\n\
+	strd	r4, [r1], #8			\n\
+	ldrd	r4, [r0], #8			\n\
+	strd	r2, [r1], #8			\n\
+	strd	r4, [r1], #8			\n\
+	mcr	p15, 0, ip, c7, c10, 1		@ clean D line\n\
+	ldrd	r2, [r0], #8			\n\
+	mcr	p15, 0, ip, c7, c6, 1		@ invalidate D line\n\
+	ldrd	r4, [r0], #8			\n\
+	mov	ip, r1				\n\
+	strd	r2, [r1], #8			\n\
+	ldrd	r2, [r0], #8			\n\
+	strd	r4, [r1], #8			\n\
+	ldrd	r4, [r0], #8			\n\
+	strd	r2, [r1], #8			\n\
+	strd	r4, [r1], #8			\n\
+	mcr	p15, 0, ip, c7, c10, 1		@ clean D line\n\
+	subs	lr, lr, #1			\n\
+	mcr	p15, 0, ip, c7, c6, 1		@ invalidate D line\n\
+	bgt	1b				\n\
+	beq	2b				\n\
+	ldmfd	sp!, {r4, r5, pc}		"
+	:
+	: "r" (from), "r" (to), "I" (PAGE_SIZE / 64 - 1));
+}
+
+void xscale_mc_copy_user_page(void *kto, const void *kfrom, unsigned long vaddr)
+{
+	spin_lock(&minicache_lock);
+
+	set_pte(TOP_PTE(COPYPAGE_MINICACHE), pfn_pte(__pa(kfrom) >> PAGE_SHIFT, minicache_pgprot));
+	flush_tlb_kernel_page(COPYPAGE_MINICACHE);
+
+	mc_copy_user_page((void *)COPYPAGE_MINICACHE, kto);
+
+	spin_unlock(&minicache_lock);
+}
+
+/*
+ * XScale optimised clear_user_page
+ */
+void __attribute__((naked))
+xscale_mc_clear_user_page(void *kaddr, unsigned long vaddr)
+{
+	asm volatile(
+	"mov	r1, %0				\n\
+	mov	r2, #0				\n\
+	mov	r3, #0				\n\
+1:	mov	ip, r0				\n\
+	strd	r2, [r0], #8			\n\
+	strd	r2, [r0], #8			\n\
+	strd	r2, [r0], #8			\n\
+	strd	r2, [r0], #8			\n\
+	mcr	p15, 0, ip, c7, c10, 1		@ clean D line\n\
+	subs	r1, r1, #1			\n\
+	mcr	p15, 0, ip, c7, c6, 1		@ invalidate D line\n\
+	bne	1b				\n\
+	mov	pc, lr"
+	:
+	: "I" (PAGE_SIZE / 32));
+}
+
+struct cpu_user_fns xscale_mc_user_fns __initdata = {
+	.cpu_clear_user_page	= xscale_mc_clear_user_page, 
+	.cpu_copy_user_page	= xscale_mc_copy_user_page,
+};
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
index 01967dd..be4ab3d 100644
--- a/arch/arm/mm/fault-armv.c
+++ b/arch/arm/mm/fault-armv.c
@@ -77,9 +77,8 @@
 }
 
 static void
-make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, int dirty)
+make_coherent(struct address_space *mapping, struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
 {
-	struct address_space *mapping = page_mapping(page);
 	struct mm_struct *mm = vma->vm_mm;
 	struct vm_area_struct *mpnt;
 	struct prio_tree_iter iter;
@@ -87,9 +86,6 @@
 	pgoff_t pgoff;
 	int aliases = 0;
 
-	if (!mapping)
-		return;
-
 	pgoff = vma->vm_pgoff + ((addr - vma->vm_start) >> PAGE_SHIFT);
 
 	/*
@@ -115,9 +111,11 @@
 	if (aliases)
 		adjust_pte(vma, addr);
 	else
-		flush_cache_page(vma, addr, page_to_pfn(page));
+		flush_cache_page(vma, addr, pfn);
 }
 
+void __flush_dcache_page(struct address_space *mapping, struct page *page);
+
 /*
  * Take care of architecture specific things when placing a new PTE into
  * a page table, or changing an existing PTE.  Basically, there are two
@@ -134,29 +132,22 @@
 void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
 {
 	unsigned long pfn = pte_pfn(pte);
+	struct address_space *mapping;
 	struct page *page;
 
 	if (!pfn_valid(pfn))
 		return;
+
 	page = pfn_to_page(pfn);
-	if (page_mapping(page)) {
+	mapping = page_mapping(page);
+	if (mapping) {
 		int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
 
-		if (dirty) {
-			/*
-			 * This is our first userspace mapping of this page.
-			 * Ensure that the physical page is coherent with
-			 * the kernel mapping.
-			 *
-			 * FIXME: only need to do this on VIVT and aliasing
-			 *        VIPT cache architectures.  We can do that
-			 *	  by choosing whether to set this bit...
-			 */
-			__cpuc_flush_dcache_page(page_address(page));
-		}
+		if (dirty)
+			__flush_dcache_page(mapping, page);
 
 		if (cache_is_vivt())
-			make_coherent(vma, addr, page, dirty);
+			make_coherent(mapping, vma, addr, pfn);
 	}
 }
 
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index 4085ed9..191788f 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -37,13 +37,8 @@
 #define flush_pfn_alias(pfn,vaddr)	do { } while (0)
 #endif
 
-static void __flush_dcache_page(struct address_space *mapping, struct page *page)
+void __flush_dcache_page(struct address_space *mapping, struct page *page)
 {
-	struct mm_struct *mm = current->active_mm;
-	struct vm_area_struct *mpnt;
-	struct prio_tree_iter iter;
-	pgoff_t pgoff;
-
 	/*
 	 * Writeback any data associated with the kernel mapping of this
 	 * page.  This ensures that data in the physical page is mutually
@@ -52,24 +47,21 @@
 	__cpuc_flush_dcache_page(page_address(page));
 
 	/*
-	 * If there's no mapping pointer here, then this page isn't
-	 * visible to userspace yet, so there are no cache lines
-	 * associated with any other aliases.
-	 */
-	if (!mapping)
-		return;
-
-	/*
-	 * This is a page cache page.  If we have a VIPT cache, we
-	 * only need to do one flush - which would be at the relevant
+	 * If this is a page cache page, and we have an aliasing VIPT cache,
+	 * we only need to do one flush - which would be at the relevant
 	 * userspace colour, which is congruent with page->index.
 	 */
-	if (cache_is_vipt()) {
-		if (cache_is_vipt_aliasing())
-			flush_pfn_alias(page_to_pfn(page),
-					page->index << PAGE_CACHE_SHIFT);
-		return;
-	}
+	if (mapping && cache_is_vipt_aliasing())
+		flush_pfn_alias(page_to_pfn(page),
+				page->index << PAGE_CACHE_SHIFT);
+}
+
+static void __flush_dcache_aliases(struct address_space *mapping, struct page *page)
+{
+	struct mm_struct *mm = current->active_mm;
+	struct vm_area_struct *mpnt;
+	struct prio_tree_iter iter;
+	pgoff_t pgoff;
 
 	/*
 	 * There are possible user space mappings of this page:
@@ -116,12 +108,12 @@
 {
 	struct address_space *mapping = page_mapping(page);
 
-	if (cache_is_vipt_nonaliasing())
-		return;
-
 	if (mapping && !mapping_mapped(mapping))
 		set_bit(PG_dcache_dirty, &page->flags);
-	else
+	else {
 		__flush_dcache_page(mapping, page);
+		if (mapping && cache_is_vivt())
+			__flush_dcache_aliases(mapping, page);
+	}
 }
 EXPORT_SYMBOL(flush_dcache_page);
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 72a2b8c..c08710b 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -93,14 +93,7 @@
 };
 
 #define O_PFN_DOWN(x)	((x) >> PAGE_SHIFT)
-#define V_PFN_DOWN(x)	O_PFN_DOWN(__pa(x))
-
 #define O_PFN_UP(x)	(PAGE_ALIGN(x) >> PAGE_SHIFT)
-#define V_PFN_UP(x)	O_PFN_UP(__pa(x))
-
-#define PFN_SIZE(x)	((x) >> PAGE_SHIFT)
-#define PFN_RANGE(s,e)	PFN_SIZE(PAGE_ALIGN((unsigned long)(e)) - \
-				(((unsigned long)(s)) & PAGE_MASK))
 
 /*
  * FIXME: We really want to avoid allocating the bootmap bitmap
@@ -113,7 +106,7 @@
 {
 	unsigned int start_pfn, bank, bootmap_pfn;
 
-	start_pfn   = V_PFN_UP(&_end);
+	start_pfn   = O_PFN_UP(__pa(&_end));
 	bootmap_pfn = 0;
 
 	for (bank = 0; bank < mi->nr_banks; bank ++) {
@@ -122,9 +115,9 @@
 		if (mi->bank[bank].node != node)
 			continue;
 
-		start = O_PFN_UP(mi->bank[bank].start);
-		end   = O_PFN_DOWN(mi->bank[bank].size +
-				   mi->bank[bank].start);
+		start = mi->bank[bank].start >> PAGE_SHIFT;
+		end   = (mi->bank[bank].size +
+			 mi->bank[bank].start) >> PAGE_SHIFT;
 
 		if (end < start_pfn)
 			continue;
@@ -191,8 +184,8 @@
 		/*
 		 * Get the start and end pfns for this bank
 		 */
-		start = O_PFN_UP(mi->bank[i].start);
-		end   = O_PFN_DOWN(mi->bank[i].start + mi->bank[i].size);
+		start = mi->bank[i].start >> PAGE_SHIFT;
+		end   = (mi->bank[i].start + mi->bank[i].size) >> PAGE_SHIFT;
 
 		if (np[node].start > start)
 			np[node].start = start;
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 00bb8fd..7110e54 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -170,3 +170,50 @@
 	vfree((void *) (PAGE_MASK & (unsigned long) addr));
 }
 EXPORT_SYMBOL(__iounmap);
+
+#ifdef __io
+void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+	return __io(port);
+}
+EXPORT_SYMBOL(ioport_map);
+
+void ioport_unmap(void __iomem *addr)
+{
+}
+EXPORT_SYMBOL(ioport_unmap);
+#endif
+
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#include <linux/ioport.h>
+
+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);
+	}
+	return NULL;
+}
+EXPORT_SYMBOL(pci_iomap);
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+	if ((unsigned long)addr >= VMALLOC_START &&
+	    (unsigned long)addr < VMALLOC_END)
+		iounmap(addr);
+}
+EXPORT_SYMBOL(pci_iounmap);
+#endif
diff --git a/arch/arm/mm/minicache.c b/arch/arm/mm/minicache.c
deleted file mode 100644
index dedf2ab..0000000
--- a/arch/arm/mm/minicache.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- *  linux/arch/arm/mm/minicache.c
- *
- *  Copyright (C) 2001 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.
- *
- * This handles the mini data cache, as found on SA11x0 and XScale
- * processors.  When we copy a user page page, we map it in such a way
- * that accesses to this page will not touch the main data cache, but
- * will be cached in the mini data cache.  This prevents us thrashing
- * the main data cache on page faults.
- */
-#include <linux/init.h>
-#include <linux/mm.h>
-
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/tlbflush.h>
-
-/*
- * 0xffff8000 to 0xffffffff is reserved for any ARM architecture
- * specific hacks for copying pages efficiently.
- */
-#define minicache_address (0xffff8000)
-#define minicache_pgprot __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | \
-				  L_PTE_CACHEABLE)
-
-static pte_t *minicache_pte;
-
-/*
- * Note that this is intended to be called only from the copy_user_page
- * asm code; anything else will require special locking to prevent the
- * mini-cache space being re-used.  (Note: probably preempt unsafe).
- *
- * We rely on the fact that the minicache is 2K, and we'll be pushing
- * 4K of data through it, so we don't actually have to specifically
- * flush the minicache when we change the mapping.
- *
- * Note also: assert(PAGE_OFFSET <= virt < high_memory).
- * Unsafe: preempt, kmap.
- */
-unsigned long map_page_minicache(unsigned long virt)
-{
-	set_pte(minicache_pte, pfn_pte(__pa(virt) >> PAGE_SHIFT, minicache_pgprot));
-	flush_tlb_kernel_page(minicache_address);
-
-	return minicache_address;
-}
-
-static int __init minicache_init(void)
-{
-	pgd_t *pgd;
-	pmd_t *pmd;
-
-	spin_lock(&init_mm.page_table_lock);
-
-	pgd = pgd_offset_k(minicache_address);
-	pmd = pmd_alloc(&init_mm, pgd, minicache_address);
-	if (!pmd)
-		BUG();
-	minicache_pte = pte_alloc_kernel(&init_mm, pmd, minicache_address);
-	if (!minicache_pte)
-		BUG();
-
-	spin_unlock(&init_mm.page_table_lock);
-
-	return 0;
-}
-
-core_initcall(minicache_init);
diff --git a/arch/arm/mm/mmap.c b/arch/arm/mm/mmap.c
index 32c4b0e..3de7f84 100644
--- a/arch/arm/mm/mmap.c
+++ b/arch/arm/mm/mmap.c
@@ -73,7 +73,12 @@
 		    (!vma || addr + len <= vma->vm_start))
 			return addr;
 	}
-	start_addr = addr = mm->free_area_cache;
+	if (len > mm->cached_hole_size) {
+	        start_addr = addr = mm->free_area_cache;
+	} else {
+	        start_addr = addr = TASK_UNMAPPED_BASE;
+	        mm->cached_hole_size = 0;
+	}
 
 full_search:
 	if (do_align)
@@ -90,6 +95,7 @@
 			 */
 			if (start_addr != TASK_UNMAPPED_BASE) {
 				start_addr = addr = TASK_UNMAPPED_BASE;
+				mm->cached_hole_size = 0;
 				goto full_search;
 			}
 			return -ENOMEM;
@@ -101,6 +107,8 @@
 			mm->free_area_cache = addr + len;
 			return addr;
 		}
+		if (addr + mm->cached_hole_size < vma->vm_start)
+		        mm->cached_hole_size = vma->vm_start - addr;
 		addr = vma->vm_end;
 		if (do_align)
 			addr = COLOUR_ALIGN(addr, pgoff);
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index 0aa73d4..e3d8510 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -132,8 +132,8 @@
  *	  100x   1   0   1	r/o	no acc
  *	  10x0   1   0   1	r/o	no acc
  *	  1011   0   0   1	r/w	no acc
- *	  110x   1   1   0	r/o	r/o
- *	  11x0   1   1   0	r/o	r/o
+ *	  110x   0   1   0	r/w	r/o
+ *	  11x0   0   1   0	r/w	r/o
  *	  1111   0   1   1	r/w	r/w
  */
 ENTRY(cpu_v6_set_pte)
@@ -150,7 +150,7 @@
 	tst	r1, #L_PTE_USER
 	orrne	r2, r2, #AP1 | nG
 	tstne	r2, #APX
-	eorne	r2, r2, #AP0
+	bicne	r2, r2, #APX | AP0
 
 	tst	r1, #L_PTE_YOUNG
 	biceq	r2, r2, #APX | AP1 | AP0
diff --git a/arch/arm/nwfpe/softfloat-macros b/arch/arm/nwfpe/softfloat-macros
index 5469989..5a060f9 100644
--- a/arch/arm/nwfpe/softfloat-macros
+++ b/arch/arm/nwfpe/softfloat-macros
@@ -563,8 +563,14 @@
     bits64 rem0, rem1, term0, term1;
     bits64 z;
     if ( b <= a0 ) return LIT64( 0xFFFFFFFFFFFFFFFF );
-    b0 = b>>32;
-    z = ( b0<<32 <= a0 ) ? LIT64( 0xFFFFFFFF00000000 ) : ( a0 / b0 )<<32;
+    b0 = b>>32;  /* hence b0 is 32 bits wide now */
+    if ( b0<<32 <= a0 ) {
+        z = LIT64( 0xFFFFFFFF00000000 );
+    }  else {
+        z = a0;
+        do_div( z, b0 );
+        z <<= 32;
+    }
     mul64To128( b, z, &term0, &term1 );
     sub128( a0, a1, term0, term1, &rem0, &rem1 );
     while ( ( (sbits64) rem0 ) < 0 ) {
@@ -573,7 +579,12 @@
         add128( rem0, rem1, b0, b1, &rem0, &rem1 );
     }
     rem0 = ( rem0<<32 ) | ( rem1>>32 );
-    z |= ( b0<<32 <= rem0 ) ? 0xFFFFFFFF : rem0 / b0;
+    if ( b0<<32 <= rem0 ) {
+        z |= 0xFFFFFFFF;
+    } else {
+        do_div( rem0, b0 );
+        z |= rem0;
+    }
     return z;
 
 }
@@ -601,6 +612,7 @@
     };
     int8 index;
     bits32 z;
+    bits64 A;
 
     index = ( a>>27 ) & 15;
     if ( aExp & 1 ) {
@@ -614,7 +626,9 @@
         z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 );
         if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 );
     }
-    return ( (bits32) ( ( ( (bits64) a )<<31 ) / z ) ) + ( z>>1 );
+    A = ( (bits64) a )<<31;
+    do_div( A, z );
+    return ( (bits32) A ) + ( z>>1 );
 
 }
 
diff --git a/arch/arm/nwfpe/softfloat.c b/arch/arm/nwfpe/softfloat.c
index 9d743ae..e038dd3 100644
--- a/arch/arm/nwfpe/softfloat.c
+++ b/arch/arm/nwfpe/softfloat.c
@@ -28,6 +28,8 @@
 ===============================================================================
 */
 
+#include <asm/div64.h>
+
 #include "fpa11.h"
 //#include "milieu.h"
 //#include "softfloat.h"
@@ -1331,7 +1333,11 @@
         aSig >>= 1;
         ++zExp;
     }
-    zSig = ( ( (bits64) aSig )<<32 ) / bSig;
+    {
+        bits64 tmp = ( (bits64) aSig )<<32;
+        do_div( tmp, bSig );
+        zSig = tmp;
+    }
     if ( ( zSig & 0x3F ) == 0 ) {
         zSig |= ( ( (bits64) bSig ) * zSig != ( (bits64) aSig )<<32 );
     }
@@ -1397,7 +1403,9 @@
         q = ( bSig <= aSig );
         if ( q ) aSig -= bSig;
         if ( 0 < expDiff ) {
-            q = ( ( (bits64) aSig )<<32 ) / bSig;
+            bits64 tmp = ( (bits64) aSig )<<32;
+            do_div( tmp, bSig );
+            q = tmp;
             q >>= 32 - expDiff;
             bSig >>= 2;
             aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q;
diff --git a/arch/arm26/Kconfig b/arch/arm26/Kconfig
index 6caed90..dc0c193 100644
--- a/arch/arm26/Kconfig
+++ b/arch/arm26/Kconfig
@@ -179,6 +179,8 @@
 	  time by entering them here. As a minimum, you should specify the
 	  memory size and the root device (e.g., mem=64M root=/dev/nfs).
 
+source "mm/Kconfig"
+
 endmenu
 
 source "drivers/base/Kconfig"
diff --git a/arch/arm26/boot/install.sh b/arch/arm26/boot/install.sh
index c628328..8a8399b 100644
--- a/arch/arm26/boot/install.sh
+++ b/arch/arm26/boot/install.sh
@@ -23,8 +23,8 @@
 
 # User may have a custom install script
 
-if [ -x /sbin/installkernel ]; then
-  exec /sbin/installkernel "$@"
+if [ -x /sbin/${CROSS_COMPILE}installkernel ]; then
+  exec /sbin/${CROSS_COMPILE}installkernel "$@"
 fi
 
 if [ "$2" = "zImage" ]; then
diff --git a/arch/arm26/kernel/ecard.c b/arch/arm26/kernel/ecard.c
index 824c6b5..f2278aa 100644
--- a/arch/arm26/kernel/ecard.c
+++ b/arch/arm26/kernel/ecard.c
@@ -562,31 +562,31 @@
 	}
 }
 
-static ssize_t ecard_show_irq(struct device *dev, char *buf)
+static ssize_t ecard_show_irq(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct expansion_card *ec = ECARD_DEV(dev);
 	return sprintf(buf, "%u\n", ec->irq);
 }
 
-static ssize_t ecard_show_vendor(struct device *dev, char *buf)
+static ssize_t ecard_show_vendor(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct expansion_card *ec = ECARD_DEV(dev);
 	return sprintf(buf, "%u\n", ec->cid.manufacturer);
 }
 
-static ssize_t ecard_show_device(struct device *dev, char *buf)
+static ssize_t ecard_show_device(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct expansion_card *ec = ECARD_DEV(dev);
 	return sprintf(buf, "%u\n", ec->cid.product);
 }
 
-static ssize_t ecard_show_dma(struct device *dev, char *buf)
+static ssize_t ecard_show_dma(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct expansion_card *ec = ECARD_DEV(dev);
 	return sprintf(buf, "%u\n", ec->dma);
 }
 
-static ssize_t ecard_show_resources(struct device *dev, char *buf)
+static ssize_t ecard_show_resources(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct expansion_card *ec = ECARD_DEV(dev);
 	char *str = buf;
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index 4332ca3..f848e37 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -74,6 +74,8 @@
 	  Say Y here if you are building a kernel for a desktop, embedded
 	  or real-time system.  Say N if you are unsure.
 
+source mm/Kconfig
+
 endmenu
 
 menu "Hardware setup"
diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig
index 2b19372..c93f951 100644
--- a/arch/frv/Kconfig
+++ b/arch/frv/Kconfig
@@ -74,6 +74,8 @@
 	  with a lot of RAM, this can be wasteful of precious low memory.
 	  Setting this option will put user-space page tables in high memory.
 
+source "mm/Kconfig"
+
 choice
 	prompt "uClinux kernel load address"
 	depends on !MMU
diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c
index ef6865f..767ebb5 100644
--- a/arch/frv/kernel/setup.c
+++ b/arch/frv/kernel/setup.c
@@ -790,12 +790,10 @@
 #ifndef CONFIG_GDBSTUB_UART0
 	__reg(UART0_BASE + UART_IER * 8) = 0;
 	early_serial_setup(&__frv_uart0);
-//	register_serial(&__frv_uart0);
 #endif
 #ifndef CONFIG_GDBSTUB_UART1
 	__reg(UART1_BASE + UART_IER * 8) = 0;
 	early_serial_setup(&__frv_uart1);
-//	register_serial(&__frv_uart1);
 #endif
 
 #if defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH)
diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c
index d8d8f3d..36a2dff 100644
--- a/arch/frv/kernel/signal.c
+++ b/arch/frv/kernel/signal.c
@@ -536,10 +536,8 @@
 	if (!user_mode(regs))
 		return 1;
 
-	if (current->flags & PF_FREEZE) {
-		refrigerator(0);
+	if (try_to_freeze())
 		goto no_signal;
-	}
 
 	if (!oldset)
 		oldset = &current->blocked;
diff --git a/arch/frv/mm/init.c b/arch/frv/mm/init.c
index 41958f5..7943315 100644
--- a/arch/frv/mm/init.c
+++ b/arch/frv/mm/init.c
@@ -169,7 +169,6 @@
 		struct page *page = &mem_map[pfn];
 
 		ClearPageReserved(page);
-		set_bit(PG_highmem, &page->flags);
 		set_page_count(page, 1);
 		__free_page(page);
 		totalram_pages++;
diff --git a/arch/h8300/Kconfig.cpu b/arch/h8300/Kconfig.cpu
index d9dd62a..a380167 100644
--- a/arch/h8300/Kconfig.cpu
+++ b/arch/h8300/Kconfig.cpu
@@ -180,4 +180,7 @@
 config PREEMPT
 	bool "Preemptible Kernel"
 	default n
+
+source "mm/Kconfig"
+
 endmenu
diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c
index a4799d6..5aab87e 100644
--- a/arch/h8300/kernel/signal.c
+++ b/arch/h8300/kernel/signal.c
@@ -517,10 +517,8 @@
 	if ((regs->ccr & 0x10))
 		return 1;
 
-	if (current->flags & PF_FREEZE) {
-		refrigerator(0);
+	if (try_to_freeze())
 		goto no_signal;
-	}
 
 	current->thread.esp0 = (unsigned long) regs;
 
diff --git a/arch/h8300/platform/h8300h/ptrace_h8300h.c b/arch/h8300/platform/h8300h/ptrace_h8300h.c
index 18e51a7..6ac93c0 100644
--- a/arch/h8300/platform/h8300h/ptrace_h8300h.c
+++ b/arch/h8300/platform/h8300h/ptrace_h8300h.c
@@ -245,12 +245,12 @@
 						addr = h8300_get_reg(child, regno-1+PT_ER1);
 					return (unsigned short *)addr;
 				case relb:
-					if ((inst = 0x55) || isbranch(child,inst & 0x0f))
+					if (inst == 0x55 || isbranch(child,inst & 0x0f))
 						pc = (unsigned short *)((unsigned long)pc +
 								       ((signed char)(*fetch_p)));
 					return pc+1; /* skip myself */
 				case relw:
-					if ((inst = 0x5c) || isbranch(child,(*fetch_p & 0xf0) >> 4))
+					if (inst == 0x5c || isbranch(child,(*fetch_p & 0xf0) >> 4))
 						pc = (unsigned short *)((unsigned long)pc +
 								       ((signed short)(*(pc+1))));
 					return pc+2; /* skip myself */
diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig
index dfd904f..6c02336 100644
--- a/arch/i386/Kconfig
+++ b/arch/i386/Kconfig
@@ -68,7 +68,6 @@
 
 config X86_NUMAQ
 	bool "NUMAQ (IBM/Sequent)"
-	select DISCONTIGMEM
 	select NUMA
 	help
 	  This option is used for getting Linux to run on a (IBM/Sequent) NUMA
@@ -511,28 +510,7 @@
 	  cost of slightly increased overhead in some places. If unsure say
 	  N here.
 
-config PREEMPT
-	bool "Preemptible Kernel"
-	help
-	  This option reduces the latency of the kernel when reacting to
-	  real-time or interactive events by allowing a low priority process to
-	  be preempted even if it is in kernel mode executing a system call.
-	  This allows applications to run more reliably even when the system is
-	  under load.
-
-	  Say Y here if you are building a kernel for a desktop, embedded
-	  or real-time system.  Say N if you are unsure.
-
-config PREEMPT_BKL
-	bool "Preempt The Big Kernel Lock"
-	depends on PREEMPT
-	default y
-	help
-	  This option reduces the latency of the kernel by making the
-	  big kernel lock preemptible.
-
-	  Say Y here if you are building a kernel for a desktop system.
-	  Say N if you are unsure.
+source "kernel/Kconfig.preempt"
 
 config X86_UP_APIC
 	bool "Local APIC support on uniprocessors"
@@ -783,26 +761,49 @@
 comment "NUMA (Summit) requires SMP, 64GB highmem support, ACPI"
 	depends on X86_SUMMIT && (!HIGHMEM64G || !ACPI)
 
-config DISCONTIGMEM
-	bool
-	depends on NUMA
-	default y
-
 config HAVE_ARCH_BOOTMEM_NODE
 	bool
 	depends on NUMA
 	default y
 
-config HAVE_MEMORY_PRESENT
+config ARCH_HAVE_MEMORY_PRESENT
 	bool
 	depends on DISCONTIGMEM
 	default y
 
 config NEED_NODE_MEMMAP_SIZE
 	bool
-	depends on DISCONTIGMEM
+	depends on DISCONTIGMEM || SPARSEMEM
 	default y
 
+config HAVE_ARCH_ALLOC_REMAP
+	bool
+	depends on NUMA
+	default y
+
+config ARCH_DISCONTIGMEM_ENABLE
+	def_bool y
+	depends on NUMA
+
+config ARCH_DISCONTIGMEM_DEFAULT
+	def_bool y
+	depends on NUMA
+
+config ARCH_SPARSEMEM_ENABLE
+	def_bool y
+	depends on NUMA
+
+config ARCH_SELECT_MEMORY_MODEL
+	def_bool y
+	depends on ARCH_SPARSEMEM_ENABLE
+
+source "mm/Kconfig"
+
+config HAVE_ARCH_EARLY_PFN_TO_NID
+	bool
+	default y
+	depends on NUMA
+
 config HIGHPTE
 	bool "Allocate 3rd-level pagetables from highmem"
 	depends on HIGHMEM4G || HIGHMEM64G
@@ -939,6 +940,43 @@
 
 	  If unsure, say Y. Only embedded should say N here.
 
+source kernel/Kconfig.hz
+
+config PHYSICAL_START
+	hex "Physical address where the kernel is loaded" if EMBEDDED
+	default "0x100000"
+	help
+	  This gives the physical address where the kernel is loaded.
+	  Primarily used in the case of kexec on panic where the
+	  fail safe kernel needs to run at a different address than
+	  the panic-ed kernel.
+
+	  Don't change this unless you know what you are doing.
+
+config KEXEC
+	bool "kexec system call (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	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
+	  you can start any kernel with it, not just Linux.
+
+	  The name comes from the similiarity to the exec system call.
+
+	  It is an ongoing process to be certain the hardware in a machine
+	  is properly shutdown, so do not be surprised if this code does not
+	  initially work for you.  It may help to enable device hotplugging
+	  support.  As of this writing the exact hardware interface is
+	  strongly in flux, so no good recommendation can be made.
+
+config CRASH_DUMP
+	bool "kernel crash dumps (EXPERIMENTAL)"
+	depends on EMBEDDED
+	depends on EXPERIMENTAL
+	depends on HIGHMEM
+	help
+	  Generate crash dump after being started by kexec.
 endmenu
 
 
@@ -1226,6 +1264,15 @@
 	  This support is also available as a module.  If compiled as a
 	  module, it will be called scx200.
 
+config HOTPLUG_CPU
+	bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
+	depends on SMP && HOTPLUG && EXPERIMENTAL
+	---help---
+	  Say Y here to experiment with turning CPUs off and on.  CPUs
+	  can be controlled through /sys/devices/system/cpu.
+
+	  Say N.
+
 source "drivers/pcmcia/Kconfig"
 
 source "drivers/pci/hotplug/Kconfig"
diff --git a/arch/i386/Makefile b/arch/i386/Makefile
index 1c36ca3..bf7c9ba 100644
--- a/arch/i386/Makefile
+++ b/arch/i386/Makefile
@@ -17,6 +17,13 @@
 # 20050320  Kianusch Sayah Karadji <kianusch@sk-tech.net>
 #           Added support for GEODE CPU
 
+HAS_BIARCH      := $(call cc-option-yn, -m32)
+ifeq ($(HAS_BIARCH),y)
+AS              := $(AS) --32
+LD              := $(LD) -m elf_i386
+CC              := $(CC) -m32
+endif
+
 LDFLAGS		:= -m elf_i386
 OBJCOPYFLAGS	:= -O binary -R .note -R .comment -S
 LDFLAGS_vmlinux :=
diff --git a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile
index aa7064a..1e71382 100644
--- a/arch/i386/boot/Makefile
+++ b/arch/i386/boot/Makefile
@@ -25,8 +25,8 @@
 
 #RAMDISK := -DRAMDISK=512
 
-targets		:= vmlinux.bin bootsect bootsect.o setup setup.o \
-		   zImage bzImage
+targets		:= vmlinux.bin bootsect bootsect.o \
+		   setup setup.o zImage bzImage
 subdir- 	:= compressed
 
 hostprogs-y	:= tools/build
@@ -48,7 +48,7 @@
 $(obj)/zImage $(obj)/bzImage: $(obj)/bootsect $(obj)/setup \
 			      $(obj)/vmlinux.bin $(obj)/tools/build FORCE
 	$(call if_changed,image)
-	@echo 'Kernel: $@ is ready'
+	@echo 'Kernel: $@ is ready' ' (#'`cat .version`')'
 
 $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE
 	$(call if_changed,objcopy)
diff --git a/arch/i386/boot/compressed/head.S b/arch/i386/boot/compressed/head.S
index c5e80b6..b5893e4 100644
--- a/arch/i386/boot/compressed/head.S
+++ b/arch/i386/boot/compressed/head.S
@@ -25,6 +25,7 @@
 
 #include <linux/linkage.h>
 #include <asm/segment.h>
+#include <asm/page.h>
 
 	.globl startup_32
 	
@@ -74,7 +75,7 @@
 	popl %esi	# discard address
 	popl %esi	# real mode pointer
 	xorl %ebx,%ebx
-	ljmp $(__BOOT_CS), $0x100000
+	ljmp $(__BOOT_CS), $__PHYSICAL_START
 
 /*
  * We come here, if we were loaded high.
@@ -99,7 +100,7 @@
 	popl %ecx	# lcount
 	popl %edx	# high_buffer_start
 	popl %eax	# hcount
-	movl $0x100000,%edi
+	movl $__PHYSICAL_START,%edi
 	cli		# make sure we don't get interrupted
 	ljmp $(__BOOT_CS), $0x1000 # and jump to the move routine
 
@@ -124,5 +125,5 @@
 	movsl
 	movl %ebx,%esi	# Restore setup pointer
 	xorl %ebx,%ebx
-	ljmp $(__BOOT_CS), $0x100000
+	ljmp $(__BOOT_CS), $__PHYSICAL_START
 move_routine_end:
diff --git a/arch/i386/boot/compressed/misc.c b/arch/i386/boot/compressed/misc.c
index cedc55c..82a807f 100644
--- a/arch/i386/boot/compressed/misc.c
+++ b/arch/i386/boot/compressed/misc.c
@@ -13,6 +13,7 @@
 #include <linux/vmalloc.h>
 #include <linux/tty.h>
 #include <asm/io.h>
+#include <asm/page.h>
 
 /*
  * gzip declarations
@@ -308,7 +309,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 *)0x100000; /* Points to 1M */
+	output_data = (char *)__PHYSICAL_START; /* Normally Points to 1M */
 	free_mem_end_ptr = (long)real_mode;
 }
 
@@ -333,8 +334,8 @@
 	low_buffer_size = low_buffer_end - LOW_BUFFER_START;
 	high_loaded = 1;
 	free_mem_end_ptr = (long)high_buffer_start;
-	if ( (0x100000 + low_buffer_size) > ((ulg)high_buffer_start)) {
-		high_buffer_start = (uch *)(0x100000 + low_buffer_size);
+	if ( (__PHYSICAL_START + low_buffer_size) > ((ulg)high_buffer_start)) {
+		high_buffer_start = (uch *)(__PHYSICAL_START + low_buffer_size);
 		mv->hcount = 0; /* say: we need not to move high_buffer */
 	}
 	else mv->hcount = -1;
@@ -353,7 +354,6 @@
 	}
 }
 
-
 asmlinkage int decompress_kernel(struct moveparams *mv, void *rmode)
 {
 	real_mode = rmode;
diff --git a/arch/i386/boot/edd.S b/arch/i386/boot/edd.S
index 027d6b3..d8d69f2 100644
--- a/arch/i386/boot/edd.S
+++ b/arch/i386/boot/edd.S
@@ -6,7 +6,7 @@
  *   projects 1572D, 1484D, 1386D, 1226DT
  * disk signature read by Matt Domsch <Matt_Domsch@dell.com>
  *	and Andrew Wilks <Andrew_Wilks@dell.com> September 2003, June 2004
- * legacy CHS retreival by Patrick J. LoPresti <patl@users.sourceforge.net>
+ * legacy CHS retrieval by Patrick J. LoPresti <patl@users.sourceforge.net>
  *      March 2004
  * Command line option parsing, Matt Domsch, November 2004
  */
diff --git a/arch/i386/boot/install.sh b/arch/i386/boot/install.sh
index 90f2452..f17b40d 100644
--- a/arch/i386/boot/install.sh
+++ b/arch/i386/boot/install.sh
@@ -21,8 +21,8 @@
 
 # User may have a custom install script
 
-if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi
-if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi
+if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi
+if [ -x /sbin/${CROSS_COMPILE}installkernel ]; then exec /sbin/${CROSS_COMPILE}installkernel "$@"; fi
 
 # Default install - same as make zlilo
 
diff --git a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S
index caa1fde..8cb420f 100644
--- a/arch/i386/boot/setup.S
+++ b/arch/i386/boot/setup.S
@@ -33,7 +33,7 @@
  * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999.
  * <stiker@northlink.com>
  *
- * Fix to work around buggy BIOSes which dont use carry bit correctly
+ * Fix to work around buggy BIOSes which don't use carry bit correctly
  * and/or report extended memory in CX/DX for e801h memory size detection 
  * call.  As a result the kernel got wrong figures.  The int15/e801h docs
  * from Ralf Brown interrupt list seem to indicate AX/BX should be used
@@ -357,7 +357,7 @@
 
 meme801:
 	stc					# fix to work around buggy
-	xorw	%cx,%cx				# BIOSes which dont clear/set
+	xorw	%cx,%cx				# BIOSes which don't clear/set
 	xorw	%dx,%dx				# carry on pass/error of
 						# e801h memory size call
 						# or merely pass cx,dx though
@@ -847,7 +847,7 @@
 #
 #	but we yet haven't reloaded the CS register, so the default size 
 #	of the target offset still is 16 bit.
-#       However, using an operand prefix (0x66), the CPU will properly
+#	However, using an operand prefix (0x66), the CPU will properly
 #	take our 48 bit far pointer. (INTeL 80386 Programmer's Reference
 #	Manual, Mixing 16-bit and 32-bit code, page 16-6)
 
diff --git a/arch/i386/boot/tools/build.c b/arch/i386/boot/tools/build.c
index 26509b8..4a17956 100644
--- a/arch/i386/boot/tools/build.c
+++ b/arch/i386/boot/tools/build.c
@@ -1,6 +1,4 @@
 /*
- *  $Id: build.c,v 1.5 1997/05/19 12:29:58 mj Exp $
- *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *  Copyright (C) 1997 Martin Mares
  */
@@ -8,7 +6,8 @@
 /*
  * This file builds a disk-image from three different files:
  *
- * - bootsect: exactly 512 bytes of 8086 machine code, loads the rest
+ * - bootsect: compatibility mbr which prints an error message if
+ *             someone tries to boot the kernel directly.
  * - setup: 8086 machine code, sets up system parm
  * - system: 80386 code for actual system
  *
diff --git a/arch/i386/crypto/aes.c b/arch/i386/crypto/aes.c
index 1019430..88ee85c 100644
--- a/arch/i386/crypto/aes.c
+++ b/arch/i386/crypto/aes.c
@@ -59,7 +59,7 @@
 };
 
 #define WPOLY 0x011b
-#define u32_in(x) le32_to_cpu(*(const u32 *)(x))
+#define u32_in(x) le32_to_cpup((const __le32 *)(x))
 #define bytes2word(b0, b1, b2, b3)  \
 	(((u32)(b3) << 24) | ((u32)(b2) << 16) | ((u32)(b1) << 8) | (b0))
 
diff --git a/arch/i386/defconfig b/arch/i386/defconfig
index 28e6203..ca07b95 100644
--- a/arch/i386/defconfig
+++ b/arch/i386/defconfig
@@ -126,7 +126,6 @@
 #
 CONFIG_PM=y
 CONFIG_SOFTWARE_SUSPEND=y
-# CONFIG_PM_DISK is not set
 
 #
 # ACPI (Advanced Configuration and Power Interface) Support
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile
index 0fbcfe0..4cc83b3 100644
--- a/arch/i386/kernel/Makefile
+++ b/arch/i386/kernel/Makefile
@@ -24,6 +24,7 @@
 obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o nmi.o
 obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o
 obj-$(CONFIG_X86_REBOOTFIXUPS)	+= reboot_fixups.o
+obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o crash.o
 obj-$(CONFIG_X86_NUMAQ)		+= numaq.o
 obj-$(CONFIG_X86_SUMMIT_NUMA)	+= summit.o
 obj-$(CONFIG_KPROBES)		+= kprobes.o
@@ -43,7 +44,7 @@
 # Note: kbuild does not track this dependency due to usage of .incbin
 $(obj)/vsyscall.o: $(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so
 targets += $(foreach F,int80 sysenter,vsyscall-$F.o vsyscall-$F.so)
-targets += vsyscall.lds
+targets += vsyscall-note.o vsyscall.lds
 
 # The DSO images are built using a special linker script.
 quiet_cmd_syscall = SYSCALL $@
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index 848bb97..9f63ae0 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -29,6 +29,7 @@
 #include <linux/efi.h>
 #include <linux/irq.h>
 #include <linux/module.h>
+#include <linux/dmi.h>
 
 #include <asm/pgtable.h>
 #include <asm/io_apic.h>
@@ -815,6 +816,219 @@
 	return;
 }
 
+extern int acpi_force;
+
+#ifdef __i386__
+
+#ifdef	CONFIG_ACPI_PCI
+static int __init disable_acpi_irq(struct dmi_system_id *d)
+{
+	if (!acpi_force) {
+		printk(KERN_NOTICE "%s detected: force use of acpi=noirq\n",
+		       d->ident);
+		acpi_noirq_set();
+	}
+	return 0;
+}
+
+static int __init disable_acpi_pci(struct dmi_system_id *d)
+{
+	if (!acpi_force) {
+		printk(KERN_NOTICE "%s detected: force use of pci=noacpi\n",
+		       d->ident);
+		acpi_disable_pci();
+	}
+	return 0;
+}
+#endif
+
+static int __init dmi_disable_acpi(struct dmi_system_id *d)
+{
+	if (!acpi_force) {
+		printk(KERN_NOTICE "%s detected: acpi off\n",d->ident);
+		disable_acpi();
+	} else {
+		printk(KERN_NOTICE
+		       "Warning: DMI blacklist says broken, but acpi forced\n");
+	}
+	return 0;
+}
+
+/*
+ * Limit ACPI to CPU enumeration for HT
+ */
+static int __init force_acpi_ht(struct dmi_system_id *d)
+{
+	if (!acpi_force) {
+		printk(KERN_NOTICE "%s detected: force use of acpi=ht\n", d->ident);
+		disable_acpi();
+		acpi_ht = 1;
+	} else {
+		printk(KERN_NOTICE
+		       "Warning: acpi=force overrules DMI blacklist: acpi=ht\n");
+	}
+	return 0;
+}
+
+/*
+ * If your system is blacklisted here, but you find that acpi=force
+ * works for you, please contact acpi-devel@sourceforge.net
+ */
+static struct dmi_system_id __initdata acpi_dmi_table[] = {
+	/*
+	 * Boxes that need ACPI disabled
+	 */
+	{
+		.callback = dmi_disable_acpi,
+		.ident = "IBM Thinkpad",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+			DMI_MATCH(DMI_BOARD_NAME, "2629H1G"),
+		},
+	},
+
+	/*
+	 * Boxes that need acpi=ht
+	 */
+	{
+		.callback = force_acpi_ht,
+		.ident = "FSC Primergy T850",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "PRIMERGY T850"),
+		},
+	},
+	{
+		.callback = force_acpi_ht,
+		.ident = "DELL GX240",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Dell Computer Corporation"),
+			DMI_MATCH(DMI_BOARD_NAME, "OptiPlex GX240"),
+		},
+	},
+	{
+		.callback = force_acpi_ht,
+		.ident = "HP VISUALIZE NT Workstation",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP VISUALIZE NT Workstation"),
+		},
+	},
+	{
+		.callback = force_acpi_ht,
+		.ident = "Compaq Workstation W8000",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Compaq"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Workstation W8000"),
+		},
+	},
+	{
+		.callback = force_acpi_ht,
+		.ident = "ASUS P4B266",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "P4B266"),
+		},
+	},
+	{
+		.callback = force_acpi_ht,
+		.ident = "ASUS P2B-DS",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "P2B-DS"),
+		},
+	},
+	{
+		.callback = force_acpi_ht,
+		.ident = "ASUS CUR-DLS",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "CUR-DLS"),
+		},
+	},
+	{
+		.callback = force_acpi_ht,
+		.ident = "ABIT i440BX-W83977",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ABIT <http://www.abit.com>"),
+			DMI_MATCH(DMI_BOARD_NAME, "i440BX-W83977 (BP6)"),
+		},
+	},
+	{
+		.callback = force_acpi_ht,
+		.ident = "IBM Bladecenter",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+			DMI_MATCH(DMI_BOARD_NAME, "IBM eServer BladeCenter HS20"),
+		},
+	},
+	{
+		.callback = force_acpi_ht,
+		.ident = "IBM eServer xSeries 360",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+			DMI_MATCH(DMI_BOARD_NAME, "eServer xSeries 360"),
+		},
+	},
+	{
+		.callback = force_acpi_ht,
+		.ident = "IBM eserver xSeries 330",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+			DMI_MATCH(DMI_BOARD_NAME, "eserver xSeries 330"),
+		},
+	},
+	{
+		.callback = force_acpi_ht,
+		.ident = "IBM eserver xSeries 440",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "IBM"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "eserver xSeries 440"),
+		},
+	},
+
+#ifdef	CONFIG_ACPI_PCI
+	/*
+	 * Boxes that need ACPI PCI IRQ routing disabled
+	 */
+	{
+		.callback = disable_acpi_irq,
+		.ident = "ASUS A7V",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"),
+			DMI_MATCH(DMI_BOARD_NAME, "<A7V>"),
+			/* newer BIOS, Revision 1011, does work */
+			DMI_MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1007"),
+		},
+	},
+
+	/*
+	 * Boxes that need ACPI PCI IRQ routing and PCI scan disabled
+	 */
+	{	/* _BBN 0 bug */
+		.callback = disable_acpi_pci,
+		.ident = "ASUS PR-DLS",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "PR-DLS"),
+			DMI_MATCH(DMI_BIOS_VERSION, "ASUS PR-DLS ACPI BIOS Revision 1010"),
+			DMI_MATCH(DMI_BIOS_DATE, "03/21/2003")
+		},
+	},
+	{
+		.callback = disable_acpi_pci,
+		.ident = "Acer TravelMate 36x Laptop",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ 			DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
+		},
+	},
+#endif
+	{ }
+};
+
+#endif	/* __i386__ */
+
 /*
  * acpi_boot_table_init() and acpi_boot_init()
  *  called from setup_arch(), always.
@@ -843,6 +1057,10 @@
 {
 	int error;
 
+#ifdef __i386__
+	dmi_check_system(acpi_dmi_table);
+#endif
+
 	/*
 	 * If acpi_disabled, bail out
 	 * One exception: acpi=ht continues far enough to enumerate LAPICs
@@ -870,8 +1088,6 @@
 	 */
 	error = acpi_blacklisted();
 	if (error) {
-		extern int acpi_force;
-
 		if (acpi_force) {
 			printk(KERN_WARNING PREFIX "acpi=force override\n");
 		} else {
diff --git a/arch/i386/kernel/acpi/sleep.c b/arch/i386/kernel/acpi/sleep.c
index 28bb051..c1af930 100644
--- a/arch/i386/kernel/acpi/sleep.c
+++ b/arch/i386/kernel/acpi/sleep.c
@@ -7,6 +7,7 @@
 
 #include <linux/acpi.h>
 #include <linux/bootmem.h>
+#include <linux/dmi.h>
 #include <asm/smp.h>
 #include <asm/tlbflush.h>
 
@@ -91,3 +92,29 @@
 
 
 __setup("acpi_sleep=", acpi_sleep_setup);
+
+
+static __init int reset_videomode_after_s3(struct dmi_system_id *d)
+{
+	acpi_video_flags |= 2;
+	return 0;
+}
+
+static __initdata struct dmi_system_id acpisleep_dmi_table[] = {
+	{	/* Reset video mode after returning from ACPI S3 sleep */
+		.callback = reset_videomode_after_s3,
+		.ident = "Toshiba Satellite 4030cdt",
+		.matches = {
+			DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
+		},
+	},
+	{ }
+};
+
+static int __init acpisleep_dmi_init(void)
+{
+	dmi_check_system(acpisleep_dmi_table);
+	return 0;
+}
+
+core_initcall(acpisleep_dmi_init);
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index d509836..93df90b 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -26,6 +26,7 @@
 #include <linux/mc146818rtc.h>
 #include <linux/kernel_stat.h>
 #include <linux/sysdev.h>
+#include <linux/cpu.h>
 
 #include <asm/atomic.h>
 #include <asm/smp.h>
@@ -40,6 +41,11 @@
 #include "io_ports.h"
 
 /*
+ * Knob to control our willingness to enable the local APIC.
+ */
+int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
+
+/*
  * Debug level
  */
 int apic_verbosity;
@@ -205,7 +211,7 @@
 	enable_apic_mode();
 }
 
-void disconnect_bsp_APIC(void)
+void disconnect_bsp_APIC(int virt_wire_setup)
 {
 	if (pic_mode) {
 		/*
@@ -219,6 +225,42 @@
 		outb(0x70, 0x22);
 		outb(0x00, 0x23);
 	}
+	else {
+		/* Go back to Virtual Wire compatibility mode */
+		unsigned long value;
+
+		/* For the spurious interrupt use vector F, and enable it */
+		value = apic_read(APIC_SPIV);
+		value &= ~APIC_VECTOR_MASK;
+		value |= APIC_SPIV_APIC_ENABLED;
+		value |= 0xf;
+		apic_write_around(APIC_SPIV, value);
+
+		if (!virt_wire_setup) {
+			/* For LVT0 make it edge triggered, active high, external and enabled */
+			value = apic_read(APIC_LVT0);
+			value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING |
+				APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
+				APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED );
+			value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
+			value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT);
+			apic_write_around(APIC_LVT0, value);
+		}
+		else {
+			/* Disable LVT0 */
+			apic_write_around(APIC_LVT0, APIC_LVT_MASKED);
+		}
+
+		/* For LVT1 make it edge triggered, active high, nmi and enabled */
+		value = apic_read(APIC_LVT1);
+		value &= ~(
+			APIC_MODE_MASK | APIC_SEND_PENDING |
+			APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
+			APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
+		value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
+		value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI);
+		apic_write_around(APIC_LVT1, value);
+	}
 }
 
 void disable_local_APIC(void)
@@ -363,7 +405,7 @@
 	apic_write_around(APIC_LVT1, value);
 }
 
-void __init setup_local_APIC (void)
+void __devinit setup_local_APIC(void)
 {
 	unsigned long oldvalue, value, ver, maxlvt;
 
@@ -634,7 +676,7 @@
 	.cls	= &lapic_sysclass,
 };
 
-static void __init apic_pm_activate(void)
+static void __devinit apic_pm_activate(void)
 {
 	apic_pm_state.active = 1;
 }
@@ -665,26 +707,6 @@
  * Original code written by Keir Fraser.
  */
 
-/*
- * Knob to control our willingness to enable the local APIC.
- */
-int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
-
-static int __init lapic_disable(char *str)
-{
-	enable_local_apic = -1;
-	clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
-	return 0;
-}
-__setup("nolapic", lapic_disable);
-
-static int __init lapic_enable(char *str)
-{
-	enable_local_apic = 1;
-	return 0;
-}
-__setup("lapic", lapic_enable);
-
 static int __init apic_set_verbosity(char *str)
 {
 	if (strcmp("debug", str) == 0)
@@ -855,7 +877,7 @@
  * but we do not accept timer interrupts yet. We only allow the BP
  * to calibrate.
  */
-static unsigned int __init get_8254_timer_count(void)
+static unsigned int __devinit get_8254_timer_count(void)
 {
 	extern spinlock_t i8253_lock;
 	unsigned long flags;
@@ -874,7 +896,7 @@
 }
 
 /* next tick in 8254 can be caught by catching timer wraparound */
-static void __init wait_8254_wraparound(void)
+static void __devinit wait_8254_wraparound(void)
 {
 	unsigned int curr_count, prev_count;
 
@@ -894,7 +916,7 @@
  * Default initialization for 8254 timers. If we use other timers like HPET,
  * we override this later
  */
-void (*wait_timer_tick)(void) __initdata = wait_8254_wraparound;
+void (*wait_timer_tick)(void) __devinitdata = wait_8254_wraparound;
 
 /*
  * This function sets up the local APIC timer, with a timeout of
@@ -930,7 +952,7 @@
 	apic_write_around(APIC_TMICT, clocks/APIC_DIVISOR);
 }
 
-static void __init setup_APIC_timer(unsigned int clocks)
+static void __devinit setup_APIC_timer(unsigned int clocks)
 {
 	unsigned long flags;
 
@@ -1043,12 +1065,12 @@
 	local_irq_enable();
 }
 
-void __init setup_secondary_APIC_clock(void)
+void __devinit setup_secondary_APIC_clock(void)
 {
 	setup_APIC_timer(calibration_result);
 }
 
-void __init disable_APIC_timer(void)
+void __devinit disable_APIC_timer(void)
 {
 	if (using_apic_timer) {
 		unsigned long v;
@@ -1133,7 +1155,7 @@
 		}
 
 #ifdef CONFIG_SMP
-		update_process_times(user_mode(regs));
+		update_process_times(user_mode_vm(regs));
 #endif
 	}
 
diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c
index 45641a8..d48ce92 100644
--- a/arch/i386/kernel/apm.c
+++ b/arch/i386/kernel/apm.c
@@ -346,10 +346,10 @@
 struct apm_user {
 	int		magic;
 	struct apm_user *	next;
-	int		suser: 1;
-	int		writer: 1;
-	int		reader: 1;
-	int		suspend_wait: 1;
+	unsigned int	suser: 1;
+	unsigned int	writer: 1;
+	unsigned int	reader: 1;
+	unsigned int	suspend_wait: 1;
 	int		suspend_result;
 	int		suspends_pending;
 	int		standbys_pending;
@@ -1222,6 +1222,7 @@
 
 	save_processor_state();
 	err = set_system_power_state(APM_STATE_SUSPEND);
+	ignore_normal_resume = 1;
 	restore_processor_state();
 
 	local_irq_disable();
@@ -1229,7 +1230,6 @@
 	spin_lock(&i8253_lock);
 	reinit_timer();
 	set_time();
-	ignore_normal_resume = 1;
 
 	spin_unlock(&i8253_lock);
 	write_sequnlock(&xtime_lock);
diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c
index d199e52..2203a9d 100644
--- a/arch/i386/kernel/cpu/common.c
+++ b/arch/i386/kernel/cpu/common.c
@@ -24,9 +24,9 @@
 DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
 EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack);
 
-static int cachesize_override __initdata = -1;
-static int disable_x86_fxsr __initdata = 0;
-static int disable_x86_serial_nr __initdata = 1;
+static int cachesize_override __devinitdata = -1;
+static int disable_x86_fxsr __devinitdata = 0;
+static int disable_x86_serial_nr __devinitdata = 1;
 
 struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {};
 
@@ -59,7 +59,7 @@
 }
 __setup("cachesize=", cachesize_setup);
 
-int __init get_model_name(struct cpuinfo_x86 *c)
+int __devinit get_model_name(struct cpuinfo_x86 *c)
 {
 	unsigned int *v;
 	char *p, *q;
@@ -89,7 +89,7 @@
 }
 
 
-void __init display_cacheinfo(struct cpuinfo_x86 *c)
+void __devinit display_cacheinfo(struct cpuinfo_x86 *c)
 {
 	unsigned int n, dummy, ecx, edx, l2size;
 
@@ -130,7 +130,7 @@
 /* in particular, if CPUID levels 0x80000002..4 are supported, this isn't used */
 
 /* Look up CPU names by table lookup. */
-static char __init *table_lookup_model(struct cpuinfo_x86 *c)
+static char __devinit *table_lookup_model(struct cpuinfo_x86 *c)
 {
 	struct cpu_model_info *info;
 
@@ -151,7 +151,7 @@
 }
 
 
-void __init get_cpu_vendor(struct cpuinfo_x86 *c, int early)
+void __devinit get_cpu_vendor(struct cpuinfo_x86 *c, int early)
 {
 	char *v = c->x86_vendor_id;
 	int i;
@@ -202,7 +202,7 @@
 
 
 /* Probe for the CPUID instruction */
-static int __init have_cpuid_p(void)
+static int __devinit have_cpuid_p(void)
 {
 	return flag_is_changeable_p(X86_EFLAGS_ID);
 }
@@ -249,7 +249,7 @@
 #endif
 }
 
-void __init generic_identify(struct cpuinfo_x86 * c)
+void __devinit generic_identify(struct cpuinfo_x86 * c)
 {
 	u32 tfms, xlvl;
 	int junk;
@@ -296,7 +296,7 @@
 	}
 }
 
-static void __init squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
+static void __devinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c)
 {
 	if (cpu_has(c, X86_FEATURE_PN) && disable_x86_serial_nr ) {
 		/* Disable processor serial number */
@@ -324,7 +324,7 @@
 /*
  * This does the hard work of actually picking apart the CPU stuff...
  */
-void __init identify_cpu(struct cpuinfo_x86 *c)
+void __devinit identify_cpu(struct cpuinfo_x86 *c)
 {
 	int i;
 
@@ -432,10 +432,13 @@
 #ifdef CONFIG_X86_MCE
 	mcheck_init(c);
 #endif
+	if (c == &boot_cpu_data)
+		sysenter_setup();
+	enable_sep_cpu();
 }
 
 #ifdef CONFIG_X86_HT
-void __init detect_ht(struct cpuinfo_x86 *c)
+void __devinit detect_ht(struct cpuinfo_x86 *c)
 {
 	u32 	eax, ebx, ecx, edx;
 	int 	index_msb, tmp;
@@ -490,7 +493,7 @@
 }
 #endif
 
-void __init print_cpu_info(struct cpuinfo_x86 *c)
+void __devinit print_cpu_info(struct cpuinfo_x86 *c)
 {
 	char *vendor = NULL;
 
@@ -513,7 +516,7 @@
 		printk("\n");
 }
 
-cpumask_t cpu_initialized __initdata = CPU_MASK_NONE;
+cpumask_t cpu_initialized __devinitdata = CPU_MASK_NONE;
 
 /* This is hacky. :)
  * We're emulating future behavior.
@@ -560,7 +563,7 @@
  * and IDT. We reload them nevertheless, this function acts as a
  * 'CPU state barrier', nothing should get across.
  */
-void __init cpu_init (void)
+void __devinit cpu_init(void)
 {
 	int cpu = smp_processor_id();
 	struct tss_struct * t = &per_cpu(init_tss, cpu);
@@ -635,7 +638,7 @@
 
 	/* Clear all 6 debug registers: */
 
-#define CD(register) __asm__("movl %0,%%db" #register ::"r"(0) );
+#define CD(register) set_debugreg(0, register)
 
 	CD(0); CD(1); CD(2); CD(3); /* no db4 and db5 */; CD(6); CD(7);
 
@@ -648,3 +651,15 @@
 	clear_used_math();
 	mxcsr_feature_mask_init();
 }
+
+#ifdef CONFIG_HOTPLUG_CPU
+void __devinit cpu_uninit(void)
+{
+	int cpu = raw_smp_processor_id();
+	cpu_clear(cpu, cpu_initialized);
+
+	/* lazy TLB state */
+	per_cpu(cpu_tlbstate, cpu).state = 0;
+	per_cpu(cpu_tlbstate, cpu).active_mm = &init_mm;
+}
+#endif
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
index 5c53006..73a5dc5 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c
@@ -648,9 +648,7 @@
 	}
 #endif
 
-	if (powernow_table)
-		kfree(powernow_table);
-
+	kfree(powernow_table);
 	return 0;
 }
 
diff --git a/arch/i386/kernel/cpu/intel.c b/arch/i386/kernel/cpu/intel.c
index 121aa21..96a75d0 100644
--- a/arch/i386/kernel/cpu/intel.c
+++ b/arch/i386/kernel/cpu/intel.c
@@ -28,7 +28,7 @@
 struct movsl_mask movsl_mask;
 #endif
 
-void __init early_intel_workaround(struct cpuinfo_x86 *c)
+void __devinit early_intel_workaround(struct cpuinfo_x86 *c)
 {
 	if (c->x86_vendor != X86_VENDOR_INTEL)
 		return;
@@ -43,7 +43,7 @@
  *	This is called before we do cpu ident work
  */
  
-int __init ppro_with_ram_bug(void)
+int __devinit ppro_with_ram_bug(void)
 {
 	/* Uses data from early_cpu_detect now */
 	if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
@@ -61,7 +61,7 @@
  * P4 Xeon errata 037 workaround.
  * Hardware prefetcher may cause stale data to be loaded into the cache.
  */
-static void __init Intel_errata_workarounds(struct cpuinfo_x86 *c)
+static void __devinit Intel_errata_workarounds(struct cpuinfo_x86 *c)
 {
 	unsigned long lo, hi;
 
@@ -80,7 +80,7 @@
 /*
  * find out the number of processor cores on the die
  */
-static int __init num_cpu_cores(struct cpuinfo_x86 *c)
+static int __devinit num_cpu_cores(struct cpuinfo_x86 *c)
 {
 	unsigned int eax;
 
@@ -98,7 +98,7 @@
 		return 1;
 }
 
-static void __init init_intel(struct cpuinfo_x86 *c)
+static void __devinit init_intel(struct cpuinfo_x86 *c)
 {
 	unsigned int l2 = 0;
 	char *p = NULL;
@@ -204,7 +204,7 @@
 	return size;
 }
 
-static struct cpu_dev intel_cpu_dev __initdata = {
+static struct cpu_dev intel_cpu_dev __devinitdata = {
 	.c_vendor	= "Intel",
 	.c_ident 	= { "GenuineIntel" },
 	.c_models = {
diff --git a/arch/i386/kernel/cpu/intel_cacheinfo.c b/arch/i386/kernel/cpu/intel_cacheinfo.c
index a710dc4..1d768b2 100644
--- a/arch/i386/kernel/cpu/intel_cacheinfo.c
+++ b/arch/i386/kernel/cpu/intel_cacheinfo.c
@@ -28,7 +28,7 @@
 };
 
 /* all the cache descriptor types we care about (no TLB or trace cache entries) */
-static struct _cache_table cache_table[] __initdata =
+static struct _cache_table cache_table[] __devinitdata =
 {
 	{ 0x06, LVL_1_INST, 8 },	/* 4-way set assoc, 32 byte line size */
 	{ 0x08, LVL_1_INST, 16 },	/* 4-way set assoc, 32 byte line size */
@@ -160,7 +160,7 @@
 	return retval;
 }
 
-unsigned int __init init_intel_cacheinfo(struct cpuinfo_x86 *c)
+unsigned int __devinit init_intel_cacheinfo(struct cpuinfo_x86 *c)
 {
 	unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */
 	unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */
diff --git a/arch/i386/kernel/cpu/mcheck/k7.c b/arch/i386/kernel/cpu/mcheck/k7.c
index 8df52e8..c4abe76 100644
--- a/arch/i386/kernel/cpu/mcheck/k7.c
+++ b/arch/i386/kernel/cpu/mcheck/k7.c
@@ -69,7 +69,7 @@
 
 
 /* AMD K7 machine check is Intel like */
-void __init amd_mcheck_init(struct cpuinfo_x86 *c)
+void __devinit amd_mcheck_init(struct cpuinfo_x86 *c)
 {
 	u32 l, h;
 	int i;
diff --git a/arch/i386/kernel/cpu/mcheck/mce.c b/arch/i386/kernel/cpu/mcheck/mce.c
index bf6d1ae..2cf25d2 100644
--- a/arch/i386/kernel/cpu/mcheck/mce.c
+++ b/arch/i386/kernel/cpu/mcheck/mce.c
@@ -16,7 +16,7 @@
 
 #include "mce.h"
 
-int mce_disabled __initdata = 0;
+int mce_disabled __devinitdata = 0;
 int nr_mce_banks;
 
 EXPORT_SYMBOL_GPL(nr_mce_banks);	/* non-fatal.o */
@@ -31,7 +31,7 @@
 void fastcall (*machine_check_vector)(struct pt_regs *, long error_code) = unexpected_machine_check;
 
 /* This has to be run for each processor */
-void __init mcheck_init(struct cpuinfo_x86 *c)
+void __devinit mcheck_init(struct cpuinfo_x86 *c)
 {
 	if (mce_disabled==1)
 		return;
diff --git a/arch/i386/kernel/cpu/mcheck/p4.c b/arch/i386/kernel/cpu/mcheck/p4.c
index 8b16ceb..0abccb6 100644
--- a/arch/i386/kernel/cpu/mcheck/p4.c
+++ b/arch/i386/kernel/cpu/mcheck/p4.c
@@ -78,7 +78,7 @@
 }
 
 /* P4/Xeon Thermal regulation detect and init */
-static void __init intel_init_thermal(struct cpuinfo_x86 *c)
+static void __devinit intel_init_thermal(struct cpuinfo_x86 *c)
 {
 	u32 l, h;
 	unsigned int cpu = smp_processor_id();
@@ -232,7 +232,7 @@
 }
 
 
-void __init intel_p4_mcheck_init(struct cpuinfo_x86 *c)
+void __devinit intel_p4_mcheck_init(struct cpuinfo_x86 *c)
 {
 	u32 l, h;
 	int i;
diff --git a/arch/i386/kernel/cpu/mcheck/p5.c b/arch/i386/kernel/cpu/mcheck/p5.c
index c45a1b4..ec0614c 100644
--- a/arch/i386/kernel/cpu/mcheck/p5.c
+++ b/arch/i386/kernel/cpu/mcheck/p5.c
@@ -29,7 +29,7 @@
 }
 
 /* Set up machine check reporting for processors with Intel style MCE */
-void __init intel_p5_mcheck_init(struct cpuinfo_x86 *c)
+void __devinit intel_p5_mcheck_init(struct cpuinfo_x86 *c)
 {
 	u32 l, h;
 	
diff --git a/arch/i386/kernel/cpu/mcheck/p6.c b/arch/i386/kernel/cpu/mcheck/p6.c
index 46640f8..f01b73f 100644
--- a/arch/i386/kernel/cpu/mcheck/p6.c
+++ b/arch/i386/kernel/cpu/mcheck/p6.c
@@ -80,7 +80,7 @@
 }
 
 /* Set up machine check reporting for processors with Intel style MCE */
-void __init intel_p6_mcheck_init(struct cpuinfo_x86 *c)
+void __devinit intel_p6_mcheck_init(struct cpuinfo_x86 *c)
 {
 	u32 l, h;
 	int i;
diff --git a/arch/i386/kernel/cpu/mcheck/winchip.c b/arch/i386/kernel/cpu/mcheck/winchip.c
index 753fa7a..7bae68f 100644
--- a/arch/i386/kernel/cpu/mcheck/winchip.c
+++ b/arch/i386/kernel/cpu/mcheck/winchip.c
@@ -23,7 +23,7 @@
 }
 
 /* Set up machine check reporting on the Winchip C6 series */
-void __init winchip_mcheck_init(struct cpuinfo_x86 *c)
+void __devinit winchip_mcheck_init(struct cpuinfo_x86 *c)
 {
 	u32 lo, hi;
 	machine_check_vector = winchip_machine_check;
diff --git a/arch/i386/kernel/cpu/mtrr/generic.c b/arch/i386/kernel/cpu/mtrr/generic.c
index f468a97..64d91f7 100644
--- a/arch/i386/kernel/cpu/mtrr/generic.c
+++ b/arch/i386/kernel/cpu/mtrr/generic.c
@@ -70,8 +70,7 @@
 /*  Free resources associated with a struct mtrr_state  */
 void __init finalize_mtrr_state(void)
 {
-	if (mtrr_state.var_ranges)
-		kfree(mtrr_state.var_ranges);
+	kfree(mtrr_state.var_ranges);
 	mtrr_state.var_ranges = NULL;
 }
 
diff --git a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c
index e1c2042..d66b09e 100644
--- a/arch/i386/kernel/cpu/mtrr/main.c
+++ b/arch/i386/kernel/cpu/mtrr/main.c
@@ -375,6 +375,19 @@
 	return error;
 }
 
+static int mtrr_check(unsigned long base, unsigned long size)
+{
+	if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
+		printk(KERN_WARNING
+			"mtrr: size and base must be multiples of 4 kiB\n");
+		printk(KERN_DEBUG
+			"mtrr: size: 0x%lx  base: 0x%lx\n", size, base);
+		dump_stack();
+		return -1;
+	}
+	return 0;
+}
+
 /**
  *	mtrr_add - Add a memory type region
  *	@base: Physical base address of region
@@ -415,11 +428,8 @@
 mtrr_add(unsigned long base, unsigned long size, unsigned int type,
 	 char increment)
 {
-	if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
-		printk(KERN_WARNING "mtrr: size and base must be multiples of 4 kiB\n");
-		printk(KERN_DEBUG "mtrr: size: 0x%lx  base: 0x%lx\n", size, base);
+	if (mtrr_check(base, size))
 		return -EINVAL;
-	}
 	return mtrr_add_page(base >> PAGE_SHIFT, size >> PAGE_SHIFT, type,
 			     increment);
 }
@@ -511,11 +521,8 @@
 int
 mtrr_del(int reg, unsigned long base, unsigned long size)
 {
-	if ((base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1))) {
-		printk(KERN_INFO "mtrr: size and base must be multiples of 4 kiB\n");
-		printk(KERN_DEBUG "mtrr: size: 0x%lx  base: 0x%lx\n", size, base);
+	if (mtrr_check(base, size))
 		return -EINVAL;
-	}
 	return mtrr_del_page(reg, base >> PAGE_SHIFT, size >> PAGE_SHIFT);
 }
 
diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c
index 7323c19..8bd77d9 100644
--- a/arch/i386/kernel/cpu/proc.c
+++ b/arch/i386/kernel/cpu/proc.c
@@ -86,7 +86,7 @@
 		seq_printf(m, "stepping\t: unknown\n");
 
 	if ( cpu_has(c, X86_FEATURE_TSC) ) {
-		seq_printf(m, "cpu MHz\t\t: %lu.%03lu\n",
+		seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
 			cpu_khz / 1000, (cpu_khz % 1000));
 	}
 
diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c
index 2e27563..4647db4 100644
--- a/arch/i386/kernel/cpuid.c
+++ b/arch/i386/kernel/cpuid.c
@@ -45,7 +45,7 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
-static struct class_simple *cpuid_class;
+static struct class *cpuid_class;
 
 #ifdef CONFIG_SMP
 
@@ -158,12 +158,12 @@
 	.open = cpuid_open,
 };
 
-static int cpuid_class_simple_device_add(int i) 
+static int cpuid_class_device_create(int i)
 {
 	int err = 0;
 	struct class_device *class_err;
 
-	class_err = class_simple_device_add(cpuid_class, MKDEV(CPUID_MAJOR, i), NULL, "cpu%d",i);
+	class_err = class_device_create(cpuid_class, MKDEV(CPUID_MAJOR, i), NULL, "cpu%d",i);
 	if (IS_ERR(class_err))
 		err = PTR_ERR(class_err);
 	return err;
@@ -175,10 +175,10 @@
 
 	switch (action) {
 	case CPU_ONLINE:
-		cpuid_class_simple_device_add(cpu);
+		cpuid_class_device_create(cpu);
 		break;
 	case CPU_DEAD:
-		class_simple_device_remove(MKDEV(CPUID_MAJOR, cpu));
+		class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
 		break;
 	}
 	return NOTIFY_OK;
@@ -200,13 +200,13 @@
 		err = -EBUSY;
 		goto out;
 	}
-	cpuid_class = class_simple_create(THIS_MODULE, "cpuid");
+	cpuid_class = class_create(THIS_MODULE, "cpuid");
 	if (IS_ERR(cpuid_class)) {
 		err = PTR_ERR(cpuid_class);
 		goto out_chrdev;
 	}
 	for_each_online_cpu(i) {
-		err = cpuid_class_simple_device_add(i);
+		err = cpuid_class_device_create(i);
 		if (err != 0) 
 			goto out_class;
 	}
@@ -218,9 +218,9 @@
 out_class:
 	i = 0;
 	for_each_online_cpu(i) {
-		class_simple_device_remove(MKDEV(CPUID_MAJOR, i));
+		class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, i));
 	}
-	class_simple_destroy(cpuid_class);
+	class_destroy(cpuid_class);
 out_chrdev:
 	unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");	
 out:
@@ -232,8 +232,8 @@
 	int cpu = 0;
 
 	for_each_online_cpu(cpu)
-		class_simple_device_remove(MKDEV(CPUID_MAJOR, cpu));
-	class_simple_destroy(cpuid_class);
+		class_device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu));
+	class_destroy(cpuid_class);
 	unregister_chrdev(CPUID_MAJOR, "cpu/cpuid");
 	unregister_cpu_notifier(&cpuid_class_cpu_notifier);
 }
diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c
new file mode 100644
index 0000000..e5fab12
--- /dev/null
+++ b/arch/i386/kernel/crash.c
@@ -0,0 +1,223 @@
+/*
+ * Architecture specific (i386) functions for kexec based crash dumps.
+ *
+ * Created by: Hariprasad Nellitheertha (hari@in.ibm.com)
+ *
+ * Copyright (C) IBM Corporation, 2004. All rights reserved.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/irq.h>
+#include <linux/reboot.h>
+#include <linux/kexec.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/elf.h>
+#include <linux/elfcore.h>
+
+#include <asm/processor.h>
+#include <asm/hardirq.h>
+#include <asm/nmi.h>
+#include <asm/hw_irq.h>
+#include <asm/apic.h>
+#include <mach_ipi.h>
+
+
+note_buf_t crash_notes[NR_CPUS];
+/* This keeps a track of which one is crashing cpu. */
+static int crashing_cpu;
+
+static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
+							       size_t data_len)
+{
+	struct elf_note note;
+
+	note.n_namesz = strlen(name) + 1;
+	note.n_descsz = data_len;
+	note.n_type   = type;
+	memcpy(buf, &note, sizeof(note));
+	buf += (sizeof(note) +3)/4;
+	memcpy(buf, name, note.n_namesz);
+	buf += (note.n_namesz + 3)/4;
+	memcpy(buf, data, note.n_descsz);
+	buf += (note.n_descsz + 3)/4;
+
+	return buf;
+}
+
+static void final_note(u32 *buf)
+{
+	struct elf_note note;
+
+	note.n_namesz = 0;
+	note.n_descsz = 0;
+	note.n_type   = 0;
+	memcpy(buf, &note, sizeof(note));
+}
+
+static void crash_save_this_cpu(struct pt_regs *regs, int cpu)
+{
+	struct elf_prstatus prstatus;
+	u32 *buf;
+
+	if ((cpu < 0) || (cpu >= NR_CPUS))
+		return;
+
+	/* Using ELF notes here is opportunistic.
+	 * I need a well defined structure format
+	 * for the data I pass, and I need tags
+	 * on the data to indicate what information I have
+	 * squirrelled away.  ELF notes happen to provide
+	 * all of that that no need to invent something new.
+	 */
+	buf = &crash_notes[cpu][0];
+	memset(&prstatus, 0, sizeof(prstatus));
+	prstatus.pr_pid = current->pid;
+	elf_core_copy_regs(&prstatus.pr_reg, regs);
+	buf = append_elf_note(buf, "CORE", NT_PRSTATUS, &prstatus,
+				sizeof(prstatus));
+	final_note(buf);
+}
+
+static void crash_get_current_regs(struct pt_regs *regs)
+{
+	__asm__ __volatile__("movl %%ebx,%0" : "=m"(regs->ebx));
+	__asm__ __volatile__("movl %%ecx,%0" : "=m"(regs->ecx));
+	__asm__ __volatile__("movl %%edx,%0" : "=m"(regs->edx));
+	__asm__ __volatile__("movl %%esi,%0" : "=m"(regs->esi));
+	__asm__ __volatile__("movl %%edi,%0" : "=m"(regs->edi));
+	__asm__ __volatile__("movl %%ebp,%0" : "=m"(regs->ebp));
+	__asm__ __volatile__("movl %%eax,%0" : "=m"(regs->eax));
+	__asm__ __volatile__("movl %%esp,%0" : "=m"(regs->esp));
+	__asm__ __volatile__("movw %%ss, %%ax;" :"=a"(regs->xss));
+	__asm__ __volatile__("movw %%cs, %%ax;" :"=a"(regs->xcs));
+	__asm__ __volatile__("movw %%ds, %%ax;" :"=a"(regs->xds));
+	__asm__ __volatile__("movw %%es, %%ax;" :"=a"(regs->xes));
+	__asm__ __volatile__("pushfl; popl %0" :"=m"(regs->eflags));
+
+	regs->eip = (unsigned long)current_text_addr();
+}
+
+/* CPU does not save ss and esp on stack if execution is already
+ * running in kernel mode at the time of NMI occurrence. This code
+ * fixes it.
+ */
+static void crash_setup_regs(struct pt_regs *newregs, struct pt_regs *oldregs)
+{
+	memcpy(newregs, oldregs, sizeof(*newregs));
+	newregs->esp = (unsigned long)&(oldregs->esp);
+	__asm__ __volatile__("xorl %eax, %eax;");
+	__asm__ __volatile__ ("movw %%ss, %%ax;" :"=a"(newregs->xss));
+}
+
+/* We may have saved_regs from where the error came from
+ * or it is NULL if via a direct panic().
+ */
+static void crash_save_self(struct pt_regs *saved_regs)
+{
+	struct pt_regs regs;
+	int cpu;
+
+	cpu = smp_processor_id();
+	if (saved_regs)
+		crash_setup_regs(&regs, saved_regs);
+	else
+		crash_get_current_regs(&regs);
+	crash_save_this_cpu(&regs, cpu);
+}
+
+#ifdef CONFIG_SMP
+static atomic_t waiting_for_crash_ipi;
+
+static int crash_nmi_callback(struct pt_regs *regs, int cpu)
+{
+	struct pt_regs fixed_regs;
+
+	/* Don't do anything if this handler is invoked on crashing cpu.
+	 * Otherwise, system will completely hang. Crashing cpu can get
+	 * an NMI if system was initially booted with nmi_watchdog parameter.
+	 */
+	if (cpu == crashing_cpu)
+		return 1;
+	local_irq_disable();
+
+	if (!user_mode(regs)) {
+		crash_setup_regs(&fixed_regs, regs);
+		regs = &fixed_regs;
+	}
+	crash_save_this_cpu(regs, cpu);
+	disable_local_APIC();
+	atomic_dec(&waiting_for_crash_ipi);
+	/* Assume hlt works */
+	__asm__("hlt");
+	for(;;);
+
+	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);
+}
+
+static void nmi_shootdown_cpus(void)
+{
+	unsigned long msecs;
+
+	atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
+	/* Would it be better to replace the trap vector here? */
+	set_nmi_callback(crash_nmi_callback);
+	/* Ensure the new callback function is set before sending
+	 * out the NMI
+	 */
+	wmb();
+
+	smp_send_nmi_allbutself();
+
+	msecs = 1000; /* Wait at most a second for the other cpus to stop */
+	while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
+		mdelay(1);
+		msecs--;
+	}
+
+	/* Leave the nmi callback set */
+	disable_local_APIC();
+}
+#else
+static void nmi_shootdown_cpus(void)
+{
+	/* There are no cpus to shootdown */
+}
+#endif
+
+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.
+	 * The minimum amount of code to allow a kexec'd kernel
+	 * to run successfully needs to happen here.
+	 *
+	 * In practice this means shooting down the other cpus in
+	 * an SMP system.
+	 */
+	/* The kernel is broken so disable interrupts */
+	local_irq_disable();
+
+	/* Make a note of crashing cpu. Will be used in NMI callback.*/
+	crashing_cpu = smp_processor_id();
+	nmi_shootdown_cpus();
+	lapic_shutdown();
+#if defined(CONFIG_X86_IO_APIC)
+	disable_IO_APIC();
+#endif
+	crash_save_self(regs);
+}
diff --git a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c
index 6ed7e28..a3cdf89 100644
--- a/arch/i386/kernel/dmi_scan.c
+++ b/arch/i386/kernel/dmi_scan.c
@@ -1,22 +1,15 @@
 #include <linux/types.h>
-#include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/acpi.h>
-#include <asm/io.h>
-#include <linux/pm.h>
-#include <asm/system.h>
 #include <linux/dmi.h>
 #include <linux/bootmem.h>
 
 
-struct dmi_header
-{
-	u8	type;
-	u8	length;
-	u16	handle;
+struct dmi_header {
+	u8 type;
+	u8 length;
+	u16 handle;
 };
 
 #undef DMI_DEBUG
@@ -29,15 +22,13 @@
 
 static char * __init dmi_string(struct dmi_header *dm, u8 s)
 {
-	u8 *bp=(u8 *)dm;
-	bp+=dm->length;
-	if(!s)
+	u8 *bp = ((u8 *) dm) + dm->length;
+
+	if (!s)
 		return "";
 	s--;
-	while(s>0 && *bp)
-	{
-		bp+=strlen(bp);
-		bp++;
+	while (s > 0 && *bp) {
+		bp += strlen(bp) + 1;
 		s--;
 	}
 	return bp;
@@ -47,16 +38,14 @@
  *	We have to be cautious here. We have seen BIOSes with DMI pointers
  *	pointing to completely the wrong place for example
  */
- 
-static int __init dmi_table(u32 base, int len, int num, void (*decode)(struct dmi_header *))
+static int __init dmi_table(u32 base, int len, int num,
+			    void (*decode)(struct dmi_header *))
 {
-	u8 *buf;
-	struct dmi_header *dm;
-	u8 *data;
-	int i=0;
+	u8 *buf, *data;
+	int i = 0;
 		
 	buf = bt_ioremap(base, len);
-	if(buf==NULL)
+	if (buf == NULL)
 		return -1;
 
 	data = buf;
@@ -65,36 +54,34 @@
  	 *	Stop when we see all the items the table claimed to have
  	 *	OR we run off the end of the table (also happens)
  	 */
- 
-	while(i<num && data-buf+sizeof(struct dmi_header)<=len)
-	{
-		dm=(struct dmi_header *)data;
+	while ((i < num) && (data - buf + sizeof(struct dmi_header)) <= len) {
+		struct dmi_header *dm = (struct dmi_header *)data;
 		/*
 		 *  We want to know the total length (formated area and strings)
 		 *  before decoding to make sure we won't run off the table in
 		 *  dmi_decode or dmi_string
 		 */
-		data+=dm->length;
-		while(data-buf<len-1 && (data[0] || data[1]))
+		data += dm->length;
+		while ((data - buf < len - 1) && (data[0] || data[1]))
 			data++;
-		if(data-buf<len-1)
+		if (data - buf < len - 1)
 			decode(dm);
-		data+=2;
+		data += 2;
 		i++;
 	}
 	bt_iounmap(buf, len);
 	return 0;
 }
 
-
-inline static int __init dmi_checksum(u8 *buf)
+static int __init dmi_checksum(u8 *buf)
 {
-	u8 sum=0;
+	u8 sum = 0;
 	int a;
 	
-	for(a=0; a<15; a++)
-		sum+=buf[a];
-	return (sum==0);
+	for (a = 0; a < 15; a++)
+		sum += buf[a];
+
+	return sum == 0;
 }
 
 static int __init dmi_iterate(void (*decode)(struct dmi_header *))
@@ -110,28 +97,30 @@
 	p = ioremap(0xF0000, 0x10000);
 	if (p == NULL)
 		return -1;
+
 	for (q = p; q < p + 0x10000; q += 16) {
 		memcpy_fromio(buf, q, 15);
-		if(memcmp(buf, "_DMI_", 5)==0 && dmi_checksum(buf))
-		{
-			u16 num=buf[13]<<8|buf[12];
-			u16 len=buf[7]<<8|buf[6];
-			u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
+		if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) {
+			u16 num = (buf[13] << 8) | buf[12];
+			u16 len = (buf[7] << 8) | buf[6];
+			u32 base = (buf[11] << 24) | (buf[10] << 16) |
+				   (buf[9] << 8) | buf[8];
 
 			/*
 			 * DMI version 0.0 means that the real version is taken from
 			 * the SMBIOS version, which we don't know at this point.
 			 */
-			if(buf[14]!=0)
+			if (buf[14] != 0)
 				printk(KERN_INFO "DMI %d.%d present.\n",
-					buf[14]>>4, buf[14]&0x0F);
+					buf[14] >> 4, buf[14] & 0xF);
 			else
 				printk(KERN_INFO "DMI present.\n");
+
 			dmi_printk((KERN_INFO "%d structures occupying %d bytes.\n",
 				num, len));
-			dmi_printk((KERN_INFO "DMI table at 0x%08X.\n",
-				base));
-			if(dmi_table(base,len, num, decode)==0)
+			dmi_printk((KERN_INFO "DMI table at 0x%08X.\n", base));
+
+			if (dmi_table(base,len, num, decode) == 0)
 				return 0;
 		}
 	}
@@ -143,16 +132,17 @@
 /*
  *	Save a DMI string
  */
- 
 static void __init dmi_save_ident(struct dmi_header *dm, int slot, int string)
 {
 	char *d = (char*)dm;
 	char *p = dmi_string(dm, d[string]);
-	if(p==NULL || *p == 0)
+
+	if (p == NULL || *p == 0)
 		return;
 	if (dmi_ident[slot])
 		return;
-	dmi_ident[slot] = alloc_bootmem(strlen(p)+1);
+
+	dmi_ident[slot] = alloc_bootmem(strlen(p) + 1);
 	if(dmi_ident[slot])
 		strcpy(dmi_ident[slot], p);
 	else
@@ -160,281 +150,47 @@
 }
 
 /*
- * Ugly compatibility crap.
- */
-#define dmi_blacklist	dmi_system_id
-#define NO_MATCH	{ DMI_NONE, NULL}
-#define MATCH		DMI_MATCH
-
-/*
- * Toshiba keyboard likes to repeat keys when they are not repeated.
- */
-
-static __init int broken_toshiba_keyboard(struct dmi_blacklist *d)
-{
-	printk(KERN_WARNING "Toshiba with broken keyboard detected. If your keyboard sometimes generates 3 keypresses instead of one, see http://davyd.ucc.asn.au/projects/toshiba/README\n");
-	return 0;
-}
-
-
-#ifdef CONFIG_ACPI_SLEEP
-static __init int reset_videomode_after_s3(struct dmi_blacklist *d)
-{
-	/* See acpi_wakeup.S */
-	extern long acpi_video_flags;
-	acpi_video_flags |= 2;
-	return 0;
-}
-#endif
-
-
-#ifdef	CONFIG_ACPI_BOOT
-extern int acpi_force;
-
-static __init __attribute__((unused)) int dmi_disable_acpi(struct dmi_blacklist *d) 
-{ 
-	if (!acpi_force) { 
-		printk(KERN_NOTICE "%s detected: acpi off\n",d->ident); 
-		disable_acpi();
-	} else { 
-		printk(KERN_NOTICE 
-		       "Warning: DMI blacklist says broken, but acpi forced\n"); 
-	}
-	return 0;
-} 
-
-/*
- * Limit ACPI to CPU enumeration for HT
- */
-static __init __attribute__((unused)) int force_acpi_ht(struct dmi_blacklist *d) 
-{ 
-	if (!acpi_force) { 
-		printk(KERN_NOTICE "%s detected: force use of acpi=ht\n", d->ident); 
-		disable_acpi();
-		acpi_ht = 1; 
-	} else { 
-		printk(KERN_NOTICE 
-		       "Warning: acpi=force overrules DMI blacklist: acpi=ht\n"); 
-	}
-	return 0;
-} 
-#endif
-
-#ifdef	CONFIG_ACPI_PCI
-static __init int disable_acpi_irq(struct dmi_blacklist *d) 
-{
-	if (!acpi_force) {
-		printk(KERN_NOTICE "%s detected: force use of acpi=noirq\n",
-		       d->ident); 	
-		acpi_noirq_set();
-	}
-	return 0;
-}
-static __init int disable_acpi_pci(struct dmi_blacklist *d) 
-{
-	if (!acpi_force) {
-		printk(KERN_NOTICE "%s detected: force use of pci=noacpi\n",
-		       d->ident); 	
-		acpi_disable_pci();
-	}
-	return 0;
-}  
-#endif
-
-/*
- *	Process the DMI blacklists
- */
- 
-
-/*
- *	This will be expanded over time to force things like the APM 
- *	interrupt mask settings according to the laptop
- */
- 
-static __initdata struct dmi_blacklist dmi_blacklist[]={
-
-	{ broken_toshiba_keyboard, "Toshiba Satellite 4030cdt", { /* Keyboard generates spurious repeats */
-			MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
-			NO_MATCH, NO_MATCH, NO_MATCH
-			} },
-#ifdef CONFIG_ACPI_SLEEP
-	{ reset_videomode_after_s3, "Toshiba Satellite 4030cdt", { /* Reset video mode after returning from ACPI S3 sleep */
-			MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),
-			NO_MATCH, NO_MATCH, NO_MATCH
-			} },
-#endif
-
-#ifdef	CONFIG_ACPI_BOOT
-	/*
-	 * If your system is blacklisted here, but you find that acpi=force
-	 * works for you, please contact acpi-devel@sourceforge.net
-	 */
-
-	/*
-	 *	Boxes that need ACPI disabled
-	 */
-
-	{ dmi_disable_acpi, "IBM Thinkpad", {
-			MATCH(DMI_BOARD_VENDOR, "IBM"),
-			MATCH(DMI_BOARD_NAME, "2629H1G"),
-			NO_MATCH, NO_MATCH }},
-
-	/*
-	 *	Boxes that need acpi=ht 
-	 */
-
-	{ force_acpi_ht, "FSC Primergy T850", {
-			MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
-			MATCH(DMI_PRODUCT_NAME, "PRIMERGY T850"),
-			NO_MATCH, NO_MATCH }},
-
-	{ force_acpi_ht, "DELL GX240", {
-			MATCH(DMI_BOARD_VENDOR, "Dell Computer Corporation"),
-			MATCH(DMI_BOARD_NAME, "OptiPlex GX240"),
-			NO_MATCH, NO_MATCH }},
-
-	{ force_acpi_ht, "HP VISUALIZE NT Workstation", {
-			MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
-			MATCH(DMI_PRODUCT_NAME, "HP VISUALIZE NT Workstation"),
-			NO_MATCH, NO_MATCH }},
-
-	{ force_acpi_ht, "Compaq Workstation W8000", {
-			MATCH(DMI_SYS_VENDOR, "Compaq"),
-			MATCH(DMI_PRODUCT_NAME, "Workstation W8000"),
-			NO_MATCH, NO_MATCH }},
-
-	{ force_acpi_ht, "ASUS P4B266", {
-			MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
-			MATCH(DMI_BOARD_NAME, "P4B266"),
-			NO_MATCH, NO_MATCH }},
-
-	{ force_acpi_ht, "ASUS P2B-DS", {
-			MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
-			MATCH(DMI_BOARD_NAME, "P2B-DS"),
-			NO_MATCH, NO_MATCH }},
-
-	{ force_acpi_ht, "ASUS CUR-DLS", {
-			MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
-			MATCH(DMI_BOARD_NAME, "CUR-DLS"),
-			NO_MATCH, NO_MATCH }},
-
-	{ force_acpi_ht, "ABIT i440BX-W83977", {
-			MATCH(DMI_BOARD_VENDOR, "ABIT <http://www.abit.com>"),
-			MATCH(DMI_BOARD_NAME, "i440BX-W83977 (BP6)"),
-			NO_MATCH, NO_MATCH }},
-
-	{ force_acpi_ht, "IBM Bladecenter", {
-			MATCH(DMI_BOARD_VENDOR, "IBM"),
-			MATCH(DMI_BOARD_NAME, "IBM eServer BladeCenter HS20"),
-			NO_MATCH, NO_MATCH }},
-
-	{ force_acpi_ht, "IBM eServer xSeries 360", {
-			MATCH(DMI_BOARD_VENDOR, "IBM"),
-			MATCH(DMI_BOARD_NAME, "eServer xSeries 360"),
-			NO_MATCH, NO_MATCH }},
-
-	{ force_acpi_ht, "IBM eserver xSeries 330", {
-			MATCH(DMI_BOARD_VENDOR, "IBM"),
-			MATCH(DMI_BOARD_NAME, "eserver xSeries 330"),
-			NO_MATCH, NO_MATCH }},
-
-	{ force_acpi_ht, "IBM eserver xSeries 440", {
-			MATCH(DMI_BOARD_VENDOR, "IBM"),
-			MATCH(DMI_PRODUCT_NAME, "eserver xSeries 440"),
-			NO_MATCH, NO_MATCH }},
-
-#endif	// CONFIG_ACPI_BOOT
-
-#ifdef	CONFIG_ACPI_PCI
-	/*
-	 *	Boxes that need ACPI PCI IRQ routing disabled
-	 */
-
-	{ disable_acpi_irq, "ASUS A7V", {
-			MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC"),
-			MATCH(DMI_BOARD_NAME, "<A7V>"),
-			/* newer BIOS, Revision 1011, does work */
-			MATCH(DMI_BIOS_VERSION, "ASUS A7V ACPI BIOS Revision 1007"),
-			NO_MATCH }},
-
-	/*
-	 *	Boxes that need ACPI PCI IRQ routing and PCI scan disabled
-	 */
-	{ disable_acpi_pci, "ASUS PR-DLS", {	/* _BBN 0 bug */
-			MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
-			MATCH(DMI_BOARD_NAME, "PR-DLS"),
-			MATCH(DMI_BIOS_VERSION, "ASUS PR-DLS ACPI BIOS Revision 1010"),
-			MATCH(DMI_BIOS_DATE, "03/21/2003") }},
-
- 	{ disable_acpi_pci, "Acer TravelMate 36x Laptop", {
- 			MATCH(DMI_SYS_VENDOR, "Acer"),
- 			MATCH(DMI_PRODUCT_NAME, "TravelMate 360"),
- 			NO_MATCH, NO_MATCH
- 			} },
-
-#endif
-
-	{ NULL, }
-};
-
-/*
  *	Process a DMI table entry. Right now all we care about are the BIOS
  *	and machine entries. For 2.5 we should pull the smbus controller info
  *	out of here.
  */
-
 static void __init dmi_decode(struct dmi_header *dm)
 {
-#ifdef DMI_DEBUG
-	u8 *data = (u8 *)dm;
-#endif
+	u8 *data __attribute__((__unused__)) = (u8 *)dm;
 	
-	switch(dm->type)
-	{
-		case  0:
-			dmi_printk(("BIOS Vendor: %s\n",
-				dmi_string(dm, data[4])));
-			dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
-			dmi_printk(("BIOS Version: %s\n", 
-				dmi_string(dm, data[5])));
-			dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
-			dmi_printk(("BIOS Release: %s\n",
-				dmi_string(dm, data[8])));
-			dmi_save_ident(dm, DMI_BIOS_DATE, 8);
-			break;
-		case 1:
-			dmi_printk(("System Vendor: %s\n",
-				dmi_string(dm, data[4])));
-			dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
-			dmi_printk(("Product Name: %s\n",
-				dmi_string(dm, data[5])));
-			dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
-			dmi_printk(("Version: %s\n",
-				dmi_string(dm, data[6])));
-			dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
-			dmi_printk(("Serial Number: %s\n",
-				dmi_string(dm, data[7])));
-			break;
-		case 2:
-			dmi_printk(("Board Vendor: %s\n",
-				dmi_string(dm, data[4])));
-			dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
-			dmi_printk(("Board Name: %s\n",
-				dmi_string(dm, data[5])));
-			dmi_save_ident(dm, DMI_BOARD_NAME, 5);
-			dmi_printk(("Board Version: %s\n",
-				dmi_string(dm, data[6])));
-			dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
-			break;
+	switch(dm->type) {
+	case  0:
+		dmi_printk(("BIOS Vendor: %s\n", dmi_string(dm, data[4])));
+		dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
+		dmi_printk(("BIOS Version: %s\n", dmi_string(dm, data[5])));
+		dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
+		dmi_printk(("BIOS Release: %s\n", dmi_string(dm, data[8])));
+		dmi_save_ident(dm, DMI_BIOS_DATE, 8);
+		break;
+	case 1:
+		dmi_printk(("System Vendor: %s\n", dmi_string(dm, data[4])));
+		dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
+		dmi_printk(("Product Name: %s\n", dmi_string(dm, data[5])));
+		dmi_save_ident(dm, DMI_PRODUCT_NAME, 5);
+		dmi_printk(("Version: %s\n", dmi_string(dm, data[6])));
+		dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
+		dmi_printk(("Serial Number: %s\n", dmi_string(dm, data[7])));
+		dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7);
+		break;
+	case 2:
+		dmi_printk(("Board Vendor: %s\n", dmi_string(dm, data[4])));
+		dmi_save_ident(dm, DMI_BOARD_VENDOR, 4);
+		dmi_printk(("Board Name: %s\n", dmi_string(dm, data[5])));
+		dmi_save_ident(dm, DMI_BOARD_NAME, 5);
+		dmi_printk(("Board Version: %s\n", dmi_string(dm, data[6])));
+		dmi_save_ident(dm, DMI_BOARD_VERSION, 6);
+		break;
 	}
 }
 
 void __init dmi_scan_machine(void)
 {
-	int err = dmi_iterate(dmi_decode);
-	if(err == 0)
- 		dmi_check_system(dmi_blacklist);
-	else
+	if (dmi_iterate(dmi_decode))
 		printk(KERN_INFO "DMI not present.\n");
 }
 
@@ -470,7 +226,6 @@
 
 	return count;
 }
-
 EXPORT_SYMBOL(dmi_check_system);
 
 /**
@@ -480,8 +235,8 @@
  *	Returns one DMI data value, can be used to perform
  *	complex DMI data checks.
  */
-char * dmi_get_system_info(int field)
+char *dmi_get_system_info(int field)
 {
 	return dmi_ident[field];
 }
-
+EXPORT_SYMBOL(dmi_get_system_info);
diff --git a/arch/i386/kernel/efi.c b/arch/i386/kernel/efi.c
index f732f42..385883e 100644
--- a/arch/i386/kernel/efi.c
+++ b/arch/i386/kernel/efi.c
@@ -30,6 +30,7 @@
 #include <linux/ioport.h>
 #include <linux/module.h>
 #include <linux/efi.h>
+#include <linux/kexec.h>
 
 #include <asm/setup.h>
 #include <asm/io.h>
@@ -598,6 +599,9 @@
 		if (md->type == EFI_CONVENTIONAL_MEMORY) {
 			request_resource(res, code_resource);
 			request_resource(res, data_resource);
+#ifdef CONFIG_KEXEC
+			request_resource(res, &crashk_res);
+#endif
 		}
 	}
 }
diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S
index e966fc8..4477bb1 100644
--- a/arch/i386/kernel/head.S
+++ b/arch/i386/kernel/head.S
@@ -299,7 +299,6 @@
 	movl %eax,%cr0
 
 	call check_x87
-	incb ready
 	lgdt cpu_gdt_descr
 	lidt idt_descr
 	ljmp $(__KERNEL_CS),$1f
@@ -316,8 +315,9 @@
 	lldt %ax
 	cld			# gcc2 wants the direction flag cleared at all times
 #ifdef CONFIG_SMP
-	movb ready, %cl	
-	cmpb $1,%cl
+	movb ready, %cl
+	movb $1, ready
+	cmpb $0,%cl
 	je 1f			# the first CPU calls start_kernel
 				# all other CPUs call initialize_secondary
 	call initialize_secondary
diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
index 903190a..180f070 100644
--- a/arch/i386/kernel/i386_ksyms.c
+++ b/arch/i386/kernel/i386_ksyms.c
@@ -1,97 +1,17 @@
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/smp.h>
-#include <linux/user.h>
-#include <linux/elfcore.h>
-#include <linux/mca.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/tty.h>
-#include <linux/highmem.h>
-#include <linux/time.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/tlbflush.h>
-#include <asm/nmi.h>
-#include <asm/ist.h>
-#include <asm/kdebug.h>
-
-extern void dump_thread(struct pt_regs *, struct user *);
-extern spinlock_t rtc_lock;
 
 /* This is definitely a GPL-only symbol */
 EXPORT_SYMBOL_GPL(cpu_gdt_table);
 
-#if defined(CONFIG_APM_MODULE)
-extern void machine_real_restart(unsigned char *, int);
-EXPORT_SYMBOL(machine_real_restart);
-extern void default_idle(void);
-EXPORT_SYMBOL(default_idle);
-#endif
-
-#ifdef CONFIG_SMP
-extern void FASTCALL( __write_lock_failed(rwlock_t *rw));
-extern void FASTCALL( __read_lock_failed(rwlock_t *rw));
-#endif
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE)
-extern struct drive_info_struct drive_info;
-EXPORT_SYMBOL(drive_info);
-#endif
-
-extern unsigned long cpu_khz;
-extern unsigned long get_cmos_time(void);
-
-/* platform dependent support */
-EXPORT_SYMBOL(boot_cpu_data);
-#ifdef CONFIG_DISCONTIGMEM
-EXPORT_SYMBOL(node_data);
-EXPORT_SYMBOL(physnode_map);
-#endif
-#ifdef CONFIG_X86_NUMAQ
-EXPORT_SYMBOL(xquad_portio);
-#endif
-EXPORT_SYMBOL(dump_thread);
-EXPORT_SYMBOL(dump_fpu);
-EXPORT_SYMBOL_GPL(kernel_fpu_begin);
-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(get_cmos_time);
-EXPORT_SYMBOL(cpu_khz);
-EXPORT_SYMBOL(apm_info);
-
 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_generic);
-/* Delay loops */
-EXPORT_SYMBOL(__ndelay);
-EXPORT_SYMBOL(__udelay);
-EXPORT_SYMBOL(__delay);
-EXPORT_SYMBOL(__const_udelay);
 
 EXPORT_SYMBOL(__get_user_1);
 EXPORT_SYMBOL(__get_user_2);
@@ -105,87 +25,11 @@
 EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strstr);
 
-EXPORT_SYMBOL(strncpy_from_user);
-EXPORT_SYMBOL(__strncpy_from_user);
-EXPORT_SYMBOL(clear_user);
-EXPORT_SYMBOL(__clear_user);
-EXPORT_SYMBOL(__copy_from_user_ll);
-EXPORT_SYMBOL(__copy_to_user_ll);
-EXPORT_SYMBOL(strnlen_user);
-
-EXPORT_SYMBOL(dma_alloc_coherent);
-EXPORT_SYMBOL(dma_free_coherent);
-
-#ifdef CONFIG_PCI
-EXPORT_SYMBOL(pci_mem_start);
-#endif
-
-#ifdef CONFIG_PCI_BIOS
-EXPORT_SYMBOL(pcibios_set_irq_routing);
-EXPORT_SYMBOL(pcibios_get_irq_routing_table);
-#endif
-
-#ifdef CONFIG_X86_USE_3DNOW
-EXPORT_SYMBOL(_mmx_memcpy);
-EXPORT_SYMBOL(mmx_clear_page);
-EXPORT_SYMBOL(mmx_copy_page);
-#endif
-
-#ifdef CONFIG_X86_HT
-EXPORT_SYMBOL(smp_num_siblings);
-EXPORT_SYMBOL(cpu_sibling_map);
-#endif
-
 #ifdef CONFIG_SMP
-EXPORT_SYMBOL(cpu_data);
-EXPORT_SYMBOL(cpu_online_map);
-EXPORT_SYMBOL(cpu_callout_map);
+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);
-
-/* Global SMP stuff */
-EXPORT_SYMBOL(smp_call_function);
-
-/* TLB flushing */
-EXPORT_SYMBOL(flush_tlb_page);
-#endif
-
-#ifdef CONFIG_X86_IO_APIC
-EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
-#endif
-
-#ifdef CONFIG_MCA
-EXPORT_SYMBOL(machine_id);
-#endif
-
-#ifdef CONFIG_VT
-EXPORT_SYMBOL(screen_info);
-#endif
-
-EXPORT_SYMBOL(get_wchan);
-
-EXPORT_SYMBOL(rtc_lock);
-
-EXPORT_SYMBOL_GPL(set_nmi_callback);
-EXPORT_SYMBOL_GPL(unset_nmi_callback);
-
-EXPORT_SYMBOL(register_die_notifier);
-#ifdef CONFIG_HAVE_DEC_LOCK
-EXPORT_SYMBOL(_atomic_dec_and_lock);
-#endif
-
-EXPORT_SYMBOL(__PAGE_KERNEL);
-
-#ifdef CONFIG_HIGHMEM
-EXPORT_SYMBOL(kmap);
-EXPORT_SYMBOL(kunmap);
-EXPORT_SYMBOL(kmap_atomic);
-EXPORT_SYMBOL(kunmap_atomic);
-EXPORT_SYMBOL(kmap_atomic_to_page);
-#endif
-
-#if defined(CONFIG_X86_SPEEDSTEP_SMI) || defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
-EXPORT_SYMBOL(ist_info);
 #endif
 
 EXPORT_SYMBOL(csum_partial);
diff --git a/arch/i386/kernel/i387.c b/arch/i386/kernel/i387.c
index c55e037..b817168 100644
--- a/arch/i386/kernel/i387.c
+++ b/arch/i386/kernel/i387.c
@@ -10,6 +10,7 @@
 
 #include <linux/config.h>
 #include <linux/sched.h>
+#include <linux/module.h>
 #include <asm/processor.h>
 #include <asm/i387.h>
 #include <asm/math_emu.h>
@@ -79,6 +80,7 @@
 	}
 	clts();
 }
+EXPORT_SYMBOL_GPL(kernel_fpu_begin);
 
 void restore_fpu( struct task_struct *tsk )
 {
@@ -526,6 +528,7 @@
 
 	return fpvalid;
 }
+EXPORT_SYMBOL(dump_fpu);
 
 int dump_task_fpu(struct task_struct *tsk, struct user_i387_struct *fpu)
 {
diff --git a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
index 2c4813b..178f4e9 100644
--- a/arch/i386/kernel/i8259.c
+++ b/arch/i386/kernel/i8259.c
@@ -268,10 +268,22 @@
 	return 0;
 }
 
+static int i8259A_shutdown(struct sys_device *dev)
+{
+	/* Put the i8259A into a quiescent state that
+	 * 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 */
+	return 0;
+}
+
 static struct sysdev_class i8259_sysdev_class = {
 	set_kset_name("i8259"),
 	.suspend = i8259A_suspend,
 	.resume = i8259A_resume,
+	.shutdown = i8259A_shutdown,
 };
 
 static struct sys_device device_i8259A = {
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 7a324e8..35eb8e2 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -31,7 +31,7 @@
 #include <linux/mc146818rtc.h>
 #include <linux/compiler.h>
 #include <linux/acpi.h>
-
+#include <linux/module.h>
 #include <linux/sysdev.h>
 #include <asm/io.h>
 #include <asm/smp.h>
@@ -573,12 +573,14 @@
 	for ( ; ; ) {
 		set_current_state(TASK_INTERRUPTIBLE);
 		time_remaining = schedule_timeout(time_remaining);
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 		if (time_after(jiffies,
 				prev_balance_time+balanced_irq_interval)) {
+			preempt_disable();
 			do_irq_balance();
 			prev_balance_time = jiffies;
 			time_remaining = balanced_irq_interval;
+			preempt_enable();
 		}
 	}
 	return 0;
@@ -630,10 +632,8 @@
 		printk(KERN_ERR "balanced_irq_init: failed to spawn balanced_irq");
 failed:
 	for (i = 0; i < NR_CPUS; i++) {
-		if(irq_cpu_data[i].irq_delta)
-			kfree(irq_cpu_data[i].irq_delta);
-		if(irq_cpu_data[i].last_irq)
-			kfree(irq_cpu_data[i].last_irq);
+		kfree(irq_cpu_data[i].irq_delta);
+		kfree(irq_cpu_data[i].last_irq);
 	}
 	return 0;
 }
@@ -812,6 +812,7 @@
 	}
 	return best_guess;
 }
+EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
 
 /*
  * This function currently is only a helper for the i386 smp boot process where 
@@ -1633,12 +1634,43 @@
  */
 void disable_IO_APIC(void)
 {
+	int pin;
 	/*
 	 * Clear the IO-APIC before rebooting:
 	 */
 	clear_IO_APIC();
 
-	disconnect_bsp_APIC();
+	/*
+	 * If the i82559 is routed through an IOAPIC
+	 * Put that IOAPIC in virtual wire mode
+	 * so legacy interrups can be delivered.
+	 */
+	pin = find_isa_irq_pin(0, mp_ExtINT);
+	if (pin != -1) {
+		struct IO_APIC_route_entry entry;
+		unsigned long flags;
+
+		memset(&entry, 0, sizeof(entry));
+		entry.mask            = 0; /* Enabled */
+		entry.trigger         = 0; /* Edge */
+		entry.irr             = 0;
+		entry.polarity        = 0; /* High */
+		entry.delivery_status = 0;
+		entry.dest_mode       = 0; /* Physical */
+		entry.delivery_mode   = 7; /* ExtInt */
+		entry.vector          = 0;
+		entry.dest.physical.physical_dest = 0;
+
+
+		/*
+		 * Add it to the IO-APIC irq-routing table:
+		 */
+		spin_lock_irqsave(&ioapic_lock, flags);
+		io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1));
+		io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0));
+		spin_unlock_irqrestore(&ioapic_lock, flags);
+	}
+	disconnect_bsp_APIC(pin != -1);
 }
 
 /*
@@ -1659,6 +1691,12 @@
 	unsigned long flags;
 
 	/*
+	 * Don't check I/O APIC IDs for xAPIC systems.  They have
+	 * no meaning without the serial APIC bus.
+	 */
+	if (!(boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && boot_cpu_data.x86 < 15))
+		return;
+	/*
 	 * This is broken; anything with a real cpu count has to
 	 * circumvent this idiocy regardless.
 	 */
@@ -1684,10 +1722,6 @@
 			mp_ioapics[apic].mpc_apicid = reg_00.bits.ID;
 		}
 
-		/* Don't check I/O APIC IDs for some xAPIC systems.  They have
-		 * no meaning without the serial APIC bus. */
-		if (NO_IOAPIC_CHECK)
-			continue;
 		/*
 		 * Sanity check, is the ID really free? Every APIC in a
 		 * system must have a unique ID or we get lots of nice
diff --git a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c
index 73945a3..ce66dcc 100644
--- a/arch/i386/kernel/irq.c
+++ b/arch/i386/kernel/irq.c
@@ -15,6 +15,9 @@
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <linux/delay.h>
 
 DEFINE_PER_CPU(irq_cpustat_t, irq_stat) ____cacheline_maxaligned_in_smp;
 EXPORT_PER_CPU_SYMBOL(irq_stat);
@@ -153,6 +156,11 @@
 		cpu,hardirq_ctx[cpu],softirq_ctx[cpu]);
 }
 
+void irq_ctx_exit(int cpu)
+{
+	hardirq_ctx[cpu] = NULL;
+}
+
 extern asmlinkage void __do_softirq(void);
 
 asmlinkage void do_softirq(void)
@@ -210,9 +218,8 @@
 
 	if (i == 0) {
 		seq_printf(p, "           ");
-		for (j=0; j<NR_CPUS; j++)
-			if (cpu_online(j))
-				seq_printf(p, "CPU%d       ",j);
+		for_each_cpu(j)
+			seq_printf(p, "CPU%d       ",j);
 		seq_putc(p, '\n');
 	}
 
@@ -225,9 +232,8 @@
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
-		for (j = 0; j < NR_CPUS; j++)
-			if (cpu_online(j))
-				seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+		for_each_cpu(j)
+			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
 		seq_printf(p, " %14s", irq_desc[i].handler->typename);
 		seq_printf(p, "  %s", action->name);
@@ -240,16 +246,14 @@
 		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
 	} else if (i == NR_IRQS) {
 		seq_printf(p, "NMI: ");
-		for (j = 0; j < NR_CPUS; j++)
-			if (cpu_online(j))
-				seq_printf(p, "%10u ", nmi_count(j));
+		for_each_cpu(j)
+			seq_printf(p, "%10u ", nmi_count(j));
 		seq_putc(p, '\n');
 #ifdef CONFIG_X86_LOCAL_APIC
 		seq_printf(p, "LOC: ");
-		for (j = 0; j < NR_CPUS; j++)
-			if (cpu_online(j))
-				seq_printf(p, "%10u ",
-					per_cpu(irq_stat,j).apic_timer_irqs);
+		for_each_cpu(j)
+			seq_printf(p, "%10u ",
+				per_cpu(irq_stat,j).apic_timer_irqs);
 		seq_putc(p, '\n');
 #endif
 		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
@@ -259,3 +263,45 @@
 	}
 	return 0;
 }
+
+#ifdef CONFIG_HOTPLUG_CPU
+#include <mach_apic.h>
+
+void fixup_irqs(cpumask_t map)
+{
+	unsigned int irq;
+	static int warned;
+
+	for (irq = 0; irq < NR_IRQS; irq++) {
+		cpumask_t mask;
+		if (irq == 2)
+			continue;
+
+		cpus_and(mask, irq_affinity[irq], map);
+		if (any_online_cpu(mask) == NR_CPUS) {
+			printk("Breaking affinity for irq %i\n", irq);
+			mask = map;
+		}
+		if (irq_desc[irq].handler->set_affinity)
+			irq_desc[irq].handler->set_affinity(irq, mask);
+		else if (irq_desc[irq].action && !(warned++))
+			printk("Cannot set affinity for irq %i\n", irq);
+	}
+
+#if 0
+	barrier();
+	/* Ingo Molnar says: "after the IO-APIC masks have been redirected
+	   [note the nop - the interrupt-enable boundary on x86 is two
+	   instructions from sti] - to flush out pending hardirqs and
+	   IPIs. After this point nothing is supposed to reach this CPU." */
+	__asm__ __volatile__("sti; nop; cli");
+	barrier();
+#else
+	/* That doesn't seem sufficient.  Give it 1ms. */
+	local_irq_enable();
+	mdelay(1);
+	local_irq_disable();
+#endif
+}
+#endif
+
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index 59ff9b4..3762f6b 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -23,6 +23,9 @@
  *		Rusty Russell).
  * 2004-July	Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes
  *		interface to access function arguments.
+ * 2005-May	Hien Nguyen <hien@us.ibm.com>, Jim Keniston
+ *		<jkenisto@us.ibm.com> and Prasanna S Panchamukhi
+ *		<prasanna@in.ibm.com> added function-return probes.
  */
 
 #include <linux/config.h>
@@ -30,15 +33,14 @@
 #include <linux/ptrace.h>
 #include <linux/spinlock.h>
 #include <linux/preempt.h>
+#include <asm/cacheflush.h>
 #include <asm/kdebug.h>
 #include <asm/desc.h>
 
-/* kprobe_status settings */
-#define KPROBE_HIT_ACTIVE	0x00000001
-#define KPROBE_HIT_SS		0x00000002
-
 static struct kprobe *current_kprobe;
 static unsigned long kprobe_status, kprobe_old_eflags, kprobe_saved_eflags;
+static struct kprobe *kprobe_prev;
+static unsigned long kprobe_status_prev, kprobe_old_eflags_prev, kprobe_saved_eflags_prev;
 static struct pt_regs jprobe_saved_regs;
 static long *jprobe_saved_esp;
 /* copy of the kernel stack at the probe fire time */
@@ -68,16 +70,50 @@
 void arch_copy_kprobe(struct kprobe *p)
 {
 	memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+	p->opcode = *p->addr;
+}
+
+void arch_arm_kprobe(struct kprobe *p)
+{
+	*p->addr = BREAKPOINT_INSTRUCTION;
+	flush_icache_range((unsigned long) p->addr,
+			   (unsigned long) p->addr + sizeof(kprobe_opcode_t));
+}
+
+void arch_disarm_kprobe(struct kprobe *p)
+{
+	*p->addr = p->opcode;
+	flush_icache_range((unsigned long) p->addr,
+			   (unsigned long) p->addr + sizeof(kprobe_opcode_t));
 }
 
 void arch_remove_kprobe(struct kprobe *p)
 {
 }
 
-static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
+static inline void save_previous_kprobe(void)
 {
-	*p->addr = p->opcode;
-	regs->eip = (unsigned long)p->addr;
+	kprobe_prev = current_kprobe;
+	kprobe_status_prev = kprobe_status;
+	kprobe_old_eflags_prev = kprobe_old_eflags;
+	kprobe_saved_eflags_prev = kprobe_saved_eflags;
+}
+
+static inline void restore_previous_kprobe(void)
+{
+	current_kprobe = kprobe_prev;
+	kprobe_status = kprobe_status_prev;
+	kprobe_old_eflags = kprobe_old_eflags_prev;
+	kprobe_saved_eflags = kprobe_saved_eflags_prev;
+}
+
+static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs)
+{
+	current_kprobe = p;
+	kprobe_saved_eflags = kprobe_old_eflags
+		= (regs->eflags & (TF_MASK | IF_MASK));
+	if (is_IF_modifier(p->opcode))
+		kprobe_saved_eflags &= ~IF_MASK;
 }
 
 static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
@@ -91,6 +127,50 @@
 		regs->eip = (unsigned long)&p->ainsn.insn;
 }
 
+struct task_struct  *arch_get_kprobe_task(void *ptr)
+{
+	return ((struct thread_info *) (((unsigned long) ptr) &
+					(~(THREAD_SIZE -1))))->task;
+}
+
+void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
+{
+	unsigned long *sara = (unsigned long *)&regs->esp;
+	struct kretprobe_instance *ri;
+	static void *orig_ret_addr;
+
+	/*
+	 * Save the return address when the return probe hits
+	 * the first time, and use it to populate the (krprobe
+	 * instance)->ret_addr for subsequent return probes at
+	 * the same addrress since stack address would have
+	 * the kretprobe_trampoline by then.
+	 */
+	if (((void*) *sara) != kretprobe_trampoline)
+		orig_ret_addr = (void*) *sara;
+
+	if ((ri = get_free_rp_inst(rp)) != NULL) {
+		ri->rp = rp;
+		ri->stack_addr = sara;
+		ri->ret_addr = orig_ret_addr;
+		add_rp_inst(ri);
+		/* Replace the return addr with trampoline addr */
+		*sara = (unsigned long) &kretprobe_trampoline;
+	} else {
+		rp->nmissed++;
+	}
+}
+
+void arch_kprobe_flush_task(struct task_struct *tk)
+{
+	struct kretprobe_instance *ri;
+	while ((ri = get_rp_inst_tsk(tk)) != NULL) {
+		*((unsigned long *)(ri->stack_addr)) =
+					(unsigned long) ri->ret_addr;
+		recycle_rp_inst(ri);
+	}
+}
+
 /*
  * Interrupts are disabled on entry as trap3 is an interrupt gate and they
  * remain disabled thorough out this function.
@@ -127,8 +207,18 @@
 				unlock_kprobes();
 				goto no_kprobe;
 			}
-			disarm_kprobe(p, regs);
-			ret = 1;
+			/* We have reentered the kprobe_handler(), since
+			 * another probe was hit while within the handler.
+			 * We here save the original kprobes variables and
+			 * just single step on the instruction of the new probe
+			 * without calling any user handlers.
+			 */
+			save_previous_kprobe();
+			set_current_kprobe(p, regs);
+			p->nmissed++;
+			prepare_singlestep(p, regs);
+			kprobe_status = KPROBE_REENTER;
+			return 1;
 		} else {
 			p = current_kprobe;
 			if (p->break_handler && p->break_handler(p, regs)) {
@@ -163,11 +253,7 @@
 	}
 
 	kprobe_status = KPROBE_HIT_ACTIVE;
-	current_kprobe = p;
-	kprobe_saved_eflags = kprobe_old_eflags
-	    = (regs->eflags & (TF_MASK | IF_MASK));
-	if (is_IF_modifier(p->opcode))
-		kprobe_saved_eflags &= ~IF_MASK;
+	set_current_kprobe(p, regs);
 
 	if (p->pre_handler && p->pre_handler(p, regs))
 		/* handler has already set things up, so skip ss setup */
@@ -184,6 +270,55 @@
 }
 
 /*
+ * For function-return probes, init_kprobes() establishes a probepoint
+ * here. When a retprobed function returns, this probe is hit and
+ * trampoline_probe_handler() runs, calling the kretprobe's handler.
+ */
+ void kretprobe_trampoline_holder(void)
+ {
+ 	asm volatile (  ".global kretprobe_trampoline\n"
+ 			"kretprobe_trampoline: \n"
+ 			"nop\n");
+ }
+
+/*
+ * Called when we hit the probe point at kretprobe_trampoline
+ */
+int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	struct task_struct *tsk;
+	struct kretprobe_instance *ri;
+	struct hlist_head *head;
+	struct hlist_node *node;
+	unsigned long *sara = ((unsigned long *) &regs->esp) - 1;
+
+	tsk = arch_get_kprobe_task(sara);
+	head = kretprobe_inst_table_head(tsk);
+
+	hlist_for_each_entry(ri, node, head, hlist) {
+		if (ri->stack_addr == sara && ri->rp) {
+			if (ri->rp->handler)
+				ri->rp->handler(ri, regs);
+		}
+	}
+	return 0;
+}
+
+void trampoline_post_handler(struct kprobe *p, struct pt_regs *regs,
+						unsigned long flags)
+{
+	struct kretprobe_instance *ri;
+	/* RA already popped */
+	unsigned long *sara = ((unsigned long *)&regs->esp) - 1;
+
+	while ((ri = get_rp_inst(sara))) {
+		regs->eip = (unsigned long)ri->ret_addr;
+		recycle_rp_inst(ri);
+	}
+	regs->eflags &= ~TF_MASK;
+}
+
+/*
  * Called after single-stepping.  p->addr is the address of the
  * instruction whose first byte has been replaced by the "int 3"
  * instruction.  To avoid the SMP problems that can occur when we
@@ -263,13 +398,22 @@
 	if (!kprobe_running())
 		return 0;
 
-	if (current_kprobe->post_handler)
+	if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) {
+		kprobe_status = KPROBE_HIT_SSDONE;
 		current_kprobe->post_handler(current_kprobe, regs, 0);
+	}
 
-	resume_execution(current_kprobe, regs);
+	if (current_kprobe->post_handler != trampoline_post_handler)
+		resume_execution(current_kprobe, regs);
 	regs->eflags |= kprobe_saved_eflags;
 
+	/*Restore back the original saved kprobes variables and continue. */
+	if (kprobe_status == KPROBE_REENTER) {
+		restore_previous_kprobe();
+		goto out;
+	}
 	unlock_kprobes();
+out:
 	preempt_enable_no_resched();
 
 	/*
diff --git a/arch/i386/kernel/machine_kexec.c b/arch/i386/kernel/machine_kexec.c
new file mode 100644
index 0000000..52ed18d
--- /dev/null
+++ b/arch/i386/kernel/machine_kexec.c
@@ -0,0 +1,226 @@
+/*
+ * machine_kexec.c - handle transition of Linux booting another kernel
+ * Copyright (C) 2002-2005 Eric Biederman  <ebiederm@xmission.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+
+#include <linux/mm.h>
+#include <linux/kexec.h>
+#include <linux/delay.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/apic.h>
+#include <asm/cpufeature.h>
+
+static inline unsigned long read_cr3(void)
+{
+	unsigned long cr3;
+	asm volatile("movl %%cr3,%0": "=r"(cr3));
+	return cr3;
+}
+
+#define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
+
+#define L0_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define L1_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define L2_ATTR (_PAGE_PRESENT)
+
+#define LEVEL0_SIZE (1UL << 12UL)
+
+#ifndef CONFIG_X86_PAE
+#define LEVEL1_SIZE (1UL << 22UL)
+static u32 pgtable_level1[1024] PAGE_ALIGNED;
+
+static void identity_map_page(unsigned long address)
+{
+	unsigned long level1_index, level2_index;
+	u32 *pgtable_level2;
+
+	/* Find the current page table */
+	pgtable_level2 = __va(read_cr3());
+
+	/* Find the indexes of the physical address to identity map */
+	level1_index = (address % LEVEL1_SIZE)/LEVEL0_SIZE;
+	level2_index = address / LEVEL1_SIZE;
+
+	/* Identity map the page table entry */
+	pgtable_level1[level1_index] = address | L0_ATTR;
+	pgtable_level2[level2_index] = __pa(pgtable_level1) | L1_ATTR;
+
+	/* Flush the tlb so the new mapping takes effect.
+	 * Global tlb entries are not flushed but that is not an issue.
+	 */
+	load_cr3(pgtable_level2);
+}
+
+#else
+#define LEVEL1_SIZE (1UL << 21UL)
+#define LEVEL2_SIZE (1UL << 30UL)
+static u64 pgtable_level1[512] PAGE_ALIGNED;
+static u64 pgtable_level2[512] PAGE_ALIGNED;
+
+static void identity_map_page(unsigned long address)
+{
+	unsigned long level1_index, level2_index, level3_index;
+	u64 *pgtable_level3;
+
+	/* Find the current page table */
+	pgtable_level3 = __va(read_cr3());
+
+	/* Find the indexes of the physical address to identity map */
+	level1_index = (address % LEVEL1_SIZE)/LEVEL0_SIZE;
+	level2_index = (address % LEVEL2_SIZE)/LEVEL1_SIZE;
+	level3_index = address / LEVEL2_SIZE;
+
+	/* Identity map the page table entry */
+	pgtable_level1[level1_index] = address | L0_ATTR;
+	pgtable_level2[level2_index] = __pa(pgtable_level1) | L1_ATTR;
+	set_64bit(&pgtable_level3[level3_index],
+					       __pa(pgtable_level2) | L2_ATTR);
+
+	/* Flush the tlb so the new mapping takes effect.
+	 * Global tlb entries are not flushed but that is not an issue.
+	 */
+	load_cr3(pgtable_level3);
+}
+#endif
+
+
+static void set_idt(void *newidt, __u16 limit)
+{
+	unsigned char curidt[6];
+
+	/* ia32 supports unaliged loads & stores */
+	(*(__u16 *)(curidt)) = limit;
+	(*(__u32 *)(curidt +2)) = (unsigned long)(newidt);
+
+	__asm__ __volatile__ (
+		"lidt %0\n"
+		: "=m" (curidt)
+		);
+};
+
+
+static void set_gdt(void *newgdt, __u16 limit)
+{
+	unsigned char curgdt[6];
+
+	/* ia32 supports unaligned loads & stores */
+	(*(__u16 *)(curgdt)) = limit;
+	(*(__u32 *)(curgdt +2)) = (unsigned long)(newgdt);
+
+	__asm__ __volatile__ (
+		"lgdt %0\n"
+		: "=m" (curgdt)
+		);
+};
+
+static void load_segments(void)
+{
+#define __STR(X) #X
+#define STR(X) __STR(X)
+
+	__asm__ __volatile__ (
+		"\tljmp $"STR(__KERNEL_CS)",$1f\n"
+		"\t1:\n"
+		"\tmovl $"STR(__KERNEL_DS)",%eax\n"
+		"\tmovl %eax,%ds\n"
+		"\tmovl %eax,%es\n"
+		"\tmovl %eax,%fs\n"
+		"\tmovl %eax,%gs\n"
+		"\tmovl %eax,%ss\n"
+		);
+#undef STR
+#undef __STR
+}
+
+typedef asmlinkage NORET_TYPE void (*relocate_new_kernel_t)(
+					unsigned long indirection_page,
+					unsigned long reboot_code_buffer,
+					unsigned long start_address,
+					unsigned int has_pae) ATTRIB_NORET;
+
+const extern unsigned char relocate_new_kernel[];
+extern void relocate_new_kernel_end(void);
+const extern unsigned int relocate_new_kernel_size;
+
+/*
+ * A architecture hook called to validate the
+ * proposed image and prepare the control pages
+ * as needed.  The pages for KEXEC_CONTROL_CODE_SIZE
+ * have been allocated, but the segments have yet
+ * been copied into the kernel.
+ *
+ * Do what every setup is needed on image and the
+ * reboot code buffer to allow us to avoid allocations
+ * later.
+ *
+ * Currently nothing.
+ */
+int machine_kexec_prepare(struct kimage *image)
+{
+	return 0;
+}
+
+/*
+ * Undo anything leftover by machine_kexec_prepare
+ * when an image is freed.
+ */
+void machine_kexec_cleanup(struct kimage *image)
+{
+}
+
+/*
+ * Do not allocate memory (or fail in any way) in machine_kexec().
+ * We are past the point of no return, committed to rebooting now.
+ */
+NORET_TYPE void machine_kexec(struct kimage *image)
+{
+	unsigned long page_list;
+	unsigned long reboot_code_buffer;
+
+	relocate_new_kernel_t rnk;
+
+	/* Interrupts aren't acceptable while we reboot */
+	local_irq_disable();
+
+	/* Compute some offsets */
+	reboot_code_buffer = page_to_pfn(image->control_code_page)
+								<< PAGE_SHIFT;
+	page_list = image->head;
+
+	/* Set up an identity mapping for the reboot_code_buffer */
+	identity_map_page(reboot_code_buffer);
+
+	/* copy it out */
+	memcpy((void *)reboot_code_buffer, relocate_new_kernel,
+						relocate_new_kernel_size);
+
+	/* The segment registers are funny things, they are
+	 * automatically loaded from a table, in memory wherever you
+	 * set them to a specific selector, but this table is never
+	 * accessed again you set the segment to a different selector.
+	 *
+	 * The more common model is are caches where the behide
+	 * the scenes work is done, but is also dropped at arbitrary
+	 * times.
+	 *
+	 * I take advantage of this here by force loading the
+	 * segments, before I zap the gdt with an invalid value.
+	 */
+	load_segments();
+	/* The gdt & idt are now invalid.
+	 * If you want to load them you must set up your own idt & gdt.
+	 */
+	set_gdt(phys_to_virt(0),0);
+	set_idt(phys_to_virt(0),0);
+
+	/* now call it */
+	rnk = (relocate_new_kernel_t) reboot_code_buffer;
+	(*rnk)(page_list, reboot_code_buffer, image->start, cpu_has_pae);
+}
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
index 1347ab4..af917f6 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -67,7 +67,6 @@
 
 /* Processor that is doing the boot up */
 unsigned int boot_cpu_physical_apicid = -1U;
-unsigned int boot_cpu_logical_apicid = -1U;
 /* Internal processor count */
 static unsigned int __initdata num_processors;
 
@@ -180,7 +179,6 @@
 	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
 		Dprintk("    Bootup CPU\n");
 		boot_cpu_physical_apicid = m->mpc_apicid;
-		boot_cpu_logical_apicid = apicid;
 	}
 
 	if (num_processors >= NR_CPUS) {
@@ -914,7 +912,10 @@
 	mp_ioapics[idx].mpc_apicaddr = address;
 
 	set_fixmap_nocache(FIX_IO_APIC_BASE_0 + idx, address);
-	mp_ioapics[idx].mpc_apicid = io_apic_get_unique_id(idx, id);
+	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) && (boot_cpu_data.x86 < 15))
+		mp_ioapics[idx].mpc_apicid = io_apic_get_unique_id(idx, id);
+	else
+		mp_ioapics[idx].mpc_apicid = id;
 	mp_ioapics[idx].mpc_apicver = io_apic_get_version(idx);
 	
 	/* 
@@ -1055,11 +1056,20 @@
 	}
 }
 
+#define MAX_GSI_NUM	4096
+
 int mp_register_gsi (u32 gsi, int edge_level, int active_high_low)
 {
 	int			ioapic = -1;
 	int			ioapic_pin = 0;
 	int			idx, bit = 0;
+	static int		pci_irq = 16;
+	/*
+	 * Mapping between Global System Interrups, which
+	 * represent all possible interrupts, and IRQs
+	 * assigned to actual devices.
+	 */
+	static int		gsi_to_irq[MAX_GSI_NUM];
 
 #ifdef CONFIG_ACPI_BUS
 	/* Don't set up the ACPI SCI because it's already set up */
@@ -1094,11 +1104,26 @@
 	if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
 		Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
 			mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
-		return gsi;
+		return gsi_to_irq[gsi];
 	}
 
 	mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
 
+	if (edge_level) {
+		/*
+		 * For PCI devices assign IRQs in order, avoiding gaps
+		 * due to unused I/O APIC pins.
+		 */
+		int irq = gsi;
+		if (gsi < MAX_GSI_NUM) {
+			gsi = pci_irq++;
+			gsi_to_irq[irq] = gsi;
+		} else {
+			printk(KERN_ERR "GSI %u is too high\n", gsi);
+			return gsi;
+		}
+	}
+
 	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
 		    edge_level == ACPI_EDGE_SENSITIVE ? 0 : 1,
 		    active_high_low == ACPI_ACTIVE_HIGH ? 0 : 1);
diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c
index 05d9f8f..b2f03c3 100644
--- a/arch/i386/kernel/msr.c
+++ b/arch/i386/kernel/msr.c
@@ -44,7 +44,7 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
-static struct class_simple *msr_class;
+static struct class *msr_class;
 
 /* Note: "err" is handled in a funny way below.  Otherwise one version
    of gcc or another breaks. */
@@ -260,12 +260,12 @@
 	.open = msr_open,
 };
 
-static int msr_class_simple_device_add(int i)
+static int msr_class_device_create(int i)
 {
 	int err = 0;
 	struct class_device *class_err;
 
-	class_err = class_simple_device_add(msr_class, MKDEV(MSR_MAJOR, i), NULL, "msr%d",i);
+	class_err = class_device_create(msr_class, MKDEV(MSR_MAJOR, i), NULL, "msr%d",i);
 	if (IS_ERR(class_err)) 
 		err = PTR_ERR(class_err);
 	return err;
@@ -277,10 +277,10 @@
 
 	switch (action) {
 	case CPU_ONLINE:
-		msr_class_simple_device_add(cpu);
+		msr_class_device_create(cpu);
 		break;
 	case CPU_DEAD:
-		class_simple_device_remove(MKDEV(MSR_MAJOR, cpu));	
+		class_device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
 		break;
 	}
 	return NOTIFY_OK;
@@ -302,13 +302,13 @@
 		err = -EBUSY;
 		goto out;
 	}
-	msr_class = class_simple_create(THIS_MODULE, "msr");
+	msr_class = class_create(THIS_MODULE, "msr");
 	if (IS_ERR(msr_class)) {
 		err = PTR_ERR(msr_class);
 		goto out_chrdev;
 	}
 	for_each_online_cpu(i) {
-		err = msr_class_simple_device_add(i);
+		err = msr_class_device_create(i);
 		if (err != 0)
 			goto out_class;
 	}
@@ -320,8 +320,8 @@
 out_class:
 	i = 0;
 	for_each_online_cpu(i)
-		class_simple_device_remove(MKDEV(MSR_MAJOR, i));
-	class_simple_destroy(msr_class);
+		class_device_destroy(msr_class, MKDEV(MSR_MAJOR, i));
+	class_destroy(msr_class);
 out_chrdev:
 	unregister_chrdev(MSR_MAJOR, "cpu/msr");
 out:
@@ -332,8 +332,8 @@
 {
 	int cpu = 0;
 	for_each_online_cpu(cpu)
-		class_simple_device_remove(MKDEV(MSR_MAJOR, cpu));
-	class_simple_destroy(msr_class);
+		class_device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu));
+	class_destroy(msr_class);
 	unregister_chrdev(MSR_MAJOR, "cpu/msr");
 	unregister_cpu_notifier(&msr_class_cpu_notifier);
 }
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c
index 2c0ee9c..da6c46d 100644
--- a/arch/i386/kernel/nmi.c
+++ b/arch/i386/kernel/nmi.c
@@ -28,8 +28,7 @@
 #include <linux/sysctl.h>
 
 #include <asm/smp.h>
-#include <asm/mtrr.h>
-#include <asm/mpspec.h>
+#include <asm/div64.h>
 #include <asm/nmi.h>
 
 #include "mach_traps.h"
@@ -324,6 +323,16 @@
 		wrmsr(base+i, 0, 0);
 }
 
+static inline void write_watchdog_counter(const char *descr)
+{
+	u64 count = (u64)cpu_khz * 1000;
+
+	do_div(count, nmi_hz);
+	if(descr)
+		Dprintk("setting %s to -0x%08Lx\n", descr, count);
+	wrmsrl(nmi_perfctr_msr, 0 - count);
+}
+
 static void setup_k7_watchdog(void)
 {
 	unsigned int evntsel;
@@ -339,8 +348,7 @@
 		| K7_NMI_EVENT;
 
 	wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
-	Dprintk("setting K7_PERFCTR0 to %08lx\n", -(cpu_khz/nmi_hz*1000));
-	wrmsr(MSR_K7_PERFCTR0, -(cpu_khz/nmi_hz*1000), -1);
+	write_watchdog_counter("K7_PERFCTR0");
 	apic_write(APIC_LVTPC, APIC_DM_NMI);
 	evntsel |= K7_EVNTSEL_ENABLE;
 	wrmsr(MSR_K7_EVNTSEL0, evntsel, 0);
@@ -361,8 +369,7 @@
 		| P6_NMI_EVENT;
 
 	wrmsr(MSR_P6_EVNTSEL0, evntsel, 0);
-	Dprintk("setting P6_PERFCTR0 to %08lx\n", -(cpu_khz/nmi_hz*1000));
-	wrmsr(MSR_P6_PERFCTR0, -(cpu_khz/nmi_hz*1000), 0);
+	write_watchdog_counter("P6_PERFCTR0");
 	apic_write(APIC_LVTPC, APIC_DM_NMI);
 	evntsel |= P6_EVNTSEL0_ENABLE;
 	wrmsr(MSR_P6_EVNTSEL0, evntsel, 0);
@@ -402,8 +409,7 @@
 
 	wrmsr(MSR_P4_CRU_ESCR0, P4_NMI_CRU_ESCR0, 0);
 	wrmsr(MSR_P4_IQ_CCCR0, P4_NMI_IQ_CCCR0 & ~P4_CCCR_ENABLE, 0);
-	Dprintk("setting P4_IQ_COUNTER0 to 0x%08lx\n", -(cpu_khz/nmi_hz*1000));
-	wrmsr(MSR_P4_IQ_COUNTER0, -(cpu_khz/nmi_hz*1000), -1);
+	write_watchdog_counter("P4_IQ_COUNTER0");
 	apic_write(APIC_LVTPC, APIC_DM_NMI);
 	wrmsr(MSR_P4_IQ_CCCR0, nmi_p4_cccr_val, 0);
 	return 1;
@@ -518,7 +524,7 @@
 			 * other P6 variant */
 			apic_write(APIC_LVTPC, APIC_DM_NMI);
 		}
-		wrmsr(nmi_perfctr_msr, -(cpu_khz/nmi_hz*1000), -1);
+		write_watchdog_counter(NULL);
 	}
 }
 
diff --git a/arch/i386/kernel/pci-dma.c b/arch/i386/kernel/pci-dma.c
index 4de2e03..1e51427 100644
--- a/arch/i386/kernel/pci-dma.c
+++ b/arch/i386/kernel/pci-dma.c
@@ -11,6 +11,7 @@
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/pci.h>
+#include <linux/module.h>
 #include <asm/io.h>
 
 struct dma_coherent_mem {
@@ -54,6 +55,7 @@
 	}
 	return ret;
 }
+EXPORT_SYMBOL(dma_alloc_coherent);
 
 void dma_free_coherent(struct device *dev, size_t size,
 			 void *vaddr, dma_addr_t dma_handle)
@@ -68,6 +70,7 @@
 	} else
 		free_pages((unsigned long)vaddr, order);
 }
+EXPORT_SYMBOL(dma_free_coherent);
 
 int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
 				dma_addr_t device_addr, size_t size, int flags)
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
index 96e3ea6..5f8cfa6 100644
--- a/arch/i386/kernel/process.c
+++ b/arch/i386/kernel/process.c
@@ -13,6 +13,7 @@
 
 #include <stdarg.h>
 
+#include <linux/cpu.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
@@ -37,6 +38,7 @@
 #include <linux/kallsyms.h>
 #include <linux/ptrace.h>
 #include <linux/random.h>
+#include <linux/kprobes.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -54,6 +56,9 @@
 #include <linux/irq.h>
 #include <linux/err.h>
 
+#include <asm/tlbflush.h>
+#include <asm/cpu.h>
+
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
 
 static int hlt_counter;
@@ -73,6 +78,7 @@
  * Powermanagement idle function, if any..
  */
 void (*pm_idle)(void);
+EXPORT_SYMBOL(pm_idle);
 static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
 
 void disable_hlt(void)
@@ -105,6 +111,9 @@
 		cpu_relax();
 	}
 }
+#ifdef CONFIG_APM_MODULE
+EXPORT_SYMBOL(default_idle);
+#endif
 
 /*
  * On SMP it's slightly faster (but much more power-consuming!)
@@ -138,14 +147,42 @@
 	}
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+#include <asm/nmi.h>
+/* We don't actually take CPU down, just spin without interrupts. */
+static inline void play_dead(void)
+{
+	/* This must be done before dead CPU ack */
+	cpu_exit_clear();
+	wbinvd();
+	mb();
+	/* Ack it */
+	__get_cpu_var(cpu_state) = CPU_DEAD;
+
+	/*
+	 * With physical CPU hotplug, we should halt the cpu
+	 */
+	local_irq_disable();
+	while (1)
+		__asm__ __volatile__("hlt":::"memory");
+}
+#else
+static inline void play_dead(void)
+{
+	BUG();
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
 /*
  * The idle thread. There's no useful work to be
  * done, so just try to conserve power and have a
  * low exit latency (ie sit in a loop waiting for
  * somebody to say that they'd like to reschedule)
  */
-void cpu_idle (void)
+void cpu_idle(void)
 {
+	int cpu = raw_smp_processor_id();
+
 	/* endless idle loop with no priority at all */
 	while (1) {
 		while (!need_resched()) {
@@ -160,6 +197,9 @@
 			if (!idle)
 				idle = default_idle;
 
+			if (cpu_is_offline(cpu))
+				play_dead();
+
 			__get_cpu_var(irq_stat).idle_timestamp = jiffies;
 			idle();
 		}
@@ -218,7 +258,7 @@
 	}
 }
 
-void __init select_idle_routine(const struct cpuinfo_x86 *c)
+void __devinit select_idle_routine(const struct cpuinfo_x86 *c)
 {
 	if (cpu_has(c, X86_FEATURE_MWAIT)) {
 		printk("monitor/mwait feature present.\n");
@@ -262,7 +302,7 @@
 	printk("EIP: %04x:[<%08lx>] CPU: %d\n",0xffff & regs->xcs,regs->eip, smp_processor_id());
 	print_symbol("EIP is at %s\n", regs->eip);
 
-	if (regs->xcs & 3)
+	if (user_mode(regs))
 		printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp);
 	printk(" EFLAGS: %08lx    %s  (%s)\n",
 	       regs->eflags, print_tainted(), system_utsname.release);
@@ -325,6 +365,7 @@
 	/* Ok, create the new process.. */
 	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
 }
+EXPORT_SYMBOL(kernel_thread);
 
 /*
  * Free current thread data structures etc..
@@ -334,6 +375,13 @@
 	struct task_struct *tsk = current;
 	struct thread_struct *t = &tsk->thread;
 
+	/*
+	 * Remove function-return probe instances associated with this task
+	 * and put them back on the free list. Do not insert an exit probe for
+	 * this function, it will be disabled by kprobe_flush_task if you do.
+	 */
+	kprobe_flush_task(tsk);
+
 	/* The process may have allocated an io port bitmap... nuke it. */
 	if (unlikely(NULL != t->io_bitmap_ptr)) {
 		int cpu = get_cpu();
@@ -357,6 +405,13 @@
 {
 	struct task_struct *tsk = current;
 
+	/*
+	 * Remove function-return probe instances associated with this task
+	 * and put them back on the free list. Do not insert an exit probe for
+	 * this function, it will be disabled by kprobe_flush_task if you do.
+	 */
+	kprobe_flush_task(tsk);
+
 	memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
 	memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));	
 	/*
@@ -508,6 +563,7 @@
 
 	dump->u_fpvalid = dump_fpu (regs, &dump->i387);
 }
+EXPORT_SYMBOL(dump_thread);
 
 /* 
  * Capture the user space registers if the task is not running (in user space)
@@ -627,13 +683,13 @@
 	 * Now maybe reload the debug registers
 	 */
 	if (unlikely(next->debugreg[7])) {
-		loaddebug(next, 0);
-		loaddebug(next, 1);
-		loaddebug(next, 2);
-		loaddebug(next, 3);
+		set_debugreg(current->thread.debugreg[0], 0);
+		set_debugreg(current->thread.debugreg[1], 1);
+		set_debugreg(current->thread.debugreg[2], 2);
+		set_debugreg(current->thread.debugreg[3], 3);
 		/* no 4 and 5 */
-		loaddebug(next, 6);
-		loaddebug(next, 7);
+		set_debugreg(current->thread.debugreg[6], 6);
+		set_debugreg(current->thread.debugreg[7], 7);
 	}
 
 	if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr))
@@ -731,6 +787,7 @@
 	} while (count++ < 16);
 	return 0;
 }
+EXPORT_SYMBOL(get_wchan);
 
 /*
  * sys_alloc_thread_area: get a yet unused TLS descriptor index.
diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
index e34f651..0da59b4 100644
--- a/arch/i386/kernel/ptrace.c
+++ b/arch/i386/kernel/ptrace.c
@@ -668,7 +668,7 @@
 	info.si_code = TRAP_BRKPT;
 
 	/* User-mode eip? */
-	info.si_addr = user_mode(regs) ? (void __user *) regs->eip : NULL;
+	info.si_addr = user_mode_vm(regs) ? (void __user *) regs->eip : NULL;
 
 	/* Send us the fakey SIGTRAP */
 	force_sig_info(SIGTRAP, &info, tsk);
diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c
index 6dc27eb..b3e5848 100644
--- a/arch/i386/kernel/reboot.c
+++ b/arch/i386/kernel/reboot.c
@@ -2,6 +2,7 @@
  *  linux/arch/i386/kernel/reboot.c
  */
 
+#include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/delay.h>
@@ -19,12 +20,12 @@
  * Power off function, if any
  */
 void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
 
 static int reboot_mode;
 static int reboot_thru_bios;
 
 #ifdef CONFIG_SMP
-int reboot_smp = 0;
 static int reboot_cpu = -1;
 /* shamelessly grabbed from lib/vsprintf.c for readability */
 #define is_digit(c)	((c) >= '0' && (c) <= '9')
@@ -47,7 +48,6 @@
 			break;
 #ifdef CONFIG_SMP
 		case 's': /* "smp" reboot by executing reset on BSP or other CPU*/
-			reboot_smp = 1;
 			if (is_digit(*(str+1))) {
 				reboot_cpu = (int) (*(str+1) - '0');
 				if (is_digit(*(str+2))) 
@@ -86,33 +86,9 @@
 	return 0;
 }
 
-/*
- * Some machines require the "reboot=s"  commandline option, this quirk makes that automatic.
- */
-static int __init set_smp_reboot(struct dmi_system_id *d)
-{
-#ifdef CONFIG_SMP
-	if (!reboot_smp) {
-		reboot_smp = 1;
-		printk(KERN_INFO "%s series board detected. Selecting SMP-method for reboots.\n", d->ident);
-	}
-#endif
-	return 0;
-}
-
-/*
- * Some machines require the "reboot=b,s"  commandline option, this quirk makes that automatic.
- */
-static int __init set_smp_bios_reboot(struct dmi_system_id *d)
-{
-	set_smp_reboot(d);
-	set_bios_reboot(d);
-	return 0;
-}
-
 static struct dmi_system_id __initdata reboot_dmi_table[] = {
 	{	/* Handle problems with rebooting on Dell 1300's */
-		.callback = set_smp_bios_reboot,
+		.callback = set_bios_reboot,
 		.ident = "Dell PowerEdge 1300",
 		.matches = {
 			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
@@ -295,42 +271,36 @@
 				:
 				: "i" ((void *) (0x1000 - sizeof (real_mode_switch) - 100)));
 }
+#ifdef CONFIG_APM_MODULE
+EXPORT_SYMBOL(machine_real_restart);
+#endif
 
-void machine_restart(char * __unused)
+void machine_shutdown(void)
 {
 #ifdef CONFIG_SMP
-	int cpuid;
-	
-	cpuid = GET_APIC_ID(apic_read(APIC_ID));
+	int reboot_cpu_id;
 
-	if (reboot_smp) {
+	/* The boot cpu is always logical cpu 0 */
+	reboot_cpu_id = 0;
 
-		/* check to see if reboot_cpu is valid 
-		   if its not, default to the BSP */
-		if ((reboot_cpu == -1) ||  
-		      (reboot_cpu > (NR_CPUS -1))  || 
-		      !physid_isset(cpuid, phys_cpu_present_map))
-			reboot_cpu = boot_cpu_physical_apicid;
-
-		reboot_smp = 0;  /* use this as a flag to only go through this once*/
-		/* re-run this function on the other CPUs
-		   it will fall though this section since we have 
-		   cleared reboot_smp, and do the reboot if it is the
-		   correct CPU, otherwise it halts. */
-		if (reboot_cpu != cpuid)
-			smp_call_function((void *)machine_restart , NULL, 1, 0);
+	/* See if there has been given a command line override */
+	if ((reboot_cpu_id != -1) && (reboot_cpu < NR_CPUS) &&
+		cpu_isset(reboot_cpu, cpu_online_map)) {
+		reboot_cpu_id = reboot_cpu;
 	}
 
-	/* if reboot_cpu is still -1, then we want a tradional reboot, 
-	   and if we are not running on the reboot_cpu,, halt */
-	if ((reboot_cpu != -1) && (cpuid != reboot_cpu)) {
-		for (;;)
-		__asm__ __volatile__ ("hlt");
+	/* Make certain the cpu I'm rebooting on is online */
+	if (!cpu_isset(reboot_cpu_id, cpu_online_map)) {
+		reboot_cpu_id = smp_processor_id();
 	}
-	/*
-	 * Stop all CPUs and turn off local APICs and the IO-APIC, so
-	 * other OSs see a clean IRQ state.
+
+	/* Make certain I only run on the appropriate processor */
+	set_cpus_allowed(current, cpumask_of_cpu(reboot_cpu_id));
+
+	/* O.K. Now that I'm on the appropriate processor, stop
+	 * all of the others, and disable their local APICs.
 	 */
+
 	smp_send_stop();
 #endif /* CONFIG_SMP */
 
@@ -339,6 +309,11 @@
 #ifdef CONFIG_X86_IO_APIC
 	disable_IO_APIC();
 #endif
+}
+
+void machine_restart(char * __unused)
+{
+	machine_shutdown();
 
 	if (!reboot_thru_bios) {
 		if (efi_enabled) {
diff --git a/arch/i386/kernel/relocate_kernel.S b/arch/i386/kernel/relocate_kernel.S
new file mode 100644
index 0000000..d312616
--- /dev/null
+++ b/arch/i386/kernel/relocate_kernel.S
@@ -0,0 +1,120 @@
+/*
+ * relocate_kernel.S - put the kernel image in place to boot
+ * Copyright (C) 2002-2004 Eric Biederman  <ebiederm@xmission.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+
+#include <linux/linkage.h>
+
+	/*
+	 * Must be relocatable PIC code callable as a C function, that once
+	 * it starts can not use the previous processes stack.
+	 */
+	.globl relocate_new_kernel
+relocate_new_kernel:
+	/* read the arguments and say goodbye to the stack */
+	movl  4(%esp), %ebx /* page_list */
+	movl  8(%esp), %ebp /* reboot_code_buffer */
+	movl  12(%esp), %edx /* start address */
+	movl  16(%esp), %ecx /* cpu_has_pae */
+
+	/* zero out flags, and disable interrupts */
+	pushl $0
+	popfl
+
+	/* set a new stack at the bottom of our page... */
+	lea   4096(%ebp), %esp
+
+	/* store the parameters back on the stack */
+	pushl   %edx /* store the start address */
+
+	/* Set cr0 to a known state:
+	 * 31 0 == Paging disabled
+	 * 18 0 == Alignment check disabled
+	 * 16 0 == Write protect disabled
+	 * 3  0 == No task switch
+	 * 2  0 == Don't do FP software emulation.
+	 * 0  1 == Proctected mode enabled
+	 */
+	movl	%cr0, %eax
+	andl	$~((1<<31)|(1<<18)|(1<<16)|(1<<3)|(1<<2)), %eax
+	orl	$(1<<0), %eax
+	movl	%eax, %cr0
+
+	/* clear cr4 if applicable */
+	testl	%ecx, %ecx
+	jz	1f
+	/* Set cr4 to a known state:
+	 * Setting everything to zero seems safe.
+	 */
+	movl	%cr4, %eax
+	andl	$0, %eax
+	movl	%eax, %cr4
+
+	jmp 1f
+1:
+
+	/* Flush the TLB (needed?) */
+	xorl	%eax, %eax
+	movl	%eax, %cr3
+
+	/* Do the copies */
+	movl	%ebx, %ecx
+	jmp	1f
+
+0:	/* top, read another word from the indirection page */
+	movl	(%ebx), %ecx
+	addl	$4, %ebx
+1:
+	testl	$0x1,   %ecx  /* is it a destination page */
+	jz	2f
+	movl	%ecx,	%edi
+	andl	$0xfffff000, %edi
+	jmp     0b
+2:
+	testl	$0x2,	%ecx  /* is it an indirection page */
+	jz	2f
+	movl	%ecx,	%ebx
+	andl	$0xfffff000, %ebx
+	jmp     0b
+2:
+	testl   $0x4,   %ecx /* is it the done indicator */
+	jz      2f
+	jmp     3f
+2:
+	testl   $0x8,   %ecx /* is it the source indicator */
+	jz      0b	     /* Ignore it otherwise */
+	movl    %ecx,   %esi /* For every source page do a copy */
+	andl    $0xfffff000, %esi
+
+	movl    $1024, %ecx
+	rep ; movsl
+	jmp     0b
+
+3:
+
+	/* To be certain of avoiding problems with self-modifying code
+	 * I need to execute a serializing instruction here.
+	 * So I flush the TLB, it's handy, and not processor dependent.
+	 */
+	xorl	%eax, %eax
+	movl	%eax, %cr3
+
+	/* set all of the registers to known values */
+	/* leave %esp alone */
+
+	xorl	%eax, %eax
+	xorl	%ebx, %ebx
+	xorl    %ecx, %ecx
+	xorl    %edx, %edx
+	xorl    %esi, %esi
+	xorl    %edi, %edi
+	xorl    %ebp, %ebp
+	ret
+relocate_new_kernel_end:
+
+	.globl relocate_new_kernel_size
+relocate_new_kernel_size:
+	.long relocate_new_kernel_end - relocate_new_kernel
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index 2bfbdde..7306353 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -23,8 +23,10 @@
  * This file handles the architecture-dependent parts of initialization
  */
 
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/mmzone.h>
 #include <linux/tty.h>
 #include <linux/ioport.h>
 #include <linux/acpi.h>
@@ -41,7 +43,12 @@
 #include <linux/init.h>
 #include <linux/edd.h>
 #include <linux/nodemask.h>
+#include <linux/kexec.h>
+#include <linux/crash_dump.h>
+
 #include <video/edid.h>
+
+#include <asm/apic.h>
 #include <asm/e820.h>
 #include <asm/mpspec.h>
 #include <asm/setup.h>
@@ -53,12 +60,15 @@
 #include "setup_arch_pre.h"
 #include <bios_ebda.h>
 
+/* Forward Declaration. */
+void __init find_max_pfn(void);
+
 /* This value is set up by the early boot code to point to the value
    immediately after the boot time page tables.  It contains a *physical*
    address, and must not be in the .bss segment! */
 unsigned long init_pg_tables_end __initdata = ~0UL;
 
-int disable_pse __initdata = 0;
+int disable_pse __devinitdata = 0;
 
 /*
  * Machine setup..
@@ -73,6 +83,7 @@
 struct cpuinfo_x86 new_cpu_data __initdata = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
 /* common cpu data for all cpus */
 struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+EXPORT_SYMBOL(boot_cpu_data);
 
 unsigned long mmu_cr4_features;
 
@@ -90,12 +101,18 @@
 
 /* for MCA, but anyone else can use it if they want */
 unsigned int machine_id;
+#ifdef CONFIG_MCA
+EXPORT_SYMBOL(machine_id);
+#endif
 unsigned int machine_submodel_id;
 unsigned int BIOS_revision;
 unsigned int mca_pentium_flag;
 
 /* For PCI or other memory-mapped resources */
 unsigned long pci_mem_start = 0x10000000;
+#ifdef CONFIG_PCI
+EXPORT_SYMBOL(pci_mem_start);
+#endif
 
 /* Boot loader ID as an integer, for the benefit of proc_dointvec */
 int bootloader_type;
@@ -107,14 +124,26 @@
  * Setup options
  */
 struct drive_info_struct { char dummy[32]; } drive_info;
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD) || \
+    defined(CONFIG_BLK_DEV_IDE_MODULE) || defined(CONFIG_BLK_DEV_HD_MODULE)
+EXPORT_SYMBOL(drive_info);
+#endif
 struct screen_info screen_info;
+#ifdef CONFIG_VT
+EXPORT_SYMBOL(screen_info);
+#endif
 struct apm_info apm_info;
+EXPORT_SYMBOL(apm_info);
 struct sys_desc_table_struct {
 	unsigned short length;
 	unsigned char table[0];
 };
 struct edid_info edid_info;
 struct ist_info ist_info;
+#if defined(CONFIG_X86_SPEEDSTEP_SMI) || \
+	defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE)
+EXPORT_SYMBOL(ist_info);
+#endif
 struct e820map e820;
 
 extern void early_cpu_init(void);
@@ -711,6 +740,15 @@
 			if (to != command_line)
 				to--;
 			if (!memcmp(from+7, "exactmap", 8)) {
+#ifdef CONFIG_CRASH_DUMP
+				/* If we are doing a crash dump, we
+				 * still need to know the real mem
+				 * size before original memory map is
+				 * reset.
+				 */
+				find_max_pfn();
+				saved_max_pfn = max_pfn;
+#endif
 				from += 8+7;
 				e820.nr_map = 0;
 				userdef = 1;
@@ -814,6 +852,44 @@
 #endif /* CONFIG_X86_LOCAL_APIC */
 #endif /* CONFIG_ACPI_BOOT */
 
+#ifdef CONFIG_X86_LOCAL_APIC
+		/* enable local APIC */
+		else if (!memcmp(from, "lapic", 5))
+			lapic_enable();
+
+		/* disable local APIC */
+		else if (!memcmp(from, "nolapic", 6))
+			lapic_disable();
+#endif /* CONFIG_X86_LOCAL_APIC */
+
+#ifdef CONFIG_KEXEC
+		/* crashkernel=size@addr specifies the location to reserve for
+		 * a crash kernel.  By reserving this memory we guarantee
+		 * that linux never set's it up as a DMA target.
+		 * Useful for holding code to do something appropriate
+		 * after a kernel panic.
+		 */
+		else if (!memcmp(from, "crashkernel=", 12)) {
+			unsigned long size, base;
+			size = memparse(from+12, &from);
+			if (*from == '@') {
+				base = memparse(from+1, &from);
+				/* FIXME: Do I want a sanity check
+				 * to validate the memory range?
+				 */
+				crashk_res.start = base;
+				crashk_res.end   = base + size - 1;
+			}
+		}
+#endif
+#ifdef CONFIG_CRASH_DUMP
+		/* elfcorehdr= specifies the location of elf core header
+		 * stored by the crashed kernel.
+		 */
+		else if (!memcmp(from, "elfcorehdr=", 11))
+			elfcorehdr_addr = memparse(from+11, &from);
+#endif
+
 		/*
 		 * highmem=size forces highmem to be exactly 'size' bytes.
 		 * This works even on boxes that have no highmem otherwise.
@@ -1022,7 +1098,7 @@
 		reserve_bootmem(addr, PAGE_SIZE);	
 }
 
-#ifndef CONFIG_DISCONTIGMEM
+#ifndef CONFIG_NEED_MULTIPLE_NODES
 void __init setup_bootmem_allocator(void);
 static unsigned long __init setup_memory(void)
 {
@@ -1072,9 +1148,9 @@
 	free_area_init(zones_size);
 }
 #else
-extern unsigned long setup_memory(void);
+extern unsigned long __init setup_memory(void);
 extern void zone_sizes_init(void);
-#endif /* !CONFIG_DISCONTIGMEM */
+#endif /* !CONFIG_NEED_MULTIPLE_NODES */
 
 void __init setup_bootmem_allocator(void)
 {
@@ -1092,8 +1168,8 @@
 	 * the (very unlikely) case of us accidentally initializing the
 	 * bootmem allocator with an invalid RAM area.
 	 */
-	reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(min_low_pfn) +
-			 bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY));
+	reserve_bootmem(__PHYSICAL_START, (PFN_PHYS(min_low_pfn) +
+			 bootmap_size + PAGE_SIZE-1) - (__PHYSICAL_START));
 
 	/*
 	 * reserve physical page 0 - it's a special BIOS page on many boxes,
@@ -1149,6 +1225,11 @@
 		}
 	}
 #endif
+#ifdef CONFIG_KEXEC
+	if (crashk_res.start != crashk_res.end)
+		reserve_bootmem(crashk_res.start,
+			crashk_res.end - crashk_res.start + 1);
+#endif
 }
 
 /*
@@ -1202,6 +1283,9 @@
 			 */
 			request_resource(res, code_resource);
 			request_resource(res, data_resource);
+#ifdef CONFIG_KEXEC
+			request_resource(res, &crashk_res);
+#endif
 		}
 	}
 }
@@ -1475,6 +1559,7 @@
 #endif
 	paging_init();
 	remapped_pgdat_init();
+	sparse_init();
 	zone_sizes_init();
 
 	/*
diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
index ea46d02..89ef7ad 100644
--- a/arch/i386/kernel/signal.c
+++ b/arch/i386/kernel/signal.c
@@ -346,8 +346,8 @@
 extern void __user __kernel_sigreturn;
 extern void __user __kernel_rt_sigreturn;
 
-static void setup_frame(int sig, struct k_sigaction *ka,
-			sigset_t *set, struct pt_regs * regs)
+static int setup_frame(int sig, struct k_sigaction *ka,
+		       sigset_t *set, struct pt_regs * regs)
 {
 	void __user *restorer;
 	struct sigframe __user *frame;
@@ -429,13 +429,14 @@
 		current->comm, current->pid, frame, regs->eip, frame->pretcode);
 #endif
 
-	return;
+	return 1;
 
 give_sigsegv:
 	force_sigsegv(sig, current);
+	return 0;
 }
 
-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 			   sigset_t *set, struct pt_regs * regs)
 {
 	void __user *restorer;
@@ -522,20 +523,23 @@
 		current->comm, current->pid, frame, regs->eip, frame->pretcode);
 #endif
 
-	return;
+	return 1;
 
 give_sigsegv:
 	force_sigsegv(sig, current);
+	return 0;
 }
 
 /*
  * OK, we're invoking a handler
  */	
 
-static void
+static int
 handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
 	      sigset_t *oldset,	struct pt_regs * regs)
 {
+	int ret;
+
 	/* Are we from a system call? */
 	if (regs->orig_eax >= 0) {
 		/* If so, check system call restarting.. */
@@ -569,17 +573,19 @@
 
 	/* Set up the stack frame */
 	if (ka->sa.sa_flags & SA_SIGINFO)
-		setup_rt_frame(sig, ka, info, oldset, regs);
+		ret = setup_rt_frame(sig, ka, info, oldset, regs);
 	else
-		setup_frame(sig, ka, oldset, regs);
+		ret = setup_frame(sig, ka, oldset, regs);
 
-	if (!(ka->sa.sa_flags & SA_NODEFER)) {
+	if (ret && !(ka->sa.sa_flags & SA_NODEFER)) {
 		spin_lock_irq(&current->sighand->siglock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
 		sigaddset(&current->blocked,sig);
 		recalc_sigpending();
 		spin_unlock_irq(&current->sighand->siglock);
 	}
+
+	return ret;
 }
 
 /*
@@ -599,13 +605,11 @@
 	 * kernel mode. Just return without doing anything
 	 * if so.
 	 */
-	if ((regs->xcs & 3) != 3)
+	if (!user_mode(regs))
 		return 1;
 
-	if (current->flags & PF_FREEZE) {
-		refrigerator(0);
+	if (try_to_freeze())
 		goto no_signal;
-	}
 
 	if (!oldset)
 		oldset = &current->blocked;
@@ -618,12 +622,11 @@
 		 * inside the kernel.
 		 */
 		if (unlikely(current->thread.debugreg[7])) {
-			loaddebug(&current->thread, 7);
+			set_debugreg(current->thread.debugreg[7], 7);
 		}
 
 		/* Whee!  Actually deliver the signal.  */
-		handle_signal(signr, &info, &ka, oldset, regs);
-		return 1;
+		return handle_signal(signr, &info, &ka, oldset, regs);
 	}
 
  no_signal:
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
index 6223c33..cec4bde 100644
--- a/arch/i386/kernel/smp.c
+++ b/arch/i386/kernel/smp.c
@@ -19,6 +19,8 @@
 #include <linux/mc146818rtc.h>
 #include <linux/cache.h>
 #include <linux/interrupt.h>
+#include <linux/cpu.h>
+#include <linux/module.h>
 
 #include <asm/mtrr.h>
 #include <asm/tlbflush.h>
@@ -163,7 +165,7 @@
 	unsigned long flags;
 
 	local_irq_save(flags);
-		
+	WARN_ON(mask & ~cpus_addr(cpu_online_map)[0]);
 	/*
 	 * Wait for idle.
 	 */
@@ -345,21 +347,21 @@
 static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
 						unsigned long va)
 {
-	cpumask_t tmp;
 	/*
 	 * A couple of (to be removed) sanity checks:
 	 *
-	 * - we do not send IPIs to not-yet booted CPUs.
 	 * - current CPU must not be in mask
 	 * - mask must exist :)
 	 */
 	BUG_ON(cpus_empty(cpumask));
-
-	cpus_and(tmp, cpumask, cpu_online_map);
-	BUG_ON(!cpus_equal(cpumask, tmp));
 	BUG_ON(cpu_isset(smp_processor_id(), cpumask));
 	BUG_ON(!mm);
 
+	/* If a CPU which we ran on has gone down, OK. */
+	cpus_and(cpumask, cpumask, cpu_online_map);
+	if (cpus_empty(cpumask))
+		return;
+
 	/*
 	 * i'm not happy about this global shared spinlock in the
 	 * MM hot path, but we'll see how contended it is.
@@ -452,6 +454,7 @@
 
 	preempt_enable();
 }
+EXPORT_SYMBOL(flush_tlb_page);
 
 static void do_flush_tlb_all(void* info)
 {
@@ -474,6 +477,7 @@
  */
 void smp_send_reschedule(int cpu)
 {
+	WARN_ON(cpu_is_offline(cpu));
 	send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR);
 }
 
@@ -491,6 +495,16 @@
 	int wait;
 };
 
+void lock_ipi_call_lock(void)
+{
+	spin_lock_irq(&call_lock);
+}
+
+void unlock_ipi_call_lock(void)
+{
+	spin_unlock_irq(&call_lock);
+}
+
 static struct call_data_struct * call_data;
 
 /*
@@ -514,10 +528,15 @@
  */
 {
 	struct call_data_struct data;
-	int cpus = num_online_cpus()-1;
+	int cpus;
 
-	if (!cpus)
+	/* Holding any lock stops cpus from going down. */
+	spin_lock(&call_lock);
+	cpus = num_online_cpus() - 1;
+	if (!cpus) {
+		spin_unlock(&call_lock);
 		return 0;
+	}
 
 	/* Can deadlock when called with interrupts disabled */
 	WARN_ON(irqs_disabled());
@@ -529,7 +548,6 @@
 	if (wait)
 		atomic_set(&data.finished, 0);
 
-	spin_lock(&call_lock);
 	call_data = &data;
 	mb();
 	
@@ -547,6 +565,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(smp_call_function);
 
 static void stop_this_cpu (void * dummy)
 {
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index bc1bb69..d66bf48 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -44,6 +44,9 @@
 #include <linux/smp_lock.h>
 #include <linux/irq.h>
 #include <linux/bootmem.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <linux/percpu.h>
 
 #include <linux/delay.h>
 #include <linux/mc146818rtc.h>
@@ -56,24 +59,46 @@
 #include <smpboot_hooks.h>
 
 /* Set if we find a B stepping CPU */
-static int __initdata smp_b_stepping;
+static int __devinitdata smp_b_stepping;
 
 /* Number of siblings per CPU package */
 int smp_num_siblings = 1;
-int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */
+#ifdef CONFIG_X86_HT
+EXPORT_SYMBOL(smp_num_siblings);
+#endif
+
+/* Package ID of each logical CPU */
+int phys_proc_id[NR_CPUS] = {[0 ... NR_CPUS-1] = BAD_APICID};
 EXPORT_SYMBOL(phys_proc_id);
-int cpu_core_id[NR_CPUS]; /* Core ID of each logical CPU */
+
+/* Core ID of each logical CPU */
+int cpu_core_id[NR_CPUS] = {[0 ... NR_CPUS-1] = BAD_APICID};
 EXPORT_SYMBOL(cpu_core_id);
 
+cpumask_t cpu_sibling_map[NR_CPUS];
+EXPORT_SYMBOL(cpu_sibling_map);
+
+cpumask_t cpu_core_map[NR_CPUS];
+EXPORT_SYMBOL(cpu_core_map);
+
 /* bitmap of online cpus */
 cpumask_t cpu_online_map;
+EXPORT_SYMBOL(cpu_online_map);
 
 cpumask_t cpu_callin_map;
 cpumask_t cpu_callout_map;
+EXPORT_SYMBOL(cpu_callout_map);
 static cpumask_t smp_commenced_mask;
 
+/* TSC's upper 32 bits can't be written in eariler CPU (before prescott), there
+ * is no way to resync one AP against BP. TBD: for prescott and above, we
+ * should use IA64's algorithm
+ */
+static int __devinitdata tsc_sync_disabled;
+
 /* Per CPU bogomips and other parameters */
 struct cpuinfo_x86 cpu_data[NR_CPUS] __cacheline_aligned;
+EXPORT_SYMBOL(cpu_data);
 
 u8 x86_cpu_to_apicid[NR_CPUS] =
 			{ [0 ... NR_CPUS-1] = 0xff };
@@ -90,13 +115,16 @@
 
 static void map_cpu_to_logical_apicid(void);
 
+/* State of each CPU. */
+DEFINE_PER_CPU(int, cpu_state) = { 0 };
+
 /*
  * Currently trivial. Write the real->protected mode
  * bootstrap into the page concerned. The caller
  * has made sure it's suitably aligned.
  */
 
-static unsigned long __init setup_trampoline(void)
+static unsigned long __devinit setup_trampoline(void)
 {
 	memcpy(trampoline_base, trampoline_data, trampoline_end - trampoline_data);
 	return virt_to_phys(trampoline_base);
@@ -126,7 +154,7 @@
  * a given CPU
  */
 
-static void __init smp_store_cpu_info(int id)
+static void __devinit smp_store_cpu_info(int id)
 {
 	struct cpuinfo_x86 *c = cpu_data + id;
 
@@ -199,7 +227,7 @@
 	unsigned long long t0;
 	unsigned long long sum, avg;
 	long long delta;
-	unsigned long one_usec;
+	unsigned int one_usec;
 	int buggy = 0;
 
 	printk(KERN_INFO "checking TSC synchronization across %u CPUs: ", num_booting_cpus());
@@ -320,7 +348,7 @@
 
 static atomic_t init_deasserted;
 
-static void __init smp_callin(void)
+static void __devinit smp_callin(void)
 {
 	int cpuid, phys_id;
 	unsigned long timeout;
@@ -405,16 +433,48 @@
 	/*
 	 *      Synchronize the TSC with the BP
 	 */
-	if (cpu_has_tsc && cpu_khz)
+	if (cpu_has_tsc && cpu_khz && !tsc_sync_disabled)
 		synchronize_tsc_ap();
 }
 
 static int cpucount;
 
+static inline void
+set_cpu_sibling_map(int cpu)
+{
+	int i;
+
+	if (smp_num_siblings > 1) {
+		for (i = 0; i < NR_CPUS; i++) {
+			if (!cpu_isset(i, cpu_callout_map))
+				continue;
+			if (cpu_core_id[cpu] == cpu_core_id[i]) {
+				cpu_set(i, cpu_sibling_map[cpu]);
+				cpu_set(cpu, cpu_sibling_map[i]);
+			}
+		}
+	} else {
+		cpu_set(cpu, cpu_sibling_map[cpu]);
+	}
+
+	if (current_cpu_data.x86_num_cores > 1) {
+		for (i = 0; i < NR_CPUS; i++) {
+			if (!cpu_isset(i, cpu_callout_map))
+				continue;
+			if (phys_proc_id[cpu] == phys_proc_id[i]) {
+				cpu_set(i, cpu_core_map[cpu]);
+				cpu_set(cpu, cpu_core_map[i]);
+			}
+		}
+	} else {
+		cpu_core_map[cpu] = cpu_sibling_map[cpu];
+	}
+}
+
 /*
  * Activate a secondary processor.
  */
-static void __init start_secondary(void *unused)
+static void __devinit start_secondary(void *unused)
 {
 	/*
 	 * Dont put anything before smp_callin(), SMP
@@ -437,7 +497,23 @@
 	 * the local TLBs too.
 	 */
 	local_flush_tlb();
+
+	/* This must be done before setting cpu_online_map */
+	set_cpu_sibling_map(raw_smp_processor_id());
+	wmb();
+
+	/*
+	 * We need to hold call_lock, so there is no inconsistency
+	 * between the time smp_call_function() determines number of
+	 * IPI receipients, and the time when the determination is made
+	 * for which cpus receive the IPI. Holding this
+	 * lock helps us to not include this cpu in a currently in progress
+	 * smp_call_function().
+	 */
+	lock_ipi_call_lock();
 	cpu_set(smp_processor_id(), cpu_online_map);
+	unlock_ipi_call_lock();
+	per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
 
 	/* We can take interrupts now: we're officially "up". */
 	local_irq_enable();
@@ -452,7 +528,7 @@
  * from the task structure
  * This function must not return.
  */
-void __init initialize_secondary(void)
+void __devinit initialize_secondary(void)
 {
 	/*
 	 * We don't actually need to load the full TSS,
@@ -566,7 +642,7 @@
  * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this
  * won't ... remember to clear down the APIC, etc later.
  */
-static int __init
+static int __devinit
 wakeup_secondary_cpu(int logical_apicid, unsigned long start_eip)
 {
 	unsigned long send_status = 0, accept_status = 0;
@@ -612,7 +688,7 @@
 #endif	/* WAKE_SECONDARY_VIA_NMI */
 
 #ifdef WAKE_SECONDARY_VIA_INIT
-static int __init
+static int __devinit
 wakeup_secondary_cpu(int phys_apicid, unsigned long start_eip)
 {
 	unsigned long send_status = 0, accept_status = 0;
@@ -747,8 +823,43 @@
 #endif	/* WAKE_SECONDARY_VIA_INIT */
 
 extern cpumask_t cpu_initialized;
+static inline int alloc_cpu_id(void)
+{
+	cpumask_t	tmp_map;
+	int cpu;
+	cpus_complement(tmp_map, cpu_present_map);
+	cpu = first_cpu(tmp_map);
+	if (cpu >= NR_CPUS)
+		return -ENODEV;
+	return cpu;
+}
 
-static int __init do_boot_cpu(int apicid)
+#ifdef CONFIG_HOTPLUG_CPU
+static struct task_struct * __devinitdata cpu_idle_tasks[NR_CPUS];
+static inline struct task_struct * alloc_idle_task(int cpu)
+{
+	struct task_struct *idle;
+
+	if ((idle = cpu_idle_tasks[cpu]) != NULL) {
+		/* initialize thread_struct.  we really want to avoid destroy
+		 * idle tread
+		 */
+		idle->thread.esp = (unsigned long)(((struct pt_regs *)
+			(THREAD_SIZE + (unsigned long) idle->thread_info)) - 1);
+		init_idle(idle, cpu);
+		return idle;
+	}
+	idle = fork_idle(cpu);
+
+	if (!IS_ERR(idle))
+		cpu_idle_tasks[cpu] = idle;
+	return idle;
+}
+#else
+#define alloc_idle_task(cpu) fork_idle(cpu)
+#endif
+
+static int __devinit do_boot_cpu(int apicid, int cpu)
 /*
  * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
  * (ie clustered apic addressing mode), this is a LOGICAL apic ID.
@@ -757,16 +868,17 @@
 {
 	struct task_struct *idle;
 	unsigned long boot_error;
-	int timeout, cpu;
+	int timeout;
 	unsigned long start_eip;
 	unsigned short nmi_high = 0, nmi_low = 0;
 
-	cpu = ++cpucount;
+	++cpucount;
+
 	/*
 	 * We can't use kernel_thread since we must avoid to
 	 * reschedule the child.
 	 */
-	idle = fork_idle(cpu);
+	idle = alloc_idle_task(cpu);
 	if (IS_ERR(idle))
 		panic("failed fork for CPU %d", cpu);
 	idle->thread.eip = (unsigned long) start_secondary;
@@ -833,13 +945,16 @@
 			inquire_remote_apic(apicid);
 		}
 	}
-	x86_cpu_to_apicid[cpu] = apicid;
+
 	if (boot_error) {
 		/* Try to put things back the way they were before ... */
 		unmap_cpu_to_logical_apicid(cpu);
 		cpu_clear(cpu, cpu_callout_map); /* was set here (do_boot_cpu()) */
 		cpu_clear(cpu, cpu_initialized); /* was set by cpu_init() */
 		cpucount--;
+	} else {
+		x86_cpu_to_apicid[cpu] = apicid;
+		cpu_set(cpu, cpu_present_map);
 	}
 
 	/* mark "stuck" area as not stuck */
@@ -848,6 +963,75 @@
 	return boot_error;
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+void cpu_exit_clear(void)
+{
+	int cpu = raw_smp_processor_id();
+
+	idle_task_exit();
+
+	cpucount --;
+	cpu_uninit();
+	irq_ctx_exit(cpu);
+
+	cpu_clear(cpu, cpu_callout_map);
+	cpu_clear(cpu, cpu_callin_map);
+	cpu_clear(cpu, cpu_present_map);
+
+	cpu_clear(cpu, smp_commenced_mask);
+	unmap_cpu_to_logical_apicid(cpu);
+}
+
+struct warm_boot_cpu_info {
+	struct completion *complete;
+	int apicid;
+	int cpu;
+};
+
+static void __devinit do_warm_boot_cpu(void *p)
+{
+	struct warm_boot_cpu_info *info = p;
+	do_boot_cpu(info->apicid, info->cpu);
+	complete(info->complete);
+}
+
+int __devinit smp_prepare_cpu(int cpu)
+{
+	DECLARE_COMPLETION(done);
+	struct warm_boot_cpu_info info;
+	struct work_struct task;
+	int	apicid, ret;
+
+	lock_cpu_hotplug();
+	apicid = x86_cpu_to_apicid[cpu];
+	if (apicid == BAD_APICID) {
+		ret = -ENODEV;
+		goto exit;
+	}
+
+	info.complete = &done;
+	info.apicid = apicid;
+	info.cpu = cpu;
+	INIT_WORK(&task, do_warm_boot_cpu, &info);
+
+	tsc_sync_disabled = 1;
+
+	/* init low mem mapping */
+	memcpy(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
+			sizeof(swapper_pg_dir[0]) * KERNEL_PGD_PTRS);
+	flush_tlb_all();
+	schedule_work(&task);
+	wait_for_completion(&done);
+
+	tsc_sync_disabled = 0;
+	zap_low_mappings();
+	ret = 0;
+exit:
+	unlock_cpu_hotplug();
+	return ret;
+}
+#endif
+
 static void smp_tune_scheduling (void)
 {
 	unsigned long cachesize;       /* kB   */
@@ -885,10 +1069,9 @@
 static int boot_cpu_logical_apicid;
 /* Where the IO area was mapped on multiquad, always 0 otherwise */
 void *xquad_portio;
-
-cpumask_t cpu_sibling_map[NR_CPUS] __cacheline_aligned;
-cpumask_t cpu_core_map[NR_CPUS] __cacheline_aligned;
-EXPORT_SYMBOL(cpu_core_map);
+#ifdef CONFIG_X86_NUMAQ
+EXPORT_SYMBOL(xquad_portio);
+#endif
 
 static void __init smp_boot_cpus(unsigned int max_cpus)
 {
@@ -1001,7 +1184,7 @@
 		if (max_cpus <= cpucount+1)
 			continue;
 
-		if (do_boot_cpu(apicid))
+		if (((cpu = alloc_cpu_id()) <= 0) || do_boot_cpu(apicid, cpu))
 			printk("CPU #%d not responding - cannot use it.\n",
 								apicid);
 		else
@@ -1053,44 +1236,8 @@
 		cpus_clear(cpu_core_map[cpu]);
 	}
 
-	for (cpu = 0; cpu < NR_CPUS; cpu++) {
-		struct cpuinfo_x86 *c = cpu_data + cpu;
-		int siblings = 0;
-		int i;
-		if (!cpu_isset(cpu, cpu_callout_map))
-			continue;
-
-		if (smp_num_siblings > 1) {
-			for (i = 0; i < NR_CPUS; i++) {
-				if (!cpu_isset(i, cpu_callout_map))
-					continue;
-				if (cpu_core_id[cpu] == cpu_core_id[i]) {
-					siblings++;
-					cpu_set(i, cpu_sibling_map[cpu]);
-				}
-			}
-		} else {
-			siblings++;
-			cpu_set(cpu, cpu_sibling_map[cpu]);
-		}
-
-		if (siblings != smp_num_siblings) {
-			printk(KERN_WARNING "WARNING: %d siblings found for CPU%d, should be %d\n", siblings, cpu, smp_num_siblings);
-			smp_num_siblings = siblings;
-		}
-
-		if (c->x86_num_cores > 1) {
-			for (i = 0; i < NR_CPUS; i++) {
-				if (!cpu_isset(i, cpu_callout_map))
-					continue;
-				if (phys_proc_id[cpu] == phys_proc_id[i]) {
-					cpu_set(i, cpu_core_map[cpu]);
-				}
-			}
-		} else {
-			cpu_core_map[cpu] = cpu_sibling_map[cpu];
-		}
-	}
+	cpu_set(0, cpu_sibling_map[0]);
+	cpu_set(0, cpu_core_map[0]);
 
 	smpboot_setup_io_apic();
 
@@ -1107,6 +1254,9 @@
    who understands all this stuff should rewrite it properly. --RR 15/Jul/02 */
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
+	smp_commenced_mask = cpumask_of_cpu(0);
+	cpu_callin_map = cpumask_of_cpu(0);
+	mb();
 	smp_boot_cpus(max_cpus);
 }
 
@@ -1114,23 +1264,98 @@
 {
 	cpu_set(smp_processor_id(), cpu_online_map);
 	cpu_set(smp_processor_id(), cpu_callout_map);
+	cpu_set(smp_processor_id(), cpu_present_map);
+	per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+static void
+remove_siblinginfo(int cpu)
+{
+	int sibling;
+
+	for_each_cpu_mask(sibling, cpu_sibling_map[cpu])
+		cpu_clear(cpu, cpu_sibling_map[sibling]);
+	for_each_cpu_mask(sibling, cpu_core_map[cpu])
+		cpu_clear(cpu, cpu_core_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;
+}
+
+int __cpu_disable(void)
+{
+	cpumask_t map = cpu_online_map;
+	int cpu = smp_processor_id();
+
+	/*
+	 * Perhaps use cpufreq to drop frequency, but that could go
+	 * into generic code.
+ 	 *
+	 * We won't take down the boot processor on i386 due to some
+	 * interrupts only being able to be serviced by the BSP.
+	 * Especially so if we're not using an IOAPIC	-zwane
+	 */
+	if (cpu == 0)
+		return -EBUSY;
+
+	/* We enable the timer again on the exit path of the death loop */
+	disable_APIC_timer();
+	/* Allow any queued timer interrupts to get serviced */
+	local_irq_enable();
+	mdelay(1);
+	local_irq_disable();
+
+	remove_siblinginfo(cpu);
+
+	cpu_clear(cpu, map);
+	fixup_irqs(map);
+	/* It's now safe to remove this processor from the online map */
+	cpu_clear(cpu, cpu_online_map);
+	return 0;
+}
+
+void __cpu_die(unsigned int cpu)
+{
+	/* We don't do anything here: idle task is faking death itself. */
+	unsigned int i;
+
+	for (i = 0; i < 10; i++) {
+		/* 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);
+			return;
+		}
+		current->state = TASK_UNINTERRUPTIBLE;
+		schedule_timeout(HZ/10);
+	}
+ 	printk(KERN_ERR "CPU %u didn't die...\n", cpu);
+}
+#else /* ... !CONFIG_HOTPLUG_CPU */
+int __cpu_disable(void)
+{
+	return -ENOSYS;
+}
+
+void __cpu_die(unsigned int cpu)
+{
+	/* We said "no" in __cpu_disable */
+	BUG();
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
 int __devinit __cpu_up(unsigned int cpu)
 {
-	/* This only works at boot for x86.  See "rewrite" above. */
-	if (cpu_isset(cpu, smp_commenced_mask)) {
-		local_irq_enable();
-		return -ENOSYS;
-	}
-
 	/* In case one didn't come up */
 	if (!cpu_isset(cpu, cpu_callin_map)) {
+		printk(KERN_DEBUG "skipping cpu%d, didn't come online\n", cpu);
 		local_irq_enable();
 		return -EIO;
 	}
 
 	local_irq_enable();
+	per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
 	/* Unleash the CPU! */
 	cpu_set(cpu, smp_commenced_mask);
 	while (!cpu_isset(cpu, cpu_online_map))
@@ -1144,10 +1369,12 @@
 	setup_ioapic_dest();
 #endif
 	zap_low_mappings();
+#ifndef CONFIG_HOTPLUG_CPU
 	/*
 	 * Disable executability of the SMP trampoline:
 	 */
 	set_kernel_exec((unsigned long)trampoline_base, trampoline_exec);
+#endif
 }
 
 void __init smp_intr_init(void)
diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S
index 6cd1ed3..3db9a04 100644
--- a/arch/i386/kernel/syscall_table.S
+++ b/arch/i386/kernel/syscall_table.S
@@ -251,7 +251,7 @@
 	.long sys_io_submit
 	.long sys_io_cancel
 	.long sys_fadvise64	/* 250 */
-	.long sys_ni_syscall
+	.long sys_set_zone_reclaim
 	.long sys_exit_group
 	.long sys_lookup_dcookie
 	.long sys_epoll_create
@@ -283,9 +283,11 @@
 	.long sys_mq_timedreceive	/* 280 */
 	.long sys_mq_notify
 	.long sys_mq_getsetattr
-	.long sys_ni_syscall		/* reserved for kexec */
+	.long sys_kexec_load
 	.long sys_waitid
 	.long sys_ni_syscall		/* 285 */ /* available */
 	.long sys_add_key
 	.long sys_request_key
 	.long sys_keyctl
+	.long sys_ioprio_set
+	.long sys_ioprio_get		/* 290 */
diff --git a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c
index 960d8bd..0bada18 100644
--- a/arch/i386/kernel/sysenter.c
+++ b/arch/i386/kernel/sysenter.c
@@ -21,11 +21,16 @@
 
 extern asmlinkage void sysenter_entry(void);
 
-void enable_sep_cpu(void *info)
+void enable_sep_cpu(void)
 {
 	int cpu = get_cpu();
 	struct tss_struct *tss = &per_cpu(init_tss, cpu);
 
+	if (!boot_cpu_has(X86_FEATURE_SEP)) {
+		put_cpu();
+		return;
+	}
+
 	tss->ss1 = __KERNEL_CS;
 	tss->esp1 = sizeof(struct tss_struct) + (unsigned long) tss;
 	wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0);
@@ -41,7 +46,7 @@
 extern const char vsyscall_int80_start, vsyscall_int80_end;
 extern const char vsyscall_sysenter_start, vsyscall_sysenter_end;
 
-static int __init sysenter_setup(void)
+int __init sysenter_setup(void)
 {
 	void *page = (void *)get_zeroed_page(GFP_ATOMIC);
 
@@ -58,8 +63,5 @@
 	       &vsyscall_sysenter_start,
 	       &vsyscall_sysenter_end - &vsyscall_sysenter_start);
 
-	on_each_cpu(enable_sep_cpu, NULL, 1, 1);
 	return 0;
 }
-
-__initcall(sysenter_setup);
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index a0dcb7c..e68d9fd 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -77,11 +77,13 @@
 
 EXPORT_SYMBOL(jiffies_64);
 
-unsigned long cpu_khz;	/* Detected as we calibrate the TSC */
+unsigned int cpu_khz;	/* Detected as we calibrate the TSC */
+EXPORT_SYMBOL(cpu_khz);
 
 extern unsigned long wall_jiffies;
 
 DEFINE_SPINLOCK(rtc_lock);
+EXPORT_SYMBOL(rtc_lock);
 
 DEFINE_SPINLOCK(i8253_lock);
 EXPORT_SYMBOL(i8253_lock);
@@ -324,6 +326,8 @@
 
 	return retval;
 }
+EXPORT_SYMBOL(get_cmos_time);
+
 static void sync_cmos_clock(unsigned long dummy);
 
 static struct timer_list sync_cmos_timer =
diff --git a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c
index 10a0cbb..658c062 100644
--- a/arch/i386/kernel/time_hpet.c
+++ b/arch/i386/kernel/time_hpet.c
@@ -50,7 +50,7 @@
  * comparator value and continue. Next tick can be caught by checking
  * for a change in the comparator value. Used in apic.c.
  */
-static void __init wait_hpet_tick(void)
+static void __devinit wait_hpet_tick(void)
 {
 	unsigned int start_cmp_val, end_cmp_val;
 
diff --git a/arch/i386/kernel/timers/common.c b/arch/i386/kernel/timers/common.c
index 8e20121..8163fe0 100644
--- a/arch/i386/kernel/timers/common.c
+++ b/arch/i386/kernel/timers/common.c
@@ -86,7 +86,7 @@
 #define CALIBRATE_CNT_HPET 	(5 * hpet_tick)
 #define CALIBRATE_TIME_HPET 	(5 * KERNEL_TICK_USEC)
 
-unsigned long __init calibrate_tsc_hpet(unsigned long *tsc_hpet_quotient_ptr)
+unsigned long __devinit calibrate_tsc_hpet(unsigned long *tsc_hpet_quotient_ptr)
 {
 	unsigned long tsc_startlow, tsc_starthigh;
 	unsigned long tsc_endlow, tsc_endhigh;
@@ -139,6 +139,15 @@
 }
 #endif
 
+
+unsigned long read_timer_tsc(void)
+{
+	unsigned long retval;
+	rdtscl(retval);
+	return retval;
+}
+
+
 /* calculate cpu_khz */
 void init_cpu_khz(void)
 {
@@ -154,7 +163,8 @@
 		       		:"=a" (cpu_khz), "=d" (edx)
         	       		:"r" (tsc_quotient),
 	                	"0" (eax), "1" (edx));
-				printk("Detected %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000);
+				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
index a3d6a28..7e39ed8 100644
--- a/arch/i386/kernel/timers/timer.c
+++ b/arch/i386/kernel/timers/timer.c
@@ -64,3 +64,12 @@
 	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_hpet.c b/arch/i386/kernel/timers/timer_hpet.c
index f778f47..d766e09 100644
--- a/arch/i386/kernel/timers/timer_hpet.c
+++ b/arch/i386/kernel/timers/timer_hpet.c
@@ -158,7 +158,7 @@
 			{	unsigned long eax=0, edx=1000;
 				ASM_DIV64_REG(cpu_khz, edx, tsc_quotient,
 						eax, edx);
-				printk("Detected %lu.%03lu MHz processor.\n",
+				printk("Detected %u.%03u MHz processor.\n",
 					cpu_khz / 1000, cpu_khz % 1000);
 			}
 			set_cyc2ns_scale(cpu_khz/1000);
@@ -186,6 +186,7 @@
 	.get_offset =		get_offset_hpet,
 	.monotonic_clock =	monotonic_clock_hpet,
 	.delay = 		delay_hpet,
+	.read_timer = 		read_timer_tsc,
 };
 
 struct init_timer_opts __initdata timer_hpet_init = {
diff --git a/arch/i386/kernel/timers/timer_pm.c b/arch/i386/kernel/timers/timer_pm.c
index d77f220..4ef20e6 100644
--- a/arch/i386/kernel/timers/timer_pm.c
+++ b/arch/i386/kernel/timers/timer_pm.c
@@ -246,6 +246,7 @@
 	.get_offset		= get_offset_pmtmr,
 	.monotonic_clock 	= monotonic_clock_pmtmr,
 	.delay 			= delay_pmtmr,
+	.read_timer 		= read_timer_tsc,
 };
 
 struct init_timer_opts __initdata timer_pmtmr_init = {
diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c
index 180444d..f46e625 100644
--- a/arch/i386/kernel/timers/timer_tsc.c
+++ b/arch/i386/kernel/timers/timer_tsc.c
@@ -33,7 +33,7 @@
 
 static inline void cpufreq_delayed_get(void);
 
-int tsc_disable __initdata = 0;
+int tsc_disable __devinitdata = 0;
 
 extern spinlock_t i8253_lock;
 
@@ -256,7 +256,7 @@
 
 #ifndef CONFIG_SMP
 static unsigned long fast_gettimeoffset_ref = 0;
-static unsigned long cpu_khz_ref = 0;
+static unsigned int cpu_khz_ref = 0;
 #endif
 
 static int
@@ -323,7 +323,7 @@
 int recalibrate_cpu_khz(void)
 {
 #ifndef CONFIG_SMP
-	unsigned long cpu_khz_old = cpu_khz;
+	unsigned int cpu_khz_old = cpu_khz;
 
 	if (cpu_has_tsc) {
 		init_cpu_khz();
@@ -534,7 +534,8 @@
 		       		:"=a" (cpu_khz), "=d" (edx)
         	       		:"r" (tsc_quotient),
 	                	"0" (eax), "1" (edx));
-				printk("Detected %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000);
+				printk("Detected %u.%03u MHz processor.\n",
+					cpu_khz / 1000, cpu_khz % 1000);
 			}
 			set_cyc2ns_scale(cpu_khz/1000);
 			return 0;
@@ -572,6 +573,7 @@
 	.get_offset = get_offset_tsc,
 	.monotonic_clock = monotonic_clock_tsc,
 	.delay = delay_tsc,
+	.read_timer = read_timer_tsc,
 };
 
 struct init_timer_opts __initdata timer_tsc_init = {
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 00c6341..a61f33d 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -27,6 +27,7 @@
 #include <linux/ptrace.h>
 #include <linux/utsname.h>
 #include <linux/kprobes.h>
+#include <linux/kexec.h>
 
 #ifdef CONFIG_EISA
 #include <linux/ioport.h>
@@ -104,6 +105,7 @@
 	spin_unlock_irqrestore(&die_notifier_lock, flags);
 	return err;
 }
+EXPORT_SYMBOL(register_die_notifier);
 
 static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
 {
@@ -209,7 +211,7 @@
 
 	esp = (unsigned long) (&regs->esp);
 	ss = __KERNEL_DS;
-	if (regs->xcs & 3) {
+	if (user_mode(regs)) {
 		in_kernel = 0;
 		esp = regs->esp;
 		ss = regs->xss & 0xffff;
@@ -233,22 +235,22 @@
 	 * time of the fault..
 	 */
 	if (in_kernel) {
-		u8 *eip;
+		u8 __user *eip;
 
 		printk("\nStack: ");
 		show_stack(NULL, (unsigned long*)esp);
 
 		printk("Code: ");
 
-		eip = (u8 *)regs->eip - 43;
+		eip = (u8 __user *)regs->eip - 43;
 		for (i = 0; i < 64; i++, eip++) {
 			unsigned char c;
 
-			if (eip < (u8 *)PAGE_OFFSET || __get_user(c, eip)) {
+			if (eip < (u8 __user *)PAGE_OFFSET || __get_user(c, eip)) {
 				printk(" Bad EIP value.");
 				break;
 			}
-			if (eip == (u8 *)regs->eip)
+			if (eip == (u8 __user *)regs->eip)
 				printk("<%02x> ", c);
 			else
 				printk("%02x ", c);
@@ -265,20 +267,20 @@
 	char c;
 	unsigned long eip;
 
-	if (regs->xcs & 3)
+	if (user_mode(regs))
 		goto no_bug;		/* Not in kernel */
 
 	eip = regs->eip;
 
 	if (eip < PAGE_OFFSET)
 		goto no_bug;
-	if (__get_user(ud2, (unsigned short *)eip))
+	if (__get_user(ud2, (unsigned short __user *)eip))
 		goto no_bug;
 	if (ud2 != 0x0b0f)
 		goto no_bug;
-	if (__get_user(line, (unsigned short *)(eip + 2)))
+	if (__get_user(line, (unsigned short __user *)(eip + 2)))
 		goto bug;
-	if (__get_user(file, (char **)(eip + 4)) ||
+	if (__get_user(file, (char * __user *)(eip + 4)) ||
 		(unsigned long)file < PAGE_OFFSET || __get_user(c, file))
 		file = "<bad filename>";
 
@@ -293,6 +295,9 @@
 	printk("Kernel BUG\n");
 }
 
+/* This is gone through when something in the kernel
+ * has done something bad and is about to be terminated.
+*/
 void die(const char * str, struct pt_regs * regs, long err)
 {
 	static struct {
@@ -306,7 +311,7 @@
 	};
 	static int die_counter;
 
-	if (die.lock_owner != _smp_processor_id()) {
+	if (die.lock_owner != raw_smp_processor_id()) {
 		console_verbose();
 		spin_lock_irq(&die.lock);
 		die.lock_owner = smp_processor_id();
@@ -340,6 +345,10 @@
 	bust_spinlocks(0);
 	die.lock_owner = -1;
 	spin_unlock_irq(&die.lock);
+
+	if (kexec_should_crash(current))
+		crash_kexec(regs);
+
 	if (in_interrupt())
 		panic("Fatal exception in interrupt");
 
@@ -353,26 +362,27 @@
 
 static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
 {
-	if (!(regs->eflags & VM_MASK) && !(3 & regs->xcs))
+	if (!user_mode_vm(regs))
 		die(str, regs, err);
 }
 
 static void do_trap(int trapnr, int signr, char *str, int vm86,
 			   struct pt_regs * regs, long error_code, siginfo_t *info)
 {
+	struct task_struct *tsk = current;
+	tsk->thread.error_code = error_code;
+	tsk->thread.trap_no = trapnr;
+
 	if (regs->eflags & VM_MASK) {
 		if (vm86)
 			goto vm86_trap;
 		goto trap_signal;
 	}
 
-	if (!(regs->xcs & 3))
+	if (!user_mode(regs))
 		goto kernel_trap;
 
 	trap_signal: {
-		struct task_struct *tsk = current;
-		tsk->thread.error_code = error_code;
-		tsk->thread.trap_no = trapnr;
 		if (info)
 			force_sig_info(signr, info, tsk);
 		else
@@ -485,10 +495,13 @@
 	}
 	put_cpu();
 
+	current->thread.error_code = error_code;
+	current->thread.trap_no = 13;
+
 	if (regs->eflags & VM_MASK)
 		goto gp_in_vm86;
 
-	if (!(regs->xcs & 3))
+	if (!user_mode(regs))
 		goto gp_in_kernel;
 
 	current->thread.error_code = error_code;
@@ -569,6 +582,15 @@
 	console_silent();
 	spin_unlock(&nmi_print_lock);
 	bust_spinlocks(0);
+
+	/* If we are in kernel we are probably nested up pretty bad
+	 * and might aswell get out now while we still can.
+	*/
+	if (!user_mode(regs)) {
+		current->thread.trap_no = 2;
+		crash_kexec(regs);
+	}
+
 	do_exit(SIGSEGV);
 }
 
@@ -624,6 +646,14 @@
 	nmi_enter();
 
 	cpu = smp_processor_id();
+
+#ifdef CONFIG_HOTPLUG_CPU
+	if (!cpu_online(cpu)) {
+		nmi_exit();
+		return;
+	}
+#endif
+
 	++nmi_count(cpu);
 
 	if (!nmi_callback(regs, cpu))
@@ -636,11 +666,13 @@
 {
 	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_KPROBES
 fastcall void do_int3(struct pt_regs *regs, long error_code)
@@ -682,7 +714,7 @@
 	unsigned int condition;
 	struct task_struct *tsk = current;
 
-	__asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
+	get_debugreg(condition, 6);
 
 	if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
 					SIGTRAP) == NOTIFY_STOP)
@@ -713,7 +745,7 @@
 		 * check for kernel mode by just checking the CPL
 		 * of CS.
 		 */
-		if ((regs->xcs & 3) == 0)
+		if (!user_mode(regs))
 			goto clear_TF_reenable;
 	}
 
@@ -724,9 +756,7 @@
 	 * the signal is delivered.
 	 */
 clear_dr7:
-	__asm__("movl %0,%%db7"
-		: /* no output */
-		: "r" (0));
+	set_debugreg(0, 7);
 	return;
 
 debug_vm86:
@@ -871,9 +901,9 @@
 					  error_code);
 			return;
 		}
-		die_if_kernel("cache flush denied", regs, error_code);
 		current->thread.trap_no = 19;
 		current->thread.error_code = error_code;
+		die_if_kernel("cache flush denied", regs, error_code);
 		force_sig(SIGSEGV, current);
 	}
 }
diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S
index e0512cc..7e01a52 100644
--- a/arch/i386/kernel/vmlinux.lds.S
+++ b/arch/i386/kernel/vmlinux.lds.S
@@ -2,20 +2,23 @@
  * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
  */
 
+#define LOAD_OFFSET __PAGE_OFFSET
+
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/thread_info.h>
 #include <asm/page.h>
 
 OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
 OUTPUT_ARCH(i386)
-ENTRY(startup_32)
+ENTRY(phys_startup_32)
 jiffies = jiffies_64;
 SECTIONS
 {
-  . = __PAGE_OFFSET + 0x100000;
+  . = __KERNEL_START;
+  phys_startup_32 = startup_32 - LOAD_OFFSET;
   /* read-only */
   _text = .;			/* Text and read-only data */
-  .text : {
+  .text : AT(ADDR(.text) - LOAD_OFFSET) {
 	*(.text)
 	SCHED_TEXT
 	LOCK_TEXT
@@ -27,49 +30,55 @@
 
   . = ALIGN(16);		/* Exception table */
   __start___ex_table = .;
-  __ex_table : { *(__ex_table) }
+  __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) }
   __stop___ex_table = .;
 
   RODATA
 
   /* writeable */
-  .data : {			/* Data */
+  .data : AT(ADDR(.data) - LOAD_OFFSET) {	/* Data */
 	*(.data)
 	CONSTRUCTORS
 	}
 
   . = ALIGN(4096);
   __nosave_begin = .;
-  .data_nosave : { *(.data.nosave) }
+  .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.data.nosave) }
   . = ALIGN(4096);
   __nosave_end = .;
 
   . = ALIGN(4096);
-  .data.page_aligned : { *(.data.idt) }
+  .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
+	*(.data.idt)
+  }
 
   . = ALIGN(32);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+  .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
+	*(.data.cacheline_aligned)
+  }
 
   _edata = .;			/* End of data section */
 
   . = ALIGN(THREAD_SIZE);	/* init_task */
-  .data.init_task : { *(.data.init_task) }
+  .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
+	*(.data.init_task)
+  }
 
   /* will be freed after init */
   . = ALIGN(4096);		/* Init code and data */
   __init_begin = .;
-  .init.text : { 
+  .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
 	_sinittext = .;
 	*(.init.text)
 	_einittext = .;
   }
-  .init.data : { *(.init.data) }
+  .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) }
   . = ALIGN(16);
   __setup_start = .;
-  .init.setup : { *(.init.setup) }
+  .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { *(.init.setup) }
   __setup_end = .;
   __initcall_start = .;
-  .initcall.init : {
+  .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
 	*(.initcall1.init) 
 	*(.initcall2.init) 
 	*(.initcall3.init) 
@@ -80,33 +89,41 @@
   }
   __initcall_end = .;
   __con_initcall_start = .;
-  .con_initcall.init : { *(.con_initcall.init) }
+  .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
+	*(.con_initcall.init)
+  }
   __con_initcall_end = .;
   SECURITY_INIT
   . = ALIGN(4);
   __alt_instructions = .;
-  .altinstructions : { *(.altinstructions) } 
+  .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) {
+	*(.altinstructions)
+  }
   __alt_instructions_end = .; 
- .altinstr_replacement : { *(.altinstr_replacement) } 
+  .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) {
+	*(.altinstr_replacement)
+  }
   /* .exit.text is discard at runtime, not link time, to deal with references
      from .altinstructions and .eh_frame */
-  .exit.text : { *(.exit.text) }
-  .exit.data : { *(.exit.data) }
+  .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) }
+  .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) }
   . = ALIGN(4096);
   __initramfs_start = .;
-  .init.ramfs : { *(.init.ramfs) }
+  .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { *(.init.ramfs) }
   __initramfs_end = .;
   . = ALIGN(32);
   __per_cpu_start = .;
-  .data.percpu  : { *(.data.percpu) }
+  .data.percpu  : AT(ADDR(.data.percpu) - LOAD_OFFSET) { *(.data.percpu) }
   __per_cpu_end = .;
   . = ALIGN(4096);
   __init_end = .;
   /* freed after init ends here */
 	
   __bss_start = .;		/* BSS */
-  .bss : {
+  .bss.page_aligned : AT(ADDR(.bss.page_aligned) - LOAD_OFFSET) {
 	*(.bss.page_aligned)
+  }
+  .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
 	*(.bss)
   }
   . = ALIGN(4);
diff --git a/arch/i386/lib/dec_and_lock.c b/arch/i386/lib/dec_and_lock.c
index ab43394..8b81b25 100644
--- a/arch/i386/lib/dec_and_lock.c
+++ b/arch/i386/lib/dec_and_lock.c
@@ -8,6 +8,7 @@
  */
 
 #include <linux/spinlock.h>
+#include <linux/module.h>
 #include <asm/atomic.h>
 
 int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
@@ -38,3 +39,4 @@
 	spin_unlock(lock);
 	return 0;
 }
+EXPORT_SYMBOL(_atomic_dec_and_lock);
diff --git a/arch/i386/lib/delay.c b/arch/i386/lib/delay.c
index 080639f..c49a6ac 100644
--- a/arch/i386/lib/delay.c
+++ b/arch/i386/lib/delay.c
@@ -13,6 +13,7 @@
 #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>
@@ -34,7 +35,7 @@
 	xloops *= 4;
 	__asm__("mull %0"
 		:"=d" (xloops), "=&a" (d0)
-		:"1" (xloops),"0" (cpu_data[_smp_processor_id()].loops_per_jiffy * (HZ/4)));
+		:"1" (xloops),"0" (cpu_data[raw_smp_processor_id()].loops_per_jiffy * (HZ/4)));
         __delay(++xloops);
 }
 
@@ -47,3 +48,8 @@
 {
 	__const_udelay(nsecs * 0x00005);  /* 2**32 / 1000000000 (rounded up) */
 }
+
+EXPORT_SYMBOL(__delay);
+EXPORT_SYMBOL(__const_udelay);
+EXPORT_SYMBOL(__udelay);
+EXPORT_SYMBOL(__ndelay);
diff --git a/arch/i386/lib/mmx.c b/arch/i386/lib/mmx.c
index 01f8b1a..2afda94 100644
--- a/arch/i386/lib/mmx.c
+++ b/arch/i386/lib/mmx.c
@@ -3,6 +3,7 @@
 #include <linux/string.h>
 #include <linux/sched.h>
 #include <linux/hardirq.h>
+#include <linux/module.h>
 
 #include <asm/i387.h>
 
@@ -397,3 +398,7 @@
 	else
 		fast_copy_page(to, from);
 }
+
+EXPORT_SYMBOL(_mmx_memcpy);
+EXPORT_SYMBOL(mmx_clear_page);
+EXPORT_SYMBOL(mmx_copy_page);
diff --git a/arch/i386/lib/usercopy.c b/arch/i386/lib/usercopy.c
index 51aa2bb..4cf981d 100644
--- a/arch/i386/lib/usercopy.c
+++ b/arch/i386/lib/usercopy.c
@@ -84,6 +84,7 @@
 	__do_strncpy_from_user(dst, src, count, res);
 	return res;
 }
+EXPORT_SYMBOL(__strncpy_from_user);
 
 /**
  * strncpy_from_user: - Copy a NUL terminated string from userspace.
@@ -111,7 +112,7 @@
 		__do_strncpy_from_user(dst, src, count, res);
 	return res;
 }
-
+EXPORT_SYMBOL(strncpy_from_user);
 
 /*
  * Zero Userspace
@@ -157,6 +158,7 @@
 		__do_clear_user(to, n);
 	return n;
 }
+EXPORT_SYMBOL(clear_user);
 
 /**
  * __clear_user: - Zero a block of memory in user space, with less checking.
@@ -175,6 +177,7 @@
 	__do_clear_user(to, n);
 	return n;
 }
+EXPORT_SYMBOL(__clear_user);
 
 /**
  * strlen_user: - Get the size of a string in user space.
@@ -218,6 +221,7 @@
 		:"cc");
 	return res & mask;
 }
+EXPORT_SYMBOL(strnlen_user);
 
 #ifdef CONFIG_X86_INTEL_USERCOPY
 static unsigned long
@@ -570,6 +574,7 @@
 		n = __copy_user_intel(to, from, n);
 	return n;
 }
+EXPORT_SYMBOL(__copy_to_user_ll);
 
 unsigned long
 __copy_from_user_ll(void *to, const void __user *from, unsigned long n)
@@ -581,6 +586,7 @@
 		n = __copy_user_zeroing_intel(to, from, n);
 	return n;
 }
+EXPORT_SYMBOL(__copy_from_user_ll);
 
 /**
  * copy_to_user: - Copy a block of data into user space.
diff --git a/arch/i386/mach-default/setup.c b/arch/i386/mach-default/setup.c
index 0aa08ea..e5a1a83 100644
--- a/arch/i386/mach-default/setup.c
+++ b/arch/i386/mach-default/setup.c
@@ -10,6 +10,14 @@
 #include <asm/acpi.h>
 #include <asm/arch_hooks.h>
 
+#ifdef CONFIG_HOTPLUG_CPU
+#define DEFAULT_SEND_IPI	(1)
+#else
+#define DEFAULT_SEND_IPI	(0)
+#endif
+
+int no_broadcast=DEFAULT_SEND_IPI;
+
 /**
  * pre_intr_init_hook - initialisation prior to setting up interrupt vectors
  *
@@ -104,3 +112,22 @@
 	printk("NMI generated from unknown source!\n");
 }
 #endif
+
+static __init int no_ipi_broadcast(char *str)
+{
+	get_option(&str, &no_broadcast);
+	printk ("Using %s mode\n", no_broadcast ? "No IPI Broadcast" :
+											"IPI Broadcast");
+	return 1;
+}
+
+__setup("no_ipi_broadcast", no_ipi_broadcast);
+
+static int __init print_ipi_mode(void)
+{
+	printk ("Using IPI %s mode\n", no_broadcast ? "No-Shortcut" :
+											"Shortcut");
+	return 0;
+}
+
+late_initcall(print_ipi_mode);
diff --git a/arch/i386/mach-default/topology.c b/arch/i386/mach-default/topology.c
index 5b3e881..23395ff 100644
--- a/arch/i386/mach-default/topology.c
+++ b/arch/i386/mach-default/topology.c
@@ -73,12 +73,11 @@
 {
 	int i;
 
-	for (i = 0; i < MAX_NUMNODES; i++) {
-		if (node_online(i))
-			arch_register_node(i);
-	}
-	for (i = 0; i < NR_CPUS; i++)
-		if (cpu_possible(i)) arch_register_cpu(i);
+	for_each_online_node(i)
+		arch_register_node(i);
+
+	for_each_cpu(i)
+		arch_register_cpu(i);
 	return 0;
 }
 
@@ -88,8 +87,8 @@
 {
 	int i;
 
-	for (i = 0; i < NR_CPUS; i++)
-		if (cpu_possible(i)) arch_register_cpu(i);
+	for_each_cpu(i)
+		arch_register_cpu(i);
 	return 0;
 }
 
diff --git a/arch/i386/mach-visws/mpparse.c b/arch/i386/mach-visws/mpparse.c
index 5a22082..5f3d7e6 100644
--- a/arch/i386/mach-visws/mpparse.c
+++ b/arch/i386/mach-visws/mpparse.c
@@ -23,7 +23,6 @@
 
 /* Processor that is doing the boot up */
 unsigned int boot_cpu_physical_apicid = -1U;
-unsigned int boot_cpu_logical_apicid = -1U;
 
 /* Bitmask of physically existing CPUs */
 physid_mask_t phys_cpu_present_map;
@@ -52,10 +51,8 @@
 		(m->mpc_cpufeature & CPU_MODEL_MASK) >> 4,
 		m->mpc_apicver);
 
-	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) {
+	if (m->mpc_cpuflag & CPU_BOOTPROCESSOR)
 		boot_cpu_physical_apicid = m->mpc_apicid;
-		boot_cpu_logical_apicid = logical_apicid;
-	}
 
 	ver = m->mpc_apicver;
 	if ((ver >= 0x14 && m->mpc_apicid >= 0xff) || m->mpc_apicid >= 0xf) {
diff --git a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c
index a6e0ddd..8c85275 100644
--- a/arch/i386/mach-voyager/voyager_smp.c
+++ b/arch/i386/mach-voyager/voyager_smp.c
@@ -1288,7 +1288,7 @@
 						per_cpu(prof_counter, cpu);
 		}
 
-		update_process_times(user_mode(regs));
+		update_process_times(user_mode_vm(regs));
 	}
 
 	if( ((1<<cpu) & voyager_extended_vic_processors) == 0)
diff --git a/arch/i386/mm/Makefile b/arch/i386/mm/Makefile
index fc32725..80908b5 100644
--- a/arch/i386/mm/Makefile
+++ b/arch/i386/mm/Makefile
@@ -4,7 +4,7 @@
 
 obj-y	:= init.o pgtable.o fault.o ioremap.o extable.o pageattr.o mmap.o
 
-obj-$(CONFIG_DISCONTIGMEM)	+= discontig.o
+obj-$(CONFIG_NUMA) += discontig.o
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
 obj-$(CONFIG_HIGHMEM) += highmem.o
 obj-$(CONFIG_BOOT_IOREMAP) += boot_ioremap.o
diff --git a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c
index 1726b40..b358f07 100644
--- a/arch/i386/mm/discontig.c
+++ b/arch/i386/mm/discontig.c
@@ -29,12 +29,16 @@
 #include <linux/highmem.h>
 #include <linux/initrd.h>
 #include <linux/nodemask.h>
+#include <linux/module.h>
+#include <linux/kexec.h>
+
 #include <asm/e820.h>
 #include <asm/setup.h>
 #include <asm/mmzone.h>
 #include <bios_ebda.h>
 
 struct pglist_data *node_data[MAX_NUMNODES];
+EXPORT_SYMBOL(node_data);
 bootmem_data_t node0_bdata;
 
 /*
@@ -42,12 +46,16 @@
  *                  populated the following initialisation.
  *
  * 1) node_online_map  - the map of all nodes configured (online) in the system
- * 2) physnode_map     - the mapping between a pfn and owning node
- * 3) node_start_pfn   - the starting page frame number for a node
+ * 2) node_start_pfn   - the starting page frame number for a node
  * 3) node_end_pfn     - the ending page fram number for a node
  */
+unsigned long node_start_pfn[MAX_NUMNODES];
+unsigned long node_end_pfn[MAX_NUMNODES];
 
+
+#ifdef CONFIG_DISCONTIGMEM
 /*
+ * 4) physnode_map     - the mapping between a pfn and owning node
  * physnode_map keeps track of the physical memory layout of a generic
  * numa node on a 256Mb break (each element of the array will
  * represent 256Mb of memory and will be marked by the node id.  so,
@@ -59,6 +67,7 @@
  *     physnode_map[8- ] = -1;
  */
 s8 physnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1};
+EXPORT_SYMBOL(physnode_map);
 
 void memory_present(int nid, unsigned long start, unsigned long end)
 {
@@ -85,9 +94,7 @@
 
 	return (nr_pages + 1) * sizeof(struct page);
 }
-
-unsigned long node_start_pfn[MAX_NUMNODES];
-unsigned long node_end_pfn[MAX_NUMNODES];
+#endif
 
 extern unsigned long find_max_low_pfn(void);
 extern void find_max_pfn(void);
@@ -108,6 +115,9 @@
 void *node_remap_start_vaddr[MAX_NUMNODES];
 void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags);
 
+void *node_remap_end_vaddr[MAX_NUMNODES];
+void *node_remap_alloc_vaddr[MAX_NUMNODES];
+
 /*
  * FLAT - support for basic PC memory model with discontig enabled, essentially
  *        a single node with all available processors in it with a flat
@@ -146,6 +156,21 @@
 		BUG();
 }
 
+/* Find the owning node for a pfn. */
+int early_pfn_to_nid(unsigned long pfn)
+{
+	int nid;
+
+	for_each_node(nid) {
+		if (node_end_pfn[nid] == 0)
+			break;
+		if (node_start_pfn[nid] <= pfn && node_end_pfn[nid] >= pfn)
+			return nid;
+	}
+
+	return 0;
+}
+
 /* 
  * Allocate memory for the pg_data_t for this node via a crude pre-bootmem
  * method.  For node zero take this from the bottom of memory, for
@@ -163,6 +188,21 @@
 	}
 }
 
+void *alloc_remap(int nid, unsigned long size)
+{
+	void *allocation = node_remap_alloc_vaddr[nid];
+
+	size = ALIGN(size, L1_CACHE_BYTES);
+
+	if (!allocation || (allocation + size) >= node_remap_end_vaddr[nid])
+		return 0;
+
+	node_remap_alloc_vaddr[nid] += size;
+	memset(allocation, 0, size);
+
+	return allocation;
+}
+
 void __init remap_numa_kva(void)
 {
 	void *vaddr;
@@ -170,8 +210,6 @@
 	int node;
 
 	for_each_online_node(node) {
-		if (node == 0)
-			continue;
 		for (pfn=0; pfn < node_remap_size[node]; pfn += PTRS_PER_PTE) {
 			vaddr = node_remap_start_vaddr[node]+(pfn<<PAGE_SHIFT);
 			set_pmd_pfn((ulong) vaddr, 
@@ -185,13 +223,9 @@
 {
 	int nid;
 	unsigned long size, reserve_pages = 0;
+	unsigned long pfn;
 
 	for_each_online_node(nid) {
-		if (nid == 0)
-			continue;
-		if (!node_remap_size[nid])
-			continue;
-
 		/*
 		 * The acpi/srat node info can show hot-add memroy zones
 		 * where memory could be added but not currently present.
@@ -208,11 +242,24 @@
 		size = (size + LARGE_PAGE_BYTES - 1) / LARGE_PAGE_BYTES;
 		/* now the roundup is correct, convert to PAGE_SIZE pages */
 		size = size * PTRS_PER_PTE;
+
+		/*
+		 * Validate the region we are allocating only contains valid
+		 * pages.
+		 */
+		for (pfn = node_end_pfn[nid] - size;
+		     pfn < node_end_pfn[nid]; pfn++)
+			if (!page_is_ram(pfn))
+				break;
+
+		if (pfn != node_end_pfn[nid])
+			size = 0;
+
 		printk("Reserving %ld pages of KVA for lmem_map of node %d\n",
 				size, nid);
 		node_remap_size[nid] = size;
-		reserve_pages += size;
 		node_remap_offset[nid] = reserve_pages;
+		reserve_pages += size;
 		printk("Shrinking node %d from %ld pages to %ld pages\n",
 			nid, node_end_pfn[nid], node_end_pfn[nid] - size);
 		node_end_pfn[nid] -= size;
@@ -265,12 +312,18 @@
 			(ulong) pfn_to_kaddr(max_low_pfn));
 	for_each_online_node(nid) {
 		node_remap_start_vaddr[nid] = pfn_to_kaddr(
-			(highstart_pfn + reserve_pages) - node_remap_offset[nid]);
+				highstart_pfn + node_remap_offset[nid]);
+		/* Init the node remap allocator */
+		node_remap_end_vaddr[nid] = node_remap_start_vaddr[nid] +
+			(node_remap_size[nid] * PAGE_SIZE);
+		node_remap_alloc_vaddr[nid] = node_remap_start_vaddr[nid] +
+			ALIGN(sizeof(pg_data_t), PAGE_SIZE);
+
 		allocate_pgdat(nid);
 		printk ("node %d will remap to vaddr %08lx - %08lx\n", nid,
 			(ulong) node_remap_start_vaddr[nid],
-			(ulong) pfn_to_kaddr(highstart_pfn + reserve_pages
-			    - node_remap_offset[nid] + node_remap_size[nid]));
+			(ulong) pfn_to_kaddr(highstart_pfn
+			   + node_remap_offset[nid] + node_remap_size[nid]));
 	}
 	printk("High memory starts at vaddr %08lx\n",
 			(ulong) pfn_to_kaddr(highstart_pfn));
@@ -333,23 +386,9 @@
 		}
 
 		zholes_size = get_zholes_size(nid);
-		/*
-		 * We let the lmem_map for node 0 be allocated from the
-		 * normal bootmem allocator, but other nodes come from the
-		 * remapped KVA area - mbligh
-		 */
-		if (!nid)
-			free_area_init_node(nid, NODE_DATA(nid),
-					zones_size, start, zholes_size);
-		else {
-			unsigned long lmem_map;
-			lmem_map = (unsigned long)node_remap_start_vaddr[nid];
-			lmem_map += sizeof(pg_data_t) + PAGE_SIZE - 1;
-			lmem_map &= PAGE_MASK;
-			NODE_DATA(nid)->node_mem_map = (struct page *)lmem_map;
-			free_area_init_node(nid, NODE_DATA(nid), zones_size,
-				start, zholes_size);
-		}
+
+		free_area_init_node(nid, NODE_DATA(nid), zones_size, start,
+				zholes_size);
 	}
 	return;
 }
@@ -358,24 +397,26 @@
 {
 #ifdef CONFIG_HIGHMEM
 	struct zone *zone;
+	struct page *page;
 
 	for_each_zone(zone) {
-		unsigned long node_pfn, node_high_size, zone_start_pfn;
-		struct page * zone_mem_map;
-		
+		unsigned long node_pfn, zone_start_pfn, zone_end_pfn;
+
 		if (!is_highmem(zone))
 			continue;
 
-		printk("Initializing %s for node %d\n", zone->name,
-			zone->zone_pgdat->node_id);
-
-		node_high_size = zone->spanned_pages;
-		zone_mem_map = zone->zone_mem_map;
 		zone_start_pfn = zone->zone_start_pfn;
+		zone_end_pfn = zone_start_pfn + zone->spanned_pages;
 
-		for (node_pfn = 0; node_pfn < node_high_size; node_pfn++) {
-			one_highpage_init((struct page *)(zone_mem_map + node_pfn),
-					  zone_start_pfn + node_pfn, bad_ppro);
+		printk("Initializing %s for node %d (%08lx:%08lx)\n",
+				zone->name, zone->zone_pgdat->node_id,
+				zone_start_pfn, zone_end_pfn);
+
+		for (node_pfn = zone_start_pfn; node_pfn < zone_end_pfn; node_pfn++) {
+			if (!pfn_valid(node_pfn))
+				continue;
+			page = pfn_to_page(node_pfn);
+			one_highpage_init(page, node_pfn, bad_ppro);
 		}
 	}
 	totalram_pages += totalhigh_pages;
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index a509237..8e90339 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -146,7 +146,7 @@
 
 		if (instr > limit)
 			break;
-		if (__get_user(opcode, (unsigned char *) instr))
+		if (__get_user(opcode, (unsigned char __user *) instr))
 			break; 
 
 		instr_hi = opcode & 0xf0; 
@@ -173,7 +173,7 @@
 			scan_more = 0;
 			if (instr > limit)
 				break;
-			if (__get_user(opcode, (unsigned char *) instr)) 
+			if (__get_user(opcode, (unsigned char __user *) instr))
 				break;
 			prefetch = (instr_lo == 0xF) &&
 				(opcode == 0x0D || opcode == 0x18);
@@ -463,6 +463,9 @@
 		printk(KERN_ALERT "*pte = %08lx\n", page);
 	}
 #endif
+	tsk->thread.cr2 = address;
+	tsk->thread.trap_no = 14;
+	tsk->thread.error_code = error_code;
 	die("Oops", regs, error_code);
 	bust_spinlocks(0);
 	do_exit(SIGKILL);
diff --git a/arch/i386/mm/highmem.c b/arch/i386/mm/highmem.c
index fc4c4ca..b6eb4dc 100644
--- a/arch/i386/mm/highmem.c
+++ b/arch/i386/mm/highmem.c
@@ -1,4 +1,5 @@
 #include <linux/highmem.h>
+#include <linux/module.h>
 
 void *kmap(struct page *page)
 {
@@ -74,6 +75,24 @@
 	preempt_check_resched();
 }
 
+/* This is the same as kmap_atomic() but can map memory that doesn't
+ * have a struct page associated with it.
+ */
+void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
+{
+	enum fixed_addresses idx;
+	unsigned long vaddr;
+
+	inc_preempt_count();
+
+	idx = type + KM_TYPE_NR*smp_processor_id();
+	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+	set_pte(kmap_pte-idx, pfn_pte(pfn, kmap_prot));
+	__flush_tlb_one(vaddr);
+
+	return (void*) vaddr;
+}
+
 struct page *kmap_atomic_to_page(void *ptr)
 {
 	unsigned long idx, vaddr = (unsigned long)ptr;
@@ -87,3 +106,8 @@
 	return pte_page(*pte);
 }
 
+EXPORT_SYMBOL(kmap);
+EXPORT_SYMBOL(kunmap);
+EXPORT_SYMBOL(kmap_atomic);
+EXPORT_SYMBOL(kunmap_atomic);
+EXPORT_SYMBOL(kmap_atomic_to_page);
diff --git a/arch/i386/mm/hugetlbpage.c b/arch/i386/mm/hugetlbpage.c
index 171fc92..3b099f3 100644
--- a/arch/i386/mm/hugetlbpage.c
+++ b/arch/i386/mm/hugetlbpage.c
@@ -18,7 +18,7 @@
 #include <asm/tlb.h>
 #include <asm/tlbflush.h>
 
-static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
 {
 	pgd_t *pgd;
 	pud_t *pud;
@@ -30,7 +30,7 @@
 	return (pte_t *) pmd;
 }
 
-static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 {
 	pgd_t *pgd;
 	pud_t *pud;
@@ -42,21 +42,6 @@
 	return (pte_t *) pmd;
 }
 
-static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma, struct page *page, pte_t * page_table, int write_access)
-{
-	pte_t entry;
-
-	add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
-	if (write_access) {
-		entry =
-		    pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
-	} else
-		entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot));
-	entry = pte_mkyoung(entry);
-	mk_pte_huge(entry);
-	set_pte(page_table, entry);
-}
-
 /*
  * This function checks for proper alignment of input addr and len parameters.
  */
@@ -69,77 +54,6 @@
 	return 0;
 }
 
-int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
-			struct vm_area_struct *vma)
-{
-	pte_t *src_pte, *dst_pte, entry;
-	struct page *ptepage;
-	unsigned long addr = vma->vm_start;
-	unsigned long end = vma->vm_end;
-
-	while (addr < end) {
-		dst_pte = huge_pte_alloc(dst, addr);
-		if (!dst_pte)
-			goto nomem;
-		src_pte = huge_pte_offset(src, addr);
-		entry = *src_pte;
-		ptepage = pte_page(entry);
-		get_page(ptepage);
-		set_pte(dst_pte, entry);
-		add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
-		addr += HPAGE_SIZE;
-	}
-	return 0;
-
-nomem:
-	return -ENOMEM;
-}
-
-int
-follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
-		    struct page **pages, struct vm_area_struct **vmas,
-		    unsigned long *position, int *length, int i)
-{
-	unsigned long vpfn, vaddr = *position;
-	int remainder = *length;
-
-	WARN_ON(!is_vm_hugetlb_page(vma));
-
-	vpfn = vaddr/PAGE_SIZE;
-	while (vaddr < vma->vm_end && remainder) {
-
-		if (pages) {
-			pte_t *pte;
-			struct page *page;
-
-			pte = huge_pte_offset(mm, vaddr);
-
-			/* hugetlb should be locked, and hence, prefaulted */
-			WARN_ON(!pte || pte_none(*pte));
-
-			page = &pte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)];
-
-			WARN_ON(!PageCompound(page));
-
-			get_page(page);
-			pages[i] = page;
-		}
-
-		if (vmas)
-			vmas[i] = vma;
-
-		vaddr += PAGE_SIZE;
-		++vpfn;
-		--remainder;
-		++i;
-	}
-
-	*length = remainder;
-	*position = vaddr;
-
-	return i;
-}
-
 #if 0	/* This is just for testing */
 struct page *
 follow_huge_addr(struct mm_struct *mm, unsigned long address, int write)
@@ -204,83 +118,15 @@
 }
 #endif
 
-void unmap_hugepage_range(struct vm_area_struct *vma,
-		unsigned long start, unsigned long end)
+void hugetlb_clean_stale_pgtable(pte_t *pte)
 {
-	struct mm_struct *mm = vma->vm_mm;
-	unsigned long address;
-	pte_t pte, *ptep;
+	pmd_t *pmd = (pmd_t *) pte;
 	struct page *page;
 
-	BUG_ON(start & (HPAGE_SIZE - 1));
-	BUG_ON(end & (HPAGE_SIZE - 1));
-
-	for (address = start; address < end; address += HPAGE_SIZE) {
-		ptep = huge_pte_offset(mm, address);
-		if (!ptep)
-			continue;
-		pte = ptep_get_and_clear(mm, address, ptep);
-		if (pte_none(pte))
-			continue;
-		page = pte_page(pte);
-		put_page(page);
-	}
-	add_mm_counter(mm ,rss, -((end - start) >> PAGE_SHIFT));
-	flush_tlb_range(vma, start, end);
-}
-
-int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
-{
-	struct mm_struct *mm = current->mm;
-	unsigned long addr;
-	int ret = 0;
-
-	BUG_ON(vma->vm_start & ~HPAGE_MASK);
-	BUG_ON(vma->vm_end & ~HPAGE_MASK);
-
-	spin_lock(&mm->page_table_lock);
-	for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
-		unsigned long idx;
-		pte_t *pte = huge_pte_alloc(mm, addr);
-		struct page *page;
-
-		if (!pte) {
-			ret = -ENOMEM;
-			goto out;
-		}
-
-		if (!pte_none(*pte))
-			continue;
-
-		idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
-			+ (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
-		page = find_get_page(mapping, idx);
-		if (!page) {
-			/* charge the fs quota first */
-			if (hugetlb_get_quota(mapping)) {
-				ret = -ENOMEM;
-				goto out;
-			}
-			page = alloc_huge_page();
-			if (!page) {
-				hugetlb_put_quota(mapping);
-				ret = -ENOMEM;
-				goto out;
-			}
-			ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
-			if (! ret) {
-				unlock_page(page);
-			} else {
-				hugetlb_put_quota(mapping);
-				free_huge_page(page);
-				goto out;
-			}
-		}
-		set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
-	}
-out:
-	spin_unlock(&mm->page_table_lock);
-	return ret;
+	page = pmd_page(*pmd);
+	pmd_clear(pmd);
+	dec_page_state(nr_page_table_pages);
+	page_cache_release(page);
 }
 
 /* x86_64 also uses this file */
@@ -294,7 +140,12 @@
 	struct vm_area_struct *vma;
 	unsigned long start_addr;
 
-	start_addr = mm->free_area_cache;
+	if (len > mm->cached_hole_size) {
+	        start_addr = mm->free_area_cache;
+	} else {
+	        start_addr = TASK_UNMAPPED_BASE;
+	        mm->cached_hole_size = 0;
+	}
 
 full_search:
 	addr = ALIGN(start_addr, HPAGE_SIZE);
@@ -308,6 +159,7 @@
 			 */
 			if (start_addr != TASK_UNMAPPED_BASE) {
 				start_addr = TASK_UNMAPPED_BASE;
+				mm->cached_hole_size = 0;
 				goto full_search;
 			}
 			return -ENOMEM;
@@ -316,6 +168,8 @@
 			mm->free_area_cache = addr + len;
 			return addr;
 		}
+		if (addr + mm->cached_hole_size < vma->vm_start)
+		        mm->cached_hole_size = vma->vm_start - addr;
 		addr = ALIGN(vma->vm_end, HPAGE_SIZE);
 	}
 }
@@ -327,12 +181,17 @@
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma, *prev_vma;
 	unsigned long base = mm->mmap_base, addr = addr0;
+	unsigned long largest_hole = mm->cached_hole_size;
 	int first_time = 1;
 
 	/* don't allow allocations above current base */
 	if (mm->free_area_cache > base)
 		mm->free_area_cache = base;
 
+	if (len <= largest_hole) {
+	        largest_hole = 0;
+		mm->free_area_cache  = base;
+	}
 try_again:
 	/* make sure it can fit in the remaining address space */
 	if (mm->free_area_cache < len)
@@ -353,13 +212,21 @@
 		 * vma->vm_start, use it:
 		 */
 		if (addr + len <= vma->vm_start &&
-				(!prev_vma || (addr >= prev_vma->vm_end)))
+		            (!prev_vma || (addr >= prev_vma->vm_end))) {
 			/* remember the address as a hint for next time */
-			return (mm->free_area_cache = addr);
-		else
+		        mm->cached_hole_size = largest_hole;
+		        return (mm->free_area_cache = addr);
+		} else {
 			/* pull free_area_cache down to the first hole */
-			if (mm->free_area_cache == vma->vm_end)
+		        if (mm->free_area_cache == vma->vm_end) {
 				mm->free_area_cache = vma->vm_start;
+				mm->cached_hole_size = largest_hole;
+			}
+		}
+
+		/* remember the largest hole we saw so far */
+		if (addr + largest_hole < vma->vm_start)
+		        largest_hole = vma->vm_start - addr;
 
 		/* try just below the current vma->vm_start */
 		addr = (vma->vm_start - len) & HPAGE_MASK;
@@ -372,6 +239,7 @@
 	 */
 	if (first_time) {
 		mm->free_area_cache = base;
+		largest_hole = 0;
 		first_time = 0;
 		goto try_again;
 	}
@@ -382,6 +250,7 @@
 	 * allocations.
 	 */
 	mm->free_area_cache = TASK_UNMAPPED_BASE;
+	mm->cached_hole_size = ~0UL;
 	addr = hugetlb_get_unmapped_area_bottomup(file, addr0,
 			len, pgoff, flags);
 
@@ -389,6 +258,7 @@
 	 * Restore the topdown base:
 	 */
 	mm->free_area_cache = base;
+	mm->cached_hole_size = ~0UL;
 
 	return addr;
 }
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 7a7ea37..12216b5 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -191,7 +191,7 @@
 
 extern int is_available_memory(efi_memory_desc_t *);
 
-static inline int page_is_ram(unsigned long pagenr)
+int page_is_ram(unsigned long pagenr)
 {
 	int i;
 	unsigned long addr, end;
@@ -269,7 +269,6 @@
 {
 	if (page_is_ram(pfn) && !(bad_ppro && page_kills_ppro(pfn))) {
 		ClearPageReserved(page);
-		set_bit(PG_highmem, &page->flags);
 		set_page_count(page, 1);
 		__free_page(page);
 		totalhigh_pages++;
@@ -277,7 +276,9 @@
 		SetPageReserved(page);
 }
 
-#ifndef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
+extern void set_highmem_pages_init(int);
+#else
 static void __init set_highmem_pages_init(int bad_ppro)
 {
 	int pfn;
@@ -285,9 +286,7 @@
 		one_highpage_init(pfn_to_page(pfn), pfn, bad_ppro);
 	totalram_pages += totalhigh_pages;
 }
-#else
-extern void set_highmem_pages_init(int);
-#endif /* !CONFIG_DISCONTIGMEM */
+#endif /* CONFIG_FLATMEM */
 
 #else
 #define kmap_init() do { } while (0)
@@ -296,12 +295,13 @@
 #endif /* CONFIG_HIGHMEM */
 
 unsigned long long __PAGE_KERNEL = _PAGE_KERNEL;
+EXPORT_SYMBOL(__PAGE_KERNEL);
 unsigned long long __PAGE_KERNEL_EXEC = _PAGE_KERNEL_EXEC;
 
-#ifndef CONFIG_DISCONTIGMEM
-#define remap_numa_kva() do {} while (0)
-#else
+#ifdef CONFIG_NUMA
 extern void __init remap_numa_kva(void);
+#else
+#define remap_numa_kva() do {} while (0)
 #endif
 
 static void __init pagetable_init (void)
@@ -352,7 +352,7 @@
 #endif
 }
 
-#if defined(CONFIG_PM_DISK) || defined(CONFIG_SOFTWARE_SUSPEND)
+#ifdef CONFIG_SOFTWARE_SUSPEND
 /*
  * Swap suspend & friends need this for resume because things like the intel-agp
  * driver might have split up a kernel 4MB mapping.
@@ -526,7 +526,7 @@
 #else
 	num_physpages = max_low_pfn;
 #endif
-#ifndef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_FLATMEM
 	max_mapnr = num_physpages;
 #endif
 }
@@ -540,7 +540,7 @@
 	int tmp;
 	int bad_ppro;
 
-#ifndef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_FLATMEM
 	if (!mem_map)
 		BUG();
 #endif
diff --git a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
index ab54279..6b25afc 100644
--- a/arch/i386/mm/ioremap.c
+++ b/arch/i386/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/fixmap.h>
 #include <asm/cacheflush.h>
@@ -165,7 +166,7 @@
 	}
 	return (void __iomem *) (offset + (char __iomem *)addr);
 }
-
+EXPORT_SYMBOL(__ioremap);
 
 /**
  * ioremap_nocache     -   map bus memory into CPU space
@@ -222,6 +223,7 @@
 
 	return p;					
 }
+EXPORT_SYMBOL(ioremap_nocache);
 
 void iounmap(volatile void __iomem *addr)
 {
@@ -241,7 +243,7 @@
 	write_lock(&vmlist_lock);
 	p = __remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
 	if (!p) { 
-		printk("iounmap: bad address %p\n", addr);
+		printk(KERN_WARNING "iounmap: bad address %p\n", addr);
 		goto out_unlock;
 	}
 
@@ -255,6 +257,7 @@
 	write_unlock(&vmlist_lock);
 	kfree(p); 
 }
+EXPORT_SYMBOL(iounmap);
 
 void __init *bt_ioremap(unsigned long phys_addr, unsigned long size)
 {
diff --git a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c
index dd81479..bd2f7af 100644
--- a/arch/i386/mm/pgtable.c
+++ b/arch/i386/mm/pgtable.c
@@ -30,13 +30,14 @@
 	struct page *page;
 	pg_data_t *pgdat;
 	unsigned long i;
+	struct page_state ps;
 
-	printk("Mem-info:\n");
+	printk(KERN_INFO "Mem-info:\n");
 	show_free_areas();
-	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+	printk(KERN_INFO "Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
 	for_each_pgdat(pgdat) {
 		for (i = 0; i < pgdat->node_spanned_pages; ++i) {
-			page = pgdat->node_mem_map + i;
+			page = pgdat_page_nr(pgdat, i);
 			total++;
 			if (PageHighMem(page))
 				highmem++;
@@ -48,11 +49,18 @@
 				shared += page_count(page) - 1;
 		}
 	}
-	printk("%d pages of RAM\n", total);
-	printk("%d pages of HIGHMEM\n",highmem);
-	printk("%d reserved pages\n",reserved);
-	printk("%d pages shared\n",shared);
-	printk("%d pages swap cached\n",cached);
+	printk(KERN_INFO "%d pages of RAM\n", total);
+	printk(KERN_INFO "%d pages of HIGHMEM\n", highmem);
+	printk(KERN_INFO "%d reserved pages\n", reserved);
+	printk(KERN_INFO "%d pages shared\n", shared);
+	printk(KERN_INFO "%d pages swap cached\n", cached);
+
+	get_page_state(&ps);
+	printk(KERN_INFO "%lu pages dirty\n", ps.nr_dirty);
+	printk(KERN_INFO "%lu pages writeback\n", ps.nr_writeback);
+	printk(KERN_INFO "%lu pages mapped\n", ps.nr_mapped);
+	printk(KERN_INFO "%lu pages slab\n", ps.nr_slab);
+	printk(KERN_INFO "%lu pages pagetables\n", ps.nr_page_table_pages);
 }
 
 /*
@@ -105,16 +113,16 @@
 	pmd_t *pmd;
 
 	if (vaddr & (PMD_SIZE-1)) {		/* vaddr is misaligned */
-		printk ("set_pmd_pfn: vaddr misaligned\n");
+		printk(KERN_WARNING "set_pmd_pfn: vaddr misaligned\n");
 		return; /* BUG(); */
 	}
 	if (pfn & (PTRS_PER_PTE-1)) {		/* pfn is misaligned */
-		printk ("set_pmd_pfn: pfn misaligned\n");
+		printk(KERN_WARNING "set_pmd_pfn: pfn misaligned\n");
 		return; /* BUG(); */
 	}
 	pgd = swapper_pg_dir + pgd_index(vaddr);
 	if (pgd_none(*pgd)) {
-		printk ("set_pmd_pfn: pgd_none\n");
+		printk(KERN_WARNING "set_pmd_pfn: pgd_none\n");
 		return; /* BUG(); */
 	}
 	pud = pud_offset(pgd, vaddr);
diff --git a/arch/i386/oprofile/backtrace.c b/arch/i386/oprofile/backtrace.c
index 52d72e0..65dfd2e 100644
--- a/arch/i386/oprofile/backtrace.c
+++ b/arch/i386/oprofile/backtrace.c
@@ -91,7 +91,7 @@
 	head = (struct frame_head *)regs->ebp;
 #endif
 
-	if (!user_mode(regs)) {
+	if (!user_mode_vm(regs)) {
 		while (depth-- && valid_kernel_stack(head, regs))
 			head = dump_backtrace(head);
 		return;
diff --git a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
index da21b1d..83458f8 100644
--- a/arch/i386/pci/irq.c
+++ b/arch/i386/pci/irq.c
@@ -227,6 +227,24 @@
 }
 
 /*
+ * The VIA pirq rules are nibble-based, like ALI,
+ * but without the ugly irq number munging.
+ * However, for 82C586, nibble map is different .
+ */
+static int pirq_via586_get(struct pci_dev *router, struct pci_dev *dev, int pirq)
+{
+	static 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 };
+	write_config_nybble(router, 0x55, pirqmap[pirq-1], irq);
+	return 1;
+}
+
+/*
  * ITE 8330G pirq rules are nibble-based
  * FIXME: pirqmap may be { 1, 0, 3, 2 },
  * 	  2+3 are both mapped to irq 9 on my system
@@ -512,6 +530,10 @@
 	switch(device)
 	{
 		case PCI_DEVICE_ID_VIA_82C586_0:
+			r->name = "VIA";
+			r->get = pirq_via586_get;
+			r->set = pirq_via586_set;
+			return 1;
 		case PCI_DEVICE_ID_VIA_82C596:
 		case PCI_DEVICE_ID_VIA_82C686:
 		case PCI_DEVICE_ID_VIA_8231:
diff --git a/arch/i386/pci/pcbios.c b/arch/i386/pci/pcbios.c
index 141421b..b9d65f0 100644
--- a/arch/i386/pci/pcbios.c
+++ b/arch/i386/pci/pcbios.c
@@ -4,6 +4,7 @@
 
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include "pci.h"
 #include "pci-functions.h"
 
@@ -456,7 +457,7 @@
 	free_page(page);
 	return rt;
 }
-
+EXPORT_SYMBOL(pcibios_get_irq_routing_table);
 
 int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq)
 {
@@ -473,6 +474,7 @@
 		  "S" (&pci_indirect));
 	return !(ret & 0xff00);
 }
+EXPORT_SYMBOL(pcibios_set_irq_routing);
 
 static int __init pci_pcbios_init(void)
 {
diff --git a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c
index cf337c6..0e6b45b 100644
--- a/arch/i386/power/cpu.c
+++ b/arch/i386/power/cpu.c
@@ -22,9 +22,11 @@
 #include <linux/device.h>
 #include <linux/suspend.h>
 #include <linux/acpi.h>
+
 #include <asm/uaccess.h>
 #include <asm/acpi.h>
 #include <asm/tlbflush.h>
+#include <asm/processor.h>
 
 static struct saved_context saved_context;
 
@@ -33,8 +35,6 @@
 unsigned long saved_context_esi, saved_context_edi;
 unsigned long saved_context_eflags;
 
-extern void enable_sep_cpu(void *);
-
 void __save_processor_state(struct saved_context *ctxt)
 {
 	kernel_fpu_begin();
@@ -44,7 +44,6 @@
 	 */
 	asm volatile ("sgdt %0" : "=m" (ctxt->gdt_limit));
 	asm volatile ("sidt %0" : "=m" (ctxt->idt_limit));
-	asm volatile ("sldt %0" : "=m" (ctxt->ldt));
 	asm volatile ("str %0"  : "=m" (ctxt->tr));
 
 	/*
@@ -94,20 +93,19 @@
 	 * Now maybe reload the debug registers
 	 */
 	if (current->thread.debugreg[7]){
-                loaddebug(&current->thread, 0);
-                loaddebug(&current->thread, 1);
-                loaddebug(&current->thread, 2);
-                loaddebug(&current->thread, 3);
-                /* no 4 and 5 */
-                loaddebug(&current->thread, 6);
-                loaddebug(&current->thread, 7);
+		set_debugreg(current->thread.debugreg[0], 0);
+		set_debugreg(current->thread.debugreg[1], 1);
+		set_debugreg(current->thread.debugreg[2], 2);
+		set_debugreg(current->thread.debugreg[3], 3);
+		/* no 4 and 5 */
+		set_debugreg(current->thread.debugreg[6], 6);
+		set_debugreg(current->thread.debugreg[7], 7);
 	}
 
 }
 
 void __restore_processor_state(struct saved_context *ctxt)
 {
-
 	/*
 	 * control registers
 	 */
@@ -117,6 +115,13 @@
 	asm volatile ("movl %0, %%cr0" :: "r" (ctxt->cr0));
 
 	/*
+	 * now restore the descriptor tables to their proper values
+	 * ltr is done i fix_processor_context().
+	 */
+	asm volatile ("lgdt %0" :: "m" (ctxt->gdt_limit));
+	asm volatile ("lidt %0" :: "m" (ctxt->idt_limit));
+
+	/*
 	 * segment registers
 	 */
 	asm volatile ("movw %0, %%es" :: "r" (ctxt->es));
@@ -125,18 +130,10 @@
 	asm volatile ("movw %0, %%ss" :: "r" (ctxt->ss));
 
 	/*
-	 * now restore the descriptor tables to their proper values
-	 * ltr is done i fix_processor_context().
-	 */
-	asm volatile ("lgdt %0" :: "m" (ctxt->gdt_limit));
-	asm volatile ("lidt %0" :: "m" (ctxt->idt_limit));
-	asm volatile ("lldt %0" :: "m" (ctxt->ldt));
-
-	/*
 	 * sysenter MSRs
 	 */
 	if (boot_cpu_has(X86_FEATURE_SEP))
-		enable_sep_cpu(NULL);
+		enable_sep_cpu();
 
 	fix_processor_context();
 	do_fpu_end();
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 3ad2c4a..01b78e7 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -50,6 +50,10 @@
 	bool
 	default y
 
+config IA64_UNCACHED_ALLOCATOR
+	bool
+	select GENERIC_ALLOCATOR
+
 choice
 	prompt "System type"
 	default IA64_GENERIC
@@ -157,6 +161,8 @@
 
 endchoice
 
+source kernel/Kconfig.hz
+
 config IA64_BRL_EMU
 	bool
 	depends on ITANIUM
@@ -193,7 +199,7 @@
 	bool
 	default y if VIRTUAL_MEM_MAP
 
-config DISCONTIGMEM
+config ARCH_DISCONTIGMEM_ENABLE
 	bool "Discontiguous memory support"
 	depends on (IA64_DIG || IA64_SGI_SN2 || IA64_GENERIC || IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB) && NUMA && VIRTUAL_MEM_MAP
 	default y if (IA64_SGI_SN2 || IA64_GENERIC) && NUMA
@@ -216,14 +222,14 @@
 
 config IA64_SGI_SN_SIM
 	bool "SGI Medusa Simulator Support"
-	depends on IA64_SGI_SN2
+	depends on IA64_SGI_SN2 || IA64_GENERIC
 	help
 	  If you are compiling a kernel that will run under SGI's IA-64
 	  simulator (Medusa) then say Y, otherwise say N.
 
 config IA64_SGI_SN_XP
 	tristate "Support communication between SGI SSIs"
-	depends on MSPEC
+	select IA64_UNCACHED_ALLOCATOR
 	help
 	  An SGI machine can be divided into multiple Single System
 	  Images which act independently of each other and have
@@ -296,6 +302,8 @@
           Say Y here if you are building a kernel for a desktop, embedded
           or real-time system.  Say N if you are unsure.
 
+source "mm/Kconfig"
+
 config HAVE_DEC_LOCK
 	bool
 	depends on (SMP || PREEMPT)
diff --git a/arch/ia64/Kconfig.debug b/arch/ia64/Kconfig.debug
index de9d507..fda67ac 100644
--- a/arch/ia64/Kconfig.debug
+++ b/arch/ia64/Kconfig.debug
@@ -2,6 +2,17 @@
 
 source "lib/Kconfig.debug"
 
+config KPROBES
+        bool "Kprobes"
+        depends on DEBUG_KERNEL
+        help
+          Kprobes allows you to trap at almost any kernel address and
+          execute a callback function.  register_kprobe() establishes
+          a probepoint and specifies the callback.  Kprobes is useful
+          for kernel debugging, non-intrusive instrumentation and testing.
+          If in doubt, say "N".
+
+
 choice
 	prompt "Physical memory granularity"
 	default IA64_GRANULE_64MB
diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig
index 6ff7107..487d2e3 100644
--- a/arch/ia64/configs/sn2_defconfig
+++ b/arch/ia64/configs/sn2_defconfig
@@ -78,7 +78,7 @@
 CONFIG_NUMA=y
 CONFIG_VIRTUAL_MEM_MAP=y
 CONFIG_HOLES_IN_ZONE=y
-CONFIG_DISCONTIGMEM=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
 # CONFIG_IA64_CYCLONE is not set
 CONFIG_IOSAPIC=y
 CONFIG_IA64_SGI_SN_SIM=y
@@ -588,6 +588,7 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_SGI_L1_CONSOLE=y
+CONFIG_SERIAL_SGI_IOC4=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -788,6 +789,11 @@
 # CONFIG_INFINIBAND_IPOIB_DEBUG is not set
 
 #
+# SN Devices
+#
+CONFIG_SGI_IOC4=y
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig
index 9086b78..47f4534 100644
--- a/arch/ia64/configs/tiger_defconfig
+++ b/arch/ia64/configs/tiger_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc3
-# Tue May  3 15:55:04 2005
+# Linux kernel version: 2.6.12-20050621
+# Tue Jun 21 14:03:24 2005
 #
 
 #
@@ -67,6 +67,7 @@
 CONFIG_TIME_INTERPOLATION=y
 CONFIG_EFI=y
 CONFIG_GENERIC_IOMAP=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
 # CONFIG_IA64_GENERIC is not set
 CONFIG_IA64_DIG=y
 # CONFIG_IA64_HP_ZX1 is not set
@@ -285,6 +286,7 @@
 CONFIG_BLK_DEV_SR=m
 # CONFIG_BLK_DEV_SR_VENDOR 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
@@ -313,11 +315,8 @@
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
@@ -366,8 +365,10 @@
 # Fusion MPT device support
 #
 CONFIG_FUSION=y
-CONFIG_FUSION_MAX_SGE=40
-# CONFIG_FUSION_CTL is not set
+CONFIG_FUSION_SPI=y
+CONFIG_FUSION_FC=y
+CONFIG_FUSION_MAX_SGE=128
+CONFIG_FUSION_CTL=y
 
 #
 # IEEE 1394 (FireWire) support
@@ -506,9 +507,11 @@
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
+# CONFIG_SKGE is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
 CONFIG_TIGON3=y
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -598,7 +601,6 @@
 # CONFIG_GAMEPORT_VORTEX is not set
 # CONFIG_GAMEPORT_FM801 is not set
 # CONFIG_GAMEPORT_CS461X is not set
-CONFIG_SOUND_GAMEPORT=m
 
 #
 # Character devices
@@ -611,7 +613,6 @@
 # CONFIG_CYCLADES is not set
 # CONFIG_MOXA_SMARTIO is not set
 # CONFIG_ISI is not set
-# CONFIG_SYNCLINK is not set
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_N_HDLC is not set
 # CONFIG_SPECIALIX is not set
diff --git a/arch/ia64/defconfig b/arch/ia64/defconfig
index 7539e83..8444add 100644
--- a/arch/ia64/defconfig
+++ b/arch/ia64/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10
-# Thu Jan  6 11:13:13 2005
+# Linux kernel version: 2.6.12
+# Tue Jun 21 11:30:42 2005
 #
 
 #
@@ -10,6 +10,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -21,24 +22,27 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=20
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=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 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_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -63,9 +67,11 @@
 CONFIG_TIME_INTERPOLATION=y
 CONFIG_EFI=y
 CONFIG_GENERIC_IOMAP=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
 CONFIG_IA64_GENERIC=y
 # CONFIG_IA64_DIG is not set
 # CONFIG_IA64_HP_ZX1 is not set
+# CONFIG_IA64_HP_ZX1_SWIOTLB is not set
 # CONFIG_IA64_SGI_SN2 is not set
 # CONFIG_IA64_HP_SIM is not set
 # CONFIG_ITANIUM is not set
@@ -77,13 +83,15 @@
 CONFIG_IA64_L1_CACHE_SHIFT=7
 CONFIG_NUMA=y
 CONFIG_VIRTUAL_MEM_MAP=y
-CONFIG_DISCONTIGMEM=y
+CONFIG_HOLES_IN_ZONE=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
 CONFIG_IA64_CYCLONE=y
 CONFIG_IOSAPIC=y
 CONFIG_FORCE_MAX_ZONEORDER=18
 CONFIG_SMP=y
 CONFIG_NR_CPUS=512
 CONFIG_HOTPLUG_CPU=y
+# CONFIG_SCHED_SMT is not set
 # CONFIG_PREEMPT is not set
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_IA32_SUPPORT=y
@@ -135,6 +143,7 @@
 # CONFIG_PCI_MSI is not set
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
 
 #
 # PCI Hotplug Support
@@ -144,7 +153,6 @@
 CONFIG_HOTPLUG_PCI_ACPI=m
 # CONFIG_HOTPLUG_PCI_ACPI_IBM is not set
 # CONFIG_HOTPLUG_PCI_CPCI is not set
-# CONFIG_HOTPLUG_PCI_PCIE is not set
 # CONFIG_HOTPLUG_PCI_SHPC is not set
 
 #
@@ -153,10 +161,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # Device Drivers
 #
 
@@ -190,6 +194,7 @@
 # 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=m
@@ -209,6 +214,7 @@
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -283,6 +289,7 @@
 CONFIG_BLK_DEV_SR=m
 # CONFIG_BLK_DEV_SR_VENDOR 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
@@ -310,13 +317,21 @@
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
+CONFIG_SCSI_SATA=y
+# CONFIG_SCSI_SATA_AHCI is not set
+# CONFIG_SCSI_SATA_SVW is not set
+# CONFIG_SCSI_ATA_PIIX is not set
+# CONFIG_SCSI_SATA_NV is not set
+# CONFIG_SCSI_SATA_PROMISE is not set
+# CONFIG_SCSI_SATA_QSTOR is not set
+# CONFIG_SCSI_SATA_SX4 is not set
+# CONFIG_SCSI_SATA_SIL is not set
+# CONFIG_SCSI_SATA_SIS is not set
+# CONFIG_SCSI_SATA_ULI is not set
+# CONFIG_SCSI_SATA_VIA is not set
+CONFIG_SCSI_SATA_VITESSE=y
 # CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
@@ -326,7 +341,6 @@
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
 CONFIG_SCSI_QLOGIC_FC=y
 # CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
 CONFIG_SCSI_QLOGIC_1280=y
@@ -337,6 +351,7 @@
 CONFIG_SCSI_QLA2300=m
 CONFIG_SCSI_QLA2322=m
 # CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -359,12 +374,16 @@
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+# CONFIG_DM_MULTIPATH_EMC is not set
 
 #
 # Fusion MPT device support
 #
 CONFIG_FUSION=y
-CONFIG_FUSION_MAX_SGE=40
+CONFIG_FUSION_SPI=y
+CONFIG_FUSION_FC=m
+CONFIG_FUSION_MAX_SGE=128
 # CONFIG_FUSION_CTL is not set
 
 #
@@ -387,7 +406,6 @@
 #
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
-CONFIG_NETLINK_DEV=y
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -447,7 +465,6 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_ETHERTAP is not set
 
 #
 # ARCnet devices
@@ -484,9 +501,7 @@
 # CONFIG_FORCEDETH is not set
 # CONFIG_DGRS is not set
 CONFIG_EEPRO100=m
-# CONFIG_EEPRO100_PIO is not set
 CONFIG_E100=m
-# CONFIG_E100_NAPI is not set
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
@@ -508,9 +523,11 @@
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
+# CONFIG_SKGE is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
 CONFIG_TIGON3=y
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -568,25 +585,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-CONFIG_GAMEPORT=m
-CONFIG_SOUND_GAMEPORT=m
-# CONFIG_GAMEPORT_NS558 is not set
-# CONFIG_GAMEPORT_L4 is not set
-# CONFIG_GAMEPORT_EMU10K1 is not set
-# CONFIG_GAMEPORT_VORTEX is not set
-# CONFIG_GAMEPORT_FM801 is not set
-# CONFIG_GAMEPORT_CS461x is not set
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_SERIO_RAW is not set
-
-#
 # Input Device Drivers
 #
 CONFIG_INPUT_KEYBOARD=y
@@ -604,6 +602,23 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+CONFIG_GAMEPORT=m
+# CONFIG_GAMEPORT_NS558 is not set
+# CONFIG_GAMEPORT_L4 is not set
+# CONFIG_GAMEPORT_EMU10K1 is not set
+# CONFIG_GAMEPORT_VORTEX is not set
+# CONFIG_GAMEPORT_FM801 is not set
+# CONFIG_GAMEPORT_CS461X is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -613,11 +628,15 @@
 # CONFIG_ROCKETPORT is not set
 # CONFIG_CYCLADES is not set
 # CONFIG_MOXA_SMARTIO is not set
-# CONFIG_SYNCLINK is not set
+# CONFIG_ISI is not set
 # CONFIG_SYNCLINKMP is not set
 # CONFIG_N_HDLC is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
 # CONFIG_STALDRV is not set
 CONFIG_SGI_SNSC=y
+CONFIG_SGI_TIOCX=y
+CONFIG_SGI_MBCS=m
 
 #
 # Serial drivers
@@ -638,6 +657,8 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_SGI_L1_CONSOLE=y
+CONFIG_SERIAL_SGI_IOC4=y
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -663,6 +684,7 @@
 CONFIG_AGP=m
 CONFIG_AGP_I460=m
 CONFIG_AGP_HP_ZX1=m
+CONFIG_AGP_SGI_TIOCA=m
 CONFIG_DRM=m
 CONFIG_DRM_TDFX=m
 CONFIG_DRM_R128=m
@@ -674,9 +696,15 @@
 # CONFIG_HPET_RTC_IRQ is not set
 CONFIG_HPET_MMAP=y
 CONFIG_MAX_RAW_DEVS=256
+# CONFIG_HANGCHECK_TIMER is not set
 CONFIG_MMTIMER=y
 
 #
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -760,6 +788,8 @@
 CONFIG_SND_CS46XX_NEW_DSP=y
 CONFIG_SND_CS4281=m
 CONFIG_SND_EMU10K1=m
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_CA0106 is not set
 # CONFIG_SND_KORG1212 is not set
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
@@ -784,13 +814,14 @@
 # CONFIG_SND_INTEL8X0M is not set
 # CONFIG_SND_SONICVIBES is not set
 # CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
 # CONFIG_SND_VX222 is not set
+# CONFIG_SND_HDA_INTEL is not set
 
 #
 # USB devices
 #
 # CONFIG_SND_USB_AUDIO is not set
-# CONFIG_SND_USB_USX2Y is not set
 
 #
 # Open Sound System
@@ -800,6 +831,8 @@
 #
 # USB support
 #
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
 CONFIG_USB=m
 # CONFIG_USB_DEBUG is not set
 
@@ -811,8 +844,6 @@
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_SUSPEND is not set
 # CONFIG_USB_OTG is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
 
 #
 # USB Host Controller Drivers
@@ -821,6 +852,8 @@
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 CONFIG_USB_UHCI_HCD=m
 # CONFIG_USB_SL811_HCD is not set
 
@@ -838,12 +871,11 @@
 #
 CONFIG_USB_STORAGE=m
 # CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_RW_DETECT 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_HP8200e 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
@@ -893,6 +925,7 @@
 # CONFIG_USB_PEGASUS is not set
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=m
 
 #
 # USB port drivers
@@ -908,7 +941,6 @@
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
-# CONFIG_USB_TIGL is not set
 # CONFIG_USB_AUERSWALD is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
@@ -917,6 +949,8 @@
 # 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_TEST is not set
 
 #
@@ -943,6 +977,11 @@
 # CONFIG_INFINIBAND_IPOIB_DEBUG is not set
 
 #
+# SN Devices
+#
+CONFIG_SGI_IOC4=y
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -964,7 +1003,12 @@
 CONFIG_REISERFS_FS_SECURITY=y
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
 CONFIG_XFS_FS=y
+CONFIG_XFS_EXPORT=y
 # CONFIG_XFS_RT is not set
 # CONFIG_XFS_QUOTA is not set
 # CONFIG_XFS_SECURITY is not set
@@ -1042,7 +1086,7 @@
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=m
 CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=m
+CONFIG_EXPORTFS=y
 CONFIG_SUNRPC=m
 CONFIG_SUNRPC_GSS=m
 CONFIG_RPCSEC_GSS_KRB5=m
@@ -1128,6 +1172,8 @@
 # CONFIG_CRC_CCITT is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
 
 #
 # HP Simulator drivers
@@ -1144,14 +1190,17 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=20
 # 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_INFO is not set
+# CONFIG_DEBUG_FS is not set
 CONFIG_IA64_GRANULE_16MB=y
 # CONFIG_IA64_GRANULE_64MB is not set
 # CONFIG_IA64_PRINT_HAZARDS is not set
@@ -1178,6 +1227,7 @@
 # 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
diff --git a/arch/ia64/ia32/ia32priv.h b/arch/ia64/ia32/ia32priv.h
index b2de948..e3e9290 100644
--- a/arch/ia64/ia32/ia32priv.h
+++ b/arch/ia64/ia32/ia32priv.h
@@ -241,7 +241,7 @@
 
 		/* POSIX.1b timers */
 		struct {
-			timer_t _tid;		/* timer id */
+			compat_timer_t _tid;		/* timer id */
 			int _overrun;		/* overrun count */
 			char _pad[sizeof(unsigned int) - sizeof(int)];
 			compat_sigval_t _sigval;	/* same as below */
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index c1a02bb..b2e2f65 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -20,6 +20,8 @@
 obj-$(CONFIG_PERFMON)		+= perfmon_default_smpl.o
 obj-$(CONFIG_IA64_CYCLONE)	+= cyclone.o
 obj-$(CONFIG_IA64_MCA_RECOVERY)	+= mca_recovery.o
+obj-$(CONFIG_KPROBES)		+= kprobes.o jprobes.o
+obj-$(CONFIG_IA64_UNCACHED_ALLOCATOR)	+= uncached.o
 mca_recovery-y			+= mca_drv.o mca_drv_asm.o
 
 # The gate DSO image is built using a special linker script.
diff --git a/arch/ia64/kernel/domain.c b/arch/ia64/kernel/domain.c
index fe532c9..d65e87b 100644
--- a/arch/ia64/kernel/domain.c
+++ b/arch/ia64/kernel/domain.c
@@ -14,7 +14,7 @@
 #include <linux/topology.h>
 #include <linux/nodemask.h>
 
-#define SD_NODES_PER_DOMAIN 6
+#define SD_NODES_PER_DOMAIN 16
 
 #ifdef CONFIG_NUMA
 /**
@@ -27,7 +27,7 @@
  *
  * Should use nodemask_t.
  */
-static int __devinit find_next_best_node(int node, unsigned long *used_nodes)
+static int find_next_best_node(int node, unsigned long *used_nodes)
 {
 	int i, n, val, min_val, best_node = 0;
 
@@ -66,7 +66,7 @@
  * should be one that prevents unnecessary balancing, but also spreads tasks
  * out optimally.
  */
-static cpumask_t __devinit sched_domain_node_span(int node)
+static cpumask_t sched_domain_node_span(int node)
 {
 	int i;
 	cpumask_t span, nodemask;
@@ -96,7 +96,7 @@
 #ifdef CONFIG_SCHED_SMT
 static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
 static struct sched_group sched_group_cpus[NR_CPUS];
-static int __devinit cpu_to_cpu_group(int cpu)
+static int cpu_to_cpu_group(int cpu)
 {
 	return cpu;
 }
@@ -104,7 +104,7 @@
 
 static DEFINE_PER_CPU(struct sched_domain, phys_domains);
 static struct sched_group sched_group_phys[NR_CPUS];
-static int __devinit cpu_to_phys_group(int cpu)
+static int cpu_to_phys_group(int cpu)
 {
 #ifdef CONFIG_SCHED_SMT
 	return first_cpu(cpu_sibling_map[cpu]);
@@ -125,44 +125,36 @@
 static DEFINE_PER_CPU(struct sched_domain, allnodes_domains);
 static struct sched_group sched_group_allnodes[MAX_NUMNODES];
 
-static int __devinit cpu_to_allnodes_group(int cpu)
+static int cpu_to_allnodes_group(int cpu)
 {
 	return cpu_to_node(cpu);
 }
 #endif
 
 /*
- * Set up scheduler domains and groups.  Callers must hold the hotplug lock.
+ * Build sched domains for a given set of cpus and attach the sched domains
+ * to the individual cpus
  */
-void __devinit arch_init_sched_domains(void)
+void build_sched_domains(const cpumask_t *cpu_map)
 {
 	int i;
-	cpumask_t cpu_default_map;
 
 	/*
-	 * Setup mask for cpus without special case scheduling requirements.
-	 * For now this just excludes isolated cpus, but could be used to
-	 * exclude other special cases in the future.
+	 * Set up domains for cpus specified by the cpu_map.
 	 */
-	cpus_complement(cpu_default_map, cpu_isolated_map);
-	cpus_and(cpu_default_map, cpu_default_map, cpu_online_map);
-
-	/*
-	 * Set up domains. Isolated domains just stay on the dummy domain.
-	 */
-	for_each_cpu_mask(i, cpu_default_map) {
+	for_each_cpu_mask(i, *cpu_map) {
 		int group;
 		struct sched_domain *sd = NULL, *p;
 		cpumask_t nodemask = node_to_cpumask(cpu_to_node(i));
 
-		cpus_and(nodemask, nodemask, cpu_default_map);
+		cpus_and(nodemask, nodemask, *cpu_map);
 
 #ifdef CONFIG_NUMA
 		if (num_online_cpus()
 				> SD_NODES_PER_DOMAIN*cpus_weight(nodemask)) {
 			sd = &per_cpu(allnodes_domains, i);
 			*sd = SD_ALLNODES_INIT;
-			sd->span = cpu_default_map;
+			sd->span = *cpu_map;
 			group = cpu_to_allnodes_group(i);
 			sd->groups = &sched_group_allnodes[group];
 			p = sd;
@@ -173,7 +165,7 @@
 		*sd = SD_NODE_INIT;
 		sd->span = sched_domain_node_span(cpu_to_node(i));
 		sd->parent = p;
-		cpus_and(sd->span, sd->span, cpu_default_map);
+		cpus_and(sd->span, sd->span, *cpu_map);
 #endif
 
 		p = sd;
@@ -190,7 +182,7 @@
 		group = cpu_to_cpu_group(i);
 		*sd = SD_SIBLING_INIT;
 		sd->span = cpu_sibling_map[i];
-		cpus_and(sd->span, sd->span, cpu_default_map);
+		cpus_and(sd->span, sd->span, *cpu_map);
 		sd->parent = p;
 		sd->groups = &sched_group_cpus[group];
 #endif
@@ -198,9 +190,9 @@
 
 #ifdef CONFIG_SCHED_SMT
 	/* Set up CPU (sibling) groups */
-	for_each_cpu_mask(i, cpu_default_map) {
+	for_each_cpu_mask(i, *cpu_map) {
 		cpumask_t this_sibling_map = cpu_sibling_map[i];
-		cpus_and(this_sibling_map, this_sibling_map, cpu_default_map);
+		cpus_and(this_sibling_map, this_sibling_map, *cpu_map);
 		if (i != first_cpu(this_sibling_map))
 			continue;
 
@@ -213,7 +205,7 @@
 	for (i = 0; i < MAX_NUMNODES; i++) {
 		cpumask_t nodemask = node_to_cpumask(i);
 
-		cpus_and(nodemask, nodemask, cpu_default_map);
+		cpus_and(nodemask, nodemask, *cpu_map);
 		if (cpus_empty(nodemask))
 			continue;
 
@@ -222,7 +214,7 @@
 	}
 
 #ifdef CONFIG_NUMA
-	init_sched_build_groups(sched_group_allnodes, cpu_default_map,
+	init_sched_build_groups(sched_group_allnodes, *cpu_map,
 				&cpu_to_allnodes_group);
 
 	for (i = 0; i < MAX_NUMNODES; i++) {
@@ -233,12 +225,12 @@
 		cpumask_t covered = CPU_MASK_NONE;
 		int j;
 
-		cpus_and(nodemask, nodemask, cpu_default_map);
+		cpus_and(nodemask, nodemask, *cpu_map);
 		if (cpus_empty(nodemask))
 			continue;
 
 		domainspan = sched_domain_node_span(i);
-		cpus_and(domainspan, domainspan, cpu_default_map);
+		cpus_and(domainspan, domainspan, *cpu_map);
 
 		sg = kmalloc(sizeof(struct sched_group), GFP_KERNEL);
 		sched_group_nodes[i] = sg;
@@ -266,7 +258,7 @@
 			int n = (i + j) % MAX_NUMNODES;
 
 			cpus_complement(notcovered, covered);
-			cpus_and(tmp, notcovered, cpu_default_map);
+			cpus_and(tmp, notcovered, *cpu_map);
 			cpus_and(tmp, tmp, domainspan);
 			if (cpus_empty(tmp))
 				break;
@@ -293,7 +285,7 @@
 #endif
 
 	/* Calculate CPU power for physical packages and nodes */
-	for_each_cpu_mask(i, cpu_default_map) {
+	for_each_cpu_mask(i, *cpu_map) {
 		int power;
 		struct sched_domain *sd;
 #ifdef CONFIG_SCHED_SMT
@@ -359,13 +351,35 @@
 		cpu_attach_domain(sd, i);
 	}
 }
+/*
+ * Set up scheduler domains and groups.  Callers must hold the hotplug lock.
+ */
+void arch_init_sched_domains(const cpumask_t *cpu_map)
+{
+	cpumask_t cpu_default_map;
 
-void __devinit arch_destroy_sched_domains(void)
+	/*
+	 * Setup mask for cpus without special case scheduling requirements.
+	 * For now this just excludes isolated cpus, but could be used to
+	 * exclude other special cases in the future.
+	 */
+	cpus_andnot(cpu_default_map, *cpu_map, cpu_isolated_map);
+
+	build_sched_domains(&cpu_default_map);
+}
+
+void arch_destroy_sched_domains(const cpumask_t *cpu_map)
 {
 #ifdef CONFIG_NUMA
 	int i;
 	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;
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 4a3b1aa..179f230 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -410,6 +410,38 @@
 }
 
 /*
+ * Walk the EFI memory map to pull out leftover pages in the lower
+ * memory regions which do not end up in the regular memory map and
+ * stick them into the uncached allocator
+ *
+ * The regular walk function is significantly more complex than the
+ * uncached walk which means it really doesn't make sense to try and
+ * marge the two.
+ */
+void __init
+efi_memmap_walk_uc (efi_freemem_callback_t callback)
+{
+	void *efi_map_start, *efi_map_end, *p;
+	efi_memory_desc_t *md;
+	u64 efi_desc_size, start, end;
+
+	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->attribute == EFI_MEMORY_UC) {
+			start = PAGE_ALIGN(md->phys_addr);
+			end = PAGE_ALIGN((md->phys_addr+(md->num_pages << EFI_PAGE_SHIFT)) & PAGE_MASK);
+			if ((*callback)(start, end, NULL) < 0)
+				return;
+		}
+	}
+}
+
+
+/*
  * Look for the PAL_CODE region reported by EFI and maps it using an
  * ITR to enable safe PAL calls in virtual mode.  See IA-64 Processor
  * Abstraction Layer chapter 11 in ADAG
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S
index d99316c..785a51b 100644
--- a/arch/ia64/kernel/entry.S
+++ b/arch/ia64/kernel/entry.S
@@ -1577,9 +1577,9 @@
 	data8 sys_add_key
 	data8 sys_request_key
 	data8 sys_keyctl
-	data8 sys_ni_syscall
-	data8 sys_ni_syscall			// 1275
-	data8 sys_ni_syscall
+	data8 sys_ioprio_set
+	data8 sys_ioprio_get			// 1275
+	data8 sys_set_zone_reclaim
 	data8 sys_ni_syscall
 	data8 sys_ni_syscall
 	data8 sys_ni_syscall
diff --git a/arch/ia64/kernel/entry.h b/arch/ia64/kernel/entry.h
index 6d4ecec..78eeb07 100644
--- a/arch/ia64/kernel/entry.h
+++ b/arch/ia64/kernel/entry.h
@@ -60,7 +60,7 @@
 	.spillsp @priunat,SW(AR_UNAT)+16+(off);					\
 	.spillsp ar.rnat,SW(AR_RNAT)+16+(off);					\
 	.spillsp ar.bspstore,SW(AR_BSPSTORE)+16+(off);				\
-	.spillsp pr,SW(PR)+16+(off))
+	.spillsp pr,SW(PR)+16+(off)
 
 #define DO_SAVE_SWITCH_STACK			\
 	movl r28=1f;				\
diff --git a/arch/ia64/kernel/fsys.S b/arch/ia64/kernel/fsys.S
index 4f3cdef..962b6c4 100644
--- a/arch/ia64/kernel/fsys.S
+++ b/arch/ia64/kernel/fsys.S
@@ -460,9 +460,9 @@
 	;;
 
 	st8 [r2]=r14				// update current->blocked with new mask
-	cmpxchg4.acq r14=[r9],r18,ar.ccv	// current->thread_info->flags <- r18
+	cmpxchg4.acq r8=[r9],r18,ar.ccv		// current->thread_info->flags <- r18
 	;;
-	cmp.ne p6,p0=r17,r14			// update failed?
+	cmp.ne p6,p0=r17,r8			// update failed?
 (p6)	br.cond.spnt.few 1b			// yes -> retry
 
 #ifdef CONFIG_SMP
diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S
index d9c05d5..2bc085a 100644
--- a/arch/ia64/kernel/ivt.S
+++ b/arch/ia64/kernel/ivt.S
@@ -405,17 +405,22 @@
 	 *		r30:	continuation address
 	 *		r31:	saved pr
 	 *
-	 * Clobbered:	b0, r18, r19, r21, psr.dt (cleared)
+	 * Clobbered:	b0, r18, r19, r21, r22, psr.dt (cleared)
 	 */
 	rsm psr.dt				// switch to using physical data addressing
 	mov r19=IA64_KR(PT_BASE)		// get the page table base address
 	shl r21=r16,3				// shift bit 60 into sign bit
+	mov r18=cr.itir
 	;;
 	shr.u r17=r16,61			// get the region number into r17
+	extr.u r18=r18,2,6			// get the faulting page size
 	;;
 	cmp.eq p6,p7=5,r17			// is faulting address in region 5?
-	shr.u r18=r16,PGDIR_SHIFT		// get bits 33-63 of faulting address
+	add r22=-PAGE_SHIFT,r18			// adjustment for hugetlb address
+	add r18=PGDIR_SHIFT-PAGE_SHIFT,r18
 	;;
+	shr.u r22=r16,r22
+	shr.u r18=r16,r18
 (p7)	dep r17=r17,r19,(PAGE_SHIFT-3),3	// put region number bits in place
 
 	srlz.d
@@ -428,7 +433,7 @@
 (p6)	dep r17=r18,r19,3,(PAGE_SHIFT-3)	// r17=PTA + IFA(33,42)*8
 (p7)	dep r17=r18,r17,3,(PAGE_SHIFT-6)	// r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8)
 	cmp.eq p7,p6=0,r21			// unused address bits all zeroes?
-	shr.u r18=r16,PMD_SHIFT			// shift L2 index into position
+	shr.u r18=r22,PMD_SHIFT			// shift L2 index into position
 	;;
 	ld8 r17=[r17]				// fetch the L1 entry (may be 0)
 	;;
@@ -436,7 +441,7 @@
 	dep r17=r18,r17,3,(PAGE_SHIFT-3)	// compute address of L2 page table entry
 	;;
 (p7)	ld8 r17=[r17]				// fetch the L2 entry (may be 0)
-	shr.u r19=r16,PAGE_SHIFT		// shift L3 index into position
+	shr.u r19=r22,PAGE_SHIFT		// shift L3 index into position
 	;;
 (p7)	cmp.eq.or.andcm p6,p7=r17,r0		// was L2 entry NULL?
 	dep r17=r19,r17,3,(PAGE_SHIFT-3)	// compute address of L3 page table entry
diff --git a/arch/ia64/kernel/jprobes.S b/arch/ia64/kernel/jprobes.S
new file mode 100644
index 0000000..b7fa3cc
--- /dev/null
+++ b/arch/ia64/kernel/jprobes.S
@@ -0,0 +1,61 @@
+/*
+ * Jprobe specific 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 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.
+ *
+ * Copyright (C) Intel Corporation, 2005
+ *
+ * 2005-May     Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
+ *              <anil.s.keshavamurthy@intel.com> initial implementation
+ *
+ * Jprobes (a.k.a. "jump probes" which is built on-top of kprobes) allow a
+ * probe to be inserted into the beginning of a function call.  The fundamental
+ * difference between a jprobe and a kprobe is the jprobe handler is executed
+ * in the same context as the target function, while the kprobe handlers
+ * are executed in interrupt context.
+ *
+ * For jprobes we initially gain control by placing a break point in the
+ * first instruction of the targeted function.  When we catch that specific
+ * break, we:
+ *        * set the return address to our jprobe_inst_return() function
+ *        * jump to the jprobe handler function
+ *
+ * Since we fixed up the return address, the jprobe handler will return to our
+ * jprobe_inst_return() function, giving us control again.  At this point we
+ * are back in the parents frame marker, so we do yet another call to our
+ * jprobe_break() function to fix up the frame marker as it would normally
+ * exist in the target function.
+ *
+ * Our jprobe_return function then transfers control back to kprobes.c by
+ * executing a break instruction using one of our reserved numbers.  When we
+ * catch that break in kprobes.c, we continue like we do for a normal kprobe
+ * by single stepping the emulated instruction, and then returning execution
+ * to the correct location.
+ */
+#include <asm/asmmacro.h>
+
+	/*
+	 * void jprobe_break(void)
+	 */
+ENTRY(jprobe_break)
+	break.m 0x80300
+END(jprobe_break)
+
+	/*
+	 * void jprobe_inst_return(void)
+	 */
+GLOBAL_ENTRY(jprobe_inst_return)
+	br.call.sptk.many b0=jprobe_break
+END(jprobe_inst_return)
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
new file mode 100644
index 0000000..5978823
--- /dev/null
+++ b/arch/ia64/kernel/kprobes.c
@@ -0,0 +1,601 @@
+/*
+ *  Kernel Probes (KProbes)
+ *  arch/ia64/kernel/kprobes.c
+ *
+ * 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.
+ *
+ * Copyright (C) IBM Corporation, 2002, 2004
+ * Copyright (C) Intel Corporation, 2005
+ *
+ * 2005-Apr     Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
+ *              <anil.s.keshavamurthy@intel.com> adapted from i386
+ */
+
+#include <linux/config.h>
+#include <linux/kprobes.h>
+#include <linux/ptrace.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/preempt.h>
+#include <linux/moduleloader.h>
+
+#include <asm/pgtable.h>
+#include <asm/kdebug.h>
+
+extern void jprobe_inst_return(void);
+
+/* kprobe_status settings */
+#define KPROBE_HIT_ACTIVE	0x00000001
+#define KPROBE_HIT_SS		0x00000002
+
+static struct kprobe *current_kprobe, *kprobe_prev;
+static unsigned long kprobe_status, kprobe_status_prev;
+static struct pt_regs jprobe_saved_regs;
+
+enum instruction_type {A, I, M, F, B, L, X, u};
+static enum instruction_type bundle_encoding[32][3] = {
+  { M, I, I },				/* 00 */
+  { M, I, I },				/* 01 */
+  { M, I, I },				/* 02 */
+  { M, I, I },				/* 03 */
+  { M, L, X },				/* 04 */
+  { M, L, X },				/* 05 */
+  { u, u, u },  			/* 06 */
+  { u, u, u },  			/* 07 */
+  { M, M, I },				/* 08 */
+  { M, M, I },				/* 09 */
+  { M, M, I },				/* 0A */
+  { M, M, I },				/* 0B */
+  { M, F, I },				/* 0C */
+  { M, F, I },				/* 0D */
+  { M, M, F },				/* 0E */
+  { M, M, F },				/* 0F */
+  { M, I, B },				/* 10 */
+  { M, I, B },				/* 11 */
+  { M, B, B },				/* 12 */
+  { M, B, B },				/* 13 */
+  { u, u, u },  			/* 14 */
+  { u, u, u },  			/* 15 */
+  { B, B, B },				/* 16 */
+  { B, B, B },				/* 17 */
+  { M, M, B },				/* 18 */
+  { M, M, B },				/* 19 */
+  { u, u, u },  			/* 1A */
+  { u, u, u },  			/* 1B */
+  { M, F, B },				/* 1C */
+  { M, F, B },				/* 1D */
+  { u, u, u },  			/* 1E */
+  { u, u, u },  			/* 1F */
+};
+
+/*
+ * In this function we check to see if the instruction
+ * is IP relative instruction and update the kprobe
+ * inst flag accordingly
+ */
+static void update_kprobe_inst_flag(uint template, uint  slot, uint major_opcode,
+	unsigned long kprobe_inst, struct kprobe *p)
+{
+	p->ainsn.inst_flag = 0;
+	p->ainsn.target_br_reg = 0;
+
+	if (bundle_encoding[template][slot] == B) {
+		switch (major_opcode) {
+		  case INDIRECT_CALL_OPCODE:
+	 		p->ainsn.inst_flag |= INST_FLAG_FIX_BRANCH_REG;
+ 			p->ainsn.target_br_reg = ((kprobe_inst >> 6) & 0x7);
+ 			break;
+		  case IP_RELATIVE_PREDICT_OPCODE:
+		  case IP_RELATIVE_BRANCH_OPCODE:
+			p->ainsn.inst_flag |= INST_FLAG_FIX_RELATIVE_IP_ADDR;
+ 			break;
+		  case IP_RELATIVE_CALL_OPCODE:
+ 			p->ainsn.inst_flag |= INST_FLAG_FIX_RELATIVE_IP_ADDR;
+ 			p->ainsn.inst_flag |= INST_FLAG_FIX_BRANCH_REG;
+ 			p->ainsn.target_br_reg = ((kprobe_inst >> 6) & 0x7);
+ 			break;
+		}
+ 	} else if (bundle_encoding[template][slot] == X) {
+		switch (major_opcode) {
+		  case LONG_CALL_OPCODE:
+			p->ainsn.inst_flag |= INST_FLAG_FIX_BRANCH_REG;
+			p->ainsn.target_br_reg = ((kprobe_inst >> 6) & 0x7);
+		  break;
+		}
+	}
+	return;
+}
+
+/*
+ * In this function we check to see if the instruction
+ * on which we are inserting kprobe is supported.
+ * Returns 0 if supported
+ * Returns -EINVAL if unsupported
+ */
+static int unsupported_inst(uint template, uint  slot, uint major_opcode,
+	unsigned long kprobe_inst, struct kprobe *p)
+{
+	unsigned long addr = (unsigned long)p->addr;
+
+	if (bundle_encoding[template][slot] == I) {
+		switch (major_opcode) {
+			case 0x0: //I_UNIT_MISC_OPCODE:
+			/*
+			 * Check for Integer speculation instruction
+			 * - Bit 33-35 to be equal to 0x1
+			 */
+			if (((kprobe_inst >> 33) & 0x7) == 1) {
+				printk(KERN_WARNING
+					"Kprobes on speculation inst at <0x%lx> not supported\n",
+					addr);
+				return -EINVAL;
+			}
+
+			/*
+			 * IP relative mov instruction
+			 *  - Bit 27-35 to be equal to 0x30
+			 */
+			if (((kprobe_inst >> 27) & 0x1FF) == 0x30) {
+				printk(KERN_WARNING
+					"Kprobes on \"mov r1=ip\" at <0x%lx> not supported\n",
+					addr);
+				return -EINVAL;
+
+			}
+		}
+	}
+	return 0;
+}
+
+
+/*
+ * In this function we check to see if the instruction
+ * (qp) cmpx.crel.ctype p1,p2=r2,r3
+ * on which we are inserting kprobe is cmp instruction
+ * with ctype as unc.
+ */
+static uint is_cmp_ctype_unc_inst(uint template, uint slot, uint major_opcode,
+unsigned long kprobe_inst)
+{
+	cmp_inst_t cmp_inst;
+	uint ctype_unc = 0;
+
+	if (!((bundle_encoding[template][slot] == I) ||
+		(bundle_encoding[template][slot] == M)))
+		goto out;
+
+	if (!((major_opcode == 0xC) || (major_opcode == 0xD) ||
+		(major_opcode == 0xE)))
+		goto out;
+
+	cmp_inst.l = kprobe_inst;
+	if ((cmp_inst.f.x2 == 0) || (cmp_inst.f.x2 == 1)) {
+		/* Integere compare - Register Register (A6 type)*/
+		if ((cmp_inst.f.tb == 0) && (cmp_inst.f.ta == 0)
+				&&(cmp_inst.f.c == 1))
+			ctype_unc = 1;
+	} else if ((cmp_inst.f.x2 == 2)||(cmp_inst.f.x2 == 3)) {
+		/* Integere compare - Immediate Register (A8 type)*/
+		if ((cmp_inst.f.ta == 0) &&(cmp_inst.f.c == 1))
+			ctype_unc = 1;
+	}
+out:
+	return ctype_unc;
+}
+
+/*
+ * In this function we override the bundle with
+ * the break instruction at the given slot.
+ */
+static void prepare_break_inst(uint template, uint  slot, uint major_opcode,
+	unsigned long kprobe_inst, struct kprobe *p)
+{
+	unsigned long break_inst = BREAK_INST;
+	bundle_t *bundle = &p->ainsn.insn.bundle;
+
+	/*
+	 * Copy the original kprobe_inst qualifying predicate(qp)
+	 * to the break instruction iff !is_cmp_ctype_unc_inst
+	 * because for cmp instruction with ctype equal to unc,
+	 * which is a special instruction always needs to be
+	 * executed regradless of qp
+	 */
+	if (!is_cmp_ctype_unc_inst(template, slot, major_opcode, kprobe_inst))
+		break_inst |= (0x3f & kprobe_inst);
+
+	switch (slot) {
+	  case 0:
+		bundle->quad0.slot0 = break_inst;
+		break;
+	  case 1:
+		bundle->quad0.slot1_p0 = break_inst;
+		bundle->quad1.slot1_p1 = break_inst >> (64-46);
+		break;
+	  case 2:
+		bundle->quad1.slot2 = break_inst;
+		break;
+	}
+
+	/*
+	 * Update the instruction flag, so that we can
+	 * emulate the instruction properly after we
+	 * single step on original instruction
+	 */
+	update_kprobe_inst_flag(template, slot, major_opcode, kprobe_inst, p);
+}
+
+static inline void get_kprobe_inst(bundle_t *bundle, uint slot,
+	       	unsigned long *kprobe_inst, uint *major_opcode)
+{
+	unsigned long kprobe_inst_p0, kprobe_inst_p1;
+	unsigned int template;
+
+	template = bundle->quad0.template;
+
+	switch (slot) {
+	  case 0:
+ 		*major_opcode = (bundle->quad0.slot0 >> SLOT0_OPCODE_SHIFT);
+ 		*kprobe_inst = bundle->quad0.slot0;
+		break;
+	  case 1:
+ 		*major_opcode = (bundle->quad1.slot1_p1 >> SLOT1_p1_OPCODE_SHIFT);
+  		kprobe_inst_p0 = bundle->quad0.slot1_p0;
+  		kprobe_inst_p1 = bundle->quad1.slot1_p1;
+  		*kprobe_inst = kprobe_inst_p0 | (kprobe_inst_p1 << (64-46));
+		break;
+	  case 2:
+ 		*major_opcode = (bundle->quad1.slot2 >> SLOT2_OPCODE_SHIFT);
+ 		*kprobe_inst = bundle->quad1.slot2;
+		break;
+	}
+}
+
+static int valid_kprobe_addr(int template, int slot, unsigned long addr)
+{
+	if ((slot > 2) || ((bundle_encoding[template][1] == L) && slot > 1)) {
+		printk(KERN_WARNING "Attempting to insert unaligned kprobe at 0x%lx\n",
+				addr);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static inline void save_previous_kprobe(void)
+{
+	kprobe_prev = current_kprobe;
+	kprobe_status_prev = kprobe_status;
+}
+
+static inline void restore_previous_kprobe(void)
+{
+	current_kprobe = kprobe_prev;
+	kprobe_status = kprobe_status_prev;
+}
+
+static inline void set_current_kprobe(struct kprobe *p)
+{
+	current_kprobe = p;
+}
+
+int arch_prepare_kprobe(struct kprobe *p)
+{
+	unsigned long addr = (unsigned long) p->addr;
+	unsigned long *kprobe_addr = (unsigned long *)(addr & ~0xFULL);
+	unsigned long kprobe_inst=0;
+	unsigned int slot = addr & 0xf, template, major_opcode = 0;
+	bundle_t *bundle = &p->ainsn.insn.bundle;
+
+	memcpy(&p->opcode.bundle, kprobe_addr, sizeof(bundle_t));
+	memcpy(&p->ainsn.insn.bundle, kprobe_addr, sizeof(bundle_t));
+
+ 	template = bundle->quad0.template;
+
+	if(valid_kprobe_addr(template, slot, addr))
+		return -EINVAL;
+
+	/* Move to slot 2, if bundle is MLX type and kprobe slot is 1 */
+ 	if (slot == 1 && bundle_encoding[template][1] == L)
+  		slot++;
+
+	/* Get kprobe_inst and major_opcode from the bundle */
+	get_kprobe_inst(bundle, slot, &kprobe_inst, &major_opcode);
+
+	if (unsupported_inst(template, slot, major_opcode, kprobe_inst, p))
+			return -EINVAL;
+
+	prepare_break_inst(template, slot, major_opcode, kprobe_inst, p);
+
+	return 0;
+}
+
+void arch_arm_kprobe(struct kprobe *p)
+{
+	unsigned long addr = (unsigned long)p->addr;
+	unsigned long arm_addr = addr & ~0xFULL;
+
+	memcpy((char *)arm_addr, &p->ainsn.insn.bundle, sizeof(bundle_t));
+	flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
+}
+
+void arch_disarm_kprobe(struct kprobe *p)
+{
+	unsigned long addr = (unsigned long)p->addr;
+	unsigned long arm_addr = addr & ~0xFULL;
+
+	/* p->opcode contains the original unaltered bundle */
+	memcpy((char *) arm_addr, (char *) &p->opcode.bundle, sizeof(bundle_t));
+	flush_icache_range(arm_addr, arm_addr + sizeof(bundle_t));
+}
+
+void arch_remove_kprobe(struct kprobe *p)
+{
+}
+
+/*
+ * We are resuming execution after a single step fault, so the pt_regs
+ * structure reflects the register state after we executed the instruction
+ * located in the kprobe (p->ainsn.insn.bundle).  We still need to adjust
+ * the ip to point back to the original stack address. To set the IP address
+ * to original stack address, handle the case where we need to fixup the
+ * relative IP address and/or fixup branch register.
+ */
+static void resume_execution(struct kprobe *p, struct pt_regs *regs)
+{
+  	unsigned long bundle_addr = ((unsigned long) (&p->opcode.bundle)) & ~0xFULL;
+  	unsigned long resume_addr = (unsigned long)p->addr & ~0xFULL;
+ 	unsigned long template;
+ 	int slot = ((unsigned long)p->addr & 0xf);
+
+	template = p->opcode.bundle.quad0.template;
+
+ 	if (slot == 1 && bundle_encoding[template][1] == L)
+ 		slot = 2;
+
+	if (p->ainsn.inst_flag) {
+
+		if (p->ainsn.inst_flag & INST_FLAG_FIX_RELATIVE_IP_ADDR) {
+			/* Fix relative IP address */
+ 			regs->cr_iip = (regs->cr_iip - bundle_addr) + resume_addr;
+		}
+
+		if (p->ainsn.inst_flag & INST_FLAG_FIX_BRANCH_REG) {
+		/*
+		 * Fix target branch register, software convention is
+		 * to use either b0 or b6 or b7, so just checking
+		 * only those registers
+		 */
+			switch (p->ainsn.target_br_reg) {
+			case 0:
+				if ((regs->b0 == bundle_addr) ||
+					(regs->b0 == bundle_addr + 0x10)) {
+					regs->b0 = (regs->b0 - bundle_addr) +
+						resume_addr;
+				}
+				break;
+			case 6:
+				if ((regs->b6 == bundle_addr) ||
+					(regs->b6 == bundle_addr + 0x10)) {
+					regs->b6 = (regs->b6 - bundle_addr) +
+						resume_addr;
+				}
+				break;
+			case 7:
+				if ((regs->b7 == bundle_addr) ||
+					(regs->b7 == bundle_addr + 0x10)) {
+					regs->b7 = (regs->b7 - bundle_addr) +
+						resume_addr;
+				}
+				break;
+			} /* end switch */
+		}
+		goto turn_ss_off;
+	}
+
+	if (slot == 2) {
+ 		if (regs->cr_iip == bundle_addr + 0x10) {
+ 			regs->cr_iip = resume_addr + 0x10;
+ 		}
+ 	} else {
+ 		if (regs->cr_iip == bundle_addr) {
+ 			regs->cr_iip = resume_addr;
+ 		}
+	}
+
+turn_ss_off:
+  	/* Turn off Single Step bit */
+  	ia64_psr(regs)->ss = 0;
+}
+
+static void prepare_ss(struct kprobe *p, struct pt_regs *regs)
+{
+	unsigned long bundle_addr = (unsigned long) &p->opcode.bundle;
+	unsigned long slot = (unsigned long)p->addr & 0xf;
+
+	/* Update instruction pointer (IIP) and slot number (IPSR.ri) */
+	regs->cr_iip = bundle_addr & ~0xFULL;
+
+	if (slot > 2)
+		slot = 0;
+
+	ia64_psr(regs)->ri = slot;
+
+	/* turn on single stepping */
+	ia64_psr(regs)->ss = 1;
+}
+
+static int pre_kprobes_handler(struct die_args *args)
+{
+	struct kprobe *p;
+	int ret = 0;
+	struct pt_regs *regs = args->regs;
+	kprobe_opcode_t *addr = (kprobe_opcode_t *)instruction_pointer(regs);
+
+	preempt_disable();
+
+	/* Handle recursion cases */
+	if (kprobe_running()) {
+		p = get_kprobe(addr);
+		if (p) {
+			if (kprobe_status == KPROBE_HIT_SS) {
+				unlock_kprobes();
+				goto no_kprobe;
+			}
+			/* We have reentered the pre_kprobe_handler(), since
+			 * another probe was hit while within the handler.
+			 * We here save the original kprobes variables and
+			 * just single step on the instruction of the new probe
+			 * without calling any user handlers.
+			 */
+			save_previous_kprobe();
+			set_current_kprobe(p);
+			p->nmissed++;
+			prepare_ss(p, regs);
+			kprobe_status = KPROBE_REENTER;
+			return 1;
+		} else if (args->err == __IA64_BREAK_JPROBE) {
+			/*
+			 * jprobe instrumented function just completed
+			 */
+			p = current_kprobe;
+			if (p->break_handler && p->break_handler(p, regs)) {
+				goto ss_probe;
+			}
+		} else {
+			/* Not our break */
+			goto no_kprobe;
+		}
+	}
+
+	lock_kprobes();
+	p = get_kprobe(addr);
+	if (!p) {
+		unlock_kprobes();
+		goto no_kprobe;
+	}
+
+	kprobe_status = KPROBE_HIT_ACTIVE;
+	set_current_kprobe(p);
+
+	if (p->pre_handler && p->pre_handler(p, regs))
+		/*
+		 * Our pre-handler is specifically requesting that we just
+		 * do a return.  This is handling the case where the
+		 * pre-handler is really our special jprobe pre-handler.
+		 */
+		return 1;
+
+ss_probe:
+	prepare_ss(p, regs);
+	kprobe_status = KPROBE_HIT_SS;
+	return 1;
+
+no_kprobe:
+	preempt_enable_no_resched();
+	return ret;
+}
+
+static int post_kprobes_handler(struct pt_regs *regs)
+{
+	if (!kprobe_running())
+		return 0;
+
+	if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) {
+		kprobe_status = KPROBE_HIT_SSDONE;
+		current_kprobe->post_handler(current_kprobe, regs, 0);
+	}
+
+	resume_execution(current_kprobe, regs);
+
+	/*Restore back the original saved kprobes variables and continue. */
+	if (kprobe_status == KPROBE_REENTER) {
+		restore_previous_kprobe();
+		goto out;
+	}
+
+	unlock_kprobes();
+
+out:
+	preempt_enable_no_resched();
+	return 1;
+}
+
+static int kprobes_fault_handler(struct pt_regs *regs, int trapnr)
+{
+	if (!kprobe_running())
+		return 0;
+
+	if (current_kprobe->fault_handler &&
+	    current_kprobe->fault_handler(current_kprobe, regs, trapnr))
+		return 1;
+
+	if (kprobe_status & KPROBE_HIT_SS) {
+		resume_execution(current_kprobe, regs);
+		unlock_kprobes();
+		preempt_enable_no_resched();
+	}
+
+	return 0;
+}
+
+int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
+			     void *data)
+{
+	struct die_args *args = (struct die_args *)data;
+	switch(val) {
+	case DIE_BREAK:
+		if (pre_kprobes_handler(args))
+			return NOTIFY_STOP;
+		break;
+	case DIE_SS:
+		if (post_kprobes_handler(args->regs))
+			return NOTIFY_STOP;
+		break;
+	case DIE_PAGE_FAULT:
+		if (kprobes_fault_handler(args->regs, args->trapnr))
+			return NOTIFY_STOP;
+	default:
+		break;
+	}
+	return NOTIFY_DONE;
+}
+
+int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	struct jprobe *jp = container_of(p, struct jprobe, kp);
+	unsigned long addr = ((struct fnptr *)(jp->entry))->ip;
+
+	/* save architectural state */
+	jprobe_saved_regs = *regs;
+
+	/* after rfi, execute the jprobe instrumented function */
+	regs->cr_iip = addr & ~0xFULL;
+	ia64_psr(regs)->ri = addr & 0xf;
+	regs->r1 = ((struct fnptr *)(jp->entry))->gp;
+
+	/*
+	 * fix the return address to our jprobe_inst_return() function
+	 * in the jprobes.S file
+	 */
+ 	regs->b0 = ((struct fnptr *)(jprobe_inst_return))->ip;
+
+	return 1;
+}
+
+int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	*regs = jprobe_saved_regs;
+	return 1;
+}
diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c
index febc091..f1aca7c 100644
--- a/arch/ia64/kernel/module.c
+++ b/arch/ia64/kernel/module.c
@@ -825,14 +825,16 @@
 		 * XXX Should have an arch-hook for running this after final section
 		 *     addresses have been selected...
 		 */
-		/* See if gp can cover the entire core module:  */
-		uint64_t gp = (uint64_t) mod->module_core + MAX_LTOFF / 2;
-		if (mod->core_size >= MAX_LTOFF)
+		uint64_t gp;
+		if (mod->core_size > MAX_LTOFF)
 			/*
 			 * This takes advantage of fact that SHF_ARCH_SMALL gets allocated
 			 * at the end of the module.
 			 */
-			gp = (uint64_t) mod->module_core + mod->core_size - MAX_LTOFF / 2;
+			gp = mod->core_size - MAX_LTOFF / 2;
+		else
+			gp = mod->core_size / 2;
+		gp = (uint64_t) mod->module_core + ((gp + 7) & -8);
 		mod->arch.gp = gp;
 		DEBUGP("%s: placing gp at 0x%lx\n", __FUNCTION__, gp);
 	}
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index 08c8a5e..6d57aeb 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -635,11 +635,17 @@
 {
 	struct ia64_psr *psr = ia64_psr(ia64_task_regs(task));
 
+	/*
+	 * Prevent migrating this task while
+	 * we're fiddling with the FPU state
+	 */
+	preempt_disable();
 	if (ia64_is_local_fpu_owner(task) && psr->mfh) {
 		psr->mfh = 0;
 		task->thread.flags |= IA64_THREAD_FPH_VALID;
 		ia64_save_fpu(&task->thread.fph[0]);
 	}
+	preempt_enable();
 }
 
 /*
@@ -939,6 +945,13 @@
 				*data = (pt->cr_ipsr & IPSR_MASK);
 			return 0;
 
+		      case PT_AR_RSC:
+			if (write_access)
+				pt->ar_rsc = *data | (3 << 2); /* force PL3 */
+			else
+				*data = pt->ar_rsc;
+			return 0;
+
 		      case PT_AR_RNAT:
 			urbs_end = ia64_get_user_rbs_end(child, pt, NULL);
 			rnat_addr = (long) ia64_rse_rnat_addr((long *)
@@ -990,9 +1003,6 @@
 		      case PT_AR_BSPSTORE:
 			ptr = pt_reg_addr(pt, ar_bspstore);
 			break;
-		      case PT_AR_RSC:
-			ptr = pt_reg_addr(pt, ar_rsc);
-			break;
 		      case PT_AR_UNAT:
 			ptr = pt_reg_addr(pt, ar_unat);
 			break;
@@ -1228,7 +1238,7 @@
 static long
 ptrace_setregs (struct task_struct *child, struct pt_all_user_regs __user *ppr)
 {
-	unsigned long psr, ec, lc, rnat, bsp, cfm, nat_bits, val = 0;
+	unsigned long psr, rsc, ec, lc, rnat, bsp, cfm, nat_bits, val = 0;
 	struct unw_frame_info info;
 	struct switch_stack *sw;
 	struct ia64_fpreg fpval;
@@ -1261,7 +1271,7 @@
 	/* app regs */
 
 	retval |= __get_user(pt->ar_pfs, &ppr->ar[PT_AUR_PFS]);
-	retval |= __get_user(pt->ar_rsc, &ppr->ar[PT_AUR_RSC]);
+	retval |= __get_user(rsc, &ppr->ar[PT_AUR_RSC]);
 	retval |= __get_user(pt->ar_bspstore, &ppr->ar[PT_AUR_BSPSTORE]);
 	retval |= __get_user(pt->ar_unat, &ppr->ar[PT_AUR_UNAT]);
 	retval |= __get_user(pt->ar_ccv, &ppr->ar[PT_AUR_CCV]);
@@ -1359,6 +1369,7 @@
 	retval |= __get_user(nat_bits, &ppr->nat);
 
 	retval |= access_uarea(child, PT_CR_IPSR, &psr, 1);
+	retval |= access_uarea(child, PT_AR_RSC, &rsc, 1);
 	retval |= access_uarea(child, PT_AR_EC, &ec, 1);
 	retval |= access_uarea(child, PT_AR_LC, &lc, 1);
 	retval |= access_uarea(child, PT_AR_RNAT, &rnat, 1);
diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c
index b7e6b4c..d14692e 100644
--- a/arch/ia64/kernel/setup.c
+++ b/arch/ia64/kernel/setup.c
@@ -720,7 +720,8 @@
 	ia64_set_kr(IA64_KR_PT_BASE, __pa(ia64_imva(empty_zero_page)));
 
 	/*
-	 * Initialize default control register to defer all speculative faults.  The
+	 * Initialize default control register to defer speculative faults except
+	 * for those arising from TLB misses, which are not deferred.  The
 	 * kernel MUST NOT depend on a particular setting of these bits (in other words,
 	 * the kernel must have recovery code for all speculative accesses).  Turn on
 	 * dcr.lc as per recommendation by the architecture team.  Most IA-32 apps
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
index 499b7e5..edd9f07 100644
--- a/arch/ia64/kernel/signal.c
+++ b/arch/ia64/kernel/signal.c
@@ -94,7 +94,7 @@
 static long
 restore_sigcontext (struct sigcontext __user *sc, struct sigscratch *scr)
 {
-	unsigned long ip, flags, nat, um, cfm;
+	unsigned long ip, flags, nat, um, cfm, rsc;
 	long err;
 
 	/* Always make any pending restarted system calls return -EINTR */
@@ -106,7 +106,7 @@
 	err |= __get_user(ip, &sc->sc_ip);			/* instruction pointer */
 	err |= __get_user(cfm, &sc->sc_cfm);
 	err |= __get_user(um, &sc->sc_um);			/* user mask */
-	err |= __get_user(scr->pt.ar_rsc, &sc->sc_ar_rsc);
+	err |= __get_user(rsc, &sc->sc_ar_rsc);
 	err |= __get_user(scr->pt.ar_unat, &sc->sc_ar_unat);
 	err |= __get_user(scr->pt.ar_fpsr, &sc->sc_ar_fpsr);
 	err |= __get_user(scr->pt.ar_pfs, &sc->sc_ar_pfs);
@@ -119,6 +119,7 @@
 	err |= __copy_from_user(&scr->pt.r15, &sc->sc_gr[15], 8);	/* r15 */
 
 	scr->pt.cr_ifs = cfm | (1UL << 63);
+	scr->pt.ar_rsc = rsc | (3 << 2); /* force PL3 */
 
 	/* establish new instruction pointer: */
 	scr->pt.cr_iip = ip & ~0x3UL;
diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c
index 953095e..b49d4dd 100644
--- a/arch/ia64/kernel/smp.c
+++ b/arch/ia64/kernel/smp.c
@@ -269,7 +269,7 @@
 	int me = get_cpu(); /* prevent preemption and reschedule on another processor */
 
 	if (cpuid == me) {
-		printk("%s: trying to call self\n", __FUNCTION__);
+		printk(KERN_INFO "%s: trying to call self\n", __FUNCTION__);
 		put_cpu();
 		return -EBUSY;
 	}
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 3865f08..623b0a5 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -346,6 +346,7 @@
 	lock_ipi_calllock();
 	cpu_set(cpuid, cpu_online_map);
 	unlock_ipi_calllock();
+	per_cpu(cpu_state, cpuid) = CPU_ONLINE;
 
 	smp_setup_percpu_timer();
 
@@ -611,6 +612,7 @@
 {
 	cpu_set(smp_processor_id(), cpu_online_map);
 	cpu_set(smp_processor_id(), cpu_callin_map);
+	per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
 }
 
 /*
@@ -688,6 +690,7 @@
 		return -EBUSY;
 
 	remove_siblinginfo(cpu);
+	cpu_clear(cpu, cpu_online_map);
 	fixup_irqs();
 	local_flush_tlb_all();
 	cpu_clear(cpu, cpu_callin_map);
@@ -774,6 +777,7 @@
 	if (cpu_isset(cpu, cpu_callin_map))
 		return -EINVAL;
 
+	per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
 	/* Processor goes to start_secondary(), sets online flag */
 	ret = do_boot_cpu(sapicid, cpu);
 	if (ret < 0)
diff --git a/arch/ia64/kernel/traps.c b/arch/ia64/kernel/traps.c
index e82ad78..e7e520d 100644
--- a/arch/ia64/kernel/traps.c
+++ b/arch/ia64/kernel/traps.c
@@ -21,12 +21,26 @@
 #include <asm/intrinsics.h>
 #include <asm/processor.h>
 #include <asm/uaccess.h>
+#include <asm/kdebug.h>
 
 extern spinlock_t timerlist_lock;
 
 fpswa_interface_t *fpswa_interface;
 EXPORT_SYMBOL(fpswa_interface);
 
+struct notifier_block *ia64die_chain;
+static DEFINE_SPINLOCK(die_notifier_lock);
+
+int register_die_notifier(struct notifier_block *nb)
+{
+	int err = 0;
+	unsigned long flags;
+	spin_lock_irqsave(&die_notifier_lock, flags);
+	err = notifier_chain_register(&ia64die_chain, nb);
+	spin_unlock_irqrestore(&die_notifier_lock, flags);
+	return err;
+}
+
 void __init
 trap_init (void)
 {
@@ -111,6 +125,24 @@
 	siginfo_t siginfo;
 	int sig, code;
 
+	/* break.b always sets cr.iim to 0, which causes problems for
+	 * debuggers.  Get the real break number from the original instruction,
+	 * but only for kernel code.  User space break.b is left alone, to
+	 * preserve the existing behaviour.  All break codings have the same
+	 * format, so there is no need to check the slot type.
+	 */
+	if (break_num == 0 && !user_mode(regs)) {
+		struct ia64_psr *ipsr = ia64_psr(regs);
+		unsigned long *bundle = (unsigned long *)regs->cr_iip;
+		unsigned long slot;
+		switch (ipsr->ri) {
+		      case 0:  slot = (bundle[0] >>  5); break;
+		      case 1:  slot = (bundle[0] >> 46) | (bundle[1] << 18); break;
+		      default: slot = (bundle[1] >> 23); break;
+		}
+		break_num = ((slot >> 36 & 1) << 20) | (slot >> 6 & 0xfffff);
+	}
+
 	/* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */
 	siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
 	siginfo.si_imm = break_num;
@@ -119,6 +151,10 @@
 
 	switch (break_num) {
 	      case 0: /* unknown error (used by GCC for __builtin_abort()) */
+		if (notify_die(DIE_BREAK, "break 0", regs, break_num, TRAP_BRKPT, SIGTRAP)
+			       	== NOTIFY_STOP) {
+			return;
+		}
 		die_if_kernel("bugcheck!", regs, break_num);
 		sig = SIGILL; code = ILL_ILLOPC;
 		break;
@@ -171,6 +207,15 @@
 		sig = SIGILL; code = __ILL_BNDMOD;
 		break;
 
+	      case 0x80200:
+	      case 0x80300:
+		if (notify_die(DIE_BREAK, "kprobe", regs, break_num, TRAP_BRKPT, SIGTRAP)
+			       	== NOTIFY_STOP) {
+			return;
+		}
+		sig = SIGTRAP; code = TRAP_BRKPT;
+		break;
+
 	      default:
 		if (break_num < 0x40000 || break_num > 0x100000)
 			die_if_kernel("Bad break", regs, break_num);
@@ -202,13 +247,21 @@
 
 	/* first, grant user-level access to fph partition: */
 	psr->dfh = 0;
+
+	/*
+	 * Make sure that no other task gets in on this processor
+	 * while we're claiming the FPU
+	 */
+	preempt_disable();
 #ifndef CONFIG_SMP
 	{
 		struct task_struct *fpu_owner
 			= (struct task_struct *)ia64_get_kr(IA64_KR_FPU_OWNER);
 
-		if (ia64_is_local_fpu_owner(current))
+		if (ia64_is_local_fpu_owner(current)) {
+			preempt_enable_no_resched();
 			return;
+		}
 
 		if (fpu_owner)
 			ia64_flush_fph(fpu_owner);
@@ -226,6 +279,7 @@
 		 */
 		psr->mfh = 1;
 	}
+	preempt_enable_no_resched();
 }
 
 static inline int
@@ -521,7 +575,11 @@
 #endif
 			break;
 		      case 35: siginfo.si_code = TRAP_BRANCH; ifa = 0; break;
-		      case 36: siginfo.si_code = TRAP_TRACE; ifa = 0; break;
+		      case 36:
+			      if (notify_die(DIE_SS, "ss", &regs, vector,
+					     vector, SIGTRAP) == NOTIFY_STOP)
+				      return;
+			      siginfo.si_code = TRAP_TRACE; ifa = 0; break;
 		}
 		siginfo.si_signo = SIGTRAP;
 		siginfo.si_errno = 0;
diff --git a/arch/ia64/kernel/uncached.c b/arch/ia64/kernel/uncached.c
new file mode 100644
index 0000000..490dfc9
--- /dev/null
+++ b/arch/ia64/kernel/uncached.c
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 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 version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * A simple uncached page allocator using the generic allocator. This
+ * allocator first utilizes the spare (spill) pages found in the EFI
+ * memmap and will then start converting cached pages to uncached ones
+ * at a granule at a time. Node awareness is implemented by having a
+ * pool of pages per node.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/efi.h>
+#include <linux/genalloc.h>
+#include <asm/page.h>
+#include <asm/pal.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/atomic.h>
+#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);
+
+#define MAX_UNCACHED_GRANULES	5
+static int allocated_granules;
+
+struct gen_pool *uncached_pool[MAX_NUMNODES];
+
+
+static void uncached_ipi_visibility(void *data)
+{
+	int status;
+
+	status = ia64_pal_prefetch_visibility(PAL_VISIBILITY_PHYSICAL);
+	if ((status != PAL_VISIBILITY_OK) &&
+	    (status != PAL_VISIBILITY_OK_REMOTE_NEEDED))
+		printk(KERN_DEBUG "pal_prefetch_visibility() returns %i on "
+		       "CPU %i\n", status, get_cpu());
+}
+
+
+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 "
+		       "CPU %i\n", status, get_cpu());
+}
+
+
+static unsigned long
+uncached_get_new_chunk(struct gen_pool *poolp)
+{
+	struct page *page;
+	void *tmp;
+	int status, i;
+	unsigned long addr, node;
+
+	if (allocated_granules >= MAX_UNCACHED_GRANULES)
+		return 0;
+
+	node = poolp->private;
+	page = alloc_pages_node(node, 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);
+
+	/*
+	 * There's a small race here where it's possible for someone to
+	 * access the page through /dev/mem halfway through the conversion
+	 * to uncached - not sure it's really worth bothering about
+	 */
+	for (i = 0; i < (IA64_GRANULE_SIZE / PAGE_SIZE); i++)
+		SetPageUncached(&page[i]);
+
+	flush_tlb_kernel_range(tmp, tmp + IA64_GRANULE_SIZE);
+
+	status = ia64_pal_prefetch_visibility(PAL_VISIBILITY_PHYSICAL);
+
+	dprintk(KERN_INFO "pal_prefetch_visibility() returns %i on cpu %i\n",
+		status, get_cpu());
+
+	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);
+	}
+
+	if (ia64_platform_is("sn2"))
+		sn_flush_all_caches((unsigned long)tmp, IA64_GRANULE_SIZE);
+	else
+		flush_icache_range((unsigned long)tmp,
+				   (unsigned long)tmp+IA64_GRANULE_SIZE);
+
+	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);
+
+	addr = (unsigned long)tmp - PAGE_OFFSET + __IA64_UNCACHED_OFFSET;
+
+	allocated_granules++;
+	return addr;
+}
+
+
+/*
+ * uncached_alloc_page
+ *
+ * Allocate 1 uncached page. Allocates on the requested node. If no
+ * uncached pages are available on the requested node, roundrobin starting
+ * with higher nodes.
+ */
+unsigned long
+uncached_alloc_page(int nid)
+{
+	unsigned long maddr;
+
+	maddr = gen_pool_alloc(uncached_pool[nid], PAGE_SIZE);
+
+	dprintk(KERN_DEBUG "uncached_alloc_page returns %lx on node %i\n",
+		maddr, nid);
+
+	/*
+	 * If no memory is availble on our local node, try the
+	 * remaining nodes in the system.
+	 */
+	if (!maddr) {
+		int i;
+
+		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;
+			}
+		}
+	}
+
+	return maddr;
+}
+EXPORT_SYMBOL(uncached_alloc_page);
+
+
+/*
+ * uncached_free_page
+ *
+ * Free a single uncached page.
+ */
+void
+uncached_free_page(unsigned long maddr)
+{
+	int node;
+
+	node = nasid_to_cnodeid(NASID_GET(maddr));
+
+	dprintk(KERN_DEBUG "uncached_free_page(%lx) on node %i\n", maddr, node);
+
+	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);
+}
+EXPORT_SYMBOL(uncached_free_page);
+
+
+/*
+ * uncached_build_memmap,
+ *
+ * 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)
+{
+	long length;
+	unsigned long vstart, vend;
+	int node;
+
+	length = end - start;
+	vstart = start + __IA64_UNCACHED_OFFSET;
+	vend = end + __IA64_UNCACHED_OFFSET;
+
+	dprintk(KERN_ERR "uncached_build_memmap(%lx %lx)\n", start, end);
+
+	memset((char *)vstart, 0, length);
+
+	node = nasid_to_cnodeid(NASID_GET(start));
+
+	for (; vstart < vend ; vstart += PAGE_SIZE) {
+		dprintk(KERN_INFO "sticking %lx into the pool!\n", vstart);
+		gen_pool_free(uncached_pool[node], vstart, PAGE_SIZE);
+	}
+
+	return 0;
+}
+
+
+static int __init uncached_init(void) {
+	int i;
+
+	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);
+	}
+
+	efi_memmap_walk_uc(uncached_build_memmap);
+
+	return 0;
+}
+
+__initcall(uncached_init);
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index c007109..f3fd528 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -560,14 +560,15 @@
 		int shared = 0, cached = 0, reserved = 0;
 		printk("Node ID: %d\n", pgdat->node_id);
 		for(i = 0; i < pgdat->node_spanned_pages; i++) {
+			struct page *page = pgdat_page_nr(pgdat, i);
 			if (!ia64_pfn_valid(pgdat->node_start_pfn+i))
 				continue;
-			if (PageReserved(pgdat->node_mem_map+i))
+			if (PageReserved(page))
 				reserved++;
-			else if (PageSwapCache(pgdat->node_mem_map+i))
+			else if (PageSwapCache(page))
 				cached++;
-			else if (page_count(pgdat->node_mem_map+i))
-				shared += page_count(pgdat->node_mem_map+i)-1;
+			else if (page_count(page))
+				shared += page_count(page)-1;
 		}
 		total_present += present;
 		total_reserved += reserved;
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
index 4174ec9..ff62551 100644
--- a/arch/ia64/mm/fault.c
+++ b/arch/ia64/mm/fault.c
@@ -14,6 +14,7 @@
 #include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/kdebug.h>
 
 extern void die (char *, struct pt_regs *, long);
 
@@ -102,6 +103,13 @@
 		goto bad_area_no_up;
 #endif
 
+	/*
+	 * This is to handle the kprobes on user space access instructions
+	 */
+	if (notify_die(DIE_PAGE_FAULT, "page fault", regs, code, TRAP_BRKPT,
+					SIGSEGV) == NOTIFY_STOP)
+		return;
+
 	down_read(&mm->mmap_sem);
 
 	vma = find_vma_prev(mm, address, &prev_vma);
diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c
index df08ae7..e0a776a 100644
--- a/arch/ia64/mm/hugetlbpage.c
+++ b/arch/ia64/mm/hugetlbpage.c
@@ -24,7 +24,7 @@
 
 unsigned int hpage_shift=HPAGE_SHIFT_DEFAULT;
 
-static pte_t *
+pte_t *
 huge_pte_alloc (struct mm_struct *mm, unsigned long addr)
 {
 	unsigned long taddr = htlbpage_to_page(addr);
@@ -43,7 +43,7 @@
 	return pte;
 }
 
-static pte_t *
+pte_t *
 huge_pte_offset (struct mm_struct *mm, unsigned long addr)
 {
 	unsigned long taddr = htlbpage_to_page(addr);
@@ -67,23 +67,6 @@
 
 #define mk_pte_huge(entry) { pte_val(entry) |= _PAGE_P; }
 
-static void
-set_huge_pte (struct mm_struct *mm, struct vm_area_struct *vma,
-	      struct page *page, pte_t * page_table, int write_access)
-{
-	pte_t entry;
-
-	add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
-	if (write_access) {
-		entry =
-		    pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
-	} else
-		entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot));
-	entry = pte_mkyoung(entry);
-	mk_pte_huge(entry);
-	set_pte(page_table, entry);
-	return;
-}
 /*
  * This function checks for proper alignment of input addr and len parameters.
  */
@@ -99,68 +82,6 @@
 	return 0;
 }
 
-int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
-			struct vm_area_struct *vma)
-{
-	pte_t *src_pte, *dst_pte, entry;
-	struct page *ptepage;
-	unsigned long addr = vma->vm_start;
-	unsigned long end = vma->vm_end;
-
-	while (addr < end) {
-		dst_pte = huge_pte_alloc(dst, addr);
-		if (!dst_pte)
-			goto nomem;
-		src_pte = huge_pte_offset(src, addr);
-		entry = *src_pte;
-		ptepage = pte_page(entry);
-		get_page(ptepage);
-		set_pte(dst_pte, entry);
-		add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
-		addr += HPAGE_SIZE;
-	}
-	return 0;
-nomem:
-	return -ENOMEM;
-}
-
-int
-follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
-		    struct page **pages, struct vm_area_struct **vmas,
-		    unsigned long *st, int *length, int i)
-{
-	pte_t *ptep, pte;
-	unsigned long start = *st;
-	unsigned long pstart;
-	int len = *length;
-	struct page *page;
-
-	do {
-		pstart = start & HPAGE_MASK;
-		ptep = huge_pte_offset(mm, start);
-		pte = *ptep;
-
-back1:
-		page = pte_page(pte);
-		if (pages) {
-			page += ((start & ~HPAGE_MASK) >> PAGE_SHIFT);
-			get_page(page);
-			pages[i] = page;
-		}
-		if (vmas)
-			vmas[i] = vma;
-		i++;
-		len--;
-		start += PAGE_SIZE;
-		if (((start & HPAGE_MASK) == pstart) && len &&
-				(start < vma->vm_end))
-			goto back1;
-	} while (len && start < vma->vm_end);
-	*length = len;
-	*st = start;
-	return i;
-}
-
 struct page *follow_huge_addr(struct mm_struct *mm, unsigned long addr, int write)
 {
 	struct page *page;
@@ -212,81 +133,6 @@
 	free_pgd_range(tlb, addr, end, floor, ceiling);
 }
 
-void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
-{
-	struct mm_struct *mm = vma->vm_mm;
-	unsigned long address;
-	pte_t *pte;
-	struct page *page;
-
-	BUG_ON(start & (HPAGE_SIZE - 1));
-	BUG_ON(end & (HPAGE_SIZE - 1));
-
-	for (address = start; address < end; address += HPAGE_SIZE) {
-		pte = huge_pte_offset(mm, address);
-		if (pte_none(*pte))
-			continue;
-		page = pte_page(*pte);
-		put_page(page);
-		pte_clear(mm, address, pte);
-	}
-	add_mm_counter(mm, rss, - ((end - start) >> PAGE_SHIFT));
-	flush_tlb_range(vma, start, end);
-}
-
-int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
-{
-	struct mm_struct *mm = current->mm;
-	unsigned long addr;
-	int ret = 0;
-
-	BUG_ON(vma->vm_start & ~HPAGE_MASK);
-	BUG_ON(vma->vm_end & ~HPAGE_MASK);
-
-	spin_lock(&mm->page_table_lock);
-	for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
-		unsigned long idx;
-		pte_t *pte = huge_pte_alloc(mm, addr);
-		struct page *page;
-
-		if (!pte) {
-			ret = -ENOMEM;
-			goto out;
-		}
-		if (!pte_none(*pte))
-			continue;
-
-		idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
-			+ (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
-		page = find_get_page(mapping, idx);
-		if (!page) {
-			/* charge the fs quota first */
-			if (hugetlb_get_quota(mapping)) {
-				ret = -ENOMEM;
-				goto out;
-			}
-			page = alloc_huge_page();
-			if (!page) {
-				hugetlb_put_quota(mapping);
-				ret = -ENOMEM;
-				goto out;
-			}
-			ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
-			if (! ret) {
-				unlock_page(page);
-			} else {
-				hugetlb_put_quota(mapping);
-				page_cache_release(page);
-				goto out;
-			}
-		}
-		set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
-	}
-out:
-	spin_unlock(&mm->page_table_lock);
-	return ret;
-}
-
 unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
 		unsigned long pgoff, unsigned long flags)
 {
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index 547785e..4eb2f52 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -305,8 +305,9 @@
 	struct page *page;
 
 	/*
-	 * Map the gate page twice: once read-only to export the ELF headers etc. and once
-	 * execute-only page to enable privilege-promotion via "epc":
+	 * Map the gate page twice: once read-only to export the ELF
+	 * headers etc. and once execute-only page to enable
+	 * privilege-promotion via "epc":
 	 */
 	page = virt_to_page(ia64_imva(__start_gate_section));
 	put_kernel_page(page, GATE_ADDR, PAGE_READONLY);
@@ -315,6 +316,20 @@
 	put_kernel_page(page, GATE_ADDR + PAGE_SIZE, PAGE_GATE);
 #else
 	put_kernel_page(page, GATE_ADDR + PERCPU_PAGE_SIZE, PAGE_GATE);
+	/* Fill in the holes (if any) with read-only zero pages: */
+	{
+		unsigned long addr;
+
+		for (addr = GATE_ADDR + PAGE_SIZE;
+		     addr < GATE_ADDR + PERCPU_PAGE_SIZE;
+		     addr += PAGE_SIZE)
+		{
+			put_kernel_page(ZERO_PAGE(0), addr,
+					PAGE_READONLY);
+			put_kernel_page(ZERO_PAGE(0), addr + PERCPU_PAGE_SIZE,
+					PAGE_READONLY);
+		}
+	}
 #endif
 	ia64_patch_gate();
 }
diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 88641e5..e3fc4ed 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -33,8 +33,6 @@
 #include <asm/hw_irq.h>
 
 
-static int pci_routeirq;
-
 /*
  * Low-level SAL-based PCI configuration access functions. Note that SAL
  * calls are already serialized (via sal_lock), so we don't need another
@@ -139,24 +137,8 @@
 static int __init
 pci_acpi_init (void)
 {
-	struct pci_dev *dev = NULL;
-
-	printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
-
 	acpi_map_iosapics();
 
-	if (pci_routeirq) {
-		/*
-		 * PCI IRQ routing is set up by pci_enable_device(), but we
-		 * also do it here in case there are still broken drivers that
-		 * don't use pci_enable_device().
-		 */
-		printk(KERN_INFO "PCI: Routing interrupts for all devices because \"pci=routeirq\" specified\n");
-		for_each_pci_dev(dev)
-			acpi_pci_irq_enable(dev);
-	} else
-		printk(KERN_INFO "PCI: If a device doesn't work, try \"pci=routeirq\".  If it helps, post a report\n");
-
 	return 0;
 }
 
@@ -500,8 +482,6 @@
 char * __init
 pcibios_setup (char *str)
 {
-	if (!strcmp(str, "routeirq"))
-		pci_routeirq = 1;
 	return NULL;
 }
 
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c
index e64cb81..44bfc7f 100644
--- a/arch/ia64/sn/kernel/setup.c
+++ b/arch/ia64/sn/kernel/setup.c
@@ -222,7 +222,7 @@
 
 extern int platform_intr_list[];
 extern nasid_t master_nasid;
-static int shub_1_1_found __initdata;
+static int __initdata shub_1_1_found = 0;
 
 /*
  * sn_check_for_wars
@@ -251,7 +251,7 @@
 	} else {
 		for_each_online_node(cnode) {
 			if (is_shub_1_1(cnodeid_to_nasid(cnode)))
-				sn_hub_info->shub_1_1_found = 1;
+				shub_1_1_found = 1;
 		}
 	}
 }
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c
index ab9b5f3..a087b27 100644
--- a/arch/ia64/sn/kernel/tiocx.c
+++ b/arch/ia64/sn/kernel/tiocx.c
@@ -432,7 +432,7 @@
 	return cx_device_reload(cx_dev);
 }
 
-static ssize_t show_cxdev_control(struct device *dev, char *buf)
+static ssize_t show_cxdev_control(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct cx_dev *cx_dev = to_cx_dev(dev);
 
@@ -442,7 +442,7 @@
 		       tiocx_btchar_get(cx_dev->cx_id.nasid));
 }
 
-static ssize_t store_cxdev_control(struct device *dev, const char *buf,
+static ssize_t store_cxdev_control(struct device *dev, struct device_attribute *attr, const char *buf,
 				   size_t count)
 {
 	int n;
@@ -518,25 +518,22 @@
 	return 0;
 }
 
+static int cx_remove_device(struct device * dev, void * data)
+{
+	struct cx_dev *cx_dev = to_cx_dev(dev);
+	device_remove_file(dev, &dev_attr_cxdev_control);
+	cx_device_unregister(cx_dev);
+	return 0;
+}
+
 static void __exit tiocx_exit(void)
 {
-	struct device *dev;
-	struct device *tdev;
-
 	DBG("tiocx_exit\n");
 
 	/*
 	 * Unregister devices.
 	 */
-	list_for_each_entry_safe(dev, tdev, &tiocx_bus_type.devices.list,
-				 bus_list) {
-		if (dev) {
-			struct cx_dev *cx_dev = to_cx_dev(dev);
-			device_remove_file(dev, &dev_attr_cxdev_control);
-			cx_device_unregister(cx_dev);
-		}
-	}
-
+	bus_for_each_dev(&tiocx_bus_type, NULL, NULL, cx_remove_device);
 	bus_unregister(&tiocx_bus_type);
 }
 
diff --git a/arch/ia64/sn/kernel/xpc.h b/arch/ia64/sn/kernel/xpc.h
index 1a0aed8..d0ee635 100644
--- a/arch/ia64/sn/kernel/xpc.h
+++ b/arch/ia64/sn/kernel/xpc.h
@@ -87,7 +87,7 @@
 	u8 partid;		/* partition ID from SAL */
 	u8 version;
 	u8 pad[6];		/* pad to u64 align */
-	u64 vars_pa;
+	volatile u64 vars_pa;
 	u64 part_nasids[XP_NASID_MASK_WORDS] ____cacheline_aligned;
 	u64 mach_nasids[XP_NASID_MASK_WORDS] ____cacheline_aligned;
 };
@@ -138,7 +138,7 @@
  * occupies half a cacheline.
  */
 struct xpc_vars_part {
-	u64 magic;
+	volatile u64 magic;
 
 	u64 openclose_args_pa;	/* physical address of open and close args */
 	u64 GPs_pa;		/* physical address of Get/Put values */
@@ -185,8 +185,8 @@
  * Define a Get/Put value pair (pointers) used with a message queue.
  */
 struct xpc_gp {
-	s64 get;	/* Get value */
-	s64 put;	/* Put value */
+	volatile s64 get;	/* Get value */
+	volatile s64 put;	/* Put value */
 };
 
 #define XPC_GP_SIZE \
@@ -231,7 +231,7 @@
  */
 struct xpc_notify {
 	struct semaphore sema;		/* notify semaphore */
-	u8 type;			/* type of notification */
+	volatile u8 type;			/* type of notification */
 
 	/* the following two fields are only used if type == XPC_N_CALL */
 	xpc_notify_func func;		/* user's notify function */
@@ -439,7 +439,7 @@
 
 	/* XPC infrastructure referencing and teardown control */
 
-	u8 setup_state;			/* infrastructure setup state */
+	volatile u8 setup_state;			/* infrastructure setup state */
 	wait_queue_head_t teardown_wq;	/* kthread waiting to teardown infra */
 	atomic_t references;		/* #of references to infrastructure */
 
diff --git a/arch/ia64/sn/kernel/xpc_channel.c b/arch/ia64/sn/kernel/xpc_channel.c
index 0bf6fbc..6d02dac 100644
--- a/arch/ia64/sn/kernel/xpc_channel.c
+++ b/arch/ia64/sn/kernel/xpc_channel.c
@@ -209,7 +209,7 @@
 	 * With the setting of the partition setup_state to XPC_P_SETUP, we're
 	 * declaring that this partition is ready to go.
 	 */
-	(volatile u8) part->setup_state = XPC_P_SETUP;
+	part->setup_state = XPC_P_SETUP;
 
 
 	/*
@@ -227,7 +227,7 @@
 	xpc_vars_part[partid].IPI_phys_cpuid =
 					cpu_physical_id(smp_processor_id());
 	xpc_vars_part[partid].nchannels = part->nchannels;
-	(volatile u64) xpc_vars_part[partid].magic = XPC_VP_MAGIC1;
+	xpc_vars_part[partid].magic = XPC_VP_MAGIC1;
 
 	return xpcSuccess;
 }
@@ -355,7 +355,7 @@
 
 		/* let the other side know that we've pulled their variables */
 
-		(volatile u64) xpc_vars_part[partid].magic = XPC_VP_MAGIC2;
+		xpc_vars_part[partid].magic = XPC_VP_MAGIC2;
 	}
 
 	if (pulled_entry->magic == XPC_VP_MAGIC1) {
@@ -1183,7 +1183,7 @@
 		 */
 		xpc_clear_local_msgqueue_flags(ch);
 
-		(volatile s64) ch->w_remote_GP.get = ch->remote_GP.get;
+		ch->w_remote_GP.get = ch->remote_GP.get;
 
 		dev_dbg(xpc_chan, "w_remote_GP.get changed to %ld, partid=%d, "
 			"channel=%d\n", ch->w_remote_GP.get, ch->partid,
@@ -1211,7 +1211,7 @@
 		 */
 		xpc_clear_remote_msgqueue_flags(ch);
 
-		(volatile s64) ch->w_remote_GP.put = ch->remote_GP.put;
+		ch->w_remote_GP.put = ch->remote_GP.put;
 
 		dev_dbg(xpc_chan, "w_remote_GP.put changed to %ld, partid=%d, "
 			"channel=%d\n", ch->w_remote_GP.put, ch->partid,
@@ -1875,7 +1875,7 @@
 		notify = &ch->notify_queue[msg_number % ch->local_nentries];
 		notify->func = func;
 		notify->key = key;
-		(volatile u8) notify->type = notify_type;
+		notify->type = notify_type;
 
 		// >>> is a mb() needed here?
 
diff --git a/arch/ia64/sn/kernel/xpc_partition.c b/arch/ia64/sn/kernel/xpc_partition.c
index 2c3c4a8..578265e 100644
--- a/arch/ia64/sn/kernel/xpc_partition.c
+++ b/arch/ia64/sn/kernel/xpc_partition.c
@@ -22,6 +22,7 @@
 #include <linux/cache.h>
 #include <linux/mmzone.h>
 #include <linux/nodemask.h>
+#include <asm/uncached.h>
 #include <asm/sn/bte.h>
 #include <asm/sn/intr.h>
 #include <asm/sn/sn_sal.h>
@@ -183,7 +184,7 @@
 	 * memory protections are never restricted.
 	 */
 	if ((amos_page = xpc_vars->amos_page) == NULL) {
-		amos_page = (AMO_t *) mspec_kalloc_page(0);
+		amos_page = (AMO_t *) TO_AMO(uncached_alloc_page(0));
 		if (amos_page == NULL) {
 			dev_err(xpc_part, "can't allocate page of AMOs\n");
 			return NULL;
@@ -200,7 +201,8 @@
 			if (ret != 0) {
 				dev_err(xpc_part, "can't change memory "
 					"protections\n");
-				mspec_kfree_page((unsigned long) amos_page);
+				uncached_free_page(__IA64_UNCACHED_OFFSET |
+						   TO_PHYS((u64) amos_page));
 				return NULL;
 			}
 		}
@@ -251,7 +253,7 @@
 	 * This signifies to the remote partition that our reserved
 	 * page is initialized.
 	 */
-	(volatile u64) rp->vars_pa = __pa(xpc_vars);
+	rp->vars_pa = __pa(xpc_vars);
 
 	return rp;
 }
diff --git a/arch/m32r/Kconfig b/arch/m32r/Kconfig
index 0d90ea5..42ca8a3 100644
--- a/arch/m32r/Kconfig
+++ b/arch/m32r/Kconfig
@@ -78,6 +78,9 @@
 config PLAT_MAPPI2
        bool "Mappi-II(M3A-ZA36/M3A-ZA52)"
 
+config PLAT_MAPPI3
+       bool "Mappi-III(M3A-2170)"
+
 endchoice
 
 choice
@@ -134,6 +137,7 @@
 	int "Bus Clock [Hz] (integer)"
 	default "70000000" if PLAT_MAPPI
 	default "25000000" if PLAT_USRV
+	default "50000000" if PLAT_MAPPI3
 	default "50000000" if PLAT_M32700UT
 	default "50000000" if PLAT_OPSPUT
 	default "33333333" if PLAT_OAKS32R
@@ -149,7 +153,7 @@
 
 config MEMORY_START
 	hex "Physical memory start address (hex)"
-	default "08000000" if PLAT_MAPPI || PLAT_MAPPI2
+	default "08000000" if PLAT_MAPPI || PLAT_MAPPI2 || PLAT_MAPPI3
 	default "08000000" if PLAT_USRV
 	default "08000000" if PLAT_M32700UT
 	default "08000000" if PLAT_OPSPUT
@@ -157,6 +161,7 @@
 
 config MEMORY_SIZE
 	hex "Physical memory size (hex)"
+	default "08000000" if PLAT_MAPPI3
 	default "04000000" if PLAT_MAPPI || PLAT_MAPPI2
 	default "02000000" if PLAT_USRV
 	default "01000000" if PLAT_M32700UT
@@ -167,11 +172,13 @@
 	bool
 	default y
 
-config DISCONTIGMEM
+config ARCH_DISCONTIGMEM_ENABLE
 	bool "Internal RAM Support"
 	depends on CHIP_M32700 || CHIP_M32102 || CHIP_VDEC2 || CHIP_OPSP
 	default y
 
+source "mm/Kconfig"
+
 config IRAM_START
 	hex "Internal memory start address (hex)"
 	default "00f00000"
diff --git a/arch/m32r/boot/compressed/m32r_sio.c b/arch/m32r/boot/compressed/m32r_sio.c
index bad5475..8f9a572 100644
--- a/arch/m32r/boot/compressed/m32r_sio.c
+++ b/arch/m32r/boot/compressed/m32r_sio.c
@@ -6,6 +6,7 @@
  */
 
 #include <linux/config.h>
+#include <asm/processor.h>
 
 static void putc(char c);
 
@@ -38,16 +39,17 @@
 
 static void putc(char c)
 {
-
-	while ((*BOOT_SIO0STS & 0x3) != 0x3) ;
+	while ((*BOOT_SIO0STS & 0x3) != 0x3)
+		cpu_relax();
 	if (c == '\n') {
 		*BOOT_SIO0TXB = '\r';
-		while ((*BOOT_SIO0STS & 0x3) != 0x3) ;
+		while ((*BOOT_SIO0STS & 0x3) != 0x3)
+			cpu_relax();
 	}
 	*BOOT_SIO0TXB = c;
 }
-#else /* defined(CONFIG_PLAT_M32700UT_Alpha) || defined(CONFIG_PLAT_M32700UT) */
-#ifdef CONFIG_MMU
+#else /* !(CONFIG_PLAT_M32700UT_Alpha) && !(CONFIG_PLAT_M32700UT) */
+#if defined(CONFIG_PLAT_MAPPI2)
 #define SIO0STS	(volatile unsigned short *)(0xa0efd000 + 14)
 #define SIO0TXB	(volatile unsigned short *)(0xa0efd000 + 30)
 #else
@@ -57,11 +59,12 @@
 
 static void putc(char c)
 {
-
-	while ((*SIO0STS & 0x1) == 0) ;
+	while ((*SIO0STS & 0x1) == 0)
+		cpu_relax();
 	if (c == '\n') {
 		*SIO0TXB = '\r';
-		while ((*SIO0STS & 0x1) == 0) ;
+		while ((*SIO0STS & 0x1) == 0)
+			cpu_relax();
 	}
 	*SIO0TXB = c;
 }
diff --git a/arch/m32r/defconfig b/arch/m32r/defconfig
index 417c95b..8530930 100644
--- a/arch/m32r/defconfig
+++ b/arch/m32r/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:10:44 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun  3 16:20:11 2005
 #
 CONFIG_M32R=y
 # CONFIG_UID16 is not set
@@ -16,6 +16,7 @@
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -28,13 +29,15 @@
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 # CONFIG_IKCONFIG_PROC is not set
 CONFIG_EMBEDDED=y
 # CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -44,6 +47,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -65,6 +69,7 @@
 # CONFIG_PLAT_OPSPUT is not set
 # CONFIG_PLAT_OAKS32R is not set
 # CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
 CONFIG_CHIP_M32700=y
 # CONFIG_CHIP_M32102 is not set
 # CONFIG_CHIP_VDEC2 is not set
@@ -268,7 +273,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
@@ -393,18 +397,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -414,6 +406,17 @@
 # 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_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -465,6 +468,10 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -508,8 +515,14 @@
 # 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_SOFT_CURSOR is not set
+# CONFIG_FB_MACMODES is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -543,10 +556,6 @@
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
@@ -719,8 +728,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_FRAME_POINTER is not set
 
diff --git a/arch/m32r/kernel/Makefile b/arch/m32r/kernel/Makefile
index cfd690b..6c6b6c3 100644
--- a/arch/m32r/kernel/Makefile
+++ b/arch/m32r/kernel/Makefile
@@ -10,6 +10,7 @@
 obj-$(CONFIG_SMP)		+= smp.o smpboot.o
 obj-$(CONFIG_PLAT_MAPPI)	+= setup_mappi.o io_mappi.o
 obj-$(CONFIG_PLAT_MAPPI2)	+= setup_mappi2.o io_mappi2.o
+obj-$(CONFIG_PLAT_MAPPI3)	+= setup_mappi3.o io_mappi3.o
 obj-$(CONFIG_PLAT_USRV)		+= setup_usrv.o io_usrv.o
 obj-$(CONFIG_PLAT_M32700UT)	+= setup_m32700ut.o io_m32700ut.o
 obj-$(CONFIG_PLAT_OPSPUT)	+= setup_opsput.o io_opsput.o
@@ -17,4 +18,3 @@
 obj-$(CONFIG_PLAT_OAKS32R)	+= setup_oaks32r.o io_oaks32r.o
 
 EXTRA_AFLAGS	:= -traditional
-
diff --git a/arch/m32r/kernel/io_m32700ut.c b/arch/m32r/kernel/io_m32700ut.c
index 371ba904..e545b06 100644
--- a/arch/m32r/kernel/io_m32700ut.c
+++ b/arch/m32r/kernel/io_m32700ut.c
@@ -3,8 +3,8 @@
  *
  *  Typical I/O routines for M32700UT board.
  *
- *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
- *                            Hitoshi Yamamoto, Takeo Takahashi
+ *  Copyright (c) 2001-2005  Hiroyuki Kondo, Hirokazu Takata,
+ *                           Hitoshi Yamamoto, Takeo Takahashi
  *
  *  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
@@ -172,64 +172,21 @@
 
 unsigned char _inb_p(unsigned long port)
 {
-	unsigned char  v;
-
-	if (port >= LAN_IOSTART && port < LAN_IOEND)
-		v = _ne_inb(PORT2ADDR_NE(port));
-	else
-#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
-	if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
-		return *(volatile unsigned char *)__port2addr_ata(port);
-	} else
-#endif
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
-	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
-		unsigned char b;
-		pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
-		return b;
-	} else
-#endif
-		v = *(volatile unsigned char *)PORT2ADDR(port);
-
+	unsigned char v = _inb(port);
 	delay();
 	return (v);
 }
 
 unsigned short _inw_p(unsigned long port)
 {
-	unsigned short  v;
-
-	if (port >= LAN_IOSTART && port < LAN_IOEND)
-		v = _ne_inw(PORT2ADDR_NE(port));
-	else
-#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
-	if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
-		return *(volatile unsigned short *)__port2addr_ata(port);
-	} else
-#endif
-#if defined(CONFIG_USB)
-	if(port >= 0x340 && port < 0x3a0)
-		return *(volatile unsigned short *)PORT2ADDR_USB(port);
-	else
-#endif
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
-	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
-		unsigned short w;
-		pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
-		return w;
-	} else
-#endif
-		v = *(volatile unsigned short *)PORT2ADDR(port);
-
+	unsigned short v = _inw(port);
 	delay();
 	return (v);
 }
 
 unsigned long _inl_p(unsigned long port)
 {
-	unsigned long  v;
-
-	v = *(volatile unsigned long *)PORT2ADDR(port);
+	unsigned long v = _inl(port);
 	delay();
 	return (v);
 }
@@ -287,52 +244,19 @@
 
 void _outb_p(unsigned char b, unsigned long port)
 {
-	if (port >= LAN_IOSTART && port < LAN_IOEND)
-		_ne_outb(b, PORT2ADDR_NE(port));
-	else
-#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
-	if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
-		*(volatile unsigned char *)__port2addr_ata(port) = b;
-	} else
-#endif
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
-	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
-		pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
-	} else
-#endif
-		*(volatile unsigned char *)PORT2ADDR(port) = b;
-
+	_outb(b, port);
 	delay();
 }
 
 void _outw_p(unsigned short w, unsigned long port)
 {
-	if (port >= LAN_IOSTART && port < LAN_IOEND)
-		_ne_outw(w, PORT2ADDR_NE(port));
-	else
-#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
-	if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
-		*(volatile unsigned short *)__port2addr_ata(port) = w;
-	} else
-#endif
-#if defined(CONFIG_USB)
-	if(port >= 0x340 && port < 0x3a0)
-		*(volatile unsigned short *)PORT2ADDR_USB(port) = w;
-	else
-#endif
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
-	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
-		pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
-	} else
-#endif
-		*(volatile unsigned short *)PORT2ADDR(port) = w;
-
+	_outw(w, port);
 	delay();
 }
 
 void _outl_p(unsigned long l, unsigned long port)
 {
-	*(volatile unsigned long *)PORT2ADDR(port) = l;
+	_outl(l, port);
 	delay();
 }
 
diff --git a/arch/m32r/kernel/io_mappi.c b/arch/m32r/kernel/io_mappi.c
index 85688ff..7803316 100644
--- a/arch/m32r/kernel/io_mappi.c
+++ b/arch/m32r/kernel/io_mappi.c
@@ -3,8 +3,8 @@
  *
  *  Typical I/O routines for Mappi board.
  *
- *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
- *                            Hitoshi Yamamoto
+ *  Copyright (c) 2001-2005  Hiroyuki Kondo, Hirokazu Takata,
+ *                           Hitoshi Yamamoto
  */
 
 #include <linux/config.h>
@@ -130,57 +130,21 @@
 
 unsigned char _inb_p(unsigned long port)
 {
-	unsigned char  v;
-
-	if (port >= 0x300 && port < 0x320)
-		v = _ne_inb(PORT2ADDR_NE(port));
-	else
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
-	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
-		unsigned char b;
-		pcc_ioread(0, port, &b, sizeof(b), 1, 0);
-		return b;
-	} else 	if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
-		unsigned char b;
-		pcc_ioread(1, port, &b, sizeof(b), 1, 0);
-		return b;
-	} else
-#endif
-		v = *(volatile unsigned char *)PORT2ADDR(port);
-
+	unsigned char v = _inb(port);
 	delay();
 	return (v);
 }
 
 unsigned short _inw_p(unsigned long port)
 {
-	unsigned short  v;
-
-	if (port >= 0x300 && port < 0x320)
-		v = _ne_inw(PORT2ADDR_NE(port));
-	else
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
-	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
-		unsigned short w;
-		pcc_ioread(0, port, &w, sizeof(w), 1, 0);
-		return w;
-	} else 	if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
-		unsigned short w;
-		pcc_ioread(1, port, &w, sizeof(w), 1, 0);
-		return w;
-	} else
-#endif
-		v = *(volatile unsigned short *)PORT2ADDR(port);
-
+	unsigned short v = _inw(port);
 	delay();
 	return (v);
 }
 
 unsigned long _inl_p(unsigned long port)
 {
-	unsigned long  v;
-
-	v = *(volatile unsigned long *)PORT2ADDR(port);
+	unsigned long v = _inl(port);
 	delay();
 	return (v);
 }
@@ -229,41 +193,19 @@
 
 void _outb_p(unsigned char b, unsigned long port)
 {
-	if (port >= 0x300 && port < 0x320)
-		_ne_outb(b, PORT2ADDR_NE(port));
-	else
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
-	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
-		pcc_iowrite(0, port, &b, sizeof(b), 1, 0);
-	} else 	if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
-		pcc_iowrite(1, port, &b, sizeof(b), 1, 0);
-	} else
-#endif
-		*(volatile unsigned char *)PORT2ADDR(port) = b;
-
+	_outb(b, port);
 	delay();
 }
 
 void _outw_p(unsigned short w, unsigned long port)
 {
-	if (port >= 0x300 && port < 0x320)
-		_ne_outw(w, PORT2ADDR_NE(port));
-	else
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_PCC)
-	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
-		pcc_iowrite(0, port, &w, sizeof(w), 1, 0);
-	} else 	if (port >= M32R_PCC_IOSTART1 && port <= M32R_PCC_IOEND1) {
-		pcc_iowrite(1, port, &w, sizeof(w), 1, 0);
-	} else
-#endif
-		*(volatile unsigned short *)PORT2ADDR(port) = w;
-
+	_outw(w, port);
 	delay();
 }
 
 void _outl_p(unsigned long l, unsigned long port)
 {
-	*(volatile unsigned long *)PORT2ADDR(port) = l;
+	_outl(l, port);
 	delay();
 }
 
diff --git a/arch/m32r/kernel/io_mappi2.c b/arch/m32r/kernel/io_mappi2.c
index 4182cd4..5c03504 100644
--- a/arch/m32r/kernel/io_mappi2.c
+++ b/arch/m32r/kernel/io_mappi2.c
@@ -3,7 +3,7 @@
  *
  *  Typical I/O routines for Mappi2 board.
  *
- *  Copyright (c) 2001-2003  Hiroyuki Kondo, Hirokazu Takata,
+ *  Copyright (c) 2001-2005  Hiroyuki Kondo, Hirokazu Takata,
  *                           Hitoshi Yamamoto, Mamoru Sakugawa
  */
 
@@ -25,7 +25,7 @@
 extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);
 extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);
 extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
-#endif /* CONFIG_PCMCIA && CONFIG_MAPPI2_CFC */
+#endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */
 
 #define PORT2ADDR(port)      _port2addr(port)
 #define PORT2ADDR_NE(port)   _port2addr_ne(port)
@@ -169,64 +169,21 @@
 
 unsigned char _inb_p(unsigned long port)
 {
-	unsigned char  v;
-
-	if (port >= LAN_IOSTART && port < LAN_IOEND)
-		v = _ne_inb(PORT2ADDR_NE(port));
-	else
-#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
-	if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
-		return *(volatile unsigned char *)__port2addr_ata(port);
-	} else
-#endif
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
-	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
-		unsigned char b;
-		pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
-		return b;
-	} else
-#endif
-		v = *(volatile unsigned char *)PORT2ADDR(port);
-
+	unsigned char v = _inb(port);
 	delay();
 	return (v);
 }
 
 unsigned short _inw_p(unsigned long port)
 {
-	unsigned short  v;
-
-	if (port >= LAN_IOSTART && port < LAN_IOEND)
-		v = _ne_inw(PORT2ADDR_NE(port));
-	else
-#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
-	if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
-		return *(volatile unsigned short *)__port2addr_ata(port);
-	} else
-#endif
-#if defined(CONFIG_USB)
-	if (port >= 0x340 && port < 0x3a0)
-		v = *(volatile unsigned short *)PORT2ADDR_USB(port);
-	else
-#endif
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
-	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
-		unsigned short w;
-		pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
-		return w;
-	} else
-#endif
-		v = *(volatile unsigned short *)PORT2ADDR(port);
-
+	unsigned short v = _inw(port);
 	delay();
 	return (v);
 }
 
 unsigned long _inl_p(unsigned long port)
 {
-	unsigned long  v;
-
-	v = *(volatile unsigned long *)PORT2ADDR(port);
+	unsigned long v = _inl(port);
 	delay();
 	return (v);
 }
@@ -284,52 +241,19 @@
 
 void _outb_p(unsigned char b, unsigned long port)
 {
-	if (port >= LAN_IOSTART && port < LAN_IOEND)
-		_ne_outb(b, PORT2ADDR_NE(port));
-	else
-#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
-	if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
-		*(volatile unsigned char *)__port2addr_ata(port) = b;
-	} else
-#endif
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
-	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
-		pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
-	} else
-#endif
-		*(volatile unsigned char *)PORT2ADDR(port) = b;
-
+	_outb(b, port);
 	delay();
 }
 
 void _outw_p(unsigned short w, unsigned long port)
 {
-	if (port >= LAN_IOSTART && port < LAN_IOEND)
-		_ne_outw(w, PORT2ADDR_NE(port));
-	else
-#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
-	if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
-		*(volatile unsigned short *)__port2addr_ata(port) = w;
-	} else
-#endif
-#if defined(CONFIG_USB)
-	  if (port >= 0x340 && port < 0x3a0)
-		*(volatile unsigned short *)PORT2ADDR_USB(port) = w;
-	else
-#endif
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
-	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
-		pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
-	} else
-#endif
-		*(volatile unsigned short *)PORT2ADDR(port) = w;
-
+	_outw(w, port);
 	delay();
 }
 
 void _outl_p(unsigned long l, unsigned long port)
 {
-	*(volatile unsigned long *)PORT2ADDR(port) = l;
+	_outl(l, port);
 	delay();
 }
 
diff --git a/arch/m32r/kernel/io_mappi3.c b/arch/m32r/kernel/io_mappi3.c
new file mode 100644
index 0000000..c80bde6
--- /dev/null
+++ b/arch/m32r/kernel/io_mappi3.c
@@ -0,0 +1,378 @@
+/*
+ *  linux/arch/m32r/kernel/io_mappi3.c
+ *
+ *  Typical I/O routines for Mappi3 board.
+ *
+ *  Copyright (c) 2001-2005  Hiroyuki Kondo, Hirokazu Takata,
+ *                           Hitoshi Yamamoto, Mamoru Sakugawa
+ */
+
+#include <linux/config.h>
+#include <asm/m32r.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+#include <linux/types.h>
+
+#define M32R_PCC_IOMAP_SIZE 0x1000
+
+#define M32R_PCC_IOSTART0 0x1000
+#define M32R_PCC_IOEND0   (M32R_PCC_IOSTART0 + M32R_PCC_IOMAP_SIZE - 1)
+
+extern void pcc_ioread_byte(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_ioread_word(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite_byte(int, unsigned long, void *, size_t, size_t, int);
+extern void pcc_iowrite_word(int, unsigned long, void *, size_t, size_t, int);
+#endif /* CONFIG_PCMCIA && CONFIG_M32R_CFC */
+
+#define PORT2ADDR(port)      _port2addr(port)
+#define PORT2ADDR_NE(port)   _port2addr_ne(port)
+#define PORT2ADDR_USB(port)  _port2addr_usb(port)
+
+static inline void *_port2addr(unsigned long port)
+{
+	return (void *)(port + NONCACHE_OFFSET);
+}
+
+#define LAN_IOSTART	0x300
+#define LAN_IOEND	0x320
+
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+static inline void *__port2addr_ata(unsigned long port)
+{
+	static int	dummy_reg;
+
+	switch (port) {
+	case 0x1f0:	return (void *)0xb4002000;
+	case 0x1f1:	return (void *)0xb4012800;
+	case 0x1f2:	return (void *)0xb4012002;
+	case 0x1f3:	return (void *)0xb4012802;
+	case 0x1f4:	return (void *)0xb4012004;
+	case 0x1f5:	return (void *)0xb4012804;
+	case 0x1f6:	return (void *)0xb4012006;
+	case 0x1f7:	return (void *)0xb4012806;
+	case 0x3f6:	return (void *)0xb401200e;
+	default: 	return (void *)&dummy_reg;
+	}
+}
+#endif
+
+static inline void *_port2addr_ne(unsigned long port)
+{
+	return (void *)(port + NONCACHE_OFFSET + 0x10000000);
+}
+
+static inline void *_port2addr_usb(unsigned long port)
+{
+	return (void *)(port + NONCACHE_OFFSET + 0x12000000);
+}
+static inline void delay(void)
+{
+	__asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
+}
+
+/*
+ * NIC I/O function
+ */
+
+static inline unsigned char _ne_inb(void *portp)
+{
+	return (unsigned char) *(volatile unsigned char *)portp;
+}
+
+static inline unsigned short _ne_inw(void *portp)
+{
+	return (unsigned short)le16_to_cpu(*(volatile unsigned short *)portp);
+}
+
+static inline void _ne_insb(void *portp, void * addr, unsigned long count)
+{
+	unsigned char *buf = addr;
+
+	while (count--)
+		*buf++ = *(volatile unsigned char *)portp;
+}
+
+static inline void _ne_outb(unsigned char b, void *portp)
+{
+	*(volatile unsigned char *)portp = (unsigned char)b;
+}
+
+static inline void _ne_outw(unsigned short w, void *portp)
+{
+	*(volatile unsigned short *)portp = cpu_to_le16(w);
+}
+
+unsigned char _inb(unsigned long port)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		return _ne_inb(PORT2ADDR_NE(port));
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+	else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+		return *(volatile unsigned char *)__port2addr_ata(port);
+	}
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+		unsigned char b;
+		pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
+		return b;
+	} else
+#endif
+	return *(volatile unsigned char *)PORT2ADDR(port);
+}
+
+unsigned short _inw(unsigned long port)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		return _ne_inw(PORT2ADDR_NE(port));
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+	else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+		return *(volatile unsigned short *)__port2addr_ata(port);
+	}
+#endif
+#if defined(CONFIG_USB)
+	else if (port >= 0x340 && port < 0x3a0)
+		return *(volatile unsigned short *)PORT2ADDR_USB(port);
+#endif
+
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+		unsigned short w;
+		pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
+		return w;
+	} else
+#endif
+	return *(volatile unsigned short *)PORT2ADDR(port);
+}
+
+unsigned long _inl(unsigned long port)
+{
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+		unsigned long l;
+		pcc_ioread_word(0, port, &l, sizeof(l), 1, 0);
+		return l;
+	} else
+#endif
+	return *(volatile unsigned long *)PORT2ADDR(port);
+}
+
+unsigned char _inb_p(unsigned long port)
+{
+	unsigned char v = _inb(port);
+	delay();
+	return (v);
+}
+
+unsigned short _inw_p(unsigned long port)
+{
+	unsigned short v = _inw(port);
+	delay();
+	return (v);
+}
+
+unsigned long _inl_p(unsigned long port)
+{
+	unsigned long v = _inl(port);
+	delay();
+	return (v);
+}
+
+void _outb(unsigned char b, unsigned long port)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		_ne_outb(b, PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+	if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+		*(volatile unsigned char *)__port2addr_ata(port) = b;
+	} else
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+		pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
+	} else
+#endif
+		*(volatile unsigned char *)PORT2ADDR(port) = b;
+}
+
+void _outw(unsigned short w, unsigned long port)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		_ne_outw(w, PORT2ADDR_NE(port));
+	else
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+	if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+		*(volatile unsigned short *)__port2addr_ata(port) = w;
+	} else
+#endif
+#if defined(CONFIG_USB)
+	if (port >= 0x340 && port < 0x3a0)
+		*(volatile unsigned short *)PORT2ADDR_USB(port) = w;
+	else
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+		pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
+	} else
+#endif
+		*(volatile unsigned short *)PORT2ADDR(port) = w;
+}
+
+void _outl(unsigned long l, unsigned long port)
+{
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+		pcc_iowrite_word(0, port, &l, sizeof(l), 1, 0);
+	} else
+#endif
+	*(volatile unsigned long *)PORT2ADDR(port) = l;
+}
+
+void _outb_p(unsigned char b, unsigned long port)
+{
+	_outb(b, port);
+	delay();
+}
+
+void _outw_p(unsigned short w, unsigned long port)
+{
+	_outw(w, port);
+	delay();
+}
+
+void _outl_p(unsigned long l, unsigned long port)
+{
+	_outl(l, port);
+	delay();
+}
+
+void _insb(unsigned int port, void * addr, unsigned long count)
+{
+	if (port >= LAN_IOSTART && port < LAN_IOEND)
+		_ne_insb(PORT2ADDR_NE(port), addr, count);
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+	else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+		unsigned char *buf = addr;
+		unsigned char *portp = __port2addr_ata(port);
+		while (count--)
+			*buf++ = *(volatile unsigned char *)portp;
+	}
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+		pcc_ioread_byte(0, port, (void *)addr, sizeof(unsigned char),
+				count, 1);
+	}
+#endif
+	else {
+		unsigned char *buf = addr;
+		unsigned char *portp = PORT2ADDR(port);
+		while (count--)
+			*buf++ = *(volatile unsigned char *)portp;
+	}
+}
+
+void _insw(unsigned int port, void * addr, unsigned long count)
+{
+	unsigned short *buf = addr;
+	unsigned short *portp;
+
+	if (port >= LAN_IOSTART && port < LAN_IOEND) {
+		portp = PORT2ADDR_NE(port);
+		while (count--)
+			*buf++ = *(volatile unsigned short *)portp;
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+		pcc_ioread_word(9, port, (void *)addr, sizeof(unsigned short),
+				count, 1);
+#endif
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+	} else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+		portp = __port2addr_ata(port);
+		while (count--)
+			*buf++ = *(volatile unsigned short *)portp;
+#endif
+	} else {
+		portp = PORT2ADDR(port);
+		while (count--)
+			*buf++ = *(volatile unsigned short *)portp;
+	}
+}
+
+void _insl(unsigned int port, void * addr, unsigned long count)
+{
+	unsigned long *buf = addr;
+	unsigned long *portp;
+
+	portp = PORT2ADDR(port);
+	while (count--)
+		*buf++ = *(volatile unsigned long *)portp;
+}
+
+void _outsb(unsigned int port, const void * addr, unsigned long count)
+{
+	const unsigned char *buf = addr;
+	unsigned char *portp;
+
+	if (port >= LAN_IOSTART && port < LAN_IOEND) {
+		portp = PORT2ADDR_NE(port);
+		while (count--)
+			_ne_outb(*buf++, portp);
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+	} else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+		portp = __port2addr_ata(port);
+		while (count--)
+			*(volatile unsigned char *)portp = *buf++;
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+		pcc_iowrite_byte(0, port, (void *)addr, sizeof(unsigned char),
+				 count, 1);
+#endif
+	} else {
+		portp = PORT2ADDR(port);
+		while (count--)
+			*(volatile unsigned char *)portp = *buf++;
+	}
+}
+
+void _outsw(unsigned int port, const void * addr, unsigned long count)
+{
+	const unsigned short *buf = addr;
+	unsigned short *portp;
+
+	if (port >= LAN_IOSTART && port < LAN_IOEND) {
+		portp = PORT2ADDR_NE(port);
+		while (count--)
+			*(volatile unsigned short *)portp = *buf++;
+#if defined(CONFIG_IDE) && !defined(CONFIG_M32R_CFC)
+	} else if ((port >= 0x1f0 && port <=0x1f7) || port == 0x3f6) {
+		portp = __port2addr_ata(port);
+		while (count--)
+			*(volatile unsigned short *)portp = *buf++;
+#endif
+#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
+	} else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
+		pcc_iowrite_word(9, port, (void *)addr, sizeof(unsigned short),
+				 count, 1);
+#endif
+	} else {
+		portp = PORT2ADDR(port);
+		while (count--)
+			*(volatile unsigned short *)portp = *buf++;
+	}
+}
+
+void _outsl(unsigned int port, const void * addr, unsigned long count)
+{
+	const unsigned long *buf = addr;
+	unsigned char *portp;
+
+	portp = PORT2ADDR(port);
+	while (count--)
+		*(volatile unsigned long *)portp = *buf++;
+}
diff --git a/arch/m32r/kernel/io_oaks32r.c b/arch/m32r/kernel/io_oaks32r.c
index 2869647..9997ddd 100644
--- a/arch/m32r/kernel/io_oaks32r.c
+++ b/arch/m32r/kernel/io_oaks32r.c
@@ -3,7 +3,7 @@
  *
  *  Typical I/O routines for OAKS32R board.
  *
- *  Copyright (c) 2001-2004  Hiroyuki Kondo, Hirokazu Takata,
+ *  Copyright (c) 2001-2005  Hiroyuki Kondo, Hirokazu Takata,
  *                           Hitoshi Yamamoto, Mamoru Sakugawa
  */
 
@@ -90,35 +90,21 @@
 
 unsigned char _inb_p(unsigned long port)
 {
-	unsigned char  v;
-
-	if (port >= 0x300 && port < 0x320)
-		v = _ne_inb(PORT2ADDR_NE(port));
-	else
-		v = *(volatile unsigned char *)PORT2ADDR(port);
-
+	unsigned char v = _inb(port);
 	delay();
 	return (v);
 }
 
 unsigned short _inw_p(unsigned long port)
 {
-	unsigned short  v;
-
-	if (port >= 0x300 && port < 0x320)
-		v = _ne_inw(PORT2ADDR_NE(port));
-	else
-		v = *(volatile unsigned short *)PORT2ADDR(port);
-
+	unsigned short v = _inw(port);
 	delay();
 	return (v);
 }
 
 unsigned long _inl_p(unsigned long port)
 {
-	unsigned long  v;
-
-	v = *(volatile unsigned long *)PORT2ADDR(port);
+	unsigned long v = _inl(port);
 	delay();
 	return (v);
 }
@@ -146,27 +132,19 @@
 
 void _outb_p(unsigned char b, unsigned long port)
 {
-	if (port >= 0x300 && port < 0x320)
-		_ne_outb(b, PORT2ADDR_NE(port));
-	else
-		*(volatile unsigned char *)PORT2ADDR(port) = b;
-
+	_outb(b, port);
 	delay();
 }
 
 void _outw_p(unsigned short w, unsigned long port)
 {
-	if (port >= 0x300 && port < 0x320)
-		_ne_outw(w, PORT2ADDR_NE(port));
-	else
-		*(volatile unsigned short *)PORT2ADDR(port) = w;
-
+	_outw(w, port);
 	delay();
 }
 
 void _outl_p(unsigned long l, unsigned long port)
 {
-	*(volatile unsigned long *)PORT2ADDR(port) = l;
+	_outl(l, port);
 	delay();
 }
 
diff --git a/arch/m32r/kernel/io_opsput.c b/arch/m32r/kernel/io_opsput.c
index aaf42f9..e34951e 100644
--- a/arch/m32r/kernel/io_opsput.c
+++ b/arch/m32r/kernel/io_opsput.c
@@ -1,10 +1,10 @@
 /*
- *  linux/arch/m32r/kernel/io_mappi.c
+ *  linux/arch/m32r/kernel/io_opsput.c
  *
  *  Typical I/O routines for OPSPUT board.
  *
- *  Copyright (c) 2001, 2002  Hiroyuki Kondo, Hirokazu Takata,
- *                            Hitoshi Yamamoto, Takeo Takahashi
+ *  Copyright (c) 2001-2005  Hiroyuki Kondo, Hirokazu Takata,
+ *                           Hitoshi Yamamoto, Takeo Takahashi
  *
  *  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
@@ -98,7 +98,6 @@
 {
 	if (port >= LAN_IOSTART && port < LAN_IOEND)
 		return _ne_inb(PORT2ADDR_NE(port));
-
 #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
 	else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
 		unsigned char b;
@@ -118,7 +117,6 @@
 	else if(port >= 0x340 && port < 0x3a0)
 		return *(volatile unsigned short *)PORT2ADDR_USB(port);
 #endif
-
 #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
 	else if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
 		unsigned short w;
@@ -143,55 +141,21 @@
 
 unsigned char _inb_p(unsigned long port)
 {
-	unsigned char  v;
-
-	if (port >= LAN_IOSTART && port < LAN_IOEND)
-		v = _ne_inb(PORT2ADDR_NE(port));
-	else
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
-	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
-		unsigned char b;
-		pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
-		return b;
-	} else
-#endif
-		v = *(volatile unsigned char *)PORT2ADDR(port);
-
+	unsigned char v = _inb(port);
 	delay();
 	return (v);
 }
 
 unsigned short _inw_p(unsigned long port)
 {
-	unsigned short  v;
-
-	if (port >= LAN_IOSTART && port < LAN_IOEND)
-		v = _ne_inw(PORT2ADDR_NE(port));
-	else
-#if defined(CONFIG_USB)
-	if(port >= 0x340 && port < 0x3a0)
-		return *(volatile unsigned short *)PORT2ADDR_USB(port);
-	else
-#endif
-
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
-	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
-		unsigned short w;
-		pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
-		return w;
-	} else
-#endif
-		v = *(volatile unsigned short *)PORT2ADDR(port);
-
+	unsigned short v = _inw(port);
 	delay();
 	return (v);
 }
 
 unsigned long _inl_p(unsigned long port)
 {
-	unsigned long  v;
-
-	v = *(volatile unsigned long *)PORT2ADDR(port);
+	unsigned long v = _inl(port);
 	delay();
 	return (v);
 }
@@ -219,7 +183,6 @@
 		*(volatile unsigned short *)PORT2ADDR_USB(port) = w;
 	else
 #endif
-
 #if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
 	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
 		pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
@@ -240,43 +203,19 @@
 
 void _outb_p(unsigned char b, unsigned long port)
 {
-	if (port >= LAN_IOSTART && port < LAN_IOEND)
-		_ne_outb(b, PORT2ADDR_NE(port));
-	else
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
-	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
-		pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
-	} else
-#endif
-		*(volatile unsigned char *)PORT2ADDR(port) = b;
-
+	_outb(b, port);
 	delay();
 }
 
 void _outw_p(unsigned short w, unsigned long port)
 {
-	if (port >= LAN_IOSTART && port < LAN_IOEND)
-		_ne_outw(w, PORT2ADDR_NE(port));
-	else
-#if defined(CONFIG_USB)
-	if(port >= 0x340 && port < 0x3a0)
-		*(volatile unsigned short *)PORT2ADDR_USB(port) = w;
-	else
-#endif
-
-#if defined(CONFIG_PCMCIA) && defined(CONFIG_M32R_CFC)
-	if (port >= M32R_PCC_IOSTART0 && port <= M32R_PCC_IOEND0) {
-		pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
-	} else
-#endif
-		*(volatile unsigned short *)PORT2ADDR(port) = w;
-
+	_outw(w, port);
 	delay();
 }
 
 void _outl_p(unsigned long l, unsigned long port)
 {
-	*(volatile unsigned long *)PORT2ADDR(port) = l;
+	_outl(l, port);
 	delay();
 }
 
diff --git a/arch/m32r/kernel/io_usrv.c b/arch/m32r/kernel/io_usrv.c
index 27928a0..9eb161d 100644
--- a/arch/m32r/kernel/io_usrv.c
+++ b/arch/m32r/kernel/io_usrv.c
@@ -3,8 +3,8 @@
  *
  *  Typical I/O routines for uServer board.
  *
- *  Copyright (c) 2001 - 2003  Hiroyuki Kondo, Hirokazu Takata,
- *                             Hitoshi Yamamoto, Takeo Takahashi
+ *  Copyright (c) 2001-2005  Hiroyuki Kondo, Hirokazu Takata,
+ *                           Hitoshi Yamamoto, Takeo Takahashi
  *
  *  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
@@ -39,7 +39,7 @@
 
 #define PORT2ADDR(port)	_port2addr(port)
 
-static __inline__ void *_port2addr(unsigned long port)
+static inline void *_port2addr(unsigned long port)
 {
 #if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
 	if (port >= UART0_IOSTART && port <= UART0_IOEND)
@@ -50,7 +50,7 @@
 	return (void *)(port + NONCACHE_OFFSET);
 }
 
-static __inline__ void delay(void)
+static inline void delay(void)
 {
 	__asm__ __volatile__ ("push r0; \n\t pop r0;" : : :"memory");
 }
@@ -87,39 +87,22 @@
 
 unsigned char _inb_p(unsigned long port)
 {
-	unsigned char b;
-
-	if (port >= CFC_IOSTART && port <= CFC_IOEND) {
-		pcc_ioread_byte(0, port, &b, sizeof(b), 1, 0);
-		return b;
-	} else {
-		b = *(volatile unsigned char *)PORT2ADDR(port);
-		delay();
-		return b;
-	}
+	unsigned char v = _inb(port);
+	delay();
+	return v;
 }
 
 unsigned short _inw_p(unsigned long port)
 {
-	unsigned short w;
-
-	if (port >= CFC_IOSTART && port <= CFC_IOEND) {
-		pcc_ioread_word(0, port, &w, sizeof(w), 1, 0);
-		return w;
-	} else {
-		w = *(volatile unsigned short *)PORT2ADDR(port);
-		delay();
-		return w;
-	}
+	unsigned short v = _inw(port);
+	delay();
+	return v;
 }
 
 unsigned long _inl_p(unsigned long port)
 {
-	unsigned long v;
-
-	v = *(volatile unsigned long *)PORT2ADDR(port);
+	unsigned long v = _inl(port);
 	delay();
-
 	return v;
 }
 
@@ -149,25 +132,19 @@
 
 void _outb_p(unsigned char b, unsigned long port)
 {
-	if (port >= CFC_IOSTART && port <= CFC_IOEND)
-		pcc_iowrite_byte(0, port, &b, sizeof(b), 1, 0);
-	else
-		*(volatile unsigned char *)PORT2ADDR(port) = b;
+	_outb(b, port);
 	delay();
 }
 
 void _outw_p(unsigned short w, unsigned long port)
 {
-	if (port >= CFC_IOSTART && port <= CFC_IOEND)
-		pcc_iowrite_word(0, port, &w, sizeof(w), 1, 0);
-	else
-		*(volatile unsigned short *)PORT2ADDR(port) = w;
+	_outw(w, port);
 	delay();
 }
 
 void _outl_p(unsigned long l, unsigned long port)
 {
-	*(volatile unsigned long *)PORT2ADDR(port) = l;
+	_outl(l, port);
 	delay();
 }
 
diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c
index 4826cd6..ec56747 100644
--- a/arch/m32r/kernel/setup.c
+++ b/arch/m32r/kernel/setup.c
@@ -330,6 +330,8 @@
 	seq_printf(m, "Machine\t\t: Mappi Evaluation board\n");
 #elif CONFIG_PLAT_MAPPI2
 	seq_printf(m, "Machine\t\t: Mappi-II Evaluation board\n");
+#elif CONFIG_PLAT_MAPPI3
+	seq_printf(m, "Machine\t\t: Mappi-III Evaluation board\n");
 #elif  CONFIG_PLAT_M32700UT
 	seq_printf(m, "Machine\t\t: M32700UT Evaluation board\n");
 #elif  CONFIG_PLAT_OPSPUT
diff --git a/arch/m32r/kernel/setup_m32700ut.c b/arch/m32r/kernel/setup_m32700ut.c
index 488aa87..b014e2c 100644
--- a/arch/m32r/kernel/setup_m32700ut.c
+++ b/arch/m32r/kernel/setup_m32700ut.c
@@ -78,13 +78,13 @@
 
 static struct hw_interrupt_type m32700ut_irq_type =
 {
-	"M32700UT-IRQ",
-	startup_m32700ut_irq,
-	shutdown_m32700ut_irq,
-	enable_m32700ut_irq,
-	disable_m32700ut_irq,
-	mask_and_ack_m32700ut,
-	end_m32700ut_irq
+	.typename = "M32700UT-IRQ",
+	.startup = startup_m32700ut_irq,
+	.shutdown = shutdown_m32700ut_irq,
+	.enable = enable_m32700ut_irq,
+	.disable = disable_m32700ut_irq,
+	.ack = mask_and_ack_m32700ut,
+	.end = end_m32700ut_irq
 };
 
 /*
@@ -155,13 +155,13 @@
 
 static struct hw_interrupt_type m32700ut_pld_irq_type =
 {
-	"M32700UT-PLD-IRQ",
-	startup_m32700ut_pld_irq,
-	shutdown_m32700ut_pld_irq,
-	enable_m32700ut_pld_irq,
-	disable_m32700ut_pld_irq,
-	mask_and_ack_m32700ut_pld,
-	end_m32700ut_pld_irq
+	.typename = "M32700UT-PLD-IRQ",
+	.startup = startup_m32700ut_pld_irq,
+	.shutdown = shutdown_m32700ut_pld_irq,
+	.enable = enable_m32700ut_pld_irq,
+	.disable = disable_m32700ut_pld_irq,
+	.ack = mask_and_ack_m32700ut_pld,
+	.end = end_m32700ut_pld_irq
 };
 
 /*
@@ -224,13 +224,13 @@
 
 static struct hw_interrupt_type m32700ut_lanpld_irq_type =
 {
-	"M32700UT-PLD-LAN-IRQ",
-	startup_m32700ut_lanpld_irq,
-	shutdown_m32700ut_lanpld_irq,
-	enable_m32700ut_lanpld_irq,
-	disable_m32700ut_lanpld_irq,
-	mask_and_ack_m32700ut_lanpld,
-	end_m32700ut_lanpld_irq
+	.typename = "M32700UT-PLD-LAN-IRQ",
+	.startup = startup_m32700ut_lanpld_irq,
+	.shutdown = shutdown_m32700ut_lanpld_irq,
+	.enable = enable_m32700ut_lanpld_irq,
+	.disable = disable_m32700ut_lanpld_irq,
+	.ack = mask_and_ack_m32700ut_lanpld,
+	.end = end_m32700ut_lanpld_irq
 };
 
 /*
@@ -293,13 +293,13 @@
 
 static struct hw_interrupt_type m32700ut_lcdpld_irq_type =
 {
-	"M32700UT-PLD-LCD-IRQ",
-	startup_m32700ut_lcdpld_irq,
-	shutdown_m32700ut_lcdpld_irq,
-	enable_m32700ut_lcdpld_irq,
-	disable_m32700ut_lcdpld_irq,
-	mask_and_ack_m32700ut_lcdpld,
-	end_m32700ut_lcdpld_irq
+	.typename = "M32700UT-PLD-LCD-IRQ",
+	.startup = startup_m32700ut_lcdpld_irq,
+	.shutdown = shutdown_m32700ut_lcdpld_irq,
+	.enable = enable_m32700ut_lcdpld_irq,
+	.disable = disable_m32700ut_lcdpld_irq,
+	.ack = mask_and_ack_m32700ut_lcdpld,
+	.end = end_m32700ut_lcdpld_irq
 };
 
 void __init init_IRQ(void)
diff --git a/arch/m32r/kernel/setup_mappi.c b/arch/m32r/kernel/setup_mappi.c
index 1e74110..aaf8e56 100644
--- a/arch/m32r/kernel/setup_mappi.c
+++ b/arch/m32r/kernel/setup_mappi.c
@@ -70,13 +70,13 @@
 
 static struct hw_interrupt_type mappi_irq_type =
 {
-	"MAPPI-IRQ",
-	startup_mappi_irq,
-	shutdown_mappi_irq,
-	enable_mappi_irq,
-	disable_mappi_irq,
-	mask_and_ack_mappi,
-	end_mappi_irq
+	.typename = "MAPPI-IRQ",
+	.startup = startup_mappi_irq,
+	.shutdown = shutdown_mappi_irq,
+	.enable = enable_mappi_irq,
+	.disable = disable_mappi_irq,
+	.ack = mask_and_ack_mappi,
+	.end = end_mappi_irq
 };
 
 void __init init_IRQ(void)
diff --git a/arch/m32r/kernel/setup_mappi2.c b/arch/m32r/kernel/setup_mappi2.c
index 1904d46..38d5e9a 100644
--- a/arch/m32r/kernel/setup_mappi2.c
+++ b/arch/m32r/kernel/setup_mappi2.c
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/m32r/kernel/setup_mappi.c
+ *  linux/arch/m32r/kernel/setup_mappi2.c
  *
  *  Setup routines for Renesas MAPPI-II(M3A-ZA36) Board
  *
@@ -79,13 +79,13 @@
 
 static struct hw_interrupt_type mappi2_irq_type =
 {
-	"MAPPI2-IRQ",
-	startup_mappi2_irq,
-	shutdown_mappi2_irq,
-	enable_mappi2_irq,
-	disable_mappi2_irq,
-	mask_and_ack_mappi2,
-	end_mappi2_irq
+	.typename = "MAPPI2-IRQ",
+	.startup = startup_mappi2_irq,
+	.shutdown = shutdown_mappi2_irq,
+	.enable = enable_mappi2_irq,
+	.disable = disable_mappi2_irq,
+	.ack = mask_and_ack_mappi2,
+	.end = end_mappi2_irq
 };
 
 void __init init_IRQ(void)
@@ -156,7 +156,6 @@
 	irq_desc[PLD_IRQ_CFIREQ].handler = &mappi2_irq_type;
 	irq_desc[PLD_IRQ_CFIREQ].action = 0;
 	irq_desc[PLD_IRQ_CFIREQ].depth = 1;	/* disable nested irq */
-//	icu_data[PLD_IRQ_CFIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD00;
 	icu_data[PLD_IRQ_CFIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
 	disable_mappi2_irq(PLD_IRQ_CFIREQ);
 
@@ -167,7 +166,6 @@
 	irq_desc[PLD_IRQ_CFC_INSERT].action = 0;
 	irq_desc[PLD_IRQ_CFC_INSERT].depth = 1;	/* disable nested irq */
 	icu_data[PLD_IRQ_CFC_INSERT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD00;
-//	icu_data[PLD_IRQ_CFC_INSERT].icucr = 0;
 	disable_mappi2_irq(PLD_IRQ_CFC_INSERT);
 
 	/* ICUCR42: CFC Eject */
@@ -176,9 +174,7 @@
 	irq_desc[PLD_IRQ_CFC_EJECT].action = 0;
 	irq_desc[PLD_IRQ_CFC_EJECT].depth = 1;	/* disable nested irq */
 	icu_data[PLD_IRQ_CFC_EJECT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
-//	icu_data[PLD_IRQ_CFC_EJECT].icucr = 0;
 	disable_mappi2_irq(PLD_IRQ_CFC_EJECT);
-
 #endif /* CONFIG_MAPPI2_CFC */
 }
 
diff --git a/arch/m32r/kernel/setup_mappi3.c b/arch/m32r/kernel/setup_mappi3.c
new file mode 100644
index 0000000..3d60a85
--- /dev/null
+++ b/arch/m32r/kernel/setup_mappi3.c
@@ -0,0 +1,208 @@
+/*
+ *  linux/arch/m32r/kernel/setup_mappi3.c
+ *
+ *  Setup routines for Renesas MAPPI-III(M3A-2170) Board
+ *
+ *  Copyright (c) 2001-2005   Hiroyuki Kondo, Hirokazu Takata,
+ *                            Hitoshi Yamamoto, Mamoru Sakugawa
+ */
+
+#include <linux/config.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/system.h>
+#include <asm/m32r.h>
+#include <asm/io.h>
+
+#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long)))
+
+#ifndef CONFIG_SMP
+typedef struct {
+	unsigned long icucr;  /* ICU Control Register */
+} icu_data_t;
+#endif /* CONFIG_SMP */
+
+icu_data_t icu_data[NR_IRQS];
+
+static void disable_mappi3_irq(unsigned int irq)
+{
+	unsigned long port, data;
+
+	if ((irq == 0) ||(irq >= NR_IRQS))  {
+		printk("bad irq 0x%08x\n", irq);
+		return;
+	}
+	port = irq2port(irq);
+	data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7;
+	outl(data, port);
+}
+
+static void enable_mappi3_irq(unsigned int irq)
+{
+	unsigned long port, data;
+
+	if ((irq == 0) ||(irq >= NR_IRQS))  {
+		printk("bad irq 0x%08x\n", irq);
+		return;
+	}
+	port = irq2port(irq);
+	data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6;
+	outl(data, port);
+}
+
+static void mask_and_ack_mappi3(unsigned int irq)
+{
+	disable_mappi3_irq(irq);
+}
+
+static void end_mappi3_irq(unsigned int irq)
+{
+	enable_mappi3_irq(irq);
+}
+
+static unsigned int startup_mappi3_irq(unsigned int irq)
+{
+	enable_mappi3_irq(irq);
+	return (0);
+}
+
+static void shutdown_mappi3_irq(unsigned int irq)
+{
+	unsigned long port;
+
+	port = irq2port(irq);
+	outl(M32R_ICUCR_ILEVEL7, port);
+}
+
+static struct hw_interrupt_type mappi3_irq_type =
+{
+	.typename = "MAPPI3-IRQ",
+	.startup = startup_mappi3_irq,
+	.shutdown = shutdown_mappi3_irq,
+	.enable = enable_mappi3_irq,
+	.disable = disable_mappi3_irq,
+	.ack = mask_and_ack_mappi3,
+	.end = end_mappi3_irq
+};
+
+void __init init_IRQ(void)
+{
+#if defined(CONFIG_SMC91X)
+	/* INT0 : LAN controller (SMC91111) */
+	irq_desc[M32R_IRQ_INT0].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_INT0].handler = &mappi3_irq_type;
+	irq_desc[M32R_IRQ_INT0].action = 0;
+	irq_desc[M32R_IRQ_INT0].depth = 1;
+	icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
+	disable_mappi3_irq(M32R_IRQ_INT0);
+#endif  /* CONFIG_SMC91X */
+
+	/* MFT2 : system timer */
+	irq_desc[M32R_IRQ_MFT2].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_MFT2].handler = &mappi3_irq_type;
+	irq_desc[M32R_IRQ_MFT2].action = 0;
+	irq_desc[M32R_IRQ_MFT2].depth = 1;
+	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
+	disable_mappi3_irq(M32R_IRQ_MFT2);
+
+#ifdef CONFIG_SERIAL_M32R_SIO
+	/* SIO0_R : uart receive data */
+	irq_desc[M32R_IRQ_SIO0_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_R].handler = &mappi3_irq_type;
+	irq_desc[M32R_IRQ_SIO0_R].action = 0;
+	irq_desc[M32R_IRQ_SIO0_R].depth = 1;
+	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
+	disable_mappi3_irq(M32R_IRQ_SIO0_R);
+
+	/* SIO0_S : uart send data */
+	irq_desc[M32R_IRQ_SIO0_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO0_S].handler = &mappi3_irq_type;
+	irq_desc[M32R_IRQ_SIO0_S].action = 0;
+	irq_desc[M32R_IRQ_SIO0_S].depth = 1;
+	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
+	disable_mappi3_irq(M32R_IRQ_SIO0_S);
+	/* SIO1_R : uart receive data */
+	irq_desc[M32R_IRQ_SIO1_R].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_R].handler = &mappi3_irq_type;
+	irq_desc[M32R_IRQ_SIO1_R].action = 0;
+	irq_desc[M32R_IRQ_SIO1_R].depth = 1;
+	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
+	disable_mappi3_irq(M32R_IRQ_SIO1_R);
+
+	/* SIO1_S : uart send data */
+	irq_desc[M32R_IRQ_SIO1_S].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_SIO1_S].handler = &mappi3_irq_type;
+	irq_desc[M32R_IRQ_SIO1_S].action = 0;
+	irq_desc[M32R_IRQ_SIO1_S].depth = 1;
+	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
+	disable_mappi3_irq(M32R_IRQ_SIO1_S);
+#endif  /* CONFIG_M32R_USE_DBG_CONSOLE */
+
+#if defined(CONFIG_USB)
+	/* INT1 : USB Host controller interrupt */
+	irq_desc[M32R_IRQ_INT1].status = IRQ_DISABLED;
+	irq_desc[M32R_IRQ_INT1].handler = &mappi3_irq_type;
+	irq_desc[M32R_IRQ_INT1].action = 0;
+	irq_desc[M32R_IRQ_INT1].depth = 1;
+	icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_ISMOD01;
+	disable_mappi3_irq(M32R_IRQ_INT1);
+#endif /* CONFIG_USB */
+
+	/* ICUCR40: CFC IREQ */
+	irq_desc[PLD_IRQ_CFIREQ].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_CFIREQ].handler = &mappi3_irq_type;
+	irq_desc[PLD_IRQ_CFIREQ].action = 0;
+	irq_desc[PLD_IRQ_CFIREQ].depth = 1;	/* disable nested irq */
+	icu_data[PLD_IRQ_CFIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
+	disable_mappi3_irq(PLD_IRQ_CFIREQ);
+
+#if defined(CONFIG_M32R_CFC)
+	/* ICUCR41: CFC Insert */
+	irq_desc[PLD_IRQ_CFC_INSERT].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_CFC_INSERT].handler = &mappi3_irq_type;
+	irq_desc[PLD_IRQ_CFC_INSERT].action = 0;
+	irq_desc[PLD_IRQ_CFC_INSERT].depth = 1;	/* disable nested irq */
+	icu_data[PLD_IRQ_CFC_INSERT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD00;
+	disable_mappi3_irq(PLD_IRQ_CFC_INSERT);
+
+	/* ICUCR42: CFC Eject */
+	irq_desc[PLD_IRQ_CFC_EJECT].status = IRQ_DISABLED;
+	irq_desc[PLD_IRQ_CFC_EJECT].handler = &mappi3_irq_type;
+	irq_desc[PLD_IRQ_CFC_EJECT].action = 0;
+	irq_desc[PLD_IRQ_CFC_EJECT].depth = 1;	/* disable nested irq */
+	icu_data[PLD_IRQ_CFC_EJECT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
+	disable_mappi3_irq(PLD_IRQ_CFC_EJECT);
+#endif /* CONFIG_M32R_CFC */
+}
+
+#define LAN_IOSTART     0x300
+#define LAN_IOEND       0x320
+static struct resource smc91x_resources[] = {
+	[0] = {
+		.start  = (LAN_IOSTART),
+		.end    = (LAN_IOEND),
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = M32R_IRQ_INT0,
+		.end    = M32R_IRQ_INT0,
+		.flags  = IORESOURCE_IRQ,
+	}
+};
+
+static struct platform_device smc91x_device = {
+	.name		= "smc91x",
+	.id		= 0,
+	.num_resources  = ARRAY_SIZE(smc91x_resources),
+	.resource       = smc91x_resources,
+};
+
+static int __init platform_init(void)
+{
+	platform_device_register(&smc91x_device);
+	return 0;
+}
+arch_initcall(platform_init);
diff --git a/arch/m32r/kernel/setup_oaks32r.c b/arch/m32r/kernel/setup_oaks32r.c
index b048345..d656640 100644
--- a/arch/m32r/kernel/setup_oaks32r.c
+++ b/arch/m32r/kernel/setup_oaks32r.c
@@ -70,13 +70,13 @@
 
 static struct hw_interrupt_type oaks32r_irq_type =
 {
-	"OAKS32R-IRQ",
-	startup_oaks32r_irq,
-	shutdown_oaks32r_irq,
-	enable_oaks32r_irq,
-	disable_oaks32r_irq,
-	mask_and_ack_mappi,
-	end_oaks32r_irq
+	.typename = "OAKS32R-IRQ",
+	.startup = startup_oaks32r_irq,
+	.shutdown = shutdown_oaks32r_irq,
+	.enable = enable_oaks32r_irq,
+	.disable = disable_oaks32r_irq,
+	.ack = mask_and_ack_mappi,
+	.end = end_oaks32r_irq
 };
 
 void __init init_IRQ(void)
diff --git a/arch/m32r/kernel/setup_opsput.c b/arch/m32r/kernel/setup_opsput.c
index 84315e3..86f4cf2 100644
--- a/arch/m32r/kernel/setup_opsput.c
+++ b/arch/m32r/kernel/setup_opsput.c
@@ -79,13 +79,13 @@
 
 static struct hw_interrupt_type opsput_irq_type =
 {
-	"OPSPUT-IRQ",
-	startup_opsput_irq,
-	shutdown_opsput_irq,
-	enable_opsput_irq,
-	disable_opsput_irq,
-	mask_and_ack_opsput,
-	end_opsput_irq
+	.typename = "OPSPUT-IRQ",
+	.startup = startup_opsput_irq,
+	.shutdown = shutdown_opsput_irq,
+	.enable = enable_opsput_irq,
+	.disable = disable_opsput_irq,
+	.ack = mask_and_ack_opsput,
+	.end = end_opsput_irq
 };
 
 /*
@@ -156,13 +156,13 @@
 
 static struct hw_interrupt_type opsput_pld_irq_type =
 {
-	"OPSPUT-PLD-IRQ",
-	startup_opsput_pld_irq,
-	shutdown_opsput_pld_irq,
-	enable_opsput_pld_irq,
-	disable_opsput_pld_irq,
-	mask_and_ack_opsput_pld,
-	end_opsput_pld_irq
+	.typename = "OPSPUT-PLD-IRQ",
+	.startup = startup_opsput_pld_irq,
+	.shutdown = shutdown_opsput_pld_irq,
+	.enable = enable_opsput_pld_irq,
+	.disable = disable_opsput_pld_irq,
+	.ack = mask_and_ack_opsput_pld,
+	.end = end_opsput_pld_irq
 };
 
 /*
diff --git a/arch/m32r/kernel/setup_usrv.c b/arch/m32r/kernel/setup_usrv.c
index fe417be..634741b 100644
--- a/arch/m32r/kernel/setup_usrv.c
+++ b/arch/m32r/kernel/setup_usrv.c
@@ -70,13 +70,13 @@
 
 static struct hw_interrupt_type mappi_irq_type =
 {
-	"M32700-IRQ",
-	startup_mappi_irq,
-	shutdown_mappi_irq,
-	enable_mappi_irq,
-	disable_mappi_irq,
-	mask_and_ack_mappi,
-	end_mappi_irq
+	.typename = "M32700-IRQ",
+	.startup = startup_mappi_irq,
+	.shutdown = shutdown_mappi_irq,
+	.enable = enable_mappi_irq,
+	.disable = disable_mappi_irq,
+	.ack = mask_and_ack_mappi,
+	.end = end_mappi_irq
 };
 
 /*
@@ -143,13 +143,13 @@
 
 static struct hw_interrupt_type m32700ut_pld_irq_type =
 {
-	"USRV-PLD-IRQ",
-	startup_m32700ut_pld_irq,
-	shutdown_m32700ut_pld_irq,
-	enable_m32700ut_pld_irq,
-	disable_m32700ut_pld_irq,
-	mask_and_ack_m32700ut_pld,
-	end_m32700ut_pld_irq
+	.typename = "USRV-PLD-IRQ",
+	.startup = startup_m32700ut_pld_irq,
+	.shutdown = shutdown_m32700ut_pld_irq,
+	.enable = enable_m32700ut_pld_irq,
+	.disable = disable_m32700ut_pld_irq,
+	.ack = mask_and_ack_m32700ut_pld,
+	.end = end_m32700ut_pld_irq
 };
 
 void __init init_IRQ(void)
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c
index 50311eb..5aef7e4 100644
--- a/arch/m32r/kernel/signal.c
+++ b/arch/m32r/kernel/signal.c
@@ -371,10 +371,8 @@
 	if (!user_mode(regs))
 		return 1;
 
-	if (current->flags & PF_FREEZE) {
-		refrigerator(0);
+	if (try_to_freeze()) 
 		goto no_signal;
-	}
 
 	if (!oldset)
 		oldset = &current->blocked;
diff --git a/arch/m32r/m32700ut/defconfig.m32700ut.smp b/arch/m32r/m32700ut/defconfig.m32700ut.smp
index 1c00218..3e607d9 100644
--- a/arch/m32r/m32700ut/defconfig.m32700ut.smp
+++ b/arch/m32r/m32700ut/defconfig.m32700ut.smp
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:10:50 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun  3 16:20:58 2005
 #
 CONFIG_M32R=y
 # CONFIG_UID16 is not set
@@ -15,6 +15,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -27,13 +28,16 @@
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=15
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 # CONFIG_IKCONFIG_PROC is not set
+# CONFIG_CPUSETS is not set
 CONFIG_EMBEDDED=y
 # CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -43,6 +47,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -65,6 +70,7 @@
 # CONFIG_PLAT_OPSPUT is not set
 # CONFIG_PLAT_OAKS32R is not set
 # CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
 CONFIG_CHIP_M32700=y
 # CONFIG_CHIP_M32102 is not set
 # CONFIG_CHIP_VDEC2 is not set
@@ -271,7 +277,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
@@ -396,18 +401,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -417,6 +410,17 @@
 # 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_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -468,6 +472,10 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -511,8 +519,14 @@
 # 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_SOFT_CURSOR is not set
+# CONFIG_FB_MACMODES is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -546,10 +560,6 @@
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
@@ -722,8 +732,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=15
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_FRAME_POINTER is not set
 
diff --git a/arch/m32r/m32700ut/defconfig.m32700ut.up b/arch/m32r/m32700ut/defconfig.m32700ut.up
index 805357f..2d3e7cd 100644
--- a/arch/m32r/m32700ut/defconfig.m32700ut.up
+++ b/arch/m32r/m32700ut/defconfig.m32700ut.up
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:10:54 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun  3 16:21:34 2005
 #
 CONFIG_M32R=y
 # CONFIG_UID16 is not set
@@ -16,6 +16,7 @@
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -28,13 +29,15 @@
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 # CONFIG_IKCONFIG_PROC is not set
 CONFIG_EMBEDDED=y
 # CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -44,6 +47,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -65,6 +69,7 @@
 # CONFIG_PLAT_OPSPUT is not set
 # CONFIG_PLAT_OAKS32R is not set
 # CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
 CONFIG_CHIP_M32700=y
 # CONFIG_CHIP_M32102 is not set
 # CONFIG_CHIP_VDEC2 is not set
@@ -268,7 +273,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
@@ -393,18 +397,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -414,6 +406,17 @@
 # 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_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -465,6 +468,10 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -508,8 +515,14 @@
 # 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_SOFT_CURSOR is not set
+# CONFIG_FB_MACMODES is not set
 # CONFIG_FB_MODE_HELPERS is not set
 # CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -543,10 +556,6 @@
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
@@ -719,8 +728,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_FRAME_POINTER is not set
 
diff --git a/arch/m32r/mappi/defconfig.nommu b/arch/m32r/mappi/defconfig.nommu
index 714aa6e..a8425fb 100644
--- a/arch/m32r/mappi/defconfig.nommu
+++ b/arch/m32r/mappi/defconfig.nommu
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:10:57 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun  3 16:21:46 2005
 #
 CONFIG_M32R=y
 # CONFIG_UID16 is not set
@@ -16,6 +16,7 @@
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -26,13 +27,15 @@
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 # CONFIG_IKCONFIG_PROC is not set
 CONFIG_EMBEDDED=y
 # CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -41,6 +44,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -62,6 +66,7 @@
 # CONFIG_PLAT_OPSPUT is not set
 # CONFIG_PLAT_OAKS32R is not set
 # CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
 CONFIG_CHIP_M32700=y
 # CONFIG_CHIP_M32102 is not set
 # CONFIG_CHIP_VDEC2 is not set
@@ -202,7 +207,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
@@ -325,18 +329,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -346,6 +338,17 @@
 # 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_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
 # Character devices
 #
 # CONFIG_VT is not set
@@ -394,6 +397,10 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -434,10 +441,6 @@
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
@@ -595,8 +598,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_FRAME_POINTER is not set
 
diff --git a/arch/m32r/mappi/defconfig.smp b/arch/m32r/mappi/defconfig.smp
index 956a8e2..1a7f3cd 100644
--- a/arch/m32r/mappi/defconfig.smp
+++ b/arch/m32r/mappi/defconfig.smp
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:11:02 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun  3 16:21:52 2005
 #
 CONFIG_M32R=y
 # CONFIG_UID16 is not set
@@ -17,6 +17,7 @@
 CONFIG_BROKEN=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -28,13 +29,16 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=15
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
 CONFIG_EMBEDDED=y
 # CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -44,6 +48,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -66,6 +71,7 @@
 # CONFIG_PLAT_OPSPUT is not set
 # CONFIG_PLAT_OAKS32R is not set
 # CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
 CONFIG_CHIP_M32700=y
 # CONFIG_CHIP_M32102 is not set
 # CONFIG_CHIP_VDEC2 is not set
@@ -139,8 +145,8 @@
 #
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
 # 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
@@ -294,7 +300,6 @@
 # Networking options
 #
 # CONFIG_PACKET is not set
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -420,18 +425,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -441,6 +434,17 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# 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 is not set
@@ -489,6 +493,10 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -529,10 +537,6 @@
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
@@ -708,8 +712,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=15
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_FRAME_POINTER is not set
 
diff --git a/arch/m32r/mappi/defconfig.up b/arch/m32r/mappi/defconfig.up
index c9253e9..38910fb 100644
--- a/arch/m32r/mappi/defconfig.up
+++ b/arch/m32r/mappi/defconfig.up
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:11:07 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun  3 16:21:59 2005
 #
 CONFIG_M32R=y
 # CONFIG_UID16 is not set
@@ -17,6 +17,7 @@
 CONFIG_BROKEN=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -28,13 +29,15 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_EMBEDDED=y
 # CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -44,6 +47,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -65,6 +69,7 @@
 # CONFIG_PLAT_OPSPUT is not set
 # CONFIG_PLAT_OAKS32R is not set
 # CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
 CONFIG_CHIP_M32700=y
 # CONFIG_CHIP_M32102 is not set
 # CONFIG_CHIP_VDEC2 is not set
@@ -135,8 +140,8 @@
 #
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
-CONFIG_MTD_PARTITIONS=y
 # 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
@@ -290,7 +295,6 @@
 # Networking options
 #
 # CONFIG_PACKET is not set
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -416,18 +420,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -437,6 +429,17 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# 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 is not set
@@ -485,6 +488,10 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -525,10 +532,6 @@
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
@@ -704,8 +707,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_FRAME_POINTER is not set
 
diff --git a/arch/m32r/mappi2/defconfig.vdec2 b/arch/m32r/mappi2/defconfig.vdec2
index c14791d..56f287b 100644
--- a/arch/m32r/mappi2/defconfig.vdec2
+++ b/arch/m32r/mappi2/defconfig.vdec2
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:11:10 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun  3 16:22:02 2005
 #
 CONFIG_M32R=y
 # CONFIG_UID16 is not set
@@ -16,6 +16,7 @@
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -28,13 +29,15 @@
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 # CONFIG_IKCONFIG_PROC is not set
 CONFIG_EMBEDDED=y
 # CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -44,6 +47,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -65,6 +69,7 @@
 # CONFIG_PLAT_OPSPUT is not set
 # CONFIG_PLAT_OAKS32R is not set
 CONFIG_PLAT_MAPPI2=y
+# CONFIG_PLAT_MAPPI3 is not set
 # CONFIG_CHIP_M32700 is not set
 # CONFIG_CHIP_M32102 is not set
 CONFIG_CHIP_VDEC2=y
@@ -264,7 +269,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
@@ -389,18 +393,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -410,6 +402,17 @@
 # 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_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -460,6 +463,10 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -521,10 +528,6 @@
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
@@ -697,8 +700,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_FRAME_POINTER is not set
 
diff --git a/arch/m32r/mappi3/defconfig.smp b/arch/m32r/mappi3/defconfig.smp
new file mode 100644
index 0000000..2eebe75f
--- /dev/null
+++ b/arch/m32r/mappi3/defconfig.smp
@@ -0,0 +1,751 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc5
+# Tue May 31 17:55:34 2005
+#
+CONFIG_M32R=y
+# CONFIG_UID16 is not set
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+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_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE 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_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# 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
+CONFIG_STOP_MACHINE=y
+
+#
+# Processor type and features
+#
+# CONFIG_PLAT_MAPPI is not set
+# CONFIG_PLAT_USRV is not set
+# CONFIG_PLAT_M32700UT is not set
+# CONFIG_PLAT_OPSPUT is not set
+# CONFIG_PLAT_OAKS32R is not set
+# CONFIG_PLAT_MAPPI2 is not set
+CONFIG_PLAT_MAPPI3=y
+CONFIG_CHIP_M32700=y
+# CONFIG_CHIP_M32102 is not set
+# CONFIG_CHIP_VDEC2 is not set
+# CONFIG_CHIP_OPSP is not set
+CONFIG_MMU=y
+CONFIG_TLB_ENTRIES=32
+CONFIG_ISA_M32R2=y
+CONFIG_ISA_DSP_LEVEL2=y
+CONFIG_ISA_DUAL_ISSUE=y
+CONFIG_BUS_CLOCK=10000000
+CONFIG_TIMER_DIVIDE=128
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+CONFIG_MEMORY_START=0x08000000
+CONFIG_MEMORY_SIZE=0x08000000
+CONFIG_NOHIGHMEM=y
+CONFIG_DISCONTIGMEM=y
+CONFIG_IRAM_START=0x00f00000
+CONFIG_IRAM_SIZE=0x00080000
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_PREEMPT=y
+# CONFIG_HAVE_DEC_LOCK is not set
+CONFIG_SMP=y
+# CONFIG_CHIP_M32700_TS1 is not set
+CONFIG_NR_CPUS=2
+# CONFIG_NUMA is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+CONFIG_PCCARD=y
+# CONFIG_PCMCIA_DEBUG is not set
+CONFIG_PCMCIA=y
+
+#
+# PC-card bridges
+#
+# CONFIG_TCIC is not set
+# CONFIG_M32R_PCC is not set
+# CONFIG_M32R_CFC is not set
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+
+#
+# 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
+
+#
+# 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
+# CONFIG_MTD_OBSOLETE_CHIPS 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
+
+#
+# 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_FD 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=m
+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 is not set
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# 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_IDECS=y
+CONFIG_BLK_DEV_IDECD=m
+# 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_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_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# 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 is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+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_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_SMC91X=y
+# CONFIG_NE2000 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
+
+#
+# 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 is not set
+# 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 is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_SERIAL_M32R_SIO=y
+CONFIG_SERIAL_M32R_SIO_CONSOLE=y
+# CONFIG_SERIAL_M32R_PLDSIO 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
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_SYNCLINK_CS is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 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 is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# 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
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR 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=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS 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_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS 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 is not set
+# CONFIG_JFFS2_FS_NOR_ECC 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_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_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
+
+#
+# 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 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
+
+#
+# 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=15
+# CONFIG_DEBUG_BUGVERBOSE is not set
+# CONFIG_FRAME_POINTER 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
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/arch/m32r/mappi3/dot.gdbinit b/arch/m32r/mappi3/dot.gdbinit
new file mode 100644
index 0000000..89c2218
--- /dev/null
+++ b/arch/m32r/mappi3/dot.gdbinit
@@ -0,0 +1,224 @@
+# .gdbinit file
+# $Id: dot.gdbinit,v 1.1 2005/04/11 02:21:08 sakugawa Exp $
+
+# setting
+set width 0d70
+set radix 0d16
+use_debug_dma
+
+# Initialize SDRAM controller for Mappi
+define sdram_init
+  # SDIR0
+  set *(unsigned long *)0x00ef6008 = 0x00000182
+  # SDIR1
+  set *(unsigned long *)0x00ef600c = 0x00000001
+  # Initialize wait
+  shell sleep 0.1
+  # MOD
+  set *(unsigned long *)0x00ef602c = 0x00000020
+  set *(unsigned long *)0x00ef604c = 0x00000020
+  # TR
+  set *(unsigned long *)0x00ef6028 = 0x00051502
+  set *(unsigned long *)0x00ef6048 = 0x00051502
+  # ADR
+  set *(unsigned long *)0x00ef6020 = 0x08000004
+  set *(unsigned long *)0x00ef6040 = 0x0c000004
+  # AutoRef On
+  set *(unsigned long *)0x00ef6004 = 0x00010517
+  # Access enable
+  set *(unsigned long *)0x00ef6024 = 0x00000001
+  set *(unsigned long *)0x00ef6044 = 0x00000001
+end
+
+# Initialize LAN controller for Mappi
+define lanc_init
+  # Set BSEL4
+  #set *(unsigned long *)0x00ef5004 = 0x0fff330f
+  #set *(unsigned long *)0x00ef5004 = 0x01113301
+
+#  set *(unsigned long *)0x00ef5004 = 0x02011101
+#  set *(unsigned long *)0x00ef5004 = 0x04441104
+end
+
+define clock_init
+  set *(unsigned long *)0x00ef4010 = 2
+  set *(unsigned long *)0x00ef4014 = 2
+  set *(unsigned long *)0x00ef4020 = 3
+  set *(unsigned long *)0x00ef4024 = 3
+  set *(unsigned long *)0x00ef4004 = 0x7
+#  shell sleep 0.1
+#  set *(unsigned long *)0x00ef4004 = 0x5
+  shell sleep 0.1
+  set *(unsigned long *)0x00ef4008 = 0x0200
+end
+
+define port_init
+  set $sfrbase = 0x00ef0000
+  set *(unsigned short *)0x00ef1060 = 0x5555
+  set *(unsigned short *)0x00ef1062 = 0x5555
+  set *(unsigned short *)0x00ef1064 = 0x5555
+  set *(unsigned short *)0x00ef1066 = 0x5555
+  set *(unsigned short *)0x00ef1068 = 0x5555
+  set *(unsigned short *)0x00ef106a = 0x0000
+  set *(unsigned short *)0x00ef106e = 0x5555
+  set *(unsigned short *)0x00ef1070 = 0x5555
+end
+
+# MMU enable
+define mmu_enable
+  set $evb=0x88000000
+  set *(unsigned long *)0xffff0024=1
+end
+
+# MMU disable
+define mmu_disable
+  set $evb=0
+  set *(unsigned long *)0xffff0024=0
+end
+
+# Show TLB entries
+define show_tlb_entries
+  set $i = 0
+  set $addr = $arg0
+  while ($i < 0d16 )
+    set $tlb_tag = *(unsigned long*)$addr
+    set $tlb_data = *(unsigned long*)($addr + 4)
+    printf " [%2d] 0x%08lx : 0x%08lx - 0x%08lx\n", $i, $addr, $tlb_tag, $tlb_data
+    set $i = $i + 1
+    set $addr = $addr + 8
+  end
+end
+define itlb
+  set $itlb=0xfe000000
+  show_tlb_entries $itlb
+end
+define dtlb
+  set $dtlb=0xfe000800
+  show_tlb_entries $dtlb
+end
+
+# Cache ON
+define set_cache_type
+  set $mctype = (void*)0xfffffff8
+# chaos
+# set *(unsigned long *)($mctype) = 0x0000c000
+# m32102 i-cache only
+  set *(unsigned long *)($mctype) = 0x00008000
+# m32102 d-cache only
+#  set *(unsigned long *)($mctype) = 0x00004000
+end
+define cache_on
+  set $param = (void*)0x08001000
+  set *(unsigned long *)($param) = 0x60ff6102
+end
+
+
+# Show current task structure
+define show_current
+  set $current = $spi & 0xffffe000
+  printf "$current=0x%08lX\n",$current
+  print *(struct task_struct *)$current
+end
+
+# Show user assigned task structure
+define show_task
+  set $task = $arg0 & 0xffffe000
+  printf "$task=0x%08lX\n",$task
+  print *(struct task_struct *)$task
+end
+document show_task
+  Show user assigned task structure
+  arg0 : task structure address
+end
+
+# Show M32R registers
+define show_regs
+  printf " R0[0x%08lX]   R1[0x%08lX]   R2[0x%08lX]   R3[0x%08lX]\n",$r0,$r1,$r2,$r3
+  printf " R4[0x%08lX]   R5[0x%08lX]   R6[0x%08lX]   R7[0x%08lX]\n",$r4,$r5,$r6,$r7
+  printf " R8[0x%08lX]   R9[0x%08lX]  R10[0x%08lX]  R11[0x%08lX]\n",$r8,$r9,$r10,$r11
+  printf "R12[0x%08lX]   FP[0x%08lX]   LR[0x%08lX]   SP[0x%08lX]\n",$r12,$fp,$lr,$sp
+  printf "PSW[0x%08lX]  CBR[0x%08lX]  SPI[0x%08lX]  SPU[0x%08lX]\n",$psw,$cbr,$spi,$spu
+  printf "BPC[0x%08lX]   PC[0x%08lX] ACCL[0x%08lX] ACCH[0x%08lX]\n",$bpc,$pc,$accl,$acch
+  printf "EVB[0x%08lX]\n",$evb
+
+  set $mests = *(unsigned long *)0xffff000c
+  set $mdeva = *(unsigned long *)0xffff0010
+  printf "MESTS[0x%08lX] MDEVA[0x%08lX]\n",$mests,$mdeva
+end
+
+
+# Setup all
+define setup
+  clock_init
+  shell sleep 0.1
+  port_init
+  sdram_init
+#  lanc_init
+#  dispc_init
+#  set $evb=0x08000000
+end
+
+# Load modules
+define load_modules
+  use_debug_dma
+  load
+#  load busybox.mot
+end
+
+# Set kernel parameters
+define set_kernel_parameters
+  set $param = (void*)0x08001000
+
+  ## MOUNT_ROOT_RDONLY
+  set {long}($param+0x00)=0
+  ## RAMDISK_FLAGS
+  #set {long}($param+0x04)=0
+  ## ORIG_ROOT_DEV
+  #set {long}($param+0x08)=0x00000100
+  ## LOADER_TYPE
+  #set {long}($param+0x0C)=0
+  ## INITRD_START
+  set {long}($param+0x10)=0x082a0000
+  ## INITRD_SIZE
+  set {long}($param+0x14)=0d6200000
+
+  # M32R_CPUCLK
+  set *(unsigned long *)($param + 0x0018) = 0d100000000
+  # M32R_BUSCLK
+  set *(unsigned long *)($param + 0x001c) = 0d50000000
+  # M32R_TIMER_DIVIDE
+  set *(unsigned long *)($param + 0x0020) = 0d128
+
+
+ set {char[0x200]}($param + 0x100) = "console=ttyS0,115200n8x root=/dev/nfsroot nfsroot=192.168.0.1:/project/m32r-linux/export/root.2.6_04 nfsaddrs=192.168.0.102:192.168.0.1:192.168.0.1:255.255.255.0:mappi: \0"
+
+
+end
+
+# Boot
+define boot
+  set_kernel_parameters
+  debug_chaos
+  set *(unsigned long *)0x00f00000=0x08002000
+  set $pc=0x08002000
+  set $fp=0
+  del b
+  si
+end
+
+# Restart
+define restart
+  sdireset
+  sdireset
+  setup
+  load_modules
+  boot
+end
+
+sdireset
+sdireset
+file vmlinux
+target m32rsdi
+
+restart
+boot
diff --git a/arch/m32r/mm/extable.c b/arch/m32r/mm/extable.c
index 9a97363..1743f23 100644
--- a/arch/m32r/mm/extable.c
+++ b/arch/m32r/mm/extable.c
@@ -1,10 +1,8 @@
 /*
- * linux/arch/i386/mm/extable.c
+ * linux/arch/m32r/mm/extable.c
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/spinlock.h>
 #include <asm/uaccess.h>
 
 int fixup_exception(struct pt_regs *regs)
@@ -19,4 +17,3 @@
 
 	return 0;
 }
-
diff --git a/arch/m32r/mm/init.c b/arch/m32r/mm/init.c
index bc423d8..d9a40b1 100644
--- a/arch/m32r/mm/init.c
+++ b/arch/m32r/mm/init.c
@@ -49,7 +49,7 @@
 	printk("Free swap:       %6ldkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
 	for_each_pgdat(pgdat) {
 		for (i = 0; i < pgdat->node_spanned_pages; ++i) {
-			page = pgdat->node_mem_map + i;
+			page = pgdat_page_nr(pgdat, i);
 			total++;
 			if (PageHighMem(page))
 				highmem++;
@@ -152,7 +152,7 @@
 	reservedpages = 0;
 	for_each_online_node(nid)
 		for (i = 0 ; i < MAX_LOW_PFN(nid) - START_PFN(nid) ; i++)
-			if (PageReserved(NODE_DATA(nid)->node_mem_map + i))
+			if (PageReserved(nid_page_nr(nid, i)))
 				reservedpages++;
 
 	return reservedpages;
diff --git a/arch/m32r/oaks32r/defconfig.nommu b/arch/m32r/oaks32r/defconfig.nommu
index f2da9be..3f9fe51 100644
--- a/arch/m32r/oaks32r/defconfig.nommu
+++ b/arch/m32r/oaks32r/defconfig.nommu
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:11:13 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun  3 16:22:04 2005
 #
 CONFIG_M32R=y
 # CONFIG_UID16 is not set
@@ -16,6 +16,7 @@
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -26,12 +27,14 @@
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
 CONFIG_EMBEDDED=y
 # CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -40,6 +43,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 CONFIG_TINY_SHMEM=y
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -61,6 +65,7 @@
 # CONFIG_PLAT_OPSPUT is not set
 CONFIG_PLAT_OAKS32R=y
 # CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
 # CONFIG_CHIP_M32700 is not set
 CONFIG_CHIP_M32102=y
 # CONFIG_CHIP_VDEC2 is not set
@@ -92,10 +97,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 
@@ -193,7 +194,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
@@ -311,18 +311,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -332,6 +320,17 @@
 # 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_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
 # Character devices
 #
 # CONFIG_VT is not set
@@ -375,6 +374,10 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -415,10 +418,6 @@
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
@@ -574,8 +573,9 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 # CONFIG_DEBUG_KERNEL is not set
-CONFIG_DEBUG_PREEMPT=y
+CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_FRAME_POINTER is not set
 
diff --git a/arch/m32r/opsput/defconfig.opsput b/arch/m32r/opsput/defconfig.opsput
index a87e1ea..66adec6 100644
--- a/arch/m32r/opsput/defconfig.opsput
+++ b/arch/m32r/opsput/defconfig.opsput
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Wed Feb 16 21:11:41 2005
+# Linux kernel version: 2.6.12-rc5
+# Fri Jun  3 16:22:06 2005
 #
 CONFIG_M32R=y
 # CONFIG_UID16 is not set
@@ -15,6 +15,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -27,13 +28,15 @@
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 # CONFIG_IKCONFIG_PROC is not set
 CONFIG_EMBEDDED=y
 # CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -43,6 +46,7 @@
 CONFIG_CC_ALIGN_LOOPS=0
 CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -64,6 +68,7 @@
 CONFIG_PLAT_OPSPUT=y
 # CONFIG_PLAT_OAKS32R is not set
 # CONFIG_PLAT_MAPPI2 is not set
+# CONFIG_PLAT_MAPPI3 is not set
 # CONFIG_CHIP_M32700 is not set
 # CONFIG_CHIP_M32102 is not set
 # CONFIG_CHIP_VDEC2 is not set
@@ -243,7 +248,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
@@ -368,18 +372,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_LIBPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -389,6 +381,17 @@
 # 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_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+
+#
 # Character devices
 #
 # CONFIG_VT is not set
@@ -438,6 +441,10 @@
 # CONFIG_RAW_DRIVER is not set
 
 #
+# TPM devices
+#
+
+#
 # I2C support
 #
 # CONFIG_I2C is not set
@@ -478,10 +485,6 @@
 # CONFIG_USB_ARCH_HAS_OHCI is not set
 
 #
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
@@ -654,8 +657,10 @@
 #
 # 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
diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index d0713c7..691a246 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -357,6 +357,8 @@
 	  is hardwired on.  The 53c710 SCSI driver is known to suffer from
 	  this problem.
 
+source "mm/Kconfig"
+
 endmenu
 
 menu "General setup"
diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig
index 7dbf997..5649fba 100644
--- a/arch/m68k/configs/amiga_defconfig
+++ b/arch/m68k/configs/amiga_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr  5 14:05:59 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun  7 20:34:23 2005
 #
 CONFIG_M68K=y
 CONFIG_MMU=y
@@ -35,6 +35,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=y
@@ -135,7 +137,6 @@
 #
 CONFIG_AMIGA_FLOPPY=y
 CONFIG_AMIGA_Z2RAM=y
-# CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
@@ -223,17 +224,12 @@
 #
 # SCSI low-level drivers
 #
-# CONFIG_SCSI_7000FASST is not set
 # CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_GENERIC_NCR5380 is not set
 # CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
 # CONFIG_SCSI_PPA is not set
@@ -244,7 +240,6 @@
 # CONFIG_SCSI_QLOGIC_FAS is not set
 # CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_DEBUG is not set
 CONFIG_A3000_SCSI=y
 CONFIG_A2091_SCSI=y
@@ -492,7 +487,6 @@
 CONFIG_ZORRO8390=m
 CONFIG_APNE=m
 # CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
 # CONFIG_AT1700 is not set
@@ -620,7 +614,6 @@
 # CONFIG_SERIO_PARKBD is not set
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig
index 505a296..63024b0 100644
--- a/arch/m68k/configs/apollo_defconfig
+++ b/arch/m68k/configs/apollo_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr  5 14:06:00 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun  7 20:34:27 2005
 #
 CONFIG_M68K=y
 CONFIG_MMU=y
@@ -35,6 +35,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=y
@@ -497,7 +499,6 @@
 CONFIG_SERIO_LIBPS2=m
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig
index 617aa73..6433da2 100644
--- a/arch/m68k/configs/atari_defconfig
+++ b/arch/m68k/configs/atari_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr  5 14:06:18 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun  7 20:34:32 2005
 #
 CONFIG_M68K=y
 CONFIG_MMU=y
@@ -35,6 +35,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=y
@@ -531,7 +533,6 @@
 CONFIG_SERIO_LIBPS2=y
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig
index b501db5..da2a23a 100644
--- a/arch/m68k/configs/bvme6000_defconfig
+++ b/arch/m68k/configs/bvme6000_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr  5 14:06:19 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun  7 20:34:37 2005
 #
 CONFIG_M68K=y
 CONFIG_MMU=y
@@ -35,6 +35,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=y
@@ -496,7 +498,6 @@
 CONFIG_SERIO_LIBPS2=m
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig
index 2bf6cef..5125188 100644
--- a/arch/m68k/configs/hp300_defconfig
+++ b/arch/m68k/configs/hp300_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr  5 14:06:21 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun  7 20:34:41 2005
 #
 CONFIG_M68K=y
 CONFIG_MMU=y
@@ -35,6 +35,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=y
@@ -498,7 +500,6 @@
 CONFIG_SERIO_LIBPS2=m
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig
index 7074f85..15b80ab 100644
--- a/arch/m68k/configs/mac_defconfig
+++ b/arch/m68k/configs/mac_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr  5 14:06:24 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun  7 20:34:45 2005
 #
 CONFIG_M68K=y
 CONFIG_MMU=y
@@ -35,6 +35,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=y
@@ -540,7 +542,6 @@
 CONFIG_SERIO_LIBPS2=m
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig
index 61f09bc..f0d5534 100644
--- a/arch/m68k/configs/mvme147_defconfig
+++ b/arch/m68k/configs/mvme147_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr  5 14:06:28 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun  7 20:34:50 2005
 #
 CONFIG_M68K=y
 CONFIG_MMU=y
@@ -35,6 +35,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=y
@@ -498,7 +500,6 @@
 CONFIG_SERIO_LIBPS2=m
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig
index 69c0100..1d5c46f 100644
--- a/arch/m68k/configs/mvme16x_defconfig
+++ b/arch/m68k/configs/mvme16x_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr  5 14:06:31 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun  7 20:34:53 2005
 #
 CONFIG_M68K=y
 CONFIG_MMU=y
@@ -35,6 +35,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=y
@@ -497,7 +499,6 @@
 CONFIG_SERIO_LIBPS2=m
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig
index 550ec260..8562386 100644
--- a/arch/m68k/configs/q40_defconfig
+++ b/arch/m68k/configs/q40_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr  5 14:06:34 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun  7 20:34:58 2005
 #
 CONFIG_M68K=y
 CONFIG_MMU=y
@@ -35,6 +35,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=y
@@ -125,7 +127,6 @@
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=m
@@ -210,17 +211,12 @@
 #
 # SCSI low-level drivers
 #
-# CONFIG_SCSI_7000FASST is not set
 # CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DTC3280 is not set
-# CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_GENERIC_NCR5380 is not set
 # CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
 # CONFIG_SCSI_NCR53C406A is not set
@@ -229,7 +225,6 @@
 # CONFIG_SCSI_QLOGIC_FAS is not set
 # CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_DEBUG is not set
 
 #
@@ -466,7 +461,6 @@
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=m
 # CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
 # CONFIG_AT1700 is not set
@@ -570,7 +564,6 @@
 CONFIG_SERIO_LIBPS2=m
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig
index 5b5a619..af903b5 100644
--- a/arch/m68k/configs/sun3_defconfig
+++ b/arch/m68k/configs/sun3_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr  5 14:06:37 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun  7 20:35:02 2005
 #
 CONFIG_M68K=y
 CONFIG_MMU=y
@@ -35,6 +35,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=y
@@ -171,7 +173,6 @@
 #
 # CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_DEBUG is not set
-CONFIG_SUN3_SCSI=y
 
 #
 # Multi-device support (RAID and LVM)
@@ -487,7 +488,6 @@
 CONFIG_SERIO_LIBPS2=m
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig
index 704e423..997143b 100644
--- a/arch/m68k/configs/sun3x_defconfig
+++ b/arch/m68k/configs/sun3x_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr  5 14:06:40 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun  7 20:35:06 2005
 #
 CONFIG_M68K=y
 CONFIG_MMU=y
@@ -35,6 +35,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=y
@@ -497,7 +499,6 @@
 CONFIG_SERIO_LIBPS2=m
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
diff --git a/arch/m68k/defconfig b/arch/m68k/defconfig
index 5b2296e..7d935e4 100644
--- a/arch/m68k/defconfig
+++ b/arch/m68k/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.12-rc2-m68k
-# Tue Apr  5 14:05:31 2005
+# Linux kernel version: 2.6.12-rc6-m68k
+# Tue Jun  7 20:34:17 2005
 #
 CONFIG_M68K=y
 CONFIG_MMU=y
@@ -33,6 +33,8 @@
 # CONFIG_EMBEDDED is not set
 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
@@ -355,7 +357,6 @@
 CONFIG_SERIO_LIBPS2=y
 # CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
 
 #
 # Character devices
diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig
index e729bd2..dbfcdc8 100644
--- a/arch/m68knommu/Kconfig
+++ b/arch/m68knommu/Kconfig
@@ -532,6 +532,8 @@
 
 endchoice
 
+source "mm/Kconfig"
+
 endmenu
 
 config ISA_DMA_API
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index ab99446..bd9de7b 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -492,7 +492,7 @@
 	  which allows for more memory.  Your system is most probably
 	  running in M-Mode, so you should say N here.
 
-config DISCONTIGMEM
+config ARCH_DISCONTIGMEM_ENABLE
 	bool
 	default y if SGI_IP27
 	help
@@ -1416,6 +1416,12 @@
 	bool "High Memory Support"
 	depends on MIPS32 && (CPU_R3000 || CPU_SB1 || CPU_R7000 || CPU_RM9000 || CPU_R10000) && !(MACH_DECSTATION || MOMENCO_JAGUAR_ATX)
 
+config ARCH_FLATMEM_ENABLE
+	def_bool y
+	depends on !NUMA
+
+source "mm/Kconfig"
+
 config SMP
 	bool "Multi-Processing support"
 	depends on CPU_RM9000 || (SIBYTE_SB1250 && !SIBYTE_STANDALONE) || SGI_IP27
diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig
index 1347229..b5bab3a 100644
--- a/arch/mips/configs/ip27_defconfig
+++ b/arch/mips/configs/ip27_defconfig
@@ -82,7 +82,7 @@
 # CONFIG_SGI_IP22 is not set
 CONFIG_SGI_IP27=y
 # CONFIG_SGI_SN0_N_MODE is not set
-CONFIG_DISCONTIGMEM=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
 CONFIG_NUMA=y
 # CONFIG_MAPPED_KERNEL is not set
 # CONFIG_REPLICATE_KTEXT is not set
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 6018ca2..3a240e3 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -33,6 +33,7 @@
 #include <linux/root_dev.h>
 #include <linux/highmem.h>
 #include <linux/console.h>
+#include <linux/mmzone.h>
 
 #include <asm/addrspace.h>
 #include <asm/bootinfo.h>
@@ -356,6 +357,8 @@
 	}
 #endif
 
+	memory_present(0, first_usable_pfn, max_low_pfn);
+
 	/* Initialize the boot-time allocator with low memory only.  */
 	bootmap_size = init_bootmem(first_usable_pfn, max_low_pfn);
 
@@ -557,6 +560,7 @@
 
 	parse_cmdline_early();
 	bootmem_init();
+	sparse_init();
 	paging_init();
 	resource_init();
 }
diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c
index b027ce7..9c9a271 100644
--- a/arch/mips/mm/init.c
+++ b/arch/mips/mm/init.c
@@ -128,7 +128,7 @@
 #endif /* CONFIG_MIPS64 */
 #endif /* CONFIG_HIGHMEM */
 
-#ifndef CONFIG_DISCONTIGMEM
+#ifndef CONFIG_NEED_MULTIPLE_NODES
 extern void pagetable_init(void);
 
 void __init paging_init(void)
@@ -232,7 +232,6 @@
 #ifdef CONFIG_LIMITED_DMA
 		set_page_address(page, lowmem_page_address(page));
 #endif
-		set_bit(PG_highmem, &page->flags);
 		set_page_count(page, 1);
 		__free_page(page);
 		totalhigh_pages++;
@@ -254,7 +253,7 @@
 	       initsize >> 10,
 	       (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
 }
-#endif /* !CONFIG_DISCONTIGMEM */
+#endif /* !CONFIG_NEED_MULTIPLE_NODES */
 
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
diff --git a/arch/mips/mm/pgtable.c b/arch/mips/mm/pgtable.c
index 3b88fde..3fe9420 100644
--- a/arch/mips/mm/pgtable.c
+++ b/arch/mips/mm/pgtable.c
@@ -5,7 +5,7 @@
 
 void show_mem(void)
 {
-#ifndef CONFIG_DISCONTIGMEM  /* XXX(hch): later.. */
+#ifndef CONFIG_NEED_MULTIPLE_NODES  /* XXX(hch): later.. */
 	int pfn, total = 0, reserved = 0;
 	int shared = 0, cached = 0;
 	int highmem = 0;
diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c
index 0a44a98..a160d04 100644
--- a/arch/mips/sgi-ip27/ip27-memory.c
+++ b/arch/mips/sgi-ip27/ip27-memory.c
@@ -549,9 +549,8 @@
 		 */
 		numslots = node_getlastslot(node);
 		for (slot = 1; slot <= numslots; slot++) {
-			p = NODE_DATA(node)->node_mem_map +
-				(slot_getbasepfn(node, slot) -
-				 slot_getbasepfn(node, 0));
+			p = nid_page_nr(node, slot_getbasepfn(node, slot) -
+					      slot_getbasepfn(node, 0));
 
 			/*
 			 * Free valid memory in current slot.
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index e7e7c56..ce327c7 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -148,7 +148,7 @@
 	default y if SMP
 	select HOTPLUG
 
-config DISCONTIGMEM
+config ARCH_DISCONTIGMEM_ENABLE
 	bool "Discontiguous memory support (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
 	help
@@ -157,6 +157,8 @@
 	  or have huge holes in the physical address space for other reasons.
 	  See <file:Documentation/vm/numa> for more.
 
+source "mm/Kconfig"
+
 config PREEMPT
 	bool
 #	bool "Preemptible Kernel"
diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
index ebf1866..d34bbe7 100644
--- a/arch/parisc/kernel/drivers.c
+++ b/arch/parisc/kernel/drivers.c
@@ -466,7 +466,7 @@
 }
 
 #define pa_dev_attr(name, field, format_string)				\
-static ssize_t name##_show(struct device *dev, char *buf)		\
+static ssize_t name##_show(struct device *dev, struct device_attribute *attr, char *buf)		\
 {									\
 	struct parisc_device *padev = to_parisc_device(dev);		\
 	return sprintf(buf, format_string, padev->field);		\
diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c
index cac3758..2886ad7 100644
--- a/arch/parisc/mm/init.c
+++ b/arch/parisc/mm/init.c
@@ -506,7 +506,7 @@
 		for (j = node_start_pfn(i); j < node_end_pfn(i); j++) {
 			struct page *p;
 
-			p = node_mem_map(i) + j - node_start_pfn(i);
+			p = nid_page_nr(i, j) - node_start_pfn(i);
 
 			total++;
 			if (PageReserved(p))
diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig
index 6e6377a..a7835cd 100644
--- a/arch/ppc/Kconfig
+++ b/arch/ppc/Kconfig
@@ -88,6 +88,9 @@
 	depends on BROKEN
 	bool "8xx"
 
+config E200
+	bool "e200"
+
 config E500
 	bool "e500"
 
@@ -98,12 +101,12 @@
 
 config BOOKE
 	bool
-	depends on E500
+	depends on E200 || E500
 	default y
 
 config FSL_BOOKE
 	bool
-	depends on E500
+	depends on E200 || E500
 	default y
 
 config PTE_64BIT
@@ -141,16 +144,16 @@
 
 config SPE
 	bool "SPE Support"
-	depends on E500
+	depends on E200 || E500
 	---help---
 	  This option enables kernel support for the Signal Processing
 	  Extensions (SPE) to the PowerPC processor. The kernel currently
 	  supports saving and restoring SPE registers, and turning on the
 	  'spe enable' bit so user processes can execute SPE instructions.
 
-	  This option is only usefully if you have a processor that supports
+	  This option is only useful if you have a processor that supports
 	  SPE (e500, otherwise known as 85xx series), but does not have any
-	  affect on a non-spe cpu (it does, however add code to the kernel).
+	  effect on a non-spe cpu (it does, however add code to the kernel).
 
 	  If in doubt, say Y here.
 
@@ -200,7 +203,7 @@
 
 config MATH_EMULATION
 	bool "Math emulation"
-	depends on 4xx || 8xx || E500
+	depends on 4xx || 8xx || E200 || E500
 	---help---
 	  Some PowerPC chips designed for embedded applications do not have
 	  a floating-point unit and therefore do not implement the
@@ -214,6 +217,26 @@
 	  here.  Saying Y here will not hurt performance (on any machine) but
 	  will increase the size of the kernel.
 
+config KEXEC
+	bool "kexec system call (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	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
+	  you can start any kernel with it, not just Linux.
+
+	  The name comes from the similiarity to the exec system call.
+
+	  It is an ongoing process to be certain the hardware in a machine
+	  is properly shutdown, so do not be surprised if this code does not
+	  initially work for you.  It may help to enable device hotplugging
+	  support.  As of this writing the exact hardware interface is
+	  strongly in flux, so no good recommendation can be made.
+
+	  In the GameCube implementation, kexec allows you to load and
+	  run DOL files, including kernel and homebrew DOLs.
+
 source "drivers/cpufreq/Kconfig"
 
 config CPU_FREQ_PMAC
@@ -254,7 +277,7 @@
 
 config NOT_COHERENT_CACHE
 	bool
-	depends on 4xx || 8xx
+	depends on 4xx || 8xx || E200
 	default y
 
 endmenu
@@ -826,11 +849,6 @@
 	depends on PCORE || POWERPMC250 || LOPEC || SANDPOINT
 	default y
 
-config FSL_OCP
-	bool
-	depends on MPC10X_BRIDGE
-	default y
-
 config MPC10X_OPENPIC
 	bool
 	depends on POWERPMC250 || LOPEC || SANDPOINT
@@ -910,6 +928,8 @@
 config HIGHMEM
 	bool "High memory support"
 
+source "mm/Kconfig"
+
 source "fs/Kconfig.binfmt"
 
 config PROC_DEVICETREE
@@ -1083,6 +1103,23 @@
 
 source kernel/power/Kconfig
 
+config SECCOMP
+	bool "Enable seccomp to safely compute untrusted bytecode"
+	depends on PROC_FS
+	default y
+	help
+	  This kernel feature is useful for number crunching applications
+	  that may need to compute untrusted bytecode during their
+	  execution. By using pipes or other transports made available to
+	  the process as file descriptors supporting the read/write
+	  syscalls, it's possible to isolate those applications in
+	  their own address space using seccomp. Once seccomp is
+	  enabled via /proc/<pid>/seccomp, it cannot be disabled
+	  and the task is only allowed to execute a few safe syscalls
+	  defined by each seccomp mode.
+
+	  If unsure, say Y. Only embedded should say N here.
+
 endmenu
 
 config ISA_DMA_API
diff --git a/arch/ppc/Kconfig.debug b/arch/ppc/Kconfig.debug
index d2e1eea..e16c771 100644
--- a/arch/ppc/Kconfig.debug
+++ b/arch/ppc/Kconfig.debug
@@ -66,7 +66,7 @@
 
 config PPC_OCP
 	bool
-	depends on IBM_OCP || FSL_OCP || XILINX_OCP
+	depends on IBM_OCP || XILINX_OCP
 	default y
 
 endmenu
diff --git a/arch/ppc/Makefile b/arch/ppc/Makefile
index 0432a25..f9b0d77 100644
--- a/arch/ppc/Makefile
+++ b/arch/ppc/Makefile
@@ -29,7 +29,7 @@
 
 CHECKFLAGS	+= -D__powerpc__
 
-ifndef CONFIG_E500
+ifndef CONFIG_FSL_BOOKE
 CFLAGS		+= -mstring
 endif
 
@@ -38,6 +38,7 @@
 cpu-as-$(CONFIG_6xx)		+= -Wa,-maltivec
 cpu-as-$(CONFIG_POWER4)		+= -Wa,-maltivec
 cpu-as-$(CONFIG_E500)		+= -Wa,-me500
+cpu-as-$(CONFIG_E200)		+= -Wa,-me200
 
 AFLAGS += $(cpu-as-y)
 CFLAGS += $(cpu-as-y)
diff --git a/arch/ppc/boot/ld.script b/arch/ppc/boot/ld.script
index 6ee602d..9362193 100644
--- a/arch/ppc/boot/ld.script
+++ b/arch/ppc/boot/ld.script
@@ -58,9 +58,6 @@
     *(.ramdisk)
     __ramdisk_end = .;
     . = ALIGN(4096);
-    __sysmap_begin = .;
-    *(.sysmap)
-    __sysmap_end = .;
     CONSTRUCTORS
   }
   _edata  =  .;
diff --git a/arch/ppc/boot/openfirmware/Makefile b/arch/ppc/boot/openfirmware/Makefile
index 4eacbd8..0341523 100644
--- a/arch/ppc/boot/openfirmware/Makefile
+++ b/arch/ppc/boot/openfirmware/Makefile
@@ -54,13 +54,10 @@
 	@echo '          RAM disk image must be provided separately'
 	@/bin/false
 
-objcpxmon-$(CONFIG_XMON) := --add-section=.sysmap=System.map \
-	--set-section-flags=.sysmap=contents,alloc,load,readonly,data
 quiet_cmd_genimage = GEN     $@
       cmd_genimage = $(OBJCOPY) -R .comment       \
 	--add-section=.image=$(images)/vmlinux.gz \
-	--set-section-flags=.image=contents,alloc,load,readonly,data \
-	$(objcpxmon-y) $< $@
+	--set-section-flags=.image=contents,alloc,load,readonly,data $< $@
 
 targets += image.o
 $(obj)/image.o: $(obj)/dummy.o $(images)/vmlinux.gz FORCE
diff --git a/arch/ppc/boot/openfirmware/chrpmain.c b/arch/ppc/boot/openfirmware/chrpmain.c
index 6fb4f73..effe4a0 100644
--- a/arch/ppc/boot/openfirmware/chrpmain.c
+++ b/arch/ppc/boot/openfirmware/chrpmain.c
@@ -39,7 +39,7 @@
 
 #define SCRATCH_SIZE	(128 << 10)
 
-static char scratch[SCRATCH_SIZE];	/* 1MB of scratch space for gunzip */
+static char scratch[SCRATCH_SIZE];	/* 128k of scratch space for gunzip */
 
 typedef void (*kernel_start_t)(int, int, void *, unsigned int, unsigned int);
 
diff --git a/arch/ppc/boot/openfirmware/common.c b/arch/ppc/boot/openfirmware/common.c
index 9e69527..0f46756 100644
--- a/arch/ppc/boot/openfirmware/common.c
+++ b/arch/ppc/boot/openfirmware/common.c
@@ -15,7 +15,6 @@
 #include <asm/page.h>
 
 /* Information from the linker */
-extern char __sysmap_begin, __sysmap_end;
 
 extern int strcmp(const char *s1, const char *s2);
 extern char *avail_ram, *avail_high;
@@ -116,14 +115,8 @@
 void make_bi_recs(unsigned long addr, char *name, unsigned int mach,
 		unsigned long progend)
 {
-	unsigned long sysmap_size;
 	struct bi_record *rec;
 
-	/* Figure out the size of a possible System.map we're going to
-	 * pass along.
-	 * */
-	sysmap_size = (unsigned long)(&__sysmap_end) -
-		(unsigned long)(&__sysmap_begin);
 
 	/* leave a 1MB gap then align to the next 1MB boundary */
 	addr = _ALIGN(addr+ (1<<20) - 1, (1<<20));
@@ -147,15 +140,6 @@
 	rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long);
 	rec = (struct bi_record *)((unsigned long)rec + rec->size);
 
-	if (sysmap_size) {
-		rec->tag = BI_SYSMAP;
-		rec->data[0] = (unsigned long)(&__sysmap_begin);
-		rec->data[1] = sysmap_size;
-		rec->size = sizeof(struct bi_record) + 2 *
-			sizeof(unsigned long);
-		rec = (struct bi_record *)((unsigned long)rec + rec->size);
-	}
-
 	rec->tag = BI_LAST;
 	rec->size = sizeof(struct bi_record);
 	rec = (struct bi_record *)((unsigned long)rec + rec->size);
diff --git a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile
index c28061a..991b4cb 100644
--- a/arch/ppc/boot/simple/Makefile
+++ b/arch/ppc/boot/simple/Makefile
@@ -203,7 +203,7 @@
 		$(obj)/dummy.o $(obj)/image.o
 	$(LD) $(LD_ARGS) -o $@ $(OBJS) $(obj)/image.o $(LIBS)
 	$(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab \
-		-R .stabstr -R .ramdisk -R .sysmap
+		-R .stabstr -R .ramdisk
 
 $(obj)/zvmlinux.initrd: $(OBJS) $(LIBS) $(srctree)/$(boot)/ld.script \
 		$(images)/vmlinux.gz $(obj)/dummy.o
@@ -215,7 +215,7 @@
 		$(obj)/dummy.o $(obj)/image.o
 	$(LD) $(LD_ARGS) -o $@ $(OBJS) $(obj)/image.o $(LIBS)
 	$(OBJCOPY) $(OBJCOPY_ARGS) $@ $@ -R .comment -R .stab \
-		-R .stabstr -R .sysmap
+		-R .stabstr
 
 # Sort-of dummy rules, that let us format the image we want.
 zImage: $(images)/$(zimage-y) $(obj)/zvmlinux
diff --git a/arch/ppc/boot/simple/misc.c b/arch/ppc/boot/simple/misc.c
index ab0f990..e02de5b 100644
--- a/arch/ppc/boot/simple/misc.c
+++ b/arch/ppc/boot/simple/misc.c
@@ -222,7 +222,7 @@
 	puts("\n");
 
 	puts("Uncompressing Linux...");
-	gunzip(0x0, 0x400000, zimage_start, &zimage_size);
+	gunzip(NULL, 0x400000, zimage_start, &zimage_size);
 	puts("done.\n");
 
 	/* get the bi_rec address */
diff --git a/arch/ppc/boot/simple/mpc10x_memory.c b/arch/ppc/boot/simple/mpc10x_memory.c
index 977daed..20d92a3 100644
--- a/arch/ppc/boot/simple/mpc10x_memory.c
+++ b/arch/ppc/boot/simple/mpc10x_memory.c
@@ -33,7 +33,7 @@
 
 #define MPC10X_PCI_OP(rw, size, type, op, mask)			 	\
 static void								\
-mpc10x_##rw##_config_##size(unsigned int *cfg_addr, 			\
+mpc10x_##rw##_config_##size(unsigned int __iomem *cfg_addr, 			\
 		unsigned int *cfg_data, int devfn, int offset,		\
 		type val)						\
 {									\
diff --git a/arch/ppc/boot/utils/addSystemMap.c b/arch/ppc/boot/utils/addSystemMap.c
deleted file mode 100644
index 4654f89..0000000
--- a/arch/ppc/boot/utils/addSystemMap.c
+++ /dev/null
@@ -1,186 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <byteswap.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-void xlate( char * inb, char * trb, unsigned len )
-{
-    unsigned i;
-    for (  i=0; i<len; ++i ) {
-	char c = *inb++;
-	char c1 = c >> 4;
-	char c2 = c & 0xf;
-	if ( c1 > 9 )
-	    c1 = c1 + 'A' - 10;
-	else
-	    c1 = c1 + '0';
-	if ( c2 > 9 )
-	    c2 = c2 + 'A' - 10;
-	else
-	    c2 = c2 + '0';
-	*trb++ = c1;
-	*trb++ = c2;
-    }
-    *trb = 0;
-}
-
-#define ElfHeaderSize  (64 * 1024)
-#define ElfPages  (ElfHeaderSize / 4096)
-#define KERNELBASE (0xc0000000)
-
-void get4k( /*istream *inf*/FILE *file, char *buf )
-{
-    unsigned j;
-    unsigned num = fread(buf, 1, 4096, file);
-    for (  j=num; j<4096; ++j )
-	buf[j] = 0;
-}
-
-void put4k( /*ostream *outf*/FILE *file, char *buf )
-{
-    fwrite(buf, 1, 4096, file);
-}
-
-int main(int argc, char **argv)
-{
-    char inbuf[4096];
-    FILE *ramDisk = NULL;
-    FILE *inputVmlinux = NULL;
-    FILE *outputVmlinux = NULL;
-    unsigned i = 0;
-    unsigned long ramFileLen = 0;
-    unsigned long ramLen = 0;
-    unsigned long roundR = 0;
-    unsigned long kernelLen = 0;
-    unsigned long actualKernelLen = 0;
-    unsigned long round = 0;
-    unsigned long roundedKernelLen = 0;
-    unsigned long ramStartOffs = 0;
-    unsigned long ramPages = 0;
-    unsigned long roundedKernelPages = 0;
-    if ( argc < 2 ) {
-	printf("Name of System Map file missing.\n");
-	exit(1);
-    }
-
-    if ( argc < 3 ) {
-	printf("Name of vmlinux file missing.\n");
-	exit(1);
-    }
-
-    if ( argc < 4 ) {
-	printf("Name of vmlinux output file missing.\n");
-	exit(1);
-    }
-
-    ramDisk = fopen(argv[1], "r");
-    if ( ! ramDisk ) {
-	printf("System Map file \"%s\" failed to open.\n", argv[1]);
-	exit(1);
-    }
-    inputVmlinux = fopen(argv[2], "r");
-    if ( ! inputVmlinux ) {
-	printf("vmlinux file \"%s\" failed to open.\n", argv[2]);
-	exit(1);
-    }
-    outputVmlinux = fopen(argv[3], "w");
-    if ( ! outputVmlinux ) {
-	printf("output vmlinux file \"%s\" failed to open.\n", argv[3]);
-	exit(1);
-    }
-    fseek(ramDisk, 0, SEEK_END);
-    ramFileLen = ftell(ramDisk);
-    fseek(ramDisk, 0, SEEK_SET);
-    printf("%s file size = %ld\n", argv[1], ramFileLen);
-
-    ramLen = ramFileLen;
-
-    roundR = 4096 - (ramLen % 4096);
-    if ( roundR ) {
-	printf("Rounding System Map file up to a multiple of 4096, adding %ld\n", roundR);
-	ramLen += roundR;
-    }
-
-    printf("Rounded System Map size is %ld\n", ramLen);
-    fseek(inputVmlinux, 0, SEEK_END);
-    kernelLen = ftell(inputVmlinux);
-    fseek(inputVmlinux, 0, SEEK_SET);
-    printf("kernel file size = %ld\n", kernelLen);
-    if ( kernelLen == 0 ) {
-	printf("You must have a linux kernel specified as argv[2]\n");
-	exit(1);
-    }
-
-    actualKernelLen = kernelLen - ElfHeaderSize;
-
-    printf("actual kernel length (minus ELF header) = %ld\n", actualKernelLen);
-
-    round = actualKernelLen % 4096;
-    roundedKernelLen = actualKernelLen;
-    if ( round )
-	roundedKernelLen += (4096 - round);
-
-    printf("actual kernel length rounded up to a 4k multiple = %ld\n", roundedKernelLen);
-
-    ramStartOffs = roundedKernelLen;
-    ramPages = ramLen / 4096;
-
-    printf("System map pages to copy = %ld\n", ramPages);
-
-    // Copy 64K ELF header
-      for (i=0; i<(ElfPages); ++i) {
-	  get4k( inputVmlinux, inbuf );
-	  put4k( outputVmlinux, inbuf );
-      }
-
-
-
-    roundedKernelPages = roundedKernelLen / 4096;
-
-    fseek(inputVmlinux, ElfHeaderSize, SEEK_SET);
-
-    {
-	for ( i=0; i<roundedKernelPages; ++i ) {
-	    get4k( inputVmlinux, inbuf );
-	    if ( i == 0 ) {
-		unsigned long * p;
-		printf("Storing embedded_sysmap_start at 0x3c\n");
-		p = (unsigned long *)(inbuf + 0x3c);
-
-#if (BYTE_ORDER == __BIG_ENDIAN)
-		*p = ramStartOffs;
-#else
-		*p = bswap_32(ramStartOffs);
-#endif
-
-		printf("Storing embedded_sysmap_end at 0x44\n");
-		p = (unsigned long *)(inbuf + 0x44);
-#if (BYTE_ORDER == __BIG_ENDIAN)
-		*p = ramStartOffs + ramFileLen;
-#else
-		*p = bswap_32(ramStartOffs + ramFileLen);
-#endif
-	    }
-	    put4k( outputVmlinux, inbuf );
-	}
-    }
-
-    {
-	for ( i=0; i<ramPages; ++i ) {
-	    get4k( ramDisk, inbuf );
-	    put4k( outputVmlinux, inbuf );
-	}
-    }
-
-
-    fclose(ramDisk);
-    fclose(inputVmlinux);
-    fclose(outputVmlinux);
-    /* Set permission to executable */
-    chmod(argv[3], S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
-
-    return 0;
-
-}
-
diff --git a/arch/ppc/configs/mpc8548_cds_defconfig b/arch/ppc/configs/mpc8548_cds_defconfig
new file mode 100644
index 0000000..abe034f
--- /dev/null
+++ b/arch/ppc/configs/mpc8548_cds_defconfig
@@ -0,0 +1,659 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.12-rc4
+# Tue May 24 22:36:27 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=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=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 is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE 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_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Processor
+#
+# CONFIG_6xx is not set
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+CONFIG_E500=y
+CONFIG_BOOKE=y
+CONFIG_FSL_BOOKE=y
+# CONFIG_PHYS_64BIT is not set
+CONFIG_SPE=y
+CONFIG_MATH_EMULATION=y
+# CONFIG_CPU_FREQ is not set
+# CONFIG_PM is not set
+CONFIG_85xx=y
+CONFIG_PPC_INDIRECT_PCI_BE=y
+
+#
+# Freescale 85xx options
+#
+# CONFIG_MPC8540_ADS is not set
+CONFIG_MPC8548_CDS=y
+# CONFIG_MPC8555_CDS is not set
+# CONFIG_MPC8560_ADS is not set
+# CONFIG_SBC8560 is not set
+# CONFIG_STX_GP3 is not set
+CONFIG_MPC8548=y
+
+#
+# Platform options
+#
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_ISA_DMA_API=y
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD 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
+
+#
+# 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 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_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_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# 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
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE 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
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# 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_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_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
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_GIANFAR=y
+CONFIG_GFAR_NAPI=y
+
+#
+# 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
+
+#
+# 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
+CONFIG_SOUND_GAMEPORT=y
+
+#
+# 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=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# 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
+
+#
+# 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
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# TPM devices
+#
+
+#
+# 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_ISA is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR 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_ASB100 is not set
+# CONFIG_SENSORS_DS1621 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_SMSC47B397 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_SENSORS_M41T00 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
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 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 is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# 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
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR 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 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_PROC_KCORE=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
+
+#
+# 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_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
+
+#
+# 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_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C 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
+
+#
+# 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/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile
index b284451..b1457a8 100644
--- a/arch/ppc/kernel/Makefile
+++ b/arch/ppc/kernel/Makefile
@@ -26,7 +26,10 @@
 obj-$(CONFIG_SMP)		+= smp.o smp-tbsync.o
 obj-$(CONFIG_TAU)		+= temp.o
 obj-$(CONFIG_ALTIVEC)		+= vecemu.o vector.o
+ifndef CONFIG_E200
 obj-$(CONFIG_FSL_BOOKE)		+= perfmon_fsl_booke.o
+endif
+obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
 
 ifndef CONFIG_MATH_EMULATION
 obj-$(CONFIG_8xx)		+= softemu8xx.o
diff --git a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c
index 8aa5e8c..50936cd 100644
--- a/arch/ppc/kernel/cputable.c
+++ b/arch/ppc/kernel/cputable.c
@@ -838,6 +838,17 @@
 		.icache_bsize		= 32,
 		.dcache_bsize		= 32,
 	},
+	{	/* 405EP */
+		.pvr_mask		= 0xffff0000,
+		.pvr_value		= 0x51210000,
+		.cpu_name		= "405EP",
+		.cpu_features		= CPU_FTR_SPLIT_ID_CACHE |
+			CPU_FTR_USE_TB,
+		.cpu_user_features	= PPC_FEATURE_32 |
+			PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+		.icache_bsize		= 32,
+		.dcache_bsize		= 32,
+	},
 
 #endif /* CONFIG_40x */
 #ifdef CONFIG_44x
@@ -892,7 +903,30 @@
 		.dcache_bsize		= 32,
 	},
 #endif /* CONFIG_44x */
-#ifdef CONFIG_E500
+#ifdef CONFIG_FSL_BOOKE
+	{ 	/* e200z5 */
+		.pvr_mask		= 0xfff00000,
+		.pvr_value		= 0x81000000,
+		.cpu_name		= "e200z5",
+		/* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
+		.cpu_features		= CPU_FTR_USE_TB,
+		.cpu_user_features	= PPC_FEATURE_32 |
+			PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_EFP_SINGLE |
+			PPC_FEATURE_UNIFIED_CACHE,
+		.dcache_bsize		= 32,
+	},
+	{ 	/* e200z6 */
+		.pvr_mask		= 0xfff00000,
+		.pvr_value		= 0x81100000,
+		.cpu_name		= "e200z6",
+		/* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
+		.cpu_features		= CPU_FTR_USE_TB,
+		.cpu_user_features	= PPC_FEATURE_32 |
+			PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP |
+			PPC_FEATURE_HAS_EFP_SINGLE |
+			PPC_FEATURE_UNIFIED_CACHE,
+		.dcache_bsize		= 32,
+	},
 	{ 	/* e500 */
 		.pvr_mask		= 0xffff0000,
 		.pvr_value		= 0x80200000,
@@ -907,6 +941,20 @@
 		.dcache_bsize		= 32,
 		.num_pmcs		= 4,
 	},
+	{ 	/* e500v2 */
+		.pvr_mask		= 0xffff0000,
+		.pvr_value		= 0x80210000,
+		.cpu_name		= "e500v2",
+		/* xxx - galak: add CPU_FTR_MAYBE_CAN_DOZE */
+		.cpu_features		= CPU_FTR_SPLIT_ID_CACHE |
+			CPU_FTR_USE_TB | CPU_FTR_BIG_PHYS,
+		.cpu_user_features	= PPC_FEATURE_32 |
+			PPC_FEATURE_HAS_MMU | PPC_FEATURE_SPE_COMP |
+			PPC_FEATURE_HAS_EFP_SINGLE | PPC_FEATURE_HAS_EFP_DOUBLE,
+		.icache_bsize		= 32,
+		.dcache_bsize		= 32,
+		.num_pmcs		= 4,
+	},
 #endif
 #if !CLASSIC_PPC
 	{	/* default match */
diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S
index 5f075db..d4df686 100644
--- a/arch/ppc/kernel/entry.S
+++ b/arch/ppc/kernel/entry.S
@@ -46,26 +46,28 @@
 
 #ifdef CONFIG_BOOKE
 #include "head_booke.h"
+#define TRANSFER_TO_HANDLER_EXC_LEVEL(exc_level)	\
+	mtspr	exc_level##_SPRG,r8;			\
+	BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);		\
+	lwz	r0,GPR10-INT_FRAME_SIZE(r8);		\
+	stw	r0,GPR10(r11);				\
+	lwz	r0,GPR11-INT_FRAME_SIZE(r8);		\
+	stw	r0,GPR11(r11);				\
+	mfspr	r8,exc_level##_SPRG
+
 	.globl	mcheck_transfer_to_handler
 mcheck_transfer_to_handler:
-	mtspr	MCHECK_SPRG,r8
-	BOOKE_LOAD_MCHECK_STACK
-	lwz	r0,GPR10-INT_FRAME_SIZE(r8)
-	stw	r0,GPR10(r11)
-	lwz	r0,GPR11-INT_FRAME_SIZE(r8)
-	stw	r0,GPR11(r11)
-	mfspr	r8,MCHECK_SPRG
+	TRANSFER_TO_HANDLER_EXC_LEVEL(MCHECK)
+	b	transfer_to_handler_full
+
+	.globl	debug_transfer_to_handler
+debug_transfer_to_handler:
+	TRANSFER_TO_HANDLER_EXC_LEVEL(DEBUG)
 	b	transfer_to_handler_full
 
 	.globl	crit_transfer_to_handler
 crit_transfer_to_handler:
-	mtspr	CRIT_SPRG,r8
-	BOOKE_LOAD_CRIT_STACK
-	lwz	r0,GPR10-INT_FRAME_SIZE(r8)
-	stw	r0,GPR10(r11)
-	lwz	r0,GPR11-INT_FRAME_SIZE(r8)
-	stw	r0,GPR11(r11)
-	mfspr	r8,CRIT_SPRG
+	TRANSFER_TO_HANDLER_EXC_LEVEL(CRIT)
 	/* fall through */
 #endif
 
@@ -202,7 +204,7 @@
 	rlwinm	r11,r11,0,~_TIFL_FORCE_NOERROR
 	stw	r11,TI_LOCAL_FLAGS(r10)
 	lwz	r11,TI_FLAGS(r10)
-	andi.	r11,r11,_TIF_SYSCALL_TRACE
+	andi.	r11,r11,_TIF_SYSCALL_T_OR_A
 	bne-	syscall_dotrace
 syscall_dotrace_cont:
 	cmplwi	0,r0,NR_syscalls
@@ -237,7 +239,7 @@
 	SYNC
 	MTMSRD(r10)
 	lwz	r9,TI_FLAGS(r12)
-	andi.	r0,r9,(_TIF_SYSCALL_TRACE|_TIF_SIGPENDING|_TIF_NEED_RESCHED)
+	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED)
 	bne-	syscall_exit_work
 syscall_exit_cont:
 #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
@@ -277,7 +279,8 @@
 	SAVE_NVGPRS(r1)
 	li	r0,0xc00
 	stw	r0,TRAP(r1)
-	bl	do_syscall_trace
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	do_syscall_trace_enter
 	lwz	r0,GPR0(r1)	/* Restore original registers */
 	lwz	r3,GPR3(r1)
 	lwz	r4,GPR4(r1)
@@ -291,7 +294,7 @@
 syscall_exit_work:
 	stw	r6,RESULT(r1)	/* Save result */
 	stw	r3,GPR3(r1)	/* Update return value */
-	andi.	r0,r9,_TIF_SYSCALL_TRACE
+	andi.	r0,r9,_TIF_SYSCALL_T_OR_A
 	beq	5f
 	ori	r10,r10,MSR_EE
 	SYNC
@@ -303,7 +306,8 @@
 	li	r4,0xc00
 	stw	r4,TRAP(r1)
 4:
-	bl	do_syscall_trace
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	do_syscall_trace_leave
 	REST_NVGPRS(r1)
 2:
 	lwz	r3,GPR3(r1)
@@ -627,8 +631,8 @@
 	subi	r1,r3,STACK_FRAME_OVERHEAD
 	rlwinm	r12,r1,0,0,18	/* current_thread_info() */
 	lwz	r9,TI_FLAGS(r12)
-	andi.	r0,r9,_TIF_SYSCALL_TRACE
-	bnel-	do_syscall_trace
+	andi.	r0,r9,_TIF_SYSCALL_T_OR_A
+	bnel-	do_syscall_trace_leave
 	/* fall through */
 
 	.globl	ret_from_except_full
@@ -781,99 +785,68 @@
  * time of the critical interrupt.
  *
  */
+#ifdef CONFIG_40x
+#define PPC_40x_TURN_OFF_MSR_DR						    \
+	/* avoid any possible TLB misses here by turning off MSR.DR, we	    \
+	 * assume the instructions here are mapped by a pinned TLB entry */ \
+	li	r10,MSR_IR;						    \
+	mtmsr	r10;							    \
+	isync;								    \
+	tophys(r1, r1);
+#else
+#define PPC_40x_TURN_OFF_MSR_DR
+#endif
+
+#define RET_FROM_EXC_LEVEL(exc_lvl_srr0, exc_lvl_srr1, exc_lvl_rfi)	\
+	REST_NVGPRS(r1);						\
+	lwz	r3,_MSR(r1);						\
+	andi.	r3,r3,MSR_PR;						\
+	LOAD_MSR_KERNEL(r10,MSR_KERNEL);				\
+	bne	user_exc_return;					\
+	lwz	r0,GPR0(r1);						\
+	lwz	r2,GPR2(r1);						\
+	REST_4GPRS(3, r1);						\
+	REST_2GPRS(7, r1);						\
+	lwz	r10,_XER(r1);						\
+	lwz	r11,_CTR(r1);						\
+	mtspr	SPRN_XER,r10;						\
+	mtctr	r11;							\
+	PPC405_ERR77(0,r1);						\
+	stwcx.	r0,0,r1;		/* to clear the reservation */	\
+	lwz	r11,_LINK(r1);						\
+	mtlr	r11;							\
+	lwz	r10,_CCR(r1);						\
+	mtcrf	0xff,r10;						\
+	PPC_40x_TURN_OFF_MSR_DR;					\
+	lwz	r9,_DEAR(r1);						\
+	lwz	r10,_ESR(r1);						\
+	mtspr	SPRN_DEAR,r9;						\
+	mtspr	SPRN_ESR,r10;						\
+	lwz	r11,_NIP(r1);						\
+	lwz	r12,_MSR(r1);						\
+	mtspr	exc_lvl_srr0,r11;					\
+	mtspr	exc_lvl_srr1,r12;					\
+	lwz	r9,GPR9(r1);						\
+	lwz	r12,GPR12(r1);						\
+	lwz	r10,GPR10(r1);						\
+	lwz	r11,GPR11(r1);						\
+	lwz	r1,GPR1(r1);						\
+	PPC405_ERR77_SYNC;						\
+	exc_lvl_rfi;							\
+	b	.;		/* prevent prefetch past exc_lvl_rfi */
+
 	.globl	ret_from_crit_exc
 ret_from_crit_exc:
-	REST_NVGPRS(r1)
-	lwz	r3,_MSR(r1)
-	andi.	r3,r3,MSR_PR
-	LOAD_MSR_KERNEL(r10,MSR_KERNEL)
-	bne	user_exc_return
-
-	lwz	r0,GPR0(r1)
-	lwz	r2,GPR2(r1)
-	REST_4GPRS(3, r1)
-	REST_2GPRS(7, r1)
-
-	lwz	r10,_XER(r1)
-	lwz	r11,_CTR(r1)
-	mtspr	SPRN_XER,r10
-	mtctr	r11
-
-	PPC405_ERR77(0,r1)
-	stwcx.	r0,0,r1			/* to clear the reservation */
-
-	lwz	r11,_LINK(r1)
-	mtlr	r11
-	lwz	r10,_CCR(r1)
-	mtcrf	0xff,r10
-#ifdef CONFIG_40x
-	/* avoid any possible TLB misses here by turning off MSR.DR, we
-	 * assume the instructions here are mapped by a pinned TLB entry */
-	li	r10,MSR_IR
-	mtmsr	r10
-	isync
-	tophys(r1, r1)
-#endif
-	lwz	r9,_DEAR(r1)
-	lwz	r10,_ESR(r1)
-	mtspr	SPRN_DEAR,r9
-	mtspr	SPRN_ESR,r10
-	lwz	r11,_NIP(r1)
-	lwz	r12,_MSR(r1)
-	mtspr	SPRN_CSRR0,r11
-	mtspr	SPRN_CSRR1,r12
-	lwz	r9,GPR9(r1)
-	lwz	r12,GPR12(r1)
-	lwz	r10,GPR10(r1)
-	lwz	r11,GPR11(r1)
-	lwz	r1,GPR1(r1)
-	PPC405_ERR77_SYNC
-	rfci
-	b	.		/* prevent prefetch past rfci */
+	RET_FROM_EXC_LEVEL(SPRN_CSRR0, SPRN_CSRR1, RFCI)
 
 #ifdef CONFIG_BOOKE
-/*
- * Return from a machine check interrupt, similar to a critical
- * interrupt.
- */
+	.globl	ret_from_debug_exc
+ret_from_debug_exc:
+	RET_FROM_EXC_LEVEL(SPRN_DSRR0, SPRN_DSRR1, RFDI)
+
 	.globl	ret_from_mcheck_exc
 ret_from_mcheck_exc:
-	REST_NVGPRS(r1)
-	lwz	r3,_MSR(r1)
-	andi.	r3,r3,MSR_PR
-	LOAD_MSR_KERNEL(r10,MSR_KERNEL)
-	bne	user_exc_return
-
-	lwz	r0,GPR0(r1)
-	lwz	r2,GPR2(r1)
-	REST_4GPRS(3, r1)
-	REST_2GPRS(7, r1)
-
-	lwz	r10,_XER(r1)
-	lwz	r11,_CTR(r1)
-	mtspr	SPRN_XER,r10
-	mtctr	r11
-
-	stwcx.	r0,0,r1			/* to clear the reservation */
-
-	lwz	r11,_LINK(r1)
-	mtlr	r11
-	lwz	r10,_CCR(r1)
-	mtcrf	0xff,r10
-	lwz	r9,_DEAR(r1)
-	lwz	r10,_ESR(r1)
-	mtspr	SPRN_DEAR,r9
-	mtspr	SPRN_ESR,r10
-	lwz	r11,_NIP(r1)
-	lwz	r12,_MSR(r1)
-	mtspr	SPRN_MCSRR0,r11
-	mtspr	SPRN_MCSRR1,r12
-	lwz	r9,GPR9(r1)
-	lwz	r12,GPR12(r1)
-	lwz	r10,GPR10(r1)
-	lwz	r11,GPR11(r1)
-	lwz	r1,GPR1(r1)
-	RFMCI
+	RET_FROM_EXC_LEVEL(SPRN_MCSRR0, SPRN_MCSRR1, RFMCI)
 #endif /* CONFIG_BOOKE */
 
 /*
diff --git a/arch/ppc/kernel/head_4xx.S b/arch/ppc/kernel/head_4xx.S
index 6f5d380..23fb518 100644
--- a/arch/ppc/kernel/head_4xx.S
+++ b/arch/ppc/kernel/head_4xx.S
@@ -291,8 +291,9 @@
 	/* If we are faulting a kernel address, we have to use the
 	 * kernel page tables.
 	 */
-	andis.	r11, r10, 0x8000
-	beq	3f
+	lis	r11, TASK_SIZE@h
+	cmplw	r10, r11
+	blt+	3f
 	lis	r11, swapper_pg_dir@h
 	ori	r11, r11, swapper_pg_dir@l
 	li	r9, 0
@@ -479,8 +480,9 @@
 	/* If we are faulting a kernel address, we have to use the
 	 * kernel page tables.
 	 */
-	andis.	r11, r10, 0x8000
-	beq	3f
+	lis	r11, TASK_SIZE@h
+	cmplw	r10, r11
+	blt+	3f
 	lis	r11, swapper_pg_dir@h
 	ori	r11, r11, swapper_pg_dir@l
 	li	r9, 0
@@ -578,8 +580,9 @@
 	/* If we are faulting a kernel address, we have to use the
 	 * kernel page tables.
 	 */
-	andis.	r11, r10, 0x8000
-	beq	3f
+	lis	r11, TASK_SIZE@h
+	cmplw	r10, r11
+	blt+	3f
 	lis	r11, swapper_pg_dir@h
 	ori	r11, r11, swapper_pg_dir@l
 	li	r9, 0
diff --git a/arch/ppc/kernel/head_booke.h b/arch/ppc/kernel/head_booke.h
index f213d12..9342acf 100644
--- a/arch/ppc/kernel/head_booke.h
+++ b/arch/ppc/kernel/head_booke.h
@@ -49,6 +49,7 @@
  *
  * On 40x critical is the only additional level
  * On 44x/e500 we have critical and machine check
+ * On e200 we have critical and debug (machine check occurs via critical)
  *
  * Additionally we reserve a SPRG for each priority level so we can free up a
  * GPR to use as the base for indirect access to the exception stacks.  This
@@ -60,53 +61,47 @@
 
 /* CRIT_SPRG only used in critical exception handling */
 #define CRIT_SPRG	SPRN_SPRG2
-/* MCHECK_SPRG only used in critical exception handling */
+/* MCHECK_SPRG only used in machine check exception handling */
 #define MCHECK_SPRG	SPRN_SPRG6W
 
 #define MCHECK_STACK_TOP	(exception_stack_top - 4096)
 #define CRIT_STACK_TOP		(exception_stack_top)
 
+/* only on e200 for now */
+#define DEBUG_STACK_TOP		(exception_stack_top - 4096)
+#define DEBUG_SPRG		SPRN_SPRG6W
+
 #ifdef CONFIG_SMP
-#define BOOKE_LOAD_CRIT_STACK				\
+#define BOOKE_LOAD_EXC_LEVEL_STACK(level)		\
 	mfspr	r8,SPRN_PIR;				\
 	mulli	r8,r8,BOOKE_EXCEPTION_STACK_SIZE;	\
 	neg	r8,r8;					\
-	addis	r8,r8,CRIT_STACK_TOP@ha;		\
-	addi	r8,r8,CRIT_STACK_TOP@l
-#define BOOKE_LOAD_MCHECK_STACK				\
-	mfspr	r8,SPRN_PIR;				\
-	mulli	r8,r8,BOOKE_EXCEPTION_STACK_SIZE;	\
-	neg	r8,r8;					\
-	addis	r8,r8,MCHECK_STACK_TOP@ha;		\
-	addi	r8,r8,MCHECK_STACK_TOP@l
+	addis	r8,r8,level##_STACK_TOP@ha;		\
+	addi	r8,r8,level##_STACK_TOP@l
 #else
-#define BOOKE_LOAD_CRIT_STACK				\
-	lis	r8,CRIT_STACK_TOP@h;			\
-	ori	r8,r8,CRIT_STACK_TOP@l
-#define BOOKE_LOAD_MCHECK_STACK				\
-	lis	r8,MCHECK_STACK_TOP@h;			\
-	ori	r8,r8,MCHECK_STACK_TOP@l
+#define BOOKE_LOAD_EXC_LEVEL_STACK(level)		\
+	lis	r8,level##_STACK_TOP@h;			\
+	ori	r8,r8,level##_STACK_TOP@l
 #endif
 
 /*
- * Exception prolog for critical exceptions.  This is a little different
- * from the normal exception prolog above since a critical exception
- * can potentially occur at any point during normal exception processing.
- * Thus we cannot use the same SPRG registers as the normal prolog above.
- * Instead we use a portion of the critical exception stack at low physical
- * addresses.
+ * Exception prolog for critical/machine check exceptions.  This is a
+ * little different from the normal exception prolog above since a
+ * critical/machine check exception can potentially occur at any point
+ * during normal exception processing. Thus we cannot use the same SPRG
+ * registers as the normal prolog above. Instead we use a portion of the
+ * critical/machine check exception stack at low physical addresses.
  */
-
-#define CRITICAL_EXCEPTION_PROLOG					     \
-	mtspr	CRIT_SPRG,r8;						     \
-	BOOKE_LOAD_CRIT_STACK;		/* r8 points to the crit stack */    \
+#define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, exc_level_srr0, exc_level_srr1) \
+	mtspr	exc_level##_SPRG,r8;					     \
+	BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);/* r8 points to the exc_level stack*/ \
 	stw	r10,GPR10-INT_FRAME_SIZE(r8);				     \
 	stw	r11,GPR11-INT_FRAME_SIZE(r8);				     \
 	mfcr	r10;			/* save CR in r10 for now	   */\
-	mfspr	r11,SPRN_CSRR1;		/* check whether user or kernel    */\
+	mfspr	r11,exc_level_srr1;	/* check whether user or kernel    */\
 	andi.	r11,r11,MSR_PR;						     \
 	mr	r11,r8;							     \
-	mfspr	r8,CRIT_SPRG;						     \
+	mfspr	r8,exc_level##_SPRG;					     \
 	beq	1f;							     \
 	/* COMING FROM USER MODE */					     \
 	mfspr	r11,SPRN_SPRG3;		/* if from user, start at top of   */\
@@ -122,9 +117,9 @@
 	stw	r12,_DEAR(r11);		/* since they may have had stuff   */\
 	mfspr	r9,SPRN_ESR;		/* in them at the point where the  */\
 	stw	r9,_ESR(r11);		/* exception was taken		   */\
-	mfspr	r12,SPRN_CSRR0;						     \
+	mfspr	r12,exc_level_srr0;					     \
 	stw	r1,GPR1(r11);						     \
-	mfspr	r9,SPRN_CSRR1;						     \
+	mfspr	r9,exc_level_srr1;					     \
 	stw	r1,0(r11);						     \
 	mr	r1,r11;							     \
 	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
@@ -132,45 +127,12 @@
 	SAVE_4GPRS(3, r11);						     \
 	SAVE_2GPRS(7, r11)
 
-/*
- * Exception prolog for machine check exceptions.  This is similar to
- * the critical exception prolog, except that machine check exceptions
- * have their stack.
- */
-#define MCHECK_EXCEPTION_PROLOG					     \
-	mtspr	MCHECK_SPRG,r8;						     \
-	BOOKE_LOAD_MCHECK_STACK;	/* r8 points to the mcheck stack   */\
-	stw	r10,GPR10-INT_FRAME_SIZE(r8);				     \
-	stw	r11,GPR11-INT_FRAME_SIZE(r8);				     \
-	mfcr	r10;			/* save CR in r10 for now	   */\
-	mfspr	r11,SPRN_MCSRR1;	/* check whether user or kernel    */\
-	andi.	r11,r11,MSR_PR;						     \
-	mr	r11,r8;							     \
-	mfspr	r8,MCHECK_SPRG;						     \
-	beq	1f;							     \
-	/* COMING FROM USER MODE */					     \
-	mfspr	r11,SPRN_SPRG3;		/* if from user, start at top of   */\
-	lwz	r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\
-	addi	r11,r11,THREAD_SIZE;					     \
-1:	subi	r11,r11,INT_FRAME_SIZE;	/* Allocate an exception frame     */\
-	stw	r10,_CCR(r11);          /* save various registers	   */\
-	stw	r12,GPR12(r11);						     \
-	stw	r9,GPR9(r11);						     \
-	mflr	r10;							     \
-	stw	r10,_LINK(r11);						     \
-	mfspr	r12,SPRN_DEAR;		/* save DEAR and ESR in the frame  */\
-	stw	r12,_DEAR(r11);		/* since they may have had stuff   */\
-	mfspr	r9,SPRN_ESR;		/* in them at the point where the  */\
-	stw	r9,_ESR(r11);		/* exception was taken		   */\
-	mfspr	r12,SPRN_MCSRR0;					     \
-	stw	r1,GPR1(r11);						     \
-	mfspr	r9,SPRN_MCSRR1;						     \
-	stw	r1,0(r11);						     \
-	mr	r1,r11;							     \
-	rlwinm	r9,r9,0,14,12;		/* clear MSR_WE (necessary?)	   */\
-	stw	r0,GPR0(r11);						     \
-	SAVE_4GPRS(3, r11);						     \
-	SAVE_2GPRS(7, r11)
+#define CRITICAL_EXCEPTION_PROLOG \
+		EXC_LEVEL_EXCEPTION_PROLOG(CRIT, SPRN_CSRR0, SPRN_CSRR1)
+#define DEBUG_EXCEPTION_PROLOG \
+		EXC_LEVEL_EXCEPTION_PROLOG(DEBUG, SPRN_DSRR0, SPRN_DSRR1)
+#define MCHECK_EXCEPTION_PROLOG \
+		EXC_LEVEL_EXCEPTION_PROLOG(MCHECK, SPRN_MCSRR0, SPRN_MCSRR1)
 
 /*
  * Exception vectors.
@@ -237,7 +199,6 @@
 	EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \
 			  ret_from_except)
 
-
 /* Check for a single step debug exception while in an exception
  * handler before state has been saved.  This is to catch the case
  * where an instruction that we are trying to single step causes
@@ -251,6 +212,60 @@
  * save (and later restore) the MSR via SPRN_CSRR1, which will still have
  * the MSR_DE bit set.
  */
+#ifdef CONFIG_E200
+#define DEBUG_EXCEPTION							      \
+	START_EXCEPTION(Debug);						      \
+	DEBUG_EXCEPTION_PROLOG;						      \
+									      \
+	/*								      \
+	 * If there is a single step or branch-taken exception in an	      \
+	 * exception entry sequence, it was probably meant to apply to	      \
+	 * the code where the exception occurred (since exception entry	      \
+	 * doesn't turn off DE automatically).  We simulate the effect	      \
+	 * of turning off DE on entry to an exception handler by turning      \
+	 * off DE in the CSRR1 value and clearing the debug status.	      \
+	 */								      \
+	mfspr	r10,SPRN_DBSR;		/* check single-step/branch taken */  \
+	andis.	r10,r10,DBSR_IC@h;					      \
+	beq+	2f;							      \
+									      \
+	lis	r10,KERNELBASE@h;	/* check if exception in vectors */   \
+	ori	r10,r10,KERNELBASE@l;					      \
+	cmplw	r12,r10;						      \
+	blt+	2f;			/* addr below exception vectors */    \
+									      \
+	lis	r10,Debug@h;						      \
+	ori	r10,r10,Debug@l;					      \
+	cmplw	r12,r10;						      \
+	bgt+	2f;			/* addr above exception vectors */    \
+									      \
+	/* here it looks like we got an inappropriate debug exception. */     \
+1:	rlwinm	r9,r9,0,~MSR_DE;	/* clear DE in the CDRR1 value */     \
+	lis	r10,DBSR_IC@h;		/* clear the IC event */	      \
+	mtspr	SPRN_DBSR,r10;						      \
+	/* restore state and get out */					      \
+	lwz	r10,_CCR(r11);						      \
+	lwz	r0,GPR0(r11);						      \
+	lwz	r1,GPR1(r11);						      \
+	mtcrf	0x80,r10;						      \
+	mtspr	SPRN_DSRR0,r12;						      \
+	mtspr	SPRN_DSRR1,r9;						      \
+	lwz	r9,GPR9(r11);						      \
+	lwz	r12,GPR12(r11);						      \
+	mtspr	DEBUG_SPRG,r8;						      \
+	BOOKE_LOAD_EXC_LEVEL_STACK(DEBUG); /* r8 points to the debug stack */ \
+	lwz	r10,GPR10-INT_FRAME_SIZE(r8);				      \
+	lwz	r11,GPR11-INT_FRAME_SIZE(r8);				      \
+	mfspr	r8,DEBUG_SPRG;						      \
+									      \
+	RFDI;								      \
+	b	.;							      \
+									      \
+	/* continue normal handling for a critical exception... */	      \
+2:	mfspr	r4,SPRN_DBSR;						      \
+	addi	r3,r1,STACK_FRAME_OVERHEAD;				      \
+	EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, debug_transfer_to_handler, ret_from_debug_exc)
+#else
 #define DEBUG_EXCEPTION							      \
 	START_EXCEPTION(Debug);						      \
 	CRITICAL_EXCEPTION_PROLOG;					      \
@@ -291,7 +306,7 @@
 	lwz	r9,GPR9(r11);						      \
 	lwz	r12,GPR12(r11);						      \
 	mtspr	CRIT_SPRG,r8;						      \
-	BOOKE_LOAD_CRIT_STACK;		/* r8 points to the crit stack */     \
+	BOOKE_LOAD_EXC_LEVEL_STACK(CRIT); /* r8 points to the debug stack */  \
 	lwz	r10,GPR10-INT_FRAME_SIZE(r8);				      \
 	lwz	r11,GPR11-INT_FRAME_SIZE(r8);				      \
 	mfspr	r8,CRIT_SPRG;						      \
@@ -303,6 +318,7 @@
 2:	mfspr	r4,SPRN_DBSR;						      \
 	addi	r3,r1,STACK_FRAME_OVERHEAD;				      \
 	EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, crit_transfer_to_handler, ret_from_crit_exc)
+#endif
 
 #define INSTRUCTION_STORAGE_EXCEPTION					      \
 	START_EXCEPTION(InstructionStorage)				      \
diff --git a/arch/ppc/kernel/head_fsl_booke.S b/arch/ppc/kernel/head_fsl_booke.S
index ce36e88..eb804b7 100644
--- a/arch/ppc/kernel/head_fsl_booke.S
+++ b/arch/ppc/kernel/head_fsl_booke.S
@@ -102,6 +102,7 @@
 	or	r7,r7,r4
 	mtspr	SPRN_MAS6,r7
 	tlbsx	0,r6				/* search MSR[IS], SPID=PID0 */
+#ifndef CONFIG_E200
 	mfspr	r7,SPRN_MAS1
 	andis.	r7,r7,MAS1_VALID@h
 	bne	match_TLB
@@ -118,6 +119,7 @@
 	or	r7,r7,r4
 	mtspr	SPRN_MAS6,r7
 	tlbsx	0,r6				/* Fall through, we had to match */
+#endif
 match_TLB:
 	mfspr	r7,SPRN_MAS0
 	rlwinm	r3,r7,16,20,31			/* Extract MAS0(Entry) */
@@ -196,8 +198,10 @@
 /* 4. Clear out PIDs & Search info */
 	li	r6,0
 	mtspr	SPRN_PID0,r6
+#ifndef CONFIG_E200
 	mtspr	SPRN_PID1,r6
 	mtspr	SPRN_PID2,r6
+#endif
 	mtspr	SPRN_MAS6,r6
 
 /* 5. Invalidate mapping we started in */
@@ -277,7 +281,9 @@
 	SET_IVOR(32, SPEUnavailable);
 	SET_IVOR(33, SPEFloatingPointData);
 	SET_IVOR(34, SPEFloatingPointRound);
+#ifndef CONFIG_E200
 	SET_IVOR(35, PerformanceMonitor);
+#endif
 
 	/* Establish the interrupt vector base */
 	lis	r4,interrupt_base@h	/* IVPR only uses the high 16-bits */
@@ -285,6 +291,9 @@
 
 	/* Setup the defaults for TLB entries */
 	li	r2,(MAS4_TSIZED(BOOKE_PAGESZ_4K))@l
+#ifdef CONFIG_E200
+	oris	r2,r2,MAS4_TLBSELD(1)@h
+#endif
    	mtspr	SPRN_MAS4, r2
 
 #if 0
@@ -293,6 +302,12 @@
 	oris	r2,r2,HID0_DOZE@h
 	mtspr	SPRN_HID0, r2
 #endif
+#ifdef CONFIG_E200
+	/* enable dedicated debug exception handling resources (Debug APU) */
+	mfspr	r2,SPRN_HID0
+	ori 	r2,r2,HID0_DAPUEN@l
+	mtspr	SPRN_HID0,r2
+#endif
 
 #if !defined(CONFIG_BDI_SWITCH)
 	/*
@@ -414,7 +429,12 @@
 	CRITICAL_EXCEPTION(0x0100, CriticalInput, UnknownException)
 
 	/* Machine Check Interrupt */
+#ifdef CONFIG_E200
+	/* no RFMCI, MCSRRs on E200 */
+	CRITICAL_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
+#else
 	MCHECK_EXCEPTION(0x0200, MachineCheck, MachineCheckException)
+#endif
 
 	/* Data Storage Interrupt */
 	START_EXCEPTION(DataStorage)
@@ -520,8 +540,13 @@
 #ifdef CONFIG_PPC_FPU
 	FP_UNAVAILABLE_EXCEPTION
 #else
+#ifdef CONFIG_E200
+	/* E200 treats 'normal' floating point instructions as FP Unavail exception */
+	EXCEPTION(0x0800, FloatingPointUnavailable, ProgramCheckException, EXC_XFER_EE)
+#else
 	EXCEPTION(0x0800, FloatingPointUnavailable, UnknownException, EXC_XFER_EE)
 #endif
+#endif
 
 	/* System Call Interrupt */
 	START_EXCEPTION(SystemCall)
@@ -691,6 +716,7 @@
 /*
  * Local functions
  */
+
 	/*
 	 * Data TLB exceptions will bail out to this point
 	 * if they can't resolve the lightweight TLB fault.
@@ -761,6 +787,31 @@
 2:	rlwimi	r11, r12, 0, 20, 31	/* Extract RPN from PTE and merge with perms */
 	mtspr	SPRN_MAS3, r11
 #endif
+#ifdef CONFIG_E200
+	/* Round robin TLB1 entries assignment */
+	mfspr	r12, SPRN_MAS0
+
+	/* Extract TLB1CFG(NENTRY) */
+	mfspr	r11, SPRN_TLB1CFG
+	andi.	r11, r11, 0xfff
+
+	/* Extract MAS0(NV) */
+	andi.	r13, r12, 0xfff
+	addi	r13, r13, 1
+	cmpw	0, r13, r11
+	addi	r12, r12, 1
+
+	/* check if we need to wrap */
+	blt	7f
+
+	/* wrap back to first free tlbcam entry */
+	lis	r13, tlbcam_index@ha
+	lwz	r13, tlbcam_index@l(r13)
+	rlwimi	r12, r13, 0, 20, 31
+7:
+	mtspr   SPRN_MAS0,r12
+#endif /* CONFIG_E200 */
+
 	tlbwe
 
 	/* Done...restore registers and get out of here.  */
diff --git a/arch/ppc/kernel/machine_kexec.c b/arch/ppc/kernel/machine_kexec.c
new file mode 100644
index 0000000..84d65a8
--- /dev/null
+++ b/arch/ppc/kernel/machine_kexec.c
@@ -0,0 +1,118 @@
+/*
+ * machine_kexec.c - handle transition of Linux booting another kernel
+ * Copyright (C) 2002-2003 Eric Biederman  <ebiederm@xmission.com>
+ *
+ * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+
+#include <linux/mm.h>
+#include <linux/kexec.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/hw_irq.h>
+#include <asm/cacheflush.h>
+#include <asm/machdep.h>
+
+typedef NORET_TYPE void (*relocate_new_kernel_t)(
+				unsigned long indirection_page,
+				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;
+
+void machine_shutdown(void)
+{
+	if (ppc_md.machine_shutdown)
+		ppc_md.machine_shutdown();
+}
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+	if (ppc_md.machine_crash_shutdown)
+		ppc_md.machine_crash_shutdown();
+}
+
+/*
+ * Do what every setup is needed on image and the
+ * reboot code buffer to allow us to avoid allocations
+ * later.
+ */
+int machine_kexec_prepare(struct kimage *image)
+{
+	if (ppc_md.machine_kexec_prepare)
+		return ppc_md.machine_kexec_prepare(image);
+	/*
+	 * Fail if platform doesn't provide its own machine_kexec_prepare
+	 * implementation.
+	 */
+	return -ENOSYS;
+}
+
+void machine_kexec_cleanup(struct kimage *image)
+{
+	if (ppc_md.machine_kexec_cleanup)
+		ppc_md.machine_kexec_cleanup(image);
+}
+
+/*
+ * Do not allocate memory (or fail in any way) in machine_kexec().
+ * We are past the point of no return, committed to rebooting now.
+ */
+NORET_TYPE void machine_kexec(struct kimage *image)
+{
+	if (ppc_md.machine_kexec)
+		ppc_md.machine_kexec(image);
+	else {
+		/*
+		 * Fall back to normal restart if platform doesn't provide
+		 * its own kexec function, and user insist to kexec...
+		 */
+		machine_restart(NULL);
+	}
+	for(;;);
+}
+
+/*
+ * This is a generic machine_kexec function suitable at least for
+ * non-OpenFirmware embedded platforms.
+ * It merely copies the image relocation code to the control page and
+ * jumps to it.
+ * A platform specific function may just call this one.
+ */
+void machine_kexec_simple(struct kimage *image)
+{
+	unsigned long page_list;
+	unsigned long reboot_code_buffer, reboot_code_buffer_phys;
+	relocate_new_kernel_t rnk;
+
+	/* Interrupts aren't acceptable while we reboot */
+	local_irq_disable();
+
+	page_list = image->head;
+
+	/* we need both effective and real address here */
+	reboot_code_buffer =
+			(unsigned long)page_address(image->control_code_page);
+	reboot_code_buffer_phys = virt_to_phys((void *)reboot_code_buffer);
+
+	/* copy our kernel relocation code to the control code page */
+	memcpy((void *)reboot_code_buffer, relocate_new_kernel,
+						relocate_new_kernel_size);
+
+	flush_icache_range(reboot_code_buffer,
+				reboot_code_buffer + KEXEC_CONTROL_CODE_SIZE);
+	printk(KERN_INFO "Bye!\n");
+
+	/* now call it */
+	rnk = (relocate_new_kernel_t) reboot_code_buffer;
+	(*rnk)(page_list, reboot_code_buffer_phys, image->start);
+}
+
diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
index e4f1615..191a8de 100644
--- a/arch/ppc/kernel/misc.S
+++ b/arch/ppc/kernel/misc.S
@@ -593,6 +593,14 @@
 	iccci	0,r3
 #endif
 #elif CONFIG_FSL_BOOKE
+BEGIN_FTR_SECTION
+	mfspr   r3,SPRN_L1CSR0
+	ori     r3,r3,L1CSR0_CFI|L1CSR0_CLFC
+	/* msync; isync recommended here */
+	mtspr   SPRN_L1CSR0,r3
+	isync
+	blr
+END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
 	mfspr	r3,SPRN_L1CSR1
 	ori	r3,r3,L1CSR1_ICFI|L1CSR1_ICLFR
 	mtspr	SPRN_L1CSR1,r3
@@ -619,7 +627,7 @@
 _GLOBAL(flush_icache_range)
 BEGIN_FTR_SECTION
 	blr				/* for 601, do nothing */
-END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE)
+END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
 	li	r5,L1_CACHE_LINE_SIZE-1
 	andc	r3,r3,r5
 	subf	r4,r3,r4
@@ -736,7 +744,7 @@
 _GLOBAL(__flush_dcache_icache)
 BEGIN_FTR_SECTION
 	blr					/* for 601, do nothing */
-END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE)
+END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
 	rlwinm	r3,r3,0,0,19			/* Get page base address */
 	li	r4,4096/L1_CACHE_LINE_SIZE	/* Number of lines in a page */
 	mtctr	r4
@@ -764,7 +772,7 @@
 _GLOBAL(__flush_dcache_icache_phys)
 BEGIN_FTR_SECTION
 	blr					/* for 601, do nothing */
-END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE)
+END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
 	mfmsr	r10
 	rlwinm	r0,r10,0,28,26			/* clear DR */
 	mtmsr	r0
@@ -1436,8 +1444,10 @@
 	.long sys_mq_timedreceive	/* 265 */
 	.long sys_mq_notify
 	.long sys_mq_getsetattr
-	.long sys_ni_syscall		/* 268 reserved for sys_kexec_load */
+	.long sys_kexec_load
 	.long sys_add_key
 	.long sys_request_key		/* 270 */
 	.long sys_keyctl
 	.long sys_waitid
+	.long sys_ioprio_set
+	.long sys_ioprio_get
diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index 47a1530..6d7b92d 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -1003,7 +1003,7 @@
 	}
 }
 
-static ssize_t pci_show_devspec(struct device *dev, 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;
diff --git a/arch/ppc/kernel/perfmon.c b/arch/ppc/kernel/perfmon.c
index 918f6b2..fa1dad9 100644
--- a/arch/ppc/kernel/perfmon.c
+++ b/arch/ppc/kernel/perfmon.c
@@ -36,7 +36,7 @@
 /* A lock to regulate grabbing the interrupt */
 DEFINE_SPINLOCK(perfmon_lock);
 
-#ifdef CONFIG_FSL_BOOKE
+#if defined (CONFIG_FSL_BOOKE) && !defined (CONFIG_E200)
 static void dummy_perf(struct pt_regs *regs)
 {
 	unsigned int pmgc0 = mfpmr(PMRN_PMGC0);
diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
index 2ccb58f..d59ad07 100644
--- a/arch/ppc/kernel/ppc_ksyms.c
+++ b/arch/ppc/kernel/ppc_ksyms.c
@@ -55,7 +55,6 @@
 #define EXPORT_SYMTAB_STROPS
 
 extern void transfer_to_handler(void);
-extern void do_syscall_trace(void);
 extern void do_IRQ(struct pt_regs *regs);
 extern void MachineCheckException(struct pt_regs *regs);
 extern void AlignmentException(struct pt_regs *regs);
@@ -74,7 +73,6 @@
 EXPORT_SYMBOL(clear_pages);
 EXPORT_SYMBOL(clear_user_page);
 EXPORT_SYMBOL(do_signal);
-EXPORT_SYMBOL(do_syscall_trace);
 EXPORT_SYMBOL(transfer_to_handler);
 EXPORT_SYMBOL(do_IRQ);
 EXPORT_SYMBOL(MachineCheckException);
diff --git a/arch/ppc/kernel/ptrace.c b/arch/ppc/kernel/ptrace.c
index 59d59a8..e7aee41 100644
--- a/arch/ppc/kernel/ptrace.c
+++ b/arch/ppc/kernel/ptrace.c
@@ -27,6 +27,9 @@
 #include <linux/user.h>
 #include <linux/security.h>
 #include <linux/signal.h>
+#include <linux/seccomp.h>
+#include <linux/audit.h>
+#include <linux/module.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -455,11 +458,10 @@
 	return ret;
 }
 
-void do_syscall_trace(void)
+static void do_syscall_trace(void)
 {
-        if (!test_thread_flag(TIF_SYSCALL_TRACE)
-	    || !(current->ptrace & PT_PTRACED))
-		return;
+	/* the 0x80 provides a way for the tracing parent to distinguish
+	   between a syscall stop and SIGTRAP delivery */
 	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
 				 ? 0x80 : 0));
 
@@ -473,3 +475,33 @@
 		current->exit_code = 0;
 	}
 }
+
+void do_syscall_trace_enter(struct pt_regs *regs)
+{
+	if (test_thread_flag(TIF_SYSCALL_TRACE)
+	    && (current->ptrace & PT_PTRACED))
+		do_syscall_trace();
+
+	if (unlikely(current->audit_context))
+		audit_syscall_entry(current, AUDIT_ARCH_PPC,
+				    regs->gpr[0],
+				    regs->gpr[3], regs->gpr[4],
+				    regs->gpr[5], regs->gpr[6]);
+}
+
+void do_syscall_trace_leave(struct pt_regs *regs)
+{
+	secure_computing(regs->gpr[0]);
+
+	if (unlikely(current->audit_context))
+		audit_syscall_exit(current,
+				   (regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
+				   regs->result);
+
+	if ((test_thread_flag(TIF_SYSCALL_TRACE))
+	    && (current->ptrace & PT_PTRACED))
+		do_syscall_trace();
+}
+
+EXPORT_SYMBOL(do_syscall_trace_enter);
+EXPORT_SYMBOL(do_syscall_trace_leave);
diff --git a/arch/ppc/kernel/relocate_kernel.S b/arch/ppc/kernel/relocate_kernel.S
new file mode 100644
index 0000000..7ff69c4
--- /dev/null
+++ b/arch/ppc/kernel/relocate_kernel.S
@@ -0,0 +1,123 @@
+/*
+ * relocate_kernel.S - put the kernel image in place to boot
+ * Copyright (C) 2002-2003 Eric Biederman  <ebiederm@xmission.com>
+ *
+ * GameCube/ppc32 port Copyright (C) 2004 Albert Herranz
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+
+#include <asm/reg.h>
+#include <asm/ppc_asm.h>
+#include <asm/processor.h>
+
+#include <asm/kexec.h>
+
+#define PAGE_SIZE      4096 /* must be same value as in <asm/page.h> */
+
+	/*
+	 * Must be relocatable PIC code callable as a C function.
+	 */
+	.globl relocate_new_kernel
+relocate_new_kernel:
+	/* r3 = page_list   */
+	/* r4 = reboot_code_buffer */
+	/* r5 = start_address      */
+
+	li	r0, 0
+
+	/*
+	 * Set Machine Status Register to a known status,
+	 * switch the MMU off and jump to 1: in a single step.
+	 */
+
+	mr	r8, r0
+	ori     r8, r8, MSR_RI|MSR_ME
+	mtspr	SRR1, r8
+	addi	r8, r4, 1f - relocate_new_kernel
+	mtspr	SRR0, r8
+	sync
+	rfi
+
+1:
+	/* from this point address translation is turned off */
+	/* and interrupts are disabled */
+
+	/* set a new stack at the bottom of our page... */
+	/* (not really needed now) */
+	addi	r1, r4, KEXEC_CONTROL_CODE_SIZE - 8 /* for LR Save+Back Chain */
+	stw	r0, 0(r1)
+
+	/* Do the copies */
+	li	r6, 0 /* checksum */
+	mr	r0, r3
+	b	1f
+
+0:	/* top, read another word for the indirection page */
+	lwzu	r0, 4(r3)
+
+1:
+	/* is it a destination page? (r8) */
+	rlwinm.	r7, r0, 0, 31, 31 /* IND_DESTINATION (1<<0) */
+	beq	2f
+
+	rlwinm	r8, r0, 0, 0, 19 /* clear kexec flags, page align */
+	b	0b
+
+2:	/* is it an indirection page? (r3) */
+	rlwinm.	r7, r0, 0, 30, 30 /* IND_INDIRECTION (1<<1) */
+	beq	2f
+
+	rlwinm	r3, r0, 0, 0, 19 /* clear kexec flags, page align */
+	subi	r3, r3, 4
+	b	0b
+
+2:	/* are we done? */
+	rlwinm.	r7, r0, 0, 29, 29 /* IND_DONE (1<<2) */
+	beq	2f
+	b	3f
+
+2:	/* is it a source page? (r9) */
+	rlwinm.	r7, r0, 0, 28, 28 /* IND_SOURCE (1<<3) */
+	beq	0b
+
+	rlwinm	r9, r0, 0, 0, 19 /* clear kexec flags, page align */
+
+	li	r7, PAGE_SIZE / 4
+	mtctr   r7
+	subi    r9, r9, 4
+	subi    r8, r8, 4
+9:
+	lwzu    r0, 4(r9)  /* do the copy */
+	xor	r6, r6, r0
+	stwu    r0, 4(r8)
+	dcbst	0, r8
+	sync
+	icbi	0, r8
+	bdnz    9b
+
+	addi    r9, r9, 4
+	addi    r8, r8, 4
+	b	0b
+
+3:
+
+	/* To be certain of avoiding problems with self-modifying code
+	 * execute a serializing instruction here.
+	 */
+	isync
+	sync
+
+	/* jump to the entry point, usually the setup routine */
+	mtlr	r5
+	blrl
+
+1:	b	1b
+
+relocate_new_kernel_end:
+
+	.globl relocate_new_kernel_size
+relocate_new_kernel_size:
+	.long relocate_new_kernel_end - relocate_new_kernel
+
diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
index 5c20266..c42f753 100644
--- a/arch/ppc/kernel/setup.c
+++ b/arch/ppc/kernel/setup.c
@@ -41,7 +41,7 @@
 #include <asm/xmon.h>
 #include <asm/ocp.h>
 
-#if defined(CONFIG_85xx) || defined(CONFIG_83xx)
+#if defined(CONFIG_85xx) || defined(CONFIG_83xx) || defined(CONFIG_MPC10X_BRIDGE)
 #include <asm/ppc_sys.h>
 #endif
 
@@ -61,8 +61,6 @@
 
 extern boot_infos_t *boot_infos;
 struct ide_machdep_calls ppc_ide_md;
-char *sysmap;
-unsigned long sysmap_size;
 
 /* Used with the BI_MEMSIZE bootinfo parameter to store the memory
    size value reported by the boot loader. */
@@ -249,7 +247,7 @@
 	seq_printf(m, "bogomips\t: %lu.%02lu\n",
 		   lpj / (500000/HZ), (lpj / (5000/HZ)) % 100);
 
-#if defined(CONFIG_85xx) || defined(CONFIG_83xx)
+#if defined(CONFIG_85xx) || defined(CONFIG_83xx) || defined(CONFIG_MPC10X_BRIDGE)
 	if (cur_ppc_sys_spec->ppc_sys_name)
 		seq_printf(m, "chipset\t\t: %s\n",
 			cur_ppc_sys_spec->ppc_sys_name);
@@ -578,11 +576,6 @@
 		case BI_CMD_LINE:
 			strlcpy(cmd_line, (void *)data, sizeof(cmd_line));
 			break;
-		case BI_SYSMAP:
-			sysmap = (char *)((data[0] >= (KERNELBASE)) ? data[0] :
-					  (data[0]+KERNELBASE));
-			sysmap_size = data[1];
-			break;
 #ifdef CONFIG_BLK_DEV_INITRD
 		case BI_INITRD:
 			initrd_start = data[0] + KERNELBASE;
diff --git a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c
index 7c8437da..8aaeb6f 100644
--- a/arch/ppc/kernel/signal.c
+++ b/arch/ppc/kernel/signal.c
@@ -705,8 +705,7 @@
 	unsigned long frame, newsp;
 	int signr, ret;
 
-	if (current->flags & PF_FREEZE) {
-		refrigerator(PF_FREEZE);
+	if (try_to_freeze()) {
 		signr = 0;
 		if (!signal_pending(current))
 			goto no_signal;
diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c
index c65731e..9e6ae56 100644
--- a/arch/ppc/kernel/traps.c
+++ b/arch/ppc/kernel/traps.c
@@ -81,8 +81,10 @@
 	console_verbose();
 	spin_lock_irq(&die_lock);
 #ifdef CONFIG_PMAC_BACKLIGHT
-	set_backlight_enable(1);
-	set_backlight_level(BACKLIGHT_MAX);
+	if (_machine == _MACH_Pmac) {
+		set_backlight_enable(1);
+		set_backlight_level(BACKLIGHT_MAX);
+	}
 #endif
 	printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter);
 #ifdef CONFIG_PREEMPT
@@ -171,13 +173,13 @@
 /* On 4xx, the reason for the machine check or program exception
    is in the ESR. */
 #define get_reason(regs)	((regs)->dsisr)
-#ifndef CONFIG_E500
+#ifndef CONFIG_FSL_BOOKE
 #define get_mc_reason(regs)	((regs)->dsisr)
 #else
 #define get_mc_reason(regs)	(mfspr(SPRN_MCSR))
 #endif
 #define REASON_FP		ESR_FP
-#define REASON_ILLEGAL		ESR_PIL
+#define REASON_ILLEGAL		(ESR_PIL | ESR_PUO)
 #define REASON_PRIVILEGED	ESR_PPR
 #define REASON_TRAP		ESR_PTR
 
@@ -300,7 +302,25 @@
 		printk("Bus - Instruction Parity Error\n");
 	if (reason & MCSR_BUS_RPERR)
 		printk("Bus - Read Parity Error\n");
-#else /* !CONFIG_4xx && !CONFIG_E500 */
+#elif defined (CONFIG_E200)
+	printk("Machine check in kernel mode.\n");
+	printk("Caused by (from MCSR=%lx): ", reason);
+
+	if (reason & MCSR_MCP)
+		printk("Machine Check Signal\n");
+	if (reason & MCSR_CP_PERR)
+		printk("Cache Push Parity Error\n");
+	if (reason & MCSR_CPERR)
+		printk("Cache Parity Error\n");
+	if (reason & MCSR_EXCP_ERR)
+		printk("ISI, ITLB, or Bus Error on first instruction fetch for an exception handler\n");
+	if (reason & MCSR_BUS_IRERR)
+		printk("Bus - Read Bus Error on instruction fetch\n");
+	if (reason & MCSR_BUS_DRERR)
+		printk("Bus - Read Bus Error on data load\n");
+	if (reason & MCSR_BUS_WRERR)
+		printk("Bus - Write Bus Error on buffered store or cache line push\n");
+#else /* !CONFIG_4xx && !CONFIG_E500 && !CONFIG_E200 */
 	printk("Machine check in kernel mode.\n");
 	printk("Caused by (from SRR1=%lx): ", reason);
 	switch (reason & 0x601F0000) {
diff --git a/arch/ppc/lib/locks.c b/arch/ppc/lib/locks.c
index 694163d..c450dc4 100644
--- a/arch/ppc/lib/locks.c
+++ b/arch/ppc/lib/locks.c
@@ -130,7 +130,7 @@
 		while (!read_can_lock(rw)) {
 			if (--stuck == 0) {
 				printk("_read_lock(%p) CPU#%d lock %d\n",
-				       rw, _smp_processor_id(), rw->lock);
+				       rw, raw_smp_processor_id(), rw->lock);
 				stuck = INIT_STUCK;
 			}
 		}
@@ -158,7 +158,7 @@
 		while (!write_can_lock(rw)) {
 			if (--stuck == 0) {
 				printk("write_lock(%p) CPU#%d lock %d)\n",
-				       rw, _smp_processor_id(), rw->lock);
+				       rw, raw_smp_processor_id(), rw->lock);
 				stuck = INIT_STUCK;
 			}
 		}
diff --git a/arch/ppc/mm/44x_mmu.c b/arch/ppc/mm/44x_mmu.c
index 72f7c0d..3d79ce2 100644
--- a/arch/ppc/mm/44x_mmu.c
+++ b/arch/ppc/mm/44x_mmu.c
@@ -39,7 +39,6 @@
 #include <linux/vmalloc.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/bootmem.h>
 #include <linux/highmem.h>
 
 #include <asm/pgalloc.h>
diff --git a/arch/ppc/mm/4xx_mmu.c b/arch/ppc/mm/4xx_mmu.c
index a7f6161..b7bcbc2 100644
--- a/arch/ppc/mm/4xx_mmu.c
+++ b/arch/ppc/mm/4xx_mmu.c
@@ -36,7 +36,6 @@
 #include <linux/vmalloc.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/bootmem.h>
 #include <linux/highmem.h>
 
 #include <asm/pgalloc.h>
diff --git a/arch/ppc/mm/fsl_booke_mmu.c b/arch/ppc/mm/fsl_booke_mmu.c
index 36233bd..af9ca0e 100644
--- a/arch/ppc/mm/fsl_booke_mmu.c
+++ b/arch/ppc/mm/fsl_booke_mmu.c
@@ -41,7 +41,6 @@
 #include <linux/vmalloc.h>
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/bootmem.h>
 #include <linux/highmem.h>
 
 #include <asm/pgalloc.h>
@@ -64,6 +63,8 @@
 extern unsigned long __max_low_memory;
 #define MAX_LOW_MEM	CONFIG_LOWMEM_SIZE
 
+#define NUM_TLBCAMS	(16)
+
 struct tlbcam {
    	u32	MAS0;
 	u32	MAS1;
@@ -124,7 +125,7 @@
 		flags |= _PAGE_COHERENT;
 #endif
 
-	TLBCAM[index].MAS0 = MAS0_TLBSEL(1) | MAS0_ESEL(index);
+	TLBCAM[index].MAS0 = MAS0_TLBSEL(1) | MAS0_ESEL(index) | MAS0_NV(index+1);
 	TLBCAM[index].MAS1 = MAS1_VALID | MAS1_IPROT | MAS1_TSIZE(tsize) | MAS1_TID(pid);
 	TLBCAM[index].MAS2 = virt & PAGE_MASK;
 
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index 363c157..334ef41 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -96,9 +96,6 @@
 char *klimit = _end;
 struct mem_pieces phys_avail;
 
-extern char *sysmap;
-extern unsigned long sysmap_size;
-
 /*
  * this tells the system to map all of ram with the segregs
  * (i.e. page tables) instead of the bats.
@@ -442,12 +439,6 @@
 	if (agp_special_page)
 		SetPageReserved(virt_to_page(agp_special_page));
 #endif
-	if ( sysmap )
-		for (addr = (unsigned long)sysmap;
-		     addr < PAGE_ALIGN((unsigned long)sysmap+sysmap_size) ;
-		     addr += PAGE_SIZE)
-			SetPageReserved(virt_to_page(addr));
-
 	for (addr = PAGE_OFFSET; addr < (unsigned long)high_memory;
 	     addr += PAGE_SIZE) {
 		if (!PageReserved(virt_to_page(addr)))
@@ -469,7 +460,6 @@
 			struct page *page = mem_map + pfn;
 
 			ClearPageReserved(page);
-			set_bit(PG_highmem, &page->flags);
 			set_page_count(page, 1);
 			__free_page(page);
 			totalhigh_pages++;
@@ -483,9 +473,7 @@
 	       codepages<< (PAGE_SHIFT-10), datapages<< (PAGE_SHIFT-10),
 	       initpages<< (PAGE_SHIFT-10),
 	       (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10)));
-	if (sysmap)
-		printk("System.map loaded at 0x%08x for debugger, size: %ld bytes\n",
-			(unsigned int)sysmap, sysmap_size);
+
 #ifdef CONFIG_PPC_PMAC
 	if (agp_special_page)
 		printk(KERN_INFO "AGP special page: 0x%08lx\n", agp_special_page);
@@ -535,9 +523,6 @@
 	if (rtas_data)
 		mem_pieces_remove(&phys_avail, rtas_data, rtas_size, 1);
 #endif
-	/* remove the sysmap pages from the available memory */
-	if (sysmap)
-		mem_pieces_remove(&phys_avail, __pa(sysmap), sysmap_size, 1);
 #ifdef CONFIG_PPC_PMAC
 	/* Because of some uninorth weirdness, we need a page of
 	 * memory as high as possible (it must be outside of the
diff --git a/arch/ppc/mm/mmu_decl.h b/arch/ppc/mm/mmu_decl.h
index ffcdb46..540f329 100644
--- a/arch/ppc/mm/mmu_decl.h
+++ b/arch/ppc/mm/mmu_decl.h
@@ -43,6 +43,8 @@
 extern PTE *Hash, *Hash_end;
 extern unsigned long Hash_size, Hash_mask;
 
+extern unsigned int num_tlbcam_entries;
+
 /* ...and now those things that may be slightly different between processor
  * architectures.  -- Dan
  */
diff --git a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
index 5d2f3f6..81a3d74 100644
--- a/arch/ppc/mm/pgtable.c
+++ b/arch/ppc/mm/pgtable.c
@@ -66,7 +66,6 @@
 
 #ifdef HAVE_TLBCAM
 extern unsigned int tlbcam_index;
-extern unsigned int num_tlbcam_entries;
 extern unsigned long v_mapped_by_tlbcam(unsigned long va);
 extern unsigned long p_mapped_by_tlbcam(unsigned long pa);
 #else /* !HAVE_TLBCAM */
diff --git a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c
index e6348b5..ddd04d4 100644
--- a/arch/ppc/platforms/83xx/mpc834x_sys.c
+++ b/arch/ppc/platforms/83xx/mpc834x_sys.c
@@ -41,7 +41,6 @@
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
-#include <asm/prom.h>
 #include <asm/ipic.h>
 #include <asm/bootinfo.h>
 #include <asm/pci-bridge.h>
@@ -95,20 +94,24 @@
 
 	/* setup the board related information for the enet controllers */
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1);
-	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
-	pdata->interruptPHY = MPC83xx_IRQ_EXT1;
-	pdata->phyid = 0;
-	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+	if (pdata) {
+		pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+		pdata->interruptPHY = MPC83xx_IRQ_EXT1;
+		pdata->phyid = 0;
+		/* fixup phy address */
+		pdata->phy_reg_addr += binfo->bi_immr_base;
+		memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+	}
 
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC2);
-	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
-	pdata->interruptPHY = MPC83xx_IRQ_EXT2;
-	pdata->phyid = 1;
-	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+	if (pdata) {
+		pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+		pdata->interruptPHY = MPC83xx_IRQ_EXT2;
+		pdata->phyid = 1;
+		/* fixup phy address */
+		pdata->phy_reg_addr += binfo->bi_immr_base;
+		memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+	}
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start)
@@ -186,6 +189,26 @@
 	ipic_set_default_priority();
 }
 
+#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374)
+extern ulong	ds1374_get_rtc_time(void);
+extern int	ds1374_set_rtc_time(ulong);
+
+static int __init
+mpc834x_rtc_hookup(void)
+{
+	struct timespec	tv;
+
+	ppc_md.get_rtc_time = ds1374_get_rtc_time;
+	ppc_md.set_rtc_time = ds1374_set_rtc_time;
+
+	tv.tv_nsec = 0;
+	tv.tv_sec = (ppc_md.get_rtc_time)();
+	do_settimeofday(&tv);
+
+	return 0;
+}
+late_initcall(mpc834x_rtc_hookup);
+#endif
 static __inline__ void
 mpc834x_sys_set_bat(void)
 {
diff --git a/arch/ppc/platforms/85xx/Kconfig b/arch/ppc/platforms/85xx/Kconfig
index ff92e38..c5bc282 100644
--- a/arch/ppc/platforms/85xx/Kconfig
+++ b/arch/ppc/platforms/85xx/Kconfig
@@ -21,6 +21,11 @@
 	help
 	  This option enables support for the MPC 8540 ADS evaluation board.
 
+config MPC8548_CDS
+	bool "Freescale MPC8548 CDS"
+	help
+	  This option enablese support for the MPC8548 CDS evaluation board.
+
 config MPC8555_CDS
 	bool "Freescale MPC8555 CDS"
 	help
@@ -53,6 +58,11 @@
 	depends on MPC8540_ADS
 	default y
 
+config MPC8548
+	bool
+	depends on MPC8548_CDS
+	default y
+
 config MPC8555
 	bool
 	depends on MPC8555_CDS
diff --git a/arch/ppc/platforms/85xx/Makefile b/arch/ppc/platforms/85xx/Makefile
index 854fbd2..efdf813 100644
--- a/arch/ppc/platforms/85xx/Makefile
+++ b/arch/ppc/platforms/85xx/Makefile
@@ -2,6 +2,7 @@
 # Makefile for the PowerPC 85xx linux kernel.
 #
 obj-$(CONFIG_MPC8540_ADS)	+= mpc85xx_ads_common.o mpc8540_ads.o
+obj-$(CONFIG_MPC8548_CDS)	+= mpc85xx_cds_common.o
 obj-$(CONFIG_MPC8555_CDS)	+= mpc85xx_cds_common.o
 obj-$(CONFIG_MPC8560_ADS)	+= mpc85xx_ads_common.o mpc8560_ads.o
 obj-$(CONFIG_SBC8560)		+= sbc85xx.o sbc8560.o
diff --git a/arch/ppc/platforms/85xx/mpc8540_ads.c b/arch/ppc/platforms/85xx/mpc8540_ads.c
index 583838a..ddd2e9a 100644
--- a/arch/ppc/platforms/85xx/mpc8540_ads.c
+++ b/arch/ppc/platforms/85xx/mpc8540_ads.c
@@ -41,7 +41,6 @@
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
-#include <asm/prom.h>
 #include <asm/open_pic.h>
 #include <asm/bootinfo.h>
 #include <asm/pci-bridge.h>
@@ -88,33 +87,39 @@
 #ifdef CONFIG_SERIAL_TEXT_DEBUG
 	/* Invalidate the entry we stole earlier the serial ports
 	 * should be properly mapped */
-	invalidate_tlbcam_entry(NUM_TLBCAMS - 1);
+	invalidate_tlbcam_entry(num_tlbcam_entries - 1);
 #endif
 
 	/* setup the board related information for the enet controllers */
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
-	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
-	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
-	pdata->phyid = 0;
-	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+	if (pdata) {
+		pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+		pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+		pdata->phyid = 0;
+		/* fixup phy address */
+		pdata->phy_reg_addr += binfo->bi_immr_base;
+		memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+	}
 
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
-	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
-	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
-	pdata->phyid = 1;
-	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+	if (pdata) {
+		pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+		pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+		pdata->phyid = 1;
+		/* fixup phy address */
+		pdata->phy_reg_addr += binfo->bi_immr_base;
+		memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+	}
 
-	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC);
-	pdata->board_flags = 0;
-	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
-	pdata->phyid = 3;
-	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6);
+	if (pdata) {
+		pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_FEC);
+		pdata->board_flags = 0;
+		pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+		pdata->phyid = 3;
+		/* fixup phy address */
+		pdata->phy_reg_addr += binfo->bi_immr_base;
+		memcpy(pdata->mac_addr, binfo->bi_enet2addr, 6);
+	}
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start)
@@ -150,7 +155,7 @@
 		struct uart_port p;
 
 		/* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */
-		settlbcam(NUM_TLBCAMS - 1, binfo->bi_immr_base,
+		settlbcam(num_tlbcam_entries - 1, binfo->bi_immr_base,
 			  binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0);
 
 		memset(&p, 0, sizeof (p));
diff --git a/arch/ppc/platforms/85xx/mpc8560_ads.c b/arch/ppc/platforms/85xx/mpc8560_ads.c
index 761b8c7..e183802 100644
--- a/arch/ppc/platforms/85xx/mpc8560_ads.c
+++ b/arch/ppc/platforms/85xx/mpc8560_ads.c
@@ -41,7 +41,6 @@
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
-#include <asm/prom.h>
 #include <asm/open_pic.h>
 #include <asm/bootinfo.h>
 #include <asm/pci-bridge.h>
@@ -91,20 +90,24 @@
 
 	/* setup the board related information for the enet controllers */
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
-	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
-	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
-	pdata->phyid = 0;
-	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+	if (pdata) {
+		pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+		pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+		pdata->phyid = 0;
+		/* fixup phy address */
+		pdata->phy_reg_addr += binfo->bi_immr_base;
+		memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+	}
 
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
-	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
-	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
-	pdata->phyid = 1;
-	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+	if (pdata) {
+		pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+		pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+		pdata->phyid = 1;
+		/* fixup phy address */
+		pdata->phy_reg_addr += binfo->bi_immr_base;
+		memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+	}
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start)
diff --git a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c
index ba9f9f5..18e952d 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c
+++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c
@@ -36,7 +36,6 @@
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
-#include <asm/prom.h>
 #include <asm/open_pic.h>
 #include <asm/bootinfo.h>
 #include <asm/pci-bridge.h>
@@ -59,40 +58,8 @@
 unsigned char __res[sizeof (bd_t)];
 
 /* Internal interrupts are all Level Sensitive, and Positive Polarity */
-
 static u_char mpc85xx_ads_openpic_initsenses[] __initdata = {
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  0: L2 Cache */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  1: ECM */
-	(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: PCI/PCI-X */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  9: RIO Inbound Port Write Error */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 10: RIO Doorbell Inbound */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 11: RIO Outbound Message */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 12: RIO Inbound Message */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 13: TSEC 0 Transmit */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 14: TSEC 0 Receive */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 15: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 16: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 17: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 18: TSEC 0 Receive/Transmit Error */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 19: TSEC 1 Transmit */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 20: TSEC 1 Receive */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 21: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 22: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 23: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 24: TSEC 1 Receive/Transmit Error */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 25: Fast Ethernet */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 26: DUART */
-	(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: CPM */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 31: Unused */
+	MPC85XX_INTERNAL_IRQ_SENSES,
 	0x0,						/* External  0: */
 #if defined(CONFIG_PCI)
 	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 1: PCI slot 0 */
@@ -159,7 +126,7 @@
 	/* Skip reserved space and internal sources */
 	openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
 	/* Map PIC IRQs 0-11 */
-	openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
+	openpic_set_sources(48, 12, OpenPIC_Addr + 0x10000);
 
 	/* we let openpic interrupts starting from an offset, to
 	 * leave space for cascading interrupts underneath.
diff --git a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
index e7cfa49..b52c431 100644
--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
@@ -42,7 +42,6 @@
 #include <asm/todc.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
-#include <asm/prom.h>
 #include <asm/open_pic.h>
 #include <asm/i8259.h>
 #include <asm/bootinfo.h>
@@ -73,40 +72,8 @@
 static volatile u8 * cadmus;
 
 /* Internal interrupts are all Level Sensitive, and Positive Polarity */
-
 static u_char mpc85xx_cds_openpic_initsenses[] __initdata = {
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  0: L2 Cache */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  1: ECM */
-	(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: PCI/PCI-X */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  9: RIO Inbound Port Write Error */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 10: RIO Doorbell Inbound */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 11: RIO Outbound Message */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 12: RIO Inbound Message */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 13: TSEC 0 Transmit */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 14: TSEC 0 Receive */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 15: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 16: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 17: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 18: TSEC 0 Receive/Transmit Error */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 19: TSEC 1 Transmit */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 20: TSEC 1 Receive */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 21: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 22: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 23: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 24: TSEC 1 Receive/Transmit Error */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 25: Fast Ethernet */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 26: DUART */
-	(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: CPM */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 31: Unused */
+	MPC85XX_INTERNAL_IRQ_SENSES,
 #if defined(CONFIG_PCI)
 	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 0: PCI1 slot */
 	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 1: PCI1 slot */
@@ -191,9 +158,13 @@
 	OpenPIC_NumInitSenses = sizeof (mpc85xx_cds_openpic_initsenses);
 
 	/* Skip reserved space and internal sources */
+#ifdef CONFIG_MPC8548
+	openpic_set_sources(0, 48, OpenPIC_Addr + 0x10200);
+#else
 	openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
+#endif
 	/* Map PIC IRQs 0-11 */
-	openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
+	openpic_set_sources(48, 12, OpenPIC_Addr + 0x10000);
 
 	/* we let openpic interrupts starting from an offset, to
 	 * leave space for cascading interrupts underneath.
@@ -475,26 +446,52 @@
 #ifdef CONFIG_SERIAL_TEXT_DEBUG
 	/* Invalidate the entry we stole earlier the serial ports
 	 * should be properly mapped */
-	invalidate_tlbcam_entry(NUM_TLBCAMS - 1);
+	invalidate_tlbcam_entry(num_tlbcam_entries - 1);
 #endif
 
 	/* setup the board related information for the enet controllers */
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
-	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
-	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
-	pdata->phyid = 0;
-	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+	if (pdata) {
+		pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+		pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+		pdata->phyid = 0;
+		/* fixup phy address */
+		pdata->phy_reg_addr += binfo->bi_immr_base;
+		memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+	}
 
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
-	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
-	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
-	pdata->phyid = 1;
-	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+	if (pdata) {
+		pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+		pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+		pdata->phyid = 1;
+		/* fixup phy address */
+		pdata->phy_reg_addr += binfo->bi_immr_base;
+		memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+	}
 
+	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_eTSEC1);
+	if (pdata) {
+		pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+		pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+		pdata->phyid = 0;
+		/* fixup phy address */
+		pdata->phy_reg_addr += binfo->bi_immr_base;
+		memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+	}
+
+	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_eTSEC2);
+	if (pdata) {
+		pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+		pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+		pdata->phyid = 1;
+		/* fixup phy address */
+		pdata->phy_reg_addr += binfo->bi_immr_base;
+		memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+	}
+
+	ppc_sys_device_remove(MPC85xx_eTSEC3);
+	ppc_sys_device_remove(MPC85xx_eTSEC4);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start)
@@ -531,7 +528,7 @@
 		struct uart_port p;
 
 		/* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */
-		settlbcam(NUM_TLBCAMS - 1, binfo->bi_immr_base,
+		settlbcam(num_tlbcam_entries - 1, binfo->bi_immr_base,
 				binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0);
 
 		memset(&p, 0, sizeof (p));
diff --git a/arch/ppc/platforms/85xx/sbc8560.c b/arch/ppc/platforms/85xx/sbc8560.c
index 7b9e154..165df94 100644
--- a/arch/ppc/platforms/85xx/sbc8560.c
+++ b/arch/ppc/platforms/85xx/sbc8560.c
@@ -41,7 +41,6 @@
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
-#include <asm/prom.h>
 #include <asm/open_pic.h>
 #include <asm/bootinfo.h>
 #include <asm/pci-bridge.h>
@@ -125,25 +124,29 @@
 #ifdef CONFIG_SERIAL_TEXT_DEBUG
 	/* Invalidate the entry we stole earlier the serial ports
 	 * should be properly mapped */ 
-	invalidate_tlbcam_entry(NUM_TLBCAMS - 1);
+	invalidate_tlbcam_entry(num_tlbcam_entries - 1);
 #endif
 
 	/* setup the board related information for the enet controllers */
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
-	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
-	pdata->interruptPHY = MPC85xx_IRQ_EXT6;
-	pdata->phyid = 25;
-	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+	if (pdata) {
+		pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+		pdata->interruptPHY = MPC85xx_IRQ_EXT6;
+		pdata->phyid = 25;
+		/* fixup phy address */
+		pdata->phy_reg_addr += binfo->bi_immr_base;
+		memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+	}
 
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
-	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
-	pdata->interruptPHY = MPC85xx_IRQ_EXT7;
-	pdata->phyid = 26;
-	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+	if (pdata) {
+		pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+		pdata->interruptPHY = MPC85xx_IRQ_EXT7;
+		pdata->phyid = 26;
+		/* fixup phy address */
+		pdata->phy_reg_addr += binfo->bi_immr_base;
+		memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+	}
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start)
@@ -176,7 +179,7 @@
 
 #ifdef CONFIG_SERIAL_TEXT_DEBUG
 	/* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */
-	settlbcam(NUM_TLBCAMS - 1, UARTA_ADDR,
+	settlbcam(num_tlbcam_entries - 1, UARTA_ADDR,
 		  UARTA_ADDR, 0x1000, _PAGE_IO, 0);
 #endif
 
diff --git a/arch/ppc/platforms/85xx/sbc85xx.c b/arch/ppc/platforms/85xx/sbc85xx.c
index 2d638c1..4f6d1dd 100644
--- a/arch/ppc/platforms/85xx/sbc85xx.c
+++ b/arch/ppc/platforms/85xx/sbc85xx.c
@@ -35,7 +35,6 @@
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
-#include <asm/prom.h>
 #include <asm/open_pic.h>
 #include <asm/bootinfo.h>
 #include <asm/pci-bridge.h>
@@ -59,40 +58,8 @@
 extern unsigned long total_memory;	/* in mm/init */
 
 /* Internal interrupts are all Level Sensitive, and Positive Polarity */
-
 static u_char sbc8560_openpic_initsenses[] __initdata = {
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  0: L2 Cache */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  1: ECM */
-	(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: PCI/PCI-X */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  9: RIO Inbound Port Write Error */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 10: RIO Doorbell Inbound */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 11: RIO Outbound Message */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 12: RIO Inbound Message */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 13: TSEC 0 Transmit */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 14: TSEC 0 Receive */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 15: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 16: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 17: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 18: TSEC 0 Receive/Transmit Error */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 19: TSEC 1 Transmit */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 20: TSEC 1 Receive */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 21: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 22: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 23: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 24: TSEC 1 Receive/Transmit Error */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 25: Fast Ethernet */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 26: DUART */
-	(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: CPM */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 31: Unused */
+	MPC85XX_INTERNAL_IRQ_SENSES,
 	0x0,				/* External  0: */
 	0x0,				/* External  1: */
 #if defined(CONFIG_PCI)
@@ -159,7 +126,7 @@
 	/* Skip reserved space and internal sources */
 	openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
 	/* Map PIC IRQs 0-11 */
-	openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
+	openpic_set_sources(48, 12, OpenPIC_Addr + 0x10000);
 
 	/* we let openpic interrupts starting from an offset, to 
 	 * leave space for cascading interrupts underneath.
diff --git a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c
index bc95836..bb41265 100644
--- a/arch/ppc/platforms/85xx/stx_gp3.c
+++ b/arch/ppc/platforms/85xx/stx_gp3.c
@@ -46,7 +46,6 @@
 #include <asm/time.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
-#include <asm/prom.h>
 #include <asm/open_pic.h>
 #include <asm/bootinfo.h>
 #include <asm/pci-bridge.h>
@@ -72,38 +71,7 @@
 
 /* Internal interrupts are all Level Sensitive, and Positive Polarity */
 static u8 gp3_openpic_initsenses[] __initdata = {
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  0: L2 Cache */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  1: ECM */
-	(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: PCI/PCI-X */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  9: RIO Inbound Port Write Error */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 10: RIO Doorbell Inbound */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 11: RIO Outbound Message */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 12: RIO Inbound Message */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 13: TSEC 0 Transmit */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 14: TSEC 0 Receive */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 15: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 16: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 17: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 18: TSEC 0 Receive/Transmit Error */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 19: TSEC 1 Transmit */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 20: TSEC 1 Receive */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 21: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 22: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 23: Unused */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 24: TSEC 1 Receive/Transmit Error */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 25: Fast Ethernet */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 26: DUART */
-	(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: CPM */
-	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 31: Unused */
+	MPC85XX_INTERNAL_IRQ_SENSES,
 	0x0,						/* External  0: */
 #if defined(CONFIG_PCI)
 	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 1: PCI slot 0 */
@@ -154,19 +122,23 @@
 
 	/* setup the board related information for the enet controllers */
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
-/*	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */
-	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
-	pdata->phyid = 2;
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+	if (pdata) {
+	/*	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */
+		pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+		pdata->phyid = 2;
+		pdata->phy_reg_addr += binfo->bi_immr_base;
+		memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+	}
 
 	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
-/*	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */
-	pdata->interruptPHY = MPC85xx_IRQ_EXT5;
-	pdata->phyid = 4;
-	/* fixup phy address */
-	pdata->phy_reg_addr += binfo->bi_immr_base;
-	memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+	if (pdata) {
+	/*	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR; */
+		pdata->interruptPHY = MPC85xx_IRQ_EXT5;
+		pdata->phyid = 4;
+		/* fixup phy address */
+		pdata->phy_reg_addr += binfo->bi_immr_base;
+		memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+	}
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (initrd_start)
@@ -200,7 +172,6 @@
 static void __init
 gp3_init_IRQ(void)
 {
-	int i;
 	bd_t *binfo = (bd_t *) __res;
 
 	/*
@@ -218,7 +189,7 @@
 	openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
 
 	/* Map PIC IRQs 0-11 */
-	openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
+	openpic_set_sources(48, 12, OpenPIC_Addr + 0x10000);
 
 	/*
 	 * Let openpic interrupts starting from an offset, to
diff --git a/arch/ppc/platforms/chrp_pci.c b/arch/ppc/platforms/chrp_pci.c
index 7d0ee30..7d3fbb5 100644
--- a/arch/ppc/platforms/chrp_pci.c
+++ b/arch/ppc/platforms/chrp_pci.c
@@ -9,7 +9,6 @@
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/ide.h>
-#include <linux/bootmem.h>
 
 #include <asm/io.h>
 #include <asm/pgtable.h>
diff --git a/arch/ppc/platforms/katana.c b/arch/ppc/platforms/katana.c
index eda922a..169dbf6 100644
--- a/arch/ppc/platforms/katana.c
+++ b/arch/ppc/platforms/katana.c
@@ -27,12 +27,12 @@
 #include <linux/root_dev.h>
 #include <linux/delay.h>
 #include <linux/seq_file.h>
-#include <linux/bootmem.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mv643xx.h>
 #ifdef CONFIG_BOOTIMG
 #include <linux/bootimg.h>
 #endif
+#include <asm/io.h>
 #include <asm/page.h>
 #include <asm/time.h>
 #include <asm/smp.h>
diff --git a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c
index 937f46d..5fdd4f6 100644
--- a/arch/ppc/platforms/pmac_cpufreq.c
+++ b/arch/ppc/platforms/pmac_cpufreq.c
@@ -83,7 +83,7 @@
 static u32 slew_done_gpio;
 static int no_schedule;
 static int has_cpu_l2lve;
-
+static int is_pmu_based;
 
 /* There are only two frequency states for each processor. Values
  * are in kHz for the time being.
@@ -463,7 +463,7 @@
 	 */
 	no_schedule = 1;
 	sleep_freq = cur_freq;
-	if (cur_freq == low_freq)
+	if (cur_freq == low_freq && !is_pmu_based)
 		do_set_cpu_speed(CPUFREQ_HIGH, 0);
 	return 0;
 }
@@ -588,6 +588,7 @@
 		return 1;
 	hi_freq = (*value) / 1000;
 	set_speed_proc = pmu_set_cpu_speed;
+	is_pmu_based = 1;
 
 	return 0;
 }
@@ -692,6 +693,7 @@
 		hi_freq = cur_freq;
 		low_freq = 400000;
 		set_speed_proc = pmu_set_cpu_speed;
+		is_pmu_based = 1;
 	}
 	/* Else check for TiPb 400 & 500 */
 	else if (machine_is_compatible("PowerBook3,2")) {
@@ -703,6 +705,7 @@
 		hi_freq = cur_freq;
 		low_freq = 300000;
 		set_speed_proc = pmu_set_cpu_speed;
+		is_pmu_based = 1;
 	}
 	/* Else check for 750FX */
 	else if (PVR_VER(mfspr(SPRN_PVR)) == 0x7000)
diff --git a/arch/ppc/platforms/pmac_pci.c b/arch/ppc/platforms/pmac_pci.c
index f6ff519..719fb49 100644
--- a/arch/ppc/platforms/pmac_pci.c
+++ b/arch/ppc/platforms/pmac_pci.c
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 #include <linux/string.h>
 #include <linux/init.h>
-#include <linux/bootmem.h>
 
 #include <asm/sections.h>
 #include <asm/io.h>
diff --git a/arch/ppc/platforms/sandpoint.c b/arch/ppc/platforms/sandpoint.c
index 531bfa0..70e58f4 100644
--- a/arch/ppc/platforms/sandpoint.c
+++ b/arch/ppc/platforms/sandpoint.c
@@ -81,6 +81,7 @@
 #include <linux/serial.h>
 #include <linux/tty.h>	/* for linux/serial_core.h */
 #include <linux/serial_core.h>
+#include <linux/serial_8250.h>
 
 #include <asm/system.h>
 #include <asm/pgtable.h>
@@ -99,6 +100,7 @@
 #include <asm/mpc10x.h>
 #include <asm/pci-bridge.h>
 #include <asm/kgdb.h>
+#include <asm/ppc_sys.h>
 
 #include "sandpoint.h"
 
@@ -305,6 +307,24 @@
 	/* Lookup PCI host bridges */
 	sandpoint_find_bridges();
 
+	if (strncmp (cur_ppc_sys_spec->ppc_sys_name, "8245", 4) == 0)
+	{
+		bd_t *bp = (bd_t *)__res;
+		struct plat_serial8250_port *pdata;
+		pdata = (struct plat_serial8250_port *) ppc_sys_get_pdata(MPC10X_DUART);
+
+		if (pdata)
+		{
+			pdata[0].uartclk = bp->bi_busfreq;
+			pdata[0].membase = ioremap(pdata[0].mapbase, 0x100);
+
+			/* this disables the 2nd serial port on the DUART
+			 * since the sandpoint does not have it connected */
+			pdata[1].uartclk = 0;
+			pdata[1].irq = 0;
+			pdata[1].mapbase = 0;
+		}
+
 	printk(KERN_INFO "Motorola SPS Sandpoint Test Platform\n");
 	printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n");
 
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index 96acf85..dec5bf4 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -92,7 +92,7 @@
 obj-$(CONFIG_SERIAL_TEXT_DEBUG)	+= mv64x60_dbg.o
 endif
 obj-$(CONFIG_BOOTX_TEXT)	+= btext.o
-obj-$(CONFIG_MPC10X_BRIDGE)     += mpc10x_common.o indirect_pci.o
+obj-$(CONFIG_MPC10X_BRIDGE)	+= mpc10x_common.o indirect_pci.o ppc_sys.o
 obj-$(CONFIG_MPC10X_OPENPIC)	+= open_pic.o
 obj-$(CONFIG_40x)		+= dcr.o
 obj-$(CONFIG_BOOKE)		+= dcr.o
@@ -107,6 +107,7 @@
 ifeq ($(CONFIG_83xx),y)
 obj-$(CONFIG_PCI)		+= indirect_pci.o pci_auto.o
 endif
+obj-$(CONFIG_MPC8548_CDS)	+= todc_time.o
 obj-$(CONFIG_MPC8555_CDS)	+= todc_time.o
 obj-$(CONFIG_PPC_MPC52xx)	+= mpc52xx_setup.o mpc52xx_pic.o \
 					mpc52xx_sys.o mpc52xx_devices.o ppc_sys.o
diff --git a/arch/ppc/syslib/cpm2_common.c b/arch/ppc/syslib/cpm2_common.c
index ea5e770..4c19a4a 100644
--- a/arch/ppc/syslib/cpm2_common.c
+++ b/arch/ppc/syslib/cpm2_common.c
@@ -21,8 +21,8 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
-#include <linux/bootmem.h>
 #include <linux/module.h>
+#include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/mpc8260.h>
 #include <asm/page.h>
diff --git a/arch/ppc/syslib/indirect_pci.c b/arch/ppc/syslib/indirect_pci.c
index a5a7526..e714884 100644
--- a/arch/ppc/syslib/indirect_pci.c
+++ b/arch/ppc/syslib/indirect_pci.c
@@ -14,7 +14,6 @@
 #include <linux/delay.h>
 #include <linux/string.h>
 #include <linux/init.h>
-#include <linux/bootmem.h>
 
 #include <asm/io.h>
 #include <asm/prom.h>
diff --git a/arch/ppc/syslib/ipic.c b/arch/ppc/syslib/ipic.c
index 580ed65..8f01e0f 100644
--- a/arch/ppc/syslib/ipic.c
+++ b/arch/ppc/syslib/ipic.c
@@ -79,7 +79,7 @@
 		.prio_mask = 7,
 	},
 	[17] = {
-		.pend	= IPIC_SIPNR_H,
+		.pend	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SEFCR,
@@ -87,7 +87,7 @@
 		.prio_mask = 5,
 	},
 	[18] = {
-		.pend	= IPIC_SIPNR_H,
+		.pend	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SEFCR,
@@ -95,7 +95,7 @@
 		.prio_mask = 6,
 	},
 	[19] = {
-		.pend	= IPIC_SIPNR_H,
+		.pend	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_A,
 		.force	= IPIC_SEFCR,
@@ -103,7 +103,7 @@
 		.prio_mask = 7,
 	},
 	[20] = {
-		.pend	= IPIC_SIPNR_H,
+		.pend	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SEFCR,
@@ -111,7 +111,7 @@
 		.prio_mask = 4,
 	},
 	[21] = {
-		.pend	= IPIC_SIPNR_H,
+		.pend	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SEFCR,
@@ -119,7 +119,7 @@
 		.prio_mask = 5,
 	},
 	[22] = {
-		.pend	= IPIC_SIPNR_H,
+		.pend	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SEFCR,
@@ -127,7 +127,7 @@
 		.prio_mask = 6,
 	},
 	[23] = {
-		.pend	= IPIC_SIPNR_H,
+		.pend	= IPIC_SEPNR,
 		.mask	= IPIC_SEMSR,
 		.prio	= IPIC_SMPRR_B,
 		.force	= IPIC_SEFCR,
diff --git a/arch/ppc/syslib/mpc10x_common.c b/arch/ppc/syslib/mpc10x_common.c
index fd93adf..8fc5f41 100644
--- a/arch/ppc/syslib/mpc10x_common.c
+++ b/arch/ppc/syslib/mpc10x_common.c
@@ -21,6 +21,9 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
+#include <linux/serial_8250.h>
+#include <linux/fsl_devices.h>
+#include <linux/device.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
@@ -30,16 +33,7 @@
 #include <asm/pci-bridge.h>
 #include <asm/open_pic.h>
 #include <asm/mpc10x.h>
-#include <asm/ocp.h>
-
-/* The OCP structure is fixed by code below, before OCP initialises.
-   paddr depends on where the board places the EUMB.
-    - fixed in mpc10x_bridge_init().
-   irq depends on two things:
-    > does the board use the EPIC at all? (PCORE does not).
-    > is the EPIC in serial or parallel mode?
-    - fixed in mpc10x_set_openpic().
-*/
+#include <asm/ppc_sys.h>
 
 #ifdef CONFIG_MPC10X_OPENPIC
 #ifdef CONFIG_EPIC_SERIAL_MODE
@@ -50,35 +44,140 @@
 #define MPC10X_I2C_IRQ (EPIC_IRQ_BASE + NUM_8259_INTERRUPTS)
 #define MPC10X_DMA0_IRQ (EPIC_IRQ_BASE + 1 + NUM_8259_INTERRUPTS)
 #define MPC10X_DMA1_IRQ (EPIC_IRQ_BASE + 2 + NUM_8259_INTERRUPTS)
+#define MPC10X_UART0_IRQ (EPIC_IRQ_BASE + 4 + NUM_8259_INTERRUPTS)
 #else
-#define MPC10X_I2C_IRQ OCP_IRQ_NA
-#define MPC10X_DMA0_IRQ OCP_IRQ_NA
-#define MPC10X_DMA1_IRQ OCP_IRQ_NA
+#define MPC10X_I2C_IRQ -1
+#define MPC10X_DMA0_IRQ -1
+#define MPC10X_DMA1_IRQ -1
+#define MPC10X_UART0_IRQ -1
 #endif
 
-
-struct ocp_def core_ocp[] = {
-	{ .vendor	= OCP_VENDOR_INVALID
-	}
+static struct fsl_i2c_platform_data mpc10x_i2c_pdata = {
+	.device_flags		= 0,
 };
 
-static struct ocp_fs_i2c_data mpc10x_i2c_data = {
-	.flags		= 0
-};
-static struct ocp_def mpc10x_i2c_ocp = {
-	.vendor		= OCP_VENDOR_MOTOROLA,
-	.function	= OCP_FUNC_IIC,
-	.index		= 0,
-	.additions	= &mpc10x_i2c_data
+static struct plat_serial8250_port serial_platform_data[] = {
+	[0] = {
+		.mapbase	= 0x4500,
+		.iotype		= UPIO_MEM,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+	},
+	[1] = {
+		.mapbase	= 0x4600,
+		.iotype		= UPIO_MEM,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+	},
+	{ },
 };
 
-static struct ocp_def mpc10x_dma_ocp[2] = {
-{	.vendor		= OCP_VENDOR_MOTOROLA,
-	.function	= OCP_FUNC_DMA,
-	.index		= 0 },
-{	.vendor		= OCP_VENDOR_MOTOROLA,
-	.function	= OCP_FUNC_DMA,
-	.index		= 1 }
+struct platform_device ppc_sys_platform_devices[] = {
+	[MPC10X_IIC1] = {
+		.name 	= "fsl-i2c",
+		.id	= 1,
+		.dev.platform_data = &mpc10x_i2c_pdata,
+		.num_resources = 2,
+		.resource = (struct resource[]) {
+			{
+				.start 	= MPC10X_EUMB_I2C_OFFSET,
+				.end	= MPC10X_EUMB_I2C_OFFSET +
+		                            MPC10X_EUMB_I2C_SIZE - 1,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.flags 	= IORESOURCE_IRQ
+			},
+		},
+	},
+	[MPC10X_DMA0] = {
+		.name	= "fsl-dma",
+		.id	= 0,
+		.num_resources = 2,
+		.resource = (struct resource[]) {
+			{
+				.start 	= MPC10X_EUMB_DMA_OFFSET + 0x10,
+				.end	= MPC10X_EUMB_DMA_OFFSET + 0x1f,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC10X_DMA1] = {
+		.name	= "fsl-dma",
+		.id	= 1,
+		.num_resources = 2,
+		.resource = (struct resource[]) {
+			{
+				.start	= MPC10X_EUMB_DMA_OFFSET + 0x20,
+				.end	= MPC10X_EUMB_DMA_OFFSET + 0x2f,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC10X_DMA1] = {
+		.name	= "fsl-dma",
+		.id	= 1,
+		.num_resources = 2,
+		.resource = (struct resource[]) {
+			{
+				.start	= MPC10X_EUMB_DMA_OFFSET + 0x20,
+				.end	= MPC10X_EUMB_DMA_OFFSET + 0x2f,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC10X_DUART] = {
+		.name = "serial8250",
+		.id	= 0,
+		.dev.platform_data = serial_platform_data,
+	},
+};
+
+/* We use the PCI ID to match on */
+struct ppc_sys_spec *cur_ppc_sys_spec;
+struct ppc_sys_spec ppc_sys_specs[] = {
+	{
+		.ppc_sys_name 	= "8245",
+		.mask		= 0xFFFFFFFF,
+		.value		= MPC10X_BRIDGE_8245,
+		.num_devices	= 4,
+		.device_list	= (enum ppc_sys_devices[])
+		{
+			MPC10X_IIC1, MPC10X_DMA0, MPC10X_DMA1, MPC10X_DUART,
+		},
+	},
+	{
+		.ppc_sys_name 	= "8240",
+		.mask		= 0xFFFFFFFF,
+		.value		= MPC10X_BRIDGE_8240,
+		.num_devices	= 3,
+		.device_list	= (enum ppc_sys_devices[])
+		{
+			MPC10X_IIC1, MPC10X_DMA0, MPC10X_DMA1,
+		},
+	},
+	{
+		.ppc_sys_name	= "107",
+		.mask		= 0xFFFFFFFF,
+		.value		= MPC10X_BRIDGE_107,
+		.num_devices	= 3,
+		.device_list	= (enum ppc_sys_devices[])
+		{
+			MPC10X_IIC1, MPC10X_DMA0, MPC10X_DMA1,
+		},
+	},
+	{       /* default match */
+		.ppc_sys_name   = "",
+		.mask           = 0x00000000,
+		.value          = 0x00000000,
+	},
 };
 
 /* Set resources to match bridge memory map */
@@ -132,7 +231,7 @@
 		   uint new_map,
 		   uint phys_eumb_base)
 {
-	int	host_bridge, picr1, picr1_bit;
+	int	host_bridge, picr1, picr1_bit, i;
 	ulong	pci_config_addr, pci_config_data;
 	u_char	pir, byte;
 
@@ -273,7 +372,7 @@
 			printk("Host bridge in Agent mode\n");
 			/* Read or Set LMBAR & PCSRBAR? */
 		}
-		
+
 		/* Set base addr of the 8240/107 EUMB.  */
 		early_write_config_dword(hose,
 					 0,
@@ -287,17 +386,6 @@
 			ioremap(phys_eumb_base + MPC10X_EUMB_EPIC_OFFSET,
 				MPC10X_EUMB_EPIC_SIZE);
 #endif
-		mpc10x_i2c_ocp.paddr = phys_eumb_base + MPC10X_EUMB_I2C_OFFSET;
-		mpc10x_i2c_ocp.irq = MPC10X_I2C_IRQ;
-		ocp_add_one_device(&mpc10x_i2c_ocp);
-		mpc10x_dma_ocp[0].paddr = phys_eumb_base +
-					MPC10X_EUMB_DMA_OFFSET + 0x100;
-		mpc10x_dma_ocp[0].irq = MPC10X_DMA0_IRQ;
-		ocp_add_one_device(&mpc10x_dma_ocp[0]);
-		mpc10x_dma_ocp[1].paddr = phys_eumb_base +
-					MPC10X_EUMB_DMA_OFFSET + 0x200;
-		mpc10x_dma_ocp[1].irq = MPC10X_DMA1_IRQ;
-		ocp_add_one_device(&mpc10x_dma_ocp[1]);
 	}
 
 #ifdef CONFIG_MPC10X_STORE_GATHERING
@@ -306,6 +394,29 @@
 	mpc10x_disable_store_gathering(hose);
 #endif
 
+	/* setup platform devices for MPC10x bridges */
+	identify_ppc_sys_by_id (host_bridge);
+
+	for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) {
+		unsigned int dev_id = cur_ppc_sys_spec->device_list[i];
+		ppc_sys_fixup_mem_resource(&ppc_sys_platform_devices[dev_id],
+			phys_eumb_base);
+	}
+
+	/* IRQ's are determined at runtime */
+	ppc_sys_platform_devices[MPC10X_IIC1].resource[1].start = MPC10X_I2C_IRQ;
+	ppc_sys_platform_devices[MPC10X_IIC1].resource[1].end = MPC10X_I2C_IRQ;
+	ppc_sys_platform_devices[MPC10X_DMA0].resource[1].start = MPC10X_DMA0_IRQ;
+	ppc_sys_platform_devices[MPC10X_DMA0].resource[1].end = MPC10X_DMA0_IRQ;
+	ppc_sys_platform_devices[MPC10X_DMA1].resource[1].start = MPC10X_DMA1_IRQ;
+	ppc_sys_platform_devices[MPC10X_DMA1].resource[1].end = MPC10X_DMA1_IRQ;
+
+	serial_platform_data[0].mapbase += phys_eumb_base;
+	serial_platform_data[0].irq = MPC10X_UART0_IRQ;
+
+	serial_platform_data[1].mapbase += phys_eumb_base;
+	serial_platform_data[1].irq = MPC10X_UART0_IRQ + 1;
+
 	/*
 	 * 8240 erratum 26, 8241/8245 erratum 29, 107 erratum 23: speculative
 	 * PCI reads may return stale data so turn off.
@@ -330,7 +441,7 @@
 	 * 8245 (Rev 2., dated 10/2003) says PICR2[0] is reserverd.
 	 */
 	if (host_bridge == MPC10X_BRIDGE_8245) {
-		ulong	picr2;
+		u32	picr2;
 
 		early_read_config_dword(hose, 0, PCI_DEVFN(0,0),
 			MPC10X_CFG_PICR2_REG, &picr2);
@@ -504,6 +615,8 @@
 	openpic_set_sources(EPIC_IRQ_BASE, 3, OpenPIC_Addr + 0x11020);
 	/* Skip reserved space and map Message Unit Interrupt (I2O) */
 	openpic_set_sources(EPIC_IRQ_BASE + 3, 1, OpenPIC_Addr + 0x110C0);
+	/* Skip reserved space and map Serial Interupts */
+	openpic_set_sources(EPIC_IRQ_BASE + 4, 2, OpenPIC_Addr + 0x11120);
 
 	openpic_init(NUM_8259_INTERRUPTS);
 }
diff --git a/arch/ppc/syslib/mpc85xx_devices.c b/arch/ppc/syslib/mpc85xx_devices.c
index 1e658ef..8af322d 100644
--- a/arch/ppc/syslib/mpc85xx_devices.c
+++ b/arch/ppc/syslib/mpc85xx_devices.c
@@ -40,6 +40,42 @@
 	.phy_reg_addr = MPC85xx_ENET1_OFFSET,
 };
 
+static struct gianfar_platform_data mpc85xx_etsec1_pdata = {
+	.device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+	    FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON |
+	    FSL_GIANFAR_DEV_HAS_MULTI_INTR |
+	    FSL_GIANFAR_DEV_HAS_CSUM | FSL_GIANFAR_DEV_HAS_VLAN |
+	    FSL_GIANFAR_DEV_HAS_EXTENDED_HASH,
+	.phy_reg_addr = MPC85xx_ENET1_OFFSET,
+};
+
+static struct gianfar_platform_data mpc85xx_etsec2_pdata = {
+	.device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+	    FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON |
+	    FSL_GIANFAR_DEV_HAS_MULTI_INTR |
+	    FSL_GIANFAR_DEV_HAS_CSUM | FSL_GIANFAR_DEV_HAS_VLAN |
+	    FSL_GIANFAR_DEV_HAS_EXTENDED_HASH,
+	.phy_reg_addr = MPC85xx_ENET1_OFFSET,
+};
+
+static struct gianfar_platform_data mpc85xx_etsec3_pdata = {
+	.device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+	    FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON |
+	    FSL_GIANFAR_DEV_HAS_MULTI_INTR |
+	    FSL_GIANFAR_DEV_HAS_CSUM | FSL_GIANFAR_DEV_HAS_VLAN |
+	    FSL_GIANFAR_DEV_HAS_EXTENDED_HASH,
+	.phy_reg_addr = MPC85xx_ENET1_OFFSET,
+};
+
+static struct gianfar_platform_data mpc85xx_etsec4_pdata = {
+	.device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+	    FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON |
+	    FSL_GIANFAR_DEV_HAS_MULTI_INTR |
+	    FSL_GIANFAR_DEV_HAS_CSUM | FSL_GIANFAR_DEV_HAS_VLAN |
+	    FSL_GIANFAR_DEV_HAS_EXTENDED_HASH,
+	.phy_reg_addr = MPC85xx_ENET1_OFFSET,
+};
+
 static struct gianfar_platform_data mpc85xx_fec_pdata = {
 	.phy_reg_addr = MPC85xx_ENET1_OFFSET,
 };
@@ -48,6 +84,10 @@
 	.device_flags = FSL_I2C_DEV_SEPARATE_DFSRR,
 };
 
+static struct fsl_i2c_platform_data mpc85xx_fsl_i2c2_pdata = {
+	.device_flags = FSL_I2C_DEV_SEPARATE_DFSRR,
+};
+
 static struct plat_serial8250_port serial_platform_data[] = {
 	[0] = {
 		.mapbase	= 0x4500,
@@ -281,7 +321,6 @@
 			},
 		},
 	},
-#ifdef CONFIG_CPM2
 	[MPC85xx_CPM_FCC1] = {
 		.name = "fsl-cpm-fcc",
 		.id	= 1,
@@ -535,7 +574,151 @@
 			},
 		},
 	},
-#endif /* CONFIG_CPM2 */
+	[MPC85xx_eTSEC1] = {
+		.name = "fsl-gianfar",
+		.id	= 1,
+		.dev.platform_data = &mpc85xx_etsec1_pdata,
+		.num_resources	 = 4,
+		.resource = (struct resource[]) {
+			{
+				.start	= MPC85xx_ENET1_OFFSET,
+				.end	= MPC85xx_ENET1_OFFSET +
+						MPC85xx_ENET1_SIZE - 1,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.name	= "tx",
+				.start	= MPC85xx_IRQ_TSEC1_TX,
+				.end	= MPC85xx_IRQ_TSEC1_TX,
+				.flags	= IORESOURCE_IRQ,
+			},
+			{
+				.name	= "rx",
+				.start	= MPC85xx_IRQ_TSEC1_RX,
+				.end	= MPC85xx_IRQ_TSEC1_RX,
+				.flags	= IORESOURCE_IRQ,
+			},
+			{
+				.name	= "error",
+				.start	= MPC85xx_IRQ_TSEC1_ERROR,
+				.end	= MPC85xx_IRQ_TSEC1_ERROR,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC85xx_eTSEC2] = {
+		.name = "fsl-gianfar",
+		.id	= 2,
+		.dev.platform_data = &mpc85xx_etsec2_pdata,
+		.num_resources	 = 4,
+		.resource = (struct resource[]) {
+			{
+				.start	= MPC85xx_ENET2_OFFSET,
+				.end	= MPC85xx_ENET2_OFFSET +
+						MPC85xx_ENET2_SIZE - 1,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.name	= "tx",
+				.start	= MPC85xx_IRQ_TSEC2_TX,
+				.end	= MPC85xx_IRQ_TSEC2_TX,
+				.flags	= IORESOURCE_IRQ,
+			},
+			{
+				.name	= "rx",
+				.start	= MPC85xx_IRQ_TSEC2_RX,
+				.end	= MPC85xx_IRQ_TSEC2_RX,
+				.flags	= IORESOURCE_IRQ,
+			},
+			{
+				.name	= "error",
+				.start	= MPC85xx_IRQ_TSEC2_ERROR,
+				.end	= MPC85xx_IRQ_TSEC2_ERROR,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC85xx_eTSEC3] = {
+		.name = "fsl-gianfar",
+		.id	= 3,
+		.dev.platform_data = &mpc85xx_etsec3_pdata,
+		.num_resources	 = 4,
+		.resource = (struct resource[]) {
+			{
+				.start	= MPC85xx_ENET3_OFFSET,
+				.end	= MPC85xx_ENET3_OFFSET +
+						MPC85xx_ENET3_SIZE - 1,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.name	= "tx",
+				.start	= MPC85xx_IRQ_TSEC3_TX,
+				.end	= MPC85xx_IRQ_TSEC3_TX,
+				.flags	= IORESOURCE_IRQ,
+			},
+			{
+				.name	= "rx",
+				.start	= MPC85xx_IRQ_TSEC3_RX,
+				.end	= MPC85xx_IRQ_TSEC3_RX,
+				.flags	= IORESOURCE_IRQ,
+			},
+			{
+				.name	= "error",
+				.start	= MPC85xx_IRQ_TSEC3_ERROR,
+				.end	= MPC85xx_IRQ_TSEC3_ERROR,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC85xx_eTSEC4] = {
+		.name = "fsl-gianfar",
+		.id	= 4,
+		.dev.platform_data = &mpc85xx_etsec4_pdata,
+		.num_resources	 = 4,
+		.resource = (struct resource[]) {
+			{
+				.start	= 0x27000,
+				.end	= 0x27fff,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.name	= "tx",
+				.start	= MPC85xx_IRQ_TSEC4_TX,
+				.end	= MPC85xx_IRQ_TSEC4_TX,
+				.flags	= IORESOURCE_IRQ,
+			},
+			{
+				.name	= "rx",
+				.start	= MPC85xx_IRQ_TSEC4_RX,
+				.end	= MPC85xx_IRQ_TSEC4_RX,
+				.flags	= IORESOURCE_IRQ,
+			},
+			{
+				.name	= "error",
+				.start	= MPC85xx_IRQ_TSEC4_ERROR,
+				.end	= MPC85xx_IRQ_TSEC4_ERROR,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC85xx_IIC2] = {
+		.name = "fsl-i2c",
+		.id	= 2,
+		.dev.platform_data = &mpc85xx_fsl_i2c2_pdata,
+		.num_resources	 = 2,
+		.resource = (struct resource[]) {
+			{
+				.start	= 0x03100,
+				.end	= 0x031ff,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.start	= MPC85xx_IRQ_IIC1,
+				.end	= MPC85xx_IRQ_IIC1,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
 };
 
 static int __init mach_mpc85xx_fixup(struct platform_device *pdev)
diff --git a/arch/ppc/syslib/mpc85xx_sys.c b/arch/ppc/syslib/mpc85xx_sys.c
index d806a92..6e3184a 100644
--- a/arch/ppc/syslib/mpc85xx_sys.c
+++ b/arch/ppc/syslib/mpc85xx_sys.c
@@ -110,6 +110,111 @@
 			MPC85xx_CPM_USB,
 		},
 	},
+	/* SVRs on 8548 rev1.0 matches for 8548/8547/8545 */
+	{
+		.ppc_sys_name	= "8548E",
+		.mask 		= 0xFFFF00F0,
+		.value 		= 0x80390010,
+		.num_devices	= 13,
+		.device_list	= (enum ppc_sys_devices[])
+		{
+			MPC85xx_eTSEC1, MPC85xx_eTSEC2, MPC85xx_eTSEC3,
+			MPC85xx_eTSEC4, MPC85xx_IIC1, MPC85xx_IIC2,
+			MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+			MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_SEC2,
+		},
+	},
+	{
+		.ppc_sys_name	= "8548",
+		.mask 		= 0xFFFF00F0,
+		.value 		= 0x80310010,
+		.num_devices	= 12,
+		.device_list	= (enum ppc_sys_devices[])
+		{
+			MPC85xx_eTSEC1, MPC85xx_eTSEC2, MPC85xx_eTSEC3,
+			MPC85xx_eTSEC4, MPC85xx_IIC1, MPC85xx_IIC2,
+			MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+			MPC85xx_PERFMON, MPC85xx_DUART,
+		},
+	},
+	{
+		.ppc_sys_name	= "8547E",
+		.mask 		= 0xFFFF00F0,
+		.value 		= 0x80390010,
+		.num_devices	= 13,
+		.device_list	= (enum ppc_sys_devices[])
+		{
+			MPC85xx_eTSEC1, MPC85xx_eTSEC2, MPC85xx_eTSEC3,
+			MPC85xx_eTSEC4, MPC85xx_IIC1, MPC85xx_IIC2,
+			MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+			MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_SEC2,
+		},
+	},
+	{
+		.ppc_sys_name	= "8547",
+		.mask 		= 0xFFFF00F0,
+		.value 		= 0x80310010,
+		.num_devices	= 12,
+		.device_list	= (enum ppc_sys_devices[])
+		{
+			MPC85xx_eTSEC1, MPC85xx_eTSEC2, MPC85xx_eTSEC3,
+			MPC85xx_eTSEC4, MPC85xx_IIC1, MPC85xx_IIC2,
+			MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+			MPC85xx_PERFMON, MPC85xx_DUART,
+		},
+	},
+	{
+		.ppc_sys_name	= "8545E",
+		.mask 		= 0xFFFF00F0,
+		.value 		= 0x80390010,
+		.num_devices	= 11,
+		.device_list	= (enum ppc_sys_devices[])
+		{
+			MPC85xx_eTSEC1, MPC85xx_eTSEC2,
+			MPC85xx_IIC1, MPC85xx_IIC2,
+			MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+			MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_SEC2,
+		},
+	},
+	{
+		.ppc_sys_name	= "8545",
+		.mask 		= 0xFFFF00F0,
+		.value 		= 0x80310010,
+		.num_devices	= 10,
+		.device_list	= (enum ppc_sys_devices[])
+		{
+			MPC85xx_eTSEC1, MPC85xx_eTSEC2,
+			MPC85xx_IIC1, MPC85xx_IIC2,
+			MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+			MPC85xx_PERFMON, MPC85xx_DUART,
+		},
+	},
+	{
+		.ppc_sys_name	= "8543E",
+		.mask 		= 0xFFFF00F0,
+		.value 		= 0x803A0010,
+		.num_devices	= 11,
+		.device_list	= (enum ppc_sys_devices[])
+		{
+			MPC85xx_eTSEC1, MPC85xx_eTSEC2,
+			MPC85xx_IIC1, MPC85xx_IIC2,
+			MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+			MPC85xx_PERFMON, MPC85xx_DUART, MPC85xx_SEC2,
+		},
+	},
+	{
+		.ppc_sys_name	= "8543",
+		.mask 		= 0xFFFF00F0,
+		.value 		= 0x80320010,
+		.num_devices	= 10,
+		.device_list	= (enum ppc_sys_devices[])
+		{
+			MPC85xx_eTSEC1, MPC85xx_eTSEC2,
+			MPC85xx_IIC1, MPC85xx_IIC2,
+			MPC85xx_DMA0, MPC85xx_DMA1, MPC85xx_DMA2, MPC85xx_DMA3,
+			MPC85xx_PERFMON, MPC85xx_DUART,
+		},
+	},
 	{	/* default match */
 		.ppc_sys_name	= "",
 		.mask 		= 0x00000000,
diff --git a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c
index 7b241e7..cc77177 100644
--- a/arch/ppc/syslib/mv64x60.c
+++ b/arch/ppc/syslib/mv64x60.c
@@ -17,7 +17,6 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/string.h>
-#include <linux/bootmem.h>
 #include <linux/spinlock.h>
 #include <linux/mv643xx.h>
 
diff --git a/arch/ppc/syslib/mv64x60_win.c b/arch/ppc/syslib/mv64x60_win.c
index b6f0f5d..5b827e2 100644
--- a/arch/ppc/syslib/mv64x60_win.c
+++ b/arch/ppc/syslib/mv64x60_win.c
@@ -17,7 +17,6 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/string.h>
-#include <linux/bootmem.h>
 #include <linux/mv643xx.h>
 
 #include <asm/byteorder.h>
diff --git a/arch/ppc/syslib/ocp.c b/arch/ppc/syslib/ocp.c
index a5156c5..e5fd2ae 100644
--- a/arch/ppc/syslib/ocp.c
+++ b/arch/ppc/syslib/ocp.c
@@ -68,7 +68,7 @@
 /* Sysfs support */
 #define OCP_DEF_ATTR(field, format_string)				\
 static ssize_t								\
-show_##field(struct device *dev, char *buf)				\
+show_##field(struct device *dev, struct device_attribute *attr, char *buf)				\
 {									\
 	struct ocp_device *odev = to_ocp_dev(dev);			\
 									\
diff --git a/arch/ppc/syslib/of_device.c b/arch/ppc/syslib/of_device.c
index 46269ed..49c0e34 100644
--- a/arch/ppc/syslib/of_device.c
+++ b/arch/ppc/syslib/of_device.c
@@ -161,7 +161,7 @@
 }
 
 
-static ssize_t dev_show_devspec(struct device *dev, char *buf)
+static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct of_device *ofdev;
 
diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c
index 000ba47..b45d826 100644
--- a/arch/ppc/syslib/open_pic.c
+++ b/arch/ppc/syslib/open_pic.c
@@ -21,7 +21,6 @@
 #include <asm/signal.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/prom.h>
 #include <asm/sections.h>
 #include <asm/open_pic.h>
 #include <asm/i8259.h>
diff --git a/arch/ppc/syslib/open_pic2.c b/arch/ppc/syslib/open_pic2.c
index ea26da0..7e272c5 100644
--- a/arch/ppc/syslib/open_pic2.c
+++ b/arch/ppc/syslib/open_pic2.c
@@ -25,7 +25,6 @@
 #include <asm/signal.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/prom.h>
 #include <asm/sections.h>
 #include <asm/open_pic.h>
 #include <asm/i8259.h>
diff --git a/arch/ppc/syslib/ppc4xx_kgdb.c b/arch/ppc/syslib/ppc4xx_kgdb.c
deleted file mode 100644
index fe8668b..0000000
--- a/arch/ppc/syslib/ppc4xx_kgdb.c
+++ /dev/null
@@ -1,124 +0,0 @@
-#include <linux/config.h>
-#include <linux/types.h>
-#include <asm/ibm4xx.h>
-#include <linux/kernel.h>
-
-
-
-#define LSR_DR		0x01 /* Data ready */
-#define LSR_OE		0x02 /* Overrun */
-#define LSR_PE		0x04 /* Parity error */
-#define LSR_FE		0x08 /* Framing error */
-#define LSR_BI		0x10 /* Break */
-#define LSR_THRE	0x20 /* Xmit holding register empty */
-#define LSR_TEMT	0x40 /* Xmitter empty */
-#define LSR_ERR		0x80 /* Error */
-
-#include <platforms/4xx/ibm_ocp.h>
-
-extern struct NS16550* COM_PORTS[];
-#ifndef NULL
-#define NULL 0x00
-#endif
-
-static volatile struct NS16550 *kgdb_debugport = NULL;
-
-volatile struct NS16550 *
-NS16550_init(int chan)
-{
-	volatile struct NS16550 *com_port;
-	int quot;
-#ifdef BASE_BAUD
-	quot = BASE_BAUD / 9600;
-#else
-	quot = 0x000c; /* 0xc = 9600 baud (on a pc) */
-#endif
-
-	com_port = (struct NS16550 *) COM_PORTS[chan];
-
-	com_port->lcr = 0x00;
-	com_port->ier = 0xFF;
-	com_port->ier = 0x00;
-	com_port->lcr = com_port->lcr | 0x80; /* Access baud rate */
-	com_port->dll = ( quot & 0x00ff ); /* 0xc = 9600 baud */
-	com_port->dlm = ( quot & 0xff00 ) >> 8;
-	com_port->lcr = 0x03; /* 8 data, 1 stop, no parity */
-	com_port->mcr = 0x00; /* RTS/DTR */
-	com_port->fcr = 0x07; /* Clear & enable FIFOs */
-
-	return( com_port );
-}
-
-
-void
-NS16550_putc(volatile struct NS16550 *com_port, unsigned char c)
-{
-	while ((com_port->lsr & LSR_THRE) == 0)
-		;
-	com_port->thr = c;
-	return;
-}
-
-unsigned char
-NS16550_getc(volatile struct NS16550 *com_port)
-{
-	while ((com_port->lsr & LSR_DR) == 0)
-		;
-	return (com_port->rbr);
-}
-
-unsigned char
-NS16550_tstc(volatile struct NS16550 *com_port)
-{
-	return ((com_port->lsr & LSR_DR) != 0);
-}
-
-
-#if defined(CONFIG_KGDB_TTYS0)
-#define KGDB_PORT 0
-#elif defined(CONFIG_KGDB_TTYS1)
-#define KGDB_PORT 1
-#elif defined(CONFIG_KGDB_TTYS2)
-#define KGDB_PORT 2
-#elif defined(CONFIG_KGDB_TTYS3)
-#define KGDB_PORT 3
-#else
-#error "invalid kgdb_tty port"
-#endif
-
-void putDebugChar( unsigned char c )
-{
-	if ( kgdb_debugport == NULL )
-		kgdb_debugport = NS16550_init(KGDB_PORT);
-	NS16550_putc( kgdb_debugport, c );
-}
-
-int getDebugChar( void )
-{
-	if (kgdb_debugport == NULL)
-		kgdb_debugport = NS16550_init(KGDB_PORT);
-
-	return(NS16550_getc(kgdb_debugport));
-}
-
-void kgdb_interruptible(int enable)
-{
-	return;
-}
-
-void putDebugString(char* str)
-{
-	while (*str != '\0') {
-		putDebugChar(*str);
-		str++;
-	}
-	putDebugChar('\r');
-	return;
-}
-
-void
-kgdb_map_scc(void)
-{
-	printk("kgdb init \n");
-	kgdb_debugport = NS16550_init(KGDB_PORT);
-}
diff --git a/arch/ppc/syslib/ppc83xx_setup.c b/arch/ppc/syslib/ppc83xx_setup.c
index 843cf88..602a868 100644
--- a/arch/ppc/syslib/ppc83xx_setup.c
+++ b/arch/ppc/syslib/ppc83xx_setup.c
@@ -23,7 +23,6 @@
 #include <linux/serial_core.h>
 #include <linux/serial_8250.h>
 
-#include <asm/prom.h>
 #include <asm/time.h>
 #include <asm/mpc83xx.h>
 #include <asm/mmu.h>
diff --git a/arch/ppc/syslib/ppc85xx_setup.c b/arch/ppc/syslib/ppc85xx_setup.c
index f3277f4..ca95d79 100644
--- a/arch/ppc/syslib/ppc85xx_setup.c
+++ b/arch/ppc/syslib/ppc85xx_setup.c
@@ -23,7 +23,6 @@
 #include <linux/serial_core.h>
 #include <linux/serial_8250.h>
 
-#include <asm/prom.h>
 #include <asm/time.h>
 #include <asm/mpc85xx.h>
 #include <asm/immap_85xx.h>
@@ -33,6 +32,8 @@
 
 #include <syslib/ppc85xx_setup.h>
 
+extern void abort(void);
+
 /* Return the amount of memory */
 unsigned long __init
 mpc85xx_find_end_of_memory(void)
@@ -133,7 +134,7 @@
 
 #ifdef CONFIG_PCI
 
-#if defined(CONFIG_MPC8555_CDS)
+#if defined(CONFIG_MPC8555_CDS) || defined(CONFIG_MPC8548_CDS)
 extern void mpc85xx_cds_enable_via(struct pci_controller *hose);
 extern void mpc85xx_cds_fixup_via(struct pci_controller *hose);
 #endif
@@ -308,14 +309,14 @@
 
 	ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 
-#if defined(CONFIG_MPC8555_CDS)
+#if defined(CONFIG_MPC8555_CDS) || defined(CONFIG_MPC8548_CDS)
 	/* Pre pciauto_bus_scan VIA init */
 	mpc85xx_cds_enable_via(hose_a);
 #endif
 
 	hose_a->last_busno = pciauto_bus_scan(hose_a, hose_a->first_busno);
 
-#if defined(CONFIG_MPC8555_CDS)
+#if defined(CONFIG_MPC8555_CDS) || defined(CONFIG_MPC8548_CDS)
 	/* Post pciauto_bus_scan VIA fixup */
 	mpc85xx_cds_fixup_via(hose_a);
 #endif
diff --git a/arch/ppc/xmon/xmon.c b/arch/ppc/xmon/xmon.c
index 8565f49..be7869e 100644
--- a/arch/ppc/xmon/xmon.c
+++ b/arch/ppc/xmon/xmon.c
@@ -9,6 +9,7 @@
 #include <linux/smp.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
+#include <linux/kallsyms.h>
 #include <asm/ptrace.h>
 #include <asm/string.h>
 #include <asm/prom.h>
@@ -93,8 +94,7 @@
 static unsigned read_spr(int);
 static void write_spr(int, unsigned);
 static void super_regs(void);
-static void print_sysmap(void);
-static void sysmap_lookup(void);
+static void symbol_lookup(void);
 static void remove_bpts(void);
 static void insert_bpts(void);
 static struct bpt *at_breakpoint(unsigned pc);
@@ -103,7 +103,6 @@
 #ifdef CONFIG_SMP
 static void cpu_cmd(void);
 #endif /* CONFIG_SMP */
-static int pretty_print_addr(unsigned long addr);
 static void csum(void);
 #ifdef CONFIG_BOOTX_TEXT
 static void vidcmds(void);
@@ -120,8 +119,6 @@
 
 extern void xmon_enter(void);
 extern void xmon_leave(void);
-extern char* xmon_find_symbol(unsigned long addr, unsigned long* saddr);
-extern unsigned long xmon_symbol_to_addr(char* symbol);
 
 static unsigned start_tb[NR_CPUS][2];
 static unsigned stop_tb[NR_CPUS][2];
@@ -148,7 +145,6 @@
   mm	move a block of memory\n\
   ms	set a block of memory\n\
   md	compare two blocks of memory\n\
-  M	print System.map\n\
   r	print registers\n\
   S	print special registers\n\
   t	print backtrace\n\
@@ -175,6 +171,35 @@
 				     "r" (loops) : "ctr");
 }
 
+/* Print an address in numeric and symbolic form (if possible) */
+static void xmon_print_symbol(unsigned long address, const char *mid,
+			      const char *after)
+{
+	char *modname;
+	const char *name = NULL;
+	unsigned long offset, size;
+	static char tmpstr[128];
+
+	printf("%.8lx", address);
+	if (setjmp(bus_error_jmp) == 0) {
+		debugger_fault_handler = handle_fault;
+		sync();
+		name = kallsyms_lookup(address, &size, &offset, &modname,
+				       tmpstr);
+		sync();
+		/* wait a little while to see if we get a machine check */
+		__delay(200);
+	}
+	debugger_fault_handler = NULL;
+
+	if (name) {
+		printf("%s%s+%#lx/%#lx", mid, name, offset, size);
+		if (modname)
+			printf(" [%s]", modname);
+	}
+	printf("%s", after);
+}
+
 static void get_tb(unsigned *p)
 {
 	unsigned hi, lo, hiagain;
@@ -454,7 +479,7 @@
 			dump();
 			break;
 		case 'l':
-			sysmap_lookup();
+			symbol_lookup();
 			break;
 		case 'r':
 			if (excp != NULL)
@@ -466,9 +491,6 @@
 			else
 				excprint(excp);
 			break;
-		case 'M':
-			print_sysmap();
-			break;
 		case 'S':
 			super_regs();
 			break;
@@ -825,20 +847,19 @@
 	for (; sp != 0; sp = stack[0]) {
 		if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
 			break;
-		pretty_print_addr(stack[1]);
-		printf(" ");
+		printf("[%.8lx] ", stack);
+		xmon_print_symbol(stack[1], " ", "\n");
 		if (stack[1] == (unsigned) &ret_from_except
 		    || stack[1] == (unsigned) &ret_from_except_full
 		    || stack[1] == (unsigned) &ret_from_syscall) {
 			if (mread(sp+16, &regs, sizeof(regs)) != sizeof(regs))
 				break;
-			printf("\nexception:%x [%x] %x ", regs.trap, sp+16,
+			printf("exception:%x [%x] %x\n", regs.trap, sp+16,
 			       regs.nip);
 			sp = regs.gpr[1];
 			if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
 				break;
 		}
-		printf("\n");
 	}
 }
 
@@ -859,11 +880,10 @@
 #ifdef CONFIG_SMP
 	printf("cpu %d: ", smp_processor_id());
 #endif /* CONFIG_SMP */
-	printf("vector: %x at pc = ", fp->trap);
-	pretty_print_addr(fp->nip);
-	printf(", lr = ");
-	pretty_print_addr(fp->link);
-	printf("\nmsr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp);
+	printf("vector: %x at pc=", fp->trap);
+	xmon_print_symbol(fp->nip, ": ", ", lr=");
+	xmon_print_symbol(fp->link, ": ", "\n");
+	printf("msr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp);
 	trap = TRAP(fp);
 	if (trap == 0x300 || trap == 0x600)
 		printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
@@ -951,24 +971,6 @@
 extern char dec_exc;
 
 void
-print_sysmap(void)
-{
-	extern char *sysmap;
-	if ( sysmap ) {
-		printf("System.map: \n");
-		if( setjmp(bus_error_jmp) == 0 ) {
-			debugger_fault_handler = handle_fault;
-			sync();
-			xmon_puts(sysmap);
-			sync();
-		}
-		debugger_fault_handler = NULL;
-	}
-	else
-		printf("No System.map\n");
-}
-
-void
 super_regs(void)
 {
 	int i, cmd;
@@ -1738,7 +1740,7 @@
 		printf("invalid register name '%%%s'\n", regname);
 		return 0;
 	} else if (c == '$') {
-		static char symname[64];
+		static char symname[128];
 		int i;
 		for (i=0; i<63; i++) {
 			c = inchar();
@@ -1749,7 +1751,14 @@
 			symname[i] = c;
 		}
 		symname[i++] = 0;
-		*vp = xmon_symbol_to_addr(symname);
+		*vp = 0;
+		if (setjmp(bus_error_jmp) == 0) {
+			debugger_fault_handler = handle_fault;
+			sync();
+			*vp = kallsyms_lookup_name(symname);
+			sync();
+		}
+		debugger_fault_handler = NULL;
 		if (!(*vp)) {
 			printf("unknown symbol\n");
 			return 0;
@@ -1840,169 +1849,34 @@
 	lineptr = str;
 }
 
-void
-sysmap_lookup(void)
+static void
+symbol_lookup(void)
 {
 	int type = inchar();
 	unsigned addr;
-	static char tmp[64];
-	char* cur;
+	static char tmp[128];
 
-	extern char *sysmap;
-	extern unsigned long sysmap_size;
-	if ( !sysmap || !sysmap_size )
-		return;
-
-	switch(type) {
-		case 'a':
-			if (scanhex(&addr)) {
-				pretty_print_addr(addr);
-				printf("\n");
-			}
-			termch = 0;
-			break;
-		case 's':
-			getstring(tmp, 64);
-			if( setjmp(bus_error_jmp) == 0 ) {
-				debugger_fault_handler = handle_fault;
-				sync();
-				cur = sysmap;
-				do {
-					cur = strstr(cur, tmp);
-					if (cur) {
-						static char res[64];
-						char *p, *d;
-						p = cur;
-						while(p > sysmap && *p != 10)
-							p--;
-						if (*p == 10) p++;
-						d = res;
-						while(*p && p < (sysmap + sysmap_size) && *p != 10)
-							*(d++) = *(p++);
-						*(d++) = 0;
-						printf("%s\n", res);
-						cur++;
-					}
-				} while (cur);
-				sync();
-			}
-			debugger_fault_handler = NULL;
-			termch = 0;
-			break;
-	}
-}
-
-static int
-pretty_print_addr(unsigned long addr)
-{
-	char *sym;
-	unsigned long saddr;
-	
-	printf("%08x", addr);
-	sym = xmon_find_symbol(addr, &saddr);
-	if (sym)
-		printf(" (%s+0x%x)", sym, addr-saddr);
-	return (sym != 0);
-}
-
-char*
-xmon_find_symbol(unsigned long addr, unsigned long* saddr)
-{
-	static char rbuffer[64];
-	char *p, *ep, *limit;
-	unsigned long prev, next;
-	char* psym;
-
-	extern char *sysmap;
-	extern unsigned long sysmap_size;
-	if ( !sysmap || !sysmap_size )
-		return NULL;
-	
-	prev = 0;
-	psym = NULL;
-	p = sysmap;
-	limit = p + sysmap_size;
-	if( setjmp(bus_error_jmp) == 0 ) {
-		debugger_fault_handler = handle_fault;
-		sync();
-		do {
-			next = simple_strtoul(p, &p, 16);
-			if (next > addr && prev <= addr) {
-				if (!psym)
-					goto bail;
-				ep = rbuffer;
-				p = psym;
-				while(*p && p < limit && *p == 32)
-					p++;
-				while(*p && p < limit && *p != 10 && (ep - rbuffer) < 63)
-					*(ep++) = *(p++);
-				*(ep++) = 0;
-				if (saddr)
-					*saddr = prev;
-				debugger_fault_handler = NULL;
-				return rbuffer;
-			}
-			prev = next;
-			psym = p;
-			while(*p && p < limit && *p != 10)
-				p++;
-			if (*p) p++;
-		} while(*p && p < limit && next);
-bail:
-		sync();
-	}
-	debugger_fault_handler = NULL;
-	return NULL;
-}
-
-unsigned long
-xmon_symbol_to_addr(char* symbol)
-{
-	char *p, *cur;
-	char *match = NULL;
-	int goodness = 0;
-	int result = 0;
-	
-	extern char *sysmap;
-	extern unsigned long sysmap_size;
-	if ( !sysmap || !sysmap_size )
-		return 0;
-
-	if( setjmp(bus_error_jmp) == 0 ) {
-		debugger_fault_handler = handle_fault;
-		sync();
-		cur = sysmap;
-		while(cur) {
-			cur = strstr(cur, symbol);
-			if (cur) {
-				int gd = 1;
-
-				/* best match if equal, better match if
-				 * begins with
-				 */
-				if (cur == sysmap || *(cur-1) == ' ') {
-					gd++;
-					if (cur[strlen(symbol)] == 10)
-						gd++;
-				}
-				if (gd > goodness) {
-					match = cur;
-					goodness = gd;
-					if (gd == 3)
-						break;
-				}
-				cur++;
-			}
-		}	
-		if (goodness) {
-			p = match;
-			while(p > sysmap && *p != 10)
-				p--;
-			if (*p == 10) p++;
-			result = simple_strtoul(p, &p, 16);
+	switch (type) {
+	case 'a':
+		if (scanhex(&addr))
+			xmon_print_symbol(addr, ": ", "\n");
+		termch = 0;
+		break;
+	case 's':
+		getstring(tmp, 64);
+		if (setjmp(bus_error_jmp) == 0) {
+			debugger_fault_handler = handle_fault;
+			sync();
+			addr = kallsyms_lookup_name(tmp);
+			if (addr)
+				printf("%s: %lx\n", tmp, addr);
+			else
+				printf("Symbol '%s' not found.\n", tmp);
+			sync();
 		}
-		sync();
+		debugger_fault_handler = NULL;
+		termch = 0;
+		break;
 	}
-	debugger_fault_handler = NULL;
-	return result;
-}		
+}
+
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
index 5cb3438..f804f25 100644
--- a/arch/ppc64/Kconfig
+++ b/arch/ppc64/Kconfig
@@ -77,6 +77,10 @@
 	bool "  IBM pSeries & new iSeries"
 	default y
 
+config PPC_BPA
+	bool "  Broadband Processor Architecture"
+	depends on PPC_MULTIPLATFORM
+
 config PPC_PMAC
 	depends on PPC_MULTIPLATFORM
 	bool "  Apple G5 based machines"
@@ -106,6 +110,21 @@
 	bool
 	default y
 
+config XICS
+	depends on PPC_PSERIES
+	bool
+	default y
+
+config MPIC
+	depends on PPC_PSERIES || PPC_PMAC || PPC_MAPLE
+	bool
+	default y
+
+config BPA_IIC
+	depends on PPC_BPA
+	bool
+	default y
+
 # VMX is pSeries only for now until somebody writes the iSeries
 # exception vectors for it
 config ALTIVEC
@@ -123,6 +142,23 @@
 	  processors, that is, which share physical processors between
 	  two or more partitions.
 
+config KEXEC
+	bool "kexec system call (EXPERIMENTAL)"
+	depends on PPC_MULTIPLATFORM && EXPERIMENTAL
+	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
+	  you can start any kernel with it, not just Linux.
+
+	  The name comes from the similiarity to the exec system call.
+
+	  It is an ongoing process to be certain the hardware in a machine
+	  is properly shutdown, so do not be surprised if this code does not
+	  initially work for you.  It may help to enable device hotplugging
+	  support.  As of this writing the exact hardware interface is
+	  strongly in flux, so no good recommendation can be made.
+
 config IBMVIO
 	depends on PPC_PSERIES || PPC_ISERIES
 	bool
@@ -198,13 +234,49 @@
 	  This option enables hardware multithreading on RS64 cpus.
 	  pSeries systems p620 and p660 have such a cpu type.
 
-config DISCONTIGMEM
-	bool "Discontiguous Memory Support"
+config ARCH_SELECT_MEMORY_MODEL
+	def_bool y
+
+config ARCH_FLATMEM_ENABLE
+       def_bool y
+       depends on !NUMA
+
+config ARCH_DISCONTIGMEM_ENABLE
+	def_bool y
 	depends on SMP && PPC_PSERIES
 
+config ARCH_DISCONTIGMEM_DEFAULT
+	def_bool y
+	depends on ARCH_DISCONTIGMEM_ENABLE
+
+config ARCH_FLATMEM_ENABLE
+	def_bool y
+
+config ARCH_SPARSEMEM_ENABLE
+	def_bool y
+	depends on ARCH_DISCONTIGMEM_ENABLE
+
+source "mm/Kconfig"
+
+config HAVE_ARCH_EARLY_PFN_TO_NID
+	def_bool y
+	depends on NEED_MULTIPLE_NODES
+
+# Some NUMA nodes have memory ranges that span
+# other nodes.  Even though a pfn is valid and
+# between a node's start and end pfns, it may not
+# reside on that node.
+#
+# This is a relatively temporary hack that should
+# be able to go away when sparsemem is fully in
+# place
+config NODES_SPAN_OTHER_NODES
+	def_bool y
+	depends on NEED_MULTIPLE_NODES
+
 config NUMA
 	bool "NUMA support"
-	depends on DISCONTIGMEM
+	default y if DISCONTIGMEM || SPARSEMEM
 
 config SCHED_SMT
 	bool "SMT (Hyperthreading) scheduler support"
@@ -215,26 +287,7 @@
 	  when dealing with POWER5 cpus at a cost of slightly increased
 	  overhead in some places. If unsure say N here.
 
-config PREEMPT
-	bool "Preemptible Kernel"
-	help
-	  This option reduces the latency of the kernel when reacting to
-	  real-time or interactive events by allowing a low priority process to
-	  be preempted even if it is in kernel mode executing a system call.
-
-	  Say Y here if you are building a kernel for a desktop, embedded
-	  or real-time system.  Say N if you are unsure.
-
-config PREEMPT_BKL
-	bool "Preempt The Big Kernel Lock"
-	depends on PREEMPT
-	default y
-	help
-	  This option reduces the latency of the kernel by making the
-	  big kernel lock preemptible.
-
-	  Say Y here if you are building a kernel for a desktop system.
-	  Say N if you are unsure.
+source "kernel/Kconfig.preempt"
 
 config EEH
 	bool "PCI Extended Error Handling (EEH)" if EMBEDDED
@@ -256,7 +309,7 @@
 
 config PPC_RTAS
 	bool
-	depends on PPC_PSERIES
+	depends on PPC_PSERIES || PPC_BPA
 	default y
 
 config RTAS_PROC
@@ -323,7 +376,7 @@
 	bool
 
 config PCI
-	bool
+	bool "support for PCI devices" if (EMBEDDED && PPC_ISERIES)
 	default y
 	help
 	  Find out whether your system includes a PCI bus. PCI is the name of
diff --git a/arch/ppc64/Makefile b/arch/ppc64/Makefile
index 691f300..731b847 100644
--- a/arch/ppc64/Makefile
+++ b/arch/ppc64/Makefile
@@ -35,9 +35,9 @@
 CROSS32LD	:= $(LD) -m elf32ppc
 CROSS32OBJCOPY	:= $(OBJCOPY)
 endif
-AS              := $(AS) -a64
-LD              := $(LD) -m elf64ppc
-CC		:= $(CC) -m64
+override AS	+= -a64
+override LD	+= -m elf64ppc
+override CC	+= -m64
 endif
 
 export CROSS32CC CROSS32AS CROSS32LD CROSS32OBJCOPY
@@ -90,12 +90,14 @@
 boottarget-$(CONFIG_PPC_PSERIES) := zImage zImage.initrd
 boottarget-$(CONFIG_PPC_MAPLE) := zImage zImage.initrd
 boottarget-$(CONFIG_PPC_ISERIES) := vmlinux.sminitrd vmlinux.initrd vmlinux.sm
+boottarget-$(CONFIG_PPC_BPA) := zImage zImage.initrd
 $(boottarget-y): vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
 bootimage-$(CONFIG_PPC_PSERIES) := $(boot)/zImage
 bootimage-$(CONFIG_PPC_PMAC) := vmlinux
 bootimage-$(CONFIG_PPC_MAPLE) := $(boot)/zImage
+bootimage-$(CONFIG_PPC_BPA) := zImage
 bootimage-$(CONFIG_PPC_ISERIES) := vmlinux
 BOOTIMAGE := $(bootimage-y)
 install: vmlinux
diff --git a/arch/ppc64/boot/install.sh b/arch/ppc64/boot/install.sh
index 955c568..cb2d662 100644
--- a/arch/ppc64/boot/install.sh
+++ b/arch/ppc64/boot/install.sh
@@ -22,8 +22,8 @@
 
 # User may have a custom install script
 
-if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi
-if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi
+if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi
+if [ -x /sbin/${CROSS_COMPILE}installkernel ]; then exec /sbin/${CROSS_COMPILE}installkernel "$@"; fi
 
 # Default install
 
diff --git a/arch/ppc64/boot/prom.c b/arch/ppc64/boot/prom.c
index 7b607d1..d5218b1 100644
--- a/arch/ppc64/boot/prom.c
+++ b/arch/ppc64/boot/prom.c
@@ -11,6 +11,23 @@
 #include <linux/string.h>
 #include <linux/ctype.h>
 
+extern __u32 __div64_32(unsigned long long *dividend, __u32 divisor);
+
+/* The unnecessary pointer compare is there
+ * to check for type safety (n must be 64bit)
+ */
+# define do_div(n,base) ({				\
+	__u32 __base = (base);			\
+	__u32 __rem;					\
+	(void)(((typeof((n)) *)0) == ((unsigned long long *)0));	\
+	if (((n) >> 32) == 0) {			\
+		__rem = (__u32)(n) % __base;		\
+		(n) = (__u32)(n) / __base;		\
+	} else 						\
+		__rem = __div64_32(&(n), __base);	\
+	__rem;						\
+ })
+
 int (*prom)(void *);
 
 void *chosen_handle;
@@ -352,7 +369,7 @@
 #define SPECIAL	32		/* 0x */
 #define LARGE	64		/* use 'ABCDEF' instead of 'abcdef' */
 
-static char * number(char * str, long num, int base, int size, int precision, int type)
+static char * number(char * str, unsigned long long num, int base, int size, int precision, int type)
 {
 	char c,sign,tmp[66];
 	const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
@@ -367,9 +384,9 @@
 	c = (type & ZEROPAD) ? '0' : ' ';
 	sign = 0;
 	if (type & SIGN) {
-		if (num < 0) {
+		if ((signed long long)num < 0) {
 			sign = '-';
-			num = -num;
+			num = - (signed long long)num;
 			size--;
 		} else if (type & PLUS) {
 			sign = '+';
@@ -389,8 +406,7 @@
 	if (num == 0)
 		tmp[i++]='0';
 	else while (num != 0) {
-		tmp[i++] = digits[num % base];
-		num /= base;
+		tmp[i++] = digits[do_div(num, base)];
 	}
 	if (i > precision)
 		precision = i;
@@ -426,7 +442,7 @@
 int vsprintf(char *buf, const char *fmt, va_list args)
 {
 	int len;
-	unsigned long num;
+	unsigned long long num;
 	int i, base;
 	char * str;
 	const char *s;
diff --git a/arch/ppc64/configs/g5_defconfig b/arch/ppc64/configs/g5_defconfig
index 0f90df0..1eb3339 100644
--- a/arch/ppc64/configs/g5_defconfig
+++ b/arch/ppc64/configs/g5_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11
-# Thu Mar 10 16:47:04 2005
+# Linux kernel version: 2.6.12-rc6
+# Tue Jun 14 16:59:20 2005
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
@@ -11,7 +11,7 @@
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_COMPAT=y
-CONFIG_FRAME_POINTER=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
 CONFIG_FORCE_MAX_ZONEORDER=13
 
 #
@@ -20,6 +20,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -31,19 +32,20 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=17
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS 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 is not set
 CONFIG_SHMEM=y
 CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
@@ -87,6 +89,8 @@
 # CONFIG_SCHED_SMT is not set
 # CONFIG_PREEMPT is not set
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
 
 #
 # General setup
@@ -97,6 +101,7 @@
 # CONFIG_BINFMT_MISC is not set
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
 # CONFIG_HOTPLUG_CPU is not set
 
 #
@@ -105,10 +110,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 # CONFIG_HOTPLUG_PCI is not set
@@ -293,7 +294,6 @@
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
@@ -301,7 +301,6 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 CONFIG_SCSI_QLA2XXX=y
@@ -310,6 +309,7 @@
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -332,6 +332,7 @@
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_ZERO=m
+# CONFIG_DM_MULTIPATH is not set
 
 #
 # Fusion MPT device support
@@ -394,7 +395,6 @@
 #
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 CONFIG_NET_KEY=m
 CONFIG_INET=y
@@ -564,6 +564,8 @@
 # CONFIG_R8169 is not set
 # CONFIG_SK98LIN is not set
 CONFIG_TIGON3=m
+# CONFIG_BNX2 is not set
+# CONFIG_MV643XX_ETH is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -631,18 +633,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-# CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-# CONFIG_SERIO_RAW is not set
-
-#
 # Input Device Drivers
 #
 CONFIG_INPUT_KEYBOARD=y
@@ -660,6 +650,16 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 CONFIG_VT=y
@@ -676,6 +676,7 @@
 # Non-8250 serial port support
 #
 # CONFIG_SERIAL_PMACZILOG is not set
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -698,9 +699,12 @@
 #
 # Ftape, the floppy tape device driver
 #
+CONFIG_AGP=m
+CONFIG_AGP_UNINORTH=m
 # CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=y
 CONFIG_MAX_RAW_DEVS=256
+# CONFIG_HANGCHECK_TIMER is not set
 
 #
 # TPM devices
@@ -730,12 +734,11 @@
 # 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 is not set
 CONFIG_I2C_KEYWEST=y
-# CONFIG_I2C_MPC is not set
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PIIX4 is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
 # CONFIG_SCx200_ACB is not set
@@ -772,6 +775,7 @@
 # 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_SMSC47B397 is not set
@@ -785,6 +789,7 @@
 #
 # Other I2C Chip support
 #
+# CONFIG_SENSORS_DS1337 is not set
 # CONFIG_SENSORS_EEPROM is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCF8591 is not set
@@ -817,6 +822,11 @@
 # Graphics support
 #
 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=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 # CONFIG_FB_CIRRUS is not set
@@ -830,6 +840,7 @@
 # CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
 # CONFIG_FB_VGA16 is not set
+# CONFIG_FB_NVIDIA is not set
 CONFIG_FB_RIVA=y
 # CONFIG_FB_RIVA_I2C is not set
 # CONFIG_FB_RIVA_DEBUG is not set
@@ -847,6 +858,7 @@
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
 # CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -880,6 +892,8 @@
 #
 # USB support
 #
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -890,8 +904,6 @@
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
 
 #
 # USB Host Controller Drivers
@@ -917,7 +929,6 @@
 #
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
-CONFIG_USB_STORAGE_RW_DETECT=y
 CONFIG_USB_STORAGE_DATAFAB=y
 CONFIG_USB_STORAGE_FREECOM=y
 CONFIG_USB_STORAGE_ISD200=y
@@ -1004,8 +1015,10 @@
 #
 CONFIG_USB_SERIAL=m
 CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
 CONFIG_USB_SERIAL_BELKIN=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
@@ -1034,6 +1047,7 @@
 CONFIG_USB_SERIAL_KOBIL_SCT=m
 CONFIG_USB_SERIAL_MCT_U232=m
 CONFIG_USB_SERIAL_PL2303=m
+# CONFIG_USB_SERIAL_HP4X is not set
 CONFIG_USB_SERIAL_SAFE=m
 CONFIG_USB_SERIAL_SAFE_PADDED=y
 CONFIG_USB_SERIAL_TI=m
@@ -1270,11 +1284,13 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
-# CONFIG_PRINTK_TIME is not set
+CONFIG_LOG_BUF_SHIFT=17
 # 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_INFO is not set
diff --git a/arch/ppc64/configs/iSeries_defconfig b/arch/ppc64/configs/iSeries_defconfig
index a39e9d2..f6a2b99 100644
--- a/arch/ppc64/configs/iSeries_defconfig
+++ b/arch/ppc64/configs/iSeries_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc3-bk6
-# Wed Feb  9 23:34:52 2005
+# Linux kernel version: 2.6.12-rc6
+# Tue Jun 14 17:01:28 2005
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
@@ -11,7 +11,7 @@
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_COMPAT=y
-CONFIG_FRAME_POINTER=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
 CONFIG_FORCE_MAX_ZONEORDER=13
 
 #
@@ -20,6 +20,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -30,24 +31,29 @@
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=17
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS 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 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_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -79,6 +85,8 @@
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_MSCHUNKS=y
 CONFIG_LPARCFG=y
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
 
 #
 # General setup
@@ -89,6 +97,7 @@
 # CONFIG_BINFMT_MISC is not set
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -96,10 +105,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 # CONFIG_HOTPLUG_PCI is not set
@@ -210,7 +215,6 @@
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
@@ -219,7 +223,6 @@
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 CONFIG_SCSI_QLA2XXX=y
@@ -228,6 +231,7 @@
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_LPFC is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -250,6 +254,7 @@
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_ZERO=m
+# CONFIG_DM_MULTIPATH is not set
 
 #
 # Fusion MPT device support
@@ -280,7 +285,6 @@
 #
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 CONFIG_NET_KEY=m
 CONFIG_INET=y
@@ -445,7 +449,6 @@
 # CONFIG_DGRS is not set
 # CONFIG_EEPRO100 is not set
 CONFIG_E100=y
-# CONFIG_E100_NAPI is not set
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
@@ -471,6 +474,7 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -539,14 +543,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -556,6 +552,12 @@
 # CONFIG_INPUT_MISC is not set
 
 #
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
 # Character devices
 #
 # CONFIG_SERIAL_NONSTANDARD is not set
@@ -570,6 +572,7 @@
 #
 CONFIG_SERIAL_CORE=m
 CONFIG_SERIAL_ICOM=m
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -592,9 +595,16 @@
 #
 # Ftape, the floppy tape device driver
 #
+# CONFIG_AGP is not set
 # CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=y
 CONFIG_MAX_RAW_DEVS=256
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -633,13 +643,9 @@
 #
 # USB support
 #
-# CONFIG_USB is not set
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
 
 #
 # USB Gadget Support
@@ -848,10 +854,13 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=17
 # 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_INFO is not set
@@ -881,6 +890,7 @@
 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
diff --git a/arch/ppc64/configs/maple_defconfig b/arch/ppc64/configs/maple_defconfig
index cf52750..8051b0f 100644
--- a/arch/ppc64/configs/maple_defconfig
+++ b/arch/ppc64/configs/maple_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc3-bk6
-# Wed Feb  9 23:34:53 2005
+# Linux kernel version: 2.6.12-rc6
+# Tue Jun 14 17:12:48 2005
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
@@ -11,7 +11,7 @@
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_COMPAT=y
-CONFIG_FRAME_POINTER=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
 CONFIG_FORCE_MAX_ZONEORDER=13
 
 #
@@ -20,6 +20,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -30,24 +31,28 @@
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_AUDIT is not set
 # CONFIG_HOTPLUG is not set
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+# CONFIG_CPUSETS is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=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 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_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -84,6 +89,8 @@
 # CONFIG_SCHED_SMT is not set
 # CONFIG_PREEMPT is not set
 CONFIG_GENERIC_HARDIRQS=y
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
 
 #
 # General setup
@@ -94,6 +101,7 @@
 # CONFIG_BINFMT_MISC is not set
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
 
 #
 # PCCARD (PCMCIA/CardBus) support
@@ -101,10 +109,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 # CONFIG_HOTPLUG_PCI is not set
@@ -261,7 +265,6 @@
 #
 CONFIG_PACKET=y
 CONFIG_PACKET_MMAP=y
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 # CONFIG_NET_KEY is not set
 CONFIG_INET=y
@@ -376,6 +379,8 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
+# CONFIG_BNX2 is not set
+# CONFIG_MV643XX_ETH is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -432,14 +437,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-# CONFIG_SERIO_I8042 is not set
-
-#
 # Input Device Drivers
 #
 # CONFIG_INPUT_KEYBOARD is not set
@@ -449,6 +446,12 @@
 # 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
@@ -469,7 +472,7 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_PMACZILOG is not set
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -492,8 +495,15 @@
 #
 # Ftape, the floppy tape device driver
 #
+# CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -518,8 +528,8 @@
 CONFIG_I2C_AMD8111=y
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
 # CONFIG_I2C_ISA is not set
-# CONFIG_I2C_MPC is not set
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
@@ -545,7 +555,9 @@
 # CONFIG_SENSORS_ASB100 is not set
 # CONFIG_SENSORS_DS1621 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
@@ -556,9 +568,11 @@
 # 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_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
@@ -568,6 +582,7 @@
 #
 # Other I2C Chip support
 #
+# CONFIG_SENSORS_DS1337 is not set
 # CONFIG_SENSORS_EEPROM is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCF8591 is not set
@@ -615,6 +630,8 @@
 #
 # USB support
 #
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -625,8 +642,6 @@
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
 
 #
 # USB Host Controller Drivers
@@ -635,6 +650,8 @@
 CONFIG_USB_EHCI_SPLIT_ISO=y
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
 CONFIG_USB_UHCI_HCD=y
 # CONFIG_USB_SL811_HCD is not set
 
@@ -688,6 +705,7 @@
 CONFIG_USB_PEGASUS=y
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
+CONFIG_USB_MON=y
 
 #
 # USB port drivers
@@ -699,8 +717,10 @@
 CONFIG_USB_SERIAL=y
 # CONFIG_USB_SERIAL_CONSOLE is not set
 CONFIG_USB_SERIAL_GENERIC=y
+# CONFIG_USB_SERIAL_AIRPRIME is not set
 # CONFIG_USB_SERIAL_BELKIN is not set
 # CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP2101 is not set
 CONFIG_USB_SERIAL_CYPRESS_M8=m
 # CONFIG_USB_SERIAL_EMPEG is not set
 # CONFIG_USB_SERIAL_FTDI_SIO is not set
@@ -729,6 +749,7 @@
 # CONFIG_USB_SERIAL_KOBIL_SCT is not set
 # CONFIG_USB_SERIAL_MCT_U232 is not set
 # CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_HP4X is not set
 # CONFIG_USB_SERIAL_SAFE is not set
 CONFIG_USB_SERIAL_TI=m
 # CONFIG_USB_SERIAL_CYBERJACK is not set
@@ -750,6 +771,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_TEST is not set
 
 #
@@ -936,10 +958,13 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=17
 # CONFIG_SCHEDSTATS is not set
 CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_SPINLOCK is not set
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
@@ -971,6 +996,7 @@
 # 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
diff --git a/arch/ppc64/configs/pSeries_defconfig b/arch/ppc64/configs/pSeries_defconfig
index 4fecf23..d0db8b5 100644
--- a/arch/ppc64/configs/pSeries_defconfig
+++ b/arch/ppc64/configs/pSeries_defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc3-bk6
-# Wed Feb  9 23:34:54 2005
+# Linux kernel version: 2.6.12-rc6
+# Tue Jun 14 17:13:47 2005
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
@@ -11,7 +11,7 @@
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_COMPAT=y
-CONFIG_FRAME_POINTER=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
 CONFIG_FORCE_MAX_ZONEORDER=13
 
 #
@@ -20,6 +20,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -30,24 +31,29 @@
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=17
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_CPUSETS=y
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 CONFIG_KALLSYMS_ALL=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 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_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -82,16 +88,19 @@
 CONFIG_IOMMU_VMERGE=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=128
-CONFIG_DISCONTIGMEM=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
 CONFIG_NUMA=y
 CONFIG_SCHED_SMT=y
 # CONFIG_PREEMPT is not set
 CONFIG_EEH=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_PPC_RTAS=y
+CONFIG_RTAS_PROC=y
 CONFIG_RTAS_FLASH=m
 CONFIG_SCANLOG=m
 CONFIG_LPARCFG=y
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
 
 #
 # General setup
@@ -102,6 +111,7 @@
 # CONFIG_BINFMT_MISC is not set
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
+# CONFIG_PCI_DEBUG is not set
 CONFIG_HOTPLUG_CPU=y
 
 #
@@ -110,10 +120,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 CONFIG_HOTPLUG_PCI=m
@@ -147,11 +153,10 @@
 #
 CONFIG_PARPORT=m
 CONFIG_PARPORT_PC=m
-CONFIG_PARPORT_PC_CML1=m
 # CONFIG_PARPORT_SERIAL is not set
 # CONFIG_PARPORT_PC_FIFO is not set
 # CONFIG_PARPORT_PC_SUPERIO is not set
-# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_GSC is not set
 # CONFIG_PARPORT_1284 is not set
 
 #
@@ -293,7 +298,6 @@
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
@@ -310,7 +314,6 @@
 CONFIG_SCSI_IPR=y
 CONFIG_SCSI_IPR_TRACE=y
 CONFIG_SCSI_IPR_DUMP=y
-# CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 CONFIG_SCSI_QLA2XXX=y
@@ -319,6 +322,7 @@
 CONFIG_SCSI_QLA2300=m
 CONFIG_SCSI_QLA2322=m
 CONFIG_SCSI_QLA6312=m
+CONFIG_SCSI_LPFC=m
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -341,6 +345,8 @@
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
 
 #
 # Fusion MPT device support
@@ -371,7 +377,6 @@
 #
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 CONFIG_NET_KEY=m
 CONFIG_INET=y
@@ -539,7 +544,6 @@
 # CONFIG_DGRS is not set
 # CONFIG_EEPRO100 is not set
 CONFIG_E100=y
-# CONFIG_E100_NAPI is not set
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
@@ -565,6 +569,8 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
 CONFIG_TIGON3=y
+# CONFIG_BNX2 is not set
+# CONFIG_MV643XX_ETH is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -636,20 +642,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PARKBD is not set
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_SERIO_RAW is not set
-
-#
 # Input Device Drivers
 #
 CONFIG_INPUT_KEYBOARD=y
@@ -669,6 +661,18 @@
 # CONFIG_INPUT_UINPUT is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PARKBD is not set
+# 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
@@ -689,8 +693,8 @@
 #
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
-# CONFIG_SERIAL_PMACZILOG is not set
 CONFIG_SERIAL_ICOM=m
+# CONFIG_SERIAL_JSM is not set
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -718,9 +722,16 @@
 #
 # Ftape, the floppy tape device driver
 #
+# CONFIG_AGP is not set
 # CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=y
 CONFIG_MAX_RAW_DEVS=1024
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -745,8 +756,8 @@
 # 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 is not set
-# CONFIG_I2C_MPC is not set
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
@@ -773,7 +784,9 @@
 # CONFIG_SENSORS_ASB100 is not set
 # CONFIG_SENSORS_DS1621 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
@@ -784,9 +797,11 @@
 # 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_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
@@ -796,6 +811,7 @@
 #
 # Other I2C Chip support
 #
+# CONFIG_SENSORS_DS1337 is not set
 # CONFIG_SENSORS_EEPROM is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCF8591 is not set
@@ -828,8 +844,13 @@
 # Graphics support
 #
 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=y
 CONFIG_FB_MODE_HELPERS=y
-# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_TILEBLITTING=y
 # CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
@@ -838,6 +859,7 @@
 # CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
 # CONFIG_FB_VGA16 is not set
+# CONFIG_FB_NVIDIA is not set
 # CONFIG_FB_RIVA is not set
 CONFIG_FB_MATROX=y
 CONFIG_FB_MATROX_MILLENIUM=y
@@ -858,6 +880,7 @@
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
 # CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -891,6 +914,8 @@
 #
 # USB support
 #
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -901,8 +926,6 @@
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
 
 #
 # USB Host Controller Drivers
@@ -911,6 +934,8 @@
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT 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
 
@@ -926,12 +951,11 @@
 #
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_RW_DETECT 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_HP8200e 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
@@ -975,6 +999,7 @@
 # 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
@@ -1000,6 +1025,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_TEST is not set
 
 #
@@ -1208,10 +1234,13 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=17
 # 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_INFO is not set
@@ -1243,6 +1272,7 @@
 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
diff --git a/arch/ppc64/defconfig b/arch/ppc64/defconfig
index 537b1cc..b8e2066 100644
--- a/arch/ppc64/defconfig
+++ b/arch/ppc64/defconfig
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc3-bk6
-# Wed Feb  9 23:34:51 2005
+# Linux kernel version: 2.6.12-rc5-git9
+# Sun Jun  5 09:26:47 2005
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
@@ -11,7 +11,7 @@
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_COMPAT=y
-CONFIG_FRAME_POINTER=y
+CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
 CONFIG_FORCE_MAX_ZONEORDER=13
 
 #
@@ -20,6 +20,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
 
 #
 # General setup
@@ -30,24 +31,28 @@
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
-CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_AUDIT is not set
 CONFIG_HOTPLUG=y
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
+CONFIG_CPUSETS=y
 # 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 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_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
 
 #
 # Loadable module support
@@ -84,16 +89,19 @@
 CONFIG_IOMMU_VMERGE=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=32
-CONFIG_DISCONTIGMEM=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
 # CONFIG_NUMA is not set
 # CONFIG_SCHED_SMT is not set
 # CONFIG_PREEMPT is not set
 CONFIG_EEH=y
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_PPC_RTAS=y
+CONFIG_RTAS_PROC=y
 CONFIG_RTAS_FLASH=m
 CONFIG_SCANLOG=m
 CONFIG_LPARCFG=y
+CONFIG_SECCOMP=y
+CONFIG_ISA_DMA_API=y
 
 #
 # General setup
@@ -104,6 +112,7 @@
 CONFIG_BINFMT_MISC=m
 # CONFIG_PCI_LEGACY_PROC is not set
 # CONFIG_PCI_NAMES is not set
+# CONFIG_PCI_DEBUG is not set
 CONFIG_HOTPLUG_CPU=y
 
 #
@@ -112,10 +121,6 @@
 # CONFIG_PCCARD is not set
 
 #
-# PC-card bridges
-#
-
-#
 # PCI Hotplug Support
 #
 CONFIG_HOTPLUG_PCI=m
@@ -149,11 +154,10 @@
 #
 CONFIG_PARPORT=m
 CONFIG_PARPORT_PC=m
-CONFIG_PARPORT_PC_CML1=m
 # CONFIG_PARPORT_SERIAL is not set
 # CONFIG_PARPORT_PC_FIFO is not set
 # CONFIG_PARPORT_PC_SUPERIO is not set
-# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_GSC is not set
 # CONFIG_PARPORT_1284 is not set
 
 #
@@ -301,6 +305,7 @@
 # CONFIG_SCSI_ATA_PIIX is not set
 # CONFIG_SCSI_SATA_NV is not set
 # CONFIG_SCSI_SATA_PROMISE is not set
+# CONFIG_SCSI_SATA_QSTOR is not set
 # CONFIG_SCSI_SATA_SX4 is not set
 # CONFIG_SCSI_SATA_SIL is not set
 # CONFIG_SCSI_SATA_SIS is not set
@@ -310,7 +315,6 @@
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
@@ -327,7 +331,6 @@
 CONFIG_SCSI_IPR=y
 CONFIG_SCSI_IPR_TRACE=y
 CONFIG_SCSI_IPR_DUMP=y
-# CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
 CONFIG_SCSI_QLA2XXX=y
@@ -336,6 +339,7 @@
 CONFIG_SCSI_QLA2300=m
 CONFIG_SCSI_QLA2322=m
 CONFIG_SCSI_QLA6312=m
+CONFIG_SCSI_LPFC=m
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 CONFIG_SCSI_DEBUG=m
@@ -358,6 +362,8 @@
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_EMC=m
 
 #
 # Fusion MPT device support
@@ -405,6 +411,7 @@
 #
 CONFIG_ADB=y
 CONFIG_ADB_PMU=y
+CONFIG_PMAC_SMU=y
 # CONFIG_PMAC_PBOOK is not set
 # CONFIG_PMAC_BACKLIGHT is not set
 # CONFIG_INPUT_ADBHID is not set
@@ -420,7 +427,6 @@
 #
 CONFIG_PACKET=y
 # CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
 CONFIG_UNIX=y
 CONFIG_NET_KEY=m
 CONFIG_INET=y
@@ -588,7 +594,6 @@
 # CONFIG_DGRS is not set
 # CONFIG_EEPRO100 is not set
 CONFIG_E100=y
-# CONFIG_E100_NAPI is not set
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
@@ -614,6 +619,8 @@
 # CONFIG_SK98LIN is not set
 # CONFIG_VIA_VELOCITY is not set
 CONFIG_TIGON3=y
+# CONFIG_BNX2 is not set
+# CONFIG_MV643XX_ETH is not set
 
 #
 # Ethernet (10000 Mbit)
@@ -683,20 +690,6 @@
 # CONFIG_INPUT_EVBUG is not set
 
 #
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PARKBD is not set
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_SERIO_RAW is not set
-
-#
 # Input Device Drivers
 #
 CONFIG_INPUT_KEYBOARD=y
@@ -716,6 +709,18 @@
 # CONFIG_INPUT_UINPUT is not set
 
 #
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PARKBD is not set
+# 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
@@ -738,6 +743,7 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_PMACZILOG is not set
 CONFIG_SERIAL_ICOM=m
+CONFIG_SERIAL_JSM=m
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
@@ -766,9 +772,16 @@
 #
 # Ftape, the floppy tape device driver
 #
+# CONFIG_AGP is not set
 # CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=y
 CONFIG_MAX_RAW_DEVS=256
+# CONFIG_HANGCHECK_TIMER is not set
+
+#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
 
 #
 # I2C support
@@ -793,9 +806,9 @@
 CONFIG_I2C_AMD8111=y
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
+# CONFIG_I2C_PIIX4 is not set
 # CONFIG_I2C_ISA is not set
 CONFIG_I2C_KEYWEST=y
-# CONFIG_I2C_MPC is not set
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
@@ -822,7 +835,9 @@
 # CONFIG_SENSORS_ASB100 is not set
 # CONFIG_SENSORS_DS1621 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
@@ -833,9 +848,11 @@
 # 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_SMSC47B397 is not set
+# CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
@@ -845,6 +862,7 @@
 #
 # Other I2C Chip support
 #
+# CONFIG_SENSORS_DS1337 is not set
 # CONFIG_SENSORS_EEPROM is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCF8591 is not set
@@ -877,6 +895,11 @@
 # Graphics support
 #
 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=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 # CONFIG_FB_CIRRUS is not set
@@ -890,9 +913,8 @@
 # CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
 # CONFIG_FB_VGA16 is not set
-CONFIG_FB_RIVA=y
-CONFIG_FB_RIVA_I2C=y
-# CONFIG_FB_RIVA_DEBUG is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
 CONFIG_FB_MATROX=y
 CONFIG_FB_MATROX_MILLENIUM=y
 CONFIG_FB_MATROX_MYSTIQUE=y
@@ -913,6 +935,7 @@
 # CONFIG_FB_3DFX is not set
 # CONFIG_FB_VOODOO1 is not set
 # CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_VIRTUAL is not set
 
 #
@@ -946,6 +969,8 @@
 #
 # USB support
 #
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
 CONFIG_USB=y
 # CONFIG_USB_DEBUG is not set
 
@@ -956,8 +981,6 @@
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
 
 #
 # USB Host Controller Drivers
@@ -966,6 +989,8 @@
 # CONFIG_USB_EHCI_SPLIT_ISO is not set
 # CONFIG_USB_EHCI_ROOT_HUB_TT 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
 
@@ -981,12 +1006,11 @@
 #
 CONFIG_USB_STORAGE=m
 # CONFIG_USB_STORAGE_DEBUG is not set
-CONFIG_USB_STORAGE_RW_DETECT=y
 # 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_HP8200e 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
@@ -1030,6 +1054,7 @@
 CONFIG_USB_PEGASUS=y
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
+# CONFIG_USB_MON is not set
 
 #
 # USB port drivers
@@ -1055,6 +1080,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_TEST is not set
 
 #
@@ -1276,10 +1302,13 @@
 #
 # Kernel hacking
 #
+# CONFIG_PRINTK_TIME is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_LOG_BUF_SHIFT=17
 # 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_INFO is not set
@@ -1311,6 +1340,7 @@
 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
diff --git a/arch/ppc64/kernel/HvLpEvent.c b/arch/ppc64/kernel/HvLpEvent.c
index f8f1963..90032b1 100644
--- a/arch/ppc64/kernel/HvLpEvent.c
+++ b/arch/ppc64/kernel/HvLpEvent.c
@@ -12,7 +12,7 @@
 #include <asm/system.h>
 #include <asm/iSeries/HvLpEvent.h>
 #include <asm/iSeries/HvCallEvent.h>
-#include <asm/iSeries/LparData.h>
+#include <asm/iSeries/ItLpNaca.h>
 
 /* Array of LpEvent handler functions */
 LpEventHandler lpEventHandler[HvLpEvent_Type_NumTypes];
diff --git a/arch/ppc64/kernel/ItLpQueue.c b/arch/ppc64/kernel/ItLpQueue.c
index c923a81..cdea00d 100644
--- a/arch/ppc64/kernel/ItLpQueue.c
+++ b/arch/ppc64/kernel/ItLpQueue.c
@@ -16,7 +16,6 @@
 #include <asm/iSeries/ItLpQueue.h>
 #include <asm/iSeries/HvLpEvent.h>
 #include <asm/iSeries/HvCallEvent.h>
-#include <asm/iSeries/LparData.h>
 
 static __inline__ int set_inUse( struct ItLpQueue * lpQueue )
 {
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
index 96d90b0..d9b2660 100644
--- a/arch/ppc64/kernel/Makefile
+++ b/arch/ppc64/kernel/Makefile
@@ -16,29 +16,33 @@
 
 obj-$(CONFIG_PPC_OF) +=	of_device.o
 
-pci-obj-$(CONFIG_PPC_ISERIES)	+= iSeries_pci.o iSeries_pci_reset.o
+pci-obj-$(CONFIG_PPC_ISERIES)	+= iSeries_pci.o iSeries_irq.o \
+				iSeries_VpdInfo.o
 pci-obj-$(CONFIG_PPC_MULTIPLATFORM)	+= pci_dn.o pci_direct_iommu.o
 
 obj-$(CONFIG_PCI)	+= pci.o pci_iommu.o iomap.o $(pci-obj-y)
 
-obj-$(CONFIG_PPC_ISERIES) += iSeries_irq.o \
-			     iSeries_VpdInfo.o XmPciLpEvent.o \
-			     HvCall.o HvLpConfig.o LparData.o \
+obj-$(CONFIG_PPC_ISERIES) += HvCall.o HvLpConfig.o LparData.o \
 			     iSeries_setup.o ItLpQueue.o hvCall.o \
 			     mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \
 			     iSeries_iommu.o
 
-obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o prom.o mpic.o
+obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o prom.o
 
 obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \
 			     pSeries_nvram.o rtasd.o ras.o pSeries_reconfig.o \
-			     xics.o rtas.o pSeries_setup.o pSeries_iommu.o
+			     pSeries_setup.o pSeries_iommu.o
 
+obj-$(CONFIG_PPC_BPA) += bpa_setup.o bpa_iommu.o bpa_nvram.o \
+			 bpa_iic.o spider-pic.o
+
+obj-$(CONFIG_KEXEC)		+= machine_kexec.o
 obj-$(CONFIG_EEH)		+= eeh.o
 obj-$(CONFIG_PROC_FS)		+= proc_ppc64.o
 obj-$(CONFIG_RTAS_FLASH)	+= rtas_flash.o
 obj-$(CONFIG_SMP)		+= smp.o
 obj-$(CONFIG_MODULES)		+= module.o ppc_ksyms.o
+obj-$(CONFIG_PPC_RTAS)		+= rtas.o rtas_pci.o
 obj-$(CONFIG_RTAS_PROC)		+= rtas-proc.o
 obj-$(CONFIG_SCANLOG)		+= scanlog.o
 obj-$(CONFIG_VIOPATH)		+= viopath.o
@@ -47,6 +51,8 @@
 obj-$(CONFIG_BOOTX_TEXT)	+= btext.o
 obj-$(CONFIG_HVCS)		+= hvcserver.o
 obj-$(CONFIG_IBMVIO)		+= vio.o
+obj-$(CONFIG_XICS)		+= xics.o
+obj-$(CONFIG_MPIC)		+= mpic.o
 
 obj-$(CONFIG_PPC_PMAC)		+= pmac_setup.o pmac_feature.o pmac_pci.o \
 				   pmac_time.o pmac_nvram.o pmac_low_i2c.o
@@ -59,6 +65,7 @@
 obj-$(CONFIG_PPC_PMAC)		+= pmac_smp.o smp-tbsync.o
 obj-$(CONFIG_PPC_ISERIES)	+= iSeries_smp.o
 obj-$(CONFIG_PPC_PSERIES)	+= pSeries_smp.o
+obj-$(CONFIG_PPC_BPA)		+= pSeries_smp.o
 obj-$(CONFIG_PPC_MAPLE)		+= smp-tbsync.o
 endif
 
diff --git a/arch/ppc64/kernel/XmPciLpEvent.c b/arch/ppc64/kernel/XmPciLpEvent.c
deleted file mode 100644
index 809c9bc..0000000
--- a/arch/ppc64/kernel/XmPciLpEvent.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * File XmPciLpEvent.h created by Wayne Holm on Mon Jan 15 2001.
- *
- * This module handles PCI interrupt events sent by the iSeries Hypervisor.
-*/
-
-#include <linux/config.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/threads.h>
-#include <linux/smp.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/bootmem.h>
-#include <linux/ide.h>
-
-#include <asm/iSeries/HvTypes.h>
-#include <asm/iSeries/HvLpEvent.h>
-#include <asm/iSeries/HvCallPci.h>
-#include <asm/iSeries/XmPciLpEvent.h>
-#include <asm/ppcdebug.h>
-
-static long Pci_Interrupt_Count;
-static long Pci_Event_Count;
-
-enum XmPciLpEvent_Subtype {
-	XmPciLpEvent_BusCreated	   = 0,		// PHB has been created
-	XmPciLpEvent_BusError	   = 1,		// PHB has failed
-	XmPciLpEvent_BusFailed	   = 2,		// Msg to Secondary, Primary failed bus
-	XmPciLpEvent_NodeFailed	   = 4,		// Multi-adapter bridge has failed
-	XmPciLpEvent_NodeRecovered = 5,		// Multi-adapter bridge has recovered
-	XmPciLpEvent_BusRecovered  = 12,	// PHB has been recovered
-	XmPciLpEvent_UnQuiesceBus  = 18,	// Secondary bus unqiescing
-	XmPciLpEvent_BridgeError   = 21,	// Bridge Error
-	XmPciLpEvent_SlotInterrupt = 22		// Slot interrupt
-};
-
-struct XmPciLpEvent_BusInterrupt {
-	HvBusNumber	busNumber;
-	HvSubBusNumber	subBusNumber;
-};
-
-struct XmPciLpEvent_NodeInterrupt {
-	HvBusNumber	busNumber;
-	HvSubBusNumber	subBusNumber;
-	HvAgentId	deviceId;
-};
-
-struct XmPciLpEvent {
-	struct HvLpEvent hvLpEvent;
-
-	union {
-		u64 alignData;			// Align on an 8-byte boundary
-
-		struct {
-			u32		fisr;
-			HvBusNumber	busNumber;
-			HvSubBusNumber	subBusNumber;
-			HvAgentId	deviceId;
-		} slotInterrupt;
-
-		struct XmPciLpEvent_BusInterrupt busFailed;
-		struct XmPciLpEvent_BusInterrupt busRecovered;
-		struct XmPciLpEvent_BusInterrupt busCreated;
-
-		struct XmPciLpEvent_NodeInterrupt nodeFailed;
-		struct XmPciLpEvent_NodeInterrupt nodeRecovered;
-
-	} eventData;
-
-};
-
-static void intReceived(struct XmPciLpEvent *eventParm,
-		struct pt_regs *regsParm);
-
-static void XmPciLpEvent_handler(struct HvLpEvent *eventParm,
-		struct pt_regs *regsParm)
-{
-#ifdef CONFIG_PCI
-#if 0
-	PPCDBG(PPCDBG_BUSWALK, "XmPciLpEvent_handler, type 0x%x\n",
-			eventParm->xType);
-#endif
-	++Pci_Event_Count;
-
-	if (eventParm && (eventParm->xType == HvLpEvent_Type_PciIo)) {
-		switch (eventParm->xFlags.xFunction) {
-		case HvLpEvent_Function_Int:
-			intReceived((struct XmPciLpEvent *)eventParm, regsParm);
-			break;
-		case HvLpEvent_Function_Ack:
-			printk(KERN_ERR
-				"XmPciLpEvent.c: unexpected ack received\n");
-			break;
-		default:
-			printk(KERN_ERR
-				"XmPciLpEvent.c: unexpected event function %d\n",
-				(int)eventParm->xFlags.xFunction);
-			break;
-		}
-	} else if (eventParm)
-		printk(KERN_ERR
-			"XmPciLpEvent.c: Unrecognized PCI event type 0x%x\n",
-			(int)eventParm->xType);
-	else
-		printk(KERN_ERR "XmPciLpEvent.c: NULL event received\n");
-#endif
-}
-
-static void intReceived(struct XmPciLpEvent *eventParm,
-		struct pt_regs *regsParm)
-{
-	int irq;
-
-	++Pci_Interrupt_Count;
-#if 0
-	PPCDBG(PPCDBG_BUSWALK, "PCI: XmPciLpEvent.c: intReceived\n");
-#endif
-
-	switch (eventParm->hvLpEvent.xSubtype) {
-	case XmPciLpEvent_SlotInterrupt:
-		irq = eventParm->hvLpEvent.xCorrelationToken;
-		/* Dispatch the interrupt handlers for this irq */
-		ppc_irq_dispatch_handler(regsParm, irq);
-		HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber,
-			eventParm->eventData.slotInterrupt.subBusNumber,
-			eventParm->eventData.slotInterrupt.deviceId);
-		break;
-		/* Ignore error recovery events for now */
-	case XmPciLpEvent_BusCreated:
-		printk(KERN_INFO "XmPciLpEvent.c: system bus %d created\n",
-			eventParm->eventData.busCreated.busNumber);
-		break;
-	case XmPciLpEvent_BusError:
-	case XmPciLpEvent_BusFailed:
-		printk(KERN_INFO "XmPciLpEvent.c: system bus %d failed\n",
-			eventParm->eventData.busFailed.busNumber);
-		break;
-	case XmPciLpEvent_BusRecovered:
-	case XmPciLpEvent_UnQuiesceBus:
-		printk(KERN_INFO "XmPciLpEvent.c: system bus %d recovered\n",
-			eventParm->eventData.busRecovered.busNumber);
-		break;
-	case XmPciLpEvent_NodeFailed:
-	case XmPciLpEvent_BridgeError:
-		printk(KERN_INFO
-			"XmPciLpEvent.c: multi-adapter bridge %d/%d/%d failed\n",
-			eventParm->eventData.nodeFailed.busNumber,
-			eventParm->eventData.nodeFailed.subBusNumber,
-			eventParm->eventData.nodeFailed.deviceId);
-		break;
-	case XmPciLpEvent_NodeRecovered:
-		printk(KERN_INFO
-			"XmPciLpEvent.c: multi-adapter bridge %d/%d/%d recovered\n",
-			eventParm->eventData.nodeRecovered.busNumber,
-			eventParm->eventData.nodeRecovered.subBusNumber,
-			eventParm->eventData.nodeRecovered.deviceId);
-		break;
-	default:
-		printk(KERN_ERR
-			"XmPciLpEvent.c: unrecognized event subtype 0x%x\n",
-			eventParm->hvLpEvent.xSubtype);
-		break;
-	}
-}
-
-
-/* This should be called sometime prior to buswalk (init_IRQ would be good) */
-int XmPciLpEvent_init()
-{
-	int xRc;
-
-	PPCDBG(PPCDBG_BUSWALK,
-			"XmPciLpEvent_init, Register Event type 0x%04X\n",
-			HvLpEvent_Type_PciIo);
-
-	xRc = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
-			&XmPciLpEvent_handler);
-	if (xRc == 0) {
-		xRc = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
-		if (xRc != 0)
-			printk(KERN_ERR
-				"XmPciLpEvent.c: open event path failed with rc 0x%x\n",
-				xRc);
-	} else
-		printk(KERN_ERR
-			"XmPciLpEvent.c: register handler failed with rc 0x%x\n",
-			xRc);
-	return xRc;
-}
diff --git a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c
index 0094ac7..abb9e5b 100644
--- a/arch/ppc64/kernel/asm-offsets.c
+++ b/arch/ppc64/kernel/asm-offsets.c
@@ -31,7 +31,6 @@
 
 #include <asm/paca.h>
 #include <asm/lppaca.h>
-#include <asm/iSeries/ItLpQueue.h>
 #include <asm/iSeries/HvLpEvent.h>
 #include <asm/rtas.h>
 #include <asm/cputable.h>
diff --git a/arch/ppc64/kernel/bpa_iic.c b/arch/ppc64/kernel/bpa_iic.c
new file mode 100644
index 0000000..c8f3dc3
--- /dev/null
+++ b/arch/ppc64/kernel/bpa_iic.c
@@ -0,0 +1,270 @@
+/*
+ * BPA Internal Interrupt Controller
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *
+ * Author: Arnd Bergmann <arndb@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.
+ */
+
+#include <linux/config.h>
+#include <linux/interrupt.h>
+#include <linux/irq.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 "bpa_iic.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;
+};
+
+struct iic {
+	struct iic_regs __iomem *regs;
+};
+
+static DEFINE_PER_CPU(struct iic, iic);
+
+void iic_local_enable(void)
+{
+	out_be64(&__get_cpu_var(iic).regs->prio, 0xff);
+}
+
+void iic_local_disable(void)
+{
+	out_be64(&__get_cpu_var(iic).regs->prio, 0x0);
+}
+
+static unsigned int iic_startup(unsigned int irq)
+{
+	return 0;
+}
+
+static void iic_enable(unsigned int irq)
+{
+	iic_local_enable();
+}
+
+static void iic_disable(unsigned int irq)
+{
+}
+
+static void iic_end(unsigned int irq)
+{
+	iic_local_enable();
+}
+
+static struct hw_interrupt_type iic_pic = {
+	.typename = " BPA-IIC  ",
+	.startup = iic_startup,
+	.enable = iic_enable,
+	.disable = iic_disable,
+	.end = iic_end,
+};
+
+static int iic_external_get_irq(struct iic_pending_bits pending)
+{
+	int irq;
+	unsigned char node, unit;
+
+	node = pending.source >> 4;
+	unit = pending.source & 0xf;
+	irq = -1;
+
+	/*
+	 * This mapping is specific to the Broadband
+	 * Engine. We might need to get the numbers
+	 * from the device tree to support future CPUs.
+	 */
+	switch (unit) {
+	case 0x00:
+	case 0x0b:
+		/*
+		 * One of these units can be connected
+		 * to an external interrupt controller.
+		 */
+		if (pending.prio > 0x3f ||
+		    pending.class != 2)
+			break;
+		irq = IIC_EXT_OFFSET
+			+ spider_get_irq(pending.prio + node * IIC_NODE_STRIDE)
+			+ node * IIC_NODE_STRIDE;
+		break;
+	case 0x01 ... 0x04:
+	case 0x07 ... 0x0a:
+		/*
+		 * These units are connected to the SPEs
+		 */
+		if (pending.class > 2)
+			break;
+		irq = IIC_SPE_OFFSET
+			+ pending.class * IIC_CLASS_STRIDE
+			+ node * IIC_NODE_STRIDE
+			+ unit;
+		break;
+	}
+	if (irq == -1)
+		printk(KERN_WARNING "Unexpected interrupt class %02x, "
+			"source %02x, prio %02x, cpu %02x\n", pending.class,
+			pending.source, pending.prio, smp_processor_id());
+	return irq;
+}
+
+/* Get an IRQ number from the pending state register of the IIC */
+int iic_get_irq(struct pt_regs *regs)
+{
+	struct iic *iic;
+	int irq;
+	struct 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) {
+			irq = IIC_IPI_OFFSET + (pending.prio >> 4);
+/*
+			if (irq > 0x80)
+				printk(KERN_WARNING "Unexpected IPI prio %02x"
+					"on CPU %02x\n", pending.prio,
+							smp_processor_id());
+*/
+		} else {
+			irq = iic_external_get_irq(pending);
+		}
+	}
+	return irq;
+}
+
+static struct iic_regs __iomem *find_iic(int cpu)
+{
+	struct device_node *np;
+	int nodeid = cpu / 2;
+	unsigned long regs;
+	struct iic_regs __iomem *iic_regs;
+
+	for (np = of_find_node_by_type(NULL, "cpu");
+	     np;
+	     np = of_find_node_by_type(np, "cpu")) {
+		if (nodeid == *(int *)get_property(np, "node-id", NULL))
+			break;
+	}
+
+	if (!np) {
+		printk(KERN_WARNING "IIC: CPU %d not found\n", cpu);
+		iic_regs = NULL;
+	} else {
+		regs = *(long *)get_property(np, "iic", NULL);
+
+		/* hack until we have decided on the devtree info */
+		regs += 0x400;
+		if (cpu & 1)
+			regs += 0x20;
+
+		printk(KERN_DEBUG "IIC for CPU %d at %lx\n", cpu, regs);
+		iic_regs = __ioremap(regs, sizeof(struct iic_regs),
+						 _PAGE_NO_CACHE);
+	}
+	return iic_regs;
+}
+
+#ifdef CONFIG_SMP
+void iic_setup_cpu(void)
+{
+	out_be64(&__get_cpu_var(iic).regs->prio, 0xff);
+}
+
+void iic_cause_IPI(int cpu, int mesg)
+{
+	out_be64(&per_cpu(iic, cpu).regs->generate, mesg);
+}
+
+static irqreturn_t iic_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
+{
+
+	smp_message_recv(irq - IIC_IPI_OFFSET, regs);
+	return IRQ_HANDLED;
+}
+
+static void iic_request_ipi(int irq, const char *name)
+{
+	/* IPIs are marked SA_INTERRUPT as they must run with irqs
+	 * disabled */
+	get_irq_desc(irq)->handler = &iic_pic;
+	get_irq_desc(irq)->status |= IRQ_PER_CPU;
+	request_irq(irq, iic_ipi_action, SA_INTERRUPT, name, NULL);
+}
+
+void iic_request_IPIs(void)
+{
+	iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_CALL_FUNCTION, "IPI-call");
+	iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_RESCHEDULE, "IPI-resched");
+#ifdef CONFIG_DEBUGGER
+	iic_request_ipi(IIC_IPI_OFFSET + PPC_MSG_DEBUGGER_BREAK, "IPI-debug");
+#endif /* CONFIG_DEBUGGER */
+}
+#endif /* CONFIG_SMP */
+
+static void iic_setup_spe_handlers(void)
+{
+	int be, isrc;
+
+	/* Assume two threads per BE are present */
+	for (be=0; be < num_present_cpus() / 2; be++) {
+		for (isrc = 0; isrc < IIC_CLASS_STRIDE * 3; isrc++) {
+			int irq = IIC_NODE_STRIDE * be + IIC_SPE_OFFSET + isrc;
+			get_irq_desc(irq)->handler = &iic_pic;
+		}
+	}
+}
+
+void iic_init_IRQ(void)
+{
+	int cpu, irq_offset;
+	struct iic *iic;
+
+	irq_offset = 0;
+	for_each_cpu(cpu) {
+		iic = &per_cpu(iic, cpu);
+		iic->regs = find_iic(cpu);
+		if (iic->regs)
+			out_be64(&iic->regs->prio, 0xff);
+	}
+	iic_setup_spe_handlers();
+}
diff --git a/arch/ppc64/kernel/bpa_iic.h b/arch/ppc64/kernel/bpa_iic.h
new file mode 100644
index 0000000..6833c30
--- /dev/null
+++ b/arch/ppc64/kernel/bpa_iic.h
@@ -0,0 +1,62 @@
+#ifndef ASM_BPA_IIC_H
+#define ASM_BPA_IIC_H
+#ifdef __KERNEL__
+/*
+ * Mapping of IIC pending bits into per-node
+ * interrupt numbers.
+ *
+ * IRQ     FF CC SS PP   FF CC SS PP	Description
+ *
+ * 00-3f   80 02 +0 00 - 80 02 +0 3f	South Bridge
+ * 00-3f   80 02 +b 00 - 80 02 +b 3f	South Bridge
+ * 41-4a   80 00 +1 ** - 80 00 +a **	SPU Class 0
+ * 51-5a   80 01 +1 ** - 80 01 +a **	SPU Class 1
+ * 61-6a   80 02 +1 ** - 80 02 +a **	SPU Class 2
+ * 70-7f   C0 ** ** 00 - C0 ** ** 0f	IPI
+ *
+ *    F flags
+ *    C class
+ *    S source
+ *    P Priority
+ *    + node number
+ *    * don't care
+ *
+ * A node consists of a Broadband Engine and an optional
+ * south bridge device providing a maximum of 64 IRQs.
+ * The south bridge may be connected to either IOIF0
+ * or IOIF1.
+ * Each SPE is represented as three IRQ lines, one per
+ * interrupt class.
+ * 16 IRQ numbers are reserved for inter processor
+ * interruptions, although these are only used in the
+ * range of the first node.
+ *
+ * This scheme needs 128 IRQ numbers per BIF node ID,
+ * which means that with the total of 512 lines
+ * available, we can have a maximum of four nodes.
+ */
+
+enum {
+	IIC_EXT_OFFSET   = 0x00, /* Start of south bridge IRQs */
+	IIC_NUM_EXT      = 0x40, /* Number of south bridge IRQs */
+	IIC_SPE_OFFSET   = 0x40, /* Start of SPE interrupts */
+	IIC_CLASS_STRIDE = 0x10, /* SPE IRQs per class    */
+	IIC_IPI_OFFSET   = 0x70, /* Start of IPI IRQs */
+	IIC_NUM_IPIS     = 0x10, /* IRQs reserved for IPI */
+	IIC_NODE_STRIDE  = 0x80, /* Total IRQs per node   */
+};
+
+extern void iic_init_IRQ(void);
+extern int  iic_get_irq(struct pt_regs *regs);
+extern void iic_cause_IPI(int cpu, int mesg);
+extern void iic_request_IPIs(void);
+extern void iic_setup_cpu(void);
+extern void iic_local_enable(void);
+extern void iic_local_disable(void);
+
+
+extern void spider_init_IRQ(void);
+extern int spider_get_irq(unsigned long int_pending);
+
+#endif
+#endif /* ASM_BPA_IIC_H */
diff --git a/arch/ppc64/kernel/bpa_iommu.c b/arch/ppc64/kernel/bpa_iommu.c
new file mode 100644
index 0000000..f33a7bc
--- /dev/null
+++ b/arch/ppc64/kernel/bpa_iommu.c
@@ -0,0 +1,377 @@
+/*
+ * IOMMU implementation for Broadband Processor Architecture
+ * We just establish a linear mapping at boot by setting all the
+ * IOPT cache entries in the CPU.
+ * The mapping functions should be identical to pci_direct_iommu, 
+ * except for the handling of the high order bit that is required
+ * by the Spider bridge. These should be split into a separate
+ * file at the point where we get a different bridge chip.
+ *
+ * Copyright (C) 2005 IBM Deutschland Entwicklung GmbH,
+ *			 Arnd Bergmann <arndb@de.ibm.com>
+ *
+ * Based on linear mapping
+ * Copyright (C) 2003 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.
+ */
+
+#undef DEBUG
+
+#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 <linux/mm.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/sections.h>
+#include <asm/iommu.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+#include <asm/abs_addr.h>
+#include <asm/system.h>
+
+#include "pci.h"
+#include "bpa_iommu.h"
+
+static inline unsigned long 
+get_iopt_entry(unsigned long real_address, unsigned long ioid,
+			 unsigned long prot)
+{
+	return (prot & IOPT_PROT_MASK)
+	     | (IOPT_COHERENT)
+	     | (IOPT_ORDER_VC)
+	     | (real_address & IOPT_RPN_MASK)
+	     | (ioid & IOPT_IOID_MASK);
+}
+
+typedef struct {
+	unsigned long val;
+} ioste;
+
+static inline ioste
+mk_ioste(unsigned long val)
+{
+	ioste ioste = { .val = val, };
+	return ioste;
+}
+
+static inline ioste
+get_iost_entry(unsigned long iopt_base, unsigned long io_address, unsigned page_size)
+{
+	unsigned long ps;
+	unsigned long iostep;
+	unsigned long nnpt;
+	unsigned long shift;
+
+	switch (page_size) {
+	case 0x1000000:
+		ps = IOST_PS_16M;
+		nnpt = 0;  /* one page per segment */
+		shift = 5; /* segment has 16 iopt entries */
+		break;
+
+	case 0x100000:
+		ps = IOST_PS_1M;
+		nnpt = 0;  /* one page per segment */
+		shift = 1; /* segment has 256 iopt entries */
+		break;
+
+	case 0x10000:
+		ps = IOST_PS_64K;
+		nnpt = 0x07; /* 8 pages per io page table */
+		shift = 0;   /* all entries are used */
+		break;
+
+	case 0x1000:
+		ps = IOST_PS_4K;
+		nnpt = 0x7f; /* 128 pages per io page table */
+		shift = 0;   /* all entries are used */
+		break;
+
+	default: /* not a known compile time constant */
+		BUILD_BUG_ON(1);
+		break;
+	}
+
+	iostep = iopt_base +
+			 /* need 8 bytes per iopte */
+			(((io_address / page_size * 8)
+			 /* align io page tables on 4k page boundaries */
+				 << shift) 
+			 /* nnpt+1 pages go into each iopt */
+				 & ~(nnpt << 12));
+
+	nnpt++; /* this seems to work, but the documentation is not clear
+		   about wether we put nnpt or nnpt-1 into the ioste bits.
+		   In theory, this can't work for 4k pages. */
+	return mk_ioste(IOST_VALID_MASK
+			| (iostep & IOST_PT_BASE_MASK)
+			| ((nnpt << 5) & IOST_NNPT_MASK)
+			| (ps & IOST_PS_MASK));
+}
+
+/* compute the address of an io pte */
+static inline unsigned long
+get_ioptep(ioste iost_entry, unsigned long io_address)
+{
+	unsigned long iopt_base;
+	unsigned long page_size;
+	unsigned long page_number;
+	unsigned long iopt_offset;
+
+	iopt_base = iost_entry.val & IOST_PT_BASE_MASK;
+	page_size = iost_entry.val & IOST_PS_MASK;
+
+	/* decode page size to compute page number */
+	page_number = (io_address & 0x0fffffff) >> (10 + 2 * page_size);
+	/* page number is an offset into the io page table */
+	iopt_offset = (page_number << 3) & 0x7fff8ul;
+	return iopt_base + iopt_offset;
+}
+
+/* compute the tag field of the iopt cache entry */
+static inline unsigned long
+get_ioc_tag(ioste iost_entry, unsigned long io_address)
+{
+	unsigned long iopte = get_ioptep(iost_entry, io_address);
+
+	return IOPT_VALID_MASK
+	     | ((iopte & 0x00000000000000ff8ul) >> 3)
+	     | ((iopte & 0x0000003fffffc0000ul) >> 9);
+}
+
+/* compute the hashed 6 bit index for the 4-way associative pte cache */
+static inline unsigned long
+get_ioc_hash(ioste iost_entry, unsigned long io_address)
+{
+	unsigned long iopte = get_ioptep(iost_entry, io_address);
+
+	return ((iopte & 0x000000000000001f8ul) >> 3)
+	     ^ ((iopte & 0x00000000000020000ul) >> 17)
+	     ^ ((iopte & 0x00000000000010000ul) >> 15)
+	     ^ ((iopte & 0x00000000000008000ul) >> 13)
+	     ^ ((iopte & 0x00000000000004000ul) >> 11)
+	     ^ ((iopte & 0x00000000000002000ul) >> 9)
+	     ^ ((iopte & 0x00000000000001000ul) >> 7);
+}
+
+/* same as above, but pretend that we have a simpler 1-way associative
+   pte cache with an 8 bit index */
+static inline unsigned long
+get_ioc_hash_1way(ioste iost_entry, unsigned long io_address)
+{
+	unsigned long iopte = get_ioptep(iost_entry, io_address);
+
+	return ((iopte & 0x000000000000001f8ul) >> 3)
+	     ^ ((iopte & 0x00000000000020000ul) >> 17)
+	     ^ ((iopte & 0x00000000000010000ul) >> 15)
+	     ^ ((iopte & 0x00000000000008000ul) >> 13)
+	     ^ ((iopte & 0x00000000000004000ul) >> 11)
+	     ^ ((iopte & 0x00000000000002000ul) >> 9)
+	     ^ ((iopte & 0x00000000000001000ul) >> 7)
+	     ^ ((iopte & 0x0000000000000c000ul) >> 8);
+}
+
+static inline ioste
+get_iost_cache(void __iomem *base, unsigned long index)
+{
+	unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR);
+	return mk_ioste(in_be64(&p[index]));
+}
+
+static inline void
+set_iost_cache(void __iomem *base, unsigned long index, ioste ste)
+{
+	unsigned long __iomem *p = (base + IOC_ST_CACHE_DIR);
+	pr_debug("ioste %02lx was %016lx, store %016lx", index,
+			get_iost_cache(base, index).val, ste.val);
+	out_be64(&p[index], ste.val);
+	pr_debug(" now %016lx\n", get_iost_cache(base, index).val);
+}
+
+static inline unsigned long
+get_iopt_cache(void __iomem *base, unsigned long index, unsigned long *tag)
+{
+	unsigned long __iomem *tags = (void *)(base + IOC_PT_CACHE_DIR);
+	unsigned long __iomem *p = (void *)(base + IOC_PT_CACHE_REG);	
+
+	*tag = tags[index];
+	rmb();
+	return *p;
+}
+
+static inline void
+set_iopt_cache(void __iomem *base, unsigned long index,
+		 unsigned long tag, unsigned long val)
+{
+	unsigned long __iomem *tags = base + IOC_PT_CACHE_DIR;
+	unsigned long __iomem *p = base + IOC_PT_CACHE_REG;
+	pr_debug("iopt %02lx was v%016lx/t%016lx, store v%016lx/t%016lx\n",
+		index, get_iopt_cache(base, index, &oldtag), oldtag, val, tag);
+
+	out_be64(p, val);
+	out_be64(&tags[index], tag);
+}
+
+static inline void
+set_iost_origin(void __iomem *base)
+{
+	unsigned long __iomem *p = base + IOC_ST_ORIGIN;
+	unsigned long origin = IOSTO_ENABLE | IOSTO_SW;
+
+	pr_debug("iost_origin %016lx, now %016lx\n", in_be64(p), origin);
+	out_be64(p, origin);
+}
+
+static inline void
+set_iocmd_config(void __iomem *base)
+{
+	unsigned long __iomem *p = base + 0xc00;
+	unsigned long conf;
+
+	conf = in_be64(p);
+	pr_debug("iost_conf %016lx, now %016lx\n", conf, conf | IOCMD_CONF_TE);
+	out_be64(p, conf | IOCMD_CONF_TE);
+}
+
+/* FIXME: get these from the device tree */
+#define ioc_base	0x20000511000ull
+#define ioc_mmio_base	0x20000510000ull
+#define ioid		0x48a
+#define iopt_phys_offset (- 0x20000000) /* We have a 512MB offset from the SB */
+#define io_page_size	0x1000000
+
+static unsigned long map_iopt_entry(unsigned long address)
+{
+	switch (address >> 20) {
+	case 0x600:
+		address = 0x24020000000ull; /* spider i/o */
+		break;
+	default:
+		address += iopt_phys_offset;
+		break;
+	}
+
+	return get_iopt_entry(address, ioid, IOPT_PROT_RW);
+}
+
+static void iommu_bus_setup_null(struct pci_bus *b) { }
+static void iommu_dev_setup_null(struct pci_dev *d) { }
+
+/* initialize the iommu to support a simple linear mapping
+ * for each DMA window used by any device. For now, we
+ * happen to know that there is only one DMA window in use,
+ * starting at iopt_phys_offset. */
+static void bpa_map_iommu(void)
+{
+	unsigned long address;
+	void __iomem *base;
+	ioste ioste;
+	unsigned long index;
+
+	base = __ioremap(ioc_base, 0x1000, _PAGE_NO_CACHE);
+	pr_debug("%lx mapped to %p\n", ioc_base, base);
+	set_iocmd_config(base);
+	iounmap(base);
+
+	base = __ioremap(ioc_mmio_base, 0x1000, _PAGE_NO_CACHE);
+	pr_debug("%lx mapped to %p\n", ioc_mmio_base, base);
+
+	set_iost_origin(base);
+
+	for (address = 0; address < 0x100000000ul; address += io_page_size) {
+		ioste = get_iost_entry(0x10000000000ul, address, io_page_size);
+		if ((address & 0xfffffff) == 0) /* segment start */
+			set_iost_cache(base, address >> 28, ioste);
+		index = get_ioc_hash_1way(ioste, address);
+		pr_debug("addr %08lx, index %02lx, ioste %016lx\n",
+					 address, index, ioste.val);
+		set_iopt_cache(base,
+			get_ioc_hash_1way(ioste, address),
+			get_ioc_tag(ioste, address),
+			map_iopt_entry(address));
+	}
+	iounmap(base);
+}
+
+
+static void *bpa_alloc_coherent(struct device *hwdev, size_t size,
+			   dma_addr_t *dma_handle, unsigned int __nocast flag)
+{
+	void *ret;
+
+	ret = (void *)__get_free_pages(flag, get_order(size));
+	if (ret != NULL) {
+		memset(ret, 0, size);
+		*dma_handle = virt_to_abs(ret) | BPA_DMA_VALID;
+	}
+	return ret;
+}
+
+static void bpa_free_coherent(struct device *hwdev, size_t size,
+				 void *vaddr, dma_addr_t dma_handle)
+{
+	free_pages((unsigned long)vaddr, get_order(size));
+}
+
+static dma_addr_t bpa_map_single(struct device *hwdev, void *ptr,
+		size_t size, enum dma_data_direction direction)
+{
+	return virt_to_abs(ptr) | BPA_DMA_VALID;
+}
+
+static void bpa_unmap_single(struct device *hwdev, dma_addr_t dma_addr,
+		size_t size, enum dma_data_direction direction)
+{
+}
+
+static int bpa_map_sg(struct device *hwdev, struct scatterlist *sg,
+		int nents, enum dma_data_direction direction)
+{
+	int i;
+
+	for (i = 0; i < nents; i++, sg++) {
+		sg->dma_address = (page_to_phys(sg->page) + sg->offset)
+					| BPA_DMA_VALID;
+		sg->dma_length = sg->length;
+	}
+
+	return nents;
+}
+
+static void bpa_unmap_sg(struct device *hwdev, struct scatterlist *sg,
+		int nents, enum dma_data_direction direction)
+{
+}
+
+static int bpa_dma_supported(struct device *dev, u64 mask)
+{
+	return mask < 0x100000000ull;
+}
+
+void bpa_init_iommu(void)
+{
+	bpa_map_iommu();
+
+	/* Direct I/O, IOMMU off */
+	ppc_md.iommu_dev_setup = iommu_dev_setup_null;
+	ppc_md.iommu_bus_setup = iommu_bus_setup_null;
+
+	pci_dma_ops.alloc_coherent = bpa_alloc_coherent;
+	pci_dma_ops.free_coherent = bpa_free_coherent;
+	pci_dma_ops.map_single = bpa_map_single;
+	pci_dma_ops.unmap_single = bpa_unmap_single;
+	pci_dma_ops.map_sg = bpa_map_sg;
+	pci_dma_ops.unmap_sg = bpa_unmap_sg;
+	pci_dma_ops.dma_supported = bpa_dma_supported;
+}
diff --git a/arch/ppc64/kernel/bpa_iommu.h b/arch/ppc64/kernel/bpa_iommu.h
new file mode 100644
index 0000000..e547d77
--- /dev/null
+++ b/arch/ppc64/kernel/bpa_iommu.h
@@ -0,0 +1,65 @@
+#ifndef BPA_IOMMU_H
+#define BPA_IOMMU_H
+
+/* some constants */
+enum {
+	/* segment table entries */
+	IOST_VALID_MASK	  = 0x8000000000000000ul,
+	IOST_TAG_MASK     = 0x3000000000000000ul,
+	IOST_PT_BASE_MASK = 0x000003fffffff000ul,
+	IOST_NNPT_MASK	  = 0x0000000000000fe0ul,
+	IOST_PS_MASK	  = 0x000000000000000ful,
+
+	IOST_PS_4K	  = 0x1,
+	IOST_PS_64K	  = 0x3,
+	IOST_PS_1M	  = 0x5,
+	IOST_PS_16M	  = 0x7,
+
+	/* iopt tag register */
+	IOPT_VALID_MASK   = 0x0000000200000000ul,
+	IOPT_TAG_MASK	  = 0x00000001fffffffful,
+
+	/* iopt cache register */
+	IOPT_PROT_MASK	  = 0xc000000000000000ul,
+	IOPT_PROT_NONE	  = 0x0000000000000000ul,
+	IOPT_PROT_READ	  = 0x4000000000000000ul,
+	IOPT_PROT_WRITE	  = 0x8000000000000000ul,
+	IOPT_PROT_RW	  = 0xc000000000000000ul,
+	IOPT_COHERENT	  = 0x2000000000000000ul,
+	
+	IOPT_ORDER_MASK	  = 0x1800000000000000ul,
+	/* order access to same IOID/VC on same address */
+	IOPT_ORDER_ADDR	  = 0x0800000000000000ul,
+	/* similar, but only after a write access */
+	IOPT_ORDER_WRITES = 0x1000000000000000ul,
+	/* Order all accesses to same IOID/VC */
+	IOPT_ORDER_VC	  = 0x1800000000000000ul,
+	
+	IOPT_RPN_MASK	  = 0x000003fffffff000ul,
+	IOPT_HINT_MASK	  = 0x0000000000000800ul,
+	IOPT_IOID_MASK	  = 0x00000000000007fful,
+
+	IOSTO_ENABLE	  = 0x8000000000000000ul,
+	IOSTO_ORIGIN	  = 0x000003fffffff000ul,
+	IOSTO_HW	  = 0x0000000000000800ul,
+	IOSTO_SW	  = 0x0000000000000400ul,
+
+	IOCMD_CONF_TE	  = 0x0000800000000000ul,
+
+	/* memory mapped registers */
+	IOC_PT_CACHE_DIR  = 0x000,
+	IOC_ST_CACHE_DIR  = 0x800,
+	IOC_PT_CACHE_REG  = 0x910,
+	IOC_ST_ORIGIN     = 0x918,
+	IOC_CONF	  = 0x930,
+
+	/* The high bit needs to be set on every DMA address,
+	   only 2GB are addressable */
+	BPA_DMA_VALID	  = 0x80000000,
+	BPA_DMA_MASK	  = 0x7fffffff,
+};
+
+
+void bpa_init_iommu(void);
+
+#endif
diff --git a/arch/ppc64/kernel/bpa_nvram.c b/arch/ppc64/kernel/bpa_nvram.c
new file mode 100644
index 0000000..06a119c
--- /dev/null
+++ b/arch/ppc64/kernel/bpa_nvram.c
@@ -0,0 +1,118 @@
+/*
+ * NVRAM for CPBW
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Authors : Utz Bacher <utz.bacher@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.
+ */
+
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/machdep.h>
+#include <asm/nvram.h>
+#include <asm/prom.h>
+
+static void __iomem *bpa_nvram_start;
+static long bpa_nvram_len;
+static spinlock_t bpa_nvram_lock = SPIN_LOCK_UNLOCKED;
+
+static ssize_t bpa_nvram_read(char *buf, size_t count, loff_t *index)
+{
+	unsigned long flags;
+
+	if (*index >= bpa_nvram_len)
+		return 0;
+	if (*index + count > bpa_nvram_len)
+		count = bpa_nvram_len - *index;
+
+	spin_lock_irqsave(&bpa_nvram_lock, flags);
+
+	memcpy_fromio(buf, bpa_nvram_start + *index, count);
+
+	spin_unlock_irqrestore(&bpa_nvram_lock, flags);
+	
+	*index += count;
+	return count;
+}
+
+static ssize_t bpa_nvram_write(char *buf, size_t count, loff_t *index)
+{
+	unsigned long flags;
+
+	if (*index >= bpa_nvram_len)
+		return 0;
+	if (*index + count > bpa_nvram_len)
+		count = bpa_nvram_len - *index;
+
+	spin_lock_irqsave(&bpa_nvram_lock, flags);
+
+	memcpy_toio(bpa_nvram_start + *index, buf, count);
+
+	spin_unlock_irqrestore(&bpa_nvram_lock, flags);
+	
+	*index += count;
+	return count;
+}
+
+static ssize_t bpa_nvram_get_size(void)
+{
+	return bpa_nvram_len;
+}
+
+int __init bpa_nvram_init(void)
+{
+	struct device_node *nvram_node;
+	unsigned long *buffer;
+	int proplen;
+	unsigned long nvram_addr;
+	int ret;
+
+	ret = -ENODEV;
+	nvram_node = of_find_node_by_type(NULL, "nvram");
+	if (!nvram_node)
+		goto out;
+
+	ret = -EIO;
+	buffer = (unsigned long *)get_property(nvram_node, "reg", &proplen);
+	if (proplen != 2*sizeof(unsigned long))
+		goto out;
+
+	ret = -ENODEV;
+	nvram_addr = buffer[0];
+	bpa_nvram_len = buffer[1];
+	if ( (!bpa_nvram_len) || (!nvram_addr) )
+		goto out;
+
+	bpa_nvram_start = ioremap(nvram_addr, bpa_nvram_len);
+	if (!bpa_nvram_start)
+		goto out;
+
+	printk(KERN_INFO "BPA NVRAM, %luk mapped to %p\n",
+	       bpa_nvram_len >> 10, bpa_nvram_start);
+
+	ppc_md.nvram_read	= bpa_nvram_read;
+	ppc_md.nvram_write	= bpa_nvram_write;
+	ppc_md.nvram_size	= bpa_nvram_get_size;
+
+out:
+	of_node_put(nvram_node);
+	return ret;
+}
diff --git a/arch/ppc64/kernel/bpa_setup.c b/arch/ppc64/kernel/bpa_setup.c
new file mode 100644
index 0000000..57b3db6
--- /dev/null
+++ b/arch/ppc64/kernel/bpa_setup.c
@@ -0,0 +1,140 @@
+/*
+ *  linux/arch/ppc/kernel/bpa_setup.c
+ *
+ *  Copyright (C) 1995  Linus Torvalds
+ *  Adapted from 'alpha' version by Gary Thomas
+ *  Modified by Cort Dougan (cort@cs.nmt.edu)
+ *  Modified by PPC64 Team, IBM Corp
+ *  Modified by BPA Team, IBM Deutschland Entwicklung GmbH
+ *
+ * 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/config.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/console.h>
+
+#include <asm/mmu.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/prom.h>
+#include <asm/rtas.h>
+#include <asm/pci-bridge.h>
+#include <asm/iommu.h>
+#include <asm/dma.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/nvram.h>
+#include <asm/cputable.h>
+
+#include "pci.h"
+#include "bpa_iic.h"
+#include "bpa_iommu.h"
+
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+void bpa_get_cpuinfo(struct seq_file *m)
+{
+	struct device_node *root;
+	const char *model = "";
+
+	root = of_find_node_by_path("/");
+	if (root)
+		model = get_property(root, "model", NULL);
+	seq_printf(m, "machine\t\t: BPA %s\n", model);
+	of_node_put(root);
+}
+
+static void bpa_progress(char *s, unsigned short hex)
+{
+	printk("*** %04x : %s\n", hex, s ? s : "");
+}
+
+static void __init bpa_setup_arch(void)
+{
+	ppc_md.init_IRQ       = iic_init_IRQ;
+	ppc_md.get_irq        = iic_get_irq;
+
+#ifdef CONFIG_SMP
+	smp_init_pSeries();
+#endif
+
+	/* init to some ~sane value until calibrate_delay() runs */
+	loops_per_jiffy = 50000000;
+
+	if (ROOT_DEV == 0) {
+		printk("No ramdisk, default root is /dev/hda2\n");
+		ROOT_DEV = Root_HDA2;
+	}
+
+	/* Find and initialize PCI host bridges */
+	init_pci_config_tokens();
+	find_and_init_phbs();
+	spider_init_IRQ();
+#ifdef CONFIG_DUMMY_CONSOLE
+	conswitchp = &dummy_con;
+#endif
+
+	bpa_nvram_init();
+}
+
+/*
+ * Early initialization.  Relocation is on but do not reference unbolted pages
+ */
+static void __init bpa_init_early(void)
+{
+	DBG(" -> bpa_init_early()\n");
+
+	hpte_init_native();
+
+	bpa_init_iommu();
+
+	ppc64_interrupt_controller = IC_BPA_IIC;
+
+	DBG(" <- bpa_init_early()\n");
+}
+
+
+static int __init bpa_probe(int platform)
+{
+	if (platform != PLATFORM_BPA)
+		return 0;
+
+	return 1;
+}
+
+struct machdep_calls __initdata bpa_md = {
+	.probe			= bpa_probe,
+	.setup_arch		= bpa_setup_arch,
+	.init_early		= bpa_init_early,
+	.get_cpuinfo		= bpa_get_cpuinfo,
+	.restart		= rtas_restart,
+	.power_off		= rtas_power_off,
+	.halt			= rtas_halt,
+	.get_boot_time		= rtas_get_boot_time,
+	.get_rtc_time		= rtas_get_rtc_time,
+	.set_rtc_time		= rtas_set_rtc_time,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= bpa_progress,
+};
diff --git a/arch/ppc64/kernel/cpu_setup_power4.S b/arch/ppc64/kernel/cpu_setup_power4.S
index 3bd9518..42fc08c 100644
--- a/arch/ppc64/kernel/cpu_setup_power4.S
+++ b/arch/ppc64/kernel/cpu_setup_power4.S
@@ -73,7 +73,21 @@
 
 _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/ppc64/kernel/cputable.c b/arch/ppc64/kernel/cputable.c
index 8644a86..1d162c7 100644
--- a/arch/ppc64/kernel/cputable.c
+++ b/arch/ppc64/kernel/cputable.c
@@ -34,6 +34,7 @@
 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_ppc970(unsigned long offset, struct cpu_spec* spec);
+extern void __setup_cpu_be(unsigned long offset, struct cpu_spec* spec);
 
 
 /* We only set the altivec features if the kernel was compiled with altivec
@@ -162,6 +163,16 @@
 	    __setup_cpu_power4,
 	    COMMON_PPC64_FW
     },
+    {	/* BE DD1.x  */
+	    0xffff0000, 0x00700000, "Broadband Engine",
+	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
+		    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP |
+		    CPU_FTR_SMT,
+	    COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP,
+	    128, 128,
+	    __setup_cpu_be,
+	    COMMON_PPC64_FW
+    },
     {	/* default match */
 	    0x00000000, 0x00000000, "POWER4 (compatible)",
   	    CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE |
diff --git a/arch/ppc64/kernel/dma.c b/arch/ppc64/kernel/dma.c
index ce714c9..4da8e31 100644
--- a/arch/ppc64/kernel/dma.c
+++ b/arch/ppc64/kernel/dma.c
@@ -15,8 +15,10 @@
 
 static struct dma_mapping_ops *get_dma_ops(struct device *dev)
 {
+#ifdef CONFIG_PCI
 	if (dev->bus == &pci_bus_type)
 		return &pci_dma_ops;
+#endif
 #ifdef CONFIG_IBMVIO
 	if (dev->bus == &vio_bus_type)
 		return &vio_dma_ops;
@@ -37,8 +39,10 @@
 
 int dma_set_mask(struct device *dev, u64 dma_mask)
 {
+#ifdef CONFIG_PCI
 	if (dev->bus == &pci_bus_type)
 		return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
+#endif
 #ifdef CONFIG_IBMVIO
 	if (dev->bus == &vio_bus_type)
 		return -EIO;
diff --git a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c
index d63d41f..af5272f 100644
--- a/arch/ppc64/kernel/eeh.c
+++ b/arch/ppc64/kernel/eeh.c
@@ -505,7 +505,7 @@
 	pte_t *ptep;
 	unsigned long pa;
 
-	ptep = find_linux_pte(ioremap_mm.pgd, token);
+	ptep = find_linux_pte(init_mm.pgd, token);
 	if (!ptep)
 		return token;
 	pa = pte_pfn(*ptep) << PAGE_SHIFT;
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S
index 346dbf6..675c270 100644
--- a/arch/ppc64/kernel/head.S
+++ b/arch/ppc64/kernel/head.S
@@ -1194,7 +1194,7 @@
 	bl	.__restore_cpu_setup
 
 	/* Set up a paca value for this processor. Since we have the
-	 * physical cpu id in r3, we need to search the pacas to find
+	 * physical cpu id in r24, we need to search the pacas to find
 	 * which logical id maps to our physical one.
 	 */
 	LOADADDR(r13, paca) 		/* Get base vaddr of paca array	 */
@@ -1207,8 +1207,8 @@
 	cmpwi	r5,NR_CPUS
 	blt	1b
 
-99:	HMT_LOW				/* Couldn't find our CPU id      */
-	b	99b
+	mr	r3,r24			/* not found, copy phys to r3	 */
+	b	.kexec_wait		/* next kernel might do better	 */
 
 2:	mtspr	SPRG3,r13		/* Save vaddr of paca in SPRG3	 */
 	/* From now on, r24 is expected to be logica cpuid */
@@ -2121,10 +2121,6 @@
 swapper_pg_dir:
 	.space	4096
 
-	.globl	ioremap_dir
-ioremap_dir:
-	.space	4096
-
 #ifdef CONFIG_SMP
 /* 1 page segment table per cpu (max 48, cpu0 allocated at STAB0_PHYS_ADDR) */
 	.globl	stab_array
diff --git a/arch/ppc64/kernel/iSeries_VpdInfo.c b/arch/ppc64/kernel/iSeries_VpdInfo.c
index a6f0ff2..d11c732 100644
--- a/arch/ppc64/kernel/iSeries_VpdInfo.c
+++ b/arch/ppc64/kernel/iSeries_VpdInfo.c
@@ -1,31 +1,31 @@
-/************************************************************************/
-/* File iSeries_vpdInfo.c created by Allan Trautman on Fri Feb  2 2001. */
-/************************************************************************/
-/* This code gets the card location of the hardware                     */
-/* Copyright (C) 20yy  <Allan H Trautman> <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.                                  */
-/*                                                                      */
-/* 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                                          */
-/************************************************************************/
-/* Change Activity:                                                     */
-/*   Created, Feb 2, 2001                                               */
-/*   Ported to ppc64, August 20, 2001                                   */
-/* End Change Activity                                                  */
-/************************************************************************/
-#include <linux/config.h>
+/*
+ * File iSeries_vpdInfo.c created by Allan Trautman on Fri Feb  2 2001.
+ *
+ * This code gets the card location of the hardware
+ * Copyright (C) 2001  <Allan H Trautman> <IBM Corp>
+ * Copyright (C) 2005  Stephen Rothwel, 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.
+ *
+ * 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
+ *
+ * Change Activity:
+ *   Created, Feb 2, 2001
+ *   Ported to ppc64, August 20, 2001
+ * End Change Activity
+ */
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/pci.h>
@@ -34,30 +34,25 @@
 
 #include <asm/iSeries/HvCallPci.h>
 #include <asm/iSeries/HvTypes.h>
-#include <asm/iSeries/mf.h>
-#include <asm/iSeries/LparData.h>
 #include <asm/iSeries/iSeries_pci.h>
-#include "pci.h"
 
 /*
  * Size of Bus VPD data
  */
 #define BUS_VPDSIZE      1024
+
 /*
  * Bus Vpd Tags
  */
-#define  VpdEndOfDataTag   0x78
 #define  VpdEndOfAreaTag   0x79
 #define  VpdIdStringTag    0x82
 #define  VpdVendorAreaTag  0x84
+
 /*
  * Mfg Area Tags
  */
-#define  VpdFruFlag       0x4647     // "FG"
 #define  VpdFruFrameId    0x4649     // "FI"
 #define  VpdSlotMapFormat 0x4D46     // "MF"
-#define  VpdAsmPartNumber 0x504E     // "PN"
-#define  VpdFruSerial     0x534E     // "SN"
 #define  VpdSlotMap       0x534D     // "SM"
 
 /*
@@ -79,74 +74,33 @@
 	char CardLocation[3];
 	char Parms[8];
 	char Reserved[2];
-}; 
+};
 typedef struct SlotMapStruct SlotMap;
 #define SLOT_ENTRY_SIZE   16
 
 /*
- * Formats the device information.
- * - Pass in pci_dev* pointer to the device.
- * - Pass in buffer to place the data.  Danger here is the buffer must
- *   be as big as the client says it is.   Should be at least 128 bytes.
- * Return will the length of the string data put in the buffer.
- * Format:
- * PCI: Bus  0, Device 26, Vendor 0x12AE  Frame  1, Card  C10  Ethernet
- * controller
- */
-int iSeries_Device_Information(struct pci_dev *PciDev, char *buffer,
-		int BufferSize)
-{
-	struct iSeries_Device_Node *DevNode =
-		(struct iSeries_Device_Node *)PciDev->sysdata;
-	int len;
-
-	if (DevNode == NULL)
-		return sprintf(buffer,
-				"PCI: iSeries_Device_Information DevNode is NULL");
-
-	if (BufferSize < 128)
-		return 0;
-
-	len = sprintf(buffer, "PCI: Bus%3d, Device%3d, Vendor %04X ",
-			ISERIES_BUS(DevNode), PCI_SLOT(PciDev->devfn),
-			PciDev->vendor);
-	len += sprintf(buffer + len, "Frame%3d, Card %4s  ",
-			DevNode->FrameId, DevNode->CardLocation);
-#ifdef CONFIG_PCI
-	if (pci_class_name(PciDev->class >> 8) == 0)
-		len += sprintf(buffer + len, "0x%04X  ",
-				(int)(PciDev->class >> 8));
-	else
-		len += sprintf(buffer + len, "%s",
-				pci_class_name(PciDev->class >> 8));
-#endif
-	return len;
-}
-
-/*
  * Parse the Slot Area
  */
-void iSeries_Parse_SlotArea(SlotMap *MapPtr, int MapLen,
-		struct iSeries_Device_Node *DevNode)
+static void __init iSeries_Parse_SlotArea(SlotMap *MapPtr, int MapLen,
+		HvAgentId agent, u8 *PhbId, char card[4])
 {
 	int SlotMapLen = MapLen;
 	SlotMap *SlotMapPtr = MapPtr;
 
 	/*
-	 * Parse Slot label until we find the one requrested
+	 * Parse Slot label until we find the one requested
 	 */
 	while (SlotMapLen > 0) {
-		if (SlotMapPtr->AgentId == DevNode->AgentId ) {
+		if (SlotMapPtr->AgentId == agent) {
 			/*
 			 * If Phb wasn't found, grab the entry first one found.
 			 */
-			if (DevNode->PhbId == 0xff)
-				DevNode->PhbId = SlotMapPtr->PhbId; 
+			if (*PhbId == 0xff)
+				*PhbId = SlotMapPtr->PhbId;
 			/* Found it, extract the data. */
-			if (SlotMapPtr->PhbId == DevNode->PhbId ) {
-	        		memcpy(&DevNode->CardLocation,
-						&SlotMapPtr->CardLocation, 3);
-				DevNode->CardLocation[3]  = 0;
+			if (SlotMapPtr->PhbId == *PhbId) {
+				memcpy(card, &SlotMapPtr->CardLocation, 3);
+				card[3]  = 0;
 				break;
 			}
 		}
@@ -159,8 +113,9 @@
 /*
  * Parse the Mfg Area
  */
-static void iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen,
-		struct iSeries_Device_Node *DevNode)
+static void __init iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen,
+		HvAgentId agent, u8 *PhbId,
+		u8 *frame, char card[4])
 {
 	MfgArea *MfgAreaPtr = (MfgArea *)AreaData;
 	int MfgAreaLen = AreaLen;
@@ -171,7 +126,7 @@
 		int MfgTagLen = MfgAreaPtr->TagLength;
 		/* Frame ID         (FI 4649020310 ) */
 		if (MfgAreaPtr->Tag == VpdFruFrameId)		/* FI  */
-			DevNode->FrameId = MfgAreaPtr->AreaData1;
+			*frame = MfgAreaPtr->AreaData1;
 		/* Slot Map Format  (MF 4D46020004 ) */
 		else if (MfgAreaPtr->Tag == VpdSlotMapFormat)	/* MF  */
 			SlotMapFmt = (MfgAreaPtr->AreaData1 * 256)
@@ -183,10 +138,11 @@
 			if (SlotMapFmt == 0x1004)
 				SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr
 						+ MFG_ENTRY_SIZE + 1);
- 	    		else
+			else
 				SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr
 						+ MFG_ENTRY_SIZE);
-	    		iSeries_Parse_SlotArea(SlotMapPtr, MfgTagLen, DevNode);
+			iSeries_Parse_SlotArea(SlotMapPtr, MfgTagLen,
+					agent, PhbId, card);
 		}
 		/*
 		 * Point to the next Mfg Area
@@ -194,19 +150,19 @@
 		 */
 		MfgAreaPtr = (MfgArea *)((char *)MfgAreaPtr + MfgTagLen
 				+ MFG_ENTRY_SIZE);
-		MfgAreaLen -= (MfgTagLen + MFG_ENTRY_SIZE); 
-	}	
+		MfgAreaLen -= (MfgTagLen + MFG_ENTRY_SIZE);
+	}
 }
 
 /*
  * Look for "BUS".. Data is not Null terminated.
  * PHBID of 0xFF indicates PHB was not found in VPD Data.
  */
-static int iSeries_Parse_PhbId(u8 *AreaPtr, int AreaLength)
+static int __init iSeries_Parse_PhbId(u8 *AreaPtr, int AreaLength)
 {
 	u8 *PhbPtr = AreaPtr;
 	int DataLen = AreaLength;
-	char PhbId = 0xFF;                   
+	char PhbId = 0xFF;
 
 	while (DataLen > 0) {
 		if ((*PhbPtr == 'B') && (*(PhbPtr + 1) == 'U')
@@ -216,7 +172,7 @@
 				++PhbPtr;
 			PhbId = (*PhbPtr & 0x0F);
 			break;
-        	}
+		}
 		++PhbPtr;
 		--DataLen;
 	}
@@ -226,52 +182,90 @@
 /*
  * Parse out the VPD Areas
  */
-static void iSeries_Parse_Vpd(u8 *VpdData, int VpdDataLen,
-		struct iSeries_Device_Node *DevNode)
+static void __init iSeries_Parse_Vpd(u8 *VpdData, int VpdDataLen,
+		HvAgentId agent, u8 *frame, char card[4])
 {
 	u8 *TagPtr = VpdData;
 	int DataLen = VpdDataLen - 3;
+	u8 PhbId;
 
 	while ((*TagPtr != VpdEndOfAreaTag) && (DataLen > 0)) {
-		int AreaLen = *(TagPtr + 1) + (*(TagPtr + 2) * 256);	
+		int AreaLen = *(TagPtr + 1) + (*(TagPtr + 2) * 256);
 		u8 *AreaData  = TagPtr + 3;
 
 		if (*TagPtr == VpdIdStringTag)
-			DevNode->PhbId = iSeries_Parse_PhbId(AreaData, AreaLen);
+			PhbId = iSeries_Parse_PhbId(AreaData, AreaLen);
 		else if (*TagPtr == VpdVendorAreaTag)
-	    		iSeries_Parse_MfgArea(AreaData, AreaLen, DevNode);
+			iSeries_Parse_MfgArea(AreaData, AreaLen,
+					agent, &PhbId, frame, card);
 		/* Point to next Area. */
 		TagPtr  = AreaData + AreaLen;
 		DataLen -= AreaLen;
 	}
-}    
+}
 
-void iSeries_Get_Location_Code(struct iSeries_Device_Node *DevNode)
+static void __init iSeries_Get_Location_Code(u16 bus, HvAgentId agent,
+		u8 *frame, char card[4])
 {
 	int BusVpdLen = 0;
-	u8 *BusVpdPtr = (u8 *)kmalloc(BUS_VPDSIZE, GFP_KERNEL);
+	u8 *BusVpdPtr = kmalloc(BUS_VPDSIZE, GFP_KERNEL);
 
 	if (BusVpdPtr == NULL) {
 		printk("PCI: Bus VPD Buffer allocation failure.\n");
 		return;
 	}
-	BusVpdLen = HvCallPci_getBusVpd(ISERIES_BUS(DevNode),
-					ISERIES_HV_ADDR(BusVpdPtr),
+	BusVpdLen = HvCallPci_getBusVpd(bus, ISERIES_HV_ADDR(BusVpdPtr),
 					BUS_VPDSIZE);
 	if (BusVpdLen == 0) {
-		kfree(BusVpdPtr);
 		printk("PCI: Bus VPD Buffer zero length.\n");
-		return;
+		goto out_free;
 	}
 	/* printk("PCI: BusVpdPtr: %p, %d\n",BusVpdPtr, BusVpdLen); */
 	/* Make sure this is what I think it is */
 	if (*BusVpdPtr != VpdIdStringTag) {	/* 0x82 */
 		printk("PCI: Bus VPD Buffer missing starting tag.\n");
-		kfree(BusVpdPtr);
+		goto out_free;
+	}
+	iSeries_Parse_Vpd(BusVpdPtr, BusVpdLen, agent, frame, card);
+out_free:
+	kfree(BusVpdPtr);
+}
+
+/*
+ * Prints the device information.
+ * - Pass in pci_dev* pointer to the device.
+ * - Pass in the device count
+ *
+ * Format:
+ * PCI: Bus  0, Device 26, Vendor 0x12AE  Frame  1, Card  C10  Ethernet
+ * controller
+ */
+void __init iSeries_Device_Information(struct pci_dev *PciDev, int count)
+{
+	struct iSeries_Device_Node *DevNode = PciDev->sysdata;
+	u16 bus;
+	u8 frame;
+	char card[4];
+	HvSubBusNumber subbus;
+	HvAgentId agent;
+
+	if (DevNode == NULL) {
+		printk("%d. PCI: iSeries_Device_Information DevNode is NULL\n",
+				count);
 		return;
 	}
-	iSeries_Parse_Vpd(BusVpdPtr,BusVpdLen, DevNode);
-	sprintf(DevNode->Location, "Frame%3d, Card %-4s", DevNode->FrameId,
-			DevNode->CardLocation);
-	kfree(BusVpdPtr);
+
+	bus = ISERIES_BUS(DevNode);
+	subbus = ISERIES_SUBBUS(DevNode);
+	agent = ISERIES_PCI_AGENTID(ISERIES_GET_DEVICE_FROM_SUBBUS(subbus),
+			ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus));
+	iSeries_Get_Location_Code(bus, agent, &frame, card);
+
+	printk("%d. PCI: Bus%3d, Device%3d, Vendor %04X Frame%3d, Card %4s  ",
+			count, bus, PCI_SLOT(PciDev->devfn), PciDev->vendor,
+			frame, card);
+	if (pci_class_name(PciDev->class >> 8) == 0)
+		printk("0x%04X\n", (int)(PciDev->class >> 8));
+	else
+		printk("%s\n", pci_class_name(PciDev->class >> 8));
 }
diff --git a/arch/ppc64/kernel/iSeries_iommu.c b/arch/ppc64/kernel/iSeries_iommu.c
index 4e1a47c..f8ff1bb 100644
--- a/arch/ppc64/kernel/iSeries_iommu.c
+++ b/arch/ppc64/kernel/iSeries_iommu.c
@@ -83,7 +83,7 @@
 	}
 }
 
-
+#ifdef CONFIG_PCI
 /*
  * This function compares the known tables to find an iommu_table
  * that has already been built for hardware TCEs.
@@ -159,6 +159,7 @@
 	else
 		kfree(tbl);
 }
+#endif
 
 static void iommu_dev_setup_iSeries(struct pci_dev *dev) { }
 static void iommu_bus_setup_iSeries(struct pci_bus *bus) { }
diff --git a/arch/ppc64/kernel/iSeries_irq.c b/arch/ppc64/kernel/iSeries_irq.c
index f831d25..77376c1 100644
--- a/arch/ppc64/kernel/iSeries_irq.c
+++ b/arch/ppc64/kernel/iSeries_irq.c
@@ -1,27 +1,29 @@
-/************************************************************************/
-/* This module supports the iSeries PCI bus interrupt handling          */
-/* Copyright (C) 20yy  <Robert L Holtorf> <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.                                  */
-/*                                                                      */
-/* 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                                          */
-/************************************************************************/
-/* Change Activity:                                                     */
-/*   Created, December 13, 2000 by Wayne Holm                           */ 
-/* End Change Activity                                                  */
-/************************************************************************/
+/*
+ * This module supports the iSeries PCI bus interrupt handling
+ * Copyright (C) 20yy  <Robert L Holtorf> <IBM Corp>
+ * Copyright (C) 2004-2005 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
+ *
+ * Change Activity:
+ *   Created, December 13, 2000 by Wayne Holm
+ * End Change Activity
+ */
+#include <linux/config.h>
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/threads.h>
@@ -30,30 +32,15 @@
 #include <linux/string.h>
 #include <linux/bootmem.h>
 #include <linux/ide.h>
-
 #include <linux/irq.h>
 #include <linux/spinlock.h>
-#include <asm/ppcdebug.h>
 
+#include <asm/ppcdebug.h>
+#include <asm/iSeries/HvTypes.h>
+#include <asm/iSeries/HvLpEvent.h>
 #include <asm/iSeries/HvCallPci.h>
 #include <asm/iSeries/HvCallXm.h>
 #include <asm/iSeries/iSeries_irq.h>
-#include <asm/iSeries/XmPciLpEvent.h>
-
-static unsigned int iSeries_startup_IRQ(unsigned int irq);
-static void iSeries_shutdown_IRQ(unsigned int irq);
-static void iSeries_enable_IRQ(unsigned int irq);
-static void iSeries_disable_IRQ(unsigned int irq);
-static void iSeries_end_IRQ(unsigned int irq);
-
-static hw_irq_controller iSeries_IRQ_handler = {
-	.typename = "iSeries irq controller",
-	.startup = iSeries_startup_IRQ,
-	.shutdown = iSeries_shutdown_IRQ,
-	.enable = iSeries_enable_IRQ,
-	.disable = iSeries_disable_IRQ,
-	.end = iSeries_end_IRQ
-};
 
 /* This maps virtual irq numbers to real irqs */
 unsigned int virt_irq_to_real_map[NR_IRQS];
@@ -62,37 +49,187 @@
 /* Note: the pcnet32 driver assumes irq numbers < 2 aren't valid. :( */
 static int next_virtual_irq = 2;
 
-/* This is called by init_IRQ.  set in ppc_md.init_IRQ by iSeries_setup.c */
-void __init iSeries_init_IRQ(void)
+static long Pci_Interrupt_Count;
+static long Pci_Event_Count;
+
+enum XmPciLpEvent_Subtype {
+	XmPciLpEvent_BusCreated		= 0,	// PHB has been created
+	XmPciLpEvent_BusError		= 1,	// PHB has failed
+	XmPciLpEvent_BusFailed		= 2,	// Msg to Secondary, Primary failed bus
+	XmPciLpEvent_NodeFailed		= 4,	// Multi-adapter bridge has failed
+	XmPciLpEvent_NodeRecovered	= 5,	// Multi-adapter bridge has recovered
+	XmPciLpEvent_BusRecovered	= 12,	// PHB has been recovered
+	XmPciLpEvent_UnQuiesceBus	= 18,	// Secondary bus unqiescing
+	XmPciLpEvent_BridgeError	= 21,	// Bridge Error
+	XmPciLpEvent_SlotInterrupt	= 22	// Slot interrupt
+};
+
+struct XmPciLpEvent_BusInterrupt {
+	HvBusNumber	busNumber;
+	HvSubBusNumber	subBusNumber;
+};
+
+struct XmPciLpEvent_NodeInterrupt {
+	HvBusNumber	busNumber;
+	HvSubBusNumber	subBusNumber;
+	HvAgentId	deviceId;
+};
+
+struct XmPciLpEvent {
+	struct HvLpEvent hvLpEvent;
+
+	union {
+		u64 alignData;			// Align on an 8-byte boundary
+
+		struct {
+			u32		fisr;
+			HvBusNumber	busNumber;
+			HvSubBusNumber	subBusNumber;
+			HvAgentId	deviceId;
+		} slotInterrupt;
+
+		struct XmPciLpEvent_BusInterrupt busFailed;
+		struct XmPciLpEvent_BusInterrupt busRecovered;
+		struct XmPciLpEvent_BusInterrupt busCreated;
+
+		struct XmPciLpEvent_NodeInterrupt nodeFailed;
+		struct XmPciLpEvent_NodeInterrupt nodeRecovered;
+
+	} eventData;
+
+};
+
+static void intReceived(struct XmPciLpEvent *eventParm,
+		struct pt_regs *regsParm)
 {
-	/* Register PCI event handler and open an event path */
-	XmPciLpEvent_init();
+	int irq;
+
+	++Pci_Interrupt_Count;
+
+	switch (eventParm->hvLpEvent.xSubtype) {
+	case XmPciLpEvent_SlotInterrupt:
+		irq = eventParm->hvLpEvent.xCorrelationToken;
+		/* Dispatch the interrupt handlers for this irq */
+		ppc_irq_dispatch_handler(regsParm, irq);
+		HvCallPci_eoi(eventParm->eventData.slotInterrupt.busNumber,
+			eventParm->eventData.slotInterrupt.subBusNumber,
+			eventParm->eventData.slotInterrupt.deviceId);
+		break;
+		/* Ignore error recovery events for now */
+	case XmPciLpEvent_BusCreated:
+		printk(KERN_INFO "intReceived: system bus %d created\n",
+			eventParm->eventData.busCreated.busNumber);
+		break;
+	case XmPciLpEvent_BusError:
+	case XmPciLpEvent_BusFailed:
+		printk(KERN_INFO "intReceived: system bus %d failed\n",
+			eventParm->eventData.busFailed.busNumber);
+		break;
+	case XmPciLpEvent_BusRecovered:
+	case XmPciLpEvent_UnQuiesceBus:
+		printk(KERN_INFO "intReceived: system bus %d recovered\n",
+			eventParm->eventData.busRecovered.busNumber);
+		break;
+	case XmPciLpEvent_NodeFailed:
+	case XmPciLpEvent_BridgeError:
+		printk(KERN_INFO
+			"intReceived: multi-adapter bridge %d/%d/%d failed\n",
+			eventParm->eventData.nodeFailed.busNumber,
+			eventParm->eventData.nodeFailed.subBusNumber,
+			eventParm->eventData.nodeFailed.deviceId);
+		break;
+	case XmPciLpEvent_NodeRecovered:
+		printk(KERN_INFO
+			"intReceived: multi-adapter bridge %d/%d/%d recovered\n",
+			eventParm->eventData.nodeRecovered.busNumber,
+			eventParm->eventData.nodeRecovered.subBusNumber,
+			eventParm->eventData.nodeRecovered.deviceId);
+		break;
+	default:
+		printk(KERN_ERR
+			"intReceived: unrecognized event subtype 0x%x\n",
+			eventParm->hvLpEvent.xSubtype);
+		break;
+	}
+}
+
+static void XmPciLpEvent_handler(struct HvLpEvent *eventParm,
+		struct pt_regs *regsParm)
+{
+#ifdef CONFIG_PCI
+	++Pci_Event_Count;
+
+	if (eventParm && (eventParm->xType == HvLpEvent_Type_PciIo)) {
+		switch (eventParm->xFlags.xFunction) {
+		case HvLpEvent_Function_Int:
+			intReceived((struct XmPciLpEvent *)eventParm, regsParm);
+			break;
+		case HvLpEvent_Function_Ack:
+			printk(KERN_ERR
+				"XmPciLpEvent_handler: unexpected ack received\n");
+			break;
+		default:
+			printk(KERN_ERR
+				"XmPciLpEvent_handler: unexpected event function %d\n",
+				(int)eventParm->xFlags.xFunction);
+			break;
+		}
+	} else if (eventParm)
+		printk(KERN_ERR
+			"XmPciLpEvent_handler: Unrecognized PCI event type 0x%x\n",
+			(int)eventParm->xType);
+	else
+		printk(KERN_ERR "XmPciLpEvent_handler: NULL event received\n");
+#endif
 }
 
 /*
- * This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot
- * It calculates the irq value for the slot.
- * Note that subBusNumber is always 0 (at the moment at least).
+ * This is called by init_IRQ.  set in ppc_md.init_IRQ by iSeries_setup.c
+ * It must be called before the bus walk.
  */
-int __init iSeries_allocate_IRQ(HvBusNumber busNumber,
-		HvSubBusNumber subBusNumber, HvAgentId deviceId)
+void __init iSeries_init_IRQ(void)
 {
-	unsigned int realirq, virtirq;
-	u8 idsel = (deviceId >> 4);
-	u8 function = deviceId & 7;
+	/* Register PCI event handler and open an event path */
+	int xRc;
 
-	virtirq = next_virtual_irq++;
-	realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function;
-	virt_irq_to_real_map[virtirq] = realirq;
-
-	irq_desc[virtirq].handler = &iSeries_IRQ_handler;
-	return virtirq;
+	xRc = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
+			&XmPciLpEvent_handler);
+	if (xRc == 0) {
+		xRc = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
+		if (xRc != 0)
+			printk(KERN_ERR "iSeries_init_IRQ: open event path "
+					"failed with rc 0x%x\n", xRc);
+	} else
+		printk(KERN_ERR "iSeries_init_IRQ: register handler "
+				"failed with rc 0x%x\n", xRc);
 }
 
 #define REAL_IRQ_TO_BUS(irq)	((((irq) >> 6) & 0xff) + 1)
 #define REAL_IRQ_TO_IDSEL(irq)	((((irq) >> 3) & 7) + 1)
 #define REAL_IRQ_TO_FUNC(irq)	((irq) & 7)
 
+/*
+ * This will be called by device drivers (via enable_IRQ)
+ * to enable INTA in the bridge interrupt status register.
+ */
+static void iSeries_enable_IRQ(unsigned int irq)
+{
+	u32 bus, deviceId, function, mask;
+	const u32 subBus = 0;
+	unsigned int rirq = virt_irq_to_real_map[irq];
+
+	/* The IRQ has already been locked by the caller */
+	bus = REAL_IRQ_TO_BUS(rirq);
+	function = REAL_IRQ_TO_FUNC(rirq);
+	deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
+
+	/* Unmask secondary INTA */
+	mask = 0x80000000;
+	HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask);
+	PPCDBG(PPCDBG_BUSWALK, "iSeries_enable_IRQ 0x%02X.%02X.%02X 0x%04X\n",
+			bus, subBus, deviceId, irq);
+}
+
 /* This is called by iSeries_activate_IRQs */
 static unsigned int iSeries_startup_IRQ(unsigned int irq)
 {
@@ -131,7 +268,7 @@
 			desc->handler->startup(irq);
 			spin_unlock_irqrestore(&desc->lock, flags);
 		}
-    	}
+	}
 }
 
 /*  this is not called anywhere currently */
@@ -173,29 +310,7 @@
 	mask = 0x80000000;
 	HvCallPci_maskInterrupts(bus, subBus, deviceId, mask);
 	PPCDBG(PPCDBG_BUSWALK, "iSeries_disable_IRQ 0x%02X.%02X.%02X 0x%04X\n",
-	       bus, subBus, deviceId, irq);
-}
-
-/*
- * This will be called by device drivers (via enable_IRQ)
- * to enable INTA in the bridge interrupt status register.
- */
-static void iSeries_enable_IRQ(unsigned int irq)
-{
-	u32 bus, deviceId, function, mask;
-	const u32 subBus = 0;
-	unsigned int rirq = virt_irq_to_real_map[irq];
-
-	/* The IRQ has already been locked by the caller */
-	bus = REAL_IRQ_TO_BUS(rirq);
-	function = REAL_IRQ_TO_FUNC(rirq);
-	deviceId = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
-
-	/* Unmask secondary INTA */
-	mask = 0x80000000;
-	HvCallPci_unmaskInterrupts(bus, subBus, deviceId, mask);
-	PPCDBG(PPCDBG_BUSWALK, "iSeries_enable_IRQ 0x%02X.%02X.%02X 0x%04X\n",
-	       bus, subBus, deviceId, irq);
+			bus, subBus, deviceId, irq);
 }
 
 /*
@@ -207,3 +322,32 @@
 static void iSeries_end_IRQ(unsigned int irq)
 {
 }
+
+static hw_irq_controller iSeries_IRQ_handler = {
+	.typename = "iSeries irq controller",
+	.startup = iSeries_startup_IRQ,
+	.shutdown = iSeries_shutdown_IRQ,
+	.enable = iSeries_enable_IRQ,
+	.disable = iSeries_disable_IRQ,
+	.end = iSeries_end_IRQ
+};
+
+/*
+ * This is called out of iSeries_scan_slot to allocate an IRQ for an EADS slot
+ * It calculates the irq value for the slot.
+ * Note that subBusNumber is always 0 (at the moment at least).
+ */
+int __init iSeries_allocate_IRQ(HvBusNumber busNumber,
+		HvSubBusNumber subBusNumber, HvAgentId deviceId)
+{
+	unsigned int realirq, virtirq;
+	u8 idsel = (deviceId >> 4);
+	u8 function = deviceId & 7;
+
+	virtirq = next_virtual_irq++;
+	realirq = ((busNumber - 1) << 6) + ((idsel - 1) << 3) + function;
+	virt_irq_to_real_map[virtirq] = realirq;
+
+	irq_desc[virtirq].handler = &iSeries_IRQ_handler;
+	return virtirq;
+}
diff --git a/arch/ppc64/kernel/iSeries_pci.c b/arch/ppc64/kernel/iSeries_pci.c
index bd4c255..356e4fd 100644
--- a/arch/ppc64/kernel/iSeries_pci.c
+++ b/arch/ppc64/kernel/iSeries_pci.c
@@ -38,9 +38,7 @@
 #include <asm/iommu.h>
 
 #include <asm/iSeries/HvCallPci.h>
-#include <asm/iSeries/HvCallSm.h>
 #include <asm/iSeries/HvCallXm.h>
-#include <asm/iSeries/LparData.h>
 #include <asm/iSeries/iSeries_irq.h>
 #include <asm/iSeries/iSeries_pci.h>
 #include <asm/iSeries/mf.h>
@@ -225,10 +223,7 @@
 	node->DsaAddr.Dsa.busNumber = Bus;
 	node->DsaAddr.Dsa.subBusNumber = SubBus;
 	node->DsaAddr.Dsa.deviceId = 0x10;
-	node->AgentId = AgentId;
 	node->DevFn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function);
-	node->IoRetry = 0;
-	iSeries_Get_Location_Code(node);
 	return node;
 }
 
@@ -302,7 +297,6 @@
 {
 	struct pci_dev *pdev = NULL;
 	struct iSeries_Device_Node *node;
-	char Buffer[256];
     	int DeviceCount = 0;
 
 	PPCDBG(PPCDBG_BUSWALK, "iSeries_pcibios_fixup Entry.\n"); 
@@ -324,9 +318,7 @@
 					"pdev 0x%p <==> DevNode 0x%p\n",
 					pdev, node);
 			allocate_device_bars(pdev);
-			iSeries_Device_Information(pdev, Buffer,
-					sizeof(Buffer));
-			printk("%d. %s\n", DeviceCount, Buffer);
+			iSeries_Device_Information(pdev, DeviceCount);
 			iommu_devnode_init_iSeries(node);
 		} else
 			printk("PCI: Device Tree not found for 0x%016lX\n",
@@ -499,7 +491,6 @@
 
 			++DeviceCount;
 			node = build_device_node(Bus, SubBus, EADsIdSel, Function);
-			node->Vendor = VendorId;
 			node->Irq = Irq;
 			node->LogicalSlot = BridgeInfo->logicalSlotNumber;
 
@@ -661,38 +652,34 @@
  * Check Return Code
  * -> On Failure, print and log information.
  *    Increment Retry Count, if exceeds max, panic partition.
- * -> If in retry, print and log success 
  *
  * PCI: Device 23.90 ReadL I/O Error( 0): 0x1234
  * PCI: Device 23.90 ReadL Retry( 1)
  * PCI: Device 23.90 ReadL Retry Successful(1)
  */
 static int CheckReturnCode(char *TextHdr, struct iSeries_Device_Node *DevNode,
-		u64 ret)
+		int *retry, u64 ret)
 {
 	if (ret != 0)  {
 		++Pci_Error_Count;
-		++DevNode->IoRetry;
+		(*retry)++;
 		printk("PCI: %s: Device 0x%04X:%02X  I/O Error(%2d): 0x%04X\n",
 				TextHdr, DevNode->DsaAddr.Dsa.busNumber, DevNode->DevFn,
-				DevNode->IoRetry, (int)ret);
+				*retry, (int)ret);
 		/*
 		 * Bump the retry and check for retry count exceeded.
 		 * If, Exceeded, panic the system.
 		 */
-		if ((DevNode->IoRetry > Pci_Retry_Max) &&
+		if (((*retry) > Pci_Retry_Max) &&
 				(Pci_Error_Flag > 0)) {
 			mf_display_src(0xB6000103);
-			panic_timeout = 0; 
+			panic_timeout = 0;
 			panic("PCI: Hardware I/O Error, SRC B6000103, "
 					"Automatic Reboot Disabled.\n");
 		}
 		return -1;	/* Retry Try */
 	}
-	/* If retry was in progress, log success and rest retry count */
-	if (DevNode->IoRetry > 0)
-		DevNode->IoRetry = 0;
-	return 0; 
+	return 0;
 }
 
 /*
@@ -738,6 +725,7 @@
 {
 	u64 BarOffset;
 	u64 dsa;
+	int retry = 0;
 	struct HvCallPci_LoadReturn ret;
 	struct iSeries_Device_Node *DevNode =
 		xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -757,7 +745,7 @@
 	do {
 		++Pci_Io_Read_Count;
 		HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0);
-	} while (CheckReturnCode("RDB", DevNode, ret.rc) != 0);
+	} while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0);
 
 	return (u8)ret.value;
 }
@@ -767,6 +755,7 @@
 {
 	u64 BarOffset;
 	u64 dsa;
+	int retry = 0;
 	struct HvCallPci_LoadReturn ret;
 	struct iSeries_Device_Node *DevNode =
 		xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -787,7 +776,7 @@
 		++Pci_Io_Read_Count;
 		HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa,
 				BarOffset, 0);
-	} while (CheckReturnCode("RDW", DevNode, ret.rc) != 0);
+	} while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0);
 
 	return swab16((u16)ret.value);
 }
@@ -797,6 +786,7 @@
 {
 	u64 BarOffset;
 	u64 dsa;
+	int retry = 0;
 	struct HvCallPci_LoadReturn ret;
 	struct iSeries_Device_Node *DevNode =
 		xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -817,7 +807,7 @@
 		++Pci_Io_Read_Count;
 		HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa,
 				BarOffset, 0);
-	} while (CheckReturnCode("RDL", DevNode, ret.rc) != 0);
+	} while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0);
 
 	return swab32((u32)ret.value);
 }
@@ -834,6 +824,7 @@
 {
 	u64 BarOffset;
 	u64 dsa;
+	int retry = 0;
 	u64 rc;
 	struct iSeries_Device_Node *DevNode =
 		xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -853,7 +844,7 @@
 	do {
 		++Pci_Io_Write_Count;
 		rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0);
-	} while (CheckReturnCode("WWB", DevNode, rc) != 0);
+	} while (CheckReturnCode("WWB", DevNode, &retry, rc) != 0);
 }
 EXPORT_SYMBOL(iSeries_Write_Byte);
 
@@ -861,6 +852,7 @@
 {
 	u64 BarOffset;
 	u64 dsa;
+	int retry = 0;
 	u64 rc;
 	struct iSeries_Device_Node *DevNode =
 		xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -880,7 +872,7 @@
 	do {
 		++Pci_Io_Write_Count;
 		rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0);
-	} while (CheckReturnCode("WWW", DevNode, rc) != 0);
+	} while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0);
 }
 EXPORT_SYMBOL(iSeries_Write_Word);
 
@@ -888,6 +880,7 @@
 {
 	u64 BarOffset;
 	u64 dsa;
+	int retry = 0;
 	u64 rc;
 	struct iSeries_Device_Node *DevNode =
 		xlate_iomm_address(IoAddress, &dsa, &BarOffset);
@@ -907,6 +900,6 @@
 	do {
 		++Pci_Io_Write_Count;
 		rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0);
-	} while (CheckReturnCode("WWL", DevNode, rc) != 0);
+	} while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0);
 }
 EXPORT_SYMBOL(iSeries_Write_Long);
diff --git a/arch/ppc64/kernel/iSeries_pci_reset.c b/arch/ppc64/kernel/iSeries_pci_reset.c
deleted file mode 100644
index 0f785e4..0000000
--- a/arch/ppc64/kernel/iSeries_pci_reset.c
+++ /dev/null
@@ -1,104 +0,0 @@
-#define PCIFR(...)
-/************************************************************************/
-/* File iSeries_pci_reset.c created by Allan Trautman on Mar 21 2001.   */
-/************************************************************************/
-/* This code supports the pci interface on the IBM iSeries systems.     */
-/* Copyright (C) 20yy  <Allan H Trautman> <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.                                  */
-/*                                                                      */
-/* 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                                          */
-/************************************************************************/
-/* Change Activity:                                                     */
-/*   Created, March 20, 2001                                            */
-/*   April 30, 2001, Added return codes on functions.                   */
-/*   September 10, 2001, Ported to ppc64.                               */
-/* End Change Activity                                                  */
-/************************************************************************/
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/irq.h>
-#include <linux/delay.h>
-
-#include <asm/io.h>
-#include <asm/iSeries/HvCallPci.h>
-#include <asm/iSeries/HvTypes.h>
-#include <asm/iSeries/mf.h>
-#include <asm/pci.h>
-
-#include <asm/iSeries/iSeries_pci.h>
-#include "pci.h"
-
-/*
- * Interface to toggle the reset line
- * Time is in .1 seconds, need for seconds.
- */
-int iSeries_Device_ToggleReset(struct pci_dev *PciDev, int AssertTime,
-		int DelayTime)
-{
-	unsigned int AssertDelay, WaitDelay;
-	struct iSeries_Device_Node *DeviceNode =
-		(struct iSeries_Device_Node *)PciDev->sysdata;
-
- 	if (DeviceNode == NULL) { 
-		printk("PCI: Pci Reset Failed, Device Node not found for pci_dev %p\n",
-				PciDev);
-		return -1;
-	}
-	/*
-	 * Set defaults, Assert is .5 second, Wait is 3 seconds.
-	 */
-	if (AssertTime == 0)
-		AssertDelay = 500;
-	else
-		AssertDelay = AssertTime * 100;
-
-	if (DelayTime == 0)
-		WaitDelay = 3000;
-	else
-		WaitDelay = DelayTime * 100;
-
-	/*
-	 * Assert reset
-	 */
-	DeviceNode->ReturnCode = HvCallPci_setSlotReset(ISERIES_BUS(DeviceNode),
-			0x00, DeviceNode->AgentId, 1);
-	if (DeviceNode->ReturnCode == 0) {
-		msleep(AssertDelay);			/* Sleep for the time */
-		DeviceNode->ReturnCode =
-			HvCallPci_setSlotReset(ISERIES_BUS(DeviceNode),
-					0x00, DeviceNode->AgentId, 0);
-
-		/*
-   		 * Wait for device to reset
-		 */
-		msleep(WaitDelay);
-	}
-	if (DeviceNode->ReturnCode == 0)
-		PCIFR("Slot 0x%04X.%02 Reset\n", ISERIES_BUS(DeviceNode),
-				DeviceNode->AgentId);
-	else {
-		printk("PCI: Slot 0x%04X.%02X Reset Failed, RCode: %04X\n",
-				ISERIES_BUS(DeviceNode), DeviceNode->AgentId,
-				DeviceNode->ReturnCode);
-		PCIFR("Slot 0x%04X.%02X Reset Failed, RCode: %04X\n",
-				ISERIES_BUS(DeviceNode), DeviceNode->AgentId,
-				DeviceNode->ReturnCode);
-	}
-	return DeviceNode->ReturnCode;
-}
-EXPORT_SYMBOL(iSeries_Device_ToggleReset);
diff --git a/arch/ppc64/kernel/iSeries_proc.c b/arch/ppc64/kernel/iSeries_proc.c
index 0cc58dd..356bd99 100644
--- a/arch/ppc64/kernel/iSeries_proc.c
+++ b/arch/ppc64/kernel/iSeries_proc.c
@@ -28,8 +28,7 @@
 #include <asm/iSeries/ItLpQueue.h>
 #include <asm/iSeries/HvCallXm.h>
 #include <asm/iSeries/IoHriMainStore.h>
-#include <asm/iSeries/LparData.h>
-#include <asm/iSeries/iSeries_proc.h>
+#include <asm/iSeries/IoHriProcessorVpd.h>
 
 static int __init iseries_proc_create(void)
 {
diff --git a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c
index 6d06eb5..86966ce 100644
--- a/arch/ppc64/kernel/iSeries_setup.c
+++ b/arch/ppc64/kernel/iSeries_setup.c
@@ -47,7 +47,7 @@
 #include <asm/paca.h>
 #include <asm/cache.h>
 #include <asm/sections.h>
-#include <asm/iSeries/LparData.h>
+#include <asm/abs_addr.h>
 #include <asm/iSeries/HvCallHpt.h>
 #include <asm/iSeries/HvLpConfig.h>
 #include <asm/iSeries/HvCallEvent.h>
@@ -55,10 +55,12 @@
 #include <asm/iSeries/HvCallXm.h>
 #include <asm/iSeries/ItLpQueue.h>
 #include <asm/iSeries/IoHriMainStore.h>
-#include <asm/iSeries/iSeries_proc.h>
 #include <asm/iSeries/mf.h>
 #include <asm/iSeries/HvLpEvent.h>
 #include <asm/iSeries/iSeries_irq.h>
+#include <asm/iSeries/IoHriProcessorVpd.h>
+#include <asm/iSeries/ItVpdAreas.h>
+#include <asm/iSeries/LparMap.h>
 
 extern void hvlog(char *fmt, ...);
 
@@ -74,7 +76,11 @@
 static void build_iSeries_Memory_Map(void);
 static void setup_iSeries_cache_sizes(void);
 static void iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr);
+#ifdef CONFIG_PCI
 extern void iSeries_pci_final_fixup(void);
+#else
+static void iSeries_pci_final_fixup(void) { }
+#endif
 
 /* Global Variables */
 static unsigned long procFreqHz;
@@ -665,9 +671,6 @@
 	}
 }
 
-extern unsigned long ppc_proc_freq;
-extern unsigned long ppc_tb_freq;
-
 /*
  * Document me.
  */
@@ -766,8 +769,6 @@
 	mf_power_off();
 }
 
-extern void setup_default_decr(void);
-
 /*
  * void __init iSeries_calibrate_decr()
  *
@@ -874,6 +875,10 @@
 }
 __setup("spread_lpevents=", set_spread_lpevents);
 
+#ifndef CONFIG_PCI
+void __init iSeries_init_IRQ(void) { }
+#endif
+
 void __init iSeries_early_setup(void)
 {
 	iSeries_fixup_klimit();
diff --git a/arch/ppc64/kernel/iSeries_smp.c b/arch/ppc64/kernel/iSeries_smp.c
index ba1f084..f74386e 100644
--- a/arch/ppc64/kernel/iSeries_smp.c
+++ b/arch/ppc64/kernel/iSeries_smp.c
@@ -38,9 +38,7 @@
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/paca.h>
-#include <asm/iSeries/LparData.h>
 #include <asm/iSeries/HvCall.h>
-#include <asm/iSeries/HvCallCfg.h>
 #include <asm/time.h>
 #include <asm/ppcdebug.h>
 #include <asm/machdep.h>
diff --git a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c
index f24ce2b..bdf13b4 100644
--- a/arch/ppc64/kernel/idle.c
+++ b/arch/ppc64/kernel/idle.c
@@ -42,6 +42,11 @@
 static unsigned long maxYieldTime = 0;
 static unsigned long minYieldTime = 0xffffffffffffffffUL;
 
+static inline void process_iSeries_events(void)
+{
+	asm volatile ("li 0,0x5555; sc" : : : "r0", "r3");
+}
+
 static void yield_shared_processor(void)
 {
 	unsigned long tb;
@@ -292,7 +297,7 @@
 		if (need_resched())
 			schedule();
 
-		if (cpu_is_offline(_smp_processor_id()) &&
+		if (cpu_is_offline(raw_smp_processor_id()) &&
 		    system_state == SYSTEM_RUNNING)
 			cpu_die();
 	}
diff --git a/arch/ppc64/kernel/iommu.c b/arch/ppc64/kernel/iommu.c
index 3441646..8316426 100644
--- a/arch/ppc64/kernel/iommu.c
+++ b/arch/ppc64/kernel/iommu.c
@@ -423,6 +423,9 @@
 	tbl->it_largehint = tbl->it_halfpoint;
 	spin_lock_init(&tbl->it_lock);
 
+	/* Clear the hardware table in case firmware left allocations in it */
+	ppc_md.tce_free(tbl, tbl->it_offset, tbl->it_size);
+
 	if (!welcomed) {
 		printk(KERN_INFO "IOMMU table initialized, virtual merging %s\n",
 		       novmerge ? "disabled" : "enabled");
diff --git a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c
index 4fd7f20..3defc8c 100644
--- a/arch/ppc64/kernel/irq.c
+++ b/arch/ppc64/kernel/irq.c
@@ -52,7 +52,7 @@
 #include <asm/cache.h>
 #include <asm/prom.h>
 #include <asm/ptrace.h>
-#include <asm/iSeries/LparData.h>
+#include <asm/iSeries/ItLpQueue.h>
 #include <asm/machdep.h>
 #include <asm/paca.h>
 
@@ -395,6 +395,9 @@
 	if (ppc64_interrupt_controller == IC_OPEN_PIC)
 		return real_irq;	/* no mapping for openpic (for now) */
 
+	if (ppc64_interrupt_controller == IC_BPA_IIC)
+		return real_irq;	/* no mapping for iic either */
+
 	/* don't map interrupts < MIN_VIRT_IRQ */
 	if (real_irq < MIN_VIRT_IRQ) {
 		virt_irq_to_real_map[real_irq] = real_irq;
diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c
index 103daaf..782ce3e 100644
--- a/arch/ppc64/kernel/kprobes.c
+++ b/arch/ppc64/kernel/kprobes.c
@@ -32,42 +32,55 @@
 #include <linux/ptrace.h>
 #include <linux/spinlock.h>
 #include <linux/preempt.h>
+#include <asm/cacheflush.h>
 #include <asm/kdebug.h>
 #include <asm/sstep.h>
 
-/* kprobe_status settings */
-#define KPROBE_HIT_ACTIVE	0x00000001
-#define KPROBE_HIT_SS		0x00000002
-
 static struct kprobe *current_kprobe;
 static unsigned long kprobe_status, kprobe_saved_msr;
+static struct kprobe *kprobe_prev;
+static unsigned long kprobe_status_prev, kprobe_saved_msr_prev;
 static struct pt_regs jprobe_saved_regs;
 
 int arch_prepare_kprobe(struct kprobe *p)
 {
+	int ret = 0;
 	kprobe_opcode_t insn = *p->addr;
 
-	if (IS_MTMSRD(insn) || IS_RFID(insn))
-		/* cannot put bp on RFID/MTMSRD */
-		return 1;
-	return 0;
+	if ((unsigned long)p->addr & 0x03) {
+		printk("Attempt to register kprobe at an unaligned address\n");
+		ret = -EINVAL;
+	} else if (IS_MTMSRD(insn) || IS_RFID(insn)) {
+		printk("Cannot register a kprobe on rfid or mtmsrd\n");
+		ret = -EINVAL;
+	}
+	return ret;
 }
 
 void arch_copy_kprobe(struct kprobe *p)
 {
 	memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+	p->opcode = *p->addr;
+}
+
+void arch_arm_kprobe(struct kprobe *p)
+{
+	*p->addr = BREAKPOINT_INSTRUCTION;
+	flush_icache_range((unsigned long) p->addr,
+			   (unsigned long) p->addr + sizeof(kprobe_opcode_t));
+}
+
+void arch_disarm_kprobe(struct kprobe *p)
+{
+	*p->addr = p->opcode;
+	flush_icache_range((unsigned long) p->addr,
+			   (unsigned long) p->addr + sizeof(kprobe_opcode_t));
 }
 
 void arch_remove_kprobe(struct kprobe *p)
 {
 }
 
-static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
-{
-	*p->addr = p->opcode;
-	regs->nip = (unsigned long)p->addr;
-}
-
 static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
 {
 	regs->msr |= MSR_SE;
@@ -78,6 +91,20 @@
 		regs->nip = (unsigned long)&p->ainsn.insn;
 }
 
+static inline void save_previous_kprobe(void)
+{
+	kprobe_prev = current_kprobe;
+	kprobe_status_prev = kprobe_status;
+	kprobe_saved_msr_prev = kprobe_saved_msr;
+}
+
+static inline void restore_previous_kprobe(void)
+{
+	current_kprobe = kprobe_prev;
+	kprobe_status = kprobe_status_prev;
+	kprobe_saved_msr = kprobe_saved_msr_prev;
+}
+
 static inline int kprobe_handler(struct pt_regs *regs)
 {
 	struct kprobe *p;
@@ -96,8 +123,19 @@
 				unlock_kprobes();
 				goto no_kprobe;
 			}
-			disarm_kprobe(p, regs);
-			ret = 1;
+			/* We have reentered the kprobe_handler(), since
+			 * another probe was hit while within the handler.
+			 * We here save the original kprobes variables and
+			 * just single step on the instruction of the new probe
+			 * without calling any user handlers.
+			 */
+			save_previous_kprobe();
+			current_kprobe = p;
+			kprobe_saved_msr = regs->msr;
+			p->nmissed++;
+			prepare_singlestep(p, regs);
+			kprobe_status = KPROBE_REENTER;
+			return 1;
 		} else {
 			p = current_kprobe;
 			if (p->break_handler && p->break_handler(p, regs)) {
@@ -172,8 +210,6 @@
 	ret = emulate_step(regs, p->ainsn.insn[0]);
 	if (ret == 0)
 		regs->nip = (unsigned long)p->addr + 4;
-
-	regs->msr &= ~MSR_SE;
 }
 
 static inline int post_kprobe_handler(struct pt_regs *regs)
@@ -181,13 +217,21 @@
 	if (!kprobe_running())
 		return 0;
 
-	if (current_kprobe->post_handler)
+	if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) {
+		kprobe_status = KPROBE_HIT_SSDONE;
 		current_kprobe->post_handler(current_kprobe, regs, 0);
+	}
 
 	resume_execution(current_kprobe, regs);
 	regs->msr |= kprobe_saved_msr;
 
+	/*Restore back the original saved kprobes variables and continue. */
+	if (kprobe_status == KPROBE_REENTER) {
+		restore_previous_kprobe();
+		goto out;
+	}
 	unlock_kprobes();
+out:
 	preempt_enable_no_resched();
 
 	/*
@@ -210,6 +254,7 @@
 
 	if (kprobe_status & KPROBE_HIT_SS) {
 		resume_execution(current_kprobe, regs);
+		regs->msr &= ~MSR_SE;
 		regs->msr |= kprobe_saved_msr;
 
 		unlock_kprobes();
@@ -233,8 +278,6 @@
 	 */
 	preempt_disable();
 	switch (val) {
-	case DIE_IABR_MATCH:
-	case DIE_DABR_MATCH:
 	case DIE_BPT:
 		if (kprobe_handler(args->regs))
 			ret = NOTIFY_STOP;
diff --git a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c
index a8fd32d..02e9662 100644
--- a/arch/ppc64/kernel/lparcfg.c
+++ b/arch/ppc64/kernel/lparcfg.c
@@ -28,12 +28,13 @@
 #include <asm/uaccess.h>
 #include <asm/iSeries/HvLpConfig.h>
 #include <asm/lppaca.h>
-#include <asm/iSeries/LparData.h>
 #include <asm/hvcall.h>
 #include <asm/cputable.h>
 #include <asm/rtas.h>
 #include <asm/system.h>
 #include <asm/time.h>
+#include <asm/iSeries/ItExtVpdPanel.h>
+#include <asm/prom.h>
 
 #define MODULE_VERS "1.6"
 #define MODULE_NAME "lparcfg"
diff --git a/arch/ppc64/kernel/machine_kexec.c b/arch/ppc64/kernel/machine_kexec.c
new file mode 100644
index 0000000..fdb2fc6
--- /dev/null
+++ b/arch/ppc64/kernel/machine_kexec.c
@@ -0,0 +1,302 @@
+/*
+ * machine_kexec.c - handle transition of Linux booting another kernel
+ *
+ * Copyright (C) 2004-2005, IBM Corp.
+ *
+ * Created by: Milton D Miller II
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+
+
+#include <linux/cpumask.h>
+#include <linux/kexec.h>
+#include <linux/smp.h>
+#include <linux/thread_info.h>
+#include <linux/errno.h>
+
+#include <asm/page.h>
+#include <asm/current.h>
+#include <asm/machdep.h>
+#include <asm/cacheflush.h>
+#include <asm/paca.h>
+#include <asm/mmu.h>
+#include <asm/sections.h>	/* _end */
+#include <asm/prom.h>
+
+#define HASH_GROUP_SIZE 0x80	/* size of each hash group, asm/mmu.h */
+
+/* Have this around till we move it into crash specific file */
+note_buf_t crash_notes[NR_CPUS];
+
+/* Dummy for now. Not sure if we need to have a crash shutdown in here
+ * and if what it will achieve. Letting it be now to compile the code
+ * in generic kexec environment
+ */
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+	/* do nothing right now */
+	/* smp_relase_cpus() if we want smp on panic kernel */
+	/* cpu_irq_down to isolate us until we are ready */
+}
+
+int machine_kexec_prepare(struct kimage *image)
+{
+	int i;
+	unsigned long begin, end;	/* limits of segment */
+	unsigned long low, high;	/* limits of blocked memory range */
+	struct device_node *node;
+	unsigned long *basep;
+	unsigned int *sizep;
+
+	if (!ppc_md.hpte_clear_all)
+		return -ENOENT;
+
+	/*
+	 * Since we use the kernel fault handlers and paging code to
+	 * handle the virtual mode, we must make sure no destination
+	 * overlaps kernel static data or bss.
+	 */
+	for (i = 0; i < image->nr_segments; i++)
+		if (image->segment[i].mem < __pa(_end))
+			return -ETXTBSY;
+
+	/*
+	 * For non-LPAR, we absolutely can not overwrite the mmu hash
+	 * table, since we are still using the bolted entries in it to
+	 * do the copy.  Check that here.
+	 *
+	 * It is safe if the end is below the start of the blocked
+	 * region (end <= low), or if the beginning is after the
+	 * end of the blocked region (begin >= high).  Use the
+	 * boolean identity !(a || b)  === (!a && !b).
+	 */
+	if (htab_address) {
+		low = __pa(htab_address);
+		high = low + (htab_hash_mask + 1) * HASH_GROUP_SIZE;
+
+		for (i = 0; i < image->nr_segments; i++) {
+			begin = image->segment[i].mem;
+			end = begin + image->segment[i].memsz;
+
+			if ((begin < high) && (end > low))
+				return -ETXTBSY;
+		}
+	}
+
+	/* We also should not overwrite the tce tables */
+	for (node = of_find_node_by_type(NULL, "pci"); node != NULL;
+			node = of_find_node_by_type(node, "pci")) {
+		basep = (unsigned long *)get_property(node, "linux,tce-base",
+							NULL);
+		sizep = (unsigned int *)get_property(node, "linux,tce-size",
+							NULL);
+		if (basep == NULL || sizep == NULL)
+			continue;
+
+		low = *basep;
+		high = low + (*sizep);
+
+		for (i = 0; i < image->nr_segments; i++) {
+			begin = image->segment[i].mem;
+			end = begin + image->segment[i].memsz;
+
+			if ((begin < high) && (end > low))
+				return -ETXTBSY;
+		}
+	}
+
+	return 0;
+}
+
+void machine_kexec_cleanup(struct kimage *image)
+{
+	/* we do nothing in prepare that needs to be undone */
+}
+
+#define IND_FLAGS (IND_DESTINATION | IND_INDIRECTION | IND_DONE | IND_SOURCE)
+
+static void copy_segments(unsigned long ind)
+{
+	unsigned long entry;
+	unsigned long *ptr;
+	void *dest;
+	void *addr;
+
+	/*
+	 * We rely on kexec_load to create a lists that properly
+	 * initializes these pointers before they are used.
+	 * We will still crash if the list is wrong, but at least
+	 * the compiler will be quiet.
+	 */
+	ptr = NULL;
+	dest = NULL;
+
+	for (entry = ind; !(entry & IND_DONE); entry = *ptr++) {
+		addr = __va(entry & PAGE_MASK);
+
+		switch (entry & IND_FLAGS) {
+		case IND_DESTINATION:
+			dest = addr;
+			break;
+		case IND_INDIRECTION:
+			ptr = addr;
+			break;
+		case IND_SOURCE:
+			copy_page(dest, addr);
+			dest += PAGE_SIZE;
+		}
+	}
+}
+
+void kexec_copy_flush(struct kimage *image)
+{
+	long i, nr_segments = image->nr_segments;
+	struct  kexec_segment ranges[KEXEC_SEGMENT_MAX];
+
+	/* save the ranges on the stack to efficiently flush the icache */
+	memcpy(ranges, image->segment, sizeof(ranges));
+
+	/*
+	 * After this call we may not use anything allocated in dynamic
+	 * memory, including *image.
+	 *
+	 * Only globals and the stack are allowed.
+	 */
+	copy_segments(image->head);
+
+	/*
+	 * we need to clear the icache for all dest pages sometime,
+	 * including ones that were in place on the original copy
+	 */
+	for (i = 0; i < nr_segments; i++)
+		flush_icache_range(ranges[i].mem + KERNELBASE,
+				ranges[i].mem + KERNELBASE +
+				ranges[i].memsz);
+}
+
+#ifdef CONFIG_SMP
+
+/* FIXME: we should schedule this function to be called on all cpus based
+ * on calling the interrupts, but we would like to call it off irq level
+ * so that the interrupt controller is clean.
+ */
+void kexec_smp_down(void *arg)
+{
+	if (ppc_md.cpu_irq_down)
+		ppc_md.cpu_irq_down();
+
+	local_irq_disable();
+	kexec_smp_wait();
+	/* NOTREACHED */
+}
+
+static void kexec_prepare_cpus(void)
+{
+	int my_cpu, i, notified=-1;
+
+	smp_call_function(kexec_smp_down, NULL, 0, /* wait */0);
+	my_cpu = get_cpu();
+
+	/* check the others cpus are now down (via paca hw cpu id == -1) */
+	for (i=0; i < NR_CPUS; i++) {
+		if (i == my_cpu)
+			continue;
+
+		while (paca[i].hw_cpu_id != -1) {
+			if (!cpu_possible(i)) {
+				printk("kexec: cpu %d hw_cpu_id %d is not"
+						" possible, ignoring\n",
+						i, paca[i].hw_cpu_id);
+				break;
+			}
+			if (!cpu_online(i)) {
+				/* Fixme: this can be spinning in
+				 * pSeries_secondary_wait with a paca
+				 * waiting for it to go online.
+				 */
+				printk("kexec: cpu %d hw_cpu_id %d is not"
+						" online, ignoring\n",
+						i, paca[i].hw_cpu_id);
+				break;
+			}
+			if (i != notified) {
+				printk( "kexec: waiting for cpu %d (physical"
+						" %d) to go down\n",
+						i, paca[i].hw_cpu_id);
+				notified = i;
+			}
+		}
+	}
+
+	/* after we tell the others to go down */
+	if (ppc_md.cpu_irq_down)
+		ppc_md.cpu_irq_down();
+
+	put_cpu();
+
+	local_irq_disable();
+}
+
+#else /* ! SMP */
+
+static void kexec_prepare_cpus(void)
+{
+	/*
+	 * move the secondarys to us so that we can copy
+	 * the new kernel 0-0x100 safely
+	 *
+	 * do this if kexec in setup.c ?
+	 */
+	smp_relase_cpus();
+	if (ppc_md.cpu_irq_down)
+		ppc_md.cpu_irq_down();
+	local_irq_disable();
+}
+
+#endif /* SMP */
+
+/*
+ * kexec thread structure and stack.
+ *
+ * We need to make sure that this is 16384-byte aligned due to the
+ * way process stacks are handled.  It also must be statically allocated
+ * or allocated as part of the kimage, because everything else may be
+ * overwritten when we copy the kexec image.  We piggyback on the
+ * "init_task" linker section here to statically allocate a stack.
+ *
+ * We could use a smaller stack if we don't care about anything using
+ * current, but that audit has not been performed.
+ */
+union thread_union kexec_stack
+	__attribute__((__section__(".data.init_task"))) = { };
+
+/* Our assembly helper, in kexec_stub.S */
+extern NORET_TYPE void kexec_sequence(void *newstack, unsigned long start,
+					void *image, void *control,
+					void (*clear_all)(void)) ATTRIB_NORET;
+
+/* too late to fail here */
+void machine_kexec(struct kimage *image)
+{
+
+	/* prepare control code if any */
+
+	/* shutdown other cpus into our wait loop and quiesce interrupts */
+	kexec_prepare_cpus();
+
+	/* switch to a staticly allocated stack.  Based on irq stack code.
+	 * XXX: the task struct will likely be invalid once we do the copy!
+	 */
+	kexec_stack.thread_info.task = current_thread_info()->task;
+	kexec_stack.thread_info.flags = 0;
+
+	/* Some things are best done in assembly.  Finding globals with
+	 * a toc is easier in C, so pass in what we can.
+	 */
+	kexec_sequence(&kexec_stack, image->start, image,
+			page_address(image->control_code_page),
+			ppc_md.hpte_clear_all);
+	/* NOTREACHED */
+}
diff --git a/arch/ppc64/kernel/maple_setup.c b/arch/ppc64/kernel/maple_setup.c
index 8cf95a2..da8900b 100644
--- a/arch/ppc64/kernel/maple_setup.c
+++ b/arch/ppc64/kernel/maple_setup.c
@@ -78,17 +78,77 @@
 extern void generic_find_legacy_serial_ports(u64 *physport,
 		unsigned int *default_speed);
 
-
 static void maple_restart(char *cmd)
 {
+	unsigned int maple_nvram_base;
+	unsigned int maple_nvram_offset;
+	unsigned int maple_nvram_command;
+	struct device_node *rtcs;
+
+	/* find NVRAM device */
+	rtcs = find_compatible_devices("nvram", "AMD8111");
+	if (rtcs && rtcs->addrs) {
+		maple_nvram_base = rtcs->addrs[0].address;
+	} else {
+		printk(KERN_EMERG "Maple: Unable to find NVRAM\n");
+		printk(KERN_EMERG "Maple: Manual Restart Required\n");
+		return;
+	}
+
+	/* find service processor device */
+	rtcs = find_devices("service-processor");
+	if (!rtcs) {
+		printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
+		printk(KERN_EMERG "Maple: Manual Restart Required\n");
+		return;
+	}
+	maple_nvram_offset = *(unsigned int*) get_property(rtcs,
+			"restart-addr", NULL);
+	maple_nvram_command = *(unsigned int*) get_property(rtcs,
+			"restart-value", NULL);
+
+	/* send command */
+	outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset);
+	for (;;) ;
 }
 
 static void maple_power_off(void)
 {
+	unsigned int maple_nvram_base;
+	unsigned int maple_nvram_offset;
+	unsigned int maple_nvram_command;
+	struct device_node *rtcs;
+
+	/* find NVRAM device */
+	rtcs = find_compatible_devices("nvram", "AMD8111");
+	if (rtcs && rtcs->addrs) {
+		maple_nvram_base = rtcs->addrs[0].address;
+	} else {
+		printk(KERN_EMERG "Maple: Unable to find NVRAM\n");
+		printk(KERN_EMERG "Maple: Manual Power-Down Required\n");
+		return;
+	}
+
+	/* find service processor device */
+	rtcs = find_devices("service-processor");
+	if (!rtcs) {
+		printk(KERN_EMERG "Maple: Unable to find Service Processor\n");
+		printk(KERN_EMERG "Maple: Manual Power-Down Required\n");
+		return;
+	}
+	maple_nvram_offset = *(unsigned int*) get_property(rtcs,
+			"power-off-addr", NULL);
+	maple_nvram_command = *(unsigned int*) get_property(rtcs,
+			"power-off-value", NULL);
+
+	/* send command */
+	outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset);
+	for (;;) ;
 }
 
 static void maple_halt(void)
 {
+	maple_power_off();
 }
 
 #ifdef CONFIG_SMP
@@ -235,6 +295,6 @@
        	.get_boot_time		= maple_get_boot_time,
        	.set_rtc_time		= maple_set_rtc_time,
        	.get_rtc_time		= maple_get_rtc_time,
-      	.calibrate_decr		= maple_calibrate_decr,
+      	.calibrate_decr		= generic_calibrate_decr,
 	.progress		= maple_progress,
 };
diff --git a/arch/ppc64/kernel/maple_time.c b/arch/ppc64/kernel/maple_time.c
index 07ce789..d65210a 100644
--- a/arch/ppc64/kernel/maple_time.c
+++ b/arch/ppc64/kernel/maple_time.c
@@ -42,11 +42,8 @@
 #define DBG(x...)
 #endif
 
-extern void setup_default_decr(void);
 extern void GregorianDay(struct rtc_time * tm);
 
-extern unsigned long ppc_tb_freq;
-extern unsigned long ppc_proc_freq;
 static int maple_rtc_addr;
 
 static int maple_clock_read(int addr)
@@ -176,51 +173,3 @@
 	maple_get_rtc_time(tm);
 }
 
-/* XXX FIXME: Some sane defaults: 125 MHz timebase, 1GHz processor */
-#define DEFAULT_TB_FREQ		125000000UL
-#define DEFAULT_PROC_FREQ	(DEFAULT_TB_FREQ * 8)
-
-void __init maple_calibrate_decr(void)
-{
-	struct device_node *cpu;
-	struct div_result divres;
-	unsigned int *fp = NULL;
-
-	/*
-	 * The cpu node should have a timebase-frequency property
-	 * to tell us the rate at which the decrementer counts.
-	 */
-	cpu = of_find_node_by_type(NULL, "cpu");
-
-	ppc_tb_freq = DEFAULT_TB_FREQ;
-	if (cpu != 0)
-		fp = (unsigned int *)get_property(cpu, "timebase-frequency", NULL);
-	if (fp != NULL)
-		ppc_tb_freq = *fp;
-	else
-		printk(KERN_ERR "WARNING: Estimating decrementer frequency (not found)\n");
-	fp = NULL;
-	ppc_proc_freq = DEFAULT_PROC_FREQ;
-	if (cpu != 0)
-		fp = (unsigned int *)get_property(cpu, "clock-frequency", NULL);
-	if (fp != NULL)
-		ppc_proc_freq = *fp;
-	else
-		printk(KERN_ERR "WARNING: Estimating processor frequency (not found)\n");
-
-	of_node_put(cpu);
-
-	printk(KERN_INFO "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",
-	       ppc_proc_freq/1000000, ppc_proc_freq%1000000);
-
-	tb_ticks_per_jiffy = ppc_tb_freq / HZ;
-	tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
-	tb_ticks_per_usec = ppc_tb_freq / 1000000;
-	tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
-	div128_by_32(1024*1024, 0, tb_ticks_per_sec, &divres);
-	tb_to_xs = divres.result_low;
-
-	setup_default_decr();
-}
diff --git a/arch/ppc64/kernel/mf.c b/arch/ppc64/kernel/mf.c
index 5aca7e8..d98bebf 100644
--- a/arch/ppc64/kernel/mf.c
+++ b/arch/ppc64/kernel/mf.c
@@ -40,7 +40,6 @@
 #include <asm/iSeries/vio.h>
 #include <asm/iSeries/mf.h>
 #include <asm/iSeries/HvLpConfig.h>
-#include <asm/iSeries/ItSpCommArea.h>
 #include <asm/iSeries/ItLpQueue.h>
 
 /*
diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
index b944717..f3dea0c 100644
--- a/arch/ppc64/kernel/misc.S
+++ b/arch/ppc64/kernel/misc.S
@@ -680,6 +680,177 @@
 	ld	r30,-16(r1)
 	blr
 
+/* kexec_wait(phys_cpu)
+ *
+ * wait for the flag to change, indicating this kernel is going away but
+ * the slave code for the next one is at addresses 0 to 100.
+ *
+ * This is used by all slaves.
+ *
+ * Physical (hardware) cpu id should be in r3.
+ */
+_GLOBAL(kexec_wait)
+	bl	1f
+1:	mflr	r5
+	addi	r5,r5,kexec_flag-1b
+
+99:	HMT_LOW
+#ifdef CONFIG_KEXEC		/* use no memory without kexec */
+	lwz	r4,0(r5)
+	cmpwi	0,r4,0
+	bnea	0x60
+#endif
+	b	99b
+
+/* this can be in text because we won't change it until we are
+ * running in real anyways
+ */
+kexec_flag:
+	.long	0
+
+
+#ifdef CONFIG_KEXEC
+
+/* kexec_smp_wait(void)
+ *
+ * call with interrupts off
+ * note: this is a terminal routine, it does not save lr
+ *
+ * get phys id from paca
+ * set paca id to -1 to say we got here
+ * switch to real mode
+ * join other cpus in kexec_wait(phys_id)
+ */
+_GLOBAL(kexec_smp_wait)
+	lhz	r3,PACAHWCPUID(r13)
+	li	r4,-1
+	sth	r4,PACAHWCPUID(r13)	/* let others know we left */
+	bl	real_mode
+	b	.kexec_wait
+
+/*
+ * switch to real mode (turn mmu off)
+ * we use the early kernel trick that the hardware ignores bits
+ * 0 and 1 (big endian) of the effective address in real mode
+ *
+ * don't overwrite r3 here, it is live for kexec_wait above.
+ */
+real_mode:	/* assume normal blr return */
+1:	li	r9,MSR_RI
+	li	r10,MSR_DR|MSR_IR
+	mflr	r11		/* return address to SRR0 */
+	mfmsr	r12
+	andc	r9,r12,r9
+	andc	r10,r12,r10
+
+	mtmsrd	r9,1
+	mtspr	SPRN_SRR1,r10
+	mtspr	SPRN_SRR0,r11
+	rfid
+
+
+/*
+ * kexec_sequence(newstack, start, image, control, clear_all())
+ *
+ * does the grungy work with stack switching and real mode switches
+ * also does simple calls to other code
+ */
+
+_GLOBAL(kexec_sequence)
+	mflr	r0
+	std	r0,16(r1)
+
+	/* switch stacks to newstack -- &kexec_stack.stack */
+	stdu	r1,THREAD_SIZE-112(r3)
+	mr	r1,r3
+
+	li	r0,0
+	std	r0,16(r1)
+
+	/* save regs for local vars on new stack.
+	 * yes, we won't go back, but ...
+	 */
+	std	r31,-8(r1)
+	std	r30,-16(r1)
+	std	r29,-24(r1)
+	std	r28,-32(r1)
+	std	r27,-40(r1)
+	std	r26,-48(r1)
+	std	r25,-56(r1)
+
+	stdu	r1,-112-64(r1)
+
+	/* save args into preserved regs */
+	mr	r31,r3			/* newstack (both) */
+	mr	r30,r4			/* start (real) */
+	mr	r29,r5			/* image (virt) */
+	mr	r28,r6			/* control, unused */
+	mr	r27,r7			/* clear_all() fn desc */
+	mr	r26,r8			/* spare */
+	lhz	r25,PACAHWCPUID(r13)	/* get our phys cpu from paca */
+
+	/* disable interrupts, we are overwriting kernel data next */
+	mfmsr	r3
+	rlwinm	r3,r3,0,17,15
+	mtmsrd	r3,1
+
+	/* copy dest pages, flush whole dest image */
+	mr	r3,r29
+	bl	.kexec_copy_flush	/* (image) */
+
+	/* turn off mmu */
+	bl	real_mode
+
+	/* clear out hardware hash page table and tlb */
+	ld	r5,0(r27)		/* deref function descriptor */
+	mtctr	r5
+	bctrl				/* ppc_md.hash_clear_all(void); */
+
+/*
+ *   kexec image calling is:
+ *      the first 0x100 bytes of the entry point are copied to 0
+ *
+ *      all slaves branch to slave = 0x60 (absolute)
+ *              slave(phys_cpu_id);
+ *
+ *      master goes to start = entry point
+ *              start(phys_cpu_id, start, 0);
+ *
+ *
+ *   a wrapper is needed to call existing kernels, here is an approximate
+ *   description of one method:
+ *
+ * v2: (2.6.10)
+ *   start will be near the boot_block (maybe 0x100 bytes before it?)
+ *   it will have a 0x60, which will b to boot_block, where it will wait
+ *   and 0 will store phys into struct boot-block and load r3 from there,
+ *   copy kernel 0-0x100 and tell slaves to back down to 0x60 again
+ *
+ * v1: (2.6.9)
+ *    boot block will have all cpus scanning device tree to see if they
+ *    are the boot cpu ?????
+ *    other device tree differences (prop sizes, va vs pa, etc)...
+ */
+
+	/* copy  0x100 bytes starting at start to 0 */
+	li	r3,0
+	mr	r4,r30
+	li	r5,0x100
+	li	r6,0
+	bl	.copy_and_flush	/* (dest, src, copy limit, start offset) */
+1:	/* assume normal blr return */
+
+	/* release other cpus to the new kernel secondary start at 0x60 */
+	mflr	r5
+	li	r6,1
+	stw	r6,kexec_flag-1b(5)
+	mr	r3,r25	# my phys cpu
+	mr	r4,r30	# start, aka phys mem offset
+	mtlr	4
+	li	r5,0
+	blr	/* image->start(physid, image->start, 0); */
+#endif /* CONFIG_KEXEC */
+
 /* Why isn't this a) automatic, b) written in 'C'? */	
 	.balign 8
 _GLOBAL(sys_call_table32)
@@ -792,7 +963,7 @@
 	.llong .compat_sys_newstat
 	.llong .compat_sys_newlstat
 	.llong .compat_sys_newfstat
-	.llong .sys_uname
+	.llong .sys32_uname
 	.llong .sys_ni_syscall		/* 110 old iopl syscall */
 	.llong .sys_vhangup
 	.llong .sys_ni_syscall		/* old idle syscall */
@@ -951,7 +1122,7 @@
 	.llong .compat_sys_mq_timedreceive /* 265 */
 	.llong .compat_sys_mq_notify
 	.llong .compat_sys_mq_getsetattr
-	.llong .sys_ni_syscall		/* 268 reserved for sys_kexec_load */
+	.llong .compat_sys_kexec_load
 	.llong .sys32_add_key
 	.llong .sys32_request_key
 	.llong .compat_sys_keyctl
@@ -1227,7 +1398,7 @@
 	.llong .sys_mq_timedreceive	/* 265 */
 	.llong .sys_mq_notify
 	.llong .sys_mq_getsetattr
-	.llong .sys_ni_syscall		/* 268 reserved for sys_kexec_load */
+	.llong .sys_kexec_load
 	.llong .sys_add_key
 	.llong .sys_request_key		/* 270 */
 	.llong .sys_keyctl
diff --git a/arch/ppc64/kernel/mpic.c b/arch/ppc64/kernel/mpic.c
index 593ea5b..e8fbab1 100644
--- a/arch/ppc64/kernel/mpic.c
+++ b/arch/ppc64/kernel/mpic.c
@@ -792,6 +792,35 @@
 #endif /* CONFIG_SMP */
 }
 
+/*
+ * XXX: someone who knows mpic should check this.
+ * do we need to eoi the ipi here (see xics comments)?
+ * or can we reset the mpic in the new kernel?
+ */
+void mpic_teardown_this_cpu(void)
+{
+	struct mpic *mpic = mpic_primary;
+	unsigned long flags;
+	u32 msk = 1 << hard_smp_processor_id();
+	unsigned int i;
+
+	BUG_ON(mpic == NULL);
+
+	DBG("%s: teardown_this_cpu(%d)\n", mpic->name, hard_smp_processor_id());
+	spin_lock_irqsave(&mpic_lock, flags);
+
+	/* let the mpic know we don't want intrs.  */
+	for (i = 0; i < mpic->num_sources ; i++)
+		mpic_irq_write(i, MPIC_IRQ_DESTINATION,
+			mpic_irq_read(i, MPIC_IRQ_DESTINATION) & ~msk);
+
+	/* Set current processor priority to max */
+	mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf);
+
+	spin_unlock_irqrestore(&mpic_lock, flags);
+}
+
+
 void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask)
 {
 	struct mpic *mpic = mpic_primary;
diff --git a/arch/ppc64/kernel/mpic.h b/arch/ppc64/kernel/mpic.h
index 571b3c9..99fbbc9 100644
--- a/arch/ppc64/kernel/mpic.h
+++ b/arch/ppc64/kernel/mpic.h
@@ -255,6 +255,9 @@
 /* Setup a non-boot CPU */
 extern void mpic_setup_this_cpu(void);
 
+/* Clean up for kexec (or cpu offline or ...) */
+extern void mpic_teardown_this_cpu(void);
+
 /* Request IPIs on primary mpic */
 extern void mpic_request_ipis(void);
 
@@ -265,3 +268,6 @@
 extern int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs);
 /* This one gets to the primary mpic */
 extern int mpic_get_irq(struct pt_regs *regs);
+
+/* global mpic for pSeries */
+extern struct mpic *pSeries_mpic;
diff --git a/arch/ppc64/kernel/of_device.c b/arch/ppc64/kernel/of_device.c
index f4c825a..66bd5ab7 100644
--- a/arch/ppc64/kernel/of_device.c
+++ b/arch/ppc64/kernel/of_device.c
@@ -161,7 +161,7 @@
 }
 
 
-static ssize_t dev_show_devspec(struct device *dev, char *buf)
+static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct of_device *ofdev;
 
diff --git a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c
index 0b1cca2..1f5f141 100644
--- a/arch/ppc64/kernel/pSeries_pci.c
+++ b/arch/ppc64/kernel/pSeries_pci.c
@@ -1,13 +1,11 @@
 /*
- * pSeries_pci.c
+ * arch/ppc64/kernel/pSeries_pci.c
  *
  * Copyright (C) 2001 Dave Engebretsen, IBM Corporation
  * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM
  *
  * pSeries specific routines for PCI.
  * 
- * Based on code from pci.c and chrp_pci.c
- *
  * 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
@@ -23,430 +21,18 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
+#include <linux/init.h>
+#include <linux/ioport.h>
 #include <linux/kernel.h>
-#include <linux/threads.h>
 #include <linux/pci.h>
 #include <linux/string.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
 
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
 #include <asm/pci-bridge.h>
-#include <asm/iommu.h>
-#include <asm/rtas.h>
+#include <asm/prom.h>
 
-#include "mpic.h"
 #include "pci.h"
 
-/* RTAS tokens */
-static int read_pci_config;
-static int write_pci_config;
-static int ibm_read_pci_config;
-static int ibm_write_pci_config;
-
-static int s7a_workaround;
-
-extern struct mpic *pSeries_mpic;
-
-static int config_access_valid(struct device_node *dn, int where)
-{
-	if (where < 256)
-		return 1;
-	if (where < 4096 && dn->pci_ext_config_space)
-		return 1;
-
-	return 0;
-}
-
-static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val)
-{
-	int returnval = -1;
-	unsigned long buid, addr;
-	int ret;
-
-	if (!dn)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	if (!config_access_valid(dn, where))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	addr = ((where & 0xf00) << 20) | (dn->busno << 16) |
-		(dn->devfn << 8) | (where & 0xff);
-	buid = dn->phb->buid;
-	if (buid) {
-		ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval,
-				addr, buid >> 32, buid & 0xffffffff, size);
-	} else {
-		ret = rtas_call(read_pci_config, 2, 2, &returnval, addr, size);
-	}
-	*val = returnval;
-
-	if (ret)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	if (returnval == EEH_IO_ERROR_VALUE(size)
-	    && eeh_dn_check_failure (dn, NULL))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int rtas_pci_read_config(struct pci_bus *bus,
-				unsigned int devfn,
-				int where, int size, u32 *val)
-{
-	struct device_node *busdn, *dn;
-
-	if (bus->self)
-		busdn = pci_device_to_OF_node(bus->self);
-	else
-		busdn = bus->sysdata;	/* must be a phb */
-
-	/* Search only direct children of the bus */
-	for (dn = busdn->child; dn; dn = dn->sibling)
-		if (dn->devfn == devfn)
-			return rtas_read_config(dn, where, size, val);
-	return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-static int rtas_write_config(struct device_node *dn, int where, int size, u32 val)
-{
-	unsigned long buid, addr;
-	int ret;
-
-	if (!dn)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	if (!config_access_valid(dn, where))
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-
-	addr = ((where & 0xf00) << 20) | (dn->busno << 16) |
-		(dn->devfn << 8) | (where & 0xff);
-	buid = dn->phb->buid;
-	if (buid) {
-		ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, buid >> 32, buid & 0xffffffff, size, (ulong) val);
-	} else {
-		ret = rtas_call(write_pci_config, 3, 1, NULL, addr, size, (ulong)val);
-	}
-
-	if (ret)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int rtas_pci_write_config(struct pci_bus *bus,
-				 unsigned int devfn,
-				 int where, int size, u32 val)
-{
-	struct device_node *busdn, *dn;
-
-	if (bus->self)
-		busdn = pci_device_to_OF_node(bus->self);
-	else
-		busdn = bus->sysdata;	/* must be a phb */
-
-	/* Search only direct children of the bus */
-	for (dn = busdn->child; dn; dn = dn->sibling)
-		if (dn->devfn == devfn)
-			return rtas_write_config(dn, where, size, val);
-	return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-struct pci_ops rtas_pci_ops = {
-	rtas_pci_read_config,
-	rtas_pci_write_config
-};
-
-int is_python(struct device_node *dev)
-{
-	char *model = (char *)get_property(dev, "model", NULL);
-
-	if (model && strstr(model, "Python"))
-		return 1;
-
-	return 0;
-}
-
-static int get_phb_reg_prop(struct device_node *dev,
-			    unsigned int addr_size_words,
-			    struct reg_property64 *reg)
-{
-	unsigned int *ui_ptr = NULL, len;
-
-	/* Found a PHB, now figure out where his registers are mapped. */
-	ui_ptr = (unsigned int *)get_property(dev, "reg", &len);
-	if (ui_ptr == NULL)
-		return 1;
-
-	if (addr_size_words == 1) {
-		reg->address = ((struct reg_property32 *)ui_ptr)->address;
-		reg->size    = ((struct reg_property32 *)ui_ptr)->size;
-	} else {
-		*reg = *((struct reg_property64 *)ui_ptr);
-	}
-
-	return 0;
-}
-
-static void python_countermeasures(struct device_node *dev,
-				   unsigned int addr_size_words)
-{
-	struct reg_property64 reg_struct;
-	void __iomem *chip_regs;
-	volatile u32 val;
-
-	if (get_phb_reg_prop(dev, addr_size_words, &reg_struct))
-		return;
-
-	/* Python's register file is 1 MB in size. */
-	chip_regs = ioremap(reg_struct.address & ~(0xfffffUL), 0x100000);
-
-	/* 
-	 * Firmware doesn't always clear this bit which is critical
-	 * for good performance - Anton
-	 */
-
-#define PRG_CL_RESET_VALID 0x00010000
-
-	val = in_be32(chip_regs + 0xf6030);
-	if (val & PRG_CL_RESET_VALID) {
-		printk(KERN_INFO "Python workaround: ");
-		val &= ~PRG_CL_RESET_VALID;
-		out_be32(chip_regs + 0xf6030, val);
-		/*
-		 * We must read it back for changes to
-		 * take effect
-		 */
-		val = in_be32(chip_regs + 0xf6030);
-		printk("reg0: %x\n", val);
-	}
-
-	iounmap(chip_regs);
-}
-
-void __init init_pci_config_tokens (void)
-{
-	read_pci_config = rtas_token("read-pci-config");
-	write_pci_config = rtas_token("write-pci-config");
-	ibm_read_pci_config = rtas_token("ibm,read-pci-config");
-	ibm_write_pci_config = rtas_token("ibm,write-pci-config");
-}
-
-unsigned long __devinit get_phb_buid (struct device_node *phb)
-{
-	int addr_cells;
-	unsigned int *buid_vals;
-	unsigned int len;
-	unsigned long buid;
-
-	if (ibm_read_pci_config == -1) return 0;
-
-	/* PHB's will always be children of the root node,
-	 * or so it is promised by the current firmware. */
-	if (phb->parent == NULL)
-		return 0;
-	if (phb->parent->parent)
-		return 0;
-
-	buid_vals = (unsigned int *) get_property(phb, "reg", &len);
-	if (buid_vals == NULL)
-		return 0;
-
-	addr_cells = prom_n_addr_cells(phb);
-	if (addr_cells == 1) {
-		buid = (unsigned long) buid_vals[0];
-	} else {
-		buid = (((unsigned long)buid_vals[0]) << 32UL) |
-			(((unsigned long)buid_vals[1]) & 0xffffffff);
-	}
-	return buid;
-}
-
-static int phb_set_bus_ranges(struct device_node *dev,
-			      struct pci_controller *phb)
-{
-	int *bus_range;
-	unsigned int len;
-
-	bus_range = (int *) get_property(dev, "bus-range", &len);
-	if (bus_range == NULL || len < 2 * sizeof(int)) {
-		return 1;
- 	}
- 
-	phb->first_busno =  bus_range[0];
-	phb->last_busno  =  bus_range[1];
-
-	return 0;
-}
-
-static int __devinit setup_phb(struct device_node *dev,
-			       struct pci_controller *phb,
-			       unsigned int addr_size_words)
-{
-	pci_setup_pci_controller(phb);
-
-	if (is_python(dev))
-		python_countermeasures(dev, addr_size_words);
-
-	if (phb_set_bus_ranges(dev, phb))
-		return 1;
-
-	phb->arch_data = dev;
-	phb->ops = &rtas_pci_ops;
-	phb->buid = get_phb_buid(dev);
-
-	return 0;
-}
-
-static void __devinit add_linux_pci_domain(struct device_node *dev,
-					   struct pci_controller *phb,
-					   struct property *of_prop)
-{
-	memset(of_prop, 0, sizeof(struct property));
-	of_prop->name = "linux,pci-domain";
-	of_prop->length = sizeof(phb->global_number);
-	of_prop->value = (unsigned char *)&of_prop[1];
-	memcpy(of_prop->value, &phb->global_number, sizeof(phb->global_number));
-	prom_add_property(dev, of_prop);
-}
-
-static struct pci_controller * __init alloc_phb(struct device_node *dev,
-						unsigned int addr_size_words)
-{
-	struct pci_controller *phb;
-	struct property *of_prop;
-
-	phb = alloc_bootmem(sizeof(struct pci_controller));
-	if (phb == NULL)
-		return NULL;
-
-	of_prop = alloc_bootmem(sizeof(struct property) +
-				sizeof(phb->global_number));
-	if (!of_prop)
-		return NULL;
-
-	if (setup_phb(dev, phb, addr_size_words))
-		return NULL;
-
-	add_linux_pci_domain(dev, phb, of_prop);
-
-	return phb;
-}
-
-static struct pci_controller * __devinit alloc_phb_dynamic(struct device_node *dev, unsigned int addr_size_words)
-{
-	struct pci_controller *phb;
-
-	phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller),
-					       GFP_KERNEL);
-	if (phb == NULL)
-		return NULL;
-
-	if (setup_phb(dev, phb, addr_size_words))
-		return NULL;
-
-	phb->is_dynamic = 1;
-
-	/* TODO: linux,pci-domain? */
-
- 	return phb;
-}
-
-unsigned long __init find_and_init_phbs(void)
-{
-	struct device_node *node;
-	struct pci_controller *phb;
-	unsigned int root_size_cells = 0;
-	unsigned int index;
-	unsigned int *opprop = NULL;
-	struct device_node *root = of_find_node_by_path("/");
-
-	if (ppc64_interrupt_controller == IC_OPEN_PIC) {
-		opprop = (unsigned int *)get_property(root,
-				"platform-open-pic", NULL);
-	}
-
-	root_size_cells = prom_n_size_cells(root);
-
-	index = 0;
-
-	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)
-			continue;
-
-		phb = alloc_phb(node, root_size_cells);
-		if (!phb)
-			continue;
-
-		pci_process_bridge_OF_ranges(phb, node);
-		pci_setup_phb_io(phb, index == 0);
-
-		if (ppc64_interrupt_controller == IC_OPEN_PIC && pSeries_mpic) {
-			int addr = root_size_cells * (index + 2) - 1;
-			mpic_assign_isu(pSeries_mpic, index, opprop[addr]);
-		}
-
-		index++;
-	}
-
-	of_node_put(root);
-	pci_devs_phb_init();
-
-	/*
-	 * pci_probe_only and pci_assign_all_buses can be set via properties
-	 * in chosen.
-	 */
-	if (of_chosen) {
-		int *prop;
-
-		prop = (int *)get_property(of_chosen, "linux,pci-probe-only",
-					   NULL);
-		if (prop)
-			pci_probe_only = *prop;
-
-		prop = (int *)get_property(of_chosen,
-					   "linux,pci-assign-all-buses", NULL);
-		if (prop)
-			pci_assign_all_buses = *prop;
-	}
-
-	return 0;
-}
-
-struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
-{
-	struct device_node *root = of_find_node_by_path("/");
-	unsigned int root_size_cells = 0;
-	struct pci_controller *phb;
-	struct pci_bus *bus;
-	int primary;
-
-	root_size_cells = prom_n_size_cells(root);
-
-	primary = list_empty(&hose_list);
-	phb = alloc_phb_dynamic(dn, root_size_cells);
-	if (!phb)
-		return NULL;
-
-	pci_process_bridge_OF_ranges(phb, dn);
-
-	pci_setup_phb_io_dynamic(phb, primary);
-	of_node_put(root);
-
-	pci_devs_phb_init_dynamic(phb);
-	phb->last_busno = 0xff;
-	bus = pci_scan_bus(phb->first_busno, phb->ops, phb->arch_data);
-	phb->bus = bus;
-	phb->last_busno = bus->subordinate;
-
-	return phb;
-}
-EXPORT_SYMBOL(init_phb_dynamic);
+static int __initdata s7a_workaround = -1;
 
 #if 0
 void pcibios_name_device(struct pci_dev *dev)
@@ -474,11 +60,12 @@
 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device);
 #endif
 
-static void check_s7a(void)
+static void __init check_s7a(void)
 {
 	struct device_node *root;
 	char *model;
 
+	s7a_workaround = 0;
 	root = of_find_node_by_path("/");
 	if (root) {
 		model = get_property(root, "model", NULL);
@@ -488,55 +75,23 @@
 	}
 }
 
-/* RPA-specific bits for removing PHBs */
-int pcibios_remove_root_bus(struct pci_controller *phb)
+void __devinit pSeries_irq_bus_setup(struct pci_bus *bus)
 {
-	struct pci_bus *b = phb->bus;
-	struct resource *res;
-	int rc, i;
+	struct pci_dev *dev;
 
-	res = b->resource[0];
-	if (!res->flags) {
-		printk(KERN_ERR "%s: no IO resource for PHB %s\n", __FUNCTION__,
-				b->name);
-		return 1;
-	}
-
-	rc = unmap_bus_range(b);
-	if (rc) {
-		printk(KERN_ERR "%s: failed to unmap IO on bus %s\n",
-			__FUNCTION__, b->name);
-		return 1;
-	}
-
-	if (release_resource(res)) {
-		printk(KERN_ERR "%s: failed to release IO on bus %s\n",
-				__FUNCTION__, b->name);
-		return 1;
-	}
-
-	for (i = 1; i < 3; ++i) {
-		res = b->resource[i];
-		if (!res->flags && i == 0) {
-			printk(KERN_ERR "%s: no MEM resource for PHB %s\n",
-				__FUNCTION__, b->name);
-			return 1;
-		}
-		if (res->flags && release_resource(res)) {
-			printk(KERN_ERR
-			       "%s: failed to release IO %d on bus %s\n",
-				__FUNCTION__, i, b->name);
-			return 1;
+	if (s7a_workaround < 0)
+		check_s7a();
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		pci_read_irq_line(dev);
+		if (s7a_workaround) {
+			if (dev->irq > 16) {
+				dev->irq -= 3;
+				pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
+					dev->irq);
+			}
 		}
 	}
-
-	list_del(&phb->list_node);
-	if (phb->is_dynamic)
-		kfree(phb);
-
-	return 0;
 }
-EXPORT_SYMBOL(pcibios_remove_root_bus);
 
 static void __init pSeries_request_regions(void)
 {
@@ -553,20 +108,6 @@
 
 void __init pSeries_final_fixup(void)
 {
-	struct pci_dev *dev = NULL;
-
-	check_s7a();
-
-	for_each_pci_dev(dev) {
-		pci_read_irq_line(dev);
-		if (s7a_workaround) {
-			if (dev->irq > 16) {
-				dev->irq -= 3;
-				pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-			}
-		}
-	}
-
 	phbs_remap_io();
 	pSeries_request_regions();
 
diff --git a/arch/ppc64/kernel/pSeries_setup.c b/arch/ppc64/kernel/pSeries_setup.c
index 6c0d1d5..44d9af7 100644
--- a/arch/ppc64/kernel/pSeries_setup.c
+++ b/arch/ppc64/kernel/pSeries_setup.c
@@ -71,11 +71,6 @@
 #define DBG(fmt...)
 #endif
 
-extern void pSeries_final_fixup(void);
-
-extern void pSeries_get_boot_time(struct rtc_time *rtc_time);
-extern void pSeries_get_rtc_time(struct rtc_time *rtc_time);
-extern int  pSeries_set_rtc_time(struct rtc_time *rtc_time);
 extern void find_udbg_vterm(void);
 extern void system_reset_fwnmi(void);	/* from head.S */
 extern void machine_check_fwnmi(void);	/* from head.S */
@@ -84,9 +79,6 @@
 
 int fwnmi_active;  /* TRUE if an FWNMI handler is present */
 
-extern unsigned long ppc_proc_freq;
-extern unsigned long ppc_tb_freq;
-
 extern void pSeries_system_reset_exception(struct pt_regs *regs);
 extern int pSeries_machine_check_exception(struct pt_regs *regs);
 
@@ -195,14 +187,16 @@
 {
 	/* Fixup ppc_md depending on the type of interrupt controller */
 	if (ppc64_interrupt_controller == IC_OPEN_PIC) {
-		ppc_md.init_IRQ       = pSeries_init_mpic; 
+		ppc_md.init_IRQ       = pSeries_init_mpic;
 		ppc_md.get_irq        = mpic_get_irq;
+	 	ppc_md.cpu_irq_down   = mpic_teardown_this_cpu;
 		/* Allocate the mpic now, so that find_and_init_phbs() can
 		 * fill the ISUs */
 		pSeries_setup_mpic();
 	} else {
 		ppc_md.init_IRQ       = xics_init_IRQ;
 		ppc_md.get_irq        = xics_get_irq;
+		ppc_md.cpu_irq_down   = xics_teardown_cpu;
 	}
 
 #ifdef CONFIG_SMP
@@ -381,171 +375,6 @@
 }
 
 
-static void pSeries_progress(char *s, unsigned short hex)
-{
-	struct device_node *root;
-	int width, *p;
-	char *os;
-	static int display_character, set_indicator;
-	static int max_width;
-	static DEFINE_SPINLOCK(progress_lock);
-	static int pending_newline = 0;  /* did last write end with unprinted newline? */
-
-	if (!rtas.base)
-		return;
-
-	if (max_width == 0) {
-		if ((root = find_path_device("/rtas")) &&
-		     (p = (unsigned int *)get_property(root,
-						       "ibm,display-line-length",
-						       NULL)))
-			max_width = *p;
-		else
-			max_width = 0x10;
-		display_character = rtas_token("display-character");
-		set_indicator = rtas_token("set-indicator");
-	}
-
-	if (display_character == RTAS_UNKNOWN_SERVICE) {
-		/* use hex display if available */
-		if (set_indicator != RTAS_UNKNOWN_SERVICE)
-			rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex);
-		return;
-	}
-
-	spin_lock(&progress_lock);
-
-	/*
-	 * Last write ended with newline, but we didn't print it since
-	 * it would just clear the bottom line of output. Print it now
-	 * instead.
-	 *
-	 * If no newline is pending, print a CR to start output at the
-	 * beginning of the line.
-	 */
-	if (pending_newline) {
-		rtas_call(display_character, 1, 1, NULL, '\r');
-		rtas_call(display_character, 1, 1, NULL, '\n');
-		pending_newline = 0;
-	} else {
-		rtas_call(display_character, 1, 1, NULL, '\r');
-	}
- 
-	width = max_width;
-	os = s;
-	while (*os) {
-		if (*os == '\n' || *os == '\r') {
-			/* Blank to end of line. */
-			while (width-- > 0)
-				rtas_call(display_character, 1, 1, NULL, ' ');
- 
-			/* If newline is the last character, save it
-			 * until next call to avoid bumping up the
-			 * display output.
-			 */
-			if (*os == '\n' && !os[1]) {
-				pending_newline = 1;
-				spin_unlock(&progress_lock);
-				return;
-			}
- 
-			/* RTAS wants CR-LF, not just LF */
- 
-			if (*os == '\n') {
-				rtas_call(display_character, 1, 1, NULL, '\r');
-				rtas_call(display_character, 1, 1, NULL, '\n');
-			} else {
-				/* CR might be used to re-draw a line, so we'll
-				 * leave it alone and not add LF.
-				 */
-				rtas_call(display_character, 1, 1, NULL, *os);
-			}
- 
-			width = max_width;
-		} else {
-			width--;
-			rtas_call(display_character, 1, 1, NULL, *os);
-		}
- 
-		os++;
- 
-		/* if we overwrite the screen length */
-		if (width <= 0)
-			while ((*os != 0) && (*os != '\n') && (*os != '\r'))
-				os++;
-	}
- 
-	/* Blank to end of line. */
-	while (width-- > 0)
-		rtas_call(display_character, 1, 1, NULL, ' ');
-
-	spin_unlock(&progress_lock);
-}
-
-extern void setup_default_decr(void);
-
-/* Some sane defaults: 125 MHz timebase, 1GHz processor */
-#define DEFAULT_TB_FREQ		125000000UL
-#define DEFAULT_PROC_FREQ	(DEFAULT_TB_FREQ * 8)
-
-static void __init pSeries_calibrate_decr(void)
-{
-	struct device_node *cpu;
-	struct div_result divres;
-	unsigned int *fp;
-	int node_found;
-
-	/*
-	 * The cpu node should have a timebase-frequency property
-	 * to tell us the rate at which the decrementer counts.
-	 */
-	cpu = of_find_node_by_type(NULL, "cpu");
-
-	ppc_tb_freq = DEFAULT_TB_FREQ;		/* hardcoded default */
-	node_found = 0;
-	if (cpu != 0) {
-		fp = (unsigned int *)get_property(cpu, "timebase-frequency",
-						  NULL);
-		if (fp != 0) {
-			node_found = 1;
-			ppc_tb_freq = *fp;
-		}
-	}
-	if (!node_found)
-		printk(KERN_ERR "WARNING: Estimating decrementer frequency "
-				"(not found)\n");
-
-	ppc_proc_freq = DEFAULT_PROC_FREQ;
-	node_found = 0;
-	if (cpu != 0) {
-		fp = (unsigned int *)get_property(cpu, "clock-frequency",
-						  NULL);
-		if (fp != 0) {
-			node_found = 1;
-			ppc_proc_freq = *fp;
-		}
-	}
-	if (!node_found)
-		printk(KERN_ERR "WARNING: Estimating processor frequency "
-				"(not found)\n");
-
-	of_node_put(cpu);
-
-	printk(KERN_INFO "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",
-	       ppc_proc_freq/1000000, ppc_proc_freq%1000000);
-
-	tb_ticks_per_jiffy = ppc_tb_freq / HZ;
-	tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
-	tb_ticks_per_usec = ppc_tb_freq / 1000000;
-	tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
-	div128_by_32(1024*1024, 0, tb_ticks_per_sec, &divres);
-	tb_to_xs = divres.result_low;
-
-	setup_default_decr();
-}
-
 static int pSeries_check_legacy_ioport(unsigned int baseport)
 {
 	struct device_node *np;
@@ -596,16 +425,17 @@
 	.get_cpuinfo		= pSeries_get_cpuinfo,
 	.log_error		= pSeries_log_error,
 	.pcibios_fixup		= pSeries_final_fixup,
+	.irq_bus_setup		= pSeries_irq_bus_setup,
 	.restart		= rtas_restart,
 	.power_off		= rtas_power_off,
 	.halt			= rtas_halt,
 	.panic			= rtas_os_term,
 	.cpu_die		= pSeries_mach_cpu_die,
-	.get_boot_time		= pSeries_get_boot_time,
-	.get_rtc_time		= pSeries_get_rtc_time,
-	.set_rtc_time		= pSeries_set_rtc_time,
-	.calibrate_decr		= pSeries_calibrate_decr,
-	.progress		= pSeries_progress,
+	.get_boot_time		= rtas_get_boot_time,
+	.get_rtc_time		= rtas_get_rtc_time,
+	.set_rtc_time		= rtas_set_rtc_time,
+	.calibrate_decr		= generic_calibrate_decr,
+	.progress		= rtas_progress,
 	.check_legacy_ioport	= pSeries_check_legacy_ioport,
 	.system_reset_exception = pSeries_system_reset_exception,
 	.machine_check_exception = pSeries_machine_check_exception,
diff --git a/arch/ppc64/kernel/pSeries_smp.c b/arch/ppc64/kernel/pSeries_smp.c
index fbad349..62c55a1 100644
--- a/arch/ppc64/kernel/pSeries_smp.c
+++ b/arch/ppc64/kernel/pSeries_smp.c
@@ -1,5 +1,5 @@
 /*
- * SMP support for pSeries machines.
+ * SMP support for pSeries and BPA machines.
  *
  * Dave Engebretsen, Peter Bergner, and
  * Mike Corrigan {engebret|bergner|mikec}@us.ibm.com
@@ -47,6 +47,7 @@
 #include <asm/pSeries_reconfig.h>
 
 #include "mpic.h"
+#include "bpa_iic.h"
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
@@ -92,10 +93,13 @@
 
 int pSeries_cpu_disable(void)
 {
+	int cpu = smp_processor_id();
+
+	cpu_clear(cpu, cpu_online_map);
 	systemcfg->processorCount--;
 
 	/*fix boot_cpuid here*/
-	if (smp_processor_id() == boot_cpuid)
+	if (cpu == boot_cpuid)
 		boot_cpuid = any_online_cpu(cpu_online_map);
 
 	/* FIXME: abstract this to not be platform specific later on */
@@ -286,6 +290,7 @@
 	return 1;
 }
 
+#ifdef CONFIG_XICS
 static inline void smp_xics_do_message(int cpu, int msg)
 {
 	set_bit(msg, &xics_ipi_message[cpu].value);
@@ -327,6 +332,37 @@
 	cpu_clear(cpu, of_spin_map);
 
 }
+#endif /* CONFIG_XICS */
+#ifdef CONFIG_BPA_IIC
+static void smp_iic_message_pass(int target, int msg)
+{
+	unsigned int i;
+
+	if (target < NR_CPUS) {
+		iic_cause_IPI(target, msg);
+	} else {
+		for_each_online_cpu(i) {
+			if (target == MSG_ALL_BUT_SELF
+			    && i == smp_processor_id())
+				continue;
+			iic_cause_IPI(i, msg);
+		}
+	}
+}
+
+static int __init smp_iic_probe(void)
+{
+	iic_request_IPIs();
+
+	return cpus_weight(cpu_possible_map);
+}
+
+static void __devinit smp_iic_setup_cpu(int cpu)
+{
+	if (cpu != boot_cpuid)
+		iic_setup_cpu();
+}
+#endif /* CONFIG_BPA_IIC */
 
 static DEFINE_SPINLOCK(timebase_lock);
 static unsigned long timebase = 0;
@@ -375,20 +411,21 @@
 	 * cpus are assumed to be secondary threads.
 	 */
 	if (system_state < SYSTEM_RUNNING &&
-	    cur_cpu_spec->cpu_features & CPU_FTR_SMT &&
+	    cpu_has_feature(CPU_FTR_SMT) &&
 	    !smt_enabled_at_boot && nr % 2 != 0)
 		return 0;
 
 	return 1;
 }
-
+#ifdef CONFIG_MPIC
 static struct smp_ops_t pSeries_mpic_smp_ops = {
 	.message_pass	= smp_mpic_message_pass,
 	.probe		= smp_mpic_probe,
 	.kick_cpu	= smp_pSeries_kick_cpu,
 	.setup_cpu	= smp_mpic_setup_cpu,
 };
-
+#endif
+#ifdef CONFIG_XICS
 static struct smp_ops_t pSeries_xics_smp_ops = {
 	.message_pass	= smp_xics_message_pass,
 	.probe		= smp_xics_probe,
@@ -396,6 +433,16 @@
 	.setup_cpu	= smp_xics_setup_cpu,
 	.cpu_bootable	= smp_pSeries_cpu_bootable,
 };
+#endif
+#ifdef CONFIG_BPA_IIC
+static struct smp_ops_t bpa_iic_smp_ops = {
+	.message_pass	= smp_iic_message_pass,
+	.probe		= smp_iic_probe,
+	.kick_cpu	= smp_pSeries_kick_cpu,
+	.setup_cpu	= smp_iic_setup_cpu,
+	.cpu_bootable	= smp_pSeries_cpu_bootable,
+};
+#endif
 
 /* This is called very early */
 void __init smp_init_pSeries(void)
@@ -404,10 +451,25 @@
 
 	DBG(" -> smp_init_pSeries()\n");
 
-	if (ppc64_interrupt_controller == IC_OPEN_PIC)
+	switch (ppc64_interrupt_controller) {
+#ifdef CONFIG_MPIC
+	case IC_OPEN_PIC:
 		smp_ops = &pSeries_mpic_smp_ops;
-	else
+		break;
+#endif
+#ifdef CONFIG_XICS
+	case IC_PPC_XIC:
 		smp_ops = &pSeries_xics_smp_ops;
+		break;
+#endif
+#ifdef CONFIG_BPA_IIC
+	case IC_BPA_IIC:
+		smp_ops = &bpa_iic_smp_ops;
+		break;
+#endif
+	default:
+		panic("Invalid interrupt controller");
+	}
 
 #ifdef CONFIG_HOTPLUG_CPU
 	smp_ops->cpu_disable = pSeries_cpu_disable;
@@ -419,8 +481,8 @@
 #endif
 
 	/* Mark threads which are still spinning in hold loops. */
-	if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
-		for_each_present_cpu(i) {
+	if (cpu_has_feature(CPU_FTR_SMT)) {
+		for_each_present_cpu(i) { 
 			if (i % 2 == 0)
 				/*
 				 * Even-numbered logical cpus correspond to
@@ -428,8 +490,9 @@
 				 */
 				cpu_set(i, of_spin_map);
 		}
-	else
+	} else {
 		of_spin_map = cpu_present_map;
+	}
 
 	cpu_clear(boot_cpuid, of_spin_map);
 
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c
index d786d4b..580676f 100644
--- a/arch/ppc64/kernel/pci.c
+++ b/arch/ppc64/kernel/pci.c
@@ -507,7 +507,7 @@
 }
 
 #ifdef CONFIG_PPC_MULTIPLATFORM
-static ssize_t pci_show_devspec(struct device *dev, 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;
@@ -902,6 +902,9 @@
 	list_for_each_entry(dev, &bus->devices, bus_list)
 		ppc_md.iommu_dev_setup(dev);
 
+	if (ppc_md.irq_bus_setup)
+		ppc_md.irq_bus_setup(bus);
+
 	if (!pci_probe_only)
 		return;
 
diff --git a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h
index 0fd7d84..26be78b 100644
--- a/arch/ppc64/kernel/pci.h
+++ b/arch/ppc64/kernel/pci.h
@@ -40,10 +40,14 @@
 void pci_addr_cache_insert_device(struct pci_dev *dev);
 void pci_addr_cache_remove_device(struct pci_dev *dev);
 
-/* From pSeries_pci.h */
+/* From rtas_pci.h */
 void init_pci_config_tokens (void);
 unsigned long get_phb_buid (struct device_node *);
 
+/* From pSeries_pci.h */
+extern void pSeries_final_fixup(void);
+extern void pSeries_irq_bus_setup(struct pci_bus *bus);
+
 extern unsigned long pci_probe_only;
 extern unsigned long pci_assign_all_buses;
 extern int pci_read_irq_line(struct pci_dev *pci_dev);
diff --git a/arch/ppc64/kernel/pmac_time.c b/arch/ppc64/kernel/pmac_time.c
index f248275..3059edb 100644
--- a/arch/ppc64/kernel/pmac_time.c
+++ b/arch/ppc64/kernel/pmac_time.c
@@ -40,11 +40,6 @@
 #define DBG(x...)
 #endif
 
-extern void setup_default_decr(void);
-
-extern unsigned long ppc_tb_freq;
-extern unsigned long ppc_proc_freq;
-
 /* Apparently the RTC stores seconds since 1 Jan 1904 */
 #define RTC_OFFSET	2082844800
 
@@ -161,8 +156,7 @@
 
 /*
  * Query the OF and get the decr frequency.
- * This was taken from the pmac time_init() when merging the prep/pmac
- * time functions.
+ * FIXME: merge this with generic_calibrate_decr
  */
 void __init pmac_calibrate_decr(void)
 {
diff --git a/arch/ppc64/kernel/proc_ppc64.c b/arch/ppc64/kernel/proc_ppc64.c
index 0914b06..a87c66a 100644
--- a/arch/ppc64/kernel/proc_ppc64.c
+++ b/arch/ppc64/kernel/proc_ppc64.c
@@ -53,7 +53,7 @@
 	if (!root)
 		return 1;
 
-	if (!(systemcfg->platform & PLATFORM_PSERIES))
+	if (!(systemcfg->platform & (PLATFORM_PSERIES | PLATFORM_BPA)))
 		return 0;
 
 	if (!proc_mkdir("rtas", root))
diff --git a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c
index cdfecbe..aba8955 100644
--- a/arch/ppc64/kernel/process.c
+++ b/arch/ppc64/kernel/process.c
@@ -58,14 +58,6 @@
 struct task_struct *last_task_used_altivec = NULL;
 #endif
 
-struct mm_struct ioremap_mm = {
-	.pgd		= ioremap_dir,
-	.mm_users	= ATOMIC_INIT(2),
-	.mm_count	= ATOMIC_INIT(1),
-	.cpu_vm_mask	= CPU_MASK_ALL,
-	.page_table_lock = SPIN_LOCK_UNLOCKED,
-};
-
 /*
  * Make sure the floating-point register state in the
  * the thread_struct is up to date for task tsk.
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
index eb6538b..47727a6 100644
--- a/arch/ppc64/kernel/prom.c
+++ b/arch/ppc64/kernel/prom.c
@@ -884,6 +884,7 @@
 {
 	char *type = get_flat_dt_prop(node, "device_type", NULL);
 	u32 *prop;
+	unsigned long size;
 
 	/* We are scanning "cpu" nodes only */
 	if (type == NULL || strcmp(type, "cpu") != 0)
@@ -929,6 +930,17 @@
 		cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC;
 	}
 
+	/*
+	 * Check for an SMT capable CPU and set the CPU feature. We do
+	 * this by looking at the size of the ibm,ppc-interrupt-server#s
+	 * property
+	 */
+	prop = (u32 *)get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s",
+				       &size);
+	cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT;
+	if (prop && ((size / sizeof(u32)) > 1))
+		cur_cpu_spec->cpu_features |= CPU_FTR_SMT;
+
 	return 0;
 }
 
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
index b7683ab..e248a79 100644
--- a/arch/ppc64/kernel/prom_init.c
+++ b/arch/ppc64/kernel/prom_init.c
@@ -1915,9 +1915,9 @@
 		prom_send_capabilities();
 
 	/*
-	 * On pSeries, copy the CPU hold code
+	 * On pSeries and BPA, copy the CPU hold code
 	 */
-       	if (RELOC(of_platform) & PLATFORM_PSERIES)
+       	if (RELOC(of_platform) & (PLATFORM_PSERIES | PLATFORM_BPA))
        		copy_and_flush(0, KERNELBASE - offset, 0x100, 0);
 
 	/*
diff --git a/arch/ppc64/kernel/ptrace.c b/arch/ppc64/kernel/ptrace.c
index 9f8c608..2993f10 100644
--- a/arch/ppc64/kernel/ptrace.c
+++ b/arch/ppc64/kernel/ptrace.c
@@ -305,6 +305,8 @@
 
 void do_syscall_trace_enter(struct pt_regs *regs)
 {
+	secure_computing(regs->gpr[0]);
+
 	if (test_thread_flag(TIF_SYSCALL_TRACE)
 	    && (current->ptrace & PT_PTRACED))
 		do_syscall_trace();
@@ -320,8 +322,6 @@
 
 void do_syscall_trace_leave(struct pt_regs *regs)
 {
-	secure_computing(regs->gpr[0]);
-
 	if (unlikely(current->audit_context))
 		audit_syscall_exit(current, 
 				   (regs->ccr&0x1000)?AUDITSC_FAILURE:AUDITSC_SUCCESS,
diff --git a/arch/ppc64/kernel/ras.c b/arch/ppc64/kernel/ras.c
index 1c4c796..3c00f7b 100644
--- a/arch/ppc64/kernel/ras.c
+++ b/arch/ppc64/kernel/ras.c
@@ -47,7 +47,6 @@
 #include <asm/cache.h>
 #include <asm/prom.h>
 #include <asm/ptrace.h>
-#include <asm/iSeries/LparData.h>
 #include <asm/machdep.h>
 #include <asm/rtas.h>
 #include <asm/ppcdebug.h>
diff --git a/arch/ppc64/kernel/rtas-proc.c b/arch/ppc64/kernel/rtas-proc.c
index 28b1f15..1f3ff86 100644
--- a/arch/ppc64/kernel/rtas-proc.c
+++ b/arch/ppc64/kernel/rtas-proc.c
@@ -371,11 +371,11 @@
 	/* Lets see if the user passed hexdigits */
 	hex = simple_strtoul(progress_led, NULL, 10);
 
-	ppc_md.progress ((char *)progress_led, hex);
+	rtas_progress ((char *)progress_led, hex);
 	return count;
 
 	/* clear the line */
-	/* ppc_md.progress("                   ", 0xffff);*/
+	/* rtas_progress("                   ", 0xffff);*/
 }
 /* ****************************************************************** */
 static int ppc_rtas_progress_show(struct seq_file *m, void *v)
diff --git a/arch/ppc64/kernel/rtas.c b/arch/ppc64/kernel/rtas.c
index 5575603..5e8eb33 100644
--- a/arch/ppc64/kernel/rtas.c
+++ b/arch/ppc64/kernel/rtas.c
@@ -91,6 +91,123 @@
 	}
 }
 
+void
+rtas_progress(char *s, unsigned short hex)
+{
+	struct device_node *root;
+	int width, *p;
+	char *os;
+	static int display_character, set_indicator;
+	static int display_width, display_lines, *row_width, form_feed;
+	static DEFINE_SPINLOCK(progress_lock);
+	static int current_line;
+	static int pending_newline = 0;  /* did last write end with unprinted newline? */
+
+	if (!rtas.base)
+		return;
+
+	if (display_width == 0) {
+		display_width = 0x10;
+		if ((root = find_path_device("/rtas"))) {
+			if ((p = (unsigned int *)get_property(root,
+					"ibm,display-line-length", NULL)))
+				display_width = *p;
+			if ((p = (unsigned int *)get_property(root,
+					"ibm,form-feed", NULL)))
+				form_feed = *p;
+			if ((p = (unsigned int *)get_property(root,
+					"ibm,display-number-of-lines", NULL)))
+				display_lines = *p;
+			row_width = (unsigned int *)get_property(root,
+					"ibm,display-truncation-length", NULL);
+		}
+		display_character = rtas_token("display-character");
+		set_indicator = rtas_token("set-indicator");
+	}
+
+	if (display_character == RTAS_UNKNOWN_SERVICE) {
+		/* use hex display if available */
+		if (set_indicator != RTAS_UNKNOWN_SERVICE)
+			rtas_call(set_indicator, 3, 1, NULL, 6, 0, hex);
+		return;
+	}
+
+	spin_lock(&progress_lock);
+
+	/*
+	 * Last write ended with newline, but we didn't print it since
+	 * it would just clear the bottom line of output. Print it now
+	 * instead.
+	 *
+	 * If no newline is pending and form feed is supported, clear the
+	 * display with a form feed; otherwise, print a CR to start output
+	 * at the beginning of the line.
+	 */
+	if (pending_newline) {
+		rtas_call(display_character, 1, 1, NULL, '\r');
+		rtas_call(display_character, 1, 1, NULL, '\n');
+		pending_newline = 0;
+	} else {
+		current_line = 0;
+		if (form_feed)
+			rtas_call(display_character, 1, 1, NULL,
+				  (char)form_feed);
+		else
+			rtas_call(display_character, 1, 1, NULL, '\r');
+	}
+ 
+	if (row_width)
+		width = row_width[current_line];
+	else
+		width = display_width;
+	os = s;
+	while (*os) {
+		if (*os == '\n' || *os == '\r') {
+			/* If newline is the last character, save it
+			 * until next call to avoid bumping up the
+			 * display output.
+			 */
+			if (*os == '\n' && !os[1]) {
+				pending_newline = 1;
+				current_line++;
+				if (current_line > display_lines-1)
+					current_line = display_lines-1;
+				spin_unlock(&progress_lock);
+				return;
+			}
+ 
+			/* RTAS wants CR-LF, not just LF */
+ 
+			if (*os == '\n') {
+				rtas_call(display_character, 1, 1, NULL, '\r');
+				rtas_call(display_character, 1, 1, NULL, '\n');
+			} else {
+				/* CR might be used to re-draw a line, so we'll
+				 * leave it alone and not add LF.
+				 */
+				rtas_call(display_character, 1, 1, NULL, *os);
+			}
+ 
+			if (row_width)
+				width = row_width[current_line];
+			else
+				width = display_width;
+		} else {
+			width--;
+			rtas_call(display_character, 1, 1, NULL, *os);
+		}
+ 
+		os++;
+ 
+		/* if we overwrite the screen length */
+		if (width <= 0)
+			while ((*os != 0) && (*os != '\n') && (*os != '\r'))
+				os++;
+	}
+ 
+	spin_unlock(&progress_lock);
+}
+
 int
 rtas_token(const char *service)
 {
@@ -425,8 +542,8 @@
 
 	printk(KERN_ALERT "FLASH: flash image is %ld bytes\n", image_size);
 	printk(KERN_ALERT "FLASH: performing flash and reboot\n");
-	ppc_md.progress("Flashing        \n", 0x0);
-	ppc_md.progress("Please Wait...  ", 0x0);
+	rtas_progress("Flashing        \n", 0x0);
+	rtas_progress("Please Wait...  ", 0x0);
 	printk(KERN_ALERT "FLASH: this will take several minutes.  Do not power off!\n");
 	status = rtas_call(update_token, 1, 1, NULL, rtas_block_list);
 	switch (status) {	/* should only get "bad" status */
diff --git a/arch/ppc64/kernel/rtas_pci.c b/arch/ppc64/kernel/rtas_pci.c
new file mode 100644
index 0000000..1048817
--- /dev/null
+++ b/arch/ppc64/kernel/rtas_pci.c
@@ -0,0 +1,495 @@
+/*
+ * arch/ppc64/kernel/rtas_pci.c
+ *
+ * Copyright (C) 2001 Dave Engebretsen, IBM Corporation
+ * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM
+ *
+ * RTAS specific routines for PCI.
+ * 
+ * Based on code from pci.c, chrp_pci.c and pSeries_pci.c
+ *
+ * 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/threads.h>
+#include <linux/pci.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/pci-bridge.h>
+#include <asm/iommu.h>
+#include <asm/rtas.h>
+
+#include "mpic.h"
+#include "pci.h"
+
+/* RTAS tokens */
+static int read_pci_config;
+static int write_pci_config;
+static int ibm_read_pci_config;
+static int ibm_write_pci_config;
+
+static int config_access_valid(struct device_node *dn, int where)
+{
+	if (where < 256)
+		return 1;
+	if (where < 4096 && dn->pci_ext_config_space)
+		return 1;
+
+	return 0;
+}
+
+static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val)
+{
+	int returnval = -1;
+	unsigned long buid, addr;
+	int ret;
+
+	if (!dn)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if (!config_access_valid(dn, where))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	addr = ((where & 0xf00) << 20) | (dn->busno << 16) |
+		(dn->devfn << 8) | (where & 0xff);
+	buid = dn->phb->buid;
+	if (buid) {
+		ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval,
+				addr, buid >> 32, buid & 0xffffffff, size);
+	} else {
+		ret = rtas_call(read_pci_config, 2, 2, &returnval, addr, size);
+	}
+	*val = returnval;
+
+	if (ret)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if (returnval == EEH_IO_ERROR_VALUE(size)
+	    && eeh_dn_check_failure (dn, NULL))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int rtas_pci_read_config(struct pci_bus *bus,
+				unsigned int devfn,
+				int where, int size, u32 *val)
+{
+	struct device_node *busdn, *dn;
+
+	if (bus->self)
+		busdn = pci_device_to_OF_node(bus->self);
+	else
+		busdn = bus->sysdata;	/* must be a phb */
+
+	/* Search only direct children of the bus */
+	for (dn = busdn->child; dn; dn = dn->sibling)
+		if (dn->devfn == devfn)
+			return rtas_read_config(dn, where, size, val);
+	return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+static int rtas_write_config(struct device_node *dn, int where, int size, u32 val)
+{
+	unsigned long buid, addr;
+	int ret;
+
+	if (!dn)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if (!config_access_valid(dn, where))
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	addr = ((where & 0xf00) << 20) | (dn->busno << 16) |
+		(dn->devfn << 8) | (where & 0xff);
+	buid = dn->phb->buid;
+	if (buid) {
+		ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, buid >> 32, buid & 0xffffffff, size, (ulong) val);
+	} else {
+		ret = rtas_call(write_pci_config, 3, 1, NULL, addr, size, (ulong)val);
+	}
+
+	if (ret)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int rtas_pci_write_config(struct pci_bus *bus,
+				 unsigned int devfn,
+				 int where, int size, u32 val)
+{
+	struct device_node *busdn, *dn;
+
+	if (bus->self)
+		busdn = pci_device_to_OF_node(bus->self);
+	else
+		busdn = bus->sysdata;	/* must be a phb */
+
+	/* Search only direct children of the bus */
+	for (dn = busdn->child; dn; dn = dn->sibling)
+		if (dn->devfn == devfn)
+			return rtas_write_config(dn, where, size, val);
+	return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+struct pci_ops rtas_pci_ops = {
+	rtas_pci_read_config,
+	rtas_pci_write_config
+};
+
+int is_python(struct device_node *dev)
+{
+	char *model = (char *)get_property(dev, "model", NULL);
+
+	if (model && strstr(model, "Python"))
+		return 1;
+
+	return 0;
+}
+
+static int get_phb_reg_prop(struct device_node *dev,
+			    unsigned int addr_size_words,
+			    struct reg_property64 *reg)
+{
+	unsigned int *ui_ptr = NULL, len;
+
+	/* Found a PHB, now figure out where his registers are mapped. */
+	ui_ptr = (unsigned int *)get_property(dev, "reg", &len);
+	if (ui_ptr == NULL)
+		return 1;
+
+	if (addr_size_words == 1) {
+		reg->address = ((struct reg_property32 *)ui_ptr)->address;
+		reg->size    = ((struct reg_property32 *)ui_ptr)->size;
+	} else {
+		*reg = *((struct reg_property64 *)ui_ptr);
+	}
+
+	return 0;
+}
+
+static void python_countermeasures(struct device_node *dev,
+				   unsigned int addr_size_words)
+{
+	struct reg_property64 reg_struct;
+	void __iomem *chip_regs;
+	volatile u32 val;
+
+	if (get_phb_reg_prop(dev, addr_size_words, &reg_struct))
+		return;
+
+	/* Python's register file is 1 MB in size. */
+	chip_regs = ioremap(reg_struct.address & ~(0xfffffUL), 0x100000);
+
+	/* 
+	 * Firmware doesn't always clear this bit which is critical
+	 * for good performance - Anton
+	 */
+
+#define PRG_CL_RESET_VALID 0x00010000
+
+	val = in_be32(chip_regs + 0xf6030);
+	if (val & PRG_CL_RESET_VALID) {
+		printk(KERN_INFO "Python workaround: ");
+		val &= ~PRG_CL_RESET_VALID;
+		out_be32(chip_regs + 0xf6030, val);
+		/*
+		 * We must read it back for changes to
+		 * take effect
+		 */
+		val = in_be32(chip_regs + 0xf6030);
+		printk("reg0: %x\n", val);
+	}
+
+	iounmap(chip_regs);
+}
+
+void __init init_pci_config_tokens (void)
+{
+	read_pci_config = rtas_token("read-pci-config");
+	write_pci_config = rtas_token("write-pci-config");
+	ibm_read_pci_config = rtas_token("ibm,read-pci-config");
+	ibm_write_pci_config = rtas_token("ibm,write-pci-config");
+}
+
+unsigned long __devinit get_phb_buid (struct device_node *phb)
+{
+	int addr_cells;
+	unsigned int *buid_vals;
+	unsigned int len;
+	unsigned long buid;
+
+	if (ibm_read_pci_config == -1) return 0;
+
+	/* PHB's will always be children of the root node,
+	 * or so it is promised by the current firmware. */
+	if (phb->parent == NULL)
+		return 0;
+	if (phb->parent->parent)
+		return 0;
+
+	buid_vals = (unsigned int *) get_property(phb, "reg", &len);
+	if (buid_vals == NULL)
+		return 0;
+
+	addr_cells = prom_n_addr_cells(phb);
+	if (addr_cells == 1) {
+		buid = (unsigned long) buid_vals[0];
+	} else {
+		buid = (((unsigned long)buid_vals[0]) << 32UL) |
+			(((unsigned long)buid_vals[1]) & 0xffffffff);
+	}
+	return buid;
+}
+
+static int phb_set_bus_ranges(struct device_node *dev,
+			      struct pci_controller *phb)
+{
+	int *bus_range;
+	unsigned int len;
+
+	bus_range = (int *) get_property(dev, "bus-range", &len);
+	if (bus_range == NULL || len < 2 * sizeof(int)) {
+		return 1;
+ 	}
+ 
+	phb->first_busno =  bus_range[0];
+	phb->last_busno  =  bus_range[1];
+
+	return 0;
+}
+
+static int __devinit setup_phb(struct device_node *dev,
+			       struct pci_controller *phb,
+			       unsigned int addr_size_words)
+{
+	pci_setup_pci_controller(phb);
+
+	if (is_python(dev))
+		python_countermeasures(dev, addr_size_words);
+
+	if (phb_set_bus_ranges(dev, phb))
+		return 1;
+
+	phb->arch_data = dev;
+	phb->ops = &rtas_pci_ops;
+	phb->buid = get_phb_buid(dev);
+
+	return 0;
+}
+
+static void __devinit add_linux_pci_domain(struct device_node *dev,
+					   struct pci_controller *phb,
+					   struct property *of_prop)
+{
+	memset(of_prop, 0, sizeof(struct property));
+	of_prop->name = "linux,pci-domain";
+	of_prop->length = sizeof(phb->global_number);
+	of_prop->value = (unsigned char *)&of_prop[1];
+	memcpy(of_prop->value, &phb->global_number, sizeof(phb->global_number));
+	prom_add_property(dev, of_prop);
+}
+
+static struct pci_controller * __init alloc_phb(struct device_node *dev,
+						unsigned int addr_size_words)
+{
+	struct pci_controller *phb;
+	struct property *of_prop;
+
+	phb = alloc_bootmem(sizeof(struct pci_controller));
+	if (phb == NULL)
+		return NULL;
+
+	of_prop = alloc_bootmem(sizeof(struct property) +
+				sizeof(phb->global_number));
+	if (!of_prop)
+		return NULL;
+
+	if (setup_phb(dev, phb, addr_size_words))
+		return NULL;
+
+	add_linux_pci_domain(dev, phb, of_prop);
+
+	return phb;
+}
+
+static struct pci_controller * __devinit alloc_phb_dynamic(struct device_node *dev, unsigned int addr_size_words)
+{
+	struct pci_controller *phb;
+
+	phb = (struct pci_controller *)kmalloc(sizeof(struct pci_controller),
+					       GFP_KERNEL);
+	if (phb == NULL)
+		return NULL;
+
+	if (setup_phb(dev, phb, addr_size_words))
+		return NULL;
+
+	phb->is_dynamic = 1;
+
+	/* TODO: linux,pci-domain? */
+
+ 	return phb;
+}
+
+unsigned long __init find_and_init_phbs(void)
+{
+	struct device_node *node;
+	struct pci_controller *phb;
+	unsigned int root_size_cells = 0;
+	unsigned int index;
+	unsigned int *opprop = NULL;
+	struct device_node *root = of_find_node_by_path("/");
+
+	if (ppc64_interrupt_controller == IC_OPEN_PIC) {
+		opprop = (unsigned int *)get_property(root,
+				"platform-open-pic", NULL);
+	}
+
+	root_size_cells = prom_n_size_cells(root);
+
+	index = 0;
+
+	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)
+			continue;
+
+		phb = alloc_phb(node, root_size_cells);
+		if (!phb)
+			continue;
+
+		pci_process_bridge_OF_ranges(phb, node);
+		pci_setup_phb_io(phb, index == 0);
+#ifdef CONFIG_PPC_PSERIES
+		if (ppc64_interrupt_controller == IC_OPEN_PIC && pSeries_mpic) {
+			int addr = root_size_cells * (index + 2) - 1;
+			mpic_assign_isu(pSeries_mpic, index, opprop[addr]);
+		}
+#endif
+		index++;
+	}
+
+	of_node_put(root);
+	pci_devs_phb_init();
+
+	/*
+	 * pci_probe_only and pci_assign_all_buses can be set via properties
+	 * in chosen.
+	 */
+	if (of_chosen) {
+		int *prop;
+
+		prop = (int *)get_property(of_chosen, "linux,pci-probe-only",
+					   NULL);
+		if (prop)
+			pci_probe_only = *prop;
+
+		prop = (int *)get_property(of_chosen,
+					   "linux,pci-assign-all-buses", NULL);
+		if (prop)
+			pci_assign_all_buses = *prop;
+	}
+
+	return 0;
+}
+
+struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
+{
+	struct device_node *root = of_find_node_by_path("/");
+	unsigned int root_size_cells = 0;
+	struct pci_controller *phb;
+	struct pci_bus *bus;
+	int primary;
+
+	root_size_cells = prom_n_size_cells(root);
+
+	primary = list_empty(&hose_list);
+	phb = alloc_phb_dynamic(dn, root_size_cells);
+	if (!phb)
+		return NULL;
+
+	pci_process_bridge_OF_ranges(phb, dn);
+
+	pci_setup_phb_io_dynamic(phb, primary);
+	of_node_put(root);
+
+	pci_devs_phb_init_dynamic(phb);
+	phb->last_busno = 0xff;
+	bus = pci_scan_bus(phb->first_busno, phb->ops, phb->arch_data);
+	phb->bus = bus;
+	phb->last_busno = bus->subordinate;
+
+	return phb;
+}
+EXPORT_SYMBOL(init_phb_dynamic);
+
+/* RPA-specific bits for removing PHBs */
+int pcibios_remove_root_bus(struct pci_controller *phb)
+{
+	struct pci_bus *b = phb->bus;
+	struct resource *res;
+	int rc, i;
+
+	res = b->resource[0];
+	if (!res->flags) {
+		printk(KERN_ERR "%s: no IO resource for PHB %s\n", __FUNCTION__,
+				b->name);
+		return 1;
+	}
+
+	rc = unmap_bus_range(b);
+	if (rc) {
+		printk(KERN_ERR "%s: failed to unmap IO on bus %s\n",
+			__FUNCTION__, b->name);
+		return 1;
+	}
+
+	if (release_resource(res)) {
+		printk(KERN_ERR "%s: failed to release IO on bus %s\n",
+				__FUNCTION__, b->name);
+		return 1;
+	}
+
+	for (i = 1; i < 3; ++i) {
+		res = b->resource[i];
+		if (!res->flags && i == 0) {
+			printk(KERN_ERR "%s: no MEM resource for PHB %s\n",
+				__FUNCTION__, b->name);
+			return 1;
+		}
+		if (res->flags && release_resource(res)) {
+			printk(KERN_ERR
+			       "%s: failed to release IO %d on bus %s\n",
+				__FUNCTION__, i, b->name);
+			return 1;
+		}
+	}
+
+	list_del(&phb->list_node);
+	if (phb->is_dynamic)
+		kfree(phb);
+
+	return 0;
+}
+EXPORT_SYMBOL(pcibios_remove_root_bus);
diff --git a/arch/ppc64/kernel/rtasd.c b/arch/ppc64/kernel/rtasd.c
index ff65dc3..b0c3b82 100644
--- a/arch/ppc64/kernel/rtasd.c
+++ b/arch/ppc64/kernel/rtasd.c
@@ -440,7 +440,7 @@
 		goto error;
 	}
 
-	printk(KERN_ERR "RTAS daemon started\n");
+	printk(KERN_INFO "RTAS daemon started\n");
 
 	DEBUG("will sleep for %d jiffies\n", (HZ*60/rtas_event_scan_rate) / 2);
 
@@ -485,7 +485,7 @@
 	/* No RTAS, only warn if we are on a pSeries box  */
 	if (rtas_token("event-scan") == RTAS_UNKNOWN_SERVICE) {
 		if (systemcfg->platform & PLATFORM_PSERIES)
-			printk(KERN_ERR "rtasd: no event-scan on system\n");
+			printk(KERN_INFO "rtasd: no event-scan on system\n");
 		return 1;
 	}
 
diff --git a/arch/ppc64/kernel/rtc.c b/arch/ppc64/kernel/rtc.c
index 6798905..d729fef 100644
--- a/arch/ppc64/kernel/rtc.c
+++ b/arch/ppc64/kernel/rtc.c
@@ -42,10 +42,8 @@
 #include <asm/time.h>
 #include <asm/rtas.h>
 
-#include <asm/iSeries/LparData.h>
 #include <asm/iSeries/mf.h>
 #include <asm/machdep.h>
-#include <asm/iSeries/ItSpCommArea.h>
 
 extern int piranha_simulator;
 
@@ -303,7 +301,7 @@
 #ifdef CONFIG_PPC_RTAS
 #define MAX_RTC_WAIT 5000	/* 5 sec */
 #define RTAS_CLOCK_BUSY (-2)
-void pSeries_get_boot_time(struct rtc_time *rtc_tm)
+void rtas_get_boot_time(struct rtc_time *rtc_tm)
 {
 	int ret[8];
 	int error, wait_time;
@@ -338,7 +336,7 @@
  * and if a delay is needed to read the clock.  In this case we just
  * silently return without updating rtc_tm.
  */
-void pSeries_get_rtc_time(struct rtc_time *rtc_tm)
+void rtas_get_rtc_time(struct rtc_time *rtc_tm)
 {
         int ret[8];
 	int error, wait_time;
@@ -373,7 +371,7 @@
 	rtc_tm->tm_year = ret[0] - 1900;
 }
 
-int pSeries_set_rtc_time(struct rtc_time *tm)
+int rtas_set_rtc_time(struct rtc_time *tm)
 {
 	int error, wait_time;
 	unsigned long max_wait_tb;
diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c
index dce198d..d5e4866 100644
--- a/arch/ppc64/kernel/setup.c
+++ b/arch/ppc64/kernel/setup.c
@@ -41,7 +41,6 @@
 #include <asm/smp.h>
 #include <asm/elf.h>
 #include <asm/machdep.h>
-#include <asm/iSeries/LparData.h>
 #include <asm/paca.h>
 #include <asm/ppcdebug.h>
 #include <asm/time.h>
@@ -57,6 +56,8 @@
 #include <asm/cache.h>
 #include <asm/page.h>
 #include <asm/mmu.h>
+#include <asm/lmb.h>
+#include <asm/iSeries/ItLpNaca.h>
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
@@ -343,6 +344,7 @@
 extern struct machdep_calls pSeries_md;
 extern struct machdep_calls pmac_md;
 extern struct machdep_calls maple_md;
+extern struct machdep_calls bpa_md;
 
 /* Ultimately, stuff them in an elf section like initcalls... */
 static struct machdep_calls __initdata *machines[] = {
@@ -355,6 +357,9 @@
 #ifdef CONFIG_PPC_MAPLE
 	&maple_md,
 #endif /* CONFIG_PPC_MAPLE */
+#ifdef CONFIG_PPC_BPA
+	&bpa_md,
+#endif
 	NULL
 };
 
@@ -672,37 +677,52 @@
 	DBG(" <- setup_system()\n");
 }
 
+/* also used by kexec */
+void machine_shutdown(void)
+{
+	if (ppc_md.nvram_sync)
+		ppc_md.nvram_sync();
+}
 
 void machine_restart(char *cmd)
 {
-	if (ppc_md.nvram_sync)
-		ppc_md.nvram_sync();
+	machine_shutdown();
 	ppc_md.restart(cmd);
+#ifdef CONFIG_SMP
+	smp_send_stop();
+#endif
+	printk(KERN_EMERG "System Halted, OK to turn off power\n");
+	local_irq_disable();
+	while (1) ;
 }
-
 EXPORT_SYMBOL(machine_restart);
-  
+
 void machine_power_off(void)
 {
-	if (ppc_md.nvram_sync)
-		ppc_md.nvram_sync();
+	machine_shutdown();
 	ppc_md.power_off();
+#ifdef CONFIG_SMP
+	smp_send_stop();
+#endif
+	printk(KERN_EMERG "System Halted, OK to turn off power\n");
+	local_irq_disable();
+	while (1) ;
 }
-
 EXPORT_SYMBOL(machine_power_off);
-  
+
 void machine_halt(void)
 {
-	if (ppc_md.nvram_sync)
-		ppc_md.nvram_sync();
+	machine_shutdown();
 	ppc_md.halt();
+#ifdef CONFIG_SMP
+	smp_send_stop();
+#endif
+	printk(KERN_EMERG "System Halted, OK to turn off power\n");
+	local_irq_disable();
+	while (1) ;
 }
-
 EXPORT_SYMBOL(machine_halt);
 
-unsigned long ppc_proc_freq;
-unsigned long ppc_tb_freq;
-
 static int ppc64_panic_event(struct notifier_block *this,
                              unsigned long event, void *ptr)
 {
@@ -1054,6 +1074,7 @@
 
 	/* set up the bootmem stuff with available memory */
 	do_init_bootmem();
+	sparse_init();
 
 	/* initialize the syscall map in systemcfg */
 	setup_syscall_map();
@@ -1078,11 +1099,11 @@
 static void ppc64_do_msg(unsigned int src, const char *msg)
 {
 	if (ppc_md.progress) {
-		char buf[32];
+		char buf[128];
 
-		sprintf(buf, "%08x        \n", src);
+		sprintf(buf, "%08X\n", src);
 		ppc_md.progress(buf, 0);
-		sprintf(buf, "%-16s", msg);
+		snprintf(buf, 128, "%s", msg);
 		ppc_md.progress(buf, 0);
 	}
 }
@@ -1116,7 +1137,7 @@
 }
 
 /* This should only be called on processor 0 during calibrate decr */
-void setup_default_decr(void)
+void __init setup_default_decr(void)
 {
 	struct paca_struct *lpaca = get_paca();
 
diff --git a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c
index 9ef5d36..2fcddfc 100644
--- a/arch/ppc64/kernel/smp.c
+++ b/arch/ppc64/kernel/smp.c
@@ -71,7 +71,7 @@
 
 int smt_enabled_at_boot = 1;
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
+#ifdef CONFIG_MPIC
 void smp_mpic_message_pass(int target, int msg)
 {
 	/* make sure we're sending something that translates to an IPI */
@@ -128,7 +128,7 @@
 	smp_mb();
 }
 
-#endif /* CONFIG_PPC_MULTIPLATFORM */
+#endif /* CONFIG_MPIC */
 
 static void __init smp_space_timers(unsigned int max_cpus)
 {
diff --git a/arch/ppc64/kernel/spider-pic.c b/arch/ppc64/kernel/spider-pic.c
new file mode 100644
index 0000000..d5c9a02
--- /dev/null
+++ b/arch/ppc64/kernel/spider-pic.c
@@ -0,0 +1,191 @@
+/*
+ * External Interrupt Controller on Spider South Bridge
+ *
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ *
+ * Author: Arnd Bergmann <arndb@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.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <asm/pgtable.h>
+#include <asm/prom.h>
+#include <asm/io.h>
+
+#include "bpa_iic.h"
+
+/* register layout taken from Spider spec, table 7.4-4 */
+enum {
+	TIR_DEN		= 0x004, /* Detection Enable Register */
+	TIR_MSK		= 0x084, /* Mask Level Register */
+	TIR_EDC		= 0x0c0, /* Edge Detection Clear Register */
+	TIR_PNDA	= 0x100, /* Pending Register A */
+	TIR_PNDB	= 0x104, /* Pending Register B */
+	TIR_CS		= 0x144, /* Current Status Register */
+	TIR_LCSA	= 0x150, /* Level Current Status Register A */
+	TIR_LCSB	= 0x154, /* Level Current Status Register B */
+	TIR_LCSC	= 0x158, /* Level Current Status Register C */
+	TIR_LCSD	= 0x15c, /* Level Current Status Register D */
+	TIR_CFGA	= 0x200, /* Setting Register A0 */
+	TIR_CFGB	= 0x204, /* Setting Register B0 */
+			/* 0x208 ... 0x3ff Setting Register An/Bn */
+	TIR_PPNDA	= 0x400, /* Packet Pending Register A */
+	TIR_PPNDB	= 0x404, /* Packet Pending Register B */
+	TIR_PIERA	= 0x408, /* Packet Output Error Register A */
+	TIR_PIERB	= 0x40c, /* Packet Output Error Register B */
+	TIR_PIEN	= 0x444, /* Packet Output Enable Register */
+	TIR_PIPND	= 0x454, /* Packet Output Pending Register */
+	TIRDID		= 0x484, /* Spider Device ID Register */
+	REISTIM		= 0x500, /* Reissue Command Timeout Time Setting */
+	REISTIMEN	= 0x504, /* Reissue Command Timeout Setting */
+	REISWAITEN	= 0x508, /* Reissue Wait Control*/
+};
+
+static void __iomem *spider_pics[4];
+
+static void __iomem *spider_get_pic(int irq)
+{
+	int node = irq / IIC_NODE_STRIDE;
+	irq %= IIC_NODE_STRIDE;
+
+	if (irq >= IIC_EXT_OFFSET &&
+	    irq < IIC_EXT_OFFSET + IIC_NUM_EXT &&
+	    spider_pics)
+		return spider_pics[node];
+	return NULL;
+}
+
+static int spider_get_nr(unsigned int irq)
+{
+	return (irq % IIC_NODE_STRIDE) - IIC_EXT_OFFSET;
+}
+
+static void __iomem *spider_get_irq_config(int irq)
+{
+	void __iomem *pic;
+	pic = spider_get_pic(irq);
+	return pic + TIR_CFGA + 8 * spider_get_nr(irq);
+}
+
+static void spider_enable_irq(unsigned int irq)
+{
+	void __iomem *cfg = spider_get_irq_config(irq);
+	irq = spider_get_nr(irq);
+
+	out_be32(cfg, in_be32(cfg) | 0x3107000eu);
+	out_be32(cfg + 4, in_be32(cfg + 4) | 0x00020000u | irq);
+}
+
+static void spider_disable_irq(unsigned int irq)
+{
+	void __iomem *cfg = spider_get_irq_config(irq);
+	irq = spider_get_nr(irq);
+
+	out_be32(cfg, in_be32(cfg) & ~0x30000000u);
+}
+
+static unsigned int spider_startup_irq(unsigned int irq)
+{
+	spider_enable_irq(irq);
+	return 0;
+}
+
+static void spider_shutdown_irq(unsigned int irq)
+{
+	spider_disable_irq(irq);
+}
+
+static void spider_end_irq(unsigned int irq)
+{
+	spider_enable_irq(irq);
+}
+
+static void spider_ack_irq(unsigned int irq)
+{
+	spider_disable_irq(irq);
+	iic_local_enable();
+}
+
+static struct hw_interrupt_type spider_pic = {
+	.typename = " SPIDER   ",
+	.startup = spider_startup_irq,
+	.shutdown = spider_shutdown_irq,
+	.enable = spider_enable_irq,
+	.disable = spider_disable_irq,
+	.ack = spider_ack_irq,
+	.end = spider_end_irq,
+};
+
+
+int spider_get_irq(unsigned long int_pending)
+{
+	void __iomem *regs = spider_get_pic(int_pending);
+	unsigned long cs;
+	int irq;
+
+	cs = in_be32(regs + TIR_CS);
+
+	irq = cs >> 24;
+	if (irq != 63)
+		return irq;
+
+	return -1;
+}
+ 
+void spider_init_IRQ(void)
+{
+	int node;
+	struct device_node *dn;
+	unsigned int *property;
+	long spiderpic;
+	int n;
+
+/* FIXME: detect multiple PICs as soon as the device tree has them */
+	for (node = 0; node < 1; node++) {
+		dn = of_find_node_by_path("/");
+		n = prom_n_addr_cells(dn);
+		property = (unsigned int *) get_property(dn,
+				"platform-spider-pic", NULL);
+
+		if (!property)
+			continue;
+		for (spiderpic = 0; n > 0; --n)
+			spiderpic = (spiderpic << 32) + *property++;
+		printk(KERN_DEBUG "SPIDER addr: %lx\n", spiderpic);
+		spider_pics[node] = __ioremap(spiderpic, 0x800, _PAGE_NO_CACHE);
+		for (n = 0; n < IIC_NUM_EXT; n++) {
+			int irq = n + IIC_EXT_OFFSET + node * IIC_NODE_STRIDE;
+			get_irq_desc(irq)->handler = &spider_pic;
+
+ 		/* do not mask any interrupts because of level */
+ 		out_be32(spider_pics[node] + TIR_MSK, 0x0);
+ 		
+ 		/* disable edge detection clear */
+ 		/* out_be32(spider_pics[node] + TIR_EDC, 0x0); */
+ 		
+ 		/* enable interrupt packets to be output */
+ 		out_be32(spider_pics[node] + TIR_PIEN,
+			in_be32(spider_pics[node] + TIR_PIEN) | 0x1);
+ 		
+ 		/* Enable the interrupt detection enable bit. Do this last! */
+ 		out_be32(spider_pics[node] + TIR_DEN,
+			in_be32(spider_pics[node] +TIR_DEN) | 0x1);
+
+		}
+	}
+}
diff --git a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
index 7cf7a96..118436e 100644
--- a/arch/ppc64/kernel/sys_ppc32.c
+++ b/arch/ppc64/kernel/sys_ppc32.c
@@ -741,6 +741,7 @@
 
 asmlinkage int sys32_pciconfig_iobase(u32 which, u32 in_bus, u32 in_devfn)
 {
+#ifdef CONFIG_PCI
 	struct pci_controller* hose;
 	struct list_head *ln;
 	struct pci_bus *bus = NULL;
@@ -786,36 +787,11 @@
 	case IOBASE_ISA_MEM:
 		return -EINVAL;
 	}
-
+#endif	/* CONFIG_PCI */
 	return -EOPNOTSUPP;
 }
 
 
-asmlinkage int ppc64_newuname(struct new_utsname __user * name)
-{
-	int errno = sys_newuname(name);
-
-	if (current->personality == PER_LINUX32 && !errno) {
-		if(copy_to_user(name->machine, "ppc\0\0", 8)) {
-			errno = -EFAULT;
-		}
-	}
-	return errno;
-}
-
-asmlinkage int ppc64_personality(unsigned long personality)
-{
-	int ret;
-	if (current->personality == PER_LINUX32 && personality == PER_LINUX)
-		personality = PER_LINUX32;
-	ret = sys_personality(personality);
-	if (ret == PER_LINUX32)
-		ret = PER_LINUX;
-	return ret;
-}
-
-
-
 /* Note: it is necessary to treat mode as an unsigned int,
  * with the corresponding cast to a signed int to insure that the 
  * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
@@ -1158,26 +1134,47 @@
 }
 #endif
 
+asmlinkage int sys32_uname(struct old_utsname __user * name)
+{
+	int err = 0;
+	
+	down_read(&uts_sem);
+	if (copy_to_user(name, &system_utsname, sizeof(*name)))
+		err = -EFAULT;
+	up_read(&uts_sem);
+	if (!err && personality(current->personality) == PER_LINUX32) {
+		/* change "ppc64" to "ppc" */
+		if (__put_user(0, name->machine + 3)
+		    || __put_user(0, name->machine + 4))
+			err = -EFAULT;
+	}
+	return err;
+}
+
 asmlinkage int sys32_olduname(struct oldold_utsname __user * name)
 {
 	int error;
-	
-	if (!name)
-		return -EFAULT;
+
 	if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
 		return -EFAULT;
   
 	down_read(&uts_sem);
 	error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
-	error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
-	error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
-	error -= __put_user(0,name->release+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
-	error -= __put_user(0,name->version+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
-	error = __put_user(0,name->machine+__OLD_UTS_LEN);
+	error |= __put_user(0,name->sysname+__OLD_UTS_LEN);
+	error |= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
+	error |= __put_user(0,name->nodename+__OLD_UTS_LEN);
+	error |= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
+	error |= __put_user(0,name->release+__OLD_UTS_LEN);
+	error |= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
+	error |= __put_user(0,name->version+__OLD_UTS_LEN);
+	error |= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
+	error |= __put_user(0,name->machine+__OLD_UTS_LEN);
+	if (personality(current->personality) == PER_LINUX32) {
+		/* change "ppc64" to "ppc" */
+		error |= __put_user(0, name->machine + 3);
+		error |= __put_user(0, name->machine + 4);
+	}
+	
 	up_read(&uts_sem);
 
 	error = error ? -EFAULT : 0;
diff --git a/arch/ppc64/kernel/syscalls.c b/arch/ppc64/kernel/syscalls.c
index f2865ff..a8cbb20 100644
--- a/arch/ppc64/kernel/syscalls.c
+++ b/arch/ppc64/kernel/syscalls.c
@@ -199,24 +199,33 @@
 	return ret;
 }
 
-static int __init set_fakeppc(char *str)
+long ppc64_personality(unsigned long personality)
 {
-	if (*str)
-		return 0;
-	init_task.personality = PER_LINUX32;
-	return 1;
-}
-__setup("fakeppc", set_fakeppc);
+	long ret;
 
-asmlinkage int sys_uname(struct old_utsname __user * name)
+	if (personality(current->personality) == PER_LINUX32
+	    && personality == PER_LINUX)
+		personality = PER_LINUX32;
+	ret = sys_personality(personality);
+	if (ret == PER_LINUX32)
+		ret = PER_LINUX;
+	return ret;
+}
+
+long ppc64_newuname(struct new_utsname __user * name)
 {
-	int err = -EFAULT;
-	
+	int err = 0;
+
 	down_read(&uts_sem);
-	if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
-		err = 0;
+	if (copy_to_user(name, &system_utsname, sizeof(*name)))
+		err = -EFAULT;
 	up_read(&uts_sem);
-	
+	if (!err && personality(current->personality) == PER_LINUX32) {
+		/* change ppc64 to ppc */
+		if (__put_user(0, name->machine + 3)
+		    || __put_user(0, name->machine + 4))
+			err = -EFAULT;
+	}
 	return err;
 }
 
diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
index 33364a7..2348a75 100644
--- a/arch/ppc64/kernel/time.c
+++ b/arch/ppc64/kernel/time.c
@@ -107,6 +107,9 @@
 
 static unsigned adjusting_time = 0;
 
+unsigned long ppc_proc_freq;
+unsigned long ppc_tb_freq;
+
 static __inline__ void timer_check_rtc(void)
 {
         /*
@@ -472,6 +475,66 @@
 
 EXPORT_SYMBOL(do_settimeofday);
 
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_MAPLE) || defined(CONFIG_PPC_BPA)
+void __init generic_calibrate_decr(void)
+{
+	struct device_node *cpu;
+	struct div_result divres;
+	unsigned int *fp;
+	int node_found;
+
+	/*
+	 * The cpu node should have a timebase-frequency property
+	 * to tell us the rate at which the decrementer counts.
+	 */
+	cpu = of_find_node_by_type(NULL, "cpu");
+
+	ppc_tb_freq = DEFAULT_TB_FREQ;		/* hardcoded default */
+	node_found = 0;
+	if (cpu != 0) {
+		fp = (unsigned int *)get_property(cpu, "timebase-frequency",
+						  NULL);
+		if (fp != 0) {
+			node_found = 1;
+			ppc_tb_freq = *fp;
+		}
+	}
+	if (!node_found)
+		printk(KERN_ERR "WARNING: Estimating decrementer frequency "
+				"(not found)\n");
+
+	ppc_proc_freq = DEFAULT_PROC_FREQ;
+	node_found = 0;
+	if (cpu != 0) {
+		fp = (unsigned int *)get_property(cpu, "clock-frequency",
+						  NULL);
+		if (fp != 0) {
+			node_found = 1;
+			ppc_proc_freq = *fp;
+		}
+	}
+	if (!node_found)
+		printk(KERN_ERR "WARNING: Estimating processor frequency "
+				"(not found)\n");
+
+	of_node_put(cpu);
+
+	printk(KERN_INFO "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",
+	       ppc_proc_freq/1000000, ppc_proc_freq%1000000);
+
+	tb_ticks_per_jiffy = ppc_tb_freq / HZ;
+	tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
+	tb_ticks_per_usec = ppc_tb_freq / 1000000;
+	tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
+	div128_by_32(1024*1024, 0, tb_ticks_per_sec, &divres);
+	tb_to_xs = divres.result_low;
+
+	setup_default_decr();
+}
+#endif
+
 void __init time_init(void)
 {
 	/* This function is only called on the boot processor */
diff --git a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c
index 7e52cb2..a8d5e83 100644
--- a/arch/ppc64/kernel/traps.c
+++ b/arch/ppc64/kernel/traps.c
@@ -126,6 +126,10 @@
 			printk("POWERMAC ");
 			nl = 1;
 			break;
+		case PLATFORM_BPA:
+			printk("BPA ");
+			nl = 1;
+			break;
 	}
 	if (nl)
 		printk("\n");
diff --git a/arch/ppc64/kernel/vio.c b/arch/ppc64/kernel/vio.c
index cdd830c..0c0ba71 100644
--- a/arch/ppc64/kernel/vio.c
+++ b/arch/ppc64/kernel/vio.c
@@ -41,20 +41,25 @@
 static struct iommu_table *vio_build_iommu_table(struct vio_dev *);
 static int vio_num_address_cells;
 #endif
-static struct vio_dev *vio_bus_device; /* fake "parent" device */
+#ifdef CONFIG_PPC_ISERIES
+static struct iommu_table veth_iommu_table;
+static struct iommu_table vio_iommu_table;
+#endif
+static struct vio_dev vio_bus_device  = { /* fake "parent" device */
+	.name = vio_bus_device.dev.bus_id,
+	.type = "",
+#ifdef CONFIG_PPC_ISERIES
+	.iommu_table = &vio_iommu_table,
+#endif
+	.dev.bus_id = "vio",
+	.dev.bus = &vio_bus_type,
+};
 
 #ifdef CONFIG_PPC_ISERIES
 static struct vio_dev *__init vio_register_device_iseries(char *type,
 		uint32_t unit_num);
 
-static struct iommu_table veth_iommu_table;
-static struct iommu_table vio_iommu_table;
-
-static struct vio_dev _vio_dev  = {
-	.iommu_table = &vio_iommu_table,
-	.dev.bus = &vio_bus_type
-};
-struct device *iSeries_vio_dev = &_vio_dev.dev;
+struct device *iSeries_vio_dev = &vio_bus_device.dev;
 EXPORT_SYMBOL(iSeries_vio_dev);
 
 #define device_is_compatible(a, b)	1
@@ -260,18 +265,10 @@
 	}
 
 	/* the fake parent of all vio devices, just to give us a nice directory */
-	vio_bus_device = kmalloc(sizeof(struct vio_dev), GFP_KERNEL);
-	if (!vio_bus_device) {
-		return 1;
-	}
-	memset(vio_bus_device, 0, sizeof(struct vio_dev));
-	strcpy(vio_bus_device->dev.bus_id, "vio");
-
-	err = device_register(&vio_bus_device->dev);
+	err = device_register(&vio_bus_device.dev);
 	if (err) {
 		printk(KERN_WARNING "%s: device_register returned %i\n", __FUNCTION__,
 			err);
-		kfree(vio_bus_device);
 		return err;
 	}
 
@@ -300,7 +297,7 @@
 }
 
 #ifdef CONFIG_PPC_PSERIES
-static ssize_t viodev_show_devspec(struct device *dev, char *buf)
+static ssize_t viodev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct device_node *of_node = dev->platform_data;
 
@@ -309,7 +306,7 @@
 DEVICE_ATTR(devspec, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_devspec, NULL);
 #endif
 
-static ssize_t viodev_show_name(struct device *dev, char *buf)
+static ssize_t viodev_show_name(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	return sprintf(buf, "%s\n", to_vio_dev(dev)->name);
 }
@@ -326,7 +323,7 @@
 	viodev->unit_address = unit_address;
 	viodev->iommu_table = iommu_table;
 	/* init generic 'struct device' fields: */
-	viodev->dev.parent = &vio_bus_device->dev;
+	viodev->dev.parent = &vio_bus_device.dev;
 	viodev->dev.bus = &vio_bus_type;
 	viodev->dev.release = vio_dev_release;
 
@@ -636,5 +633,3 @@
 	.name = "vio",
 	.match = vio_bus_match,
 };
-
-EXPORT_SYMBOL(vio_bus_type);
diff --git a/arch/ppc64/kernel/viopath.c b/arch/ppc64/kernel/viopath.c
index 2ed8ee0..2a6c4f0 100644
--- a/arch/ppc64/kernel/viopath.c
+++ b/arch/ppc64/kernel/viopath.c
@@ -43,12 +43,10 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/iSeries/HvTypes.h>
-#include <asm/iSeries/LparData.h>
+#include <asm/iSeries/ItExtVpdPanel.h>
 #include <asm/iSeries/HvLpEvent.h>
 #include <asm/iSeries/HvLpConfig.h>
-#include <asm/iSeries/HvCallCfg.h>
 #include <asm/iSeries/mf.h>
-#include <asm/iSeries/iSeries_proc.h>
 #include <asm/iSeries/vio.h>
 
 /* Status of the path to each other partition in the system.
@@ -365,7 +363,7 @@
 	 * while we're active
 	 */
 	viopath_ourLp = HvLpConfig_getLpIndex();
-	viopath_hostLp = HvCallCfg_getHostingLpIndex(viopath_ourLp);
+	viopath_hostLp = HvLpConfig_getHostingLpIndex(viopath_ourLp);
 
 	if (viopath_hostLp != HvLpIndexInvalid)
 		vio_setHandler(viomajorsubtype_config, handleConfig);
@@ -487,7 +485,7 @@
 	unsigned long flags;
 	int tempNumAllocated;
 
-	if ((remoteLp >= HvMaxArchitectedLps) || (remoteLp == HvLpIndexInvalid))
+	if ((remoteLp >= HVMAXARCHITECTEDLPS) || (remoteLp == HvLpIndexInvalid))
 		return -EINVAL;
 
 	subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
@@ -558,7 +556,7 @@
 	int numOpen;
 	struct alloc_parms parms;
 
-	if ((remoteLp >= HvMaxArchitectedLps) || (remoteLp == HvLpIndexInvalid))
+	if ((remoteLp >= HVMAXARCHITECTEDLPS) || (remoteLp == HvLpIndexInvalid))
 		return -EINVAL;
 
 	subtype = subtype >> VIOMAJOR_SUBTYPE_SHIFT;
diff --git a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c
index 879f39b..677c445 100644
--- a/arch/ppc64/kernel/xics.c
+++ b/arch/ppc64/kernel/xics.c
@@ -647,6 +647,31 @@
 	}
 }
 
+void xics_teardown_cpu(void)
+{
+	int cpu = smp_processor_id();
+	int status;
+
+	ops->cppr_info(cpu, 0x00);
+	iosync();
+
+	/*
+	 * we need to EOI the IPI if we got here from kexec down IPI
+	 *
+	 * xics doesn't care if we duplicate an EOI as long as we
+	 * don't EOI and raise priority.
+	 *
+	 * 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);
+
+	status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
+		(1UL << interrupt_server_size) - 1 - default_distrib_server, 0);
+	WARN_ON(status != 0);
+}
+
 #ifdef CONFIG_HOTPLUG_CPU
 
 /* Interrupts are disabled. */
diff --git a/arch/ppc64/lib/Makefile b/arch/ppc64/lib/Makefile
index bf7b5bb..76fbfa9 100644
--- a/arch/ppc64/lib/Makefile
+++ b/arch/ppc64/lib/Makefile
@@ -12,7 +12,7 @@
 
 # e2a provides EBCDIC to ASCII conversions.
 ifdef CONFIG_PPC_ISERIES
-obj-$(CONFIG_PCI)	+= e2a.o
+obj-y += e2a.o
 endif
 
 lib-$(CONFIG_DEBUG_KERNEL) += sstep.o
diff --git a/arch/ppc64/mm/Makefile b/arch/ppc64/mm/Makefile
index ac522d5..3695d00 100644
--- a/arch/ppc64/mm/Makefile
+++ b/arch/ppc64/mm/Makefile
@@ -6,6 +6,6 @@
 
 obj-y := fault.o init.o imalloc.o hash_utils.o hash_low.o tlb.o \
 	slb_low.o slb.o stab.o mmap.o
-obj-$(CONFIG_DISCONTIGMEM) += numa.o
+obj-$(CONFIG_NEED_MULTIPLE_NODES) += numa.o
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
 obj-$(CONFIG_PPC_MULTIPLATFORM) += hash_native.o
diff --git a/arch/ppc64/mm/hash_native.c b/arch/ppc64/mm/hash_native.c
index 52b6b93..4fec058 100644
--- a/arch/ppc64/mm/hash_native.c
+++ b/arch/ppc64/mm/hash_native.c
@@ -304,6 +304,50 @@
 	local_irq_restore(flags);
 }
 
+/*
+ * clear all mappings on kexec.  All cpus are in real mode (or they will
+ * be when they isi), and we are the only one left.  We rely on our kernel
+ * mapping being 0xC0's and the hardware ignoring those two real bits.
+ *
+ * TODO: add batching support when enabled.  remember, no dynamic memory here,
+ * athough there is the control page available...
+ */
+static void native_hpte_clear(void)
+{
+	unsigned long slot, slots, flags;
+	HPTE *hptep = htab_address;
+	Hpte_dword0 dw0;
+	unsigned long pteg_count;
+
+	pteg_count = htab_hash_mask + 1;
+
+	local_irq_save(flags);
+
+	/* we take the tlbie lock and hold it.  Some hardware will
+	 * deadlock if we try to tlbie from two processors at once.
+	 */
+	spin_lock(&native_tlbie_lock);
+
+	slots = pteg_count * HPTES_PER_GROUP;
+
+	for (slot = 0; slot < slots; slot++, hptep++) {
+		/*
+		 * we could lock the pte here, but we are the only cpu
+		 * running,  right?  and for crash dump, we probably
+		 * don't want to wait for a maybe bad cpu.
+		 */
+		dw0 = hptep->dw0.dw0;
+
+		if (dw0.v) {
+			hptep->dw0.dword0 = 0;
+			tlbie(slot2va(dw0.avpn, dw0.l, dw0.h, slot), dw0.l);
+		}
+	}
+
+	spin_unlock(&native_tlbie_lock);
+	local_irq_restore(flags);
+}
+
 static void native_flush_hash_range(unsigned long context,
 				    unsigned long number, int local)
 {
@@ -415,7 +459,8 @@
 	ppc_md.hpte_updatepp	= native_hpte_updatepp;
 	ppc_md.hpte_updateboltedpp = native_hpte_updateboltedpp;
 	ppc_md.hpte_insert	= native_hpte_insert;
-	ppc_md.hpte_remove     	= native_hpte_remove;
+	ppc_md.hpte_remove	= native_hpte_remove;
+	ppc_md.hpte_clear_all	= native_hpte_clear;
 	if (tlb_batching_enabled())
 		ppc_md.flush_hash_range = native_flush_hash_range;
 	htab_finish_init();
diff --git a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c
index 0a0f970..1647b1c 100644
--- a/arch/ppc64/mm/hash_utils.c
+++ b/arch/ppc64/mm/hash_utils.c
@@ -195,7 +195,7 @@
 		memset((void *)table, 0, htab_size_bytes);
 	}
 
-	mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX;
+	mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX;
 
 	/* On U3 based machines, we need to reserve the DART area and
 	 * _NOT_ map it to avoid cache paradoxes as it's remapped non
@@ -310,10 +310,6 @@
 
 		vsid = get_vsid(mm->context.id, ea);
 		break;
-	case IO_REGION_ID:
-		mm = &ioremap_mm;
-		vsid = get_kernel_vsid(ea);
-		break;
 	case VMALLOC_REGION_ID:
 		mm = &init_mm;
 		vsid = get_kernel_vsid(ea);
diff --git a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c
index d3bf86a..fdcfe97 100644
--- a/arch/ppc64/mm/hugetlbpage.c
+++ b/arch/ppc64/mm/hugetlbpage.c
@@ -121,7 +121,7 @@
 	return hugepte_offset(dir, addr);
 }
 
-static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 {
 	pud_t *pud;
 
@@ -134,7 +134,7 @@
 	return hugepte_offset(pud, addr);
 }
 
-static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
 {
 	pud_t *pud;
 
@@ -147,25 +147,6 @@
 	return hugepte_alloc(mm, pud, addr);
 }
 
-static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
-			 unsigned long addr, struct page *page,
-			 pte_t *ptep, int write_access)
-{
-	pte_t entry;
-
-	add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
-	if (write_access) {
-		entry =
-		    pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
-	} else {
-		entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot));
-	}
-	entry = pte_mkyoung(entry);
-	entry = pte_mkhuge(entry);
-
-	set_pte_at(mm, addr, ptep, entry);
-}
-
 /*
  * This function checks for proper alignment of input addr and len parameters.
  */
@@ -259,80 +240,6 @@
 	return -EINVAL;
 }
 
-int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
-			struct vm_area_struct *vma)
-{
-	pte_t *src_pte, *dst_pte, entry;
-	struct page *ptepage;
-	unsigned long addr = vma->vm_start;
-	unsigned long end = vma->vm_end;
-	int err = -ENOMEM;
-
-	while (addr < end) {
-		dst_pte = huge_pte_alloc(dst, addr);
-		if (!dst_pte)
-			goto out;
-
-		src_pte = huge_pte_offset(src, addr);
-		entry = *src_pte;
-		
-		ptepage = pte_page(entry);
-		get_page(ptepage);
-		add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
-		set_pte_at(dst, addr, dst_pte, entry);
-
-		addr += HPAGE_SIZE;
-	}
-
-	err = 0;
- out:
-	return err;
-}
-
-int
-follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
-		    struct page **pages, struct vm_area_struct **vmas,
-		    unsigned long *position, int *length, int i)
-{
-	unsigned long vpfn, vaddr = *position;
-	int remainder = *length;
-
-	WARN_ON(!is_vm_hugetlb_page(vma));
-
-	vpfn = vaddr/PAGE_SIZE;
-	while (vaddr < vma->vm_end && remainder) {
-		if (pages) {
-			pte_t *pte;
-			struct page *page;
-
-			pte = huge_pte_offset(mm, vaddr);
-
-			/* hugetlb should be locked, and hence, prefaulted */
-			WARN_ON(!pte || pte_none(*pte));
-
-			page = &pte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)];
-
-			WARN_ON(!PageCompound(page));
-
-			get_page(page);
-			pages[i] = page;
-		}
-
-		if (vmas)
-			vmas[i] = vma;
-
-		vaddr += PAGE_SIZE;
-		++vpfn;
-		--remainder;
-		++i;
-	}
-
-	*length = remainder;
-	*position = vaddr;
-
-	return i;
-}
-
 struct page *
 follow_huge_addr(struct mm_struct *mm, unsigned long address, int write)
 {
@@ -363,89 +270,6 @@
 	return NULL;
 }
 
-void unmap_hugepage_range(struct vm_area_struct *vma,
-			  unsigned long start, unsigned long end)
-{
-	struct mm_struct *mm = vma->vm_mm;
-	unsigned long addr;
-	pte_t *ptep;
-	struct page *page;
-
-	WARN_ON(!is_vm_hugetlb_page(vma));
-	BUG_ON((start % HPAGE_SIZE) != 0);
-	BUG_ON((end % HPAGE_SIZE) != 0);
-
-	for (addr = start; addr < end; addr += HPAGE_SIZE) {
-		pte_t pte;
-
-		ptep = huge_pte_offset(mm, addr);
-		if (!ptep || pte_none(*ptep))
-			continue;
-
-		pte = *ptep;
-		page = pte_page(pte);
-		pte_clear(mm, addr, ptep);
-
-		put_page(page);
-	}
-	add_mm_counter(mm, rss, -((end - start) >> PAGE_SHIFT));
-	flush_tlb_pending();
-}
-
-int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
-{
-	struct mm_struct *mm = current->mm;
-	unsigned long addr;
-	int ret = 0;
-
-	WARN_ON(!is_vm_hugetlb_page(vma));
-	BUG_ON((vma->vm_start % HPAGE_SIZE) != 0);
-	BUG_ON((vma->vm_end % HPAGE_SIZE) != 0);
-
-	spin_lock(&mm->page_table_lock);
-	for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
-		unsigned long idx;
-		pte_t *pte = huge_pte_alloc(mm, addr);
-		struct page *page;
-
-		if (!pte) {
-			ret = -ENOMEM;
-			goto out;
-		}
-		if (! pte_none(*pte))
-			continue;
-
-		idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
-			+ (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
-		page = find_get_page(mapping, idx);
-		if (!page) {
-			/* charge the fs quota first */
-			if (hugetlb_get_quota(mapping)) {
-				ret = -ENOMEM;
-				goto out;
-			}
-			page = alloc_huge_page();
-			if (!page) {
-				hugetlb_put_quota(mapping);
-				ret = -ENOMEM;
-				goto out;
-			}
-			ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
-			if (! ret) {
-				unlock_page(page);
-			} else {
-				hugetlb_put_quota(mapping);
-				free_huge_page(page);
-				goto out;
-			}
-		}
-		set_huge_pte(mm, vma, addr, page, pte, vma->vm_flags & VM_WRITE);
-	}
-out:
-	spin_unlock(&mm->page_table_lock);
-	return ret;
-}
-
 /* Because we have an exclusive hugepage region which lies within the
  * normal user address space, we have to take special measures to make
  * non-huge mmap()s evade the hugepage reserved regions. */
@@ -468,7 +292,12 @@
 		    && !is_hugepage_only_range(mm, addr,len))
 			return addr;
 	}
-	start_addr = addr = mm->free_area_cache;
+	if (len > mm->cached_hole_size) {
+	        start_addr = addr = mm->free_area_cache;
+	} else {
+	        start_addr = addr = TASK_UNMAPPED_BASE;
+	        mm->cached_hole_size = 0;
+	}
 
 full_search:
 	vma = find_vma(mm, addr);
@@ -492,6 +321,8 @@
 			mm->free_area_cache = addr + len;
 			return addr;
 		}
+		if (addr + mm->cached_hole_size < vma->vm_start)
+		        mm->cached_hole_size = vma->vm_start - addr;
 		addr = vma->vm_end;
 		vma = vma->vm_next;
 	}
@@ -499,6 +330,7 @@
 	/* Make sure we didn't miss any holes */
 	if (start_addr != TASK_UNMAPPED_BASE) {
 		start_addr = addr = TASK_UNMAPPED_BASE;
+		mm->cached_hole_size = 0;
 		goto full_search;
 	}
 	return -ENOMEM;
@@ -520,6 +352,7 @@
 	struct vm_area_struct *vma, *prev_vma;
 	struct mm_struct *mm = current->mm;
 	unsigned long base = mm->mmap_base, addr = addr0;
+	unsigned long largest_hole = mm->cached_hole_size;
 	int first_time = 1;
 
 	/* requested length too big for entire address space */
@@ -540,6 +373,10 @@
 			return addr;
 	}
 
+	if (len <= largest_hole) {
+	        largest_hole = 0;
+		mm->free_area_cache = base;
+	}
 try_again:
 	/* make sure it can fit in the remaining address space */
 	if (mm->free_area_cache < len)
@@ -568,13 +405,21 @@
 		 * vma->vm_start, use it:
 		 */
 		if (addr+len <= vma->vm_start &&
-				(!prev_vma || (addr >= prev_vma->vm_end)))
+		          (!prev_vma || (addr >= prev_vma->vm_end))) {
 			/* remember the address as a hint for next time */
-			return (mm->free_area_cache = addr);
-		else
+		        mm->cached_hole_size = largest_hole;
+		        return (mm->free_area_cache = addr);
+		} else {
 			/* pull free_area_cache down to the first hole */
-			if (mm->free_area_cache == vma->vm_end)
+		        if (mm->free_area_cache == vma->vm_end) {
 				mm->free_area_cache = vma->vm_start;
+				mm->cached_hole_size = largest_hole;
+			}
+		}
+
+		/* remember the largest hole we saw so far */
+		if (addr + largest_hole < vma->vm_start)
+		        largest_hole = vma->vm_start - addr;
 
 		/* try just below the current vma->vm_start */
 		addr = vma->vm_start-len;
@@ -587,6 +432,7 @@
 	 */
 	if (first_time) {
 		mm->free_area_cache = base;
+		largest_hole = 0;
 		first_time = 0;
 		goto try_again;
 	}
@@ -597,11 +443,13 @@
 	 * allocations.
 	 */
 	mm->free_area_cache = TASK_UNMAPPED_BASE;
+	mm->cached_hole_size = ~0UL;
 	addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
 	/*
 	 * Restore the topdown base:
 	 */
 	mm->free_area_cache = base;
+	mm->cached_hole_size = ~0UL;
 
 	return addr;
 }
diff --git a/arch/ppc64/mm/imalloc.c b/arch/ppc64/mm/imalloc.c
index cb8727f..b6e75b8 100644
--- a/arch/ppc64/mm/imalloc.c
+++ b/arch/ppc64/mm/imalloc.c
@@ -15,6 +15,7 @@
 #include <asm/pgtable.h>
 #include <asm/semaphore.h>
 #include <asm/imalloc.h>
+#include <asm/cacheflush.h>
 
 static DECLARE_MUTEX(imlist_sem);
 struct vm_struct * imlist = NULL;
@@ -285,29 +286,32 @@
 	return area;
 }
 
-unsigned long im_free(void * addr)
+void im_free(void * addr)
 {
 	struct vm_struct **p, *tmp;
-	unsigned long ret_size = 0;
   
 	if (!addr)
-		return ret_size;
-	if ((PAGE_SIZE-1) & (unsigned long) addr) {
+		return;
+	if ((unsigned long) addr & ~PAGE_MASK) {
 		printk(KERN_ERR "Trying to %s bad address (%p)\n", __FUNCTION__,			addr);
-		return ret_size;
+		return;
 	}
 	down(&imlist_sem);
 	for (p = &imlist ; (tmp = *p) ; p = &tmp->next) {
 		if (tmp->addr == addr) {
-			ret_size = tmp->size;
 			*p = tmp->next;
+
+			/* XXX: do we need the lock? */
+			spin_lock(&init_mm.page_table_lock);
+			unmap_vm_area(tmp);
+			spin_unlock(&init_mm.page_table_lock);
+
 			kfree(tmp);
 			up(&imlist_sem);
-			return ret_size;
+			return;
 		}
 	}
 	up(&imlist_sem);
 	printk(KERN_ERR "Trying to %s nonexistent area (%p)\n", __FUNCTION__,
 			addr);
-	return ret_size;
 }
diff --git a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
index 4b42aff..b50b3a4 100644
--- a/arch/ppc64/mm/init.c
+++ b/arch/ppc64/mm/init.c
@@ -73,9 +73,6 @@
 extern pgd_t swapper_pg_dir[];
 extern struct task_struct *current_set[NR_CPUS];
 
-extern pgd_t ioremap_dir[];
-pgd_t * ioremap_pgd = (pgd_t *)&ioremap_dir;
-
 unsigned long klimit = (unsigned long)_end;
 
 unsigned long _SDR1=0;
@@ -101,7 +98,7 @@
 	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
 	for_each_pgdat(pgdat) {
 		for (i = 0; i < pgdat->node_spanned_pages; i++) {
-			page = pgdat->node_mem_map + i;
+			page = pgdat_page_nr(pgdat, i);
 			total++;
 			if (PageReserved(page))
 				reserved++;
@@ -137,69 +134,6 @@
 
 #else
 
-static void unmap_im_area_pte(pmd_t *pmd, unsigned long addr,
-				  unsigned long end)
-{
-	pte_t *pte;
-
-	pte = pte_offset_kernel(pmd, addr);
-	do {
-		pte_t ptent = ptep_get_and_clear(&ioremap_mm, addr, pte);
-		WARN_ON(!pte_none(ptent) && !pte_present(ptent));
-	} while (pte++, addr += PAGE_SIZE, addr != end);
-}
-
-static inline void unmap_im_area_pmd(pud_t *pud, unsigned long addr,
-				     unsigned long end)
-{
-	pmd_t *pmd;
-	unsigned long next;
-
-	pmd = pmd_offset(pud, addr);
-	do {
-		next = pmd_addr_end(addr, end);
-		if (pmd_none_or_clear_bad(pmd))
-			continue;
-		unmap_im_area_pte(pmd, addr, next);
-	} while (pmd++, addr = next, addr != end);
-}
-
-static inline void unmap_im_area_pud(pgd_t *pgd, unsigned long addr,
-				     unsigned long end)
-{
-	pud_t *pud;
-	unsigned long next;
-
-	pud = pud_offset(pgd, addr);
-	do {
-		next = pud_addr_end(addr, end);
-		if (pud_none_or_clear_bad(pud))
-			continue;
-		unmap_im_area_pmd(pud, addr, next);
-	} while (pud++, addr = next, addr != end);
-}
-
-static void unmap_im_area(unsigned long addr, unsigned long end)
-{
-	struct mm_struct *mm = &ioremap_mm;
-	unsigned long next;
-	pgd_t *pgd;
-
-	spin_lock(&mm->page_table_lock);
-
-	pgd = pgd_offset_i(addr);
-	flush_cache_vunmap(addr, end);
-	do {
-		next = pgd_addr_end(addr, end);
-		if (pgd_none_or_clear_bad(pgd))
-			continue;
-		unmap_im_area_pud(pgd, addr, next);
-	} while (pgd++, addr = next, addr != end);
-	flush_tlb_kernel_range(start, end);
-
-	spin_unlock(&mm->page_table_lock);
-}
-
 /*
  * map_io_page currently only called by __ioremap
  * map_io_page adds an entry to the ioremap page table
@@ -214,21 +148,21 @@
 	unsigned long vsid;
 
 	if (mem_init_done) {
-		spin_lock(&ioremap_mm.page_table_lock);
-		pgdp = pgd_offset_i(ea);
-		pudp = pud_alloc(&ioremap_mm, pgdp, ea);
+		spin_lock(&init_mm.page_table_lock);
+		pgdp = pgd_offset_k(ea);
+		pudp = pud_alloc(&init_mm, pgdp, ea);
 		if (!pudp)
 			return -ENOMEM;
-		pmdp = pmd_alloc(&ioremap_mm, pudp, ea);
+		pmdp = pmd_alloc(&init_mm, pudp, ea);
 		if (!pmdp)
 			return -ENOMEM;
-		ptep = pte_alloc_kernel(&ioremap_mm, pmdp, ea);
+		ptep = pte_alloc_kernel(&init_mm, pmdp, ea);
 		if (!ptep)
 			return -ENOMEM;
 		pa = abs_to_phys(pa);
-		set_pte_at(&ioremap_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
+		set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
 							  __pgprot(flags)));
-		spin_unlock(&ioremap_mm.page_table_lock);
+		spin_unlock(&init_mm.page_table_lock);
 	} else {
 		unsigned long va, vpn, hash, hpteg;
 
@@ -267,13 +201,9 @@
 
 	for (i = 0; i < size; i += PAGE_SIZE)
 		if (map_io_page(ea+i, pa+i, flags))
-			goto failure;
+			return NULL;
 
 	return (void __iomem *) (ea + (addr & ~PAGE_MASK));
- failure:
-	if (mem_init_done)
-		unmap_im_area(ea, ea + size);
-	return NULL;
 }
 
 
@@ -381,19 +311,14 @@
  */
 void iounmap(volatile void __iomem *token)
 {
-	unsigned long address, size;
 	void *addr;
 
 	if (!mem_init_done)
 		return;
 	
 	addr = (void *) ((unsigned long __force) token & PAGE_MASK);
-	
-	if ((size = im_free(addr)) == 0)
-		return;
 
-	address = (unsigned long)addr; 
-	unmap_im_area(address, address + size);
+	im_free(addr);
 }
 
 static int iounmap_subset_regions(unsigned long addr, unsigned long size)
@@ -606,7 +531,7 @@
  * Initialize the bootmem system and give it all the memory we
  * have available.
  */
-#ifndef CONFIG_DISCONTIGMEM
+#ifndef CONFIG_NEED_MULTIPLE_NODES
 void __init do_init_bootmem(void)
 {
 	unsigned long i;
@@ -628,12 +553,20 @@
 
 	max_pfn = max_low_pfn;
 
-	/* add all physical memory to the bootmem map. Also find the first */
+	/* Add all physical memory to the bootmem map, mark each area
+	 * present.
+	 */
 	for (i=0; i < lmb.memory.cnt; i++) {
 		unsigned long physbase, size;
+		unsigned long start_pfn, end_pfn;
 
 		physbase = lmb.memory.region[i].physbase;
 		size = lmb.memory.region[i].size;
+
+		start_pfn = physbase >> PAGE_SHIFT;
+		end_pfn = start_pfn + (size >> PAGE_SHIFT);
+		memory_present(0, start_pfn, end_pfn);
+
 		free_bootmem(physbase, size);
 	}
 
@@ -672,7 +605,7 @@
 	free_area_init_node(0, NODE_DATA(0), zones_size,
 			    __pa(PAGE_OFFSET) >> PAGE_SHIFT, zholes_size);
 }
-#endif /* CONFIG_DISCONTIGMEM */
+#endif /* ! CONFIG_NEED_MULTIPLE_NODES */
 
 static struct kcore_list kcore_vmem;
 
@@ -703,7 +636,7 @@
 
 void __init mem_init(void)
 {
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NEED_MULTIPLE_NODES
 	int nid;
 #endif
 	pg_data_t *pgdat;
@@ -714,7 +647,7 @@
 	num_physpages = max_low_pfn;	/* RAM is assumed contiguous */
 	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
 
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NEED_MULTIPLE_NODES
         for_each_online_node(nid) {
 		if (NODE_DATA(nid)->node_spanned_pages != 0) {
 			printk("freeing bootmem node %x\n", nid);
@@ -729,7 +662,7 @@
 
 	for_each_pgdat(pgdat) {
 		for (i = 0; i < pgdat->node_spanned_pages; i++) {
-			page = pgdat->node_mem_map + i;
+			page = pgdat_page_nr(pgdat, i);
 			if (PageReserved(page))
 				reservedpages++;
 		}
diff --git a/arch/ppc64/mm/numa.c b/arch/ppc64/mm/numa.c
index ea862ec..cafd91a 100644
--- a/arch/ppc64/mm/numa.c
+++ b/arch/ppc64/mm/numa.c
@@ -440,6 +440,8 @@
 		for (i = start ; i < (start+size); i += MEMORY_INCREMENT)
 			numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] =
 				numa_domain;
+		memory_present(numa_domain, start >> PAGE_SHIFT,
+						(start + size) >> PAGE_SHIFT);
 
 		if (--ranges)
 			goto new_range;
@@ -481,6 +483,7 @@
 
 	for (i = 0 ; i < top_of_ram; i += MEMORY_INCREMENT)
 		numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = 0;
+	memory_present(0, 0, init_node_data[0].node_end_pfn);
 }
 
 static void __init dump_numa_topology(void)
diff --git a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c
index 3c0ccb2..7f6e13a 100644
--- a/arch/ppc64/xmon/xmon.c
+++ b/arch/ppc64/xmon/xmon.c
@@ -2247,7 +2247,14 @@
 			tmpstr[i] = c;
 		}
 		tmpstr[i++] = 0;
-		*vp = kallsyms_lookup_name(tmpstr);
+		*vp = 0;
+		if (setjmp(bus_error_jmp) == 0) {
+			catch_memory_errors = 1;
+			sync();
+			*vp = kallsyms_lookup_name(tmpstr);
+			sync();
+		}
+		catch_memory_errors = 0;
 		if (!(*vp)) {
 			printf("unknown symbol '%s'\n", tmpstr);
 			return 0;
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index ab79af8..6600ee8 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -226,6 +226,8 @@
 	  This allows you to specify the maximum frame size a function may
 	  have without the compiler complaining about it.
 
+source "mm/Kconfig"
+
 comment "I/O subsystem configuration"
 
 config MACHCHK_WARNING
@@ -453,6 +455,14 @@
 	  The HZ timer is switched off in idle by default. That means the
 	  HZ timer is already disabled at boot time.
 
+config KEXEC
+	bool "kexec system call (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	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 is independent of hardware/microcode support.
+
 endmenu
 
 config PCMCIA
diff --git a/arch/s390/boot/install.sh b/arch/s390/boot/install.sh
index 278a813..d4026f6 100644
--- a/arch/s390/boot/install.sh
+++ b/arch/s390/boot/install.sh
@@ -21,8 +21,8 @@
 
 # User may have a custom install script
 
-if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi
-if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi
+if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi
+if [ -x /sbin/${CROSS_COMPILE}installkernel ]; then exec /sbin/${CROSS_COMPILE}installkernel "$@"; fi
 
 # Default install - same as make zlilo
 
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index 07fd041..89850b2 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -245,6 +245,7 @@
 #
 CONFIG_S390_TAPE_34XX=m
 # CONFIG_VMLOGRDR is not set
+# CONFIG_VMCP is not set
 # CONFIG_MONREADER is not set
 # CONFIG_DCSS_SHM is not set
 
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index b41e0e1..ab1e49d2 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -25,6 +25,16 @@
 
 obj-$(CONFIG_VIRT_TIMER)	+= vtime.o
 
+# Kexec part
+S390_KEXEC_OBJS := machine_kexec.o crash.o
+ifeq ($(CONFIG_ARCH_S390X),y)
+S390_KEXEC_OBJS += relocate_kernel64.o
+else
+S390_KEXEC_OBJS += relocate_kernel.o
+endif
+obj-$(CONFIG_KEXEC) += $(S390_KEXEC_OBJS)
+
+
 #
 # This is just to get the dependencies...
 #
diff --git a/arch/s390/kernel/compat_ioctl.c b/arch/s390/kernel/compat_ioctl.c
index 03d03c6..24a1e9f 100644
--- a/arch/s390/kernel/compat_ioctl.c
+++ b/arch/s390/kernel/compat_ioctl.c
@@ -42,7 +42,6 @@
 #include "../../../fs/compat_ioctl.c"
 
 /* s390 only ioctls */
-#if defined(CONFIG_DASD) || defined(CONFIG_DASD_MODULE)
 COMPATIBLE_IOCTL(DASDAPIVER)
 COMPATIBLE_IOCTL(BIODASDDISABLE)
 COMPATIBLE_IOCTL(BIODASDENABLE)
@@ -59,16 +58,11 @@
 COMPATIBLE_IOCTL(BIODASDPSRD)
 COMPATIBLE_IOCTL(BIODASDGATTR)
 COMPATIBLE_IOCTL(BIODASDSATTR)
-#if defined(CONFIG_DASD_CMB) || defined(CONFIG_DASD_CMB_MODULE)
 COMPATIBLE_IOCTL(BIODASDCMFENABLE)
 COMPATIBLE_IOCTL(BIODASDCMFDISABLE)
 COMPATIBLE_IOCTL(BIODASDREADALLCMB)
-#endif
-#endif
 
-#if defined(CONFIG_S390_TAPE) || defined(CONFIG_S390_TAPE_MODULE)
 COMPATIBLE_IOCTL(TAPE390_DISPLAY)
-#endif
 
 /* s390 doesn't need handlers here */
 COMPATIBLE_IOCTL(TIOCGSERIAL)
diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h
index bf33dcf..3898f66 100644
--- a/arch/s390/kernel/compat_linux.h
+++ b/arch/s390/kernel/compat_linux.h
@@ -45,7 +45,7 @@
 
 		/* POSIX.1b timers */
 		struct {
-			timer_t _tid;		/* timer id */
+			compat_timer_t _tid;		/* timer id */
 			int _overrun;		/* overrun count */
 			compat_sigval_t _sigval;	/* same as below */
 			int _sys_private;       /* not to be passed to user */
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 7a607b1..bf52973 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1441,3 +1441,11 @@
 	lgfr	%r5,%r5			# int
 	llgtr	%r6,%r6			# struct rusage_emu31 *
 	jg	compat_sys_waitid
+
+	.globl	compat_sys_kexec_load_wrapper
+compat_sys_kexec_load_wrapper:
+	llgfr	%r2,%r2			# unsigned long
+	llgfr	%r3,%r3			# unsigned long
+	llgtr	%r4,%r4			# struct kexec_segment *
+	llgfr	%r5,%r5			# unsigned long
+	jg	compat_sys_kexec_load
diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c
index 44df8dc..2006214 100644
--- a/arch/s390/kernel/cpcmd.c
+++ b/arch/s390/kernel/cpcmd.c
@@ -2,7 +2,7 @@
  *  arch/s390/kernel/cpcmd.c
  *
  *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *               Christian Borntraeger (cborntra@de.ibm.com),
  */
@@ -18,93 +18,114 @@
 #include <asm/system.h>
 
 static DEFINE_SPINLOCK(cpcmd_lock);
-static char cpcmd_buf[240];
+static char cpcmd_buf[241];
 
 /*
  * the caller of __cpcmd has to ensure that the response buffer is below 2 GB
  */
-void __cpcmd(char *cmd, char *response, int rlen)
+int  __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
 {
 	const int mask = 0x40000000L;
 	unsigned long flags;
+	int return_code;
+	int return_len;
 	int cmdlen;
 
 	spin_lock_irqsave(&cpcmd_lock, flags);
 	cmdlen = strlen(cmd);
 	BUG_ON(cmdlen > 240);
-	strcpy(cpcmd_buf, cmd);
+	memcpy(cpcmd_buf, cmd, cmdlen);
 	ASCEBC(cpcmd_buf, cmdlen);
 
 	if (response != NULL && rlen > 0) {
 		memset(response, 0, rlen);
 #ifndef CONFIG_ARCH_S390X
-		asm volatile ("LRA   2,0(%0)\n\t"
-                              "LR    4,%1\n\t"
-                              "O     4,%4\n\t"
-                              "LRA   3,0(%2)\n\t"
-                              "LR    5,%3\n\t"
-                              ".long 0x83240008 # Diagnose X'08'\n\t"
-                              : /* no output */
-                              : "a" (cpcmd_buf), "d" (cmdlen),
-                                "a" (response), "d" (rlen), "m" (mask)
-                              : "cc", "2", "3", "4", "5" );
+		asm volatile (	"lra	2,0(%2)\n"
+				"lr	4,%3\n"
+				"o	4,%6\n"
+				"lra	3,0(%4)\n"
+				"lr	5,%5\n"
+				"diag	2,4,0x8\n"
+				"brc	8, .Litfits\n"
+				"ar	5, %5\n"
+				".Litfits: \n"
+				"lr	%0,4\n"
+				"lr	%1,5\n"
+				: "=d" (return_code), "=d" (return_len)
+				: "a" (cpcmd_buf), "d" (cmdlen),
+				"a" (response), "d" (rlen), "m" (mask)
+				: "cc", "2", "3", "4", "5" );
 #else /* CONFIG_ARCH_S390X */
-                asm volatile ("   lrag  2,0(%0)\n"
-                              "   lgr   4,%1\n"
-                              "   o     4,%4\n"
-                              "   lrag  3,0(%2)\n"
-                              "   lgr   5,%3\n"
-                              "   sam31\n"
-                              "   .long 0x83240008 # Diagnose X'08'\n"
-                              "   sam64"
-                              : /* no output */
-                              : "a" (cpcmd_buf), "d" (cmdlen),
-                                "a" (response), "d" (rlen), "m" (mask)
-                              : "cc", "2", "3", "4", "5" );
+                asm volatile (	"lrag	2,0(%2)\n"
+				"lgr	4,%3\n"
+				"o	4,%6\n"
+				"lrag	3,0(%4)\n"
+				"lgr	5,%5\n"
+				"sam31\n"
+				"diag	2,4,0x8\n"
+				"sam64\n"
+				"brc	8, .Litfits\n"
+				"agr	5, %5\n"
+				".Litfits: \n"
+				"lgr	%0,4\n"
+				"lgr	%1,5\n"
+				: "=d" (return_code), "=d" (return_len)
+				: "a" (cpcmd_buf), "d" (cmdlen),
+				"a" (response), "d" (rlen), "m" (mask)
+				: "cc", "2", "3", "4", "5" );
 #endif /* CONFIG_ARCH_S390X */
                 EBCASC(response, rlen);
         } else {
+		return_len = 0;
 #ifndef CONFIG_ARCH_S390X
-                asm volatile ("LRA   2,0(%0)\n\t"
-                              "LR    3,%1\n\t"
-                              ".long 0x83230008 # Diagnose X'08'\n\t"
-                              : /* no output */
-                              : "a" (cpcmd_buf), "d" (cmdlen)
-                              : "2", "3"  );
+                asm volatile (	"lra	2,0(%1)\n"
+				"lr	3,%2\n"
+				"diag	2,3,0x8\n"
+				"lr	%0,3\n"
+				: "=d" (return_code)
+				: "a" (cpcmd_buf), "d" (cmdlen)
+				: "2", "3"  );
 #else /* CONFIG_ARCH_S390X */
-                asm volatile ("   lrag  2,0(%0)\n"
-                              "   lgr   3,%1\n"
-                              "   sam31\n"
-                              "   .long 0x83230008 # Diagnose X'08'\n"
-                              "   sam64"
-                              : /* no output */
-                              : "a" (cpcmd_buf), "d" (cmdlen)
-                              : "2", "3"  );
+                asm volatile (	"lrag	2,0(%1)\n"
+				"lgr	3,%2\n"
+				"sam31\n"
+				"diag	2,3,0x8\n"
+				"sam64\n"
+				"lgr	%0,3\n"
+				: "=d" (return_code)
+				: "a" (cpcmd_buf), "d" (cmdlen)
+				: "2", "3" );
 #endif /* CONFIG_ARCH_S390X */
         }
 	spin_unlock_irqrestore(&cpcmd_lock, flags);
+	if (response_code != NULL)
+		*response_code = return_code;
+	return return_len;
 }
 
 EXPORT_SYMBOL(__cpcmd);
 
 #ifdef CONFIG_ARCH_S390X
-void cpcmd(char *cmd, char *response, int rlen)
+int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
 {
 	char *lowbuf;
+	int len;
+
 	if ((rlen == 0) || (response == NULL)
 	    || !((unsigned long)response >> 31))
-		__cpcmd(cmd, response, rlen);
+		len = __cpcmd(cmd, response, rlen, response_code);
 	else {
 		lowbuf = kmalloc(rlen, GFP_KERNEL | GFP_DMA);
 		if (!lowbuf) {
 			printk(KERN_WARNING
 				"cpcmd: could not allocate response buffer\n");
-			return;
+			return -ENOMEM;
 		}
-		__cpcmd(cmd, lowbuf, rlen);
+		len = __cpcmd(cmd, lowbuf, rlen, response_code);
 		memcpy(response, lowbuf, rlen);
 		kfree(lowbuf);
 	}
+	return len;
 }
 
 EXPORT_SYMBOL(cpcmd);
diff --git a/arch/s390/kernel/crash.c b/arch/s390/kernel/crash.c
new file mode 100644
index 0000000..7bd169c
--- /dev/null
+++ b/arch/s390/kernel/crash.c
@@ -0,0 +1,17 @@
+/*
+ * arch/s390/kernel/crash.c
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
+ *
+ */
+
+#include <linux/threads.h>
+#include <linux/kexec.h>
+
+note_buf_t crash_notes[NR_CPUS];
+
+void machine_crash_shutdown(struct pt_regs *regs)
+{
+}
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index 91f8ce5..960ba60 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -19,22 +19,27 @@
 #include <linux/sysctl.h>
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
-
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/debugfs.h>
 
 #include <asm/debug.h>
 
 #define DEBUG_PROLOG_ENTRY -1
 
+#define ALL_AREAS 0 /* copy all debug areas */
+#define NO_AREAS  1 /* copy no debug areas */
+
 /* typedefs */
 
 typedef struct file_private_info {
 	loff_t offset;			/* offset of last read in file */
 	int    act_area;                /* number of last formated area */
+	int    act_page;                /* act page in given area */
 	int    act_entry;               /* last formated entry (offset */
                                         /* relative to beginning of last */
-                                        /* formated area) */ 
+                                        /* formated page) */
 	size_t act_entry_offset;        /* up to this offset we copied */
 					/* in last read the last formated */
 					/* entry to userland */
@@ -51,8 +56,8 @@
 	 * This assumes that all args are converted into longs 
 	 * on L/390 this is the case for all types of parameter 
 	 * except of floats, and long long (32 bit) 
-         *
-         */
+	 *
+	 */
 	long args[0];
 } debug_sprintf_entry_t;
 
@@ -63,32 +68,38 @@
 
 static int debug_init(void);
 static ssize_t debug_output(struct file *file, char __user *user_buf,
-			    size_t user_len, loff_t * offset);
+			size_t user_len, loff_t * offset);
 static ssize_t debug_input(struct file *file, const char __user *user_buf,
-			   size_t user_len, loff_t * offset);
+			size_t user_len, loff_t * offset);
 static int debug_open(struct inode *inode, struct file *file);
 static int debug_close(struct inode *inode, struct file *file);
-static debug_info_t*  debug_info_create(char *name, int page_order, int nr_areas, int buf_size);
+static debug_info_t*  debug_info_create(char *name, int pages_per_area,
+			int nr_areas, int buf_size);
 static void debug_info_get(debug_info_t *);
 static void debug_info_put(debug_info_t *);
 static int debug_prolog_level_fn(debug_info_t * id,
-				 struct debug_view *view, char *out_buf);
+			struct debug_view *view, char *out_buf);
 static int debug_input_level_fn(debug_info_t * id, struct debug_view *view,
-				struct file *file, const char __user *user_buf,
-				size_t user_buf_size, loff_t * offset);
+			struct file *file, const char __user *user_buf,
+			size_t user_buf_size, loff_t * offset);
+static int debug_prolog_pages_fn(debug_info_t * id,
+			struct debug_view *view, char *out_buf);
+static int debug_input_pages_fn(debug_info_t * id, struct debug_view *view,
+			struct file *file, const char __user *user_buf,
+			size_t user_buf_size, loff_t * offset);
 static int debug_input_flush_fn(debug_info_t * id, struct debug_view *view,
-                                struct file *file, const char __user *user_buf,
-                                size_t user_buf_size, loff_t * offset);
+			struct file *file, const char __user *user_buf,
+			size_t user_buf_size, loff_t * offset);
 static int debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
-                                char *out_buf, const char *in_buf);
+			char *out_buf, const char *in_buf);
 static int debug_raw_format_fn(debug_info_t * id,
-				 struct debug_view *view, char *out_buf,
-				 const char *in_buf);
+			struct debug_view *view, char *out_buf,
+			const char *in_buf);
 static int debug_raw_header_fn(debug_info_t * id, struct debug_view *view,
-                         int area, debug_entry_t * entry, char *out_buf);
+			int area, debug_entry_t * entry, char *out_buf);
 
 static int debug_sprintf_format_fn(debug_info_t * id, struct debug_view *view,
-				   char *out_buf, debug_sprintf_entry_t *curr_event);
+			char *out_buf, debug_sprintf_entry_t *curr_event);
 
 /* globals */
 
@@ -119,6 +130,15 @@
 	NULL
 };
 
+struct debug_view debug_pages_view = {
+	"pages",
+	&debug_prolog_pages_fn,
+	NULL,
+	NULL,
+	&debug_input_pages_fn,
+	NULL
+};
+
 struct debug_view debug_flush_view = {
         "flush",
         NULL,
@@ -149,98 +169,161 @@
 static int initialized;
 
 static struct file_operations debug_file_ops = {
-	.owner	 = THIS_MODULE,
+	.owner   = THIS_MODULE,
 	.read    = debug_output,
-	.write   = debug_input,	
+	.write   = debug_input,
 	.open    = debug_open,
 	.release = debug_close,
 };
 
-static struct proc_dir_entry *debug_proc_root_entry;
+static struct dentry *debug_debugfs_root_entry;
 
 /* functions */
 
 /*
+ * debug_areas_alloc
+ * - Debug areas are implemented as a threedimensonal array:
+ *   areas[areanumber][pagenumber][pageoffset]
+ */
+
+static debug_entry_t***
+debug_areas_alloc(int pages_per_area, int nr_areas)
+{
+	debug_entry_t*** areas;
+	int i,j;
+
+	areas = (debug_entry_t ***) kmalloc(nr_areas *
+					sizeof(debug_entry_t**),
+					GFP_KERNEL);
+	if (!areas)
+		goto fail_malloc_areas;
+	for (i = 0; i < nr_areas; i++) {
+		areas[i] = (debug_entry_t**) kmalloc(pages_per_area *
+				sizeof(debug_entry_t*),GFP_KERNEL);
+		if (!areas[i]) {
+			goto fail_malloc_areas2;
+		}
+		for(j = 0; j < pages_per_area; j++) {
+			areas[i][j] = (debug_entry_t*)kmalloc(PAGE_SIZE,
+						GFP_KERNEL);
+			if(!areas[i][j]) {
+				for(j--; j >=0 ; j--) {
+					kfree(areas[i][j]);
+				}
+				kfree(areas[i]);
+				goto fail_malloc_areas2;
+			} else {
+				memset(areas[i][j],0,PAGE_SIZE);
+			}
+		}
+	}
+	return areas;
+
+fail_malloc_areas2:
+	for(i--; i >= 0; i--){
+		for(j=0; j < pages_per_area;j++){
+			kfree(areas[i][j]);
+		}
+		kfree(areas[i]);
+	}
+	kfree(areas);
+fail_malloc_areas:
+	return NULL;
+
+}
+
+
+/*
  * debug_info_alloc
  * - alloc new debug-info
  */
 
-static debug_info_t*  debug_info_alloc(char *name, int page_order,
-                                        int nr_areas, int buf_size)
+static debug_info_t*
+debug_info_alloc(char *name, int pages_per_area, int nr_areas, int buf_size,
+		int level, int mode)
 {
 	debug_info_t* rc;
-	int i;
 
 	/* alloc everything */
 
-	rc = (debug_info_t*) kmalloc(sizeof(debug_info_t), GFP_ATOMIC);
+	rc = (debug_info_t*) kmalloc(sizeof(debug_info_t), GFP_KERNEL);
 	if(!rc)
 		goto fail_malloc_rc;
-	rc->active_entry = (int*)kmalloc(nr_areas * sizeof(int), GFP_ATOMIC);
-	if(!rc->active_entry)
-		goto fail_malloc_active_entry;
-	memset(rc->active_entry, 0, nr_areas * sizeof(int));
-	rc->areas = (debug_entry_t **) kmalloc(nr_areas *
-						sizeof(debug_entry_t *),
-						GFP_ATOMIC);
-	if (!rc->areas)
-		goto fail_malloc_areas;
-	for (i = 0; i < nr_areas; i++) {
-		rc->areas[i] = (debug_entry_t *) __get_free_pages(GFP_ATOMIC,
-								page_order);
-		if (!rc->areas[i]) {
-			for (i--; i >= 0; i--) {
-				free_pages((unsigned long) rc->areas[i],
-						page_order);
-			}
-			goto fail_malloc_areas2;
-		} else {
-			memset(rc->areas[i], 0, PAGE_SIZE << page_order);
-		}
+	rc->active_entries = (int*)kmalloc(nr_areas * sizeof(int), GFP_KERNEL);
+	if(!rc->active_entries)
+		goto fail_malloc_active_entries;
+	memset(rc->active_entries, 0, nr_areas * sizeof(int));
+	rc->active_pages = (int*)kmalloc(nr_areas * sizeof(int), GFP_KERNEL);
+	if(!rc->active_pages)
+		goto fail_malloc_active_pages;
+	memset(rc->active_pages, 0, nr_areas * sizeof(int));
+	if((mode == ALL_AREAS) && (pages_per_area != 0)){
+		rc->areas = debug_areas_alloc(pages_per_area, nr_areas);
+		if(!rc->areas)
+			goto fail_malloc_areas;
+	} else {
+		rc->areas = NULL;
 	}
 
 	/* initialize members */
 
 	spin_lock_init(&rc->lock);
-	rc->page_order  = page_order;
-	rc->nr_areas    = nr_areas;
-	rc->active_area = 0;
-	rc->level       = DEBUG_DEFAULT_LEVEL;
-	rc->buf_size    = buf_size;
-	rc->entry_size  = sizeof(debug_entry_t) + buf_size;
-	strlcpy(rc->name, name, sizeof(rc->name));
+	rc->pages_per_area = pages_per_area;
+	rc->nr_areas       = nr_areas;
+	rc->active_area    = 0;
+	rc->level          = level;
+	rc->buf_size       = buf_size;
+	rc->entry_size     = sizeof(debug_entry_t) + buf_size;
+	strlcpy(rc->name, name, sizeof(rc->name)-1);
 	memset(rc->views, 0, DEBUG_MAX_VIEWS * sizeof(struct debug_view *));
-#ifdef CONFIG_PROC_FS
-	memset(rc->proc_entries, 0 ,DEBUG_MAX_VIEWS *
-		sizeof(struct proc_dir_entry*));
-#endif /* CONFIG_PROC_FS */
+	memset(rc->debugfs_entries, 0 ,DEBUG_MAX_VIEWS *
+		sizeof(struct dentry*));
 	atomic_set(&(rc->ref_count), 0);
 
 	return rc;
 
-fail_malloc_areas2:
-	kfree(rc->areas);
 fail_malloc_areas:
-	kfree(rc->active_entry);
-fail_malloc_active_entry:
+	kfree(rc->active_pages);
+fail_malloc_active_pages:
+	kfree(rc->active_entries);
+fail_malloc_active_entries:
 	kfree(rc);
 fail_malloc_rc:
 	return NULL;
 }
 
 /*
+ * debug_areas_free
+ * - free all debug areas
+ */
+
+static void
+debug_areas_free(debug_info_t* db_info)
+{
+	int i,j;
+
+	if(!db_info->areas)
+		return;
+	for (i = 0; i < db_info->nr_areas; i++) {
+		for(j = 0; j < db_info->pages_per_area; j++) {
+			kfree(db_info->areas[i][j]);
+		}
+		kfree(db_info->areas[i]);
+	}
+	kfree(db_info->areas);
+	db_info->areas = NULL;
+}
+
+/*
  * debug_info_free
  * - free memory debug-info
  */
 
-static void debug_info_free(debug_info_t* db_info){
-	int i;
-	for (i = 0; i < db_info->nr_areas; i++) {
-		free_pages((unsigned long) db_info->areas[i],
-		db_info->page_order);
-	}
-	kfree(db_info->areas);
-	kfree(db_info->active_entry);
+static void
+debug_info_free(debug_info_t* db_info){
+	debug_areas_free(db_info);
+	kfree(db_info->active_entries);
+	kfree(db_info->active_pages);
 	kfree(db_info);
 }
 
@@ -249,21 +332,22 @@
  * - create new debug-info
  */
 
-static debug_info_t*  debug_info_create(char *name, int page_order, 
-                                        int nr_areas, int buf_size)
+static debug_info_t*
+debug_info_create(char *name, int pages_per_area, int nr_areas, int buf_size)
 {
 	debug_info_t* rc;
 
-        rc = debug_info_alloc(name, page_order, nr_areas, buf_size);
+        rc = debug_info_alloc(name, pages_per_area, nr_areas, buf_size,
+				DEBUG_DEFAULT_LEVEL, ALL_AREAS);
         if(!rc) 
 		goto out;
 
-
-	/* create proc rood directory */
-        rc->proc_root_entry = proc_mkdir(rc->name, debug_proc_root_entry);
+	/* create root directory */
+        rc->debugfs_root_entry = debugfs_create_dir(rc->name,
+					debug_debugfs_root_entry);
 
 	/* append new element to linked list */
-        if (debug_area_first == NULL) {
+        if (!debug_area_first) {
                 /* first element in list */
                 debug_area_first = rc;
                 rc->prev = NULL;
@@ -285,17 +369,21 @@
  * - copy debug-info
  */
 
-static debug_info_t* debug_info_copy(debug_info_t* in)
+static debug_info_t*
+debug_info_copy(debug_info_t* in, int mode)
 {
-        int i;
+        int i,j;
         debug_info_t* rc;
-        rc = debug_info_alloc(in->name, in->page_order, 
-                                in->nr_areas, in->buf_size);
-        if(!rc)
+
+        rc = debug_info_alloc(in->name, in->pages_per_area, in->nr_areas,
+				in->buf_size, in->level, mode);
+        if(!rc || (mode == NO_AREAS))
                 goto out;
 
         for(i = 0; i < in->nr_areas; i++){
-                memcpy(rc->areas[i],in->areas[i], PAGE_SIZE << in->page_order);
+		for(j = 0; j < in->pages_per_area; j++) {
+			memcpy(rc->areas[i][j], in->areas[i][j],PAGE_SIZE);
+		}
         }
 out:
         return rc;
@@ -306,7 +394,8 @@
  * - increments reference count for debug-info
  */
 
-static void debug_info_get(debug_info_t * db_info)
+static void
+debug_info_get(debug_info_t * db_info)
 {
 	if (db_info)
 		atomic_inc(&db_info->ref_count);
@@ -317,29 +406,20 @@
  * - decreases reference count for debug-info and frees it if necessary
  */
 
-static void debug_info_put(debug_info_t *db_info)
+static void
+debug_info_put(debug_info_t *db_info)
 {
 	int i;
 
 	if (!db_info)
 		return;
 	if (atomic_dec_and_test(&db_info->ref_count)) {
-#ifdef DEBUG
-		printk(KERN_INFO "debug: freeing debug area %p (%s)\n",
-		       db_info, db_info->name);
-#endif
 		for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
-			if (db_info->views[i] == NULL)
+			if (!db_info->views[i])
 				continue;
-#ifdef CONFIG_PROC_FS
-			remove_proc_entry(db_info->proc_entries[i]->name,
-					  db_info->proc_root_entry);
-#endif
+			debugfs_remove(db_info->debugfs_entries[i]);
 		}
-#ifdef CONFIG_PROC_FS
-		remove_proc_entry(db_info->proc_root_entry->name,
-				  debug_proc_root_entry);
-#endif
+		debugfs_remove(db_info->debugfs_root_entry);
 		if(db_info == debug_area_first)
 			debug_area_first = db_info->next;
 		if(db_info == debug_area_last)
@@ -355,9 +435,9 @@
  * - format one debug entry and return size of formated data
  */
 
-static int debug_format_entry(file_private_info_t *p_info)
+static int
+debug_format_entry(file_private_info_t *p_info)
 {
-	debug_info_t *id_org    = p_info->debug_info_org;
 	debug_info_t *id_snap   = p_info->debug_info_snap;
 	struct debug_view *view = p_info->view;
 	debug_entry_t *act_entry;
@@ -365,22 +445,23 @@
 	if(p_info->act_entry == DEBUG_PROLOG_ENTRY){
 		/* print prolog */
         	if (view->prolog_proc)
-                	len += view->prolog_proc(id_org, view,p_info->temp_buf);
+                	len += view->prolog_proc(id_snap,view,p_info->temp_buf);
 		goto out;
 	}
-
-	act_entry = (debug_entry_t *) ((char*)id_snap->areas[p_info->act_area] +
-					p_info->act_entry);
+	if (!id_snap->areas) /* this is true, if we have a prolog only view */
+		goto out;    /* or if 'pages_per_area' is 0 */
+	act_entry = (debug_entry_t *) ((char*)id_snap->areas[p_info->act_area]
+				[p_info->act_page] + p_info->act_entry);
                         
 	if (act_entry->id.stck == 0LL)
 			goto out;  /* empty entry */
 	if (view->header_proc)
-		len += view->header_proc(id_org, view, p_info->act_area, 
+		len += view->header_proc(id_snap, view, p_info->act_area,
 					act_entry, p_info->temp_buf + len);
 	if (view->format_proc)
-		len += view->format_proc(id_org, view, p_info->temp_buf + len,
+		len += view->format_proc(id_snap, view, p_info->temp_buf + len,
 						DEBUG_DATA(act_entry));
-      out:
+out:
         return len;
 }
 
@@ -389,20 +470,30 @@
  * - goto next entry in p_info
  */
 
-extern inline int debug_next_entry(file_private_info_t *p_info)
+extern inline int
+debug_next_entry(file_private_info_t *p_info)
 {
-	debug_info_t *id = p_info->debug_info_snap;
+	debug_info_t *id;
+
+	id = p_info->debug_info_snap;
 	if(p_info->act_entry == DEBUG_PROLOG_ENTRY){
 		p_info->act_entry = 0;
+		p_info->act_page  = 0;
 		goto out;
 	}
-	if ((p_info->act_entry += id->entry_size)
-		> ((PAGE_SIZE << (id->page_order)) 
-		- id->entry_size)){
-
-		/* next area */
+	if(!id->areas)
+		return 1;
+	p_info->act_entry += id->entry_size;
+	/* switch to next page, if we reached the end of the page  */
+	if (p_info->act_entry > (PAGE_SIZE - id->entry_size)){
+		/* next page */
 		p_info->act_entry = 0;
-        	p_info->act_area++;
+		p_info->act_page += 1;
+		if((p_info->act_page % id->pages_per_area) == 0) {
+			/* next area */
+        		p_info->act_area++;
+			p_info->act_page=0;
+		}
         	if(p_info->act_area >= id->nr_areas)
 			return 1;
 	}
@@ -416,13 +507,14 @@
  * - copies formated debug entries to the user buffer
  */
 
-static ssize_t debug_output(struct file *file,		/* file descriptor */
-			    char __user *user_buf,	/* user buffer */
-			    size_t  len,		/* length of buffer */
-			    loff_t *offset)	      /* offset in the file */
+static ssize_t
+debug_output(struct file *file,		/* file descriptor */
+	    char __user *user_buf,	/* user buffer */
+	    size_t  len,		/* length of buffer */
+	    loff_t *offset)		/* offset in the file */
 {
 	size_t count = 0;
-	size_t entry_offset, size = 0;
+	size_t entry_offset;
 	file_private_info_t *p_info;
 
 	p_info = ((file_private_info_t *) file->private_data);
@@ -430,27 +522,33 @@
 		return -EPIPE;
 	if(p_info->act_area >= p_info->debug_info_snap->nr_areas)
 		return 0;
-
 	entry_offset = p_info->act_entry_offset;
-
 	while(count < len){
-		size = debug_format_entry(p_info);
-		size = min((len - count), (size - entry_offset));
+		int formatted_line_size;
+		int formatted_line_residue;
+		int user_buf_residue;
+		size_t copy_size;
 
-		if(size){
-			if (copy_to_user(user_buf + count, 
-					p_info->temp_buf + entry_offset, size))
-			return -EFAULT;
+		formatted_line_size = debug_format_entry(p_info);
+		formatted_line_residue = formatted_line_size - entry_offset;
+		user_buf_residue = len-count;
+		copy_size = min(user_buf_residue, formatted_line_residue);
+		if(copy_size){
+			if (copy_to_user(user_buf + count, p_info->temp_buf
+					+ entry_offset, copy_size))
+				return -EFAULT;
+			count += copy_size;
+			entry_offset += copy_size;
 		}
-		count += size;
-		entry_offset = 0;
-		if(count != len)
-			if(debug_next_entry(p_info)) 
+		if(copy_size == formatted_line_residue){
+			entry_offset = 0;
+			if(debug_next_entry(p_info))
 				goto out;
+		}
 	}
 out:
 	p_info->offset           = *offset + count;
-	p_info->act_entry_offset = size;	
+	p_info->act_entry_offset = entry_offset;
 	*offset = p_info->offset;
 	return count;
 }
@@ -461,9 +559,9 @@
  * - calls input function of view
  */
 
-static ssize_t debug_input(struct file *file,
-			   const char __user *user_buf, size_t length,
-			   loff_t *offset)
+static ssize_t
+debug_input(struct file *file, const char __user *user_buf, size_t length,
+		loff_t *offset)
 {
 	int rc = 0;
 	file_private_info_t *p_info;
@@ -487,26 +585,23 @@
  *   handle
  */
 
-static int debug_open(struct inode *inode, struct file *file)
+static int
+debug_open(struct inode *inode, struct file *file)
 {
 	int i = 0, rc = 0;
 	file_private_info_t *p_info;
 	debug_info_t *debug_info, *debug_info_snapshot;
 
-#ifdef DEBUG
-	printk("debug_open\n");
-#endif
 	down(&debug_lock);
 
 	/* find debug log and view */
-
 	debug_info = debug_area_first;
 	while(debug_info != NULL){
 		for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
-			if (debug_info->views[i] == NULL)
+			if (!debug_info->views[i])
 				continue;
-			else if (debug_info->proc_entries[i] ==
-				 PDE(file->f_dentry->d_inode)) {
+			else if (debug_info->debugfs_entries[i] ==
+				 file->f_dentry) {
 				goto found;	/* found view ! */
 			}
 		}
@@ -516,41 +611,42 @@
 	rc = -EINVAL;
 	goto out;
 
-      found:
+found:
 
-	/* make snapshot of current debug areas to get it consistent */
+	/* Make snapshot of current debug areas to get it consistent.     */
+	/* To copy all the areas is only needed, if we have a view which  */
+	/* formats the debug areas. */
 
-	debug_info_snapshot = debug_info_copy(debug_info);
+	if(!debug_info->views[i]->format_proc &&
+		!debug_info->views[i]->header_proc){
+		debug_info_snapshot = debug_info_copy(debug_info, NO_AREAS);
+	} else {
+		debug_info_snapshot = debug_info_copy(debug_info, ALL_AREAS);
+	}
 
 	if(!debug_info_snapshot){
-#ifdef DEBUG
-		printk(KERN_ERR "debug_open: debug_info_copy failed (out of mem)\n");
-#endif
 		rc = -ENOMEM;
 		goto out;
 	}
-
-	if ((file->private_data =
-	     kmalloc(sizeof(file_private_info_t), GFP_ATOMIC)) == 0) {
-#ifdef DEBUG
-		printk(KERN_ERR "debug_open: kmalloc failed\n");
-#endif
-		debug_info_free(debug_info_snapshot);	
+	p_info = (file_private_info_t *) kmalloc(sizeof(file_private_info_t),
+						GFP_KERNEL);
+	if(!p_info){
+		if(debug_info_snapshot)
+			debug_info_free(debug_info_snapshot);
 		rc = -ENOMEM;
 		goto out;
 	}
-	p_info = (file_private_info_t *) file->private_data;
 	p_info->offset = 0;
 	p_info->debug_info_snap = debug_info_snapshot;
 	p_info->debug_info_org  = debug_info;
 	p_info->view = debug_info->views[i];
 	p_info->act_area = 0;
+	p_info->act_page = 0;
 	p_info->act_entry = DEBUG_PROLOG_ENTRY;
 	p_info->act_entry_offset = 0;
-
+	file->private_data = p_info;
 	debug_info_get(debug_info);
-
-      out:
+out:
 	up(&debug_lock);
 	return rc;
 }
@@ -561,14 +657,13 @@
  * - deletes  private_data area of the file handle
  */
 
-static int debug_close(struct inode *inode, struct file *file)
+static int
+debug_close(struct inode *inode, struct file *file)
 {
 	file_private_info_t *p_info;
-#ifdef DEBUG
-	printk("debug_close\n");
-#endif
 	p_info = (file_private_info_t *) file->private_data;
-	debug_info_free(p_info->debug_info_snap);
+	if(p_info->debug_info_snap)
+		debug_info_free(p_info->debug_info_snap);
 	debug_info_put(p_info->debug_info_org);
 	kfree(file->private_data);
 	return 0;		/* success */
@@ -580,8 +675,8 @@
  * - returns handle for debug area
  */
 
-debug_info_t *debug_register
-    (char *name, int page_order, int nr_areas, int buf_size) 
+debug_info_t*
+debug_register (char *name, int pages_per_area, int nr_areas, int buf_size)
 {
 	debug_info_t *rc = NULL;
 
@@ -591,18 +686,14 @@
 
         /* create new debug_info */
 
-	rc = debug_info_create(name, page_order, nr_areas, buf_size);
+	rc = debug_info_create(name, pages_per_area, nr_areas, buf_size);
 	if(!rc) 
 		goto out;
 	debug_register_view(rc, &debug_level_view);
         debug_register_view(rc, &debug_flush_view);
-#ifdef DEBUG
-	printk(KERN_INFO
-	       "debug: reserved %d areas of %d pages for debugging %s\n",
-	       nr_areas, 1 << page_order, rc->name);
-#endif
-      out:
-        if (rc == NULL){
+	debug_register_view(rc, &debug_pages_view);
+out:
+        if (!rc){
 		printk(KERN_ERR "debug: debug_register failed for %s\n",name);
         }
 	up(&debug_lock);
@@ -614,27 +705,65 @@
  * - give back debug area
  */
 
-void debug_unregister(debug_info_t * id)
+void
+debug_unregister(debug_info_t * id)
 {
 	if (!id)
 		goto out;
 	down(&debug_lock);
-#ifdef DEBUG
-	printk(KERN_INFO "debug: unregistering %s\n", id->name);
-#endif
 	debug_info_put(id);
 	up(&debug_lock);
 
-      out:
+out:
 	return;
 }
 
 /*
+ * debug_set_size:
+ * - set area size (number of pages) and number of areas
+ */
+static int
+debug_set_size(debug_info_t* id, int nr_areas, int pages_per_area)
+{
+	unsigned long flags;
+	debug_entry_t *** new_areas;
+	int rc=0;
+
+	if(!id || (nr_areas <= 0) || (pages_per_area < 0))
+		return -EINVAL;
+	if(pages_per_area > 0){
+		new_areas = debug_areas_alloc(pages_per_area, nr_areas);
+		if(!new_areas) {
+			printk(KERN_WARNING "debug: could not allocate memory "\
+					 "for pagenumber: %i\n",pages_per_area);
+			rc = -ENOMEM;
+			goto out;
+		}
+	} else {
+		new_areas = NULL;
+	}
+	spin_lock_irqsave(&id->lock,flags);
+	debug_areas_free(id);
+	id->areas = new_areas;
+	id->nr_areas = nr_areas;
+	id->pages_per_area = pages_per_area;
+	id->active_area = 0;
+	memset(id->active_entries,0,sizeof(int)*id->nr_areas);
+	memset(id->active_pages, 0, sizeof(int)*id->nr_areas);
+	spin_unlock_irqrestore(&id->lock,flags);
+	printk(KERN_INFO "debug: %s: set new size (%i pages)\n"\
+			 ,id->name, pages_per_area);
+out:
+	return rc;
+}
+
+/*
  * debug_set_level:
  * - set actual debug level
  */
 
-void debug_set_level(debug_info_t* id, int new_level)
+void
+debug_set_level(debug_info_t* id, int new_level)
 {
 	unsigned long flags;
 	if(!id)
@@ -649,10 +778,6 @@
                         id->name, new_level, 0, DEBUG_MAX_LEVEL);
         } else {
                 id->level = new_level;
-#ifdef DEBUG
-                printk(KERN_INFO 
-			"debug: %s: new level %i\n",id->name,id->level);
-#endif
         }
 	spin_unlock_irqrestore(&id->lock,flags);
 }
@@ -663,11 +788,16 @@
  * - set active entry to next in the ring buffer
  */
 
-extern inline void proceed_active_entry(debug_info_t * id)
+extern inline void
+proceed_active_entry(debug_info_t * id)
 {
-	if ((id->active_entry[id->active_area] += id->entry_size)
-	    > ((PAGE_SIZE << (id->page_order)) - id->entry_size))
-		id->active_entry[id->active_area] = 0;
+	if ((id->active_entries[id->active_area] += id->entry_size)
+	    > (PAGE_SIZE - id->entry_size)){
+		id->active_entries[id->active_area] = 0;
+		id->active_pages[id->active_area] =
+			(id->active_pages[id->active_area] + 1) %
+			id->pages_per_area;
+	}
 }
 
 /*
@@ -675,7 +805,8 @@
  * - set active area to next in the ring buffer
  */
 
-extern inline void proceed_active_area(debug_info_t * id)
+extern inline void
+proceed_active_area(debug_info_t * id)
 {
 	id->active_area++;
 	id->active_area = id->active_area % id->nr_areas;
@@ -685,10 +816,12 @@
  * get_active_entry:
  */
 
-extern inline debug_entry_t *get_active_entry(debug_info_t * id)
+extern inline debug_entry_t*
+get_active_entry(debug_info_t * id)
 {
-	return (debug_entry_t *) ((char *) id->areas[id->active_area] +
-				  id->active_entry[id->active_area]);
+	return (debug_entry_t *) (((char *) id->areas[id->active_area]
+					[id->active_pages[id->active_area]]) +
+					id->active_entries[id->active_area]);
 }
 
 /*
@@ -696,8 +829,9 @@
  * - set timestamp, caller address, cpu number etc.
  */
 
-extern inline void debug_finish_entry(debug_info_t * id, debug_entry_t* active,
-		int level, int exception)
+extern inline void
+debug_finish_entry(debug_info_t * id, debug_entry_t* active, int level,
+			int exception)
 {
 	STCK(active->id.stck);
 	active->id.fields.cpuid = smp_processor_id();
@@ -721,7 +855,8 @@
  * always allow read, allow write only if debug_stoppable is set or
  * if debug_active is already off
  */
-static int s390dbf_procactive(ctl_table *table, int write, struct file *filp,
+static int
+s390dbf_procactive(ctl_table *table, int write, struct file *filp,
                      void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	if (!write || debug_stoppable || !debug_active)
@@ -766,7 +901,8 @@
 
 struct ctl_table_header *s390dbf_sysctl_header;
 
-void debug_stop_all(void)
+void
+debug_stop_all(void)
 {
 	if (debug_stoppable)
 		debug_active = 0;
@@ -778,13 +914,13 @@
  * - write debug entry with given size
  */
 
-debug_entry_t *debug_event_common(debug_info_t * id, int level, const void *buf,
-			          int len)
+debug_entry_t*
+debug_event_common(debug_info_t * id, int level, const void *buf, int len)
 {
 	unsigned long flags;
 	debug_entry_t *active;
 
-	if (!debug_active)
+	if (!debug_active || !id->areas)
 		return NULL;
 	spin_lock_irqsave(&id->lock, flags);
 	active = get_active_entry(id);
@@ -801,13 +937,13 @@
  * - write debug entry with given size and switch to next debug area
  */
 
-debug_entry_t *debug_exception_common(debug_info_t * id, int level, 
-                                      const void *buf, int len)
+debug_entry_t
+*debug_exception_common(debug_info_t * id, int level, const void *buf, int len)
 {
 	unsigned long flags;
 	debug_entry_t *active;
 
-	if (!debug_active)
+	if (!debug_active || !id->areas)
 		return NULL;
 	spin_lock_irqsave(&id->lock, flags);
 	active = get_active_entry(id);
@@ -823,7 +959,8 @@
  * counts arguments in format string for sprintf view
  */
 
-extern inline int debug_count_numargs(char *string)
+extern inline int
+debug_count_numargs(char *string)
 {
 	int numargs=0;
 
@@ -838,8 +975,8 @@
  * debug_sprintf_event:
  */
 
-debug_entry_t *debug_sprintf_event(debug_info_t* id,
-                                   int level,char *string,...)
+debug_entry_t*
+debug_sprintf_event(debug_info_t* id, int level,char *string,...)
 {
 	va_list   ap;
 	int numargs,idx;
@@ -849,7 +986,7 @@
 
 	if((!id) || (level > id->level))
 		return NULL;
-	if (!debug_active)
+	if (!debug_active || !id->areas)
 		return NULL;
 	numargs=debug_count_numargs(string);
 
@@ -871,8 +1008,8 @@
  * debug_sprintf_exception:
  */
 
-debug_entry_t *debug_sprintf_exception(debug_info_t* id,
-                                       int level,char *string,...)
+debug_entry_t*
+debug_sprintf_exception(debug_info_t* id, int level,char *string,...)
 {
 	va_list   ap;
 	int numargs,idx;
@@ -882,7 +1019,7 @@
 
 	if((!id) || (level > id->level))
 		return NULL;
-	if (!debug_active)
+	if (!debug_active || !id->areas)
 		return NULL;
 
 	numargs=debug_count_numargs(string);
@@ -906,15 +1043,14 @@
  * - is called exactly once to initialize the debug feature
  */
 
-static int __init debug_init(void)
+static int
+__init debug_init(void)
 {
 	int rc = 0;
 
 	s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table, 1);
 	down(&debug_lock);
-#ifdef CONFIG_PROC_FS
-	debug_proc_root_entry = proc_mkdir(DEBUG_DIR_ROOT, NULL);
-#endif /* CONFIG_PROC_FS */
+	debug_debugfs_root_entry = debugfs_create_dir(DEBUG_DIR_ROOT,NULL);
 	printk(KERN_INFO "debug: Initialization complete\n");
 	initialized = 1;
 	up(&debug_lock);
@@ -926,13 +1062,14 @@
  * debug_register_view:
  */
 
-int debug_register_view(debug_info_t * id, struct debug_view *view)
+int
+debug_register_view(debug_info_t * id, struct debug_view *view)
 {
 	int rc = 0;
 	int i;
 	unsigned long flags;
 	mode_t mode = S_IFREG;
-	struct proc_dir_entry *pde;
+	struct dentry *pde;
 
 	if (!id)
 		goto out;
@@ -940,16 +1077,17 @@
 		mode |= S_IRUSR;
 	if (view->input_proc)
 		mode |= S_IWUSR;
-	pde = create_proc_entry(view->name, mode, id->proc_root_entry);
+	pde = debugfs_create_file(view->name, mode, id->debugfs_root_entry,
+				NULL, &debug_file_ops);
 	if (!pde){
-		printk(KERN_WARNING "debug: create_proc_entry() failed! Cannot register view %s/%s\n", id->name,view->name);
+		printk(KERN_WARNING "debug: debugfs_create_file() failed!"\
+			" Cannot register view %s/%s\n", id->name,view->name);
 		rc = -1;
 		goto out;
 	}
-
 	spin_lock_irqsave(&id->lock, flags);
 	for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
-		if (id->views[i] == NULL)
+		if (!id->views[i])
 			break;
 	}
 	if (i == DEBUG_MAX_VIEWS) {
@@ -957,16 +1095,14 @@
 			id->name,view->name);
 		printk(KERN_WARNING 
 			"debug: maximum number of views reached (%i)!\n", i);
-		remove_proc_entry(pde->name, id->proc_root_entry);
+		debugfs_remove(pde);
 		rc = -1;
-	}
-	else {
+	} else {
 		id->views[i] = view;
-		pde->proc_fops = &debug_file_ops;
-		id->proc_entries[i] = pde;
+		id->debugfs_entries[i] = pde;
 	}
 	spin_unlock_irqrestore(&id->lock, flags);
-      out:
+out:
 	return rc;
 }
 
@@ -974,7 +1110,8 @@
  * debug_unregister_view:
  */
 
-int debug_unregister_view(debug_info_t * id, struct debug_view *view)
+int
+debug_unregister_view(debug_info_t * id, struct debug_view *view)
 {
 	int rc = 0;
 	int i;
@@ -990,15 +1127,46 @@
 	if (i == DEBUG_MAX_VIEWS)
 		rc = -1;
 	else {
-#ifdef CONFIG_PROC_FS
-		remove_proc_entry(id->proc_entries[i]->name,
-				  id->proc_root_entry);
-#endif
+		debugfs_remove(id->debugfs_entries[i]);
 		id->views[i] = NULL;
 		rc = 0;
 	}
 	spin_unlock_irqrestore(&id->lock, flags);
-      out:
+out:
+	return rc;
+}
+
+static inline char *
+debug_get_user_string(const char __user *user_buf, size_t user_len)
+{
+	char* buffer;
+
+	buffer = kmalloc(user_len + 1, GFP_KERNEL);
+	if (!buffer)
+		return ERR_PTR(-ENOMEM);
+	if (copy_from_user(buffer, user_buf, user_len) != 0) {
+		kfree(buffer);
+		return ERR_PTR(-EFAULT);
+	}
+	/* got the string, now strip linefeed. */
+	if (buffer[user_len - 1] == '\n')
+		buffer[user_len - 1] = 0;
+	else
+		buffer[user_len] = 0;
+        return buffer;
+}
+
+static inline int
+debug_get_uint(char *buf)
+{
+	int rc;
+
+	for(; isspace(*buf); buf++);
+	rc = simple_strtoul(buf, &buf, 10);
+	if(*buf){
+		printk("debug: no integer specified!\n");
+		rc = -EINVAL;
+	}
 	return rc;
 }
 
@@ -1011,13 +1179,69 @@
  * prints out actual debug level
  */
 
-static int debug_prolog_level_fn(debug_info_t * id,
+static int
+debug_prolog_pages_fn(debug_info_t * id,
 				 struct debug_view *view, char *out_buf)
 {
+	return sprintf(out_buf, "%i\n", id->pages_per_area);
+}
+
+/*
+ * reads new size (number of pages per debug area)
+ */
+
+static int
+debug_input_pages_fn(debug_info_t * id, struct debug_view *view,
+			struct file *file, const char __user *user_buf,
+			size_t user_len, loff_t * offset)
+{
+	char *str;
+	int rc,new_pages;
+
+	if (user_len > 0x10000)
+                user_len = 0x10000;
+	if (*offset != 0){
+		rc = -EPIPE;
+		goto out;
+	}
+	str = debug_get_user_string(user_buf,user_len);
+	if(IS_ERR(str)){
+		rc = PTR_ERR(str);
+		goto out;
+	}
+	new_pages = debug_get_uint(str);
+	if(new_pages < 0){
+		rc = -EINVAL;
+		goto free_str;
+	}
+	rc = debug_set_size(id,id->nr_areas, new_pages);
+	if(rc != 0){
+		rc = -EINVAL;
+		goto free_str;
+	}
+	rc = user_len;
+free_str:
+	kfree(str);
+out:
+	*offset += user_len;
+	return rc;		/* number of input characters */
+}
+
+/*
+ * prints out actual debug level
+ */
+
+static int
+debug_prolog_level_fn(debug_info_t * id, struct debug_view *view, char *out_buf)
+{
 	int rc = 0;
 
-	if(id->level == -1) rc = sprintf(out_buf,"-\n");
-	else rc = sprintf(out_buf, "%i\n", id->level);
+	if(id->level == DEBUG_OFF_LEVEL) {
+		rc = sprintf(out_buf,"-\n");
+	}
+	else {
+		rc = sprintf(out_buf, "%i\n", id->level);
+	}
 	return rc;
 }
 
@@ -1025,30 +1249,43 @@
  * reads new debug level
  */
 
-static int debug_input_level_fn(debug_info_t * id, struct debug_view *view,
-				struct file *file, const char __user *user_buf,
-				size_t in_buf_size, loff_t * offset)
+static int
+debug_input_level_fn(debug_info_t * id, struct debug_view *view,
+			struct file *file, const char __user *user_buf,
+			size_t user_len, loff_t * offset)
 {
-	char input_buf[1];
-	int rc = in_buf_size;
+	char *str;
+	int rc,new_level;
 
-	if (*offset != 0)
-		goto out;
-	if (copy_from_user(input_buf, user_buf, 1)){
-		rc = -EFAULT;
+	if (user_len > 0x10000)
+                user_len = 0x10000;
+	if (*offset != 0){
+		rc = -EPIPE;
 		goto out;
 	}
-	if (isdigit(input_buf[0])) {
-		int new_level = ((int) input_buf[0] - (int) '0');
-		debug_set_level(id, new_level);
-	} else if(input_buf[0] == '-') {
+	str = debug_get_user_string(user_buf,user_len);
+	if(IS_ERR(str)){
+		rc = PTR_ERR(str);
+		goto out;
+	}
+	if(str[0] == '-'){
 		debug_set_level(id, DEBUG_OFF_LEVEL);
+		rc = user_len;
+		goto free_str;
 	} else {
-		printk(KERN_INFO "debug: level `%c` is not valid\n",
-		       input_buf[0]);
+		new_level = debug_get_uint(str);
 	}
-      out:
-	*offset += in_buf_size;
+	if(new_level < 0) {
+		printk(KERN_INFO "debug: level `%s` is not valid\n", str);
+		rc = -EINVAL;
+	} else {
+		debug_set_level(id, new_level);
+		rc = user_len;
+	}
+free_str:
+	kfree(str);
+out:
+	*offset += user_len;
 	return rc;		/* number of input characters */
 }
 
@@ -1057,29 +1294,36 @@
  * flushes debug areas
  */
  
-void debug_flush(debug_info_t* id, int area)
+void
+debug_flush(debug_info_t* id, int area)
 {
         unsigned long flags;
-        int i;
+        int i,j;
 
-        if(!id)
+        if(!id || !id->areas)
                 return;
         spin_lock_irqsave(&id->lock,flags);
         if(area == DEBUG_FLUSH_ALL){
                 id->active_area = 0;
-                memset(id->active_entry, 0, id->nr_areas * sizeof(int));
-                for (i = 0; i < id->nr_areas; i++) 
-                        memset(id->areas[i], 0, PAGE_SIZE << id->page_order);
+                memset(id->active_entries, 0, id->nr_areas * sizeof(int));
+                for (i = 0; i < id->nr_areas; i++) {
+			id->active_pages[i] = 0;
+			for(j = 0; j < id->pages_per_area; j++) {
+                        	memset(id->areas[i][j], 0, PAGE_SIZE);
+			}
+		}
                 printk(KERN_INFO "debug: %s: all areas flushed\n",id->name);
         } else if(area >= 0 && area < id->nr_areas) {
-                id->active_entry[area] = 0;
-                memset(id->areas[area], 0, PAGE_SIZE << id->page_order);
-                printk(KERN_INFO
-                        "debug: %s: area %i has been flushed\n",
+                id->active_entries[area] = 0;
+		id->active_pages[area] = 0;
+		for(i = 0; i < id->pages_per_area; i++) {
+                	memset(id->areas[area][i],0,PAGE_SIZE);
+		}
+                printk(KERN_INFO "debug: %s: area %i has been flushed\n",
                         id->name, area);
         } else {
                 printk(KERN_INFO
-                        "debug: %s: area %i cannot be flushed (range: %i - %i)\n",
+                      "debug: %s: area %i cannot be flushed (range: %i - %i)\n",
                         id->name, area, 0, id->nr_areas-1);
         }
         spin_unlock_irqrestore(&id->lock,flags);
@@ -1089,15 +1333,20 @@
  * view function: flushes debug areas 
  */
 
-static int debug_input_flush_fn(debug_info_t * id, struct debug_view *view,
-                                struct file *file, const char __user *user_buf,
-                                size_t in_buf_size, loff_t * offset)
+static int
+debug_input_flush_fn(debug_info_t * id, struct debug_view *view,
+			struct file *file, const char __user *user_buf,
+			size_t user_len, loff_t * offset)
 {
         char input_buf[1];
-        int rc = in_buf_size;
- 
-        if (*offset != 0)
+        int rc = user_len;
+
+	if (user_len > 0x10000)
+                user_len = 0x10000;
+        if (*offset != 0){
+		rc = -EPIPE;
                 goto out;
+	}
         if (copy_from_user(input_buf, user_buf, 1)){
                 rc = -EFAULT;
                 goto out;
@@ -1114,8 +1363,8 @@
 
         printk(KERN_INFO "debug: area `%c` is not valid\n", input_buf[0]);
 
-      out:
-        *offset += in_buf_size;
+out:
+        *offset += user_len;
         return rc;              /* number of input characters */
 }
 
@@ -1123,8 +1372,9 @@
  * prints debug header in raw format
  */
 
-int debug_raw_header_fn(debug_info_t * id, struct debug_view *view,
-                         int area, debug_entry_t * entry, char *out_buf)
+static int
+debug_raw_header_fn(debug_info_t * id, struct debug_view *view,
+			int area, debug_entry_t * entry, char *out_buf)
 {
         int rc;
 
@@ -1137,7 +1387,8 @@
  * prints debug data in raw format
  */
 
-static int debug_raw_format_fn(debug_info_t * id, struct debug_view *view,
+static int
+debug_raw_format_fn(debug_info_t * id, struct debug_view *view,
 			       char *out_buf, const char *in_buf)
 {
 	int rc;
@@ -1151,8 +1402,9 @@
  * prints debug data in hex/ascii format
  */
 
-static int debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
-		    		  char *out_buf, const char *in_buf)
+static int
+debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
+	    		  char *out_buf, const char *in_buf)
 {
 	int i, rc = 0;
 
@@ -1176,7 +1428,8 @@
  * prints header for debug entry
  */
 
-int debug_dflt_header_fn(debug_info_t * id, struct debug_view *view,
+int
+debug_dflt_header_fn(debug_info_t * id, struct debug_view *view,
 			 int area, debug_entry_t * entry, char *out_buf)
 {
 	struct timeval time_val;
@@ -1210,8 +1463,9 @@
 
 #define DEBUG_SPRINTF_MAX_ARGS 10
 
-int debug_sprintf_format_fn(debug_info_t * id, struct debug_view *view,
-                            char *out_buf, debug_sprintf_entry_t *curr_event)
+static int
+debug_sprintf_format_fn(debug_info_t * id, struct debug_view *view,
+                        char *out_buf, debug_sprintf_entry_t *curr_event)
 {
 	int num_longs, num_used_args = 0,i, rc = 0;
 	int index[DEBUG_SPRINTF_MAX_ARGS];
@@ -1251,14 +1505,10 @@
 /*
  * clean up module
  */
-void __exit debug_exit(void)
+void
+__exit debug_exit(void)
 {
-#ifdef DEBUG
-	printk("debug_cleanup_module: \n");
-#endif
-#ifdef CONFIG_PROC_FS
-	remove_proc_entry(debug_proc_root_entry->name, NULL);
-#endif /* CONFIG_PROC_FS */
+	debugfs_remove(debug_debugfs_root_entry);
 	unregister_sysctl_table(s390dbf_sysctl_header);
 	return;
 }
@@ -1266,7 +1516,7 @@
 /*
  * module definitions
  */
-core_initcall(debug_init);
+postcore_initcall(debug_init);
 module_exit(debug_exit);
 MODULE_LICENSE("GPL");
 
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index c0e09b3..5b262b5 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -7,6 +7,7 @@
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *               Hartmut Penner (hp@de.ibm.com),
  *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
+ *		 Heiko Carstens <heiko.carstens@de.ibm.com>
  */
 
 #include <linux/sys.h>
@@ -49,9 +50,9 @@
 SP_TRAP      =  STACK_FRAME_OVERHEAD + __PT_TRAP
 SP_SIZE      =  STACK_FRAME_OVERHEAD + __PT_SIZE
 
-_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
+_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING | \
 		 _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
-_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
+_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
 
 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
@@ -121,7 +122,11 @@
 	bz	BASED(stack_overflow)
 3:
 #endif
-2:	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
+2:
+	.endm
+
+	.macro  CREATE_STACK_FRAME psworg,savearea
+	s	%r15,BASED(.Lc_spsize)	# make room for registers & psw
 	mvc	SP_PSW(8,%r15),0(%r12)	# move user PSW to stack
 	la	%r12,\psworg
 	st	%r2,SP_ORIG_R2(%r15)	# store original content of gpr 2
@@ -161,6 +166,13 @@
         be      __switch_to_noper-__switch_to_base(%r1)	# we got away w/o bashing TLB's
         lctl    %c9,%c11,__THREAD_per(%r3)	# Nope we didn't
 __switch_to_noper:
+	l	%r4,__THREAD_info(%r2)		# get thread_info of prev
+	tm	__TI_flags+3(%r4),_TIF_MCCK_PENDING # machine check pending?
+	bz	__switch_to_no_mcck-__switch_to_base(%r1)
+	ni	__TI_flags+3(%r4),255-_TIF_MCCK_PENDING # clear flag in prev
+	l	%r4,__THREAD_info(%r3)		# get thread_info of next
+	oi	__TI_flags+3(%r4),_TIF_MCCK_PENDING # set it in next
+__switch_to_no_mcck:
         stm     %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
 	st	%r15,__THREAD_ksp(%r2)	# store kernel stack to prev->tss.ksp
 	l	%r15,__THREAD_ksp(%r3)	# load kernel stack from next->tss.ksp
@@ -185,6 +197,7 @@
 sysc_saveall:
 	SAVE_ALL_BASE __LC_SAVE_AREA
         SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
+	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 	lh	%r7,0x8a	  # get svc number from lowcore
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 sysc_vtime:
@@ -234,6 +247,8 @@
 # One of the work bits is on. Find out which one.
 #
 sysc_work:
+	tm	__TI_flags+3(%r9),_TIF_MCCK_PENDING
+	bo	BASED(sysc_mcck_pending)
 	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED
 	bo	BASED(sysc_reschedule)
 	tm	__TI_flags+3(%r9),_TIF_SIGPENDING
@@ -253,6 +268,14 @@
 	br      %r1		       # call scheduler
 
 #
+# _TIF_MCCK_PENDING is set, call handler
+#
+sysc_mcck_pending:
+	l	%r1,BASED(.Ls390_handle_mcck)
+	la	%r14,BASED(sysc_work_loop)
+	br	%r1			# TIF bit will be cleared by handler
+
+#
 # _TIF_SIGPENDING is set, call do_signal
 #
 sysc_sigpending:     
@@ -430,6 +453,7 @@
         tm      __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
         bnz     BASED(pgm_per)           # got per exception -> special case
 	SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
+	CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
 	bz	BASED(pgm_no_vtime)
@@ -468,6 +492,7 @@
 #
 pgm_per_std:
 	SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
+	CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
 	bz	BASED(pgm_no_vtime2)
@@ -493,6 +518,7 @@
 #
 pgm_svcper:
 	SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
+	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
 	bz	BASED(pgm_no_vtime3)
@@ -521,6 +547,7 @@
 	stck	__LC_INT_CLOCK
 	SAVE_ALL_BASE __LC_SAVE_AREA+16
         SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+16,0
+	CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+16
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
 	bz	BASED(io_no_vtime)
@@ -578,9 +605,11 @@
 	lr	%r15,%r1
 #
 # One of the work bits is on. Find out which one.
-# Checked are: _TIF_SIGPENDING and _TIF_NEED_RESCHED
+# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED and _TIF_MCCK_PENDING
 #
 io_work_loop:
+	tm	__TI_flags+3(%r9),_TIF_MCCK_PENDING
+	bo      BASED(io_mcck_pending)
 	tm	__TI_flags+3(%r9),_TIF_NEED_RESCHED
 	bo	BASED(io_reschedule)
 	tm	__TI_flags+3(%r9),_TIF_SIGPENDING
@@ -588,6 +617,14 @@
 	b	BASED(io_leave)
 
 #
+# _TIF_MCCK_PENDING is set, call handler
+#
+io_mcck_pending:
+	l	%r1,BASED(.Ls390_handle_mcck)
+	l	%r14,BASED(io_work_loop)
+	br	%r1		       # TIF bit will be cleared by handler
+
+#
 # _TIF_NEED_RESCHED is set, call schedule
 #	
 io_reschedule:        
@@ -621,6 +658,7 @@
 	stck	__LC_INT_CLOCK
 	SAVE_ALL_BASE __LC_SAVE_AREA+16
         SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16,0
+	CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
 	bz	BASED(ext_no_vtime)
@@ -642,19 +680,62 @@
 
         .globl mcck_int_handler
 mcck_int_handler:
-	STORE_TIMER __LC_ASYNC_ENTER_TIMER
+	spt	__LC_CPU_TIMER_SAVE_AREA	# revalidate cpu timer
+	lm	%r0,%r15,__LC_GPREGS_SAVE_AREA	# revalidate gprs
 	SAVE_ALL_BASE __LC_SAVE_AREA+32
-        SAVE_ALL __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32,0
+	la	%r12,__LC_MCK_OLD_PSW
+	tm	__LC_MCCK_CODE,0x80     # system damage?
+	bo	BASED(mcck_int_main)	# yes -> rest of mcck code invalid
+	tm	__LC_MCCK_CODE+5,0x02   # stored cpu timer value valid?
+	bo	BASED(0f)
+	spt	__LC_LAST_UPDATE_TIMER	# revalidate cpu timer
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
-	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
+	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
+	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
+	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_EXIT_TIMER
+0:	tm	__LC_MCCK_CODE+2,0x08   # mwp of old psw valid?
+	bno	BASED(mcck_no_vtime)	# no -> skip cleanup critical
+	tm	__LC_MCK_OLD_PSW+1,0x01 # interrupting from user ?
 	bz	BASED(mcck_no_vtime)
 	UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
 	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
 	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
 mcck_no_vtime:
 #endif
+0:
+	tm	__LC_MCCK_CODE+2,0x09   # mwp + ia of old psw valid?
+	bno	BASED(mcck_int_main)	# no -> skip cleanup critical
+	tm	__LC_MCK_OLD_PSW+1,0x01	# test problem state bit
+	bnz	BASED(mcck_int_main)	# from user -> load async stack
+	clc	__LC_MCK_OLD_PSW+4(4),BASED(.Lcritical_end)
+	bhe	BASED(mcck_int_main)
+	clc	__LC_MCK_OLD_PSW+4(4),BASED(.Lcritical_start)
+	bl	BASED(mcck_int_main)
+	l	%r14,BASED(.Lcleanup_critical)
+	basr	%r14,%r14
+mcck_int_main:
+	l	%r14,__LC_PANIC_STACK	# are we already on the panic stack?
+	slr	%r14,%r15
+	sra	%r14,PAGE_SHIFT
+	be	BASED(0f)
+	l	%r15,__LC_PANIC_STACK	# load panic stack
+0:	CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32
+	l	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs
 	l       %r1,BASED(.Ls390_mcck)
-	basr    %r14,%r1	  # call machine check handler
+	basr    %r14,%r1		# call machine check handler
+	tm      SP_PSW+1(%r15),0x01	# returning to user ?
+	bno	BASED(mcck_return)
+	l	%r1,__LC_KERNEL_STACK   # switch to kernel stack
+	s	%r1,BASED(.Lc_spsize)
+	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
+	xc      __SF_BACKCHAIN(4,%r1),__SF_BACKCHAIN(%r1) # clear back chain
+	lr	%r15,%r1
+	stosm	__SF_EMPTY(%r15),0x04	# turn dat on
+	tm	__TI_flags+3(%r9),_TIF_MCCK_PENDING
+	bno	BASED(mcck_return)
+	l	%r1,BASED(.Ls390_handle_mcck)
+	basr	%r14,%r1		# call machine check handler
 mcck_return:
         RESTORE_ALL 0
 
@@ -742,7 +823,7 @@
 	clc	4(4,%r12),BASED(cleanup_table_sysc_work_loop)
 	bl	BASED(0f)
 	clc	4(4,%r12),BASED(cleanup_table_sysc_work_loop+4)
-	bl	BASED(cleanup_sysc_leave)
+	bl	BASED(cleanup_sysc_return)
 0:
 	br	%r14
 
@@ -760,6 +841,7 @@
 	mvc	__LC_SAVE_AREA(16),__LC_SAVE_AREA+16
 0:	st	%r13,__LC_SAVE_AREA+20
 	SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
+	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 	st	%r15,__LC_SAVE_AREA+28
 	lh	%r7,0x8a
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
@@ -834,6 +916,8 @@
  * Symbol constants
  */
 .Ls390_mcck:   .long  s390_do_machine_check
+.Ls390_handle_mcck:
+	       .long  s390_handle_mcck
 .Ldo_IRQ:      .long  do_IRQ
 .Ldo_extint:   .long  do_extint
 .Ldo_signal:   .long  do_signal
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S
index 51527ab..57ca75d 100644
--- a/arch/s390/kernel/entry64.S
+++ b/arch/s390/kernel/entry64.S
@@ -7,6 +7,7 @@
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *               Hartmut Penner (hp@de.ibm.com),
  *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
+ *		 Heiko Carstens <heiko.carstens@de.ibm.com>
  */
 
 #include <linux/sys.h>
@@ -52,9 +53,9 @@
 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
 
-_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
+_TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING | \
 		 _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
-_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
+_TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING)
 
 #define BASED(name) name-system_call(%r13)
 
@@ -114,7 +115,11 @@
 	jz	stack_overflow
 3:
 #endif
-2:	aghi    %r15,-SP_SIZE		# make room for registers & psw
+2:
+	.endm
+
+	.macro	CREATE_STACK_FRAME psworg,savearea
+	aghi    %r15,-SP_SIZE		# make room for registers & psw
 	mvc     SP_PSW(16,%r15),0(%r12)	# move user PSW to stack
 	la	%r12,\psworg
 	stg	%r2,SP_ORIG_R2(%r15)	# store original content of gpr 2
@@ -152,6 +157,13 @@
         je      __switch_to_noper            # we got away without bashing TLB's
         lctlg   %c9,%c11,__THREAD_per(%r3)	# Nope we didn't
 __switch_to_noper:
+	lg	%r4,__THREAD_info(%r2)              # get thread_info of prev
+	tm	__TI_flags+7(%r4),_TIF_MCCK_PENDING # machine check pending?
+	jz	__switch_to_no_mcck
+	ni	__TI_flags+7(%r4),255-_TIF_MCCK_PENDING # clear flag in prev
+	lg	%r4,__THREAD_info(%r3)		    # get thread_info of next
+	oi	__TI_flags+7(%r4),_TIF_MCCK_PENDING # set it in next
+__switch_to_no_mcck:
         stmg    %r6,%r15,__SF_GPRS(%r15)# store __switch_to registers of prev task
 	stg	%r15,__THREAD_ksp(%r2)	# store kernel stack to prev->tss.ksp
 	lg	%r15,__THREAD_ksp(%r3)	# load kernel stack from next->tss.ksp
@@ -176,6 +188,7 @@
 sysc_saveall:
 	SAVE_ALL_BASE __LC_SAVE_AREA
         SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
+        CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 	llgh    %r7,__LC_SVC_INT_CODE # get svc number from lowcore
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 sysc_vtime:
@@ -232,6 +245,8 @@
 # One of the work bits is on. Find out which one.
 #
 sysc_work:
+	tm	__TI_flags+7(%r9),_TIF_MCCK_PENDING
+	jo	sysc_mcck_pending
 	tm	__TI_flags+7(%r9),_TIF_NEED_RESCHED
 	jo	sysc_reschedule
 	tm	__TI_flags+7(%r9),_TIF_SIGPENDING
@@ -250,6 +265,13 @@
         jg      schedule            # return point is sysc_return
 
 #
+# _TIF_MCCK_PENDING is set, call handler
+#
+sysc_mcck_pending:
+	larl	%r14,sysc_work_loop
+	jg	s390_handle_mcck    # TIF bit will be cleared by handler
+
+#
 # _TIF_SIGPENDING is set, call do_signal
 #
 sysc_sigpending:     
@@ -474,6 +496,7 @@
         tm      __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
         jnz     pgm_per                  # got per exception -> special case
 	SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
+	CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
 	jz	pgm_no_vtime
@@ -512,6 +535,7 @@
 #
 pgm_per_std:
 	SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1
+	CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
 	jz	pgm_no_vtime2
@@ -537,6 +561,7 @@
 #
 pgm_svcper:
 	SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
+	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
 	jz	pgm_no_vtime3
@@ -564,6 +589,7 @@
 	stck	__LC_INT_CLOCK
 	SAVE_ALL_BASE __LC_SAVE_AREA+32
         SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+32,0
+	CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+32
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
 	jz	io_no_vtime
@@ -621,9 +647,11 @@
 	lgr	%r15,%r1
 #
 # One of the work bits is on. Find out which one.
-# Checked are: _TIF_SIGPENDING and _TIF_NEED_RESCHED
+# Checked are: _TIF_SIGPENDING, _TIF_NEED_RESCHED and _TIF_MCCK_PENDING
 #
 io_work_loop:
+	tm	__TI_flags+7(%r9),_TIF_MCCK_PENDING
+	jo	io_mcck_pending
 	tm	__TI_flags+7(%r9),_TIF_NEED_RESCHED
 	jo	io_reschedule
 	tm	__TI_flags+7(%r9),_TIF_SIGPENDING
@@ -631,6 +659,13 @@
 	j	io_leave
 
 #
+# _TIF_MCCK_PENDING is set, call handler
+#
+io_mcck_pending:
+	larl	%r14,io_work_loop
+	jg	s390_handle_mcck	# TIF bit will be cleared by handler
+
+#
 # _TIF_NEED_RESCHED is set, call schedule
 #	
 io_reschedule:        
@@ -661,6 +696,7 @@
 	stck	__LC_INT_CLOCK
 	SAVE_ALL_BASE __LC_SAVE_AREA+32
         SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32,0
+	CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
 	jz	ext_no_vtime
@@ -680,18 +716,60 @@
  */
         .globl mcck_int_handler
 mcck_int_handler:
-	STORE_TIMER __LC_ASYNC_ENTER_TIMER
+	la	%r1,4095		# revalidate r1
+	spt	__LC_CPU_TIMER_SAVE_AREA-4095(%r1)	# revalidate cpu timer
+  	lmg     %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs
 	SAVE_ALL_BASE __LC_SAVE_AREA+64
-        SAVE_ALL __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64,0
+	la	%r12,__LC_MCK_OLD_PSW
+	tm	__LC_MCCK_CODE,0x80     # system damage?
+	jo	mcck_int_main		# yes -> rest of mcck code invalid
+	tm	__LC_MCCK_CODE+5,0x02   # stored cpu timer value valid?
+	jo	0f
+	spt	__LC_LAST_UPDATE_TIMER
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
-	tm	SP_PSW+1(%r15),0x01	# interrupting from user ?
+	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
+	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_SYNC_ENTER_TIMER
+	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_EXIT_TIMER
+0:	tm	__LC_MCCK_CODE+2,0x08	# mwp of old psw valid?
+	jno	mcck_no_vtime		# no -> no timer update
+	tm      __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ?
 	jz	mcck_no_vtime
 	UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER
 	UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER
 	mvc	__LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER
 mcck_no_vtime:
 #endif
-	brasl   %r14,s390_do_machine_check
+0:
+	tm	__LC_MCCK_CODE+2,0x09   # mwp + ia of old psw valid?
+	jno	mcck_int_main		# no -> skip cleanup critical
+	tm      __LC_MCK_OLD_PSW+1,0x01 # test problem state bit
+	jnz	mcck_int_main		# from user -> load kernel stack
+	clc	__LC_MCK_OLD_PSW+8(8),BASED(.Lcritical_end)
+	jhe	mcck_int_main
+	clc     __LC_MCK_OLD_PSW+8(8),BASED(.Lcritical_start)
+	jl	mcck_int_main
+	brasl   %r14,cleanup_critical
+mcck_int_main:
+	lg      %r14,__LC_PANIC_STACK   # are we already on the panic stack?
+	slgr	%r14,%r15
+	srag	%r14,%r14,PAGE_SHIFT
+	jz	0f
+	lg      %r15,__LC_PANIC_STACK   # load panic stack
+0:	CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64
+	lg	%r9,__LC_THREAD_INFO	# load pointer to thread_info struct
+	la	%r2,SP_PTREGS(%r15)	# load pt_regs
+	brasl	%r14,s390_do_machine_check
+	tm	SP_PSW+1(%r15),0x01     # returning to user ?
+	jno	mcck_return
+	lg	%r1,__LC_KERNEL_STACK	# switch to kernel stack
+	aghi	%r1,-SP_SIZE
+	mvc	SP_PTREGS(__PT_SIZE,%r1),SP_PTREGS(%r15)
+	xc	__SF_BACKCHAIN(8,%r1),__SF_BACKCHAIN(%r1) # clear back chain
+	lgr	%r15,%r1
+	stosm	__SF_EMPTY(%r15),0x04	# turn dat on
+	tm	__TI_flags+7(%r9),_TIF_MCCK_PENDING
+	jno	mcck_return
+	brasl	%r14,s390_handle_mcck
 mcck_return:
         RESTORE_ALL 0
 
@@ -775,7 +853,7 @@
 	clc	8(8,%r12),BASED(cleanup_table_sysc_work_loop)
 	jl	0f
 	clc	8(8,%r12),BASED(cleanup_table_sysc_work_loop+8)
-	jl	cleanup_sysc_leave
+	jl	cleanup_sysc_return
 0:
 	br	%r14
 
@@ -793,6 +871,7 @@
 	mvc	__LC_SAVE_AREA(32),__LC_SAVE_AREA+32
 0:	stg	%r13,__LC_SAVE_AREA+40
 	SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1
+	CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA
 	stg	%r15,__LC_SAVE_AREA+56
 	llgh	%r7,__LC_SVC_INT_CODE
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index b804c55..fc8bf5e 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -345,10 +345,25 @@
 	bno   .Lnoreset
         la    %r2,.Lreset              
         lhi   %r3,26
-        .long 0x83230008
+	diag  %r2,%r3,8
+	mvc   0x78(8),.Lrdrnewpsw              # set up IO interrupt psw
+.Lwaitrdrirq:
+	lpsw  .Lrdrwaitpsw
+.Lrdrint:
+	c     %r1,0xb8                         # compare subchannel number
+	bne   .Lwaitrdrirq
+	la    %r5,.Lirb
+	tsch  0(%r5)
 .Lnoreset:
+        b     .Lnoload
+
+	.align 8
+.Lrdrnewpsw:
+	.long  0x00080000,0x80000000+.Lrdrint
+.Lrdrwaitpsw:
+	.long  0x020a0000,0x80000000+.Lrdrint
 #endif
-	
+
 #
 # everything loaded, go for it
 #
@@ -517,10 +532,10 @@
 	l     %r2, .Lrcp2-.LPG1(%r13)	# try with Read SCP
 	b     .Lservicecall-.LPG1(%r13)
 .Lprocsccb:
-	lh    %r1,.Lscpincr1-PARMAREA(%r4) # use this one if != 0
-	chi   %r1,0x00
-	jne   .Lscnd
-	l     %r1,.Lscpincr2-PARMAREA(%r4) # otherwise use this one
+	lhi   %r1,0
+	icm   %r1,3,.Lscpincr1-PARMAREA(%r4) # use this one if != 0
+	jnz   .Lscnd
+	l     %r1,.Lscpincr2-PARMAREA+4(%r4) # otherwise use this one
 .Lscnd:
 	xr    %r3,%r3			# same logic
 	ic    %r3,.Lscpa1-PARMAREA(%r4)
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S
index 8366793..f525c0c 100644
--- a/arch/s390/kernel/head64.S
+++ b/arch/s390/kernel/head64.S
@@ -344,10 +344,25 @@
 	bno   .Lnoreset
         la    %r2,.Lreset              
         lhi   %r3,26
-        .long 0x83230008
+	diag  %r2,%r3,8
+	mvc   0x78(8),.Lrdrnewpsw	       # set up IO interrupt psw
+.Lwaitrdrirq:
+	lpsw  .Lrdrwaitpsw
+.Lrdrint:
+	c     %r1,0xb8			       # compare subchannel number
+	bne   .Lwaitrdrirq
+	la    %r5,.Lirb
+	tsch  0(%r5)
 .Lnoreset:
+	b     .Lnoload
+
+	.align 8
+.Lrdrnewpsw:
+	.long  0x00080000,0x80000000+.Lrdrint
+.Lrdrwaitpsw:
+	.long  0x020a0000,0x80000000+.Lrdrint
 #endif
-	
+
 #
 # everything loaded, go for it
 #
@@ -518,9 +533,9 @@
 	l     %r2,.Lrcp2-.LPG1(%r13)	# try with Read SCP
 	b     .Lservicecall-.LPG1(%r13)
 .Lprocsccb:
-	lh    %r1,.Lscpincr1-PARMAREA(%r4) # use this one if != 0
-	chi   %r1,0x00
-	jne   .Lscnd
+	lghi  %r1,0
+	icm   %r1,3,.Lscpincr1-PARMAREA(%r4) # use this one if != 0
+	jnz   .Lscnd
 	lg    %r1,.Lscpincr2-PARMAREA(%r4) # otherwise use this one
 .Lscnd:
 	xr    %r3,%r3			# same logic
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c
new file mode 100644
index 0000000..2721c3a
--- /dev/null
+++ b/arch/s390/kernel/machine_kexec.c
@@ -0,0 +1,98 @@
+/*
+ * arch/s390/kernel/machine_kexec.c
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
+ *
+ */
+
+/*
+ * s390_machine_kexec.c - handle the transition of Linux booting another kernel
+ * on the S390 architecture.
+ */
+
+#include <asm/cio.h>
+#include <asm/setup.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/kexec.h>
+#include <linux/delay.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/system.h>
+
+static void kexec_halt_all_cpus(void *);
+
+typedef void (*relocate_kernel_t) (kimage_entry_t *, unsigned long);
+
+const extern unsigned char relocate_kernel[];
+const extern unsigned long long relocate_kernel_len;
+
+int
+machine_kexec_prepare(struct kimage *image)
+{
+	unsigned long reboot_code_buffer;
+
+	/* We don't support anything but the default image type for now. */
+	if (image->type != KEXEC_TYPE_DEFAULT)
+		return -EINVAL;
+
+	/* Get the destination where the assembler code should be copied to.*/
+	reboot_code_buffer = page_to_pfn(image->control_code_page)<<PAGE_SHIFT;
+
+	/* Then copy it */
+	memcpy((void *) reboot_code_buffer, relocate_kernel,
+	       relocate_kernel_len);
+	return 0;
+}
+
+void
+machine_kexec_cleanup(struct kimage *image)
+{
+}
+
+void
+machine_shutdown(void)
+{
+	printk(KERN_INFO "kexec: machine_shutdown called\n");
+}
+
+NORET_TYPE void
+machine_kexec(struct kimage *image)
+{
+	clear_all_subchannels();
+
+	/* Disable lowcore protection */
+	ctl_clear_bit(0,28);
+
+	on_each_cpu(kexec_halt_all_cpus, image, 0, 0);
+	for (;;);
+}
+
+static void
+kexec_halt_all_cpus(void *kernel_image)
+{
+	static atomic_t cpuid = ATOMIC_INIT(-1);
+	int cpu;
+	struct kimage *image;
+	relocate_kernel_t data_mover;
+
+	if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid))
+		signal_processor(smp_processor_id(), sigp_stop);
+
+	/* Wait for all other cpus to enter stopped state */
+	for_each_online_cpu(cpu) {
+		if (cpu == smp_processor_id())
+			continue;
+		while (!smp_cpu_not_running(cpu))
+			cpu_relax();
+	}
+
+	image = (struct kimage *) kernel_image;
+	data_mover = (relocate_kernel_t)
+		(page_to_pfn(image->control_code_page) << PAGE_SHIFT);
+
+	/* Call the moving routine */
+	(*data_mover) (&image->head, image->start);
+}
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 7aea25d..9f3dff6 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -91,13 +91,12 @@
 			    (void *)(long) smp_processor_id());
 }
 
+extern void s390_handle_mcck(void);
 /*
  * The idle loop on a S390...
  */
 void default_idle(void)
 {
-	psw_t wait_psw;
-	unsigned long reg;
 	int cpu, rc;
 
 	local_irq_disable();
@@ -125,38 +124,17 @@
 		cpu_die();
 #endif
 
-	/* 
-	 * Wait for external, I/O or machine check interrupt and
-	 * switch off machine check bit after the wait has ended.
-	 */
-	wait_psw.mask = PSW_KERNEL_BITS | PSW_MASK_MCHECK | PSW_MASK_WAIT |
-		PSW_MASK_IO | PSW_MASK_EXT;
-#ifndef CONFIG_ARCH_S390X
-	asm volatile (
-		"    basr %0,0\n"
-		"0:  la   %0,1f-0b(%0)\n"
-		"    st   %0,4(%1)\n"
-		"    oi   4(%1),0x80\n"
-		"    lpsw 0(%1)\n"
-		"1:  la   %0,2f-1b(%0)\n"
-		"    st   %0,4(%1)\n"
-		"    oi   4(%1),0x80\n"
-		"    ni   1(%1),0xf9\n"
-		"    lpsw 0(%1)\n"
-		"2:"
-		: "=&a" (reg) : "a" (&wait_psw) : "memory", "cc" );
-#else /* CONFIG_ARCH_S390X */
-	asm volatile (
-		"    larl  %0,0f\n"
-		"    stg   %0,8(%1)\n"
-		"    lpswe 0(%1)\n"
-		"0:  larl  %0,1f\n"
-		"    stg   %0,8(%1)\n"
-		"    ni    1(%1),0xf9\n"
-		"    lpswe 0(%1)\n"
-		"1:"
-		: "=&a" (reg) : "a" (&wait_psw) : "memory", "cc" );
-#endif /* CONFIG_ARCH_S390X */
+	local_mcck_disable();
+	if (test_thread_flag(TIF_MCCK_PENDING)) {
+		local_mcck_enable();
+		local_irq_enable();
+		s390_handle_mcck();
+		return;
+	}
+
+	/* Wait for external, I/O or machine check interrupt. */
+	__load_psw_mask(PSW_KERNEL_BITS | PSW_MASK_WAIT |
+			PSW_MASK_IO | PSW_MASK_EXT);
 }
 
 void cpu_idle(void)
diff --git a/arch/s390/kernel/relocate_kernel.S b/arch/s390/kernel/relocate_kernel.S
new file mode 100644
index 0000000..d5e4a62
--- /dev/null
+++ b/arch/s390/kernel/relocate_kernel.S
@@ -0,0 +1,81 @@
+/*
+ * arch/s390/kernel/relocate_kernel.S
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
+ *
+ */
+
+/*
+ * moves the new kernel to its destination...
+ * %r2 = pointer to first kimage_entry_t
+ * %r3 = start address - where to jump to after the job is done...
+ *
+ * %r5 will be used as temp. storage
+ * %r6 holds the destination address
+ * %r7 = PAGE_SIZE
+ * %r8 holds the source address
+ * %r9 = PAGE_SIZE
+ * %r10 is a page mask
+ */
+
+	.text
+	.globl		relocate_kernel
+	relocate_kernel:
+		basr	%r13,0		#base address
+	.base:
+		spx	zero64-.base(%r13)	#absolute addressing mode
+		stnsm	sys_msk-.base(%r13),0xf8	#disable DAT and IRQ (external)
+		lhi	%r10,-1		#preparing the mask
+		sll	%r10,12		#shift it such that it becomes 0xf000
+	.top:
+		lhi	%r7,4096	#load PAGE_SIZE in r7
+		lhi	%r9,4096	#load PAGE_SIZE in r9
+		l	%r5,0(%r2)	#read another word for indirection page
+		ahi	%r2,4		#increment pointer
+		tml	%r5,0x1		#is it a destination page?
+		je	.indir_check	#NO, goto "indir_check"
+		lr	%r6,%r5		#r6 = r5
+		nr	%r6,%r10	#mask it out and...
+		j	.top		#...next iteration
+	.indir_check:
+		tml	%r5,0x2		#is it a indirection page?
+		je	.done_test	#NO, goto "done_test"
+		nr	%r5,%r10	#YES, mask out,
+		lr	%r2,%r5		#move it into the right register,
+		j	.top		#and read next...
+	.done_test:
+		tml	%r5,0x4		#is it the done indicator?
+		je	.source_test	#NO! Well, then it should be the source indicator...
+		j	.done		#ok, lets finish it here...
+	.source_test:
+		tml	%r5,0x8		#it should be a source indicator...
+		je	.top		#NO, ignore it...
+		lr	%r8,%r5		#r8 = r5
+		nr	%r8,%r10	#masking
+	0:	mvcle	%r6,%r8,0x0	#copy PAGE_SIZE bytes from r8 to r6 - pad with 0
+		jo	0b
+		j	.top
+	.done:
+		sr	%r0,%r0		#clear register r0
+		la	%r4,load_psw-.base(%r13)	#load psw-address into the register
+		o	%r3,4(%r4)	#or load address into psw
+		st	%r3,4(%r4)
+		mvc	0(8,%r0),0(%r4)	#copy psw to absolute address 0
+		sr	%r1,%r1		#clear %r1
+		sr	%r2,%r2		#clear %r2
+		sigp	%r1,%r2,0x12	#set cpuid to zero
+		lpsw	0		#hopefully start new kernel...
+
+		.align	8
+	zero64:
+		.quad	0
+	load_psw:
+		.long	0x00080000,0x80000000
+	sys_msk:
+		.quad	0
+	relocate_kernel_end:
+	.globl	relocate_kernel_len
+	relocate_kernel_len:
+		.quad	relocate_kernel_end - relocate_kernel
diff --git a/arch/s390/kernel/relocate_kernel64.S b/arch/s390/kernel/relocate_kernel64.S
new file mode 100644
index 0000000..96290cc
--- /dev/null
+++ b/arch/s390/kernel/relocate_kernel64.S
@@ -0,0 +1,82 @@
+/*
+ * arch/s390/kernel/relocate_kernel64.S
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
+ *
+ */
+
+/*
+ * moves the new kernel to its destination...
+ * %r2 = pointer to first kimage_entry_t
+ * %r3 = start address - where to jump to after the job is done...
+ *
+ * %r5 will be used as temp. storage
+ * %r6 holds the destination address
+ * %r7 = PAGE_SIZE
+ * %r8 holds the source address
+ * %r9 = PAGE_SIZE
+ *
+ * 0xf000 is a page_mask
+ */
+
+	.text
+	.globl		relocate_kernel
+	relocate_kernel:
+		basr	%r13,0		#base address
+	.base:
+		spx	zero64-.base(%r13)	#absolute addressing mode
+		stnsm	sys_msk-.base(%r13),0xf8	#disable DAT and IRQ (external)
+	.top:
+		lghi	%r7,4096	#load PAGE_SIZE in r7
+		lghi	%r9,4096	#load PAGE_SIZE in r9
+		lg	%r5,0(%r2)	#read another word for indirection page
+		aghi	%r2,8		#increment pointer
+		tml	%r5,0x1		#is it a destination page?
+		je	.indir_check	#NO, goto "indir_check"
+		lgr	%r6,%r5		#r6 = r5
+		nill	%r6,0xf000	#mask it out and...
+		j	.top		#...next iteration
+	.indir_check:
+		tml     %r5,0x2		#is it a indirection page?
+		je      .done_test	#NO, goto "done_test"
+		nill    %r5,0xf000	#YES, mask out,
+		lgr     %r2,%r5		#move it into the right register,
+		j       .top		#and read next...
+	.done_test:
+		tml     %r5,0x4		#is it the done indicator?
+		je      .source_test	#NO! Well, then it should be the source indicator...
+		j       .done		#ok, lets finish it here...
+	.source_test:
+		tml     %r5,0x8		#it should be a source indicator...
+		je      .top		#NO, ignore it...
+		lgr     %r8,%r5		#r8 = r5
+		nill    %r8,0xf000	#masking
+	0:	mvcle   %r6,%r8,0x0	#copy PAGE_SIZE bytes from r8 to r6 - pad with 0
+		jo	0b
+		j       .top
+	.done:
+		sgr     %r0,%r0		#clear register r0
+		la      %r4,load_psw-.base(%r13)	#load psw-address into the register
+		o	%r3,4(%r4)	#or load address into psw
+		st	%r3,4(%r4)
+		mvc     0(8,%r0),0(%r4)	#copy psw to absolute address 0
+		sam31			#31 bit mode
+		sr      %r1,%r1		#erase register r1
+		sr      %r2,%r2		#erase register r2
+		sigp    %r1,%r2,0x12	#set cpuid to zero
+		lpsw    0		#hopefully start new kernel...
+
+	        .align	8
+	zero64:
+		.quad	0
+	load_psw:
+		.long	0x00080000,0x80000000
+	sys_msk:
+		.quad	0
+	relocate_kernel_end:
+	.globl	relocate_kernel_len
+	relocate_kernel_len:
+		.quad	relocate_kernel_end - relocate_kernel
+
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index df83215..b6d740a 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -198,11 +198,11 @@
 	char *ptr;
 
         if (MACHINE_IS_VM) {
-		__cpcmd("QUERY CONSOLE", query_buffer, 1024);
+		__cpcmd("QUERY CONSOLE", query_buffer, 1024, NULL);
 		console_devno = simple_strtoul(query_buffer + 5, NULL, 16);
 		ptr = strstr(query_buffer, "SUBCHANNEL =");
 		console_irq = simple_strtoul(ptr + 13, NULL, 16);
-		__cpcmd("QUERY TERM", query_buffer, 1024);
+		__cpcmd("QUERY TERM", query_buffer, 1024, NULL);
 		ptr = strstr(query_buffer, "CONMODE");
 		/*
 		 * Set the conmode to 3215 so that the device recognition 
@@ -211,7 +211,7 @@
 		 * 3215 and the 3270 driver will try to access the console
 		 * device (3215 as console and 3270 as normal tty).
 		 */
-		__cpcmd("TERM CONMODE 3215", NULL, 0);
+		__cpcmd("TERM CONMODE 3215", NULL, 0, NULL);
 		if (ptr == NULL) {
 #if defined(CONFIG_SCLP_CONSOLE)
 			SET_CONSOLE_SCLP;
@@ -414,7 +414,8 @@
 	lc->program_new_psw.mask = PSW_KERNEL_BITS;
 	lc->program_new_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long)pgm_check_handler;
-	lc->mcck_new_psw.mask = PSW_KERNEL_BITS;
+	lc->mcck_new_psw.mask =
+		PSW_KERNEL_BITS & ~PSW_MASK_MCHECK & ~PSW_MASK_DAT;
 	lc->mcck_new_psw.addr =
 		PSW_ADDR_AMODE | (unsigned long) mcck_int_handler;
 	lc->io_new_psw.mask = PSW_KERNEL_BITS;
@@ -424,12 +425,18 @@
 	lc->kernel_stack = ((unsigned long) &init_thread_union) + THREAD_SIZE;
 	lc->async_stack = (unsigned long)
 		__alloc_bootmem(ASYNC_SIZE, ASYNC_SIZE, 0) + ASYNC_SIZE;
-#ifdef CONFIG_CHECK_STACK
 	lc->panic_stack = (unsigned long)
 		__alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0) + PAGE_SIZE;
-#endif
 	lc->current_task = (unsigned long) init_thread_union.thread_info.task;
 	lc->thread_info = (unsigned long) &init_thread_union;
+#ifndef CONFIG_ARCH_S390X
+	if (MACHINE_HAS_IEEE) {
+		lc->extended_save_area_addr = (__u32)
+			__alloc_bootmem(PAGE_SIZE, PAGE_SIZE, 0);
+		/* enable extended save area */
+		ctl_set_bit(14, 29);
+	}
+#endif
 #ifdef CONFIG_ARCH_S390X
 	if (MACHINE_HAS_DIAG44)
 		lc->diag44_opcode = 0x83000044;
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index fdfcf04..642572a 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -284,7 +284,7 @@
 	 * locks are always held disabled).
 	 */
 	if (MACHINE_IS_VM)
-		cpcmd ("IPL", NULL, 0);
+		cpcmd ("IPL", NULL, 0, NULL);
 	else
 		reipl (0x10000 | S390_lowcore.ipl_device);
 }
@@ -313,7 +313,7 @@
 	if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid) == 0) {
 		smp_send_stop();
 		if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
-			cpcmd(vmhalt_cmd, NULL, 0);
+			cpcmd(vmhalt_cmd, NULL, 0, NULL);
 		signal_processor(smp_processor_id(),
 				 sigp_stop_and_store_status);
 	}
@@ -332,7 +332,7 @@
 	if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid) == 0) {
 		smp_send_stop();
 		if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
-			cpcmd(vmpoff_cmd, NULL, 0);
+			cpcmd(vmpoff_cmd, NULL, 0, NULL);
 		signal_processor(smp_processor_id(),
 				 sigp_stop_and_store_status);
 	}
@@ -679,12 +679,14 @@
 {
 	unsigned long flags;
 	ec_creg_mask_parms cr_parms;
+	int cpu = smp_processor_id();
 
 	spin_lock_irqsave(&smp_reserve_lock, flags);
-	if (smp_cpu_reserved[smp_processor_id()] != 0) {
+	if (smp_cpu_reserved[cpu] != 0) {
 		spin_unlock_irqrestore(&smp_reserve_lock, flags);
 		return -EBUSY;
 	}
+	cpu_clear(cpu, cpu_online_map);
 
 #ifdef CONFIG_PFAULT
 	/* Disable pfault pseudo page faults on this cpu. */
@@ -771,13 +773,24 @@
 
 		*(lowcore_ptr[i]) = S390_lowcore;
 		lowcore_ptr[i]->async_stack = stack + (ASYNC_SIZE);
-#ifdef CONFIG_CHECK_STACK
 		stack = __get_free_pages(GFP_KERNEL,0);
 		if (stack == 0ULL)
 			panic("smp_boot_cpus failed to allocate memory\n");
 		lowcore_ptr[i]->panic_stack = stack + (PAGE_SIZE);
+#ifndef __s390x__
+		if (MACHINE_HAS_IEEE) {
+			lowcore_ptr[i]->extended_save_area_addr =
+				(__u32) __get_free_pages(GFP_KERNEL,0);
+			if (lowcore_ptr[i]->extended_save_area_addr == 0)
+				panic("smp_boot_cpus failed to "
+				      "allocate memory\n");
+		}
 #endif
 	}
+#ifndef __s390x__
+	if (MACHINE_HAS_IEEE)
+		ctl_set_bit(14, 29); /* enable extended save area */
+#endif
 	set_prefix((u32)(unsigned long) lowcore_ptr[smp_processor_id()]);
 
 	for_each_cpu(cpu)
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 5159386..a8668af 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -285,7 +285,7 @@
 SYSCALL(sys_mq_timedreceive,sys_mq_timedreceive,compat_sys_mq_timedreceive_wrapper)
 SYSCALL(sys_mq_notify,sys_mq_notify,compat_sys_mq_notify_wrapper) /* 275 */
 SYSCALL(sys_mq_getsetattr,sys_mq_getsetattr,compat_sys_mq_getsetattr_wrapper)
-NI_SYSCALL							/* reserved for kexec */
+SYSCALL(sys_kexec_load,sys_kexec_load,compat_sys_kexec_load_wrapper)
 SYSCALL(sys_add_key,sys_add_key,compat_sys_add_key_wrapper)
 SYSCALL(sys_request_key,sys_request_key,compat_sys_request_key_wrapper)
 SYSCALL(sys_keyctl,sys_keyctl,compat_sys_keyctl)		/* 280 */
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 8b90e95..bc7b7be 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -668,7 +668,10 @@
 
 asmlinkage void kernel_stack_overflow(struct pt_regs * regs)
 {
-	die("Kernel stack overflow", regs, 0);
+	bust_spinlocks(1);
+	printk("Kernel stack overflow.\n");
+	show_regs(regs);
+	bust_spinlocks(0);
 	panic("Corrupt kernel stack, can't continue.");
 }
 
@@ -732,7 +735,7 @@
 						    &ext_int_pfault);
 #endif
 #ifndef CONFIG_ARCH_S390X
-		cpcmd("SET PAGEX ON", NULL, 0);
+		cpcmd("SET PAGEX ON", NULL, 0, NULL);
 #endif
 	}
 }
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index f5a5bc0..2d5cb13 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -21,7 +21,7 @@
 #include <asm/uaccess.h>
 
 static char *sender = "VMRMSVM";
-module_param(sender, charp, 0);
+module_param(sender, charp, 0400);
 MODULE_PARM_DESC(sender,
 		 "Guest name that may send SMSG messages (default VMRMSVM)");
 
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
index 648deed..c534810 100644
--- a/arch/s390/mm/extmem.c
+++ b/arch/s390/mm/extmem.c
@@ -576,8 +576,8 @@
 			segtype_string[seg->range[i].start & 0xff]);
 	}
 	sprintf(cmd2, "SAVESEG %s", name);
-	cpcmd(cmd1, NULL, 0);
-	cpcmd(cmd2, NULL, 0);
+	cpcmd(cmd1, NULL, 0, NULL);
+	cpcmd(cmd2, NULL, 0, NULL);
 	spin_unlock(&dcss_lock);
 }
 
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 3468d51..a7c8bfc 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -486,7 +486,7 @@
        depends on CPU_SUBTYPE_ST40STB1 || CPU_SUBTYPE_ST40GX1
        default y
 
-config DISCONTIGMEM
+config ARCH_DISCONTIGMEM_ENABLE
 	bool
 	depends on SH_HP690
 	default y
@@ -496,6 +496,8 @@
 	  or have huge holes in the physical address space for other reasons.
 	  See <file:Documentation/vm/numa> for more.
 
+source "mm/Kconfig"
+
 config ZERO_PAGE_OFFSET
 	hex "Zero page offset"
 	default "0x00001000" if !(SH_MPC1211 || SH_SH03)
diff --git a/arch/sh/kernel/sys_sh.c b/arch/sh/kernel/sys_sh.c
index df5ac29..917b2f3 100644
--- a/arch/sh/kernel/sys_sh.c
+++ b/arch/sh/kernel/sys_sh.c
@@ -79,6 +79,10 @@
 		    (!vma || addr + len <= vma->vm_start))
 			return addr;
 	}
+	if (len <= mm->cached_hole_size) {
+	        mm->cached_hole_size = 0;
+		mm->free_area_cache = TASK_UNMAPPED_BASE;
+	}
 	if (flags & MAP_PRIVATE)
 		addr = PAGE_ALIGN(mm->free_area_cache);
 	else
@@ -95,6 +99,7 @@
 			 */
 			if (start_addr != TASK_UNMAPPED_BASE) {
 				start_addr = addr = TASK_UNMAPPED_BASE;
+				mm->cached_hole_size = 0;
 				goto full_search;
 			}
 			return -ENOMEM;
@@ -106,6 +111,9 @@
 			mm->free_area_cache = addr + len;
 			return addr;
 		}
+		if (addr + mm->cached_hole_size < vma->vm_start)
+		        mm->cached_hole_size = vma->vm_start - addr;
+
 		addr = vma->vm_end;
 		if (!(flags & MAP_PRIVATE))
 			addr = COLOUR_ALIGN(addr);
diff --git a/arch/sh/lib/delay.c b/arch/sh/lib/delay.c
index 50b3603..3517146 100644
--- a/arch/sh/lib/delay.c
+++ b/arch/sh/lib/delay.c
@@ -24,7 +24,7 @@
 	__asm__("dmulu.l	%0, %2\n\t"
 		"sts	mach, %0"
 		: "=r" (xloops)
-		: "0" (xloops), "r" (cpu_data[_smp_processor_id()].loops_per_jiffy)
+		: "0" (xloops), "r" (cpu_data[raw_smp_processor_id()].loops_per_jiffy)
 		: "macl", "mach");
 	__delay(xloops * HZ);
 }
diff --git a/arch/sh/mm/hugetlbpage.c b/arch/sh/mm/hugetlbpage.c
index 1f897ba..95bb1a6 100644
--- a/arch/sh/mm/hugetlbpage.c
+++ b/arch/sh/mm/hugetlbpage.c
@@ -24,7 +24,7 @@
 #include <asm/tlbflush.h>
 #include <asm/cacheflush.h>
 
-static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
 {
 	pgd_t *pgd;
 	pmd_t *pmd;
@@ -39,7 +39,7 @@
 	return pte;
 }
 
-static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 {
 	pgd_t *pgd;
 	pmd_t *pmd;
@@ -56,30 +56,36 @@
 
 #define mk_pte_huge(entry) do { pte_val(entry) |= _PAGE_SZHUGE; } while (0)
 
-static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
-			 struct page *page, pte_t * page_table, int write_access)
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+		     pte_t *ptep, pte_t entry)
 {
-	unsigned long i;
-	pte_t entry;
-
-	add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
-
-	if (write_access)
-		entry = pte_mkwrite(pte_mkdirty(mk_pte(page,
-						       vma->vm_page_prot)));
-	else
-		entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot));
-	entry = pte_mkyoung(entry);
-	mk_pte_huge(entry);
+	int i;
 
 	for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-		set_pte(page_table, entry);
-		page_table++;
-
+		set_pte_at(mm, addr, ptep, entry);
+		ptep++;
+		addr += PAGE_SIZE;
 		pte_val(entry) += PAGE_SIZE;
 	}
 }
 
+pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+			      pte_t *ptep)
+{
+	pte_t entry;
+	int i;
+
+	entry = *ptep;
+
+	for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
+		pte_clear(mm, addr, ptep);
+		addr += PAGE_SIZE;
+		ptep++;
+	}
+
+	return entry;
+}
+
 /*
  * This function checks for proper alignment of input addr and len parameters.
  */
@@ -92,79 +98,6 @@
 	return 0;
 }
 
-int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
-			    struct vm_area_struct *vma)
-{
-	pte_t *src_pte, *dst_pte, entry;
-	struct page *ptepage;
-	unsigned long addr = vma->vm_start;
-	unsigned long end = vma->vm_end;
-	int i;
-
-	while (addr < end) {
-		dst_pte = huge_pte_alloc(dst, addr);
-		if (!dst_pte)
-			goto nomem;
-		src_pte = huge_pte_offset(src, addr);
-		BUG_ON(!src_pte || pte_none(*src_pte));
-		entry = *src_pte;
-		ptepage = pte_page(entry);
-		get_page(ptepage);
-		for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-			set_pte(dst_pte, entry);
-			pte_val(entry) += PAGE_SIZE;
-			dst_pte++;
-		}
-		add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
-		addr += HPAGE_SIZE;
-	}
-	return 0;
-
-nomem:
-	return -ENOMEM;
-}
-
-int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
-			struct page **pages, struct vm_area_struct **vmas,
-			unsigned long *position, int *length, int i)
-{
-	unsigned long vaddr = *position;
-	int remainder = *length;
-
-	WARN_ON(!is_vm_hugetlb_page(vma));
-
-	while (vaddr < vma->vm_end && remainder) {
-		if (pages) {
-			pte_t *pte;
-			struct page *page;
-
-			pte = huge_pte_offset(mm, vaddr);
-
-			/* hugetlb should be locked, and hence, prefaulted */
-			BUG_ON(!pte || pte_none(*pte));
-
-			page = pte_page(*pte);
-
-			WARN_ON(!PageCompound(page));
-
-			get_page(page);
-			pages[i] = page;
-		}
-
-		if (vmas)
-			vmas[i] = vma;
-
-		vaddr += PAGE_SIZE;
-		--remainder;
-		++i;
-	}
-
-	*length = remainder;
-	*position = vaddr;
-
-	return i;
-}
-
 struct page *follow_huge_addr(struct mm_struct *mm,
 			      unsigned long address, int write)
 {
@@ -181,84 +114,3 @@
 {
 	return NULL;
 }
-
-void unmap_hugepage_range(struct vm_area_struct *vma,
-			  unsigned long start, unsigned long end)
-{
-	struct mm_struct *mm = vma->vm_mm;
-	unsigned long address;
-	pte_t *pte;
-	struct page *page;
-	int i;
-
-	BUG_ON(start & (HPAGE_SIZE - 1));
-	BUG_ON(end & (HPAGE_SIZE - 1));
-
-	for (address = start; address < end; address += HPAGE_SIZE) {
-		pte = huge_pte_offset(mm, address);
-		BUG_ON(!pte);
-		if (pte_none(*pte))
-			continue;
-		page = pte_page(*pte);
-		put_page(page);
-		for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-			pte_clear(mm, address+(i*PAGE_SIZE), pte);
-			pte++;
-		}
-	}
-	add_mm_counter(mm, rss, -((end - start) >> PAGE_SHIFT));
-	flush_tlb_range(vma, start, end);
-}
-
-int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
-{
-	struct mm_struct *mm = current->mm;
-	unsigned long addr;
-	int ret = 0;
-
-	BUG_ON(vma->vm_start & ~HPAGE_MASK);
-	BUG_ON(vma->vm_end & ~HPAGE_MASK);
-
-	spin_lock(&mm->page_table_lock);
-	for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
-		unsigned long idx;
-		pte_t *pte = huge_pte_alloc(mm, addr);
-		struct page *page;
-
-		if (!pte) {
-			ret = -ENOMEM;
-			goto out;
-		}
-		if (!pte_none(*pte))
-			continue;
-
-		idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
-			+ (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
-		page = find_get_page(mapping, idx);
-		if (!page) {
-			/* charge the fs quota first */
-			if (hugetlb_get_quota(mapping)) {
-				ret = -ENOMEM;
-				goto out;
-			}
-			page = alloc_huge_page();
-			if (!page) {
-				hugetlb_put_quota(mapping);
-				ret = -ENOMEM;
-				goto out;
-			}
-			ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
-			if (! ret) {
-				unlock_page(page);
-			} else {
-				hugetlb_put_quota(mapping);
-				free_huge_page(page);
-				goto out;
-			}
-		}
-		set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
-	}
-out:
-	spin_unlock(&mm->page_table_lock);
-	return ret;
-}
diff --git a/arch/sh64/Kconfig b/arch/sh64/Kconfig
index 76eb81f..708e5973 100644
--- a/arch/sh64/Kconfig
+++ b/arch/sh64/Kconfig
@@ -217,6 +217,8 @@
 	bool "Preemptible Kernel (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
 
+source "mm/Kconfig"
+
 endmenu
 
 menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)"
diff --git a/arch/sh64/mm/hugetlbpage.c b/arch/sh64/mm/hugetlbpage.c
index bcad2ae..dcd9c8a 100644
--- a/arch/sh64/mm/hugetlbpage.c
+++ b/arch/sh64/mm/hugetlbpage.c
@@ -24,7 +24,7 @@
 #include <asm/tlbflush.h>
 #include <asm/cacheflush.h>
 
-static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
 {
 	pgd_t *pgd;
 	pmd_t *pmd;
@@ -39,7 +39,7 @@
 	return pte;
 }
 
-static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 {
 	pgd_t *pgd;
 	pmd_t *pmd;
@@ -80,6 +80,20 @@
 	}
 }
 
+pte_t huge_ptep_get_and_clear(pte_t *ptep)
+{
+	pte_t entry;
+
+	entry = *ptep;
+
+	for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
+		pte_clear(pte);
+		pte++;
+	}
+
+	return entry;
+}
+
 /*
  * This function checks for proper alignment of input addr and len parameters.
  */
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 237f922..262e13d 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -264,7 +264,11 @@
 	  want to run SunOS binaries on an Ultra you must also say Y to
 	  "Kernel support for 32-bit a.out binaries" above.
 
-source "drivers/parport/Kconfig"
+source "mm/Kconfig"
+
+endmenu
+
+source "drivers/Kconfig"
 
 config PRINTER
 	tristate "Parallel printer support"
@@ -291,6 +295,8 @@
 	  If you have more than 8 printers, you need to increase the LP_NO
 	  macro in lp.c and the PARPORT_MAX macro in parport.h.
 
+source "mm/Kconfig"
+
 endmenu
 
 source "drivers/base/Kconfig"
@@ -372,18 +378,8 @@
 
 endmenu
 
-source "drivers/input/Kconfig"
-
 source "fs/Kconfig"
 
-source "sound/Kconfig"
-
-source "drivers/usb/Kconfig"
-
-source "drivers/infiniband/Kconfig"
-
-source "drivers/char/watchdog/Kconfig"
-
 source "arch/sparc/Kconfig.debug"
 
 source "security/Kconfig"
diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c
index a2dea69..ec2e050 100644
--- a/arch/sparc/mm/init.c
+++ b/arch/sparc/mm/init.c
@@ -384,7 +384,6 @@
 		struct page *page = pfn_to_page(tmp);
 
 		ClearPageReserved(page);
-		set_bit(PG_highmem, &page->flags);
 		set_page_count(page, 1);
 		__free_page(page);
 		totalhigh_pages++;
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index a72fd15..e2b050e 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -484,6 +484,8 @@
 
 	  NOTE: This option WILL override the PROM bootargs setting!
 
+source "mm/Kconfig"
+
 endmenu
 
 source "drivers/base/Kconfig"
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index 7066d7b..bdac631 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -6,7 +6,6 @@
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/kprobes.h>
-
 #include <asm/kdebug.h>
 #include <asm/signal.h>
 
@@ -47,25 +46,59 @@
 {
 	p->ainsn.insn[0] = *p->addr;
 	p->ainsn.insn[1] = BREAKPOINT_INSTRUCTION_2;
+	p->opcode = *p->addr;
+}
+
+void arch_arm_kprobe(struct kprobe *p)
+{
+	*p->addr = BREAKPOINT_INSTRUCTION;
+	flushi(p->addr);
+}
+
+void arch_disarm_kprobe(struct kprobe *p)
+{
+	*p->addr = p->opcode;
+	flushi(p->addr);
 }
 
 void arch_remove_kprobe(struct kprobe *p)
 {
 }
 
-/* kprobe_status settings */
-#define KPROBE_HIT_ACTIVE	0x00000001
-#define KPROBE_HIT_SS		0x00000002
-
 static struct kprobe *current_kprobe;
 static unsigned long current_kprobe_orig_tnpc;
 static unsigned long current_kprobe_orig_tstate_pil;
 static unsigned int kprobe_status;
+static struct kprobe *kprobe_prev;
+static unsigned long kprobe_orig_tnpc_prev;
+static unsigned long kprobe_orig_tstate_pil_prev;
+static unsigned int kprobe_status_prev;
 
-static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+static inline void save_previous_kprobe(void)
+{
+	kprobe_status_prev = kprobe_status;
+	kprobe_orig_tnpc_prev = current_kprobe_orig_tnpc;
+	kprobe_orig_tstate_pil_prev = current_kprobe_orig_tstate_pil;
+	kprobe_prev = current_kprobe;
+}
+
+static inline void restore_previous_kprobe(void)
+{
+	kprobe_status = kprobe_status_prev;
+	current_kprobe_orig_tnpc = kprobe_orig_tnpc_prev;
+	current_kprobe_orig_tstate_pil = kprobe_orig_tstate_pil_prev;
+	current_kprobe = kprobe_prev;
+}
+
+static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs)
 {
 	current_kprobe_orig_tnpc = regs->tnpc;
 	current_kprobe_orig_tstate_pil = (regs->tstate & TSTATE_PIL);
+	current_kprobe = p;
+}
+
+static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
 	regs->tstate |= TSTATE_PIL;
 
 	/*single step inline, if it a breakpoint instruction*/
@@ -78,17 +111,6 @@
 	}
 }
 
-static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
-{
-	*p->addr = p->opcode;
-	flushi(p->addr);
-
-	regs->tpc = (unsigned long) p->addr;
-	regs->tnpc = current_kprobe_orig_tnpc;
-	regs->tstate = ((regs->tstate & ~TSTATE_PIL) |
-			current_kprobe_orig_tstate_pil);
-}
-
 static int kprobe_handler(struct pt_regs *regs)
 {
 	struct kprobe *p;
@@ -109,8 +131,18 @@
 				unlock_kprobes();
 				goto no_kprobe;
 			}
-			disarm_kprobe(p, regs);
-			ret = 1;
+			/* We have reentered the kprobe_handler(), since
+			 * another probe was hit while within the handler.
+			 * We here save the original kprobes variables and
+			 * just single step on the instruction of the new probe
+			 * without calling any user handlers.
+			 */
+			save_previous_kprobe();
+			set_current_kprobe(p, regs);
+			p->nmissed++;
+			kprobe_status = KPROBE_REENTER;
+			prepare_singlestep(p, regs);
+			return 1;
 		} else {
 			p = current_kprobe;
 			if (p->break_handler && p->break_handler(p, regs))
@@ -138,8 +170,8 @@
 		goto no_kprobe;
 	}
 
+	set_current_kprobe(p, regs);
 	kprobe_status = KPROBE_HIT_ACTIVE;
-	current_kprobe = p;
 	if (p->pre_handler && p->pre_handler(p, regs))
 		return 1;
 
@@ -245,12 +277,20 @@
 	if (!kprobe_running())
 		return 0;
 
-	if (current_kprobe->post_handler)
+	if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) {
+		kprobe_status = KPROBE_HIT_SSDONE;
 		current_kprobe->post_handler(current_kprobe, regs, 0);
+	}
 
 	resume_execution(current_kprobe, regs);
 
+	/*Restore back the original saved kprobes variables and continue. */
+	if (kprobe_status == KPROBE_REENTER) {
+		restore_previous_kprobe();
+		goto out;
+	}
 	unlock_kprobes();
+out:
 	preempt_enable_no_resched();
 
 	return 1;
@@ -392,3 +432,4 @@
 	}
 	return 0;
 }
+
diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
index 9a375e97..f28428f 100644
--- a/arch/sparc64/kernel/signal32.c
+++ b/arch/sparc64/kernel/signal32.c
@@ -102,7 +102,7 @@
 
 		/* POSIX.1b timers */
 		struct {
-			timer_t _tid;			/* timer id */
+			compat_timer_t _tid;			/* timer id */
 			int _overrun;			/* overrun count */
 			compat_sigval_t _sigval;		/* same as below */
 			int _sys_private;		/* not to be passed to user */
diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
index 0077f02..5f8c822 100644
--- a/arch/sparc64/kernel/sys_sparc.c
+++ b/arch/sparc64/kernel/sys_sparc.c
@@ -84,6 +84,10 @@
 			return addr;
 	}
 
+	if (len <= mm->cached_hole_size) {
+	        mm->cached_hole_size = 0;
+		mm->free_area_cache = TASK_UNMAPPED_BASE;
+	}
 	start_addr = addr = mm->free_area_cache;
 
 	task_size -= len;
@@ -103,6 +107,7 @@
 		if (task_size < addr) {
 			if (start_addr != TASK_UNMAPPED_BASE) {
 				start_addr = addr = TASK_UNMAPPED_BASE;
+				mm->cached_hole_size = 0;
 				goto full_search;
 			}
 			return -ENOMEM;
@@ -114,6 +119,9 @@
 			mm->free_area_cache = addr + len;
 			return addr;
 		}
+		if (addr + mm->cached_hole_size < vma->vm_start)
+		        mm->cached_hole_size = vma->vm_start - addr;
+
 		addr = vma->vm_end;
 		if (do_color_align)
 			addr = COLOUR_ALIGN(addr, pgoff);
diff --git a/arch/sparc64/lib/delay.c b/arch/sparc64/lib/delay.c
index f6b4c78..e880872 100644
--- a/arch/sparc64/lib/delay.c
+++ b/arch/sparc64/lib/delay.c
@@ -31,7 +31,7 @@
 {
 	n *= 4;
 
-	n *= (cpu_data(_smp_processor_id()).udelay_val * (HZ/4));
+	n *= (cpu_data(raw_smp_processor_id()).udelay_val * (HZ/4));
 	n >>= 32;
 
 	__delay(n + 1);
diff --git a/arch/sparc64/mm/hugetlbpage.c b/arch/sparc64/mm/hugetlbpage.c
index 5a1f831..625cbb3 100644
--- a/arch/sparc64/mm/hugetlbpage.c
+++ b/arch/sparc64/mm/hugetlbpage.c
@@ -22,7 +22,7 @@
 #include <asm/cacheflush.h>
 #include <asm/mmu_context.h>
 
-static pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr)
 {
 	pgd_t *pgd;
 	pud_t *pud;
@@ -41,7 +41,7 @@
 	return pte;
 }
 
-static pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr)
 {
 	pgd_t *pgd;
 	pud_t *pud;
@@ -62,32 +62,36 @@
 
 #define mk_pte_huge(entry) do { pte_val(entry) |= _PAGE_SZHUGE; } while (0)
 
-static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
-			 unsigned long addr,
-			 struct page *page, pte_t * page_table, int write_access)
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+		     pte_t *ptep, pte_t entry)
 {
-	unsigned long i;
-	pte_t entry;
-
-	add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
-
-	if (write_access)
-		entry = pte_mkwrite(pte_mkdirty(mk_pte(page,
-						       vma->vm_page_prot)));
-	else
-		entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot));
-	entry = pte_mkyoung(entry);
-	mk_pte_huge(entry);
+	int i;
 
 	for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-		set_pte_at(mm, addr, page_table, entry);
-		page_table++;
+		set_pte_at(mm, addr, ptep, entry);
+		ptep++;
 		addr += PAGE_SIZE;
-
 		pte_val(entry) += PAGE_SIZE;
 	}
 }
 
+pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+			      pte_t *ptep)
+{
+	pte_t entry;
+	int i;
+
+	entry = *ptep;
+
+	for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
+		pte_clear(mm, addr, ptep);
+		addr += PAGE_SIZE;
+		ptep++;
+	}
+
+	return entry;
+}
+
 /*
  * This function checks for proper alignment of input addr and len parameters.
  */
@@ -100,79 +104,6 @@
 	return 0;
 }
 
-int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
-			    struct vm_area_struct *vma)
-{
-	pte_t *src_pte, *dst_pte, entry;
-	struct page *ptepage;
-	unsigned long addr = vma->vm_start;
-	unsigned long end = vma->vm_end;
-	int i;
-
-	while (addr < end) {
-		dst_pte = huge_pte_alloc(dst, addr);
-		if (!dst_pte)
-			goto nomem;
-		src_pte = huge_pte_offset(src, addr);
-		BUG_ON(!src_pte || pte_none(*src_pte));
-		entry = *src_pte;
-		ptepage = pte_page(entry);
-		get_page(ptepage);
-		for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-			set_pte_at(dst, addr, dst_pte, entry);
-			pte_val(entry) += PAGE_SIZE;
-			dst_pte++;
-			addr += PAGE_SIZE;
-		}
-		add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
-	}
-	return 0;
-
-nomem:
-	return -ENOMEM;
-}
-
-int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
-			struct page **pages, struct vm_area_struct **vmas,
-			unsigned long *position, int *length, int i)
-{
-	unsigned long vaddr = *position;
-	int remainder = *length;
-
-	WARN_ON(!is_vm_hugetlb_page(vma));
-
-	while (vaddr < vma->vm_end && remainder) {
-		if (pages) {
-			pte_t *pte;
-			struct page *page;
-
-			pte = huge_pte_offset(mm, vaddr);
-
-			/* hugetlb should be locked, and hence, prefaulted */
-			BUG_ON(!pte || pte_none(*pte));
-
-			page = pte_page(*pte);
-
-			WARN_ON(!PageCompound(page));
-
-			get_page(page);
-			pages[i] = page;
-		}
-
-		if (vmas)
-			vmas[i] = vma;
-
-		vaddr += PAGE_SIZE;
-		--remainder;
-		++i;
-	}
-
-	*length = remainder;
-	*position = vaddr;
-
-	return i;
-}
-
 struct page *follow_huge_addr(struct mm_struct *mm,
 			      unsigned long address, int write)
 {
@@ -190,34 +121,6 @@
 	return NULL;
 }
 
-void unmap_hugepage_range(struct vm_area_struct *vma,
-			  unsigned long start, unsigned long end)
-{
-	struct mm_struct *mm = vma->vm_mm;
-	unsigned long address;
-	pte_t *pte;
-	struct page *page;
-	int i;
-
-	BUG_ON(start & (HPAGE_SIZE - 1));
-	BUG_ON(end & (HPAGE_SIZE - 1));
-
-	for (address = start; address < end; address += HPAGE_SIZE) {
-		pte = huge_pte_offset(mm, address);
-		BUG_ON(!pte);
-		if (pte_none(*pte))
-			continue;
-		page = pte_page(*pte);
-		put_page(page);
-		for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-			pte_clear(mm, address+(i*PAGE_SIZE), pte);
-			pte++;
-		}
-	}
-	add_mm_counter(mm, rss, -((end - start) >> PAGE_SHIFT));
-	flush_tlb_range(vma, start, end);
-}
-
 static void context_reload(void *__data)
 {
 	struct mm_struct *mm = __data;
@@ -226,12 +129,8 @@
 		load_secondary_context(mm);
 }
 
-int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
+void hugetlb_prefault_arch_hook(struct mm_struct *mm)
 {
-	struct mm_struct *mm = current->mm;
-	unsigned long addr;
-	int ret = 0;
-
 	/* On UltraSPARC-III+ and later, configure the second half of
 	 * the Data-TLB for huge pages.
 	 */
@@ -261,50 +160,4 @@
 		}
 		spin_unlock(&ctx_alloc_lock);
 	}
-
-	BUG_ON(vma->vm_start & ~HPAGE_MASK);
-	BUG_ON(vma->vm_end & ~HPAGE_MASK);
-
-	spin_lock(&mm->page_table_lock);
-	for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
-		unsigned long idx;
-		pte_t *pte = huge_pte_alloc(mm, addr);
-		struct page *page;
-
-		if (!pte) {
-			ret = -ENOMEM;
-			goto out;
-		}
-		if (!pte_none(*pte))
-			continue;
-
-		idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
-			+ (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
-		page = find_get_page(mapping, idx);
-		if (!page) {
-			/* charge the fs quota first */
-			if (hugetlb_get_quota(mapping)) {
-				ret = -ENOMEM;
-				goto out;
-			}
-			page = alloc_huge_page();
-			if (!page) {
-				hugetlb_put_quota(mapping);
-				ret = -ENOMEM;
-				goto out;
-			}
-			ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
-			if (! ret) {
-				unlock_page(page);
-			} else {
-				hugetlb_put_quota(mapping);
-				free_huge_page(page);
-				goto out;
-			}
-		}
-		set_huge_pte(mm, vma, addr, page, pte, vma->vm_flags & VM_WRITE);
-	}
-out:
-	spin_unlock(&mm->page_table_lock);
-	return ret;
 }
diff --git a/arch/sparc64/solaris/socket.c b/arch/sparc64/solaris/socket.c
index ec8e074..0674058 100644
--- a/arch/sparc64/solaris/socket.c
+++ b/arch/sparc64/solaris/socket.c
@@ -317,8 +317,10 @@
 		unsigned long *kcmsg;
 		compat_size_t cmlen;
 
-		if(kern_msg.msg_controllen > sizeof(ctl) &&
-		   kern_msg.msg_controllen <= 256) {
+		if (kern_msg.msg_controllen <= sizeof(compat_size_t))
+			return -EINVAL;
+
+		if(kern_msg.msg_controllen > sizeof(ctl)) {
 			err = -ENOBUFS;
 			ctl_buf = kmalloc(kern_msg.msg_controllen, GFP_KERNEL);
 			if(!ctl_buf)
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index c529218..9469e77 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -35,6 +35,11 @@
 	bool
 	default y
 
+# Used in kernel/irq/manage.c and include/linux/irq.h
+config IRQ_RELEASE_METHOD
+	bool
+	default y
+
 menu "UML-specific options"
 
 config MODE_TT
@@ -69,6 +74,7 @@
 	option will shrink the UML binary slightly.
 
 source "arch/um/Kconfig_arch"
+source "mm/Kconfig"
 
 config LD_SCRIPT_STATIC
 	bool
diff --git a/arch/um/Kconfig_char b/arch/um/Kconfig_char
index 3e50fdb..62d87b7 100644
--- a/arch/um/Kconfig_char
+++ b/arch/um/Kconfig_char
@@ -204,5 +204,11 @@
 	http://sourceforge.net/projects/gkernel/).  rngd periodically reads
 	/dev/hwrng and injects the entropy into /dev/random.
 
+config MMAPPER
+	tristate "iomem emulation driver"
+	help
+	This driver allows a host file to be used as emulated IO memory inside
+	UML.
+
 endmenu
 
diff --git a/arch/um/Makefile b/arch/um/Makefile
index f2a0c40..3f07390 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -122,7 +122,7 @@
 CPPFLAGS_vmlinux.lds = $(shell echo -U$(SUBARCH) \
 	-DSTART=$(START) -DELF_ARCH=$(ELF_ARCH) \
 	-DELF_FORMAT=\"$(ELF_FORMAT)\" $(CPP_MODE-y) \
-	-DKERNEL_STACK_SIZE=$(STACK_SIZE))
+	-DKERNEL_STACK_SIZE=$(STACK_SIZE) -DSUBARCH=$(SUBARCH))
 
 #The wrappers will select whether using "malloc" or the kernel allocator.
 LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile
index 323f72c..b2de991 100644
--- a/arch/um/drivers/Makefile
+++ b/arch/um/drivers/Makefile
@@ -22,8 +22,8 @@
 obj-$(CONFIG_SSL) += ssl.o
 obj-$(CONFIG_STDERR_CONSOLE) += stderr_console.o
 
-obj-$(CONFIG_UML_NET_SLIP) += slip.o
-obj-$(CONFIG_UML_NET_SLIRP) += slirp.o
+obj-$(CONFIG_UML_NET_SLIP) += slip.o slip_common.o
+obj-$(CONFIG_UML_NET_SLIRP) += slirp.o slip_common.o
 obj-$(CONFIG_UML_NET_DAEMON) += daemon.o 
 obj-$(CONFIG_UML_NET_MCAST) += mcast.o 
 #obj-$(CONFIG_UML_NET_PCAP) += pcap.o $(PCAP)
@@ -41,6 +41,6 @@
 obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o
 obj-$(CONFIG_UML_RANDOM) += random.o
 
-USER_OBJS := fd.o null.o pty.o tty.o xterm.o
+USER_OBJS := fd.o null.o pty.o tty.o xterm.o slip_common.o
 
 include arch/um/scripts/Makefile.rules
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index 583b8e1..5d37681 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -143,22 +143,22 @@
 {
 	struct winch_data data;
 	unsigned long stack;
-	int fds[2], pid, n, err;
+	int fds[2], n, err;
 	char c;
 
 	err = os_pipe(fds, 1, 1);
 	if(err < 0){
 		printk("winch_tramp : os_pipe failed, err = %d\n", -err);
-		return(err);
+		goto out;
 	}
 
 	data = ((struct winch_data) { .pty_fd 		= fd,
 				      .pipe_fd 		= fds[1],
 				      .close_me 	= fds[0] } );
-	pid = run_helper_thread(winch_thread, &data, 0, &stack, 0);
-	if(pid < 0){
+	err = run_helper_thread(winch_thread, &data, 0, &stack, 0);
+	if(err < 0){
 		printk("fork of winch_thread failed - errno = %d\n", errno);
-		return(pid);
+		goto out_close;
 	}
 
 	os_close_file(fds[1]);
@@ -168,14 +168,22 @@
 		printk("winch_tramp : failed to read synchronization byte\n");
 		printk("read failed, err = %d\n", -n);
 		printk("fd %d will not support SIGWINCH\n", fd);
-		*fd_out = -1;
+                err = -EINVAL;
+		goto out_close1;
 	}
-	return(pid);
+	return err ;
+
+ out_close:
+	os_close_file(fds[1]);
+ out_close1:
+	os_close_file(fds[0]);
+ out:
+	return err;
 }
 
 void register_winch(int fd, struct tty_struct *tty)
 {
-	int pid, thread, thread_fd;
+	int pid, thread, thread_fd = -1;
 	int count;
 	char c = 1;
 
@@ -186,7 +194,7 @@
 	if(!CHOOSE_MODE_PROC(is_tracer_winch, is_skas_winch, pid, fd,
 			     tty) && (pid == -1)){
 		thread = winch_tramp(fd, tty, &thread_fd);
-		if(fd != -1){
+		if(thread > 0){
 			register_winch_irq(thread_fd, fd, thread, tty);
 
 			count = os_write_file(thread_fd, &c, sizeof(c));
diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c
index cf15b4a..c1b03f7 100644
--- a/arch/um/drivers/daemon_user.c
+++ b/arch/um/drivers/daemon_user.c
@@ -157,9 +157,9 @@
 
 	os_close_file(pri->fd);
 	os_close_file(pri->control);
-	if(pri->data_addr != NULL) kfree(pri->data_addr);
-	if(pri->ctl_addr != NULL) kfree(pri->ctl_addr);
-	if(pri->local_addr != NULL) kfree(pri->local_addr);
+	kfree(pri->data_addr);
+	kfree(pri->ctl_addr);
+	kfree(pri->local_addr);
 }
 
 int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri)
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 025d3be..2bb4c4f 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -406,14 +406,12 @@
 	if(line->driver->read_irq == current_irq)
 		free_irq_later(line->driver->read_irq, tty);
 	else {
-		free_irq_by_irq_and_dev(line->driver->read_irq, tty);
 		free_irq(line->driver->read_irq, tty);
 	}
 
 	if(line->driver->write_irq == current_irq)
 		free_irq_later(line->driver->write_irq, tty);
 	else {
-		free_irq_by_irq_and_dev(line->driver->write_irq, tty);
 		free_irq(line->driver->write_irq, tty);
 	}
 
@@ -604,11 +602,26 @@
 	return n;
 }
 
-int line_remove(struct line *lines, unsigned int num, char *str)
+int line_id(char **str, int *start_out, int *end_out)
+{
+	char *end;
+        int n;
+
+	n = simple_strtoul(*str, &end, 0);
+	if((*end != '\0') || (end == *str))
+                return -1;
+
+        *str = end;
+        *start_out = n;
+        *end_out = n;
+        return n;
+}
+
+int line_remove(struct line *lines, unsigned int num, int n)
 {
 	char config[sizeof("conxxxx=none\0")];
 
-	sprintf(config, "%s=none", str);
+	sprintf(config, "%d=none", n);
 	return !line_setup(lines, num, config, 0);
 }
 
@@ -758,7 +771,6 @@
         if(winch->pid != -1)
                 os_kill_process(winch->pid, 1);
 
-        free_irq_by_irq_and_dev(WINCH_IRQ, winch);
         free_irq(WINCH_IRQ, winch);
         list_del(&winch->list);
         kfree(winch);
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index d7c7adc..404de41 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -419,8 +419,9 @@
 void mconsole_remove(struct mc_request *req)
 {
 	struct mc_device *dev;	
-	char *ptr = req->request.data;
-	int err;
+	char *ptr = req->request.data, *err_msg = "";
+        char error[256];
+	int err, start, end, n;
 
 	ptr += strlen("remove");
 	while(isspace(*ptr)) ptr++;
@@ -429,8 +430,35 @@
 		mconsole_reply(req, "Bad remove option", 1, 0);
 		return;
 	}
-	err = (*dev->remove)(&ptr[strlen(dev->name)]);
-	mconsole_reply(req, "", err, 0);
+
+        ptr = &ptr[strlen(dev->name)];
+
+        err = 1;
+        n = (*dev->id)(&ptr, &start, &end);
+        if(n < 0){
+                err_msg = "Couldn't parse device number";
+                goto out;
+        }
+        else if((n < start) || (n > end)){
+                sprintf(error, "Invalid device number - must be between "
+                        "%d and %d", start, end);
+                err_msg = error;
+                goto out;
+        }
+
+	err = (*dev->remove)(n);
+        switch(err){
+        case -ENODEV:
+                err_msg = "Device doesn't exist";
+                break;
+        case -EBUSY:
+                err_msg = "Device is currently open";
+                break;
+        default:
+                break;
+        }
+ out:
+	mconsole_reply(req, err_msg, err, 0);
 }
 
 #ifdef CONFIG_MAGIC_SYSRQ
diff --git a/arch/um/drivers/mmapper_kern.c b/arch/um/drivers/mmapper_kern.c
index a63231d..a37a5ac 100644
--- a/arch/um/drivers/mmapper_kern.c
+++ b/arch/um/drivers/mmapper_kern.c
@@ -18,6 +18,7 @@
 #include <linux/slab.h>
 #include <linux/init.h> 
 #include <linux/smp_lock.h>
+#include <linux/miscdevice.h>
 #include <asm/uaccess.h>
 #include <asm/irq.h>
 #include <asm/pgtable.h>
@@ -117,24 +118,39 @@
 	.release	= mmapper_release,
 };
 
+static struct miscdevice mmapper_dev = {
+	.minor		= MISC_DYNAMIC_MINOR,
+	.name		= "mmapper",
+	.fops		= &mmapper_fops
+};
+
 static int __init mmapper_init(void)
 {
+	int err;
+
 	printk(KERN_INFO "Mapper v0.1\n");
 
 	v_buf = (char *) find_iomem("mmapper", &mmapper_size);
 	if(mmapper_size == 0){
 		printk(KERN_ERR "mmapper_init - find_iomem failed\n");
-		return(0);
+		goto out;
+	}
+
+	err = misc_register(&mmapper_dev);
+	if(err){
+		printk(KERN_ERR "mmapper - misc_register failed, err = %d\n",
+		       err);
+		goto out;
 	}
 
 	p_buf = __pa(v_buf);
-
-	devfs_mk_cdev(MKDEV(30, 0), S_IFCHR|S_IRUGO|S_IWUGO, "mmapper");
-	return(0);
+out:
+	return 0;
 }
 
 static void mmapper_exit(void)
 {
+	misc_deregister(&mmapper_dev);
 }
 
 module_init(mmapper_init);
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 4eeaf88..1495007 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -146,7 +146,6 @@
 	netif_stop_queue(dev);
 	spin_lock(&lp->lock);
 
-	free_irq_by_irq_and_dev(dev->irq, dev);
 	free_irq(dev->irq, dev);
 	if(lp->close != NULL)
 		(*lp->close)(lp->fd, &lp->user);
@@ -613,25 +612,35 @@
 	return(err);
 }
 
-static int net_remove(char *str)
+static int net_id(char **str, int *start_out, int *end_out)
+{
+        char *end;
+        int n;
+
+	n = simple_strtoul(*str, &end, 0);
+	if((*end != '\0') || (end == *str))
+		return -1;
+
+        *start_out = n;
+        *end_out = n;
+        *str = end;
+        return n;
+}
+
+static int net_remove(int n)
 {
 	struct uml_net *device;
 	struct net_device *dev;
 	struct uml_net_private *lp;
-	char *end;
-	int n;
-
-	n = simple_strtoul(str, &end, 0);
-	if((*end != '\0') || (end == str))
-		return(-1);
 
 	device = find_device(n);
 	if(device == NULL)
-		return(0);
+		return -ENODEV;
 
 	dev = device->dev;
 	lp = dev->priv;
-	if(lp->fd > 0) return(-1);
+	if(lp->fd > 0)
+                return -EBUSY;
 	if(lp->remove != NULL) (*lp->remove)(&lp->user);
 	unregister_netdev(dev);
 	platform_device_unregister(&device->pdev);
@@ -639,13 +648,14 @@
 	list_del(&device->list);
 	kfree(device);
 	free_netdev(dev);
-	return(0);
+	return 0;
 }
 
 static struct mc_device net_mc = {
 	.name		= "eth",
 	.config		= net_config,
 	.get_config	= NULL,
+        .id		= net_id,
 	.remove		= net_remove,
 };
 
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 47229fe..3730d4f 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -32,7 +32,7 @@
 	return(0);
 }
 
-void tap_check_ips(char *gate_addr, char *eth_addr)
+void tap_check_ips(char *gate_addr, unsigned char *eth_addr)
 {
 	int tap_addr[4];
 
diff --git a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
index b5ee074..c41efd2 100644
--- a/arch/um/drivers/port_kern.c
+++ b/arch/um/drivers/port_kern.c
@@ -257,7 +257,6 @@
 		 * connection.  Then we loop here throwing out failed 
 		 * connections until a good one is found.
 		 */
-		free_irq_by_irq_and_dev(TELNETD_IRQ, conn);
 		free_irq(TELNETD_IRQ, conn);
 
 		if(conn->fd >= 0) break;
diff --git a/arch/um/drivers/slip.h b/arch/um/drivers/slip.h
index 495f2f1..bb0dab4 100644
--- a/arch/um/drivers/slip.h
+++ b/arch/um/drivers/slip.h
@@ -1,10 +1,7 @@
 #ifndef __UM_SLIP_H
 #define __UM_SLIP_H
 
-#define BUF_SIZE 1500
- /* two bytes each for a (pathological) max packet of escaped chars +  * 
-  * terminating END char + initial END char                            */
-#define ENC_BUF_SIZE (2 * BUF_SIZE + 2)
+#include "slip_common.h"
 
 struct slip_data {
 	void *dev;
@@ -12,28 +9,12 @@
 	char *addr;
 	char *gate_addr;
 	int slave;
-	char ibuf[ENC_BUF_SIZE];
-	char obuf[ENC_BUF_SIZE];
-	int more; /* more data: do not read fd until ibuf has been drained */
-	int pos;
-	int esc;
+	struct slip_proto slip;
 };
 
 extern struct net_user_info slip_user_info;
 
-extern int set_umn_addr(int fd, char *addr, char *ptp_addr);
 extern int slip_user_read(int fd, void *buf, int len, struct slip_data *pri);
 extern int slip_user_write(int fd, void *buf, int len, struct slip_data *pri);
 
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/slip_common.c b/arch/um/drivers/slip_common.c
new file mode 100644
index 0000000..e89cfc6
--- /dev/null
+++ b/arch/um/drivers/slip_common.c
@@ -0,0 +1,54 @@
+#include <string.h>
+#include "slip_common.h"
+#include "net_user.h"
+
+int slip_proto_read(int fd, void *buf, int len, struct slip_proto *slip)
+{
+	int i, n, size, start;
+
+	if(slip->more > 0){
+		i = 0;
+		while(i < slip->more){
+			size = slip_unesc(slip->ibuf[i++], slip->ibuf,
+					  &slip->pos, &slip->esc);
+			if(size){
+				memcpy(buf, slip->ibuf, size);
+				memmove(slip->ibuf, &slip->ibuf[i],
+					slip->more - i);
+				slip->more = slip->more - i;
+				return size;
+			}
+		}
+		slip->more = 0;
+	}
+
+	n = net_read(fd, &slip->ibuf[slip->pos],
+		     sizeof(slip->ibuf) - slip->pos);
+	if(n <= 0)
+		return n;
+
+	start = slip->pos;
+	for(i = 0; i < n; i++){
+		size = slip_unesc(slip->ibuf[start + i], slip->ibuf,&slip->pos,
+				  &slip->esc);
+		if(size){
+			memcpy(buf, slip->ibuf, size);
+			memmove(slip->ibuf, &slip->ibuf[start+i+1],
+				n - (i + 1));
+			slip->more = n - (i + 1);
+			return size;
+		}
+	}
+	return 0;
+}
+
+int slip_proto_write(int fd, void *buf, int len, struct slip_proto *slip)
+{
+	int actual, n;
+
+	actual = slip_esc(buf, slip->obuf, len);
+	n = net_write(fd, slip->obuf, actual);
+	if(n < 0)
+		return n;
+	else return len;
+}
diff --git a/arch/um/drivers/slip_common.h b/arch/um/drivers/slip_common.h
new file mode 100644
index 0000000..2ae76d8
--- /dev/null
+++ b/arch/um/drivers/slip_common.h
@@ -0,0 +1,104 @@
+#ifndef __UM_SLIP_COMMON_H
+#define __UM_SLIP_COMMON_H
+
+#define BUF_SIZE 1500
+ /* two bytes each for a (pathological) max packet of escaped chars +  *
+  * terminating END char + initial END char                            */
+#define ENC_BUF_SIZE (2 * BUF_SIZE + 2)
+
+/* SLIP protocol characters. */
+#define SLIP_END             0300	/* indicates end of frame	*/
+#define SLIP_ESC             0333	/* indicates byte stuffing	*/
+#define SLIP_ESC_END         0334	/* ESC ESC_END means END 'data'	*/
+#define SLIP_ESC_ESC         0335	/* ESC ESC_ESC means ESC 'data'	*/
+
+static inline int slip_unesc(unsigned char c, unsigned char *buf, int *pos,
+                             int *esc)
+{
+	int ret;
+
+	switch(c){
+	case SLIP_END:
+		*esc = 0;
+		ret=*pos;
+		*pos=0;
+		return(ret);
+	case SLIP_ESC:
+		*esc = 1;
+		return(0);
+	case SLIP_ESC_ESC:
+		if(*esc){
+			*esc = 0;
+			c = SLIP_ESC;
+		}
+		break;
+	case SLIP_ESC_END:
+		if(*esc){
+			*esc = 0;
+			c = SLIP_END;
+		}
+		break;
+	}
+	buf[(*pos)++] = c;
+	return(0);
+}
+
+static inline int slip_esc(unsigned char *s, unsigned char *d, int len)
+{
+	unsigned char *ptr = d;
+	unsigned char c;
+
+	/*
+	 * Send an initial END character to flush out any
+	 * data that may have accumulated in the receiver
+	 * due to line noise.
+	 */
+
+	*ptr++ = SLIP_END;
+
+	/*
+	 * For each byte in the packet, send the appropriate
+	 * character sequence, according to the SLIP protocol.
+	 */
+
+	while (len-- > 0) {
+		switch(c = *s++) {
+		case SLIP_END:
+			*ptr++ = SLIP_ESC;
+			*ptr++ = SLIP_ESC_END;
+			break;
+		case SLIP_ESC:
+			*ptr++ = SLIP_ESC;
+			*ptr++ = SLIP_ESC_ESC;
+			break;
+		default:
+			*ptr++ = c;
+			break;
+		}
+	}
+	*ptr++ = SLIP_END;
+	return (ptr - d);
+}
+
+struct slip_proto {
+	unsigned char ibuf[ENC_BUF_SIZE];
+	unsigned char obuf[ENC_BUF_SIZE];
+	int more; /* more data: do not read fd until ibuf has been drained */
+	int pos;
+	int esc;
+};
+
+#define SLIP_PROTO_INIT { \
+	.ibuf  	= { '\0' }, \
+	.obuf  	= { '\0' }, \
+        .more	= 0, \
+	.pos	= 0, \
+	.esc	= 0 \
+}
+
+extern int slip_proto_read(int fd, void *buf, int len,
+			   struct slip_proto *slip);
+extern int slip_proto_write(int fd, void *buf, int len,
+			    struct slip_proto *slip);
+
+#endif
diff --git a/arch/um/drivers/slip_kern.c b/arch/um/drivers/slip_kern.c
index 0886eed..9a6f5c8 100644
--- a/arch/um/drivers/slip_kern.c
+++ b/arch/um/drivers/slip_kern.c
@@ -26,16 +26,16 @@
 		  .addr		= NULL,
 		  .gate_addr 	= init->gate_addr,
 		  .slave  	= -1,
-		  .ibuf  	= { '\0' },
-		  .obuf  	= { '\0' },
-		  .pos 		= 0,
-		  .esc 		= 0,
+		  .slip		= SLIP_PROTO_INIT,
 		  .dev 		= dev });
 
 	dev->init = NULL;
+	dev->header_cache_update = NULL;
+	dev->hard_header_cache = NULL;
+	dev->hard_header = NULL;
 	dev->hard_header_len = 0;
-	dev->addr_len = 4;
-	dev->type = ARPHRD_ETHER;
+	dev->addr_len = 0;
+	dev->type = ARPHRD_SLIP;
 	dev->tx_queue_len = 256;
 	dev->flags = IFF_NOARP;
 	printk("SLIP backend - SLIP IP = %s\n", spri->gate_addr);
diff --git a/arch/um/drivers/slip_proto.h b/arch/um/drivers/slip_proto.h
deleted file mode 100644
index 7206361..0000000
--- a/arch/um/drivers/slip_proto.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#ifndef __UM_SLIP_PROTO_H__
-#define __UM_SLIP_PROTO_H__
-
-/* SLIP protocol characters. */
-#define SLIP_END             0300	/* indicates end of frame	*/
-#define SLIP_ESC             0333	/* indicates byte stuffing	*/
-#define SLIP_ESC_END         0334	/* ESC ESC_END means END 'data'	*/
-#define SLIP_ESC_ESC         0335	/* ESC ESC_ESC means ESC 'data'	*/
-
-static inline int slip_unesc(unsigned char c,char *buf,int *pos, int *esc)
-{
-	int ret;
-
-	switch(c){
-	case SLIP_END:
-		*esc = 0;
-		ret=*pos;
-		*pos=0;
-		return(ret);
-	case SLIP_ESC:
-		*esc = 1;
-		return(0);
-	case SLIP_ESC_ESC:
-		if(*esc){
-			*esc = 0;
-			c = SLIP_ESC;
-		}
-		break;
-	case SLIP_ESC_END:
-		if(*esc){
-			*esc = 0;
-			c = SLIP_END;
-		}
-		break;
-	}
-	buf[(*pos)++] = c;
-	return(0);
-}
-
-static inline int slip_esc(unsigned char *s, unsigned char *d, int len)
-{
-	unsigned char *ptr = d;
-	unsigned char c;
-
-	/*
-	 * Send an initial END character to flush out any
-	 * data that may have accumulated in the receiver
-	 * due to line noise.
-	 */
-
-	*ptr++ = SLIP_END;
-
-	/*
-	 * For each byte in the packet, send the appropriate
-	 * character sequence, according to the SLIP protocol.
-	 */
-
-	while (len-- > 0) {
-		switch(c = *s++) {
-		case SLIP_END:
-			*ptr++ = SLIP_ESC;
-			*ptr++ = SLIP_ESC_END;
-			break;
-		case SLIP_ESC:
-			*ptr++ = SLIP_ESC;
-			*ptr++ = SLIP_ESC_ESC;
-			break;
-		default:
-			*ptr++ = c;
-			break;
-		}
-	}
-	*ptr++ = SLIP_END;
-	return (ptr - d);
-}
-
-#endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index d94846b..71af444 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -13,7 +13,7 @@
 #include "user.h"
 #include "net_user.h"
 #include "slip.h"
-#include "slip_proto.h"
+#include "slip_common.h"
 #include "helper.h"
 #include "os.h"
 
@@ -77,41 +77,51 @@
 	err = os_pipe(fds, 1, 0);
 	if(err < 0){
 		printk("slip_tramp : pipe failed, err = %d\n", -err);
-		return(err);
+		goto out;
 	}
 
 	err = 0;
 	pe_data.stdin = fd;
 	pe_data.stdout = fds[1];
 	pe_data.close_me = fds[0];
-	pid = run_helper(slip_pre_exec, &pe_data, argv, NULL);
+	err = run_helper(slip_pre_exec, &pe_data, argv, NULL);
+	if(err < 0)
+		goto out_close;
+	pid = err;
 
-	if(pid < 0) err = pid;
-	else {
-		output_len = page_size();
-		output = um_kmalloc(output_len);
-		if(output == NULL)
-			printk("slip_tramp : failed to allocate output "
-			       "buffer\n");
-
-		os_close_file(fds[1]);
-		read_output(fds[0], output, output_len);
-		if(output != NULL){
-			printk("%s", output);
-			kfree(output);
-		}
-		CATCH_EINTR(err = waitpid(pid, &status, 0));
-		if(err < 0)
-			err = errno;
-		else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)){
-			printk("'%s' didn't exit with status 0\n", argv[0]);
-			err = -EINVAL;
-		}
+	output_len = page_size();
+	output = um_kmalloc(output_len);
+	if(output == NULL){
+		printk("slip_tramp : failed to allocate output buffer\n");
+		os_kill_process(pid, 1);
+		err = -ENOMEM;
+		goto out_free;
 	}
 
+	os_close_file(fds[1]);
+	read_output(fds[0], output, output_len);
+	printk("%s", output);
+
+	CATCH_EINTR(err = waitpid(pid, &status, 0));
+	if(err < 0)
+		err = errno;
+	else if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)){
+		printk("'%s' didn't exit with status 0\n", argv[0]);
+		err = -EINVAL;
+	}
+	else err = 0;
+
 	os_close_file(fds[0]);
 
-	return(err);
+out_free:
+	kfree(output);
+	return err;
+
+out_close:
+	os_close_file(fds[0]);
+	os_close_file(fds[1]);
+out:
+	return err;
 }
 
 static int slip_open(void *data)
@@ -123,21 +133,26 @@
 			 NULL };
 	int sfd, mfd, err;
 
-	mfd = get_pty();
-	if(mfd < 0){
-		printk("umn : Failed to open pty, err = %d\n", -mfd);
-		return(mfd);
+	err = get_pty();
+	if(err < 0){
+		printk("slip-open : Failed to open pty, err = %d\n", -err);
+		goto out;
 	}
-	sfd = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0);
-	if(sfd < 0){
-		printk("Couldn't open tty for slip line, err = %d\n", -sfd);
-		os_close_file(mfd);
-		return(sfd);
+	mfd = err;
+
+	err = os_open_file(ptsname(mfd), of_rdwr(OPENFLAGS()), 0);
+	if(err < 0){
+		printk("Couldn't open tty for slip line, err = %d\n", -err);
+		goto out_close;
 	}
-	if(set_up_tty(sfd)) return(-1);
+	sfd = err;
+
+	if(set_up_tty(sfd))
+		goto out_close2;
+
 	pri->slave = sfd;
-	pri->pos = 0;
-	pri->esc = 0;
+	pri->slip.pos = 0;
+	pri->slip.esc = 0;
 	if(pri->gate_addr != NULL){
 		sprintf(version_buf, "%d", UML_NET_VERSION);
 		strcpy(gate_buf, pri->gate_addr);
@@ -146,12 +161,12 @@
 
 		if(err < 0){
 			printk("slip_tramp failed - err = %d\n", -err);
-			return(err);
+			goto out_close2;
 		}
 		err = os_get_ifname(pri->slave, pri->name);
 		if(err < 0){
 			printk("get_ifname failed, err = %d\n", -err);
-			return(err);
+			goto out_close2;
 		}
 		iter_addresses(pri->dev, open_addr, pri->name);
 	}
@@ -160,10 +175,16 @@
 		if(err < 0){
 			printk("Failed to set slip discipline encapsulation - "
 			       "err = %d\n", -err);
-			return(err);
+			goto out_close2;
 		}
 	}
 	return(mfd);
+out_close2:
+	os_close_file(sfd);
+out_close:
+	os_close_file(mfd);
+out:
+	return err;
 }
 
 static void slip_close(int fd, void *data)
@@ -190,48 +211,12 @@
 
 int slip_user_read(int fd, void *buf, int len, struct slip_data *pri)
 {
-	int i, n, size, start;
-
-	if(pri->more>0) {
-		i = 0;
-		while(i < pri->more) {
-			size = slip_unesc(pri->ibuf[i++],
-					pri->ibuf, &pri->pos, &pri->esc);
-			if(size){
-				memcpy(buf, pri->ibuf, size);
-				memmove(pri->ibuf, &pri->ibuf[i], pri->more-i);
-				pri->more=pri->more-i; 
-				return(size);
-			}
-		}
-		pri->more=0;
-	}
-
-	n = net_read(fd, &pri->ibuf[pri->pos], sizeof(pri->ibuf) - pri->pos);
-	if(n <= 0) return(n);
-
-	start = pri->pos;
-	for(i = 0; i < n; i++){
-		size = slip_unesc(pri->ibuf[start + i],
-				pri->ibuf, &pri->pos, &pri->esc);
-		if(size){
-			memcpy(buf, pri->ibuf, size);
-			memmove(pri->ibuf, &pri->ibuf[start+i+1], n-(i+1));
-			pri->more=n-(i+1); 
-			return(size);
-		}
-	}
-	return(0);
+	return slip_proto_read(fd, buf, len, &pri->slip);
 }
 
 int slip_user_write(int fd, void *buf, int len, struct slip_data *pri)
 {
-	int actual, n;
-
-	actual = slip_esc(buf, pri->obuf, len);
-	n = net_write(fd, pri->obuf, actual);
-	if(n < 0) return(n);
-	else return(len);
+	return slip_proto_write(fd, buf, len, &pri->slip);
 }
 
 static int slip_set_mtu(int mtu, void *data)
@@ -267,14 +252,3 @@
 	.delete_address = slip_del_addr,
 	.max_packet	= BUF_SIZE
 };
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/slirp.h b/arch/um/drivers/slirp.h
index 04e407d..6cf88ab 100644
--- a/arch/um/drivers/slirp.h
+++ b/arch/um/drivers/slirp.h
@@ -1,10 +1,7 @@
 #ifndef __UM_SLIRP_H
 #define __UM_SLIRP_H
 
-#define BUF_SIZE 1500
- /* two bytes each for a (pathological) max packet of escaped chars +  * 
-  * terminating END char + initial END char                            */
-#define ENC_BUF_SIZE (2 * BUF_SIZE + 2)
+#include "slip_common.h"
 
 #define SLIRP_MAX_ARGS 100
 /*
@@ -24,28 +21,13 @@
 	struct arg_list_dummy_wrapper argw;
 	int pid;
 	int slave;
-	char ibuf[ENC_BUF_SIZE];
-	char obuf[ENC_BUF_SIZE];
-	int more; /* more data: do not read fd until ibuf has been drained */
-	int pos;
-	int esc;
+	struct slip_proto slip;
 };
 
 extern struct net_user_info slirp_user_info;
 
-extern int set_umn_addr(int fd, char *addr, char *ptp_addr);
 extern int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri);
-extern int slirp_user_write(int fd, void *buf, int len, struct slirp_data *pri);
+extern int slirp_user_write(int fd, void *buf, int len,
+			    struct slirp_data *pri);
 
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/slirp_kern.c b/arch/um/drivers/slirp_kern.c
index c9d6b52..9864d27 100644
--- a/arch/um/drivers/slirp_kern.c
+++ b/arch/um/drivers/slirp_kern.c
@@ -25,10 +25,7 @@
 		{ .argw 	= init->argw,
 		  .pid  	= -1,
 		  .slave  	= -1,
-		  .ibuf  	= { '\0' },
-		  .obuf  	= { '\0' },
-		  .pos 		= 0,
-		  .esc 		= 0,
+		  .slip		= SLIP_PROTO_INIT,
 		  .dev 		= dev });
 
 	dev->init = NULL;
diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c
index c322515..8d91f66 100644
--- a/arch/um/drivers/slirp_user.c
+++ b/arch/um/drivers/slirp_user.c
@@ -12,7 +12,7 @@
 #include "user.h"
 #include "net_user.h"
 #include "slirp.h"
-#include "slip_proto.h"
+#include "slip_common.h"
 #include "helper.h"
 #include "os.h"
 
@@ -48,47 +48,32 @@
 	return(pid);
 }
 
-/* XXX This is just a trivial wrapper around os_pipe */
-static int slirp_datachan(int *mfd, int *sfd)
-{
-	int fds[2], err;
-
-	err = os_pipe(fds, 1, 1);
-	if(err < 0){
-		printk("slirp_datachan: Failed to open pipe, err = %d\n", -err);
-		return(err);
-	}
-
-	*mfd = fds[0];
-	*sfd = fds[1];
-	return(0);
-}
-
 static int slirp_open(void *data)
 {
 	struct slirp_data *pri = data;
-	int sfd, mfd, pid, err;
+	int fds[2], pid, err;
 
-	err = slirp_datachan(&mfd, &sfd);
+	err = os_pipe(fds, 1, 1);
 	if(err)
 		return(err);
 
-	pid = slirp_tramp(pri->argw.argv, sfd);
-
-	if(pid < 0){
-		printk("slirp_tramp failed - errno = %d\n", -pid);
-		os_close_file(sfd);	
-		os_close_file(mfd);	
-		return(pid);
+	err = slirp_tramp(pri->argw.argv, fds[1]);
+	if(err < 0){
+		printk("slirp_tramp failed - errno = %d\n", -err);
+		goto out;
 	}
+	pid = err;
 
-	pri->slave = sfd;
-	pri->pos = 0;
-	pri->esc = 0;
+	pri->slave = fds[1];
+	pri->slip.pos = 0;
+	pri->slip.esc = 0;
+	pri->pid = err;
 
-	pri->pid = pid;
-
-	return(mfd);
+	return(fds[0]);
+out:
+	os_close_file(fds[0]);
+	os_close_file(fds[1]);
+	return err;
 }
 
 static void slirp_close(int fd, void *data)
@@ -129,48 +114,12 @@
 
 int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri)
 {
-	int i, n, size, start;
-
-	if(pri->more>0) {
-		i = 0;
-		while(i < pri->more) {
-			size = slip_unesc(pri->ibuf[i++],
-					pri->ibuf,&pri->pos,&pri->esc);
-			if(size){
-				memcpy(buf, pri->ibuf, size);
-				memmove(pri->ibuf, &pri->ibuf[i], pri->more-i);
-				pri->more=pri->more-i; 
-				return(size);
-			}
-		}
-		pri->more=0;
-	}
-
-	n = net_read(fd, &pri->ibuf[pri->pos], sizeof(pri->ibuf) - pri->pos);
-	if(n <= 0) return(n);
-
-	start = pri->pos;
-	for(i = 0; i < n; i++){
-		size = slip_unesc(pri->ibuf[start + i],
-				pri->ibuf,&pri->pos,&pri->esc);
-		if(size){
-			memcpy(buf, pri->ibuf, size);
-			memmove(pri->ibuf, &pri->ibuf[start+i+1], n-(i+1));
-			pri->more=n-(i+1); 
-			return(size);
-		}
-	}
-	return(0);
+	return slip_proto_read(fd, buf, len, &pri->slip);
 }
 
 int slirp_user_write(int fd, void *buf, int len, struct slirp_data *pri)
 {
-	int actual, n;
-
-	actual = slip_esc(buf, pri->obuf, len);
-	n = net_write(fd, pri->obuf, actual);
-	if(n < 0) return(n);
-	else return(len);
+	return slip_proto_write(fd, buf, len, &pri->slip);
 }
 
 static int slirp_set_mtu(int mtu, void *data)
@@ -188,14 +137,3 @@
 	.delete_address = NULL,
 	.max_packet	= BUF_SIZE
 };
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index b32a770..62e04ec 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -49,7 +49,7 @@
 
 static int ssl_config(char *str);
 static int ssl_get_config(char *dev, char *str, int size, char **error_out);
-static int ssl_remove(char *str);
+static int ssl_remove(int n);
 
 static struct line_driver driver = {
 	.name 			= "UML serial line",
@@ -69,6 +69,7 @@
 		.name  		= "ssl",
 		.config 	= ssl_config,
 		.get_config 	= ssl_get_config,
+                .id		= line_id,
 		.remove 	= ssl_remove,
 	},
 };
@@ -94,10 +95,10 @@
 			       str, size, error_out));
 }
 
-static int ssl_remove(char *str)
+static int ssl_remove(int n)
 {
-	return(line_remove(serial_lines, 
-			   sizeof(serial_lines)/sizeof(serial_lines[0]), str));
+        return line_remove(serial_lines,
+                           sizeof(serial_lines)/sizeof(serial_lines[0]), n);
 }
 
 int ssl_open(struct tty_struct *tty, struct file *filp)
diff --git a/arch/um/drivers/stderr_console.c b/arch/um/drivers/stderr_console.c
index 98565b5..429ae8e 100644
--- a/arch/um/drivers/stderr_console.c
+++ b/arch/um/drivers/stderr_console.c
@@ -22,9 +22,9 @@
 }
 
 static struct console stderr_console = {
-	.name		"stderr",
-	.write		stderr_console_write,
-	.flags		CON_PRINTBUFFER,
+	.name		= "stderr",
+	.write		= stderr_console_write,
+	.flags		= CON_PRINTBUFFER,
 };
 
 static int __init stderr_console_init(void)
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index afbe1e7..005aa63 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -55,7 +55,7 @@
 
 static int con_config(char *str);
 static int con_get_config(char *dev, char *str, int size, char **error_out);
-static int con_remove(char *str);
+static int con_remove(int n);
 
 static struct line_driver driver = {
 	.name 			= "UML console",
@@ -75,6 +75,7 @@
 		.name  		= "con",
 		.config 	= con_config,
 		.get_config 	= con_get_config,
+                .id		= line_id,
 		.remove 	= con_remove,
 	},
 };
@@ -99,9 +100,9 @@
 			       size, error_out));
 }
 
-static int con_remove(char *str)
+static int con_remove(int n)
 {
-	return(line_remove(vts, sizeof(vts)/sizeof(vts[0]), str));
+        return line_remove(vts, sizeof(vts)/sizeof(vts[0]), n);
 }
 
 static int con_open(struct tty_struct *tty, struct file *filp)
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 2a7f689..344b24d 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -754,26 +754,36 @@
 	return(len);
 }
 
-static int ubd_remove(char *str)
+static int ubd_id(char **str, int *start_out, int *end_out)
+{
+        int n;
+
+	n = parse_unit(str);
+        *start_out = 0;
+        *end_out = MAX_DEV - 1;
+        return n;
+}
+
+static int ubd_remove(int n)
 {
 	struct ubd *dev;
-	int n, err = -ENODEV;
+	int err = -ENODEV;
 
-	n = parse_unit(&str);
-
-	if((n < 0) || (n >= MAX_DEV))
-		return(err);
-
-	dev = &ubd_dev[n];
-	if(dev->count > 0)
-		return(-EBUSY);	/* you cannot remove a open disk */
-
-	err = 0;
- 	spin_lock(&ubd_lock);
+	spin_lock(&ubd_lock);
 
 	if(ubd_gendisk[n] == NULL)
 		goto out;
 
+	dev = &ubd_dev[n];
+
+	if(dev->file == NULL)
+		goto out;
+
+	/* you cannot remove a open disk */
+	err = -EBUSY;
+	if(dev->count > 0)
+		goto out;
+
 	del_gendisk(ubd_gendisk[n]);
 	put_disk(ubd_gendisk[n]);
 	ubd_gendisk[n] = NULL;
@@ -787,15 +797,16 @@
 	platform_device_unregister(&dev->pdev);
 	*dev = ((struct ubd) DEFAULT_UBD);
 	err = 0;
- out:
- 	spin_unlock(&ubd_lock);
-	return(err);
+out:
+	spin_unlock(&ubd_lock);
+	return err;
 }
 
 static struct mc_device ubd_mc = {
 	.name		= "ubd",
 	.config		= ubd_config,
  	.get_config	= ubd_get_config,
+	.id		= ubd_id,
 	.remove		= ubd_remove,
 };
 
diff --git a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c
index a4fdf35..d269a80 100644
--- a/arch/um/drivers/xterm_kern.c
+++ b/arch/um/drivers/xterm_kern.c
@@ -69,7 +69,6 @@
 	 * isn't set) this will hang... */
 	wait_for_completion(&data->ready);
 
-	free_irq_by_irq_and_dev(XTERM_IRQ, data);
 	free_irq(XTERM_IRQ, data);
 
 	ret = data->new_fd;
diff --git a/arch/um/include/line.h b/arch/um/include/line.h
index 4c5e92c..5323d22 100644
--- a/arch/um/include/line.h
+++ b/arch/um/include/line.h
@@ -101,7 +101,8 @@
 extern void close_lines(struct line *lines, int nlines);
 
 extern int line_config(struct line *lines, unsigned int sizeof_lines, char *str);
-extern int line_remove(struct line *lines, unsigned int sizeof_lines, char *str);
+extern int line_id(char **str, int *start_out, int *end_out);
+extern int line_remove(struct line *lines, unsigned int sizeof_lines, int n);
 extern int line_get_config(char *dev, struct line *lines, unsigned int sizeof_lines, char *str,
 			   int size, char **error_out);
 
diff --git a/arch/um/include/mconsole.h b/arch/um/include/mconsole.h
index 9fbe308..cfa368e 100644
--- a/arch/um/include/mconsole.h
+++ b/arch/um/include/mconsole.h
@@ -56,7 +56,7 @@
 	int as_interrupt;
 
 	int originating_fd;
-	int originlen;
+	unsigned int originlen;
 	unsigned char origin[128];			/* sockaddr_un */
 
 	struct mconsole_request request;
diff --git a/arch/um/include/mconsole_kern.h b/arch/um/include/mconsole_kern.h
index 61c274f..d86ee14 100644
--- a/arch/um/include/mconsole_kern.h
+++ b/arch/um/include/mconsole_kern.h
@@ -20,7 +20,8 @@
 	char *name;
 	int (*config)(char *);
 	int (*get_config)(char *, char *, int, char **);
-	int (*remove)(char *);
+        int (*id)(char **, int *, int *);
+	int (*remove)(int);
 };
 
 #define CONFIG_CHUNK(str, size, current, chunk, end) \
diff --git a/arch/um/include/net_user.h b/arch/um/include/net_user.h
index 36807b7..89885a7 100644
--- a/arch/um/include/net_user.h
+++ b/arch/um/include/net_user.h
@@ -35,7 +35,7 @@
 extern void free_output_buffer(void *buffer);
 
 extern int tap_open_common(void *dev, char *gate_addr);
-extern void tap_check_ips(char *gate_addr, char *eth_addr);
+extern void tap_check_ips(char *gate_addr, unsigned char *eth_addr);
 
 extern void read_output(int fd, char *output_out, int len);
 
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index d246d5a..881d298 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -136,7 +136,7 @@
 extern int os_open_file(char *file, struct openflags flags, int mode);
 extern int os_read_file(int fd, void *buf, int len);
 extern int os_write_file(int fd, const void *buf, int count);
-extern int os_file_size(char *file, long long *size_out);
+extern int os_file_size(char *file, unsigned long long *size_out);
 extern int os_file_modtime(char *file, unsigned long *modtime);
 extern int os_pipe(int *fd, int stream, int close_on_exec);
 extern int os_set_fd_async(int fd, int owner);
diff --git a/arch/um/include/sysdep-i386/ptrace.h b/arch/um/include/sysdep-i386/ptrace.h
index 6eaeb99..c8ee955 100644
--- a/arch/um/include/sysdep-i386/ptrace.h
+++ b/arch/um/include/sysdep-i386/ptrace.h
@@ -8,6 +8,8 @@
 
 #include "uml-config.h"
 #include "user_constants.h"
+#include "sysdep/faultinfo.h"
+#include "choose-mode.h"
 
 #define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long))
 #define MAX_REG_OFFSET (UM_FRAME_SIZE)
@@ -58,9 +60,6 @@
 #define PTRACE_SYSEMU_SINGLESTEP 32
 #endif
 
-#include "sysdep/faultinfo.h"
-#include "choose-mode.h"
-
 union uml_pt_regs {
 #ifdef UML_CONFIG_MODE_TT
 	struct tt_regs {
diff --git a/arch/um/include/time_user.h b/arch/um/include/time_user.h
index 6793a2f..f64ef77 100644
--- a/arch/um/include/time_user.h
+++ b/arch/um/include/time_user.h
@@ -8,11 +8,11 @@
 
 extern void timer(void);
 extern void switch_timers(int to_real);
-extern void set_interval(int timer_type);
 extern void idle_sleep(int secs);
 extern void enable_timer(void);
 extern void disable_timer(void);
 extern unsigned long time_lock(void);
 extern void time_unlock(unsigned long);
+extern void user_time_init(void);
 
 #endif
diff --git a/arch/um/include/user_util.h b/arch/um/include/user_util.h
index b8c5b8a..7b6a24d 100644
--- a/arch/um/include/user_util.h
+++ b/arch/um/include/user_util.h
@@ -41,9 +41,6 @@
 extern char host_info[];
 
 extern char saved_command_line[];
-extern char command_line[];
-
-extern char *tempdir;
 
 extern unsigned long _stext, _etext, _sdata, _edata, __bss_start, _end;
 extern unsigned long _unprotected_end;
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index d44fb52..9f18061 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -124,14 +124,16 @@
 	spin_unlock_irqrestore(&irq_spinlock, flags);
 }
 
-/*  presently hw_interrupt_type must define (startup || enable) &&
- *  disable && end */
+/* hw_interrupt_type must define (startup || enable) &&
+ * (shutdown || disable) && end */
 static void dummy(unsigned int irq)
 {
 }
 
-static struct hw_interrupt_type SIGIO_irq_type = {
+/* This is used for everything else than the timer. */
+static struct hw_interrupt_type normal_irq_type = {
 	.typename = "SIGIO",
+	.release = free_irq_by_irq_and_dev,
 	.disable = dummy,
 	.enable = dummy,
 	.ack = dummy,
@@ -140,6 +142,7 @@
 
 static struct hw_interrupt_type SIGVTALRM_irq_type = {
 	.typename = "SIGVTALRM",
+	.release = free_irq_by_irq_and_dev,
 	.shutdown = dummy, /* never called */
 	.disable = dummy,
 	.enable = dummy,
@@ -160,7 +163,7 @@
 		irq_desc[i].status = IRQ_DISABLED;
 		irq_desc[i].action = NULL;
 		irq_desc[i].depth = 1;
-		irq_desc[i].handler = &SIGIO_irq_type;
+		irq_desc[i].handler = &normal_irq_type;
 		enable_irq(i);
 	}
 }
diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c
index b3074cb..c3ccaf24 100644
--- a/arch/um/kernel/irq_user.c
+++ b/arch/um/kernel/irq_user.c
@@ -85,8 +85,6 @@
 				next = irq_fd->next;
 				if(irq_fd->freed){
 					free_irq(irq_fd->irq, irq_fd->id);
-					free_irq_by_irq_and_dev(irq_fd->irq,
-								irq_fd->id);
 				}
 			}
 		}
diff --git a/arch/um/kernel/main.c b/arch/um/kernel/main.c
index e42e636..1e1a87f 100644
--- a/arch/um/kernel/main.c
+++ b/arch/um/kernel/main.c
@@ -24,8 +24,6 @@
 #include "mode.h"
 #include "choose-mode.h"
 #include "uml-config.h"
-#include "irq_user.h"
-#include "time_user.h"
 #include "os.h"
 
 /* Set in set_stklim, which is called from main and __wrap_malloc.
@@ -71,7 +69,6 @@
 
 static void last_ditch_exit(int sig)
 {
-        kmalloc_ok = 0;
 	signal(SIGINT, SIG_DFL);
 	signal(SIGTERM, SIG_DFL);
 	signal(SIGHUP, SIG_DFL);
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index c22825f..5597bd3 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -53,7 +53,6 @@
 	for(i = 0; i < highmem_len >> PAGE_SHIFT; i++){
 		page = &mem_map[highmem_pfn + i];
 		ClearPageReserved(page);
-		set_bit(PG_highmem, &page->flags);
 		set_page_count(page, 1);
 		__free_page(page);
 	}
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 51f8e5a..1b5ef3e 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -30,7 +30,6 @@
 #include "init.h"
 #include "os.h"
 #include "uml-config.h"
-#include "ptrace_user.h"
 #include "choose-mode.h"
 #include "mode.h"
 #ifdef UML_CONFIG_MODE_SKAS
@@ -131,7 +130,7 @@
 	return(arg.pid);
 }
 
-static int ptrace_child(void *arg)
+static int ptrace_child(void)
 {
 	int ret;
 	int pid = os_getpid(), ppid = getppid();
@@ -160,20 +159,16 @@
 	_exit(ret);
 }
 
-static int start_ptraced_child(void **stack_out)
+static int start_ptraced_child(void)
 {
-	void *stack;
-	unsigned long sp;
 	int pid, n, status;
 	
-	stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
-		     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-	if(stack == MAP_FAILED)
-		panic("check_ptrace : mmap failed, errno = %d", errno);
-	sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
-	pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL);
+	pid = fork();
+	if(pid == 0)
+		ptrace_child();
+
 	if(pid < 0)
-		panic("check_ptrace : clone failed, errno = %d", errno);
+		panic("check_ptrace : fork failed, errno = %d", errno);
 	CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
 	if(n < 0)
 		panic("check_ptrace : wait failed, errno = %d", errno);
@@ -181,7 +176,6 @@
 		panic("check_ptrace : expected SIGSTOP, got status = %d",
 		      status);
 
-	*stack_out = stack;
 	return(pid);
 }
 
@@ -189,12 +183,12 @@
  * just avoid using sysemu, not panic, but only if SYSEMU features are broken.
  * So only for SYSEMU features we test mustpanic, while normal host features
  * must work anyway!*/
-static int stop_ptraced_child(int pid, void *stack, int exitcode, int mustpanic)
+static int stop_ptraced_child(int pid, int exitcode, int mustexit)
 {
 	int status, n, ret = 0;
 
 	if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
-		panic("check_ptrace : ptrace failed, errno = %d", errno);
+		panic("stop_ptraced_child : ptrace failed, errno = %d", errno);
 	CATCH_EINTR(n = waitpid(pid, &status, 0));
 	if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) {
 		int exit_with = WEXITSTATUS(status);
@@ -205,15 +199,13 @@
 		printk("check_ptrace : child exited with exitcode %d, while "
 		      "expecting %d; status 0x%x", exit_with,
 		      exitcode, status);
-		if (mustpanic)
+		if (mustexit)
 			panic("\n");
 		else
 			printk("\n");
 		ret = -1;
 	}
 
-	if(munmap(stack, PAGE_SIZE) < 0)
-		panic("check_ptrace : munmap failed, errno = %d", errno);
 	return ret;
 }
 
@@ -235,12 +227,11 @@
 
 static void __init check_sysemu(void)
 {
-	void *stack;
 	int pid, syscall, n, status, count=0;
 
 	printk("Checking syscall emulation patch for ptrace...");
 	sysemu_supported = 0;
-	pid = start_ptraced_child(&stack);
+	pid = start_ptraced_child();
 
 	if(ptrace(PTRACE_SYSEMU, pid, 0, 0) < 0)
 		goto fail;
@@ -258,7 +249,7 @@
 		panic("check_sysemu : failed to modify system "
 		      "call return, errno = %d", errno);
 
-	if (stop_ptraced_child(pid, stack, 0, 0) < 0)
+	if (stop_ptraced_child(pid, 0, 0) < 0)
 		goto fail_stopped;
 
 	sysemu_supported = 1;
@@ -266,7 +257,7 @@
 	set_using_sysemu(!force_sysemu_disabled);
 
 	printk("Checking advanced syscall emulation patch for ptrace...");
-	pid = start_ptraced_child(&stack);
+	pid = start_ptraced_child();
 	while(1){
 		count++;
 		if(ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0)
@@ -291,7 +282,7 @@
 			break;
 		}
 	}
-	if (stop_ptraced_child(pid, stack, 0, 0) < 0)
+	if (stop_ptraced_child(pid, 0, 0) < 0)
 		goto fail_stopped;
 
 	sysemu_supported = 2;
@@ -302,18 +293,17 @@
 	return;
 
 fail:
-	stop_ptraced_child(pid, stack, 1, 0);
+	stop_ptraced_child(pid, 1, 0);
 fail_stopped:
 	printk("missing\n");
 }
 
 void __init check_ptrace(void)
 {
-	void *stack;
 	int pid, syscall, n, status;
 
 	printk("Checking that ptrace can change system call numbers...");
-	pid = start_ptraced_child(&stack);
+	pid = start_ptraced_child();
 
 	if (ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
 		panic("check_ptrace: PTRACE_SETOPTIONS failed, errno = %d", errno);
@@ -340,7 +330,7 @@
 			break;
 		}
 	}
-	stop_ptraced_child(pid, stack, 0, 1);
+	stop_ptraced_child(pid, 0, 1);
 	printk("OK\n");
 	check_sysemu();
 }
@@ -372,11 +362,10 @@
 static inline int check_skas3_ptrace_support(void)
 {
 	struct ptrace_faultinfo fi;
-	void *stack;
 	int pid, n, ret = 1;
 
 	printf("Checking for the skas3 patch in the host...");
-	pid = start_ptraced_child(&stack);
+	pid = start_ptraced_child();
 
 	n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi);
 	if (n < 0) {
@@ -391,7 +380,7 @@
 	}
 
 	init_registers(pid);
-	stop_ptraced_child(pid, stack, 1, 1);
+	stop_ptraced_child(pid, 1, 1);
 
 	return(ret);
 }
diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
index 804c6bb..d4036ed 100644
--- a/arch/um/kernel/process_kern.c
+++ b/arch/um/kernel/process_kern.c
@@ -8,6 +8,7 @@
 #include "linux/kernel.h"
 #include "linux/sched.h"
 #include "linux/interrupt.h"
+#include "linux/string.h"
 #include "linux/mm.h"
 #include "linux/slab.h"
 #include "linux/utsname.h"
@@ -95,8 +96,8 @@
 
 	current->thread.request.u.thread.proc = fn;
 	current->thread.request.u.thread.arg = arg;
-	pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0, NULL, 0, NULL,
-		      NULL);
+	pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0,
+		      &current->thread.regs, 0, NULL, NULL);
 	if(pid < 0)
 		panic("do_fork failed in kernel_thread, errno = %d", pid);
 	return(pid);
@@ -168,7 +169,7 @@
 
 void default_idle(void)
 {
-	uml_idle_timer();
+	CHOOSE_MODE(uml_idle_timer(), (void) 0);
 
 	atomic_inc(&init_mm.mm_count);
 	current->mm = &init_mm;
@@ -322,12 +323,7 @@
 
 char *uml_strdup(char *string)
 {
-	char *new;
-
-	new = kmalloc(strlen(string) + 1, GFP_KERNEL);
-	if(new == NULL) return(NULL);
-	strcpy(new, string);
-	return(new);
+	return kstrdup(string, GFP_KERNEL);
 }
 
 int copy_to_user_proc(void __user *to, void *from, int size)
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index 207f89d..fcec51d 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -38,14 +38,14 @@
 
 void uml_cleanup(void)
 {
-	kill_off_processes();
+        kmalloc_ok = 0;
 	do_uml_exitcalls();
+	kill_off_processes();
 }
 
 void machine_restart(char * __unused)
 {
-	do_uml_exitcalls();
-	kill_off_processes();
+        uml_cleanup();
 	CHOOSE_MODE(reboot_tt(), reboot_skas());
 }
 
@@ -53,8 +53,7 @@
 
 void machine_power_off(void)
 {
-	do_uml_exitcalls();
-	kill_off_processes();
+        uml_cleanup();
 	CHOOSE_MODE(halt_tt(), halt_skas());
 }
 
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index d37d1bf..ff69c4b 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -4,10 +4,10 @@
 #
 
 obj-y := exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \
-	syscall_kern.o syscall_user.o time.o tlb.o trap_user.o uaccess.o \
+	syscall_kern.o syscall_user.o tlb.o trap_user.o uaccess.o \
 
 subdir- := util
 
-USER_OBJS := process.o time.o
+USER_OBJS := process.o
 
 include arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/skas/include/mode-skas.h b/arch/um/kernel/skas/include/mode-skas.h
index c1e33bd..bcd26a6 100644
--- a/arch/um/kernel/skas/include/mode-skas.h
+++ b/arch/um/kernel/skas/include/mode-skas.h
@@ -13,7 +13,6 @@
 extern unsigned long exec_fpx_regs[];
 extern int have_fpx_regs;
 
-extern void user_time_init_skas(void);
 extern void sig_handler_common_skas(int sig, void *sc_ptr);
 extern void halt_skas(void);
 extern void reboot_skas(void);
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index ab5d327..0a7b8aa 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -68,8 +68,11 @@
 	 * 0 if it just exits
 	 */
 	n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
-	if(n == 1)
+	if(n == 1){
+		/* Handle any immediate reschedules or signals */
+		interrupt_end();
 		userspace(&current->thread.regs.regs);
+	}
 	else do_exit(0);
 }
 
@@ -96,6 +99,8 @@
 	schedule_tail(current->thread.prev_sched);
 	current->thread.prev_sched = NULL;
 
+	/* Handle any immediate reschedules or signals */
+	interrupt_end();
 	userspace(&current->thread.regs.regs);
 }
 
@@ -106,8 +111,7 @@
   	void (*handler)(int);
 
 	if(current->thread.forking){
-	  	memcpy(&p->thread.regs.regs.skas, 
-		       &current->thread.regs.regs.skas, 
+	  	memcpy(&p->thread.regs.regs.skas, &regs->regs.skas,
 		       sizeof(p->thread.regs.regs.skas));
 		REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0);
 		if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp;
@@ -176,7 +180,6 @@
 	start_userspace(0);
 
 	init_new_thread_signals(1);
-	uml_idle_timer();
 
 	init_task.thread.request.u.thread.proc = start_kernel_proc;
 	init_task.thread.request.u.thread.arg = NULL;
@@ -196,14 +199,3 @@
 #warning Need to look up userspace_pid by cpu
 	return(userspace_pid[0]);
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/skas/time.c b/arch/um/kernel/skas/time.c
deleted file mode 100644
index 9809149..0000000
--- a/arch/um/kernel/skas/time.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* 
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <sys/signal.h>
-#include <sys/time.h>
-#include "time_user.h"
-#include "process.h"
-#include "user.h"
-
-void user_time_init_skas(void)
-{
-        if(signal(SIGALRM, (__sighandler_t) alarm_handler) == SIG_ERR)
-                panic("Couldn't set SIGALRM handler");
- 	if(signal(SIGVTALRM, (__sighandler_t) alarm_handler) == SIG_ERR)
- 		panic("Couldn't set SIGVTALRM handler");
-	set_interval(ITIMER_VIRTUAL);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c
index b7a5525..8e1a350 100644
--- a/arch/um/kernel/syscall_kern.c
+++ b/arch/um/kernel/syscall_kern.c
@@ -31,7 +31,8 @@
 	long ret;
 
 	current->thread.forking = 1;
-        ret = do_fork(SIGCHLD, 0, NULL, 0, NULL, NULL);
+	ret = do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
+		      &current->thread.regs, 0, NULL, NULL);
 	current->thread.forking = 0;
 	return(ret);
 }
@@ -41,8 +42,9 @@
 	long ret;
 
 	current->thread.forking = 1;
-	ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, NULL, 0, NULL,
-		      NULL);
+	ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
+		      UPT_SP(&current->thread.regs.regs),
+		      &current->thread.regs, 0, NULL, NULL);
 	current->thread.forking = 0;
 	return(ret);
 }
@@ -162,14 +164,3 @@
 	spin_unlock(&syscall_lock);
 	return(ret);
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index c40c86a..f829b30 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -33,7 +33,7 @@
 	timeradd(&xtime, &local_offset, &xtime);
 }
 
-void set_interval(int timer_type)
+static void set_interval(int timer_type)
 {
 	int usec = 1000000/hz();
 	struct itimerval interval = ((struct itimerval) { { 0, usec },
@@ -45,12 +45,7 @@
 
 void enable_timer(void)
 {
-	int usec = 1000000/hz();
-	struct itimerval enable = ((struct itimerval) { { 0, usec },
-							{ 0, usec }});
-	if(setitimer(ITIMER_VIRTUAL, &enable, NULL))
-		printk("enable_timer - setitimer failed, errno = %d\n",
-		       errno);
+	set_interval(ITIMER_VIRTUAL);
 }
 
 void disable_timer(void)
@@ -155,13 +150,15 @@
 	nanosleep(&ts, NULL);
 }
 
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+/* XXX This partly duplicates init_irq_signals */
+
+void user_time_init(void)
+{
+	set_handler(SIGVTALRM, (__sighandler_t) alarm_handler,
+		    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH,
+		    SIGALRM, SIGUSR2, -1);
+	set_handler(SIGALRM, (__sighandler_t) alarm_handler,
+		    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH,
+		    SIGVTALRM, SIGUSR2, -1);
+	set_interval(ITIMER_VIRTUAL);
+}
diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c
index 6516fc5..a8b4ef6 100644
--- a/arch/um/kernel/time_kern.c
+++ b/arch/um/kernel/time_kern.c
@@ -162,7 +162,7 @@
 {
 	int err;
 
-	CHOOSE_MODE(user_time_init_tt(), user_time_init_skas());
+	user_time_init();
 	err = request_irq(TIMER_IRQ, um_timer, SA_INTERRUPT, "timer", NULL);
 	if(err != 0)
 		printk(KERN_ERR "timer_init : request_irq failed - "
diff --git a/arch/um/kernel/tt/Makefile b/arch/um/kernel/tt/Makefile
index c3faea2..6939e5a 100644
--- a/arch/um/kernel/tt/Makefile
+++ b/arch/um/kernel/tt/Makefile
@@ -3,27 +3,12 @@
 # Licensed under the GPL
 #
 
-extra-y := unmap_fin.o
-targets := unmap.o
-clean-files := unmap_tmp.o
-
 obj-y = exec_kern.o exec_user.o gdb.o ksyms.o mem.o mem_user.o process_kern.o \
-	syscall_kern.o syscall_user.o time.o tlb.o tracer.o trap_user.o \
+	syscall_kern.o syscall_user.o tlb.o tracer.o trap_user.o \
 	uaccess.o uaccess_user.o
 
 obj-$(CONFIG_PT_PROXY) += gdb_kern.o ptproxy/
 
-USER_OBJS := gdb.o time.o tracer.o
+USER_OBJS := gdb.o tracer.o
 
 include arch/um/scripts/Makefile.rules
-
-UNMAP_CFLAGS := $(patsubst -pg -DPROFILING,,$(USER_CFLAGS))
-UNMAP_CFLAGS := $(patsubst -fprofile-arcs -ftest-coverage,,$(UNMAP_CFLAGS))
-
-#XXX: partially copied from arch/um/scripts/Makefile.rules
-$(obj)/unmap.o: c_flags = -Wp,-MD,$(depfile) $(UNMAP_CFLAGS)
-
-$(obj)/unmap_fin.o : $(obj)/unmap.o
-	$(LD) -r -o $(obj)/unmap_tmp.o $< $(shell $(CC) -print-file-name=libc.a)
-	$(OBJCOPY) $(obj)/unmap_tmp.o $@ -G switcheroo
-
diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c
index 19a0ad7..37e22d7 100644
--- a/arch/um/kernel/tt/gdb.c
+++ b/arch/um/kernel/tt/gdb.c
@@ -153,10 +153,10 @@
 	exit_debugger_cb(NULL);
 }
 
-int gdb_remove(char *unused)
+int gdb_remove(int unused)
 {
 	initial_thread_cb(remove_gdb_cb, NULL);
-	return(0);
+        return 0;
 }
 
 void signal_usr1(int sig)
diff --git a/arch/um/kernel/tt/gdb_kern.c b/arch/um/kernel/tt/gdb_kern.c
index 93fb121..2650638 100644
--- a/arch/um/kernel/tt/gdb_kern.c
+++ b/arch/um/kernel/tt/gdb_kern.c
@@ -10,7 +10,7 @@
 #ifdef CONFIG_MCONSOLE
 
 extern int gdb_config(char *str);
-extern int gdb_remove(char *unused);
+extern int gdb_remove(int n);
 
 static struct mc_device gdb_mc = {
 	.name		= "gdb",
diff --git a/arch/um/kernel/tt/include/debug.h b/arch/um/kernel/tt/include/debug.h
index 8eff674..7384354 100644
--- a/arch/um/kernel/tt/include/debug.h
+++ b/arch/um/kernel/tt/include/debug.h
@@ -4,8 +4,8 @@
  * Licensed under the GPL
  */
 
-#ifndef __DEBUG_H
-#define __DEBUG_H
+#ifndef __UML_TT_DEBUG_H
+#define __UML_TT_DEBUG_H
 
 extern int debugger_proxy(int status, pid_t pid);
 extern void child_proxy(pid_t pid, int status);
@@ -13,17 +13,6 @@
 extern int start_debugger(char *prog, int startup, int stop, int *debugger_fd);
 extern void fake_child_exit(void);
 extern int gdb_config(char *str);
-extern int gdb_remove(char *unused);
+extern int gdb_remove(int unused);
 
 #endif
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/include/mode-tt.h b/arch/um/kernel/tt/include/mode-tt.h
index efe4620..e171e15 100644
--- a/arch/um/kernel/tt/include/mode-tt.h
+++ b/arch/um/kernel/tt/include/mode-tt.h
@@ -13,7 +13,6 @@
 extern int tracing_pid;
 
 extern int tracer(int (*init_proc)(void *), void *sp);
-extern void user_time_init_tt(void);
 extern void sig_handler_common_tt(int sig, void *sc);
 extern void syscall_handler_tt(int sig, union uml_pt_regs *regs);
 extern void reboot_tt(void);
diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
index 776310f..a189a2b 100644
--- a/arch/um/kernel/tt/process_kern.c
+++ b/arch/um/kernel/tt/process_kern.c
@@ -266,10 +266,10 @@
 	}
 
 	if(current->thread.forking){
-		sc_to_sc(UPT_SC(&p->thread.regs.regs), 
-			 UPT_SC(&current->thread.regs.regs));
+		sc_to_sc(UPT_SC(&p->thread.regs.regs), UPT_SC(&regs->regs));
 		SC_SET_SYSCALL_RETURN(UPT_SC(&p->thread.regs.regs), 0);
-		if(sp != 0) SC_SP(UPT_SC(&p->thread.regs.regs)) = sp;
+		if(sp != 0)
+			SC_SP(UPT_SC(&p->thread.regs.regs)) = sp;
 	}
 	p->thread.mode.tt.extern_pid = new_pid;
 
@@ -459,14 +459,3 @@
 	read_unlock(&tasklist_lock);
 	return(0);
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/time.c b/arch/um/kernel/tt/time.c
deleted file mode 100644
index 8565b71..0000000
--- a/arch/um/kernel/tt/time.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/* 
- * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <signal.h>
-#include <sys/time.h>
-#include <time_user.h>
-#include "process.h"
-#include "user.h"
-
-void user_time_init_tt(void)
-{
-	if(signal(SIGVTALRM, (__sighandler_t) alarm_handler) == SIG_ERR)
-		panic("Couldn't set SIGVTALRM handler");
-	set_interval(ITIMER_VIRTUAL);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/tt/unmap.c b/arch/um/kernel/tt/unmap.c
deleted file mode 100644
index 3f7aecd..0000000
--- a/arch/um/kernel/tt/unmap.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/* 
- * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include <sys/mman.h>
-
-int switcheroo(int fd, int prot, void *from, void *to, int size)
-{
-	if(munmap(to, size) < 0){
-		return(-1);
-	}
-	if(mmap(to, size, prot,	MAP_SHARED | MAP_FIXED, fd, 0) != to){
-		return(-1);
-	}
-	if(munmap(from, size) < 0){
-		return(-1);
-	}
-	return(0);
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index 4184271..8736d09 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -26,7 +26,6 @@
 #include "asm/setup.h"
 #include "ubd_user.h"
 #include "asm/current.h"
-#include "asm/setup.h"
 #include "user_util.h"
 #include "kern_util.h"
 #include "kern.h"
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
index dd53555..61dfd4f 100644
--- a/arch/um/kernel/uml.lds.S
+++ b/arch/um/kernel/uml.lds.S
@@ -14,19 +14,10 @@
   /* Used in arch/um/kernel/mem.c. Any memory between START and __binary_start
    * is remapped.*/
   __binary_start = .;
-#ifdef MODE_TT
-  .thread_private : {
-    __start_thread_private = .;
-    errno = .;
-    . += 4;
-    arch/um/kernel/tt/unmap_fin.o (.data)
-    __end_thread_private = .;
-  }
-  . = ALIGN(4096);
-  .remap : { arch/um/kernel/tt/unmap_fin.o (.text) }
 
-  /* We want it only if we are in MODE_TT. In both cases, however, when MODE_TT
-   * is off the resulting binary segfaults.*/
+#ifdef MODE_TT
+  .remap_data : { arch/um/sys-SUBARCH/unmap_fin.o (.data .bss) }
+  .remap : { arch/um/sys-SUBARCH/unmap_fin.o (.text) }
 
   . = ALIGN(4096);		/* Init code and data */
 #endif
diff --git a/arch/um/os-Linux/elf_aux.c b/arch/um/os-Linux/elf_aux.c
index 9aee0b6..f0d6060 100644
--- a/arch/um/os-Linux/elf_aux.c
+++ b/arch/um/os-Linux/elf_aux.c
@@ -45,7 +45,11 @@
 				elf_aux_hwcap = auxv->a_un.a_val;
 				break;
 			case AT_PLATFORM:
-				elf_aux_platform = auxv->a_un.a_ptr;
+                                /* elf.h removed the pointer elements from
+                                 * a_un, so we have to use a_val, which is
+                                 * all that's left.
+                                 */
+				elf_aux_platform = (char *) auxv->a_un.a_val;
 				break;
 			case AT_PAGESZ:
 				page_size = auxv->a_un.a_val;
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index 77d4066..fd45bb2 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -363,7 +363,7 @@
 		       (int (*)(int, void *, int)) write, copy_to_user_proc));
 }
 
-int os_file_size(char *file, long long *size_out)
+int os_file_size(char *file, unsigned long long *size_out)
 {
 	struct uml_stat buf;
 	int err;
diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules
index 0b24918..7459d09 100644
--- a/arch/um/scripts/Makefile.rules
+++ b/arch/um/scripts/Makefile.rules
@@ -10,11 +10,17 @@
 $(USER_OBJS) : c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) \
 	$(CFLAGS_$(notdir $@))
 
+# The stubs and unmap.o can't try to call mcount or update basic block data
+define unprofile
+	$(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1)))
+endef
+
+
 quiet_cmd_make_link = SYMLINK $@
 cmd_make_link       = ln -sf $(srctree)/arch/$(SUBARCH)/$($(notdir $@)-dir)/$(notdir $@) $@
 
 # this needs to be before the foreach, because targets does not accept
-# complete paths like $(obj)/$(f). To make sure this works, use a := assignment,
+# complete paths like $(obj)/$(f). To make sure this works, use a := assignment
 # or we will get $(obj)/$(f) in the "targets" value.
 # Also, this forces you to use the := syntax when assigning to targets.
 # Otherwise the line below will cause an infinite loop (if you don't know why,
diff --git a/arch/um/scripts/Makefile.unmap b/arch/um/scripts/Makefile.unmap
new file mode 100644
index 0000000..37a8f97
--- /dev/null
+++ b/arch/um/scripts/Makefile.unmap
@@ -0,0 +1,22 @@
+clean-files += unmap_tmp.o unmap_fin.o unmap.o
+
+ifdef CONFIG_MODE_TT
+
+#Always build unmap_fin.o
+extra-y += unmap_fin.o
+#Do dependency tracking for unmap.o (it will be always built, but won't get the tracking unless we use this).
+targets += unmap.o
+
+#XXX: partially copied from arch/um/scripts/Makefile.rules
+$(obj)/unmap.o: _c_flags = $(call unprofile,$(CFLAGS))
+
+quiet_cmd_wrapld = LD      $@
+define cmd_wrapld
+	$(LD) -r -o $(obj)/unmap_tmp.o $< $(shell $(CC) -print-file-name=libc.a); \
+	$(OBJCOPY) $(obj)/unmap_tmp.o $@ -G switcheroo
+endef
+
+$(obj)/unmap_fin.o : $(obj)/unmap.o FORCE
+	$(call if_changed,wrapld)
+
+endif
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index 4351e56..095bcdb 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -17,3 +17,5 @@
 module.c-dir = kernel
 
 subdir- := util
+
+include arch/um/scripts/Makefile.unmap
diff --git a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
index 03913ca..4efc69a 100644
--- a/arch/um/sys-i386/signal.c
+++ b/arch/um/sys-i386/signal.c
@@ -312,7 +312,7 @@
 	unsigned long __user *extramask = frame->extramask;
 	int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
 
-	if(copy_from_user(&set.sig[0], oldmask, sizeof(&set.sig[0])) ||
+	if(copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) ||
 	   copy_from_user(&set.sig[1], extramask, sig_size))
 		goto segfault;
 
diff --git a/arch/um/sys-i386/syscalls.c b/arch/um/sys-i386/syscalls.c
index 335e2d8..83e9be8 100644
--- a/arch/um/sys-i386/syscalls.c
+++ b/arch/um/sys-i386/syscalls.c
@@ -69,15 +69,11 @@
 {
 	long ret;
 
-	/* XXX: normal arch do here this pass, and also pass the regs to
-	 * do_fork, instead of NULL. Currently the arch-independent code
-	 * ignores these values, while the UML code (actually it's
-	 * copy_thread) does the right thing. But this should change,
-	 probably. */
-	/*if (!newsp)
-		newsp = UPT_SP(current->thread.regs);*/
+	if (!newsp)
+		newsp = UPT_SP(&current->thread.regs.regs);
 	current->thread.forking = 1;
-	ret = do_fork(clone_flags, newsp, NULL, 0, parent_tid, child_tid);
+	ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
+		      child_tid);
 	current->thread.forking = 0;
 	return(ret);
 }
@@ -197,14 +193,3 @@
 
 	return ret;
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/sys-i386/unmap.c b/arch/um/sys-i386/unmap.c
new file mode 100644
index 0000000..1368752
--- /dev/null
+++ b/arch/um/sys-i386/unmap.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <linux/mman.h>
+#include <asm/unistd.h>
+
+static int errno;
+
+static inline _syscall2(int,munmap,void *,start,size_t,len)
+static inline _syscall6(void *,mmap2,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset)
+int switcheroo(int fd, int prot, void *from, void *to, int size)
+{
+	if(munmap(to, size) < 0){
+		return(-1);
+	}
+	if(mmap2(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) != to){
+		return(-1);
+	}
+	if(munmap(from, size) < 0){
+		return(-1);
+	}
+	return(0);
+}
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index 608466a..2bc6f68 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -29,3 +29,5 @@
 module.c-dir = kernel
 
 subdir- := util
+
+include arch/um/scripts/Makefile.unmap
diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
index 6f44f40..3259a4d 100644
--- a/arch/um/sys-x86_64/syscalls.c
+++ b/arch/um/sys-x86_64/syscalls.c
@@ -174,26 +174,11 @@
 {
 	long ret;
 
-	/* XXX: normal arch do here this pass, and also pass the regs to
-	 * do_fork, instead of NULL. Currently the arch-independent code
-	 * ignores these values, while the UML code (actually it's
-	 * copy_thread) does the right thing. But this should change,
-	 probably. */
-	/*if (!newsp)
-		newsp = UPT_SP(current->thread.regs);*/
+	if (!newsp)
+		newsp = UPT_SP(&current->thread.regs.regs);
 	current->thread.forking = 1;
-	ret = do_fork(clone_flags, newsp, NULL, 0, parent_tid, child_tid);
+	ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
+		      child_tid);
 	current->thread.forking = 0;
 	return(ret);
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/sys-x86_64/unmap.c b/arch/um/sys-x86_64/unmap.c
new file mode 100644
index 0000000..bc7094c
--- /dev/null
+++ b/arch/um/sys-x86_64/unmap.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2000 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <linux/mman.h>
+#include <asm/unistd.h>
+
+static int errno;
+
+static inline _syscall2(int,munmap,void *,start,size_t,len)
+static inline _syscall6(void *,mmap,void *,addr,size_t,len,int,prot,int,flags,int,fd,off_t,offset)
+int switcheroo(int fd, int prot, void *from, void *to, int size)
+{
+	if(munmap(to, size) < 0){
+		return(-1);
+	}
+	if(mmap(to, size, prot, MAP_SHARED | MAP_FIXED, fd, 0) != to){
+		return(-1);
+	}
+	if(munmap(from, size) < 0){
+		return(-1);
+	}
+	return(0);
+}
diff --git a/arch/v850/Kconfig b/arch/v850/Kconfig
index 90cd4ba..27febd6 100644
--- a/arch/v850/Kconfig
+++ b/arch/v850/Kconfig
@@ -218,6 +218,8 @@
 	     a lot of RAM, and you need to able to allocate very large
 	     contiguous chunks. If unsure, say N.
 
+source "mm/Kconfig"
+
 endmenu
 
 
diff --git a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
index 289f448..d09437b 100644
--- a/arch/x86_64/Kconfig
+++ b/arch/x86_64/Kconfig
@@ -207,33 +207,6 @@
 
 	  If you don't know what to do here, say N.
 
-config PREEMPT
-	bool "Preemptible Kernel"
-	---help---
-	  This option reduces the latency of the kernel when reacting to
-	  real-time or interactive events by allowing a low priority process to
-	  be preempted even if it is in kernel mode executing a system call.
-	  This allows applications to run more reliably even when the system is
-	  under load. On contrary it may also break your drivers and add
-	  priority inheritance problems to your system. Don't select it if
-	  you rely on a stable system or have slightly obscure hardware.
-	  It's also not very well tested on x86-64 currently.
-	  You have been warned.
-
-	  Say Y here if you are feeling brave and building a kernel for a
-	  desktop, embedded or real-time system.  Say N if you are unsure.
-
-config PREEMPT_BKL
-	bool "Preempt The Big Kernel Lock"
-	depends on PREEMPT
-	default y
-	help
-	  This option reduces the latency of the kernel by making the
-	  big kernel lock preemptible.
-
-	  Say Y here if you are building a kernel for a desktop system.
-	  Say N if you are unsure.
-
 config SCHED_SMT
 	bool "SMT (Hyperthreading) scheduler support"
 	depends on SMP
@@ -244,6 +217,8 @@
 	  cost of slightly increased overhead in some places. If unsure say
 	  N here.
 
+source "kernel/Kconfig.preempt"
+
 config K8_NUMA
        bool "K8 NUMA support"
        select NUMA
@@ -265,7 +240,7 @@
 	  into virtual nodes when booted with "numa=fake=N", where N is the
 	  number of nodes. This is only useful for debugging.
 
-config DISCONTIGMEM
+config ARCH_DISCONTIGMEM_ENABLE
        bool
        depends on NUMA
        default y
@@ -274,6 +249,27 @@
        bool
        default n
 
+config ARCH_DISCONTIGMEM_ENABLE
+	def_bool y
+	depends on NUMA
+
+config ARCH_DISCONTIGMEM_DEFAULT
+	def_bool y
+	depends on NUMA
+
+config ARCH_SPARSEMEM_ENABLE
+	def_bool y
+	depends on NUMA
+
+config ARCH_FLATMEM_ENABLE
+	def_bool y
+	depends on !NUMA
+
+source "mm/Kconfig"
+
+config HAVE_ARCH_EARLY_PFN_TO_NID
+	def_bool y
+
 config HAVE_DEC_LOCK
 	bool
 	depends on SMP
@@ -292,6 +288,15 @@
 	  This is purely to save memory - each supported CPU requires
 	  memory in the static kernel configuration.
 
+config HOTPLUG_CPU
+	bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
+	depends on SMP && HOTPLUG && EXPERIMENTAL
+	help
+		Say Y here to experiment with turning CPUs off and on.  CPUs
+		can be controlled through /sys/devices/system/cpu/cpu#.
+		Say N if you want to disable CPU hotplug.
+
+
 config HPET_TIMER
 	bool
 	default y
@@ -364,6 +369,34 @@
 	   Additional support for intel specific MCE features such as
 	   the thermal monitor.
 
+config PHYSICAL_START
+	hex "Physical address where the kernel is loaded" if EMBEDDED
+	default "0x100000"
+	help
+	  This gives the physical address where the kernel is loaded.
+	  Primarily used in the case of kexec on panic where the
+	  fail safe kernel needs to run at a different address than
+	  the panic-ed kernel.
+
+	  Don't change this unless you know what you are doing.
+
+config KEXEC
+	bool "kexec system call (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	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
+	  you can start any kernel with it, not just Linux.
+
+	  The name comes from the similiarity to the exec system call.
+
+	  It is an ongoing process to be certain the hardware in a machine
+	  is properly shutdown, so do not be surprised if this code does not
+	  initially work for you.  It may help to enable device hotplugging
+	  support.  As of this writing the exact hardware interface is
+	  strongly in flux, so no good recommendation can be made.
+
 config SECCOMP
 	bool "Enable seccomp to safely compute untrusted bytecode"
 	depends on PROC_FS
@@ -381,6 +414,8 @@
 
 	  If unsure, say Y. Only embedded should say N here.
 
+source kernel/Kconfig.hz
+
 endmenu
 
 #
diff --git a/arch/x86_64/Makefile b/arch/x86_64/Makefile
index 6f90c24..8a73794 100644
--- a/arch/x86_64/Makefile
+++ b/arch/x86_64/Makefile
@@ -35,7 +35,7 @@
 
 LDFLAGS		:= -m elf_x86_64
 OBJCOPYFLAGS	:= -O binary -R .note -R .comment -S
-LDFLAGS_vmlinux := -e stext
+LDFLAGS_vmlinux :=
 
 CHECKFLAGS      += -D__x86_64__ -m64
 
diff --git a/arch/x86_64/boot/compressed/head.S b/arch/x86_64/boot/compressed/head.S
index 27264db..6f55565 100644
--- a/arch/x86_64/boot/compressed/head.S
+++ b/arch/x86_64/boot/compressed/head.S
@@ -2,8 +2,6 @@
  *  linux/boot/head.S
  *
  *  Copyright (C) 1991, 1992, 1993  Linus Torvalds
- *
- *  $Id: head.S,v 1.3 2001/04/20 00:59:28 ak Exp $	 		
  */
 
 /*
@@ -21,13 +19,14 @@
  */
 
 /*
- * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996	
+ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
  */
 .code32
 .text
 
 #include <linux/linkage.h>
 #include <asm/segment.h>
+#include <asm/page.h>
 
 	.code32
 	.globl startup_32
@@ -77,7 +76,7 @@
 	jnz  3f
 	addl $8,%esp
 	xorl %ebx,%ebx
-	ljmp $(__KERNEL_CS), $0x100000
+	ljmp $(__KERNEL_CS), $__PHYSICAL_START
 
 /*
  * We come here, if we were loaded high.
@@ -103,7 +102,7 @@
 	popl %ecx	# lcount
 	popl %edx	# high_buffer_start
 	popl %eax	# hcount
-	movl $0x100000,%edi
+	movl $__PHYSICAL_START,%edi
 	cli		# make sure we don't get interrupted
 	ljmp $(__KERNEL_CS), $0x1000 # and jump to the move routine
 
@@ -128,7 +127,7 @@
 	movsl
 	movl %ebx,%esi	# Restore setup pointer
 	xorl %ebx,%ebx
-	ljmp $(__KERNEL_CS), $0x100000
+	ljmp $(__KERNEL_CS), $__PHYSICAL_START
 move_routine_end:
 
 
diff --git a/arch/x86_64/boot/compressed/misc.c b/arch/x86_64/boot/compressed/misc.c
index c8b9216..b38d5b8 100644
--- a/arch/x86_64/boot/compressed/misc.c
+++ b/arch/x86_64/boot/compressed/misc.c
@@ -11,6 +11,7 @@
 
 #include "miscsetup.h"
 #include <asm/io.h>
+#include <asm/page.h>
 
 /*
  * gzip declarations
@@ -92,8 +93,11 @@
 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 putstr(const char *);
-  
+
 extern int end;
 static long free_mem_ptr = (long)&end;
 static long free_mem_end_ptr;
@@ -284,7 +288,7 @@
 #else
 	if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory");
 #endif
-	output_data = (char *)0x100000; /* Points to 1M */
+	output_data = (char *)__PHYSICAL_START; /* Normally Points to 1M */
 	free_mem_end_ptr = (long)real_mode;
 }
 
@@ -307,8 +311,8 @@
 	low_buffer_size = low_buffer_end - LOW_BUFFER_START;
 	high_loaded = 1;
 	free_mem_end_ptr = (long)high_buffer_start;
-	if ( (0x100000 + low_buffer_size) > ((ulg)high_buffer_start)) {
-		high_buffer_start = (uch *)(0x100000 + low_buffer_size);
+	if ( (__PHYSICAL_START + low_buffer_size) > ((ulg)high_buffer_start)) {
+		high_buffer_start = (uch *)(__PHYSICAL_START + low_buffer_size);
 		mv->hcount = 0; /* say: we need not to move high_buffer */
 	}
 	else mv->hcount = -1;
diff --git a/arch/x86_64/boot/install.sh b/arch/x86_64/boot/install.sh
index 90f2452..198af15 100644
--- a/arch/x86_64/boot/install.sh
+++ b/arch/x86_64/boot/install.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# arch/i386/boot/install.sh
+# arch/x86_64/boot/install.sh
 #
 # 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
@@ -21,8 +21,8 @@
 
 # User may have a custom install script
 
-if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi
-if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi
+if [ -x ~/bin/${CROSS_COMPILE}installkernel ]; then exec ~/bin/${CROSS_COMPILE}installkernel "$@"; fi
+if [ -x /sbin/${CROSS_COMPILE}installkernel ]; then exec /sbin/${CROSS_COMPILE}installkernel "$@"; fi
 
 # Default install - same as make zlilo
 
diff --git a/arch/x86_64/boot/setup.S b/arch/x86_64/boot/setup.S
index 75d4d2a..ff58b28 100644
--- a/arch/x86_64/boot/setup.S
+++ b/arch/x86_64/boot/setup.S
@@ -33,7 +33,7 @@
  * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999.
  * <stiker@northlink.com>
  *
- * Fix to work around buggy BIOSes which dont use carry bit correctly
+ * Fix to work around buggy BIOSes which don't use carry bit correctly
  * and/or report extended memory in CX/DX for e801h memory size detection 
  * call.  As a result the kernel got wrong figures.  The int15/e801h docs
  * from Ralf Brown interrupt list seem to indicate AX/BX should be used
@@ -383,7 +383,7 @@
 # a whole bunch of different types, and allows memory holes and
 # everything.  We scan through this memory map and build a list
 # of the first 32 memory areas, which we return at [E820MAP].
-# This is documented at http://www.teleport.com/~acpi/acpihtml/topic245.htm
+# This is documented at http://www.acpi.info/, in the ACPI 2.0 specification.
 
 #define SMAP  0x534d4150
 
@@ -436,7 +436,7 @@
 
 meme801:
 	stc					# fix to work around buggy
-	xorw	%cx,%cx				# BIOSes which dont clear/set
+	xorw	%cx,%cx				# BIOSes which don't clear/set
 	xorw	%dx,%dx				# carry on pass/error of
 						# e801h memory size call
 						# or merely pass cx,dx though
@@ -733,7 +733,7 @@
 #
 #	but we yet haven't reloaded the CS register, so the default size 
 #	of the target offset still is 16 bit.
-#       However, using an operant prefix (0x66), the CPU will properly
+#	However, using an operand prefix (0x66), the CPU will properly
 #	take our 48 bit far pointer. (INTeL 80386 Programmer's Reference
 #	Manual, Mixing 16-bit and 32-bit code, page 16-6)
 
diff --git a/arch/x86_64/boot/tools/build.c b/arch/x86_64/boot/tools/build.c
index c2fa663..18b5bac 100644
--- a/arch/x86_64/boot/tools/build.c
+++ b/arch/x86_64/boot/tools/build.c
@@ -1,6 +1,4 @@
 /*
- *  $Id: build.c,v 1.3 2001/06/26 15:14:50 pavel Exp $
- *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *  Copyright (C) 1997 Martin Mares
  */
@@ -8,7 +6,8 @@
 /*
  * This file builds a disk-image from three different files:
  *
- * - bootsect: exactly 512 bytes of 8086 machine code, loads the rest
+ * - bootsect: compatibility mbr which prints an error message if
+ *             someone tries to boot the kernel directly.
  * - setup: 8086 machine code, sets up system parm
  * - system: 80386 code for actual system
  *
diff --git a/arch/x86_64/ia32/ia32_aout.c b/arch/x86_64/ia32/ia32_aout.c
index 1965efc..c12edf5 100644
--- a/arch/x86_64/ia32/ia32_aout.c
+++ b/arch/x86_64/ia32/ia32_aout.c
@@ -312,6 +312,7 @@
 	current->mm->brk = ex.a_bss +
 		(current->mm->start_brk = N_BSSADDR(ex));
 	current->mm->free_area_cache = TASK_UNMAPPED_BASE;
+	current->mm->cached_hole_size = 0;
 
 	set_mm_counter(current->mm, rss, 0);
 	current->mm->mmap = NULL;
diff --git a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c
index 99b5220..c8131f3 100644
--- a/arch/x86_64/ia32/ia32_binfmt.c
+++ b/arch/x86_64/ia32/ia32_binfmt.c
@@ -46,7 +46,7 @@
 
 #define IA32_EMULATOR 1
 
-#define ELF_ET_DYN_BASE		(TASK_UNMAPPED_32 + 0x1000000)
+#define ELF_ET_DYN_BASE		(TASK_UNMAPPED_BASE + 0x1000000)
 
 #undef ELF_ARCH
 #define ELF_ARCH EM_386
@@ -307,9 +307,6 @@
 
 #define elf_addr_t __u32
 
-#undef TASK_SIZE
-#define TASK_SIZE 0xffffffff
-
 static void elf32_init(struct pt_regs *);
 
 #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
diff --git a/arch/x86_64/ia32/ia32_signal.c b/arch/x86_64/ia32/ia32_signal.c
index fbd09b5..66e2821 100644
--- a/arch/x86_64/ia32/ia32_signal.c
+++ b/arch/x86_64/ia32/ia32_signal.c
@@ -428,8 +428,8 @@
 	return (void __user *)((rsp - frame_size) & -8UL);
 }
 
-void ia32_setup_frame(int sig, struct k_sigaction *ka,
-			compat_sigset_t *set, struct pt_regs * regs)
+int ia32_setup_frame(int sig, struct k_sigaction *ka,
+		     compat_sigset_t *set, struct pt_regs * regs)
 {
 	struct sigframe __user *frame;
 	int err = 0;
@@ -514,14 +514,15 @@
 		current->comm, current->pid, frame, regs->rip, frame->pretcode);
 #endif
 
-	return;
+	return 1;
 
 give_sigsegv:
 	force_sigsegv(sig, current);
+	return 0;
 }
 
-void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-			   compat_sigset_t *set, struct pt_regs * regs)
+int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+			compat_sigset_t *set, struct pt_regs * regs)
 {
 	struct rt_sigframe __user *frame;
 	int err = 0;
@@ -613,9 +614,9 @@
 		current->comm, current->pid, frame, regs->rip, frame->pretcode);
 #endif
 
-	return;
+	return 1;
 
 give_sigsegv:
 	force_sigsegv(sig, current);
+	return 0;
 }
-
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index f3ca0db..cc93542 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -589,7 +589,7 @@
 	.quad compat_sys_mq_timedreceive	/* 280 */
 	.quad compat_sys_mq_notify
 	.quad compat_sys_mq_getsetattr
-	.quad quiet_ni_syscall		/* reserved for kexec */
+	.quad compat_sys_kexec_load	/* reserved for kexec */
 	.quad compat_sys_waitid
 	.quad quiet_ni_syscall		/* sys_altroot */
 	.quad sys_add_key
diff --git a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile
index 5ca4a45..48f9e2c 100644
--- a/arch/x86_64/kernel/Makefile
+++ b/arch/x86_64/kernel/Makefile
@@ -20,6 +20,7 @@
 obj-$(CONFIG_X86_LOCAL_APIC)	+= apic.o  nmi.o
 obj-$(CONFIG_X86_IO_APIC)	+= io_apic.o mpparse.o \
 		genapic.o genapic_cluster.o genapic_flat.o
+obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o crash.o
 obj-$(CONFIG_PM)		+= suspend.o
 obj-$(CONFIG_SOFTWARE_SUSPEND)	+= suspend_asm.o
 obj-$(CONFIG_CPU_FREQ)		+= cpufreq/
diff --git a/arch/x86_64/kernel/acpi/wakeup.S b/arch/x86_64/kernel/acpi/wakeup.S
index a4c6300..185faa9 100644
--- a/arch/x86_64/kernel/acpi/wakeup.S
+++ b/arch/x86_64/kernel/acpi/wakeup.S
@@ -67,7 +67,7 @@
 	shll	$4, %eax
 	addl	$(gdta - wakeup_code), %eax
 	movl	%eax, gdt_48a +2 - wakeup_code
-	lgdt	%ds:gdt_48a - wakeup_code		# load gdt with whatever is
+	lgdtl	%ds:gdt_48a - wakeup_code	# load gdt with whatever is
 						# appropriate
 
 	movl	$1, %eax			# protected mode (PE) bit
diff --git a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c
index a491f72..c9a6b81 100644
--- a/arch/x86_64/kernel/aperture.c
+++ b/arch/x86_64/kernel/aperture.c
@@ -33,20 +33,14 @@
 
 int fix_aperture __initdata = 1;
 
-#define NB_ID_3 (PCI_VENDOR_ID_AMD | (0x1103<<16))
+/* This code runs before the PCI subsystem is initialized, so just
+   access the northbridge directly. */
 
-static struct resource aper_res = {
-	.name = "Aperture",
-	.flags = IORESOURCE_MEM,
-};
+#define NB_ID_3 (PCI_VENDOR_ID_AMD | (0x1103<<16))
 
 static u32 __init allocate_aperture(void) 
 {
-#ifdef CONFIG_DISCONTIGMEM
 	pg_data_t *nd0 = NODE_DATA(0);
-#else
-	pg_data_t *nd0 = &contig_page_data;
-#endif	
 	u32 aper_size;
 	void *p; 
 
@@ -55,24 +49,11 @@
 	aper_size = (32 * 1024 * 1024) << fallback_aper_order; 
 
 	/* 
-	 * Aperture has to be naturally aligned. This means an 2GB
-	 * aperture won't have much chances to find a place in the
-	 * lower 4GB of memory.  Unfortunately we cannot move it up
-	 * because that would make the IOMMU useless.
+	 * Aperture has to be naturally aligned. This means an 2GB aperture won't
+	 * have much chances to find a place in the lower 4GB of memory.
+	 * Unfortunately we cannot move it up because that would make the
+	 * IOMMU useless.
 	 */
-
-	/* First try to find some free unused space */
-	if (!allocate_resource(&iomem_resource, &aper_res,
-			       aper_size,
-			       0, 0xffffffff,
-			       aper_size,
-			       NULL, NULL)) {
-		printk(KERN_INFO "Putting aperture at %lx-%lx\n",
-		       aper_res.start, aper_res.end);
-		return aper_res.start;
-	}
-
-	/* No free space found. Go on to waste some memory... */
 	p = __alloc_bootmem_node(nd0, aper_size, aper_size, 0); 
 	if (!p || __pa(p)+aper_size > 0xffffffff) {
 		printk("Cannot allocate aperture memory hole (%p,%uK)\n",
@@ -81,7 +62,7 @@
 			free_bootmem_node(nd0, (unsigned long)p, aper_size); 
 		return 0;
 	}
-	printk("Mapping aperture over %d KB of precious RAM @ %lx\n",
+	printk("Mapping aperture over %d KB of RAM @ %lx\n",
 	       aper_size >> 10, __pa(p)); 
 	return (u32)__pa(p); 
 }
@@ -102,16 +83,10 @@
 		printk("Aperture from %s pointing to e820 RAM. Ignoring.\n",name);
 		return 0; 
 	} 
-	/* Don't check the resource here because the aperture is usually
-	   in an e820 reserved area, and we allocated these earlier. */
 	return 1;
 } 
 
-/*
- * Find a PCI capability.
- * This code runs before the PCI subsystem is initialized, so just
- * access the northbridge directly.
- */
+/* Find a PCI capability */
 static __u32 __init find_cap(int num, int slot, int func, int cap) 
 { 
 	u8 pos;
@@ -276,6 +251,8 @@
 		   fallback_aper_force) { 
 		printk("Your BIOS doesn't leave a aperture memory hole\n");
 		printk("Please enable the IOMMU option in the BIOS setup\n");
+		printk("This costs you %d MB of RAM\n",
+		       32 << fallback_aper_order);
 
 		aper_order = fallback_aper_order;
 		aper_alloc = allocate_aperture();
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c
index f8e6cc4..375d369 100644
--- a/arch/x86_64/kernel/apic.c
+++ b/arch/x86_64/kernel/apic.c
@@ -133,7 +133,7 @@
 	}
 }
 
-void disconnect_bsp_APIC(void)
+void disconnect_bsp_APIC(int virt_wire_setup)
 {
 	if (pic_mode) {
 		/*
@@ -146,6 +146,42 @@
 		outb(0x70, 0x22);
 		outb(0x00, 0x23);
 	}
+	else {
+		/* Go back to Virtual Wire compatibility mode */
+		unsigned long value;
+
+		/* For the spurious interrupt use vector F, and enable it */
+		value = apic_read(APIC_SPIV);
+		value &= ~APIC_VECTOR_MASK;
+		value |= APIC_SPIV_APIC_ENABLED;
+		value |= 0xf;
+		apic_write_around(APIC_SPIV, value);
+
+		if (!virt_wire_setup) {
+			/* For LVT0 make it edge triggered, active high, external and enabled */
+			value = apic_read(APIC_LVT0);
+			value &= ~(APIC_MODE_MASK | APIC_SEND_PENDING |
+				APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
+				APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED );
+			value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
+			value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_EXTINT);
+			apic_write_around(APIC_LVT0, value);
+		}
+		else {
+			/* Disable LVT0 */
+			apic_write_around(APIC_LVT0, APIC_LVT_MASKED);
+		}
+
+		/* For LVT1 make it edge triggered, active high, nmi and enabled */
+		value = apic_read(APIC_LVT1);
+		value &= ~(
+			APIC_MODE_MASK | APIC_SEND_PENDING |
+			APIC_INPUT_POLARITY | APIC_LVT_REMOTE_IRR |
+			APIC_LVT_LEVEL_TRIGGER | APIC_LVT_MASKED);
+		value |= APIC_LVT_REMOTE_IRR | APIC_SEND_PENDING;
+		value = SET_APIC_DELIVERY_MODE(value, APIC_MODE_NMI);
+		apic_write_around(APIC_LVT1, value);
+	}
 }
 
 void disable_local_APIC(void)
@@ -285,7 +321,7 @@
 	apic_write_around(APIC_LVT1, value);
 }
 
-void __init setup_local_APIC (void)
+void __cpuinit setup_local_APIC (void)
 {
 	unsigned int value, ver, maxlvt;
 
@@ -534,7 +570,7 @@
 	.cls		= &lapic_sysclass,
 };
 
-static void __init apic_pm_activate(void)
+static void __cpuinit apic_pm_activate(void)
 {
 	apic_pm_state.active = 1;
 }
@@ -774,14 +810,14 @@
 	local_irq_enable();
 }
 
-void __init setup_secondary_APIC_clock(void)
+void __cpuinit setup_secondary_APIC_clock(void)
 {
 	local_irq_disable(); /* FIXME: Do we need this? --RR */
 	setup_APIC_timer(calibration_result);
 	local_irq_enable();
 }
 
-void __init disable_APIC_timer(void)
+void __cpuinit disable_APIC_timer(void)
 {
 	if (using_apic_timer) {
 		unsigned long v;
diff --git a/arch/x86_64/kernel/crash.c b/arch/x86_64/kernel/crash.c
new file mode 100644
index 0000000..d7fa424
--- /dev/null
+++ b/arch/x86_64/kernel/crash.c
@@ -0,0 +1,35 @@
+/*
+ * Architecture specific (x86_64) functions for kexec based crash dumps.
+ *
+ * Created by: Hariprasad Nellitheertha (hari@in.ibm.com)
+ *
+ * Copyright (C) IBM Corporation, 2004. All rights reserved.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <linux/irq.h>
+#include <linux/reboot.h>
+#include <linux/kexec.h>
+
+#include <asm/processor.h>
+#include <asm/hardirq.h>
+#include <asm/nmi.h>
+#include <asm/hw_irq.h>
+
+note_buf_t crash_notes[NR_CPUS];
+
+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.
+	 * The minimum amount of code to allow a kexec'd kernel
+	 * to run successfully needs to happen here.
+	 *
+	 * In practice this means shooting down the other cpus in
+	 * an SMP system.
+	 */
+}
diff --git a/arch/x86_64/kernel/e820.c b/arch/x86_64/kernel/e820.c
index 7c154df..6ded3a5 100644
--- a/arch/x86_64/kernel/e820.c
+++ b/arch/x86_64/kernel/e820.c
@@ -16,6 +16,7 @@
 #include <linux/bootmem.h>
 #include <linux/ioport.h>
 #include <linux/string.h>
+#include <linux/kexec.h>
 #include <asm/page.h>
 #include <asm/e820.h>
 #include <asm/proto.h>
@@ -191,8 +192,6 @@
 	int i;
 	for (i = 0; i < e820.nr_map; i++) {
 		struct resource *res;
-		if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)
-			continue;
 		res = alloc_bootmem_low(sizeof(struct resource));
 		switch (e820.map[i].type) {
 		case E820_RAM:	res->name = "System RAM"; break;
@@ -212,6 +211,9 @@
 			 */
 			request_resource(res, &code_resource);
 			request_resource(res, &data_resource);
+#ifdef CONFIG_KEXEC
+			request_resource(res, &crashk_res);
+#endif
 		}
 	}
 }
diff --git a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c
index e3a19e8..9631c74 100644
--- a/arch/x86_64/kernel/early_printk.c
+++ b/arch/x86_64/kernel/early_printk.c
@@ -2,20 +2,24 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/string.h>
+#include <linux/tty.h>
 #include <asm/io.h>
 #include <asm/processor.h>
 
 /* Simple VGA output */
 
 #ifdef __i386__
+#include <asm/setup.h>
 #define VGABASE		(__ISA_IO_base + 0xb8000)
 #else
+#include <asm/bootsetup.h>
 #define VGABASE		((void __iomem *)0xffffffff800b8000UL)
 #endif
 
-#define MAX_YPOS	25
-#define MAX_XPOS	80
+#define MAX_YPOS	max_ypos
+#define MAX_XPOS	max_xpos
 
+static int max_ypos = 25, max_xpos = 80;
 static int current_ypos = 1, current_xpos = 0; 
 
 static void early_vga_write(struct console *con, const char *str, unsigned n)
@@ -196,7 +200,10 @@
 	} else if (!strncmp(buf, "ttyS", 4)) { 
 		early_serial_init(buf);
 		early_console = &early_serial_console;		
-	} else if (!strncmp(buf, "vga", 3)) {
+	} else if (!strncmp(buf, "vga", 3)
+	           && SCREEN_INFO.orig_video_isVGA == 1) {
+		max_xpos = SCREEN_INFO.orig_video_cols;
+		max_ypos = SCREEN_INFO.orig_video_lines;
 		early_console = &early_vga_console; 
 	}
 	early_console_initialized = 1;
diff --git a/arch/x86_64/kernel/genapic_flat.c b/arch/x86_64/kernel/genapic_flat.c
index b4cbbad..2828469 100644
--- a/arch/x86_64/kernel/genapic_flat.c
+++ b/arch/x86_64/kernel/genapic_flat.c
@@ -7,6 +7,8 @@
  * Hacked for x86-64 by James Cleverdon from i386 architecture code by
  * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
  * James Cleverdon.
+ * Ashok Raj <ashok.raj@intel.com>
+ * 	Removed IPI broadcast shortcut to support CPU hotplug
  */
 #include <linux/config.h>
 #include <linux/threads.h>
@@ -18,6 +20,46 @@
 #include <asm/smp.h>
 #include <asm/ipi.h>
 
+/*
+ * The following permit choosing broadcast IPI shortcut v.s sending IPI only
+ * to online cpus via the send_IPI_mask varient.
+ * The mask version is my preferred option, since it eliminates a lot of
+ * other extra code that would need to be written to cleanup intrs sent
+ * to a CPU while offline.
+ *
+ * Sending broadcast introduces lots of trouble in CPU hotplug situations.
+ * These IPI's are delivered to cpu's irrespective of their offline status
+ * and could pickup stale intr data when these CPUS are turned online.
+ *
+ * Not using broadcast is a cleaner approach IMO, but Andi Kleen disagrees with
+ * the idea of not using broadcast IPI's anymore. Hence the run time check
+ * is introduced, on his request so we can choose an alternate mechanism.
+ *
+ * Initial wacky performance tests that collect cycle counts show
+ * no increase in using mask v.s broadcast version. In fact they seem
+ * identical in terms of cycle counts.
+ *
+ * if we need to use broadcast, we need to do the following.
+ *
+ * cli;
+ * hold call_lock;
+ * clear any pending IPI, just ack and clear all pending intr
+ * set cpu_online_map;
+ * release call_lock;
+ * sti;
+ *
+ * The complicated dummy irq processing shown above is not required if
+ * we didnt sent IPI's to wrong CPU's in the first place.
+ *
+ * - Ashok Raj <ashok.raj@intel.com>
+ */
+#ifdef CONFIG_HOTPLUG_CPU
+#define DEFAULT_SEND_IPI	(1)
+#else
+#define DEFAULT_SEND_IPI	(0)
+#endif
+
+static int no_broadcast=DEFAULT_SEND_IPI;
 
 static cpumask_t flat_target_cpus(void)
 {
@@ -45,22 +87,6 @@
 	apic_write_around(APIC_LDR, val);
 }
 
-static void flat_send_IPI_allbutself(int vector)
-{
-	/*
-	 * if there are no other CPUs in the system then
-	 * we get an APIC send error if we try to broadcast.
-	 * thus we have to avoid sending IPIs in this case.
-	 */
-	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);
-}
-
 static void flat_send_IPI_mask(cpumask_t cpumask, int vector)
 {
 	unsigned long mask = cpus_addr(cpumask)[0];
@@ -93,6 +119,39 @@
 	local_irq_restore(flags);
 }
 
+static inline void __local_flat_send_IPI_allbutself(int vector)
+{
+	if (no_broadcast) {
+		cpumask_t mask = cpu_online_map;
+		int this_cpu = get_cpu();
+
+		cpu_clear(this_cpu, mask);
+		flat_send_IPI_mask(mask, vector);
+		put_cpu();
+	}
+	else
+		__send_IPI_shortcut(APIC_DEST_ALLBUT, vector, APIC_DEST_LOGICAL);
+}
+
+static inline void __local_flat_send_IPI_all(int vector)
+{
+	if (no_broadcast)
+		flat_send_IPI_mask(cpu_online_map, vector);
+	else
+		__send_IPI_shortcut(APIC_DEST_ALLINC, vector, APIC_DEST_LOGICAL);
+}
+
+static void flat_send_IPI_allbutself(int vector)
+{
+	if (((num_online_cpus()) - 1) >= 1)
+		__local_flat_send_IPI_allbutself(vector);
+}
+
+static void flat_send_IPI_all(int vector)
+{
+	__local_flat_send_IPI_all(vector);
+}
+
 static int flat_apic_id_registered(void)
 {
 	return physid_isset(GET_APIC_ID(apic_read(APIC_ID)), phys_cpu_present_map);
@@ -111,6 +170,16 @@
 	return ((ebx >> 24) & 0xFF) >> index_msb;
 }
 
+static __init int no_ipi_broadcast(char *str)
+{
+	get_option(&str, &no_broadcast);
+	printk ("Using %s mode\n", no_broadcast ? "No IPI Broadcast" :
+											"IPI Broadcast");
+	return 1;
+}
+
+__setup("no_ipi_broadcast", no_ipi_broadcast);
+
 struct genapic apic_flat =  {
 	.name = "flat",
 	.int_delivery_mode = dest_LowestPrio,
@@ -125,3 +194,12 @@
 	.cpu_mask_to_apicid = flat_cpu_mask_to_apicid,
 	.phys_pkg_id = phys_pkg_id,
 };
+
+static int __init print_ipi_mode(void)
+{
+	printk ("Using IPI %s mode\n", no_broadcast ? "No-Shortcut" :
+											"Shortcut");
+	return 0;
+}
+
+late_initcall(print_ipi_mode);
diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S
index 9bd2e7a..8d765aa 100644
--- a/arch/x86_64/kernel/head.S
+++ b/arch/x86_64/kernel/head.S
@@ -248,23 +248,23 @@
 	 */
 .org 0x1000
 ENTRY(init_level4_pgt)
-	.quad	0x0000000000102007		/* -> level3_ident_pgt */
+	.quad	0x0000000000002007 + __PHYSICAL_START	/* -> level3_ident_pgt */
 	.fill	255,8,0
-	.quad	0x000000000010a007
+	.quad	0x000000000000a007 + __PHYSICAL_START
 	.fill	254,8,0
 	/* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
-	.quad	0x0000000000103007		/* -> level3_kernel_pgt */
+	.quad	0x0000000000003007 + __PHYSICAL_START	/* -> level3_kernel_pgt */
 
 .org 0x2000
 ENTRY(level3_ident_pgt)
-	.quad	0x0000000000104007
+	.quad	0x0000000000004007 + __PHYSICAL_START
 	.fill	511,8,0
 
 .org 0x3000
 ENTRY(level3_kernel_pgt)
 	.fill	510,8,0
 	/* (2^48-(2*1024*1024*1024)-((2^39)*511))/(2^30) = 510 */
-	.quad	0x0000000000105007		/* -> level2_kernel_pgt */
+	.quad	0x0000000000005007 + __PHYSICAL_START	/* -> level2_kernel_pgt */
 	.fill	1,8,0
 
 .org 0x4000
@@ -337,17 +337,17 @@
 
 .org 0xa000
 ENTRY(level3_physmem_pgt)
-	.quad	0x0000000000105007		/* -> level2_kernel_pgt (so that __va works even before pagetable_init) */
+	.quad	0x0000000000005007 + __PHYSICAL_START	/* -> level2_kernel_pgt (so that __va works even before pagetable_init) */
 
 	.org 0xb000
 #ifdef CONFIG_ACPI_SLEEP
 ENTRY(wakeup_level4_pgt)
-	.quad	0x0000000000102007		/* -> level3_ident_pgt */
+	.quad	0x0000000000002007 + __PHYSICAL_START	/* -> level3_ident_pgt */
 	.fill	255,8,0
-	.quad	0x000000000010a007
+	.quad	0x000000000000a007 + __PHYSICAL_START
 	.fill	254,8,0
 	/* (2^48-(2*1024*1024*1024))/(2^39) = 511 */
-	.quad	0x0000000000103007		/* -> level3_kernel_pgt */
+	.quad	0x0000000000003007 + __PHYSICAL_START	/* -> level3_kernel_pgt */
 #endif
 
 	.data
diff --git a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c
index 0f8c78d..cf6ab14 100644
--- a/arch/x86_64/kernel/head64.c
+++ b/arch/x86_64/kernel/head64.c
@@ -94,7 +94,7 @@
 	s = strstr(saved_command_line, "earlyprintk=");
 	if (s != NULL)
 		setup_early_printk(s);
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
 	s = strstr(saved_command_line, "numa=");
 	if (s != NULL)
 		numa_setup(s+5);
diff --git a/arch/x86_64/kernel/i387.c b/arch/x86_64/kernel/i387.c
index ba139ca..d9b22b6 100644
--- a/arch/x86_64/kernel/i387.c
+++ b/arch/x86_64/kernel/i387.c
@@ -42,7 +42,7 @@
  * Called at bootup to set up the initial FPU state that is later cloned
  * into all processes.
  */
-void __init fpu_init(void)
+void __cpuinit fpu_init(void)
 {
 	unsigned long oldcr0 = read_cr0();
 	extern void __bad_fxsave_alignment(void);
diff --git a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c
index 7873d9b..a891690 100644
--- a/arch/x86_64/kernel/i8259.c
+++ b/arch/x86_64/kernel/i8259.c
@@ -157,14 +157,13 @@
 }
 
 static struct hw_interrupt_type i8259A_irq_type = {
-	"XT-PIC",
-	startup_8259A_irq,
-	shutdown_8259A_irq,
-	enable_8259A_irq,
-	disable_8259A_irq,
-	mask_and_ack_8259A,
-	end_8259A_irq,
-	NULL
+	.typename = "XT-PIC",
+	.startup = startup_8259A_irq,
+	.shutdown = shutdown_8259A_irq,
+	.enable = enable_8259A_irq,
+	.disable = disable_8259A_irq,
+	.ack = mask_and_ack_8259A,
+	.end = end_8259A_irq,
 };
 
 /*
@@ -415,10 +414,22 @@
 	return 0;
 }
 
+static int i8259A_shutdown(struct sys_device *dev)
+{
+	/* Put the i8259A into a quiescent state that
+	 * 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 */
+	return 0;
+}
+
 static struct sysdev_class i8259_sysdev_class = {
 	set_kset_name("i8259"),
 	.suspend = i8259A_suspend,
 	.resume = i8259A_resume,
+	.shutdown = i8259A_shutdown,
 };
 
 static struct sys_device device_i8259A = {
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index afd87e6..157190d 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -330,7 +330,7 @@
 /*
  * Find the pin to which IRQ[irq] (ISA) is connected
  */
-static int __init find_isa_irq_pin(int irq, int type)
+static int find_isa_irq_pin(int irq, int type)
 {
 	int i;
 
@@ -1132,12 +1132,44 @@
  */
 void disable_IO_APIC(void)
 {
+	int pin;
 	/*
 	 * Clear the IO-APIC before rebooting:
 	 */
 	clear_IO_APIC();
 
-	disconnect_bsp_APIC();
+	/*
+	 * If the i82559 is routed through an IOAPIC
+	 * Put that IOAPIC in virtual wire mode
+	 * so legacy interrups can be delivered.
+	 */
+	pin = find_isa_irq_pin(0, mp_ExtINT);
+	if (pin != -1) {
+		struct IO_APIC_route_entry entry;
+		unsigned long flags;
+
+		memset(&entry, 0, sizeof(entry));
+		entry.mask            = 0; /* Enabled */
+		entry.trigger         = 0; /* Edge */
+		entry.irr             = 0;
+		entry.polarity        = 0; /* High */
+		entry.delivery_status = 0;
+		entry.dest_mode       = 0; /* Physical */
+		entry.delivery_mode   = 7; /* ExtInt */
+		entry.vector          = 0;
+		entry.dest.physical.physical_dest = 0;
+
+
+		/*
+		 * Add it to the IO-APIC irq-routing table:
+		 */
+		spin_lock_irqsave(&ioapic_lock, flags);
+		io_apic_write(0, 0x11+2*pin, *(((int *)&entry)+1));
+		io_apic_write(0, 0x10+2*pin, *(((int *)&entry)+0));
+		spin_unlock_irqrestore(&ioapic_lock, flags);
+	}
+
+	disconnect_bsp_APIC(pin != -1);
 }
 
 /*
diff --git a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c
index 62b112e..cc3fb85 100644
--- a/arch/x86_64/kernel/irq.c
+++ b/arch/x86_64/kernel/irq.c
@@ -14,6 +14,7 @@
 #include <linux/interrupt.h>
 #include <linux/seq_file.h>
 #include <linux/module.h>
+#include <linux/delay.h>
 #include <asm/uaccess.h>
 #include <asm/io_apic.h>
 
@@ -106,3 +107,31 @@
 	return 1;
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+void fixup_irqs(cpumask_t map)
+{
+	unsigned int irq;
+	static int warned;
+
+	for (irq = 0; irq < NR_IRQS; irq++) {
+		cpumask_t mask;
+		if (irq == 2)
+			continue;
+
+		cpus_and(mask, irq_affinity[irq], map);
+		if (any_online_cpu(mask) == NR_CPUS) {
+			printk("Breaking affinity for irq %i\n", irq);
+			mask = map;
+		}
+		if (irq_desc[irq].handler->set_affinity)
+			irq_desc[irq].handler->set_affinity(irq, mask);
+		else if (irq_desc[irq].action && !(warned++))
+			printk("Cannot set affinity for irq %i\n", irq);
+	}
+
+	/* That doesn't seem sufficient.  Give it 1ms. */
+	local_irq_enable();
+	mdelay(1);
+	local_irq_disable();
+}
+#endif
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c
index f77f8a0..4e680f8 100644
--- a/arch/x86_64/kernel/kprobes.c
+++ b/arch/x86_64/kernel/kprobes.c
@@ -27,6 +27,8 @@
  *		<prasanna@in.ibm.com> adapted for x86_64
  * 2005-Mar	Roland McGrath <roland@redhat.com>
  *		Fixed to handle %rip-relative addressing mode correctly.
+ * 2005-May     Rusty Lynch <rusty.lynch@intel.com>
+ *              Added function return probes functionality
  */
 
 #include <linux/config.h>
@@ -37,18 +39,16 @@
 #include <linux/slab.h>
 #include <linux/preempt.h>
 #include <linux/moduleloader.h>
-
+#include <asm/cacheflush.h>
 #include <asm/pgtable.h>
 #include <asm/kdebug.h>
 
 static DECLARE_MUTEX(kprobe_mutex);
 
-/* kprobe_status settings */
-#define KPROBE_HIT_ACTIVE	0x00000001
-#define KPROBE_HIT_SS		0x00000002
-
 static struct kprobe *current_kprobe;
 static unsigned long kprobe_status, kprobe_old_rflags, kprobe_saved_rflags;
+static struct kprobe *kprobe_prev;
+static unsigned long kprobe_status_prev, kprobe_old_rflags_prev, kprobe_saved_rflags_prev;
 static struct pt_regs jprobe_saved_regs;
 static long *jprobe_saved_rsp;
 static kprobe_opcode_t *get_insn_slot(void);
@@ -214,6 +214,21 @@
 		BUG_ON((s64) (s32) disp != disp); /* Sanity check.  */
 		*ripdisp = disp;
 	}
+	p->opcode = *p->addr;
+}
+
+void arch_arm_kprobe(struct kprobe *p)
+{
+	*p->addr = BREAKPOINT_INSTRUCTION;
+	flush_icache_range((unsigned long) p->addr,
+			   (unsigned long) p->addr + sizeof(kprobe_opcode_t));
+}
+
+void arch_disarm_kprobe(struct kprobe *p)
+{
+	*p->addr = p->opcode;
+	flush_icache_range((unsigned long) p->addr,
+			   (unsigned long) p->addr + sizeof(kprobe_opcode_t));
 }
 
 void arch_remove_kprobe(struct kprobe *p)
@@ -223,10 +238,29 @@
 	down(&kprobe_mutex);
 }
 
-static inline void disarm_kprobe(struct kprobe *p, struct pt_regs *regs)
+static inline void save_previous_kprobe(void)
 {
-	*p->addr = p->opcode;
-	regs->rip = (unsigned long)p->addr;
+	kprobe_prev = current_kprobe;
+	kprobe_status_prev = kprobe_status;
+	kprobe_old_rflags_prev = kprobe_old_rflags;
+	kprobe_saved_rflags_prev = kprobe_saved_rflags;
+}
+
+static inline void restore_previous_kprobe(void)
+{
+	current_kprobe = kprobe_prev;
+	kprobe_status = kprobe_status_prev;
+	kprobe_old_rflags = kprobe_old_rflags_prev;
+	kprobe_saved_rflags = kprobe_saved_rflags_prev;
+}
+
+static inline void set_current_kprobe(struct kprobe *p, struct pt_regs *regs)
+{
+	current_kprobe = p;
+	kprobe_saved_rflags = kprobe_old_rflags
+		= (regs->eflags & (TF_MASK | IF_MASK));
+	if (is_IF_modifier(p->ainsn.insn))
+		kprobe_saved_rflags &= ~IF_MASK;
 }
 
 static void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
@@ -240,6 +274,50 @@
 		regs->rip = (unsigned long)p->ainsn.insn;
 }
 
+struct task_struct  *arch_get_kprobe_task(void *ptr)
+{
+	return ((struct thread_info *) (((unsigned long) ptr) &
+					(~(THREAD_SIZE -1))))->task;
+}
+
+void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs)
+{
+	unsigned long *sara = (unsigned long *)regs->rsp;
+	struct kretprobe_instance *ri;
+	static void *orig_ret_addr;
+
+	/*
+	 * Save the return address when the return probe hits
+	 * the first time, and use it to populate the (krprobe
+	 * instance)->ret_addr for subsequent return probes at
+	 * the same addrress since stack address would have
+	 * the kretprobe_trampoline by then.
+	 */
+	if (((void*) *sara) != kretprobe_trampoline)
+		orig_ret_addr = (void*) *sara;
+
+	if ((ri = get_free_rp_inst(rp)) != NULL) {
+		ri->rp = rp;
+		ri->stack_addr = sara;
+		ri->ret_addr = orig_ret_addr;
+		add_rp_inst(ri);
+		/* Replace the return addr with trampoline addr */
+		*sara = (unsigned long) &kretprobe_trampoline;
+	} else {
+		rp->nmissed++;
+	}
+}
+
+void arch_kprobe_flush_task(struct task_struct *tk)
+{
+	struct kretprobe_instance *ri;
+	while ((ri = get_rp_inst_tsk(tk)) != NULL) {
+		*((unsigned long *)(ri->stack_addr)) =
+					(unsigned long) ri->ret_addr;
+		recycle_rp_inst(ri);
+	}
+}
+
 /*
  * Interrupts are disabled on entry as trap3 is an interrupt gate and they
  * remain disabled thorough out this function.
@@ -264,9 +342,30 @@
 				regs->eflags |= kprobe_saved_rflags;
 				unlock_kprobes();
 				goto no_kprobe;
+			} else if (kprobe_status == KPROBE_HIT_SSDONE) {
+				/* TODO: Provide re-entrancy from
+				 * post_kprobes_handler() and avoid exception
+				 * stack corruption while single-stepping on
+				 * the instruction of the new probe.
+				 */
+				arch_disarm_kprobe(p);
+				regs->rip = (unsigned long)p->addr;
+				ret = 1;
+			} else {
+				/* We have reentered the kprobe_handler(), since
+				 * another probe was hit while within the
+				 * handler. We here save the original kprobe
+				 * variables and just single step on instruction
+				 * of the new probe without calling any user
+				 * handlers.
+				 */
+				save_previous_kprobe();
+				set_current_kprobe(p, regs);
+				p->nmissed++;
+				prepare_singlestep(p, regs);
+				kprobe_status = KPROBE_REENTER;
+				return 1;
 			}
-			disarm_kprobe(p, regs);
-			ret = 1;
 		} else {
 			p = current_kprobe;
 			if (p->break_handler && p->break_handler(p, regs)) {
@@ -296,11 +395,7 @@
 	}
 
 	kprobe_status = KPROBE_HIT_ACTIVE;
-	current_kprobe = p;
-	kprobe_saved_rflags = kprobe_old_rflags
-	    = (regs->eflags & (TF_MASK | IF_MASK));
-	if (is_IF_modifier(p->ainsn.insn))
-		kprobe_saved_rflags &= ~IF_MASK;
+	set_current_kprobe(p, regs);
 
 	if (p->pre_handler && p->pre_handler(p, regs))
 		/* handler has already set things up, so skip ss setup */
@@ -317,6 +412,55 @@
 }
 
 /*
+ * For function-return probes, init_kprobes() establishes a probepoint
+ * here. When a retprobed function returns, this probe is hit and
+ * trampoline_probe_handler() runs, calling the kretprobe's handler.
+ */
+ void kretprobe_trampoline_holder(void)
+ {
+ 	asm volatile (  ".global kretprobe_trampoline\n"
+ 			"kretprobe_trampoline: \n"
+ 			"nop\n");
+ }
+
+/*
+ * Called when we hit the probe point at kretprobe_trampoline
+ */
+int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	struct task_struct *tsk;
+	struct kretprobe_instance *ri;
+	struct hlist_head *head;
+	struct hlist_node *node;
+	unsigned long *sara = (unsigned long *)regs->rsp - 1;
+
+	tsk = arch_get_kprobe_task(sara);
+	head = kretprobe_inst_table_head(tsk);
+
+	hlist_for_each_entry(ri, node, head, hlist) {
+		if (ri->stack_addr == sara && ri->rp) {
+			if (ri->rp->handler)
+				ri->rp->handler(ri, regs);
+		}
+	}
+	return 0;
+}
+
+void trampoline_post_handler(struct kprobe *p, struct pt_regs *regs,
+						unsigned long flags)
+{
+	struct kretprobe_instance *ri;
+	/* RA already popped */
+	unsigned long *sara = ((unsigned long *)regs->rsp) - 1;
+
+	while ((ri = get_rp_inst(sara))) {
+		regs->rip = (unsigned long)ri->ret_addr;
+		recycle_rp_inst(ri);
+	}
+	regs->eflags &= ~TF_MASK;
+}
+
+/*
  * Called after single-stepping.  p->addr is the address of the
  * instruction whose first byte has been replaced by the "int 3"
  * instruction.  To avoid the SMP problems that can occur when we
@@ -401,13 +545,23 @@
 	if (!kprobe_running())
 		return 0;
 
-	if (current_kprobe->post_handler)
+	if ((kprobe_status != KPROBE_REENTER) && current_kprobe->post_handler) {
+		kprobe_status = KPROBE_HIT_SSDONE;
 		current_kprobe->post_handler(current_kprobe, regs, 0);
+	}
 
-	resume_execution(current_kprobe, regs);
+	if (current_kprobe->post_handler != trampoline_post_handler)
+		resume_execution(current_kprobe, regs);
 	regs->eflags |= kprobe_saved_rflags;
 
-	unlock_kprobes();
+	/* Restore the original saved kprobes variables and continue. */
+	if (kprobe_status == KPROBE_REENTER) {
+		restore_previous_kprobe();
+		goto out;
+	} else {
+		unlock_kprobes();
+	}
+out:
 	preempt_enable_no_resched();
 
 	/*
diff --git a/arch/x86_64/kernel/machine_kexec.c b/arch/x86_64/kernel/machine_kexec.c
new file mode 100644
index 0000000..60d1eff
--- /dev/null
+++ b/arch/x86_64/kernel/machine_kexec.c
@@ -0,0 +1,250 @@
+/*
+ * machine_kexec.c - handle transition of Linux booting another kernel
+ * Copyright (C) 2002-2005 Eric Biederman  <ebiederm@xmission.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+
+#include <linux/mm.h>
+#include <linux/kexec.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/reboot.h>
+#include <asm/pda.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/apic.h>
+#include <asm/cpufeature.h>
+#include <asm/hw_irq.h>
+
+#define LEVEL0_SIZE (1UL << 12UL)
+#define LEVEL1_SIZE (1UL << 21UL)
+#define LEVEL2_SIZE (1UL << 30UL)
+#define LEVEL3_SIZE (1UL << 39UL)
+#define LEVEL4_SIZE (1UL << 48UL)
+
+#define L0_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define L1_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_PSE)
+#define L2_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define L3_ATTR (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+
+static void init_level2_page(u64 *level2p, unsigned long addr)
+{
+	unsigned long end_addr;
+
+	addr &= PAGE_MASK;
+	end_addr = addr + LEVEL2_SIZE;
+	while (addr < end_addr) {
+		*(level2p++) = addr | L1_ATTR;
+		addr += LEVEL1_SIZE;
+	}
+}
+
+static int init_level3_page(struct kimage *image, u64 *level3p,
+				unsigned long addr, unsigned long last_addr)
+{
+	unsigned long end_addr;
+	int result;
+
+	result = 0;
+	addr &= PAGE_MASK;
+	end_addr = addr + LEVEL3_SIZE;
+	while ((addr < last_addr) && (addr < end_addr)) {
+		struct page *page;
+		u64 *level2p;
+
+		page = kimage_alloc_control_pages(image, 0);
+		if (!page) {
+			result = -ENOMEM;
+			goto out;
+		}
+		level2p = (u64 *)page_address(page);
+		init_level2_page(level2p, addr);
+		*(level3p++) = __pa(level2p) | L2_ATTR;
+		addr += LEVEL2_SIZE;
+	}
+	/* clear the unused entries */
+	while (addr < end_addr) {
+		*(level3p++) = 0;
+		addr += LEVEL2_SIZE;
+	}
+out:
+	return result;
+}
+
+
+static int init_level4_page(struct kimage *image, u64 *level4p,
+				unsigned long addr, unsigned long last_addr)
+{
+	unsigned long end_addr;
+	int result;
+
+	result = 0;
+	addr &= PAGE_MASK;
+	end_addr = addr + LEVEL4_SIZE;
+	while ((addr < last_addr) && (addr < end_addr)) {
+		struct page *page;
+		u64 *level3p;
+
+		page = kimage_alloc_control_pages(image, 0);
+		if (!page) {
+			result = -ENOMEM;
+			goto out;
+		}
+		level3p = (u64 *)page_address(page);
+		result = init_level3_page(image, level3p, addr, last_addr);
+		if (result) {
+			goto out;
+		}
+		*(level4p++) = __pa(level3p) | L3_ATTR;
+		addr += LEVEL3_SIZE;
+	}
+	/* clear the unused entries */
+	while (addr < end_addr) {
+		*(level4p++) = 0;
+		addr += LEVEL3_SIZE;
+	}
+out:
+	return result;
+}
+
+
+static int init_pgtable(struct kimage *image, unsigned long start_pgtable)
+{
+	u64 *level4p;
+	level4p = (u64 *)__va(start_pgtable);
+ 	return init_level4_page(image, level4p, 0, end_pfn << PAGE_SHIFT);
+}
+
+static void set_idt(void *newidt, u16 limit)
+{
+	unsigned char curidt[10];
+
+	/* x86-64 supports unaliged loads & stores */
+	(*(u16 *)(curidt)) = limit;
+	(*(u64 *)(curidt +2)) = (unsigned long)(newidt);
+
+	__asm__ __volatile__ (
+		"lidt %0\n"
+		: "=m" (curidt)
+		);
+};
+
+
+static void set_gdt(void *newgdt, u16 limit)
+{
+	unsigned char curgdt[10];
+
+	/* x86-64 supports unaligned loads & stores */
+	(*(u16 *)(curgdt)) = limit;
+	(*(u64 *)(curgdt +2)) = (unsigned long)(newgdt);
+
+	__asm__ __volatile__ (
+		"lgdt %0\n"
+		: "=m" (curgdt)
+		);
+};
+
+static void load_segments(void)
+{
+	__asm__ __volatile__ (
+		"\tmovl $"STR(__KERNEL_DS)",%eax\n"
+		"\tmovl %eax,%ds\n"
+		"\tmovl %eax,%es\n"
+		"\tmovl %eax,%ss\n"
+		"\tmovl %eax,%fs\n"
+		"\tmovl %eax,%gs\n"
+		);
+#undef STR
+#undef __STR
+}
+
+typedef NORET_TYPE void (*relocate_new_kernel_t)(unsigned long indirection_page,
+					unsigned long control_code_buffer,
+					unsigned long start_address,
+					unsigned long pgtable) ATTRIB_NORET;
+
+const extern unsigned char relocate_new_kernel[];
+const extern unsigned long relocate_new_kernel_size;
+
+int machine_kexec_prepare(struct kimage *image)
+{
+	unsigned long start_pgtable, control_code_buffer;
+	int result;
+
+	/* Calculate the offsets */
+	start_pgtable = page_to_pfn(image->control_code_page) << PAGE_SHIFT;
+	control_code_buffer = start_pgtable + 4096UL;
+
+	/* Setup the identity mapped 64bit page table */
+	result = init_pgtable(image, start_pgtable);
+	if (result)
+		return result;
+
+	/* Place the code in the reboot code buffer */
+	memcpy(__va(control_code_buffer), relocate_new_kernel,
+						relocate_new_kernel_size);
+
+	return 0;
+}
+
+void machine_kexec_cleanup(struct kimage *image)
+{
+	return;
+}
+
+/*
+ * Do not allocate memory (or fail in any way) in machine_kexec().
+ * We are past the point of no return, committed to rebooting now.
+ */
+NORET_TYPE void machine_kexec(struct kimage *image)
+{
+	unsigned long page_list;
+	unsigned long control_code_buffer;
+	unsigned long start_pgtable;
+	relocate_new_kernel_t rnk;
+
+	/* Interrupts aren't acceptable while we reboot */
+	local_irq_disable();
+
+	/* Calculate the offsets */
+	page_list = image->head;
+	start_pgtable = page_to_pfn(image->control_code_page) << PAGE_SHIFT;
+	control_code_buffer = start_pgtable + 4096UL;
+
+	/* Set the low half of the page table to my identity mapped
+	 * page table for kexec.  Leave the high half pointing at the
+	 * kernel pages.   Don't bother to flush the global pages
+	 * as that will happen when I fully switch to my identity mapped
+	 * page table anyway.
+	 */
+	memcpy(__va(read_cr3()), __va(start_pgtable), PAGE_SIZE/2);
+	__flush_tlb();
+
+
+	/* The segment registers are funny things, they are
+	 * automatically loaded from a table, in memory wherever you
+	 * set them to a specific selector, but this table is never
+	 * accessed again unless you set the segment to a different selector.
+	 *
+	 * The more common model are caches where the behide
+	 * the scenes work is done, but is also dropped at arbitrary
+	 * times.
+	 *
+	 * I take advantage of this here by force loading the
+	 * segments, before I zap the gdt with an invalid value.
+	 */
+	load_segments();
+	/* The gdt & idt are now invalid.
+	 * If you want to load them you must set up your own idt & gdt.
+	 */
+	set_gdt(phys_to_virt(0),0);
+	set_idt(phys_to_virt(0),0);
+	/* now call it */
+	rnk = (relocate_new_kernel_t) control_code_buffer;
+	(*rnk)(page_list, control_code_buffer, image->start, start_pgtable);
+}
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c
index 3a89d73..21e7062 100644
--- a/arch/x86_64/kernel/mce.c
+++ b/arch/x86_64/kernel/mce.c
@@ -327,7 +327,7 @@
 }
 
 /* Add per CPU specific workarounds here */
-static void __init mce_cpu_quirks(struct cpuinfo_x86 *c) 
+static void __cpuinit mce_cpu_quirks(struct cpuinfo_x86 *c)
 { 
 	/* This should be disabled by the BIOS, but isn't always */
 	if (c->x86_vendor == X86_VENDOR_AMD && c->x86 == 15) {
@@ -337,7 +337,7 @@
 	}
 }			
 
-static void __init mce_cpu_features(struct cpuinfo_x86 *c)
+static void __cpuinit mce_cpu_features(struct cpuinfo_x86 *c)
 {
 	switch (c->x86_vendor) {
 	case X86_VENDOR_INTEL:
@@ -352,7 +352,7 @@
  * Called for each booted CPU to set up machine checks.
  * Must be called with preempt off. 
  */
-void __init mcheck_init(struct cpuinfo_x86 *c)
+void __cpuinit mcheck_init(struct cpuinfo_x86 *c)
 {
 	static cpumask_t mce_cpus __initdata = CPU_MASK_NONE;
 
@@ -411,7 +411,7 @@
 	memset(mcelog.entry, 0, next * sizeof(struct mce));
 	mcelog.next = 0;
 
-	synchronize_kernel();	
+	synchronize_sched();
 
 	/* Collect entries that were still getting written before the synchronize. */
 
@@ -542,7 +542,7 @@
 ACCESSOR(tolerant,tolerant,)
 ACCESSOR(check_interval,check_interval,mce_restart())
 
-static __init int mce_init_device(void)
+static __cpuinit int mce_init_device(void)
 {
 	int err;
 	if (!mce_available(&boot_cpu_data))
diff --git a/arch/x86_64/kernel/mce_intel.c b/arch/x86_64/kernel/mce_intel.c
index 4db9a64..0be0a79 100644
--- a/arch/x86_64/kernel/mce_intel.c
+++ b/arch/x86_64/kernel/mce_intel.c
@@ -42,7 +42,7 @@
 	irq_exit();
 }
 
-static void __init intel_init_thermal(struct cpuinfo_x86 *c)
+static void __cpuinit intel_init_thermal(struct cpuinfo_x86 *c)
 {
 	u32 l, h;
 	int tm2 = 0;
@@ -93,7 +93,7 @@
 	return;
 }
 
-void __init mce_intel_feature_init(struct cpuinfo_x86 *c)
+void __cpuinit mce_intel_feature_init(struct cpuinfo_x86 *c)
 {
 	intel_init_thermal(c);
 }
diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c
index 61a63be..9c5aa2a 100644
--- a/arch/x86_64/kernel/mpparse.c
+++ b/arch/x86_64/kernel/mpparse.c
@@ -23,6 +23,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/mc146818rtc.h>
 #include <linux/acpi.h>
+#include <linux/module.h>
 
 #include <asm/smp.h>
 #include <asm/mtrr.h>
@@ -45,7 +46,8 @@
 int apic_version [MAX_APICS];
 unsigned char mp_bus_id_to_type [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
 int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
-cpumask_t pci_bus_to_cpumask [256] = { [0 ... 255] = CPU_MASK_ALL };
+unsigned char pci_bus_to_node [256];
+EXPORT_SYMBOL(pci_bus_to_node);
 
 static int mp_current_pci_id = 0;
 /* I/O APIC entries */
@@ -904,11 +906,20 @@
 	return;
 }
 
+#define MAX_GSI_NUM	4096
+
 int mp_register_gsi(u32 gsi, int edge_level, int active_high_low)
 {
 	int			ioapic = -1;
 	int			ioapic_pin = 0;
 	int			idx, bit = 0;
+	static int		pci_irq = 16;
+	/*
+	 * Mapping between Global System Interrupts, which
+	 * represent all possible interrupts, to the IRQs
+	 * assigned to actual devices.
+	 */
+	static int		gsi_to_irq[MAX_GSI_NUM];
 
 	if (acpi_irq_model != ACPI_IRQ_MODEL_IOAPIC)
 		return gsi;
@@ -943,11 +954,21 @@
 	if ((1<<bit) & mp_ioapic_routing[ioapic].pin_programmed[idx]) {
 		Dprintk(KERN_DEBUG "Pin %d-%d already programmed\n",
 			mp_ioapic_routing[ioapic].apic_id, ioapic_pin);
-		return gsi;
+		return gsi_to_irq[gsi];
 	}
 
 	mp_ioapic_routing[ioapic].pin_programmed[idx] |= (1<<bit);
 
+	if (edge_level) {
+		/*
+		 * For PCI devices assign IRQs in order, avoiding gaps
+		 * due to unused I/O APIC pins.
+		 */
+		int irq = gsi;
+		gsi = pci_irq++;
+		gsi_to_irq[irq] = gsi;
+	}
+
 	io_apic_set_pci_routing(ioapic, ioapic_pin, gsi,
 		edge_level == ACPI_EDGE_SENSITIVE ? 0 : 1,
 		active_high_low == ACPI_ACTIVE_HIGH ? 0 : 1);
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c
index 31c0f2e..4e44d6e 100644
--- a/arch/x86_64/kernel/nmi.c
+++ b/arch/x86_64/kernel/nmi.c
@@ -98,7 +98,7 @@
 	(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)
 
-static __init inline int nmi_known_cpu(void)
+static __cpuinit inline int nmi_known_cpu(void)
 {
 	switch (boot_cpu_data.x86_vendor) {
 	case X86_VENDOR_AMD:
@@ -110,7 +110,7 @@
 }
 
 /* Run after command line and cpu_init init, but before all other checks */
-void __init nmi_watchdog_default(void)
+void __cpuinit nmi_watchdog_default(void)
 {
 	if (nmi_watchdog != NMI_DEFAULT)
 		return;
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
index 761b6d3..1d91271 100644
--- a/arch/x86_64/kernel/process.c
+++ b/arch/x86_64/kernel/process.c
@@ -8,7 +8,8 @@
  * 
  *  X86-64 port
  *	Andi Kleen.
- * 
+ *
+ *	CPU hotplug support - ashok.raj@intel.com
  *  $Id: process.c,v 1.38 2002/01/15 10:08:03 ak Exp $
  */
 
@@ -18,6 +19,7 @@
 
 #include <stdarg.h>
 
+#include <linux/cpu.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -34,6 +36,7 @@
 #include <linux/ptrace.h>
 #include <linux/utsname.h>
 #include <linux/random.h>
+#include <linux/kprobes.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -153,6 +156,29 @@
 }
 EXPORT_SYMBOL_GPL(cpu_idle_wait);
 
+#ifdef CONFIG_HOTPLUG_CPU
+DECLARE_PER_CPU(int, cpu_state);
+
+#include <asm/nmi.h>
+/* We don't actually take CPU down, just spin without interrupts. */
+static inline void play_dead(void)
+{
+	idle_task_exit();
+	wbinvd();
+	mb();
+	/* Ack it */
+	__get_cpu_var(cpu_state) = CPU_DEAD;
+
+	while (1)
+		safe_halt();
+}
+#else
+static inline void play_dead(void)
+{
+	BUG();
+}
+#endif /* CONFIG_HOTPLUG_CPU */
+
 /*
  * The idle thread. There's no useful work to be
  * done, so just try to conserve power and have a
@@ -173,6 +199,8 @@
 			idle = pm_idle;
 			if (!idle)
 				idle = default_idle;
+			if (cpu_is_offline(smp_processor_id()))
+				play_dead();
 			idle();
 		}
 
@@ -203,7 +231,7 @@
 	}
 }
 
-void __init select_idle_routine(const struct cpuinfo_x86 *c)
+void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
 {
 	static int printed;
 	if (cpu_has(c, X86_FEATURE_MWAIT)) {
@@ -293,6 +321,14 @@
 {
 	struct task_struct *me = current;
 	struct thread_struct *t = &me->thread;
+
+	/*
+	 * Remove function-return probe instances associated with this task
+	 * and put them back on the free list. Do not insert an exit probe for
+	 * this function, it will be disabled by kprobe_flush_task if you do.
+	 */
+	kprobe_flush_task(me);
+
 	if (me->thread.io_bitmap_ptr) { 
 		struct tss_struct *tss = &per_cpu(init_tss, get_cpu());
 
@@ -312,6 +348,13 @@
 	struct task_struct *tsk = current;
 	struct thread_info *t = current_thread_info();
 
+	/*
+	 * Remove function-return probe instances associated with this task
+	 * and put them back on the free list. Do not insert an exit probe for
+	 * this function, it will be disabled by kprobe_flush_task if you do.
+	 */
+	kprobe_flush_task(tsk);
+
 	if (t->flags & _TIF_ABI_PENDING)
 		t->flags ^= (_TIF_ABI_PENDING | _TIF_IA32);
 
@@ -656,7 +699,7 @@
 
 	switch (code) { 
 	case ARCH_SET_GS:
-		if (addr >= TASK_SIZE) 
+		if (addr >= TASK_SIZE_OF(task))
 			return -EPERM; 
 		cpu = get_cpu();
 		/* handle small bases via the GDT because that's faster to 
@@ -682,7 +725,7 @@
 	case ARCH_SET_FS:
 		/* Not strictly needed for fs, but do it for symmetry
 		   with gs */
-		if (addr >= TASK_SIZE)
+		if (addr >= TASK_SIZE_OF(task))
 			return -EPERM; 
 		cpu = get_cpu();
 		/* handle small bases via the GDT because that's faster to 
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
index 525f6a1..bbf64b5 100644
--- a/arch/x86_64/kernel/ptrace.c
+++ b/arch/x86_64/kernel/ptrace.c
@@ -257,12 +257,12 @@
 			value &= 0xffff;
 			return 0;
 		case offsetof(struct user_regs_struct,fs_base):
-			if (value >= TASK_SIZE)
+			if (value >= TASK_SIZE_OF(child))
 				return -EIO;
 			child->thread.fs = value;
 			return 0;
 		case offsetof(struct user_regs_struct,gs_base):
-			if (value >= TASK_SIZE)
+			if (value >= TASK_SIZE_OF(child))
 				return -EIO;
 			child->thread.gs = value;
 			return 0;
@@ -279,7 +279,7 @@
 			break;
 		case offsetof(struct user_regs_struct, rip):
 			/* Check if the new RIP address is canonical */
-			if (value >= TASK_SIZE)
+			if (value >= TASK_SIZE_OF(child))
 				return -EIO;
 			break;
 	}
@@ -419,6 +419,8 @@
 		break;
 
 	case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
+	{
+		int dsize = test_tsk_thread_flag(child, TIF_IA32) ? 3 : 7;
 		ret = -EIO;
 		if ((addr & 7) ||
 		    addr > sizeof(struct user) - 7)
@@ -430,22 +432,22 @@
 			break;
 		/* Disallows to set a breakpoint into the vsyscall */
 		case offsetof(struct user, u_debugreg[0]):
-			if (data >= TASK_SIZE-7) break;
+			if (data >= TASK_SIZE_OF(child) - dsize) break;
 			child->thread.debugreg0 = data;
 			ret = 0;
 			break;
 		case offsetof(struct user, u_debugreg[1]):
-			if (data >= TASK_SIZE-7) break;
+			if (data >= TASK_SIZE_OF(child) - dsize) break;
 			child->thread.debugreg1 = data;
 			ret = 0;
 			break;
 		case offsetof(struct user, u_debugreg[2]):
-			if (data >= TASK_SIZE-7) break;
+			if (data >= TASK_SIZE_OF(child) - dsize) break;
 			child->thread.debugreg2 = data;
 			ret = 0;
 			break;
 		case offsetof(struct user, u_debugreg[3]):
-			if (data >= TASK_SIZE-7) break;
+			if (data >= TASK_SIZE_OF(child) - dsize) break;
 			child->thread.debugreg3 = data;
 			ret = 0;
 			break;
@@ -469,6 +471,7 @@
 		  break;
 		}
 		break;
+	}
 	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
 	case PTRACE_CONT:    /* restart after signal. */
 
diff --git a/arch/x86_64/kernel/reboot.c b/arch/x86_64/kernel/reboot.c
index be4b36f..57e71db 100644
--- a/arch/x86_64/kernel/reboot.c
+++ b/arch/x86_64/kernel/reboot.c
@@ -66,34 +66,6 @@
 
 __setup("reboot=", reboot_setup);
 
-#ifdef CONFIG_SMP
-static void smp_halt(void)
-{
-	int cpuid = safe_smp_processor_id(); 
-	static int first_entry = 1;
-
-	if (reboot_force)
-		return;
-
-	if (first_entry) {
-		first_entry = 0;
-		smp_call_function((void *)machine_restart, NULL, 1, 0);
-	}
-			
-	smp_stop_cpu(); 
-
-	/* AP calling this. Just halt */
-	if (cpuid != boot_cpu_id) { 
-		for (;;) 
-			asm("hlt");
-	}
-
-	/* Wait for all other CPUs to have run smp_stop_cpu */
-	while (!cpus_empty(cpu_online_map))
-		rep_nop(); 
-}
-#endif
-
 static inline void kb_wait(void)
 {
 	int i;
@@ -103,15 +75,47 @@
 			break;
 }
 
+void machine_shutdown(void)
+{
+	/* Stop the cpus and apics */
+#ifdef CONFIG_SMP
+	int reboot_cpu_id;
+
+	/* The boot cpu is always logical cpu 0 */
+	reboot_cpu_id = 0;
+
+	/* Make certain the cpu I'm about to reboot on is online */
+	if (!cpu_isset(reboot_cpu_id, cpu_online_map)) {
+		reboot_cpu_id = smp_processor_id();
+	}
+
+	/* Make certain I only run on the appropriate processor */
+	set_cpus_allowed(current, cpumask_of_cpu(reboot_cpu_id));
+
+	/* O.K Now that I'm on the appropriate processor,
+	 * stop all of the others.
+	 */
+	smp_send_stop();
+#endif
+
+	local_irq_disable();
+
+#ifndef CONFIG_SMP
+	disable_local_APIC();
+#endif
+
+	disable_IO_APIC();
+
+	local_irq_enable();
+}
+
 void machine_restart(char * __unused)
 {
 	int i;
 
 	printk("machine restart\n");
 
-#ifdef CONFIG_SMP
-	smp_halt(); 
-#endif
+	machine_shutdown();
 
 	if (!reboot_force) {
 		local_irq_disable();
diff --git a/arch/x86_64/kernel/relocate_kernel.S b/arch/x86_64/kernel/relocate_kernel.S
new file mode 100644
index 0000000..d24fa9b
--- /dev/null
+++ b/arch/x86_64/kernel/relocate_kernel.S
@@ -0,0 +1,143 @@
+/*
+ * relocate_kernel.S - put the kernel image in place to boot
+ * Copyright (C) 2002-2005 Eric Biederman  <ebiederm@xmission.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+
+#include <linux/linkage.h>
+
+	/*
+	 * Must be relocatable PIC code callable as a C function, that once
+	 * it starts can not use the previous processes stack.
+	 */
+	.globl relocate_new_kernel
+	.code64
+relocate_new_kernel:
+	/* %rdi page_list
+	 * %rsi reboot_code_buffer
+	 * %rdx start address
+	 * %rcx page_table
+	 * %r8  arg5
+	 * %r9  arg6
+	 */
+
+	/* zero out flags, and disable interrupts */
+	pushq $0
+	popfq
+
+	/* set a new stack at the bottom of our page... */
+	lea   4096(%rsi), %rsp
+
+	/* store the parameters back on the stack */
+	pushq	%rdx /* store the start address */
+
+	/* Set cr0 to a known state:
+	 * 31 1 == Paging enabled
+	 * 18 0 == Alignment check disabled
+	 * 16 0 == Write protect disabled
+	 * 3  0 == No task switch
+	 * 2  0 == Don't do FP software emulation.
+	 * 0  1 == Proctected mode enabled
+	 */
+	movq	%cr0, %rax
+	andq	$~((1<<18)|(1<<16)|(1<<3)|(1<<2)), %rax
+	orl	$((1<<31)|(1<<0)), %eax
+	movq	%rax, %cr0
+
+	/* Set cr4 to a known state:
+	 * 10 0 == xmm exceptions disabled
+	 * 9  0 == xmm registers instructions disabled
+	 * 8  0 == performance monitoring counter disabled
+	 * 7  0 == page global disabled
+	 * 6  0 == machine check exceptions disabled
+	 * 5  1 == physical address extension enabled
+	 * 4  0 == page size extensions	disabled
+	 * 3  0 == Debug extensions disabled
+	 * 2  0 == Time stamp disable (disabled)
+	 * 1  0 == Protected mode virtual interrupts disabled
+	 * 0  0 == VME disabled
+	 */
+
+	movq	$((1<<5)), %rax
+	movq	%rax, %cr4
+
+	jmp 1f
+1:
+
+	/* Switch to the identity mapped page tables,
+	 * and flush the TLB.
+	*/
+	movq	%rcx, %cr3
+
+	/* Do the copies */
+	movq	%rdi, %rcx 	/* Put the page_list in %rcx */
+	xorq	%rdi, %rdi
+	xorq	%rsi, %rsi
+	jmp	1f
+
+0:	/* top, read another word for the indirection page */
+
+	movq	(%rbx), %rcx
+	addq	$8,	%rbx
+1:
+	testq	$0x1,	%rcx  /* is it a destination page? */
+	jz	2f
+	movq	%rcx,	%rdi
+	andq	$0xfffffffffffff000, %rdi
+	jmp	0b
+2:
+	testq	$0x2,	%rcx  /* is it an indirection page? */
+	jz	2f
+	movq	%rcx,   %rbx
+	andq	$0xfffffffffffff000, %rbx
+	jmp	0b
+2:
+	testq	$0x4,	%rcx  /* is it the done indicator? */
+	jz	2f
+	jmp	3f
+2:
+	testq	$0x8,	%rcx  /* is it the source indicator? */
+	jz	0b	      /* Ignore it otherwise */
+	movq	%rcx,   %rsi  /* For ever source page do a copy */
+	andq	$0xfffffffffffff000, %rsi
+
+	movq	$512,   %rcx
+	rep ; movsq
+	jmp	0b
+3:
+
+	/* To be certain of avoiding problems with self-modifying code
+	 * I need to execute a serializing instruction here.
+	 * So I flush the TLB by reloading %cr3 here, it's handy,
+	 * and not processor dependent.
+	 */
+	movq	%cr3, %rax
+	movq	%rax, %cr3
+
+	/* set all of the registers to known values */
+	/* leave %rsp alone */
+
+	xorq	%rax, %rax
+	xorq	%rbx, %rbx
+	xorq    %rcx, %rcx
+	xorq    %rdx, %rdx
+	xorq    %rsi, %rsi
+	xorq    %rdi, %rdi
+	xorq    %rbp, %rbp
+	xorq	%r8,  %r8
+	xorq	%r9,  %r9
+	xorq	%r10, %r9
+	xorq	%r11, %r11
+	xorq	%r12, %r12
+	xorq	%r13, %r13
+	xorq	%r14, %r14
+	xorq	%r15, %r15
+
+	ret
+relocate_new_kernel_end:
+
+	.globl relocate_new_kernel_size
+relocate_new_kernel_size:
+	.quad relocate_new_kernel_end - relocate_new_kernel
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c
index 99f038e..b02d921 100644
--- a/arch/x86_64/kernel/setup.c
+++ b/arch/x86_64/kernel/setup.c
@@ -40,6 +40,9 @@
 #include <linux/acpi.h>
 #include <linux/kallsyms.h>
 #include <linux/edd.h>
+#include <linux/mmzone.h>
+#include <linux/kexec.h>
+
 #include <asm/mtrr.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -348,7 +351,7 @@
 		if (!memcmp(from, "mem=", 4))
 			parse_memopt(from+4, &from); 
 
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
 		if (!memcmp(from, "numa=", 5))
 			numa_setup(from+5); 
 #endif
@@ -365,6 +368,27 @@
 		if (!memcmp(from, "noexec=", 7))
 			nonx_setup(from + 7);
 
+#ifdef CONFIG_KEXEC
+		/* crashkernel=size@addr specifies the location to reserve for
+		 * a crash kernel.  By reserving this memory we guarantee
+		 * that linux never set's it up as a DMA target.
+		 * Useful for holding code to do something appropriate
+		 * after a kernel panic.
+		 */
+		else if (!memcmp(from, "crashkernel=", 12)) {
+			unsigned long size, base;
+			size = memparse(from+12, &from);
+			if (*from == '@') {
+				base = memparse(from+1, &from);
+				/* FIXME: Do I want a sanity check
+				 * to validate the memory range?
+				 */
+				crashk_res.start = base;
+				crashk_res.end   = base + size - 1;
+			}
+		}
+#endif
+
 	next_char:
 		c = *(from++);
 		if (!c)
@@ -377,17 +401,20 @@
 	*cmdline_p = command_line;
 }
 
-#ifndef CONFIG_DISCONTIGMEM
-static void __init contig_initmem_init(void)
+#ifndef CONFIG_NUMA
+static void __init
+contig_initmem_init(unsigned long start_pfn, unsigned long end_pfn)
 {
-        unsigned long bootmap_size, bootmap; 
-        bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
-        bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size);
-        if (bootmap == -1L) 
-                panic("Cannot find bootmem map of size %ld\n",bootmap_size);
-        bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
-        e820_bootmem_free(&contig_page_data, 0, end_pfn << PAGE_SHIFT); 
-        reserve_bootmem(bootmap, bootmap_size);
+	unsigned long bootmap_size, bootmap;
+
+	memory_present(0, start_pfn, end_pfn);
+	bootmap_size = bootmem_bootmap_pages(end_pfn)<<PAGE_SHIFT;
+	bootmap = find_e820_area(0, end_pfn<<PAGE_SHIFT, bootmap_size);
+	if (bootmap == -1L)
+		panic("Cannot find bootmem map of size %ld\n",bootmap_size);
+	bootmap_size = init_bootmem(bootmap >> PAGE_SHIFT, end_pfn);
+	e820_bootmem_free(NODE_DATA(0), 0, end_pfn << PAGE_SHIFT);
+	reserve_bootmem(bootmap, bootmap_size);
 } 
 #endif
 
@@ -554,10 +581,10 @@
 	acpi_numa_init();
 #endif
 
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
 	numa_initmem_init(0, end_pfn); 
 #else
-	contig_initmem_init(); 
+	contig_initmem_init(0, end_pfn);
 #endif
 
 	/* Reserve direct mapping */
@@ -618,6 +645,15 @@
 		}
 	}
 #endif
+
+	sparse_init();
+
+#ifdef CONFIG_KEXEC
+	if (crashk_res.start != crashk_res.end) {
+		reserve_bootmem(crashk_res.start,
+			crashk_res.end - crashk_res.start + 1);
+	}
+#endif
 	paging_init();
 
 	check_ioapic();
@@ -669,7 +705,7 @@
 #endif
 }
 
-static int __init get_model_name(struct cpuinfo_x86 *c)
+static int __cpuinit get_model_name(struct cpuinfo_x86 *c)
 {
 	unsigned int *v;
 
@@ -685,7 +721,7 @@
 }
 
 
-static void __init display_cacheinfo(struct cpuinfo_x86 *c)
+static void __cpuinit display_cacheinfo(struct cpuinfo_x86 *c)
 {
 	unsigned int n, dummy, eax, ebx, ecx, edx;
 
@@ -796,7 +832,7 @@
 	return r;
 }
 
-static void __init detect_ht(struct cpuinfo_x86 *c)
+static void __cpuinit detect_ht(struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_SMP
 	u32 	eax, ebx, ecx, edx;
@@ -857,7 +893,7 @@
 /*
  * find out the number of processor cores on the die
  */
-static int __init intel_num_cpu_cores(struct cpuinfo_x86 *c)
+static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c)
 {
 	unsigned int eax;
 
@@ -875,7 +911,7 @@
 		return 1;
 }
 
-static void __init init_intel(struct cpuinfo_x86 *c)
+static void __cpuinit init_intel(struct cpuinfo_x86 *c)
 {
 	/* Cache sizes */
 	unsigned n;
@@ -895,7 +931,7 @@
  	c->x86_num_cores = intel_num_cpu_cores(c);
 }
 
-void __init get_cpu_vendor(struct cpuinfo_x86 *c)
+void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c)
 {
 	char *v = c->x86_vendor_id;
 
@@ -916,7 +952,7 @@
 /* Do some early cpuid on the boot CPU to get some parameter that are
    needed before check_bugs. Everything advanced is in identify_cpu
    below. */
-void __init early_identify_cpu(struct cpuinfo_x86 *c)
+void __cpuinit early_identify_cpu(struct cpuinfo_x86 *c)
 {
 	u32 tfms;
 
@@ -970,7 +1006,7 @@
 /*
  * This does the hard work of actually picking apart the CPU stuff...
  */
-void __init identify_cpu(struct cpuinfo_x86 *c)
+void __cpuinit identify_cpu(struct cpuinfo_x86 *c)
 {
 	int i;
 	u32 xlvl;
@@ -1047,7 +1083,7 @@
 }
  
 
-void __init print_cpu_info(struct cpuinfo_x86 *c)
+void __cpuinit print_cpu_info(struct cpuinfo_x86 *c)
 {
 	if (c->x86_model_id[0])
 		printk("%s", c->x86_model_id);
diff --git a/arch/x86_64/kernel/setup64.c b/arch/x86_64/kernel/setup64.c
index 678b7ac..f2b9c6b 100644
--- a/arch/x86_64/kernel/setup64.c
+++ b/arch/x86_64/kernel/setup64.c
@@ -29,7 +29,7 @@
 
 char x86_boot_params[BOOT_PARAM_SIZE] __initdata = {0,};
 
-cpumask_t cpu_initialized __initdata = CPU_MASK_NONE;
+cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE;
 
 struct x8664_pda cpu_pda[NR_CPUS] __cacheline_aligned; 
 
@@ -171,7 +171,7 @@
 	wrmsrl(MSR_SYSCALL_MASK, EF_TF|EF_DF|EF_IE|0x3000); 
 }
 
-void __init check_efer(void)
+void __cpuinit check_efer(void)
 {
 	unsigned long efer;
 
@@ -188,7 +188,7 @@
  * 'CPU state barrier', nothing should get across.
  * A lot of state is already set up in PDA init.
  */
-void __init cpu_init (void)
+void __cpuinit cpu_init (void)
 {
 #ifdef CONFIG_SMP
 	int cpu = stack_smp_processor_id();
diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c
index 429c026..98590a9 100644
--- a/arch/x86_64/kernel/signal.c
+++ b/arch/x86_64/kernel/signal.c
@@ -34,9 +34,9 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                sigset_t *set, struct pt_regs * regs); 
-void ia32_setup_frame(int sig, struct k_sigaction *ka,
+int ia32_setup_frame(int sig, struct k_sigaction *ka,
             sigset_t *set, struct pt_regs * regs); 
 
 asmlinkage long
@@ -238,7 +238,7 @@
 	return (void __user *)round_down(rsp - size, 16); 
 }
 
-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 			   sigset_t *set, struct pt_regs * regs)
 {
 	struct rt_sigframe __user *frame;
@@ -327,20 +327,23 @@
 		current->comm, current->pid, frame, regs->rip, frame->pretcode);
 #endif
 
-	return;
+	return 1;
 
 give_sigsegv:
 	force_sigsegv(sig, current);
+	return 0;
 }
 
 /*
  * OK, we're invoking a handler
  */	
 
-static void
+static int
 handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
 		sigset_t *oldset, struct pt_regs *regs)
 {
+	int ret;
+
 #ifdef DEBUG_SIG
 	printk("handle_signal pid:%d sig:%lu rip:%lx rsp:%lx regs=%p\n",
 		current->pid, sig,
@@ -384,20 +387,22 @@
 #ifdef CONFIG_IA32_EMULATION
 	if (test_thread_flag(TIF_IA32)) {
 		if (ka->sa.sa_flags & SA_SIGINFO)
-			ia32_setup_rt_frame(sig, ka, info, oldset, regs);
+			ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs);
 		else
-			ia32_setup_frame(sig, ka, oldset, regs);
+			ret = ia32_setup_frame(sig, ka, oldset, regs);
 	} else 
 #endif
-	setup_rt_frame(sig, ka, info, oldset, regs);
+	ret = setup_rt_frame(sig, ka, info, oldset, regs);
 
-	if (!(ka->sa.sa_flags & SA_NODEFER)) {
+	if (ret && !(ka->sa.sa_flags & SA_NODEFER)) {
 		spin_lock_irq(&current->sighand->siglock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
 		sigaddset(&current->blocked,sig);
 		recalc_sigpending();
 		spin_unlock_irq(&current->sighand->siglock);
 	}
+
+	return ret;
 }
 
 /*
@@ -417,10 +422,10 @@
 	 * kernel mode. Just return without doing anything
 	 * if so.
 	 */
-	if ((regs->cs & 3) != 3)
+	if (!user_mode(regs))
 		return 1;
 
-	if (try_to_freeze(0))
+	if (try_to_freeze())
 		goto no_signal;
 
 	if (!oldset)
@@ -434,11 +439,10 @@
 		 * inside the kernel.
 		 */
 		if (current->thread.debugreg7)
-			asm volatile("movq %0,%%db7"	: : "r" (current->thread.debugreg7));
+			set_debugreg(current->thread.debugreg7, 7);
 
 		/* Whee!  Actually deliver the signal.  */
-		handle_signal(signr, &info, &ka, oldset, regs);
-		return 1;
+		return handle_signal(signr, &info, &ka, oldset, regs);
 	}
 
  no_signal:
diff --git a/arch/x86_64/kernel/smp.c b/arch/x86_64/kernel/smp.c
index 1e379ed..ccae392 100644
--- a/arch/x86_64/kernel/smp.c
+++ b/arch/x86_64/kernel/smp.c
@@ -283,6 +283,16 @@
 
 static struct call_data_struct * call_data;
 
+void lock_ipi_call_lock(void)
+{
+	spin_lock_irq(&call_lock);
+}
+
+void unlock_ipi_call_lock(void)
+{
+	spin_unlock_irq(&call_lock);
+}
+
 /*
  * this function sends a 'generic call function' IPI to all other CPUs
  * in the system.
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index f1ec0f3..b969ee1 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -34,6 +34,7 @@
  *      Andi Kleen              :       Converted to new state machine.
  *					Various cleanups.
  *					Probably mostly hotplug CPU ready now.
+ *	Ashok Raj			: CPU hotplug support
  */
 
 
@@ -58,11 +59,6 @@
 #include <asm/proto.h>
 #include <asm/nmi.h>
 
-/* Change for real CPU hotplug. Note other files need to be fixed
-   first too. */
-#define __cpuinit __init
-#define __cpuinitdata __initdata
-
 /* Number of siblings per CPU package */
 int smp_num_siblings = 1;
 /* Package ID of each logical CPU */
@@ -103,6 +99,37 @@
 extern unsigned char trampoline_data[];
 extern unsigned char trampoline_end[];
 
+/* State of each CPU */
+DEFINE_PER_CPU(int, cpu_state) = { 0 };
+
+/*
+ * Store all idle threads, this can be reused instead of creating
+ * a new thread. Also avoids complicated thread destroy functionality
+ * for idle threads.
+ */
+struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;
+
+#define get_idle_for_cpu(x)     (idle_thread_array[(x)])
+#define set_idle_for_cpu(x,p)   (idle_thread_array[(x)] = (p))
+
+/*
+ * cpu_possible_map should be static, it cannot change as cpu's
+ * are onlined, or offlined. The reason is per-cpu data-structures
+ * are allocated by some modules at init time, and dont expect to
+ * do this dynamically on cpu arrival/departure.
+ * cpu_present_map on the other hand can change dynamically.
+ * In case when cpu_hotplug is not compiled, then we resort to current
+ * behaviour, which is cpu_possible == cpu_present.
+ * If cpu-hotplug is supported, then we need to preallocate for all
+ * those NR_CPUS, hence cpu_possible_map represents entire NR_CPUS range.
+ * - Ashok Raj
+ */
+#ifdef CONFIG_HOTPLUG_CPU
+#define fixup_cpu_possible_map(x)	cpu_set((x), cpu_possible_map)
+#else
+#define fixup_cpu_possible_map(x)
+#endif
+
 /*
  * Currently trivial. Write the real->protected mode
  * bootstrap into the page concerned. The caller
@@ -418,6 +445,33 @@
 	cpu_set(cpuid, cpu_callin_map);
 }
 
+static inline void set_cpu_sibling_map(int cpu)
+{
+	int i;
+
+	if (smp_num_siblings > 1) {
+		for_each_cpu(i) {
+			if (cpu_core_id[cpu] == cpu_core_id[i]) {
+				cpu_set(i, cpu_sibling_map[cpu]);
+				cpu_set(cpu, cpu_sibling_map[i]);
+			}
+		}
+	} else {
+		cpu_set(cpu, cpu_sibling_map[cpu]);
+	}
+
+	if (current_cpu_data.x86_num_cores > 1) {
+		for_each_cpu(i) {
+			if (phys_proc_id[cpu] == phys_proc_id[i]) {
+				cpu_set(i, cpu_core_map[cpu]);
+				cpu_set(cpu, cpu_core_map[i]);
+			}
+		}
+	} else {
+		cpu_core_map[cpu] = cpu_sibling_map[cpu];
+	}
+}
+
 /*
  * Setup code on secondary processor (after comming out of the trampoline)
  */
@@ -448,9 +502,28 @@
 	enable_APIC_timer();
 
 	/*
+	 * The sibling maps must be set before turing the online map on for
+	 * this cpu
+	 */
+	set_cpu_sibling_map(smp_processor_id());
+
+	/*
+	 * We need to hold call_lock, so there is no inconsistency
+	 * between the time smp_call_function() determines number of
+	 * IPI receipients, and the time when the determination is made
+	 * for which cpus receive the IPI in genapic_flat.c. Holding this
+	 * lock helps us to not include this cpu in a currently in progress
+	 * smp_call_function().
+	 */
+	lock_ipi_call_lock();
+
+	/*
 	 * Allow the master to continue.
 	 */
 	cpu_set(smp_processor_id(), cpu_online_map);
+	per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
+	unlock_ipi_call_lock();
+
 	mb();
 
 	/* Wait for TSC sync to not schedule things before.
@@ -628,33 +701,77 @@
 	return (send_status | accept_status);
 }
 
+struct create_idle {
+	struct task_struct *idle;
+	struct completion done;
+	int cpu;
+};
+
+void do_fork_idle(void *_c_idle)
+{
+	struct create_idle *c_idle = _c_idle;
+
+	c_idle->idle = fork_idle(c_idle->cpu);
+	complete(&c_idle->done);
+}
+
 /*
  * Boot one CPU.
  */
 static int __cpuinit do_boot_cpu(int cpu, int apicid)
 {
-	struct task_struct *idle;
 	unsigned long boot_error;
 	int timeout;
 	unsigned long start_rip;
-	/*
-	 * We can't use kernel_thread since we must avoid to
-	 * reschedule the child.
-	 */
-	idle = fork_idle(cpu);
-	if (IS_ERR(idle)) {
-		printk("failed fork for CPU %d\n", cpu);
-		return PTR_ERR(idle);
+	struct create_idle c_idle = {
+		.cpu = cpu,
+		.done = COMPLETION_INITIALIZER(c_idle.done),
+	};
+	DECLARE_WORK(work, do_fork_idle, &c_idle);
+
+	c_idle.idle = get_idle_for_cpu(cpu);
+
+	if (c_idle.idle) {
+		c_idle.idle->thread.rsp = (unsigned long) (((struct pt_regs *)
+			(THREAD_SIZE + (unsigned long) c_idle.idle->thread_info)) - 1);
+		init_idle(c_idle.idle, cpu);
+		goto do_rest;
 	}
 
-	cpu_pda[cpu].pcurrent = idle;
+	/*
+	 * During cold boot process, keventd thread is not spun up yet.
+	 * When we do cpu hot-add, we create idle threads on the fly, we should
+	 * not acquire any attributes from the calling context. Hence the clean
+	 * way to create kernel_threads() is to do that from keventd().
+	 * We do the current_is_keventd() due to the fact that ACPI notifier
+	 * was also queuing to keventd() and when the caller is already running
+	 * in context of keventd(), we would end up with locking up the keventd
+	 * thread.
+	 */
+	if (!keventd_up() || current_is_keventd())
+		work.func(work.data);
+	else {
+		schedule_work(&work);
+		wait_for_completion(&c_idle.done);
+	}
+
+	if (IS_ERR(c_idle.idle)) {
+		printk("failed fork for CPU %d\n", cpu);
+		return PTR_ERR(c_idle.idle);
+	}
+
+	set_idle_for_cpu(cpu, c_idle.idle);
+
+do_rest:
+
+	cpu_pda[cpu].pcurrent = c_idle.idle;
 
 	start_rip = setup_trampoline();
 
-	init_rsp = idle->thread.rsp;
+	init_rsp = c_idle.idle->thread.rsp;
 	per_cpu(init_tss,cpu).rsp0 = init_rsp;
 	initial_code = start_secondary;
-	clear_ti_thread_flag(idle->thread_info, TIF_FORK);
+	clear_ti_thread_flag(c_idle.idle->thread_info, TIF_FORK);
 
 	printk(KERN_INFO "Booting processor %d/%d rip %lx rsp %lx\n", cpu, apicid,
 	       start_rip, init_rsp);
@@ -746,51 +863,6 @@
 unsigned long cache_decay_ticks;
 
 /*
- * Construct cpu_sibling_map[], so that we can tell the sibling CPU
- * on SMT systems efficiently.
- */
-static __cpuinit void detect_siblings(void)
-{
-	int cpu;
-
-	for (cpu = 0; cpu < NR_CPUS; cpu++) {
-		cpus_clear(cpu_sibling_map[cpu]);
-		cpus_clear(cpu_core_map[cpu]);
-	}
-
-	for_each_online_cpu (cpu) {
-		struct cpuinfo_x86 *c = cpu_data + cpu;
-		int siblings = 0;
-		int i;
-		if (smp_num_siblings > 1) {
-			for_each_online_cpu (i) {
-				if (cpu_core_id[cpu] == cpu_core_id[i]) {
-					siblings++;
-					cpu_set(i, cpu_sibling_map[cpu]);
-				}
-			}
-		} else {
-			siblings++;
-			cpu_set(cpu, cpu_sibling_map[cpu]);
-		}
-
-		if (siblings != smp_num_siblings) {
-			printk(KERN_WARNING
-	       "WARNING: %d siblings found for CPU%d, should be %d\n",
-			       siblings, cpu, smp_num_siblings);
-			smp_num_siblings = siblings;
-		}
-		if (c->x86_num_cores > 1) {
-			for_each_online_cpu(i) {
-				if (phys_proc_id[cpu] == phys_proc_id[i])
-					cpu_set(i, cpu_core_map[cpu]);
-			}
-		} else
-			cpu_core_map[cpu] = cpu_sibling_map[cpu];
-	}
-}
-
-/*
  * Cleanup possible dangling ends...
  */
 static __cpuinit void smp_cleanup_boot(void)
@@ -823,7 +895,7 @@
  *
  * RED-PEN audit/test this more. I bet there is more state messed up here.
  */
-static __cpuinit void disable_smp(void)
+static __init void disable_smp(void)
 {
 	cpu_present_map = cpumask_of_cpu(0);
 	cpu_possible_map = cpumask_of_cpu(0);
@@ -838,7 +910,7 @@
 /*
  * Handle user cpus=... parameter.
  */
-static __cpuinit void enforce_max_cpus(unsigned max_cpus)
+static __init void enforce_max_cpus(unsigned max_cpus)
 {
 	int i, k;
 	k = 0;
@@ -855,7 +927,7 @@
 /*
  * Various sanity checks.
  */
-static int __cpuinit smp_sanity_check(unsigned max_cpus)
+static int __init smp_sanity_check(unsigned max_cpus)
 {
 	if (!physid_isset(hard_smp_processor_id(), phys_cpu_present_map)) {
 		printk("weird, boot CPU (#%d) not listed by the BIOS.\n",
@@ -913,7 +985,7 @@
  * Prepare for SMP bootup.  The MP table or ACPI has been read
  * earlier.  Just do some sanity checking here and enable APIC mode.
  */
-void __cpuinit smp_prepare_cpus(unsigned int max_cpus)
+void __init smp_prepare_cpus(unsigned int max_cpus)
 {
 	int i;
 
@@ -930,10 +1002,9 @@
 		int apicid = cpu_present_to_apicid(i);
 		if (physid_isset(apicid, phys_cpu_present_map)) {
 			cpu_set(i, cpu_present_map);
-			/* possible map would be different if we supported real
-			   CPU hotplug. */
 			cpu_set(i, cpu_possible_map);
 		}
+		fixup_cpu_possible_map(i);
 	}
 
 	if (smp_sanity_check(max_cpus) < 0) {
@@ -978,13 +1049,13 @@
 	int me = smp_processor_id();
 	cpu_set(me, cpu_online_map);
 	cpu_set(me, cpu_callout_map);
+	cpu_set(0, cpu_sibling_map[0]);
+	cpu_set(0, cpu_core_map[0]);
+	per_cpu(cpu_state, me) = CPU_ONLINE;
 }
 
 /*
  * Entry point to boot a CPU.
- *
- * This is all __cpuinit, not __devinit for now because we don't support
- * CPU hotplug (yet).
  */
 int __cpuinit __cpu_up(unsigned int cpu)
 {
@@ -1001,6 +1072,15 @@
 		return -EINVAL;
 	}
 
+	/*
+	 * Already booted CPU?
+	 */
+ 	if (cpu_isset(cpu, cpu_callin_map)) {
+		Dprintk("do_boot_cpu %d Already started\n", cpu);
+ 		return -ENOSYS;
+	}
+
+	per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
 	/* Boot it! */
 	err = do_boot_cpu(cpu, apicid);
 	if (err < 0) {
@@ -1013,23 +1093,118 @@
 
 	while (!cpu_isset(cpu, cpu_online_map))
 		cpu_relax();
-	return 0;
+	err = 0;
+
+	return err;
 }
 
 /*
  * Finish the SMP boot.
  */
-void __cpuinit smp_cpus_done(unsigned int max_cpus)
+void __init smp_cpus_done(unsigned int max_cpus)
 {
+#ifndef CONFIG_HOTPLUG_CPU
 	zap_low_mappings();
+#endif
 	smp_cleanup_boot();
 
 #ifdef CONFIG_X86_IO_APIC
 	setup_ioapic_dest();
 #endif
 
-	detect_siblings();
 	time_init_gtod();
 
 	check_nmi_watchdog();
 }
+
+#ifdef CONFIG_HOTPLUG_CPU
+
+static void remove_siblinginfo(int cpu)
+{
+	int sibling;
+
+	for_each_cpu_mask(sibling, cpu_sibling_map[cpu])
+		cpu_clear(cpu, cpu_sibling_map[sibling]);
+	for_each_cpu_mask(sibling, cpu_core_map[cpu])
+		cpu_clear(cpu, cpu_core_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;
+}
+
+void remove_cpu_from_maps(void)
+{
+	int cpu = smp_processor_id();
+
+	cpu_clear(cpu, cpu_callout_map);
+	cpu_clear(cpu, cpu_callin_map);
+	clear_bit(cpu, &cpu_initialized); /* was set by cpu_init() */
+}
+
+int __cpu_disable(void)
+{
+	int cpu = smp_processor_id();
+
+	/*
+	 * Perhaps use cpufreq to drop frequency, but that could go
+	 * into generic code.
+ 	 *
+	 * We won't take down the boot processor on i386 due to some
+	 * interrupts only being able to be serviced by the BSP.
+	 * Especially so if we're not using an IOAPIC	-zwane
+	 */
+	if (cpu == 0)
+		return -EBUSY;
+
+	disable_APIC_timer();
+
+	/*
+	 * HACK:
+	 * Allow any queued timer interrupts to get serviced
+	 * This is only a temporary solution until we cleanup
+	 * fixup_irqs as we do for IA64.
+	 */
+	local_irq_enable();
+	mdelay(1);
+
+	local_irq_disable();
+	remove_siblinginfo(cpu);
+
+	/* It's now safe to remove this processor from the online map */
+	cpu_clear(cpu, cpu_online_map);
+	remove_cpu_from_maps();
+	fixup_irqs(cpu_online_map);
+	return 0;
+}
+
+void __cpu_die(unsigned int cpu)
+{
+	/* We don't do anything here: idle task is faking death itself. */
+	unsigned int i;
+
+	for (i = 0; i < 10; i++) {
+		/* 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);
+			return;
+		}
+		current->state = TASK_UNINTERRUPTIBLE;
+		schedule_timeout(HZ/10);
+	}
+ 	printk(KERN_ERR "CPU %u didn't die...\n", cpu);
+}
+
+#else /* ... !CONFIG_HOTPLUG_CPU */
+
+int __cpu_disable(void)
+{
+	return -ENOSYS;
+}
+
+void __cpu_die(unsigned int cpu)
+{
+	/* We said "no" in __cpu_disable */
+	BUG();
+}
+#endif /* CONFIG_HOTPLUG_CPU */
diff --git a/arch/x86_64/kernel/suspend.c b/arch/x86_64/kernel/suspend.c
index ebaa1e3..6c0f402e 100644
--- a/arch/x86_64/kernel/suspend.c
+++ b/arch/x86_64/kernel/suspend.c
@@ -44,7 +44,6 @@
 	 */
 	asm volatile ("sgdt %0" : "=m" (ctxt->gdt_limit));
 	asm volatile ("sidt %0" : "=m" (ctxt->idt_limit));
-	asm volatile ("sldt %0" : "=m" (ctxt->ldt));
 	asm volatile ("str %0"  : "=m" (ctxt->tr));
 
 	/* XMM0..XMM15 should be handled by kernel_fpu_begin(). */
@@ -69,6 +68,7 @@
 	asm volatile ("movq %%cr2, %0" : "=r" (ctxt->cr2));
 	asm volatile ("movq %%cr3, %0" : "=r" (ctxt->cr3));
 	asm volatile ("movq %%cr4, %0" : "=r" (ctxt->cr4));
+	asm volatile ("movq %%cr8, %0" : "=r" (ctxt->cr8));
 }
 
 void save_processor_state(void)
@@ -90,12 +90,20 @@
 	/*
 	 * control registers
 	 */
+	asm volatile ("movq %0, %%cr8" :: "r" (ctxt->cr8));
 	asm volatile ("movq %0, %%cr4" :: "r" (ctxt->cr4));
 	asm volatile ("movq %0, %%cr3" :: "r" (ctxt->cr3));
 	asm volatile ("movq %0, %%cr2" :: "r" (ctxt->cr2));
 	asm volatile ("movq %0, %%cr0" :: "r" (ctxt->cr0));
 
 	/*
+	 * now restore the descriptor tables to their proper values
+	 * ltr is done i fix_processor_context().
+	 */
+	asm volatile ("lgdt %0" :: "m" (ctxt->gdt_limit));
+	asm volatile ("lidt %0" :: "m" (ctxt->idt_limit));
+
+	/*
 	 * segment registers
 	 */
 	asm volatile ("movw %0, %%ds" :: "r" (ctxt->ds));
@@ -108,14 +116,6 @@
 	wrmsrl(MSR_GS_BASE, ctxt->gs_base);
 	wrmsrl(MSR_KERNEL_GS_BASE, ctxt->gs_kernel_base);
 
-	/*
-	 * now restore the descriptor tables to their proper values
-	 * ltr is done i fix_processor_context().
-	 */
-	asm volatile ("lgdt %0" :: "m" (ctxt->gdt_limit));
-	asm volatile ("lidt %0" :: "m" (ctxt->idt_limit));
-	asm volatile ("lldt %0" :: "m" (ctxt->ldt));
-
 	fix_processor_context();
 
 	do_fpu_end();
diff --git a/arch/x86_64/kernel/sys_x86_64.c b/arch/x86_64/kernel/sys_x86_64.c
index dbebd5c..cc7821c 100644
--- a/arch/x86_64/kernel/sys_x86_64.c
+++ b/arch/x86_64/kernel/sys_x86_64.c
@@ -68,13 +68,7 @@
 static void find_start_end(unsigned long flags, unsigned long *begin,
 			   unsigned long *end)
 {
-#ifdef CONFIG_IA32_EMULATION
-	if (test_thread_flag(TIF_IA32)) { 
-		*begin = TASK_UNMAPPED_32;
-		*end = IA32_PAGE_OFFSET; 
-	} else 
-#endif
-	if (flags & MAP_32BIT) { 
+	if (!test_thread_flag(TIF_IA32) && (flags & MAP_32BIT)) {
 		/* This is usually used needed to map code in small
 		   model, so it needs to be in the first 31bit. Limit
 		   it to that.  This means we need to move the
@@ -84,10 +78,10 @@
 		   of playground for now. -AK */ 
 		*begin = 0x40000000; 
 		*end = 0x80000000;		
-	} else { 
-		*begin = TASK_UNMAPPED_64; 
+	} else {
+		*begin = TASK_UNMAPPED_BASE;
 		*end = TASK_SIZE; 
-		}
+	}
 } 
 
 unsigned long
@@ -111,6 +105,11 @@
 		    (!vma || addr + len <= vma->vm_start))
 			return addr;
 	}
+	if (((flags & MAP_32BIT) || test_thread_flag(TIF_IA32))
+	    && len <= mm->cached_hole_size) {
+	        mm->cached_hole_size = 0;
+		mm->free_area_cache = begin;
+	}
 	addr = mm->free_area_cache;
 	if (addr < begin) 
 		addr = begin; 
@@ -126,6 +125,7 @@
 			 */
 			if (start_addr != begin) {
 				start_addr = addr = begin;
+				mm->cached_hole_size = 0;
 				goto full_search;
 			}
 			return -ENOMEM;
@@ -137,6 +137,9 @@
 			mm->free_area_cache = addr + len;
 			return addr;
 		}
+		if (addr + mm->cached_hole_size < vma->vm_start)
+		        mm->cached_hole_size = vma->vm_start - addr;
+
 		addr = vma->vm_end;
 	}
 }
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index fb8c809..66bf6dd 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -64,6 +64,7 @@
 unsigned int cpu_khz;					/* TSC clocks / usec, not used here */
 static unsigned long hpet_period;			/* fsecs / HPET clock */
 unsigned long hpet_tick;				/* HPET clocks / interrupt */
+static int hpet_use_timer;
 unsigned long vxtime_hz = PIT_TICK_RATE;
 int report_lost_ticks;				/* command line option */
 unsigned long long monotonic_base;
@@ -105,7 +106,9 @@
 
 static inline unsigned int do_gettimeoffset_hpet(void)
 {
-	return ((hpet_readl(HPET_COUNTER) - vxtime.last) * vxtime.quot) >> 32;
+	/* 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;
 }
 
 unsigned int (*do_gettimeoffset)(void) = do_gettimeoffset_tsc;
@@ -301,7 +304,7 @@
 
 			last_offset = vxtime.last;
 			base = monotonic_base;
-			this_offset = hpet_readl(HPET_T0_CMP) - hpet_tick;
+			this_offset = hpet_readl(HPET_COUNTER);
 
 		} while (read_seqretry(&xtime_lock, seq));
 		offset = (this_offset - last_offset);
@@ -377,7 +380,14 @@
 
 	write_seqlock(&xtime_lock);
 
-	if (vxtime.hpet_address) {
+	if (vxtime.hpet_address)
+		offset = hpet_readl(HPET_COUNTER);
+
+	if (hpet_use_timer) {
+		/* if we're using the hpet timer functionality,
+		 * we can more accurately know the counter value
+		 * when the timer interrupt occured.
+		 */
 		offset = hpet_readl(HPET_T0_CMP) - hpet_tick;
 		delay = hpet_readl(HPET_COUNTER) - offset;
 	} else {
@@ -803,17 +813,18 @@
  * Set up timer 0, as periodic with first interrupt to happen at hpet_tick,
  * and period also hpet_tick.
  */
-
-	hpet_writel(HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL |
+	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);
+		hpet_writel(hpet_tick, HPET_T0_CMP); /* AK: why twice? */
+		cfg |= HPET_CFG_LEGACY;
+	}
 /*
  * Go!
  */
 
-	cfg |= HPET_CFG_ENABLE | HPET_CFG_LEGACY;
+	cfg |= HPET_CFG_ENABLE;
 	hpet_writel(cfg, HPET_CFG);
 
 	return 0;
@@ -834,8 +845,7 @@
 
 	id = hpet_readl(HPET_ID);
 
-	if (!(id & HPET_ID_VENDOR) || !(id & HPET_ID_NUMBER) ||
-	    !(id & HPET_ID_LEGSUP))
+	if (!(id & HPET_ID_VENDOR) || !(id & HPET_ID_NUMBER))
 		return -1;
 
 	hpet_period = hpet_readl(HPET_PERIOD);
@@ -845,6 +855,8 @@
 	hpet_tick = (1000000000L * (USEC_PER_SEC / HZ) + hpet_period / 2) /
 		hpet_period;
 
+	hpet_use_timer = (id & HPET_ID_LEGSUP);
+
 	return hpet_timer_stop_set_go(hpet_tick);
 }
 
@@ -901,9 +913,11 @@
 	set_normalized_timespec(&wall_to_monotonic,
 	                        -xtime.tv_sec, -xtime.tv_nsec);
 
-	if (!hpet_init()) {
+	if (!hpet_init())
                 vxtime_hz = (1000000000000000L + hpet_period / 2) /
 			hpet_period;
+
+	if (hpet_use_timer) {
 		cpu_khz = hpet_calibrate_tsc();
 		timename = "HPET";
 #ifdef CONFIG_X86_PM_TIMER
@@ -968,7 +982,7 @@
 	if (unsynchronized_tsc())
 		notsc = 1;
 	if (vxtime.hpet_address && notsc) {
-		timetype = "HPET";
+		timetype = hpet_use_timer ? "HPET" : "PIT/HPET";
 		vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
 		vxtime.mode = VXTIME_HPET;
 		do_gettimeoffset = do_gettimeoffset_hpet;
@@ -983,7 +997,7 @@
 		printk(KERN_INFO "Disabling vsyscall due to use of PM timer\n");
 #endif
 	} else {
-		timetype = vxtime.hpet_address ? "HPET/TSC" : "PIT/TSC";
+		timetype = hpet_use_timer ? "HPET/TSC" : "PIT/TSC";
 		vxtime.mode = VXTIME_TSC;
 	}
 
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c
index 3dfec8f..1027366 100644
--- a/arch/x86_64/kernel/traps.c
+++ b/arch/x86_64/kernel/traps.c
@@ -274,7 +274,7 @@
 void show_registers(struct pt_regs *regs)
 {
 	int i;
-	int in_kernel = (regs->cs & 3) == 0;
+	int in_kernel = !user_mode(regs);
 	unsigned long rsp;
 	const int cpu = safe_smp_processor_id(); 
 	struct task_struct *cur = cpu_pda[cpu].pcurrent; 
@@ -318,7 +318,7 @@
 	struct bug_frame f;
 	char tmp;
 
-	if (regs->cs & 3)
+	if (user_mode(regs))
 		return; 
 	if (__copy_from_user(&f, (struct bug_frame *) regs->rip, 
 			     sizeof(struct bug_frame)))
@@ -437,7 +437,7 @@
        }
 #endif
 
-	if ((regs->cs & 3)  != 0) { 
+	if (user_mode(regs)) {
 		struct task_struct *tsk = current;
 
 		if (exception_trace && unhandled_signal(tsk, signr))
@@ -522,7 +522,7 @@
        }
 #endif
 
-	if ((regs->cs & 3)!=0) { 
+	if (user_mode(regs)) {
 		struct task_struct *tsk = current;
 
 		if (exception_trace && unhandled_signal(tsk, SIGSEGV))
@@ -586,11 +586,17 @@
 asmlinkage void default_do_nmi(struct pt_regs *regs)
 {
 	unsigned char reason = 0;
+	int cpu;
+
+	cpu = smp_processor_id();
 
 	/* Only the BSP gets external NMIs from the system.  */
-	if (!smp_processor_id())
+	if (!cpu)
 		reason = get_nmi_reason();
 
+	if (!cpu_online(cpu))
+		return;
+
 	if (!(reason & 0xc0)) {
 		if (notify_die(DIE_NMI_IPI, "nmi_ipi", regs, reason, 0, SIGINT)
 								== NOTIFY_STOP)
@@ -638,7 +644,7 @@
 	if (eregs == (struct pt_regs *)eregs->rsp)
 		;
 	/* Exception from user space */
-	else if (eregs->cs & 3)
+	else if (user_mode(eregs))
 		regs = ((struct pt_regs *)current->thread.rsp0) - 1;
 	/* Exception from kernel and interrupts are enabled. Move to
  	   kernel process stack. */
@@ -669,7 +675,7 @@
        }
 #endif
 
-	asm("movq %%db6,%0" : "=r" (condition));
+	get_debugreg(condition, 6);
 
 	if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
 						SIGTRAP) == NOTIFY_STOP)
@@ -697,7 +703,7 @@
 		 * allowing programs to debug themselves without the ptrace()
 		 * interface.
 		 */
-                if ((regs->cs & 3) == 0)
+                if (!user_mode(regs))
                        goto clear_TF_reenable;
 		/*
 		 * Was the TF flag set by a debugger? If so, clear it now,
@@ -715,13 +721,13 @@
 	info.si_signo = SIGTRAP;
 	info.si_errno = 0;
 	info.si_code = TRAP_BRKPT;
-	if ((regs->cs & 3) == 0) 
+	if (!user_mode(regs))
 		goto clear_dr7; 
 
 	info.si_addr = (void __user *)regs->rip;
 	force_sig_info(SIGTRAP, &info, tsk);	
 clear_dr7:
-	asm volatile("movq %0,%%db7"::"r"(0UL));
+	set_debugreg(0UL, 7);
 	return;
 
 clear_TF_reenable:
@@ -756,7 +762,7 @@
 	unsigned short cwd, swd;
 
 	conditional_sti(regs);
-	if ((regs->cs & 3) == 0 &&
+	if (!user_mode(regs) &&
 	    kernel_math_error(regs, "kernel x87 math error"))
 		return;
 
@@ -822,7 +828,7 @@
 	unsigned short mxcsr;
 
 	conditional_sti(regs);
-	if ((regs->cs & 3) == 0 &&
+	if (!user_mode(regs) &&
         	kernel_math_error(regs, "kernel simd math error"))
 		return;
 
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S
index 59ebd5b..73389f5 100644
--- a/arch/x86_64/kernel/vmlinux.lds.S
+++ b/arch/x86_64/kernel/vmlinux.lds.S
@@ -2,7 +2,10 @@
  * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
  */
 
+#define LOAD_OFFSET __START_KERNEL_map
+
 #include <asm-generic/vmlinux.lds.h>
+#include <asm/page.h>
 #include <linux/config.h>
 
 OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
@@ -11,28 +14,30 @@
 jiffies_64 = jiffies;
 SECTIONS
 {
-  . = 0xffffffff80100000;
+  . = __START_KERNEL;
   phys_startup_64 = startup_64 - LOAD_OFFSET;
   _text = .;			/* Text and read-only data */
-  .text : {
+  .text :  AT(ADDR(.text) - LOAD_OFFSET) {
 	*(.text)
 	SCHED_TEXT
 	LOCK_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x9090
-  .text.lock : { *(.text.lock) }	/* out-of-line lock text */
+  				/* out-of-line lock text */
+  .text.lock : AT(ADDR(.text.lock) - LOAD_OFFSET) { *(.text.lock) }
 
   _etext = .;			/* End of text section */
 
   . = ALIGN(16);		/* Exception table */
   __start___ex_table = .;
-  __ex_table : { *(__ex_table) }
+  __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) }
   __stop___ex_table = .;
 
   RODATA
 
-  .data : {			/* Data */
+				/* Data */
+  .data : AT(ADDR(.data) - LOAD_OFFSET) {
 	*(.data)
 	CONSTRUCTORS
 	}
@@ -40,62 +45,95 @@
   _edata = .;			/* End of data section */
 
   __bss_start = .;		/* BSS */
-  .bss : {
+  .bss : AT(ADDR(.bss) - LOAD_OFFSET) {
 	*(.bss.page_aligned)	
 	*(.bss)
 	}
   __bss_end = .;
 
+  . = ALIGN(PAGE_SIZE);
   . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+  .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
+	*(.data.cacheline_aligned)
+  }
 
-#define AFTER(x)      BINALIGN(LOADADDR(x) + SIZEOF(x), 16)
-#define BINALIGN(x,y) (((x) + (y) - 1)  & ~((y) - 1))
-#define CACHE_ALIGN(x) BINALIGN(x, CONFIG_X86_L1_CACHE_BYTES)
+#define VSYSCALL_ADDR (-10*1024*1024)
+#define VSYSCALL_PHYS_ADDR ((LOADADDR(.data.cacheline_aligned) + SIZEOF(.data.cacheline_aligned) + 4095) & ~(4095))
+#define VSYSCALL_VIRT_ADDR ((ADDR(.data.cacheline_aligned) + SIZEOF(.data.cacheline_aligned) + 4095) & ~(4095))
 
-  .vsyscall_0 -10*1024*1024: AT ((LOADADDR(.data.cacheline_aligned) + SIZEOF(.data.cacheline_aligned) + 4095) & ~(4095)) { *(.vsyscall_0) }
-  __vsyscall_0 = LOADADDR(.vsyscall_0);
+#define VLOAD_OFFSET (VSYSCALL_ADDR - VSYSCALL_PHYS_ADDR)
+#define VLOAD(x) (ADDR(x) - VLOAD_OFFSET)
+
+#define VVIRT_OFFSET (VSYSCALL_ADDR - VSYSCALL_VIRT_ADDR)
+#define VVIRT(x) (ADDR(x) - VVIRT_OFFSET)
+
+  . = VSYSCALL_ADDR;
+  .vsyscall_0 :	 AT(VSYSCALL_PHYS_ADDR) { *(.vsyscall_0) }
+  __vsyscall_0 = VSYSCALL_VIRT_ADDR;
+
   . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
-  .xtime_lock : AT CACHE_ALIGN(AFTER(.vsyscall_0)) { *(.xtime_lock) }
-  xtime_lock = LOADADDR(.xtime_lock);
-  .vxtime : AT AFTER(.xtime_lock) { *(.vxtime) }
-  vxtime = LOADADDR(.vxtime);
-  .wall_jiffies : AT AFTER(.vxtime) { *(.wall_jiffies) }
-  wall_jiffies = LOADADDR(.wall_jiffies);
-  .sys_tz : AT AFTER(.wall_jiffies) { *(.sys_tz) }
-  sys_tz = LOADADDR(.sys_tz);
-  .sysctl_vsyscall : AT AFTER(.sys_tz) { *(.sysctl_vsyscall) }
-  sysctl_vsyscall = LOADADDR(.sysctl_vsyscall); 
-  .xtime : AT AFTER(.sysctl_vsyscall) { *(.xtime) }
-  xtime = LOADADDR(.xtime);
+  .xtime_lock : AT(VLOAD(.xtime_lock)) { *(.xtime_lock) }
+  xtime_lock = VVIRT(.xtime_lock);
+
+  .vxtime : AT(VLOAD(.vxtime)) { *(.vxtime) }
+  vxtime = VVIRT(.vxtime);
+
+  .wall_jiffies : AT(VLOAD(.wall_jiffies)) { *(.wall_jiffies) }
+  wall_jiffies = VVIRT(.wall_jiffies);
+
+  .sys_tz : AT(VLOAD(.sys_tz)) { *(.sys_tz) }
+  sys_tz = VVIRT(.sys_tz);
+
+  .sysctl_vsyscall : AT(VLOAD(.sysctl_vsyscall)) { *(.sysctl_vsyscall) }
+  sysctl_vsyscall = VVIRT(.sysctl_vsyscall);
+
+  .xtime : AT(VLOAD(.xtime)) { *(.xtime) }
+  xtime = VVIRT(.xtime);
+
   . = ALIGN(CONFIG_X86_L1_CACHE_BYTES);
-  .jiffies : AT CACHE_ALIGN(AFTER(.xtime)) { *(.jiffies) }
-  jiffies = LOADADDR(.jiffies);
-  .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT (LOADADDR(.vsyscall_0) + 1024) { *(.vsyscall_1) }
-  . = LOADADDR(.vsyscall_0) + 4096;
+  .jiffies : AT(VLOAD(.jiffies)) { *(.jiffies) }
+  jiffies = VVIRT(.jiffies);
+
+  .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1)) { *(.vsyscall_1) }
+  .vsyscall_2 ADDR(.vsyscall_0) + 2048: AT(VLOAD(.vsyscall_2)) { *(.vsyscall_2) }
+  .vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3)) { *(.vsyscall_3) }
+
+  . = VSYSCALL_VIRT_ADDR + 4096;
+
+#undef VSYSCALL_ADDR
+#undef VSYSCALL_PHYS_ADDR
+#undef VSYSCALL_VIRT_ADDR
+#undef VLOAD_OFFSET
+#undef VLOAD
+#undef VVIRT_OFFSET
+#undef VVIRT
 
   . = ALIGN(8192);		/* init_task */
-  .data.init_task : { *(.data.init_task) }
+  .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
+	*(.data.init_task)
+  }
 
   . = ALIGN(4096);
-  .data.page_aligned : { *(.data.page_aligned) }
+  .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
+	*(.data.page_aligned)
+  }
 
   . = ALIGN(4096);		/* Init code and data */
   __init_begin = .;
-  .init.text : { 
+  .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
 	_sinittext = .;
 	*(.init.text)
 	_einittext = .;
   }
   __initdata_begin = .;
-  .init.data : { *(.init.data) }
+  .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) }
   __initdata_end = .;
   . = ALIGN(16);
   __setup_start = .;
-  .init.setup : { *(.init.setup) }
+  .init.setup : AT(ADDR(.init.setup) - LOAD_OFFSET) { *(.init.setup) }
   __setup_end = .;
   __initcall_start = .;
-  .initcall.init : {
+  .initcall.init : AT(ADDR(.initcall.init) - LOAD_OFFSET) {
 	*(.initcall1.init) 
 	*(.initcall2.init) 
 	*(.initcall3.init) 
@@ -106,32 +144,38 @@
   }
   __initcall_end = .;
   __con_initcall_start = .;
-  .con_initcall.init : { *(.con_initcall.init) }
+  .con_initcall.init : AT(ADDR(.con_initcall.init) - LOAD_OFFSET) {
+	*(.con_initcall.init)
+  }
   __con_initcall_end = .;
   SECURITY_INIT
   . = ALIGN(8);
   __alt_instructions = .;
-  .altinstructions : { *(.altinstructions) } 
+  .altinstructions : AT(ADDR(.altinstructions) - LOAD_OFFSET) {
+	*(.altinstructions)
+  }
   __alt_instructions_end = .; 
- .altinstr_replacement : { *(.altinstr_replacement) }
+  .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) {
+	*(.altinstr_replacement)
+  }
   /* .exit.text is discard at runtime, not link time, to deal with references
      from .altinstructions and .eh_frame */
-  .exit.text : { *(.exit.text) }
-  .exit.data : { *(.exit.data) }	
+  .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) }
+  .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) }
   . = ALIGN(4096);
   __initramfs_start = .;
-  .init.ramfs : { *(.init.ramfs) }
+  .init.ramfs : AT(ADDR(.init.ramfs) - LOAD_OFFSET) { *(.init.ramfs) }
   __initramfs_end = .;	
   . = ALIGN(32);
   __per_cpu_start = .;
-  .data.percpu  : { *(.data.percpu) }
+  .data.percpu  : AT(ADDR(.data.percpu) - LOAD_OFFSET) { *(.data.percpu) }
   __per_cpu_end = .;
   . = ALIGN(4096);
   __init_end = .;
 
   . = ALIGN(4096);
   __nosave_begin = .;
-  .data_nosave : { *(.data.nosave) }
+  .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.data.nosave) }
   . = ALIGN(4096);
   __nosave_end = .;
 
diff --git a/arch/x86_64/lib/delay.c b/arch/x86_64/lib/delay.c
index 6e2d664..33a873a 100644
--- a/arch/x86_64/lib/delay.c
+++ b/arch/x86_64/lib/delay.c
@@ -12,6 +12,7 @@
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <asm/delay.h>
+#include <asm/msr.h>
 
 #ifdef CONFIG_SMP
 #include <asm/smp.h>
@@ -19,6 +20,12 @@
 
 int x86_udelay_tsc = 0;		/* Delay via TSC */
 
+int read_current_timer(unsigned long *timer_value)
+{
+	rdtscll(*timer_value);
+	return 0;
+}
+
 void __delay(unsigned long loops)
 {
 	unsigned bclock, now;
@@ -34,7 +41,7 @@
 
 inline void __const_udelay(unsigned long xloops)
 {
-	__delay(((xloops * cpu_data[_smp_processor_id()].loops_per_jiffy) >> 32) * HZ);
+	__delay(((xloops * cpu_data[raw_smp_processor_id()].loops_per_jiffy) >> 32) * HZ);
 }
 
 void __udelay(unsigned long usecs)
diff --git a/arch/x86_64/mm/Makefile b/arch/x86_64/mm/Makefile
index 66c354a..1d232a8 100644
--- a/arch/x86_64/mm/Makefile
+++ b/arch/x86_64/mm/Makefile
@@ -4,7 +4,7 @@
 
 obj-y	 := init.o fault.o ioremap.o extable.o pageattr.o
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
-obj-$(CONFIG_DISCONTIGMEM) += numa.o
+obj-$(CONFIG_NUMA) += numa.o
 obj-$(CONFIG_K8_NUMA) += k8topology.o
 obj-$(CONFIG_ACPI_NUMA) += srat.o
 
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c
index 5d6b211..2f18798 100644
--- a/arch/x86_64/mm/fault.c
+++ b/arch/x86_64/mm/fault.c
@@ -74,7 +74,7 @@
 	instr = (unsigned char *)convert_rip_to_linear(current, regs);
 	max_instr = instr + 15;
 
-	if ((regs->cs & 3) != 0 && instr >= (unsigned char *)TASK_SIZE)
+	if (user_mode(regs) && instr >= (unsigned char *)TASK_SIZE)
 		return 0;
 
 	while (scan_more && instr < max_instr) { 
@@ -106,7 +106,7 @@
 			/* Could check the LDT for lm, but for now it's good
 			   enough to assume that long mode only uses well known
 			   segments or kernel. */
-			scan_more = ((regs->cs & 3) == 0) || (regs->cs == __USER_CS);
+			scan_more = (!user_mode(regs)) || (regs->cs == __USER_CS);
 			break;
 			
 		case 0x60:
@@ -350,7 +350,7 @@
 	 * (error_code & 4) == 0, and that the fault was not a
 	 * protection error (error_code & 1) == 0.
 	 */
-	if (unlikely(address >= TASK_SIZE)) {
+	if (unlikely(address >= TASK_SIZE64)) {
 		if (!(error_code & 5) &&
 		      ((address >= VMALLOC_START && address < VMALLOC_END) ||
 		       (address >= MODULES_VADDR && address < MODULES_END))) {
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c
index dbe53b4..72e4b36 100644
--- a/arch/x86_64/mm/init.c
+++ b/arch/x86_64/mm/init.c
@@ -318,7 +318,7 @@
 	flush_tlb_all();
 }
 
-#ifndef CONFIG_DISCONTIGMEM
+#ifndef CONFIG_NUMA
 void __init paging_init(void)
 {
 	{
@@ -427,13 +427,16 @@
 	reservedpages = 0;
 
 	/* this will put all low memory onto the freelists */
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
 	totalram_pages += numa_free_all_bootmem();
 	tmp = 0;
 	/* should count reserved pages here for all nodes */ 
 #else
+
+#ifdef CONFIG_FLATMEM
 	max_mapnr = end_pfn;
 	if (!mem_map) BUG();
+#endif
 
 	totalram_pages += free_all_bootmem();
 
@@ -515,7 +518,7 @@
 void __init reserve_bootmem_generic(unsigned long phys, unsigned len) 
 { 
 	/* Should check here against the e820 map to avoid double free */ 
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
 	int nid = phys_to_nid(phys);
   	reserve_bootmem_node(NODE_DATA(nid), phys, len);
 #else       		
diff --git a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c
index 58aac23..6972df4 100644
--- a/arch/x86_64/mm/ioremap.c
+++ b/arch/x86_64/mm/ioremap.c
@@ -178,7 +178,7 @@
 	if (phys_addr >= ISA_START_ADDRESS && last_addr < ISA_END_ADDRESS)
 		return (__force void __iomem *)phys_to_virt(phys_addr);
 
-#ifndef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_FLATMEM
 	/*
 	 * Don't allow anybody to remap normal RAM that we're using..
 	 */
diff --git a/arch/x86_64/mm/numa.c b/arch/x86_64/mm/numa.c
index fd9f25d..ac61c18 100644
--- a/arch/x86_64/mm/numa.c
+++ b/arch/x86_64/mm/numa.c
@@ -66,6 +66,13 @@
 	return -1; 
 }
 
+#ifdef CONFIG_SPARSEMEM
+int early_pfn_to_nid(unsigned long pfn)
+{
+	return phys_to_nid(pfn << PAGE_SHIFT);
+}
+#endif
+
 /* Initialize bootmem allocator for a node */
 void __init setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
 { 
@@ -80,6 +87,7 @@
 	start_pfn = start >> PAGE_SHIFT;
 	end_pfn = end >> PAGE_SHIFT;
 
+	memory_present(nodeid, start_pfn, end_pfn);
 	nodedata_phys = find_e820_area(start, end, pgdat_size); 
 	if (nodedata_phys == -1L) 
 		panic("Cannot find memory pgdat in node %d\n", nodeid);
@@ -243,7 +251,7 @@
 	setup_node_bootmem(0, start_pfn << PAGE_SHIFT, end_pfn << PAGE_SHIFT);
 }
 
-__init void numa_add_cpu(int cpu)
+__cpuinit void numa_add_cpu(int cpu)
 {
 	/* BP is initialized elsewhere */
 	if (cpu) 
diff --git a/arch/x86_64/pci/k8-bus.c b/arch/x86_64/pci/k8-bus.c
index 62349c7..7e7d0c2 100644
--- a/arch/x86_64/pci/k8-bus.c
+++ b/arch/x86_64/pci/k8-bus.c
@@ -53,25 +53,11 @@
 				for (j = SECONDARY_LDT_BUS_NUMBER(ldtbus);
 				     j <= SUBORDINATE_LDT_BUS_NUMBER(ldtbus);
 				     j++)
-					pci_bus_to_cpumask[j] =
-						node_to_cpumask(NODE_ID(nid));
+					pci_bus_to_node[j] = NODE_ID(nid);
 			}
 		}
 	}
 
-	/* quick sanity check */
-	printed = 0;
-	for (i = 0; i < 256; i++) {
-		if (cpus_empty(pci_bus_to_cpumask[i])) {
-			pci_bus_to_cpumask[i] = CPU_MASK_ALL;
-			if (printed)
-				continue;
-			printk(KERN_ERR
-			       "k8-bus.c: some busses have empty cpu mask\n");
-			printed = 1;
-		}
-	}
-
 	return 0;
 }
 
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
new file mode 100644
index 0000000..3e89767
--- /dev/null
+++ b/arch/xtensa/Kconfig
@@ -0,0 +1,258 @@
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/config-language.txt.
+
+mainmenu "Linux/Xtensa Kernel Configuration"
+
+config FRAME_POINTER
+	bool
+	default n
+
+config XTENSA
+	bool
+	default y
+	help
+	  Xtensa processors are 32-bit RISC machines designed by Tensilica
+	  primarily for embedded systems.  These processors are both
+	  configurable and extensible.  The Linux port to the Xtensa
+	  architecture supports all processor configurations and extensions,
+	  with reasonable minimum requirements.  The Xtensa Linux project has
+	  a home page at <http://xtensa.sourceforge.net/>.
+
+config UID16
+	bool
+	default n
+
+config RWSEM_XCHGADD_ALGORITHM
+	bool
+	default y
+
+config HAVE_DEC_LOCK
+	bool
+	default y
+
+config GENERIC_HARDIRQS
+	bool
+	default y
+
+source "init/Kconfig"
+
+menu "Processor type and features"
+
+choice
+	prompt "Xtensa Processor Configuration"
+	default XTENSA_CPU_LINUX_BE
+
+config XTENSA_CPU_LINUX_BE
+	bool "linux_be"
+	---help---
+	  The linux_be processor configuration is the baseline Xtensa
+	  configurations included in this kernel and also used by
+	  binutils, gcc, and gdb. It contains no TIE, no coprocessors,
+	  and the following configuration options:
+
+	  Code Density Option                2 Misc Special Registers
+	  NSA/NSAU Instructions              128-bit Data Bus Width
+	  Processor ID                       8K, 2-way I and D Caches
+	  Zero-Overhead Loops                2 Inst Address Break Registers
+	  Big Endian                         2 Data Address Break Registers
+	  64 General-Purpose Registers       JTAG Interface and Trace Port
+	  17 Interrupts                      MMU w/ TLBs and Autorefill
+	  3 Interrupt Levels                 8 Autorefill Ways (I/D TLBs)
+	  3 Timers                           Unaligned Exceptions
+endchoice
+
+config MMU
+	bool
+	default y
+
+config XTENSA_UNALIGNED_USER
+	bool "Unaligned memory access in use space"
+	---help---
+	   The Xtensa architecture currently does not handle unaligned
+	   memory accesses in hardware but through an exception handler.
+	   Per default, unaligned memory accesses are disabled in user space.
+
+	   Say Y here to enable unaligned memory access in user space.
+
+config PREEMPT
+	bool "Preemptible Kernel"
+	---help---
+           This option reduces the latency of the kernel when reacting to
+           real-time or interactive events by allowing a low priority process to
+           be preempted even if it is in kernel mode executing a system call.
+           Unfortunately the kernel code has some race conditions if both
+           CONFIG_SMP and CONFIG_PREEMPT are enabled, so this option is
+           currently disabled if you are building an SMP kernel.
+
+           Say Y here if you are building a kernel for a desktop, embedded
+           or real-time system.  Say N if you are unsure.
+
+config MATH_EMULATION
+	bool "Math emulation"
+	help
+	Can we use information of configuration file?
+
+config HIGHMEM
+	bool "High memory support"
+
+endmenu
+
+menu "Platform options"
+
+choice
+	prompt "Xtensa System Type"
+	default XTENSA_PLATFORM_ISS
+
+config XTENSA_PLATFORM_ISS
+	bool "ISS"
+	help
+	  ISS is an acronym for Tensilica's Instruction Set Simulator.
+
+config XTENSA_PLATFORM_XT2000
+	bool "XT2000"
+	help
+	  XT2000 is the name of Tensilica's feature-rich emulation platform.
+	  This hardware is capable of running a full Linux distribution.
+
+endchoice
+
+
+config XTENSA_CALIBRATE_CCOUNT
+	bool "Auto calibration of the CPU clock rate"
+	---help---
+	  On some platforms (XT2000, for example), the CPU clock rate can
+	  vary.  The frequency can be determined, however, by measuring
+	  against a well known, fixed frequency, such as an UART oscillator.
+
+config XTENSA_CPU_CLOCK
+	int "CPU clock rate [MHz]"
+	depends on !XTENSA_CALIBRATE_CCOUNT
+	default "16"
+
+config GENERIC_CALIBRATE_DELAY
+	bool "Auto calibration of the BogoMIPS value"
+	---help---
+	  The BogoMIPS value can easily derived from the CPU frequency.
+
+config CMDLINE_BOOL
+	bool "Default bootloader kernel arguments"
+
+config CMDLINE
+	string "Initial kernel command string"
+	depends on CMDLINE_BOOL
+	default "console=ttyS0,38400 root=/dev/ram"
+	help
+	  On some architectures (EBSA110 and CATS), there is currently no way
+	  for the boot loader to pass arguments to the kernel. For these
+	  architectures, you should supply some command-line options at build
+	  time by entering them here. As a minimum, you should specify the
+	  memory size and the root device (e.g., mem=64M root=/dev/nfs).
+
+config SERIAL_CONSOLE
+	bool
+	depends on XTENSA_PLATFORM_ISS
+	default y
+
+config XTENSA_ISS_NETWORK
+	bool
+	depends on XTENSA_PLATFORM_ISS
+	default y
+
+endmenu
+
+menu "Bus options"
+
+config PCI
+	bool "PCI support" if !XTENSA_PLATFORM_ISS
+	depends on !XTENSA_PLATFORM_ISS
+	default y
+	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
+	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
+	  VESA. If you have PCI, say Y, otherwise N.
+
+	  The PCI-HOWTO, available from
+	  <http://www.linuxdoc.org/docs.html#howto>, contains valuable
+	  information about which PCI hardware does work under Linux and which
+	  doesn't
+
+source "drivers/pci/Kconfig"
+
+config HOTPLUG
+
+	bool "Support for hot-pluggable devices"
+	---help---
+	Say Y here if you want to plug devices into your computer while
+	the system is running, and be able to use them quickly.  In many
+	cases, the devices can likewise be unplugged at any time too.
+
+	One well known example of this is PCMCIA- or PC-cards, credit-card
+	size devices such as network cards, modems or hard drives which are
+	plugged into slots found on all modern laptop computers.  Another
+	example, used on modern desktops as well as laptops, is USB.
+
+	Enable HOTPLUG and KMOD, and build a modular kernel.  Get agent
+	software (at <http://linux-hotplug.sourceforge.net/>) and install it.
+	Then your kernel will automatically call out to a user mode "policy
+	agent" (/sbin/hotplug) to load modules and set up software needed
+	to use devices as you hotplug them.
+
+source "drivers/pcmcia/Kconfig"
+
+source "drivers/pci/hotplug/Kconfig"
+
+endmenu
+
+menu "Exectuable file formats"
+
+# only elf supported
+config KCORE_ELF
+        bool
+        depends on PROC_FS
+        default y
+        help
+          If you enabled support for /proc file system then the file
+          /proc/kcore will contain the kernel core image in ELF format. This
+          can be used in gdb:
+
+          $ cd /usr/src/linux ; gdb vmlinux /proc/kcore
+
+          This is especially useful if you have compiled the kernel with the
+          "-g" option to preserve debugging information. It is mainly used
+	  for examining kernel data structures on the live kernel.
+
+source "fs/Kconfig.binfmt"
+
+endmenu
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+menu "Xtensa initrd options"
+	depends on BLK_DEV_INITRD
+
+	config EMBEDDED_RAMDISK
+	bool "Embed root filesystem ramdisk into the kernel"
+
+config EMBEDDED_RAMDISK_IMAGE
+	string "Filename of gziped ramdisk image"
+	depends on EMBEDDED_RAMDISK
+	default "ramdisk.gz"
+	help
+	  This is the filename of the ramdisk image to be built into the
+	  kernel.  Relative pathnames are relative to arch/xtensa/boot/ramdisk/.
+	  The ramdisk image is not part of the kernel distribution; you must
+	  provide one yourself.
+endmenu
+
+source "arch/xtensa/Kconfig.debug"
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
+
+
diff --git a/arch/xtensa/Kconfig.debug b/arch/xtensa/Kconfig.debug
new file mode 100644
index 0000000..11c5852
--- /dev/null
+++ b/arch/xtensa/Kconfig.debug
@@ -0,0 +1,7 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+endmenu
+
+
diff --git a/arch/xtensa/Makefile b/arch/xtensa/Makefile
new file mode 100644
index 0000000..4fa2745
--- /dev/null
+++ b/arch/xtensa/Makefile
@@ -0,0 +1,102 @@
+#
+# 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) 2001 - 2005  Tensilica Inc.
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies. Remember to do have actions
+# for "archclean" and "archdep" for cleaning up and making dependencies for
+# this architecture
+
+# Core configuration.
+# (Use CPU=<xtensa_config> to use another default compiler.)
+
+cpu-$(CONFIG_XTENSA_CPU_LINUX_BE)	:= linux_be
+cpu-$(CONFIG_XTENSA_CPU_LINUX_CUSTOM)	:= linux_custom
+
+CPU = $(cpu-y)
+export CPU
+
+# Platform configuration
+
+platform-y					:= common
+platform-$(CONFIG_XTENSA_PLATFORM_XT2000)	:= xt2000
+platform-$(CONFIG_XTENSA_PLATFORM_ISS)		:= iss
+
+PLATFORM = $(platform-y)
+export PLATFORM
+
+#LDFLAGS_vmlinux		:= -T$(word 1,$(LINKSCRIPT))
+AFLAGS_vmlinux.lds.o	:= -Uxtensa
+CPPFLAGS		+= -Iarch/xtensa -Iinclude/asm  -mlongcalls  -g
+AFLAGS			+= -Iarch/xtensa -Iinclude/asm
+CPP			= $(CC) -E $(CFLAGS)
+
+cflags-y	+= -Iarch/xtensa -pipe -mlongcalls
+
+
+KBUILD_DEFCONFIG := common_defconfig
+
+# ramdisk/initrd support
+# You need a compressed ramdisk image, named ramdisk.gz in
+# arch/xtensa/boot/ramdisk
+
+core-$(CONFIG_EMBEDDED_RAMDISK)	+= arch/xtensa/boot/ramdisk/
+
+# Test for cross compiling
+
+ifneq ($(CPU),)
+  COMPILE_ARCH = $(shell uname -m)
+
+  ifneq ($(COMPILE_ARCH), xtensa)
+    ifndef CROSS_COMPILE
+      CROSS_COMPILE = xtensa_$(CPU)-
+    endif
+  endif
+endif
+
+#
+
+LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
+
+head-y		:= arch/xtensa/kernel/head.o
+core-y		+= arch/xtensa/kernel/ \
+		   arch/xtensa/mm/ arch/xtensa/platform-$(PLATFORM)/
+libs-y		+= arch/xtensa/lib/ $(LIBGCC)
+
+boot	:= arch/xtensa/boot
+
+arch/xtensa/kernel/asm-offsets.s: \
+	arch/xtensa/kernel/asm-offsets.c \
+	include/asm-xtensa/.platform
+
+include/asm-xtensa/offsets.h: arch/xtensa/kernel/asm-offsets.s
+	$(call filechk,gen-asm-offsets)
+
+prepare: include/asm-xtensa/.platform include/asm-xtensa/offsets.h
+
+# Update machine cpu and platform symlinks if something which affects
+# them changed.
+
+include/asm-xtensa/.platform: $(wildcard include/config/arch/*.h)
+	@echo '  Setting up cpu ($(CPU)) and platform ($(PLATFORM)) symlinks'
+	$(Q)rm -f include/asm-xtensa/platform
+	$(Q)rm -f include/asm-xtensa/xtensa/config
+	$(Q)(cd include/asm-xtensa/; ln -sf platform-$(PLATFORM) platform)
+	$(Q)(cd include/asm-xtensa/xtensa; ln -sf config-$(CPU) config)
+
+all: zImage
+
+bzImage : zImage
+
+zImage zImage.initrd: vmlinux
+	$(Q)$(MAKE) $(build)=$(boot) $@
+
+CLEAN_FILES	+= arch/xtensa/vmlinux.lds include/asm-xtensa/offset.h
+
+define archhelp
+  @echo '* zImage      - Compressed kernel image (arch/xtensa/boot/images/zImage.*)'
+endef
+
diff --git a/arch/xtensa/boot/Makefile b/arch/xtensa/boot/Makefile
new file mode 100644
index 0000000..260f456
--- /dev/null
+++ b/arch/xtensa/boot/Makefile
@@ -0,0 +1,37 @@
+#
+# arch/xtensa/boot/Makefile
+#
+# 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.
+#
+#
+
+
+CFLAGS 		+= -fno-builtin -Iarch/$(ARCH)/boot/include
+HOSTFLAGS	+= -Iarch/$(ARCH)/boot/include
+
+BIG_ENDIAN	:= $(shell echo -e "\#ifdef __XTENSA_EL__\nint little;\n\#else\nint big;\n\#endif" | $(CC) -E -|grep -c big)
+
+
+export CFLAGS
+export AFLAGS
+export BIG_ENDIAN
+
+# Subdirs for the boot loader(s)
+
+bootdir-$(CONFIG_XTENSA_PLATFORM_ISS)	 += boot-elf
+bootdir-$(CONFIG_XTENSA_PLATFORM_XT2000) += boot-redboot boot-elf
+
+subdir-y	:= lib/
+
+subdir-y	+= boot-elf/ boot-redboot/
+
+zImage zImage.initrd Image Image.initrd: $(bootdir-y)
+
+$(bootdir-y): $(addprefix $(obj)/,$(subdir-y)) \
+	      $(addprefix $(obj)/,$(host-progs))
+	$(Q)$(MAKE) $(build)=$(obj)/$@ $(MAKECMDGOALS)
+
+
+
diff --git a/arch/xtensa/boot/boot-elf/Makefile b/arch/xtensa/boot/boot-elf/Makefile
new file mode 100644
index 0000000..f6ef6a3
--- /dev/null
+++ b/arch/xtensa/boot/boot-elf/Makefile
@@ -0,0 +1,52 @@
+#
+# 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.
+#
+
+GZIP = gzip
+GZIP_FLAGS = -v9fc
+
+ifeq ($(BIG_ENDIAN),1)
+OBJCOPY_ARGS    := -O elf32-xtensa-be
+else
+OBJCOPY_ARGS    := -O elf32-xtensa-le
+endif
+
+export OBJCOPY_ARGS
+
+boot-y		:= bootstrap.o
+
+OBJS		:= $(addprefix $(obj)/,$(boot-y))
+
+Image:	vmlinux $(OBJS)
+	$(OBJCOPY) --strip-all -R .comment -R .xt.insn -O binary \
+		vmlinux vmlinux.tmp
+	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
+		--add-section image=vmlinux.tmp \
+		--set-section-flags image=contents,alloc,load,load,data \
+		$(OBJS) $@.tmp
+	$(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) \
+		-T arch/$(ARCH)/boot/boot-elf/boot.ld \
+		-o arch/$(ARCH)/boot/$@.elf $@.tmp
+	rm -f $@.tmp vmlinux.tmp
+
+Image.initrd:	vmlinux $(OBJS)
+	$(OBJCOPY) --strip-all -R .comment -R .xt.insn -O binary \
+		--add-section .initrd=arch/$(ARCH)/boot/ramdisk \
+		--set-section-flags .initrd=contents,alloc,load,load,data \
+		vmlinux vmlinux.tmp
+	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
+		--add-section image=vmlinux.tmp \
+		--set-section-flags image=contents,alloc,load,load,data \
+		$(OBJS) $@.tmp
+	$(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) \
+		-T arch/$(ARCH)/boot/boot-elf/boot.ld \
+		-o arch/$(ARCH)/boot/$@.elf $@.tmp
+	rm -f $@.tmp vmlinux.tmp
+
+
+zImage:	Image
+
+zImage.initrd:	Image.initrd
+
diff --git a/arch/xtensa/boot/boot-elf/boot.ld b/arch/xtensa/boot/boot-elf/boot.ld
new file mode 100644
index 0000000..4ab06a0
--- /dev/null
+++ b/arch/xtensa/boot/boot-elf/boot.ld
@@ -0,0 +1,71 @@
+OUTPUT_ARCH(xtensa)
+
+SECTIONS
+{
+	.start 0xD0000000 : { *(.start) }
+
+	.text 0xD0000000:
+	{
+		__reloc_start = . ;
+		_text_start = . ;
+		*(.literal .text.literal .text)
+		_text_end = . ;
+	}
+
+	.rodata ALIGN(0x04):
+	{
+		*(.rodata)
+		*(.rodata1)
+	}
+
+	.data ALIGN(0x04):
+	{
+		*(.data)
+		*(.data1)
+		*(.sdata)
+		*(.sdata2)
+		*(.got.plt)
+		*(.got)
+		*(.dynamic)
+	}
+
+	__reloc_end = . ;
+
+	.initrd ALIGN(0x10) :
+	{
+		boot_initrd_start = . ;
+		*(.initrd)
+		boot_initrd_end = .;
+	}
+
+	. = ALIGN(0x10);
+	__image_load = . ;
+	.image 0xd0001000:
+	{
+		_image_start = .;
+		*(image)
+		. = (. + 3) & ~ 3;
+		_image_end = .	;
+	}
+
+
+	.bss ((LOADADDR(.image) + SIZEOF(.image) + 3) & ~ 3):
+	{
+		__bss_start = .;
+		*(.sbss)
+		*(.scommon)
+		*(.dynbss)
+		*(.bss)
+		__bss_end = .;
+	}
+	_end = .;
+	_param_start = .;
+
+	.ResetVector.text 0xfe000020 :
+	{
+		*(.ResetVector.text)
+	}
+
+
+	PROVIDE (end = .);
+}
diff --git a/arch/xtensa/boot/boot-elf/bootstrap.S b/arch/xtensa/boot/boot-elf/bootstrap.S
new file mode 100644
index 0000000..7cba94a
--- /dev/null
+++ b/arch/xtensa/boot/boot-elf/bootstrap.S
@@ -0,0 +1,37 @@
+
+#include <xtensa/config/specreg.h>
+#include <xtensa/config/core.h>
+
+#include <linux/config.h>
+#include <asm/bootparam.h>
+
+
+/* ResetVector
+ */
+	.section        .ResetVector.text, "ax"
+	.global         _ResetVector
+_ResetVector:
+	_j reset
+	.align 4
+RomInitAddr:
+	.word 0xd0001000
+RomBootParam:
+	.word _bootparam
+reset:
+	l32r    a0, RomInitAddr
+	l32r	a2, RomBootParam
+	movi	a3, 0
+	movi	a4, 0
+	jx      a0
+
+	.align 4
+	.section .bootstrap.data, "aw"
+
+	.globl _bootparam
+_bootparam:
+	.short	BP_TAG_FIRST
+	.short	4
+	.long	BP_VERSION
+	.short	BP_TAG_LAST
+	.short	0
+	.long	0
diff --git a/arch/xtensa/boot/boot-redboot/Makefile b/arch/xtensa/boot/boot-redboot/Makefile
new file mode 100644
index 0000000..ca8a68b
--- /dev/null
+++ b/arch/xtensa/boot/boot-redboot/Makefile
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+
+GZIP = gzip
+GZIP_FLAGS = -v9fc
+ifeq ($(BIG_ENDIAN),1)
+OBJCOPY_ARGS 	:= -O elf32-xtensa-be
+else
+OBJCOPY_ARGS 	:= -O elf32-xtensa-le
+endif
+
+LD_ARGS	= -T $(obj)/boot.ld
+
+boot-y	:= bootstrap.o
+
+OBJS	:= $(addprefix $(obj)/,$(boot-y))
+LIBS	:= arch/$(ARCH)/boot/lib/lib.a arch/$(ARCH)/lib/lib.a
+
+LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
+
+zImage: vmlinux $(OBJS) $(LIBS)
+	$(OBJCOPY) --strip-all -R .comment -R .xt.insn -O binary \
+		$(TOPDIR)/vmlinux vmlinux.tmp
+	gzip -vf9 vmlinux.tmp
+	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
+		--add-section image=vmlinux.tmp.gz \
+		--set-section-flags image=contents,alloc,load,load,data \
+		$(OBJS) $@.tmp
+	$(LD) $(LD_ARGS) -o $@.elf $@.tmp $(LIBS) -L/xtensa-elf/lib $(LIBGCC)
+	$(OBJCOPY) -S -O binary $@.elf arch/$(ARCH)/boot/images/$@.redboot
+#	rm -f $@.tmp $@.elf vmlinux.tmp.gz
+
diff --git a/arch/xtensa/boot/boot-redboot/boot.ld b/arch/xtensa/boot/boot-redboot/boot.ld
new file mode 100644
index 0000000..65b7264
--- /dev/null
+++ b/arch/xtensa/boot/boot-redboot/boot.ld
@@ -0,0 +1,66 @@
+OUTPUT_ARCH(xtensa)
+
+SECTIONS
+{
+	.start 0xD0200000 : { *(.start) }
+
+	.text :
+	{
+		__reloc_start = . ;
+		_text_start = . ;
+		*(.literal .text.literal .text)
+		_text_end = . ;
+	}
+
+	.rodata ALIGN(0x04):
+	{
+		*(.rodata)
+		*(.rodata1)
+	}
+
+	.data ALIGN(0x04):
+	{
+		*(.data)
+		*(.data1)
+		*(.sdata)
+		*(.sdata2)
+		*(.got.plt)
+		*(.got)
+		*(.dynamic)
+	}
+
+	__reloc_end = . ;
+
+	.initrd ALIGN(0x10) :
+	{
+		boot_initrd_start = . ;
+		*(.initrd)
+		boot_initrd_end = .;
+	}
+
+	. = ALIGN(0x10);
+	__image_load = . ;
+	.image 0xd0001000: AT(__image_load)
+	{
+		_image_start = .;
+		*(image)
+		. = (. + 3) & ~ 3;
+		_image_end = .	;
+	}
+
+
+	.bss ((LOADADDR(.image) + SIZEOF(.image) + 3) & ~ 3):
+	{
+		__bss_start = .;
+		*(.sbss)
+		*(.scommon)
+		*(.dynbss)
+		*(.bss)
+		__bss_end = .;
+	}
+	_end = .;
+	_param_start = .;
+
+
+	PROVIDE (end = .);
+}
diff --git a/arch/xtensa/boot/boot-redboot/bootstrap.S b/arch/xtensa/boot/boot-redboot/bootstrap.S
new file mode 100644
index 0000000..ee636b0
--- /dev/null
+++ b/arch/xtensa/boot/boot-redboot/bootstrap.S
@@ -0,0 +1,246 @@
+
+#define _ASMLANGUAGE
+#include <xtensa/config/specreg.h>
+#include <xtensa/config/core.h>
+#include <xtensa/cacheasm.h>
+
+	/*
+	 * RB-Data: RedBoot data/bss
+	 * P:	    Boot-Parameters
+	 * L:	    Kernel-Loader
+	 *
+	 * The Linux-Kernel image including the loader must be loaded
+	 * to a position so that the kernel and the boot parameters
+	 * can fit in the space before the load address.
+	 *  ______________________________________________________
+	 * |_RB-Data_|_P_|__________|_L_|___Linux-Kernel___|______|
+	 *                          ^
+	 *                          ^ Load address
+	 *  ______________________________________________________
+	 * |___Linux-Kernel___|_P_|_L_|___________________________|
+	 *
+	 * The loader copies the parameter to the position that will
+	 * be the end of the kernel and itself to the end of the
+	 * parameter list.
+	 */
+
+/* Make sure we have enough space for the 'uncompressor' */
+
+#define STACK_SIZE 32768
+#define HEAP_SIZE (131072*4)
+
+	# a2: Parameter list
+	# a3: Size of parameter list
+
+	.section .start, "ax"
+
+	.globl __start
+	/* this must be the first byte of the loader! */
+__start:
+	entry	sp, 32		# we do not intend to return
+	_call0	_start
+__start_a0:
+	.align 4
+
+	.section .text, "ax"
+	.begin literal_prefix .text
+
+	/* put literals in here! */
+
+	.globl _start
+_start:
+
+	/* 'reset' window registers */
+
+	movi	a4, 1
+	wsr	a4, PS
+	rsync
+
+	rsr	a5, WINDOWBASE
+	ssl	a5
+	sll	a4, a4
+	wsr	a4, WINDOWSTART
+	rsync
+
+	movi	a4, 0x00040000
+	wsr	a4, PS
+	rsync
+
+	/* copy the loader to its address
+	 * Note: The loader itself is a very small piece, so we assume we
+	 *       don't partially overlap. We also assume (even more important)
+	 *	 that the kernel image is out of the way. Usually, when the
+	 *	 load address of this image is not at an arbitrary address,
+	 *	 but aligned to some 10K's we shouldn't overlap.
+	 */
+
+	/* Note: The assembler cannot relax "addi a0, a0, ..." to an
+	   l32r, so we load to a4 first. */
+
+	addi	a4, a0, __start - __start_a0
+	mov	a0, a4
+	movi	a4, __start
+	movi	a5, __reloc_end
+
+	# a0: address where this code has been loaded
+	# a4: compiled address of __start
+	# a5: compiled end address
+
+	mov.n	a7, a0
+	mov.n	a8, a4
+
+1:
+	l32i	a10, a7, 0
+	l32i	a11, a7, 4
+	s32i	a10, a8, 0
+	s32i	a11, a8, 4
+	l32i	a10, a7, 8
+	l32i	a11, a7, 12
+	s32i	a10, a8, 8
+	s32i	a11, a8, 12
+	addi	a8, a8, 16
+	addi	a7, a7, 16
+	blt	a8, a5, 1b
+
+
+	/* We have to flush and invalidate the caches here before we jump. */
+
+#if XCHAL_DCACHE_IS_WRITEBACK
+	dcache_writeback_all  a5, a6
+#endif
+	icache_invalidate_all a5, a6
+
+	movi	a11, _reloc
+	jx	a11
+
+	.globl _reloc
+_reloc:
+
+	/* RedBoot is now at the end of the memory, so we don't have
+	 * to copy the parameter list. Keep the code around; in case
+	 * we need it again. */
+#if 0
+	# a0: load address
+	# a2: start address of parameter list
+	# a3: length of parameter list
+	# a4: __start
+
+	/* copy the parameter list out of the way */
+
+	movi	a6, _param_start
+	add	a3, a2, a3
+2:
+	l32i	a8, a2, 0
+	s32i	a8, a6, 0
+	addi	a2, a2, 4
+	addi	a6, a6, 4
+	blt	a2, a3, 2b
+#endif
+
+	/* clear BSS section */
+	movi	a6, __bss_start
+	movi	a7, __bss_end
+	movi.n	a5, 0
+3:
+	s32i	a5, a6, 0
+	addi	a6, a6, 4
+	blt	a6, a7, 3b
+
+	movi	a5, -16
+	movi	a1, _stack + STACK_SIZE
+	and	a1, a1, a5
+
+	/* Uncompress the kernel */
+
+	# a0: load address
+	# a2: boot parameter
+	# a4: __start
+
+	movi	a3, __image_load
+	sub	a4, a3, a4
+	add	a8, a0, a4
+
+	# a1  Stack
+	# a8(a4)  Load address of the image
+
+	movi	a6, _image_start
+	movi	a10, _image_end
+	movi	a7, 0x1000000
+	sub	a11, a10, a6
+	movi	a9, complen
+	s32i	a11, a9, 0
+
+	movi	a0, 0
+
+	# a6 destination
+	# a7 maximum size of destination
+	# a8 source
+	# a9 ptr to length
+
+	.extern gunzip
+	movi	a4, gunzip
+	beqz	a4, 1f
+
+	callx4	a4
+
+	j	2f
+
+
+	# a6 destination start
+	# a7 maximum size of destination
+	# a8 source start
+	# a9 ptr to length
+	# a10 destination end
+
+1:
+        l32i    a9, a8, 0
+        l32i    a11, a8, 4
+        s32i    a9, a6, 0
+        s32i    a11, a6, 4
+        l32i    a9, a8, 8
+        l32i    a11, a8, 12
+        s32i    a9, a6, 8
+        s32i    a11, a6, 12
+        addi    a6, a6, 16
+        addi    a8, a8, 16
+        blt     a6, a10, 1b
+
+
+	/* jump to the kernel */
+2:
+#if XCHAL_DCACHE_IS_WRITEBACK
+	dcache_writeback_all a5, a6
+#endif
+	icache_invalidate_all a5, a6
+
+	movi	a5, __start
+	movi	a3, boot_initrd_start
+	movi	a4, boot_initrd_end
+	sub	a3, a3, a5
+	sub	a4, a4, a5
+	add	a3, a0, a3
+	add	a4, a0, a4
+
+	# a2  Boot parameter list
+	# a3  initrd_start (virtual load address)
+	# a4  initrd_end   (virtual load address)
+
+	movi	a0, _image_start
+	jx	a0
+
+	.align 16
+	.data
+	.globl avail_ram
+avail_ram:
+	.long	_heap
+	.globl end_avail
+end_avail:
+	.long	_heap + HEAP_SIZE
+
+	.comm _stack, STACK_SIZE
+	.comm _heap, HEAP_SIZE
+
+	.globl end_avail
+	.comm complen, 4
+
+	.end	literal_prefix
diff --git a/arch/xtensa/boot/include/zlib.h b/arch/xtensa/boot/include/zlib.h
new file mode 100644
index 0000000..ea29b62
--- /dev/null
+++ b/arch/xtensa/boot/include/zlib.h
@@ -0,0 +1,433 @@
+/*
+ * BK Id: SCCS/s.zlib.h 1.8 05/18/01 15:17:23 cort
+ */
+/*
+ * This file is derived from zlib.h and zconf.h from the zlib-0.95
+ * distribution by Jean-loup Gailly and Mark Adler, with some additions
+ * by Paul Mackerras to aid in implementing Deflate compression and
+ * decompression for PPP packets.
+ */
+
+/*
+ *  ==FILEVERSION 960122==
+ *
+ * This marker is used by the Linux installation script to determine
+ * whether an up-to-date version of this file is already installed.
+ */
+
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+  version 0.95, Aug 16th, 1995.
+
+  Copyright (C) 1995 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
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  gzip@prep.ai.mit.edu    madler@alumni.caltech.edu
+ */
+
+#ifndef _ZLIB_H
+#define _ZLIB_H
+
+/* #include "zconf.h" */	/* included directly here */
+
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* From: zconf.h,v 1.12 1995/05/03 17:27:12 jloup Exp */
+
+/*
+     The library does not install any signal handler. It is recommended to
+  add at least a handler for SIGSEGV when decompressing; the library checks
+  the consistency of the input data whenever possible but may go nuts
+  for some forms of corrupted input.
+ */
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ * Compile with -DUNALIGNED_OK if it is OK to access shorts or ints
+ * at addresses which are not a multiple of their size.
+ * Under DOS, -DFAR=far or -DFAR=__far may be needed.
+ */
+
+#ifndef STDC
+#  if defined(MSDOS) || defined(__STDC__) || defined(__cplusplus)
+#    define STDC
+#  endif
+#endif
+
+#ifdef	__MWERKS__ /* Metrowerks CodeWarrior declares fileno() in unix.h */
+#  include <unix.h>
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  ifdef MAXSEG_64K
+#    define MAX_MEM_LEVEL 8
+#  else
+#    define MAX_MEM_LEVEL 9
+#  endif
+#endif
+
+#ifndef FAR
+#  define FAR
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2 */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            1 << (windowBits+2)   +  1 << (memLevel+9)
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+typedef unsigned char  Byte;  /* 8 bits */
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+typedef Byte FAR Bytef;
+typedef char FAR charf;
+typedef int FAR intf;
+typedef uInt FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+   typedef void FAR *voidpf;
+   typedef void     *voidp;
+#else
+   typedef Byte FAR *voidpf;
+   typedef Byte     *voidp;
+#endif
+
+/* end of original zconf.h */
+
+#define ZLIB_VERSION "0.95P"
+
+/*
+     The 'zlib' compression library provides in-memory compression and
+  decompression functions, including integrity checks of the uncompressed
+  data.  This version of the library supports only one compression method
+  (deflation) but other algorithms may be added later and will have the same
+  stream interface.
+
+     For compression the application must provide the output buffer and
+  may optionally provide the input buffer for optimization. For decompression,
+  the application must provide the input buffer and may optionally provide
+  the output buffer for optimization.
+
+     Compression can be done in a single step if the buffers are large
+  enough (for example if an input file is mmap'ed), or can be done by
+  repeated calls of the compression function.  In the latter case, the
+  application must provide more input and/or consume the output
+  (providing more output space) before each call.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void   (*free_func)  OF((voidpf opaque, voidpf address, uInt nbytes));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+    Bytef    *next_in;  /* next input byte */
+    uInt     avail_in;  /* number of bytes available at next_in */
+    uLong    total_in;  /* total nb of input bytes read so far */
+
+    Bytef    *next_out; /* next output byte should be put there */
+    uInt     avail_out; /* remaining free space at next_out */
+    uLong    total_out; /* total nb of bytes output so far */
+
+    char     *msg;      /* last error message, NULL if no error */
+    struct internal_state FAR *state; /* not visible by applications */
+
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    voidp      opaque;  /* private data object passed to zalloc and zfree */
+
+    Byte     data_type; /* best guess about the data type: ascii or binary */
+
+} z_stream;
+
+/*
+   The application must update next_in and avail_in when avail_in has
+   dropped to zero. It must update next_out and avail_out when avail_out
+   has dropped to zero. The application must initialize zalloc, zfree and
+   opaque before calling the init function. All other fields are set by the
+   compression library and must not be updated by the application.
+
+   The opaque value provided by the application will be passed as the first
+   parameter for calls of zalloc and zfree. This can be useful for custom
+   memory management. The compression library attaches no meaning to the
+   opaque value.
+
+   zalloc must return Z_NULL if there is not enough memory for the object.
+   On 16-bit systems, the functions zalloc and zfree must be able to allocate
+   exactly 65536 bytes, but will not be required to allocate more than this
+   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+   pointers returned by zalloc for objects of exactly 65536 bytes *must*
+   have their offset normalized to zero. The default allocation function
+   provided by this library ensures this (see zutil.c). To reduce memory
+   requirements and avoid any allocation of 64K objects, at the expense of
+   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+   The fields total_in and total_out can be used for statistics or
+   progress reports. After compression, total_in holds the total size of
+   the uncompressed data and may be saved for use in the decompressor
+   (particularly if the decompressor wants to decompress everything in
+   a single step).
+*/
+
+                        /* constants */
+
+#define Z_NO_FLUSH      0
+#define Z_PARTIAL_FLUSH 1
+#define Z_FULL_FLUSH    2
+#define Z_SYNC_FLUSH    3 /* experimental: partial_flush + byte align */
+#define Z_FINISH        4
+#define Z_PACKET_FLUSH	5
+/* See deflate() below for the usage of these constants */
+
+#define Z_OK            0
+#define Z_STREAM_END    1
+#define Z_ERRNO        (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR   (-3)
+#define Z_MEM_ERROR    (-4)
+#define Z_BUF_ERROR    (-5)
+/* error codes for the compression/decompression functions */
+
+#define Z_BEST_SPEED             1
+#define Z_BEST_COMPRESSION       9
+#define Z_DEFAULT_COMPRESSION  (-1)
+/* compression levels */
+
+#define Z_FILTERED            1
+#define Z_HUFFMAN_ONLY        2
+#define Z_DEFAULT_STRATEGY    0
+
+#define Z_BINARY   0
+#define Z_ASCII    1
+#define Z_UNKNOWN  2
+/* Used to set the data_type field */
+
+#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
+
+extern char *zlib_version;
+/* The application can compare zlib_version 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.
+ */
+
+                        /* basic functions */
+
+extern int inflateInit OF((z_stream *strm));
+/*
+     Initializes the internal stream state for decompression. The fields
+   zalloc and zfree must be initialized before by the caller.  If zalloc and
+   zfree are set to Z_NULL, inflateInit updates them to use default allocation
+   functions.
+
+     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory.  msg is set to null if there is no error message.
+   inflateInit does not perform any decompression: this will be done by
+   inflate().
+*/
+
+
+extern int inflate OF((z_stream *strm, int flush));
+/*
+  Performs one or both of the following actions:
+
+  - Decompress more input starting at next_in and update next_in and avail_in
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), next_in is updated and processing
+    will resume at this point for the next call of inflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly.  inflate() always provides as much output as possible
+    (until there is no more input data or no more space in the output buffer).
+
+  Before the call of inflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating the next_* and avail_* values accordingly.
+  The application can consume the uncompressed output when it wants, for
+  example when the output buffer is full (avail_out == 0), or after each
+  call of inflate().
+
+    If the parameter flush is set to Z_PARTIAL_FLUSH or Z_PACKET_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_PARTIAL_FLUSH, Z_PACKET_FLUSH or Z_FINISH, but the
+  current implementation actually flushes as much output as possible
+  anyway.  For Z_PACKET_FLUSH, inflate checks that once all the input data
+  has been consumed, it is expecting to see the length field of a stored
+  block; if not, it returns Z_DATA_ERROR.
+
+    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
+  (a single call of inflate), the parameter flush should be set to
+  Z_FINISH. In this case all pending input is processed and all pending
+  output is flushed; avail_out must be large enough to hold all the
+  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
+  may be used for the single inflate() call.
+
+    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_DATA_ERROR if the input data was corrupted, 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.  */
+
+
+extern int inflateEnd OF((z_stream *strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+
+     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+   was inconsistent. In the error case, msg may be set but then points to a
+   static string (which must not be deallocated).
+*/
+
+                        /* advanced functions */
+
+extern int inflateInit2 OF((z_stream *strm,
+                            int  windowBits));
+/*
+     This is another version of inflateInit with more compression options. The
+   fields next_out, zalloc and zfree must be initialized before by the caller.
+
+     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 value 16 will be allowed soon). 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.
+
+     If next_out is not null, the library will use this buffer for the history
+   buffer; the buffer must either be large enough to hold the entire output
+   data, or have at least 1<<windowBits bytes.  If next_out is null, the
+   library will allocate its own buffer (and leave next_out null). next_in
+   need not be provided here but must be provided by the application for the
+   next call of inflate().
+
+     If the history buffer is provided by the application, next_out must
+   never be changed by the application since the decompressor maintains
+   history information inside this buffer from call to call; the application
+   can only reset next_out to the beginning of the history buffer when
+   avail_out is zero and all output has been consumed.
+
+      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
+   windowBits < 8). msg is set to null if there is no error message.
+   inflateInit2 does not perform any decompression: this will be done by
+   inflate().
+*/
+
+extern int inflateSync OF((z_stream *strm));
+/*
+    Skips invalid compressed data until the special marker (see deflate()
+  above) can be found, or until all available input is skipped. No output
+  is provided.
+
+    inflateSync returns Z_OK if the special marker has been found, Z_BUF_ERROR
+  if no more input was provided, Z_DATA_ERROR if no marker has been found,
+  or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+  case, the application may save the current current value of total_in which
+  indicates where valid compressed data was found. In the error case, the
+  application may repeatedly call inflateSync, providing more input each time,
+  until success or end of the input data.
+*/
+
+extern int inflateReset OF((z_stream *strm));
+/*
+     This function is equivalent to inflateEnd followed by inflateInit,
+   but does not free and reallocate all the internal decompression state.
+   The stream will keep attributes that may have been set by inflateInit2.
+
+      inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+extern int inflateIncomp OF((z_stream *strm));
+/*
+     This function adds the data at next_in (avail_in bytes) to the output
+   history without performing any output.  There must be no pending output,
+   and the decompressor must be expecting to see the start of a block.
+   Calling this function is equivalent to decompressing a stored block
+   containing the data at next_in (except that the data is not output).
+*/
+
+                        /* checksum functions */
+
+/*
+     This function is not related to compression but is exported
+   anyway because it might be useful in applications using the
+   compression library.
+*/
+
+extern uLong adler32 OF((uLong adler, Bytef *buf, uInt len));
+
+/*
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum. If buf is NULL, this function returns
+   the required initial value for the checksum.
+   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+   much faster. Usage example:
+
+     uLong adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+*/
+
+#ifndef _Z_UTIL_H
+    struct internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+#endif /* _ZLIB_H */
diff --git a/arch/xtensa/boot/lib/Makefile b/arch/xtensa/boot/lib/Makefile
new file mode 100644
index 0000000..c0a74dc
--- /dev/null
+++ b/arch/xtensa/boot/lib/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for some libs needed by zImage.
+#
+
+
+lib-y := zlib.o zmem.o
diff --git a/arch/xtensa/boot/lib/memcpy.S b/arch/xtensa/boot/lib/memcpy.S
new file mode 100644
index 0000000..a029f5d
--- /dev/null
+++ b/arch/xtensa/boot/lib/memcpy.S
@@ -0,0 +1,36 @@
+/*
+ *  arch/xtensa/lib/memcpy.S
+ *
+ *  ANSI C standard library function memcpy
+ *
+ *  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) 2002 Tensilica Inc.
+ */
+
+#define _ASMLANGUAGE
+#include <xtensa/config/core.h>
+
+.text
+.align	4
+.global	bcopy
+.type   bcopy,@function
+bcopy:
+        movi    a14, xthal_bcopy        // a14 safe to use regardless of whether caller
+                                        //   used call4 or call8 (can't have used call12)
+        jx      a14                     // let the Core HAL do the work
+
+.text
+.align	4
+.global	memcpy
+.type   memcpy,@function
+memcpy:
+.global	memmove
+.type   memmove,@function
+memmove:
+        movi    a14, xthal_memcpy      // a14 safe to use regardless of whether caller
+                                        //   used call4 or call8 (can't have used call12)
+        jx      a14                     // let the Core HAL do the work
+
diff --git a/arch/xtensa/boot/lib/zlib.c b/arch/xtensa/boot/lib/zlib.c
new file mode 100644
index 0000000..e3859f6
--- /dev/null
+++ b/arch/xtensa/boot/lib/zlib.c
@@ -0,0 +1,2150 @@
+/*
+ * BK Id: SCCS/s.zlib.c 1.8 05/18/01 15:17:24 cort
+ */
+/*
+ * This file is derived from various .h and .c files from the zlib-0.95
+ * distribution by Jean-loup Gailly and Mark Adler, with some additions
+ * by Paul Mackerras to aid in implementing Deflate compression and
+ * decompression for PPP packets.  See zlib.h for conditions of
+ * distribution and use.
+ *
+ * Changes that have been made include:
+ * - changed functions not used outside this file to "local"
+ * - added minCompression parameter to deflateInit2
+ * - added Z_PACKET_FLUSH (see zlib.h for details)
+ * - added inflateIncomp
+ *
+ */
+
+/*+++++*/
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995 Jean-loup Gailly.
+ * 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.
+ */
+
+/* From: zutil.h,v 1.9 1995/05/03 17:27:12 jloup Exp */
+
+#define _Z_UTIL_H
+
+#include "zlib.h"
+
+#ifndef local
+#  define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+#define FAR
+
+typedef unsigned char  uch;
+typedef uch FAR uchf;
+typedef unsigned short ush;
+typedef ush FAR ushf;
+typedef unsigned long  ulg;
+
+extern char *z_errmsg[]; /* indexed by 1-zlib_error */
+
+#define ERR_RETURN(strm,err) return (strm->msg=z_errmsg[1-err], err)
+/* To be used only when the state is known to be valid */
+
+#ifndef NULL
+#define NULL	((void *) 0)
+#endif
+
+        /* common constants */
+
+#define DEFLATED   8
+
+#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
+/* The three kinds of block type */
+
+#define MIN_MATCH  3
+#define MAX_MATCH  258
+/* The minimum and maximum match lengths */
+
+         /* functions */
+
+#include <linux/string.h>
+#define zmemcpy memcpy
+#define zmemzero(dest, len)	memset(dest, 0, len)
+
+/* Diagnostic functions */
+#ifdef DEBUG_ZLIB
+#  include <stdio.h>
+#  ifndef verbose
+#    define verbose 0
+#  endif
+#  define Assert(cond,msg) {if(!(cond)) z_error(msg);}
+#  define Trace(x) fprintf x
+#  define Tracev(x) {if (verbose) fprintf x ;}
+#  define Tracevv(x) {if (verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+
+typedef uLong (*check_func) OF((uLong check, Bytef *buf, uInt len));
+
+/* voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); */
+/* void   zcfree  OF((voidpf opaque, voidpf ptr)); */
+
+#define ZALLOC(strm, items, size) \
+           (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr, size)	\
+	   (*((strm)->zfree))((strm)->opaque, (voidpf)(addr), (size))
+#define TRY_FREE(s, p, n) {if (p) ZFREE(s, p, n);}
+
+/* deflate.h -- internal compression state
+ * Copyright (C) 1995 Jean-loup Gailly
+ * 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.
+ */
+
+/*+++++*/
+/* infblock.h -- header to use infblock.c
+ * Copyright (C) 1995 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.
+ */
+
+struct inflate_blocks_state;
+typedef struct inflate_blocks_state FAR inflate_blocks_statef;
+
+local inflate_blocks_statef * inflate_blocks_new OF((
+    z_stream *z,
+    check_func c,               /* check function */
+    uInt w));                   /* window size */
+
+local int inflate_blocks OF((
+    inflate_blocks_statef *,
+    z_stream *,
+    int));                      /* initial return code */
+
+local void inflate_blocks_reset OF((
+    inflate_blocks_statef *,
+    z_stream *,
+    uLongf *));                  /* check value on output */
+
+local int inflate_blocks_free OF((
+    inflate_blocks_statef *,
+    z_stream *,
+    uLongf *));                  /* check value on output */
+
+local int inflate_addhistory OF((
+    inflate_blocks_statef *,
+    z_stream *));
+
+local int inflate_packet_flush OF((
+    inflate_blocks_statef *));
+
+/*+++++*/
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995 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.
+ */
+
+/* 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). */
+
+typedef struct inflate_huft_s FAR 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 Nalloc;	/* number of these allocated here */
+    Bytef *pad;         /* pad structure to a power of 2 (4 bytes for */
+  } word;               /*  16-bit, 8 bytes for 32-bit machines) */
+  union {
+    uInt Base;          /* literal, length base, or distance base */
+    inflate_huft *Next; /* pointer to next level of table */
+  } more;
+};
+
+#ifdef DEBUG_ZLIB
+  local uInt inflate_hufts;
+#endif
+
+local int inflate_trees_bits OF((
+    uIntf *,                    /* 19 code lengths */
+    uIntf *,                    /* bits tree desired/actual depth */
+    inflate_huft * FAR *,       /* bits tree result */
+    z_stream *));               /* for zalloc, zfree functions */
+
+local int inflate_trees_dynamic OF((
+    uInt,                       /* number of literal/length codes */
+    uInt,                       /* number of distance codes */
+    uIntf *,                    /* that many (total) code lengths */
+    uIntf *,                    /* literal desired/actual bit depth */
+    uIntf *,                    /* distance desired/actual bit depth */
+    inflate_huft * FAR *,       /* literal/length tree result */
+    inflate_huft * FAR *,       /* distance tree result */
+    z_stream *));               /* for zalloc, zfree functions */
+
+local int inflate_trees_fixed OF((
+    uIntf *,                    /* literal desired/actual bit depth */
+    uIntf *,                    /* distance desired/actual bit depth */
+    inflate_huft * FAR *,       /* literal/length tree result */
+    inflate_huft * FAR *));     /* distance tree result */
+
+local int inflate_trees_free OF((
+    inflate_huft *,             /* tables to free */
+    z_stream *));               /* for zfree function */
+
+
+/*+++++*/
+/* infcodes.h -- header to use infcodes.c
+ * Copyright (C) 1995 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.
+ */
+
+struct inflate_codes_state;
+typedef struct inflate_codes_state FAR inflate_codes_statef;
+
+local inflate_codes_statef *inflate_codes_new OF((
+    uInt, uInt,
+    inflate_huft *, inflate_huft *,
+    z_stream *));
+
+local int inflate_codes OF((
+    inflate_blocks_statef *,
+    z_stream *,
+    int));
+
+local void inflate_codes_free OF((
+    inflate_codes_statef *,
+    z_stream *));
+
+
+/*+++++*/
+/* inflate.c -- zlib interface to inflate modules
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* inflate private state */
+struct internal_state {
+
+  /* mode */
+  enum {
+      METHOD,   /* waiting for method byte */
+      FLAG,     /* waiting for flag byte */
+      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 */
+      DONE,     /* finished check, done */
+      BAD}      /* got an error--stay here */
+    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 */
+
+};
+
+
+int inflateReset(z)
+z_stream *z;
+{
+  uLong c;
+
+  if (z == Z_NULL || z->state == Z_NULL)
+    return Z_STREAM_ERROR;
+  z->total_in = z->total_out = 0;
+  z->msg = Z_NULL;
+  z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
+  inflate_blocks_reset(z->state->blocks, z, &c);
+  Trace((stderr, "inflate: reset\n"));
+  return Z_OK;
+}
+
+
+int inflateEnd(z)
+z_stream *z;
+{
+  uLong c;
+
+  if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
+    return Z_STREAM_ERROR;
+  if (z->state->blocks != Z_NULL)
+    inflate_blocks_free(z->state->blocks, z, &c);
+  ZFREE(z, z->state, sizeof(struct internal_state));
+  z->state = Z_NULL;
+  Trace((stderr, "inflate: end\n"));
+  return Z_OK;
+}
+
+
+int inflateInit2(z, w)
+z_stream *z;
+int w;
+{
+  /* initialize state */
+  if (z == Z_NULL)
+    return Z_STREAM_ERROR;
+/*  if (z->zalloc == Z_NULL) z->zalloc = zcalloc; */
+/*  if (z->zfree == Z_NULL) z->zfree = zcfree; */
+  if ((z->state = (struct internal_state FAR *)
+       ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
+    return Z_MEM_ERROR;
+  z->state->blocks = Z_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)
+  {
+    inflateEnd(z);
+    return Z_STREAM_ERROR;
+  }
+  z->state->wbits = (uInt)w;
+
+  /* create inflate_blocks state */
+  if ((z->state->blocks =
+       inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, 1 << w))
+      == Z_NULL)
+  {
+    inflateEnd(z);
+    return Z_MEM_ERROR;
+  }
+  Trace((stderr, "inflate: allocated\n"));
+
+  /* reset state */
+  inflateReset(z);
+  return Z_OK;
+}
+
+
+int inflateInit(z)
+z_stream *z;
+{
+  return inflateInit2(z, DEF_WBITS);
+}
+
+
+#define NEEDBYTE {if(z->avail_in==0)goto empty;r=Z_OK;}
+#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
+
+int inflate(z, f)
+z_stream *z;
+int f;
+{
+  int r;
+  uInt b;
+
+  if (z == Z_NULL || z->next_in == Z_NULL)
+    return Z_STREAM_ERROR;
+  r = Z_BUF_ERROR;
+  while (1) switch (z->state->mode)
+  {
+    case METHOD:
+      NEEDBYTE
+      if (((z->state->sub.method = NEXTBYTE) & 0xf) != DEFLATED)
+      {
+        z->state->mode = BAD;
+        z->msg = "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 = BAD;
+        z->msg = "invalid window size";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      z->state->mode = FLAG;
+    case FLAG:
+      NEEDBYTE
+      if ((b = NEXTBYTE) & 0x20)
+      {
+        z->state->mode = BAD;
+        z->msg = "invalid reserved bit";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      if (((z->state->sub.method << 8) + b) % 31)
+      {
+        z->state->mode = BAD;
+        z->msg = "incorrect header check";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      Trace((stderr, "inflate: zlib header ok\n"));
+      z->state->mode = BLOCKS;
+    case BLOCKS:
+      r = inflate_blocks(z->state->blocks, z, r);
+      if (f == Z_PACKET_FLUSH && z->avail_in == 0 && z->avail_out != 0)
+	  r = inflate_packet_flush(z->state->blocks);
+      if (r == Z_DATA_ERROR)
+      {
+        z->state->mode = BAD;
+        z->state->sub.marker = 0;       /* can try inflateSync */
+        break;
+      }
+      if (r != Z_STREAM_END)
+        return r;
+      r = Z_OK;
+      inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
+      if (z->state->nowrap)
+      {
+        z->state->mode = 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;
+
+      if (z->state->sub.check.was != z->state->sub.check.need)
+      {
+        z->state->mode = BAD;
+        z->msg = "incorrect data check";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      Trace((stderr, "inflate: zlib check ok\n"));
+      z->state->mode = DONE;
+    case DONE:
+      return Z_STREAM_END;
+    case BAD:
+      return Z_DATA_ERROR;
+    default:
+      return Z_STREAM_ERROR;
+  }
+
+ empty:
+  if (f != Z_PACKET_FLUSH)
+    return r;
+  z->state->mode = BAD;
+  z->state->sub.marker = 0;       /* can try inflateSync */
+  return Z_DATA_ERROR;
+}
+
+/*
+ * 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 inflateIncomp(z)
+z_stream *z;
+{
+    if (z->state->mode != BLOCKS)
+	return Z_DATA_ERROR;
+    return inflate_addhistory(z->state->blocks, z);
+}
+
+
+int inflateSync(z)
+z_stream *z;
+{
+  uInt n;       /* number of bytes to look at */
+  Bytef *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 == Z_NULL || z->state == Z_NULL)
+    return Z_STREAM_ERROR;
+  if (z->state->mode != BAD)
+  {
+    z->state->mode = 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)
+  {
+    if (*p == (Byte)(m < 2 ? 0 : 0xff))
+      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;
+  inflateReset(z);
+  z->total_in = r;  z->total_out = w;
+  z->state->mode = BLOCKS;
+  return Z_OK;
+}
+
+#undef NEEDBYTE
+#undef NEXTBYTE
+
+/*+++++*/
+/* infutil.h -- types and macros common to blocks and codes
+ * Copyright (C) 1995 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.
+ */
+
+/* inflate blocks semi-private state */
+struct inflate_blocks_state {
+
+  /* mode */
+  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 */
+      DONEB,     /* finished last block, done */
+      BADB}      /* got a data error--stuck here */
+    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) */
+      uIntf *blens;             /* bit lengths of codes */
+      uInt bb;                  /* bit length tree depth */
+      inflate_huft *tb;         /* bit length decoding tree */
+      int nblens;		/* # elements allocated at blens */
+    } trees;            /* if DTREE, decoding info for trees */
+    struct {
+      inflate_huft *tl, *td;    /* trees to free */
+      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 */
+  Bytef *window;        /* sliding window */
+  Bytef *end;           /* one byte after sliding window */
+  Bytef *read;          /* window read pointer */
+  Bytef *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 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 (q<s->read?s->read-q-1:s->end-q)
+#define LOADOUT {q=s->write;m=WAVAIL;}
+#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=WAVAIL;}}
+#define FLUSH {UPDOUT r=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}
+
+/*
+ * The IBM 150 firmware munges the data right after _etext[].  This
+ * protects it. -- Cort
+ */
+local uInt protect_mask[] = {0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0};
+/* And'ing with mask[n] masks the lower n bits */
+local uInt inflate_mask[] = {
+    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 */
+local int inflate_flush OF((
+    inflate_blocks_statef *,
+    z_stream *,
+    int));
+
+/*+++++*/
+/* inffast.h -- header to use inffast.c
+ * Copyright (C) 1995 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.
+ */
+
+local int inflate_fast OF((
+    uInt,
+    uInt,
+    inflate_huft *,
+    inflate_huft *,
+    inflate_blocks_statef *,
+    z_stream *));
+
+
+/*+++++*/
+/* infblock.c -- interpret and process block types to last block
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* Table for deflate from PKZIP's appnote.txt. */
+local 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.
+ */
+
+
+local void inflate_blocks_reset(s, z, c)
+inflate_blocks_statef *s;
+z_stream *z;
+uLongf *c;
+{
+  if (s->checkfn != Z_NULL)
+    *c = s->check;
+  if (s->mode == BTREE || s->mode == DTREE)
+    ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
+  if (s->mode == CODES)
+  {
+    inflate_codes_free(s->sub.decode.codes, z);
+    inflate_trees_free(s->sub.decode.td, z);
+    inflate_trees_free(s->sub.decode.tl, z);
+  }
+  s->mode = TYPE;
+  s->bitk = 0;
+  s->bitb = 0;
+  s->read = s->write = s->window;
+  if (s->checkfn != Z_NULL)
+    s->check = (*s->checkfn)(0L, Z_NULL, 0);
+  Trace((stderr, "inflate:   blocks reset\n"));
+}
+
+
+local inflate_blocks_statef *inflate_blocks_new(z, c, w)
+z_stream *z;
+check_func c;
+uInt w;
+{
+  inflate_blocks_statef *s;
+
+  if ((s = (inflate_blocks_statef *)ZALLOC
+       (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
+    return s;
+  if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL)
+  {
+    ZFREE(z, s, sizeof(struct inflate_blocks_state));
+    return Z_NULL;
+  }
+  s->end = s->window + w;
+  s->checkfn = c;
+  s->mode = TYPE;
+  Trace((stderr, "inflate:   blocks allocated\n"));
+  inflate_blocks_reset(s, z, &s->check);
+  return s;
+}
+
+
+local int inflate_blocks(s, z, r)
+inflate_blocks_statef *s;
+z_stream *z;
+int r;
+{
+  uInt t;               /* temporary storage */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Bytef *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Bytef *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 */
+          Trace((stderr, "inflate:     stored block%s\n",
+                 s->last ? " (last)" : ""));
+          DUMPBITS(3)
+          t = k & 7;                    /* go to byte boundary */
+          DUMPBITS(t)
+          s->mode = LENS;               /* get length of stored block */
+          break;
+        case 1:                         /* fixed */
+          Trace((stderr, "inflate:     fixed codes block%s\n",
+                 s->last ? " (last)" : ""));
+          {
+            uInt bl, bd;
+            inflate_huft *tl, *td;
+
+            inflate_trees_fixed(&bl, &bd, &tl, &td);
+            s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
+            if (s->sub.decode.codes == Z_NULL)
+            {
+              r = Z_MEM_ERROR;
+              LEAVE
+            }
+            s->sub.decode.tl = Z_NULL;  /* don't try to free these */
+            s->sub.decode.td = Z_NULL;
+          }
+          DUMPBITS(3)
+          s->mode = CODES;
+          break;
+        case 2:                         /* dynamic */
+          Trace((stderr, "inflate:     dynamic codes block%s\n",
+                 s->last ? " (last)" : ""));
+          DUMPBITS(3)
+          s->mode = TABLE;
+          break;
+        case 3:                         /* illegal */
+          DUMPBITS(3)
+          s->mode = BADB;
+          z->msg = "invalid block type";
+          r = Z_DATA_ERROR;
+          LEAVE
+      }
+      break;
+    case LENS:
+      NEEDBITS(32)
+      if (((~b) >> 16) != (b & 0xffff))
+      {
+        s->mode = BADB;
+        z->msg = "invalid stored block lengths";
+        r = Z_DATA_ERROR;
+        LEAVE
+      }
+      s->sub.left = (uInt)b & 0xffff;
+      b = k = 0;                      /* dump bits */
+      Tracev((stderr, "inflate:       stored length %u\n", s->sub.left));
+      s->mode = s->sub.left ? STORED : TYPE;
+      break;
+    case STORED:
+      if (n == 0)
+        LEAVE
+      NEEDOUT
+      t = s->sub.left;
+      if (t > n) t = n;
+      if (t > m) t = m;
+      zmemcpy(q, p, t);
+      p += t;  n -= t;
+      q += t;  m -= t;
+      if ((s->sub.left -= t) != 0)
+        break;
+      Tracev((stderr, "inflate:       stored end, %lu total out\n",
+              z->total_out + (q >= s->read ? q - s->read :
+              (s->end - s->read) + (q - s->window))));
+      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 = BADB;
+        z->msg = "too many length or distance symbols";
+        r = Z_DATA_ERROR;
+        LEAVE
+      }
+#endif
+      t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+      if (t < 19)
+        t = 19;
+      if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
+      {
+        r = Z_MEM_ERROR;
+        LEAVE
+      }
+      s->sub.trees.nblens = t;
+      DUMPBITS(14)
+      s->sub.trees.index = 0;
+      Tracev((stderr, "inflate:       table sizes ok\n"));
+      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 = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
+                             &s->sub.trees.tb, z);
+      if (t != Z_OK)
+      {
+        r = t;
+        if (r == Z_DATA_ERROR)
+          s->mode = BADB;
+        LEAVE
+      }
+      s->sub.trees.index = 0;
+      Tracev((stderr, "inflate:       bits tree ok\n"));
+      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 & inflate_mask[t]);
+        t = h->word.what.Bits;
+        c = h->more.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 & 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 = BADB;
+            z->msg = "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;
+        }
+      }
+      inflate_trees_free(s->sub.trees.tb, z);
+      s->sub.trees.tb = Z_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 = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
+                                  s->sub.trees.blens, &bl, &bd, &tl, &td, z);
+        if (t != Z_OK)
+        {
+          if (t == (uInt)Z_DATA_ERROR)
+            s->mode = BADB;
+          r = t;
+          LEAVE
+        }
+        Tracev((stderr, "inflate:       trees ok\n"));
+        if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
+        {
+          inflate_trees_free(td, z);
+          inflate_trees_free(tl, z);
+          r = Z_MEM_ERROR;
+          LEAVE
+        }
+        ZFREE(z, s->sub.trees.blens, s->sub.trees.nblens * sizeof(uInt));
+        s->sub.decode.codes = c;
+        s->sub.decode.tl = tl;
+        s->sub.decode.td = td;
+      }
+      s->mode = CODES;
+    case CODES:
+      UPDATE
+      if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
+        return inflate_flush(s, z, r);
+      r = Z_OK;
+      inflate_codes_free(s->sub.decode.codes, z);
+      inflate_trees_free(s->sub.decode.td, z);
+      inflate_trees_free(s->sub.decode.tl, z);
+      LOAD
+      Tracev((stderr, "inflate:       codes end, %lu total out\n",
+              z->total_out + (q >= s->read ? q - s->read :
+              (s->end - s->read) + (q - s->window))));
+      if (!s->last)
+      {
+        s->mode = TYPE;
+        break;
+      }
+      if (k > 7)              /* return unused byte, if any */
+      {
+        Assert(k < 16, "inflate_codes grabbed too many bytes")
+        k -= 8;
+        n++;
+        p--;                    /* can always return one */
+      }
+      s->mode = DRY;
+    case DRY:
+      FLUSH
+      if (s->read != s->write)
+        LEAVE
+      s->mode = DONEB;
+    case DONEB:
+      r = Z_STREAM_END;
+      LEAVE
+    case BADB:
+      r = Z_DATA_ERROR;
+      LEAVE
+    default:
+      r = Z_STREAM_ERROR;
+      LEAVE
+  }
+}
+
+
+local int inflate_blocks_free(s, z, c)
+inflate_blocks_statef *s;
+z_stream *z;
+uLongf *c;
+{
+  inflate_blocks_reset(s, z, c);
+  ZFREE(z, s->window, s->end - s->window);
+  ZFREE(z, s, sizeof(struct inflate_blocks_state));
+  Trace((stderr, "inflate:   blocks freed\n"));
+  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.
+ */
+local int inflate_addhistory(s, z)
+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 */
+    Bytef *p;             /* input data pointer */
+    uInt n;               /* bytes available there */
+    Bytef *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 != Z_NULL)
+	    s->check = (*s->checkfn)(s->check, q, t);
+	zmemcpy(q, p, t);
+	q += t;
+	p += t;
+	n -= t;
+	z->total_out += t;
+	s->read = q;    /* drag read pointer forward */
+/*      WRAP  */ 	/* expand WRAP macro by hand to handle s->read */
+	if (q == s->end) {
+	    s->read = q = s->window;
+	    m = WAVAIL;
+	}
+    }
+    UPDATE
+    return Z_OK;
+}
+
+
+/*
+ * 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.
+ */
+local int inflate_packet_flush(s)
+    inflate_blocks_statef *s;
+{
+    if (s->mode != LENS)
+	return Z_DATA_ERROR;
+    s->mode = TYPE;
+    return Z_OK;
+}
+
+
+/*+++++*/
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+
+local int huft_build OF((
+    uIntf *,            /* code lengths in bits */
+    uInt,               /* number of codes */
+    uInt,               /* number of "simple" codes */
+    uIntf *,            /* list of base values for non-simple codes */
+    uIntf *,            /* list of extra bits for non-simple codes */
+    inflate_huft * FAR*,/* result: starting table */
+    uIntf *,            /* maximum lookup bits (returns actual) */
+    z_stream *));       /* for zalloc function */
+
+local voidpf falloc OF((
+    voidpf,             /* opaque pointer (not used) */
+    uInt,               /* number of items */
+    uInt));             /* size of item */
+
+local void ffree OF((
+    voidpf q,           /* opaque pointer (not used) */
+    voidpf p,           /* what to free (not used) */
+    uInt n));		/* number of bytes (not used) */
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+local uInt cplens[] = { /* Copy lengths for literal codes 257..285 */
+        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};
+        /* actually lengths - 2; also see note #13 above about 258 */
+local uInt cplext[] = { /* 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, 192, 192}; /* 192==invalid */
+local uInt cpdist[] = { /* Copy offsets for distance codes 0..29 */
+        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};
+local uInt cpdext[] = { /* 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};
+
+/*
+   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.
+
+   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.
+
+   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.
+ */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
+#define BMAX 15         /* maximum bit length of any code */
+#define N_MAX 288       /* maximum number of codes in any set */
+
+#ifdef DEBUG_ZLIB
+  uInt inflate_hufts;
+#endif
+
+local int huft_build(b, n, s, d, e, t, m, zs)
+uIntf *b;               /* code lengths in bits (all assumed <= BMAX) */
+uInt n;                 /* number of codes (assumed <= N_MAX) */
+uInt s;                 /* number of simple-valued codes (0..s-1) */
+uIntf *d;               /* list of base values for non-simple codes */
+uIntf *e;               /* list of extra bits for non-simple codes */
+inflate_huft * FAR *t;  /* result: starting table */
+uIntf *m;               /* maximum lookup bits, returns actual */
+z_stream *zs;           /* for zalloc function */
+/* 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 (all zero length codes or an
+   over-subscribed set of lengths), or Z_MEM_ERROR if not enough memory. */
+{
+
+  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) */
+  register uIntf *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 */
+  uInt v[N_MAX];                /* values in order of bit length */
+  register int w;               /* bits before this table == (l * h) */
+  uInt x[BMAX+1];               /* bit offsets, then code stack */
+  uIntf *xp;                    /* pointer into x */
+  int y;                        /* number of dummy codes added */
+  uInt z;                       /* number of entries in current table */
+
+
+  /* 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 = (inflate_huft *)Z_NULL;
+    *m = 0;
+    return Z_OK;
+  }
+
+
+  /* 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;
+
+
+  /* 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;
+
+
+  /* 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++);
+  }
+
+
+  /* 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);
+
+
+  /* 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] = (inflate_huft *)Z_NULL;        /* just to keep compilers happy */
+  q = (inflate_huft *)Z_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 = (z = g - w) > (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 */
+            }
+        }
+        z = 1 << j;             /* table entries for j-bit table */
+
+        /* allocate and link in new table */
+        if ((q = (inflate_huft *)ZALLOC
+             (zs,z + 1,sizeof(inflate_huft))) == Z_NULL)
+        {
+          if (h)
+            inflate_trees_free(u[0], zs);
+          return Z_MEM_ERROR;   /* not enough memory */
+        }
+	q->word.Nalloc = z + 1;
+#ifdef DEBUG_ZLIB
+        inflate_hufts += z + 1;
+#endif
+        *t = q + 1;             /* link to list for huft_free() */
+        *(t = &(q->next)) = Z_NULL;
+        u[h] = ++q;             /* table starts after link */
+
+        /* 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 */
+          r.next = q;           /* pointer to this table */
+          j = i >> (w - l);     /* (get around Turbo C bug) */
+          u[h-1][j] = r;        /* connect to last table */
+        }
+      }
+
+      /* 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];
+      }
+
+      /* fill code-like entries with r */
+      f = 1 << (k - w);
+      for (j = i >> w; j < z; j += f)
+        q[j] = r;
+
+      /* backwards increment the k-bit code i */
+      for (j = 1 << (k - 1); i & j; j >>= 1)
+        i ^= j;
+      i ^= j;
+
+      /* backup over finished tables */
+      while ((i & ((1 << w) - 1)) != x[h])
+      {
+        h--;                    /* don't need to update q */
+        w -= l;
+      }
+    }
+  }
+
+
+  /* Return Z_BUF_ERROR if we were given an incomplete table */
+  return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
+}
+
+
+local int inflate_trees_bits(c, bb, tb, z)
+uIntf *c;               /* 19 code lengths */
+uIntf *bb;              /* bits tree desired/actual depth */
+inflate_huft * FAR *tb; /* bits tree result */
+z_stream *z;            /* for zfree function */
+{
+  int r;
+
+  r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, tb, bb, z);
+  if (r == Z_DATA_ERROR)
+    z->msg = "oversubscribed dynamic bit lengths tree";
+  else if (r == Z_BUF_ERROR)
+  {
+    inflate_trees_free(*tb, z);
+    z->msg = "incomplete dynamic bit lengths tree";
+    r = Z_DATA_ERROR;
+  }
+  return r;
+}
+
+
+local int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, z)
+uInt nl;                /* number of literal/length codes */
+uInt nd;                /* number of distance codes */
+uIntf *c;               /* that many (total) code lengths */
+uIntf *bl;              /* literal desired/actual bit depth */
+uIntf *bd;              /* distance desired/actual bit depth */
+inflate_huft * FAR *tl; /* literal/length tree result */
+inflate_huft * FAR *td; /* distance tree result */
+z_stream *z;            /* for zfree function */
+{
+  int r;
+
+  /* build literal/length tree */
+  if ((r = huft_build(c, nl, 257, cplens, cplext, tl, bl, z)) != Z_OK)
+  {
+    if (r == Z_DATA_ERROR)
+      z->msg = "oversubscribed literal/length tree";
+    else if (r == Z_BUF_ERROR)
+    {
+      inflate_trees_free(*tl, z);
+      z->msg = "incomplete literal/length tree";
+      r = Z_DATA_ERROR;
+    }
+    return r;
+  }
+
+  /* build distance tree */
+  if ((r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, z)) != Z_OK)
+  {
+    if (r == Z_DATA_ERROR)
+      z->msg = "oversubscribed literal/length tree";
+    else if (r == Z_BUF_ERROR) {
+#ifdef PKZIP_BUG_WORKAROUND
+      r = Z_OK;
+    }
+#else
+      inflate_trees_free(*td, z);
+      z->msg = "incomplete literal/length tree";
+      r = Z_DATA_ERROR;
+    }
+    inflate_trees_free(*tl, z);
+    return r;
+#endif
+  }
+
+  /* done */
+  return Z_OK;
+}
+
+
+/* build fixed tables only once--keep them here */
+local int fixed_lock = 0;
+local int fixed_built = 0;
+#define FIXEDH 530      /* number of hufts used by fixed tables */
+local uInt fixed_left = FIXEDH;
+local inflate_huft fixed_mem[FIXEDH];
+local uInt fixed_bl;
+local uInt fixed_bd;
+local inflate_huft *fixed_tl;
+local inflate_huft *fixed_td;
+
+
+local voidpf falloc(q, n, s)
+voidpf q;        /* opaque pointer (not used) */
+uInt n;         /* number of items */
+uInt s;         /* size of item */
+{
+  Assert(s == sizeof(inflate_huft) && n <= fixed_left,
+         "inflate_trees falloc overflow");
+  if (q) s++; /* to make some compilers happy */
+  fixed_left -= n;
+  return (voidpf)(fixed_mem + fixed_left);
+}
+
+
+local void ffree(q, p, n)
+voidpf q;
+voidpf p;
+uInt n;
+{
+  Assert(0, "inflate_trees ffree called!");
+  if (q) q = p; /* to make some compilers happy */
+}
+
+
+local int inflate_trees_fixed(bl, bd, tl, td)
+uIntf *bl;               /* literal desired/actual bit depth */
+uIntf *bd;               /* distance desired/actual bit depth */
+inflate_huft * FAR *tl;  /* literal/length tree result */
+inflate_huft * FAR *td;  /* distance tree result */
+{
+  /* build fixed tables if not built already--lock out other instances */
+  while (++fixed_lock > 1)
+    fixed_lock--;
+  if (!fixed_built)
+  {
+    int k;              /* temporary variable */
+    unsigned c[288];    /* length list for huft_build */
+    z_stream z;         /* for falloc function */
+
+    /* set up fake z_stream for memory routines */
+    z.zalloc = falloc;
+    z.zfree = ffree;
+    z.opaque = Z_NULL;
+
+    /* literal table */
+    for (k = 0; k < 144; k++)
+      c[k] = 8;
+    for (; k < 256; k++)
+      c[k] = 9;
+    for (; k < 280; k++)
+      c[k] = 7;
+    for (; k < 288; k++)
+      c[k] = 8;
+    fixed_bl = 7;
+    huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, &z);
+
+    /* distance table */
+    for (k = 0; k < 30; k++)
+      c[k] = 5;
+    fixed_bd = 5;
+    huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, &z);
+
+    /* done */
+    fixed_built = 1;
+  }
+  fixed_lock--;
+  *bl = fixed_bl;
+  *bd = fixed_bd;
+  *tl = fixed_tl;
+  *td = fixed_td;
+  return Z_OK;
+}
+
+
+local int inflate_trees_free(t, z)
+inflate_huft *t;        /* table to free */
+z_stream *z;            /* for zfree function */
+/* Free the malloc'ed tables built by huft_build(), which makes a linked
+   list of the tables it made, with the links in a dummy first entry of
+   each table. */
+{
+  register inflate_huft *p, *q;
+
+  /* Go through linked list, freeing from the malloced (t[-1]) address. */
+  p = t;
+  while (p != Z_NULL)
+  {
+    q = (--p)->next;
+    ZFREE(z, p, p->word.Nalloc * sizeof(inflate_huft));
+    p = q;
+  }
+  return Z_OK;
+}
+
+/*+++++*/
+/* infcodes.c -- process literals and length/distance pairs
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* inflate codes private state */
+struct inflate_codes_state {
+
+  /* mode */
+  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 */
+    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 */
+
+};
+
+
+local inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
+uInt bl, bd;
+inflate_huft *tl, *td;
+z_stream *z;
+{
+  inflate_codes_statef *c;
+
+  if ((c = (inflate_codes_statef *)
+       ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
+  {
+    c->mode = START;
+    c->lbits = (Byte)bl;
+    c->dbits = (Byte)bd;
+    c->ltree = tl;
+    c->dtree = td;
+    Tracev((stderr, "inflate:       codes new\n"));
+  }
+  return c;
+}
+
+
+local int inflate_codes(s, z, r)
+inflate_blocks_statef *s;
+z_stream *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 */
+  Bytef *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Bytef *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+  Bytef *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 = 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 & inflate_mask[j]);
+      DUMPBITS(t->bits)
+      e = (uInt)(t->exop);
+      if (e == 0)               /* literal */
+      {
+        c->sub.lit = t->base;
+        Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                 "inflate:         literal '%c'\n" :
+                 "inflate:         literal 0x%02x\n", 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->next;
+        break;
+      }
+      if (e & 32)               /* end of block */
+      {
+        Tracevv((stderr, "inflate:         end of block\n"));
+        c->mode = WASH;
+        break;
+      }
+      c->mode = BADCODE;        /* invalid code */
+      z->msg = "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 & inflate_mask[j];
+      DUMPBITS(j)
+      c->sub.code.need = c->dbits;
+      c->sub.code.tree = c->dtree;
+      Tracevv((stderr, "inflate:         length %u\n", c->len));
+      c->mode = DIST;
+    case DIST:          /* i: get distance next */
+      j = c->sub.code.need;
+      NEEDBITS(j)
+      t = c->sub.code.tree + ((uInt)b & 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->next;
+        break;
+      }
+      c->mode = BADCODE;        /* invalid code */
+      z->msg = "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 & inflate_mask[j];
+      DUMPBITS(j)
+      Tracevv((stderr, "inflate:         distance %u\n", c->sub.copy.dist));
+      c->mode = COPY;
+    case COPY:          /* o: copying bytes in window, waiting for space */
+#ifndef __TURBOC__ /* Turbo C bug for following expression */
+      f = (uInt)(q - s->window) < c->sub.copy.dist ?
+          s->end - (c->sub.copy.dist - (q - s->window)) :
+          q - c->sub.copy.dist;
+#else
+      f = q - c->sub.copy.dist;
+      if ((uInt)(q - s->window) < c->sub.copy.dist)
+        f = s->end - (c->sub.copy.dist - (q - s->window));
+#endif
+      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 */
+      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
+  }
+}
+
+
+local void inflate_codes_free(c, z)
+inflate_codes_statef *c;
+z_stream *z;
+{
+  ZFREE(z, c, sizeof(struct inflate_codes_state));
+  Tracev((stderr, "inflate:       codes free\n"));
+}
+
+/*+++++*/
+/* inflate_util.c -- data and routines common to blocks and codes
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* copy as much as possible from the sliding window to the output area */
+local int inflate_flush(s, z, r)
+inflate_blocks_statef *s;
+z_stream *z;
+int r;
+{
+  uInt n;
+  Bytef *p, *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 != Z_NULL)
+    s->check = (*s->checkfn)(s->check, q, n);
+
+  /* copy as far as end of window */
+  zmemcpy(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 != Z_NULL)
+      s->check = (*s->checkfn)(s->check, q, n);
+
+    /* copy */
+    zmemcpy(p, q, n);
+    p += n;
+    q += n;
+  }
+
+  /* update pointers */
+  z->next_out = p;
+  s->read = q;
+
+  /* done */
+  return r;
+}
+
+
+/*+++++*/
+/* inffast.c -- process literals and length/distance pairs fast
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define base more.Base
+#define next more.Next
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* 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 {n+=(c=k>>3);p-=c;k&=7;}
+
+/* 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. */
+
+local int inflate_fast(bl, bd, tl, td, s, z)
+uInt bl, bd;
+inflate_huft *tl, *td;
+inflate_blocks_statef *s;
+z_stream *z;
+{
+  inflate_huft *t;      /* temporary pointer */
+  uInt e;               /* extra bits or operation */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Bytef *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Bytef *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 */
+  Bytef *r;             /* copy source pointer */
+
+  /* load input, output, bit values */
+  LOAD
+
+  /* initialize masks */
+  ml = inflate_mask[bl];
+  md = 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)
+      Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                "inflate:         * literal '%c'\n" :
+                "inflate:         * literal 0x%02x\n", t->base));
+      *q++ = (Byte)t->base;
+      m--;
+      continue;
+    }
+    do {
+      DUMPBITS(t->bits)
+      if (e & 16)
+      {
+        /* get extra bits for length */
+        e &= 15;
+        c = t->base + ((uInt)b & inflate_mask[e]);
+        DUMPBITS(e)
+        Tracevv((stderr, "inflate:         * length %u\n", c));
+
+        /* 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 & inflate_mask[e]);
+            DUMPBITS(e)
+            Tracevv((stderr, "inflate:         * distance %u\n", d));
+
+            /* do the copy */
+            m -= c;
+            if ((uInt)(q - s->window) >= d)     /* offset before dest */
+            {                                   /*  just copy */
+              r = q - d;
+              *q++ = *r++;  c--;        /* minimum count is three, */
+              *q++ = *r++;  c--;        /*  so unroll loop a little */
+            }
+            else                        /* else offset after destination */
+            {
+              e = d - (q - s->window);  /* bytes from offset to end */
+              r = s->end - e;           /* pointer to offset */
+              if (c > e)                /* if source crosses, */
+              {
+                c -= e;                 /* copy to end of window */
+                do {
+                  *q++ = *r++;
+                } while (--e);
+                r = s->window;          /* copy rest from start of window */
+              }
+            }
+            do {                        /* copy all or what's left */
+              *q++ = *r++;
+            } while (--c);
+            break;
+          }
+          else if ((e & 64) == 0)
+            e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop;
+          else
+          {
+            z->msg = "invalid distance code";
+            UNGRAB
+            UPDATE
+            return Z_DATA_ERROR;
+          }
+        } while (1);
+        break;
+      }
+      if ((e & 64) == 0)
+      {
+        if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0)
+        {
+          DUMPBITS(t->bits)
+          Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                    "inflate:         * literal '%c'\n" :
+                    "inflate:         * literal 0x%02x\n", t->base));
+          *q++ = (Byte)t->base;
+          m--;
+          break;
+        }
+      }
+      else if (e & 32)
+      {
+        Tracevv((stderr, "inflate:         * end of block\n"));
+        UNGRAB
+        UPDATE
+        return Z_STREAM_END;
+      }
+      else
+      {
+        z->msg = "invalid literal/length code";
+        UNGRAB
+        UPDATE
+        return Z_DATA_ERROR;
+      }
+    } while (1);
+  } while (m >= 258 && n >= 10);
+
+  /* not enough input or output--restore pointers and return */
+  UNGRAB
+  UPDATE
+  return Z_OK;
+}
+
+
+/*+++++*/
+/* zutil.c -- target dependent utility functions for the compression library
+ * Copyright (C) 1995 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* From: zutil.c,v 1.8 1995/05/03 17:27:12 jloup Exp */
+
+char *zlib_version = ZLIB_VERSION;
+
+char *z_errmsg[] = {
+"stream end",          /* Z_STREAM_END    1 */
+"",                    /* Z_OK            0 */
+"file error",          /* Z_ERRNO        (-1) */
+"stream error",        /* Z_STREAM_ERROR (-2) */
+"data error",          /* Z_DATA_ERROR   (-3) */
+"insufficient memory", /* Z_MEM_ERROR    (-4) */
+"buffer error",        /* Z_BUF_ERROR    (-5) */
+""};
+
+
+/*+++++*/
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* From: adler32.c,v 1.6 1995/05/03 17:27:08 jloup Exp */
+
+#define BASE 65521L /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf)  {s1 += *buf++; s2 += s1;}
+#define DO2(buf)  DO1(buf); DO1(buf);
+#define DO4(buf)  DO2(buf); DO2(buf);
+#define DO8(buf)  DO4(buf); DO4(buf);
+#define DO16(buf) DO8(buf); DO8(buf);
+
+/* ========================================================================= */
+uLong adler32(adler, buf, len)
+    uLong adler;
+    Bytef *buf;
+    uInt len;
+{
+    unsigned long s1 = adler & 0xffff;
+    unsigned long s2 = (adler >> 16) & 0xffff;
+    int k;
+
+    if (buf == Z_NULL) return 1L;
+
+    while (len > 0) {
+        k = len < NMAX ? len : NMAX;
+        len -= k;
+        while (k >= 16) {
+            DO16(buf);
+            k -= 16;
+        }
+        if (k != 0) do {
+            DO1(buf);
+        } while (--k);
+        s1 %= BASE;
+        s2 %= BASE;
+    }
+    return (s2 << 16) | s1;
+}
diff --git a/arch/xtensa/boot/lib/zmem.c b/arch/xtensa/boot/lib/zmem.c
new file mode 100644
index 0000000..7848f12
--- /dev/null
+++ b/arch/xtensa/boot/lib/zmem.c
@@ -0,0 +1,87 @@
+#include "zlib.h"
+
+/* bits taken from ppc */
+
+extern void *avail_ram, *end_avail;
+
+void exit (void)
+{
+  for (;;);
+}
+
+void *zalloc(void *x, unsigned items, unsigned size)
+{
+        void *p = avail_ram;
+
+        size *= items;
+        size = (size + 7) & -8;
+        avail_ram += size;
+        if (avail_ram > end_avail) {
+                //puts("oops... out of memory\n");
+                //pause();
+                exit ();
+        }
+        return p;
+}
+
+void zfree(void *x, void *addr, unsigned nb)
+{
+}
+
+
+#define HEAD_CRC        2
+#define EXTRA_FIELD     4
+#define ORIG_NAME       8
+#define COMMENT         0x10
+#define RESERVED        0xe0
+
+#define DEFLATED        8
+
+void gunzip (void *dst, int dstlen, unsigned char *src, int *lenp)
+{
+	z_stream s;
+	int r, i, flags;
+
+        /* skip header */
+
+        i = 10;
+        flags = src[3];
+        if (src[2] != DEFLATED || (flags & RESERVED) != 0) {
+                //puts("bad gzipped data\n");
+                exit();
+        }
+        if ((flags & EXTRA_FIELD) != 0)
+                i = 12 + src[10] + (src[11] << 8);
+        if ((flags & ORIG_NAME) != 0)
+                while (src[i++] != 0)
+                        ;
+        if ((flags & COMMENT) != 0)
+                while (src[i++] != 0)
+                        ;
+        if ((flags & HEAD_CRC) != 0)
+                i += 2;
+        if (i >= *lenp) {
+                //puts("gunzip: ran out of data in header\n");
+                exit();
+        }
+
+        s.zalloc = zalloc;
+        s.zfree = zfree;
+        r = inflateInit2(&s, -MAX_WBITS);
+        if (r != Z_OK) {
+                //puts("inflateInit2 returned "); puthex(r); puts("\n");
+                exit();
+        }
+        s.next_in = src + i;
+        s.avail_in = *lenp - i;
+        s.next_out = dst;
+        s.avail_out = dstlen;
+        r = inflate(&s, Z_FINISH);
+        if (r != Z_OK && r != Z_STREAM_END) {
+                //puts("inflate returned "); puthex(r); puts("\n");
+                exit();
+        }
+        *lenp = s.next_out - (unsigned char *) dst;
+        inflateEnd(&s);
+}
+
diff --git a/arch/xtensa/boot/ramdisk/Makefile b/arch/xtensa/boot/ramdisk/Makefile
new file mode 100644
index 0000000..b12f763
--- /dev/null
+++ b/arch/xtensa/boot/ramdisk/Makefile
@@ -0,0 +1,23 @@
+#
+# Makefile for a ramdisk image
+#
+
+BIG_ENDIAN	:= $(shell echo -e "\#ifdef __XTENSA_EL__\nint little;\n\#else\nint big;\n\#endif" | $(CC) -E -|grep -c big)
+
+ifeq ($(BIG_ENDIAN),1)
+OBJCOPY_ARGS    := -O elf32-xtensa-be
+else
+OBJCOPY_ARGS    := -O elf32-xtensa-le
+endif
+
+obj-y = ramdisk.o
+
+RAMDISK_IMAGE = arch/$(ARCH)/boot/ramdisk/$(CONFIG_EMBEDDED_RAMDISK_IMAGE)
+
+arch/$(ARCH)/boot/ramdisk/ramdisk.o:
+	$(Q)echo -e "dummy:" | $(AS) -o $@;
+	$(Q)$(OBJCOPY) $(OBJCOPY_ARGS)					    \
+		--add-section .initrd=$(RAMDISK_IMAGE)			    \
+		--set-section-flags .initrd=contents,alloc,load,load,data   \
+		arch/$(ARCH)/boot/ramdisk/ramdisk.o $@
+
diff --git a/arch/xtensa/configs/common_defconfig b/arch/xtensa/configs/common_defconfig
new file mode 100644
index 0000000..1d230ee
--- /dev/null
+++ b/arch/xtensa/configs/common_defconfig
@@ -0,0 +1,662 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Tue Mar  1 16:36:53 2005
+#
+# CONFIG_FRAME_POINTER is not set
+CONFIG_XTENSA=y
+# CONFIG_UID16 is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+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_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# 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_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE 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_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Processor type and features
+#
+CONFIG_XTENSA_ARCH_LINUX_BE=y
+# CONFIG_XTENSA_ARCH_LINUX_LE is not set
+# CONFIG_XTENSA_ARCH_LINUX_TEST is not set
+# CONFIG_XTENSA_ARCH_S5 is not set
+# CONFIG_XTENSA_CUSTOM is not set
+CONFIG_MMU=y
+# CONFIG_XTENSA_UNALIGNED_USER is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_HIGHMEM is not set
+
+#
+# Platform options
+#
+# CONFIG_XTENSA_PLATFORM_ISS is not set
+CONFIG_XTENSA_PLATFORM_XT2000=y
+CONFIG_XTENSA_CALIBRATE_CCOUNT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,38400 ip=bootp root=nfs nfsroot=/opt/montavista/pro/devkit/xtensa/linux_be/target"
+
+#
+# Bus options
+#
+CONFIG_PCI=y
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
+# Exectuable file formats
+#
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+
+#
+# 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
+
+#
+# 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 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_RAM_COUNT=16
+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
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE 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
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=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 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=y
+CONFIG_NET_SCH_CLK_JIFFIES=y
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU is not set
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+# CONFIG_NET_SCH_HFSC is not set
+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 is not set
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_QOS=y
+CONFIG_NET_ESTIMATOR=y
+CONFIG_NET_CLS=y
+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_NET_CLS_IND is not set
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_CLS_POLICE=y
+
+#
+# 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=y
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_XT2000_SONIC=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM 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_SK98LIN is not set
+# CONFIG_TIGON3 is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+# 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=y
+
+#
+# Obsolete Wireless cards support (pre-802.11)
+#
+CONFIG_STRIP=m
+
+#
+# Wireless 802.11b ISA/PCI cards support
+#
+CONFIG_HERMES=m
+# CONFIG_PLX_HERMES is not set
+# CONFIG_TMD_HERMES is not set
+# CONFIG_PCI_HERMES is not set
+# CONFIG_ATMEL is not set
+
+#
+# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
+#
+# CONFIG_PRISM54 is not set
+CONFIG_NET_WIRELESS=y
+
+#
+# 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
+
+#
+# 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 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 I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_I8042 is not set
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW 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
+
+#
+# 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=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# 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
+
+#
+# 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
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 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
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# 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
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS 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_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 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_PROC_KCORE is not set
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# 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_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 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_EXPORTFS is not set
+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
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_KGDB 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 is not set
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/xtensa/configs/iss_defconfig b/arch/xtensa/configs/iss_defconfig
new file mode 100644
index 0000000..802621d
--- /dev/null
+++ b/arch/xtensa/configs/iss_defconfig
@@ -0,0 +1,531 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc2
+# Fri Feb 25 19:21:24 2005
+#
+CONFIG_FRAME_POINTER=y
+CONFIG_XTENSA=y
+# CONFIG_UID16 is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+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_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_KOBJECT_UEVENT is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE 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_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Processor type and features
+#
+CONFIG_XTENSA_ARCH_LINUX_BE=y
+# CONFIG_XTENSA_ARCH_LINUX_LE is not set
+# CONFIG_XTENSA_ARCH_LINUX_TEST is not set
+# CONFIG_XTENSA_ARCH_S5 is not set
+# CONFIG_XTENSA_CUSTOM is not set
+CONFIG_MMU=y
+# CONFIG_XTENSA_UNALIGNED_USER is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_MATH_EMULATION is not set
+# CONFIG_HIGHMEM is not set
+
+#
+# Platform options
+#
+CONFIG_XTENSA_PLATFORM_ISS=y
+# CONFIG_XTENSA_PLATFORM_XT2000 is not set
+# CONFIG_XTENSA_PLATFORM_ARUBA is not set
+# CONFIG_XTENSA_CALIBRATE_CCOUNT is not set
+CONFIG_XTENSA_CPU_CLOCK=10
+# CONFIG_GENERIC_CALIBRATE_DELAY is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,38400 eth0=tuntap,,tap0 ip=192.168.168.5:192.168.168.1 root=nfs nfsroot=192.168.168.1:/opt/montavista/pro/devkit/xtensa/linux_be/target"
+CONFIG_SERIAL_CONSOLE=y
+CONFIG_XTENSA_ISS_NETWORK=y
+
+#
+# Bus options
+#
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Exectuable file formats
+#
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER 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_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_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 is not set
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE 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=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_SCTP_HMAC_NONE is not set
+# CONFIG_SCTP_HMAC_SHA1 is not set
+# CONFIG_SCTP_HMAC_MD5 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_SCH_CLK_JIFFIES is not set
+# CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set
+# CONFIG_NET_SCH_CLK_CPU 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 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 I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 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
+
+#
+# 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_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=y
+# CONFIG_RTC is not set
+# CONFIG_GEN_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
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 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
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# 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
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS 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_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_PROC_KCORE=y
+CONFIG_SYSFS=y
+CONFIG_DEVFS_FS=y
+CONFIG_DEVFS_MOUNT=y
+# CONFIG_DEVFS_DEBUG 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
+
+#
+# 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_V4 is not set
+CONFIG_NFS_DIRECTIO=y
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+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
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_KGDB 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 is not set
+# CONFIG_LIBCRC32C is not set
diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
new file mode 100644
index 0000000..d573017
--- /dev/null
+++ b/arch/xtensa/kernel/Makefile
@@ -0,0 +1,18 @@
+#
+# Makefile for the Linux/Xtensa kernel.
+#
+
+extra-y := head.o vmlinux.lds
+
+
+obj-y := align.o entry.o irq.o coprocessor.o process.o ptrace.o semaphore.o  \
+	 setup.o signal.o syscalls.o time.o traps.o vectors.o platform.o  \
+	 pci-dma.o
+
+## windowspill.o
+
+obj-$(CONFIG_KGDB) += xtensa-stub.o
+obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_MODULES) += xtensa_ksyms.o module.o
+
+
diff --git a/arch/xtensa/kernel/align.S b/arch/xtensa/kernel/align.S
new file mode 100644
index 0000000..74b1e90
--- /dev/null
+++ b/arch/xtensa/kernel/align.S
@@ -0,0 +1,459 @@
+/*
+ * arch/xtensa/kernel/align.S
+ *
+ * Handle unalignment exceptions in kernel space.
+ *
+ * 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) 2001 - 2005 Tensilica, Inc.
+ *
+ * Rewritten by Chris Zankel <chris@zankel.net>
+ *
+ * Based on work from Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
+ * and Marc Gauthier <marc@tensilica.com, marc@alimni.uwaterloo.ca>
+ */
+
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+#include <asm/ptrace.h>
+#include <asm/current.h>
+#include <asm/offsets.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/thread_info.h>
+
+#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
+
+/*  First-level exception handler for unaligned exceptions.
+ *
+ *  Note: This handler works only for kernel exceptions.  Unaligned user
+ *        access should get a seg fault.
+ */
+
+/* Big and little endian 16-bit values are located in
+ * different halves of a register.  HWORD_START helps to
+ * abstract the notion of extracting a 16-bit value from a
+ * register.
+ * We also have to define new shifting instructions because
+ * lsb and msb are on 'opposite' ends in a register for
+ * different endian machines.
+ *
+ * Assume a memory region in ascending address:
+ *   	0 1 2 3|4 5 6 7
+ *
+ * When loading one word into a register, the content of that register is:
+ *  LE	3 2 1 0, 7 6 5 4
+ *  BE  0 1 2 3, 4 5 6 7
+ *
+ * Masking the bits of the higher/lower address means:
+ *  LE  X X 0 0, 0 0 X X
+ *  BE	0 0 X X, X X 0 0
+ *
+ * Shifting to higher/lower addresses, means:
+ *  LE  shift left / shift right
+ *  BE  shift right / shift left
+ *
+ * Extracting 16 bits from a 32 bit reg. value to higher/lower address means:
+ *  LE  mask 0 0 X X / shift left
+ *  BE  shift left / mask 0 0 X X
+ */
+
+#define UNALIGNED_USER_EXCEPTION
+
+#if XCHAL_HAVE_BE
+
+#define HWORD_START	16
+#define	INSN_OP0	28
+#define	INSN_T		24
+#define	INSN_OP1	16
+
+.macro __src_b	r, w0, w1;	src	\r, \w0, \w1;	.endm
+.macro __ssa8	r;		ssa8b	\r;		.endm
+.macro __ssa8r	r;		ssa8l	\r;		.endm
+.macro __sh	r, s;		srl	\r, \s;		.endm
+.macro __sl	r, s;		sll	\r, \s;		.endm
+.macro __exth	r, s;		extui	\r, \s, 0, 16;	.endm
+.macro __extl	r, s;		slli	\r, \s, 16;	.endm
+
+#else
+
+#define HWORD_START	0
+#define	INSN_OP0	0
+#define	INSN_T		4
+#define	INSN_OP1	12
+
+.macro __src_b	r, w0, w1;	src	\r, \w1, \w0;	.endm
+.macro __ssa8	r;		ssa8l	\r;		.endm
+.macro __ssa8r	r;		ssa8b	\r;		.endm
+.macro __sh	r, s;		sll	\r, \s;		.endm
+.macro __sl	r, s;		srl	\r, \s;		.endm
+.macro __exth	r, s;		slli	\r, \s, 16;	.endm
+.macro __extl	r, s;		extui	\r, \s, 0, 16;	.endm
+
+#endif
+
+/*
+ *	xxxx xxxx = imm8 field
+ *	     yyyy = imm4 field
+ *	     ssss = s field
+ *	     tttt = t field
+ *
+ *	       		 16		    0
+ *		          -------------------
+ *	L32I.N		  yyyy ssss tttt 1000
+ *	S32I.N	          yyyy ssss tttt 1001
+ *
+ *	       23			    0
+ *		-----------------------------
+ *	res	          0000           0010
+ *	L16UI	xxxx xxxx 0001 ssss tttt 0010
+ *	L32I	xxxx xxxx 0010 ssss tttt 0010
+ *	XXX	          0011 ssss tttt 0010
+ *	XXX	          0100 ssss tttt 0010
+ *	S16I	xxxx xxxx 0101 ssss tttt 0010
+ *	S32I	xxxx xxxx 0110 ssss tttt 0010
+ *	XXX	          0111 ssss tttt 0010
+ *	XXX	          1000 ssss tttt 0010
+ *	L16SI	xxxx xxxx 1001 ssss tttt 0010
+ *	XXX	          1010           0010
+ *      **L32AI	xxxx xxxx 1011 ssss tttt 0010 unsupported
+ *	XXX	          1100           0010
+ *	XXX	          1101           0010
+ *	XXX	          1110           0010
+ *	**S32RI	xxxx xxxx 1111 ssss tttt 0010 unsupported
+ *		-----------------------------
+ *                           ^         ^    ^
+ *    sub-opcode (NIBBLE_R) -+         |    |
+ *       t field (NIBBLE_T) -----------+    |
+ *  major opcode (NIBBLE_OP0) --------------+
+ */
+
+#define OP0_L32I_N	0x8		/* load immediate narrow */
+#define OP0_S32I_N	0x9		/* store immediate narrow */
+#define OP1_SI_MASK	0x4		/* OP1 bit set for stores */
+#define OP1_SI_BIT	2		/* OP1 bit number for stores */
+
+#define OP1_L32I	0x2
+#define OP1_L16UI	0x1
+#define OP1_L16SI	0x9
+#define OP1_L32AI	0xb
+
+#define OP1_S32I	0x6
+#define OP1_S16I	0x5
+#define OP1_S32RI	0xf
+
+/*
+ * Entry condition:
+ *
+ *   a0:	trashed, original value saved on stack (PT_AREG0)
+ *   a1:	a1
+ *   a2:	new stack pointer, original in DEPC
+ *   a3:	dispatch table
+ *   depc:	a2, original value saved on stack (PT_DEPC)
+ *   excsave_1:	a3
+ *
+ *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
+ *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
+ */
+
+
+ENTRY(fast_unaligned)
+
+	/* Note: We don't expect the address to be aligned on a word
+	 *       boundary. After all, the processor generated that exception
+	 *       and it would be a hardware fault.
+	 */
+
+	/* Save some working register */
+
+	s32i	a4, a2, PT_AREG4
+	s32i	a5, a2, PT_AREG5
+	s32i	a6, a2, PT_AREG6
+	s32i	a7, a2, PT_AREG7
+	s32i	a8, a2, PT_AREG8
+
+	rsr	a0, DEPC
+	xsr	a3, EXCSAVE_1
+	s32i	a0, a2, PT_AREG2
+	s32i	a3, a2, PT_AREG3
+
+	/* Keep value of SAR in a0 */
+
+	rsr	a0, SAR
+	rsr	a8, EXCVADDR		# load unaligned memory address
+
+	/* Now, identify one of the following load/store instructions.
+	 *
+	 * The only possible danger of a double exception on the
+	 * following l32i instructions is kernel code in vmalloc
+	 * memory. The processor was just executing at the EPC_1
+	 * address, and indeed, already fetched the instruction.  That
+	 * guarantees a TLB mapping, which hasn't been replaced by
+	 * this unaligned exception handler that uses only static TLB
+	 * mappings. However, high-level interrupt handlers might
+	 * modify TLB entries, so for the generic case, we register a
+	 * TABLE_FIXUP handler here, too.
+	 */
+
+	/* a3...a6 saved on stack, a2 = SP */
+
+	/* Extract the instruction that caused the unaligned access. */
+
+	rsr	a7, EPC_1	# load exception address
+	movi	a3, ~3
+	and	a3, a3, a7	# mask lower bits
+
+	l32i	a4, a3, 0	# load 2 words
+	l32i	a5, a3, 4
+
+	__ssa8	a7
+	__src_b	a4, a4, a5	# a4 has the instruction
+
+	/* Analyze the instruction (load or store?). */
+
+	extui	a5, a4, INSN_OP0, 4	# get insn.op0 nibble
+
+#if XCHAL_HAVE_NARROW
+	_beqi	a5, OP0_L32I_N, .Lload	# L32I.N, jump
+	addi	a6, a5, -OP0_S32I_N
+	_beqz	a6, .Lstore		# S32I.N, do a store
+#endif
+	/* 'store indicator bit' not set, jump */
+	_bbci.l	a4, OP1_SI_BIT + INSN_OP1, .Lload
+
+	/* Store: Jump to table entry to get the value in the source register.*/
+
+.Lstore:movi	a5, .Lstore_table	# table
+	extui	a6, a4, INSN_T, 4	# get source register
+	addx8	a5, a6, a5
+	jx	a5			# jump into table
+
+	/* Invalid instruction, CRITICAL! */
+.Linvalid_instruction_load:
+	j	.Linvalid_instruction
+
+	/* Load: Load memory address. */
+
+.Lload: movi	a3, ~3
+	and	a3, a3, a8		# align memory address
+
+	__ssa8	a8
+#ifdef UNALIGNED_USER_EXCEPTION
+	addi	a3, a3, 8
+	l32e	a5, a3, -8
+	l32e	a6, a3, -4
+#else
+	l32i	a5, a3, 0
+	l32i	a6, a3, 4
+#endif
+	__src_b	a3, a5, a6		# a3 has the data word
+
+#if XCHAL_HAVE_NARROW
+	addi	a7, a7, 2		# increment PC (assume 16-bit insn)
+
+	extui	a5, a4, INSN_OP0, 4
+	_beqi	a5, OP0_L32I_N, 1f	# l32i.n: jump
+
+	addi	a7, a7, 1
+#else
+	addi	a7, a7, 3
+#endif
+
+	extui	a5, a4, INSN_OP1, 4
+	_beqi	a5, OP1_L32I, 1f	# l32i: jump
+
+	extui	a3, a3, 0, 16		# extract lower 16 bits
+	_beqi	a5, OP1_L16UI, 1f
+	addi	a5, a5, -OP1_L16SI
+	_bnez	a5, .Linvalid_instruction_load
+
+	/* sign extend value */
+
+	slli	a3, a3, 16
+	srai	a3, a3, 16
+
+	/* Set target register. */
+
+1:
+
+#if XCHAL_HAVE_LOOP
+	rsr	a3, LEND		# check if we reached LEND
+	bne	a7, a3, 1f
+	rsr	a3, LCOUNT		# and LCOUNT != 0
+	beqz	a3, 1f
+	addi	a3, a3, -1		# decrement LCOUNT and set
+	rsr	a7, LBEG		# set PC to LBEGIN
+	wsr	a3, LCOUNT
+#endif
+
+1:	wsr	a7, EPC_1		# skip load instruction
+	extui	a4, a4, INSN_T, 4	# extract target register
+	movi	a5, .Lload_table
+	addx8	a4, a4, a5
+	jx	a4			# jump to entry for target register
+
+	.align	8
+.Lload_table:
+	s32i	a3, a2, PT_AREG0;	_j .Lexit;	.align 8
+	mov	a1, a3;			_j .Lexit;	.align 8 # fishy??
+	s32i	a3, a2, PT_AREG2;	_j .Lexit;	.align 8
+	s32i	a3, a2, PT_AREG3;	_j .Lexit;	.align 8
+	s32i	a3, a2, PT_AREG4;	_j .Lexit;	.align 8
+	s32i	a3, a2, PT_AREG5;	_j .Lexit;	.align 8
+	s32i	a3, a2, PT_AREG6;	_j .Lexit;	.align 8
+	s32i	a3, a2, PT_AREG7;	_j .Lexit;	.align 8
+	s32i	a3, a2, PT_AREG8;	_j .Lexit;	.align 8
+	mov	a9, a3		;	_j .Lexit;	.align 8
+	mov	a10, a3		;	_j .Lexit;	.align 8
+	mov	a11, a3		;	_j .Lexit;	.align 8
+	mov	a12, a3		;	_j .Lexit;	.align 8
+	mov	a13, a3		;	_j .Lexit;	.align 8
+	mov	a14, a3		;	_j .Lexit;	.align 8
+	mov	a15, a3		;	_j .Lexit;	.align 8
+
+.Lstore_table:
+	l32i	a3, a2, PT_AREG0;	_j 1f;	.align 8
+	mov	a3, a1;			_j 1f;	.align 8	# fishy??
+	l32i	a3, a2, PT_AREG2;	_j 1f;	.align 8
+	l32i	a3, a2, PT_AREG3;	_j 1f;	.align 8
+	l32i	a3, a2, PT_AREG4;	_j 1f;	.align 8
+	l32i	a3, a2, PT_AREG5;	_j 1f;	.align 8
+	l32i	a3, a2, PT_AREG6;	_j 1f;	.align 8
+	l32i	a3, a2, PT_AREG7;	_j 1f;	.align 8
+	l32i	a3, a2, PT_AREG8;	_j 1f;	.align 8
+	mov	a3, a9		;	_j 1f;	.align 8
+	mov	a3, a10		;	_j 1f;	.align 8
+	mov	a3, a11		;	_j 1f;	.align 8
+	mov	a3, a12		;	_j 1f;	.align 8
+	mov	a3, a13		;	_j 1f;	.align 8
+	mov	a3, a14		;	_j 1f;	.align 8
+	mov	a3, a15		;	_j 1f;	.align 8
+
+1: 	# a7: instruction pointer, a4: instruction, a3: value
+
+	movi	a6, 0			# mask: ffffffff:00000000
+
+#if XCHAL_HAVE_NARROW
+	addi	a7, a7, 2		# incr. PC,assume 16-bit instruction
+
+	extui	a5, a4, INSN_OP0, 4	# extract OP0
+	addi	a5, a5, -OP0_S32I_N
+	_beqz	a5, 1f			# s32i.n: jump
+
+	addi	a7, a7, 1		# increment PC, 32-bit instruction
+#else
+	addi	a7, a7, 3		# increment PC, 32-bit instruction
+#endif
+
+	extui	a5, a4, INSN_OP1, 4	# extract OP1
+	_beqi	a5, OP1_S32I, 1f	# jump if 32 bit store
+	_bnei	a5, OP1_S16I, .Linvalid_instruction_store
+
+	movi	a5, -1
+	__extl	a3, a3			# get 16-bit value
+	__exth	a6, a5			# get 16-bit mask ffffffff:ffff0000
+
+	/* Get memory address */
+
+1:
+#if XCHAL_HAVE_LOOP
+	rsr	a3, LEND		# check if we reached LEND
+	bne	a7, a3, 1f
+	rsr	a3, LCOUNT		# and LCOUNT != 0
+	beqz	a3, 1f
+	addi	a3, a3, -1		# decrement LCOUNT and set
+	rsr	a7, LBEG		# set PC to LBEGIN
+	wsr	a3, LCOUNT
+#endif
+
+1:	wsr	a7, EPC_1		# skip store instruction
+	movi	a4, ~3
+	and	a4, a4, a8		# align memory address
+
+	/* Insert value into memory */
+
+	movi	a5, -1			# mask: ffffffff:XXXX0000
+#ifdef UNALIGNED_USER_EXCEPTION
+	addi	a4, a4, 8
+#endif
+
+	__ssa8r a8
+	__src_b	a7, a5, a6		# lo-mask  F..F0..0 (BE) 0..0F..F (LE)
+	__src_b	a6, a6, a5		# hi-mask  0..0F..F (BE) F..F0..0 (LE)
+#ifdef UNALIGNED_USER_EXCEPTION
+	l32e	a5, a4, -8
+#else
+	l32i	a5, a4, 0		# load lower address word
+#endif
+	and	a5, a5, a7		# mask
+	__sh	a7, a3 			# shift value
+	or	a5, a5, a7		# or with original value
+#ifdef UNALIGNED_USER_EXCEPTION
+	s32e	a5, a4, -8
+	l32e	a7, a4, -4
+#else
+	s32i	a5, a4, 0		# store
+	l32i	a7, a4, 4		# same for upper address word
+#endif
+	__sl	a5, a3
+	and	a6, a7, a6
+	or	a6, a6, a5
+#ifdef UNALIGNED_USER_EXCEPTION
+	s32e	a6, a4, -4
+#else
+	s32i	a6, a4, 4
+#endif
+
+	/* Done. restore stack and return */
+
+.Lexit:
+	movi	a4, 0
+	rsr	a3, EXCSAVE_1
+	s32i	a4, a3, EXC_TABLE_FIXUP
+
+	/* Restore working register */
+
+	l32i	a7, a2, PT_AREG7
+	l32i	a6, a2, PT_AREG6
+	l32i	a5, a2, PT_AREG5
+	l32i	a4, a2, PT_AREG4
+	l32i	a3, a2, PT_AREG3
+
+	/* restore SAR and return */
+
+	wsr	a0, SAR
+	l32i	a0, a2, PT_AREG0
+	l32i	a2, a2, PT_AREG2
+	rfe
+
+	/* We cannot handle this exception. */
+
+	.extern _kernel_exception
+.Linvalid_instruction_store:
+.Linvalid_instruction:
+
+	/* Restore a4...a8 and SAR, set SP, and jump to default exception. */
+
+	l32i	a8, a2, PT_AREG8
+	l32i	a7, a2, PT_AREG7
+	l32i	a6, a2, PT_AREG6
+	l32i	a5, a2, PT_AREG5
+	l32i	a4, a2, PT_AREG4
+	wsr	a0, SAR
+	mov	a1, a2
+
+	rsr	a0, PS
+        bbsi.l  a2, PS_UM_SHIFT, 1f     # jump if user mode
+
+	movi	a0, _kernel_exception
+	jx	a0
+
+1:	movi	a0, _user_exception
+	jx	a0
+
+
+#endif /* XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION */
+
diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c
new file mode 100644
index 0000000..840cd9a
--- /dev/null
+++ b/arch/xtensa/kernel/asm-offsets.c
@@ -0,0 +1,94 @@
+/*
+ * arch/xtensa/kernel/asm-offsets.c
+ *
+ * Generates definitions from c-type structures used by assembly sources.
+ *
+ * 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 Tensilica Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ */
+
+#include <asm/processor.h>
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/stddef.h>
+#include <linux/thread_info.h>
+#include <linux/ptrace.h>
+#include <asm/ptrace.h>
+#include <asm/processor.h>
+#include <asm/uaccess.h>
+
+#define DEFINE(sym, val) asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+#define BLANK() asm volatile("\n->" : : )
+
+int main(void)
+{
+	/* struct pt_regs */
+	DEFINE(PT_PC, offsetof (struct pt_regs, pc));
+	DEFINE(PT_PS, offsetof (struct pt_regs, ps));
+	DEFINE(PT_DEPC, offsetof (struct pt_regs, depc));
+	DEFINE(PT_EXCCAUSE, offsetof (struct pt_regs, exccause));
+	DEFINE(PT_EXCVADDR, offsetof (struct pt_regs, excvaddr));
+	DEFINE(PT_DEBUGCAUSE, offsetof (struct pt_regs, debugcause));
+	DEFINE(PT_WMASK, offsetof (struct pt_regs, wmask));
+	DEFINE(PT_LBEG, offsetof (struct pt_regs, lbeg));
+	DEFINE(PT_LEND, offsetof (struct pt_regs, lend));
+	DEFINE(PT_LCOUNT, offsetof (struct pt_regs, lcount));
+	DEFINE(PT_SAR, offsetof (struct pt_regs, sar));
+	DEFINE(PT_SYSCALL, offsetof (struct pt_regs, syscall));
+	DEFINE(PT_AREG, offsetof (struct pt_regs, areg[0]));
+	DEFINE(PT_AREG0, offsetof (struct pt_regs, areg[0]));
+	DEFINE(PT_AREG1, offsetof (struct pt_regs, areg[1]));
+	DEFINE(PT_AREG2, offsetof (struct pt_regs, areg[2]));
+	DEFINE(PT_AREG3, offsetof (struct pt_regs, areg[3]));
+	DEFINE(PT_AREG4, offsetof (struct pt_regs, areg[4]));
+	DEFINE(PT_AREG5, offsetof (struct pt_regs, areg[5]));
+	DEFINE(PT_AREG6, offsetof (struct pt_regs, areg[6]));
+	DEFINE(PT_AREG7, offsetof (struct pt_regs, areg[7]));
+	DEFINE(PT_AREG8, offsetof (struct pt_regs, areg[8]));
+	DEFINE(PT_AREG9, offsetof (struct pt_regs, areg[9]));
+	DEFINE(PT_AREG10, offsetof (struct pt_regs, areg[10]));
+	DEFINE(PT_AREG11, offsetof (struct pt_regs, areg[11]));
+	DEFINE(PT_AREG12, offsetof (struct pt_regs, areg[12]));
+	DEFINE(PT_AREG13, offsetof (struct pt_regs, areg[13]));
+	DEFINE(PT_AREG14, offsetof (struct pt_regs, areg[14]));
+	DEFINE(PT_AREG15, offsetof (struct pt_regs, areg[15]));
+	DEFINE(PT_WINDOWBASE, offsetof (struct pt_regs, windowbase));
+	DEFINE(PT_WINDOWSTART, offsetof(struct pt_regs, windowstart));
+	DEFINE(PT_SIZE, sizeof(struct pt_regs));
+	DEFINE(PT_AREG_END, offsetof (struct pt_regs, areg[XCHAL_NUM_AREGS]));
+	DEFINE(PT_USER_SIZE, offsetof(struct pt_regs, areg[XCHAL_NUM_AREGS]));
+	BLANK();
+
+	/* struct task_struct */
+	DEFINE(TASK_PTRACE, offsetof (struct task_struct, ptrace));
+	DEFINE(TASK_MM, offsetof (struct task_struct, mm));
+	DEFINE(TASK_ACTIVE_MM, offsetof (struct task_struct, active_mm));
+	DEFINE(TASK_PID, offsetof (struct task_struct, pid));
+	DEFINE(TASK_THREAD, offsetof (struct task_struct, thread));
+	DEFINE(TASK_THREAD_INFO, offsetof (struct task_struct, thread_info));
+	DEFINE(TASK_STRUCT_SIZE, sizeof (struct task_struct));
+	BLANK();
+
+	/* struct thread_info (offset from start_struct) */
+	DEFINE(THREAD_RA, offsetof (struct task_struct, thread.ra));
+	DEFINE(THREAD_SP, offsetof (struct task_struct, thread.sp));
+	DEFINE(THREAD_CP_SAVE, offsetof (struct task_struct, thread.cp_save));
+	DEFINE(THREAD_CURRENT_DS, offsetof (struct task_struct, thread.current_ds));
+	BLANK();
+
+	/* struct mm_struct */
+	DEFINE(MM_USERS, offsetof(struct mm_struct, mm_users));
+	DEFINE(MM_PGD, offsetof (struct mm_struct, pgd));
+	DEFINE(MM_CONTEXT, offsetof (struct mm_struct, context));
+	BLANK();
+	DEFINE(PT_SINGLESTEP_BIT, PT_SINGLESTEP_BIT);
+	return 0;
+}
+
+
diff --git a/arch/xtensa/kernel/coprocessor.S b/arch/xtensa/kernel/coprocessor.S
new file mode 100644
index 0000000..356192a
--- /dev/null
+++ b/arch/xtensa/kernel/coprocessor.S
@@ -0,0 +1,201 @@
+/*
+ * arch/xtensa/kernel/coprocessor.S
+ *
+ * Xtensa processor configuration-specific table of coprocessor and
+ * other custom register layout information.
+ *
+ * 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 - 2005 Tensilica Inc.
+ *
+ * Marc Gauthier <marc@tensilica.com> <marc@alumni.uwaterloo.ca>
+ */
+
+/*
+ * This module contains a table that describes the layout of the various
+ * custom registers and states associated with each coprocessor, as well
+ * as those not associated with any coprocessor ("extra state").
+ * This table is included with core dumps and is available via the ptrace
+ * interface, allowing the layout of such register/state information to
+ * be modified in the kernel without affecting the debugger.  Each
+ * register or state is identified using a 32-bit "libdb target number"
+ * assigned when the Xtensa processor is generated.
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <asm/processor.h>
+
+#if XCHAL_HAVE_CP
+
+#define CP_LAST ((XCHAL_CP_MAX - 1) * COPROCESSOR_INFO_SIZE)
+
+ENTRY(release_coprocessors)
+
+	entry	a1, 16
+						# a2: task
+	movi	a3, 1 << XCHAL_CP_MAX 		# a3: coprocessor-bit
+	movi	a4, coprocessor_info+CP_LAST	# a4: owner-table
+						# a5: tmp
+	movi	a6, 0				# a6: 0
+	rsil	a7, LOCKLEVEL			# a7: PS
+
+1:	/* Check if task is coprocessor owner of coprocessor[i]. */
+
+	l32i	a5, a4, COPROCESSOR_INFO_OWNER
+	srli	a3, a3, 1
+	beqz	a3, 1f
+	addi	a4, a4, -8
+	beq	a2, a5, 1b
+
+	/* Found an entry: Clear entry CPENABLE bit to disable CP. */
+
+	rsr	a5, CPENABLE
+	s32i	a6, a4, COPROCESSOR_INFO_OWNER
+	xor	a5, a3, a5
+	wsr	a5, CPENABLE
+
+	bnez	a3, 1b
+
+1:	wsr	a7, PS
+	rsync
+	retw
+
+
+ENTRY(disable_coprocessor)
+	entry	sp, 16
+	rsil	a7, LOCKLEVEL
+	rsr	a3, CPENABLE
+	movi	a4, 1
+	ssl	a2
+	sll	a4, a4
+	and	a4, a3, a4
+	xor	a3, a3, a4
+	wsr	a3, CPENABLE
+	wsr	a7, PS
+	rsync
+	retw
+
+ENTRY(enable_coprocessor)
+	entry	sp, 16
+	rsil	a7, LOCKLEVEL
+	rsr	a3, CPENABLE
+	movi	a4, 1
+	ssl	a2
+	sll	a4, a4
+	or	a3, a3, a4
+	wsr	a3, CPENABLE
+	wsr	a7, PS
+	rsync
+	retw
+
+#endif
+
+ENTRY(save_coprocessor_extra)
+	entry	sp, 16
+	xchal_extra_store_funcbody
+	retw
+
+ENTRY(restore_coprocessor_extra)
+	entry	sp, 16
+	xchal_extra_load_funcbody
+	retw
+
+ENTRY(save_coprocessor_registers)
+	entry	sp, 16
+	xchal_cpi_store_funcbody
+	retw
+
+ENTRY(restore_coprocessor_registers)
+	entry	sp, 16
+	xchal_cpi_load_funcbody
+	retw
+
+
+/*
+ *  The Xtensa compile-time HAL (core.h) XCHAL_*_SA_CONTENTS_LIBDB macros
+ *  describe the contents of coprocessor & extra save areas in terms of
+ *  undefined CONTENTS_LIBDB_{SREG,UREG,REGF} macros.  We define these
+ *  latter macros here; they expand into a table of the format we want.
+ *  The general format is:
+ *
+ *	CONTENTS_LIBDB_SREG(libdbnum, offset, size, align, rsv1, name, sregnum,
+ *			    bitmask, rsv2, rsv3)
+ *	CONTENTS_LIBDB_UREG(libdbnum, offset, size, align, rsv1, name, uregnum,
+ *			    bitmask, rsv2, rsv3)
+ *	CONTENTS_LIBDB_REGF(libdbnum, offset, size, align, rsv1, name, index,
+ *			    numentries, contentsize, regname_base,
+ *			    regfile_name, rsv2, rsv3)
+ *
+ *  For this table, we only care about the <libdbnum>, <offset> and <size>
+ *  fields.
+ */
+
+/*  Map all XCHAL CONTENTS macros to the reg_entry asm macro defined below:  */
+
+#define CONTENTS_LIBDB_SREG(libdbnum,offset,size,align,rsv1,name,sregnum,     \
+			    bitmask, rsv2, rsv3)			      \
+		reg_entry libdbnum, offset, size ;
+#define CONTENTS_LIBDB_UREG(libdbnum,offset,size,align,rsv1,name,uregnum,     \
+			    bitmask, rsv2, rsv3)			      \
+		reg_entry libdbnum, offset, size ;
+#define CONTENTS_LIBDB_REGF(libdbnum, offset, size, align, rsv1, name, index, \
+			    numentries, contentsize, regname_base,	      \
+			    regfile_name, rsv2, rsv3)			      \
+		reg_entry libdbnum, offset, size ;
+
+/* A single table entry: */
+	.macro	reg_entry	libdbnum, offset, size
+	 .ifne	(__last_offset-(__last_group_offset+\offset))
+	  /* padding entry */
+	  .word	(0xFC000000+__last_offset-(__last_group_offset+\offset))
+	 .endif
+	 .word	\libdbnum				/* actual entry */
+	 .set	__last_offset, __last_group_offset+\offset+\size
+	.endm	/* reg_entry */
+
+
+/* Table entry that marks the beginning of a group (coprocessor or "extra"): */
+	.macro	reg_group	cpnum, num_entries, align
+	 .set	__last_group_offset, (__last_offset + \align- 1) & -\align
+	 .ifne	\num_entries
+	  .word	0xFD000000+(\cpnum<<16)+\num_entries
+	 .endif
+	.endm	/* reg_group */
+
+/*
+ * Register info tables.
+ */
+
+	.section .rodata, "a"
+	.globl	_xtensa_reginfo_tables
+	.globl	_xtensa_reginfo_table_size
+	.align	4
+_xtensa_reginfo_table_size:
+	.word	_xtensa_reginfo_table_end - _xtensa_reginfo_tables
+
+_xtensa_reginfo_tables:
+	.set	__last_offset, 0
+	reg_group 0xFF, XCHAL_EXTRA_SA_CONTENTS_LIBDB_NUM, XCHAL_EXTRA_SA_ALIGN
+	XCHAL_EXTRA_SA_CONTENTS_LIBDB
+	reg_group 0, XCHAL_CP0_SA_CONTENTS_LIBDB_NUM, XCHAL_CP0_SA_ALIGN
+	XCHAL_CP0_SA_CONTENTS_LIBDB
+	reg_group 1, XCHAL_CP1_SA_CONTENTS_LIBDB_NUM, XCHAL_CP1_SA_ALIGN
+	XCHAL_CP1_SA_CONTENTS_LIBDB
+	reg_group 2, XCHAL_CP2_SA_CONTENTS_LIBDB_NUM, XCHAL_CP2_SA_ALIGN
+	XCHAL_CP2_SA_CONTENTS_LIBDB
+	reg_group 3, XCHAL_CP3_SA_CONTENTS_LIBDB_NUM, XCHAL_CP3_SA_ALIGN
+	XCHAL_CP3_SA_CONTENTS_LIBDB
+	reg_group 4, XCHAL_CP4_SA_CONTENTS_LIBDB_NUM, XCHAL_CP4_SA_ALIGN
+	XCHAL_CP4_SA_CONTENTS_LIBDB
+	reg_group 5, XCHAL_CP5_SA_CONTENTS_LIBDB_NUM, XCHAL_CP5_SA_ALIGN
+	XCHAL_CP5_SA_CONTENTS_LIBDB
+	reg_group 6, XCHAL_CP6_SA_CONTENTS_LIBDB_NUM, XCHAL_CP6_SA_ALIGN
+	XCHAL_CP6_SA_CONTENTS_LIBDB
+	reg_group 7, XCHAL_CP7_SA_CONTENTS_LIBDB_NUM, XCHAL_CP7_SA_ALIGN
+	XCHAL_CP7_SA_CONTENTS_LIBDB
+	.word	0xFC000000	/* invalid register number,marks end of table*/
+_xtensa_reginfo_table_end:
+
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
new file mode 100644
index 0000000..c64a01f
--- /dev/null
+++ b/arch/xtensa/kernel/entry.S
@@ -0,0 +1,1996 @@
+/*
+ * arch/xtensa/kernel/entry.S
+ *
+ * Low-level exception handling
+ *
+ * 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-2005 by Tensilica Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ *
+ */
+
+#include <linux/linkage.h>
+#include <asm/offsets.h>
+#include <asm/processor.h>
+#include <asm/thread_info.h>
+#include <asm/uaccess.h>
+#include <asm/unistd.h>
+#include <asm/ptrace.h>
+#include <asm/current.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/signal.h>
+#include <xtensa/coreasm.h>
+
+/* Unimplemented features. */
+
+#undef SIGNAL_HANDLING_IN_DOUBLE_EXCEPTION
+#undef KERNEL_STACK_OVERFLOW_CHECK
+#undef PREEMPTIBLE_KERNEL
+#undef ALLOCA_EXCEPTION_IN_IRAM
+
+/* Not well tested.
+ *
+ * - fast_coprocessor
+ */
+
+/*
+ * Macro to find first bit set in WINDOWBASE from the left + 1
+ *
+ * 100....0 -> 1
+ * 010....0 -> 2
+ * 000....1 -> WSBITS
+ */
+
+	.macro ffs_ws bit mask
+
+#if XCHAL_HAVE_NSA
+	nsau    \bit, \mask			# 32-WSBITS ... 31 (32 iff 0)
+	addi    \bit, \bit, WSBITS - 32 + 1   	# uppest bit set -> return 1
+#else
+	movi    \bit, WSBITS
+#if WSBITS > 16
+	_bltui  \mask, 0x10000, 99f
+	addi    \bit, \bit, -16
+	extui   \mask, \mask, 16, 16
+#endif
+#if WSBITS > 8
+99:	_bltui  \mask, 0x100, 99f
+	addi    \bit, \bit, -8
+	srli    \mask, \mask, 8
+#endif
+99:	_bltui  \mask, 0x10, 99f
+	addi    \bit, \bit, -4
+	srli    \mask, \mask, 4
+99:	_bltui  \mask, 0x4, 99f
+	addi    \bit, \bit, -2
+	srli    \mask, \mask, 2
+99:	_bltui  \mask, 0x2, 99f
+	addi    \bit, \bit, -1
+99:
+
+#endif
+	.endm
+
+/* ----------------- DEFAULT FIRST LEVEL EXCEPTION HANDLERS ----------------- */
+
+/*
+ * First-level exception handler for user exceptions.
+ * Save some special registers, extra states and all registers in the AR
+ * register file that were in use in the user task, and jump to the common
+ * exception code.
+ * We save SAR (used to calculate WMASK), and WB and WS (we don't have to
+ * save them for kernel exceptions).
+ *
+ * Entry condition for user_exception:
+ *
+ *   a0:	trashed, original value saved on stack (PT_AREG0)
+ *   a1:	a1
+ *   a2:	new stack pointer, original value in depc
+ *   a3:	dispatch table
+ *   depc:	a2, original value saved on stack (PT_DEPC)
+ *   excsave1:	a3
+ *
+ *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
+ *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
+ *
+ * Entry condition for _user_exception:
+ *
+ *   a0-a3 and depc have been saved to PT_AREG0...PT_AREG3 and PT_DEPC
+ *   excsave has been restored, and
+ *   stack pointer (a1) has been set.
+ *
+ * Note: _user_exception might be at an odd adress. Don't use call0..call12
+ */
+
+ENTRY(user_exception)
+
+	/* Save a2, a3, and depc, restore excsave_1 and set SP. */
+
+	xsr	a3, EXCSAVE_1
+	rsr	a0, DEPC
+	s32i	a1, a2, PT_AREG1
+	s32i	a0, a2, PT_AREG2
+	s32i	a3, a2, PT_AREG3
+	mov	a1, a2
+
+	.globl _user_exception
+_user_exception:
+
+	/* Save SAR and turn off single stepping */
+
+	movi	a2, 0
+	rsr	a3, SAR
+	wsr	a2, ICOUNTLEVEL
+	s32i	a3, a1, PT_SAR
+
+	/* Rotate ws so that the current windowbase is at bit0. */
+	/* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */
+
+	rsr	a2, WINDOWBASE
+	rsr	a3, WINDOWSTART
+	ssr	a2
+	s32i	a2, a1, PT_WINDOWBASE
+	s32i	a3, a1, PT_WINDOWSTART
+	slli	a2, a3, 32-WSBITS
+	src	a2, a3, a2
+	srli	a2, a2, 32-WSBITS
+	s32i	a2, a1, PT_WMASK	# needed for restoring registers
+
+	/* Save only live registers. */
+
+	_bbsi.l	a2, 1, 1f
+	s32i	a4, a1, PT_AREG4
+	s32i	a5, a1, PT_AREG5
+	s32i	a6, a1, PT_AREG6
+	s32i	a7, a1, PT_AREG7
+	_bbsi.l	a2, 2, 1f
+	s32i	a8, a1, PT_AREG8
+	s32i	a9, a1, PT_AREG9
+	s32i	a10, a1, PT_AREG10
+	s32i	a11, a1, PT_AREG11
+	_bbsi.l	a2, 3, 1f
+	s32i	a12, a1, PT_AREG12
+	s32i	a13, a1, PT_AREG13
+	s32i	a14, a1, PT_AREG14
+	s32i	a15, a1, PT_AREG15
+	_bnei	a2, 1, 1f		# only one valid frame?
+
+	/* Only one valid frame, skip saving regs. */
+
+	j	2f
+
+	/* Save the remaining registers.
+	 * We have to save all registers up to the first '1' from
+	 * the right, except the current frame (bit 0).
+	 * Assume a2 is:  001001000110001
+	 * All regiser frames starting from the top fiel to the marked '1'
+	 * must be saved.
+	 */
+
+1:	addi	a3, a2, -1		# eliminate '1' in bit 0: yyyyxxww0
+	neg	a3, a3			# yyyyxxww0 -> YYYYXXWW1+1
+	and	a3, a3, a2		# max. only one bit is set
+
+	/* Find number of frames to save */
+
+	ffs_ws	a0, a3			# number of frames to the '1' from left
+
+	/* Store information into WMASK:
+	 * bits 0..3: xxx1 masked lower 4 bits of the rotated windowstart,
+	 * bits 4...: number of valid 4-register frames
+	 */
+
+	slli	a3, a0, 4		# number of frames to save in bits 8..4
+	extui	a2, a2, 0, 4		# mask for the first 16 registers
+	or	a2, a3, a2
+	s32i	a2, a1, PT_WMASK	# needed when we restore the reg-file
+
+	/* Save 4 registers at a time */
+
+1:	rotw	-1
+	s32i	a0, a5, PT_AREG_END - 16
+	s32i	a1, a5, PT_AREG_END - 12
+	s32i	a2, a5, PT_AREG_END - 8
+	s32i	a3, a5, PT_AREG_END - 4
+	addi	a0, a4, -1
+	addi	a1, a5, -16
+	_bnez	a0, 1b
+
+	/* WINDOWBASE still in SAR! */
+
+	rsr	a2, SAR			# original WINDOWBASE
+	movi	a3, 1
+	ssl	a2
+	sll	a3, a3
+	wsr	a3, WINDOWSTART		# set corresponding WINDOWSTART bit
+	wsr	a2, WINDOWBASE		# and WINDOWSTART
+	rsync
+
+	/* We are back to the original stack pointer (a1) */
+
+2:
+#if XCHAL_EXTRA_SA_SIZE
+
+	/* For user exceptions, save the extra state into the user's TCB.
+	 * Note: We must assume that xchal_extra_store_funcbody destroys a2..a15
+	 */
+
+	GET_CURRENT(a2,a1)
+	addi	a2, a2, THREAD_CP_SAVE
+	xchal_extra_store_funcbody
+#endif
+
+	/* Now, jump to the common exception handler. */
+
+	j	common_exception
+
+
+/*
+ * First-level exit handler for kernel exceptions
+ * Save special registers and the live window frame.
+ * Note: Even though we changes the stack pointer, we don't have to do a
+ *	 MOVSP here, as we do that when we return from the exception.
+ *	 (See comment in the kernel exception exit code)
+ *
+ * Entry condition for kernel_exception:
+ *
+ *   a0:	trashed, original value saved on stack (PT_AREG0)
+ *   a1:	a1
+ *   a2:	new stack pointer, original in DEPC
+ *   a3:	dispatch table
+ *   depc:	a2, original value saved on stack (PT_DEPC)
+ *   excsave_1:	a3
+ *
+ *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
+ *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
+ *
+ * Entry condition for _kernel_exception:
+ *
+ *   a0-a3 and depc have been saved to PT_AREG0...PT_AREG3 and PT_DEPC
+ *   excsave has been restored, and
+ *   stack pointer (a1) has been set.
+ *
+ * Note: _kernel_exception might be at an odd adress. Don't use call0..call12
+ */
+
+ENTRY(kernel_exception)
+
+	/* Save a0, a2, a3, DEPC and set SP. */
+
+	xsr	a3, EXCSAVE_1		# restore a3, excsave_1
+	rsr	a0, DEPC		# get a2
+	s32i	a1, a2, PT_AREG1
+	s32i	a0, a2, PT_AREG2
+	s32i	a3, a2, PT_AREG3
+	mov	a1, a2
+
+	.globl _kernel_exception
+_kernel_exception:
+
+	/* Save SAR and turn off single stepping */
+
+	movi	a2, 0
+	rsr	a3, SAR
+	wsr	a2, ICOUNTLEVEL
+	s32i	a3, a1, PT_SAR
+
+	/* Rotate ws so that the current windowbase is at bit0. */
+	/* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */
+
+	rsr	a2, WINDOWBASE		# don't need to save these, we only
+	rsr	a3, WINDOWSTART		# need shifted windowstart: windowmask
+	ssr	a2
+	slli	a2, a3, 32-WSBITS
+	src	a2, a3, a2
+	srli	a2, a2, 32-WSBITS
+	s32i	a2, a1, PT_WMASK	# needed for kernel_exception_exit
+
+	/* Save only the live window-frame */
+
+	_bbsi.l	a2, 1, 1f
+	s32i	a4, a1, PT_AREG4
+	s32i	a5, a1, PT_AREG5
+	s32i	a6, a1, PT_AREG6
+	s32i	a7, a1, PT_AREG7
+	_bbsi.l	a2, 2, 1f
+	s32i	a8, a1, PT_AREG8
+	s32i	a9, a1, PT_AREG9
+	s32i	a10, a1, PT_AREG10
+	s32i	a11, a1, PT_AREG11
+	_bbsi.l	a2, 3, 1f
+	s32i	a12, a1, PT_AREG12
+	s32i	a13, a1, PT_AREG13
+	s32i	a14, a1, PT_AREG14
+	s32i	a15, a1, PT_AREG15
+
+1:
+
+#ifdef KERNEL_STACK_OVERFLOW_CHECK
+
+	/*  Stack overflow check, for debugging  */
+	extui	a2, a1, TASK_SIZE_BITS,XX
+	movi	a3, SIZE??
+	_bge	a2, a3, out_of_stack_panic
+
+#endif
+
+/*
+ * This is the common exception handler.
+ * We get here from the user exception handler or simply by falling through
+ * from the kernel exception handler.
+ * Save the remaining special registers, switch to kernel mode, and jump
+ * to the second-level exception handler.
+ *
+ */
+
+common_exception:
+
+	/* Save EXCVADDR, DEBUGCAUSE, and PC, and clear LCOUNT */
+
+	rsr	a2, DEBUGCAUSE
+	rsr	a3, EPC_1
+	s32i	a2, a1, PT_DEBUGCAUSE
+	s32i	a3, a1, PT_PC
+
+	rsr	a3, EXCVADDR
+	movi	a2, 0
+	s32i	a3, a1, PT_EXCVADDR
+	xsr	a2, LCOUNT
+	s32i	a2, a1, PT_LCOUNT
+
+	/* It is now save to restore the EXC_TABLE_FIXUP variable. */
+
+	rsr	a0, EXCCAUSE
+	movi	a3, 0
+	rsr	a2, EXCSAVE_1
+	s32i	a0, a1, PT_EXCCAUSE
+	s32i	a3, a2, EXC_TABLE_FIXUP
+
+	/* All unrecoverable states are saved on stack, now, and a1 is valid,
+	 * so we can allow exceptions and interrupts (*) again.
+	 * Set PS(EXCM = 0, UM = 0, RING = 0, OWB = 0, WOE = 1, INTLEVEL = X)
+	 *
+	 * (*) We only allow interrupts if PS.INTLEVEL was not set to 1 before
+	 *     (interrupts disabled) and if this exception is not an interrupt.
+	 */
+
+	rsr	a3, PS
+	addi	a0, a0, -4
+	movi	a2, 1
+	extui	a3, a3, 0, 1		# a3 = PS.INTLEVEL[0]
+	moveqz	a3, a2, a0		# a3 = 1 iff interrupt exception
+	movi	a2, PS_WOE_MASK
+	or	a3, a3, a2
+	rsr	a0, EXCCAUSE
+	xsr	a3, PS
+
+	s32i	a3, a1, PT_PS		# save ps
+
+	/* Save LBEG, LEND */
+
+	rsr	a2, LBEG
+	rsr	a3, LEND
+	s32i	a2, a1, PT_LBEG
+	s32i	a3, a1, PT_LEND
+
+	/* Go to second-level dispatcher. Set up parameters to pass to the
+	 * exception handler and call the exception handler.
+	 */
+
+	movi	a4, exc_table
+	mov	a6, a1			# pass stack frame
+	mov	a7, a0			# pass EXCCAUSE
+	addx4	a4, a0, a4
+	l32i	a4, a4, EXC_TABLE_DEFAULT		# load handler
+
+	/* Call the second-level handler */
+
+	callx4	a4
+
+	/* Jump here for exception exit */
+
+common_exception_return:
+
+	/* Jump if we are returning from kernel exceptions. */
+
+1:	l32i	a3, a1, PT_PS
+	_bbsi.l	a3, PS_UM_SHIFT, 2f
+	j	kernel_exception_exit
+
+	/* Specific to a user exception exit:
+	 * We need to check some flags for signal handling and rescheduling,
+	 * and have to restore WB and WS, extra states, and all registers
+	 * in the register file that were in use in the user task.
+	 */
+
+2:	wsr	a3, PS		/* disable interrupts */
+
+	/* Check for signals (keep interrupts disabled while we read TI_FLAGS)
+	 * Note: PS.INTLEVEL = 0, PS.EXCM = 1
+	 */
+
+	GET_THREAD_INFO(a2,a1)
+	l32i	a4, a2, TI_FLAGS
+
+	/* Enable interrupts again.
+	 * Note: When we get here, we certainly have handled any interrupts.
+	 *       (Hint: There is only one user exception frame on stack)
+	 */
+
+	movi	a3, PS_WOE_MASK
+
+	_bbsi.l	a4, TIF_NEED_RESCHED, 3f
+	_bbci.l	a4, TIF_SIGPENDING, 4f
+
+#ifndef SIGNAL_HANDLING_IN_DOUBLE_EXCEPTION
+	l32i	a4, a1, PT_DEPC
+	bgeui	a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f
+#endif
+
+	/* Reenable interrupts and call do_signal() */
+
+	wsr	a3, PS
+	movi	a4, do_signal	# int do_signal(struct pt_regs*, sigset_t*)
+	mov	a6, a1
+	movi	a7, 0
+	callx4	a4
+	j	1b
+
+3:	/* Reenable interrupts and reschedule */
+
+	wsr	a3, PS
+	movi	a4, schedule	# void schedule (void)
+	callx4	a4
+	j	1b
+
+	/* Restore the state of the task and return from the exception. */
+
+
+	/* If we are returning from a user exception, and the process
+	 * to run next has PT_SINGLESTEP set, we want to setup
+	 * ICOUNT and ICOUNTLEVEL to step one instruction.
+	 * PT_SINGLESTEP is set by sys_ptrace (ptrace.c)
+	 */
+
+4:	/* a2 holds GET_CURRENT(a2,a1)  */
+
+	l32i	a3, a2, TI_TASK
+	l32i	a3, a3, TASK_PTRACE
+	bbci.l	a3, PT_SINGLESTEP_BIT, 1f # jump if single-step flag is not set
+
+	movi	a3, -2			# PT_SINGLESTEP flag is set,
+	movi	a4, 1			# icountlevel of 1 means it won't
+	wsr	a3, ICOUNT		# start counting until after rfe
+	wsr	a4, ICOUNTLEVEL		# so setup icount & icountlevel.
+	isync
+
+1:
+
+#if XCHAL_EXTRA_SA_SIZE
+
+	/* For user exceptions, restore the extra state from the user's TCB. */
+
+	/* Note: a2 still contains GET_CURRENT(a2,a1) */
+	addi	a2, a2, THREAD_CP_SAVE
+	xchal_extra_load_funcbody
+
+	/* We must assume that xchal_extra_store_funcbody destroys
+	 * registers a2..a15.  FIXME, this list can eventually be
+	 * reduced once real register requirements of the macro are
+	 * finalized. */
+
+#endif /* XCHAL_EXTRA_SA_SIZE */
+
+
+	/* Switch to the user thread WINDOWBASE. Save SP temporarily in DEPC */
+
+	l32i	a2, a1, PT_WINDOWBASE
+	l32i	a3, a1, PT_WINDOWSTART
+	wsr	a1, DEPC		# use DEPC as temp storage
+	wsr	a3, WINDOWSTART		# restore WINDOWSTART
+	ssr	a2			# preserve user's WB in the SAR
+	wsr	a2, WINDOWBASE		# switch to user's saved WB
+	rsync
+	rsr	a1, DEPC		# restore stack pointer
+	l32i	a2, a1, PT_WMASK	# register frames saved (in bits 4...9)
+	rotw	-1			# we restore a4..a7
+	_bltui	a6, 16, 1f		# only have to restore current window?
+
+	/* The working registers are a0 and a3.  We are restoring to
+	 * a4..a7.  Be careful not to destroy what we have just restored.
+	 * Note: wmask has the format YYYYM:
+	 *       Y: number of registers saved in groups of 4
+	 *       M: 4 bit mask of first 16 registers
+	 */
+
+	mov	a2, a6
+	mov	a3, a5
+
+2:	rotw	-1			# a0..a3 become a4..a7
+	addi	a3, a7, -4*4		# next iteration
+	addi	a2, a6, -16		# decrementing Y in WMASK
+	l32i	a4, a3, PT_AREG_END + 0
+	l32i	a5, a3, PT_AREG_END + 4
+	l32i	a6, a3, PT_AREG_END + 8
+	l32i	a7, a3, PT_AREG_END + 12
+	_bgeui	a2, 16, 2b
+
+	/* Clear unrestored registers (don't leak anything to user-land */
+
+1:	rsr	a0, WINDOWBASE
+	rsr	a3, SAR
+	sub	a3, a0, a3
+	beqz	a3, 2f
+	extui	a3, a3, 0, WBBITS
+
+1:	rotw	-1
+	addi	a3, a7, -1
+	movi	a4, 0
+	movi	a5, 0
+	movi	a6, 0
+	movi	a7, 0
+	bgei	a3, 1, 1b
+
+	/* We are back were we were when we started.
+	 * Note: a2 still contains WMASK (if we've returned to the original
+	 *	 frame where we had loaded a2), or at least the lower 4 bits
+	 *	 (if we have restored WSBITS-1 frames).
+	 */
+
+2:	j	common_exception_exit
+
+	/* This is the kernel exception exit.
+	 * We avoided to do a MOVSP when we entered the exception, but we
+	 * have to do it here.
+	 */
+
+kernel_exception_exit:
+
+	/* Disable interrupts (a3 holds PT_PS) */
+
+	wsr	a3, PS
+
+#ifdef PREEMPTIBLE_KERNEL
+
+#ifdef CONFIG_PREEMPT
+
+	/*
+	 * Note: We've just returned from a call4, so we have
+	 * at least 4 addt'l regs.
+	 */
+
+	/* Check current_thread_info->preempt_count */
+
+	GET_THREAD_INFO(a2)
+	l32i	a3, a2, TI_PREEMPT
+	bnez	a3, 1f
+
+	l32i	a2, a2, TI_FLAGS
+
+1:
+
+#endif
+
+#endif
+
+	/* Check if we have to do a movsp.
+	 *
+	 * We only have to do a movsp if the previous window-frame has
+	 * been spilled to the *temporary* exception stack instead of the
+	 * task's stack. This is the case if the corresponding bit in
+	 * WINDOWSTART for the previous window-frame was set before
+	 * (not spilled) but is zero now (spilled).
+	 * If this bit is zero, all other bits except the one for the
+	 * current window frame are also zero. So, we can use a simple test:
+	 * 'and' WINDOWSTART and WINDOWSTART-1:
+	 *
+	 *  (XXXXXX1[0]* - 1) AND XXXXXX1[0]* = XXXXXX0[0]*
+	 *
+	 * The result is zero only if one bit was set.
+	 *
+	 * (Note: We might have gone through several task switches before
+	 *        we come back to the current task, so WINDOWBASE might be
+	 *        different from the time the exception occurred.)
+	 */
+
+	/* Test WINDOWSTART before and after the exception.
+	 * We actually have WMASK, so we only have to test if it is 1 or not.
+	 */
+
+	l32i	a2, a1, PT_WMASK
+	_beqi	a2, 1, common_exception_exit	# Spilled before exception,jump
+
+	/* Test WINDOWSTART now. If spilled, do the movsp */
+
+	rsr     a3, WINDOWSTART
+	addi	a0, a3, -1
+	and     a3, a3, a0
+	_bnez	a3, common_exception_exit
+
+	/* Do a movsp (we returned from a call4, so we have at least a0..a7) */
+
+	addi    a0, a1, -16
+	l32i    a3, a0, 0
+	l32i    a4, a0, 4
+	s32i    a3, a1, PT_SIZE+0
+	s32i    a4, a1, PT_SIZE+4
+	l32i    a3, a0, 8
+	l32i    a4, a0, 12
+	s32i    a3, a1, PT_SIZE+8
+	s32i    a4, a1, PT_SIZE+12
+
+	/* Common exception exit.
+	 * We restore the special register and the current window frame, and
+	 * return from the exception.
+	 *
+	 * Note: We expect a2 to hold PT_WMASK
+	 */
+
+common_exception_exit:
+
+	_bbsi.l	a2, 1, 1f
+	l32i	a4,  a1, PT_AREG4
+	l32i	a5,  a1, PT_AREG5
+	l32i	a6,  a1, PT_AREG6
+	l32i	a7,  a1, PT_AREG7
+	_bbsi.l	a2, 2, 1f
+	l32i	a8,  a1, PT_AREG8
+	l32i	a9,  a1, PT_AREG9
+	l32i	a10, a1, PT_AREG10
+	l32i	a11, a1, PT_AREG11
+	_bbsi.l	a2, 3, 1f
+	l32i	a12, a1, PT_AREG12
+	l32i	a13, a1, PT_AREG13
+	l32i	a14, a1, PT_AREG14
+	l32i	a15, a1, PT_AREG15
+
+	/* Restore PC, SAR */
+
+1:	l32i	a2, a1, PT_PC
+	l32i	a3, a1, PT_SAR
+	wsr	a2, EPC_1
+	wsr	a3, SAR
+
+	/* Restore LBEG, LEND, LCOUNT */
+
+	l32i	a2, a1, PT_LBEG
+	l32i	a3, a1, PT_LEND
+	wsr	a2, LBEG
+	l32i	a2, a1, PT_LCOUNT
+	wsr	a3, LEND
+	wsr	a2, LCOUNT
+
+	/* Check if it was double exception. */
+
+	l32i	a0, a1, PT_DEPC
+	l32i	a3, a1, PT_AREG3
+	l32i	a2, a1, PT_AREG2
+	_bgeui	a0, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
+
+	/* Restore a0...a3 and return */
+
+	l32i	a0, a1, PT_AREG0
+	l32i	a1, a1, PT_AREG1
+	rfe
+
+1:	wsr	a0, DEPC
+	l32i	a0, a1, PT_AREG0
+	l32i	a1, a1, PT_AREG1
+	rfde
+
+/*
+ * Debug exception handler.
+ *
+ * Currently, we don't support KGDB, so only user application can be debugged.
+ *
+ * When we get here,  a0 is trashed and saved to excsave[debuglevel]
+ */
+
+ENTRY(debug_exception)
+
+	rsr	a0, EPS + XCHAL_DEBUGLEVEL
+	bbsi.l	a0, PS_EXCM_SHIFT, 1f	# exception mode
+
+	/* Set EPC_1 and EXCCAUSE */
+
+	wsr	a2, DEPC		# save a2 temporarily
+	rsr	a2, EPC + XCHAL_DEBUGLEVEL
+	wsr	a2, EPC_1
+
+	movi	a2, EXCCAUSE_MAPPED_DEBUG
+	wsr	a2, EXCCAUSE
+
+	/* Restore PS to the value before the debug exc but with PS.EXCM set.*/
+
+	movi	a2, 1 << PS_EXCM_SHIFT
+	or	a2, a0, a2
+	movi	a0, debug_exception	# restore a3, debug jump vector
+	wsr	a2, PS
+	xsr	a0, EXCSAVE + XCHAL_DEBUGLEVEL
+
+	/* Switch to kernel/user stack, restore jump vector, and save a0 */
+
+	bbsi.l	a2, PS_UM_SHIFT, 2f	# jump if user mode
+
+	addi	a2, a1, -16-PT_SIZE	# assume kernel stack
+	s32i	a0, a2, PT_AREG0
+	movi	a0, 0
+	s32i	a1, a2, PT_AREG1
+	s32i	a0, a2, PT_DEPC		# mark it as a regular exception
+	xsr	a0, DEPC
+	s32i	a3, a2, PT_AREG3
+	s32i	a0, a2, PT_AREG2
+	mov	a1, a2
+	j	_kernel_exception
+
+2:	rsr	a2, EXCSAVE_1
+	l32i	a2, a2, EXC_TABLE_KSTK	# load kernel stack pointer
+	s32i	a0, a2, PT_AREG0
+	movi	a0, 0
+	s32i	a1, a2, PT_AREG1
+	s32i	a0, a2, PT_DEPC
+	xsr	a0, DEPC
+	s32i	a3, a2, PT_AREG3
+	s32i	a0, a2, PT_AREG2
+	mov	a1, a2
+	j	_user_exception
+
+	/* Debug exception while in exception mode. */
+1:	j	1b	// FIXME!!
+
+
+/*
+ * We get here in case of an unrecoverable exception.
+ * The only thing we can do is to be nice and print a panic message.
+ * We only produce a single stack frame for panic, so ???
+ *
+ *
+ * Entry conditions:
+ *
+ *   - a0 contains the caller address; original value saved in excsave1.
+ *   - the original a0 contains a valid return address (backtrace) or 0.
+ *   - a2 contains a valid stackpointer
+ *
+ * Notes:
+ *
+ *   - If the stack pointer could be invalid, the caller has to setup a
+ *     dummy stack pointer (e.g. the stack of the init_task)
+ *
+ *   - If the return address could be invalid, the caller has to set it
+ *     to 0, so the backtrace would stop.
+ *
+ */
+	.align 4
+unrecoverable_text:
+	.ascii "Unrecoverable error in exception handler\0"
+
+ENTRY(unrecoverable_exception)
+
+	movi	a0, 1
+	movi	a1, 0
+
+	wsr	a0, WINDOWSTART
+	wsr	a1, WINDOWBASE
+	rsync
+
+	movi	a1, PS_WOE_MASK | 1
+	wsr	a1, PS
+	rsync
+
+	movi	a1, init_task
+	movi	a0, 0
+	addi	a1, a1, PT_REGS_OFFSET
+
+	movi	a4, panic
+	movi	a6, unrecoverable_text
+
+	callx4	a4
+
+1:	j	1b
+
+
+/* -------------------------- FAST EXCEPTION HANDLERS ----------------------- */
+
+/*
+ * Fast-handler for alloca exceptions
+ *
+ *  The ALLOCA handler is entered when user code executes the MOVSP
+ *  instruction and the caller's frame is not in the register file.
+ *  In this case, the caller frame's a0..a3 are on the stack just
+ *  below sp (a1), and this handler moves them.
+ *
+ *  For "MOVSP <ar>,<as>" without destination register a1, this routine
+ *  simply moves the value from <as> to <ar> without moving the save area.
+ *
+ * Entry condition:
+ *
+ *   a0:	trashed, original value saved on stack (PT_AREG0)
+ *   a1:	a1
+ *   a2:	new stack pointer, original in DEPC
+ *   a3:	dispatch table
+ *   depc:	a2, original value saved on stack (PT_DEPC)
+ *   excsave_1:	a3
+ *
+ *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
+ *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
+ */
+
+#if XCHAL_HAVE_BE
+#define _EXTUI_MOVSP_SRC(ar)	extui ar, ar, 4, 4
+#define _EXTUI_MOVSP_DST(ar)	extui ar, ar, 0, 4
+#else
+#define _EXTUI_MOVSP_SRC(ar)	extui ar, ar, 0, 4
+#define _EXTUI_MOVSP_DST(ar)	extui ar, ar, 4, 4
+#endif
+
+ENTRY(fast_alloca)
+
+	/* We shouldn't be in a double exception. */
+
+	l32i	a0, a2, PT_DEPC
+	_bgeui	a0, VALID_DOUBLE_EXCEPTION_ADDRESS, .Lunhandled_double
+
+	rsr	a0, DEPC		# get a2
+	s32i	a4, a2, PT_AREG4	# save a4 and
+	s32i	a0, a2, PT_AREG2	# a2 to stack
+
+	/* Exit critical section. */
+
+	movi	a0, 0
+	s32i	a0, a3, EXC_TABLE_FIXUP
+
+	/* Restore a3, excsave_1 */
+
+	xsr	a3, EXCSAVE_1		# make sure excsave_1 is valid for dbl.
+	rsr	a4, EPC_1		# get exception address
+	s32i	a3, a2, PT_AREG3	# save a3 to stack
+
+#ifdef ALLOCA_EXCEPTION_IN_IRAM
+#error	iram not supported
+#else
+	/* Note: l8ui not allowed in IRAM/IROM!! */
+	l8ui	a0, a4, 1		# read as(src) from MOVSP instruction
+#endif
+	movi	a3, .Lmovsp_src
+	_EXTUI_MOVSP_SRC(a0)		# extract source register number
+	addx8	a3, a0, a3
+	jx	a3
+
+.Lunhandled_double:
+	wsr	a0, EXCSAVE_1
+	movi	a0, unrecoverable_exception
+	callx0	a0
+
+	.align 8
+.Lmovsp_src:
+	l32i	a3, a2, PT_AREG0;	_j 1f;	.align 8
+	mov	a3, a1;			_j 1f;	.align 8
+	l32i	a3, a2, PT_AREG2;	_j 1f;	.align 8
+	l32i	a3, a2, PT_AREG3;	_j 1f;	.align 8
+	l32i	a3, a2, PT_AREG4;	_j 1f;	.align 8
+	mov	a3, a5;			_j 1f;	.align 8
+	mov	a3, a6;			_j 1f;	.align 8
+	mov	a3, a7;			_j 1f;	.align 8
+	mov	a3, a8;			_j 1f;	.align 8
+	mov	a3, a9;			_j 1f;	.align 8
+	mov	a3, a10;		_j 1f;	.align 8
+	mov	a3, a11;		_j 1f;	.align 8
+	mov	a3, a12;		_j 1f;	.align 8
+	mov	a3, a13;		_j 1f;	.align 8
+	mov	a3, a14;		_j 1f;	.align 8
+	mov	a3, a15;		_j 1f;	.align 8
+
+1:
+
+#ifdef ALLOCA_EXCEPTION_IN_IRAM
+#error	iram not supported
+#else
+	l8ui	a0, a4, 0		# read ar(dst) from MOVSP instruction
+#endif
+	addi	a4, a4, 3		# step over movsp
+	_EXTUI_MOVSP_DST(a0)		# extract destination register
+	wsr	a4, EPC_1		# save new epc_1
+
+	_bnei	a0, 1, 1f		# no 'movsp a1, ax': jump
+
+        /* Move the save area. This implies the use of the L32E
+	 * and S32E instructions, because this move must be done with
+	 * the user's PS.RING privilege levels, not with ring 0
+	 * (kernel's) privileges currently active with PS.EXCM
+	 * set. Note that we have stil registered a fixup routine with the
+	 * double exception vector in case a double exception occurs.
+	 */
+
+	/* a0,a4:avail a1:old user stack a2:exc. stack a3:new user stack. */
+
+	l32e	a0, a1, -16
+	l32e	a4, a1, -12
+	s32e	a0, a3, -16
+	s32e	a4, a3, -12
+	l32e	a0, a1, -8
+	l32e	a4, a1, -4
+	s32e	a0, a3, -8
+	s32e	a4, a3, -4
+
+	/* Restore stack-pointer and all the other saved registers. */
+
+	mov	a1, a3
+
+	l32i	a4, a2, PT_AREG4
+	l32i	a3, a2, PT_AREG3
+	l32i	a0, a2, PT_AREG0
+	l32i	a2, a2, PT_AREG2
+	rfe
+
+	/*  MOVSP <at>,<as>  was invoked with <at> != a1.
+	 *  Because the stack pointer is not being modified,
+	 *  we should be able to just modify the pointer
+	 *  without moving any save area.
+	 *  The processor only traps these occurrences if the
+	 *  caller window isn't live, so unfortunately we can't
+	 *  use this as an alternate trap mechanism.
+	 *  So we just do the move.  This requires that we
+	 *  resolve the destination register, not just the source,
+	 *  so there's some extra work.
+	 *  (PERHAPS NOT REALLY NEEDED, BUT CLEANER...)
+	 */
+
+	/* a0 dst-reg, a1 user-stack, a2 stack, a3 value of src reg. */
+
+1:	movi	a4, .Lmovsp_dst
+	addx8	a4, a0, a4
+	jx	a4
+
+	.align 8
+.Lmovsp_dst:
+	s32i	a3, a2, PT_AREG0;	_j 1f;	.align 8
+	mov	a1, a3;			_j 1f;	.align 8
+	s32i	a3, a2, PT_AREG2;	_j 1f;	.align 8
+	s32i	a3, a2, PT_AREG3;	_j 1f;	.align 8
+	s32i	a3, a2, PT_AREG4;	_j 1f;	.align 8
+	mov	a5, a3;			_j 1f;	.align 8
+	mov	a6, a3;			_j 1f;	.align 8
+	mov	a7, a3;			_j 1f;	.align 8
+	mov	a8, a3;			_j 1f;	.align 8
+	mov	a9, a3;			_j 1f;	.align 8
+	mov	a10, a3;		_j 1f;	.align 8
+	mov	a11, a3;		_j 1f;	.align 8
+	mov	a12, a3;		_j 1f;	.align 8
+	mov	a13, a3;		_j 1f;	.align 8
+	mov	a14, a3;		_j 1f;	.align 8
+	mov	a15, a3;		_j 1f;	.align 8
+
+1:	l32i	a4, a2, PT_AREG4
+	l32i	a3, a2, PT_AREG3
+	l32i	a0, a2, PT_AREG0
+	l32i	a2, a2, PT_AREG2
+	rfe
+
+
+/*
+ * fast system calls.
+ *
+ * WARNING:  The kernel doesn't save the entire user context before
+ * handling a fast system call.  These functions are small and short,
+ * usually offering some functionality not available to user tasks.
+ *
+ * BE CAREFUL TO PRESERVE THE USER'S CONTEXT.
+ *
+ * Entry condition:
+ *
+ *   a0:	trashed, original value saved on stack (PT_AREG0)
+ *   a1:	a1
+ *   a2:	new stack pointer, original in DEPC
+ *   a3:	dispatch table
+ *   depc:	a2, original value saved on stack (PT_DEPC)
+ *   excsave_1:	a3
+ */
+
+ENTRY(fast_syscall_kernel)
+
+	/* Skip syscall. */
+
+	rsr	a0, EPC_1
+	addi	a0, a0, 3
+	wsr	a0, EPC_1
+
+	l32i	a0, a2, PT_DEPC
+	bgeui	a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_syscall_unrecoverable
+
+	rsr	a0, DEPC			# get syscall-nr
+	_beqz	a0, fast_syscall_spill_registers
+
+	addi	a0, a0, -__NR_sysxtensa
+	_beqz	a0, fast_syscall_sysxtensa
+
+	j	kernel_exception
+
+
+ENTRY(fast_syscall_user)
+
+	/* Skip syscall. */
+
+	rsr	a0, EPC_1
+	addi	a0, a0, 3
+	wsr	a0, EPC_1
+
+	l32i	a0, a2, PT_DEPC
+	bgeui	a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_syscall_unrecoverable
+
+	rsr	a0, DEPC			# get syscall-nr
+	_beqz	a0, fast_syscall_spill_registers
+
+	addi	a0, a0, -__NR_sysxtensa
+	_beqz	a0, fast_syscall_sysxtensa
+
+	j	user_exception
+
+ENTRY(fast_syscall_unrecoverable)
+
+        /* Restore all states. */
+
+        l32i    a0, a2, PT_AREG0        # restore a0
+        xsr     a2, DEPC                # restore a2, depc
+        rsr     a3, EXCSAVE_1
+
+        wsr     a0, EXCSAVE_1
+        movi    a0, unrecoverable_exception
+        callx0  a0
+
+
+
+/*
+ * sysxtensa syscall handler
+ *
+ * int sysxtensa (XTENSA_ATOMIC_SET, ptr, val, unused);
+ * int sysxtensa (XTENSA_ATOMIC_ADD, ptr, val, unused);
+ * int sysxtensa (XTENSA_ATOMIC_EXG_ADD, ptr, val, unused);
+ * int sysxtensa (XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval);
+ * a2                    a6              a3    a4      a5
+ *
+ * Entry condition:
+ *
+ *   a0:	trashed, original value saved on stack (PT_AREG0)
+ *   a1:	a1
+ *   a2:	new stack pointer, original in DEPC
+ *   a3:	dispatch table
+ *   depc:	a2, original value saved on stack (PT_DEPC)
+ *   excsave_1:	a3
+ *
+ *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
+ *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
+ *
+ * Note: we don't have to save a2; a2 holds the return value
+ *
+ * We use the two macros TRY and CATCH:
+ *
+ * TRY	 adds an entry to the __ex_table fixup table for the immediately
+ *	 following instruction.
+ *
+ * CATCH catches any exception that occurred at one of the preceeding TRY
+ *       statements and continues from there
+ *
+ * Usage TRY	l32i	a0, a1, 0
+ *		<other code>
+ *	 done:	rfe
+ *	 CATCH	<set return code>
+ *		j done
+ */
+
+#define TRY								\
+	.section __ex_table, "a";					\
+	.word	66f, 67f;						\
+	.text;								\
+66:
+
+#define CATCH								\
+67:
+
+ENTRY(fast_syscall_sysxtensa)
+
+	_beqz	a6, 1f
+	_blti	a6, SYSXTENSA_COUNT, 2f
+
+1:	j	user_exception
+
+2:	xsr	a3, EXCSAVE_1		# restore a3, excsave1
+	s32i	a7, a2, PT_AREG7
+
+	movi	a7, 4			# sizeof(unsigned int)
+	verify_area a3, a7, a0, a2, .Leac
+
+	_beqi	a6, SYSXTENSA_ATOMIC_SET, .Lset
+	_beqi	a6, SYSXTENSA_ATOMIC_EXG_ADD, .Lexg
+	_beqi	a6, SYSXTENSA_ATOMIC_ADD, .Ladd
+
+	/* Fall through for SYSXTENSA_ATOMIC_CMP_SWP */
+
+.Lswp:	/* Atomic compare and swap */
+
+TRY	l32i	a7, a3, 0		# read old value
+	bne	a7, a4, 1f		# same as old value? jump
+	s32i	a5, a3, 0		# different, modify value
+	movi	a7, 1			# and return 1
+	j	.Lret
+
+1:	movi	a7, 0			# same values: return 0
+	j	.Lret
+
+.Ladd:	/* Atomic add */
+.Lexg:	/* Atomic (exchange) add */
+
+TRY	l32i	a7, a3, 0
+	add	a4, a4, a7
+	s32i	a4, a3, 0
+	j	.Lret
+
+.Lset:	/* Atomic set */
+
+TRY	l32i	a7, a3, 0		# read old value as return value
+	s32i	a4, a3, 0		# write new value
+
+.Lret:	mov	a0, a2
+	mov	a2, a7
+	l32i	a7, a0, PT_AREG7
+	l32i	a3, a0, PT_AREG3
+	l32i	a0, a0, PT_AREG0
+	rfe
+
+CATCH
+.Leac:	movi	a7, -EFAULT
+	j	.Lret
+
+
+
+/* fast_syscall_spill_registers.
+ *
+ * Entry condition:
+ *
+ *   a0:	trashed, original value saved on stack (PT_AREG0)
+ *   a1:	a1
+ *   a2:	new stack pointer, original in DEPC
+ *   a3:	dispatch table
+ *   depc:	a2, original value saved on stack (PT_DEPC)
+ *   excsave_1:	a3
+ *
+ * Note: We assume the stack pointer is EXC_TABLE_KSTK in the fixup handler.
+ * Note: We don't need to save a2 in depc (return value)
+ */
+
+ENTRY(fast_syscall_spill_registers)
+
+	/* Register a FIXUP handler (pass current wb as a parameter) */
+
+	movi	a0, fast_syscall_spill_registers_fixup
+	s32i	a0, a3, EXC_TABLE_FIXUP
+	rsr	a0, WINDOWBASE
+	s32i	a0, a3, EXC_TABLE_PARAM
+
+	/* Save a3 and SAR on stack. */
+
+	rsr	a0, SAR
+	xsr	a3, EXCSAVE_1		# restore a3 and excsave_1
+	s32i	a0, a2, PT_AREG4	# store SAR to PT_AREG4
+	s32i	a3, a2, PT_AREG3
+
+	/* The spill routine might clobber a7, a11, and a15. */
+
+	s32i	a7, a2, PT_AREG5
+	s32i	a11, a2, PT_AREG6
+	s32i	a15, a2, PT_AREG7
+
+	call0	_spill_registers	# destroys a3, DEPC, and SAR
+
+	/* Advance PC, restore registers and SAR, and return from exception. */
+
+	l32i	a3, a2, PT_AREG4
+	l32i	a0, a2, PT_AREG0
+	wsr	a3, SAR
+	l32i	a3, a2, PT_AREG3
+
+	/* Restore clobbered registers. */
+
+	l32i	a7, a2, PT_AREG5
+	l32i	a11, a2, PT_AREG6
+	l32i	a15, a2, PT_AREG7
+
+	movi	a2, 0
+	rfe
+
+/* Fixup handler.
+ *
+ * We get here if the spill routine causes an exception, e.g. tlb miss.
+ * We basically restore WINDOWBASE and WINDOWSTART to the condition when
+ * we entered the spill routine and jump to the user exception handler.
+ *
+ * a0: value of depc, original value in depc
+ * a2: trashed, original value in EXC_TABLE_DOUBLE_SAVE
+ * a3: exctable, original value in excsave1
+ */
+
+fast_syscall_spill_registers_fixup:
+
+	rsr	a2, WINDOWBASE	# get current windowbase (a2 is saved)
+	xsr	a0, DEPC	# restore depc and a0
+	ssl	a2		# set shift (32 - WB)
+
+	/* We need to make sure the current registers (a0-a3) are preserved.
+	 * To do this, we simply set the bit for the current window frame
+	 * in WS, so that the exception handlers save them to the task stack.
+	 */
+
+	rsr	a3, EXCSAVE_1	# get spill-mask
+	slli	a2, a3, 1	# shift left by one
+
+	slli	a3, a2, 32-WSBITS
+	src	a2, a2, a3	# a1 = xxwww1yyxxxwww1yy......
+	wsr	a2, WINDOWSTART	# set corrected windowstart
+
+	movi	a3, exc_table
+	l32i	a2, a3, EXC_TABLE_DOUBLE_SAVE	# restore a2
+	l32i	a3, a3, EXC_TABLE_PARAM	# original WB (in user task)
+
+	/* Return to the original (user task) WINDOWBASE.
+	 * We leave the following frame behind:
+	 * a0, a1, a2	same
+	 * a3:		trashed (saved in excsave_1)
+	 * depc:	depc (we have to return to that address)
+	 * excsave_1:	a3
+	 */
+
+	wsr	a3, WINDOWBASE
+	rsync
+
+	/* We are now in the original frame when we entered _spill_registers:
+	 *  a0: return address
+	 *  a1: used, stack pointer
+	 *  a2: kernel stack pointer
+	 *  a3: available, saved in EXCSAVE_1
+	 *  depc: exception address
+	 *  excsave: a3
+	 * Note: This frame might be the same as above.
+	 */
+
+#ifdef SIGNAL_HANDLING_IN_DOUBLE_EXCEPTION
+	/* Restore registers we precautiously saved.
+	 * We have the value of the 'right' a3
+	 */
+
+	l32i	a7, a2, PT_AREG5
+	l32i	a11, a2, PT_AREG6
+	l32i	a15, a2, PT_AREG7
+#endif
+
+	/* Setup stack pointer. */
+
+	addi	a2, a2, -PT_USER_SIZE
+	s32i	a0, a2, PT_AREG0
+
+	/* Make sure we return to this fixup handler. */
+
+	movi	a3, fast_syscall_spill_registers_fixup_return
+	s32i	a3, a2, PT_DEPC		# setup depc
+
+	/* Jump to the exception handler. */
+
+	movi	a3, exc_table
+	rsr	a0, EXCCAUSE
+        addx4   a0, a0, a3              	# find entry in table
+        l32i    a0, a0, EXC_TABLE_FAST_USER     # load handler
+        jx      a0
+
+fast_syscall_spill_registers_fixup_return:
+
+	/* When we return here, all registers have been restored (a2: DEPC) */
+
+	wsr	a2, DEPC		# exception address
+
+	/* Restore fixup handler. */
+
+	xsr	a3, EXCSAVE_1
+	movi	a2, fast_syscall_spill_registers_fixup
+	s32i	a2, a3, EXC_TABLE_FIXUP
+	rsr	a2, WINDOWBASE
+	s32i	a2, a3, EXC_TABLE_PARAM
+	l32i	a2, a3, EXC_TABLE_KSTK
+
+#ifdef SIGNAL_HANDLING_IN_DOUBLE_EXCEPTION
+	/* Save registers again that might be clobbered. */
+
+	s32i	a7, a2, PT_AREG5
+	s32i	a11, a2, PT_AREG6
+	s32i	a15, a2, PT_AREG7
+#endif
+
+	/* Load WB at the time the exception occurred. */
+
+	rsr	a3, SAR			# WB is still in SAR
+	neg	a3, a3
+	wsr	a3, WINDOWBASE
+	rsync
+
+	/* Restore a3 and return. */
+
+	movi	a3, exc_table
+	xsr	a3, EXCSAVE_1
+
+	rfde
+
+
+/*
+ * spill all registers.
+ *
+ * This is not a real function. The following conditions must be met:
+ *
+ *  - must be called with call0.
+ *  - uses DEPC, a3 and SAR.
+ *  - the last 'valid' register of each frame are clobbered.
+ *  - the caller must have registered a fixup handler
+ *    (or be inside a critical section)
+ *  - PS_EXCM must be set (PS_WOE cleared?)
+ */
+
+ENTRY(_spill_registers)
+
+	/*
+	 * Rotate ws so that the current windowbase is at bit 0.
+	 * Assume ws = xxxwww1yy (www1 current window frame).
+	 * Rotate ws right so that a2 = yyxxxwww1.
+	 */
+
+	wsr	a2, DEPC		# preserve a2
+	rsr	a2, WINDOWBASE
+	rsr	a3, WINDOWSTART
+	ssr	a2			# holds WB
+	slli	a2, a3, WSBITS
+	or	a3, a3, a2		# a2 = xxxwww1yyxxxwww1yy
+	srl	a3, a3
+
+	/* We are done if there are no more than the current register frame. */
+
+	extui	a3, a3, 1, WSBITS-2	# a3 = 0yyxxxwww
+	movi	a2, (1 << (WSBITS-1))
+	_beqz	a3, .Lnospill		# only one active frame? jump
+
+	/* We want 1 at the top, so that we return to the current windowbase */
+
+	or	a3, a3, a2		# 1yyxxxwww
+
+	/* Skip empty frames - get 'oldest' WINDOWSTART-bit. */
+
+	wsr	a3, WINDOWSTART		# save shifted windowstart
+	neg	a2, a3
+	and	a3, a2, a3		# first bit set from right: 000010000
+
+	ffs_ws	a2, a3			# a2: shifts to skip empty frames
+	movi	a3, WSBITS
+	sub	a2, a3, a2		# WSBITS-a2:number of 0-bits from right
+	ssr	a2			# save in SAR for later.
+
+	rsr	a3, WINDOWBASE
+	add	a3, a3, a2
+	rsr	a2, DEPC		# restore a2
+	wsr	a3, WINDOWBASE
+	rsync
+
+	rsr	a3, WINDOWSTART
+	srl	a3, a3			# shift windowstart
+
+	/* WB is now just one frame below the oldest frame in the register
+	   window. WS is shifted so the oldest frame is in bit 0, thus, WB
+	   and WS differ by one 4-register frame. */
+
+	/* Save frames. Depending what call was used (call4, call8, call12),
+	 * we have to save 4,8. or 12 registers.
+	 */
+
+	_bbsi.l	a3, 1, .Lc4
+	_bbsi.l	a3, 2, .Lc8
+
+	/* Special case: we have a call12-frame starting at a4. */
+
+	_bbci.l	a3, 3, .Lc12	# bit 3 shouldn't be zero! (Jump to Lc12 first)
+
+	s32e	a4, a1, -16	# a1 is valid with an empty spill area
+	l32e	a4, a5, -12
+	s32e	a8, a4, -48
+	mov	a8, a4
+	l32e	a4, a1, -16
+	j	.Lc12c
+
+.Lloop: _bbsi.l	a3, 1, .Lc4
+	_bbci.l	a3, 2, .Lc12
+
+.Lc8:	s32e	a4, a13, -16
+	l32e	a4, a5, -12
+	s32e	a8, a4, -32
+	s32e	a5, a13, -12
+	s32e	a6, a13, -8
+	s32e	a7, a13, -4
+	s32e	a9, a4, -28
+	s32e	a10, a4, -24
+	s32e	a11, a4, -20
+
+	srli	a11, a3, 2		# shift windowbase by 2
+	rotw	2
+	_bnei	a3, 1, .Lloop
+
+.Lexit: /* Done. Do the final rotation, set WS, and return. */
+
+	rotw	1
+	rsr	a3, WINDOWBASE
+	ssl	a3
+	movi	a3, 1
+	sll	a3, a3
+	wsr	a3, WINDOWSTART
+
+.Lnospill:
+	jx	a0
+
+.Lc4:	s32e	a4, a9, -16
+	s32e	a5, a9, -12
+	s32e	a6, a9, -8
+	s32e	a7, a9, -4
+
+	srli	a7, a3, 1
+	rotw	1
+	_bnei	a3, 1, .Lloop
+	j	.Lexit
+
+.Lc12:	_bbci.l	a3, 3, .Linvalid_mask	# bit 2 shouldn't be zero!
+
+	/* 12-register frame (call12) */
+
+	l32e	a2, a5, -12
+	s32e	a8, a2, -48
+	mov	a8, a2
+
+.Lc12c: s32e	a9, a8, -44
+	s32e	a10, a8, -40
+	s32e	a11, a8, -36
+	s32e	a12, a8, -32
+	s32e	a13, a8, -28
+	s32e	a14, a8, -24
+	s32e	a15, a8, -20
+	srli	a15, a3, 3
+
+	/* The stack pointer for a4..a7 is out of reach, so we rotate the
+	 * window, grab the stackpointer, and rotate back.
+	 * Alternatively, we could also use the following approach, but that
+	 * makes the fixup routine much more complicated:
+	 * rotw	1
+	 * s32e	a0, a13, -16
+	 * ...
+	 * rotw 2
+	 */
+
+	rotw	1
+	mov	a5, a13
+	rotw	-1
+
+	s32e	a4, a9, -16
+	s32e	a5, a9, -12
+	s32e	a6, a9, -8
+	s32e	a7, a9, -4
+
+	rotw	3
+
+	_beqi	a3, 1, .Lexit
+	j	.Lloop
+
+.Linvalid_mask:
+
+	/* We get here because of an unrecoverable error in the window
+	 * registers. If we are in user space, we kill the application,
+	 * however, this condition is unrecoverable in kernel space.
+	 */
+
+	rsr	a0, PS
+	_bbci.l	a0, PS_UM_SHIFT, 1f
+
+ 	/* User space: Setup a dummy frame and kill application.
+	 * Note: We assume EXC_TABLE_KSTK contains a valid stack pointer.
+	 */
+
+	movi	a0, 1
+	movi	a1, 0
+
+	wsr	a0, WINDOWSTART
+	wsr	a1, WINDOWBASE
+	rsync
+
+	movi	a0, 0
+
+	movi	a3, exc_table
+	l32i	a1, a3, EXC_TABLE_KSTK
+	wsr	a3, EXCSAVE_1
+
+	movi	a4, PS_WOE_MASK | 1
+	wsr	a4, PS
+	rsync
+
+	movi	a6, SIGSEGV
+	movi	a4, do_exit
+	callx4	a4
+
+1:	/* Kernel space: PANIC! */
+
+	wsr	a0, EXCSAVE_1
+	movi	a0, unrecoverable_exception
+	callx0	a0		# should not return
+1:	j	1b
+
+/*
+ * We should never get here. Bail out!
+ */
+
+ENTRY(fast_second_level_miss_double_kernel)
+
+1:	movi	a0, unrecoverable_exception
+	callx0	a0		# should not return
+1:	j	1b
+
+/* First-level entry handler for user, kernel, and double 2nd-level
+ * TLB miss exceptions.  Note that for now, user and kernel miss
+ * exceptions share the same entry point and are handled identically.
+ *
+ * An old, less-efficient C version of this function used to exist.
+ * We include it below, interleaved as comments, for reference.
+ *
+ * Entry condition:
+ *
+ *   a0:	trashed, original value saved on stack (PT_AREG0)
+ *   a1:	a1
+ *   a2:	new stack pointer, original in DEPC
+ *   a3:	dispatch table
+ *   depc:	a2, original value saved on stack (PT_DEPC)
+ *   excsave_1:	a3
+ *
+ *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
+ *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
+ */
+
+ENTRY(fast_second_level_miss)
+
+	/* Save a1. Note: we don't expect a double exception. */
+
+	s32i	a1, a2, PT_AREG1
+
+	/* We need to map the page of PTEs for the user task.  Find
+	 * the pointer to that page.  Also, it's possible for tsk->mm
+	 * to be NULL while tsk->active_mm is nonzero if we faulted on
+	 * a vmalloc address.  In that rare case, we must use
+	 * active_mm instead to avoid a fault in this handler.  See
+	 *
+	 * http://mail.nl.linux.org/linux-mm/2002-08/msg00258.html
+	 *   (or search Internet on "mm vs. active_mm")
+	 *
+	 *	if (!mm)
+	 *		mm = tsk->active_mm;
+	 *	pgd = pgd_offset (mm, regs->excvaddr);
+	 *	pmd = pmd_offset (pgd, regs->excvaddr);
+	 *	pmdval = *pmd;
+	 */
+
+	GET_CURRENT(a1,a2)
+	l32i	a0, a1, TASK_MM		# tsk->mm
+	beqz	a0, 9f
+
+8:	rsr	a1, EXCVADDR		# fault address
+	_PGD_OFFSET(a0, a1, a1)
+	l32i	a0, a0, 0		# read pmdval
+	//beqi	a0, _PAGE_USER, 2f
+	beqz	a0, 2f
+
+	/* Read ptevaddr and convert to top of page-table page.
+	 *
+	 * 	vpnval = read_ptevaddr_register() & PAGE_MASK;
+	 * 	vpnval += DTLB_WAY_PGTABLE;
+	 *	pteval = mk_pte (virt_to_page(pmd_val(pmdval)), PAGE_KERNEL);
+	 *	write_dtlb_entry (pteval, vpnval);
+	 *
+	 * The messy computation for 'pteval' above really simplifies
+	 * into the following:
+	 *
+	 * pteval = ((pmdval - PAGE_OFFSET) & PAGE_MASK) | PAGE_KERNEL
+	 */
+
+	movi	a1, -PAGE_OFFSET
+	add	a0, a0, a1		# pmdval - PAGE_OFFSET
+	extui	a1, a0, 0, PAGE_SHIFT	# ... & PAGE_MASK
+	xor	a0, a0, a1
+
+
+	movi	a1, PAGE_DIRECTORY
+	or	a0, a0, a1		# ... | PAGE_DIRECTORY
+
+	rsr	a1, PTEVADDR
+	srli	a1, a1, PAGE_SHIFT
+	slli	a1, a1, PAGE_SHIFT	# ptevaddr & PAGE_MASK
+	addi	a1, a1, DTLB_WAY_PGTABLE	# ... + way_number
+
+	wdtlb	a0, a1
+	dsync
+
+	/* Exit critical section. */
+
+	movi	a0, 0
+	s32i	a0, a3, EXC_TABLE_FIXUP
+
+	/* Restore the working registers, and return. */
+
+	l32i	a0, a2, PT_AREG0
+	l32i	a1, a2, PT_AREG1
+	l32i	a2, a2, PT_DEPC
+	xsr	a3, EXCSAVE_1
+
+	bgeui	a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
+
+	/* Restore excsave1 and return. */
+
+	rsr	a2, DEPC
+	rfe
+
+	/* Return from double exception. */
+
+1:	xsr	a2, DEPC
+	esync
+	rfde
+
+9:	l32i	a0, a1, TASK_ACTIVE_MM	# unlikely case mm == 0
+	j	8b
+
+2:	/* Invalid PGD, default exception handling */
+
+	rsr	a1, DEPC
+	xsr	a3, EXCSAVE_1
+	s32i	a1, a2, PT_AREG2
+	s32i	a3, a2, PT_AREG3
+	mov	a1, a2
+
+	rsr	a2, PS
+	bbsi.l	a2, PS_UM_SHIFT, 1f
+	j	_kernel_exception
+1:	j	_user_exception
+
+
+/*
+ * StoreProhibitedException
+ *
+ * Update the pte and invalidate the itlb mapping for this pte.
+ *
+ * Entry condition:
+ *
+ *   a0:	trashed, original value saved on stack (PT_AREG0)
+ *   a1:	a1
+ *   a2:	new stack pointer, original in DEPC
+ *   a3:	dispatch table
+ *   depc:	a2, original value saved on stack (PT_DEPC)
+ *   excsave_1:	a3
+ *
+ *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
+ *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
+ */
+
+ENTRY(fast_store_prohibited)
+
+	/* Save a1 and a4. */
+
+	s32i	a1, a2, PT_AREG1
+	s32i	a4, a2, PT_AREG4
+
+	GET_CURRENT(a1,a2)
+	l32i	a0, a1, TASK_MM		# tsk->mm
+	beqz	a0, 9f
+
+8:	rsr	a1, EXCVADDR		# fault address
+	_PGD_OFFSET(a0, a1, a4)
+	l32i	a0, a0, 0
+	//beqi	a0, _PAGE_USER, 2f	# FIXME use _PAGE_INVALID
+	beqz	a0, 2f
+
+	_PTE_OFFSET(a0, a1, a4)
+	l32i	a4, a0, 0		# read pteval
+	movi	a1, _PAGE_VALID | _PAGE_RW
+	bnall	a4, a1, 2f
+
+	movi	a1, _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_WRENABLE
+	or	a4, a4, a1
+	rsr	a1, EXCVADDR
+	s32i	a4, a0, 0
+
+	/* We need to flush the cache if we have page coloring. */
+#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
+	dhwb	a0, 0
+#endif
+	pdtlb	a0, a1
+	beqz	a0, 1f
+	idtlb	a0		// FIXME do we need this?
+	wdtlb	a4, a0
+1:
+
+	/* Exit critical section. */
+
+	movi	a0, 0
+	s32i	a0, a3, EXC_TABLE_FIXUP
+
+	/* Restore the working registers, and return. */
+
+	l32i	a4, a2, PT_AREG4
+	l32i	a1, a2, PT_AREG1
+	l32i	a0, a2, PT_AREG0
+	l32i	a2, a2, PT_DEPC
+
+	/* Restore excsave1 and a3. */
+
+	xsr	a3, EXCSAVE_1
+	bgeui	a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
+
+	rsr	a2, DEPC
+	rfe
+
+	/* Double exception. Restore FIXUP handler and return. */
+
+1:	xsr	a2, DEPC
+	esync
+	rfde
+
+9:	l32i	a0, a1, TASK_ACTIVE_MM	# unlikely case mm == 0
+	j	8b
+
+2:	/* If there was a problem, handle fault in C */
+
+	rsr	a4, DEPC	# still holds a2
+	xsr	a3, EXCSAVE_1
+	s32i	a4, a2, PT_AREG2
+	s32i	a3, a2, PT_AREG3
+	l32i	a4, a2, PT_AREG4
+	mov	a1, a2
+
+	rsr	a2, PS
+	bbsi.l	a2, PS_UM_SHIFT, 1f
+	j	_kernel_exception
+1:	j	_user_exception
+
+
+#if XCHAL_EXTRA_SA_SIZE
+
+#warning fast_coprocessor untested
+
+/*
+ * Entry condition:
+ *
+ *   a0:	trashed, original value saved on stack (PT_AREG0)
+ *   a1:	a1
+ *   a2:	new stack pointer, original in DEPC
+ *   a3:	dispatch table
+ *   depc:	a2, original value saved on stack (PT_DEPC)
+ *   excsave_1:	a3
+ *
+ *   PT_DEPC >= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception, DEPC
+ *	     <  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
+ */
+
+ENTRY(fast_coprocessor_double)
+	wsr	a0, EXCSAVE_1
+	movi	a0, unrecoverable_exception
+	callx0	a0
+
+ENTRY(fast_coprocessor)
+
+	/* Fatal if we are in a double exception. */
+
+	l32i	a0, a2, PT_DEPC
+	_bgeui	a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_coprocessor_double
+
+	/* Save some registers a1, a3, a4, SAR */
+
+	xsr	a3, EXCSAVE_1
+	s32i	a3, a2, PT_AREG3
+	rsr	a3, SAR
+	s32i	a4, a2, PT_AREG4
+	s32i	a1, a2, PT_AREG1
+	s32i	a5, a1, PT_AREG5
+	s32i	a3, a2, PT_SAR
+	mov	a1, a2
+
+	/* Currently, the HAL macros only guarantee saving a0 and a1.
+	 * These can and will be refined in the future, but for now,
+	 * just save the remaining registers of a2...a15.
+	 */
+	s32i	a6, a1, PT_AREG6
+	s32i	a7, a1, PT_AREG7
+	s32i	a8, a1, PT_AREG8
+	s32i	a9, a1, PT_AREG9
+	s32i	a10, a1, PT_AREG10
+	s32i	a11, a1, PT_AREG11
+	s32i	a12, a1, PT_AREG12
+	s32i	a13, a1, PT_AREG13
+	s32i	a14, a1, PT_AREG14
+	s32i	a15, a1, PT_AREG15
+
+	/* Find coprocessor number. Subtract first CP EXCCAUSE from EXCCAUSE */
+
+	rsr	a0, EXCCAUSE
+	addi	a3, a0, -XCHAL_EXCCAUSE_COPROCESSOR0_DISABLED
+
+	/* Set corresponding CPENABLE bit */
+
+	movi	a4, 1
+	ssl	a3			# SAR: 32 - coprocessor_number
+	rsr	a5, CPENABLE
+	sll	a4, a4
+	or	a4, a5, a4
+	wsr	a4, CPENABLE
+	rsync
+	movi	a5, coprocessor_info	# list of owner and offset into cp_save
+	addx8	a0, a4, a5		# entry for CP
+
+	bne	a4, a5, .Lload		# bit wasn't set before, cp not in use
+
+	/* Now compare the current task with the owner of the coprocessor.
+	 * If they are the same, there is no reason to save or restore any
+	 * coprocessor state. Having already enabled the coprocessor,
+	 * branch ahead to return.
+	 */
+	GET_CURRENT(a5,a1)
+	l32i	a4, a0, COPROCESSOR_INFO_OWNER	# a4: current owner for this CP
+	beq	a4, a5, .Ldone
+
+	/* Find location to dump current coprocessor state:
+	 *  task_struct->task_cp_save_offset + coprocessor_offset[coprocessor]
+	 *
+	 * Note: a0 pointer to the entry in the coprocessor owner table,
+	 *	 a3 coprocessor number,
+         *	 a4 current owner of coprocessor.
+	 */
+	l32i	a5, a0, COPROCESSOR_INFO_OFFSET
+	addi	a2, a4, THREAD_CP_SAVE
+	add	a2, a2, a5
+
+	/* Store current coprocessor states. (a5 still has CP number) */
+
+	xchal_cpi_store_funcbody
+
+	/* The macro might have destroyed a3 (coprocessor number), but
+	 * SAR still has 32 - coprocessor_number!
+	 */
+	movi	a3, 32
+	rsr	a4, SAR
+	sub	a3, a3, a4
+
+.Lload:	/* A new task now owns the corpocessors. Save its TCB pointer into
+	 * the coprocessor owner table.
+	 *
+	 * Note: a0 pointer to the entry in the coprocessor owner table,
+	 *	 a3 coprocessor number.
+	 */
+	GET_CURRENT(a4,a1)
+	s32i	a4, a0, 0
+
+	/* Find location from where to restore the current coprocessor state.*/
+
+	l32i	a5, a0, COPROCESSOR_INFO_OFFSET
+	addi	a2, a4, THREAD_CP_SAVE
+	add	a2, a2, a4
+
+	xchal_cpi_load_funcbody
+
+	/* We must assume that the xchal_cpi_store_funcbody macro destroyed
+	 * registers a2..a15.
+	 */
+
+.Ldone:	l32i	a15, a1, PT_AREG15
+	l32i	a14, a1, PT_AREG14
+	l32i	a13, a1, PT_AREG13
+	l32i	a12, a1, PT_AREG12
+	l32i	a11, a1, PT_AREG11
+	l32i	a10, a1, PT_AREG10
+	l32i	a9, a1, PT_AREG9
+	l32i	a8, a1, PT_AREG8
+	l32i	a7, a1, PT_AREG7
+	l32i	a6, a1, PT_AREG6
+	l32i	a5, a1, PT_AREG5
+	l32i	a4, a1, PT_AREG4
+	l32i	a3, a1, PT_AREG3
+	l32i	a2, a1, PT_AREG2
+	l32i	a0, a1, PT_AREG0
+	l32i	a1, a1, PT_AREG1
+
+	rfe
+
+#endif /* XCHAL_EXTRA_SA_SIZE */
+
+/*
+ * Task switch.
+ *
+ * struct task*  _switch_to (struct task* prev, struct task* next)
+ *         a2                              a2                 a3
+ */
+
+ENTRY(_switch_to)
+
+	entry	a1, 16
+
+	mov	a4, a3			# preserve a3
+
+	s32i	a0, a2, THREAD_RA	# save return address
+	s32i	a1, a2, THREAD_SP	# save stack pointer
+
+	/* Disable ints while we manipulate the stack pointer; spill regs. */
+
+	movi	a5, PS_EXCM_MASK | LOCKLEVEL
+	xsr	a5, PS
+	rsr	a3, EXCSAVE_1
+	rsync
+	s32i	a3, a3, EXC_TABLE_FIXUP	/* enter critical section */
+
+	call0	_spill_registers
+
+	/* Set kernel stack (and leave critical section)
+	 * Note: It's save to set it here. The stack will not be overwritten
+	 *       because the kernel stack will only be loaded again after
+	 *       we return from kernel space.
+	 */
+
+	l32i	a0, a4, TASK_THREAD_INFO
+	rsr	a3, EXCSAVE_1		# exc_table
+	movi	a1, 0
+	addi	a0, a0, PT_REGS_OFFSET
+	s32i	a1, a3, EXC_TABLE_FIXUP
+	s32i	a0, a3, EXC_TABLE_KSTK
+
+	/* restore context of the task that 'next' addresses */
+
+	l32i	a0, a4, THREAD_RA	/* restore return address */
+	l32i	a1, a4, THREAD_SP	/* restore stack pointer */
+
+	wsr	a5, PS
+	rsync
+
+	retw
+
+
+ENTRY(ret_from_fork)
+
+	/* void schedule_tail (struct task_struct *prev)
+	 * Note: prev is still in a6 (return value from fake call4 frame)
+	 */
+	movi	a4, schedule_tail
+	callx4	a4
+
+	movi	a4, do_syscall_trace
+	callx4	a4
+
+	j	common_exception_return
+
+
+
+/*
+ * Table of syscalls
+ */
+
+.data
+.align  4
+.global sys_call_table
+sys_call_table:
+
+#define SYSCALL(call, narg) .word call
+#include "syscalls.h"
+
+/*
+ * Number of arguments of each syscall
+ */
+
+.global sys_narg_table
+sys_narg_table:
+
+#undef SYSCALL
+#define SYSCALL(call, narg) .byte narg
+#include "syscalls.h"
+
diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S
new file mode 100644
index 0000000..6e9b522
--- /dev/null
+++ b/arch/xtensa/kernel/head.S
@@ -0,0 +1,237 @@
+/*
+ * arch/xtensa/kernel/head.S
+ *
+ * Xtensa Processor startup code.
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca>
+ * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
+ * Kevin Chea
+ */
+
+#include <xtensa/cacheasm.h>
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+
+/*
+ * This module contains the entry code for kernel images. It performs the
+ * minimal setup needed to call the generic C routines.
+ *
+ * Prerequisites:
+ *
+ * - The kernel image has been loaded to the actual address where it was
+ *   compiled to.
+ * - a2 contains either 0 or a pointer to a list of boot parameters.
+ *   (see setup.c for more details)
+ *
+ */
+
+	.macro	iterate	from, to , cmd
+		.ifeq	((\to - \from) & ~0xfff)
+			\cmd	\from
+			iterate "(\from+1)", \to, \cmd
+		.endif
+	.endm
+
+/*
+ *  _start
+ *
+ *  The bootloader passes a pointer to a list of boot parameters in a2.
+ */
+
+	/* The first bytes of the kernel image must be an instruction, so we
+	 * manually allocate and define the literal constant we need for a jx
+	 * instruction.
+	 */
+
+	.section .head.text, "ax"
+	.globl _start
+_start:	_j	2f
+	.align	4
+1:	.word	_startup
+2:	l32r	a0, 1b
+	jx	a0
+
+	.text
+	.align 4
+_startup:
+
+	/* Disable interrupts and exceptions. */
+
+	movi	a0, XCHAL_PS_EXCM_MASK
+	wsr	a0, PS
+
+	/* Preserve the pointer to the boot parameter list in EXCSAVE_1 */
+
+	wsr	a2, EXCSAVE_1
+
+	/* Start with a fresh windowbase and windowstart.  */
+
+	movi	a1, 1
+	movi	a0, 0
+	wsr	a1, WINDOWSTART
+	wsr	a0, WINDOWBASE
+	rsync
+
+	/* Set a0 to 0 for the remaining initialization. */
+
+	movi	a0, 0
+
+	/* Clear debugging registers. */
+
+#if XCHAL_HAVE_DEBUG
+	wsr	a0, IBREAKENABLE
+	wsr	a0, ICOUNT
+	movi	a1, 15
+	wsr	a0, ICOUNTLEVEL
+
+	.macro reset_dbreak num
+	wsr	a0, DBREAKC + \num
+	.endm
+
+        iterate 0, XCHAL_NUM_IBREAK-1, reset_dbreak
+#endif
+
+	/* Clear CCOUNT (not really necessary, but nice) */
+
+	wsr	a0, CCOUNT	# not really necessary, but nice
+
+	/* Disable zero-loops. */
+
+#if XCHAL_HAVE_LOOPS
+	wsr	a0, LCOUNT
+#endif
+
+	/* Disable all timers. */
+
+	.macro	reset_timer	num
+	wsr	a0, CCOMPARE_0 + \num
+	.endm
+	iterate	0, XCHAL_NUM_TIMERS-1, reset_timer
+
+	/* Interrupt initialization. */
+
+	movi	a2, XCHAL_INTTYPE_MASK_SOFTWARE | XCHAL_INTTYPE_MASK_EXTERN_EDGE
+	wsr	a0, INTENABLE
+	wsr	a2, INTCLEAR
+
+	/* Disable coprocessors. */
+
+#if XCHAL_CP_NUM > 0
+	wsr	a0, CPENABLE
+#endif
+
+	/* Set PS.INTLEVEL=1, PS.WOE=0, kernel stack, PS.EXCM=0
+	 *
+	 * Note: PS.EXCM must be cleared before using any loop
+	 *	 instructions; otherwise, they are silently disabled, and
+	 * 	 at most one iteration of the loop is executed.
+	 */
+
+	movi	a1, 1
+	wsr	a1, PS
+	rsync
+
+	/*  Initialize the caches.
+	 *  Does not include flushing writeback d-cache.
+	 *  a6, a7 are just working registers (clobbered).
+	 */
+
+	icache_reset  a2, a3
+	dcache_reset  a2, a3
+
+	/* Unpack data sections
+	 *
+	 * The linker script used to build the Linux kernel image
+	 * creates a table located at __boot_reloc_table_start
+	 * that contans the information what data needs to be unpacked.
+	 *
+	 * Uses a2-a7.
+	 */
+
+	movi	a2, __boot_reloc_table_start
+	movi	a3, __boot_reloc_table_end
+
+1:	beq	a2, a3, 3f	# no more entries?
+	l32i	a4, a2, 0	# start destination (in RAM)
+	l32i	a5, a2, 4	# end desination (in RAM)
+	l32i	a6, a2, 8	# start source (in ROM)
+	addi	a2, a2, 12	# next entry
+	beq	a4, a5, 1b	# skip, empty entry
+	beq	a4, a6, 1b	# skip, source and dest. are the same
+
+2:	l32i	a7, a6, 0	# load word
+	addi	a6, a6, 4
+	s32i	a7, a4, 0	# store word
+	addi	a4, a4, 4
+	bltu	a4, a5, 2b
+	j	1b
+
+3:
+	/* All code and initialized data segments have been copied.
+	 * Now clear the BSS segment.
+	 */
+
+	movi	a2, _bss_start	# start of BSS
+	movi	a3, _bss_end	# end of BSS
+
+1:	addi	a2, a2, 4
+	s32i	a0, a2, 0
+	blt	a2, a3, 1b
+
+#if XCHAL_DCACHE_IS_WRITEBACK
+
+	/* After unpacking, flush the writeback cache to memory so the
+	 * instructions/data are available.
+	 */
+
+	dcache_writeback_all	a2, a3
+#endif
+
+	/* Setup stack and enable window exceptions (keep irqs disabled) */
+
+	movi	a1, init_thread_union
+	addi	a1, a1, KERNEL_STACK_SIZE
+
+	movi	a2, 0x00040001		# WOE=1, INTLEVEL=1, UM=0
+	wsr	a2, PS			# (enable reg-windows; progmode stack)
+	rsync
+
+	/* Set up EXCSAVE[DEBUGLEVEL] to point to the Debug Exception Handler.*/
+
+	movi	a2, debug_exception
+	wsr	a2, EXCSAVE + XCHAL_DEBUGLEVEL
+
+	/* Set up EXCSAVE[1] to point to the exc_table. */
+
+	movi	a6, exc_table
+	xsr	a6, EXCSAVE_1
+
+	/* init_arch kick-starts the linux kernel */
+
+	movi	a4, init_arch
+	callx4	a4
+
+	movi	a4, start_kernel
+	callx4	a4
+
+should_never_return:
+	j	should_never_return
+
+	/* Define some common data structures here.  We define them
+	 * here in this assembly file due to their unusual alignment
+	 * requirements.
+	 */
+
+	.comm   swapper_pg_dir,PAGE_SIZE,PAGE_SIZE
+	.comm	empty_bad_page_table,PAGE_SIZE,PAGE_SIZE
+	.comm	empty_bad_page,PAGE_SIZE,PAGE_SIZE
+	.comm	empty_zero_page,PAGE_SIZE,PAGE_SIZE
+
diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c
new file mode 100644
index 0000000..4cbf6d9
--- /dev/null
+++ b/arch/xtensa/kernel/irq.c
@@ -0,0 +1,192 @@
+/*
+ * linux/arch/xtensa/kernel/irq.c
+ *
+ * Xtensa built-in interrupt controller and some generic functions copied
+ * from i386.
+ *
+ * Copyright (C) 2002 - 2005 Tensilica, Inc.
+ * Copyright (C) 1992, 1998 Linus Torvalds, Ingo Molnar
+ *
+ *
+ * Chris Zankel <chris@zankel.net>
+ * Kevin Chea
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/uaccess.h>
+#include <asm/platform.h>
+
+static void enable_xtensa_irq(unsigned int irq);
+static void disable_xtensa_irq(unsigned int irq);
+static void mask_and_ack_xtensa(unsigned int irq);
+static void end_xtensa_irq(unsigned int irq);
+
+static unsigned int cached_irq_mask;
+
+atomic_t irq_err_count;
+
+/*
+ * 'what should we do if we get a hw irq event on an illegal vector'.
+ * each architecture has to answer this themselves.
+ */
+void ack_bad_irq(unsigned int irq)
+{
+          printk("unexpected IRQ trap at vector %02x\n", irq);
+}
+
+/*
+ * do_IRQ handles all normal device IRQ's (the special
+ * SMP cross-CPU interrupts have their own specific
+ * handlers).
+ */
+
+unsigned int  do_IRQ(int irq, struct pt_regs *regs)
+{
+	irq_enter();
+
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
+	/* Debugging check for stack overflow: is there less than 1KB free? */
+	{
+		unsigned long sp;
+
+		__asm__ __volatile__ ("mov %0, a1\n" : "=a" (sp));
+		sp &= THREAD_SIZE - 1;
+
+		if (unlikely(sp < (sizeof(thread_info) + 1024)))
+			printk("Stack overflow in do_IRQ: %ld\n",
+			       sp - sizeof(struct thread_info));
+	}
+#endif
+
+	__do_IRQ(irq, regs);
+
+	irq_exit();
+
+	return 1;
+}
+
+/*
+ * Generic, controller-independent functions:
+ */
+
+int show_interrupts(struct seq_file *p, void *v)
+{
+	int i = *(loff_t *) v, j;
+	struct irqaction * action;
+	unsigned long flags;
+
+	if (i == 0) {
+		seq_printf(p, "           ");
+		for (j=0; j<NR_CPUS; j++)
+			if (cpu_online(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 (j = 0; j < NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+#endif
+		seq_printf(p, " %14s", 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);
+	} else if (i == NR_IRQS) {
+		seq_printf(p, "NMI: ");
+		for (j = 0; j < NR_CPUS; j++)
+			if (cpu_online(j))
+				seq_printf(p, "%10u ", nmi_count(j));
+		seq_putc(p, '\n');
+		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+	}
+	return 0;
+}
+/* shutdown is same as "disable" */
+#define shutdown_xtensa_irq disable_xtensa_irq
+
+static unsigned int startup_xtensa_irq(unsigned int irq)
+{
+	enable_xtensa_irq(irq);
+	return 0;               /* never anything pending */
+}
+
+static struct hw_interrupt_type xtensa_irq_type = {
+	"Xtensa-IRQ",
+	startup_xtensa_irq,
+	shutdown_xtensa_irq,
+	enable_xtensa_irq,
+	disable_xtensa_irq,
+	mask_and_ack_xtensa,
+	end_xtensa_irq
+};
+
+static inline void mask_irq(unsigned int irq)
+{
+	cached_irq_mask &= ~(1 << irq);
+	set_sr (cached_irq_mask, INTENABLE);
+}
+
+static inline void unmask_irq(unsigned int irq)
+{
+	cached_irq_mask |= 1 << irq;
+	set_sr (cached_irq_mask, INTENABLE);
+}
+
+static void disable_xtensa_irq(unsigned int irq)
+{
+	unsigned long flags;
+	local_save_flags(flags);
+	mask_irq(irq);
+	local_irq_restore(flags);
+}
+
+static void enable_xtensa_irq(unsigned int irq)
+{
+	unsigned long flags;
+	local_save_flags(flags);
+	unmask_irq(irq);
+	local_irq_restore(flags);
+}
+
+static void mask_and_ack_xtensa(unsigned int irq)
+{
+        disable_xtensa_irq(irq);
+}
+
+static void end_xtensa_irq(unsigned int irq)
+{
+        enable_xtensa_irq(irq);
+}
+
+
+void __init init_IRQ(void)
+{
+	int i;
+
+	for (i=0; i < XTENSA_NR_IRQS; i++)
+		irq_desc[i].handler = &xtensa_irq_type;
+
+	cached_irq_mask = 0;
+
+	platform_init_irq();
+}
diff --git a/arch/xtensa/kernel/module.c b/arch/xtensa/kernel/module.c
new file mode 100644
index 0000000..d1683cf
--- /dev/null
+++ b/arch/xtensa/kernel/module.c
@@ -0,0 +1,78 @@
+/*
+ * arch/xtensa/kernel/platform.c
+ *
+ * Module support.
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/cache.h>
+
+LIST_HEAD(module_buf_list);
+
+void *module_alloc(unsigned long size)
+{
+  panic("module_alloc not implemented");
+}
+
+void module_free(struct module *mod, void *module_region)
+{
+  panic("module_free not implemented");
+}
+
+int module_frob_arch_sections(Elf32_Ehdr *hdr,
+    			      Elf32_Shdr *sechdrs,
+			      char *secstrings,
+			      struct module *me)
+{
+  panic("module_frob_arch_sections not implemented");
+}
+
+int apply_relocate(Elf32_Shdr *sechdrs,
+    		   const char *strtab,
+		   unsigned int symindex,
+		   unsigned int relsec,
+		   struct module *module)
+{
+  panic ("apply_relocate not implemented");
+}
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+		       const char *strtab,
+		       unsigned int symindex,
+		       unsigned int relsec,
+		       struct module *module)
+{
+  panic("apply_relocate_add not implemented");
+}
+
+int module_finalize(const Elf_Ehdr *hdr,
+    		    const Elf_Shdr *sechdrs,
+		    struct module *me)
+{
+  panic ("module_finalize not implemented");
+}
+
+void module_arch_cleanup(struct module *mod)
+{
+  panic("module_arch_cleanup not implemented");
+}
+
+struct bug_entry *module_find_bug(unsigned long bugaddr)
+{
+  panic("module_find_bug not implemented");
+}
diff --git a/arch/xtensa/kernel/pci-dma.c b/arch/xtensa/kernel/pci-dma.c
new file mode 100644
index 0000000..84fde25
--- /dev/null
+++ b/arch/xtensa/kernel/pci-dma.c
@@ -0,0 +1,73 @@
+/*
+ * arch/xtensa/pci-dma.c
+ *
+ * DMA coherent memory allocation.
+ *
+ * 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.
+ *
+ * Copyright (C) 2002 - 2005 Tensilica Inc.
+ *
+ * Based on version for i386.
+ *
+ * Chris Zankel <chris@zankel.net>
+ * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/cacheflush.h>
+
+/*
+ * Note: We assume that the full memory space is always mapped to 'kseg'
+ *	 Otherwise we have to use page attributes (not implemented).
+ */
+
+void *
+dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, int gfp)
+{
+	void *ret;
+
+	/* ignore region speicifiers */
+	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
+
+	if (dev == NULL || (*dev->dma_mask < 0xffffffff))
+		gfp |= GFP_DMA;
+	ret = (void *)__get_free_pages(gfp, get_order(size));
+
+	if (ret != NULL) {
+		memset(ret, 0, size);
+		*handle = virt_to_bus(ret);
+	}
+	return (void*) BYPASS_ADDR((unsigned long)ret);
+}
+
+void dma_free_coherent(struct device *hwdev, size_t size,
+			 void *vaddr, dma_addr_t dma_handle)
+{
+	free_pages(CACHED_ADDR((unsigned long)vaddr), get_order(size));
+}
+
+
+void consistent_sync(void *vaddr, size_t size, int direction)
+{
+	switch (direction) {
+	case PCI_DMA_NONE:
+		BUG();
+	case PCI_DMA_FROMDEVICE:        /* invalidate only */
+		__invalidate_dcache_range((unsigned long)vaddr,
+				          (unsigned long)size);
+		break;
+
+	case PCI_DMA_TODEVICE:          /* writeback only */
+	case PCI_DMA_BIDIRECTIONAL:     /* writeback and invalidate */
+		__flush_invalidate_dcache_range((unsigned long)vaddr,
+				    		(unsigned long)size);
+		break;
+	}
+}
diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c
new file mode 100644
index 0000000..d29a816
--- /dev/null
+++ b/arch/xtensa/kernel/pci.c
@@ -0,0 +1,563 @@
+/*
+ * arch/xtensa/pcibios.c
+ *
+ * PCI bios-type initialisation for PCI machines
+ *
+ * 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.
+ *
+ * Copyright (C) 2001-2005 Tensilica Inc.
+ *
+ * Based largely on work from Cort (ppc/kernel/pci.c)
+ * IO functions copied from sparc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/bootmem.h>
+
+#include <asm/pci-bridge.h>
+#include <asm/platform.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+/* PCI Controller */
+
+
+/*
+ * pcibios_alloc_controller
+ * pcibios_enable_device
+ * pcibios_fixups
+ * pcibios_align_resource
+ * pcibios_fixup_bus
+ * pcibios_setup
+ * pci_bus_add_device
+ * pci_mmap_page_range
+ */
+
+struct pci_controller* pci_ctrl_head;
+struct pci_controller** pci_ctrl_tail = &pci_ctrl_head;
+
+static int pci_bus_count;
+
+static void pcibios_fixup_resources(struct pci_dev* dev);
+
+#if 0 // FIXME
+struct pci_fixup pcibios_fixups[] = {
+	{ DECLARE_PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources },
+	{ 0 }
+};
+#endif
+
+void
+pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+			struct resource *res, int resource)
+{
+	u32 new, check, mask;
+	int reg;
+	struct pci_controller* pci_ctrl = dev->sysdata;
+
+	new = res->start;
+	if (pci_ctrl && res->flags & IORESOURCE_IO) {
+		new -= pci_ctrl->io_space.base;
+	}
+	new |= (res->flags & PCI_REGION_FLAG_MASK);
+	if (resource < 6) {
+		reg = PCI_BASE_ADDRESS_0 + 4*resource;
+	} else if (resource == PCI_ROM_RESOURCE) {
+		res->flags |= PCI_ROM_ADDRESS_ENABLE;
+		reg = dev->rom_base_reg;
+	} else {
+	/* Somebody might have asked allocation of a non-standard resource */
+		return;
+	}
+
+	pci_write_config_dword(dev, reg, new);
+	pci_read_config_dword(dev, reg, &check);
+	mask = (new & PCI_BASE_ADDRESS_SPACE_IO) ?
+		PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK;
+
+	if ((new ^ check) & mask) {
+		printk(KERN_ERR "PCI: Error while updating region "
+		       "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
+		       new, check);
+	}
+}
+
+/*
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ *
+ * Why? Because some silly external IO cards only decode
+ * the low 10 bits of the IO address. The 0x00-0xff region
+ * is reserved for motherboard devices that decode all 16
+ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
+ * but we want to try to avoid allocating at 0x2900-0x2bff
+ * which might have be mirrored at 0x0100-0x03ff..
+ */
+void
+pcibios_align_resource(void *data, struct resource *res, unsigned long size,
+    		       unsigned long align)
+{
+	struct pci_dev *dev = data;
+
+	if (res->flags & IORESOURCE_IO) {
+		unsigned long start = res->start;
+
+		if (size > 0x100) {
+			printk(KERN_ERR "PCI: I/O Region %s/%d too large"
+			       " (%ld bytes)\n", dev->slot_name,
+			       dev->resource - res, size);
+		}
+
+		if (start & 0x300) {
+			start = (start + 0x3ff) & ~0x3ff;
+			res->start = start;
+		}
+	}
+}
+
+int
+pcibios_enable_resources(struct pci_dev *dev, int mask)
+{
+	u16 cmd, old_cmd;
+	int idx;
+	struct resource *r;
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	old_cmd = cmd;
+	for(idx=0; idx<6; idx++) {
+		r = &dev->resource[idx];
+		if (!r->start && r->end) {
+			printk (KERN_ERR "PCI: Device %s not available because "
+				"of resource collisions\n", dev->slot_name);
+			return -EINVAL;
+		}
+		if (r->flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+		if (r->flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+	}
+	if (dev->resource[PCI_ROM_RESOURCE].start)
+		cmd |= PCI_COMMAND_MEMORY;
+	if (cmd != old_cmd) {
+		printk("PCI: Enabling device %s (%04x -> %04x)\n",
+			dev->slot_name, old_cmd, cmd);
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+	}
+	return 0;
+}
+
+struct pci_controller * __init pcibios_alloc_controller(void)
+{
+	struct pci_controller *pci_ctrl;
+
+	pci_ctrl = (struct pci_controller *)alloc_bootmem(sizeof(*pci_ctrl));
+	memset(pci_ctrl, 0, sizeof(struct pci_controller));
+
+	*pci_ctrl_tail = pci_ctrl;
+	pci_ctrl_tail = &pci_ctrl->next;
+
+	return pci_ctrl;
+}
+
+static int __init pcibios_init(void)
+{
+	struct pci_controller *pci_ctrl;
+	struct pci_bus *bus;
+	int next_busno = 0, i;
+
+	printk("PCI: Probing PCI hardware\n");
+
+	/* Scan all of the recorded PCI controllers.  */
+	for (pci_ctrl = pci_ctrl_head; pci_ctrl; pci_ctrl = pci_ctrl->next) {
+		pci_ctrl->last_busno = 0xff;
+		bus = pci_scan_bus(pci_ctrl->first_busno, pci_ctrl->ops,
+				   pci_ctrl);
+		if (pci_ctrl->io_resource.flags) {
+			unsigned long offs;
+
+			offs = (unsigned long)pci_ctrl->io_space.base;
+			pci_ctrl->io_resource.start += offs;
+			pci_ctrl->io_resource.end += offs;
+			bus->resource[0] = &pci_ctrl->io_resource;
+		}
+		for (i = 0; i < 3; ++i)
+			if (pci_ctrl->mem_resources[i].flags)
+				bus->resource[i+1] =&pci_ctrl->mem_resources[i];
+		pci_ctrl->bus = bus;
+		pci_ctrl->last_busno = bus->subordinate;
+		if (next_busno <= pci_ctrl->last_busno)
+			next_busno = pci_ctrl->last_busno+1;
+	}
+	pci_bus_count = next_busno;
+
+	return platform_pcibios_fixup();
+}
+
+subsys_initcall(pcibios_init);
+
+void __init pcibios_fixup_bus(struct pci_bus *bus)
+{
+	struct pci_controller *pci_ctrl = bus->sysdata;
+	struct resource *res;
+	unsigned long io_offset;
+	int i;
+
+	io_offset = (unsigned long)pci_ctrl->io_space.base;
+	if (bus->parent == NULL) {
+		/* this is a host bridge - fill in its resources */
+		pci_ctrl->bus = bus;
+
+		bus->resource[0] = res = &pci_ctrl->io_resource;
+		if (!res->flags) {
+			if (io_offset)
+				printk (KERN_ERR "I/O resource not set for host"
+					" bridge %d\n", pci_ctrl->index);
+			res->start = 0;
+			res->end = IO_SPACE_LIMIT;
+			res->flags = IORESOURCE_IO;
+		}
+		res->start += io_offset;
+		res->end += io_offset;
+
+		for (i = 0; i < 3; i++) {
+			res = &pci_ctrl->mem_resources[i];
+			if (!res->flags) {
+				if (i > 0)
+					continue;
+				printk(KERN_ERR "Memory resource not set for "
+				       "host bridge %d\n", pci_ctrl->index);
+				res->start = 0;
+				res->end = ~0U;
+				res->flags = IORESOURCE_MEM;
+			}
+			bus->resource[i+1] = res;
+		}
+	} else {
+		/* This is a subordinate bridge */
+		pci_read_bridge_bases(bus);
+
+		for (i = 0; i < 4; i++) {
+			if ((res = bus->resource[i]) == NULL || !res->flags)
+				continue;
+			if (io_offset && (res->flags & IORESOURCE_IO)) {
+				res->start += io_offset;
+				res->end += io_offset;
+			}
+		}
+	}
+}
+
+char __init *pcibios_setup(char *str)
+{
+	return str;
+}
+
+/* the next one is stolen from the alpha port... */
+
+void __init
+pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+	u16 cmd, old_cmd;
+	int idx;
+	struct resource *r;
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	old_cmd = cmd;
+	for (idx=0; idx<6; idx++) {
+		r = &dev->resource[idx];
+		if (!r->start && r->end) {
+			printk(KERN_ERR "PCI: Device %s not available because "
+			       "of resource collisions\n", dev->slot_name);
+			return -EINVAL;
+		}
+		if (r->flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+		if (r->flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+	}
+	if (cmd != old_cmd) {
+		printk("PCI: Enabling device %s (%04x -> %04x)\n",
+		       dev->slot_name, old_cmd, cmd);
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_PROC_FS
+
+/*
+ * Return the index of the PCI controller for device pdev.
+ */
+
+int
+pci_controller_num(struct pci_dev *dev)
+{
+	struct pci_controller *pci_ctrl = (struct pci_controller*) dev->sysdata;
+	return pci_ctrl->index;
+}
+
+#endif /* CONFIG_PROC_FS */
+
+
+static void
+pcibios_fixup_resources(struct pci_dev *dev)
+{
+	struct pci_controller* pci_ctrl = (struct pci_controller *)dev->sysdata;
+	int i;
+	unsigned long offset;
+
+	if (!pci_ctrl) {
+		printk(KERN_ERR "No pci_ctrl for PCI dev %s!\n",dev->slot_name);
+		return;
+	}
+	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+		struct resource *res = dev->resource + i;
+		if (!res->start || !res->flags)
+			continue;
+		if (res->end == 0xffffffff) {
+			DBG("PCI:%s Resource %d [%08lx-%08lx] is unassigned\n",
+			    dev->slot_name, i, res->start, res->end);
+			res->end -= res->start;
+			res->start = 0;
+			continue;
+		}
+		offset = 0;
+		if (res->flags & IORESOURCE_IO)
+			offset = (unsigned long) pci_ctrl->io_space.base;
+		else if (res->flags & IORESOURCE_MEM)
+			offset = (unsigned long) pci_ctrl->mem_space.base;
+
+		if (offset != 0) {
+			res->start += offset;
+			res->end += offset;
+#ifdef DEBUG
+			printk("Fixup res %d (%lx) of dev %s: %lx -> %lx\n",
+			       i, res->flags, dev->slot_name,
+			       res->start - offset, res->start);
+#endif
+		}
+	}
+}
+
+/*
+ * Platform support for /proc/bus/pci/X/Y mmap()s,
+ * modelled on the sparc64 implementation by Dave Miller.
+ *  -- paulus.
+ */
+
+/*
+ * Adjust vm_pgoff of VMA such that it is the physical page offset
+ * corresponding to the 32-bit pci bus offset for DEV requested by the user.
+ *
+ * Basically, the user finds the base address for his device which he wishes
+ * to mmap.  They read the 32-bit value from the config space base register,
+ * add whatever PAGE_SIZE multiple offset they wish, and feed this into the
+ * offset parameter of mmap on /proc/bus/pci/XXX for that device.
+ *
+ * Returns negative error code on failure, zero on success.
+ */
+static __inline__ int
+__pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma,
+		       enum pci_mmap_state mmap_state)
+{
+	struct pci_controller *pci_ctrl = (struct pci_controller*) dev->sysdata;
+	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+	unsigned long io_offset = 0;
+	int i, res_bit;
+
+	if (pci_ctrl == 0)
+		return -EINVAL;		/* should never happen */
+
+	/* If memory, add on the PCI bridge address offset */
+	if (mmap_state == pci_mmap_mem) {
+		res_bit = IORESOURCE_MEM;
+	} else {
+		io_offset = (unsigned long)pci_ctrl->io_space.base;
+		offset += io_offset;
+		res_bit = IORESOURCE_IO;
+	}
+
+	/*
+	 * Check that the offset requested corresponds to one of the
+	 * resources of the device.
+	 */
+	for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
+		struct resource *rp = &dev->resource[i];
+		int flags = rp->flags;
+
+		/* treat ROM as memory (should be already) */
+		if (i == PCI_ROM_RESOURCE)
+			flags |= IORESOURCE_MEM;
+
+		/* Active and same type? */
+		if ((flags & res_bit) == 0)
+			continue;
+
+		/* In the range of this resource? */
+		if (offset < (rp->start & PAGE_MASK) || offset > rp->end)
+			continue;
+
+		/* found it! construct the final physical address */
+		if (mmap_state == pci_mmap_io)
+			offset += pci_ctrl->io_space.start - io_offset;
+		vma->vm_pgoff = offset >> PAGE_SHIFT;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+/*
+ * 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.
+ */
+static __inline__ void
+__pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
+		      enum pci_mmap_state mmap_state, int write_combine)
+{
+	int prot = pgprot_val(vma->vm_page_prot);
+
+	/* Set to write-through */
+	prot &= ~_PAGE_NO_CACHE;
+#if 0
+	if (!write_combine)
+		prot |= _PAGE_WRITETHRU;
+#endif
+	vma->vm_page_prot = __pgprot(prot);
+}
+
+/*
+ * Perform the actual remap of the pages for a PCI device mapping, as
+ * appropriate for this architecture.  The region in the process to map
+ * is described by vm_start and vm_end members of VMA, the base physical
+ * address is found in vm_pgoff.
+ * The pci device structure is provided so that architectures may make mapping
+ * decisions on a per-device or per-bus basis.
+ *
+ * Returns a negative error code on failure, zero on success.
+ */
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+			enum pci_mmap_state mmap_state,
+			int write_combine)
+{
+	int ret;
+
+	ret = __pci_mmap_make_offset(dev, vma, mmap_state);
+	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_page_range(vma, vma->vm_start, vma->vm_pgoff<<PAGE_SHIFT,
+			       vma->vm_end - vma->vm_start, vma->vm_page_prot);
+
+	return ret;
+}
+
+/*
+ * This probably belongs here rather than ioport.c because
+ * we do not want this crud linked into SBus kernels.
+ * Also, think for a moment about likes of floppy.c that
+ * include architecture specific parts. They may want to redefine ins/outs.
+ *
+ * We do not use horroble macroses here because we want to
+ * advance pointer by sizeof(size).
+ */
+void outsb(unsigned long addr, const void *src, unsigned long count) {
+        while (count) {
+                count -= 1;
+                writeb(*(const char *)src, addr);
+                src += 1;
+                addr += 1;
+        }
+}
+
+void outsw(unsigned long addr, const void *src, unsigned long count) {
+        while (count) {
+                count -= 2;
+                writew(*(const short *)src, addr);
+                src += 2;
+                addr += 2;
+        }
+}
+
+void outsl(unsigned long addr, const void *src, unsigned long count) {
+        while (count) {
+                count -= 4;
+                writel(*(const long *)src, addr);
+                src += 4;
+                addr += 4;
+        }
+}
+
+void insb(unsigned long addr, void *dst, unsigned long count) {
+        while (count) {
+                count -= 1;
+                *(unsigned char *)dst = readb(addr);
+                dst += 1;
+                addr += 1;
+        }
+}
+
+void insw(unsigned long addr, void *dst, unsigned long count) {
+        while (count) {
+                count -= 2;
+                *(unsigned short *)dst = readw(addr);
+                dst += 2;
+                addr += 2;
+        }
+}
+
+void insl(unsigned long addr, void *dst, unsigned long count) {
+        while (count) {
+                count -= 4;
+                /*
+                 * XXX I am sure we are in for an unaligned trap here.
+                 */
+                *(unsigned long *)dst = readl(addr);
+                dst += 4;
+                addr += 4;
+        }
+}
+
+
+
diff --git a/arch/xtensa/kernel/platform.c b/arch/xtensa/kernel/platform.c
new file mode 100644
index 0000000..cf13627
--- /dev/null
+++ b/arch/xtensa/kernel/platform.c
@@ -0,0 +1,49 @@
+/*
+ * arch/xtensa/kernel/platform.c
+ *
+ * Default platform functions.
+ *
+ * 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 Tensilica Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/time.h>
+#include <asm/platform.h>
+#include <asm/timex.h>
+
+#define _F(r,f,a,b)							\
+	r __platform_##f a b;                                   	\
+	r platform_##f a __attribute__((weak, alias("__platform_"#f)))
+
+/*
+ * Default functions that are used if no platform specific function is defined.
+ * (Please, refer to include/asm-xtensa/platform.h for more information)
+ */
+
+_F(void, setup, (char** cmd), { });
+_F(void, init_irq, (void), { });
+_F(void, restart, (void), { while(1); });
+_F(void, halt, (void), { while(1); });
+_F(void, power_off, (void), { while(1); });
+_F(void, idle, (void), { __asm__ __volatile__ ("waiti 0" ::: "memory"); });
+_F(void, heartbeat, (void), { });
+_F(int,  pcibios_fixup, (void), { return 0; });
+_F(int, get_rtc_time, (time_t* t), { return 0; });
+_F(int, set_rtc_time, (time_t t), { return 0; });
+
+#if CONFIG_XTENSA_CALIBRATE_CCOUNT
+_F(void, calibrate_ccount, (void),
+{
+  printk ("ERROR: Cannot calibrate cpu frequency! Assuming 100MHz.\n");
+  ccount_per_jiffy = 100 * (1000000UL/HZ);
+});
+#endif
+
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c
new file mode 100644
index 0000000..4099703
--- /dev/null
+++ b/arch/xtensa/kernel/process.c
@@ -0,0 +1,482 @@
+// TODO	verify coprocessor handling
+/*
+ * arch/xtensa/kernel/process.c
+ *
+ * Xtensa Processor version.
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ *
+ * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
+ * Chris Zankel <chris@zankel.net>
+ * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca>
+ * Kevin Chea
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/elf.h>
+#include <linux/init.h>
+#include <linux/prctl.h>
+#include <linux/init_task.h>
+#include <linux/module.h>
+#include <linux/mqueue.h>
+
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/platform.h>
+#include <asm/mmu.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/offsets.h>
+#include <asm/coprocessor.h>
+
+extern void ret_from_fork(void);
+
+static struct fs_struct init_fs = INIT_FS;
+static struct files_struct init_files = INIT_FILES;
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+struct mm_struct init_mm = INIT_MM(init_mm);
+EXPORT_SYMBOL(init_mm);
+
+union thread_union init_thread_union
+	__attribute__((__section__(".data.init_task"))) =
+{ INIT_THREAD_INFO(init_task) };
+
+struct task_struct init_task = INIT_TASK(init_task);
+EXPORT_SYMBOL(init_task);
+
+struct task_struct *current_set[NR_CPUS] = {&init_task, };
+
+
+#if XCHAL_CP_NUM > 0
+
+/*
+ * Coprocessor ownership.
+ */
+
+coprocessor_info_t coprocessor_info[] = {
+	{ 0, XTENSA_CPE_CP0_OFFSET },
+	{ 0, XTENSA_CPE_CP1_OFFSET },
+	{ 0, XTENSA_CPE_CP2_OFFSET },
+	{ 0, XTENSA_CPE_CP3_OFFSET },
+	{ 0, XTENSA_CPE_CP4_OFFSET },
+	{ 0, XTENSA_CPE_CP5_OFFSET },
+	{ 0, XTENSA_CPE_CP6_OFFSET },
+	{ 0, XTENSA_CPE_CP7_OFFSET },
+};
+
+#endif
+
+/*
+ * Powermanagement idle function, if any is provided by the platform.
+ */
+
+void cpu_idle(void)
+{
+  	local_irq_enable();
+
+	/* endless idle loop with no priority at all */
+	while (1) {
+		while (!need_resched())
+			platform_idle();
+		preempt_enable();
+		schedule();
+	}
+}
+
+/*
+ * Free current thread data structures etc..
+ */
+
+void exit_thread(void)
+{
+	release_coprocessors(current);	/* Empty macro if no CPs are defined */
+}
+
+void flush_thread(void)
+{
+	release_coprocessors(current);	/* Empty macro if no CPs are defined */
+}
+
+/*
+ * Copy thread.
+ *
+ * The stack layout for the new thread looks like this:
+ *
+ *	+------------------------+ <- sp in childregs (= tos)
+ *	|       childregs        |
+ *	+------------------------+ <- thread.sp = sp in dummy-frame
+ *	|      dummy-frame       |    (saved in dummy-frame spill-area)
+ *	+------------------------+
+ *
+ * We create a dummy frame to return to ret_from_fork:
+ *   a0 points to ret_from_fork (simulating a call4)
+ *   sp points to itself (thread.sp)
+ *   a2, a3 are unused.
+ *
+ * Note: This is a pristine frame, so we don't need any spill region on top of
+ *       childregs.
+ */
+
+int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+		unsigned long unused,
+                struct task_struct * p, struct pt_regs * regs)
+{
+	struct pt_regs *childregs;
+	unsigned long tos;
+	int user_mode = user_mode(regs);
+
+	/* Set up new TSS. */
+	tos = (unsigned long)p->thread_info + THREAD_SIZE;
+	if (user_mode)
+		childregs = (struct pt_regs*)(tos - PT_USER_SIZE);
+	else
+		childregs = (struct pt_regs*)tos - 1;
+
+	*childregs = *regs;
+
+	/* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */
+	*((int*)childregs - 3) = (unsigned long)childregs;
+	*((int*)childregs - 4) = 0;
+
+	childregs->areg[1] = tos;
+	childregs->areg[2] = 0;
+	p->set_child_tid = p->clear_child_tid = NULL;
+	p->thread.ra = MAKE_RA_FOR_CALL((unsigned long)ret_from_fork, 0x1);
+	p->thread.sp = (unsigned long)childregs;
+	if (user_mode(regs)) {
+
+		int len = childregs->wmask & ~0xf;
+		childregs->areg[1] = usp;
+		memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4],
+		       &regs->areg[XCHAL_NUM_AREGS - len/4], len);
+
+		if (clone_flags & CLONE_SETTLS)
+			childregs->areg[2] = childregs->areg[6];
+
+	} else {
+		/* In kernel space, we start a new thread with a new stack. */
+		childregs->wmask = 1;
+	}
+	return 0;
+}
+
+
+/*
+ * Create a kernel thread
+ */
+
+int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{
+	long retval;
+	__asm__ __volatile__
+		("mov           a5, %4\n\t" /* preserve fn in a5 */
+		 "mov           a6, %3\n\t" /* preserve and setup arg in a6 */
+		 "movi		a2, %1\n\t" /* load __NR_clone for syscall*/
+		 "mov		a3, sp\n\t" /* sp check and sys_clone */
+		 "mov		a4, %5\n\t" /* load flags for syscall */
+		 "syscall\n\t"
+		 "beq		a3, sp, 1f\n\t" /* branch if parent */
+		 "callx4	a5\n\t"     /* call fn */
+		 "movi		a2, %2\n\t" /* load __NR_exit for syscall */
+		 "mov		a3, a6\n\t" /* load fn return value */
+		 "syscall\n"
+		 "1:\n\t"
+		 "mov		%0, a2\n\t" /* parent returns zero */
+		 :"=r" (retval)
+		 :"i" (__NR_clone), "i" (__NR_exit),
+		 "r" (arg), "r" (fn),
+		 "r" (flags | CLONE_VM)
+		 : "a2", "a3", "a4", "a5", "a6" );
+	return retval;
+}
+
+
+/*
+ * These bracket the sleeping functions..
+ */
+
+unsigned long get_wchan(struct task_struct *p)
+{
+	unsigned long sp, pc;
+	unsigned long stack_page = (unsigned long) p->thread_info;
+	int count = 0;
+
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+
+	sp = p->thread.sp;
+	pc = MAKE_PC_FROM_RA(p->thread.ra, p->thread.sp);
+
+	do {
+		if (sp < stack_page + sizeof(struct task_struct) ||
+		    sp >= (stack_page + THREAD_SIZE) ||
+		    pc == 0)
+			return 0;
+		if (!in_sched_functions(pc))
+			return pc;
+
+		/* Stack layout: sp-4: ra, sp-3: sp' */
+
+		pc = MAKE_PC_FROM_RA(*(unsigned long*)sp - 4, sp);
+		sp = *(unsigned long *)sp - 3;
+	} while (count++ < 16);
+	return 0;
+}
+
+/*
+ * do_copy_regs() gathers information from 'struct pt_regs' and
+ * 'current->thread.areg[]' to fill in the xtensa_gregset_t
+ * structure.
+ *
+ * xtensa_gregset_t and 'struct pt_regs' are vastly different formats
+ * of processor registers.  Besides different ordering,
+ * xtensa_gregset_t contains non-live register information that
+ * 'struct pt_regs' does not.  Exception handling (primarily) uses
+ * 'struct pt_regs'.  Core files and ptrace use xtensa_gregset_t.
+ *
+ */
+
+void do_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs,
+		   struct task_struct *tsk)
+{
+	int i, n, wb_offset;
+
+	elfregs->xchal_config_id0 = XCHAL_HW_CONFIGID0;
+	elfregs->xchal_config_id1 = XCHAL_HW_CONFIGID1;
+
+	__asm__ __volatile__ ("rsr  %0, 176\n" : "=a" (i));
+ 	elfregs->cpux = i;
+	__asm__ __volatile__ ("rsr  %0, 208\n" : "=a" (i));
+ 	elfregs->cpuy = i;
+
+	/* Note:  PS.EXCM is not set while user task is running; its
+	 * being set in regs->ps is for exception handling convenience.
+	 */
+
+	elfregs->pc		= regs->pc;
+	elfregs->ps		= (regs->ps & ~XCHAL_PS_EXCM_MASK);
+	elfregs->exccause	= regs->exccause;
+	elfregs->excvaddr	= regs->excvaddr;
+	elfregs->windowbase	= regs->windowbase;
+	elfregs->windowstart	= regs->windowstart;
+	elfregs->lbeg		= regs->lbeg;
+	elfregs->lend		= regs->lend;
+	elfregs->lcount		= regs->lcount;
+	elfregs->sar		= regs->sar;
+	elfregs->syscall	= regs->syscall;
+
+	/* Copy register file.
+	 * The layout looks like this:
+	 *
+	 * |  a0 ... a15  | Z ... Z |  arX ... arY  |
+	 *  current window  unused    saved frames
+	 */
+
+	memset (elfregs->ar, 0, sizeof(elfregs->ar));
+
+	wb_offset = regs->windowbase * 4;
+	n = (regs->wmask&1)? 4 : (regs->wmask&2)? 8 : (regs->wmask&4)? 12 : 16;
+
+	for (i = 0; i < n; i++)
+		elfregs->ar[(wb_offset + i) % XCHAL_NUM_AREGS] = regs->areg[i];
+
+	n = (regs->wmask >> 4) * 4;
+
+	for (i = XCHAL_NUM_AREGS - n; n > 0; i++, n--)
+		elfregs->ar[(wb_offset + i) % XCHAL_NUM_AREGS] = regs->areg[i];
+}
+
+void xtensa_elf_core_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs)
+{
+	do_copy_regs ((xtensa_gregset_t *)elfregs, regs, current);
+}
+
+
+/* The inverse of do_copy_regs().  No error or sanity checking. */
+
+void do_restore_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs,
+		      struct task_struct *tsk)
+{
+	int i, n, wb_offset;
+
+	/* Note:  PS.EXCM is not set while user task is running; it
+	 * needs to be set in regs->ps is for exception handling convenience.
+	 */
+
+	regs->pc		= elfregs->pc;
+	regs->ps		= (elfregs->ps | XCHAL_PS_EXCM_MASK);
+	regs->exccause		= elfregs->exccause;
+	regs->excvaddr		= elfregs->excvaddr;
+	regs->windowbase	= elfregs->windowbase;
+	regs->windowstart	= elfregs->windowstart;
+	regs->lbeg		= elfregs->lbeg;
+	regs->lend		= elfregs->lend;
+	regs->lcount		= elfregs->lcount;
+	regs->sar		= elfregs->sar;
+	regs->syscall	= elfregs->syscall;
+
+	/* Clear everything. */
+
+	memset (regs->areg, 0, sizeof(regs->areg));
+
+	/* Copy regs from live window frame. */
+
+	wb_offset = regs->windowbase * 4;
+	n = (regs->wmask&1)? 4 : (regs->wmask&2)? 8 : (regs->wmask&4)? 12 : 16;
+
+	for (i = 0; i < n; i++)
+		regs->areg[(wb_offset+i) % XCHAL_NUM_AREGS] = elfregs->ar[i];
+
+	n = (regs->wmask >> 4) * 4;
+
+	for (i = XCHAL_NUM_AREGS - n; n > 0; i++, n--)
+		regs->areg[(wb_offset+i) % XCHAL_NUM_AREGS] = elfregs->ar[i];
+}
+
+/*
+ * do_save_fpregs() gathers information from 'struct pt_regs' and
+ * 'current->thread' to fill in the elf_fpregset_t structure.
+ *
+ * Core files and ptrace use elf_fpregset_t.
+ */
+
+void do_save_fpregs (elf_fpregset_t *fpregs, struct pt_regs *regs,
+		     struct task_struct *tsk)
+{
+#if XCHAL_HAVE_CP
+
+	extern unsigned char	_xtensa_reginfo_tables[];
+	extern unsigned		_xtensa_reginfo_table_size;
+	int i;
+	unsigned long flags;
+
+	/* Before dumping coprocessor state from memory,
+	 * ensure any live coprocessor contents for this
+	 * task are first saved to memory:
+	 */
+	local_irq_save(flags);
+
+	for (i = 0; i < XCHAL_CP_MAX; i++) {
+		if (tsk == coprocessor_info[i].owner) {
+			enable_coprocessor(i);
+			save_coprocessor_registers(
+			    tsk->thread.cp_save+coprocessor_info[i].offset,i);
+			disable_coprocessor(i);
+		}
+	}
+
+	local_irq_restore(flags);
+
+	/* Now dump coprocessor & extra state: */
+	memcpy((unsigned char*)fpregs,
+		_xtensa_reginfo_tables, _xtensa_reginfo_table_size);
+	memcpy((unsigned char*)fpregs + _xtensa_reginfo_table_size,
+		tsk->thread.cp_save, XTENSA_CP_EXTRA_SIZE);
+#endif
+}
+
+/*
+ * The inverse of do_save_fpregs().
+ * Copies coprocessor and extra state from fpregs into regs and tsk->thread.
+ * Returns 0 on success, non-zero if layout doesn't match.
+ */
+
+int  do_restore_fpregs (elf_fpregset_t *fpregs, struct pt_regs *regs,
+		        struct task_struct *tsk)
+{
+#if XCHAL_HAVE_CP
+
+	extern unsigned char	_xtensa_reginfo_tables[];
+	extern unsigned		_xtensa_reginfo_table_size;
+	int i;
+	unsigned long flags;
+
+	/* Make sure save area layouts match.
+	 * FIXME:  in the future we could allow restoring from
+	 * a different layout of the same registers, by comparing
+	 * fpregs' table with _xtensa_reginfo_tables and matching
+	 * entries and copying registers one at a time.
+	 * Not too sure yet whether that's very useful.
+	 */
+
+	if( memcmp((unsigned char*)fpregs,
+		_xtensa_reginfo_tables, _xtensa_reginfo_table_size) ) {
+	    return -1;
+	}
+
+	/* Before restoring coprocessor state from memory,
+	 * ensure any live coprocessor contents for this
+	 * task are first invalidated.
+	 */
+
+	local_irq_save(flags);
+
+	for (i = 0; i < XCHAL_CP_MAX; i++) {
+		if (tsk == coprocessor_info[i].owner) {
+			enable_coprocessor(i);
+			save_coprocessor_registers(
+			    tsk->thread.cp_save+coprocessor_info[i].offset,i);
+			coprocessor_info[i].owner = 0;
+			disable_coprocessor(i);
+		}
+	}
+
+	local_irq_restore(flags);
+
+	/*  Now restore coprocessor & extra state:  */
+
+	memcpy(tsk->thread.cp_save,
+		(unsigned char*)fpregs + _xtensa_reginfo_table_size,
+		XTENSA_CP_EXTRA_SIZE);
+#endif
+	return 0;
+}
+/*
+ * Fill in the CP structure for a core dump for a particular task.
+ */
+
+int
+dump_task_fpu(struct pt_regs *regs, struct task_struct *task, elf_fpregset_t *r)
+{
+/* see asm/coprocessor.h for this magic number 16 */
+#if TOTAL_CPEXTRA_SIZE > 16
+	do_save_fpregs (r, regs, task);
+
+	/*  For now, bit 16 means some extra state may be present:  */
+// FIXME!! need to track to return more accurate mask
+	return 0x10000 | XCHAL_CP_MASK;
+#else
+	return 0;	/* no coprocessors active on this processor */
+#endif
+}
+
+/*
+ * Fill in the CP structure for a core dump.
+ * This includes any FPU coprocessor.
+ * Here, we dump all coprocessors, and other ("extra") custom state.
+ *
+ * This function is called by elf_core_dump() in fs/binfmt_elf.c
+ * (in which case 'regs' comes from calls to do_coredump, see signals.c).
+ */
+int  dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)
+{
+	return dump_task_fpu(regs, current, r);
+}
diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c
new file mode 100644
index 0000000..9ef07a4
--- /dev/null
+++ b/arch/xtensa/kernel/ptrace.c
@@ -0,0 +1,407 @@
+// TODO some minor issues
+/*
+ * 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) 2001 - 2005  Tensilica Inc.
+ *
+ * Joe Taylor	<joe@tensilica.com, joetylr@yahoo.com>
+ * Chris Zankel <chris@zankel.net>
+ * Scott Foehner<sfoehner@yahoo.com>,
+ * Kevin Chea
+ * Marc Gauthier<marc@tensilica.com> <marc@alumni.uwaterloo.ca>
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/security.h>
+
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/ptrace.h>
+#include <asm/elf.h>
+
+#define TEST_KERNEL	// verify kernel operations FIXME: remove
+
+
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Make sure single step bits etc are not set.
+ */
+
+void ptrace_disable(struct task_struct *child)
+{
+	/* Nothing to do.. */
+}
+
+int sys_ptrace(long request, long pid, long addr, long data)
+{
+	struct task_struct *child;
+	int ret = -EPERM;
+
+	lock_kernel();
+
+#if 0
+	if ((int)request != 1)
+	printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n",
+	       (int) request, (int) pid, (unsigned long) addr,
+	       (unsigned long) data);
+#endif
+
+	if (request == PTRACE_TRACEME) {
+
+		/* Are we already being traced? */
+
+		if (current->ptrace & PT_PTRACED)
+			goto out;
+
+		if ((ret = security_ptrace(current->parent, current)))
+			goto out;
+
+		/* Set the ptrace bit in the process flags. */
+
+		current->ptrace |= PT_PTRACED;
+		ret = 0;
+		goto out;
+	}
+
+	ret = -ESRCH;
+	read_lock(&tasklist_lock);
+	child = find_task_by_pid(pid);
+	if (child)
+		get_task_struct(child);
+	read_unlock(&tasklist_lock);
+	if (!child)
+		goto out;
+
+	ret = -EPERM;
+	if (pid == 1)		/* you may not mess with init */
+		goto out;
+
+	if (request == PTRACE_ATTACH) {
+		ret = ptrace_attach(child);
+		goto out_tsk;
+	}
+
+	if ((ret = ptrace_check_attach(child, request == PTRACE_KILL)) < 0)
+		goto out_tsk;
+
+	switch (request) {
+	case PTRACE_PEEKTEXT: /* read word at location addr. */
+	case PTRACE_PEEKDATA:
+	{
+		unsigned long tmp;
+		int copied;
+
+		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+		ret = -EIO;
+		if (copied != sizeof(tmp))
+			break;
+		ret = put_user(tmp,(unsigned long *) data);
+
+		goto out;
+	}
+
+	/* Read the word at location addr in the USER area.  */
+
+	case PTRACE_PEEKUSR:
+		{
+		struct pt_regs *regs;
+		unsigned long tmp;
+
+		regs = xtensa_pt_regs(child);
+		tmp = 0;  /* Default return value. */
+
+		switch(addr) {
+
+		case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1:
+			{
+			int ar = addr - REG_AR_BASE - regs->windowbase * 4;
+			ar &= (XCHAL_NUM_AREGS - 1);
+			if (ar < 16 && ar + (regs->wmask >> 4) * 4 >= 0)
+				tmp = regs->areg[ar];
+			else
+				ret = -EIO;
+			break;
+			}
+		case REG_A_BASE ... REG_A_BASE + 15:
+			tmp = regs->areg[addr - REG_A_BASE];
+			break;
+		case REG_PC:
+			tmp = regs->pc;
+			break;
+		case REG_PS:
+			/* Note:  PS.EXCM is not set while user task is running;
+			 * its being set in regs is for exception handling
+			 * convenience.  */
+			tmp = (regs->ps & ~XCHAL_PS_EXCM_MASK);
+			break;
+		case REG_WB:
+			tmp = regs->windowbase;
+			break;
+		case REG_WS:
+			tmp = regs->windowstart;
+			break;
+		case REG_LBEG:
+			tmp = regs->lbeg;
+			break;
+		case REG_LEND:
+			tmp = regs->lend;
+			break;
+		case REG_LCOUNT:
+			tmp = regs->lcount;
+			break;
+		case REG_SAR:
+			tmp = regs->sar;
+			break;
+		case REG_DEPC:
+			tmp = regs->depc;
+			break;
+		case REG_EXCCAUSE:
+			tmp = regs->exccause;
+			break;
+		case REG_EXCVADDR:
+			tmp = regs->excvaddr;
+			break;
+		case SYSCALL_NR:
+			tmp = regs->syscall;
+			break;
+		default:
+			tmp = 0;
+			ret = -EIO;
+			goto out;
+		}
+		ret = put_user(tmp, (unsigned long *) data);
+		goto out;
+		}
+
+	case PTRACE_POKETEXT: /* write the word at location addr. */
+	case PTRACE_POKEDATA:
+		if (access_process_vm(child, addr, &data, sizeof(data), 1)
+		    == sizeof(data))
+			break;
+		ret = -EIO;
+		goto out;
+
+	case PTRACE_POKEUSR:
+		{
+		struct pt_regs *regs;
+		regs = xtensa_pt_regs(child);
+
+		switch (addr) {
+		case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1:
+			{
+			int ar = addr - REG_AR_BASE - regs->windowbase * 4;
+			if (ar < 16 && ar + (regs->wmask >> 4) * 4 >= 0)
+				regs->areg[ar & (XCHAL_NUM_AREGS - 1)] = data;
+			else
+				ret = -EIO;
+			break;
+			}
+		case REG_A_BASE ... REG_A_BASE + 15:
+			regs->areg[addr - REG_A_BASE] = data;
+			break;
+		case REG_PC:
+			regs->pc = data;
+			break;
+		case SYSCALL_NR:
+			regs->syscall = data;
+			break;
+#ifdef TEST_KERNEL
+		case REG_WB:
+			regs->windowbase = data;
+			break;
+		case REG_WS:
+			regs->windowstart = data;
+			break;
+#endif
+
+		default:
+			/* The rest are not allowed. */
+			ret = -EIO;
+			break;
+		}
+		break;
+		}
+
+	/* continue and stop at next (return from) syscall */
+	case PTRACE_SYSCALL:
+	case PTRACE_CONT: /* restart after signal. */
+	{
+		ret = -EIO;
+		if ((unsigned long) data > _NSIG)
+			break;
+		if (request == PTRACE_SYSCALL)
+			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+		else
+			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+		child->exit_code = data;
+		/* Make sure the single step bit is not set. */
+		child->ptrace &= ~PT_SINGLESTEP;
+		wake_up_process(child);
+		ret = 0;
+		break;
+	}
+
+	/*
+	 * make the child exit.  Best I can do is send it a sigkill.
+	 * perhaps it should be put in the status that it wants to
+	 * exit.
+	 */
+	case PTRACE_KILL:
+		ret = 0;
+		if (child->state == EXIT_ZOMBIE)	/* already dead */
+			break;
+		child->exit_code = SIGKILL;
+		child->ptrace &= ~PT_SINGLESTEP;
+		wake_up_process(child);
+		break;
+
+	case PTRACE_SINGLESTEP:
+		ret = -EIO;
+		if ((unsigned long) data > _NSIG)
+			break;
+		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
+		child->ptrace |= PT_SINGLESTEP;
+		child->exit_code = data;
+		wake_up_process(child);
+		ret = 0;
+		break;
+
+	case PTRACE_GETREGS:
+	{
+		/* 'data' points to user memory in which to write.
+		 * Mainly due to the non-live register values, we
+		 * reformat the register values into something more
+		 * standard.  For convenience, we use the handy
+		 * elf_gregset_t format. */
+
+		xtensa_gregset_t format;
+		struct pt_regs *regs = xtensa_pt_regs(child);
+
+		do_copy_regs (&format, regs, child);
+
+		/* Now, copy to user space nice and easy... */
+		ret = 0;
+		if (copy_to_user((void *)data, &format, sizeof(elf_gregset_t)))
+			ret = -EFAULT;
+		break;
+	}
+
+	case PTRACE_SETREGS:
+	{
+		/* 'data' points to user memory that contains the new
+		 * values in the elf_gregset_t format. */
+
+		xtensa_gregset_t format;
+		struct pt_regs *regs = xtensa_pt_regs(child);
+
+		if (copy_from_user(&format,(void *)data,sizeof(elf_gregset_t))){
+			ret = -EFAULT;
+			break;
+		}
+
+		/* FIXME: Perhaps we want some sanity checks on
+		 * these user-space values?  See ARM version.  Are
+		 * debuggers a security concern? */
+
+		do_restore_regs (&format, regs, child);
+
+		ret = 0;
+		break;
+	}
+
+	case PTRACE_GETFPREGS:
+	{
+		/* 'data' points to user memory in which to write.
+		 * For convenience, we use the handy
+		 * elf_fpregset_t format. */
+
+		elf_fpregset_t fpregs;
+		struct pt_regs *regs = xtensa_pt_regs(child);
+
+		do_save_fpregs (&fpregs, regs, child);
+
+		/* Now, copy to user space nice and easy... */
+		ret = 0;
+		if (copy_to_user((void *)data, &fpregs, sizeof(elf_fpregset_t)))
+			ret = -EFAULT;
+
+		break;
+	}
+
+	case PTRACE_SETFPREGS:
+	{
+		/* 'data' points to user memory that contains the new
+		 * values in the elf_fpregset_t format.
+		 */
+		elf_fpregset_t fpregs;
+		struct pt_regs *regs = xtensa_pt_regs(child);
+
+		ret = 0;
+		if (copy_from_user(&fpregs, (void *)data, sizeof(elf_fpregset_t))) {
+			ret = -EFAULT;
+			break;
+		}
+
+		if (do_restore_fpregs (&fpregs, regs, child))
+			ret = -EIO;
+		break;
+	}
+
+	case PTRACE_GETFPREGSIZE:
+		/* 'data' points to 'unsigned long' set to the size
+		 * of elf_fpregset_t
+		 */
+		ret = put_user(sizeof(elf_fpregset_t), (unsigned long *) data);
+		break;
+
+	case PTRACE_DETACH: /* detach a process that was attached. */
+		ret = ptrace_detach(child, data);
+		break;
+
+	default:
+		ret = ptrace_request(child, request, addr, data);
+		goto out;
+	}
+out_tsk:
+	put_task_struct(child);
+out:
+	unlock_kernel();
+	return ret;
+}
+
+void do_syscall_trace(void)
+{
+	if (!test_thread_flag(TIF_SYSCALL_TRACE))
+		return;
+
+	if (!(current->ptrace & PT_PTRACED))
+		return;
+
+	/*
+	 * The 0x80 provides a way for the tracing parent to distinguish
+	 * between a syscall stop and SIGTRAP delivery
+	 */
+	ptrace_notify(SIGTRAP|((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0));
+
+	/*
+	 * this isn't the same as continuing with a signal, but it will do
+	 * for normal use.  strace only continues with a signal if the
+	 * stopping signal is not SIGTRAP.  -brl
+	 */
+	if (current->exit_code) {
+		send_sig(current->exit_code, current, 1);
+		current->exit_code = 0;
+	}
+}
diff --git a/arch/xtensa/kernel/semaphore.c b/arch/xtensa/kernel/semaphore.c
new file mode 100644
index 0000000..d40f4b1
--- /dev/null
+++ b/arch/xtensa/kernel/semaphore.c
@@ -0,0 +1,226 @@
+/*
+ * arch/xtensa/kernel/semaphore.c
+ *
+ * Generic semaphore code. Buyer beware. Do your own specific changes
+ * in <asm/semaphore-helper.h>
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ *
+ * Joe Taylor	<joe@tensilica.com, joetylr@yahoo.com>
+ * Chris Zankel	<chris@zankel.net>
+ * Marc Gauthier<marc@tensilica.com, marc@alumni.uwaterloo.ca>
+ * Kevin Chea
+ */
+
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/init.h>
+#include <asm/semaphore.h>
+#include <asm/errno.h>
+
+/*
+ * These two _must_ execute atomically wrt each other.
+ */
+
+static __inline__ void wake_one_more(struct semaphore * sem)
+{
+	atomic_inc((atomic_t *)&sem->sleepers);
+}
+
+static __inline__ int waking_non_zero(struct semaphore *sem)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&semaphore_wake_lock, flags);
+	if (sem->sleepers > 0) {
+		sem->sleepers--;
+		ret = 1;
+	}
+	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+	return ret;
+}
+
+/*
+ * waking_non_zero_interruptible:
+ *	1	got the lock
+ *	0	go to sleep
+ *	-EINTR	interrupted
+ *
+ * We must undo the sem->count down_interruptible() increment while we are
+ * protected by the spinlock in order to make atomic this atomic_inc() with the
+ * atomic_read() in wake_one_more(), otherwise we can race. -arca
+ */
+
+static __inline__ int waking_non_zero_interruptible(struct semaphore *sem,
+						struct task_struct *tsk)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&semaphore_wake_lock, flags);
+	if (sem->sleepers > 0) {
+		sem->sleepers--;
+		ret = 1;
+	} else if (signal_pending(tsk)) {
+		atomic_inc(&sem->count);
+		ret = -EINTR;
+	}
+	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+	return ret;
+}
+
+/*
+ * waking_non_zero_trylock:
+ *	1	failed to lock
+ *	0	got the lock
+ *
+ * We must undo the sem->count down_trylock() increment while we are
+ * protected by the spinlock in order to make atomic this atomic_inc() with the
+ * atomic_read() in wake_one_more(), otherwise we can race. -arca
+ */
+
+static __inline__ int waking_non_zero_trylock(struct semaphore *sem)
+{
+	unsigned long flags;
+	int ret = 1;
+
+	spin_lock_irqsave(&semaphore_wake_lock, flags);
+	if (sem->sleepers <= 0)
+		atomic_inc(&sem->count);
+	else {
+		sem->sleepers--;
+		ret = 0;
+	}
+	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+	return ret;
+}
+
+spinlock_t semaphore_wake_lock;
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to sleep, while the "waking" variable is
+ * incremented when the "up()" code goes to wake up waiting
+ * processes.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * waking_non_zero() (from asm/semaphore.h) must execute
+ * atomically.
+ *
+ * When __up() is called, the count was negative before
+ * incrementing it, and we need to wake up somebody.
+ *
+ * This routine adds one to the count of processes that need to
+ * wake up and exit.  ALL waiting processes actually wake up but
+ * only the one that gets to the "waking" field first will gate
+ * through and acquire the semaphore.  The others will go back
+ * to sleep.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+
+void __up(struct semaphore *sem)
+{
+	wake_one_more(sem);
+	wake_up(&sem->wait);
+}
+
+/*
+ * Perform the "down" function.  Return zero for semaphore acquired,
+ * return negative for signalled out of the function.
+ *
+ * If called from __down, the return is ignored and the wait loop is
+ * not interruptible.  This means that a task waiting on a semaphore
+ * using "down()" cannot be killed until someone does an "up()" on
+ * the semaphore.
+ *
+ * If called from __down_interruptible, the return value gets checked
+ * upon return.  If the return value is negative then the task continues
+ * with the negative value in the return register (it can be tested by
+ * the caller).
+ *
+ * Either form may be used in conjunction with "up()".
+ *
+ */
+
+#define DOWN_VAR				\
+	struct task_struct *tsk = current;	\
+	wait_queue_t wait;			\
+	init_waitqueue_entry(&wait, tsk);
+
+#define DOWN_HEAD(task_state)						\
+									\
+									\
+	tsk->state = (task_state);					\
+	add_wait_queue(&sem->wait, &wait);				\
+									\
+	/*								\
+	 * Ok, we're set up.  sem->count is known to be less than zero	\
+	 * so we must wait.						\
+	 *								\
+	 * We can let go the lock for purposes of waiting.		\
+	 * We re-acquire it after awaking so as to protect		\
+	 * all semaphore operations.					\
+	 *								\
+	 * If "up()" is called before we call waking_non_zero() then	\
+	 * we will catch it right away.  If it is called later then	\
+	 * we will have to go through a wakeup cycle to catch it.	\
+	 *								\
+	 * Multiple waiters contend for the semaphore lock to see	\
+	 * who gets to gate through and who has to wait some more.	\
+	 */								\
+	for (;;) {
+
+#define DOWN_TAIL(task_state)			\
+		tsk->state = (task_state);	\
+	}					\
+	tsk->state = TASK_RUNNING;		\
+	remove_wait_queue(&sem->wait, &wait);
+
+void __sched __down(struct semaphore * sem)
+{
+	DOWN_VAR
+	DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+	if (waking_non_zero(sem))
+		break;
+	schedule();
+	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+}
+
+int __sched __down_interruptible(struct semaphore * sem)
+{
+	int ret = 0;
+	DOWN_VAR
+	DOWN_HEAD(TASK_INTERRUPTIBLE)
+
+	ret = waking_non_zero_interruptible(sem, tsk);
+	if (ret)
+	{
+		if (ret == 1)
+			/* ret != 0 only if we get interrupted -arca */
+			ret = 0;
+		break;
+	}
+	schedule();
+	DOWN_TAIL(TASK_INTERRUPTIBLE)
+	return ret;
+}
+
+int __down_trylock(struct semaphore * sem)
+{
+	return waking_non_zero_trylock(sem);
+}
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c
new file mode 100644
index 0000000..1f5bf5d
--- /dev/null
+++ b/arch/xtensa/kernel/setup.c
@@ -0,0 +1,520 @@
+/*
+ * arch/xtensa/setup.c
+ *
+ * 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  Linus Torvalds
+ * Copyright (C) 2001 - 2005  Tensilica Inc.
+ *
+ * Chris Zankel	<chris@zankel.net>
+ * Joe Taylor	<joe@tensilica.com, joetylr@yahoo.com>
+ * Kevin Chea
+ * Marc Gauthier<marc@tensilica.com> <marc@alumni.uwaterloo.ca>
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/tty.h>
+#include <linux/bootmem.h>
+#include <linux/kernel.h>
+
+#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
+# include <linux/console.h>
+#endif
+
+#ifdef CONFIG_RTC
+# include <linux/timex.h>
+#endif
+
+#ifdef CONFIG_PROC_FS
+# include <linux/seq_file.h>
+#endif
+
+#include <asm/system.h>
+#include <asm/bootparam.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/timex.h>
+#include <asm/platform.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+
+#include <xtensa/config/system.h>
+
+#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
+struct screen_info screen_info = { 0, 24, 0, 0, 0, 80, 0, 0, 0, 24, 1, 16};
+#endif
+
+#ifdef CONFIG_BLK_DEV_FD
+extern struct fd_ops no_fd_ops;
+struct fd_ops *fd_ops;
+#endif
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+extern struct ide_ops no_ide_ops;
+struct ide_ops *ide_ops;
+#endif
+
+extern struct rtc_ops no_rtc_ops;
+struct rtc_ops *rtc_ops;
+
+#ifdef CONFIG_PC_KEYB
+extern struct kbd_ops no_kbd_ops;
+struct kbd_ops *kbd_ops;
+#endif
+
+#ifdef CONFIG_BLK_DEV_INITRD
+extern void *initrd_start;
+extern void *initrd_end;
+extern void *__initrd_start;
+extern void *__initrd_end;
+int initrd_is_mapped = 0;
+extern int initrd_below_start_ok;
+#endif
+
+unsigned char aux_device_present;
+extern unsigned long loops_per_jiffy;
+
+/* Command line specified as configuration option. */
+
+static char command_line[COMMAND_LINE_SIZE];
+
+#ifdef CONFIG_CMDLINE_BOOL
+static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
+#endif
+
+sysmem_info_t __initdata sysmem;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+int initrd_is_mapped;
+#endif
+
+extern void init_mmu(void);
+
+/*
+ * Boot parameter parsing.
+ *
+ * The Xtensa port uses a list of variable-sized tags to pass data to
+ * the kernel. The first tag must be a BP_TAG_FIRST tag for the list
+ * to be recognised. The list is terminated with a zero-sized
+ * BP_TAG_LAST tag.
+ */
+
+typedef struct tagtable {
+	u32 tag;
+	int (*parse)(const bp_tag_t*);
+} tagtable_t;
+
+#define __tagtable(tag, fn) static tagtable_t __tagtable_##fn 		\
+	__attribute__((unused, __section__(".taglist"))) = { tag, fn }
+
+/* parse current tag */
+
+static int __init parse_tag_mem(const bp_tag_t *tag)
+{
+	meminfo_t *mi = (meminfo_t*)(tag->data);
+
+	if (mi->type != MEMORY_TYPE_CONVENTIONAL)
+		return -1;
+
+	if (sysmem.nr_banks >= SYSMEM_BANKS_MAX) {
+		printk(KERN_WARNING
+		       "Ignoring memory bank 0x%08lx size %ldKB\n",
+		       (unsigned long)mi->start,
+		       (unsigned long)mi->end - (unsigned long)mi->start);
+		return -EINVAL;
+	}
+	sysmem.bank[sysmem.nr_banks].type  = mi->type;
+	sysmem.bank[sysmem.nr_banks].start = PAGE_ALIGN(mi->start);
+	sysmem.bank[sysmem.nr_banks].end   = mi->end & PAGE_SIZE;
+	sysmem.nr_banks++;
+
+	return 0;
+}
+
+__tagtable(BP_TAG_MEMORY, parse_tag_mem);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+
+static int __init parse_tag_initrd(const bp_tag_t* tag)
+{
+	meminfo_t* mi;
+	mi = (meminfo_t*)(tag->data);
+	initrd_start = (void*)(mi->start);
+	initrd_end = (void*)(mi->end);
+
+	return 0;
+}
+
+__tagtable(BP_TAG_INITRD, parse_tag_initrd);
+
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+static int __init parse_tag_cmdline(const bp_tag_t* tag)
+{
+	strncpy(command_line, (char*)(tag->data), COMMAND_LINE_SIZE);
+	command_line[COMMAND_LINE_SIZE - 1] = '\0';
+	return 0;
+}
+
+__tagtable(BP_TAG_COMMAND_LINE, parse_tag_cmdline);
+
+static int __init parse_bootparam(const bp_tag_t* tag)
+{
+	extern tagtable_t __tagtable_begin, __tagtable_end;
+	tagtable_t *t;
+
+	/* Boot parameters must start with a BP_TAG_FIRST tag. */
+
+	if (tag->id != BP_TAG_FIRST) {
+		printk(KERN_WARNING "Invalid boot parameters!\n");
+		return 0;
+	}
+
+	tag = (bp_tag_t*)((unsigned long)tag + sizeof(bp_tag_t) + tag->size);
+
+	/* Parse all tags. */
+
+	while (tag != NULL && tag->id != BP_TAG_LAST) {
+	 	for (t = &__tagtable_begin; t < &__tagtable_end; t++) {
+			if (tag->id == t->tag) {
+				t->parse(tag);
+				break;
+			}
+		}
+		if (t == &__tagtable_end)
+			printk(KERN_WARNING "Ignoring tag "
+			       "0x%08x\n", tag->id);
+		tag = (bp_tag_t*)((unsigned long)(tag + 1) + tag->size);
+	}
+
+	return 0;
+}
+
+/*
+ * Initialize architecture. (Early stage)
+ */
+
+void __init init_arch(bp_tag_t *bp_start)
+{
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	initrd_start = &__initrd_start;
+	initrd_end = &__initrd_end;
+#endif
+
+	sysmem.nr_banks = 0;
+
+#ifdef CONFIG_CMDLINE_BOOL
+	strcpy(command_line, default_command_line);
+#endif
+
+	/* Parse boot parameters */
+
+        if (bp_start)
+	  parse_bootparam(bp_start);
+
+	if (sysmem.nr_banks == 0) {
+		sysmem.nr_banks = 1;
+		sysmem.bank[0].start = PLATFORM_DEFAULT_MEM_START;
+		sysmem.bank[0].end = PLATFORM_DEFAULT_MEM_START
+				     + PLATFORM_DEFAULT_MEM_SIZE;
+	}
+
+	/* Early hook for platforms */
+
+	platform_init(bp_start);
+
+	/* Initialize MMU. */
+
+	init_mmu();
+}
+
+/*
+ * Initialize system. Setup memory and reserve regions.
+ */
+
+extern char _end;
+extern char _stext;
+extern char _WindowVectors_text_start;
+extern char _WindowVectors_text_end;
+extern char _DebugInterruptVector_literal_start;
+extern char _DebugInterruptVector_text_end;
+extern char _KernelExceptionVector_literal_start;
+extern char _KernelExceptionVector_text_end;
+extern char _UserExceptionVector_literal_start;
+extern char _UserExceptionVector_text_end;
+extern char _DoubleExceptionVector_literal_start;
+extern char _DoubleExceptionVector_text_end;
+
+void __init setup_arch(char **cmdline_p)
+{
+	extern int mem_reserve(unsigned long, unsigned long, int);
+	extern void bootmem_init(void);
+
+	memcpy(saved_command_line, command_line, COMMAND_LINE_SIZE);
+	saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+	*cmdline_p = command_line;
+
+	/* Reserve some memory regions */
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start < initrd_end) {
+		initrd_is_mapped = mem_reserve(__pa(initrd_start),
+					       __pa(initrd_end), 0);
+		initrd_below_start_ok = 1;
+ 	} else {
+		initrd_start = 0;
+	}
+#endif
+
+	mem_reserve(__pa(&_stext),__pa(&_end), 1);
+
+	mem_reserve(__pa(&_WindowVectors_text_start),
+		    __pa(&_WindowVectors_text_end), 0);
+
+	mem_reserve(__pa(&_DebugInterruptVector_literal_start),
+		    __pa(&_DebugInterruptVector_text_end), 0);
+
+	mem_reserve(__pa(&_KernelExceptionVector_literal_start),
+		    __pa(&_KernelExceptionVector_text_end), 0);
+
+	mem_reserve(__pa(&_UserExceptionVector_literal_start),
+		    __pa(&_UserExceptionVector_text_end), 0);
+
+	mem_reserve(__pa(&_DoubleExceptionVector_literal_start),
+		    __pa(&_DoubleExceptionVector_text_end), 0);
+
+	bootmem_init();
+
+	platform_setup(cmdline_p);
+
+
+	paging_init();
+
+#ifdef CONFIG_VT
+# if defined(CONFIG_VGA_CONSOLE)
+	conswitchp = &vga_con;
+# elif defined(CONFIG_DUMMY_CONSOLE)
+	conswitchp = &dummy_con;
+# endif
+#endif
+
+#if CONFIG_PCI
+	platform_pcibios_init();
+#endif
+}
+
+void machine_restart(char * cmd)
+{
+	platform_restart();
+}
+
+void machine_halt(void)
+{
+	platform_halt();
+	while (1);
+}
+
+void machine_power_off(void)
+{
+	platform_power_off();
+	while (1);
+}
+#ifdef CONFIG_PROC_FS
+
+/*
+ * Display some core information through /proc/cpuinfo.
+ */
+
+static int
+c_show(struct seq_file *f, void *slot)
+{
+	/* high-level stuff */
+	seq_printf(f,"processor\t: 0\n"
+		     "vendor_id\t: Tensilica\n"
+		     "model\t\t: Xtensa " XCHAL_HW_RELEASE_NAME "\n"
+		     "core ID\t\t: " XCHAL_CORE_ID "\n"
+		     "build ID\t: 0x%x\n"
+		     "byte order\t: %s\n"
+ 		     "cpu MHz\t\t: %lu.%02lu\n"
+		     "bogomips\t: %lu.%02lu\n",
+		     XCHAL_BUILD_UNIQUE_ID,
+		     XCHAL_HAVE_BE ?  "big" : "little",
+		     CCOUNT_PER_JIFFY/(1000000/HZ),
+		     (CCOUNT_PER_JIFFY/(10000/HZ)) % 100,
+		     loops_per_jiffy/(500000/HZ),
+		     (loops_per_jiffy/(5000/HZ)) % 100);
+
+	seq_printf(f,"flags\t\t: "
+#if XCHAL_HAVE_NMI
+		     "nmi "
+#endif
+#if XCHAL_HAVE_DEBUG
+		     "debug "
+# if XCHAL_HAVE_OCD
+		     "ocd "
+# endif
+#endif
+#if XCHAL_HAVE_DENSITY
+	    	     "density "
+#endif
+#if XCHAL_HAVE_BOOLEANS
+		     "boolean "
+#endif
+#if XCHAL_HAVE_LOOPS
+		     "loop "
+#endif
+#if XCHAL_HAVE_NSA
+		     "nsa "
+#endif
+#if XCHAL_HAVE_MINMAX
+		     "minmax "
+#endif
+#if XCHAL_HAVE_SEXT
+		     "sext "
+#endif
+#if XCHAL_HAVE_CLAMPS
+		     "clamps "
+#endif
+#if XCHAL_HAVE_MAC16
+		     "mac16 "
+#endif
+#if XCHAL_HAVE_MUL16
+		     "mul16 "
+#endif
+#if XCHAL_HAVE_MUL32
+		     "mul32 "
+#endif
+#if XCHAL_HAVE_MUL32_HIGH
+		     "mul32h "
+#endif
+#if XCHAL_HAVE_FP
+		     "fpu "
+#endif
+		     "\n");
+
+	/* Registers. */
+	seq_printf(f,"physical aregs\t: %d\n"
+		     "misc regs\t: %d\n"
+		     "ibreak\t\t: %d\n"
+		     "dbreak\t\t: %d\n",
+		     XCHAL_NUM_AREGS,
+		     XCHAL_NUM_MISC_REGS,
+		     XCHAL_NUM_IBREAK,
+		     XCHAL_NUM_DBREAK);
+
+
+	/* Interrupt. */
+	seq_printf(f,"num ints\t: %d\n"
+		     "ext ints\t: %d\n"
+		     "int levels\t: %d\n"
+		     "timers\t\t: %d\n"
+		     "debug level\t: %d\n",
+		     XCHAL_NUM_INTERRUPTS,
+		     XCHAL_NUM_EXTINTERRUPTS,
+		     XCHAL_NUM_INTLEVELS,
+		     XCHAL_NUM_TIMERS,
+		     XCHAL_DEBUGLEVEL);
+
+	/* Coprocessors */
+#if XCHAL_HAVE_CP
+	seq_printf(f, "coprocessors\t: %d\n", XCHAL_CP_NUM);
+#else
+	seq_printf(f, "coprocessors\t: none\n");
+#endif
+
+	/* {I,D}{RAM,ROM} and XLMI */
+	seq_printf(f,"inst ROMs\t: %d\n"
+		     "inst RAMs\t: %d\n"
+		     "data ROMs\t: %d\n"
+		     "data RAMs\t: %d\n"
+		     "XLMI ports\t: %d\n",
+		     XCHAL_NUM_IROM,
+		     XCHAL_NUM_IRAM,
+		     XCHAL_NUM_DROM,
+		     XCHAL_NUM_DRAM,
+		     XCHAL_NUM_XLMI);
+
+	/* Cache */
+	seq_printf(f,"icache line size: %d\n"
+		     "icache ways\t: %d\n"
+		     "icache size\t: %d\n"
+		     "icache flags\t: "
+#if XCHAL_ICACHE_LINE_LOCKABLE
+		     "lock"
+#endif
+		     "\n"
+		     "dcache line size: %d\n"
+		     "dcache ways\t: %d\n"
+		     "dcache size\t: %d\n"
+		     "dcache flags\t: "
+#if XCHAL_DCACHE_IS_WRITEBACK
+		     "writeback"
+#endif
+#if XCHAL_DCACHE_LINE_LOCKABLE
+		     "lock"
+#endif
+		     "\n",
+		     XCHAL_ICACHE_LINESIZE,
+		     XCHAL_ICACHE_WAYS,
+		     XCHAL_ICACHE_SIZE,
+		     XCHAL_DCACHE_LINESIZE,
+		     XCHAL_DCACHE_WAYS,
+		     XCHAL_DCACHE_SIZE);
+
+	/* MMU */
+	seq_printf(f,"ASID bits\t: %d\n"
+		     "ASID invalid\t: %d\n"
+		     "ASID kernel\t: %d\n"
+		     "rings\t\t: %d\n"
+		     "itlb ways\t: %d\n"
+		     "itlb AR ways\t: %d\n"
+		     "dtlb ways\t: %d\n"
+		     "dtlb AR ways\t: %d\n",
+		     XCHAL_MMU_ASID_BITS,
+		     XCHAL_MMU_ASID_INVALID,
+		     XCHAL_MMU_ASID_KERNEL,
+		     XCHAL_MMU_RINGS,
+		     XCHAL_ITLB_WAYS,
+		     XCHAL_ITLB_ARF_WAYS,
+		     XCHAL_DTLB_WAYS,
+		     XCHAL_DTLB_ARF_WAYS);
+
+	return 0;
+}
+
+/*
+ * We show only CPU #0 info.
+ */
+static void *
+c_start(struct seq_file *f, loff_t *pos)
+{
+	return (void *) ((*pos == 0) ? (void *)1 : NULL);
+}
+
+static void *
+c_next(struct seq_file *f, void *v, loff_t *pos)
+{
+	return NULL;
+}
+
+static void
+c_stop(struct seq_file *f, void *v)
+{
+}
+
+struct seq_operations cpuinfo_op =
+{
+	start:  c_start,
+	next:   c_next,
+	stop:   c_stop,
+	show:   c_show
+};
+
+#endif /* CONFIG_PROC_FS */
+
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
new file mode 100644
index 0000000..df6e1e1
--- /dev/null
+++ b/arch/xtensa/kernel/signal.c
@@ -0,0 +1,713 @@
+// TODO coprocessor stuff
+/*
+ *  linux/arch/xtensa/kernel/signal.c
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
+ *
+ *  Joe Taylor <joe@tensilica.com>
+ *  Chris Zankel <chris@zankel.net>
+ *
+ *
+ *
+ */
+
+#include <xtensa/config/core.h>
+#include <xtensa/hal.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+#include <linux/personality.h>
+#include <asm/ucontext.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/cacheflush.h>
+
+#define DEBUG_SIG  0
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options,
+			  struct rusage * ru);
+asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
+
+extern struct task_struct *coproc_owners[];
+
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+
+int sys_sigsuspend(struct pt_regs *regs)
+{
+	old_sigset_t mask = (old_sigset_t) regs->areg[3];
+	sigset_t saveset;
+
+	mask &= _BLOCKABLE;
+	spin_lock_irq(&current->sighand->siglock);
+	saveset = current->blocked;
+	siginitset(&current->blocked, mask);
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	regs->areg[2] = -EINTR;
+	while (1) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule();
+		if (do_signal(regs, &saveset))
+			return -EINTR;
+	}
+}
+
+asmlinkage int
+sys_rt_sigsuspend(struct pt_regs *regs)
+{
+	sigset_t *unewset = (sigset_t *) regs->areg[4];
+	size_t sigsetsize = (size_t) regs->areg[3];
+	sigset_t saveset, newset;
+	/* XXX: Don't preclude handling different sized sigset_t's.  */
+	if (sigsetsize != sizeof(sigset_t))
+		return -EINVAL;
+
+	if (copy_from_user(&newset, unewset, sizeof(newset)))
+		return -EFAULT;
+	sigdelsetmask(&newset, ~_BLOCKABLE);
+	spin_lock_irq(&current->sighand->siglock);
+	saveset = current->blocked;
+	current->blocked = newset;
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	regs->areg[2] = -EINTR;
+	while (1) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule();
+		if (do_signal(regs, &saveset))
+			return -EINTR;
+	}
+}
+
+asmlinkage int
+sys_sigaction(int sig, const struct old_sigaction *act,
+	      struct old_sigaction *oact)
+{
+	struct k_sigaction new_ka, old_ka;
+	int ret;
+
+	if (act) {
+		old_sigset_t mask;
+		if (verify_area(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;
+		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
+		__get_user(mask, &act->sa_mask);
+		siginitset(&new_ka.sa.sa_mask, mask);
+	}
+
+	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+	if (!ret && oact) {
+		if (verify_area(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;
+		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+	}
+
+	return ret;
+}
+
+asmlinkage int
+sys_sigaltstack(struct pt_regs *regs)
+{
+	const stack_t *uss = (stack_t *) regs->areg[4];
+	stack_t *uoss = (stack_t *) regs->areg[3];
+
+	if (regs->depc > 64)
+		panic ("Double exception sys_sigreturn\n");
+
+
+	return do_sigaltstack(uss, uoss, regs->areg[1]);
+}
+
+
+/*
+ * Do a signal return; undo the signal stack.
+ */
+
+struct sigframe
+{
+	struct sigcontext sc;
+	struct _cpstate cpstate;
+	unsigned long extramask[_NSIG_WORDS-1];
+	unsigned char retcode[6];
+	unsigned int reserved[4]; /* Reserved area for chaining */
+	unsigned int window[4]; /* Window of 4 registers for initial context */
+};
+
+struct rt_sigframe
+{
+	struct siginfo info;
+	struct ucontext uc;
+	struct _cpstate cpstate;
+	unsigned char retcode[6];
+	unsigned int reserved[4]; /* Reserved area for chaining */
+	unsigned int window[4]; /* Window of 4 registers for initial context */
+};
+
+extern void release_all_cp (struct task_struct *);
+
+
+// FIXME restore_cpextra
+static inline int
+restore_cpextra (struct _cpstate *buf)
+{
+#if 0
+	/* The signal handler may have used coprocessors in which
+	 * case they are still enabled.  We disable them to force a
+	 * reloading of the original task's CP state by the lazy
+	 * context-switching mechanisms of CP exception handling.
+	 * Also, we essentially discard any coprocessor state that the
+	 * signal handler created. */
+
+	struct task_struct *tsk = current;
+	release_all_cp(tsk);
+	return __copy_from_user(tsk->thread.cpextra, buf, TOTAL_CPEXTRA_SIZE);
+#endif
+	return 0;
+}
+
+/* Note: We don't copy double exception 'tregs', we have to finish double exc. first before we return to signal handler! This dbl.exc.handler might cause another double exception, but I think we are fine as the situation is the same as if we had returned to the signal handerl and got an interrupt immediately...
+ */
+
+
+static int
+restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
+{
+	struct thread_struct *thread;
+	unsigned int err = 0;
+	unsigned long ps;
+	struct _cpstate *buf;
+
+#define COPY(x)	err |= __get_user(regs->x, &sc->sc_##x)
+	COPY(pc);
+	COPY(depc);
+	COPY(wmask);
+	COPY(lbeg);
+	COPY(lend);
+	COPY(lcount);
+	COPY(sar);
+	COPY(windowbase);
+	COPY(windowstart);
+#undef COPY
+
+	/* For PS, restore only PS.CALLINC.
+	 * Assume that all other bits are either the same as for the signal
+	 * handler, or the user mode value doesn't matter (e.g. PS.OWB).
+	 */
+	err |= __get_user(ps, &sc->sc_ps);
+	regs->ps = (regs->ps & ~XCHAL_PS_CALLINC_MASK)
+		| (ps & XCHAL_PS_CALLINC_MASK);
+
+	/* Additional corruption checks */
+
+	if ((regs->windowbase >= (XCHAL_NUM_AREGS/4))
+	|| ((regs->windowstart & ~((1<<(XCHAL_NUM_AREGS/4)) - 1)) != 0) )
+		err = 1;
+	if ((regs->lcount > 0)
+	&& ((regs->lbeg > TASK_SIZE) || (regs->lend > TASK_SIZE)) )
+		err = 1;
+
+	/* Restore extended register state.
+	 * See struct thread_struct in processor.h.
+	 */
+	thread = &current->thread;
+
+	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)))
+			goto badframe;
+		err |= restore_cpextra(buf);
+	}
+
+	regs->syscall = -1;		/* disable syscall checks */
+	return err;
+
+badframe:
+	return 1;
+}
+
+static inline void
+flush_my_cpstate(struct task_struct *tsk)
+{
+	unsigned long flags;
+	local_irq_save(flags);
+
+#if 0	// FIXME
+	for (i = 0; i < XCHAL_CP_NUM; i++) {
+		if (tsk == coproc_owners[i]) {
+			xthal_validate_cp(i);
+			xthal_save_cpregs(tsk->thread.cpregs_ptr[i], i);
+
+			/* Invalidate and "disown" the cp to allow
+			 * callers the chance to reset cp state in the
+			 * task_struct. */
+
+			xthal_invalidate_cp(i);
+			coproc_owners[i] = 0;
+		}
+	}
+#endif
+	local_irq_restore(flags);
+}
+
+/* Return codes:
+	0:  nothing saved
+	1:  stuff to save, successful
+       -1:  stuff to save, error happened
+*/
+static int
+save_cpextra (struct _cpstate *buf)
+{
+#if (XCHAL_EXTRA_SA_SIZE == 0) && (XCHAL_CP_NUM == 0)
+	return 0;
+#else
+
+	/* FIXME: If a task has never used a coprocessor, there is
+	 * no need to save and restore anything.  Tracking this
+	 * information would allow us to optimize this section.
+	 * Perhaps we can use current->used_math or (current->flags &
+	 * PF_USEDFPU) or define a new field in the thread
+	 * structure. */
+
+	/* We flush any live, task-owned cp state to the task_struct,
+	 * then copy it all to the sigframe.  Then we clear all
+	 * cp/extra state in the task_struct, effectively
+	 * clearing/resetting all cp/extra state for the signal
+	 * handler (cp-exception handling will load these new values
+	 * into the cp/extra registers.)  This step is important for
+	 * things like a floating-point cp, where the OS must reset
+	 * the FCR to the default rounding mode. */
+
+	int err = 0;
+	struct task_struct *tsk = current;
+
+	flush_my_cpstate(tsk);
+	/* Note that we just copy everything: 'extra' and 'cp' state together.*/
+	err |= __copy_to_user(buf, tsk->thread.cp_save, XTENSA_CP_EXTRA_SIZE);
+	memset(tsk->thread.cp_save, 0, XTENSA_CP_EXTRA_SIZE);
+
+#if (XTENSA_CP_EXTRA_SIZE == 0)
+#error Sanity check on memset above, cpextra_size should not be zero.
+#endif
+
+	return err ? -1 : 1;
+#endif
+}
+
+static int
+setup_sigcontext(struct sigcontext *sc, struct _cpstate *cpstate,
+		 struct pt_regs *regs, unsigned long mask)
+{
+	struct thread_struct *thread;
+	int err = 0;
+
+//printk("setup_sigcontext\n");
+#define COPY(x)	err |= __put_user(regs->x, &sc->sc_##x)
+	COPY(pc);
+	COPY(ps);
+	COPY(depc);
+	COPY(wmask);
+	COPY(lbeg);
+	COPY(lend);
+	COPY(lcount);
+	COPY(sar);
+	COPY(windowbase);
+	COPY(windowstart);
+#undef COPY
+
+	/* Save extended register state.
+	 * See struct thread_struct in processor.h.
+	 */
+	thread = &current->thread;
+	err |= __copy_to_user (sc->sc_areg, regs->areg, XCHAL_NUM_AREGS * 4);
+	err |= save_cpextra(cpstate);
+	err |= __put_user(err ? NULL : cpstate, &sc->sc_cpstate);
+	/* non-iBCS2 extensions.. */
+	err |= __put_user(mask, &sc->oldmask);
+
+	return err;
+}
+
+asmlinkage int sys_sigreturn(struct pt_regs *regs)
+{
+	struct sigframe *frame = (struct sigframe *)regs->areg[1];
+	sigset_t set;
+	if (regs->depc > 64)
+		panic ("Double exception sys_sigreturn\n");
+
+	if (verify_area(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))
+		goto badframe;
+	return regs->areg[2];
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
+{
+	struct rt_sigframe *frame = (struct rt_sigframe *)regs->areg[1];
+	sigset_t set;
+	stack_t st;
+	int ret;
+	if (regs->depc > 64)
+	{
+		printk("!!!!!!! DEPC !!!!!!!\n");
+		return 0;
+	}
+
+	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+
+	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+		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))
+		goto badframe;
+	ret = regs->areg[2];
+
+	if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+		goto badframe;
+	/* It is more difficult to avoid calling this function than to
+	   call it and ignore errors.  */
+	do_sigaltstack(&st, NULL, regs->areg[1]);
+
+	return ret;
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+/*
+ * Set up a signal frame.
+ */
+
+/*
+ * Determine which stack to use..
+ */
+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))
+		sp = current->sas_ss_sp + current->sas_ss_size;
+
+	return (void *)((sp - frame_size) & -16ul);
+}
+
+#define USE_SIGRETURN		0
+#define USE_RT_SIGRETURN	1
+
+static int
+gen_return_code(unsigned char *codemem, unsigned int use_rt_sigreturn)
+{
+	unsigned int retcall;
+	int err = 0;
+
+#if 0
+	/* Ignoring SA_RESTORER for now; it's supposed to be obsolete,
+	 * and the xtensa glibc doesn't use it.
+	 */
+	if (ka->sa.sa_flags & SA_RESTORER) {
+		regs->pr = (unsigned long) ka->sa.sa_restorer;
+	} else
+#endif /* 0 */
+	{
+
+#if (__NR_sigreturn > 255) || (__NR_rt_sigreturn > 255)
+
+/* The 12-bit immediate is really split up within the 24-bit MOVI
+ * instruction.  As long as the above system call numbers fit within
+ * 8-bits, the following code works fine. See the Xtensa ISA for
+ * details.
+ */
+
+#error Generating the MOVI instruction below breaks!
+#endif
+
+		retcall = use_rt_sigreturn ? __NR_rt_sigreturn : __NR_sigreturn;
+
+#ifdef __XTENSA_EB__   /* Big Endian version */
+		/* Generate instruction:  MOVI a2, retcall */
+		err |= __put_user(0x22, &codemem[0]);
+		err |= __put_user(0x0a, &codemem[1]);
+		err |= __put_user(retcall, &codemem[2]);
+		/* Generate instruction:  SYSCALL */
+		err |= __put_user(0x00, &codemem[3]);
+		err |= __put_user(0x05, &codemem[4]);
+		err |= __put_user(0x00, &codemem[5]);
+
+#elif defined __XTENSA_EL__   /* Little Endian version */
+		/* Generate instruction:  MOVI a2, retcall */
+		err |= __put_user(0x22, &codemem[0]);
+		err |= __put_user(0xa0, &codemem[1]);
+		err |= __put_user(retcall, &codemem[2]);
+		/* Generate instruction:  SYSCALL */
+		err |= __put_user(0x00, &codemem[3]);
+		err |= __put_user(0x50, &codemem[4]);
+		err |= __put_user(0x00, &codemem[5]);
+#else
+#error Must use compiler for Xtensa processors.
+#endif
+	}
+
+	/* Flush generated code out of the data cache */
+
+	if (err == 0)
+		__flush_invalidate_cache_range((unsigned long)codemem, 6UL);
+
+	return err;
+}
+
+static void
+set_thread_state(struct pt_regs *regs, void *stack, unsigned char *retaddr,
+	void *handler, unsigned long arg1, void *arg2, void *arg3)
+{
+	/* Set up registers for signal handler */
+	start_thread(regs, (unsigned long) handler, (unsigned long) stack);
+
+	/* Set up a stack frame for a call4
+	 * Note: PS.CALLINC is set to one by start_thread
+	 */
+	regs->areg[4] = (((unsigned long) retaddr) & 0x3fffffff) | 0x40000000;
+	regs->areg[6] = arg1;
+	regs->areg[7] = (unsigned long) arg2;
+	regs->areg[8] = (unsigned long) arg3;
+}
+
+static void setup_frame(int sig, struct k_sigaction *ka,
+			sigset_t *set, struct pt_regs *regs)
+{
+	struct sigframe *frame;
+	int err = 0;
+	int signal;
+
+	frame = get_sigframe(ka, regs->areg[1], sizeof(*frame));
+	if (regs->depc > 64)
+	{
+		printk("!!!!!!! DEPC !!!!!!!\n");
+		return;
+	}
+
+
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		goto give_sigsegv;
+
+	signal = current_thread_info()->exec_domain
+		&& current_thread_info()->exec_domain->signal_invmap
+		&& sig < 32
+		? current_thread_info()->exec_domain->signal_invmap[sig]
+		: sig;
+
+	err |= setup_sigcontext(&frame->sc, &frame->cpstate, regs, set->sig[0]);
+
+	if (_NSIG_WORDS > 1) {
+		err |= __copy_to_user(frame->extramask, &set->sig[1],
+				      sizeof(frame->extramask));
+	}
+
+	/* Create sys_sigreturn syscall in stack frame */
+	err |= gen_return_code(frame->retcode, USE_SIGRETURN);
+
+	if (err)
+		goto give_sigsegv;
+
+	/* Create signal handler execution context.
+	 * Return context not modified until this point.
+	 */
+	set_thread_state(regs, frame, frame->retcode,
+		ka->sa.sa_handler, signal, &frame->sc, NULL);
+
+	/* Set access mode to USER_DS.  Nomenclature is outdated, but
+	 * functionality is used in uaccess.h
+	 */
+	set_fs(USER_DS);
+
+
+#if DEBUG_SIG
+	printk("SIG deliver (%s:%d): signal=%d sp=%p pc=%08x\n",
+		current->comm, current->pid, signal, frame, regs->pc);
+#endif
+
+	return;
+
+give_sigsegv:
+	if (sig == SIGSEGV)
+		ka->sa.sa_handler = SIG_DFL;
+	force_sig(SIGSEGV, current);
+}
+
+static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+			   sigset_t *set, struct pt_regs *regs)
+{
+	struct rt_sigframe *frame;
+	int err = 0;
+	int signal;
+
+	frame = get_sigframe(ka, regs->areg[1], sizeof(*frame));
+	if (regs->depc > 64)
+		panic ("Double exception sys_sigreturn\n");
+
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		goto give_sigsegv;
+
+	signal = current_thread_info()->exec_domain
+		&& current_thread_info()->exec_domain->signal_invmap
+		&& sig < 32
+		? current_thread_info()->exec_domain->signal_invmap[sig]
+		: sig;
+
+	err |= copy_siginfo_to_user(&frame->info, info);
+
+	/* Create the ucontext.  */
+	err |= __put_user(0, &frame->uc.uc_flags);
+	err |= __put_user(0, &frame->uc.uc_link);
+	err |= __put_user((void *)current->sas_ss_sp,
+			  &frame->uc.uc_stack.ss_sp);
+	err |= __put_user(sas_ss_flags(regs->areg[1]),
+			  &frame->uc.uc_stack.ss_flags);
+	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+	err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->cpstate,
+			        regs, set->sig[0]);
+	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
+	/* Create sys_rt_sigreturn syscall in stack frame */
+	err |= gen_return_code(frame->retcode, USE_RT_SIGRETURN);
+
+	if (err)
+		goto give_sigsegv;
+
+	/* Create signal handler execution context.
+	 * Return context not modified until this point.
+	 */
+	set_thread_state(regs, frame, frame->retcode,
+		ka->sa.sa_handler, signal, &frame->info, &frame->uc);
+
+	/* Set access mode to USER_DS.  Nomenclature is outdated, but
+	 * functionality is used in uaccess.h
+	 */
+	set_fs(USER_DS);
+
+#if DEBUG_SIG
+	printk("SIG rt deliver (%s:%d): signal=%d sp=%p pc=%08x\n",
+		current->comm, current->pid, signal, frame, regs->pc);
+#endif
+
+	return;
+
+give_sigsegv:
+	if (sig == SIGSEGV)
+		ka->sa.sa_handler = SIG_DFL;
+	force_sig(SIGSEGV, current);
+}
+
+
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ *
+ * Note that we go through the signals twice: once to check the signals that
+ * the kernel can handle, and then we build all the user-level signal handling
+ * stack-frames in one go after that.
+ */
+int do_signal(struct pt_regs *regs, sigset_t *oldset)
+{
+	siginfo_t info;
+	int signr;
+	struct k_sigaction ka;
+
+	if (!oldset)
+		oldset = &current->blocked;
+
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+
+	/* Are we from a system call? */
+	if (regs->syscall >= 0) {
+		/* If so, check system call restarting.. */
+		switch (regs->areg[2]) {
+			case ERESTARTNOHAND:
+			case ERESTART_RESTARTBLOCK:
+				regs->areg[2] = -EINTR;
+				break;
+
+			case ERESTARTSYS:
+				if (!(ka.sa.sa_flags & SA_RESTART)) {
+					regs->areg[2] = -EINTR;
+					break;
+				}
+			/* fallthrough */
+			case ERESTARTNOINTR:
+				regs->areg[2] = regs->syscall;
+				regs->pc -= 3;
+		}
+	}
+
+	if (signr == 0)
+		return 0;		/* no signals delivered */
+
+	/* Whee!  Actually deliver the signal.  */
+
+	/* Set up the stack frame */
+	if (ka.sa.sa_flags & SA_SIGINFO)
+		setup_rt_frame(signr, &ka, &info, oldset, regs);
+	else
+		setup_frame(signr, &ka, oldset, regs);
+
+	if (ka.sa.sa_flags & SA_ONESHOT)
+		ka.sa.sa_handler = SIG_DFL;
+
+	if (!(ka.sa.sa_flags & SA_NODEFER)) {
+		spin_lock_irq(&current->sighand->siglock);
+		sigorsets(&current->blocked, &current->blocked, &ka.sa.sa_mask);
+		sigaddset(&current->blocked, signr);
+		recalc_sigpending();
+		spin_unlock_irq(&current->sighand->siglock);
+	}
+	return 1;
+}
diff --git a/arch/xtensa/kernel/syscalls.c b/arch/xtensa/kernel/syscalls.c
new file mode 100644
index 0000000..abc8ed6
--- /dev/null
+++ b/arch/xtensa/kernel/syscalls.c
@@ -0,0 +1,418 @@
+/*
+ * arch/xtensa/kernel/syscall.c
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ * Copyright (C) 2000 Silicon Graphics, Inc.
+ * Copyright (C) 1995 - 2000 by Ralf Baechle
+ *
+ * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
+ * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca>
+ * Chris Zankel <chris@zankel.net>
+ * Kevin Chea
+ *
+ */
+
+#define DEBUG	0
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/mman.h>
+#include <linux/sched.h>
+#include <linux/file.h>
+#include <linux/slab.h>
+#include <linux/utsname.h>
+#include <linux/unistd.h>
+#include <linux/stringify.h>
+#include <linux/syscalls.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/errno.h>
+#include <asm/ptrace.h>
+#include <asm/signal.h>
+#include <asm/uaccess.h>
+#include <asm/hardirq.h>
+#include <asm/mman.h>
+#include <asm/shmparam.h>
+#include <asm/page.h>
+#include <asm/ipc.h>
+
+extern void do_syscall_trace(void);
+typedef int (*syscall_t)(void *a0,...);
+extern int (*do_syscalls)(struct pt_regs *regs, syscall_t fun,
+				     int narg);
+extern syscall_t sys_call_table[];
+extern unsigned char sys_narg_table[];
+
+/*
+ * sys_pipe() is the normal C calling standard for creating a pipe. It's not
+ * the way unix traditional does this, though.
+ */
+
+int sys_pipe(int __user *userfds)
+{
+	int fd[2];
+	int error;
+
+	error = do_pipe(fd);
+	if (!error) {
+		if (copy_to_user(userfds, fd, 2 * sizeof(int)))
+			error = -EFAULT;
+	}
+	return error;
+}
+
+/*
+ * Common code for old and new mmaps.
+ */
+
+static inline long do_mmap2(unsigned long addr, unsigned long len,
+    			    unsigned long prot, unsigned long flags,
+			    unsigned long fd, unsigned long pgoff)
+{
+	int error = -EBADF;
+	struct file * file = NULL;
+
+	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+	if (!(flags & MAP_ANONYMOUS)) {
+		file = fget(fd);
+		if (!file)
+			goto out;
+	}
+
+	down_write(&current->mm->mmap_sem);
+	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+	up_write(&current->mm->mmap_sem);
+
+	if (file)
+		fput(file);
+out:
+	return error;
+}
+
+unsigned long old_mmap(unsigned long addr, size_t len, int prot,
+		       int flags, int fd, off_t offset)
+{
+	return do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+}
+
+long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
+	       unsigned long flags, unsigned long fd, unsigned long pgoff)
+{
+	return do_mmap2(addr, len, prot, flags, fd, pgoff);
+}
+
+int sys_fork(struct pt_regs *regs)
+{
+	return do_fork(SIGCHLD, regs->areg[1], regs, 0, NULL, NULL);
+}
+
+int sys_vfork(struct pt_regs *regs)
+{
+	return do_fork(CLONE_VFORK|CLONE_VM|SIGCHLD, regs->areg[1],
+		       regs, 0, NULL, NULL);
+}
+
+int sys_clone(struct pt_regs *regs)
+{
+	unsigned long clone_flags;
+	unsigned long newsp;
+	int __user *parent_tidptr, *child_tidptr;
+	clone_flags = regs->areg[4];
+	newsp = regs->areg[3];
+	parent_tidptr = (int __user *)regs->areg[5];
+	child_tidptr = (int __user *)regs->areg[6];
+	if (!newsp)
+		newsp = regs->areg[1];
+	return do_fork(clone_flags,newsp,regs,0,parent_tidptr,child_tidptr);
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+
+int sys_execve(struct pt_regs *regs)
+{
+	int error;
+	char * filename;
+
+	filename = getname((char *) (long)regs->areg[5]);
+	error = PTR_ERR(filename);
+	if (IS_ERR(filename))
+		goto out;
+	error = do_execve(filename, (char **) (long)regs->areg[3],
+	                  (char **) (long)regs->areg[4], regs);
+	putname(filename);
+
+out:
+	return error;
+}
+
+int sys_uname(struct old_utsname * name)
+{
+	if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
+		return 0;
+	return -EFAULT;
+}
+
+int sys_olduname(struct oldold_utsname * name)
+{
+	int error;
+
+	if (!name)
+		return -EFAULT;
+	if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
+		return -EFAULT;
+
+	error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
+	error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
+	error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
+	error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
+	error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
+	error -= __put_user(0,name->release+__OLD_UTS_LEN);
+	error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
+	error -= __put_user(0,name->version+__OLD_UTS_LEN);
+	error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
+	error -= __put_user(0,name->machine+__OLD_UTS_LEN);
+
+	return error ? -EFAULT : 0;
+}
+
+
+/*
+ * Build the string table for the builtin "poor man's strace".
+ */
+
+#if DEBUG
+#define SYSCALL(fun, narg) #fun,
+static char *sfnames[] = {
+#include "syscalls.h"
+};
+#undef SYS
+#endif
+
+void system_call (struct pt_regs *regs)
+{
+	syscall_t syscall;
+	unsigned long parm0, parm1, parm2, parm3, parm4, parm5;
+	int nargs, res;
+	unsigned int syscallnr;
+	int ps;
+
+#if DEBUG
+	int i;
+	unsigned long parms[6];
+	char *sysname;
+#endif
+
+	regs->syscall = regs->areg[2];
+
+	do_syscall_trace();
+
+	/* Have to load after syscall_trace because strace
+	 * sometimes changes regs->syscall.
+	 */
+	syscallnr = regs->syscall;
+
+	parm0 = parm1 = parm2 = parm3 = parm4 = parm5 = 0;
+
+	/* Restore interrupt level to syscall invoker's.
+	 * If this were in assembly, we wouldn't disable
+	 * interrupts in the first place:
+	 */
+	local_save_flags (ps);
+	local_irq_restore((ps & ~XCHAL_PS_INTLEVEL_MASK) |
+			  (regs->ps & XCHAL_PS_INTLEVEL_MASK) );
+
+	if (syscallnr > __NR_Linux_syscalls) {
+		regs->areg[2] = -ENOSYS;
+		return;
+	}
+
+	syscall = sys_call_table[syscallnr];
+	nargs = sys_narg_table[syscallnr];
+
+	if (syscall == NULL) {
+		regs->areg[2] = -ENOSYS;
+		return;
+	}
+
+	/* There shouldn't be more than six arguments in the table! */
+
+	if (nargs > 6)
+		panic("Internal error - too many syscall arguments (%d)!\n",
+		      nargs);
+
+	/* Linux takes system-call arguments in registers.  The ABI
+         * and Xtensa software conventions require the system-call
+         * number in a2.  If an argument exists in a2, we move it to
+         * the next available register.  Note that for improved
+         * efficiency, we do NOT shift all parameters down one
+         * register to maintain the original order.
+	 *
+         * At best case (zero arguments), we just write the syscall
+         * number to a2.  At worst case (1 to 6 arguments), we move
+         * the argument in a2 to the next available register, then
+         * write the syscall number to a2.
+	 *
+         * For clarity, the following truth table enumerates all
+         * possibilities.
+	 *
+         * arguments	syscall number	arg0, arg1, arg2, arg3, arg4, arg5
+         * ---------	--------------	----------------------------------
+	 *	0	      a2
+	 *	1	      a2	a3
+	 *	2	      a2	a4,   a3
+	 *	3	      a2	a5,   a3,   a4
+	 *	4	      a2	a6,   a3,   a4,   a5
+	 *	5	      a2	a7,   a3,   a4,   a5,   a6
+	 *	6	      a2	a8,   a3,   a4,   a5,   a6,   a7
+	 */
+	if (nargs) {
+		parm0 = regs->areg[nargs+2];
+		parm1 = regs->areg[3];
+		parm2 = regs->areg[4];
+		parm3 = regs->areg[5];
+		parm4 = regs->areg[6];
+		parm5 = regs->areg[7];
+	} else /* nargs == 0 */
+		parm0 = (unsigned long) regs;
+
+#if DEBUG
+	parms[0] = parm0;
+	parms[1] = parm1;
+	parms[2] = parm2;
+	parms[3] = parm3;
+	parms[4] = parm4;
+	parms[5] = parm5;
+
+	sysname = sfnames[syscallnr];
+	if (strncmp(sysname, "sys_", 4) == 0)
+		sysname = sysname + 4;
+
+	printk("\017SYSCALL:I:%x:%d:%s  %s(", regs->pc, current->pid,
+	       current->comm, sysname);
+	for (i = 0; i < nargs; i++)
+		printk((i>0) ? ", %#lx" : "%#lx", parms[i]);
+	printk(")\n");
+#endif
+
+	res = syscall((void *)parm0, parm1, parm2, parm3, parm4, parm5);
+
+#if DEBUG
+	printk("\017SYSCALL:O:%d:%s  %s(",current->pid, current->comm, sysname);
+	for (i = 0; i < nargs; i++)
+		printk((i>0) ? ", %#lx" : "%#lx", parms[i]);
+	if (res < 4096)
+		printk(") = %d\n", res);
+	else
+		printk(") = %#x\n", res);
+#endif /* DEBUG */
+
+	regs->areg[2] = res;
+	do_syscall_trace();
+}
+
+/*
+ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+ *
+ * This is really horribly ugly.
+ */
+
+int sys_ipc (uint call, int first, int second,
+			int third, void __user *ptr, long fifth)
+{
+	int version, ret;
+
+	version = call >> 16; /* hack for backward compatibility */
+	call &= 0xffff;
+	ret = -ENOSYS;
+
+	switch (call) {
+	case SEMOP:
+		ret = sys_semtimedop (first, (struct sembuf __user *)ptr,
+				     second, NULL);
+		break;
+
+	case SEMTIMEDOP:
+		ret = sys_semtimedop (first, (struct sembuf __user *)ptr,
+				      second, (const struct timespec *) fifth);
+		break;
+
+	case SEMGET:
+		ret = sys_semget (first, second, third);
+		break;
+
+	case SEMCTL: {
+		union semun fourth;
+
+		if (ptr && !get_user(fourth.__pad, (void *__user *) ptr))
+			ret = sys_semctl (first, second, third, fourth);
+		break;
+		}
+
+	case MSGSND:
+		ret = sys_msgsnd (first, (struct msgbuf __user*) ptr,
+				  second, third);
+		break;
+
+	case MSGRCV:
+		switch (version) {
+		case 0: {
+			struct ipc_kludge tmp;
+
+			if (ptr && !copy_from_user(&tmp,
+					   (struct ipc_kludge *) ptr,
+					   sizeof (tmp)))
+				ret = sys_msgrcv (first, tmp.msgp, second,
+						  tmp.msgtyp, third);
+			break;
+			}
+
+		default:
+			ret = sys_msgrcv (first, (struct msgbuf __user *) ptr,
+					  second, 0, third);
+			break;
+		}
+		break;
+
+	case MSGGET:
+		ret = sys_msgget ((key_t) first, second);
+		break;
+
+	case MSGCTL:
+		ret = sys_msgctl (first, second, (struct msqid_ds __user*) ptr);
+		break;
+
+	case SHMAT: {
+		ulong raddr;
+		ret = do_shmat (first, (char __user *) ptr, second, &raddr);
+
+		if (!ret)
+			ret = put_user (raddr, (ulong __user *) third);
+
+		break;
+		}
+
+	case SHMDT:
+		ret = sys_shmdt ((char __user *)ptr);
+		break;
+
+	case SHMGET:
+		ret = sys_shmget (first, second, third);
+		break;
+
+	case SHMCTL:
+		ret = sys_shmctl (first, second, (struct shmid_ds __user*) ptr);
+		break;
+	}
+	return ret;
+}
+
diff --git a/arch/xtensa/kernel/syscalls.h b/arch/xtensa/kernel/syscalls.h
new file mode 100644
index 0000000..5b3f75f
--- /dev/null
+++ b/arch/xtensa/kernel/syscalls.h
@@ -0,0 +1,248 @@
+/*
+ * arch/xtensa/kernel/syscalls.h
+ *
+ * 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, 1998 by Ralf Baechle
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ *
+ * Changes by Joe Taylor <joe@tensilica.com>
+ */
+
+/*
+ * This file is being included twice - once to build a list of all
+ * syscalls and once to build a table of how many arguments each syscall
+ * accepts.  Syscalls that receive a pointer to the saved registers are
+ * marked as having zero arguments.
+ *
+ * The binary compatibility calls are in a separate list.
+ *
+ * Entry '0' used to be system_call.  It's removed to disable indirect
+ * system calls for now so user tasks can't recurse.  See mips'
+ * sys_syscall for a comparable example.
+ */
+
+SYSCALL(0, 0)		                /* 00 */
+
+SYSCALL(sys_exit, 1)
+SYSCALL(sys_fork, 0)
+SYSCALL(sys_read, 3)
+SYSCALL(sys_write, 3)
+SYSCALL(sys_open, 3)			/* 05 */
+SYSCALL(sys_close, 1)
+SYSCALL(sys_waitpid, 3)
+SYSCALL(sys_creat, 2)
+SYSCALL(sys_link, 2)
+SYSCALL(sys_unlink, 1)			/* 10 */
+SYSCALL(sys_execve, 0)
+SYSCALL(sys_chdir, 1)
+SYSCALL(sys_time, 1)
+SYSCALL(sys_mknod, 3)
+SYSCALL(sys_chmod, 2)			/* 15 */
+SYSCALL(sys_lchown, 3)
+SYSCALL(sys_ni_syscall, 0)
+SYSCALL(sys_stat, 2)
+SYSCALL(sys_lseek, 3)
+SYSCALL(sys_getpid, 0)			/* 20 */
+SYSCALL(sys_mount, 5)
+SYSCALL(sys_oldumount, 1)
+SYSCALL(sys_setuid, 1)
+SYSCALL(sys_getuid, 0)
+SYSCALL(sys_stime, 1)			/* 25 */
+SYSCALL(sys_ptrace, 4)
+SYSCALL(sys_alarm, 1)
+SYSCALL(sys_fstat, 2)
+SYSCALL(sys_pause, 0)
+SYSCALL(sys_utime, 2)			/* 30 */
+SYSCALL(sys_ni_syscall, 0)
+SYSCALL(sys_ni_syscall, 0)
+SYSCALL(sys_access, 2)
+SYSCALL(sys_nice, 1)
+SYSCALL(sys_ni_syscall, 0)		/* 35 */
+SYSCALL(sys_sync, 0)
+SYSCALL(sys_kill, 2)
+SYSCALL(sys_rename, 2)
+SYSCALL(sys_mkdir, 2)
+SYSCALL(sys_rmdir, 1)			/* 40 */
+SYSCALL(sys_dup, 1)
+SYSCALL(sys_pipe, 1)
+SYSCALL(sys_times, 1)
+SYSCALL(sys_ni_syscall, 0)
+SYSCALL(sys_brk, 1)			/* 45 */
+SYSCALL(sys_setgid, 1)
+SYSCALL(sys_getgid, 0)
+SYSCALL(sys_ni_syscall, 0)		/* was signal(2) */
+SYSCALL(sys_geteuid, 0)
+SYSCALL(sys_getegid, 0)			/* 50 */
+SYSCALL(sys_acct, 1)
+SYSCALL(sys_umount, 2)
+SYSCALL(sys_ni_syscall, 0)
+SYSCALL(sys_ioctl, 3)
+SYSCALL(sys_fcntl, 3)			/* 55 */
+SYSCALL(sys_ni_syscall, 2)
+SYSCALL(sys_setpgid, 2)
+SYSCALL(sys_ni_syscall, 0)
+SYSCALL(sys_olduname, 1)
+SYSCALL(sys_umask, 1)			/* 60 */
+SYSCALL(sys_chroot, 1)
+SYSCALL(sys_ustat, 2)
+SYSCALL(sys_dup2, 2)
+SYSCALL(sys_getppid, 0)
+SYSCALL(sys_getpgrp, 0)			/* 65 */
+SYSCALL(sys_setsid, 0)
+SYSCALL(sys_sigaction, 3)
+SYSCALL(sys_sgetmask, 0)
+SYSCALL(sys_ssetmask, 1)
+SYSCALL(sys_setreuid, 2)		/* 70 */
+SYSCALL(sys_setregid, 2)
+SYSCALL(sys_sigsuspend, 0)
+SYSCALL(sys_sigpending, 1)
+SYSCALL(sys_sethostname, 2)
+SYSCALL(sys_setrlimit, 2)		/* 75 */
+SYSCALL(sys_getrlimit, 2)
+SYSCALL(sys_getrusage, 2)
+SYSCALL(sys_gettimeofday, 2)
+SYSCALL(sys_settimeofday, 2)
+SYSCALL(sys_getgroups, 2)		/* 80 */
+SYSCALL(sys_setgroups, 2)
+SYSCALL(sys_ni_syscall, 0)		 /* old_select */
+SYSCALL(sys_symlink, 2)
+SYSCALL(sys_lstat, 2)
+SYSCALL(sys_readlink, 3)		/* 85 */
+SYSCALL(sys_uselib, 1)
+SYSCALL(sys_swapon, 2)
+SYSCALL(sys_reboot, 3)
+SYSCALL(old_readdir, 3)
+SYSCALL(old_mmap, 6)			/* 90 */
+SYSCALL(sys_munmap, 2)
+SYSCALL(sys_truncate, 2)
+SYSCALL(sys_ftruncate, 2)
+SYSCALL(sys_fchmod, 2)
+SYSCALL(sys_fchown, 3)			/* 95 */
+SYSCALL(sys_getpriority, 2)
+SYSCALL(sys_setpriority, 3)
+SYSCALL(sys_ni_syscall, 0)
+SYSCALL(sys_statfs, 2)
+SYSCALL(sys_fstatfs, 2)			/* 100 */
+SYSCALL(sys_ni_syscall, 3)
+SYSCALL(sys_socketcall, 2)
+SYSCALL(sys_syslog, 3)
+SYSCALL(sys_setitimer, 3)
+SYSCALL(sys_getitimer, 2)		/* 105 */
+SYSCALL(sys_newstat, 2)
+SYSCALL(sys_newlstat, 2)
+SYSCALL(sys_newfstat, 2)
+SYSCALL(sys_uname, 1)
+SYSCALL(sys_ni_syscall, 0)		/* 110 */
+SYSCALL(sys_vhangup, 0)
+SYSCALL(sys_ni_syscall, 0)		/* was sys_idle() */
+SYSCALL(sys_ni_syscall, 0)
+SYSCALL(sys_wait4, 4)
+SYSCALL(sys_swapoff, 1)			/* 115 */
+SYSCALL(sys_sysinfo, 1)
+SYSCALL(sys_ipc, 5)   			/* 6 really, but glibc uses only 5) */
+SYSCALL(sys_fsync, 1)
+SYSCALL(sys_sigreturn, 0)
+SYSCALL(sys_clone, 0)			/* 120 */
+SYSCALL(sys_setdomainname, 2)
+SYSCALL(sys_newuname, 1)
+SYSCALL(sys_ni_syscall, 0) 		/* sys_modify_ldt */
+SYSCALL(sys_adjtimex, 1)
+SYSCALL(sys_mprotect, 3)		/* 125 */
+SYSCALL(sys_sigprocmask, 3)
+SYSCALL(sys_ni_syscall, 2)		/* old sys_create_module */
+SYSCALL(sys_init_module, 2)
+SYSCALL(sys_delete_module, 1)
+SYSCALL(sys_ni_syscall, 1)		/* old sys_get_kernel_sysm */	/* 130 */
+SYSCALL(sys_quotactl, 0)
+SYSCALL(sys_getpgid, 1)
+SYSCALL(sys_fchdir, 1)
+SYSCALL(sys_bdflush, 2)
+SYSCALL(sys_sysfs, 3)			/* 135 */
+SYSCALL(sys_personality, 1)
+SYSCALL(sys_ni_syscall, 0)		/* for afs_syscall */
+SYSCALL(sys_setfsuid, 1)
+SYSCALL(sys_setfsgid, 1)
+SYSCALL(sys_llseek, 5)			/* 140 */
+SYSCALL(sys_getdents, 3)
+SYSCALL(sys_select, 5)
+SYSCALL(sys_flock, 2)
+SYSCALL(sys_msync, 3)
+SYSCALL(sys_readv, 3)			/* 145 */
+SYSCALL(sys_writev, 3)
+SYSCALL(sys_ni_syscall, 3)
+SYSCALL(sys_ni_syscall, 3)
+SYSCALL(sys_ni_syscall, 4)		/* handled in fast syscall handler. */
+SYSCALL(sys_ni_syscall, 0)		/* 150 */
+SYSCALL(sys_getsid, 1)
+SYSCALL(sys_fdatasync, 1)
+SYSCALL(sys_sysctl, 1)
+SYSCALL(sys_mlock, 2)
+SYSCALL(sys_munlock, 2)			/* 155 */
+SYSCALL(sys_mlockall, 1)
+SYSCALL(sys_munlockall, 0)
+SYSCALL(sys_sched_setparam,2)
+SYSCALL(sys_sched_getparam,2)
+SYSCALL(sys_sched_setscheduler,3)	/* 160 */
+SYSCALL(sys_sched_getscheduler,1)
+SYSCALL(sys_sched_yield,0)
+SYSCALL(sys_sched_get_priority_max,1)
+SYSCALL(sys_sched_get_priority_min,1)
+SYSCALL(sys_sched_rr_get_interval,2)	/* 165 */
+SYSCALL(sys_nanosleep,2)
+SYSCALL(sys_mremap,4)
+SYSCALL(sys_accept, 3)
+SYSCALL(sys_bind, 3)
+SYSCALL(sys_connect, 3)			/* 170 */
+SYSCALL(sys_getpeername, 3)
+SYSCALL(sys_getsockname, 3)
+SYSCALL(sys_getsockopt, 5)
+SYSCALL(sys_listen, 2)
+SYSCALL(sys_recv, 4)			/* 175 */
+SYSCALL(sys_recvfrom, 6)
+SYSCALL(sys_recvmsg, 3)
+SYSCALL(sys_send, 4)
+SYSCALL(sys_sendmsg, 3)
+SYSCALL(sys_sendto, 6)			/* 180 */
+SYSCALL(sys_setsockopt, 5)
+SYSCALL(sys_shutdown, 2)
+SYSCALL(sys_socket, 3)
+SYSCALL(sys_socketpair, 4)
+SYSCALL(sys_setresuid, 3)		/* 185 */
+SYSCALL(sys_getresuid, 3)
+SYSCALL(sys_ni_syscall, 5)		/* old sys_query_module */
+SYSCALL(sys_poll, 3)
+SYSCALL(sys_nfsservctl, 3)
+SYSCALL(sys_setresgid, 3)		/* 190 */
+SYSCALL(sys_getresgid, 3)
+SYSCALL(sys_prctl, 5)
+SYSCALL(sys_rt_sigreturn, 0)
+SYSCALL(sys_rt_sigaction, 4)
+SYSCALL(sys_rt_sigprocmask, 4)		/* 195 */
+SYSCALL(sys_rt_sigpending, 2)
+SYSCALL(sys_rt_sigtimedwait, 4)
+SYSCALL(sys_rt_sigqueueinfo, 3)
+SYSCALL(sys_rt_sigsuspend, 0)
+SYSCALL(sys_pread64, 5)			/* 200 */
+SYSCALL(sys_pwrite64, 5)
+SYSCALL(sys_chown, 3)
+SYSCALL(sys_getcwd, 2)
+SYSCALL(sys_capget, 2)
+SYSCALL(sys_capset, 2)			/* 205 */
+SYSCALL(sys_sigaltstack, 0)
+SYSCALL(sys_sendfile, 4)
+SYSCALL(sys_ni_syscall, 0)
+SYSCALL(sys_ni_syscall, 0)
+SYSCALL(sys_mmap2, 6)			/* 210 */
+SYSCALL(sys_truncate64, 2)
+SYSCALL(sys_ftruncate64, 2)
+SYSCALL(sys_stat64, 2)
+SYSCALL(sys_lstat64, 2)
+SYSCALL(sys_fstat64, 2)			/* 215 */
+SYSCALL(sys_pivot_root, 2)
+SYSCALL(sys_mincore, 3)
+SYSCALL(sys_madvise, 3)
+SYSCALL(sys_getdents64, 3)
+SYSCALL(sys_vfork, 0)			/* 220 */
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c
new file mode 100644
index 0000000..e07287d
--- /dev/null
+++ b/arch/xtensa/kernel/time.c
@@ -0,0 +1,227 @@
+/*
+ * arch/xtensa/kernel/time.c
+ *
+ * Timer and clock support.
+ *
+ * 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 Tensilica Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/profile.h>
+#include <linux/delay.h>
+
+#include <asm/timex.h>
+#include <asm/platform.h>
+
+
+extern volatile unsigned long wall_jiffies;
+
+u64 jiffies_64 = INITIAL_JIFFIES;
+EXPORT_SYMBOL(jiffies_64);
+
+spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
+EXPORT_SYMBOL(rtc_lock);
+
+
+#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
+unsigned long ccount_per_jiffy;		/* per 1/HZ */
+unsigned long ccount_nsec;		/* nsec per ccount increment */
+#endif
+
+unsigned int last_ccount_stamp;
+static long last_rtc_update = 0;
+
+/*
+ * Scheduler clock - returns current tim in nanosec units.
+ */
+
+unsigned long long sched_clock(void)
+{
+	return (unsigned long long)jiffies * (1000000000 / HZ);
+}
+
+static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static struct irqaction timer_irqaction = {
+	.handler =	timer_interrupt,
+	.flags =	SA_INTERRUPT,
+	.name =		"timer",
+};
+
+void __init time_init(void)
+{
+	time_t sec_o, sec_n = 0;
+
+	/* The platform must provide a function to calibrate the processor
+	 * speed for the CALIBRATE.
+	 */
+
+#if CONFIG_XTENSA_CALIBRATE_CCOUNT
+	printk("Calibrating CPU frequency ");
+	platform_calibrate_ccount();
+	printk("%d.%02d MHz\n", (int)ccount_per_jiffy/(1000000/HZ),
+			(int)(ccount_per_jiffy/(10000/HZ))%100);
+#endif
+
+	/* Set time from RTC (if provided) */
+
+	if (platform_get_rtc_time(&sec_o) == 0)
+		while (platform_get_rtc_time(&sec_n))
+			if (sec_o != sec_n)
+				break;
+
+	xtime.tv_nsec = 0;
+	last_rtc_update = xtime.tv_sec = sec_n;
+	last_ccount_stamp = get_ccount();
+
+	set_normalized_timespec(&wall_to_monotonic,
+		-xtime.tv_sec, -xtime.tv_nsec);
+
+	/* Initialize the linux timer interrupt. */
+
+	setup_irq(LINUX_TIMER_INT, &timer_irqaction);
+	set_linux_timer(get_ccount() + CCOUNT_PER_JIFFY);
+}
+
+
+int do_settimeofday(struct timespec *tv)
+{
+	time_t wtm_sec, sec = tv->tv_sec;
+	long wtm_nsec, nsec = tv->tv_nsec;
+	unsigned long ccount;
+
+	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!
+	 */
+	ccount = get_ccount();
+	nsec -= (ccount - last_ccount_stamp) * CCOUNT_NSEC;
+	nsec -= (jiffies - wall_jiffies) * CCOUNT_PER_JIFFY * CCOUNT_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);
+
+	time_adjust = 0;                /* stop active adjtime() */
+	time_status |= STA_UNSYNC;
+	time_maxerror = NTP_PHASE_LIMIT;
+	time_esterror = NTP_PHASE_LIMIT;
+	write_sequnlock_irq(&xtime_lock);
+	return 0;
+}
+
+EXPORT_SYMBOL(do_settimeofday);
+
+
+void do_gettimeofday(struct timeval *tv)
+{
+	unsigned long flags;
+	unsigned long sec, usec, delta, lost, seq;
+
+	do {
+		seq = read_seqbegin_irqsave(&xtime_lock, flags);
+
+		delta = get_ccount() - last_ccount_stamp;
+		sec = xtime.tv_sec;
+		usec = (xtime.tv_nsec / NSEC_PER_USEC);
+
+		lost = jiffies - wall_jiffies;
+
+	} while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
+
+	usec += lost * (1000000UL/HZ) + (delta * CCOUNT_NSEC) / NSEC_PER_USEC;
+	for (; usec >= 1000000; sec++, usec -= 1000000)
+		;
+
+	tv->tv_sec = sec;
+	tv->tv_usec = usec;
+}
+
+EXPORT_SYMBOL(do_gettimeofday);
+
+/*
+ * The timer interrupt is called HZ times per second.
+ */
+
+irqreturn_t timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
+{
+
+	unsigned long next;
+
+	next = get_linux_timer();
+
+again:
+	while ((signed long)(get_ccount() - next) > 0) {
+
+		profile_tick(CPU_PROFILING, regs);
+#ifndef CONFIG_SMP
+		update_process_times(user_mode(regs));
+#endif
+
+		write_seqlock(&xtime_lock);
+
+		last_ccount_stamp = next;
+		next += CCOUNT_PER_JIFFY;
+		do_timer (regs); /* Linux handler in kernel/timer.c */
+
+		if ((time_status & STA_UNSYNC) == 0 &&
+		    xtime.tv_sec - last_rtc_update >= 659 &&
+		    abs((xtime.tv_nsec/1000)-(1000000-1000000/HZ))<5000000/HZ &&
+		    jiffies - wall_jiffies == 1) {
+
+			if (platform_set_rtc_time(xtime.tv_sec+1) == 0)
+				last_rtc_update = xtime.tv_sec+1;
+			else
+				/* Do it again in 60 s */
+				last_rtc_update += 60;
+		}
+		write_sequnlock(&xtime_lock);
+	}
+
+	/* NOTE: writing CCOMPAREn clears the interrupt.  */
+
+	set_linux_timer (next);
+
+	/* Make sure we didn't miss any tick... */
+
+	if ((signed long)(get_ccount() - next) > 0)
+		goto again;
+
+	/* Allow platform to do something usefull (Wdog). */
+
+	platform_heartbeat();
+
+	return IRQ_HANDLED;
+}
+
+#ifndef CONFIG_GENERIC_CALIBRATE_DELAY
+void __devinit calibrate_delay(void)
+{
+	loops_per_jiffy = CCOUNT_PER_JIFFY;
+	printk("Calibrating delay loop (skipped)... "
+	       "%lu.%02lu BogoMIPS preset\n",
+	       loops_per_jiffy/(1000000/HZ),
+	       (loops_per_jiffy/(10000/HZ)) % 100);
+}
+#endif
+
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
new file mode 100644
index 0000000..804246e
--- /dev/null
+++ b/arch/xtensa/kernel/traps.c
@@ -0,0 +1,498 @@
+/*
+ * arch/xtensa/kernel/traps.c
+ *
+ * Exception handling.
+ *
+ * Derived from code with the following copyrights:
+ * Copyright (C) 1994 - 1999 by Ralf Baechle
+ * Modified for R3000 by Paul M. Antoine, 1995, 1996
+ * Complete output from die() by Ulf Carlsson, 1998
+ * Copyright (C) 1999 Silicon Graphics, Inc.
+ *
+ * Essentially rewritten for the Xtensa architecture port.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ *
+ * Joe Taylor	<joe@tensilica.com, joetylr@yahoo.com>
+ * Chris Zankel	<chris@zankel.net>
+ * Marc Gauthier<marc@tensilica.com, marc@alumni.uwaterloo.ca>
+ * Kevin Chea
+ *
+ * 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/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/stringify.h>
+#include <linux/kallsyms.h>
+
+#include <asm/ptrace.h>
+#include <asm/timex.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+
+#ifdef CONFIG_KGDB
+extern int gdb_enter;
+extern int return_from_debug_flag;
+#endif
+
+/*
+ * Machine specific interrupt handlers
+ */
+
+extern void kernel_exception(void);
+extern void user_exception(void);
+
+extern void fast_syscall_kernel(void);
+extern void fast_syscall_user(void);
+extern void fast_alloca(void);
+extern void fast_unaligned(void);
+extern void fast_second_level_miss(void);
+extern void fast_store_prohibited(void);
+extern void fast_coprocessor(void);
+
+extern void do_illegal_instruction (struct pt_regs*);
+extern void do_interrupt (struct pt_regs*);
+extern void do_unaligned_user (struct pt_regs*);
+extern void do_multihit (struct pt_regs*, unsigned long);
+extern void do_page_fault (struct pt_regs*, unsigned long);
+extern void do_debug (struct pt_regs*);
+extern void system_call (struct pt_regs*);
+
+/*
+ * The vector table must be preceded by a save area (which
+ * implies it must be in RAM, unless one places RAM immediately
+ * before a ROM and puts the vector at the start of the ROM (!))
+ */
+
+#define KRNL		0x01
+#define USER		0x02
+
+#define COPROCESSOR(x)							\
+{ XCHAL_EXCCAUSE_COPROCESSOR ## x ## _DISABLED, USER, fast_coprocessor }
+
+typedef struct {
+	int cause;
+	int fast;
+	void* handler;
+} dispatch_init_table_t;
+
+dispatch_init_table_t __init dispatch_init_table[] = {
+
+{ XCHAL_EXCCAUSE_ILLEGAL_INSTRUCTION,	0,	   do_illegal_instruction},
+{ XCHAL_EXCCAUSE_SYSTEM_CALL,		KRNL,	   fast_syscall_kernel },
+{ XCHAL_EXCCAUSE_SYSTEM_CALL,		USER,	   fast_syscall_user },
+{ XCHAL_EXCCAUSE_SYSTEM_CALL,		0,	   system_call },
+/* XCHAL_EXCCAUSE_INSTRUCTION_FETCH unhandled */
+/* XCHAL_EXCCAUSE_LOAD_STORE_ERROR unhandled*/
+{ XCHAL_EXCCAUSE_LEVEL1_INTERRUPT,	0,	   do_interrupt },
+{ XCHAL_EXCCAUSE_ALLOCA,		USER|KRNL, fast_alloca },
+/* XCHAL_EXCCAUSE_INTEGER_DIVIDE_BY_ZERO unhandled */
+/* XCHAL_EXCCAUSE_PRIVILEGED unhandled */
+#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
+#ifdef CONFIG_UNALIGNED_USER
+{ XCHAL_EXCCAUSE_UNALIGNED,		USER,	   fast_unaligned },
+#else
+{ XCHAL_EXCCAUSE_UNALIGNED,		0,	   do_unaligned_user },
+#endif
+{ XCHAL_EXCCAUSE_UNALIGNED,		KRNL,	   fast_unaligned },
+#endif
+{ XCHAL_EXCCAUSE_ITLB_MISS,		0,	   do_page_fault },
+{ XCHAL_EXCCAUSE_ITLB_MISS,		USER|KRNL, fast_second_level_miss},
+{ XCHAL_EXCCAUSE_ITLB_MULTIHIT,		0,	   do_multihit },
+{ XCHAL_EXCCAUSE_ITLB_PRIVILEGE,	0,	   do_page_fault },
+/* XCHAL_EXCCAUSE_SIZE_RESTRICTION unhandled */
+{ XCHAL_EXCCAUSE_FETCH_CACHE_ATTRIBUTE,	0,	   do_page_fault },
+{ XCHAL_EXCCAUSE_DTLB_MISS,		USER|KRNL, fast_second_level_miss},
+{ XCHAL_EXCCAUSE_DTLB_MISS,		0,	   do_page_fault },
+{ XCHAL_EXCCAUSE_DTLB_MULTIHIT,		0,	   do_multihit },
+{ XCHAL_EXCCAUSE_DTLB_PRIVILEGE,	0,	   do_page_fault },
+/* XCHAL_EXCCAUSE_DTLB_SIZE_RESTRICTION unhandled */
+{ XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE,	USER|KRNL, fast_store_prohibited },
+{ XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE,	0,	   do_page_fault },
+{ XCHAL_EXCCAUSE_LOAD_CACHE_ATTRIBUTE,	0,	   do_page_fault },
+/* XCCHAL_EXCCAUSE_FLOATING_POINT unhandled */
+#if (XCHAL_CP_MASK & 1)
+COPROCESSOR(0),
+#endif
+#if (XCHAL_CP_MASK & 2)
+COPROCESSOR(1),
+#endif
+#if (XCHAL_CP_MASK & 4)
+COPROCESSOR(2),
+#endif
+#if (XCHAL_CP_MASK & 8)
+COPROCESSOR(3),
+#endif
+#if (XCHAL_CP_MASK & 16)
+COPROCESSOR(4),
+#endif
+#if (XCHAL_CP_MASK & 32)
+COPROCESSOR(5),
+#endif
+#if (XCHAL_CP_MASK & 64)
+COPROCESSOR(6),
+#endif
+#if (XCHAL_CP_MASK & 128)
+COPROCESSOR(7),
+#endif
+{ EXCCAUSE_MAPPED_DEBUG,		0,		do_debug },
+{ -1, -1, 0 }
+
+};
+
+/* The exception table <exc_table> serves two functions:
+ * 1. it contains three dispatch tables (fast_user, fast_kernel, default-c)
+ * 2. it is a temporary memory buffer for the exception handlers.
+ */
+
+unsigned long exc_table[EXC_TABLE_SIZE/4];
+
+void die(const char*, struct pt_regs*, long);
+
+static inline void
+__die_if_kernel(const char *str, struct pt_regs *regs, long err)
+{
+	if (!user_mode(regs))
+		die(str, regs, err);
+}
+
+/*
+ * Unhandled Exceptions. Kill user task or panic if in kernel space.
+ */
+
+void do_unhandled(struct pt_regs *regs, unsigned long exccause)
+{
+	__die_if_kernel("Caught unhandled exception - should not happen",
+	    		regs, SIGKILL);
+
+	/* If in user mode, send SIGILL signal to current process */
+	printk("Caught unhandled exception in '%s' "
+	       "(pid = %d, pc = %#010lx) - should not happen\n"
+	       "\tEXCCAUSE is %ld\n",
+	       current->comm, current->pid, regs->pc, exccause);
+	force_sig(SIGILL, current);
+}
+
+/*
+ * Multi-hit exception. This if fatal!
+ */
+
+void do_multihit(struct pt_regs *regs, unsigned long exccause)
+{
+	die("Caught multihit exception", regs, SIGKILL);
+}
+
+/*
+ * Level-1 interrupt.
+ * We currently have no priority encoding.
+ */
+
+unsigned long ignored_level1_interrupts;
+extern void do_IRQ(int, struct pt_regs *);
+
+void do_interrupt (struct pt_regs *regs)
+{
+	unsigned long intread = get_sr (INTREAD);
+	unsigned long intenable = get_sr (INTENABLE);
+	int i, mask;
+
+	/* Handle all interrupts (no priorities).
+	 * (Clear the interrupt before processing, in case it's
+	 *  edge-triggered or software-generated)
+	 */
+
+	for (i=0, mask = 1; i < XCHAL_NUM_INTERRUPTS; i++, mask <<= 1) {
+		if (mask & (intread & intenable)) {
+			set_sr (mask, INTCLEAR);
+			do_IRQ (i,regs);
+		}
+	}
+}
+
+/*
+ * Illegal instruction. Fatal if in kernel space.
+ */
+
+void
+do_illegal_instruction(struct pt_regs *regs)
+{
+	__die_if_kernel("Illegal instruction in kernel", regs, SIGKILL);
+
+	/* If in user mode, send SIGILL signal to current process. */
+
+	printk("Illegal Instruction in '%s' (pid = %d, pc = %#010lx)\n",
+	    current->comm, current->pid, regs->pc);
+	force_sig(SIGILL, current);
+}
+
+
+/*
+ * Handle unaligned memory accesses from user space. Kill task.
+ *
+ * If CONFIG_UNALIGNED_USER is not set, we don't allow unaligned memory
+ * accesses causes from user space.
+ */
+
+#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
+#ifndef CONFIG_UNALIGNED_USER
+void
+do_unaligned_user (struct pt_regs *regs)
+{
+	siginfo_t info;
+
+	__die_if_kernel("Unhandled unaligned exception in kernel",
+	    		regs, SIGKILL);
+
+	current->thread.bad_vaddr = regs->excvaddr;
+	current->thread.error_code = -3;
+	printk("Unaligned memory access to %08lx in '%s' "
+	       "(pid = %d, pc = %#010lx)\n",
+	       regs->excvaddr, current->comm, current->pid, regs->pc);
+	info.si_signo = SIGBUS;
+	info.si_errno = 0;
+	info.si_code = BUS_ADRALN;
+	info.si_addr = (void *) regs->excvaddr;
+	force_sig_info(SIGSEGV, &info, current);
+
+}
+#endif
+#endif
+
+void
+do_debug(struct pt_regs *regs)
+{
+#ifdef CONFIG_KGDB
+	/* If remote debugging is configured AND enabled, we give control to
+	 * kgdb.  Otherwise, we fall through, perhaps giving control to the
+	 * native debugger.
+	 */
+
+	if (gdb_enter) {
+		extern void gdb_handle_exception(struct pt_regs *);
+		gdb_handle_exception(regs);
+		return_from_debug_flag = 1;
+		return;
+	}
+#endif
+
+	__die_if_kernel("Breakpoint in kernel", regs, SIGKILL);
+
+	/* If in user mode, send SIGTRAP signal to current process */
+
+	force_sig(SIGTRAP, current);
+}
+
+
+/*
+ * Initialize dispatch tables.
+ *
+ * The exception vectors are stored compressed the __init section in the
+ * dispatch_init_table. This function initializes the following three tables
+ * from that compressed table:
+ * - fast user		first dispatch table for user exceptions
+ * - fast kernel	first dispatch table for kernel exceptions
+ * - default C-handler	C-handler called by the default fast handler.
+ *
+ * See vectors.S for more details.
+ */
+
+#define set_handler(idx,handler) (exc_table[idx] = (unsigned long) (handler))
+
+void trap_init(void)
+{
+	int i;
+
+	/* Setup default vectors. */
+
+	for(i = 0; i < 64; i++) {
+		set_handler(EXC_TABLE_FAST_USER/4   + i, user_exception);
+		set_handler(EXC_TABLE_FAST_KERNEL/4 + i, kernel_exception);
+		set_handler(EXC_TABLE_DEFAULT/4 + i, do_unhandled);
+	}
+
+	/* Setup specific handlers. */
+
+	for(i = 0; dispatch_init_table[i].cause >= 0; i++) {
+
+		int fast = dispatch_init_table[i].fast;
+		int cause = dispatch_init_table[i].cause;
+		void *handler = dispatch_init_table[i].handler;
+
+		if (fast == 0)
+			set_handler (EXC_TABLE_DEFAULT/4 + cause, handler);
+		if (fast && fast & USER)
+			set_handler (EXC_TABLE_FAST_USER/4 + cause, handler);
+		if (fast && fast & KRNL)
+			set_handler (EXC_TABLE_FAST_KERNEL/4 + cause, handler);
+	}
+
+	/* Initialize EXCSAVE_1 to hold the address of the exception table. */
+
+	i = (unsigned long)exc_table;
+	__asm__ __volatile__("wsr  %0, "__stringify(EXCSAVE_1)"\n" : : "a" (i));
+}
+
+/*
+ * This function dumps the current valid window frame and other base registers.
+ */
+
+void show_regs(struct pt_regs * regs)
+{
+	int i, wmask;
+
+	wmask = regs->wmask & ~1;
+
+	for (i = 0; i < 32; i++) {
+		if (wmask & (1 << (i / 4)))
+			break;
+		if ((i % 8) == 0)
+			printk ("\n" KERN_INFO "a%02d: ", i);
+		printk("%08lx ", regs->areg[i]);
+	}
+	printk("\n");
+
+	printk("pc: %08lx, ps: %08lx, depc: %08lx, excvaddr: %08lx\n",
+	       regs->pc, regs->ps, regs->depc, regs->excvaddr);
+	printk("lbeg: %08lx, lend: %08lx lcount: %08lx, sar: %08lx\n",
+	       regs->lbeg, regs->lend, regs->lcount, regs->sar);
+	if (user_mode(regs))
+		printk("wb: %08lx, ws: %08lx, wmask: %08lx, syscall: %ld\n",
+		       regs->windowbase, regs->windowstart, regs->wmask,
+		       regs->syscall);
+}
+
+void show_trace(struct task_struct *task, unsigned long *sp)
+{
+	unsigned long a0, a1, pc;
+	unsigned long sp_start, sp_end;
+
+	a1 = (unsigned long)sp;
+
+	if (a1 == 0)
+		__asm__ __volatile__ ("mov %0, a1\n" : "=a"(a1));
+
+
+	sp_start = a1 & ~(THREAD_SIZE-1);
+	sp_end = sp_start + THREAD_SIZE;
+
+	printk("Call Trace:");
+#ifdef CONFIG_KALLSYMS
+	printk("\n");
+#endif
+	spill_registers();
+
+	while (a1 > sp_start && a1 < sp_end) {
+		sp = (unsigned long*)a1;
+
+		a0 = *(sp - 4);
+		a1 = *(sp - 3);
+
+		if (a1 <= (unsigned long) sp)
+			break;
+
+		pc = MAKE_PC_FROM_RA(a0, a1);
+
+		if (kernel_text_address(pc)) {
+			printk(" [<%08lx>] ", pc);
+			print_symbol("%s\n", pc);
+		}
+	}
+	printk("\n");
+}
+
+/*
+ * This routine abuses get_user()/put_user() to reference pointers
+ * with at least a bit of error checking ...
+ */
+
+static int kstack_depth_to_print = 24;
+
+void show_stack(struct task_struct *task, unsigned long *sp)
+{
+	int i = 0;
+	unsigned long *stack;
+
+	if (sp == 0)
+		__asm__ __volatile__ ("mov %0, a1\n" : "=a"(sp));
+
+ 	stack = sp;
+
+	printk("\nStack: ");
+
+	for (i = 0; i < kstack_depth_to_print; i++) {
+		if (kstack_end(sp))
+			break;
+		if (i && ((i % 8) == 0))
+			printk("\n       ");
+		printk("%08lx ", *sp++);
+	}
+	printk("\n");
+	show_trace(task, stack);
+}
+
+void dump_stack(void)
+{
+	show_stack(current, NULL);
+}
+
+EXPORT_SYMBOL(dump_stack);
+
+
+void show_code(unsigned int *pc)
+{
+	long i;
+
+	printk("\nCode:");
+
+	for(i = -3 ; i < 6 ; i++) {
+		unsigned long insn;
+		if (__get_user(insn, pc + i)) {
+			printk(" (Bad address in pc)\n");
+			break;
+		}
+		printk("%c%08lx%c",(i?' ':'<'),insn,(i?' ':'>'));
+	}
+}
+
+spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
+
+void die(const char * str, struct pt_regs * regs, long err)
+{
+	static int die_counter;
+	int nl = 0;
+
+	console_verbose();
+	spin_lock_irq(&die_lock);
+
+	printk("%s: sig: %ld [#%d]\n", str, err, ++die_counter);
+#ifdef CONFIG_PREEMPT
+	printk("PREEMPT ");
+	nl = 1;
+#endif
+	if (nl)
+		printk("\n");
+	show_regs(regs);
+	if (!user_mode(regs))
+		show_stack(NULL, (unsigned long*)regs->areg[1]);
+
+	spin_unlock_irq(&die_lock);
+
+	if (in_interrupt())
+		panic("Fatal exception in interrupt");
+
+	if (panic_on_oops) {
+		printk(KERN_EMERG "Fatal exception: panic in 5 seconds\n");
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(5 * HZ);
+		panic("Fatal exception");
+	}
+	do_exit(err);
+}
+
+
diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S
new file mode 100644
index 0000000..81808f0
--- /dev/null
+++ b/arch/xtensa/kernel/vectors.S
@@ -0,0 +1,464 @@
+/*
+ * arch/xtensa/kernel/vectors.S
+ *
+ * This file contains all exception vectors (user, kernel, and double),
+ * as well as the window vectors (overflow and underflow), and the debug
+ * vector. These are the primary vectors executed by the processor if an
+ * exception occurs.
+ *
+ * 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 Tensilica, Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ *
+ */
+
+/*
+ * We use a two-level table approach. The user and kernel exception vectors
+ * use a first-level dispatch table to dispatch the exception to a registered
+ * fast handler or the default handler, if no fast handler was registered.
+ * The default handler sets up a C-stack and dispatches the exception to a
+ * registerd C handler in the second-level dispatch table.
+ *
+ * Fast handler entry condition:
+ *
+ *   a0:	trashed, original value saved on stack (PT_AREG0)
+ *   a1:	a1
+ *   a2:	new stack pointer, original value in depc
+ *   a3:	dispatch table
+ *   depc:	a2, original value saved on stack (PT_DEPC)
+ *   excsave_1:	a3
+ *
+ * The value for PT_DEPC saved to stack also functions as a boolean to
+ * indicate that the exception is either a double or a regular exception:
+ *
+ *   PT_DEPC	>= VALID_DOUBLE_EXCEPTION_ADDRESS: double exception
+ *		<  VALID_DOUBLE_EXCEPTION_ADDRESS: regular exception
+ *
+ * Note:  Neither the kernel nor the user exception handler generate literals.
+ *
+ */
+
+#include <linux/linkage.h>
+#include <asm/ptrace.h>
+#include <asm/ptrace.h>
+#include <asm/current.h>
+#include <asm/offsets.h>
+#include <asm/pgtable.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/thread_info.h>
+#include <asm/processor.h>
+
+
+/*
+ * User exception vector. (Exceptions with PS.UM == 1, PS.EXCM == 0)
+ *
+ * We get here when an exception occurred while we were in userland.
+ * We switch to the kernel stack and jump to the first level handler
+ * associated to the exception cause.
+ *
+ * Note: the saved kernel stack pointer (EXC_TABLE_KSTK) is already
+ *       decremented by PT_USER_SIZE.
+ */
+
+	.section .UserExceptionVector.text, "ax"
+
+ENTRY(_UserExceptionVector)
+
+	xsr	a3, EXCSAVE_1		# save a3 and get dispatch table
+	wsr	a2, DEPC		# save a2
+	l32i	a2, a3, EXC_TABLE_KSTK	# load kernel stack to a2
+	s32i	a0, a2, PT_AREG0	# save a0 to ESF
+	rsr	a0, EXCCAUSE		# retrieve exception cause
+	s32i	a0, a2, PT_DEPC		# mark it as a regular exception
+	addx4	a0, a0, a3		# find entry in table
+	l32i	a0, a0, EXC_TABLE_FAST_USER	# load handler
+	jx	a0
+
+/*
+ * Kernel exception vector. (Exceptions with PS.UM == 0, PS.EXCM == 0)
+ *
+ * We get this exception when we were already in kernel space.
+ * We decrement the current stack pointer (kernel) by PT_SIZE and
+ * jump to the first-level handler associated with the exception cause.
+ *
+ * Note: we need to preserve space for the spill region.
+ */
+
+	.section .KernelExceptionVector.text, "ax"
+
+ENTRY(_KernelExceptionVector)
+
+	xsr	a3, EXCSAVE_1		# save a3, and get dispatch table
+	wsr	a2, DEPC		# save a2
+	addi	a2, a1, -16-PT_SIZE	# adjust stack pointer
+	s32i	a0, a2, PT_AREG0	# save a0 to ESF
+	rsr	a0, EXCCAUSE		# retrieve exception cause
+	s32i	a0, a2, PT_DEPC		# mark it as a regular exception
+	addx4	a0, a0, a3		# find entry in table
+	l32i	a0, a0, EXC_TABLE_FAST_KERNEL	# load handler address
+	jx	a0
+
+
+/*
+ * Double exception vector (Exceptions with PS.EXCM == 1)
+ * We get this exception when another exception occurs while were are
+ * already in an exception, such as window overflow/underflow exception,
+ * or 'expected' exceptions, for example memory exception when we were trying
+ * to read data from an invalid address in user space.
+ *
+ * Note that this vector is never invoked for level-1 interrupts, because such
+ * interrupts are disabled (masked) when PS.EXCM is set.
+ *
+ * We decode the exception and take the appropriate action.  However, the
+ * double exception vector is much more careful, because a lot more error
+ * cases go through the double exception vector than through the user and
+ * kernel exception vectors.
+ *
+ * Occasionally, the kernel expects a double exception to occur.  This usually
+ * happens when accessing user-space memory with the user's permissions
+ * (l32e/s32e instructions).  The kernel state, though, is not always suitable
+ * for immediate transfer of control to handle_double, where "normal" exception
+ * processing occurs. Also in kernel mode, TLB misses can occur if accessing
+ * vmalloc memory, possibly requiring repair in a double exception handler.
+ *
+ * The variable at TABLE_FIXUP offset from the pointer in EXCSAVE_1 doubles as
+ * a boolean variable and a pointer to a fixup routine. If the variable
+ * EXC_TABLE_FIXUP is non-zero, this handler jumps to that address. A value of
+ * zero indicates to use the default kernel/user exception handler.
+ * There is only one exception, when the value is identical to the exc_table
+ * label, the kernel is in trouble. This mechanism is used to protect critical
+ * sections, mainly when the handler writes to the stack to assert the stack
+ * pointer is valid. Once the fixup/default handler leaves that area, the
+ * EXC_TABLE_FIXUP variable is reset to the fixup handler or zero.
+ *
+ * Procedures wishing to use this mechanism should set EXC_TABLE_FIXUP to the
+ * nonzero address of a fixup routine before it could cause a double exception
+ * and reset it before it returns.
+ *
+ * Some other things to take care of when a fast exception handler doesn't
+ * specify a particular fixup handler but wants to use the default handlers:
+ *
+ *  - The original stack pointer (in a1) must not be modified. The fast
+ *    exception handler should only use a2 as the stack pointer.
+ *
+ *  - If the fast handler manipulates the stack pointer (in a2), it has to
+ *    register a valid fixup handler and cannot use the default handlers.
+ *
+ *  - The handler can use any other generic register from a3 to a15, but it
+ *    must save the content of these registers to stack (PT_AREG3...PT_AREGx)
+ *
+ *  - These registers must be saved before a double exception can occur.
+ *
+ *  - If we ever implement handling signals while in double exceptions, the
+ *    number of registers a fast handler has saved (excluding a0 and a1) must
+ *    be written to  PT_AREG1. (1 if only a3 is used, 2 for a3 and a4, etc. )
+ *
+ * The fixup handlers are special handlers:
+ *
+ *  - Fixup entry conditions differ from regular exceptions:
+ *
+ *	a0:	   DEPC
+ *	a1: 	   a1
+ *	a2:	   trashed, original value in EXC_TABLE_DOUBLE_A2
+ *	a3:	   exctable
+ *	depc:	   a0
+ *	excsave_1: a3
+ *
+ *  - When the kernel enters the fixup handler, it still assumes it is in a
+ *    critical section, so EXC_TABLE_FIXUP variable is set to exc_table.
+ *    The fixup handler, therefore, has to re-register itself as the fixup
+ *    handler before it returns from the double exception.
+ *
+ *  - Fixup handler can share the same exception frame with the fast handler.
+ *    The kernel stack pointer is not changed when entering the fixup handler.
+ *
+ *  - Fixup handlers can jump to the default kernel and user exception
+ *    handlers. Before it jumps, though, it has to setup a exception frame
+ *    on stack. Because the default handler resets the register fixup handler
+ *    the fixup handler must make sure that the default handler returns to
+ *    it instead of the exception address, so it can re-register itself as
+ *    the fixup handler.
+ *
+ * In case of a critical condition where the kernel cannot recover, we jump
+ * to unrecoverable_exception with the following entry conditions.
+ * All registers a0...a15 are unchanged from the last exception, except:
+ *
+ *	a0:	   last address before we jumped to the unrecoverable_exception.
+ *	excsave_1: a0
+ *
+ *
+ * See the handle_alloca_user and spill_registers routines for example clients.
+ *
+ * FIXME: Note: we currently don't allow signal handling coming from a double
+ *        exception, so the item markt with (*) is not required.
+ */
+
+	.section .DoubleExceptionVector.text, "ax"
+	.begin literal_prefix .DoubleExceptionVector
+
+ENTRY(_DoubleExceptionVector)
+
+	/* Deliberately destroy excsave (don't assume it's value was valid). */
+
+	wsr	a3, EXCSAVE_1		# save a3
+
+	/* Check for kernel double exception (usually fatal). */
+
+	rsr	a3, PS
+	_bbci.l	a3, PS_UM_SHIFT, .Lksp
+
+	/* Check if we are currently handling a window exception. */
+	/* Note: We don't need to indicate that we enter a critical section. */
+
+	xsr	a0, DEPC		# get DEPC, save a0
+
+	movi	a3, XCHAL_WINDOW_VECTORS_VADDR
+	_bltu	a0, a3, .Lfixup
+	addi	a3, a3, XSHAL_WINDOW_VECTORS_SIZE
+	_bgeu	a0, a3, .Lfixup
+
+	/* Window overflow/underflow exception. Get stack pointer. */
+
+	mov	a3, a2
+	movi	a2, exc_table
+	l32i	a2, a2, EXC_TABLE_KSTK
+
+	/* Check for overflow/underflow exception, jump if overflow. */
+
+	_bbci.l	a0, 6, .Lovfl
+
+	/* a0: depc, a1: a1, a2: kstk, a3: a2, depc: a0, excsave: a3  */
+
+	/* Restart window underflow exception.
+	 * We return to the instruction in user space that caused the window
+	 * underflow exception. Therefore, we change window base to the value
+	 * before we entered the window underflow exception and prepare the
+	 * registers to return as if we were coming from a regular exception
+	 * by changing depc (in a0).
+	 * Note: We can trash the current window frame (a0...a3) and depc!
+	 */
+
+	wsr	a2, DEPC		# save stack pointer temporarily
+	rsr	a0, PS
+	extui	a0, a0, XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS
+	wsr	a0, WINDOWBASE
+	rsync
+
+	/* We are now in the previous window frame. Save registers again. */
+
+	xsr	a2, DEPC		# save a2 and get stack pointer
+	s32i	a0, a2, PT_AREG0
+
+	wsr	a3, EXCSAVE_1		# save a3
+	movi	a3, exc_table
+
+	rsr	a0, EXCCAUSE
+	s32i	a0, a2, PT_DEPC		# mark it as a regular exception
+	addx4	a0, a0, a3
+	l32i	a0, a0, EXC_TABLE_FAST_USER
+	jx	a0
+
+.Lfixup:/* Check for a fixup handler or if we were in a critical section. */
+
+	/* a0: depc, a1: a1, a2: a2, a3: trashed, depc: a0, excsave1: a3 */
+
+	movi	a3, exc_table
+	s32i	a2, a3, EXC_TABLE_DOUBLE_SAVE	# temporary variable
+
+	/* Enter critical section. */
+
+	l32i	a2, a3, EXC_TABLE_FIXUP
+	s32i	a3, a3, EXC_TABLE_FIXUP
+	beq	a2, a3, .Lunrecoverable_fixup	# critical!
+	beqz	a2, .Ldflt			# no handler was registered
+
+	/* a0: depc, a1: a1, a2: trash, a3: exctable, depc: a0, excsave: a3 */
+
+	jx	a2
+
+.Ldflt:	/* Get stack pointer. */
+
+	l32i	a3, a3, EXC_TABLE_DOUBLE_SAVE
+	addi	a2, a3, -PT_USER_SIZE
+
+.Lovfl:	/* Jump to default handlers. */
+
+	/* a0: depc, a1: a1, a2: kstk, a3: a2, depc: a0, excsave: a3 */
+
+	xsr	a3, DEPC
+	s32i	a0, a2, PT_DEPC
+	s32i	a3, a2, PT_AREG0
+
+	/* a0: avail, a1: a1, a2: kstk, a3: avail, depc: a2, excsave: a3 */
+
+	movi	a3, exc_table
+	rsr	a0, EXCCAUSE
+	addx4	a0, a0, a3
+	l32i	a0, a0, EXC_TABLE_FAST_USER
+	jx	a0
+
+	/*
+	 * We only allow the ITLB miss exception if we are in kernel space.
+	 * All other exceptions are unexpected and thus unrecoverable!
+	 */
+
+	.extern fast_second_level_miss_double_kernel
+
+.Lksp:	/* a0: a0, a1: a1, a2: a2, a3: trashed, depc: depc, excsave: a3 */
+
+	rsr	a3, EXCCAUSE
+	beqi	a3, XCHAL_EXCCAUSE_ITLB_MISS, 1f
+	addi	a3, a3, -XCHAL_EXCCAUSE_DTLB_MISS
+	bnez	a3, .Lunrecoverable
+1:	movi	a3, fast_second_level_miss_double_kernel
+	jx	a3
+
+	/* Critical! We can't handle this situation. PANIC! */
+
+	.extern unrecoverable_exception
+
+.Lunrecoverable_fixup:
+	l32i	a2, a3, EXC_TABLE_DOUBLE_SAVE
+	xsr	a0, DEPC
+
+.Lunrecoverable:
+	rsr	a3, EXCSAVE_1
+	wsr	a0, EXCSAVE_1
+	movi	a0, unrecoverable_exception
+	callx0	a0
+
+	.end literal_prefix
+
+
+/*
+ * Debug interrupt vector
+ *
+ * There is not much space here, so simply jump to another handler.
+ * EXCSAVE[DEBUGLEVEL] has been set to that handler.
+ */
+
+	.section .DebugInterruptVector.text, "ax"
+
+ENTRY(_DebugInterruptVector)
+	xsr	a0, EXCSAVE + XCHAL_DEBUGLEVEL
+	jx	a0
+
+
+
+/* Window overflow and underflow handlers.
+ * The handlers must be 64 bytes apart, first starting with the underflow
+ * handlers underflow-4 to underflow-12, then the overflow handlers
+ * overflow-4 to overflow-12.
+ *
+ * Note: We rerun the underflow handlers if we hit an exception, so
+ *	 we try to access any page that would cause a page fault early.
+ */
+
+	.section		.WindowVectors.text, "ax"
+
+
+/* 4-Register Window Overflow Vector (Handler) */
+
+	.align 64
+.global _WindowOverflow4
+_WindowOverflow4:
+	s32e	a0, a5, -16
+	s32e	a1, a5, -12
+	s32e	a2, a5,  -8
+	s32e	a3, a5,  -4
+	rfwo
+
+
+/* 4-Register Window Underflow Vector (Handler) */
+
+	.align 64
+.global _WindowUnderflow4
+_WindowUnderflow4:
+	l32e	a0, a5, -16
+	l32e	a1, a5, -12
+	l32e	a2, a5,  -8
+	l32e	a3, a5,  -4
+	rfwu
+
+
+/* 8-Register Window Overflow Vector (Handler) */
+
+	.align 64
+.global _WindowOverflow8
+_WindowOverflow8:
+	s32e	a0, a9, -16
+	l32e	a0, a1, -12
+	s32e	a2, a9,  -8
+	s32e	a1, a9, -12
+	s32e	a3, a9,  -4
+	s32e	a4, a0, -32
+	s32e	a5, a0, -28
+	s32e	a6, a0, -24
+	s32e	a7, a0, -20
+	rfwo
+
+/* 8-Register Window Underflow Vector (Handler) */
+
+	.align 64
+.global _WindowUnderflow8
+_WindowUnderflow8:
+	l32e	a1, a9, -12
+	l32e	a0, a9, -16
+	l32e	a7, a1, -12
+	l32e	a2, a9,  -8
+	l32e	a4, a7, -32
+	l32e	a3, a9,  -4
+	l32e	a5, a7, -28
+	l32e	a6, a7, -24
+	l32e	a7, a7, -20
+	rfwu
+
+
+/* 12-Register Window Overflow Vector (Handler) */
+
+	.align 64
+.global _WindowOverflow12
+_WindowOverflow12:
+	s32e	a0,  a13, -16
+	l32e	a0,  a1,  -12
+	s32e	a1,  a13, -12
+	s32e	a2,  a13,  -8
+	s32e	a3,  a13,  -4
+	s32e	a4,  a0,  -48
+	s32e	a5,  a0,  -44
+	s32e	a6,  a0,  -40
+	s32e	a7,  a0,  -36
+	s32e	a8,  a0,  -32
+	s32e	a9,  a0,  -28
+	s32e	a10, a0,  -24
+	s32e	a11, a0,  -20
+	rfwo
+
+/* 12-Register Window Underflow Vector (Handler) */
+
+	.align 64
+.global _WindowUnderflow12
+_WindowUnderflow12:
+	l32e	a1,  a13, -12
+	l32e	a0,  a13, -16
+	l32e	a11, a1,  -12
+	l32e	a2,  a13,  -8
+	l32e	a4,  a11, -48
+	l32e	a8,  a11, -32
+	l32e	a3,  a13,  -4
+	l32e	a5,  a11, -44
+	l32e	a6,  a11, -40
+	l32e	a7,  a11, -36
+	l32e	a9,  a11, -28
+	l32e	a10, a11, -24
+	l32e	a11, a11, -20
+	rfwu
+
+	.text
+
+
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
new file mode 100644
index 0000000..476b2b5
--- /dev/null
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -0,0 +1,341 @@
+/*
+ * arch/xtensa/kernel/vmlinux.lds.S
+ *
+ * Xtensa linker script
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ * Marc Gauthier <marc@tensilica.com, marc@alumni.uwaterloo.ca>
+ * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
+ */
+
+#include <asm-generic/vmlinux.lds.h>
+
+#include <linux/config.h>
+#define _NOCLANGUAGE
+#include <xtensa/config/core.h>
+#include <xtensa/config/system.h>
+OUTPUT_ARCH(xtensa)
+ENTRY(_start)
+
+#if XCHAL_MEMORY_ORDER == XTHAL_BIGENDIAN
+jiffies = jiffies_64 + 4;
+#else
+jiffies = jiffies_64;
+#endif
+
+#define KERNELOFFSET 0x1000
+
+/* Note: In the following macros, it would be nice to specify only the
+   vector name and section kind and construct "sym" and "section" using
+   CPP concatenation, but that does not work reliably.  Concatenating a
+   string with "." produces an invalid token.  CPP will not print a
+   warning because it thinks this is an assembly file, but it leaves
+   them as multiple tokens and there may or may not be whitespace
+   between them.  */
+
+/* Macro for a relocation entry */
+
+#define RELOCATE_ENTRY(sym, section)		\
+	LONG(sym ## _start);			\
+	LONG(sym ## _end);			\
+	LONG(LOADADDR(section))
+
+/* Macro to define a section for a vector.
+ *
+ * Use of the MIN function catches the types of errors illustrated in
+ * the following example:
+ *
+ * Assume the section .DoubleExceptionVector.literal is completely
+ * full.  Then a programmer adds code to .DoubleExceptionVector.text
+ * that produces another literal.  The final literal position will
+ * overlay onto the first word of the adjacent code section
+ * .DoubleExceptionVector.text.  (In practice, the literals will
+ * overwrite the code, and the first few instructions will be
+ * garbage.)
+ */
+
+#define SECTION_VECTOR(sym, section, addr, max_prevsec_size, prevsec)       \
+  section addr : AT((MIN(LOADADDR(prevsec) + max_prevsec_size,		    \
+		         LOADADDR(prevsec) + SIZEOF(prevsec)) + 3) & ~ 3)   \
+  {									    \
+    . = ALIGN(4);							    \
+    sym ## _start = ABSOLUTE(.);		 			    \
+    *(section)								    \
+    sym ## _end = ABSOLUTE(.);						    \
+  }
+
+/*
+ *  Mapping of input sections to output sections when linking.
+ */
+
+SECTIONS
+{
+  . = XCHAL_KSEG_CACHED_VADDR + KERNELOFFSET;
+  /* .text section */
+
+  _text = .;
+  _stext = .;
+  _ftext = .;
+
+  .text :
+  {
+    /* The .head.text section must be the first section! */
+    *(.head.text)
+    *(.literal .text)
+    *(.srom.text)
+    VMLINUX_SYMBOL(__sched_text_start) = .;
+    *(.sched.text.literal .sched.text)
+    VMLINUX_SYMBOL(__sched_text_end) = .;
+    VMLINUX_SYMBOL(__lock_text_start) = .;
+    *(.spinlock.text.literal .spinlock.text)
+    VMLINUX_SYMBOL(__lock_text_end) = .;
+
+  }
+  _etext = .;
+
+  . = ALIGN(16);
+
+  RODATA
+
+  /*  Relocation table */
+
+  . = ALIGN(16);
+  __boot_reloc_table_start = ABSOLUTE(.);
+
+  __relocate : {
+
+    RELOCATE_ENTRY(_WindowVectors_text,
+		   .WindowVectors.text);
+#if 0
+    RELOCATE_ENTRY(_KernelExceptionVector_literal,
+		   .KernelExceptionVector.literal);
+#endif
+    RELOCATE_ENTRY(_KernelExceptionVector_text,
+		   .KernelExceptionVector.text);
+#if 0
+    RELOCATE_ENTRY(_UserExceptionVector_literal,
+		   .UserExceptionVector.literal);
+#endif
+    RELOCATE_ENTRY(_UserExceptionVector_text,
+		   .UserExceptionVector.text);
+    RELOCATE_ENTRY(_DoubleExceptionVector_literal,
+		   .DoubleExceptionVector.literal);
+    RELOCATE_ENTRY(_DoubleExceptionVector_text,
+		   .DoubleExceptionVector.text);
+  }
+  __boot_reloc_table_end = ABSOLUTE(.) ;
+
+  .fixup   : { *(.fixup) }
+
+  . = ALIGN(16);
+
+  __ex_table : {
+    __start___ex_table = .;
+    *(__ex_table)
+    __stop___ex_table = .;
+  }
+
+  /* Data section */
+
+  . = ALIGN(XCHAL_ICACHE_LINESIZE);
+  _fdata = .;
+  .data :
+  {
+    *(.data) CONSTRUCTORS
+    . = ALIGN(XCHAL_ICACHE_LINESIZE);
+    *(.data.cacheline_aligned)
+  }
+
+  _edata = .;
+
+  /* The initial task */
+  . = ALIGN(8192);
+  .data.init_task : { *(.data.init_task) }
+
+  /* Initialization code and data: */
+
+  . = ALIGN(1<<XCHAL_MMU_MIN_PTE_PAGE_SIZE);
+  __init_begin = .;
+  .init.text : {
+  	_sinittext = .;
+	*(.init.text.literal) *(.init.text)
+	_einittext = .;
+  }
+
+  .init.data :
+  {
+    *(.init.data)
+    . = ALIGN(0x4);
+    __tagtable_begin = .;
+    *(.taglist)
+    __tagtable_end = .;
+  }
+
+  . = ALIGN(XCHAL_ICACHE_LINESIZE);
+
+  __setup_start = .;
+  .init.setup : { *(.init.setup) }
+  __setup_end = .;
+
+  __initcall_start = .;
+  .initcall.init : {
+  	*(.initcall1.init)
+  	*(.initcall2.init)
+  	*(.initcall3.init)
+  	*(.initcall4.init)
+  	*(.initcall5.init)
+  	*(.initcall6.init)
+  	*(.initcall7.init)
+  }
+  __initcall_end = .;
+
+  __con_initcall_start = .;
+  .con_initcall.init : { *(.con_initcall.init) }
+  __con_initcall_end = .;
+
+  SECURITY_INIT
+
+  . = ALIGN(4);
+
+  __start___ftr_fixup = .;
+  __ftr_fixup : { *(__ftr_fixup) }
+  __stop___ftr_fixup = .;
+
+  . = ALIGN(32);
+  __per_cpu_start = .;
+  .data.percpu  : { *(.data.percpu) }
+  __per_cpu_end = .;
+
+  . = ALIGN(4096);
+  __initramfs_start =.;
+  .init.ramfs : { *(.init.ramfs) }
+  __initramfs_end = .;
+
+  /* We need this dummy segment here */
+
+  . = ALIGN(4);
+  .dummy : { LONG(0) }
+
+  /* The vectors are relocated to the real position at startup time */
+
+  SECTION_VECTOR (_WindowVectors_text,
+		  .WindowVectors.text,
+		  XCHAL_WINDOW_VECTORS_VADDR, 4,
+		  .dummy)
+  SECTION_VECTOR (_DebugInterruptVector_literal,
+		  .DebugInterruptVector.literal,
+		  XCHAL_INTLEVEL_VECTOR_VADDR(XCHAL_DEBUGLEVEL) - 4,
+		  SIZEOF(.WindowVectors.text),
+		  .WindowVectors.text)
+  SECTION_VECTOR (_DebugInterruptVector_text,
+		  .DebugInterruptVector.text,
+		  XCHAL_INTLEVEL_VECTOR_VADDR(XCHAL_DEBUGLEVEL),
+		  4,
+		  .DebugInterruptVector.literal)
+  SECTION_VECTOR (_KernelExceptionVector_literal,
+		  .KernelExceptionVector.literal,
+		  XCHAL_KERNELEXC_VECTOR_VADDR - 4,
+		  SIZEOF(.DebugInterruptVector.text),
+		  .DebugInterruptVector.text)
+  SECTION_VECTOR (_KernelExceptionVector_text,
+		  .KernelExceptionVector.text,
+		  XCHAL_KERNELEXC_VECTOR_VADDR,
+		  4,
+		  .KernelExceptionVector.literal)
+  SECTION_VECTOR (_UserExceptionVector_literal,
+		  .UserExceptionVector.literal,
+		  XCHAL_USEREXC_VECTOR_VADDR - 4,
+		  SIZEOF(.KernelExceptionVector.text),
+		  .KernelExceptionVector.text)
+  SECTION_VECTOR (_UserExceptionVector_text,
+		  .UserExceptionVector.text,
+		  XCHAL_USEREXC_VECTOR_VADDR,
+		  4,
+		  .UserExceptionVector.literal)
+  SECTION_VECTOR (_DoubleExceptionVector_literal,
+		  .DoubleExceptionVector.literal,
+		  XCHAL_DOUBLEEXC_VECTOR_VADDR - 16,
+		  SIZEOF(.UserExceptionVector.text),
+		  .UserExceptionVector.text)
+  SECTION_VECTOR (_DoubleExceptionVector_text,
+		  .DoubleExceptionVector.text,
+		  XCHAL_DOUBLEEXC_VECTOR_VADDR,
+		  32,
+		  .DoubleExceptionVector.literal)
+
+  . = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3;
+  . = ALIGN(1<<XCHAL_MMU_MIN_PTE_PAGE_SIZE);
+
+  __init_end = .;
+
+  . = ALIGN(8192);
+
+  /* BSS section */
+  _bss_start = .;
+  .sbss : { *(.sbss) *(.scommon) }
+  .bss : { *(COMMON) *(.bss) }
+  _bss_end = .;
+  _end = .;
+
+  /* only used by the boot loader  */
+
+  . = ALIGN(0x10);
+  .bootstrap : { *(.bootstrap.literal .bootstrap.text .bootstrap.data) }
+
+  . = ALIGN(0x1000);
+  __initrd_start = .;
+  .initrd : { *(.initrd) }
+  __initrd_end = .;
+
+  .ResetVector.text XCHAL_RESET_VECTOR_VADDR :
+  {
+    *(.ResetVector.text)
+  }
+
+
+  /* Sections to be discarded */
+  /DISCARD/ :
+  {
+        *(.text.exit)
+	*(.text.exit.literal)
+        *(.data.exit)
+        *(.exitcall.exit)
+  }
+
+
+  .debug  0 :  { *(.debug) }
+  .line  0 :  { *(.line) }
+  .debug_srcinfo  0 :  { *(.debug_srcinfo) }
+  .debug_sfnames  0 :  { *(.debug_sfnames) }
+  .debug_aranges  0 :  { *(.debug_aranges) }
+  .debug_pubnames  0 :  { *(.debug_pubnames) }
+  .debug_info  0 :  { *(.debug_info) }
+  .debug_abbrev  0 :  { *(.debug_abbrev) }
+  .debug_line  0 :  { *(.debug_line) }
+  .debug_frame  0 :  { *(.debug_frame) }
+  .debug_str  0 :  { *(.debug_str) }
+  .debug_loc  0 :  { *(.debug_loc) }
+  .debug_macinfo  0 :  { *(.debug_macinfo) }
+  .debug_weaknames  0 :  { *(.debug_weaknames) }
+  .debug_funcnames  0 :  { *(.debug_funcnames) }
+  .debug_typenames  0 :  { *(.debug_typenames) }
+  .debug_varnames  0 :  { *(.debug_varnames) }
+
+  .xt.insn 0 :
+  {
+    *(.xt.insn)
+    *(.gnu.linkonce.x*)
+  }
+
+  .xt.lit 0 :
+  {
+    *(.xt.lit)
+    *(.gnu.linkonce.p*)
+  }
+}
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c
new file mode 100644
index 0000000..efae56a
--- /dev/null
+++ b/arch/xtensa/kernel/xtensa_ksyms.c
@@ -0,0 +1,123 @@
+/*
+ * arch/xtensa/kernel/xtensa_ksyms.c
+ *
+ * Export Xtensa-specific functions for loadable modules.
+ *
+ * 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) 2001 - 2005  Tensilica Inc.
+ *
+ * Joe Taylor <joe@tensilica.com>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <asm/irq.h>
+#include <linux/in6.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+
+#include <asm/uaccess.h>
+#include <asm/checksum.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/semaphore.h>
+#ifdef CONFIG_BLK_DEV_FD
+#include <asm/floppy.h>
+#endif
+#ifdef CONFIG_NET
+#include <net/checksum.h>
+#endif /* CONFIG_NET */
+
+
+/*
+ * String functions
+ */
+EXPORT_SYMBOL(memcmp);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memchr);
+EXPORT_SYMBOL(strcat);
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strpbrk);
+EXPORT_SYMBOL(strncat);
+EXPORT_SYMBOL(strnlen);
+EXPORT_SYMBOL(strrchr);
+EXPORT_SYMBOL(strstr);
+
+EXPORT_SYMBOL(enable_irq);
+EXPORT_SYMBOL(disable_irq);
+EXPORT_SYMBOL(kernel_thread);
+
+/*
+ * gcc internal math functions
+ */
+extern long long __ashrdi3(long long, int);
+extern long long __ashldi3(long long, int);
+extern long long __lshrdi3(long long, int);
+extern int __divsi3(int, int);
+extern int __modsi3(int, int);
+extern long long __muldi3(long long, long long);
+extern int __mulsi3(int, int);
+extern unsigned int __udivsi3(unsigned int, unsigned int);
+extern unsigned int __umodsi3(unsigned int, unsigned int);
+extern unsigned long long __umoddi3(unsigned long long, unsigned long long);
+extern unsigned long long __udivdi3(unsigned long long, unsigned long long);
+
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__divsi3);
+EXPORT_SYMBOL(__modsi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__mulsi3);
+EXPORT_SYMBOL(__udivsi3);
+EXPORT_SYMBOL(__umodsi3);
+EXPORT_SYMBOL(__udivdi3);
+EXPORT_SYMBOL(__umoddi3);
+
+/*
+ * Semaphore operations
+ */
+EXPORT_SYMBOL(__down);
+EXPORT_SYMBOL(__down_interruptible);
+EXPORT_SYMBOL(__down_trylock);
+EXPORT_SYMBOL(__up);
+
+#ifdef CONFIG_NET
+/*
+ * Networking support
+ */
+EXPORT_SYMBOL(csum_partial_copy_generic);
+#endif /* CONFIG_NET */
+
+/*
+ * Architecture-specific symbols
+ */
+EXPORT_SYMBOL(__xtensa_copy_user);
+
+/*
+ * Kernel hacking ...
+ */
+
+#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
+// FIXME EXPORT_SYMBOL(screen_info);
+#endif
+
+EXPORT_SYMBOL(get_wchan);
+
+EXPORT_SYMBOL(outsb);
+EXPORT_SYMBOL(outsw);
+EXPORT_SYMBOL(outsl);
+EXPORT_SYMBOL(insb);
+EXPORT_SYMBOL(insw);
+EXPORT_SYMBOL(insl);
diff --git a/arch/xtensa/lib/Makefile b/arch/xtensa/lib/Makefile
new file mode 100644
index 0000000..ed935b5
--- /dev/null
+++ b/arch/xtensa/lib/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for Xtensa-specific library files.
+#
+
+lib-y	+= memcopy.o memset.o checksum.o strcasecmp.o \
+	   usercopy.o strncpy_user.o strnlen_user.o
+lib-$(CONFIG_PCI) += pci-auto.o
diff --git a/arch/xtensa/lib/checksum.S b/arch/xtensa/lib/checksum.S
new file mode 100644
index 0000000..e2d64df
--- /dev/null
+++ b/arch/xtensa/lib/checksum.S
@@ -0,0 +1,410 @@
+/*
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the  BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		IP/TCP/UDP checksumming routines
+ *
+ * Xtensa version:  Copyright (C) 2001 Tensilica, Inc. by Kevin Chea
+ *                  Optimized by Joe Taylor
+ *
+ *		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 <asm/errno.h>
+#include <linux/linkage.h>
+#define _ASMLANGUAGE
+#include <xtensa/config/core.h>
+
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+
+/*
+ * unsigned int csum_partial(const unsigned char *buf, int len,
+ *                           unsigned int sum);
+ *    a2 = buf
+ *    a3 = len
+ *    a4 = sum
+ *
+ * This function assumes 2- or 4-byte alignment.  Other alignments will fail!
+ */
+
+/* ONES_ADD converts twos-complement math to ones-complement. */
+#define ONES_ADD(sum, val)	  \
+	add	sum, sum, val	; \
+	bgeu	sum, val, 99f	; \
+	addi	sum, sum, 1	; \
+99:				;
+
+.text
+ENTRY(csum_partial)
+	  /*
+	   * Experiments with Ethernet and SLIP connections show that buf
+	   * is aligned on either a 2-byte or 4-byte boundary.
+	   */
+	entry	sp, 32
+	extui	a5, a2, 0, 2
+	bnez	a5, 8f		/* branch if 2-byte aligned */
+	/* Fall-through on common case, 4-byte alignment */
+1:
+	srli	a5, a3, 5	/* 32-byte chunks */
+#if XCHAL_HAVE_LOOPS
+	loopgtz	a5, 2f
+#else
+	beqz	a5, 2f
+	slli	a5, a5, 5
+	add	a5, a5, a2	/* a5 = end of last 32-byte chunk */
+.Loop1:
+#endif
+	l32i	a6, a2, 0
+	l32i	a7, a2, 4
+	ONES_ADD(a4, a6)
+	ONES_ADD(a4, a7)
+	l32i	a6, a2, 8
+	l32i	a7, a2, 12
+	ONES_ADD(a4, a6)
+	ONES_ADD(a4, a7)
+	l32i	a6, a2, 16
+	l32i	a7, a2, 20
+	ONES_ADD(a4, a6)
+	ONES_ADD(a4, a7)
+	l32i	a6, a2, 24
+	l32i	a7, a2, 28
+	ONES_ADD(a4, a6)
+	ONES_ADD(a4, a7)
+	addi	a2, a2, 4*8
+#if !XCHAL_HAVE_LOOPS
+	blt	a2, a5, .Loop1
+#endif
+2:
+	extui	a5, a3, 2, 3	/* remaining 4-byte chunks */
+#if XCHAL_HAVE_LOOPS
+	loopgtz	a5, 3f
+#else
+	beqz	a5, 3f
+	slli	a5, a5, 2
+	add	a5, a5, a2	/* a5 = end of last 4-byte chunk */
+.Loop2:
+#endif
+	l32i	a6, a2, 0
+	ONES_ADD(a4, a6)
+	addi	a2, a2, 4
+#if !XCHAL_HAVE_LOOPS
+	blt	a2, a5, .Loop2
+#endif
+3:
+	_bbci.l	a3, 1, 5f	/* remaining 2-byte chunk */
+	l16ui	a6, a2, 0
+	ONES_ADD(a4, a6)
+	addi	a2, a2, 2
+5:
+	_bbci.l	a3, 0, 7f	/* remaining 1-byte chunk */
+6:	l8ui	a6, a2, 0
+#ifdef __XTENSA_EB__
+	slli	a6, a6, 8	/* load byte into bits 8..15 */
+#endif
+	ONES_ADD(a4, a6)
+7:
+	mov	a2, a4
+	retw
+
+	/* uncommon case, buf is 2-byte aligned */
+8:
+	beqz	a3, 7b		/* branch if len == 0 */
+	beqi	a3, 1, 6b	/* branch if len == 1 */
+
+	extui	a5, a2, 0, 1
+	bnez	a5, 8f		/* branch if 1-byte aligned */
+
+	l16ui	a6, a2, 0	/* common case, len >= 2 */
+	ONES_ADD(a4, a6)
+	addi	a2, a2, 2	/* adjust buf */
+	addi	a3, a3, -2	/* adjust len */
+	j	1b		/* now buf is 4-byte aligned */
+
+	/* case: odd-byte aligned, len > 1
+	 * This case is dog slow, so don't give us an odd address.
+	 * (I don't think this ever happens, but just in case.)
+	 */
+8:
+	srli	a5, a3, 2	/* 4-byte chunks */
+#if XCHAL_HAVE_LOOPS
+	loopgtz	a5, 2f
+#else
+	beqz	a5, 2f
+	slli	a5, a5, 2
+	add	a5, a5, a2	/* a5 = end of last 4-byte chunk */
+.Loop3:
+#endif
+	l8ui	a6, a2, 0	/* bits 24..31 */
+	l16ui	a7, a2, 1	/* bits  8..23 */
+	l8ui	a8, a2, 3	/* bits  0.. 8 */
+#ifdef	__XTENSA_EB__
+	slli	a6, a6, 24
+#else
+	slli	a8, a8, 24
+#endif
+	slli	a7, a7, 8
+	or	a7, a7, a6
+	or	a7, a7, a8
+	ONES_ADD(a4, a7)
+	addi	a2, a2, 4
+#if !XCHAL_HAVE_LOOPS
+	blt	a2, a5, .Loop3
+#endif
+2:
+	_bbci.l	a3, 1, 3f	/* remaining 2-byte chunk, still odd addr */
+	l8ui	a6, a2, 0
+	l8ui	a7, a2, 1
+#ifdef	__XTENSA_EB__
+	slli	a6, a6, 8
+#else
+	slli	a7, a7, 8
+#endif
+	or	a7, a7, a6
+	ONES_ADD(a4, a7)
+	addi	a2, a2, 2
+3:
+	j	5b		/* branch to handle the remaining byte */
+
+
+
+/*
+ * Copy from ds while checksumming, otherwise like csum_partial
+ *
+ * The macros SRC and DST specify the type of access for the instruction.
+ * thus we can call a custom exception handler for each access type.
+ */
+
+#define SRC(y...)			\
+	9999: y;			\
+	.section __ex_table, "a";	\
+	.long 9999b, 6001f	;	\
+	.previous
+
+#define DST(y...)			\
+	9999: y;			\
+	.section __ex_table, "a";	\
+	.long 9999b, 6002f	;	\
+	.previous
+
+/*
+unsigned int csum_partial_copy_generic (const char *src, char *dst, int len,
+					int sum, int *src_err_ptr, int *dst_err_ptr)
+	a2  = src
+	a3  = dst
+	a4  = len
+	a5  = sum
+	a6  = src_err_ptr
+	a7  = dst_err_ptr
+	a8  = temp
+	a9  = temp
+	a10 = temp
+	a11 = original len for exception handling
+	a12 = original dst for exception handling
+
+    This function is optimized for 4-byte aligned addresses.  Other
+    alignments work, but not nearly as efficiently.
+ */
+
+ENTRY(csum_partial_copy_generic)
+	entry	sp, 32
+	mov	a12, a3
+	mov	a11, a4
+	or	a10, a2, a3
+
+	/* We optimize the following alignment tests for the 4-byte
+	aligned case.  Two bbsi.l instructions might seem more optimal
+	(commented out below).  However, both labels 5: and 3: are out
+	of the imm8 range, so the assembler relaxes them into
+	equivalent bbci.l, j combinations, which is actually
+	slower. */
+
+	extui	a9, a10, 0, 2
+	beqz	a9, 1f		/* branch if both are 4-byte aligned */
+	bbsi.l	a10, 0, 5f	/* branch if one address is odd */
+	j	3f		/* one address is 2-byte aligned */
+
+/*	_bbsi.l	a10, 0, 5f */	/* branch if odd address */
+/*	_bbsi.l	a10, 1, 3f */	/* branch if 2-byte-aligned address */
+
+1:
+	/* src and dst are both 4-byte aligned */
+	srli	a10, a4, 5	/* 32-byte chunks */
+#if XCHAL_HAVE_LOOPS
+	loopgtz	a10, 2f
+#else
+	beqz	a10, 2f
+	slli	a10, a10, 5
+	add	a10, a10, a2	/* a10 = end of last 32-byte src chunk */
+.Loop5:
+#endif
+SRC(	l32i	a9, a2, 0	)
+SRC(	l32i	a8, a2, 4	)
+DST(	s32i	a9, a3, 0	)
+DST(	s32i	a8, a3, 4	)
+	ONES_ADD(a5, a9)
+	ONES_ADD(a5, a8)
+SRC(	l32i	a9, a2, 8	)
+SRC(	l32i	a8, a2, 12	)
+DST(	s32i	a9, a3, 8	)
+DST(	s32i	a8, a3, 12	)
+	ONES_ADD(a5, a9)
+	ONES_ADD(a5, a8)
+SRC(	l32i	a9, a2, 16	)
+SRC(	l32i	a8, a2, 20	)
+DST(	s32i	a9, a3, 16	)
+DST(	s32i	a8, a3, 20	)
+	ONES_ADD(a5, a9)
+	ONES_ADD(a5, a8)
+SRC(	l32i	a9, a2, 24	)
+SRC(	l32i	a8, a2, 28	)
+DST(	s32i	a9, a3, 24	)
+DST(	s32i	a8, a3, 28	)
+	ONES_ADD(a5, a9)
+	ONES_ADD(a5, a8)
+	addi	a2, a2, 32
+	addi	a3, a3, 32
+#if !XCHAL_HAVE_LOOPS
+	blt	a2, a10, .Loop5
+#endif
+2:
+	extui	a10, a4, 2, 3	/* remaining 4-byte chunks */
+	extui	a4, a4, 0, 2	/* reset len for general-case, 2-byte chunks */
+#if XCHAL_HAVE_LOOPS
+	loopgtz	a10, 3f
+#else
+	beqz	a10, 3f
+	slli	a10, a10, 2
+	add	a10, a10, a2	/* a10 = end of last 4-byte src chunk */
+.Loop6:
+#endif
+SRC(	l32i	a9, a2, 0	)
+DST(	s32i	a9, a3, 0	)
+	ONES_ADD(a5, a9)
+	addi	a2, a2, 4
+	addi	a3, a3, 4
+#if !XCHAL_HAVE_LOOPS
+	blt	a2, a10, .Loop6
+#endif
+3:
+	/*
+	Control comes to here in two cases: (1) It may fall through
+	to here from the 4-byte alignment case to process, at most,
+	one 2-byte chunk.  (2) It branches to here from above if
+	either src or dst is 2-byte aligned, and we process all bytes
+	here, except for perhaps a trailing odd byte.  It's
+	inefficient, so align your addresses to 4-byte boundaries.
+
+	a2 = src
+	a3 = dst
+	a4 = len
+	a5 = sum
+	*/
+	srli	a10, a4, 1	/* 2-byte chunks */
+#if XCHAL_HAVE_LOOPS
+	loopgtz	a10, 4f
+#else
+	beqz	a10, 4f
+	slli	a10, a10, 1
+	add	a10, a10, a2	/* a10 = end of last 2-byte src chunk */
+.Loop7:
+#endif
+SRC(	l16ui	a9, a2, 0	)
+DST(	s16i	a9, a3, 0	)
+	ONES_ADD(a5, a9)
+	addi	a2, a2, 2
+	addi	a3, a3, 2
+#if !XCHAL_HAVE_LOOPS
+	blt	a2, a10, .Loop7
+#endif
+4:
+	/* This section processes a possible trailing odd byte. */
+	_bbci.l	a4, 0, 8f	/* 1-byte chunk */
+SRC(	l8ui	a9, a2, 0	)
+DST(	s8i	a9, a3, 0	)
+#ifdef __XTENSA_EB__
+	slli	a9, a9, 8	/* shift byte to bits 8..15 */
+#endif
+	ONES_ADD(a5, a9)
+8:
+	mov	a2, a5
+	retw
+
+5:
+	/* Control branch to here when either src or dst is odd.  We
+	process all bytes using 8-bit accesses.  Grossly inefficient,
+	so don't feed us an odd address. */
+
+	srli	a10, a4, 1	/* handle in pairs for 16-bit csum */
+#if XCHAL_HAVE_LOOPS
+	loopgtz	a10, 6f
+#else
+	beqz	a10, 6f
+	slli	a10, a10, 1
+	add	a10, a10, a2	/* a10 = end of last odd-aligned, 2-byte src chunk */
+.Loop8:
+#endif
+SRC(	l8ui	a9, a2, 0	)
+SRC(	l8ui	a8, a2, 1	)
+DST(	s8i	a9, a3, 0	)
+DST(	s8i	a8, a3, 1	)
+#ifdef __XTENSA_EB__
+	slli	a9, a9, 8	/* combine into a single 16-bit value */
+#else				/* for checksum computation */
+	slli	a8, a8, 8
+#endif
+	or	a9, a9, a8
+	ONES_ADD(a5, a9)
+	addi	a2, a2, 2
+	addi	a3, a3, 2
+#if !XCHAL_HAVE_LOOPS
+	blt	a2, a10, .Loop8
+#endif
+6:
+	j	4b		/* process the possible trailing odd byte */
+
+
+# Exception handler:
+.section .fixup, "ax"
+/*
+	a6  = src_err_ptr
+	a7  = dst_err_ptr
+	a11 = original len for exception handling
+	a12 = original dst for exception handling
+*/
+
+6001:
+	_movi	a2, -EFAULT
+	s32i	a2, a6, 0	/* src_err_ptr */
+
+	# clear the complete destination - computing the rest
+	# is too much work
+	movi	a2, 0
+#if XCHAL_HAVE_LOOPS
+	loopgtz	a11, 2f
+#else
+	beqz	a11, 2f
+	add	a11, a11, a12	/* a11 = ending address */
+.Leloop:
+#endif
+	s8i	a2, a12, 0
+	addi	a12, a12, 1
+#if !XCHAL_HAVE_LOOPS
+	blt	a12, a11, .Leloop
+#endif
+2:
+	retw
+
+6002:
+	movi	a2, -EFAULT
+	s32i	a2, a7, 0	/* dst_err_ptr */
+	movi	a2, 0
+	retw
+
+.previous
+
diff --git a/arch/xtensa/lib/memcopy.S b/arch/xtensa/lib/memcopy.S
new file mode 100644
index 0000000..e8f6d7e
--- /dev/null
+++ b/arch/xtensa/lib/memcopy.S
@@ -0,0 +1,315 @@
+/*
+ * arch/xtensa/lib/hal/memcopy.S -- Core HAL library functions
+ * xthal_memcpy and xthal_bcopy
+ *
+ * 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) 2002 - 2005 Tensilica Inc.
+ */
+
+#include <xtensa/coreasm.h>
+
+	.macro	src_b	r, w0, w1
+#ifdef __XTENSA_EB__
+	src	\r, \w0, \w1
+#else
+	src	\r, \w1, \w0
+#endif
+	.endm
+
+	.macro	ssa8	r
+#ifdef __XTENSA_EB__
+	ssa8b	\r
+#else
+	ssa8l	\r
+#endif
+	.endm
+
+
+/*
+ * void *memcpy(void *dst, const void *src, size_t len);
+ * void *memmove(void *dst, const void *src, size_t len);
+ * void *bcopy(const void *src, void *dst, size_t len);
+ *
+ * This function is intended to do the same thing as the standard
+ * library function memcpy() (or bcopy()) for most cases.
+ * However, where the source and/or destination references
+ * an instruction RAM or ROM or a data RAM or ROM, that
+ * source and/or destination will always be accessed with
+ * 32-bit load and store instructions (as required for these
+ * types of devices).
+ *
+ * !!!!!!!  XTFIXME:
+ * !!!!!!!  Handling of IRAM/IROM has not yet
+ * !!!!!!!  been implemented.
+ *
+ * The bcopy version is provided here to avoid the overhead
+ * of an extra call, for callers that require this convention.
+ *
+ * The (general case) algorithm is as follows:
+ *   If destination is unaligned, align it by conditionally
+ *     copying 1 and 2 bytes.
+ *   If source is aligned,
+ *     do 16 bytes with a loop, and then finish up with
+ *     8, 4, 2, and 1 byte copies conditional on the length;
+ *   else (if source is unaligned),
+ *     do the same, but use SRC to align the source data.
+ *   This code tries to use fall-through branches for the common
+ *     case of aligned source and destination and multiple
+ *     of 4 (or 8) length.
+ *
+ * Register use:
+ *	a0/ return address
+ *	a1/ stack pointer
+ *	a2/ return value
+ *	a3/ src
+ *	a4/ length
+ *	a5/ dst
+ *	a6/ tmp
+ *	a7/ tmp
+ *	a8/ tmp
+ *	a9/ tmp
+ *	a10/ tmp
+ *	a11/ tmp
+ */
+
+	.text
+	.align	4
+	.global	bcopy
+	.type   bcopy,@function
+bcopy:
+	entry	sp, 16		# minimal stack frame
+	# a2=src, a3=dst, a4=len
+	mov	a5, a3		# copy dst so that a2 is return value
+	mov	a3, a2
+	mov	a2, a5
+	j	.Lcommon	# go to common code for memcpy+bcopy
+
+
+/*
+ * Byte by byte copy
+ */
+	.align	4
+	.byte	0		# 1 mod 4 alignment for LOOPNEZ
+				# (0 mod 4 alignment for LBEG)
+.Lbytecopy:
+#if XCHAL_HAVE_LOOPS
+	loopnez	a4, .Lbytecopydone
+#else /* !XCHAL_HAVE_LOOPS */
+	beqz	a4, .Lbytecopydone
+	add	a7, a3, a4	# a7 = end address for source
+#endif /* !XCHAL_HAVE_LOOPS */
+.Lnextbyte:
+	l8ui	a6, a3, 0
+	addi	a3, a3, 1
+	s8i	a6, a5, 0
+	addi	a5, a5, 1
+#if !XCHAL_HAVE_LOOPS
+	blt	a3, a7, .Lnextbyte
+#endif /* !XCHAL_HAVE_LOOPS */
+.Lbytecopydone:
+	retw
+
+/*
+ * Destination is unaligned
+ */
+
+	.align	4
+.Ldst1mod2:	# dst is only byte aligned
+	_bltui	a4, 7, .Lbytecopy	# do short copies byte by byte
+
+	# copy 1 byte
+	l8ui	a6, a3,  0
+	addi	a3, a3,  1
+	addi	a4, a4, -1
+	s8i	a6, a5,  0
+	addi	a5, a5,  1
+	_bbci.l	a5, 1, .Ldstaligned	# if dst is now aligned, then
+					# return to main algorithm
+.Ldst2mod4:	# dst 16-bit aligned
+	# copy 2 bytes
+	_bltui	a4, 6, .Lbytecopy	# do short copies byte by byte
+	l8ui	a6, a3,  0
+	l8ui	a7, a3,  1
+	addi	a3, a3,  2
+	addi	a4, a4, -2
+	s8i	a6, a5,  0
+	s8i	a7, a5,  1
+	addi	a5, a5,  2
+	j	.Ldstaligned	# dst is now aligned, return to main algorithm
+
+	.align	4
+	.global	memcpy
+	.type   memcpy,@function
+memcpy:
+	.global	memmove
+	.type   memmove,@function
+memmove:
+
+	entry	sp, 16		# minimal stack frame
+	# a2/ dst, a3/ src, a4/ len
+	mov	a5, a2		# copy dst so that a2 is return value
+.Lcommon:
+	_bbsi.l	a2, 0, .Ldst1mod2	# if dst is 1 mod 2
+	_bbsi.l	a2, 1, .Ldst2mod4	# if dst is 2 mod 4
+.Ldstaligned:	# return here from .Ldst?mod? once dst is aligned
+	srli	a7, a4, 4	# number of loop iterations with 16B
+				# per iteration
+	movi	a8, 3		# if source is not aligned,
+	_bany	a3, a8, .Lsrcunaligned	# then use shifting copy
+	/*
+	 * Destination and source are word-aligned, use word copy.
+	 */
+	# copy 16 bytes per iteration for word-aligned dst and word-aligned src
+#if XCHAL_HAVE_LOOPS
+	loopnez	a7, .Loop1done
+#else /* !XCHAL_HAVE_LOOPS */
+	beqz	a7, .Loop1done
+	slli	a8, a7, 4
+	add	a8, a8, a3	# a8 = end of last 16B source chunk
+#endif /* !XCHAL_HAVE_LOOPS */
+.Loop1:
+	l32i	a6, a3,  0
+	l32i	a7, a3,  4
+	s32i	a6, a5,  0
+	l32i	a6, a3,  8
+	s32i	a7, a5,  4
+	l32i	a7, a3, 12
+	s32i	a6, a5,  8
+	addi	a3, a3, 16
+	s32i	a7, a5, 12
+	addi	a5, a5, 16
+#if !XCHAL_HAVE_LOOPS
+	blt	a3, a8, .Loop1
+#endif /* !XCHAL_HAVE_LOOPS */
+.Loop1done:
+	bbci.l	a4, 3, .L2
+	# copy 8 bytes
+	l32i	a6, a3,  0
+	l32i	a7, a3,  4
+	addi	a3, a3,  8
+	s32i	a6, a5,  0
+	s32i	a7, a5,  4
+	addi	a5, a5,  8
+.L2:
+	bbsi.l	a4, 2, .L3
+	bbsi.l	a4, 1, .L4
+	bbsi.l	a4, 0, .L5
+	retw
+.L3:
+	# copy 4 bytes
+	l32i	a6, a3,  0
+	addi	a3, a3,  4
+	s32i	a6, a5,  0
+	addi	a5, a5,  4
+	bbsi.l	a4, 1, .L4
+	bbsi.l	a4, 0, .L5
+	retw
+.L4:
+	# copy 2 bytes
+	l16ui	a6, a3,  0
+	addi	a3, a3,  2
+	s16i	a6, a5,  0
+	addi	a5, a5,  2
+	bbsi.l	a4, 0, .L5
+	retw
+.L5:
+	# copy 1 byte
+	l8ui	a6, a3,  0
+	s8i	a6, a5,  0
+	retw
+
+/*
+ * Destination is aligned, Source is unaligned
+ */
+
+	.align	4
+.Lsrcunaligned:
+	_beqz	a4, .Ldone	# avoid loading anything for zero-length copies
+	# copy 16 bytes per iteration for word-aligned dst and unaligned src
+	ssa8	a3		# set shift amount from byte offset
+#define SIM_CHECKS_ALIGNMENT	1	/* set to 1 when running on ISS (simulator) with the
+					   lint or ferret client, or 0 to save a few cycles */
+#if XCHAL_UNALIGNED_LOAD_EXCEPTION || SIM_CHECKS_ALIGNMENT
+	and	a11, a3, a8	# save unalignment offset for below
+	sub	a3, a3, a11	# align a3
+#endif
+	l32i	a6, a3, 0	# load first word
+#if XCHAL_HAVE_LOOPS
+	loopnez	a7, .Loop2done
+#else /* !XCHAL_HAVE_LOOPS */
+	beqz	a7, .Loop2done
+	slli	a10, a7, 4
+	add	a10, a10, a3	# a10 = end of last 16B source chunk
+#endif /* !XCHAL_HAVE_LOOPS */
+.Loop2:
+	l32i	a7, a3,  4
+	l32i	a8, a3,  8
+	src_b	a6, a6, a7
+	s32i	a6, a5,  0
+	l32i	a9, a3, 12
+	src_b	a7, a7, a8
+	s32i	a7, a5,  4
+	l32i	a6, a3, 16
+	src_b	a8, a8, a9
+	s32i	a8, a5,  8
+	addi	a3, a3, 16
+	src_b	a9, a9, a6
+	s32i	a9, a5, 12
+	addi	a5, a5, 16
+#if !XCHAL_HAVE_LOOPS
+	blt	a3, a10, .Loop2
+#endif /* !XCHAL_HAVE_LOOPS */
+.Loop2done:
+	bbci.l	a4, 3, .L12
+	# copy 8 bytes
+	l32i	a7, a3,  4
+	l32i	a8, a3,  8
+	src_b	a6, a6, a7
+	s32i	a6, a5,  0
+	addi	a3, a3,  8
+	src_b	a7, a7, a8
+	s32i	a7, a5,  4
+	addi	a5, a5,  8
+	mov	a6, a8
+.L12:
+	bbci.l	a4, 2, .L13
+	# copy 4 bytes
+	l32i	a7, a3,  4
+	addi	a3, a3,  4
+	src_b	a6, a6, a7
+	s32i	a6, a5,  0
+	addi	a5, a5,  4
+	mov	a6, a7
+.L13:
+#if XCHAL_UNALIGNED_LOAD_EXCEPTION || SIM_CHECKS_ALIGNMENT
+	add	a3, a3, a11	# readjust a3 with correct misalignment
+#endif
+	bbsi.l	a4, 1, .L14
+	bbsi.l	a4, 0, .L15
+.Ldone:	retw
+.L14:
+	# copy 2 bytes
+	l8ui	a6, a3,  0
+	l8ui	a7, a3,  1
+	addi	a3, a3,  2
+	s8i	a6, a5,  0
+	s8i	a7, a5,  1
+	addi	a5, a5,  2
+	bbsi.l	a4, 0, .L15
+	retw
+.L15:
+	# copy 1 byte
+	l8ui	a6, a3,  0
+	s8i	a6, a5,  0
+	retw
+
+/*
+ * Local Variables:
+ * mode:fundamental
+ * comment-start: "# "
+ * comment-start-skip: "# *"
+ * End:
+ */
diff --git a/arch/xtensa/lib/memset.S b/arch/xtensa/lib/memset.S
new file mode 100644
index 0000000..4de2513
--- /dev/null
+++ b/arch/xtensa/lib/memset.S
@@ -0,0 +1,160 @@
+/*
+ *  arch/xtensa/lib/memset.S
+ *
+ *  ANSI C standard library function memset
+ *  (Well, almost.  .fixup code might return zero.)
+ *
+ *  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) 2002 Tensilica Inc.
+ */
+
+#include <xtensa/coreasm.h>
+
+/*
+ * void *memset(void *dst, int c, size_t length)
+ *
+ * The algorithm is as follows:
+ *   Create a word with c in all byte positions
+ *   If the destination is aligned,
+ *     do 16B chucks with a loop, and then finish up with
+ *     8B, 4B, 2B, and 1B stores conditional on the length.
+ *   If destination is unaligned, align it by conditionally
+ *     setting 1B and 2B and then go to aligned case.
+ *   This code tries to use fall-through branches for the common
+ *     case of an aligned destination (except for the branches to
+ *     the alignment labels).
+ */
+
+/* Load or store instructions that may cause exceptions use the EX macro. */
+
+#define EX(insn,reg1,reg2,offset,handler)	\
+9:	insn	reg1, reg2, offset;		\
+	.section __ex_table, "a";		\
+	.word	9b, handler;			\
+	.previous
+
+
+.text
+.align	4
+.global	memset
+.type	memset,@function
+memset:
+	entry	sp, 16		# minimal stack frame
+	# a2/ dst, a3/ c, a4/ length
+	extui	a3, a3, 0, 8	# mask to just 8 bits
+	slli	a7, a3, 8	# duplicate character in all bytes of word
+	or	a3, a3, a7	# ...
+	slli	a7, a3, 16	# ...
+	or	a3, a3, a7	# ...
+	mov	a5, a2		# copy dst so that a2 is return value
+	movi	a6, 3		# for alignment tests
+	bany	a2, a6, .Ldstunaligned # if dst is unaligned
+.L0:	# return here from .Ldstunaligned when dst is aligned
+	srli	a7, a4, 4	# number of loop iterations with 16B
+				# per iteration
+	bnez	a4, .Laligned
+	retw
+
+/*
+ * Destination is word-aligned.
+ */
+	# set 16 bytes per iteration for word-aligned dst
+	.align	4		# 1 mod 4 alignment for LOOPNEZ
+	.byte	0		# (0 mod 4 alignment for LBEG)
+.Laligned:
+#if XCHAL_HAVE_LOOPS
+	loopnez	a7, .Loop1done
+#else /* !XCHAL_HAVE_LOOPS */
+	beqz	a7, .Loop1done
+	slli	a6, a7, 4
+	add	a6, a6, a5	# a6 = end of last 16B chunk
+#endif /* !XCHAL_HAVE_LOOPS */
+.Loop1:
+	EX(s32i, a3, a5,  0, memset_fixup)
+	EX(s32i, a3, a5,  4, memset_fixup)
+	EX(s32i, a3, a5,  8, memset_fixup)
+	EX(s32i, a3, a5, 12, memset_fixup)
+	addi	a5, a5, 16
+#if !XCHAL_HAVE_LOOPS
+	blt	a5, a6, .Loop1
+#endif /* !XCHAL_HAVE_LOOPS */
+.Loop1done:
+	bbci.l	a4, 3, .L2
+	# set 8 bytes
+	EX(s32i, a3, a5,  0, memset_fixup)
+	EX(s32i, a3, a5,  4, memset_fixup)
+	addi	a5, a5,  8
+.L2:
+	bbci.l	a4, 2, .L3
+	# set 4 bytes
+	EX(s32i, a3, a5,  0, memset_fixup)
+	addi	a5, a5,  4
+.L3:
+	bbci.l	a4, 1, .L4
+	# set 2 bytes
+	EX(s16i, a3, a5,  0, memset_fixup)
+	addi	a5, a5,  2
+.L4:
+	bbci.l	a4, 0, .L5
+	# set 1 byte
+	EX(s8i, a3, a5,  0, memset_fixup)
+.L5:
+.Lret1:
+	retw
+
+/*
+ * Destination is unaligned
+ */
+
+.Ldstunaligned:
+	bltui	a4, 8, .Lbyteset	# do short copies byte by byte
+	bbci.l	a5, 0, .L20		# branch if dst alignment half-aligned
+	# dst is only byte aligned
+	# set 1 byte
+	EX(s8i, a3, a5,  0, memset_fixup)
+	addi	a5, a5,  1
+	addi	a4, a4, -1
+	# now retest if dst aligned
+	bbci.l	a5, 1, .L0	# if now aligned, return to main algorithm
+.L20:
+	# dst half-aligned
+	# set 2 bytes
+	EX(s16i, a3, a5,  0, memset_fixup)
+	addi	a5, a5,  2
+	addi	a4, a4, -2
+	j	.L0		# dst is now aligned, return to main algorithm
+
+/*
+ * Byte by byte set
+ */
+	.align	4
+	.byte	0		# 1 mod 4 alignment for LOOPNEZ
+				# (0 mod 4 alignment for LBEG)
+.Lbyteset:
+#if XCHAL_HAVE_LOOPS
+	loopnez	a4, .Lbytesetdone
+#else /* !XCHAL_HAVE_LOOPS */
+	beqz	a4, .Lbytesetdone
+	add	a6, a5, a4	# a6 = ending address
+#endif /* !XCHAL_HAVE_LOOPS */
+.Lbyteloop:
+	EX(s8i, a3, a5, 0, memset_fixup)
+	addi	a5, a5, 1
+#if !XCHAL_HAVE_LOOPS
+	blt	a5, a6, .Lbyteloop
+#endif /* !XCHAL_HAVE_LOOPS */
+.Lbytesetdone:
+	retw
+
+
+	.section .fixup, "ax"
+	.align	4
+
+/* We return zero if a failure occurred. */
+
+memset_fixup:
+	movi	a2, 0
+	retw
diff --git a/arch/xtensa/lib/pci-auto.c b/arch/xtensa/lib/pci-auto.c
new file mode 100644
index 0000000..90c790f
--- /dev/null
+++ b/arch/xtensa/lib/pci-auto.c
@@ -0,0 +1,352 @@
+/*
+ * arch/xtensa/kernel/pci-auto.c
+ *
+ * PCI autoconfiguration library
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ *
+ * Chris Zankel <zankel@tensilica.com, cez@zankel.net>
+ *
+ * Based on work from Matt Porter <mporter@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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/pci-bridge.h>
+
+
+/*
+ *
+ * Setting up a PCI
+ *
+ * pci_ctrl->first_busno = <first bus number (0)>
+ * pci_ctrl->last_busno = <last bus number (0xff)>
+ * pci_ctrl->ops = <PCI config operations>
+ * pci_ctrl->map_irq = <function to return the interrupt number for a device>
+ *
+ * pci_ctrl->io_space.start = <IO space start address (PCI view)>
+ * pci_ctrl->io_space.end = <IO space end address (PCI view)>
+ * pci_ctrl->io_space.base = <IO space offset: address 0 from CPU space>
+ * pci_ctrl->mem_space.start = <MEM space start address (PCI view)>
+ * pci_ctrl->mem_space.end = <MEM space end address (PCI view)>
+ * pci_ctrl->mem_space.base = <MEM space offset: address 0 from CPU space>
+ *
+ * pcibios_init_resource(&pci_ctrl->io_resource, <IO space start>,
+ * 			 <IO space end>, IORESOURCE_IO, "PCI host bridge");
+ * pcibios_init_resource(&pci_ctrl->mem_resources[0], <MEM space start>,
+ * 			 <MEM space end>, IORESOURCE_MEM, "PCI host bridge");
+ *
+ * pci_ctrl->last_busno = pciauto_bus_scan(pci_ctrl,pci_ctrl->first_busno);
+ *
+ * int __init pciauto_bus_scan(struct pci_controller *pci_ctrl, int current_bus)
+ *
+ */
+
+
+/* define DEBUG to print some debugging messages. */
+
+#undef DEBUG
+
+#ifdef DEBUG
+# define DBG(x...) printk(x)
+#else
+# define DBG(x...)
+#endif
+
+static int pciauto_upper_iospc;
+static int pciauto_upper_memspc;
+
+static struct pci_dev pciauto_dev;
+static struct pci_bus pciauto_bus;
+
+/*
+ * Helper functions
+ */
+
+/* Initialize the bars of a PCI device.  */
+
+static void __init
+pciauto_setup_bars(struct pci_dev *dev, int bar_limit)
+{
+	int bar_size;
+	int bar, bar_nr;
+	int *upper_limit;
+	int found_mem64 = 0;
+
+	for (bar = PCI_BASE_ADDRESS_0, bar_nr = 0;
+	     bar <= bar_limit;
+	     bar+=4, bar_nr++)
+	{
+		/* Tickle the BAR and get the size */
+		pci_write_config_dword(dev, bar, 0xffffffff);
+		pci_read_config_dword(dev, bar, &bar_size);
+
+		/* If BAR is not implemented go to the next BAR */
+		if (!bar_size)
+			continue;
+
+		/* Check the BAR type and set our address mask */
+		if (bar_size & PCI_BASE_ADDRESS_SPACE_IO)
+		{
+			bar_size &= PCI_BASE_ADDRESS_IO_MASK;
+			upper_limit = &pciauto_upper_iospc;
+			DBG("PCI Autoconfig: BAR %d, I/O, ", bar_nr);
+		}
+		else
+		{
+			if ((bar_size & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+			    PCI_BASE_ADDRESS_MEM_TYPE_64)
+				found_mem64 = 1;
+
+			bar_size &= PCI_BASE_ADDRESS_MEM_MASK;
+			upper_limit = &pciauto_upper_memspc;
+			DBG("PCI Autoconfig: BAR %d, Mem, ", bar_nr);
+		}
+
+		/* Allocate a base address (bar_size is negative!) */
+		*upper_limit = (*upper_limit + bar_size) & bar_size;
+
+		/* Write it out and update our limit */
+		pci_write_config_dword(dev, bar, *upper_limit);
+
+		/*
+		 * If we are a 64-bit decoder then increment to the
+		 * upper 32 bits of the bar and force it to locate
+		 * in the lower 4GB of memory.
+		 */
+
+		if (found_mem64)
+			pci_write_config_dword(dev, (bar+=4), 0x00000000);
+
+		DBG("size=0x%x, address=0x%x\n", ~bar_size + 1, *upper_limit);
+	}
+}
+
+/* Initialize the interrupt number. */
+
+static void __init
+pciauto_setup_irq(struct pci_controller* pci_ctrl,struct pci_dev *dev,int devfn)
+{
+	u8 pin;
+	int irq = 0;
+
+	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+
+	/* Fix illegal pin numbers. */
+
+	if (pin == 0 || pin > 4)
+		pin = 1;
+
+	if (pci_ctrl->map_irq)
+		irq = pci_ctrl->map_irq(dev, PCI_SLOT(devfn), pin);
+
+	if (irq == -1)
+		irq = 0;
+
+	DBG("PCI Autoconfig: Interrupt %d, pin %d\n", irq, pin);
+
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+
+static void __init
+pciauto_prescan_setup_bridge(struct pci_dev *dev, int current_bus,
+			     int sub_bus, int *iosave, int *memsave)
+{
+	/* Configure bus number registers */
+	pci_write_config_byte(dev, PCI_PRIMARY_BUS, current_bus);
+	pci_write_config_byte(dev, PCI_SECONDARY_BUS, sub_bus + 1);
+	pci_write_config_byte(dev, PCI_SUBORDINATE_BUS,	0xff);
+
+	/* Round memory allocator to 1MB boundary */
+	pciauto_upper_memspc &= ~(0x100000 - 1);
+	*memsave = pciauto_upper_memspc;
+
+	/* Round I/O allocator to 4KB boundary */
+	pciauto_upper_iospc &= ~(0x1000 - 1);
+	*iosave = pciauto_upper_iospc;
+
+	/* Set up memory and I/O filter limits, assume 32-bit I/O space */
+	pci_write_config_word(dev, PCI_MEMORY_LIMIT,
+			      ((pciauto_upper_memspc - 1) & 0xfff00000) >> 16);
+	pci_write_config_byte(dev, PCI_IO_LIMIT,
+			      ((pciauto_upper_iospc - 1) & 0x0000f000) >> 8);
+	pci_write_config_word(dev, PCI_IO_LIMIT_UPPER16,
+			      ((pciauto_upper_iospc - 1) & 0xffff0000) >> 16);
+}
+
+static void __init
+pciauto_postscan_setup_bridge(struct pci_dev *dev, int current_bus, int sub_bus,
+			      int *iosave, int *memsave)
+{
+	int cmdstat;
+
+	/* Configure bus number registers */
+	pci_write_config_byte(dev, PCI_SUBORDINATE_BUS,	sub_bus);
+
+	/*
+	 * Round memory allocator to 1MB boundary.
+	 * If no space used, allocate minimum.
+	 */
+	pciauto_upper_memspc &= ~(0x100000 - 1);
+	if (*memsave == pciauto_upper_memspc)
+		pciauto_upper_memspc -= 0x00100000;
+
+	pci_write_config_word(dev, PCI_MEMORY_BASE, pciauto_upper_memspc >> 16);
+
+	/* Allocate 1MB for pre-fretch */
+	pci_write_config_word(dev, PCI_PREF_MEMORY_LIMIT,
+			      ((pciauto_upper_memspc - 1) & 0xfff00000) >> 16);
+
+	pciauto_upper_memspc -= 0x100000;
+
+	pci_write_config_word(dev, PCI_PREF_MEMORY_BASE,
+			      pciauto_upper_memspc >> 16);
+
+	/* Round I/O allocator to 4KB boundary */
+	pciauto_upper_iospc &= ~(0x1000 - 1);
+	if (*iosave == pciauto_upper_iospc)
+		pciauto_upper_iospc -= 0x1000;
+
+	pci_write_config_byte(dev, PCI_IO_BASE,
+			      (pciauto_upper_iospc & 0x0000f000) >> 8);
+	pci_write_config_word(dev, PCI_IO_BASE_UPPER16,
+			      pciauto_upper_iospc >> 16);
+
+	/* Enable memory and I/O accesses, enable bus master */
+	pci_read_config_dword(dev, PCI_COMMAND, &cmdstat);
+	pci_write_config_dword(dev, PCI_COMMAND,
+			       cmdstat |
+			       PCI_COMMAND_IO |
+			       PCI_COMMAND_MEMORY |
+			       PCI_COMMAND_MASTER);
+}
+
+/*
+ * Scan the current PCI bus.
+ */
+
+
+int __init pciauto_bus_scan(struct pci_controller *pci_ctrl, int current_bus)
+{
+	int sub_bus, pci_devfn, pci_class, cmdstat, found_multi=0;
+	unsigned short vid;
+	unsigned char header_type;
+	struct pci_dev *dev = &pciauto_dev;
+
+        pciauto_dev.bus = &pciauto_bus;
+        pciauto_dev.sysdata = pci_ctrl;
+	pciauto_bus.ops = pci_ctrl->ops;
+
+	/*
+	 * Fetch our I/O and memory space upper boundaries used
+	 * to allocated base addresses on this pci_controller.
+	 */
+
+	if (current_bus == pci_ctrl->first_busno)
+	{
+		pciauto_upper_iospc = pci_ctrl->io_resource.end + 1;
+		pciauto_upper_memspc = pci_ctrl->mem_resources[0].end + 1;
+	}
+
+	sub_bus = current_bus;
+
+	for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++)
+	{
+		/* Skip our host bridge */
+		if ((current_bus == pci_ctrl->first_busno) && (pci_devfn == 0))
+			continue;
+
+		if (PCI_FUNC(pci_devfn) && !found_multi)
+			continue;
+
+		pciauto_bus.number = current_bus;
+		pciauto_dev.devfn = pci_devfn;
+
+		/* If config space read fails from this device, move on */
+		if (pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type))
+			continue;
+
+		if (!PCI_FUNC(pci_devfn))
+			found_multi = header_type & 0x80;
+		pci_read_config_word(dev, PCI_VENDOR_ID, &vid);
+
+		if (vid == 0xffff || vid == 0x0000) {
+			found_multi = 0;
+			continue;
+		}
+
+		pci_read_config_dword(dev, PCI_CLASS_REVISION, &pci_class);
+
+		if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) {
+
+			int iosave, memsave;
+
+			DBG("PCI Autoconfig: Found P2P bridge, device %d\n",
+			    PCI_SLOT(pci_devfn));
+
+			/* Allocate PCI I/O and/or memory space */
+			pciauto_setup_bars(dev, PCI_BASE_ADDRESS_1);
+
+			pciauto_prescan_setup_bridge(dev, current_bus, sub_bus,
+					&iosave, &memsave);
+			sub_bus = pciauto_bus_scan(pci_ctrl, sub_bus+1);
+			pciauto_postscan_setup_bridge(dev, current_bus, sub_bus,
+					&iosave, &memsave);
+			pciauto_bus.number = current_bus;
+
+			continue;
+
+		}
+
+
+#if 0
+		/* Skip legacy mode IDE controller */
+
+		if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) {
+
+			unsigned char prg_iface;
+			pci_read_config_byte(dev, PCI_CLASS_PROG, &prg_iface);
+
+			if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) {
+				DBG("PCI Autoconfig: Skipping legacy mode "
+				    "IDE controller\n");
+				continue;
+			}
+		}
+#endif
+
+		/*
+		 * Found a peripheral, enable some standard
+		 * settings
+		 */
+
+		pci_read_config_dword(dev, PCI_COMMAND,	&cmdstat);
+		pci_write_config_dword(dev, PCI_COMMAND,
+				cmdstat |
+					PCI_COMMAND_IO |
+					PCI_COMMAND_MEMORY |
+					PCI_COMMAND_MASTER);
+		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);
+
+		/* Allocate PCI I/O and/or memory space */
+		DBG("PCI Autoconfig: Found Bus %d, Device %d, Function %d\n",
+		    current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn) );
+
+		pciauto_setup_bars(dev, PCI_BASE_ADDRESS_5);
+		pciauto_setup_irq(pci_ctrl, dev, pci_devfn);
+	}
+	return sub_bus;
+}
+
+
+
+
+
diff --git a/arch/xtensa/lib/strcasecmp.c b/arch/xtensa/lib/strcasecmp.c
new file mode 100644
index 0000000..165b2d6
--- /dev/null
+++ b/arch/xtensa/lib/strcasecmp.c
@@ -0,0 +1,32 @@
+/*
+ *  linux/arch/xtensa/lib/strcasecmp.c
+ *
+ *  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) 2002 Tensilica Inc.
+ */
+
+#include <linux/string.h>
+
+
+/* We handle nothing here except the C locale.  Since this is used in
+   only one place, on strings known to contain only 7 bit ASCII, this
+   is ok.  */
+
+int strcasecmp(const char *a, const char *b)
+{
+	int ca, cb;
+
+	do {
+		ca = *a++ & 0xff;
+		cb = *b++ & 0xff;
+		if (ca >= 'A' && ca <= 'Z')
+			ca += 'a' - 'A';
+		if (cb >= 'A' && cb <= 'Z')
+			cb += 'a' - 'A';
+	} while (ca == cb && ca != '\0');
+
+	return ca - cb;
+}
diff --git a/arch/xtensa/lib/strncpy_user.S b/arch/xtensa/lib/strncpy_user.S
new file mode 100644
index 0000000..71d55df
--- /dev/null
+++ b/arch/xtensa/lib/strncpy_user.S
@@ -0,0 +1,224 @@
+/*
+ *  arch/xtensa/lib/strncpy_user.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.
+ *
+ *  Returns: -EFAULT if exception before terminator, N if the entire
+ *  buffer filled, else strlen.
+ *
+ *  Copyright (C) 2002 Tensilica Inc.
+ */
+
+#include <xtensa/coreasm.h>
+#include <linux/errno.h>
+
+/* Load or store instructions that may cause exceptions use the EX macro. */
+
+#define EX(insn,reg1,reg2,offset,handler)	\
+9:	insn	reg1, reg2, offset;		\
+	.section __ex_table, "a";		\
+	.word	9b, handler;			\
+	.previous
+
+/*
+ * char *__strncpy_user(char *dst, const char *src, size_t len)
+ */
+.text
+.begin literal
+.align	4
+.Lmask0:
+	.byte	0xff, 0x00, 0x00, 0x00
+.Lmask1:
+	.byte	0x00, 0xff, 0x00, 0x00
+.Lmask2:
+	.byte	0x00, 0x00, 0xff, 0x00
+.Lmask3:
+	.byte	0x00, 0x00, 0x00, 0xff
+.end literal
+
+# Register use
+#   a0/ return address
+#   a1/ stack pointer
+#   a2/ return value
+#   a3/ src
+#   a4/ len
+#   a5/ mask0
+#   a6/ mask1
+#   a7/ mask2
+#   a8/ mask3
+#   a9/ tmp
+#   a10/ tmp
+#   a11/ dst
+#   a12/ tmp
+
+.align	4
+.global	__strncpy_user
+.type	__strncpy_user,@function
+__strncpy_user:
+	entry	sp, 16		# minimal stack frame
+	# a2/ dst, a3/ src, a4/ len
+	mov	a11, a2		# leave dst in return value register
+	beqz	a4, .Lret	# if len is zero
+	l32r	a5, .Lmask0	# mask for byte 0
+	l32r	a6, .Lmask1	# mask for byte 1
+	l32r	a7, .Lmask2	# mask for byte 2
+	l32r	a8, .Lmask3	# mask for byte 3
+	bbsi.l	a3, 0, .Lsrc1mod2 # if only  8-bit aligned
+	bbsi.l	a3, 1, .Lsrc2mod4 # if only 16-bit aligned
+.Lsrcaligned:	# return here when src is word-aligned
+	srli	a12, a4, 2	# number of loop iterations with 4B per loop
+	movi	a9, 3
+	bnone	a11, a9, .Laligned
+	j	.Ldstunaligned
+
+.Lsrc1mod2:	# src address is odd
+	EX(l8ui, a9, a3, 0, fixup_l)	# get byte 0
+	addi	a3, a3, 1		# advance src pointer
+	EX(s8i, a9, a11, 0, fixup_s)	# store byte 0
+	beqz	a9, .Lret		# if byte 0 is zero
+	addi	a11, a11, 1		# advance dst pointer
+	addi	a4, a4, -1		# decrement len
+	beqz	a4, .Lret		# if len is zero
+	bbci.l	a3, 1, .Lsrcaligned	# if src is now word-aligned
+
+.Lsrc2mod4:	# src address is 2 mod 4
+	EX(l8ui, a9, a3, 0, fixup_l)	# get byte 0
+	/* 1-cycle interlock */
+	EX(s8i, a9, a11, 0, fixup_s)	# store byte 0
+	beqz	a9, .Lret		# if byte 0 is zero
+	addi	a11, a11, 1		# advance dst pointer
+	addi	a4, a4, -1		# decrement len
+	beqz	a4, .Lret		# if len is zero
+	EX(l8ui, a9, a3, 1, fixup_l)	# get byte 0
+	addi	a3, a3, 2		# advance src pointer
+	EX(s8i, a9, a11, 0, fixup_s)	# store byte 0
+	beqz	a9, .Lret		# if byte 0 is zero
+	addi	a11, a11, 1		# advance dst pointer
+	addi	a4, a4, -1		# decrement len
+	bnez	a4, .Lsrcaligned	# if len is nonzero
+.Lret:
+	sub	a2, a11, a2		# compute strlen
+	retw
+
+/*
+ * dst is word-aligned, src is word-aligned
+ */
+	.align	4		# 1 mod 4 alignment for LOOPNEZ
+	.byte	0		# (0 mod 4 alignment for LBEG)
+.Laligned:
+#if XCHAL_HAVE_LOOPS
+	loopnez	a12, .Loop1done
+#else
+	beqz	a12, .Loop1done
+	slli	a12, a12, 2
+	add	a12, a12, a11	# a12 = end of last 4B chunck
+#endif
+.Loop1:
+	EX(l32i, a9, a3, 0, fixup_l)	# get word from src
+	addi	a3, a3, 4		# advance src pointer
+	bnone	a9, a5, .Lz0		# if byte 0 is zero
+	bnone	a9, a6, .Lz1		# if byte 1 is zero
+	bnone	a9, a7, .Lz2		# if byte 2 is zero
+	EX(s32i, a9, a11, 0, fixup_s)	# store word to dst
+	bnone	a9, a8, .Lz3		# if byte 3 is zero
+	addi	a11, a11, 4		# advance dst pointer
+#if !XCHAL_HAVE_LOOPS
+	blt	a11, a12, .Loop1
+#endif
+
+.Loop1done:
+	bbci.l	a4, 1, .L100
+	# copy 2 bytes
+	EX(l16ui, a9, a3, 0, fixup_l)
+	addi	a3, a3, 2		# advance src pointer
+#ifdef __XTENSA_EB__
+	bnone	a9, a7, .Lz0		# if byte 2 is zero
+	bnone	a9, a8, .Lz1		# if byte 3 is zero
+#else
+	bnone	a9, a5, .Lz0		# if byte 0 is zero
+	bnone	a9, a6, .Lz1		# if byte 1 is zero
+#endif
+	EX(s16i, a9, a11, 0, fixup_s)
+	addi	a11, a11, 2		# advance dst pointer
+.L100:
+	bbci.l	a4, 0, .Lret
+	EX(l8ui, a9, a3, 0, fixup_l)
+	/* slot */
+	EX(s8i, a9, a11, 0, fixup_s)
+	beqz	a9, .Lret		# if byte is zero
+	addi	a11, a11, 1-3		# advance dst ptr 1, but also cancel
+					# the effect of adding 3 in .Lz3 code
+	/* fall thru to .Lz3 and "retw" */
+
+.Lz3:	# byte 3 is zero
+	addi	a11, a11, 3		# advance dst pointer
+	sub	a2, a11, a2		# compute strlen
+	retw
+.Lz0:	# byte 0 is zero
+#ifdef __XTENSA_EB__
+	movi	a9, 0
+#endif /* __XTENSA_EB__ */
+	EX(s8i, a9, a11, 0, fixup_s)
+	sub	a2, a11, a2		# compute strlen
+	retw
+.Lz1:	# byte 1 is zero
+#ifdef __XTENSA_EB__
+        extui   a9, a9, 16, 16
+#endif /* __XTENSA_EB__ */
+	EX(s16i, a9, a11, 0, fixup_s)
+	addi	a11, a11, 1		# advance dst pointer
+	sub	a2, a11, a2		# compute strlen
+	retw
+.Lz2:	# byte 2 is zero
+#ifdef __XTENSA_EB__
+        extui   a9, a9, 16, 16
+#endif /* __XTENSA_EB__ */
+	EX(s16i, a9, a11, 0, fixup_s)
+	movi	a9, 0
+	EX(s8i, a9, a11, 2, fixup_s)
+	addi	a11, a11, 2		# advance dst pointer
+	sub	a2, a11, a2		# compute strlen
+	retw
+
+	.align	4		# 1 mod 4 alignment for LOOPNEZ
+	.byte	0		# (0 mod 4 alignment for LBEG)
+.Ldstunaligned:
+/*
+ * for now just use byte copy loop
+ */
+#if XCHAL_HAVE_LOOPS
+	loopnez	a4, .Lunalignedend
+#else
+	beqz	a4, .Lunalignedend
+	add	a12, a11, a4		# a12 = ending address
+#endif /* XCHAL_HAVE_LOOPS */
+.Lnextbyte:
+	EX(l8ui, a9, a3, 0, fixup_l)
+	addi	a3, a3, 1
+	EX(s8i, a9, a11, 0, fixup_s)
+	beqz	a9, .Lunalignedend
+	addi	a11, a11, 1
+#if !XCHAL_HAVE_LOOPS
+	blt	a11, a12, .Lnextbyte
+#endif
+
+.Lunalignedend:
+	sub	a2, a11, a2		# compute strlen
+	retw
+
+
+	.section .fixup, "ax"
+	.align	4
+
+	/* For now, just return -EFAULT.  Future implementations might
+	 * like to clear remaining kernel space, like the fixup
+	 * implementation in memset().  Thus, we differentiate between
+	 * load/store fixups. */
+
+fixup_s:
+fixup_l:
+	movi	a2, -EFAULT
+	retw
+
diff --git a/arch/xtensa/lib/strnlen_user.S b/arch/xtensa/lib/strnlen_user.S
new file mode 100644
index 0000000..cdff4d6
--- /dev/null
+++ b/arch/xtensa/lib/strnlen_user.S
@@ -0,0 +1,147 @@
+/*
+ *  arch/xtensa/lib/strnlen_user.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.
+ *
+ *  Returns strnlen, including trailing zero terminator.
+ *  Zero indicates error.
+ *
+ *  Copyright (C) 2002 Tensilica Inc.
+ */
+
+#include <xtensa/coreasm.h>
+
+/* Load or store instructions that may cause exceptions use the EX macro. */
+
+#define EX(insn,reg1,reg2,offset,handler)	\
+9:	insn	reg1, reg2, offset;		\
+	.section __ex_table, "a";		\
+	.word	9b, handler;			\
+	.previous
+
+/*
+ * size_t __strnlen_user(const char *s, size_t len)
+ */
+.text
+.begin literal
+.align	4
+.Lmask0:
+	.byte	0xff, 0x00, 0x00, 0x00
+.Lmask1:
+	.byte	0x00, 0xff, 0x00, 0x00
+.Lmask2:
+	.byte	0x00, 0x00, 0xff, 0x00
+.Lmask3:
+	.byte	0x00, 0x00, 0x00, 0xff
+.end literal
+
+# Register use:
+#   a2/ src
+#   a3/ len
+#   a4/ tmp
+#   a5/ mask0
+#   a6/ mask1
+#   a7/ mask2
+#   a8/ mask3
+#   a9/ tmp
+#   a10/ tmp
+
+.align	4
+.global	__strnlen_user
+.type	__strnlen_user,@function
+__strnlen_user:
+	entry	sp, 16		# minimal stack frame
+	# a2/ s, a3/ len
+	addi	a4, a2, -4	# because we overincrement at the end;
+				# we compensate with load offsets of 4
+	l32r	a5, .Lmask0	# mask for byte 0
+	l32r	a6, .Lmask1	# mask for byte 1
+	l32r	a7, .Lmask2	# mask for byte 2
+	l32r	a8, .Lmask3	# mask for byte 3
+	bbsi.l	a2, 0, .L1mod2	# if only  8-bit aligned
+	bbsi.l	a2, 1, .L2mod4	# if only 16-bit aligned
+
+/*
+ * String is word-aligned.
+ */
+.Laligned:
+	srli	a10, a3, 2	# number of loop iterations with 4B per loop
+#if XCHAL_HAVE_LOOPS
+	loopnez	a10, .Ldone
+#else
+	beqz	a10, .Ldone
+	slli	a10, a10, 2
+	add	a10, a10, a4	# a10 = end of last 4B chunk
+#endif /* XCHAL_HAVE_LOOPS */
+.Loop:
+	EX(l32i, a9, a4, 4, lenfixup)	# get next word of string
+	addi	a4, a4, 4		# advance string pointer
+	bnone	a9, a5, .Lz0		# if byte 0 is zero
+	bnone	a9, a6, .Lz1		# if byte 1 is zero
+	bnone	a9, a7, .Lz2		# if byte 2 is zero
+	bnone	a9, a8, .Lz3		# if byte 3 is zero
+#if !XCHAL_HAVE_LOOPS
+	blt	a4, a10, .Loop
+#endif
+
+.Ldone:
+	EX(l32i, a9, a4, 4, lenfixup)	# load 4 bytes for remaining checks
+
+	bbci.l	a3, 1, .L100
+	# check two more bytes (bytes 0, 1 of word)
+	addi	a4, a4, 2	# advance string pointer
+	bnone	a9, a5, .Lz0	# if byte 0 is zero
+	bnone	a9, a6, .Lz1	# if byte 1 is zero
+.L100:
+	bbci.l	a3, 0, .L101
+	# check one more byte (byte 2 of word)
+	# Actually, we don't need to check.  Zero or nonzero, we'll add one.
+	# Do not add an extra one for the NULL terminator since we have
+	#  exhausted the original len parameter.
+	addi	a4, a4, 1	# advance string pointer
+.L101:
+	sub	a2, a4, a2	# compute length
+	retw
+
+# NOTE that in several places below, we point to the byte just after
+# the zero byte in order to include the NULL terminator in the count.
+
+.Lz3:	# byte 3 is zero
+	addi	a4, a4, 3	# point to zero byte
+.Lz0:	# byte 0 is zero
+	addi	a4, a4, 1	# point just beyond zero byte
+	sub	a2, a4, a2	# subtract to get length
+	retw
+.Lz1:	# byte 1 is zero
+	addi	a4, a4, 1+1	# point just beyond zero byte
+	sub	a2, a4, a2	# subtract to get length
+	retw
+.Lz2:	# byte 2 is zero
+	addi	a4, a4, 2+1	# point just beyond zero byte
+	sub	a2, a4, a2	# subtract to get length
+	retw
+
+.L1mod2:	# address is odd
+	EX(l8ui, a9, a4, 4, lenfixup)	# get byte 0
+	addi	a4, a4, 1		# advance string pointer
+	beqz	a9, .Lz3		# if byte 0 is zero
+	bbci.l	a4, 1, .Laligned	# if string pointer is now word-aligned
+
+.L2mod4:	# address is 2 mod 4
+	addi	a4, a4, 2	# advance ptr for aligned access
+	EX(l32i, a9, a4, 0, lenfixup)	# get word with first two bytes of string
+	bnone	a9, a7, .Lz2	# if byte 2 (of word, not string) is zero
+	bany	a9, a8, .Laligned # if byte 3 (of word, not string) is nonzero
+	# byte 3 is zero
+	addi	a4, a4, 3+1	# point just beyond zero byte
+	sub	a2, a4, a2	# subtract to get length
+	retw
+
+	.section .fixup, "ax"
+	.align	4
+lenfixup:
+	movi	a2, 0
+	retw
+
diff --git a/arch/xtensa/lib/usercopy.S b/arch/xtensa/lib/usercopy.S
new file mode 100644
index 0000000..265db26
--- /dev/null
+++ b/arch/xtensa/lib/usercopy.S
@@ -0,0 +1,321 @@
+/*
+ *  arch/xtensa/lib/usercopy.S
+ *
+ *  Copy to/from user space (derived from arch/xtensa/lib/hal/memcopy.S)
+ *
+ *  DO NOT COMBINE this function with <arch/xtensa/lib/hal/memcopy.S>.
+ *  It needs to remain separate and distinct.  The hal files are part
+ *  of the the Xtensa link-time HAL, and those files may differ per
+ *  processor configuration.  Patching the kernel for another
+ *  processor configuration includes replacing the hal files, and we
+ *  could loose the special functionality for accessing user-space
+ *  memory during such a patch.  We sacrifice a little code space here
+ *  in favor to simplify code maintenance.
+ *
+ *  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) 2002 Tensilica Inc.
+ */
+
+
+/*
+ * size_t __xtensa_copy_user (void *dst, const void *src, size_t len);
+ *
+ * The returned value is the number of bytes not copied.  Implies zero
+ * is success.
+ *
+ * The general case algorithm is as follows:
+ *   If the destination and source are both aligned,
+ *     do 16B chunks with a loop, and then finish up with
+ *     8B, 4B, 2B, and 1B copies conditional on the length.
+ *   If destination is aligned and source unaligned,
+ *     do the same, but use SRC to align the source data.
+ *   If destination is unaligned, align it by conditionally
+ *     copying 1B and 2B and then retest.
+ *   This code tries to use fall-through braches for the common
+ *     case of aligned destinations (except for the branches to
+ *     the alignment label).
+ *
+ * Register use:
+ *	a0/ return address
+ *	a1/ stack pointer
+ *	a2/ return value
+ *	a3/ src
+ *	a4/ length
+ *	a5/ dst
+ *	a6/ tmp
+ *	a7/ tmp
+ *	a8/ tmp
+ *	a9/ tmp
+ *	a10/ tmp
+ *	a11/ original length
+ */
+
+#include <xtensa/coreasm.h>
+
+#ifdef __XTENSA_EB__
+#define ALIGN(R, W0, W1) src	R, W0, W1
+#define SSA8(R)	ssa8b R
+#else
+#define ALIGN(R, W0, W1) src	R, W1, W0
+#define SSA8(R)	ssa8l R
+#endif
+
+/* Load or store instructions that may cause exceptions use the EX macro. */
+
+#define EX(insn,reg1,reg2,offset,handler)	\
+9:	insn	reg1, reg2, offset;		\
+	.section __ex_table, "a";		\
+	.word	9b, handler;			\
+	.previous
+
+
+	.text
+	.align	4
+	.global	__xtensa_copy_user
+	.type	__xtensa_copy_user,@function
+__xtensa_copy_user:
+	entry	sp, 16		# minimal stack frame
+	# a2/ dst, a3/ src, a4/ len
+	mov	a5, a2		# copy dst so that a2 is return value
+	mov	a11, a4		# preserve original len for error case
+.Lcommon:
+	bbsi.l	a2, 0, .Ldst1mod2 # if dst is 1 mod 2
+	bbsi.l	a2, 1, .Ldst2mod4 # if dst is 2 mod 4
+.Ldstaligned:	# return here from .Ldstunaligned when dst is aligned
+	srli	a7, a4, 4	# number of loop iterations with 16B
+				# per iteration
+	movi	a8, 3		  # if source is also aligned,
+	bnone	a3, a8, .Laligned # then use word copy
+	SSA8(	a3)		# set shift amount from byte offset
+	bnez	a4, .Lsrcunaligned
+	movi	a2, 0		# return success for len==0
+	retw
+
+/*
+ * Destination is unaligned
+ */
+
+.Ldst1mod2:	# dst is only byte aligned
+	bltui	a4, 7, .Lbytecopy	# do short copies byte by byte
+
+	# copy 1 byte
+	EX(l8ui, a6, a3, 0, l_fixup)
+	addi	a3, a3,  1
+	EX(s8i, a6, a5,  0, s_fixup)
+	addi	a5, a5,  1
+	addi	a4, a4, -1
+	bbci.l	a5, 1, .Ldstaligned	# if dst is now aligned, then
+					# return to main algorithm
+.Ldst2mod4:	# dst 16-bit aligned
+	# copy 2 bytes
+	bltui	a4, 6, .Lbytecopy	# do short copies byte by byte
+	EX(l8ui, a6, a3, 0, l_fixup)
+	EX(l8ui, a7, a3, 1, l_fixup)
+	addi	a3, a3,  2
+	EX(s8i, a6, a5,  0, s_fixup)
+	EX(s8i, a7, a5,  1, s_fixup)
+	addi	a5, a5,  2
+	addi	a4, a4, -2
+	j	.Ldstaligned	# dst is now aligned, return to main algorithm
+
+/*
+ * Byte by byte copy
+ */
+	.align	4
+	.byte	0		# 1 mod 4 alignment for LOOPNEZ
+				# (0 mod 4 alignment for LBEG)
+.Lbytecopy:
+#if XCHAL_HAVE_LOOPS
+	loopnez	a4, .Lbytecopydone
+#else /* !XCHAL_HAVE_LOOPS */
+	beqz	a4, .Lbytecopydone
+	add	a7, a3, a4	# a7 = end address for source
+#endif /* !XCHAL_HAVE_LOOPS */
+.Lnextbyte:
+	EX(l8ui, a6, a3, 0, l_fixup)
+	addi	a3, a3, 1
+	EX(s8i, a6, a5, 0, s_fixup)
+	addi	a5, a5, 1
+#if !XCHAL_HAVE_LOOPS
+	blt	a3, a7, .Lnextbyte
+#endif /* !XCHAL_HAVE_LOOPS */
+.Lbytecopydone:
+	movi	a2, 0		# return success for len bytes copied
+	retw
+
+/*
+ * Destination and source are word-aligned.
+ */
+	# copy 16 bytes per iteration for word-aligned dst and word-aligned src
+	.align	4		# 1 mod 4 alignment for LOOPNEZ
+	.byte	0		# (0 mod 4 alignment for LBEG)
+.Laligned:
+#if XCHAL_HAVE_LOOPS
+	loopnez	a7, .Loop1done
+#else /* !XCHAL_HAVE_LOOPS */
+	beqz	a7, .Loop1done
+	slli	a8, a7, 4
+	add	a8, a8, a3	# a8 = end of last 16B source chunk
+#endif /* !XCHAL_HAVE_LOOPS */
+.Loop1:
+	EX(l32i, a6, a3,  0, l_fixup)
+	EX(l32i, a7, a3,  4, l_fixup)
+	EX(s32i, a6, a5,  0, s_fixup)
+	EX(l32i, a6, a3,  8, l_fixup)
+	EX(s32i, a7, a5,  4, s_fixup)
+	EX(l32i, a7, a3, 12, l_fixup)
+	EX(s32i, a6, a5,  8, s_fixup)
+	addi	a3, a3, 16
+	EX(s32i, a7, a5, 12, s_fixup)
+	addi	a5, a5, 16
+#if !XCHAL_HAVE_LOOPS
+	blt	a3, a8, .Loop1
+#endif /* !XCHAL_HAVE_LOOPS */
+.Loop1done:
+	bbci.l	a4, 3, .L2
+	# copy 8 bytes
+	EX(l32i, a6, a3,  0, l_fixup)
+	EX(l32i, a7, a3,  4, l_fixup)
+	addi	a3, a3,  8
+	EX(s32i, a6, a5,  0, s_fixup)
+	EX(s32i, a7, a5,  4, s_fixup)
+	addi	a5, a5,  8
+.L2:
+	bbci.l	a4, 2, .L3
+	# copy 4 bytes
+	EX(l32i, a6, a3,  0, l_fixup)
+	addi	a3, a3,  4
+	EX(s32i, a6, a5,  0, s_fixup)
+	addi	a5, a5,  4
+.L3:
+	bbci.l	a4, 1, .L4
+	# copy 2 bytes
+	EX(l16ui, a6, a3,  0, l_fixup)
+	addi	a3, a3,  2
+	EX(s16i,  a6, a5,  0, s_fixup)
+	addi	a5, a5,  2
+.L4:
+	bbci.l	a4, 0, .L5
+	# copy 1 byte
+	EX(l8ui, a6, a3,  0, l_fixup)
+	EX(s8i,  a6, a5,  0, s_fixup)
+.L5:
+	movi	a2, 0		# return success for len bytes copied
+	retw
+
+/*
+ * Destination is aligned, Source is unaligned
+ */
+
+	.align	4
+	.byte	0		# 1 mod 4 alignement for LOOPNEZ
+				# (0 mod 4 alignment for LBEG)
+.Lsrcunaligned:
+	# copy 16 bytes per iteration for word-aligned dst and unaligned src
+	and	a10, a3, a8	# save unalignment offset for below
+	sub	a3, a3, a10	# align a3 (to avoid sim warnings only; not needed for hardware)
+	EX(l32i, a6, a3, 0, l_fixup)	# load first word
+#if XCHAL_HAVE_LOOPS
+	loopnez	a7, .Loop2done
+#else /* !XCHAL_HAVE_LOOPS */
+	beqz	a7, .Loop2done
+	slli	a10, a7, 4
+	add	a10, a10, a3	# a10 = end of last 16B source chunk
+#endif /* !XCHAL_HAVE_LOOPS */
+.Loop2:
+	EX(l32i, a7, a3,  4, l_fixup)
+	EX(l32i, a8, a3,  8, l_fixup)
+	ALIGN(	a6, a6, a7)
+	EX(s32i, a6, a5,  0, s_fixup)
+	EX(l32i, a9, a3, 12, l_fixup)
+	ALIGN(	a7, a7, a8)
+	EX(s32i, a7, a5,  4, s_fixup)
+	EX(l32i, a6, a3, 16, l_fixup)
+	ALIGN(	a8, a8, a9)
+	EX(s32i, a8, a5,  8, s_fixup)
+	addi	a3, a3, 16
+	ALIGN(	a9, a9, a6)
+	EX(s32i, a9, a5, 12, s_fixup)
+	addi	a5, a5, 16
+#if !XCHAL_HAVE_LOOPS
+	blt	a3, a10, .Loop2
+#endif /* !XCHAL_HAVE_LOOPS */
+.Loop2done:
+	bbci.l	a4, 3, .L12
+	# copy 8 bytes
+	EX(l32i, a7, a3,  4, l_fixup)
+	EX(l32i, a8, a3,  8, l_fixup)
+	ALIGN(	a6, a6, a7)
+	EX(s32i, a6, a5,  0, s_fixup)
+	addi	a3, a3,  8
+	ALIGN(	a7, a7, a8)
+	EX(s32i, a7, a5,  4, s_fixup)
+	addi	a5, a5,  8
+	mov	a6, a8
+.L12:
+	bbci.l	a4, 2, .L13
+	# copy 4 bytes
+	EX(l32i, a7, a3,  4, l_fixup)
+	addi	a3, a3,  4
+	ALIGN(	a6, a6, a7)
+	EX(s32i, a6, a5,  0, s_fixup)
+	addi	a5, a5,  4
+	mov	a6, a7
+.L13:
+	add	a3, a3, a10	# readjust a3 with correct misalignment
+	bbci.l	a4, 1, .L14
+	# copy 2 bytes
+	EX(l8ui, a6, a3,  0, l_fixup)
+	EX(l8ui, a7, a3,  1, l_fixup)
+	addi	a3, a3,  2
+	EX(s8i, a6, a5,  0, s_fixup)
+	EX(s8i, a7, a5,  1, s_fixup)
+	addi	a5, a5,  2
+.L14:
+	bbci.l	a4, 0, .L15
+	# copy 1 byte
+	EX(l8ui, a6, a3,  0, l_fixup)
+	EX(s8i,  a6, a5,  0, s_fixup)
+.L15:
+	movi	a2, 0		# return success for len bytes copied
+	retw
+
+
+	.section .fixup, "ax"
+	.align	4
+
+/* a2 = original dst; a5 = current dst; a11= original len
+ * bytes_copied = a5 - a2
+ * retval = bytes_not_copied = original len - bytes_copied
+ * retval = a11 - (a5 - a2)
+ *
+ * Clearing the remaining pieces of kernel memory plugs security
+ * holes.  This functionality is the equivalent of the *_zeroing
+ * functions that some architectures provide.
+ */
+
+.Lmemset:
+	.word	memset
+
+s_fixup:
+	sub	a2, a5, a2	/* a2 <-- bytes copied */
+	sub	a2, a11, a2	/* a2 <-- bytes not copied */
+	retw
+
+l_fixup:
+	sub	a2, a5, a2	/* a2 <-- bytes copied */
+	sub	a2, a11, a2	/* a2 <-- bytes not copied == return value */
+
+	/* void *memset(void *s, int c, size_t n); */
+	mov	a6, a5		/* s */
+	movi	a7, 0		/* c */
+	mov	a8, a2		/* n */
+	l32r	a4, .Lmemset
+	callx4	a4
+	/* Ignore memset return value in a6. */
+	/* a2 still contains bytes not copied. */
+	retw
+
diff --git a/arch/xtensa/mm/Makefile b/arch/xtensa/mm/Makefile
new file mode 100644
index 0000000..a5aed59
--- /dev/null
+++ b/arch/xtensa/mm/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for the Linux/Xtensa-specific parts of the memory manager.
+#
+# 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).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+obj-y	 := init.o fault.o tlb.o misc.o
+obj-m	 :=
+obj-n	 :=
+obj-	 :=
diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c
new file mode 100644
index 0000000..a945a33
--- /dev/null
+++ b/arch/xtensa/mm/fault.c
@@ -0,0 +1,241 @@
+// TODO VM_EXEC flag work-around, cache aliasing
+/*
+ * arch/xtensa/mm/fault.c
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ * Joe Taylor	<joe@tensilica.com, joetylr@yahoo.com>
+ */
+
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+#include <asm/hardirq.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/pgalloc.h>
+
+unsigned long asid_cache = ASID_FIRST_VERSION;
+void bad_page_fault(struct pt_regs*, unsigned long, int);
+
+/*
+ * This routine handles page faults.  It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ *
+ * Note: does not handle Miss and MultiHit.
+ */
+
+void do_page_fault(struct pt_regs *regs)
+{
+	struct vm_area_struct * vma;
+	struct mm_struct *mm = current->mm;
+	unsigned int exccause = regs->exccause;
+	unsigned int address = regs->excvaddr;
+	siginfo_t info;
+
+	int is_write, is_exec;
+
+	info.si_code = SEGV_MAPERR;
+
+	/* We fault-in kernel-space virtual memory on-demand. The
+	 * 'reference' page table is init_mm.pgd.
+	 */
+	if (address >= TASK_SIZE && !user_mode(regs))
+		goto vmalloc_fault;
+
+	/* If we're in an interrupt or have no user
+	 * context, we must not take the fault..
+	 */
+	if (in_atomic() || !mm) {
+		bad_page_fault(regs, address, SIGSEGV);
+		return;
+	}
+
+	is_write = (exccause == XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE) ? 1 : 0;
+	is_exec =  (exccause == XCHAL_EXCCAUSE_ITLB_PRIVILEGE ||
+		    exccause == XCHAL_EXCCAUSE_ITLB_MISS ||
+		    exccause == XCHAL_EXCCAUSE_FETCH_CACHE_ATTRIBUTE) ? 1 : 0;
+
+#if 0
+	printk("[%s:%d:%08x:%d:%08x:%s%s]\n", current->comm, current->pid,
+	       address, exccause, regs->pc, is_write? "w":"", is_exec? "x":"");
+#endif
+
+	down_read(&mm->mmap_sem);
+	vma = find_vma(mm, address);
+
+	if (!vma)
+		goto bad_area;
+	if (vma->vm_start <= address)
+		goto good_area;
+	if (!(vma->vm_flags & VM_GROWSDOWN))
+		goto bad_area;
+	if (expand_stack(vma, address))
+		goto bad_area;
+
+	/* Ok, we have a good vm_area for this memory access, so
+	 * we can handle it..
+	 */
+
+good_area:
+	info.si_code = SEGV_ACCERR;
+
+	if (is_write) {
+		if (!(vma->vm_flags & VM_WRITE))
+			goto bad_area;
+	} else if (is_exec) {
+		if (!(vma->vm_flags & VM_EXEC))
+			goto bad_area;
+	} else	/* Allow read even from write-only pages. */
+		if (!(vma->vm_flags & (VM_READ | VM_WRITE)))
+			goto bad_area;
+
+	/* If for any reason at all we couldn't handle the fault,
+	 * make sure we exit gracefully rather than endlessly redo
+	 * the fault.
+	 */
+survive:
+	switch (handle_mm_fault(mm, vma, address, is_write)) {
+	case VM_FAULT_MINOR:
+		current->min_flt++;
+		break;
+	case VM_FAULT_MAJOR:
+		current->maj_flt++;
+		break;
+	case VM_FAULT_SIGBUS:
+		goto do_sigbus;
+	case VM_FAULT_OOM:
+		goto out_of_memory;
+	default:
+		BUG();
+	}
+
+	up_read(&mm->mmap_sem);
+	return;
+
+	/* Something tried to access memory that isn't in our memory map..
+	 * Fix it, but check if it's kernel or user first..
+	 */
+bad_area:
+	up_read(&mm->mmap_sem);
+	if (user_mode(regs)) {
+		current->thread.bad_vaddr = address;
+		current->thread.error_code = is_write;
+		info.si_signo = SIGSEGV;
+		info.si_errno = 0;
+		/* info.si_code has been set above */
+		info.si_addr = (void *) address;
+		force_sig_info(SIGSEGV, &info, current);
+		return;
+	}
+	bad_page_fault(regs, address, SIGSEGV);
+	return;
+
+
+	/* We ran out of memory, or some other thing happened to us that made
+	 * us unable to handle the page fault gracefully.
+	 */
+out_of_memory:
+	up_read(&mm->mmap_sem);
+	if (current->pid == 1) {
+		yield();
+		down_read(&mm->mmap_sem);
+		goto survive;
+	}
+	printk("VM: killing process %s\n", current->comm);
+	if (user_mode(regs))
+		do_exit(SIGKILL);
+	bad_page_fault(regs, address, SIGKILL);
+	return;
+
+do_sigbus:
+	up_read(&mm->mmap_sem);
+
+	/* Send a sigbus, regardless of whether we were in kernel
+	 * or user mode.
+	 */
+	current->thread.bad_vaddr = address;
+	info.si_code = SIGBUS;
+	info.si_errno = 0;
+	info.si_code = BUS_ADRERR;
+	info.si_addr = (void *) address;
+	force_sig_info(SIGBUS, &info, current);
+
+	/* Kernel mode? Handle exceptions or die */
+	if (!user_mode(regs))
+		bad_page_fault(regs, address, SIGBUS);
+
+vmalloc_fault:
+	{
+		/* Synchronize this task's top level page-table
+		 * with the 'reference' page table.
+		 */
+		struct mm_struct *act_mm = current->active_mm;
+		int index = pgd_index(address);
+		pgd_t *pgd, *pgd_k;
+		pmd_t *pmd, *pmd_k;
+		pte_t *pte_k;
+
+		if (act_mm == NULL)
+			goto bad_page_fault;
+
+		pgd = act_mm->pgd + index;
+		pgd_k = init_mm.pgd + index;
+
+		if (!pgd_present(*pgd_k))
+			goto bad_page_fault;
+
+		pgd_val(*pgd) = pgd_val(*pgd_k);
+
+		pmd = pmd_offset(pgd, address);
+		pmd_k = pmd_offset(pgd_k, address);
+		if (!pmd_present(*pmd) || !pmd_present(*pmd_k))
+			goto bad_page_fault;
+
+		pmd_val(*pmd) = pmd_val(*pmd_k);
+		pte_k = pte_offset_kernel(pmd_k, address);
+
+		if (!pte_present(*pte_k))
+			goto bad_page_fault;
+		return;
+	}
+bad_page_fault:
+	bad_page_fault(regs, address, SIGKILL);
+	return;
+}
+
+
+void
+bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
+{
+	extern void die(const char*, struct pt_regs*, long);
+	const struct exception_table_entry *entry;
+
+	/* Are we prepared to handle this kernel fault?  */
+	if ((entry = search_exception_tables(regs->pc)) != NULL) {
+#if 1
+		printk(KERN_DEBUG "%s: Exception at pc=%#010lx (%lx)\n",
+				current->comm, regs->pc, entry->fixup);
+#endif
+		current->thread.bad_uaddr = address;
+		regs->pc = entry->fixup;
+		return;
+	}
+
+	/* Oops. The kernel tried to access some bad page. We'll have to
+	 * terminate things with extreme prejudice.
+	 */
+	printk(KERN_ALERT "Unable to handle kernel paging request at virtual "
+	       "address %08lx\n pc = %08lx, ra = %08lx\n",
+	       address, regs->pc, regs->areg[0]);
+	die("Oops", regs, sig);
+	do_exit(sig);
+}
+
diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c
new file mode 100644
index 0000000..56aace8
--- /dev/null
+++ b/arch/xtensa/mm/init.c
@@ -0,0 +1,551 @@
+/*
+ * arch/xtensa/mm/init.c
+ *
+ * Derived from MIPS, PPC.
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ *
+ * Chris Zankel	<chris@zankel.net>
+ * Joe Taylor	<joe@tensilica.com, joetylr@yahoo.com>
+ * Marc Gauthier
+ * Kevin Chea
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/bootmem.h>
+#include <linux/swap.h>
+
+#include <asm/pgtable.h>
+#include <asm/bootparam.h>
+#include <asm/mmu_context.h>
+#include <asm/tlb.h>
+#include <asm/tlbflush.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+
+
+#define DEBUG 0
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+//static DEFINE_SPINLOCK(tlb_lock);
+
+/*
+ * This flag is used to indicate that the page was mapped and modified in
+ * kernel space, so the cache is probably dirty at that address.
+ * If cache aliasing is enabled and the page color mismatches, update_mmu_cache
+ * synchronizes the caches if this bit is set.
+ */
+
+#define PG_cache_clean PG_arch_1
+
+/* References to section boundaries */
+
+extern char _ftext, _etext, _fdata, _edata, _rodata_end;
+extern char __init_begin, __init_end;
+
+/*
+ * mem_reserve(start, end, must_exist)
+ *
+ * Reserve some memory from the memory pool.
+ *
+ * Parameters:
+ *  start	Start of region,
+ *  end		End of region,
+ *  must_exist	Must exist in memory pool.
+ *
+ * Returns:
+ *  0 (memory area couldn't be mapped)
+ * -1 (success)
+ */
+
+int __init mem_reserve(unsigned long start, unsigned long end, int must_exist)
+{
+	int i;
+
+	if (start == end)
+		return 0;
+
+	start = start & PAGE_MASK;
+	end = PAGE_ALIGN(end);
+
+	for (i = 0; i < sysmem.nr_banks; i++)
+		if (start < sysmem.bank[i].end
+		    && end >= sysmem.bank[i].start)
+			break;
+
+	if (i == sysmem.nr_banks) {
+		if (must_exist)
+			printk (KERN_WARNING "mem_reserve: [0x%0lx, 0x%0lx) "
+				"not in any region!\n", start, end);
+		return 0;
+	}
+
+	if (start > sysmem.bank[i].start) {
+		if (end < sysmem.bank[i].end) {
+			/* split entry */
+			if (sysmem.nr_banks >= SYSMEM_BANKS_MAX)
+				panic("meminfo overflow\n");
+			sysmem.bank[sysmem.nr_banks].start = end;
+			sysmem.bank[sysmem.nr_banks].end = sysmem.bank[i].end;
+			sysmem.nr_banks++;
+		}
+		sysmem.bank[i].end = start;
+	} else {
+		if (end < sysmem.bank[i].end)
+			sysmem.bank[i].start = end;
+		else {
+			/* remove entry */
+			sysmem.nr_banks--;
+			sysmem.bank[i].start = sysmem.bank[sysmem.nr_banks].start;
+			sysmem.bank[i].end   = sysmem.bank[sysmem.nr_banks].end;
+		}
+	}
+	return -1;
+}
+
+
+/*
+ * Initialize the bootmem system and give it all the memory we have available.
+ */
+
+void __init bootmem_init(void)
+{
+	unsigned long pfn;
+	unsigned long bootmap_start, bootmap_size;
+	int i;
+
+	max_low_pfn = max_pfn = 0;
+	min_low_pfn = ~0;
+
+	for (i=0; i < sysmem.nr_banks; i++) {
+		pfn = PAGE_ALIGN(sysmem.bank[i].start) >> PAGE_SHIFT;
+		if (pfn < min_low_pfn)
+			min_low_pfn = pfn;
+		pfn = PAGE_ALIGN(sysmem.bank[i].end - 1) >> PAGE_SHIFT;
+		if (pfn > max_pfn)
+			max_pfn = pfn;
+	}
+
+	if (min_low_pfn > max_pfn)
+		panic("No memory found!\n");
+
+	max_low_pfn = max_pfn < MAX_LOW_MEMORY >> PAGE_SHIFT ?
+		max_pfn : MAX_LOW_MEMORY >> PAGE_SHIFT;
+
+	/* Find an area to use for the bootmem bitmap. */
+
+	bootmap_size = bootmem_bootmap_pages(max_low_pfn) << PAGE_SHIFT;
+	bootmap_start = ~0;
+
+	for (i=0; i<sysmem.nr_banks; i++)
+		if (sysmem.bank[i].end - sysmem.bank[i].start >= bootmap_size) {
+			bootmap_start = sysmem.bank[i].start;
+			break;
+		}
+
+	if (bootmap_start == ~0UL)
+		panic("Cannot find %ld bytes for bootmap\n", bootmap_size);
+
+	/* Reserve the bootmem bitmap area */
+
+	mem_reserve(bootmap_start, bootmap_start + bootmap_size, 1);
+	bootmap_size = init_bootmem_node(NODE_DATA(0), min_low_pfn,
+					 bootmap_start >> PAGE_SHIFT,
+					 max_low_pfn);
+
+	/* Add all remaining memory pieces into the bootmem map */
+
+	for (i=0; i<sysmem.nr_banks; i++)
+		free_bootmem(sysmem.bank[i].start,
+			     sysmem.bank[i].end - sysmem.bank[i].start);
+
+}
+
+
+void __init paging_init(void)
+{
+	unsigned long zones_size[MAX_NR_ZONES];
+	int i;
+
+	/* All pages are DMA-able, so we put them all in the DMA zone. */
+
+	zones_size[ZONE_DMA] = max_low_pfn;
+	for (i = 1; i < MAX_NR_ZONES; i++)
+		zones_size[i] = 0;
+
+#ifdef CONFIG_HIGHMEM
+	zones_size[ZONE_HIGHMEM] = max_pfn - max_low_pfn;
+#endif
+
+	/* Initialize the kernel's page tables. */
+
+	memset(swapper_pg_dir, 0, PAGE_SIZE);
+
+	free_area_init(zones_size);
+}
+
+/*
+ * Flush the mmu and reset associated register to default values.
+ */
+
+void __init init_mmu (void)
+{
+	/* Writing zeros to the <t>TLBCFG special registers ensure
+	 * that valid values exist in the register.  For existing
+	 * PGSZID<w> fields, zero selects the first element of the
+	 * page-size array.  For nonexistant PGSZID<w> fields, zero is
+	 * the best value to write.  Also, when changing PGSZID<w>
+	 * fields, the corresponding TLB must be flushed.
+	 */
+	set_itlbcfg_register (0);
+	set_dtlbcfg_register (0);
+	flush_tlb_all ();
+
+	/* Set rasid register to a known value. */
+
+	set_rasid_register (ASID_ALL_RESERVED);
+
+	/* Set PTEVADDR special register to the start of the page
+	 * table, which is in kernel mappable space (ie. not
+	 * statically mapped).  This register's value is undefined on
+	 * reset.
+	 */
+	set_ptevaddr_register (PGTABLE_START);
+}
+
+/*
+ * Initialize memory pages.
+ */
+
+void __init mem_init(void)
+{
+	unsigned long codesize, reservedpages, datasize, initsize;
+	unsigned long highmemsize, tmp, ram;
+
+	max_mapnr = num_physpages = max_low_pfn;
+	high_memory = (void *) __va(max_mapnr << PAGE_SHIFT);
+	highmemsize = 0;
+
+#if CONFIG_HIGHMEM
+#error HIGHGMEM not implemented in init.c
+#endif
+
+	totalram_pages += free_all_bootmem();
+
+	reservedpages = ram = 0;
+	for (tmp = 0; tmp < max_low_pfn; tmp++) {
+		ram++;
+		if (PageReserved(mem_map+tmp))
+			reservedpages++;
+	}
+
+	codesize =  (unsigned long) &_etext - (unsigned long) &_ftext;
+	datasize =  (unsigned long) &_edata - (unsigned long) &_fdata;
+	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
+
+	printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, "
+	       "%ldk data, %ldk init %ldk highmem)\n",
+	       (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
+	       ram << (PAGE_SHIFT-10),
+	       codesize >> 10,
+	       reservedpages << (PAGE_SHIFT-10),
+	       datasize >> 10,
+	       initsize >> 10,
+	       highmemsize >> 10);
+}
+
+void
+free_reserved_mem(void *start, void *end)
+{
+	for (; start < end; start += PAGE_SIZE) {
+		ClearPageReserved(virt_to_page(start));
+		set_page_count(virt_to_page(start), 1);
+		free_page((unsigned long)start);
+		totalram_pages++;
+	}
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+extern int initrd_is_mapped;
+
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+	if (initrd_is_mapped) {
+		free_reserved_mem((void*)start, (void*)end);
+		printk ("Freeing initrd memory: %ldk freed\n",(end-start)>>10);
+	}
+}
+#endif
+
+void free_initmem(void)
+{
+	free_reserved_mem(&__init_begin, &__init_end);
+	printk("Freeing unused kernel memory: %dk freed\n",
+	       (&__init_end - &__init_begin) >> 10);
+}
+
+void show_mem(void)
+{
+	int i, free = 0, total = 0, reserved = 0;
+	int shared = 0, cached = 0;
+
+	printk("Mem-info:\n");
+	show_free_areas();
+	printk("Free swap:       %6ldkB\n", nr_swap_pages<<(PAGE_SHIFT-10));
+	i = max_mapnr;
+	while (i-- > 0) {
+		total++;
+		if (PageReserved(mem_map+i))
+			reserved++;
+		else if (PageSwapCache(mem_map+i))
+			cached++;
+		else if (!page_count(mem_map + i))
+			free++;
+		else
+			shared += page_count(mem_map + i) - 1;
+	}
+	printk("%d pages of RAM\n", total);
+	printk("%d reserved pages\n", reserved);
+	printk("%d pages shared\n", shared);
+	printk("%d pages swap cached\n",cached);
+	printk("%d free pages\n", free);
+}
+
+/* ------------------------------------------------------------------------- */
+
+#if (DCACHE_WAY_SIZE > PAGE_SIZE)
+
+/*
+ * With cache aliasing, the page color of the page in kernel space and user
+ * space might mismatch. We temporarily map the page to a different virtual
+ * address with the same color and clear the page there.
+ */
+
+void clear_user_page(void *kaddr, unsigned long vaddr, struct page* page)
+{
+
+  	/*  There shouldn't be any entries for this page. */
+
+	__flush_invalidate_dcache_page_phys(__pa(page_address(page)));
+
+	if (!PAGE_COLOR_EQ(vaddr, kaddr)) {
+		unsigned long v, p;
+
+		/* Temporarily map page to DTLB_WAY_DCACHE_ALIAS0. */
+
+		spin_lock(&tlb_lock);
+
+		p = (unsigned long)pte_val((mk_pte(page,PAGE_KERNEL)));
+		kaddr = (void*)PAGE_COLOR_MAP0(vaddr);
+		v = (unsigned long)kaddr | DTLB_WAY_DCACHE_ALIAS0;
+		__asm__ __volatile__("wdtlb %0,%1; dsync" : :"a" (p), "a" (v));
+
+		clear_page(kaddr);
+
+		spin_unlock(&tlb_lock);
+	} else {
+		clear_page(kaddr);
+	}
+
+	/* We need to make sure that i$ and d$ are coherent. */
+
+	clear_bit(PG_cache_clean, &page->flags);
+}
+
+/*
+ * With cache aliasing, we have to make sure that the page color of the page
+ * in kernel space matches that of the virtual user address before we read
+ * the page. If the page color differ, we create a temporary DTLB entry with
+ * the corrent page color and use this 'temporary' address as the source.
+ * We then use the same approach as in clear_user_page and copy the data
+ * to the kernel space and clear the PG_cache_clean bit to synchronize caches
+ * later.
+ *
+ * Note:
+ * Instead of using another 'way' for the temporary DTLB entry, we could
+ * probably use the same entry that points to the kernel address (after
+ * saving the original value and restoring it when we are done).
+ */
+
+void copy_user_page(void* to, void* from, unsigned long vaddr,
+    		    struct page* to_page)
+{
+	/* There shouldn't be any entries for the new page. */
+
+	__flush_invalidate_dcache_page_phys(__pa(page_address(to_page)));
+
+	spin_lock(&tlb_lock);
+
+	if (!PAGE_COLOR_EQ(vaddr, from)) {
+		unsigned long v, p, t;
+
+		__asm__ __volatile__ ("pdtlb %1,%2; rdtlb1 %0,%1"
+				      : "=a"(p), "=a"(t) : "a"(from));
+		from = (void*)PAGE_COLOR_MAP0(vaddr);
+		v = (unsigned long)from | DTLB_WAY_DCACHE_ALIAS0;
+		__asm__ __volatile__ ("wdtlb %0,%1; dsync" ::"a" (p), "a" (v));
+	}
+
+	if (!PAGE_COLOR_EQ(vaddr, to)) {
+		unsigned long v, p;
+
+		p = (unsigned long)pte_val((mk_pte(to_page,PAGE_KERNEL)));
+		to = (void*)PAGE_COLOR_MAP1(vaddr);
+		v = (unsigned long)to | DTLB_WAY_DCACHE_ALIAS1;
+		__asm__ __volatile__ ("wdtlb %0,%1; dsync" ::"a" (p), "a" (v));
+	}
+	copy_page(to, from);
+
+	spin_unlock(&tlb_lock);
+
+	/* We need to make sure that i$ and d$ are coherent. */
+
+	clear_bit(PG_cache_clean, &to_page->flags);
+}
+
+
+
+/*
+ * Any time the kernel writes to a user page cache page, or it is about to
+ * read from a page cache page this routine is called.
+ *
+ * Note:
+ * The kernel currently only provides one architecture bit in the page
+ * flags that we use for I$/D$ coherency. Maybe, in future, we can
+ * use a sepearte bit for deferred dcache aliasing:
+ * If the page is not mapped yet, we only need to set a flag,
+ * if mapped, we need to invalidate the page.
+ */
+// FIXME: we probably need this for WB caches not only for Page Coloring..
+
+void flush_dcache_page(struct page *page)
+{
+	unsigned long addr = __pa(page_address(page));
+	struct address_space *mapping = page_mapping(page);
+
+	__flush_invalidate_dcache_page_phys(addr);
+
+	if (!test_bit(PG_cache_clean, &page->flags))
+		return;
+
+	/* If this page hasn't been mapped, yet, handle I$/D$ coherency later.*/
+#if 0
+	if (mapping && !mapping_mapped(mapping))
+		clear_bit(PG_cache_clean, &page->flags);
+	else
+#endif
+		__invalidate_icache_page_phys(addr);
+}
+
+void flush_cache_range(struct vm_area_struct* vma, unsigned long s,
+		       unsigned long e)
+{
+	__flush_invalidate_cache_all();
+}
+
+void flush_cache_page(struct vm_area_struct* vma, unsigned long address,
+    		      unsigned long pfn)
+{
+	struct page *page = pfn_to_page(pfn);
+
+	/* Remove any entry for the old mapping. */
+
+	if (current->active_mm == vma->vm_mm) {
+		unsigned long addr = __pa(page_address(page));
+		__flush_invalidate_dcache_page_phys(addr);
+		if ((vma->vm_flags & VM_EXEC) != 0)
+			__invalidate_icache_page_phys(addr);
+	} else {
+		BUG();
+	}
+}
+
+#endif	/* (DCACHE_WAY_SIZE > PAGE_SIZE) */
+
+
+pte_t* pte_alloc_one_kernel (struct mm_struct* mm, unsigned long addr)
+{
+	pte_t* pte = (pte_t*)__get_free_pages(GFP_KERNEL|__GFP_REPEAT, 0);
+	if (likely(pte)) {
+	       	pte_t* ptep = (pte_t*)(pte_val(*pte) + PAGE_OFFSET);
+		int i;
+		for (i = 0; i < 1024; i++, ptep++)
+			pte_clear(mm, addr, ptep);
+	}
+	return pte;
+}
+
+struct page* pte_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+	struct page *page;
+
+	page = alloc_pages(GFP_KERNEL | __GFP_REPEAT, 0);
+
+	if (likely(page)) {
+		pte_t* ptep = kmap_atomic(page, KM_USER0);
+		int i;
+
+		for (i = 0; i < 1024; i++, ptep++)
+			pte_clear(mm, addr, ptep);
+
+		kunmap_atomic(ptep, KM_USER0);
+	}
+	return page;
+}
+
+
+/*
+ * Handle D$/I$ coherency.
+ *
+ * Note:
+ * We only have one architecture bit for the page flags, so we cannot handle
+ * cache aliasing, yet.
+ */
+
+void
+update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t pte)
+{
+	unsigned long pfn = pte_pfn(pte);
+	struct page *page;
+	unsigned long vaddr = addr & PAGE_MASK;
+
+	if (!pfn_valid(pfn))
+		return;
+
+	page = pfn_to_page(pfn);
+
+	invalidate_itlb_mapping(addr);
+	invalidate_dtlb_mapping(addr);
+
+	/* We have a new mapping. Use it. */
+
+	write_dtlb_entry(pte, dtlb_probe(addr));
+
+	/* If the processor can execute from this page, synchronize D$/I$. */
+
+	if ((vma->vm_flags & VM_EXEC) != 0) {
+
+		write_itlb_entry(pte, itlb_probe(addr));
+
+		/* Synchronize caches, if not clean. */
+
+		if (!test_and_set_bit(PG_cache_clean, &page->flags)) {
+			__flush_dcache_page(vaddr);
+			__invalidate_icache_page(vaddr);
+		}
+	}
+}
+
diff --git a/arch/xtensa/mm/misc.S b/arch/xtensa/mm/misc.S
new file mode 100644
index 0000000..327c0f1
--- /dev/null
+++ b/arch/xtensa/mm/misc.S
@@ -0,0 +1,374 @@
+/*
+ * arch/xtensa/mm/misc.S
+ *
+ * Miscellaneous assembly functions.
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ *
+ * Chris Zankel	<chris@zankel.net>
+ */
+
+/* Note: we might want to implement some of the loops as zero-overhead-loops,
+ *	 where applicable and if supported by the processor.
+ */
+
+#include <linux/linkage.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include <xtensa/cacheasm.h>
+#include <xtensa/cacheattrasm.h>
+
+/* clear_page (page) */
+
+ENTRY(clear_page)
+	entry	a1, 16
+	addi	a4, a2, PAGE_SIZE
+	movi	a3, 0
+
+1:	s32i	a3, a2, 0
+	s32i	a3, a2, 4
+	s32i	a3, a2, 8
+	s32i	a3, a2, 12
+	s32i	a3, a2, 16
+	s32i	a3, a2, 20
+	s32i	a3, a2, 24
+	s32i	a3, a2, 28
+	addi	a2, a2, 32
+	blt	a2, a4, 1b
+
+	retw
+
+/*
+ * copy_page (void *to, void *from)
+ *                  a2        a3
+ */
+
+ENTRY(copy_page)
+	entry	a1, 16
+	addi	a4, a2, PAGE_SIZE
+
+1:	l32i	a5, a3, 0
+	l32i	a6, a3, 4
+	l32i	a7, a3, 8
+	s32i	a5, a2, 0
+	s32i	a6, a2, 4
+	s32i	a7, a2, 8
+	l32i	a5, a3, 12
+	l32i	a6, a3, 16
+	l32i	a7, a3, 20
+	s32i	a5, a2, 12
+	s32i	a6, a2, 16
+	s32i	a7, a2, 20
+	l32i	a5, a3, 24
+	l32i	a6, a3, 28
+	s32i	a5, a2, 24
+	s32i	a6, a2, 28
+	addi	a2, a2, 32
+	addi	a3, a3, 32
+	blt	a2, a4, 1b
+
+	retw
+
+
+/*
+ * void __flush_invalidate_cache_all(void)
+ */
+
+ENTRY(__flush_invalidate_cache_all)
+	entry	sp, 16
+	dcache_writeback_inv_all a2, a3
+	icache_invalidate_all a2, a3
+	retw
+
+/*
+ * void __invalidate_icache_all(void)
+ */
+
+ENTRY(__invalidate_icache_all)
+	entry	sp, 16
+	icache_invalidate_all a2, a3
+	retw
+
+/*
+ * void __flush_invalidate_dcache_all(void)
+ */
+
+ENTRY(__flush_invalidate_dcache_all)
+	entry	sp, 16
+	dcache_writeback_inv_all a2, a3
+	retw
+
+
+/*
+ * void __flush_invalidate_cache_range(ulong start, ulong size)
+ */
+
+ENTRY(__flush_invalidate_cache_range)
+	entry	sp, 16
+	mov	a4, a2
+	mov	a5, a3
+	dcache_writeback_inv_region a4, a5, a6
+	icache_invalidate_region a2, a3, a4
+	retw
+
+/*
+ * void __invalidate_icache_page(ulong start)
+ */
+
+ENTRY(__invalidate_icache_page)
+	entry	sp, 16
+	movi	a3, PAGE_SIZE
+	icache_invalidate_region a2, a3, a4
+	retw
+
+/*
+ * void __invalidate_dcache_page(ulong start)
+ */
+
+ENTRY(__invalidate_dcache_page)
+	entry	sp, 16
+	movi	a3, PAGE_SIZE
+	dcache_invalidate_region a2, a3, a4
+	retw
+
+/*
+ * void __invalidate_icache_range(ulong start, ulong size)
+ */
+
+ENTRY(__invalidate_icache_range)
+	entry	sp, 16
+	icache_invalidate_region a2, a3, a4
+	retw
+
+/*
+ * void __invalidate_dcache_range(ulong start, ulong size)
+ */
+
+ENTRY(__invalidate_dcache_range)
+	entry	sp, 16
+	dcache_invalidate_region a2, a3, a4
+	retw
+
+/*
+ * void __flush_dcache_page(ulong start)
+ */
+
+ENTRY(__flush_dcache_page)
+	entry	sp, 16
+	movi	a3, PAGE_SIZE
+	dcache_writeback_region a2, a3, a4
+	retw
+
+/*
+ * void __flush_invalidate_dcache_page(ulong start)
+ */
+
+ENTRY(__flush_invalidate_dcache_page)
+	entry	sp, 16
+	movi	a3, PAGE_SIZE
+	dcache_writeback_inv_region a2, a3, a4
+	retw
+
+/*
+ * void __flush_invalidate_dcache_range(ulong start, ulong size)
+ */
+
+ENTRY(__flush_invalidate_dcache_range)
+	entry	sp, 16
+	dcache_writeback_inv_region a2, a3, a4
+	retw
+
+/*
+ * void __invalidate_dcache_all(void)
+ */
+
+ENTRY(__invalidate_dcache_all)
+	entry	sp, 16
+	dcache_invalidate_all a2, a3
+	retw
+
+/*
+ * void __flush_invalidate_dcache_page_phys(ulong start)
+ */
+
+ENTRY(__flush_invalidate_dcache_page_phys)
+	entry	sp, 16
+
+	movi	a3, XCHAL_DCACHE_SIZE
+	movi	a4, PAGE_MASK | 1
+	addi	a2, a2, 1
+
+1:	addi	a3, a3, -XCHAL_DCACHE_LINESIZE
+
+	ldct	a6, a3
+	dsync
+	and	a6, a6, a4
+	beq	a6, a2, 2f
+	bgeui	a3, 2, 1b
+	retw
+
+2:	diwbi	a3, 0
+	bgeui	a3, 2, 1b
+	retw
+
+ENTRY(check_dcache_low0)
+	entry	sp, 16
+
+	movi	a3, XCHAL_DCACHE_SIZE / 4
+	movi	a4, PAGE_MASK | 1
+	addi	a2, a2, 1
+
+1:	addi	a3, a3, -XCHAL_DCACHE_LINESIZE
+
+	ldct	a6, a3
+	dsync
+	and	a6, a6, a4
+	beq	a6, a2, 2f
+	bgeui	a3, 2, 1b
+	retw
+
+2:	j 2b
+
+ENTRY(check_dcache_high0)
+	entry	sp, 16
+
+	movi	a5, XCHAL_DCACHE_SIZE / 4
+	movi	a3, XCHAL_DCACHE_SIZE / 2
+	movi	a4, PAGE_MASK | 1
+	addi	a2, a2, 1
+
+1:	addi	a3, a3, -XCHAL_DCACHE_LINESIZE
+	addi	a5, a5, -XCHAL_DCACHE_LINESIZE
+
+	ldct	a6, a3
+	dsync
+	and	a6, a6, a4
+	beq	a6, a2, 2f
+	bgeui	a5, 2, 1b
+	retw
+
+2:	j 2b
+
+ENTRY(check_dcache_low1)
+	entry	sp, 16
+
+	movi	a5, XCHAL_DCACHE_SIZE / 4
+	movi	a3, XCHAL_DCACHE_SIZE * 3 / 4
+	movi	a4, PAGE_MASK | 1
+	addi	a2, a2, 1
+
+1:	addi	a3, a3, -XCHAL_DCACHE_LINESIZE
+	addi	a5, a5, -XCHAL_DCACHE_LINESIZE
+
+	ldct	a6, a3
+	dsync
+	and	a6, a6, a4
+	beq	a6, a2, 2f
+	bgeui	a5, 2, 1b
+	retw
+
+2:	j 2b
+
+ENTRY(check_dcache_high1)
+	entry	sp, 16
+
+	movi	a5, XCHAL_DCACHE_SIZE / 4
+	movi	a3, XCHAL_DCACHE_SIZE
+	movi	a4, PAGE_MASK | 1
+	addi	a2, a2, 1
+
+1:	addi	a3, a3, -XCHAL_DCACHE_LINESIZE
+	addi	a5, a5, -XCHAL_DCACHE_LINESIZE
+
+	ldct	a6, a3
+	dsync
+	and	a6, a6, a4
+	beq	a6, a2, 2f
+	bgeui	a5, 2, 1b
+	retw
+
+2:	j 2b
+
+
+/*
+ * void __invalidate_icache_page_phys(ulong start)
+ */
+
+ENTRY(__invalidate_icache_page_phys)
+	entry	sp, 16
+
+	movi	a3, XCHAL_ICACHE_SIZE
+	movi	a4, PAGE_MASK | 1
+	addi	a2, a2, 1
+
+1:	addi	a3, a3, -XCHAL_ICACHE_LINESIZE
+
+	lict	a6, a3
+	isync
+	and	a6, a6, a4
+	beq	a6, a2, 2f
+	bgeui	a3, 2, 1b
+	retw
+
+2:	iii	a3, 0
+	bgeui	a3, 2, 1b
+	retw
+
+
+#if 0
+
+	movi	a3, XCHAL_DCACHE_WAYS - 1
+	movi	a4, PAGE_SIZE
+
+1:	mov	a5, a2
+	add	a6, a2, a4
+
+2:	diwbi	a5, 0
+	diwbi	a5, XCHAL_DCACHE_LINESIZE
+	diwbi	a5, XCHAL_DCACHE_LINESIZE * 2
+	diwbi	a5, XCHAL_DCACHE_LINESIZE * 3
+
+	addi	a5, a5, XCHAL_DCACHE_LINESIZE * 4
+	blt	a5, a6, 2b
+
+	addi	a3, a3, -1
+	addi	a2, a2, XCHAL_DCACHE_SIZE / XCHAL_DCACHE_WAYS
+	bgez	a3, 1b
+
+	retw
+
+ENTRY(__invalidate_icache_page_index)
+	entry	sp, 16
+
+	movi	a3, XCHAL_ICACHE_WAYS - 1
+	movi	a4, PAGE_SIZE
+
+1:	mov	a5, a2
+	add	a6, a2, a4
+
+2:	iii	a5, 0
+	iii	a5, XCHAL_ICACHE_LINESIZE
+	iii	a5, XCHAL_ICACHE_LINESIZE * 2
+	iii	a5, XCHAL_ICACHE_LINESIZE * 3
+
+	addi	a5, a5, XCHAL_ICACHE_LINESIZE * 4
+	blt	a5, a6, 2b
+
+	addi	a3, a3, -1
+	addi	a2, a2, XCHAL_ICACHE_SIZE / XCHAL_ICACHE_WAYS
+	bgez	a3, 2b
+
+	retw
+
+#endif
+
+
+
+
+
+
diff --git a/arch/xtensa/mm/pgtable.c b/arch/xtensa/mm/pgtable.c
new file mode 100644
index 0000000..e5e119c
--- /dev/null
+++ b/arch/xtensa/mm/pgtable.c
@@ -0,0 +1,76 @@
+/*
+ * arch/xtensa/mm/fault.c
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ *
+ * Chris Zankel <chris@zankel.net>
+ */
+
+#if (DCACHE_SIZE > PAGE_SIZE)
+
+pte_t* pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+{
+	pte_t *pte, p;
+	int color = ADDR_COLOR(address);
+	int i;
+
+	p = (pte_t*) __get_free_pages(GFP_KERNEL|__GFP_REPEAT, COLOR_ORDER);
+
+	if (likely(p)) {
+		struct page *page;
+
+		for (i = 0; i < COLOR_SIZE; i++, p++) {
+			page = virt_to_page(pte);
+
+			set_page_count(page, 1);
+			ClearPageCompound(page);
+
+			if (ADDR_COLOR(p) == color)
+				pte = p;
+			else
+				free_page(p);
+		}
+		clear_page(pte);
+	}
+	return pte;
+}
+
+#ifdef PROFILING
+
+int mask;
+int hit;
+int flush;
+
+#endif
+
+struct page* pte_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+	struct page *page, p;
+	int color = ADDR_COLOR(address);
+
+	p = alloc_pages(GFP_KERNEL | __GFP_REPEAT, PTE_ORDER);
+
+	if (likely(p)) {
+		for (i = 0; i < PAGE_ORDER; i++) {
+			set_page_count(p, 1);
+			ClearPageCompound(p);
+
+			if (PADDR_COLOR(page_address(pg)) == color)
+				page = p;
+			else
+				free_page(p);
+		}
+		clear_highpage(page);
+	}
+
+	return page;
+}
+
+#endif
+
+
+
diff --git a/arch/xtensa/mm/tlb.c b/arch/xtensa/mm/tlb.c
new file mode 100644
index 0000000..d3bd3bf
--- /dev/null
+++ b/arch/xtensa/mm/tlb.c
@@ -0,0 +1,545 @@
+/*
+ * arch/xtensa/mm/mmu.c
+ *
+ * Logic that manipulates the Xtensa MMU.  Derived from MIPS.
+ *
+ * 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) 2001 - 2003 Tensilica Inc.
+ *
+ * Joe Taylor
+ * Chris Zankel	<chris@zankel.net>
+ * Marc Gauthier
+ */
+
+#include <linux/mm.h>
+#include <asm/processor.h>
+#include <asm/mmu_context.h>
+#include <asm/tlbflush.h>
+#include <asm/system.h>
+#include <asm/cacheflush.h>
+
+
+static inline void __flush_itlb_all (void)
+{
+	int way, index;
+
+	for (way = 0; way < XCHAL_ITLB_ARF_WAYS; way++) {
+		for (index = 0; index < ITLB_ENTRIES_PER_ARF_WAY; index++) {
+			int entry = way + (index << PAGE_SHIFT);
+			invalidate_itlb_entry_no_isync (entry);
+		}
+	}
+	asm volatile ("isync\n");
+}
+
+static inline void __flush_dtlb_all (void)
+{
+	int way, index;
+
+	for (way = 0; way < XCHAL_DTLB_ARF_WAYS; way++) {
+		for (index = 0; index < DTLB_ENTRIES_PER_ARF_WAY; index++) {
+			int entry = way + (index << PAGE_SHIFT);
+			invalidate_dtlb_entry_no_isync (entry);
+		}
+	}
+	asm volatile ("isync\n");
+}
+
+
+void flush_tlb_all (void)
+{
+	__flush_itlb_all();
+	__flush_dtlb_all();
+}
+
+/* If mm is current, we simply assign the current task a new ASID, thus,
+ * invalidating all previous tlb entries. If mm is someone else's user mapping,
+ * wie invalidate the context, thus, when that user mapping is swapped in,
+ * a new context will be assigned to it.
+ */
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+#if 0
+	printk("[tlbmm<%lx>]\n", (unsigned long)mm->context);
+#endif
+
+	if (mm == current->active_mm) {
+		int flags;
+		local_save_flags(flags);
+		get_new_mmu_context(mm, asid_cache);
+		set_rasid_register(ASID_INSERT(mm->context));
+		local_irq_restore(flags);
+	}
+	else
+		mm->context = 0;
+}
+
+void flush_tlb_range (struct vm_area_struct *vma,
+    		      unsigned long start, unsigned long end)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	unsigned long flags;
+
+	if (mm->context == NO_CONTEXT)
+		return;
+
+#if 0
+	printk("[tlbrange<%02lx,%08lx,%08lx>]\n",
+			(unsigned long)mm->context, start, end);
+#endif
+	local_save_flags(flags);
+
+	if (end-start + (PAGE_SIZE-1) <= SMALLEST_NTLB_ENTRIES << PAGE_SHIFT) {
+		int oldpid = get_rasid_register();
+		set_rasid_register (ASID_INSERT(mm->context));
+		start &= PAGE_MASK;
+ 		if (vma->vm_flags & VM_EXEC)
+			while(start < end) {
+				invalidate_itlb_mapping(start);
+				invalidate_dtlb_mapping(start);
+				start += PAGE_SIZE;
+			}
+		else
+			while(start < end) {
+				invalidate_dtlb_mapping(start);
+				start += PAGE_SIZE;
+			}
+
+		set_rasid_register(oldpid);
+	} else {
+		get_new_mmu_context(mm, asid_cache);
+		if (mm == current->active_mm)
+			set_rasid_register(ASID_INSERT(mm->context));
+	}
+	local_irq_restore(flags);
+}
+
+void flush_tlb_page (struct vm_area_struct *vma, unsigned long page)
+{
+	struct mm_struct* mm = vma->vm_mm;
+	unsigned long flags;
+	int oldpid;
+#if 0
+	printk("[tlbpage<%02lx,%08lx>]\n",
+			(unsigned long)mm->context, page);
+#endif
+
+	if(mm->context == NO_CONTEXT)
+		return;
+
+	local_save_flags(flags);
+
+       	oldpid = get_rasid_register();
+
+	if (vma->vm_flags & VM_EXEC)
+		invalidate_itlb_mapping(page);
+	invalidate_dtlb_mapping(page);
+
+	set_rasid_register(oldpid);
+
+	local_irq_restore(flags);
+
+#if 0
+	flush_tlb_all();
+	return;
+#endif
+}
+
+
+#ifdef DEBUG_TLB
+
+#define USE_ITLB  0
+#define USE_DTLB  1
+
+struct way_config_t {
+	int indicies;
+	int indicies_log2;
+	int pgsz_log2;
+	int arf;
+};
+
+static struct way_config_t itlb[XCHAL_ITLB_WAYS] =
+{
+	{ XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ENTRIES),
+	  XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ENTRIES_LOG2),
+	  XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, PAGESZ_LOG2_MIN),
+	  XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ARF)
+	},
+	{ XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ENTRIES),
+	  XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ENTRIES_LOG2),
+	  XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, PAGESZ_LOG2_MIN),
+	  XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ARF)
+	},
+	{ XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ENTRIES),
+	  XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ENTRIES_LOG2),
+	  XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, PAGESZ_LOG2_MIN),
+	  XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ARF)
+	},
+	{ XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ENTRIES),
+	  XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ENTRIES_LOG2),
+	  XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, PAGESZ_LOG2_MIN),
+	  XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ARF)
+	},
+	{ XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ENTRIES),
+	  XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ENTRIES_LOG2),
+	  XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, PAGESZ_LOG2_MIN),
+	  XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ARF)
+	},
+	{ XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ENTRIES),
+	  XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ENTRIES_LOG2),
+	  XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, PAGESZ_LOG2_MIN),
+	  XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ARF)
+	},
+	{ XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ENTRIES),
+	  XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ENTRIES_LOG2),
+	  XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, PAGESZ_LOG2_MIN),
+	  XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ARF)
+	}
+};
+
+static struct way_config_t dtlb[XCHAL_DTLB_WAYS] =
+{
+	{ XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ENTRIES),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ENTRIES_LOG2),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, PAGESZ_LOG2_MIN),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ARF)
+	},
+	{ XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ENTRIES),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ENTRIES_LOG2),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, PAGESZ_LOG2_MIN),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ARF)
+	},
+	{ XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ENTRIES),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ENTRIES_LOG2),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, PAGESZ_LOG2_MIN),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ARF)
+	},
+	{ XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ENTRIES),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ENTRIES_LOG2),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, PAGESZ_LOG2_MIN),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ARF)
+	},
+	{ XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ENTRIES),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ENTRIES_LOG2),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, PAGESZ_LOG2_MIN),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ARF)
+	},
+	{ XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ENTRIES),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ENTRIES_LOG2),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, PAGESZ_LOG2_MIN),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ARF)
+	},
+	{ XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ENTRIES),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ENTRIES_LOG2),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, PAGESZ_LOG2_MIN),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ARF)
+	},
+	{ XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ENTRIES),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ENTRIES_LOG2),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, PAGESZ_LOG2_MIN),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ARF)
+	},
+	{ XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ENTRIES),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ENTRIES_LOG2),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, PAGESZ_LOG2_MIN),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ARF)
+	},
+	{ XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ENTRIES),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ENTRIES_LOG2),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, PAGESZ_LOG2_MIN),
+	  XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ARF)
+	}
+};
+
+/*  Total number of entries:  */
+#define ITLB_TOTAL_ENTRIES	\
+		XCHAL_ITLB_SET(XCHAL_ITLB_WAY0_SET, ENTRIES) + \
+		XCHAL_ITLB_SET(XCHAL_ITLB_WAY1_SET, ENTRIES) + \
+		XCHAL_ITLB_SET(XCHAL_ITLB_WAY2_SET, ENTRIES) + \
+		XCHAL_ITLB_SET(XCHAL_ITLB_WAY3_SET, ENTRIES) + \
+		XCHAL_ITLB_SET(XCHAL_ITLB_WAY4_SET, ENTRIES) + \
+		XCHAL_ITLB_SET(XCHAL_ITLB_WAY5_SET, ENTRIES) + \
+		XCHAL_ITLB_SET(XCHAL_ITLB_WAY6_SET, ENTRIES)
+#define DTLB_TOTAL_ENTRIES	\
+		XCHAL_DTLB_SET(XCHAL_DTLB_WAY0_SET, ENTRIES) + \
+		XCHAL_DTLB_SET(XCHAL_DTLB_WAY1_SET, ENTRIES) + \
+		XCHAL_DTLB_SET(XCHAL_DTLB_WAY2_SET, ENTRIES) + \
+		XCHAL_DTLB_SET(XCHAL_DTLB_WAY3_SET, ENTRIES) + \
+		XCHAL_DTLB_SET(XCHAL_DTLB_WAY4_SET, ENTRIES) + \
+		XCHAL_DTLB_SET(XCHAL_DTLB_WAY5_SET, ENTRIES) + \
+		XCHAL_DTLB_SET(XCHAL_DTLB_WAY6_SET, ENTRIES) + \
+		XCHAL_DTLB_SET(XCHAL_DTLB_WAY7_SET, ENTRIES) + \
+		XCHAL_DTLB_SET(XCHAL_DTLB_WAY8_SET, ENTRIES) + \
+		XCHAL_DTLB_SET(XCHAL_DTLB_WAY9_SET, ENTRIES)
+
+
+typedef struct {
+    unsigned		va;
+    unsigned		pa;
+    unsigned char	asid;
+    unsigned char	ca;
+    unsigned char	way;
+    unsigned char	index;
+    unsigned char	pgsz_log2;	/* 0 .. 32 */
+    unsigned char	type;		/* 0=ITLB 1=DTLB */
+} tlb_dump_entry_t;
+
+/*  Return -1 if a precedes b, +1 if a follows b, 0 if same:  */
+int cmp_tlb_dump_info( tlb_dump_entry_t *a, tlb_dump_entry_t *b )
+{
+    if (a->asid < b->asid) return -1;
+    if (a->asid > b->asid) return  1;
+    if (a->va < b->va) return -1;
+    if (a->va > b->va) return  1;
+    if (a->pa < b->pa) return -1;
+    if (a->pa > b->pa) return  1;
+    if (a->ca < b->ca) return -1;
+    if (a->ca > b->ca) return  1;
+    if (a->way < b->way) return -1;
+    if (a->way > b->way) return  1;
+    if (a->index < b->index) return -1;
+    if (a->index > b->index) return  1;
+    return 0;
+}
+
+void sort_tlb_dump_info( tlb_dump_entry_t *t, int n )
+{
+    int i, j;
+    /*  Simple O(n*n) sort:  */
+    for (i = 0; i < n-1; i++)
+	for (j = i+1; j < n; j++)
+	    if (cmp_tlb_dump_info(t+i, t+j) > 0) {
+		tlb_dump_entry_t tmp = t[i];
+		t[i] = t[j];
+		t[j] = tmp;
+	    }
+}
+
+
+static tlb_dump_entry_t itlb_dump_info[ITLB_TOTAL_ENTRIES];
+static tlb_dump_entry_t dtlb_dump_info[DTLB_TOTAL_ENTRIES];
+
+
+static inline char *way_type (int type)
+{
+	return type ? "autorefill" : "non-autorefill";
+}
+
+void print_entry (struct way_config_t *way_info,
+		  unsigned int way,
+		  unsigned int index,
+		  unsigned int virtual,
+		  unsigned int translation)
+{
+	char valid_chr;
+	unsigned int va, pa, asid, ca;
+
+	va = virtual &
+	  	~((1 << (way_info->pgsz_log2 + way_info->indicies_log2)) - 1);
+	asid = virtual & ((1 << XCHAL_MMU_ASID_BITS) - 1);
+	pa = translation & ~((1 << way_info->pgsz_log2) - 1);
+	ca = translation & ((1 << XCHAL_MMU_CA_BITS) - 1);
+	valid_chr = asid ? 'V' : 'I';
+
+	/* Compute and incorporate the effect of the index bits on the
+	 * va.  It's more useful for kernel debugging, since we always
+	 * want to know the effective va anyway. */
+
+	va += index << way_info->pgsz_log2;
+
+	printk ("\t[%d,%d] (%c) vpn 0x%.8x  ppn 0x%.8x  asid 0x%.2x  am 0x%x\n",
+		way, index, valid_chr, va, pa, asid, ca);
+}
+
+void print_itlb_entry (struct way_config_t *way_info, int way, int index)
+{
+	print_entry (way_info, way, index,
+		     read_itlb_virtual (way + (index << way_info->pgsz_log2)),
+		     read_itlb_translation (way + (index << way_info->pgsz_log2)));
+}
+
+void print_dtlb_entry (struct way_config_t *way_info, int way, int index)
+{
+	print_entry (way_info, way, index,
+		     read_dtlb_virtual (way + (index << way_info->pgsz_log2)),
+		     read_dtlb_translation (way + (index << way_info->pgsz_log2)));
+}
+
+void dump_itlb (void)
+{
+	int way, index;
+
+	printk ("\nITLB: ways = %d\n", XCHAL_ITLB_WAYS);
+
+	for (way = 0; way < XCHAL_ITLB_WAYS; way++) {
+		printk ("\nWay: %d, Entries: %d, MinPageSize: %d, Type: %s\n",
+			way, itlb[way].indicies,
+			itlb[way].pgsz_log2, way_type(itlb[way].arf));
+		for (index = 0; index < itlb[way].indicies; index++) {
+			print_itlb_entry(&itlb[way], way, index);
+		}
+	}
+}
+
+void dump_dtlb (void)
+{
+	int way, index;
+
+	printk ("\nDTLB: ways = %d\n", XCHAL_DTLB_WAYS);
+
+	for (way = 0; way < XCHAL_DTLB_WAYS; way++) {
+		printk ("\nWay: %d, Entries: %d, MinPageSize: %d, Type: %s\n",
+			way, dtlb[way].indicies,
+			dtlb[way].pgsz_log2, way_type(dtlb[way].arf));
+		for (index = 0; index < dtlb[way].indicies; index++) {
+			print_dtlb_entry(&dtlb[way], way, index);
+		}
+	}
+}
+
+void dump_tlb (tlb_dump_entry_t *tinfo, struct way_config_t *config,
+		int entries, int ways, int type, int show_invalid)
+{
+    tlb_dump_entry_t *e = tinfo;
+    int way, i;
+
+    /*  Gather all info:  */
+    for (way = 0; way < ways; way++) {
+	struct way_config_t *cfg = config + way;
+	for (i = 0; i < cfg->indicies; i++) {
+	    unsigned wayindex = way + (i << cfg->pgsz_log2);
+	    unsigned vv = (type ? read_dtlb_virtual (wayindex)
+		    		: read_itlb_virtual (wayindex));
+	    unsigned pp = (type ? read_dtlb_translation (wayindex)
+		    		: read_itlb_translation (wayindex));
+
+	    /* Compute and incorporate the effect of the index bits on the
+	     * va.  It's more useful for kernel debugging, since we always
+	     * want to know the effective va anyway. */
+
+	    e->va = (vv & ~((1 << (cfg->pgsz_log2 + cfg->indicies_log2)) - 1));
+	    e->va += (i << cfg->pgsz_log2);
+	    e->pa = (pp & ~((1 << cfg->pgsz_log2) - 1));
+	    e->asid = (vv & ((1 << XCHAL_MMU_ASID_BITS) - 1));
+	    e->ca = (pp & ((1 << XCHAL_MMU_CA_BITS) - 1));
+	    e->way = way;
+	    e->index = i;
+	    e->pgsz_log2 = cfg->pgsz_log2;
+	    e->type = type;
+	    e++;
+	}
+    }
+#if 1
+    /*  Sort by ASID and VADDR:  */
+    sort_tlb_dump_info (tinfo, entries);
+#endif
+
+    /*  Display all sorted info:  */
+    printk ("\n%cTLB dump:\n", (type ? 'D' : 'I'));
+    for (e = tinfo, i = 0; i < entries; i++, e++) {
+#if 0
+	if (e->asid == 0 && !show_invalid)
+	    continue;
+#endif
+	printk ("%c way=%d i=%d  ASID=%02X V=%08X -> P=%08X CA=%X (%d %cB)\n",
+		(e->type ? 'D' : 'I'), e->way, e->index,
+		e->asid, e->va, e->pa, e->ca,
+		(1 << (e->pgsz_log2 % 10)),
+		" kMG"[e->pgsz_log2 / 10]
+		);
+    }
+}
+
+void dump_tlbs2 (int showinv)
+{
+    dump_tlb (itlb_dump_info, itlb, ITLB_TOTAL_ENTRIES, XCHAL_ITLB_WAYS, 0, showinv);
+    dump_tlb (dtlb_dump_info, dtlb, DTLB_TOTAL_ENTRIES, XCHAL_DTLB_WAYS, 1, showinv);
+}
+
+void dump_all_tlbs (void)
+{
+    dump_tlbs2 (1);
+}
+
+void dump_valid_tlbs (void)
+{
+    dump_tlbs2 (0);
+}
+
+
+void dump_tlbs (void)
+{
+	dump_itlb();
+	dump_dtlb();
+}
+
+void dump_cache_tag(int dcache, int idx)
+{
+	int w, i, s, e;
+	unsigned long tag, index;
+	unsigned long num_lines, num_ways, cache_size, line_size;
+
+	num_ways = dcache ? XCHAL_DCACHE_WAYS : XCHAL_ICACHE_WAYS;
+	cache_size = dcache ? XCHAL_DCACHE_SIZE : XCHAL_ICACHE_SIZE;
+	line_size = dcache ? XCHAL_DCACHE_LINESIZE : XCHAL_ICACHE_LINESIZE;
+
+	num_lines = cache_size / num_ways;
+
+	s = 0; e = num_lines;
+
+	if (idx >= 0)
+		e = (s = idx * line_size) + 1;
+
+	for (i = s; i < e; i+= line_size) {
+		printk("\nline %#08x:", i);
+		for (w = 0; w < num_ways; w++) {
+			index = w * num_lines + i;
+			if (dcache)
+				__asm__ __volatile__("ldct %0, %1\n\t"
+						: "=a"(tag) : "a"(index));
+			else
+				__asm__ __volatile__("lict %0, %1\n\t"
+						: "=a"(tag) : "a"(index));
+
+			printk(" %#010lx", tag);
+		}
+	}
+	printk ("\n");
+}
+
+void dump_icache(int index)
+{
+	unsigned long data, addr;
+	int w, i;
+
+	const unsigned long num_ways = XCHAL_ICACHE_WAYS;
+	const unsigned long cache_size = XCHAL_ICACHE_SIZE;
+	const unsigned long line_size = XCHAL_ICACHE_LINESIZE;
+	const unsigned long num_lines = cache_size / num_ways / line_size;
+
+	for (w = 0; w < num_ways; w++) {
+		printk ("\nWay %d", w);
+
+		for (i = 0; i < line_size; i+= 4) {
+			addr = w * num_lines + index * line_size + i;
+			__asm__ __volatile__("licw %0, %1\n\t"
+					: "=a"(data) : "a"(addr));
+			printk(" %#010lx", data);
+		}
+	}
+	printk ("\n");
+}
+
+void dump_cache_tags(void)
+{
+	printk("Instruction cache\n");
+	dump_cache_tag(0, -1);
+	printk("Data cache\n");
+	dump_cache_tag(1, -1);
+}
+
+#endif
diff --git a/arch/xtensa/platform-iss/Makefile b/arch/xtensa/platform-iss/Makefile
new file mode 100644
index 0000000..5b394e9
--- /dev/null
+++ b/arch/xtensa/platform-iss/Makefile
@@ -0,0 +1,13 @@
+# $Id: Makefile,v 1.1.1.1 2002/08/28 16:10:14 aroll Exp $
+#
+# Makefile for the Xtensa Instruction Set Simulator (ISS)
+# "prom monitor" library routines under Linux.
+#
+# 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).
+#
+# Note 2! The CFLAGS definitions are in the main makefile...
+
+obj-y			= io.o console.o setup.o network.o
+
diff --git a/arch/xtensa/platform-iss/console.c b/arch/xtensa/platform-iss/console.c
new file mode 100644
index 0000000..4fbddf9
--- /dev/null
+++ b/arch/xtensa/platform-iss/console.c
@@ -0,0 +1,300 @@
+/*
+ * arch/xtensa/platform-iss/console.c
+ *
+ * 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) 2001-2005 Tensilica Inc.
+ *   Authors	Christian Zankel, Joe Taylor
+ */
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/major.h>
+#include <linux/param.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/console.h>
+
+#include <asm/uaccess.h>
+#include <asm/irq.h>
+
+#include <xtensa/simcall.h>
+
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+
+#ifdef SERIAL_INLINE
+#define _INLINE_ inline
+#endif
+
+#define SERIAL_MAX_NUM_LINES 1
+#define SERIAL_TIMER_VALUE (20 * HZ)
+
+static struct tty_driver *serial_driver;
+static struct timer_list serial_timer;
+
+static DEFINE_SPINLOCK(timer_lock);
+
+int errno;
+
+static int __simc (int a, int b, int c, int d, int e, int f)
+{
+	int ret;
+	__asm__ __volatile__ ("simcall\n"
+			"mov %0, a2\n"
+			"mov %1, a3\n" : "=a" (ret), "=a" (errno)
+			: : "a2", "a3");
+	return ret;
+}
+
+static char *serial_version = "0.1";
+static char *serial_name = "ISS serial driver";
+
+/*
+ * 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 void rs_poll(unsigned long);
+
+static int rs_open(struct tty_struct *tty, struct file * filp)
+{
+	int line = tty->index;
+
+	if ((line < 0) || (line >= SERIAL_MAX_NUM_LINES))
+		return -ENODEV;
+
+	spin_lock(&timer_lock);
+
+	if (tty->count == 1) {
+		init_timer(&serial_timer);
+		serial_timer.data = (unsigned long) tty;
+		serial_timer.function = rs_poll;
+		mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
+	}
+	spin_unlock(&timer_lock);
+
+	return 0;
+}
+
+
+/*
+ * ------------------------------------------------------------
+ * iss_serial_close()
+ *
+ * This routine is called when the serial port gets closed.  First, we
+ * wait for the last remaining data to be sent.  Then, we unlink its
+ * async structure from the interrupt chain if necessary, and we free
+ * that IRQ if nothing is left in the chain.
+ * ------------------------------------------------------------
+ */
+static void rs_close(struct tty_struct *tty, struct file * filp)
+{
+	spin_lock(&timer_lock);
+	if (tty->count == 1)
+		del_timer_sync(&serial_timer);
+	spin_unlock(&timer_lock);
+}
+
+
+static int rs_write(struct tty_struct * tty,
+		    const unsigned char *buf, int count)
+{
+	/* see drivers/char/serialX.c to reference original version */
+
+	__simc (SYS_write, 1, (unsigned long)buf, count, 0, 0);
+	return count;
+}
+
+static void rs_poll(unsigned long priv)
+{
+	struct tty_struct* tty = (struct tty_struct*) priv;
+
+	struct timeval tv = { .tv_sec = 0, .tv_usec = 0 };
+	int i = 0;
+	unsigned char c;
+
+	spin_lock(&timer_lock);
+
+	while (__simc(SYS_select_one, 0, XTISS_SELECT_ONE_READ, (int)&tv,0,0)){
+		__simc (SYS_read, 0, (unsigned long)&c, 1, 0, 0);
+		tty->flip.count++;
+		*tty->flip.char_buf_ptr++ = c;
+		*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
+		i++;
+	}
+
+	if (i)
+		tty_flip_buffer_push(tty);
+
+
+	mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
+	spin_unlock(&timer_lock);
+}
+
+
+static void rs_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	char buf[2];
+
+	if (!tty)
+		return;
+
+	buf[0] = ch;
+	buf[1] = '\0';		/* Is this NULL necessary? */
+	__simc (SYS_write, 1, (unsigned long) buf, 1, 0, 0);
+}
+
+static void rs_flush_chars(struct tty_struct *tty)
+{
+}
+
+static int rs_write_room(struct tty_struct *tty)
+{
+	/* Let's say iss can always accept 2K characters.. */
+	return 2 * 1024;
+}
+
+static int rs_chars_in_buffer(struct tty_struct *tty)
+{
+	/* the iss doesn't buffer characters */
+	return 0;
+}
+
+static void rs_hangup(struct tty_struct *tty)
+{
+	/* Stub, once again.. */
+}
+
+static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	/* Stub, once again.. */
+}
+
+static int rs_read_proc(char *page, char **start, off_t off, int count,
+			int *eof, void *data)
+{
+	int len = 0;
+	off_t begin = 0;
+
+	len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);
+	*eof = 1;
+
+	if (off >= len + begin)
+		return 0;
+
+	*start = page + (off - begin);
+	return ((count < begin + len - off) ? count : begin + len - off);
+}
+
+
+static struct tty_operations serial_ops = {
+	.open = rs_open,
+	.close = rs_close,
+	.write = rs_write,
+	.put_char = rs_put_char,
+	.flush_chars = rs_flush_chars,
+	.write_room = rs_write_room,
+	.chars_in_buffer = rs_chars_in_buffer,
+	.hangup = rs_hangup,
+	.wait_until_sent = rs_wait_until_sent,
+	.read_proc = rs_read_proc
+};
+
+int __init rs_init(void)
+{
+	serial_driver = alloc_tty_driver(1);
+
+	printk ("%s %s\n", serial_name, serial_version);
+
+	/* Initialize the tty_driver structure */
+
+	serial_driver->owner = THIS_MODULE;
+	serial_driver->driver_name = "iss_serial";
+	serial_driver->name = "ttyS";
+	serial_driver->major = TTY_MAJOR;
+	serial_driver->minor_start = 64;
+	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver->subtype = SERIAL_TYPE_NORMAL;
+	serial_driver->init_termios = tty_std_termios;
+	serial_driver->init_termios.c_cflag =
+		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+	serial_driver->flags = TTY_DRIVER_REAL_RAW;
+
+	tty_set_operations(serial_driver, &serial_ops);
+
+	if (tty_register_driver(serial_driver))
+		panic("Couldn't register serial driver\n");
+	return 0;
+}
+
+
+static __exit void rs_exit(void)
+{
+	int error;
+
+	if ((error = tty_unregister_driver(serial_driver)))
+		printk("ISS_SERIAL: failed to unregister serial driver (%d)\n",
+		       error);
+	put_tty_driver(serial_driver);
+}
+
+
+/* We use `late_initcall' instead of just `__initcall' as a workaround for
+ * the fact that (1) simcons_tty_init can't be called before tty_init,
+ * (2) tty_init is called via `module_init', (3) if statically linked,
+ * module_init == device_init, and (4) there's no ordering of init lists.
+ * We can do this easily because simcons is always statically linked, but
+ * other tty drivers that depend on tty_init and which must use
+ * `module_init' to declare their init routines are likely to be broken.
+ */
+
+late_initcall(rs_init);
+
+
+#ifdef CONFIG_SERIAL_CONSOLE
+
+static void iss_console_write(struct console *co, const char *s, unsigned count)
+{
+	int len = strlen(s);
+
+	if (s != 0 && *s != 0)
+		__simc (SYS_write, 1, (unsigned long)s,
+			count < len ? count : len,0,0);
+}
+
+static struct tty_driver* iss_console_device(struct console *c, int *index)
+{
+	*index = c->index;
+	return serial_driver;
+}
+
+
+static struct console sercons = {
+	.name = "ttyS",
+	.write = iss_console_write,
+	.device = iss_console_device,
+	.flags = CON_PRINTBUFFER,
+	.index = -1
+};
+
+static int __init iss_console_init(void)
+{
+	register_console(&sercons);
+	return 0;
+}
+
+console_initcall(iss_console_init);
+
+#endif /* CONFIG_SERIAL_CONSOLE */
+
diff --git a/arch/xtensa/platform-iss/io.c b/arch/xtensa/platform-iss/io.c
new file mode 100644
index 0000000..5b161a5
--- /dev/null
+++ b/arch/xtensa/platform-iss/io.c
@@ -0,0 +1,32 @@
+/* This file isn't really needed right now. */
+
+#if 0
+
+#include <asm/io.h>
+#include <xtensa/simcall.h>
+
+extern int __simc ();
+
+
+char iss_serial_getc()
+{
+  char c;
+  __simc( SYS_read, 0, &c, 1 );
+  return c;
+}
+
+void iss_serial_putc( char c )
+{
+  __simc( SYS_write, 1, &c, 1 );
+}
+
+void iss_serial_puts( char *s )
+{
+  if( s != 0 && *s != 0 )
+    __simc( SYS_write, 1, s, strlen(s) );
+}
+
+/*#error Need I/O ports to specific hardware!*/
+
+#endif
+
diff --git a/arch/xtensa/platform-iss/network.c b/arch/xtensa/platform-iss/network.c
new file mode 100644
index 0000000..498d7dc
--- /dev/null
+++ b/arch/xtensa/platform-iss/network.c
@@ -0,0 +1,855 @@
+/*
+ *
+ * arch/xtensa/platform-iss/network.c
+ *
+ * Platform specific initialization.
+ *
+ * Authors: Chris Zankel <chris@zankel.net>
+ * Based on work form the UML team.
+ *
+ * Copyright 2005 Tensilica 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/list.h>
+#include <linux/irq.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/if_ether.h>
+#include <linux/inetdevice.h>
+#include <linux/init.h>
+#include <linux/if_tun.h>
+#include <linux/etherdevice.h>
+#include <linux/interrupt.h>
+#include <linux/ioctl.h>
+#include <linux/bootmem.h>
+#include <linux/ethtool.h>
+#include <linux/rtnetlink.h>
+#include <linux/timer.h>
+
+#include <xtensa/simcall.h>
+
+#define DRIVER_NAME "iss-netdev"
+#define ETH_MAX_PACKET 1500
+#define ETH_HEADER_OTHER 14
+#define ISS_NET_TIMER_VALUE (2 * HZ)
+
+
+static DEFINE_SPINLOCK(opened_lock);
+static LIST_HEAD(opened);
+
+static DEFINE_SPINLOCK(devices_lock);
+static LIST_HEAD(devices);
+
+/* ------------------------------------------------------------------------- */
+
+/* We currently only support the TUNTAP transport protocol. */
+
+#define TRANSPORT_TUNTAP_NAME "tuntap"
+#define TRANSPORT_TUNTAP_MTU ETH_MAX_PACKET
+
+struct tuntap_info {
+	char dev_name[IFNAMSIZ];
+	int fixed_config;
+	unsigned char gw[ETH_ALEN];
+	int fd;
+};
+
+/* ------------------------------------------------------------------------- */
+
+
+/* This structure contains out private information for the driver. */
+
+struct iss_net_private {
+
+	struct list_head device_list;
+	struct list_head opened_list;
+
+	spinlock_t lock;
+	struct net_device *dev;
+	struct platform_device pdev;
+	struct timer_list tl;
+	struct net_device_stats stats;
+
+	struct timer_list timer;
+	unsigned int timer_val;
+
+	int index;
+	int mtu;
+
+	unsigned char mac[ETH_ALEN];
+	int have_mac;
+
+	struct {
+		union {
+			struct tuntap_info tuntap;
+		} info;
+
+		int (*open)(struct iss_net_private *lp);
+		void (*close)(struct iss_net_private *lp);
+		int (*read)(struct iss_net_private *lp, struct sk_buff **skb);
+		int (*write)(struct iss_net_private *lp, struct sk_buff **skb);
+		unsigned short (*protocol)(struct sk_buff *skb);
+		int (*poll)(struct iss_net_private *lp);
+	} tp;
+
+};
+
+/* ======================= ISS SIMCALL INTERFACE =========================== */
+
+/* Note: __simc must _not_ be declared inline! */
+
+static int errno;
+
+static int __simc (int a, int b, int c, int d, int e, int f)
+{
+	int ret;
+	__asm__ __volatile__ ("simcall\n"
+	    		      "mov %0, a2\n"
+			      "mov %1, a3\n" : "=a" (ret), "=a" (errno)
+			      : : "a2", "a3");
+	return ret;
+}
+
+static int inline simc_open(char *file, int flags, int mode)
+{
+	return __simc(SYS_open, (int) file, flags, mode, 0, 0);
+}
+
+static int inline simc_close(int fd)
+{
+	return __simc(SYS_close, fd, 0, 0, 0, 0);
+}
+
+static int inline simc_ioctl(int fd, int request, void *arg)
+{
+	return __simc(SYS_ioctl, fd, request, (int) arg, 0, 0);
+}
+
+static int inline simc_read(int fd, void *buf, size_t count)
+{
+	return __simc(SYS_read, fd, (int) buf, count, 0, 0);
+}
+
+static int inline simc_write(int fd, void *buf, size_t count)
+{
+	return __simc(SYS_write, fd, (int) buf, count, 0, 0);
+}
+
+static int inline simc_poll(int fd)
+{
+	struct timeval tv = { .tv_sec = 0, .tv_usec = 0 };
+
+	return __simc(SYS_select_one, fd, XTISS_SELECT_ONE_READ, (int)&tv,0,0);
+}
+
+/* ================================ HELPERS ================================ */
+
+
+static char *split_if_spec(char *str, ...)
+{
+	char **arg, *end;
+	va_list ap;
+
+	va_start(ap, str);
+	while ((arg = va_arg(ap, char**)) != NULL) {
+		if (*str == '\0')
+			return NULL;
+		end = strchr(str, ',');
+		if (end != str)
+			*arg = str;
+		if (end == NULL)
+			return NULL;
+		*end ++ = '\0';
+		str = end;
+	}
+	va_end(ap);
+	return str;
+}
+
+
+#if 0
+/* Adjust SKB. */
+
+struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra)
+{
+	if ((skb != NULL) && (skb_tailroom(skb) < extra)) {
+		struct sk_buff *skb2;
+
+		skb2 = skb_copy_expand(skb, 0, extra, GFP_ATOMIC);
+		dev_kfree_skb(skb);
+		skb = skb2;
+	}
+	if (skb != NULL)
+		skb_put(skb, extra);
+
+	return skb;
+}
+#endif
+
+/* Return the IP address as a string for a given device. */
+
+static void dev_ip_addr(void *d, char *buf, char *bin_buf)
+{
+	struct net_device *dev = d;
+	struct in_device *ip = dev->ip_ptr;
+	struct in_ifaddr *in;
+	u32 addr;
+
+	if ((ip == NULL) || ((in = ip->ifa_list) == NULL)) {
+		printk(KERN_WARNING "Device not assigned an IP address!\n");
+		return;
+	}
+
+	addr = in->ifa_address;
+	sprintf(buf, "%d.%d.%d.%d", addr & 0xff, (addr >> 8) & 0xff,
+		(addr >> 16) & 0xff, addr >> 24);
+
+	if (bin_buf) {
+		bin_buf[0] = addr & 0xff;
+		bin_buf[1] = (addr >> 8) & 0xff;
+		bin_buf[2] = (addr >> 16) & 0xff;
+		bin_buf[3] = addr >> 24;
+	}
+}
+
+/* Set Ethernet address of the specified device. */
+
+static void inline set_ether_mac(void *d, unsigned char *addr)
+{
+	struct net_device *dev = d;
+	memcpy(dev->dev_addr, addr, ETH_ALEN);
+}
+
+
+/* ======================= TUNTAP TRANSPORT INTERFACE ====================== */
+
+static int tuntap_open(struct iss_net_private *lp)
+{
+	struct ifreq ifr;
+	char *dev_name = lp->tp.info.tuntap.dev_name;
+	int err = -EINVAL;
+	int fd;
+
+	/* We currently only support a fixed configuration. */
+
+	if (!lp->tp.info.tuntap.fixed_config)
+		return -EINVAL;
+
+	if ((fd = simc_open("/dev/net/tun", 02, 0)) < 0) {	/* O_RDWR */
+		printk("Failed to open /dev/net/tun, returned %d "
+		       "(errno = %d)\n", fd, errno);
+		return fd;
+	}
+
+	memset(&ifr, 0, sizeof ifr);
+	ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+	strlcpy(ifr.ifr_name, dev_name, sizeof ifr.ifr_name - 1);
+
+	if ((err = simc_ioctl(fd, TUNSETIFF, (void*) &ifr)) < 0) {
+		printk("Failed to set interface, returned %d "
+		       "(errno = %d)\n", err, errno);
+		simc_close(fd);
+		return err;
+	}
+
+	lp->tp.info.tuntap.fd = fd;
+	return err;
+}
+
+static void tuntap_close(struct iss_net_private *lp)
+{
+#if 0
+	if (lp->tp.info.tuntap.fixed_config)
+		iter_addresses(lp->tp.info.tuntap.dev, close_addr, lp->host.dev_name);
+#endif
+	simc_close(lp->tp.info.tuntap.fd);
+	lp->tp.info.tuntap.fd = -1;
+}
+
+static int tuntap_read (struct iss_net_private *lp, struct sk_buff **skb)
+{
+#if 0
+	*skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER);
+	if (*skb == NULL)
+		return -ENOMEM;
+#endif
+
+	return simc_read(lp->tp.info.tuntap.fd,
+			(*skb)->data, (*skb)->dev->mtu + ETH_HEADER_OTHER);
+}
+
+static int tuntap_write (struct iss_net_private *lp, struct sk_buff **skb)
+{
+	return simc_write(lp->tp.info.tuntap.fd, (*skb)->data, (*skb)->len);
+}
+
+unsigned short tuntap_protocol(struct sk_buff *skb)
+{
+	return eth_type_trans(skb, skb->dev);
+}
+
+static int tuntap_poll(struct iss_net_private *lp)
+{
+	return simc_poll(lp->tp.info.tuntap.fd);
+}
+
+/*
+ * Currently only a device name is supported.
+ * ethX=tuntap[,[mac address][,[device name]]]
+ */
+
+static int tuntap_probe(struct iss_net_private *lp, int index, char *init)
+{
+	const int len = strlen(TRANSPORT_TUNTAP_NAME);
+	char *dev_name = NULL, *mac_str = NULL, *rem = NULL;
+
+	/* Transport should be 'tuntap': ethX=tuntap,mac,dev_name */
+
+	if (strncmp(init, TRANSPORT_TUNTAP_NAME, len))
+		return 0;
+
+	if (*(init += strlen(TRANSPORT_TUNTAP_NAME)) == ',') {
+		if ((rem=split_if_spec(init+1, &mac_str, &dev_name)) != NULL) {
+			printk("Extra garbage on specification : '%s'\n", rem);
+			return 0;
+		}
+	} else if (*init != '\0') {
+		printk("Invalid argument: %s. Skipping device!\n", init);
+		return 0;
+	}
+
+	if (dev_name) {
+		strncpy(lp->tp.info.tuntap.dev_name, dev_name,
+			 sizeof lp->tp.info.tuntap.dev_name);
+		lp->tp.info.tuntap.fixed_config = 1;
+	} else
+		strcpy(lp->tp.info.tuntap.dev_name, TRANSPORT_TUNTAP_NAME);
+
+
+#if 0
+	if (setup_etheraddr(mac_str, lp->mac))
+		lp->have_mac = 1;
+#endif
+	lp->mtu = TRANSPORT_TUNTAP_MTU;
+
+	//lp->info.tuntap.gate_addr = gate_addr;
+
+	lp->tp.info.tuntap.fd = -1;
+
+	lp->tp.open = tuntap_open;
+	lp->tp.close = tuntap_close;
+	lp->tp.read = tuntap_read;
+	lp->tp.write = tuntap_write;
+	lp->tp.protocol = tuntap_protocol;
+	lp->tp.poll = tuntap_poll;
+
+	printk("TUN/TAP backend - ");
+#if 0
+	if (lp->host.gate_addr != NULL)
+		printk("IP = %s", lp->host.gate_addr);
+#endif
+	printk("\n");
+
+	return 1;
+}
+
+/* ================================ ISS NET ================================ */
+
+static int iss_net_rx(struct net_device *dev)
+{
+	struct iss_net_private *lp = dev->priv;
+	int pkt_len;
+	struct sk_buff *skb;
+
+	/* Check if there is any new data. */
+
+	if (lp->tp.poll(lp) == 0)
+		return 0;
+
+	/* Try to allocate memory, if it fails, try again next round. */
+
+	if ((skb = dev_alloc_skb(dev->mtu + 2 + ETH_HEADER_OTHER)) == NULL) {
+		lp->stats.rx_dropped++;
+		return 0;
+	}
+
+	skb_reserve(skb, 2);
+
+	/* Setup skb */
+
+	skb->dev = dev;
+	skb->mac.raw = skb->data;
+	pkt_len = lp->tp.read(lp, &skb);
+	skb_put(skb, pkt_len);
+
+	if (pkt_len > 0) {
+		skb_trim(skb, pkt_len);
+		skb->protocol = lp->tp.protocol(skb);
+	//	netif_rx(skb);
+		netif_rx_ni(skb);
+
+		lp->stats.rx_bytes += skb->len;
+		lp->stats.rx_packets++;
+		return pkt_len;
+	}
+	kfree_skb(skb);
+	return pkt_len;
+}
+
+static int iss_net_poll(void)
+{
+	struct list_head *ele;
+	int err, ret = 0;
+
+	spin_lock(&opened_lock);
+
+	list_for_each(ele, &opened) {
+		struct iss_net_private *lp;
+
+		lp = list_entry(ele, struct iss_net_private, opened_list);
+
+		if (!netif_running(lp->dev))
+			break;
+
+		spin_lock(&lp->lock);
+
+		while ((err = iss_net_rx(lp->dev)) > 0)
+			ret++;
+
+		spin_unlock(&lp->lock);
+
+		if (err < 0) {
+			printk(KERN_ERR "Device '%s' read returned %d, "
+			       "shutting it down\n", lp->dev->name, err);
+			dev_close(lp->dev);
+		} else {
+			// FIXME reactivate_fd(lp->fd, ISS_ETH_IRQ);
+		}
+	}
+
+	spin_unlock(&opened_lock);
+	return ret;
+}
+
+
+static void iss_net_timer(unsigned long priv)
+{
+	struct iss_net_private* lp = (struct iss_net_private*) priv;
+
+	spin_lock(&lp->lock);
+
+	iss_net_poll();
+
+	mod_timer(&lp->timer, jiffies + lp->timer_val);
+
+	spin_unlock(&lp->lock);
+}
+
+
+static int iss_net_open(struct net_device *dev)
+{
+	struct iss_net_private *lp = dev->priv;
+	char addr[sizeof "255.255.255.255\0"];
+	int err;
+
+	spin_lock(&lp->lock);
+
+	if ((err = lp->tp.open(lp)) < 0)
+		goto out;
+
+	if (!lp->have_mac) {
+		dev_ip_addr(dev, addr, &lp->mac[2]);
+		set_ether_mac(dev, lp->mac);
+	}
+
+	netif_start_queue(dev);
+
+	/* clear buffer - it can happen that the host side of the interface
+	 * is full when we gethere. In this case, new data is never queued,
+	 * SIGIOs never arrive, and the net never works.
+	 */
+	while ((err = iss_net_rx(dev)) > 0)
+		;
+
+	spin_lock(&opened_lock);
+	list_add(&lp->opened_list, &opened);
+	spin_unlock(&opened_lock);
+
+	init_timer(&lp->timer);
+	lp->timer_val = ISS_NET_TIMER_VALUE;
+	lp->timer.data = (unsigned long) lp;
+	lp->timer.function = iss_net_timer;
+	mod_timer(&lp->timer, jiffies + lp->timer_val);
+
+out:
+	spin_unlock(&lp->lock);
+	return err;
+}
+
+static int iss_net_close(struct net_device *dev)
+{
+	struct iss_net_private *lp = dev->priv;
+printk("iss_net_close!\n");
+	netif_stop_queue(dev);
+	spin_lock(&lp->lock);
+
+	spin_lock(&opened_lock);
+	list_del(&opened);
+	spin_unlock(&opened_lock);
+
+	del_timer_sync(&lp->timer);
+
+	lp->tp.close(lp);
+
+	spin_unlock(&lp->lock);
+	return 0;
+}
+
+static int iss_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct iss_net_private *lp = dev->priv;
+	unsigned long flags;
+	int len;
+
+	netif_stop_queue(dev);
+	spin_lock_irqsave(&lp->lock, flags);
+
+	len = lp->tp.write(lp, &skb);
+
+	if (len == skb->len) {
+		lp->stats.tx_packets++;
+		lp->stats.tx_bytes += skb->len;
+		dev->trans_start = jiffies;
+		netif_start_queue(dev);
+
+		/* this is normally done in the interrupt when tx finishes */
+		netif_wake_queue(dev);
+
+	} else if (len == 0) {
+		netif_start_queue(dev);
+		lp->stats.tx_dropped++;
+
+	} else {
+		netif_start_queue(dev);
+		printk(KERN_ERR "iss_net_start_xmit: failed(%d)\n", len);
+	}
+
+	spin_unlock_irqrestore(&lp->lock, flags);
+
+	dev_kfree_skb(skb);
+	return 0;
+}
+
+
+static struct net_device_stats *iss_net_get_stats(struct net_device *dev)
+{
+	struct iss_net_private *lp = dev->priv;
+	return &lp->stats;
+}
+
+static void iss_net_set_multicast_list(struct net_device *dev)
+{
+#if 0
+	if (dev->flags & IFF_PROMISC)
+		return;
+	else if (dev->mc_count)
+		dev->flags |= IFF_ALLMULTI;
+	else
+		dev->flags &= ~IFF_ALLMULTI;
+#endif
+}
+
+static void iss_net_tx_timeout(struct net_device *dev)
+{
+#if 0
+	dev->trans_start = jiffies;
+	netif_wake_queue(dev);
+#endif
+}
+
+static int iss_net_set_mac(struct net_device *dev, void *addr)
+{
+#if 0
+	struct iss_net_private *lp = dev->priv;
+	struct sockaddr *hwaddr = addr;
+
+	spin_lock(&lp->lock);
+	memcpy(dev->dev_addr, hwaddr->sa_data, ETH_ALEN);
+	spin_unlock(&lp->lock);
+#endif
+
+	return 0;
+}
+
+static int iss_net_change_mtu(struct net_device *dev, int new_mtu)
+{
+#if 0
+	struct iss_net_private *lp = dev->priv;
+	int err = 0;
+
+	spin_lock(&lp->lock);
+
+	// FIXME not needed new_mtu = transport_set_mtu(new_mtu, &lp->user);
+
+	if (new_mtu < 0)
+		err = new_mtu;
+	else
+		dev->mtu = new_mtu;
+
+	spin_unlock(&lp->lock);
+	return err;
+#endif
+	return -EINVAL;
+}
+
+static int iss_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+#if 0
+	static const struct ethtool_drvinfo info = {
+		.cmd     = ETHTOOL_GDRVINFO,
+		.driver  = DRIVER_NAME,
+		.version = "42",
+	};
+	void *useraddr;
+	u32 ethcmd;
+
+	switch (cmd) {
+	case SIOCETHTOOL:
+		useraddr = ifr->ifr_data;
+		if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
+			return -EFAULT;
+
+		switch (ethcmd) {
+			case ETHTOOL_GDRVINFO:
+				if (copy_to_user(useraddr, &info, sizeof(info)))
+					return -EFAULT;
+				return 0;
+			default:
+				return -EOPNOTSUPP;
+		}
+	default:
+		return -EINVAL;
+	}
+#endif
+	return -EINVAL;
+}
+
+void iss_net_user_timer_expire(unsigned long _conn)
+{
+}
+
+
+static struct device_driver iss_net_driver = {
+	.name  = DRIVER_NAME,
+	.bus   = &platform_bus_type,
+};
+
+static int driver_registered;
+
+static int iss_net_configure(int index, char *init)
+{
+	struct net_device *dev;
+	struct iss_net_private *lp;
+	int err;
+
+	if ((dev = alloc_etherdev(sizeof *lp)) == NULL) {
+		printk(KERN_ERR "eth_configure: failed to allocate device\n");
+		return 1;
+	}
+
+	/* Initialize private element. */
+
+	lp = dev->priv;
+	*lp = ((struct iss_net_private) {
+		.device_list		= LIST_HEAD_INIT(lp->device_list),
+		.opened_list		= LIST_HEAD_INIT(lp->opened_list),
+		.lock			= SPIN_LOCK_UNLOCKED,
+		.dev			= dev,
+		.index			= index,
+		//.fd                   = -1,
+		.mac			= { 0xfe, 0xfd, 0x0, 0x0, 0x0, 0x0 },
+		.have_mac		= 0,
+		});
+
+	/*
+	 * Try all transport protocols.
+	 * Note: more protocols can be added by adding '&& !X_init(lp, eth)'.
+	 */
+
+	if (!tuntap_probe(lp, index, init)) {
+		printk("Invalid arguments. Skipping device!\n");
+		goto errout;
+	}
+
+	printk(KERN_INFO "Netdevice %d ", index);
+	if (lp->have_mac)
+		printk("(%02x:%02x:%02x:%02x:%02x:%02x) ",
+				lp->mac[0], lp->mac[1],
+				lp->mac[2], lp->mac[3],
+				lp->mac[4], lp->mac[5]);
+	printk(": ");
+
+	/* sysfs register */
+
+	if (!driver_registered) {
+		driver_register(&iss_net_driver);
+		driver_registered = 1;
+	}
+
+	spin_lock(&devices_lock);
+	list_add(&lp->device_list, &devices);
+	spin_unlock(&devices_lock);
+
+	lp->pdev.id = index;
+	lp->pdev.name = DRIVER_NAME;
+	platform_device_register(&lp->pdev);
+	SET_NETDEV_DEV(dev,&lp->pdev.dev);
+
+	/*
+	 * If this name ends up conflicting with an existing registered
+	 * netdevice, that is OK, register_netdev{,ice}() will notice this
+	 * and fail.
+	 */
+	snprintf(dev->name, sizeof dev->name, "eth%d", index);
+
+	dev->mtu = lp->mtu;
+	dev->open = iss_net_open;
+	dev->hard_start_xmit = iss_net_start_xmit;
+	dev->stop = iss_net_close;
+	dev->get_stats = iss_net_get_stats;
+	dev->set_multicast_list = iss_net_set_multicast_list;
+	dev->tx_timeout = iss_net_tx_timeout;
+	dev->set_mac_address = iss_net_set_mac;
+	dev->change_mtu = iss_net_change_mtu;
+	dev->do_ioctl = iss_net_ioctl;
+	dev->watchdog_timeo = (HZ >> 1);
+	dev->irq = -1;
+
+	rtnl_lock();
+	err = register_netdevice(dev);
+	rtnl_unlock();
+
+	if (err) {
+		printk("Error registering net device!\n");
+		/* XXX: should we call ->remove() here? */
+		free_netdev(dev);
+		return 1;
+	}
+
+	init_timer(&lp->tl);
+	lp->tl.function = iss_net_user_timer_expire;
+
+#if 0
+	if (lp->have_mac)
+		set_ether_mac(dev, lp->mac);
+#endif
+	return 0;
+
+errout:
+	// FIXME: unregister; free, etc..
+	return -EIO;
+
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Filled in during early boot */
+
+struct list_head eth_cmd_line = LIST_HEAD_INIT(eth_cmd_line);
+
+struct iss_net_init {
+	struct list_head list;
+	char *init;		/* init string */
+	int index;
+};
+
+/*
+ * Parse the command line and look for 'ethX=...' fields, and register all
+ * those fields. They will be later initialized in iss_net_init.
+ */
+
+#define ERR KERN_ERR "iss_net_setup: "
+
+static int iss_net_setup(char *str)
+{
+	struct iss_net_private *device = NULL;
+	struct iss_net_init *new;
+	struct list_head *ele;
+	char *end;
+	int n;
+
+	n = simple_strtoul(str, &end, 0);
+	if (end == str) {
+		printk(ERR "Failed to parse '%s'\n", str);
+		return 1;
+	}
+	if (n < 0) {
+		printk(ERR "Device %d is negative\n", n);
+		return 1;
+	}
+	if (*(str = end) != '=') {
+		printk(ERR "Expected '=' after device number\n");
+		return 1;
+	}
+
+	spin_lock(&devices_lock);
+
+	list_for_each(ele, &devices) {
+		device = list_entry(ele, struct iss_net_private, device_list);
+		if (device->index == n)
+			break;
+	}
+
+	spin_unlock(&devices_lock);
+
+	if (device && device->index == n) {
+		printk(ERR "Device %d already configured\n", n);
+		return 1;
+	}
+
+	if ((new = alloc_bootmem(sizeof new)) == NULL) {
+		printk("Alloc_bootmem failed\n");
+		return 1;
+	}
+
+	INIT_LIST_HEAD(&new->list);
+	new->index = n;
+	new->init = str + 1;
+
+	list_add_tail(&new->list, &eth_cmd_line);
+	return 1;
+}
+
+#undef ERR
+
+__setup("eth", iss_net_setup);
+
+/*
+ * Initialize all ISS Ethernet devices previously registered in iss_net_setup.
+ */
+
+static int iss_net_init(void)
+{
+	struct list_head *ele, *next;
+
+	/* Walk through all Ethernet devices specified in the command line. */
+
+	list_for_each_safe(ele, next, &eth_cmd_line) {
+		struct iss_net_init *eth;
+		eth = list_entry(ele, struct iss_net_init, list);
+		iss_net_configure(eth->index, eth->init);
+	}
+
+	return 1;
+}
+
+module_init(iss_net_init);
+
diff --git a/arch/xtensa/platform-iss/setup.c b/arch/xtensa/platform-iss/setup.c
new file mode 100644
index 0000000..2e6dcbf
--- /dev/null
+++ b/arch/xtensa/platform-iss/setup.c
@@ -0,0 +1,112 @@
+/*
+ *
+ * arch/xtensa/platform-iss/setup.c
+ *
+ * Platform specific initialization.
+ *
+ * Authors: Chris Zankel <chris@zankel.net>
+ *          Joe Taylor <joe@tensilica.com>
+ *
+ * Copyright 2001 - 2005 Tensilica 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/types.h>
+#include <linux/major.h>
+#include <linux/blkdev.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/stringify.h>
+#include <linux/notifier.h>
+
+#include <asm/platform.h>
+#include <asm/bootparam.h>
+
+
+void __init platform_init(bp_tag_t* bootparam)
+{
+
+}
+
+void platform_halt(void)
+{
+	printk (" ** Called platform_halt(), looping forever! **\n");
+	while (1);
+}
+
+void platform_power_off(void)
+{
+	printk (" ** Called platform_power_off(), looping forever! **\n");
+	while (1);
+}
+void platform_restart(void)
+{
+	/* Flush and reset the mmu, simulate a processor reset, and
+	 * jump to the reset vector. */
+
+	__asm__ __volatile__("movi	a2, 15\n\t"
+			     "wsr	a2, " __stringify(ICOUNTLEVEL) "\n\t"
+			     "movi	a2, 0\n\t"
+			     "wsr	a2, " __stringify(ICOUNT) "\n\t"
+			     "wsr	a2, " __stringify(IBREAKENABLE) "\n\t"
+			     "wsr	a2, " __stringify(LCOUNT) "\n\t"
+			     "movi	a2, 0x1f\n\t"
+			     "wsr	a2, " __stringify(PS) "\n\t"
+			     "isync\n\t"
+			     "jx	%0\n\t"
+			     :
+			     : "a" (XCHAL_RESET_VECTOR_VADDR)
+			     : "a2");
+
+	/* control never gets here */
+}
+
+extern void iss_net_poll(void);
+
+const char twirl[]="|/-\\|/-\\";
+
+void platform_heartbeat(void)
+{
+#if 0
+	static int i = 0, j = 0;
+
+	if (--i < 0) {
+		i = 99;
+		printk("\r%c\r", twirl[j++]);
+		if (j == 8)
+			j = 0;
+	}
+#endif
+}
+
+
+
+static int
+iss_panic_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+	__asm__ __volatile__("movi a2, -1; simcall\n");
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block iss_panic_block = {
+	iss_panic_event,
+	NULL,
+	0
+};
+
+void __init platform_setup(char **p_cmdline)
+{
+	notifier_chain_register(&panic_notifier_list, &iss_panic_block);
+}
diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c
index 92b0352..bd7524c 100644
--- a/crypto/tcrypt.c
+++ b/crypto/tcrypt.c
@@ -1,4 +1,4 @@
-/* 
+/*
  * Quick & dirty crypto testing module.
  *
  * This will only exist until we have a better testing mechanism
@@ -9,11 +9,12 @@
  *
  * 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) 
+ * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * 14 - 09 - 2003 
- *	Rewritten by Kartikey Mahendra Bhatt
+ * 2004-08-09 Added cipher speed tests (Reyk Floeter <reyk@vantronix.net>)
+ * 2003-09-14 Rewritten by Kartikey Mahendra Bhatt
+ *
  */
 
 #include <linux/init.h>
@@ -25,12 +26,15 @@
 #include <linux/crypto.h>
 #include <linux/highmem.h>
 #include <linux/moduleparam.h>
+#include <linux/jiffies.h>
+#include <linux/timex.h>
+#include <linux/interrupt.h>
 #include "tcrypt.h"
 
 /*
  * Need to kmalloc() memory for testing kmap().
  */
-#define TVMEMSIZE	4096
+#define TVMEMSIZE	16384
 #define XBUFSIZE	32768
 
 /*
@@ -55,19 +59,23 @@
 
 static unsigned int IDX[8] = { IDX1, IDX2, IDX3, IDX4, IDX5, IDX6, IDX7, IDX8 };
 
+/*
+ * Used by test_cipher_speed()
+ */
+static unsigned int sec;
+
 static int mode;
 static char *xbuf;
 static char *tvmem;
 
 static char *check[] = {
 	"des", "md5", "des3_ede", "rot13", "sha1", "sha256", "blowfish",
-	"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6", 
-	"arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea", 
+	"twofish", "serpent", "sha384", "sha512", "md4", "aes", "cast6",
+	"arc4", "michael_mic", "deflate", "crc32c", "tea", "xtea",
 	"khazad", "wp512", "wp384", "wp256", "tnepres", NULL
 };
 
-static void
-hexdump(unsigned char *buf, unsigned int len)
+static void hexdump(unsigned char *buf, unsigned int len)
 {
 	while (len--)
 		printk("%02x", *buf++);
@@ -75,29 +83,29 @@
 	printk("\n");
 }
 
-static void 
-test_hash (char * algo, struct hash_testvec * template, unsigned int tcount)
+static void test_hash(char *algo, struct hash_testvec *template,
+		      unsigned int tcount)
 {
-	char *p; 
-        unsigned int i, j, k, temp;
-        struct scatterlist sg[8];
-        char result[64];
-        struct crypto_tfm *tfm;
-        struct hash_testvec *hash_tv;
-        unsigned int tsize;
-	 
-        printk("\ntesting %s\n", algo);
+	char *p;
+	unsigned int i, j, k, temp;
+	struct scatterlist sg[8];
+	char result[64];
+	struct crypto_tfm *tfm;
+	struct hash_testvec *hash_tv;
+	unsigned int tsize;
 
-	tsize = sizeof (struct hash_testvec);
+	printk("\ntesting %s\n", algo);
+
+	tsize = sizeof(struct hash_testvec);
 	tsize *= tcount;
-	
+
 	if (tsize > TVMEMSIZE) {
 		printk("template (%u) too big for tvmem (%u)\n", tsize, TVMEMSIZE);
 		return;
 	}
 
 	memcpy(tvmem, template, tsize);
-	hash_tv = (void *) tvmem;
+	hash_tv = (void *)tvmem;
 	tfm = crypto_alloc_tfm(algo, 0);
 	if (tfm == NULL) {
 		printk("failed to load transform for %s\n", algo);
@@ -105,70 +113,71 @@
 	}
 
 	for (i = 0; i < tcount; i++) {
-		printk ("test %u:\n", i + 1);
-		memset (result, 0, 64);
+		printk("test %u:\n", i + 1);
+		memset(result, 0, 64);
 
 		p = hash_tv[i].plaintext;
-		sg[0].page = virt_to_page (p);
-		sg[0].offset = offset_in_page (p);
+		sg[0].page = virt_to_page(p);
+		sg[0].offset = offset_in_page(p);
 		sg[0].length = hash_tv[i].psize;
 
-		crypto_digest_init (tfm);
+		crypto_digest_init(tfm);
 		if (tfm->crt_u.digest.dit_setkey) {
-			crypto_digest_setkey (tfm, hash_tv[i].key,
-					      hash_tv[i].ksize);
+			crypto_digest_setkey(tfm, hash_tv[i].key,
+					     hash_tv[i].ksize);
 		}
-		crypto_digest_update (tfm, sg, 1);
-		crypto_digest_final (tfm, result);
+		crypto_digest_update(tfm, sg, 1);
+		crypto_digest_final(tfm, result);
 
-		hexdump (result, crypto_tfm_alg_digestsize (tfm));
+		hexdump(result, crypto_tfm_alg_digestsize(tfm));
 		printk("%s\n",
-			memcmp(result, hash_tv[i].digest,
-				crypto_tfm_alg_digestsize(tfm)) ? "fail" :
-			"pass");
+		       memcmp(result, hash_tv[i].digest,
+			      crypto_tfm_alg_digestsize(tfm)) ?
+		       "fail" : "pass");
 	}
 
-	printk ("testing %s across pages\n", algo);
+	printk("testing %s across pages\n", algo);
 
 	/* setup the dummy buffer first */
-        memset(xbuf, 0, XBUFSIZE);
+	memset(xbuf, 0, XBUFSIZE);
 
 	j = 0;
 	for (i = 0; i < tcount; i++) {
 		if (hash_tv[i].np) {
 			j++;
-			printk ("test %u:\n", j);
-			memset (result, 0, 64);
+			printk("test %u:\n", j);
+			memset(result, 0, 64);
 
 			temp = 0;
 			for (k = 0; k < hash_tv[i].np; k++) {
-				memcpy (&xbuf[IDX[k]], hash_tv[i].plaintext + temp, 
-						hash_tv[i].tap[k]);	
+				memcpy(&xbuf[IDX[k]],
+				       hash_tv[i].plaintext + temp,
+				       hash_tv[i].tap[k]);
 				temp += hash_tv[i].tap[k];
 				p = &xbuf[IDX[k]];
-				sg[k].page = virt_to_page (p);
-				sg[k].offset = offset_in_page (p);
+				sg[k].page = virt_to_page(p);
+				sg[k].offset = offset_in_page(p);
 				sg[k].length = hash_tv[i].tap[k];
 			}
 
-			crypto_digest_digest (tfm, sg, hash_tv[i].np, result);
-			
-			hexdump (result, crypto_tfm_alg_digestsize (tfm));
+			crypto_digest_digest(tfm, sg, hash_tv[i].np, result);
+
+			hexdump(result, crypto_tfm_alg_digestsize(tfm));
 			printk("%s\n",
-				memcmp(result, hash_tv[i].digest,
-					crypto_tfm_alg_digestsize(tfm)) ? "fail" :
-				"pass");
+			       memcmp(result, hash_tv[i].digest,
+				      crypto_tfm_alg_digestsize(tfm)) ?
+			       "fail" : "pass");
 		}
 	}
-	
-	crypto_free_tfm (tfm);
+
+	crypto_free_tfm(tfm);
 }
 
 
 #ifdef CONFIG_CRYPTO_HMAC
 
-static void
-test_hmac(char *algo, struct hmac_testvec * template, unsigned int tcount)
+static void test_hmac(char *algo, struct hmac_testvec *template,
+		      unsigned int tcount)
 {
 	char *p;
 	unsigned int i, j, k, temp;
@@ -185,8 +194,8 @@
 	}
 
 	printk("\ntesting hmac_%s\n", algo);
-	
-	tsize = sizeof (struct hmac_testvec);
+
+	tsize = sizeof(struct hmac_testvec);
 	tsize *= tcount;
 	if (tsize > TVMEMSIZE) {
 		printk("template (%u) too big for tvmem (%u)\n", tsize,
@@ -195,7 +204,7 @@
 	}
 
 	memcpy(tvmem, template, tsize);
-	hmac_tv = (void *) tvmem;
+	hmac_tv = (void *)tvmem;
 
 	for (i = 0; i < tcount; i++) {
 		printk("test %u:\n", i + 1);
@@ -219,34 +228,35 @@
 	printk("\ntesting hmac_%s across pages\n", algo);
 
 	memset(xbuf, 0, XBUFSIZE);
-	
+
 	j = 0;
 	for (i = 0; i < tcount; i++) {
 		if (hmac_tv[i].np) {
 			j++;
-			printk ("test %u:\n",j);
-			memset (result, 0, 64);
+			printk("test %u:\n",j);
+			memset(result, 0, 64);
 
 			temp = 0;
 			klen = hmac_tv[i].ksize;
 			for (k = 0; k < hmac_tv[i].np; k++) {
-				memcpy (&xbuf[IDX[k]], hmac_tv[i].plaintext + temp, 
-						hmac_tv[i].tap[k]);	
+				memcpy(&xbuf[IDX[k]],
+				       hmac_tv[i].plaintext + temp,
+				       hmac_tv[i].tap[k]);
 				temp += hmac_tv[i].tap[k];
 				p = &xbuf[IDX[k]];
-				sg[k].page = virt_to_page (p);
-				sg[k].offset = offset_in_page (p);
+				sg[k].page = virt_to_page(p);
+				sg[k].offset = offset_in_page(p);
 				sg[k].length = hmac_tv[i].tap[k];
 			}
 
-			crypto_hmac(tfm, hmac_tv[i].key, &klen, sg, hmac_tv[i].np, 
-					result);
+			crypto_hmac(tfm, hmac_tv[i].key, &klen, sg,
+				    hmac_tv[i].np, result);
 			hexdump(result, crypto_tfm_alg_digestsize(tfm));
-			
+
 			printk("%s\n",
-				memcmp(result, hmac_tv[i].digest,
-					crypto_tfm_alg_digestsize(tfm)) ? "fail" : 
-				"pass");
+			       memcmp(result, hmac_tv[i].digest,
+				      crypto_tfm_alg_digestsize(tfm)) ?
+			       "fail" : "pass");
 		}
 	}
 out:
@@ -255,8 +265,8 @@
 
 #endif	/* CONFIG_CRYPTO_HMAC */
 
-static void
-test_cipher(char * algo, int mode, int enc, struct cipher_testvec * template, unsigned int tcount)
+static void test_cipher(char *algo, int mode, int enc,
+			struct cipher_testvec *template, unsigned int tcount)
 {
 	unsigned int ret, i, j, k, temp;
 	unsigned int tsize;
@@ -265,22 +275,22 @@
 	char *key;
 	struct cipher_testvec *cipher_tv;
 	struct scatterlist sg[8];
-	char e[11], m[4];
+	const char *e, *m;
 
 	if (enc == ENCRYPT)
-	        strncpy(e, "encryption", 11);
+	        e = "encryption";
 	else
-        	strncpy(e, "decryption", 11);
+		e = "decryption";
 	if (mode == MODE_ECB)
-        	strncpy(m, "ECB", 4);
+		m = "ECB";
 	else
-        	strncpy(m, "CBC", 4);
+		m = "CBC";
 
-	printk("\ntesting %s %s %s \n", algo, m, e);
+	printk("\ntesting %s %s %s\n", algo, m, e);
 
-	tsize = sizeof (struct cipher_testvec);	
+	tsize = sizeof (struct cipher_testvec);
 	tsize *= tcount;
-	
+
 	if (tsize > TVMEMSIZE) {
 		printk("template (%u) too big for tvmem (%u)\n", tsize,
 		       TVMEMSIZE);
@@ -288,112 +298,113 @@
 	}
 
 	memcpy(tvmem, template, tsize);
-	cipher_tv = (void *) tvmem;
+	cipher_tv = (void *)tvmem;
 
-	if (mode) 
-		tfm = crypto_alloc_tfm (algo, 0);
-	else 
-		tfm = crypto_alloc_tfm (algo, CRYPTO_TFM_MODE_CBC);
-	
+	if (mode)
+		tfm = crypto_alloc_tfm(algo, 0);
+	else
+		tfm = crypto_alloc_tfm(algo, CRYPTO_TFM_MODE_CBC);
+
 	if (tfm == NULL) {
 		printk("failed to load transform for %s %s\n", algo, m);
 		return;
 	}
-	
+
 	j = 0;
 	for (i = 0; i < tcount; i++) {
 		if (!(cipher_tv[i].np)) {
-			j++;	
+			j++;
 			printk("test %u (%d bit key):\n",
 			j, cipher_tv[i].klen * 8);
 
 			tfm->crt_flags = 0;
-			if (cipher_tv[i].wk) 
+			if (cipher_tv[i].wk)
 				tfm->crt_flags |= CRYPTO_TFM_REQ_WEAK_KEY;
 			key = cipher_tv[i].key;
-	
+
 			ret = crypto_cipher_setkey(tfm, key, cipher_tv[i].klen);
 			if (ret) {
 				printk("setkey() failed flags=%x\n", tfm->crt_flags);
-	
+
 				if (!cipher_tv[i].fail)
 					goto out;
-			}	
+			}
 
 			p = cipher_tv[i].input;
 			sg[0].page = virt_to_page(p);
 			sg[0].offset = offset_in_page(p);
 			sg[0].length = cipher_tv[i].ilen;
-	
+
 			if (!mode) {
 				crypto_cipher_set_iv(tfm, cipher_tv[i].iv,
-					crypto_tfm_alg_ivsize (tfm));
+					crypto_tfm_alg_ivsize(tfm));
 			}
-		
+
 			if (enc)
 				ret = crypto_cipher_encrypt(tfm, sg, sg, cipher_tv[i].ilen);
 			else
 				ret = crypto_cipher_decrypt(tfm, sg, sg, cipher_tv[i].ilen);
-			
-				
+
+
 			if (ret) {
 				printk("%s () failed flags=%x\n", e, tfm->crt_flags);
 				goto out;
-			}	
-	
+			}
+
 			q = kmap(sg[0].page) + sg[0].offset;
 			hexdump(q, cipher_tv[i].rlen);
-	
-			printk("%s\n", 
-				memcmp(q, cipher_tv[i].result, cipher_tv[i].rlen) ? "fail" : 
-			"pass");
+
+			printk("%s\n",
+			       memcmp(q, cipher_tv[i].result,
+				      cipher_tv[i].rlen) ? "fail" : "pass");
 		}
 	}
-	
-	printk("\ntesting %s %s %s across pages (chunking) \n", algo, m, e);
+
+	printk("\ntesting %s %s %s across pages (chunking)\n", algo, m, e);
 	memset(xbuf, 0, XBUFSIZE);
-	
+
 	j = 0;
 	for (i = 0; i < tcount; i++) {
 		if (cipher_tv[i].np) {
-			j++;				
+			j++;
 			printk("test %u (%d bit key):\n",
 			j, cipher_tv[i].klen * 8);
 
-			tfm->crt_flags = 0;			
-			if (cipher_tv[i].wk) 
+			tfm->crt_flags = 0;
+			if (cipher_tv[i].wk)
 				tfm->crt_flags |= CRYPTO_TFM_REQ_WEAK_KEY;
 			key = cipher_tv[i].key;
-			
-			ret = crypto_cipher_setkey(tfm, key, cipher_tv[i].klen);		
+
+			ret = crypto_cipher_setkey(tfm, key, cipher_tv[i].klen);
 			if (ret) {
 				printk("setkey() failed flags=%x\n", tfm->crt_flags);
-				
+
 				if (!cipher_tv[i].fail)
 					goto out;
 			}
 
 			temp = 0;
 			for (k = 0; k < cipher_tv[i].np; k++) {
-				memcpy (&xbuf[IDX[k]], cipher_tv[i].input + temp, 
-						cipher_tv[i].tap[k]);	
+				memcpy(&xbuf[IDX[k]],
+				       cipher_tv[i].input + temp,
+				       cipher_tv[i].tap[k]);
 				temp += cipher_tv[i].tap[k];
 				p = &xbuf[IDX[k]];
-				sg[k].page = virt_to_page (p);
-				sg[k].offset = offset_in_page (p);
+				sg[k].page = virt_to_page(p);
+				sg[k].offset = offset_in_page(p);
 				sg[k].length = cipher_tv[i].tap[k];
 			}
-			
+
 			if (!mode) {
 				crypto_cipher_set_iv(tfm, cipher_tv[i].iv,
-						crypto_tfm_alg_ivsize (tfm));
+						crypto_tfm_alg_ivsize(tfm));
 			}
-			
+
 			if (enc)
 				ret = crypto_cipher_encrypt(tfm, sg, sg, cipher_tv[i].ilen);
 			else
 				ret = crypto_cipher_decrypt(tfm, sg, sg, cipher_tv[i].ilen);
-			
+
 			if (ret) {
 				printk("%s () failed flags=%x\n", e, tfm->crt_flags);
 				goto out;
@@ -404,9 +415,9 @@
 				printk("page %u\n", k);
 				q = kmap(sg[k].page) + sg[k].offset;
 				hexdump(q, cipher_tv[i].tap[k]);
-				printk("%s\n", 
-					memcmp(q, cipher_tv[i].result + temp, 
-						cipher_tv[i].tap[k]) ? "fail" : 
+				printk("%s\n",
+					memcmp(q, cipher_tv[i].result + temp,
+						cipher_tv[i].tap[k]) ? "fail" :
 					"pass");
 				temp += cipher_tv[i].tap[k];
 			}
@@ -417,8 +428,169 @@
 	crypto_free_tfm(tfm);
 }
 
-static void
-test_deflate(void)
+static int test_cipher_jiffies(struct crypto_tfm *tfm, int enc, char *p,
+			       int blen, int sec)
+{
+	struct scatterlist sg[8];
+	unsigned long start, end;
+	int bcount;
+	int ret;
+
+	sg[0].page = virt_to_page(p);
+	sg[0].offset = offset_in_page(p);
+	sg[0].length = blen;
+
+	for (start = jiffies, end = start + sec * HZ, bcount = 0;
+	     time_before(jiffies, end); bcount++) {
+		if (enc)
+			ret = crypto_cipher_encrypt(tfm, sg, sg, blen);
+		else
+			ret = crypto_cipher_decrypt(tfm, sg, sg, blen);
+
+		if (ret)
+			return ret;
+	}
+
+	printk("%d operations in %d seconds (%ld bytes)\n",
+	       bcount, sec, (long)bcount * blen);
+	return 0;
+}
+
+static int test_cipher_cycles(struct crypto_tfm *tfm, int enc, char *p,
+			      int blen)
+{
+	struct scatterlist sg[8];
+	unsigned long cycles = 0;
+	int ret = 0;
+	int i;
+
+	sg[0].page = virt_to_page(p);
+	sg[0].offset = offset_in_page(p);
+	sg[0].length = blen;
+
+	local_bh_disable();
+	local_irq_disable();
+
+	/* Warm-up run. */
+	for (i = 0; i < 4; i++) {
+		if (enc)
+			ret = crypto_cipher_encrypt(tfm, sg, sg, blen);
+		else
+			ret = crypto_cipher_decrypt(tfm, sg, sg, blen);
+
+		if (ret)
+			goto out;
+	}
+
+	/* The real thing. */
+	for (i = 0; i < 8; i++) {
+		cycles_t start, end;
+
+		start = get_cycles();
+		if (enc)
+			ret = crypto_cipher_encrypt(tfm, sg, sg, blen);
+		else
+			ret = crypto_cipher_decrypt(tfm, sg, sg, blen);
+		end = get_cycles();
+
+		if (ret)
+			goto out;
+
+		cycles += end - start;
+	}
+
+out:
+	local_irq_enable();
+	local_bh_enable();
+
+	if (ret == 0)
+		printk("1 operation in %lu cycles (%d bytes)\n",
+		       (cycles + 4) / 8, blen);
+
+	return ret;
+}
+
+static void test_cipher_speed(char *algo, int mode, int enc, unsigned int sec,
+			      struct cipher_testvec *template,
+			      unsigned int tcount, struct cipher_speed *speed)
+{
+	unsigned int ret, i, j, iv_len;
+	unsigned char *key, *p, iv[128];
+	struct crypto_tfm *tfm;
+	const char *e, *m;
+
+	if (enc == ENCRYPT)
+	        e = "encryption";
+	else
+		e = "decryption";
+	if (mode == MODE_ECB)
+		m = "ECB";
+	else
+		m = "CBC";
+
+	printk("\ntesting speed of %s %s %s\n", algo, m, e);
+
+	if (mode)
+		tfm = crypto_alloc_tfm(algo, 0);
+	else
+		tfm = crypto_alloc_tfm(algo, CRYPTO_TFM_MODE_CBC);
+
+	if (tfm == NULL) {
+		printk("failed to load transform for %s %s\n", algo, m);
+		return;
+	}
+
+	for (i = 0; speed[i].klen != 0; i++) {
+		if ((speed[i].blen + speed[i].klen) > TVMEMSIZE) {
+			printk("template (%u) too big for tvmem (%u)\n",
+			       speed[i].blen + speed[i].klen, TVMEMSIZE);
+			goto out;
+		}
+
+		printk("test %u (%d bit key, %d byte blocks): ", i,
+		       speed[i].klen * 8, speed[i].blen);
+
+		memset(tvmem, 0xff, speed[i].klen + speed[i].blen);
+
+		/* set key, plain text and IV */
+		key = (unsigned char *)tvmem;
+		for (j = 0; j < tcount; j++) {
+			if (template[j].klen == speed[i].klen) {
+				key = template[j].key;
+				break;
+			}
+		}
+		p = (unsigned char *)tvmem + speed[i].klen;
+
+		ret = crypto_cipher_setkey(tfm, key, speed[i].klen);
+		if (ret) {
+			printk("setkey() failed flags=%x\n", tfm->crt_flags);
+			goto out;
+		}
+
+		if (!mode) {
+			iv_len = crypto_tfm_alg_ivsize(tfm);
+			memset(&iv, 0xff, iv_len);
+			crypto_cipher_set_iv(tfm, iv, iv_len);
+		}
+
+		if (sec)
+			ret = test_cipher_jiffies(tfm, enc, p, speed[i].blen,
+						  sec);
+		else
+			ret = test_cipher_cycles(tfm, enc, p, speed[i].blen);
+
+		if (ret) {
+			printk("%s() failed flags=%x\n", e, tfm->crt_flags);
+			break;
+		}
+	}
+
+out:
+	crypto_free_tfm(tfm);
+}
+
+static void test_deflate(void)
 {
 	unsigned int i;
 	char result[COMP_BUF_SIZE];
@@ -436,7 +608,7 @@
 	}
 
 	memcpy(tvmem, deflate_comp_tv_template, tsize);
-	tv = (void *) tvmem;
+	tv = (void *)tvmem;
 
 	tfm = crypto_alloc_tfm("deflate", 0);
 	if (tfm == NULL) {
@@ -446,7 +618,7 @@
 
 	for (i = 0; i < DEFLATE_COMP_TEST_VECTORS; i++) {
 		int ilen, ret, dlen = COMP_BUF_SIZE;
-		
+
 		printk("test %u:\n", i + 1);
 		memset(result, 0, sizeof (result));
 
@@ -473,11 +645,11 @@
 	}
 
 	memcpy(tvmem, deflate_decomp_tv_template, tsize);
-	tv = (void *) tvmem;
+	tv = (void *)tvmem;
 
 	for (i = 0; i < DEFLATE_DECOMP_TEST_VECTORS; i++) {
 		int ilen, ret, dlen = COMP_BUF_SIZE;
-		
+
 		printk("test %u:\n", i + 1);
 		memset(result, 0, sizeof (result));
 
@@ -497,8 +669,7 @@
 	crypto_free_tfm(tfm);
 }
 
-static void
-test_crc32c(void)
+static void test_crc32c(void)
 {
 #define NUMVEC 6
 #define VECSIZE 40
@@ -511,7 +682,7 @@
 		0xd579c862, 0xba979ad0, 0x2b29d913
 	};
 	static u32 tot_vec_results = 0x24c5d375;
-	
+
 	struct scatterlist sg[NUMVEC];
 	struct crypto_tfm *tfm;
 	char *fmtdata = "testing crc32c initialized to %08x: %s\n";
@@ -525,18 +696,18 @@
 		printk("failed to load transform for crc32c\n");
 		return;
 	}
-	
+
 	crypto_digest_init(tfm);
 	crypto_digest_final(tfm, (u8*)&crc);
 	printk(fmtdata, crc, (crc == 0) ? "pass" : "ERROR");
-	
+
 	/*
 	 * stuff test_vec with known values, simple incrementing
 	 * byte values.
 	 */
 	b = 0;
 	for (i = 0; i < NUMVEC; i++) {
-		for (j = 0; j < VECSIZE; j++) 
+		for (j = 0; j < VECSIZE; j++)
 			test_vec[i][j] = ++b;
 		sg[i].page = virt_to_page(test_vec[i]);
 		sg[i].offset = offset_in_page(test_vec[i]);
@@ -548,11 +719,11 @@
 	crypto_digest_final(tfm, (u8*)&crc);
 	printk("testing crc32c setkey returns %08x : %s\n", crc, (crc == (SEEDTESTVAL ^ ~(u32)0)) ?
 	       "pass" : "ERROR");
-	
+
 	printk("testing crc32c using update/final:\n");
 
 	pass = 1;		    /* assume all is well */
-	
+
 	for (i = 0; i < NUMVEC; i++) {
 		seed = ~(u32)0;
 		(void)crypto_digest_setkey(tfm, (const u8*)&seed, sizeof(u32));
@@ -591,66 +762,64 @@
 		printk(" %08x:BAD, wanted %08x\n", crc, tot_vec_results);
 		pass = 0;
 	}
-	
+
 	printk("\n%s\n", pass ? "pass" : "ERROR");
 
 	crypto_free_tfm(tfm);
 	printk("crc32c test complete\n");
 }
 
-static void
-test_available(void)
+static void test_available(void)
 {
 	char **name = check;
-	
+
 	while (*name) {
 		printk("alg %s ", *name);
 		printk((crypto_alg_available(*name, 0)) ?
 			"found\n" : "not found\n");
 		name++;
-	}	
+	}
 }
 
-static void
-do_test(void)
+static void do_test(void)
 {
 	switch (mode) {
 
 	case 0:
 		test_hash("md5", md5_tv_template, MD5_TEST_VECTORS);
-		
+
 		test_hash("sha1", sha1_tv_template, SHA1_TEST_VECTORS);
-		
+
 		//DES
 		test_cipher ("des", MODE_ECB, ENCRYPT, des_enc_tv_template, DES_ENC_TEST_VECTORS);
-                test_cipher ("des", MODE_ECB, DECRYPT, des_dec_tv_template, DES_DEC_TEST_VECTORS);
-                test_cipher ("des", MODE_CBC, ENCRYPT, des_cbc_enc_tv_template, DES_CBC_ENC_TEST_VECTORS);
-                test_cipher ("des", MODE_CBC, DECRYPT, des_cbc_dec_tv_template, DES_CBC_DEC_TEST_VECTORS);
-	
+		test_cipher ("des", MODE_ECB, DECRYPT, des_dec_tv_template, DES_DEC_TEST_VECTORS);
+		test_cipher ("des", MODE_CBC, ENCRYPT, des_cbc_enc_tv_template, DES_CBC_ENC_TEST_VECTORS);
+		test_cipher ("des", MODE_CBC, DECRYPT, des_cbc_dec_tv_template, DES_CBC_DEC_TEST_VECTORS);
+
 		//DES3_EDE
 		test_cipher ("des3_ede", MODE_ECB, ENCRYPT, des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS);
-                test_cipher ("des3_ede", MODE_ECB, DECRYPT, des3_ede_dec_tv_template, DES3_EDE_DEC_TEST_VECTORS);
-		
+		test_cipher ("des3_ede", MODE_ECB, DECRYPT, des3_ede_dec_tv_template, DES3_EDE_DEC_TEST_VECTORS);
+
 		test_hash("md4", md4_tv_template, MD4_TEST_VECTORS);
-		
+
 		test_hash("sha256", sha256_tv_template, SHA256_TEST_VECTORS);
-		
+
 		//BLOWFISH
 		test_cipher ("blowfish", MODE_ECB, ENCRYPT, bf_enc_tv_template, BF_ENC_TEST_VECTORS);
 		test_cipher ("blowfish", MODE_ECB, DECRYPT, bf_dec_tv_template, BF_DEC_TEST_VECTORS);
 		test_cipher ("blowfish", MODE_CBC, ENCRYPT, bf_cbc_enc_tv_template, BF_CBC_ENC_TEST_VECTORS);
 		test_cipher ("blowfish", MODE_CBC, DECRYPT, bf_cbc_dec_tv_template, BF_CBC_DEC_TEST_VECTORS);
-		
+
 		//TWOFISH
 		test_cipher ("twofish", MODE_ECB, ENCRYPT, tf_enc_tv_template, TF_ENC_TEST_VECTORS);
 		test_cipher ("twofish", MODE_ECB, DECRYPT, tf_dec_tv_template, TF_DEC_TEST_VECTORS);
 		test_cipher ("twofish", MODE_CBC, ENCRYPT, tf_cbc_enc_tv_template, TF_CBC_ENC_TEST_VECTORS);
 		test_cipher ("twofish", MODE_CBC, DECRYPT, tf_cbc_dec_tv_template, TF_CBC_DEC_TEST_VECTORS);
-		
+
 		//SERPENT
 		test_cipher ("serpent", MODE_ECB, ENCRYPT, serpent_enc_tv_template, SERPENT_ENC_TEST_VECTORS);
 		test_cipher ("serpent", MODE_ECB, DECRYPT, serpent_dec_tv_template, SERPENT_DEC_TEST_VECTORS);
-		
+
 		//TNEPRES
 		test_cipher ("tnepres", MODE_ECB, ENCRYPT, tnepres_enc_tv_template, TNEPRES_ENC_TEST_VECTORS);
 		test_cipher ("tnepres", MODE_ECB, DECRYPT, tnepres_dec_tv_template, TNEPRES_DEC_TEST_VECTORS);
@@ -662,7 +831,7 @@
 		//CAST5
 		test_cipher ("cast5", MODE_ECB, ENCRYPT, cast5_enc_tv_template, CAST5_ENC_TEST_VECTORS);
 		test_cipher ("cast5", MODE_ECB, DECRYPT, cast5_dec_tv_template, CAST5_DEC_TEST_VECTORS);
-		
+
 		//CAST6
 		test_cipher ("cast6", MODE_ECB, ENCRYPT, cast6_enc_tv_template, CAST6_ENC_TEST_VECTORS);
 		test_cipher ("cast6", MODE_ECB, DECRYPT, cast6_dec_tv_template, CAST6_DEC_TEST_VECTORS);
@@ -702,9 +871,9 @@
 		test_crc32c();
 #ifdef CONFIG_CRYPTO_HMAC
 		test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
-		test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS);		
+		test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS);
 		test_hmac("sha256", hmac_sha256_tv_template, HMAC_SHA256_TEST_VECTORS);
-#endif		
+#endif
 
 		test_hash("michael_mic", michael_mic_tv_template, MICHAEL_MIC_TEST_VECTORS);
 		break;
@@ -726,17 +895,17 @@
 
 	case 4:
 		test_cipher ("des3_ede", MODE_ECB, ENCRYPT, des3_ede_enc_tv_template, DES3_EDE_ENC_TEST_VECTORS);
-                test_cipher ("des3_ede", MODE_ECB, DECRYPT, des3_ede_dec_tv_template, DES3_EDE_DEC_TEST_VECTORS);
+		test_cipher ("des3_ede", MODE_ECB, DECRYPT, des3_ede_dec_tv_template, DES3_EDE_DEC_TEST_VECTORS);
 		break;
 
 	case 5:
 		test_hash("md4", md4_tv_template, MD4_TEST_VECTORS);
 		break;
-		
+
 	case 6:
 		test_hash("sha256", sha256_tv_template, SHA256_TEST_VECTORS);
 		break;
-	
+
 	case 7:
 		test_cipher ("blowfish", MODE_ECB, ENCRYPT, bf_enc_tv_template, BF_ENC_TEST_VECTORS);
 		test_cipher ("blowfish", MODE_ECB, DECRYPT, bf_dec_tv_template, BF_DEC_TEST_VECTORS);
@@ -750,7 +919,7 @@
 		test_cipher ("twofish", MODE_CBC, ENCRYPT, tf_cbc_enc_tv_template, TF_CBC_ENC_TEST_VECTORS);
 		test_cipher ("twofish", MODE_CBC, DECRYPT, tf_cbc_dec_tv_template, TF_CBC_DEC_TEST_VECTORS);
 		break;
-		
+
 	case 9:
 		test_cipher ("serpent", MODE_ECB, ENCRYPT, serpent_enc_tv_template, SERPENT_ENC_TEST_VECTORS);
 		test_cipher ("serpent", MODE_ECB, DECRYPT, serpent_dec_tv_template, SERPENT_DEC_TEST_VECTORS);
@@ -758,13 +927,13 @@
 
 	case 10:
 		test_cipher ("aes", MODE_ECB, ENCRYPT, aes_enc_tv_template, AES_ENC_TEST_VECTORS);
-		test_cipher ("aes", MODE_ECB, DECRYPT, aes_dec_tv_template, AES_DEC_TEST_VECTORS);	
+		test_cipher ("aes", MODE_ECB, DECRYPT, aes_dec_tv_template, AES_DEC_TEST_VECTORS);
 		break;
 
 	case 11:
 		test_hash("sha384", sha384_tv_template, SHA384_TEST_VECTORS);
 		break;
-		
+
 	case 12:
 		test_hash("sha512", sha512_tv_template, SHA512_TEST_VECTORS);
 		break;
@@ -852,21 +1021,84 @@
 	case 100:
 		test_hmac("md5", hmac_md5_tv_template, HMAC_MD5_TEST_VECTORS);
 		break;
-		
+
 	case 101:
-		test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS);		
+		test_hmac("sha1", hmac_sha1_tv_template, HMAC_SHA1_TEST_VECTORS);
 		break;
-	
+
 	case 102:
 		test_hmac("sha256", hmac_sha256_tv_template, HMAC_SHA256_TEST_VECTORS);
 		break;
 
 #endif
 
+	case 200:
+		test_cipher_speed("aes", MODE_ECB, ENCRYPT, sec, NULL, 0,
+				  aes_speed_template);
+		test_cipher_speed("aes", MODE_ECB, DECRYPT, sec, NULL, 0,
+				  aes_speed_template);
+		test_cipher_speed("aes", MODE_CBC, ENCRYPT, sec, NULL, 0,
+				  aes_speed_template);
+		test_cipher_speed("aes", MODE_CBC, DECRYPT, sec, NULL, 0,
+				  aes_speed_template);
+		break;
+
+	case 201:
+		test_cipher_speed("des3_ede", MODE_ECB, ENCRYPT, sec,
+				  des3_ede_enc_tv_template,
+				  DES3_EDE_ENC_TEST_VECTORS,
+				  des3_ede_speed_template);
+		test_cipher_speed("des3_ede", MODE_ECB, DECRYPT, sec,
+				  des3_ede_dec_tv_template,
+				  DES3_EDE_DEC_TEST_VECTORS,
+				  des3_ede_speed_template);
+		test_cipher_speed("des3_ede", MODE_CBC, ENCRYPT, sec,
+				  des3_ede_enc_tv_template,
+				  DES3_EDE_ENC_TEST_VECTORS,
+				  des3_ede_speed_template);
+		test_cipher_speed("des3_ede", MODE_CBC, DECRYPT, sec,
+				  des3_ede_dec_tv_template,
+				  DES3_EDE_DEC_TEST_VECTORS,
+				  des3_ede_speed_template);
+		break;
+
+	case 202:
+		test_cipher_speed("twofish", MODE_ECB, ENCRYPT, sec, NULL, 0,
+				  twofish_speed_template);
+		test_cipher_speed("twofish", MODE_ECB, DECRYPT, sec, NULL, 0,
+				  twofish_speed_template);
+		test_cipher_speed("twofish", MODE_CBC, ENCRYPT, sec, NULL, 0,
+				  twofish_speed_template);
+		test_cipher_speed("twofish", MODE_CBC, DECRYPT, sec, NULL, 0,
+				  twofish_speed_template);
+		break;
+
+	case 203:
+		test_cipher_speed("blowfish", MODE_ECB, ENCRYPT, sec, NULL, 0,
+				  blowfish_speed_template);
+		test_cipher_speed("blowfish", MODE_ECB, DECRYPT, sec, NULL, 0,
+				  blowfish_speed_template);
+		test_cipher_speed("blowfish", MODE_CBC, ENCRYPT, sec, NULL, 0,
+				  blowfish_speed_template);
+		test_cipher_speed("blowfish", MODE_CBC, DECRYPT, sec, NULL, 0,
+				  blowfish_speed_template);
+		break;
+
+	case 204:
+		test_cipher_speed("des", MODE_ECB, ENCRYPT, sec, NULL, 0,
+				  des_speed_template);
+		test_cipher_speed("des", MODE_ECB, DECRYPT, sec, NULL, 0,
+				  des_speed_template);
+		test_cipher_speed("des", MODE_CBC, ENCRYPT, sec, NULL, 0,
+				  des_speed_template);
+		test_cipher_speed("des", MODE_CBC, DECRYPT, sec, NULL, 0,
+				  des_speed_template);
+		break;
+
 	case 1000:
 		test_available();
 		break;
-		
+
 	default:
 		/* useful for debugging */
 		printk("not testing anything\n");
@@ -874,8 +1106,7 @@
 	}
 }
 
-static int __init
-init(void)
+static int __init init(void)
 {
 	tvmem = kmalloc(TVMEMSIZE, GFP_KERNEL);
 	if (tvmem == NULL)
@@ -904,6 +1135,9 @@
 module_exit(fini);
 
 module_param(mode, int, 0);
+module_param(sec, uint, 0);
+MODULE_PARM_DESC(sec, "Length in seconds of speed tests "
+		      "(defaults to zero which uses CPU cycles instead)");
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Quick & dirty crypto testing module");
diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h
index a3097af..c01a0ce9 100644
--- a/crypto/tcrypt.h
+++ b/crypto/tcrypt.h
@@ -9,10 +9,11 @@
  *
  * 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) 
+ * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
- * 14 - 09 - 2003 Changes by Kartikey Mahendra Bhatt
+ * 2004-08-09 Cipher speed tests by Reyk Floeter <reyk@vantronix.net>
+ * 2003-09-14 Changes by Kartikey Mahendra Bhatt
  *
  */
 #ifndef _CRYPTO_TCRYPT_H
@@ -29,19 +30,19 @@
 	unsigned char psize;
 	char digest[MAX_DIGEST_SIZE];
 	unsigned char np;
-	unsigned char tap[MAX_TAP];		
+	unsigned char tap[MAX_TAP];
 	char key[128]; /* only used with keyed hash algorithms */
 	unsigned char ksize;
 };
 
-struct hmac_testvec {	
+struct hmac_testvec {
 	char key[128];
 	unsigned char ksize;
 	char plaintext[128];
 	unsigned char psize;
 	char digest[MAX_DIGEST_SIZE];
 	unsigned char np;
-	unsigned char tap[MAX_TAP];		
+	unsigned char tap[MAX_TAP];
 };
 
 struct cipher_testvec {
@@ -55,7 +56,12 @@
 	char result[48];
 	unsigned char rlen;
 	int np;
-	unsigned char tap[MAX_TAP];	
+	unsigned char tap[MAX_TAP];
+};
+
+struct cipher_speed {
+	unsigned char klen;
+	unsigned int blen;
 };
 
 /*
@@ -155,7 +161,7 @@
 #define SHA1_TEST_VECTORS	2
 
 static struct hash_testvec sha1_tv_template[] = {
-	{ 
+	{
 		.plaintext = "abc",
 		.psize	= 3,
 		.digest	= { 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e,
@@ -175,8 +181,8 @@
  */
 #define SHA256_TEST_VECTORS	2
 
-static struct hash_testvec sha256_tv_template[] = {	
-	{ 
+static struct hash_testvec sha256_tv_template[] = {
+	{
 		.plaintext = "abc",
 		.psize	= 3,
 		.digest	= { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
@@ -201,7 +207,7 @@
 #define SHA384_TEST_VECTORS	4
 
 static struct hash_testvec sha384_tv_template[] = {
-	{ 
+	{
 		.plaintext= "abc",
 		.psize	= 3,
 		.digest	= { 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b,
@@ -221,7 +227,7 @@
 			    0x5f, 0xe9, 0x5b, 0x1f, 0xe3, 0xc8, 0x45, 0x2b},
 	}, {
 		.plaintext = "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
- 			     "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
+			     "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu",
 		.psize	= 112,
 		.digest	= { 0x09, 0x33, 0x0c, 0x33, 0xf7, 0x11, 0x47, 0xe8,
 			    0x3d, 0x19, 0x2f, 0xc7, 0x82, 0xcd, 0x1b, 0x47,
@@ -250,7 +256,7 @@
 #define SHA512_TEST_VECTORS	4
 
 static struct hash_testvec sha512_tv_template[] = {
-	{ 
+	{
 		.plaintext = "abc",
 		.psize	= 3,
 		.digest	= { 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
@@ -303,14 +309,14 @@
 
 
 /*
- * WHIRLPOOL test vectors from Whirlpool package 
+ * WHIRLPOOL test vectors from Whirlpool package
  * by Vincent Rijmen and Paulo S. L. M. Barreto as part of the NESSIE
  * submission
  */
 #define WP512_TEST_VECTORS	8
 
 static struct hash_testvec wp512_tv_template[] = {
-	{ 
+	{
 		.plaintext = "",
 		.psize	= 0,
 		.digest	= { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66,
@@ -348,13 +354,13 @@
 	}, {
 		.plaintext = "message digest",
 		.psize	= 14,
-		.digest	= { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6, 
-			    0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC, 
-			    0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C, 
-			    0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B, 
-			    0x84, 0x21, 0x55, 0x76, 0x59, 0xEF, 0x55, 0xC1, 
-			    0x06, 0xB4, 0xB5, 0x2A, 0xC5, 0xA4, 0xAA, 0xA6, 
-			    0x92, 0xED, 0x92, 0x00, 0x52, 0x83, 0x8F, 0x33, 
+		.digest	= { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6,
+			    0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC,
+			    0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C,
+			    0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B,
+			    0x84, 0x21, 0x55, 0x76, 0x59, 0xEF, 0x55, 0xC1,
+			    0x06, 0xB4, 0xB5, 0x2A, 0xC5, 0xA4, 0xAA, 0xA6,
+			    0x92, 0xED, 0x92, 0x00, 0x52, 0x83, 0x8F, 0x33,
 			    0x62, 0xE8, 0x6D, 0xBD, 0x37, 0xA8, 0x90, 0x3E },
 	}, {
 		.plaintext = "abcdefghijklmnopqrstuvwxyz",
@@ -394,7 +400,7 @@
 	}, {
 		.plaintext = "abcdbcdecdefdefgefghfghighijhijk",
 		.psize	= 32,
-		.digest	= { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61, 
+		.digest	= { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61,
 			    0xF5, 0xD6, 0xF0, 0xA0, 0xE4, 0x64, 0x4F, 0x48,
 			    0x8A, 0x7A, 0x5A, 0x52, 0xDE, 0xEE, 0x65, 0x62,
 			    0x07, 0xC5, 0x62, 0xF9, 0x88, 0xE9, 0x5C, 0x69,
@@ -408,7 +414,7 @@
 #define WP384_TEST_VECTORS	8
 
 static struct hash_testvec wp384_tv_template[] = {
-	{ 
+	{
 		.plaintext = "",
 		.psize	= 0,
 		.digest	= { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66,
@@ -440,11 +446,11 @@
 	}, {
 		.plaintext = "message digest",
 		.psize	= 14,
-		.digest	= { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6, 
-			    0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC, 
-			    0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C, 
-			    0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B, 
-			    0x84, 0x21, 0x55, 0x76, 0x59, 0xEF, 0x55, 0xC1, 
+		.digest	= { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6,
+			    0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC,
+			    0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C,
+			    0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B,
+			    0x84, 0x21, 0x55, 0x76, 0x59, 0xEF, 0x55, 0xC1,
 			    0x06, 0xB4, 0xB5, 0x2A, 0xC5, 0xA4, 0xAA, 0xA6 },
 	}, {
 		.plaintext = "abcdefghijklmnopqrstuvwxyz",
@@ -478,7 +484,7 @@
 	}, {
 		.plaintext = "abcdbcdecdefdefgefghfghighijhijk",
 		.psize	= 32,
-		.digest	= { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61, 
+		.digest	= { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61,
 			    0xF5, 0xD6, 0xF0, 0xA0, 0xE4, 0x64, 0x4F, 0x48,
 			    0x8A, 0x7A, 0x5A, 0x52, 0xDE, 0xEE, 0x65, 0x62,
 			    0x07, 0xC5, 0x62, 0xF9, 0x88, 0xE9, 0x5C, 0x69,
@@ -490,7 +496,7 @@
 #define WP256_TEST_VECTORS	8
 
 static struct hash_testvec wp256_tv_template[] = {
-	{ 
+	{
 		.plaintext = "",
 		.psize	= 0,
 		.digest	= { 0x19, 0xFA, 0x61, 0xD7, 0x55, 0x22, 0xA4, 0x66,
@@ -516,9 +522,9 @@
 	}, {
 		.plaintext = "message digest",
 		.psize	= 14,
-		.digest	= { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6, 
-			    0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC, 
-			    0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C, 
+		.digest	= { 0x37, 0x8C, 0x84, 0xA4, 0x12, 0x6E, 0x2D, 0xC6,
+			    0xE5, 0x6D, 0xCC, 0x74, 0x58, 0x37, 0x7A, 0xAC,
+			    0x83, 0x8D, 0x00, 0x03, 0x22, 0x30, 0xF5, 0x3C,
 			    0xE1, 0xF5, 0x70, 0x0C, 0x0F, 0xFB, 0x4D, 0x3B },
 	}, {
 		.plaintext = "abcdefghijklmnopqrstuvwxyz",
@@ -546,7 +552,7 @@
 	}, {
 		.plaintext = "abcdbcdecdefdefgefghfghighijhijk",
 		.psize	= 32,
-		.digest	= { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61, 
+		.digest	= { 0x2A, 0x98, 0x7E, 0xA4, 0x0F, 0x91, 0x70, 0x61,
 			    0xF5, 0xD6, 0xF0, 0xA0, 0xE4, 0x64, 0x4F, 0x48,
 			    0x8A, 0x7A, 0x5A, 0x52, 0xDE, 0xEE, 0x65, 0x62,
 			    0x07, 0xC5, 0x62, 0xF9, 0x88, 0xE9, 0x5C, 0x69 },
@@ -554,7 +560,7 @@
 };
 
 /*
- * TIGER test vectors from Tiger website 
+ * TIGER test vectors from Tiger website
  */
 #define TGR192_TEST_VECTORS	6
 
@@ -693,7 +699,7 @@
 #define HMAC_MD5_TEST_VECTORS	7
 
 static struct hmac_testvec hmac_md5_tv_template[] =
-{	
+{
 	{
 		.key	= { [0 ... 15] =  0x0b },
 		.ksize	= 16,
@@ -756,7 +762,7 @@
  */
 #define HMAC_SHA1_TEST_VECTORS	7
 
-static struct hmac_testvec hmac_sha1_tv_template[] = {	
+static struct hmac_testvec hmac_sha1_tv_template[] = {
 	{
 		.key	= { [0 ... 19] = 0x0b },
 		.ksize	= 20,
@@ -766,11 +772,11 @@
 			    0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e, 0xf1,
 			    0x46, 0xbe },
 	}, {
-		.key	= { 'J', 'e', 'f', 'e' },		
+		.key	= { 'J', 'e', 'f', 'e' },
 		.ksize	= 4,
 		.plaintext = "what do ya want for nothing?",
 		.psize	= 28,
-		.digest	= { 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, 0xd2, 0x74, 
+		.digest	= { 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb, 0x2f, 0xa2, 0xd2, 0x74,
 			    0x16, 0xd5, 0xf1, 0x84, 0xdf, 0x9c, 0x25, 0x9a, 0x7c, 0x79 },
 		.np	= 2,
 		.tap	= { 14, 14 }
@@ -779,30 +785,30 @@
 		.ksize	= 20,
 		.plaintext = { [0 ... 49] = 0xdd },
 		.psize	= 50,
-		.digest	= { 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, 0x91, 0xa3, 
+		.digest	= { 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac, 0x11, 0xcd, 0x91, 0xa3,
 			    0x9a, 0xf4, 0x8a, 0xa1, 0x7b, 0x4f, 0x63, 0xf1, 0x75, 0xd3 },
 	}, {
 		.key	= { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
-			    0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 
+			    0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
 			    0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19 },
 		.ksize	= 25,
 		.plaintext = { [0 ... 49] = 0xcd },
 		.psize	= 50,
-		.digest	= { 0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6, 0xbc, 0x84, 
+		.digest	= { 0x4c, 0x90, 0x07, 0xf4, 0x02, 0x62, 0x50, 0xc6, 0xbc, 0x84,
 			    0x14, 0xf9, 0xbf, 0x50, 0xc8, 0x6c, 0x2d, 0x72, 0x35, 0xda },
 	}, {
 		.key	= { [0 ... 19] = 0x0c },
 		.ksize	= 20,
 		.plaintext = "Test With Truncation",
 		.psize	= 20,
-		.digest	= { 0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2, 
+		.digest	= { 0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2,
 			    0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04 },
 	}, {
 		.key	= { [0 ... 79] = 0xaa },
 		.ksize	= 80,
 		.plaintext = "Test Using Larger Than Block-Size Key - Hash Key First",
 		.psize	= 54,
-		.digest	= { 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, 0x95, 0x70, 
+		.digest	= { 0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, 0x95, 0x70,
 			    0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, 0xed, 0x40, 0x21, 0x12 },
 	}, {
 		.key	= { [0 ... 79] = 0xaa },
@@ -810,7 +816,7 @@
 		.plaintext = "Test Using Larger Than Block-Size Key and Larger Than One "
 			     "Block-Size Data",
 		.psize	= 73,
-		.digest	= { 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, 0x6b, 
+		.digest	= { 0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, 0x6b,
 			    0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91 },
 	},
 };
@@ -1011,7 +1017,7 @@
 			    0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b },
 		.rlen	= 32,
 		.np	= 3,
-		.tap	= { 14, 10, 8 } 
+		.tap	= { 14, 10, 8 }
 	}, {
 		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
 		.klen	= 8,
@@ -1024,7 +1030,7 @@
 			    0xb4, 0x99, 0x26, 0xf7, 0x1f, 0xe1, 0xd4, 0x90 },
 		.rlen	= 24,
 		.np	= 4,
-		.tap	= { 2, 1, 3, 18 } 
+		.tap	= { 2, 1, 3, 18 }
 	}, {
 		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
 		.klen	= 8,
@@ -1035,7 +1041,7 @@
 			    0xf7, 0x9c, 0x89, 0x2a, 0x33, 0x8f, 0x4a, 0x8b },
 		.rlen	= 16,
 		.np	= 5,
-		.tap	= { 2, 2, 2, 2, 8 } 
+		.tap	= { 2, 2, 2, 2, 8 }
 	}, {
 		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
 		.klen	= 8,
@@ -1044,7 +1050,7 @@
 		.result	= { 0xc9, 0x57, 0x44, 0x25, 0x6a, 0x5e, 0xd3, 0x1d },
 		.rlen	= 8,
 		.np	= 8,
-		.tap	= { 1, 1, 1, 1, 1, 1, 1, 1 } 
+		.tap	= { 1, 1, 1, 1, 1, 1, 1, 1 }
 	},
 };
 
@@ -1057,7 +1063,7 @@
 		.result	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xe7 },
 		.rlen	= 8,
 	}, { /* Sbox test from NBS */
-		.key	= { 0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57 },		
+		.key	= { 0x7c, 0xa1, 0x10, 0x45, 0x4a, 0x1a, 0x6e, 0x57 },
 		.klen	= 8,
 		.input	= { 0x69, 0x0f, 0x5b, 0x0d, 0x9a, 0x26, 0x93, 0x9b },
 		.ilen	= 8,
@@ -1092,19 +1098,19 @@
 	{ /* From OpenSSL */
 		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
 		.klen	= 8,
-		.iv	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},		
-		.input	= { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20, 
-			    0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74, 
-			    0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 }, 
+		.iv	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+		.input	= { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
+			    0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
+			    0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 },
 		.ilen	= 24,
-		.result	= { 0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4, 
-			    0xac, 0xd8, 0xae, 0xfd, 0xdf, 0xd8, 0xa1, 0xeb, 
-			    0x46, 0x8e, 0x91, 0x15, 0x78, 0x88, 0xba, 0x68 }, 
+		.result	= { 0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4,
+			    0xac, 0xd8, 0xae, 0xfd, 0xdf, 0xd8, 0xa1, 0xeb,
+			    0x46, 0x8e, 0x91, 0x15, 0x78, 0x88, 0xba, 0x68 },
 		.rlen	= 24,
 	}, { /* FIPS Pub 81 */
 		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
 		.klen	= 8,
-		.iv	= { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef },		
+		.iv	= { 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef },
 		.input	= { 0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 },
 		.ilen	= 8,
 		.result	= { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
@@ -1117,7 +1123,7 @@
 		.ilen	= 8,
 		.result	= { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
 		.rlen	= 8,
-	}, {	
+	}, {
 		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
 		.klen	= 8,
 		.iv	= { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
@@ -1125,18 +1131,18 @@
 		.ilen	= 8,
 		.result	= { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 },
 		.rlen	= 8,
-	}, { /* Copy of openssl vector for chunk testing */	
+	}, { /* Copy of openssl vector for chunk testing */
 	     /* From OpenSSL */
 		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef},
 		.klen	= 8,
-		.iv	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},		
-		.input	= { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20, 
-			    0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74, 
-			    0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 }, 
+		.iv	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10},
+		.input	= { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
+			    0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
+			    0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 },
 		.ilen	= 24,
-		.result	= { 0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4, 
-			    0xac, 0xd8, 0xae, 0xfd, 0xdf, 0xd8, 0xa1, 0xeb, 
-			    0x46, 0x8e, 0x91, 0x15, 0x78, 0x88, 0xba, 0x68 }, 
+		.result	= { 0xcc, 0xd1, 0x73, 0xff, 0xab, 0x20, 0x39, 0xf4,
+			    0xac, 0xd8, 0xae, 0xfd, 0xdf, 0xd8, 0xa1, 0xeb,
+			    0x46, 0x8e, 0x91, 0x15, 0x78, 0x88, 0xba, 0x68 },
 		.rlen	= 24,
 		.np	= 2,
 		.tap	= { 13, 11 }
@@ -1155,24 +1161,24 @@
 	}, {
 		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
 		.klen	= 8,
-		.iv	= { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },		
+		.iv	= { 0xe5, 0xc7, 0xcd, 0xde, 0x87, 0x2b, 0xf2, 0x7c },
 		.input	= { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
 		.ilen	= 8,
-		.result	= { 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 }, 
+		.result	= { 0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20 },
 		.rlen	= 8,
 	}, {
 		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
 		.klen	= 8,
 		.iv	= { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
-		.input	= { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 }, 
+		.input	= { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 },
 		.ilen	= 8,
 		.result	= { 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 },
 		.rlen	= 8,
-	}, { /* Copy of above, for chunk testing */	
+	}, { /* Copy of above, for chunk testing */
 		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
 		.klen	= 8,
 		.iv	= { 0x43, 0xe9, 0x34, 0x00, 0x8c, 0x38, 0x9c, 0x0f },
-		.input	= { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 }, 
+		.input	= { 0x68, 0x37, 0x88, 0x49, 0x9a, 0x7c, 0x05, 0xf6 },
 		.ilen	= 8,
 		.result	= { 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20 },
 		.rlen	= 8,
@@ -1276,7 +1282,7 @@
 		.ilen	= 8,
 		.result	= { 0xe8, 0x7a, 0x24, 0x4e, 0x2c, 0xc8, 0x5e, 0x82 },
 		.rlen	= 8,
-	}, { /* Vary the keylength... */	
+	}, { /* Vary the keylength... */
 		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
 			    0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f },
 		.klen	= 16,
@@ -1297,9 +1303,9 @@
 		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
 			    0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f,
 			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
-			    0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f, 
-			    0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76, 
-			    0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e, 
+			    0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f,
+			    0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76,
+			    0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e,
 			    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
 		.klen	= 56,
 		.input	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
@@ -1331,7 +1337,7 @@
 		.ilen	= 8,
 		.result	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
 		.rlen	= 8,
-	}, { /* Vary the keylength... */	
+	}, { /* Vary the keylength... */
 		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
 			    0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f },
 		.klen	= 16,
@@ -1352,9 +1358,9 @@
 		.key	= { 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87,
 			    0x78, 0x69, 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f,
 			    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
-			    0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f, 
-			    0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76, 
-			    0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e, 
+			    0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd, 0x3b, 0x2f,
+			    0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76,
+			    0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e,
 			    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
 		.klen	= 56,
 		.input	= { 0xc0, 0x45, 0x04, 0x01, 0x2e, 0x4e, 0x1f, 0x53 },
@@ -1369,7 +1375,7 @@
 		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
 			    0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
 		.klen	= 16,
-		.iv	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },		
+		.iv	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
 		.input	= { 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
 			    0x4e, 0x6f, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
 			    0x68, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20,
@@ -1388,7 +1394,7 @@
 		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
 			    0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87 },
 		.klen	= 16,
-		.iv	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },		
+		.iv	= { 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 },
 		.input	= { 0x6b, 0x77, 0xb4, 0xd6, 0x30, 0x06, 0xde, 0xe6,
 			    0x05, 0xb1, 0x56, 0xe2, 0x74, 0x03, 0x97, 0x93,
 			    0x58, 0xde, 0xb9, 0xe7, 0x15, 0x46, 0x16, 0xd9,
@@ -1490,7 +1496,7 @@
 		.key	= { [0 ... 15] = 0x00 },
 		.klen	= 16,
 		.iv	= { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
-			    0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },		
+			    0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
 		.input	= { [0 ... 15] = 0x00 },
 		.ilen	= 16,
 		.result	= { 0xd4, 0x91, 0xdb, 0x16, 0xe7, 0xb1, 0xc3, 0x9e,
@@ -1528,7 +1534,7 @@
 		.klen	= 16,
 		.iv	= { [0 ... 15] = 0x00 },
 		.input	= { 0x9f, 0x58, 0x9f, 0x5c, 0xf6, 0x12, 0x2c, 0x32,
-			    0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },		  
+			    0xb6, 0xbf, 0xec, 0x2f, 0x2a, 0xe8, 0xc3, 0x5a },
 		.ilen	= 16,
 		.result	= { [0 ... 15] = 0x00 },
 		.rlen	= 16,
@@ -1578,8 +1584,7 @@
 #define TNEPRES_ENC_TEST_VECTORS	4
 #define TNEPRES_DEC_TEST_VECTORS	4
 
-static struct cipher_testvec serpent_enc_tv_template[] = 
-{
+static struct cipher_testvec serpent_enc_tv_template[] = {
 	{
 		.input	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
 			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
@@ -1620,8 +1625,7 @@
 	},
 };
 
-static struct cipher_testvec tnepres_enc_tv_template[] = 
-{
+static struct cipher_testvec tnepres_enc_tv_template[] = {
 	{ /* KeySize=128, PT=0, I=1 */
 		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
@@ -1629,7 +1633,7 @@
 			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
 		.klen   = 16,
 		.ilen	= 16,
-		.result	= { 0x49, 0xaf, 0xbf, 0xad, 0x9d, 0x5a, 0x34, 0x05, 
+		.result	= { 0x49, 0xaf, 0xbf, 0xad, 0x9d, 0x5a, 0x34, 0x05,
 			    0x2c, 0xd8, 0xff, 0xa5, 0x98, 0x6b, 0xd2, 0xdd },
 		.rlen	= 16,
 	}, { /* KeySize=192, PT=0, I=1 */
@@ -1640,7 +1644,7 @@
 		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
 		.ilen	= 16,
-		.result	= { 0xe7, 0x8e, 0x54, 0x02, 0xc7, 0x19, 0x55, 0x68, 
+		.result	= { 0xe7, 0x8e, 0x54, 0x02, 0xc7, 0x19, 0x55, 0x68,
 			    0xac, 0x36, 0x78, 0xf7, 0xa3, 0xf6, 0x0c, 0x66 },
 		.rlen	= 16,
 	}, { /* KeySize=256, PT=0, I=1 */
@@ -1652,7 +1656,7 @@
 		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
 		.ilen	= 16,
-		.result	= { 0xab, 0xed, 0x96, 0xe7, 0x66, 0xbf, 0x28, 0xcb, 
+		.result	= { 0xab, 0xed, 0x96, 0xe7, 0x66, 0xbf, 0x28, 0xcb,
 			    0xc0, 0xeb, 0xd2, 0x1a, 0x82, 0xef, 0x08, 0x19 },
 		.rlen	= 16,
 	}, { /* KeySize=256, I=257 */
@@ -1664,15 +1668,14 @@
 		.input	= { 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
 			    0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 },
 		.ilen	= 16,
-		.result	= { 0x5c, 0xe7, 0x1c, 0x70, 0xd2, 0x88, 0x2e, 0x5b, 
+		.result	= { 0x5c, 0xe7, 0x1c, 0x70, 0xd2, 0x88, 0x2e, 0x5b,
 			    0xb8, 0x32, 0xe4, 0x33, 0xf8, 0x9f, 0x26, 0xde },
 		.rlen	= 16,
 	},
 };
 
 
-static struct cipher_testvec serpent_dec_tv_template[] = 
-{
+static struct cipher_testvec serpent_dec_tv_template[] = {
 	{
 		.input	= { 0x12, 0x07, 0xfc, 0xce, 0x9b, 0xd0, 0xd6, 0x47,
 			    0x6a, 0xe9, 0x8f, 0xbe, 0xd1, 0x43, 0xa0, 0xe2 },
@@ -1713,8 +1716,7 @@
 	},
 };
 
-static struct cipher_testvec tnepres_dec_tv_template[] =
-{
+static struct cipher_testvec tnepres_dec_tv_template[] = {
 	{
 		.input	= { 0x41, 0xcc, 0x6b, 0x31, 0x59, 0x31, 0x45, 0x97,
 			    0x6d, 0x6f, 0xbb, 0x38, 0x4b, 0x37, 0x21, 0x28 },
@@ -1726,7 +1728,7 @@
 		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
 			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
 		.klen	= 16,
-		.input	= { 0xea, 0xf4, 0xd7, 0xfc, 0xd8, 0x01, 0x34, 0x47, 
+		.input	= { 0xea, 0xf4, 0xd7, 0xfc, 0xd8, 0x01, 0x34, 0x47,
 			    0x81, 0x45, 0x0b, 0xfa, 0x0c, 0xd6, 0xad, 0x6e },
 		.ilen	= 16,
 		.result	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
@@ -1738,7 +1740,7 @@
 			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
 			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
 		.klen	= 32,
-		.input	= { 0x64, 0xa9, 0x1a, 0x37, 0xed, 0x9f, 0xe7, 0x49, 
+		.input	= { 0x64, 0xa9, 0x1a, 0x37, 0xed, 0x9f, 0xe7, 0x49,
 			    0xa8, 0x4e, 0x76, 0xd6, 0xf5, 0x0d, 0x78, 0xee },
 		.ilen	= 16,
 		.result	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
@@ -1747,7 +1749,7 @@
 	}, { /* KeySize=128, I=121 */
 		.key	= { [15] = 0x80 },
 		.klen	= 16,
-		.input	= { 0x3d, 0xda, 0xbf, 0xc0, 0x06, 0xda, 0xab, 0x06, 
+		.input	= { 0x3d, 0xda, 0xbf, 0xc0, 0x06, 0xda, 0xab, 0x06,
 			    0x46, 0x2a, 0xf4, 0xef, 0x81, 0x54, 0x4e, 0x26 },
 		.ilen	= 16,
 		.result	= { [0 ... 15] = 0x00 },
@@ -1760,58 +1762,56 @@
 #define CAST6_ENC_TEST_VECTORS	3
 #define CAST6_DEC_TEST_VECTORS  3
 
-static struct cipher_testvec cast6_enc_tv_template[] = 
-{
+static struct cipher_testvec cast6_enc_tv_template[] = {
 	{
-		.key	= { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c, 
+		.key	= { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
 			    0x0a, 0xf7, 0x56, 0x47, 0xf2, 0x9f, 0x61, 0x5d },
 		.klen	= 16,
 		.input	= { [0 ... 15] = 0x00 },
 		.ilen	= 16,
-		.result	= { 0xc8, 0x42, 0xa0, 0x89, 0x72, 0xb4, 0x3d, 0x20, 
+		.result	= { 0xc8, 0x42, 0xa0, 0x89, 0x72, 0xb4, 0x3d, 0x20,
 			    0x83, 0x6c, 0x91, 0xd1, 0xb7, 0x53, 0x0f, 0x6b },
 		.rlen	= 16,
 	}, {
-		.key	= { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c, 
-			    0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98, 
+		.key	= { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
+			    0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98,
 			    0xba, 0xc7, 0x7a, 0x77, 0x17, 0x94, 0x28, 0x63 },
 		.klen	= 24,
 		.input	= { [0 ... 15] = 0x00 },
 		.ilen	= 16,
-		.result	= { 0x1b, 0x38, 0x6c, 0x02, 0x10, 0xdc, 0xad, 0xcb, 
+		.result	= { 0x1b, 0x38, 0x6c, 0x02, 0x10, 0xdc, 0xad, 0xcb,
 			    0xdd, 0x0e, 0x41, 0xaa, 0x08, 0xa7, 0xa7, 0xe8 },
 		.rlen	= 16,
 	}, {
 		.key	= { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
 			    0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98,
 			    0x8d, 0x7c, 0x47, 0xce, 0x26, 0x49, 0x08, 0x46,
-			    0x1c, 0xc1, 0xb5, 0x13, 0x7a, 0xe6, 0xb6, 0x04 },				  
+			    0x1c, 0xc1, 0xb5, 0x13, 0x7a, 0xe6, 0xb6, 0x04 },
 		.klen	= 32,
 		.input	= { [0 ... 15] = 0x00 },
 		.ilen	= 16,
-		.result	= { 0x4f, 0x6a, 0x20, 0x38, 0x28, 0x68, 0x97, 0xb9, 
+		.result	= { 0x4f, 0x6a, 0x20, 0x38, 0x28, 0x68, 0x97, 0xb9,
 			    0xc9, 0x87, 0x01, 0x36, 0x55, 0x33, 0x17, 0xfa },
 		.rlen	= 16,
 	},
 };
 
-static struct cipher_testvec cast6_dec_tv_template[] = 
-{
+static struct cipher_testvec cast6_dec_tv_template[] = {
 	{
-		.key	= { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c, 
+		.key	= { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
 			    0x0a, 0xf7, 0x56, 0x47, 0xf2, 0x9f, 0x61, 0x5d },
 		.klen	= 16,
-		.input	= { 0xc8, 0x42, 0xa0, 0x89, 0x72, 0xb4, 0x3d, 0x20, 
+		.input	= { 0xc8, 0x42, 0xa0, 0x89, 0x72, 0xb4, 0x3d, 0x20,
 			    0x83, 0x6c, 0x91, 0xd1, 0xb7, 0x53, 0x0f, 0x6b },
 		.ilen	= 16,
 		.result	= { [0 ... 15] = 0x00 },
 		.rlen	= 16,
 	}, {
-		.key	= { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c, 
-			    0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98, 
+		.key	= { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
+			    0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98,
 			    0xba, 0xc7, 0x7a, 0x77, 0x17, 0x94, 0x28, 0x63 },
 		.klen	= 24,
-		.input	= { 0x1b, 0x38, 0x6c, 0x02, 0x10, 0xdc, 0xad, 0xcb, 
+		.input	= { 0x1b, 0x38, 0x6c, 0x02, 0x10, 0xdc, 0xad, 0xcb,
 			    0xdd, 0x0e, 0x41, 0xaa, 0x08, 0xa7, 0xa7, 0xe8 },
 		.ilen	= 16,
 		.result	= { [0 ... 15] = 0x00 },
@@ -1820,9 +1820,9 @@
 		.key	= { 0x23, 0x42, 0xbb, 0x9e, 0xfa, 0x38, 0x54, 0x2c,
 			    0xbe, 0xd0, 0xac, 0x83, 0x94, 0x0a, 0xc2, 0x98,
 			    0x8d, 0x7c, 0x47, 0xce, 0x26, 0x49, 0x08, 0x46,
-			    0x1c, 0xc1, 0xb5, 0x13, 0x7a, 0xe6, 0xb6, 0x04 },				  
+			    0x1c, 0xc1, 0xb5, 0x13, 0x7a, 0xe6, 0xb6, 0x04 },
 		.klen	= 32,
-		.input	= { 0x4f, 0x6a, 0x20, 0x38, 0x28, 0x68, 0x97, 0xb9, 
+		.input	= { 0x4f, 0x6a, 0x20, 0x38, 0x28, 0x68, 0x97, 0xb9,
 			    0xc9, 0x87, 0x01, 0x36, 0x55, 0x33, 0x17, 0xfa },
 		.ilen	= 16,
 		.result	= { [0 ... 15] = 0x00 },
@@ -1837,9 +1837,9 @@
 #define AES_ENC_TEST_VECTORS 3
 #define AES_DEC_TEST_VECTORS 3
 
-static struct cipher_testvec aes_enc_tv_template[] = { 
+static struct cipher_testvec aes_enc_tv_template[] = {
 	{ /* From FIPS-197 */
-		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
+		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
 			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
 		.klen	= 16,
 		.input	= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
@@ -1853,7 +1853,7 @@
 			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
 			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
 		.klen	= 24,
-		.input	= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 
+		.input	= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
 			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
 		.ilen	= 16,
 		.result	= { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
@@ -1865,7 +1865,7 @@
 			    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
 			    0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
 		.klen	= 32,
-		.input	= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 
+		.input	= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
 			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
 		.ilen	= 16,
 		.result	= { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
@@ -1874,9 +1874,9 @@
 	},
 };
 
-static struct cipher_testvec aes_dec_tv_template[] = { 
+static struct cipher_testvec aes_dec_tv_template[] = {
 	{ /* From FIPS-197 */
-		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
+		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
 			    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
 		.klen	= 16,
 		.input	= { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
@@ -1893,8 +1893,8 @@
 		.input	= { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
 			    0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 },
 		.ilen	= 16,
-		.result	= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 
-			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },  
+		.result	= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
 		.rlen	= 16,
 	}, {
 		.key	= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
@@ -1905,7 +1905,7 @@
 		.input	= { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
 			    0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 },
 		.ilen	= 16,
-		.result	= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 
+		.result	= { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
 			    0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
 		.rlen	= 16,
 	},
@@ -1915,8 +1915,7 @@
 #define CAST5_ENC_TEST_VECTORS	3
 #define CAST5_DEC_TEST_VECTORS	3
 
-static struct cipher_testvec cast5_enc_tv_template[] =
-{
+static struct cipher_testvec cast5_enc_tv_template[] = {
 	{
 		.key	= { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
 			    0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9a },
@@ -1943,8 +1942,7 @@
 	},
 };
 
-static struct cipher_testvec cast5_dec_tv_template[] =
-{
+static struct cipher_testvec cast5_dec_tv_template[] = {
 	{
 		.key	= { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
 			    0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9a },
@@ -1971,14 +1969,13 @@
 	},
 };
 
-/* 
- * ARC4 test vectors from OpenSSL 
+/*
+ * ARC4 test vectors from OpenSSL
  */
 #define ARC4_ENC_TEST_VECTORS	7
 #define ARC4_DEC_TEST_VECTORS	7
 
-static struct cipher_testvec arc4_enc_tv_template[] =
-{
+static struct cipher_testvec arc4_enc_tv_template[] = {
 	{
 		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
 		.klen	= 8,
@@ -2044,8 +2041,7 @@
 	},
 };
 
-static struct cipher_testvec arc4_dec_tv_template[] =
-{
+static struct cipher_testvec arc4_dec_tv_template[] = {
 	{
 		.key	= { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef },
 		.klen	= 8,
@@ -2111,14 +2107,13 @@
 	},
 };
 
-/* 
+/*
  * TEA test vectors
  */
 #define TEA_ENC_TEST_VECTORS	4
 #define TEA_DEC_TEST_VECTORS	4
 
-static struct cipher_testvec tea_enc_tv_template[] =
-{
+static struct cipher_testvec tea_enc_tv_template[] = {
 	{
 		.key    = { [0 ... 15] = 0x00 },
 		.klen	= 16,
@@ -2138,31 +2133,30 @@
 		.key	= { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
 			    0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
 		.klen	= 16,
-		.input	= { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74, 
+		.input	= { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
 			    0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
 		.ilen	= 16,
-		.result	= { 0xbe, 0x7a, 0xbb, 0x81, 0x95, 0x2d, 0x1f, 0x1e, 
+		.result	= { 0xbe, 0x7a, 0xbb, 0x81, 0x95, 0x2d, 0x1f, 0x1e,
 			    0xdd, 0x89, 0xa1, 0x25, 0x04, 0x21, 0xdf, 0x95 },
 		.rlen	= 16,
 	}, {
 		.key	= { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
 			    0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
 		.klen	= 16,
-		.input	= { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67, 
-			    0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 
-			    0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72, 
+		.input	= { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+			    0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+			    0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
 			    0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
 		.ilen	= 32,
-		.result	= { 0xe0, 0x4d, 0x5d, 0x3c, 0xb7, 0x8c, 0x36, 0x47, 
-			    0x94, 0x18, 0x95, 0x91, 0xa9, 0xfc, 0x49, 0xf8, 
-			    0x44, 0xd1, 0x2d, 0xc2, 0x99, 0xb8, 0x08, 0x2a, 
+		.result	= { 0xe0, 0x4d, 0x5d, 0x3c, 0xb7, 0x8c, 0x36, 0x47,
+			    0x94, 0x18, 0x95, 0x91, 0xa9, 0xfc, 0x49, 0xf8,
+			    0x44, 0xd1, 0x2d, 0xc2, 0x99, 0xb8, 0x08, 0x2a,
 			    0x07, 0x89, 0x73, 0xc2, 0x45, 0x92, 0xc6, 0x90 },
 		.rlen	= 32,
 	}
 };
 
-static struct cipher_testvec tea_dec_tv_template[] =
-{
+static struct cipher_testvec tea_dec_tv_template[] = {
 	{
 		.key    = { [0 ... 15] = 0x00 },
 		.klen	= 16,
@@ -2183,9 +2177,9 @@
 			    0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
 		.klen	= 16,
 		.input	= { 0xbe, 0x7a, 0xbb, 0x81, 0x95, 0x2d, 0x1f, 0x1e,
-                            0xdd, 0x89, 0xa1, 0x25, 0x04, 0x21, 0xdf, 0x95 },
-                .ilen   = 16,
-		.result	= { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74, 
+			    0xdd, 0x89, 0xa1, 0x25, 0x04, 0x21, 0xdf, 0x95 },
+		.ilen   = 16,
+		.result	= { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
 			    0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
 		.rlen	= 16,
 	}, {
@@ -2193,26 +2187,25 @@
 			    0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
 		.klen	= 16,
 		.input	= { 0xe0, 0x4d, 0x5d, 0x3c, 0xb7, 0x8c, 0x36, 0x47,
-                            0x94, 0x18, 0x95, 0x91, 0xa9, 0xfc, 0x49, 0xf8,
-                            0x44, 0xd1, 0x2d, 0xc2, 0x99, 0xb8, 0x08, 0x2a,
-                            0x07, 0x89, 0x73, 0xc2, 0x45, 0x92, 0xc6, 0x90 },
+			    0x94, 0x18, 0x95, 0x91, 0xa9, 0xfc, 0x49, 0xf8,
+			    0x44, 0xd1, 0x2d, 0xc2, 0x99, 0xb8, 0x08, 0x2a,
+			    0x07, 0x89, 0x73, 0xc2, 0x45, 0x92, 0xc6, 0x90 },
 		.ilen	= 32,
-		.result	= { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67, 
-			    0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 
-			    0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72, 
+		.result	= { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+			    0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+			    0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
 			    0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
 		.rlen	= 32,
 	}
 };
 
-/* 
- * XTEA test vectors 
+/*
+ * XTEA test vectors
  */
 #define XTEA_ENC_TEST_VECTORS	4
 #define XTEA_DEC_TEST_VECTORS	4
 
-static struct cipher_testvec xtea_enc_tv_template[] =
-{
+static struct cipher_testvec xtea_enc_tv_template[] = {
 	{
 		.key    = { [0 ... 15] = 0x00 },
 		.klen	= 16,
@@ -2232,31 +2225,30 @@
 		.key	= { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
 			    0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
 		.klen	= 16,
-		.input	= { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74, 
+		.input	= { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
 			    0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
 		.ilen	= 16,
-		.result	= { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea, 
+		.result	= { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea,
 			    0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c },
 		.rlen	= 16,
 	}, {
 		.key	= { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
 			    0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
 		.klen	= 16,
-		.input	= { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67, 
-			    0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 
-			    0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72, 
+		.input	= { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+			    0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+			    0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
 			    0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
 		.ilen	= 32,
-		.result	= { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1, 
-			    0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4, 
-			    0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f, 
+		.result	= { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1,
+			    0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4,
+			    0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f,
 			    0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 },
 		.rlen	= 32,
 	}
 };
 
-static struct cipher_testvec xtea_dec_tv_template[] =
-{
+static struct cipher_testvec xtea_dec_tv_template[] = {
 	{
 		.key    = { [0 ... 15] = 0x00 },
 		.klen	= 16,
@@ -2276,24 +2268,24 @@
 		.key	= { 0x09, 0x65, 0x43, 0x11, 0x66, 0x44, 0x39, 0x25,
 			    0x51, 0x3a, 0x16, 0x10, 0x0a, 0x08, 0x12, 0x6e },
 		.klen	= 16,
-		.input	= { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea, 
+		.input	= { 0xe2, 0x04, 0xdb, 0xf2, 0x89, 0x85, 0x9e, 0xea,
 			    0x61, 0x35, 0xaa, 0xed, 0xb5, 0xcb, 0x71, 0x2c },
 		.ilen	= 16,
-		.result	= { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74, 
+		.result	= { 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x5f, 0x74,
 			    0x65, 0x73, 0x74, 0x5f, 0x76, 0x65, 0x63, 0x74 },
 		.rlen	= 16,
 	}, {
 		.key	= { 0x4d, 0x76, 0x32, 0x17, 0x05, 0x3f, 0x75, 0x2c,
 			    0x5d, 0x04, 0x16, 0x36, 0x15, 0x72, 0x63, 0x2f },
 		.klen	= 16,
-		.input	= { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1, 
-			    0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4, 
-			    0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f, 
+		.input	= { 0x0b, 0x03, 0xcd, 0x8a, 0xbe, 0x95, 0xfd, 0xb1,
+			    0xc1, 0x44, 0x91, 0x0b, 0xa5, 0xc9, 0x1b, 0xb4,
+			    0xa9, 0xda, 0x1e, 0x9e, 0xb1, 0x3e, 0x2a, 0x8f,
 			    0xea, 0xa5, 0x6a, 0x85, 0xd1, 0xf4, 0xa8, 0xa5 },
 		.ilen	= 32,
-		.result	= { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67, 
-			    0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 
-			    0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72, 
+		.result	= { 0x54, 0x65, 0x61, 0x20, 0x69, 0x73, 0x20, 0x67,
+			    0x6f, 0x6f, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20,
+			    0x79, 0x6f, 0x75, 0x21, 0x21, 0x21, 0x20, 0x72,
 			    0x65, 0x61, 0x6c, 0x6c, 0x79, 0x21, 0x21, 0x21 },
 		.rlen	= 32,
 	}
@@ -2305,9 +2297,9 @@
 #define KHAZAD_ENC_TEST_VECTORS 5
 #define KHAZAD_DEC_TEST_VECTORS 5
 
-static struct cipher_testvec khazad_enc_tv_template[] = { 
-	{ 
-		.key	= { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+static struct cipher_testvec khazad_enc_tv_template[] = {
+	{
+		.key	= { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
 		.klen	= 16,
 		.input	= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
@@ -2351,9 +2343,9 @@
 	},
 };
 
-static struct cipher_testvec khazad_dec_tv_template[] = { 
+static struct cipher_testvec khazad_dec_tv_template[] = {
 	{
-		.key	= { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+		.key	= { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 			    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
 		.klen	= 16,
 		.input	= { 0X49, 0Xa4, 0Xce, 0X32, 0Xac, 0X19, 0X0e, 0X3f },
@@ -2697,8 +2689,7 @@
  */
 #define MICHAEL_MIC_TEST_VECTORS 6
 
-static struct hash_testvec michael_mic_tv_template[] =
-{
+static struct hash_testvec michael_mic_tv_template[] = {
 	{
 		.key = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
 		.ksize = 8,
@@ -2743,4 +2734,88 @@
 	}
 };
 
+/*
+ * Cipher speed tests
+ */
+static struct cipher_speed aes_speed_template[] = {
+	{ .klen = 16, .blen = 16, },
+	{ .klen = 16, .blen = 64, },
+	{ .klen = 16, .blen = 256, },
+	{ .klen = 16, .blen = 1024, },
+	{ .klen = 16, .blen = 8192, },
+	{ .klen = 24, .blen = 16, },
+	{ .klen = 24, .blen = 64, },
+	{ .klen = 24, .blen = 256, },
+	{ .klen = 24, .blen = 1024, },
+	{ .klen = 24, .blen = 8192, },
+	{ .klen = 32, .blen = 16, },
+	{ .klen = 32, .blen = 64, },
+	{ .klen = 32, .blen = 256, },
+	{ .klen = 32, .blen = 1024, },
+	{ .klen = 32, .blen = 8192, },
+
+	/* End marker */
+	{  .klen = 0, .blen = 0, }
+};
+
+static struct cipher_speed des3_ede_speed_template[] = {
+	{ .klen = 24, .blen = 16, },
+	{ .klen = 24, .blen = 64, },
+	{ .klen = 24, .blen = 256, },
+	{ .klen = 24, .blen = 1024, },
+	{ .klen = 24, .blen = 8192, },
+
+	/* End marker */
+	{  .klen = 0, .blen = 0, }
+};
+
+static struct cipher_speed twofish_speed_template[] = {
+	{ .klen = 16, .blen = 16, },
+	{ .klen = 16, .blen = 64, },
+	{ .klen = 16, .blen = 256, },
+	{ .klen = 16, .blen = 1024, },
+	{ .klen = 16, .blen = 8192, },
+	{ .klen = 24, .blen = 16, },
+	{ .klen = 24, .blen = 64, },
+	{ .klen = 24, .blen = 256, },
+	{ .klen = 24, .blen = 1024, },
+	{ .klen = 24, .blen = 8192, },
+	{ .klen = 32, .blen = 16, },
+	{ .klen = 32, .blen = 64, },
+	{ .klen = 32, .blen = 256, },
+	{ .klen = 32, .blen = 1024, },
+	{ .klen = 32, .blen = 8192, },
+
+	/* End marker */
+	{  .klen = 0, .blen = 0, }
+};
+
+static struct cipher_speed blowfish_speed_template[] = {
+	/* Don't support blowfish keys > 256 bit in this test */
+	{ .klen = 8, .blen = 16, },
+	{ .klen = 8, .blen = 64, },
+	{ .klen = 8, .blen = 256, },
+	{ .klen = 8, .blen = 1024, },
+	{ .klen = 8, .blen = 8192, },
+	{ .klen = 32, .blen = 16, },
+	{ .klen = 32, .blen = 64, },
+	{ .klen = 32, .blen = 256, },
+	{ .klen = 32, .blen = 1024, },
+	{ .klen = 32, .blen = 8192, },
+
+	/* End marker */
+	{  .klen = 0, .blen = 0, }
+};
+
+static struct cipher_speed des_speed_template[] = {
+	{ .klen = 8, .blen = 16, },
+	{ .klen = 8, .blen = 64, },
+	{ .klen = 8, .blen = 256, },
+	{ .klen = 8, .blen = 1024, },
+	{ .klen = 8, .blen = 8192, },
+
+	/* End marker */
+	{  .klen = 0, .blen = 0, }
+};
+
 #endif	/* _CRYPTO_TCRYPT_H */
diff --git a/drivers/Kconfig b/drivers/Kconfig
index ed41d90..aed4a9b 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -58,4 +58,6 @@
 
 source "drivers/infiniband/Kconfig"
 
+source "drivers/sn/Kconfig"
+
 endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 15681de..3167be5 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -61,6 +61,6 @@
 obj-$(CONFIG_CPU_FREQ)		+= cpufreq/
 obj-$(CONFIG_MMC)		+= mmc/
 obj-$(CONFIG_INFINIBAND)	+= infiniband/
-obj-$(CONFIG_BLK_DEV_SGIIOC4)	+= sn/
+obj-$(CONFIG_SGI_IOC4)		+= sn/
 obj-y				+= firmware/
 obj-$(CONFIG_CRYPTO)		+= crypto/
diff --git a/drivers/acorn/char/pcf8583.c b/drivers/acorn/char/pcf8583.c
index ad7ae7a..141b4c2 100644
--- a/drivers/acorn/char/pcf8583.c
+++ b/drivers/acorn/char/pcf8583.c
@@ -26,11 +26,8 @@
 
 static struct i2c_client_address_data addr_data = {
 	.normal_i2c		= normal_addr,
-	.normal_i2c_range	= ignore,
 	.probe			= ignore,
-	.probe_range		= ignore,
 	.ignore			= ignore,
-	.ignore_range		= ignore,
 	.force			= ignore,
 };
 
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 670fdb5..86c5252 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -55,7 +55,7 @@
 
 config ACPI_SLEEP
 	bool "Sleep States (EXPERIMENTAL)"
-	depends on X86
+	depends on X86 && (!SMP || SUSPEND_SMP)
 	depends on EXPERIMENTAL && PM
 	default y
 	---help---
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 8093f2e..8dbf802 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -435,6 +435,7 @@
 		/* Interrupt Line values above 0xF are forbidden */
 		if (dev->irq >= 0 && (dev->irq <= 0xF)) {
 			printk(" - using IRQ %d\n", dev->irq);
+			acpi_register_gsi(dev->irq, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW);
 			return_VALUE(0);
 		}
 		else {
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index ff64d33..c9d671c 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -171,7 +171,7 @@
 	int			sleep_ticks = 0;
 	u32			t1, t2 = 0;
 
-	pr = processors[_smp_processor_id()];
+	pr = processors[raw_smp_processor_id()];
 	if (!pr)
 		return;
 
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 119c940..e858855 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -65,14 +65,14 @@
 {
 	struct acpi_device *device = to_acpi_device(kobj);
 	struct acpi_device_attribute *attribute = to_handle_attr(attr);
-	return attribute->show ? attribute->show(device, buf) : 0;
+	return attribute->show ? attribute->show(device, buf) : -EIO;
 }
 static ssize_t acpi_device_attr_store(struct kobject *kobj,
 		struct attribute *attr, const char *buf, size_t len)
 {
 	struct acpi_device *device = to_acpi_device(kobj);
 	struct acpi_device_attribute *attribute = to_handle_attr(attr);
-	return attribute->store ? attribute->store(device, buf, len) : len;
+	return attribute->store ? attribute->store(device, buf, len) : -EIO;
 }
 
 static struct sysfs_ops acpi_device_sysfs_ops = {
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index a47928a2..66d9c46 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -1,7 +1,7 @@
 # Makefile for the Linux device tree
 
-obj-y			:= core.o sys.o bus.o \
-			   driver.o class.o class_simple.o platform.o \
+obj-y			:= core.o sys.o bus.o dd.o \
+			   driver.o class.o platform.o \
 			   cpu.o firmware.o init.o map.o dmapool.o \
 			   attribute_container.o transport_class.o
 obj-y			+= power/
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 8d1e8bd..645f626 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -4,6 +4,8 @@
 extern int bus_add_driver(struct device_driver *);
 extern void bus_remove_driver(struct device_driver *);
 
+extern void driver_detach(struct device_driver * drv);
+
 static inline struct class_device *to_class_dev(struct kobject *obj)
 {
 	return container_of(obj, struct class_device, kobj);
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 3cb04bb..c3fac7f 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -17,9 +17,6 @@
 #include "base.h"
 #include "power/power.h"
 
-#define to_dev(node) container_of(node, struct device, bus_list)
-#define to_drv(node) container_of(node, struct device_driver, kobj.entry)
-
 #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr)
 #define to_bus(obj) container_of(obj, struct bus_type, subsys.kset.kobj)
 
@@ -36,7 +33,7 @@
 {
 	struct driver_attribute * drv_attr = to_drv_attr(attr);
 	struct device_driver * drv = to_driver(kobj);
-	ssize_t ret = 0;
+	ssize_t ret = -EIO;
 
 	if (drv_attr->show)
 		ret = drv_attr->show(drv, buf);
@@ -49,7 +46,7 @@
 {
 	struct driver_attribute * drv_attr = to_drv_attr(attr);
 	struct device_driver * drv = to_driver(kobj);
-	ssize_t ret = 0;
+	ssize_t ret = -EIO;
 
 	if (drv_attr->store)
 		ret = drv_attr->store(drv, buf, count);
@@ -135,50 +132,11 @@
 
 decl_subsys(bus, &ktype_bus, NULL);
 
-static int __bus_for_each_dev(struct bus_type *bus, struct device *start,
-			      void *data, int (*fn)(struct device *, void *))
+
+static struct device * next_device(struct klist_iter * i)
 {
-	struct list_head *head;
-	struct device *dev;
-	int error = 0;
-
-	if (!(bus = get_bus(bus)))
-		return -EINVAL;
-
-	head = &bus->devices.list;
-	dev = list_prepare_entry(start, head, bus_list);
-	list_for_each_entry_continue(dev, head, bus_list) {
-		get_device(dev);
-		error = fn(dev, data);
-		put_device(dev);
-		if (error)
-			break;
-	}
-	put_bus(bus);
-	return error;
-}
-
-static int __bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
-			      void * data, int (*fn)(struct device_driver *, void *))
-{
-	struct list_head *head;
-	struct device_driver *drv;
-	int error = 0;
-
-	if (!(bus = get_bus(bus)))
-		return -EINVAL;
-
-	head = &bus->drivers.list;
-	drv = list_prepare_entry(start, head, kobj.entry);
-	list_for_each_entry_continue(drv, head, kobj.entry) {
-		get_driver(drv);
-		error = fn(drv, data);
-		put_driver(drv);
-		if (error)
-			break;
-	}
-	put_bus(bus);
-	return error;
+	struct klist_node * n = klist_next(i);
+	return n ? container_of(n, struct device, knode_bus) : NULL;
 }
 
 /**
@@ -204,12 +162,27 @@
 int bus_for_each_dev(struct bus_type * bus, struct device * start,
 		     void * data, int (*fn)(struct device *, void *))
 {
-	int ret;
+	struct klist_iter i;
+	struct device * dev;
+	int error = 0;
 
-	down_read(&bus->subsys.rwsem);
-	ret = __bus_for_each_dev(bus, start, data, fn);
-	up_read(&bus->subsys.rwsem);
-	return ret;
+	if (!bus)
+		return -EINVAL;
+
+	klist_iter_init_node(&bus->klist_devices, &i,
+			     (start ? &start->knode_bus : NULL));
+	while ((dev = next_device(&i)) && !error)
+		error = fn(dev, data);
+	klist_iter_exit(&i);
+	return error;
+}
+
+
+
+static struct device_driver * next_driver(struct klist_iter * i)
+{
+	struct klist_node * n = klist_next(i);
+	return n ? container_of(n, struct device_driver, knode_bus) : NULL;
 }
 
 /**
@@ -235,179 +208,19 @@
 int bus_for_each_drv(struct bus_type * bus, struct device_driver * start,
 		     void * data, int (*fn)(struct device_driver *, void *))
 {
-	int ret;
+	struct klist_iter i;
+	struct device_driver * drv;
+	int error = 0;
 
-	down_read(&bus->subsys.rwsem);
-	ret = __bus_for_each_drv(bus, start, data, fn);
-	up_read(&bus->subsys.rwsem);
-	return ret;
-}
+	if (!bus)
+		return -EINVAL;
 
-/**
- *	device_bind_driver - bind a driver to one device.
- *	@dev:	device.
- *
- *	Allow manual attachment of a driver to a device.
- *	Caller must have already set @dev->driver.
- *
- *	Note that this does not modify the bus reference count
- *	nor take the bus's rwsem. Please verify those are accounted
- *	for before calling this. (It is ok to call with no other effort
- *	from a driver's probe() method.)
- */
-
-void device_bind_driver(struct device * dev)
-{
-	pr_debug("bound device '%s' to driver '%s'\n",
-		 dev->bus_id, dev->driver->name);
-	list_add_tail(&dev->driver_list, &dev->driver->devices);
-	sysfs_create_link(&dev->driver->kobj, &dev->kobj,
-			  kobject_name(&dev->kobj));
-	sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver");
-}
-
-
-/**
- *	driver_probe_device - attempt to bind device & driver.
- *	@drv:	driver.
- *	@dev:	device.
- *
- *	First, we call the bus's match function, if one present, which
- *	should compare the device IDs the driver supports with the
- *	device IDs of the device. Note we don't do this ourselves
- *	because we don't know the format of the ID structures, nor what
- *	is to be considered a match and what is not.
- *
- *	If we find a match, we call @drv->probe(@dev) if it exists, and
- *	call device_bind_driver() above.
- */
-int driver_probe_device(struct device_driver * drv, struct device * dev)
-{
-	if (drv->bus->match && !drv->bus->match(dev, drv))
-		return -ENODEV;
-
-	dev->driver = drv;
-	if (drv->probe) {
-		int error = drv->probe(dev);
-		if (error) {
-			dev->driver = NULL;
-			return error;
-		}
-	}
-
-	device_bind_driver(dev);
-	return 0;
-}
-
-
-/**
- *	device_attach - try to attach device to a driver.
- *	@dev:	device.
- *
- *	Walk the list of drivers that the bus has and call
- *	driver_probe_device() for each pair. If a compatible
- *	pair is found, break out and return.
- */
-int device_attach(struct device * dev)
-{
- 	struct bus_type * bus = dev->bus;
-	struct list_head * entry;
-	int error;
-
-	if (dev->driver) {
-		device_bind_driver(dev);
-		return 1;
-	}
-
-	if (bus->match) {
-		list_for_each(entry, &bus->drivers.list) {
-			struct device_driver * drv = to_drv(entry);
-			error = driver_probe_device(drv, dev);
-			if (!error)
-				/* success, driver matched */
-				return 1;
-			if (error != -ENODEV && error != -ENXIO)
-				/* driver matched but the probe failed */
-				printk(KERN_WARNING
-				    "%s: probe of %s failed with error %d\n",
-				    drv->name, dev->bus_id, error);
-		}
-	}
-
-	return 0;
-}
-
-
-/**
- *	driver_attach - try to bind driver to devices.
- *	@drv:	driver.
- *
- *	Walk the list of devices that the bus has on it and try to
- *	match the driver with each one.  If driver_probe_device()
- *	returns 0 and the @dev->driver is set, we've found a
- *	compatible pair.
- *
- *	Note that we ignore the -ENODEV error from driver_probe_device(),
- *	since it's perfectly valid for a driver not to bind to any devices.
- */
-void driver_attach(struct device_driver * drv)
-{
-	struct bus_type * bus = drv->bus;
-	struct list_head * entry;
-	int error;
-
-	if (!bus->match)
-		return;
-
-	list_for_each(entry, &bus->devices.list) {
-		struct device * dev = container_of(entry, struct device, bus_list);
-		if (!dev->driver) {
-			error = driver_probe_device(drv, dev);
-			if (error && (error != -ENODEV))
-				/* driver matched but the probe failed */
-				printk(KERN_WARNING
-				    "%s: probe of %s failed with error %d\n",
-				    drv->name, dev->bus_id, error);
-		}
-	}
-}
-
-
-/**
- *	device_release_driver - manually detach device from driver.
- *	@dev:	device.
- *
- *	Manually detach device from driver.
- *	Note that this is called without incrementing the bus
- *	reference count nor taking the bus's rwsem. Be sure that
- *	those are accounted for before calling this function.
- */
-
-void device_release_driver(struct device * dev)
-{
-	struct device_driver * drv = dev->driver;
-	if (drv) {
-		sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
-		sysfs_remove_link(&dev->kobj, "driver");
-		list_del_init(&dev->driver_list);
-		if (drv->remove)
-			drv->remove(dev);
-		dev->driver = NULL;
-	}
-}
-
-
-/**
- *	driver_detach - detach driver from all devices it controls.
- *	@drv:	driver.
- */
-
-static void driver_detach(struct device_driver * drv)
-{
-	while (!list_empty(&drv->devices)) {
-		struct device * dev = container_of(drv->devices.next, struct device, driver_list);
-		device_release_driver(dev);
-	}
+	klist_iter_init_node(&bus->klist_drivers, &i,
+			     start ? &start->knode_bus : NULL);
+	while ((drv = next_driver(&i)) && !error)
+		error = fn(drv, data);
+	klist_iter_exit(&i);
+	return error;
 }
 
 static int device_add_attrs(struct bus_type * bus, struct device * dev)
@@ -456,14 +269,14 @@
 	int error = 0;
 
 	if (bus) {
-		down_write(&dev->bus->subsys.rwsem);
 		pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id);
-		list_add_tail(&dev->bus_list, &dev->bus->devices.list);
 		device_attach(dev);
-		up_write(&dev->bus->subsys.rwsem);
-		device_add_attrs(bus, dev);
-		sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
-		sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus");
+		klist_add_tail(&bus->klist_devices, &dev->knode_bus);
+		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, "bus");
+		}
 	}
 	return error;
 }
@@ -483,11 +296,9 @@
 		sysfs_remove_link(&dev->kobj, "bus");
 		sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);
 		device_remove_attrs(dev->bus, dev);
-		down_write(&dev->bus->subsys.rwsem);
+		klist_remove(&dev->knode_bus);
 		pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id);
 		device_release_driver(dev);
-		list_del_init(&dev->bus_list);
-		up_write(&dev->bus->subsys.rwsem);
 		put_bus(dev->bus);
 	}
 }
@@ -547,9 +358,8 @@
 			return error;
 		}
 
-		down_write(&bus->subsys.rwsem);
 		driver_attach(drv);
-		up_write(&bus->subsys.rwsem);
+		klist_add_tail(&bus->klist_drivers, &drv->knode_bus);
 		module_add_driver(drv->owner, drv);
 
 		driver_add_attrs(bus, drv);
@@ -571,10 +381,9 @@
 {
 	if (drv->bus) {
 		driver_remove_attrs(drv->bus, drv);
-		down_write(&drv->bus->subsys.rwsem);
+		klist_remove(&drv->knode_bus);
 		pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
 		driver_detach(drv);
-		up_write(&drv->bus->subsys.rwsem);
 		module_remove_driver(drv);
 		kobject_unregister(&drv->kobj);
 		put_bus(drv->bus);
@@ -587,7 +396,7 @@
 {
 	int *count = data;
 
-	if (!dev->driver && device_attach(dev))
+	if (!dev->driver && (device_attach(dev) > 0))
 		(*count)++;
 
 	return 0;
@@ -607,9 +416,7 @@
 {
 	int count = 0;
 
-	down_write(&bus->subsys.rwsem);
-	__bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper);
-	up_write(&bus->subsys.rwsem);
+	bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper);
 
 	return count;
 }
@@ -710,6 +517,9 @@
 	retval = kset_register(&bus->drivers);
 	if (retval)
 		goto bus_drivers_fail;
+
+	klist_init(&bus->klist_devices);
+	klist_init(&bus->klist_drivers);
 	bus_add_attrs(bus);
 
 	pr_debug("bus type '%s' registered\n", bus->name);
@@ -749,12 +559,6 @@
 EXPORT_SYMBOL_GPL(bus_for_each_dev);
 EXPORT_SYMBOL_GPL(bus_for_each_drv);
 
-EXPORT_SYMBOL_GPL(driver_probe_device);
-EXPORT_SYMBOL_GPL(device_bind_driver);
-EXPORT_SYMBOL_GPL(device_release_driver);
-EXPORT_SYMBOL_GPL(device_attach);
-EXPORT_SYMBOL_GPL(driver_attach);
-
 EXPORT_SYMBOL_GPL(bus_add_device);
 EXPORT_SYMBOL_GPL(bus_remove_device);
 EXPORT_SYMBOL_GPL(bus_register);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index d2a2f8f..479c125 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/string.h>
 #include <linux/kdev_t.h>
+#include <linux/err.h>
 #include "base.h"
 
 #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
@@ -26,7 +27,7 @@
 {
 	struct class_attribute * class_attr = to_class_attr(attr);
 	struct class * dc = to_class(kobj);
-	ssize_t ret = 0;
+	ssize_t ret = -EIO;
 
 	if (class_attr->show)
 		ret = class_attr->show(dc, buf);
@@ -39,7 +40,7 @@
 {
 	struct class_attribute * class_attr = to_class_attr(attr);
 	struct class * dc = to_class(kobj);
-	ssize_t ret = 0;
+	ssize_t ret = -EIO;
 
 	if (class_attr->store)
 		ret = class_attr->store(dc, buf, count);
@@ -162,6 +163,69 @@
 	subsystem_unregister(&cls->subsys);
 }
 
+static void class_create_release(struct class *cls)
+{
+	kfree(cls);
+}
+
+static void class_device_create_release(struct class_device *class_dev)
+{
+	kfree(class_dev);
+}
+
+/**
+ * class_create - create a struct class structure
+ * @owner: pointer to the module that is to "own" this struct class
+ * @name: pointer to a string for the name of this class.
+ *
+ * This is used to create a struct class pointer that can then be used
+ * in calls to class_device_create().
+ *
+ * Note, the pointer created here is to be destroyed when finished by
+ * making a call to class_destroy().
+ */
+struct class *class_create(struct module *owner, char *name)
+{
+	struct class *cls;
+	int retval;
+
+	cls = kmalloc(sizeof(struct class), GFP_KERNEL);
+	if (!cls) {
+		retval = -ENOMEM;
+		goto error;
+	}
+	memset(cls, 0x00, sizeof(struct class));
+
+	cls->name = name;
+	cls->owner = owner;
+	cls->class_release = class_create_release;
+	cls->release = class_device_create_release;
+
+	retval = class_register(cls);
+	if (retval)
+		goto error;
+
+	return cls;
+
+error:
+	kfree(cls);
+	return ERR_PTR(retval);
+}
+
+/**
+ * class_destroy - destroys a struct class structure
+ * @cs: pointer to the struct class that is to be destroyed
+ *
+ * Note, the pointer to be destroyed must have been created with a call
+ * to class_create().
+ */
+void class_destroy(struct class *cls)
+{
+	if ((cls == NULL) || (IS_ERR(cls)))
+		return;
+
+	class_unregister(cls);
+}
 
 /* Class Device Stuff */
 
@@ -262,7 +326,7 @@
 	return 0;
 }
 
-static char *class_hotplug_name(struct kset *kset, struct kobject *kobj)
+static const char *class_hotplug_name(struct kset *kset, struct kobject *kobj)
 {
 	struct class_device *class_dev = to_class_dev(kobj);
 
@@ -375,7 +439,6 @@
 {
 	return print_dev_t(buf, class_dev->devt);
 }
-static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
 
 void class_device_initialize(struct class_device *class_dev)
 {
@@ -412,7 +475,31 @@
 	if ((error = kobject_add(&class_dev->kobj)))
 		goto register_done;
 
-	/* now take care of our own registration */
+	/* add the needed attributes to this device */
+	if (MAJOR(class_dev->devt)) {
+		struct class_device_attribute *attr;
+		attr = kmalloc(sizeof(*attr), GFP_KERNEL);
+		if (!attr) {
+			error = -ENOMEM;
+			kobject_del(&class_dev->kobj);
+			goto register_done;
+		}
+		memset(attr, sizeof(*attr), 0x00);
+		attr->attr.name = "dev";
+		attr->attr.mode = S_IRUGO;
+		attr->attr.owner = parent->owner;
+		attr->show = show_dev;
+		attr->store = NULL;
+		class_device_create_file(class_dev, attr);
+		class_dev->devt_attr = attr;
+	}
+
+	class_device_add_attrs(class_dev);
+	if (class_dev->dev)
+		sysfs_create_link(&class_dev->kobj,
+				  &class_dev->dev->kobj, "device");
+
+	/* notify any interfaces this device is now here */
 	if (parent) {
 		down(&parent->sem);
 		list_add_tail(&class_dev->node, &parent->children);
@@ -421,16 +508,8 @@
 				class_intf->add(class_dev);
 		up(&parent->sem);
 	}
-
-	if (MAJOR(class_dev->devt))
-		class_device_create_file(class_dev, &class_device_attr_dev);
-
-	class_device_add_attrs(class_dev);
-	if (class_dev->dev)
-		sysfs_create_link(&class_dev->kobj,
-				  &class_dev->dev->kobj, "device");
-
 	kobject_hotplug(&class_dev->kobj, KOBJ_ADD);
+
  register_done:
 	if (error && parent)
 		class_put(parent);
@@ -444,6 +523,58 @@
 	return class_device_add(class_dev);
 }
 
+/**
+ * class_device_create - creates a class device and registers it with sysfs
+ * @cs: pointer to the struct class that this device should be registered to.
+ * @dev: the dev_t for the char device to be added.
+ * @device: a pointer to a struct device that is assiociated with this class device.
+ * @fmt: string for the class device's name
+ *
+ * This function can be used by char device classes.  A struct
+ * class_device will be created in sysfs, registered to the specified
+ * class.  A "dev" file will be created, showing the dev_t for the
+ * device.  The pointer to the struct class_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 class_device *class_device_create(struct class *cls, dev_t devt,
+					 struct device *device, char *fmt, ...)
+{
+	va_list args;
+	struct class_device *class_dev = NULL;
+	int retval = -ENODEV;
+
+	if (cls == NULL || IS_ERR(cls))
+		goto error;
+
+	class_dev = kmalloc(sizeof(struct class_device), GFP_KERNEL);
+	if (!class_dev) {
+		retval = -ENOMEM;
+		goto error;
+	}
+	memset(class_dev, 0x00, sizeof(struct class_device));
+
+	class_dev->devt = devt;
+	class_dev->dev = device;
+	class_dev->class = cls;
+
+	va_start(args, fmt);
+	vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
+	va_end(args);
+	retval = class_device_register(class_dev);
+	if (retval)
+		goto error;
+
+	return class_dev;
+
+error:
+	kfree(class_dev);
+	return ERR_PTR(retval);
+}
+
 void class_device_del(struct class_device *class_dev)
 {
 	struct class * parent = class_dev->class;
@@ -460,6 +591,11 @@
 
 	if (class_dev->dev)
 		sysfs_remove_link(&class_dev->kobj, "device");
+	if (class_dev->devt_attr) {
+		class_device_remove_file(class_dev, class_dev->devt_attr);
+		kfree(class_dev->devt_attr);
+		class_dev->devt_attr = NULL;
+	}
 	class_device_remove_attrs(class_dev);
 
 	kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE);
@@ -477,6 +613,32 @@
 	class_device_put(class_dev);
 }
 
+/**
+ * class_device_destroy - removes a class device that was created with class_device_create()
+ * @cls: 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 class_device_destroy(struct class *cls, dev_t devt)
+{
+	struct class_device *class_dev = NULL;
+	struct class_device *class_dev_tmp;
+
+	down(&cls->sem);
+	list_for_each_entry(class_dev_tmp, &cls->children, node) {
+		if (class_dev_tmp->devt == devt) {
+			class_dev = class_dev_tmp;
+			break;
+		}
+	}
+	up(&cls->sem);
+
+	if (class_dev)
+		class_device_unregister(class_dev);
+}
+
 int class_device_rename(struct class_device *class_dev, char *new_name)
 {
 	int error = 0;
@@ -576,6 +738,8 @@
 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);
 
 EXPORT_SYMBOL_GPL(class_device_register);
 EXPORT_SYMBOL_GPL(class_device_unregister);
@@ -584,6 +748,8 @@
 EXPORT_SYMBOL_GPL(class_device_del);
 EXPORT_SYMBOL_GPL(class_device_get);
 EXPORT_SYMBOL_GPL(class_device_put);
+EXPORT_SYMBOL_GPL(class_device_create);
+EXPORT_SYMBOL_GPL(class_device_destroy);
 EXPORT_SYMBOL_GPL(class_device_create_file);
 EXPORT_SYMBOL_GPL(class_device_remove_file);
 EXPORT_SYMBOL_GPL(class_device_create_bin_file);
diff --git a/drivers/base/class_simple.c b/drivers/base/class_simple.c
deleted file mode 100644
index 27699eb..0000000
--- a/drivers/base/class_simple.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * class_simple.c - a "simple" interface for classes for simple char devices.
- *
- * Copyright (c) 2003-2004 Greg Kroah-Hartman <greg@kroah.com>
- * Copyright (c) 2003-2004 IBM Corp.
- *
- * This file is released under the GPLv2
- *
- */
-
-#include <linux/config.h>
-#include <linux/device.h>
-#include <linux/err.h>
-
-struct class_simple {
-	struct class class;
-};
-#define to_class_simple(d) container_of(d, struct class_simple, class)
-
-struct simple_dev {
-	struct list_head node;
-	struct class_device class_dev;
-};
-#define to_simple_dev(d) container_of(d, struct simple_dev, class_dev)
-
-static LIST_HEAD(simple_dev_list);
-static DEFINE_SPINLOCK(simple_dev_list_lock);
-
-static void release_simple_dev(struct class_device *class_dev)
-{
-	struct simple_dev *s_dev = to_simple_dev(class_dev);
-	kfree(s_dev);
-}
-
-static void class_simple_release(struct class *class)
-{
-	struct class_simple *cs = to_class_simple(class);
-	kfree(cs);
-}
-
-/**
- * class_simple_create - create a struct class_simple structure
- * @owner: pointer to the module that is to "own" this struct class_simple
- * @name: pointer to a string for the name of this class.
- *
- * This is used to create a struct class_simple pointer that can then be used
- * in calls to class_simple_device_add().  This is used when you do not wish to
- * create a full blown class support for a type of char devices.
- *
- * Note, the pointer created here is to be destroyed when finished by making a
- * call to class_simple_destroy().
- */
-struct class_simple *class_simple_create(struct module *owner, char *name)
-{
-	struct class_simple *cs;
-	int retval;
-
-	cs = kmalloc(sizeof(*cs), GFP_KERNEL);
-	if (!cs) {
-		retval = -ENOMEM;
-		goto error;
-	}
-	memset(cs, 0x00, sizeof(*cs));
-
-	cs->class.name = name;
-	cs->class.class_release = class_simple_release;
-	cs->class.release = release_simple_dev;
-
-	retval = class_register(&cs->class);
-	if (retval)
-		goto error;
-
-	return cs;
-
-error:
-	kfree(cs);
-	return ERR_PTR(retval);
-}
-EXPORT_SYMBOL(class_simple_create);
-
-/**
- * class_simple_destroy - destroys a struct class_simple structure
- * @cs: pointer to the struct class_simple that is to be destroyed
- *
- * Note, the pointer to be destroyed must have been created with a call to
- * class_simple_create().
- */
-void class_simple_destroy(struct class_simple *cs)
-{
-	if ((cs == NULL) || (IS_ERR(cs)))
-		return;
-
-	class_unregister(&cs->class);
-}
-EXPORT_SYMBOL(class_simple_destroy);
-
-/**
- * class_simple_device_add - adds a class device to sysfs for a character driver
- * @cs: pointer to the struct class_simple that this device should be registered to.
- * @dev: the dev_t for the device to be added.
- * @device: a pointer to a struct device that is assiociated with this class device.
- * @fmt: string for the class device's name
- *
- * This function can be used by simple char device classes that do not
- * implement their own class device registration.  A struct class_device will
- * be created in sysfs, registered to the specified class.  A "dev" file will
- * be created, showing the dev_t for the device.  The pointer to the struct
- * class_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_simple passed to this function must have previously been
- * created with a call to class_simple_create().
- */
-struct class_device *class_simple_device_add(struct class_simple *cs, dev_t dev, struct device *device, const char *fmt, ...)
-{
-	va_list args;
-	struct simple_dev *s_dev = NULL;
-	int retval;
-
-	if ((cs == NULL) || (IS_ERR(cs))) {
-		retval = -ENODEV;
-		goto error;
-	}
-
-	s_dev = kmalloc(sizeof(*s_dev), GFP_KERNEL);
-	if (!s_dev) {
-		retval = -ENOMEM;
-		goto error;
-	}
-	memset(s_dev, 0x00, sizeof(*s_dev));
-
-	s_dev->class_dev.devt = dev;
-	s_dev->class_dev.dev = device;
-	s_dev->class_dev.class = &cs->class;
-
-	va_start(args, fmt);
-	vsnprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, fmt, args);
-	va_end(args);
-	retval = class_device_register(&s_dev->class_dev);
-	if (retval)
-		goto error;
-
-	spin_lock(&simple_dev_list_lock);
-	list_add(&s_dev->node, &simple_dev_list);
-	spin_unlock(&simple_dev_list_lock);
-
-	return &s_dev->class_dev;
-
-error:
-	kfree(s_dev);
-	return ERR_PTR(retval);
-}
-EXPORT_SYMBOL(class_simple_device_add);
-
-/**
- * class_simple_set_hotplug - set the hotplug callback in the embedded struct class
- * @cs: pointer to the struct class_simple to hold the pointer
- * @hotplug: function pointer to the hotplug function
- *
- * Implement and set a hotplug function to add environment variables specific to this
- * class on the hotplug event.
- */
-int class_simple_set_hotplug(struct class_simple *cs,
-	int (*hotplug)(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size))
-{
-	if ((cs == NULL) || (IS_ERR(cs)))
-		return -ENODEV;
-	cs->class.hotplug = hotplug;
-	return 0;
-}
-EXPORT_SYMBOL(class_simple_set_hotplug);
-
-/**
- * class_simple_device_remove - removes a class device that was created with class_simple_device_add()
- * @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_simple_add()
- */
-void class_simple_device_remove(dev_t dev)
-{
-	struct simple_dev *s_dev = NULL;
-	int found = 0;
-
-	spin_lock(&simple_dev_list_lock);
-	list_for_each_entry(s_dev, &simple_dev_list, node) {
-		if (s_dev->class_dev.devt == dev) {
-			found = 1;
-			break;
-		}
-	}
-	if (found) {
-		list_del(&s_dev->node);
-		spin_unlock(&simple_dev_list_lock);
-		class_device_unregister(&s_dev->class_dev);
-	} else {
-		spin_unlock(&simple_dev_list_lock);
-	}
-}
-EXPORT_SYMBOL(class_simple_device_remove);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index fbc2234..86d7975 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -36,10 +36,10 @@
 {
 	struct device_attribute * dev_attr = to_dev_attr(attr);
 	struct device * dev = to_dev(kobj);
-	ssize_t ret = 0;
+	ssize_t ret = -EIO;
 
 	if (dev_attr->show)
-		ret = dev_attr->show(dev, buf);
+		ret = dev_attr->show(dev, dev_attr, buf);
 	return ret;
 }
 
@@ -49,10 +49,10 @@
 {
 	struct device_attribute * dev_attr = to_dev_attr(attr);
 	struct device * dev = to_dev(kobj);
-	ssize_t ret = 0;
+	ssize_t ret = -EIO;
 
 	if (dev_attr->store)
-		ret = dev_attr->store(dev, buf, count);
+		ret = dev_attr->store(dev, dev_attr, buf, count);
 	return ret;
 }
 
@@ -102,7 +102,7 @@
 	return 0;
 }
 
-static char *dev_hotplug_name(struct kset *kset, struct kobject *kobj)
+static const char *dev_hotplug_name(struct kset *kset, struct kobject *kobj)
 {
 	struct device *dev = to_dev(kobj);
 
@@ -207,11 +207,9 @@
 {
 	kobj_set_kset_s(dev, devices_subsys);
 	kobject_init(&dev->kobj);
-	INIT_LIST_HEAD(&dev->node);
-	INIT_LIST_HEAD(&dev->children);
-	INIT_LIST_HEAD(&dev->driver_list);
-	INIT_LIST_HEAD(&dev->bus_list);
+	klist_init(&dev->klist_children);
 	INIT_LIST_HEAD(&dev->dma_pools);
+	init_MUTEX(&dev->sem);
 }
 
 /**
@@ -250,10 +248,8 @@
 		goto PMError;
 	if ((error = bus_add_device(dev)))
 		goto BusError;
-	down_write(&devices_subsys.rwsem);
 	if (parent)
-		list_add_tail(&dev->node, &parent->children);
-	up_write(&devices_subsys.rwsem);
+		klist_add_tail(&parent->klist_children, &dev->knode_parent);
 
 	/* notify platform of device entry */
 	if (platform_notify)
@@ -336,10 +332,8 @@
 {
 	struct device * parent = dev->parent;
 
-	down_write(&devices_subsys.rwsem);
 	if (parent)
-		list_del_init(&dev->node);
-	up_write(&devices_subsys.rwsem);
+		klist_remove(&dev->knode_parent);
 
 	/* Notify the platform of the removal, in case they
 	 * need to do anything...
@@ -373,6 +367,12 @@
 }
 
 
+static struct device * next_device(struct klist_iter * i)
+{
+	struct klist_node * n = klist_next(i);
+	return n ? container_of(n, struct device, knode_parent) : NULL;
+}
+
 /**
  *	device_for_each_child - device child iterator.
  *	@dev:	parent struct device.
@@ -385,39 +385,20 @@
  *	We check the return of @fn each time. If it returns anything
  *	other than 0, we break out and return that value.
  */
-int device_for_each_child(struct device * dev, void * data,
+int device_for_each_child(struct device * parent, void * data,
 		     int (*fn)(struct device *, void *))
 {
+	struct klist_iter i;
 	struct device * child;
 	int error = 0;
 
-	down_read(&devices_subsys.rwsem);
-	list_for_each_entry(child, &dev->children, node) {
-		if((error = fn(child, data)))
-			break;
-	}
-	up_read(&devices_subsys.rwsem);
+	klist_iter_init(&parent->klist_children, &i);
+	while ((child = next_device(&i)) && !error)
+		error = fn(child, data);
+	klist_iter_exit(&i);
 	return error;
 }
 
-/**
- *	device_find - locate device on a bus by name.
- *	@name:	name of the device.
- *	@bus:	bus to scan for the device.
- *
- *	Call kset_find_obj() to iterate over list of devices on
- *	a bus to find device by name. Return device if found.
- *
- *	Note that kset_find_obj increments device's reference count.
- */
-struct device *device_find(const char *name, struct bus_type *bus)
-{
-	struct kobject *k = kset_find_obj(&bus->devices, name);
-	if (k)
-		return to_dev(k);
-	return NULL;
-}
-
 int __init devices_init(void)
 {
 	return subsystem_register(&devices_subsys);
@@ -433,7 +414,6 @@
 EXPORT_SYMBOL_GPL(device_unregister);
 EXPORT_SYMBOL_GPL(get_device);
 EXPORT_SYMBOL_GPL(put_device);
-EXPORT_SYMBOL_GPL(device_find);
 
 EXPORT_SYMBOL_GPL(device_create_file);
 EXPORT_SYMBOL_GPL(device_remove_file);
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 6ef3069..b79badd 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -16,6 +16,11 @@
 EXPORT_SYMBOL(cpu_sysdev_class);
 
 #ifdef CONFIG_HOTPLUG_CPU
+int __attribute__((weak)) smp_prepare_cpu (int cpu)
+{
+	return 0;
+}
+
 static ssize_t show_online(struct sys_device *dev, char *buf)
 {
 	struct cpu *cpu = container_of(dev, struct cpu, sysdev);
@@ -36,7 +41,11 @@
 			kobject_hotplug(&dev->kobj, KOBJ_OFFLINE);
 		break;
 	case '1':
-		ret = cpu_up(cpu->sysdev.id);
+		ret = smp_prepare_cpu(cpu->sysdev.id);
+		if (!ret)
+			ret = cpu_up(cpu->sysdev.id);
+		if (!ret)
+			kobject_hotplug(&dev->kobj, KOBJ_ONLINE);
 		break;
 	default:
 		ret = -EINVAL;
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
new file mode 100644
index 0000000..6db3a78
--- /dev/null
+++ b/drivers/base/dd.c
@@ -0,0 +1,248 @@
+/*
+ *	drivers/base/dd.c - The core device/driver interactions.
+ *
+ * 	This file contains the (sometimes tricky) code that controls the
+ *	interactions between devices and drivers, which primarily includes
+ *	driver binding and unbinding.
+ *
+ *	All of this code used to exist in drivers/base/bus.c, but was
+ *	relocated to here in the name of compartmentalization (since it wasn't
+ *	strictly code just for the 'struct bus_type'.
+ *
+ *	Copyright (c) 2002-5 Patrick Mochel
+ *	Copyright (c) 2002-3 Open Source Development Labs
+ *
+ *	This file is released under the GPLv2
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+
+#include "base.h"
+#include "power/power.h"
+
+#define to_drv(node) container_of(node, struct device_driver, kobj.entry)
+
+
+/**
+ *	device_bind_driver - bind a driver to one device.
+ *	@dev:	device.
+ *
+ *	Allow manual attachment of a driver to a device.
+ *	Caller must have already set @dev->driver.
+ *
+ *	Note that this does not modify the bus reference count
+ *	nor take the bus's rwsem. Please verify those are accounted
+ *	for before calling this. (It is ok to call with no other effort
+ *	from a driver's probe() method.)
+ *
+ *	This function must be called with @dev->sem held.
+ */
+void device_bind_driver(struct device * dev)
+{
+	pr_debug("bound device '%s' to driver '%s'\n",
+		 dev->bus_id, dev->driver->name);
+	klist_add_tail(&dev->driver->klist_devices, &dev->knode_driver);
+	sysfs_create_link(&dev->driver->kobj, &dev->kobj,
+			  kobject_name(&dev->kobj));
+	sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver");
+}
+
+/**
+ *	driver_probe_device - attempt to bind device & driver.
+ *	@drv:	driver.
+ *	@dev:	device.
+ *
+ *	First, we call the bus's match function, if one present, which
+ *	should compare the device IDs the driver supports with the
+ *	device IDs of the device. Note we don't do this ourselves
+ *	because we don't know the format of the ID structures, nor what
+ *	is to be considered a match and what is not.
+ *
+ *
+ *	This function returns 1 if a match is found, an error if one
+ *	occurs (that is not -ENODEV or -ENXIO), and 0 otherwise.
+ *
+ *	This function must be called with @dev->sem held.
+ */
+static int driver_probe_device(struct device_driver * drv, struct device * dev)
+{
+	int ret = 0;
+
+	if (drv->bus->match && !drv->bus->match(dev, drv))
+		goto Done;
+
+	pr_debug("%s: Matched Device %s with Driver %s\n",
+		 drv->bus->name, dev->bus_id, drv->name);
+	dev->driver = drv;
+	if (drv->probe) {
+		ret = drv->probe(dev);
+		if (ret) {
+			dev->driver = NULL;
+			goto ProbeFailed;
+		}
+	}
+	device_bind_driver(dev);
+	ret = 1;
+	pr_debug("%s: Bound Device %s to Driver %s\n",
+		 drv->bus->name, dev->bus_id, drv->name);
+	goto Done;
+
+ ProbeFailed:
+	if (ret == -ENODEV || ret == -ENXIO) {
+		/* Driver matched, but didn't support device
+		 * or device not found.
+		 * Not an error; keep going.
+		 */
+		ret = 0;
+	} else {
+		/* driver matched but the probe failed */
+		printk(KERN_WARNING
+		       "%s: probe of %s failed with error %d\n",
+		       drv->name, dev->bus_id, ret);
+	}
+ Done:
+	return ret;
+}
+
+static int __device_attach(struct device_driver * drv, void * data)
+{
+	struct device * dev = data;
+	return driver_probe_device(drv, dev);
+}
+
+/**
+ *	device_attach - try to attach device to a driver.
+ *	@dev:	device.
+ *
+ *	Walk the list of drivers that the bus has and call
+ *	driver_probe_device() for each pair. If a compatible
+ *	pair is found, break out and return.
+ *
+ *	Returns 1 if the device was bound to a driver;
+ *	0 if no matching device was found; error code otherwise.
+ */
+int device_attach(struct device * dev)
+{
+	int ret = 0;
+
+	down(&dev->sem);
+	if (dev->driver) {
+		device_bind_driver(dev);
+		ret = 1;
+	} else
+		ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
+	up(&dev->sem);
+	return ret;
+}
+
+static int __driver_attach(struct device * dev, void * data)
+{
+	struct device_driver * drv = data;
+
+	/*
+	 * Lock device and try to bind to it. We drop the error
+	 * here and always return 0, because we need to keep trying
+	 * to bind to devices and some drivers will return an error
+	 * simply if it didn't support the device.
+	 *
+	 * driver_probe_device() will spit a warning if there
+	 * is an error.
+	 */
+
+	down(&dev->sem);
+	if (!dev->driver)
+		driver_probe_device(drv, dev);
+	up(&dev->sem);
+
+
+	return 0;
+}
+
+/**
+ *	driver_attach - try to bind driver to devices.
+ *	@drv:	driver.
+ *
+ *	Walk the list of devices that the bus has on it and try to
+ *	match the driver with each one.  If driver_probe_device()
+ *	returns 0 and the @dev->driver is set, we've found a
+ *	compatible pair.
+ */
+void driver_attach(struct device_driver * drv)
+{
+	bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
+}
+
+/**
+ *	device_release_driver - manually detach device from driver.
+ *	@dev:	device.
+ *
+ *	Manually detach device from driver.
+ *
+ *	__device_release_driver() must be called with @dev->sem held.
+ */
+
+static void __device_release_driver(struct device * dev)
+{
+	struct device_driver * drv;
+
+	drv = dev->driver;
+	if (drv) {
+		get_driver(drv);
+		sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj));
+		sysfs_remove_link(&dev->kobj, "driver");
+		klist_remove(&dev->knode_driver);
+
+		if (drv->remove)
+			drv->remove(dev);
+		dev->driver = NULL;
+		put_driver(drv);
+	}
+}
+
+void device_release_driver(struct device * dev)
+{
+	/*
+	 * If anyone calls device_release_driver() recursively from
+	 * within their ->remove callback for the same device, they
+	 * will deadlock right here.
+	 */
+	down(&dev->sem);
+	__device_release_driver(dev);
+	up(&dev->sem);
+}
+
+
+/**
+ * driver_detach - detach driver from all devices it controls.
+ * @drv: driver.
+ */
+void driver_detach(struct device_driver * drv)
+{
+	struct device * dev;
+
+	for (;;) {
+		spin_lock_irq(&drv->klist_devices.k_lock);
+		if (list_empty(&drv->klist_devices.k_list)) {
+			spin_unlock_irq(&drv->klist_devices.k_lock);
+			break;
+		}
+		dev = list_entry(drv->klist_devices.k_list.prev,
+				struct device, knode_driver.n_node);
+		get_device(dev);
+		spin_unlock_irq(&drv->klist_devices.k_lock);
+
+		down(&dev->sem);
+		if (dev->driver == drv)
+			__device_release_driver(dev);
+		up(&dev->sem);
+		put_device(dev);
+	}
+}
+
+
+EXPORT_SYMBOL_GPL(device_bind_driver);
+EXPORT_SYMBOL_GPL(device_release_driver);
+EXPORT_SYMBOL_GPL(device_attach);
+EXPORT_SYMBOL_GPL(driver_attach);
+
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c
index f48833d..c4aebf2 100644
--- a/drivers/base/dmapool.c
+++ b/drivers/base/dmapool.c
@@ -41,7 +41,7 @@
 static DECLARE_MUTEX (pools_lock);
 
 static ssize_t
-show_pools (struct device *dev, char *buf)
+show_pools (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	unsigned temp;
 	unsigned size;
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 3b269f7..1b64588 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -18,6 +18,43 @@
 #define to_dev(node) container_of(node, struct device, driver_list)
 #define to_drv(obj) container_of(obj, struct device_driver, kobj)
 
+
+static struct device * next_device(struct klist_iter * i)
+{
+	struct klist_node * n = klist_next(i);
+	return n ? container_of(n, struct device, knode_driver) : NULL;
+}
+
+/**
+ *	driver_for_each_device - Iterator for devices bound to a driver.
+ *	@drv:	Driver we're iterating.
+ *	@data:	Data to pass to the callback.
+ *	@fn:	Function to call for each device.
+ *
+ *	Iterate over the @drv's list of devices calling @fn for each one.
+ */
+
+int driver_for_each_device(struct device_driver * drv, struct device * start, 
+			   void * data, int (*fn)(struct device *, void *))
+{
+	struct klist_iter i;
+	struct device * dev;
+	int error = 0;
+
+	if (!drv)
+		return -EINVAL;
+
+	klist_iter_init_node(&drv->klist_devices, &i,
+			     start ? &start->knode_driver : NULL);
+	while ((dev = next_device(&i)) && !error)
+		error = fn(dev, data);
+	klist_iter_exit(&i);
+	return error;
+}
+
+EXPORT_SYMBOL_GPL(driver_for_each_device);
+
+
 /**
  *	driver_create_file - create sysfs file for driver.
  *	@drv:	driver.
@@ -85,7 +122,7 @@
  */
 int driver_register(struct device_driver * drv)
 {
-	INIT_LIST_HEAD(&drv->devices);
+	klist_init(&drv->klist_devices);
 	init_completion(&drv->unloaded);
 	return bus_add_driver(drv);
 }
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 583d57e..904b27c 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -87,7 +87,7 @@
 	for (i = 0; i < MAX_NR_ZONES; i++) {
 		struct zone *z = &pg->node_zones[i];
 		for (cpu = 0; cpu < NR_CPUS; cpu++) {
-			struct per_cpu_pageset *ps = &z->pageset[cpu];
+			struct per_cpu_pageset *ps = zone_pcp(z,cpu);
 			numa_hit += ps->numa_hit;
 			numa_miss += ps->numa_miss;
 			numa_foreign += ps->numa_foreign;
@@ -136,7 +136,7 @@
  *
  * Initialize and register the node device.
  */
-int __init register_node(struct node *node, int num, struct node *parent)
+int register_node(struct node *node, int num, struct node *parent)
 {
 	int error;
 
@@ -153,8 +153,24 @@
 	return error;
 }
 
+/**
+ * unregister_node - unregister a node device
+ * @node: node going away
+ *
+ * Unregisters a node device @node.  All the devices on the node must be
+ * unregistered before calling this function.
+ */
+void unregister_node(struct node *node)
+{
+	sysdev_remove_file(&node->sysdev, &attr_cpumap);
+	sysdev_remove_file(&node->sysdev, &attr_meminfo);
+	sysdev_remove_file(&node->sysdev, &attr_numastat);
+	sysdev_remove_file(&node->sysdev, &attr_distance);
 
-int __init register_node_type(void)
+	sysdev_unregister(&node->sysdev);
+}
+
+static int __init register_node_type(void)
 {
 	return sysdev_class_register(&node_class);
 }
diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c
index 2646897..bdd96b0 100644
--- a/drivers/base/power/resume.c
+++ b/drivers/base/power/resume.c
@@ -22,6 +22,9 @@
 
 int resume_device(struct device * dev)
 {
+	int error = 0;
+
+	down(&dev->sem);
 	if (dev->power.pm_parent
 			&& dev->power.pm_parent->power.power_state) {
 		dev_err(dev, "PM: resume from %d, parent %s still %d\n",
@@ -31,9 +34,10 @@
 	}
 	if (dev->bus && dev->bus->resume) {
 		dev_dbg(dev,"resuming\n");
-		return dev->bus->resume(dev);
+		error = dev->bus->resume(dev);
 	}
-	return 0;
+	up(&dev->sem);
+	return error;
 }
 
 
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
index 0ec44ef..2ccee37 100644
--- a/drivers/base/power/suspend.c
+++ b/drivers/base/power/suspend.c
@@ -39,6 +39,7 @@
 {
 	int error = 0;
 
+	down(&dev->sem);
 	if (dev->power.power_state) {
 		dev_dbg(dev, "PM: suspend %d-->%d\n",
 			dev->power.power_state, state);
@@ -58,7 +59,7 @@
 		dev_dbg(dev, "suspending\n");
 		error = dev->bus->suspend(dev, state);
 	}
-
+	up(&dev->sem);
 	return error;
 }
 
@@ -113,8 +114,19 @@
 		put_device(dev);
 	}
 	up(&dpm_list_sem);
-	if (error)
+	if (error) {
+		/* we failed... before resuming, bring back devices from
+		 * dpm_off_irq list back to main dpm_off list, we do want
+		 * to call resume() on them, in case they partially suspended
+		 * despite returning -EAGAIN
+		 */
+		while (!list_empty(&dpm_off_irq)) {
+			struct list_head * entry = dpm_off_irq.next;
+			list_del(entry);
+			list_add(entry, &dpm_off);
+		}
 		dpm_resume();
+	}
 	up(&dpm_sem);
 	return error;
 }
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index 6ac9634..f82b3df 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -24,12 +24,12 @@
  *	low-power state.
  */
 
-static ssize_t state_show(struct device * dev, char * buf)
+static ssize_t state_show(struct device * dev, struct device_attribute *attr, char * buf)
 {
 	return sprintf(buf, "%u\n", dev->power.power_state);
 }
 
-static ssize_t state_store(struct device * dev, const char * buf, size_t n)
+static ssize_t state_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t n)
 {
 	u32 state;
 	char * rest;
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 9102e37..f37a13d 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -37,7 +37,7 @@
 
 	if (sysdev_attr->show)
 		return sysdev_attr->show(sysdev, buffer);
-	return 0;
+	return -EIO;
 }
 
 
@@ -50,7 +50,7 @@
 
 	if (sysdev_attr->store)
 		return sysdev_attr->store(sysdev, buffer, count);
-	return 0;
+	return -EIO;
 }
 
 static struct sysfs_ops sysfs_ops = {
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index 14aeca3..45a2430 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -36,7 +36,7 @@
 static struct semaphore emsgs_sema;
 static spinlock_t emsgs_lock;
 static int nblocked_emsgs_readers;
-static struct class_simple *aoe_class;
+static struct class *aoe_class;
 static struct aoe_chardev chardevs[] = {
 	{ MINOR_ERR, "err" },
 	{ MINOR_DISCOVER, "discover" },
@@ -218,13 +218,13 @@
 	}
 	sema_init(&emsgs_sema, 0);
 	spin_lock_init(&emsgs_lock);
-	aoe_class = class_simple_create(THIS_MODULE, "aoe");
+	aoe_class = class_create(THIS_MODULE, "aoe");
 	if (IS_ERR(aoe_class)) {
 		unregister_chrdev(AOE_MAJOR, "aoechr");
 		return PTR_ERR(aoe_class);
 	}
 	for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
-		class_simple_device_add(aoe_class,
+		class_device_create(aoe_class,
 					MKDEV(AOE_MAJOR, chardevs[i].minor),
 					NULL, chardevs[i].name);
 
@@ -237,8 +237,8 @@
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(chardevs); ++i)
-		class_simple_device_remove(MKDEV(AOE_MAJOR, chardevs[i].minor));
-	class_simple_destroy(aoe_class);
+		class_device_destroy(aoe_class, MKDEV(AOE_MAJOR, chardevs[i].minor));
+	class_destroy(aoe_class);
 	unregister_chrdev(AOE_MAJOR, "aoechr");
 }
 
diff --git a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c
index a9575bb..91aeb67 100644
--- a/drivers/block/as-iosched.c
+++ b/drivers/block/as-iosched.c
@@ -1806,7 +1806,8 @@
 	rq->elevator_private = NULL;
 }
 
-static int as_set_request(request_queue_t *q, struct request *rq, int gfp_mask)
+static int as_set_request(request_queue_t *q, struct request *rq,
+			  struct bio *bio, int gfp_mask)
 {
 	struct as_data *ad = q->elevator->elevator_data;
 	struct as_rq *arq = mempool_alloc(ad->arq_pool, gfp_mask);
@@ -1827,7 +1828,7 @@
 	return 1;
 }
 
-static int as_may_queue(request_queue_t *q, int rw)
+static int as_may_queue(request_queue_t *q, int rw, struct bio *bio)
 {
 	int ret = ELV_MQUEUE_MAY;
 	struct as_data *ad = q->elevator->elevator_data;
@@ -1871,20 +1872,22 @@
 	if (!arq_pool)
 		return -ENOMEM;
 
-	ad = kmalloc(sizeof(*ad), GFP_KERNEL);
+	ad = kmalloc_node(sizeof(*ad), GFP_KERNEL, q->node);
 	if (!ad)
 		return -ENOMEM;
 	memset(ad, 0, sizeof(*ad));
 
 	ad->q = q; /* Identify what queue the data belongs to */
 
-	ad->hash = kmalloc(sizeof(struct list_head)*AS_HASH_ENTRIES,GFP_KERNEL);
+	ad->hash = kmalloc_node(sizeof(struct list_head)*AS_HASH_ENTRIES,
+				GFP_KERNEL, q->node);
 	if (!ad->hash) {
 		kfree(ad);
 		return -ENOMEM;
 	}
 
-	ad->arq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, arq_pool);
+	ad->arq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
+				mempool_free_slab, arq_pool, q->node);
 	if (!ad->arq_pool) {
 		kfree(ad->hash);
 		kfree(ad);
@@ -2044,7 +2047,7 @@
 	struct as_fs_entry *entry = to_as(attr);
 
 	if (!entry->show)
-		return 0;
+		return -EIO;
 
 	return entry->show(e->elevator_data, page);
 }
@@ -2057,7 +2060,7 @@
 	struct as_fs_entry *entry = to_as(attr);
 
 	if (!entry->store)
-		return -EINVAL;
+		return -EIO;
 
 	return entry->store(e->elevator_data, page, length);
 }
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 8f7c1a1..abde270 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -41,6 +41,7 @@
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
+#include <linux/dma-mapping.h>
 #include <linux/blkdev.h>
 #include <linux/genhd.h>
 #include <linux/completion.h>
@@ -126,8 +127,6 @@
 #define MAX_CTLR_ORIG 	8
 
 
-#define CCISS_DMA_MASK	0xFFFFFFFF	/* 32 bit DMA */
-
 static ctlr_info_t *hba[MAX_CTLR];
 
 static void do_cciss_request(request_queue_t *q);
@@ -2393,11 +2392,6 @@
 		printk(KERN_ERR "cciss: Unable to Enable PCI device\n");
 		return( -1);
 	}
-	if (pci_set_dma_mask(pdev, CCISS_DMA_MASK ) != 0)
-	{
-		printk(KERN_ERR "cciss:  Unable to set DMA mask\n");
-		return(-1);
-	}
 
 	subsystem_vendor_id = pdev->subsystem_vendor;
 	subsystem_device_id = pdev->subsystem_device;
@@ -2747,9 +2741,9 @@
 	hba[i]->pdev = pdev;
 
 	/* configure PCI DMA stuff */
-	if (!pci_set_dma_mask(pdev, 0xffffffffffffffffULL))
+	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK))
 		printk("cciss: using DAC cycles\n");
-	else if (!pci_set_dma_mask(pdev, 0xffffffff))
+	else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK))
 		printk("cciss: not using DAC cycles\n");
 	else {
 		printk("cciss: no suitable DMA available\n");
diff --git a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c
index 0ef7a00..ff1cc96 100644
--- a/drivers/block/cfq-iosched.c
+++ b/drivers/block/cfq-iosched.c
@@ -21,22 +21,34 @@
 #include <linux/hash.h>
 #include <linux/rbtree.h>
 #include <linux/mempool.h>
-
-static unsigned long max_elapsed_crq;
-static unsigned long max_elapsed_dispatch;
+#include <linux/ioprio.h>
+#include <linux/writeback.h>
 
 /*
  * tunables
  */
 static int cfq_quantum = 4;		/* max queue in one round of service */
 static int cfq_queued = 8;		/* minimum rq allocate limit per-queue*/
-static int cfq_service = HZ;		/* period over which service is avg */
-static int cfq_fifo_expire_r = HZ / 2;	/* fifo timeout for sync requests */
-static int cfq_fifo_expire_w = 5 * HZ;	/* fifo timeout for async requests */
-static int cfq_fifo_rate = HZ / 8;	/* fifo expiry rate */
+static int cfq_fifo_expire[2] = { HZ / 4, HZ / 8 };
 static int cfq_back_max = 16 * 1024;	/* maximum backwards seek, in KiB */
 static int cfq_back_penalty = 2;	/* penalty of a backwards seek */
 
+static int cfq_slice_sync = HZ / 10;
+static int cfq_slice_async = HZ / 25;
+static int cfq_slice_async_rq = 2;
+static int cfq_slice_idle = HZ / 100;
+
+#define CFQ_IDLE_GRACE		(HZ / 10)
+#define CFQ_SLICE_SCALE		(5)
+
+#define CFQ_KEY_ASYNC		(0)
+#define CFQ_KEY_ANY		(0xffff)
+
+/*
+ * disable queueing at the driver/hardware level
+ */
+static int cfq_max_depth = 1;
+
 /*
  * for the hash of cfqq inside the cfqd
  */
@@ -55,6 +67,7 @@
 #define list_entry_hash(ptr)	hlist_entry((ptr), struct cfq_rq, hash)
 
 #define list_entry_cfqq(ptr)	list_entry((ptr), struct cfq_queue, cfq_list)
+#define list_entry_fifo(ptr)	list_entry((ptr), struct request, queuelist)
 
 #define RQ_DATA(rq)		(rq)->elevator_private
 
@@ -75,78 +88,110 @@
 #define rb_entry_crq(node)	rb_entry((node), struct cfq_rq, rb_node)
 #define rq_rb_key(rq)		(rq)->sector
 
-/*
- * threshold for switching off non-tag accounting
- */
-#define CFQ_MAX_TAG		(4)
-
-/*
- * sort key types and names
- */
-enum {
-	CFQ_KEY_PGID,
-	CFQ_KEY_TGID,
-	CFQ_KEY_UID,
-	CFQ_KEY_GID,
-	CFQ_KEY_LAST,
-};
-
-static char *cfq_key_types[] = { "pgid", "tgid", "uid", "gid", NULL };
-
 static kmem_cache_t *crq_pool;
 static kmem_cache_t *cfq_pool;
 static kmem_cache_t *cfq_ioc_pool;
 
+#define CFQ_PRIO_LISTS		IOPRIO_BE_NR
+#define cfq_class_idle(cfqq)	((cfqq)->ioprio_class == IOPRIO_CLASS_IDLE)
+#define cfq_class_be(cfqq)	((cfqq)->ioprio_class == IOPRIO_CLASS_BE)
+#define cfq_class_rt(cfqq)	((cfqq)->ioprio_class == IOPRIO_CLASS_RT)
+
+#define ASYNC			(0)
+#define SYNC			(1)
+
+#define cfq_cfqq_dispatched(cfqq)	\
+	((cfqq)->on_dispatch[ASYNC] + (cfqq)->on_dispatch[SYNC])
+
+#define cfq_cfqq_class_sync(cfqq)	((cfqq)->key != CFQ_KEY_ASYNC)
+
+#define cfq_cfqq_sync(cfqq)		\
+	(cfq_cfqq_class_sync(cfqq) || (cfqq)->on_dispatch[SYNC])
+
+/*
+ * Per block device queue structure
+ */
 struct cfq_data {
-	struct list_head rr_list;
+	atomic_t ref;
+	request_queue_t *queue;
+
+	/*
+	 * rr list of queues with requests and the count of them
+	 */
+	struct list_head rr_list[CFQ_PRIO_LISTS];
+	struct list_head busy_rr;
+	struct list_head cur_rr;
+	struct list_head idle_rr;
+	unsigned int busy_queues;
+
+	/*
+	 * non-ordered list of empty cfqq's
+	 */
 	struct list_head empty_list;
 
+	/*
+	 * cfqq lookup hash
+	 */
 	struct hlist_head *cfq_hash;
-	struct hlist_head *crq_hash;
 
-	/* queues on rr_list (ie they have pending requests */
-	unsigned int busy_queues;
+	/*
+	 * global crq hash for all queues
+	 */
+	struct hlist_head *crq_hash;
 
 	unsigned int max_queued;
 
-	atomic_t ref;
-
-	int key_type;
-
 	mempool_t *crq_pool;
 
-	request_queue_t *queue;
+	int rq_in_driver;
+
+	/*
+	 * schedule slice state info
+	 */
+	/*
+	 * idle window management
+	 */
+	struct timer_list idle_slice_timer;
+	struct work_struct unplug_work;
+
+	struct cfq_queue *active_queue;
+	struct cfq_io_context *active_cic;
+	int cur_prio, cur_end_prio;
+	unsigned int dispatch_slice;
+
+	struct timer_list idle_class_timer;
 
 	sector_t last_sector;
+	unsigned long last_end_request;
 
-	int rq_in_driver;
+	unsigned int rq_starved;
 
 	/*
 	 * tunables, see top of file
 	 */
 	unsigned int cfq_quantum;
 	unsigned int cfq_queued;
-	unsigned int cfq_fifo_expire_r;
-	unsigned int cfq_fifo_expire_w;
-	unsigned int cfq_fifo_batch_expire;
+	unsigned int cfq_fifo_expire[2];
 	unsigned int cfq_back_penalty;
 	unsigned int cfq_back_max;
-	unsigned int find_best_crq;
-
-	unsigned int cfq_tagged;
+	unsigned int cfq_slice[2];
+	unsigned int cfq_slice_async_rq;
+	unsigned int cfq_slice_idle;
+	unsigned int cfq_max_depth;
 };
 
+/*
+ * Per process-grouping structure
+ */
 struct cfq_queue {
 	/* reference count */
 	atomic_t ref;
 	/* parent cfq_data */
 	struct cfq_data *cfqd;
-	/* hash of mergeable requests */
+	/* cfqq lookup hash */
 	struct hlist_node cfq_hash;
 	/* hash key */
-	unsigned long key;
-	/* whether queue is on rr (or empty) list */
-	int on_rr;
+	unsigned int key;
 	/* on either rr or empty list of cfqd */
 	struct list_head cfq_list;
 	/* sorted list of pending requests */
@@ -158,21 +203,22 @@
 	/* currently allocated requests */
 	int allocated[2];
 	/* fifo list of requests in sort_list */
-	struct list_head fifo[2];
-	/* last time fifo expired */
-	unsigned long last_fifo_expire;
+	struct list_head fifo;
 
-	int key_type;
+	unsigned long slice_start;
+	unsigned long slice_end;
+	unsigned long slice_left;
+	unsigned long service_last;
 
-	unsigned long service_start;
-	unsigned long service_used;
+	/* number of requests that are on the dispatch list */
+	int on_dispatch[2];
 
-	unsigned int max_rate;
+	/* io prio of this group */
+	unsigned short ioprio, org_ioprio;
+	unsigned short ioprio_class, org_ioprio_class;
 
-	/* number of requests that have been handed to the driver */
-	int in_flight;
-	/* number of currently allocated requests */
-	int alloc_limit[2];
+	/* various state flags, see below */
+	unsigned int flags;
 };
 
 struct cfq_rq {
@@ -184,43 +230,80 @@
 	struct cfq_queue *cfq_queue;
 	struct cfq_io_context *io_context;
 
-	unsigned long service_start;
-	unsigned long queue_start;
-
-	unsigned int in_flight : 1;
-	unsigned int accounted : 1;
-	unsigned int is_sync   : 1;
-	unsigned int is_write  : 1;
+	unsigned int crq_flags;
 };
 
-static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned long);
-static void cfq_dispatch_sort(request_queue_t *, struct cfq_rq *);
-static void cfq_update_next_crq(struct cfq_rq *);
-static void cfq_put_cfqd(struct cfq_data *cfqd);
+enum cfqq_state_flags {
+	CFQ_CFQQ_FLAG_on_rr = 0,
+	CFQ_CFQQ_FLAG_wait_request,
+	CFQ_CFQQ_FLAG_must_alloc,
+	CFQ_CFQQ_FLAG_must_alloc_slice,
+	CFQ_CFQQ_FLAG_must_dispatch,
+	CFQ_CFQQ_FLAG_fifo_expire,
+	CFQ_CFQQ_FLAG_idle_window,
+	CFQ_CFQQ_FLAG_prio_changed,
+	CFQ_CFQQ_FLAG_expired,
+};
 
-/*
- * what the fairness is based on (ie how processes are grouped and
- * differentiated)
- */
-static inline unsigned long
-cfq_hash_key(struct cfq_data *cfqd, struct task_struct *tsk)
-{
-	/*
-	 * optimize this so that ->key_type is the offset into the struct
-	 */
-	switch (cfqd->key_type) {
-		case CFQ_KEY_PGID:
-			return process_group(tsk);
-		default:
-		case CFQ_KEY_TGID:
-			return tsk->tgid;
-		case CFQ_KEY_UID:
-			return tsk->uid;
-		case CFQ_KEY_GID:
-			return tsk->gid;
-	}
+#define CFQ_CFQQ_FNS(name)						\
+static inline void cfq_mark_cfqq_##name(struct cfq_queue *cfqq)		\
+{									\
+	cfqq->flags |= (1 << CFQ_CFQQ_FLAG_##name);			\
+}									\
+static inline void cfq_clear_cfqq_##name(struct cfq_queue *cfqq)	\
+{									\
+	cfqq->flags &= ~(1 << CFQ_CFQQ_FLAG_##name);			\
+}									\
+static inline int cfq_cfqq_##name(const struct cfq_queue *cfqq)		\
+{									\
+	return (cfqq->flags & (1 << CFQ_CFQQ_FLAG_##name)) != 0;	\
 }
 
+CFQ_CFQQ_FNS(on_rr);
+CFQ_CFQQ_FNS(wait_request);
+CFQ_CFQQ_FNS(must_alloc);
+CFQ_CFQQ_FNS(must_alloc_slice);
+CFQ_CFQQ_FNS(must_dispatch);
+CFQ_CFQQ_FNS(fifo_expire);
+CFQ_CFQQ_FNS(idle_window);
+CFQ_CFQQ_FNS(prio_changed);
+CFQ_CFQQ_FNS(expired);
+#undef CFQ_CFQQ_FNS
+
+enum cfq_rq_state_flags {
+	CFQ_CRQ_FLAG_in_flight = 0,
+	CFQ_CRQ_FLAG_in_driver,
+	CFQ_CRQ_FLAG_is_sync,
+	CFQ_CRQ_FLAG_requeued,
+};
+
+#define CFQ_CRQ_FNS(name)						\
+static inline void cfq_mark_crq_##name(struct cfq_rq *crq)		\
+{									\
+	crq->crq_flags |= (1 << CFQ_CRQ_FLAG_##name);			\
+}									\
+static inline void cfq_clear_crq_##name(struct cfq_rq *crq)		\
+{									\
+	crq->crq_flags &= ~(1 << CFQ_CRQ_FLAG_##name);			\
+}									\
+static inline int cfq_crq_##name(const struct cfq_rq *crq)		\
+{									\
+	return (crq->crq_flags & (1 << CFQ_CRQ_FLAG_##name)) != 0;	\
+}
+
+CFQ_CRQ_FNS(in_flight);
+CFQ_CRQ_FNS(in_driver);
+CFQ_CRQ_FNS(is_sync);
+CFQ_CRQ_FNS(requeued);
+#undef CFQ_CRQ_FNS
+
+static struct cfq_queue *cfq_find_cfq_hash(struct cfq_data *, unsigned int, unsigned short);
+static void cfq_dispatch_sort(request_queue_t *, struct cfq_rq *);
+static void cfq_put_cfqd(struct cfq_data *cfqd);
+static inline int cfq_pending_requests(struct cfq_data *cfqd);
+
+#define process_sync(tsk)	((tsk)->flags & PF_SYNCWRITE)
+
 /*
  * lots of deadline iosched dupes, can be abstracted later...
  */
@@ -235,16 +318,12 @@
 
 	if (q->last_merge == crq->request)
 		q->last_merge = NULL;
-
-	cfq_update_next_crq(crq);
 }
 
 static inline void cfq_add_crq_hash(struct cfq_data *cfqd, struct cfq_rq *crq)
 {
 	const int hash_idx = CFQ_MHASH_FN(rq_hash_key(crq->request));
 
-	BUG_ON(!hlist_unhashed(&crq->hash));
-
 	hlist_add_head(&crq->hash, &cfqd->crq_hash[hash_idx]);
 }
 
@@ -257,8 +336,6 @@
 		struct cfq_rq *crq = list_entry_hash(entry);
 		struct request *__rq = crq->request;
 
-		BUG_ON(hlist_unhashed(&crq->hash));
-
 		if (!rq_mergeable(__rq)) {
 			cfq_del_crq_hash(crq);
 			continue;
@@ -287,36 +364,16 @@
 		return crq2;
 	if (crq2 == NULL)
 		return crq1;
+	if (cfq_crq_requeued(crq1))
+		return crq1;
+	if (cfq_crq_requeued(crq2))
+		return crq2;
 
 	s1 = crq1->request->sector;
 	s2 = crq2->request->sector;
 
 	last = cfqd->last_sector;
 
-#if 0
-	if (!list_empty(&cfqd->queue->queue_head)) {
-		struct list_head *entry = &cfqd->queue->queue_head;
-		unsigned long distance = ~0UL;
-		struct request *rq;
-
-		while ((entry = entry->prev) != &cfqd->queue->queue_head) {
-			rq = list_entry_rq(entry);
-
-			if (blk_barrier_rq(rq))
-				break;
-
-			if (distance < abs(s1 - rq->sector + rq->nr_sectors)) {
-				distance = abs(s1 - rq->sector +rq->nr_sectors);
-				last = rq->sector + rq->nr_sectors;
-			}
-			if (distance < abs(s2 - rq->sector + rq->nr_sectors)) {
-				distance = abs(s2 - rq->sector +rq->nr_sectors);
-				last = rq->sector + rq->nr_sectors;
-			}
-		}
-	}
-#endif
-
 	/*
 	 * by definition, 1KiB is 2 sectors
 	 */
@@ -377,11 +434,14 @@
 	struct cfq_rq *crq_next = NULL, *crq_prev = NULL;
 	struct rb_node *rbnext, *rbprev;
 
-	if (!ON_RB(&last->rb_node))
-		return NULL;
-
-	if ((rbnext = rb_next(&last->rb_node)) == NULL)
+	rbnext = NULL;
+	if (ON_RB(&last->rb_node))
+		rbnext = rb_next(&last->rb_node);
+	if (!rbnext) {
 		rbnext = rb_first(&cfqq->sort_list);
+		if (rbnext == &last->rb_node)
+			rbnext = NULL;
+	}
 
 	rbprev = rb_prev(&last->rb_node);
 
@@ -401,67 +461,53 @@
 		cfqq->next_crq = cfq_find_next_crq(cfqq->cfqd, cfqq, crq);
 }
 
-static int cfq_check_sort_rr_list(struct cfq_queue *cfqq)
+static void cfq_resort_rr_list(struct cfq_queue *cfqq, int preempted)
 {
-	struct list_head *head = &cfqq->cfqd->rr_list;
-	struct list_head *next, *prev;
+	struct cfq_data *cfqd = cfqq->cfqd;
+	struct list_head *list, *entry;
 
-	/*
-	 * list might still be ordered
-	 */
-	next = cfqq->cfq_list.next;
-	if (next != head) {
-		struct cfq_queue *cnext = list_entry_cfqq(next);
-
-		if (cfqq->service_used > cnext->service_used)
-			return 1;
-	}
-
-	prev = cfqq->cfq_list.prev;
-	if (prev != head) {
-		struct cfq_queue *cprev = list_entry_cfqq(prev);
-
-		if (cfqq->service_used < cprev->service_used)
-			return 1;
-	}
-
-	return 0;
-}
-
-static void cfq_sort_rr_list(struct cfq_queue *cfqq, int new_queue)
-{
-	struct list_head *entry = &cfqq->cfqd->rr_list;
-
-	if (!cfqq->on_rr)
-		return;
-	if (!new_queue && !cfq_check_sort_rr_list(cfqq))
-		return;
+	BUG_ON(!cfq_cfqq_on_rr(cfqq));
 
 	list_del(&cfqq->cfq_list);
 
+	if (cfq_class_rt(cfqq))
+		list = &cfqd->cur_rr;
+	else if (cfq_class_idle(cfqq))
+		list = &cfqd->idle_rr;
+	else {
+		/*
+		 * if cfqq has requests in flight, don't allow it to be
+		 * found in cfq_set_active_queue before it has finished them.
+		 * this is done to increase fairness between a process that
+		 * has lots of io pending vs one that only generates one
+		 * sporadically or synchronously
+		 */
+		if (cfq_cfqq_dispatched(cfqq))
+			list = &cfqd->busy_rr;
+		else
+			list = &cfqd->rr_list[cfqq->ioprio];
+	}
+
 	/*
-	 * sort by our mean service_used, sub-sort by in-flight requests
+	 * if queue was preempted, just add to front to be fair. busy_rr
+	 * isn't sorted.
 	 */
-	while ((entry = entry->prev) != &cfqq->cfqd->rr_list) {
+	if (preempted || list == &cfqd->busy_rr) {
+		list_add(&cfqq->cfq_list, list);
+		return;
+	}
+
+	/*
+	 * sort by when queue was last serviced
+	 */
+	entry = list;
+	while ((entry = entry->prev) != list) {
 		struct cfq_queue *__cfqq = list_entry_cfqq(entry);
 
-		if (cfqq->service_used > __cfqq->service_used)
+		if (!__cfqq->service_last)
 			break;
-		else if (cfqq->service_used == __cfqq->service_used) {
-			struct list_head *prv;
-
-			while ((prv = entry->prev) != &cfqq->cfqd->rr_list) {
-				__cfqq = list_entry_cfqq(prv);
-
-				WARN_ON(__cfqq->service_used > cfqq->service_used);
-				if (cfqq->service_used != __cfqq->service_used)
-					break;
-				if (cfqq->in_flight > __cfqq->in_flight)
-					break;
-
-				entry = prv;
-			}
-		}
+		if (time_before(__cfqq->service_last, cfqq->service_last))
+			break;
 	}
 
 	list_add(&cfqq->cfq_list, entry);
@@ -469,28 +515,24 @@
 
 /*
  * add to busy list of queues for service, trying to be fair in ordering
- * the pending list according to requests serviced
+ * the pending list according to last request service
  */
 static inline void
-cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
+cfq_add_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq, int requeue)
 {
-	/*
-	 * it's currently on the empty list
-	 */
-	cfqq->on_rr = 1;
+	BUG_ON(cfq_cfqq_on_rr(cfqq));
+	cfq_mark_cfqq_on_rr(cfqq);
 	cfqd->busy_queues++;
 
-	if (time_after(jiffies, cfqq->service_start + cfq_service))
-		cfqq->service_used >>= 3;
-
-	cfq_sort_rr_list(cfqq, 1);
+	cfq_resort_rr_list(cfqq, requeue);
 }
 
 static inline void
 cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 {
+	BUG_ON(!cfq_cfqq_on_rr(cfqq));
+	cfq_clear_cfqq_on_rr(cfqq);
 	list_move(&cfqq->cfq_list, &cfqd->empty_list);
-	cfqq->on_rr = 0;
 
 	BUG_ON(!cfqd->busy_queues);
 	cfqd->busy_queues--;
@@ -505,16 +547,17 @@
 
 	if (ON_RB(&crq->rb_node)) {
 		struct cfq_data *cfqd = cfqq->cfqd;
+		const int sync = cfq_crq_is_sync(crq);
 
-		BUG_ON(!cfqq->queued[crq->is_sync]);
+		BUG_ON(!cfqq->queued[sync]);
+		cfqq->queued[sync]--;
 
 		cfq_update_next_crq(crq);
 
-		cfqq->queued[crq->is_sync]--;
 		rb_erase(&crq->rb_node, &cfqq->sort_list);
 		RB_CLEAR_COLOR(&crq->rb_node);
 
-		if (RB_EMPTY(&cfqq->sort_list) && cfqq->on_rr)
+		if (cfq_cfqq_on_rr(cfqq) && RB_EMPTY(&cfqq->sort_list))
 			cfq_del_cfqq_rr(cfqd, cfqq);
 	}
 }
@@ -550,7 +593,7 @@
 	struct cfq_rq *__alias;
 
 	crq->rb_key = rq_rb_key(rq);
-	cfqq->queued[crq->is_sync]++;
+	cfqq->queued[cfq_crq_is_sync(crq)]++;
 
 	/*
 	 * looks a little odd, but the first insert might return an alias.
@@ -561,8 +604,8 @@
 
 	rb_insert_color(&crq->rb_node, &cfqq->sort_list);
 
-	if (!cfqq->on_rr)
-		cfq_add_cfqq_rr(cfqd, cfqq);
+	if (!cfq_cfqq_on_rr(cfqq))
+		cfq_add_cfqq_rr(cfqd, cfqq, cfq_crq_requeued(crq));
 
 	/*
 	 * check if this request is a better next-serve candidate
@@ -575,17 +618,16 @@
 {
 	if (ON_RB(&crq->rb_node)) {
 		rb_erase(&crq->rb_node, &cfqq->sort_list);
-		cfqq->queued[crq->is_sync]--;
+		cfqq->queued[cfq_crq_is_sync(crq)]--;
 	}
 
 	cfq_add_crq_rb(crq);
 }
 
-static struct request *
-cfq_find_rq_rb(struct cfq_data *cfqd, sector_t sector)
+static struct request *cfq_find_rq_rb(struct cfq_data *cfqd, sector_t sector)
+
 {
-	const unsigned long key = cfq_hash_key(cfqd, current);
-	struct cfq_queue *cfqq = cfq_find_cfq_hash(cfqd, key);
+	struct cfq_queue *cfqq = cfq_find_cfq_hash(cfqd, current->pid, CFQ_KEY_ANY);
 	struct rb_node *n;
 
 	if (!cfqq)
@@ -609,20 +651,25 @@
 
 static void cfq_deactivate_request(request_queue_t *q, struct request *rq)
 {
+	struct cfq_data *cfqd = q->elevator->elevator_data;
 	struct cfq_rq *crq = RQ_DATA(rq);
 
 	if (crq) {
 		struct cfq_queue *cfqq = crq->cfq_queue;
 
-		if (cfqq->cfqd->cfq_tagged) {
-			cfqq->service_used--;
-			cfq_sort_rr_list(cfqq, 0);
+		if (cfq_crq_in_driver(crq)) {
+			cfq_clear_crq_in_driver(crq);
+			WARN_ON(!cfqd->rq_in_driver);
+			cfqd->rq_in_driver--;
 		}
+		if (cfq_crq_in_flight(crq)) {
+			const int sync = cfq_crq_is_sync(crq);
 
-		if (crq->accounted) {
-			crq->accounted = 0;
-			cfqq->cfqd->rq_in_driver--;
+			cfq_clear_crq_in_flight(crq);
+			WARN_ON(!cfqq->on_dispatch[sync]);
+			cfqq->on_dispatch[sync]--;
 		}
+		cfq_mark_crq_requeued(crq);
 	}
 }
 
@@ -640,11 +687,10 @@
 	struct cfq_rq *crq = RQ_DATA(rq);
 
 	if (crq) {
-		cfq_remove_merge_hints(q, crq);
 		list_del_init(&rq->queuelist);
+		cfq_del_crq_rb(crq);
+		cfq_remove_merge_hints(q, crq);
 
-		if (crq->cfq_queue)
-			cfq_del_crq_rb(crq);
 	}
 }
 
@@ -662,21 +708,15 @@
 	}
 
 	__rq = cfq_find_rq_hash(cfqd, bio->bi_sector);
-	if (__rq) {
-		BUG_ON(__rq->sector + __rq->nr_sectors != bio->bi_sector);
-
-		if (elv_rq_merge_ok(__rq, bio)) {
-			ret = ELEVATOR_BACK_MERGE;
-			goto out;
-		}
+	if (__rq && elv_rq_merge_ok(__rq, bio)) {
+		ret = ELEVATOR_BACK_MERGE;
+		goto out;
 	}
 
 	__rq = cfq_find_rq_rb(cfqd, bio->bi_sector + bio_sectors(bio));
-	if (__rq) {
-		if (elv_rq_merge_ok(__rq, bio)) {
-			ret = ELEVATOR_FRONT_MERGE;
-			goto out;
-		}
+	if (__rq && elv_rq_merge_ok(__rq, bio)) {
+		ret = ELEVATOR_FRONT_MERGE;
+		goto out;
 	}
 
 	return ELEVATOR_NO_MERGE;
@@ -709,20 +749,220 @@
 cfq_merged_requests(request_queue_t *q, struct request *rq,
 		    struct request *next)
 {
-	struct cfq_rq *crq = RQ_DATA(rq);
-	struct cfq_rq *cnext = RQ_DATA(next);
-
 	cfq_merged_request(q, rq);
 
-	if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist)) {
-		if (time_before(cnext->queue_start, crq->queue_start)) {
-			list_move(&rq->queuelist, &next->queuelist);
-			crq->queue_start = cnext->queue_start;
-		}
+	/*
+	 * reposition in fifo if next is older than rq
+	 */
+	if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist) &&
+	    time_before(next->start_time, rq->start_time))
+		list_move(&rq->queuelist, &next->queuelist);
+
+	cfq_remove_request(q, next);
+}
+
+static inline void
+__cfq_set_active_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
+{
+	if (cfqq) {
+		/*
+		 * stop potential idle class queues waiting service
+		 */
+		del_timer(&cfqd->idle_class_timer);
+
+		cfqq->slice_start = jiffies;
+		cfqq->slice_end = 0;
+		cfqq->slice_left = 0;
+		cfq_clear_cfqq_must_alloc_slice(cfqq);
+		cfq_clear_cfqq_fifo_expire(cfqq);
+		cfq_clear_cfqq_expired(cfqq);
 	}
 
-	cfq_update_next_crq(cnext);
-	cfq_remove_request(q, next);
+	cfqd->active_queue = cfqq;
+}
+
+/*
+ * 0
+ * 0,1
+ * 0,1,2
+ * 0,1,2,3
+ * 0,1,2,3,4
+ * 0,1,2,3,4,5
+ * 0,1,2,3,4,5,6
+ * 0,1,2,3,4,5,6,7
+ */
+static int cfq_get_next_prio_level(struct cfq_data *cfqd)
+{
+	int prio, wrap;
+
+	prio = -1;
+	wrap = 0;
+	do {
+		int p;
+
+		for (p = cfqd->cur_prio; p <= cfqd->cur_end_prio; p++) {
+			if (!list_empty(&cfqd->rr_list[p])) {
+				prio = p;
+				break;
+			}
+		}
+
+		if (prio != -1)
+			break;
+		cfqd->cur_prio = 0;
+		if (++cfqd->cur_end_prio == CFQ_PRIO_LISTS) {
+			cfqd->cur_end_prio = 0;
+			if (wrap)
+				break;
+			wrap = 1;
+		}
+	} while (1);
+
+	if (unlikely(prio == -1))
+		return -1;
+
+	BUG_ON(prio >= CFQ_PRIO_LISTS);
+
+	list_splice_init(&cfqd->rr_list[prio], &cfqd->cur_rr);
+
+	cfqd->cur_prio = prio + 1;
+	if (cfqd->cur_prio > cfqd->cur_end_prio) {
+		cfqd->cur_end_prio = cfqd->cur_prio;
+		cfqd->cur_prio = 0;
+	}
+	if (cfqd->cur_end_prio == CFQ_PRIO_LISTS) {
+		cfqd->cur_prio = 0;
+		cfqd->cur_end_prio = 0;
+	}
+
+	return prio;
+}
+
+static struct cfq_queue *cfq_set_active_queue(struct cfq_data *cfqd)
+{
+	struct cfq_queue *cfqq;
+
+	/*
+	 * if current queue is expired but not done with its requests yet,
+	 * wait for that to happen
+	 */
+	if ((cfqq = cfqd->active_queue) != NULL) {
+		if (cfq_cfqq_expired(cfqq) && cfq_cfqq_dispatched(cfqq))
+			return NULL;
+	}
+
+	/*
+	 * if current list is non-empty, grab first entry. if it is empty,
+	 * get next prio level and grab first entry then if any are spliced
+	 */
+	if (!list_empty(&cfqd->cur_rr) || cfq_get_next_prio_level(cfqd) != -1)
+		cfqq = list_entry_cfqq(cfqd->cur_rr.next);
+
+	/*
+	 * if we have idle queues and no rt or be queues had pending
+	 * requests, either allow immediate service if the grace period
+	 * has passed or arm the idle grace timer
+	 */
+	if (!cfqq && !list_empty(&cfqd->idle_rr)) {
+		unsigned long end = cfqd->last_end_request + CFQ_IDLE_GRACE;
+
+		if (time_after_eq(jiffies, end))
+			cfqq = list_entry_cfqq(cfqd->idle_rr.next);
+		else
+			mod_timer(&cfqd->idle_class_timer, end);
+	}
+
+	__cfq_set_active_queue(cfqd, cfqq);
+	return cfqq;
+}
+
+/*
+ * current cfqq expired its slice (or was too idle), select new one
+ */
+static void
+__cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq,
+		    int preempted)
+{
+	unsigned long now = jiffies;
+
+	if (cfq_cfqq_wait_request(cfqq))
+		del_timer(&cfqd->idle_slice_timer);
+
+	if (!preempted && !cfq_cfqq_dispatched(cfqq))
+		cfqq->service_last = now;
+
+	cfq_clear_cfqq_must_dispatch(cfqq);
+	cfq_clear_cfqq_wait_request(cfqq);
+
+	/*
+	 * store what was left of this slice, if the queue idled out
+	 * or was preempted
+	 */
+	if (time_after(now, cfqq->slice_end))
+		cfqq->slice_left = now - cfqq->slice_end;
+	else
+		cfqq->slice_left = 0;
+
+	if (cfq_cfqq_on_rr(cfqq))
+		cfq_resort_rr_list(cfqq, preempted);
+
+	if (cfqq == cfqd->active_queue)
+		cfqd->active_queue = NULL;
+
+	if (cfqd->active_cic) {
+		put_io_context(cfqd->active_cic->ioc);
+		cfqd->active_cic = NULL;
+	}
+
+	cfqd->dispatch_slice = 0;
+}
+
+static inline void cfq_slice_expired(struct cfq_data *cfqd, int preempted)
+{
+	struct cfq_queue *cfqq = cfqd->active_queue;
+
+	if (cfqq) {
+		/*
+		 * use deferred expiry, if there are requests in progress as
+		 * not to disturb the slice of the next queue
+		 */
+		if (cfq_cfqq_dispatched(cfqq))
+			cfq_mark_cfqq_expired(cfqq);
+		else
+			__cfq_slice_expired(cfqd, cfqq, preempted);
+	}
+}
+
+static int cfq_arm_slice_timer(struct cfq_data *cfqd, struct cfq_queue *cfqq)
+
+{
+	WARN_ON(!RB_EMPTY(&cfqq->sort_list));
+	WARN_ON(cfqq != cfqd->active_queue);
+
+	/*
+	 * idle is disabled, either manually or by past process history
+	 */
+	if (!cfqd->cfq_slice_idle)
+		return 0;
+	if (!cfq_cfqq_idle_window(cfqq))
+		return 0;
+	/*
+	 * task has exited, don't wait
+	 */
+	if (cfqd->active_cic && !cfqd->active_cic->ioc->task)
+		return 0;
+
+	cfq_mark_cfqq_must_dispatch(cfqq);
+	cfq_mark_cfqq_wait_request(cfqq);
+
+	if (!timer_pending(&cfqd->idle_slice_timer)) {
+		unsigned long slice_left = min(cfqq->slice_end - 1, (unsigned long) cfqd->cfq_slice_idle);
+
+		cfqd->idle_slice_timer.expires = jiffies + slice_left;
+		add_timer(&cfqd->idle_slice_timer);
+	}
+
+	return 1;
 }
 
 /*
@@ -738,31 +978,40 @@
 	struct request *__rq;
 	sector_t last;
 
-	cfq_del_crq_rb(crq);
-	cfq_remove_merge_hints(q, crq);
 	list_del(&crq->request->queuelist);
 
 	last = cfqd->last_sector;
-	while ((entry = entry->prev) != head) {
-		__rq = list_entry_rq(entry);
+	list_for_each_entry_reverse(__rq, head, queuelist) {
+		struct cfq_rq *__crq = RQ_DATA(__rq);
 
-		if (blk_barrier_rq(crq->request))
+		if (blk_barrier_rq(__rq))
 			break;
-		if (!blk_fs_request(crq->request))
+		if (!blk_fs_request(__rq))
+			break;
+		if (cfq_crq_requeued(__crq))
 			break;
 
-		if (crq->request->sector > __rq->sector)
+		if (__rq->sector <= crq->request->sector)
 			break;
 		if (__rq->sector > last && crq->request->sector < last) {
-			last = crq->request->sector;
+			last = crq->request->sector + crq->request->nr_sectors;
 			break;
 		}
+		entry = &__rq->queuelist;
 	}
 
 	cfqd->last_sector = last;
-	crq->in_flight = 1;
-	cfqq->in_flight++;
-	list_add(&crq->request->queuelist, entry);
+
+	cfqq->next_crq = cfq_find_next_crq(cfqd, cfqq, crq);
+
+	cfq_del_crq_rb(crq);
+	cfq_remove_merge_hints(q, crq);
+
+	cfq_mark_crq_in_flight(crq);
+	cfq_clear_crq_requeued(crq);
+
+	cfqq->on_dispatch[cfq_crq_is_sync(crq)]++;
+	list_add_tail(&crq->request->queuelist, entry);
 }
 
 /*
@@ -771,173 +1020,235 @@
 static inline struct cfq_rq *cfq_check_fifo(struct cfq_queue *cfqq)
 {
 	struct cfq_data *cfqd = cfqq->cfqd;
-	const int reads = !list_empty(&cfqq->fifo[0]);
-	const int writes = !list_empty(&cfqq->fifo[1]);
-	unsigned long now = jiffies;
+	struct request *rq;
 	struct cfq_rq *crq;
 
-	if (time_before(now, cfqq->last_fifo_expire + cfqd->cfq_fifo_batch_expire))
+	if (cfq_cfqq_fifo_expire(cfqq))
 		return NULL;
 
-	crq = RQ_DATA(list_entry(cfqq->fifo[0].next, struct request, queuelist));
-	if (reads && time_after(now, crq->queue_start + cfqd->cfq_fifo_expire_r)) {
-		cfqq->last_fifo_expire = now;
-		return crq;
-	}
+	if (!list_empty(&cfqq->fifo)) {
+		int fifo = cfq_cfqq_class_sync(cfqq);
 
-	crq = RQ_DATA(list_entry(cfqq->fifo[1].next, struct request, queuelist));
-	if (writes && time_after(now, crq->queue_start + cfqd->cfq_fifo_expire_w)) {
-		cfqq->last_fifo_expire = now;
-		return crq;
+		crq = RQ_DATA(list_entry_fifo(cfqq->fifo.next));
+		rq = crq->request;
+		if (time_after(jiffies, rq->start_time + cfqd->cfq_fifo_expire[fifo])) {
+			cfq_mark_cfqq_fifo_expire(cfqq);
+			return crq;
+		}
 	}
 
 	return NULL;
 }
 
 /*
- * dispatch a single request from given queue
+ * Scale schedule slice based on io priority. Use the sync time slice only
+ * if a queue is marked sync and has sync io queued. A sync queue with async
+ * io only, should not get full sync slice length.
  */
-static inline void
-cfq_dispatch_request(request_queue_t *q, struct cfq_data *cfqd,
-		     struct cfq_queue *cfqq)
+static inline int
+cfq_prio_to_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
 {
-	struct cfq_rq *crq;
+	const int base_slice = cfqd->cfq_slice[cfq_cfqq_sync(cfqq)];
 
-	/*
-	 * follow expired path, else get first next available
-	 */
-	if ((crq = cfq_check_fifo(cfqq)) == NULL) {
-		if (cfqd->find_best_crq)
-			crq = cfqq->next_crq;
-		else
-			crq = rb_entry_crq(rb_first(&cfqq->sort_list));
-	}
+	WARN_ON(cfqq->ioprio >= IOPRIO_BE_NR);
 
-	cfqd->last_sector = crq->request->sector + crq->request->nr_sectors;
-
-	/*
-	 * finally, insert request into driver list
-	 */
-	cfq_dispatch_sort(q, crq);
+	return base_slice + (base_slice/CFQ_SLICE_SCALE * (4 - cfqq->ioprio));
 }
 
-static int cfq_dispatch_requests(request_queue_t *q, int max_dispatch)
+static inline void
+cfq_set_prio_slice(struct cfq_data *cfqd, struct cfq_queue *cfqq)
+{
+	cfqq->slice_end = cfq_prio_to_slice(cfqd, cfqq) + jiffies;
+}
+
+static inline int
+cfq_prio_to_maxrq(struct cfq_data *cfqd, struct cfq_queue *cfqq)
+{
+	const int base_rq = cfqd->cfq_slice_async_rq;
+
+	WARN_ON(cfqq->ioprio >= IOPRIO_BE_NR);
+
+	return 2 * (base_rq + base_rq * (CFQ_PRIO_LISTS - 1 - cfqq->ioprio));
+}
+
+/*
+ * scheduler run of queue, if there are requests pending and no one in the
+ * driver that will restart queueing
+ */
+static inline void cfq_schedule_dispatch(struct cfq_data *cfqd)
+{
+	if (!cfqd->rq_in_driver && cfq_pending_requests(cfqd))
+		kblockd_schedule_work(&cfqd->unplug_work);
+}
+
+/*
+ * get next queue for service
+ */
+static struct cfq_queue *cfq_select_queue(struct cfq_data *cfqd, int force)
+{
+	unsigned long now = jiffies;
+	struct cfq_queue *cfqq;
+
+	cfqq = cfqd->active_queue;
+	if (!cfqq)
+		goto new_queue;
+
+	if (cfq_cfqq_expired(cfqq))
+		goto new_queue;
+
+	/*
+	 * slice has expired
+	 */
+	if (!cfq_cfqq_must_dispatch(cfqq) && time_after(now, cfqq->slice_end))
+		goto expire;
+
+	/*
+	 * if queue has requests, dispatch one. if not, check if
+	 * enough slice is left to wait for one
+	 */
+	if (!RB_EMPTY(&cfqq->sort_list))
+		goto keep_queue;
+	else if (!force && cfq_cfqq_class_sync(cfqq) &&
+		 time_before(now, cfqq->slice_end)) {
+		if (cfq_arm_slice_timer(cfqd, cfqq))
+			return NULL;
+	}
+
+expire:
+	cfq_slice_expired(cfqd, 0);
+new_queue:
+	cfqq = cfq_set_active_queue(cfqd);
+keep_queue:
+	return cfqq;
+}
+
+static int
+__cfq_dispatch_requests(struct cfq_data *cfqd, struct cfq_queue *cfqq,
+			int max_dispatch)
+{
+	int dispatched = 0;
+
+	BUG_ON(RB_EMPTY(&cfqq->sort_list));
+
+	do {
+		struct cfq_rq *crq;
+
+		/*
+		 * follow expired path, else get first next available
+		 */
+		if ((crq = cfq_check_fifo(cfqq)) == NULL)
+			crq = cfqq->next_crq;
+
+		/*
+		 * finally, insert request into driver dispatch list
+		 */
+		cfq_dispatch_sort(cfqd->queue, crq);
+
+		cfqd->dispatch_slice++;
+		dispatched++;
+
+		if (!cfqd->active_cic) {
+			atomic_inc(&crq->io_context->ioc->refcount);
+			cfqd->active_cic = crq->io_context;
+		}
+
+		if (RB_EMPTY(&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 (!cfqq->slice_end)
+		cfq_set_prio_slice(cfqd, cfqq);
+
+	/*
+	 * expire an async queue immediately if it has used up its slice. idle
+	 * queue always expire after 1 dispatch round.
+	 */
+	if ((!cfq_cfqq_sync(cfqq) &&
+	    cfqd->dispatch_slice >= cfq_prio_to_maxrq(cfqd, cfqq)) ||
+	    cfq_class_idle(cfqq))
+		cfq_slice_expired(cfqd, 0);
+
+	return dispatched;
+}
+
+static int
+cfq_dispatch_requests(request_queue_t *q, int max_dispatch, int force)
 {
 	struct cfq_data *cfqd = q->elevator->elevator_data;
 	struct cfq_queue *cfqq;
-	struct list_head *entry, *tmp;
-	int queued, busy_queues, first_round;
 
-	if (list_empty(&cfqd->rr_list))
+	if (!cfqd->busy_queues)
 		return 0;
 
-	queued = 0;
-	first_round = 1;
-restart:
-	busy_queues = 0;
-	list_for_each_safe(entry, tmp, &cfqd->rr_list) {
-		cfqq = list_entry_cfqq(entry);
+	cfqq = cfq_select_queue(cfqd, force);
+	if (cfqq) {
+		cfq_clear_cfqq_must_dispatch(cfqq);
+		cfq_clear_cfqq_wait_request(cfqq);
+		del_timer(&cfqd->idle_slice_timer);
 
-		BUG_ON(RB_EMPTY(&cfqq->sort_list));
+		if (cfq_class_idle(cfqq))
+			max_dispatch = 1;
 
-		/*
-		 * first round of queueing, only select from queues that
-		 * don't already have io in-flight
-		 */
-		if (first_round && cfqq->in_flight)
-			continue;
-
-		cfq_dispatch_request(q, cfqd, cfqq);
-
-		if (!RB_EMPTY(&cfqq->sort_list))
-			busy_queues++;
-
-		queued++;
+		return __cfq_dispatch_requests(cfqd, cfqq, max_dispatch);
 	}
 
-	if ((queued < max_dispatch) && (busy_queues || first_round)) {
-		first_round = 0;
-		goto restart;
-	}
-
-	return queued;
+	return 0;
 }
 
 static inline void cfq_account_dispatch(struct cfq_rq *crq)
 {
 	struct cfq_queue *cfqq = crq->cfq_queue;
 	struct cfq_data *cfqd = cfqq->cfqd;
-	unsigned long now, elapsed;
 
-	if (!blk_fs_request(crq->request))
+	if (unlikely(!blk_fs_request(crq->request)))
 		return;
 
 	/*
 	 * accounted bit is necessary since some drivers will call
 	 * elv_next_request() many times for the same request (eg ide)
 	 */
-	if (crq->accounted)
+	if (cfq_crq_in_driver(crq))
 		return;
 
-	now = jiffies;
-	if (cfqq->service_start == ~0UL)
-		cfqq->service_start = now;
-
-	/*
-	 * on drives with tagged command queueing, command turn-around time
-	 * doesn't necessarily reflect the time spent processing this very
-	 * command inside the drive. so do the accounting differently there,
-	 * by just sorting on the number of requests
-	 */
-	if (cfqd->cfq_tagged) {
-		if (time_after(now, cfqq->service_start + cfq_service)) {
-			cfqq->service_start = now;
-			cfqq->service_used /= 10;
-		}
-
-		cfqq->service_used++;
-		cfq_sort_rr_list(cfqq, 0);
-	}
-
-	elapsed = now - crq->queue_start;
-	if (elapsed > max_elapsed_dispatch)
-		max_elapsed_dispatch = elapsed;
-
-	crq->accounted = 1;
-	crq->service_start = now;
-
-	if (++cfqd->rq_in_driver >= CFQ_MAX_TAG && !cfqd->cfq_tagged) {
-		cfqq->cfqd->cfq_tagged = 1;
-		printk("cfq: depth %d reached, tagging now on\n", CFQ_MAX_TAG);
-	}
+	cfq_mark_crq_in_driver(crq);
+	cfqd->rq_in_driver++;
 }
 
 static inline void
 cfq_account_completion(struct cfq_queue *cfqq, struct cfq_rq *crq)
 {
 	struct cfq_data *cfqd = cfqq->cfqd;
+	unsigned long now;
 
-	if (!crq->accounted)
+	if (!cfq_crq_in_driver(crq))
 		return;
 
+	now = jiffies;
+
 	WARN_ON(!cfqd->rq_in_driver);
 	cfqd->rq_in_driver--;
 
-	if (!cfqd->cfq_tagged) {
-		unsigned long now = jiffies;
-		unsigned long duration = now - crq->service_start;
+	if (!cfq_class_idle(cfqq))
+		cfqd->last_end_request = now;
 
-		if (time_after(now, cfqq->service_start + cfq_service)) {
-			cfqq->service_start = now;
-			cfqq->service_used >>= 3;
+	if (!cfq_cfqq_dispatched(cfqq)) {
+		if (cfq_cfqq_on_rr(cfqq)) {
+			cfqq->service_last = now;
+			cfq_resort_rr_list(cfqq, 0);
 		}
-
-		cfqq->service_used += duration;
-		cfq_sort_rr_list(cfqq, 0);
-
-		if (duration > max_elapsed_crq)
-			max_elapsed_crq = duration;
+		if (cfq_cfqq_expired(cfqq)) {
+			__cfq_slice_expired(cfqd, cfqq, 0);
+			cfq_schedule_dispatch(cfqd);
+		}
 	}
+
+	if (cfq_crq_is_sync(crq))
+		crq->io_context->last_end_request = now;
 }
 
 static struct request *cfq_next_request(request_queue_t *q)
@@ -950,7 +1261,18 @@
 dispatch:
 		rq = list_entry_rq(q->queue_head.next);
 
-		if ((crq = RQ_DATA(rq)) != NULL) {
+		crq = RQ_DATA(rq);
+		if (crq) {
+			struct cfq_queue *cfqq = crq->cfq_queue;
+
+			/*
+			 * if idle window is disabled, allow queue buildup
+			 */
+			if (!cfq_crq_in_driver(crq) &&
+			    !cfq_cfqq_idle_window(cfqq) &&
+			    cfqd->rq_in_driver >= cfqd->cfq_max_depth)
+				return NULL;
+
 			cfq_remove_merge_hints(q, crq);
 			cfq_account_dispatch(crq);
 		}
@@ -958,7 +1280,7 @@
 		return rq;
 	}
 
-	if (cfq_dispatch_requests(q, cfqd->cfq_quantum))
+	if (cfq_dispatch_requests(q, cfqd->cfq_quantum, 0))
 		goto dispatch;
 
 	return NULL;
@@ -972,13 +1294,21 @@
  */
 static void cfq_put_queue(struct cfq_queue *cfqq)
 {
-	BUG_ON(!atomic_read(&cfqq->ref));
+	struct cfq_data *cfqd = cfqq->cfqd;
+
+	BUG_ON(atomic_read(&cfqq->ref) <= 0);
 
 	if (!atomic_dec_and_test(&cfqq->ref))
 		return;
 
 	BUG_ON(rb_first(&cfqq->sort_list));
-	BUG_ON(cfqq->on_rr);
+	BUG_ON(cfqq->allocated[READ] + cfqq->allocated[WRITE]);
+	BUG_ON(cfq_cfqq_on_rr(cfqq));
+
+	if (unlikely(cfqd->active_queue == cfqq)) {
+		__cfq_slice_expired(cfqd, cfqq, 0);
+		cfq_schedule_dispatch(cfqd);
+	}
 
 	cfq_put_cfqd(cfqq->cfqd);
 
@@ -991,15 +1321,17 @@
 }
 
 static inline struct cfq_queue *
-__cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned long key, const int hashval)
+__cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned int prio,
+		    const int hashval)
 {
 	struct hlist_head *hash_list = &cfqd->cfq_hash[hashval];
 	struct hlist_node *entry, *next;
 
 	hlist_for_each_safe(entry, next, hash_list) {
 		struct cfq_queue *__cfqq = list_entry_qhash(entry);
+		const unsigned short __p = IOPRIO_PRIO_VALUE(__cfqq->ioprio_class, __cfqq->ioprio);
 
-		if (__cfqq->key == key)
+		if (__cfqq->key == key && (__p == prio || prio == CFQ_KEY_ANY))
 			return __cfqq;
 	}
 
@@ -1007,196 +1339,173 @@
 }
 
 static struct cfq_queue *
-cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned long key)
+cfq_find_cfq_hash(struct cfq_data *cfqd, unsigned int key, unsigned short prio)
 {
-	return __cfq_find_cfq_hash(cfqd, key, hash_long(key, CFQ_QHASH_SHIFT));
-}
-
-static inline void
-cfq_rehash_cfqq(struct cfq_data *cfqd, struct cfq_queue **cfqq,
-		struct cfq_io_context *cic)
-{
-	unsigned long hashkey = cfq_hash_key(cfqd, current);
-	unsigned long hashval = hash_long(hashkey, CFQ_QHASH_SHIFT);
-	struct cfq_queue *__cfqq;
-	unsigned long flags;
-
-	spin_lock_irqsave(cfqd->queue->queue_lock, flags);
-
-	hlist_del(&(*cfqq)->cfq_hash);
-
-	__cfqq = __cfq_find_cfq_hash(cfqd, hashkey, hashval);
-	if (!__cfqq || __cfqq == *cfqq) {
-		__cfqq = *cfqq;
-		hlist_add_head(&__cfqq->cfq_hash, &cfqd->cfq_hash[hashval]);
-		__cfqq->key_type = cfqd->key_type;
-	} else {
-		atomic_inc(&__cfqq->ref);
-		cic->cfqq = __cfqq;
-		cfq_put_queue(*cfqq);
-		*cfqq = __cfqq;
-	}
-
-	cic->cfqq = __cfqq;
-	spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
+	return __cfq_find_cfq_hash(cfqd, key, prio, hash_long(key, CFQ_QHASH_SHIFT));
 }
 
 static void cfq_free_io_context(struct cfq_io_context *cic)
 {
+	struct cfq_io_context *__cic;
+	struct list_head *entry, *next;
+
+	list_for_each_safe(entry, next, &cic->list) {
+		__cic = list_entry(entry, struct cfq_io_context, list);
+		kmem_cache_free(cfq_ioc_pool, __cic);
+	}
+
 	kmem_cache_free(cfq_ioc_pool, cic);
 }
 
 /*
- * locking hierarchy is: io_context lock -> queue locks
+ * Called with interrupts disabled
+ */
+static void cfq_exit_single_io_context(struct cfq_io_context *cic)
+{
+	struct cfq_data *cfqd = cic->cfqq->cfqd;
+	request_queue_t *q = cfqd->queue;
+
+	WARN_ON(!irqs_disabled());
+
+	spin_lock(q->queue_lock);
+
+	if (unlikely(cic->cfqq == cfqd->active_queue)) {
+		__cfq_slice_expired(cfqd, cic->cfqq, 0);
+		cfq_schedule_dispatch(cfqd);
+	}
+
+	cfq_put_queue(cic->cfqq);
+	cic->cfqq = NULL;
+	spin_unlock(q->queue_lock);
+}
+
+/*
+ * Another task may update the task cic list, if it is doing a queue lookup
+ * on its behalf. cfq_cic_lock excludes such concurrent updates
  */
 static void cfq_exit_io_context(struct cfq_io_context *cic)
 {
-	struct cfq_queue *cfqq = cic->cfqq;
-	struct list_head *entry = &cic->list;
-	request_queue_t *q;
+	struct cfq_io_context *__cic;
+	struct list_head *entry;
 	unsigned long flags;
 
+	local_irq_save(flags);
+
 	/*
 	 * put the reference this task is holding to the various queues
 	 */
-	spin_lock_irqsave(&cic->ioc->lock, flags);
-	while ((entry = cic->list.next) != &cic->list) {
-		struct cfq_io_context *__cic;
-
+	list_for_each(entry, &cic->list) {
 		__cic = list_entry(entry, struct cfq_io_context, list);
-		list_del(entry);
-
-		q = __cic->cfqq->cfqd->queue;
-		spin_lock(q->queue_lock);
-		cfq_put_queue(__cic->cfqq);
-		spin_unlock(q->queue_lock);
+		cfq_exit_single_io_context(__cic);
 	}
 
-	q = cfqq->cfqd->queue;
-	spin_lock(q->queue_lock);
-	cfq_put_queue(cfqq);
-	spin_unlock(q->queue_lock);
-
-	cic->cfqq = NULL;
-	spin_unlock_irqrestore(&cic->ioc->lock, flags);
+	cfq_exit_single_io_context(cic);
+	local_irq_restore(flags);
 }
 
-static struct cfq_io_context *cfq_alloc_io_context(int gfp_flags)
+static struct cfq_io_context *
+cfq_alloc_io_context(struct cfq_data *cfqd, int gfp_mask)
 {
-	struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_flags);
+	struct cfq_io_context *cic = kmem_cache_alloc(cfq_ioc_pool, gfp_mask);
 
 	if (cic) {
-		cic->dtor = cfq_free_io_context;
-		cic->exit = cfq_exit_io_context;
 		INIT_LIST_HEAD(&cic->list);
 		cic->cfqq = NULL;
+		cic->key = NULL;
+		cic->last_end_request = jiffies;
+		cic->ttime_total = 0;
+		cic->ttime_samples = 0;
+		cic->ttime_mean = 0;
+		cic->dtor = cfq_free_io_context;
+		cic->exit = cfq_exit_io_context;
 	}
 
 	return cic;
 }
 
+static void cfq_init_prio_data(struct cfq_queue *cfqq)
+{
+	struct task_struct *tsk = current;
+	int ioprio_class;
+
+	if (!cfq_cfqq_prio_changed(cfqq))
+		return;
+
+	ioprio_class = IOPRIO_PRIO_CLASS(tsk->ioprio);
+	switch (ioprio_class) {
+		default:
+			printk(KERN_ERR "cfq: bad prio %x\n", ioprio_class);
+		case IOPRIO_CLASS_NONE:
+			/*
+			 * no prio set, place us in the middle of the BE classes
+			 */
+			cfqq->ioprio = task_nice_ioprio(tsk);
+			cfqq->ioprio_class = IOPRIO_CLASS_BE;
+			break;
+		case IOPRIO_CLASS_RT:
+			cfqq->ioprio = task_ioprio(tsk);
+			cfqq->ioprio_class = IOPRIO_CLASS_RT;
+			break;
+		case IOPRIO_CLASS_BE:
+			cfqq->ioprio = task_ioprio(tsk);
+			cfqq->ioprio_class = IOPRIO_CLASS_BE;
+			break;
+		case IOPRIO_CLASS_IDLE:
+			cfqq->ioprio_class = IOPRIO_CLASS_IDLE;
+			cfqq->ioprio = 7;
+			cfq_clear_cfqq_idle_window(cfqq);
+			break;
+	}
+
+	/*
+	 * keep track of original prio settings in case we have to temporarily
+	 * elevate the priority of this queue
+	 */
+	cfqq->org_ioprio = cfqq->ioprio;
+	cfqq->org_ioprio_class = cfqq->ioprio_class;
+
+	if (cfq_cfqq_on_rr(cfqq))
+		cfq_resort_rr_list(cfqq, 0);
+
+	cfq_clear_cfqq_prio_changed(cfqq);
+}
+
+static inline void changed_ioprio(struct cfq_queue *cfqq)
+{
+	if (cfqq) {
+		struct cfq_data *cfqd = cfqq->cfqd;
+
+		spin_lock(cfqd->queue->queue_lock);
+		cfq_mark_cfqq_prio_changed(cfqq);
+		cfq_init_prio_data(cfqq);
+		spin_unlock(cfqd->queue->queue_lock);
+	}
+}
+
 /*
- * Setup general io context and cfq io context. There can be several cfq
- * io contexts per general io context, if this process is doing io to more
- * than one device managed by cfq. Note that caller is holding a reference to
- * cfqq, so we don't need to worry about it disappearing
+ * callback from sys_ioprio_set, irqs are disabled
  */
-static struct cfq_io_context *
-cfq_get_io_context(struct cfq_queue **cfqq, int gfp_flags)
+static int cfq_ioc_set_ioprio(struct io_context *ioc, unsigned int ioprio)
 {
-	struct cfq_data *cfqd = (*cfqq)->cfqd;
-	struct cfq_queue *__cfqq = *cfqq;
-	struct cfq_io_context *cic;
-	struct io_context *ioc;
+	struct cfq_io_context *cic = ioc->cic;
 
-	might_sleep_if(gfp_flags & __GFP_WAIT);
+	changed_ioprio(cic->cfqq);
 
-	ioc = get_io_context(gfp_flags);
-	if (!ioc)
-		return NULL;
+	list_for_each_entry(cic, &cic->list, list)
+		changed_ioprio(cic->cfqq);
 
-	if ((cic = ioc->cic) == NULL) {
-		cic = cfq_alloc_io_context(gfp_flags);
-
-		if (cic == NULL)
-			goto err;
-
-		ioc->cic = cic;
-		cic->ioc = ioc;
-		cic->cfqq = __cfqq;
-		atomic_inc(&__cfqq->ref);
-	} else {
-		struct cfq_io_context *__cic;
-		unsigned long flags;
-
-		/*
-		 * since the first cic on the list is actually the head
-		 * itself, need to check this here or we'll duplicate an
-		 * cic per ioc for no reason
-		 */
-		if (cic->cfqq == __cfqq)
-			goto out;
-
-		/*
-		 * cic exists, check if we already are there. linear search
-		 * should be ok here, the list will usually not be more than
-		 * 1 or a few entries long
-		 */
-		spin_lock_irqsave(&ioc->lock, flags);
-		list_for_each_entry(__cic, &cic->list, list) {
-			/*
-			 * this process is already holding a reference to
-			 * this queue, so no need to get one more
-			 */
-			if (__cic->cfqq == __cfqq) {
-				cic = __cic;
-				spin_unlock_irqrestore(&ioc->lock, flags);
-				goto out;
-			}
-		}
-		spin_unlock_irqrestore(&ioc->lock, flags);
-
-		/*
-		 * nope, process doesn't have a cic assoicated with this
-		 * cfqq yet. get a new one and add to list
-		 */
-		__cic = cfq_alloc_io_context(gfp_flags);
-		if (__cic == NULL)
-			goto err;
-
-		__cic->ioc = ioc;
-		__cic->cfqq = __cfqq;
-		atomic_inc(&__cfqq->ref);
-		spin_lock_irqsave(&ioc->lock, flags);
-		list_add(&__cic->list, &cic->list);
-		spin_unlock_irqrestore(&ioc->lock, flags);
-
-		cic = __cic;
-		*cfqq = __cfqq;
-	}
-
-out:
-	/*
-	 * if key_type has been changed on the fly, we lazily rehash
-	 * each queue at lookup time
-	 */
-	if ((*cfqq)->key_type != cfqd->key_type)
-		cfq_rehash_cfqq(cfqd, cfqq, cic);
-
-	return cic;
-err:
-	put_io_context(ioc);
-	return NULL;
+	return 0;
 }
 
 static struct cfq_queue *
-__cfq_get_queue(struct cfq_data *cfqd, unsigned long key, int gfp_mask)
+cfq_get_queue(struct cfq_data *cfqd, unsigned int key, unsigned short ioprio,
+	      int gfp_mask)
 {
 	const int hashval = hash_long(key, CFQ_QHASH_SHIFT);
 	struct cfq_queue *cfqq, *new_cfqq = NULL;
 
 retry:
-	cfqq = __cfq_find_cfq_hash(cfqd, key, hashval);
+	cfqq = __cfq_find_cfq_hash(cfqd, key, ioprio, hashval);
 
 	if (!cfqq) {
 		if (new_cfqq) {
@@ -1207,24 +1516,32 @@
 			new_cfqq = kmem_cache_alloc(cfq_pool, gfp_mask);
 			spin_lock_irq(cfqd->queue->queue_lock);
 			goto retry;
-		} else
-			goto out;
+		} else {
+			cfqq = kmem_cache_alloc(cfq_pool, gfp_mask);
+			if (!cfqq)
+				goto out;
+		}
 
 		memset(cfqq, 0, sizeof(*cfqq));
 
 		INIT_HLIST_NODE(&cfqq->cfq_hash);
 		INIT_LIST_HEAD(&cfqq->cfq_list);
 		RB_CLEAR_ROOT(&cfqq->sort_list);
-		INIT_LIST_HEAD(&cfqq->fifo[0]);
-		INIT_LIST_HEAD(&cfqq->fifo[1]);
+		INIT_LIST_HEAD(&cfqq->fifo);
 
 		cfqq->key = key;
 		hlist_add_head(&cfqq->cfq_hash, &cfqd->cfq_hash[hashval]);
 		atomic_set(&cfqq->ref, 0);
 		cfqq->cfqd = cfqd;
 		atomic_inc(&cfqd->ref);
-		cfqq->key_type = cfqd->key_type;
-		cfqq->service_start = ~0UL;
+		cfqq->service_last = 0;
+		/*
+		 * set ->slice_left to allow preemption for a new process
+		 */
+		cfqq->slice_left = 2 * cfqd->cfq_slice_idle;
+		cfq_mark_cfqq_idle_window(cfqq);
+		cfq_mark_cfqq_prio_changed(cfqq);
+		cfq_init_prio_data(cfqq);
 	}
 
 	if (new_cfqq)
@@ -1236,55 +1553,309 @@
 	return cfqq;
 }
 
-static void cfq_enqueue(struct cfq_data *cfqd, struct cfq_rq *crq)
+/*
+ * Setup general io context and cfq io context. There can be several cfq
+ * io contexts per general io context, if this process is doing io to more
+ * than one device managed by cfq. Note that caller is holding a reference to
+ * cfqq, so we don't need to worry about it disappearing
+ */
+static struct cfq_io_context *
+cfq_get_io_context(struct cfq_data *cfqd, pid_t pid, int gfp_mask)
 {
-	crq->is_sync = 0;
-	if (rq_data_dir(crq->request) == READ || current->flags & PF_SYNCWRITE)
-		crq->is_sync = 1;
+	struct io_context *ioc = NULL;
+	struct cfq_io_context *cic;
+
+	might_sleep_if(gfp_mask & __GFP_WAIT);
+
+	ioc = get_io_context(gfp_mask);
+	if (!ioc)
+		return NULL;
+
+	if ((cic = ioc->cic) == NULL) {
+		cic = cfq_alloc_io_context(cfqd, gfp_mask);
+
+		if (cic == NULL)
+			goto err;
+
+		/*
+		 * manually increment generic io_context usage count, it
+		 * cannot go away since we are already holding one ref to it
+		 */
+		ioc->cic = cic;
+		ioc->set_ioprio = cfq_ioc_set_ioprio;
+		cic->ioc = ioc;
+		cic->key = cfqd;
+		atomic_inc(&cfqd->ref);
+	} else {
+		struct cfq_io_context *__cic;
+
+		/*
+		 * the first cic on the list is actually the head itself
+		 */
+		if (cic->key == cfqd)
+			goto out;
+
+		/*
+		 * cic exists, check if we already are there. linear search
+		 * should be ok here, the list will usually not be more than
+		 * 1 or a few entries long
+		 */
+		list_for_each_entry(__cic, &cic->list, list) {
+			/*
+			 * this process is already holding a reference to
+			 * this queue, so no need to get one more
+			 */
+			if (__cic->key == cfqd) {
+				cic = __cic;
+				goto out;
+			}
+		}
+
+		/*
+		 * nope, process doesn't have a cic assoicated with this
+		 * cfqq yet. get a new one and add to list
+		 */
+		__cic = cfq_alloc_io_context(cfqd, gfp_mask);
+		if (__cic == NULL)
+			goto err;
+
+		__cic->ioc = ioc;
+		__cic->key = cfqd;
+		atomic_inc(&cfqd->ref);
+		list_add(&__cic->list, &cic->list);
+		cic = __cic;
+	}
+
+out:
+	return cic;
+err:
+	put_io_context(ioc);
+	return NULL;
+}
+
+static void
+cfq_update_io_thinktime(struct cfq_data *cfqd, struct cfq_io_context *cic)
+{
+	unsigned long elapsed, ttime;
+
+	/*
+	 * if this context already has stuff queued, thinktime is from
+	 * last queue not last end
+	 */
+#if 0
+	if (time_after(cic->last_end_request, cic->last_queue))
+		elapsed = jiffies - cic->last_end_request;
+	else
+		elapsed = jiffies - cic->last_queue;
+#else
+		elapsed = jiffies - cic->last_end_request;
+#endif
+
+	ttime = min(elapsed, 2UL * cfqd->cfq_slice_idle);
+
+	cic->ttime_samples = (7*cic->ttime_samples + 256) / 8;
+	cic->ttime_total = (7*cic->ttime_total + 256*ttime) / 8;
+	cic->ttime_mean = (cic->ttime_total + 128) / cic->ttime_samples;
+}
+
+#define sample_valid(samples)	((samples) > 80)
+
+/*
+ * Disable idle window if the process thinks too long or seeks so much that
+ * it doesn't matter
+ */
+static void
+cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq,
+		       struct cfq_io_context *cic)
+{
+	int enable_idle = cfq_cfqq_idle_window(cfqq);
+
+	if (!cic->ioc->task || !cfqd->cfq_slice_idle)
+		enable_idle = 0;
+	else if (sample_valid(cic->ttime_samples)) {
+		if (cic->ttime_mean > cfqd->cfq_slice_idle)
+			enable_idle = 0;
+		else
+			enable_idle = 1;
+	}
+
+	if (enable_idle)
+		cfq_mark_cfqq_idle_window(cfqq);
+	else
+		cfq_clear_cfqq_idle_window(cfqq);
+}
+
+
+/*
+ * Check if new_cfqq should preempt the currently active queue. Return 0 for
+ * no or if we aren't sure, a 1 will cause a preempt.
+ */
+static int
+cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq,
+		   struct cfq_rq *crq)
+{
+	struct cfq_queue *cfqq = cfqd->active_queue;
+
+	if (cfq_class_idle(new_cfqq))
+		return 0;
+
+	if (!cfqq)
+		return 1;
+
+	if (cfq_class_idle(cfqq))
+		return 1;
+	if (!cfq_cfqq_wait_request(new_cfqq))
+		return 0;
+	/*
+	 * if it doesn't have slice left, forget it
+	 */
+	if (new_cfqq->slice_left < cfqd->cfq_slice_idle)
+		return 0;
+	if (cfq_crq_is_sync(crq) && !cfq_cfqq_sync(cfqq))
+		return 1;
+
+	return 0;
+}
+
+/*
+ * cfqq preempts the active queue. if we allowed preempt with no slice left,
+ * let it have half of its nominal slice.
+ */
+static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq)
+{
+	struct cfq_queue *__cfqq, *next;
+
+	list_for_each_entry_safe(__cfqq, next, &cfqd->cur_rr, cfq_list)
+		cfq_resort_rr_list(__cfqq, 1);
+
+	if (!cfqq->slice_left)
+		cfqq->slice_left = cfq_prio_to_slice(cfqd, cfqq) / 2;
+
+	cfqq->slice_end = cfqq->slice_left + jiffies;
+	__cfq_slice_expired(cfqd, cfqq, 1);
+	__cfq_set_active_queue(cfqd, cfqq);
+}
+
+/*
+ * should really be a ll_rw_blk.c helper
+ */
+static void cfq_start_queueing(struct cfq_data *cfqd, struct cfq_queue *cfqq)
+{
+	request_queue_t *q = cfqd->queue;
+
+	if (!blk_queue_plugged(q))
+		q->request_fn(q);
+	else
+		__generic_unplug_device(q);
+}
+
+/*
+ * Called when a new fs request (crq) is added (to cfqq). Check if there's
+ * something we should do about it
+ */
+static void
+cfq_crq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
+		 struct cfq_rq *crq)
+{
+	const int sync = cfq_crq_is_sync(crq);
+
+	cfqq->next_crq = cfq_choose_req(cfqd, cfqq->next_crq, crq);
+
+	if (sync) {
+		struct cfq_io_context *cic = crq->io_context;
+
+		cfq_update_io_thinktime(cfqd, cic);
+		cfq_update_idle_window(cfqd, cfqq, cic);
+
+		cic->last_queue = jiffies;
+	}
+
+	if (cfqq == cfqd->active_queue) {
+		/*
+		 * if we are waiting for a request for this queue, let it rip
+		 * immediately and flag that we must not expire this queue
+		 * just now
+		 */
+		if (cfq_cfqq_wait_request(cfqq)) {
+			cfq_mark_cfqq_must_dispatch(cfqq);
+			del_timer(&cfqd->idle_slice_timer);
+			cfq_start_queueing(cfqd, cfqq);
+		}
+	} else if (cfq_should_preempt(cfqd, cfqq, crq)) {
+		/*
+		 * not the active queue - expire current slice if it is
+		 * idle and has expired it's mean thinktime or this new queue
+		 * has some old slice time left and is of higher priority
+		 */
+		cfq_preempt_queue(cfqd, cfqq);
+		cfq_mark_cfqq_must_dispatch(cfqq);
+		cfq_start_queueing(cfqd, cfqq);
+	}
+}
+
+static void cfq_enqueue(struct cfq_data *cfqd, struct request *rq)
+{
+	struct cfq_rq *crq = RQ_DATA(rq);
+	struct cfq_queue *cfqq = crq->cfq_queue;
+
+	cfq_init_prio_data(cfqq);
 
 	cfq_add_crq_rb(crq);
-	crq->queue_start = jiffies;
 
-	list_add_tail(&crq->request->queuelist, &crq->cfq_queue->fifo[crq->is_sync]);
+	list_add_tail(&rq->queuelist, &cfqq->fifo);
+
+	if (rq_mergeable(rq)) {
+		cfq_add_crq_hash(cfqd, crq);
+
+		if (!cfqd->queue->last_merge)
+			cfqd->queue->last_merge = rq;
+	}
+
+	cfq_crq_enqueued(cfqd, cfqq, crq);
 }
 
 static void
 cfq_insert_request(request_queue_t *q, struct request *rq, int where)
 {
 	struct cfq_data *cfqd = q->elevator->elevator_data;
-	struct cfq_rq *crq = RQ_DATA(rq);
 
 	switch (where) {
 		case ELEVATOR_INSERT_BACK:
-			while (cfq_dispatch_requests(q, cfqd->cfq_quantum))
+			while (cfq_dispatch_requests(q, INT_MAX, 1))
 				;
 			list_add_tail(&rq->queuelist, &q->queue_head);
+			/*
+			 * If we were idling with pending requests on
+			 * inactive cfqqs, force dispatching will
+			 * remove the idle timer and the queue won't
+			 * be kicked by __make_request() afterward.
+			 * Kick it here.
+			 */
+			cfq_schedule_dispatch(cfqd);
 			break;
 		case ELEVATOR_INSERT_FRONT:
 			list_add(&rq->queuelist, &q->queue_head);
 			break;
 		case ELEVATOR_INSERT_SORT:
 			BUG_ON(!blk_fs_request(rq));
-			cfq_enqueue(cfqd, crq);
+			cfq_enqueue(cfqd, rq);
 			break;
 		default:
 			printk("%s: bad insert point %d\n", __FUNCTION__,where);
 			return;
 	}
+}
 
-	if (rq_mergeable(rq)) {
-		cfq_add_crq_hash(cfqd, crq);
-
-		if (!q->last_merge)
-			q->last_merge = rq;
-	}
+static inline int cfq_pending_requests(struct cfq_data *cfqd)
+{
+	return !list_empty(&cfqd->queue->queue_head) || cfqd->busy_queues;
 }
 
 static int cfq_queue_empty(request_queue_t *q)
 {
 	struct cfq_data *cfqd = q->elevator->elevator_data;
 
-	return list_empty(&q->queue_head) && list_empty(&cfqd->rr_list);
+	return !cfq_pending_requests(cfqd);
 }
 
 static void cfq_completed_request(request_queue_t *q, struct request *rq)
@@ -1297,9 +1868,11 @@
 
 	cfqq = crq->cfq_queue;
 
-	if (crq->in_flight) {
-		WARN_ON(!cfqq->in_flight);
-		cfqq->in_flight--;
+	if (cfq_crq_in_flight(crq)) {
+		const int sync = cfq_crq_is_sync(crq);
+
+		WARN_ON(!cfqq->on_dispatch[sync]);
+		cfqq->on_dispatch[sync]--;
 	}
 
 	cfq_account_completion(cfqq, crq);
@@ -1329,51 +1902,136 @@
 	return NULL;
 }
 
-static int cfq_may_queue(request_queue_t *q, int rw)
+/*
+ * we temporarily boost lower priority queues if they are holding fs exclusive
+ * resources. they are boosted to normal prio (CLASS_BE/4)
+ */
+static void cfq_prio_boost(struct cfq_queue *cfqq)
 {
-	struct cfq_data *cfqd = q->elevator->elevator_data;
-	struct cfq_queue *cfqq;
-	int ret = ELV_MQUEUE_MAY;
+	const int ioprio_class = cfqq->ioprio_class;
+	const int ioprio = cfqq->ioprio;
 
-	if (current->flags & PF_MEMALLOC)
-		return ELV_MQUEUE_MAY;
-
-	cfqq = cfq_find_cfq_hash(cfqd, cfq_hash_key(cfqd, current));
-	if (cfqq) {
-		int limit = cfqd->max_queued;
-
-		if (cfqq->allocated[rw] < cfqd->cfq_queued)
-			return ELV_MQUEUE_MUST;
-
-		if (cfqd->busy_queues)
-			limit = q->nr_requests / cfqd->busy_queues;
-
-		if (limit < cfqd->cfq_queued)
-			limit = cfqd->cfq_queued;
-		else if (limit > cfqd->max_queued)
-			limit = cfqd->max_queued;
-
-		if (cfqq->allocated[rw] >= limit) {
-			if (limit > cfqq->alloc_limit[rw])
-				cfqq->alloc_limit[rw] = limit;
-
-			ret = ELV_MQUEUE_NO;
-		}
+	if (has_fs_excl()) {
+		/*
+		 * boost idle prio on transactions that would lock out other
+		 * users of the filesystem
+		 */
+		if (cfq_class_idle(cfqq))
+			cfqq->ioprio_class = IOPRIO_CLASS_BE;
+		if (cfqq->ioprio > IOPRIO_NORM)
+			cfqq->ioprio = IOPRIO_NORM;
+	} else {
+		/*
+		 * check if we need to unboost the queue
+		 */
+		if (cfqq->ioprio_class != cfqq->org_ioprio_class)
+			cfqq->ioprio_class = cfqq->org_ioprio_class;
+		if (cfqq->ioprio != cfqq->org_ioprio)
+			cfqq->ioprio = cfqq->org_ioprio;
 	}
 
-	return ret;
+	/*
+	 * refile between round-robin lists if we moved the priority class
+	 */
+	if ((ioprio_class != cfqq->ioprio_class || ioprio != cfqq->ioprio) &&
+	    cfq_cfqq_on_rr(cfqq))
+		cfq_resort_rr_list(cfqq, 0);
+}
+
+static inline pid_t cfq_queue_pid(struct task_struct *task, int rw)
+{
+	if (rw == READ || process_sync(task))
+		return task->pid;
+
+	return CFQ_KEY_ASYNC;
+}
+
+static inline int
+__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) {
+		cfq_mark_cfqq_must_alloc_slice(cfqq);
+		return ELV_MQUEUE_MUST;
+	}
+
+	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) {
+			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)
+{
+	struct cfq_data *cfqd = q->elevator->elevator_data;
+	struct task_struct *tsk = current;
+	struct cfq_queue *cfqq;
+
+	/*
+	 * don't force setup of a queue from here, as a call to may_queue
+	 * does not necessarily imply that a request actually will be queued.
+	 * so just lookup a possibly existing queue, or return 'may queue'
+	 * if that fails
+	 */
+	cfqq = cfq_find_cfq_hash(cfqd, cfq_queue_pid(tsk, rw), tsk->ioprio);
+	if (cfqq) {
+		cfq_init_prio_data(cfqq);
+		cfq_prio_boost(cfqq);
+
+		return __cfq_may_queue(cfqd, cfqq, tsk, rw);
+	}
+
+	return ELV_MQUEUE_MAY;
 }
 
 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;
-	const int write = waitqueue_active(&rl->wait[WRITE]);
-	const int read = waitqueue_active(&rl->wait[READ]);
 
-	if (read && cfqq->allocated[READ] < cfqq->alloc_limit[READ])
-		wake_up(&rl->wait[READ]);
-	if (write && cfqq->allocated[WRITE] < cfqq->alloc_limit[WRITE])
-		wake_up(&rl->wait[WRITE]);
+	if (cfqq->allocated[READ] <= cfqd->max_queued || cfqd->rq_starved) {
+		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]);
+	}
 }
 
 /*
@@ -1386,69 +2044,61 @@
 
 	if (crq) {
 		struct cfq_queue *cfqq = crq->cfq_queue;
+		const int rw = rq_data_dir(rq);
 
-		BUG_ON(q->last_merge == rq);
-		BUG_ON(!hlist_unhashed(&crq->hash));
+		BUG_ON(!cfqq->allocated[rw]);
+		cfqq->allocated[rw]--;
 
-		if (crq->io_context)
-			put_io_context(crq->io_context->ioc);
-
-		BUG_ON(!cfqq->allocated[crq->is_write]);
-		cfqq->allocated[crq->is_write]--;
+		put_io_context(crq->io_context->ioc);
 
 		mempool_free(crq, cfqd->crq_pool);
 		rq->elevator_private = NULL;
 
-		smp_mb();
 		cfq_check_waiters(q, cfqq);
 		cfq_put_queue(cfqq);
 	}
 }
 
 /*
- * Allocate cfq data structures associated with this request. A queue and
+ * Allocate cfq data structures associated with this request.
  */
-static int cfq_set_request(request_queue_t *q, struct request *rq, int gfp_mask)
+static int
+cfq_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
+		int gfp_mask)
 {
 	struct cfq_data *cfqd = q->elevator->elevator_data;
+	struct task_struct *tsk = current;
 	struct cfq_io_context *cic;
 	const int rw = rq_data_dir(rq);
-	struct cfq_queue *cfqq, *saved_cfqq;
+	pid_t key = cfq_queue_pid(tsk, rw);
+	struct cfq_queue *cfqq;
 	struct cfq_rq *crq;
 	unsigned long flags;
 
 	might_sleep_if(gfp_mask & __GFP_WAIT);
 
+	cic = cfq_get_io_context(cfqd, key, gfp_mask);
+
 	spin_lock_irqsave(q->queue_lock, flags);
 
-	cfqq = __cfq_get_queue(cfqd, cfq_hash_key(cfqd, current), gfp_mask);
-	if (!cfqq)
-		goto out_lock;
+	if (!cic)
+		goto queue_fail;
 
-repeat:
-	if (cfqq->allocated[rw] >= cfqd->max_queued)
-		goto out_lock;
+	if (!cic->cfqq) {
+		cfqq = cfq_get_queue(cfqd, key, tsk->ioprio, gfp_mask);
+		if (!cfqq)
+			goto queue_fail;
+
+		cic->cfqq = cfqq;
+	} else
+		cfqq = cic->cfqq;
 
 	cfqq->allocated[rw]++;
+	cfq_clear_cfqq_must_alloc(cfqq);
+	cfqd->rq_starved = 0;
+	atomic_inc(&cfqq->ref);
 	spin_unlock_irqrestore(q->queue_lock, flags);
 
-	/*
-	 * if hashing type has changed, the cfq_queue might change here.
-	 */
-	saved_cfqq = cfqq;
-	cic = cfq_get_io_context(&cfqq, gfp_mask);
-	if (!cic)
-		goto err;
-
-	/*
-	 * repeat allocation checks on queue change
-	 */
-	if (unlikely(saved_cfqq != cfqq)) {
-		spin_lock_irqsave(q->queue_lock, flags);
-		saved_cfqq->allocated[rw]--;
-		goto repeat;
-	}
-
 	crq = mempool_alloc(cfqd->crq_pool, gfp_mask);
 	if (crq) {
 		RB_CLEAR(&crq->rb_node);
@@ -1457,24 +2107,141 @@
 		INIT_HLIST_NODE(&crq->hash);
 		crq->cfq_queue = cfqq;
 		crq->io_context = cic;
-		crq->service_start = crq->queue_start = 0;
-		crq->in_flight = crq->accounted = crq->is_sync = 0;
-		crq->is_write = rw;
+		cfq_clear_crq_in_flight(crq);
+		cfq_clear_crq_in_driver(crq);
+		cfq_clear_crq_requeued(crq);
+
+		if (rw == READ || process_sync(tsk))
+			cfq_mark_crq_is_sync(crq);
+		else
+			cfq_clear_crq_is_sync(crq);
+
 		rq->elevator_private = crq;
-		cfqq->alloc_limit[rw] = 0;
 		return 0;
 	}
 
-	put_io_context(cic->ioc);
-err:
 	spin_lock_irqsave(q->queue_lock, flags);
 	cfqq->allocated[rw]--;
+	if (!(cfqq->allocated[0] + cfqq->allocated[1]))
+		cfq_mark_cfqq_must_alloc(cfqq);
 	cfq_put_queue(cfqq);
-out_lock:
+queue_fail:
+	if (cic)
+		put_io_context(cic->ioc);
+	/*
+	 * mark us rq allocation starved. we need to kickstart the process
+	 * ourselves if there are no pending requests that can do it for us.
+	 * that would be an extremely rare OOM situation
+	 */
+	cfqd->rq_starved = 1;
+	cfq_schedule_dispatch(cfqd);
 	spin_unlock_irqrestore(q->queue_lock, flags);
 	return 1;
 }
 
+static void cfq_kick_queue(void *data)
+{
+	request_queue_t *q = data;
+	struct cfq_data *cfqd = q->elevator->elevator_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(q->queue_lock, flags);
+
+	if (cfqd->rq_starved) {
+		struct request_list *rl = &q->rq;
+
+		/*
+		 * we aren't guaranteed to get a request after this, but we
+		 * have to be opportunistic
+		 */
+		smp_mb();
+		if (waitqueue_active(&rl->wait[READ]))
+			wake_up(&rl->wait[READ]);
+		if (waitqueue_active(&rl->wait[WRITE]))
+			wake_up(&rl->wait[WRITE]);
+	}
+
+	blk_remove_plug(q);
+	q->request_fn(q);
+	spin_unlock_irqrestore(q->queue_lock, flags);
+}
+
+/*
+ * Timer running if the active_queue is currently idling inside its time slice
+ */
+static void cfq_idle_slice_timer(unsigned long data)
+{
+	struct cfq_data *cfqd = (struct cfq_data *) data;
+	struct cfq_queue *cfqq;
+	unsigned long flags;
+
+	spin_lock_irqsave(cfqd->queue->queue_lock, flags);
+
+	if ((cfqq = cfqd->active_queue) != NULL) {
+		unsigned long now = jiffies;
+
+		/*
+		 * expired
+		 */
+		if (time_after(now, cfqq->slice_end))
+			goto expire;
+
+		/*
+		 * only expire and reinvoke request handler, if there are
+		 * other queues with pending requests
+		 */
+		if (!cfq_pending_requests(cfqd)) {
+			cfqd->idle_slice_timer.expires = min(now + cfqd->cfq_slice_idle, cfqq->slice_end);
+			add_timer(&cfqd->idle_slice_timer);
+			goto out_cont;
+		}
+
+		/*
+		 * not expired and it has a request pending, let it dispatch
+		 */
+		if (!RB_EMPTY(&cfqq->sort_list)) {
+			cfq_mark_cfqq_must_dispatch(cfqq);
+			goto out_kick;
+		}
+	}
+expire:
+	cfq_slice_expired(cfqd, 0);
+out_kick:
+	cfq_schedule_dispatch(cfqd);
+out_cont:
+	spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
+}
+
+/*
+ * Timer running if an idle class queue is waiting for service
+ */
+static void cfq_idle_class_timer(unsigned long data)
+{
+	struct cfq_data *cfqd = (struct cfq_data *) data;
+	unsigned long flags, end;
+
+	spin_lock_irqsave(cfqd->queue->queue_lock, flags);
+
+	/*
+	 * race with a non-idle queue, reset timer
+	 */
+	end = cfqd->last_end_request + CFQ_IDLE_GRACE;
+	if (!time_after_eq(jiffies, end)) {
+		cfqd->idle_class_timer.expires = end;
+		add_timer(&cfqd->idle_class_timer);
+	} else
+		cfq_schedule_dispatch(cfqd);
+
+	spin_unlock_irqrestore(cfqd->queue->queue_lock, flags);
+}
+
+static void cfq_shutdown_timer_wq(struct cfq_data *cfqd)
+{
+	del_timer_sync(&cfqd->idle_slice_timer);
+	del_timer_sync(&cfqd->idle_class_timer);
+	blk_sync_queue(cfqd->queue);
+}
+
 static void cfq_put_cfqd(struct cfq_data *cfqd)
 {
 	request_queue_t *q = cfqd->queue;
@@ -1484,6 +2251,9 @@
 
 	blk_put_queue(q);
 
+	cfq_shutdown_timer_wq(cfqd);
+	q->elevator->elevator_data = NULL;
+
 	mempool_destroy(cfqd->crq_pool);
 	kfree(cfqd->crq_hash);
 	kfree(cfqd->cfq_hash);
@@ -1492,7 +2262,10 @@
 
 static void cfq_exit_queue(elevator_t *e)
 {
-	cfq_put_cfqd(e->elevator_data);
+	struct cfq_data *cfqd = e->elevator_data;
+
+	cfq_shutdown_timer_wq(cfqd);
+	cfq_put_cfqd(cfqd);
 }
 
 static int cfq_init_queue(request_queue_t *q, elevator_t *e)
@@ -1505,7 +2278,13 @@
 		return -ENOMEM;
 
 	memset(cfqd, 0, sizeof(*cfqd));
-	INIT_LIST_HEAD(&cfqd->rr_list);
+
+	for (i = 0; i < CFQ_PRIO_LISTS; i++)
+		INIT_LIST_HEAD(&cfqd->rr_list[i]);
+
+	INIT_LIST_HEAD(&cfqd->busy_rr);
+	INIT_LIST_HEAD(&cfqd->cur_rr);
+	INIT_LIST_HEAD(&cfqd->idle_rr);
 	INIT_LIST_HEAD(&cfqd->empty_list);
 
 	cfqd->crq_hash = kmalloc(sizeof(struct hlist_head) * CFQ_MHASH_ENTRIES, GFP_KERNEL);
@@ -1530,24 +2309,32 @@
 	cfqd->queue = q;
 	atomic_inc(&q->refcnt);
 
-	/*
-	 * just set it to some high value, we want anyone to be able to queue
-	 * some requests. fairness is handled differently
-	 */
-	q->nr_requests = 1024;
-	cfqd->max_queued = q->nr_requests / 16;
+	cfqd->max_queued = q->nr_requests / 4;
 	q->nr_batching = cfq_queued;
-	cfqd->key_type = CFQ_KEY_TGID;
-	cfqd->find_best_crq = 1;
+
+	init_timer(&cfqd->idle_slice_timer);
+	cfqd->idle_slice_timer.function = cfq_idle_slice_timer;
+	cfqd->idle_slice_timer.data = (unsigned long) cfqd;
+
+	init_timer(&cfqd->idle_class_timer);
+	cfqd->idle_class_timer.function = cfq_idle_class_timer;
+	cfqd->idle_class_timer.data = (unsigned long) cfqd;
+
+	INIT_WORK(&cfqd->unplug_work, cfq_kick_queue, q);
+
 	atomic_set(&cfqd->ref, 1);
 
 	cfqd->cfq_queued = cfq_queued;
 	cfqd->cfq_quantum = cfq_quantum;
-	cfqd->cfq_fifo_expire_r = cfq_fifo_expire_r;
-	cfqd->cfq_fifo_expire_w = cfq_fifo_expire_w;
-	cfqd->cfq_fifo_batch_expire = cfq_fifo_rate;
+	cfqd->cfq_fifo_expire[0] = cfq_fifo_expire[0];
+	cfqd->cfq_fifo_expire[1] = cfq_fifo_expire[1];
 	cfqd->cfq_back_max = cfq_back_max;
 	cfqd->cfq_back_penalty = cfq_back_penalty;
+	cfqd->cfq_slice[0] = cfq_slice_async;
+	cfqd->cfq_slice[1] = cfq_slice_sync;
+	cfqd->cfq_slice_async_rq = cfq_slice_async_rq;
+	cfqd->cfq_slice_idle = cfq_slice_idle;
+	cfqd->cfq_max_depth = cfq_max_depth;
 
 	return 0;
 out_crqpool:
@@ -1592,7 +2379,6 @@
 	return -ENOMEM;
 }
 
-
 /*
  * sysfs parts below -->
  */
@@ -1617,45 +2403,6 @@
 	return count;
 }
 
-static ssize_t
-cfq_clear_elapsed(struct cfq_data *cfqd, const char *page, size_t count)
-{
-	max_elapsed_dispatch = max_elapsed_crq = 0;
-	return count;
-}
-
-static ssize_t
-cfq_set_key_type(struct cfq_data *cfqd, const char *page, size_t count)
-{
-	spin_lock_irq(cfqd->queue->queue_lock);
-	if (!strncmp(page, "pgid", 4))
-		cfqd->key_type = CFQ_KEY_PGID;
-	else if (!strncmp(page, "tgid", 4))
-		cfqd->key_type = CFQ_KEY_TGID;
-	else if (!strncmp(page, "uid", 3))
-		cfqd->key_type = CFQ_KEY_UID;
-	else if (!strncmp(page, "gid", 3))
-		cfqd->key_type = CFQ_KEY_GID;
-	spin_unlock_irq(cfqd->queue->queue_lock);
-	return count;
-}
-
-static ssize_t
-cfq_read_key_type(struct cfq_data *cfqd, char *page)
-{
-	ssize_t len = 0;
-	int i;
-
-	for (i = CFQ_KEY_PGID; i < CFQ_KEY_LAST; i++) {
-		if (cfqd->key_type == i)
-			len += sprintf(page+len, "[%s] ", cfq_key_types[i]);
-		else
-			len += sprintf(page+len, "%s ", cfq_key_types[i]);
-	}
-	len += sprintf(page+len, "\n");
-	return len;
-}
-
 #define SHOW_FUNCTION(__FUNC, __VAR, __CONV)				\
 static ssize_t __FUNC(struct cfq_data *cfqd, char *page)		\
 {									\
@@ -1666,12 +2413,15 @@
 }
 SHOW_FUNCTION(cfq_quantum_show, cfqd->cfq_quantum, 0);
 SHOW_FUNCTION(cfq_queued_show, cfqd->cfq_queued, 0);
-SHOW_FUNCTION(cfq_fifo_expire_r_show, cfqd->cfq_fifo_expire_r, 1);
-SHOW_FUNCTION(cfq_fifo_expire_w_show, cfqd->cfq_fifo_expire_w, 1);
-SHOW_FUNCTION(cfq_fifo_batch_expire_show, cfqd->cfq_fifo_batch_expire, 1);
-SHOW_FUNCTION(cfq_find_best_show, cfqd->find_best_crq, 0);
+SHOW_FUNCTION(cfq_fifo_expire_sync_show, cfqd->cfq_fifo_expire[1], 1);
+SHOW_FUNCTION(cfq_fifo_expire_async_show, cfqd->cfq_fifo_expire[0], 1);
 SHOW_FUNCTION(cfq_back_max_show, cfqd->cfq_back_max, 0);
 SHOW_FUNCTION(cfq_back_penalty_show, cfqd->cfq_back_penalty, 0);
+SHOW_FUNCTION(cfq_slice_idle_show, cfqd->cfq_slice_idle, 1);
+SHOW_FUNCTION(cfq_slice_sync_show, cfqd->cfq_slice[1], 1);
+SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1);
+SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0);
+SHOW_FUNCTION(cfq_max_depth_show, cfqd->cfq_max_depth, 0);
 #undef SHOW_FUNCTION
 
 #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV)			\
@@ -1691,12 +2441,15 @@
 }
 STORE_FUNCTION(cfq_quantum_store, &cfqd->cfq_quantum, 1, UINT_MAX, 0);
 STORE_FUNCTION(cfq_queued_store, &cfqd->cfq_queued, 1, UINT_MAX, 0);
-STORE_FUNCTION(cfq_fifo_expire_r_store, &cfqd->cfq_fifo_expire_r, 1, UINT_MAX, 1);
-STORE_FUNCTION(cfq_fifo_expire_w_store, &cfqd->cfq_fifo_expire_w, 1, UINT_MAX, 1);
-STORE_FUNCTION(cfq_fifo_batch_expire_store, &cfqd->cfq_fifo_batch_expire, 0, UINT_MAX, 1);
-STORE_FUNCTION(cfq_find_best_store, &cfqd->find_best_crq, 0, 1, 0);
+STORE_FUNCTION(cfq_fifo_expire_sync_store, &cfqd->cfq_fifo_expire[1], 1, UINT_MAX, 1);
+STORE_FUNCTION(cfq_fifo_expire_async_store, &cfqd->cfq_fifo_expire[0], 1, UINT_MAX, 1);
 STORE_FUNCTION(cfq_back_max_store, &cfqd->cfq_back_max, 0, UINT_MAX, 0);
 STORE_FUNCTION(cfq_back_penalty_store, &cfqd->cfq_back_penalty, 1, UINT_MAX, 0);
+STORE_FUNCTION(cfq_slice_idle_store, &cfqd->cfq_slice_idle, 0, UINT_MAX, 1);
+STORE_FUNCTION(cfq_slice_sync_store, &cfqd->cfq_slice[1], 1, UINT_MAX, 1);
+STORE_FUNCTION(cfq_slice_async_store, &cfqd->cfq_slice[0], 1, UINT_MAX, 1);
+STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1, UINT_MAX, 0);
+STORE_FUNCTION(cfq_max_depth_store, &cfqd->cfq_max_depth, 1, UINT_MAX, 0);
 #undef STORE_FUNCTION
 
 static struct cfq_fs_entry cfq_quantum_entry = {
@@ -1709,25 +2462,15 @@
 	.show = cfq_queued_show,
 	.store = cfq_queued_store,
 };
-static struct cfq_fs_entry cfq_fifo_expire_r_entry = {
+static struct cfq_fs_entry cfq_fifo_expire_sync_entry = {
 	.attr = {.name = "fifo_expire_sync", .mode = S_IRUGO | S_IWUSR },
-	.show = cfq_fifo_expire_r_show,
-	.store = cfq_fifo_expire_r_store,
+	.show = cfq_fifo_expire_sync_show,
+	.store = cfq_fifo_expire_sync_store,
 };
-static struct cfq_fs_entry cfq_fifo_expire_w_entry = {
+static struct cfq_fs_entry cfq_fifo_expire_async_entry = {
 	.attr = {.name = "fifo_expire_async", .mode = S_IRUGO | S_IWUSR },
-	.show = cfq_fifo_expire_w_show,
-	.store = cfq_fifo_expire_w_store,
-};
-static struct cfq_fs_entry cfq_fifo_batch_expire_entry = {
-	.attr = {.name = "fifo_batch_expire", .mode = S_IRUGO | S_IWUSR },
-	.show = cfq_fifo_batch_expire_show,
-	.store = cfq_fifo_batch_expire_store,
-};
-static struct cfq_fs_entry cfq_find_best_entry = {
-	.attr = {.name = "find_best_crq", .mode = S_IRUGO | S_IWUSR },
-	.show = cfq_find_best_show,
-	.store = cfq_find_best_store,
+	.show = cfq_fifo_expire_async_show,
+	.store = cfq_fifo_expire_async_store,
 };
 static struct cfq_fs_entry cfq_back_max_entry = {
 	.attr = {.name = "back_seek_max", .mode = S_IRUGO | S_IWUSR },
@@ -1739,27 +2482,44 @@
 	.show = cfq_back_penalty_show,
 	.store = cfq_back_penalty_store,
 };
-static struct cfq_fs_entry cfq_clear_elapsed_entry = {
-	.attr = {.name = "clear_elapsed", .mode = S_IWUSR },
-	.store = cfq_clear_elapsed,
+static struct cfq_fs_entry cfq_slice_sync_entry = {
+	.attr = {.name = "slice_sync", .mode = S_IRUGO | S_IWUSR },
+	.show = cfq_slice_sync_show,
+	.store = cfq_slice_sync_store,
 };
-static struct cfq_fs_entry cfq_key_type_entry = {
-	.attr = {.name = "key_type", .mode = S_IRUGO | S_IWUSR },
-	.show = cfq_read_key_type,
-	.store = cfq_set_key_type,
+static struct cfq_fs_entry cfq_slice_async_entry = {
+	.attr = {.name = "slice_async", .mode = S_IRUGO | S_IWUSR },
+	.show = cfq_slice_async_show,
+	.store = cfq_slice_async_store,
+};
+static struct cfq_fs_entry cfq_slice_async_rq_entry = {
+	.attr = {.name = "slice_async_rq", .mode = S_IRUGO | S_IWUSR },
+	.show = cfq_slice_async_rq_show,
+	.store = cfq_slice_async_rq_store,
+};
+static struct cfq_fs_entry cfq_slice_idle_entry = {
+	.attr = {.name = "slice_idle", .mode = S_IRUGO | S_IWUSR },
+	.show = cfq_slice_idle_show,
+	.store = cfq_slice_idle_store,
+};
+static struct cfq_fs_entry cfq_max_depth_entry = {
+	.attr = {.name = "max_depth", .mode = S_IRUGO | S_IWUSR },
+	.show = cfq_max_depth_show,
+	.store = cfq_max_depth_store,
 };
 
 static struct attribute *default_attrs[] = {
 	&cfq_quantum_entry.attr,
 	&cfq_queued_entry.attr,
-	&cfq_fifo_expire_r_entry.attr,
-	&cfq_fifo_expire_w_entry.attr,
-	&cfq_fifo_batch_expire_entry.attr,
-	&cfq_key_type_entry.attr,
-	&cfq_find_best_entry.attr,
+	&cfq_fifo_expire_sync_entry.attr,
+	&cfq_fifo_expire_async_entry.attr,
 	&cfq_back_max_entry.attr,
 	&cfq_back_penalty_entry.attr,
-	&cfq_clear_elapsed_entry.attr,
+	&cfq_slice_sync_entry.attr,
+	&cfq_slice_async_entry.attr,
+	&cfq_slice_async_rq_entry.attr,
+	&cfq_slice_idle_entry.attr,
+	&cfq_max_depth_entry.attr,
 	NULL,
 };
 
@@ -1772,7 +2532,7 @@
 	struct cfq_fs_entry *entry = to_cfq(attr);
 
 	if (!entry->show)
-		return 0;
+		return -EIO;
 
 	return entry->show(e->elevator_data, page);
 }
@@ -1785,7 +2545,7 @@
 	struct cfq_fs_entry *entry = to_cfq(attr);
 
 	if (!entry->store)
-		return -EINVAL;
+		return -EIO;
 
 	return entry->store(e->elevator_data, page, length);
 }
@@ -1829,21 +2589,46 @@
 {
 	int ret;
 
+	/*
+	 * could be 0 on HZ < 1000 setups
+	 */
+	if (!cfq_slice_async)
+		cfq_slice_async = 1;
+	if (!cfq_slice_idle)
+		cfq_slice_idle = 1;
+
 	if (cfq_slab_setup())
 		return -ENOMEM;
 
 	ret = elv_register(&iosched_cfq);
-	if (!ret) {
-		__module_get(THIS_MODULE);
-		return 0;
-	}
+	if (ret)
+		cfq_slab_kill();
 
-	cfq_slab_kill();
 	return ret;
 }
 
 static void __exit cfq_exit(void)
 {
+	struct task_struct *g, *p;
+	unsigned long flags;
+
+	read_lock_irqsave(&tasklist_lock, flags);
+
+	/*
+	 * iterate each process in the system, removing our io_context
+	 */
+	do_each_thread(g, p) {
+		struct io_context *ioc = p->io_context;
+
+		if (ioc && ioc->cic) {
+			ioc->cic->exit(ioc->cic);
+			cfq_free_io_context(ioc->cic);
+			ioc->cic = NULL;
+		}
+	} while_each_thread(g, p);
+
+	read_unlock_irqrestore(&tasklist_lock, flags);
+
 	cfq_slab_kill();
 	elv_unregister(&iosched_cfq);
 }
diff --git a/drivers/block/deadline-iosched.c b/drivers/block/deadline-iosched.c
index d63d34c..ff5201e 100644
--- a/drivers/block/deadline-iosched.c
+++ b/drivers/block/deadline-iosched.c
@@ -711,18 +711,20 @@
 	if (!drq_pool)
 		return -ENOMEM;
 
-	dd = kmalloc(sizeof(*dd), GFP_KERNEL);
+	dd = kmalloc_node(sizeof(*dd), GFP_KERNEL, q->node);
 	if (!dd)
 		return -ENOMEM;
 	memset(dd, 0, sizeof(*dd));
 
-	dd->hash = kmalloc(sizeof(struct list_head)*DL_HASH_ENTRIES,GFP_KERNEL);
+	dd->hash = kmalloc_node(sizeof(struct list_head)*DL_HASH_ENTRIES,
+				GFP_KERNEL, q->node);
 	if (!dd->hash) {
 		kfree(dd);
 		return -ENOMEM;
 	}
 
-	dd->drq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, drq_pool);
+	dd->drq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
+					mempool_free_slab, drq_pool, q->node);
 	if (!dd->drq_pool) {
 		kfree(dd->hash);
 		kfree(dd);
@@ -758,7 +760,8 @@
 }
 
 static int
-deadline_set_request(request_queue_t *q, struct request *rq, int gfp_mask)
+deadline_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
+		     int gfp_mask)
 {
 	struct deadline_data *dd = q->elevator->elevator_data;
 	struct deadline_rq *drq;
@@ -886,7 +889,7 @@
 	struct deadline_fs_entry *entry = to_deadline(attr);
 
 	if (!entry->show)
-		return 0;
+		return -EIO;
 
 	return entry->show(e->elevator_data, page);
 }
@@ -899,7 +902,7 @@
 	struct deadline_fs_entry *entry = to_deadline(attr);
 
 	if (!entry->store)
-		return -EINVAL;
+		return -EIO;
 
 	return entry->store(e->elevator_data, page, length);
 }
diff --git a/drivers/block/elevator.c b/drivers/block/elevator.c
index 6b79b43..98f0126 100644
--- a/drivers/block/elevator.c
+++ b/drivers/block/elevator.c
@@ -220,11 +220,6 @@
 	kfree(e);
 }
 
-static int elevator_global_init(void)
-{
-	return 0;
-}
-
 int elv_merge(request_queue_t *q, struct request **req, struct bio *bio)
 {
 	elevator_t *e = q->elevator;
@@ -291,6 +286,13 @@
 	}
 
 	/*
+	 * the request is prepped and may have some resources allocated.
+	 * allowing unprepped requests to pass this one may cause resource
+	 * deadlock.  turn on softbarrier.
+	 */
+	rq->flags |= REQ_SOFTBARRIER;
+
+	/*
 	 * if iosched has an explicit requeue hook, then use that. otherwise
 	 * just put the request at the front of the queue
 	 */
@@ -322,7 +324,7 @@
 			int nrq = q->rq.count[READ] + q->rq.count[WRITE]
 				  - q->in_flight;
 
-			if (nrq == q->unplug_thresh)
+			if (nrq >= q->unplug_thresh)
 				__generic_unplug_device(q);
 		}
 	} else
@@ -386,6 +388,12 @@
 		if (ret == BLKPREP_OK) {
 			break;
 		} else if (ret == BLKPREP_DEFER) {
+			/*
+			 * the request may have been (partially) prepped.
+			 * we need to keep this request in the front to
+			 * avoid resource deadlock.  turn on softbarrier.
+			 */
+			rq->flags |= REQ_SOFTBARRIER;
 			rq = NULL;
 			break;
 		} else if (ret == BLKPREP_KILL) {
@@ -478,12 +486,13 @@
 	return NULL;
 }
 
-int elv_set_request(request_queue_t *q, struct request *rq, int gfp_mask)
+int elv_set_request(request_queue_t *q, struct request *rq, struct bio *bio,
+		    int gfp_mask)
 {
 	elevator_t *e = q->elevator;
 
 	if (e->ops->elevator_set_req_fn)
-		return e->ops->elevator_set_req_fn(q, rq, gfp_mask);
+		return e->ops->elevator_set_req_fn(q, rq, bio, gfp_mask);
 
 	rq->elevator_private = NULL;
 	return 0;
@@ -497,12 +506,12 @@
 		e->ops->elevator_put_req_fn(q, rq);
 }
 
-int elv_may_queue(request_queue_t *q, int rw)
+int elv_may_queue(request_queue_t *q, int rw, struct bio *bio)
 {
 	elevator_t *e = q->elevator;
 
 	if (e->ops->elevator_may_queue_fn)
-		return e->ops->elevator_may_queue_fn(q, rw);
+		return e->ops->elevator_may_queue_fn(q, rw, bio);
 
 	return ELV_MQUEUE_MAY;
 }
@@ -692,8 +701,6 @@
 	return len;
 }
 
-module_init(elevator_global_init);
-
 EXPORT_SYMBOL(elv_add_request);
 EXPORT_SYMBOL(__elv_add_request);
 EXPORT_SYMBOL(elv_requeue_request);
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index 8bbe01d..47fd365 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -40,7 +40,7 @@
 
 #ifdef CONFIG_PROC_FS
 /* get block device names in somewhat random order */
-int get_blkdev_list(char *p)
+int get_blkdev_list(char *p, int used)
 {
 	struct blk_major_name *n;
 	int i, len;
@@ -49,10 +49,18 @@
 
 	down(&block_subsys_sem);
 	for (i = 0; i < ARRAY_SIZE(major_names); i++) {
-		for (n = major_names[i]; n; n = n->next)
+		for (n = major_names[i]; n; n = n->next) {
+			/*
+			 * If the curent string plus the 5 extra characters
+			 * in the line would run us off the page, then we're done
+			 */
+			if ((len + used + strlen(n->name) + 5) >= PAGE_SIZE)
+				goto page_full;
 			len += sprintf(p+len, "%3d %s\n",
 				       n->major, n->name);
+		}
 	}
+page_full:
 	up(&block_subsys_sem);
 
 	return len;
@@ -322,7 +330,7 @@
 	struct gendisk *disk = to_disk(kobj);
 	struct disk_attribute *disk_attr =
 		container_of(attr,struct disk_attribute,attr);
-	ssize_t ret = 0;
+	ssize_t ret = -EIO;
 
 	if (disk_attr->show)
 		ret = disk_attr->show(disk,page);
@@ -582,10 +590,16 @@
 	.show	= diskstats_show
 };
 
-
 struct gendisk *alloc_disk(int minors)
 {
-	struct gendisk *disk = kmalloc(sizeof(struct gendisk), GFP_KERNEL);
+	return alloc_disk_node(minors, -1);
+}
+
+struct gendisk *alloc_disk_node(int minors, int node_id)
+{
+	struct gendisk *disk;
+
+	disk = kmalloc_node(sizeof(struct gendisk), GFP_KERNEL, node_id);
 	if (disk) {
 		memset(disk, 0, sizeof(struct gendisk));
 		if (!init_disk_stats(disk)) {
@@ -594,7 +608,7 @@
 		}
 		if (minors > 1) {
 			int size = (minors - 1) * sizeof(struct hd_struct *);
-			disk->part = kmalloc(size, GFP_KERNEL);
+			disk->part = kmalloc_node(size, GFP_KERNEL, node_id);
 			if (!disk->part) {
 				kfree(disk);
 				return NULL;
@@ -610,6 +624,7 @@
 }
 
 EXPORT_SYMBOL(alloc_disk);
+EXPORT_SYMBOL(alloc_disk_node);
 
 struct kobject *get_disk(struct gendisk *disk)
 {
diff --git a/drivers/block/ioctl.c b/drivers/block/ioctl.c
index 6d7bcc9..6e27847 100644
--- a/drivers/block/ioctl.c
+++ b/drivers/block/ioctl.c
@@ -133,11 +133,9 @@
 	return put_user(val, (u64 __user *)arg);
 }
 
-int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
-			unsigned long arg)
+static int blkdev_locked_ioctl(struct file *file, struct block_device *bdev,
+				unsigned cmd, unsigned long arg)
 {
-	struct block_device *bdev = inode->i_bdev;
-	struct gendisk *disk = bdev->bd_disk;
 	struct backing_dev_info *bdi;
 	int ret, n;
 
@@ -190,36 +188,72 @@
 		return put_ulong(arg, bdev->bd_inode->i_size >> 9);
 	case BLKGETSIZE64:
 		return put_u64(arg, bdev->bd_inode->i_size);
+	}
+	return -ENOIOCTLCMD;
+}
+
+static int blkdev_driver_ioctl(struct inode *inode, struct file *file,
+		struct gendisk *disk, unsigned cmd, unsigned long arg)
+{
+	int ret;
+	if (disk->fops->unlocked_ioctl)
+		return disk->fops->unlocked_ioctl(file, cmd, arg);
+
+	if (disk->fops->ioctl) {
+		lock_kernel();
+		ret = disk->fops->ioctl(inode, file, cmd, arg);
+		unlock_kernel();
+		return ret;
+	}
+
+	return -ENOTTY;
+}
+
+int blkdev_ioctl(struct inode *inode, struct file *file, unsigned cmd,
+			unsigned long arg)
+{
+	struct block_device *bdev = inode->i_bdev;
+	struct gendisk *disk = bdev->bd_disk;
+	int ret, n;
+
+	switch(cmd) {
 	case BLKFLSBUF:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EACCES;
-		if (disk->fops->ioctl) {
-			ret = disk->fops->ioctl(inode, file, cmd, arg);
-			/* -EINVAL to handle old uncorrected drivers */
-			if (ret != -EINVAL && ret != -ENOTTY)
-				return ret;
-		}
+
+		ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg);
+		/* -EINVAL to handle old uncorrected drivers */
+		if (ret != -EINVAL && ret != -ENOTTY)
+			return ret;
+
+		lock_kernel();
 		fsync_bdev(bdev);
 		invalidate_bdev(bdev, 0);
+		unlock_kernel();
 		return 0;
+
 	case BLKROSET:
-		if (disk->fops->ioctl) {
-			ret = disk->fops->ioctl(inode, file, cmd, arg);
-			/* -EINVAL to handle old uncorrected drivers */
-			if (ret != -EINVAL && ret != -ENOTTY)
-				return ret;
-		}
+		ret = blkdev_driver_ioctl(inode, file, disk, cmd, arg);
+		/* -EINVAL to handle old uncorrected drivers */
+		if (ret != -EINVAL && ret != -ENOTTY)
+			return ret;
 		if (!capable(CAP_SYS_ADMIN))
 			return -EACCES;
 		if (get_user(n, (int __user *)(arg)))
 			return -EFAULT;
+		lock_kernel();
 		set_device_ro(bdev, n);
+		unlock_kernel();
 		return 0;
-	default:
-		if (disk->fops->ioctl)
-			return disk->fops->ioctl(inode, file, cmd, arg);
 	}
-	return -ENOTTY;
+
+	lock_kernel();
+	ret = blkdev_locked_ioctl(file, bdev, cmd, arg);
+	unlock_kernel();
+	if (ret != -ENOIOCTLCMD)
+		return ret;
+
+	return blkdev_driver_ioctl(inode, file, disk, cmd, arg);
 }
 
 /* Most of the generic ioctls are handled in the normal fallback path.
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 11ef9d9..234fdcf 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/writeback.h>
+#include <linux/blkdev.h>
 
 /*
  * for max sense size
@@ -36,6 +37,7 @@
 
 static void blk_unplug_work(void *data);
 static void blk_unplug_timeout(unsigned long data);
+static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io);
 
 /*
  * For the allocated request tables
@@ -274,6 +276,7 @@
 	rq->errors = 0;
 	rq->rq_status = RQ_ACTIVE;
 	rq->bio = rq->biotail = NULL;
+	rq->ioprio = 0;
 	rq->buffer = NULL;
 	rq->ref_count = 1;
 	rq->q = q;
@@ -716,7 +719,7 @@
 {
 	struct blk_queue_tag *bqt = q->queue_tags;
 
-	if (unlikely(bqt == NULL || tag >= bqt->real_max_depth))
+	if (unlikely(bqt == NULL || tag >= bqt->max_depth))
 		return NULL;
 
 	return bqt->tag_index[tag];
@@ -774,9 +777,9 @@
 static int
 init_tag_map(request_queue_t *q, struct blk_queue_tag *tags, int depth)
 {
-	int bits, i;
 	struct request **tag_index;
 	unsigned long *tag_map;
+	int nr_ulongs;
 
 	if (depth > q->nr_requests * 2) {
 		depth = q->nr_requests * 2;
@@ -788,24 +791,17 @@
 	if (!tag_index)
 		goto fail;
 
-	bits = (depth / BLK_TAGS_PER_LONG) + 1;
-	tag_map = kmalloc(bits * sizeof(unsigned long), GFP_ATOMIC);
+	nr_ulongs = ALIGN(depth, BITS_PER_LONG) / BITS_PER_LONG;
+	tag_map = kmalloc(nr_ulongs * sizeof(unsigned long), GFP_ATOMIC);
 	if (!tag_map)
 		goto fail;
 
 	memset(tag_index, 0, depth * sizeof(struct request *));
-	memset(tag_map, 0, bits * sizeof(unsigned long));
+	memset(tag_map, 0, nr_ulongs * sizeof(unsigned long));
 	tags->max_depth = depth;
-	tags->real_max_depth = bits * BITS_PER_LONG;
 	tags->tag_index = tag_index;
 	tags->tag_map = tag_map;
 
-	/*
-	 * set the upper bits if the depth isn't a multiple of the word size
-	 */
-	for (i = depth; i < bits * BLK_TAGS_PER_LONG; i++)
-		__set_bit(i, tag_map);
-
 	return 0;
 fail:
 	kfree(tag_index);
@@ -870,32 +866,24 @@
 	struct blk_queue_tag *bqt = q->queue_tags;
 	struct request **tag_index;
 	unsigned long *tag_map;
-	int bits, max_depth;
+	int max_depth, nr_ulongs;
 
 	if (!bqt)
 		return -ENXIO;
 
 	/*
-	 * don't bother sizing down
-	 */
-	if (new_depth <= bqt->real_max_depth) {
-		bqt->max_depth = new_depth;
-		return 0;
-	}
-
-	/*
 	 * save the old state info, so we can copy it back
 	 */
 	tag_index = bqt->tag_index;
 	tag_map = bqt->tag_map;
-	max_depth = bqt->real_max_depth;
+	max_depth = bqt->max_depth;
 
 	if (init_tag_map(q, bqt, new_depth))
 		return -ENOMEM;
 
 	memcpy(bqt->tag_index, tag_index, max_depth * sizeof(struct request *));
-	bits = max_depth / BLK_TAGS_PER_LONG;
-	memcpy(bqt->tag_map, tag_map, bits * sizeof(unsigned long));
+	nr_ulongs = ALIGN(max_depth, BITS_PER_LONG) / BITS_PER_LONG;
+	memcpy(bqt->tag_map, tag_map, nr_ulongs * sizeof(unsigned long));
 
 	kfree(tag_index);
 	kfree(tag_map);
@@ -925,11 +913,16 @@
 
 	BUG_ON(tag == -1);
 
-	if (unlikely(tag >= bqt->real_max_depth))
+	if (unlikely(tag >= bqt->max_depth))
+		/*
+		 * This can happen after tag depth has been reduced.
+		 * FIXME: how about a warning or info message here?
+		 */
 		return;
 
 	if (unlikely(!__test_and_clear_bit(tag, bqt->tag_map))) {
-		printk("attempt to clear non-busy tag (%d)\n", tag);
+		printk(KERN_ERR "%s: attempt to clear non-busy tag (%d)\n",
+		       __FUNCTION__, tag);
 		return;
 	}
 
@@ -938,7 +931,8 @@
 	rq->tag = -1;
 
 	if (unlikely(bqt->tag_index[tag] == NULL))
-		printk("tag %d is missing\n", tag);
+		printk(KERN_ERR "%s: tag %d is missing\n",
+		       __FUNCTION__, tag);
 
 	bqt->tag_index[tag] = NULL;
 	bqt->busy--;
@@ -967,24 +961,20 @@
 int blk_queue_start_tag(request_queue_t *q, struct request *rq)
 {
 	struct blk_queue_tag *bqt = q->queue_tags;
-	unsigned long *map = bqt->tag_map;
-	int tag = 0;
+	int tag;
 
 	if (unlikely((rq->flags & REQ_QUEUED))) {
 		printk(KERN_ERR 
-		       "request %p for device [%s] already tagged %d",
-		       rq, rq->rq_disk ? rq->rq_disk->disk_name : "?", rq->tag);
+		       "%s: request %p for device [%s] already tagged %d",
+		       __FUNCTION__, rq,
+		       rq->rq_disk ? rq->rq_disk->disk_name : "?", rq->tag);
 		BUG();
 	}
 
-	for (map = bqt->tag_map; *map == -1UL; map++) {
-		tag += BLK_TAGS_PER_LONG;
+	tag = find_first_zero_bit(bqt->tag_map, bqt->max_depth);
+	if (tag >= bqt->max_depth)
+		return 1;
 
-		if (tag >= bqt->max_depth)
-			return 1;
-	}
-
-	tag += ffz(*map);
 	__set_bit(tag, bqt->tag_map);
 
 	rq->flags |= REQ_QUEUED;
@@ -1020,7 +1010,8 @@
 		rq = list_entry_rq(tmp);
 
 		if (rq->tag == -1) {
-			printk("bad tag found on list\n");
+			printk(KERN_ERR
+			       "%s: bad tag found on list\n", __FUNCTION__);
 			list_del_init(&rq->queuelist);
 			rq->flags &= ~REQ_QUEUED;
 		} else
@@ -1148,7 +1139,7 @@
 }
 
 
-int blk_phys_contig_segment(request_queue_t *q, struct bio *bio,
+static int blk_phys_contig_segment(request_queue_t *q, struct bio *bio,
 				   struct bio *nxt)
 {
 	if (!(q->queue_flags & (1 << QUEUE_FLAG_CLUSTER)))
@@ -1169,9 +1160,7 @@
 	return 0;
 }
 
-EXPORT_SYMBOL(blk_phys_contig_segment);
-
-int blk_hw_contig_segment(request_queue_t *q, struct bio *bio,
+static int blk_hw_contig_segment(request_queue_t *q, struct bio *bio,
 				 struct bio *nxt)
 {
 	if (unlikely(!bio_flagged(bio, BIO_SEG_VALID)))
@@ -1187,8 +1176,6 @@
 	return 1;
 }
 
-EXPORT_SYMBOL(blk_hw_contig_segment);
-
 /*
  * map a request to scatterlist, return number of sg entries setup. Caller
  * must make sure sg can hold rq->nr_phys_segments entries
@@ -1358,8 +1345,8 @@
 static int ll_merge_requests_fn(request_queue_t *q, struct request *req,
 				struct request *next)
 {
-	int total_phys_segments = req->nr_phys_segments +next->nr_phys_segments;
-	int total_hw_segments = req->nr_hw_segments + next->nr_hw_segments;
+	int total_phys_segments;
+	int total_hw_segments;
 
 	/*
 	 * First check if the either of the requests are re-queued
@@ -1369,7 +1356,7 @@
 		return 0;
 
 	/*
-	 * Will it become to large?
+	 * Will it become too large?
 	 */
 	if ((req->nr_sectors + next->nr_sectors) > q->max_sectors)
 		return 0;
@@ -1450,17 +1437,13 @@
  */
 void __generic_unplug_device(request_queue_t *q)
 {
-	if (test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags))
+	if (unlikely(test_bit(QUEUE_FLAG_STOPPED, &q->queue_flags)))
 		return;
 
 	if (!blk_remove_plug(q))
 		return;
 
-	/*
-	 * was plugged, fire request_fn if queue has stuff to do
-	 */
-	if (elv_next_request(q))
-		q->request_fn(q);
+	q->request_fn(q);
 }
 EXPORT_SYMBOL(__generic_unplug_device);
 
@@ -1645,7 +1628,8 @@
 	init_waitqueue_head(&rl->wait[WRITE]);
 	init_waitqueue_head(&rl->drain);
 
-	rl->rq_pool = mempool_create(BLKDEV_MIN_RQ, mempool_alloc_slab, mempool_free_slab, request_cachep);
+	rl->rq_pool = mempool_create_node(BLKDEV_MIN_RQ, mempool_alloc_slab,
+				mempool_free_slab, request_cachep, q->node);
 
 	if (!rl->rq_pool)
 		return -ENOMEM;
@@ -1657,8 +1641,15 @@
 
 request_queue_t *blk_alloc_queue(int gfp_mask)
 {
-	request_queue_t *q = kmem_cache_alloc(requestq_cachep, gfp_mask);
+	return blk_alloc_queue_node(gfp_mask, -1);
+}
+EXPORT_SYMBOL(blk_alloc_queue);
 
+request_queue_t *blk_alloc_queue_node(int gfp_mask, int node_id)
+{
+	request_queue_t *q;
+
+	q = kmem_cache_alloc_node(requestq_cachep, gfp_mask, node_id);
 	if (!q)
 		return NULL;
 
@@ -1671,8 +1662,7 @@
 
 	return q;
 }
-
-EXPORT_SYMBOL(blk_alloc_queue);
+EXPORT_SYMBOL(blk_alloc_queue_node);
 
 /**
  * blk_init_queue  - prepare a request queue for use with a block device
@@ -1705,13 +1695,22 @@
  *    blk_init_queue() must be paired with a blk_cleanup_queue() call
  *    when the block device is deactivated (such as at module unload).
  **/
+
 request_queue_t *blk_init_queue(request_fn_proc *rfn, spinlock_t *lock)
 {
-	request_queue_t *q = blk_alloc_queue(GFP_KERNEL);
+	return blk_init_queue_node(rfn, lock, -1);
+}
+EXPORT_SYMBOL(blk_init_queue);
+
+request_queue_t *
+blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id)
+{
+	request_queue_t *q = blk_alloc_queue_node(GFP_KERNEL, node_id);
 
 	if (!q)
 		return NULL;
 
+	q->node = node_id;
 	if (blk_init_free_list(q))
 		goto out_init;
 
@@ -1754,12 +1753,11 @@
 	kmem_cache_free(requestq_cachep, q);
 	return NULL;
 }
-
-EXPORT_SYMBOL(blk_init_queue);
+EXPORT_SYMBOL(blk_init_queue_node);
 
 int blk_get_queue(request_queue_t *q)
 {
-	if (!test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)) {
+	if (likely(!test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))) {
 		atomic_inc(&q->refcnt);
 		return 0;
 	}
@@ -1775,8 +1773,8 @@
 	mempool_free(rq, q->rq.rq_pool);
 }
 
-static inline struct request *blk_alloc_request(request_queue_t *q, int rw,
-						int gfp_mask)
+static inline struct request *
+blk_alloc_request(request_queue_t *q, int rw, struct bio *bio, int gfp_mask)
 {
 	struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask);
 
@@ -1789,7 +1787,7 @@
 	 */
 	rq->flags = rw;
 
-	if (!elv_set_request(q, rq, gfp_mask))
+	if (!elv_set_request(q, rq, bio, gfp_mask))
 		return rq;
 
 	mempool_free(rq, q->rq.rq_pool);
@@ -1821,7 +1819,7 @@
  * is the behaviour we want though - once it gets a wakeup it should be given
  * a nice run.
  */
-void ioc_set_batching(request_queue_t *q, struct io_context *ioc)
+static void ioc_set_batching(request_queue_t *q, struct io_context *ioc)
 {
 	if (!ioc || ioc_batching(q, ioc))
 		return;
@@ -1838,7 +1836,6 @@
 		clear_queue_congested(q, rw);
 
 	if (rl->count[rw] + 1 <= q->nr_requests) {
-		smp_mb();
 		if (waitqueue_active(&rl->wait[rw]))
 			wake_up(&rl->wait[rw]);
 
@@ -1872,7 +1869,8 @@
 /*
  * Get a free request, queue_lock must not be held
  */
-static struct request *get_request(request_queue_t *q, int rw, int gfp_mask)
+static struct request *get_request(request_queue_t *q, int rw, struct bio *bio,
+				   int gfp_mask)
 {
 	struct request *rq = NULL;
 	struct request_list *rl = &q->rq;
@@ -1895,7 +1893,7 @@
 		}
 	}
 
-	switch (elv_may_queue(q, rw)) {
+	switch (elv_may_queue(q, rw, bio)) {
 		case ELV_MQUEUE_NO:
 			goto rq_starved;
 		case ELV_MQUEUE_MAY:
@@ -1920,7 +1918,7 @@
 		set_queue_congested(q, rw);
 	spin_unlock_irq(q->queue_lock);
 
-	rq = blk_alloc_request(q, rw, gfp_mask);
+	rq = blk_alloc_request(q, rw, bio, gfp_mask);
 	if (!rq) {
 		/*
 		 * Allocation failed presumably due to memory. Undo anything
@@ -1961,23 +1959,24 @@
  * No available requests for this queue, unplug the device and wait for some
  * requests to become available.
  */
-static struct request *get_request_wait(request_queue_t *q, int rw)
+static struct request *get_request_wait(request_queue_t *q, int rw,
+					struct bio *bio)
 {
 	DEFINE_WAIT(wait);
 	struct request *rq;
 
-	generic_unplug_device(q);
 	do {
 		struct request_list *rl = &q->rq;
 
 		prepare_to_wait_exclusive(&rl->wait[rw], &wait,
 				TASK_UNINTERRUPTIBLE);
 
-		rq = get_request(q, rw, GFP_NOIO);
+		rq = get_request(q, rw, bio, GFP_NOIO);
 
 		if (!rq) {
 			struct io_context *ioc;
 
+			generic_unplug_device(q);
 			io_schedule();
 
 			/*
@@ -2003,9 +2002,9 @@
 	BUG_ON(rw != READ && rw != WRITE);
 
 	if (gfp_mask & __GFP_WAIT)
-		rq = get_request_wait(q, rw);
+		rq = get_request_wait(q, rw, NULL);
 	else
-		rq = get_request(q, rw, gfp_mask);
+		rq = get_request(q, rw, NULL, gfp_mask);
 
 	return rq;
 }
@@ -2038,7 +2037,6 @@
  * @rq:		request to be inserted
  * @at_head:	insert request at head or tail of queue
  * @data:	private data
- * @reinsert:	true if request it a reinsertion of previously processed one
  *
  * Description:
  *    Many block devices need to execute commands asynchronously, so they don't
@@ -2053,8 +2051,9 @@
  *    host that is unable to accept a particular command.
  */
 void blk_insert_request(request_queue_t *q, struct request *rq,
-			int at_head, void *data, int reinsert)
+			int at_head, void *data)
 {
+	int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
 	unsigned long flags;
 
 	/*
@@ -2071,20 +2070,12 @@
 	/*
 	 * If command is tagged, release the tag
 	 */
-	if (reinsert)
-		blk_requeue_request(q, rq);
-	else {
-		int where = ELEVATOR_INSERT_BACK;
+	if (blk_rq_tagged(rq))
+		blk_queue_end_tag(q, rq);
 
-		if (at_head)
-			where = ELEVATOR_INSERT_FRONT;
+	drive_stat_acct(rq, rq->nr_sectors, 1);
+	__elv_add_request(q, rq, where, 0);
 
-		if (blk_rq_tagged(rq))
-			blk_queue_end_tag(q, rq);
-
-		drive_stat_acct(rq, rq->nr_sectors, 1);
-		__elv_add_request(q, rq, where, 0);
-	}
 	if (blk_queue_plugged(q))
 		__generic_unplug_device(q);
 	else
@@ -2259,45 +2250,7 @@
 
 EXPORT_SYMBOL(blkdev_issue_flush);
 
-/**
- * blkdev_scsi_issue_flush_fn - issue flush for SCSI devices
- * @q:		device queue
- * @disk:	gendisk
- * @error_sector:	error offset
- *
- * Description:
- *    Devices understanding the SCSI command set, can use this function as
- *    a helper for issuing a cache flush. Note: driver is required to store
- *    the error offset (in case of error flushing) in ->sector of struct
- *    request.
- */
-int blkdev_scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
-			       sector_t *error_sector)
-{
-	struct request *rq = blk_get_request(q, WRITE, __GFP_WAIT);
-	int ret;
-
-	rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER;
-	rq->sector = 0;
-	memset(rq->cmd, 0, sizeof(rq->cmd));
-	rq->cmd[0] = 0x35;
-	rq->cmd_len = 12;
-	rq->data = NULL;
-	rq->data_len = 0;
-	rq->timeout = 60 * HZ;
-
-	ret = blk_execute_rq(q, disk, rq);
-
-	if (ret && error_sector)
-		*error_sector = rq->sector;
-
-	blk_put_request(rq);
-	return ret;
-}
-
-EXPORT_SYMBOL(blkdev_scsi_issue_flush_fn);
-
-void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
+static void drive_stat_acct(struct request *rq, int nr_sectors, int new_io)
 {
 	int rw = rq_data_dir(rq);
 
@@ -2379,7 +2332,6 @@
 		return;
 
 	req->rq_status = RQ_INACTIVE;
-	req->q = NULL;
 	req->rl = NULL;
 
 	/*
@@ -2508,6 +2460,8 @@
 		req->rq_disk->in_flight--;
 	}
 
+	req->ioprio = ioprio_best(req->ioprio, next->ioprio);
+
 	__blk_put_request(q, next);
 	return 1;
 }
@@ -2556,25 +2510,17 @@
 
 EXPORT_SYMBOL(blk_attempt_remerge);
 
-/*
- * Non-locking blk_attempt_remerge variant.
- */
-void __blk_attempt_remerge(request_queue_t *q, struct request *rq)
-{
-	attempt_back_merge(q, rq);
-}
-
-EXPORT_SYMBOL(__blk_attempt_remerge);
-
 static int __make_request(request_queue_t *q, struct bio *bio)
 {
 	struct request *req, *freereq = NULL;
 	int el_ret, rw, nr_sectors, cur_nr_sectors, barrier, err, sync;
+	unsigned short prio;
 	sector_t sector;
 
 	sector = bio->bi_sector;
 	nr_sectors = bio_sectors(bio);
 	cur_nr_sectors = bio_cur_sectors(bio);
+	prio = bio_prio(bio);
 
 	rw = bio_data_dir(bio);
 	sync = bio_sync(bio);
@@ -2589,7 +2535,7 @@
 	spin_lock_prefetch(q->queue_lock);
 
 	barrier = bio_barrier(bio);
-	if (barrier && (q->ordered == QUEUE_ORDERED_NONE)) {
+	if (unlikely(barrier) && (q->ordered == QUEUE_ORDERED_NONE)) {
 		err = -EOPNOTSUPP;
 		goto end_io;
 	}
@@ -2615,6 +2561,7 @@
 			req->biotail->bi_next = bio;
 			req->biotail = bio;
 			req->nr_sectors = req->hard_nr_sectors += nr_sectors;
+			req->ioprio = ioprio_best(req->ioprio, prio);
 			drive_stat_acct(req, nr_sectors, 0);
 			if (!attempt_back_merge(q, req))
 				elv_merged_request(q, req);
@@ -2639,6 +2586,7 @@
 			req->hard_cur_sectors = cur_nr_sectors;
 			req->sector = req->hard_sector = sector;
 			req->nr_sectors = req->hard_nr_sectors += nr_sectors;
+			req->ioprio = ioprio_best(req->ioprio, prio);
 			drive_stat_acct(req, nr_sectors, 0);
 			if (!attempt_front_merge(q, req))
 				elv_merged_request(q, req);
@@ -2666,7 +2614,7 @@
 		freereq = NULL;
 	} else {
 		spin_unlock_irq(q->queue_lock);
-		if ((freereq = get_request(q, rw, GFP_ATOMIC)) == NULL) {
+		if ((freereq = get_request(q, rw, bio, GFP_ATOMIC)) == NULL) {
 			/*
 			 * READA bit set
 			 */
@@ -2674,7 +2622,7 @@
 			if (bio_rw_ahead(bio))
 				goto end_io;
 	
-			freereq = get_request_wait(q, rw);
+			freereq = get_request_wait(q, rw, bio);
 		}
 		goto again;
 	}
@@ -2690,7 +2638,7 @@
 	/*
 	 * REQ_BARRIER implies no merging, but lets make it explicit
 	 */
-	if (barrier)
+	if (unlikely(barrier))
 		req->flags |= (REQ_HARDBARRIER | REQ_NOMERGE);
 
 	req->errors = 0;
@@ -2702,6 +2650,7 @@
 	req->buffer = bio_data(bio);	/* see ->buffer comment above */
 	req->waiting = NULL;
 	req->bio = req->biotail = bio;
+	req->ioprio = prio;
 	req->rq_disk = bio->bi_bdev->bd_disk;
 	req->start_time = jiffies;
 
@@ -2730,7 +2679,7 @@
 	if (bdev != bdev->bd_contains) {
 		struct hd_struct *p = bdev->bd_part;
 
-		switch (bio->bi_rw) {
+		switch (bio_data_dir(bio)) {
 		case READ:
 			p->read_sectors += bio_sectors(bio);
 			p->reads++;
@@ -2749,6 +2698,7 @@
 {
 	struct request_list *rl = &q->rq;
 	struct request *rq;
+	int requeued = 0;
 
 	spin_lock_irq(q->queue_lock);
 	clear_bit(QUEUE_FLAG_DRAIN, &q->queue_flags);
@@ -2757,9 +2707,13 @@
 		rq = list_entry_rq(q->drain_list.next);
 
 		list_del_init(&rq->queuelist);
-		__elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1);
+		elv_requeue_request(q, rq);
+		requeued++;
 	}
 
+	if (requeued)
+		q->request_fn(q);
+
 	spin_unlock_irq(q->queue_lock);
 
 	wake_up(&rl->wait[0]);
@@ -2814,7 +2768,7 @@
 {
 	DEFINE_WAIT(wait);
 
-	while (test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags)) {
+	while (unlikely(test_bit(QUEUE_FLAG_DRAIN, &q->queue_flags))) {
 		struct request_list *rl = &q->rq;
 
 		prepare_to_wait_exclusive(&rl->drain, &wait,
@@ -2923,7 +2877,7 @@
 			goto end_io;
 		}
 
-		if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))
+		if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
 			goto end_io;
 
 		block_wait_queue_running(q);
@@ -2956,7 +2910,7 @@
 
 	BIO_BUG_ON(!bio->bi_size);
 	BIO_BUG_ON(!bio->bi_io_vec);
-	bio->bi_rw = rw;
+	bio->bi_rw |= rw;
 	if (rw & WRITE)
 		mod_page_state(pgpgout, count);
 	else
@@ -2976,7 +2930,7 @@
 
 EXPORT_SYMBOL(submit_bio);
 
-void blk_recalc_rq_segments(struct request *rq)
+static void blk_recalc_rq_segments(struct request *rq)
 {
 	struct bio *bio, *prevbio = NULL;
 	int nr_phys_segs, nr_hw_segs;
@@ -3018,7 +2972,7 @@
 	rq->nr_hw_segments = nr_hw_segs;
 }
 
-void blk_recalc_rq_sectors(struct request *rq, int nsect)
+static void blk_recalc_rq_sectors(struct request *rq, int nsect)
 {
 	if (blk_fs_request(rq)) {
 		rq->hard_sector += nsect;
@@ -3313,8 +3267,11 @@
 	struct io_context *ioc;
 
 	local_irq_save(flags);
+	task_lock(current);
 	ioc = current->io_context;
 	current->io_context = NULL;
+	ioc->task = NULL;
+	task_unlock(current);
 	local_irq_restore(flags);
 
 	if (ioc->aic && ioc->aic->exit)
@@ -3349,12 +3306,12 @@
 	ret = kmem_cache_alloc(iocontext_cachep, gfp_flags);
 	if (ret) {
 		atomic_set(&ret->refcount, 1);
-		ret->pid = tsk->pid;
+		ret->task = current;
+		ret->set_ioprio = NULL;
 		ret->last_waited = jiffies; /* doesn't matter... */
 		ret->nr_batch_requests = 0; /* because this is 0 */
 		ret->aic = NULL;
 		ret->cic = NULL;
-		spin_lock_init(&ret->lock);
 
 		local_irq_save(flags);
 
@@ -3582,7 +3539,7 @@
 
 	q = container_of(kobj, struct request_queue, kobj);
 	if (!entry->show)
-		return 0;
+		return -EIO;
 
 	return entry->show(q, page);
 }
@@ -3596,7 +3553,7 @@
 
 	q = container_of(kobj, struct request_queue, kobj);
 	if (!entry->store)
-		return -EINVAL;
+		return -EIO;
 
 	return entry->store(q, page, length);
 }
@@ -3606,7 +3563,7 @@
 	.store	= queue_attr_store,
 };
 
-struct kobj_type queue_ktype = {
+static struct kobj_type queue_ktype = {
 	.sysfs_ops	= &queue_sysfs_ops,
 	.default_attrs	= default_attrs,
 };
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 6f011d0..b35e088 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -472,17 +472,11 @@
  */
 static void loop_add_bio(struct loop_device *lo, struct bio *bio)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&lo->lo_lock, flags);
 	if (lo->lo_biotail) {
 		lo->lo_biotail->bi_next = bio;
 		lo->lo_biotail = bio;
 	} else
 		lo->lo_bio = lo->lo_biotail = bio;
-	spin_unlock_irqrestore(&lo->lo_lock, flags);
-
-	up(&lo->lo_bh_mutex);
 }
 
 /*
@@ -492,14 +486,12 @@
 {
 	struct bio *bio;
 
-	spin_lock_irq(&lo->lo_lock);
 	if ((bio = lo->lo_bio)) {
 		if (bio == lo->lo_biotail)
 			lo->lo_biotail = NULL;
 		lo->lo_bio = bio->bi_next;
 		bio->bi_next = NULL;
 	}
-	spin_unlock_irq(&lo->lo_lock);
 
 	return bio;
 }
@@ -509,35 +501,28 @@
 	struct loop_device *lo = q->queuedata;
 	int rw = bio_rw(old_bio);
 
-	if (!lo)
-		goto out;
+	if (rw == READA)
+		rw = READ;
+
+	BUG_ON(!lo || (rw != READ && rw != WRITE));
 
 	spin_lock_irq(&lo->lo_lock);
 	if (lo->lo_state != Lo_bound)
-		goto inactive;
-	atomic_inc(&lo->lo_pending);
-	spin_unlock_irq(&lo->lo_lock);
-
-	if (rw == WRITE) {
-		if (lo->lo_flags & LO_FLAGS_READ_ONLY)
-			goto err;
-	} else if (rw == READA) {
-		rw = READ;
-	} else if (rw != READ) {
-		printk(KERN_ERR "loop: unknown command (%x)\n", rw);
-		goto err;
-	}
+		goto out;
+	if (unlikely(rw == WRITE && (lo->lo_flags & LO_FLAGS_READ_ONLY)))
+		goto out;
+	lo->lo_pending++;
 	loop_add_bio(lo, old_bio);
+	spin_unlock_irq(&lo->lo_lock);
+	up(&lo->lo_bh_mutex);
 	return 0;
-err:
-	if (atomic_dec_and_test(&lo->lo_pending))
-		up(&lo->lo_bh_mutex);
+
 out:
+	if (lo->lo_pending == 0)
+		up(&lo->lo_bh_mutex);
+	spin_unlock_irq(&lo->lo_lock);
 	bio_io_error(old_bio, old_bio->bi_size);
 	return 0;
-inactive:
-	spin_unlock_irq(&lo->lo_lock);
-	goto out;
 }
 
 /*
@@ -560,13 +545,11 @@
 
 static inline void loop_handle_bio(struct loop_device *lo, struct bio *bio)
 {
-	int ret;
-
 	if (unlikely(!bio->bi_bdev)) {
 		do_loop_switch(lo, bio->bi_private);
 		bio_put(bio);
 	} else {
-		ret = do_bio_filebacked(lo, bio);
+		int ret = do_bio_filebacked(lo, bio);
 		bio_endio(bio, bio->bi_size, ret);
 	}
 }
@@ -594,7 +577,7 @@
 	set_user_nice(current, -20);
 
 	lo->lo_state = Lo_bound;
-	atomic_inc(&lo->lo_pending);
+	lo->lo_pending = 1;
 
 	/*
 	 * up sem, we are running
@@ -602,26 +585,37 @@
 	up(&lo->lo_sem);
 
 	for (;;) {
-		down_interruptible(&lo->lo_bh_mutex);
+		int pending;
+
 		/*
-		 * could be upped because of tear-down, not because of
-		 * pending work
+		 * interruptible just to not contribute to load avg
 		 */
-		if (!atomic_read(&lo->lo_pending))
+		if (down_interruptible(&lo->lo_bh_mutex))
+			continue;
+
+		spin_lock_irq(&lo->lo_lock);
+
+		/*
+		 * could be upped because of tear-down, not pending work
+		 */
+		if (unlikely(!lo->lo_pending)) {
+			spin_unlock_irq(&lo->lo_lock);
 			break;
+		}
 
 		bio = loop_get_bio(lo);
-		if (!bio) {
-			printk("loop: missing bio\n");
-			continue;
-		}
+		lo->lo_pending--;
+		pending = lo->lo_pending;
+		spin_unlock_irq(&lo->lo_lock);
+
+		BUG_ON(!bio);
 		loop_handle_bio(lo, bio);
 
 		/*
 		 * upped both for pending work and tear-down, lo_pending
 		 * will hit zero then
 		 */
-		if (atomic_dec_and_test(&lo->lo_pending))
+		if (unlikely(!pending))
 			break;
 	}
 
@@ -900,7 +894,8 @@
 
 	spin_lock_irq(&lo->lo_lock);
 	lo->lo_state = Lo_rundown;
-	if (atomic_dec_and_test(&lo->lo_pending))
+	lo->lo_pending--;
+	if (!lo->lo_pending)
 		up(&lo->lo_bh_mutex);
 	spin_unlock_irq(&lo->lo_lock);
 
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 202a5a7..fa49d62 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -723,7 +723,7 @@
 	rq.ref_count = 1;
 	rq.waiting = &wait;
 	rq.end_io = blk_end_sync_rq;
-	blk_insert_request(disk->gd->queue, &rq, 0, func, 0);
+	blk_insert_request(disk->gd->queue, &rq, 0, func);
 	wait_for_completion(&wait);
 	rq.waiting = NULL;
 	if (rq.errors)
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index dbeb107..84d8e29 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -222,7 +222,7 @@
 
 static char pg_scratch[512];	/* scratch block buffer */
 
-static struct class_simple *pg_class;
+static struct class *pg_class;
 
 /* kernel glue structures */
 
@@ -666,7 +666,7 @@
 		err = -1;
 		goto out;
 	}
-	pg_class = class_simple_create(THIS_MODULE, "pg");
+	pg_class = class_create(THIS_MODULE, "pg");
 	if (IS_ERR(pg_class)) {
 		err = PTR_ERR(pg_class);
 		goto out_chrdev;
@@ -675,7 +675,7 @@
 	for (unit = 0; unit < PG_UNITS; unit++) {
 		struct pg *dev = &devices[unit];
 		if (dev->present) {
-			class_simple_device_add(pg_class, MKDEV(major, unit), 
+			class_device_create(pg_class, MKDEV(major, unit),
 					NULL, "pg%u", unit);
 			err = devfs_mk_cdev(MKDEV(major, unit),
 				      S_IFCHR | S_IRUSR | S_IWUSR, "pg/%u",
@@ -688,8 +688,8 @@
 	goto out;
 
 out_class:
-	class_simple_device_remove(MKDEV(major, unit));
-	class_simple_destroy(pg_class);
+	class_device_destroy(pg_class, MKDEV(major, unit));
+	class_destroy(pg_class);
 out_chrdev:
 	unregister_chrdev(major, "pg");
 out:
@@ -703,11 +703,11 @@
 	for (unit = 0; unit < PG_UNITS; unit++) {
 		struct pg *dev = &devices[unit];
 		if (dev->present) {
-			class_simple_device_remove(MKDEV(major, unit));
+			class_device_destroy(pg_class, MKDEV(major, unit));
 			devfs_remove("pg/%u", unit);
 		}
 	}
-	class_simple_destroy(pg_class);
+	class_destroy(pg_class);
 	devfs_remove("pg");
 	unregister_chrdev(major, name);
 
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 8fbd692..5fe8ee8 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -242,7 +242,7 @@
 };
 
 /* sysfs class support */
-static struct class_simple *pt_class;
+static struct class *pt_class;
 
 static inline int status_reg(struct pi_adapter *pi)
 {
@@ -963,7 +963,7 @@
 		err = -1;
 		goto out;
 	}
-	pt_class = class_simple_create(THIS_MODULE, "pt");
+	pt_class = class_create(THIS_MODULE, "pt");
 	if (IS_ERR(pt_class)) {
 		err = PTR_ERR(pt_class);
 		goto out_chrdev;
@@ -972,29 +972,29 @@
 	devfs_mk_dir("pt");
 	for (unit = 0; unit < PT_UNITS; unit++)
 		if (pt[unit].present) {
-			class_simple_device_add(pt_class, MKDEV(major, unit), 
+			class_device_create(pt_class, MKDEV(major, unit),
 					NULL, "pt%d", unit);
 			err = devfs_mk_cdev(MKDEV(major, unit),
 				      S_IFCHR | S_IRUSR | S_IWUSR,
 				      "pt/%d", unit);
 			if (err) {
-				class_simple_device_remove(MKDEV(major, unit));
+				class_device_destroy(pt_class, MKDEV(major, unit));
 				goto out_class;
 			}
-			class_simple_device_add(pt_class, MKDEV(major, unit + 128),
+			class_device_create(pt_class, MKDEV(major, unit + 128),
 					NULL, "pt%dn", unit);
 			err = devfs_mk_cdev(MKDEV(major, unit + 128),
 				      S_IFCHR | S_IRUSR | S_IWUSR,
 				      "pt/%dn", unit);
 			if (err) {
-				class_simple_device_remove(MKDEV(major, unit + 128));
+				class_device_destroy(pt_class, MKDEV(major, unit + 128));
 				goto out_class;
 			}
 		}
 	goto out;
 
 out_class:
-	class_simple_destroy(pt_class);
+	class_destroy(pt_class);
 out_chrdev:
 	unregister_chrdev(major, "pt");
 out:
@@ -1006,12 +1006,12 @@
 	int unit;
 	for (unit = 0; unit < PT_UNITS; unit++)
 		if (pt[unit].present) {
-			class_simple_device_remove(MKDEV(major, unit));
+			class_device_destroy(pt_class, MKDEV(major, unit));
 			devfs_remove("pt/%d", unit);
-			class_simple_device_remove(MKDEV(major, unit + 128));
+			class_device_destroy(pt_class, MKDEV(major, unit + 128));
 			devfs_remove("pt/%dn", unit);
 		}
-	class_simple_destroy(pt_class);
+	class_destroy(pt_class);
 	devfs_remove("pt");
 	unregister_chrdev(major, name);
 	for (unit = 0; unit < PT_UNITS; unit++)
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index bc56770..7b83834 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -467,14 +467,12 @@
  * Queue a bio for processing by the low-level CD device. Must be called
  * from process context.
  */
-static void pkt_queue_bio(struct pktcdvd_device *pd, struct bio *bio, int high_prio_read)
+static void pkt_queue_bio(struct pktcdvd_device *pd, struct bio *bio)
 {
 	spin_lock(&pd->iosched.lock);
 	if (bio_data_dir(bio) == READ) {
 		pkt_add_list_last(bio, &pd->iosched.read_queue,
 				  &pd->iosched.read_queue_tail);
-		if (high_prio_read)
-			pd->iosched.high_prio_read = 1;
 	} else {
 		pkt_add_list_last(bio, &pd->iosched.write_queue,
 				  &pd->iosched.write_queue_tail);
@@ -490,15 +488,16 @@
  * requirements for CDRW drives:
  * - A cache flush command must be inserted before a read request if the
  *   previous request was a write.
- * - Switching between reading and writing is slow, so don't it more often
+ * - Switching between reading and writing is slow, so don't do it more often
  *   than necessary.
+ * - Optimize for throughput at the expense of latency. This means that streaming
+ *   writes will never be interrupted by a read, but if the drive has to seek
+ *   before the next write, switch to reading instead if there are any pending
+ *   read requests.
  * - Set the read speed according to current usage pattern. When only reading
  *   from the device, it's best to use the highest possible read speed, but
  *   when switching often between reading and writing, it's better to have the
  *   same read and write speeds.
- * - Reads originating from user space should have higher priority than reads
- *   originating from pkt_gather_data, because some process is usually waiting
- *   on reads of the first kind.
  */
 static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
 {
@@ -512,21 +511,24 @@
 
 	for (;;) {
 		struct bio *bio;
-		int reads_queued, writes_queued, high_prio_read;
+		int reads_queued, writes_queued;
 
 		spin_lock(&pd->iosched.lock);
 		reads_queued = (pd->iosched.read_queue != NULL);
 		writes_queued = (pd->iosched.write_queue != NULL);
-		if (!reads_queued)
-			pd->iosched.high_prio_read = 0;
-		high_prio_read = pd->iosched.high_prio_read;
 		spin_unlock(&pd->iosched.lock);
 
 		if (!reads_queued && !writes_queued)
 			break;
 
 		if (pd->iosched.writing) {
-			if (high_prio_read || (!writes_queued && reads_queued)) {
+			int need_write_seek = 1;
+			spin_lock(&pd->iosched.lock);
+			bio = pd->iosched.write_queue;
+			spin_unlock(&pd->iosched.lock);
+			if (bio && (bio->bi_sector == pd->iosched.last_write))
+				need_write_seek = 0;
+			if (need_write_seek && reads_queued) {
 				if (atomic_read(&pd->cdrw.pending_bios) > 0) {
 					VPRINTK("pktcdvd: write, waiting\n");
 					break;
@@ -559,8 +561,10 @@
 
 		if (bio_data_dir(bio) == READ)
 			pd->iosched.successive_reads += bio->bi_size >> 10;
-		else
+		else {
 			pd->iosched.successive_reads = 0;
+			pd->iosched.last_write = bio->bi_sector + bio_sectors(bio);
+		}
 		if (pd->iosched.successive_reads >= HI_SPEED_SWITCH) {
 			if (pd->read_speed == pd->write_speed) {
 				pd->read_speed = MAX_SPEED;
@@ -765,7 +769,7 @@
 
 		atomic_inc(&pkt->io_wait);
 		bio->bi_rw = READ;
-		pkt_queue_bio(pd, bio, 0);
+		pkt_queue_bio(pd, bio);
 		frames_read++;
 	}
 
@@ -1062,7 +1066,7 @@
 
 	atomic_set(&pkt->io_wait, 1);
 	pkt->w_bio->bi_rw = WRITE;
-	pkt_queue_bio(pd, pkt->w_bio, 0);
+	pkt_queue_bio(pd, pkt->w_bio);
 }
 
 static void pkt_finish_packet(struct packet_data *pkt, int uptodate)
@@ -1247,8 +1251,7 @@
 			VPRINTK("kcdrwd: wake up\n");
 
 			/* make swsusp happy with our thread */
-			if (current->flags & PF_FREEZE)
-				refrigerator(PF_FREEZE);
+			try_to_freeze();
 
 			list_for_each_entry(pkt, &pd->cdrw.pkt_active_list, list) {
 				if (!pkt->sleep_time)
@@ -2120,7 +2123,7 @@
 		cloned_bio->bi_private = psd;
 		cloned_bio->bi_end_io = pkt_end_io_read_cloned;
 		pd->stats.secs_r += bio->bi_size >> 9;
-		pkt_queue_bio(pd, cloned_bio, 1);
+		pkt_queue_bio(pd, cloned_bio);
 		return 0;
 	}
 
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index 797f598..5ed3a63 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -614,7 +614,7 @@
 	spin_unlock_irq(&host->lock);
 
 	DPRINTK("blk_insert_request, tag == %u\n", idx);
-	blk_insert_request(host->oob_q, crq->rq, 1, crq, 0);
+	blk_insert_request(host->oob_q, crq->rq, 1, crq);
 
 	return 0;
 
@@ -653,7 +653,7 @@
 	crq->msg_bucket = (u32) rc;
 
 	DPRINTK("blk_insert_request, tag == %u\n", idx);
-	blk_insert_request(host->oob_q, crq->rq, 1, crq, 0);
+	blk_insert_request(host->oob_q, crq->rq, 1, crq);
 
 	return 0;
 }
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index adc4dcc..685f061 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -51,7 +51,7 @@
  * This many LUNs per USB device.
  * Every one of them takes a host, see UB_MAX_HOSTS.
  */
-#define UB_MAX_LUNS   4
+#define UB_MAX_LUNS   9
 
 /*
  */
@@ -430,7 +430,7 @@
 	}
 }
 
-static ssize_t ub_diag_show(struct device *dev, char *page)
+static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr, char *page)
 {
 	struct usb_interface *intf;
 	struct ub_dev *sc;
@@ -2100,7 +2100,7 @@
 			nluns = rc;
 			break;
 		}
-		mdelay(100);
+		msleep(100);
 	}
 
 	for (i = 0; i < nluns; i++) {
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 9075bbb..f766bc2 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -576,7 +576,7 @@
 #endif
 
 	/* Release tty registration of line discipline */
-	if ((err = tty_register_ldisc(N_HCI, NULL)))
+	if ((err = tty_unregister_ldisc(N_HCI)))
 		BT_ERR("Can't unregister HCI line discipline (%d)", err);
 }
 
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
index da80b14..01f0351 100644
--- a/drivers/cdrom/cm206.c
+++ b/drivers/cdrom/cm206.c
@@ -307,7 +307,7 @@
 /* First, we define some polling functions. These are actually
    only being used in the initialization. */
 
-void send_command_polled(int command)
+static void send_command_polled(int command)
 {
 	int loop = POLLOOP;
 	while (!(inw(r_line_status) & ls_transmitter_buffer_empty)
@@ -318,7 +318,7 @@
 	outw(command, r_uart_transmit);
 }
 
-uch receive_echo_polled(void)
+static uch receive_echo_polled(void)
 {
 	int loop = POLLOOP;
 	while (!(inw(r_line_status) & ls_receive_buffer_full) && loop > 0) {
@@ -328,13 +328,13 @@
 	return ((uch) inw(r_uart_receive));
 }
 
-uch send_receive_polled(int command)
+static uch send_receive_polled(int command)
 {
 	send_command_polled(command);
 	return receive_echo_polled();
 }
 
-inline void clear_ur(void)
+static inline void clear_ur(void)
 {
 	if (cd->ur_r != cd->ur_w) {
 		debug(("Deleting bytes from fifo:"));
@@ -439,7 +439,7 @@
 }
 
 /* we have put the address of the wait queue in who */
-void cm206_timeout(unsigned long who)
+static void cm206_timeout(unsigned long who)
 {
 	cd->timed_out = 1;
 	debug(("Timing out\n"));
@@ -448,7 +448,7 @@
 
 /* This function returns 1 if a timeout occurred, 0 if an interrupt
    happened */
-int sleep_or_timeout(wait_queue_head_t * wait, int timeout)
+static int sleep_or_timeout(wait_queue_head_t * wait, int timeout)
 {
 	cd->timed_out = 0;
 	init_timer(&cd->timer);
@@ -465,13 +465,7 @@
 		return 0;
 }
 
-void cm206_delay(int nr_jiffies)
-{
-	DECLARE_WAIT_QUEUE_HEAD(wait);
-	sleep_or_timeout(&wait, nr_jiffies);
-}
-
-void send_command(int command)
+static void send_command(int command)
 {
 	debug(("Sending 0x%x\n", command));
 	if (!(inw(r_line_status) & ls_transmitter_buffer_empty)) {
@@ -490,7 +484,7 @@
 		outw(command, r_uart_transmit);
 }
 
-uch receive_byte(int timeout)
+static uch receive_byte(int timeout)
 {
 	uch ret;
 	cli();
@@ -521,23 +515,23 @@
 	return ret;
 }
 
-inline uch receive_echo(void)
+static inline uch receive_echo(void)
 {
 	return receive_byte(UART_TIMEOUT);
 }
 
-inline uch send_receive(int command)
+static inline uch send_receive(int command)
 {
 	send_command(command);
 	return receive_echo();
 }
 
-inline uch wait_dsb(void)
+static inline uch wait_dsb(void)
 {
 	return receive_byte(DSB_TIMEOUT);
 }
 
-int type_0_command(int command, int expect_dsb)
+static int type_0_command(int command, int expect_dsb)
 {
 	int e;
 	clear_ur();
@@ -552,7 +546,7 @@
 	return 0;
 }
 
-int type_1_command(int command, int bytes, uch * status)
+static int type_1_command(int command, int bytes, uch * status)
 {				/* returns info */
 	int i;
 	if (type_0_command(command, 0))
@@ -564,7 +558,7 @@
 
 /* This function resets the adapter card. We'd better not do this too
  * often, because it tends to generate `lost interrupts.' */
-void reset_cm260(void)
+static void reset_cm260(void)
 {
 	outw(dc_normal | dc_initialize | READ_AHEAD, r_data_control);
 	udelay(10);		/* 3.3 mu sec minimum */
@@ -572,7 +566,7 @@
 }
 
 /* fsm: frame-sec-min from linear address; one of many */
-void fsm(int lba, uch * fsm)
+static void fsm(int lba, uch * fsm)
 {
 	fsm[0] = lba % 75;
 	lba /= 75;
@@ -581,17 +575,17 @@
 	fsm[2] = lba / 60;
 }
 
-inline int fsm2lba(uch * fsm)
+static inline int fsm2lba(uch * fsm)
 {
 	return fsm[0] + 75 * (fsm[1] - 2 + 60 * fsm[2]);
 }
 
-inline int f_s_m2lba(uch f, uch s, uch m)
+static inline int f_s_m2lba(uch f, uch s, uch m)
 {
 	return f + 75 * (s - 2 + 60 * m);
 }
 
-int start_read(int start)
+static int start_read(int start)
 {
 	uch read_sector[4] = { c_read_data, };
 	int i, e;
@@ -613,7 +607,7 @@
 	return 0;
 }
 
-int stop_read(void)
+static int stop_read(void)
 {
 	int e;
 	type_0_command(c_stop, 0);
@@ -630,7 +624,7 @@
    routine takes care of this. Set a flag `background' in the cd
    struct to indicate the process. */
 
-int read_background(int start, int reading)
+static int read_background(int start, int reading)
 {
 	if (cd->background)
 		return -1;	/* can't do twice */
@@ -658,7 +652,7 @@
 
 
 #define MAX_TRIES 100
-int read_sector(int start)
+static int read_sector(int start)
 {
 	int tries = 0;
 	if (cd->background) {
@@ -753,7 +747,7 @@
 /* This command clears the dsb_possible_media_change flag, so we must 
  * retain it.
  */
-void get_drive_status(void)
+static void get_drive_status(void)
 {
 	uch status[2];
 	type_1_command(c_drive_status, 2, status);	/* this might be done faster */
@@ -764,7 +758,7 @@
 			  dsb_drive_not_ready | dsb_tray_not_closed));
 }
 
-void get_disc_status(void)
+static void get_disc_status(void)
 {
 	if (type_1_command(c_disc_status, 7, cd->disc_status)) {
 		debug(("get_disc_status: error\n"));
@@ -801,7 +795,7 @@
 
 /* Empty buffer empties $sectors$ sectors of the adapter card buffer,
  * and then reads a sector in kernel memory.  */
-void empty_buffer(int sectors)
+static void empty_buffer(int sectors)
 {
 	while (sectors >= 0) {
 		transport_data(r_fifo_output_buffer,
@@ -819,7 +813,7 @@
 /* try_adapter. This function determines if the requested sector is
    in adapter memory, or will appear there soon. Returns 0 upon
    success */
-int try_adapter(int sector)
+static int try_adapter(int sector)
 {
 	if (cd->adapter_first <= sector && sector < cd->adapter_last) {
 		/* sector is in adapter memory */
@@ -910,7 +904,7 @@
 */
 
 /* seek seeks to address lba. It does wait to arrive there. */
-void seek(int lba)
+static void seek(int lba)
 {
 	int i;
 	uch seek_command[4] = { c_seek, };
@@ -926,7 +920,7 @@
 	return (bcd >> 4) * 10 + (bcd & 0xf);
 }
 
-inline uch normalize_track(uch track)
+static inline uch normalize_track(uch track)
 {
 	if (track < 1)
 		return 1;
@@ -939,7 +933,7 @@
  * tracks seen in the process. Input $track$ must be between 1 and
  * #-of-tracks+1.  Note that the start of the disc must be in toc[1].fsm. 
  */
-int get_toc_lba(uch track)
+static int get_toc_lba(uch track)
 {
 	int max = 74 * 60 * 75 - 150, min = fsm2lba(cd->toc[1].fsm);
 	int i, lba, l, old_lba = 0;
@@ -991,7 +985,7 @@
 	return lba;
 }
 
-void update_toc_entry(uch track)
+static void update_toc_entry(uch track)
 {
 	track = normalize_track(track);
 	if (!cd->toc[track].track)
@@ -999,7 +993,7 @@
 }
 
 /* return 0 upon success */
-int read_toc_header(struct cdrom_tochdr *hp)
+static int read_toc_header(struct cdrom_tochdr *hp)
 {
 	if (!FIRST_TRACK)
 		get_disc_status();
@@ -1016,7 +1010,7 @@
 	return -1;
 }
 
-void play_from_to_msf(struct cdrom_msf *msfp)
+static void play_from_to_msf(struct cdrom_msf *msfp)
 {
 	uch play_command[] = { c_play,
 		msfp->cdmsf_frame0, msfp->cdmsf_sec0, msfp->cdmsf_min0,
@@ -1032,7 +1026,7 @@
 	cd->dsb = wait_dsb();
 }
 
-void play_from_to_track(int from, int to)
+static void play_from_to_track(int from, int to)
 {
 	uch play_command[8] = { c_play, };
 	int i;
@@ -1059,7 +1053,7 @@
 	cd->dsb = wait_dsb();
 }
 
-int get_current_q(struct cdrom_subchnl *qp)
+static int get_current_q(struct cdrom_subchnl *qp)
 {
 	int i;
 	uch *q = cd->q;
@@ -1093,14 +1087,14 @@
 	return 0;
 }
 
-void invalidate_toc(void)
+static void invalidate_toc(void)
 {
 	memset(cd->toc, 0, sizeof(cd->toc));
 	memset(cd->disc_status, 0, sizeof(cd->disc_status));
 }
 
 /* cdrom.c guarantees that cdte_format == CDROM_MSF */
-void get_toc_entry(struct cdrom_tocentry *ep)
+static void get_toc_entry(struct cdrom_tocentry *ep)
 {
 	uch track = normalize_track(ep->cdte_track);
 	update_toc_entry(track);
@@ -1117,8 +1111,8 @@
  * upon success. Memory checking has been done by cdrom_ioctl(), the
  * calling function, as well as LBA/MSF sanitization.
 */
-int cm206_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
-		      void *arg)
+static int cm206_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
+			     void *arg)
 {
 	switch (cmd) {
 	case CDROMREADTOCHDR:
@@ -1189,7 +1183,7 @@
 	}
 }
 
-int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr)
+static int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr)
 {
 	if (cd != NULL) {
 		int r;
@@ -1204,16 +1198,9 @@
 /* The new generic cdrom support. Routines should be concise, most of
    the logic should be in cdrom.c */
 
-/* returns number of times device is in use */
-int cm206_open_files(struct cdrom_device_info *cdi)
-{
-	if (cd)
-		return cd->openfiles;
-	return -1;
-}
 
 /* controls tray movement */
-int cm206_tray_move(struct cdrom_device_info *cdi, int position)
+static int cm206_tray_move(struct cdrom_device_info *cdi, int position)
 {
 	if (position) {		/* 1: eject */
 		type_0_command(c_open_tray, 1);
@@ -1224,7 +1211,7 @@
 }
 
 /* gives current state of the drive */
-int cm206_drive_status(struct cdrom_device_info *cdi, int slot_nr)
+static int cm206_drive_status(struct cdrom_device_info *cdi, int slot_nr)
 {
 	get_drive_status();
 	if (cd->dsb & dsb_tray_not_closed)
@@ -1237,7 +1224,7 @@
 }
 
 /* locks or unlocks door lock==1: lock; return 0 upon success */
-int cm206_lock_door(struct cdrom_device_info *cdi, int lock)
+static int cm206_lock_door(struct cdrom_device_info *cdi, int lock)
 {
 	uch command = (lock) ? c_lock_tray : c_unlock_tray;
 	type_0_command(command, 1);	/* wait and get dsb */
@@ -1248,8 +1235,8 @@
 /* Although a session start should be in LBA format, we return it in 
    MSF format because it is slightly easier, and the new generic ioctl
    will take care of the necessary conversion. */
-int cm206_get_last_session(struct cdrom_device_info *cdi,
-			   struct cdrom_multisession *mssp)
+static int cm206_get_last_session(struct cdrom_device_info *cdi,
+				  struct cdrom_multisession *mssp)
 {
 	if (!FIRST_TRACK)
 		get_disc_status();
@@ -1268,7 +1255,7 @@
 	return 0;
 }
 
-int cm206_get_upc(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
+static int cm206_get_upc(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
 {
 	uch upc[10];
 	char *ret = mcn->medium_catalog_number;
@@ -1287,7 +1274,7 @@
 	return 0;
 }
 
-int cm206_reset(struct cdrom_device_info *cdi)
+static int cm206_reset(struct cdrom_device_info *cdi)
 {
 	stop_read();
 	reset_cm260();
@@ -1300,7 +1287,7 @@
 	return 0;
 }
 
-int cm206_select_speed(struct cdrom_device_info *cdi, int speed)
+static int cm206_select_speed(struct cdrom_device_info *cdi, int speed)
 {
 	int r;
 	switch (speed) {
@@ -1392,7 +1379,7 @@
    request_region, 15 bits of one port and 6 of another make things
    likely enough to accept the region on the first hit...
  */
-int __init probe_base_port(int base)
+static int __init probe_base_port(int base)
 {
 	int b = 0x300, e = 0x370;	/* this is the range of start addresses */
 	volatile int fool, i;
@@ -1416,7 +1403,7 @@
 
 #if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
 /* Probe for irq# nr. If nr==0, probe for all possible irq's. */
-int __init probe_irq(int nr)
+static int __init probe_irq(int nr)
 {
 	int irqs, irq;
 	outw(dc_normal | READ_AHEAD, r_data_control);	/* disable irq-generation */
@@ -1558,7 +1545,7 @@
 	}
 }
 
-int __cm206_init(void)
+static int __cm206_init(void)
 {
 	parse_options();
 #if !defined(AUTO_PROBE_MODULE)
@@ -1567,7 +1554,7 @@
 	return cm206_init();
 }
 
-void __exit cm206_exit(void)
+static void __exit cm206_exit(void)
 {
 	del_gendisk(cm206_gendisk);
 	put_disk(cm206_gendisk);
diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
index f4be7bf..9f22e8f 100644
--- a/drivers/cdrom/sonycd535.c
+++ b/drivers/cdrom/sonycd535.c
@@ -1605,8 +1605,7 @@
 	put_disk(cdu_disk);
 out6:
 	for (i = 0; i < sony_buffer_sectors; i++)
-		if (sony_buffer[i]) 
-			kfree(sony_buffer[i]);
+		kfree(sony_buffer[i]);
 out5:
 	kfree(sony_buffer);
 out4:
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 5ed6515..43d0cb1 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -929,6 +929,10 @@
 
 	  If compiled as a module, it will be called scx200_gpio.
 
+config GPIO_VR41XX
+	tristate "NEC VR4100 series General-purpose I/O Unit support"
+	depends on CPU_VR41XX
+
 config RAW_DRIVER
 	tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)"
 	help
@@ -936,8 +940,8 @@
 	  Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O. 
 	  See the raw(8) manpage for more details.
 
-          The raw driver is deprecated and may be removed from 2.7
-          kernels.  Applications should simply open the device (eg /dev/hda1)
+          The raw driver is deprecated and will be removed soon.
+          Applications should simply open the device (eg /dev/hda1)
           with the O_DIRECT flag.
 
 config HPET
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index e3f5c32..1aff819 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -80,6 +80,7 @@
 obj-$(CONFIG_NWBUTTON) += nwbutton.o
 obj-$(CONFIG_NWFLASH) += nwflash.o
 obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
+obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
 obj-$(CONFIG_TANBAC_TB0219) += tb0219.o
 
 obj-$(CONFIG_WATCHDOG)	+= watchdog/
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index ad9c113..c1fe013 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -278,6 +278,8 @@
 #define AGP_GENERIC_SIZES_ENTRIES 11
 extern struct aper_size_info_16 agp3_generic_sizes[];
 
+#define virt_to_gart(x) (phys_to_gart(virt_to_phys(x)))
+#define gart_to_virt(x) (phys_to_virt(gart_to_phys(x)))
 
 extern int agp_off;
 extern int agp_try_unsupported_boot;
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
index 0212feb..9c9c9c2 100644
--- a/drivers/char/agp/ali-agp.c
+++ b/drivers/char/agp/ali-agp.c
@@ -150,7 +150,7 @@
 	pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
 	pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
 			(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
-			  virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN ));
+			  virt_to_gart(addr)) | ALI_CACHE_FLUSH_EN ));
 	return addr;
 }
 
@@ -174,7 +174,7 @@
 	pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
 	pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
 			(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
-			  virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN));
+			  virt_to_gart(addr)) | ALI_CACHE_FLUSH_EN));
 	agp_generic_destroy_page(addr);
 }
 
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index e62a3c2..3a41672 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -43,7 +43,7 @@
 
 	SetPageReserved(virt_to_page(page_map->real));
 	global_cache_flush();
-	page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
+	page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real),
 					    PAGE_SIZE);
 	if (page_map->remapped == NULL) {
 		ClearPageReserved(virt_to_page(page_map->real));
@@ -154,7 +154,7 @@
 
 	agp_bridge->gatt_table_real = (u32 *)page_dir.real;
 	agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped;
-	agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
+	agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
 
 	/* Get the address for the gart region.
 	 * This is a bus address even on the alpha, b/c its
@@ -167,7 +167,7 @@
 
 	/* Calculate the agp offset */
 	for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
-		writel(virt_to_phys(amd_irongate_private.gatt_pages[i]->real) | 1,
+		writel(virt_to_gart(amd_irongate_private.gatt_pages[i]->real) | 1,
 			page_dir.remapped+GET_PAGE_DIR_OFF(addr));
 		readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr));	/* PCI Posting. */
 	}
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 399c042..1407945 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -219,7 +219,7 @@
 
 static int amd_8151_configure(void)
 {
-	unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real);
+	unsigned long gatt_bus = virt_to_gart(agp_bridge->gatt_table_real);
 
 	/* Configure AGP regs in each x86-64 host bridge. */
 	for_each_nb() {
@@ -591,7 +591,7 @@
 {
 	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
 
-	release_mem_region(virt_to_phys(bridge->gatt_table_real),
+	release_mem_region(virt_to_gart(bridge->gatt_table_real),
 			   amd64_aperture_sizes[bridge->aperture_size_idx].size);
 	agp_remove_bridge(bridge);
 	agp_put_bridge(bridge);
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index a65f882..e572ced 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -61,7 +61,7 @@
 
 	SetPageReserved(virt_to_page(page_map->real));
 	err = map_page_into_agp(virt_to_page(page_map->real));
-	page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
+	page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real),
 					    PAGE_SIZE);
 	if (page_map->remapped == NULL || err) {
 		ClearPageReserved(virt_to_page(page_map->real));
@@ -343,7 +343,7 @@
 
 	agp_bridge->gatt_table_real = (u32 *)page_dir.real;
 	agp_bridge->gatt_table = (u32 __iomem *) page_dir.remapped;
-	agp_bridge->gatt_bus_addr = virt_to_bus(page_dir.real);
+	agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
 
 	/* Write out the size register */
 	current_size = A_SIZE_LVL2(agp_bridge->current_size);
@@ -373,7 +373,7 @@
 
 	/* Calculate the agp offset */
 	for(i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
-		writel(virt_to_bus(ati_generic_private.gatt_pages[i]->real) | 1,
+		writel(virt_to_gart(ati_generic_private.gatt_pages[i]->real) | 1,
 			page_dir.remapped+GET_PAGE_DIR_OFF(addr));
 		readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr));	/* PCI Posting. */
 	}
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index 2f3dfb6..4d4e602 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -148,7 +148,7 @@
 			return -ENOMEM;
 		}
 
-		bridge->scratch_page_real = virt_to_phys(addr);
+		bridge->scratch_page_real = virt_to_gart(addr);
 		bridge->scratch_page =
 		    bridge->driver->mask_memory(bridge, bridge->scratch_page_real, 0);
 	}
@@ -189,7 +189,7 @@
 err_out:
 	if (bridge->driver->needs_scratch_page)
 		bridge->driver->agp_destroy_page(
-				phys_to_virt(bridge->scratch_page_real));
+				gart_to_virt(bridge->scratch_page_real));
 	if (got_gatt)
 		bridge->driver->free_gatt_table(bridge);
 	if (got_keylist) {
@@ -214,7 +214,7 @@
 	if (bridge->driver->agp_destroy_page &&
 	    bridge->driver->needs_scratch_page)
 		bridge->driver->agp_destroy_page(
-				phys_to_virt(bridge->scratch_page_real));
+				gart_to_virt(bridge->scratch_page_real));
 }
 
 /* When we remove the global variable agp_bridge from all drivers
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
index 1383c31..ac19fdc 100644
--- a/drivers/char/agp/efficeon-agp.c
+++ b/drivers/char/agp/efficeon-agp.c
@@ -219,7 +219,7 @@
 
 		efficeon_private.l1_table[index] = page;
 
-		value = __pa(page) | pati | present | index;
+		value = virt_to_gart(page) | pati | present | index;
 
 		pci_write_config_dword(agp_bridge->dev,
 			EFFICEON_ATTPAGE, value);
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index c321a92..f0079e9 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -153,7 +153,7 @@
 	}
 	if (curr->page_count != 0) {
 		for (i = 0; i < curr->page_count; i++) {
-			curr->bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[i]));
+			curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i]));
 		}
 	}
 	agp_free_key(curr->key);
@@ -209,7 +209,7 @@
 			agp_free_memory(new);
 			return NULL;
 		}
-		new->memory[i] = virt_to_phys(addr);
+		new->memory[i] = virt_to_gart(addr);
 		new->page_count++;
 	}
        new->bridge = bridge;
@@ -295,19 +295,6 @@
 EXPORT_SYMBOL_GPL(agp_num_entries);
 
 
-static int check_bridge_mode(struct pci_dev *dev)
-{
-	u32 agp3;
-	u8 cap_ptr;
-
-	cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP);
-	pci_read_config_dword(dev, cap_ptr+AGPSTAT, &agp3);
-	if (agp3 & AGPSTAT_MODE_3_0)
-		return 1;
-	return 0;
-}
-
-
 /**
  *	agp_copy_info  -  copy bridge state information
  *
@@ -328,7 +315,7 @@
 	info->version.minor = bridge->version->minor;
 	info->chipset = SUPPORTED;
 	info->device = bridge->dev;
-	if (check_bridge_mode(bridge->dev))
+	if (bridge->mode & AGPSTAT_MODE_3_0)
 		info->mode = bridge->mode & ~AGP3_RESERVED_MASK;
 	else
 		info->mode = bridge->mode & ~AGP2_RESERVED_MASK;
@@ -661,7 +648,7 @@
 		bridge_agpstat &= ~AGPSTAT_FW;
 
 	/* Check to see if we are operating in 3.0 mode */
-	if (check_bridge_mode(agp_bridge->dev))
+	if (agp_bridge->mode & AGPSTAT_MODE_3_0)
 		agp_v3_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat);
 	else
 		agp_v2_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat);
@@ -732,7 +719,7 @@
 
 	/* Do AGP version specific frobbing. */
 	if (bridge->major_version >= 3) {
-		if (check_bridge_mode(bridge->dev)) {
+		if (bridge->mode & AGPSTAT_MODE_3_0) {
 			/* If we have 3.5, we can do the isoch stuff. */
 			if (bridge->minor_version >= 5)
 				agp_3_5_enable(bridge);
@@ -806,8 +793,7 @@
 				break;
 			}
 
-			table = (char *) __get_free_pages(GFP_KERNEL,
-							  page_order);
+			table = alloc_gatt_pages(page_order);
 
 			if (table == NULL) {
 				i++;
@@ -838,7 +824,7 @@
 		size = ((struct aper_size_info_fixed *) temp)->size;
 		page_order = ((struct aper_size_info_fixed *) temp)->page_order;
 		num_entries = ((struct aper_size_info_fixed *) temp)->num_entries;
-		table = (char *) __get_free_pages(GFP_KERNEL, page_order);
+		table = alloc_gatt_pages(page_order);
 	}
 
 	if (table == NULL)
@@ -853,7 +839,7 @@
 	agp_gatt_table = (void *)table;
 
 	bridge->driver->cache_flush();
-	bridge->gatt_table = ioremap_nocache(virt_to_phys(table),
+	bridge->gatt_table = ioremap_nocache(virt_to_gart(table),
 					(PAGE_SIZE * (1 << page_order)));
 	bridge->driver->cache_flush();
 
@@ -861,11 +847,11 @@
 		for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
 			ClearPageReserved(page);
 
-		free_pages((unsigned long) table, page_order);
+		free_gatt_pages(table, page_order);
 
 		return -ENOMEM;
 	}
-	bridge->gatt_bus_addr = virt_to_phys(bridge->gatt_table_real);
+	bridge->gatt_bus_addr = virt_to_gart(bridge->gatt_table_real);
 
 	/* AK: bogus, should encode addresses > 4GB */
 	for (i = 0; i < num_entries; i++) {
@@ -919,7 +905,7 @@
 	for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
 		ClearPageReserved(page);
 
-	free_pages((unsigned long) bridge->gatt_table_real, page_order);
+	free_gatt_pages(bridge->gatt_table_real, page_order);
 
 	agp_gatt_table = NULL;
 	bridge->gatt_table = NULL;
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
index 6052bfa..99762b6 100644
--- a/drivers/char/agp/hp-agp.c
+++ b/drivers/char/agp/hp-agp.c
@@ -110,7 +110,7 @@
 	hp->gart_size = HP_ZX1_GART_SIZE;
 	hp->gatt_entries = hp->gart_size / hp->io_page_size;
 
-	hp->io_pdir = phys_to_virt(readq(hp->ioc_regs+HP_ZX1_PDIR_BASE));
+	hp->io_pdir = gart_to_virt(readq(hp->ioc_regs+HP_ZX1_PDIR_BASE));
 	hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)];
 
 	if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) {
@@ -248,7 +248,7 @@
 	agp_bridge->mode = readl(hp->lba_regs+hp->lba_cap_offset+PCI_AGP_STATUS);
 
 	if (hp->io_pdir_owner) {
-		writel(virt_to_phys(hp->io_pdir), hp->ioc_regs+HP_ZX1_PDIR_BASE);
+		writel(virt_to_gart(hp->io_pdir), hp->ioc_regs+HP_ZX1_PDIR_BASE);
 		readl(hp->ioc_regs+HP_ZX1_PDIR_BASE);
 		writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG);
 		readl(hp->ioc_regs+HP_ZX1_TCNFG);
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
index adbea89..9494329 100644
--- a/drivers/char/agp/i460-agp.c
+++ b/drivers/char/agp/i460-agp.c
@@ -372,7 +372,7 @@
 	}
 	memset(lp->alloced_map, 0, map_size);
 
-	lp->paddr = virt_to_phys(lpage);
+	lp->paddr = virt_to_gart(lpage);
 	lp->refcount = 0;
 	atomic_add(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp);
 	return 0;
@@ -383,7 +383,7 @@
 	kfree(lp->alloced_map);
 	lp->alloced_map = NULL;
 
-	free_pages((unsigned long) phys_to_virt(lp->paddr), I460_IO_PAGE_SHIFT - PAGE_SHIFT);
+	free_pages((unsigned long) gart_to_virt(lp->paddr), I460_IO_PAGE_SHIFT - PAGE_SHIFT);
 	atomic_sub(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp);
 }
 
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 8c7d727..51266d6 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -286,7 +286,7 @@
 	if (new == NULL)
 		return NULL;
 
-	new->memory[0] = virt_to_phys(addr);
+	new->memory[0] = virt_to_gart(addr);
 	if (pg_count == 4) {
 		/* kludge to get 4 physical pages for ARGB cursor */
 		new->memory[1] = new->memory[0] + PAGE_SIZE;
@@ -329,10 +329,10 @@
 	agp_free_key(curr->key);
 	if(curr->type == AGP_PHYS_MEMORY) {
 		if (curr->page_count == 4)
-			i8xx_destroy_pages(phys_to_virt(curr->memory[0]));
+			i8xx_destroy_pages(gart_to_virt(curr->memory[0]));
 		else
 			agp_bridge->driver->agp_destroy_page(
-				 phys_to_virt(curr->memory[0]));
+				 gart_to_virt(curr->memory[0]));
 		vfree(curr->memory);
 	}
 	kfree(curr);
@@ -418,7 +418,8 @@
 		case I915_GMCH_GMS_STOLEN_48M:
 			/* Check it's really I915G */
 			if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
-			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB)
+			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
+			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB)
 				gtt_entries = MB(48) - KB(size);
 			else
 				gtt_entries = 0;
@@ -426,7 +427,8 @@
 		case I915_GMCH_GMS_STOLEN_64M:
 			/* Check it's really I915G */
 			if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
-			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB)
+			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
+			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB)
 				gtt_entries = MB(64) - KB(size);
 			else
 				gtt_entries = 0;
@@ -1662,6 +1664,14 @@
 		}
 		name = "915GM";
 		break;
+	case PCI_DEVICE_ID_INTEL_82945G_HB:
+		if (find_i830(PCI_DEVICE_ID_INTEL_82945G_IG)) {
+			bridge->driver = &intel_915_driver;
+		} else {
+			bridge->driver = &intel_845_driver;
+		}
+		name = "945G";
+		break;
 	case PCI_DEVICE_ID_INTEL_7505_0:
 		bridge->driver = &intel_7505_driver;
 		name = "E7505";
@@ -1801,6 +1811,7 @@
 	ID(PCI_DEVICE_ID_INTEL_7205_0),
 	ID(PCI_DEVICE_ID_INTEL_82915G_HB),
 	ID(PCI_DEVICE_ID_INTEL_82915GM_HB),
+	ID(PCI_DEVICE_ID_INTEL_82945G_HB),
 	{ }
 };
 
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c
index 4b3eda2..d3aa159 100644
--- a/drivers/char/agp/sgi-agp.c
+++ b/drivers/char/agp/sgi-agp.c
@@ -133,11 +133,14 @@
 	off_t j;
 	void *temp;
 	struct agp_bridge_data *bridge;
+	u64 *table;
 
 	bridge = mem->bridge;
 	if (!bridge)
 		return -EINVAL;
 
+	table = (u64 *)bridge->gatt_table;
+
 	temp = bridge->current_size;
 
 	switch (bridge->driver->size_type) {
@@ -175,7 +178,7 @@
 	j = pg_start;
 
 	while (j < (pg_start + mem->page_count)) {
-		if (*(bridge->gatt_table + j))
+		if (table[j])
 			return -EBUSY;
 		j++;
 	}
@@ -186,7 +189,7 @@
 	}
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-		*(bridge->gatt_table + j) =
+		table[j] =
 		    bridge->driver->mask_memory(bridge, mem->memory[i],
 						mem->type);
 	}
@@ -200,6 +203,7 @@
 {
 	size_t i;
 	struct agp_bridge_data *bridge;
+	u64 *table;
 
 	bridge = mem->bridge;
 	if (!bridge)
@@ -209,8 +213,10 @@
 		return -EINVAL;
 	}
 
+	table = (u64 *)bridge->gatt_table;
+
 	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
-		*(bridge->gatt_table + i) = 0;
+		table[i] = 0;
 	}
 
 	bridge->driver->tlb_flush(mem);
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index 10c2330..a9fb12c 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -51,7 +51,7 @@
 	}
 	SetPageReserved(virt_to_page(page_map->real));
 	global_cache_flush();
-	page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), 
+	page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real),
 					    PAGE_SIZE);
 	if (page_map->remapped == NULL) {
 		ClearPageReserved(virt_to_page(page_map->real));
@@ -162,7 +162,7 @@
 	/* Create a fake scratch directory */
 	for(i = 0; i < 1024; i++) {
 		writel(agp_bridge->scratch_page, serverworks_private.scratch_dir.remapped+i);
-		writel(virt_to_phys(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i);
+		writel(virt_to_gart(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i);
 	}
 
 	retval = serverworks_create_gatt_pages(value->num_entries / 1024);
@@ -174,7 +174,7 @@
 
 	agp_bridge->gatt_table_real = (u32 *)page_dir.real;
 	agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped;
-	agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
+	agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
 
 	/* Get the address for the gart region.
 	 * This is a bus address even on the alpha, b/c its
@@ -187,7 +187,7 @@
 	/* Calculate the agp offset */	
 
 	for(i = 0; i < value->num_entries / 1024; i++)
-		writel(virt_to_phys(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i);
+		writel(virt_to_gart(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i);
 
 	return 0;
 }
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
index a673971..c825531 100644
--- a/drivers/char/agp/uninorth-agp.c
+++ b/drivers/char/agp/uninorth-agp.c
@@ -407,7 +407,7 @@
 
 	bridge->gatt_table_real = (u32 *) table;
 	bridge->gatt_table = (u32 *)table;
-	bridge->gatt_bus_addr = virt_to_phys(table);
+	bridge->gatt_bus_addr = virt_to_gart(table);
 
 	for (i = 0; i < num_entries; i++)
 		bridge->gatt_table[i] = 0;
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 1dc4259..2a36561 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -861,13 +861,18 @@
 
 static void rs_put_char(struct tty_struct *tty, unsigned char ch)
 {
-	struct async_struct *info = (struct async_struct *)tty->driver_data;
+	struct async_struct *info;
 	unsigned long flags;
 
+	if (!tty)
+		return;
+
+	info = tty->driver_data;
+
 	if (serial_paranoia_check(info, tty->name, "rs_put_char"))
 		return;
 
-	if (!tty || !info->xmit.buf)
+	if (!info->xmit.buf)
 		return;
 
 	local_irq_save(flags);
@@ -910,13 +915,18 @@
 static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count)
 {
 	int	c, ret = 0;
-	struct async_struct *info = (struct async_struct *)tty->driver_data;
+	struct async_struct *info;
 	unsigned long flags;
 
+	if (!tty)
+		return 0;
+
+	info = tty->driver_data;
+
 	if (serial_paranoia_check(info, tty->name, "rs_write"))
 		return 0;
 
-	if (!tty || !info->xmit.buf || !tmp_buf)
+	if (!info->xmit.buf || !tmp_buf)
 		return 0;
 
 	local_save_flags(flags);
@@ -1963,10 +1973,6 @@
 }
 
 
-int register_serial(struct serial_struct *req);
-void unregister_serial(int line);
-
-
 static struct tty_operations serial_ops = {
 	.open = rs_open,
 	.close = rs_close,
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index 6bf2e27..11f9ee5 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -599,7 +599,7 @@
 
 #ifdef DEBUG
 		if (loopcount++ > 2) {
-			printk("Looping in ac_read. loopcount %d\n", loopcount);
+			printk(KERN_DEBUG "Looping in ac_read. loopcount %d\n", loopcount);
 		}
 #endif
 	} 
diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig
index d9a0299..c2b12ea 100644
--- a/drivers/char/drm/Kconfig
+++ b/drivers/char/drm/Kconfig
@@ -6,7 +6,7 @@
 #
 config DRM
 	tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
-	depends on AGP || AGP=n
+	depends on (AGP || AGP=n) && PCI
 	help
 	  Kernel-level support for the Direct Rendering Infrastructure (DRI)
 	  introduced in XFree86 4.0. If you say Y here, you need to select
diff --git a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile
index 23ab263..7444dec 100644
--- a/drivers/char/drm/Makefile
+++ b/drivers/char/drm/Makefile
@@ -19,6 +19,11 @@
 ffb-objs    := ffb_drv.o ffb_context.o
 sis-objs    := sis_drv.o sis_ds.o sis_mm.o
 
+ifeq ($(CONFIG_COMPAT),y)
+drm-objs    += drm_ioc32.o
+radeon-objs += radeon_ioc32.o
+endif
+
 obj-$(CONFIG_DRM)	+= drm.o
 obj-$(CONFIG_DRM_GAMMA) += gamma.o
 obj-$(CONFIG_DRM_TDFX)	+= tdfx.o
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 21f4c54..b04ddf1 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -316,6 +316,9 @@
 typedef int drm_ioctl_t( struct inode *inode, struct file *filp,
 			 unsigned int cmd, unsigned long arg );
 
+typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
+			       unsigned long arg);
+
 typedef struct drm_ioctl_desc {
 	drm_ioctl_t	     *func;
 	int		     auth_needed;
@@ -775,6 +778,8 @@
 				  unsigned int cmd, unsigned long arg);
 extern int           drm_ioctl(struct inode *inode, struct file *filp,
 				unsigned int cmd, unsigned long arg);
+extern long	     drm_compat_ioctl(struct file *filp,
+				unsigned int cmd, unsigned long arg);
 extern int           drm_takedown(drm_device_t * dev);
 
 				/* Device support (drm_fops.h) */
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index 4113bcb..3407380 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -60,6 +60,15 @@
 }
 EXPORT_SYMBOL(drm_order);
 
+#ifdef CONFIG_COMPAT
+/*
+ * Used to allocate 32-bit handles for _DRM_SHM regions
+ * The 0x10000000 value is chosen to be out of the way of
+ * FB/register and GART physical addresses.
+ */
+static unsigned int map32_handle = 0x10000000;
+#endif
+
 /**
  * Ioctl to specify a range of memory that is available for mapping by a non-root process.
  *
@@ -187,16 +196,18 @@
 
 	down(&dev->struct_sem);
 	list_add(&list->head, &dev->maplist->head);
+#ifdef CONFIG_COMPAT
+	/* Assign a 32-bit handle for _DRM_SHM mappings */
+	/* We do it here so that dev->struct_sem protects the increment */
+	if (map->type == _DRM_SHM)
+		map->offset = map32_handle += PAGE_SIZE;
+#endif
  	up(&dev->struct_sem);
 
 	if ( copy_to_user( argp, map, sizeof(*map) ) )
 		return -EFAULT;
-	if ( map->type != _DRM_SHM ) {
-		if ( copy_to_user( &argp->handle,
-				   &map->offset,
-				   sizeof(map->offset) ) )
-			return -EFAULT;
-	}
+	if (copy_to_user(&argp->handle, &map->offset, sizeof(map->offset)))
+		return -EFAULT;
 	return 0;
 }
 
@@ -240,7 +251,7 @@
 		r_list = list_entry(list, drm_map_list_t, head);
 
 		if(r_list->map &&
-		   r_list->map->handle == request.handle &&
+		   r_list->map->offset == (unsigned long) request.handle &&
 		   r_list->map->flags & _DRM_REMOVABLE) break;
 	}
 
diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c
index f15c86c..fdf661f 100644
--- a/drivers/char/drm/drm_context.c
+++ b/drivers/char/drm/drm_context.c
@@ -225,7 +225,7 @@
 	map = dev->context_sareas[request.ctx_id];
 	up(&dev->struct_sem);
 
-	request.handle = map->handle;
+	request.handle = (void *) map->offset;
 	if (copy_to_user(argp, &request, sizeof(request)))
 		return -EFAULT;
 	return 0;
@@ -261,8 +261,8 @@
 	down(&dev->struct_sem);
 	list_for_each(list, &dev->maplist->head) {
 		r_list = list_entry(list, drm_map_list_t, head);
-		if(r_list->map &&
-		   r_list->map->handle == request.handle)
+		if (r_list->map
+		    && r_list->map->offset == (unsigned long) request.handle)
 			goto found;
 	}
 bad:
diff --git a/drivers/char/drm/drm_ioc32.c b/drivers/char/drm/drm_ioc32.c
new file mode 100644
index 0000000..8087a96
--- /dev/null
+++ b/drivers/char/drm/drm_ioc32.c
@@ -0,0 +1,1069 @@
+/**
+ * \file drm_ioc32.c
+ *
+ * 32-bit ioctl compatibility routines for the DRM.
+ *
+ * \author Paul Mackerras <paulus@samba.org>
+ *
+ * Copyright (C) Paul Mackerras 2005.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * 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 AUTHOR 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 <linux/compat.h>
+#include <linux/ioctl32.h>
+
+#include "drmP.h"
+#include "drm_core.h"
+
+#define DRM_IOCTL_VERSION32		DRM_IOWR(0x00, drm_version32_t)
+#define DRM_IOCTL_GET_UNIQUE32		DRM_IOWR(0x01, drm_unique32_t)
+#define DRM_IOCTL_GET_MAP32		DRM_IOWR(0x04, drm_map32_t)
+#define DRM_IOCTL_GET_CLIENT32		DRM_IOWR(0x05, drm_client32_t)
+#define DRM_IOCTL_GET_STATS32		DRM_IOR( 0x06, drm_stats32_t)
+
+#define DRM_IOCTL_SET_UNIQUE32		DRM_IOW( 0x10, drm_unique32_t)
+#define DRM_IOCTL_ADD_MAP32		DRM_IOWR(0x15, drm_map32_t)
+#define DRM_IOCTL_ADD_BUFS32		DRM_IOWR(0x16, drm_buf_desc32_t)
+#define DRM_IOCTL_MARK_BUFS32		DRM_IOW( 0x17, drm_buf_desc32_t)
+#define DRM_IOCTL_INFO_BUFS32		DRM_IOWR(0x18, drm_buf_info32_t)
+#define DRM_IOCTL_MAP_BUFS32		DRM_IOWR(0x19, drm_buf_map32_t)
+#define DRM_IOCTL_FREE_BUFS32		DRM_IOW( 0x1a, drm_buf_free32_t)
+
+#define DRM_IOCTL_RM_MAP32		DRM_IOW( 0x1b, drm_map32_t)
+
+#define DRM_IOCTL_SET_SAREA_CTX32	DRM_IOW( 0x1c, drm_ctx_priv_map32_t)
+#define DRM_IOCTL_GET_SAREA_CTX32	DRM_IOWR(0x1d, drm_ctx_priv_map32_t)
+
+#define DRM_IOCTL_RES_CTX32		DRM_IOWR(0x26, drm_ctx_res32_t)
+#define DRM_IOCTL_DMA32			DRM_IOWR(0x29, drm_dma32_t)
+
+#define DRM_IOCTL_AGP_ENABLE32		DRM_IOW( 0x32, drm_agp_mode32_t)
+#define DRM_IOCTL_AGP_INFO32		DRM_IOR( 0x33, drm_agp_info32_t)
+#define DRM_IOCTL_AGP_ALLOC32		DRM_IOWR(0x34, drm_agp_buffer32_t)
+#define DRM_IOCTL_AGP_FREE32		DRM_IOW( 0x35, drm_agp_buffer32_t)
+#define DRM_IOCTL_AGP_BIND32		DRM_IOW( 0x36, drm_agp_binding32_t)
+#define DRM_IOCTL_AGP_UNBIND32		DRM_IOW( 0x37, drm_agp_binding32_t)
+
+#define DRM_IOCTL_SG_ALLOC32		DRM_IOW( 0x38, drm_scatter_gather32_t)
+#define DRM_IOCTL_SG_FREE32		DRM_IOW( 0x39, drm_scatter_gather32_t)
+
+#define DRM_IOCTL_WAIT_VBLANK32		DRM_IOWR(0x3a, drm_wait_vblank32_t)
+
+typedef struct drm_version_32 {
+	int	version_major;	  /**< Major version */
+	int	version_minor;	  /**< Minor version */
+	int	version_patchlevel;/**< Patch level */
+	u32	name_len;	  /**< Length of name buffer */
+	u32	name;		  /**< Name of driver */
+	u32	date_len;	  /**< Length of date buffer */
+	u32	date;		  /**< User-space buffer to hold date */
+	u32	desc_len;	  /**< Length of desc buffer */
+	u32	desc;		  /**< User-space buffer to hold desc */
+} drm_version32_t;
+
+static int compat_drm_version(struct file *file, unsigned int cmd,
+			      unsigned long arg)
+{
+	drm_version32_t v32;
+	drm_version_t __user *version;
+	int err;
+
+	if (copy_from_user(&v32, (void __user *) arg, sizeof(v32)))
+		return -EFAULT;
+
+	version = compat_alloc_user_space(sizeof(*version));
+	if (!access_ok(VERIFY_WRITE, version, sizeof(*version)))
+		return -EFAULT;
+	if (__put_user(v32.name_len, &version->name_len)
+	    || __put_user((void __user *)(unsigned long)v32.name,
+			  &version->name)
+	    || __put_user(v32.date_len, &version->date_len)
+	    || __put_user((void __user *)(unsigned long)v32.date,
+			  &version->date)
+	    || __put_user(v32.desc_len, &version->desc_len)
+	    || __put_user((void __user *)(unsigned long)v32.desc,
+			  &version->desc))
+		return -EFAULT;
+
+	err = drm_ioctl(file->f_dentry->d_inode, file,
+			DRM_IOCTL_VERSION, (unsigned long) version);
+	if (err)
+		return err;
+
+	if (__get_user(v32.version_major, &version->version_major)
+	    || __get_user(v32.version_minor, &version->version_minor)
+	    || __get_user(v32.version_patchlevel, &version->version_patchlevel)
+	    || __get_user(v32.name_len, &version->name_len)
+	    || __get_user(v32.date_len, &version->date_len)
+	    || __get_user(v32.desc_len, &version->desc_len))
+		return -EFAULT;
+
+	if (copy_to_user((void __user *) arg, &v32, sizeof(v32)))
+		return -EFAULT;
+	return 0;
+}
+
+typedef struct drm_unique32 {
+	u32 unique_len;	/**< Length of unique */
+	u32 unique;	/**< Unique name for driver instantiation */
+} drm_unique32_t;
+
+static int compat_drm_getunique(struct file *file, unsigned int cmd,
+				unsigned long arg)
+{
+	drm_unique32_t uq32;
+	drm_unique_t __user *u;
+	int err;
+
+	if (copy_from_user(&uq32, (void __user *) arg, sizeof(uq32)))
+		return -EFAULT;
+
+	u = compat_alloc_user_space(sizeof(*u));
+	if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
+		return -EFAULT;
+	if (__put_user(uq32.unique_len, &u->unique_len)
+	    || __put_user((void __user *)(unsigned long) uq32.unique,
+			  &u->unique))
+		return -EFAULT;
+
+	err = drm_ioctl(file->f_dentry->d_inode, file,
+			DRM_IOCTL_GET_UNIQUE, (unsigned long) u);
+	if (err)
+		return err;
+
+	if (__get_user(uq32.unique_len, &u->unique_len))
+		return -EFAULT;
+	if (copy_to_user((void __user *) arg, &uq32, sizeof(uq32)))
+		return -EFAULT;
+	return 0;
+}
+
+static int compat_drm_setunique(struct file *file, unsigned int cmd,
+				unsigned long arg)
+{
+	drm_unique32_t uq32;
+	drm_unique_t __user *u;
+
+	if (copy_from_user(&uq32, (void __user *) arg, sizeof(uq32)))
+		return -EFAULT;
+
+	u = compat_alloc_user_space(sizeof(*u));
+	if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
+		return -EFAULT;
+	if (__put_user(uq32.unique_len, &u->unique_len)
+	    || __put_user((void __user *)(unsigned long) uq32.unique,
+			  &u->unique))
+		return -EFAULT;
+
+	return drm_ioctl(file->f_dentry->d_inode, file,
+			 DRM_IOCTL_SET_UNIQUE, (unsigned long) u);
+}
+
+typedef struct drm_map32 {
+	u32	offset;	 	/**< Requested physical address (0 for SAREA)*/
+	u32	size;	 	/**< Requested physical size (bytes) */
+	drm_map_type_t	type;	/**< Type of memory to map */
+	drm_map_flags_t flags;	/**< Flags */
+	u32	handle;		/**< User-space: "Handle" to pass to mmap() */
+	int	mtrr;		/**< MTRR slot used */
+} drm_map32_t;
+
+static int compat_drm_getmap(struct file *file, unsigned int cmd,
+			     unsigned long arg)
+{
+	drm_map32_t __user *argp = (void __user *)arg;
+	drm_map32_t m32;
+	drm_map_t __user *map;
+	int idx, err;
+	void *handle;
+
+	if (get_user(idx, &argp->offset))
+		return -EFAULT;
+
+	map = compat_alloc_user_space(sizeof(*map));
+	if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
+		return -EFAULT;
+	if (__put_user(idx, &map->offset))
+		return -EFAULT;
+
+	err = drm_ioctl(file->f_dentry->d_inode, file,
+			DRM_IOCTL_GET_MAP, (unsigned long) map);
+	if (err)
+		return err;
+
+	if (__get_user(m32.offset, &map->offset)
+	    || __get_user(m32.size, &map->size)
+	    || __get_user(m32.type, &map->type)
+	    || __get_user(m32.flags, &map->flags)
+	    || __get_user(handle, &map->handle)
+	    || __get_user(m32.mtrr, &map->mtrr))
+		return -EFAULT;
+
+	m32.handle = (unsigned long) handle;
+	if (copy_to_user(argp, &m32, sizeof(m32)))
+		return -EFAULT;
+	return 0;
+
+}
+
+static int compat_drm_addmap(struct file *file, unsigned int cmd,
+			     unsigned long arg)
+{
+	drm_map32_t __user *argp = (void __user *)arg;
+	drm_map32_t m32;
+	drm_map_t __user *map;
+	int err;
+	void *handle;
+
+	if (copy_from_user(&m32, argp, sizeof(m32)))
+		return -EFAULT;
+
+	map = compat_alloc_user_space(sizeof(*map));
+	if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
+		return -EFAULT;
+	if (__put_user(m32.offset, &map->offset)
+	    || __put_user(m32.size, &map->size)
+	    || __put_user(m32.type, &map->type)
+	    || __put_user(m32.flags, &map->flags))
+		return -EFAULT;
+
+	err = drm_ioctl(file->f_dentry->d_inode, file,
+			DRM_IOCTL_ADD_MAP, (unsigned long) map);
+	if (err)
+		return err;
+
+	if (__get_user(m32.offset, &map->offset)
+	    || __get_user(m32.mtrr, &map->mtrr)
+	    || __get_user(handle, &map->handle))
+		return -EFAULT;
+
+	m32.handle = (unsigned long) handle;
+	if (m32.handle != (unsigned long) handle && printk_ratelimit())
+		printk(KERN_ERR "compat_drm_addmap truncated handle"
+		       " %p for type %d offset %x\n",
+		       handle, m32.type, m32.offset);
+
+	if (copy_to_user(argp, &m32, sizeof(m32)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int compat_drm_rmmap(struct file *file, unsigned int cmd,
+			    unsigned long arg)
+{
+	drm_map32_t __user *argp = (void __user *)arg;
+	drm_map_t __user *map;
+	u32 handle;
+
+	if (get_user(handle, &argp->handle))
+		return -EFAULT;
+
+	map = compat_alloc_user_space(sizeof(*map));
+	if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
+		return -EFAULT;
+	if (__put_user((void *)(unsigned long) handle, &map->handle))
+		return -EFAULT;
+
+	return drm_ioctl(file->f_dentry->d_inode, file,
+			 DRM_IOCTL_RM_MAP, (unsigned long) map);
+}
+
+typedef struct drm_client32 {
+	int	idx;	/**< Which client desired? */
+	int	auth;	/**< Is client authenticated? */
+	u32	pid;	/**< Process ID */
+	u32	uid;	/**< User ID */
+	u32	magic;	/**< Magic */
+	u32	iocs;	/**< Ioctl count */
+} drm_client32_t;
+
+static int compat_drm_getclient(struct file *file, unsigned int cmd,
+				unsigned long arg)
+{
+	drm_client32_t c32;
+	drm_client32_t __user *argp = (void __user *)arg;
+	drm_client_t __user *client;
+	int idx, err;
+
+	if (get_user(idx, &argp->idx))
+		return -EFAULT;
+
+	client = compat_alloc_user_space(sizeof(*client));
+	if (!access_ok(VERIFY_WRITE, client, sizeof(*client)))
+		return -EFAULT;
+	if (__put_user(idx, &client->idx))
+		return -EFAULT;
+
+	err = drm_ioctl(file->f_dentry->d_inode, file,
+			DRM_IOCTL_GET_CLIENT, (unsigned long) client);
+	if (err)
+		return err;
+
+	if (__get_user(c32.auth, &client->auth)
+	    || __get_user(c32.pid, &client->pid)
+	    || __get_user(c32.uid, &client->uid)
+	    || __get_user(c32.magic, &client->magic)
+	    || __get_user(c32.iocs, &client->iocs))
+		return -EFAULT;
+
+	if (copy_to_user(argp, &c32, sizeof(c32)))
+		return -EFAULT;
+	return 0;
+}
+
+typedef struct drm_stats32 {
+	u32 count;
+	struct {
+		u32 value;
+		drm_stat_type_t type;
+	} data[15];
+} drm_stats32_t;
+
+static int compat_drm_getstats(struct file *file, unsigned int cmd,
+			       unsigned long arg)
+{
+	drm_stats32_t s32;
+	drm_stats32_t __user *argp = (void __user *)arg;
+	drm_stats_t __user *stats;
+	int i, err;
+
+	stats = compat_alloc_user_space(sizeof(*stats));
+	if (!access_ok(VERIFY_WRITE, stats, sizeof(*stats)))
+		return -EFAULT;
+
+	err = drm_ioctl(file->f_dentry->d_inode, file,
+			DRM_IOCTL_GET_STATS, (unsigned long) stats);
+	if (err)
+		return err;
+
+	if (__get_user(s32.count, &stats->count))
+		return -EFAULT;
+	for (i = 0; i < 15; ++i)
+		if (__get_user(s32.data[i].value, &stats->data[i].value)
+		    || __get_user(s32.data[i].type, &stats->data[i].type))
+			return -EFAULT;
+
+	if (copy_to_user(argp, &s32, sizeof(s32)))
+		return -EFAULT;
+	return 0;
+}
+
+typedef struct drm_buf_desc32 {
+	int	      count;	 /**< Number of buffers of this size */
+	int	      size;	 /**< Size in bytes */
+	int	      low_mark;	 /**< Low water mark */
+	int	      high_mark; /**< High water mark */
+	int	      flags;
+	u32	      agp_start; /**< Start address in the AGP aperture */
+} drm_buf_desc32_t;
+
+static int compat_drm_addbufs(struct file *file, unsigned int cmd,
+			      unsigned long arg)
+{
+	drm_buf_desc32_t __user *argp = (void __user *)arg;
+	drm_buf_desc_t __user *buf;
+	int err;
+	unsigned long agp_start;
+
+	buf = compat_alloc_user_space(sizeof(*buf));
+	if (!access_ok(VERIFY_WRITE, buf, sizeof(*buf))
+	    || !access_ok(VERIFY_WRITE, argp, sizeof(*argp)))
+		return -EFAULT;
+
+	if (__copy_in_user(buf, argp, offsetof(drm_buf_desc32_t, agp_start))
+	    || __get_user(agp_start, &argp->agp_start)
+	    || __put_user(agp_start, &buf->agp_start))
+		return -EFAULT;
+
+	err = drm_ioctl(file->f_dentry->d_inode, file,
+			DRM_IOCTL_ADD_BUFS, (unsigned long) buf);
+	if (err)
+		return err;
+
+	if (__copy_in_user(argp, buf, offsetof(drm_buf_desc32_t, agp_start))
+	    || __get_user(agp_start, &buf->agp_start)
+	    || __put_user(agp_start, &argp->agp_start))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int compat_drm_markbufs(struct file *file, unsigned int cmd,
+			       unsigned long arg)
+{
+	drm_buf_desc32_t b32;
+	drm_buf_desc32_t __user *argp = (void __user *)arg;
+	drm_buf_desc_t __user *buf;
+
+	if (copy_from_user(&b32, argp, sizeof(b32)))
+		return -EFAULT;
+
+	buf = compat_alloc_user_space(sizeof(*buf));
+	if (!access_ok(VERIFY_WRITE, buf, sizeof(*buf)))
+		return -EFAULT;
+
+	if (__put_user(b32.size, &buf->size)
+	    || __put_user(b32.low_mark, &buf->low_mark)
+	    || __put_user(b32.high_mark, &buf->high_mark))
+		return -EFAULT;
+
+	return drm_ioctl(file->f_dentry->d_inode, file,
+			 DRM_IOCTL_MARK_BUFS, (unsigned long) buf);
+}
+
+typedef struct drm_buf_info32 {
+	int	       count;	/**< Entries in list */
+	u32	       list;
+} drm_buf_info32_t;
+
+static int compat_drm_infobufs(struct file *file, unsigned int cmd,
+			       unsigned long arg)
+{
+	drm_buf_info32_t req32;
+	drm_buf_info32_t __user *argp = (void __user *)arg;
+	drm_buf_desc32_t __user *to;
+	drm_buf_info_t __user *request;
+	drm_buf_desc_t __user *list;
+	size_t nbytes;
+	int i, err;
+	int count, actual;
+
+	if (copy_from_user(&req32, argp, sizeof(req32)))
+		return -EFAULT;
+
+	count = req32.count;
+	to = (drm_buf_desc32_t __user *)(unsigned long) req32.list;
+	if (count < 0)
+		count = 0;
+	if (count > 0
+	    && !access_ok(VERIFY_WRITE, to, count * sizeof(drm_buf_desc32_t)))
+		return -EFAULT;
+
+	nbytes = sizeof(*request) + count * sizeof(drm_buf_desc_t);
+	request = compat_alloc_user_space(nbytes);
+	if (!access_ok(VERIFY_WRITE, request, nbytes))
+		return -EFAULT;
+	list = (drm_buf_desc_t *) (request + 1);
+
+	if (__put_user(count, &request->count)
+	    || __put_user(list, &request->list))
+		return -EFAULT;
+
+	err = drm_ioctl(file->f_dentry->d_inode, file,
+			DRM_IOCTL_INFO_BUFS, (unsigned long) request);
+	if (err)
+		return err;
+
+	if (__get_user(actual, &request->count))
+		return -EFAULT;
+	if (count >= actual)
+		for (i = 0; i < actual; ++i)
+			if (__copy_in_user(&to[i], &list[i],
+					   offsetof(drm_buf_desc_t, flags)))
+				return -EFAULT;
+
+	if (__put_user(actual, &argp->count))
+		return -EFAULT;
+
+	return 0;
+}
+
+typedef struct drm_buf_pub32 {
+	int	idx;		/**< Index into the master buffer list */
+	int	total;		/**< Buffer size */
+	int	used;		/**< Amount of buffer in use (for DMA) */
+	u32	address;	/**< Address of buffer */
+} drm_buf_pub32_t;
+
+typedef struct drm_buf_map32 {
+	int	count;		/**< Length of the buffer list */
+	u32	virtual;	/**< Mmap'd area in user-virtual */
+	u32	list;		/**< Buffer information */
+} drm_buf_map32_t;
+
+static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
+			      unsigned long arg)
+{
+	drm_buf_map32_t __user *argp = (void __user *)arg;
+	drm_buf_map32_t req32;
+	drm_buf_pub32_t __user *list32;
+	drm_buf_map_t __user *request;
+	drm_buf_pub_t __user *list;
+	int i, err;
+	int count, actual;
+	size_t nbytes;
+	void __user *addr;
+
+	if (copy_from_user(&req32, argp, sizeof(req32)))
+		return -EFAULT;
+	count = req32.count;
+	list32 = (void __user *)(unsigned long)req32.list;
+
+	if (count < 0)
+		return -EINVAL;
+	nbytes = sizeof(*request) + count * sizeof(drm_buf_pub_t);
+	request = compat_alloc_user_space(nbytes);
+	if (!access_ok(VERIFY_WRITE, request, nbytes))
+		return -EFAULT;
+	list = (drm_buf_pub_t *) (request + 1);
+
+	if (__put_user(count, &request->count)
+	    || __put_user(list, &request->list))
+		return -EFAULT;
+
+	err = drm_ioctl(file->f_dentry->d_inode, file,
+			DRM_IOCTL_MAP_BUFS, (unsigned long) request);
+	if (err)
+		return err;
+
+	if (__get_user(actual, &request->count))
+		return -EFAULT;
+	if (count >= actual)
+		for (i = 0; i < actual; ++i)
+			if (__copy_in_user(&list32[i], &list[i],
+					   offsetof(drm_buf_pub_t, address))
+			    || __get_user(addr, &list[i].address)
+			    || __put_user((unsigned long) addr,
+					  &list32[i].address))
+				return -EFAULT;
+
+	if (__put_user(actual, &argp->count)
+	    || __get_user(addr, &request->virtual)
+	    || __put_user((unsigned long) addr, &argp->virtual))
+		return -EFAULT;
+
+	return 0;
+}
+
+typedef struct drm_buf_free32 {
+	int	count;
+	u32	list;
+} drm_buf_free32_t;
+
+static int compat_drm_freebufs(struct file *file, unsigned int cmd,
+			       unsigned long arg)
+{
+	drm_buf_free32_t req32;
+	drm_buf_free_t __user *request;
+	drm_buf_free32_t __user *argp = (void __user *)arg;
+
+	if (copy_from_user(&req32, argp, sizeof(req32)))
+		return -EFAULT;
+
+	request = compat_alloc_user_space(sizeof(*request));
+	if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
+		return -EFAULT;
+	if (__put_user(req32.count, &request->count)
+	    || __put_user((int __user *)(unsigned long) req32.list,
+			  &request->list))
+		return -EFAULT;
+
+	return drm_ioctl(file->f_dentry->d_inode, file,
+			 DRM_IOCTL_FREE_BUFS, (unsigned long) request);
+}
+
+typedef struct drm_ctx_priv_map32 {
+	unsigned int	ctx_id;  /**< Context requesting private mapping */
+	u32		handle; /**< Handle of map */
+} drm_ctx_priv_map32_t;
+
+static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
+				  unsigned long arg)
+{
+	drm_ctx_priv_map32_t req32;
+	drm_ctx_priv_map_t __user *request;
+	drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
+
+	if (copy_from_user(&req32, argp, sizeof(req32)))
+		return -EFAULT;
+
+	request = compat_alloc_user_space(sizeof(*request));
+	if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
+		return -EFAULT;
+	if (__put_user(req32.ctx_id, &request->ctx_id)
+	    || __put_user((void *)(unsigned long) req32.handle,
+			  &request->handle))
+		return -EFAULT;
+
+	return drm_ioctl(file->f_dentry->d_inode, file,
+			 DRM_IOCTL_SET_SAREA_CTX, (unsigned long) request);
+}
+
+static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
+				  unsigned long arg)
+{
+	drm_ctx_priv_map_t __user *request;
+	drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
+	int err;
+	unsigned int ctx_id;
+	void *handle;
+
+	if (!access_ok(VERIFY_WRITE, argp, sizeof(*argp))
+	    || __get_user(ctx_id, &argp->ctx_id))
+		return -EFAULT;
+
+	request = compat_alloc_user_space(sizeof(*request));
+	if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
+		return -EFAULT;
+	if (__put_user(ctx_id, &request->ctx_id))
+		return -EFAULT;
+
+	err = drm_ioctl(file->f_dentry->d_inode, file,
+			DRM_IOCTL_GET_SAREA_CTX, (unsigned long) request);
+	if (err)
+		return err;
+
+	if (__get_user(handle, &request->handle)
+	    || __put_user((unsigned long) handle, &argp->handle))
+		return -EFAULT;
+
+	return 0;
+}
+
+typedef struct drm_ctx_res32 {
+	int	count;
+	u32	contexts;
+} drm_ctx_res32_t;
+
+static int compat_drm_resctx(struct file *file, unsigned int cmd,
+			     unsigned long arg)
+{
+	drm_ctx_res32_t __user *argp = (void __user *)arg;
+	drm_ctx_res32_t res32;
+	drm_ctx_res_t __user *res;
+	int err;
+
+	if (copy_from_user(&res32, argp, sizeof(res32)))
+		return -EFAULT;
+
+	res = compat_alloc_user_space(sizeof(*res));
+	if (!access_ok(VERIFY_WRITE, res, sizeof(*res)))
+		return -EFAULT;
+	if (__put_user(res32.count, &res->count)
+	    || __put_user((drm_ctx_t __user *)(unsigned long) res32.contexts,
+			  &res->contexts))
+		return -EFAULT;
+
+	err = drm_ioctl(file->f_dentry->d_inode, file,
+			DRM_IOCTL_RES_CTX, (unsigned long) res);
+	if (err)
+		return err;
+
+	if (__get_user(res32.count, &res->count)
+	    || __put_user(res32.count, &argp->count))
+		return -EFAULT;
+
+	return 0;
+}
+
+typedef struct drm_dma32 {
+	int	context;	  /**< Context handle */
+	int	send_count;	  /**< Number of buffers to send */
+	u32	send_indices;	  /**< List of handles to buffers */
+	u32	send_sizes;	  /**< Lengths of data to send */
+	drm_dma_flags_t flags;		  /**< Flags */
+	int	request_count;	  /**< Number of buffers requested */
+	int	request_size;	  /**< Desired size for buffers */
+	u32	request_indices;  /**< Buffer information */
+	u32	request_sizes;
+	int	granted_count;	  /**< Number of buffers granted */
+} drm_dma32_t;
+
+static int compat_drm_dma(struct file *file, unsigned int cmd,
+			  unsigned long arg)
+{
+	drm_dma32_t d32;
+	drm_dma32_t __user *argp = (void __user *) arg;
+	drm_dma_t __user *d;
+	int err;
+
+	if (copy_from_user(&d32, argp, sizeof(d32)))
+		return -EFAULT;
+
+	d = compat_alloc_user_space(sizeof(*d));
+	if (!access_ok(VERIFY_WRITE, d, sizeof(*d)))
+		return -EFAULT;
+
+	if (__put_user(d32.context, &d->context)
+	    || __put_user(d32.send_count, &d->send_count)
+	    || __put_user((int __user *)(unsigned long) d32.send_indices,
+			  &d->send_indices)
+	    || __put_user((int __user *)(unsigned long) d32.send_sizes,
+			  &d->send_sizes)
+	    || __put_user(d32.flags, &d->flags)
+	    || __put_user(d32.request_count, &d->request_count)
+	    || __put_user((int __user *)(unsigned long) d32.request_indices,
+			  &d->request_indices)
+	    || __put_user((int __user *)(unsigned long) d32.request_sizes,
+			  &d->request_sizes))
+		return -EFAULT;
+
+	err = drm_ioctl(file->f_dentry->d_inode, file,
+			DRM_IOCTL_DMA, (unsigned long) d);
+	if (err)
+		return err;
+
+	if (__get_user(d32.request_size, &d->request_size)
+	    || __get_user(d32.granted_count, &d->granted_count)
+	    || __put_user(d32.request_size, &argp->request_size)
+	    || __put_user(d32.granted_count, &argp->granted_count))
+		return -EFAULT;
+
+	return 0;
+}
+
+#if __OS_HAS_AGP
+typedef struct drm_agp_mode32 {
+	u32 mode;	/**< AGP mode */
+} drm_agp_mode32_t;
+
+static int compat_drm_agp_enable(struct file *file, unsigned int cmd,
+				 unsigned long arg)
+{
+	drm_agp_mode32_t __user *argp = (void __user *)arg;
+	drm_agp_mode32_t m32;
+	drm_agp_mode_t __user *mode;
+
+	if (get_user(m32.mode, &argp->mode))
+		return -EFAULT;
+
+	mode = compat_alloc_user_space(sizeof(*mode));
+	if (put_user(m32.mode, &mode->mode))
+		return -EFAULT;
+
+	return drm_ioctl(file->f_dentry->d_inode, file,
+			 DRM_IOCTL_AGP_ENABLE, (unsigned long) mode);
+}
+
+typedef struct drm_agp_info32 {
+	int       agp_version_major;
+	int       agp_version_minor;
+	u32	  mode;
+	u32	  aperture_base;  /* physical address */
+	u32	  aperture_size;  /* bytes */
+	u32	  memory_allowed; /* bytes */
+	u32	  memory_used;
+
+				/* PCI information */
+	unsigned short id_vendor;
+	unsigned short id_device;
+} drm_agp_info32_t;
+
+static int compat_drm_agp_info(struct file *file, unsigned int cmd,
+			       unsigned long arg)
+{
+	drm_agp_info32_t __user *argp = (void __user *)arg;
+	drm_agp_info32_t i32;
+	drm_agp_info_t __user *info;
+	int err;
+
+	info = compat_alloc_user_space(sizeof(*info));
+	if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
+		return -EFAULT;
+
+	err = drm_ioctl(file->f_dentry->d_inode, file,
+			DRM_IOCTL_AGP_INFO, (unsigned long) info);
+	if (err)
+		return err;
+
+	if (__get_user(i32.agp_version_major, &info->agp_version_major)
+	    || __get_user(i32.agp_version_minor, &info->agp_version_minor)
+	    || __get_user(i32.mode, &info->mode)
+	    || __get_user(i32.aperture_base, &info->aperture_base)
+	    || __get_user(i32.aperture_size, &info->aperture_size)
+	    || __get_user(i32.memory_allowed, &info->memory_allowed)
+	    || __get_user(i32.memory_used, &info->memory_used)
+	    || __get_user(i32.id_vendor, &info->id_vendor)
+	    || __get_user(i32.id_device, &info->id_device))
+		return -EFAULT;
+
+	if (copy_to_user(argp, &i32, sizeof(i32)))
+		return -EFAULT;
+
+	return 0;
+}
+
+typedef struct drm_agp_buffer32 {
+	u32 size;	/**< In bytes -- will round to page boundary */
+	u32 handle;	/**< Used for binding / unbinding */
+	u32 type;	/**< Type of memory to allocate */
+        u32 physical;	/**< Physical used by i810 */
+} drm_agp_buffer32_t;
+
+static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
+				unsigned long arg)
+{
+	drm_agp_buffer32_t __user *argp = (void __user *)arg;
+	drm_agp_buffer32_t req32;
+	drm_agp_buffer_t __user *request;
+	int err;
+
+	if (copy_from_user(&req32, argp, sizeof(req32)))
+		return -EFAULT;
+
+	request = compat_alloc_user_space(sizeof(*request));
+	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+	    || __put_user(req32.size, &request->size)
+	    || __put_user(req32.type, &request->type))
+		return -EFAULT;
+
+	err = drm_ioctl(file->f_dentry->d_inode, file,
+			DRM_IOCTL_AGP_ALLOC, (unsigned long) request);
+	if (err)
+		return err;
+
+	if (__get_user(req32.handle, &request->handle)
+	    || __get_user(req32.physical, &request->physical)
+	    || copy_to_user(argp, &req32, sizeof(req32))) {
+		drm_ioctl(file->f_dentry->d_inode, file,
+			  DRM_IOCTL_AGP_FREE, (unsigned long) request);
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int compat_drm_agp_free(struct file *file, unsigned int cmd,
+			       unsigned long arg)
+{
+	drm_agp_buffer32_t __user *argp = (void __user *)arg;
+	drm_agp_buffer_t __user *request;
+	u32 handle;
+
+	request = compat_alloc_user_space(sizeof(*request));
+	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+	    || get_user(handle, &argp->handle)
+	    || __put_user(handle, &request->handle))
+		return -EFAULT;
+
+	return drm_ioctl(file->f_dentry->d_inode, file,
+			 DRM_IOCTL_AGP_FREE, (unsigned long) request);
+}
+
+typedef struct drm_agp_binding32 {
+	u32 handle;	/**< From drm_agp_buffer */
+	u32 offset;	/**< In bytes -- will round to page boundary */
+} drm_agp_binding32_t;
+
+static int compat_drm_agp_bind(struct file *file, unsigned int cmd,
+			       unsigned long arg)
+{
+	drm_agp_binding32_t __user *argp = (void __user *)arg;
+	drm_agp_binding32_t req32;
+	drm_agp_binding_t __user *request;
+
+	if (copy_from_user(&req32, argp, sizeof(req32)))
+		return -EFAULT;
+
+	request = compat_alloc_user_space(sizeof(*request));
+	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+	    || __put_user(req32.handle, &request->handle)
+	    || __put_user(req32.offset, &request->offset))
+		return -EFAULT;
+
+	return drm_ioctl(file->f_dentry->d_inode, file,
+			 DRM_IOCTL_AGP_BIND, (unsigned long) request);
+}
+
+static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
+				 unsigned long arg)
+{
+	drm_agp_binding32_t __user *argp = (void __user *)arg;
+	drm_agp_binding_t __user *request;
+	u32 handle;
+
+	request = compat_alloc_user_space(sizeof(*request));
+	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+	    || get_user(handle, &argp->handle)
+	    || __put_user(handle, &request->handle))
+		return -EFAULT;
+
+	return drm_ioctl(file->f_dentry->d_inode, file,
+			 DRM_IOCTL_AGP_UNBIND, (unsigned long) request);
+}
+#endif /* __OS_HAS_AGP */
+
+typedef struct drm_scatter_gather32 {
+	u32 size;	/**< In bytes -- will round to page boundary */
+	u32 handle;	/**< Used for mapping / unmapping */
+} drm_scatter_gather32_t;
+
+static int compat_drm_sg_alloc(struct file *file, unsigned int cmd,
+			       unsigned long arg)
+{
+	drm_scatter_gather32_t __user *argp = (void __user *)arg;
+	drm_scatter_gather_t __user *request;
+	int err;
+	unsigned long x;
+
+	request = compat_alloc_user_space(sizeof(*request));
+	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+	    || !access_ok(VERIFY_WRITE, argp, sizeof(*argp))
+	    || __get_user(x, &argp->size)
+	    || __put_user(x, &request->size))
+		return -EFAULT;
+
+	err = drm_ioctl(file->f_dentry->d_inode, file,
+			DRM_IOCTL_SG_ALLOC, (unsigned long) request);
+	if (err)
+		return err;
+
+	/* XXX not sure about the handle conversion here... */
+	if (__get_user(x, &request->handle)
+	    || __put_user(x >> PAGE_SHIFT, &argp->handle))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int compat_drm_sg_free(struct file *file, unsigned int cmd,
+			      unsigned long arg)
+{
+	drm_scatter_gather32_t __user *argp = (void __user *)arg;
+	drm_scatter_gather_t __user *request;
+	unsigned long x;
+
+	request = compat_alloc_user_space(sizeof(*request));
+	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+	    || !access_ok(VERIFY_WRITE, argp, sizeof(*argp))
+	    || __get_user(x, &argp->handle)
+	    || __put_user(x << PAGE_SHIFT, &request->handle))
+		return -EFAULT;
+
+	return drm_ioctl(file->f_dentry->d_inode, file,
+			 DRM_IOCTL_SG_FREE, (unsigned long) request);
+}
+
+struct drm_wait_vblank_request32 {
+	drm_vblank_seq_type_t type;
+	unsigned int sequence;
+	u32 signal;
+};
+
+struct drm_wait_vblank_reply32 {
+	drm_vblank_seq_type_t type;
+	unsigned int sequence;
+	s32 tval_sec;
+	s32 tval_usec;
+};
+
+typedef union drm_wait_vblank32 {
+	struct drm_wait_vblank_request32 request;
+	struct drm_wait_vblank_reply32 reply;
+} drm_wait_vblank32_t;
+
+static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
+				  unsigned long arg)
+{
+	drm_wait_vblank32_t __user *argp = (void __user *)arg;
+	drm_wait_vblank32_t req32;
+	drm_wait_vblank_t __user *request;
+	int err;
+
+	if (copy_from_user(&req32, argp, sizeof(req32)))
+		return -EFAULT;
+
+	request = compat_alloc_user_space(sizeof(*request));
+	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+	    || __put_user(req32.request.type, &request->request.type)
+	    || __put_user(req32.request.sequence, &request->request.sequence)
+	    || __put_user(req32.request.signal, &request->request.signal))
+		return -EFAULT;
+
+	err = drm_ioctl(file->f_dentry->d_inode, file,
+			DRM_IOCTL_WAIT_VBLANK, (unsigned long) request);
+	if (err)
+		return err;
+
+	if (__get_user(req32.reply.type, &request->reply.type)
+	    || __get_user(req32.reply.sequence, &request->reply.sequence)
+	    || __get_user(req32.reply.tval_sec, &request->reply.tval_sec)
+	    || __get_user(req32.reply.tval_usec, &request->reply.tval_usec))
+		return -EFAULT;
+
+	if (copy_to_user(argp, &req32, sizeof(req32)))
+		return -EFAULT;
+
+	return 0;
+}
+
+drm_ioctl_compat_t *drm_compat_ioctls[] = {
+	[DRM_IOCTL_NR(DRM_IOCTL_VERSION32)] = compat_drm_version,
+	[DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE32)] = compat_drm_getunique,
+	[DRM_IOCTL_NR(DRM_IOCTL_GET_MAP32)] = compat_drm_getmap,
+	[DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT32)] = compat_drm_getclient,
+	[DRM_IOCTL_NR(DRM_IOCTL_GET_STATS32)] = compat_drm_getstats,
+	[DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE32)] = compat_drm_setunique,
+	[DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP32)] = compat_drm_addmap,
+	[DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS32)] = compat_drm_addbufs,
+	[DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS32)] = compat_drm_markbufs,
+	[DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS32)] = compat_drm_infobufs,
+	[DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS32)] = compat_drm_mapbufs,
+	[DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS32)] = compat_drm_freebufs,
+	[DRM_IOCTL_NR(DRM_IOCTL_RM_MAP32)] = compat_drm_rmmap,
+	[DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX32)] = compat_drm_setsareactx,
+	[DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX32)] = compat_drm_getsareactx,
+	[DRM_IOCTL_NR(DRM_IOCTL_RES_CTX32)] = compat_drm_resctx,
+	[DRM_IOCTL_NR(DRM_IOCTL_DMA32)] = compat_drm_dma,
+#if __OS_HAS_AGP
+	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE32)] = compat_drm_agp_enable,
+	[DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO32)] = compat_drm_agp_info,
+	[DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC32)] = compat_drm_agp_alloc,
+	[DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE32)] = compat_drm_agp_free,
+	[DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND32)] = compat_drm_agp_bind,
+	[DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND32)] = compat_drm_agp_unbind,
+#endif
+	[DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC32)] = compat_drm_sg_alloc,
+	[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE32)] = compat_drm_sg_free,
+	[DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK32)] = compat_drm_wait_vblank,
+};
+
+/**
+ * Called whenever a 32-bit process running under a 64-bit kernel
+ * performs an ioctl on /dev/drm.
+ *
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ */
+long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	unsigned int nr = DRM_IOCTL_NR(cmd);
+	drm_ioctl_compat_t *fn;
+	int ret;
+
+	if (nr >= DRM_ARRAY_SIZE(drm_compat_ioctls))
+		return -ENOTTY;
+
+	fn = drm_compat_ioctls[nr];
+
+	lock_kernel();		/* XXX for now */
+	if (fn != NULL)
+		ret = (*fn)(filp, cmd, arg);
+	else
+		ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+	unlock_kernel();
+
+	return ret;
+}
+EXPORT_SYMBOL(drm_compat_ioctl);
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
index 54a2914..11c6950 100644
--- a/drivers/char/drm/drm_pciids.h
+++ b/drivers/char/drm/drm_pciids.h
@@ -220,5 +220,6 @@
 	{0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
 	{0x8086, 0x2582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
 	{0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
+	{0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
 	{0, 0, 0}
 
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
index 7300a09..b5903f9 100644
--- a/drivers/char/drm/i915_dma.c
+++ b/drivers/char/drm/i915_dma.c
@@ -1,10 +1,30 @@
 /* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
  */
 /**************************************************************************
- * 
+ *
  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
  * All Rights Reserved.
- * 
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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 "drmP.h"
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h
index 7e55edf..23e027d 100644
--- a/drivers/char/drm/i915_drm.h
+++ b/drivers/char/drm/i915_drm.h
@@ -1,3 +1,30 @@
+/**************************************************************************
+ *
+ * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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 _I915_DRM_H_
 #define _I915_DRM_H_
 
diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c
index 002b708..e6a9e1d 100644
--- a/drivers/char/drm/i915_drv.c
+++ b/drivers/char/drm/i915_drv.c
@@ -1,11 +1,30 @@
 /* i915_drv.c -- i830,i845,i855,i865,i915 driver -*- linux-c -*-
  */
-
 /**************************************************************************
- * 
+ *
  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
  * All Rights Reserved.
- * 
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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 "drmP.h"
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
index f6ca92a..fa940d6 100644
--- a/drivers/char/drm/i915_drv.h
+++ b/drivers/char/drm/i915_drv.h
@@ -1,10 +1,30 @@
 /* i915_drv.h -- Private header for the I915 driver -*- linux-c -*-
  */
 /**************************************************************************
- * 
+ *
  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
  * All Rights Reserved.
- * 
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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 _I915_DRV_H_
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index b023926..a101cc9 100644
--- a/drivers/char/drm/i915_irq.c
+++ b/drivers/char/drm/i915_irq.c
@@ -1,10 +1,30 @@
 /* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
  */
 /**************************************************************************
- * 
+ *
  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
  * All Rights Reserved.
- * 
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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 "drmP.h"
diff --git a/drivers/char/drm/i915_mem.c b/drivers/char/drm/i915_mem.c
index d54a300..9b1698f 100644
--- a/drivers/char/drm/i915_mem.c
+++ b/drivers/char/drm/i915_mem.c
@@ -1,10 +1,30 @@
 /* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*-
  */
 /**************************************************************************
- * 
+ *
  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
  * All Rights Reserved.
- * 
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * 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 NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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 "drmP.h"
diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
index 7b983d9..18e4e5b 100644
--- a/drivers/char/drm/radeon_drv.c
+++ b/drivers/char/drm/radeon_drv.c
@@ -101,6 +101,9 @@
 		.mmap = drm_mmap,
 		.poll = drm_poll,
 		.fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+		.compat_ioctl = radeon_compat_ioctl,
+#endif
 	},
 	.pci_driver = {
 		.name          = DRIVER_NAME,
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index 5837098..771aa80 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -317,6 +317,9 @@
 extern int radeon_postinit( struct drm_device *dev, unsigned long flags );
 extern int radeon_postcleanup( struct drm_device *dev );
 
+extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
+				unsigned long arg);
+
 /* Flags for stats.boxes
  */
 #define RADEON_BOX_DMA_IDLE      0x1
diff --git a/drivers/char/drm/radeon_ioc32.c b/drivers/char/drm/radeon_ioc32.c
new file mode 100644
index 0000000..bfe6122
--- /dev/null
+++ b/drivers/char/drm/radeon_ioc32.c
@@ -0,0 +1,395 @@
+/**
+ * \file radeon_ioc32.c
+ *
+ * 32-bit ioctl compatibility routines for the Radeon DRM.
+ *
+ * \author Paul Mackerras <paulus@samba.org>
+ *
+ * Copyright (C) Paul Mackerras 2005
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * 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 AUTHOR 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 <linux/compat.h>
+#include <linux/ioctl32.h>
+
+#include "drmP.h"
+#include "drm.h"
+#include "radeon_drm.h"
+#include "radeon_drv.h"
+
+typedef struct drm_radeon_init32 {
+	int func;
+	u32 sarea_priv_offset;
+	int is_pci;
+	int cp_mode;
+	int gart_size;
+	int ring_size;
+	int usec_timeout;
+
+	unsigned int fb_bpp;
+	unsigned int front_offset, front_pitch;
+	unsigned int back_offset, back_pitch;
+	unsigned int depth_bpp;
+	unsigned int depth_offset, depth_pitch;
+
+	u32 fb_offset;
+	u32 mmio_offset;
+	u32 ring_offset;
+	u32 ring_rptr_offset;
+	u32 buffers_offset;
+	u32 gart_textures_offset;
+} drm_radeon_init32_t;
+
+static int compat_radeon_cp_init(struct file *file, unsigned int cmd,
+				 unsigned long arg)
+{
+	drm_radeon_init32_t init32;
+	drm_radeon_init_t __user *init;
+
+	if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
+		return -EFAULT;
+
+	init = compat_alloc_user_space(sizeof(*init));
+	if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
+	    || __put_user(init32.func, &init->func)
+	    || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset)
+	    || __put_user(init32.is_pci, &init->is_pci)
+	    || __put_user(init32.cp_mode, &init->cp_mode)
+	    || __put_user(init32.gart_size, &init->gart_size)
+	    || __put_user(init32.ring_size, &init->ring_size)
+	    || __put_user(init32.usec_timeout, &init->usec_timeout)
+	    || __put_user(init32.fb_bpp, &init->fb_bpp)
+	    || __put_user(init32.front_offset, &init->front_offset)
+	    || __put_user(init32.front_pitch, &init->front_pitch)
+	    || __put_user(init32.back_offset, &init->back_offset)
+	    || __put_user(init32.back_pitch, &init->back_pitch)
+	    || __put_user(init32.depth_bpp, &init->depth_bpp)
+	    || __put_user(init32.depth_offset, &init->depth_offset)
+	    || __put_user(init32.depth_pitch, &init->depth_pitch)
+	    || __put_user(init32.fb_offset, &init->fb_offset)
+	    || __put_user(init32.mmio_offset, &init->mmio_offset)
+	    || __put_user(init32.ring_offset, &init->ring_offset)
+	    || __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset)
+	    || __put_user(init32.buffers_offset, &init->buffers_offset)
+	    || __put_user(init32.gart_textures_offset,
+			  &init->gart_textures_offset))
+		return -EFAULT;
+
+	return drm_ioctl(file->f_dentry->d_inode, file,
+			 DRM_IOCTL_RADEON_CP_INIT, (unsigned long) init);
+}
+
+typedef struct drm_radeon_clear32 {
+	unsigned int flags;
+	unsigned int clear_color;
+	unsigned int clear_depth;
+	unsigned int color_mask;
+	unsigned int depth_mask;   /* misnamed field:  should be stencil */
+	u32	     depth_boxes;
+} drm_radeon_clear32_t;
+
+static int compat_radeon_cp_clear(struct file *file, unsigned int cmd,
+				  unsigned long arg)
+{
+	drm_radeon_clear32_t clr32;
+	drm_radeon_clear_t __user *clr;
+
+	if (copy_from_user(&clr32, (void __user *)arg, sizeof(clr32)))
+		return -EFAULT;
+
+	clr = compat_alloc_user_space(sizeof(*clr));
+	if (!access_ok(VERIFY_WRITE, clr, sizeof(*clr))
+	    || __put_user(clr32.flags, &clr->flags)
+	    || __put_user(clr32.clear_color, &clr->clear_color)
+	    || __put_user(clr32.clear_depth, &clr->clear_depth)
+	    || __put_user(clr32.color_mask, &clr->color_mask)
+	    || __put_user(clr32.depth_mask, &clr->depth_mask)
+	    || __put_user((void __user *)(unsigned long)clr32.depth_boxes,
+			  &clr->depth_boxes))
+		return -EFAULT;
+
+	return drm_ioctl(file->f_dentry->d_inode, file,
+			 DRM_IOCTL_RADEON_CLEAR, (unsigned long) clr);
+}
+
+typedef struct drm_radeon_stipple32 {
+	u32 mask;
+} drm_radeon_stipple32_t;
+
+static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd,
+				    unsigned long arg)
+{
+	drm_radeon_stipple32_t __user *argp = (void __user *) arg;
+	drm_radeon_stipple_t __user *request;
+	u32 mask;
+
+	if (get_user(mask, &argp->mask))
+		return -EFAULT;
+
+	request = compat_alloc_user_space(sizeof(*request));
+	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+	    || __put_user((unsigned int __user *)(unsigned long) mask,
+			  &request->mask))
+		return -EFAULT;
+
+	return drm_ioctl(file->f_dentry->d_inode, file,
+			 DRM_IOCTL_RADEON_STIPPLE, (unsigned long) request);
+}
+
+typedef struct drm_radeon_tex_image32 {
+	unsigned int x, y;		/* Blit coordinates */
+	unsigned int width, height;
+	u32 data;
+} drm_radeon_tex_image32_t;
+
+typedef struct drm_radeon_texture32 {
+	unsigned int offset;
+	int pitch;
+	int format;
+	int width;			/* Texture image coordinates */
+	int height;
+	u32 image;
+} drm_radeon_texture32_t;
+
+static int compat_radeon_cp_texture(struct file *file, unsigned int cmd,
+				    unsigned long arg)
+{
+	drm_radeon_texture32_t req32;
+	drm_radeon_texture_t __user *request;
+	drm_radeon_tex_image32_t img32;
+	drm_radeon_tex_image_t __user *image;
+
+	if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+		return -EFAULT;
+	if (req32.image == 0)
+		return -EINVAL;
+	if (copy_from_user(&img32, (void __user *)(unsigned long)req32.image,
+			   sizeof(img32)))
+		return -EFAULT;
+
+	request = compat_alloc_user_space(sizeof(*request) + sizeof(*image));
+	if (!access_ok(VERIFY_WRITE, request,
+		       sizeof(*request) + sizeof(*image)))
+		return -EFAULT;
+	image = (drm_radeon_tex_image_t __user *) (request + 1);
+
+	if (__put_user(req32.offset, &request->offset)
+	    || __put_user(req32.pitch, &request->pitch)
+	    || __put_user(req32.format, &request->format)
+	    || __put_user(req32.width, &request->width)
+	    || __put_user(req32.height, &request->height)
+	    || __put_user(image, &request->image)
+	    || __put_user(img32.x, &image->x)
+	    || __put_user(img32.y, &image->y)
+	    || __put_user(img32.width, &image->width)
+	    || __put_user(img32.height, &image->height)
+	    || __put_user((const void __user *)(unsigned long)img32.data,
+			  &image->data))
+		return -EFAULT;
+
+	return drm_ioctl(file->f_dentry->d_inode, file,
+			 DRM_IOCTL_RADEON_TEXTURE, (unsigned long) request);
+}
+
+typedef struct drm_radeon_vertex2_32 {
+	int idx;			/* Index of vertex buffer */
+	int discard;			/* Client finished with buffer? */
+	int nr_states;
+	u32 state;
+	int nr_prims;
+	u32 prim;
+} drm_radeon_vertex2_32_t;
+
+static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd,
+				    unsigned long arg)
+{
+	drm_radeon_vertex2_32_t req32;
+	drm_radeon_vertex2_t __user *request;
+
+	if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+		return -EFAULT;
+
+	request = compat_alloc_user_space(sizeof(*request));
+	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+	    || __put_user(req32.idx, &request->idx)
+	    || __put_user(req32.discard, &request->discard)
+	    || __put_user(req32.nr_states, &request->nr_states)
+	    || __put_user((void __user *)(unsigned long)req32.state,
+			  &request->state)
+	    || __put_user(req32.nr_prims, &request->nr_prims)
+	    || __put_user((void __user *)(unsigned long)req32.prim,
+			  &request->prim))
+		return -EFAULT;
+
+	return drm_ioctl(file->f_dentry->d_inode, file,
+			 DRM_IOCTL_RADEON_VERTEX2, (unsigned long) request);
+}
+
+typedef struct drm_radeon_cmd_buffer32 {
+	int bufsz;
+	u32 buf;
+	int nbox;
+	u32 boxes;
+} drm_radeon_cmd_buffer32_t;
+
+static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd,
+				   unsigned long arg)
+{
+	drm_radeon_cmd_buffer32_t req32;
+	drm_radeon_cmd_buffer_t __user *request;
+
+	if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+		return -EFAULT;
+
+	request = compat_alloc_user_space(sizeof(*request));
+	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+	    || __put_user(req32.bufsz, &request->bufsz)
+	    || __put_user((void __user *)(unsigned long)req32.buf,
+			  &request->buf)
+	    || __put_user(req32.nbox, &request->nbox)
+	    || __put_user((void __user *)(unsigned long)req32.boxes,
+			  &request->boxes))
+		return -EFAULT;
+
+	return drm_ioctl(file->f_dentry->d_inode, file,
+			 DRM_IOCTL_RADEON_CMDBUF, (unsigned long) request);
+}
+
+typedef struct drm_radeon_getparam32 {
+	int param;
+	u32 value;
+} drm_radeon_getparam32_t;
+
+static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd,
+				     unsigned long arg)
+{
+	drm_radeon_getparam32_t req32;
+	drm_radeon_getparam_t __user *request;
+
+	if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+		return -EFAULT;
+
+	request = compat_alloc_user_space(sizeof(*request));
+	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+	    || __put_user(req32.param, &request->param)
+	    || __put_user((void __user *)(unsigned long)req32.value,
+			  &request->value))
+		return -EFAULT;
+
+	return drm_ioctl(file->f_dentry->d_inode, file,
+			 DRM_IOCTL_RADEON_GETPARAM, (unsigned long) request);
+}
+
+typedef struct drm_radeon_mem_alloc32 {
+	int region;
+	int alignment;
+	int size;
+	u32 region_offset;	/* offset from start of fb or GART */
+} drm_radeon_mem_alloc32_t;
+
+static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd,
+				   unsigned long arg)
+{
+	drm_radeon_mem_alloc32_t req32;
+	drm_radeon_mem_alloc_t __user *request;
+
+	if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+		return -EFAULT;
+
+	request = compat_alloc_user_space(sizeof(*request));
+	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+	    || __put_user(req32.region, &request->region)
+	    || __put_user(req32.alignment, &request->alignment)
+	    || __put_user(req32.size, &request->size)
+	    || __put_user((int __user *)(unsigned long)req32.region_offset,
+			  &request->region_offset))
+		return -EFAULT;
+
+	return drm_ioctl(file->f_dentry->d_inode, file,
+			 DRM_IOCTL_RADEON_ALLOC, (unsigned long) request);
+}
+
+typedef struct drm_radeon_irq_emit32 {
+	u32 irq_seq;
+} drm_radeon_irq_emit32_t;
+
+static int compat_radeon_irq_emit(struct file *file, unsigned int cmd,
+				  unsigned long arg)
+{
+	drm_radeon_irq_emit32_t req32;
+	drm_radeon_irq_emit_t __user *request;
+
+	if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
+		return -EFAULT;
+
+	request = compat_alloc_user_space(sizeof(*request));
+	if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
+	    || __put_user((int __user *)(unsigned long)req32.irq_seq,
+			  &request->irq_seq))
+		return -EFAULT;
+
+	return drm_ioctl(file->f_dentry->d_inode, file,
+			 DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long) request);
+}
+
+drm_ioctl_compat_t *radeon_compat_ioctls[] = {
+	[DRM_RADEON_CP_INIT] = compat_radeon_cp_init,
+	[DRM_RADEON_CLEAR] = compat_radeon_cp_clear,
+	[DRM_RADEON_STIPPLE] = compat_radeon_cp_stipple,
+	[DRM_RADEON_TEXTURE] = compat_radeon_cp_texture,
+	[DRM_RADEON_VERTEX2] = compat_radeon_cp_vertex2,
+	[DRM_RADEON_CMDBUF] = compat_radeon_cp_cmdbuf,
+	[DRM_RADEON_GETPARAM] = compat_radeon_cp_getparam,
+	[DRM_RADEON_ALLOC] = compat_radeon_mem_alloc,
+	[DRM_RADEON_IRQ_EMIT] = compat_radeon_irq_emit,
+};
+
+/**
+ * Called whenever a 32-bit process running under a 64-bit kernel
+ * performs an ioctl on /dev/dri/card<n>.
+ *
+ * \param filp file pointer.
+ * \param cmd command.
+ * \param arg user argument.
+ * \return zero on success or negative number on failure.
+ */
+long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
+			 unsigned long arg)
+{
+	unsigned int nr = DRM_IOCTL_NR(cmd);
+	drm_ioctl_compat_t *fn = NULL;
+	int ret;
+
+	if (nr < DRM_COMMAND_BASE)
+		return drm_compat_ioctl(filp, cmd, arg);
+
+	if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(radeon_compat_ioctls))
+		fn = radeon_compat_ioctls[nr - DRM_COMMAND_BASE];
+
+	lock_kernel();		/* XXX for now */
+	if (fn != NULL)
+		ret = (*fn)(filp, cmd, arg);
+	else
+		ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
+	unlock_kernel();
+
+	return ret;
+}
diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c
index 5b18bee..40474a6 100644
--- a/drivers/char/drm/radeon_irq.c
+++ b/drivers/char/drm/radeon_irq.c
@@ -35,6 +35,14 @@
 #include "radeon_drm.h"
 #include "radeon_drv.h"
 
+static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 mask)
+{
+	u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
+	if (irqs)
+		RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
+	return irqs;
+}
+
 /* Interrupts - Used for device synchronization and flushing in the
  * following circumstances:
  *
@@ -63,8 +71,8 @@
 	/* Only consider the bits we're interested in - others could be used
 	 * outside the DRM
 	 */
-	stat = RADEON_READ(RADEON_GEN_INT_STATUS)
-	     & (RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT);
+	stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK | 
+						  RADEON_CRTC_VBLANK_STAT));
 	if (!stat)
 		return IRQ_NONE;
 
@@ -80,19 +88,9 @@
 		drm_vbl_send_signals( dev );
 	}
 
-	/* Acknowledge interrupts we handle */
-	RADEON_WRITE(RADEON_GEN_INT_STATUS, stat);
 	return IRQ_HANDLED;
 }
 
-static __inline__ void radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv)
-{
-	u32 tmp = RADEON_READ( RADEON_GEN_INT_STATUS )
-		& (RADEON_SW_INT_TEST_ACK | RADEON_CRTC_VBLANK_STAT);
-	if (tmp)
-		RADEON_WRITE( RADEON_GEN_INT_STATUS, tmp );
-}
-
 static int radeon_emit_irq(drm_device_t *dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -123,11 +121,6 @@
 
 	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
 
-	/* This is a hack to work around mysterious freezes on certain
-	 * systems:
-	 */ 
-	radeon_acknowledge_irqs( dev_priv );
-
 	DRM_WAIT_ON( ret, dev_priv->swi_queue, 3 * DRM_HZ, 
 		     RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr );
 
@@ -146,7 +139,7 @@
 		return DRM_ERR(EINVAL);
 	}
 
-	radeon_acknowledge_irqs( dev_priv );
+	radeon_acknowledge_irqs(dev_priv, RADEON_CRTC_VBLANK_STAT);
 
 	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
 
@@ -224,7 +217,8 @@
       	RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
 
 	/* Clear bits if they're already high */
-	radeon_acknowledge_irqs( dev_priv );
+	radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
+					   RADEON_CRTC_VBLANK_STAT));
 }
 
 void radeon_driver_irq_postinstall( drm_device_t *dev ) {
diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c
index 7def6ad..62cda25 100644
--- a/drivers/char/ds1620.c
+++ b/drivers/char/ds1620.c
@@ -163,8 +163,7 @@
 	netwinder_ds1620_reset();
 	netwinder_unlock(&flags);
 
-	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout(2);
+	msleep(20);
 }
 
 static unsigned int ds1620_in(int cmd, int bits)
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index 37d6649..26271e3 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -144,7 +144,7 @@
 	int tx_wsize, rx_wsize;
 } dsp56k;
 
-static struct class_simple *dsp56k_class;
+static struct class *dsp56k_class;
 
 static int dsp56k_reset(void)
 {
@@ -510,12 +510,12 @@
 		printk("DSP56k driver: Unable to register driver\n");
 		return -ENODEV;
 	}
-	dsp56k_class = class_simple_create(THIS_MODULE, "dsp56k");
+	dsp56k_class = class_create(THIS_MODULE, "dsp56k");
 	if (IS_ERR(dsp56k_class)) {
 		err = PTR_ERR(dsp56k_class);
 		goto out_chrdev;
 	}
-	class_simple_device_add(dsp56k_class, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k");
+	class_device_create(dsp56k_class, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k");
 
 	err = devfs_mk_cdev(MKDEV(DSP56K_MAJOR, 0),
 		      S_IFCHR | S_IRUSR | S_IWUSR, "dsp56k");
@@ -526,8 +526,8 @@
 	goto out;
 
 out_class:
-	class_simple_device_remove(MKDEV(DSP56K_MAJOR, 0));
-	class_simple_destroy(dsp56k_class);
+	class_device_destroy(dsp56k_class, MKDEV(DSP56K_MAJOR, 0));
+	class_destroy(dsp56k_class);
 out_chrdev:
 	unregister_chrdev(DSP56K_MAJOR, "dsp56k");
 out:
@@ -537,8 +537,8 @@
 
 static void __exit dsp56k_cleanup_driver(void)
 {
-	class_simple_device_remove(MKDEV(DSP56K_MAJOR, 0));
-	class_simple_destroy(dsp56k_class);
+	class_device_destroy(dsp56k_class, MKDEV(DSP56K_MAJOR, 0));
+	class_destroy(dsp56k_class);
 	unregister_chrdev(DSP56K_MAJOR, "dsp56k");
 	devfs_remove("dsp56k");
 }
diff --git a/drivers/char/ftape/compressor/zftape-compress.c b/drivers/char/ftape/compressor/zftape-compress.c
index 220a227..65ffc0b 100644
--- a/drivers/char/ftape/compressor/zftape-compress.c
+++ b/drivers/char/ftape/compressor/zftape-compress.c
@@ -1176,8 +1176,8 @@
         }
 #else /* !MODULE */
 	/* print a short no-nonsense boot message */
-	printk("zftape compressor v1.00a 970514\n");
-	printk("For use with " FTAPE_VERSION "\n");
+	printk(KERN_INFO "zftape compressor v1.00a 970514\n");
+	printk(KERN_INFO "For use with " FTAPE_VERSION "\n");
 #endif /* MODULE */
 	TRACE(ft_t_info, "zft_compressor_init @ 0x%p", zft_compressor_init);
 	TRACE(ft_t_info, "installing compressor for zftape ...");
diff --git a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c
index dbac7e5..5745b74 100644
--- a/drivers/char/ftape/zftape/zftape-init.c
+++ b/drivers/char/ftape/zftape/zftape-init.c
@@ -99,7 +99,7 @@
 	.release	= zft_close,
 };
 
-static struct class_simple *zft_class;
+static struct class *zft_class;
 
 /*      Open floppy tape device
  */
@@ -329,29 +329,29 @@
 	      "installing zftape VFS interface for ftape driver ...");
 	TRACE_CATCH(register_chrdev(QIC117_TAPE_MAJOR, "zft", &zft_cdev),);
 
-	zft_class = class_simple_create(THIS_MODULE, "zft");
+	zft_class = class_create(THIS_MODULE, "zft");
 	for (i = 0; i < 4; i++) {
-		class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i);
+		class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i);
 		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i),
 				S_IFCHR | S_IRUSR | S_IWUSR,
 				"qft%i", i);
-		class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i);
+		class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i);
 		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 4),
 				S_IFCHR | S_IRUSR | S_IWUSR,
 				"nqft%i", i);
-		class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i);
+		class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i);
 		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 16),
 				S_IFCHR | S_IRUSR | S_IWUSR,
 				"zqft%i", i);
-		class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i);
+		class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i);
 		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 20),
 				S_IFCHR | S_IRUSR | S_IWUSR,
 				"nzqft%i", i);
-		class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i);
+		class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i);
 		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 32),
 				S_IFCHR | S_IRUSR | S_IWUSR,
 				"rawqft%i", i);
-		class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i);
+		class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i);
 		devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 36),
 				S_IFCHR | S_IRUSR | S_IWUSR,
 				"nrawqft%i", i);
@@ -381,19 +381,19 @@
 	}
         for (i = 0; i < 4; i++) {
 		devfs_remove("qft%i", i);
-		class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i));
+		class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i));
 		devfs_remove("nqft%i", i);
-		class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 4));
+		class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4));
 		devfs_remove("zqft%i", i);
-		class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 16));
+		class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16));
 		devfs_remove("nzqft%i", i);
-		class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 20));
+		class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20));
 		devfs_remove("rawqft%i", i);
-		class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 32));
+		class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32));
 		devfs_remove("nrawqft%i", i);
-		class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 36));
+		class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36));
 	}
-	class_simple_destroy(zft_class);
+	class_destroy(zft_class);
 	zft_uninit_mem(); /* release remaining memory, if any */
         printk(KERN_INFO "zftape successfully unloaded.\n");
 	TRACE_EXIT;
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 5ec732e..762fa43 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -834,7 +834,7 @@
 	printk("\n");
 
 	ns = hpetp->hp_period;	/* femptoseconds, 10^-15 */
-	do_div(ns, 1000000);	/* convert to nanoseconds, 10^-9 */
+	ns /= 1000000;		/* convert to nanoseconds, 10^-9 */
 	printk(KERN_INFO "hpet%d: %ldns tick, %d %d-bit timers\n",
 		hpetp->hp_which, ns, hpetp->hp_ntimer,
 		cap & HPET_COUNTER_SIZE_MASK ? 64 : 32);
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
index abfbdcf..3236d24 100644
--- a/drivers/char/hvcs.c
+++ b/drivers/char/hvcs.c
@@ -1466,7 +1466,7 @@
 }
 /* The sysfs interface for the driver and devices */
 
-static ssize_t hvcs_partner_vtys_show(struct device *dev, char *buf)
+static ssize_t hvcs_partner_vtys_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct vio_dev *viod = to_vio_dev(dev);
 	struct hvcs_struct *hvcsd = from_vio_dev(viod);
@@ -1480,7 +1480,7 @@
 }
 static DEVICE_ATTR(partner_vtys, S_IRUGO, hvcs_partner_vtys_show, NULL);
 
-static ssize_t hvcs_partner_clcs_show(struct device *dev, char *buf)
+static ssize_t hvcs_partner_clcs_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct vio_dev *viod = to_vio_dev(dev);
 	struct hvcs_struct *hvcsd = from_vio_dev(viod);
@@ -1494,7 +1494,7 @@
 }
 static DEVICE_ATTR(partner_clcs, S_IRUGO, hvcs_partner_clcs_show, NULL);
 
-static ssize_t hvcs_current_vty_store(struct device *dev, const char * buf,
+static ssize_t hvcs_current_vty_store(struct device *dev, struct device_attribute *attr, const char * buf,
 		size_t count)
 {
 	/*
@@ -1505,7 +1505,7 @@
 	return -EPERM;
 }
 
-static ssize_t hvcs_current_vty_show(struct device *dev, char *buf)
+static ssize_t hvcs_current_vty_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct vio_dev *viod = to_vio_dev(dev);
 	struct hvcs_struct *hvcsd = from_vio_dev(viod);
@@ -1521,7 +1521,7 @@
 static DEVICE_ATTR(current_vty,
 	S_IRUGO | S_IWUSR, hvcs_current_vty_show, hvcs_current_vty_store);
 
-static ssize_t hvcs_vterm_state_store(struct device *dev, const char *buf,
+static ssize_t hvcs_vterm_state_store(struct device *dev, struct device_attribute *attr, const char *buf,
 		size_t count)
 {
 	struct vio_dev *viod = to_vio_dev(dev);
@@ -1559,7 +1559,7 @@
 	return count;
 }
 
-static ssize_t hvcs_vterm_state_show(struct device *dev, char *buf)
+static ssize_t hvcs_vterm_state_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct vio_dev *viod = to_vio_dev(dev);
 	struct hvcs_struct *hvcsd = from_vio_dev(viod);
@@ -1574,7 +1574,7 @@
 static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR,
 		hvcs_vterm_state_show, hvcs_vterm_state_store);
 
-static ssize_t hvcs_index_show(struct device *dev, char *buf)
+static ssize_t hvcs_index_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct vio_dev *viod = to_vio_dev(dev);
 	struct hvcs_struct *hvcsd = from_vio_dev(viod);
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c
index a811976..6c4b3f9 100644
--- a/drivers/char/i8k.c
+++ b/drivers/char/i8k.c
@@ -20,13 +20,14 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
-#include <linux/apm_bios.h>
+#include <linux/seq_file.h>
+#include <linux/dmi.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
 #include <linux/i8k.h>
 
-#define I8K_VERSION		"1.13 14/05/2002"
+#define I8K_VERSION		"1.14 21/02/2005"
 
 #define I8K_SMM_FN_STATUS	0x0025
 #define I8K_SMM_POWER_STATUS	0x0069
@@ -34,7 +35,8 @@
 #define I8K_SMM_GET_FAN		0x00a3
 #define I8K_SMM_GET_SPEED	0x02a3
 #define I8K_SMM_GET_TEMP	0x10a3
-#define I8K_SMM_GET_DELL_SIG	0xffa3
+#define I8K_SMM_GET_DELL_SIG1	0xfea3
+#define I8K_SMM_GET_DELL_SIG2	0xffa3
 #define I8K_SMM_BIOS_VERSION	0x00a6
 
 #define I8K_FAN_MULT		30
@@ -52,18 +54,7 @@
 
 #define I8K_TEMPERATURE_BUG	1
 
-#define DELL_SIGNATURE		"Dell Computer"
-
-static char *supported_models[] = {
-    "Inspiron",
-    "Latitude",
-    NULL
-};
-
-static char system_vendor[48] = "?";
-static char product_name [48] = "?";
-static char bios_version [4]  = "?";
-static char serial_number[16] = "?";
+static char bios_version[4];
 
 MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)");
 MODULE_DESCRIPTION("Driver for accessing SMM BIOS on Dell laptops");
@@ -73,6 +64,10 @@
 module_param(force, bool, 0);
 MODULE_PARM_DESC(force, "Force loading without checking for supported models");
 
+static int ignore_dmi;
+module_param(ignore_dmi, bool, 0);
+MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match");
+
 static int restricted;
 module_param(restricted, bool, 0);
 MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set");
@@ -81,69 +76,69 @@
 module_param(power_status, bool, 0600);
 MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k");
 
-static ssize_t i8k_read(struct file *, char __user *, size_t, loff_t *);
+static int i8k_open_fs(struct inode *inode, struct file *file);
 static int i8k_ioctl(struct inode *, struct file *, unsigned int,
 		     unsigned long);
 
 static struct file_operations i8k_fops = {
-    .read	= i8k_read,
-    .ioctl	= i8k_ioctl,
+	.open		= i8k_open_fs,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+	.ioctl		= i8k_ioctl,
 };
 
-typedef struct {
-    unsigned int eax;
-    unsigned int ebx __attribute__ ((packed));
-    unsigned int ecx __attribute__ ((packed));
-    unsigned int edx __attribute__ ((packed));
-    unsigned int esi __attribute__ ((packed));
-    unsigned int edi __attribute__ ((packed));
-} SMMRegisters;
+struct smm_regs {
+	unsigned int eax;
+	unsigned int ebx __attribute__ ((packed));
+	unsigned int ecx __attribute__ ((packed));
+	unsigned int edx __attribute__ ((packed));
+	unsigned int esi __attribute__ ((packed));
+	unsigned int edi __attribute__ ((packed));
+};
 
-typedef struct {
-    u8	type;
-    u8	length;
-    u16	handle;
-} DMIHeader;
+static inline char *i8k_get_dmi_data(int field)
+{
+	return dmi_get_system_info(field) ? : "N/A";
+}
 
 /*
  * Call the System Management Mode BIOS. Code provided by Jonathan Buzzard.
  */
-static int i8k_smm(SMMRegisters *regs)
+static int i8k_smm(struct smm_regs *regs)
 {
-    int rc;
-    int eax = regs->eax;
+	int rc;
+	int eax = regs->eax;
 
-    asm("pushl %%eax\n\t" \
-	"movl 0(%%eax),%%edx\n\t" \
-	"push %%edx\n\t" \
-	"movl 4(%%eax),%%ebx\n\t" \
-	"movl 8(%%eax),%%ecx\n\t" \
-	"movl 12(%%eax),%%edx\n\t" \
-	"movl 16(%%eax),%%esi\n\t" \
-	"movl 20(%%eax),%%edi\n\t" \
-	"popl %%eax\n\t" \
-	"out %%al,$0xb2\n\t" \
-	"out %%al,$0x84\n\t" \
-	"xchgl %%eax,(%%esp)\n\t"
-	"movl %%ebx,4(%%eax)\n\t" \
-	"movl %%ecx,8(%%eax)\n\t" \
-	"movl %%edx,12(%%eax)\n\t" \
-	"movl %%esi,16(%%eax)\n\t" \
-	"movl %%edi,20(%%eax)\n\t" \
-	"popl %%edx\n\t" \
-	"movl %%edx,0(%%eax)\n\t" \
-	"lahf\n\t" \
-	"shrl $8,%%eax\n\t" \
-	"andl $1,%%eax\n" \
-	: "=a" (rc)
-	: "a" (regs)
-	: "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
+	asm("pushl %%eax\n\t"
+	    "movl 0(%%eax),%%edx\n\t"
+	    "push %%edx\n\t"
+	    "movl 4(%%eax),%%ebx\n\t"
+	    "movl 8(%%eax),%%ecx\n\t"
+	    "movl 12(%%eax),%%edx\n\t"
+	    "movl 16(%%eax),%%esi\n\t"
+	    "movl 20(%%eax),%%edi\n\t"
+	    "popl %%eax\n\t"
+	    "out %%al,$0xb2\n\t"
+	    "out %%al,$0x84\n\t"
+	    "xchgl %%eax,(%%esp)\n\t"
+	    "movl %%ebx,4(%%eax)\n\t"
+	    "movl %%ecx,8(%%eax)\n\t"
+	    "movl %%edx,12(%%eax)\n\t"
+	    "movl %%esi,16(%%eax)\n\t"
+	    "movl %%edi,20(%%eax)\n\t"
+	    "popl %%edx\n\t"
+	    "movl %%edx,0(%%eax)\n\t"
+	    "lahf\n\t"
+	    "shrl $8,%%eax\n\t"
+	    "andl $1,%%eax\n":"=a"(rc)
+	    :    "a"(regs)
+	    :    "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
 
-    if ((rc != 0) || ((regs->eax & 0xffff) == 0xffff) || (regs->eax == eax)) {
-	return -EINVAL;
-    }
+	if (rc != 0 || (regs->eax & 0xffff) == 0xffff || regs->eax == eax)
+		return -EINVAL;
 
-    return 0;
+	return 0;
 }
 
 /*
@@ -152,24 +147,9 @@
  */
 static int i8k_get_bios_version(void)
 {
-    SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
-    int rc;
+	struct smm_regs regs = { .eax = I8K_SMM_BIOS_VERSION, };
 
-    regs.eax = I8K_SMM_BIOS_VERSION;
-    if ((rc=i8k_smm(&regs)) < 0) {
-	return rc;
-    }
-
-    return regs.eax;
-}
-
-/*
- * Read the machine id.
- */
-static int i8k_get_serial_number(unsigned char *buff)
-{
-    strlcpy(buff, serial_number, sizeof(serial_number));
-    return 0;
+	return i8k_smm(&regs) ? : regs.eax;
 }
 
 /*
@@ -177,24 +157,22 @@
  */
 static int i8k_get_fn_status(void)
 {
-    SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
-    int rc;
+	struct smm_regs regs = { .eax = I8K_SMM_FN_STATUS, };
+	int rc;
 
-    regs.eax = I8K_SMM_FN_STATUS;
-    if ((rc=i8k_smm(&regs)) < 0) {
-	return rc;
-    }
+	if ((rc = i8k_smm(&regs)) < 0)
+		return rc;
 
-    switch ((regs.eax >> I8K_FN_SHIFT) & I8K_FN_MASK) {
-    case I8K_FN_UP:
-	return I8K_VOL_UP;
-    case I8K_FN_DOWN:
-	return I8K_VOL_DOWN;
-    case I8K_FN_MUTE:
-	return I8K_VOL_MUTE;
-    default:
-	return 0;
-    }
+	switch ((regs.eax >> I8K_FN_SHIFT) & I8K_FN_MASK) {
+	case I8K_FN_UP:
+		return I8K_VOL_UP;
+	case I8K_FN_DOWN:
+		return I8K_VOL_DOWN;
+	case I8K_FN_MUTE:
+		return I8K_VOL_MUTE;
+	default:
+		return 0;
+	}
 }
 
 /*
@@ -202,20 +180,13 @@
  */
 static int i8k_get_power_status(void)
 {
-    SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
-    int rc;
+	struct smm_regs regs = { .eax = I8K_SMM_POWER_STATUS, };
+	int rc;
 
-    regs.eax = I8K_SMM_POWER_STATUS;
-    if ((rc=i8k_smm(&regs)) < 0) {
-	return rc;
-    }
+	if ((rc = i8k_smm(&regs)) < 0)
+		return rc;
 
-    switch (regs.eax & 0xff) {
-    case I8K_POWER_AC:
-	return I8K_AC;
-    default:
-	return I8K_BATTERY;
-    }
+	return (regs.eax & 0xff) == I8K_POWER_AC ? I8K_AC : I8K_BATTERY;
 }
 
 /*
@@ -223,16 +194,10 @@
  */
 static int i8k_get_fan_status(int fan)
 {
-    SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
-    int rc;
+	struct smm_regs regs = { .eax = I8K_SMM_GET_FAN, };
 
-    regs.eax = I8K_SMM_GET_FAN;
-    regs.ebx = fan & 0xff;
-    if ((rc=i8k_smm(&regs)) < 0) {
-	return rc;
-    }
-
-    return (regs.eax & 0xff);
+	regs.ebx = fan & 0xff;
+	return i8k_smm(&regs) ? : regs.eax & 0xff;
 }
 
 /*
@@ -240,16 +205,10 @@
  */
 static int i8k_get_fan_speed(int fan)
 {
-    SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
-    int rc;
+	struct smm_regs regs = { .eax = I8K_SMM_GET_SPEED, };
 
-    regs.eax = I8K_SMM_GET_SPEED;
-    regs.ebx = fan & 0xff;
-    if ((rc=i8k_smm(&regs)) < 0) {
-	return rc;
-    }
-
-    return (regs.eax & 0xffff) * I8K_FAN_MULT;
+	regs.ebx = fan & 0xff;
+	return i8k_smm(&regs) ? : (regs.eax & 0xffff) * I8K_FAN_MULT;
 }
 
 /*
@@ -257,532 +216,318 @@
  */
 static int i8k_set_fan(int fan, int speed)
 {
-    SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
-    int rc;
+	struct smm_regs regs = { .eax = I8K_SMM_SET_FAN, };
 
-    speed = (speed < 0) ? 0 : ((speed > I8K_FAN_MAX) ? I8K_FAN_MAX : speed);
+	speed = (speed < 0) ? 0 : ((speed > I8K_FAN_MAX) ? I8K_FAN_MAX : speed);
+	regs.ebx = (fan & 0xff) | (speed << 8);
 
-    regs.eax = I8K_SMM_SET_FAN;
-    regs.ebx = (fan & 0xff) | (speed << 8);
-    if ((rc=i8k_smm(&regs)) < 0) {
-	return rc;
-    }
-
-    return (i8k_get_fan_status(fan));
+	return i8k_smm(&regs) ? : i8k_get_fan_status(fan);
 }
 
 /*
  * Read the cpu temperature.
  */
-static int i8k_get_cpu_temp(void)
+static int i8k_get_temp(int sensor)
 {
-    SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
-    int rc;
-    int temp;
+	struct smm_regs regs = { .eax = I8K_SMM_GET_TEMP, };
+	int rc;
+	int temp;
 
 #ifdef I8K_TEMPERATURE_BUG
-    static int prev = 0;
+	static int prev;
 #endif
+	regs.ebx = sensor & 0xff;
+	if ((rc = i8k_smm(&regs)) < 0)
+		return rc;
 
-    regs.eax = I8K_SMM_GET_TEMP;
-    if ((rc=i8k_smm(&regs)) < 0) {
-	return rc;
-    }
-    temp = regs.eax & 0xff;
+	temp = regs.eax & 0xff;
 
 #ifdef I8K_TEMPERATURE_BUG
-    /*
-     * Sometimes the temperature sensor returns 0x99, which is out of range.
-     * In this case we return (once) the previous cached value. For example:
-     # 1003655137 00000058 00005a4b
-     # 1003655138 00000099 00003a80 <--- 0x99 = 153 degrees
-     # 1003655139 00000054 00005c52
-     */
-    if (temp > I8K_MAX_TEMP) {
-	temp = prev;
-	prev = I8K_MAX_TEMP;
-    } else {
-	prev = temp;
-    }
+	/*
+	 * Sometimes the temperature sensor returns 0x99, which is out of range.
+	 * In this case we return (once) the previous cached value. For example:
+	 # 1003655137 00000058 00005a4b
+	 # 1003655138 00000099 00003a80 <--- 0x99 = 153 degrees
+	 # 1003655139 00000054 00005c52
+	 */
+	if (temp > I8K_MAX_TEMP) {
+		temp = prev;
+		prev = I8K_MAX_TEMP;
+	} else {
+		prev = temp;
+	}
 #endif
 
-    return temp;
+	return temp;
 }
 
-static int i8k_get_dell_signature(void)
+static int i8k_get_dell_signature(int req_fn)
 {
-    SMMRegisters regs = { 0, 0, 0, 0, 0, 0 };
-    int rc;
+	struct smm_regs regs = { .eax = req_fn, };
+	int rc;
 
-    regs.eax = I8K_SMM_GET_DELL_SIG;
-    if ((rc=i8k_smm(&regs)) < 0) {
-	return rc;
-    }
+	if ((rc = i8k_smm(&regs)) < 0)
+		return rc;
 
-    if ((regs.eax == 1145651527) && (regs.edx == 1145392204)) {
-	return 0;
-    } else {
-	return -1;
-    }
+	return regs.eax == 1145651527 && regs.edx == 1145392204 ? 0 : -1;
 }
 
 static int i8k_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
 		     unsigned long arg)
 {
-    int val;
-    int speed;
-    unsigned char buff[16];
-    int __user *argp = (int __user *)arg;
+	int val = 0;
+	int speed;
+	unsigned char buff[16];
+	int __user *argp = (int __user *)arg;
 
-    if (!argp)
-	return -EINVAL;
+	if (!argp)
+		return -EINVAL;
 
-    switch (cmd) {
-    case I8K_BIOS_VERSION:
-	val = i8k_get_bios_version();
-	break;
+	switch (cmd) {
+	case I8K_BIOS_VERSION:
+		val = i8k_get_bios_version();
+		break;
 
-    case I8K_MACHINE_ID:
-	memset(buff, 0, 16);
-	val = i8k_get_serial_number(buff);
-	break;
+	case I8K_MACHINE_ID:
+		memset(buff, 0, 16);
+		strlcpy(buff, i8k_get_dmi_data(DMI_PRODUCT_SERIAL), sizeof(buff));
+		break;
 
-    case I8K_FN_STATUS:
-	val = i8k_get_fn_status();
-	break;
+	case I8K_FN_STATUS:
+		val = i8k_get_fn_status();
+		break;
 
-    case I8K_POWER_STATUS:
-	val = i8k_get_power_status();
-	break;
+	case I8K_POWER_STATUS:
+		val = i8k_get_power_status();
+		break;
 
-    case I8K_GET_TEMP:
-	val = i8k_get_cpu_temp();
-	break;
+	case I8K_GET_TEMP:
+		val = i8k_get_temp(0);
+		break;
 
-    case I8K_GET_SPEED:
-	if (copy_from_user(&val, argp, sizeof(int))) {
-	    return -EFAULT;
+	case I8K_GET_SPEED:
+		if (copy_from_user(&val, argp, sizeof(int)))
+			return -EFAULT;
+
+		val = i8k_get_fan_speed(val);
+		break;
+
+	case I8K_GET_FAN:
+		if (copy_from_user(&val, argp, sizeof(int)))
+			return -EFAULT;
+
+		val = i8k_get_fan_status(val);
+		break;
+
+	case I8K_SET_FAN:
+		if (restricted && !capable(CAP_SYS_ADMIN))
+			return -EPERM;
+
+		if (copy_from_user(&val, argp, sizeof(int)))
+			return -EFAULT;
+
+		if (copy_from_user(&speed, argp + 1, sizeof(int)))
+			return -EFAULT;
+
+		val = i8k_set_fan(val, speed);
+		break;
+
+	default:
+		return -EINVAL;
 	}
-	val = i8k_get_fan_speed(val);
-	break;
 
-    case I8K_GET_FAN:
-	if (copy_from_user(&val, argp, sizeof(int))) {
-	    return -EFAULT;
-	}
-	val = i8k_get_fan_status(val);
-	break;
+	if (val < 0)
+		return val;
 
-    case I8K_SET_FAN:
-	if (restricted && !capable(CAP_SYS_ADMIN)) {
-	    return -EPERM;
-	}
-	if (copy_from_user(&val, argp, sizeof(int))) {
-	    return -EFAULT;
-	}
-	if (copy_from_user(&speed, argp+1, sizeof(int))) {
-	    return -EFAULT;
-	}
-	val = i8k_set_fan(val, speed);
-	break;
+	switch (cmd) {
+	case I8K_BIOS_VERSION:
+		if (copy_to_user(argp, &val, 4))
+			return -EFAULT;
 
-    default:
-	return -EINVAL;
-    }
+		break;
+	case I8K_MACHINE_ID:
+		if (copy_to_user(argp, buff, 16))
+			return -EFAULT;
 
-    if (val < 0) {
-	return val;
-    }
+		break;
+	default:
+		if (copy_to_user(argp, &val, sizeof(int)))
+			return -EFAULT;
 
-    switch (cmd) {
-    case I8K_BIOS_VERSION:
-	if (copy_to_user(argp, &val, 4)) {
-	    return -EFAULT;
+		break;
 	}
-	break;
-    case I8K_MACHINE_ID:
-	if (copy_to_user(argp, buff, 16)) {
-	    return -EFAULT;
-	}
-	break;
-    default:
-	if (copy_to_user(argp, &val, sizeof(int))) {
-	    return -EFAULT;
-	}
-	break;
-    }
 
-    return 0;
+	return 0;
 }
 
 /*
  * Print the information for /proc/i8k.
  */
-static int i8k_get_info(char *buffer, char **start, off_t fpos, int length)
+static int i8k_proc_show(struct seq_file *seq, void *offset)
 {
-    int n, fn_key, cpu_temp, ac_power;
-    int left_fan, right_fan, left_speed, right_speed;
+	int fn_key, cpu_temp, ac_power;
+	int left_fan, right_fan, left_speed, right_speed;
 
-    cpu_temp     = i8k_get_cpu_temp();			/* 11100 µs */
-    left_fan     = i8k_get_fan_status(I8K_FAN_LEFT);	/*   580 µs */
-    right_fan    = i8k_get_fan_status(I8K_FAN_RIGHT);	/*   580 µs */
-    left_speed   = i8k_get_fan_speed(I8K_FAN_LEFT);	/*   580 µs */
-    right_speed  = i8k_get_fan_speed(I8K_FAN_RIGHT);	/*   580 µs */
-    fn_key       = i8k_get_fn_status();			/*   750 µs */
-    if (power_status) {
-	ac_power = i8k_get_power_status();		/* 14700 µs */
-    } else {
-	ac_power = -1;
-    }
+	cpu_temp	= i8k_get_temp(0);			/* 11100 µs */
+	left_fan	= i8k_get_fan_status(I8K_FAN_LEFT);	/*   580 µs */
+	right_fan	= i8k_get_fan_status(I8K_FAN_RIGHT);	/*   580 µs */
+	left_speed	= i8k_get_fan_speed(I8K_FAN_LEFT);	/*   580 µs */
+	right_speed	= i8k_get_fan_speed(I8K_FAN_RIGHT);	/*   580 µs */
+	fn_key		= i8k_get_fn_status();			/*   750 µs */
+	if (power_status)
+		ac_power = i8k_get_power_status();		/* 14700 µs */
+	else
+		ac_power = -1;
 
-    /*
-     * Info:
-     *
-     * 1)  Format version (this will change if format changes)
-     * 2)  BIOS version
-     * 3)  BIOS machine ID
-     * 4)  Cpu temperature
-     * 5)  Left fan status
-     * 6)  Right fan status
-     * 7)  Left fan speed
-     * 8)  Right fan speed
-     * 9)  AC power
-     * 10) Fn Key status
-     */
-    n = sprintf(buffer, "%s %s %s %d %d %d %d %d %d %d\n",
-		I8K_PROC_FMT,
-		bios_version,
-		serial_number,
-		cpu_temp,
-		left_fan,
-		right_fan,
-		left_speed,
-		right_speed,
-		ac_power,
-		fn_key);
-
-    return n;
-}
-
-static ssize_t i8k_read(struct file *f, char __user *buffer, size_t len, loff_t *fpos)
-{
-    int n;
-    char info[128];
-
-    n = i8k_get_info(info, NULL, 0, 128);
-    if (n <= 0) {
-	return n;
-    }
-
-    if (*fpos >= n) {
-	return 0;
-    }
-
-    if ((*fpos + len) >= n) {
-	len = n - *fpos;
-    }
-
-    if (copy_to_user(buffer, info, len) != 0) {
-	return -EFAULT;
-    }
-
-    *fpos += len;
-    return len;
-}
-
-static char* __init string_trim(char *s, int size)
-{
-    int len;
-    char *p;
-
-    if ((len = strlen(s)) > size) {
-	len = size;
-    }
-
-    for (p=s+len-1; len && (*p==' '); len--,p--) {
-	*p = '\0';
-    }
-
-    return s;
-}
-
-/* DMI code, stolen from arch/i386/kernel/dmi_scan.c */
-
-/*
- * |<-- dmi->length -->|
- * |                   |
- * |dmi header    s=N  | string1,\0, ..., stringN,\0, ..., \0
- *                |                       |
- *                +-----------------------+
- */
-static char* __init dmi_string(DMIHeader *dmi, u8 s)
-{
-    u8 *p;
-
-    if (!s) {
-	return "";
-    }
-    s--;
-
-    p = (u8 *)dmi + dmi->length;
-    while (s > 0) {
-	p += strlen(p);
-	p++;
-	s--;
-    }
-
-    return p;
-}
-
-static void __init dmi_decode(DMIHeader *dmi)
-{
-    u8 *data = (u8 *) dmi;
-    char *p;
-
-#ifdef I8K_DEBUG
-    int i;
-    printk("%08x ", (int)data);
-    for (i=0; i<data[1] && i<64; i++) {
-	printk("%02x ", data[i]);
-    }
-    printk("\n");
-#endif
-
-    switch (dmi->type) {
-    case  0:	/* BIOS Information */
-	p = dmi_string(dmi,data[5]);
-	if (*p) {
-	    strlcpy(bios_version, p, sizeof(bios_version));
-	    string_trim(bios_version, sizeof(bios_version));
-	}
-	break;	
-    case 1:	/* System Information */
-	p = dmi_string(dmi,data[4]);
-	if (*p) {
-	    strlcpy(system_vendor, p, sizeof(system_vendor));
-	    string_trim(system_vendor, sizeof(system_vendor));
-	}
-	p = dmi_string(dmi,data[5]);
-	if (*p) {
-	    strlcpy(product_name, p, sizeof(product_name));
-	    string_trim(product_name, sizeof(product_name));
-	}
-	p = dmi_string(dmi,data[7]);
-	if (*p) {
-	    strlcpy(serial_number, p, sizeof(serial_number));
-	    string_trim(serial_number, sizeof(serial_number));
-	}
-	break;
-    }
-}
-
-static int __init dmi_table(u32 base, int len, int num, void (*fn)(DMIHeader*))
-{
-    u8 *buf;
-    u8 *data;
-    DMIHeader *dmi;
-    int i = 1;
-
-    buf = ioremap(base, len);
-    if (buf == NULL) {
-	return -1;
-    }
-    data = buf;
-
-    /*
-     * Stop when we see al the items the table claimed to have
-     * or we run off the end of the table (also happens)
-     */
-    while ((i<num) && ((data-buf) < len)) {
-	dmi = (DMIHeader *)data;
 	/*
-	 * Avoid misparsing crud if the length of the last
-	 * record is crap
+	 * Info:
+	 *
+	 * 1)  Format version (this will change if format changes)
+	 * 2)  BIOS version
+	 * 3)  BIOS machine ID
+	 * 4)  Cpu temperature
+	 * 5)  Left fan status
+	 * 6)  Right fan status
+	 * 7)  Left fan speed
+	 * 8)  Right fan speed
+	 * 9)  AC power
+	 * 10) Fn Key status
 	 */
-	if ((data-buf+dmi->length) >= len) {
-	    break;
-	}
-	fn(dmi);
-	data += dmi->length;
-	/*
-	 * Don't go off the end of the data if there is
-	 * stuff looking like string fill past the end
-	 */
-	while (((data-buf) < len) && (*data || data[1])) {
-	    data++;
-	}
-	data += 2;
-	i++;
-    }
-    iounmap(buf);
-
-    return 0;
+	return seq_printf(seq, "%s %s %s %d %d %d %d %d %d %d\n",
+			  I8K_PROC_FMT,
+			  bios_version,
+			  dmi_get_system_info(DMI_PRODUCT_SERIAL) ? : "N/A",
+			  cpu_temp,
+			  left_fan, right_fan, left_speed, right_speed,
+			  ac_power, fn_key);
 }
 
-static int __init dmi_iterate(void (*decode)(DMIHeader *))
+static int i8k_open_fs(struct inode *inode, struct file *file)
 {
-	unsigned char buf[20];
-	void __iomem *p = ioremap(0xe0000, 0x20000), *q;
-
-	if (!p)
-		return -1;
-
-	for (q = p; q < p + 0x20000; q += 16) {
-		memcpy_fromio(buf, q, 20);
-		if (memcmp(buf, "_DMI_", 5)==0) {
-			u16 num  = buf[13]<<8  | buf[12];
-			u16 len  = buf [7]<<8  | buf [6];
-			u32 base = buf[11]<<24 | buf[10]<<16 | buf[9]<<8 | buf[8];
-#ifdef I8K_DEBUG
-			printk(KERN_INFO "DMI %d.%d present.\n",
-			   buf[14]>>4, buf[14]&0x0F);
-			printk(KERN_INFO "%d structures occupying %d bytes.\n",
-			   buf[13]<<8 | buf[12],
-			   buf [7]<<8 | buf[6]);
-			printk(KERN_INFO "DMI table at 0x%08X.\n",
-			   buf[11]<<24 | buf[10]<<16 | buf[9]<<8 | buf[8]);
-#endif
-			if (dmi_table(base, len, num, decode)==0) {
-				iounmap(p);
-				return 0;
-			}
-		}
-	}
-	iounmap(p);
-	return -1;
+	return single_open(file, i8k_proc_show, NULL);
 }
-/* end of DMI code */
 
-/*
- * Get DMI information.
- */
-static int __init i8k_dmi_probe(void)
-{
-    char **p;
-
-    if (dmi_iterate(dmi_decode) != 0) {
-	printk(KERN_INFO "i8k: unable to get DMI information\n");
-	return -ENODEV;
-    }
-
-    if (strncmp(system_vendor,DELL_SIGNATURE,strlen(DELL_SIGNATURE)) != 0) {
-	printk(KERN_INFO "i8k: not running on a Dell system\n");
-	return -ENODEV;
-    }
-
-    for (p=supported_models; ; p++) {
-	if (!*p) {
-	    printk(KERN_INFO "i8k: unsupported model: %s\n", product_name);
-	    return -ENODEV;
-	}
-	if (strncmp(product_name,*p,strlen(*p)) == 0) {
-	    break;
-	}
-    }
-
-    return 0;
-}
+static struct dmi_system_id __initdata i8k_dmi_table[] = {
+	{
+		.ident = "Dell Inspiron",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron"),
+		},
+	},
+	{
+		.ident = "Dell Latitude",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"),
+		},
+	},
+	{
+		.ident = "Dell Inspiron 2",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron"),
+		},
+	},
+	{
+		.ident = "Dell Latitude 2",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"),
+		},
+	},
+	{ }
+};
 
 /*
  * Probe for the presence of a supported laptop.
  */
 static int __init i8k_probe(void)
 {
-    char buff[4];
-    int version;
-    int smm_found = 0;
+	char buff[4];
+	int version;
 
-    /*
-     * Get DMI information
-     */
-    if (i8k_dmi_probe() != 0) {
-	printk(KERN_INFO "i8k: vendor=%s, model=%s, version=%s\n",
-	       system_vendor, product_name, bios_version);
-    }
-
-    /*
-     * Get SMM Dell signature
-     */
-    if (i8k_get_dell_signature() != 0) {
-	printk(KERN_INFO "i8k: unable to get SMM Dell signature\n");
-    } else {
-	smm_found = 1;
-    }
-
-    /*
-     * Get SMM BIOS version.
-     */
-    version = i8k_get_bios_version();
-    if (version <= 0) {
-	printk(KERN_INFO "i8k: unable to get SMM BIOS version\n");
-    } else {
-	smm_found = 1;
-	buff[0] = (version >> 16) & 0xff;
-	buff[1] = (version >>  8) & 0xff;
-	buff[2] = (version)       & 0xff;
-	buff[3] = '\0';
 	/*
-	 * If DMI BIOS version is unknown use SMM BIOS version.
+	 * Get DMI information
 	 */
-	if (bios_version[0] == '?') {
-	    strcpy(bios_version, buff);
+	if (!dmi_check_system(i8k_dmi_table)) {
+		if (!ignore_dmi && !force)
+			return -ENODEV;
+
+		printk(KERN_INFO "i8k: not running on a supported Dell system.\n");
+		printk(KERN_INFO "i8k: vendor=%s, model=%s, version=%s\n",
+			i8k_get_dmi_data(DMI_SYS_VENDOR),
+			i8k_get_dmi_data(DMI_PRODUCT_NAME),
+			i8k_get_dmi_data(DMI_BIOS_VERSION));
 	}
+
+	strlcpy(bios_version, i8k_get_dmi_data(DMI_BIOS_VERSION), sizeof(bios_version));
+
 	/*
-	 * Check if the two versions match.
+	 * Get SMM Dell signature
 	 */
-	if (strncmp(buff,bios_version,sizeof(bios_version)) != 0) {
-	    printk(KERN_INFO "i8k: BIOS version mismatch: %s != %s\n",
-		   buff, bios_version);
+	if (i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG1) &&
+	    i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG2)) {
+		printk(KERN_ERR "i8k: unable to get SMM Dell signature\n");
+		if (!force)
+			return -ENODEV;
 	}
-    }
 
-    if (!smm_found && !force) {
-	return -ENODEV;
-    }
+	/*
+	 * Get SMM BIOS version.
+	 */
+	version = i8k_get_bios_version();
+	if (version <= 0) {
+		printk(KERN_WARNING "i8k: unable to get SMM BIOS version\n");
+	} else {
+		buff[0] = (version >> 16) & 0xff;
+		buff[1] = (version >> 8) & 0xff;
+		buff[2] = (version) & 0xff;
+		buff[3] = '\0';
+		/*
+		 * If DMI BIOS version is unknown use SMM BIOS version.
+		 */
+		if (!dmi_get_system_info(DMI_BIOS_VERSION))
+			strlcpy(bios_version, buff, sizeof(bios_version));
 
-    return 0;
+		/*
+		 * Check if the two versions match.
+		 */
+		if (strncmp(buff, bios_version, sizeof(bios_version)) != 0)
+			printk(KERN_WARNING "i8k: BIOS version mismatch: %s != %s\n",
+				buff, bios_version);
+	}
+
+	return 0;
 }
 
-#ifdef MODULE
-static
-#endif
-int __init i8k_init(void)
+static int __init i8k_init(void)
 {
-    struct proc_dir_entry *proc_i8k;
+	struct proc_dir_entry *proc_i8k;
 
-    /* Are we running on an supported laptop? */
-    if (i8k_probe() != 0) {
-	return -ENODEV;
-    }
+	/* Are we running on an supported laptop? */
+	if (i8k_probe())
+		return -ENODEV;
 
-    /* Register the proc entry */
-    proc_i8k = create_proc_info_entry("i8k", 0, NULL, i8k_get_info);
-    if (!proc_i8k) {
-	return -ENOENT;
-    }
-    proc_i8k->proc_fops = &i8k_fops;
-    proc_i8k->owner = THIS_MODULE;
+	/* Register the proc entry */
+	proc_i8k = create_proc_entry("i8k", 0, NULL);
+	if (!proc_i8k)
+		return -ENOENT;
 
-    printk(KERN_INFO
-	   "Dell laptop SMM driver v%s Massimo Dal Zotto (dz@debian.org)\n",
-	   I8K_VERSION);
+	proc_i8k->proc_fops = &i8k_fops;
+	proc_i8k->owner = THIS_MODULE;
 
-    return 0;
+	printk(KERN_INFO
+	       "Dell laptop SMM driver v%s Massimo Dal Zotto (dz@debian.org)\n",
+	       I8K_VERSION);
+
+	return 0;
 }
 
-#ifdef MODULE
-int init_module(void)
+static void __exit i8k_exit(void)
 {
-    return i8k_init();
+	remove_proc_entry("i8k", NULL);
 }
 
-void cleanup_module(void)
-{
-    /* Remove the proc entry */
-    remove_proc_entry("i8k", NULL);
-
-    printk(KERN_INFO "i8k: module unloaded\n");
-}
-#endif
-
-/* end of file */
+module_init(i8k_init);
+module_exit(i8k_exit);
diff --git a/drivers/char/ip2/i2cmd.c b/drivers/char/ip2/i2cmd.c
index fd299d6..cb8f419 100644
--- a/drivers/char/ip2/i2cmd.c
+++ b/drivers/char/ip2/i2cmd.c
@@ -97,7 +97,7 @@
 //static UCHAR ct44[]={ 2, BTH,     0x2C,0                   }; // MS PING
 //static UCHAR ct45[]={ 1, BTH,     0x2D                     }; // HOTENAB
 //static UCHAR ct46[]={ 1, BTH,     0x2E                     }; // HOTDSAB
-static UCHAR ct47[] = { 7, BTH,     0x2F,0,0,0,0,0,0         }; // UNIX FLAGS
+//static UCHAR ct47[]={ 7, BTH,     0x2F,0,0,0,0,0,0         }; // UNIX FLAGS
 //static UCHAR ct48[]={ 1, BTH,     0x30                     }; // DSRFLOWENAB
 //static UCHAR ct49[]={ 1, BTH,     0x31                     }; // DSRFLOWDSAB
 //static UCHAR ct50[]={ 1, BTH,     0x32                     }; // DTRFLOWENAB
@@ -162,6 +162,7 @@
 // This routine sets the parameters of command 47 and returns a pointer to the
 // appropriate structure.
 //******************************************************************************
+#if 0
 cmdSyntaxPtr
 i2cmdUnixFlags(unsigned short iflag,unsigned short cflag,unsigned short lflag)
 {
@@ -175,6 +176,7 @@
 	pCM->cmd[6] = (unsigned char) (lflag >> 8);
 	return pCM;
 }
+#endif  /*  0  */
 
 //******************************************************************************
 // Function:   i2cmdBaudDef(which, rate)
@@ -187,7 +189,7 @@
 // This routine sets the parameters of commands 54 or 55 (according to the
 // argument which), and returns a pointer to the appropriate structure.
 //******************************************************************************
-cmdSyntaxPtr
+static cmdSyntaxPtr
 i2cmdBaudDef(int which, unsigned short rate)
 {
 	cmdSyntaxPtr pCM;
diff --git a/drivers/char/ip2/i2cmd.h b/drivers/char/ip2/i2cmd.h
index c41728a..baa4e72 100644
--- a/drivers/char/ip2/i2cmd.h
+++ b/drivers/char/ip2/i2cmd.h
@@ -64,16 +64,6 @@
 						// directly from user-level
 #define VAR 0x10        // This command is of variable length!
 
-//-----------------------------------
-// External declarations for i2cmd.c
-//-----------------------------------
-// Routine to set up parameters for the "define hot-key sequence" command. Since
-// there is more than one parameter to assign, we must use a function rather
-// than a macro (used usually).
-//
-extern cmdSyntaxPtr i2cmdUnixFlags(USHORT iflag,USHORT cflag,USHORT lflag);
-extern cmdSyntaxPtr i2cmdBaudDef(int which, USHORT rate);
-
 // Declarations for the global arrays used to bear the commands and their
 // arguments.
 //
@@ -433,6 +423,7 @@
 #define CMD_HOT_ENAB (cmdSyntaxPtr)(ct45) // Enable Hot-key checking
 #define CMD_HOT_DSAB (cmdSyntaxPtr)(ct46) // Disable Hot-key checking
 
+#if 0
 // COMMAND 47: Send Protocol info via Unix flags:
 // iflag = Unix tty t_iflag
 // cflag = Unix tty t_cflag
@@ -441,6 +432,7 @@
 // within these flags
 //
 #define CMD_UNIX_FLAGS(iflag,cflag,lflag) i2cmdUnixFlags(iflag,cflag,lflag)
+#endif  /*  0  */
 
 #define CMD_DSRFL_ENAB  (cmdSyntaxPtr)(ct48) // Enable  DSR receiver ctrl
 #define CMD_DSRFL_DSAB  (cmdSyntaxPtr)(ct49) // Disable DSR receiver ctrl
diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c
index fca9a97..cf0cd58 100644
--- a/drivers/char/ip2main.c
+++ b/drivers/char/ip2main.c
@@ -302,7 +302,7 @@
 static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0};
 
 /* for sysfs class support */
-static struct class_simple *ip2_class;
+static struct class *ip2_class;
 
 // Some functions to keep track of what irq's we have
 
@@ -414,9 +414,9 @@
 			iiResetDelay( i2BoardPtrTable[i] );
 			/* free io addresses and Tibet */
 			release_region( ip2config.addr[i], 8 );
-			class_simple_device_remove(MKDEV(IP2_IPL_MAJOR, 4 * i)); 
+			class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i));
 			devfs_remove("ip2/ipl%d", i);
-			class_simple_device_remove(MKDEV(IP2_IPL_MAJOR, 4 * i + 1));
+			class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i + 1));
 			devfs_remove("ip2/stat%d", i);
 		}
 		/* Disable and remove interrupt handler. */
@@ -425,7 +425,7 @@
 			clear_requested_irq( ip2config.irq[i]);
 		}
 	}
-	class_simple_destroy(ip2_class);
+	class_destroy(ip2_class);
 	devfs_remove("ip2");
 	if ( ( err = tty_unregister_driver ( ip2_tty_driver ) ) ) {
 		printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", err);
@@ -700,7 +700,7 @@
 		printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err );
 	} else {
 		/* create the sysfs class */
-		ip2_class = class_simple_create(THIS_MODULE, "ip2");
+		ip2_class = class_create(THIS_MODULE, "ip2");
 		if (IS_ERR(ip2_class)) {
 			err = PTR_ERR(ip2_class);
 			goto out_chrdev;	
@@ -722,25 +722,25 @@
 			}
 
 			if ( NULL != ( pB = i2BoardPtrTable[i] ) ) {
-				class_simple_device_add(ip2_class, MKDEV(IP2_IPL_MAJOR, 
+				class_device_create(ip2_class, MKDEV(IP2_IPL_MAJOR,
 						4 * i), NULL, "ipl%d", i);
 				err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i),
 						S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
 						"ip2/ipl%d", i);
 				if (err) {
-					class_simple_device_remove(MKDEV(IP2_IPL_MAJOR, 
-						4 * i));
+					class_device_destroy(ip2_class,
+						MKDEV(IP2_IPL_MAJOR, 4 * i));
 					goto out_class;
 				}
 
-				class_simple_device_add(ip2_class, MKDEV(IP2_IPL_MAJOR, 
+				class_device_create(ip2_class, MKDEV(IP2_IPL_MAJOR,
 						4 * i + 1), NULL, "stat%d", i);
 				err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
 						S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
 						"ip2/stat%d", i);
 				if (err) {
-					class_simple_device_remove(MKDEV(IP2_IPL_MAJOR, 
-						4 * i + 1));
+					class_device_destroy(ip2_class,
+						MKDEV(IP2_IPL_MAJOR, 4 * i + 1));
 					goto out_class;
 				}
 
@@ -798,7 +798,7 @@
 	goto out;
 
 out_class:
-	class_simple_destroy(ip2_class);
+	class_destroy(ip2_class);
 out_chrdev:
 	unregister_chrdev(IP2_IPL_MAJOR, "ip2");
 out:
@@ -2691,16 +2691,6 @@
 		pCh->flags	|= ASYNC_CHECK_CD;
 	}
 
-#ifdef XXX
-do_flags_thing:	// This is a test, we don't do the flags thing
-	
-	if ( (cflag & CRTSCTS) ) {
-		cflag |= 014000000000;
-	}
-	i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, 
-				CMD_UNIX_FLAGS(iflag,cflag,lflag));
-#endif
-		
 service_it:
 	i2DrainOutput( pCh, 100 );		
 }
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index 6dc765d..e0a5357 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -45,6 +45,7 @@
 #include <asm/semaphore.h>
 #include <linux/init.h>
 #include <linux/device.h>
+#include <linux/compat.h>
 
 #define IPMI_DEVINTF_VERSION "v33"
 
@@ -500,10 +501,205 @@
 	return rv;
 }
 
+#ifdef CONFIG_COMPAT
+
+/*
+ * The following code contains code for supporting 32-bit compatible
+ * ioctls on 64-bit kernels.  This allows running 32-bit apps on the
+ * 64-bit kernel
+ */
+#define COMPAT_IPMICTL_SEND_COMMAND	\
+	_IOR(IPMI_IOC_MAGIC, 13, struct compat_ipmi_req)
+#define COMPAT_IPMICTL_SEND_COMMAND_SETTIME	\
+	_IOR(IPMI_IOC_MAGIC, 21, struct compat_ipmi_req_settime)
+#define COMPAT_IPMICTL_RECEIVE_MSG	\
+	_IOWR(IPMI_IOC_MAGIC, 12, struct compat_ipmi_recv)
+#define COMPAT_IPMICTL_RECEIVE_MSG_TRUNC	\
+	_IOWR(IPMI_IOC_MAGIC, 11, struct compat_ipmi_recv)
+
+struct compat_ipmi_msg {
+	u8		netfn;
+	u8		cmd;
+	u16		data_len;
+	compat_uptr_t	data;
+};
+
+struct compat_ipmi_req {
+	compat_uptr_t		addr;
+	compat_uint_t		addr_len;
+	compat_long_t		msgid;
+	struct compat_ipmi_msg	msg;
+};
+
+struct compat_ipmi_recv {
+	compat_int_t		recv_type;
+	compat_uptr_t		addr;
+	compat_uint_t		addr_len;
+	compat_long_t		msgid;
+	struct compat_ipmi_msg	msg;
+};
+
+struct compat_ipmi_req_settime {
+	struct compat_ipmi_req	req;
+	compat_int_t		retries;
+	compat_uint_t		retry_time_ms;
+};
+
+/*
+ * Define some helper functions for copying IPMI data
+ */
+static long get_compat_ipmi_msg(struct ipmi_msg *p64,
+				struct compat_ipmi_msg __user *p32)
+{
+	compat_uptr_t tmp;
+
+	if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
+			__get_user(p64->netfn, &p32->netfn) ||
+			__get_user(p64->cmd, &p32->cmd) ||
+			__get_user(p64->data_len, &p32->data_len) ||
+			__get_user(tmp, &p32->data))
+		return -EFAULT;
+	p64->data = compat_ptr(tmp);
+	return 0;
+}
+
+static long put_compat_ipmi_msg(struct ipmi_msg *p64,
+				struct compat_ipmi_msg __user *p32)
+{
+	if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) ||
+			__put_user(p64->netfn, &p32->netfn) ||
+			__put_user(p64->cmd, &p32->cmd) ||
+			__put_user(p64->data_len, &p32->data_len))
+		return -EFAULT;
+	return 0;
+}
+
+static long get_compat_ipmi_req(struct ipmi_req *p64,
+				struct compat_ipmi_req __user *p32)
+{
+
+	compat_uptr_t	tmp;
+
+	if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
+			__get_user(tmp, &p32->addr) ||
+			__get_user(p64->addr_len, &p32->addr_len) ||
+			__get_user(p64->msgid, &p32->msgid) ||
+			get_compat_ipmi_msg(&p64->msg, &p32->msg))
+		return -EFAULT;
+	p64->addr = compat_ptr(tmp);
+	return 0;
+}
+
+static long get_compat_ipmi_req_settime(struct ipmi_req_settime *p64,
+		struct compat_ipmi_req_settime __user *p32)
+{
+	if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
+			get_compat_ipmi_req(&p64->req, &p32->req) ||
+			__get_user(p64->retries, &p32->retries) ||
+			__get_user(p64->retry_time_ms, &p32->retry_time_ms))
+		return -EFAULT;
+	return 0;
+}
+
+static long get_compat_ipmi_recv(struct ipmi_recv *p64,
+				 struct compat_ipmi_recv __user *p32)
+{
+	compat_uptr_t tmp;
+
+	if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
+			__get_user(p64->recv_type, &p32->recv_type) ||
+			__get_user(tmp, &p32->addr) ||
+			__get_user(p64->addr_len, &p32->addr_len) ||
+			__get_user(p64->msgid, &p32->msgid) ||
+			get_compat_ipmi_msg(&p64->msg, &p32->msg))
+		return -EFAULT;
+	p64->addr = compat_ptr(tmp);
+	return 0;
+}
+
+static long put_compat_ipmi_recv(struct ipmi_recv *p64,
+				 struct compat_ipmi_recv __user *p32)
+{
+	if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) ||
+			__put_user(p64->recv_type, &p32->recv_type) ||
+			__put_user(p64->addr_len, &p32->addr_len) ||
+			__put_user(p64->msgid, &p32->msgid) ||
+			put_compat_ipmi_msg(&p64->msg, &p32->msg))
+		return -EFAULT;
+	return 0;
+}
+
+/*
+ * Handle compatibility ioctls
+ */
+static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
+			      unsigned long arg)
+{
+	int rc;
+	struct ipmi_file_private *priv = filep->private_data;
+
+	switch(cmd) {
+	case COMPAT_IPMICTL_SEND_COMMAND:
+	{
+		struct ipmi_req	rp;
+
+		if (get_compat_ipmi_req(&rp, compat_ptr(arg)))
+			return -EFAULT;
+
+		return handle_send_req(priv->user, &rp,
+				priv->default_retries,
+				priv->default_retry_time_ms);
+	}
+	case COMPAT_IPMICTL_SEND_COMMAND_SETTIME:
+	{
+		struct ipmi_req_settime	sp;
+
+		if (get_compat_ipmi_req_settime(&sp, compat_ptr(arg)))
+			return -EFAULT;
+
+		return handle_send_req(priv->user, &sp.req,
+				sp.retries, sp.retry_time_ms);
+	}
+	case COMPAT_IPMICTL_RECEIVE_MSG:
+	case COMPAT_IPMICTL_RECEIVE_MSG_TRUNC:
+	{
+		struct ipmi_recv   *precv64, recv64;
+
+		if (get_compat_ipmi_recv(&recv64, compat_ptr(arg)))
+			return -EFAULT;
+
+		precv64 = compat_alloc_user_space(sizeof(recv64));
+		if (copy_to_user(precv64, &recv64, sizeof(recv64)))
+			return -EFAULT;
+
+		rc = ipmi_ioctl(filep->f_dentry->d_inode, filep,
+				((cmd == COMPAT_IPMICTL_RECEIVE_MSG)
+				 ? IPMICTL_RECEIVE_MSG
+				 : IPMICTL_RECEIVE_MSG_TRUNC),
+				(long) precv64);
+		if (rc != 0)
+			return rc;
+
+		if (copy_from_user(&recv64, precv64, sizeof(recv64)))
+			return -EFAULT;
+
+		if (put_compat_ipmi_recv(&recv64, compat_ptr(arg)))
+			return -EFAULT;
+
+		return rc;
+	}
+	default:
+		return ipmi_ioctl(filep->f_dentry->d_inode, filep, cmd, arg);
+	}
+}
+#endif
 
 static struct file_operations ipmi_fops = {
 	.owner		= THIS_MODULE,
 	.ioctl		= ipmi_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl   = compat_ipmi_ioctl,
+#endif
 	.open		= ipmi_open,
 	.release	= ipmi_release,
 	.fasync		= ipmi_fasync,
@@ -520,7 +716,7 @@
 		 " interface.  Other values will set the major device number"
 		 " to that value.");
 
-static struct class_simple *ipmi_class;
+static struct class *ipmi_class;
 
 static void ipmi_new_smi(int if_num)
 {
@@ -529,12 +725,12 @@
 	devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR,
 		      "ipmidev/%d", if_num);
 
-	class_simple_device_add(ipmi_class, dev, NULL, "ipmi%d", if_num);
+	class_device_create(ipmi_class, dev, NULL, "ipmi%d", if_num);
 }
 
 static void ipmi_smi_gone(int if_num)
 {
-	class_simple_device_remove(MKDEV(ipmi_major, if_num));
+	class_device_destroy(ipmi_class, MKDEV(ipmi_major, if_num));
 	devfs_remove("ipmidev/%d", if_num);
 }
 
@@ -555,7 +751,7 @@
 	printk(KERN_INFO "ipmi device interface version "
 	       IPMI_DEVINTF_VERSION "\n");
 
-	ipmi_class = class_simple_create(THIS_MODULE, "ipmi");
+	ipmi_class = class_create(THIS_MODULE, "ipmi");
 	if (IS_ERR(ipmi_class)) {
 		printk(KERN_ERR "ipmi: can't register device class\n");
 		return PTR_ERR(ipmi_class);
@@ -563,7 +759,7 @@
 
 	rv = register_chrdev(ipmi_major, DEVICE_NAME, &ipmi_fops);
 	if (rv < 0) {
-		class_simple_destroy(ipmi_class);
+		class_destroy(ipmi_class);
 		printk(KERN_ERR "ipmi: can't get major %d\n", ipmi_major);
 		return rv;
 	}
@@ -577,7 +773,7 @@
 	rv = ipmi_smi_watcher_register(&smi_watcher);
 	if (rv) {
 		unregister_chrdev(ipmi_major, DEVICE_NAME);
-		class_simple_destroy(ipmi_class);
+		class_destroy(ipmi_class);
 		printk(KERN_WARNING "ipmi: can't register smi watcher\n");
 		return rv;
 	}
@@ -588,7 +784,7 @@
 
 static __exit void cleanup_ipmi(void)
 {
-	class_simple_destroy(ipmi_class);
+	class_destroy(ipmi_class);
 	ipmi_smi_watcher_unregister(&smi_watcher);
 	devfs_remove(DEVICE_NAME);
 	unregister_chrdev(ipmi_major, DEVICE_NAME);
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index d7fb452..1813d0d 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -54,7 +54,9 @@
 
 static int initialized = 0;
 
-static struct proc_dir_entry *proc_ipmi_root = NULL;
+#ifdef CONFIG_PROC_FS
+struct proc_dir_entry *proc_ipmi_root = NULL;
+#endif /* CONFIG_PROC_FS */
 
 #define MAX_EVENTS_IN_QUEUE	25
 
@@ -124,11 +126,13 @@
 	unsigned char protocol;
 };
 
+#ifdef CONFIG_PROC_FS
 struct ipmi_proc_entry
 {
 	char                   *name;
 	struct ipmi_proc_entry *next;
 };
+#endif
 
 #define IPMI_IPMB_NUM_SEQ	64
 #define IPMI_MAX_CHANNELS       8
@@ -156,10 +160,13 @@
 	struct ipmi_smi_handlers *handlers;
 	void                     *send_info;
 
+#ifdef CONFIG_PROC_FS
 	/* A list of proc entries for this interface.  This does not
 	   need a lock, only one thread creates it and only one thread
 	   destroys it. */
+	spinlock_t             proc_entry_lock;
 	struct ipmi_proc_entry *proc_entries;
+#endif
 
 	/* A table of sequence numbers for this interface.  We use the
            sequence numbers for IPMB messages that go out of the
@@ -641,7 +648,7 @@
 		return -ENOMEM;
 
 	down_read(&interfaces_sem);
-	if ((if_num > MAX_IPMI_INTERFACES) || ipmi_interfaces[if_num] == NULL)
+	if ((if_num >= MAX_IPMI_INTERFACES) || ipmi_interfaces[if_num] == NULL)
 	{
 		rv = -EINVAL;
 		goto out_unlock;
@@ -1470,8 +1477,9 @@
 			    read_proc_t *read_proc, write_proc_t *write_proc,
 			    void *data, struct module *owner)
 {
-	struct proc_dir_entry  *file;
 	int                    rv = 0;
+#ifdef CONFIG_PROC_FS
+	struct proc_dir_entry  *file;
 	struct ipmi_proc_entry *entry;
 
 	/* Create a list element. */
@@ -1497,10 +1505,13 @@
 		file->write_proc = write_proc;
 		file->owner = owner;
 
+		spin_lock(&smi->proc_entry_lock);
 		/* Stick it on the list. */
 		entry->next = smi->proc_entries;
 		smi->proc_entries = entry;
+		spin_unlock(&smi->proc_entry_lock);
 	}
+#endif /* CONFIG_PROC_FS */
 
 	return rv;
 }
@@ -1509,6 +1520,7 @@
 {
 	int rv = 0;
 
+#ifdef CONFIG_PROC_FS
 	sprintf(smi->proc_dir_name, "%d", num);
 	smi->proc_dir = proc_mkdir(smi->proc_dir_name, proc_ipmi_root);
 	if (!smi->proc_dir)
@@ -1531,14 +1543,17 @@
 		rv = ipmi_smi_add_proc_entry(smi, "version",
 					     version_file_read_proc, NULL,
 					     smi, THIS_MODULE);
+#endif /* CONFIG_PROC_FS */
 
 	return rv;
 }
 
 static void remove_proc_entries(ipmi_smi_t smi)
 {
+#ifdef CONFIG_PROC_FS
 	struct ipmi_proc_entry *entry;
 
+	spin_lock(&smi->proc_entry_lock);
 	while (smi->proc_entries) {
 		entry = smi->proc_entries;
 		smi->proc_entries = entry->next;
@@ -1547,7 +1562,9 @@
 		kfree(entry->name);
 		kfree(entry);
 	}
+	spin_unlock(&smi->proc_entry_lock);
 	remove_proc_entry(smi->proc_dir_name, proc_ipmi_root);
+#endif /* CONFIG_PROC_FS */
 }
 
 static int
@@ -1694,6 +1711,9 @@
 				new_intf->seq_table[j].seqid = 0;
 			}
 			new_intf->curr_seq = 0;
+#ifdef CONFIG_PROC_FS
+			spin_lock_init(&(new_intf->proc_entry_lock));
+#endif
 			spin_lock_init(&(new_intf->waiting_msgs_lock));
 			INIT_LIST_HEAD(&(new_intf->waiting_msgs));
 			spin_lock_init(&(new_intf->events_lock));
@@ -2747,16 +2767,13 @@
    the queue and this silliness can go away. */
 #define IPMI_REQUEST_EV_TIME	(1000 / (IPMI_TIMEOUT_TIME))
 
-static volatile int stop_operation = 0;
-static volatile int timer_stopped = 0;
+static atomic_t stop_operation;
 static unsigned int ticks_to_req_ev = IPMI_REQUEST_EV_TIME;
 
 static void ipmi_timeout(unsigned long data)
 {
-	if (stop_operation) {
-		timer_stopped = 1;
+	if (atomic_read(&stop_operation))
 		return;
-	}
 
 	ticks_to_req_ev--;
 	if (ticks_to_req_ev == 0) {
@@ -2766,8 +2783,7 @@
 
 	ipmi_timeout_handler(IPMI_TIMEOUT_TIME);
 
-	ipmi_timer.expires += IPMI_TIMEOUT_JIFFIES;
-	add_timer(&ipmi_timer);
+	mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES);
 }
 
 
@@ -3089,6 +3105,7 @@
 		ipmi_interfaces[i] = NULL;
 	}
 
+#ifdef CONFIG_PROC_FS
 	proc_ipmi_root = proc_mkdir("ipmi", NULL);
 	if (!proc_ipmi_root) {
 	    printk(KERN_ERR PFX "Unable to create IPMI proc dir");
@@ -3096,6 +3113,7 @@
 	}
 
 	proc_ipmi_root->owner = THIS_MODULE;
+#endif /* CONFIG_PROC_FS */
 
 	init_timer(&ipmi_timer);
 	ipmi_timer.data = 0;
@@ -3130,13 +3148,12 @@
 
 	/* Tell the timer to stop, then wait for it to stop.  This avoids
 	   problems with race conditions removing the timer here. */
-	stop_operation = 1;
-	while (!timer_stopped) {
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(1);
-	}
+	atomic_inc(&stop_operation);
+	del_timer_sync(&ipmi_timer);
 
+#ifdef CONFIG_PROC_FS
 	remove_proc_entry(proc_ipmi_root->name, &proc_root);
+#endif /* CONFIG_PROC_FS */
 
 	initialized = 0;
 
@@ -3177,4 +3194,5 @@
 EXPORT_SYMBOL(ipmi_set_my_LUN);
 EXPORT_SYMBOL(ipmi_get_my_LUN);
 EXPORT_SYMBOL(ipmi_smi_add_proc_entry);
+EXPORT_SYMBOL(proc_ipmi_root);
 EXPORT_SYMBOL(ipmi_user_set_run_to_completion);
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index cb5cdc6..f951c30 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -31,10 +31,13 @@
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
-#include <asm/semaphore.h>
-#include <linux/kdev_t.h>
+#include <linux/config.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/proc_fs.h>
 #include <linux/string.h>
+#include <linux/completion.h>
+#include <linux/kdev_t.h>
 #include <linux/ipmi.h>
 #include <linux/ipmi_smi.h>
 
@@ -44,6 +47,18 @@
 /* Where to we insert our poweroff function? */
 extern void (*pm_power_off)(void);
 
+/* Definitions for controlling power off (if the system supports it).  It
+ * conveniently matches the IPMI chassis control values. */
+#define IPMI_CHASSIS_POWER_DOWN		0	/* power down, the default. */
+#define IPMI_CHASSIS_POWER_CYCLE	0x02	/* power cycle */
+
+/* the IPMI data command */
+static int poweroff_control = IPMI_CHASSIS_POWER_DOWN;
+
+/* parameter definition to allow user to flag power cycle */
+module_param(poweroff_control, int, IPMI_CHASSIS_POWER_DOWN);
+MODULE_PARM_DESC(poweroff_control, " Set to 2 to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down.");
+
 /* Stuff from the get device id command. */
 static unsigned int mfg_id;
 static unsigned int prod_id;
@@ -75,10 +90,10 @@
 
 static void receive_handler(struct ipmi_recv_msg *recv_msg, void *handler_data)
 {
-	struct semaphore *sem = recv_msg->user_msg_data;
+	struct completion *comp = recv_msg->user_msg_data;
 
-	if (sem)
-		up(sem);
+	if (comp)
+		complete(comp);
 }
 
 static struct ipmi_user_hndl ipmi_poweroff_handler =
@@ -91,27 +106,27 @@
 					  struct ipmi_addr       *addr,
 					  struct kernel_ipmi_msg *send_msg)
 {
-	int              rv;
-	struct semaphore sem;
+	int               rv;
+	struct completion comp;
 
-	sema_init (&sem, 0);
+	init_completion(&comp);
 
-	rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, &sem,
+	rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, &comp,
 				      &halt_smi_msg, &halt_recv_msg, 0);
 	if (rv)
 		return rv;
 
-	down (&sem);
+	wait_for_completion(&comp);
 
 	return halt_recv_msg.msg.data[0];
 }
 
-/* We are in run-to-completion mode, no semaphore is desired. */
+/* We are in run-to-completion mode, no completion is desired. */
 static int ipmi_request_in_rc_mode(ipmi_user_t            user,
 				   struct ipmi_addr       *addr,
 				   struct kernel_ipmi_msg *send_msg)
 {
-	int              rv;
+	int rv;
 
 	rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, NULL,
 				      &halt_smi_msg, &halt_recv_msg, 0);
@@ -349,26 +364,38 @@
         smi_addr.channel = IPMI_BMC_CHANNEL;
         smi_addr.lun = 0;
 
-	printk(KERN_INFO PFX "Powering down via IPMI chassis control command\n");
+ powercyclefailed:
+	printk(KERN_INFO PFX "Powering %s via IPMI chassis control command\n",
+		((poweroff_control != IPMI_CHASSIS_POWER_CYCLE) ? "down" : "cycle"));
 
 	/*
 	 * Power down
 	 */
 	send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST;
 	send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD;
-	data[0] = 0; /* Power down */
+	data[0] = poweroff_control;
 	send_msg.data = data;
 	send_msg.data_len = sizeof(data);
 	rv = ipmi_request_in_rc_mode(user,
 				     (struct ipmi_addr *) &smi_addr,
 				     &send_msg);
 	if (rv) {
-		printk(KERN_ERR PFX "Unable to send chassis powerdown message,"
-		       " IPMI error 0x%x\n", rv);
-		goto out;
+		switch (poweroff_control) {
+			case IPMI_CHASSIS_POWER_CYCLE:
+				/* power cycle failed, default to power down */
+				printk(KERN_ERR PFX "Unable to send chassis power " \
+					"cycle message, IPMI error 0x%x\n", rv);
+				poweroff_control = IPMI_CHASSIS_POWER_DOWN;
+				goto powercyclefailed;
+
+			case IPMI_CHASSIS_POWER_DOWN:
+			default:
+				printk(KERN_ERR PFX "Unable to send chassis power " \
+					"down message, IPMI error 0x%x\n", rv);
+				break;
+		}
 	}
 
- out:
 	return;
 }
 
@@ -430,7 +457,8 @@
 	if (ready)
 		return;
 
-	rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, NULL, &ipmi_user);
+	rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, NULL,
+			      &ipmi_user);
 	if (rv) {
 		printk(KERN_ERR PFX "could not create IPMI user, error %d\n",
 		       rv);
@@ -509,21 +537,84 @@
 };
 
 
+#ifdef CONFIG_PROC_FS
+/* displays properties to proc */
+static int proc_read_chassctrl(char *page, char **start, off_t off, int count,
+			       int *eof, void *data)
+{
+	return sprintf(page, "%d\t[ 0=powerdown 2=powercycle ]\n",
+			poweroff_control);
+}
+
+/* process property writes from proc */
+static int proc_write_chassctrl(struct file *file, const char *buffer,
+			        unsigned long count, void *data)
+{
+	int          rv = count;
+	unsigned int newval = 0;
+
+	sscanf(buffer, "%d", &newval);
+	switch (newval) {
+		case IPMI_CHASSIS_POWER_CYCLE:
+			printk(KERN_INFO PFX "power cycle is now enabled\n");
+			poweroff_control = newval;
+			break;
+
+		case IPMI_CHASSIS_POWER_DOWN:
+			poweroff_control = IPMI_CHASSIS_POWER_DOWN;
+			break;
+
+		default:
+			rv = -EINVAL;
+			break;
+	}
+
+	return rv;
+}
+#endif /* CONFIG_PROC_FS */
+
 /*
  * Startup and shutdown functions.
  */
 static int ipmi_poweroff_init (void)
 {
-	int rv;
+	int                   rv;
+	struct proc_dir_entry *file;
 
 	printk ("Copyright (C) 2004 MontaVista Software -"
 		" IPMI Powerdown via sys_reboot version "
 		IPMI_POWEROFF_VERSION ".\n");
 
-	rv = ipmi_smi_watcher_register(&smi_watcher);
-	if (rv)
-		printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv);
+	switch (poweroff_control) {
+		case IPMI_CHASSIS_POWER_CYCLE:
+			printk(KERN_INFO PFX "Power cycle is enabled.\n");
+			break;
 
+		case IPMI_CHASSIS_POWER_DOWN:
+		default:
+			poweroff_control = IPMI_CHASSIS_POWER_DOWN;
+			break;
+	}
+
+	rv = ipmi_smi_watcher_register(&smi_watcher);
+	if (rv) {
+		printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv);
+		goto out_err;
+	}
+
+#ifdef CONFIG_PROC_FS
+	file = create_proc_entry("poweroff_control", 0, proc_ipmi_root);
+	if (!file) {
+		printk(KERN_ERR PFX "Unable to create proc power control\n");
+	} else {
+		file->nlink = 1;
+		file->read_proc = proc_read_chassctrl;
+		file->write_proc = proc_write_chassctrl;
+		file->owner = THIS_MODULE;
+	}
+#endif
+
+ out_err:
 	return rv;
 }
 
@@ -532,6 +623,10 @@
 {
 	int rv;
 
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry("poweroff_control", proc_ipmi_root);
+#endif
+
 	ipmi_smi_watcher_unregister(&smi_watcher);
 
 	if (ready) {
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 601c7fc..1bbf507 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -1756,7 +1756,7 @@
 }
 
 
-static int __init register_ioregion(void)
+static int __devinit register_ioregion(void)
 {
 	int count, done=0;
 	for (count=0; count < BOARD_COUNT; count++ ) {
@@ -1771,7 +1771,7 @@
 	return done;
 }
 
-static void __exit unregister_ioregion(void)
+static void unregister_ioregion(void)
 {
 	int count;
 	for (count=0; count < BOARD_COUNT; count++ ) 
@@ -1803,7 +1803,7 @@
 	.tiocmset	= isicom_tiocmset,
 };
 
-static int __init register_drivers(void)
+static int __devinit register_drivers(void)
 {
 	int error;
 
@@ -1834,7 +1834,7 @@
 	return 0;
 }
 
-static void __exit unregister_drivers(void)
+static void unregister_drivers(void)
 {
 	int error = tty_unregister_driver(isicom_normal);
 	if (error)
@@ -1842,7 +1842,7 @@
 	put_tty_driver(isicom_normal);
 }
 
-static int __init register_isr(void)
+static int __devinit register_isr(void)
 {
 	int count, done=0;
 	unsigned long irqflags;
@@ -1883,7 +1883,7 @@
 	}
 }
 
-static int __init isicom_init(void)
+static int __devinit isicom_init(void)
 {
 	int card, channel, base;
 	struct isi_port * port;
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 21aed0e..52a073e 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -407,7 +407,6 @@
 };
 
 static int	stli_eisamempsize = sizeof(stli_eisamemprobeaddrs) / sizeof(unsigned long);
-int		stli_eisaprobe = STLI_EISAPROBE;
 
 /*
  *	Define the Stallion PCI vendor and device IDs.
@@ -792,7 +791,7 @@
 
 /*****************************************************************************/
 
-static struct class_simple *istallion_class;
+static struct class *istallion_class;
 
 #ifdef MODULE
 
@@ -854,10 +853,10 @@
 	put_tty_driver(stli_serial);
 	for (i = 0; i < 4; i++) {
 		devfs_remove("staliomem/%d", i);
-		class_simple_device_remove(MKDEV(STL_SIOMEMMAJOR, i));
+		class_device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, i));
 	}
 	devfs_remove("staliomem");
-	class_simple_destroy(istallion_class);
+	class_destroy(istallion_class);
 	if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
 		printk("STALLION: failed to un-register serial memory device, "
 			"errno=%d\n", -i);
@@ -4685,7 +4684,7 @@
 #ifdef MODULE
 	stli_argbrds();
 #endif
-	if (stli_eisaprobe)
+	if (STLI_EISAPROBE)
 		stli_findeisabrds();
 #ifdef CONFIG_PCI
 	stli_findpcibrds();
@@ -5242,12 +5241,12 @@
 				"device\n");
 
 	devfs_mk_dir("staliomem");
-	istallion_class = class_simple_create(THIS_MODULE, "staliomem");
+	istallion_class = class_create(THIS_MODULE, "staliomem");
 	for (i = 0; i < 4; i++) {
 		devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
 			       S_IFCHR | S_IRUSR | S_IWUSR,
 			       "staliomem/%d", i);
-		class_simple_device_add(istallion_class, MKDEV(STL_SIOMEMMAJOR, i), 
+		class_device_create(istallion_class, MKDEV(STL_SIOMEMMAJOR, i),
 				NULL, "staliomem%d", i);
 	}
 
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 4dee945..59eebe5 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -146,7 +146,7 @@
 static struct lp_struct lp_table[LP_NO];
 
 static unsigned int lp_count = 0;
-static struct class_simple *lp_class;
+static struct class *lp_class;
 
 #ifdef CONFIG_LP_CONSOLE
 static struct parport *console_registered; // initially NULL
@@ -804,7 +804,7 @@
 	if (reset)
 		lp_reset(nr);
 
-	class_simple_device_add(lp_class, MKDEV(LP_MAJOR, nr), NULL,
+	class_device_create(lp_class, MKDEV(LP_MAJOR, nr), NULL,
 				"lp%d", nr);
 	devfs_mk_cdev(MKDEV(LP_MAJOR, nr), S_IFCHR | S_IRUGO | S_IWUGO,
 			"printers/%d", nr);
@@ -907,7 +907,7 @@
 	}
 
 	devfs_mk_dir("printers");
-	lp_class = class_simple_create(THIS_MODULE, "printer");
+	lp_class = class_create(THIS_MODULE, "printer");
 	if (IS_ERR(lp_class)) {
 		err = PTR_ERR(lp_class);
 		goto out_devfs;
@@ -930,7 +930,7 @@
 	return 0;
 
 out_class:
-	class_simple_destroy(lp_class);
+	class_destroy(lp_class);
 out_devfs:
 	devfs_remove("printers");
 	unregister_chrdev(LP_MAJOR, "lp");
@@ -981,10 +981,10 @@
 			continue;
 		parport_unregister_device(lp_table[offset].dev);
 		devfs_remove("printers/%d", offset);
-		class_simple_device_remove(MKDEV(LP_MAJOR, offset));
+		class_device_destroy(lp_class, MKDEV(LP_MAJOR, offset));
 	}
 	devfs_remove("printers");
-	class_simple_destroy(lp_class);
+	class_destroy(lp_class);
 }
 
 __setup("lp=", lp_setup);
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c
index ac9cfa9..115dbb3 100644
--- a/drivers/char/mbcs.c
+++ b/drivers/char/mbcs.c
@@ -699,7 +699,7 @@
 	return 0;
 }
 
-static ssize_t show_algo(struct device *dev, char *buf)
+static ssize_t show_algo(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct cx_dev *cx_dev = to_cx_dev(dev);
 	struct mbcs_soft *soft = cx_dev->soft;
@@ -715,7 +715,7 @@
 		       (debug0 >> 32), (debug0 & 0xffffffff));
 }
 
-static ssize_t store_algo(struct device *dev, const char *buf, size_t count)
+static ssize_t store_algo(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	int n;
 	struct cx_dev *cx_dev = to_cx_dev(dev);
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 947cb3c..4218738 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -23,7 +23,10 @@
 #include <linux/devfs_fs_kernel.h>
 #include <linux/ptrace.h>
 #include <linux/device.h>
+#include <linux/highmem.h>
+#include <linux/crash_dump.h>
 #include <linux/backing-dev.h>
+#include <linux/bootmem.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -273,6 +276,40 @@
 	return mmap_mem(file, vma);
 }
 
+#ifdef CONFIG_CRASH_DUMP
+/*
+ * Read memory corresponding to the old kernel.
+ */
+static ssize_t read_oldmem(struct file *file, char __user *buf,
+				size_t count, loff_t *ppos)
+{
+	unsigned long pfn, offset;
+	size_t read = 0, csize;
+	int rc = 0;
+
+	while (count) {
+		pfn = *ppos / PAGE_SIZE;
+		if (pfn > saved_max_pfn)
+			return read;
+
+		offset = (unsigned long)(*ppos % PAGE_SIZE);
+		if (count > PAGE_SIZE - offset)
+			csize = PAGE_SIZE - offset;
+		else
+			csize = count;
+
+		rc = copy_oldmem_page(pfn, buf, csize, offset, 1);
+		if (rc < 0)
+			return rc;
+		buf += csize;
+		*ppos += csize;
+		read += csize;
+		count -= csize;
+	}
+	return read;
+}
+#endif
+
 extern long vread(char *buf, char *addr, unsigned long count);
 extern long vwrite(char *buf, char *addr, unsigned long count);
 
@@ -484,7 +521,7 @@
  	return virtr + wrote;
 }
 
-#if defined(CONFIG_ISA) || !defined(__mc68000__)
+#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
 static ssize_t read_port(struct file * file, char __user * buf,
 			 size_t count, loff_t *ppos)
 {
@@ -721,6 +758,7 @@
 #define read_full       read_zero
 #define open_mem	open_port
 #define open_kmem	open_mem
+#define open_oldmem	open_mem
 
 static struct file_operations mem_fops = {
 	.llseek		= memory_lseek,
@@ -744,7 +782,7 @@
 	.write		= write_null,
 };
 
-#if defined(CONFIG_ISA) || !defined(__mc68000__)
+#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
 static struct file_operations port_fops = {
 	.llseek		= memory_lseek,
 	.read		= read_port,
@@ -770,6 +808,13 @@
 	.write		= write_full,
 };
 
+#ifdef CONFIG_CRASH_DUMP
+static struct file_operations oldmem_fops = {
+	.read	= read_oldmem,
+	.open	= open_oldmem,
+};
+#endif
+
 static ssize_t kmsg_write(struct file * file, const char __user * buf,
 			  size_t count, loff_t *ppos)
 {
@@ -804,7 +849,7 @@
 		case 3:
 			filp->f_op = &null_fops;
 			break;
-#if defined(CONFIG_ISA) || !defined(__mc68000__)
+#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
 		case 4:
 			filp->f_op = &port_fops;
 			break;
@@ -825,6 +870,11 @@
 		case 11:
 			filp->f_op = &kmsg_fops;
 			break;
+#ifdef CONFIG_CRASH_DUMP
+		case 12:
+			filp->f_op = &oldmem_fops;
+			break;
+#endif
 		default:
 			return -ENXIO;
 	}
@@ -846,7 +896,7 @@
 	{1, "mem",     S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops},
 	{2, "kmem",    S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops},
 	{3, "null",    S_IRUGO | S_IWUGO,           &null_fops},
-#if defined(CONFIG_ISA) || !defined(__mc68000__)
+#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
 	{4, "port",    S_IRUSR | S_IWUSR | S_IRGRP, &port_fops},
 #endif
 	{5, "zero",    S_IRUGO | S_IWUGO,           &zero_fops},
@@ -854,9 +904,12 @@
 	{8, "random",  S_IRUGO | S_IWUSR,           &random_fops},
 	{9, "urandom", S_IRUGO | S_IWUSR,           &urandom_fops},
 	{11,"kmsg",    S_IRUGO | S_IWUSR,           &kmsg_fops},
+#ifdef CONFIG_CRASH_DUMP
+	{12,"oldmem",    S_IRUSR | S_IWUSR | S_IRGRP, &oldmem_fops},
+#endif
 };
 
-static struct class_simple *mem_class;
+static struct class *mem_class;
 
 static int __init chr_dev_init(void)
 {
@@ -865,10 +918,9 @@
 	if (register_chrdev(MEM_MAJOR,"mem",&memory_fops))
 		printk("unable to get major %d for memory devs\n", MEM_MAJOR);
 
-	mem_class = class_simple_create(THIS_MODULE, "mem");
+	mem_class = class_create(THIS_MODULE, "mem");
 	for (i = 0; i < ARRAY_SIZE(devlist); i++) {
-		class_simple_device_add(mem_class,
-					MKDEV(MEM_MAJOR, devlist[i].minor),
+		class_device_create(mem_class, MKDEV(MEM_MAJOR, devlist[i].minor),
 					NULL, devlist[i].name);
 		devfs_mk_cdev(MKDEV(MEM_MAJOR, devlist[i].minor),
 				S_IFCHR | devlist[i].mode, devlist[i].name);
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 0937544..31cf84d 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -66,8 +66,6 @@
 extern int rtc_DP8570A_init(void);
 extern int rtc_MK48T08_init(void);
 extern int pmu_device_init(void);
-extern int tosh_init(void);
-extern int i8k_init(void);
 
 #ifdef CONFIG_PROC_FS
 static void *misc_seq_start(struct seq_file *seq, loff_t *pos)
@@ -177,10 +175,10 @@
 
 /* 
  * TODO for 2.7:
- *  - add a struct class_device to struct miscdevice and make all usages of
+ *  - add a struct kref to struct miscdevice and make all usages of
  *    them dynamic.
  */
-static struct class_simple *misc_class;
+static struct class *misc_class;
 
 static struct file_operations misc_fops = {
 	.owner		= THIS_MODULE,
@@ -238,8 +236,8 @@
 	}
 	dev = MKDEV(MISC_MAJOR, misc->minor);
 
-	misc->class = class_simple_device_add(misc_class, dev,
-					      misc->dev, misc->name);
+	misc->class = class_device_create(misc_class, dev, misc->dev,
+					  "%s", misc->name);
 	if (IS_ERR(misc->class)) {
 		err = PTR_ERR(misc->class);
 		goto out;
@@ -248,7 +246,7 @@
 	err = devfs_mk_cdev(dev, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP, 
 			    misc->devfs_name);
 	if (err) {
-		class_simple_device_remove(dev);
+		class_device_destroy(misc_class, dev);
 		goto out;
 	}
 
@@ -281,7 +279,7 @@
 
 	down(&misc_sem);
 	list_del(&misc->list);
-	class_simple_device_remove(MKDEV(MISC_MAJOR, misc->minor));
+	class_device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
 	devfs_remove(misc->devfs_name);
 	if (i < DYNAMIC_MINORS && i>0) {
 		misc_minors[i>>3] &= ~(1 << (misc->minor & 7));
@@ -302,7 +300,7 @@
 	if (ent)
 		ent->proc_fops = &misc_proc_fops;
 #endif
-	misc_class = class_simple_create(THIS_MODULE, "misc");
+	misc_class = class_create(THIS_MODULE, "misc");
 	if (IS_ERR(misc_class))
 		return PTR_ERR(misc_class);
 #ifdef CONFIG_MVME16x
@@ -314,16 +312,10 @@
 #ifdef CONFIG_PMAC_PBOOK
 	pmu_device_init();
 #endif
-#ifdef CONFIG_TOSHIBA
-	tosh_init();
-#endif
-#ifdef CONFIG_I8K
-	i8k_init();
-#endif
 	if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
 		printk("unable to get major %d for misc devices\n",
 		       MISC_MAJOR);
-		class_simple_destroy(misc_class);
+		class_destroy(misc_class);
 		return -EIO;
 	}
 	return 0;
diff --git a/drivers/char/mwave/3780i.c b/drivers/char/mwave/3780i.c
index ab00f51..613aed9 100644
--- a/drivers/char/mwave/3780i.c
+++ b/drivers/char/mwave/3780i.c
@@ -107,8 +107,8 @@
 	spin_unlock_irqrestore(&dsp_lock, flags);
 }
 
-void dsp3780I_WriteGenCfg(unsigned short usDspBaseIO, unsigned uIndex,
-                          unsigned char ucValue)
+static void dsp3780I_WriteGenCfg(unsigned short usDspBaseIO, unsigned uIndex,
+				 unsigned char ucValue)
 {
 	DSP_ISA_SLAVE_CONTROL rSlaveControl;
 	DSP_ISA_SLAVE_CONTROL rSlaveControl_Save;
@@ -141,6 +141,7 @@
 
 }
 
+#if 0
 unsigned char dsp3780I_ReadGenCfg(unsigned short usDspBaseIO,
                                   unsigned uIndex)
 {
@@ -167,6 +168,7 @@
 
 	return ucValue;
 }
+#endif  /*  0  */
 
 int dsp3780I_EnableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings,
                        unsigned short *pIrqMap,
diff --git a/drivers/char/mwave/3780i.h b/drivers/char/mwave/3780i.h
index 3e7d020..270431c 100644
--- a/drivers/char/mwave/3780i.h
+++ b/drivers/char/mwave/3780i.h
@@ -338,10 +338,6 @@
                                    unsigned long ulMsaAddr);
 void dsp3780I_WriteMsaCfg(unsigned short usDspBaseIO,
                           unsigned long ulMsaAddr, unsigned short usValue);
-void dsp3780I_WriteGenCfg(unsigned short usDspBaseIO, unsigned uIndex,
-                          unsigned char ucValue);
-unsigned char dsp3780I_ReadGenCfg(unsigned short usDspBaseIO,
-                                  unsigned uIndex);
 int dsp3780I_GetIPCSource(unsigned short usDspBaseIO,
                           unsigned short *pusIPCSource);
 
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
index d37625d..d568991 100644
--- a/drivers/char/mwave/mwavedd.c
+++ b/drivers/char/mwave/mwavedd.c
@@ -472,7 +472,7 @@
 
 /* Prevent code redundancy, create a macro for mwave_show_* functions. */
 #define mwave_show_function(attr_name, format_string, field)		\
-static ssize_t mwave_show_##attr_name(struct device *dev, char *buf)	\
+static ssize_t mwave_show_##attr_name(struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	DSP_3780I_CONFIG_SETTINGS *pSettings =				\
 		&mwave_s_mdd.rBDData.rDspSettings;			\
diff --git a/drivers/char/mwave/tp3780i.c b/drivers/char/mwave/tp3780i.c
index ab650cd..d6c72e0 100644
--- a/drivers/char/mwave/tp3780i.c
+++ b/drivers/char/mwave/tp3780i.c
@@ -242,20 +242,14 @@
 {
 	int retval = 0;
 	DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 	struct resource *pres;
-#endif
 
 	PRINTK_2(TRACE_TP3780I,
 		"tp3780i::tp3780I_ClaimResources entry pBDData %p\n", pBDData);
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 	pres = request_region(pSettings->usDspBaseIO, 16, "mwave_3780i");
 	if ( pres == NULL ) retval = -EIO;
-#else
-	retval = check_region(pSettings->usDspBaseIO, 16);
-	if (!retval) request_region(pSettings->usDspBaseIO, 16, "mwave_3780i");
-#endif
+
 	if (retval) {
 		PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_ClaimResources: Error: Could not claim I/O region starting at %x\n", pSettings->usDspBaseIO);
 		retval = -EIO;
@@ -292,7 +286,7 @@
 int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData)
 {
 	DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
-	BOOLEAN bDSPPoweredUp = FALSE, bDSPEnabled = FALSE, bInterruptAllocated = FALSE;
+	BOOLEAN bDSPPoweredUp = FALSE, bInterruptAllocated = FALSE;
 
 	PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_EnableDSP entry pBDData %p\n", pBDData);
 
@@ -397,8 +391,6 @@
 	if (dsp3780I_EnableDSP(pSettings, s_ausThinkpadIrqToField, s_ausThinkpadDmaToField)) {
 		PRINTK_ERROR("tp3780i::tp3780I_EnableDSP: Error: dsp7880I_EnableDSP() failed\n");
 		goto exit_cleanup;
-	} else {
-		bDSPEnabled = TRUE;
 	}
 
 	EnableSRAM(pBDData);
@@ -411,8 +403,6 @@
 
 exit_cleanup:
 	PRINTK_ERROR("tp3780i::tp3780I_EnableDSP: Cleaning up\n");
-	if (bDSPEnabled)
-		dsp3780I_DisableDSP(pSettings);
 	if (bDSPPoweredUp)
 		smapi_set_DSP_power_state(FALSE);
 	if (bInterruptAllocated) {
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 7a24506..f022f09 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -1995,9 +1995,6 @@
 	unsigned char ch, gdl;
 	int ignored = 0;
 	int cnt = 0;
-	unsigned char *cp;
-	char *fp;
-	int count;
 	int recv_room;
 	int max = 256;
 	unsigned long flags;
@@ -2011,10 +2008,6 @@
 		//return;
 	}
 
-	cp = tty->flip.char_buf;
-	fp = tty->flip.flag_buf;
-	count = 0;
-
 	// following add by Victor Yu. 09-02-2002
 	if (info->IsMoxaMustChipFlag != MOXA_OTHER_UART) {
 
@@ -2041,12 +2034,10 @@
 		}
 		while (gdl--) {
 			ch = inb(info->base + UART_RX);
-			count++;
-			*cp++ = ch;
-			*fp++ = 0;
+			tty_insert_flip_char(tty, ch, 0);
 			cnt++;
 			/*
-			   if((count>=HI_WATER) && (info->stop_rx==0)){
+			   if((cnt>=HI_WATER) && (info->stop_rx==0)){
 			   mxser_stoprx(tty);
 			   info->stop_rx=1;
 			   break;
@@ -2061,7 +2052,7 @@
 		if (max-- < 0)
 			break;
 		/*
-		   if((count>=HI_WATER) && (info->stop_rx==0)){
+		   if((cnt>=HI_WATER) && (info->stop_rx==0)){
 		   mxser_stoprx(tty);
 		   info->stop_rx=1;
 		   break;
@@ -2078,36 +2069,33 @@
 			if (++ignored > 100)
 				break;
 		} else {
-			count++;
+			char flag = 0;
 			if (*status & UART_LSR_SPECIAL) {
 				if (*status & UART_LSR_BI) {
-					*fp++ = TTY_BREAK;
+					flag = TTY_BREAK;
 /* added by casper 1/11/2000 */
 					info->icount.brk++;
-
 /* */
 					if (info->flags & ASYNC_SAK)
 						do_SAK(tty);
 				} else if (*status & UART_LSR_PE) {
-					*fp++ = TTY_PARITY;
+					flag = TTY_PARITY;
 /* added by casper 1/11/2000 */
 					info->icount.parity++;
 /* */
 				} else if (*status & UART_LSR_FE) {
-					*fp++ = TTY_FRAME;
+					flag = TTY_FRAME;
 /* added by casper 1/11/2000 */
 					info->icount.frame++;
 /* */
 				} else if (*status & UART_LSR_OE) {
-					*fp++ = TTY_OVERRUN;
+					flag = TTY_OVERRUN;
 /* added by casper 1/11/2000 */
 					info->icount.overrun++;
 /* */
-				} else
-					*fp++ = 0;
-			} else
-				*fp++ = 0;
-			*cp++ = ch;
+				}
+			}
+			tty_insert_flip_char(tty, ch, flag);
 			cnt++;
 			if (cnt >= recv_room) {
 				if (!info->ldisc_stop_rx) {
@@ -2132,13 +2120,13 @@
 		// 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;
 	spin_unlock_irqrestore(&info->slock, flags);
-	
+
 	tty_flip_buffer_push(tty);
 }
 
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index b3dbff1..5079bed 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -960,7 +960,7 @@
 static void __exit n_hdlc_exit(void)
 {
 	/* Release tty registration of line discipline */
-	int status = tty_register_ldisc(N_HDLC, NULL);
+	int status = tty_unregister_ldisc(N_HDLC);
 
 	if (status)
 		printk(hdlc_unregister_fail, status);
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index 3883073..2291a87 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -200,7 +200,7 @@
    
    TRACE_M ("cleanup_module()");
 
-   status=tty_register_ldisc(N_R3964, NULL);
+   status=tty_unregister_ldisc(N_R3964);
    
    if(status!=0)
    {
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index f63a3fd..1af733d 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -211,12 +211,13 @@
 	return rv;
 }
 
-void
+static void
 __nvram_set_checksum(void)
 {
 	mach_set_checksum();
 }
 
+#if 0
 void
 nvram_set_checksum(void)
 {
@@ -226,6 +227,7 @@
 	__nvram_set_checksum();
 	spin_unlock_irqrestore(&rtc_lock, flags);
 }
+#endif  /*  0  */
 
 /*
  * The are the file operation function for user access to /dev/nvram
@@ -921,6 +923,4 @@
 EXPORT_SYMBOL(nvram_write_byte);
 EXPORT_SYMBOL(__nvram_check_checksum);
 EXPORT_SYMBOL(nvram_check_checksum);
-EXPORT_SYMBOL(__nvram_set_checksum);
-EXPORT_SYMBOL(nvram_set_checksum);
 MODULE_ALIAS_MISCDEV(NVRAM_MINOR);
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index 5eda075..0e22880 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -737,7 +737,7 @@
 	return mask;
 }
 
-static struct class_simple *ppdev_class;
+static struct class *ppdev_class;
 
 static struct file_operations pp_fops = {
 	.owner		= THIS_MODULE,
@@ -752,13 +752,13 @@
 
 static void pp_attach(struct parport *port)
 {
-	class_simple_device_add(ppdev_class, MKDEV(PP_MAJOR, port->number),
+	class_device_create(ppdev_class, MKDEV(PP_MAJOR, port->number),
 			NULL, "parport%d", port->number);
 }
 
 static void pp_detach(struct parport *port)
 {
-	class_simple_device_remove(MKDEV(PP_MAJOR, port->number));
+	class_device_destroy(ppdev_class, MKDEV(PP_MAJOR, port->number));
 }
 
 static struct parport_driver pp_driver = {
@@ -776,7 +776,7 @@
 			PP_MAJOR);
 		return -EIO;
 	}
-	ppdev_class = class_simple_create(THIS_MODULE, CHRDEV);
+	ppdev_class = class_create(THIS_MODULE, CHRDEV);
 	if (IS_ERR(ppdev_class)) {
 		err = PTR_ERR(ppdev_class);
 		goto out_chrdev;
@@ -798,7 +798,7 @@
 	for (i = 0; i < PARPORT_MAX; i++)
 		devfs_remove("parports/%d", i);
 	devfs_remove("parports");
-	class_simple_destroy(ppdev_class);
+	class_destroy(ppdev_class);
 out_chrdev:
 	unregister_chrdev(PP_MAJOR, CHRDEV);
 out:
@@ -813,7 +813,7 @@
 		devfs_remove("parports/%d", i);
 	parport_unregister_driver(&pp_driver);
 	devfs_remove("parports");
-	class_simple_destroy(ppdev_class);
+	class_destroy(ppdev_class);
 	unregister_chrdev (PP_MAJOR, CHRDEV);
 }
 
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index ca5f42b..f13e5de 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -27,7 +27,7 @@
 	int inuse;
 };
 
-static struct class_simple *raw_class;
+static struct class *raw_class;
 static struct raw_device_data raw_devices[MAX_RAW_MINORS];
 static DECLARE_MUTEX(raw_mutex);
 static struct file_operations raw_ctl_fops;	     /* forward declaration */
@@ -127,8 +127,8 @@
 
 static void bind_device(struct raw_config_request *rq)
 {
-	class_simple_device_remove(MKDEV(RAW_MAJOR, rq->raw_minor));
-	class_simple_device_add(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor),
+	class_device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
+	class_device_create(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor),
 				      NULL, "raw%d", rq->raw_minor);
 }
 
@@ -200,8 +200,8 @@
 			if (rq.block_major == 0 && rq.block_minor == 0) {
 				/* unbind */
 				rawdev->binding = NULL;
-				class_simple_device_remove(MKDEV(RAW_MAJOR,
-								rq.raw_minor));
+				class_device_destroy(raw_class,
+						MKDEV(RAW_MAJOR, rq.raw_minor));
 			} else {
 				rawdev->binding = bdget(dev);
 				if (rawdev->binding == NULL)
@@ -300,14 +300,14 @@
 		goto error;
 	}
 
-	raw_class = class_simple_create(THIS_MODULE, "raw");
+	raw_class = class_create(THIS_MODULE, "raw");
 	if (IS_ERR(raw_class)) {
 		printk(KERN_ERR "Error creating raw class.\n");
 		cdev_del(&raw_cdev);
 		unregister_chrdev_region(dev, MAX_RAW_MINORS);
 		goto error;
 	}
-	class_simple_device_add(raw_class, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
+	class_device_create(raw_class, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
 
 	devfs_mk_cdev(MKDEV(RAW_MAJOR, 0),
 		      S_IFCHR | S_IRUGO | S_IWUGO,
@@ -331,8 +331,8 @@
 		devfs_remove("raw/raw%d", i);
 	devfs_remove("raw/rawctl");
 	devfs_remove("raw");
-	class_simple_device_remove(MKDEV(RAW_MAJOR, 0));
-	class_simple_destroy(raw_class);
+	class_device_destroy(raw_class, MKDEV(RAW_MAJOR, 0));
+	class_destroy(raw_class);
 	cdev_del(&raw_cdev);
 	unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), MAX_RAW_MINORS);
 }
diff --git a/drivers/char/rio/func.h b/drivers/char/rio/func.h
index e8f3860..01987c6 100644
--- a/drivers/char/rio/func.h
+++ b/drivers/char/rio/func.h
@@ -147,7 +147,6 @@
 extern int    rio_pcicopy(char *src, char *dst, int n);
 extern int rio_minor (struct tty_struct *tty);
 extern int rio_ismodem (struct tty_struct *tty);
-extern void rio_udelay (int usecs);
 
 extern void rio_start_card_running (struct Host * HostP);
 
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index 763893e..7db3370 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -354,11 +354,6 @@
 }
 
 
-void rio_udelay (int usecs)
-{
-  udelay (usecs);
-}
-
 static int rio_set_real_termios (void *ptr)
 {
   int rv, modem;
diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c
index dca941e..898a126 100644
--- a/drivers/char/rio/rioinit.c
+++ b/drivers/char/rio/rioinit.c
@@ -37,6 +37,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
+#include <linux/delay.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/string.h>
@@ -1560,14 +1561,14 @@
 					  INTERRUPT_DISABLE | BYTE_OPERATION |
 					  SLOW_LINKS | SLOW_AT_BUS);
 			WBYTE(DpRamP->DpResetTpu, 0xFF);
-			rio_udelay (3);
+			udelay(3);
 
 			rio_dprintk (RIO_DEBUG_INIT,  "RIOHostReset: Don't know if it worked. Try reset again\n");
 			WBYTE(DpRamP->DpControl,  BOOT_FROM_RAM | EXTERNAL_BUS_OFF |
 					  INTERRUPT_DISABLE | BYTE_OPERATION |
 					  SLOW_LINKS | SLOW_AT_BUS);
 			WBYTE(DpRamP->DpResetTpu, 0xFF);
-			rio_udelay (3);
+			udelay(3);
 			break;
 #ifdef FUTURE_RELEASE
 	case RIO_EISA:
@@ -1599,7 +1600,7 @@
 		DpRamP->DpControl  = RIO_PCI_BOOT_FROM_RAM;
 		DpRamP->DpResetInt = 0xFF;
 		DpRamP->DpResetTpu = 0xFF;
-		rio_udelay (100);
+		udelay(100);
 		/* for (i=0; i<6000; i++);  */
 		/* suspend( 3 ); */
 		break;
diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c
index db65500..78a321a 100644
--- a/drivers/char/rio/riotty.c
+++ b/drivers/char/rio/riotty.c
@@ -524,16 +524,16 @@
 	register uint SysPort = dev;
 	struct ttystatics *tp;		/* pointer to our ttystruct */
 #endif
-	struct Port *PortP =ptr;	/* pointer to the port structure */
+	struct Port *PortP = ptr;	/* pointer to the port structure */
 	int deleted = 0;
 	int	try = -1; /* Disable the timeouts by setting them to -1 */
 	int	repeat_this = -1; /* Congrats to those having 15 years of 
 				     uptime! (You get to break the driver.) */
-	long end_time;
+	unsigned long end_time;
 	struct tty_struct * tty;
 	unsigned long flags;
 	int Modem;
-	int rv =0;
+	int rv = 0;
 	
 	rio_dprintk (RIO_DEBUG_TTY, "port close SysPort %d\n",PortP->PortNum);
 
@@ -620,7 +620,7 @@
 		if (repeat_this -- <= 0) {
 			rv = -EINTR;
 			rio_dprintk (RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
-			RIOPreemptiveCmd(p, PortP, FCLOSE ); 
+			RIOPreemptiveCmd(p, PortP, FCLOSE);
 			goto close_end;
 		}
 		rio_dprintk (RIO_DEBUG_TTY, "Calling timeout to flush in closing\n");
@@ -656,14 +656,12 @@
 		goto close_end;
 	}
 
-	
-
 	/* Can't call RIOShortCommand with the port locked. */
 	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
 
 	if (RIOShortCommand(p, PortP, CLOSE, 1, 0) == RIO_FAIL) {
-	  RIOPreemptiveCmd(p, PortP,FCLOSE);
-	  goto close_end;
+		RIOPreemptiveCmd(p, PortP, FCLOSE);
+		goto close_end;
 	}
 
 	if (!deleted)
@@ -698,7 +696,6 @@
 */
 	PortP->Config &= ~(RIO_CTSFLOW|RIO_RTSFLOW);
 
-
 #ifdef STATS
 	PortP->Stat.CloseCnt++;
 #endif
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 5bcbeb0..f463d6b 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -161,6 +161,64 @@
 	UPCI_AIOP_INTR_BIT_3
 };
 
+static Byte_t RData[RDATASIZE] = {
+	0x00, 0x09, 0xf6, 0x82,
+	0x02, 0x09, 0x86, 0xfb,
+	0x04, 0x09, 0x00, 0x0a,
+	0x06, 0x09, 0x01, 0x0a,
+	0x08, 0x09, 0x8a, 0x13,
+	0x0a, 0x09, 0xc5, 0x11,
+	0x0c, 0x09, 0x86, 0x85,
+	0x0e, 0x09, 0x20, 0x0a,
+	0x10, 0x09, 0x21, 0x0a,
+	0x12, 0x09, 0x41, 0xff,
+	0x14, 0x09, 0x82, 0x00,
+	0x16, 0x09, 0x82, 0x7b,
+	0x18, 0x09, 0x8a, 0x7d,
+	0x1a, 0x09, 0x88, 0x81,
+	0x1c, 0x09, 0x86, 0x7a,
+	0x1e, 0x09, 0x84, 0x81,
+	0x20, 0x09, 0x82, 0x7c,
+	0x22, 0x09, 0x0a, 0x0a
+};
+
+static Byte_t RRegData[RREGDATASIZE] = {
+	0x00, 0x09, 0xf6, 0x82,	/* 00: Stop Rx processor */
+	0x08, 0x09, 0x8a, 0x13,	/* 04: Tx software flow control */
+	0x0a, 0x09, 0xc5, 0x11,	/* 08: XON char */
+	0x0c, 0x09, 0x86, 0x85,	/* 0c: XANY */
+	0x12, 0x09, 0x41, 0xff,	/* 10: Rx mask char */
+	0x14, 0x09, 0x82, 0x00,	/* 14: Compare/Ignore #0 */
+	0x16, 0x09, 0x82, 0x7b,	/* 18: Compare #1 */
+	0x18, 0x09, 0x8a, 0x7d,	/* 1c: Compare #2 */
+	0x1a, 0x09, 0x88, 0x81,	/* 20: Interrupt #1 */
+	0x1c, 0x09, 0x86, 0x7a,	/* 24: Ignore/Replace #1 */
+	0x1e, 0x09, 0x84, 0x81,	/* 28: Interrupt #2 */
+	0x20, 0x09, 0x82, 0x7c,	/* 2c: Ignore/Replace #2 */
+	0x22, 0x09, 0x0a, 0x0a	/* 30: Rx FIFO Enable */
+};
+
+static CONTROLLER_T sController[CTL_SIZE] = {
+	{-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
+	 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
+	{-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
+	 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
+	{-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
+	 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
+	{-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
+	 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}}
+};
+
+static Byte_t sBitMapClrTbl[8] = {
+	0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f
+};
+
+static Byte_t sBitMapSetTbl[8] = {
+	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
+};
+
+static int sClockPrescale = 0x14;
+
 /*
  *  Line number is the ttySIx number (x), the Minor number.  We 
  *  assign them sequentially, starting at zero.  The following 
@@ -177,6 +235,26 @@
 static unsigned char GetLineNumber(int ctrl, int aiop, int ch);
 static unsigned char SetLineNumber(int ctrl, int aiop, int ch);
 static void rp_start(struct tty_struct *tty);
+static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
+		     int ChanNum);
+static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode);
+static void sFlushRxFIFO(CHANNEL_T * ChP);
+static void sFlushTxFIFO(CHANNEL_T * ChP);
+static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags);
+static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags);
+static void sModemReset(CONTROLLER_T * CtlP, int chan, int on);
+static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on);
+static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data);
+static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
+			      ByteIO_t * AiopIOList, int AiopIOListSize,
+			      WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
+			      int PeriodicOnly, int altChanRingIndicator,
+			      int UPCIRingInd);
+static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
+			   ByteIO_t * AiopIOList, int AiopIOListSize,
+			   int IRQNum, Byte_t Frequency, int PeriodicOnly);
+static int sReadAiopID(ByteIO_t io);
+static int sReadAiopNumChan(WordIO_t io);
 
 #ifdef MODULE
 MODULE_AUTHOR("Theodore Ts'o");
@@ -1798,7 +1876,7 @@
  *  init's aiopic and serial port hardware.
  *  Inputs:  i is the board number (0-n)
  */
-__init int register_PCI(int i, struct pci_dev *dev)
+static __init int register_PCI(int i, struct pci_dev *dev)
 {
 	int num_aiops, aiop, max_num_aiops, num_chan, chan;
 	unsigned int aiopio[MAX_AIOPS_PER_BOARD];
@@ -2453,72 +2531,6 @@
 }
 #endif
 
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-static Byte_t RData[RDATASIZE] = {
-	0x00, 0x09, 0xf6, 0x82,
-	0x02, 0x09, 0x86, 0xfb,
-	0x04, 0x09, 0x00, 0x0a,
-	0x06, 0x09, 0x01, 0x0a,
-	0x08, 0x09, 0x8a, 0x13,
-	0x0a, 0x09, 0xc5, 0x11,
-	0x0c, 0x09, 0x86, 0x85,
-	0x0e, 0x09, 0x20, 0x0a,
-	0x10, 0x09, 0x21, 0x0a,
-	0x12, 0x09, 0x41, 0xff,
-	0x14, 0x09, 0x82, 0x00,
-	0x16, 0x09, 0x82, 0x7b,
-	0x18, 0x09, 0x8a, 0x7d,
-	0x1a, 0x09, 0x88, 0x81,
-	0x1c, 0x09, 0x86, 0x7a,
-	0x1e, 0x09, 0x84, 0x81,
-	0x20, 0x09, 0x82, 0x7c,
-	0x22, 0x09, 0x0a, 0x0a
-};
-
-static Byte_t RRegData[RREGDATASIZE] = {
-	0x00, 0x09, 0xf6, 0x82,	/* 00: Stop Rx processor */
-	0x08, 0x09, 0x8a, 0x13,	/* 04: Tx software flow control */
-	0x0a, 0x09, 0xc5, 0x11,	/* 08: XON char */
-	0x0c, 0x09, 0x86, 0x85,	/* 0c: XANY */
-	0x12, 0x09, 0x41, 0xff,	/* 10: Rx mask char */
-	0x14, 0x09, 0x82, 0x00,	/* 14: Compare/Ignore #0 */
-	0x16, 0x09, 0x82, 0x7b,	/* 18: Compare #1 */
-	0x18, 0x09, 0x8a, 0x7d,	/* 1c: Compare #2 */
-	0x1a, 0x09, 0x88, 0x81,	/* 20: Interrupt #1 */
-	0x1c, 0x09, 0x86, 0x7a,	/* 24: Ignore/Replace #1 */
-	0x1e, 0x09, 0x84, 0x81,	/* 28: Interrupt #2 */
-	0x20, 0x09, 0x82, 0x7c,	/* 2c: Ignore/Replace #2 */
-	0x22, 0x09, 0x0a, 0x0a	/* 30: Rx FIFO Enable */
-};
-
-CONTROLLER_T sController[CTL_SIZE] = {
-	{-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
-	 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
-	{-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
-	 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
-	{-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
-	 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
-	{-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
-	 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}}
-};
-
-Byte_t sBitMapClrTbl[8] = {
-	0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f
-};
-
-Byte_t sBitMapSetTbl[8] = {
-	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
-};
-
-int sClockPrescale = 0x14;
-
 /***************************************************************************
 Function: sInitController
 Purpose:  Initialization of controller global registers and controller
@@ -2554,22 +2566,22 @@
                       FREQ_4HZ - 4 Hertz
                    If IRQNum is set to 0 the Frequency parameter is
                    overidden, it is forced to a value of FREQ_DIS.
-          int PeriodicOnly: TRUE if all interrupts except the periodic
+          int PeriodicOnly: 1 if all interrupts except the periodic
                                interrupt are to be blocked.
-                            FALSE is both the periodic interrupt and
+                            0 is both the periodic interrupt and
                                other channel interrupts are allowed.
                             If IRQNum is set to 0 the PeriodicOnly parameter is
-                               overidden, it is forced to a value of FALSE.
+                               overidden, it is forced to a value of 0.
 Return:   int: Number of AIOPs on the controller, or CTLID_NULL if controller
                initialization failed.
 
 Comments:
           If periodic interrupts are to be disabled but AIOP interrupts
-          are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE.
+          are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
 
           If interrupts are to be completely disabled set IRQNum to 0.
 
-          Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an
+          Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
           invalid combination.
 
           This function performs initialization of global interrupt modes,
@@ -2589,9 +2601,9 @@
           After this function all AIOPs on the controller are disabled,
           they can be enabled with sEnAiop().
 */
-int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
-		    ByteIO_t * AiopIOList, int AiopIOListSize, int IRQNum,
-		    Byte_t Frequency, int PeriodicOnly)
+static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
+			   ByteIO_t * AiopIOList, int AiopIOListSize,
+			   int IRQNum, Byte_t Frequency, int PeriodicOnly)
 {
 	int i;
 	ByteIO_t io;
@@ -2687,22 +2699,22 @@
                       FREQ_4HZ - 4 Hertz
                    If IRQNum is set to 0 the Frequency parameter is
                    overidden, it is forced to a value of FREQ_DIS.
-          int PeriodicOnly: TRUE if all interrupts except the periodic
+          int PeriodicOnly: 1 if all interrupts except the periodic
                                interrupt are to be blocked.
-                            FALSE is both the periodic interrupt and
+                            0 is both the periodic interrupt and
                                other channel interrupts are allowed.
                             If IRQNum is set to 0 the PeriodicOnly parameter is
-                               overidden, it is forced to a value of FALSE.
+                               overidden, it is forced to a value of 0.
 Return:   int: Number of AIOPs on the controller, or CTLID_NULL if controller
                initialization failed.
 
 Comments:
           If periodic interrupts are to be disabled but AIOP interrupts
-          are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE.
+          are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
 
           If interrupts are to be completely disabled set IRQNum to 0.
 
-          Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an
+          Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
           invalid combination.
 
           This function performs initialization of global interrupt modes,
@@ -2722,11 +2734,11 @@
           After this function all AIOPs on the controller are disabled,
           they can be enabled with sEnAiop().
 */
-int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
-		       ByteIO_t * AiopIOList, int AiopIOListSize,
-		       WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
-		       int PeriodicOnly, int altChanRingIndicator,
-		       int UPCIRingInd)
+static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
+			      ByteIO_t * AiopIOList, int AiopIOListSize,
+			      WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
+			      int PeriodicOnly, int altChanRingIndicator,
+			      int UPCIRingInd)
 {
 	int i;
 	ByteIO_t io;
@@ -2784,7 +2796,7 @@
 Warnings: No context switches are allowed while executing this function.
 
 */
-int sReadAiopID(ByteIO_t io)
+static int sReadAiopID(ByteIO_t io)
 {
 	Byte_t AiopID;		/* ID byte from AIOP */
 
@@ -2810,7 +2822,7 @@
           AIOP, otherwise it is an 8 channel.
 Warnings: No context switches are allowed while executing this function.
 */
-int sReadAiopNumChan(WordIO_t io)
+static int sReadAiopNumChan(WordIO_t io)
 {
 	Word_t x;
 	static Byte_t R[4] = { 0x00, 0x00, 0x34, 0x12 };
@@ -2834,15 +2846,15 @@
           CHANNEL_T *ChP; Ptr to channel structure
           int AiopNum; AIOP number within controller
           int ChanNum; Channel number within AIOP
-Return:   int: TRUE if initialization succeeded, FALSE if it fails because channel
+Return:   int: 1 if initialization succeeded, 0 if it fails because channel
                number exceeds number of channels available in AIOP.
 Comments: This function must be called before a channel can be used.
 Warnings: No range checking on any of the parameters is done.
 
           No context switches are allowed while executing this function.
 */
-int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
-	      int ChanNum)
+static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
+		     int ChanNum)
 {
 	int i;
 	WordIO_t AiopIO;
@@ -2853,7 +2865,7 @@
 	int brd9600;
 
 	if (ChanNum >= CtlP->AiopNumChan[AiopNum])
-		return (FALSE);	/* exceeds num chans in AIOP */
+		return 0;	/* exceeds num chans in AIOP */
 
 	/* Channel, AIOP, and controller identifiers */
 	ChP->CtlP = CtlP;
@@ -2968,7 +2980,7 @@
 	ChP->TxPrioBuf = ChOff + _TXP_BUF;
 	sEnRxProcessor(ChP);	/* start the Rx processor */
 
-	return (TRUE);
+	return 1;
 }
 
 /***************************************************************************
@@ -2989,7 +3001,7 @@
           After calling this function a delay of 4 uS is required to ensure
           that the receive processor is no longer processing this channel.
 */
-void sStopRxProcessor(CHANNEL_T * ChP)
+static void sStopRxProcessor(CHANNEL_T * ChP)
 {
 	Byte_t R[4];
 
@@ -3014,18 +3026,18 @@
           this function.
 Warnings: No context switches are allowed while executing this function.
 */
-void sFlushRxFIFO(CHANNEL_T * ChP)
+static void sFlushRxFIFO(CHANNEL_T * ChP)
 {
 	int i;
 	Byte_t Ch;		/* channel number within AIOP */
-	int RxFIFOEnabled;	/* TRUE if Rx FIFO enabled */
+	int RxFIFOEnabled;	/* 1 if Rx FIFO enabled */
 
 	if (sGetRxCnt(ChP) == 0)	/* Rx FIFO empty */
 		return;		/* don't need to flush */
 
-	RxFIFOEnabled = FALSE;
+	RxFIFOEnabled = 0;
 	if (ChP->R[0x32] == 0x08) {	/* Rx FIFO is enabled */
-		RxFIFOEnabled = TRUE;
+		RxFIFOEnabled = 1;
 		sDisRxFIFO(ChP);	/* disable it */
 		for (i = 0; i < 2000 / 200; i++)	/* delay 2 uS to allow proc to disable FIFO */
 			sInB(ChP->IntChan);	/* depends on bus i/o timing */
@@ -3056,18 +3068,18 @@
           this function.
 Warnings: No context switches are allowed while executing this function.
 */
-void sFlushTxFIFO(CHANNEL_T * ChP)
+static void sFlushTxFIFO(CHANNEL_T * ChP)
 {
 	int i;
 	Byte_t Ch;		/* channel number within AIOP */
-	int TxEnabled;		/* TRUE if transmitter enabled */
+	int TxEnabled;		/* 1 if transmitter enabled */
 
 	if (sGetTxCnt(ChP) == 0)	/* Tx FIFO empty */
 		return;		/* don't need to flush */
 
-	TxEnabled = FALSE;
+	TxEnabled = 0;
 	if (ChP->TxControl[3] & TX_ENABLE) {
-		TxEnabled = TRUE;
+		TxEnabled = 1;
 		sDisTransmit(ChP);	/* disable transmitter */
 	}
 	sStopRxProcessor(ChP);	/* stop Rx processor */
@@ -3096,7 +3108,7 @@
 
 Warnings: No context switches are allowed while executing this function.
 */
-int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data)
+static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data)
 {
 	Byte_t DWBuf[4];	/* buffer for double word writes */
 	Word_t *WordPtr;	/* must be far because Win SS != DS */
@@ -3158,7 +3170,7 @@
           enable channel interrupts.  This would allow the global interrupt
           status register to be used to determine which AIOPs need service.
 */
-void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags)
+static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags)
 {
 	Byte_t Mask;		/* Interrupt Mask Register */
 
@@ -3202,7 +3214,7 @@
           this channel's bit from being set in the AIOP's Interrupt Channel
           Register.
 */
-void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags)
+static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags)
 {
 	Byte_t Mask;		/* Interrupt Mask Register */
 
@@ -3218,7 +3230,7 @@
 	}
 }
 
-void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode)
+static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode)
 {
 	sOutB(ChP->CtlP->AiopIO[2], (mode & 0x18) | ChP->ChanNum);
 }
@@ -3227,7 +3239,7 @@
  *  Not an official SSCI function, but how to reset RocketModems.
  *  ISA bus version
  */
-void sModemReset(CONTROLLER_T * CtlP, int chan, int on)
+static void sModemReset(CONTROLLER_T * CtlP, int chan, int on)
 {
 	ByteIO_t addr;
 	Byte_t val;
@@ -3252,7 +3264,7 @@
  *  Not an official SSCI function, but how to reset RocketModems.
  *  PCI bus version
  */
-void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on)
+static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on)
 {
 	ByteIO_t addr;
 
diff --git a/drivers/char/rocket_int.h b/drivers/char/rocket_int.h
index 8026872..3a8bcc8 100644
--- a/drivers/char/rocket_int.h
+++ b/drivers/char/rocket_int.h
@@ -1130,46 +1130,6 @@
 */
 #define sWriteTxByte(IO,DATA) sOutB(IO,DATA)
 
-int sInitController(CONTROLLER_T * CtlP,
-		    int CtlNum,
-		    ByteIO_t MudbacIO,
-		    ByteIO_t * AiopIOList,
-		    int AiopIOListSize,
-		    int IRQNum, Byte_t Frequency, int PeriodicOnly);
-
-int sPCIInitController(CONTROLLER_T * CtlP,
-		       int CtlNum,
-		       ByteIO_t * AiopIOList,
-		       int AiopIOListSize,
-		       WordIO_t ConfigIO,
-		       int IRQNum,
-		       Byte_t Frequency,
-		       int PeriodicOnly,
-		       int altChanRingIndicator, int UPCIRingInd);
-
-int sReadAiopID(ByteIO_t io);
-int sReadAiopNumChan(WordIO_t io);
-int sInitChan(CONTROLLER_T * CtlP,
-	      CHANNEL_T * ChP, int AiopNum, int ChanNum);
-Byte_t sGetRxErrStatus(CHANNEL_T * ChP);
-void sStopRxProcessor(CHANNEL_T * ChP);
-void sStopSWInFlowCtl(CHANNEL_T * ChP);
-void sFlushRxFIFO(CHANNEL_T * ChP);
-void sFlushTxFIFO(CHANNEL_T * ChP);
-int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data);
-void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags);
-void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags);
-void sModemReset(CONTROLLER_T * CtlP, int chan, int on);
-void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on);
-void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode);
-
-extern Byte_t R[RDATASIZE];
-extern CONTROLLER_T sController[CTL_SIZE];
-extern Byte_t sIRQMap[16];
-extern Byte_t sBitMapClrTbl[8];
-extern Byte_t sBitMapSetTbl[8];
-extern int sClockPrescale;
-
 /*
  * Begin Linux specific definitions for the Rocketport driver
  *
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index e3c0b52..261a41b 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -357,6 +357,8 @@
 	.release =	scdrv_release,
 };
 
+static struct class *snsc_class;
+
 /*
  * scdrv_init
  *
@@ -372,7 +374,6 @@
 	char *devnamep;
 	struct sysctl_data_s *scd;
 	void *salbuf;
-	struct class_simple *snsc_class;
 	dev_t first_dev, dev;
 	nasid_t event_nasid = ia64_sn_get_console_nasid();
 
@@ -382,7 +383,7 @@
 		       __FUNCTION__);
 		return -ENODEV;
 	}
-	snsc_class = class_simple_create(THIS_MODULE, SYSCTL_BASENAME);
+	snsc_class = class_create(THIS_MODULE, SYSCTL_BASENAME);
 
 	for (cnode = 0; cnode < numionodes; cnode++) {
 			geoid = cnodeid_get_geoid(cnode);
@@ -436,7 +437,7 @@
 				continue;
 			}
 
-			class_simple_device_add(snsc_class, dev, NULL,
+			class_device_create(snsc_class, dev, NULL,
 						"%s", devname);
 
 			ia64_sn_irtr_intr_enable(scd->scd_nasid,
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index b8899f5..951545a 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -719,7 +719,7 @@
 
 /*****************************************************************************/
 
-static struct class_simple *stallion_class;
+static struct class *stallion_class;
 
 /*
  *	Loadable module initialization stuff.
@@ -777,13 +777,13 @@
 	}
 	for (i = 0; i < 4; i++) {
 		devfs_remove("staliomem/%d", i);
-		class_simple_device_remove(MKDEV(STL_SIOMEMMAJOR, i));
+		class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
 	}
 	devfs_remove("staliomem");
 	if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
 		printk("STALLION: failed to un-register serial memory device, "
 			"errno=%d\n", -i);
-	class_simple_destroy(stallion_class);
+	class_destroy(stallion_class);
 
 	if (stl_tmpwritebuf != (char *) NULL)
 		kfree(stl_tmpwritebuf);
@@ -3090,12 +3090,12 @@
 		printk("STALLION: failed to register serial board device\n");
 	devfs_mk_dir("staliomem");
 
-	stallion_class = class_simple_create(THIS_MODULE, "staliomem");
+	stallion_class = class_create(THIS_MODULE, "staliomem");
 	for (i = 0; i < 4; i++) {
 		devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
 				S_IFCHR|S_IRUSR|S_IWUSR,
 				"staliomem/%d", i);
-		class_simple_device_add(stallion_class, MKDEV(STL_SIOMEMMAJOR, i), NULL, "staliomem%d", i);
+		class_device_create(stallion_class, MKDEV(STL_SIOMEMMAJOR, i), NULL, "staliomem%d", i);
 	}
 
 	stl_serial->owner = THIS_MODULE;
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index f59f7cb..af79805 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -35,6 +35,7 @@
 #include <linux/spinlock.h>
 #include <linux/vt_kern.h>
 #include <linux/workqueue.h>
+#include <linux/kexec.h>
 
 #include <asm/ptrace.h>
 
@@ -94,6 +95,21 @@
 };
 #endif /* CONFIG_VT */
 
+#ifdef CONFIG_KEXEC
+/* crashdump sysrq handler */
+static void sysrq_handle_crashdump(int key, struct pt_regs *pt_regs,
+				struct tty_struct *tty)
+{
+	crash_kexec(pt_regs);
+}
+static struct sysrq_key_op sysrq_crashdump_op = {
+	.handler	= sysrq_handle_crashdump,
+	.help_msg	= "Crashdump",
+	.action_msg	= "Trigger a crashdump",
+	.enable_mask	= SYSRQ_ENABLE_DUMP,
+};
+#endif
+
 /* reboot sysrq handler */
 static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs,
 				struct tty_struct *tty) 
@@ -273,8 +289,12 @@
 		 it is handled specially on the sparc
 		 and will never arrive */
 /* b */	&sysrq_reboot_op,
-/* c */ NULL,
-/* d */	NULL,
+#ifdef CONFIG_KEXEC
+/* c */ &sysrq_crashdump_op,
+#else
+/* c */	NULL,
+#endif
+/* d */ NULL,
 /* e */	&sysrq_term_op,
 /* f */	&sysrq_moom_op,
 /* g */	NULL,
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c
index 0c5ba9d..659335d 100644
--- a/drivers/char/tipar.c
+++ b/drivers/char/tipar.c
@@ -90,7 +90,7 @@
 static unsigned int tp_count;	/* tipar count */
 static unsigned long opened;	/* opened devices */
 
-static struct class_simple *tipar_class;
+static struct class *tipar_class;
 
 /* --- macros for parport access -------------------------------------- */
 
@@ -436,7 +436,7 @@
 		goto out;
 	}
 
-	class_simple_device_add(tipar_class, MKDEV(TIPAR_MAJOR,
+	class_device_create(tipar_class, MKDEV(TIPAR_MAJOR,
 			TIPAR_MINOR + nr), NULL, "par%d", nr);
 	/* Use devfs, tree: /dev/ticables/par/[0..2] */
 	err = devfs_mk_cdev(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr),
@@ -458,8 +458,8 @@
 	goto out;
 
 out_class:
-	class_simple_device_remove(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr));
-	class_simple_destroy(tipar_class);
+	class_device_destroy(tipar_class, MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr));
+	class_destroy(tipar_class);
 out:
 	return err;
 }
@@ -505,7 +505,7 @@
 	/* Use devfs with tree: /dev/ticables/par/[0..2] */
 	devfs_mk_dir("ticables/par");
 
-	tipar_class = class_simple_create(THIS_MODULE, "ticables");
+	tipar_class = class_create(THIS_MODULE, "ticables");
 	if (IS_ERR(tipar_class)) {
 		err = PTR_ERR(tipar_class);
 		goto out_chrdev;
@@ -539,10 +539,10 @@
 		if (table[i].dev == NULL)
 			continue;
 		parport_unregister_device(table[i].dev);
-		class_simple_device_remove(MKDEV(TIPAR_MAJOR, i));
+		class_device_destroy(tipar_class, MKDEV(TIPAR_MAJOR, i));
 		devfs_remove("ticables/par/%d", i);
 	}
-	class_simple_destroy(tipar_class);
+	class_destroy(tipar_class);
 	devfs_remove("ticables/par");
 
 	pr_info("tipar: module unloaded\n");
diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c
index 58e21fe..0c6f521 100644
--- a/drivers/char/toshiba.c
+++ b/drivers/char/toshiba.c
@@ -73,16 +73,20 @@
 
 #define TOSH_MINOR_DEV 181
 
-static int tosh_id = 0x0000;
-static int tosh_bios = 0x0000;
-static int tosh_date = 0x0000;
-static int tosh_sci = 0x0000;
-static int tosh_fan = 0;
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jonathan Buzzard <jonathan@buzzard.org.uk>");
+MODULE_DESCRIPTION("Toshiba laptop SMM driver");
+MODULE_SUPPORTED_DEVICE("toshiba");
 
-static int tosh_fn = 0;
+static int tosh_fn;
+module_param_named(fn, tosh_fn, int, 0);
+MODULE_PARM_DESC(fn, "User specified Fn key detection port");
 
-module_param(tosh_fn, int, 0);
-
+static int tosh_id;
+static int tosh_bios;
+static int tosh_date;
+static int tosh_sci;
+static int tosh_fan;
 
 static int tosh_ioctl(struct inode *, struct file *, unsigned int,
 	unsigned long);
@@ -359,7 +363,7 @@
 	unsigned long address;
 
 	id = (0x100*(int) isa_readb(0xffffe))+((int) isa_readb(0xffffa));
-	
+
 	/* do we have a SCTTable machine identication number on our hands */
 
 	if (id==0xfc2f) {
@@ -424,7 +428,7 @@
 	}
 
 	/* call the Toshiba SCI support check routine */
-	
+
 	regs.eax = 0xf0f0;
 	regs.ebx = 0x0000;
 	regs.ecx = 0x0000;
@@ -440,7 +444,7 @@
 	/* if we get this far then we are running on a Toshiba (probably)! */
 
 	tosh_sci = regs.edx & 0xffff;
-	
+
 	/* next get the machine ID of the current laptop */
 
 	tosh_id = tosh_get_machine_id();
@@ -475,16 +479,15 @@
 	return 0;
 }
 
-int __init tosh_init(void)
+static int __init toshiba_init(void)
 {
 	int retval;
 	/* are we running on a Toshiba laptop */
 
-	if (tosh_probe()!=0)
-		return -EIO;
+	if (tosh_probe())
+		return -ENODEV;
 
-	printk(KERN_INFO "Toshiba System Managment Mode driver v"
-		TOSH_VERSION"\n");
+	printk(KERN_INFO "Toshiba System Managment Mode driver v" TOSH_VERSION "\n");
 
 	/* set the port to use for Fn status if not specified as a parameter */
 	if (tosh_fn==0x00)
@@ -492,12 +495,12 @@
 
 	/* register the device file */
 	retval = misc_register(&tosh_device);
-	if(retval < 0)
+	if (retval < 0)
 		return retval;
 
 #ifdef CONFIG_PROC_FS
 	/* register the proc entry */
-	if(create_proc_info_entry("toshiba", 0, NULL, tosh_get_info) == NULL){
+	if (create_proc_info_entry("toshiba", 0, NULL, tosh_get_info) == NULL) {
 		misc_deregister(&tosh_device);
 		return -ENOMEM;
 	}
@@ -506,27 +509,12 @@
 	return 0;
 }
 
-#ifdef MODULE
-int init_module(void)
+static void __exit toshiba_exit(void)
 {
-	return tosh_init();
-}
-
-void cleanup_module(void)
-{
-	/* remove the proc entry */
-
 	remove_proc_entry("toshiba", NULL);
-
-	/* unregister the device file */
-
 	misc_deregister(&tosh_device);
 }
-#endif
 
-MODULE_LICENSE("GPL");
-MODULE_PARM_DESC(tosh_fn, "User specified Fn key detection port");
-MODULE_AUTHOR("Jonathan Buzzard <jonathan@buzzard.org.uk>");
-MODULE_DESCRIPTION("Toshiba laptop SMM driver");
-MODULE_SUPPORTED_DEVICE("toshiba");
+module_init(toshiba_init);
+module_exit(toshiba_exit);
 
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 8723533..854475c 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -19,7 +19,7 @@
  * 
  * Note, the TPM chip is not interrupt driven (only polling)
  * and can have very long timeouts (minutes!). Hence the unusual
- * calls to schedule_timeout.
+ * calls to msleep.
  *
  */
 
@@ -28,19 +28,16 @@
 #include <linux/spinlock.h>
 #include "tpm.h"
 
-#define	TPM_MINOR			224	/* officially assigned */
-
-#define	TPM_BUFSIZE			2048
-
-/* PCI configuration addresses */
-#define	PCI_GEN_PMCON_1			0xA0
-#define	PCI_GEN1_DEC			0xE4
-#define	PCI_LPC_EN			0xE6
-#define	PCI_GEN2_DEC			0xEC
+enum tpm_const {
+	TPM_MINOR = 224,	/* officially assigned */
+	TPM_BUFSIZE = 2048,
+	TPM_NUM_DEVICES = 256,
+	TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int))
+};
 
 static LIST_HEAD(tpm_chip_list);
 static DEFINE_SPINLOCK(driver_lock);
-static int dev_mask[32];
+static int dev_mask[TPM_NUM_MASK_ENTRIES];
 
 static void user_reader_timeout(unsigned long ptr)
 {
@@ -52,92 +49,17 @@
 	up(&chip->buffer_mutex);
 }
 
-void tpm_time_expired(unsigned long ptr)
-{
-	int *exp = (int *) ptr;
-	*exp = 1;
-}
-
-EXPORT_SYMBOL_GPL(tpm_time_expired);
-
-/*
- * Initialize the LPC bus and enable the TPM ports
- */
-int tpm_lpc_bus_init(struct pci_dev *pci_dev, u16 base)
-{
-	u32 lpcenable, tmp;
-	int is_lpcm = 0;
-
-	switch (pci_dev->vendor) {
-	case PCI_VENDOR_ID_INTEL:
-		switch (pci_dev->device) {
-		case PCI_DEVICE_ID_INTEL_82801CA_12:
-		case PCI_DEVICE_ID_INTEL_82801DB_12:
-			is_lpcm = 1;
-			break;
-		}
-		/* init ICH (enable LPC) */
-		pci_read_config_dword(pci_dev, PCI_GEN1_DEC, &lpcenable);
-		lpcenable |= 0x20000000;
-		pci_write_config_dword(pci_dev, PCI_GEN1_DEC, lpcenable);
-
-		if (is_lpcm) {
-			pci_read_config_dword(pci_dev, PCI_GEN1_DEC,
-					      &lpcenable);
-			if ((lpcenable & 0x20000000) == 0) {
-				dev_err(&pci_dev->dev,
-					"cannot enable LPC\n");
-				return -ENODEV;
-			}
-		}
-
-		/* initialize TPM registers */
-		pci_read_config_dword(pci_dev, PCI_GEN2_DEC, &tmp);
-
-		if (!is_lpcm)
-			tmp = (tmp & 0xFFFF0000) | (base & 0xFFF0);
-		else
-			tmp =
-			    (tmp & 0xFFFF0000) | (base & 0xFFF0) |
-			    0x00000001;
-
-		pci_write_config_dword(pci_dev, PCI_GEN2_DEC, tmp);
-
-		if (is_lpcm) {
-			pci_read_config_dword(pci_dev, PCI_GEN_PMCON_1,
-					      &tmp);
-			tmp |= 0x00000004;	/* enable CLKRUN */
-			pci_write_config_dword(pci_dev, PCI_GEN_PMCON_1,
-					       tmp);
-		}
-		tpm_write_index(0x0D, 0x55);	/* unlock 4F */
-		tpm_write_index(0x0A, 0x00);	/* int disable */
-		tpm_write_index(0x08, base);	/* base addr lo */
-		tpm_write_index(0x09, (base & 0xFF00) >> 8);	/* base addr hi */
-		tpm_write_index(0x0D, 0xAA);	/* lock 4F */
-		break;
-	case PCI_VENDOR_ID_AMD:
-		/* nothing yet */
-		break;
-	}
-
-	return 0;
-}
-
-EXPORT_SYMBOL_GPL(tpm_lpc_bus_init);
-
 /*
  * Internal kernel interface to transmit TPM commands
  */
 static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
 			    size_t bufsiz)
 {
-	ssize_t len;
+	ssize_t rc;
 	u32 count;
-	__be32 *native_size;
+	unsigned long stop;
 
-	native_size = (__force __be32 *) (buf + 2);
-	count = be32_to_cpu(*native_size);
+	count = be32_to_cpu(*((__be32 *) (buf + 2)));
 
 	if (count == 0)
 		return -ENODATA;
@@ -149,53 +71,49 @@
 
 	down(&chip->tpm_mutex);
 
-	if ((len = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
+	if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
 		dev_err(&chip->pci_dev->dev,
-			"tpm_transmit: tpm_send: error %zd\n", len);
-		return len;
+			"tpm_transmit: tpm_send: error %zd\n", rc);
+		goto out;
 	}
 
-	down(&chip->timer_manipulation_mutex);
-	chip->time_expired = 0;
-	init_timer(&chip->device_timer);
-	chip->device_timer.function = tpm_time_expired;
-	chip->device_timer.expires = jiffies + 2 * 60 * HZ;
-	chip->device_timer.data = (unsigned long) &chip->time_expired;
-	add_timer(&chip->device_timer);
-	up(&chip->timer_manipulation_mutex);
-
+	stop = jiffies + 2 * 60 * HZ;
 	do {
 		u8 status = inb(chip->vendor->base + 1);
 		if ((status & chip->vendor->req_complete_mask) ==
 		    chip->vendor->req_complete_val) {
-			down(&chip->timer_manipulation_mutex);
-			del_singleshot_timer_sync(&chip->device_timer);
-			up(&chip->timer_manipulation_mutex);
 			goto out_recv;
 		}
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(TPM_TIMEOUT);
+
+		if ((status == chip->vendor->req_canceled)) {
+			dev_err(&chip->pci_dev->dev, "Operation Canceled\n");
+			rc = -ECANCELED;
+			goto out;
+		}
+
+		msleep(TPM_TIMEOUT);	/* CHECK */
 		rmb();
-	} while (!chip->time_expired);
+	} while (time_before(jiffies, stop));
 
 
 	chip->vendor->cancel(chip);
-	dev_err(&chip->pci_dev->dev, "Time expired\n");
-	up(&chip->tpm_mutex);
-	return -EIO;
+	dev_err(&chip->pci_dev->dev, "Operation Timed out\n");
+	rc = -ETIME;
+	goto out;
 
 out_recv:
-	len = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
-	if (len < 0)
+	rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
+	if (rc < 0)
 		dev_err(&chip->pci_dev->dev,
-			"tpm_transmit: tpm_recv: error %zd\n", len);
+			"tpm_transmit: tpm_recv: error %zd\n", rc);
+out:
 	up(&chip->tpm_mutex);
-	return len;
+	return rc;
 }
 
 #define TPM_DIGEST_SIZE 20
 #define CAP_PCR_RESULT_SIZE 18
-static u8 cap_pcr[] = {
+static const u8 cap_pcr[] = {
 	0, 193,			/* TPM_TAG_RQU_COMMAND */
 	0, 0, 0, 22,		/* length */
 	0, 0, 0, 101,		/* TPM_ORD_GetCapability */
@@ -205,75 +123,94 @@
 };
 
 #define READ_PCR_RESULT_SIZE 30
-static u8 pcrread[] = {
+static const u8 pcrread[] = {
 	0, 193,			/* TPM_TAG_RQU_COMMAND */
 	0, 0, 0, 14,		/* length */
 	0, 0, 0, 21,		/* TPM_ORD_PcrRead */
 	0, 0, 0, 0		/* PCR index */
 };
 
-static ssize_t show_pcrs(struct device *dev, char *buf)
+ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
+		      char *buf)
 {
 	u8 data[READ_PCR_RESULT_SIZE];
 	ssize_t len;
-	int i, j, index, num_pcrs;
+	int i, j, num_pcrs;
+	__be32 index;
 	char *str = buf;
 
 	struct tpm_chip *chip =
-	    pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+	    pci_get_drvdata(to_pci_dev(dev));
 	if (chip == NULL)
 		return -ENODEV;
 
 	memcpy(data, cap_pcr, sizeof(cap_pcr));
 	if ((len = tpm_transmit(chip, data, sizeof(data)))
-	    < CAP_PCR_RESULT_SIZE)
-		return len;
+	    < CAP_PCR_RESULT_SIZE) {
+		dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred "
+				"attempting to determine the number of PCRS\n",
+			be32_to_cpu(*((__be32 *) (data + 6))));
+		return 0;
+	}
 
-	num_pcrs = be32_to_cpu(*((__force __be32 *) (data + 14)));
+	num_pcrs = be32_to_cpu(*((__be32 *) (data + 14)));
 
 	for (i = 0; i < num_pcrs; i++) {
 		memcpy(data, pcrread, sizeof(pcrread));
 		index = cpu_to_be32(i);
 		memcpy(data + 10, &index, 4);
 		if ((len = tpm_transmit(chip, data, sizeof(data)))
-		    < READ_PCR_RESULT_SIZE)
-			return len;
+		    < READ_PCR_RESULT_SIZE){
+			dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred"
+				" attempting to read PCR %d of %d\n",
+				be32_to_cpu(*((__be32 *) (data + 6))), i, num_pcrs);
+			goto out;
+		}
 		str += sprintf(str, "PCR-%02d: ", i);
 		for (j = 0; j < TPM_DIGEST_SIZE; j++)
 			str += sprintf(str, "%02X ", *(data + 10 + j));
 		str += sprintf(str, "\n");
 	}
+out:
 	return str - buf;
 }
-
-static DEVICE_ATTR(pcrs, S_IRUGO, show_pcrs, NULL);
+EXPORT_SYMBOL_GPL(tpm_show_pcrs);
 
 #define  READ_PUBEK_RESULT_SIZE 314
-static u8 readpubek[] = {
+static const u8 readpubek[] = {
 	0, 193,			/* TPM_TAG_RQU_COMMAND */
 	0, 0, 0, 30,		/* length */
 	0, 0, 0, 124,		/* TPM_ORD_ReadPubek */
 };
 
-static ssize_t show_pubek(struct device *dev, char *buf)
+ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
+		       char *buf)
 {
-	u8 data[READ_PUBEK_RESULT_SIZE];
+	u8 *data;
 	ssize_t len;
-	__be32 *native_val;
-	int i;
+	int i, rc;
 	char *str = buf;
 
 	struct tpm_chip *chip =
-	    pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+	    pci_get_drvdata(to_pci_dev(dev));
 	if (chip == NULL)
 		return -ENODEV;
 
+	data = kmalloc(READ_PUBEK_RESULT_SIZE, GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
 	memcpy(data, readpubek, sizeof(readpubek));
 	memset(data + sizeof(readpubek), 0, 20);	/* zero nonce */
 
-	if ((len = tpm_transmit(chip, data, sizeof(data))) <
-	    READ_PUBEK_RESULT_SIZE)
-		return len;
+	if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) <
+	    READ_PUBEK_RESULT_SIZE) {
+		dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred "
+				"attempting to read the PUBEK\n",
+			    be32_to_cpu(*((__be32 *) (data + 6))));
+		rc = 0;
+		goto out;
+	}
 
 	/* 
 	   ignore header 10 bytes
@@ -286,8 +223,6 @@
 	   ignore checksum 20 bytes
 	 */
 
-	native_val = (__force __be32 *) (data + 34);
-
 	str +=
 	    sprintf(str,
 		    "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n"
@@ -298,21 +233,23 @@
 		    data[15], data[16], data[17], data[22], data[23],
 		    data[24], data[25], data[26], data[27], data[28],
 		    data[29], data[30], data[31], data[32], data[33],
-		    be32_to_cpu(*native_val)
-	    );
+		    be32_to_cpu(*((__be32 *) (data + 34))));
 
 	for (i = 0; i < 256; i++) {
-		str += sprintf(str, "%02X ", data[i + 39]);
+		str += sprintf(str, "%02X ", data[i + 38]);
 		if ((i + 1) % 16 == 0)
 			str += sprintf(str, "\n");
 	}
-	return str - buf;
+	rc = str - buf;
+out:
+	kfree(data);
+	return rc;
 }
 
-static DEVICE_ATTR(pubek, S_IRUGO, show_pubek, NULL);
+EXPORT_SYMBOL_GPL(tpm_show_pubek);
 
 #define CAP_VER_RESULT_SIZE 18
-static u8 cap_version[] = {
+static const u8 cap_version[] = {
 	0, 193,			/* TPM_TAG_RQU_COMMAND */
 	0, 0, 0, 18,		/* length */
 	0, 0, 0, 101,		/* TPM_ORD_GetCapability */
@@ -321,7 +258,7 @@
 };
 
 #define CAP_MANUFACTURER_RESULT_SIZE 18
-static u8 cap_manufacturer[] = {
+static const u8 cap_manufacturer[] = {
 	0, 193,			/* TPM_TAG_RQU_COMMAND */
 	0, 0, 0, 22,		/* length */
 	0, 0, 0, 101,		/* TPM_ORD_GetCapability */
@@ -330,14 +267,15 @@
 	0, 0, 1, 3
 };
 
-static ssize_t show_caps(struct device *dev, char *buf)
+ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
+		      char *buf)
 {
-	u8 data[READ_PUBEK_RESULT_SIZE];
+	u8 data[sizeof(cap_manufacturer)];
 	ssize_t len;
 	char *str = buf;
 
 	struct tpm_chip *chip =
-	    pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+	    pci_get_drvdata(to_pci_dev(dev));
 	if (chip == NULL)
 		return -ENODEV;
 
@@ -348,7 +286,7 @@
 		return len;
 
 	str += sprintf(str, "Manufacturer: 0x%x\n",
-		       be32_to_cpu(*(data + 14)));
+		       be32_to_cpu(*((__be32 *) (data + 14))));
 
 	memcpy(data, cap_version, sizeof(cap_version));
 
@@ -363,8 +301,20 @@
 
 	return str - buf;
 }
+EXPORT_SYMBOL_GPL(tpm_show_caps);
 
-static DEVICE_ATTR(caps, S_IRUGO, show_caps, NULL);
+ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct tpm_chip *chip = dev_get_drvdata(dev);
+	if (chip == NULL)
+		return 0;
+
+	chip->vendor->cancel(chip);
+	return count;
+}
+EXPORT_SYMBOL_GPL(tpm_store_cancel);
+
 
 /*
  * Device file system interface to the TPM
@@ -422,24 +372,15 @@
 int tpm_release(struct inode *inode, struct file *file)
 {
 	struct tpm_chip *chip = file->private_data;
-	
-	file->private_data = NULL;
 
 	spin_lock(&driver_lock);
+	file->private_data = NULL;
 	chip->num_opens--;
-	spin_unlock(&driver_lock);
-
-	down(&chip->timer_manipulation_mutex);
-	if (timer_pending(&chip->user_read_timer))
-		del_singleshot_timer_sync(&chip->user_read_timer);
-	else if (timer_pending(&chip->device_timer))
-		del_singleshot_timer_sync(&chip->device_timer);
-	up(&chip->timer_manipulation_mutex);
-
-	kfree(chip->data_buffer);
+	del_singleshot_timer_sync(&chip->user_read_timer);
 	atomic_set(&chip->data_pending, 0);
-
 	pci_dev_put(chip->pci_dev);
+	kfree(chip->data_buffer);
+	spin_unlock(&driver_lock);
 	return 0;
 }
 
@@ -453,10 +394,8 @@
 
 	/* cannot perform a write until the read has cleared
 	   either via tpm_read or a user_read_timer timeout */
-	while (atomic_read(&chip->data_pending) != 0) {
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(TPM_TIMEOUT);
-	}
+	while (atomic_read(&chip->data_pending) != 0)
+		msleep(TPM_TIMEOUT);
 
 	down(&chip->buffer_mutex);
 
@@ -476,13 +415,7 @@
 	up(&chip->buffer_mutex);
 
 	/* Set a timeout by which the reader must come claim the result */
-	down(&chip->timer_manipulation_mutex);
-	init_timer(&chip->user_read_timer);
-	chip->user_read_timer.function = user_reader_timeout;
-	chip->user_read_timer.data = (unsigned long) chip;
-	chip->user_read_timer.expires = jiffies + (60 * HZ);
-	add_timer(&chip->user_read_timer);
-	up(&chip->timer_manipulation_mutex);
+	mod_timer(&chip->user_read_timer, jiffies + (60 * HZ));
 
 	return in_size;
 }
@@ -493,29 +426,19 @@
 		 size_t size, loff_t * off)
 {
 	struct tpm_chip *chip = file->private_data;
-	int ret_size = -ENODATA;
+	int ret_size;
 
-	if (atomic_read(&chip->data_pending) != 0) {	/* Result available */
-		down(&chip->timer_manipulation_mutex);
-		del_singleshot_timer_sync(&chip->user_read_timer);
-		up(&chip->timer_manipulation_mutex);
+	del_singleshot_timer_sync(&chip->user_read_timer);
+	ret_size = atomic_read(&chip->data_pending);
+	atomic_set(&chip->data_pending, 0);
+	if (ret_size > 0) {	/* relay data */
+		if (size < ret_size)
+			ret_size = size;
 
 		down(&chip->buffer_mutex);
-
-		ret_size = atomic_read(&chip->data_pending);
-		atomic_set(&chip->data_pending, 0);
-
-		if (ret_size == 0)	/* timeout just occurred */
-			ret_size = -ETIME;
-		else if (ret_size > 0) {	/* relay data */
-			if (size < ret_size)
-				ret_size = size;
-
-			if (copy_to_user((void __user *) buf,
-					 chip->data_buffer, ret_size)) {
-				ret_size = -EFAULT;
-			}
-		}
+		if (copy_to_user
+		    ((void __user *) buf, chip->data_buffer, ret_size))
+			ret_size = -EFAULT;
 		up(&chip->buffer_mutex);
 	}
 
@@ -541,14 +464,13 @@
 
 	pci_set_drvdata(pci_dev, NULL);
 	misc_deregister(&chip->vendor->miscdev);
+	kfree(&chip->vendor->miscdev.name);
 
-	device_remove_file(&pci_dev->dev, &dev_attr_pubek);
-	device_remove_file(&pci_dev->dev, &dev_attr_pcrs);
-	device_remove_file(&pci_dev->dev, &dev_attr_caps);
+	sysfs_remove_group(&pci_dev->dev.kobj, chip->vendor->attr_group);
 
 	pci_disable_device(pci_dev);
 
-	dev_mask[chip->dev_num / 32] &= !(1 << (chip->dev_num % 32));
+	dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= !(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES));
 
 	kfree(chip);
 
@@ -590,10 +512,6 @@
 	if (chip == NULL)
 		return -ENODEV;
 
-	spin_lock(&driver_lock);
-	tpm_lpc_bus_init(pci_dev, chip->vendor->base);
-	spin_unlock(&driver_lock);
-
 	return 0;
 }
 
@@ -609,7 +527,9 @@
 int tpm_register_hardware(struct pci_dev *pci_dev,
 			  struct tpm_vendor_specific *entry)
 {
-	char devname[7];
+#define DEVNAME_SIZE 7
+
+	char *devname;
 	struct tpm_chip *chip;
 	int i, j;
 
@@ -622,17 +542,21 @@
 
 	init_MUTEX(&chip->buffer_mutex);
 	init_MUTEX(&chip->tpm_mutex);
-	init_MUTEX(&chip->timer_manipulation_mutex);
 	INIT_LIST_HEAD(&chip->list);
 
+	init_timer(&chip->user_read_timer);
+	chip->user_read_timer.function = user_reader_timeout;
+	chip->user_read_timer.data = (unsigned long) chip;
+
 	chip->vendor = entry;
 
 	chip->dev_num = -1;
 
-	for (i = 0; i < 32; i++)
-		for (j = 0; j < 8; j++)
+	for (i = 0; i < TPM_NUM_MASK_ENTRIES; i++)
+		for (j = 0; j < 8 * sizeof(int); j++)
 			if ((dev_mask[i] & (1 << j)) == 0) {
-				chip->dev_num = i * 32 + j;
+				chip->dev_num =
+				    i * TPM_NUM_MASK_ENTRIES + j;
 				dev_mask[i] |= 1 << j;
 				goto dev_num_search_complete;
 			}
@@ -648,7 +572,8 @@
 	else
 		chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR;
 
-	snprintf(devname, sizeof(devname), "%s%d", "tpm", chip->dev_num);
+	devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL);
+	scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num);
 	chip->vendor->miscdev.name = devname;
 
 	chip->vendor->miscdev.dev = &(pci_dev->dev);
@@ -665,32 +590,21 @@
 		return -ENODEV;
 	}
 
+	spin_lock(&driver_lock);
+
 	pci_set_drvdata(pci_dev, chip);
 
 	list_add(&chip->list, &tpm_chip_list);
 
-	device_create_file(&pci_dev->dev, &dev_attr_pubek);
-	device_create_file(&pci_dev->dev, &dev_attr_pcrs);
-	device_create_file(&pci_dev->dev, &dev_attr_caps);
+	spin_unlock(&driver_lock);
+
+	sysfs_create_group(&pci_dev->dev.kobj, chip->vendor->attr_group);
 
 	return 0;
 }
 
 EXPORT_SYMBOL_GPL(tpm_register_hardware);
 
-static int __init init_tpm(void)
-{
-	return 0;
-}
-
-static void __exit cleanup_tpm(void)
-{
-
-}
-
-module_init(init_tpm);
-module_exit(cleanup_tpm);
-
 MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
 MODULE_DESCRIPTION("TPM Driver");
 MODULE_VERSION("2.0");
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index de0c796..373b41f 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -25,23 +25,38 @@
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
 
-#define TPM_TIMEOUT msecs_to_jiffies(5)
+enum tpm_timeout {
+	TPM_TIMEOUT = 5,	/* msecs */
+};
 
 /* TPM addresses */
-#define	TPM_ADDR			0x4E
-#define	TPM_DATA			0x4F
+enum tpm_addr {
+	TPM_SUPERIO_ADDR = 0x2E,
+	TPM_ADDR = 0x4E,
+};
+
+extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr,
+				char *);
+extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr,
+				char *);
+extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr,
+				char *);
+extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr,
+				const char *, size_t);
 
 struct tpm_chip;
 
 struct tpm_vendor_specific {
 	u8 req_complete_mask;
 	u8 req_complete_val;
+	u8 req_canceled;
 	u16 base;		/* TPM base address */
 
 	int (*recv) (struct tpm_chip *, u8 *, size_t);
 	int (*send) (struct tpm_chip *, u8 *, size_t);
 	void (*cancel) (struct tpm_chip *);
 	struct miscdevice miscdev;
+	struct attribute_group *attr_group;
 };
 
 struct tpm_chip {
@@ -58,29 +73,24 @@
 
 	struct timer_list user_read_timer;	/* user needs to claim result */
 	struct semaphore tpm_mutex;	/* tpm is processing */
-	struct timer_list device_timer;	/* tpm is processing */
-	struct semaphore timer_manipulation_mutex;
 
 	struct tpm_vendor_specific *vendor;
 
 	struct list_head list;
 };
 
-static inline int tpm_read_index(int index)
+static inline int tpm_read_index(int base, int index)
 {
-	outb(index, TPM_ADDR);
-	return inb(TPM_DATA) & 0xFF;
+	outb(index, base);
+	return inb(base+1) & 0xFF;
 }
 
-static inline void tpm_write_index(int index, int value)
+static inline void tpm_write_index(int base, int index, int value)
 {
-	outb(index, TPM_ADDR);
-	outb(value & 0xFF, TPM_DATA);
+	outb(index, base);
+	outb(value & 0xFF, base+1);
 }
 
-extern void tpm_time_expired(unsigned long);
-extern int tpm_lpc_bus_init(struct pci_dev *, u16);
-
 extern int tpm_register_hardware(struct pci_dev *,
 				 struct tpm_vendor_specific *);
 extern int tpm_open(struct inode *, struct file *);
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c
index f9333e7..cc2cc77 100644
--- a/drivers/char/tpm/tpm_atmel.c
+++ b/drivers/char/tpm/tpm_atmel.c
@@ -22,17 +22,23 @@
 #include "tpm.h"
 
 /* Atmel definitions */
-#define	TPM_ATML_BASE			0x400
+enum tpm_atmel_addr {
+	TPM_ATMEL_BASE_ADDR_LO = 0x08,
+	TPM_ATMEL_BASE_ADDR_HI = 0x09
+};
 
 /* write status bits */
-#define	ATML_STATUS_ABORT		0x01
-#define	ATML_STATUS_LASTBYTE		0x04
-
+enum tpm_atmel_write_status {
+	ATML_STATUS_ABORT = 0x01,
+	ATML_STATUS_LASTBYTE = 0x04
+};
 /* read status bits */
-#define	ATML_STATUS_BUSY		0x01
-#define	ATML_STATUS_DATA_AVAIL		0x02
-#define	ATML_STATUS_REWRITE		0x04
-
+enum tpm_atmel_read_status {
+	ATML_STATUS_BUSY = 0x01,
+	ATML_STATUS_DATA_AVAIL = 0x02,
+	ATML_STATUS_REWRITE = 0x04,
+	ATML_STATUS_READY = 0x08
+};
 
 static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count)
 {
@@ -121,13 +127,29 @@
 	.release = tpm_release,
 };
 
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR |S_IWGRP, NULL, tpm_store_cancel);
+
+static struct attribute* atmel_attrs[] = {
+	&dev_attr_pubek.attr,
+	&dev_attr_pcrs.attr,
+	&dev_attr_caps.attr,
+	&dev_attr_cancel.attr,
+	0,
+};
+
+static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs };
+
 static struct tpm_vendor_specific tpm_atmel = {
 	.recv = tpm_atml_recv,
 	.send = tpm_atml_send,
 	.cancel = tpm_atml_cancel,
 	.req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL,
 	.req_complete_val = ATML_STATUS_DATA_AVAIL,
-	.base = TPM_ATML_BASE,
+	.req_canceled = ATML_STATUS_READY,
+	.attr_group = &atmel_attr_grp,
 	.miscdev = { .fops = &atmel_ops, },
 };
 
@@ -136,27 +158,29 @@
 {
 	u8 version[4];
 	int rc = 0;
+	int lo, hi;
 
 	if (pci_enable_device(pci_dev))
 		return -EIO;
 
-	if (tpm_lpc_bus_init(pci_dev, TPM_ATML_BASE)) {
-		rc = -ENODEV;
-		goto out_err;
-	}
+	lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
+	hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
+
+	tpm_atmel.base = (hi<<8)|lo;
+	dev_dbg( &pci_dev->dev, "Operating with base: 0x%x\n", tpm_atmel.base);
 
 	/* verify that it is an Atmel part */
-	if (tpm_read_index(4) != 'A' || tpm_read_index(5) != 'T'
-	    || tpm_read_index(6) != 'M' || tpm_read_index(7) != 'L') {
+	if (tpm_read_index(TPM_ADDR, 4) != 'A' || tpm_read_index(TPM_ADDR, 5) != 'T'
+	    || tpm_read_index(TPM_ADDR, 6) != 'M' || tpm_read_index(TPM_ADDR, 7) != 'L') {
 		rc = -ENODEV;
 		goto out_err;
 	}
 
 	/* query chip for its version number */
-	if ((version[0] = tpm_read_index(0x00)) != 0xFF) {
-		version[1] = tpm_read_index(0x01);
-		version[2] = tpm_read_index(0x02);
-		version[3] = tpm_read_index(0x03);
+	if ((version[0] = tpm_read_index(TPM_ADDR, 0x00)) != 0xFF) {
+		version[1] = tpm_read_index(TPM_ADDR, 0x01);
+		version[2] = tpm_read_index(TPM_ADDR, 0x02);
+		version[3] = tpm_read_index(TPM_ADDR, 0x03);
 	} else {
 		dev_info(&pci_dev->dev, "version query failed\n");
 		rc = -ENODEV;
@@ -183,6 +207,7 @@
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
 	{PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
+	{PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6LPC)},
 	{0,}
 };
 
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
index 9cce833a..b412734 100644
--- a/drivers/char/tpm/tpm_nsc.c
+++ b/drivers/char/tpm/tpm_nsc.c
@@ -22,43 +22,52 @@
 #include "tpm.h"
 
 /* National definitions */
-#define	TPM_NSC_BASE			0x360
-#define	TPM_NSC_IRQ			0x07
+enum tpm_nsc_addr{
+	TPM_NSC_IRQ = 0x07,
+	TPM_NSC_BASE0_HI = 0x60,
+	TPM_NSC_BASE0_LO = 0x61,
+	TPM_NSC_BASE1_HI = 0x62,
+	TPM_NSC_BASE1_LO = 0x63
+};
 
-#define	NSC_LDN_INDEX			0x07
-#define	NSC_SID_INDEX			0x20
-#define	NSC_LDC_INDEX			0x30
-#define	NSC_DIO_INDEX			0x60
-#define	NSC_CIO_INDEX			0x62
-#define	NSC_IRQ_INDEX			0x70
-#define	NSC_ITS_INDEX			0x71
+enum tpm_nsc_index {
+	NSC_LDN_INDEX = 0x07,
+	NSC_SID_INDEX = 0x20,
+	NSC_LDC_INDEX = 0x30,
+	NSC_DIO_INDEX = 0x60,
+	NSC_CIO_INDEX = 0x62,
+	NSC_IRQ_INDEX = 0x70,
+	NSC_ITS_INDEX = 0x71
+};
 
-#define	NSC_STATUS			0x01
-#define	NSC_COMMAND			0x01
-#define	NSC_DATA			0x00
+enum tpm_nsc_status_loc {
+	NSC_STATUS = 0x01,
+	NSC_COMMAND = 0x01,
+	NSC_DATA = 0x00
+};
 
 /* status bits */
-#define	NSC_STATUS_OBF			0x01	/* output buffer full */
-#define	NSC_STATUS_IBF			0x02	/* input buffer full */
-#define	NSC_STATUS_F0			0x04	/* F0 */
-#define	NSC_STATUS_A2			0x08	/* A2 */
-#define	NSC_STATUS_RDY			0x10	/* ready to receive command */
-#define	NSC_STATUS_IBR			0x20	/* ready to receive data */
+enum tpm_nsc_status {
+	NSC_STATUS_OBF = 0x01,	/* output buffer full */
+	NSC_STATUS_IBF = 0x02,	/* input buffer full */
+	NSC_STATUS_F0 = 0x04,	/* F0 */
+	NSC_STATUS_A2 = 0x08,	/* A2 */
+	NSC_STATUS_RDY = 0x10,	/* ready to receive command */
+	NSC_STATUS_IBR = 0x20	/* ready to receive data */
+};
 
 /* command bits */
-#define	NSC_COMMAND_NORMAL		0x01	/* normal mode */
-#define	NSC_COMMAND_EOC			0x03
-#define	NSC_COMMAND_CANCEL		0x22
-
+enum tpm_nsc_cmd_mode {
+	NSC_COMMAND_NORMAL = 0x01,	/* normal mode */
+	NSC_COMMAND_EOC = 0x03,
+	NSC_COMMAND_CANCEL = 0x22
+};
 /*
  * Wait for a certain status to appear
  */
 static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
 {
-	int expired = 0;
-	struct timer_list status_timer =
-	    TIMER_INITIALIZER(tpm_time_expired, jiffies + 10 * HZ,
-			      (unsigned long) &expired);
+	unsigned long stop;
 
 	/* status immediately available check */
 	*data = inb(chip->vendor->base + NSC_STATUS);
@@ -66,17 +75,14 @@
 		return 0;
 
 	/* wait for status */
-	add_timer(&status_timer);
+	stop = jiffies + 10 * HZ;
 	do {
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(TPM_TIMEOUT);
+		msleep(TPM_TIMEOUT);
 		*data = inb(chip->vendor->base + 1);
-		if ((*data & mask) == val) {
-			del_singleshot_timer_sync(&status_timer);
+		if ((*data & mask) == val)
 			return 0;
-		}
 	}
-	while (!expired);
+	while (time_before(jiffies, stop));
 
 	return -EBUSY;
 }
@@ -84,10 +90,7 @@
 static int nsc_wait_for_ready(struct tpm_chip *chip)
 {
 	int status;
-	int expired = 0;
-	struct timer_list status_timer =
-	    TIMER_INITIALIZER(tpm_time_expired, jiffies + 100,
-			      (unsigned long) &expired);
+	unsigned long stop;
 
 	/* status immediately available check */
 	status = inb(chip->vendor->base + NSC_STATUS);
@@ -97,19 +100,16 @@
 		return 0;
 
 	/* wait for status */
-	add_timer(&status_timer);
+	stop = jiffies + 100;
 	do {
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(TPM_TIMEOUT);
+		msleep(TPM_TIMEOUT);
 		status = inb(chip->vendor->base + NSC_STATUS);
 		if (status & NSC_STATUS_OBF)
 			status = inb(chip->vendor->base + NSC_DATA);
-		if (status & NSC_STATUS_RDY) {
-			del_singleshot_timer_sync(&status_timer);
+		if (status & NSC_STATUS_RDY)
 			return 0;
-		}
 	}
-	while (!expired);
+	while (time_before(jiffies, stop));
 
 	dev_info(&chip->pci_dev->dev, "wait for ready failed\n");
 	return -EBUSY;
@@ -150,7 +150,8 @@
 		*p = inb(chip->vendor->base + NSC_DATA);
 	}
 
-	if ((data & NSC_STATUS_F0) == 0) {
+	if ((data & NSC_STATUS_F0) == 0 &&
+	(wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0)) {
 		dev_err(&chip->pci_dev->dev, "F0 not set\n");
 		return -EIO;
 	}
@@ -228,100 +229,95 @@
 	.release = tpm_release,
 };
 
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR|S_IWGRP, NULL, tpm_store_cancel);
+
+static struct attribute * nsc_attrs[] = {
+	&dev_attr_pubek.attr,
+	&dev_attr_pcrs.attr,
+	&dev_attr_caps.attr,
+	&dev_attr_cancel.attr,
+	0,
+};
+
+static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs };
+
 static struct tpm_vendor_specific tpm_nsc = {
 	.recv = tpm_nsc_recv,
 	.send = tpm_nsc_send,
 	.cancel = tpm_nsc_cancel,
 	.req_complete_mask = NSC_STATUS_OBF,
 	.req_complete_val = NSC_STATUS_OBF,
-	.base = TPM_NSC_BASE,
+	.req_canceled = NSC_STATUS_RDY,
+	.attr_group = &nsc_attr_grp,
 	.miscdev = { .fops = &nsc_ops, },
-	
 };
 
 static int __devinit tpm_nsc_init(struct pci_dev *pci_dev,
 				  const struct pci_device_id *pci_id)
 {
 	int rc = 0;
+	int lo, hi;
+	int nscAddrBase = TPM_ADDR;
+
 
 	if (pci_enable_device(pci_dev))
 		return -EIO;
 
-	if (tpm_lpc_bus_init(pci_dev, TPM_NSC_BASE)) {
-		rc = -ENODEV;
-		goto out_err;
-	}
+	/* select PM channel 1 */
+	tpm_write_index(nscAddrBase,NSC_LDN_INDEX, 0x12);
 
 	/* verify that it is a National part (SID) */
-	if (tpm_read_index(NSC_SID_INDEX) != 0xEF) {
-		rc = -ENODEV;
-		goto out_err;
+	if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) {
+		nscAddrBase = (tpm_read_index(TPM_SUPERIO_ADDR, 0x2C)<<8)|
+			(tpm_read_index(TPM_SUPERIO_ADDR, 0x2B)&0xFE);
+		if (tpm_read_index(nscAddrBase, NSC_SID_INDEX) != 0xF6) {
+			rc = -ENODEV;
+			goto out_err;
+		}
 	}
 
+	hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI);
+	lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO);
+	tpm_nsc.base = (hi<<8) | lo;
+
 	dev_dbg(&pci_dev->dev, "NSC TPM detected\n");
 	dev_dbg(&pci_dev->dev,
 		"NSC LDN 0x%x, SID 0x%x, SRID 0x%x\n",
-		tpm_read_index(0x07), tpm_read_index(0x20),
-		tpm_read_index(0x27));
+		tpm_read_index(nscAddrBase,0x07), tpm_read_index(nscAddrBase,0x20),
+		tpm_read_index(nscAddrBase,0x27));
 	dev_dbg(&pci_dev->dev,
 		"NSC SIOCF1 0x%x SIOCF5 0x%x SIOCF6 0x%x SIOCF8 0x%x\n",
-		tpm_read_index(0x21), tpm_read_index(0x25),
-		tpm_read_index(0x26), tpm_read_index(0x28));
+		tpm_read_index(nscAddrBase,0x21), tpm_read_index(nscAddrBase,0x25),
+		tpm_read_index(nscAddrBase,0x26), tpm_read_index(nscAddrBase,0x28));
 	dev_dbg(&pci_dev->dev, "NSC IO Base0 0x%x\n",
-		(tpm_read_index(0x60) << 8) | tpm_read_index(0x61));
+		(tpm_read_index(nscAddrBase,0x60) << 8) | tpm_read_index(nscAddrBase,0x61));
 	dev_dbg(&pci_dev->dev, "NSC IO Base1 0x%x\n",
-		(tpm_read_index(0x62) << 8) | tpm_read_index(0x63));
+		(tpm_read_index(nscAddrBase,0x62) << 8) | tpm_read_index(nscAddrBase,0x63));
 	dev_dbg(&pci_dev->dev, "NSC Interrupt number and wakeup 0x%x\n",
-		tpm_read_index(0x70));
+		tpm_read_index(nscAddrBase,0x70));
 	dev_dbg(&pci_dev->dev, "NSC IRQ type select 0x%x\n",
-		tpm_read_index(0x71));
+		tpm_read_index(nscAddrBase,0x71));
 	dev_dbg(&pci_dev->dev,
 		"NSC DMA channel select0 0x%x, select1 0x%x\n",
-		tpm_read_index(0x74), tpm_read_index(0x75));
+		tpm_read_index(nscAddrBase,0x74), tpm_read_index(nscAddrBase,0x75));
 	dev_dbg(&pci_dev->dev,
 		"NSC Config "
 		"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
-		tpm_read_index(0xF0), tpm_read_index(0xF1),
-		tpm_read_index(0xF2), tpm_read_index(0xF3),
-		tpm_read_index(0xF4), tpm_read_index(0xF5),
-		tpm_read_index(0xF6), tpm_read_index(0xF7),
-		tpm_read_index(0xF8), tpm_read_index(0xF9));
+		tpm_read_index(nscAddrBase,0xF0), tpm_read_index(nscAddrBase,0xF1),
+		tpm_read_index(nscAddrBase,0xF2), tpm_read_index(nscAddrBase,0xF3),
+		tpm_read_index(nscAddrBase,0xF4), tpm_read_index(nscAddrBase,0xF5),
+		tpm_read_index(nscAddrBase,0xF6), tpm_read_index(nscAddrBase,0xF7),
+		tpm_read_index(nscAddrBase,0xF8), tpm_read_index(nscAddrBase,0xF9));
 
 	dev_info(&pci_dev->dev,
-		 "NSC PC21100 TPM revision %d\n",
-		 tpm_read_index(0x27) & 0x1F);
-
-	if (tpm_read_index(NSC_LDC_INDEX) == 0)
-		dev_info(&pci_dev->dev, ": NSC TPM not active\n");
-
-	/* select PM channel 1 */
-	tpm_write_index(NSC_LDN_INDEX, 0x12);
-	tpm_read_index(NSC_LDN_INDEX);
-
-	/* disable the DPM module */
-	tpm_write_index(NSC_LDC_INDEX, 0);
-	tpm_read_index(NSC_LDC_INDEX);
-
-	/* set the data register base addresses */
-	tpm_write_index(NSC_DIO_INDEX, TPM_NSC_BASE >> 8);
-	tpm_write_index(NSC_DIO_INDEX + 1, TPM_NSC_BASE);
-	tpm_read_index(NSC_DIO_INDEX);
-	tpm_read_index(NSC_DIO_INDEX + 1);
-
-	/* set the command register base addresses */
-	tpm_write_index(NSC_CIO_INDEX, (TPM_NSC_BASE + 1) >> 8);
-	tpm_write_index(NSC_CIO_INDEX + 1, (TPM_NSC_BASE + 1));
-	tpm_read_index(NSC_DIO_INDEX);
-	tpm_read_index(NSC_DIO_INDEX + 1);
-
-	/* set the interrupt number to be used for the host interface */
-	tpm_write_index(NSC_IRQ_INDEX, TPM_NSC_IRQ);
-	tpm_write_index(NSC_ITS_INDEX, 0x00);
-	tpm_read_index(NSC_IRQ_INDEX);
+		 "NSC TPM revision %d\n",
+		 tpm_read_index(nscAddrBase, 0x27) & 0x1F);
 
 	/* enable the DPM module */
-	tpm_write_index(NSC_LDC_INDEX, 0x01);
-	tpm_read_index(NSC_LDC_INDEX);
+	tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01);
 
 	if ((rc = tpm_register_hardware(pci_dev, &tpm_nsc)) < 0)
 		goto out_err;
@@ -339,6 +335,9 @@
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
 	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0)},
 	{PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
 	{0,}
 };
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 26e5e19..6e4be3b 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -94,6 +94,7 @@
 #include <linux/idr.h>
 #include <linux/wait.h>
 #include <linux/bitops.h>
+#include <linux/delay.h>
 
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -251,7 +252,7 @@
  
 static DEFINE_SPINLOCK(tty_ldisc_lock);
 static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
-static struct tty_ldisc tty_ldiscs[NR_LDISCS];	/* line disc dispatch table	*/
+static struct tty_ldisc tty_ldiscs[NR_LDISCS];	/* line disc dispatch table */
 
 int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
 {
@@ -262,24 +263,35 @@
 		return -EINVAL;
 	
 	spin_lock_irqsave(&tty_ldisc_lock, flags);
-	if (new_ldisc) {
-		tty_ldiscs[disc] = *new_ldisc;
-		tty_ldiscs[disc].num = disc;
-		tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
-		tty_ldiscs[disc].refcount = 0;
-	} else {
-		if(tty_ldiscs[disc].refcount)
-			ret = -EBUSY;
-		else
-			tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED;
-	}
+	tty_ldiscs[disc] = *new_ldisc;
+	tty_ldiscs[disc].num = disc;
+	tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
+	tty_ldiscs[disc].refcount = 0;
 	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
 	
 	return ret;
 }
-
 EXPORT_SYMBOL(tty_register_ldisc);
 
+int tty_unregister_ldisc(int disc)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	if (disc < N_TTY || disc >= NR_LDISCS)
+		return -EINVAL;
+
+	spin_lock_irqsave(&tty_ldisc_lock, flags);
+	if (tty_ldiscs[disc].refcount)
+		ret = -EBUSY;
+	else
+		tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED;
+	spin_unlock_irqrestore(&tty_ldisc_lock, flags);
+
+	return ret;
+}
+EXPORT_SYMBOL(tty_unregister_ldisc);
+
 struct tty_ldisc *tty_ldisc_get(int disc)
 {
 	unsigned long flags;
@@ -2169,12 +2181,11 @@
 	return tty_set_ldisc(tty, ldisc);
 }
 
-static int send_break(struct tty_struct *tty, int duration)
+static int send_break(struct tty_struct *tty, unsigned int duration)
 {
 	tty->driver->break_ctl(tty, -1);
 	if (!signal_pending(current)) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(duration);
+		msleep_interruptible(duration);
 	}
 	tty->driver->break_ctl(tty, 0);
 	if (signal_pending(current))
@@ -2355,10 +2366,10 @@
 			 * all by anyone?
 			 */
 			if (!arg)
-				return send_break(tty, HZ/4);
+				return send_break(tty, 250);
 			return 0;
 		case TCSBRKP:	/* support for POSIX tcsendbreak() */	
-			return send_break(tty, arg ? arg*(HZ/10) : HZ/4);
+			return send_break(tty, arg ? arg*100 : 250);
 
 		case TIOCMGET:
 			return tty_tiocmget(tty, file, p);
@@ -2654,7 +2665,7 @@
 	tty->driver->write(tty, &ch, 1);
 }
 
-static struct class_simple *tty_class;
+static struct class *tty_class;
 
 /**
  * tty_register_device - register a tty device
@@ -2687,7 +2698,7 @@
 		pty_line_name(driver, index, name);
 	else
 		tty_line_name(driver, index, name);
-	class_simple_device_add(tty_class, dev, device, name);
+	class_device_create(tty_class, dev, device, name);
 }
 
 /**
@@ -2701,7 +2712,7 @@
 void tty_unregister_device(struct tty_driver *driver, unsigned index)
 {
 	devfs_remove("%s%d", driver->devfs_name, index + driver->name_base);
-	class_simple_device_remove(MKDEV(driver->major, driver->minor_start) + index);
+	class_device_destroy(tty_class, MKDEV(driver->major, driver->minor_start) + index);
 }
 
 EXPORT_SYMBOL(tty_register_device);
@@ -2918,7 +2929,7 @@
 
 static int __init tty_class_init(void)
 {
-	tty_class = class_simple_create(THIS_MODULE, "tty");
+	tty_class = class_create(THIS_MODULE, "tty");
 	if (IS_ERR(tty_class))
 		return PTR_ERR(tty_class);
 	return 0;
@@ -2947,14 +2958,14 @@
 	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
 		panic("Couldn't register /dev/tty driver\n");
 	devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty");
-	class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
+	class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
 
 	cdev_init(&console_cdev, &console_fops);
 	if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
 	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
 		panic("Couldn't register /dev/console driver\n");
 	devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console");
-	class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
+	class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
 
 #ifdef CONFIG_UNIX98_PTYS
 	cdev_init(&ptmx_cdev, &ptmx_fops);
@@ -2962,7 +2973,7 @@
 	    register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
 		panic("Couldn't register /dev/ptmx driver\n");
 	devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx");
-	class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
+	class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
 #endif
 
 #ifdef CONFIG_VT
@@ -2971,7 +2982,7 @@
 	    register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
 		panic("Couldn't register /dev/tty0 driver\n");
 	devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vc/0");
-	class_simple_device_add(tty_class, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
+	class_device_create(tty_class, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
 
 	vty_init();
 #endif
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index 7abe405..79c2928 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -474,7 +474,7 @@
 	.open		= vcs_open,
 };
 
-static struct class_simple *vc_class;
+static struct class *vc_class;
 
 void vcs_make_devfs(struct tty_struct *tty)
 {
@@ -484,26 +484,26 @@
 	devfs_mk_cdev(MKDEV(VCS_MAJOR, tty->index + 129),
 			S_IFCHR|S_IRUSR|S_IWUSR,
 			"vcc/a%u", tty->index + 1);
-	class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, tty->index + 1), NULL, "vcs%u", tty->index + 1);
-	class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, tty->index + 129), NULL, "vcsa%u", tty->index + 1);
+	class_device_create(vc_class, MKDEV(VCS_MAJOR, tty->index + 1), NULL, "vcs%u", tty->index + 1);
+	class_device_create(vc_class, MKDEV(VCS_MAJOR, tty->index + 129), NULL, "vcsa%u", tty->index + 1);
 }
 void vcs_remove_devfs(struct tty_struct *tty)
 {
 	devfs_remove("vcc/%u", tty->index + 1);
 	devfs_remove("vcc/a%u", tty->index + 1);
-	class_simple_device_remove(MKDEV(VCS_MAJOR, tty->index + 1));
-	class_simple_device_remove(MKDEV(VCS_MAJOR, tty->index + 129));
+	class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1));
+	class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 129));
 }
 
 int __init vcs_init(void)
 {
 	if (register_chrdev(VCS_MAJOR, "vcs", &vcs_fops))
 		panic("unable to get major %d for vcs device", VCS_MAJOR);
-	vc_class = class_simple_create(THIS_MODULE, "vc");
+	vc_class = class_create(THIS_MODULE, "vc");
 
 	devfs_mk_cdev(MKDEV(VCS_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/0");
 	devfs_mk_cdev(MKDEV(VCS_MAJOR, 128), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/a0");
-	class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
-	class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
+	class_device_create(vc_class, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
+	class_device_create(vc_class, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
 	return 0;
 }
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index aea3cbf..4764b4f 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -237,7 +237,7 @@
 
 static struct mtget viomtget[VIOTAPE_MAX_TAPE];
 
-static struct class_simple *tape_class;
+static struct class *tape_class;
 
 static struct device *tape_device[VIOTAPE_MAX_TAPE];
 
@@ -956,9 +956,9 @@
 	state[i].cur_part = 0;
 	for (j = 0; j < MAX_PARTITIONS; ++j)
 		state[i].part_stat_rwi[j] = VIOT_IDLE;
-	class_simple_device_add(tape_class, MKDEV(VIOTAPE_MAJOR, i), NULL,
+	class_device_create(tape_class, MKDEV(VIOTAPE_MAJOR, i), NULL,
 			"iseries!vt%d", i);
-	class_simple_device_add(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80),
+	class_device_create(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80),
 			NULL, "iseries!nvt%d", i);
 	devfs_mk_cdev(MKDEV(VIOTAPE_MAJOR, i), S_IFCHR | S_IRUSR | S_IWUSR,
 			"iseries/vt%d", i);
@@ -980,8 +980,8 @@
 	devfs_remove("iseries/nvt%d", i);
 	devfs_remove("iseries/vt%d", i);
 	devfs_unregister_tape(state[i].dev_handle);
-	class_simple_device_remove(MKDEV(VIOTAPE_MAJOR, i | 0x80));
-	class_simple_device_remove(MKDEV(VIOTAPE_MAJOR, i));
+	class_device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80));
+	class_device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i));
 	return 0;
 }
 
@@ -1045,7 +1045,7 @@
 		goto clear_handler;
 	}
 
-	tape_class = class_simple_create(THIS_MODULE, "tape");
+	tape_class = class_create(THIS_MODULE, "tape");
 	if (IS_ERR(tape_class)) {
 		printk(VIOTAPE_KERN_WARN "Unable to allocat class\n");
 		ret = PTR_ERR(tape_class);
@@ -1070,7 +1070,7 @@
 	return 0;
 
 unreg_class:
-	class_simple_destroy(tape_class);
+	class_destroy(tape_class);
 unreg_chrdev:
 	unregister_chrdev(VIOTAPE_MAJOR, "viotape");
 clear_handler:
@@ -1110,7 +1110,7 @@
 
 	remove_proc_entry("iSeries/viotape", NULL);
 	vio_unregister_driver(&viotape_driver);
-	class_simple_destroy(tape_class);
+	class_destroy(tape_class);
 	ret = unregister_chrdev(VIOTAPE_MAJOR, "viotape");
 	if (ret < 0)
 		printk(VIOTAPE_KERN_WARN "Error unregistering device: %d\n",
diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c
new file mode 100644
index 0000000..683278b
--- /dev/null
+++ b/drivers/char/vr41xx_giu.c
@@ -0,0 +1,743 @@
+/*
+ *  Driver for NEC VR4100 series General-purpose I/O Unit.
+ *
+ *  Copyright (C) 2002 MontaVista Software Inc.
+ *	Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
+ *  Copyright (C) 2003-2005  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ *  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/device.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/cpu.h>
+#include <asm/io.h>
+#include <asm/vr41xx/giu.h>
+#include <asm/vr41xx/vr41xx.h>
+
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>");
+MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
+MODULE_LICENSE("GPL");
+
+static int major;	/* default is dynamic major device number */
+module_param(major, int, 0);
+MODULE_PARM_DESC(major, "Major device number");
+
+#define GIU_TYPE1_START		0x0b000100UL
+#define GIU_TYPE1_SIZE		0x20UL
+
+#define GIU_TYPE2_START		0x0f000140UL
+#define GIU_TYPE2_SIZE		0x20UL
+
+#define GIU_TYPE3_START		0x0f000140UL
+#define GIU_TYPE3_SIZE		0x28UL
+
+#define GIU_PULLUPDOWN_START	0x0b0002e0UL
+#define GIU_PULLUPDOWN_SIZE	0x04UL
+
+#define GIUIOSELL	0x00
+#define GIUIOSELH	0x02
+#define GIUPIODL	0x04
+#define GIUPIODH	0x06
+#define GIUINTSTATL	0x08
+#define GIUINTSTATH	0x0a
+#define GIUINTENL	0x0c
+#define GIUINTENH	0x0e
+#define GIUINTTYPL	0x10
+#define GIUINTTYPH	0x12
+#define GIUINTALSELL	0x14
+#define GIUINTALSELH	0x16
+#define GIUINTHTSELL	0x18
+#define GIUINTHTSELH	0x1a
+#define GIUPODATL	0x1c
+#define GIUPODATEN	0x1c
+#define GIUPODATH	0x1e
+ #define PIOEN0		0x0100
+ #define PIOEN1		0x0200
+#define GIUPODAT	0x1e
+#define GIUFEDGEINHL	0x20
+#define GIUFEDGEINHH	0x22
+#define GIUREDGEINHL	0x24
+#define GIUREDGEINHH	0x26
+
+#define GIUUSEUPDN	0x1e0
+#define GIUTERMUPDN	0x1e2
+
+#define GPIO_HAS_PULLUPDOWN_IO		0x0001
+#define GPIO_HAS_OUTPUT_ENABLE		0x0002
+#define GPIO_HAS_INTERRUPT_EDGE_SELECT	0x0100
+
+static spinlock_t giu_lock;
+static struct resource *giu_resource1;
+static struct resource *giu_resource2;
+static unsigned long giu_flags;
+static unsigned int giu_nr_pins;
+
+static void __iomem *giu_base;
+
+#define giu_read(offset)		readw(giu_base + (offset))
+#define giu_write(offset, value)	writew((value), giu_base + (offset))
+
+#define GPIO_PIN_OF_IRQ(irq)	((irq) - GIU_IRQ_BASE)
+#define GIUINT_HIGH_OFFSET	16
+#define GIUINT_HIGH_MAX		32
+
+static inline uint16_t giu_set(uint16_t offset, uint16_t set)
+{
+	uint16_t data;
+
+	data = giu_read(offset);
+	data |= set;
+	giu_write(offset, data);
+
+	return data;
+}
+
+static inline uint16_t giu_clear(uint16_t offset, uint16_t clear)
+{
+	uint16_t data;
+
+	data = giu_read(offset);
+	data &= ~clear;
+	giu_write(offset, data);
+
+	return data;
+}
+
+static unsigned int startup_giuint_low_irq(unsigned int irq)
+{
+	unsigned int pin;
+
+	pin = GPIO_PIN_OF_IRQ(irq);
+	giu_write(GIUINTSTATL, 1 << pin);
+	giu_set(GIUINTENL, 1 << pin);
+
+	return 0;
+}
+
+static void shutdown_giuint_low_irq(unsigned int irq)
+{
+	giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
+}
+
+static void enable_giuint_low_irq(unsigned int irq)
+{
+	giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
+}
+
+#define disable_giuint_low_irq	shutdown_giuint_low_irq
+
+static void ack_giuint_low_irq(unsigned int irq)
+{
+	unsigned int pin;
+
+	pin = GPIO_PIN_OF_IRQ(irq);
+	giu_clear(GIUINTENL, 1 << pin);
+	giu_write(GIUINTSTATL, 1 << pin);
+}
+
+static void end_giuint_low_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+		giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
+}
+
+static struct hw_interrupt_type giuint_low_irq_type = {
+	.typename	= "GIUINTL",
+	.startup	= startup_giuint_low_irq,
+	.shutdown	= shutdown_giuint_low_irq,
+	.enable		= enable_giuint_low_irq,
+	.disable	= disable_giuint_low_irq,
+	.ack		= ack_giuint_low_irq,
+	.end		= end_giuint_low_irq,
+};
+
+static unsigned int startup_giuint_high_irq(unsigned int irq)
+{
+	unsigned int pin;
+
+	pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET;
+	giu_write(GIUINTSTATH, 1 << pin);
+	giu_set(GIUINTENH, 1 << pin);
+
+	return 0;
+}
+
+static void shutdown_giuint_high_irq(unsigned int irq)
+{
+	giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
+}
+
+static void enable_giuint_high_irq(unsigned int irq)
+{
+	giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
+}
+
+#define disable_giuint_high_irq	shutdown_giuint_high_irq
+
+static void ack_giuint_high_irq(unsigned int irq)
+{
+	unsigned int pin;
+
+	pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET;
+	giu_clear(GIUINTENH, 1 << pin);
+	giu_write(GIUINTSTATH, 1 << pin);
+}
+
+static void end_giuint_high_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+		giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
+}
+
+static struct hw_interrupt_type giuint_high_irq_type = {
+	.typename	= "GIUINTH",
+	.startup	= startup_giuint_high_irq,
+	.shutdown	= shutdown_giuint_high_irq,
+	.enable		= enable_giuint_high_irq,
+	.disable	= disable_giuint_high_irq,
+	.ack		= ack_giuint_high_irq,
+	.end		= end_giuint_high_irq,
+};
+
+static int giu_get_irq(unsigned int irq, struct pt_regs *regs)
+{
+	uint16_t pendl, pendh, maskl, maskh;
+	int i;
+
+	pendl = giu_read(GIUINTSTATL);
+	pendh = giu_read(GIUINTSTATH);
+	maskl = giu_read(GIUINTENL);
+	maskh = giu_read(GIUINTENH);
+
+	maskl &= pendl;
+	maskh &= pendh;
+
+	if (maskl) {
+		for (i = 0; i < 16; i++) {
+			if (maskl & (1 << i))
+				return GIU_IRQ(i);
+		}
+	} else if (maskh) {
+		for (i = 0; i < 16; i++) {
+			if (maskh & (1 << i))
+				return GIU_IRQ(i + GIUINT_HIGH_OFFSET);
+		}
+	}
+
+	printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
+	       maskl, pendl, maskh, pendh);
+
+	atomic_inc(&irq_err_count);
+
+	return -EINVAL;
+}
+
+void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal)
+{
+	uint16_t mask;
+
+	if (pin < GIUINT_HIGH_OFFSET) {
+		mask = 1 << pin;
+		if (trigger != IRQ_TRIGGER_LEVEL) {
+        		giu_set(GIUINTTYPL, mask);
+			if (signal == IRQ_SIGNAL_HOLD)
+				giu_set(GIUINTHTSELL, mask);
+			else
+				giu_clear(GIUINTHTSELL, mask);
+			if (current_cpu_data.cputype == CPU_VR4133) {
+				switch (trigger) {
+				case IRQ_TRIGGER_EDGE_FALLING:
+					giu_set(GIUFEDGEINHL, mask);
+					giu_clear(GIUREDGEINHL, mask);
+					break;
+				case IRQ_TRIGGER_EDGE_RISING:
+					giu_clear(GIUFEDGEINHL, mask);
+					giu_set(GIUREDGEINHL, mask);
+					break;
+				default:
+					giu_set(GIUFEDGEINHL, mask);
+					giu_set(GIUREDGEINHL, mask);
+					break;
+				}
+			}
+		} else {
+			giu_clear(GIUINTTYPL, mask);
+			giu_clear(GIUINTHTSELL, mask);
+		}
+		giu_write(GIUINTSTATL, mask);
+	} else if (pin < GIUINT_HIGH_MAX) {
+		mask = 1 << (pin - GIUINT_HIGH_OFFSET);
+		if (trigger != IRQ_TRIGGER_LEVEL) {
+			giu_set(GIUINTTYPH, mask);
+			if (signal == IRQ_SIGNAL_HOLD)
+				giu_set(GIUINTHTSELH, mask);
+			else
+				giu_clear(GIUINTHTSELH, mask);
+			if (current_cpu_data.cputype == CPU_VR4133) {
+				switch (trigger) {
+				case IRQ_TRIGGER_EDGE_FALLING:
+					giu_set(GIUFEDGEINHH, mask);
+					giu_clear(GIUREDGEINHH, mask);
+					break;
+				case IRQ_TRIGGER_EDGE_RISING:
+					giu_clear(GIUFEDGEINHH, mask);
+					giu_set(GIUREDGEINHH, mask);
+					break;
+				default:
+					giu_set(GIUFEDGEINHH, mask);
+					giu_set(GIUREDGEINHH, mask);
+					break;
+				}
+			}
+		} else {
+			giu_clear(GIUINTTYPH, mask);
+			giu_clear(GIUINTHTSELH, mask);
+		}
+		giu_write(GIUINTSTATH, mask);
+	}
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
+
+void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
+{
+	uint16_t mask;
+
+	if (pin < GIUINT_HIGH_OFFSET) {
+		mask = 1 << pin;
+		if (level == IRQ_LEVEL_HIGH)
+			giu_set(GIUINTALSELL, mask);
+		else
+			giu_clear(GIUINTALSELL, mask);
+		giu_write(GIUINTSTATL, mask);
+	} else if (pin < GIUINT_HIGH_MAX) {
+		mask = 1 << (pin - GIUINT_HIGH_OFFSET);
+		if (level == IRQ_LEVEL_HIGH)
+			giu_set(GIUINTALSELH, mask);
+		else
+			giu_clear(GIUINTALSELH, mask);
+		giu_write(GIUINTSTATH, mask);
+	}
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
+
+gpio_data_t vr41xx_gpio_get_pin(unsigned int pin)
+{
+	uint16_t reg, mask;
+
+	if (pin >= giu_nr_pins)
+		return GPIO_DATA_INVAL;
+
+	if (pin < 16) {
+		reg = giu_read(GIUPIODL);
+		mask = (uint16_t)1 << pin;
+	} else if (pin < 32) {
+		reg = giu_read(GIUPIODH);
+		mask = (uint16_t)1 << (pin - 16);
+	} else if (pin < 48) {
+		reg = giu_read(GIUPODATL);
+		mask = (uint16_t)1 << (pin - 32);
+	} else {
+		reg = giu_read(GIUPODATH);
+		mask = (uint16_t)1 << (pin - 48);
+	}
+
+	if (reg & mask)
+		return GPIO_DATA_HIGH;
+
+	return GPIO_DATA_LOW;
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin);
+
+int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data)
+{
+	uint16_t offset, mask, reg;
+	unsigned long flags;
+
+	if (pin >= giu_nr_pins)
+		return -EINVAL;
+
+	if (pin < 16) {
+		offset = GIUPIODL;
+		mask = (uint16_t)1 << pin;
+	} else if (pin < 32) {
+		offset = GIUPIODH;
+		mask = (uint16_t)1 << (pin - 16);
+	} else if (pin < 48) {
+		offset = GIUPODATL;
+		mask = (uint16_t)1 << (pin - 32);
+	} else {
+		offset = GIUPODATH;
+		mask = (uint16_t)1 << (pin - 48);
+	}
+
+	spin_lock_irqsave(&giu_lock, flags);
+
+	reg = giu_read(offset);
+	if (data == GPIO_DATA_HIGH)
+		reg |= mask;
+	else
+		reg &= ~mask;
+	giu_write(offset, reg);
+
+	spin_unlock_irqrestore(&giu_lock, flags);
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin);
+
+int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir)
+{
+	uint16_t offset, mask, reg;
+	unsigned long flags;
+
+	if (pin >= giu_nr_pins)
+		return -EINVAL;
+
+	if (pin < 16) {
+		offset = GIUIOSELL;
+		mask = (uint16_t)1 << pin;
+	} else if (pin < 32) {
+		offset = GIUIOSELH;
+		mask = (uint16_t)1 << (pin - 16);
+	} else {
+		if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) {
+			offset = GIUPODATEN;
+			mask = (uint16_t)1 << (pin - 32);
+		} else {
+			switch (pin) {
+			case 48:
+				offset = GIUPODATH;
+				mask = PIOEN0;
+				break;
+			case 49:
+				offset = GIUPODATH;
+				mask = PIOEN1;
+				break;
+			default:
+				return -EINVAL;
+			}
+		}
+	}
+
+	spin_lock_irqsave(&giu_lock, flags);
+
+	reg = giu_read(offset);
+	if (dir == GPIO_OUTPUT)
+		reg |= mask;
+	else
+		reg &= ~mask;
+	giu_write(offset, reg);
+
+	spin_unlock_irqrestore(&giu_lock, flags);
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction);
+
+int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
+{
+	uint16_t reg, mask;
+	unsigned long flags;
+
+	if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO)
+		return -EPERM;
+
+	if (pin >= 15)
+		return -EINVAL;
+
+	mask = (uint16_t)1 << pin;
+
+	spin_lock_irqsave(&giu_lock, flags);
+
+	if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) {
+		reg = giu_read(GIUTERMUPDN);
+		if (pull == GPIO_PULL_UP)
+			reg |= mask;
+		else
+			reg &= ~mask;
+		giu_write(GIUTERMUPDN, reg);
+
+		reg = giu_read(GIUUSEUPDN);
+		reg |= mask;
+		giu_write(GIUUSEUPDN, reg);
+	} else {
+		reg = giu_read(GIUUSEUPDN);
+		reg &= ~mask;
+		giu_write(GIUUSEUPDN, reg);
+	}
+
+	spin_unlock_irqrestore(&giu_lock, flags);
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);
+
+static ssize_t gpio_read(struct file *file, char __user *buf, size_t len,
+                         loff_t *ppos)
+{
+	unsigned int pin;
+	char value = '0';
+
+	pin = iminor(file->f_dentry->d_inode);
+	if (pin >= giu_nr_pins)
+		return -EBADF;
+
+	if (vr41xx_gpio_get_pin(pin) == GPIO_DATA_HIGH)
+		value = '1';
+
+	if (len <= 0)
+		return -EFAULT;
+
+	if (put_user(value, buf))
+		return -EFAULT;
+
+	return 1;
+}
+
+static ssize_t gpio_write(struct file *file, const char __user *data,
+                          size_t len, loff_t *ppos)
+{
+	unsigned int pin;
+	size_t i;
+	char c;
+	int retval = 0;
+
+	pin = iminor(file->f_dentry->d_inode);
+	if (pin >= giu_nr_pins)
+		return -EBADF;
+
+	for (i = 0; i < len; i++) {
+		if (get_user(c, data + i))
+			return -EFAULT;
+
+		switch (c) {
+		case '0':
+			retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_LOW);
+			break;
+		case '1':
+			retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_HIGH);
+			break;
+		case 'D':
+			printk(KERN_INFO "GPIO%d: pull down\n", pin);
+			retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DOWN);
+			break;
+		case 'd':
+			printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin);
+			retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE);
+			break;
+		case 'I':
+			printk(KERN_INFO "GPIO%d: input\n", pin);
+			retval = vr41xx_gpio_set_direction(pin, GPIO_INPUT);
+			break;
+		case 'O':
+			printk(KERN_INFO "GPIO%d: output\n", pin);
+			retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT);
+			break;
+		case 'o':
+			printk(KERN_INFO "GPIO%d: output disable\n", pin);
+			retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT_DISABLE);
+			break;
+		case 'P':
+			printk(KERN_INFO "GPIO%d: pull up\n", pin);
+			retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_UP);
+			break;
+		case 'p':
+			printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin);
+			retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE);
+			break;
+		default:
+			break;
+		}
+
+		if (retval < 0)
+			break;
+	}
+
+	return i;
+}
+
+static int gpio_open(struct inode *inode, struct file *file)
+{
+	unsigned int pin;
+
+	pin = iminor(inode);
+	if (pin >= giu_nr_pins)
+		return -EBADF;
+
+	return nonseekable_open(inode, file);
+}
+
+static int gpio_release(struct inode *inode, struct file *file)
+{
+	unsigned int pin;
+
+	pin = iminor(inode);
+	if (pin >= giu_nr_pins)
+		return -EBADF;
+
+	return 0;
+}
+
+static struct file_operations gpio_fops = {
+	.owner		= THIS_MODULE,
+	.read		= gpio_read,
+	.write		= gpio_write,
+	.open		= gpio_open,
+	.release	= gpio_release,
+};
+
+static int giu_probe(struct device *dev)
+{
+	unsigned long start, size, flags = 0;
+	unsigned int nr_pins = 0;
+	struct resource *res1, *res2 = NULL;
+	void *base;
+	int retval, i;
+
+	switch (current_cpu_data.cputype) {
+	case CPU_VR4111:
+	case CPU_VR4121:
+		start = GIU_TYPE1_START;
+		size = GIU_TYPE1_SIZE;
+		flags = GPIO_HAS_PULLUPDOWN_IO;
+		nr_pins = 50;
+		break;
+	case CPU_VR4122:
+	case CPU_VR4131:
+		start = GIU_TYPE2_START;
+		size = GIU_TYPE2_SIZE;
+		nr_pins = 36;
+		break;
+	case CPU_VR4133:
+		start = GIU_TYPE3_START;
+		size = GIU_TYPE3_SIZE;
+		flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
+		nr_pins = 48;
+		break;
+	default:
+		return -ENODEV;
+	}
+
+	res1 = request_mem_region(start, size, "GIU");
+	if (res1 == NULL)
+		return -EBUSY;
+
+	base = ioremap(start, size);
+	if (base == NULL) {
+		release_resource(res1);
+		return -ENOMEM;
+	}
+
+	if (flags & GPIO_HAS_PULLUPDOWN_IO) {
+		res2 = request_mem_region(GIU_PULLUPDOWN_START, GIU_PULLUPDOWN_SIZE, "GIU");
+		if (res2 == NULL) {
+			iounmap(base);
+			release_resource(res1);
+			return -EBUSY;
+		}
+	}
+
+	retval = register_chrdev(major, "GIU", &gpio_fops);
+	if (retval < 0) {
+		iounmap(base);
+		release_resource(res1);
+		release_resource(res2);
+		return retval;
+	}
+
+	if (major == 0) {
+		major = retval;
+		printk(KERN_INFO "GIU: major number %d\n", major);
+	}
+
+	spin_lock_init(&giu_lock);
+	giu_base = base;
+	giu_resource1 = res1;
+	giu_resource2 = res2;
+	giu_flags = flags;
+	giu_nr_pins = nr_pins;
+
+	giu_write(GIUINTENL, 0);
+	giu_write(GIUINTENH, 0);
+
+	for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
+		if (i < GIU_IRQ(GIUINT_HIGH_OFFSET))
+			irq_desc[i].handler = &giuint_low_irq_type;
+		else
+			irq_desc[i].handler = &giuint_high_irq_type;
+	}
+
+	return cascade_irq(GIUINT_IRQ, giu_get_irq);
+}
+
+static int giu_remove(struct device *dev)
+{
+	iounmap(giu_base);
+
+	release_resource(giu_resource1);
+	if (giu_flags & GPIO_HAS_PULLUPDOWN_IO)
+		release_resource(giu_resource2);
+
+	return 0;
+}
+
+static struct platform_device *giu_platform_device;
+
+static struct device_driver giu_device_driver = {
+	.name		= "GIU",
+	.bus		= &platform_bus_type,
+	.probe		= giu_probe,
+	.remove		= giu_remove,
+};
+
+static int __devinit vr41xx_giu_init(void)
+{
+	int retval;
+
+	giu_platform_device = platform_device_register_simple("GIU", -1, NULL, 0);
+	if (IS_ERR(giu_platform_device))
+		return PTR_ERR(giu_platform_device);
+
+	retval = driver_register(&giu_device_driver);
+	if (retval < 0)
+		platform_device_unregister(giu_platform_device);
+
+	return retval;
+}
+
+static void __devexit vr41xx_giu_exit(void)
+{
+	driver_unregister(&giu_device_driver);
+
+	platform_device_unregister(giu_platform_device);
+}
+
+module_init(vr41xx_giu_init);
+module_exit(vr41xx_giu_exit);
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index e5ef1df..d7aa7a2 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -2867,6 +2867,10 @@
  */
 static void blank_screen_t(unsigned long dummy)
 {
+	if (unlikely(!keventd_up())) {
+		mod_timer(&console_timer, jiffies + blankinterval);
+		return;
+	}
 	blank_timer_expired = 1;
 	schedule_work(&console_work);
 }
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index 06a31da..b53e2e2 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -414,6 +414,16 @@
 	  machines.  The watchdog timeout period is normally one minute but
 	  can be changed with a boot-time parameter.
 
+# ppc64 RTAS watchdog
+config WATCHDOG_RTAS
+	tristate "RTAS watchdog"
+	depends on WATCHDOG && PPC_RTAS
+	help
+	  This driver adds watchdog support for the RTAS watchdog.
+
+          To compile this driver as a module, choose M here. The module
+	  will be called wdrtas.
+
 #
 # ISA-based Watchdog Cards
 #
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index 1cd27ef..c183883 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -33,6 +33,7 @@
 obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
 obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
 obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
+obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o
 
 # Only one watchdog can succeed. We probe the hardware watchdog
 # drivers first, then the softdog driver.  This means if your hardware
diff --git a/drivers/char/watchdog/ixp2000_wdt.c b/drivers/char/watchdog/ixp2000_wdt.c
index ab659d3..4e98c21 100644
--- a/drivers/char/watchdog/ixp2000_wdt.c
+++ b/drivers/char/watchdog/ixp2000_wdt.c
@@ -192,7 +192,12 @@
 
 static int __init ixp2000_wdt_init(void)
 {
-	wdt_tick_rate = (*IXP2000_T1_CLD * HZ)/ 256;;
+	if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) {
+		printk(KERN_INFO "Unable to use IXP2000 watchdog due to IXP2800 erratum #25.\n");
+		return -EIO;
+	}
+
+	wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256;
 
 	return misc_register(&ixp2000_wdt_miscdev);
 }
diff --git a/drivers/char/watchdog/wdrtas.c b/drivers/char/watchdog/wdrtas.c
new file mode 100644
index 0000000..619e2ff
--- /dev/null
+++ b/drivers/char/watchdog/wdrtas.c
@@ -0,0 +1,696 @@
+/*
+ * FIXME: add wdrtas_get_status and wdrtas_get_boot_status as soon as
+ * RTAS calls are available
+ */
+
+/*
+ * RTAS watchdog driver
+ *
+ * (C) Copyright IBM Corp. 2005
+ * device driver to exploit watchdog RTAS functions
+ *
+ * Authors : Utz Bacher <utz.bacher@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.
+ */
+
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+
+#include <asm/rtas.h>
+#include <asm/uaccess.h>
+
+#define WDRTAS_MAGIC_CHAR		42
+#define WDRTAS_SUPPORTED_MASK		(WDIOF_SETTIMEOUT | \
+					 WDIOF_MAGICCLOSE)
+
+MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
+MODULE_DESCRIPTION("RTAS watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+MODULE_ALIAS_MISCDEV(TEMP_MINOR);
+
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int wdrtas_nowayout = 1;
+#else
+static int wdrtas_nowayout = 0;
+#endif
+
+static atomic_t wdrtas_miscdev_open = ATOMIC_INIT(0);
+static char wdrtas_expect_close = 0;
+
+static int wdrtas_interval;
+
+#define WDRTAS_THERMAL_SENSOR		3
+static int wdrtas_token_get_sensor_state;
+#define WDRTAS_SURVEILLANCE_IND		9000
+static int wdrtas_token_set_indicator;
+#define WDRTAS_SP_SPI			28
+static int wdrtas_token_get_sp;
+static int wdrtas_token_event_scan;
+
+#define WDRTAS_DEFAULT_INTERVAL		300
+
+#define WDRTAS_LOGBUFFER_LEN		128
+static char wdrtas_logbuffer[WDRTAS_LOGBUFFER_LEN];
+
+
+/*** watchdog access functions */
+
+/**
+ * wdrtas_set_interval - sets the watchdog interval
+ * @interval: new interval
+ *
+ * returns 0 on success, <0 on failures
+ *
+ * wdrtas_set_interval sets the watchdog keepalive interval by calling the
+ * RTAS function set-indicator (surveillance). The unit of interval is
+ * seconds.
+ */
+static int
+wdrtas_set_interval(int interval)
+{
+	long result;
+	static int print_msg = 10;
+
+	/* rtas uses minutes */
+	interval = (interval + 59) / 60;
+
+	result = rtas_call(wdrtas_token_set_indicator, 3, 1, NULL,
+			   WDRTAS_SURVEILLANCE_IND, 0, interval);
+	if ( (result < 0) && (print_msg) ) {
+		printk(KERN_ERR "wdrtas: setting the watchdog to %i "
+		       "timeout failed: %li\n", interval, result);
+		print_msg--;
+	}
+
+	return result;
+}
+
+/**
+ * wdrtas_get_interval - returns the current watchdog interval
+ * @fallback_value: value (in seconds) to use, if the RTAS call fails
+ *
+ * returns the interval
+ *
+ * wdrtas_get_interval returns the current watchdog keepalive interval
+ * as reported by the RTAS function ibm,get-system-parameter. The unit
+ * of the return value is seconds.
+ */
+static int
+wdrtas_get_interval(int fallback_value)
+{
+	long result;
+	char value[4];
+
+	result = rtas_call(wdrtas_token_get_sp, 3, 1, NULL,
+			   WDRTAS_SP_SPI, (void *)__pa(&value), 4);
+	if ( (value[0] != 0) || (value[1] != 2) || (value[3] != 0) ||
+	     (result < 0) ) {
+		printk(KERN_WARNING "wdrtas: could not get sp_spi watchdog "
+		       "timeout (%li). Continuing\n", result);
+		return fallback_value;
+	}
+
+	/* rtas uses minutes */
+	return ((int)value[2]) * 60;
+}
+
+/**
+ * wdrtas_timer_start - starts watchdog
+ *
+ * wdrtas_timer_start starts the watchdog by calling the RTAS function
+ * set-interval (surveillance)
+ */
+static void
+wdrtas_timer_start(void)
+{
+	wdrtas_set_interval(wdrtas_interval);
+}
+
+/**
+ * wdrtas_timer_stop - stops watchdog
+ *
+ * wdrtas_timer_stop stops the watchdog timer by calling the RTAS function
+ * set-interval (surveillance)
+ */
+static void
+wdrtas_timer_stop(void)
+{
+	wdrtas_set_interval(0);
+}
+
+/**
+ * wdrtas_log_scanned_event - logs an event we received during keepalive
+ *
+ * wdrtas_log_scanned_event prints a message to the log buffer dumping
+ * the results of the last event-scan call
+ */
+static void
+wdrtas_log_scanned_event(void)
+{
+	int i;
+
+	for (i = 0; i < WDRTAS_LOGBUFFER_LEN; i += 16)
+		printk(KERN_INFO "wdrtas: dumping event (line %i/%i), data = "
+		       "%02x %02x %02x %02x  %02x %02x %02x %02x   "
+		       "%02x %02x %02x %02x  %02x %02x %02x %02x\n",
+		       (i / 16) + 1, (WDRTAS_LOGBUFFER_LEN / 16),
+		       wdrtas_logbuffer[i + 0], wdrtas_logbuffer[i + 1], 
+		       wdrtas_logbuffer[i + 2], wdrtas_logbuffer[i + 3], 
+		       wdrtas_logbuffer[i + 4], wdrtas_logbuffer[i + 5], 
+		       wdrtas_logbuffer[i + 6], wdrtas_logbuffer[i + 7], 
+		       wdrtas_logbuffer[i + 8], wdrtas_logbuffer[i + 9], 
+		       wdrtas_logbuffer[i + 10], wdrtas_logbuffer[i + 11], 
+		       wdrtas_logbuffer[i + 12], wdrtas_logbuffer[i + 13], 
+		       wdrtas_logbuffer[i + 14], wdrtas_logbuffer[i + 15]);
+}
+
+/**
+ * wdrtas_timer_keepalive - resets watchdog timer to keep system alive
+ *
+ * wdrtas_timer_keepalive restarts the watchdog timer by calling the
+ * RTAS function event-scan and repeats these calls as long as there are
+ * events available. All events will be dumped.
+ */
+static void
+wdrtas_timer_keepalive(void)
+{
+	long result;
+
+	do {
+		result = rtas_call(wdrtas_token_event_scan, 4, 1, NULL,
+				   RTAS_EVENT_SCAN_ALL_EVENTS, 0,
+				   (void *)__pa(wdrtas_logbuffer),
+				   WDRTAS_LOGBUFFER_LEN);
+		if (result < 0)
+			printk(KERN_ERR "wdrtas: event-scan failed: %li\n",
+			       result);
+		if (result == 0)
+			wdrtas_log_scanned_event();
+	} while (result == 0);
+}
+
+/**
+ * wdrtas_get_temperature - returns current temperature
+ *
+ * returns temperature or <0 on failures
+ *
+ * wdrtas_get_temperature returns the current temperature in Fahrenheit. It
+ * uses the RTAS call get-sensor-state, token 3 to do so
+ */
+static int
+wdrtas_get_temperature(void)
+{
+	long result;
+	int temperature = 0;
+
+	result = rtas_call(wdrtas_token_get_sensor_state, 2, 2,
+			   (void *)__pa(&temperature),
+			   WDRTAS_THERMAL_SENSOR, 0);
+
+	if (result < 0)
+		printk(KERN_WARNING "wdrtas: reading the thermal sensor "
+		       "faild: %li\n", result);
+	else
+		temperature = ((temperature * 9) / 5) + 32; /* fahrenheit */
+
+	return temperature;
+}
+
+/**
+ * wdrtas_get_status - returns the status of the watchdog
+ *
+ * returns a bitmask of defines WDIOF_... as defined in
+ * include/linux/watchdog.h
+ */
+static int
+wdrtas_get_status(void)
+{
+	return 0; /* TODO */
+}
+
+/**
+ * wdrtas_get_boot_status - returns the reason for the last boot
+ *
+ * returns a bitmask of defines WDIOF_... as defined in
+ * include/linux/watchdog.h, indicating why the watchdog rebooted the system
+ */
+static int
+wdrtas_get_boot_status(void)
+{
+	return 0; /* TODO */
+}
+
+/*** watchdog API and operations stuff */
+
+/* wdrtas_write - called when watchdog device is written to
+ * @file: file structure
+ * @buf: user buffer with data
+ * @len: amount to data written
+ * @ppos: position in file
+ *
+ * returns the number of successfully processed characters, which is always
+ * the number of bytes passed to this function
+ *
+ * wdrtas_write processes all the data given to it and looks for the magic
+ * character 'V'. This character allows the watchdog device to be closed
+ * properly.
+ */
+static ssize_t
+wdrtas_write(struct file *file, const char __user *buf,
+	     size_t len, loff_t *ppos)
+{
+	int i;
+	char c;
+
+	if (!len)
+		goto out;
+
+	if (!wdrtas_nowayout) {
+		wdrtas_expect_close = 0;
+		/* look for 'V' */
+		for (i = 0; i < len; i++) {
+			if (get_user(c, buf + i))
+				return -EFAULT;
+			/* allow to close device */
+			if (c == 'V')
+				wdrtas_expect_close = WDRTAS_MAGIC_CHAR;
+		}
+	}
+
+	wdrtas_timer_keepalive();
+
+out:
+	return len;
+}
+
+/**
+ * wdrtas_ioctl - ioctl function for the watchdog device
+ * @inode: inode structure
+ * @file: file structure
+ * @cmd: command for ioctl
+ * @arg: argument pointer
+ *
+ * returns 0 on success, <0 on failure
+ *
+ * wdrtas_ioctl implements the watchdog API ioctls
+ */
+static int
+wdrtas_ioctl(struct inode *inode, struct file *file,
+	     unsigned int cmd, unsigned long arg)
+{
+	int __user *argp = (void *)arg;
+	int i;
+	static struct watchdog_info wdinfo = {
+		.options = WDRTAS_SUPPORTED_MASK,
+		.firmware_version = 0,
+		.identity = "wdrtas"
+	};
+
+	switch (cmd) {
+	case WDIOC_GETSUPPORT:
+		if (copy_to_user(argp, &wdinfo, sizeof(wdinfo)))
+			return -EFAULT;
+		return 0;
+
+	case WDIOC_GETSTATUS:
+		i = wdrtas_get_status();
+		return put_user(i, argp);
+
+	case WDIOC_GETBOOTSTATUS:
+		i = wdrtas_get_boot_status();
+		return put_user(i, argp);
+
+	case WDIOC_GETTEMP:
+		if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE)
+			return -EOPNOTSUPP;
+
+		i = wdrtas_get_temperature();
+		return put_user(i, argp);
+
+	case WDIOC_SETOPTIONS:
+		if (get_user(i, argp))
+			return -EFAULT;
+		if (i & WDIOS_DISABLECARD)
+			wdrtas_timer_stop();
+		if (i & WDIOS_ENABLECARD) {
+			wdrtas_timer_keepalive();
+			wdrtas_timer_start();
+		}
+		if (i & WDIOS_TEMPPANIC) {
+			/* not implemented. Done by H8 */
+		}
+		return 0;
+
+	case WDIOC_KEEPALIVE:
+		wdrtas_timer_keepalive();
+		return 0;
+
+	case WDIOC_SETTIMEOUT:
+		if (get_user(i, argp))
+			return -EFAULT;
+
+		if (wdrtas_set_interval(i))
+			return -EINVAL;
+
+		wdrtas_timer_keepalive();
+
+		if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE)
+			wdrtas_interval = i;
+		else
+			wdrtas_interval = wdrtas_get_interval(i);
+		/* fallthrough */
+
+	case WDIOC_GETTIMEOUT:
+		return put_user(wdrtas_interval, argp);
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+
+/**
+ * wdrtas_open - open function of watchdog device
+ * @inode: inode structure
+ * @file: file structure
+ *
+ * returns 0 on success, -EBUSY if the file has been opened already, <0 on
+ * other failures
+ *
+ * function called when watchdog device is opened
+ */
+static int
+wdrtas_open(struct inode *inode, struct file *file)
+{
+	/* only open once */
+	if (atomic_inc_return(&wdrtas_miscdev_open) > 1) {
+		atomic_dec(&wdrtas_miscdev_open);
+		return -EBUSY;
+	}
+
+	wdrtas_timer_start();
+	wdrtas_timer_keepalive();
+
+	return nonseekable_open(inode, file);
+}
+
+/**
+ * wdrtas_close - close function of watchdog device
+ * @inode: inode structure
+ * @file: file structure
+ *
+ * returns 0 on success
+ *
+ * close function. Always succeeds
+ */
+static int
+wdrtas_close(struct inode *inode, struct file *file)
+{
+	/* only stop watchdog, if this was announced using 'V' before */
+	if (wdrtas_expect_close == WDRTAS_MAGIC_CHAR)
+		wdrtas_timer_stop();
+	else {
+		printk(KERN_WARNING "wdrtas: got unexpected close. Watchdog "
+		       "not stopped.\n");
+		wdrtas_timer_keepalive();
+	}
+
+	wdrtas_expect_close = 0;
+	atomic_dec(&wdrtas_miscdev_open);
+	return 0;
+}
+
+/**
+ * wdrtas_temp_read - gives back the temperature in fahrenheit
+ * @file: file structure
+ * @buf: user buffer
+ * @count: number of bytes to be read
+ * @ppos: position in file
+ *
+ * returns always 1 or -EFAULT in case of user space copy failures, <0 on
+ * other failures
+ *
+ * wdrtas_temp_read gives the temperature to the users by copying this
+ * value as one byte into the user space buffer. The unit is Fahrenheit...
+ */
+static ssize_t
+wdrtas_temp_read(struct file *file, char __user *buf,
+		 size_t count, loff_t *ppos)
+{
+	int temperature = 0;
+
+	temperature = wdrtas_get_temperature();
+	if (temperature < 0)
+		return temperature;
+
+	if (copy_to_user(buf, &temperature, 1))
+		return -EFAULT;
+
+	return 1;
+}
+
+/**
+ * wdrtas_temp_open - open function of temperature device
+ * @inode: inode structure
+ * @file: file structure
+ *
+ * returns 0 on success, <0 on failure
+ *
+ * function called when temperature device is opened
+ */
+static int
+wdrtas_temp_open(struct inode *inode, struct file *file)
+{
+	return nonseekable_open(inode, file);
+}
+
+/**
+ * wdrtas_temp_close - close function of temperature device
+ * @inode: inode structure
+ * @file: file structure
+ *
+ * returns 0 on success
+ *
+ * close function. Always succeeds
+ */
+static int
+wdrtas_temp_close(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+/**
+ * wdrtas_reboot - reboot notifier function
+ * @nb: notifier block structure
+ * @code: reboot code
+ * @ptr: unused
+ *
+ * returns NOTIFY_DONE
+ *
+ * wdrtas_reboot stops the watchdog in case of a reboot
+ */
+static int
+wdrtas_reboot(struct notifier_block *this, unsigned long code, void *ptr)
+{
+	if ( (code==SYS_DOWN) || (code==SYS_HALT) )
+		wdrtas_timer_stop();
+
+	return NOTIFY_DONE;
+}
+
+/*** initialization stuff */
+
+static struct file_operations wdrtas_fops = {
+	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
+	.write		= wdrtas_write,
+	.ioctl		= wdrtas_ioctl,
+	.open		= wdrtas_open,
+	.release	= wdrtas_close,
+};
+
+static struct miscdevice wdrtas_miscdev = {
+	.minor =	WATCHDOG_MINOR,
+	.name =		"watchdog",
+	.fops =		&wdrtas_fops,
+};
+
+static struct file_operations wdrtas_temp_fops = {
+	.owner		= THIS_MODULE,
+	.llseek		= no_llseek,
+	.read		= wdrtas_temp_read,
+	.open		= wdrtas_temp_open,
+	.release	= wdrtas_temp_close,
+};
+
+static struct miscdevice wdrtas_tempdev = {
+	.minor =	TEMP_MINOR,
+	.name =		"temperature",
+	.fops =		&wdrtas_temp_fops,
+};
+
+static struct notifier_block wdrtas_notifier = {
+	.notifier_call =	wdrtas_reboot,
+};
+
+/**
+ * wdrtas_get_tokens - reads in RTAS tokens
+ *
+ * returns 0 on succes, <0 on failure
+ *
+ * wdrtas_get_tokens reads in the tokens for the RTAS calls used in
+ * this watchdog driver. It tolerates, if "get-sensor-state" and
+ * "ibm,get-system-parameter" are not available.
+ */
+static int
+wdrtas_get_tokens(void)
+{
+	wdrtas_token_get_sensor_state = rtas_token("get-sensor-state");
+	if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE) {
+		printk(KERN_WARNING "wdrtas: couldn't get token for "
+		       "get-sensor-state. Trying to continue without "
+		       "temperature support.\n");
+	}
+
+	wdrtas_token_get_sp = rtas_token("ibm,get-system-parameter");
+	if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE) {
+		printk(KERN_WARNING "wdrtas: couldn't get token for "
+		       "ibm,get-system-parameter. Trying to continue with "
+		       "a default timeout value of %i seconds.\n",
+		       WDRTAS_DEFAULT_INTERVAL);
+	}
+
+	wdrtas_token_set_indicator = rtas_token("set-indicator");
+	if (wdrtas_token_set_indicator == RTAS_UNKNOWN_SERVICE) {
+		printk(KERN_ERR "wdrtas: couldn't get token for "
+		       "set-indicator. Terminating watchdog code.\n");
+		return -EIO;
+	}
+
+	wdrtas_token_event_scan = rtas_token("event-scan");
+	if (wdrtas_token_event_scan == RTAS_UNKNOWN_SERVICE) {
+		printk(KERN_ERR "wdrtas: couldn't get token for event-scan. "
+		       "Terminating watchdog code.\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/**
+ * wdrtas_unregister_devs - unregisters the misc dev handlers
+ *
+ * wdrtas_register_devs unregisters the watchdog and temperature watchdog
+ * misc devs
+ */
+static void
+wdrtas_unregister_devs(void)
+{
+	misc_deregister(&wdrtas_miscdev);
+	if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE)
+		misc_deregister(&wdrtas_tempdev);
+}
+
+/**
+ * wdrtas_register_devs - registers the misc dev handlers
+ *
+ * returns 0 on succes, <0 on failure
+ *
+ * wdrtas_register_devs registers the watchdog and temperature watchdog
+ * misc devs
+ */
+static int
+wdrtas_register_devs(void)
+{
+	int result;
+
+	result = misc_register(&wdrtas_miscdev);
+	if (result) {
+		printk(KERN_ERR "wdrtas: couldn't register watchdog misc "
+		       "device. Terminating watchdog code.\n");
+		return result;
+	}
+
+	if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE) {
+		result = misc_register(&wdrtas_tempdev);
+		if (result) {
+			printk(KERN_WARNING "wdrtas: couldn't register "
+			       "watchdog temperature misc device. Continuing "
+			       "without temperature support.\n");
+			wdrtas_token_get_sensor_state = RTAS_UNKNOWN_SERVICE;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * wdrtas_init - init function of the watchdog driver
+ *
+ * returns 0 on succes, <0 on failure
+ *
+ * registers the file handlers and the reboot notifier
+ */
+static int __init
+wdrtas_init(void)
+{
+	if (wdrtas_get_tokens())
+		return -ENODEV;
+
+	if (wdrtas_register_devs())
+		return -ENODEV;
+
+	if (register_reboot_notifier(&wdrtas_notifier)) {
+		printk(KERN_ERR "wdrtas: could not register reboot notifier. "
+		       "Terminating watchdog code.\n");
+		wdrtas_unregister_devs();
+		return -ENODEV;
+	}
+
+	if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE)
+		wdrtas_interval = WDRTAS_DEFAULT_INTERVAL;
+	else
+		wdrtas_interval = wdrtas_get_interval(WDRTAS_DEFAULT_INTERVAL);
+
+	return 0;
+}
+
+/**
+ * wdrtas_exit - exit function of the watchdog driver
+ *
+ * unregisters the file handlers and the reboot notifier
+ */
+static void __exit
+wdrtas_exit(void)
+{
+	if (!wdrtas_nowayout)
+		wdrtas_timer_stop();
+
+	wdrtas_unregister_devs();
+
+	unregister_reboot_notifier(&wdrtas_notifier);
+}
+
+module_init(wdrtas_init);
+module_exit(wdrtas_exit);
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 03b5fb2..bf62dfe 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -521,7 +521,7 @@
 	policy = cpufreq_cpu_get(policy->cpu);
 	if (!policy)
 		return -EINVAL;
-	ret = fattr->show ? fattr->show(policy,buf) : 0;
+	ret = fattr->show ? fattr->show(policy,buf) : -EIO;
 	cpufreq_cpu_put(policy);
 	return ret;
 }
@@ -535,7 +535,7 @@
 	policy = cpufreq_cpu_get(policy->cpu);
 	if (!policy)
 		return -EINVAL;
-	ret = fattr->store ? fattr->store(policy,buf,count) : 0;
+	ret = fattr->store ? fattr->store(policy,buf,count) : -EIO;
 	cpufreq_cpu_put(policy);
 	return ret;
 }
diff --git a/drivers/dio/dio-sysfs.c b/drivers/dio/dio-sysfs.c
index d30591f..f464630 100644
--- a/drivers/dio/dio-sysfs.c
+++ b/drivers/dio/dio-sysfs.c
@@ -17,7 +17,7 @@
 
 /* show configuration fields */
 
-static ssize_t dio_show_id(struct device *dev, char *buf)
+static ssize_t dio_show_id(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct dio_dev *d;
 
@@ -26,7 +26,7 @@
 }
 static DEVICE_ATTR(id, S_IRUGO, dio_show_id, NULL);
 
-static ssize_t dio_show_ipl(struct device *dev, char *buf)
+static ssize_t dio_show_ipl(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct dio_dev *d;
 
@@ -35,7 +35,7 @@
 }
 static DEVICE_ATTR(ipl, S_IRUGO, dio_show_ipl, NULL);
 
-static ssize_t dio_show_secid(struct device *dev, char *buf)
+static ssize_t dio_show_secid(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct dio_dev *d;
 
@@ -44,7 +44,7 @@
 }
 static DEVICE_ATTR(secid, S_IRUGO, dio_show_secid, NULL);
 
-static ssize_t dio_show_name(struct device *dev, char *buf)
+static ssize_t dio_show_name(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct dio_dev *d;
 
@@ -53,7 +53,7 @@
 }
 static DEVICE_ATTR(name, S_IRUGO, dio_show_name, NULL);
 
-static ssize_t dio_show_resource(struct device *dev, char *buf)
+static ssize_t dio_show_resource(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct dio_dev *d = to_dio_dev(dev);
 
diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c
index 6381ba5..1937743 100644
--- a/drivers/eisa/eisa-bus.c
+++ b/drivers/eisa/eisa-bus.c
@@ -149,7 +149,7 @@
 	driver_unregister (&edrv->driver);
 }
 
-static ssize_t eisa_show_sig (struct device *dev, char *buf)
+static ssize_t eisa_show_sig (struct device *dev, struct device_attribute *attr, char *buf)
 {
         struct eisa_device *edev = to_eisa_device (dev);
         return sprintf (buf,"%s\n", edev->id.sig);
@@ -157,7 +157,7 @@
 
 static DEVICE_ATTR(signature, S_IRUGO, eisa_show_sig, NULL);
 
-static ssize_t eisa_show_state (struct device *dev, char *buf)
+static ssize_t eisa_show_state (struct device *dev, struct device_attribute *attr, char *buf)
 {
         struct eisa_device *edev = to_eisa_device (dev);
         return sprintf (buf,"%d\n", edev->state & EISA_CONFIG_ENABLED);
diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c
index 1fbb219..e3c9588 100644
--- a/drivers/fc4/fc.c
+++ b/drivers/fc4/fc.c
@@ -765,12 +765,8 @@
 
 static void fcp_scsi_done (Scsi_Cmnd *SCpnt)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
 	if (FCP_CMND(SCpnt)->done)
 		FCP_CMND(SCpnt)->done(SCpnt);
-	spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
 }
 
 static int fcp_scsi_queue_it(fc_channel *fc, Scsi_Cmnd *SCpnt, fcp_cmnd *fcmd, int prepare)
@@ -909,12 +905,8 @@
 	 */
 
 	if (++fc->abort_count < (fc->can_queue >> 1)) {
-		unsigned long flags;
-
 		SCpnt->result = DID_ABORT;
-		spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
 		fcmd->done(SCpnt);
-		spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
 		printk("FC: soft abort\n");
 		return SUCCESS;
 	} else {
@@ -935,6 +927,7 @@
 
 int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt)
 {
+	unsigned long flags;
 	fcp_cmd *cmd;
 	fcp_cmnd *fcmd;
 	fc_channel *fc = FC_SCMND(SCpnt);
@@ -987,7 +980,10 @@
 	fc->rst_pkt->request->rq_status = RQ_SCSI_BUSY;
 
 	fc->rst_pkt->done = fcp_scsi_reset_done;
+
+	spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
 	fcp_scsi_queue_it(fc, fc->rst_pkt, fcmd, 0);
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
 	
 	down(&sem);
 
@@ -1006,13 +1002,7 @@
 	return SUCCESS;
 }
 
-int fcp_scsi_bus_reset(Scsi_Cmnd *SCpnt)
-{
-	printk ("FC: bus reset!\n");
-	return FAILED;
-}
-
-int fcp_scsi_host_reset(Scsi_Cmnd *SCpnt)
+static int __fcp_scsi_host_reset(Scsi_Cmnd *SCpnt)
 {
 	fc_channel *fc = FC_SCMND(SCpnt);
 	fcp_cmnd *fcmd = FCP_CMND(SCpnt);
@@ -1033,6 +1023,18 @@
 	else return FAILED;
 }
 
+int fcp_scsi_host_reset(Scsi_Cmnd *SCpnt)
+{
+	unsigned long flags;
+	int rc;
+
+	spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
+	rc = __fcp_scsi_host_reset(SCpnt);
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
+
+	return rc;
+}
+
 static int fcp_els_queue_it(fc_channel *fc, fcp_cmnd *fcmd)
 {
 	long i;
diff --git a/drivers/fc4/fc_syms.c b/drivers/fc4/fc_syms.c
index 8bac2c4..ed85dfc 100644
--- a/drivers/fc4/fc_syms.c
+++ b/drivers/fc4/fc_syms.c
@@ -27,7 +27,6 @@
 EXPORT_SYMBOL(fcp_scsi_queuecommand);
 EXPORT_SYMBOL(fcp_scsi_abort);
 EXPORT_SYMBOL(fcp_scsi_dev_reset);
-EXPORT_SYMBOL(fcp_scsi_bus_reset);
 EXPORT_SYMBOL(fcp_scsi_host_reset);
 
 #endif /* CONFIG_MODULES */
diff --git a/drivers/fc4/fcp_impl.h b/drivers/fc4/fcp_impl.h
index e44d652..c397c84 100644
--- a/drivers/fc4/fcp_impl.h
+++ b/drivers/fc4/fcp_impl.h
@@ -158,7 +158,6 @@
 int fcp_scsi_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
 int fcp_scsi_abort(Scsi_Cmnd *);
 int fcp_scsi_dev_reset(Scsi_Cmnd *);
-int fcp_scsi_bus_reset(Scsi_Cmnd *);
 int fcp_scsi_host_reset(Scsi_Cmnd *);
 
 #endif /* !(_FCP_SCSI_H) */
diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c
index 33b669e..6996476 100644
--- a/drivers/firmware/edd.c
+++ b/drivers/firmware/edd.c
@@ -115,7 +115,7 @@
 {
 	struct edd_device *dev = to_edd_device(kobj);
 	struct edd_attribute *edd_attr = to_edd_attr(attr);
-	ssize_t ret = 0;
+	ssize_t ret = -EIO;
 
 	if (edd_attr->show)
 		ret = edd_attr->show(dev, buf);
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 0287ff6..33b17c6 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -352,7 +352,7 @@
 {
 	struct efivar_entry *var = to_efivar_entry(kobj);
 	struct efivar_attribute *efivar_attr = to_efivar_attr(attr);
-	ssize_t ret = 0;
+	ssize_t ret = -EIO;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
@@ -368,7 +368,7 @@
 {
 	struct efivar_entry *var = to_efivar_entry(kobj);
 	struct efivar_attribute *efivar_attr = to_efivar_attr(attr);
-	ssize_t ret = 0;
+	ssize_t ret = -EIO;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
@@ -618,8 +618,8 @@
 	new_efivar = kmalloc(sizeof(struct efivar_entry), GFP_KERNEL);
 
 	if (!short_name || !new_efivar)  {
-		if (short_name)        kfree(short_name);
-		if (new_efivar)        kfree(new_efivar);
+		kfree(short_name);
+		kfree(new_efivar);
 		return 1;
 	}
 	memset(short_name, 0, short_name_size+1);
@@ -644,7 +644,8 @@
 	kobj_set_kset_s(new_efivar, vars_subsys);
 	kobject_register(&new_efivar->kobj);
 
-	kfree(short_name); short_name = NULL;
+	kfree(short_name);
+	short_name = NULL;
 
 	spin_lock(&efivars_lock);
 	list_add(&new_efivar->list, &efivar_list);
diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c
index df1b721..839b44a 100644
--- a/drivers/firmware/pcdp.c
+++ b/drivers/firmware/pcdp.c
@@ -23,12 +23,15 @@
 {
 #ifdef CONFIG_SERIAL_8250_CONSOLE
 	int mmio;
-	static char options[64];
+	static char options[64], *p = options;
 
 	mmio = (uart->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY);
-	snprintf(options, sizeof(options), "console=uart,%s,0x%lx,%lun%d",
-		mmio ? "mmio" : "io", uart->addr.address, uart->baud,
-		uart->bits ? uart->bits : 8);
+	p += sprintf(p, "console=uart,%s,0x%lx",
+		mmio ? "mmio" : "io", uart->addr.address);
+	if (uart->baud)
+		p += sprintf(p, ",%lu", uart->baud);
+	if (uart->bits)
+		p += sprintf(p, "n%d", uart->bits);
 
 	return early_serial_console_init(options);
 #else
diff --git a/drivers/firmware/pcdp.h b/drivers/firmware/pcdp.h
index 863bb6f..1dc7c88 100644
--- a/drivers/firmware/pcdp.h
+++ b/drivers/firmware/pcdp.h
@@ -2,7 +2,7 @@
  * Definitions for PCDP-defined console devices
  *
  * v1.0a: http://www.dig64.org/specifications/DIG64_HCDPv10a_01.pdf
- * v2.0:  http://www.dig64.org/specifications/DIG64_HCDPv20_042804.pdf
+ * v2.0:  http://www.dig64.org/specifications/DIG64_PCDPv20.pdf
  *
  * (c) Copyright 2002, 2004 Hewlett-Packard Development Company, L.P.
  *	Khalid Aziz <khalid.aziz@hp.com>
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
index c3d912c..cc3a952 100644
--- a/drivers/i2c/algos/i2c-algo-pca.c
+++ b/drivers/i2c/algos/i2c-algo-pca.c
@@ -49,7 +49,7 @@
 /*
  * Generate a start condition on the i2c bus.
  *
- * returns after the start condition has occured
+ * returns after the start condition has occurred
  */
 static void pca_start(struct i2c_algo_pca_data *adap)
 {
@@ -62,9 +62,9 @@
 }
 
 /*
- * Generate a repeated start condition on the i2c bus 
+ * Generate a repeated start condition on the i2c bus
  *
- * return after the repeated start condition has occured
+ * return after the repeated start condition has occurred
  */
 static void pca_repeated_start(struct i2c_algo_pca_data *adap)
 {
@@ -82,7 +82,7 @@
  * returns after the stop condition has been generated
  *
  * STOPs do not generate an interrupt or set the SI flag, since the
- * part returns the the idle state (0xf8). Hence we don't need to
+ * part returns the idle state (0xf8). Hence we don't need to
  * pca_wait here.
  */
 static void pca_stop(struct i2c_algo_pca_data *adap)
diff --git a/drivers/i2c/algos/i2c-algo-sibyte.c b/drivers/i2c/algos/i2c-algo-sibyte.c
index 35789bb..f278549 100644
--- a/drivers/i2c/algos/i2c-algo-sibyte.c
+++ b/drivers/i2c/algos/i2c-algo-sibyte.c
@@ -24,7 +24,6 @@
 
 /* Ported for SiByte SOCs by Broadcom Corporation.  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index a0018de..916ba5e 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -7,7 +7,7 @@
 
 config I2C_ALI1535
 	tristate "ALI 1535"
-	depends on I2C && PCI && EXPERIMENTAL
+	depends on I2C && PCI
 	help
 	  If you say yes to this option, support will be included for the SMB
 	  Host controller on Acer Labs Inc. (ALI) M1535 South Bridges.  The SMB
@@ -31,7 +31,7 @@
 
 config I2C_ALI15X3
 	tristate "ALI 15x3"
-	depends on I2C && PCI && EXPERIMENTAL
+	depends on I2C && PCI
 	help
 	  If you say yes to this option, support will be included for the
 	  Acer Labs Inc. (ALI) M1514 and M1543 motherboard I2C interfaces.
@@ -41,7 +41,7 @@
 
 config I2C_AMD756
 	tristate "AMD 756/766/768/8111 and nVidia nForce"
-	depends on I2C && PCI && EXPERIMENTAL
+	depends on I2C && PCI
 	help
 	  If you say yes to this option, support will be included for the AMD
 	  756/766/768 mainboard I2C interfaces.  The driver also includes
@@ -66,7 +66,7 @@
 
 config I2C_AMD8111
 	tristate "AMD 8111"
-	depends on I2C && PCI && EXPERIMENTAL
+	depends on I2C && PCI
 	help
 	  If you say yes to this option, support will be included for the
 	  second (SMBus 2.0) AMD 8111 mainboard I2C interface.
@@ -109,7 +109,7 @@
 
 config I2C_I801
 	tristate "Intel 82801 (ICH)"
-	depends on I2C && PCI && EXPERIMENTAL
+	depends on I2C && PCI
 	help
 	  If you say yes to this option, support will be included for the Intel
 	  801 family of mainboard I2C interfaces.  Specifically, the following
@@ -130,7 +130,7 @@
 
 config I2C_I810
 	tristate "Intel 810/815"
-	depends on I2C && PCI && EXPERIMENTAL
+	depends on I2C && PCI
 	select I2C_ALGOBIT
 	help
 	  If you say yes to this option, support will be included for the Intel
@@ -183,7 +183,7 @@
 
 config I2C_ISA
 	tristate "ISA Bus support"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	help
 	  If you say yes to this option, support will be included for i2c
 	  interfaces that are on the ISA bus.
@@ -248,12 +248,11 @@
 	  will be called i2c-mpc.
 
 config I2C_NFORCE2
-	tristate "Nvidia Nforce2"
-	depends on I2C && PCI && EXPERIMENTAL
+	tristate "Nvidia nForce2, nForce3 and nForce4"
+	depends on I2C && PCI
 	help
 	  If you say yes to this option, support will be included for the Nvidia
-	  Nforce2 family of mainboard I2C interfaces.
-	  This driver also supports the nForce3 Pro 150 MCP.
+	  nForce2, nForce3 and nForce4 families of mainboard I2C interfaces.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-nforce2.
@@ -305,7 +304,7 @@
 
 config I2C_PROSAVAGE
 	tristate "S3/VIA (Pro)Savage"
-	depends on I2C && PCI && EXPERIMENTAL
+	depends on I2C && PCI
 	select I2C_ALGOBIT
 	help
 	  If you say yes to this option, support will be included for the
@@ -388,7 +387,7 @@
 
 config I2C_SIS5595
 	tristate "SiS 5595"
-	depends on I2C && PCI && EXPERIMENTAL
+	depends on I2C && PCI
 	help
 	  If you say yes to this option, support will be included for the 
 	  SiS5595 SMBus (a subset of I2C) interface.
@@ -398,7 +397,7 @@
 
 config I2C_SIS630
 	tristate "SiS 630/730"
-	depends on I2C && PCI && EXPERIMENTAL
+	depends on I2C && PCI
 	help
 	  If you say yes to this option, support will be included for the 
 	  SiS630 and SiS730 SMBus (a subset of I2C) interface.
@@ -408,7 +407,7 @@
 
 config I2C_SIS96X
 	tristate "SiS 96x"
-	depends on I2C && PCI && EXPERIMENTAL
+	depends on I2C && PCI
 	help
 	  If you say yes to this option, support will be included for the SiS
 	  96x SMBus (a subset of I2C) interfaces.  Specifically, the following
@@ -419,6 +418,7 @@
 	    648/961
 	    650/961
 	    735
+	    745
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-sis96x.
@@ -449,7 +449,7 @@
 
 config I2C_VIAPRO
 	tristate "VIA 82C596/82C686/823x"
-	depends on I2C && PCI && EXPERIMENTAL
+	depends on I2C && PCI
 	help
 	  If you say yes to this option, support will be included for the VIA
 	  82C596/82C686/823x I2C interfaces.  Specifically, the following 
@@ -467,7 +467,7 @@
 
 config I2C_VOODOO3
 	tristate "Voodoo 3"
-	depends on I2C && PCI && EXPERIMENTAL
+	depends on I2C && PCI
 	select I2C_ALGOBIT
 	help
 	  If you say yes to this option, support will be included for the
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
index b00cd40..f634a07 100644
--- a/drivers/i2c/busses/i2c-ali1535.c
+++ b/drivers/i2c/busses/i2c-ali1535.c
@@ -53,7 +53,6 @@
 
 /* Note: we assume there can only be one ALI1535, with one SMBus interface */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
index 5bd6a4a..0f781a1 100644
--- a/drivers/i2c/busses/i2c-ali15x3.c
+++ b/drivers/i2c/busses/i2c-ali15x3.c
@@ -60,7 +60,6 @@
 
 /* Note: we assume there can only be one ALI15X3, with one SMBus interface */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
index eca5ed3..6347ebc 100644
--- a/drivers/i2c/busses/i2c-amd756.c
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -37,7 +37,6 @@
    Note: we assume there can only be one device, with one SMBus interface.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
index af22b40..d664448 100644
--- a/drivers/i2c/busses/i2c-amd8111.c
+++ b/drivers/i2c/busses/i2c-amd8111.c
@@ -8,7 +8,6 @@
  * the Free Software Foundation version 2.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
diff --git a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c
index 75831a20..a7ff112 100644
--- a/drivers/i2c/busses/i2c-au1550.c
+++ b/drivers/i2c/busses/i2c-au1550.c
@@ -27,7 +27,6 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
-#include <linux/config.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
diff --git a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
index 0a77200..6930b66 100644
--- a/drivers/i2c/busses/i2c-elektor.c
+++ b/drivers/i2c/busses/i2c-elektor.c
@@ -25,7 +25,6 @@
 /* Partialy rewriten by Oleg I. Vdovikin for mmapped support of 
    for Alpha Processor Inc. UP-2000(+) boards */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
diff --git a/drivers/i2c/busses/i2c-frodo.c b/drivers/i2c/busses/i2c-frodo.c
index e093829..b6f52f5 100644
--- a/drivers/i2c/busses/i2c-frodo.c
+++ b/drivers/i2c/busses/i2c-frodo.c
@@ -12,7 +12,6 @@
  * version 2 as published by the Free Software Foundation.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 59c238c..45e6efb1 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -41,7 +41,6 @@
 
 /* Note: we assume there can only be one I801, with one SMBus interface */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
diff --git a/drivers/i2c/busses/i2c-i810.c b/drivers/i2c/busses/i2c-i810.c
index ef358bd..0ff7016 100644
--- a/drivers/i2c/busses/i2c-i810.c
+++ b/drivers/i2c/busses/i2c-i810.c
@@ -34,7 +34,6 @@
    i815			1132           
 */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index bb88521..93ca36d 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -695,7 +695,7 @@
 
 	dev->irq = iic_force_poll ? -1 : ocp->def->irq;
 	if (dev->irq >= 0){
-		/* Disable interrupts until we finish intialization,
+		/* Disable interrupts until we finish initialization,
 		   assumes level-sensitive IRQ setup...
 		 */
 		iic_interrupt_mode(dev, 0);
diff --git a/drivers/i2c/busses/i2c-ibm_iic.h b/drivers/i2c/busses/i2c-ibm_iic.h
index d819a95..2b3219d 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.h
+++ b/drivers/i2c/busses/i2c-ibm_iic.h
@@ -22,7 +22,6 @@
 #ifndef __I2C_IBM_IIC_H_
 #define __I2C_IBM_IIC_H_
 
-#include <linux/config.h>
 #include <linux/i2c.h> 
 
 struct iic_regs {
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index c961ba4..6b682e9 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -85,7 +85,7 @@
 	u32 cr = IOP3XX_ICR_GCD | IOP3XX_ICR_SCLEN | IOP3XX_ICR_UE;
 
 	/* 
-	 * Everytime unit enable is asserted, GPOD needs to be cleared
+	 * Every time unit enable is asserted, GPOD needs to be cleared
 	 * on IOP321 to avoid data corruption on the bus.
 	 */
 #ifdef CONFIG_ARCH_IOP321
diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c
index 0f54a2a..00e7f71 100644
--- a/drivers/i2c/busses/i2c-isa.c
+++ b/drivers/i2c/busses/i2c-isa.c
@@ -24,7 +24,6 @@
    the SMBus and the ISA bus very much easier. See lm78.c for an example
    of this. */
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
diff --git a/drivers/i2c/busses/i2c-ite.c b/drivers/i2c/busses/i2c-ite.c
index 702e3de..5f5d294 100644
--- a/drivers/i2c/busses/i2c-ite.c
+++ b/drivers/i2c/busses/i2c-ite.c
@@ -33,7 +33,6 @@
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
    Frodo Looijaard <frodol@dds.nl> */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
diff --git a/drivers/i2c/busses/i2c-ixp2000.c b/drivers/i2c/busses/i2c-ixp2000.c
index 21cd54d..1956af3 100644
--- a/drivers/i2c/busses/i2c-ixp2000.c
+++ b/drivers/i2c/busses/i2c-ixp2000.c
@@ -26,11 +26,6 @@
  * 'enabled' to drive the GPIOs.
  */
 
-#include <linux/config.h>
-#ifdef CONFIG_I2C_DEBUG_BUS
-#define DEBUG	1
-#endif
-
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/device.h>
@@ -38,7 +33,8 @@
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
 
-#include <asm/hardware.h>	/* Pick up IXP42000-specific bits */
+#include <asm/hardware.h>	/* Pick up IXP2000-specific bits */
+#include <asm/arch/gpio.h>
 
 static inline int ixp2000_scl_pin(void *data)
 {
diff --git a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c
index 8c55eaf..f6f5ca3 100644
--- a/drivers/i2c/busses/i2c-ixp4xx.c
+++ b/drivers/i2c/busses/i2c-ixp4xx.c
@@ -26,11 +26,6 @@
  *       that is passed as the platform_data to this driver.
  */
 
-#include <linux/config.h>
-#ifdef CONFIG_I2C_DEBUG_BUS
-#define DEBUG	1
-#endif
-
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/device.h>
diff --git a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c
index 867d443..363e545 100644
--- a/drivers/i2c/busses/i2c-keywest.c
+++ b/drivers/i2c/busses/i2c-keywest.c
@@ -46,7 +46,6 @@
     sound driver to be happy
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 6f33496..03c23ce 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -20,13 +20,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <asm/io.h>
-#ifdef CONFIG_FSL_OCP
-#include <asm/ocp.h>
-#define FSL_I2C_DEV_SEPARATE_DFSRR FS_I2C_SEPARATE_DFSRR
-#define FSL_I2C_DEV_CLOCK_5200 FS_I2C_CLOCK_5200
-#else
 #include <linux/fsl_devices.h>
-#endif
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
@@ -294,202 +288,6 @@
 	.retries = 1
 };
 
-#ifdef CONFIG_FSL_OCP
-static int __devinit mpc_i2c_probe(struct ocp_device *ocp)
-{
-	int result = 0;
-	struct mpc_i2c *i2c;
-
-	if (!(i2c = kmalloc(sizeof(*i2c), GFP_KERNEL))) {
-		return -ENOMEM;
-	}
-	memset(i2c, 0, sizeof(*i2c));
-
-	i2c->irq = ocp->def->irq;
-	i2c->flags = ((struct ocp_fs_i2c_data *)ocp->def->additions)->flags;
-	init_waitqueue_head(&i2c->queue);
-
-	if (!request_mem_region(ocp->def->paddr, MPC_I2C_REGION, "i2c-mpc")) {
-		printk(KERN_ERR "i2c-mpc - resource unavailable\n");
-		return -ENODEV;
-	}
-
-	i2c->base = ioremap(ocp->def->paddr, MPC_I2C_REGION);
-
-	if (!i2c->base) {
-		printk(KERN_ERR "i2c-mpc - failed to map controller\n");
-		result = -ENOMEM;
-		goto fail_map;
-	}
-
-	if (i2c->irq != OCP_IRQ_NA)
-	{
-		if ((result = request_irq(ocp->def->irq, mpc_i2c_isr,
-					  0, "i2c-mpc", i2c)) < 0) {
-			printk(KERN_ERR
-			       "i2c-mpc - failed to attach interrupt\n");
-			goto fail_irq;
-		}
-	} else
-		i2c->irq = 0;
-
-	i2c->adap = mpc_ops;
-	i2c_set_adapdata(&i2c->adap, i2c);
-
-	if ((result = i2c_add_adapter(&i2c->adap)) < 0) {
-		printk(KERN_ERR "i2c-mpc - failed to add adapter\n");
-		goto fail_add;
-	}
-
-	mpc_i2c_setclock(i2c);
-	ocp_set_drvdata(ocp, i2c);
-	return result;
-
-      fail_add:
-	if (ocp->def->irq != OCP_IRQ_NA)
-		free_irq(ocp->def->irq, 0);
-      fail_irq:
-	iounmap(i2c->base);
-      fail_map:
-	release_mem_region(ocp->def->paddr, MPC_I2C_REGION);
-	kfree(i2c);
-	return result;
-}
-static void __devexit mpc_i2c_remove(struct ocp_device *ocp)
-{
-	struct mpc_i2c *i2c = ocp_get_drvdata(ocp);
-	ocp_set_drvdata(ocp, NULL);
-	i2c_del_adapter(&i2c->adap);
-
-	if (ocp->def->irq != OCP_IRQ_NA)
-		free_irq(i2c->irq, i2c);
-	iounmap(i2c->base);
-	release_mem_region(ocp->def->paddr, MPC_I2C_REGION);
-	kfree(i2c);
-}
-
-static struct ocp_device_id mpc_iic_ids[] __devinitdata = {
-	{.vendor = OCP_VENDOR_FREESCALE,.function = OCP_FUNC_IIC},
-	{.vendor = OCP_VENDOR_INVALID}
-};
-
-MODULE_DEVICE_TABLE(ocp, mpc_iic_ids);
-
-static struct ocp_driver mpc_iic_driver = {
-	.name = "iic",
-	.id_table = mpc_iic_ids,
-	.probe = mpc_i2c_probe,
-	.remove = __devexit_p(mpc_i2c_remove)
-};
-
-static int __init iic_init(void)
-{
-	return ocp_register_driver(&mpc_iic_driver);
-}
-
-static void __exit iic_exit(void)
-{
-	ocp_unregister_driver(&mpc_iic_driver);
-}
-
-module_init(iic_init);
-module_exit(iic_exit);
-#else
-static int fsl_i2c_probe(struct device *device)
-{
-	int result = 0;
-	struct mpc_i2c *i2c;
-	struct platform_device *pdev = to_platform_device(device);
-	struct fsl_i2c_platform_data *pdata;
-	struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
-	pdata = (struct fsl_i2c_platform_data *) pdev->dev.platform_data;
-
-	if (!(i2c = kmalloc(sizeof(*i2c), GFP_KERNEL))) {
-		return -ENOMEM;
-	}
-	memset(i2c, 0, sizeof(*i2c));
-
-	i2c->irq = platform_get_irq(pdev, 0);
-	i2c->flags = pdata->device_flags;
-	init_waitqueue_head(&i2c->queue);
-
-	i2c->base = ioremap((phys_addr_t)r->start, MPC_I2C_REGION);
-
-	if (!i2c->base) {
-		printk(KERN_ERR "i2c-mpc - failed to map controller\n");
-		result = -ENOMEM;
-		goto fail_map;
-	}
-
-	if (i2c->irq != 0)
-		if ((result = request_irq(i2c->irq, mpc_i2c_isr,
-					  0, "fsl-i2c", i2c)) < 0) {
-			printk(KERN_ERR
-			       "i2c-mpc - failed to attach interrupt\n");
-			goto fail_irq;
-		}
-
-	i2c->adap = mpc_ops;
-	i2c_set_adapdata(&i2c->adap, i2c);
-	i2c->adap.dev.parent = &pdev->dev;
-	if ((result = i2c_add_adapter(&i2c->adap)) < 0) {
-		printk(KERN_ERR "i2c-mpc - failed to add adapter\n");
-		goto fail_add;
-	}
-
-	mpc_i2c_setclock(i2c);
-	dev_set_drvdata(device, i2c);
-	return result;
-
-      fail_add:
-	if (i2c->irq != 0)
-		free_irq(i2c->irq, NULL);
-      fail_irq:
-	iounmap(i2c->base);
-      fail_map:
-	kfree(i2c);
-	return result;
-};
-
-static int fsl_i2c_remove(struct device *device)
-{
-	struct mpc_i2c *i2c = dev_get_drvdata(device);
-
-	dev_set_drvdata(device, NULL);
-	i2c_del_adapter(&i2c->adap);
-
-	if (i2c->irq != 0)
-		free_irq(i2c->irq, i2c);
-
-	iounmap(i2c->base);
-	kfree(i2c);
-	return 0;
-};
-
-/* Structure for a device driver */
-static struct device_driver fsl_i2c_driver = {
-	.name = "fsl-i2c",
-	.bus = &platform_bus_type,
-	.probe = fsl_i2c_probe,
-	.remove = fsl_i2c_remove,
-};
-
-static int __init fsl_i2c_init(void)
-{
-	return driver_register(&fsl_i2c_driver);
-}
-
-static void __exit fsl_i2c_exit(void)
-{
-	driver_unregister(&fsl_i2c_driver);
-}
-
-module_init(fsl_i2c_init);
-module_exit(fsl_i2c_exit);
-
-#endif /* CONFIG_FSL_OCP */
-
 MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>");
 MODULE_DESCRIPTION
     ("I2C-Bus adapter for MPC107 bridge and MPC824x/85xx/52xx processors");
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index 6d13127..74eb89a 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -37,7 +37,6 @@
 
 /* Note: we assume there can only be one nForce2, with two SMBus interfaces */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
diff --git a/drivers/i2c/busses/i2c-parport-light.c b/drivers/i2c/busses/i2c-parport-light.c
index cb5e722..3e5eba9 100644
--- a/drivers/i2c/busses/i2c-parport-light.c
+++ b/drivers/i2c/busses/i2c-parport-light.c
@@ -24,7 +24,6 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  * ------------------------------------------------------------------------ */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
diff --git a/drivers/i2c/busses/i2c-parport.c b/drivers/i2c/busses/i2c-parport.c
index e9560ba..71a2502 100644
--- a/drivers/i2c/busses/i2c-parport.c
+++ b/drivers/i2c/busses/i2c-parport.c
@@ -24,7 +24,6 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  * ------------------------------------------------------------------------ */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -131,7 +130,7 @@
 /* Encapsulate the functions above in the correct structure.
    Note that this is only a template, from which the real structures are
    copied. The attaching code will set getscl to NULL for adapters that
-   cannot read SCL back, and will also make the the data field point to
+   cannot read SCL back, and will also make the data field point to
    the parallel port structure. */
 static struct i2c_algo_bit_data parport_algo_data = {
 	.setsda		= parport_setsda,
diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c
index 9c61113..d9b4ddb 100644
--- a/drivers/i2c/busses/i2c-pca-isa.c
+++ b/drivers/i2c/busses/i2c-pca-isa.c
@@ -17,7 +17,6 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 646381b..1f80ba9 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -28,7 +28,6 @@
    Note: we assume there can only be one device, with one SMBus interface.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/pci.h>
diff --git a/drivers/i2c/busses/i2c-prosavage.c b/drivers/i2c/busses/i2c-prosavage.c
index 13d6628..83fd16d 100644
--- a/drivers/i2c/busses/i2c-prosavage.c
+++ b/drivers/i2c/busses/i2c-prosavage.c
@@ -54,7 +54,6 @@
  *    (Additional documentation needed :(
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/pci.h>
diff --git a/drivers/i2c/busses/i2c-rpx.c b/drivers/i2c/busses/i2c-rpx.c
index 9497b1b..0ebec3c 100644
--- a/drivers/i2c/busses/i2c-rpx.c
+++ b/drivers/i2c/busses/i2c-rpx.c
@@ -11,7 +11,6 @@
  * changed to eliminate RPXLite references.
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index fcfa51c..a3b3825 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -20,6 +20,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 
@@ -533,7 +534,7 @@
 /* s3c24xx_i2c_xfer
  *
  * first port of call from the i2c bus code when an message needs
- * transfering across the i2c bus.
+ * transferring across the i2c bus.
 */
 
 static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
diff --git a/drivers/i2c/busses/i2c-savage4.c b/drivers/i2c/busses/i2c-savage4.c
index 092d032..0c85182 100644
--- a/drivers/i2c/busses/i2c-savage4.c
+++ b/drivers/i2c/busses/i2c-savage4.c
@@ -29,7 +29,6 @@
    it easier to add later.
 */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
diff --git a/drivers/i2c/busses/i2c-sibyte.c b/drivers/i2c/busses/i2c-sibyte.c
index e5dd90b..1c99536 100644
--- a/drivers/i2c/busses/i2c-sibyte.c
+++ b/drivers/i2c/busses/i2c-sibyte.c
@@ -17,7 +17,6 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/i2c-algo-sibyte.h>
 #include <asm/sibyte/sb1250_regs.h>
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
index 425733b..2b5911c 100644
--- a/drivers/i2c/busses/i2c-sis5595.c
+++ b/drivers/i2c/busses/i2c-sis5595.c
@@ -55,7 +55,6 @@
  * Add adapter resets
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/delay.h>
diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c
index 58df63d..f58455e 100644
--- a/drivers/i2c/busses/i2c-sis630.c
+++ b/drivers/i2c/busses/i2c-sis630.c
@@ -48,7 +48,6 @@
    Note: we assume there can only be one device, with one SMBus interface.
 */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/delay.h>
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
index 3cac6d4..6484792 100644
--- a/drivers/i2c/busses/i2c-sis96x.c
+++ b/drivers/i2c/busses/i2c-sis96x.c
@@ -32,7 +32,6 @@
     We assume there can only be one SiS96x with one SMBus interface.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/busses/i2c-stub.c
index 19c805e..00d94e8 100644
--- a/drivers/i2c/busses/i2c-stub.c
+++ b/drivers/i2c/busses/i2c-stub.c
@@ -21,7 +21,6 @@
 
 #define DEBUG 1
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c
index 2cbc4cd..040b8ab 100644
--- a/drivers/i2c/busses/i2c-via.c
+++ b/drivers/i2c/busses/i2c-via.c
@@ -21,7 +21,6 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index 0bb60a6..6b50080 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -33,7 +33,6 @@
    Note: we assume there can only be one device, with one SMBus interface.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
diff --git a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c
index 3edf0e3..b675773 100644
--- a/drivers/i2c/busses/i2c-voodoo3.c
+++ b/drivers/i2c/busses/i2c-voodoo3.c
@@ -27,7 +27,6 @@
 /* This interfaces to the I2C bus of the Voodoo3 to gain access to
     the BT869 and possibly other I2C devices. */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c
index 1c4159a..a18bdd9 100644
--- a/drivers/i2c/busses/scx200_acb.c
+++ b/drivers/i2c/busses/scx200_acb.c
@@ -24,7 +24,6 @@
 
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index 74d23cf..a0982da 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -1,5 +1,5 @@
 #
-# I2C Sensor device configuration
+# I2C Sensor and "other" chip configuration
 #
 
 menu "Hardware Sensors Chip support"
@@ -11,7 +11,7 @@
 
 config SENSORS_ADM1021
 	tristate "Analog Devices ADM1021 and compatibles"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	select I2C_SENSOR
 	help
 	  If you say yes here you get support for Analog Devices ADM1021 
@@ -29,6 +29,7 @@
 	help
 	  If you say yes here you get support for Analog Devices ADM1025
 	  and Philips NE1619 sensor chips.
+
 	  This driver can also be built as a module.  If so, the module
 	  will be called adm1025.
 
@@ -38,6 +39,8 @@
 	select I2C_SENSOR
 	help
 	  If you say yes here you get support for Analog Devices ADM1026
+	  sensor chip.
+
 	  This driver can also be built as a module.  If so, the module
 	  will be called adm1026.
 
@@ -48,9 +51,21 @@
 	help
 	  If you say yes here you get support for Analog Devices ADM1031 
 	  and ADM1030 sensor chips.
+
 	  This driver can also be built as a module.  If so, the module
 	  will be called adm1031.
 
+config SENSORS_ADM9240
+	tristate "Analog Devices ADM9240 and compatibles"
+	depends on I2C && EXPERIMENTAL
+	select I2C_SENSOR
+	help
+	  If you say yes here you get support for Analog Devices ADM9240,
+	  Dallas DS1780, National Semiconductor LM81 sensor chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called adm9240.
+
 config SENSORS_ASB100
 	tristate "Asus ASB100 Bach"
 	depends on I2C && EXPERIMENTAL
@@ -62,6 +77,19 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called asb100.
 
+config SENSORS_ATXP1
+	tristate "Attansic ATXP1 VID controller"
+	depends on I2C && EXPERIMENTAL
+	help
+	  If you say yes here you get support for the Attansic ATXP1 VID
+	  controller.
+
+	  If your board have such a chip, you are able to control your CPU
+	  core and other voltages.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called atxp1.
+
 config SENSORS_DS1621
 	tristate "Dallas Semiconductor DS1621 and DS1625"
 	depends on I2C && EXPERIMENTAL
@@ -97,7 +125,7 @@
 
 config SENSORS_GL518SM
 	tristate "Genesys Logic GL518SM"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	select I2C_SENSOR
 	help
 	  If you say yes here you get support for Genesys Logic GL518SM
@@ -119,7 +147,7 @@
 
 config SENSORS_IT87
 	tristate "ITE IT87xx and compatibles"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	select I2C_SENSOR
 	help
 	  If you say yes here you get support for ITE IT87xx sensor chips
@@ -143,7 +171,7 @@
 
 config SENSORS_LM75
 	tristate "National Semiconductor LM75 and compatibles"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	select I2C_SENSOR
 	help
 	  If you say yes here you get support for National Semiconductor LM75
@@ -174,8 +202,7 @@
 	select I2C_SENSOR
 	help
 	  If you say yes here you get support for National Semiconductor LM78,
-	  LM78-J and LM79.  This can also be built as a module which can be
-	  inserted and removed while the kernel is running.
+	  LM78-J and LM79.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called lm78.
@@ -208,7 +235,7 @@
 	select I2C_SENSOR
 	help
 	  If you say yes here you get support for National Semiconductor LM85
-	  sensor chips and clones: ADT7463 and ADM1027.
+	  sensor chips and clones: ADT7463, EMC6D100, EMC6D102 and ADM1027.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called lm85.
@@ -307,14 +334,14 @@
 	help
 	  If you say yes here you get support for the integrated fan
 	  monitoring and control capabilities of the SMSC LPC47B27x,
-	  LPC47M10x, LPC47M13x and LPC47M14x chips.
+	  LPC47M10x, LPC47M13x, LPC47M14x, LPC47M15x and LPC47M192 chips.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called smsc47m1.
 
 config SENSORS_VIA686A
 	tristate "VIA686A"
-	depends on I2C && PCI && EXPERIMENTAL
+	depends on I2C && PCI
 	select I2C_SENSOR
 	select I2C_ISA
 	help
@@ -326,7 +353,7 @@
 
 config SENSORS_W83781D
 	tristate "Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F"
-	depends on I2C && EXPERIMENTAL
+	depends on I2C
 	select I2C_SENSOR
 	help
 	  If you say yes here you get support for the Winbond W8378x series
@@ -360,22 +387,47 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called w83627hf.
 
+config SENSORS_W83627EHF
+	tristate "Winbond W83627EHF"
+	depends on I2C && EXPERIMENTAL
+	select I2C_SENSOR
+	select I2C_ISA
+	help
+	  If you say yes here you get preliminary support for the hardware
+	  monitoring functionality of the Winbond W83627EHF Super-I/O chip.
+	  Only fan and temperature inputs are supported at the moment, while
+	  the chip does much more than that.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called w83627ehf.
+
 endmenu
 
 menu "Other I2C Chip support"
 	depends on I2C
 
 config SENSORS_DS1337
-	tristate "Dallas Semiconductor DS1337 Real Time Clock"
+	tristate "Dallas Semiconductor DS1337 and DS1339 Real Time Clock"
 	depends on I2C && EXPERIMENTAL
 	select I2C_SENSOR
 	help
 	  If you say yes here you get support for Dallas Semiconductor
-	  DS1337 real-time clock chips. 
+	  DS1337 and DS1339 real-time clock chips.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called ds1337.
 
+config SENSORS_DS1374
+	tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock"
+	depends on I2C && EXPERIMENTAL
+	select I2C_SENSOR
+	help
+	  If you say yes here you get support for Dallas Semiconductor
+	  DS1374 real-time clock chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called ds1374.
+
 config SENSORS_EEPROM
 	tristate "EEPROM reader"
 	depends on I2C && EXPERIMENTAL
@@ -399,6 +451,16 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called pcf8574.
 
+config SENSORS_PCA9539
+	tristate "Philips PCA9539 16-bit I/O port"
+	depends on I2C && EXPERIMENTAL
+	help
+	  If you say yes here you get support for the Philips PCA9539
+	  16-bit I/O port.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called pca9539.
+
 config SENSORS_PCF8591
 	tristate "Philips PCF8591"
 	depends on I2C && EXPERIMENTAL
@@ -431,6 +493,23 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called isp1301_omap.
 
+# NOTE:  This isn't really OMAP-specific, except for the current
+# interface location in  <include/asm-arm/arch-omap/tps65010.h>
+# and having mostly OMAP-specific board support
+config TPS65010
+	tristate "TPS6501x Power Management chips"
+	depends on I2C && ARCH_OMAP
+	default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK
+	help
+	  If you say yes here you get support for the TPS6501x series of
+	  Power Management chips.  These include voltage regulators,
+	  lithium ion/polymer battery charging, and other features that
+	  are often used in portable devices like cell phones and cameras.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called tps65010.
+
+
 config SENSORS_M41T00
 	tristate "ST M41T00 RTC chip"
 	depends on I2C && PPC32
@@ -440,4 +519,16 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called m41t00.
 
+config SENSORS_MAX6875
+	tristate "MAXIM MAX6875 Power supply supervisor"
+	depends on I2C && EXPERIMENTAL
+	help
+	  If you say yes here you get support for the MAX6875
+	  EEPROM-Programmable, Hex/Quad, Power-Suppy Sequencers/Supervisors.
+
+          This provides a interface to program the EEPROM and reset the chip.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called max6875.
+
 endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 6559916..b5e6d2f 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -1,5 +1,5 @@
 #
-# Makefile for the kernel hardware sensors chip drivers.
+# Makefile for sensor and "other" I2C chip drivers.
 #
 
 # asb100, then w83781d go first, as they can override other drivers' addresses.
@@ -11,7 +11,10 @@
 obj-$(CONFIG_SENSORS_ADM1025)	+= adm1025.o
 obj-$(CONFIG_SENSORS_ADM1026)	+= adm1026.o
 obj-$(CONFIG_SENSORS_ADM1031)	+= adm1031.o
+obj-$(CONFIG_SENSORS_ADM9240)	+= adm9240.o
+obj-$(CONFIG_SENSORS_ATXP1)	+= atxp1.o
 obj-$(CONFIG_SENSORS_DS1337)	+= ds1337.o
+obj-$(CONFIG_SENSORS_DS1374)	+= ds1374.o
 obj-$(CONFIG_SENSORS_DS1621)	+= ds1621.o
 obj-$(CONFIG_SENSORS_EEPROM)	+= eeprom.o
 obj-$(CONFIG_SENSORS_FSCHER)	+= fscher.o
@@ -30,8 +33,10 @@
 obj-$(CONFIG_SENSORS_LM90)	+= lm90.o
 obj-$(CONFIG_SENSORS_LM92)	+= lm92.o
 obj-$(CONFIG_SENSORS_MAX1619)	+= max1619.o
+obj-$(CONFIG_SENSORS_MAX6875)	+= max6875.o
 obj-$(CONFIG_SENSORS_M41T00)	+= m41t00.o
 obj-$(CONFIG_SENSORS_PC87360)	+= pc87360.o
+obj-$(CONFIG_SENSORS_PCA9539)	+= pca9539.o
 obj-$(CONFIG_SENSORS_PCF8574)	+= pcf8574.o
 obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
 obj-$(CONFIG_SENSORS_RTC8564)	+= rtc8564.o
@@ -39,8 +44,11 @@
 obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
 obj-$(CONFIG_SENSORS_SMSC47M1)	+= smsc47m1.o
 obj-$(CONFIG_SENSORS_VIA686A)	+= via686a.o
+obj-$(CONFIG_SENSORS_W83627EHF)	+= w83627ehf.o
 obj-$(CONFIG_SENSORS_W83L785TS)	+= w83l785ts.o
+
 obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
+obj-$(CONFIG_TPS65010)		+= tps65010.o
 
 ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
index 9c59a37..d2c774c 100644
--- a/drivers/i2c/chips/adm1021.c
+++ b/drivers/i2c/chips/adm1021.c
@@ -19,7 +19,6 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -103,8 +102,6 @@
 	u8	remote_temp_hyst;
 	u8	remote_temp_input;
 	u8	alarms;
-	/* special values for ADM1021 only */
-	u8	die_code;
         /* Special values for ADM1023 only */
 	u8	remote_temp_prec;
 	u8	remote_temp_os_prec;
@@ -137,7 +134,7 @@
 };
 
 #define show(value)	\
-static ssize_t show_##value(struct device *dev, char *buf)		\
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf)		\
 {									\
 	struct adm1021_data *data = adm1021_update_device(dev);		\
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value));	\
@@ -150,16 +147,15 @@
 show(remote_temp_input);
 
 #define show2(value)	\
-static ssize_t show_##value(struct device *dev, char *buf)		\
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf)		\
 {									\
 	struct adm1021_data *data = adm1021_update_device(dev);		\
 	return sprintf(buf, "%d\n", data->value);			\
 }
 show2(alarms);
-show2(die_code);
 
 #define set(value, reg)	\
-static ssize_t set_##value(struct device *dev, const char *buf, size_t count)	\
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)	\
 {								\
 	struct i2c_client *client = to_i2c_client(dev);		\
 	struct adm1021_data *data = i2c_get_clientdata(client);	\
@@ -183,7 +179,6 @@
 static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_remote_temp_hyst, set_remote_temp_hyst);
 static DEVICE_ATTR(temp2_input, S_IRUGO, show_remote_temp_input, NULL);
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
-static DEVICE_ATTR(die_code, S_IRUGO, show_die_code, NULL);
 
 
 static int adm1021_attach_adapter(struct i2c_adapter *adapter)
@@ -307,8 +302,6 @@
 	device_create_file(&new_client->dev, &dev_attr_temp2_min);
 	device_create_file(&new_client->dev, &dev_attr_temp2_input);
 	device_create_file(&new_client->dev, &dev_attr_alarms);
-	if (data->type == adm1021)
-		device_create_file(&new_client->dev, &dev_attr_die_code);
 
 	return 0;
 
@@ -371,8 +364,6 @@
 		data->remote_temp_max = adm1021_read_value(client, ADM1021_REG_REMOTE_TOS_R);
 		data->remote_temp_hyst = adm1021_read_value(client, ADM1021_REG_REMOTE_THYST_R);
 		data->alarms = adm1021_read_value(client, ADM1021_REG_STATUS) & 0x7c;
-		if (data->type == adm1021)
-			data->die_code = adm1021_read_value(client, ADM1021_REG_DIE_CODE);
 		if (data->type == adm1023) {
 			data->remote_temp_prec = adm1021_read_value(client, ADM1021_REG_REM_TEMP_PREC);
 			data->remote_temp_os_prec = adm1021_read_value(client, ADM1021_REG_REM_TOS_PREC);
diff --git a/drivers/i2c/chips/adm1025.c b/drivers/i2c/chips/adm1025.c
index e0771a3..e452d0d 100644
--- a/drivers/i2c/chips/adm1025.c
+++ b/drivers/i2c/chips/adm1025.c
@@ -45,7 +45,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -153,19 +152,19 @@
  */
 
 #define show_in(offset) \
-static ssize_t show_in##offset(struct device *dev, char *buf) \
+static ssize_t show_in##offset(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct adm1025_data *data = adm1025_update_device(dev); \
 	return sprintf(buf, "%u\n", IN_FROM_REG(data->in[offset], \
 		       in_scale[offset])); \
 } \
-static ssize_t show_in##offset##_min(struct device *dev, char *buf) \
+static ssize_t show_in##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct adm1025_data *data = adm1025_update_device(dev); \
 	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[offset], \
 		       in_scale[offset])); \
 } \
-static ssize_t show_in##offset##_max(struct device *dev, char *buf) \
+static ssize_t show_in##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct adm1025_data *data = adm1025_update_device(dev); \
 	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[offset], \
@@ -180,17 +179,17 @@
 show_in(5);
 
 #define show_temp(offset) \
-static ssize_t show_temp##offset(struct device *dev, char *buf) \
+static ssize_t show_temp##offset(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct adm1025_data *data = adm1025_update_device(dev); \
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[offset-1])); \
 } \
-static ssize_t show_temp##offset##_min(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct adm1025_data *data = adm1025_update_device(dev); \
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[offset-1])); \
 } \
-static ssize_t show_temp##offset##_max(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct adm1025_data *data = adm1025_update_device(dev); \
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[offset-1])); \
@@ -200,7 +199,7 @@
 show_temp(2);
 
 #define set_in(offset) \
-static ssize_t set_in##offset##_min(struct device *dev, const char *buf, \
+static ssize_t set_in##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
 	size_t count) \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
@@ -214,7 +213,7 @@
 	up(&data->update_lock); \
 	return count; \
 } \
-static ssize_t set_in##offset##_max(struct device *dev, const char *buf, \
+static ssize_t set_in##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
 	size_t count) \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
@@ -240,7 +239,7 @@
 set_in(5);
 
 #define set_temp(offset) \
-static ssize_t set_temp##offset##_min(struct device *dev, const char *buf, \
+static ssize_t set_temp##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
 	size_t count) \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
@@ -254,7 +253,7 @@
 	up(&data->update_lock); \
 	return count; \
 } \
-static ssize_t set_temp##offset##_max(struct device *dev, const char *buf, \
+static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
 	size_t count) \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
@@ -275,26 +274,28 @@
 set_temp(1);
 set_temp(2);
 
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1025_data *data = adm1025_update_device(dev);
 	return sprintf(buf, "%u\n", data->alarms);
 }
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
-static ssize_t show_vid(struct device *dev, char *buf)
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1025_data *data = adm1025_update_device(dev);
 	return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));
 }
+/* in1_ref is deprecated in favour of cpu0_vid, remove after 2005-11-11 */
 static DEVICE_ATTR(in1_ref, S_IRUGO, show_vid, NULL);
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
 
-static ssize_t show_vrm(struct device *dev, char *buf)
+static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1025_data *data = adm1025_update_device(dev);
 	return sprintf(buf, "%u\n", data->vrm);
 }
-static ssize_t set_vrm(struct device *dev, const char *buf, size_t count)
+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 adm1025_data *data = i2c_get_clientdata(client);
@@ -437,7 +438,9 @@
 	device_create_file(&new_client->dev, &dev_attr_temp1_max);
 	device_create_file(&new_client->dev, &dev_attr_temp2_max);
 	device_create_file(&new_client->dev, &dev_attr_alarms);
+	/* in1_ref is deprecated, remove after 2005-11-11 */
 	device_create_file(&new_client->dev, &dev_attr_in1_ref);
+	device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
 	device_create_file(&new_client->dev, &dev_attr_vrm);
 
 	/* Pin 11 is either in4 (+12V) or VID4 */
diff --git a/drivers/i2c/chips/adm1026.c b/drivers/i2c/chips/adm1026.c
index 39e2f4a..3c85fe1 100644
--- a/drivers/i2c/chips/adm1026.c
+++ b/drivers/i2c/chips/adm1026.c
@@ -23,7 +23,6 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -31,6 +30,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 #include <linux/i2c-vid.h>
+#include <linux/hwmon-sysfs.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
@@ -711,19 +711,27 @@
 	return data;
 }
 
-static ssize_t show_in(struct device *dev, char *buf, int nr)
+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 adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in[nr]));
 }
-static ssize_t show_in_min(struct device *dev, char *buf, int 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 adm1026_data *data = adm1026_update_device(dev); 
 	return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_min[nr]));
 }
-static ssize_t set_in_min(struct device *dev, const char *buf, 
-		size_t count, int 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 adm1026_data *data = i2c_get_clientdata(client);
 	int val = simple_strtol(buf, NULL, 10);
@@ -734,14 +742,19 @@
 	up(&data->update_lock);
 	return count; 
 }
-static ssize_t show_in_max(struct device *dev, char *buf, int 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 adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%d\n", INS_FROM_REG(nr, data->in_max[nr]));
 }
-static ssize_t set_in_max(struct device *dev, const char *buf,
-		size_t count, int nr)
+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 adm1026_data *data = i2c_get_clientdata(client);
 	int val = simple_strtol(buf, NULL, 10);
@@ -753,34 +766,13 @@
 	return count;
 }
 
-#define in_reg(offset)                                                    \
-static ssize_t show_in##offset (struct device *dev, char *buf)            \
-{                                                                         \
-	return show_in(dev, buf, offset);                                 \
-}                                                                         \
-static ssize_t show_in##offset##_min (struct device *dev, char *buf)      \
-{                                                                         \
-	return show_in_min(dev, buf, offset);                             \
-}                                                                         \
-static ssize_t set_in##offset##_min (struct device *dev,                  \
-	const char *buf, size_t count)                                    \
-{                                                                         \
-	return set_in_min(dev, buf, count, offset);                       \
-}                                                                         \
-static ssize_t show_in##offset##_max (struct device *dev, char *buf)      \
-{                                                                         \
-	return show_in_max(dev, buf, offset);                             \
-}                                                                         \
-static ssize_t set_in##offset##_max (struct device *dev,                  \
-	const char *buf, size_t count)                                    \
-{                                                                         \
-	return set_in_max(dev, buf, count, offset);                       \
-}                                                                         \
-static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL);   \
-static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR,                   \
-		show_in##offset##_min, set_in##offset##_min);             \
-static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,                   \
-		show_in##offset##_max, set_in##offset##_max);
+#define in_reg(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);
 
 
 in_reg(0);
@@ -800,19 +792,19 @@
 in_reg(14);
 in_reg(15);
 
-static ssize_t show_in16(struct device *dev, char *buf)
+static ssize_t show_in16(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%d\n", INS_FROM_REG(16, data->in[16]) -
 		NEG12_OFFSET);
 }
-static ssize_t show_in16_min(struct device *dev, char *buf) 
+static ssize_t show_in16_min(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev); 
 	return sprintf(buf,"%d\n", INS_FROM_REG(16, data->in_min[16])
 		- NEG12_OFFSET);
 }
-static ssize_t set_in16_min(struct device *dev, const char *buf, size_t count)
+static ssize_t set_in16_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
@@ -824,13 +816,13 @@
 	up(&data->update_lock);
 	return count; 
 }
-static ssize_t show_in16_max(struct device *dev, char *buf)
+static ssize_t show_in16_max(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%d\n", INS_FROM_REG(16, data->in_max[16])
 			- NEG12_OFFSET);
 }
-static ssize_t set_in16_max(struct device *dev, const char *buf, size_t count)
+static ssize_t set_in16_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
@@ -843,30 +835,38 @@
 	return count;
 }
 
-static DEVICE_ATTR(in16_input, S_IRUGO, show_in16, NULL);
-static DEVICE_ATTR(in16_min, S_IRUGO | S_IWUSR, show_in16_min, set_in16_min);
-static DEVICE_ATTR(in16_max, S_IRUGO | S_IWUSR, show_in16_max, set_in16_max);
+static SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, show_in16, NULL, 16);
+static SENSOR_DEVICE_ATTR(in16_min, S_IRUGO | S_IWUSR, show_in16_min, set_in16_min, 16);
+static SENSOR_DEVICE_ATTR(in16_max, S_IRUGO | S_IWUSR, show_in16_max, set_in16_max, 16);
 
 
 
 
 /* Now add fan read/write functions */
 
-static ssize_t show_fan(struct device *dev, char *buf, int nr)
+static ssize_t show_fan(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 adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr],
 		data->fan_div[nr]));
 }
-static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_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 adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr],
 		data->fan_div[nr]));
 }
-static ssize_t set_fan_min(struct device *dev, const char *buf,
-		size_t count, int nr)
+static ssize_t set_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);
+	int nr = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
 	int val = simple_strtol(buf, NULL, 10);
@@ -879,23 +879,11 @@
 	return count;
 }
 
-#define fan_offset(offset)                                                  \
-static ssize_t show_fan_##offset (struct device *dev, char *buf)            \
-{                                                                           \
-	return show_fan(dev, buf, offset - 1);                              \
-}                                                                           \
-static ssize_t show_fan_##offset##_min (struct device *dev, char *buf)      \
-{                                                                           \
-	return show_fan_min(dev, buf, offset - 1);                          \
-}                                                                           \
-static ssize_t set_fan_##offset##_min (struct device *dev,                  \
-	const char *buf, size_t count)                                      \
-{                                                                           \
-	return set_fan_min(dev, buf, count, offset - 1);                    \
-}                                                                           \
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL);  \
-static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,                    \
-		show_fan_##offset##_min, set_fan_##offset##_min);
+#define fan_offset(offset)                                         		\
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL, 	\
+		offset - 1);							\
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,           	\
+		show_fan_min, set_fan_min, offset - 1);
 
 fan_offset(1);
 fan_offset(2);
@@ -926,14 +914,19 @@
 }
 
 /* Now add fan_div read/write functions */
-static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
+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 adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%d\n", data->fan_div[nr]);
 }
-static ssize_t set_fan_div(struct device *dev, const char *buf,
-		size_t count, int nr)
+static ssize_t set_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);
+	int nr = sensor_attr->index;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
 	int    val,orig_div,new_div,shift;
@@ -967,17 +960,8 @@
 }
 
 #define fan_offset_div(offset)                                          \
-static ssize_t show_fan_##offset##_div (struct device *dev, char *buf)  \
-{                                                                       \
-	return show_fan_div(dev, buf, offset - 1);                      \
-}                                                                       \
-static ssize_t set_fan_##offset##_div (struct device *dev,              \
-	const char *buf, size_t count)                                  \
-{                                                                       \
-	return set_fan_div(dev, buf, count, offset - 1);                \
-}                                                                       \
-static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,                \
-		show_fan_##offset##_div, set_fan_##offset##_div);
+static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,         \
+		show_fan_div, set_fan_div, offset - 1);
 
 fan_offset_div(1);
 fan_offset_div(2);
@@ -989,19 +973,27 @@
 fan_offset_div(8);
 
 /* Temps */
-static ssize_t show_temp(struct device *dev, char *buf, int nr)
+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 adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp[nr]));
 }
-static ssize_t show_temp_min(struct device *dev, char *buf, int 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 adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_min[nr]));
 }
-static ssize_t set_temp_min(struct device *dev, const char *buf,
-		size_t count, int 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 adm1026_data *data = i2c_get_clientdata(client);
 	int val = simple_strtol(buf, NULL, 10);
@@ -1013,14 +1005,19 @@
 	up(&data->update_lock);
 	return count;
 }
-static ssize_t show_temp_max(struct device *dev, char *buf, int 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 adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_max[nr]));
 }
-static ssize_t set_temp_max(struct device *dev, const char *buf,
-		size_t count, int nr)
+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 adm1026_data *data = i2c_get_clientdata(client);
 	int val = simple_strtol(buf, NULL, 10);
@@ -1032,48 +1029,34 @@
 	up(&data->update_lock);
 	return count;
 }
-#define temp_reg(offset)                                                      \
-static ssize_t show_temp_##offset (struct device *dev, char *buf)             \
-{                                                                             \
-	return show_temp(dev, buf, offset - 1);                               \
-}                                                                             \
-static ssize_t show_temp_##offset##_min (struct device *dev, char *buf)       \
-{                                                                             \
-	return show_temp_min(dev, buf, offset - 1);                           \
-}                                                                             \
-static ssize_t show_temp_##offset##_max (struct device *dev, char *buf)       \
-{                                                                             \
-	return show_temp_max(dev, buf, offset - 1);                           \
-}                                                                             \
-static ssize_t set_temp_##offset##_min (struct device *dev,                   \
-	const char *buf, size_t count)                                        \
-{                                                                             \
-	return set_temp_min(dev, buf, count, offset - 1);                     \
-}                                                                             \
-static ssize_t set_temp_##offset##_max (struct device *dev,                   \
-	const char *buf, size_t count)                                        \
-{                                                                             \
-	return set_temp_max(dev, buf, count, offset - 1);                     \
-}                                                                             \
-static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL);  \
-static DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,                     \
-		show_temp_##offset##_min, set_temp_##offset##_min);           \
-static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,                     \
-		show_temp_##offset##_max, set_temp_##offset##_max);
+
+#define temp_reg(offset)						\
+static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp, 	\
+		NULL, offset - 1);					\
+static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,	\
+		show_temp_min, set_temp_min, offset - 1);		\
+static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,	\
+		show_temp_max, set_temp_max, offset - 1);
 
 
 temp_reg(1);
 temp_reg(2);
 temp_reg(3);
 
-static ssize_t show_temp_offset(struct device *dev, char *buf, int nr)
+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 adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_offset[nr]));
 }
-static ssize_t set_temp_offset(struct device *dev, const char *buf,
-		size_t count, int 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 adm1026_data *data = i2c_get_clientdata(client);
 	int val = simple_strtol(buf, NULL, 10);
@@ -1086,46 +1069,45 @@
 	return count;
 }
 
-#define temp_offset_reg(offset)                                             \
-static ssize_t show_temp_##offset##_offset (struct device *dev, char *buf)  \
-{                                                                           \
-	return show_temp_offset(dev, buf, offset - 1);                      \
-}                                                                           \
-static ssize_t set_temp_##offset##_offset (struct device *dev,              \
-	const char *buf, size_t count)                                      \
-{                                                                           \
-	return set_temp_offset(dev, buf, count, offset - 1);                \
-}                                                                           \
-static DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR,                \
-		show_temp_##offset##_offset, set_temp_##offset##_offset);
+#define temp_offset_reg(offset)							\
+static SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR,		\
+		show_temp_offset, set_temp_offset, offset - 1);
 
 temp_offset_reg(1);
 temp_offset_reg(2);
 temp_offset_reg(3);
 
-static ssize_t show_temp_auto_point1_temp_hyst(struct device *dev, char *buf,
-		int nr)
+static ssize_t show_temp_auto_point1_temp_hyst(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 adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%d\n", TEMP_FROM_REG(
 		ADM1026_FAN_ACTIVATION_TEMP_HYST + data->temp_tmin[nr]));
 }
-static ssize_t show_temp_auto_point2_temp(struct device *dev, char *buf,
-		int nr)
+static ssize_t show_temp_auto_point2_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 adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_tmin[nr] +
 		ADM1026_FAN_CONTROL_TEMP_RANGE));
 }
-static ssize_t show_temp_auto_point1_temp(struct device *dev, char *buf,
-		int nr)
+static ssize_t show_temp_auto_point1_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 adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_tmin[nr]));
 }
-static ssize_t set_temp_auto_point1_temp(struct device *dev, const char *buf,
-		size_t count, int nr)
+static ssize_t set_temp_auto_point1_temp(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 adm1026_data *data = i2c_get_clientdata(client);
 	int val = simple_strtol(buf, NULL, 10);
@@ -1138,46 +1120,27 @@
 	return count;
 }
 
-#define temp_auto_point(offset)                                             \
-static ssize_t show_temp##offset##_auto_point1_temp (struct device *dev,    \
-	char *buf)                                                          \
-{                                                                           \
-	return show_temp_auto_point1_temp(dev, buf, offset - 1);            \
-}                                                                           \
-static ssize_t set_temp##offset##_auto_point1_temp (struct device *dev,     \
-	const char *buf, size_t count)                                      \
-{                                                                           \
-	return set_temp_auto_point1_temp(dev, buf, count, offset - 1);      \
-}                                                                           \
-static ssize_t show_temp##offset##_auto_point1_temp_hyst (struct device     \
-	*dev, char *buf)                                                    \
-{                                                                           \
-	return show_temp_auto_point1_temp_hyst(dev, buf, offset - 1);       \
-}                                                                           \
-static ssize_t show_temp##offset##_auto_point2_temp (struct device *dev,    \
-	 char *buf)                                                         \
-{                                                                           \
-	return show_temp_auto_point2_temp(dev, buf, offset - 1);            \
-}                                                                           \
-static DEVICE_ATTR(temp##offset##_auto_point1_temp, S_IRUGO | S_IWUSR,      \
-		show_temp##offset##_auto_point1_temp,                       \
-		set_temp##offset##_auto_point1_temp);                       \
-static DEVICE_ATTR(temp##offset##_auto_point1_temp_hyst, S_IRUGO,           \
-		show_temp##offset##_auto_point1_temp_hyst, NULL);           \
-static DEVICE_ATTR(temp##offset##_auto_point2_temp, S_IRUGO,                \
-		show_temp##offset##_auto_point2_temp, NULL);
+#define temp_auto_point(offset)							\
+static SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp, S_IRUGO | S_IWUSR,	\
+		show_temp_auto_point1_temp, set_temp_auto_point1_temp, 		\
+		offset - 1);							\
+static SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp_hyst, S_IRUGO,	\
+		show_temp_auto_point1_temp_hyst, NULL, offset - 1);		\
+static SENSOR_DEVICE_ATTR(temp##offset##_auto_point2_temp, S_IRUGO,		\
+		show_temp_auto_point2_temp, NULL, offset - 1);
 
 temp_auto_point(1);
 temp_auto_point(2);
 temp_auto_point(3);
 
-static ssize_t show_temp_crit_enable(struct device *dev, char *buf)
+static ssize_t show_temp_crit_enable(struct device *dev,
+		struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%d\n", (data->config1 & CFG1_THERM_HOT) >> 4);
 }
-static ssize_t set_temp_crit_enable(struct device *dev, const char *buf,
-		size_t count)
+static ssize_t set_temp_crit_enable(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct adm1026_data *data = i2c_get_clientdata(client);
@@ -1193,24 +1156,27 @@
 	return count;
 }
 
-static DEVICE_ATTR(temp1_crit_enable, S_IRUGO | S_IWUSR, 
+#define temp_crit_enable(offset)				\
+static DEVICE_ATTR(temp##offset##_crit_enable, S_IRUGO | S_IWUSR, \
 	show_temp_crit_enable, set_temp_crit_enable);
 
-static DEVICE_ATTR(temp2_crit_enable, S_IRUGO | S_IWUSR, 
-	show_temp_crit_enable, set_temp_crit_enable);
+temp_crit_enable(1);
+temp_crit_enable(2);
+temp_crit_enable(3);
 
-static DEVICE_ATTR(temp3_crit_enable, S_IRUGO | S_IWUSR, 
-	show_temp_crit_enable, set_temp_crit_enable);
-
-
-static ssize_t show_temp_crit(struct device *dev, char *buf, int nr)
+static ssize_t show_temp_crit(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 adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%d\n", TEMP_FROM_REG(data->temp_crit[nr]));
 }
-static ssize_t set_temp_crit(struct device *dev, const char *buf,
-		size_t count, int nr)
+static ssize_t set_temp_crit(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 adm1026_data *data = i2c_get_clientdata(client);
 	int val = simple_strtol(buf, NULL, 10);
@@ -1223,29 +1189,20 @@
 	return count;
 }
 
-#define temp_crit_reg(offset)                                             \
-static ssize_t show_temp_##offset##_crit (struct device *dev, char *buf)  \
-{                                                                         \
-	return show_temp_crit(dev, buf, offset - 1);                      \
-}                                                                         \
-static ssize_t set_temp_##offset##_crit (struct device *dev,              \
-	const char *buf, size_t count)                                    \
-{                                                                         \
-	return set_temp_crit(dev, buf, count, offset - 1);                \
-}                                                                         \
-static DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR,                \
-		show_temp_##offset##_crit, set_temp_##offset##_crit);
+#define temp_crit_reg(offset)						\
+static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR,	\
+		show_temp_crit, set_temp_crit, offset - 1);
 
 temp_crit_reg(1);
 temp_crit_reg(2);
 temp_crit_reg(3);
 
-static ssize_t show_analog_out_reg(struct device *dev, char *buf)
+static ssize_t show_analog_out_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%d\n", DAC_FROM_REG(data->analog_out));
 }
-static ssize_t set_analog_out_reg(struct device *dev, const char *buf,
+static ssize_t set_analog_out_reg(struct device *dev, struct device_attribute *attr, const char *buf,
 		size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -1262,20 +1219,21 @@
 static DEVICE_ATTR(analog_out, S_IRUGO | S_IWUSR, show_analog_out_reg, 
 	set_analog_out_reg);
 
-static ssize_t show_vid_reg(struct device *dev, char *buf)
+static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%d\n", vid_from_reg(data->vid & 0x3f, data->vrm));
 }
-
+/* vid deprecated in favour of cpu0_vid, remove after 2005-11-11 */
 static DEVICE_ATTR(vid, S_IRUGO, show_vid_reg, NULL);
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
 
-static ssize_t show_vrm_reg(struct device *dev, char *buf)
+static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%d\n", data->vrm);
 }
-static ssize_t store_vrm_reg(struct device *dev, const char *buf,
+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);
@@ -1287,7 +1245,7 @@
 
 static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
 
-static ssize_t show_alarms_reg(struct device *dev, char *buf)
+static ssize_t show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf, "%ld\n", (long) (data->alarms));
@@ -1295,12 +1253,12 @@
 
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
 
-static ssize_t show_alarm_mask(struct device *dev, char *buf)
+static ssize_t show_alarm_mask(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%ld\n", data->alarm_mask);
 }
-static ssize_t set_alarm_mask(struct device *dev, const char *buf,
+static ssize_t set_alarm_mask(struct device *dev, struct device_attribute *attr, const char *buf,
 		size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -1331,12 +1289,12 @@
 	set_alarm_mask);
 
 
-static ssize_t show_gpio(struct device *dev, char *buf)
+static ssize_t show_gpio(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%ld\n", data->gpio);
 }
-static ssize_t set_gpio(struct device *dev, const char *buf,
+static ssize_t set_gpio(struct device *dev, struct device_attribute *attr, const char *buf,
 		size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -1359,12 +1317,12 @@
 static DEVICE_ATTR(gpio, S_IRUGO | S_IWUSR, show_gpio, set_gpio);
 
 
-static ssize_t show_gpio_mask(struct device *dev, char *buf)
+static ssize_t show_gpio_mask(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%ld\n", data->gpio_mask);
 }
-static ssize_t set_gpio_mask(struct device *dev, const char *buf,
+static ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr, const char *buf,
 		size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -1386,12 +1344,12 @@
 
 static DEVICE_ATTR(gpio_mask, S_IRUGO | S_IWUSR, show_gpio_mask, set_gpio_mask);
 
-static ssize_t show_pwm_reg(struct device *dev, char *buf)
+static ssize_t show_pwm_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%d\n", PWM_FROM_REG(data->pwm1.pwm));
 }
-static ssize_t set_pwm_reg(struct device *dev, const char *buf,
+static ssize_t set_pwm_reg(struct device *dev, struct device_attribute *attr, const char *buf,
 		size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -1407,12 +1365,12 @@
 	}
 	return count;
 }
-static ssize_t show_auto_pwm_min(struct device *dev, char *buf)
+static ssize_t show_auto_pwm_min(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%d\n", data->pwm1.auto_pwm_min);
 }
-static ssize_t set_auto_pwm_min(struct device *dev, const char *buf,
+static ssize_t set_auto_pwm_min(struct device *dev, struct device_attribute *attr, const char *buf,
 		size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -1429,16 +1387,16 @@
 	up(&data->update_lock);
 	return count;
 }
-static ssize_t show_auto_pwm_max(struct device *dev, char *buf)
+static ssize_t show_auto_pwm_max(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	return sprintf(buf,"%d\n", ADM1026_PWM_MAX);
 }
-static ssize_t show_pwm_enable(struct device *dev, char *buf)
+static ssize_t show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1026_data *data = adm1026_update_device(dev);
 	return sprintf(buf,"%d\n", data->pwm1.enable);
 }
-static ssize_t set_pwm_enable(struct device *dev, const char *buf,
+static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, const char *buf,
 		size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -1597,118 +1555,120 @@
 	adm1026_init_client(new_client);
 
 	/* Register sysfs hooks */
-	device_create_file(&new_client->dev, &dev_attr_in0_input);
-	device_create_file(&new_client->dev, &dev_attr_in0_max);
-	device_create_file(&new_client->dev, &dev_attr_in0_min);
-	device_create_file(&new_client->dev, &dev_attr_in1_input);
-	device_create_file(&new_client->dev, &dev_attr_in1_max);
-	device_create_file(&new_client->dev, &dev_attr_in1_min);
-	device_create_file(&new_client->dev, &dev_attr_in2_input);
-	device_create_file(&new_client->dev, &dev_attr_in2_max);
-	device_create_file(&new_client->dev, &dev_attr_in2_min);
-	device_create_file(&new_client->dev, &dev_attr_in3_input);
-	device_create_file(&new_client->dev, &dev_attr_in3_max);
-	device_create_file(&new_client->dev, &dev_attr_in3_min);
-	device_create_file(&new_client->dev, &dev_attr_in4_input);
-	device_create_file(&new_client->dev, &dev_attr_in4_max);
-	device_create_file(&new_client->dev, &dev_attr_in4_min);
-	device_create_file(&new_client->dev, &dev_attr_in5_input);
-	device_create_file(&new_client->dev, &dev_attr_in5_max);
-	device_create_file(&new_client->dev, &dev_attr_in5_min);
-	device_create_file(&new_client->dev, &dev_attr_in6_input);
-	device_create_file(&new_client->dev, &dev_attr_in6_max);
-	device_create_file(&new_client->dev, &dev_attr_in6_min);
-	device_create_file(&new_client->dev, &dev_attr_in7_input);
-	device_create_file(&new_client->dev, &dev_attr_in7_max);
-	device_create_file(&new_client->dev, &dev_attr_in7_min);
-	device_create_file(&new_client->dev, &dev_attr_in8_input);
-	device_create_file(&new_client->dev, &dev_attr_in8_max);
-	device_create_file(&new_client->dev, &dev_attr_in8_min);
-	device_create_file(&new_client->dev, &dev_attr_in9_input);
-	device_create_file(&new_client->dev, &dev_attr_in9_max);
-	device_create_file(&new_client->dev, &dev_attr_in9_min);
-	device_create_file(&new_client->dev, &dev_attr_in10_input);
-	device_create_file(&new_client->dev, &dev_attr_in10_max);
-	device_create_file(&new_client->dev, &dev_attr_in10_min);
-	device_create_file(&new_client->dev, &dev_attr_in11_input);
-	device_create_file(&new_client->dev, &dev_attr_in11_max);
-	device_create_file(&new_client->dev, &dev_attr_in11_min);
-	device_create_file(&new_client->dev, &dev_attr_in12_input);
-	device_create_file(&new_client->dev, &dev_attr_in12_max);
-	device_create_file(&new_client->dev, &dev_attr_in12_min);
-	device_create_file(&new_client->dev, &dev_attr_in13_input);
-	device_create_file(&new_client->dev, &dev_attr_in13_max);
-	device_create_file(&new_client->dev, &dev_attr_in13_min);
-	device_create_file(&new_client->dev, &dev_attr_in14_input);
-	device_create_file(&new_client->dev, &dev_attr_in14_max);
-	device_create_file(&new_client->dev, &dev_attr_in14_min);
-	device_create_file(&new_client->dev, &dev_attr_in15_input);
-	device_create_file(&new_client->dev, &dev_attr_in15_max);
-	device_create_file(&new_client->dev, &dev_attr_in15_min);
-	device_create_file(&new_client->dev, &dev_attr_in16_input);
-	device_create_file(&new_client->dev, &dev_attr_in16_max);
-	device_create_file(&new_client->dev, &dev_attr_in16_min);
-	device_create_file(&new_client->dev, &dev_attr_fan1_input);
-	device_create_file(&new_client->dev, &dev_attr_fan1_div);
-	device_create_file(&new_client->dev, &dev_attr_fan1_min);
-	device_create_file(&new_client->dev, &dev_attr_fan2_input);
-	device_create_file(&new_client->dev, &dev_attr_fan2_div);
-	device_create_file(&new_client->dev, &dev_attr_fan2_min);
-	device_create_file(&new_client->dev, &dev_attr_fan3_input);
-	device_create_file(&new_client->dev, &dev_attr_fan3_div);
-	device_create_file(&new_client->dev, &dev_attr_fan3_min);
-	device_create_file(&new_client->dev, &dev_attr_fan4_input);
-	device_create_file(&new_client->dev, &dev_attr_fan4_div);
-	device_create_file(&new_client->dev, &dev_attr_fan4_min);
-	device_create_file(&new_client->dev, &dev_attr_fan5_input);
-	device_create_file(&new_client->dev, &dev_attr_fan5_div);
-	device_create_file(&new_client->dev, &dev_attr_fan5_min);
-	device_create_file(&new_client->dev, &dev_attr_fan6_input);
-	device_create_file(&new_client->dev, &dev_attr_fan6_div);
-	device_create_file(&new_client->dev, &dev_attr_fan6_min);
-	device_create_file(&new_client->dev, &dev_attr_fan7_input);
-	device_create_file(&new_client->dev, &dev_attr_fan7_div);
-	device_create_file(&new_client->dev, &dev_attr_fan7_min);
-	device_create_file(&new_client->dev, &dev_attr_fan8_input);
-	device_create_file(&new_client->dev, &dev_attr_fan8_div);
-	device_create_file(&new_client->dev, &dev_attr_fan8_min);
-	device_create_file(&new_client->dev, &dev_attr_temp1_input);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max);
-	device_create_file(&new_client->dev, &dev_attr_temp1_min);
-	device_create_file(&new_client->dev, &dev_attr_temp2_input);
-	device_create_file(&new_client->dev, &dev_attr_temp2_max);
-	device_create_file(&new_client->dev, &dev_attr_temp2_min);
-	device_create_file(&new_client->dev, &dev_attr_temp3_input);
-	device_create_file(&new_client->dev, &dev_attr_temp3_max);
-	device_create_file(&new_client->dev, &dev_attr_temp3_min);
-	device_create_file(&new_client->dev, &dev_attr_temp1_offset);
-	device_create_file(&new_client->dev, &dev_attr_temp2_offset);
-	device_create_file(&new_client->dev, &dev_attr_temp3_offset);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in1_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in1_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in2_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in2_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in3_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in3_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in3_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in4_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in4_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in5_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in5_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in5_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in6_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in6_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in6_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in7_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in7_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in7_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in8_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in8_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in8_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in9_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in9_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in9_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in10_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in10_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in10_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in11_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in11_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in11_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in12_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in12_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in12_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in13_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in13_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in13_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in14_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in14_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in14_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in15_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in15_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in15_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in16_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in16_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in16_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan1_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan1_div.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan1_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan2_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan2_div.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan2_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan3_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan3_div.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan3_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan4_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan4_div.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan4_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan5_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan5_div.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan5_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan6_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan6_div.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan6_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan7_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan7_div.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan7_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan8_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan8_div.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan8_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_temp1_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_temp1_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_temp2_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_temp2_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_temp3_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_temp1_offset.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_temp2_offset.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_temp3_offset.dev_attr);
 	device_create_file(&new_client->dev, 
-		&dev_attr_temp1_auto_point1_temp);
+		&sensor_dev_attr_temp1_auto_point1_temp.dev_attr);
 	device_create_file(&new_client->dev, 
-		&dev_attr_temp2_auto_point1_temp);
+		&sensor_dev_attr_temp2_auto_point1_temp.dev_attr);
 	device_create_file(&new_client->dev, 
-		&dev_attr_temp3_auto_point1_temp);
+		&sensor_dev_attr_temp3_auto_point1_temp.dev_attr);
 	device_create_file(&new_client->dev,
-		&dev_attr_temp1_auto_point1_temp_hyst);
+		&sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr);
 	device_create_file(&new_client->dev,
-		&dev_attr_temp2_auto_point1_temp_hyst);
+		&sensor_dev_attr_temp2_auto_point1_temp_hyst.dev_attr);
 	device_create_file(&new_client->dev,
-		&dev_attr_temp3_auto_point1_temp_hyst);
+		&sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr);
 	device_create_file(&new_client->dev, 
-		&dev_attr_temp1_auto_point2_temp);
+		&sensor_dev_attr_temp1_auto_point2_temp.dev_attr);
 	device_create_file(&new_client->dev, 
-		&dev_attr_temp2_auto_point2_temp);
+		&sensor_dev_attr_temp2_auto_point2_temp.dev_attr);
 	device_create_file(&new_client->dev, 
-		&dev_attr_temp3_auto_point2_temp);
-	device_create_file(&new_client->dev, &dev_attr_temp1_crit);
-	device_create_file(&new_client->dev, &dev_attr_temp2_crit);
-	device_create_file(&new_client->dev, &dev_attr_temp3_crit);
+		&sensor_dev_attr_temp3_auto_point2_temp.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, &dev_attr_temp1_crit_enable);
 	device_create_file(&new_client->dev, &dev_attr_temp2_crit_enable);
 	device_create_file(&new_client->dev, &dev_attr_temp3_crit_enable);
+	/* vid deprecated in favour of cpu0_vid, remove after 2005-11-11 */
 	device_create_file(&new_client->dev, &dev_attr_vid);
+	device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
 	device_create_file(&new_client->dev, &dev_attr_vrm);
 	device_create_file(&new_client->dev, &dev_attr_alarms);
 	device_create_file(&new_client->dev, &dev_attr_alarm_mask);
diff --git a/drivers/i2c/chips/adm1031.c b/drivers/i2c/chips/adm1031.c
index d4385a2..9168e98 100644
--- a/drivers/i2c/chips/adm1031.c
+++ b/drivers/i2c/chips/adm1031.c
@@ -292,11 +292,11 @@
 }
 
 #define fan_auto_channel_offset(offset)						\
-static ssize_t show_fan_auto_channel_##offset (struct device *dev, char *buf)	\
+static ssize_t show_fan_auto_channel_##offset (struct device *dev, struct device_attribute *attr, char *buf)	\
 {										\
 	return show_fan_auto_channel(dev, buf, offset - 1);			\
 }										\
-static ssize_t set_fan_auto_channel_##offset (struct device *dev,		\
+static ssize_t set_fan_auto_channel_##offset (struct device *dev, struct device_attribute *attr,		\
 	const char *buf, size_t count)						\
 {										\
 	return set_fan_auto_channel(dev, buf, count, offset - 1);		\
@@ -357,24 +357,24 @@
 }
 
 #define auto_temp_reg(offset)							\
-static ssize_t show_auto_temp_##offset##_off (struct device *dev, char *buf)	\
+static ssize_t show_auto_temp_##offset##_off (struct device *dev, struct device_attribute *attr, char *buf)	\
 {										\
 	return show_auto_temp_off(dev, buf, offset - 1);			\
 }										\
-static ssize_t show_auto_temp_##offset##_min (struct device *dev, char *buf)	\
+static ssize_t show_auto_temp_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)	\
 {										\
 	return show_auto_temp_min(dev, buf, offset - 1);			\
 }										\
-static ssize_t show_auto_temp_##offset##_max (struct device *dev, char *buf)	\
+static ssize_t show_auto_temp_##offset##_max (struct device *dev, struct device_attribute *attr, char *buf)	\
 {										\
 	return show_auto_temp_max(dev, buf, offset - 1);			\
 }										\
-static ssize_t set_auto_temp_##offset##_min (struct device *dev,		\
+static ssize_t set_auto_temp_##offset##_min (struct device *dev, struct device_attribute *attr,		\
 					     const char *buf, size_t count)	\
 {										\
 	return set_auto_temp_min(dev, buf, count, offset - 1);		\
 }										\
-static ssize_t set_auto_temp_##offset##_max (struct device *dev,		\
+static ssize_t set_auto_temp_##offset##_max (struct device *dev, struct device_attribute *attr,		\
 					     const char *buf, size_t count)	\
 {										\
 	return set_auto_temp_max(dev, buf, count, offset - 1);		\
@@ -421,11 +421,11 @@
 }
 
 #define pwm_reg(offset)							\
-static ssize_t show_pwm_##offset (struct device *dev, char *buf)	\
+static ssize_t show_pwm_##offset (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return show_pwm(dev, buf, offset - 1);			\
 }									\
-static ssize_t set_pwm_##offset (struct device *dev,			\
+static ssize_t set_pwm_##offset (struct device *dev, struct device_attribute *attr,			\
 				 const char *buf, size_t count)		\
 {									\
 	return set_pwm(dev, buf, count, offset - 1);		\
@@ -440,7 +440,7 @@
 
 /*
  * That function checks the cases where the fan reading is not
- * relevent.  It is used to provide 0 as fan reading when the fan is
+ * relevant.  It is used to provide 0 as fan reading when the fan is
  * not supposed to run
  */
 static int trust_fan_readings(struct adm1031_data *data, int chan)
@@ -557,24 +557,24 @@
 }
 
 #define fan_offset(offset)						\
-static ssize_t show_fan_##offset (struct device *dev, char *buf)	\
+static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return show_fan(dev, buf, offset - 1);			\
 }									\
-static ssize_t show_fan_##offset##_min (struct device *dev, char *buf)	\
+static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return show_fan_min(dev, buf, offset - 1);			\
 }									\
-static ssize_t show_fan_##offset##_div (struct device *dev, char *buf)	\
+static ssize_t show_fan_##offset##_div (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return show_fan_div(dev, buf, offset - 1);			\
 }									\
-static ssize_t set_fan_##offset##_min (struct device *dev,		\
+static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr,		\
 	const char *buf, size_t count)					\
 {									\
 	return set_fan_min(dev, buf, count, offset - 1);		\
 }									\
-static ssize_t set_fan_##offset##_div (struct device *dev,		\
+static ssize_t set_fan_##offset##_div (struct device *dev, struct device_attribute *attr,		\
 	const char *buf, size_t count)					\
 {									\
 	return set_fan_div(dev, buf, count, offset - 1);		\
@@ -667,33 +667,33 @@
 }
 
 #define temp_reg(offset)							\
-static ssize_t show_temp_##offset (struct device *dev, char *buf)		\
+static ssize_t show_temp_##offset (struct device *dev, struct device_attribute *attr, char *buf)		\
 {										\
 	return show_temp(dev, buf, offset - 1);				\
 }										\
-static ssize_t show_temp_##offset##_min (struct device *dev, char *buf)		\
+static ssize_t show_temp_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)		\
 {										\
 	return show_temp_min(dev, buf, offset - 1);				\
 }										\
-static ssize_t show_temp_##offset##_max (struct device *dev, char *buf)		\
+static ssize_t show_temp_##offset##_max (struct device *dev, struct device_attribute *attr, char *buf)		\
 {										\
 	return show_temp_max(dev, buf, offset - 1);				\
 }										\
-static ssize_t show_temp_##offset##_crit (struct device *dev, char *buf)	\
+static ssize_t show_temp_##offset##_crit (struct device *dev, struct device_attribute *attr, char *buf)	\
 {										\
 	return show_temp_crit(dev, buf, offset - 1);			\
 }										\
-static ssize_t set_temp_##offset##_min (struct device *dev,			\
+static ssize_t set_temp_##offset##_min (struct device *dev, struct device_attribute *attr,			\
 					const char *buf, size_t count)		\
 {										\
 	return set_temp_min(dev, buf, count, offset - 1);			\
 }										\
-static ssize_t set_temp_##offset##_max (struct device *dev,			\
+static ssize_t set_temp_##offset##_max (struct device *dev, struct device_attribute *attr,			\
 					const char *buf, size_t count)		\
 {										\
 	return set_temp_max(dev, buf, count, offset - 1);			\
 }										\
-static ssize_t set_temp_##offset##_crit (struct device *dev,			\
+static ssize_t set_temp_##offset##_crit (struct device *dev, struct device_attribute *attr,			\
 					 const char *buf, size_t count)		\
 {										\
 	return set_temp_crit(dev, buf, count, offset - 1);			\
@@ -712,7 +712,7 @@
 temp_reg(3);
 
 /* Alarms */
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct adm1031_data *data = adm1031_update_device(dev);
 	return sprintf(buf, "%d\n", data->alarm);
diff --git a/drivers/i2c/chips/adm9240.c b/drivers/i2c/chips/adm9240.c
new file mode 100644
index 0000000..5c68e9c
--- /dev/null
+++ b/drivers/i2c/chips/adm9240.c
@@ -0,0 +1,791 @@
+/*
+ * adm9240.c	Part of lm_sensors, Linux kernel modules for hardware
+ * 		monitoring
+ *
+ * Copyright (C) 1999	Frodo Looijaard <frodol@dds.nl>
+ *			Philip Edelbrock <phil@netroedge.com>
+ * Copyright (C) 2003	Michiel Rook <michiel@grendelproject.nl>
+ * Copyright (C) 2005	Grant Coady <gcoady@gmail.com> with valuable
+ * 				guidance from Jean Delvare
+ *
+ * Driver supports	Analog Devices		ADM9240
+ *			Dallas Semiconductor	DS1780
+ *			National Semiconductor	LM81
+ *
+ * ADM9240 is the reference, DS1780 and LM81 are register compatibles
+ *
+ * Voltage	Six inputs are scaled by chip, VID also reported
+ * Temperature	Chip temperature to 0.5'C, maximum and max_hysteris
+ * Fans		2 fans, low speed alarm, automatic fan clock divider
+ * Alarms	16-bit map of active alarms
+ * Analog Out	0..1250 mV output
+ *
+ * Chassis Intrusion: clear CI latch with 'echo 1 > chassis_clear'
+ *
+ * Test hardware: Intel SE440BX-2 desktop motherboard --Grant
+ *
+ * LM81 extended temp reading not implemented
+ *
+ * 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/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/i2c-vid.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
+					I2C_CLIENT_END };
+
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_3(adm9240, ds1780, lm81);
+
+/* ADM9240 registers */
+#define ADM9240_REG_MAN_ID		0x3e
+#define ADM9240_REG_DIE_REV		0x3f
+#define ADM9240_REG_CONFIG		0x40
+
+#define ADM9240_REG_IN(nr)		(0x20 + (nr))   /* 0..5 */
+#define ADM9240_REG_IN_MAX(nr)		(0x2b + (nr) * 2)
+#define ADM9240_REG_IN_MIN(nr)		(0x2c + (nr) * 2)
+#define ADM9240_REG_FAN(nr)		(0x28 + (nr))   /* 0..1 */
+#define ADM9240_REG_FAN_MIN(nr)		(0x3b + (nr))
+#define ADM9240_REG_INT(nr)		(0x41 + (nr))
+#define ADM9240_REG_INT_MASK(nr)	(0x43 + (nr))
+#define ADM9240_REG_TEMP		0x27
+#define ADM9240_REG_TEMP_HIGH		0x39
+#define ADM9240_REG_TEMP_HYST		0x3a
+#define ADM9240_REG_ANALOG_OUT		0x19
+#define ADM9240_REG_CHASSIS_CLEAR	0x46
+#define ADM9240_REG_VID_FAN_DIV		0x47
+#define ADM9240_REG_I2C_ADDR		0x48
+#define ADM9240_REG_VID4		0x49
+#define ADM9240_REG_TEMP_CONF		0x4b
+
+/* 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;
+}
+
+/* adm9240 internally scales voltage measurements */
+static const u16 nom_mv[] = { 2500, 2700, 3300, 5000, 12000, 2700 };
+
+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);
+}
+
+/* temperature range: -40..125, 127 disables temperature alarm */
+static inline s8 TEMP_TO_REG(long val)
+{
+	return SENSORS_LIMIT(SCALE(val, 1, 1000), -40, 127);
+}
+
+/* two fans, each with low fan speed limit */
+static inline unsigned int FAN_FROM_REG(u8 reg, u8 div)
+{
+	if (!reg) /* error */
+		return -1;
+
+	if (reg == 255)
+		return 0;
+
+	return SCALE(1350000, 1, reg * div);
+}
+
+/* analog out 0..1250mV */
+static inline u8 AOUT_TO_REG(unsigned long val)
+{
+	return SENSORS_LIMIT(SCALE(val, 255, 1250), 0, 255);
+}
+
+static inline unsigned int AOUT_FROM_REG(u8 reg)
+{
+	return SCALE(reg, 1250, 255);
+}
+
+static int adm9240_attach_adapter(struct i2c_adapter *adapter);
+static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind);
+static void adm9240_init_client(struct i2c_client *client);
+static int adm9240_detach_client(struct i2c_client *client);
+static struct adm9240_data *adm9240_update_device(struct device *dev);
+
+/* driver data */
+static struct i2c_driver adm9240_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "adm9240",
+	.id		= I2C_DRIVERID_ADM9240,
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter	= adm9240_attach_adapter,
+	.detach_client	= adm9240_detach_client,
+};
+
+/* per client data */
+struct adm9240_data {
+	enum chips type;
+	struct i2c_client client;
+	struct semaphore update_lock;
+	char valid;
+	unsigned long last_updated_measure;
+	unsigned long last_updated_config;
+
+	u8 in[6];		/* ro	in0_input */
+	u8 in_max[6];		/* rw	in0_max */
+	u8 in_min[6];		/* rw	in0_min */
+	u8 fan[2];		/* ro	fan1_input */
+	u8 fan_min[2];		/* rw	fan1_min */
+	u8 fan_div[2];		/* rw	fan1_div, read-only accessor */
+	s16 temp;		/* ro	temp1_input, 9-bit sign-extended */
+	s8 temp_high;		/* rw	temp1_max */
+	s8 temp_hyst;		/* rw	temp1_max_hyst */
+	u16 alarms;		/* ro	alarms */
+	u8 aout;		/* rw	aout_output */
+	u8 vid;			/* ro	vid */
+	u8 vrm;			/* --	vrm set on startup, no accessor */
+};
+
+/* i2c byte read/write interface */
+static int adm9240_read_value(struct i2c_client *client, u8 reg)
+{
+	return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int adm9240_write_value(struct i2c_client *client, u8 reg, u8 value)
+{
+	return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+/*** sysfs accessors ***/
+
+/* temperature */
+#define show_temp(value, scale)					\
+static ssize_t show_##value(struct device *dev,			\
+			    struct device_attribute *attr,	\
+			    char *buf)				\
+{								\
+	struct adm9240_data *data = adm9240_update_device(dev);	\
+	return sprintf(buf, "%d\n", data->value * scale);	\
+}
+show_temp(temp_high, 1000);
+show_temp(temp_hyst, 1000);
+show_temp(temp, 500); /* 0.5'C per bit */
+
+#define set_temp(value, reg)					\
+static ssize_t set_##value(struct device *dev, 			\
+			   struct device_attribute *attr,	\
+			   const char *buf, size_t count)	\
+{								\
+	struct i2c_client *client = to_i2c_client(dev);		\
+	struct adm9240_data *data = adm9240_update_device(dev);	\
+	long temp = simple_strtoul(buf, NULL, 10);		\
+								\
+	down(&data->update_lock);				\
+	data->value = TEMP_TO_REG(temp);			\
+	adm9240_write_value(client, reg, data->value);		\
+	up(&data->update_lock);					\
+	return count;						\
+}
+
+set_temp(temp_high, ADM9240_REG_TEMP_HIGH);
+set_temp(temp_hyst, ADM9240_REG_TEMP_HYST);
+
+static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
+		show_temp_high, set_temp_high);
+static DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
+		show_temp_hyst, set_temp_hyst);
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
+
+/* voltage */
+static ssize_t show_in(struct device *dev, char *buf, int nr)
+{
+	struct adm9240_data *data = adm9240_update_device(dev);
+	return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr], nr));
+}
+
+static ssize_t show_in_min(struct device *dev, char *buf, int nr)
+{
+	struct adm9240_data *data = adm9240_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, char *buf, int nr)
+{
+	struct adm9240_data *data = adm9240_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, const char *buf,
+		size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct adm9240_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);
+	adm9240_write_value(client, ADM9240_REG_IN_MIN(nr), data->in_min[nr]);
+	up(&data->update_lock);
+	return count;
+}
+
+static ssize_t set_in_max(struct device *dev, const char *buf,
+		size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct adm9240_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);
+	adm9240_write_value(client, ADM9240_REG_IN_MAX(nr), data->in_max[nr]);
+	up(&data->update_lock);
+	return count;
+}
+
+#define show_in_offset(offset)						\
+static ssize_t show_in##offset(struct device *dev,			\
+			       struct device_attribute *attr,		\
+			       char *buf)				\
+{									\
+	return show_in(dev, buf, offset);				\
+}									\
+static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL);	\
+static ssize_t show_in##offset##_min(struct device *dev,		\
+				     struct device_attribute *attr,	\
+				     char *buf)				\
+{									\
+	return show_in_min(dev, buf, offset);				\
+}									\
+static ssize_t show_in##offset##_max(struct device *dev,		\
+				     struct device_attribute *attr,	\
+				     char *buf)				\
+{									\
+	return show_in_max(dev, buf, offset);				\
+}									\
+static ssize_t								\
+set_in##offset##_min(struct device *dev,				\
+		     struct device_attribute *attr, const char *buf,	\
+		     size_t count)					\
+{									\
+	return set_in_min(dev, buf, count, offset);			\
+}									\
+static ssize_t								\
+set_in##offset##_max(struct device *dev,				\
+		     struct device_attribute *attr, const char *buf,	\
+		     size_t count)					\
+{									\
+	return set_in_max(dev, buf, count, offset);			\
+}									\
+static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR,			\
+		show_in##offset##_min, set_in##offset##_min);		\
+static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,			\
+		show_in##offset##_max, set_in##offset##_max);
+
+show_in_offset(0);
+show_in_offset(1);
+show_in_offset(2);
+show_in_offset(3);
+show_in_offset(4);
+show_in_offset(5);
+
+/* fans */
+static ssize_t show_fan(struct device *dev, char *buf, int nr)
+{
+	struct adm9240_data *data = adm9240_update_device(dev);
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
+				1 << data->fan_div[nr]));
+}
+
+static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
+{
+	struct adm9240_data *data = adm9240_update_device(dev);
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
+				1 << data->fan_div[nr]));
+}
+
+static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
+{
+	struct adm9240_data *data = adm9240_update_device(dev);
+	return sprintf(buf, "%d\n", 1 << data->fan_div[nr]);
+}
+
+/* write new fan div, callers must hold data->update_lock */
+static void adm9240_write_fan_div(struct i2c_client *client, int nr,
+		u8 fan_div)
+{
+	u8 reg, old, shift = (nr + 2) * 2;
+
+	reg = adm9240_read_value(client, ADM9240_REG_VID_FAN_DIV);
+	old = (reg >> shift) & 3;
+	reg &= ~(3 << shift);
+	reg |= (fan_div << shift);
+	adm9240_write_value(client, ADM9240_REG_VID_FAN_DIV, reg);
+	dev_dbg(&client->dev, "fan%d clock divider changed from %u "
+			"to %u\n", nr + 1, 1 << old, 1 << fan_div);
+}
+
+/* 
+ * set fan speed low limit:
+ *
+ * - value is zero: disable fan speed low limit alarm
+ *
+ * - value is below fan speed measurement range: enable fan speed low
+ *   limit alarm to be asserted while fan speed too slow to measure
+ *
+ * - otherwise: select fan clock divider to suit fan speed low limit,
+ *   measurement code may adjust registers to ensure fan speed reading
+ */
+static ssize_t set_fan_min(struct device *dev, const char *buf,
+		size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct adm9240_data *data = i2c_get_clientdata(client);
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+	u8 new_div;
+
+	down(&data->update_lock);
+
+	if (!val) {
+		data->fan_min[nr] = 255;
+		new_div = data->fan_div[nr];
+
+		dev_dbg(&client->dev, "fan%u low limit set disabled\n",
+				nr + 1);
+
+	} else if (val < 1350000 / (8 * 254)) {
+		new_div = 3;
+		data->fan_min[nr] = 254;
+
+		dev_dbg(&client->dev, "fan%u low limit set minimum %u\n",
+				nr + 1, FAN_FROM_REG(254, 1 << new_div));
+
+	} else {
+		unsigned int new_min = 1350000 / val;
+
+		new_div = 0;
+		while (new_min > 192 && new_div < 3) {
+			new_div++;
+			new_min /= 2;
+		}
+		if (!new_min) /* keep > 0 */
+			new_min++;
+
+		data->fan_min[nr] = new_min;
+
+		dev_dbg(&client->dev, "fan%u low limit set fan speed %u\n",
+				nr + 1, FAN_FROM_REG(new_min, 1 << new_div));
+	}
+
+	if (new_div != data->fan_div[nr]) {
+		data->fan_div[nr] = new_div;
+		adm9240_write_fan_div(client, nr, new_div);
+	}
+	adm9240_write_value(client, ADM9240_REG_FAN_MIN(nr),
+			data->fan_min[nr]);
+
+	up(&data->update_lock);
+	return count;
+}
+
+#define show_fan_offset(offset)						\
+static ssize_t show_fan_##offset (struct device *dev,			\
+				  struct device_attribute *attr,	\
+				  char *buf)				\
+{									\
+return show_fan(dev, buf, offset - 1);					\
+}									\
+static ssize_t show_fan_##offset##_div (struct device *dev,		\
+					struct device_attribute *attr,	\
+					char *buf)			\
+{									\
+return show_fan_div(dev, buf, offset - 1);				\
+}									\
+static ssize_t show_fan_##offset##_min (struct device *dev,		\
+					struct device_attribute *attr,	\
+					char *buf)			\
+{									\
+return show_fan_min(dev, buf, offset - 1);				\
+}									\
+static ssize_t set_fan_##offset##_min (struct device *dev, 		\
+				       struct device_attribute *attr,	\
+				       const char *buf, size_t count)	\
+{									\
+return set_fan_min(dev, buf, count, offset - 1);			\
+}									\
+static DEVICE_ATTR(fan##offset##_input, S_IRUGO, 			\
+		show_fan_##offset, NULL);				\
+static DEVICE_ATTR(fan##offset##_div, S_IRUGO, 				\
+		show_fan_##offset##_div, NULL);				\
+static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, 		\
+		show_fan_##offset##_min, set_fan_##offset##_min);
+
+show_fan_offset(1);
+show_fan_offset(2);
+
+/* alarms */
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct adm9240_data *data = adm9240_update_device(dev);
+	return sprintf(buf, "%u\n", data->alarms);
+}
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+
+/* vid */
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct adm9240_data *data = adm9240_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);
+
+/* analog output */
+static ssize_t show_aout(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct adm9240_data *data = adm9240_update_device(dev);
+	return sprintf(buf, "%d\n", AOUT_FROM_REG(data->aout));
+}
+
+static ssize_t set_aout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct adm9240_data *data = i2c_get_clientdata(client);
+	unsigned long val = simple_strtol(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->aout = AOUT_TO_REG(val);
+	adm9240_write_value(client, ADM9240_REG_ANALOG_OUT, data->aout);
+	up(&data->update_lock);
+	return count;
+}
+static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout);
+
+/* chassis_clear */
+static ssize_t chassis_clear(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	unsigned long val = simple_strtol(buf, NULL, 10);
+
+	if (val == 1) {
+		adm9240_write_value(client, ADM9240_REG_CHASSIS_CLEAR, 0x80);
+		dev_dbg(&client->dev, "chassis intrusion latch cleared\n");
+	}
+	return count;
+}
+static DEVICE_ATTR(chassis_clear, S_IWUSR, NULL, chassis_clear);
+
+
+/*** sensor chip detect and driver install ***/
+
+static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *new_client;
+	struct adm9240_data *data;
+	int err = 0;
+	const char *name = "";
+	u8 man_id, die_rev;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		goto exit;
+
+	if (!(data = kmalloc(sizeof(struct adm9240_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit;
+	}
+	memset(data, 0, sizeof(struct adm9240_data));
+
+	new_client = &data->client;
+	i2c_set_clientdata(new_client, data);
+	new_client->addr = address;
+	new_client->adapter = adapter;
+	new_client->driver = &adm9240_driver;
+	new_client->flags = 0;
+
+	if (kind == 0) {
+		kind = adm9240;
+	}
+
+	if (kind < 0) {
+
+		/* verify chip: reg address should match i2c address */
+		if (adm9240_read_value(new_client, ADM9240_REG_I2C_ADDR)
+				!= address) {
+			dev_err(&adapter->dev, "detect fail: address match, "
+					"0x%02x\n", address);
+			goto exit_free;
+		}
+
+		/* check known chip manufacturer */
+		man_id = adm9240_read_value(new_client, ADM9240_REG_MAN_ID);
+
+		if (man_id == 0x23) {
+			kind = adm9240;
+		} else if (man_id == 0xda) {
+			kind = ds1780;
+		} else if (man_id == 0x01) {
+			kind = lm81;
+		} else {
+			dev_err(&adapter->dev, "detect fail: unknown manuf, "
+					"0x%02x\n", man_id);
+			goto exit_free;
+		}
+
+		/* successful detect, print chip info */
+		die_rev = adm9240_read_value(new_client, ADM9240_REG_DIE_REV);
+		dev_info(&adapter->dev, "found %s revision %u\n",
+				man_id == 0x23 ? "ADM9240" :
+				man_id == 0xda ? "DS1780" : "LM81", die_rev);
+	}
+
+	/* either forced or detected chip kind */
+	if (kind == adm9240) {
+		name = "adm9240";
+	} else if (kind == ds1780) {
+		name = "ds1780";
+	} else if (kind == lm81) {
+		name = "lm81";
+	}
+
+	/* fill in the remaining client fields and attach */
+	strlcpy(new_client->name, name, I2C_NAME_SIZE);
+	data->type = kind;
+	init_MUTEX(&data->update_lock);
+
+	if ((err = i2c_attach_client(new_client)))
+		goto exit_free;
+
+	adm9240_init_client(new_client);
+
+	/* populate sysfs filesystem */
+	device_create_file(&new_client->dev, &dev_attr_in0_input);
+	device_create_file(&new_client->dev, &dev_attr_in0_min);
+	device_create_file(&new_client->dev, &dev_attr_in0_max);
+	device_create_file(&new_client->dev, &dev_attr_in1_input);
+	device_create_file(&new_client->dev, &dev_attr_in1_min);
+	device_create_file(&new_client->dev, &dev_attr_in1_max);
+	device_create_file(&new_client->dev, &dev_attr_in2_input);
+	device_create_file(&new_client->dev, &dev_attr_in2_min);
+	device_create_file(&new_client->dev, &dev_attr_in2_max);
+	device_create_file(&new_client->dev, &dev_attr_in3_input);
+	device_create_file(&new_client->dev, &dev_attr_in3_min);
+	device_create_file(&new_client->dev, &dev_attr_in3_max);
+	device_create_file(&new_client->dev, &dev_attr_in4_input);
+	device_create_file(&new_client->dev, &dev_attr_in4_min);
+	device_create_file(&new_client->dev, &dev_attr_in4_max);
+	device_create_file(&new_client->dev, &dev_attr_in5_input);
+	device_create_file(&new_client->dev, &dev_attr_in5_min);
+	device_create_file(&new_client->dev, &dev_attr_in5_max);
+	device_create_file(&new_client->dev, &dev_attr_temp1_max);
+	device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
+	device_create_file(&new_client->dev, &dev_attr_temp1_input);
+	device_create_file(&new_client->dev, &dev_attr_fan1_input);
+	device_create_file(&new_client->dev, &dev_attr_fan1_div);
+	device_create_file(&new_client->dev, &dev_attr_fan1_min);
+	device_create_file(&new_client->dev, &dev_attr_fan2_input);
+	device_create_file(&new_client->dev, &dev_attr_fan2_div);
+	device_create_file(&new_client->dev, &dev_attr_fan2_min);
+	device_create_file(&new_client->dev, &dev_attr_alarms);
+	device_create_file(&new_client->dev, &dev_attr_aout_output);
+	device_create_file(&new_client->dev, &dev_attr_chassis_clear);
+	device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
+
+	return 0;
+exit_free:
+	kfree(new_client);
+exit:
+	return err;
+}
+
+static int adm9240_attach_adapter(struct i2c_adapter *adapter)
+{
+	if (!(adapter->class & I2C_CLASS_HWMON))
+		return 0;
+	return i2c_detect(adapter, &addr_data, adm9240_detect);
+}
+
+static int adm9240_detach_client(struct i2c_client *client)
+{
+	int err;
+
+	if ((err = i2c_detach_client(client))) {
+		dev_err(&client->dev, "Client deregistration failed, "
+				"client not detached.\n");
+		return err;
+	}
+
+	kfree(i2c_get_clientdata(client));
+	return 0;
+}
+
+static void adm9240_init_client(struct i2c_client *client)
+{
+	struct adm9240_data *data = i2c_get_clientdata(client);
+	u8 conf = adm9240_read_value(client, ADM9240_REG_CONFIG);
+	u8 mode = adm9240_read_value(client, ADM9240_REG_TEMP_CONF) & 3;
+
+	data->vrm = i2c_which_vrm(); /* need this to report vid as mV */
+
+	dev_info(&client->dev, "Using VRM: %d.%d\n", data->vrm / 10,
+			data->vrm % 10);
+
+	if (conf & 1) { /* measurement cycle running: report state */
+
+		dev_info(&client->dev, "status: config 0x%02x mode %u\n",
+				conf, mode);
+
+	} else { /* cold start: open limits before starting chip */
+		int i;
+
+		for (i = 0; i < 6; i++)
+		{
+			adm9240_write_value(client,
+					ADM9240_REG_IN_MIN(i), 0);
+			adm9240_write_value(client,
+					ADM9240_REG_IN_MAX(i), 255);
+		}
+		adm9240_write_value(client, ADM9240_REG_FAN_MIN(0), 255);
+		adm9240_write_value(client, ADM9240_REG_FAN_MIN(1), 255);
+		adm9240_write_value(client, ADM9240_REG_TEMP_HIGH, 127);
+		adm9240_write_value(client, ADM9240_REG_TEMP_HYST, 127);
+
+		/* start measurement cycle */
+		adm9240_write_value(client, ADM9240_REG_CONFIG, 1);
+
+		dev_info(&client->dev, "cold start: config was 0x%02x "
+				"mode %u\n", conf, mode);
+	}
+}
+
+static struct adm9240_data *adm9240_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct adm9240_data *data = i2c_get_clientdata(client);
+	int i;
+
+	down(&data->update_lock);
+
+	/* minimum measurement cycle: 1.75 seconds */
+	if (time_after(jiffies, data->last_updated_measure + (HZ * 7 / 4))
+			|| !data->valid) {
+
+		for (i = 0; i < 6; i++) /* read voltages */
+		{
+			data->in[i] = adm9240_read_value(client,
+					ADM9240_REG_IN(i));
+		}
+		data->alarms = adm9240_read_value(client,
+					ADM9240_REG_INT(0)) |
+					adm9240_read_value(client,
+					ADM9240_REG_INT(1)) << 8;
+
+		/* read temperature: assume temperature changes less than
+		 * 0.5'C per two measurement cycles thus ignore possible
+		 * but unlikely aliasing error on lsb reading. --Grant */
+		data->temp = ((adm9240_read_value(client,
+					ADM9240_REG_TEMP) << 8) |
+					adm9240_read_value(client,
+					ADM9240_REG_TEMP_CONF)) / 128;
+
+		for (i = 0; i < 2; i++) /* read fans */
+		{
+			data->fan[i] = adm9240_read_value(client,
+					ADM9240_REG_FAN(i));
+
+			/* adjust fan clock divider on overflow */
+			if (data->valid && data->fan[i] == 255 &&
+					data->fan_div[i] < 3) {
+
+				adm9240_write_fan_div(client, i,
+						++data->fan_div[i]);
+
+				/* adjust fan_min if active, but not to 0 */
+				if (data->fan_min[i] < 255 &&
+						data->fan_min[i] >= 2)
+					data->fan_min[i] /= 2;
+			}
+		}
+		data->last_updated_measure = jiffies;
+	}
+
+	/* minimum config reading cycle: 300 seconds */
+	if (time_after(jiffies, data->last_updated_config + (HZ * 300))
+			|| !data->valid) {
+
+		for (i = 0; i < 6; i++)
+		{
+			data->in_min[i] = adm9240_read_value(client,
+					ADM9240_REG_IN_MIN(i));
+			data->in_max[i] = adm9240_read_value(client,
+					ADM9240_REG_IN_MAX(i));
+		}
+		for (i = 0; i < 2; i++)
+		{
+			data->fan_min[i] = adm9240_read_value(client,
+					ADM9240_REG_FAN_MIN(i));
+		}
+		data->temp_high = adm9240_read_value(client,
+				ADM9240_REG_TEMP_HIGH);
+		data->temp_hyst = adm9240_read_value(client,
+				ADM9240_REG_TEMP_HYST);
+
+		/* read fan divs and 5-bit VID */
+		i = adm9240_read_value(client, ADM9240_REG_VID_FAN_DIV);
+		data->fan_div[0] = (i >> 4) & 3;
+		data->fan_div[1] = (i >> 6) & 3;
+		data->vid = i & 0x0f;
+		data->vid |= (adm9240_read_value(client,
+					ADM9240_REG_VID4) & 1) << 4;
+		/* read analog out */
+		data->aout = adm9240_read_value(client,
+				ADM9240_REG_ANALOG_OUT);
+
+		data->last_updated_config = jiffies;
+		data->valid = 1;
+	}
+	up(&data->update_lock);
+	return data;
+}
+
+static int __init sensors_adm9240_init(void)
+{
+	return i2c_add_driver(&adm9240_driver);
+}
+
+static void __exit sensors_adm9240_exit(void)
+{
+	i2c_del_driver(&adm9240_driver);
+}
+
+MODULE_AUTHOR("Michiel Rook <michiel@grendelproject.nl>, "
+		"Grant Coady <gcoady@gmail.com> and others");
+MODULE_DESCRIPTION("ADM9240/DS1780/LM81 driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_adm9240_init);
+module_exit(sensors_adm9240_exit);
+
diff --git a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c
index 7f89900..70d996d 100644
--- a/drivers/i2c/chips/asb100.c
+++ b/drivers/i2c/chips/asb100.c
@@ -42,6 +42,7 @@
 #include <linux/i2c-sensor.h>
 #include <linux/i2c-vid.h>
 #include <linux/init.h>
+#include <linux/jiffies.h>
 #include "lm75.h"
 
 /*
@@ -168,8 +169,6 @@
 	return reg * 16;
 }
 
-#define ALARMS_FROM_REG(val) (val)
-
 #define DIV_FROM_REG(val) (1 << (val))
 
 /* FAN DIV: 1, 2, 4, or 8 (defaults to 2)
@@ -260,28 +259,28 @@
 
 #define sysfs_in(offset) \
 static ssize_t \
-	show_in##offset (struct device *dev, char *buf) \
+	show_in##offset (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_in(dev, buf, offset); \
 } \
 static DEVICE_ATTR(in##offset##_input, S_IRUGO, \
 		show_in##offset, NULL); \
 static ssize_t \
-	show_in##offset##_min (struct device *dev, char *buf) \
+	show_in##offset##_min (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_in_min(dev, buf, offset); \
 } \
 static ssize_t \
-	show_in##offset##_max (struct device *dev, char *buf) \
+	show_in##offset##_max (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_in_max(dev, buf, offset); \
 } \
-static ssize_t set_in##offset##_min (struct device *dev, \
+static ssize_t set_in##offset##_min (struct device *dev, struct device_attribute *attr, \
 		const char *buf, size_t count) \
 { \
 	return set_in_min(dev, buf, count, offset); \
 } \
-static ssize_t set_in##offset##_max (struct device *dev, \
+static ssize_t set_in##offset##_max (struct device *dev, struct device_attribute *attr, \
 		const char *buf, size_t count) \
 { \
 	return set_in_max(dev, buf, count, offset); \
@@ -389,24 +388,24 @@
 }
 
 #define sysfs_fan(offset) \
-static ssize_t show_fan##offset(struct device *dev, char *buf) \
+static ssize_t show_fan##offset(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_fan(dev, buf, offset - 1); \
 } \
-static ssize_t show_fan##offset##_min(struct device *dev, char *buf) \
+static ssize_t show_fan##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_fan_min(dev, buf, offset - 1); \
 } \
-static ssize_t show_fan##offset##_div(struct device *dev, char *buf) \
+static ssize_t show_fan##offset##_div(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_fan_div(dev, buf, offset - 1); \
 } \
-static ssize_t set_fan##offset##_min(struct device *dev, const char *buf, \
+static ssize_t set_fan##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
 					size_t count) \
 { \
 	return set_fan_min(dev, buf, count, offset - 1); \
 } \
-static ssize_t set_fan##offset##_div(struct device *dev, const char *buf, \
+static ssize_t set_fan##offset##_div(struct device *dev, struct device_attribute *attr, const char *buf, \
 					size_t count) \
 { \
 	return set_fan_div(dev, buf, count, offset - 1); \
@@ -482,27 +481,27 @@
 set_temp_reg(HYST, temp_hyst);
 
 #define sysfs_temp(num) \
-static ssize_t show_temp##num(struct device *dev, char *buf) \
+static ssize_t show_temp##num(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_temp(dev, buf, num-1); \
 } \
 static DEVICE_ATTR(temp##num##_input, S_IRUGO, show_temp##num, NULL); \
-static ssize_t show_temp_max##num(struct device *dev, char *buf) \
+static ssize_t show_temp_max##num(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_temp_max(dev, buf, num-1); \
 } \
-static ssize_t set_temp_max##num(struct device *dev, const char *buf, \
+static ssize_t set_temp_max##num(struct device *dev, struct device_attribute *attr, const char *buf, \
 					size_t count) \
 { \
 	return set_temp_max(dev, buf, count, num-1); \
 } \
 static DEVICE_ATTR(temp##num##_max, S_IRUGO | S_IWUSR, \
 		show_temp_max##num, set_temp_max##num); \
-static ssize_t show_temp_hyst##num(struct device *dev, char *buf) \
+static ssize_t show_temp_hyst##num(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_temp_hyst(dev, buf, num-1); \
 } \
-static ssize_t set_temp_hyst##num(struct device *dev, const char *buf, \
+static ssize_t set_temp_hyst##num(struct device *dev, struct device_attribute *attr, const char *buf, \
 					size_t count) \
 { \
 	return set_temp_hyst(dev, buf, count, num-1); \
@@ -522,7 +521,7 @@
 	device_create_file(&client->dev, &dev_attr_temp##num##_max_hyst); \
 } while (0)
 
-static ssize_t show_vid(struct device *dev, char *buf)
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct asb100_data *data = asb100_update_device(dev);
 	return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
@@ -533,13 +532,13 @@
 device_create_file(&client->dev, &dev_attr_cpu0_vid)
 
 /* VRM */
-static ssize_t show_vrm(struct device *dev, char *buf)
+static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct asb100_data *data = asb100_update_device(dev);
 	return sprintf(buf, "%d\n", data->vrm);
 }
 
-static ssize_t set_vrm(struct device *dev, const char *buf, size_t count)
+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 asb100_data *data = i2c_get_clientdata(client);
@@ -553,10 +552,10 @@
 #define device_create_file_vrm(client) \
 device_create_file(&client->dev, &dev_attr_vrm);
 
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct asb100_data *data = asb100_update_device(dev);
-	return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->alarms));
+	return sprintf(buf, "%u\n", data->alarms);
 }
 
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
@@ -564,13 +563,13 @@
 device_create_file(&client->dev, &dev_attr_alarms)
 
 /* 1 PWM */
-static ssize_t show_pwm1(struct device *dev, char *buf)
+static ssize_t show_pwm1(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct asb100_data *data = asb100_update_device(dev);
 	return sprintf(buf, "%d\n", ASB100_PWM_FROM_REG(data->pwm & 0x0f));
 }
 
-static ssize_t set_pwm1(struct device *dev, const char *buf, size_t count)
+static ssize_t set_pwm1(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct asb100_data *data = i2c_get_clientdata(client);
@@ -584,13 +583,13 @@
 	return count;
 }
 
-static ssize_t show_pwm_enable1(struct device *dev, char *buf)
+static ssize_t show_pwm_enable1(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct asb100_data *data = asb100_update_device(dev);
 	return sprintf(buf, "%d\n", (data->pwm & 0x80) ? 1 : 0);
 }
 
-static ssize_t set_pwm_enable1(struct device *dev, const char *buf,
+static ssize_t set_pwm_enable1(struct device *dev, struct device_attribute *attr, const char *buf,
 				size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
diff --git a/drivers/i2c/chips/atxp1.c b/drivers/i2c/chips/atxp1.c
new file mode 100644
index 0000000..5c6597a
--- /dev/null
+++ b/drivers/i2c/chips/atxp1.c
@@ -0,0 +1,361 @@
+/*
+    atxp1.c - kernel module for setting CPU VID and general purpose
+                     I/Os using the Attansic ATXP1 chip.
+
+    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/init.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/i2c-vid.h>
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("System voltages control via Attansic ATXP1");
+MODULE_VERSION("0.6.2");
+MODULE_AUTHOR("Sebastian Witt <se.witt@gmx.net>");
+
+#define ATXP1_VID	0x00
+#define ATXP1_CVID	0x01
+#define ATXP1_GPIO1	0x06
+#define ATXP1_GPIO2	0x0a
+#define ATXP1_VIDENA	0x20
+#define ATXP1_VIDMASK	0x1f
+#define ATXP1_GPIO1MASK	0x0f
+
+static unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END };
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+
+SENSORS_INSMOD_1(atxp1);
+
+static int atxp1_attach_adapter(struct i2c_adapter * adapter);
+static int atxp1_detach_client(struct i2c_client * client);
+static struct atxp1_data * atxp1_update_device(struct device *dev);
+static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind);
+
+static struct i2c_driver atxp1_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "atxp1",
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter = atxp1_attach_adapter,
+	.detach_client	= atxp1_detach_client,
+};
+
+struct atxp1_data {
+	struct i2c_client client;
+	struct semaphore update_lock;
+	unsigned long last_updated;
+	u8 valid;
+	struct {
+		u8 vid;		/* VID output register */
+		u8 cpu_vid; /* VID input from CPU */
+		u8 gpio1;   /* General purpose I/O register 1 */
+		u8 gpio2;   /* General purpose I/O register 2 */
+	} reg;
+	u8 vrm;			/* Detected CPU VRM */
+};
+
+static struct atxp1_data * atxp1_update_device(struct device *dev)
+{
+	struct i2c_client *client;
+	struct atxp1_data *data;
+
+	client = to_i2c_client(dev);
+	data = i2c_get_clientdata(client);
+
+	down(&data->update_lock);
+
+	if ((jiffies - data->last_updated > HZ) ||
+	    (jiffies < data->last_updated) ||
+	    !data->valid) {
+
+		/* Update local register data */
+		data->reg.vid = i2c_smbus_read_byte_data(client, ATXP1_VID);
+		data->reg.cpu_vid = i2c_smbus_read_byte_data(client, ATXP1_CVID);
+		data->reg.gpio1 = i2c_smbus_read_byte_data(client, ATXP1_GPIO1);
+		data->reg.gpio2 = i2c_smbus_read_byte_data(client, ATXP1_GPIO2);
+
+		data->valid = 1;
+	}
+
+	up(&data->update_lock);
+
+	return(data);
+}
+
+/* sys file functions for cpu0_vid */
+static ssize_t atxp1_showvcore(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	int size;
+	struct atxp1_data *data;
+
+	data = atxp1_update_device(dev);
+
+	size = sprintf(buf, "%d\n", vid_from_reg(data->reg.vid & ATXP1_VIDMASK, data->vrm));
+
+	return size;
+}
+
+static ssize_t atxp1_storevcore(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct atxp1_data *data;
+	struct i2c_client *client;
+	char vid;
+	char cvid;
+	unsigned int vcore;
+
+	client = to_i2c_client(dev);
+	data = atxp1_update_device(dev);
+
+	vcore = simple_strtoul(buf, NULL, 10);
+	vcore /= 25;
+	vcore *= 25;
+
+	/* Calculate VID */
+	vid = vid_to_reg(vcore, data->vrm);
+
+	if (vid < 0) {
+		dev_err(dev, "VID calculation failed.\n");
+		return -1;
+	}
+
+	/* If output enabled, use control register value. Otherwise original CPU VID */
+	if (data->reg.vid & ATXP1_VIDENA)
+		cvid = data->reg.vid & ATXP1_VIDMASK;
+	else
+		cvid = data->reg.cpu_vid;
+
+	/* Nothing changed, aborting */
+	if (vid == cvid)
+		return count;
+
+	dev_info(dev, "Setting VCore to %d mV (0x%02x)\n", vcore, vid);
+
+	/* Write every 25 mV step to increase stability */
+	if (cvid > vid) {
+		for (; cvid >= vid; cvid--) {
+        		i2c_smbus_write_byte_data(client, ATXP1_VID, cvid | ATXP1_VIDENA);
+		}
+	}
+	else {
+		for (; cvid <= vid; cvid++) {
+        		i2c_smbus_write_byte_data(client, ATXP1_VID, cvid | ATXP1_VIDENA);
+		}
+	}
+
+	data->valid = 0;
+
+	return count;
+}
+
+/* CPU core reference voltage
+    unit: millivolt
+*/
+static DEVICE_ATTR(cpu0_vid, S_IRUGO | S_IWUSR, atxp1_showvcore, atxp1_storevcore);
+
+/* sys file functions for GPIO1 */
+static ssize_t atxp1_showgpio1(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	int size;
+	struct atxp1_data *data;
+
+	data = atxp1_update_device(dev);
+
+	size = sprintf(buf, "0x%02x\n", data->reg.gpio1 & ATXP1_GPIO1MASK);
+
+	return size;
+}
+
+static ssize_t atxp1_storegpio1(struct device *dev, struct device_attribute *attr, const char*buf, size_t count)
+{
+	struct atxp1_data *data;
+	struct i2c_client *client;
+	unsigned int value;
+
+	client = to_i2c_client(dev);
+	data = atxp1_update_device(dev);
+
+	value = simple_strtoul(buf, NULL, 16);
+
+	value &= ATXP1_GPIO1MASK;
+
+	if (value != (data->reg.gpio1 & ATXP1_GPIO1MASK)) {
+		dev_info(dev, "Writing 0x%x to GPIO1.\n", value);
+
+		i2c_smbus_write_byte_data(client, ATXP1_GPIO1, value);
+
+		data->valid = 0;
+	}
+
+	return count;
+}
+
+/* GPIO1 data register
+    unit: Four bit as hex (e.g. 0x0f)
+*/
+static DEVICE_ATTR(gpio1, S_IRUGO | S_IWUSR, atxp1_showgpio1, atxp1_storegpio1);
+
+/* sys file functions for GPIO2 */
+static ssize_t atxp1_showgpio2(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	int size;
+	struct atxp1_data *data;
+
+	data = atxp1_update_device(dev);
+
+	size = sprintf(buf, "0x%02x\n", data->reg.gpio2);
+
+	return size;
+}
+
+static ssize_t atxp1_storegpio2(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct atxp1_data *data;
+	struct i2c_client *client;
+	unsigned int value;
+
+	client = to_i2c_client(dev);
+	data = atxp1_update_device(dev);
+
+	value = simple_strtoul(buf, NULL, 16) & 0xff;
+
+	if (value != data->reg.gpio2) {
+		dev_info(dev, "Writing 0x%x to GPIO1.\n", value);
+
+		i2c_smbus_write_byte_data(client, ATXP1_GPIO2, value);
+
+		data->valid = 0;
+	}
+
+	return count;
+}
+
+/* GPIO2 data register
+    unit: Eight bit as hex (e.g. 0xff)
+*/
+static DEVICE_ATTR(gpio2, S_IRUGO | S_IWUSR, atxp1_showgpio2, atxp1_storegpio2);
+
+
+static int atxp1_attach_adapter(struct i2c_adapter *adapter)
+{
+	return i2c_detect(adapter, &addr_data, &atxp1_detect);
+};
+
+static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client * new_client;
+	struct atxp1_data * data;
+	int err = 0;
+	u8 temp;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		goto exit;
+
+	if (!(data = kmalloc(sizeof(struct atxp1_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	memset(data, 0, sizeof(struct atxp1_data));
+	new_client = &data->client;
+	i2c_set_clientdata(new_client, data);
+
+	new_client->addr = address;
+	new_client->adapter = adapter;
+	new_client->driver = &atxp1_driver;
+	new_client->flags = 0;
+
+	/* Detect ATXP1, checking if vendor ID registers are all zero */
+	if (!((i2c_smbus_read_byte_data(new_client, 0x3e) == 0) &&
+	     (i2c_smbus_read_byte_data(new_client, 0x3f) == 0) &&
+	     (i2c_smbus_read_byte_data(new_client, 0xfe) == 0) &&
+	     (i2c_smbus_read_byte_data(new_client, 0xff) == 0) )) {
+
+		/* No vendor ID, now checking if registers 0x10,0x11 (non-existent)
+		 * showing the same as register 0x00 */
+		temp = i2c_smbus_read_byte_data(new_client, 0x00);
+
+		if (!((i2c_smbus_read_byte_data(new_client, 0x10) == temp) &&
+			 (i2c_smbus_read_byte_data(new_client, 0x11) == temp) ))
+			goto exit_free;
+	}
+
+	/* Get VRM */
+	data->vrm = i2c_which_vrm();
+
+	if ((data->vrm != 90) && (data->vrm != 91)) {
+		dev_err(&new_client->dev, "Not supporting VRM %d.%d\n",
+				data->vrm / 10, data->vrm % 10);
+		goto exit_free;
+	}
+
+	strncpy(new_client->name, "atxp1", I2C_NAME_SIZE);
+
+	data->valid = 0;
+
+	init_MUTEX(&data->update_lock);
+
+	err = i2c_attach_client(new_client);
+
+	if (err)
+	{
+		dev_err(&new_client->dev, "Attach client error.\n");
+		goto exit_free;
+	}
+
+	device_create_file(&new_client->dev, &dev_attr_gpio1);
+	device_create_file(&new_client->dev, &dev_attr_gpio2);
+	device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
+
+	dev_info(&new_client->dev, "Using VRM: %d.%d\n",
+			 data->vrm / 10, data->vrm % 10);
+
+	return 0;
+
+exit_free:
+	kfree(data);
+exit:
+	return err;
+};
+
+static int atxp1_detach_client(struct i2c_client * client)
+{
+	int err;
+
+	err = i2c_detach_client(client);
+
+	if (err)
+		dev_err(&client->dev, "Failed to detach client.\n");
+	else
+		kfree(i2c_get_clientdata(client));
+
+	return err;
+};
+
+static int __init atxp1_init(void)
+{
+	return i2c_add_driver(&atxp1_driver);
+};
+
+static void __exit atxp1_exit(void)
+{
+	i2c_del_driver(&atxp1_driver);
+};
+
+module_init(atxp1_init);
+module_exit(atxp1_exit);
diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c
index 07f16c3..74ece8a 100644
--- a/drivers/i2c/chips/ds1337.c
+++ b/drivers/i2c/chips/ds1337.c
@@ -3,17 +3,16 @@
  *
  *  Copyright (C) 2005 James Chapman <jchapman@katalix.com>
  *
- *	based on linux/drivers/acron/char/pcf8583.c
+ *	based on linux/drivers/acorn/char/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 Dallas Semiconductor DS1337 real time clock chip
+ * Driver for Dallas Semiconductor DS1337 and DS1339 real time clock chip
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -69,13 +68,11 @@
 struct ds1337_data {
 	struct i2c_client client;
 	struct list_head list;
-	int id;
 };
 
 /*
  * Internal variables
  */
-static int ds1337_id;
 static LIST_HEAD(ds1337_clients);
 
 static inline int ds1337_read(struct i2c_client *client, u8 reg, u8 *value)
@@ -95,7 +92,6 @@
  */
 static int ds1337_get_datetime(struct i2c_client *client, struct rtc_time *dt)
 {
-	struct ds1337_data *data = i2c_get_clientdata(client);
 	int result;
 	u8 buf[7];
 	u8 val;
@@ -103,9 +99,7 @@
 	u8 offs = 0;
 
 	if (!dt) {
-		dev_dbg(&client->adapter->dev, "%s: EINVAL: dt=NULL\n",
-			__FUNCTION__);
-
+		dev_dbg(&client->dev, "%s: EINVAL: dt=NULL\n", __FUNCTION__);
 		return -EINVAL;
 	}
 
@@ -119,98 +113,86 @@
 	msg[1].len = sizeof(buf);
 	msg[1].buf = &buf[0];
 
-	result = client->adapter->algo->master_xfer(client->adapter,
-						    &msg[0], 2);
+	result = i2c_transfer(client->adapter, msg, 2);
 
-	dev_dbg(&client->adapter->dev,
-		"%s: [%d] %02x %02x %02x %02x %02x %02x %02x\n",
+	dev_dbg(&client->dev, "%s: [%d] %02x %02x %02x %02x %02x %02x %02x\n",
 		__FUNCTION__, result, buf[0], buf[1], buf[2], buf[3],
 		buf[4], buf[5], buf[6]);
 
-	if (result >= 0) {
-		dt->tm_sec = BCD_TO_BIN(buf[0]);
-		dt->tm_min = BCD_TO_BIN(buf[1]);
+	if (result == 2) {
+		dt->tm_sec = BCD2BIN(buf[0]);
+		dt->tm_min = BCD2BIN(buf[1]);
 		val = buf[2] & 0x3f;
-		dt->tm_hour = BCD_TO_BIN(val);
-		dt->tm_wday = BCD_TO_BIN(buf[3]) - 1;
-		dt->tm_mday = BCD_TO_BIN(buf[4]);
+		dt->tm_hour = BCD2BIN(val);
+		dt->tm_wday = BCD2BIN(buf[3]) - 1;
+		dt->tm_mday = BCD2BIN(buf[4]);
 		val = buf[5] & 0x7f;
-		dt->tm_mon = BCD_TO_BIN(val);
-		dt->tm_year = 1900 + BCD_TO_BIN(buf[6]);
+		dt->tm_mon = BCD2BIN(val) - 1;
+		dt->tm_year = BCD2BIN(buf[6]);
 		if (buf[5] & 0x80)
 			dt->tm_year += 100;
 
-		dev_dbg(&client->adapter->dev, "%s: secs=%d, mins=%d, "
+		dev_dbg(&client->dev, "%s: secs=%d, mins=%d, "
 			"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
 			__FUNCTION__, dt->tm_sec, dt->tm_min,
 			dt->tm_hour, dt->tm_mday,
 			dt->tm_mon, dt->tm_year, dt->tm_wday);
-	} else {
-		dev_err(&client->adapter->dev, "ds1337[%d]: error reading "
-			"data! %d\n", data->id, result);
-		result = -EIO;
+
+		return 0;
 	}
 
-	return result;
+	dev_err(&client->dev, "error reading data! %d\n", result);
+	return -EIO;
 }
 
 static int ds1337_set_datetime(struct i2c_client *client, struct rtc_time *dt)
 {
-	struct ds1337_data *data = i2c_get_clientdata(client);
 	int result;
 	u8 buf[8];
 	u8 val;
 	struct i2c_msg msg[1];
 
 	if (!dt) {
-		dev_dbg(&client->adapter->dev, "%s: EINVAL: dt=NULL\n",
-			__FUNCTION__);
-
+		dev_dbg(&client->dev, "%s: EINVAL: dt=NULL\n", __FUNCTION__);
 		return -EINVAL;
 	}
 
-	dev_dbg(&client->adapter->dev, "%s: secs=%d, mins=%d, hours=%d, "
+	dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
 		"mday=%d, mon=%d, year=%d, wday=%d\n", __FUNCTION__,
 		dt->tm_sec, dt->tm_min, dt->tm_hour,
 		dt->tm_mday, dt->tm_mon, dt->tm_year, dt->tm_wday);
 
 	buf[0] = 0;		/* reg offset */
-	buf[1] = BIN_TO_BCD(dt->tm_sec);
-	buf[2] = BIN_TO_BCD(dt->tm_min);
-	buf[3] = BIN_TO_BCD(dt->tm_hour) | (1 << 6);
-	buf[4] = BIN_TO_BCD(dt->tm_wday) + 1;
-	buf[5] = BIN_TO_BCD(dt->tm_mday);
-	buf[6] = BIN_TO_BCD(dt->tm_mon);
-	if (dt->tm_year >= 2000) {
-		val = dt->tm_year - 2000;
+	buf[1] = BIN2BCD(dt->tm_sec);
+	buf[2] = BIN2BCD(dt->tm_min);
+	buf[3] = BIN2BCD(dt->tm_hour) | (1 << 6);
+	buf[4] = BIN2BCD(dt->tm_wday) + 1;
+	buf[5] = BIN2BCD(dt->tm_mday);
+	buf[6] = BIN2BCD(dt->tm_mon) + 1;
+	val = dt->tm_year;
+	if (val >= 100) {
+		val -= 100;
 		buf[6] |= (1 << 7);
-	} else {
-		val = dt->tm_year - 1900;
 	}
-	buf[7] = BIN_TO_BCD(val);
+	buf[7] = BIN2BCD(val);
 
 	msg[0].addr = client->addr;
 	msg[0].flags = 0;
 	msg[0].len = sizeof(buf);
 	msg[0].buf = &buf[0];
 
-	result = client->adapter->algo->master_xfer(client->adapter,
-						    &msg[0], 1);
-	if (result < 0) {
-		dev_err(&client->adapter->dev, "ds1337[%d]: error "
-			"writing data! %d\n", data->id, result);
-		result = -EIO;
-	} else {
-		result = 0;
-	}
+	result = i2c_transfer(client->adapter, msg, 1);
+	if (result == 1)
+		return 0;
 
-	return result;
+	dev_err(&client->dev, "error writing data! %d\n", result);
+	return -EIO;
 }
 
 static int ds1337_command(struct i2c_client *client, unsigned int cmd,
 			  void *arg)
 {
-	dev_dbg(&client->adapter->dev, "%s: cmd=%d\n", __FUNCTION__, cmd);
+	dev_dbg(&client->dev, "%s: cmd=%d\n", __FUNCTION__, cmd);
 
 	switch (cmd) {
 	case DS1337_GET_DATE:
@@ -228,7 +210,7 @@
  * Public API for access to specific device. Useful for low-level
  * RTC access from kernel code.
  */
-int ds1337_do_command(int id, int cmd, void *arg)
+int ds1337_do_command(int bus, int cmd, void *arg)
 {
 	struct list_head *walk;
 	struct list_head *tmp;
@@ -236,7 +218,7 @@
 
 	list_for_each_safe(walk, tmp, &ds1337_clients) {
 		data = list_entry(walk, struct ds1337_data, list);
-		if (data->id == id)
+		if (data->client.adapter->nr == bus)
 			return ds1337_command(&data->client, cmd, arg);
 	}
 
@@ -346,7 +328,6 @@
 	ds1337_init_client(new_client);
 
 	/* Add client to local list */
-	data->id = ds1337_id++;
 	list_add(&data->list, &ds1337_clients);
 
 	return 0;
@@ -398,5 +379,7 @@
 MODULE_DESCRIPTION("DS1337 RTC driver");
 MODULE_LICENSE("GPL");
 
+EXPORT_SYMBOL_GPL(ds1337_do_command);
+
 module_init(ds1337_init);
 module_exit(ds1337_exit);
diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c
new file mode 100644
index 0000000..a445736
--- /dev/null
+++ b/drivers/i2c/chips/ds1374.c
@@ -0,0 +1,260 @@
+/*
+ * drivers/i2c/chips/ds1374.c
+ *
+ * I2C client/driver for the Maxim/Dallas DS1374 Real-Time Clock
+ *
+ * Author: Randy Vinson <rvinson@mvista.com>
+ *
+ * Based on the m41t00.c by Mark Greer <mgreer@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.
+ */
+/*
+ * 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>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+
+#define DS1374_REG_TOD0		0x00
+#define DS1374_REG_TOD1		0x01
+#define DS1374_REG_TOD2		0x02
+#define DS1374_REG_TOD3		0x03
+#define DS1374_REG_WDALM0	0x04
+#define DS1374_REG_WDALM1	0x05
+#define DS1374_REG_WDALM2	0x06
+#define DS1374_REG_CR		0x07
+#define DS1374_REG_SR		0x08
+#define DS1374_REG_SR_OSF	0x80
+#define DS1374_REG_TCR		0x09
+
+#define	DS1374_DRV_NAME		"ds1374"
+
+static DECLARE_MUTEX(ds1374_mutex);
+
+static struct i2c_driver ds1374_driver;
+static struct i2c_client *save_client;
+
+static unsigned short ignore[] = { I2C_CLIENT_END };
+static unsigned short normal_addr[] = { 0x68, I2C_CLIENT_END };
+
+static struct i2c_client_address_data addr_data = {
+	.normal_i2c = normal_addr,
+	.probe = ignore,
+	.ignore = ignore,
+	.force = ignore,
+};
+
+static ulong ds1374_read_rtc(void)
+{
+	ulong time = 0;
+	int reg = DS1374_REG_WDALM0;
+
+	while (reg--) {
+		s32 tmp;
+		if ((tmp = i2c_smbus_read_byte_data(save_client, reg)) < 0) {
+			dev_warn(&save_client->dev,
+				 "can't read from rtc chip\n");
+			return 0;
+		}
+		time = (time << 8) | (tmp & 0xff);
+	}
+	return time;
+}
+
+static void ds1374_write_rtc(ulong time)
+{
+	int reg;
+
+	for (reg = DS1374_REG_TOD0; reg < DS1374_REG_WDALM0; reg++) {
+		if (i2c_smbus_write_byte_data(save_client, reg, time & 0xff)
+		    < 0) {
+			dev_warn(&save_client->dev,
+				 "can't write to rtc chip\n");
+			break;
+		}
+		time = time >> 8;
+	}
+}
+
+static void ds1374_check_rtc_status(void)
+{
+	s32 tmp;
+
+	tmp = i2c_smbus_read_byte_data(save_client, DS1374_REG_SR);
+	if (tmp < 0) {
+		dev_warn(&save_client->dev,
+			 "can't read status from rtc chip\n");
+		return;
+	}
+	if (tmp & DS1374_REG_SR_OSF) {
+		dev_warn(&save_client->dev,
+			 "oscillator discontinuity flagged, time unreliable\n");
+		tmp &= ~DS1374_REG_SR_OSF;
+		tmp = i2c_smbus_write_byte_data(save_client, DS1374_REG_SR,
+						tmp & 0xff);
+		if (tmp < 0)
+			dev_warn(&save_client->dev,
+				 "can't clear discontinuity notification\n");
+	}
+}
+
+ulong ds1374_get_rtc_time(void)
+{
+	ulong t1, t2;
+	int limit = 10;		/* arbitrary retry limit */
+
+	down(&ds1374_mutex);
+
+	/*
+	 * Since the reads are being performed one byte at a time using
+	 * the SMBus vs a 4-byte i2c transfer, there is a chance that a
+	 * carry will occur during the read. To detect this, 2 reads are
+	 * performed and compared.
+	 */
+	do {
+		t1 = ds1374_read_rtc();
+		t2 = ds1374_read_rtc();
+	} while (t1 != t2 && limit--);
+
+	up(&ds1374_mutex);
+
+	if (t1 != t2) {
+		dev_warn(&save_client->dev,
+			 "can't get consistent time from rtc chip\n");
+		t1 = 0;
+	}
+
+	return t1;
+}
+
+static void ds1374_set_tlet(ulong arg)
+{
+	ulong t1, t2;
+	int limit = 10;		/* arbitrary retry limit */
+
+	t1 = *(ulong *) arg;
+
+	down(&ds1374_mutex);
+
+	/*
+	 * Since the writes are being performed one byte at a time using
+	 * the SMBus vs a 4-byte i2c transfer, there is a chance that a
+	 * carry will occur during the write. To detect this, the write
+	 * value is read back and compared.
+	 */
+	do {
+		ds1374_write_rtc(t1);
+		t2 = ds1374_read_rtc();
+	} while (t1 != t2 && limit--);
+
+	up(&ds1374_mutex);
+
+	if (t1 != t2)
+		dev_warn(&save_client->dev,
+			 "can't confirm time set from rtc chip\n");
+}
+
+ulong new_time;
+
+DECLARE_TASKLET_DISABLED(ds1374_tasklet, ds1374_set_tlet, (ulong) & new_time);
+
+int ds1374_set_rtc_time(ulong nowtime)
+{
+	new_time = nowtime;
+
+	if (in_interrupt())
+		tasklet_schedule(&ds1374_tasklet);
+	else
+		ds1374_set_tlet((ulong) & new_time);
+
+	return 0;
+}
+
+/*
+ *****************************************************************************
+ *
+ *	Driver Interface
+ *
+ *****************************************************************************
+ */
+static int ds1374_probe(struct i2c_adapter *adap, int addr, int kind)
+{
+	struct i2c_client *client;
+	int rc;
+
+	client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+	if (!client)
+		return -ENOMEM;
+
+	memset(client, 0, sizeof(struct i2c_client));
+	strncpy(client->name, DS1374_DRV_NAME, I2C_NAME_SIZE);
+	client->flags = I2C_DF_NOTIFY;
+	client->addr = addr;
+	client->adapter = adap;
+	client->driver = &ds1374_driver;
+
+	if ((rc = i2c_attach_client(client)) != 0) {
+		kfree(client);
+		return rc;
+	}
+
+	save_client = client;
+
+	ds1374_check_rtc_status();
+
+	return 0;
+}
+
+static int ds1374_attach(struct i2c_adapter *adap)
+{
+	return i2c_probe(adap, &addr_data, ds1374_probe);
+}
+
+static int ds1374_detach(struct i2c_client *client)
+{
+	int rc;
+
+	if ((rc = i2c_detach_client(client)) == 0) {
+		kfree(i2c_get_clientdata(client));
+		tasklet_kill(&ds1374_tasklet);
+	}
+	return rc;
+}
+
+static struct i2c_driver ds1374_driver = {
+	.owner = THIS_MODULE,
+	.name = DS1374_DRV_NAME,
+	.id = I2C_DRIVERID_DS1374,
+	.flags = I2C_DF_NOTIFY,
+	.attach_adapter = ds1374_attach,
+	.detach_client = ds1374_detach,
+};
+
+static int __init ds1374_init(void)
+{
+	return i2c_add_driver(&ds1374_driver);
+}
+
+static void __exit ds1374_exit(void)
+{
+	i2c_del_driver(&ds1374_driver);
+}
+
+module_init(ds1374_init);
+module_exit(ds1374_exit);
+
+MODULE_AUTHOR("Randy Vinson <rvinson@mvista.com>");
+MODULE_DESCRIPTION("Maxim/Dallas DS1374 RTC I2C Client Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/chips/ds1621.c b/drivers/i2c/chips/ds1621.c
index bb1fefb..5360d58 100644
--- a/drivers/i2c/chips/ds1621.c
+++ b/drivers/i2c/chips/ds1621.c
@@ -121,7 +121,7 @@
 static void ds1621_init_client(struct i2c_client *client)
 {
 	int reg = ds1621_read_value(client, DS1621_REG_CONF);
-	/* switch to continous conversion mode */
+	/* switch to continuous conversion mode */
 	reg &= ~ DS1621_REG_CONFIG_1SHOT;
 
 	/* setup output polarity */
@@ -137,7 +137,7 @@
 }
 
 #define show(value)							\
-static ssize_t show_##value(struct device *dev, char *buf)		\
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf)		\
 {									\
 	struct ds1621_data *data = ds1621_update_client(dev);		\
 	return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->value));	\
@@ -148,7 +148,7 @@
 show(temp_max);
 
 #define set_temp(suffix, value, reg)					\
-static ssize_t set_temp_##suffix(struct device *dev, const char *buf,	\
+static ssize_t set_temp_##suffix(struct device *dev, struct device_attribute *attr, const char *buf,	\
 				 size_t count)				\
 {									\
 	struct i2c_client *client = to_i2c_client(dev);			\
@@ -165,7 +165,7 @@
 set_temp(min, temp_min, DS1621_REG_TEMP_MIN);
 set_temp(max, temp_max, DS1621_REG_TEMP_MAX);
 
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct ds1621_data *data = ds1621_update_client(dev);
 	return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->conf));
@@ -303,7 +303,7 @@
 		data->temp_max = ds1621_read_value(client,
 						    DS1621_REG_TEMP_MAX);
 
-		/* reset alarms if neccessary */
+		/* reset alarms if necessary */
 		new_conf = data->conf;
 		if (data->temp < data->temp_min)
 			new_conf &= ~DS1621_ALARM_TEMP_LOW;
diff --git a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
index cbdfa2d..addf0ad 100644
--- a/drivers/i2c/chips/eeprom.c
+++ b/drivers/i2c/chips/eeprom.c
@@ -26,7 +26,6 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/module.h>
diff --git a/drivers/i2c/chips/fscher.c b/drivers/i2c/chips/fscher.c
index 18e33ac..da41174 100644
--- a/drivers/i2c/chips/fscher.c
+++ b/drivers/i2c/chips/fscher.c
@@ -26,7 +26,6 @@
  *  and Philip Edelbrock <phil@netroedge.com>
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -157,8 +156,8 @@
 
 #define sysfs_r(kind, sub, offset, reg) \
 static ssize_t show_##kind##sub (struct fscher_data *, char *, int); \
-static ssize_t show_##kind##offset##sub (struct device *, char *); \
-static ssize_t show_##kind##offset##sub (struct device *dev, char *buf) \
+static ssize_t show_##kind##offset##sub (struct device *, struct device_attribute *attr, char *); \
+static ssize_t show_##kind##offset##sub (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct fscher_data *data = fscher_update_device(dev); \
 	return show_##kind##sub(data, buf, (offset)); \
@@ -166,8 +165,8 @@
 
 #define sysfs_w(kind, sub, offset, reg) \
 static ssize_t set_##kind##sub (struct i2c_client *, struct fscher_data *, const char *, size_t, int, int); \
-static ssize_t set_##kind##offset##sub (struct device *, const char *, size_t); \
-static ssize_t set_##kind##offset##sub (struct device *dev, const char *buf, size_t count) \
+static ssize_t set_##kind##offset##sub (struct device *, struct device_attribute *attr, const char *, size_t); \
+static ssize_t set_##kind##offset##sub (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
 	struct fscher_data *data = i2c_get_clientdata(client); \
diff --git a/drivers/i2c/chips/fscpos.c b/drivers/i2c/chips/fscpos.c
index 2cac791..3beaa61 100644
--- a/drivers/i2c/chips/fscpos.c
+++ b/drivers/i2c/chips/fscpos.c
@@ -245,19 +245,19 @@
 /* Volts */
 #define VOLT_FROM_REG(val, mult)	((val) * (mult) / 255)
 
-static ssize_t show_volt_12(struct device *dev, char *buf)
+static ssize_t show_volt_12(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct fscpos_data *data = fscpos_update_device(dev);
 	return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[0], 14200));
 }
 
-static ssize_t show_volt_5(struct device *dev, char *buf)
+static ssize_t show_volt_5(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct fscpos_data *data = fscpos_update_device(dev);
 	return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[1], 6600));
 }
 
-static ssize_t show_volt_batt(struct device *dev, char *buf)
+static ssize_t show_volt_batt(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct fscpos_data *data = fscpos_update_device(dev);
 	return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[2], 3300));
@@ -327,7 +327,7 @@
 }
 
 /* Event */
-static ssize_t show_event(struct device *dev, char *buf)
+static ssize_t show_event(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	/* bits 5..7 reserved => mask with 0x1f */
 	struct fscpos_data *data = fscpos_update_device(dev);
@@ -338,14 +338,14 @@
  * Sysfs stuff
  */
 #define create_getter(kind, sub) \
-	static ssize_t sysfs_show_##kind##sub(struct device *dev, char *buf) \
+	static ssize_t sysfs_show_##kind##sub(struct device *dev, struct device_attribute *attr, char *buf) \
 	{ \
 		struct fscpos_data *data = fscpos_update_device(dev); \
 		return show_##kind##sub(data, buf); \
 	}
 
 #define create_getter_n(kind, offset, sub) \
-	static ssize_t sysfs_show_##kind##offset##sub(struct device *dev, char\
+	static ssize_t sysfs_show_##kind##offset##sub(struct device *dev, struct device_attribute *attr, char\
 								 	*buf) \
 	{ \
 		struct fscpos_data *data = fscpos_update_device(dev); \
@@ -353,7 +353,7 @@
 	}
 
 #define create_setter(kind, sub, reg) \
-	static ssize_t sysfs_set_##kind##sub (struct device *dev, const char \
+	static ssize_t sysfs_set_##kind##sub (struct device *dev, struct device_attribute *attr, const char \
 							*buf, size_t count) \
 	{ \
 		struct i2c_client *client = to_i2c_client(dev); \
@@ -362,7 +362,7 @@
 	}
 
 #define create_setter_n(kind, offset, sub, reg) \
-	static ssize_t sysfs_set_##kind##offset##sub (struct device *dev, \
+	static ssize_t sysfs_set_##kind##offset##sub (struct device *dev, struct device_attribute *attr, \
 					const char *buf, size_t count) \
 	{ \
 		struct i2c_client *client = to_i2c_client(dev); \
diff --git a/drivers/i2c/chips/gl518sm.c b/drivers/i2c/chips/gl518sm.c
index c82d6ce..6bedf72 100644
--- a/drivers/i2c/chips/gl518sm.c
+++ b/drivers/i2c/chips/gl518sm.c
@@ -36,7 +36,6 @@
  * 2004-01-31  Code review and approval. (Jean Delvare)
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -164,14 +163,14 @@
  */
 
 #define show(type, suffix, value)					\
-static ssize_t show_##suffix(struct device *dev, char *buf)		\
+static ssize_t show_##suffix(struct device *dev, struct device_attribute *attr, char *buf)		\
 {									\
 	struct gl518_data *data = gl518_update_device(dev);		\
 	return sprintf(buf, "%d\n", type##_FROM_REG(data->value));	\
 }
 
 #define show_fan(suffix, value, index)					\
-static ssize_t show_##suffix(struct device *dev, char *buf)		\
+static ssize_t show_##suffix(struct device *dev, struct device_attribute *attr, char *buf)		\
 {									\
 	struct gl518_data *data = gl518_update_device(dev);		\
 	return sprintf(buf, "%d\n", FAN_FROM_REG(data->value[index],	\
@@ -205,7 +204,7 @@
 show(BEEP_MASK, beep_mask, beep_mask);
 
 #define set(type, suffix, value, reg)					\
-static ssize_t set_##suffix(struct device *dev, const char *buf,	\
+static ssize_t set_##suffix(struct device *dev, struct device_attribute *attr, const char *buf,	\
 	size_t count)							\
 {									\
 	struct i2c_client *client = to_i2c_client(dev);			\
@@ -220,7 +219,7 @@
 }
 
 #define set_bits(type, suffix, value, reg, mask, shift)			\
-static ssize_t set_##suffix(struct device *dev, const char *buf,	\
+static ssize_t set_##suffix(struct device *dev, struct device_attribute *attr, const char *buf,	\
 	size_t count)							\
 {									\
 	struct i2c_client *client = to_i2c_client(dev);			\
@@ -258,7 +257,7 @@
 set_bits(BOOL, beep_enable, beep_enable, GL518_REG_CONF, 0x04, 2);
 set(BEEP_MASK, beep_mask, beep_mask, GL518_REG_ALARM);
 
-static ssize_t set_fan_min1(struct device *dev, const char *buf, size_t count)
+static ssize_t set_fan_min1(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct gl518_data *data = i2c_get_clientdata(client);
@@ -284,7 +283,7 @@
 	return count;
 }
 
-static ssize_t set_fan_min2(struct device *dev, const char *buf, size_t count)
+static ssize_t set_fan_min2(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct gl518_data *data = i2c_get_clientdata(client);
diff --git a/drivers/i2c/chips/gl520sm.c b/drivers/i2c/chips/gl520sm.c
index 3fd17e4..a13a504 100644
--- a/drivers/i2c/chips/gl520sm.c
+++ b/drivers/i2c/chips/gl520sm.c
@@ -148,8 +148,8 @@
 
 #define sysfs_r(type, n, item, reg) \
 static ssize_t get_##type##item (struct gl520_data *, char *, int); \
-static ssize_t get_##type##n##item (struct device *, char *); \
-static ssize_t get_##type##n##item (struct device *dev, char *buf) \
+static ssize_t get_##type##n##item (struct device *, struct device_attribute *attr, char *); \
+static ssize_t get_##type##n##item (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct gl520_data *data = gl520_update_device(dev); \
 	return get_##type##item(data, buf, (n)); \
@@ -157,8 +157,8 @@
 
 #define sysfs_w(type, n, item, reg) \
 static ssize_t set_##type##item (struct i2c_client *, struct gl520_data *, const char *, size_t, int, int); \
-static ssize_t set_##type##n##item (struct device *, const char *, size_t); \
-static ssize_t set_##type##n##item (struct device *dev, const char *buf, size_t count) \
+static ssize_t set_##type##n##item (struct device *, struct device_attribute *attr, const char *, size_t); \
+static ssize_t set_##type##n##item (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
 	struct gl520_data *data = i2c_get_clientdata(client); \
diff --git a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
index 7f29a8a..354a262 100644
--- a/drivers/i2c/chips/isp1301_omap.c
+++ b/drivers/i2c/chips/isp1301_omap.c
@@ -145,7 +145,6 @@
 static unsigned short normal_i2c[] = {
 	ISP_BASE, ISP_BASE + 1,
 	I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
 I2C_CLIENT_INSMOD;
 
diff --git a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
index cf7e689..db20c9e 100644
--- a/drivers/i2c/chips/it87.c
+++ b/drivers/i2c/chips/it87.c
@@ -31,7 +31,6 @@
     type at module load time.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -39,6 +38,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 #include <linux/i2c-vid.h>
+#include <linux/hwmon-sysfs.h>
 #include <asm/io.h>
 
 
@@ -173,8 +173,6 @@
 					((val)+500)/1000),-128,127))
 #define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*1000)
 
-#define ALARMS_FROM_REG(val) (val)
-
 #define PWM_TO_REG(val)   ((val) >> 1)
 #define PWM_FROM_REG(val) (((val)&0x7f) << 1)
 
@@ -241,27 +239,42 @@
 	.detach_client	= it87_detach_client,
 };
 
-static ssize_t show_in(struct device *dev, char *buf, int nr)
+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 it87_data *data = it87_update_device(dev);
 	return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr]));
 }
 
-static ssize_t show_in_min(struct device *dev, char *buf, int 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 it87_data *data = it87_update_device(dev);
 	return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr]));
 }
 
-static ssize_t show_in_max(struct device *dev, char *buf, int 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 it87_data *data = it87_update_device(dev);
 	return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr]));
 }
 
-static ssize_t set_in_min(struct device *dev, const char *buf, 
-		size_t count, int 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 it87_data *data = i2c_get_clientdata(client);
 	unsigned long val = simple_strtoul(buf, NULL, 10);
@@ -273,9 +286,12 @@
 	up(&data->update_lock);
 	return count;
 }
-static ssize_t set_in_max(struct device *dev, const char *buf, 
-		size_t count, int nr)
+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 it87_data *data = i2c_get_clientdata(client);
 	unsigned long val = simple_strtoul(buf, NULL, 10);
@@ -289,38 +305,14 @@
 }
 
 #define show_in_offset(offset)					\
-static ssize_t							\
-	show_in##offset (struct device *dev, char *buf)		\
-{								\
-	return show_in(dev, buf, offset);			\
-}								\
-static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL);
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO,		\
+		show_in, NULL, offset);
 
 #define limit_in_offset(offset)					\
-static ssize_t							\
-	show_in##offset##_min (struct device *dev, char *buf)	\
-{								\
-	return show_in_min(dev, buf, offset);			\
-}								\
-static ssize_t							\
-	show_in##offset##_max (struct device *dev, char *buf)	\
-{								\
-	return show_in_max(dev, buf, offset);			\
-}								\
-static ssize_t set_in##offset##_min (struct device *dev, 	\
-		const char *buf, size_t count) 			\
-{								\
-	return set_in_min(dev, buf, count, offset);		\
-}								\
-static ssize_t set_in##offset##_max (struct device *dev,	\
-			const char *buf, size_t count)		\
-{								\
-	return set_in_max(dev, buf, count, offset);		\
-}								\
-static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, 	\
-		show_in##offset##_min, set_in##offset##_min);	\
-static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, 	\
-		show_in##offset##_max, set_in##offset##_max);
+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);
 limit_in_offset(0);
@@ -341,24 +333,39 @@
 show_in_offset(8);
 
 /* 3 temperatures */
-static ssize_t show_temp(struct device *dev, char *buf, int nr)
+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 it87_data *data = it87_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr]));
 }
-static ssize_t show_temp_max(struct device *dev, char *buf, int 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 it87_data *data = it87_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[nr]));
 }
-static ssize_t show_temp_min(struct device *dev, char *buf, int 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 it87_data *data = it87_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_low[nr]));
 }
-static ssize_t set_temp_max(struct device *dev, const char *buf, 
-		size_t count, int nr)
+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 it87_data *data = i2c_get_clientdata(client);
 	int val = simple_strtol(buf, NULL, 10);
@@ -369,9 +376,12 @@
 	up(&data->update_lock);
 	return count;
 }
-static ssize_t set_temp_min(struct device *dev, const char *buf, 
-		size_t count, int 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 it87_data *data = i2c_get_clientdata(client);
 	int val = simple_strtol(buf, NULL, 10);
@@ -383,42 +393,23 @@
 	return count;
 }
 #define show_temp_offset(offset)					\
-static ssize_t show_temp_##offset (struct device *dev, char *buf)	\
-{									\
-	return show_temp(dev, buf, offset - 1);				\
-}									\
-static ssize_t								\
-show_temp_##offset##_max (struct device *dev, char *buf)		\
-{									\
-	return show_temp_max(dev, buf, offset - 1);			\
-}									\
-static ssize_t								\
-show_temp_##offset##_min (struct device *dev, char *buf)		\
-{									\
-	return show_temp_min(dev, buf, offset - 1);			\
-}									\
-static ssize_t set_temp_##offset##_max (struct device *dev, 		\
-		const char *buf, size_t count) 				\
-{									\
-	return set_temp_max(dev, buf, count, offset - 1);		\
-}									\
-static ssize_t set_temp_##offset##_min (struct device *dev, 		\
-		const char *buf, size_t count) 				\
-{									\
-	return set_temp_min(dev, buf, count, offset - 1);		\
-}									\
-static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL); \
-static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, 		\
-		show_temp_##offset##_max, set_temp_##offset##_max); 	\
-static DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, 		\
-		show_temp_##offset##_min, set_temp_##offset##_min);	
+static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO,		\
+		show_temp, NULL, offset - 1);				\
+static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,	\
+		show_temp_max, set_temp_max, offset - 1);		\
+static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,	\
+		show_temp_min, set_temp_min, offset - 1);
 
 show_temp_offset(1);
 show_temp_offset(2);
 show_temp_offset(3);
 
-static ssize_t show_sensor(struct device *dev, char *buf, int nr)
+static ssize_t show_sensor(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 it87_data *data = it87_update_device(dev);
 	u8 reg = data->sensor; /* In case the value is updated while we use it */
 	
@@ -428,9 +419,12 @@
 		return sprintf(buf, "2\n");  /* thermistor */
 	return sprintf(buf, "0\n");      /* disabled */
 }
-static ssize_t set_sensor(struct device *dev, const char *buf, 
-		size_t count, int nr)
+static ssize_t set_sensor(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 it87_data *data = i2c_get_clientdata(client);
 	int val = simple_strtol(buf, NULL, 10);
@@ -453,53 +447,67 @@
 	return count;
 }
 #define show_sensor_offset(offset)					\
-static ssize_t show_sensor_##offset (struct device *dev, char *buf)	\
-{									\
-	return show_sensor(dev, buf, offset - 1);			\
-}									\
-static ssize_t set_sensor_##offset (struct device *dev, 		\
-		const char *buf, size_t count) 				\
-{									\
-	return set_sensor(dev, buf, count, offset - 1);			\
-}									\
-static DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, 		\
-		show_sensor_##offset, set_sensor_##offset);
+static SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR,	\
+		show_sensor, set_sensor, offset - 1);
 
 show_sensor_offset(1);
 show_sensor_offset(2);
 show_sensor_offset(3);
 
 /* 3 Fans */
-static ssize_t show_fan(struct device *dev, char *buf, int nr)
+static ssize_t show_fan(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 it87_data *data = it87_update_device(dev);
 	return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr], 
 				DIV_FROM_REG(data->fan_div[nr])));
 }
-static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_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 it87_data *data = it87_update_device(dev);
 	return sprintf(buf,"%d\n",
 		FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])));
 }
-static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
+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 it87_data *data = it87_update_device(dev);
 	return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
 }
-static ssize_t show_pwm_enable(struct device *dev, char *buf, int nr)
+static ssize_t show_pwm_enable(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 it87_data *data = it87_update_device(dev);
 	return sprintf(buf,"%d\n", (data->fan_main_ctrl & (1 << nr)) ? 1 : 0);
 }
-static ssize_t show_pwm(struct device *dev, char *buf, int nr)
+static ssize_t show_pwm(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 it87_data *data = it87_update_device(dev);
 	return sprintf(buf,"%d\n", data->manual_pwm_ctl[nr]);
 }
-static ssize_t set_fan_min(struct device *dev, const char *buf, 
-		size_t count, int nr)
+static ssize_t set_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);
+	int nr = sensor_attr->index;
+
 	struct i2c_client *client = to_i2c_client(dev);
 	struct it87_data *data = i2c_get_clientdata(client);
 	int val = simple_strtol(buf, NULL, 10);
@@ -510,9 +518,12 @@
 	up(&data->update_lock);
 	return count;
 }
-static ssize_t set_fan_div(struct device *dev, const char *buf, 
-		size_t count, int nr)
+static ssize_t set_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);
+	int nr = sensor_attr->index;
+
 	struct i2c_client *client = to_i2c_client(dev);
 	struct it87_data *data = i2c_get_clientdata(client);
 	int val = simple_strtol(buf, NULL, 10);
@@ -550,9 +561,12 @@
 	up(&data->update_lock);
 	return count;
 }
-static ssize_t set_pwm_enable(struct device *dev, const char *buf,
-		size_t count, int nr)
+static ssize_t set_pwm_enable(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 it87_data *data = i2c_get_clientdata(client);
 	int val = simple_strtol(buf, NULL, 10);
@@ -581,9 +595,12 @@
 	up(&data->update_lock);
 	return count;
 }
-static ssize_t set_pwm(struct device *dev, const char *buf,
-		size_t count, int nr)
+static ssize_t set_pwm(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 it87_data *data = i2c_get_clientdata(client);
 	int val = simple_strtol(buf, NULL, 10);
@@ -599,85 +616,44 @@
 	return count;
 }
 
-#define show_fan_offset(offset)						\
-static ssize_t show_fan_##offset (struct device *dev, char *buf)	\
-{									\
-	return show_fan(dev, buf, offset - 1);				\
-}									\
-static ssize_t show_fan_##offset##_min (struct device *dev, char *buf)	\
-{									\
-	return show_fan_min(dev, buf, offset - 1);			\
-}									\
-static ssize_t show_fan_##offset##_div (struct device *dev, char *buf)	\
-{									\
-	return show_fan_div(dev, buf, offset - 1);			\
-}									\
-static ssize_t set_fan_##offset##_min (struct device *dev, 		\
-	const char *buf, size_t count) 					\
-{									\
-	return set_fan_min(dev, buf, count, offset - 1);		\
-}									\
-static ssize_t set_fan_##offset##_div (struct device *dev, 		\
-		const char *buf, size_t count) 				\
-{									\
-	return set_fan_div(dev, buf, count, offset - 1);		\
-}									\
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL); \
-static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, 		\
-		show_fan_##offset##_min, set_fan_##offset##_min); 	\
-static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, 		\
-		show_fan_##offset##_div, set_fan_##offset##_div);
+#define show_fan_offset(offset)					\
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,		\
+		show_fan, NULL, offset - 1);			\
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
+		show_fan_min, set_fan_min, offset - 1);		\
+static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
+		show_fan_div, set_fan_div, offset - 1);
 
 show_fan_offset(1);
 show_fan_offset(2);
 show_fan_offset(3);
 
 #define show_pwm_offset(offset)						\
-static ssize_t show_pwm##offset##_enable (struct device *dev,		\
-	char *buf)							\
-{									\
-	return show_pwm_enable(dev, buf, offset - 1);			\
-}									\
-static ssize_t show_pwm##offset (struct device *dev, char *buf)		\
-{									\
-	return show_pwm(dev, buf, offset - 1);				\
-}									\
-static ssize_t set_pwm##offset##_enable (struct device *dev,		\
-		const char *buf, size_t count)				\
-{									\
-	return set_pwm_enable(dev, buf, count, offset - 1);		\
-}									\
-static ssize_t set_pwm##offset (struct device *dev,			\
-		const char *buf, size_t count)				\
-{									\
-	return set_pwm(dev, buf, count, offset - 1);			\
-}									\
-static DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR,		\
-		show_pwm##offset##_enable,				\
-		set_pwm##offset##_enable);				\
-static DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR,			\
-		show_pwm##offset , set_pwm##offset );
+static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR,	\
+		show_pwm_enable, set_pwm_enable, offset - 1);		\
+static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR,		\
+		show_pwm, set_pwm, offset - 1);
 
 show_pwm_offset(1);
 show_pwm_offset(2);
 show_pwm_offset(3);
 
 /* Alarms */
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct it87_data *data = it87_update_device(dev);
-	return sprintf(buf,"%d\n", ALARMS_FROM_REG(data->alarms));
+	return sprintf(buf, "%u\n", data->alarms);
 }
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
 static ssize_t
-show_vrm_reg(struct device *dev, char *buf)
+show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct it87_data *data = it87_update_device(dev);
 	return sprintf(buf, "%ld\n", (long) data->vrm);
 }
 static ssize_t
-store_vrm_reg(struct device *dev, const char *buf, size_t count)
+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 it87_data *data = i2c_get_clientdata(client);
@@ -693,7 +669,7 @@
 device_create_file(&client->dev, &dev_attr_vrm)
 
 static ssize_t
-show_vid_reg(struct device *dev, char *buf)
+show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct it87_data *data = it87_update_device(dev);
 	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
@@ -864,60 +840,60 @@
 	it87_init_client(new_client, data);
 
 	/* Register sysfs hooks */
-	device_create_file(&new_client->dev, &dev_attr_in0_input);
-	device_create_file(&new_client->dev, &dev_attr_in1_input);
-	device_create_file(&new_client->dev, &dev_attr_in2_input);
-	device_create_file(&new_client->dev, &dev_attr_in3_input);
-	device_create_file(&new_client->dev, &dev_attr_in4_input);
-	device_create_file(&new_client->dev, &dev_attr_in5_input);
-	device_create_file(&new_client->dev, &dev_attr_in6_input);
-	device_create_file(&new_client->dev, &dev_attr_in7_input);
-	device_create_file(&new_client->dev, &dev_attr_in8_input);
-	device_create_file(&new_client->dev, &dev_attr_in0_min);
-	device_create_file(&new_client->dev, &dev_attr_in1_min);
-	device_create_file(&new_client->dev, &dev_attr_in2_min);
-	device_create_file(&new_client->dev, &dev_attr_in3_min);
-	device_create_file(&new_client->dev, &dev_attr_in4_min);
-	device_create_file(&new_client->dev, &dev_attr_in5_min);
-	device_create_file(&new_client->dev, &dev_attr_in6_min);
-	device_create_file(&new_client->dev, &dev_attr_in7_min);
-	device_create_file(&new_client->dev, &dev_attr_in0_max);
-	device_create_file(&new_client->dev, &dev_attr_in1_max);
-	device_create_file(&new_client->dev, &dev_attr_in2_max);
-	device_create_file(&new_client->dev, &dev_attr_in3_max);
-	device_create_file(&new_client->dev, &dev_attr_in4_max);
-	device_create_file(&new_client->dev, &dev_attr_in5_max);
-	device_create_file(&new_client->dev, &dev_attr_in6_max);
-	device_create_file(&new_client->dev, &dev_attr_in7_max);
-	device_create_file(&new_client->dev, &dev_attr_temp1_input);
-	device_create_file(&new_client->dev, &dev_attr_temp2_input);
-	device_create_file(&new_client->dev, &dev_attr_temp3_input);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max);
-	device_create_file(&new_client->dev, &dev_attr_temp2_max);
-	device_create_file(&new_client->dev, &dev_attr_temp3_max);
-	device_create_file(&new_client->dev, &dev_attr_temp1_min);
-	device_create_file(&new_client->dev, &dev_attr_temp2_min);
-	device_create_file(&new_client->dev, &dev_attr_temp3_min);
-	device_create_file(&new_client->dev, &dev_attr_temp1_type);
-	device_create_file(&new_client->dev, &dev_attr_temp2_type);
-	device_create_file(&new_client->dev, &dev_attr_temp3_type);
-	device_create_file(&new_client->dev, &dev_attr_fan1_input);
-	device_create_file(&new_client->dev, &dev_attr_fan2_input);
-	device_create_file(&new_client->dev, &dev_attr_fan3_input);
-	device_create_file(&new_client->dev, &dev_attr_fan1_min);
-	device_create_file(&new_client->dev, &dev_attr_fan2_min);
-	device_create_file(&new_client->dev, &dev_attr_fan3_min);
-	device_create_file(&new_client->dev, &dev_attr_fan1_div);
-	device_create_file(&new_client->dev, &dev_attr_fan2_div);
-	device_create_file(&new_client->dev, &dev_attr_fan3_div);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in3_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in4_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in5_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in6_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in7_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in8_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in1_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in2_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in3_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in5_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in6_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in7_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in1_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in2_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in3_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in4_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in5_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in6_max.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_in7_max.dev_attr);
+	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_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_temp1_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_temp2_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_temp3_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_temp1_type.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_temp2_type.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_temp3_type.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan1_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan2_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan3_input.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan1_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan2_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan3_min.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan1_div.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan2_div.dev_attr);
+	device_create_file(&new_client->dev, &sensor_dev_attr_fan3_div.dev_attr);
 	device_create_file(&new_client->dev, &dev_attr_alarms);
 	if (enable_pwm_interface) {
-		device_create_file(&new_client->dev, &dev_attr_pwm1_enable);
-		device_create_file(&new_client->dev, &dev_attr_pwm2_enable);
-		device_create_file(&new_client->dev, &dev_attr_pwm3_enable);
-		device_create_file(&new_client->dev, &dev_attr_pwm1);
-		device_create_file(&new_client->dev, &dev_attr_pwm2);
-		device_create_file(&new_client->dev, &dev_attr_pwm3);
+		device_create_file(&new_client->dev, &sensor_dev_attr_pwm1_enable.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_pwm2_enable.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_pwm3_enable.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_pwm1.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_pwm2.dev_attr);
+		device_create_file(&new_client->dev, &sensor_dev_attr_pwm3.dev_attr);
 	}
 
 	if (data->type == it8712) {
@@ -954,7 +930,7 @@
 	return 0;
 }
 
-/* The SMBus locks itself, but ISA access must be locked explicitely! 
+/* The SMBus locks itself, but ISA access must be locked explicitly! 
    We don't want to lock the whole ISA bus, so we lock each client
    separately.
    We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
@@ -974,7 +950,7 @@
 		return i2c_smbus_read_byte_data(client, reg);
 }
 
-/* The SMBus locks itself, but ISA access muse be locked explicitely! 
+/* The SMBus locks itself, but ISA access muse be locked explicitly! 
    We don't want to lock the whole ISA bus, so we lock each client
    separately.
    We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
diff --git a/drivers/i2c/chips/lm63.c b/drivers/i2c/chips/lm63.c
index 14cc5af..7c6f9ea 100644
--- a/drivers/i2c/chips/lm63.c
+++ b/drivers/i2c/chips/lm63.c
@@ -1,7 +1,7 @@
 /*
  * lm63.c - driver for the National Semiconductor LM63 temperature sensor
  *          with integrated fan control
- * Copyright (C) 2004  Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2004-2005  Jean Delvare <khali@linux-fr.org>
  * Based on the lm90 driver.
  *
  * The LM63 is a sensor chip made by National Semiconductor. It measures
@@ -37,13 +37,13 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
+#include <linux/hwmon-sysfs.h>
 
 /*
  * Addresses to scan
@@ -99,9 +99,9 @@
  * Conversions and various macros
  * For tachometer counts, the LM63 uses 16-bit values.
  * For local temperature and high limit, remote critical limit and hysteresis
- * value, it uses signed 8-bit values with LSB = 1 degree Celcius.
+ * value, it uses signed 8-bit values with LSB = 1 degree Celsius.
  * For remote temperature, low and high limits, it uses signed 11-bit values
- * with LSB = 0.125 degree Celcius, left-justified in 16-bit registers.
+ * with LSB = 0.125 degree Celsius, left-justified in 16-bit registers.
  */
 
 #define FAN_FROM_REG(reg)	((reg) == 0xFFFC || (reg) == 0 ? 0 : \
@@ -158,16 +158,16 @@
 
 	/* registers values */
 	u8 config, config_fan;
-	u16 fan1_input;
-	u16 fan1_low;
+	u16 fan[2];	/* 0: input
+			   1: low limit */
 	u8 pwm1_freq;
 	u8 pwm1_value;
-	s8 temp1_input;
-	s8 temp1_high;
-	s16 temp2_input;
-	s16 temp2_high;
-	s16 temp2_low;
-	s8 temp2_crit;
+	s8 temp8[3];	/* 0: local input
+			   1: local high limit
+			   2: remote critical limit */
+	s16 temp11[3];	/* 0: remote input
+			   1: remote low limit
+			   2: remote high limit */
 	u8 temp2_crit_hyst;
 	u8 alarms;
 };
@@ -176,33 +176,33 @@
  * Sysfs callback functions and files
  */
 
-#define show_fan(value) \
-static ssize_t show_##value(struct device *dev, char *buf) \
-{ \
-	struct lm63_data *data = lm63_update_device(dev); \
-	return sprintf(buf, "%d\n", FAN_FROM_REG(data->value)); \
+static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
+			char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct lm63_data *data = lm63_update_device(dev);
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[attr->index]));
 }
-show_fan(fan1_input);
-show_fan(fan1_low);
 
-static ssize_t set_fan1_low(struct device *dev, const char *buf,
-	size_t count)
+static ssize_t set_fan(struct device *dev, struct device_attribute *dummy,
+		       const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm63_data *data = i2c_get_clientdata(client);
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 
 	down(&data->update_lock);
-	data->fan1_low = FAN_TO_REG(val);
+	data->fan[1] = FAN_TO_REG(val);
 	i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_LSB,
-				  data->fan1_low & 0xFF);
+				  data->fan[1] & 0xFF);
 	i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_MSB,
-				  data->fan1_low >> 8);
+				  data->fan[1] >> 8);
 	up(&data->update_lock);
 	return count;
 }
 
-static ssize_t show_pwm1(struct device *dev, char *buf)
+static ssize_t show_pwm1(struct device *dev, struct device_attribute *dummy,
+			 char *buf)
 {
 	struct lm63_data *data = lm63_update_device(dev);
 	return sprintf(buf, "%d\n", data->pwm1_value >= 2 * data->pwm1_freq ?
@@ -210,7 +210,8 @@
 		       (2 * data->pwm1_freq));
 }
 
-static ssize_t set_pwm1(struct device *dev, const char *buf, size_t count)
+static ssize_t set_pwm1(struct device *dev, struct device_attribute *dummy,
+			const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm63_data *data = i2c_get_clientdata(client);
@@ -229,77 +230,83 @@
 	return count;
 }
 
-static ssize_t show_pwm1_enable(struct device *dev, char *buf)
+static ssize_t show_pwm1_enable(struct device *dev, struct device_attribute *dummy,
+				char *buf)
 {
 	struct lm63_data *data = lm63_update_device(dev);
 	return sprintf(buf, "%d\n", data->config_fan & 0x20 ? 1 : 2);
 }
 
-#define show_temp8(value) \
-static ssize_t show_##value(struct device *dev, char *buf) \
-{ \
-	struct lm63_data *data = lm63_update_device(dev); \
-	return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->value)); \
+static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr,
+			  char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct lm63_data *data = lm63_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[attr->index]));
 }
-#define show_temp11(value) \
-static ssize_t show_##value(struct device *dev, char *buf) \
-{ \
-	struct lm63_data *data = lm63_update_device(dev); \
-	return sprintf(buf, "%d\n", TEMP11_FROM_REG(data->value)); \
-}
-show_temp8(temp1_input);
-show_temp8(temp1_high);
-show_temp11(temp2_input);
-show_temp11(temp2_high);
-show_temp11(temp2_low);
-show_temp8(temp2_crit);
 
-#define set_temp8(value, reg) \
-static ssize_t set_##value(struct device *dev, const char *buf, \
-	size_t count) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct lm63_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtol(buf, NULL, 10); \
- \
-	down(&data->update_lock); \
-	data->value = TEMP8_TO_REG(val); \
-	i2c_smbus_write_byte_data(client, reg, data->value); \
-	up(&data->update_lock); \
-	return count; \
+static ssize_t set_temp8(struct device *dev, struct device_attribute *dummy,
+			 const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm63_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+
+	down(&data->update_lock);
+	data->temp8[1] = TEMP8_TO_REG(val);
+	i2c_smbus_write_byte_data(client, LM63_REG_LOCAL_HIGH, data->temp8[1]);
+	up(&data->update_lock);
+	return count;
 }
-#define set_temp11(value, reg_msb, reg_lsb) \
-static ssize_t set_##value(struct device *dev, const char *buf, \
-	size_t count) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct lm63_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtol(buf, NULL, 10); \
- \
-	down(&data->update_lock); \
-	data->value = TEMP11_TO_REG(val); \
-	i2c_smbus_write_byte_data(client, reg_msb, data->value >> 8); \
-	i2c_smbus_write_byte_data(client, reg_lsb, data->value & 0xff); \
-	up(&data->update_lock); \
-	return count; \
+
+static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr,
+			   char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct lm63_data *data = lm63_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP11_FROM_REG(data->temp11[attr->index]));
 }
-set_temp8(temp1_high, LM63_REG_LOCAL_HIGH);
-set_temp11(temp2_high, LM63_REG_REMOTE_HIGH_MSB, LM63_REG_REMOTE_HIGH_LSB);
-set_temp11(temp2_low, LM63_REG_REMOTE_LOW_MSB, LM63_REG_REMOTE_LOW_LSB);
+
+static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
+			  const char *buf, size_t count)
+{
+	static const u8 reg[4] = {
+		LM63_REG_REMOTE_LOW_MSB,
+		LM63_REG_REMOTE_LOW_LSB,
+		LM63_REG_REMOTE_HIGH_MSB,
+		LM63_REG_REMOTE_HIGH_LSB,
+	};
+
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm63_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+	int nr = attr->index;
+
+	down(&data->update_lock);
+	data->temp11[nr] = TEMP11_TO_REG(val);
+	i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2],
+				  data->temp11[nr] >> 8);
+	i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1],
+				  data->temp11[nr] & 0xff);
+	up(&data->update_lock);
+	return count;
+}
 
 /* Hysteresis register holds a relative value, while we want to present
    an absolute to user-space */
-static ssize_t show_temp2_crit_hyst(struct device *dev, char *buf)
+static ssize_t show_temp2_crit_hyst(struct device *dev, struct device_attribute *dummy,
+				    char *buf)
 {
 	struct lm63_data *data = lm63_update_device(dev);
-	return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp2_crit)
+	return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[2])
 		       - TEMP8_FROM_REG(data->temp2_crit_hyst));
 }
 
 /* And now the other way around, user-space provides an absolute
    hysteresis value and we have to store a relative one */
-static ssize_t set_temp2_crit_hyst(struct device *dev, const char *buf,
-	size_t count)
+static ssize_t set_temp2_crit_hyst(struct device *dev, struct device_attribute *dummy,
+				   const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm63_data *data = i2c_get_clientdata(client);
@@ -307,36 +314,37 @@
 	long hyst;
 
 	down(&data->update_lock);
-	hyst = TEMP8_FROM_REG(data->temp2_crit) - val;
+	hyst = TEMP8_FROM_REG(data->temp8[2]) - val;
 	i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST,
 				  HYST_TO_REG(hyst));
 	up(&data->update_lock);
 	return count;
 }
 
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
+			   char *buf)
 {
 	struct lm63_data *data = lm63_update_device(dev);
 	return sprintf(buf, "%u\n", data->alarms);
 }
 
-static DEVICE_ATTR(fan1_input, S_IRUGO, show_fan1_input, NULL);
-static DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan1_low,
-	set_fan1_low);
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan,
+	set_fan, 1);
 
 static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1);
 static DEVICE_ATTR(pwm1_enable, S_IRUGO, show_pwm1_enable, NULL);
 
-static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1_input, NULL);
-static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp1_high,
-	set_temp1_high);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp8, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp8,
+	set_temp8, 1);
 
-static DEVICE_ATTR(temp2_input, S_IRUGO, show_temp2_input, NULL);
-static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp2_low,
-	set_temp2_low);
-static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp2_high,
-	set_temp2_high);
-static DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp2_crit, NULL);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11,
+	set_temp11, 1);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11,
+	set_temp11, 2);
+static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp8, NULL, 2);
 static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst,
 	set_temp2_crit_hyst);
 
@@ -430,17 +438,25 @@
 
 	/* Register sysfs hooks */
 	if (data->config & 0x04) { /* tachometer enabled */
-		device_create_file(&new_client->dev, &dev_attr_fan1_input);
-		device_create_file(&new_client->dev, &dev_attr_fan1_min);
+		device_create_file(&new_client->dev,
+				   &sensor_dev_attr_fan1_input.dev_attr);
+		device_create_file(&new_client->dev,
+				   &sensor_dev_attr_fan1_min.dev_attr);
 	}
 	device_create_file(&new_client->dev, &dev_attr_pwm1);
 	device_create_file(&new_client->dev, &dev_attr_pwm1_enable);
-	device_create_file(&new_client->dev, &dev_attr_temp1_input);
-	device_create_file(&new_client->dev, &dev_attr_temp2_input);
-	device_create_file(&new_client->dev, &dev_attr_temp2_min);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max);
-	device_create_file(&new_client->dev, &dev_attr_temp2_max);
-	device_create_file(&new_client->dev, &dev_attr_temp2_crit);
+	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_temp2_min.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_temp2_crit.dev_attr);
 	device_create_file(&new_client->dev, &dev_attr_temp2_crit_hyst);
 	device_create_file(&new_client->dev, &dev_attr_alarms);
 
@@ -511,14 +527,14 @@
 	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
 		if (data->config & 0x04) { /* tachometer enabled  */
 			/* order matters for fan1_input */
-			data->fan1_input = i2c_smbus_read_byte_data(client,
-					   LM63_REG_TACH_COUNT_LSB) & 0xFC;
-			data->fan1_input |= i2c_smbus_read_byte_data(client,
-					    LM63_REG_TACH_COUNT_MSB) << 8;
-			data->fan1_low = (i2c_smbus_read_byte_data(client,
-					  LM63_REG_TACH_LIMIT_LSB) & 0xFC)
-				       | (i2c_smbus_read_byte_data(client,
-					  LM63_REG_TACH_LIMIT_MSB) << 8);
+			data->fan[0] = i2c_smbus_read_byte_data(client,
+				       LM63_REG_TACH_COUNT_LSB) & 0xFC;
+			data->fan[0] |= i2c_smbus_read_byte_data(client,
+					LM63_REG_TACH_COUNT_MSB) << 8;
+			data->fan[1] = (i2c_smbus_read_byte_data(client,
+					LM63_REG_TACH_LIMIT_LSB) & 0xFC)
+				     | (i2c_smbus_read_byte_data(client,
+					LM63_REG_TACH_LIMIT_MSB) << 8);
 		}
 
 		data->pwm1_freq = i2c_smbus_read_byte_data(client,
@@ -528,26 +544,26 @@
 		data->pwm1_value = i2c_smbus_read_byte_data(client,
 				   LM63_REG_PWM_VALUE);
 
-		data->temp1_input = i2c_smbus_read_byte_data(client,
-				    LM63_REG_LOCAL_TEMP);
-		data->temp1_high = i2c_smbus_read_byte_data(client,
-				   LM63_REG_LOCAL_HIGH);
+		data->temp8[0] = i2c_smbus_read_byte_data(client,
+				 LM63_REG_LOCAL_TEMP);
+		data->temp8[1] = i2c_smbus_read_byte_data(client,
+				 LM63_REG_LOCAL_HIGH);
 
 		/* order matters for temp2_input */
-		data->temp2_input = i2c_smbus_read_byte_data(client,
-				    LM63_REG_REMOTE_TEMP_MSB) << 8;
-		data->temp2_input |= i2c_smbus_read_byte_data(client,
-				     LM63_REG_REMOTE_TEMP_LSB);
-		data->temp2_high = (i2c_smbus_read_byte_data(client,
-				   LM63_REG_REMOTE_HIGH_MSB) << 8)
-				 | i2c_smbus_read_byte_data(client,
-				   LM63_REG_REMOTE_HIGH_LSB);
-		data->temp2_low = (i2c_smbus_read_byte_data(client,
+		data->temp11[0] = i2c_smbus_read_byte_data(client,
+				  LM63_REG_REMOTE_TEMP_MSB) << 8;
+		data->temp11[0] |= i2c_smbus_read_byte_data(client,
+				   LM63_REG_REMOTE_TEMP_LSB);
+		data->temp11[1] = (i2c_smbus_read_byte_data(client,
 				  LM63_REG_REMOTE_LOW_MSB) << 8)
 				| i2c_smbus_read_byte_data(client,
 				  LM63_REG_REMOTE_LOW_LSB);
-		data->temp2_crit = i2c_smbus_read_byte_data(client,
-				   LM63_REG_REMOTE_TCRIT);
+		data->temp11[2] = (i2c_smbus_read_byte_data(client,
+				  LM63_REG_REMOTE_HIGH_MSB) << 8)
+				| i2c_smbus_read_byte_data(client,
+				  LM63_REG_REMOTE_HIGH_LSB);
+		data->temp8[2] = i2c_smbus_read_byte_data(client,
+				 LM63_REG_REMOTE_TCRIT);
 		data->temp2_crit_hyst = i2c_smbus_read_byte_data(client,
 					LM63_REG_REMOTE_TCRIT_HYST);
 
diff --git a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c
index 0e86cc8..5be164e 100644
--- a/drivers/i2c/chips/lm75.c
+++ b/drivers/i2c/chips/lm75.c
@@ -18,7 +18,6 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -75,7 +74,7 @@
 };
 
 #define show(value)	\
-static ssize_t show_##value(struct device *dev, char *buf)		\
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf)		\
 {									\
 	struct lm75_data *data = lm75_update_device(dev);		\
 	return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->value));	\
@@ -85,7 +84,7 @@
 show(temp_input);
 
 #define set(value, reg)	\
-static ssize_t set_##value(struct device *dev, const char *buf, size_t count)	\
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)	\
 {								\
 	struct i2c_client *client = to_i2c_client(dev);		\
 	struct lm75_data *data = i2c_get_clientdata(client);	\
diff --git a/drivers/i2c/chips/lm77.c b/drivers/i2c/chips/lm77.c
index f56b7a3..b98f449 100644
--- a/drivers/i2c/chips/lm77.c
+++ b/drivers/i2c/chips/lm77.c
@@ -25,7 +25,6 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -103,7 +102,7 @@
 
 /* read routines for temperature limits */
 #define show(value)	\
-static ssize_t show_##value(struct device *dev, char *buf)	\
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf)	\
 {								\
 	struct lm77_data *data = lm77_update_device(dev);	\
 	return sprintf(buf, "%d\n", data->value);		\
@@ -116,17 +115,17 @@
 show(alarms);
 
 /* read routines for hysteresis values */
-static ssize_t show_temp_crit_hyst(struct device *dev, char *buf)
+static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm77_data *data = lm77_update_device(dev);
 	return sprintf(buf, "%d\n", data->temp_crit - data->temp_hyst);
 }
-static ssize_t show_temp_min_hyst(struct device *dev, char *buf)
+static ssize_t show_temp_min_hyst(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm77_data *data = lm77_update_device(dev);
 	return sprintf(buf, "%d\n", data->temp_min + data->temp_hyst);
 }
-static ssize_t show_temp_max_hyst(struct device *dev, char *buf)
+static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm77_data *data = lm77_update_device(dev);
 	return sprintf(buf, "%d\n", data->temp_max - data->temp_hyst);
@@ -134,7 +133,7 @@
 
 /* write routines */
 #define set(value, reg)	\
-static ssize_t set_##value(struct device *dev, const char *buf, size_t count)	\
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)	\
 {										\
 	struct i2c_client *client = to_i2c_client(dev);				\
 	struct lm77_data *data = i2c_get_clientdata(client);			\
@@ -152,7 +151,7 @@
 
 /* hysteresis is stored as a relative value on the chip, so it has to be
    converted first */
-static ssize_t set_temp_crit_hyst(struct device *dev, const char *buf, size_t count)
+static ssize_t set_temp_crit_hyst(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm77_data *data = i2c_get_clientdata(client);
@@ -167,7 +166,7 @@
 }
 
 /* preserve hysteresis when setting T_crit */
-static ssize_t set_temp_crit(struct device *dev, const char *buf, size_t count)
+static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm77_data *data = i2c_get_clientdata(client);
diff --git a/drivers/i2c/chips/lm78.c b/drivers/i2c/chips/lm78.c
index 6d52d14..2924146 100644
--- a/drivers/i2c/chips/lm78.c
+++ b/drivers/i2c/chips/lm78.c
@@ -18,7 +18,6 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -224,28 +223,28 @@
 	
 #define show_in_offset(offset)					\
 static ssize_t							\
-	show_in##offset (struct device *dev, char *buf)		\
+	show_in##offset (struct device *dev, struct device_attribute *attr, char *buf)		\
 {								\
 	return show_in(dev, buf, offset);			\
 }								\
 static DEVICE_ATTR(in##offset##_input, S_IRUGO, 		\
 		show_in##offset, NULL);				\
 static ssize_t							\
-	show_in##offset##_min (struct device *dev, char *buf)   \
+	show_in##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)   \
 {								\
 	return show_in_min(dev, buf, offset);			\
 }								\
 static ssize_t							\
-	show_in##offset##_max (struct device *dev, char *buf)   \
+	show_in##offset##_max (struct device *dev, struct device_attribute *attr, char *buf)   \
 {								\
 	return show_in_max(dev, buf, offset);			\
 }								\
-static ssize_t set_in##offset##_min (struct device *dev,	\
+static ssize_t set_in##offset##_min (struct device *dev, struct device_attribute *attr,	\
 		const char *buf, size_t count)			\
 {								\
 	return set_in_min(dev, buf, count, offset);		\
 }								\
-static ssize_t set_in##offset##_max (struct device *dev,	\
+static ssize_t set_in##offset##_max (struct device *dev, struct device_attribute *attr,	\
 		const char *buf, size_t count)			\
 {								\
 	return set_in_max(dev, buf, count, offset);		\
@@ -264,19 +263,19 @@
 show_in_offset(6);
 
 /* Temperature */
-static ssize_t show_temp(struct device *dev, char *buf)
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm78_data *data = lm78_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp));
 }
 
-static ssize_t show_temp_over(struct device *dev, char *buf)
+static ssize_t show_temp_over(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm78_data *data = lm78_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over));
 }
 
-static ssize_t set_temp_over(struct device *dev, const char *buf, size_t count)
+static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm78_data *data = i2c_get_clientdata(client);
@@ -289,13 +288,13 @@
 	return count;
 }
 
-static ssize_t show_temp_hyst(struct device *dev, char *buf)
+static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm78_data *data = lm78_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_hyst));
 }
 
-static ssize_t set_temp_hyst(struct device *dev, const char *buf, size_t count)
+static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm78_data *data = i2c_get_clientdata(client);
@@ -398,19 +397,19 @@
 }
 
 #define show_fan_offset(offset)						\
-static ssize_t show_fan_##offset (struct device *dev, char *buf)	\
+static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return show_fan(dev, buf, offset - 1);				\
 }									\
-static ssize_t show_fan_##offset##_min (struct device *dev, char *buf)  \
+static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)  \
 {									\
 	return show_fan_min(dev, buf, offset - 1);			\
 }									\
-static ssize_t show_fan_##offset##_div (struct device *dev, char *buf)  \
+static ssize_t show_fan_##offset##_div (struct device *dev, struct device_attribute *attr, char *buf)  \
 {									\
 	return show_fan_div(dev, buf, offset - 1);			\
 }									\
-static ssize_t set_fan_##offset##_min (struct device *dev,		\
+static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr,		\
 		const char *buf, size_t count)				\
 {									\
 	return set_fan_min(dev, buf, count, offset - 1);		\
@@ -419,13 +418,13 @@
 static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
 		show_fan_##offset##_min, set_fan_##offset##_min);
 
-static ssize_t set_fan_1_div(struct device *dev, const char *buf,
+static ssize_t set_fan_1_div(struct device *dev, struct device_attribute *attr, const char *buf,
 		size_t count)
 {
 	return set_fan_div(dev, buf, count, 0) ;
 }
 
-static ssize_t set_fan_2_div(struct device *dev, const char *buf,
+static ssize_t set_fan_2_div(struct device *dev, struct device_attribute *attr, const char *buf,
 		size_t count)
 {
 	return set_fan_div(dev, buf, count, 1) ;
@@ -443,7 +442,7 @@
 static DEVICE_ATTR(fan3_div, S_IRUGO, show_fan_3_div, NULL);
 
 /* VID */
-static ssize_t show_vid(struct device *dev, char *buf)
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm78_data *data = lm78_update_device(dev);
 	return sprintf(buf, "%d\n", VID_FROM_REG(data->vid));
@@ -451,7 +450,7 @@
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
 
 /* Alarms */
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm78_data *data = lm78_update_device(dev);
 	return sprintf(buf, "%u\n", data->alarms);
@@ -671,7 +670,7 @@
 	return 0;
 }
 
-/* The SMBus locks itself, but ISA access must be locked explicitely! 
+/* The SMBus locks itself, but ISA access must be locked explicitly! 
    We don't want to lock the whole ISA bus, so we lock each client
    separately.
    We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks,
@@ -690,7 +689,7 @@
 		return i2c_smbus_read_byte_data(client, reg);
 }
 
-/* The SMBus locks itself, but ISA access muse be locked explicitely! 
+/* The SMBus locks itself, but ISA access muse be locked explicitly! 
    We don't want to lock the whole ISA bus, so we lock each client
    separately.
    We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks,
diff --git a/drivers/i2c/chips/lm80.c b/drivers/i2c/chips/lm80.c
index a72f431..8100595 100644
--- a/drivers/i2c/chips/lm80.c
+++ b/drivers/i2c/chips/lm80.c
@@ -21,7 +21,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -156,7 +155,7 @@
  */
 
 #define show_in(suffix, value) \
-static ssize_t show_in_##suffix(struct device *dev, char *buf) \
+static ssize_t show_in_##suffix(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct lm80_data *data = lm80_update_device(dev); \
 	return sprintf(buf, "%d\n", IN_FROM_REG(data->value)); \
@@ -184,7 +183,7 @@
 show_in(input6, in[6]);
 
 #define set_in(suffix, value, reg) \
-static ssize_t set_in_##suffix(struct device *dev, const char *buf, \
+static ssize_t set_in_##suffix(struct device *dev, struct device_attribute *attr, const char *buf, \
 	size_t count) \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
@@ -213,7 +212,7 @@
 set_in(max6, in_max[6], LM80_REG_IN_MAX(6));
 
 #define show_fan(suffix, value, div) \
-static ssize_t show_fan_##suffix(struct device *dev, char *buf) \
+static ssize_t show_fan_##suffix(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct lm80_data *data = lm80_update_device(dev); \
 	return sprintf(buf, "%d\n", FAN_FROM_REG(data->value, \
@@ -225,7 +224,7 @@
 show_fan(input2, fan[1], fan_div[1]);
 
 #define show_fan_div(suffix, value) \
-static ssize_t show_fan_div##suffix(struct device *dev, char *buf) \
+static ssize_t show_fan_div##suffix(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct lm80_data *data = lm80_update_device(dev); \
 	return sprintf(buf, "%d\n", DIV_FROM_REG(data->value)); \
@@ -234,7 +233,7 @@
 show_fan_div(2, fan_div[1]);
 
 #define set_fan(suffix, value, reg, div) \
-static ssize_t set_fan_##suffix(struct device *dev, const char *buf, \
+static ssize_t set_fan_##suffix(struct device *dev, struct device_attribute *attr, const char *buf, \
 	size_t count) \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
@@ -292,7 +291,7 @@
 }
 
 #define set_fan_div(number) \
-static ssize_t set_fan_div##number(struct device *dev, const char *buf, \
+static ssize_t set_fan_div##number(struct device *dev, struct device_attribute *attr, const char *buf, \
 	size_t count) \
 { \
 	return set_fan_div(dev, buf, count, number - 1); \
@@ -300,14 +299,14 @@
 set_fan_div(1);
 set_fan_div(2);
 
-static ssize_t show_temp_input1(struct device *dev, char *buf)
+static ssize_t show_temp_input1(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm80_data *data = lm80_update_device(dev);
 	return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp));
 }
 
 #define show_temp(suffix, value) \
-static ssize_t show_temp_##suffix(struct device *dev, char *buf) \
+static ssize_t show_temp_##suffix(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct lm80_data *data = lm80_update_device(dev); \
 	return sprintf(buf, "%d\n", TEMP_LIMIT_FROM_REG(data->value)); \
@@ -318,7 +317,7 @@
 show_temp(os_hyst, temp_os_hyst);
 
 #define set_temp(suffix, value, reg) \
-static ssize_t set_temp_##suffix(struct device *dev, const char *buf, \
+static ssize_t set_temp_##suffix(struct device *dev, struct device_attribute *attr, const char *buf, \
 	size_t count) \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
@@ -336,7 +335,7 @@
 set_temp(os_max, temp_os_max, LM80_REG_TEMP_OS_MAX);
 set_temp(os_hyst, temp_os_hyst, LM80_REG_TEMP_OS_HYST);
 
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm80_data *data = lm80_update_device(dev);
 	return sprintf(buf, "%u\n", data->alarms);
diff --git a/drivers/i2c/chips/lm83.c b/drivers/i2c/chips/lm83.c
index 3dafe60..a49008b 100644
--- a/drivers/i2c/chips/lm83.c
+++ b/drivers/i2c/chips/lm83.c
@@ -1,7 +1,7 @@
 /*
  * lm83.c - Part of lm_sensors, Linux kernel modules for hardware
  *          monitoring
- * Copyright (C) 2003  Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2003-2005  Jean Delvare <khali@linux-fr.org>
  *
  * Heavily inspired from the lm78, lm75 and adm1021 drivers. The LM83 is
  * a sensor chip made by National Semiconductor. It reports up to four
@@ -27,13 +27,13 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
+#include <linux/hwmon-sysfs.h>
 
 /*
  * Addresses to scan
@@ -81,7 +81,7 @@
 
 /*
  * Conversions and various macros
- * The LM83 uses signed 8-bit values with LSB = 1 degree Celcius.
+ * The LM83 uses signed 8-bit values with LSB = 1 degree Celsius.
  */
 
 #define TEMP_FROM_REG(val)	((val) * 1000)
@@ -94,21 +94,20 @@
 	LM83_REG_R_LOCAL_TEMP,
 	LM83_REG_R_REMOTE1_TEMP,
 	LM83_REG_R_REMOTE2_TEMP,
-	LM83_REG_R_REMOTE3_TEMP
-};
-
-static const u8 LM83_REG_R_HIGH[] = {
+	LM83_REG_R_REMOTE3_TEMP,
 	LM83_REG_R_LOCAL_HIGH,
 	LM83_REG_R_REMOTE1_HIGH,
 	LM83_REG_R_REMOTE2_HIGH,
-	LM83_REG_R_REMOTE3_HIGH
+	LM83_REG_R_REMOTE3_HIGH,
+	LM83_REG_R_TCRIT,
 };
 
 static const u8 LM83_REG_W_HIGH[] = {
 	LM83_REG_W_LOCAL_HIGH,
 	LM83_REG_W_REMOTE1_HIGH,
 	LM83_REG_W_REMOTE2_HIGH,
-	LM83_REG_W_REMOTE3_HIGH
+	LM83_REG_W_REMOTE3_HIGH,
+	LM83_REG_W_TCRIT,
 };
 
 /*
@@ -144,9 +143,9 @@
 	unsigned long last_updated; /* in jiffies */
 
 	/* registers values */
-	s8 temp_input[4];
-	s8 temp_high[4];
-	s8 temp_crit;
+	s8 temp[9];	/* 0..3: input 1-4,
+			   4..7: high limit 1-4,
+			   8   : critical limit */
 	u16 alarms; /* bitvector, combined */
 };
 
@@ -154,65 +153,55 @@
  * Sysfs stuff
  */
 
-#define show_temp(suffix, value) \
-static ssize_t show_temp_##suffix(struct device *dev, char *buf) \
-{ \
-	struct lm83_data *data = lm83_update_device(dev); \
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value)); \
+static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
+			 char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct lm83_data *data = lm83_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index]));
 }
-show_temp(input1, temp_input[0]);
-show_temp(input2, temp_input[1]);
-show_temp(input3, temp_input[2]);
-show_temp(input4, temp_input[3]);
-show_temp(high1, temp_high[0]);
-show_temp(high2, temp_high[1]);
-show_temp(high3, temp_high[2]);
-show_temp(high4, temp_high[3]);
-show_temp(crit, temp_crit);
 
-#define set_temp(suffix, value, reg) \
-static ssize_t set_temp_##suffix(struct device *dev, const char *buf, \
-	size_t count) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct lm83_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtol(buf, NULL, 10); \
- \
-	down(&data->update_lock); \
-	data->value = TEMP_TO_REG(val); \
-	i2c_smbus_write_byte_data(client, reg, data->value); \
-	up(&data->update_lock); \
-	return count; \
+static ssize_t set_temp(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 lm83_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+	int nr = attr->index;
+
+	down(&data->update_lock);
+	data->temp[nr] = TEMP_TO_REG(val);
+	i2c_smbus_write_byte_data(client, LM83_REG_W_HIGH[nr - 4],
+				  data->temp[nr]);
+	up(&data->update_lock);
+	return count;
 }
-set_temp(high1, temp_high[0], LM83_REG_W_LOCAL_HIGH);
-set_temp(high2, temp_high[1], LM83_REG_W_REMOTE1_HIGH);
-set_temp(high3, temp_high[2], LM83_REG_W_REMOTE2_HIGH);
-set_temp(high4, temp_high[3], LM83_REG_W_REMOTE3_HIGH);
-set_temp(crit, temp_crit, LM83_REG_W_TCRIT);
 
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
+			   char *buf)
 {
 	struct lm83_data *data = lm83_update_device(dev);
 	return sprintf(buf, "%d\n", data->alarms);
 }
 
-static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL);
-static DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input2, NULL);
-static DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_input3, NULL);
-static DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_input4, NULL);
-static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_high1,
-    set_temp_high1);
-static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_high2,
-    set_temp_high2);
-static DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp_high3,
-    set_temp_high3);
-static DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp_high4,
-    set_temp_high4);
-static DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL);
-static DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit, NULL);
-static DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_temp_crit,
-    set_temp_crit);
-static DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp_crit, NULL);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp,
+	set_temp, 4);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp,
+	set_temp, 5);
+static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp,
+	set_temp, 6);
+static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp,
+	set_temp, 7);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL, 8);
+static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp, NULL, 8);
+static SENSOR_DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_temp,
+	set_temp, 8);
+static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp, NULL, 8);
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
 /*
@@ -323,18 +312,30 @@
 	 */
 
 	/* Register sysfs hooks */
-	device_create_file(&new_client->dev, &dev_attr_temp1_input);
-	device_create_file(&new_client->dev, &dev_attr_temp2_input);
-	device_create_file(&new_client->dev, &dev_attr_temp3_input);
-	device_create_file(&new_client->dev, &dev_attr_temp4_input);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max);
-	device_create_file(&new_client->dev, &dev_attr_temp2_max);
-	device_create_file(&new_client->dev, &dev_attr_temp3_max);
-	device_create_file(&new_client->dev, &dev_attr_temp4_max);
-	device_create_file(&new_client->dev, &dev_attr_temp1_crit);
-	device_create_file(&new_client->dev, &dev_attr_temp2_crit);
-	device_create_file(&new_client->dev, &dev_attr_temp3_crit);
-	device_create_file(&new_client->dev, &dev_attr_temp4_crit);
+	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);
 
 	return 0;
@@ -370,16 +371,11 @@
 		int nr;
 
 		dev_dbg(&client->dev, "Updating lm83 data.\n");
-		for (nr = 0; nr < 4 ; nr++) {
-			data->temp_input[nr] =
+		for (nr = 0; nr < 9; nr++) {
+			data->temp[nr] =
 			    i2c_smbus_read_byte_data(client,
 			    LM83_REG_R_TEMP[nr]);
-			data->temp_high[nr] =
-			    i2c_smbus_read_byte_data(client,
-			    LM83_REG_R_HIGH[nr]);
 		}
-		data->temp_crit =
-		    i2c_smbus_read_byte_data(client, LM83_REG_R_TCRIT);
 		data->alarms =
 		    i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS1)
 		    + (i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS2)
diff --git a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c
index b1a0dc5..b4d7fd4 100644
--- a/drivers/i2c/chips/lm85.c
+++ b/drivers/i2c/chips/lm85.c
@@ -23,7 +23,6 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -285,8 +284,6 @@
 /* i2c-vid.h defines vid_from_reg() */
 #define VID_FROM_REG(val,vrm) (vid_from_reg((val),(vrm)))
 
-#define ALARMS_FROM_REG(val) (val)
-
 /* Unlike some other drivers we DO NOT set initial limits.  Use
  * the config file to set limits.  Some users have reported
  * motherboards shutting down when we set limits in a previous
@@ -426,15 +423,15 @@
 }
 
 #define show_fan_offset(offset)						\
-static ssize_t show_fan_##offset (struct device *dev, char *buf)	\
+static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return show_fan(dev, buf, offset - 1);				\
 }									\
-static ssize_t show_fan_##offset##_min (struct device *dev, char *buf)	\
+static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return show_fan_min(dev, buf, offset - 1);			\
 }									\
-static ssize_t set_fan_##offset##_min (struct device *dev, 		\
+static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr, 		\
 	const char *buf, size_t count) 					\
 {									\
 	return set_fan_min(dev, buf, count, offset - 1);		\
@@ -451,7 +448,7 @@
 
 /* vid, vrm, alarms */
 
-static ssize_t show_vid_reg(struct device *dev, char *buf)
+static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm85_data *data = lm85_update_device(dev);
 	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
@@ -459,13 +456,13 @@
 
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
 
-static ssize_t show_vrm_reg(struct device *dev, char *buf)
+static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm85_data *data = lm85_update_device(dev);
 	return sprintf(buf, "%ld\n", (long) data->vrm);
 }
 
-static ssize_t store_vrm_reg(struct device *dev, const char *buf, size_t count)
+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 lm85_data *data = i2c_get_clientdata(client);
@@ -478,10 +475,10 @@
 
 static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
 
-static ssize_t show_alarms_reg(struct device *dev, char *buf)
+static ssize_t show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm85_data *data = lm85_update_device(dev);
-	return sprintf(buf, "%ld\n", (long) ALARMS_FROM_REG(data->alarms));
+	return sprintf(buf, "%u\n", data->alarms);
 }
 
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
@@ -516,16 +513,16 @@
 }
 
 #define show_pwm_reg(offset)						\
-static ssize_t show_pwm_##offset (struct device *dev, char *buf)	\
+static ssize_t show_pwm_##offset (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return show_pwm(dev, buf, offset - 1);				\
 }									\
-static ssize_t set_pwm_##offset (struct device *dev,			\
+static ssize_t set_pwm_##offset (struct device *dev, struct device_attribute *attr,			\
 				 const char *buf, size_t count)		\
 {									\
 	return set_pwm(dev, buf, count, offset - 1);			\
 }									\
-static ssize_t show_pwm_enable##offset (struct device *dev, char *buf)	\
+static ssize_t show_pwm_enable##offset (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return show_pwm_enable(dev, buf, offset - 1);			\
 }									\
@@ -585,24 +582,24 @@
 	return count;
 }
 #define show_in_reg(offset)						\
-static ssize_t show_in_##offset (struct device *dev, char *buf)		\
+static ssize_t show_in_##offset (struct device *dev, struct device_attribute *attr, char *buf)		\
 {									\
 	return show_in(dev, buf, offset);				\
 }									\
-static ssize_t show_in_##offset##_min (struct device *dev, char *buf)	\
+static ssize_t show_in_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return show_in_min(dev, buf, offset);				\
 }									\
-static ssize_t show_in_##offset##_max (struct device *dev, char *buf)	\
+static ssize_t show_in_##offset##_max (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return show_in_max(dev, buf, offset);				\
 }									\
-static ssize_t set_in_##offset##_min (struct device *dev, 		\
+static ssize_t set_in_##offset##_min (struct device *dev, struct device_attribute *attr, 		\
 	const char *buf, size_t count) 					\
 {									\
 	return set_in_min(dev, buf, count, offset);			\
 }									\
-static ssize_t set_in_##offset##_max (struct device *dev, 		\
+static ssize_t set_in_##offset##_max (struct device *dev, struct device_attribute *attr, 		\
 	const char *buf, size_t count) 					\
 {									\
 	return set_in_max(dev, buf, count, offset);			\
@@ -666,24 +663,24 @@
 	return count;
 }
 #define show_temp_reg(offset)						\
-static ssize_t show_temp_##offset (struct device *dev, char *buf)	\
+static ssize_t show_temp_##offset (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return show_temp(dev, buf, offset - 1);				\
 }									\
-static ssize_t show_temp_##offset##_min (struct device *dev, char *buf)	\
+static ssize_t show_temp_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return show_temp_min(dev, buf, offset - 1);			\
 }									\
-static ssize_t show_temp_##offset##_max (struct device *dev, char *buf)	\
+static ssize_t show_temp_##offset##_max (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return show_temp_max(dev, buf, offset - 1);			\
 }									\
-static ssize_t set_temp_##offset##_min (struct device *dev, 		\
+static ssize_t set_temp_##offset##_min (struct device *dev, struct device_attribute *attr, 		\
 	const char *buf, size_t count) 					\
 {									\
 	return set_temp_min(dev, buf, count, offset - 1);		\
 }									\
-static ssize_t set_temp_##offset##_max (struct device *dev, 		\
+static ssize_t set_temp_##offset##_max (struct device *dev, struct device_attribute *attr, 		\
 	const char *buf, size_t count) 					\
 {									\
 	return set_temp_max(dev, buf, count, offset - 1);		\
@@ -786,42 +783,42 @@
 	return count;
 }
 #define pwm_auto(offset)						\
-static ssize_t show_pwm##offset##_auto_channels (struct device *dev,	\
+static ssize_t show_pwm##offset##_auto_channels (struct device *dev, struct device_attribute *attr,	\
 	char *buf)							\
 {									\
 	return show_pwm_auto_channels(dev, buf, offset - 1);		\
 }									\
-static ssize_t set_pwm##offset##_auto_channels (struct device *dev,	\
+static ssize_t set_pwm##offset##_auto_channels (struct device *dev, struct device_attribute *attr,	\
 	const char *buf, size_t count)					\
 {									\
 	return set_pwm_auto_channels(dev, buf, count, offset - 1);	\
 }									\
-static ssize_t show_pwm##offset##_auto_pwm_min (struct device *dev,	\
+static ssize_t show_pwm##offset##_auto_pwm_min (struct device *dev, struct device_attribute *attr,	\
 	char *buf)							\
 {									\
 	return show_pwm_auto_pwm_min(dev, buf, offset - 1);		\
 }									\
-static ssize_t set_pwm##offset##_auto_pwm_min (struct device *dev,	\
+static ssize_t set_pwm##offset##_auto_pwm_min (struct device *dev, struct device_attribute *attr,	\
 	const char *buf, size_t count)					\
 {									\
 	return set_pwm_auto_pwm_min(dev, buf, count, offset - 1);	\
 }									\
-static ssize_t show_pwm##offset##_auto_pwm_minctl (struct device *dev,	\
+static ssize_t show_pwm##offset##_auto_pwm_minctl (struct device *dev, struct device_attribute *attr,	\
 	char *buf)							\
 {									\
 	return show_pwm_auto_pwm_minctl(dev, buf, offset - 1);		\
 }									\
-static ssize_t set_pwm##offset##_auto_pwm_minctl (struct device *dev,	\
+static ssize_t set_pwm##offset##_auto_pwm_minctl (struct device *dev, struct device_attribute *attr,	\
 	const char *buf, size_t count)					\
 {									\
 	return set_pwm_auto_pwm_minctl(dev, buf, count, offset - 1);	\
 }									\
-static ssize_t show_pwm##offset##_auto_pwm_freq (struct device *dev,	\
+static ssize_t show_pwm##offset##_auto_pwm_freq (struct device *dev, struct device_attribute *attr,	\
 	char *buf)							\
 {									\
 	return show_pwm_auto_pwm_freq(dev, buf, offset - 1);		\
 }									\
-static ssize_t set_pwm##offset##_auto_pwm_freq(struct device *dev,	\
+static ssize_t set_pwm##offset##_auto_pwm_freq(struct device *dev, struct device_attribute *attr,	\
 	const char *buf, size_t count)					\
 {									\
 	return set_pwm_auto_pwm_freq(dev, buf, count, offset - 1);	\
@@ -962,42 +959,42 @@
 	return count;
 }
 #define temp_auto(offset)						\
-static ssize_t show_temp##offset##_auto_temp_off (struct device *dev,	\
+static ssize_t show_temp##offset##_auto_temp_off (struct device *dev, struct device_attribute *attr,	\
 	char *buf)							\
 {									\
 	return show_temp_auto_temp_off(dev, buf, offset - 1);		\
 }									\
-static ssize_t set_temp##offset##_auto_temp_off (struct device *dev,	\
+static ssize_t set_temp##offset##_auto_temp_off (struct device *dev, struct device_attribute *attr,	\
 	const char *buf, size_t count)					\
 {									\
 	return set_temp_auto_temp_off(dev, buf, count, offset - 1);	\
 }									\
-static ssize_t show_temp##offset##_auto_temp_min (struct device *dev,	\
+static ssize_t show_temp##offset##_auto_temp_min (struct device *dev, struct device_attribute *attr,	\
 	char *buf)							\
 {									\
 	return show_temp_auto_temp_min(dev, buf, offset - 1);		\
 }									\
-static ssize_t set_temp##offset##_auto_temp_min (struct device *dev,	\
+static ssize_t set_temp##offset##_auto_temp_min (struct device *dev, struct device_attribute *attr,	\
 	const char *buf, size_t count)					\
 {									\
 	return set_temp_auto_temp_min(dev, buf, count, offset - 1);	\
 }									\
-static ssize_t show_temp##offset##_auto_temp_max (struct device *dev,	\
+static ssize_t show_temp##offset##_auto_temp_max (struct device *dev, struct device_attribute *attr,	\
 	char *buf)							\
 {									\
 	return show_temp_auto_temp_max(dev, buf, offset - 1);		\
 }									\
-static ssize_t set_temp##offset##_auto_temp_max (struct device *dev,	\
+static ssize_t set_temp##offset##_auto_temp_max (struct device *dev, struct device_attribute *attr,	\
 	const char *buf, size_t count)					\
 {									\
 	return set_temp_auto_temp_max(dev, buf, count, offset - 1);	\
 }									\
-static ssize_t show_temp##offset##_auto_temp_crit (struct device *dev,	\
+static ssize_t show_temp##offset##_auto_temp_crit (struct device *dev, struct device_attribute *attr,	\
 	char *buf)							\
 {									\
 	return show_temp_auto_temp_crit(dev, buf, offset - 1);		\
 }									\
-static ssize_t set_temp##offset##_auto_temp_crit (struct device *dev,	\
+static ssize_t set_temp##offset##_auto_temp_crit (struct device *dev, struct device_attribute *attr,	\
 	const char *buf, size_t count)					\
 {									\
 	return set_temp_auto_temp_crit(dev, buf, count, offset - 1);	\
diff --git a/drivers/i2c/chips/lm87.c b/drivers/i2c/chips/lm87.c
index 98cabd6..1921ed1 100644
--- a/drivers/i2c/chips/lm87.c
+++ b/drivers/i2c/chips/lm87.c
@@ -52,7 +52,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -218,19 +217,19 @@
 }
 
 #define show_in(offset) \
-static ssize_t show_in##offset##_input(struct device *dev, char *buf) \
+static ssize_t show_in##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct lm87_data *data = lm87_update_device(dev); \
 	return sprintf(buf, "%u\n", IN_FROM_REG(data->in[offset], \
 		       data->in_scale[offset])); \
 } \
-static ssize_t show_in##offset##_min(struct device *dev, char *buf) \
+static ssize_t show_in##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct lm87_data *data = lm87_update_device(dev); \
 	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[offset], \
 		       data->in_scale[offset])); \
 } \
-static ssize_t show_in##offset##_max(struct device *dev, char *buf) \
+static ssize_t show_in##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct lm87_data *data = lm87_update_device(dev); \
 	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[offset], \
@@ -274,13 +273,13 @@
 }
 
 #define set_in(offset) \
-static ssize_t set_in##offset##_min(struct device *dev, \
+static ssize_t set_in##offset##_min(struct device *dev, struct device_attribute *attr, \
 		const char *buf, size_t count) \
 { \
 	set_in_min(dev, buf, offset); \
 	return count; \
 } \
-static ssize_t set_in##offset##_max(struct device *dev, \
+static ssize_t set_in##offset##_max(struct device *dev, struct device_attribute *attr, \
 		const char *buf, size_t count) \
 { \
 	set_in_max(dev, buf, offset); \
@@ -300,17 +299,17 @@
 set_in(7);
 
 #define show_temp(offset) \
-static ssize_t show_temp##offset##_input(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct lm87_data *data = lm87_update_device(dev); \
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[offset-1])); \
 } \
-static ssize_t show_temp##offset##_low(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_low(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct lm87_data *data = lm87_update_device(dev); \
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_low[offset-1])); \
 } \
-static ssize_t show_temp##offset##_high(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_high(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct lm87_data *data = lm87_update_device(dev); \
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[offset-1])); \
@@ -346,13 +345,13 @@
 }
 
 #define set_temp(offset) \
-static ssize_t set_temp##offset##_low(struct device *dev, \
+static ssize_t set_temp##offset##_low(struct device *dev, struct device_attribute *attr, \
 		const char *buf, size_t count) \
 { \
 	set_temp_low(dev, buf, offset-1); \
 	return count; \
 } \
-static ssize_t set_temp##offset##_high(struct device *dev, \
+static ssize_t set_temp##offset##_high(struct device *dev, struct device_attribute *attr, \
 		const char *buf, size_t count) \
 { \
 	set_temp_high(dev, buf, offset-1); \
@@ -366,13 +365,13 @@
 set_temp(2);
 set_temp(3);
 
-static ssize_t show_temp_crit_int(struct device *dev, char *buf)
+static ssize_t show_temp_crit_int(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm87_data *data = lm87_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit_int));
 }
 
-static ssize_t show_temp_crit_ext(struct device *dev, char *buf)
+static ssize_t show_temp_crit_ext(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm87_data *data = lm87_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit_ext));
@@ -383,19 +382,19 @@
 static DEVICE_ATTR(temp3_crit, S_IRUGO, show_temp_crit_ext, NULL);
 
 #define show_fan(offset) \
-static ssize_t show_fan##offset##_input(struct device *dev, char *buf) \
+static ssize_t show_fan##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct lm87_data *data = lm87_update_device(dev); \
 	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[offset-1], \
 		       FAN_DIV_FROM_REG(data->fan_div[offset-1]))); \
 } \
-static ssize_t show_fan##offset##_min(struct device *dev, char *buf) \
+static ssize_t show_fan##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct lm87_data *data = lm87_update_device(dev); \
 	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[offset-1], \
 		       FAN_DIV_FROM_REG(data->fan_div[offset-1]))); \
 } \
-static ssize_t show_fan##offset##_div(struct device *dev, char *buf) \
+static ssize_t show_fan##offset##_div(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct lm87_data *data = lm87_update_device(dev); \
 	return sprintf(buf, "%d\n", FAN_DIV_FROM_REG(data->fan_div[offset-1])); \
@@ -465,13 +464,13 @@
 }
 
 #define set_fan(offset) \
-static ssize_t set_fan##offset##_min(struct device *dev, const char *buf, \
+static ssize_t set_fan##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
 		size_t count) \
 { \
 	set_fan_min(dev, buf, offset-1); \
 	return count; \
 } \
-static ssize_t set_fan##offset##_div(struct device *dev, const char *buf, \
+static ssize_t set_fan##offset##_div(struct device *dev, struct device_attribute *attr, const char *buf, \
 		size_t count) \
 { \
 	return set_fan_div(dev, buf, count, offset-1); \
@@ -483,26 +482,26 @@
 set_fan(1);
 set_fan(2);
 
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm87_data *data = lm87_update_device(dev);
 	return sprintf(buf, "%d\n", data->alarms);
 }
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
-static ssize_t show_vid(struct device *dev, char *buf)
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm87_data *data = lm87_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, char *buf)
+static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm87_data *data = lm87_update_device(dev);
 	return sprintf(buf, "%d\n", data->vrm);
 }
-static ssize_t set_vrm(struct device *dev, const char *buf, size_t count)
+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 lm87_data *data = i2c_get_clientdata(client);
@@ -511,12 +510,12 @@
 }
 static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
 
-static ssize_t show_aout(struct device *dev, char *buf)
+static ssize_t show_aout(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm87_data *data = lm87_update_device(dev);
 	return sprintf(buf, "%d\n", AOUT_FROM_REG(data->aout));
 }
-static ssize_t set_aout(struct device *dev, const char *buf, size_t count)
+static ssize_t set_aout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm87_data *data = i2c_get_clientdata(client);
diff --git a/drivers/i2c/chips/lm90.c b/drivers/i2c/chips/lm90.c
index 2c00ff8..a67dcad 100644
--- a/drivers/i2c/chips/lm90.c
+++ b/drivers/i2c/chips/lm90.c
@@ -1,7 +1,7 @@
 /*
  * lm90.c - Part of lm_sensors, Linux kernel modules for hardware
  *          monitoring
- * Copyright (C) 2003-2004  Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2003-2005  Jean Delvare <khali@linux-fr.org>
  *
  * Based on the lm83 driver. The LM90 is a sensor chip made by National
  * Semiconductor. It reports up to two temperatures (its own plus up to
@@ -19,7 +19,7 @@
  * Complete datasheets can be obtained from National's website at:
  *   http://www.national.com/pf/LM/LM89.html
  *   http://www.national.com/pf/LM/LM99.html
- * Note that there is no way to differenciate between both chips.
+ * Note that there is no way to differentiate between both chips.
  *
  * This driver also supports the LM86, another sensor chip made by
  * National Semiconductor. It is exactly similar to the LM90 except it
@@ -39,7 +39,7 @@
  * chips made by Maxim. These chips are similar to the LM86. Complete
  * datasheet can be obtained at Maxim's website at:
  *   http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2578
- * Note that there is no easy way to differenciate between the three
+ * Note that there is no easy way to differentiate between the three
  * variants. The extra address and features of the MAX6659 are not
  * supported by this driver.
  *
@@ -70,13 +70,13 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
+#include <linux/hwmon-sysfs.h>
 
 /*
  * Addresses to scan
@@ -139,9 +139,9 @@
 /*
  * Conversions and various macros
  * For local temperatures and limits, critical limits and the hysteresis
- * value, the LM90 uses signed 8-bit values with LSB = 1 degree Celcius.
+ * value, the LM90 uses signed 8-bit values with LSB = 1 degree Celsius.
  * For remote temperatures and limits, it uses signed 11-bit values with
- * LSB = 0.125 degree Celcius, left-justified in 16-bit registers.
+ * LSB = 0.125 degree Celsius, left-justified in 16-bit registers.
  */
 
 #define TEMP1_FROM_REG(val)	((val) * 1000)
@@ -206,9 +206,14 @@
 	int kind;
 
 	/* registers values */
-	s8 temp_input1, temp_low1, temp_high1; /* local */
-	s16 temp_input2, temp_low2, temp_high2; /* remote, combined */
-	s8 temp_crit1, temp_crit2;
+	s8 temp8[5];	/* 0: local input
+			   1: local low limit
+			   2: local high limit
+			   3: local critical limit
+			   4: remote critical limit */
+	s16 temp11[3];	/* 0: remote input
+			   1: remote low limit
+			   2: remote high limit */
 	u8 temp_hyst;
 	u8 alarms; /* bitvector */
 };
@@ -217,75 +222,88 @@
  * Sysfs stuff
  */
 
-#define show_temp(value, converter) \
-static ssize_t show_##value(struct device *dev, char *buf) \
-{ \
-	struct lm90_data *data = lm90_update_device(dev); \
-	return sprintf(buf, "%d\n", converter(data->value)); \
+static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr,
+			  char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct lm90_data *data = lm90_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp8[attr->index]));
 }
-show_temp(temp_input1, TEMP1_FROM_REG);
-show_temp(temp_input2, TEMP2_FROM_REG);
-show_temp(temp_low1, TEMP1_FROM_REG);
-show_temp(temp_low2, TEMP2_FROM_REG);
-show_temp(temp_high1, TEMP1_FROM_REG);
-show_temp(temp_high2, TEMP2_FROM_REG);
-show_temp(temp_crit1, TEMP1_FROM_REG);
-show_temp(temp_crit2, TEMP1_FROM_REG);
 
-#define set_temp1(value, reg) \
-static ssize_t set_##value(struct device *dev, const char *buf, \
-	size_t count) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct lm90_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtol(buf, NULL, 10); \
- \
-	down(&data->update_lock); \
-	if (data->kind == adt7461) \
-		data->value = TEMP1_TO_REG_ADT7461(val); \
-	else \
-		data->value = TEMP1_TO_REG(val); \
-	i2c_smbus_write_byte_data(client, reg, data->value); \
-	up(&data->update_lock); \
-	return count; \
-}
-#define set_temp2(value, regh, regl) \
-static ssize_t set_##value(struct device *dev, const char *buf, \
-	size_t count) \
-{ \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct lm90_data *data = i2c_get_clientdata(client); \
-	long val = simple_strtol(buf, NULL, 10); \
- \
-	down(&data->update_lock); \
-	if (data->kind == adt7461) \
-		data->value = TEMP2_TO_REG_ADT7461(val); \
-	else \
-		data->value = TEMP2_TO_REG(val); \
-	i2c_smbus_write_byte_data(client, regh, data->value >> 8); \
-	i2c_smbus_write_byte_data(client, regl, data->value & 0xff); \
-	up(&data->update_lock); \
-	return count; \
-}
-set_temp1(temp_low1, LM90_REG_W_LOCAL_LOW);
-set_temp2(temp_low2, LM90_REG_W_REMOTE_LOWH, LM90_REG_W_REMOTE_LOWL);
-set_temp1(temp_high1, LM90_REG_W_LOCAL_HIGH);
-set_temp2(temp_high2, LM90_REG_W_REMOTE_HIGHH, LM90_REG_W_REMOTE_HIGHL);
-set_temp1(temp_crit1, LM90_REG_W_LOCAL_CRIT);
-set_temp1(temp_crit2, LM90_REG_W_REMOTE_CRIT);
+static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr,
+			 const char *buf, size_t count)
+{
+	static const u8 reg[4] = {
+		LM90_REG_W_LOCAL_LOW,
+		LM90_REG_W_LOCAL_HIGH,
+		LM90_REG_W_LOCAL_CRIT,
+		LM90_REG_W_REMOTE_CRIT,
+	};
 
-#define show_temp_hyst(value, basereg) \
-static ssize_t show_##value(struct device *dev, char *buf) \
-{ \
-	struct lm90_data *data = lm90_update_device(dev); \
-	return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->basereg) \
-		       - TEMP1_FROM_REG(data->temp_hyst)); \
-}
-show_temp_hyst(temp_hyst1, temp_crit1);
-show_temp_hyst(temp_hyst2, temp_crit2);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm90_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+	int nr = attr->index;
 
-static ssize_t set_temp_hyst1(struct device *dev, const char *buf,
-	size_t count)
+	down(&data->update_lock);
+	if (data->kind == adt7461)
+		data->temp8[nr] = TEMP1_TO_REG_ADT7461(val);
+	else
+		data->temp8[nr] = TEMP1_TO_REG(val);
+	i2c_smbus_write_byte_data(client, reg[nr - 1], data->temp8[nr]);
+	up(&data->update_lock);
+	return count;
+}
+
+static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr,
+			   char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct lm90_data *data = lm90_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP2_FROM_REG(data->temp11[attr->index]));
+}
+
+static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
+			  const char *buf, size_t count)
+{
+	static const u8 reg[4] = {
+		LM90_REG_W_REMOTE_LOWH,
+		LM90_REG_W_REMOTE_LOWL,
+		LM90_REG_W_REMOTE_HIGHH,
+		LM90_REG_W_REMOTE_HIGHL,
+	};
+
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm90_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+	int nr = attr->index;
+
+	down(&data->update_lock);
+	if (data->kind == adt7461)
+		data->temp11[nr] = TEMP2_TO_REG_ADT7461(val);
+	else
+		data->temp11[nr] = TEMP2_TO_REG(val);
+	i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2],
+				  data->temp11[nr] >> 8);
+	i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1],
+				  data->temp11[nr] & 0xff);
+	up(&data->update_lock);
+	return count;
+}
+
+static ssize_t show_temphyst(struct device *dev, struct device_attribute *devattr,
+			     char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct lm90_data *data = lm90_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp8[attr->index])
+		       - TEMP1_FROM_REG(data->temp_hyst));
+}
+
+static ssize_t set_temphyst(struct device *dev, struct device_attribute *dummy,
+			    const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct lm90_data *data = i2c_get_clientdata(client);
@@ -293,36 +311,37 @@
 	long hyst;
 
 	down(&data->update_lock);
-	hyst = TEMP1_FROM_REG(data->temp_crit1) - val;
+	hyst = TEMP1_FROM_REG(data->temp8[3]) - val;
 	i2c_smbus_write_byte_data(client, LM90_REG_W_TCRIT_HYST,
 				  HYST_TO_REG(hyst));
 	up(&data->update_lock);
 	return count;
 }
 
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy,
+			   char *buf)
 {
 	struct lm90_data *data = lm90_update_device(dev);
 	return sprintf(buf, "%d\n", data->alarms);
 }
 
-static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL);
-static DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input2, NULL);
-static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_low1,
-	set_temp_low1);
-static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_low2,
-	set_temp_low2);
-static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_high1,
-	set_temp_high1);
-static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_high2,
-	set_temp_high2);
-static DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp_crit1,
-	set_temp_crit1);
-static DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp_crit2,
-	set_temp_crit2);
-static DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp_hyst1,
-	set_temp_hyst1);
-static DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temp_hyst2, NULL);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp8, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp8,
+	set_temp8, 1);
+static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11,
+	set_temp11, 1);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp8,
+	set_temp8, 2);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11,
+	set_temp11, 2);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp8,
+	set_temp8, 3);
+static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp8,
+	set_temp8, 4);
+static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temphyst,
+	set_temphyst, 3);
+static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4);
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
 /*
@@ -481,16 +500,26 @@
 	lm90_init_client(new_client);
 
 	/* Register sysfs hooks */
-	device_create_file(&new_client->dev, &dev_attr_temp1_input);
-	device_create_file(&new_client->dev, &dev_attr_temp2_input);
-	device_create_file(&new_client->dev, &dev_attr_temp1_min);
-	device_create_file(&new_client->dev, &dev_attr_temp2_min);
-	device_create_file(&new_client->dev, &dev_attr_temp1_max);
-	device_create_file(&new_client->dev, &dev_attr_temp2_max);
-	device_create_file(&new_client->dev, &dev_attr_temp1_crit);
-	device_create_file(&new_client->dev, &dev_attr_temp2_crit);
-	device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst);
-	device_create_file(&new_client->dev, &dev_attr_temp2_crit_hyst);
+	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_temp1_min.dev_attr);
+	device_create_file(&new_client->dev,
+			   &sensor_dev_attr_temp2_min.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_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_temp1_crit_hyst.dev_attr);
+	device_create_file(&new_client->dev,
+			   &sensor_dev_attr_temp2_crit_hyst.dev_attr);
 	device_create_file(&new_client->dev, &dev_attr_alarms);
 
 	return 0;
@@ -541,16 +570,16 @@
 		u8 oldh, newh;
 
 		dev_dbg(&client->dev, "Updating lm90 data.\n");
-		data->temp_input1 = i2c_smbus_read_byte_data(client,
-				    LM90_REG_R_LOCAL_TEMP);
-		data->temp_high1 = i2c_smbus_read_byte_data(client,
-				   LM90_REG_R_LOCAL_HIGH);
-		data->temp_low1 = i2c_smbus_read_byte_data(client,
-				  LM90_REG_R_LOCAL_LOW);
-		data->temp_crit1 = i2c_smbus_read_byte_data(client,
-				   LM90_REG_R_LOCAL_CRIT);
-		data->temp_crit2 = i2c_smbus_read_byte_data(client,
-				   LM90_REG_R_REMOTE_CRIT);
+		data->temp8[0] = i2c_smbus_read_byte_data(client,
+				 LM90_REG_R_LOCAL_TEMP);
+		data->temp8[1] = i2c_smbus_read_byte_data(client,
+				 LM90_REG_R_LOCAL_LOW);
+		data->temp8[2] = i2c_smbus_read_byte_data(client,
+				 LM90_REG_R_LOCAL_HIGH);
+		data->temp8[3] = i2c_smbus_read_byte_data(client,
+				 LM90_REG_R_LOCAL_CRIT);
+		data->temp8[4] = i2c_smbus_read_byte_data(client,
+				 LM90_REG_R_REMOTE_CRIT);
 		data->temp_hyst = i2c_smbus_read_byte_data(client,
 				  LM90_REG_R_TCRIT_HYST);
 
@@ -570,13 +599,13 @@
 		 */
 		oldh = i2c_smbus_read_byte_data(client,
 		       LM90_REG_R_REMOTE_TEMPH);
-		data->temp_input2 = i2c_smbus_read_byte_data(client,
-				    LM90_REG_R_REMOTE_TEMPL);
+		data->temp11[0] = i2c_smbus_read_byte_data(client,
+				  LM90_REG_R_REMOTE_TEMPL);
 		newh = i2c_smbus_read_byte_data(client,
 		       LM90_REG_R_REMOTE_TEMPH);
 		if (newh != oldh) {
-			data->temp_input2 = i2c_smbus_read_byte_data(client,
-					    LM90_REG_R_REMOTE_TEMPL);
+			data->temp11[0] = i2c_smbus_read_byte_data(client,
+					  LM90_REG_R_REMOTE_TEMPL);
 #ifdef DEBUG
 			oldh = i2c_smbus_read_byte_data(client,
 			       LM90_REG_R_REMOTE_TEMPH);
@@ -586,16 +615,16 @@
 					 "wrong.\n");
 #endif
 		}
-		data->temp_input2 |= (newh << 8);
+		data->temp11[0] |= (newh << 8);
 
-		data->temp_high2 = (i2c_smbus_read_byte_data(client,
+		data->temp11[1] = (i2c_smbus_read_byte_data(client,
+				   LM90_REG_R_REMOTE_LOWH) << 8) +
+				   i2c_smbus_read_byte_data(client,
+				   LM90_REG_R_REMOTE_LOWL);
+		data->temp11[2] = (i2c_smbus_read_byte_data(client,
 				   LM90_REG_R_REMOTE_HIGHH) << 8) +
 				   i2c_smbus_read_byte_data(client,
 				   LM90_REG_R_REMOTE_HIGHL);
-		data->temp_low2 = (i2c_smbus_read_byte_data(client,
-				  LM90_REG_R_REMOTE_LOWH) << 8) +
-				  i2c_smbus_read_byte_data(client,
-				  LM90_REG_R_REMOTE_LOWL);
 		data->alarms = i2c_smbus_read_byte_data(client,
 			       LM90_REG_R_STATUS);
 
diff --git a/drivers/i2c/chips/lm92.c b/drivers/i2c/chips/lm92.c
index fe6e83d..215c8e4 100644
--- a/drivers/i2c/chips/lm92.c
+++ b/drivers/i2c/chips/lm92.c
@@ -140,7 +140,7 @@
 }
 
 #define show_temp(value) \
-static ssize_t show_##value(struct device *dev, char *buf) \
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct lm92_data *data = lm92_update_device(dev); \
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value)); \
@@ -151,7 +151,7 @@
 show_temp(temp1_max);
 
 #define set_temp(value, reg) \
-static ssize_t set_##value(struct device *dev, const char *buf, \
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, \
 	size_t count) \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
@@ -168,26 +168,26 @@
 set_temp(temp1_min, LM92_REG_TEMP_LOW);
 set_temp(temp1_max, LM92_REG_TEMP_HIGH);
 
-static ssize_t show_temp1_crit_hyst(struct device *dev, char *buf)
+static ssize_t show_temp1_crit_hyst(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm92_data *data = lm92_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_crit)
 		       - TEMP_FROM_REG(data->temp1_hyst));
 }
-static ssize_t show_temp1_max_hyst(struct device *dev, char *buf)
+static ssize_t show_temp1_max_hyst(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm92_data *data = lm92_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_max)
 		       - TEMP_FROM_REG(data->temp1_hyst));
 }
-static ssize_t show_temp1_min_hyst(struct device *dev, char *buf)
+static ssize_t show_temp1_min_hyst(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm92_data *data = lm92_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_min)
 		       + TEMP_FROM_REG(data->temp1_hyst));
 }
 
-static ssize_t set_temp1_crit_hyst(struct device *dev, const char *buf,
+static ssize_t set_temp1_crit_hyst(struct device *dev, struct device_attribute *attr, const char *buf,
 	size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -202,7 +202,7 @@
 	return count;
 }
 
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lm92_data *data = lm92_update_device(dev);
 	return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->temp1_input));
diff --git a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
index e771566..5e463c47 100644
--- a/drivers/i2c/chips/m41t00.c
+++ b/drivers/i2c/chips/m41t00.c
@@ -40,11 +40,8 @@
 
 static struct i2c_client_address_data addr_data = {
 	.normal_i2c		= normal_addr,
-	.normal_i2c_range	= ignore,
 	.probe			= ignore,
-	.probe_range		= ignore,
 	.ignore			= ignore,
-	.ignore_range		= ignore,
 	.force			= ignore,
 };
 
diff --git a/drivers/i2c/chips/max1619.c b/drivers/i2c/chips/max1619.c
index 5afa961..bf553dc 100644
--- a/drivers/i2c/chips/max1619.c
+++ b/drivers/i2c/chips/max1619.c
@@ -26,7 +26,6 @@
  */
 
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -122,7 +121,7 @@
  */
 
 #define show_temp(value) \
-static ssize_t show_##value(struct device *dev, char *buf) \
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct max1619_data *data = max1619_update_device(dev); \
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value)); \
@@ -135,7 +134,7 @@
 show_temp(temp_hyst2);
 
 #define set_temp2(value, reg) \
-static ssize_t set_##value(struct device *dev, const char *buf, \
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, \
 	size_t count) \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
@@ -154,7 +153,7 @@
 set_temp2(temp_crit2, MAX1619_REG_W_REMOTE_CRIT);
 set_temp2(temp_hyst2, MAX1619_REG_W_TCRIT_HYST);
 
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct max1619_data *data = max1619_update_device(dev);
 	return sprintf(buf, "%d\n", data->alarms);
diff --git a/drivers/i2c/chips/max6875.c b/drivers/i2c/chips/max6875.c
new file mode 100644
index 0000000..fe6b150
--- /dev/null
+++ b/drivers/i2c/chips/max6875.c
@@ -0,0 +1,473 @@
+/*
+    max6875.c - driver for MAX6874/MAX6875
+
+    Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com>
+
+    Based on i2c/chips/eeprom.c
+
+    The MAX6875 has two EEPROM sections: config and user.
+    At reset, the config EEPROM is read into the registers.
+
+    This driver make 3 binary files available in sysfs:
+      reg_config    - direct access to the registers
+      eeprom_config - acesses configuration eeprom space
+      eeprom_user   - free for application use
+
+    In our application, we put device serial & model numbers in user eeprom.
+
+    Notes:
+      1) The datasheet says that register 0x44 / EEPROM 0x8044 should NOT
+         be overwritten, so the driver explicitly prevents that.
+      2) It's a good idea to keep the config (0x45) locked in config EEPROM.
+         You can temporarily enable config writes by changing register 0x45.
+
+    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.
+*/
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = {0x50, 0x52, I2C_CLIENT_END};
+static unsigned int normal_isa[] = {I2C_CLIENT_ISA_END};
+
+/* Insmod parameters */
+SENSORS_INSMOD_1(max6875);
+
+/* this param will prevent 'accidental' writes to the eeprom */
+static int allow_write = 0;
+module_param(allow_write, int, 0);
+MODULE_PARM_DESC(allow_write,
+		 "Enable write access:\n"
+		 "*0: Read only\n"
+		 " 1: Read/Write access");
+
+/* The MAX6875 can only read/write 16 bytes at a time */
+#define SLICE_SIZE			16
+#define SLICE_BITS			4
+
+/* CONFIG EEPROM is at addresses 0x8000 - 0x8045, registers are at 0 - 0x45 */
+#define CONFIG_EEPROM_BASE		0x8000
+#define CONFIG_EEPROM_SIZE		0x0046
+#define CONFIG_EEPROM_SLICES		5
+
+/* USER EEPROM is at addresses 0x8100 - 0x82FF */
+#define USER_EEPROM_BASE		0x8100
+#define USER_EEPROM_SIZE		0x0200
+#define USER_EEPROM_SLICES		32
+
+/* MAX6875 commands */
+#define MAX6875_CMD_BLOCK_WRITE		0x83
+#define MAX6875_CMD_BLOCK_READ		0x84
+#define MAX6875_CMD_REBOOT		0x88
+
+enum max6875_area_type {
+	max6875_register_config=0,
+	max6875_eeprom_config,
+	max6875_eeprom_user,
+	max6857_max
+};
+
+struct eeprom_block {
+	enum max6875_area_type	type;
+	u8			slices;
+	u32			size;
+	u32			valid;
+	u32			base;
+	unsigned long		*updated;
+	u8			*data;
+};
+
+/* Each client has this additional data */
+struct max6875_data {
+	struct i2c_client	client;
+	struct semaphore	update_lock;
+	struct eeprom_block	blocks[max6857_max];
+	/* the above structs point into the arrays below */
+	u8 data[USER_EEPROM_SIZE + (CONFIG_EEPROM_SIZE*2)];
+	unsigned long last_updated[USER_EEPROM_SLICES + (CONFIG_EEPROM_SLICES*2)];
+};
+
+static int max6875_attach_adapter(struct i2c_adapter *adapter);
+static int max6875_detect(struct i2c_adapter *adapter, int address, int kind);
+static int max6875_detach_client(struct i2c_client *client);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver max6875_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "max6875",
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter	= max6875_attach_adapter,
+	.detach_client	= max6875_detach_client,
+};
+
+static int max6875_update_slice(struct i2c_client *client,
+				struct eeprom_block *blk,
+				int slice)
+{
+	struct max6875_data *data = i2c_get_clientdata(client);
+	int i, j, addr, count;
+	u8 rdbuf[SLICE_SIZE];
+	int retval = 0;
+
+	if (slice >= blk->slices)
+		return -1;
+
+	down(&data->update_lock);
+
+	if (!(blk->valid & (1 << slice)) ||
+	    (jiffies - blk->updated[slice] > 300 * HZ) ||
+	    (jiffies < blk->updated[slice])) {
+		dev_dbg(&client->dev, "Starting eeprom update, slice %u, base %u\n",
+			slice, blk->base);
+
+		addr = blk->base + (slice << SLICE_BITS);
+		count = blk->size - (slice << SLICE_BITS);
+		if (count > SLICE_SIZE) {
+			count = SLICE_SIZE;
+		}
+
+		/* Preset the read address */
+		if (addr < 0x100) {
+			/* select the register */
+			if (i2c_smbus_write_byte(client, addr & 0xFF)) {
+				dev_dbg(&client->dev, "max6875 register select has failed!\n");
+				retval = -1;
+				goto exit;
+			}
+		} else {
+			/* select the eeprom */
+			if (i2c_smbus_write_byte_data(client, addr >> 8, addr & 0xFF)) {
+				dev_dbg(&client->dev, "max6875 address set has failed!\n");
+				retval = -1;
+				goto exit;
+			}
+		}
+
+		if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
+			if (i2c_smbus_read_i2c_block_data(client, MAX6875_CMD_BLOCK_READ,
+							  rdbuf) != SLICE_SIZE)
+			{
+				retval = -1;
+				goto exit;
+			}
+
+			memcpy(&blk->data[slice << SLICE_BITS], rdbuf, count);
+		} else {
+			for (i = 0; i < count; i++) {
+				j = i2c_smbus_read_byte(client);
+				if (j < 0)
+				{
+					retval = -1;
+					goto exit;
+				}
+				blk->data[(slice << SLICE_BITS) + i] = (u8) j;
+			}
+		}
+		blk->updated[slice] = jiffies;
+		blk->valid |= (1 << slice);
+	}
+	exit:
+	up(&data->update_lock);
+	return retval;
+}
+
+static ssize_t max6875_read(struct kobject *kobj, char *buf, loff_t off, size_t count,
+			    enum max6875_area_type area_type)
+{
+	struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
+	struct max6875_data *data = i2c_get_clientdata(client);
+	struct eeprom_block *blk;
+	int slice;
+
+	blk = &data->blocks[area_type];
+
+	if (off > blk->size)
+		return 0;
+	if (off + count > blk->size)
+		count = blk->size - off;
+
+	/* Only refresh slices which contain requested bytes */
+	for (slice = (off >> SLICE_BITS); slice <= ((off + count - 1) >> SLICE_BITS); slice++)
+		max6875_update_slice(client, blk, slice);
+
+	memcpy(buf, &blk->data[off], count);
+
+	return count;
+}
+
+static ssize_t max6875_user_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+	return max6875_read(kobj, buf, off, count, max6875_eeprom_user);
+}
+
+static ssize_t max6875_config_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+	return max6875_read(kobj, buf, off, count, max6875_eeprom_config);
+}
+
+static ssize_t max6875_cfgreg_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+	return max6875_read(kobj, buf, off, count, max6875_register_config);
+}
+
+
+static ssize_t max6875_write(struct kobject *kobj, char *buf, loff_t off, size_t count,
+			     enum max6875_area_type area_type)
+{
+	struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
+	struct max6875_data *data = i2c_get_clientdata(client);
+	struct eeprom_block *blk;
+	int slice, addr, retval;
+	ssize_t sent = 0;
+
+	blk = &data->blocks[area_type];
+
+	if (off > blk->size)
+		return 0;
+	if ((off + count) > blk->size)
+		count = blk->size - off;
+
+	if (down_interruptible(&data->update_lock))
+		return -EAGAIN;
+
+	/* writing to a register is done with i2c_smbus_write_byte_data() */
+	if (blk->type == max6875_register_config) {
+		for (sent = 0; sent < count; sent++) {
+			addr = off + sent;
+			if (addr == 0x44)
+				continue;
+
+			retval = i2c_smbus_write_byte_data(client, addr, buf[sent]);
+		}
+	} else {
+		int cmd, val;
+
+		/* We are writing to EEPROM */
+		for (sent = 0; sent < count; sent++) {
+			addr = blk->base + off + sent;
+			cmd = addr >> 8;
+			val = (addr & 0xff) | (buf[sent] << 8);	// reversed
+
+			if (addr == 0x8044)
+				continue;
+
+			retval = i2c_smbus_write_word_data(client, cmd, val);
+
+			if (retval) {
+				goto error_exit;
+			}
+
+			/* A write takes up to 11 ms */
+			msleep(11);
+		}
+	}
+
+	/* Invalidate the scratch buffer */
+	for (slice = (off >> SLICE_BITS); slice <= ((off + count - 1) >> SLICE_BITS); slice++)
+		blk->valid &= ~(1 << slice);
+
+	error_exit:
+	up(&data->update_lock);
+
+	return sent;
+}
+
+static ssize_t max6875_user_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+	return max6875_write(kobj, buf, off, count, max6875_eeprom_user);
+}
+
+static ssize_t max6875_config_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+	return max6875_write(kobj, buf, off, count, max6875_eeprom_config);
+}
+
+static ssize_t max6875_cfgreg_write(struct kobject *kobj, char *buf, loff_t off, size_t count)
+{
+	return max6875_write(kobj, buf, off, count, max6875_register_config);
+}
+
+static struct bin_attribute user_eeprom_attr = {
+	.attr = {
+		.name = "eeprom_user",
+		.mode = S_IRUGO | S_IWUSR | S_IWGRP,
+		.owner = THIS_MODULE,
+	},
+	.size  = USER_EEPROM_SIZE,
+	.read  = max6875_user_read,
+	.write = max6875_user_write,
+};
+
+static struct bin_attribute config_eeprom_attr = {
+	.attr = {
+		.name = "eeprom_config",
+		.mode = S_IRUGO | S_IWUSR,
+		.owner = THIS_MODULE,
+	},
+	.size  = CONFIG_EEPROM_SIZE,
+	.read  = max6875_config_read,
+	.write = max6875_config_write,
+};
+
+static struct bin_attribute config_register_attr = {
+	.attr = {
+		.name = "reg_config",
+		.mode = S_IRUGO | S_IWUSR,
+		.owner = THIS_MODULE,
+	},
+	.size  = CONFIG_EEPROM_SIZE,
+	.read  = max6875_cfgreg_read,
+	.write = max6875_cfgreg_write,
+};
+
+static int max6875_attach_adapter(struct i2c_adapter *adapter)
+{
+	return i2c_detect(adapter, &addr_data, max6875_detect);
+}
+
+/* This function is called by i2c_detect */
+static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *new_client;
+	struct max6875_data *data;
+	int err = 0;
+
+	/* There are three ways we can read the EEPROM data:
+	   (1) I2C block reads (faster, but unsupported by most adapters)
+	   (2) Consecutive byte reads (100% overhead)
+	   (3) Regular byte data reads (200% overhead)
+	   The third method is not implemented by this driver because all
+	   known adapters support at least the second. */
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA |
+				     I2C_FUNC_SMBUS_BYTE |
+				     I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+		goto exit;
+
+	/* 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 eeprom_{read,write}_value. */
+	if (!(data = kmalloc(sizeof(struct max6875_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit;
+	}
+	memset(data, 0, sizeof(struct max6875_data));
+
+	new_client = &data->client;
+	i2c_set_clientdata(new_client, data);
+	new_client->addr = address;
+	new_client->adapter = adapter;
+	new_client->driver = &max6875_driver;
+	new_client->flags = 0;
+
+	/* Setup the user section */
+	data->blocks[max6875_eeprom_user].type    = max6875_eeprom_user;
+	data->blocks[max6875_eeprom_user].slices  = USER_EEPROM_SLICES;
+	data->blocks[max6875_eeprom_user].size    = USER_EEPROM_SIZE;
+	data->blocks[max6875_eeprom_user].base    = USER_EEPROM_BASE;
+	data->blocks[max6875_eeprom_user].data    = data->data;
+	data->blocks[max6875_eeprom_user].updated = data->last_updated;
+
+	/* Setup the config section */
+	data->blocks[max6875_eeprom_config].type    = max6875_eeprom_config;
+	data->blocks[max6875_eeprom_config].slices  = CONFIG_EEPROM_SLICES;
+	data->blocks[max6875_eeprom_config].size    = CONFIG_EEPROM_SIZE;
+	data->blocks[max6875_eeprom_config].base    = CONFIG_EEPROM_BASE;
+	data->blocks[max6875_eeprom_config].data    = &data->data[USER_EEPROM_SIZE];
+	data->blocks[max6875_eeprom_config].updated = &data->last_updated[USER_EEPROM_SLICES];
+
+	/* Setup the register section */
+	data->blocks[max6875_register_config].type    = max6875_register_config;
+	data->blocks[max6875_register_config].slices  = CONFIG_EEPROM_SLICES;
+	data->blocks[max6875_register_config].size    = CONFIG_EEPROM_SIZE;
+	data->blocks[max6875_register_config].base    = 0;
+	data->blocks[max6875_register_config].data    = &data->data[USER_EEPROM_SIZE+CONFIG_EEPROM_SIZE];
+	data->blocks[max6875_register_config].updated = &data->last_updated[USER_EEPROM_SLICES+CONFIG_EEPROM_SLICES];
+
+	/* Init the data */
+	memset(data->data, 0xff, sizeof(data->data));
+
+	/* Fill in the remaining client fields */
+	strlcpy(new_client->name, "max6875", I2C_NAME_SIZE);
+	init_MUTEX(&data->update_lock);
+
+	/* Verify that the chip is really what we think it is */
+	if ((max6875_update_slice(new_client, &data->blocks[max6875_eeprom_config], 4) < 0) ||
+	    (max6875_update_slice(new_client, &data->blocks[max6875_register_config], 4) < 0))
+		goto exit_kfree;
+
+	/* 0x41,0x42 must be zero and 0x40 must match in eeprom and registers */
+	if ((data->blocks[max6875_eeprom_config].data[0x41] != 0) ||
+	    (data->blocks[max6875_eeprom_config].data[0x42] != 0) ||
+	    (data->blocks[max6875_register_config].data[0x41] != 0) ||
+	    (data->blocks[max6875_register_config].data[0x42] != 0) ||
+	    (data->blocks[max6875_eeprom_config].data[0x40] !=
+	     data->blocks[max6875_register_config].data[0x40]))
+		goto exit_kfree;
+
+	/* Tell the I2C layer a new client has arrived */
+	if ((err = i2c_attach_client(new_client)))
+		goto exit_kfree;
+
+	/* create the sysfs eeprom files with the correct permissions */
+	if (allow_write == 0) {
+		user_eeprom_attr.attr.mode &= ~S_IWUGO;
+		user_eeprom_attr.write = NULL;
+		config_eeprom_attr.attr.mode &= ~S_IWUGO;
+		config_eeprom_attr.write = NULL;
+		config_register_attr.attr.mode &= ~S_IWUGO;
+		config_register_attr.write = NULL;
+	}
+	sysfs_create_bin_file(&new_client->dev.kobj, &user_eeprom_attr);
+	sysfs_create_bin_file(&new_client->dev.kobj, &config_eeprom_attr);
+	sysfs_create_bin_file(&new_client->dev.kobj, &config_register_attr);
+
+	return 0;
+
+exit_kfree:
+	kfree(data);
+exit:
+	return err;
+}
+
+static int max6875_detach_client(struct i2c_client *client)
+{
+	int err;
+
+	err = i2c_detach_client(client);
+	if (err) {
+		dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
+		return err;
+	}
+
+	kfree(i2c_get_clientdata(client));
+
+	return 0;
+}
+
+static int __init max6875_init(void)
+{
+	return i2c_add_driver(&max6875_driver);
+}
+
+static void __exit max6875_exit(void)
+{
+	i2c_del_driver(&max6875_driver);
+}
+
+
+MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
+MODULE_DESCRIPTION("MAX6875 driver");
+MODULE_LICENSE("GPL");
+
+module_init(max6875_init);
+module_exit(max6875_exit);
diff --git a/drivers/i2c/chips/pc87360.c b/drivers/i2c/chips/pc87360.c
index 6d94c36..876c68f 100644
--- a/drivers/i2c/chips/pc87360.c
+++ b/drivers/i2c/chips/pc87360.c
@@ -33,7 +33,6 @@
  *  the standard Super-I/O addresses is used (0x2E/0x2F or 0x4E/0x4F).
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -282,31 +281,31 @@
 }
 
 #define show_and_set_fan(offset) \
-static ssize_t show_fan##offset##_input(struct device *dev, char *buf) \
+static ssize_t show_fan##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct pc87360_data *data = pc87360_update_device(dev); \
 	return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan[offset-1], \
 		       FAN_DIV_FROM_REG(data->fan_status[offset-1]))); \
 } \
-static ssize_t show_fan##offset##_min(struct device *dev, char *buf) \
+static ssize_t show_fan##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct pc87360_data *data = pc87360_update_device(dev); \
 	return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan_min[offset-1], \
 		       FAN_DIV_FROM_REG(data->fan_status[offset-1]))); \
 } \
-static ssize_t show_fan##offset##_div(struct device *dev, char *buf) \
+static ssize_t show_fan##offset##_div(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct pc87360_data *data = pc87360_update_device(dev); \
 	return sprintf(buf, "%u\n", \
 		       FAN_DIV_FROM_REG(data->fan_status[offset-1])); \
 } \
-static ssize_t show_fan##offset##_status(struct device *dev, char *buf) \
+static ssize_t show_fan##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct pc87360_data *data = pc87360_update_device(dev); \
 	return sprintf(buf, "%u\n", \
 		       FAN_STATUS_FROM_REG(data->fan_status[offset-1])); \
 } \
-static ssize_t set_fan##offset##_min(struct device *dev, const char *buf, \
+static ssize_t set_fan##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
 	size_t count) \
 { \
 	return set_fan_min(dev, buf, count, offset-1); \
@@ -324,7 +323,7 @@
 show_and_set_fan(3)
 
 #define show_and_set_pwm(offset) \
-static ssize_t show_pwm##offset(struct device *dev, char *buf) \
+static ssize_t show_pwm##offset(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct pc87360_data *data = pc87360_update_device(dev); \
 	return sprintf(buf, "%u\n", \
@@ -332,7 +331,7 @@
 				    FAN_CONFIG_INVERT(data->fan_conf, \
 						      offset-1))); \
 } \
-static ssize_t set_pwm##offset(struct device *dev, const char *buf, \
+static ssize_t set_pwm##offset(struct device *dev, struct device_attribute *attr, const char *buf, \
 	size_t count) \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
@@ -354,30 +353,30 @@
 show_and_set_pwm(3)
 
 #define show_and_set_in(offset) \
-static ssize_t show_in##offset##_input(struct device *dev, char *buf) \
+static ssize_t show_in##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct pc87360_data *data = pc87360_update_device(dev); \
 	return sprintf(buf, "%u\n", IN_FROM_REG(data->in[offset], \
 		       data->in_vref)); \
 } \
-static ssize_t show_in##offset##_min(struct device *dev, char *buf) \
+static ssize_t show_in##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct pc87360_data *data = pc87360_update_device(dev); \
 	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[offset], \
 		       data->in_vref)); \
 } \
-static ssize_t show_in##offset##_max(struct device *dev, char *buf) \
+static ssize_t show_in##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct pc87360_data *data = pc87360_update_device(dev); \
 	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[offset], \
 		       data->in_vref)); \
 } \
-static ssize_t show_in##offset##_status(struct device *dev, char *buf) \
+static ssize_t show_in##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct pc87360_data *data = pc87360_update_device(dev); \
 	return sprintf(buf, "%u\n", data->in_status[offset]); \
 } \
-static ssize_t set_in##offset##_min(struct device *dev, const char *buf, \
+static ssize_t set_in##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
 	size_t count) \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
@@ -391,7 +390,7 @@
 	up(&data->update_lock); \
 	return count; \
 } \
-static ssize_t set_in##offset##_max(struct device *dev, const char *buf, \
+static ssize_t set_in##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
 	size_t count) \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
@@ -427,36 +426,36 @@
 show_and_set_in(10)
 
 #define show_and_set_therm(offset) \
-static ssize_t show_temp##offset##_input(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct pc87360_data *data = pc87360_update_device(dev); \
 	return sprintf(buf, "%u\n", IN_FROM_REG(data->in[offset+7], \
 		       data->in_vref)); \
 } \
-static ssize_t show_temp##offset##_min(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct pc87360_data *data = pc87360_update_device(dev); \
 	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[offset+7], \
 		       data->in_vref)); \
 } \
-static ssize_t show_temp##offset##_max(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct pc87360_data *data = pc87360_update_device(dev); \
 	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[offset+7], \
 		       data->in_vref)); \
 } \
-static ssize_t show_temp##offset##_crit(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_crit(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct pc87360_data *data = pc87360_update_device(dev); \
 	return sprintf(buf, "%u\n", IN_FROM_REG(data->in_crit[offset-4], \
 		       data->in_vref)); \
 } \
-static ssize_t show_temp##offset##_status(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct pc87360_data *data = pc87360_update_device(dev); \
 	return sprintf(buf, "%u\n", data->in_status[offset+7]); \
 } \
-static ssize_t set_temp##offset##_min(struct device *dev, const char *buf, \
+static ssize_t set_temp##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
 	size_t count) \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
@@ -470,7 +469,7 @@
 	up(&data->update_lock); \
 	return count; \
 } \
-static ssize_t set_temp##offset##_max(struct device *dev, const char *buf, \
+static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
 	size_t count) \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
@@ -484,7 +483,7 @@
 	up(&data->update_lock); \
 	return count; \
 } \
-static ssize_t set_temp##offset##_crit(struct device *dev, const char *buf, \
+static ssize_t set_temp##offset##_crit(struct device *dev, struct device_attribute *attr, const char *buf, \
 	size_t count) \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
@@ -512,19 +511,19 @@
 show_and_set_therm(5)
 show_and_set_therm(6)
 
-static ssize_t show_vid(struct device *dev, char *buf)
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%u\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, char *buf)
+static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%u\n", data->vrm);
 }
-static ssize_t set_vrm(struct device *dev, const char *buf, size_t count)
+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 pc87360_data *data = i2c_get_clientdata(client);
@@ -533,7 +532,7 @@
 }
 static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
 
-static ssize_t show_in_alarms(struct device *dev, char *buf)
+static ssize_t show_in_alarms(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%u\n", data->in_alarms);
@@ -541,32 +540,32 @@
 static DEVICE_ATTR(alarms_in, S_IRUGO, show_in_alarms, NULL);
 
 #define show_and_set_temp(offset) \
-static ssize_t show_temp##offset##_input(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_input(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct pc87360_data *data = pc87360_update_device(dev); \
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[offset-1])); \
 } \
-static ssize_t show_temp##offset##_min(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_min(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct pc87360_data *data = pc87360_update_device(dev); \
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[offset-1])); \
 } \
-static ssize_t show_temp##offset##_max(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_max(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct pc87360_data *data = pc87360_update_device(dev); \
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[offset-1])); \
 }\
-static ssize_t show_temp##offset##_crit(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_crit(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct pc87360_data *data = pc87360_update_device(dev); \
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[offset-1])); \
 }\
-static ssize_t show_temp##offset##_status(struct device *dev, char *buf) \
+static ssize_t show_temp##offset##_status(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct pc87360_data *data = pc87360_update_device(dev); \
 	return sprintf(buf, "%d\n", data->temp_status[offset-1]); \
 }\
-static ssize_t set_temp##offset##_min(struct device *dev, const char *buf, \
+static ssize_t set_temp##offset##_min(struct device *dev, struct device_attribute *attr, const char *buf, \
 	size_t count) \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
@@ -580,7 +579,7 @@
 	up(&data->update_lock); \
 	return count; \
 } \
-static ssize_t set_temp##offset##_max(struct device *dev, const char *buf, \
+static ssize_t set_temp##offset##_max(struct device *dev, struct device_attribute *attr, const char *buf, \
 	size_t count) \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
@@ -594,7 +593,7 @@
 	up(&data->update_lock); \
 	return count; \
 } \
-static ssize_t set_temp##offset##_crit(struct device *dev, const char *buf, \
+static ssize_t set_temp##offset##_crit(struct device *dev, struct device_attribute *attr, const char *buf, \
 	size_t count) \
 { \
 	struct i2c_client *client = to_i2c_client(dev); \
@@ -622,7 +621,7 @@
 show_and_set_temp(2)
 show_and_set_temp(3)
 
-static ssize_t show_temp_alarms(struct device *dev, char *buf)
+static ssize_t show_temp_alarms(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct pc87360_data *data = pc87360_update_device(dev);
 	return sprintf(buf, "%u\n", data->temp_alarms);
diff --git a/drivers/i2c/chips/pca9539.c b/drivers/i2c/chips/pca9539.c
new file mode 100644
index 0000000..9f3ad45
--- /dev/null
+++ b/drivers/i2c/chips/pca9539.c
@@ -0,0 +1,192 @@
+/*
+    pca9539.c - 16-bit I/O port with interrupt and reset
+
+    Copyright (C) 2005 Ben Gardner <bgardner@wabtec.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; version 2 of the License.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/i2c-sensor.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = {0x74, 0x75, 0x76, 0x77, I2C_CLIENT_END};
+static unsigned int normal_isa[] = {I2C_CLIENT_ISA_END};
+
+/* Insmod parameters */
+SENSORS_INSMOD_1(pca9539);
+
+enum pca9539_cmd
+{
+	PCA9539_INPUT_0		= 0,
+	PCA9539_INPUT_1		= 1,
+	PCA9539_OUTPUT_0	= 2,
+	PCA9539_OUTPUT_1	= 3,
+	PCA9539_INVERT_0	= 4,
+	PCA9539_INVERT_1	= 5,
+	PCA9539_DIRECTION_0	= 6,
+	PCA9539_DIRECTION_1	= 7,
+};
+
+static int pca9539_attach_adapter(struct i2c_adapter *adapter);
+static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind);
+static int pca9539_detach_client(struct i2c_client *client);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver pca9539_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "pca9539",
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter	= pca9539_attach_adapter,
+	.detach_client	= pca9539_detach_client,
+};
+
+struct pca9539_data {
+	struct i2c_client client;
+};
+
+/* following are the sysfs callback functions */
+static ssize_t pca9539_show(struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+	struct sensor_device_attribute *psa = to_sensor_dev_attr(attr);
+	struct i2c_client *client = to_i2c_client(dev);
+	return sprintf(buf, "%d\n", i2c_smbus_read_byte_data(client,
+							     psa->index));
+}
+
+static ssize_t pca9539_store(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+	struct sensor_device_attribute *psa = to_sensor_dev_attr(attr);
+	struct i2c_client *client = to_i2c_client(dev);
+	unsigned long val = simple_strtoul(buf, NULL, 0);
+	if (val > 0xff)
+		return -EINVAL;
+	i2c_smbus_write_byte_data(client, psa->index, val);
+	return count;
+}
+
+/* Define the device attributes */
+
+#define PCA9539_ENTRY_RO(name, cmd_idx) \
+	static SENSOR_DEVICE_ATTR(name, S_IRUGO, pca9539_show, NULL, cmd_idx)
+
+#define PCA9539_ENTRY_RW(name, cmd_idx) \
+	static SENSOR_DEVICE_ATTR(name, S_IRUGO | S_IWUSR, pca9539_show, \
+				  pca9539_store, cmd_idx)
+
+PCA9539_ENTRY_RO(input0, PCA9539_INPUT_0);
+PCA9539_ENTRY_RO(input1, PCA9539_INPUT_1);
+PCA9539_ENTRY_RW(output0, PCA9539_OUTPUT_0);
+PCA9539_ENTRY_RW(output1, PCA9539_OUTPUT_1);
+PCA9539_ENTRY_RW(invert0, PCA9539_INVERT_0);
+PCA9539_ENTRY_RW(invert1, PCA9539_INVERT_1);
+PCA9539_ENTRY_RW(direction0, PCA9539_DIRECTION_0);
+PCA9539_ENTRY_RW(direction1, PCA9539_DIRECTION_1);
+
+static struct attribute *pca9539_attributes[] = {
+	&sensor_dev_attr_input0.dev_attr.attr,
+	&sensor_dev_attr_input1.dev_attr.attr,
+	&sensor_dev_attr_output0.dev_attr.attr,
+	&sensor_dev_attr_output1.dev_attr.attr,
+	&sensor_dev_attr_invert0.dev_attr.attr,
+	&sensor_dev_attr_invert1.dev_attr.attr,
+	&sensor_dev_attr_direction0.dev_attr.attr,
+	&sensor_dev_attr_direction1.dev_attr.attr,
+	NULL
+};
+
+static struct attribute_group pca9539_defattr_group = {
+	.attrs = pca9539_attributes,
+};
+
+static int pca9539_attach_adapter(struct i2c_adapter *adapter)
+{
+	return i2c_detect(adapter, &addr_data, pca9539_detect);
+}
+
+/* This function is called by i2c_detect */
+static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *new_client;
+	struct pca9539_data *data;
+	int err = 0;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		goto exit;
+
+	/* OK. For now, we presume we have a valid client. We now create the
+	   client structure, even though we cannot fill it completely yet. */
+	if (!(data = kmalloc(sizeof(struct pca9539_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit;
+	}
+	memset(data, 0, sizeof(struct pca9539_data));
+
+	new_client = &data->client;
+	i2c_set_clientdata(new_client, data);
+	new_client->addr = address;
+	new_client->adapter = adapter;
+	new_client->driver = &pca9539_driver;
+	new_client->flags = 0;
+
+	/* Detection: the pca9539 only has 8 registers (0-7).
+	   A read of 7 should succeed, but a read of 8 should fail. */
+	if ((i2c_smbus_read_byte_data(new_client, 7) < 0) ||
+	    (i2c_smbus_read_byte_data(new_client, 8) >= 0))
+		goto exit_kfree;
+
+	strlcpy(new_client->name, "pca9539", I2C_NAME_SIZE);
+
+	/* Tell the I2C layer a new client has arrived */
+	if ((err = i2c_attach_client(new_client)))
+		goto exit_kfree;
+
+	/* Register sysfs hooks (don't care about failure) */
+	sysfs_create_group(&new_client->dev.kobj, &pca9539_defattr_group);
+
+	return 0;
+
+exit_kfree:
+	kfree(data);
+exit:
+	return err;
+}
+
+static int pca9539_detach_client(struct i2c_client *client)
+{
+	int err;
+
+	if ((err = i2c_detach_client(client))) {
+		dev_err(&client->dev, "Client deregistration failed.\n");
+		return err;
+	}
+
+	kfree(i2c_get_clientdata(client));
+	return 0;
+}
+
+static int __init pca9539_init(void)
+{
+	return i2c_add_driver(&pca9539_driver);
+}
+
+static void __exit pca9539_exit(void)
+{
+	i2c_del_driver(&pca9539_driver);
+}
+
+MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
+MODULE_DESCRIPTION("PCA9539 driver");
+MODULE_LICENSE("GPL");
+
+module_init(pca9539_init);
+module_exit(pca9539_exit);
+
diff --git a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c
index 48b4e22..cfcf646 100644
--- a/drivers/i2c/chips/pcf8574.c
+++ b/drivers/i2c/chips/pcf8574.c
@@ -57,7 +57,7 @@
 struct pcf8574_data {
 	struct i2c_client client;
 
-	u8 read, write;			/* Register values */
+	u8 write;			/* Remember last written value */
 };
 
 static int pcf8574_attach_adapter(struct i2c_adapter *adapter);
@@ -76,23 +76,21 @@
 };
 
 /* following are the sysfs callback functions */
-static ssize_t show_read(struct device *dev, char *buf)
+static ssize_t show_read(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct i2c_client *client = to_i2c_client(dev);
-	struct pcf8574_data *data = i2c_get_clientdata(client);
-	data->read = i2c_smbus_read_byte(client); 
-	return sprintf(buf, "%u\n", data->read);
+	return sprintf(buf, "%u\n", i2c_smbus_read_byte(client));
 }
 
 static DEVICE_ATTR(read, S_IRUGO, show_read, NULL);
 
-static ssize_t show_write(struct device *dev, char *buf)
+static ssize_t show_write(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct pcf8574_data *data = i2c_get_clientdata(to_i2c_client(dev));
 	return sprintf(buf, "%u\n", data->write);
 }
 
-static ssize_t set_write(struct device *dev, const char *buf,
+static ssize_t set_write(struct device *dev, struct device_attribute *attr, const char *buf,
 			 size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
index b6b927d..db812ad 100644
--- a/drivers/i2c/chips/pcf8591.c
+++ b/drivers/i2c/chips/pcf8591.c
@@ -100,7 +100,7 @@
 
 /* following are the sysfs callback functions */
 #define show_in_channel(channel)					\
-static ssize_t show_in##channel##_input(struct device *dev, char *buf)	\
+static ssize_t show_in##channel##_input(struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return sprintf(buf, "%d\n", pcf8591_read_channel(dev, channel));\
 }									\
@@ -112,13 +112,13 @@
 show_in_channel(2);
 show_in_channel(3);
 
-static ssize_t show_out0_ouput(struct device *dev, char *buf)
+static ssize_t show_out0_ouput(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct pcf8591_data *data = i2c_get_clientdata(to_i2c_client(dev));
 	return sprintf(buf, "%d\n", data->aout * 10);
 }
 
-static ssize_t set_out0_output(struct device *dev, const char *buf, size_t count)
+static ssize_t set_out0_output(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	unsigned int value;
 	struct i2c_client *client = to_i2c_client(dev);
@@ -134,13 +134,13 @@
 static DEVICE_ATTR(out0_output, S_IWUSR | S_IRUGO, 
 		   show_out0_ouput, set_out0_output);
 
-static ssize_t show_out0_enable(struct device *dev, char *buf)
+static ssize_t show_out0_enable(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct pcf8591_data *data = i2c_get_clientdata(to_i2c_client(dev));
 	return sprintf(buf, "%u\n", !(!(data->control & PCF8591_CONTROL_AOEF)));
 }
 
-static ssize_t set_out0_enable(struct device *dev, const char *buf, size_t count)
+static ssize_t set_out0_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct pcf8591_data *data = i2c_get_clientdata(client);
diff --git a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c
index 5a9dedd..588fc22 100644
--- a/drivers/i2c/chips/rtc8564.c
+++ b/drivers/i2c/chips/rtc8564.c
@@ -19,7 +19,6 @@
 #include <linux/string.h>
 #include <linux/rtc.h>		/* get the user-level API */
 #include <linux/init.h>
-#include <linux/init.h>
 
 #include "rtc8564.h"
 
@@ -66,11 +65,8 @@
 
 static struct i2c_client_address_data addr_data = {
 	.normal_i2c		= normal_addr,
-	.normal_i2c_range	= ignore,
 	.probe			= ignore,
-	.probe_range		= ignore,
 	.ignore			= ignore,
-	.ignore_range		= ignore,
 	.force			= ignore,
 };
 
diff --git a/drivers/i2c/chips/sis5595.c b/drivers/i2c/chips/sis5595.c
index 7ea8453..6bbfc8f 100644
--- a/drivers/i2c/chips/sis5595.c
+++ b/drivers/i2c/chips/sis5595.c
@@ -57,6 +57,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 #include <linux/init.h>
+#include <linux/jiffies.h>
 #include <asm/io.h>
 
 
@@ -256,28 +257,28 @@
 
 #define show_in_offset(offset)					\
 static ssize_t							\
-	show_in##offset (struct device *dev, char *buf)		\
+	show_in##offset (struct device *dev, struct device_attribute *attr, char *buf)		\
 {								\
 	return show_in(dev, buf, offset);			\
 }								\
 static DEVICE_ATTR(in##offset##_input, S_IRUGO, 		\
 		show_in##offset, NULL);				\
 static ssize_t							\
-	show_in##offset##_min (struct device *dev, char *buf)	\
+	show_in##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)	\
 {								\
 	return show_in_min(dev, buf, offset);			\
 }								\
 static ssize_t							\
-	show_in##offset##_max (struct device *dev, char *buf)	\
+	show_in##offset##_max (struct device *dev, struct device_attribute *attr, char *buf)	\
 {								\
 	return show_in_max(dev, buf, offset);			\
 }								\
-static ssize_t set_in##offset##_min (struct device *dev,	\
+static ssize_t set_in##offset##_min (struct device *dev, struct device_attribute *attr,	\
 		const char *buf, size_t count)			\
 {								\
 	return set_in_min(dev, buf, count, offset);		\
 }								\
-static ssize_t set_in##offset##_max (struct device *dev,	\
+static ssize_t set_in##offset##_max (struct device *dev, struct device_attribute *attr,	\
 		const char *buf, size_t count)			\
 {								\
 	return set_in_max(dev, buf, count, offset);		\
@@ -294,19 +295,19 @@
 show_in_offset(4);
 
 /* Temperature */
-static ssize_t show_temp(struct device *dev, char *buf)
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct sis5595_data *data = sis5595_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp));
 }
 
-static ssize_t show_temp_over(struct device *dev, char *buf)
+static ssize_t show_temp_over(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct sis5595_data *data = sis5595_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over));
 }
 
-static ssize_t set_temp_over(struct device *dev, const char *buf, size_t count)
+static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct sis5595_data *data = i2c_get_clientdata(client);
@@ -319,13 +320,13 @@
 	return count;
 }
 
-static ssize_t show_temp_hyst(struct device *dev, char *buf)
+static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct sis5595_data *data = sis5595_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_hyst));
 }
 
-static ssize_t set_temp_hyst(struct device *dev, const char *buf, size_t count)
+static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct sis5595_data *data = i2c_get_clientdata(client);
@@ -426,19 +427,19 @@
 }
 
 #define show_fan_offset(offset)						\
-static ssize_t show_fan_##offset (struct device *dev, char *buf)	\
+static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return show_fan(dev, buf, offset - 1);			\
 }									\
-static ssize_t show_fan_##offset##_min (struct device *dev, char *buf)	\
+static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return show_fan_min(dev, buf, offset - 1);			\
 }									\
-static ssize_t show_fan_##offset##_div (struct device *dev, char *buf)	\
+static ssize_t show_fan_##offset##_div (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return show_fan_div(dev, buf, offset - 1);			\
 }									\
-static ssize_t set_fan_##offset##_min (struct device *dev,		\
+static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr,		\
 		const char *buf, size_t count)				\
 {									\
 	return set_fan_min(dev, buf, count, offset - 1);		\
@@ -450,13 +451,13 @@
 show_fan_offset(1);
 show_fan_offset(2);
 
-static ssize_t set_fan_1_div(struct device *dev, const char *buf,
+static ssize_t set_fan_1_div(struct device *dev, struct device_attribute *attr, const char *buf,
 		size_t count)
 {
 	return set_fan_div(dev, buf, count, 0) ;
 }
 
-static ssize_t set_fan_2_div(struct device *dev, const char *buf,
+static ssize_t set_fan_2_div(struct device *dev, struct device_attribute *attr, const char *buf,
 		size_t count)
 {
 	return set_fan_div(dev, buf, count, 1) ;
@@ -467,7 +468,7 @@
 		show_fan_2_div, set_fan_2_div);
 
 /* Alarms */
-static ssize_t show_alarms(struct device *dev, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct sis5595_data *data = sis5595_update_device(dev);
 	return sprintf(buf, "%d\n", data->alarms);
diff --git a/drivers/i2c/chips/smsc47b397.c b/drivers/i2c/chips/smsc47b397.c
index 1119c76..251ac26 100644
--- a/drivers/i2c/chips/smsc47b397.c
+++ b/drivers/i2c/chips/smsc47b397.c
@@ -172,7 +172,7 @@
 }
 
 #define sysfs_temp(num) \
-static ssize_t show_temp##num(struct device *dev, char *buf) \
+static ssize_t show_temp##num(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_temp(dev, buf, num-1); \
 } \
@@ -201,7 +201,7 @@
 }
 
 #define sysfs_fan(num) \
-static ssize_t show_fan##num(struct device *dev, char *buf) \
+static ssize_t show_fan##num(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_fan(dev, buf, num-1); \
 } \
diff --git a/drivers/i2c/chips/smsc47m1.c b/drivers/i2c/chips/smsc47m1.c
index 0e12ca3..897117a 100644
--- a/drivers/i2c/chips/smsc47m1.c
+++ b/drivers/i2c/chips/smsc47m1.c
@@ -184,7 +184,7 @@
 	return sprintf(buf, "%d\n", PWM_EN_FROM_REG(data->pwm[nr]));
 }
 
-static ssize_t get_alarms(struct device *dev, char *buf)
+static ssize_t get_alarms(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
 	return sprintf(buf, "%d\n", data->alarms);
@@ -298,42 +298,42 @@
 }
 
 #define fan_present(offset)						\
-static ssize_t get_fan##offset (struct device *dev, char *buf)		\
+static ssize_t get_fan##offset (struct device *dev, struct device_attribute *attr, char *buf)		\
 {									\
 	return get_fan(dev, buf, offset - 1);				\
 }									\
-static ssize_t get_fan##offset##_min (struct device *dev, char *buf)	\
+static ssize_t get_fan##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return get_fan_min(dev, buf, offset - 1);			\
 }									\
-static ssize_t set_fan##offset##_min (struct device *dev,		\
+static ssize_t set_fan##offset##_min (struct device *dev, struct device_attribute *attr,		\
 		const char *buf, size_t count)				\
 {									\
 	return set_fan_min(dev, buf, count, offset - 1);		\
 }									\
-static ssize_t get_fan##offset##_div (struct device *dev, char *buf)	\
+static ssize_t get_fan##offset##_div (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return get_fan_div(dev, buf, offset - 1);			\
 }									\
-static ssize_t set_fan##offset##_div (struct device *dev,		\
+static ssize_t set_fan##offset##_div (struct device *dev, struct device_attribute *attr,		\
 		const char *buf, size_t count)				\
 {									\
 	return set_fan_div(dev, buf, count, offset - 1);		\
 }									\
-static ssize_t get_pwm##offset (struct device *dev, char *buf)		\
+static ssize_t get_pwm##offset (struct device *dev, struct device_attribute *attr, char *buf)		\
 {									\
 	return get_pwm(dev, buf, offset - 1);				\
 }									\
-static ssize_t set_pwm##offset (struct device *dev,			\
+static ssize_t set_pwm##offset (struct device *dev, struct device_attribute *attr,			\
 		const char *buf, size_t count)				\
 {									\
 	return set_pwm(dev, buf, count, offset - 1);			\
 }									\
-static ssize_t get_pwm##offset##_en (struct device *dev, char *buf)	\
+static ssize_t get_pwm##offset##_en (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return get_pwm_en(dev, buf, offset - 1);			\
 }									\
-static ssize_t set_pwm##offset##_en (struct device *dev,		\
+static ssize_t set_pwm##offset##_en (struct device *dev, struct device_attribute *attr,		\
 		const char *buf, size_t count)				\
 {									\
 	return set_pwm_en(dev, buf, count, offset - 1);			\
@@ -372,14 +372,16 @@
 	 * SMSC LPC47M10x/LPC47M13x (device id 0x59), LPC47M14x (device id
 	 * 0x5F) and LPC47B27x (device id 0x51) have fan control.
 	 * The LPC47M15x and LPC47M192 chips "with hardware monitoring block"
-	 * can do much more besides (device id 0x60, unsupported).
+	 * can do much more besides (device id 0x60).
 	 */
 	if (val == 0x51)
-		printk(KERN_INFO "smsc47m1: Found SMSC47B27x\n");
+		printk(KERN_INFO "smsc47m1: Found SMSC LPC47B27x\n");
 	else if (val == 0x59)
-		printk(KERN_INFO "smsc47m1: Found SMSC47M10x/SMSC47M13x\n");
+		printk(KERN_INFO "smsc47m1: Found SMSC LPC47M10x/LPC47M13x\n");
 	else if (val == 0x5F)
-		printk(KERN_INFO "smsc47m1: Found SMSC47M14x\n");
+		printk(KERN_INFO "smsc47m1: Found SMSC LPC47M14x\n");
+	else if (val == 0x60)
+		printk(KERN_INFO "smsc47m1: Found SMSC LPC47M15x/LPC47M192\n");
 	else {
 		superio_exit();
 		return -ENODEV;
diff --git a/drivers/i2c/chips/tps65010.c b/drivers/i2c/chips/tps65010.c
new file mode 100644
index 0000000..c0ac01b
--- /dev/null
+++ b/drivers/i2c/chips/tps65010.c
@@ -0,0 +1,1072 @@
+/*
+ * tps65010 - driver for tps6501x power management chips
+ *
+ * Copyright (C) 2004 Texas Instruments
+ * Copyright (C) 2004-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.
+ *
+ * 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.
+ */
+#undef	DEBUG
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/suspend.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/mux.h>
+#include <asm/arch/tps65010.h>
+
+/*-------------------------------------------------------------------------*/
+
+#define	DRIVER_VERSION	"2 May 2005"
+#define	DRIVER_NAME	(tps65010_driver.name)
+
+MODULE_DESCRIPTION("TPS6501x Power Management Driver");
+MODULE_LICENSE("GPL");
+
+/* only two addresses possible */
+#define	TPS_BASE	0x48
+static unsigned short normal_i2c[] = {
+	TPS_BASE,
+	I2C_CLIENT_END };
+static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
+
+I2C_CLIENT_INSMOD;
+
+static struct i2c_driver tps65010_driver;
+
+/*-------------------------------------------------------------------------*/
+
+/* This driver handles a family of multipurpose chips, which incorporate
+ * voltage regulators, lithium ion/polymer battery charging, GPIOs, LEDs,
+ * and other features often needed in portable devices like cell phones
+ * or digital cameras.
+ *
+ * The tps65011 and tps65013 have different voltage settings compared
+ * to tps65010 and tps65012.  The tps65013 has a NO_CHG status/irq.
+ * All except tps65010 have "wait" mode, possibly defaulted so that
+ * battery-insert != device-on.
+ *
+ * We could distinguish between some models by checking VDCDC1.UVLO or
+ * other registers, unless they've been changed already after powerup
+ * as part of board setup by a bootloader.
+ */
+enum tps_model {
+	TPS_UNKNOWN = 0,
+	TPS65010,
+	TPS65011,
+	TPS65012,
+	TPS65013,
+};
+
+struct tps65010 {
+	struct i2c_client	client;
+	struct semaphore	lock;
+	int			irq;
+	struct work_struct	work;
+	struct dentry		*file;
+	unsigned		charging:1;
+	unsigned		por:1;
+	unsigned		model:8;
+	u16			vbus;
+	unsigned long		flags;
+#define	FLAG_VBUS_CHANGED	0
+#define	FLAG_IRQ_ENABLE		1
+
+	/* copies of last register state */
+	u8			chgstatus, regstatus, chgconf;
+	u8			nmask1, nmask2;
+
+	/* plus four GPIOs, probably used to switch power */
+};
+
+#define	POWER_POLL_DELAY	msecs_to_jiffies(800)
+
+/*-------------------------------------------------------------------------*/
+
+#if	defined(DEBUG) || defined(CONFIG_DEBUG_FS)
+
+static void dbg_chgstat(char *buf, size_t len, u8 chgstatus)
+{
+	snprintf(buf, len, "%02x%s%s%s%s%s%s%s%s\n",
+		chgstatus,
+		(chgstatus & TPS_CHG_USB) ? " USB" : "",
+		(chgstatus & TPS_CHG_AC) ? " AC" : "",
+		(chgstatus & TPS_CHG_THERM) ? " therm" : "",
+		(chgstatus & TPS_CHG_TERM) ? " done" :
+			((chgstatus & (TPS_CHG_USB|TPS_CHG_AC))
+				? " (charging)" : ""),
+		(chgstatus & TPS_CHG_TAPER_TMO) ? " taper_tmo" : "",
+		(chgstatus & TPS_CHG_CHG_TMO) ? " charge_tmo" : "",
+		(chgstatus & TPS_CHG_PRECHG_TMO) ? " prechg_tmo" : "",
+		(chgstatus & TPS_CHG_TEMP_ERR) ? " temp_err" : "");
+}
+
+static void dbg_regstat(char *buf, size_t len, u8 regstatus)
+{
+	snprintf(buf, len, "%02x %s%s%s%s%s%s%s%s\n",
+		regstatus,
+		(regstatus & TPS_REG_ONOFF) ? "off" : "(on)",
+		(regstatus & TPS_REG_COVER) ? " uncover" : "",
+		(regstatus & TPS_REG_UVLO) ? " UVLO" : "",
+		(regstatus & TPS_REG_NO_CHG) ? " NO_CHG" : "",
+		(regstatus & TPS_REG_PG_LD02) ? " ld01_bad" : "",
+		(regstatus & TPS_REG_PG_LD01) ? " ld01_bad" : "",
+		(regstatus & TPS_REG_PG_MAIN) ? " main_bad" : "",
+		(regstatus & TPS_REG_PG_CORE) ? " core_bad" : "");
+}
+
+static void dbg_chgconf(int por, char *buf, size_t len, u8 chgconfig)
+{
+	char *hibit;
+
+	if (por)
+		hibit = (chgconfig & TPS_CHARGE_POR)
+				? "POR=69ms" : "POR=1sec";
+	else
+		hibit = (chgconfig & TPS65013_AUA) ? "AUA" : "";
+
+	snprintf(buf, len, "%02x %s%s%s AC=%d%% USB=%dmA %sCharge\n",
+		chgconfig, hibit,
+		(chgconfig & TPS_CHARGE_RESET) ? " reset" : "",
+		(chgconfig & TPS_CHARGE_FAST) ? " fast" : "",
+		({int p; switch ((chgconfig >> 3) & 3) {
+		case 3:		p = 100; break;
+		case 2:		p = 75; break;
+		case 1:		p = 50; break;
+		default:	p = 25; break;
+		}; p; }),
+		(chgconfig & TPS_VBUS_CHARGING)
+			? ((chgconfig & TPS_VBUS_500MA) ? 500 : 100)
+			: 0,
+		(chgconfig & TPS_CHARGE_ENABLE) ? "" : "No");
+}
+
+#endif
+
+#ifdef	DEBUG
+
+static void show_chgstatus(const char *label, u8 chgstatus)
+{
+	char buf [100];
+
+	dbg_chgstat(buf, sizeof buf, chgstatus);
+	pr_debug("%s: %s %s", DRIVER_NAME, label, buf);
+}
+
+static void show_regstatus(const char *label, u8 regstatus)
+{
+	char buf [100];
+
+	dbg_regstat(buf, sizeof buf, regstatus);
+	pr_debug("%s: %s %s", DRIVER_NAME, label, buf);
+}
+
+static void show_chgconfig(int por, const char *label, u8 chgconfig)
+{
+	char buf [100];
+
+	dbg_chgconf(por, buf, sizeof buf, chgconfig);
+	pr_debug("%s: %s %s", DRIVER_NAME, label, buf);
+}
+
+#else
+
+static inline void show_chgstatus(const char *label, u8 chgstatus) { }
+static inline void show_regstatus(const char *label, u8 chgstatus) { }
+static inline void show_chgconfig(int por, const char *label, u8 chgconfig) { }
+
+#endif
+
+#ifdef	CONFIG_DEBUG_FS
+
+static int dbg_show(struct seq_file *s, void *_)
+{
+	struct tps65010	*tps = s->private;
+	u8		value, v2;
+	unsigned	i;
+	char		buf[100];
+	const char	*chip;
+
+	switch (tps->model) {
+	case TPS65010:	chip = "tps65010"; break;
+	case TPS65011:	chip = "tps65011"; break;
+	case TPS65012:	chip = "tps65012"; break;
+	case TPS65013:	chip = "tps65013"; break;
+	default:	chip = NULL; break;
+	}
+	seq_printf(s, "driver  %s\nversion %s\nchip    %s\n\n",
+			DRIVER_NAME, DRIVER_VERSION, chip);
+
+	down(&tps->lock);
+
+	/* FIXME how can we tell whether a battery is present?
+	 * likely involves a charge gauging chip (like BQ26501).
+	 */
+
+	seq_printf(s, "%scharging\n\n", tps->charging ? "" : "(not) ");
+
+
+	/* registers for monitoring battery charging and status; note
+	 * that reading chgstat and regstat may ack IRQs...
+	 */
+	value = i2c_smbus_read_byte_data(&tps->client, TPS_CHGCONFIG);
+	dbg_chgconf(tps->por, buf, sizeof buf, value);
+	seq_printf(s, "chgconfig %s", buf);
+
+	value = i2c_smbus_read_byte_data(&tps->client, TPS_CHGSTATUS);
+	dbg_chgstat(buf, sizeof buf, value);
+	seq_printf(s, "chgstat   %s", buf);
+	value = i2c_smbus_read_byte_data(&tps->client, TPS_MASK1);
+	dbg_chgstat(buf, sizeof buf, value);
+	seq_printf(s, "mask1     %s", buf);
+	/* ignore ackint1 */
+
+	value = i2c_smbus_read_byte_data(&tps->client, TPS_REGSTATUS);
+	dbg_regstat(buf, sizeof buf, value);
+	seq_printf(s, "regstat   %s", buf);
+	value = i2c_smbus_read_byte_data(&tps->client, TPS_MASK2);
+	dbg_regstat(buf, sizeof buf, value);
+	seq_printf(s, "mask2     %s\n", buf);
+	/* ignore ackint2 */
+
+	(void) schedule_delayed_work(&tps->work, POWER_POLL_DELAY);
+
+
+	/* VMAIN voltage, enable lowpower, etc */
+	value = i2c_smbus_read_byte_data(&tps->client, TPS_VDCDC1);
+	seq_printf(s, "vdcdc1    %02x\n", value);
+
+	/* VCORE voltage, vibrator on/off */
+	value = i2c_smbus_read_byte_data(&tps->client, TPS_VDCDC2);
+	seq_printf(s, "vdcdc2    %02x\n", value);
+
+	/* both LD0s, and their lowpower behavior */
+	value = i2c_smbus_read_byte_data(&tps->client, TPS_VREGS1);
+	seq_printf(s, "vregs1    %02x\n\n", value);
+
+
+	/* LEDs and GPIOs */
+	value = i2c_smbus_read_byte_data(&tps->client, TPS_LED1_ON);
+	v2 = i2c_smbus_read_byte_data(&tps->client, TPS_LED1_PER);
+	seq_printf(s, "led1 %s, on=%02x, per=%02x, %d/%d msec\n",
+		(value & 0x80)
+			? ((v2 & 0x80) ? "on" : "off")
+			: ((v2 & 0x80) ? "blink" : "(nPG)"),
+		value, v2,
+		(value & 0x7f) * 10, (v2 & 0x7f) * 100);
+
+	value = i2c_smbus_read_byte_data(&tps->client, TPS_LED2_ON);
+	v2 = i2c_smbus_read_byte_data(&tps->client, TPS_LED2_PER);
+	seq_printf(s, "led2 %s, on=%02x, per=%02x, %d/%d msec\n",
+		(value & 0x80)
+			? ((v2 & 0x80) ? "on" : "off")
+			: ((v2 & 0x80) ? "blink" : "off"),
+		value, v2,
+		(value & 0x7f) * 10, (v2 & 0x7f) * 100);
+
+	value = i2c_smbus_read_byte_data(&tps->client, TPS_DEFGPIO);
+	v2 = i2c_smbus_read_byte_data(&tps->client, TPS_MASK3);
+	seq_printf(s, "defgpio %02x mask3 %02x\n", value, v2);
+
+	for (i = 0; i < 4; i++) {
+		if (value & (1 << (4 +i)))
+			seq_printf(s, "  gpio%d-out %s\n", i + 1,
+				(value & (1 << i)) ? "low" : "hi ");
+		else
+			seq_printf(s, "  gpio%d-in  %s %s %s\n", i + 1,
+				(value & (1 << i)) ? "hi " : "low",
+				(v2 & (1 << i)) ? "no-irq" : "irq",
+				(v2 & (1 << (4 + i))) ? "rising" : "falling");
+	}
+
+	up(&tps->lock);
+	return 0;
+}
+
+static int dbg_tps_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, dbg_show, inode->u.generic_ip);
+}
+
+static struct file_operations debug_fops = {
+	.open		= dbg_tps_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+#define	DEBUG_FOPS	&debug_fops
+
+#else
+#define	DEBUG_FOPS	NULL
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+/* handle IRQS in a task context, so we can use I2C calls */
+static void tps65010_interrupt(struct tps65010 *tps)
+{
+	u8 tmp = 0, mask, poll;
+
+	/* IRQs won't trigger irqs for certain events, but we can get
+	 * others by polling (normally, with external power applied).
+	 */
+	poll = 0;
+
+	/* regstatus irqs */
+	if (tps->nmask2) {
+		tmp = i2c_smbus_read_byte_data(&tps->client, TPS_REGSTATUS);
+		mask = tmp ^ tps->regstatus;
+		tps->regstatus = tmp;
+		mask &= tps->nmask2;
+	} else
+		mask = 0;
+	if (mask) {
+		tps->regstatus =  tmp;
+		/* may need to shut something down ... */
+
+		/* "off" usually means deep sleep */
+		if (tmp & TPS_REG_ONOFF) {
+			pr_info("%s: power off button\n", DRIVER_NAME);
+#if 0
+			/* REVISIT:  this might need its own workqueue
+			 * plus tweaks including deadlock avoidance ...
+			 */
+			software_suspend();
+#endif
+			poll = 1;
+		}
+	}
+
+	/* chgstatus irqs */
+	if (tps->nmask1) {
+		tmp = i2c_smbus_read_byte_data(&tps->client, TPS_CHGSTATUS);
+		mask = tmp ^ tps->chgstatus;
+		tps->chgstatus = tmp;
+		mask &= tps->nmask1;
+	} else
+		mask = 0;
+	if (mask) {
+		unsigned	charging = 0;
+
+		show_chgstatus("chg/irq", tmp);
+		if (tmp & (TPS_CHG_USB|TPS_CHG_AC))
+			show_chgconfig(tps->por, "conf", tps->chgconf);
+
+		/* Unless it was turned off or disabled, we charge any
+		 * battery whenever there's power available for it
+		 * and the charger hasn't been disabled.
+		 */
+		if (!(tps->chgstatus & ~(TPS_CHG_USB|TPS_CHG_AC))
+				&& (tps->chgstatus & (TPS_CHG_USB|TPS_CHG_AC))
+				&& (tps->chgconf & TPS_CHARGE_ENABLE)
+				) {
+			if (tps->chgstatus & TPS_CHG_USB) {
+				/* VBUS options are readonly until reconnect */
+				if (mask & TPS_CHG_USB)
+					set_bit(FLAG_VBUS_CHANGED, &tps->flags);
+				charging = 1;
+			} else if (tps->chgstatus & TPS_CHG_AC)
+				charging = 1;
+		}
+		if (charging != tps->charging) {
+			tps->charging = charging;
+			pr_info("%s: battery %scharging\n",
+				DRIVER_NAME, charging ? "" :
+				((tps->chgstatus & (TPS_CHG_USB|TPS_CHG_AC))
+					? "NOT " : "dis"));
+		}
+	}
+
+	/* always poll to detect (a) power removal, without tps65013
+	 * NO_CHG IRQ; or (b) restart of charging after stop.
+	 */
+	if ((tps->model != TPS65013 || !tps->charging)
+			&& (tps->chgstatus & (TPS_CHG_USB|TPS_CHG_AC)))
+		poll = 1;
+	if (poll)
+		(void) schedule_delayed_work(&tps->work, POWER_POLL_DELAY);
+
+	/* also potentially gpio-in rise or fall */
+}
+
+/* handle IRQs and polling using keventd for now */
+static void tps65010_work(void *_tps)
+{
+	struct tps65010		*tps = _tps;
+
+	down(&tps->lock);
+
+	tps65010_interrupt(tps);
+
+	if (test_and_clear_bit(FLAG_VBUS_CHANGED, &tps->flags)) {
+		int	status;
+		u8	chgconfig, tmp;
+
+		chgconfig = i2c_smbus_read_byte_data(&tps->client,
+					TPS_CHGCONFIG);
+		chgconfig &= ~(TPS_VBUS_500MA | TPS_VBUS_CHARGING);
+		if (tps->vbus == 500)
+			chgconfig |= TPS_VBUS_500MA | TPS_VBUS_CHARGING;
+		else if (tps->vbus >= 100)
+			chgconfig |= TPS_VBUS_CHARGING;
+
+		status = i2c_smbus_write_byte_data(&tps->client,
+				TPS_CHGCONFIG, chgconfig);
+
+		/* vbus update fails unless VBUS is connected! */
+		tmp = i2c_smbus_read_byte_data(&tps->client, TPS_CHGCONFIG);
+		tps->chgconf = tmp;
+		show_chgconfig(tps->por, "update vbus", tmp);
+	}
+
+	if (test_and_clear_bit(FLAG_IRQ_ENABLE, &tps->flags))
+		enable_irq(tps->irq);
+
+	up(&tps->lock);
+}
+
+static irqreturn_t tps65010_irq(int irq, void *_tps, struct pt_regs *regs)
+{
+	struct tps65010		*tps = _tps;
+
+	disable_irq_nosync(irq);
+	set_bit(FLAG_IRQ_ENABLE, &tps->flags);
+	(void) schedule_work(&tps->work);
+	return IRQ_HANDLED;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct tps65010 *the_tps;
+
+static int __exit tps65010_detach_client(struct i2c_client *client)
+{
+	struct tps65010		*tps;
+
+	tps = container_of(client, struct tps65010, client);
+#ifdef	CONFIG_ARM
+	if (machine_is_omap_h2())
+		omap_free_gpio(58);
+	if (machine_is_omap_osk())
+		omap_free_gpio(OMAP_MPUIO(1));
+#endif
+	free_irq(tps->irq, tps);
+	debugfs_remove(tps->file);
+	if (i2c_detach_client(client) == 0)
+		kfree(tps);
+	the_tps = 0;
+	return 0;
+}
+
+static int tps65010_noscan(struct i2c_adapter *bus)
+{
+	/* pure paranoia, in case someone adds another i2c bus
+	 * after our init section's gone...
+	 */
+	return -ENODEV;
+}
+
+/* no error returns, they'd just make bus scanning stop */
+static int __init
+tps65010_probe(struct i2c_adapter *bus, int address, int kind)
+{
+	struct tps65010		*tps;
+	int			status;
+
+	if (the_tps) {
+		dev_dbg(&bus->dev, "only one %s for now\n", DRIVER_NAME);
+		return 0;
+	}
+
+	tps = kmalloc(sizeof *tps, GFP_KERNEL);
+	if (!tps)
+		return 0;
+
+	memset(tps, 0, sizeof *tps);
+	init_MUTEX(&tps->lock);
+	INIT_WORK(&tps->work, tps65010_work, tps);
+	tps->irq = -1;
+	tps->client.addr = address;
+	i2c_set_clientdata(&tps->client, tps);
+	tps->client.adapter = bus;
+	tps->client.driver = &tps65010_driver;
+	strlcpy(tps->client.name, DRIVER_NAME, I2C_NAME_SIZE);
+
+	status = i2c_attach_client(&tps->client);
+	if (status < 0) {
+		dev_dbg(&bus->dev, "can't attach %s to device %d, err %d\n",
+				DRIVER_NAME, address, status);
+fail1:
+		kfree(tps);
+		return 0;
+	}
+
+#ifdef	CONFIG_ARM
+	if (machine_is_omap_h2()) {
+		tps->model = TPS65010;
+		omap_cfg_reg(W4_GPIO58);
+		tps->irq = OMAP_GPIO_IRQ(58);
+		omap_request_gpio(58);
+		omap_set_gpio_direction(58, 1);
+		omap_set_gpio_edge_ctrl(58, OMAP_GPIO_FALLING_EDGE);
+	}
+	if (machine_is_omap_osk()) {
+		tps->model = TPS65010;
+		// omap_cfg_reg(U19_1610_MPUIO1);
+		tps->irq = OMAP_GPIO_IRQ(OMAP_MPUIO(1));
+		omap_request_gpio(OMAP_MPUIO(1));
+		omap_set_gpio_direction(OMAP_MPUIO(1), 1);
+		omap_set_gpio_edge_ctrl(OMAP_MPUIO(1), OMAP_GPIO_FALLING_EDGE);
+	}
+	if (machine_is_omap_h3()) {
+		tps->model = TPS65013;
+
+		// FIXME set up this board's IRQ ...
+	}
+#else
+#define set_irq_type(num,trigger)	do{}while(0)
+#endif
+
+	if (tps->irq > 0) {
+		set_irq_type(tps->irq, IRQT_LOW);
+		status = request_irq(tps->irq, tps65010_irq,
+			SA_SAMPLE_RANDOM, DRIVER_NAME, tps);
+		if (status < 0) {
+			dev_dbg(&tps->client.dev, "can't get IRQ %d, err %d\n",
+					tps->irq, status);
+			i2c_detach_client(&tps->client);
+			goto fail1;
+		}
+#ifdef	CONFIG_ARM
+		/* annoying race here, ideally we'd have an option
+		 * to claim the irq now and enable it later.
+		 */
+		disable_irq(tps->irq);
+		set_bit(FLAG_IRQ_ENABLE, &tps->flags);
+#endif
+	} else
+		printk(KERN_WARNING "%s: IRQ not configured!\n",
+				DRIVER_NAME);
+
+
+	switch (tps->model) {
+	case TPS65010:
+	case TPS65012:
+		tps->por = 1;
+		break;
+	case TPS_UNKNOWN:
+		printk(KERN_WARNING "%s: unknown TPS chip\n", DRIVER_NAME);
+		break;
+	/* else CHGCONFIG.POR is replaced by AUA, enabling a WAIT mode */
+	}
+	tps->chgconf = i2c_smbus_read_byte_data(&tps->client, TPS_CHGCONFIG);
+	show_chgconfig(tps->por, "conf/init", tps->chgconf);
+
+	show_chgstatus("chg/init",
+		i2c_smbus_read_byte_data(&tps->client, TPS_CHGSTATUS));
+	show_regstatus("reg/init",
+		i2c_smbus_read_byte_data(&tps->client, TPS_REGSTATUS));
+
+	pr_debug("%s: vdcdc1 0x%02x, vdcdc2 %02x, vregs1 %02x\n", DRIVER_NAME,
+		i2c_smbus_read_byte_data(&tps->client, TPS_VDCDC1),
+		i2c_smbus_read_byte_data(&tps->client, TPS_VDCDC2),
+		i2c_smbus_read_byte_data(&tps->client, TPS_VREGS1));
+	pr_debug("%s: defgpio 0x%02x, mask3 0x%02x\n", DRIVER_NAME,
+		i2c_smbus_read_byte_data(&tps->client, TPS_DEFGPIO),
+		i2c_smbus_read_byte_data(&tps->client, TPS_MASK3));
+
+	tps65010_driver.attach_adapter = tps65010_noscan;
+	the_tps = tps;
+
+#if	defined(CONFIG_USB_GADGET) && !defined(CONFIG_USB_OTG)
+	/* USB hosts can't draw VBUS.  OTG devices could, later
+	 * when OTG infrastructure enables it.  USB peripherals
+	 * could be relying on VBUS while booting, though.
+	 */
+	tps->vbus = 100;
+#endif
+
+	/* unmask the "interesting" irqs, then poll once to
+	 * kickstart monitoring, initialize shadowed status
+	 * registers, and maybe disable VBUS draw.
+	 */
+	tps->nmask1 = ~0;
+	(void) i2c_smbus_write_byte_data(&tps->client, TPS_MASK1, ~tps->nmask1);
+
+	tps->nmask2 = TPS_REG_ONOFF;
+	if (tps->model == TPS65013)
+		tps->nmask2 |= TPS_REG_NO_CHG;
+	(void) i2c_smbus_write_byte_data(&tps->client, TPS_MASK2, ~tps->nmask2);
+
+	(void) i2c_smbus_write_byte_data(&tps->client, TPS_MASK3, 0x0f
+		| i2c_smbus_read_byte_data(&tps->client, TPS_MASK3));
+
+	tps65010_work(tps);
+
+	tps->file = debugfs_create_file(DRIVER_NAME, S_IRUGO, NULL,
+				tps, DEBUG_FOPS);
+	return 0;
+}
+
+static int __init tps65010_scan_bus(struct i2c_adapter *bus)
+{
+	if (!i2c_check_functionality(bus, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -EINVAL;
+	return i2c_probe(bus, &addr_data, tps65010_probe);
+}
+
+static struct i2c_driver tps65010_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "tps65010",
+	.id		= 888,		/* FIXME assign "official" value */
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter	= tps65010_scan_bus,
+	.detach_client	= __exit_p(tps65010_detach_client),
+};
+
+/*-------------------------------------------------------------------------*/
+
+/* Draw from VBUS:
+ *   0 mA -- DON'T DRAW (might supply power instead)
+ * 100 mA -- usb unit load (slowest charge rate)
+ * 500 mA -- usb high power (fast battery charge)
+ */
+int tps65010_set_vbus_draw(unsigned mA)
+{
+	unsigned long	flags;
+
+	if (!the_tps)
+		return -ENODEV;
+
+	/* assumes non-SMP */
+	local_irq_save(flags);
+	if (mA >= 500)
+		mA = 500;
+	else if (mA >= 100)
+		mA = 100;
+	else
+		mA = 0;
+	the_tps->vbus = mA;
+	if ((the_tps->chgstatus & TPS_CHG_USB)
+			&& test_and_set_bit(
+				FLAG_VBUS_CHANGED, &the_tps->flags)) {
+		/* gadget drivers call this in_irq() */
+		(void) schedule_work(&the_tps->work);
+	}
+	local_irq_restore(flags);
+
+	return 0;
+}
+EXPORT_SYMBOL(tps65010_set_vbus_draw);
+
+/*-------------------------------------------------------------------------*/
+/* tps65010_set_gpio_out_value parameter:
+ * gpio:  GPIO1, GPIO2, GPIO3 or GPIO4
+ * value: LOW or HIGH
+ */
+int tps65010_set_gpio_out_value(unsigned gpio, unsigned value)
+{
+	int	 status;
+	unsigned defgpio;
+
+	if (!the_tps)
+		return -ENODEV;
+	if ((gpio < GPIO1) || (gpio > GPIO4))
+		return -EINVAL;
+
+	down(&the_tps->lock);
+
+	defgpio = i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO);
+
+	/* Configure GPIO for output */
+	defgpio |= 1 << (gpio + 3);
+
+	/* Writing 1 forces a logic 0 on that GPIO and vice versa */
+	switch (value) {
+	case LOW:
+		defgpio |= 1 << (gpio - 1);    /* set GPIO low by writing 1 */
+		break;
+	/* case HIGH: */
+	default:
+		defgpio &= ~(1 << (gpio - 1)); /* set GPIO high by writing 0 */
+		break;
+	}
+
+	status = i2c_smbus_write_byte_data(&the_tps->client,
+		TPS_DEFGPIO, defgpio);
+
+	pr_debug("%s: gpio%dout = %s, defgpio 0x%02x\n", DRIVER_NAME,
+		gpio, value ? "high" : "low",
+		i2c_smbus_read_byte_data(&the_tps->client, TPS_DEFGPIO));
+
+	up(&the_tps->lock);
+	return status;
+}
+EXPORT_SYMBOL(tps65010_set_gpio_out_value);
+
+/*-------------------------------------------------------------------------*/
+/* tps65010_set_led parameter:
+ * led:  LED1 or LED2
+ * mode: ON, OFF or BLINK
+ */
+int tps65010_set_led(unsigned led, unsigned mode)
+{
+	int	 status;
+	unsigned led_on, led_per, offs;
+
+	if (!the_tps)
+		return -ENODEV;
+
+	if(led == LED1)
+		offs = 0;
+	else {
+		offs = 2;
+		led = LED2;
+	}
+
+	down(&the_tps->lock);
+
+	dev_dbg (&the_tps->client.dev, "led%i_on   0x%02x\n", led,
+		i2c_smbus_read_byte_data(&the_tps->client, TPS_LED1_ON + offs));
+
+	dev_dbg (&the_tps->client.dev, "led%i_per  0x%02x\n", led,
+		i2c_smbus_read_byte_data(&the_tps->client, TPS_LED1_PER + offs));
+
+	switch (mode) {
+	case OFF:
+		led_on  = 1 << 7;
+		led_per = 0 << 7;
+		break;
+	case ON:
+		led_on  = 1 << 7;
+		led_per = 1 << 7;
+		break;
+	case BLINK:
+		led_on  = 0x30 | (0 << 7);
+		led_per = 0x08 | (1 << 7);
+		break;
+	default:
+		printk(KERN_ERR "%s: Wrong mode parameter for tps65010_set_led()\n",
+		       DRIVER_NAME);
+		up(&the_tps->lock);
+		return -EINVAL;
+	}
+
+	status = i2c_smbus_write_byte_data(&the_tps->client,
+			TPS_LED1_ON + offs, led_on);
+
+	if (status != 0) {
+		printk(KERN_ERR "%s: Failed to write led%i_on register\n",
+		       DRIVER_NAME, led);
+		up(&the_tps->lock);
+		return status;
+	}
+
+	dev_dbg (&the_tps->client.dev, "led%i_on   0x%02x\n", led,
+		i2c_smbus_read_byte_data(&the_tps->client, TPS_LED1_ON + offs));
+
+	status = i2c_smbus_write_byte_data(&the_tps->client,
+			TPS_LED1_PER + offs, led_per);
+
+	if (status != 0) {
+		printk(KERN_ERR "%s: Failed to write led%i_per register\n",
+		       DRIVER_NAME, led);
+		up(&the_tps->lock);
+		return status;
+	}
+
+	dev_dbg (&the_tps->client.dev, "led%i_per  0x%02x\n", led,
+		i2c_smbus_read_byte_data(&the_tps->client, TPS_LED1_PER + offs));
+
+	up(&the_tps->lock);
+
+	return status;
+}
+EXPORT_SYMBOL(tps65010_set_led);
+
+/*-------------------------------------------------------------------------*/
+/* tps65010_set_vib parameter:
+ * value: ON or OFF
+ */
+int tps65010_set_vib(unsigned value)
+{
+	int	 status;
+	unsigned vdcdc2;
+
+	if (!the_tps)
+		return -ENODEV;
+
+	down(&the_tps->lock);
+
+	vdcdc2 = i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC2);
+	vdcdc2 &= ~(1 << 1);
+	if (value)
+		vdcdc2 |= (1 << 1);
+	status = i2c_smbus_write_byte_data(&the_tps->client,
+		TPS_VDCDC2, vdcdc2);
+
+	pr_debug("%s: vibrator %s\n", DRIVER_NAME, value ? "on" : "off");
+
+	up(&the_tps->lock);
+	return status;
+}
+EXPORT_SYMBOL(tps65010_set_vib);
+
+/*-------------------------------------------------------------------------*/
+/* tps65010_set_low_pwr parameter:
+ * mode: ON or OFF
+ */
+int tps65010_set_low_pwr(unsigned mode)
+{
+	int	 status;
+	unsigned vdcdc1;
+
+	if (!the_tps)
+		return -ENODEV;
+
+	down(&the_tps->lock);
+
+	pr_debug("%s: %s low_pwr, vdcdc1 0x%02x\n", DRIVER_NAME,
+		mode ? "enable" : "disable",
+		i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1));
+
+	vdcdc1 = i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1);
+
+	switch (mode) {
+	case OFF:
+		vdcdc1 &= ~TPS_ENABLE_LP; /* disable ENABLE_LP bit */
+		break;
+	/* case ON: */
+	default:
+		vdcdc1 |= TPS_ENABLE_LP;  /* enable ENABLE_LP bit */
+		break;
+	}
+
+	status = i2c_smbus_write_byte_data(&the_tps->client,
+			TPS_VDCDC1, vdcdc1);
+
+	if (status != 0)
+		printk(KERN_ERR "%s: Failed to write vdcdc1 register\n",
+		       DRIVER_NAME);
+	else
+		pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME,
+			i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1));
+
+	up(&the_tps->lock);
+
+	return status;
+}
+EXPORT_SYMBOL(tps65010_set_low_pwr);
+
+/*-------------------------------------------------------------------------*/
+/* tps65010_config_vregs1 parameter:
+ * value to be written to VREGS1 register
+ * Note: The complete register is written, set all bits you need
+ */
+int tps65010_config_vregs1(unsigned value)
+{
+	int	 status;
+
+	if (!the_tps)
+		return -ENODEV;
+
+	down(&the_tps->lock);
+
+	pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME,
+		        i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1));
+
+	status = i2c_smbus_write_byte_data(&the_tps->client,
+			TPS_VREGS1, value);
+
+	if (status != 0)
+		printk(KERN_ERR "%s: Failed to write vregs1 register\n",
+		        DRIVER_NAME);
+	else
+		pr_debug("%s: vregs1 0x%02x\n", DRIVER_NAME,
+			i2c_smbus_read_byte_data(&the_tps->client, TPS_VREGS1));
+
+	up(&the_tps->lock);
+
+	return status;
+}
+EXPORT_SYMBOL(tps65010_config_vregs1);
+
+/*-------------------------------------------------------------------------*/
+/* tps65013_set_low_pwr parameter:
+ * mode: ON or OFF
+ */
+
+/* FIXME: Assumes AC or USB power is present. Setting AUA bit is not
+	required if power supply is through a battery */
+
+int tps65013_set_low_pwr(unsigned mode)
+{
+	int	 status;
+	unsigned vdcdc1, chgconfig;
+
+	if (!the_tps || the_tps->por)
+		return -ENODEV;
+
+	down(&the_tps->lock);
+
+	pr_debug("%s: %s low_pwr, chgconfig 0x%02x vdcdc1 0x%02x\n",
+		DRIVER_NAME,
+		mode ? "enable" : "disable",
+		i2c_smbus_read_byte_data(&the_tps->client, TPS_CHGCONFIG),
+		i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1));
+
+	chgconfig = i2c_smbus_read_byte_data(&the_tps->client, TPS_CHGCONFIG);
+	vdcdc1 = i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1);
+
+	switch (mode) {
+	case OFF:
+		chgconfig &= ~TPS65013_AUA; /* disable AUA bit */
+		vdcdc1 &= ~TPS_ENABLE_LP; /* disable ENABLE_LP bit */
+		break;
+	/* case ON: */
+	default:
+		chgconfig |= TPS65013_AUA;  /* enable AUA bit */
+		vdcdc1 |= TPS_ENABLE_LP;  /* enable ENABLE_LP bit */
+		break;
+	}
+
+	status = i2c_smbus_write_byte_data(&the_tps->client,
+			TPS_CHGCONFIG, chgconfig);
+	if (status != 0) {
+		printk(KERN_ERR "%s: Failed to write chconfig register\n",
+	 DRIVER_NAME);
+		up(&the_tps->lock);
+		return status;
+	}
+
+	chgconfig = i2c_smbus_read_byte_data(&the_tps->client, TPS_CHGCONFIG);
+	the_tps->chgconf = chgconfig;
+	show_chgconfig(0, "chgconf", chgconfig);
+
+	status = i2c_smbus_write_byte_data(&the_tps->client,
+			TPS_VDCDC1, vdcdc1);
+
+	if (status != 0)
+		printk(KERN_ERR "%s: Failed to write vdcdc1 register\n",
+	 DRIVER_NAME);
+	else
+		pr_debug("%s: vdcdc1 0x%02x\n", DRIVER_NAME,
+			i2c_smbus_read_byte_data(&the_tps->client, TPS_VDCDC1));
+
+	up(&the_tps->lock);
+
+	return status;
+}
+EXPORT_SYMBOL(tps65013_set_low_pwr);
+
+/*-------------------------------------------------------------------------*/
+
+static int __init tps_init(void)
+{
+	u32	tries = 3;
+	int	status = -ENODEV;
+
+	printk(KERN_INFO "%s: version %s\n", DRIVER_NAME, DRIVER_VERSION);
+
+	/* some boards have startup glitches */
+	while (tries--) {
+		status = i2c_add_driver(&tps65010_driver);
+		if (the_tps)
+			break;
+		i2c_del_driver(&tps65010_driver);
+		if (!tries) {
+			printk(KERN_ERR "%s: no chip?\n", DRIVER_NAME);
+			return -ENODEV;
+		}
+		pr_debug("%s: re-probe ...\n", DRIVER_NAME);
+		msleep(10);
+	}
+
+#if defined(CONFIG_ARM)
+	if (machine_is_omap_osk()) {
+
+		// FIXME: More should be placed in the initialization code
+		//	  of the submodules (DSP, ethernet, power management,
+		//	  board-osk.c). Careful: I2C is initialized "late".
+
+		/* Let LED1 (D9) blink */
+		tps65010_set_led(LED1, BLINK);
+
+		/* Disable LED 2 (D2) */
+		tps65010_set_led(LED2, OFF);
+
+		/* Set GPIO 1 HIGH to disable VBUS power supply;
+		 * OHCI driver powers it up/down as needed.
+		 */
+		tps65010_set_gpio_out_value(GPIO1, HIGH);
+
+		/* Set GPIO 2 low to turn on LED D3 */
+		tps65010_set_gpio_out_value(GPIO2, HIGH);
+
+		/* Set GPIO 3 low to take ethernet out of reset */
+		tps65010_set_gpio_out_value(GPIO3, LOW);
+
+		/* gpio4 for VDD_DSP */
+
+		/* Enable LOW_PWR */
+		tps65010_set_low_pwr(ON);
+
+		/* Switch VLDO2 to 3.0V for AIC23 */
+		tps65010_config_vregs1(TPS_LDO2_ENABLE | TPS_VLDO2_3_0V | TPS_LDO1_ENABLE);
+
+	} else if (machine_is_omap_h2()) {
+		/* gpio3 for SD, gpio4 for VDD_DSP */
+
+		/* Enable LOW_PWR */
+		tps65010_set_low_pwr(ON);
+	} else if (machine_is_omap_h3()) {
+		/* gpio4 for SD, gpio3 for VDD_DSP */
+#ifdef CONFIG_PM
+		/* Enable LOW_PWR */
+		tps65013_set_low_pwr(ON);
+#endif
+	}
+#endif
+
+	return status;
+}
+/* NOTE:  this MUST be initialized before the other parts of the system
+ * that rely on it ... but after the i2c bus on which this relies.
+ * That is, much earlier than on PC-type systems, which don't often use
+ * I2C as a core system bus.
+ */
+subsys_initcall(tps_init);
+
+static void __exit tps_exit(void)
+{
+	i2c_del_driver(&tps65010_driver);
+}
+module_exit(tps_exit);
+
diff --git a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c
index 6614a59..137d9b7 100644
--- a/drivers/i2c/chips/via686a.c
+++ b/drivers/i2c/chips/via686a.c
@@ -1,12 +1,12 @@
 /*
     via686a.c - Part of lm_sensors, Linux kernel modules
                 for hardware monitoring
-                
+
     Copyright (c) 1998 - 2002  Frodo Looijaard <frodol@dds.nl>,
                         Kyösti Mälkki <kmalkki@cc.hut.fi>,
 			Mark Studebaker <mdsxyz123@yahoo.com>,
 			and Bob Dougherty <bobd@stanford.edu>
-    (Some conversion-factor data were contributed by Jonathan Teh Soon Yew 
+    (Some conversion-factor data were contributed by Jonathan Teh Soon Yew
     <j.teh@iname.com> and Alex van Kaam <darkside@chello.nl>.)
 
     This program is free software; you can redistribute it and/or modify
@@ -30,11 +30,9 @@
     Warning - only supports a single device.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
-#include <linux/delay.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
@@ -66,49 +64,46 @@
 /* Many VIA686A constants specified below */
 
 /* Length of ISA address segment */
-#define VIA686A_EXTENT 0x80
-#define VIA686A_BASE_REG 0x70
-#define VIA686A_ENABLE_REG 0x74
+#define VIA686A_EXTENT		0x80
+#define VIA686A_BASE_REG	0x70
+#define VIA686A_ENABLE_REG	0x74
 
 /* The VIA686A registers */
 /* ins numbered 0-4 */
-#define VIA686A_REG_IN_MAX(nr) (0x2b + ((nr) * 2))
-#define VIA686A_REG_IN_MIN(nr) (0x2c + ((nr) * 2))
-#define VIA686A_REG_IN(nr)     (0x22 + (nr))
+#define VIA686A_REG_IN_MAX(nr)	(0x2b + ((nr) * 2))
+#define VIA686A_REG_IN_MIN(nr)	(0x2c + ((nr) * 2))
+#define VIA686A_REG_IN(nr)	(0x22 + (nr))
 
 /* fans numbered 1-2 */
-#define VIA686A_REG_FAN_MIN(nr) (0x3a + (nr))
-#define VIA686A_REG_FAN(nr)     (0x28 + (nr))
-
-/* the following values are as speced by VIA: */
-static const u8 regtemp[] = { 0x20, 0x21, 0x1f };
-static const u8 regover[] = { 0x39, 0x3d, 0x1d };
-static const u8 reghyst[] = { 0x3a, 0x3e, 0x1e };
+#define VIA686A_REG_FAN_MIN(nr)	(0x3a + (nr))
+#define VIA686A_REG_FAN(nr)	(0x28 + (nr))
 
 /* temps numbered 1-3 */
-#define VIA686A_REG_TEMP(nr)		(regtemp[nr])
-#define VIA686A_REG_TEMP_OVER(nr)	(regover[nr])
-#define VIA686A_REG_TEMP_HYST(nr)	(reghyst[nr])
-#define VIA686A_REG_TEMP_LOW1	0x4b	// bits 7-6
-#define VIA686A_REG_TEMP_LOW23	0x49	// 2 = bits 5-4, 3 = bits 7-6
+static const u8 VIA686A_REG_TEMP[]	= { 0x20, 0x21, 0x1f };
+static const u8 VIA686A_REG_TEMP_OVER[]	= { 0x39, 0x3d, 0x1d };
+static const u8 VIA686A_REG_TEMP_HYST[]	= { 0x3a, 0x3e, 0x1e };
+/* bits 7-6 */
+#define VIA686A_REG_TEMP_LOW1	0x4b
+/* 2 = bits 5-4, 3 = bits 7-6 */
+#define VIA686A_REG_TEMP_LOW23	0x49
 
-#define VIA686A_REG_ALARM1 0x41
-#define VIA686A_REG_ALARM2 0x42
-#define VIA686A_REG_FANDIV 0x47
-#define VIA686A_REG_CONFIG 0x40
-/* The following register sets temp interrupt mode (bits 1-0 for temp1, 
+#define VIA686A_REG_ALARM1	0x41
+#define VIA686A_REG_ALARM2	0x42
+#define VIA686A_REG_FANDIV	0x47
+#define VIA686A_REG_CONFIG	0x40
+/* The following register sets temp interrupt mode (bits 1-0 for temp1,
  3-2 for temp2, 5-4 for temp3).  Modes are:
     00 interrupt stays as long as value is out-of-range
     01 interrupt is cleared once register is read (default)
     10 comparator mode- like 00, but ignores hysteresis
     11 same as 00 */
-#define VIA686A_REG_TEMP_MODE 0x4b
+#define VIA686A_REG_TEMP_MODE		0x4b
 /* We'll just assume that you want to set all 3 simultaneously: */
-#define VIA686A_TEMP_MODE_MASK 0x3F
-#define VIA686A_TEMP_MODE_CONTINUOUS (0x00)
+#define VIA686A_TEMP_MODE_MASK		0x3F
+#define VIA686A_TEMP_MODE_CONTINUOUS	0x00
 
 /* Conversions. Limit checking is only done on the TO_REG
-   variants. 
+   variants.
 
 ********* VOLTAGE CONVERSIONS (Bob Dougherty) ********
  From HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew):
@@ -121,7 +116,7 @@
  That is:
  volts = (25*regVal+133)*factor
  regVal = (volts/factor-133)/25
- (These conversions were contributed by Jonathan Teh Soon Yew 
+ (These conversions were contributed by Jonathan Teh Soon Yew
  <j.teh@iname.com>) */
 static inline u8 IN_TO_REG(long val, int inNum)
 {
@@ -182,55 +177,55 @@
       else
               return double(temp)*0.924-127.33;
 
- A fifth-order polynomial fits the unofficial data (provided by Alex van 
- Kaam <darkside@chello.nl>) a bit better.  It also give more reasonable 
- numbers on my machine (ie. they agree with what my BIOS tells me).  
+ A fifth-order polynomial fits the unofficial data (provided by Alex van
+ Kaam <darkside@chello.nl>) a bit better.  It also give more reasonable
+ numbers on my machine (ie. they agree with what my BIOS tells me).
  Here's the fifth-order fit to the 8-bit data:
- temp = 1.625093e-10*val^5 - 1.001632e-07*val^4 + 2.457653e-05*val^3 - 
+ temp = 1.625093e-10*val^5 - 1.001632e-07*val^4 + 2.457653e-05*val^3 -
         2.967619e-03*val^2 + 2.175144e-01*val - 7.090067e+0.
 
- (2000-10-25- RFD: thanks to Uwe Andersen <uandersen@mayah.com> for 
+ (2000-10-25- RFD: thanks to Uwe Andersen <uandersen@mayah.com> for
  finding my typos in this formula!)
 
- Alas, none of the elegant function-fit solutions will work because we 
- aren't allowed to use floating point in the kernel and doing it with 
- integers doesn't rpovide enough precision.  So we'll do boring old 
- look-up table stuff.  The unofficial data (see below) have effectively 
- 7-bit resolution (they are rounded to the nearest degree).  I'm assuming 
- that the transfer function of the device is monotonic and smooth, so a 
- smooth function fit to the data will allow us to get better precision.  
+ Alas, none of the elegant function-fit solutions will work because we
+ aren't allowed to use floating point in the kernel and doing it with
+ integers doesn't provide enough precision.  So we'll do boring old
+ look-up table stuff.  The unofficial data (see below) have effectively
+ 7-bit resolution (they are rounded to the nearest degree).  I'm assuming
+ that the transfer function of the device is monotonic and smooth, so a
+ smooth function fit to the data will allow us to get better precision.
  I used the 5th-order poly fit described above and solved for
- VIA register values 0-255.  I *10 before rounding, so we get tenth-degree 
- precision.  (I could have done all 1024 values for our 10-bit readings, 
- but the function is very linear in the useful range (0-80 deg C), so 
- we'll just use linear interpolation for 10-bit readings.)  So, tempLUT 
+ VIA register values 0-255.  I *10 before rounding, so we get tenth-degree
+ precision.  (I could have done all 1024 values for our 10-bit readings,
+ but the function is very linear in the useful range (0-80 deg C), so
+ we'll just use linear interpolation for 10-bit readings.)  So, tempLUT
  is the temp at via register values 0-255: */
 static const long tempLUT[] =
-    { -709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
-	    -503, -487, -471, -456, -442, -428, -414, -400, -387, -375,
-	    -362, -350, -339, -327, -316, -305, -295, -285, -275, -265,
-	    -255, -246, -237, -229, -220, -212, -204, -196, -188, -180,
-	    -173, -166, -159, -152, -145, -139, -132, -126, -120, -114,
-	    -108, -102, -96, -91, -85, -80, -74, -69, -64, -59, -54, -49,
-	    -44, -39, -34, -29, -25, -20, -15, -11, -6, -2, 3, 7, 12, 16,
-	    20, 25, 29, 33, 37, 42, 46, 50, 54, 59, 63, 67, 71, 75, 79, 84,
-	    88, 92, 96, 100, 104, 109, 113, 117, 121, 125, 130, 134, 138,
-	    142, 146, 151, 155, 159, 163, 168, 172, 176, 181, 185, 189,
-	    193, 198, 202, 206, 211, 215, 219, 224, 228, 232, 237, 241,
-	    245, 250, 254, 259, 263, 267, 272, 276, 281, 285, 290, 294,
-	    299, 303, 307, 312, 316, 321, 325, 330, 334, 339, 344, 348,
-	    353, 357, 362, 366, 371, 376, 380, 385, 390, 395, 399, 404,
-	    409, 414, 419, 423, 428, 433, 438, 443, 449, 454, 459, 464,
-	    469, 475, 480, 486, 491, 497, 502, 508, 514, 520, 526, 532,
-	    538, 544, 551, 557, 564, 571, 578, 584, 592, 599, 606, 614,
-	    621, 629, 637, 645, 654, 662, 671, 680, 689, 698, 708, 718,
-	    728, 738, 749, 759, 770, 782, 793, 805, 818, 830, 843, 856,
-	    870, 883, 898, 912, 927, 943, 958, 975, 991, 1008, 1026, 1044,
-	    1062, 1081, 1101, 1121, 1141, 1162, 1184, 1206, 1229, 1252,
-	    1276, 1301, 1326, 1352, 1378, 1406, 1434, 1462
+{ -709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
+	-503, -487, -471, -456, -442, -428, -414, -400, -387, -375,
+	-362, -350, -339, -327, -316, -305, -295, -285, -275, -265,
+	-255, -246, -237, -229, -220, -212, -204, -196, -188, -180,
+	-173, -166, -159, -152, -145, -139, -132, -126, -120, -114,
+	-108, -102, -96, -91, -85, -80, -74, -69, -64, -59, -54, -49,
+	-44, -39, -34, -29, -25, -20, -15, -11, -6, -2, 3, 7, 12, 16,
+	20, 25, 29, 33, 37, 42, 46, 50, 54, 59, 63, 67, 71, 75, 79, 84,
+	88, 92, 96, 100, 104, 109, 113, 117, 121, 125, 130, 134, 138,
+	142, 146, 151, 155, 159, 163, 168, 172, 176, 181, 185, 189,
+	193, 198, 202, 206, 211, 215, 219, 224, 228, 232, 237, 241,
+	245, 250, 254, 259, 263, 267, 272, 276, 281, 285, 290, 294,
+	299, 303, 307, 312, 316, 321, 325, 330, 334, 339, 344, 348,
+	353, 357, 362, 366, 371, 376, 380, 385, 390, 395, 399, 404,
+	409, 414, 419, 423, 428, 433, 438, 443, 449, 454, 459, 464,
+	469, 475, 480, 486, 491, 497, 502, 508, 514, 520, 526, 532,
+	538, 544, 551, 557, 564, 571, 578, 584, 592, 599, 606, 614,
+	621, 629, 637, 645, 654, 662, 671, 680, 689, 698, 708, 718,
+	728, 738, 749, 759, 770, 782, 793, 805, 818, 830, 843, 856,
+	870, 883, 898, 912, 927, 943, 958, 975, 991, 1008, 1026, 1044,
+	1062, 1081, 1101, 1121, 1141, 1162, 1184, 1206, 1229, 1252,
+	1276, 1301, 1326, 1352, 1378, 1406, 1434, 1462
 };
 
-/* the original LUT values from Alex van Kaam <darkside@chello.nl> 
+/* the original LUT values from Alex van Kaam <darkside@chello.nl>
    (for via register values 12-240):
 {-50,-49,-47,-45,-43,-41,-39,-38,-37,-35,-34,-33,-32,-31,
 -30,-29,-28,-27,-26,-25,-24,-24,-23,-22,-21,-20,-20,-19,-18,-17,-17,-16,-15,
@@ -245,26 +240,26 @@
 
 
  Here's the reverse LUT.  I got it by doing a 6-th order poly fit (needed
- an extra term for a good fit to these inverse data!) and then 
- solving for each temp value from -50 to 110 (the useable range for 
- this chip).  Here's the fit: 
- viaRegVal = -1.160370e-10*val^6 +3.193693e-08*val^5 - 1.464447e-06*val^4 
+ an extra term for a good fit to these inverse data!) and then
+ solving for each temp value from -50 to 110 (the useable range for
+ this chip).  Here's the fit:
+ viaRegVal = -1.160370e-10*val^6 +3.193693e-08*val^5 - 1.464447e-06*val^4
  - 2.525453e-04*val^3 + 1.424593e-02*val^2 + 2.148941e+00*val +7.275808e+01)
  Note that n=161: */
 static const u8 viaLUT[] =
-    { 12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 23,
-	    23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40,
-	    41, 43, 45, 46, 48, 49, 51, 53, 55, 57, 59, 60, 62, 64, 66,
-	    69, 71, 73, 75, 77, 79, 82, 84, 86, 88, 91, 93, 95, 98, 100,
-	    103, 105, 107, 110, 112, 115, 117, 119, 122, 124, 126, 129,
-	    131, 134, 136, 138, 140, 143, 145, 147, 150, 152, 154, 156,
-	    158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180,
-	    182, 183, 185, 187, 188, 190, 192, 193, 195, 196, 198, 199,
-	    200, 202, 203, 205, 206, 207, 208, 209, 210, 211, 212, 213,
-	    214, 215, 216, 217, 218, 219, 220, 221, 222, 222, 223, 224,
-	    225, 226, 226, 227, 228, 228, 229, 230, 230, 231, 232, 232,
-	    233, 233, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239,
-	    239, 240
+{ 12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 23,
+	23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40,
+	41, 43, 45, 46, 48, 49, 51, 53, 55, 57, 59, 60, 62, 64, 66,
+	69, 71, 73, 75, 77, 79, 82, 84, 86, 88, 91, 93, 95, 98, 100,
+	103, 105, 107, 110, 112, 115, 117, 119, 122, 124, 126, 129,
+	131, 134, 136, 138, 140, 143, 145, 147, 150, 152, 154, 156,
+	158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180,
+	182, 183, 185, 187, 188, 190, 192, 193, 195, 196, 198, 199,
+	200, 202, 203, 205, 206, 207, 208, 209, 210, 211, 212, 213,
+	214, 215, 216, 217, 218, 219, 220, 221, 222, 222, 223, 224,
+	225, 226, 226, 227, 228, 228, 229, 230, 230, 231, 232, 232,
+	233, 233, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239,
+	239, 240
 };
 
 /* Converting temps to (8-bit) hyst and over registers
@@ -272,7 +267,7 @@
    The +50 is because the temps start at -50 */
 static inline u8 TEMP_TO_REG(long val)
 {
-	return viaLUT[val <= -50000 ? 0 : val >= 110000 ? 160 : 
+	return viaLUT[val <= -50000 ? 0 : val >= 110000 ? 160 :
 		      (val < 0 ? val - 500 : val + 500) / 1000 + 50];
 }
 
@@ -291,11 +286,9 @@
 
 	/* do some linear interpolation */
 	return (tempLUT[eightBits] * (4 - twoBits) +
-	        tempLUT[eightBits + 1] * twoBits) * 25;
+		tempLUT[eightBits + 1] * twoBits) * 25;
 }
 
-#define ALARMS_FROM_REG(val) (val)
-
 #define DIV_FROM_REG(val) (1 << (val))
 #define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
 
@@ -358,54 +351,54 @@
 	return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_max[nr], nr));
 }
 
-static ssize_t set_in_min(struct device *dev, const char *buf, 
+static ssize_t set_in_min(struct device *dev, const char *buf,
 		size_t count, int nr) {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct via686a_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);
-	via686a_write_value(client, VIA686A_REG_IN_MIN(nr), 
+	data->in_min[nr] = IN_TO_REG(val, nr);
+	via686a_write_value(client, VIA686A_REG_IN_MIN(nr),
 			data->in_min[nr]);
 	up(&data->update_lock);
 	return count;
 }
-static ssize_t set_in_max(struct device *dev, const char *buf, 
+static ssize_t set_in_max(struct device *dev, const char *buf,
 		size_t count, int nr) {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct via686a_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);
-	via686a_write_value(client, VIA686A_REG_IN_MAX(nr), 
+	data->in_max[nr] = IN_TO_REG(val, nr);
+	via686a_write_value(client, VIA686A_REG_IN_MAX(nr),
 			data->in_max[nr]);
 	up(&data->update_lock);
 	return count;
 }
 #define show_in_offset(offset)					\
 static ssize_t 							\
-	show_in##offset (struct device *dev, char *buf)		\
+	show_in##offset (struct device *dev, struct device_attribute *attr, char *buf)		\
 {								\
 	return show_in(dev, buf, offset);			\
 }								\
 static ssize_t 							\
-	show_in##offset##_min (struct device *dev, char *buf)	\
+	show_in##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)	\
 {								\
 	return show_in_min(dev, buf, offset);		\
 }								\
 static ssize_t 							\
-	show_in##offset##_max (struct device *dev, char *buf)	\
+	show_in##offset##_max (struct device *dev, struct device_attribute *attr, char *buf)	\
 {								\
 	return show_in_max(dev, buf, offset);		\
 }								\
-static ssize_t set_in##offset##_min (struct device *dev, 	\
+static ssize_t set_in##offset##_min (struct device *dev, struct device_attribute *attr, 	\
 		const char *buf, size_t count) 			\
 {								\
 	return set_in_min(dev, buf, count, offset);		\
 }								\
-static ssize_t set_in##offset##_max (struct device *dev,	\
+static ssize_t set_in##offset##_max (struct device *dev, struct device_attribute *attr,	\
 			const char *buf, size_t count)		\
 {								\
 	return set_in_max(dev, buf, count, offset);		\
@@ -435,7 +428,7 @@
 	struct via686a_data *data = via686a_update_device(dev);
 	return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_hyst[nr]));
 }
-static ssize_t set_temp_over(struct device *dev, const char *buf, 
+static ssize_t set_temp_over(struct device *dev, const char *buf,
 		size_t count, int nr) {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct via686a_data *data = i2c_get_clientdata(client);
@@ -443,11 +436,12 @@
 
 	down(&data->update_lock);
 	data->temp_over[nr] = TEMP_TO_REG(val);
-	via686a_write_value(client, VIA686A_REG_TEMP_OVER(nr), data->temp_over[nr]);
+	via686a_write_value(client, VIA686A_REG_TEMP_OVER[nr],
+			    data->temp_over[nr]);
 	up(&data->update_lock);
 	return count;
 }
-static ssize_t set_temp_hyst(struct device *dev, const char *buf, 
+static ssize_t set_temp_hyst(struct device *dev, const char *buf,
 		size_t count, int nr) {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct via686a_data *data = i2c_get_clientdata(client);
@@ -455,31 +449,32 @@
 
 	down(&data->update_lock);
 	data->temp_hyst[nr] = TEMP_TO_REG(val);
-	via686a_write_value(client, VIA686A_REG_TEMP_HYST(nr), data->temp_hyst[nr]);
+	via686a_write_value(client, VIA686A_REG_TEMP_HYST[nr],
+			    data->temp_hyst[nr]);
 	up(&data->update_lock);
 	return count;
 }
 #define show_temp_offset(offset)					\
-static ssize_t show_temp_##offset (struct device *dev, char *buf)	\
+static ssize_t show_temp_##offset (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return show_temp(dev, buf, offset - 1);				\
 }									\
 static ssize_t								\
-show_temp_##offset##_over (struct device *dev, char *buf)		\
+show_temp_##offset##_over (struct device *dev, struct device_attribute *attr, char *buf)		\
 {									\
 	return show_temp_over(dev, buf, offset - 1);			\
 }									\
 static ssize_t								\
-show_temp_##offset##_hyst (struct device *dev, char *buf)		\
+show_temp_##offset##_hyst (struct device *dev, struct device_attribute *attr, char *buf)		\
 {									\
 	return show_temp_hyst(dev, buf, offset - 1);			\
 }									\
-static ssize_t set_temp_##offset##_over (struct device *dev, 		\
+static ssize_t set_temp_##offset##_over (struct device *dev, struct device_attribute *attr, 		\
 		const char *buf, size_t count) 				\
 {									\
 	return set_temp_over(dev, buf, count, offset - 1);		\
 }									\
-static ssize_t set_temp_##offset##_hyst (struct device *dev, 		\
+static ssize_t set_temp_##offset##_hyst (struct device *dev, struct device_attribute *attr, 		\
 		const char *buf, size_t count) 				\
 {									\
 	return set_temp_hyst(dev, buf, count, offset - 1);		\
@@ -488,7 +483,7 @@
 static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, 		\
 		show_temp_##offset##_over, set_temp_##offset##_over);	\
 static DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, 		\
-		show_temp_##offset##_hyst, set_temp_##offset##_hyst);	
+		show_temp_##offset##_hyst, set_temp_##offset##_hyst);
 
 show_temp_offset(1);
 show_temp_offset(2);
@@ -497,19 +492,19 @@
 /* 2 Fans */
 static ssize_t show_fan(struct device *dev, char *buf, int nr) {
 	struct via686a_data *data = via686a_update_device(dev);
-	return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr], 
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
 				DIV_FROM_REG(data->fan_div[nr])) );
 }
 static ssize_t show_fan_min(struct device *dev, char *buf, int nr) {
 	struct via686a_data *data = via686a_update_device(dev);
-	return sprintf(buf,"%d\n",
+	return sprintf(buf, "%d\n",
 		FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])) );
 }
 static ssize_t show_fan_div(struct device *dev, char *buf, int nr) {
 	struct via686a_data *data = via686a_update_device(dev);
-	return sprintf(buf,"%d\n", DIV_FROM_REG(data->fan_div[nr]) );
+	return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]) );
 }
-static ssize_t set_fan_min(struct device *dev, const char *buf, 
+static ssize_t set_fan_min(struct device *dev, const char *buf,
 		size_t count, int nr) {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct via686a_data *data = i2c_get_clientdata(client);
@@ -521,7 +516,7 @@
 	up(&data->update_lock);
 	return count;
 }
-static ssize_t set_fan_div(struct device *dev, const char *buf, 
+static ssize_t set_fan_div(struct device *dev, const char *buf,
 		size_t count, int nr) {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct via686a_data *data = i2c_get_clientdata(client);
@@ -538,24 +533,24 @@
 }
 
 #define show_fan_offset(offset)						\
-static ssize_t show_fan_##offset (struct device *dev, char *buf)	\
+static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return show_fan(dev, buf, offset - 1);				\
 }									\
-static ssize_t show_fan_##offset##_min (struct device *dev, char *buf)	\
+static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return show_fan_min(dev, buf, offset - 1);			\
 }									\
-static ssize_t show_fan_##offset##_div (struct device *dev, char *buf)	\
+static ssize_t show_fan_##offset##_div (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	return show_fan_div(dev, buf, offset - 1);			\
 }									\
-static ssize_t set_fan_##offset##_min (struct device *dev, 		\
+static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr, 		\
 	const char *buf, size_t count) 					\
 {									\
 	return set_fan_min(dev, buf, count, offset - 1);		\
 }									\
-static ssize_t set_fan_##offset##_div (struct device *dev, 		\
+static ssize_t set_fan_##offset##_div (struct device *dev, struct device_attribute *attr, 		\
 		const char *buf, size_t count) 				\
 {									\
 	return set_fan_div(dev, buf, count, offset - 1);		\
@@ -570,9 +565,9 @@
 show_fan_offset(2);
 
 /* Alarms */
-static ssize_t show_alarms(struct device *dev, char *buf) {
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) {
 	struct via686a_data *data = via686a_update_device(dev);
-	return sprintf(buf,"%d\n", ALARMS_FROM_REG(data->alarms));
+	return sprintf(buf, "%u\n", data->alarms);
 }
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
@@ -612,11 +607,12 @@
 	}
 
 	/* 8231 requires multiple of 256, we enforce that on 686 as well */
-	if(force_addr)
+	if (force_addr)
 		address = force_addr & 0xFF00;
 
-	if(force_addr) {
-		dev_warn(&adapter->dev,"forcing ISA address 0x%04X\n", address);
+	if (force_addr) {
+		dev_warn(&adapter->dev, "forcing ISA address 0x%04X\n",
+			 address);
 		if (PCIBIOS_SUCCESSFUL !=
 		    pci_write_config_word(s_bridge, VIA686A_BASE_REG, address))
 			return -ENODEV;
@@ -625,17 +621,17 @@
 	    pci_read_config_word(s_bridge, VIA686A_ENABLE_REG, &val))
 		return -ENODEV;
 	if (!(val & 0x0001)) {
-		dev_warn(&adapter->dev,"enabling sensors\n");
+		dev_warn(&adapter->dev, "enabling sensors\n");
 		if (PCIBIOS_SUCCESSFUL !=
 		    pci_write_config_word(s_bridge, VIA686A_ENABLE_REG,
-		                      val | 0x0001))
+					  val | 0x0001))
 			return -ENODEV;
 	}
 
 	/* Reserve the ISA region */
 	if (!request_region(address, VIA686A_EXTENT, via686a_driver.name)) {
-		dev_err(&adapter->dev,"region 0x%x already in use!\n",
-		       address);
+		dev_err(&adapter->dev, "region 0x%x already in use!\n",
+			address);
 		return -ENODEV;
 	}
 
@@ -660,7 +656,7 @@
 	/* Tell the I2C layer a new client has arrived */
 	if ((err = i2c_attach_client(new_client)))
 		goto ERROR3;
-	
+
 	/* Initialize the VIA686A chip */
 	via686a_init_client(new_client);
 
@@ -699,9 +695,9 @@
 
 	return 0;
 
-      ERROR3:
+ERROR3:
 	kfree(data);
-      ERROR0:
+ERROR0:
 	release_region(address, VIA686A_EXTENT);
 	return err;
 }
@@ -732,7 +728,7 @@
 	via686a_write_value(client, VIA686A_REG_CONFIG, (reg|0x01)&0x7F);
 
 	/* Configure temp interrupt mode for continuous-interrupt operation */
-	via686a_write_value(client, VIA686A_REG_TEMP_MODE, 
+	via686a_write_value(client, VIA686A_REG_TEMP_MODE,
 			    via686a_read_value(client, VIA686A_REG_TEMP_MODE) &
 			    !(VIA686A_TEMP_MODE_MASK | VIA686A_TEMP_MODE_CONTINUOUS));
 }
@@ -764,15 +760,15 @@
 		}
 		for (i = 0; i <= 2; i++) {
 			data->temp[i] = via686a_read_value(client,
-						 VIA686A_REG_TEMP(i)) << 2;
+						 VIA686A_REG_TEMP[i]) << 2;
 			data->temp_over[i] =
 			    via686a_read_value(client,
-					       VIA686A_REG_TEMP_OVER(i));
+					       VIA686A_REG_TEMP_OVER[i]);
 			data->temp_hyst[i] =
 			    via686a_read_value(client,
-					       VIA686A_REG_TEMP_HYST(i));
+					       VIA686A_REG_TEMP_HYST[i]);
 		}
-		/* add in lower 2 bits 
+		/* add in lower 2 bits
 		   temp1 uses bits 7-6 of VIA686A_REG_TEMP_LOW1
 		   temp2 uses bits 5-4 of VIA686A_REG_TEMP_LOW23
 		   temp3 uses bits 7-6 of VIA686A_REG_TEMP_LOW23
@@ -804,35 +800,36 @@
 }
 
 static struct pci_device_id via686a_pci_ids[] = {
-       { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) },
-       { 0, }
+	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) },
+	{ 0, }
 };
 
 MODULE_DEVICE_TABLE(pci, via686a_pci_ids);
 
 static int __devinit via686a_pci_probe(struct pci_dev *dev,
-                                      const struct pci_device_id *id)
+				       const struct pci_device_id *id)
 {
-       u16 val;
-       int addr = 0;
+	u16 val;
+	int addr = 0;
 
-       if (PCIBIOS_SUCCESSFUL !=
-           pci_read_config_word(dev, VIA686A_BASE_REG, &val))
-               return -ENODEV;
+	if (PCIBIOS_SUCCESSFUL !=
+	    pci_read_config_word(dev, VIA686A_BASE_REG, &val))
+		return -ENODEV;
 
-       addr = val & ~(VIA686A_EXTENT - 1);
-       if (addr == 0 && force_addr == 0) {
-               dev_err(&dev->dev,"base address not set - upgrade BIOS or use force_addr=0xaddr\n");
-               return -ENODEV;
-       }
-       if (force_addr)
-               addr = force_addr;      /* so detect will get called */
+	addr = val & ~(VIA686A_EXTENT - 1);
+	if (addr == 0 && force_addr == 0) {
+		dev_err(&dev->dev, "base address not set - upgrade BIOS "
+			"or use force_addr=0xaddr\n");
+		return -ENODEV;
+	}
+	if (force_addr)
+		addr = force_addr;	/* so detect will get called */
 
-       if (!addr) {
-               dev_err(&dev->dev,"No Via 686A sensors found.\n");
-               return -ENODEV;
-       }
-       normal_isa[0] = addr;
+	if (!addr) {
+		dev_err(&dev->dev, "No Via 686A sensors found.\n");
+		return -ENODEV;
+	}
+	normal_isa[0] = addr;
 
 	s_bridge = pci_dev_get(dev);
 	if (i2c_add_driver(&via686a_driver)) {
@@ -848,14 +845,14 @@
 }
 
 static struct pci_driver via686a_pci_driver = {
-       .name		= "via686a",
-       .id_table	= via686a_pci_ids,
-       .probe		= via686a_pci_probe,
+	.name		= "via686a",
+	.id_table	= via686a_pci_ids,
+	.probe		= via686a_pci_probe,
 };
 
 static int __init sm_via686a_init(void)
 {
-       return pci_register_driver(&via686a_pci_driver);
+	return pci_register_driver(&via686a_pci_driver);
 }
 
 static void __exit sm_via686a_exit(void)
@@ -869,8 +866,8 @@
 }
 
 MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>, "
-              "Mark Studebaker <mdsxyz123@yahoo.com> "
-             "and Bob Dougherty <bobd@stanford.edu>");
+	      "Mark Studebaker <mdsxyz123@yahoo.com> "
+	      "and Bob Dougherty <bobd@stanford.edu>");
 MODULE_DESCRIPTION("VIA 686A Sensor device");
 MODULE_LICENSE("GPL");
 
diff --git a/drivers/i2c/chips/w83627ehf.c b/drivers/i2c/chips/w83627ehf.c
new file mode 100644
index 0000000..8a40b69
--- /dev/null
+++ b/drivers/i2c/chips/w83627ehf.c
@@ -0,0 +1,846 @@
+/*
+    w83627ehf - Driver for the hardware monitoring functionality of
+                the Winbond W83627EHF Super-I/O chip
+    Copyright (C) 2005  Jean Delvare <khali@linux-fr.org>
+
+    Shamelessly ripped from the w83627hf driver
+    Copyright (C) 2003  Mark Studebaker
+
+    Thanks to Leon Moonen, Steve Cliffe and Grant Coady for their help
+    in testing and debugging this driver.
+
+    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 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.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <asm/io.h>
+#include "lm75.h"
+
+/* Addresses to scan
+   The actual ISA address is read from Super-I/O configuration space */
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+static unsigned int normal_isa[] = { 0, I2C_CLIENT_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_1(w83627ehf);
+
+/*
+ * Super-I/O constants and functions
+ */
+
+static int REG;		/* The register to read/write */
+static int VAL;		/* The value to read/write */
+
+#define W83627EHF_LD_HWM	0x0b
+
+#define SIO_REG_LDSEL		0x07	/* Logical device select */
+#define SIO_REG_DEVID		0x20	/* Device ID (2 bytes) */
+#define SIO_REG_ENABLE		0x30	/* Logical device enable */
+#define SIO_REG_ADDR		0x60	/* Logical device address (2 bytes) */
+
+#define SIO_W83627EHF_ID	0x8840
+#define SIO_ID_MASK		0xFFC0
+
+static inline void
+superio_outb(int reg, int val)
+{
+	outb(reg, REG);
+	outb(val, VAL);
+}
+
+static inline int
+superio_inb(int reg)
+{
+	outb(reg, REG);
+	return inb(VAL);
+}
+
+static inline void
+superio_select(int ld)
+{
+	outb(SIO_REG_LDSEL, REG);
+	outb(ld, VAL);
+}
+
+static inline void
+superio_enter(void)
+{
+	outb(0x87, REG);
+	outb(0x87, REG);
+}
+
+static inline void
+superio_exit(void)
+{
+	outb(0x02, REG);
+	outb(0x02, VAL);
+}
+
+/*
+ * ISA constants
+ */
+
+#define REGION_LENGTH		8
+#define ADDR_REG_OFFSET		5
+#define DATA_REG_OFFSET		6
+
+#define W83627EHF_REG_BANK		0x4E
+#define W83627EHF_REG_CONFIG		0x40
+#define W83627EHF_REG_CHIP_ID		0x49
+#define W83627EHF_REG_MAN_ID		0x4F
+
+static const u16 W83627EHF_REG_FAN[] = { 0x28, 0x29, 0x2a, 0x3f, 0x553 };
+static const u16 W83627EHF_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d, 0x3e, 0x55c };
+
+#define W83627EHF_REG_TEMP1		0x27
+#define W83627EHF_REG_TEMP1_HYST	0x3a
+#define W83627EHF_REG_TEMP1_OVER	0x39
+static const u16 W83627EHF_REG_TEMP[] = { 0x150, 0x250 };
+static const u16 W83627EHF_REG_TEMP_HYST[] = { 0x153, 0x253 };
+static const u16 W83627EHF_REG_TEMP_OVER[] = { 0x155, 0x255 };
+static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0x152, 0x252 };
+
+/* Fan clock dividers are spread over the following five registers */
+#define W83627EHF_REG_FANDIV1		0x47
+#define W83627EHF_REG_FANDIV2		0x4B
+#define W83627EHF_REG_VBAT		0x5D
+#define W83627EHF_REG_DIODE		0x59
+#define W83627EHF_REG_SMI_OVT		0x4C
+
+/*
+ * Conversions
+ */
+
+static inline unsigned int
+fan_from_reg(u8 reg, unsigned int div)
+{
+	if (reg == 0 || reg == 255)
+		return 0;
+	return 1350000U / (reg * div);
+}
+
+static inline unsigned int
+div_from_reg(u8 reg)
+{
+	return 1 << reg;
+}
+
+static inline int
+temp1_from_reg(s8 reg)
+{
+	return reg * 1000;
+}
+
+static inline s8
+temp1_to_reg(int temp)
+{
+	if (temp <= -128000)
+		return -128;
+	if (temp >= 127000)
+		return 127;
+	if (temp < 0)
+		return (temp - 500) / 1000;
+	return (temp + 500) / 1000;
+}
+
+/*
+ * Data structures and manipulation thereof
+ */
+
+struct w83627ehf_data {
+	struct i2c_client client;
+	struct semaphore lock;
+
+	struct semaphore update_lock;
+	char valid;		/* !=0 if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+
+	/* Register values */
+	u8 fan[5];
+	u8 fan_min[5];
+	u8 fan_div[5];
+	u8 has_fan;		/* some fan inputs can be disabled */
+	s8 temp1;
+	s8 temp1_max;
+	s8 temp1_max_hyst;
+	s16 temp[2];
+	s16 temp_max[2];
+	s16 temp_max_hyst[2];
+};
+
+static inline int is_word_sized(u16 reg)
+{
+	return (((reg & 0xff00) == 0x100
+	      || (reg & 0xff00) == 0x200)
+	     && ((reg & 0x00ff) == 0x50
+	      || (reg & 0x00ff) == 0x53
+	      || (reg & 0x00ff) == 0x55));
+}
+
+/* We assume that the default bank is 0, thus the following two functions do
+   nothing for registers which live in bank 0. For others, they respectively
+   set the bank register to the correct value (before the register is
+   accessed), and back to 0 (afterwards). */
+static inline void w83627ehf_set_bank(struct i2c_client *client, u16 reg)
+{
+	if (reg & 0xff00) {
+		outb_p(W83627EHF_REG_BANK, client->addr + ADDR_REG_OFFSET);
+		outb_p(reg >> 8, client->addr + DATA_REG_OFFSET);
+	}
+}
+
+static inline void w83627ehf_reset_bank(struct i2c_client *client, u16 reg)
+{
+	if (reg & 0xff00) {
+		outb_p(W83627EHF_REG_BANK, client->addr + ADDR_REG_OFFSET);
+		outb_p(0, client->addr + DATA_REG_OFFSET);
+	}
+}
+
+static u16 w83627ehf_read_value(struct i2c_client *client, u16 reg)
+{
+	struct w83627ehf_data *data = i2c_get_clientdata(client);
+	int res, word_sized = is_word_sized(reg);
+
+	down(&data->lock);
+
+	w83627ehf_set_bank(client, reg);
+	outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET);
+	res = inb_p(client->addr + DATA_REG_OFFSET);
+	if (word_sized) {
+		outb_p((reg & 0xff) + 1,
+		       client->addr + ADDR_REG_OFFSET);
+		res = (res << 8) + inb_p(client->addr + DATA_REG_OFFSET);
+	}
+	w83627ehf_reset_bank(client, reg);
+
+	up(&data->lock);
+
+	return res;
+}
+
+static int w83627ehf_write_value(struct i2c_client *client, u16 reg, u16 value)
+{
+	struct w83627ehf_data *data = i2c_get_clientdata(client);
+	int word_sized = is_word_sized(reg);
+
+	down(&data->lock);
+
+	w83627ehf_set_bank(client, reg);
+	outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET);
+	if (word_sized) {
+		outb_p(value >> 8, client->addr + DATA_REG_OFFSET);
+		outb_p((reg & 0xff) + 1,
+		       client->addr + ADDR_REG_OFFSET);
+	}
+	outb_p(value & 0xff, client->addr + DATA_REG_OFFSET);
+	w83627ehf_reset_bank(client, reg);
+
+	up(&data->lock);
+	return 0;
+}
+
+/* This function assumes that the caller holds data->update_lock */
+static void w83627ehf_write_fan_div(struct i2c_client *client, int nr)
+{
+	struct w83627ehf_data *data = i2c_get_clientdata(client);
+	u8 reg;
+
+	switch (nr) {
+	case 0:
+		reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0xcf)
+		    | ((data->fan_div[0] & 0x03) << 4);
+		w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg);
+		reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xdf)
+		    | ((data->fan_div[0] & 0x04) << 3);
+		w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
+		break;
+	case 1:
+		reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0x3f)
+		    | ((data->fan_div[1] & 0x03) << 6);
+		w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg);
+		reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xbf)
+		    | ((data->fan_div[1] & 0x04) << 4);
+		w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
+		break;
+	case 2:
+		reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV2) & 0x3f)
+		    | ((data->fan_div[2] & 0x03) << 6);
+		w83627ehf_write_value(client, W83627EHF_REG_FANDIV2, reg);
+		reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0x7f)
+		    | ((data->fan_div[2] & 0x04) << 5);
+		w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
+		break;
+	case 3:
+		reg = (w83627ehf_read_value(client, W83627EHF_REG_DIODE) & 0xfc)
+		    | (data->fan_div[3] & 0x03);
+		w83627ehf_write_value(client, W83627EHF_REG_DIODE, reg);
+		reg = (w83627ehf_read_value(client, W83627EHF_REG_SMI_OVT) & 0x7f)
+		    | ((data->fan_div[3] & 0x04) << 5);
+		w83627ehf_write_value(client, W83627EHF_REG_SMI_OVT, reg);
+		break;
+	case 4:
+		reg = (w83627ehf_read_value(client, W83627EHF_REG_DIODE) & 0x73)
+		    | ((data->fan_div[4] & 0x03) << 3)
+		    | ((data->fan_div[4] & 0x04) << 5);
+		w83627ehf_write_value(client, W83627EHF_REG_DIODE, reg);
+		break;
+	}
+}
+
+static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83627ehf_data *data = i2c_get_clientdata(client);
+	int i;
+
+	down(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ)
+	 || !data->valid) {
+		/* Fan clock dividers */
+		i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1);
+		data->fan_div[0] = (i >> 4) & 0x03;
+		data->fan_div[1] = (i >> 6) & 0x03;
+		i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV2);
+		data->fan_div[2] = (i >> 6) & 0x03;
+		i = w83627ehf_read_value(client, W83627EHF_REG_VBAT);
+		data->fan_div[0] |= (i >> 3) & 0x04;
+		data->fan_div[1] |= (i >> 4) & 0x04;
+		data->fan_div[2] |= (i >> 5) & 0x04;
+		if (data->has_fan & ((1 << 3) | (1 << 4))) {
+			i = w83627ehf_read_value(client, W83627EHF_REG_DIODE);
+			data->fan_div[3] = i & 0x03;
+			data->fan_div[4] = ((i >> 2) & 0x03)
+					 | ((i >> 5) & 0x04);
+		}
+		if (data->has_fan & (1 << 3)) {
+			i = w83627ehf_read_value(client, W83627EHF_REG_SMI_OVT);
+			data->fan_div[3] |= (i >> 5) & 0x04;
+		}
+
+		/* Measured fan speeds and limits */
+		for (i = 0; i < 5; i++) {
+			if (!(data->has_fan & (1 << i)))
+				continue;
+
+			data->fan[i] = w83627ehf_read_value(client,
+				       W83627EHF_REG_FAN[i]);
+			data->fan_min[i] = w83627ehf_read_value(client,
+					   W83627EHF_REG_FAN_MIN[i]);
+
+			/* If we failed to measure the fan speed and clock
+			   divider can be increased, let's try that for next
+			   time */
+			if (data->fan[i] == 0xff
+			 && data->fan_div[i] < 0x07) {
+			 	dev_dbg(&client->dev, "Increasing fan %d "
+					"clock divider from %u to %u\n",
+					i, div_from_reg(data->fan_div[i]),
+					div_from_reg(data->fan_div[i] + 1));
+				data->fan_div[i]++;
+				w83627ehf_write_fan_div(client, i);
+				/* Preserve min limit if possible */
+				if (data->fan_min[i] >= 2
+				 && data->fan_min[i] != 255)
+					w83627ehf_write_value(client,
+						W83627EHF_REG_FAN_MIN[i],
+						(data->fan_min[i] /= 2));
+			}
+		}
+
+		/* Measured temperatures and limits */
+		data->temp1 = w83627ehf_read_value(client,
+			      W83627EHF_REG_TEMP1);
+		data->temp1_max = w83627ehf_read_value(client,
+				  W83627EHF_REG_TEMP1_OVER);
+		data->temp1_max_hyst = w83627ehf_read_value(client,
+				       W83627EHF_REG_TEMP1_HYST);
+		for (i = 0; i < 2; i++) {
+			data->temp[i] = w83627ehf_read_value(client,
+					W83627EHF_REG_TEMP[i]);
+			data->temp_max[i] = w83627ehf_read_value(client,
+					    W83627EHF_REG_TEMP_OVER[i]);
+			data->temp_max_hyst[i] = w83627ehf_read_value(client,
+						 W83627EHF_REG_TEMP_HYST[i]);
+		}
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	up(&data->update_lock);
+	return data;
+}
+
+/*
+ * Sysfs callback functions
+ */
+
+#define show_fan_reg(reg) \
+static ssize_t \
+show_##reg(struct device *dev, char *buf, int nr) \
+{ \
+	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
+	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
+show_fan_div(struct device *dev, char *buf, int nr)
+{
+	struct w83627ehf_data *data = w83627ehf_update_device(dev);
+	return sprintf(buf, "%u\n",
+		       div_from_reg(data->fan_div[nr]));
+}
+
+static ssize_t
+store_fan_min(struct device *dev, const char *buf, size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct w83627ehf_data *data = i2c_get_clientdata(client);
+	unsigned int val = simple_strtoul(buf, NULL, 10);
+	unsigned int reg;
+	u8 new_div;
+
+	down(&data->update_lock);
+	if (!val) {
+		/* No min limit, alarm disabled */
+		data->fan_min[nr] = 255;
+		new_div = data->fan_div[nr]; /* No change */
+		dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
+	} else if ((reg = 1350000U / val) >= 128 * 255) {
+		/* Speed below this value cannot possibly be represented,
+		   even with the highest divider (128) */
+		data->fan_min[nr] = 254;
+		new_div = 7; /* 128 == (1 << 7) */
+		dev_warn(dev, "fan%u low limit %u below minimum %u, set to "
+			 "minimum\n", nr + 1, val, fan_from_reg(254, 128));
+	} else if (!reg) {
+		/* Speed above this value cannot possibly be represented,
+		   even with the lowest divider (1) */
+		data->fan_min[nr] = 1;
+		new_div = 0; /* 1 == (1 << 0) */
+		dev_warn(dev, "fan%u low limit %u above maximum %u, set to "
+			 "maximum\n", nr + 1, val, fan_from_reg(1, 1));
+	} else {
+		/* Automatically pick the best divider, i.e. the one such
+		   that the min limit will correspond to a register value
+		   in the 96..192 range */
+		new_div = 0;
+		while (reg > 192 && new_div < 7) {
+			reg >>= 1;
+			new_div++;
+		}
+		data->fan_min[nr] = reg;
+	}
+
+	/* Write both the fan clock divider (if it changed) and the new
+	   fan min (unconditionally) */
+	if (new_div != data->fan_div[nr]) {
+		if (new_div > data->fan_div[nr])
+			data->fan[nr] >>= (data->fan_div[nr] - new_div);
+		else
+			data->fan[nr] <<= (new_div - data->fan_div[nr]);
+
+		dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
+			nr + 1, div_from_reg(data->fan_div[nr]),
+			div_from_reg(new_div));
+		data->fan_div[nr] = new_div;
+		w83627ehf_write_fan_div(client, nr);
+	}
+	w83627ehf_write_value(client, W83627EHF_REG_FAN_MIN[nr],
+			      data->fan_min[nr]);
+	up(&data->update_lock);
+
+	return count;
+}
+
+#define sysfs_fan_offset(offset) \
+static ssize_t \
+show_reg_fan_##offset(struct device *dev, struct device_attribute *attr, \
+		      char *buf) \
+{ \
+	return show_fan(dev, buf, offset-1); \
+} \
+static DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
+		   show_reg_fan_##offset, NULL);
+
+#define sysfs_fan_min_offset(offset) \
+static ssize_t \
+show_reg_fan##offset##_min(struct device *dev, struct device_attribute *attr, \
+			   char *buf) \
+{ \
+	return show_fan_min(dev, buf, offset-1); \
+} \
+static ssize_t \
+store_reg_fan##offset##_min(struct device *dev, struct device_attribute *attr, \
+			    const char *buf, size_t count) \
+{ \
+	return store_fan_min(dev, buf, count, offset-1); \
+} \
+static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
+		   show_reg_fan##offset##_min, \
+		   store_reg_fan##offset##_min);
+
+#define sysfs_fan_div_offset(offset) \
+static ssize_t \
+show_reg_fan##offset##_div(struct device *dev, struct device_attribute *attr, \
+			   char *buf) \
+{ \
+	return show_fan_div(dev, buf, offset - 1); \
+} \
+static DEVICE_ATTR(fan##offset##_div, S_IRUGO, \
+		   show_reg_fan##offset##_div, NULL);
+
+sysfs_fan_offset(1);
+sysfs_fan_min_offset(1);
+sysfs_fan_div_offset(1);
+sysfs_fan_offset(2);
+sysfs_fan_min_offset(2);
+sysfs_fan_div_offset(2);
+sysfs_fan_offset(3);
+sysfs_fan_min_offset(3);
+sysfs_fan_div_offset(3);
+sysfs_fan_offset(4);
+sysfs_fan_min_offset(4);
+sysfs_fan_div_offset(4);
+sysfs_fan_offset(5);
+sysfs_fan_min_offset(5);
+sysfs_fan_div_offset(5);
+
+#define show_temp1_reg(reg) \
+static ssize_t \
+show_##reg(struct device *dev, struct device_attribute *attr, \
+	   char *buf) \
+{ \
+	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
+	return sprintf(buf, "%d\n", temp1_from_reg(data->reg)); \
+}
+show_temp1_reg(temp1);
+show_temp1_reg(temp1_max);
+show_temp1_reg(temp1_max_hyst);
+
+#define store_temp1_reg(REG, reg) \
+static ssize_t \
+store_temp1_##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); \
+	u32 val = simple_strtoul(buf, NULL, 10); \
+ \
+	down(&data->update_lock); \
+	data->temp1_##reg = temp1_to_reg(val); \
+	w83627ehf_write_value(client, W83627EHF_REG_TEMP1_##REG, \
+			      data->temp1_##reg); \
+	up(&data->update_lock); \
+	return count; \
+}
+store_temp1_reg(OVER, max);
+store_temp1_reg(HYST, max_hyst);
+
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1, NULL);
+static DEVICE_ATTR(temp1_max, S_IRUGO| S_IWUSR,
+		   show_temp1_max, store_temp1_max);
+static DEVICE_ATTR(temp1_max_hyst, S_IRUGO| S_IWUSR,
+		   show_temp1_max_hyst, store_temp1_max_hyst);
+
+#define show_temp_reg(reg) \
+static ssize_t \
+show_##reg (struct device *dev, char *buf, int nr) \
+{ \
+	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
+	return sprintf(buf, "%d\n", \
+		       LM75_TEMP_FROM_REG(data->reg[nr])); \
+}
+show_temp_reg(temp);
+show_temp_reg(temp_max);
+show_temp_reg(temp_max_hyst);
+
+#define store_temp_reg(REG, reg) \
+static ssize_t \
+store_##reg (struct device *dev, const char *buf, size_t count, int nr) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct w83627ehf_data *data = i2c_get_clientdata(client); \
+	u32 val = simple_strtoul(buf, NULL, 10); \
+ \
+	down(&data->update_lock); \
+	data->reg[nr] = LM75_TEMP_TO_REG(val); \
+	w83627ehf_write_value(client, W83627EHF_REG_TEMP_##REG[nr], \
+			      data->reg[nr]); \
+	up(&data->update_lock); \
+	return count; \
+}
+store_temp_reg(OVER, temp_max);
+store_temp_reg(HYST, temp_max_hyst);
+
+#define sysfs_temp_offset(offset) \
+static ssize_t \
+show_reg_temp##offset (struct device *dev, struct device_attribute *attr, \
+		       char *buf) \
+{ \
+	return show_temp(dev, buf, offset - 2); \
+} \
+static DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
+		   show_reg_temp##offset, NULL);
+
+#define sysfs_temp_reg_offset(reg, offset) \
+static ssize_t \
+show_reg_temp##offset##_##reg(struct device *dev, struct device_attribute *attr, \
+			      char *buf) \
+{ \
+	return show_temp_##reg(dev, buf, offset - 2); \
+} \
+static ssize_t \
+store_reg_temp##offset##_##reg(struct device *dev, struct device_attribute *attr, \
+			       const char *buf, size_t count) \
+{ \
+	return store_temp_##reg(dev, buf, count, offset - 2); \
+} \
+static DEVICE_ATTR(temp##offset##_##reg, S_IRUGO| S_IWUSR, \
+		   show_reg_temp##offset##_##reg, \
+		   store_reg_temp##offset##_##reg);
+
+sysfs_temp_offset(2);
+sysfs_temp_reg_offset(max, 2);
+sysfs_temp_reg_offset(max_hyst, 2);
+sysfs_temp_offset(3);
+sysfs_temp_reg_offset(max, 3);
+sysfs_temp_reg_offset(max_hyst, 3);
+
+/*
+ * Driver and client management
+ */
+
+static struct i2c_driver w83627ehf_driver;
+
+static void w83627ehf_init_client(struct i2c_client *client)
+{
+	int i;
+	u8 tmp;
+
+	/* Start monitoring is needed */
+	tmp = w83627ehf_read_value(client, W83627EHF_REG_CONFIG);
+	if (!(tmp & 0x01))
+		w83627ehf_write_value(client, W83627EHF_REG_CONFIG,
+				      tmp | 0x01);
+
+	/* Enable temp2 and temp3 if needed */
+	for (i = 0; i < 2; i++) {
+		tmp = w83627ehf_read_value(client,
+					   W83627EHF_REG_TEMP_CONFIG[i]);
+		if (tmp & 0x01)
+			w83627ehf_write_value(client,
+					      W83627EHF_REG_TEMP_CONFIG[i],
+					      tmp & 0xfe);
+	}
+}
+
+static int w83627ehf_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *client;
+	struct w83627ehf_data *data;
+	int i, err = 0;
+
+	if (!i2c_is_isa_adapter(adapter))
+		return 0;
+
+	if (!request_region(address, REGION_LENGTH, w83627ehf_driver.name)) {
+		err = -EBUSY;
+		goto exit;
+	}
+
+	if (!(data = kmalloc(sizeof(struct w83627ehf_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit_release;
+	}
+	memset(data, 0, sizeof(struct w83627ehf_data));
+
+	client = &data->client;
+	i2c_set_clientdata(client, data);
+	client->addr = address;
+	init_MUTEX(&data->lock);
+	client->adapter = adapter;
+	client->driver = &w83627ehf_driver;
+	client->flags = 0;
+
+	strlcpy(client->name, "w83627ehf", I2C_NAME_SIZE);
+	data->valid = 0;
+	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 chip */
+	w83627ehf_init_client(client);
+
+	/* A few vars need to be filled upon startup */
+	for (i = 0; i < 5; i++)
+		data->fan_min[i] = w83627ehf_read_value(client,
+				   W83627EHF_REG_FAN_MIN[i]);
+
+	/* It looks like fan4 and fan5 pins can be alternatively used
+	   as fan on/off switches */
+	data->has_fan = 0x07; /* fan1, fan2 and fan3 */
+	i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1);
+	if (i & (1 << 2))
+		data->has_fan |= (1 << 3);
+	if (i & (1 << 0))
+		data->has_fan |= (1 << 4);
+
+	/* Register sysfs hooks */
+	device_create_file(&client->dev, &dev_attr_fan1_input);
+	device_create_file(&client->dev, &dev_attr_fan1_min);
+	device_create_file(&client->dev, &dev_attr_fan1_div);
+	device_create_file(&client->dev, &dev_attr_fan2_input);
+	device_create_file(&client->dev, &dev_attr_fan2_min);
+	device_create_file(&client->dev, &dev_attr_fan2_div);
+	device_create_file(&client->dev, &dev_attr_fan3_input);
+	device_create_file(&client->dev, &dev_attr_fan3_min);
+	device_create_file(&client->dev, &dev_attr_fan3_div);
+
+	if (data->has_fan & (1 << 3)) {
+		device_create_file(&client->dev, &dev_attr_fan4_input);
+		device_create_file(&client->dev, &dev_attr_fan4_min);
+		device_create_file(&client->dev, &dev_attr_fan4_div);
+	}
+	if (data->has_fan & (1 << 4)) {
+		device_create_file(&client->dev, &dev_attr_fan5_input);
+		device_create_file(&client->dev, &dev_attr_fan5_min);
+		device_create_file(&client->dev, &dev_attr_fan5_div);
+	}
+
+	device_create_file(&client->dev, &dev_attr_temp1_input);
+	device_create_file(&client->dev, &dev_attr_temp1_max);
+	device_create_file(&client->dev, &dev_attr_temp1_max_hyst);
+	device_create_file(&client->dev, &dev_attr_temp2_input);
+	device_create_file(&client->dev, &dev_attr_temp2_max);
+	device_create_file(&client->dev, &dev_attr_temp2_max_hyst);
+	device_create_file(&client->dev, &dev_attr_temp3_input);
+	device_create_file(&client->dev, &dev_attr_temp3_max);
+	device_create_file(&client->dev, &dev_attr_temp3_max_hyst);
+
+	return 0;
+
+exit_free:
+	kfree(data);
+exit_release:
+	release_region(address, REGION_LENGTH);
+exit:
+	return err;
+}
+
+static int w83627ehf_attach_adapter(struct i2c_adapter *adapter)
+{
+	if (!(adapter->class & I2C_CLASS_HWMON))
+		return 0;
+	return i2c_detect(adapter, &addr_data, w83627ehf_detect);
+}
+
+static int w83627ehf_detach_client(struct i2c_client *client)
+{
+	int err;
+
+	if ((err = i2c_detach_client(client))) {
+		dev_err(&client->dev, "Client deregistration failed, "
+			"client not detached.\n");
+		return err;
+	}
+	release_region(client->addr, REGION_LENGTH);
+	kfree(i2c_get_clientdata(client));
+
+	return 0;
+}
+
+static struct i2c_driver w83627ehf_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "w83627ehf",
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter	= w83627ehf_attach_adapter,
+	.detach_client	= w83627ehf_detach_client,
+};
+
+static int __init w83627ehf_find(int sioaddr, int *address)
+{
+	u16 val;
+
+	REG = sioaddr;
+	VAL = sioaddr + 1;
+	superio_enter();
+
+	val = (superio_inb(SIO_REG_DEVID) << 8)
+	    | superio_inb(SIO_REG_DEVID + 1);
+	if ((val & SIO_ID_MASK) != SIO_W83627EHF_ID) {
+		superio_exit();
+		return -ENODEV;
+	}
+
+	superio_select(W83627EHF_LD_HWM);
+	val = (superio_inb(SIO_REG_ADDR) << 8)
+	    | superio_inb(SIO_REG_ADDR + 1);
+	*address = val & ~(REGION_LENGTH - 1);
+	if (*address == 0) {
+		superio_exit();
+		return -ENODEV;
+	}
+
+	/* Activate logical device if needed */
+	val = superio_inb(SIO_REG_ENABLE);
+	if (!(val & 0x01))
+		superio_outb(SIO_REG_ENABLE, val | 0x01);
+
+	superio_exit();
+	return 0;
+}
+
+static int __init sensors_w83627ehf_init(void)
+{
+	if (w83627ehf_find(0x2e, &normal_isa[0])
+	 && w83627ehf_find(0x4e, &normal_isa[0]))
+		return -ENODEV;
+
+	return i2c_add_driver(&w83627ehf_driver);
+}
+
+static void __exit sensors_w83627ehf_exit(void)
+{
+	i2c_del_driver(&w83627ehf_driver);
+}
+
+MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
+MODULE_DESCRIPTION("W83627EHF driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_w83627ehf_init);
+module_exit(sensors_w83627ehf_exit);
diff --git a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c
index b1da5ed..bd87a42 100644
--- a/drivers/i2c/chips/w83627hf.c
+++ b/drivers/i2c/chips/w83627hf.c
@@ -264,7 +264,7 @@
 {
 	int i;
 	val = SENSORS_LIMIT(val, 1, 128) >> 1;
-	for (i = 0; i < 6; i++) {
+	for (i = 0; i < 7; i++) {
 		if (val == 0)
 			break;
 		val >>= 1;
@@ -368,19 +368,19 @@
 
 #define sysfs_in_offset(offset) \
 static ssize_t \
-show_regs_in_##offset (struct device *dev, char *buf) \
+show_regs_in_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
         return show_in(dev, buf, offset); \
 } \
 static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_regs_in_##offset, NULL);
 
 #define sysfs_in_reg_offset(reg, offset) \
-static ssize_t show_regs_in_##reg##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_in_##reg##offset (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_in_##reg (dev, buf, offset); \
 } \
 static ssize_t \
-store_regs_in_##reg##offset (struct device *dev, \
+store_regs_in_##reg##offset (struct device *dev, struct device_attribute *attr, \
 			    const char *buf, size_t count) \
 { \
 	return store_in_##reg (dev, buf, count, offset); \
@@ -419,25 +419,25 @@
 	return sprintf(buf,"%ld\n", in0);
 }
 
-static ssize_t show_regs_in_0(struct device *dev, char *buf)
+static ssize_t show_regs_in_0(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct w83627hf_data *data = w83627hf_update_device(dev);
 	return show_in_0(data, buf, data->in[0]);
 }
 
-static ssize_t show_regs_in_min0(struct device *dev, char *buf)
+static ssize_t show_regs_in_min0(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct w83627hf_data *data = w83627hf_update_device(dev);
 	return show_in_0(data, buf, data->in_min[0]);
 }
 
-static ssize_t show_regs_in_max0(struct device *dev, char *buf)
+static ssize_t show_regs_in_max0(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct w83627hf_data *data = w83627hf_update_device(dev);
 	return show_in_0(data, buf, data->in_max[0]);
 }
 
-static ssize_t store_regs_in_min0(struct device *dev,
+static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *attr,
 	const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -462,7 +462,7 @@
 	return count;
 }
 
-static ssize_t store_regs_in_max0(struct device *dev,
+static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *attr,
 	const char *buf, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -531,19 +531,19 @@
 }
 
 #define sysfs_fan_offset(offset) \
-static ssize_t show_regs_fan_##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_fan(dev, buf, offset); \
 } \
 static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_regs_fan_##offset, NULL);
 
 #define sysfs_fan_min_offset(offset) \
-static ssize_t show_regs_fan_min##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_fan_min##offset (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_fan_min(dev, buf, offset); \
 } \
 static ssize_t \
-store_regs_fan_min##offset (struct device *dev, const char *buf, size_t count) \
+store_regs_fan_min##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
 { \
 	return store_fan_min(dev, buf, count, offset); \
 } \
@@ -608,19 +608,19 @@
 
 #define sysfs_temp_offset(offset) \
 static ssize_t \
-show_regs_temp_##offset (struct device *dev, char *buf) \
+show_regs_temp_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_temp(dev, buf, offset); \
 } \
 static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_regs_temp_##offset, NULL);
 
 #define sysfs_temp_reg_offset(reg, offset) \
-static ssize_t show_regs_temp_##reg##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_temp_##reg##offset (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_temp_##reg (dev, buf, offset); \
 } \
 static ssize_t \
-store_regs_temp_##reg##offset (struct device *dev, \
+store_regs_temp_##reg##offset (struct device *dev, struct device_attribute *attr, \
 			      const char *buf, size_t count) \
 { \
 	return store_temp_##reg (dev, buf, count, offset); \
@@ -645,7 +645,7 @@
 } while (0)
 
 static ssize_t
-show_vid_reg(struct device *dev, char *buf)
+show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct w83627hf_data *data = w83627hf_update_device(dev);
 	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
@@ -655,13 +655,13 @@
 device_create_file(&client->dev, &dev_attr_cpu0_vid)
 
 static ssize_t
-show_vrm_reg(struct device *dev, char *buf)
+show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct w83627hf_data *data = w83627hf_update_device(dev);
 	return sprintf(buf, "%ld\n", (long) data->vrm);
 }
 static ssize_t
-store_vrm_reg(struct device *dev, const char *buf, size_t count)
+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 w83627hf_data *data = i2c_get_clientdata(client);
@@ -677,7 +677,7 @@
 device_create_file(&client->dev, &dev_attr_vrm)
 
 static ssize_t
-show_alarms_reg(struct device *dev, char *buf)
+show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct w83627hf_data *data = w83627hf_update_device(dev);
 	return sprintf(buf, "%ld\n", (long) data->alarms);
@@ -687,7 +687,7 @@
 device_create_file(&client->dev, &dev_attr_alarms)
 
 #define show_beep_reg(REG, reg) \
-static ssize_t show_beep_##reg (struct device *dev, char *buf) \
+static ssize_t show_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	struct w83627hf_data *data = w83627hf_update_device(dev); \
 	return sprintf(buf,"%ld\n", \
@@ -732,12 +732,12 @@
 }
 
 #define sysfs_beep(REG, reg) \
-static ssize_t show_regs_beep_##reg (struct device *dev, char *buf) \
+static ssize_t show_regs_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
-	return show_beep_##reg(dev, buf); \
+	return show_beep_##reg(dev, attr, buf); \
 } \
 static ssize_t \
-store_regs_beep_##reg (struct device *dev, const char *buf, size_t count) \
+store_regs_beep_##reg (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
 { \
 	return store_beep_reg(dev, buf, count, BEEP_##REG); \
 } \
@@ -801,12 +801,12 @@
 }
 
 #define sysfs_fan_div(offset) \
-static ssize_t show_regs_fan_div_##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_fan_div_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_fan_div_reg(dev, buf, offset); \
 } \
 static ssize_t \
-store_regs_fan_div_##offset (struct device *dev, \
+store_regs_fan_div_##offset (struct device *dev, struct device_attribute *attr, \
 			    const char *buf, size_t count) \
 { \
 	return store_fan_div_reg(dev, buf, count, offset - 1); \
@@ -861,12 +861,12 @@
 }
 
 #define sysfs_pwm(offset) \
-static ssize_t show_regs_pwm_##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_pwm_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_pwm_reg(dev, buf, offset); \
 } \
 static ssize_t \
-store_regs_pwm_##offset (struct device *dev, const char *buf, size_t count) \
+store_regs_pwm_##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
 { \
 	return store_pwm_reg(dev, buf, count, offset); \
 } \
@@ -937,12 +937,12 @@
 }
 
 #define sysfs_sensor(offset) \
-static ssize_t show_regs_sensor_##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_sensor_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
     return show_sensor_reg(dev, buf, offset); \
 } \
 static ssize_t \
-store_regs_sensor_##offset (struct device *dev, const char *buf, size_t count) \
+store_regs_sensor_##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
 { \
     return store_sensor_reg(dev, buf, count, offset); \
 } \
diff --git a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
index 4954e46..0bb131c 100644
--- a/drivers/i2c/chips/w83781d.c
+++ b/drivers/i2c/chips/w83781d.c
@@ -28,14 +28,11 @@
     as99127f rev.2 (type_name = as99127f)	0x31	0x5ca3	yes	no
     w83781d	7	3	0	3	0x10-1	0x5ca3	yes	yes
     w83627hf	9	3	2	3	0x21	0x5ca3	yes	yes(LPC)
-    w83627thf	9	3	2	3	0x90	0x5ca3	no	yes(LPC)
     w83782d	9	3	2-4	3	0x30	0x5ca3	yes	yes
     w83783s	5-6	3	2	1-2	0x40	0x5ca3	yes	no
-    w83697hf	8	2	2	2	0x60	0x5ca3	no	yes(LPC)
 
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -53,7 +50,7 @@
 static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_6(w83781d, w83782d, w83783s, w83627hf, as99127f, w83697hf);
+SENSORS_INSMOD_5(w83781d, w83782d, w83783s, w83627hf, as99127f);
 I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
 		    "{bus, clientaddr, subclientaddr1, subclientaddr2}");
 
@@ -173,7 +170,6 @@
 						: (val)) / 1000, 0, 0xff))
 #define TEMP_FROM_REG(val)		(((val) & 0x80 ? (val)-0x100 : (val)) * 1000)
 
-#define ALARMS_FROM_REG(val)		(val)
 #define PWM_FROM_REG(val)		(val)
 #define PWM_TO_REG(val)			(SENSORS_LIMIT((val),0,255))
 #define BEEP_MASK_FROM_REG(val,type)	((type) == as99127f ? \
@@ -193,7 +189,7 @@
 	val = SENSORS_LIMIT(val, 1,
 			    ((type == w83781d
 			      || type == as99127f) ? 8 : 128)) >> 1;
-	for (i = 0; i < 6; i++) {
+	for (i = 0; i < 7; i++) {
 		if (val == 0)
 			break;
 		val >>= 1;
@@ -309,18 +305,18 @@
 
 #define sysfs_in_offset(offset) \
 static ssize_t \
-show_regs_in_##offset (struct device *dev, char *buf) \
+show_regs_in_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
         return show_in(dev, buf, offset); \
 } \
 static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_regs_in_##offset, NULL);
 
 #define sysfs_in_reg_offset(reg, offset) \
-static ssize_t show_regs_in_##reg##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_in_##reg##offset (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_in_##reg (dev, buf, offset); \
 } \
-static ssize_t store_regs_in_##reg##offset (struct device *dev, const char *buf, size_t count) \
+static ssize_t store_regs_in_##reg##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
 { \
 	return store_in_##reg (dev, buf, count, offset); \
 } \
@@ -378,18 +374,18 @@
 }
 
 #define sysfs_fan_offset(offset) \
-static ssize_t show_regs_fan_##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_fan(dev, buf, offset); \
 } \
 static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_regs_fan_##offset, NULL);
 
 #define sysfs_fan_min_offset(offset) \
-static ssize_t show_regs_fan_min##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_fan_min##offset (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_fan_min(dev, buf, offset); \
 } \
-static ssize_t store_regs_fan_min##offset (struct device *dev, const char *buf, size_t count) \
+static ssize_t store_regs_fan_min##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
 { \
 	return store_fan_min(dev, buf, count, offset); \
 } \
@@ -452,18 +448,18 @@
 
 #define sysfs_temp_offset(offset) \
 static ssize_t \
-show_regs_temp_##offset (struct device *dev, char *buf) \
+show_regs_temp_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_temp(dev, buf, offset); \
 } \
 static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_regs_temp_##offset, NULL);
 
 #define sysfs_temp_reg_offset(reg, offset) \
-static ssize_t show_regs_temp_##reg##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_temp_##reg##offset (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_temp_##reg (dev, buf, offset); \
 } \
-static ssize_t store_regs_temp_##reg##offset (struct device *dev, const char *buf, size_t count) \
+static ssize_t store_regs_temp_##reg##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
 { \
 	return store_temp_##reg (dev, buf, count, offset); \
 } \
@@ -486,7 +482,7 @@
 } while (0)
 
 static ssize_t
-show_vid_reg(struct device *dev, char *buf)
+show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct w83781d_data *data = w83781d_update_device(dev);
 	return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
@@ -497,14 +493,14 @@
 #define device_create_file_vid(client) \
 device_create_file(&client->dev, &dev_attr_cpu0_vid);
 static ssize_t
-show_vrm_reg(struct device *dev, char *buf)
+show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct w83781d_data *data = w83781d_update_device(dev);
 	return sprintf(buf, "%ld\n", (long) data->vrm);
 }
 
 static ssize_t
-store_vrm_reg(struct device *dev, const char *buf, size_t count)
+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 w83781d_data *data = i2c_get_clientdata(client);
@@ -521,23 +517,23 @@
 #define device_create_file_vrm(client) \
 device_create_file(&client->dev, &dev_attr_vrm);
 static ssize_t
-show_alarms_reg(struct device *dev, char *buf)
+show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct w83781d_data *data = w83781d_update_device(dev);
-	return sprintf(buf, "%ld\n", (long) ALARMS_FROM_REG(data->alarms));
+	return sprintf(buf, "%u\n", data->alarms);
 }
 
 static
 DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
 #define device_create_file_alarms(client) \
 device_create_file(&client->dev, &dev_attr_alarms);
-static ssize_t show_beep_mask (struct device *dev, char *buf)
+static ssize_t show_beep_mask (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct w83781d_data *data = w83781d_update_device(dev);
 	return sprintf(buf, "%ld\n",
 		       (long)BEEP_MASK_FROM_REG(data->beep_mask, data->type));
 }
-static ssize_t show_beep_enable (struct device *dev, char *buf)
+static ssize_t show_beep_enable (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct w83781d_data *data = w83781d_update_device(dev);
 	return sprintf(buf, "%ld\n",
@@ -583,11 +579,11 @@
 }
 
 #define sysfs_beep(REG, reg) \
-static ssize_t show_regs_beep_##reg (struct device *dev, char *buf) \
+static ssize_t show_regs_beep_##reg (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
-	return show_beep_##reg(dev, buf); \
+	return show_beep_##reg(dev, attr, buf); \
 } \
-static ssize_t store_regs_beep_##reg (struct device *dev, const char *buf, size_t count) \
+static ssize_t store_regs_beep_##reg (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
 { \
 	return store_beep_reg(dev, buf, count, BEEP_##REG); \
 } \
@@ -653,11 +649,11 @@
 }
 
 #define sysfs_fan_div(offset) \
-static ssize_t show_regs_fan_div_##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_fan_div_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_fan_div_reg(dev, buf, offset); \
 } \
-static ssize_t store_regs_fan_div_##offset (struct device *dev, const char *buf, size_t count) \
+static ssize_t store_regs_fan_div_##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
 { \
 	return store_fan_div_reg(dev, buf, count, offset - 1); \
 } \
@@ -737,11 +733,11 @@
 }
 
 #define sysfs_pwm(offset) \
-static ssize_t show_regs_pwm_##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_pwm_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_pwm_reg(dev, buf, offset); \
 } \
-static ssize_t store_regs_pwm_##offset (struct device *dev, \
+static ssize_t store_regs_pwm_##offset (struct device *dev, struct device_attribute *attr, \
 		const char *buf, size_t count) \
 { \
 	return store_pwm_reg(dev, buf, count, offset); \
@@ -750,11 +746,11 @@
 		show_regs_pwm_##offset, store_regs_pwm_##offset);
 
 #define sysfs_pwmenable(offset) \
-static ssize_t show_regs_pwmenable_##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_pwmenable_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
 	return show_pwmenable_reg(dev, buf, offset); \
 } \
-static ssize_t store_regs_pwmenable_##offset (struct device *dev, \
+static ssize_t store_regs_pwmenable_##offset (struct device *dev, struct device_attribute *attr, \
 		const char *buf, size_t count) \
 { \
 	return store_pwmenable_reg(dev, buf, count, offset); \
@@ -832,11 +828,11 @@
 }
 
 #define sysfs_sensor(offset) \
-static ssize_t show_regs_sensor_##offset (struct device *dev, char *buf) \
+static ssize_t show_regs_sensor_##offset (struct device *dev, struct device_attribute *attr, char *buf) \
 { \
     return show_sensor_reg(dev, buf, offset); \
 } \
-static ssize_t store_regs_sensor_##offset (struct device *dev, const char *buf, size_t count) \
+static ssize_t store_regs_sensor_##offset (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \
 { \
     return store_sensor_reg(dev, buf, count, offset); \
 } \
@@ -1000,13 +996,6 @@
 		err = -EINVAL;
 		goto ERROR0;
 	}
-	if (!is_isa && kind == w83697hf) {
-		dev_err(&adapter->dev,
-			"Cannot force ISA-only chip for I2C address 0x%02x.\n",
-			address);
-		err = -EINVAL;
-		goto ERROR0;
-	}
 	
 	if (is_isa)
 		if (!request_region(address, W83781D_EXTENT,
@@ -1139,12 +1128,10 @@
 		else if (val1 == 0x40 && vendid == winbond && !is_isa
 				&& address == 0x2d)
 			kind = w83783s;
-		else if ((val1 == 0x21 || val1 == 0x90) && vendid == winbond)
+		else if (val1 == 0x21 && vendid == winbond)
 			kind = w83627hf;
 		else if (val1 == 0x31 && !is_isa && address >= 0x28)
 			kind = as99127f;
-		else if (val1 == 0x60 && vendid == winbond && is_isa)
-			kind = w83697hf;
 		else {
 			if (kind == 0)
 				dev_warn(&new_client->dev, "Ignoring 'force' "
@@ -1163,14 +1150,9 @@
 	} else if (kind == w83783s) {
 		client_name = "w83783s";
 	} else if (kind == w83627hf) {
-		if (val1 == 0x90)
-			client_name = "w83627thf";
-		else
-			client_name = "w83627hf";
+		client_name = "w83627hf";
 	} else if (kind == as99127f) {
 		client_name = "as99127f";
-	} else if (kind == w83697hf) {
-		client_name = "w83697hf";
 	}
 
 	/* Fill in the remaining client fields and put into the global list */
@@ -1208,7 +1190,7 @@
 
 	/* Register sysfs hooks */
 	device_create_file_in(new_client, 0);
-	if (kind != w83783s && kind != w83697hf)
+	if (kind != w83783s)
 		device_create_file_in(new_client, 1);
 	device_create_file_in(new_client, 2);
 	device_create_file_in(new_client, 3);
@@ -1222,24 +1204,19 @@
 
 	device_create_file_fan(new_client, 1);
 	device_create_file_fan(new_client, 2);
-	if (kind != w83697hf)
-		device_create_file_fan(new_client, 3);
+	device_create_file_fan(new_client, 3);
 
 	device_create_file_temp(new_client, 1);
 	device_create_file_temp(new_client, 2);
-	if (kind != w83783s && kind != w83697hf)
+	if (kind != w83783s)
 		device_create_file_temp(new_client, 3);
 
-	if (kind != w83697hf)
-		device_create_file_vid(new_client);
-
-	if (kind != w83697hf)
-		device_create_file_vrm(new_client);
+	device_create_file_vid(new_client);
+	device_create_file_vrm(new_client);
 
 	device_create_file_fan_div(new_client, 1);
 	device_create_file_fan_div(new_client, 2);
-	if (kind != w83697hf)
-		device_create_file_fan_div(new_client, 3);
+	device_create_file_fan_div(new_client, 3);
 
 	device_create_file_alarms(new_client);
 
@@ -1258,7 +1235,7 @@
 	if (kind != as99127f && kind != w83781d) {
 		device_create_file_sensor(new_client, 1);
 		device_create_file_sensor(new_client, 2);
-		if (kind != w83783s && kind != w83697hf)
+		if (kind != w83783s)
 			device_create_file_sensor(new_client, 3);
 	}
 
@@ -1481,7 +1458,7 @@
 				else
 					data->sens[i - 1] = 2;
 			}
-			if ((type == w83783s || type == w83697hf) && (i == 2))
+			if (type == w83783s && i == 2)
 				break;
 		}
 	}
@@ -1497,7 +1474,7 @@
 		}
 
 		/* Enable temp3 */
-		if (type != w83783s && type != w83697hf) {
+		if (type != w83783s) {
 			tmp = w83781d_read_value(client,
 				W83781D_REG_TEMP3_CONFIG);
 			if (tmp & 0x01) {
@@ -1538,8 +1515,7 @@
 		dev_dbg(dev, "Starting device update\n");
 
 		for (i = 0; i <= 8; i++) {
-			if ((data->type == w83783s || data->type == w83697hf)
-			    && (i == 1))
+			if (data->type == w83783s && i == 1)
 				continue;	/* 783S has no in1 */
 			data->in[i] =
 			    w83781d_read_value(client, W83781D_REG_IN(i));
@@ -1547,7 +1523,7 @@
 			    w83781d_read_value(client, W83781D_REG_IN_MIN(i));
 			data->in_max[i] =
 			    w83781d_read_value(client, W83781D_REG_IN_MAX(i));
-			if ((data->type != w83782d) && (data->type != w83697hf)
+			if ((data->type != w83782d)
 			    && (data->type != w83627hf) && (i == 6))
 				break;
 		}
@@ -1583,7 +1559,7 @@
 		    w83781d_read_value(client, W83781D_REG_TEMP_OVER(2));
 		data->temp_max_hyst_add[0] =
 		    w83781d_read_value(client, W83781D_REG_TEMP_HYST(2));
-		if (data->type != w83783s && data->type != w83697hf) {
+		if (data->type != w83783s) {
 			data->temp_add[1] =
 			    w83781d_read_value(client, W83781D_REG_TEMP(3));
 			data->temp_max_add[1] =
@@ -1594,26 +1570,18 @@
 					       W83781D_REG_TEMP_HYST(3));
 		}
 		i = w83781d_read_value(client, W83781D_REG_VID_FANDIV);
-		if (data->type != w83697hf) {
-			data->vid = i & 0x0f;
-			data->vid |=
-			    (w83781d_read_value(client, W83781D_REG_CHIPID) &
-			     0x01)
-			    << 4;
-		}
+		data->vid = i & 0x0f;
+		data->vid |= (w83781d_read_value(client,
+					W83781D_REG_CHIPID) & 0x01) << 4;
 		data->fan_div[0] = (i >> 4) & 0x03;
 		data->fan_div[1] = (i >> 6) & 0x03;
-		if (data->type != w83697hf) {
-			data->fan_div[2] = (w83781d_read_value(client,
-							       W83781D_REG_PIN)
-					    >> 6) & 0x03;
-		}
+		data->fan_div[2] = (w83781d_read_value(client,
+					W83781D_REG_PIN) >> 6) & 0x03;
 		if ((data->type != w83781d) && (data->type != as99127f)) {
 			i = w83781d_read_value(client, W83781D_REG_VBAT);
 			data->fan_div[0] |= (i >> 3) & 0x04;
 			data->fan_div[1] |= (i >> 4) & 0x04;
-			if (data->type != w83697hf)
-				data->fan_div[2] |= (i >> 5) & 0x04;
+			data->fan_div[2] |= (i >> 5) & 0x04;
 		}
 		data->alarms =
 		    w83781d_read_value(client,
diff --git a/drivers/i2c/chips/w83l785ts.c b/drivers/i2c/chips/w83l785ts.c
index 59bbc58..4469d52 100644
--- a/drivers/i2c/chips/w83l785ts.c
+++ b/drivers/i2c/chips/w83l785ts.c
@@ -30,7 +30,6 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/init.h>
@@ -118,13 +117,13 @@
  * Sysfs stuff
  */
 
-static ssize_t show_temp(struct device *dev, char *buf)
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct w83l785ts_data *data = w83l785ts_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp));
 }
 
-static ssize_t show_temp_over(struct device *dev, char *buf)
+static ssize_t show_temp_over(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct w83l785ts_data *data = w83l785ts_update_device(dev);
 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over));
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 9011627..51ce268 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -21,7 +21,6 @@
    All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl>
    SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com>                */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -103,7 +102,7 @@
 	.release =	&i2c_adapter_class_dev_release,
 };
 
-static ssize_t show_adapter_name(struct device *dev, char *buf)
+static ssize_t show_adapter_name(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
 	return sprintf(buf, "%s\n", adap->name);
@@ -117,7 +116,7 @@
 	complete(&client->released);
 }
 
-static ssize_t show_client_name(struct device *dev, char *buf)
+static ssize_t show_client_name(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	return sprintf(buf, "%s\n", client->name);
@@ -239,7 +238,7 @@
 	}
 
 	/* detach any active clients. This must be done first, because
-	 * it can fail; in which case we give upp. */
+	 * it can fail; in which case we give up. */
 	list_for_each_safe(item, _n, &adap->clients) {
 		client = list_entry(item, struct i2c_client, list);
 
@@ -612,27 +611,16 @@
 	struct i2c_adapter *adap=client->adapter;
 	struct i2c_msg msg;
 
-	if (client->adapter->algo->master_xfer) {
-		msg.addr   = client->addr;
-		msg.flags = client->flags & I2C_M_TEN;
-		msg.len = count;
-		msg.buf = (char *)buf;
+	msg.addr = client->addr;
+	msg.flags = client->flags & I2C_M_TEN;
+	msg.len = count;
+	msg.buf = (char *)buf;
 	
-		dev_dbg(&client->adapter->dev, "master_send: writing %d bytes.\n",
-			count);
-	
-		down(&adap->bus_lock);
-		ret = adap->algo->master_xfer(adap,&msg,1);
-		up(&adap->bus_lock);
+	ret = i2c_transfer(adap, &msg, 1);
 
-		/* if everything went ok (i.e. 1 msg transmitted), return #bytes
-		 * transmitted, else error code.
-		 */
-		return (ret == 1 )? count : ret;
-	} else {
-		dev_err(&client->adapter->dev, "I2C level transfers not supported\n");
-		return -ENOSYS;
-	}
+	/* If everything went ok (i.e. 1 msg transmitted), return #bytes
+	   transmitted, else error code. */
+	return (ret == 1) ? count : ret;
 }
 
 int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
@@ -640,31 +628,18 @@
 	struct i2c_adapter *adap=client->adapter;
 	struct i2c_msg msg;
 	int ret;
-	if (client->adapter->algo->master_xfer) {
-		msg.addr   = client->addr;
-		msg.flags = client->flags & I2C_M_TEN;
-		msg.flags |= I2C_M_RD;
-		msg.len = count;
-		msg.buf = buf;
 
-		dev_dbg(&client->adapter->dev, "master_recv: reading %d bytes.\n",
-			count);
-	
-		down(&adap->bus_lock);
-		ret = adap->algo->master_xfer(adap,&msg,1);
-		up(&adap->bus_lock);
-	
-		dev_dbg(&client->adapter->dev, "master_recv: return:%d (count:%d, addr:0x%02x)\n",
-			ret, count, client->addr);
-	
-		/* if everything went ok (i.e. 1 msg transmitted), return #bytes
-	 	* transmitted, else error code.
-	 	*/
-		return (ret == 1 )? count : ret;
-	} else {
-		dev_err(&client->adapter->dev, "I2C level transfers not supported\n");
-		return -ENOSYS;
-	}
+	msg.addr = client->addr;
+	msg.flags = client->flags & I2C_M_TEN;
+	msg.flags |= I2C_M_RD;
+	msg.len = count;
+	msg.buf = buf;
+
+	ret = i2c_transfer(adap, &msg, 1);
+
+	/* If everything went ok (i.e. 1 msg transmitted), return #bytes
+	   transmitted, else error code. */
+	return (ret == 1) ? count : ret;
 }
 
 
@@ -742,18 +717,6 @@
 				found = 1;
 			}
 		}
-		for (i = 0;
-		     !found && (address_data->ignore_range[i] != I2C_CLIENT_END);
-		     i += 3) {
-			if (((adap_id == address_data->ignore_range[i]) ||
-			    ((address_data->ignore_range[i]==ANY_I2C_BUS))) &&
-			    (addr >= address_data->ignore_range[i+1]) &&
-			    (addr <= address_data->ignore_range[i+2])) {
-				dev_dbg(&adapter->dev, "found ignore_range parameter for adapter %d, "
-					"addr %04x\n", adap_id,addr);
-				found = 1;
-			}
-		}
 		if (found) 
 			continue;
 
@@ -770,17 +733,6 @@
 		}
 
 		for (i = 0;
-		     !found && (address_data->normal_i2c_range[i] != I2C_CLIENT_END);
-		     i += 2) {
-			if ((addr >= address_data->normal_i2c_range[i]) &&
-			    (addr <= address_data->normal_i2c_range[i+1])) {
-				found = 1;
-				dev_dbg(&adapter->dev, "found normal i2c_range entry for adapter %d, "
-					"addr %04x\n", adap_id,addr);
-			}
-		}
-
-		for (i = 0;
 		     !found && (address_data->probe[i] != I2C_CLIENT_END);
 		     i += 2) {
 			if (((adap_id == address_data->probe[i]) ||
@@ -791,18 +743,6 @@
 					"addr %04x\n", adap_id,addr);
 			}
 		}
-		for (i = 0;
-		     !found && (address_data->probe_range[i] != I2C_CLIENT_END);
-		     i += 3) {
-			if (((adap_id == address_data->probe_range[i]) ||
-			   (address_data->probe_range[i] == ANY_I2C_BUS)) &&
-			   (addr >= address_data->probe_range[i+1]) &&
-			   (addr <= address_data->probe_range[i+2])) {
-				found = 1;
-				dev_dbg(&adapter->dev, "found probe_range parameter for adapter %d, "
-					"addr %04x\n", adap_id,addr);
-			}
-		}
 		if (!found) 
 			continue;
 
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 86c4d01..bc5d557 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -29,7 +29,6 @@
 /* The devfs code is contributed by Philipp Matthias Hahn 
    <pmhahn@titan.lahn.de> */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/fs.h>
@@ -214,7 +213,7 @@
 				   sizeof(rdwr_arg)))
 			return -EFAULT;
 
-		/* Put an arbritrary limit on the number of messages that can
+		/* Put an arbitrary limit on the number of messages that can
 		 * be sent at once */
 		if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS)
 			return -EINVAL;
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 3ac0a53..0273f12 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -672,8 +672,8 @@
 	  chipsets.
 
 config BLK_DEV_SGIIOC4
-	tristate "Silicon Graphics IOC4 chipset support"
-	depends on IA64_SGI_SN2 || IA64_GENERIC
+	tristate "Silicon Graphics IOC4 chipset ATA/ATAPI support"
+	depends on (IA64_SGI_SN2 || IA64_GENERIC) && SGI_IOC4
 	help
 	  This driver adds PIO & MultiMode DMA-2 support for the SGI IOC4
 	  chipset, which has one channel and can support two devices.
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 39f3e91..0a31cfd 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -2657,16 +2657,63 @@
 }
 
 static
+int ide_cdrom_get_capabilities(ide_drive_t *drive, struct atapi_capabilities_page *cap)
+{
+	struct cdrom_info *info = drive->driver_data;
+	struct cdrom_device_info *cdi = &info->devinfo;
+	struct packet_command cgc;
+	int stat, attempts = 3, size = sizeof(*cap);
+
+	/*
+	 * ACER50 (and others?) require the full spec length mode sense
+	 * page capabilities size, but older drives break.
+	 */
+	if (!(!strcmp(drive->id->model, "ATAPI CD ROM DRIVE 50X MAX") ||
+	    !strcmp(drive->id->model, "WPI CDS-32X")))
+		size -= sizeof(cap->pad);
+
+	init_cdrom_command(&cgc, cap, size, CGC_DATA_UNKNOWN);
+	do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
+		stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
+		if (!stat)
+			break;
+	} while (--attempts);
+	return stat;
+}
+
+static
+void ide_cdrom_update_speed (ide_drive_t *drive, struct atapi_capabilities_page *cap)
+{
+	/* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */
+	if (!drive->id->model[0] &&
+	    !strncmp(drive->id->fw_rev, "241N", 4)) {
+		CDROM_STATE_FLAGS(drive)->current_speed  =
+			(((unsigned int)cap->curspeed) + (176/2)) / 176;
+		CDROM_CONFIG_FLAGS(drive)->max_speed =
+			(((unsigned int)cap->maxspeed) + (176/2)) / 176;
+	} else {
+		CDROM_STATE_FLAGS(drive)->current_speed  =
+			(ntohs(cap->curspeed) + (176/2)) / 176;
+		CDROM_CONFIG_FLAGS(drive)->max_speed =
+			(ntohs(cap->maxspeed) + (176/2)) / 176;
+	}
+}
+
+static
 int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed)
 {
 	ide_drive_t *drive = (ide_drive_t*) cdi->handle;
 	struct request_sense sense;
+	struct atapi_capabilities_page cap;
 	int stat;
 
 	if ((stat = cdrom_select_speed(drive, speed, &sense)) < 0)
 		return stat;
 
-        cdi->speed = CDROM_STATE_FLAGS(drive)->current_speed;
+	if (!ide_cdrom_get_capabilities(drive, &cap)) {
+		ide_cdrom_update_speed(drive, &cap);
+		cdi->speed = CDROM_STATE_FLAGS(drive)->current_speed;
+	}
         return 0;
 }
 
@@ -2869,31 +2916,6 @@
 }
 
 static
-int ide_cdrom_get_capabilities(ide_drive_t *drive, struct atapi_capabilities_page *cap)
-{
-	struct cdrom_info *info = drive->driver_data;
-	struct cdrom_device_info *cdi = &info->devinfo;
-	struct packet_command cgc;
-	int stat, attempts = 3, size = sizeof(*cap);
-
-	/*
-	 * ACER50 (and others?) require the full spec length mode sense
-	 * page capabilities size, but older drives break.
-	 */
-	if (!(!strcmp(drive->id->model, "ATAPI CD ROM DRIVE 50X MAX") ||
-	    !strcmp(drive->id->model, "WPI CDS-32X")))
-		size -= sizeof(cap->pad);
-
-	init_cdrom_command(&cgc, cap, size, CGC_DATA_UNKNOWN);
-	do { /* we seem to get stat=0x01,err=0x00 the first time (??) */
-		stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
-		if (!stat)
-			break;
-	} while (--attempts);
-	return stat;
-}
-
-static
 int ide_cdrom_probe_capabilities (ide_drive_t *drive)
 {
 	struct cdrom_info *info = drive->driver_data;
@@ -2978,20 +3000,7 @@
 		}
 	}
 
-	/* The ACER/AOpen 24X cdrom has the speed fields byte-swapped */
-	if (!drive->id->model[0] &&
-	    !strncmp(drive->id->fw_rev, "241N", 4)) {
-		CDROM_STATE_FLAGS(drive)->current_speed  = 
-			(((unsigned int)cap.curspeed) + (176/2)) / 176;
-		CDROM_CONFIG_FLAGS(drive)->max_speed = 
-			(((unsigned int)cap.maxspeed) + (176/2)) / 176;
-	} else {
-		CDROM_STATE_FLAGS(drive)->current_speed  = 
-			(ntohs(cap.curspeed) + (176/2)) / 176;
-		CDROM_CONFIG_FLAGS(drive)->max_speed = 
-			(ntohs(cap.maxspeed) + (176/2)) / 176;
-	}
-
+	ide_cdrom_update_speed(drive, &cap);
 	/* don't print speed if the drive reported 0.
 	 */
 	printk(KERN_INFO "%s: ATAPI", drive->name);
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 3302cd8..d6f9348 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -1215,7 +1215,8 @@
 	if (!idkp)
 		goto failed;
 
-	g = alloc_disk(1 << PARTN_BITS);
+	g = alloc_disk_node(1 << PARTN_BITS,
+			pcibus_to_node(drive->hwif->pci_dev->bus));
 	if (!g)
 		goto out_free_idkp;
 
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index c949e98..9eab642 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -661,10 +661,12 @@
 
 	idefloppy_do_end_request(drive, 1, done >> 9);
 
+#if IDEFLOPPY_DEBUG_BUGS
 	if (bcount) {
 		printk(KERN_ERR "%s: leftover data in idefloppy_output_buffers, bcount == %d\n", drive->name, bcount);
 		idefloppy_write_zeros(drive, bcount);
 	}
+#endif
 }
 
 static void idefloppy_update_buffers (ide_drive_t *drive, idefloppy_pc_t *pc)
@@ -1048,6 +1050,9 @@
 	atapi_bcount_t bcount;
 	ide_handler_t *pkt_xfer_routine;
 
+#if 0 /* Accessing floppy->pc is not valid here, the previous pc may be gone
+         and have lived on another thread's stack; that stack may have become
+         unmapped meanwhile (CONFIG_DEBUG_PAGEALLOC). */
 #if IDEFLOPPY_DEBUG_BUGS
 	if (floppy->pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD &&
 	    pc->c[0] == IDEFLOPPY_REQUEST_SENSE_CMD) {
@@ -1055,6 +1060,7 @@
 			"Two request sense in serial were issued\n");
 	}
 #endif /* IDEFLOPPY_DEBUG_BUGS */
+#endif
 
 	if (floppy->failed_pc == NULL &&
 	    pc->c[0] != IDEFLOPPY_REQUEST_SENSE_CMD)
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 5d876f5..7df85af 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -977,8 +977,9 @@
 	 *	limits and LBA48 we could raise it but as yet
 	 *	do not.
 	 */
-	 
-	q = blk_init_queue(do_ide_request, &ide_lock);
+
+	q = blk_init_queue_node(do_ide_request, &ide_lock,
+				pcibus_to_node(drive->hwif->pci_dev->bus));
 	if (!q)
 		return 1;
 
@@ -1095,7 +1096,8 @@
 		hwgroup->hwif->next = hwif;
 		spin_unlock_irq(&ide_lock);
 	} else {
-		hwgroup = kmalloc(sizeof(ide_hwgroup_t),GFP_KERNEL);
+		hwgroup = kmalloc_node(sizeof(ide_hwgroup_t), GFP_KERNEL,
+			pcibus_to_node(hwif->drives[0].hwif->pci_dev->bus));
 		if (!hwgroup)
 	       		goto out_up;
 
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index 4651a22..af526b6 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -34,7 +34,7 @@
 #include <linux/mm.h>
 #include <linux/ioport.h>
 #include <linux/blkdev.h>
-#include <linux/ioc4_common.h>
+#include <linux/ioc4.h>
 #include <asm/io.h>
 
 #include <linux/ide.h>
@@ -715,14 +715,34 @@
 };
 
 int
-ioc4_ide_attach_one(struct pci_dev *dev, const struct pci_device_id *id)
+ioc4_ide_attach_one(struct ioc4_driver_data *idd)
 {
-	return pci_init_sgiioc4(dev, &sgiioc4_chipsets[id->driver_data]);
+	return pci_init_sgiioc4(idd->idd_pdev,
+				&sgiioc4_chipsets[idd->idd_pci_id->driver_data]);
 }
 
+static struct ioc4_submodule ioc4_ide_submodule = {
+	.is_name = "IOC4_ide",
+	.is_owner = THIS_MODULE,
+	.is_probe = ioc4_ide_attach_one,
+/*	.is_remove = ioc4_ide_remove_one,	*/
+};
+
+static int __devinit
+ioc4_ide_init(void)
+{
+	return ioc4_register_submodule(&ioc4_ide_submodule);
+}
+
+static void __devexit
+ioc4_ide_exit(void)
+{
+	ioc4_unregister_submodule(&ioc4_ide_submodule);
+}
+
+module_init(ioc4_ide_init);
+module_exit(ioc4_ide_exit);
 
 MODULE_AUTHOR("Aniket Malatpure - Silicon Graphics Inc. (SGI)");
 MODULE_DESCRIPTION("IDE PCI driver module for SGI IOC4 Base-IO Card");
 MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(ioc4_ide_attach_one);
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
index 68c7a5f..4538b02 100644
--- a/drivers/ieee1394/dv1394.c
+++ b/drivers/ieee1394/dv1394.c
@@ -2343,8 +2343,8 @@
 			dv1394_un_init(video);
 	} while (video != NULL);
 
-	class_simple_device_remove(MKDEV(
-		IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)));
+	class_device_destroy(hpsb_protocol_class,
+		MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)));
 	devfs_remove("ieee1394/dv/host%d/NTSC", id);
 	devfs_remove("ieee1394/dv/host%d/PAL", id);
 	devfs_remove("ieee1394/dv/host%d", id);
@@ -2361,7 +2361,7 @@
 
 	ohci = (struct ti_ohci *)host->hostdata;
 
-	class_simple_device_add(hpsb_protocol_class, MKDEV(
+	class_device_create(hpsb_protocol_class, MKDEV(
 		IEEE1394_MAJOR,	IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), 
 		NULL, "dv1394-%d", id);
 	devfs_mk_dir("ieee1394/dv/host%d", id);
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
index a294e45..629070b 100644
--- a/drivers/ieee1394/ieee1394_core.c
+++ b/drivers/ieee1394/ieee1394_core.c
@@ -67,7 +67,7 @@
 
 /* Some globals used */
 const char *hpsb_speedto_str[] = { "S100", "S200", "S400", "S800", "S1600", "S3200" };
-struct class_simple *hpsb_protocol_class;
+struct class *hpsb_protocol_class;
 
 #ifdef CONFIG_IEEE1394_VERBOSEDEBUG
 static void dump_packet(const char *text, quadlet_t *data, int size)
@@ -1041,10 +1041,8 @@
 
 	while (1) {
 		if (down_interruptible(&khpsbpkt_sig)) {
-			if (current->flags & PF_FREEZE) {
-				refrigerator(0);
+			if (try_to_freeze())
 				continue;
-			}
 			printk("khpsbpkt: received unexpected signal?!\n" );
 			break;
 		}
@@ -1121,7 +1119,7 @@
 	if (ret < 0)
 		goto release_all_bus;
 
-	hpsb_protocol_class = class_simple_create(THIS_MODULE, "ieee1394_protocol");
+	hpsb_protocol_class = class_create(THIS_MODULE, "ieee1394_protocol");
 	if (IS_ERR(hpsb_protocol_class)) {
 		ret = PTR_ERR(hpsb_protocol_class);
 		goto release_class_host;
@@ -1159,7 +1157,7 @@
 cleanup_csr:
 	cleanup_csr();
 release_class_protocol:
-	class_simple_destroy(hpsb_protocol_class);
+	class_destroy(hpsb_protocol_class);
 release_class_host:
 	class_unregister(&hpsb_host_class);
 release_all_bus:
@@ -1189,7 +1187,7 @@
 
 	cleanup_csr();
 
-	class_simple_destroy(hpsb_protocol_class);
+	class_destroy(hpsb_protocol_class);
 	class_unregister(&hpsb_host_class);
 	for (i = 0; fw_bus_attrs[i]; i++)
 		bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]);
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
index c4b4408..73bd8ef 100644
--- a/drivers/ieee1394/ieee1394_core.h
+++ b/drivers/ieee1394/ieee1394_core.h
@@ -223,6 +223,7 @@
 /* Our sysfs bus entry */
 extern struct bus_type ieee1394_bus_type;
 extern struct class hpsb_host_class;
-extern struct class_simple *hpsb_protocol_class;
+extern struct class *hpsb_protocol_class;
 
 #endif /* _IEEE1394_CORE_H */
+
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 83e66ed9..9a46c3b 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -220,7 +220,7 @@
 
 
 #define fw_attr(class, class_type, field, type, format_string)		\
-static ssize_t fw_show_##class##_##field (struct device *dev, char *buf)\
+static ssize_t fw_show_##class##_##field (struct device *dev, struct device_attribute *attr, char *buf)\
 {									\
 	class_type *class;						\
 	class = container_of(dev, class_type, device);			\
@@ -232,7 +232,7 @@
 };
 
 #define fw_attr_td(class, class_type, td_kv)				\
-static ssize_t fw_show_##class##_##td_kv (struct device *dev, char *buf)\
+static ssize_t fw_show_##class##_##td_kv (struct device *dev, struct device_attribute *attr, char *buf)\
 {									\
 	int len;							\
 	class_type *class = container_of(dev, class_type, device);	\
@@ -265,7 +265,7 @@
 };
 
 
-static ssize_t fw_show_ne_bus_options(struct device *dev, char *buf)
+static ssize_t fw_show_ne_bus_options(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct node_entry *ne = container_of(dev, struct node_entry, device);
 
@@ -281,7 +281,7 @@
 static DEVICE_ATTR(bus_options,S_IRUGO,fw_show_ne_bus_options,NULL);
 
 
-static ssize_t fw_show_ne_tlabels_free(struct device *dev, char *buf)
+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);
@@ -289,7 +289,7 @@
 static DEVICE_ATTR(tlabels_free,S_IRUGO,fw_show_ne_tlabels_free,NULL);
 
 
-static ssize_t fw_show_ne_tlabels_allocations(struct device *dev, char *buf)
+static ssize_t fw_show_ne_tlabels_allocations(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct node_entry *ne = container_of(dev, struct node_entry, device);
 	return sprintf(buf, "%u\n", ne->tpool->allocations);
@@ -297,7 +297,7 @@
 static DEVICE_ATTR(tlabels_allocations,S_IRUGO,fw_show_ne_tlabels_allocations,NULL);
 
 
-static ssize_t fw_show_ne_tlabels_mask(struct device *dev, char *buf)
+static ssize_t fw_show_ne_tlabels_mask(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct node_entry *ne = container_of(dev, struct node_entry, device);
 #if (BITS_PER_LONG <= 32)
@@ -309,7 +309,7 @@
 static DEVICE_ATTR(tlabels_mask, S_IRUGO, fw_show_ne_tlabels_mask, NULL);
 
 
-static ssize_t fw_set_ignore_driver(struct device *dev, const char *buf, size_t count)
+static ssize_t fw_set_ignore_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct unit_directory *ud = container_of(dev, struct unit_directory, device);
 	int state = simple_strtoul(buf, NULL, 10);
@@ -324,7 +324,7 @@
 
 	return count;
 }
-static ssize_t fw_get_ignore_driver(struct device *dev, char *buf)
+static ssize_t fw_get_ignore_driver(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct unit_directory *ud = container_of(dev, struct unit_directory, device);
 
@@ -695,14 +695,15 @@
 	put_device(dev);
 }
 
+static int __nodemgr_remove_host_dev(struct device *dev, void *data)
+{
+	nodemgr_remove_ne(container_of(dev, struct node_entry, device));
+	return 0;
+}
 
 static void nodemgr_remove_host_dev(struct device *dev)
 {
-	struct device *ne_dev, *next;
-
-	list_for_each_entry_safe(ne_dev, next, &dev->children, node)
-		nodemgr_remove_ne(container_of(ne_dev, struct node_entry, device));
-
+	device_for_each_child(dev, NULL, __nodemgr_remove_host_dev);
 	sysfs_remove_link(&dev->kobj, "irm_id");
 	sysfs_remove_link(&dev->kobj, "busmgr_id");
 	sysfs_remove_link(&dev->kobj, "host_id");
@@ -1509,7 +1510,7 @@
 
 		if (down_interruptible(&hi->reset_sem) ||
 		    down_interruptible(&nodemgr_serialize)) {
-			if (try_to_freeze(PF_FREEZE))
+			if (try_to_freeze())
 				continue;
 			printk("NodeMgr: received unexpected signal?!\n" );
 			break;
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index 6a08a89..7419af4 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -2901,7 +2901,7 @@
 
 	hpsb_register_highlevel(&raw1394_highlevel);
 
-	if (IS_ERR(class_simple_device_add(hpsb_protocol_class, MKDEV(
+	if (IS_ERR(class_device_create(hpsb_protocol_class, MKDEV(
 		IEEE1394_MAJOR,	IEEE1394_MINOR_BLOCK_RAW1394 * 16), 
 		NULL, RAW1394_DEVICE_NAME))) {
 		ret = -EFAULT;
@@ -2934,8 +2934,8 @@
 
 out_dev:
 	devfs_remove(RAW1394_DEVICE_NAME);
-	class_simple_device_remove(MKDEV(
-		IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+	class_device_destroy(hpsb_protocol_class,
+		MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16));
 out_unreg:
 	hpsb_unregister_highlevel(&raw1394_highlevel);
 out:
@@ -2944,8 +2944,8 @@
 
 static void __exit cleanup_raw1394(void)
 {
-	class_simple_device_remove(MKDEV(
-		IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+	class_device_destroy(hpsb_protocol_class,
+		MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16));
 	cdev_del(&raw1394_cdev);
 	devfs_remove(RAW1394_DEVICE_NAME);
 	hpsb_unregister_highlevel(&raw1394_highlevel);
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
index 00c7b95..32368f3 100644
--- a/drivers/ieee1394/sbp2.c
+++ b/drivers/ieee1394/sbp2.c
@@ -745,7 +745,8 @@
 	list_add_tail(&scsi_id->scsi_list, &hi->scsi_ids);
 
 	/* Register our host with the SCSI stack. */
-	scsi_host = scsi_host_alloc(&scsi_driver_template, 0);
+	scsi_host = scsi_host_alloc(&scsi_driver_template,
+				    sizeof (unsigned long));
 	if (!scsi_host) {
 		SBP2_ERR("failed to register scsi host");
 		goto failed_alloc;
@@ -1070,7 +1071,7 @@
 static __inline__ int sbp2_command_conversion_device_type(u8 device_type)
 {
 	return (((device_type == TYPE_DISK) ||
-		 (device_type == TYPE_SDAD) ||
+		 (device_type == TYPE_RBC) ||
 		 (device_type == TYPE_ROM)) ? 1:0);
 }
 
@@ -2111,102 +2112,6 @@
  */
 static void sbp2_check_sbp2_command(struct scsi_id_instance_data *scsi_id, unchar *cmd)
 {
-	unchar new_cmd[16];
-	u8 device_type = SBP2_DEVICE_TYPE (scsi_id->sbp2_device_type_and_lun);
-
-	SBP2_DEBUG("sbp2_check_sbp2_command");
-
-	switch (*cmd) {
-
-		case READ_6:
-
-			if (sbp2_command_conversion_device_type(device_type)) {
-
-				SBP2_DEBUG("Convert READ_6 to READ_10");
-
-				/*
-				 * Need to turn read_6 into read_10
-				 */
-				new_cmd[0] = 0x28;
-				new_cmd[1] = (cmd[1] & 0xe0);
-				new_cmd[2] = 0x0;
-				new_cmd[3] = (cmd[1] & 0x1f);
-				new_cmd[4] = cmd[2];
-				new_cmd[5] = cmd[3];
-				new_cmd[6] = 0x0;
-				new_cmd[7] = 0x0;
-				new_cmd[8] = cmd[4];
-				new_cmd[9] = cmd[5];
-
-				memcpy(cmd, new_cmd, 10);
-
-			}
-
-			break;
-
-		case WRITE_6:
-
-			if (sbp2_command_conversion_device_type(device_type)) {
-
-				SBP2_DEBUG("Convert WRITE_6 to WRITE_10");
-
-				/*
-				 * Need to turn write_6 into write_10
-				 */
-				new_cmd[0] = 0x2a;
-				new_cmd[1] = (cmd[1] & 0xe0);
-				new_cmd[2] = 0x0;
-				new_cmd[3] = (cmd[1] & 0x1f);
-				new_cmd[4] = cmd[2];
-				new_cmd[5] = cmd[3];
-				new_cmd[6] = 0x0;
-				new_cmd[7] = 0x0;
-				new_cmd[8] = cmd[4];
-				new_cmd[9] = cmd[5];
-
-				memcpy(cmd, new_cmd, 10);
-
-			}
-
-			break;
-
-		case MODE_SENSE:
-
-			if (sbp2_command_conversion_device_type(device_type)) {
-
-				SBP2_DEBUG("Convert MODE_SENSE_6 to MODE_SENSE_10");
-
-				/*
-				 * Need to turn mode_sense_6 into mode_sense_10
-				 */
-				new_cmd[0] = 0x5a;
-				new_cmd[1] = cmd[1];
-				new_cmd[2] = cmd[2];
-				new_cmd[3] = 0x0;
-				new_cmd[4] = 0x0;
-				new_cmd[5] = 0x0;
-				new_cmd[6] = 0x0;
-				new_cmd[7] = 0x0;
-				new_cmd[8] = cmd[4];
-				new_cmd[9] = cmd[5];
-
-				memcpy(cmd, new_cmd, 10);
-
-			}
-
-			break;
-
-		case MODE_SELECT:
-
-			/*
-			 * TODO. Probably need to change mode select to 10 byte version
-			 */
-
-		default:
-			break;
-	}
-
-	return;
 }
 
 /*
@@ -2247,7 +2152,6 @@
 				     struct scsi_cmnd *SCpnt)
 {
 	u8 *scsi_buf = SCpnt->request_buffer;
-	u8 device_type = SBP2_DEVICE_TYPE (scsi_id->sbp2_device_type_and_lun);
 
 	SBP2_DEBUG("sbp2_check_sbp2_response");
 
@@ -2272,14 +2176,6 @@
 			}
 
 			/*
-			 * Check for Simple Direct Access Device and change it to TYPE_DISK
-			 */
-			if ((scsi_buf[0] & 0x1f) == TYPE_SDAD) {
-				SBP2_DEBUG("Changing TYPE_SDAD to TYPE_DISK");
-				scsi_buf[0] &= 0xe0;
-			}
-
-			/*
 			 * Fix ansi revision and response data format
 			 */
 			scsi_buf[2] |= 2;
@@ -2287,27 +2183,6 @@
 
 			break;
 
-		case MODE_SENSE:
-
-			if (sbp2_command_conversion_device_type(device_type)) {
-
-				SBP2_DEBUG("Modify mode sense response (10 byte version)");
-
-				scsi_buf[0] = scsi_buf[1];	/* Mode data length */
-				scsi_buf[1] = scsi_buf[2];	/* Medium type */
-				scsi_buf[2] = scsi_buf[3];	/* Device specific parameter */
-				scsi_buf[3] = scsi_buf[7];	/* Block descriptor length */
-				memcpy(scsi_buf + 4, scsi_buf + 8, scsi_buf[0]);
-			}
-
-			break;
-
-		case MODE_SELECT:
-
-			/*
-			 * TODO. Probably need to change mode select to 10 byte version
-			 */
-
 		default:
 			break;
 	}
@@ -2579,8 +2454,6 @@
 				      u32 scsi_status, struct scsi_cmnd *SCpnt,
 				      void (*done)(struct scsi_cmnd *))
 {
-	unsigned long flags;
-
 	SBP2_DEBUG("sbp2scsi_complete_command");
 
 	/*
@@ -2679,18 +2552,15 @@
 	/*
 	 * Tell scsi stack that we're done with this command
 	 */
-	spin_lock_irqsave(scsi_id->scsi_host->host_lock,flags);
 	done (SCpnt);
-	spin_unlock_irqrestore(scsi_id->scsi_host->host_lock,flags);
-
-	return;
 }
 
 
 static int sbp2scsi_slave_configure (struct scsi_device *sdev)
 {
 	blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
-
+	sdev->use_10_for_rw = 1;
+	sdev->use_10_for_ms = 1;
 	return 0;
 }
 
@@ -2746,7 +2616,7 @@
 /*
  * Called by scsi stack when something has really gone wrong.
  */
-static int sbp2scsi_reset(struct scsi_cmnd *SCpnt)
+static int __sbp2scsi_reset(struct scsi_cmnd *SCpnt)
 {
 	struct scsi_id_instance_data *scsi_id =
 		(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
@@ -2761,12 +2631,24 @@
 	return(SUCCESS);
 }
 
+static int sbp2scsi_reset(struct scsi_cmnd *SCpnt)
+{
+	unsigned long flags;
+	int rc;
+
+	spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
+	rc = __sbp2scsi_reset(SCpnt);
+	spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
+
+	return rc;
+}
+
 static const char *sbp2scsi_info (struct Scsi_Host *host)
 {
         return "SCSI emulation for IEEE-1394 SBP-2 Devices";
 }
 
-static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev, char *buf)
+static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct scsi_device *sdev;
 	struct scsi_id_instance_data *scsi_id;
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
index a84b039..cd425be 100644
--- a/drivers/ieee1394/sbp2.h
+++ b/drivers/ieee1394/sbp2.h
@@ -266,10 +266,6 @@
 #define SBP2_MAX_UDS_PER_NODE		16	/* Maximum scsi devices per node */
 #define SBP2_MAX_SECTORS		255	/* Max sectors supported */
 
-#ifndef TYPE_SDAD
-#define TYPE_SDAD			0x0e	/* simplified direct access device */
-#endif
-
 /*
  * SCSI direction table...
  * (now used as a back-up in case the direction passed down from above is "unknown")
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
index d68c465..06759b3 100644
--- a/drivers/ieee1394/video1394.c
+++ b/drivers/ieee1394/video1394.c
@@ -1370,7 +1370,7 @@
 	hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
 
 	minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
-	class_simple_device_add(hpsb_protocol_class, MKDEV(
+	class_device_create(hpsb_protocol_class, MKDEV(
 		IEEE1394_MAJOR,	minor), 
 		NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
 	devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor),
@@ -1384,7 +1384,7 @@
 	struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host);
 
 	if (ohci) {
-		class_simple_device_remove(MKDEV(IEEE1394_MAJOR, 
+		class_device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
 			IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
 		devfs_remove("%s/%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
 	}
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 3a413f7..90d51b1 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -40,9 +40,7 @@
 	struct kobject         kobj;
 	struct ib_device      *ibdev;
 	struct attribute_group gid_group;
-	struct attribute     **gid_attr;
 	struct attribute_group pkey_group;
-	struct attribute     **pkey_attr;
 	u8                     port_num;
 };
 
@@ -60,8 +58,9 @@
 struct port_attribute port_attr_##_name = __ATTR_RO(_name)
 
 struct port_table_attribute {
-	struct port_attribute attr;
-	int                   index;
+	struct port_attribute	attr;
+	char			name[8];
+	int			index;
 };
 
 static ssize_t port_attr_show(struct kobject *kobj,
@@ -72,7 +71,7 @@
 	struct ib_port *p = container_of(kobj, struct ib_port, kobj);
 
 	if (!port_attr->show)
-		return 0;
+		return -EIO;
 
 	return port_attr->show(p, port_attr, buf);
 }
@@ -398,17 +397,16 @@
 	struct attribute *a;
 	int i;
 
-	for (i = 0; (a = p->gid_attr[i]); ++i) {
-		kfree(a->name);
+	for (i = 0; (a = p->gid_group.attrs[i]); ++i)
 		kfree(a);
-	}
 
-	for (i = 0; (a = p->pkey_attr[i]); ++i) {
-		kfree(a->name);
+	kfree(p->gid_group.attrs);
+
+	for (i = 0; (a = p->pkey_group.attrs[i]); ++i)
 		kfree(a);
-	}
 
-	kfree(p->gid_attr);
+	kfree(p->pkey_group.attrs);
+
 	kfree(p);
 }
 
@@ -449,58 +447,45 @@
 	return 0;
 }
 
-static int alloc_group(struct attribute ***attr,
-		       ssize_t (*show)(struct ib_port *,
-				       struct port_attribute *, char *buf),
-		       int len)
+static struct attribute **
+alloc_group_attrs(ssize_t (*show)(struct ib_port *,
+				  struct port_attribute *, char *buf),
+		  int len)
 {
-	struct port_table_attribute ***tab_attr =
-		(struct port_table_attribute ***) attr;
+	struct attribute **tab_attr;
+	struct port_table_attribute *element;
 	int i;
-	int ret;
 
-	*tab_attr = kmalloc((1 + len) * sizeof *tab_attr, GFP_KERNEL);
-	if (!*tab_attr)
-		return -ENOMEM;
+	tab_attr = kcalloc(1 + len, sizeof(struct attribute *), GFP_KERNEL);
+	if (!tab_attr)
+		return NULL;
 
-	memset(*tab_attr, 0, (1 + len) * sizeof *tab_attr);
-
-	for (i = 0; i < len; ++i) {
-		(*tab_attr)[i] = kmalloc(sizeof *(*tab_attr)[i], GFP_KERNEL);
-		if (!(*tab_attr)[i]) {
-			ret = -ENOMEM;
+	for (i = 0; i < len; i++) {
+		element = kcalloc(1, sizeof(struct port_table_attribute),
+				  GFP_KERNEL);
+		if (!element)
 			goto err;
-		}
-		memset((*tab_attr)[i], 0, sizeof *(*tab_attr)[i]);
-		(*tab_attr)[i]->attr.attr.name = kmalloc(8, GFP_KERNEL);
-		if (!(*tab_attr)[i]->attr.attr.name) {
-			ret = -ENOMEM;
-			goto err;
-		}
 
-		if (snprintf((*tab_attr)[i]->attr.attr.name, 8, "%d", i) >= 8) {
-			ret = -ENOMEM;
+		if (snprintf(element->name, sizeof(element->name),
+			     "%d", i) >= sizeof(element->name))
 			goto err;
-		}
 
-		(*tab_attr)[i]->attr.attr.mode  = S_IRUGO;
-		(*tab_attr)[i]->attr.attr.owner = THIS_MODULE;
-		(*tab_attr)[i]->attr.show       = show;
-		(*tab_attr)[i]->index           = i;
+		element->attr.attr.name  = element->name;
+		element->attr.attr.mode  = S_IRUGO;
+		element->attr.attr.owner = THIS_MODULE;
+		element->attr.show       = show;
+		element->index		 = i;
+
+		tab_attr[i] = &element->attr.attr;
 	}
 
-	return 0;
+	return tab_attr;
 
 err:
-	for (i = 0; i < len; ++i) {
-		if ((*tab_attr)[i])
-			kfree((*tab_attr)[i]->attr.attr.name);
-		kfree((*tab_attr)[i]);
-	}
-
-	kfree(*tab_attr);
-
-	return ret;
+	while (--i >= 0)
+		kfree(tab_attr[i]);
+	kfree(tab_attr);
+	return NULL;
 }
 
 static int add_port(struct ib_device *device, int port_num)
@@ -541,23 +526,20 @@
 	if (ret)
 		goto err_put;
 
-	ret = alloc_group(&p->gid_attr, show_port_gid, attr.gid_tbl_len);
-	if (ret)
-		goto err_remove_pma;
-
 	p->gid_group.name  = "gids";
-	p->gid_group.attrs = p->gid_attr;
+	p->gid_group.attrs = alloc_group_attrs(show_port_gid, attr.gid_tbl_len);
+	if (!p->gid_group.attrs)
+		goto err_remove_pma;
 
 	ret = sysfs_create_group(&p->kobj, &p->gid_group);
 	if (ret)
 		goto err_free_gid;
 
-	ret = alloc_group(&p->pkey_attr, show_port_pkey, attr.pkey_tbl_len);
-	if (ret)
-		goto err_remove_gid;
-
 	p->pkey_group.name  = "pkeys";
-	p->pkey_group.attrs = p->pkey_attr;
+	p->pkey_group.attrs = alloc_group_attrs(show_port_pkey,
+						attr.pkey_tbl_len);
+	if (!p->pkey_group.attrs)
+		goto err_remove_gid;
 
 	ret = sysfs_create_group(&p->kobj, &p->pkey_group);
 	if (ret)
@@ -568,23 +550,19 @@
 	return 0;
 
 err_free_pkey:
-	for (i = 0; i < attr.pkey_tbl_len; ++i) {
-		kfree(p->pkey_attr[i]->name);
-		kfree(p->pkey_attr[i]);
-	}
+	for (i = 0; i < attr.pkey_tbl_len; ++i)
+		kfree(p->pkey_group.attrs[i]);
 
-	kfree(p->pkey_attr);
+	kfree(p->pkey_group.attrs);
 
 err_remove_gid:
 	sysfs_remove_group(&p->kobj, &p->gid_group);
 
 err_free_gid:
-	for (i = 0; i < attr.gid_tbl_len; ++i) {
-		kfree(p->gid_attr[i]->name);
-		kfree(p->gid_attr[i]);
-	}
+	for (i = 0; i < attr.gid_tbl_len; ++i)
+		kfree(p->gid_group.attrs[i]);
 
-	kfree(p->gid_attr);
+	kfree(p->gid_group.attrs);
 
 err_remove_pma:
 	sysfs_remove_group(&p->kobj, &pma_group);
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index d62c73f..374f404 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -678,9 +678,9 @@
 
 	devfs_mk_cdev(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
 			S_IFCHR|S_IRUGO|S_IWUSR, "input/event%d", minor);
-	class_simple_device_add(input_class,
-				MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
-				dev->dev, "event%d", minor);
+	class_device_create(input_class,
+			MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + minor),
+			dev->dev, "event%d", minor);
 
 	return &evdev->handle;
 }
@@ -690,7 +690,8 @@
 	struct evdev *evdev = handle->private;
 	struct evdev_list *list;
 
-	class_simple_device_remove(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
+	class_device_destroy(input_class,
+			MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
 	devfs_remove("input/event%d", evdev->minor);
 	evdev->exist = 0;
 
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index d7dfa6f..c77a82e 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -17,10 +17,11 @@
 #include <linux/init.h>
 #include <linux/gameport.h>
 #include <linux/wait.h>
+#include <linux/completion.h>
 #include <linux/sched.h>
+#include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
-#include <linux/kthread.h>
 
 /*#include <asm/io.h>*/
 
@@ -133,7 +134,7 @@
 	}
 
 	gameport_close(gameport);
-	return (cpu_data[_smp_processor_id()].loops_per_jiffy * (unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx);
+	return (cpu_data[raw_smp_processor_id()].loops_per_jiffy * (unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx);
 
 #else
 
@@ -237,7 +238,8 @@
 static DEFINE_SPINLOCK(gameport_event_lock);	/* protects gameport_event_list */
 static LIST_HEAD(gameport_event_list);
 static DECLARE_WAIT_QUEUE_HEAD(gameport_wait);
-static struct task_struct *gameport_task;
+static DECLARE_COMPLETION(gameport_exited);
+static int gameport_pid;
 
 static void gameport_queue_event(void *object, struct module *owner,
 			      enum gameport_event_type event_type)
@@ -248,12 +250,12 @@
 	spin_lock_irqsave(&gameport_event_lock, flags);
 
 	/*
-	 * Scan event list for the other events for the same gameport port,
+ 	 * Scan event list for the other events for the same gameport port,
 	 * starting with the most recent one. If event is the same we
 	 * do not need add new one. If event is of different type we
 	 * need to add this event and should not look further because
 	 * we need to preseve sequence of distinct events.
-	 */
+ 	 */
 	list_for_each_entry_reverse(event, &gameport_event_list, node) {
 		if (event->object == object) {
 			if (event->type == event_type)
@@ -430,15 +432,20 @@
 
 static int gameport_thread(void *nothing)
 {
+	lock_kernel();
+	daemonize("kgameportd");
+	allow_signal(SIGTERM);
+
 	do {
 		gameport_handle_events();
-		wait_event_interruptible(gameport_wait,
-			kthread_should_stop() || !list_empty(&gameport_event_list));
-		try_to_freeze(PF_FREEZE);
-	} while (!kthread_should_stop());
+		wait_event_interruptible(gameport_wait, !list_empty(&gameport_event_list));
+		try_to_freeze();
+	} while (!signal_pending(current));
 
 	printk(KERN_DEBUG "gameport: kgameportd exiting\n");
-	return 0;
+
+	unlock_kernel();
+	complete_and_exit(&gameport_exited, 0);
 }
 
 
@@ -446,13 +453,13 @@
  * Gameport port operations
  */
 
-static ssize_t gameport_show_description(struct device *dev, char *buf)
+static ssize_t gameport_show_description(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct gameport *gameport = to_gameport_port(dev);
 	return sprintf(buf, "%s\n", gameport->name);
 }
 
-static ssize_t gameport_rebind_driver(struct device *dev, const char *buf, size_t count)
+static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct gameport *gameport = to_gameport_port(dev);
 	struct device_driver *drv;
@@ -766,10 +773,9 @@
 
 static int __init gameport_init(void)
 {
-	gameport_task = kthread_run(gameport_thread, NULL, "kgameportd");
-	if (IS_ERR(gameport_task)) {
+	if (!(gameport_pid = kernel_thread(gameport_thread, NULL, CLONE_KERNEL))) {
 		printk(KERN_ERR "gameport: Failed to start kgameportd\n");
-		return PTR_ERR(gameport_task);
+		return -1;
 	}
 
 	gameport_bus.dev_attrs = gameport_device_attrs;
@@ -783,7 +789,8 @@
 static void __exit gameport_exit(void)
 {
 	bus_unregister(&gameport_bus);
-	kthread_stop(gameport_task);
+	kill_proc(gameport_pid, SIGTERM, 1);
+	wait_for_completion(&gameport_exited);
 }
 
 module_init(gameport_init);
diff --git a/drivers/input/input.c b/drivers/input/input.c
index c1dbc04..7c4b4d3 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -729,13 +729,13 @@
 static inline int input_proc_init(void) { return 0; }
 #endif
 
-struct class_simple *input_class;
+struct class *input_class;
 
 static int __init input_init(void)
 {
 	int retval = -ENOMEM;
 
-	input_class = class_simple_create(THIS_MODULE, "input");
+	input_class = class_create(THIS_MODULE, "input");
 	if (IS_ERR(input_class))
 		return PTR_ERR(input_class);
 	input_proc_init();
@@ -745,7 +745,7 @@
 		remove_proc_entry("devices", proc_bus_input_dir);
 		remove_proc_entry("handlers", proc_bus_input_dir);
 		remove_proc_entry("input", proc_bus);
-		class_simple_destroy(input_class);
+		class_destroy(input_class);
 		return retval;
 	}
 
@@ -755,7 +755,7 @@
 		remove_proc_entry("handlers", proc_bus_input_dir);
 		remove_proc_entry("input", proc_bus);
 		unregister_chrdev(INPUT_MAJOR, "input");
-		class_simple_destroy(input_class);
+		class_destroy(input_class);
 	}
 	return retval;
 }
@@ -768,7 +768,7 @@
 
 	devfs_remove("input");
 	unregister_chrdev(INPUT_MAJOR, "input");
-	class_simple_destroy(input_class);
+	class_destroy(input_class);
 }
 
 subsys_initcall(input_init);
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 816a585..ff8e1bb 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -518,9 +518,9 @@
 
 	devfs_mk_cdev(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
 			S_IFCHR|S_IRUGO|S_IWUSR, "input/js%d", minor);
-	class_simple_device_add(input_class,
-				MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
-				dev->dev, "js%d", minor);
+	class_device_create(input_class,
+			MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + minor),
+			dev->dev, "js%d", minor);
 
 	return &joydev->handle;
 }
@@ -530,7 +530,7 @@
 	struct joydev *joydev = handle->private;
 	struct joydev_list *list;
 
-	class_simple_device_remove(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
+	class_device_destroy(input_class, MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
 	devfs_remove("input/js%d", joydev->minor);
 	joydev->exist = 0;
 
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 9f9da6d..4d4985b 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -54,7 +54,7 @@
 module_param_named(softraw, atkbd_softraw, bool, 0);
 MODULE_PARM_DESC(softraw, "Use software generated rawmode");
 
-static int atkbd_scroll = 1;
+static int atkbd_scroll = 0;
 module_param_named(scroll, atkbd_scroll, bool, 0);
 MODULE_PARM_DESC(scroll, "Enable scroll-wheel on MS Office and similar keyboards");
 
@@ -219,11 +219,11 @@
 #define ATKBD_DEFINE_ATTR(_name)						\
 static ssize_t atkbd_show_##_name(struct atkbd *, char *);			\
 static ssize_t atkbd_set_##_name(struct atkbd *, const char *, size_t);		\
-static ssize_t atkbd_do_show_##_name(struct device *d, char *b)			\
+static ssize_t atkbd_do_show_##_name(struct device *d, struct device_attribute *attr, char *b)			\
 {										\
 	return atkbd_attr_show_helper(d, b, atkbd_show_##_name);		\
 }										\
-static ssize_t atkbd_do_set_##_name(struct device *d, const char *b, size_t s)	\
+static ssize_t atkbd_do_set_##_name(struct device *d, struct device_attribute *attr, const char *b, size_t s)	\
 {										\
 	return atkbd_attr_set_helper(d, b, s, atkbd_set_##_name);		\
 }										\
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index ffdc823..a12e981 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -364,7 +364,7 @@
 	if (alps_get_status(psmouse, param))
 		return -1;
 
-	if (param[0] & 0x04)
+	if (!(param[0] & 0x04))
 		alps_tap_mode(psmouse, 1);
 
 	if (alps_absolute_mode(psmouse)) {
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
index dc8e9ae..86691cf 100644
--- a/drivers/input/mouse/psmouse.h
+++ b/drivers/input/mouse/psmouse.h
@@ -93,11 +93,11 @@
 #define PSMOUSE_DEFINE_ATTR(_name)						\
 static ssize_t psmouse_attr_show_##_name(struct psmouse *, char *);		\
 static ssize_t psmouse_attr_set_##_name(struct psmouse *, const char *, size_t);\
-static ssize_t psmouse_do_show_##_name(struct device *d, char *b)		\
+static ssize_t psmouse_do_show_##_name(struct device *d, struct device_attribute *attr, char *b)		\
 {										\
 	return psmouse_attr_show_helper(d, b, psmouse_attr_show_##_name);	\
 }										\
-static ssize_t psmouse_do_set_##_name(struct device *d, const char *b, size_t s)\
+static ssize_t psmouse_do_set_##_name(struct device *d, struct device_attribute *attr, const char *b, size_t s)\
 {										\
 	return psmouse_attr_set_helper(d, b, s, psmouse_attr_set_##_name);	\
 }										\
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index 08b1911..c6194a9 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -651,9 +651,9 @@
 
 	devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
 			S_IFCHR|S_IRUGO|S_IWUSR, "input/mouse%d", minor);
-	class_simple_device_add(input_class,
-				MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
-				dev->dev, "mouse%d", minor);
+	class_device_create(input_class,
+			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + minor),
+			dev->dev, "mouse%d", minor);
 
 	return &mousedev->handle;
 }
@@ -663,7 +663,8 @@
 	struct mousedev *mousedev = handle->private;
 	struct mousedev_list *list;
 
-	class_simple_device_remove(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
+	class_device_destroy(input_class,
+			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
 	devfs_remove("input/mouse%d", mousedev->minor);
 	mousedev->exist = 0;
 
@@ -739,8 +740,8 @@
 
 	devfs_mk_cdev(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX),
 			S_IFCHR|S_IRUGO|S_IWUSR, "input/mice");
-	class_simple_device_add(input_class, MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX),
-				NULL, "mice");
+	class_device_create(input_class,
+			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX), NULL, "mice");
 
 #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX
 	if (!(psaux_registered = !misc_register(&psaux_mouse)))
@@ -759,7 +760,8 @@
 		misc_deregister(&psaux_mouse);
 #endif
 	devfs_remove("input/mice");
-	class_simple_device_remove(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX));
+	class_device_destroy(input_class,
+			MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + MOUSEDEV_MIX));
 	input_unregister_handler(&mousedev_handler);
 }
 
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 5900de3..a9bf549 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -396,7 +396,7 @@
 	struct i8042_port *port = serio->port_data;
 
 	port->exists = 0;
-	synchronize_kernel();
+	synchronize_sched();
 	port->serio = NULL;
 }
 
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index 615bf62..341824c 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -31,9 +31,10 @@
 #include <linux/serio.h>
 #include <linux/errno.h>
 #include <linux/wait.h>
+#include <linux/completion.h>
 #include <linux/sched.h>
+#include <linux/smp_lock.h>
 #include <linux/slab.h>
-#include <linux/kthread.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("Serio abstraction core");
@@ -42,7 +43,6 @@
 EXPORT_SYMBOL(serio_interrupt);
 EXPORT_SYMBOL(__serio_register_port);
 EXPORT_SYMBOL(serio_unregister_port);
-EXPORT_SYMBOL(serio_unregister_child_port);
 EXPORT_SYMBOL(__serio_unregister_port_delayed);
 EXPORT_SYMBOL(__serio_register_driver);
 EXPORT_SYMBOL(serio_unregister_driver);
@@ -68,37 +68,6 @@
 static void serio_reconnect_port(struct serio *serio);
 static void serio_disconnect_port(struct serio *serio);
 
-static int serio_connect_driver(struct serio *serio, struct serio_driver *drv)
-{
-	int retval;
-
-	down(&serio->drv_sem);
-	retval = drv->connect(serio, drv);
-	up(&serio->drv_sem);
-
-	return retval;
-}
-
-static int serio_reconnect_driver(struct serio *serio)
-{
-	int retval = -1;
-
-	down(&serio->drv_sem);
-	if (serio->drv && serio->drv->reconnect)
-		retval = serio->drv->reconnect(serio);
-	up(&serio->drv_sem);
-
-	return retval;
-}
-
-static void serio_disconnect_driver(struct serio *serio)
-{
-	down(&serio->drv_sem);
-	if (serio->drv)
-		serio->drv->disconnect(serio);
-	up(&serio->drv_sem);
-}
-
 static int serio_match_port(const struct serio_device_id *ids, struct serio *serio)
 {
 	while (ids->type || ids->proto) {
@@ -122,7 +91,7 @@
 
 	if (serio_match_port(drv->id_table, serio)) {
 		serio->dev.driver = &drv->driver;
-		if (serio_connect_driver(serio, drv)) {
+		if (drv->connect(serio, drv)) {
 			serio->dev.driver = NULL;
 			goto out;
 		}
@@ -169,7 +138,8 @@
 static DEFINE_SPINLOCK(serio_event_lock);	/* protects serio_event_list */
 static LIST_HEAD(serio_event_list);
 static DECLARE_WAIT_QUEUE_HEAD(serio_wait);
-static struct task_struct *serio_task;
+static DECLARE_COMPLETION(serio_exited);
+static int serio_pid;
 
 static void serio_queue_event(void *object, struct module *owner,
 			      enum serio_event_type event_type)
@@ -180,12 +150,12 @@
 	spin_lock_irqsave(&serio_event_lock, flags);
 
 	/*
-	 * Scan event list for the other events for the same serio port,
+ 	 * Scan event list for the other events for the same serio port,
 	 * starting with the most recent one. If event is the same we
 	 * do not need add new one. If event is of different type we
 	 * need to add this event and should not look further because
 	 * we need to preseve sequence of distinct events.
-	 */
+ 	 */
 	list_for_each_entry_reverse(event, &serio_event_list, node) {
 		if (event->object == object) {
 			if (event->type == event_type)
@@ -367,15 +337,20 @@
 
 static int serio_thread(void *nothing)
 {
+	lock_kernel();
+	daemonize("kseriod");
+	allow_signal(SIGTERM);
+
 	do {
 		serio_handle_events();
-		wait_event_interruptible(serio_wait,
-			kthread_should_stop() || !list_empty(&serio_event_list));
-		try_to_freeze(PF_FREEZE);
-	} while (!kthread_should_stop());
+		wait_event_interruptible(serio_wait, !list_empty(&serio_event_list));
+		try_to_freeze();
+	} while (!signal_pending(current));
 
 	printk(KERN_DEBUG "serio: kseriod exiting\n");
-	return 0;
+
+	unlock_kernel();
+	complete_and_exit(&serio_exited, 0);
 }
 
 
@@ -383,31 +358,31 @@
  * Serio port operations
  */
 
-static ssize_t serio_show_description(struct device *dev, char *buf)
+static ssize_t serio_show_description(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct serio *serio = to_serio_port(dev);
 	return sprintf(buf, "%s\n", serio->name);
 }
 
-static ssize_t serio_show_id_type(struct device *dev, char *buf)
+static ssize_t serio_show_id_type(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct serio *serio = to_serio_port(dev);
 	return sprintf(buf, "%02x\n", serio->id.type);
 }
 
-static ssize_t serio_show_id_proto(struct device *dev, char *buf)
+static ssize_t serio_show_id_proto(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct serio *serio = to_serio_port(dev);
 	return sprintf(buf, "%02x\n", serio->id.proto);
 }
 
-static ssize_t serio_show_id_id(struct device *dev, char *buf)
+static ssize_t serio_show_id_id(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct serio *serio = to_serio_port(dev);
 	return sprintf(buf, "%02x\n", serio->id.id);
 }
 
-static ssize_t serio_show_id_extra(struct device *dev, char *buf)
+static ssize_t serio_show_id_extra(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct serio *serio = to_serio_port(dev);
 	return sprintf(buf, "%02x\n", serio->id.extra);
@@ -431,7 +406,7 @@
 	.attrs	= serio_device_id_attrs,
 };
 
-static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t count)
+static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct serio *serio = to_serio_port(dev);
 	struct device_driver *drv;
@@ -462,13 +437,13 @@
 	return retval;
 }
 
-static ssize_t serio_show_bind_mode(struct device *dev, char *buf)
+static ssize_t serio_show_bind_mode(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct serio *serio = to_serio_port(dev);
 	return sprintf(buf, "%s\n", serio->manual_bind ? "manual" : "auto");
 }
 
-static ssize_t serio_set_bind_mode(struct device *dev, const char *buf, size_t count)
+static ssize_t serio_set_bind_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct serio *serio = to_serio_port(dev);
 	int retval;
@@ -582,7 +557,7 @@
 static void serio_reconnect_port(struct serio *serio)
 {
 	do {
-		if (serio_reconnect_driver(serio)) {
+		if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) {
 			serio_disconnect_port(serio);
 			serio_find_driver(serio);
 			/* Ok, old children are now gone, we are done */
@@ -655,19 +630,6 @@
 }
 
 /*
- * Safely unregisters child port if one is present.
- */
-void serio_unregister_child_port(struct serio *serio)
-{
-	down(&serio_sem);
-	if (serio->child) {
-		serio_disconnect_port(serio->child);
-		serio_destroy_port(serio->child);
-	}
-	up(&serio_sem);
-}
-
-/*
  * Submits register request to kseriod for subsequent execution.
  * Can be used when it is not obvious whether the serio_sem is
  * taken or not and when delayed execution is feasible.
@@ -724,14 +686,15 @@
 	struct serio *serio = to_serio_port(dev);
 	struct serio_driver *drv = to_serio_driver(dev->driver);
 
-	return serio_connect_driver(serio, drv);
+	return drv->connect(serio, drv);
 }
 
 static int serio_driver_remove(struct device *dev)
 {
 	struct serio *serio = to_serio_port(dev);
+	struct serio_driver *drv = to_serio_driver(dev->driver);
 
-	serio_disconnect_driver(serio);
+	drv->disconnect(serio);
 	return 0;
 }
 
@@ -767,9 +730,11 @@
 
 static void serio_set_drv(struct serio *serio, struct serio_driver *drv)
 {
+	down(&serio->drv_sem);
 	serio_pause_rx(serio);
 	serio->drv = drv;
 	serio_continue_rx(serio);
+	up(&serio->drv_sem);
 }
 
 static int serio_bus_match(struct device *dev, struct device_driver *drv)
@@ -829,7 +794,7 @@
 {
 	struct serio *serio = to_serio_port(dev);
 
-	if (serio_reconnect_driver(serio)) {
+	if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) {
 		/*
 		 * Driver re-probing can take a while, so better let kseriod
 		 * deal with it.
@@ -883,10 +848,9 @@
 
 static int __init serio_init(void)
 {
-	serio_task = kthread_run(serio_thread, NULL, "kseriod");
-	if (IS_ERR(serio_task)) {
+	if (!(serio_pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL))) {
 		printk(KERN_ERR "serio: Failed to start kseriod\n");
-		return PTR_ERR(serio_task);
+		return -1;
 	}
 
 	serio_bus.dev_attrs = serio_device_attrs;
@@ -902,7 +866,8 @@
 static void __exit serio_exit(void)
 {
 	bus_unregister(&serio_bus);
-	kthread_stop(serio_task);
+	kill_proc(serio_pid, SIGTERM, 1);
+	wait_for_completion(&serio_exited);
 }
 
 module_init(serio_init);
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
index f6b8522..79ca384 100644
--- a/drivers/input/serio/serport.c
+++ b/drivers/input/serio/serport.c
@@ -257,7 +257,7 @@
 
 static void __exit serport_exit(void)
 {
-	tty_register_ldisc(N_MOUSE, NULL);
+	tty_unregister_ldisc(N_MOUSE);
 }
 
 module_init(serport_init);
diff --git a/drivers/input/tsdev.c b/drivers/input/tsdev.c
index d0afba8..50c63a1 100644
--- a/drivers/input/tsdev.c
+++ b/drivers/input/tsdev.c
@@ -414,9 +414,9 @@
 			S_IFCHR|S_IRUGO|S_IWUSR, "input/ts%d", minor);
 	devfs_mk_cdev(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor + TSDEV_MINORS/2),
 			S_IFCHR|S_IRUGO|S_IWUSR, "input/tsraw%d", minor);
-	class_simple_device_add(input_class,
-				MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
-				dev->dev, "ts%d", minor);
+	class_device_create(input_class,
+			MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + minor),
+			dev->dev, "ts%d", minor);
 
 	return &tsdev->handle;
 }
@@ -426,7 +426,8 @@
 	struct tsdev *tsdev = handle->private;
 	struct tsdev_list *list;
 
-	class_simple_device_remove(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));
+	class_device_destroy(input_class,
+			MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));
 	devfs_remove("input/ts%d", tsdev->minor);
 	devfs_remove("input/tsraw%d", tsdev->minor);
 	tsdev->exist = 0;
diff --git a/drivers/isdn/act2000/capi.c b/drivers/isdn/act2000/capi.c
index 40395f5..afa4668 100644
--- a/drivers/isdn/act2000/capi.c
+++ b/drivers/isdn/act2000/capi.c
@@ -224,6 +224,7 @@
 /*
  * Switch V.42 on or off
  */
+#if 0
 int
 actcapi_manufacturer_req_v42(act2000_card *card, ulong arg)
 {
@@ -242,6 +243,7 @@
 	ACTCAPI_QUEUE_TX;
         return 0;
 }
+#endif  /*  0  */
 
 /*
  * Set error-handler
diff --git a/drivers/isdn/act2000/capi.h b/drivers/isdn/act2000/capi.h
index 04d2bcd..f6d5f53 100644
--- a/drivers/isdn/act2000/capi.h
+++ b/drivers/isdn/act2000/capi.h
@@ -350,7 +350,6 @@
 extern int actcapi_chkhdr(act2000_card *, actcapi_msghdr *);
 extern int actcapi_listen_req(act2000_card *);
 extern int actcapi_manufacturer_req_net(act2000_card *);
-extern int actcapi_manufacturer_req_v42(act2000_card *, ulong);
 extern int actcapi_manufacturer_req_errh(act2000_card *);
 extern int actcapi_manufacturer_req_msn(act2000_card *);
 extern int actcapi_connect_req(act2000_card *, act2000_chan *, char *, char, int, int);
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 12dee8e..04fb606 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -58,7 +58,7 @@
 
 /* -------- driver information -------------------------------------- */
 
-static struct class_simple *capi_class;
+static struct class *capi_class;
 
 static int capi_major = 68;		/* allocated */
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
@@ -1499,20 +1499,20 @@
 		return -EIO;
 	}
 
-	capi_class = class_simple_create(THIS_MODULE, "capi");
+	capi_class = class_create(THIS_MODULE, "capi");
 	if (IS_ERR(capi_class)) {
 		unregister_chrdev(capi_major, "capi20");
 		return PTR_ERR(capi_class);
 	}
 
-	class_simple_device_add(capi_class, MKDEV(capi_major, 0), NULL, "capi");
+	class_device_create(capi_class, MKDEV(capi_major, 0), NULL, "capi");
 	devfs_mk_cdev(MKDEV(capi_major, 0), S_IFCHR | S_IRUSR | S_IWUSR,
 			"isdn/capi20");
 
 #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
 	if (capinc_tty_init() < 0) {
-		class_simple_device_remove(MKDEV(capi_major, 0));
-		class_simple_destroy(capi_class);
+		class_device_destroy(capi_class, MKDEV(capi_major, 0));
+		class_destroy(capi_class);
 		unregister_chrdev(capi_major, "capi20");
 		return -ENOMEM;
 	}
@@ -1539,8 +1539,8 @@
 {
 	proc_exit();
 
-	class_simple_device_remove(MKDEV(capi_major, 0));
-	class_simple_destroy(capi_class);
+	class_device_destroy(capi_class, MKDEV(capi_major, 0));
+	class_destroy(capi_class);
 	unregister_chrdev(capi_major, "capi20");
 	devfs_remove("isdn/capi20");
 
diff --git a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c
index 55bed00..91dd055 100644
--- a/drivers/isdn/hardware/avm/b1dma.c
+++ b/drivers/isdn/hardware/avm/b1dma.c
@@ -955,7 +955,7 @@
 EXPORT_SYMBOL(b1dma_send_message);
 EXPORT_SYMBOL(b1dmactl_read_proc);
 
-int b1dma_init(void)
+static int __init b1dma_init(void)
 {
 	char *p;
 	char rev[32];
@@ -972,7 +972,7 @@
 	return 0;
 }
 
-void b1dma_exit(void)
+static void __exit b1dma_exit(void)
 {
 }
 
diff --git a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c
index fa6b93b..724aac2 100644
--- a/drivers/isdn/hardware/avm/c4.c
+++ b/drivers/isdn/hardware/avm/c4.c
@@ -885,7 +885,7 @@
 }
 
 
-void c4_reset_ctr(struct capi_ctr *ctrl)
+static void c4_reset_ctr(struct capi_ctr *ctrl)
 {
 	avmcard *card = ((avmctrl_info *)(ctrl->driverdata))->card;
 	avmctrl_info *cinfo;
@@ -933,7 +933,7 @@
 /* ------------------------------------------------------------- */
 
 
-void c4_register_appl(struct capi_ctr *ctrl,
+static void c4_register_appl(struct capi_ctr *ctrl,
 				u16 appl,
 				capi_register_params *rp)
 {
@@ -978,7 +978,7 @@
 
 /* ------------------------------------------------------------- */
 
-void c4_release_appl(struct capi_ctr *ctrl, u16 appl)
+static void c4_release_appl(struct capi_ctr *ctrl, u16 appl)
 {
 	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
 	avmcard *card = cinfo->card;
diff --git a/drivers/isdn/hardware/avm/t1isa.c b/drivers/isdn/hardware/avm/t1isa.c
index cb9d9ce..3b701d9 100644
--- a/drivers/isdn/hardware/avm/t1isa.c
+++ b/drivers/isdn/hardware/avm/t1isa.c
@@ -328,7 +328,7 @@
 	return 0;
 }
 
-void t1isa_reset_ctr(struct capi_ctr *ctrl)
+static void t1isa_reset_ctr(struct capi_ctr *ctrl)
 {
 	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
 	avmcard *card = cinfo->card;
diff --git a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile
index 8d6bb56..293e277 100644
--- a/drivers/isdn/hisax/Makefile
+++ b/drivers/isdn/hisax/Makefile
@@ -23,7 +23,7 @@
 # Multipart objects.
 
 hisax_st5481-y 				:= st5481_init.o st5481_usb.o st5481_d.o \
-					   st5481_b.o st5481_hdlc.o
+					   st5481_b.o
 
 hisax-y	  				:= config.o isdnl1.o tei.o isdnl2.o isdnl3.o \
 		     			   lmgr.o q931.o callc.o fsm.o
diff --git a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c
index c4f861a..8ae08c4 100644
--- a/drivers/isdn/hisax/amd7930_fn.c
+++ b/drivers/isdn/hisax/amd7930_fn.c
@@ -97,7 +97,7 @@
 };
 
 
-void /* macro wWordAMD */
+static void /* macro wWordAMD */
 WriteWordAmd7930(struct IsdnCardState *cs, BYTE reg, WORD val)
 {
         wByteAMD(cs, 0x00, reg);
@@ -105,7 +105,7 @@
         wByteAMD(cs, 0x01, HIBYTE(val));
 }
 
-WORD /* macro rWordAMD */
+static WORD /* macro rWordAMD */
 ReadWordAmd7930(struct IsdnCardState *cs, BYTE reg)
 {
         WORD res;
@@ -665,7 +665,7 @@
 	}
 }
 
-void
+static void
 setstack_Amd7930(struct PStack *st, struct IsdnCardState *cs)
 {
 
@@ -676,7 +676,7 @@
 }
 
 
-void
+static void
 DC_Close_Amd7930(struct IsdnCardState *cs) {
         if (cs->debug & L1_DEB_ISAC)
 		debugl1(cs, "Amd7930: DC_Close called");
diff --git a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c
index 7546e2e..a98c5e3 100644
--- a/drivers/isdn/hisax/asuscom.c
+++ b/drivers/isdn/hisax/asuscom.c
@@ -22,7 +22,7 @@
 
 extern const char *CardType[];
 
-const char *Asuscom_revision = "$Revision: 1.14.2.4 $";
+static const char *Asuscom_revision = "$Revision: 1.14.2.4 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -239,7 +239,7 @@
 	return IRQ_HANDLED;
 }
 
-void
+static void
 release_io_asuscom(struct IsdnCardState *cs)
 {
 	int bytecnt = 8;
diff --git a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
index 6fcb2cf..625799a 100644
--- a/drivers/isdn/hisax/avm_pci.c
+++ b/drivers/isdn/hisax/avm_pci.c
@@ -172,7 +172,7 @@
 		return(NULL);
 }
 
-void
+static void
 write_ctrl(struct BCState *bcs, int which) {
 
 	if (bcs->cs->debug & L1_DEB_HSCX)
@@ -193,7 +193,7 @@
 	}
 }
 
-void
+static void
 modehdlc(struct BCState *bcs, int mode, int bc)
 {
 	struct IsdnCardState *cs = bcs->cs;
@@ -451,7 +451,7 @@
 	}
 }
 
-inline void
+static inline void
 HDLC_irq_main(struct IsdnCardState *cs)
 {
 	u_int stat;
@@ -487,7 +487,7 @@
 	}
 }
 
-void
+static void
 hdlc_l2l1(struct PStack *st, int pr, void *arg)
 {
 	struct BCState *bcs = st->l1.bcs;
@@ -547,7 +547,7 @@
 	}
 }
 
-void
+static void
 close_hdlcstate(struct BCState *bcs)
 {
 	modehdlc(bcs, 0, 0);
@@ -570,7 +570,7 @@
 	}
 }
 
-int
+static int
 open_hdlcstate(struct IsdnCardState *cs, struct BCState *bcs)
 {
 	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
@@ -598,7 +598,7 @@
 	return (0);
 }
 
-int
+static int
 setstack_hdlc(struct PStack *st, struct BCState *bcs)
 {
 	bcs->channel = st->l1.bc;
@@ -612,6 +612,7 @@
 	return (0);
 }
 
+#if 0
 void __init
 clear_pending_hdlc_ints(struct IsdnCardState *cs)
 {
@@ -641,8 +642,9 @@
 		debugl1(cs, "HDLC 2 VIN %x", val);
 	}
 }
+#endif  /*  0  */
 
-void __init
+static void __init
 inithdlc(struct IsdnCardState *cs)
 {
 	cs->bcs[0].BC_SetStack = setstack_hdlc;
diff --git a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c
index f410f62..dcb308a 100644
--- a/drivers/isdn/hisax/bkm_a4t.c
+++ b/drivers/isdn/hisax/bkm_a4t.c
@@ -23,7 +23,7 @@
 
 extern const char *CardType[];
 
-const char *bkm_a4t_revision = "$Revision: 1.22.2.4 $";
+static const char *bkm_a4t_revision = "$Revision: 1.22.2.4 $";
 
 
 static inline u_char
@@ -167,7 +167,7 @@
 	}
 }
 
-void
+static void
 release_io_bkm(struct IsdnCardState *cs)
 {
 	if (cs->hw.ax.base) {
diff --git a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c
index 94bb83c..5f21b82 100644
--- a/drivers/isdn/hisax/bkm_a8.c
+++ b/drivers/isdn/hisax/bkm_a8.c
@@ -27,7 +27,7 @@
 
 extern const char *CardType[];
 
-const char sct_quadro_revision[] = "$Revision: 1.22.2.4 $";
+static const char sct_quadro_revision[] = "$Revision: 1.22.2.4 $";
 
 static const char *sct_quadro_subtypes[] =
 {
@@ -193,7 +193,7 @@
 	return IRQ_HANDLED;
 }
 
-void
+static void
 release_io_sct_quadro(struct IsdnCardState *cs)
 {
 	release_region(cs->hw.ax.base & 0xffffffc0, 128);
@@ -261,7 +261,7 @@
 	return (0);
 }
 
-int __init
+static int __init
 sct_alloc_io(u_int adr, u_int len)
 {
 	if (!request_region(adr, len, "scitel")) {
diff --git a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c
index 04065ab..7c56c44 100644
--- a/drivers/isdn/hisax/callc.c
+++ b/drivers/isdn/hisax/callc.c
@@ -874,7 +874,7 @@
 	} 
 }
 
-struct Channel
+static struct Channel
 *selectfreechannel(struct PStack *st, int bch)
 {
 	struct IsdnCardState *cs = st->l1.hardware;
@@ -1429,7 +1429,7 @@
 	HiSax_putstatus(chanp->cs, "Ch", "%d CAPIMSG %s", chanp->chan, tmpbuf);
 }
 
-void
+static void
 lli_got_fac_req(struct Channel *chanp, capi_msg *cm) {
 	if ((cm->para[0] != 3) || (cm->para[1] != 0))
 		return;
@@ -1454,7 +1454,7 @@
 	}
 }
 
-void
+static void
 lli_got_manufacturer(struct Channel *chanp, struct IsdnCardState *cs, capi_msg *cm) {
 	if ((cs->typ == ISDN_CTYPE_ELSA) || (cs->typ == ISDN_CTYPE_ELSA_PNP) ||
 		(cs->typ == ISDN_CTYPE_ELSA_PCI)) {
diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index 1663ee6..c542e6f 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -332,7 +332,7 @@
 #define HISAX_IDSIZE (HISAX_MAX_CARDS*8)
 static char HiSaxID[HISAX_IDSIZE] = { 0, };
 
-char *HiSax_id = HiSaxID;
+static char *HiSax_id = HiSaxID;
 #ifdef MODULE
 /* Variables for insmod */
 static int type[HISAX_MAX_CARDS] = { 0, };
@@ -391,7 +391,7 @@
 	return rev;
 }
 
-void __init HiSaxVersion(void)
+static void __init HiSaxVersion(void)
 {
 	char tmp[64];
 
@@ -608,6 +608,7 @@
 /*
  * Find card with given card number
  */
+#if 0
 struct IsdnCardState *hisax_get_card(int cardnr)
 {
 	if ((cardnr <= nrcards) && (cardnr > 0))
@@ -615,8 +616,9 @@
 			return cards[cardnr - 1].cs;
 	return NULL;
 }
+#endif  /*  0  */
 
-int HiSax_readstatus(u_char __user *buf, int len, int id, int channel)
+static int HiSax_readstatus(u_char __user *buf, int len, int id, int channel)
 {
 	int count, cnt;
 	u_char __user *p = buf;
@@ -768,7 +770,7 @@
 	return 0;
 }
 
-void ll_stop(struct IsdnCardState *cs)
+static void ll_stop(struct IsdnCardState *cs)
 {
 	isdn_ctrl ic;
 
@@ -1184,7 +1186,7 @@
 	return ret;
 }
 
-void HiSax_shiftcards(int idx)
+static void HiSax_shiftcards(int idx)
 {
 	int i;
 
@@ -1192,7 +1194,7 @@
 		memcpy(&cards[i], &cards[i + 1], sizeof(cards[i]));
 }
 
-int HiSax_inithardware(int *busy_flag)
+static int HiSax_inithardware(int *busy_flag)
 {
 	int foundcards = 0;
 	int i = 0;
diff --git a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c
index 394d481..b62d6b3 100644
--- a/drivers/isdn/hisax/diva.c
+++ b/drivers/isdn/hisax/diva.c
@@ -28,7 +28,7 @@
 
 extern const char *CardType[];
 
-const char *Diva_revision = "$Revision: 1.33.2.6 $";
+static const char *Diva_revision = "$Revision: 1.33.2.6 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -706,7 +706,7 @@
 	return IRQ_HANDLED;
 }
 
-void
+static void
 release_io_diva(struct IsdnCardState *cs)
 {
 	int bytecnt;
diff --git a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c
index 4d7a025..110e9fd 100644
--- a/drivers/isdn/hisax/elsa.c
+++ b/drivers/isdn/hisax/elsa.c
@@ -33,13 +33,13 @@
 
 extern const char *CardType[];
 
-const char *Elsa_revision = "$Revision: 2.32.2.4 $";
-const char *Elsa_Types[] =
+static const char *Elsa_revision = "$Revision: 2.32.2.4 $";
+static const char *Elsa_Types[] =
 {"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro",
  "PCMCIA", "QS 1000", "QS 3000", "Microlink PCI", "QS 3000 PCI", 
  "PCMCIA-IPAC" };
 
-const char *ITACVer[] =
+static const char *ITACVer[] =
 {"?0?", "?1?", "?2?", "?3?", "?4?", "V2.2",
  "B1", "A1"};
 
@@ -425,7 +425,7 @@
 	return IRQ_HANDLED;
 }
 
-void
+static void
 release_io_elsa(struct IsdnCardState *cs)
 {
 	int bytecnt = 8;
diff --git a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c
index 689c833..898ec09 100644
--- a/drivers/isdn/hisax/elsa_ser.c
+++ b/drivers/isdn/hisax/elsa_ser.c
@@ -237,7 +237,7 @@
 #endif
 }
 
-inline int
+static inline int
 write_modem(struct BCState *bcs) {
 	int ret=0;
 	struct IsdnCardState *cs = bcs->cs;
@@ -275,7 +275,7 @@
 	return(ret);
 }
 
-inline void
+static inline void
 modem_fill(struct BCState *bcs) {
 		
 	if (bcs->tx_skb) {
@@ -422,7 +422,7 @@
 extern void modehscx(struct BCState *bcs, int mode, int bc);
 extern void hscx_l2l1(struct PStack *st, int pr, void *arg);
 
-void
+static void
 close_elsastate(struct BCState *bcs)
 {
 	modehscx(bcs, 0, bcs->channel);
@@ -442,7 +442,7 @@
 	}
 }
 
-void
+static void
 modem_write_cmd(struct IsdnCardState *cs, u_char *buf, int len) {
 	int count, fp;
 	u_char *msg = buf;
@@ -472,7 +472,7 @@
 	}
 }
 
-void
+static void
 modem_set_init(struct IsdnCardState *cs) {
 	int timeout;
 
@@ -521,7 +521,7 @@
 	udelay(RCV_DELAY);
 }
 
-void
+static void
 modem_set_dial(struct IsdnCardState *cs, int outgoing) {
 	int timeout;
 #define RCV_DELAY 20000	
@@ -543,7 +543,7 @@
 	udelay(RCV_DELAY);
 }
 
-void
+static void
 modem_l2l1(struct PStack *st, int pr, void *arg)
 {
 	struct BCState *bcs = st->l1.bcs;
@@ -579,7 +579,7 @@
 	}
 }
 
-int
+static int
 setstack_elsa(struct PStack *st, struct BCState *bcs)
 {
 
@@ -614,7 +614,7 @@
 	return (0);
 }
 
-void
+static void
 init_modem(struct IsdnCardState *cs) {
 
 	cs->bcs[0].BC_SetStack = setstack_elsa;
@@ -641,7 +641,7 @@
 	modem_set_init(cs);
 }
 
-void
+static void
 release_modem(struct IsdnCardState *cs) {
 
 	cs->hw.elsa.MFlag = 0;
diff --git a/drivers/isdn/hisax/enternow.h b/drivers/isdn/hisax/enternow.h
deleted file mode 100644
index ed2eec5..0000000
--- a/drivers/isdn/hisax/enternow.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* 2001/10/02
- *
- * enternow.h   Header-file included by
- *              enternow_pci.c
- *
- * Author       Christoph Ersfeld <info@formula-n.de>
- *              Formula-n Europe AG (www.formula-n.com)
- *              previously Gerdes AG
- *
- *
- *              This file is (c) under GNU PUBLIC LICENSE
- */
-
-
-/* ***************************************************************************************** *
- * ****************************** datatypes and macros ************************************* *
- * ***************************************************************************************** */
-
-#define BYTE							unsigned char
-#define WORD							unsigned int
-#define HIBYTE(w)						((unsigned char)((w & 0xff00) / 256))
-#define LOBYTE(w)						((unsigned char)(w & 0x00ff))
-#define InByte(addr)						inb(addr)
-#define OutByte(addr,val)					outb(val,addr)
-
-
-
-/* ***************************************************************************************** *
- * *********************************** card-specific *************************************** *
- * ***************************************************************************************** */
-
-/* für PowerISDN PCI */
-#define TJ_AMD_IRQ 						0x20
-#define TJ_LED1 						0x40
-#define TJ_LED2 						0x80
-
-
-/* Das Fenster zum AMD...
- * Ab Adresse hw.njet.base + TJ_AMD_PORT werden vom AMD jeweils 8 Bit in
- * den TigerJet i/o-Raum gemappt
- * -> 0x01 des AMD bei hw.njet.base + 0C4 */
-#define TJ_AMD_PORT						0xC0
-
-
-
-/* ***************************************************************************************** *
- * *************************************** Prototypen ************************************** *
- * ***************************************************************************************** */
-
-BYTE ReadByteAmd7930(struct IsdnCardState *cs, BYTE offset);
-void WriteByteAmd7930(struct IsdnCardState *cs, BYTE offset, BYTE value);
diff --git a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c
index 1cc4d11..3341cf1 100644
--- a/drivers/isdn/hisax/enternow_pci.c
+++ b/drivers/isdn/hisax/enternow_pci.c
@@ -65,7 +65,6 @@
 #include "isac.h"
 #include "isdnl1.h"
 #include "amd7930_fn.h"
-#include "enternow.h"
 #include <linux/interrupt.h>
 #include <linux/ppp_defs.h>
 #include <linux/pci.h>
@@ -74,58 +73,72 @@
 
 
 
-const char *enternow_pci_rev = "$Revision: 1.1.4.5 $";
+static const char *enternow_pci_rev = "$Revision: 1.1.4.5 $";
+
+
+/* für PowerISDN PCI */
+#define TJ_AMD_IRQ                                              0x20
+#define TJ_LED1                                                 0x40
+#define TJ_LED2                                                 0x80
+
+
+/* Das Fenster zum AMD...
+ * Ab Adresse hw.njet.base + TJ_AMD_PORT werden vom AMD jeweils 8 Bit in
+ * den TigerJet i/o-Raum gemappt
+ * -> 0x01 des AMD bei hw.njet.base + 0C4 */
+#define TJ_AMD_PORT                                             0xC0
+
 
 
 /* *************************** I/O-Interface functions ************************************* */
 
 
 /* cs->readisac, macro rByteAMD */
-BYTE
-ReadByteAmd7930(struct IsdnCardState *cs, BYTE offset)
+static unsigned char
+ReadByteAmd7930(struct IsdnCardState *cs, unsigned char offset)
 {
 	/* direktes Register */
 	if(offset < 8)
-		return (InByte(cs->hw.njet.isac + 4*offset));
+		return (inb(cs->hw.njet.isac + 4*offset));
 
 	/* indirektes Register */
 	else {
-		OutByte(cs->hw.njet.isac + 4*AMD_CR, offset);
-		return(InByte(cs->hw.njet.isac + 4*AMD_DR));
+		outb(offset, cs->hw.njet.isac + 4*AMD_CR);
+		return(inb(cs->hw.njet.isac + 4*AMD_DR));
 	}
 }
 
 /* cs->writeisac, macro wByteAMD */
-void
-WriteByteAmd7930(struct IsdnCardState *cs, BYTE offset, BYTE value)
+static void
+WriteByteAmd7930(struct IsdnCardState *cs, unsigned char offset, unsigned char value)
 {
 	/* direktes Register */
 	if(offset < 8)
-		OutByte(cs->hw.njet.isac + 4*offset, value);
+		outb(value, cs->hw.njet.isac + 4*offset);
 
 	/* indirektes Register */
 	else {
-		OutByte(cs->hw.njet.isac + 4*AMD_CR, offset);
-		OutByte(cs->hw.njet.isac + 4*AMD_DR, value);
+		outb(offset, cs->hw.njet.isac + 4*AMD_CR);
+		outb(value, cs->hw.njet.isac + 4*AMD_DR);
 	}
 }
 
 
-void
-enpci_setIrqMask(struct IsdnCardState *cs, BYTE val) {
+static void
+enpci_setIrqMask(struct IsdnCardState *cs, unsigned char val) {
         if (!val)
-	        OutByte(cs->hw.njet.base+NETJET_IRQMASK1, 0x00);
+	        outb(0x00, cs->hw.njet.base+NETJET_IRQMASK1);
         else
-	        OutByte(cs->hw.njet.base+NETJET_IRQMASK1, TJ_AMD_IRQ);
+	        outb(TJ_AMD_IRQ, cs->hw.njet.base+NETJET_IRQMASK1);
 }
 
 
-static BYTE dummyrr(struct IsdnCardState *cs, int chan, BYTE off)
+static unsigned char dummyrr(struct IsdnCardState *cs, int chan, unsigned char off)
 {
         return(5);
 }
 
-static void dummywr(struct IsdnCardState *cs, int chan, BYTE off, BYTE value)
+static void dummywr(struct IsdnCardState *cs, int chan, unsigned char off, unsigned char value)
 {
 
 }
@@ -142,18 +155,18 @@
 
 	/* Reset on, (also for AMD) */
 	cs->hw.njet.ctrl_reg = 0x07;
-	OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+	outb(cs->hw.njet.ctrl_reg, cs->hw.njet.base + NETJET_CTRL);
 	mdelay(20);
 	/* Reset off */
 	cs->hw.njet.ctrl_reg = 0x30;
-	OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+	outb(cs->hw.njet.ctrl_reg, cs->hw.njet.base + NETJET_CTRL);
 	/* 20ms delay */
 	mdelay(20);
 	cs->hw.njet.auxd = 0;  // LED-status
 	cs->hw.njet.dmactrl = 0;
-	OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ);
-	OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ);
-	OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd); // LED off
+	outb(~TJ_AMD_IRQ, cs->hw.njet.base + NETJET_AUXCTRL);
+	outb(TJ_AMD_IRQ, cs->hw.njet.base + NETJET_IRQMASK1);
+	outb(cs->hw.njet.auxd, cs->hw.njet.auxa); // LED off
 }
 
 
@@ -161,7 +174,7 @@
 enpci_card_msg(struct IsdnCardState *cs, int mt, void *arg)
 {
 	u_long flags;
-        BYTE *chan;
+        unsigned char *chan;
 
 	if (cs->debug & L1_DEB_ISAC)
 		debugl1(cs, "enter:now PCI: card_msg: 0x%04X", mt);
@@ -187,16 +200,16 @@
                 case MDL_ASSIGN:
                         /* TEI assigned, LED1 on */
                         cs->hw.njet.auxd = TJ_AMD_IRQ << 1;
-                        OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd);
+                        outb(cs->hw.njet.auxd, cs->hw.njet.base + NETJET_AUXDATA);
                         break;
                 case MDL_REMOVE:
                         /* TEI removed, LEDs off */
 	                cs->hw.njet.auxd = 0;
-                        OutByte(cs->hw.njet.base + NETJET_AUXDATA, 0x00);
+                        outb(0x00, cs->hw.njet.base + NETJET_AUXDATA);
                         break;
                 case MDL_BC_ASSIGN:
                         /* activate B-channel */
-                        chan = (BYTE *)arg;
+                        chan = (unsigned char *)arg;
 
                         if (cs->debug & L1_DEB_ISAC)
 		                debugl1(cs, "enter:now PCI: assign phys. BC %d in AMD LMR1", *chan);
@@ -204,11 +217,11 @@
                         cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 | (*chan + 1)), "MDL_BC_ASSIGN");
                         /* at least one b-channel in use, LED 2 on */
                         cs->hw.njet.auxd |= TJ_AMD_IRQ << 2;
-                        OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd);
+                        outb(cs->hw.njet.auxd, cs->hw.njet.base + NETJET_AUXDATA);
                         break;
                 case MDL_BC_RELEASE:
                         /* deactivate B-channel */
-                        chan = (BYTE *)arg;
+                        chan = (unsigned char *)arg;
 
                         if (cs->debug & L1_DEB_ISAC)
 		                debugl1(cs, "enter:now PCI: release phys. BC %d in Amd LMR1", *chan);
@@ -217,7 +230,7 @@
                         /* no b-channel active -> LED2 off */
                         if (!(cs->dc.amd7930.lmr1 & 3)) {
                                 cs->hw.njet.auxd &= ~(TJ_AMD_IRQ << 2);
-                                OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd);
+                                outb(cs->hw.njet.auxd, cs->hw.njet.base + NETJET_AUXDATA);
                         }
                         break;
                 default:
@@ -231,11 +244,11 @@
 enpci_interrupt(int intno, void *dev_id, struct pt_regs *regs)
 {
 	struct IsdnCardState *cs = dev_id;
-	BYTE s0val, s1val, ir;
+	unsigned char s0val, s1val, ir;
 	u_long flags;
 
 	spin_lock_irqsave(&cs->lock, flags);
-	s1val = InByte(cs->hw.njet.base + NETJET_IRQSTAT1);
+	s1val = inb(cs->hw.njet.base + NETJET_IRQSTAT1);
 
         /* AMD threw an interrupt */
 	if (!(s1val & TJ_AMD_IRQ)) {
@@ -245,13 +258,13 @@
 		s1val = 1;
 	} else
 		s1val = 0;
-	s0val = InByte(cs->hw.njet.base + NETJET_IRQSTAT0);
+	s0val = inb(cs->hw.njet.base + NETJET_IRQSTAT0);
 	if ((s0val | s1val)==0) { // shared IRQ
 		spin_unlock_irqrestore(&cs->lock, flags);
 		return IRQ_NONE;
 	} 
 	if (s0val)
-		OutByte(cs->hw.njet.base + NETJET_IRQSTAT0, s0val);
+		outb(s0val, cs->hw.njet.base + NETJET_IRQSTAT0);
 
 	/* DMA-Interrupt: B-channel-stuff */
 	/* set bits in sval to indicate which page is free */
@@ -342,20 +355,20 @@
 
 		/* Reset an */
 		cs->hw.njet.ctrl_reg = 0x07;  // geändert von 0xff
-		OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+		outb(cs->hw.njet.ctrl_reg, cs->hw.njet.base + NETJET_CTRL);
 		/* 20 ms Pause */
 		mdelay(20);
 
 		cs->hw.njet.ctrl_reg = 0x30;  /* Reset Off and status read clear */
-		OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg);
+		outb(cs->hw.njet.ctrl_reg, cs->hw.njet.base + NETJET_CTRL);
 		mdelay(10);
 
 		cs->hw.njet.auxd = 0x00; // war 0xc0
 		cs->hw.njet.dmactrl = 0;
 
-		OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ);
-		OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ);
-		OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd);
+		outb(~TJ_AMD_IRQ, cs->hw.njet.base + NETJET_AUXCTRL);
+		outb(TJ_AMD_IRQ, cs->hw.njet.base + NETJET_IRQMASK1);
+		outb(cs->hw.njet.auxd, cs->hw.njet.auxa);
 
 		break;
 	}
diff --git a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c
index 24a05a4..352b45a 100644
--- a/drivers/isdn/hisax/gazel.c
+++ b/drivers/isdn/hisax/gazel.c
@@ -21,7 +21,7 @@
 #include <linux/pci.h>
 
 extern const char *CardType[];
-const char *gazel_revision = "$Revision: 2.19.2.4 $";
+static const char *gazel_revision = "$Revision: 2.19.2.4 $";
 
 #define R647      1
 #define R685      2
@@ -317,7 +317,8 @@
 	spin_unlock_irqrestore(&cs->lock, flags);
 	return IRQ_HANDLED;
 }
-void
+
+static void
 release_io_gazel(struct IsdnCardState *cs)
 {
 	unsigned int i;
diff --git a/drivers/isdn/hisax/hfc4s8s_l1.c b/drivers/isdn/hisax/hfc4s8s_l1.c
index ba1d028..6e7e060 100644
--- a/drivers/isdn/hisax/hfc4s8s_l1.c
+++ b/drivers/isdn/hisax/hfc4s8s_l1.c
@@ -1358,7 +1358,7 @@
 /********************************************/
 /* disable/enable hardware in nt or te mode */
 /********************************************/
-void
+static void
 hfc_hardware_enable(hfc4s8s_hw * hw, int enable, int nt_mode)
 {
 	u_long flags;
diff --git a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c
index ebea3fe..7cf8779 100644
--- a/drivers/isdn/hisax/hfc_2bds0.c
+++ b/drivers/isdn/hisax/hfc_2bds0.c
@@ -345,7 +345,7 @@
 		debugl1(cs,"send_data %d blocked", bcs->channel);
 }
 
-void
+static void
 main_rec_2bds0(struct BCState *bcs)
 {
 	struct IsdnCardState *cs = bcs->cs;
@@ -399,7 +399,7 @@
 	return;
 }
 
-void
+static void
 mode_2bs0(struct BCState *bcs, int mode, int bc)
 {
 	struct IsdnCardState *cs = bcs->cs;
@@ -505,7 +505,7 @@
 	}
 }
 
-void
+static void
 close_2bs0(struct BCState *bcs)
 {
 	mode_2bs0(bcs, 0, bcs->channel);
@@ -534,7 +534,7 @@
 	return (0);
 }
 
-int
+static int
 setstack_2b(struct PStack *st, struct BCState *bcs)
 {
 	bcs->channel = st->l1.bc;
@@ -1004,7 +1004,7 @@
 	}
 }
 
-void
+static void
 setstack_hfcd(struct PStack *st, struct IsdnCardState *cs)
 {
 	st->l1.l1hw = HFCD_l1hw;
@@ -1015,7 +1015,7 @@
 {
 }
 
-unsigned int __init
+static unsigned int __init
 *init_send_hfcd(int cnt)
 {
 	int i, *send;
diff --git a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c
index bb376f3..f978a5a 100644
--- a/drivers/isdn/hisax/hfc_2bs0.c
+++ b/drivers/isdn/hisax/hfc_2bs0.c
@@ -52,7 +52,7 @@
 		return (to);
 }
 
-int
+static int
 GetFreeFifoBytes(struct BCState *bcs)
 {
 	int s;
@@ -66,7 +66,7 @@
 	return (s);
 }
 
-int
+static int
 ReadZReg(struct BCState *bcs, u_char reg)
 {
 	int val;
@@ -394,7 +394,7 @@
 	return;
 }
 
-void
+static void
 mode_hfc(struct BCState *bcs, int mode, int bc)
 {
 	struct IsdnCardState *cs = bcs->cs;
@@ -507,7 +507,7 @@
 }
 
 
-void
+static void
 close_hfcstate(struct BCState *bcs)
 {
 	mode_hfc(bcs, 0, bcs->channel);
@@ -537,7 +537,7 @@
 	return (0);
 }
 
-int
+static int
 setstack_hfc(struct PStack *st, struct BCState *bcs)
 {
 	bcs->channel = st->l1.bc;
@@ -551,7 +551,7 @@
 	return (0);
 }
 
-void __init
+static void __init
 init_send(struct BCState *bcs)
 {
 	int i;
diff --git a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
index c2db526..8337b0f 100644
--- a/drivers/isdn/hisax/hfc_pci.c
+++ b/drivers/isdn/hisax/hfc_pci.c
@@ -70,7 +70,7 @@
 /******************************************/
 /* free hardware resources used by driver */
 /******************************************/
-void
+static void
 release_io_hfcpci(struct IsdnCardState *cs)
 {
 	printk(KERN_INFO "HiSax: release hfcpci at %p\n",
@@ -394,7 +394,7 @@
 /*******************************************************************************/
 /* check for transparent receive data and read max one threshold size if avail */
 /*******************************************************************************/
-int
+static int
 hfcpci_empty_fifo_trans(struct BCState *bcs, bzfifo_type * bz, u_char * bdata)
 {
 	unsigned short *z1r, *z2r;
@@ -446,7 +446,7 @@
 /**********************************/
 /* B-channel main receive routine */
 /**********************************/
-void
+static void
 main_rec_hfcpci(struct BCState *bcs)
 {
 	struct IsdnCardState *cs = bcs->cs;
@@ -1244,7 +1244,7 @@
 /***********************************************/
 /* called during init setting l1 stack pointer */
 /***********************************************/
-void
+static void
 setstack_hfcpci(struct PStack *st, struct IsdnCardState *cs)
 {
 	st->l1.l1hw = HFCPCI_l1hw;
@@ -1268,7 +1268,7 @@
 /***************************************************************/
 /* activate/deactivate hardware for selected channels and mode */
 /***************************************************************/
-void
+static void
 mode_hfcpci(struct BCState *bcs, int mode, int bc)
 {
 	struct IsdnCardState *cs = bcs->cs;
@@ -1579,7 +1579,7 @@
 /********************************/
 /* called for card init message */
 /********************************/
-void __init
+static void __init
 inithfcpci(struct IsdnCardState *cs)
 {
 	cs->bcs[0].BC_SetStack = setstack_2b;
diff --git a/drivers/isdn/hisax/hfc_pci.h b/drivers/isdn/hisax/hfc_pci.h
index 4df036e..9ef2981 100644
--- a/drivers/isdn/hisax/hfc_pci.h
+++ b/drivers/isdn/hisax/hfc_pci.h
@@ -232,5 +232,4 @@
 #define Read_hfc(a,b) (*(((u_char *)a->hw.hfcpci.pci_io)+b))
 
 extern void main_irq_hcpci(struct BCState *bcs);
-extern void inithfcpci(struct IsdnCardState *cs);
 extern void releasehfcpci(struct IsdnCardState *cs);
diff --git a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c
index a307fcb..f27c160 100644
--- a/drivers/isdn/hisax/hfc_sx.c
+++ b/drivers/isdn/hisax/hfc_sx.c
@@ -308,7 +308,7 @@
 /******************************************/
 /* free hardware resources used by driver */
 /******************************************/
-void
+static void
 release_io_hfcsx(struct IsdnCardState *cs)
 {
 	cs->hw.hfcsx.int_m2 = 0;	/* interrupt output off ! */
@@ -472,7 +472,7 @@
 /**********************************/
 /* B-channel main receive routine */
 /**********************************/
-void
+static void
 main_rec_hfcsx(struct BCState *bcs)
 {
 	struct IsdnCardState *cs = bcs->cs;
@@ -1003,7 +1003,7 @@
 /***********************************************/
 /* called during init setting l1 stack pointer */
 /***********************************************/
-void
+static void
 setstack_hfcsx(struct PStack *st, struct IsdnCardState *cs)
 {
 	st->l1.l1hw = HFCSX_l1hw;
@@ -1027,7 +1027,7 @@
 /***************************************************************/
 /* activate/deactivate hardware for selected channels and mode */
 /***************************************************************/
-void
+static void
 mode_hfcsx(struct BCState *bcs, int mode, int bc)
 {
 	struct IsdnCardState *cs = bcs->cs;
@@ -1328,7 +1328,7 @@
 /********************************/
 /* called for card init message */
 /********************************/
-void __devinit
+static void __devinit
 inithfcsx(struct IsdnCardState *cs)
 {
 	cs->setstack_d = setstack_hfcsx;
diff --git a/drivers/isdn/hisax/hfc_sx.h b/drivers/isdn/hisax/hfc_sx.h
index 12f5415..6792f13 100644
--- a/drivers/isdn/hisax/hfc_sx.h
+++ b/drivers/isdn/hisax/hfc_sx.h
@@ -193,5 +193,4 @@
 };
 
 extern void main_irq_hfcsx(struct BCState *bcs);
-extern void inithfcsx(struct IsdnCardState *cs);
 extern void releasehfcsx(struct IsdnCardState *cs);
diff --git a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c
index ffd74b8..e2c3af4 100644
--- a/drivers/isdn/hisax/hfc_usb.c
+++ b/drivers/isdn/hisax/hfc_usb.c
@@ -60,7 +60,7 @@
 #include "hisax_debug.h"
 static u_int debug;
 module_param(debug, uint, 0);
-int hfc_debug;
+static int hfc_debug;
 #endif
 
 
@@ -85,7 +85,7 @@
 *   VendorID, ProductID, Devicename, LED_SCHEME,
 *   LED's BitMask in HFCUSB_P_DATA Register : LED_USB, LED_S0, LED_B1, LED_B2
 */
-vendor_data vdata[] = {
+static vendor_data vdata[] = {
 	/* CologneChip Eval TA */
 	{0x0959, 0x2bd0, "ISDN USB TA (Cologne Chip HFC-S USB based)",
 	 LED_OFF, {4, 0, 2, 1}
@@ -1137,7 +1137,7 @@
 	}
 }
 
-void
+static void
 hfc_usb_l2l1(struct hisax_if *my_hisax_if, int pr, void *arg)
 {
 	usb_fifo *fifo = my_hisax_if->priv;
diff --git a/drivers/isdn/hisax/hfc_usb.h b/drivers/isdn/hisax/hfc_usb.h
index b171600..280dd29 100644
--- a/drivers/isdn/hisax/hfc_usb.h
+++ b/drivers/isdn/hisax/hfc_usb.h
@@ -168,7 +168,7 @@
 * 3 entries are the configuration number, the minimum interval for
 * Interrupt endpoints & boolean if E-channel logging possible
 */
-int validconf[][19] = {
+static int validconf[][19] = {
 	// INT in, ISO out config
 	{EP_NUL, EP_INT, EP_NUL, EP_INT, EP_NUL, EP_INT, EP_NOP, EP_INT,
 	 EP_ISO, EP_NUL, EP_ISO, EP_NUL, EP_ISO, EP_NUL, EP_NUL, EP_NUL,
@@ -187,7 +187,7 @@
 };
 
 // string description of chosen config
-char *conf_str[] = {
+static char *conf_str[] = {
 	"4 Interrupt IN + 3 Isochron OUT",
 	"3 Interrupt IN + 3 Isochron OUT",
 	"4 Isochron IN + 3 Isochron OUT",
diff --git a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c
index 6fc55fe..86ab1c1 100644
--- a/drivers/isdn/hisax/hfcscard.c
+++ b/drivers/isdn/hisax/hfcscard.c
@@ -52,7 +52,7 @@
 */
 }
 
-void
+static void
 release_io_hfcs(struct IsdnCardState *cs)
 {
 	release2bds0(cs);
diff --git a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h
index dc57917..17cf766 100644
--- a/drivers/isdn/hisax/hisax.h
+++ b/drivers/isdn/hisax/hisax.h
@@ -1271,7 +1271,6 @@
 void init_bcstate(struct IsdnCardState *cs, int bc);
 
 void setstack_HiSax(struct PStack *st, struct IsdnCardState *cs);
-unsigned int random_ri(void);
 void HiSax_addlist(struct IsdnCardState *sp, struct PStack *st);
 void HiSax_rmlist(struct IsdnCardState *sp, struct PStack *st);
 
@@ -1315,15 +1314,11 @@
 void LogFrame(struct IsdnCardState *cs, u_char * p, int size);
 void dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir);
 void iecpy(u_char * dest, u_char * iestart, int ieoffset);
-#ifdef ISDN_CHIP_ISAC
-void setstack_isac(struct PStack *st, struct IsdnCardState *cs);
-#endif	/* ISDN_CHIP_ISAC */
 #endif	/* __KERNEL__ */
 
 #define HZDELAY(jiffs) {int tout = jiffs; while (tout--) udelay(1000000/HZ);}
 
 int ll_run(struct IsdnCardState *cs, int addfeatures);
-void ll_stop(struct IsdnCardState *cs);
 int CallcNew(void);
 void CallcFree(void);
 int CallcNewChan(struct IsdnCardState *cs);
diff --git a/drivers/isdn/hisax/hscx.c b/drivers/isdn/hisax/hscx.c
index 5bbbe3e..66dbaee 100644
--- a/drivers/isdn/hisax/hscx.c
+++ b/drivers/isdn/hisax/hscx.c
@@ -151,7 +151,7 @@
 	}
 }
 
-void
+static void
 close_hscxstate(struct BCState *bcs)
 {
 	modehscx(bcs, 0, bcs->channel);
@@ -203,7 +203,7 @@
 	return (0);
 }
 
-int
+static int
 setstack_hscx(struct PStack *st, struct BCState *bcs)
 {
 	bcs->channel = st->l1.bc;
diff --git a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c
index dcf31f8..b4ca585 100644
--- a/drivers/isdn/hisax/icc.c
+++ b/drivers/isdn/hisax/icc.c
@@ -108,7 +108,7 @@
 #endif
 }
 
-void
+static void
 icc_empty_fifo(struct IsdnCardState *cs, int count)
 {
 	u_char *ptr;
@@ -563,13 +563,13 @@
 	}
 }
 
-void
+static void
 setstack_icc(struct PStack *st, struct IsdnCardState *cs)
 {
 	st->l1.l1hw = ICC_l1hw;
 }
 
-void 
+static void
 DC_Close_icc(struct IsdnCardState *cs) {
 	if (cs->dc.icc.mon_rx) {
 		kfree(cs->dc.icc.mon_rx);
diff --git a/drivers/isdn/hisax/ipacx.c b/drivers/isdn/hisax/ipacx.c
index 6485e23..efba2f4 100644
--- a/drivers/isdn/hisax/ipacx.c
+++ b/drivers/isdn/hisax/ipacx.c
@@ -36,8 +36,6 @@
 static inline void cic_int(struct IsdnCardState *cs);
 static void dch_l2l1(struct PStack *st, int pr, void *arg);
 static void dbusy_timer_handler(struct IsdnCardState *cs);
-static void ipacx_new_ph(struct IsdnCardState *cs);
-static void dch_bh(struct IsdnCardState *cs);
 static void dch_empty_fifo(struct IsdnCardState *cs, int count);
 static void dch_fill_fifo(struct IsdnCardState *cs);
 static inline void dch_int(struct IsdnCardState *cs);
@@ -232,81 +230,6 @@
 }
 
 //----------------------------------------------------------
-// L1 state machine intermediate layer to isdnl1 module
-//----------------------------------------------------------
-static void
-ipacx_new_ph(struct IsdnCardState *cs)
-{
-	switch (cs->dc.isac.ph_state) {
-		case (IPACX_IND_RES):
-			ph_command(cs, IPACX_CMD_DI);
-			l1_msg(cs, HW_RESET | INDICATION, NULL);
-			break;
-      
-		case (IPACX_IND_DC):
-			l1_msg(cs, HW_DEACTIVATE | CONFIRM, NULL);
-			break;
-      
-		case (IPACX_IND_DR):
-			l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
-			break;
-      
-		case (IPACX_IND_PU):
-			l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
-			break;
-
-		case (IPACX_IND_RSY):
-			l1_msg(cs, HW_RSYNC | INDICATION, NULL);
-			break;
-
-		case (IPACX_IND_AR):
-			l1_msg(cs, HW_INFO2 | INDICATION, NULL);
-			break;
-      
-		case (IPACX_IND_AI8):
-			l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
-			break;
-      
-		case (IPACX_IND_AI10):
-			l1_msg(cs, HW_INFO4_P10 | INDICATION, NULL);
-			break;
-      
-		default:
-			break;
-	}
-}
-
-//----------------------------------------------------------
-// bottom half handler for D channel
-//----------------------------------------------------------
-static void
-dch_bh(struct IsdnCardState *cs)
-{
-	struct PStack *st;
-	
-	if (!cs) return;
-  
-	if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
-		if (cs->debug) debugl1(cs, "D-Channel Busy cleared");
-		for (st = cs->stlist; st; st = st->next) {
-			st->l1.l1l2(st, PH_PAUSE | CONFIRM, NULL);
-		}
-	}
-  
-	if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) {
-		DChannel_proc_rcv(cs);
-  }  
-  
-	if (test_and_clear_bit(D_XMTBUFREADY, &cs->event)) {
-		DChannel_proc_xmt(cs);
-  }  
-  
-	if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
-    ipacx_new_ph(cs);
-  }  
-}
-
-//----------------------------------------------------------
 // Fill buffer from receive FIFO
 //----------------------------------------------------------
 static void 
@@ -991,14 +914,5 @@
 	}
 }
 
-
-void __devinit
-setup_ipacx(struct IsdnCardState *cs)
-{
-	INIT_WORK(&cs->tqueue, (void *)(void *) dch_bh, cs);
-	cs->dbusytimer.function = (void *) dbusy_timer_handler;
-	cs->dbusytimer.data = (long) cs;
-	init_timer(&cs->dbusytimer);
-}
 //----------------- end of file -----------------------
 
diff --git a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c
index 20b9499..85e063a 100644
--- a/drivers/isdn/hisax/isac.c
+++ b/drivers/isdn/hisax/isac.c
@@ -112,7 +112,7 @@
 #endif
 }
 
-void
+static void
 isac_empty_fifo(struct IsdnCardState *cs, int count)
 {
 	u_char *ptr;
@@ -563,13 +563,13 @@
 	}
 }
 
-void
+static void
 setstack_isac(struct PStack *st, struct IsdnCardState *cs)
 {
 	st->l1.l1hw = ISAC_l1hw;
 }
 
-void 
+static void
 DC_Close_isac(struct IsdnCardState *cs) {
 	if (cs->dc.isac.mon_rx) {
 		kfree(cs->dc.isac.mon_rx);
diff --git a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c
index ee081321..642a87c 100644
--- a/drivers/isdn/hisax/isar.c
+++ b/drivers/isdn/hisax/isar.c
@@ -21,13 +21,13 @@
 #define ETX	0x03
 
 #define FAXMODCNT	13
-const	u_char	faxmodulation[] = {3,24,48,72,73,74,96,97,98,121,122,145,146};
+static const	u_char	faxmodulation[] = {3,24,48,72,73,74,96,97,98,121,122,145,146};
 static	u_int	modmask = 0x1fff;
 static	int	frm_extra_delay = 2;
 static	int	para_TOA = 6;
-const   u_char  *FC1_CMD[] = {"FAE", "FTS", "FRS", "FTM", "FRM", "FTH", "FRH", "CTRL" };
+static const   u_char  *FC1_CMD[] = {"FAE", "FTS", "FRS", "FTM", "FRM", "FTH", "FRH", "CTRL" };
 
-void isar_setup(struct IsdnCardState *cs);
+static void isar_setup(struct IsdnCardState *cs);
 static void isar_pump_cmd(struct BCState *bcs, u_char cmd, u_char para);
 static void ll_deliver_faxstat(struct BCState *bcs, u_char status);
 
@@ -45,7 +45,7 @@
 }
 
 
-int
+static int
 sendmsg(struct IsdnCardState *cs, u_char his, u_char creg, u_char len,
 	u_char *msg)
 {
@@ -85,7 +85,7 @@
 }
 
 /* Call only with IRQ disabled !!! */
-inline void
+static inline void
 rcv_mbox(struct IsdnCardState *cs, struct isar_reg *ireg, u_char *msg)
 {
 	int i;
@@ -114,7 +114,7 @@
 }
 
 /* Call only with IRQ disabled !!! */
-inline void
+static inline void
 get_irq_infos(struct IsdnCardState *cs, struct isar_reg *ireg)
 {
 	ireg->iis = cs->BC_Read_Reg(cs, 1, ISAR_IIS);
@@ -127,7 +127,7 @@
 #endif
 }
 
-int
+static int
 waitrecmsg(struct IsdnCardState *cs, u_char *len,
 	u_char *msg, int maxdelay)
 {
@@ -185,7 +185,7 @@
 	return(ver);
 }
 
-int
+static int
 isar_load_firmware(struct IsdnCardState *cs, u_char __user *buf)
 {
 	int ret, size, cnt, debug;
@@ -739,7 +739,7 @@
 	}
 }
 
-inline
+static inline
 struct BCState *sel_bcs_isar(struct IsdnCardState *cs, u_char dpath)
 {
 	if ((!dpath) || (dpath == 3))
@@ -751,7 +751,7 @@
 	return(NULL);
 }
 
-void
+static void
 send_frames(struct BCState *bcs)
 {
 	if (bcs->tx_skb) {
@@ -806,7 +806,7 @@
 	}
 }
 
-inline void
+static inline void
 check_send(struct IsdnCardState *cs, u_char rdm)
 {
 	struct BCState *bcs;
@@ -828,11 +828,13 @@
 	
 }
 
-const char *dmril[] = {"NO SPEED", "1200/75", "NODEF2", "75/1200", "NODEF4",
-			"300", "600", "1200", "2400", "4800", "7200",
-			"9600nt", "9600t", "12000", "14400", "WRONG"};
-const char *dmrim[] = {"NO MOD", "NO DEF", "V32/V32b", "V22", "V21",
-			"Bell103", "V23", "Bell202", "V17", "V29", "V27ter"};
+static const char *dmril[] = {"NO SPEED", "1200/75", "NODEF2", "75/1200",
+				"NODEF4", "300", "600", "1200", "2400",
+				"4800", "7200", "9600nt", "9600t", "12000",
+				"14400", "WRONG"};
+static const char *dmrim[] = {"NO MOD", "NO DEF", "V32/V32b", "V22", "V21",
+				"Bell103", "V23", "Bell202", "V17", "V29",
+				"V27ter"};
 
 static void
 isar_pump_status_rsp(struct BCState *bcs, struct isar_reg *ireg) {
@@ -1388,7 +1390,7 @@
 	udelay(1000);
 }
 
-int
+static int
 modeisar(struct BCState *bcs, int mode, int bc)
 {
 	struct IsdnCardState *cs = bcs->cs;
@@ -1562,7 +1564,7 @@
 		sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, ctrl, nom, &p1);
 }
 
-void
+static void
 isar_setup(struct IsdnCardState *cs)
 {
 	u_char msg;
@@ -1582,7 +1584,7 @@
 	}
 }
 
-void
+static void
 isar_l2l1(struct PStack *st, int pr, void *arg)
 {
 	struct BCState *bcs = st->l1.bcs;
@@ -1681,7 +1683,7 @@
 	}
 }
 
-void
+static void
 close_isarstate(struct BCState *bcs)
 {
 	modeisar(bcs, 0, bcs->channel);
@@ -1703,7 +1705,7 @@
 	del_timer(&bcs->hw.isar.ftimer);
 }
 
-int
+static int
 open_isarstate(struct IsdnCardState *cs, struct BCState *bcs)
 {
 	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
@@ -1725,7 +1727,7 @@
 	return (0);
 }
 
-int
+static int
 setstack_isar(struct PStack *st, struct BCState *bcs)
 {
 	bcs->channel = st->l1.bc;
diff --git a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c
index 4d08d27..ac89950 100644
--- a/drivers/isdn/hisax/isdnl1.c
+++ b/drivers/isdn/hisax/isdnl1.c
@@ -151,7 +151,7 @@
 	va_end(args);
 }
 
-void
+static void
 L1activated(struct IsdnCardState *cs)
 {
 	struct PStack *st;
@@ -166,7 +166,7 @@
 	}
 }
 
-void
+static void
 L1deactivated(struct IsdnCardState *cs)
 {
 	struct PStack *st;
@@ -370,7 +370,7 @@
 
 #ifdef L2FRAME_DEBUG		/* psa */
 
-char *
+static char *
 l2cmd(u_char cmd)
 {
 	switch (cmd & ~0x10) {
@@ -404,7 +404,7 @@
 
 static char tmpdeb[32];
 
-char *
+static char *
 l2frames(u_char * ptr)
 {
 	switch (ptr[2] & ~0x10) {
diff --git a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c
index d311b5f..9022583 100644
--- a/drivers/isdn/hisax/isdnl2.c
+++ b/drivers/isdn/hisax/isdnl2.c
@@ -142,7 +142,7 @@
 	return cnt;
 }
 
-inline void
+static inline void
 freewin(struct PStack *st)
 {
 	freewin1(&st->l2);
@@ -157,7 +157,7 @@
 		printk(KERN_WARNING "isdl2 freed %d skbuffs in release\n", cnt);
 }
 
-inline unsigned int
+static inline unsigned int
 cansend(struct PStack *st)
 {
 	unsigned int p1;
@@ -169,7 +169,7 @@
 	return ((p1 < st->l2.window) && !test_bit(FLG_PEER_BUSY, &st->l2.flag));
 }
 
-inline void
+static inline void
 clear_exception(struct Layer2 *l2)
 {
 	test_and_clear_bit(FLG_ACK_PEND, &l2->flag);
@@ -178,7 +178,7 @@
 	clear_peer_busy(l2);
 }
 
-inline int
+static inline int
 l2headersize(struct Layer2 *l2, int ui)
 {
 	return (((test_bit(FLG_MOD128, &l2->flag) && (!ui)) ? 2 : 1) +
@@ -223,40 +223,31 @@
 
 #define enqueue_ui(a, b) enqueue_super(a, b)
 
-inline int
+static inline int
 IsUI(u_char * data)
 {
 	return ((data[0] & 0xef) == UI);
 }
 
-inline int
+static inline int
 IsUA(u_char * data)
 {
 	return ((data[0] & 0xef) == UA);
 }
 
-inline int
+static inline int
 IsDM(u_char * data)
 {
 	return ((data[0] & 0xef) == DM);
 }
 
-inline int
+static inline int
 IsDISC(u_char * data)
 {
 	return ((data[0] & 0xef) == DISC);
 }
 
-inline int
-IsRR(u_char * data, struct PStack *st)
-{
-	if (test_bit(FLG_MOD128, &st->l2.flag))
-		return (data[0] == RR);
-	else
-		return ((data[0] & 0xf) == 1);
-}
-
-inline int
+static inline int
 IsSFrame(u_char * data, struct PStack *st)
 {
 	register u_char d = *data;
@@ -266,7 +257,7 @@
 	return(((d & 0xf3) == 1) && ((d & 0x0c) != 0x0c));
 }
 
-inline int
+static inline int
 IsSABME(u_char * data, struct PStack *st)
 {
 	u_char d = data[0] & ~0x10;
@@ -274,25 +265,25 @@
 	return (test_bit(FLG_MOD128, &st->l2.flag) ? d == SABME : d == SABM);
 }
 
-inline int
+static inline int
 IsREJ(u_char * data, struct PStack *st)
 {
 	return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == REJ : (data[0] & 0xf) == REJ);
 }
 
-inline int
+static inline int
 IsFRMR(u_char * data)
 {
 	return ((data[0] & 0xef) == FRMR);
 }
 
-inline int
+static inline int
 IsRNR(u_char * data, struct PStack *st)
 {
 	return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == RNR : (data[0] & 0xf) == RNR);
 }
 
-int
+static int
 iframe_error(struct PStack *st, struct sk_buff *skb)
 {
 	int i = l2addrsize(&st->l2) + (test_bit(FLG_MOD128, &st->l2.flag) ? 2 : 1);
@@ -315,7 +306,7 @@
 	return 0;
 }
 
-int
+static int
 super_error(struct PStack *st, struct sk_buff *skb)
 {
 	if (skb->len != l2addrsize(&st->l2) +
@@ -325,7 +316,7 @@
 	return 0;
 }
 
-int
+static int
 unnum_error(struct PStack *st, struct sk_buff *skb, int wantrsp)
 {
 	int rsp = (*skb->data & 0x2) >> 1;
@@ -341,7 +332,7 @@
 	return 0;
 }
 
-int
+static int
 UI_error(struct PStack *st, struct sk_buff *skb)
 {
 	int rsp = *skb->data & 0x2;
@@ -357,7 +348,7 @@
 	return 0;
 }
 
-int
+static int
 FRMR_error(struct PStack *st, struct sk_buff *skb)
 {
 	int headers = l2addrsize(&st->l2) + 1;
@@ -444,51 +435,44 @@
 	enqueue_super(st, skb);
 }
 
-inline u_char
+static inline u_char
 get_PollFlag(struct PStack * st, struct sk_buff * skb)
 {
 	return (skb->data[l2addrsize(&(st->l2))] & 0x10);
 }
 
-inline void
-FreeSkb(struct sk_buff *skb)
-{
-	dev_kfree_skb(skb);
-}
-
-
-inline u_char
+static inline u_char
 get_PollFlagFree(struct PStack *st, struct sk_buff *skb)
 {
 	u_char PF;
 
 	PF = get_PollFlag(st, skb);
-	FreeSkb(skb);
+	dev_kfree_skb(skb);
 	return (PF);
 }
 
-inline void
+static inline void
 start_t200(struct PStack *st, int i)
 {
 	FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, i);
 	test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
 }
 
-inline void
+static inline void
 restart_t200(struct PStack *st, int i)
 {
 	FsmRestartTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, i);
 	test_and_set_bit(FLG_T200_RUN, &st->l2.flag);
 }
 
-inline void
+static inline void
 stop_t200(struct PStack *st, int i)
 {
 	if(test_and_clear_bit(FLG_T200_RUN, &st->l2.flag))
 		FsmDelTimer(&st->l2.t200, i);
 }
 
-inline void
+static inline void
 st5_dl_release_l2l3(struct PStack *st)
 {
 		int pr;
@@ -501,7 +485,7 @@
 		st->l2.l2l3(st, pr, NULL);
 }
 
-inline void
+static inline void
 lapb_dl_release_l2l3(struct PStack *st, int f)
 {
 		if (test_bit(FLG_LAPB, &st->l2.flag))
@@ -802,7 +786,7 @@
 		l2_mdl_error_ua(fi, event, arg);
 		return;
 	}
-	FreeSkb(skb);
+	dev_kfree_skb(skb);
 
 	if (test_and_clear_bit(FLG_PEND_REL, &st->l2.flag))
 		l2_disconnect(fi, event, arg);
@@ -840,7 +824,7 @@
 		l2_mdl_error_ua(fi, event, arg);
 		return;
 	}
-	FreeSkb(skb);
+	dev_kfree_skb(skb);
 
 	stop_t200(st, 6);
 	lapb_dl_release_l2l3(st, CONFIRM);
@@ -889,7 +873,7 @@
 	}
 }
 
-inline void
+static inline void
 enquiry_cr(struct PStack *st, u_char typ, u_char cr, u_char pf)
 {
 	struct sk_buff *skb;
@@ -912,7 +896,7 @@
 	enqueue_super(st, skb);
 }
 
-inline void
+static inline void
 enquiry_response(struct PStack *st)
 {
 	if (test_bit(FLG_OWN_BUSY, &st->l2.flag))
@@ -922,7 +906,7 @@
 	test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
 }
 
-inline void
+static inline void
 transmit_enquiry(struct PStack *st)
 {
 	if (test_bit(FLG_OWN_BUSY, &st->l2.flag))
@@ -1004,7 +988,7 @@
 		PollFlag = (skb->data[0] & 0x10);
 		nr = (skb->data[0] >> 5) & 0x7;
 	}
-	FreeSkb(skb);
+	dev_kfree_skb(skb);
 
 	if (PollFlag) {
 		if (rsp)
@@ -1047,7 +1031,7 @@
 	if (!test_bit(FLG_L3_INIT, &st->l2.flag))
 		skb_queue_tail(&st->l2.i_queue, skb);
 	else
-		FreeSkb(skb);
+		dev_kfree_skb(skb);
 }
 
 static void
@@ -1093,7 +1077,7 @@
 		nr = (skb->data[i] >> 5) & 0x7;
 	}
 	if (test_bit(FLG_OWN_BUSY, &l2->flag)) {
-		FreeSkb(skb);
+		dev_kfree_skb(skb);
 		if(PollFlag) enquiry_response(st);
 	} else if (l2->vr == ns) {
 		(l2->vr)++;
@@ -1111,7 +1095,7 @@
 		st->l2.l2l3(st, DL_DATA | INDICATION, skb);
 	} else {
 		/* n(s)!=v(r) */
-		FreeSkb(skb);
+		dev_kfree_skb(skb);
 		if (test_and_set_bit(FLG_REJEXC, &l2->flag)) {
 			if (PollFlag)
 				enquiry_response(st);
@@ -1309,7 +1293,7 @@
 		skb = alloc_skb(oskb->len + i, GFP_ATOMIC);
 		memcpy(skb_put(skb, i), header, i);
 		memcpy(skb_put(skb, oskb->len), oskb->data, oskb->len);
-		FreeSkb(oskb);
+		dev_kfree_skb(oskb);
 	}
 	st->l2.l2l1(st, PH_PULL | INDICATION, skb);
 	test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag);
@@ -1349,7 +1333,7 @@
 		PollFlag = (skb->data[0] & 0x10);
 		nr = (skb->data[0] >> 5) & 0x7;
 	}
-	FreeSkb(skb);
+	dev_kfree_skb(skb);
 
 	if (rsp && PollFlag) {
 		if (legalnr(st, nr)) {
@@ -1391,7 +1375,7 @@
 		establishlink(fi);
 		test_and_clear_bit(FLG_L3_INIT, &st->l2.flag);
 	}
-	FreeSkb(skb);
+	dev_kfree_skb(skb);
 }
 
 static void
@@ -1655,7 +1639,7 @@
 				datap += len;
 			else {
 				FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) 'N');
-				FreeSkb(skb);
+				dev_kfree_skb(skb);
 				return;
 			}
 			if (!(*datap & 1)) {	/* I-Frame */
@@ -1684,16 +1668,16 @@
 					ret = FsmEvent(&st->l2.l2m, EV_L2_FRMR, skb);
 			} else {
 				FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *) 'L');
-				FreeSkb(skb);
+				dev_kfree_skb(skb);
 				ret = 0;
 			}
 			if(c) {
-				FreeSkb(skb);
+				dev_kfree_skb(skb);
 				FsmEvent(&st->l2.l2m, EV_L2_FRAME_ERROR, (void *)(long)c);
 				ret = 0;
 			}
 			if (ret)
-				FreeSkb(skb);
+				dev_kfree_skb(skb);
 			break;
 		case (PH_PULL | CONFIRM):
 			FsmEvent(&st->l2.l2m, EV_L2_ACK_PULL, arg);
diff --git a/drivers/isdn/hisax/isdnl3.c b/drivers/isdn/hisax/isdnl3.c
index f571b5d..abcc953 100644
--- a/drivers/isdn/hisax/isdnl3.c
+++ b/drivers/isdn/hisax/isdnl3.c
@@ -390,7 +390,7 @@
 	}
 }
 
-void
+static void
 isdnl3_trans(struct PStack *st, int pr, void *arg) {
 	st->l3.l3l2(st, pr, arg);
 }
diff --git a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c
index af5171d..33747af 100644
--- a/drivers/isdn/hisax/isurf.c
+++ b/drivers/isdn/hisax/isurf.c
@@ -122,7 +122,7 @@
 	return IRQ_HANDLED;
 }
 
-void
+static void
 release_io_isurf(struct IsdnCardState *cs)
 {
 	release_region(cs->hw.isurf.reset, 1);
diff --git a/drivers/isdn/hisax/ix1_micro.c b/drivers/isdn/hisax/ix1_micro.c
index b843b75..908a7e1 100644
--- a/drivers/isdn/hisax/ix1_micro.c
+++ b/drivers/isdn/hisax/ix1_micro.c
@@ -25,7 +25,7 @@
 #include "isdnl1.h"
 
 extern const char *CardType[];
-const char *ix1_revision = "$Revision: 2.12.2.4 $";
+static const char *ix1_revision = "$Revision: 2.12.2.4 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -162,7 +162,7 @@
 	return IRQ_HANDLED;
 }
 
-void
+static void
 release_io_ix1micro(struct IsdnCardState *cs)
 {
 	if (cs->hw.ix1.cfg_reg)
diff --git a/drivers/isdn/hisax/jade.c b/drivers/isdn/hisax/jade.c
index f05d527..363ae31 100644
--- a/drivers/isdn/hisax/jade.c
+++ b/drivers/isdn/hisax/jade.c
@@ -74,7 +74,7 @@
 
 
 
-void
+static void
 modejade(struct BCState *bcs, int mode, int bc)
 {
     struct IsdnCardState *cs = bcs->cs;
@@ -190,7 +190,7 @@
     }
 }
 
-void
+static void
 close_jadestate(struct BCState *bcs)
 {
     modejade(bcs, 0, bcs->channel);
@@ -243,7 +243,7 @@
 }
 
 
-int
+static int
 setstack_jade(struct PStack *st, struct BCState *bcs)
 {
 	bcs->channel = st->l1.bc;
diff --git a/drivers/isdn/hisax/jade.h b/drivers/isdn/hisax/jade.h
index fa29444..29055e1 100644
--- a/drivers/isdn/hisax/jade.h
+++ b/drivers/isdn/hisax/jade.h
@@ -128,7 +128,6 @@
 #define	jade_TXAUDIOCH2CFG				0x1A
 
 extern int JadeVersion(struct IsdnCardState *cs, char *s);
-extern void modejade(struct BCState *bcs, int mode, int bc);
 extern void clear_pending_jade_ints(struct IsdnCardState *cs);
 extern void initjade(struct IsdnCardState *cs);
 
diff --git a/drivers/isdn/hisax/l3_1tr6.c b/drivers/isdn/hisax/l3_1tr6.c
index d6c1c8f..c5c36ee 100644
--- a/drivers/isdn/hisax/l3_1tr6.c
+++ b/drivers/isdn/hisax/l3_1tr6.c
@@ -19,7 +19,7 @@
 #include <linux/ctype.h>
 
 extern char *HiSax_getrev(const char *revision);
-const char *l3_1tr6_revision = "$Revision: 2.15.2.3 $";
+static const char *l3_1tr6_revision = "$Revision: 2.15.2.3 $";
 
 #define MsgHead(ptr, cref, mty, dis) \
 	*ptr++ = dis; \
diff --git a/drivers/isdn/hisax/l3dss1.c b/drivers/isdn/hisax/l3dss1.c
index ec92308..a6d2abd 100644
--- a/drivers/isdn/hisax/l3dss1.c
+++ b/drivers/isdn/hisax/l3dss1.c
@@ -26,7 +26,7 @@
 #include <linux/config.h>
 
 extern char *HiSax_getrev(const char *revision);
-const char *dss1_revision = "$Revision: 2.32.2.3 $";
+static const char *dss1_revision = "$Revision: 2.32.2.3 $";
 
 #define EXT_BEARER_CAPS 1
 
diff --git a/drivers/isdn/hisax/l3ni1.c b/drivers/isdn/hisax/l3ni1.c
index 3ab3a54..f7041d5 100644
--- a/drivers/isdn/hisax/l3ni1.c
+++ b/drivers/isdn/hisax/l3ni1.c
@@ -24,7 +24,7 @@
 #include <linux/ctype.h>
 
 extern char *HiSax_getrev(const char *revision);
-const char *ni1_revision = "$Revision: 2.8.2.3 $";
+static const char *ni1_revision = "$Revision: 2.8.2.3 $";
 
 #define EXT_BEARER_CAPS 1
 
@@ -2665,7 +2665,7 @@
 	l3ni1_SendSpid( pc, pr, arg, 20 );
 }
 
-void l3ni1_spid_epid( struct l3_process *pc, u_char pr, void *arg )
+static void l3ni1_spid_epid( struct l3_process *pc, u_char pr, void *arg )
 {
 	struct sk_buff *skb = arg;
 
diff --git a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c
index 3ac4484..fe11f22 100644
--- a/drivers/isdn/hisax/mic.c
+++ b/drivers/isdn/hisax/mic.c
@@ -18,7 +18,7 @@
 
 extern const char *CardType[];
 
-const char *mic_revision = "$Revision: 1.12.2.4 $";
+static const char *mic_revision = "$Revision: 1.12.2.4 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -157,7 +157,7 @@
 	return IRQ_HANDLED;
 }
 
-void
+static void
 release_io_mic(struct IsdnCardState *cs)
 {
 	int bytecnt = 8;
diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c
index fe61d26..94da03c 100644
--- a/drivers/isdn/hisax/netjet.c
+++ b/drivers/isdn/hisax/netjet.c
@@ -25,8 +25,6 @@
 #include <asm/io.h>
 #include "netjet.h"
 
-const char *NETjet_revision = "$Revision: 1.29.2.4 $";
-
 /* Interface functions */
 
 u_char
@@ -66,7 +64,7 @@
 	outsb(cs->hw.njet.isac, data, size);
 }
 
-void fill_mem(struct BCState *bcs, u_int *pos, u_int cnt, int chan, u_char fill)
+static void fill_mem(struct BCState *bcs, u_int *pos, u_int cnt, int chan, u_char fill)
 {
 	u_int mask=0x000000ff, val = 0, *p=pos;
 	u_int i;
@@ -85,7 +83,7 @@
 	}
 }
 
-void
+static void
 mode_tiger(struct BCState *bcs, int mode, int bc)
 {
 	struct IsdnCardState *cs = bcs->cs;
@@ -852,7 +850,7 @@
 }
 
 
-void
+static void
 close_tigerstate(struct BCState *bcs)
 {
 	mode_tiger(bcs, 0, bcs->channel);
@@ -900,7 +898,7 @@
 	return (0);
 }
 
-int
+static int
 setstack_tiger(struct PStack *st, struct BCState *bcs)
 {
 	bcs->channel = st->l1.bc;
@@ -966,7 +964,7 @@
 	cs->bcs[1].BC_Close = close_tigerstate;
 }
 
-void
+static void
 releasetiger(struct IsdnCardState *cs)
 {
 	if (cs->bcs[0].hw.tiger.send) {
diff --git a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c
index cf77d83..68a2159 100644
--- a/drivers/isdn/hisax/niccy.c
+++ b/drivers/isdn/hisax/niccy.c
@@ -24,7 +24,7 @@
 #include <linux/isapnp.h>
 
 extern const char *CardType[];
-const char *niccy_revision = "$Revision: 1.21.2.4 $";
+static const char *niccy_revision = "$Revision: 1.21.2.4 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -178,7 +178,7 @@
 	return IRQ_HANDLED;
 }
 
-void
+static void
 release_io_niccy(struct IsdnCardState *cs)
 {
 	if (cs->subtyp == NICCY_PCI) {
diff --git a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c
index fd66469..a7d3cd3 100644
--- a/drivers/isdn/hisax/nj_s.c
+++ b/drivers/isdn/hisax/nj_s.c
@@ -15,7 +15,7 @@
 #include <linux/ppp_defs.h>
 #include "netjet.h"
 
-const char *NETjet_S_revision = "$Revision: 2.13.2.4 $";
+static const char *NETjet_S_revision = "$Revision: 2.13.2.4 $";
 
 static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
 {
diff --git a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c
index 3d6441e..1ae7cac 100644
--- a/drivers/isdn/hisax/nj_u.c
+++ b/drivers/isdn/hisax/nj_u.c
@@ -15,7 +15,7 @@
 #include <linux/ppp_defs.h>
 #include "netjet.h"
 
-const char *NETjet_U_revision = "$Revision: 2.14.2.3 $";
+static const char *NETjet_U_revision = "$Revision: 2.14.2.3 $";
 
 static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
 {
diff --git a/drivers/isdn/hisax/q931.c b/drivers/isdn/hisax/q931.c
index 170fcd4..abecabf 100644
--- a/drivers/isdn/hisax/q931.c
+++ b/drivers/isdn/hisax/q931.c
@@ -516,7 +516,7 @@
 	{CAUSE_UserInfoDiscarded, "User Info Discarded"}
 };
 
-int cause_1tr6_len = (sizeof(cause_1tr6) / sizeof(struct MessageType));
+static int cause_1tr6_len = (sizeof(cause_1tr6) / sizeof(struct MessageType));
 
 static int
 prcause_1tr6(char *dest, u_char * p)
@@ -935,7 +935,7 @@
 	return (dp - dest);
 }
 
-int
+static int
 prfacility(char *dest, u_char * p)
 {
 	char *dp = dest;
diff --git a/drivers/isdn/hisax/s0box.c b/drivers/isdn/hisax/s0box.c
index f3c4813..7b63085 100644
--- a/drivers/isdn/hisax/s0box.c
+++ b/drivers/isdn/hisax/s0box.c
@@ -17,7 +17,7 @@
 #include "isdnl1.h"
 
 extern const char *CardType[];
-const char *s0box_revision = "$Revision: 2.6.2.4 $";
+static const char *s0box_revision = "$Revision: 2.6.2.4 $";
 
 static inline void
 writereg(unsigned int padr, signed int addr, u_char off, u_char val) {
@@ -183,7 +183,7 @@
 	return IRQ_HANDLED;
 }
 
-void
+static void
 release_io_s0box(struct IsdnCardState *cs)
 {
 	release_region(cs->hw.teles3.cfg_reg, 8);
diff --git a/drivers/isdn/hisax/saphir.c b/drivers/isdn/hisax/saphir.c
index 9e6d3d6..821776e 100644
--- a/drivers/isdn/hisax/saphir.c
+++ b/drivers/isdn/hisax/saphir.c
@@ -171,7 +171,7 @@
 	mod_timer(&cs->hw.saphir.timer, jiffies+1*HZ);
 }
 
-void
+static void
 release_io_saphir(struct IsdnCardState *cs)
 {
 	byteout(cs->hw.saphir.cfg_reg + IRQ_REG, 0xff);
diff --git a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c
index 8390f16..8c044a6 100644
--- a/drivers/isdn/hisax/sedlbauer.c
+++ b/drivers/isdn/hisax/sedlbauer.c
@@ -51,9 +51,9 @@
 
 extern const char *CardType[];
 
-const char *Sedlbauer_revision = "$Revision: 1.34.2.6 $";
+static const char *Sedlbauer_revision = "$Revision: 1.34.2.6 $";
 
-const char *Sedlbauer_Types[] =
+static const char *Sedlbauer_Types[] =
 	{"None", "speed card/win", "speed star", "speed fax+",
 	"speed win II / ISDN PC/104", "speed star II", "speed pci",
 	"speed fax+ pyramid", "speed fax+ pci", "HST Saphir III"};
@@ -394,7 +394,7 @@
 	return IRQ_HANDLED;
 }
 
-void
+static void
 release_io_sedlbauer(struct IsdnCardState *cs)
 {
 	int bytecnt = 8;
diff --git a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c
index 132840b..cdf35dc 100644
--- a/drivers/isdn/hisax/sportster.c
+++ b/drivers/isdn/hisax/sportster.c
@@ -19,7 +19,7 @@
 #include "isdnl1.h"
 
 extern const char *CardType[];
-const char *sportster_revision = "$Revision: 1.16.2.4 $";
+static const char *sportster_revision = "$Revision: 1.16.2.4 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -132,7 +132,7 @@
 	return IRQ_HANDLED;
 }
 
-void
+static void
 release_io_sportster(struct IsdnCardState *cs)
 {
 	int i, adr;
@@ -144,7 +144,7 @@
 	}
 }
 
-void
+static void
 reset_sportster(struct IsdnCardState *cs)
 {
 	cs->hw.spt.res_irq |= SPORTSTER_RESET; /* Reset On */
diff --git a/drivers/isdn/hisax/st5481.h b/drivers/isdn/hisax/st5481.h
index e8177b0..0fda5c8 100644
--- a/drivers/isdn/hisax/st5481.h
+++ b/drivers/isdn/hisax/st5481.h
@@ -450,12 +450,8 @@
 			   usb_complete_t complete, void *context);
 void st5481_release_isocpipes(struct urb* urb[2]);
 
-int  st5481_isoc_flatten(struct urb *urb);
 void st5481_usb_pipe_reset(struct st5481_adapter *adapter,
 		    u_char pipe, ctrl_complete_t complete, void *context);
-void st5481_usb_ctrl_msg(struct st5481_adapter *adapter,
-		  u8 request, u8 requesttype, u16 value, u16 index,
-		  ctrl_complete_t complete, void *context);
 void st5481_usb_device_ctrl_msg(struct st5481_adapter *adapter,
 			 u8 request, u16 value,
 			 ctrl_complete_t complete, void *context);
diff --git a/drivers/isdn/hisax/st5481_hdlc.c b/drivers/isdn/hisax/st5481_hdlc.c
deleted file mode 100644
index 680f42e..0000000
--- a/drivers/isdn/hisax/st5481_hdlc.c
+++ /dev/null
@@ -1,580 +0,0 @@
-/*
- * Driver for ST5481 USB ISDN modem
- *
- * Author       Frode Isaksen
- * Copyright    2001 by Frode Isaksen      <fisaksen@bewan.com>
- *              2001 by Kai Germaschewski  <kai.germaschewski@gmx.de>
- * 
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#include <linux/crc-ccitt.h>
-#include "st5481_hdlc.h"
-
-
-enum {
-	HDLC_FAST_IDLE,HDLC_GET_FLAG_B0,HDLC_GETFLAG_B1A6,HDLC_GETFLAG_B7,
-	HDLC_GET_DATA,HDLC_FAST_FLAG
-};
-
-enum {
-	HDLC_SEND_DATA,HDLC_SEND_CRC1,HDLC_SEND_FAST_FLAG,
-	HDLC_SEND_FIRST_FLAG,HDLC_SEND_CRC2,HDLC_SEND_CLOSING_FLAG,
-	HDLC_SEND_IDLE1,HDLC_SEND_FAST_IDLE,HDLC_SENDFLAG_B0,
-	HDLC_SENDFLAG_B1A6,HDLC_SENDFLAG_B7,STOPPED
-};
-
-void 
-hdlc_rcv_init(struct hdlc_vars *hdlc, int do_adapt56)
-{
-   	hdlc->bit_shift = 0;
-	hdlc->hdlc_bits1 = 0;
-	hdlc->data_bits = 0;
-	hdlc->ffbit_shift = 0;
-	hdlc->data_received = 0;
-	hdlc->state = HDLC_GET_DATA;
-	hdlc->do_adapt56 = do_adapt56;
-	hdlc->dchannel = 0;
-	hdlc->crc = 0;
-	hdlc->cbin = 0;
-	hdlc->shift_reg = 0;
-	hdlc->ffvalue = 0;
-	hdlc->dstpos = 0;
-}
-
-void 
-hdlc_out_init(struct hdlc_vars *hdlc, int is_d_channel, int do_adapt56)
-{
-   	hdlc->bit_shift = 0;
-	hdlc->hdlc_bits1 = 0;
-	hdlc->data_bits = 0;
-	hdlc->ffbit_shift = 0;
-	hdlc->data_received = 0;
-	hdlc->do_closing = 0;
-	hdlc->ffvalue = 0;
-	if (is_d_channel) {
-		hdlc->dchannel = 1;
-		hdlc->state = HDLC_SEND_FIRST_FLAG;
-	} else {
-		hdlc->dchannel = 0;
-		hdlc->state = HDLC_SEND_FAST_FLAG;
-		hdlc->ffvalue = 0x7e;
-	} 
-	hdlc->cbin = 0x7e;
-	hdlc->bit_shift = 0;
-	if(do_adapt56){
-		hdlc->do_adapt56 = 1;		
-		hdlc->data_bits = 0;
-		hdlc->state = HDLC_SENDFLAG_B0;
-	} else {
-		hdlc->do_adapt56 = 0;		
-		hdlc->data_bits = 8;
-	}
-	hdlc->shift_reg = 0;
-}
-
-/*
-  hdlc_decode - decodes HDLC frames from a transparent bit stream.
-
-  The source buffer is scanned for valid HDLC frames looking for
-  flags (01111110) to indicate the start of a frame. If the start of
-  the frame is found, the bit stuffing is removed (0 after 5 1's).
-  When a new flag is found, the complete frame has been received
-  and the CRC is checked.
-  If a valid frame is found, the function returns the frame length 
-  excluding the CRC with the bit HDLC_END_OF_FRAME set.
-  If the beginning of a valid frame is found, the function returns
-  the length. 
-  If a framing error is found (too many 1s and not a flag) the function 
-  returns the length with the bit HDLC_FRAMING_ERROR set.
-  If a CRC error is found the function returns the length with the
-  bit HDLC_CRC_ERROR set.
-  If the frame length exceeds the destination buffer size, the function
-  returns the length with the bit HDLC_LENGTH_ERROR set.
-
-  src - source buffer
-  slen - source buffer length
-  count - number of bytes removed (decoded) from the source buffer
-  dst _ destination buffer
-  dsize - destination buffer size
-  returns - number of decoded bytes in the destination buffer and status
-  flag.
- */
-int hdlc_decode(struct hdlc_vars *hdlc, const unsigned char *src,
-		int slen, int *count, unsigned char *dst, int dsize)
-{
-	int status=0;
-
-	static const unsigned char fast_flag[]={
-		0x00,0x00,0x00,0x20,0x30,0x38,0x3c,0x3e,0x3f
-	};
-
-	static const unsigned char fast_flag_value[]={
-		0x00,0x7e,0xfc,0xf9,0xf3,0xe7,0xcf,0x9f,0x3f
-	};
-
-	static const unsigned char fast_abort[]={
-		0x00,0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff
-	};
-
-	*count = slen;
-
-	while(slen > 0){
-		if(hdlc->bit_shift==0){
-			hdlc->cbin = *src++;
-			slen--;
-			hdlc->bit_shift = 8;
-			if(hdlc->do_adapt56){
-				hdlc->bit_shift --;
-			}
-		}
-
-		switch(hdlc->state){
-		case STOPPED:
-			return 0;
-		case HDLC_FAST_IDLE:
-			if(hdlc->cbin == 0xff){
-				hdlc->bit_shift = 0;
-				break;
-			}
-			hdlc->state = HDLC_GET_FLAG_B0;
-			hdlc->hdlc_bits1 = 0;
-			hdlc->bit_shift = 8;
-			break;
-		case HDLC_GET_FLAG_B0:
-			if(!(hdlc->cbin & 0x80)) {
-				hdlc->state = HDLC_GETFLAG_B1A6;
-				hdlc->hdlc_bits1 = 0;
-			} else {
-				if(!hdlc->do_adapt56){
-					if(++hdlc->hdlc_bits1 >=8 ) if(hdlc->bit_shift==1)
-						hdlc->state = HDLC_FAST_IDLE;
-				}
-			}
-			hdlc->cbin<<=1;
-			hdlc->bit_shift --;
-			break;
-		case HDLC_GETFLAG_B1A6:
-			if(hdlc->cbin & 0x80){
-				hdlc->hdlc_bits1++;
-				if(hdlc->hdlc_bits1==6){
-					hdlc->state = HDLC_GETFLAG_B7;
-				}
-			} else {
-				hdlc->hdlc_bits1 = 0;
-			}
-			hdlc->cbin<<=1;
-			hdlc->bit_shift --;
-			break;
-		case HDLC_GETFLAG_B7:
-			if(hdlc->cbin & 0x80) {
-				hdlc->state = HDLC_GET_FLAG_B0;
-			} else {
-				hdlc->state = HDLC_GET_DATA;
-				hdlc->crc = 0xffff;
-				hdlc->shift_reg = 0;
-				hdlc->hdlc_bits1 = 0;
-				hdlc->data_bits = 0;
-				hdlc->data_received = 0;
-			}
-			hdlc->cbin<<=1;
-			hdlc->bit_shift --;
-			break;
-		case HDLC_GET_DATA:
-			if(hdlc->cbin & 0x80){
-				hdlc->hdlc_bits1++;
-				switch(hdlc->hdlc_bits1){
-				case 6:
-					break;
-				case 7:
-					if(hdlc->data_received) {
-						// bad frame
-						status = -HDLC_FRAMING_ERROR;
-					}
-					if(!hdlc->do_adapt56){
-						if(hdlc->cbin==fast_abort[hdlc->bit_shift+1]){
-							hdlc->state = HDLC_FAST_IDLE;
-							hdlc->bit_shift=1;
-							break;
-						}
-					} else {
-						hdlc->state = HDLC_GET_FLAG_B0;
-					}
-					break;
-				default:
-					hdlc->shift_reg>>=1;
-					hdlc->shift_reg |= 0x80;
-					hdlc->data_bits++;
-					break;
-				}
-			} else {
-				switch(hdlc->hdlc_bits1){
-				case 5:
-					break;
-				case 6:
-					if(hdlc->data_received){
-						if (hdlc->dstpos < 2) {
-							status = -HDLC_FRAMING_ERROR;
-						} else if (hdlc->crc != 0xf0b8){
-							// crc error
-							status = -HDLC_CRC_ERROR;
-						} else {
-							// remove CRC
-							hdlc->dstpos -= 2;
-							// good frame
-							status = hdlc->dstpos;
-						}
-					}
-					hdlc->crc = 0xffff;
-					hdlc->shift_reg = 0;
-					hdlc->data_bits = 0;
-					if(!hdlc->do_adapt56){
-						if(hdlc->cbin==fast_flag[hdlc->bit_shift]){
-							hdlc->ffvalue = fast_flag_value[hdlc->bit_shift];
-							hdlc->state = HDLC_FAST_FLAG;
-							hdlc->ffbit_shift = hdlc->bit_shift;
-							hdlc->bit_shift = 1;
-						} else {
-							hdlc->state = HDLC_GET_DATA;
-							hdlc->data_received = 0;
-						}
-					} else {
-						hdlc->state = HDLC_GET_DATA;
-						hdlc->data_received = 0;
-					}
-					break;
-				default:
-					hdlc->shift_reg>>=1;
-					hdlc->data_bits++;
-					break;
-				}
-				hdlc->hdlc_bits1 = 0;
-			}
-			if (status) {
-				hdlc->dstpos = 0;
-				*count -= slen;
-				hdlc->cbin <<= 1;
-				hdlc->bit_shift--;
-				return status;
-			}
-			if(hdlc->data_bits==8){
-				hdlc->data_bits = 0;
-				hdlc->data_received = 1;
-				hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg);
-
-				// good byte received
-				if (dsize--) {
-					dst[hdlc->dstpos++] = hdlc->shift_reg;
-				} else {
-					// frame too long
-					status = -HDLC_LENGTH_ERROR;
-					hdlc->dstpos = 0;
-				}
-			}
-			hdlc->cbin <<= 1;
-			hdlc->bit_shift--;
-			break;
-		case HDLC_FAST_FLAG:
-			if(hdlc->cbin==hdlc->ffvalue){
-				hdlc->bit_shift = 0;
-				break;
-			} else {
-				if(hdlc->cbin == 0xff){
-					hdlc->state = HDLC_FAST_IDLE;
-					hdlc->bit_shift=0;
-				} else if(hdlc->ffbit_shift==8){
-					hdlc->state = HDLC_GETFLAG_B7;
-					break;
-				} else {
-					hdlc->shift_reg = fast_abort[hdlc->ffbit_shift-1];
-					hdlc->hdlc_bits1 = hdlc->ffbit_shift-2;
-					if(hdlc->hdlc_bits1<0)hdlc->hdlc_bits1 = 0;
-					hdlc->data_bits = hdlc->ffbit_shift-1;
-					hdlc->state = HDLC_GET_DATA;
-					hdlc->data_received = 0;
-				}
-			}
-			break;
-		default:
-			break;
-		}
-	}
-	*count -= slen;
-	return 0;
-}
-
-/*
-  hdlc_encode - encodes HDLC frames to a transparent bit stream.
-
-  The bit stream starts with a beginning flag (01111110). After
-  that each byte is added to the bit stream with bit stuffing added
-  (0 after 5 1's).
-  When the last byte has been removed from the source buffer, the
-  CRC (2 bytes is added) and the frame terminates with the ending flag.
-  For the dchannel, the idle character (all 1's) is also added at the end.
-  If this function is called with empty source buffer (slen=0), flags or
-  idle character will be generated.
- 
-  src - source buffer
-  slen - source buffer length
-  count - number of bytes removed (encoded) from source buffer
-  dst _ destination buffer
-  dsize - destination buffer size
-  returns - number of encoded bytes in the destination buffer
-*/
-int hdlc_encode(struct hdlc_vars *hdlc, const unsigned char *src, 
-		unsigned short slen, int *count,
-		unsigned char *dst, int dsize)
-{
-	static const unsigned char xfast_flag_value[] = {
-		0x7e,0x3f,0x9f,0xcf,0xe7,0xf3,0xf9,0xfc,0x7e
-	};
-
-	int len = 0;
-
-	*count = slen;
-
-	while (dsize > 0) {
-		if(hdlc->bit_shift==0){	
-			if(slen && !hdlc->do_closing){
-				hdlc->shift_reg = *src++;
-				slen--;
-				if (slen == 0) 
-					hdlc->do_closing = 1;  /* closing sequence, CRC + flag(s) */
-				hdlc->bit_shift = 8;
-			} else {
-				if(hdlc->state == HDLC_SEND_DATA){
-					if(hdlc->data_received){
-						hdlc->state = HDLC_SEND_CRC1;
-						hdlc->crc ^= 0xffff;
-						hdlc->bit_shift = 8;
-						hdlc->shift_reg = hdlc->crc & 0xff;
-					} else if(!hdlc->do_adapt56){
-						hdlc->state = HDLC_SEND_FAST_FLAG;
-					} else {
-						hdlc->state = HDLC_SENDFLAG_B0;
-					}
-				}
-			  
-			}
-		}
-
-		switch(hdlc->state){
-		case STOPPED:
-			while (dsize--)
-				*dst++ = 0xff;
-		  
-			return dsize;
-		case HDLC_SEND_FAST_FLAG:
-			hdlc->do_closing = 0;
-			if(slen == 0){
-				*dst++ = hdlc->ffvalue;
-				len++;
-				dsize--;
-				break;
-			}
-			if(hdlc->bit_shift==8){
-				hdlc->cbin = hdlc->ffvalue>>(8-hdlc->data_bits);
-				hdlc->state = HDLC_SEND_DATA;
-				hdlc->crc = 0xffff;
-				hdlc->hdlc_bits1 = 0;
-				hdlc->data_received = 1;
-			}
-			break;
-		case HDLC_SENDFLAG_B0:
-			hdlc->do_closing = 0;
-			hdlc->cbin <<= 1;
-			hdlc->data_bits++;
-			hdlc->hdlc_bits1 = 0;
-			hdlc->state = HDLC_SENDFLAG_B1A6;
-			break;
-		case HDLC_SENDFLAG_B1A6:
-			hdlc->cbin <<= 1;
-			hdlc->data_bits++;
-			hdlc->cbin++;
-			if(++hdlc->hdlc_bits1 == 6)
-				hdlc->state = HDLC_SENDFLAG_B7;
-			break;
-		case HDLC_SENDFLAG_B7:
-			hdlc->cbin <<= 1;
-			hdlc->data_bits++;
-			if(slen == 0){
-				hdlc->state = HDLC_SENDFLAG_B0;
-				break;
-			}
-			if(hdlc->bit_shift==8){
-				hdlc->state = HDLC_SEND_DATA;
-				hdlc->crc = 0xffff;
-				hdlc->hdlc_bits1 = 0;
-				hdlc->data_received = 1;
-			}
-			break;
-		case HDLC_SEND_FIRST_FLAG:
-			hdlc->data_received = 1;
-			if(hdlc->data_bits==8){
-				hdlc->state = HDLC_SEND_DATA;
-				hdlc->crc = 0xffff;
-				hdlc->hdlc_bits1 = 0;
-				break;
-			}
-			hdlc->cbin <<= 1;
-			hdlc->data_bits++;
-			if(hdlc->shift_reg & 0x01)
-				hdlc->cbin++;
-			hdlc->shift_reg >>= 1;
-			hdlc->bit_shift--;
-			if(hdlc->bit_shift==0){
-				hdlc->state = HDLC_SEND_DATA;
-				hdlc->crc = 0xffff;
-				hdlc->hdlc_bits1 = 0;
-			}
-			break;
-		case HDLC_SEND_DATA:
-			hdlc->cbin <<= 1;
-			hdlc->data_bits++;
-			if(hdlc->hdlc_bits1 == 5){
-				hdlc->hdlc_bits1 = 0;
-				break;
-			}
-			if(hdlc->bit_shift==8){
-				hdlc->crc = crc_ccitt_byte(hdlc->crc, hdlc->shift_reg);
-			}
-			if(hdlc->shift_reg & 0x01){
-				hdlc->hdlc_bits1++;
-				hdlc->cbin++;
-				hdlc->shift_reg >>= 1;
-				hdlc->bit_shift--;
-			} else {
-				hdlc->hdlc_bits1 = 0;
-				hdlc->shift_reg >>= 1;
-				hdlc->bit_shift--;
-			}
-			break;
-		case HDLC_SEND_CRC1:
-			hdlc->cbin <<= 1;
-			hdlc->data_bits++;
-			if(hdlc->hdlc_bits1 == 5){
-				hdlc->hdlc_bits1 = 0;
-				break;
-			}
-			if(hdlc->shift_reg & 0x01){
-				hdlc->hdlc_bits1++;
-				hdlc->cbin++;
-				hdlc->shift_reg >>= 1;
-				hdlc->bit_shift--;
-			} else {
-				hdlc->hdlc_bits1 = 0;
-				hdlc->shift_reg >>= 1;
-				hdlc->bit_shift--;
-			}
-			if(hdlc->bit_shift==0){
-				hdlc->shift_reg = (hdlc->crc >> 8);
-				hdlc->state = HDLC_SEND_CRC2;
-				hdlc->bit_shift = 8;
-			}
-			break;
-		case HDLC_SEND_CRC2:
-			hdlc->cbin <<= 1;
-			hdlc->data_bits++;
-			if(hdlc->hdlc_bits1 == 5){
-				hdlc->hdlc_bits1 = 0;
-				break;
-			}
-			if(hdlc->shift_reg & 0x01){
-				hdlc->hdlc_bits1++;
-				hdlc->cbin++;
-				hdlc->shift_reg >>= 1;
-				hdlc->bit_shift--;
-			} else {
-				hdlc->hdlc_bits1 = 0;
-				hdlc->shift_reg >>= 1;
-				hdlc->bit_shift--;
-			}
-			if(hdlc->bit_shift==0){
-				hdlc->shift_reg = 0x7e;
-				hdlc->state = HDLC_SEND_CLOSING_FLAG;
-				hdlc->bit_shift = 8;
-			}
-			break;
-		case HDLC_SEND_CLOSING_FLAG:
-			hdlc->cbin <<= 1;
-			hdlc->data_bits++;
-			if(hdlc->hdlc_bits1 == 5){
-				hdlc->hdlc_bits1 = 0;
-				break;
-			}
-			if(hdlc->shift_reg & 0x01){
-				hdlc->cbin++;
-			}
-			hdlc->shift_reg >>= 1;
-			hdlc->bit_shift--;
-			if(hdlc->bit_shift==0){
-				hdlc->ffvalue = xfast_flag_value[hdlc->data_bits];
-				if(hdlc->dchannel){
-					hdlc->ffvalue = 0x7e;
-					hdlc->state = HDLC_SEND_IDLE1;
-					hdlc->bit_shift = 8-hdlc->data_bits;
-					if(hdlc->bit_shift==0)
-						hdlc->state = HDLC_SEND_FAST_IDLE;
-				} else {
-					if(!hdlc->do_adapt56){
-						hdlc->state = HDLC_SEND_FAST_FLAG;
-						hdlc->data_received = 0;
-					} else {
-						hdlc->state = HDLC_SENDFLAG_B0;
-						hdlc->data_received = 0;
-					}
-					// Finished with this frame, send flags
-					if (dsize > 1) dsize = 1; 
-				}
-			}
-			break;
-		case HDLC_SEND_IDLE1:
-			hdlc->do_closing = 0;
-			hdlc->cbin <<= 1;
-			hdlc->cbin++;
-			hdlc->data_bits++;
-			hdlc->bit_shift--;
-			if(hdlc->bit_shift==0){
-				hdlc->state = HDLC_SEND_FAST_IDLE;
-				hdlc->bit_shift = 0;
-			}
-			break;
-		case HDLC_SEND_FAST_IDLE:
-			hdlc->do_closing = 0;
-			hdlc->cbin = 0xff;
-			hdlc->data_bits = 8;
-			if(hdlc->bit_shift == 8){
-				hdlc->cbin = 0x7e;
-				hdlc->state = HDLC_SEND_FIRST_FLAG;
-			} else {
-				*dst++ = hdlc->cbin;
-				hdlc->bit_shift = hdlc->data_bits = 0;
-				len++;
-				dsize = 0;
-			}
-			break;
-		default:
-			break;
-		}
-		if(hdlc->do_adapt56){
-			if(hdlc->data_bits==7){
-				hdlc->cbin <<= 1;
-				hdlc->cbin++;
-				hdlc->data_bits++;
-			}
-		}
-		if(hdlc->data_bits==8){
-			*dst++ = hdlc->cbin;
-			hdlc->data_bits = 0;
-			len++;
-			dsize--;
-		}
-	}
-	*count -= slen;
-
-	return len;
-}
-
diff --git a/drivers/isdn/hisax/st5481_hdlc.h b/drivers/isdn/hisax/st5481_hdlc.h
deleted file mode 100644
index 495432f..0000000
--- a/drivers/isdn/hisax/st5481_hdlc.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Driver for ST5481 USB ISDN modem
- *
- * Author       Frode Isaksen
- * Copyright    2001 by Frode Isaksen      <fisaksen@bewan.com>
- *              2001 by Kai Germaschewski  <kai.germaschewski@gmx.de>
- * 
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- */
-
-#ifndef __ST5481_HDLC_H__
-#define __ST5481_HDLC_H__
-
-struct hdlc_vars {
-  	int bit_shift; 
-	int hdlc_bits1;
-	int data_bits;
-	int ffbit_shift; // encoding only
-	int state;
-	int dstpos;
-
-	int data_received:1; // set if transferring data
-	int dchannel:1; // set if D channel (send idle instead of flags)
-	int do_adapt56:1; // set if 56K adaptation
-        int do_closing:1; // set if in closing phase (need to send CRC + flag
-
-	unsigned short crc;
-
-	unsigned char cbin; 
-	unsigned char shift_reg;
-	unsigned char ffvalue;
-	
-};
-
-
-/*
-  The return value from hdlc_decode is
-  the frame length, 0 if no complete frame was decoded,
-  or a negative error number
-*/
-
-#define HDLC_FRAMING_ERROR     1
-#define HDLC_CRC_ERROR         2
-#define HDLC_LENGTH_ERROR      3
-
-void 
-hdlc_rcv_init(struct hdlc_vars *hdlc, int do_adapt56);
-
-int
-hdlc_decode(struct hdlc_vars *hdlc, const unsigned char *src, int slen,int *count, 
-	    unsigned char *dst, int dsize);
-
-void 
-hdlc_out_init(struct hdlc_vars *hdlc,int is_d_channel,int do_adapt56);
-
-int 
-hdlc_encode(struct hdlc_vars *hdlc,const unsigned char *src,unsigned short slen,int *count,
-	    unsigned char *dst,int dsize);
-
-#endif
diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c
index 2369180..ab62223 100644
--- a/drivers/isdn/hisax/st5481_usb.c
+++ b/drivers/isdn/hisax/st5481_usb.c
@@ -15,6 +15,8 @@
 #include <linux/slab.h>
 #include "st5481.h"
 
+static int st5481_isoc_flatten(struct urb *urb);
+
 /* ======================================================================
  * control pipe
  */
@@ -55,9 +57,9 @@
  * Asynchronous endpoint 0 request (async version of usb_control_msg).
  * The request will be queued up in a FIFO if the endpoint is busy.
  */
-void usb_ctrl_msg(struct st5481_adapter *adapter,
-		  u8 request, u8 requesttype, u16 value, u16 index,
-		  ctrl_complete_t complete, void *context)
+static void usb_ctrl_msg(struct st5481_adapter *adapter,
+			 u8 request, u8 requesttype, u16 value, u16 index,
+			 ctrl_complete_t complete, void *context)
 {
 	struct st5481_ctrl *ctrl = &adapter->ctrl;
 	int w_index;
@@ -571,7 +573,7 @@
  * Make the transfer_buffer contiguous by
  * copying from the iso descriptors if necessary. 
  */
-int st5481_isoc_flatten(struct urb *urb)
+static int st5481_isoc_flatten(struct urb *urb)
 {
 	struct usb_iso_packet_descriptor *pipd,*pend;
 	unsigned char *src,*dst;
diff --git a/drivers/isdn/hisax/tei.c b/drivers/isdn/hisax/tei.c
index 082726d..ceb0df9 100644
--- a/drivers/isdn/hisax/tei.c
+++ b/drivers/isdn/hisax/tei.c
@@ -74,7 +74,7 @@
 	"EV_T202",
 };
 
-unsigned int
+static unsigned int
 random_ri(void)
 {
 	unsigned int x;
diff --git a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c
index ef8984c..a2b1816 100644
--- a/drivers/isdn/hisax/teleint.c
+++ b/drivers/isdn/hisax/teleint.c
@@ -18,7 +18,7 @@
 
 extern const char *CardType[];
 
-const char *TeleInt_revision = "$Revision: 1.16.2.5 $";
+static const char *TeleInt_revision = "$Revision: 1.16.2.5 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -203,7 +203,7 @@
 	add_timer(&cs->hw.hfc.timer);
 }
 
-void
+static void
 release_io_TeleInt(struct IsdnCardState *cs)
 {
 	del_timer(&cs->hw.hfc.timer);
diff --git a/drivers/isdn/hisax/teles0.c b/drivers/isdn/hisax/teles0.c
index 5ec5ec3..2b7df8f 100644
--- a/drivers/isdn/hisax/teles0.c
+++ b/drivers/isdn/hisax/teles0.c
@@ -23,7 +23,7 @@
 
 extern const char *CardType[];
 
-const char *teles0_revision = "$Revision: 2.15.2.4 $";
+static const char *teles0_revision = "$Revision: 2.15.2.4 $";
 
 #define TELES_IOMEM_SIZE	0x400
 #define byteout(addr,val) outb(val,addr)
@@ -183,7 +183,7 @@
 	return IRQ_HANDLED;
 }
 
-void
+static void
 release_io_teles0(struct IsdnCardState *cs)
 {
 	if (cs->hw.teles0.cfg_reg)
diff --git a/drivers/isdn/hisax/teles3.c b/drivers/isdn/hisax/teles3.c
index c5b1f65..adeaad6 100644
--- a/drivers/isdn/hisax/teles3.c
+++ b/drivers/isdn/hisax/teles3.c
@@ -21,7 +21,7 @@
 #include "isdnl1.h"
 
 extern const char *CardType[];
-const char *teles3_revision = "$Revision: 2.19.2.4 $";
+static const char *teles3_revision = "$Revision: 2.19.2.4 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -154,7 +154,7 @@
 		release_region(cs->hw.teles3.hscx[1] + 32, 32);
 }
 
-void
+static void
 release_io_teles3(struct IsdnCardState *cs)
 {
 	if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
diff --git a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c
index 0661c6c..e2bb4fd 100644
--- a/drivers/isdn/hisax/telespci.c
+++ b/drivers/isdn/hisax/telespci.c
@@ -21,7 +21,7 @@
 #include <linux/pci.h>
 
 extern const char *CardType[];
-const char *telespci_revision = "$Revision: 2.23.2.3 $";
+static const char *telespci_revision = "$Revision: 2.23.2.3 $";
 
 #define ZORAN_PO_RQ_PEN	0x02000000
 #define ZORAN_PO_WR	0x00800000
@@ -257,7 +257,7 @@
 	return IRQ_HANDLED;
 }
 
-void
+static void
 release_io_telespci(struct IsdnCardState *cs)
 {
 	iounmap(cs->hw.teles0.membase);
diff --git a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c
index d2b6b8e..7baf8e4 100644
--- a/drivers/isdn/hisax/w6692.c
+++ b/drivers/isdn/hisax/w6692.c
@@ -41,7 +41,7 @@
 
 extern const char *CardType[];
 
-const char *w6692_revision = "$Revision: 1.18.2.4 $";
+static const char *w6692_revision = "$Revision: 1.18.2.4 $";
 
 #define DBUSY_TIMER_VALUE 80
 
@@ -880,7 +880,7 @@
 	return (0);
 }
 
-void resetW6692(struct IsdnCardState *cs)
+static void resetW6692(struct IsdnCardState *cs)
 {
 	cs->writeW6692(cs, W_D_CTL, W_D_CTL_SRST);
 	mdelay(10);
@@ -902,7 +902,7 @@
 	}
 }
 
-void __init initW6692(struct IsdnCardState *cs, int part)
+static void __init initW6692(struct IsdnCardState *cs, int part)
 {
 	if (part & 1) {
 		cs->setstack_d = setstack_W6692;
diff --git a/drivers/isdn/i4l/isdn_audio.c b/drivers/isdn/i4l/isdn_audio.c
index 5350836..2cc56d6 100644
--- a/drivers/isdn/i4l/isdn_audio.c
+++ b/drivers/isdn/i4l/isdn_audio.c
@@ -392,16 +392,6 @@
 }
 
 int
-isdn_audio_2adpcm_flush(adpcm_state * s, unsigned char *out)
-{
-	int olen = 0;
-
-	if (s->nleft)
-		isdn_audio_put_bits(0, 8 - s->nleft, s, &out, &olen);
-	return olen;
-}
-
-int
 isdn_audio_xlaw2adpcm(adpcm_state * s, int fmt, unsigned char *in,
 		      unsigned char *out, int len)
 {
diff --git a/drivers/isdn/i4l/isdn_audio.h b/drivers/isdn/i4l/isdn_audio.h
index 5a977b2..013c358 100644
--- a/drivers/isdn/i4l/isdn_audio.h
+++ b/drivers/isdn/i4l/isdn_audio.h
@@ -35,7 +35,6 @@
 extern adpcm_state *isdn_audio_adpcm_init(adpcm_state *, int);
 extern int isdn_audio_adpcm2xlaw(adpcm_state *, int, unsigned char *, unsigned char *, int);
 extern int isdn_audio_xlaw2adpcm(adpcm_state *, int, unsigned char *, unsigned char *, int);
-extern int isdn_audio_2adpcm_flush(adpcm_state * s, unsigned char *out);
 extern void isdn_audio_calc_dtmf(modem_info *, unsigned char *, int, int);
 extern void isdn_audio_eval_dtmf(modem_info *);
 dtmf_state *isdn_audio_dtmf_init(dtmf_state *);
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index c406df6..eebcb0b 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -67,7 +67,7 @@
 static int isdn_writebuf_stub(int, int, const u_char __user *, int);
 static void set_global_features(void);
 static int isdn_wildmat(char *s, char *p);
-
+static int isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding);
 
 static inline void
 isdn_lock_driver(isdn_driver_t *drv)
@@ -388,7 +388,7 @@
  */
 #include <linux/isdn/capicmd.h>
 
-int
+static int
 isdn_capi_rec_hl_msg(capi_msg *cm) {
 	
 	int di;
@@ -1923,7 +1923,7 @@
 	return ret;
 }
 
-int
+static int
 isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding)
 {
 	int j, k, m;
diff --git a/drivers/isdn/i4l/isdn_common.h b/drivers/isdn/i4l/isdn_common.h
index 808135c..e27e9c3 100644
--- a/drivers/isdn/i4l/isdn_common.h
+++ b/drivers/isdn/i4l/isdn_common.h
@@ -41,7 +41,6 @@
 extern int  isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
 extern int  register_isdn(isdn_if * i);
 extern int  isdn_msncmp( const char *,  const char *);
-extern int  isdn_add_channels(isdn_driver_t *, int, int, int);
 #if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
 extern void isdn_dumppkt(char *, u_char *, int, int);
 #endif
diff --git a/drivers/isdn/i4l/isdn_concap.c b/drivers/isdn/i4l/isdn_concap.c
index 83a4f53..0193b6f 100644
--- a/drivers/isdn/i4l/isdn_concap.c
+++ b/drivers/isdn/i4l/isdn_concap.c
@@ -39,7 +39,7 @@
    */
 
 
-int isdn_concap_dl_data_req(struct concap_proto *concap, struct sk_buff *skb)
+static int isdn_concap_dl_data_req(struct concap_proto *concap, struct sk_buff *skb)
 {
 	struct net_device *ndev = concap -> net_dev;
 	isdn_net_dev *nd = ((isdn_net_local *) ndev->priv)->netdev;
@@ -58,7 +58,7 @@
 }
 
 
-int isdn_concap_dl_connect_req(struct concap_proto *concap)
+static int isdn_concap_dl_connect_req(struct concap_proto *concap)
 {
 	struct net_device *ndev = concap -> net_dev;
 	isdn_net_local *lp = (isdn_net_local *) ndev->priv;
@@ -71,7 +71,7 @@
 	return ret;
 }
 
-int isdn_concap_dl_disconn_req(struct concap_proto *concap)
+static int isdn_concap_dl_disconn_req(struct concap_proto *concap)
 {
 	IX25DEBUG( "isdn_concap_dl_disconn_req: %s \n", concap -> net_dev -> name);
 
@@ -85,15 +85,6 @@
 	&isdn_concap_dl_disconn_req
 };
 
-struct concap_device_ops isdn_concap_demand_dial_dops = {
-	NULL, /* set this first entry to something like &isdn_net_start_xmit,
-		 but the entry part of the current isdn_net_start_xmit must be
-		 separated first. */
-	/* no connection control for demand dial semantics */
-	NULL,
-	NULL,
-};
-
 /* The following should better go into a dedicated source file such that
    this sourcefile does not need to include any protocol specific header
    files. For now:
diff --git a/drivers/isdn/i4l/isdn_concap.h b/drivers/isdn/i4l/isdn_concap.h
index 306eb18..6ac7e04 100644
--- a/drivers/isdn/i4l/isdn_concap.h
+++ b/drivers/isdn/i4l/isdn_concap.h
@@ -8,7 +8,6 @@
  */
 
 extern struct concap_device_ops isdn_concap_reliable_dl_dops;
-extern struct concap_device_ops isdn_concap_demand_dial_dops;
 extern struct concap_proto * isdn_concap_new( int );
 
 
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index e2b790e..f30e8e6 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -176,7 +176,7 @@
 
 /* Prototypes */
 
-int isdn_net_force_dial_lp(isdn_net_local *);
+static int isdn_net_force_dial_lp(isdn_net_local *);
 static int isdn_net_start_xmit(struct sk_buff *, struct net_device *);
 
 static void isdn_net_ciscohdlck_connected(isdn_net_local *lp);
@@ -312,7 +312,7 @@
  * Since this function is called every second, simply reset the
  * byte-counter of the interface after copying it to the cps-variable.
  */
-unsigned long last_jiffies = -HZ;
+static unsigned long last_jiffies = -HZ;
 
 void
 isdn_net_autohup(void)
@@ -1131,7 +1131,7 @@
 }
 
 
-void isdn_net_tx_timeout(struct net_device * ndev)
+static void isdn_net_tx_timeout(struct net_device * ndev)
 {
 	isdn_net_local *lp = (isdn_net_local *) ndev->priv;
 
@@ -1424,7 +1424,7 @@
 }
 
 /* cisco hdlck device private ioctls */
-int
+static int
 isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	isdn_net_local *lp = (isdn_net_local *) dev->priv;
@@ -2461,7 +2461,7 @@
  * This is called from the userlevel-routine below or
  * from isdn_net_start_xmit().
  */
-int
+static int
 isdn_net_force_dial_lp(isdn_net_local * lp)
 {
 	if ((!(lp->flags & ISDN_NET_CONNECTED)) && !lp->dialstate) {
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index e21007e..ad5aa38 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -273,7 +273,7 @@
 	return 1;
 }
 
-void
+static void
 isdn_tty_cleanup_xmit(modem_info * info)
 {
 	skb_queue_purge(&info->xmit_queue);
@@ -560,7 +560,7 @@
 /*
  * return the usage calculated by si and layer 2 protocol
  */
-int
+static int
 isdn_calc_usage(int si, int l2)
 {
 	int usg = ISDN_USAGE_MODEM;
diff --git a/drivers/isdn/i4l/isdn_tty.h b/drivers/isdn/i4l/isdn_tty.h
index 2423a7f..9f0fa95 100644
--- a/drivers/isdn/i4l/isdn_tty.h
+++ b/drivers/isdn/i4l/isdn_tty.h
@@ -109,7 +109,6 @@
 extern void isdn_tty_exit(void);
 extern void isdn_tty_readmodem(void);
 extern int  isdn_tty_find_icall(int, int, setup_parm *);
-extern void isdn_tty_cleanup_xmit(modem_info *);
 extern int  isdn_tty_stat_callback(int, isdn_ctrl *);
 extern int  isdn_tty_rcv_skb(int, int, int, struct sk_buff *);
 extern int  isdn_tty_capi_facility(capi_msg *cm); 
diff --git a/drivers/isdn/i4l/isdn_ttyfax.c b/drivers/isdn/i4l/isdn_ttyfax.c
index ce2c3ef..a943d07 100644
--- a/drivers/isdn/i4l/isdn_ttyfax.c
+++ b/drivers/isdn/i4l/isdn_ttyfax.c
@@ -148,7 +148,7 @@
 	}
 }
 
-int
+static int
 isdn_tty_fax_command1(modem_info * info, isdn_ctrl * c)
 {
 	static char *msg[] =
@@ -316,7 +316,7 @@
  * Parse AT+F.. FAX class 1 commands
  */
 
-int
+static int
 isdn_tty_cmd_FCLASS1(char **p, modem_info * info)
 {
 	static char *cmd[] =
@@ -408,7 +408,7 @@
  * Parse AT+F.. FAX class 2 commands
  */
 
-int
+static int
 isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
 {
 	atemu *m = &info->emu;
diff --git a/drivers/isdn/i4l/isdn_x25iface.c b/drivers/isdn/i4l/isdn_x25iface.c
index 4ab7600..edf14a2 100644
--- a/drivers/isdn/i4l/isdn_x25iface.c
+++ b/drivers/isdn/i4l/isdn_x25iface.c
@@ -40,15 +40,15 @@
 
 
 /* is now in header file (extern): struct concap_proto * isdn_x25iface_proto_new(void); */
-void isdn_x25iface_proto_del( struct concap_proto * );
-int isdn_x25iface_proto_close( struct concap_proto * );
-int isdn_x25iface_proto_restart( struct concap_proto *,
-				 struct net_device *,
-				 struct concap_device_ops *);
-int isdn_x25iface_xmit( struct concap_proto *, struct sk_buff * );
-int isdn_x25iface_receive( struct concap_proto *, struct sk_buff * );
-int isdn_x25iface_connect_ind( struct concap_proto * );
-int isdn_x25iface_disconn_ind( struct concap_proto * );
+static void isdn_x25iface_proto_del( struct concap_proto * );
+static int isdn_x25iface_proto_close( struct concap_proto * );
+static int isdn_x25iface_proto_restart( struct concap_proto *,
+					struct net_device *,
+					struct concap_device_ops *);
+static int isdn_x25iface_xmit( struct concap_proto *, struct sk_buff * );
+static int isdn_x25iface_receive( struct concap_proto *, struct sk_buff * );
+static int isdn_x25iface_connect_ind( struct concap_proto * );
+static int isdn_x25iface_disconn_ind( struct concap_proto * );
 
 
 static struct concap_proto_ops ix25_pops = {
@@ -102,7 +102,7 @@
 
 /* close the x25iface encapsulation protocol 
  */
-int isdn_x25iface_proto_close(struct concap_proto *cprot){
+static int isdn_x25iface_proto_close(struct concap_proto *cprot){
 
 	ix25_pdata_t *tmp;
         int ret = 0;
@@ -129,7 +129,7 @@
 
 /* Delete the x25iface encapsulation protocol instance
  */
-void isdn_x25iface_proto_del(struct concap_proto *cprot){
+static void isdn_x25iface_proto_del(struct concap_proto *cprot){
 
 	ix25_pdata_t * tmp;
  
@@ -158,9 +158,9 @@
 
 /* (re-)initialize the data structures for x25iface encapsulation
  */
-int isdn_x25iface_proto_restart(struct concap_proto *cprot,
-				struct net_device *ndev, 
-				struct concap_device_ops *dops)
+static int isdn_x25iface_proto_restart(struct concap_proto *cprot,
+					struct net_device *ndev,
+					struct concap_device_ops *dops)
 {
 	ix25_pdata_t * pda = cprot -> proto_data ;
 	ulong flags;
@@ -187,7 +187,7 @@
 
 /* deliver a dl_data frame received from i4l HL driver to the network layer 
  */
-int isdn_x25iface_receive(struct concap_proto *cprot, struct sk_buff *skb)
+static int isdn_x25iface_receive(struct concap_proto *cprot, struct sk_buff *skb)
 {
   	IX25DEBUG( "isdn_x25iface_receive %s \n", MY_DEVNAME(cprot->net_dev) );
 	if ( ( (ix25_pdata_t*) (cprot->proto_data) ) 
@@ -206,7 +206,7 @@
 
 /* a connection set up is indicated by lower layer 
  */
-int isdn_x25iface_connect_ind(struct concap_proto *cprot)
+static int isdn_x25iface_connect_ind(struct concap_proto *cprot)
 {
 	struct sk_buff * skb = dev_alloc_skb(1);
 	enum wan_states *state_p 
@@ -235,7 +235,7 @@
 	
 /* a disconnect is indicated by lower layer 
  */
-int isdn_x25iface_disconn_ind(struct concap_proto *cprot)
+static int isdn_x25iface_disconn_ind(struct concap_proto *cprot)
 {
 	struct sk_buff *skb;
 	enum wan_states *state_p 
@@ -264,7 +264,7 @@
 /* process a frame handed over to us from linux network layer. First byte
    semantics as defined in Documentation/networking/x25-iface.txt
    */
-int isdn_x25iface_xmit(struct concap_proto *cprot, struct sk_buff *skb)
+static int isdn_x25iface_xmit(struct concap_proto *cprot, struct sk_buff *skb)
 {
 	unsigned char firstbyte = skb->data[0];
 	enum wan_states *state = &((ix25_pdata_t*)cprot->proto_data)->state;
diff --git a/drivers/isdn/pcbit/callbacks.c b/drivers/isdn/pcbit/callbacks.c
index 692ec72..f151f36 100644
--- a/drivers/isdn/pcbit/callbacks.c
+++ b/drivers/isdn/pcbit/callbacks.c
@@ -125,23 +125,6 @@
 
 
 /*
- * Disconnect received (actually RELEASE COMPLETE) 
- * This means we were not able to establish connection with remote
- * Inform the big boss above
- */
-void cb_out_3(struct pcbit_dev * dev, struct pcbit_chan* chan,
-	      struct callb_data *data) 
-{
-        isdn_ctrl ictl;
-
-        ictl.command = ISDN_STAT_DHUP;
-        ictl.driver=dev->id;
-        ictl.arg=chan->id;
-        dev->dev_if->statcallb(&ictl);
-}
-
-
-/*
  * Incoming call received
  * inform user
  */
diff --git a/drivers/isdn/pcbit/callbacks.h b/drivers/isdn/pcbit/callbacks.h
index f510dc5..17aa0f5 100644
--- a/drivers/isdn/pcbit/callbacks.h
+++ b/drivers/isdn/pcbit/callbacks.h
@@ -19,9 +19,6 @@
 extern void cb_out_2(struct pcbit_dev * dev, struct pcbit_chan* chan, 
 		     struct callb_data *data);
 
-extern void cb_out_3(struct pcbit_dev * dev, struct pcbit_chan* chan, 
-		     struct callb_data *data);
-
 extern void cb_in_1(struct pcbit_dev * dev, struct pcbit_chan* chan, 
 		    struct callb_data *data);
 extern void cb_in_2(struct pcbit_dev * dev, struct pcbit_chan* chan, 
diff --git a/drivers/isdn/pcbit/capi.c b/drivers/isdn/pcbit/capi.c
index 29eb03a..bef321d0 100644
--- a/drivers/isdn/pcbit/capi.c
+++ b/drivers/isdn/pcbit/capi.c
@@ -627,16 +627,6 @@
         return 0;
 }
 
-int capi_decode_disc_conf(struct pcbit_chan *chan, struct sk_buff *skb)
-{
-        ushort errcode;
-
-        errcode = *((ushort*) skb->data);
-        skb_pull(skb, 2);
-
-        return errcode;                
-}
-
 #ifdef DEBUG
 int capi_decode_debug_188(u_char *hdr, ushort hdrlen)
 {
diff --git a/drivers/isdn/pcbit/capi.h b/drivers/isdn/pcbit/capi.h
index 18e6aa3..df8e73c 100644
--- a/drivers/isdn/pcbit/capi.h
+++ b/drivers/isdn/pcbit/capi.h
@@ -54,7 +54,6 @@
 
 /* Connection Termination */
 extern int capi_disc_req(ushort callref, struct sk_buff **skb, u_char cause);
-extern int capi_decode_disc_conf(struct pcbit_chan *chan, struct sk_buff *skb);
 
 extern int capi_decode_disc_ind(struct pcbit_chan *chan, struct sk_buff *skb);
 extern int capi_disc_resp(struct pcbit_chan *chan, struct sk_buff **skb);
diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c
index e98f9c4..5de861f 100644
--- a/drivers/isdn/pcbit/drv.c
+++ b/drivers/isdn/pcbit/drv.c
@@ -56,10 +56,10 @@
  * prototypes
  */
 
-int pcbit_command(isdn_ctrl* ctl);
-int pcbit_stat(u_char __user * buf, int len, int, int);
-int pcbit_xmit(int driver, int chan, int ack, struct sk_buff *skb);
-int pcbit_writecmd(const u_char __user *, int, int, int);
+static int pcbit_command(isdn_ctrl* ctl);
+static int pcbit_stat(u_char __user * buf, int len, int, int);
+static int pcbit_xmit(int driver, int chan, int ack, struct sk_buff *skb);
+static int pcbit_writecmd(const u_char __user *, int, int, int);
 
 static int set_protocol_running(struct pcbit_dev * dev);
 
@@ -238,7 +238,7 @@
 }
 #endif
 
-int pcbit_command(isdn_ctrl* ctl)
+static int pcbit_command(isdn_ctrl* ctl)
 {
 	struct pcbit_dev  *dev;
 	struct pcbit_chan *chan;
@@ -330,7 +330,7 @@
 }
 #endif
 
-int pcbit_xmit(int driver, int chnum, int ack, struct sk_buff *skb)
+static int pcbit_xmit(int driver, int chnum, int ack, struct sk_buff *skb)
 {
 	ushort hdrlen;
 	int refnum, len;
@@ -389,7 +389,7 @@
 	return len;
 }
 
-int pcbit_writecmd(const u_char __user *buf, int len, int driver, int channel)
+static int pcbit_writecmd(const u_char __user *buf, int len, int driver, int channel)
 {
 	struct pcbit_dev * dev;
 	int i, j;
@@ -713,7 +713,7 @@
 static int stat_st = 0;
 static int stat_end = 0;
 
-int pcbit_stat(u_char __user *buf, int len, int driver, int channel)
+static int pcbit_stat(u_char __user *buf, int len, int driver, int channel)
 {
 	int stat_count;
 	stat_count = stat_end - stat_st;
diff --git a/drivers/isdn/sc/Makefile b/drivers/isdn/sc/Makefile
index 9cc474c..0f2b7d6 100644
--- a/drivers/isdn/sc/Makefile
+++ b/drivers/isdn/sc/Makefile
@@ -6,5 +6,5 @@
 
 # Multipart objects.
 
-sc-y				:= shmem.o init.o debug.o packet.o command.o event.o \
+sc-y				:= shmem.o init.o packet.o command.o event.o \
 		   		   ioctl.o interrupt.o message.o timer.o	
diff --git a/drivers/isdn/sc/command.c b/drivers/isdn/sc/command.c
index b2c4eac..19f2fcf 100644
--- a/drivers/isdn/sc/command.c
+++ b/drivers/isdn/sc/command.c
@@ -22,14 +22,14 @@
 #include "card.h"
 #include "scioc.h"
 
-int dial(int card, unsigned long channel, setup_parm setup);
-int hangup(int card, unsigned long channel);
-int answer(int card, unsigned long channel);
-int clreaz(int card, unsigned long channel);
-int seteaz(int card, unsigned long channel, char *);
-int setl2(int card, unsigned long arg);
-int setl3(int card, unsigned long arg);
-int acceptb(int card, unsigned long channel);
+static int dial(int card, unsigned long channel, setup_parm setup);
+static int hangup(int card, unsigned long channel);
+static int answer(int card, unsigned long channel);
+static int clreaz(int card, unsigned long channel);
+static int seteaz(int card, unsigned long channel, char *);
+static int setl2(int card, unsigned long arg);
+static int setl3(int card, unsigned long arg);
+static int acceptb(int card, unsigned long channel);
 
 extern int cinst;
 extern board *sc_adapter[];
@@ -148,56 +148,6 @@
 }
 
 /*
- * Confirm our ability to communicate with the board.  This test assumes no
- * other message activity is present
- */
-int loopback(int card) 
-{
-
-	int status;
-	static char testmsg[] = "Test Message";
-	RspMessage rspmsg;
-
-	if(!IS_VALID_CARD(card)) {
-		pr_debug("Invalid param: %d is not a valid card id\n", card);
-		return -ENODEV;
-	}
-
-	pr_debug("%s: Sending loopback message\n",
-		sc_adapter[card]->devicename);
-
-	/*
-	 * Send the loopback message to confirm that memory transfer is
-	 * operational
-	 */
-	status = send_and_receive(card, CMPID, cmReqType1,
-				  cmReqClass0,
-				  cmReqMsgLpbk,
-				  0,
-				  (unsigned char) strlen(testmsg),
-				  (unsigned char *)testmsg,
-				  &rspmsg, SAR_TIMEOUT);
-
-
-	if (!status) {
-		pr_debug("%s: Loopback message successfully sent\n",
-			sc_adapter[card]->devicename);
-		if(strcmp(rspmsg.msg_data.byte_array, testmsg)) {
-			pr_debug("%s: Loopback return != sent\n",
-				sc_adapter[card]->devicename);
-			return -EIO;
-		}
-		return 0;
-	}
-	else {
-		pr_debug("%s: Send loopback message failed\n",
-			sc_adapter[card]->devicename);
-		return -EIO;
-	}
-
-}
-
-/*
  * start the onboard firmware
  */
 int startproc(int card) 
@@ -222,16 +172,10 @@
 }
 
 
-int loadproc(int card, char *data) 
-{
-	return -1;
-}
-
-
 /*
  * Dials the number passed in 
  */
-int dial(int card, unsigned long channel, setup_parm setup) 
+static int dial(int card, unsigned long channel, setup_parm setup)
 {
 	int status;
 	char Phone[48];
@@ -261,7 +205,7 @@
 /*
  * Answer an incoming call 
  */
-int answer(int card, unsigned long channel) 
+static int answer(int card, unsigned long channel)
 {
 	if(!IS_VALID_CARD(card)) {
 		pr_debug("Invalid param: %d is not a valid card id\n", card);
@@ -282,7 +226,7 @@
 /*
  * Hangup up the call on specified channel
  */
-int hangup(int card, unsigned long channel) 
+static int hangup(int card, unsigned long channel)
 {
 	int status;
 
@@ -305,7 +249,7 @@
 /*
  * Set the layer 2 protocol (X.25, HDLC, Raw)
  */
-int setl2(int card, unsigned long arg) 
+static int setl2(int card, unsigned long arg)
 {
 	int status =0;
 	int protocol,channel;
@@ -340,7 +284,7 @@
 /*
  * Set the layer 3 protocol
  */
-int setl3(int card, unsigned long channel) 
+static int setl3(int card, unsigned long channel)
 {
 	int protocol = channel >> 8;
 
@@ -355,7 +299,7 @@
 	return 0;
 }
 
-int acceptb(int card, unsigned long channel)
+static int acceptb(int card, unsigned long channel)
 {
 	if(!IS_VALID_CARD(card)) {
 		pr_debug("Invalid param: %d is not a valid card id\n", card);
@@ -374,7 +318,7 @@
 	return 0;
 }
 
-int clreaz(int card, unsigned long arg)
+static int clreaz(int card, unsigned long arg)
 {
 	if(!IS_VALID_CARD(card)) {
 		pr_debug("Invalid param: %d is not a valid card id\n", card);
@@ -388,7 +332,7 @@
 	return 0;
 }
 
-int seteaz(int card, unsigned long arg, char *num)
+static int seteaz(int card, unsigned long arg, char *num)
 {
 	if(!IS_VALID_CARD(card)) {
 		pr_debug("Invalid param: %d is not a valid card id\n", card);
diff --git a/drivers/isdn/sc/debug.c b/drivers/isdn/sc/debug.c
deleted file mode 100644
index 1a992a7..0000000
--- a/drivers/isdn/sc/debug.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/* $Id: debug.c,v 1.5.6.1 2001/09/23 22:24:59 kai Exp $
- *
- * Copyright (C) 1996  SpellCaster Telecommunications Inc.
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * For more information, please contact gpl-info@spellcast.com or write:
- *
- *     SpellCaster Telecommunications Inc.
- *     5621 Finch Avenue East, Unit #3
- *     Scarborough, Ontario  Canada
- *     M1B 2T9
- *     +1 (416) 297-8565
- *     +1 (416) 297-6433 Facsimile
- */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-
-int dbg_level = 0;
-static char dbg_funcname[255];
-
-void dbg_endfunc(void)
-{
-	if (dbg_level) {
-		printk("<-- Leaving function %s\n", dbg_funcname);
-		strcpy(dbg_funcname, "");
-	}
-}
-
-void dbg_func(char *func)
-{
-	strcpy(dbg_funcname, func);
-	if(dbg_level)
-		printk("--> Entering function %s\n", dbg_funcname);
-}
-
-inline void pullphone(char *dn, char *str)
-{
-	int i = 0;
-
-	while(dn[i] != ',')
-		str[i] = dn[i], i++;
-	str[i] = 0x0;
-}
diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c
index efefede..40b0df0 100644
--- a/drivers/isdn/sc/init.c
+++ b/drivers/isdn/sc/init.c
@@ -20,9 +20,9 @@
 int cinst;
 
 static char devname[] = "scX";
-const char version[] = "2.0b1";
+static const char version[] = "2.0b1";
 
-const char *boardname[] = { "DataCommute/BRI", "DataCommute/PRI", "TeleCommute/BRI" };
+static const char *boardname[] = { "DataCommute/BRI", "DataCommute/PRI", "TeleCommute/BRI" };
 
 /* insmod set parameters */
 static unsigned int io[] = {0,0,0,0};
@@ -35,26 +35,13 @@
 module_param_array(ram, int, NULL, 0);
 module_param(do_reset, bool, 0);
 
-static int sup_irq[] = { 11, 10, 9, 5, 12, 14, 7, 3, 4, 6 };
-#define MAX_IRQS	10
-
 extern irqreturn_t interrupt_handler(int, void *, struct pt_regs *);
 extern int sndpkt(int, int, int, struct sk_buff *);
 extern int command(isdn_ctrl *);
 extern int indicate_status(int, int, ulong, char*);
 extern int reset(int);
 
-int identify_board(unsigned long, unsigned int);
-
-int irq_supported(int irq_x)
-{
-	int i;
-	for(i=0 ; i < MAX_IRQS ; i++) {
-		if(sup_irq[i] == irq_x)
-			return 1;
-	}
-	return 0;
-}
+static int identify_board(unsigned long, unsigned int);
 
 static int __init sc_init(void)
 {
@@ -454,7 +441,7 @@
 	pr_info("SpellCaster ISA ISDN Adapter Driver Unloaded.\n");
 }
 
-int identify_board(unsigned long rambase, unsigned int iobase) 
+static int identify_board(unsigned long rambase, unsigned int iobase)
 {
 	unsigned int pgport;
 	unsigned long sig;
diff --git a/drivers/isdn/sc/interrupt.c b/drivers/isdn/sc/interrupt.c
index e5e164a..8631d33 100644
--- a/drivers/isdn/sc/interrupt.c
+++ b/drivers/isdn/sc/interrupt.c
@@ -31,7 +31,7 @@
 extern int cinst;
 extern board *sc_adapter[];
 
-int get_card_from_irq(int irq)
+static int get_card_from_irq(int irq)
 {
 	int i;
 
diff --git a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c
index 1371a99..3314a5a 100644
--- a/drivers/isdn/sc/ioctl.c
+++ b/drivers/isdn/sc/ioctl.c
@@ -14,7 +14,6 @@
 
 extern int indicate_status(int, int, unsigned long, char *);
 extern int startproc(int);
-extern int loadproc(int, char *record);
 extern int reset(int);
 extern int send_and_receive(int, unsigned int, unsigned char,unsigned char,
 		unsigned char,unsigned char, 
@@ -23,7 +22,7 @@
 extern board *sc_adapter[];
 
 
-int GetStatus(int card, boardInfo *);
+static int GetStatus(int card, boardInfo *);
 
 /*
  * Process private IOCTL messages (typically from scctrl)
@@ -428,7 +427,7 @@
 	return 0;
 }
 
-int GetStatus(int card, boardInfo *bi)
+static int GetStatus(int card, boardInfo *bi)
 {
 	RspMessage rcvmsg;
 	int i, status;
diff --git a/drivers/isdn/sc/packet.c b/drivers/isdn/sc/packet.c
index 8e3fac3..f50defc 100644
--- a/drivers/isdn/sc/packet.c
+++ b/drivers/isdn/sc/packet.c
@@ -213,19 +213,3 @@
 	return 0;
 }
 
-int print_skb(int card,char *skb_p, int len){
-	int i,data;
-	pr_debug("%s: data at 0x%x len: 0x%x\n", sc_adapter[card]->devicename,
-			skb_p,len);
-	for(i=1;i<=len;i++,skb_p++){
-		data = (int) (0xff & (*skb_p));
-		pr_debug("%s: data =  0x%x", sc_adapter[card]->devicename,data);
-		if(!(i%4))
-			pr_debug(" ");
-		if(!(i%32))
-			pr_debug("\n");
-	}
-	pr_debug("\n");
-	return 0;
-}		
-
diff --git a/drivers/isdn/sc/shmem.c b/drivers/isdn/sc/shmem.c
index 7bc2dfa..2485482 100644
--- a/drivers/isdn/sc/shmem.c
+++ b/drivers/isdn/sc/shmem.c
@@ -108,6 +108,7 @@
 		sc_adapter[card]->rambase + ((unsigned long) src %0x4000), (unsigned long) dest); */
 }
 
+#if 0
 void memset_shmem(int card, void *dest, int c, size_t n)
 {
 	unsigned long flags;
@@ -141,3 +142,4 @@
 		((sc_adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80);
 	spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
 }
+#endif  /*  0  */
diff --git a/drivers/isdn/sc/timer.c b/drivers/isdn/sc/timer.c
index 710d0f4..aced19a 100644
--- a/drivers/isdn/sc/timer.c
+++ b/drivers/isdn/sc/timer.c
@@ -32,7 +32,7 @@
 /*
  * Write the proper values into the I/O ports following a reset
  */
-void setup_ports(int card)
+static void setup_ports(int card)
 {
 
 	outb((sc_adapter[card]->rambase >> 12), sc_adapter[card]->ioport[EXP_BASE]);
@@ -129,19 +129,3 @@
 		ceReqPhyStatus,0,0,NULL);
 }
 
-/*
- * When in trace mode, this callback is used to swap the working shared
- * RAM page to the trace page(s) and process all received messages. It
- * must be called often enough to get all of the messages out of RAM before
- * it loops around.
- * Trace messages are \n terminated strings.
- * We output the messages in 64 byte chunks through readstat. Each chunk
- * is scanned for a \n followed by a time stamp. If the timerstamp is older
- * than the current time, scanning stops and the page and offset are recorded
- * as the starting point the next time the trace timer is called. The final
- * step is to restore the working page and reset the timer.
- */
-void trace_timer(unsigned long data)
-{
-	/* not implemented */
-}
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index 7297c77..493e2af 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -77,7 +77,7 @@
 	NULL
 };
 
-static struct class_simple *adb_dev_class;
+static struct class *adb_dev_class;
 
 struct adb_driver *adb_controller;
 struct notifier_block *adb_client_list = NULL;
@@ -902,9 +902,8 @@
 
 	devfs_mk_cdev(MKDEV(ADB_MAJOR, 0), S_IFCHR | S_IRUSR | S_IWUSR, "adb");
 
-	adb_dev_class = class_simple_create(THIS_MODULE, "adb");
-	if (IS_ERR(adb_dev_class)) {
+	adb_dev_class = class_create(THIS_MODULE, "adb");
+	if (IS_ERR(adb_dev_class))
 		return;
-	}
-	class_simple_device_add(adb_dev_class, MKDEV(ADB_MAJOR, 0), NULL, "adb");
+	class_device_create(adb_dev_class, MKDEV(ADB_MAJOR, 0), NULL, "adb");
 }
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index d09308f..c9ca111 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -328,9 +328,7 @@
 	struct thermostat* th = arg;
 
 	while(!kthread_should_stop()) {
-		if (current->flags & PF_FREEZE)
-			refrigerator(PF_FREEZE);
-
+		try_to_freeze();
 		msleep_interruptible(2000);
 
 #ifndef DEBUG
@@ -455,21 +453,22 @@
  * pass around to the attribute functions, so we don't really have
  * choice but implement a bunch of them...
  *
+ * FIXME, it does now...
  */
 #define BUILD_SHOW_FUNC_INT(name, data)				\
-static ssize_t show_##name(struct device *dev, char *buf)	\
+static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf)	\
 {								\
 	return sprintf(buf, "%d\n", data);			\
 }
 
 #define BUILD_SHOW_FUNC_STR(name, data)				\
-static ssize_t show_##name(struct device *dev, char *buf)	\
+static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf)       \
 {								\
 	return sprintf(buf, "%s\n", data);			\
 }
 
 #define BUILD_SHOW_FUNC_FAN(name, data)				\
-static ssize_t show_##name(struct device *dev, char *buf)       \
+static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf)       \
 {								\
 	return sprintf(buf, "%d (%d rpm)\n", 			\
 		thermostat->last_speed[data],			\
@@ -478,7 +477,7 @@
 }
 
 #define BUILD_STORE_FUNC_DEG(name, data)			\
-static ssize_t store_##name(struct device *dev, const char *buf, size_t n) \
+static ssize_t store_##name(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) \
 {								\
 	int val;						\
 	int i;							\
@@ -491,7 +490,7 @@
 }
 
 #define BUILD_STORE_FUNC_INT(name, data)			\
-static ssize_t store_##name(struct device *dev, const char *buf, size_t n) \
+static ssize_t store_##name(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) \
 {								\
 	u32 val;						\
 	val = simple_strtoul(buf, NULL, 10);			\
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index 82336a5..feb4e24 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -685,7 +685,7 @@
  * the input twice... I accept patches :)
  */
 #define BUILD_SHOW_FUNC_FIX(name, data)				\
-static ssize_t show_##name(struct device *dev, char *buf)	\
+static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf)	\
 {								\
 	ssize_t r;						\
 	down(&driver_lock);					\
@@ -694,7 +694,7 @@
 	return r;						\
 }
 #define BUILD_SHOW_FUNC_INT(name, data)				\
-static ssize_t show_##name(struct device *dev, char *buf)	\
+static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf)	\
 {								\
 	return sprintf(buf, "%d", data);			\
 }
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index c153699..61400f0 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -51,8 +51,10 @@
 static int 			do_probe( struct i2c_adapter *adapter, int addr, int kind);
 
 /* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */
-static unsigned short		normal_i2c[] = { 0x49, 0x2c, I2C_CLIENT_END };
-static unsigned short		normal_i2c_range[] = { 0x48, 0x4f, 0x2c, 0x2f, I2C_CLIENT_END };
+static unsigned short		normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
+						 0x4c, 0x4d, 0x4e, 0x4f,
+						 0x2c, 0x2d, 0x2e, 0x2f,
+						 I2C_CLIENT_END };
 
 I2C_CLIENT_INSMOD;
 
@@ -107,13 +109,13 @@
 }
 
 static ssize_t
-show_cpu_temperature( struct device *dev, char *buf )
+show_cpu_temperature( struct device *dev, struct device_attribute *attr, char *buf )
 {
 	return sprintf(buf, "%d.%d\n", x.temp>>8, (x.temp & 255)*10/256 );
 }
 
 static ssize_t
-show_case_temperature( struct device *dev, char *buf )
+show_case_temperature( struct device *dev, struct device_attribute *attr, char *buf )
 {
 	return sprintf(buf, "%d.%d\n", x.casetemp>>8, (x.casetemp & 255)*10/256 );
 }
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index bb9f404..b941ee2 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -2593,6 +2593,9 @@
 	/* Restore VIA */
 	restore_via_state();
 
+	/* tweak LPJ before cpufreq is there */
+	loops_per_jiffy *= 2;
+
 	/* Restore video */
 	pmac_call_early_video_resume();
 
@@ -2613,6 +2616,9 @@
 	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);
 	pmu_wait_complete(&req);
 
+	/* Restore LPJ, cpufreq will adjust the cpu frequency */
+	loops_per_jiffy /= 2;
+
 	pmac_wakeup_devices();
 
 	return 0;
diff --git a/drivers/mca/mca-bus.c b/drivers/mca/mca-bus.c
index ff9be67..09baa43 100644
--- a/drivers/mca/mca-bus.c
+++ b/drivers/mca/mca-bus.c
@@ -69,7 +69,7 @@
 };
 EXPORT_SYMBOL (mca_bus_type);
 
-static ssize_t mca_show_pos_id(struct device *dev, char *buf)
+static ssize_t mca_show_pos_id(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	/* four digits, \n and trailing \0 */
 	struct mca_device *mca_dev = to_mca_device(dev);
@@ -81,7 +81,7 @@
 		len = sprintf(buf, "none\n");
 	return len;
 }
-static ssize_t mca_show_pos(struct device *dev, char *buf)
+static ssize_t mca_show_pos(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	/* enough for 8 two byte hex chars plus space and new line */
 	int j, len=0;
diff --git a/drivers/mca/mca-legacy.c b/drivers/mca/mca-legacy.c
index af56313..0c7bfa7 100644
--- a/drivers/mca/mca-legacy.c
+++ b/drivers/mca/mca-legacy.c
@@ -180,7 +180,6 @@
 
 	return info.mca_dev;
 }
-EXPORT_SYMBOL(mca_find_device_by_slot);
 
 /**
  *	mca_read_stored_pos - read POS register from boot data
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index 90de9c1..d3efedf 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -7,6 +7,7 @@
 dm-multipath-objs := dm-hw-handler.o dm-path-selector.o dm-mpath.o
 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 \
 		   raid6int1.o raid6int2.o raid6int4.o \
 		   raid6int8.o raid6int16.o raid6int32.o \
@@ -28,7 +29,7 @@
 obj-$(CONFIG_MD_RAID6)		+= raid6.o xor.o
 obj-$(CONFIG_MD_MULTIPATH)	+= multipath.o
 obj-$(CONFIG_MD_FAULTY)		+= faulty.o
-obj-$(CONFIG_BLK_DEV_MD)	+= md.o
+obj-$(CONFIG_BLK_DEV_MD)	+= md-mod.o
 obj-$(CONFIG_BLK_DEV_DM)	+= dm-mod.o
 obj-$(CONFIG_DM_CRYPT)		+= dm-crypt.o
 obj-$(CONFIG_DM_MULTIPATH)	+= dm-multipath.o dm-round-robin.o
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
new file mode 100644
index 0000000..95980ad
--- /dev/null
+++ b/drivers/md/bitmap.c
@@ -0,0 +1,1586 @@
+/*
+ * bitmap.c two-level bitmap (C) Peter T. Breuer (ptb@ot.uc3m.es) 2003
+ *
+ * bitmap_create  - sets up the bitmap structure
+ * bitmap_destroy - destroys the bitmap structure
+ *
+ * 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)
+ */
+
+/*
+ * Still to do:
+ *
+ * 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>
+#include <linux/version.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/timer.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+#include <linux/file.h>
+#include <linux/mount.h>
+#include <linux/buffer_head.h>
+#include <linux/raid/md.h>
+#include <linux/raid/bitmap.h>
+
+/* debug macros */
+
+#define DEBUG 0
+
+#if DEBUG
+/* these are for debugging purposes only! */
+
+/* define one and only one of these */
+#define INJECT_FAULTS_1 0 /* cause bitmap_alloc_page to fail always */
+#define INJECT_FAULTS_2 0 /* cause bitmap file to be kicked when first bit set*/
+#define INJECT_FAULTS_3 0 /* treat bitmap file as kicked at init time */
+#define INJECT_FAULTS_4 0 /* undef */
+#define INJECT_FAULTS_5 0 /* undef */
+#define INJECT_FAULTS_6 0
+
+/* if these are defined, the driver will fail! debug only */
+#define INJECT_FATAL_FAULT_1 0 /* fail kmalloc, causing bitmap_create to fail */
+#define INJECT_FATAL_FAULT_2 0 /* undef */
+#define INJECT_FATAL_FAULT_3 0 /* undef */
+#endif
+
+//#define DPRINTK PRINTK /* set this NULL to avoid verbose debug output */
+#define DPRINTK(x...) do { } while(0)
+
+#ifndef PRINTK
+#  if DEBUG > 0
+#    define PRINTK(x...) printk(KERN_DEBUG x)
+#  else
+#    define PRINTK(x...)
+#  endif
+#endif
+
+static inline char * bmname(struct bitmap *bitmap)
+{
+	return bitmap->mddev ? mdname(bitmap->mddev) : "mdX";
+}
+
+
+/*
+ * 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
+/* mempool for queueing pending writes on the bitmap file */
+static void *write_pool_alloc(unsigned int gfp_flags, void *data)
+{
+	return kmalloc(sizeof(struct page_list), gfp_flags);
+}
+
+static void write_pool_free(void *ptr, void *data)
+{
+	kfree(ptr);
+}
+
+/*
+ * just a placeholder - calls kmalloc for bitmap pages
+ */
+static unsigned char *bitmap_alloc_page(struct bitmap *bitmap)
+{
+	unsigned char *page;
+
+#if INJECT_FAULTS_1
+	page = NULL;
+#else
+	page = kmalloc(PAGE_SIZE, GFP_NOIO);
+#endif
+	if (!page)
+		printk("%s: bitmap_alloc_page FAILED\n", bmname(bitmap));
+	else
+		PRINTK("%s: bitmap_alloc_page: allocated page at %p\n",
+			bmname(bitmap), page);
+	return page;
+}
+
+/*
+ * for now just a placeholder -- just calls kfree for bitmap pages
+ */
+static void bitmap_free_page(struct bitmap *bitmap, unsigned char *page)
+{
+	PRINTK("%s: bitmap_free_page: free page %p\n", bmname(bitmap), page);
+	kfree(page);
+}
+
+/*
+ * check a page and, if necessary, allocate it (or hijack it if the alloc fails)
+ *
+ * 1) check to see if this page is allocated, if it's not then try to alloc
+ * 2) if the alloc fails, set the page's hijacked flag so we'll use the
+ *    page pointer directly as a counter
+ *
+ * if we find our page, we increment the page's refcount so that it stays
+ * allocated while we're using it
+ */
+static int bitmap_checkpage(struct bitmap *bitmap, unsigned long page, int create)
+{
+	unsigned char *mappage;
+
+	if (page >= bitmap->pages) {
+		printk(KERN_ALERT
+			"%s: invalid bitmap page request: %lu (> %lu)\n",
+			bmname(bitmap), page, bitmap->pages-1);
+		return -EINVAL;
+	}
+
+
+	if (bitmap->bp[page].hijacked) /* it's hijacked, don't try to alloc */
+		return 0;
+
+	if (bitmap->bp[page].map) /* page is already allocated, just return */
+		return 0;
+
+	if (!create)
+		return -ENOENT;
+
+	spin_unlock_irq(&bitmap->lock);
+
+	/* this page has not been allocated yet */
+
+	if ((mappage = bitmap_alloc_page(bitmap)) == NULL) {
+		PRINTK("%s: bitmap map page allocation failed, hijacking\n",
+			bmname(bitmap));
+		/* failed - set the hijacked flag so that we can use the
+		 * pointer as a counter */
+		spin_lock_irq(&bitmap->lock);
+		if (!bitmap->bp[page].map)
+			bitmap->bp[page].hijacked = 1;
+		goto out;
+	}
+
+	/* got a page */
+
+	spin_lock_irq(&bitmap->lock);
+
+	/* recheck the page */
+
+	if (bitmap->bp[page].map || bitmap->bp[page].hijacked) {
+		/* somebody beat us to getting the page */
+		bitmap_free_page(bitmap, mappage);
+		return 0;
+	}
+
+	/* no page was in place and we have one, so install it */
+
+	memset(mappage, 0, PAGE_SIZE);
+	bitmap->bp[page].map = mappage;
+	bitmap->missing_pages--;
+out:
+	return 0;
+}
+
+
+/* if page is completely empty, put it back on the free list, or dealloc it */
+/* if page was hijacked, unmark the flag so it might get alloced next time */
+/* Note: lock should be held when calling this */
+static inline void bitmap_checkfree(struct bitmap *bitmap, unsigned long page)
+{
+	char *ptr;
+
+	if (bitmap->bp[page].count) /* page is still busy */
+		return;
+
+	/* page is no longer in use, it can be released */
+
+	if (bitmap->bp[page].hijacked) { /* page was hijacked, undo this now */
+		bitmap->bp[page].hijacked = 0;
+		bitmap->bp[page].map = NULL;
+		return;
+	}
+
+	/* normal case, free the page */
+
+#if 0
+/* actually ... let's not.  We will probably need the page again exactly when
+ * memory is tight and we are flusing to disk
+ */
+	return;
+#else
+	ptr = bitmap->bp[page].map;
+	bitmap->bp[page].map = NULL;
+	bitmap->missing_pages++;
+	bitmap_free_page(bitmap, ptr);
+	return;
+#endif
+}
+
+
+/*
+ * bitmap file handling - read and write the bitmap file and its superblock
+ */
+
+/* copy the pathname of a file to a buffer */
+char *file_path(struct file *file, char *buf, int count)
+{
+	struct dentry *d;
+	struct vfsmount *v;
+
+	if (!buf)
+		return NULL;
+
+	d = file->f_dentry;
+	v = file->f_vfsmnt;
+
+	buf = d_path(d, v, buf, count);
+
+	return IS_ERR(buf) ? NULL : buf;
+}
+
+/*
+ * basic page I/O operations
+ */
+
+/* IO operations when bitmap is stored near all superblocks */
+static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long index)
+{
+	/* choose a good rdev and read the page from there */
+
+	mdk_rdev_t *rdev;
+	struct list_head *tmp;
+	struct page *page = alloc_page(GFP_KERNEL);
+	sector_t target;
+
+	if (!page)
+		return ERR_PTR(-ENOMEM);
+	do {
+		ITERATE_RDEV(mddev, rdev, tmp)
+			if (rdev->in_sync && !rdev->faulty)
+				goto found;
+		return ERR_PTR(-EIO);
+
+	found:
+		target = (rdev->sb_offset << 1) + offset + index * (PAGE_SIZE/512);
+
+	} while (!sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ));
+
+	page->index = index;
+	return page;
+}
+
+static int write_sb_page(mddev_t *mddev, long offset, struct page *page, int wait)
+{
+	mdk_rdev_t *rdev;
+	struct list_head *tmp;
+
+	ITERATE_RDEV(mddev, rdev, tmp)
+		if (rdev->in_sync && !rdev->faulty)
+			md_super_write(mddev, rdev,
+				       (rdev->sb_offset<<1) + offset
+				       + page->index * (PAGE_SIZE/512),
+				       PAGE_SIZE,
+				       page);
+
+	if (wait)
+		wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0);
+	return 0;
+}
+
+/*
+ * write out a page to a file
+ */
+static int write_page(struct bitmap *bitmap, struct page *page, int wait)
+{
+	int ret = -ENOMEM;
+
+	if (bitmap->file == NULL)
+		return write_sb_page(bitmap->mddev, bitmap->offset, page, wait);
+
+	if (wait)
+		lock_page(page);
+	else {
+		if (TestSetPageLocked(page))
+			return -EAGAIN; /* already locked */
+		if (PageWriteback(page)) {
+			unlock_page(page);
+			return -EAGAIN;
+		}
+	}
+
+	ret = page->mapping->a_ops->prepare_write(NULL, page, 0, PAGE_SIZE);
+	if (!ret)
+		ret = page->mapping->a_ops->commit_write(NULL, page, 0,
+			PAGE_SIZE);
+	if (ret) {
+		unlock_page(page);
+		return ret;
+	}
+
+	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;
+		page_cache_get(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);
+}
+
+/* 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)
+{
+	struct inode *inode = file->f_mapping->host;
+	struct page *page = NULL;
+	loff_t isize = i_size_read(inode);
+	unsigned long end_index = isize >> PAGE_CACHE_SHIFT;
+
+	PRINTK("read bitmap file (%dB @ %Lu)\n", (int)PAGE_CACHE_SIZE,
+			(unsigned long long)index << PAGE_CACHE_SHIFT);
+
+	page = read_cache_page(inode->i_mapping, index,
+			(filler_t *)inode->i_mapping->a_ops->readpage, file);
+	if (IS_ERR(page))
+		goto out;
+	wait_on_page_locked(page);
+	if (!PageUptodate(page) || PageError(page)) {
+		page_cache_release(page);
+		page = ERR_PTR(-EIO);
+		goto out;
+	}
+
+	if (index > end_index) /* we have read beyond EOF */
+		*bytes_read = 0;
+	else if (index == end_index) /* possible short read */
+		*bytes_read = isize & ~PAGE_CACHE_MASK;
+	else
+		*bytes_read = PAGE_CACHE_SIZE; /* got a full page */
+out:
+	if (IS_ERR(page))
+		printk(KERN_ALERT "md: bitmap read error: (%dB @ %Lu): %ld\n",
+			(int)PAGE_CACHE_SIZE,
+			(unsigned long long)index << PAGE_CACHE_SHIFT,
+			PTR_ERR(page));
+	return page;
+}
+
+/*
+ * bitmap file superblock operations
+ */
+
+/* update the event counter and sync the superblock to disk */
+int bitmap_update_sb(struct bitmap *bitmap)
+{
+	bitmap_super_t *sb;
+	unsigned long flags;
+
+	if (!bitmap || !bitmap->mddev) /* no bitmap for this array */
+		return 0;
+	spin_lock_irqsave(&bitmap->lock, flags);
+	if (!bitmap->sb_page) { /* no superblock */
+		spin_unlock_irqrestore(&bitmap->lock, flags);
+		return 0;
+	}
+	spin_unlock_irqrestore(&bitmap->lock, flags);
+	sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+	sb->events = cpu_to_le64(bitmap->mddev->events);
+	if (!bitmap->mddev->degraded)
+		sb->events_cleared = cpu_to_le64(bitmap->mddev->events);
+	kunmap(bitmap->sb_page);
+	return write_page(bitmap, bitmap->sb_page, 1);
+}
+
+/* print out the bitmap file superblock */
+void bitmap_print_sb(struct bitmap *bitmap)
+{
+	bitmap_super_t *sb;
+
+	if (!bitmap || !bitmap->sb_page)
+		return;
+	sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+	printk(KERN_DEBUG "%s: bitmap file superblock:\n", bmname(bitmap));
+	printk(KERN_DEBUG "         magic: %08x\n", le32_to_cpu(sb->magic));
+	printk(KERN_DEBUG "       version: %d\n", le32_to_cpu(sb->version));
+	printk(KERN_DEBUG "          uuid: %08x.%08x.%08x.%08x\n",
+					*(__u32 *)(sb->uuid+0),
+					*(__u32 *)(sb->uuid+4),
+					*(__u32 *)(sb->uuid+8),
+					*(__u32 *)(sb->uuid+12));
+	printk(KERN_DEBUG "        events: %llu\n",
+			(unsigned long long) le64_to_cpu(sb->events));
+	printk(KERN_DEBUG "events cleared: %llu\n",
+			(unsigned long long) le64_to_cpu(sb->events_cleared));
+	printk(KERN_DEBUG "         state: %08x\n", le32_to_cpu(sb->state));
+	printk(KERN_DEBUG "     chunksize: %d B\n", le32_to_cpu(sb->chunksize));
+	printk(KERN_DEBUG "  daemon sleep: %ds\n", le32_to_cpu(sb->daemon_sleep));
+	printk(KERN_DEBUG "     sync size: %llu KB\n",
+			(unsigned long long)le64_to_cpu(sb->sync_size)/2);
+	kunmap(bitmap->sb_page);
+}
+
+/* read the superblock from the bitmap file and initialize some bitmap fields */
+static int bitmap_read_sb(struct bitmap *bitmap)
+{
+	char *reason = NULL;
+	bitmap_super_t *sb;
+	unsigned long chunksize, daemon_sleep;
+	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);
+	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);
+		bitmap->sb_page = NULL;
+		return err;
+	}
+
+	sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+
+	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);
+
+	/* verify that the bitmap-specific fields are valid */
+	if (sb->magic != cpu_to_le32(BITMAP_MAGIC))
+		reason = "bad magic";
+	else if (sb->version != cpu_to_le32(BITMAP_MAJOR))
+		reason = "unrecognized superblock version";
+	else if (chunksize < 512 || chunksize > (1024 * 1024 * 4))
+		reason = "bitmap chunksize out of range (512B - 4MB)";
+	else if ((1 << ffz(~chunksize)) != chunksize)
+		reason = "bitmap chunksize not a power of 2";
+	else if (daemon_sleep < 1 || daemon_sleep > 15)
+		reason = "daemon sleep period out of range";
+	if (reason) {
+		printk(KERN_INFO "%s: invalid bitmap file superblock: %s\n",
+			bmname(bitmap), reason);
+		goto out;
+	}
+
+	/* keep the array size field of the bitmap superblock up to date */
+	sb->sync_size = cpu_to_le64(bitmap->mddev->resync_max_sectors);
+
+	if (!bitmap->mddev->persistent)
+		goto success;
+
+	/*
+	 * if we have a persistent array superblock, compare the
+	 * bitmap's UUID and event counter to the mddev's
+	 */
+	if (memcmp(sb->uuid, bitmap->mddev->uuid, 16)) {
+		printk(KERN_INFO "%s: bitmap superblock UUID mismatch\n",
+			bmname(bitmap));
+		goto out;
+	}
+	events = le64_to_cpu(sb->events);
+	if (events < bitmap->mddev->events) {
+		printk(KERN_INFO "%s: bitmap file is out of date (%llu < %llu) "
+			"-- forcing full recovery\n", bmname(bitmap), events,
+			(unsigned long long) bitmap->mddev->events);
+		sb->state |= BITMAP_STALE;
+	}
+success:
+	/* assign fields using values from superblock */
+	bitmap->chunksize = chunksize;
+	bitmap->daemon_sleep = daemon_sleep;
+	bitmap->flags |= sb->state;
+	bitmap->events_cleared = le64_to_cpu(sb->events_cleared);
+	err = 0;
+out:
+	kunmap(bitmap->sb_page);
+	if (err)
+		bitmap_print_sb(bitmap);
+	return err;
+}
+
+enum bitmap_mask_op {
+	MASK_SET,
+	MASK_UNSET
+};
+
+/* record the state of the bitmap in the superblock */
+static void bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
+				enum bitmap_mask_op op)
+{
+	bitmap_super_t *sb;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bitmap->lock, flags);
+	if (!bitmap || !bitmap->sb_page) { /* can't set the state */
+		spin_unlock_irqrestore(&bitmap->lock, flags);
+		return;
+	}
+	page_cache_get(bitmap->sb_page);
+	spin_unlock_irqrestore(&bitmap->lock, flags);
+	sb = (bitmap_super_t *)kmap(bitmap->sb_page);
+	switch (op) {
+		case MASK_SET: sb->state |= bits;
+				break;
+		case MASK_UNSET: sb->state &= ~bits;
+				break;
+		default: BUG();
+	}
+	kunmap(bitmap->sb_page);
+	page_cache_release(bitmap->sb_page);
+}
+
+/*
+ * general bitmap file operations
+ */
+
+/* calculate the index of the page that contains this bit */
+static inline unsigned long file_page_index(unsigned long chunk)
+{
+	return CHUNK_BIT_OFFSET(chunk) >> PAGE_BIT_SHIFT;
+}
+
+/* calculate the (bit) offset of this bit within a page */
+static inline unsigned long file_page_offset(unsigned long chunk)
+{
+	return CHUNK_BIT_OFFSET(chunk) & (PAGE_BITS - 1);
+}
+
+/*
+ * return a pointer to the page in the filemap that contains the given bit
+ *
+ * this lookup is complicated by the fact that the bitmap sb might be exactly
+ * 1 page (e.g., x86) or less than 1 page -- so the bitmap might start on page
+ * 0 or page 1
+ */
+static inline struct page *filemap_get_page(struct bitmap *bitmap,
+					unsigned long chunk)
+{
+	return bitmap->filemap[file_page_index(chunk) - file_page_index(0)];
+}
+
+
+static void bitmap_file_unmap(struct bitmap *bitmap)
+{
+	struct page **map, *sb_page;
+	unsigned long *attr;
+	int pages;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bitmap->lock, flags);
+	map = bitmap->filemap;
+	bitmap->filemap = NULL;
+	attr = bitmap->filemap_attr;
+	bitmap->filemap_attr = NULL;
+	pages = bitmap->file_pages;
+	bitmap->file_pages = 0;
+	sb_page = bitmap->sb_page;
+	bitmap->sb_page = NULL;
+	spin_unlock_irqrestore(&bitmap->lock, flags);
+
+	while (pages--)
+		if (map[pages]->index != 0) /* 0 is sb_page, release it below */
+			page_cache_release(map[pages]);
+	kfree(map);
+	kfree(attr);
+
+	if (sb_page)
+		page_cache_release(sb_page);
+}
+
+static void bitmap_stop_daemons(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 */
+		page_cache_release(item->page);
+		mempool_free(item, bitmap->write_pool);
+	}
+
+	wake_up(&bitmap->write_wait);
+}
+
+static void bitmap_file_put(struct bitmap *bitmap)
+{
+	struct file *file;
+	struct inode *inode;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bitmap->lock, flags);
+	file = bitmap->file;
+	bitmap->file = NULL;
+	spin_unlock_irqrestore(&bitmap->lock, flags);
+
+	bitmap_stop_daemons(bitmap);
+
+	drain_write_queues(bitmap);
+
+	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);
+		fput(file);
+	}
+}
+
+
+/*
+ * bitmap_file_kick - if an error occurs while manipulating the bitmap file
+ * then it is no longer reliable, so we stop using it and we mark the file
+ * as failed in the superblock
+ */
+static void bitmap_file_kick(struct bitmap *bitmap)
+{
+	char *path, *ptr = NULL;
+
+	bitmap_mask_state(bitmap, BITMAP_STALE, MASK_SET);
+	bitmap_update_sb(bitmap);
+
+	if (bitmap->file) {
+		path = kmalloc(PAGE_SIZE, GFP_KERNEL);
+		if (path)
+			ptr = file_path(bitmap->file, path, PAGE_SIZE);
+
+		printk(KERN_ALERT "%s: kicking failed bitmap file %s from array!\n",
+		       bmname(bitmap), ptr ? ptr : "");
+
+		kfree(path);
+	}
+
+	bitmap_file_put(bitmap);
+
+	return;
+}
+
+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
+};
+
+static inline void set_page_attr(struct bitmap *bitmap, struct page *page,
+				enum bitmap_page_attr attr)
+{
+	bitmap->filemap_attr[page->index] |= attr;
+}
+
+static inline void clear_page_attr(struct bitmap *bitmap, struct page *page,
+				enum bitmap_page_attr attr)
+{
+	bitmap->filemap_attr[page->index] &= ~attr;
+}
+
+static inline unsigned long get_page_attr(struct bitmap *bitmap, struct page *page)
+{
+	return bitmap->filemap_attr[page->index];
+}
+
+/*
+ * bitmap_file_set_bit -- called before performing a write to the md device
+ * to set (and eventually sync) a particular bit in the bitmap file
+ *
+ * we set the bit immediately, then we record the page number so that
+ * when an unplug occurs, we can flush the dirty pages out to disk
+ */
+static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block)
+{
+	unsigned long bit;
+	struct page *page;
+	void *kaddr;
+	unsigned long chunk = block >> CHUNK_BLOCK_SHIFT(bitmap);
+
+	if (!bitmap->filemap) {
+		return;
+	}
+
+	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))
+		page_cache_get(page);
+
+ 	/* set the bit */
+	kaddr = kmap_atomic(page, KM_USER0);
+	set_bit(bit, kaddr);
+	kunmap_atomic(kaddr, KM_USER0);
+	PRINTK("set file bit %lu page %lu\n", bit, page->index);
+
+	/* record page number so it gets flushed to disk when unplug occurs */
+	set_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
+
+}
+
+/* this gets called when the md device is ready to unplug its underlying
+ * (slave) device queues -- before we let any writes go down, we need to
+ * sync the dirty pages of the bitmap file to disk */
+int bitmap_unplug(struct bitmap *bitmap)
+{
+	unsigned long i, attr, flags;
+	struct page *page;
+	int wait = 0;
+	int err;
+
+	if (!bitmap)
+		return 0;
+
+	/* look at each page to see if there are any set bits that need to be
+	 * flushed out to disk */
+	for (i = 0; i < bitmap->file_pages; i++) {
+		spin_lock_irqsave(&bitmap->lock, flags);
+		if (!bitmap->filemap) {
+			spin_unlock_irqrestore(&bitmap->lock, flags);
+			return 0;
+		}
+		page = bitmap->filemap[i];
+		attr = get_page_attr(bitmap, page);
+		clear_page_attr(bitmap, page, BITMAP_PAGE_DIRTY);
+		clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
+		if ((attr & BITMAP_PAGE_DIRTY))
+			wait = 1;
+		spin_unlock_irqrestore(&bitmap->lock, flags);
+
+		if (attr & (BITMAP_PAGE_DIRTY | BITMAP_PAGE_NEEDWRITE)) {
+			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
+			wait_event(bitmap->mddev->sb_wait,
+				   atomic_read(&bitmap->mddev->pending_writes)==0);
+	}
+	return 0;
+}
+
+static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
+	unsigned long sectors, int in_sync);
+/* * bitmap_init_from_disk -- called at bitmap_create time to initialize
+ * the in-memory bitmap from the on-disk bitmap -- also, sets up the
+ * memory mapping of the bitmap file
+ * Special cases:
+ *   if there's no bitmap file, or if the bitmap file had been
+ *   previously kicked from the array, we mark all the bits as
+ *   1's in order to cause a full resync.
+ */
+static int bitmap_init_from_disk(struct bitmap *bitmap, int in_sync)
+{
+	unsigned long i, chunks, index, oldindex, bit;
+	struct page *page = NULL, *oldpage = NULL;
+	unsigned long num_pages, bit_cnt = 0;
+	struct file *file;
+	unsigned long bytes, offset, dummy;
+	int outofdate;
+	int ret = -ENOSPC;
+
+	chunks = bitmap->chunks;
+	file = bitmap->file;
+
+	BUG_ON(!file && !bitmap->offset);
+
+#if INJECT_FAULTS_3
+	outofdate = 1;
+#else
+	outofdate = bitmap->flags & BITMAP_STALE;
+#endif
+	if (outofdate)
+		printk(KERN_INFO "%s: bitmap file is out of date, doing full "
+			"recovery\n", bmname(bitmap));
+
+	bytes = (chunks + 7) / 8;
+
+	num_pages = (bytes + sizeof(bitmap_super_t) + PAGE_SIZE - 1) / PAGE_SIZE;
+
+	if (file && i_size_read(file->f_mapping->host) < bytes + sizeof(bitmap_super_t)) {
+		printk(KERN_INFO "%s: bitmap file too short %lu < %lu\n",
+			bmname(bitmap),
+			(unsigned long) i_size_read(file->f_mapping->host),
+			bytes + sizeof(bitmap_super_t));
+		goto out;
+	}
+
+	ret = -ENOMEM;
+
+	bitmap->filemap = kmalloc(sizeof(struct page *) * num_pages, GFP_KERNEL);
+	if (!bitmap->filemap)
+		goto out;
+
+	bitmap->filemap_attr = kmalloc(sizeof(long) * num_pages, GFP_KERNEL);
+	if (!bitmap->filemap_attr)
+		goto out;
+
+	memset(bitmap->filemap_attr, 0, sizeof(long) * num_pages);
+
+	oldindex = ~0L;
+
+	for (i = 0; i < chunks; i++) {
+		index = file_page_index(i);
+		bit = file_page_offset(i);
+		if (index != oldindex) { /* this is a new page, read it in */
+			/* unmap the old page, we're done with it */
+			if (oldpage != NULL)
+				kunmap(oldpage);
+			if (index == 0) {
+				/*
+				 * if we're here then the superblock page
+				 * contains some bits (PAGE_SIZE != sizeof sb)
+				 * we've already read it in, so just use it
+				 */
+				page = bitmap->sb_page;
+				offset = sizeof(bitmap_super_t);
+			} else if (file) {
+				page = read_page(file, index, &dummy);
+				offset = 0;
+			} else {
+				page = read_sb_page(bitmap->mddev, bitmap->offset, index);
+				offset = 0;
+			}
+			if (IS_ERR(page)) { /* read error */
+				ret = PTR_ERR(page);
+				goto out;
+			}
+
+			oldindex = index;
+			oldpage = page;
+			kmap(page);
+
+			if (outofdate) {
+				/*
+				 * if bitmap is out of date, dirty the
+			 	 * whole page and write it out
+				 */
+				memset(page_address(page) + offset, 0xff,
+					PAGE_SIZE - offset);
+				ret = write_page(bitmap, page, 1);
+				if (ret) {
+					kunmap(page);
+					/* release, page not in filemap yet */
+					page_cache_release(page);
+					goto out;
+				}
+			}
+
+			bitmap->filemap[bitmap->file_pages++] = page;
+		}
+		if (test_bit(bit, page_address(page))) {
+			/* if the disk bit is set, set the memory bit */
+			bitmap_set_memory_bits(bitmap,
+					i << CHUNK_BLOCK_SHIFT(bitmap), 1, in_sync);
+			bit_cnt++;
+		}
+	}
+
+ 	/* everything went OK */
+	ret = 0;
+	bitmap_mask_state(bitmap, BITMAP_STALE, MASK_UNSET);
+
+	if (page) /* unmap the last page */
+		kunmap(page);
+
+	if (bit_cnt) { /* Kick recovery if any bits were set */
+		set_bit(MD_RECOVERY_NEEDED, &bitmap->mddev->recovery);
+		md_wakeup_thread(bitmap->mddev->thread);
+	}
+
+out:
+	printk(KERN_INFO "%s: bitmap initialized from disk: "
+		"read %lu/%lu pages, set %lu bits, status: %d\n",
+		bmname(bitmap), bitmap->file_pages, num_pages, bit_cnt, ret);
+
+	return ret;
+}
+
+void bitmap_write_all(struct bitmap *bitmap)
+{
+	/* We don't actually write all bitmap blocks here,
+	 * just flag them as needing to be written
+	 */
+
+	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;
+}
+
+
+static void bitmap_count_page(struct bitmap *bitmap, sector_t offset, int inc)
+{
+	sector_t chunk = offset >> CHUNK_BLOCK_SHIFT(bitmap);
+	unsigned long page = chunk >> PAGE_COUNTER_SHIFT;
+	bitmap->bp[page].count += inc;
+/*
+	if (page == 0) printk("count page 0, offset %llu: %d gives %d\n",
+			      (unsigned long long)offset, inc, bitmap->bp[page].count);
+*/
+	bitmap_checkfree(bitmap, page);
+}
+static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
+					    sector_t offset, int *blocks,
+					    int create);
+
+/*
+ * bitmap daemon -- periodically wakes up to clean bits and flush pages
+ *			out to disk
+ */
+
+int bitmap_daemon_work(struct bitmap *bitmap)
+{
+	unsigned long j;
+	unsigned long flags;
+	struct page *page = NULL, *lastpage = NULL;
+	int err = 0;
+	int blocks;
+	int attr;
+
+	if (bitmap == NULL)
+		return 0;
+	if (time_before(jiffies, bitmap->daemon_lastrun + bitmap->daemon_sleep*HZ))
+		return 0;
+	bitmap->daemon_lastrun = jiffies;
+
+	for (j = 0; j < bitmap->chunks; j++) {
+		bitmap_counter_t *bmc;
+		spin_lock_irqsave(&bitmap->lock, flags);
+		if (!bitmap->filemap) {
+			/* error or shutdown */
+			spin_unlock_irqrestore(&bitmap->lock, flags);
+			break;
+		}
+
+		page = filemap_get_page(bitmap, j);
+
+		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) {
+					page_cache_get(page);
+					clear_page_attr(bitmap, page, BITMAP_PAGE_NEEDWRITE);
+				}
+				spin_unlock_irqrestore(&bitmap->lock, flags);
+				if (attr & BITMAP_PAGE_NEEDWRITE) {
+					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);
+					}
+					page_cache_release(page);
+				}
+				continue;
+			}
+
+			/* grab the new page, sync and release the old */
+			page_cache_get(page);
+			if (lastpage != NULL) {
+				if (get_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);
+				}
+				kunmap(lastpage);
+				page_cache_release(lastpage);
+				if (err)
+					bitmap_file_kick(bitmap);
+			} else
+				spin_unlock_irqrestore(&bitmap->lock, flags);
+			lastpage = page;
+			kmap(page);
+/*
+			printk("bitmap clean at page %lu\n", j);
+*/
+			spin_lock_irqsave(&bitmap->lock, flags);
+			clear_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
+		}
+		bmc = bitmap_get_counter(bitmap, j << CHUNK_BLOCK_SHIFT(bitmap),
+					&blocks, 0);
+		if (bmc) {
+/*
+  if (j < 100) printk("bitmap: j=%lu, *bmc = 0x%x\n", j, *bmc);
+*/
+			if (*bmc == 2) {
+				*bmc=1; /* maybe clear the bit next time */
+				set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
+			} else if (*bmc == 1) {
+				/* we can clear the bit */
+				*bmc = 0;
+				bitmap_count_page(bitmap, j << CHUNK_BLOCK_SHIFT(bitmap),
+						  -1);
+
+				/* clear the bit */
+				clear_bit(file_page_offset(j), page_address(page));
+			}
+		}
+		spin_unlock_irqrestore(&bitmap->lock, flags);
+	}
+
+	/* now sync the final page */
+	if (lastpage != NULL) {
+		kunmap(lastpage);
+		spin_lock_irqsave(&bitmap->lock, flags);
+		if (get_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);
+		}
+
+		page_cache_release(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;
+	}
+
+	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);
+		page_cache_release(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 int bitmap_start_daemon(struct bitmap *bitmap, mdk_thread_t **ptr,
+				void (*func)(mddev_t *), char *name)
+{
+	mdk_thread_t *daemon;
+	unsigned long flags;
+	char namebuf[32];
+
+	spin_lock_irqsave(&bitmap->lock, flags);
+	*ptr = NULL;
+
+	if (!bitmap->file) /* no need for daemon if there's no backing file */
+		goto out_unlock;
+
+	spin_unlock_irqrestore(&bitmap->lock, flags);
+
+#if 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 -ECHILD;
+	}
+
+	spin_lock_irqsave(&bitmap->lock, flags);
+	*ptr = daemon;
+
+	md_wakeup_thread(daemon); /* start it running */
+
+	PRINTK("%s: %s daemon (pid %d) started...\n",
+		bmname(bitmap), name, daemon->tsk->pid);
+out_unlock:
+	spin_unlock_irqrestore(&bitmap->lock, flags);
+	return 0;
+}
+
+static int bitmap_start_daemons(struct bitmap *bitmap)
+{
+	int err = bitmap_start_daemon(bitmap, &bitmap->writeback_daemon,
+					bitmap_writeback_daemon, "bitmap_wb");
+	return err;
+}
+
+static void bitmap_stop_daemon(struct bitmap *bitmap, mdk_thread_t **ptr)
+{
+	mdk_thread_t *daemon;
+	unsigned long flags;
+
+	spin_lock_irqsave(&bitmap->lock, flags);
+	daemon = *ptr;
+	*ptr = NULL;
+	spin_unlock_irqrestore(&bitmap->lock, flags);
+	if (daemon)
+		md_unregister_thread(daemon); /* destroy the thread */
+}
+
+static void bitmap_stop_daemons(struct bitmap *bitmap)
+{
+	/* the daemons can't stop themselves... they'll just exit instead... */
+	if (bitmap->writeback_daemon &&
+	    current->pid != bitmap->writeback_daemon->tsk->pid)
+		bitmap_stop_daemon(bitmap, &bitmap->writeback_daemon);
+}
+
+static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
+					    sector_t offset, int *blocks,
+					    int create)
+{
+	/* If 'create', we might release the lock and reclaim it.
+	 * The lock must have been taken with interrupts enabled.
+	 * If !create, we don't release the lock.
+	 */
+	sector_t chunk = offset >> CHUNK_BLOCK_SHIFT(bitmap);
+	unsigned long page = chunk >> PAGE_COUNTER_SHIFT;
+	unsigned long pageoff = (chunk & PAGE_COUNTER_MASK) << COUNTER_BYTE_SHIFT;
+	sector_t csize;
+
+	if (bitmap_checkpage(bitmap, page, create) < 0) {
+		csize = ((sector_t)1) << (CHUNK_BLOCK_SHIFT(bitmap));
+		*blocks = csize - (offset & (csize- 1));
+		return NULL;
+	}
+	/* now locked ... */
+
+	if (bitmap->bp[page].hijacked) { /* hijacked pointer */
+		/* should we use the first or second counter field
+		 * of the hijacked pointer? */
+		int hi = (pageoff > PAGE_COUNTER_MASK);
+		csize = ((sector_t)1) << (CHUNK_BLOCK_SHIFT(bitmap) +
+					  PAGE_COUNTER_SHIFT - 1);
+		*blocks = csize - (offset & (csize- 1));
+		return  &((bitmap_counter_t *)
+			  &bitmap->bp[page].map)[hi];
+	} else { /* page is allocated */
+		csize = ((sector_t)1) << (CHUNK_BLOCK_SHIFT(bitmap));
+		*blocks = csize - (offset & (csize- 1));
+		return (bitmap_counter_t *)
+			&(bitmap->bp[page].map[pageoff]);
+	}
+}
+
+int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors)
+{
+	if (!bitmap) return 0;
+	while (sectors) {
+		int blocks;
+		bitmap_counter_t *bmc;
+
+		spin_lock_irq(&bitmap->lock);
+		bmc = bitmap_get_counter(bitmap, offset, &blocks, 1);
+		if (!bmc) {
+			spin_unlock_irq(&bitmap->lock);
+			return 0;
+		}
+
+		switch(*bmc) {
+		case 0:
+			bitmap_file_set_bit(bitmap, offset);
+			bitmap_count_page(bitmap,offset, 1);
+			blk_plug_device(bitmap->mddev->queue);
+			/* fall through */
+		case 1:
+			*bmc = 2;
+		}
+		if ((*bmc & COUNTER_MAX) == COUNTER_MAX) BUG();
+		(*bmc)++;
+
+		spin_unlock_irq(&bitmap->lock);
+
+		offset += blocks;
+		if (sectors > blocks)
+			sectors -= blocks;
+		else sectors = 0;
+	}
+	return 0;
+}
+
+void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors,
+		     int success)
+{
+	if (!bitmap) return;
+	while (sectors) {
+		int blocks;
+		unsigned long flags;
+		bitmap_counter_t *bmc;
+
+		spin_lock_irqsave(&bitmap->lock, flags);
+		bmc = bitmap_get_counter(bitmap, offset, &blocks, 0);
+		if (!bmc) {
+			spin_unlock_irqrestore(&bitmap->lock, flags);
+			return;
+		}
+
+		if (!success && ! (*bmc & NEEDED_MASK))
+			*bmc |= NEEDED_MASK;
+
+		(*bmc)--;
+		if (*bmc <= 2) {
+			set_page_attr(bitmap,
+				      filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)),
+				      BITMAP_PAGE_CLEAN);
+		}
+		spin_unlock_irqrestore(&bitmap->lock, flags);
+		offset += blocks;
+		if (sectors > blocks)
+			sectors -= blocks;
+		else sectors = 0;
+	}
+}
+
+int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks)
+{
+	bitmap_counter_t *bmc;
+	int rv;
+	if (bitmap == NULL) {/* FIXME or bitmap set as 'failed' */
+		*blocks = 1024;
+		return 1; /* always resync if no bitmap */
+	}
+	spin_lock_irq(&bitmap->lock);
+	bmc = bitmap_get_counter(bitmap, offset, blocks, 0);
+	rv = 0;
+	if (bmc) {
+		/* locked */
+		if (RESYNC(*bmc))
+			rv = 1;
+		else if (NEEDED(*bmc)) {
+			rv = 1;
+			*bmc |= RESYNC_MASK;
+			*bmc &= ~NEEDED_MASK;
+		}
+	}
+	spin_unlock_irq(&bitmap->lock);
+	return rv;
+}
+
+void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted)
+{
+	bitmap_counter_t *bmc;
+	unsigned long flags;
+/*
+	if (offset == 0) printk("bitmap_end_sync 0 (%d)\n", aborted);
+*/	if (bitmap == NULL) {
+		*blocks = 1024;
+		return;
+	}
+	spin_lock_irqsave(&bitmap->lock, flags);
+	bmc = bitmap_get_counter(bitmap, offset, blocks, 0);
+	if (bmc == NULL)
+		goto unlock;
+	/* locked */
+/*
+	if (offset == 0) printk("bitmap_end sync found 0x%x, blocks %d\n", *bmc, *blocks);
+*/
+	if (RESYNC(*bmc)) {
+		*bmc &= ~RESYNC_MASK;
+
+		if (!NEEDED(*bmc) && aborted)
+			*bmc |= NEEDED_MASK;
+		else {
+			if (*bmc <= 2) {
+				set_page_attr(bitmap,
+					      filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap)),
+					      BITMAP_PAGE_CLEAN);
+			}
+		}
+	}
+ unlock:
+	spin_unlock_irqrestore(&bitmap->lock, flags);
+}
+
+void bitmap_close_sync(struct bitmap *bitmap)
+{
+	/* Sync has finished, and any bitmap chunks that weren't synced
+	 * properly have been aborted.  It remains to us to clear the
+	 * RESYNC bit wherever it is still on
+	 */
+	sector_t sector = 0;
+	int blocks;
+	if (!bitmap) return;
+	while (sector < bitmap->mddev->resync_max_sectors) {
+		bitmap_end_sync(bitmap, sector, &blocks, 0);
+/*
+		if (sector < 500) printk("bitmap_close_sync: sec %llu blks %d\n",
+					 (unsigned long long)sector, blocks);
+*/		sector += blocks;
+	}
+}
+
+static void bitmap_set_memory_bits(struct bitmap *bitmap, sector_t offset,
+				   unsigned long sectors, int in_sync)
+{
+	/* For each chunk covered by any of these sectors, set the
+	 * counter to 1 and set resync_needed unless in_sync.  They should all
+	 * be 0 at this point
+	 */
+	while (sectors) {
+		int secs;
+		bitmap_counter_t *bmc;
+		spin_lock_irq(&bitmap->lock);
+		bmc = bitmap_get_counter(bitmap, offset, &secs, 1);
+		if (!bmc) {
+			spin_unlock_irq(&bitmap->lock);
+			return;
+		}
+		if (! *bmc) {
+			struct page *page;
+			*bmc = 1 | (in_sync? 0 : NEEDED_MASK);
+			bitmap_count_page(bitmap, offset, 1);
+			page = filemap_get_page(bitmap, offset >> CHUNK_BLOCK_SHIFT(bitmap));
+			set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
+		}
+		spin_unlock_irq(&bitmap->lock);
+		if (sectors > secs)
+			sectors -= secs;
+		else
+			sectors = 0;
+	}
+}
+
+/*
+ * free memory that was allocated
+ */
+void bitmap_destroy(mddev_t *mddev)
+{
+	unsigned long k, pages;
+	struct bitmap_page *bp;
+	struct bitmap *bitmap = mddev->bitmap;
+
+	if (!bitmap) /* there was no bitmap */
+		return;
+
+	mddev->bitmap = NULL; /* disconnect from the md device */
+
+	/* release the bitmap file and kill the daemon */
+	bitmap_file_put(bitmap);
+
+	bp = bitmap->bp;
+	pages = bitmap->pages;
+
+	/* 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)
+				kfree(bp[k].map);
+	kfree(bp);
+	kfree(bitmap);
+}
+
+/*
+ * initialize the bitmap structure
+ * if this returns an error, bitmap_destroy must be called to do clean up
+ */
+int bitmap_create(mddev_t *mddev)
+{
+	struct bitmap *bitmap;
+	unsigned long blocks = mddev->resync_max_sectors;
+	unsigned long chunks;
+	unsigned long pages;
+	struct file *file = mddev->bitmap_file;
+	int err;
+
+	BUG_ON(sizeof(bitmap_super_t) != 256);
+
+	if (!file && !mddev->bitmap_offset) /* bitmap disabled, nothing to do */
+		return 0;
+
+	BUG_ON(file && mddev->bitmap_offset);
+
+	bitmap = kmalloc(sizeof(*bitmap), GFP_KERNEL);
+	if (!bitmap)
+		return -ENOMEM;
+
+	memset(bitmap, 0, sizeof(*bitmap));
+
+	spin_lock_init(&bitmap->lock);
+	bitmap->mddev = mddev;
+	mddev->bitmap = bitmap;
+
+	spin_lock_init(&bitmap->write_lock);
+	INIT_LIST_HEAD(&bitmap->complete_pages);
+	init_waitqueue_head(&bitmap->write_wait);
+	bitmap->write_pool = mempool_create(WRITE_POOL_SIZE, write_pool_alloc,
+				write_pool_free, NULL);
+	if (!bitmap->write_pool)
+		return -ENOMEM;
+
+	bitmap->file = file;
+	bitmap->offset = mddev->bitmap_offset;
+	if (file) get_file(file);
+	/* read superblock from bitmap file (this sets bitmap->chunksize) */
+	err = bitmap_read_sb(bitmap);
+	if (err)
+		return err;
+
+	bitmap->chunkshift = find_first_bit(&bitmap->chunksize,
+					sizeof(bitmap->chunksize));
+
+	/* now that chunksize and chunkshift are set, we can use these macros */
+ 	chunks = (blocks + CHUNK_BLOCK_RATIO(bitmap) - 1) /
+			CHUNK_BLOCK_RATIO(bitmap);
+ 	pages = (chunks + PAGE_COUNTER_RATIO - 1) / PAGE_COUNTER_RATIO;
+
+	BUG_ON(!pages);
+
+	bitmap->chunks = chunks;
+	bitmap->pages = pages;
+	bitmap->missing_pages = pages;
+	bitmap->counter_bits = COUNTER_BITS;
+
+	bitmap->syncchunk = ~0UL;
+
+#if INJECT_FATAL_FAULT_1
+	bitmap->bp = NULL;
+#else
+	bitmap->bp = kmalloc(pages * sizeof(*bitmap->bp), GFP_KERNEL);
+#endif
+	if (!bitmap->bp)
+		return -ENOMEM;
+	memset(bitmap->bp, 0, pages * sizeof(*bitmap->bp));
+
+	bitmap->flags |= BITMAP_ACTIVE;
+
+	/* now that we have some pages available, initialize the in-memory
+	 * bitmap from the on-disk bitmap */
+	err = bitmap_init_from_disk(bitmap, mddev->recovery_cp == MaxSector);
+	if (err)
+		return err;
+
+	printk(KERN_INFO "created bitmap (%lu pages) for device %s\n",
+		pages, bmname(bitmap));
+
+	/* kick off the bitmap daemons */
+	err = bitmap_start_daemons(bitmap);
+	if (err)
+		return err;
+	return bitmap_update_sb(bitmap);
+}
+
+/* the bitmap API -- for raid personalities */
+EXPORT_SYMBOL(bitmap_startwrite);
+EXPORT_SYMBOL(bitmap_endwrite);
+EXPORT_SYMBOL(bitmap_start_sync);
+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 0dd6c2b..d0a4bab 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -704,8 +704,7 @@
 	mempool_destroy(cc->page_pool);
 	mempool_destroy(cc->io_pool);
 
-	if (cc->iv_mode)
-		kfree(cc->iv_mode);
+	kfree(cc->iv_mode);
 	if (cc->iv_gen_ops && cc->iv_gen_ops->dtr)
 		cc->iv_gen_ops->dtr(cc);
 	crypto_free_tfm(cc->tfm);
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index ee3c869..200a068 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -122,14 +122,6 @@
 /*-----------------------------------------------------------------
  * Inserting, removing and renaming a device.
  *---------------------------------------------------------------*/
-static inline char *kstrdup(const char *str)
-{
-	char *r = kmalloc(strlen(str) + 1, GFP_KERNEL);
-	if (r)
-		strcpy(r, str);
-	return r;
-}
-
 static struct hash_cell *alloc_cell(const char *name, const char *uuid,
 				    struct mapped_device *md)
 {
@@ -139,7 +131,7 @@
 	if (!hc)
 		return NULL;
 
-	hc->name = kstrdup(name);
+	hc->name = kstrdup(name, GFP_KERNEL);
 	if (!hc->name) {
 		kfree(hc);
 		return NULL;
@@ -149,7 +141,7 @@
 		hc->uuid = NULL;
 
 	else {
-		hc->uuid = kstrdup(uuid);
+		hc->uuid = kstrdup(uuid, GFP_KERNEL);
 		if (!hc->uuid) {
 			kfree(hc->name);
 			kfree(hc);
@@ -273,7 +265,7 @@
 	/*
 	 * duplicate new.
 	 */
-	new_name = kstrdup(new);
+	new_name = kstrdup(new, GFP_KERNEL);
 	if (!new_name)
 		return -ENOMEM;
 
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index 1e97b3c..0c1b852 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -985,6 +985,9 @@
 	if (!error)
 		return 0;	/* I/O complete */
 
+	if ((error == -EWOULDBLOCK) && bio_rw_ahead(bio))
+		return error;
+
 	spin_lock(&m->lock);
 	if (!m->nr_valid_paths) {
 		if (!m->queue_if_no_path || m->suspended) {
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index b1941b8..8d74001 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -217,8 +217,7 @@
 	return 0;
 
 out:
-	if (conf)
-		kfree(conf);
+	kfree(conf);
 	return 1;
 }
 
diff --git a/drivers/md/md.c b/drivers/md/md.c
index d899204..3802f7a 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -19,6 +19,9 @@
 
      Neil Brown <neilb@cse.unsw.edu.au>.
 
+   - persistent bitmap code
+     Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, 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, or (at your option)
@@ -33,6 +36,7 @@
 #include <linux/config.h>
 #include <linux/linkage.h>
 #include <linux/raid/md.h>
+#include <linux/raid/bitmap.h>
 #include <linux/sysctl.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/buffer_head.h> /* for invalidate_bdev */
@@ -40,6 +44,8 @@
 
 #include <linux/init.h>
 
+#include <linux/file.h>
+
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
 #endif
@@ -189,8 +195,7 @@
 		if (mddev->unit == unit) {
 			mddev_get(mddev);
 			spin_unlock(&all_mddevs_lock);
-			if (new)
-				kfree(new);
+			kfree(new);
 			return mddev;
 		}
 
@@ -218,6 +223,8 @@
 	INIT_LIST_HEAD(&new->all_mddevs);
 	init_timer(&new->safemode_timer);
 	atomic_set(&new->active, 1);
+	spin_lock_init(&new->write_lock);
+	init_waitqueue_head(&new->sb_wait);
 
 	new->queue = blk_alloc_queue(GFP_KERNEL);
 	if (!new->queue) {
@@ -320,6 +327,40 @@
 }
 
 
+static int super_written(struct bio *bio, unsigned int bytes_done, int error)
+{
+	mdk_rdev_t *rdev = bio->bi_private;
+	if (bio->bi_size)
+		return 1;
+
+	if (error || !test_bit(BIO_UPTODATE, &bio->bi_flags))
+		md_error(rdev->mddev, rdev);
+
+	if (atomic_dec_and_test(&rdev->mddev->pending_writes))
+		wake_up(&rdev->mddev->sb_wait);
+	return 0;
+}
+
+void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
+		   sector_t sector, int size, struct page *page)
+{
+	/* write first size bytes of page to sector of rdev
+	 * Increment mddev->pending_writes before returning
+	 * and decrement it on completion, waking up sb_wait
+	 * if zero is reached.
+	 * If an error occurred, call md_error
+	 */
+	struct bio *bio = bio_alloc(GFP_NOIO, 1);
+
+	bio->bi_bdev = rdev->bdev;
+	bio->bi_sector = sector;
+	bio_add_page(bio, page, size, 0);
+	bio->bi_private = rdev;
+	bio->bi_end_io = super_written;
+	atomic_inc(&mddev->pending_writes);
+	submit_bio((1<<BIO_RW)|(1<<BIO_RW_SYNC), bio);
+}
+
 static int bi_complete(struct bio *bio, unsigned int bytes_done, int error)
 {
 	if (bio->bi_size)
@@ -329,7 +370,7 @@
 	return 0;
 }
 
-static int sync_page_io(struct block_device *bdev, sector_t sector, int size,
+int sync_page_io(struct block_device *bdev, sector_t sector, int size,
 		   struct page *page, int rw)
 {
 	struct bio *bio = bio_alloc(GFP_NOIO, 1);
@@ -416,11 +457,8 @@
 		ret = 1;
 
 abort:
-	if (tmp1)
-		kfree(tmp1);
-	if (tmp2)
-		kfree(tmp2);
-
+	kfree(tmp1);
+	kfree(tmp2);
 	return ret;
 }
 
@@ -569,6 +607,8 @@
 	mdp_disk_t *desc;
 	mdp_super_t *sb = (mdp_super_t *)page_address(rdev->sb_page);
 
+	rdev->raid_disk = -1;
+	rdev->in_sync = 0;
 	if (mddev->raid_disks == 0) {
 		mddev->major_version = 0;
 		mddev->minor_version = sb->minor_version;
@@ -599,16 +639,35 @@
 		memcpy(mddev->uuid+12,&sb->set_uuid3, 4);
 
 		mddev->max_disks = MD_SB_DISKS;
-	} else {
-		__u64 ev1;
-		ev1 = md_event(sb);
+
+		if (sb->state & (1<<MD_SB_BITMAP_PRESENT) &&
+		    mddev->bitmap_file == NULL) {
+			if (mddev->level != 1) {
+				/* FIXME use a better test */
+				printk(KERN_WARNING "md: bitmaps only support for raid1\n");
+				return -EINVAL;
+			}
+			mddev->bitmap_offset = (MD_SB_BYTES >> 9);
+		}
+
+	} else if (mddev->pers == NULL) {
+		/* Insist on good event counter while assembling */
+		__u64 ev1 = md_event(sb);
 		++ev1;
 		if (ev1 < mddev->events) 
 			return -EINVAL;
-	}
+	} else if (mddev->bitmap) {
+		/* 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;
+
 	if (mddev->level != LEVEL_MULTIPATH) {
-		rdev->raid_disk = -1;
-		rdev->in_sync = rdev->faulty = 0;
+		rdev->faulty = 0;
 		desc = sb->disks + rdev->desc_nr;
 
 		if (desc->state & (1<<MD_DISK_FAULTY))
@@ -618,7 +677,8 @@
 			rdev->in_sync = 1;
 			rdev->raid_disk = desc->raid_disk;
 		}
-	}
+	} else /* MULTIPATH are always insync */
+		rdev->in_sync = 1;
 	return 0;
 }
 
@@ -683,6 +743,9 @@
 	sb->layout = mddev->layout;
 	sb->chunk_size = mddev->chunk_size;
 
+	if (mddev->bitmap && mddev->bitmap_file == NULL)
+		sb->state |= (1<<MD_SB_BITMAP_PRESENT);
+
 	sb->disks[0].state = (1<<MD_DISK_REMOVED);
 	ITERATE_RDEV(mddev,rdev2,tmp) {
 		mdp_disk_t *d;
@@ -780,7 +843,7 @@
 	case 0:
 		sb_offset = rdev->bdev->bd_inode->i_size >> 9;
 		sb_offset -= 8*2;
-		sb_offset &= ~(4*2-1);
+		sb_offset &= ~(sector_t)(4*2-1);
 		/* convert from sectors to K */
 		sb_offset /= 2;
 		break;
@@ -860,6 +923,8 @@
 {
 	struct mdp_superblock_1 *sb = (struct mdp_superblock_1*)page_address(rdev->sb_page);
 
+	rdev->raid_disk = -1;
+	rdev->in_sync = 0;
 	if (mddev->raid_disks == 0) {
 		mddev->major_version = 1;
 		mddev->patch_version = 0;
@@ -877,13 +942,30 @@
 		memcpy(mddev->uuid, sb->set_uuid, 16);
 
 		mddev->max_disks =  (4096-256)/2;
-	} else {
-		__u64 ev1;
-		ev1 = le64_to_cpu(sb->events);
+
+		if ((le32_to_cpu(sb->feature_map) & 1) &&
+		    mddev->bitmap_file == NULL ) {
+			if (mddev->level != 1) {
+				printk(KERN_WARNING "md: bitmaps only supported for raid1\n");
+				return -EINVAL;
+			}
+			mddev->bitmap_offset = (__s32)le32_to_cpu(sb->bitmap_offset);
+		}
+	} 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;
-	}
+	} else if (mddev->bitmap) {
+		/* 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;
 
 	if (mddev->level != LEVEL_MULTIPATH) {
 		int role;
@@ -891,14 +973,10 @@
 		role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]);
 		switch(role) {
 		case 0xffff: /* spare */
-			rdev->in_sync = 0;
 			rdev->faulty = 0;
-			rdev->raid_disk = -1;
 			break;
 		case 0xfffe: /* faulty */
-			rdev->in_sync = 0;
 			rdev->faulty = 1;
-			rdev->raid_disk = -1;
 			break;
 		default:
 			rdev->in_sync = 1;
@@ -906,7 +984,9 @@
 			rdev->raid_disk = role;
 			break;
 		}
-	}
+	} else /* MULTIPATH are always insync */
+		rdev->in_sync = 1;
+
 	return 0;
 }
 
@@ -933,6 +1013,11 @@
 	else
 		sb->resync_offset = cpu_to_le64(0);
 
+	if (mddev->bitmap && mddev->bitmap_file == NULL) {
+		sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset);
+		sb->feature_map = cpu_to_le32(1);
+	}
+
 	max_dev = 0;
 	ITERATE_RDEV(mddev,rdev2,tmp)
 		if (rdev2->desc_nr+1 > max_dev)
@@ -1196,8 +1281,11 @@
 	printk("md:	* <COMPLETE RAID STATE PRINTOUT> *\n");
 	printk("md:	**********************************\n");
 	ITERATE_MDDEV(mddev,tmp) {
-		printk("%s: ", mdname(mddev));
 
+		if (mddev->bitmap)
+			bitmap_print_sb(mddev->bitmap);
+		else
+			printk("%s: ", mdname(mddev));
 		ITERATE_RDEV(mddev,rdev,tmp2)
 			printk("<%s>", bdevname(rdev->bdev,b));
 		printk("\n");
@@ -1210,30 +1298,6 @@
 }
 
 
-static int write_disk_sb(mdk_rdev_t * rdev)
-{
-	char b[BDEVNAME_SIZE];
-	if (!rdev->sb_loaded) {
-		MD_BUG();
-		return 1;
-	}
-	if (rdev->faulty) {
-		MD_BUG();
-		return 1;
-	}
-
-	dprintk(KERN_INFO "(write) %s's sb offset: %llu\n",
-		bdevname(rdev->bdev,b),
-	       (unsigned long long)rdev->sb_offset);
-  
-	if (sync_page_io(rdev->bdev, rdev->sb_offset<<1, MD_SB_BYTES, rdev->sb_page, WRITE))
-		return 0;
-
-	printk("md: write_disk_sb failed for device %s\n", 
-		bdevname(rdev->bdev,b));
-	return 1;
-}
-
 static void sync_sbs(mddev_t * mddev)
 {
 	mdk_rdev_t *rdev;
@@ -1248,12 +1312,14 @@
 
 static void md_update_sb(mddev_t * mddev)
 {
-	int err, count = 100;
+	int err;
 	struct list_head *tmp;
 	mdk_rdev_t *rdev;
+	int sync_req;
 
-	mddev->sb_dirty = 0;
 repeat:
+	spin_lock(&mddev->write_lock);
+	sync_req = mddev->in_sync;
 	mddev->utime = get_seconds();
 	mddev->events ++;
 
@@ -1266,20 +1332,26 @@
 		MD_BUG();
 		mddev->events --;
 	}
+	mddev->sb_dirty = 2;
 	sync_sbs(mddev);
 
 	/*
 	 * do not write anything to disk if using
 	 * nonpersistent superblocks
 	 */
-	if (!mddev->persistent)
+	if (!mddev->persistent) {
+		mddev->sb_dirty = 0;
+		spin_unlock(&mddev->write_lock);
+		wake_up(&mddev->sb_wait);
 		return;
+	}
+	spin_unlock(&mddev->write_lock);
 
 	dprintk(KERN_INFO 
 		"md: updating %s RAID superblock on device (in sync %d)\n",
 		mdname(mddev),mddev->in_sync);
 
-	err = 0;
+	err = bitmap_update_sb(mddev->bitmap);
 	ITERATE_RDEV(mddev,rdev,tmp) {
 		char b[BDEVNAME_SIZE];
 		dprintk(KERN_INFO "md: ");
@@ -1288,22 +1360,32 @@
 
 		dprintk("%s ", bdevname(rdev->bdev,b));
 		if (!rdev->faulty) {
-			err += write_disk_sb(rdev);
+			md_super_write(mddev,rdev,
+				       rdev->sb_offset<<1, MD_SB_BYTES,
+				       rdev->sb_page);
+			dprintk(KERN_INFO "(write) %s's sb offset: %llu\n",
+				bdevname(rdev->bdev,b),
+				(unsigned long long)rdev->sb_offset);
+
 		} else
 			dprintk(")\n");
-		if (!err && mddev->level == LEVEL_MULTIPATH)
+		if (mddev->level == LEVEL_MULTIPATH)
 			/* only need to write one superblock... */
 			break;
 	}
-	if (err) {
-		if (--count) {
-			printk(KERN_ERR "md: errors occurred during superblock"
-				" update, repeating\n");
-			goto repeat;
-		}
-		printk(KERN_ERR \
-			"md: excessive errors occurred during superblock update, exiting\n");
+	wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0);
+	/* if there was a failure, sb_dirty was set to 1, and we re-write super */
+
+	spin_lock(&mddev->write_lock);
+	if (mddev->in_sync != sync_req|| mddev->sb_dirty == 1) {
+		/* have to write it out again */
+		spin_unlock(&mddev->write_lock);
+		goto repeat;
 	}
+	mddev->sb_dirty = 0;
+	spin_unlock(&mddev->write_lock);
+	wake_up(&mddev->sb_wait);
+
 }
 
 /*
@@ -1607,12 +1689,19 @@
 
 	mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */
 
-	err = mddev->pers->run(mddev);
+	/* before we start the array running, initialise the bitmap */
+	err = bitmap_create(mddev);
+	if (err)
+		printk(KERN_ERR "%s: failed to create bitmap (%d)\n",
+			mdname(mddev), err);
+	else
+		err = mddev->pers->run(mddev);
 	if (err) {
 		printk(KERN_ERR "md: pers->run() failed ...\n");
 		module_put(mddev->pers->owner);
 		mddev->pers = NULL;
-		return -EINVAL;
+		bitmap_destroy(mddev);
+		return err;
 	}
  	atomic_set(&mddev->writes_pending,0);
 	mddev->safemode = 0;
@@ -1725,6 +1814,14 @@
 		if (ro)
 			set_disk_ro(disk, 1);
 	}
+
+	bitmap_destroy(mddev);
+	if (mddev->bitmap_file) {
+		atomic_set(&mddev->bitmap_file->f_dentry->d_inode->i_writecount, 1);
+		fput(mddev->bitmap_file);
+		mddev->bitmap_file = NULL;
+	}
+
 	/*
 	 * Free resources if final stop
 	 */
@@ -1983,6 +2080,42 @@
 	return 0;
 }
 
+static int get_bitmap_file(mddev_t * mddev, void * arg)
+{
+	mdu_bitmap_file_t *file = NULL; /* too big for stack allocation */
+	char *ptr, *buf = NULL;
+	int err = -ENOMEM;
+
+	file = kmalloc(sizeof(*file), GFP_KERNEL);
+	if (!file)
+		goto out;
+
+	/* bitmap disabled, zero the first byte and copy out */
+	if (!mddev->bitmap || !mddev->bitmap->file) {
+		file->pathname[0] = '\0';
+		goto copy_out;
+	}
+
+	buf = kmalloc(sizeof(file->pathname), GFP_KERNEL);
+	if (!buf)
+		goto out;
+
+	ptr = file_path(mddev->bitmap->file, buf, sizeof(file->pathname));
+	if (!ptr)
+		goto out;
+
+	strcpy(file->pathname, ptr);
+
+copy_out:
+	err = 0;
+	if (copy_to_user(arg, file, sizeof(*file)))
+		err = -EFAULT;
+out:
+	kfree(buf);
+	kfree(file);
+	return err;
+}
+
 static int get_disk_info(mddev_t * mddev, void __user * arg)
 {
 	mdu_disk_info_t info;
@@ -2078,11 +2211,25 @@
 				PTR_ERR(rdev));
 			return PTR_ERR(rdev);
 		}
+		/* set save_raid_disk if appropriate */
+		if (!mddev->persistent) {
+			if (info->state & (1<<MD_DISK_SYNC)  &&
+			    info->raid_disk < mddev->raid_disks)
+				rdev->raid_disk = info->raid_disk;
+			else
+				rdev->raid_disk = -1;
+		} else
+			super_types[mddev->major_version].
+				validate_super(mddev, rdev);
+		rdev->saved_raid_disk = rdev->raid_disk;
+
 		rdev->in_sync = 0; /* just to be sure */
 		rdev->raid_disk = -1;
 		err = bind_rdev_to_array(rdev, mddev);
 		if (err)
 			export_rdev(rdev);
+
+		set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
 		if (mddev->thread)
 			md_wakeup_thread(mddev->thread);
 		return err;
@@ -2256,6 +2403,49 @@
 	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;
+
+	if (mddev->pers)
+		return -EBUSY;
+
+	mddev->bitmap_file = fget(fd);
+
+	if (mddev->bitmap_file == NULL) {
+		printk(KERN_ERR "%s: error: failed to get bitmap file\n",
+			mdname(mddev));
+		return -EBADF;
+	}
+
+	err = deny_bitmap_write_access(mddev->bitmap_file);
+	if (err) {
+		printk(KERN_ERR "%s: error: bitmap file is already in use\n",
+			mdname(mddev));
+		fput(mddev->bitmap_file);
+		mddev->bitmap_file = NULL;
+	} else
+		mddev->bitmap_offset = 0; /* file overrides offset */
+	return err;
+}
+
 /*
  * set_array_info is used two different ways
  * The original usage is when creating a new array.
@@ -2567,8 +2757,10 @@
 	/*
 	 * Commands querying/configuring an existing array:
 	 */
-	/* if we are initialised yet, only ADD_NEW_DISK or STOP_ARRAY is allowed */
-	if (!mddev->raid_disks && cmd != ADD_NEW_DISK && cmd != STOP_ARRAY && cmd != RUN_ARRAY) {
+	/* if we are not initialised yet, only ADD_NEW_DISK, STOP_ARRAY,
+	 * RUN_ARRAY, and SET_BITMAP_FILE are allowed */
+	if (!mddev->raid_disks && cmd != ADD_NEW_DISK && cmd != STOP_ARRAY
+			&& cmd != RUN_ARRAY && cmd != SET_BITMAP_FILE) {
 		err = -ENODEV;
 		goto abort_unlock;
 	}
@@ -2582,6 +2774,10 @@
 			err = get_array_info(mddev, argp);
 			goto done_unlock;
 
+		case GET_BITMAP_FILE:
+			err = get_bitmap_file(mddev, (void *)arg);
+			goto done_unlock;
+
 		case GET_DISK_INFO:
 			err = get_disk_info(mddev, argp);
 			goto done_unlock;
@@ -2662,6 +2858,10 @@
 			err = do_md_run (mddev);
 			goto done_unlock;
 
+		case SET_BITMAP_FILE:
+			err = set_bitmap_file(mddev, (int)arg);
+			goto done_unlock;
+
 		default:
 			if (_IOC_TYPE(cmd) == MD_MAJOR)
 				printk(KERN_WARNING "md: %s(pid %d) used"
@@ -2773,10 +2973,10 @@
 	while (thread->run) {
 		void (*run)(mddev_t *);
 
-		wait_event_interruptible(thread->wqueue,
-					 test_bit(THREAD_WAKEUP, &thread->flags));
-		if (current->flags & PF_FREEZE)
-			refrigerator(PF_FREEZE);
+		wait_event_interruptible_timeout(thread->wqueue,
+						 test_bit(THREAD_WAKEUP, &thread->flags),
+						 thread->timeout);
+		try_to_freeze();
 
 		clear_bit(THREAD_WAKEUP, &thread->flags);
 
@@ -2820,6 +3020,7 @@
 	thread->run = run;
 	thread->mddev = mddev;
 	thread->name = name;
+	thread->timeout = MAX_SCHEDULE_TIMEOUT;
 	ret = kernel_thread(md_thread, thread, 0);
 	if (ret < 0) {
 		kfree(thread);
@@ -2858,13 +3059,13 @@
 
 	if (!rdev || rdev->faulty)
 		return;
-
+/*
 	dprintk("md_error dev:%s, rdev:(%d:%d), (caller: %p,%p,%p,%p).\n",
 		mdname(mddev),
 		MAJOR(rdev->bdev->bd_dev), MINOR(rdev->bdev->bd_dev),
 		__builtin_return_address(0),__builtin_return_address(1),
 		__builtin_return_address(2),__builtin_return_address(3));
-
+*/
 	if (!mddev->pers->error_handler)
 		return;
 	mddev->pers->error_handler(mddev,rdev);
@@ -3018,6 +3219,7 @@
 	struct list_head *tmp2;
 	mdk_rdev_t *rdev;
 	int i;
+	struct bitmap *bitmap;
 
 	if (v == (void*)1) {
 		seq_printf(seq, "Personalities : ");
@@ -3070,10 +3272,35 @@
 		if (mddev->pers) {
 			mddev->pers->status (seq, mddev);
 	 		seq_printf(seq, "\n      ");
-			if (mddev->curr_resync > 2)
+			if (mddev->curr_resync > 2) {
 				status_resync (seq, mddev);
-			else if (mddev->curr_resync == 1 || mddev->curr_resync == 2)
-				seq_printf(seq, "	resync=DELAYED");
+				seq_printf(seq, "\n      ");
+			} else if (mddev->curr_resync == 1 || mddev->curr_resync == 2)
+				seq_printf(seq, "	resync=DELAYED\n      ");
+		} else
+			seq_printf(seq, "\n       ");
+
+		if ((bitmap = mddev->bitmap)) {
+			unsigned long chunk_kb;
+			unsigned long flags;
+			spin_lock_irqsave(&bitmap->lock, flags);
+			chunk_kb = bitmap->chunksize >> 10;
+			seq_printf(seq, "bitmap: %lu/%lu pages [%luKB], "
+				"%lu%s chunk",
+				bitmap->pages - bitmap->missing_pages,
+				bitmap->pages,
+				(bitmap->pages - bitmap->missing_pages)
+					<< (PAGE_SHIFT - 10),
+				chunk_kb ? chunk_kb : bitmap->chunksize,
+				chunk_kb ? "KB" : "B");
+			if (bitmap->file) {
+				seq_printf(seq, ", file: ");
+				seq_path(seq, bitmap->file->f_vfsmnt,
+					 bitmap->file->f_dentry," \t\n");
+			}
+
+			seq_printf(seq, "\n");
+			spin_unlock_irqrestore(&bitmap->lock, flags);
 		}
 
 		seq_printf(seq, "\n");
@@ -3176,19 +3403,28 @@
 }
 
 
-void md_write_start(mddev_t *mddev)
+/* md_write_start(mddev, bi)
+ * If we need to update some array metadata (e.g. 'active' flag
+ * in superblock) before writing, schedule a superblock update
+ * and wait for it to complete.
+ */
+void md_write_start(mddev_t *mddev, struct bio *bi)
 {
-	if (!atomic_read(&mddev->writes_pending)) {
-		mddev_lock_uninterruptible(mddev);
+	DEFINE_WAIT(w);
+	if (bio_data_dir(bi) != WRITE)
+		return;
+
+	atomic_inc(&mddev->writes_pending);
+	if (mddev->in_sync) {
+		spin_lock(&mddev->write_lock);
 		if (mddev->in_sync) {
 			mddev->in_sync = 0;
- 			del_timer(&mddev->safemode_timer);
-			md_update_sb(mddev);
+			mddev->sb_dirty = 1;
+			md_wakeup_thread(mddev->thread);
 		}
-		atomic_inc(&mddev->writes_pending);
-		mddev_unlock(mddev);
-	} else
-		atomic_inc(&mddev->writes_pending);
+		spin_unlock(&mddev->write_lock);
+	}
+	wait_event(mddev->sb_wait, mddev->sb_dirty==0);
 }
 
 void md_write_end(mddev_t *mddev)
@@ -3201,37 +3437,6 @@
 	}
 }
 
-static inline void md_enter_safemode(mddev_t *mddev)
-{
-	if (!mddev->safemode) return;
-	if (mddev->safemode == 2 &&
-	    (atomic_read(&mddev->writes_pending) || mddev->in_sync ||
-		    mddev->recovery_cp != MaxSector))
-		return; /* avoid the lock */
-	mddev_lock_uninterruptible(mddev);
-	if (mddev->safemode && !atomic_read(&mddev->writes_pending) &&
-	    !mddev->in_sync && mddev->recovery_cp == MaxSector) {
-		mddev->in_sync = 1;
-		md_update_sb(mddev);
-	}
-	mddev_unlock(mddev);
-
-	if (mddev->safemode == 1)
-		mddev->safemode = 0;
-}
-
-void md_handle_safemode(mddev_t *mddev)
-{
-	if (signal_pending(current)) {
-		printk(KERN_INFO "md: %s in immediate safe mode\n",
-			mdname(mddev));
-		mddev->safemode = 2;
-		flush_signals(current);
-	}
-	md_enter_safemode(mddev);
-}
-
-
 static DECLARE_WAIT_QUEUE_HEAD(resync_wait);
 
 #define SYNC_MARKS	10
@@ -3241,12 +3446,13 @@
 	mddev_t *mddev2;
 	unsigned int currspeed = 0,
 		 window;
-	sector_t max_sectors,j;
+	sector_t max_sectors,j, io_sectors;
 	unsigned long mark[SYNC_MARKS];
 	sector_t mark_cnt[SYNC_MARKS];
 	int last_mark,m;
 	struct list_head *tmp;
 	sector_t last_check;
+	int skipped = 0;
 
 	/* just incase thread restarts... */
 	if (test_bit(MD_RECOVERY_DONE, &mddev->recovery))
@@ -3312,7 +3518,7 @@
 
 	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
 		/* resync follows the size requested by the personality,
-		 * which default to physical size, but can be virtual size
+		 * which defaults to physical size, but can be virtual size
 		 */
 		max_sectors = mddev->resync_max_sectors;
 	else
@@ -3327,13 +3533,15 @@
 	       sysctl_speed_limit_max);
 
 	is_mddev_idle(mddev); /* this also initializes IO event counters */
-	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
+	/* we don't use the checkpoint if there's a bitmap */
+	if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && !mddev->bitmap)
 		j = mddev->recovery_cp;
 	else
 		j = 0;
+	io_sectors = 0;
 	for (m = 0; m < SYNC_MARKS; m++) {
 		mark[m] = jiffies;
-		mark_cnt[m] = j;
+		mark_cnt[m] = io_sectors;
 	}
 	last_mark = 0;
 	mddev->resync_mark = mark[last_mark];
@@ -3358,21 +3566,29 @@
 	}
 
 	while (j < max_sectors) {
-		int sectors;
+		sector_t sectors;
 
-		sectors = mddev->pers->sync_request(mddev, j, currspeed < sysctl_speed_limit_min);
-		if (sectors < 0) {
+		skipped = 0;
+		sectors = mddev->pers->sync_request(mddev, j, &skipped,
+					    currspeed < sysctl_speed_limit_min);
+		if (sectors == 0) {
 			set_bit(MD_RECOVERY_ERR, &mddev->recovery);
 			goto out;
 		}
-		atomic_add(sectors, &mddev->recovery_active);
+
+		if (!skipped) { /* actual IO requested */
+			io_sectors += sectors;
+			atomic_add(sectors, &mddev->recovery_active);
+		}
+
 		j += sectors;
 		if (j>1) mddev->curr_resync = j;
 
-		if (last_check + window > j || j == max_sectors)
+
+		if (last_check + window > io_sectors || j == max_sectors)
 			continue;
 
-		last_check = j;
+		last_check = io_sectors;
 
 		if (test_bit(MD_RECOVERY_INTR, &mddev->recovery) ||
 		    test_bit(MD_RECOVERY_ERR, &mddev->recovery))
@@ -3386,7 +3602,7 @@
 			mddev->resync_mark = mark[next];
 			mddev->resync_mark_cnt = mark_cnt[next];
 			mark[next] = jiffies;
-			mark_cnt[next] = j - atomic_read(&mddev->recovery_active);
+			mark_cnt[next] = io_sectors - atomic_read(&mddev->recovery_active);
 			last_mark = next;
 		}
 
@@ -3413,7 +3629,8 @@
 		mddev->queue->unplug_fn(mddev->queue);
 		cond_resched();
 
-		currspeed = ((unsigned long)(j-mddev->resync_mark_cnt))/2/((jiffies-mddev->resync_mark)/HZ +1) +1;
+		currspeed = ((unsigned long)(io_sectors-mddev->resync_mark_cnt))/2
+			/((jiffies-mddev->resync_mark)/HZ +1) +1;
 
 		if (currspeed > sysctl_speed_limit_min) {
 			if ((currspeed > sysctl_speed_limit_max) ||
@@ -3433,7 +3650,7 @@
 	wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active));
 
 	/* tell personality that we are finished */
-	mddev->pers->sync_request(mddev, max_sectors, 1);
+	mddev->pers->sync_request(mddev, max_sectors, &skipped, 1);
 
 	if (!test_bit(MD_RECOVERY_ERR, &mddev->recovery) &&
 	    mddev->curr_resync > 2 &&
@@ -3447,7 +3664,6 @@
 			mddev->recovery_cp = MaxSector;
 	}
 
-	md_enter_safemode(mddev);
  skip:
 	mddev->curr_resync = 0;
 	wake_up(&resync_wait);
@@ -3484,20 +3700,48 @@
 	struct list_head *rtmp;
 
 
-	dprintk(KERN_INFO "md: recovery thread got woken up ...\n");
+	if (mddev->bitmap)
+		bitmap_daemon_work(mddev->bitmap);
 
 	if (mddev->ro)
 		return;
+
+	if (signal_pending(current)) {
+		if (mddev->pers->sync_request) {
+			printk(KERN_INFO "md: %s in immediate safe mode\n",
+			       mdname(mddev));
+			mddev->safemode = 2;
+		}
+		flush_signals(current);
+	}
+
 	if ( ! (
 		mddev->sb_dirty ||
 		test_bit(MD_RECOVERY_NEEDED, &mddev->recovery) ||
-		test_bit(MD_RECOVERY_DONE, &mddev->recovery)
+		test_bit(MD_RECOVERY_DONE, &mddev->recovery) ||
+		(mddev->safemode == 1) ||
+		(mddev->safemode == 2 && ! atomic_read(&mddev->writes_pending)
+		 && !mddev->in_sync && mddev->recovery_cp == MaxSector)
 		))
 		return;
+
 	if (mddev_trylock(mddev)==0) {
 		int spares =0;
+
+		spin_lock(&mddev->write_lock);
+		if (mddev->safemode && !atomic_read(&mddev->writes_pending) &&
+		    !mddev->in_sync && mddev->recovery_cp == MaxSector) {
+			mddev->in_sync = 1;
+			mddev->sb_dirty = 1;
+		}
+		if (mddev->safemode == 1)
+			mddev->safemode = 0;
+		spin_unlock(&mddev->write_lock);
+
 		if (mddev->sb_dirty)
 			md_update_sb(mddev);
+
+
 		if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) &&
 		    !test_bit(MD_RECOVERY_DONE, &mddev->recovery)) {
 			/* resync/recovery still happening */
@@ -3515,6 +3759,14 @@
 				mddev->pers->spare_active(mddev);
 			}
 			md_update_sb(mddev);
+
+			/* if array is no-longer degraded, then any saved_raid_disk
+			 * information must be scrapped
+			 */
+			if (!mddev->degraded)
+				ITERATE_RDEV(mddev,rdev,rtmp)
+					rdev->saved_raid_disk = -1;
+
 			mddev->recovery = 0;
 			/* flag recovery needed just to double check */
 			set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
@@ -3557,6 +3809,13 @@
 			set_bit(MD_RECOVERY_RUNNING, &mddev->recovery);
 			if (!spares)
 				set_bit(MD_RECOVERY_SYNC, &mddev->recovery);
+			if (spares && mddev->bitmap && ! mddev->bitmap->file) {
+				/* We are adding a device or devices to an array
+				 * which has the bitmap stored on all devices.
+				 * So make sure all bitmap pages get written
+				 */
+				bitmap_write_all(mddev->bitmap);
+			}
 			mddev->sync_thread = md_register_thread(md_do_sync,
 								mddev,
 								"%s_resync");
@@ -3624,6 +3883,8 @@
 			" MD_SB_DISKS=%d\n",
 			MD_MAJOR_VERSION, MD_MINOR_VERSION,
 			MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS);
+	printk(KERN_INFO "md: bitmap version %d.%d\n", BITMAP_MAJOR,
+			BITMAP_MINOR);
 
 	if (register_blkdev(MAJOR_NR, "md"))
 		return -1;
@@ -3739,7 +4000,6 @@
 EXPORT_SYMBOL(md_done_sync);
 EXPORT_SYMBOL(md_write_start);
 EXPORT_SYMBOL(md_write_end);
-EXPORT_SYMBOL(md_handle_safemode);
 EXPORT_SYMBOL(md_register_thread);
 EXPORT_SYMBOL(md_unregister_thread);
 EXPORT_SYMBOL(md_wakeup_thread);
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 2ae2d70..2d2ca7f 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -533,8 +533,7 @@
 out_free_conf:
 	if (conf->pool)
 		mempool_destroy(conf->pool);
-	if (conf->multipaths)
-		kfree(conf->multipaths);
+	kfree(conf->multipaths);
 	kfree(conf);
 	mddev->private = NULL;
 out:
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index e7d934e..e11dd14 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -371,10 +371,8 @@
 	return 0;
 
 out_free_conf:
-	if (conf->strip_zone)
-		kfree(conf->strip_zone);
-	if (conf->devlist)
-		kfree (conf->devlist);
+	kfree(conf->strip_zone);
+	kfree(conf->devlist);
 	kfree(conf);
 	mddev->private = NULL;
 out:
@@ -386,11 +384,11 @@
 	raid0_conf_t *conf = mddev_to_conf(mddev);
 
 	blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
-	kfree (conf->hash_table);
+	kfree(conf->hash_table);
 	conf->hash_table = NULL;
-	kfree (conf->strip_zone);
+	kfree(conf->strip_zone);
 	conf->strip_zone = NULL;
-	kfree (conf);
+	kfree(conf);
 	mddev->private = NULL;
 
 	return 0;
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 1db5de5..ff1dbec 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -12,6 +12,15 @@
  * Fixes to reconstruction by Jakob Østergaard" <jakob@ostenfeld.dk>
  * Various fixes by Neil Brown <neilb@cse.unsw.edu.au>
  *
+ * Changes by Peter T. Breuer <ptb@it.uc3m.es> 31/1/2003 to support
+ * bitmapped intelligence in resync:
+ *
+ *      - bitmap marked during normal i/o
+ *      - bitmap used to skip nondirty blocks during sync
+ *
+ * Additions to bitmap code, (C) 2003-2004 Paul Clements, SteelEye Technology:
+ * - persistent bitmap code
+ *
  * 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)
@@ -22,7 +31,16 @@
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include "dm-bio-list.h"
 #include <linux/raid/raid1.h>
+#include <linux/raid/bitmap.h>
+
+#define DEBUG 0
+#if DEBUG
+#define PRINTK(x...) printk(x)
+#else
+#define PRINTK(x...)
+#endif
 
 /*
  * Number of guaranteed r1bios in case of extreme VM load:
@@ -287,9 +305,11 @@
 	/*
 	 * this branch is our 'one mirror IO has finished' event handler:
 	 */
-	if (!uptodate)
+	if (!uptodate) {
 		md_error(r1_bio->mddev, conf->mirrors[mirror].rdev);
-	else
+		/* an I/O failed, we can't clear the bitmap */
+		set_bit(R1BIO_Degraded, &r1_bio->state);
+	} else
 		/*
 		 * Set R1BIO_Uptodate in our master bio, so that
 		 * we will return a good error code for to the higher
@@ -309,6 +329,10 @@
 	 * already.
 	 */
 	if (atomic_dec_and_test(&r1_bio->remaining)) {
+		/* 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));
 		md_write_end(r1_bio->mddev);
 		raid_end_bio_io(r1_bio);
 	}
@@ -458,7 +482,10 @@
 
 static void raid1_unplug(request_queue_t *q)
 {
-	unplug_slaves(q->queuedata);
+	mddev_t *mddev = q->queuedata;
+
+	unplug_slaves(mddev);
+	md_wakeup_thread(mddev->thread);
 }
 
 static int raid1_issue_flush(request_queue_t *q, struct gendisk *disk,
@@ -501,16 +528,16 @@
 {
 	spin_lock_irq(&conf->resync_lock);
 	wait_event_lock_irq(conf->wait_idle, !waitqueue_active(&conf->wait_resume),
-			    conf->resync_lock, unplug_slaves(conf->mddev));
+			    conf->resync_lock, raid1_unplug(conf->mddev->queue));
 	
 	if (!conf->barrier++) {
 		wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
-				    conf->resync_lock, unplug_slaves(conf->mddev));
+				    conf->resync_lock, raid1_unplug(conf->mddev->queue));
 		if (conf->nr_pending)
 			BUG();
 	}
 	wait_event_lock_irq(conf->wait_resume, conf->barrier < RESYNC_DEPTH,
-			    conf->resync_lock, unplug_slaves(conf->mddev));
+			    conf->resync_lock, raid1_unplug(conf->mddev->queue));
 	conf->next_resync = sect;
 	spin_unlock_irq(&conf->resync_lock);
 }
@@ -522,14 +549,20 @@
 	mirror_info_t *mirror;
 	r1bio_t *r1_bio;
 	struct bio *read_bio;
-	int i, disks;
+	int i, targets = 0, disks;
 	mdk_rdev_t *rdev;
+	struct bitmap *bitmap = mddev->bitmap;
+	unsigned long flags;
+	struct bio_list bl;
+
 
 	/*
 	 * Register the new request and wait if the reconstruction
 	 * thread has put up a bar for new requests.
 	 * Continue immediately if no resync is active currently.
 	 */
+	md_write_start(mddev, bio); /* wait on superblock update early */
+
 	spin_lock_irq(&conf->resync_lock);
 	wait_event_lock_irq(conf->wait_resume, !conf->barrier, conf->resync_lock, );
 	conf->nr_pending++;
@@ -552,7 +585,7 @@
 
 	r1_bio->master_bio = bio;
 	r1_bio->sectors = bio->bi_size >> 9;
-
+	r1_bio->state = 0;
 	r1_bio->mddev = mddev;
 	r1_bio->sector = bio->bi_sector;
 
@@ -595,6 +628,13 @@
 	 * bios[x] to bio
 	 */
 	disks = conf->raid_disks;
+#if 0
+	{ static int first=1;
+	if (first) printk("First Write sector %llu disks %d\n",
+			  (unsigned long long)r1_bio->sector, disks);
+	first = 0;
+	}
+#endif
 	rcu_read_lock();
 	for (i = 0;  i < disks; i++) {
 		if ((rdev=conf->mirrors[i].rdev) != NULL &&
@@ -605,13 +645,21 @@
 				r1_bio->bios[i] = NULL;
 			} else
 				r1_bio->bios[i] = bio;
+			targets++;
 		} else
 			r1_bio->bios[i] = NULL;
 	}
 	rcu_read_unlock();
 
-	atomic_set(&r1_bio->remaining, 1);
-	md_write_start(mddev);
+	if (targets < conf->raid_disks) {
+		/* array is degraded, we will not clear the bitmap
+		 * on I/O completion (see raid1_end_write_request) */
+		set_bit(R1BIO_Degraded, &r1_bio->state);
+	}
+
+	atomic_set(&r1_bio->remaining, 0);
+
+	bio_list_init(&bl);
 	for (i = 0; i < disks; i++) {
 		struct bio *mbio;
 		if (!r1_bio->bios[i])
@@ -627,13 +675,22 @@
 		mbio->bi_private = r1_bio;
 
 		atomic_inc(&r1_bio->remaining);
-		generic_make_request(mbio);
+
+		bio_list_add(&bl, mbio);
 	}
 
-	if (atomic_dec_and_test(&r1_bio->remaining)) {
-		md_write_end(mddev);
-		raid_end_bio_io(r1_bio);
-	}
+	bitmap_startwrite(bitmap, bio->bi_sector, r1_bio->sectors);
+	spin_lock_irqsave(&conf->device_lock, flags);
+	bio_list_merge(&conf->pending_bio_list, &bl);
+	bio_list_init(&bl);
+
+	blk_plug_device(mddev->queue);
+	spin_unlock_irqrestore(&conf->device_lock, flags);
+
+#if 0
+	while ((bio = bio_list_pop(&bl)) != NULL)
+		generic_make_request(bio);
+#endif
 
 	return 0;
 }
@@ -714,7 +771,7 @@
 {
 	spin_lock_irq(&conf->resync_lock);
 	wait_event_lock_irq(conf->wait_resume, !conf->barrier,
-			    conf->resync_lock, 	unplug_slaves(conf->mddev));
+			    conf->resync_lock, 	raid1_unplug(conf->mddev->queue));
 	spin_unlock_irq(&conf->resync_lock);
 
 	if (conf->barrier) BUG();
@@ -754,9 +811,12 @@
 {
 	conf_t *conf = mddev->private;
 	int found = 0;
-	int mirror;
+	int mirror = 0;
 	mirror_info_t *p;
 
+	if (rdev->saved_raid_disk >= 0 &&
+	    conf->mirrors[rdev->saved_raid_disk].rdev == NULL)
+		mirror = rdev->saved_raid_disk;
 	for (mirror=0; mirror < mddev->raid_disks; mirror++)
 		if ( !(p=conf->mirrors+mirror)->rdev) {
 
@@ -773,6 +833,8 @@
 			p->head_position = 0;
 			rdev->raid_disk = mirror;
 			found = 1;
+			if (rdev->saved_raid_disk != mirror)
+				conf->fullsync = 1;
 			p->rdev = rdev;
 			break;
 		}
@@ -828,10 +890,11 @@
 	 * or re-read if the read failed.
 	 * We don't do much here, just schedule handling by raid1d
 	 */
-	if (!uptodate)
+	if (!uptodate) {
 		md_error(r1_bio->mddev,
 			 conf->mirrors[r1_bio->read_disk].rdev);
-	else
+		set_bit(R1BIO_Degraded, &r1_bio->state);
+	} else
 		set_bit(R1BIO_Uptodate, &r1_bio->state);
 	rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev);
 	reschedule_retry(r1_bio);
@@ -855,8 +918,10 @@
 			mirror = i;
 			break;
 		}
-	if (!uptodate)
+	if (!uptodate) {
 		md_error(mddev, conf->mirrors[mirror].rdev);
+		set_bit(R1BIO_Degraded, &r1_bio->state);
+	}
 	update_head_pos(mirror, r1_bio);
 
 	if (atomic_dec_and_test(&r1_bio->remaining)) {
@@ -876,6 +941,9 @@
 
 	bio = r1_bio->bios[r1_bio->read_disk];
 
+/*
+	if (r1_bio->sector == 0) printk("First sync write startss\n");
+*/
 	/*
 	 * schedule writes
 	 */
@@ -903,10 +971,12 @@
 		atomic_inc(&conf->mirrors[i].rdev->nr_pending);
 		atomic_inc(&r1_bio->remaining);
 		md_sync_acct(conf->mirrors[i].rdev->bdev, wbio->bi_size >> 9);
+
 		generic_make_request(wbio);
 	}
 
 	if (atomic_dec_and_test(&r1_bio->remaining)) {
+		/* if we're here, all write(s) have completed, so clean up */
 		md_done_sync(mddev, r1_bio->sectors, 1);
 		put_buf(r1_bio);
 	}
@@ -931,11 +1001,30 @@
 	mdk_rdev_t *rdev;
 
 	md_check_recovery(mddev);
-	md_handle_safemode(mddev);
 	
 	for (;;) {
 		char b[BDEVNAME_SIZE];
 		spin_lock_irqsave(&conf->device_lock, flags);
+
+		if (conf->pending_bio_list.head) {
+			bio = bio_list_get(&conf->pending_bio_list);
+			blk_remove_plug(mddev->queue);
+			spin_unlock_irqrestore(&conf->device_lock, flags);
+			/* flush any pending bitmap writes to disk before proceeding w/ I/O */
+			if (bitmap_unplug(mddev->bitmap) != 0)
+				printk("%s: bitmap file write failed!\n", mdname(mddev));
+
+			while (bio) { /* submit pending writes */
+				struct bio *next = bio->bi_next;
+				bio->bi_next = NULL;
+				generic_make_request(bio);
+				bio = next;
+			}
+			unplug = 1;
+
+			continue;
+		}
+
 		if (list_empty(head))
 			break;
 		r1_bio = list_entry(head->prev, r1bio_t, retry_list);
@@ -1009,7 +1098,7 @@
  * that can be installed to exclude normal IO requests.
  */
 
-static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
+static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
 {
 	conf_t *conf = mddev_to_conf(mddev);
 	mirror_info_t *mirror;
@@ -1019,17 +1108,43 @@
 	int disk;
 	int i;
 	int write_targets = 0;
+	int sync_blocks;
 
 	if (!conf->r1buf_pool)
+	{
+/*
+		printk("sync start - bitmap %p\n", mddev->bitmap);
+*/
 		if (init_resync(conf))
-			return -ENOMEM;
+			return 0;
+	}
 
 	max_sector = mddev->size << 1;
 	if (sector_nr >= max_sector) {
+		/* If we aborted, we need to abort the
+		 * sync on the 'current' bitmap chunk (there will
+		 * only be one in raid1 resync.
+		 * We can find the current addess in mddev->curr_resync
+		 */
+		if (!conf->fullsync) {
+			if (mddev->curr_resync < max_sector)
+				bitmap_end_sync(mddev->bitmap,
+						mddev->curr_resync,
+						&sync_blocks, 1);
+			bitmap_close_sync(mddev->bitmap);
+		}
+		if (mddev->curr_resync >= max_sector)
+			conf->fullsync = 0;
 		close_sync(conf);
 		return 0;
 	}
 
+	if (!conf->fullsync &&
+	    !bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks)) {
+		/* We can skip this block, and probably several more */
+		*skipped = 1;
+		return sync_blocks;
+	}
 	/*
 	 * If there is non-resync activity waiting for us then
 	 * put in a delay to throttle resync.
@@ -1068,6 +1183,7 @@
 
 	r1_bio->mddev = mddev;
 	r1_bio->sector = sector_nr;
+	r1_bio->state = 0;
 	set_bit(R1BIO_IsSync, &r1_bio->state);
 	r1_bio->read_disk = disk;
 
@@ -1102,18 +1218,24 @@
 		bio->bi_bdev = conf->mirrors[i].rdev->bdev;
 		bio->bi_private = r1_bio;
 	}
+
+	if (write_targets + 1 < conf->raid_disks)
+		/* array degraded, can't clear bitmap */
+		set_bit(R1BIO_Degraded, &r1_bio->state);
+
 	if (write_targets == 0) {
 		/* There is nowhere to write, so all non-sync
 		 * drives must be failed - so we are finished
 		 */
-		int rv = max_sector - sector_nr;
-		md_done_sync(mddev, rv, 1);
+		sector_t rv = max_sector - sector_nr;
+		*skipped = 1;
 		put_buf(r1_bio);
 		rdev_dec_pending(conf->mirrors[disk].rdev, mddev);
 		return rv;
 	}
 
 	nr_sectors = 0;
+	sync_blocks = 0;
 	do {
 		struct page *page;
 		int len = PAGE_SIZE;
@@ -1121,6 +1243,17 @@
 			len = (max_sector - sector_nr) << 9;
 		if (len == 0)
 			break;
+		if (!conf->fullsync) {
+			if (sync_blocks == 0) {
+				if (!bitmap_start_sync(mddev->bitmap,
+						       sector_nr, &sync_blocks))
+					break;
+				if (sync_blocks < (PAGE_SIZE>>9))
+					BUG();
+				if (len > (sync_blocks<<9)) len = sync_blocks<<9;
+			}
+		}
+
 		for (i=0 ; i < conf->raid_disks; i++) {
 			bio = r1_bio->bios[i];
 			if (bio->bi_end_io) {
@@ -1143,6 +1276,7 @@
 		}
 		nr_sectors += len>>9;
 		sector_nr += len>>9;
+		sync_blocks -= (len>>9);
 	} while (r1_bio->bios[disk]->bi_vcnt < RESYNC_PAGES);
  bio_full:
 	bio = r1_bio->bios[disk];
@@ -1231,6 +1365,9 @@
 	init_waitqueue_head(&conf->wait_idle);
 	init_waitqueue_head(&conf->wait_resume);
 
+	bio_list_init(&conf->pending_bio_list);
+	bio_list_init(&conf->flushing_bio_list);
+
 	if (!conf->working_disks) {
 		printk(KERN_ERR "raid1: no operational mirrors for %s\n",
 			mdname(mddev));
@@ -1259,16 +1396,15 @@
 	conf->last_used = j;
 
 
-
-	{
-		mddev->thread = md_register_thread(raid1d, mddev, "%s_raid1");
-		if (!mddev->thread) {
-			printk(KERN_ERR 
-				"raid1: couldn't allocate thread for %s\n", 
-				mdname(mddev));
-			goto out_free_conf;
-		}
+	mddev->thread = md_register_thread(raid1d, mddev, "%s_raid1");
+	if (!mddev->thread) {
+		printk(KERN_ERR
+		       "raid1: couldn't allocate thread for %s\n",
+		       mdname(mddev));
+		goto out_free_conf;
 	}
+	if (mddev->bitmap) mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+
 	printk(KERN_INFO 
 		"raid1: raid set %s active with %d out of %d mirrors\n",
 		mdname(mddev), mddev->raid_disks - mddev->degraded, 
@@ -1291,10 +1427,8 @@
 	if (conf) {
 		if (conf->r1bio_pool)
 			mempool_destroy(conf->r1bio_pool);
-		if (conf->mirrors)
-			kfree(conf->mirrors);
-		if (conf->poolinfo)
-			kfree(conf->poolinfo);
+		kfree(conf->mirrors);
+		kfree(conf->poolinfo);
 		kfree(conf);
 		mddev->private = NULL;
 	}
@@ -1311,10 +1445,8 @@
 	blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
 	if (conf->r1bio_pool)
 		mempool_destroy(conf->r1bio_pool);
-	if (conf->mirrors)
-		kfree(conf->mirrors);
-	if (conf->poolinfo)
-		kfree(conf->poolinfo);
+	kfree(conf->mirrors);
+	kfree(conf->poolinfo);
 	kfree(conf);
 	mddev->private = NULL;
 	return 0;
@@ -1349,17 +1481,26 @@
 	 * We allocate a new r1bio_pool if we can.
 	 * Then raise a device barrier and wait until all IO stops.
 	 * Then resize conf->mirrors and swap in the new r1bio pool.
+	 *
+	 * At the same time, we "pack" the devices so that all the missing
+	 * devices have the higher raid_disk numbers.
 	 */
 	mempool_t *newpool, *oldpool;
 	struct pool_info *newpoolinfo;
 	mirror_info_t *newmirrors;
 	conf_t *conf = mddev_to_conf(mddev);
+	int cnt;
 
-	int d;
+	int d, d2;
 
-	for (d= raid_disks; d < conf->raid_disks; d++)
-		if (conf->mirrors[d].rdev)
+	if (raid_disks < conf->raid_disks) {
+		cnt=0;
+		for (d= 0; d < conf->raid_disks; d++)
+			if (conf->mirrors[d].rdev)
+				cnt++;
+		if (cnt > raid_disks)
 			return -EBUSY;
+	}
 
 	newpoolinfo = kmalloc(sizeof(*newpoolinfo), GFP_KERNEL);
 	if (!newpoolinfo)
@@ -1384,14 +1525,18 @@
 	spin_lock_irq(&conf->resync_lock);
 	conf->barrier++;
 	wait_event_lock_irq(conf->wait_idle, !conf->nr_pending,
-			    conf->resync_lock, unplug_slaves(mddev));
+			    conf->resync_lock, raid1_unplug(mddev->queue));
 	spin_unlock_irq(&conf->resync_lock);
 
 	/* ok, everything is stopped */
 	oldpool = conf->r1bio_pool;
 	conf->r1bio_pool = newpool;
-	for (d=0; d < raid_disks && d < conf->raid_disks; d++)
-		newmirrors[d] = conf->mirrors[d];
+
+	for (d=d2=0; d < conf->raid_disks; d++)
+		if (conf->mirrors[d].rdev) {
+			conf->mirrors[d].rdev->raid_disk = d2;
+			newmirrors[d2++].rdev = conf->mirrors[d].rdev;
+		}
 	kfree(conf->mirrors);
 	conf->mirrors = newmirrors;
 	kfree(conf->poolinfo);
@@ -1400,6 +1545,7 @@
 	mddev->degraded += (raid_disks - conf->raid_disks);
 	conf->raid_disks = mddev->raid_disks = raid_disks;
 
+	conf->last_used = 0; /* just make sure it is in-range */
 	spin_lock_irq(&conf->resync_lock);
 	conf->barrier--;
 	spin_unlock_irq(&conf->resync_lock);
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 3c37be6..62ebb1b 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -700,6 +700,8 @@
 		return 0;
 	}
 
+	md_write_start(mddev, bio);
+
 	/*
 	 * Register the new request and wait if the reconstruction
 	 * thread has put up a bar for new requests.
@@ -774,7 +776,7 @@
 	rcu_read_unlock();
 
 	atomic_set(&r10_bio->remaining, 1);
-	md_write_start(mddev);
+
 	for (i = 0; i < conf->copies; i++) {
 		struct bio *mbio;
 		int d = r10_bio->devs[i].devnum;
@@ -1216,7 +1218,6 @@
 	mdk_rdev_t *rdev;
 
 	md_check_recovery(mddev);
-	md_handle_safemode(mddev);
 
 	for (;;) {
 		char b[BDEVNAME_SIZE];
@@ -1319,7 +1320,7 @@
  *
  */
 
-static int sync_request(mddev_t *mddev, sector_t sector_nr, int go_faster)
+static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster)
 {
 	conf_t *conf = mddev_to_conf(mddev);
 	r10bio_t *r10_bio;
@@ -1333,7 +1334,7 @@
 
 	if (!conf->r10buf_pool)
 		if (init_resync(conf))
-			return -ENOMEM;
+			return 0;
 
  skipped:
 	max_sector = mddev->size << 1;
@@ -1341,15 +1342,15 @@
 		max_sector = mddev->resync_max_sectors;
 	if (sector_nr >= max_sector) {
 		close_sync(conf);
+		*skipped = 1;
 		return sectors_skipped;
 	}
 	if (chunks_skipped >= conf->raid_disks) {
 		/* if there has been nothing to do on any drive,
 		 * then there is nothing to do at all..
 		 */
-		sector_t sec = max_sector - sector_nr;
-		md_done_sync(mddev, sec, 1);
-		return sec + sectors_skipped;
+		*skipped = 1;
+		return (max_sector - sector_nr) + sectors_skipped;
 	}
 
 	/* make sure whole request will fit in a chunk - if chunks
@@ -1563,17 +1564,22 @@
 		}
 	}
 
+	if (sectors_skipped)
+		/* pretend they weren't skipped, it makes
+		 * no important difference in this case
+		 */
+		md_done_sync(mddev, sectors_skipped, 1);
+
 	return sectors_skipped + nr_sectors;
  giveup:
 	/* There is nowhere to write, so all non-sync
 	 * drives must be failed, so try the next chunk...
 	 */
 	{
-	int sec = max_sector - sector_nr;
+	sector_t sec = max_sector - sector_nr;
 	sectors_skipped += sec;
 	chunks_skipped ++;
 	sector_nr = max_sector;
-	md_done_sync(mddev, sec, 1);
 	goto skipped;
 	}
 }
@@ -1731,8 +1737,7 @@
 out_free_conf:
 	if (conf->r10bio_pool)
 		mempool_destroy(conf->r10bio_pool);
-	if (conf->mirrors)
-		kfree(conf->mirrors);
+	kfree(conf->mirrors);
 	kfree(conf);
 	mddev->private = NULL;
 out:
@@ -1748,8 +1753,7 @@
 	blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
 	if (conf->r10bio_pool)
 		mempool_destroy(conf->r10bio_pool);
-	if (conf->mirrors)
-		kfree(conf->mirrors);
+	kfree(conf->mirrors);
 	kfree(conf);
 	mddev->private = NULL;
 	return 0;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 3cb11ac..93a9726 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -1411,6 +1411,8 @@
 	sector_t logical_sector, last_sector;
 	struct stripe_head *sh;
 
+	md_write_start(mddev, bi);
+
 	if (bio_data_dir(bi)==WRITE) {
 		disk_stat_inc(mddev->gendisk, writes);
 		disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bi));
@@ -1423,8 +1425,7 @@
 	last_sector = bi->bi_sector + (bi->bi_size>>9);
 	bi->bi_next = NULL;
 	bi->bi_phys_segments = 1;	/* over-loaded to count active stripes */
-	if ( bio_data_dir(bi) == WRITE )
-		md_write_start(mddev);
+
 	for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) {
 		DEFINE_WAIT(w);
 		
@@ -1475,7 +1476,7 @@
 }
 
 /* FIXME go_faster isn't used */
-static int sync_request (mddev_t *mddev, sector_t sector_nr, int go_faster)
+static 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;
@@ -1498,8 +1499,8 @@
 	 * nothing we can do.
 	 */
 	if (mddev->degraded >= 1 && test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
-		int rv = (mddev->size << 1) - sector_nr;
-		md_done_sync(mddev, rv, 1);
+		sector_t rv = (mddev->size << 1) - sector_nr;
+		*skipped = 1;
 		return rv;
 	}
 
@@ -1546,7 +1547,6 @@
 	PRINTK("+++ raid5d active\n");
 
 	md_check_recovery(mddev);
-	md_handle_safemode(mddev);
 
 	handled = 0;
 	spin_lock_irq(&conf->device_lock);
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c
index 908edd7..f62ea1a 100644
--- a/drivers/md/raid6main.c
+++ b/drivers/md/raid6main.c
@@ -1570,6 +1570,8 @@
 	sector_t logical_sector, last_sector;
 	struct stripe_head *sh;
 
+	md_write_start(mddev, bi);
+
 	if (bio_data_dir(bi)==WRITE) {
 		disk_stat_inc(mddev->gendisk, writes);
 		disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bi));
@@ -1583,8 +1585,7 @@
 
 	bi->bi_next = NULL;
 	bi->bi_phys_segments = 1;	/* over-loaded to count active stripes */
-	if ( bio_data_dir(bi) == WRITE )
-		md_write_start(mddev);
+
 	for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) {
 		DEFINE_WAIT(w);
 
@@ -1634,7 +1635,7 @@
 }
 
 /* FIXME go_faster isn't used */
-static int sync_request (mddev_t *mddev, sector_t sector_nr, int go_faster)
+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;
@@ -1657,8 +1658,8 @@
 	 * nothing we can do.
 	 */
 	if (mddev->degraded >= 2 && test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
-		int rv = (mddev->size << 1) - sector_nr;
-		md_done_sync(mddev, rv, 1);
+		sector_t rv = (mddev->size << 1) - sector_nr;
+		*skipped = 1;
 		return rv;
 	}
 
@@ -1705,7 +1706,6 @@
 	PRINTK("+++ raid6d active\n");
 
 	md_check_recovery(mddev);
-	md_handle_safemode(mddev);
 
 	handled = 0;
 	spin_lock_irq(&conf->device_lock);
diff --git a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c
index 84a49d2..4adb284 100644
--- a/drivers/media/common/ir-common.c
+++ b/drivers/media/common/ir-common.c
@@ -1,5 +1,5 @@
 /*
- * $Id: ir-common.c,v 1.8 2005/02/22 12:28:40 kraxel Exp $
+ * $Id: ir-common.c,v 1.10 2005/05/22 19:23:39 nsh Exp $
  *
  * some common structs and functions to handle infrared remotes via
  * input layer ...
@@ -131,10 +131,10 @@
 	[ 18 ] = KEY_KP0,
 
 	[  0 ] = KEY_POWER,
-	[ 27 ] = KEY_LANGUAGE,  //MTS button
+//      [ 27 ] = MTS button
 	[  2 ] = KEY_TUNER,     // TV/FM
 	[ 30 ] = KEY_VIDEO,
-	[ 22 ] = KEY_INFO,      //display button
+//      [ 22 ] = display button
 	[  4 ] = KEY_VOLUMEUP,
 	[  8 ] = KEY_VOLUMEDOWN,
 	[ 12 ] = KEY_CHANNELUP,
@@ -142,7 +142,7 @@
 	[  3 ] = KEY_ZOOM,      // fullscreen
 	[ 31 ] = KEY_SUBTITLE,  // closed caption/teletext
 	[ 32 ] = KEY_SLEEP,
-	[ 41 ] = KEY_SEARCH,    //boss key
+//      [ 41 ] = boss key
 	[ 20 ] = KEY_MUTE,
 	[ 43 ] = KEY_RED,
 	[ 44 ] = KEY_GREEN,
@@ -150,17 +150,17 @@
 	[ 46 ] = KEY_BLUE,
 	[ 24 ] = KEY_KPPLUS,    //fine tune +
 	[ 25 ] = KEY_KPMINUS,   //fine tune -
-	[ 42 ] = KEY_ANGLE,     //picture in picture
-	[ 33 ] = KEY_KPDOT,
+//      [ 42 ] = picture in picture
+        [ 33 ] = KEY_KPDOT,
 	[ 19 ] = KEY_KPENTER,
-	[ 17 ] = KEY_AGAIN,     //recall
+//      [ 17 ] = recall
 	[ 34 ] = KEY_BACK,
 	[ 35 ] = KEY_PLAYPAUSE,
 	[ 36 ] = KEY_NEXT,
-	[ 37 ] = KEY_T,         //time shifting
+//      [ 37 ] = time shifting
 	[ 38 ] = KEY_STOP,
-	[ 39 ] = KEY_RECORD,
-	[ 40 ] = KEY_SHUFFLE    //snapshot
+	[ 39 ] = KEY_RECORD
+//      [ 40 ] = snapshot
 };
 EXPORT_SYMBOL_GPL(ir_codes_winfast);
 
@@ -184,18 +184,30 @@
 	[ 0x07 ] = KEY_KP7,             // 7
 	[ 0x08 ] = KEY_KP8,             // 8
 	[ 0x09 ] = KEY_KP9,             // 9
+	[ 0x0a ] = KEY_TEXT,      	// keypad asterisk as well
 	[ 0x0b ] = KEY_RED,             // red button
-	[ 0x0c ] = KEY_OPTION,          // black key without text
+	[ 0x0c ] = KEY_RADIO,           // radio
 	[ 0x0d ] = KEY_MENU,            // menu
+	[ 0x0e ] = KEY_SUBTITLE,	// also the # key
 	[ 0x0f ] = KEY_MUTE,            // mute
 	[ 0x10 ] = KEY_VOLUMEUP,        // volume +
 	[ 0x11 ] = KEY_VOLUMEDOWN,      // volume -
-	[ 0x1e ] = KEY_NEXT,            // skip >|
+	[ 0x12 ] = KEY_PREVIOUS,        // previous channel
+	[ 0x14 ] = KEY_UP,              // up
+	[ 0x15 ] = KEY_DOWN,		// down
+	[ 0x16 ] = KEY_LEFT,		// left
+	[ 0x17 ] = KEY_RIGHT,		// right
+	[ 0x18 ] = KEY_VIDEO,		// Videos
+	[ 0x19 ] = KEY_AUDIO,		// Music
+	[ 0x1a ] = KEY_MHP,		// Pictures - presume this means "Multimedia Home Platform"- no "PICTURES" key in input.h
+	[ 0x1b ] = KEY_EPG,		// Guide
+	[ 0x1c ] = KEY_TV,		// TV
+	[ 0x1e ] = KEY_NEXTSONG,        // skip >|
 	[ 0x1f ] = KEY_EXIT,            // back/exit
 	[ 0x20 ] = KEY_CHANNELUP,       // channel / program +
 	[ 0x21 ] = KEY_CHANNELDOWN,     // channel / program -
 	[ 0x22 ] = KEY_CHANNEL,         // source (old black remote)
-	[ 0x24 ] = KEY_PREVIOUS,        // replay |<
+	[ 0x24 ] = KEY_PREVIOUSSONG,    // replay |<
 	[ 0x25 ] = KEY_ENTER,           // OK
 	[ 0x26 ] = KEY_SLEEP,           // minimize (old black remote)
 	[ 0x29 ] = KEY_BLUE,            // blue key
@@ -213,6 +225,39 @@
 };
 EXPORT_SYMBOL(ir_codes_hauppauge_new);
 
+IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = {
+	[  2 ] = KEY_KP0,
+	[  1 ] = KEY_KP1,
+	[ 11 ] = KEY_KP2,
+	[ 27 ] = KEY_KP3,
+	[  5 ] = KEY_KP4,
+	[  9 ] = KEY_KP5,
+	[ 21 ] = KEY_KP6,
+	[  6 ] = KEY_KP7,
+	[ 10 ] = KEY_KP8,
+	[ 18 ] = KEY_KP9,
+
+	[  3 ] = KEY_TUNER,       // TV/FM
+	[  7 ] = KEY_SEARCH,      // scan
+	[ 28 ] = KEY_ZOOM,        // full screen
+	[ 30 ] = KEY_POWER,
+	[ 23 ] = KEY_VOLUMEDOWN,
+	[ 31 ] = KEY_VOLUMEUP,
+	[ 20 ] = KEY_CHANNELDOWN,
+	[ 22 ] = KEY_CHANNELUP,
+	[ 24 ] = KEY_MUTE,
+
+	[  0 ] = KEY_LIST,        // source
+	[ 19 ] = KEY_INFO,        // loop
+	[ 16 ] = KEY_LAST,        // +100
+	[ 13 ] = KEY_CLEAR,       // reset
+	[ 12 ] = BTN_RIGHT,       // fun++
+	[  4 ] = BTN_LEFT,        // fun--
+	[ 14 ] = KEY_GOTO,        // function
+	[ 15 ] = KEY_STOP,         // freeze
+};
+EXPORT_SYMBOL(ir_codes_pixelview);
+
 /* -------------------------------------------------------------------------- */
 
 static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir)
@@ -379,3 +424,4 @@
  * c-basic-offset: 8
  * End:
  */
+
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c
index cb826c9..c04fd11 100644
--- a/drivers/media/common/saa7146_fops.c
+++ b/drivers/media/common/saa7146_fops.c
@@ -403,7 +403,7 @@
 	.llseek		= no_llseek,
 };
 
-void vv_callback(struct saa7146_dev *dev, unsigned long status)
+static void vv_callback(struct saa7146_dev *dev, unsigned long status)
 {
 	u32 isr = status;
 	
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
index 4983e1b..01387f8 100644
--- a/drivers/media/dvb/Kconfig
+++ b/drivers/media/dvb/Kconfig
@@ -27,9 +27,9 @@
 
 comment "Supported USB Adapters"
 	depends on DVB_CORE && USB
+source "drivers/media/dvb/dvb-usb/Kconfig"
 source "drivers/media/dvb/ttusb-budget/Kconfig"
 source "drivers/media/dvb/ttusb-dec/Kconfig"
-source "drivers/media/dvb/dibusb/Kconfig"
 source "drivers/media/dvb/cinergyT2/Kconfig"
 
 comment "Supported FlexCopII (B2C2) Adapters"
diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile
index 520fc39..3c6ff16 100644
--- a/drivers/media/dvb/Makefile
+++ b/drivers/media/dvb/Makefile
@@ -2,4 +2,4 @@
 # Makefile for the kernel multimedia device drivers.
 #
 
-obj-y        := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ dibusb/ cinergyT2/
+obj-y        := dvb-core/ frontends/ ttpci/ ttusb-dec/ ttusb-budget/ b2c2/ bt8xx/ cinergyT2/ dvb-usb/
diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig
index 99bd675..fafd0ab 100644
--- a/drivers/media/dvb/b2c2/Kconfig
+++ b/drivers/media/dvb/b2c2/Kconfig
@@ -6,6 +6,7 @@
 	select DVB_MT312
 	select DVB_NXT2002
 	select DVB_STV0297
+	select DVB_BCM3510
 	help
 	  Support for the digital TV receiver chip made by B2C2 Inc. included in
 	  Technisats PCI cards and USB boxes.
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
index 71be400..0410cc9 100644
--- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
+++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c
@@ -10,6 +10,7 @@
 #include "stv0299.h"
 #include "mt352.h"
 #include "nxt2002.h"
+#include "bcm3510.h"
 #include "stv0297.h"
 #include "mt312.h"
 
@@ -285,21 +286,25 @@
 }
 
 static struct mt352_config samsung_tdtc9251dh0_config = {
-
 	.demod_address = 0x0f,
-	.demod_init = samsung_tdtc9251dh0_demod_init,
-	.pll_set = samsung_tdtc9251dh0_pll_set,
+	.demod_init    = samsung_tdtc9251dh0_demod_init,
+	.pll_set       = samsung_tdtc9251dh0_pll_set,
 };
 
-static int nxt2002_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
+static int flexcop_fe_request_firmware(struct dvb_frontend* fe, const struct firmware **fw, char* name)
 {
 	struct flexcop_device *fc = fe->dvb->priv;
 	return request_firmware(fw, name, fc->dev);
 }
 
 static struct nxt2002_config samsung_tbmv_config = {
-	.demod_address = 0x0a,
-	.request_firmware = nxt2002_request_firmware,
+	.demod_address    = 0x0a,
+	.request_firmware = flexcop_fe_request_firmware,
+};
+
+static struct bcm3510_config air2pc_atsc_first_gen_config = {
+	.demod_address    = 0x0f,
+	.request_firmware = flexcop_fe_request_firmware,
 };
 
 static int skystar23_samsung_tbdu18132_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params)
@@ -354,11 +359,16 @@
 		fc->dev_type          = FC_AIR_DVB;
 		info("found the mt352 at i2c address: 0x%02x",samsung_tdtc9251dh0_config.demod_address);
 	} else
-	/* try the air atsc (nxt2002) */
+	/* try the air atsc 2nd generation (nxt2002) */
 	if ((fc->fe = nxt2002_attach(&samsung_tbmv_config, &fc->i2c_adap)) != NULL) {
-		fc->dev_type          = FC_AIR_ATSC;
+		fc->dev_type          = FC_AIR_ATSC2;
 		info("found the nxt2002 at i2c address: 0x%02x",samsung_tbmv_config.demod_address);
 	} else
+	/* try the air atsc 1nd generation (bcm3510)/panasonic ct10s */
+	if ((fc->fe = bcm3510_attach(&air2pc_atsc_first_gen_config, &fc->i2c_adap)) != NULL) {
+		fc->dev_type          = FC_AIR_ATSC1;
+		info("found the bcm3510 at i2c address: 0x%02x",air2pc_atsc_first_gen_config.demod_address);
+	} else
 	/* try the cable dvb (stv0297) */
 	if ((fc->fe = stv0297_attach(&alps_tdee4_stv0297_config, &fc->i2c_adap, 0xf8)) != NULL) {
 		fc->dev_type                        = FC_CABLE;
diff --git a/drivers/media/dvb/b2c2/flexcop-misc.c b/drivers/media/dvb/b2c2/flexcop-misc.c
index 19e06da..2308254 100644
--- a/drivers/media/dvb/b2c2/flexcop-misc.c
+++ b/drivers/media/dvb/b2c2/flexcop-misc.c
@@ -45,11 +45,12 @@
 
 const char *flexcop_device_names[] = {
 	"Unkown device",
-	"AirStar 2 DVB-T",
-	"AirStar 2 ATSC",
-	"SkyStar 2 DVB-S",
-	"SkyStar 2 DVB-S (old version)",
-	"CableStar 2 DVB-C",
+	"Air2PC/AirStar 2 DVB-T",
+	"Air2PC/AirStar 2 ATSC 1st generation",
+	"Air2PC/AirStar 2 ATSC 2nd generation",
+	"Sky2PC/SkyStar 2 DVB-S",
+	"Sky2PC/SkyStar 2 DVB-S (old version)",
+	"Cable2PC/CableStar 2 DVB-C",
 };
 
 const char *flexcop_bus_names[] = {
diff --git a/drivers/media/dvb/b2c2/flexcop-reg.h b/drivers/media/dvb/b2c2/flexcop-reg.h
index 5e131be..75b50f2 100644
--- a/drivers/media/dvb/b2c2/flexcop-reg.h
+++ b/drivers/media/dvb/b2c2/flexcop-reg.h
@@ -21,7 +21,8 @@
 typedef enum {
 	FC_UNK = 0,
 	FC_AIR_DVB,
-	FC_AIR_ATSC,
+	FC_AIR_ATSC1,
+	FC_AIR_ATSC2,
 	FC_SKY,
 	FC_SKY_OLD,
 	FC_CABLE,
diff --git a/drivers/media/dvb/dibusb/Kconfig b/drivers/media/dvb/dibusb/Kconfig
deleted file mode 100644
index 74dfc73..0000000
--- a/drivers/media/dvb/dibusb/Kconfig
+++ /dev/null
@@ -1,62 +0,0 @@
-config DVB_DIBUSB
-	tristate "DiBcom USB DVB-T devices (see help for a complete device list)"
-	depends on DVB_CORE && USB
-	select FW_LOADER
-	select DVB_DIB3000MB
-	select DVB_DIB3000MC
-	select DVB_MT352
-	help
-	  Support for USB 1.1 and 2.0 DVB-T devices based on reference designs made by
-	  DiBcom (http://www.dibcom.fr) and C&E.
-
-	  Devices supported by this driver:
-
-	    TwinhanDTV USB-Ter (VP7041)
-		TwinhanDTV Magic Box (VP7041e)
-	    KWorld/JetWay/ADSTech V-Stream XPERT DTV - DVB-T USB1.1 and USB2.0
-	    Hama DVB-T USB-Box
-	    DiBcom reference devices (non-public)
-	    Ultima Electronic/Artec T1 USB TVBOX
-	    Compro Videomate DVB-U2000 - DVB-T USB
-	    Grandtec DVB-T USB
-	    Avermedia AverTV DVBT USB
-	    Artec T1 USB1.1 and USB2.0 boxes
-	    Yakumo/Typhoon DVB-T USB2.0
-	    Hanftek UMT-010 USB2.0
-	    Hauppauge WinTV NOVA-T USB2
-
-	  The VP7041 seems to be identical to "CTS Portable" (Chinese
-	  Television System).
-
-	  These devices can be understood as budget ones, they "only" deliver
-	  (a part of) the MPEG2 transport stream.
-
-	  A firmware is needed to get the device working. See Documentation/dvb/README.dibusb
-	  details.
-
-	  Say Y if you own such a device and want to use it. You should build it as
-	  a module.
-
-config DVB_DIBUSB_MISDESIGNED_DEVICES
-	bool "Enable support for some misdesigned (see help) devices, which identify with wrong IDs"
-	depends on DVB_DIBUSB
-	help
-	  Somehow Artec/Ultima Electronic forgot to program the eeprom of some of their
-	  USB1.1/USB2.0 devices.
-	  So comes that they identify with the default Vendor and Product ID of the Cypress
-	  CY7C64613 (AN2235) or Cypress FX2.
-
-	  Affected device IDs:
-	    0x0574:0x2235 (Artec T1 USB1.1, cold)
-	    0x04b4:0x8613 (Artec T1 USB2.0, cold)
-	    0x0574:0x1002 (Artec T1 USB2.0, warm)
-	    0x0574:0x2131 (aged DiBcom USB1.1 test device)
-
-	  Say Y if your device has one of the mentioned IDs.
-
-config DVB_DIBCOM_DEBUG
-	bool "Enable extended debug support for DiBcom USB device"
-	depends on DVB_DIBUSB
-	help
-	  Say Y if you want to enable debuging. See modinfo dvb-dibusb for
-	  debug levels.
diff --git a/drivers/media/dvb/dibusb/Makefile b/drivers/media/dvb/dibusb/Makefile
deleted file mode 100644
index e941c50..0000000
--- a/drivers/media/dvb/dibusb/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-dvb-dibusb-objs = dvb-dibusb-core.o \
-	dvb-dibusb-dvb.o \
-	dvb-dibusb-fe-i2c.o \
-	dvb-dibusb-firmware.o \
-	dvb-dibusb-remote.o \
-	dvb-dibusb-usb.o \
-	dvb-fe-dtt200u.o
-
-obj-$(CONFIG_DVB_DIBUSB) += dvb-dibusb.o
-
-EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-core.c b/drivers/media/dvb/dibusb/dvb-dibusb-core.c
deleted file mode 100644
index 26235f9..0000000
--- a/drivers/media/dvb/dibusb/dvb-dibusb-core.c
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
- * Driver for mobile USB Budget DVB-T devices based on reference 
- * design made by DiBcom (http://www.dibcom.fr/)
- * 
- * dvb-dibusb-core.c
- * 
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- * 
- * based on GPL code from DiBcom, which has
- * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.fr)
- *
- * Remote control code added by David Matthews (dm@prolingua.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, version 2.
- *
- * Acknowledgements
- * 
- *  Amaury Demol (ademol@dibcom.fr) from DiBcom for providing specs and driver
- *  sources, on which this driver (and the dib3000mb/mc/p frontends) are based.
- * 
- * see Documentation/dvb/README.dibusb for more information
- */
-#include "dvb-dibusb.h"
-
-#include <linux/moduleparam.h>
-
-/* debug */
-int dvb_dibusb_debug;
-module_param_named(debug, dvb_dibusb_debug,  int, 0644);
-
-#ifdef CONFIG_DVB_DIBCOM_DEBUG
-#define DBSTATUS ""
-#else
-#define DBSTATUS " (debugging is not enabled)"
-#endif
-MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=alotmore,8=ts,16=err,32=rc (|-able))." DBSTATUS);
-#undef DBSTATUS
-
-static int pid_parse;
-module_param(pid_parse, int, 0644);
-MODULE_PARM_DESC(pid_parse, "enable pid parsing (filtering) when running at USB2.0");
-
-static int rc_query_interval = 100;
-module_param(rc_query_interval, int, 0644);
-MODULE_PARM_DESC(rc_query_interval, "interval in msecs for remote control query (default: 100; min: 40)");
-
-static int rc_key_repeat_count = 2;
-module_param(rc_key_repeat_count, int, 0644);
-MODULE_PARM_DESC(rc_key_repeat_count, "how many key repeats will be dropped before passing the key event again (default: 2)");
-
-/* Vendor IDs */
-#define USB_VID_ADSTECH						0x06e1
-#define USB_VID_ANCHOR						0x0547
-#define USB_VID_AVERMEDIA					0x14aa
-#define USB_VID_COMPRO						0x185b
-#define USB_VID_COMPRO_UNK					0x145f
-#define USB_VID_CYPRESS						0x04b4
-#define USB_VID_DIBCOM						0x10b8
-#define USB_VID_EMPIA						0xeb1a
-#define USB_VID_GRANDTEC					0x5032
-#define USB_VID_HANFTEK						0x15f4
-#define USB_VID_HAUPPAUGE					0x2040
-#define USB_VID_HYPER_PALTEK				0x1025
-#define USB_VID_IMC_NETWORKS				0x13d3
-#define USB_VID_TWINHAN						0x1822
-#define USB_VID_ULTIMA_ELECTRONIC			0x05d8
-
-/* Product IDs */
-#define USB_PID_ADSTECH_USB2_COLD			0xa333
-#define USB_PID_ADSTECH_USB2_WARM			0xa334
-#define USB_PID_AVERMEDIA_DVBT_USB_COLD		0x0001
-#define USB_PID_AVERMEDIA_DVBT_USB_WARM		0x0002
-#define USB_PID_COMPRO_DVBU2000_COLD		0xd000
-#define USB_PID_COMPRO_DVBU2000_WARM		0xd001
-#define USB_PID_COMPRO_DVBU2000_UNK_COLD	0x010c
-#define USB_PID_COMPRO_DVBU2000_UNK_WARM	0x010d
-#define USB_PID_DIBCOM_MOD3000_COLD			0x0bb8
-#define USB_PID_DIBCOM_MOD3000_WARM			0x0bb9
-#define USB_PID_DIBCOM_MOD3001_COLD			0x0bc6
-#define USB_PID_DIBCOM_MOD3001_WARM			0x0bc7
-#define USB_PID_DIBCOM_ANCHOR_2135_COLD		0x2131
-#define USB_PID_GRANDTEC_DVBT_USB_COLD		0x0fa0
-#define USB_PID_GRANDTEC_DVBT_USB_WARM		0x0fa1
-#define USB_PID_KWORLD_VSTREAM_COLD			0x17de
-#define USB_PID_KWORLD_VSTREAM_WARM			0x17df
-#define USB_PID_TWINHAN_VP7041_COLD			0x3201
-#define USB_PID_TWINHAN_VP7041_WARM			0x3202
-#define USB_PID_ULTIMA_TVBOX_COLD			0x8105
-#define USB_PID_ULTIMA_TVBOX_WARM			0x8106
-#define USB_PID_ULTIMA_TVBOX_AN2235_COLD	0x8107
-#define USB_PID_ULTIMA_TVBOX_AN2235_WARM	0x8108
-#define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD	0x2235
-#define USB_PID_ULTIMA_TVBOX_USB2_COLD		0x8109
-#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD	0x8613
-#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM	0x1002
-#define USB_PID_UNK_HYPER_PALTEK_COLD		0x005e
-#define USB_PID_UNK_HYPER_PALTEK_WARM		0x005f
-#define USB_PID_HANFTEK_UMT_010_COLD		0x0001
-#define USB_PID_HANFTEK_UMT_010_WARM		0x0015
-#define USB_PID_YAKUMO_DTT200U_COLD			0x0201
-#define USB_PID_YAKUMO_DTT200U_WARM			0x0301
-#define USB_PID_WINTV_NOVA_T_USB2_COLD		0x9300
-#define USB_PID_WINTV_NOVA_T_USB2_WARM		0x9301
-
-/* USB Driver stuff
- * table of devices that this driver is working with
- *
- * ATTENTION: Never ever change the order of this table, the particular 
- * devices depend on this order 
- *
- * Each entry is used as a reference in the device_struct. Currently this is 
- * the only non-redundant way of assigning USB ids to actual devices I'm aware 
- * of, because there is only one place in the code where the assignment of 
- * vendor and product id is done, here.
- */
-static struct usb_device_id dib_table [] = {
-/* 00 */	{ USB_DEVICE(USB_VID_AVERMEDIA,		USB_PID_AVERMEDIA_DVBT_USB_COLD)},
-/* 01 */	{ USB_DEVICE(USB_VID_AVERMEDIA,		USB_PID_AVERMEDIA_DVBT_USB_WARM)},
-/* 02 */	{ USB_DEVICE(USB_VID_AVERMEDIA,		USB_PID_YAKUMO_DTT200U_COLD) },
-/* 03 */	{ USB_DEVICE(USB_VID_AVERMEDIA,		USB_PID_YAKUMO_DTT200U_WARM) },
-
-/* 04 */	{ USB_DEVICE(USB_VID_COMPRO,		USB_PID_COMPRO_DVBU2000_COLD) },
-/* 05 */	{ USB_DEVICE(USB_VID_COMPRO,		USB_PID_COMPRO_DVBU2000_WARM) },
-/* 06 */	{ USB_DEVICE(USB_VID_COMPRO_UNK,	USB_PID_COMPRO_DVBU2000_UNK_COLD) },
-/* 07 */	{ USB_DEVICE(USB_VID_DIBCOM,		USB_PID_DIBCOM_MOD3000_COLD) },
-/* 08 */	{ USB_DEVICE(USB_VID_DIBCOM,		USB_PID_DIBCOM_MOD3000_WARM) },
-/* 09 */	{ USB_DEVICE(USB_VID_DIBCOM,		USB_PID_DIBCOM_MOD3001_COLD) },
-/* 10 */	{ USB_DEVICE(USB_VID_DIBCOM,		USB_PID_DIBCOM_MOD3001_WARM) },
-/* 11 */	{ USB_DEVICE(USB_VID_EMPIA,			USB_PID_KWORLD_VSTREAM_COLD) },
-/* 12 */	{ USB_DEVICE(USB_VID_EMPIA,			USB_PID_KWORLD_VSTREAM_WARM) },
-/* 13 */	{ USB_DEVICE(USB_VID_GRANDTEC,		USB_PID_GRANDTEC_DVBT_USB_COLD) },
-/* 14 */	{ USB_DEVICE(USB_VID_GRANDTEC,		USB_PID_GRANDTEC_DVBT_USB_WARM) },
-/* 15 */	{ USB_DEVICE(USB_VID_GRANDTEC,		USB_PID_DIBCOM_MOD3000_COLD) },
-/* 16 */	{ USB_DEVICE(USB_VID_GRANDTEC,		USB_PID_DIBCOM_MOD3000_WARM) },
-/* 17 */	{ USB_DEVICE(USB_VID_HYPER_PALTEK,	USB_PID_UNK_HYPER_PALTEK_COLD) },
-/* 18 */	{ USB_DEVICE(USB_VID_HYPER_PALTEK,	USB_PID_UNK_HYPER_PALTEK_WARM) },
-/* 19 */	{ USB_DEVICE(USB_VID_IMC_NETWORKS,	USB_PID_TWINHAN_VP7041_COLD) },
-/* 20 */	{ USB_DEVICE(USB_VID_IMC_NETWORKS,	USB_PID_TWINHAN_VP7041_WARM) },
-/* 21 */	{ USB_DEVICE(USB_VID_TWINHAN, 		USB_PID_TWINHAN_VP7041_COLD) },
-/* 22 */	{ USB_DEVICE(USB_VID_TWINHAN, 		USB_PID_TWINHAN_VP7041_WARM) },
-/* 23 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) },
-/* 24 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) },
-/* 25 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) },
-/* 26 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) },
-/* 27 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC,	USB_PID_ULTIMA_TVBOX_USB2_COLD) },
-	
-/* 28 */	{ USB_DEVICE(USB_VID_HANFTEK,		USB_PID_HANFTEK_UMT_010_COLD) },
-/* 29 */	{ USB_DEVICE(USB_VID_HANFTEK,		USB_PID_HANFTEK_UMT_010_WARM) },
-
-/* 30 */	{ USB_DEVICE(USB_VID_HAUPPAUGE,		USB_PID_WINTV_NOVA_T_USB2_COLD) },
-/* 31 */	{ USB_DEVICE(USB_VID_HAUPPAUGE,		USB_PID_WINTV_NOVA_T_USB2_WARM) },
-/* 32 */	{ USB_DEVICE(USB_VID_ADSTECH,		USB_PID_ADSTECH_USB2_COLD) },
-/* 33 */	{ USB_DEVICE(USB_VID_ADSTECH,		USB_PID_ADSTECH_USB2_WARM) },
-/* 
- * activate the following define when you have one of the devices and want to 
- * build it from build-2.6 in dvb-kernel
- */
-// #define CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES
-#ifdef CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES
-/* 34 */	{ USB_DEVICE(USB_VID_ANCHOR,		USB_PID_ULTIMA_TVBOX_ANCHOR_COLD) },
-/* 35 */	{ USB_DEVICE(USB_VID_CYPRESS,		USB_PID_ULTIMA_TVBOX_USB2_FX_COLD) },
-/* 36 */	{ USB_DEVICE(USB_VID_ANCHOR,		USB_PID_ULTIMA_TVBOX_USB2_FX_WARM) },
-/* 37 */	{ USB_DEVICE(USB_VID_ANCHOR,		USB_PID_DIBCOM_ANCHOR_2135_COLD) },
-#endif
-			{ }		/* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, dib_table);
-
-static struct dibusb_usb_controller dibusb_usb_ctrl[] = {
-	{ .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 },
-	{ .name = "Cypress AN2235", .cpu_cs_register = 0x7f92 },
-	{ .name = "Cypress FX2",    .cpu_cs_register = 0xe600 },
-};
-
-struct dibusb_tuner dibusb_tuner[] = {
-	{ DIBUSB_TUNER_CABLE_THOMSON, 
-	  0x61 
-	},
-	{ DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5,
-	  0x60 
-	},
-	{ DIBUSB_TUNER_CABLE_LG_TDTP_E102P,
-	  0x61
-	},
-	{ DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5,
-	  0x60
-	},
-};
-
-static struct dibusb_demod dibusb_demod[] = {
-	{ DIBUSB_DIB3000MB,
-	  16,
-	  { 0x8, 0 },
-	},
-	{ DIBUSB_DIB3000MC,
-	  32,
-	  { 0x9, 0xa, 0xb, 0xc }, 
-	},
-	{ DIBUSB_MT352,
-	  254,
-	  { 0xf, 0 }, 
-	},
-	{ DTT200U_FE,
-	  8,
-	  { 0xff,0 }, /* there is no i2c bus in this device */
-	}
-};
-
-static struct dibusb_device_class dibusb_device_classes[] = {
-	{ .id = DIBUSB1_1, .usb_ctrl = &dibusb_usb_ctrl[0],
-	  .firmware = "dvb-dibusb-5.0.0.11.fw",
-	  .pipe_cmd = 0x01, .pipe_data = 0x02, 
-	  .urb_count = 7, .urb_buffer_size = 4096,
-	  DIBUSB_RC_NEC_PROTOCOL,
-	  &dibusb_demod[DIBUSB_DIB3000MB],
-	  &dibusb_tuner[DIBUSB_TUNER_CABLE_THOMSON],
-	},
-	{ DIBUSB1_1_AN2235, &dibusb_usb_ctrl[1],
-	  "dvb-dibusb-an2235-1.fw",
-	  0x01, 0x02, 
-	  7, 4096,
-	  DIBUSB_RC_NEC_PROTOCOL,
-	  &dibusb_demod[DIBUSB_DIB3000MB],
-	  &dibusb_tuner[DIBUSB_TUNER_CABLE_THOMSON],
-	},
-	{ DIBUSB2_0,&dibusb_usb_ctrl[2],
-	  "dvb-dibusb-6.0.0.5.fw",
-	  0x01, 0x06, 
-	  7, 4096,
-	  DIBUSB_RC_NEC_PROTOCOL,
-	  &dibusb_demod[DIBUSB_DIB3000MC],
-	  &dibusb_tuner[DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5],
-	},
-	{ UMT2_0, &dibusb_usb_ctrl[2],
-	  "dvb-dibusb-umt-2.fw",
-	  0x01, 0x06,
-	  20, 512,
-	  DIBUSB_RC_NO,
-	  &dibusb_demod[DIBUSB_MT352],
-	  &dibusb_tuner[DIBUSB_TUNER_CABLE_LG_TDTP_E102P],
-	},
-	{ DIBUSB2_0B,&dibusb_usb_ctrl[2],
-	  "dvb-dibusb-adstech-usb2-1.fw",
-	  0x01, 0x06,
-	  7, 4096,
-	  DIBUSB_RC_NEC_PROTOCOL,
-	  &dibusb_demod[DIBUSB_DIB3000MB],
-	  &dibusb_tuner[DIBUSB_TUNER_CABLE_THOMSON],
-	},
-	{ NOVAT_USB2,&dibusb_usb_ctrl[2],
-	  "dvb-dibusb-nova-t-1.fw",
-	  0x01, 0x06,
-	  7, 4096,
-	  DIBUSB_RC_HAUPPAUGE_PROTO,
-	  &dibusb_demod[DIBUSB_DIB3000MC],
-	  &dibusb_tuner[DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5],
-	},
-	{ DTT200U,&dibusb_usb_ctrl[2],
-	  "dvb-dtt200u-1.fw",
-	  0x01, 0x02,
-	  7, 4096,
-	  DIBUSB_RC_NO,
-	  &dibusb_demod[DTT200U_FE],
-	  NULL, /* no explicit tuner/pll-programming necessary (it has the ENV57H1XD5) */
-	},
-};
-
-static struct dibusb_usb_device dibusb_devices[] = {
-	{	"TwinhanDTV USB1.1 / Magic Box / HAMA USB1.1 DVB-T device",
-		&dibusb_device_classes[DIBUSB1_1],
-		{ &dib_table[19], &dib_table[21], NULL},
-		{ &dib_table[20], &dib_table[22], NULL},
-	},
-	{	"KWorld V-Stream XPERT DTV - DVB-T USB1.1",
-		&dibusb_device_classes[DIBUSB1_1],
-		{ &dib_table[11], NULL },
-		{ &dib_table[12], NULL },
-	},
-	{	"Grandtec USB1.1 DVB-T",
-		&dibusb_device_classes[DIBUSB1_1],
-		{ &dib_table[13], &dib_table[15], NULL },
-		{ &dib_table[14], &dib_table[16], NULL },
-	},
-	{	"DiBcom USB1.1 DVB-T reference design (MOD3000)",
-		&dibusb_device_classes[DIBUSB1_1],
-		{ &dib_table[7],  NULL },
-		{ &dib_table[8],  NULL },
-	},
-	{	"Artec T1 USB1.1 TVBOX with AN2135",
-		&dibusb_device_classes[DIBUSB1_1],
-		{ &dib_table[23], NULL },
-		{ &dib_table[24], NULL },
-	},
-	{	"Artec T1 USB1.1 TVBOX with AN2235",
-		&dibusb_device_classes[DIBUSB1_1_AN2235],
-		{ &dib_table[25], NULL },
-		{ &dib_table[26], NULL },
-	},
-	{	"Avermedia AverTV DVBT USB1.1",
-		&dibusb_device_classes[DIBUSB1_1],
-		{ &dib_table[0],  NULL },
-		{ &dib_table[1],  NULL },
-	},
-	{	"Compro Videomate DVB-U2000 - DVB-T USB1.1 (please confirm to linux-dvb)",
-		&dibusb_device_classes[DIBUSB1_1],
-		{ &dib_table[4], &dib_table[6], NULL},
-		{ &dib_table[5], NULL },
-	},
-	{	"Unkown USB1.1 DVB-T device ???? please report the name to the author",
-		&dibusb_device_classes[DIBUSB1_1],
-		{ &dib_table[17], NULL },
-		{ &dib_table[18], NULL },
-	},
-	{	"DiBcom USB2.0 DVB-T reference design (MOD3000P)",
-		&dibusb_device_classes[DIBUSB2_0],
-		{ &dib_table[9],  NULL },
-		{ &dib_table[10], NULL },
-	},
-	{	"Artec T1 USB2.0 TVBOX (please report the warm ID)",
-		&dibusb_device_classes[DIBUSB2_0],
-		{ &dib_table[27], NULL },
-		{ NULL },
-	},
-	{	"Hauppauge WinTV NOVA-T USB2",
-		&dibusb_device_classes[NOVAT_USB2],
-		{ &dib_table[30], NULL },
-		{ &dib_table[31], NULL },
-	},
-	{	"DTT200U (Yakumo/Hama/Typhoon) DVB-T USB2.0",
-		&dibusb_device_classes[DTT200U],
-		{ &dib_table[2], NULL },
-		{ &dib_table[3], NULL },
-	},	
-	{	"Hanftek UMT-010 DVB-T USB2.0",
-		&dibusb_device_classes[UMT2_0],
-		{ &dib_table[28], NULL },
-		{ &dib_table[29], NULL },
-	},	
-	{	"KWorld/ADSTech Instant DVB-T USB 2.0",
-		&dibusb_device_classes[DIBUSB2_0B],
-		{ &dib_table[32], NULL },
-		{ &dib_table[33], NULL }, /* device ID with default DIBUSB2_0-firmware */
-	},
-#ifdef CONFIG_DVB_DIBUSB_MISDESIGNED_DEVICES
-	{	"Artec T1 USB1.1 TVBOX with AN2235 (misdesigned)",
-		&dibusb_device_classes[DIBUSB1_1_AN2235],
-		{ &dib_table[34], NULL },
-		{ NULL },
-	},
-	{	"Artec T1 USB2.0 TVBOX with FX2 IDs (misdesigned, please report the warm ID)",
-		&dibusb_device_classes[DTT200U],
-		{ &dib_table[35], NULL },
-		{ &dib_table[36], NULL }, /* undefined, it could be that the device will get another USB ID in warm state */
-	},
-	{	"DiBcom USB1.1 DVB-T reference design (MOD3000) with AN2135 default IDs",
-		&dibusb_device_classes[DIBUSB1_1],
-		{ &dib_table[37], NULL },
-		{ NULL },
-	},
-#endif
-};
-
-static int dibusb_exit(struct usb_dibusb *dib)
-{
-	deb_info("init_state before exiting everything: %x\n",dib->init_state);
-	dibusb_remote_exit(dib);
-	dibusb_fe_exit(dib);
-	dibusb_i2c_exit(dib);
-	dibusb_dvb_exit(dib);
-	dibusb_urb_exit(dib);
-	deb_info("init_state should be zero now: %x\n",dib->init_state);
-	dib->init_state = DIBUSB_STATE_INIT;
-	kfree(dib);
-	return 0;
-}
-
-static int dibusb_init(struct usb_dibusb *dib)
-{
-	int ret = 0;
-	sema_init(&dib->usb_sem, 1);
-	sema_init(&dib->i2c_sem, 1);
-
-	dib->init_state = DIBUSB_STATE_INIT;
-	
-	if ((ret = dibusb_urb_init(dib)) ||
-		(ret = dibusb_dvb_init(dib)) || 
-		(ret = dibusb_i2c_init(dib))) {
-		dibusb_exit(dib);
-		return ret;
-	}
-
-	if ((ret = dibusb_fe_init(dib)))
-		err("could not initialize a frontend.");
-	
-	if ((ret = dibusb_remote_init(dib)))
-		err("could not initialize remote control.");
-	
-	return 0;
-}
-
-static struct dibusb_usb_device * dibusb_device_class_quirk(struct usb_device *udev, struct dibusb_usb_device *dev)
-{
-	int i;
-
-	/* Quirk for the Kworld/ADSTech Instant USB2.0 device. It has the same USB
-	 * IDs like the USB1.1 KWorld after loading the firmware. Which is a bad
-	 * idea and make this quirk necessary.
-	 */
-	if (dev->dev_cl->id == DIBUSB1_1 && udev->speed == USB_SPEED_HIGH) {
-		info("this seems to be the Kworld/ADSTech Instant USB2.0 device or equal.");
-		for (i = 0; i < sizeof(dibusb_devices)/sizeof(struct dibusb_usb_device); i++) {
-			if (dibusb_devices[i].dev_cl->id == DIBUSB2_0B) {
-				dev = &dibusb_devices[i];
-				break;
-			}
-		}
-	}
-
-	return dev;
-}
-
-static struct dibusb_usb_device * dibusb_find_device (struct usb_device *udev,int *cold)
-{
-	int i,j;
-	struct dibusb_usb_device *dev = NULL;
-	*cold = -1;
-
-	for (i = 0; i < sizeof(dibusb_devices)/sizeof(struct dibusb_usb_device); i++) {
-		for (j = 0; j < DIBUSB_ID_MAX_NUM && dibusb_devices[i].cold_ids[j] != NULL; j++) {
-			deb_info("check for cold %x %x\n",dibusb_devices[i].cold_ids[j]->idVendor, dibusb_devices[i].cold_ids[j]->idProduct);
-			if (dibusb_devices[i].cold_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) &&
-				dibusb_devices[i].cold_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
-				*cold = 1;
-				dev = &dibusb_devices[i];
-				break;
-			}
-		}
-
-		if (dev != NULL)
-			break;
-
-		for (j = 0; j < DIBUSB_ID_MAX_NUM && dibusb_devices[i].warm_ids[j] != NULL; j++) {
-			deb_info("check for warm %x %x\n",dibusb_devices[i].warm_ids[j]->idVendor, dibusb_devices[i].warm_ids[j]->idProduct);
-			if (dibusb_devices[i].warm_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) &&
-				dibusb_devices[i].warm_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
-				*cold = 0;
-				dev = &dibusb_devices[i];
-				break;
-			}
-		}
-	}
-
-	if (dev != NULL)
-		dev = dibusb_device_class_quirk(udev,dev);
-
-	return dev;
-}
-
-/*
- * USB 
- */
-static int dibusb_probe(struct usb_interface *intf, 
-		const struct usb_device_id *id)
-{
-	struct usb_device *udev = interface_to_usbdev(intf);
-	struct usb_dibusb *dib = NULL;
-	struct dibusb_usb_device *dibdev = NULL;
-	
-	int ret = -ENOMEM,cold=0;
-
-	if ((dibdev = dibusb_find_device(udev,&cold)) == NULL) {
-		err("something went very wrong, "
-				"unknown product ID: %.4x",le16_to_cpu(udev->descriptor.idProduct));
-		return -ENODEV;
-	}
-	
-	if (cold == 1) {
-		info("found a '%s' in cold state, will try to load a firmware",dibdev->name);
-		ret = dibusb_loadfirmware(udev,dibdev);
-	} else {
-		info("found a '%s' in warm state.",dibdev->name);
-		dib = kmalloc(sizeof(struct usb_dibusb),GFP_KERNEL);
-		if (dib == NULL) {
-			err("no memory");
-			return ret;
-		}
-		memset(dib,0,sizeof(struct usb_dibusb));
-		
-		dib->udev = udev;
-		dib->dibdev = dibdev;
-
-		/* store parameters to structures */
-		dib->rc_query_interval = rc_query_interval;
-		dib->pid_parse = pid_parse;
-		dib->rc_key_repeat_count = rc_key_repeat_count;
-
-		usb_set_intfdata(intf, dib);
-		
-		ret = dibusb_init(dib);
-	}
-	
-	if (ret == 0)
-		info("%s successfully initialized and connected.",dibdev->name);
-	else 
-		info("%s error while loading driver (%d)",dibdev->name,ret);
-	return ret;
-}
-
-static void dibusb_disconnect(struct usb_interface *intf)
-{
-	struct usb_dibusb *dib = usb_get_intfdata(intf);
-	const char *name = DRIVER_DESC;
-	
-	usb_set_intfdata(intf,NULL);
-	if (dib != NULL && dib->dibdev != NULL) {
-		name = dib->dibdev->name;
-		dibusb_exit(dib);
-	}
-	info("%s successfully deinitialized and disconnected.",name);
-	
-}
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver dibusb_driver = {
-	.owner		= THIS_MODULE,
-	.name		= DRIVER_DESC,
-	.probe 		= dibusb_probe,
-	.disconnect = dibusb_disconnect,
-	.id_table 	= dib_table,
-};
-
-/* module stuff */
-static int __init usb_dibusb_init(void)
-{
-	int result;
-	if ((result = usb_register(&dibusb_driver))) {
-		err("usb_register failed. Error number %d",result);
-		return result;
-	}
-	
-	return 0;
-}
-
-static void __exit usb_dibusb_exit(void)
-{
-	/* deregister this driver from the USB subsystem */
-	usb_deregister(&dibusb_driver);
-}
-
-module_init (usb_dibusb_init);
-module_exit (usb_dibusb_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c b/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c
deleted file mode 100644
index 400b439..0000000
--- a/drivers/media/dvb/dibusb/dvb-dibusb-dvb.c
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * dvb-dibusb-dvb.c is part of the driver for mobile USB Budget DVB-T devices 
- * based on reference design made by DiBcom (http://www.dibcom.fr/)
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * see dvb-dibusb-core.c for more copyright details.
- *
- * This file contains functions for initializing and handling the 
- * linux-dvb API.
- */
-#include "dvb-dibusb.h"
-
-#include <linux/usb.h>
-#include <linux/version.h>
-
-static u32 urb_compl_count;
-
-/*
- * MPEG2 TS DVB stuff 
- */
-void dibusb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
-{
-	struct usb_dibusb *dib = urb->context;
-
-	deb_ts("urb complete feedcount: %d, status: %d, length: %d\n",dib->feedcount,urb->status,
-			urb->actual_length);
-
-	urb_compl_count++;
-	if (urb_compl_count % 1000 == 0)
-		deb_info("%d urbs completed so far.\n",urb_compl_count);
-
-	switch (urb->status) {
-		case 0:         /* success */
-		case -ETIMEDOUT:    /* NAK */
-			break;
-		case -ECONNRESET:   /* kill */
-		case -ENOENT:
-		case -ESHUTDOWN:
-			return;
-		default:        /* error */
-			deb_ts("urb completition error %d.", urb->status);
-			break;
-	}
-
-	if (dib->feedcount > 0 && urb->actual_length > 0) {
-		if (dib->init_state & DIBUSB_STATE_DVB)
-			dvb_dmx_swfilter(&dib->demux, (u8*) urb->transfer_buffer,urb->actual_length);
-	} else 
-		deb_ts("URB dropped because of feedcount.\n");
-
-	usb_submit_urb(urb,GFP_ATOMIC);
-}
-
-static int dibusb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff) 
-{
-	struct usb_dibusb *dib = dvbdmxfeed->demux->priv;
-	int newfeedcount;
-	
-	if (dib == NULL)
-		return -ENODEV;
-
-	newfeedcount = dib->feedcount + (onoff ? 1 : -1);
-
-	/* 
-	 * stop feed before setting a new pid if there will be no pid anymore 
-	 */
-	if (newfeedcount == 0) {
-		deb_ts("stop feeding\n");
-		if (dib->xfer_ops.fifo_ctrl != NULL) {
-			if (dib->xfer_ops.fifo_ctrl(dib->fe,0)) {
-				err("error while inhibiting fifo.");
-				return -ENODEV;
-			}
-		}
-		dibusb_streaming(dib,0);
-	}
-	
-	dib->feedcount = newfeedcount;
-
-	/* activate the pid on the device specific pid_filter */
-	deb_ts("setting pid: %5d %04x at index %d '%s'\n",dvbdmxfeed->pid,dvbdmxfeed->pid,dvbdmxfeed->index,onoff ? "on" : "off");
-	if (dib->pid_parse && dib->xfer_ops.pid_ctrl != NULL)
-		dib->xfer_ops.pid_ctrl(dib->fe,dvbdmxfeed->index,dvbdmxfeed->pid,onoff);
-
-	/* 
-	 * start the feed if this was the first pid to set and there is still a pid
-	 * for reception.
-	 */
-	if (dib->feedcount == onoff && dib->feedcount > 0) {
-
-		deb_ts("controlling pid parser\n");
-		if (dib->xfer_ops.pid_parse != NULL) {
-			if (dib->xfer_ops.pid_parse(dib->fe,dib->pid_parse) < 0) {
-				err("could not handle pid_parser");
-			}
-		}
-		
-		deb_ts("start feeding\n");
-		if (dib->xfer_ops.fifo_ctrl != NULL) {
-			if (dib->xfer_ops.fifo_ctrl(dib->fe,1)) {
-				err("error while enabling fifo.");
-				return -ENODEV;
-			}
-		}
-		dibusb_streaming(dib,1);
-	}
-	return 0;
-}
-
-static int dibusb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	deb_ts("start pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,dvbdmxfeed->type);
-	return dibusb_ctrl_feed(dvbdmxfeed,1);
-}
-
-static int dibusb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
-	deb_ts("stop pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid, dvbdmxfeed->type);
-	return dibusb_ctrl_feed(dvbdmxfeed,0);
-}
-
-int dibusb_dvb_init(struct usb_dibusb *dib)
-{
-	int ret;
-
-	urb_compl_count = 0;
-
-	if ((ret = dvb_register_adapter(&dib->adapter, DRIVER_DESC,
-			THIS_MODULE)) < 0) {
-		deb_info("dvb_register_adapter failed: error %d", ret);
-		goto err;
-	}
-	dib->adapter.priv = dib;
-	
-/* i2c is done in dibusb_i2c_init */
-	
-	dib->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
-
-	dib->demux.priv = (void *)dib;
-	/* get pidcount from demod */
-	dib->demux.feednum = dib->demux.filternum = 255;
-	dib->demux.start_feed = dibusb_start_feed;
-	dib->demux.stop_feed = dibusb_stop_feed;
-	dib->demux.write_to_decoder = NULL;
-	if ((ret = dvb_dmx_init(&dib->demux)) < 0) {
-		err("dvb_dmx_init failed: error %d",ret);
-		goto err_dmx;
-	}
-
-	dib->dmxdev.filternum = dib->demux.filternum;
-	dib->dmxdev.demux = &dib->demux.dmx;
-	dib->dmxdev.capabilities = 0;
-	if ((ret = dvb_dmxdev_init(&dib->dmxdev, &dib->adapter)) < 0) {
-		err("dvb_dmxdev_init failed: error %d",ret);
-		goto err_dmx_dev;
-	}
-
-	dvb_net_init(&dib->adapter, &dib->dvb_net, &dib->demux.dmx);
-
-	goto success;
-err_dmx_dev:
-	dvb_dmx_release(&dib->demux);
-err_dmx:
-	dvb_unregister_adapter(&dib->adapter);
-err:
-	return ret;
-success:
-	dib->init_state |= DIBUSB_STATE_DVB;
-	return 0;
-}
-
-int dibusb_dvb_exit(struct usb_dibusb *dib)
-{
-	if (dib->init_state & DIBUSB_STATE_DVB) {
-		dib->init_state &= ~DIBUSB_STATE_DVB;
-		deb_info("unregistering DVB part\n");
-		dvb_net_release(&dib->dvb_net);
-		dib->demux.dmx.close(&dib->demux.dmx);
-		dvb_dmxdev_release(&dib->dmxdev);
-		dvb_dmx_release(&dib->demux);
-		dvb_unregister_adapter(&dib->adapter);
-	}
-	return 0;
-}
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c b/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c
deleted file mode 100644
index 5a71b88..0000000
--- a/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c
+++ /dev/null
@@ -1,582 +0,0 @@
-/*
- * dvb-dibusb-fe-i2c.c is part of the driver for mobile USB Budget DVB-T devices
- * based on reference design made by DiBcom (http://www.dibcom.fr/)
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * see dvb-dibusb-core.c for more copyright details.
- *
- * This file contains functions for attaching, initializing of an appropriate
- * demodulator/frontend. I2C-stuff is also located here.
- *
- */
-#include "dvb-dibusb.h"
-
-#include <linux/usb.h>
-
-static int dibusb_i2c_msg(struct usb_dibusb *dib, u8 addr,
-			  u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
-{
-	u8 sndbuf[wlen+4]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */
-	/* write only ? */
-	int wo = (rbuf == NULL || rlen == 0),
-		len = 2 + wlen + (wo ? 0 : 2);
-
-	sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ;
-	sndbuf[1] = (addr << 1) | (wo ? 0 : 1);
-
-	memcpy(&sndbuf[2],wbuf,wlen);
-
-	if (!wo) {
-		sndbuf[wlen+2] = (rlen >> 8) & 0xff;
-		sndbuf[wlen+3] = rlen & 0xff;
-	}
-
-	return dibusb_readwrite_usb(dib,sndbuf,len,rbuf,rlen);
-}
-
-/*
- * I2C master xfer function
- */
-static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msg,int num)
-{
-	struct usb_dibusb *dib = i2c_get_adapdata(adap);
-	int i;
-
-	if (down_interruptible(&dib->i2c_sem) < 0)
-		return -EAGAIN;
-
-	if (num > 2)
-		warn("more than 2 i2c messages at a time is not handled yet. TODO.");
-
-	for (i = 0; i < num; i++) {
-		/* write/read request */
-		if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
-			if (dibusb_i2c_msg(dib, msg[i].addr, msg[i].buf,msg[i].len,
-						msg[i+1].buf,msg[i+1].len) < 0)
-				break;
-			i++;
-		} else
-			if (dibusb_i2c_msg(dib, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0)
-				break;
-	}
-
-	up(&dib->i2c_sem);
-	return i;
-}
-
-static u32 dibusb_i2c_func(struct i2c_adapter *adapter)
-{
-	return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm dibusb_algo = {
-	.name			= "DiBcom USB i2c algorithm",
-	.id				= I2C_ALGO_BIT,
-	.master_xfer	= dibusb_i2c_xfer,
-	.functionality	= dibusb_i2c_func,
-};
-
-static int dibusb_general_demod_init(struct dvb_frontend *fe);
-static u8 dibusb_general_pll_addr(struct dvb_frontend *fe);
-static int dibusb_general_pll_init(struct dvb_frontend *fe, u8 pll_buf[5]);
-static int dibusb_general_pll_set(struct dvb_frontend *fe,
-		struct dvb_frontend_parameters* params, u8 pll_buf[5]);
-
-static struct mt352_config mt352_hanftek_umt_010_config = {
-	.demod_address = 0x1e,
-	.demod_init = dibusb_general_demod_init,
-	.pll_set = dibusb_general_pll_set,
-};
-
-static int dibusb_tuner_quirk(struct usb_dibusb *dib)
-{
-	switch (dib->dibdev->dev_cl->id) {
-		case DIBUSB1_1: /* some these device have the ENV77H11D5 and some the THOMSON CABLE */
-		case DIBUSB1_1_AN2235: { /* actually its this device, but in warm state they are indistinguishable */
-			struct dibusb_tuner *t;
-			u8 b[2] = { 0,0 } ,b2[1];
-			struct i2c_msg msg[2] = {
-				{ .flags = 0, .buf = b, .len = 2 },
-				{ .flags = I2C_M_RD, .buf = b2, .len = 1},
-			};
-
-			t = &dibusb_tuner[DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5];
-
-			msg[0].addr = msg[1].addr = t->pll_addr;
-
-			if (dib->xfer_ops.tuner_pass_ctrl != NULL)
-				dib->xfer_ops.tuner_pass_ctrl(dib->fe,1,t->pll_addr);
-			dibusb_i2c_xfer(&dib->i2c_adap,msg,2);
-			if (dib->xfer_ops.tuner_pass_ctrl != NULL)
-				dib->xfer_ops.tuner_pass_ctrl(dib->fe,0,t->pll_addr);
-
-			if (b2[0] == 0xfe)
-				info("this device has the Thomson Cable onboard. Which is default.");
-			else {
-				dib->tuner = t;
-				info("this device has the Panasonic ENV77H11D5 onboard.");
-			}
-			break;
-		}
-		default:
-			break;
-	}
-	return 0;
-}
-
-int dibusb_fe_init(struct usb_dibusb* dib)
-{
-	struct dib3000_config demod_cfg;
-	int i;
-
-	if (dib->init_state & DIBUSB_STATE_I2C) {
-		for (i = 0; i < sizeof(dib->dibdev->dev_cl->demod->i2c_addrs) / sizeof(unsigned char) &&
-				dib->dibdev->dev_cl->demod->i2c_addrs[i] != 0; i++) {
-
-			demod_cfg.demod_address = dib->dibdev->dev_cl->demod->i2c_addrs[i];
-			demod_cfg.pll_addr = dibusb_general_pll_addr;
-			demod_cfg.pll_set = dibusb_general_pll_set;
-			demod_cfg.pll_init = dibusb_general_pll_init;
-
-			deb_info("demod id: %d %d\n",dib->dibdev->dev_cl->demod->id,DTT200U_FE);
-
-			switch (dib->dibdev->dev_cl->demod->id) {
-				case DIBUSB_DIB3000MB:
-					dib->fe = dib3000mb_attach(&demod_cfg,&dib->i2c_adap,&dib->xfer_ops);
-				break;
-				case DIBUSB_DIB3000MC:
-					dib->fe = dib3000mc_attach(&demod_cfg,&dib->i2c_adap,&dib->xfer_ops);
-				break;
-				case DIBUSB_MT352:
-					mt352_hanftek_umt_010_config.demod_address = dib->dibdev->dev_cl->demod->i2c_addrs[i];
-					dib->fe = mt352_attach(&mt352_hanftek_umt_010_config, &dib->i2c_adap);
-				break;
-				case DTT200U_FE:
-					dib->fe = dtt200u_fe_attach(dib,&dib->xfer_ops);
-				break;
-			}
-			if (dib->fe != NULL) {
-				info("found demodulator at i2c address 0x%x",dib->dibdev->dev_cl->demod->i2c_addrs[i]);
-				break;
-			}
-		}
-		/* if a frontend was found */
-		if (dib->fe != NULL) {
-			if (dib->fe->ops->sleep != NULL)
-				dib->fe_sleep = dib->fe->ops->sleep;
-			dib->fe->ops->sleep = dibusb_hw_sleep;
-
-			if (dib->fe->ops->init != NULL )
-				dib->fe_init = dib->fe->ops->init;
-			dib->fe->ops->init = dibusb_hw_wakeup;
-
-			/* setting the default tuner */
-			dib->tuner = dib->dibdev->dev_cl->tuner;
-
-			/* check which tuner is mounted on this device, in case this is unsure */
-			dibusb_tuner_quirk(dib);
-		}
-	}
-	if (dib->fe == NULL) {
-		err("A frontend driver was not found for device '%s'.",
-		       dib->dibdev->name);
-		return -ENODEV;
-	} else {
-		if (dvb_register_frontend(&dib->adapter, dib->fe)) {
-			err("Frontend registration failed.");
-			if (dib->fe->ops->release)
-				dib->fe->ops->release(dib->fe);
-			dib->fe = NULL;
-			return -ENODEV;
-		}
-	}
-
-	return 0;
-}
-
-int dibusb_fe_exit(struct usb_dibusb *dib)
-{
-	if (dib->fe != NULL)
-		dvb_unregister_frontend(dib->fe);
-	return 0;
-}
-
-int dibusb_i2c_init(struct usb_dibusb *dib)
-{
-	int ret = 0;
-
-	dib->adapter.priv = dib;
-
-	strncpy(dib->i2c_adap.name,dib->dibdev->name,I2C_NAME_SIZE);
-#ifdef I2C_ADAP_CLASS_TV_DIGITAL
-	dib->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL,
-#else
-	dib->i2c_adap.class = I2C_CLASS_TV_DIGITAL,
-#endif
-	dib->i2c_adap.algo		= &dibusb_algo;
-	dib->i2c_adap.algo_data = NULL;
-	dib->i2c_adap.id		= I2C_ALGO_BIT;
-
-	i2c_set_adapdata(&dib->i2c_adap, dib);
-
-	if ((ret = i2c_add_adapter(&dib->i2c_adap)) < 0)
-		err("could not add i2c adapter");
-
-	dib->init_state |= DIBUSB_STATE_I2C;
-
-	return ret;
-}
-
-int dibusb_i2c_exit(struct usb_dibusb *dib)
-{
-	if (dib->init_state & DIBUSB_STATE_I2C)
-		i2c_del_adapter(&dib->i2c_adap);
-	dib->init_state &= ~DIBUSB_STATE_I2C;
-	return 0;
-}
-
-
-/* pll stuff, maybe removed soon (thx to Gerd/Andrew in advance) */
-static int thomson_cable_eu_pll_set(struct dvb_frontend_parameters *fep, u8 pllbuf[4])
-{
-	u32 tfreq = (fep->frequency + 36125000) / 62500;
-	int vu,p0,p1,p2;
-
-	if (fep->frequency > 403250000)
-		vu = 1, p2 = 1, p1 = 0, p0 = 1;
-	else if (fep->frequency > 115750000)
-		vu = 0, p2 = 1, p1 = 1, p0 = 0;
-	else if (fep->frequency > 44250000)
-		vu = 0, p2 = 0, p1 = 1, p0 = 1;
-	else
-		return -EINVAL;
-
-	pllbuf[0] = (tfreq >> 8) & 0x7f;
-	pllbuf[1] = tfreq & 0xff;
-	pllbuf[2] = 0x8e;
-	pllbuf[3] = (vu << 7) | (p2 << 2) | (p1 << 1) | p0;
-	return 0;
-}
-
-static int panasonic_cofdm_env57h1xd5_pll_set(struct dvb_frontend_parameters *fep, u8 pllbuf[4])
-{
-	u32 freq_khz = fep->frequency / 1000;
-	u32 tfreq = ((freq_khz + 36125)*6 + 500) / 1000;
-	u8 TA, T210, R210, ctrl1, cp210, p4321;
-	if (freq_khz > 858000) {
-		err("frequency cannot be larger than 858 MHz.");
-		return -EINVAL;
-	}
-
-	// contol data 1 : 1 | T/A=1 | T2,T1,T0 = 0,0,0 | R2,R1,R0 = 0,1,0
-	TA = 1;
-	T210 = 0;
-	R210 = 0x2;
-	ctrl1 = (1 << 7) | (TA << 6) | (T210 << 3) | R210;
-
-// ********    CHARGE PUMP CONFIG vs RF FREQUENCIES     *****************
-	if (freq_khz < 470000)
-		cp210 = 2;  // VHF Low and High band ch E12 to E4 to E12
-	else if (freq_khz < 526000)
-		cp210 = 4;  // UHF band Ch E21 to E27
-	else // if (freq < 862000000)
-		cp210 = 5;  // UHF band ch E28 to E69
-
-//*********************    BW select  *******************************
-	if (freq_khz < 153000)
-		p4321  = 1; // BW selected for VHF low
-	else if (freq_khz < 470000)
-		p4321  = 2; // BW selected for VHF high E5 to E12
-	else // if (freq < 862000000)
-		p4321  = 4; // BW selection for UHF E21 to E69
-
-	pllbuf[0] = (tfreq >> 8) & 0xff;
-	pllbuf[1] = (tfreq >> 0) & 0xff;
-	pllbuf[2] = 0xff & ctrl1;
-	pllbuf[3] =  (cp210 << 5) | (p4321);
-
-	return 0;
-}
-
-/*
- *			    7	6		5	4	3	2	1	0
- * Address Byte             1	1		0	0	0	MA1	MA0	R/~W=0
- *
- * Program divider byte 1   0	n14		n13	n12	n11	n10	n9	n8
- * Program divider byte 2	n7	n6		n5	n4	n3	n2	n1	n0
- *
- * Control byte 1           1	T/A=1	T2	T1	T0	R2	R1	R0
- *                          1	T/A=0	0	0	ATC	AL2	AL1	AL0
- *
- * Control byte 2           CP2	CP1		CP0	BS5	BS4	BS3	BS2	BS1
- *
- * MA0/1 = programmable address bits
- * R/~W  = read/write bit (0 for writing)
- * N14-0 = programmable LO frequency
- *
- * T/A   = test AGC bit (0 = next 6 bits AGC setting,
- *                       1 = next 6 bits test and reference divider ratio settings)
- * T2-0  = test bits
- * R2-0  = reference divider ratio and programmable frequency step
- * ATC   = AGC current setting and time constant
- *         ATC = 0: AGC current = 220nA, AGC time constant = 2s
- *         ATC = 1: AGC current = 9uA, AGC time constant = 50ms
- * AL2-0 = AGC take-over point bits
- * CP2-0 = charge pump current
- * BS5-1 = PMOS ports control bits;
- *             BSn = 0 corresponding port is off, high-impedance state (at power-on)
- *             BSn = 1 corresponding port is on
- */
-static int panasonic_cofdm_env77h11d5_tda6650_init(struct dvb_frontend *fe, u8 pllbuf[4])
-{
-	pllbuf[0] = 0x0b;
-	pllbuf[1] = 0xf5;
-	pllbuf[2] = 0x85;
-	pllbuf[3] = 0xab;
-	return 0;
-}
-
-static int panasonic_cofdm_env77h11d5_tda6650_set (struct dvb_frontend_parameters *fep,u8 pllbuf[4])
-{
-	int tuner_frequency = 0;
-	u8 band, cp, filter;
-
-	// determine charge pump
-	tuner_frequency = fep->frequency + 36166000;
-	if (tuner_frequency < 87000000)
-		return -EINVAL;
-	else if (tuner_frequency < 130000000)
-		cp = 3;
-	else if (tuner_frequency < 160000000)
-		cp = 5;
-	else if (tuner_frequency < 200000000)
-		cp = 6;
-	else if (tuner_frequency < 290000000)
-		cp = 3;
-	else if (tuner_frequency < 420000000)
-		cp = 5;
-	else if (tuner_frequency < 480000000)
-		cp = 6;
-	else if (tuner_frequency < 620000000)
-		cp = 3;
-	else if (tuner_frequency < 830000000)
-		cp = 5;
-	else if (tuner_frequency < 895000000)
-		cp = 7;
-	else
-		return -EINVAL;
-
-	// determine band
-	if (fep->frequency < 49000000)
-		return -EINVAL;
-	else if (fep->frequency < 161000000)
-		band = 1;
-	else if (fep->frequency < 444000000)
-		band = 2;
-	else if (fep->frequency < 861000000)
-		band = 4;
-	else
-		return -EINVAL;
-
-	// setup PLL filter
-	switch (fep->u.ofdm.bandwidth) {
-		case BANDWIDTH_6_MHZ:
-		case BANDWIDTH_7_MHZ:
-			filter = 0;
-			break;
-		case BANDWIDTH_8_MHZ:
-			filter = 1;
-			break;
-		default:
-			return -EINVAL;
-	}
-
-	// calculate divisor
-	// ((36166000+((1000000/6)/2)) + Finput)/(1000000/6)
-	tuner_frequency = (((fep->frequency / 1000) * 6) + 217496) / 1000;
-
-	// setup tuner buffer
-	pllbuf[0] = (tuner_frequency >> 8) & 0x7f;
-	pllbuf[1] = tuner_frequency & 0xff;
-	pllbuf[2] = 0xca;
-	pllbuf[3] = (cp << 5) | (filter << 3) | band;
-	return 0;
-}
-
-/*
- *			    7	6	5	4	3	2	1	0
- * Address Byte             1	1	0	0	0	MA1	MA0	R/~W=0
- *
- * Program divider byte 1   0	n14	n13	n12	n11	n10	n9	n8
- * Program divider byte 2	n7	n6	n5	n4	n3	n2	n1	n0
- *
- * Control byte             1	CP	T2	T1	T0	RSA	RSB	OS
- *
- * Band Switch byte         X	X	X	P4	P3	P2	P1	P0
- *
- * Auxiliary byte           ATC	AL2	AL1	AL0	0	0	0	0
- *
- * Address: MA1	MA0	Address
- *          0	0	c0
- *          0	1	c2 (always valid)
- *          1	0	c4
- *          1	1	c6
- */
-static int lg_tdtp_e102p_tua6034(struct dvb_frontend_parameters* fep, u8 pllbuf[4])
-{
-	u32 div;
-	u8 p210, p3;
-
-#define TUNER_MUL 62500
-
-	div = (fep->frequency + 36125000 + TUNER_MUL / 2) / TUNER_MUL;
-//	div = ((fep->frequency/1000 + 36166) * 6) / 1000;
-
-	if (fep->frequency < 174500000)
-		p210 = 1; // not supported by the tdtp_e102p
-	else if (fep->frequency < 230000000) // VHF
-		p210 = 2;
-	else
-		p210 = 4;
-
-	if (fep->u.ofdm.bandwidth == BANDWIDTH_7_MHZ)
-		p3 = 0;
-	else
-		p3 = 1;
-
-	pllbuf[0] = (div >> 8) & 0x7f;
-	pllbuf[1] = div & 0xff;
-	pllbuf[2] = 0xce;
-//	pllbuf[2] = 0xcc;
-	pllbuf[3] = (p3 << 3) | p210;
-
-	return 0;
-}
-
-static int lg_tdtp_e102p_mt352_demod_init(struct dvb_frontend *fe)
-{
-	static u8 mt352_clock_config[] = { 0x89, 0xb8, 0x2d };
-	static u8 mt352_reset[] = { 0x50, 0x80 };
-	static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 };
-	static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 };
-	static u8 mt352_agc_cfg[] = { 0x67, 0x10, 0xa0 };
-
-	static u8 mt352_sec_agc_cfg1[] = { 0x6a, 0xff };
-	static u8 mt352_sec_agc_cfg2[] = { 0x6d, 0xff };
-	static u8 mt352_sec_agc_cfg3[] = { 0x70, 0x40 };
-	static u8 mt352_sec_agc_cfg4[] = { 0x7b, 0x03 };
-	static u8 mt352_sec_agc_cfg5[] = { 0x7d, 0x0f };
-
-	static u8 mt352_acq_ctl[] = { 0x53, 0x50 };
-	static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x06 };
-
-	mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
-	udelay(2000);
-	mt352_write(fe, mt352_reset, sizeof(mt352_reset));
-	mt352_write(fe, mt352_mclk_ratio, sizeof(mt352_mclk_ratio));
-
-	mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
-	mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
-
-	mt352_write(fe, mt352_sec_agc_cfg1, sizeof(mt352_sec_agc_cfg1));
-	mt352_write(fe, mt352_sec_agc_cfg2, sizeof(mt352_sec_agc_cfg2));
-	mt352_write(fe, mt352_sec_agc_cfg3, sizeof(mt352_sec_agc_cfg3));
-	mt352_write(fe, mt352_sec_agc_cfg4, sizeof(mt352_sec_agc_cfg4));
-	mt352_write(fe, mt352_sec_agc_cfg5, sizeof(mt352_sec_agc_cfg5));
-
-	mt352_write(fe, mt352_acq_ctl, sizeof(mt352_acq_ctl));
-	mt352_write(fe, mt352_input_freq_1, sizeof(mt352_input_freq_1));
-
-	return 0;
-}
-
-static int dibusb_general_demod_init(struct dvb_frontend *fe)
-{
-	struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv;
-	switch (dib->dibdev->dev_cl->id) {
-		case UMT2_0:
-			return lg_tdtp_e102p_mt352_demod_init(fe);
-		default: /* other device classes do not have device specific demod inits */
-			break;
-	}
-	return 0;
-}
-
-static u8 dibusb_general_pll_addr(struct dvb_frontend *fe)
-{
-	struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv;
-	return dib->tuner->pll_addr;
-}
-
-static int dibusb_pll_i2c_helper(struct usb_dibusb *dib, u8 pll_buf[5], u8 buf[4])
-{
-	if (pll_buf == NULL) {
-		struct i2c_msg msg = {
-			.addr = dib->tuner->pll_addr,
-			.flags = 0,
-			.buf = buf,
-			.len = sizeof(buf)
-		};
-		if (i2c_transfer (&dib->i2c_adap, &msg, 1) != 1)
-			return -EIO;
-		msleep(1);
-	} else {
-		pll_buf[0] = dib->tuner->pll_addr << 1;
-		memcpy(&pll_buf[1],buf,4);
-	}
-
-	return 0;
-}
-
-static int dibusb_general_pll_init(struct dvb_frontend *fe,
-		u8 pll_buf[5])
-{
-	struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv;
-	u8 buf[4];
-	int ret=0;
-	switch (dib->tuner->id) {
-		case DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5:
-			ret = panasonic_cofdm_env77h11d5_tda6650_init(fe,buf);
-			break;
-		default:
-			break;
-	}
-
-	if (ret)
-		return ret;
-
-	return dibusb_pll_i2c_helper(dib,pll_buf,buf);
-}
-
-static int dibusb_general_pll_set(struct dvb_frontend *fe,
-		struct dvb_frontend_parameters *fep, u8 pll_buf[5])
-{
-	struct usb_dibusb* dib = (struct usb_dibusb*) fe->dvb->priv;
-	u8 buf[4];
-	int ret=0;
-
-	switch (dib->tuner->id) {
-		case DIBUSB_TUNER_CABLE_THOMSON:
-			ret = thomson_cable_eu_pll_set(fep, buf);
-			break;
-		case DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5:
-			ret = panasonic_cofdm_env57h1xd5_pll_set(fep, buf);
-			break;
-		case DIBUSB_TUNER_CABLE_LG_TDTP_E102P:
-			ret = lg_tdtp_e102p_tua6034(fep, buf);
-			break;
-		case DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5:
-			ret = panasonic_cofdm_env77h11d5_tda6650_set(fep,buf);
-			break;
-		default:
-			warn("no pll programming routine found for tuner %d.\n",dib->tuner->id);
-			ret = -ENODEV;
-			break;
-	}
-
-	if (ret)
-		return ret;
-
-	return dibusb_pll_i2c_helper(dib,pll_buf,buf);
-}
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c b/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c
deleted file mode 100644
index 504ba47..0000000
--- a/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * dvb-dibusb-firmware.c is part of the driver for mobile USB Budget DVB-T devices 
- * based on reference design made by DiBcom (http://www.dibcom.fr/)
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * see dvb-dibusb-core.c for more copyright details.
- *
- * This file contains functions for downloading the firmware to the device.
- */
-#include "dvb-dibusb.h"
-
-#include <linux/firmware.h>
-#include <linux/usb.h>
-
-/*
- * load a firmware packet to the device 
- */
-static int dibusb_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 len)
-{
-	return usb_control_msg(udev, usb_sndctrlpipe(udev,0),
-			0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5000);
-}
-
-int dibusb_loadfirmware(struct usb_device *udev, struct dibusb_usb_device *dibdev)
-{
-	const struct firmware *fw = NULL;
-	u16 addr;
-	u8 *b,*p;
-	int ret = 0,i;
-	
-	if ((ret = request_firmware(&fw, dibdev->dev_cl->firmware, &udev->dev)) != 0) {
-		err("did not find the firmware file. (%s) "
-			"Please see linux/Documentation/dvb/ for more details on firmware-problems.",
-			dibdev->dev_cl->firmware);
-		return ret;
-	}
-
-	info("downloading firmware from file '%s'.",dibdev->dev_cl->firmware);
-	
-	p = kmalloc(fw->size,GFP_KERNEL);	
-	if (p != NULL) {
-		u8 reset;
-		/*
-		 * you cannot use the fw->data as buffer for 
-		 * usb_control_msg, a new buffer has to be
-		 * created
-		 */
-		memcpy(p,fw->data,fw->size);
-
-		/* stop the CPU */
-		reset = 1;
-		if ((ret = dibusb_writemem(udev,dibdev->dev_cl->usb_ctrl->cpu_cs_register,&reset,1)) != 1) 
-			err("could not stop the USB controller CPU.");
-		for(i = 0; p[i+3] == 0 && i < fw->size; ) { 
-			b = (u8 *) &p[i];
-			addr = *((u16 *) &b[1]);
-
-			ret = dibusb_writemem(udev,addr,&b[4],b[0]);
-		
-			if (ret != b[0]) {
-				err("error while transferring firmware "
-					"(transferred size: %d, block size: %d)",
-					ret,b[0]);
-				ret = -EINVAL;
-				break;
-			}
-			i += 5 + b[0];
-		}
-		/* length in ret */
-		if (ret > 0)
-			ret = 0;
-		/* restart the CPU */
-		reset = 0;
-		if (ret || dibusb_writemem(udev,dibdev->dev_cl->usb_ctrl->cpu_cs_register,&reset,1) != 1) {
-			err("could not restart the USB controller CPU.");
-			ret = -EINVAL;
-		}
-
-		kfree(p);
-	} else { 
-		ret = -ENOMEM;
-	}
-	release_firmware(fw);
-
-	return ret;
-}
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-remote.c b/drivers/media/dvb/dibusb/dvb-dibusb-remote.c
deleted file mode 100644
index 9dc8b15..0000000
--- a/drivers/media/dvb/dibusb/dvb-dibusb-remote.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * dvb-dibusb-remote.c is part of the driver for mobile USB Budget DVB-T devices
- * based on reference design made by DiBcom (http://www.dibcom.fr/)
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * see dvb-dibusb-core.c for more copyright details.
- *
- * This file contains functions for handling the event device on the software
- * side and the remote control on the hardware side.
- */
-#include "dvb-dibusb.h"
-
-/* Table to map raw key codes to key events.  This should not be hard-wired
-   into the kernel.  */
-static const struct { u8 c0, c1, c2; uint32_t key; } nec_rc_keys [] =
-{
-	/* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */
-	{ 0x00, 0xff, 0x16, KEY_POWER },
-	{ 0x00, 0xff, 0x10, KEY_MUTE },
-	{ 0x00, 0xff, 0x03, KEY_1 },
-	{ 0x00, 0xff, 0x01, KEY_2 },
-	{ 0x00, 0xff, 0x06, KEY_3 },
-	{ 0x00, 0xff, 0x09, KEY_4 },
-	{ 0x00, 0xff, 0x1d, KEY_5 },
-	{ 0x00, 0xff, 0x1f, KEY_6 },
-	{ 0x00, 0xff, 0x0d, KEY_7 },
-	{ 0x00, 0xff, 0x19, KEY_8 },
-	{ 0x00, 0xff, 0x1b, KEY_9 },
-	{ 0x00, 0xff, 0x15, KEY_0 },
-	{ 0x00, 0xff, 0x05, KEY_CHANNELUP },
-	{ 0x00, 0xff, 0x02, KEY_CHANNELDOWN },
-	{ 0x00, 0xff, 0x1e, KEY_VOLUMEUP },
-	{ 0x00, 0xff, 0x0a, KEY_VOLUMEDOWN },
-	{ 0x00, 0xff, 0x11, KEY_RECORD },
-	{ 0x00, 0xff, 0x17, KEY_FAVORITES }, /* Heart symbol - Channel list. */
-	{ 0x00, 0xff, 0x14, KEY_PLAY },
-	{ 0x00, 0xff, 0x1a, KEY_STOP },
-	{ 0x00, 0xff, 0x40, KEY_REWIND },
-	{ 0x00, 0xff, 0x12, KEY_FASTFORWARD },
-	{ 0x00, 0xff, 0x0e, KEY_PREVIOUS }, /* Recall - Previous channel. */
-	{ 0x00, 0xff, 0x4c, KEY_PAUSE },
-	{ 0x00, 0xff, 0x4d, KEY_SCREEN }, /* Full screen mode. */
-	{ 0x00, 0xff, 0x54, KEY_AUDIO }, /* MTS - Switch to secondary audio. */
-	/* additional keys TwinHan VisionPlus, the Artec seemingly not have */
-	{ 0x00, 0xff, 0x0c, KEY_CANCEL }, /* Cancel */
-	{ 0x00, 0xff, 0x1c, KEY_EPG }, /* EPG */
-	{ 0x00, 0xff, 0x00, KEY_TAB }, /* Tab */
-	{ 0x00, 0xff, 0x48, KEY_INFO }, /* Preview */
-	{ 0x00, 0xff, 0x04, KEY_LIST }, /* RecordList */
-	{ 0x00, 0xff, 0x0f, KEY_TEXT }, /* Teletext */
-	/* Key codes for the KWorld/ADSTech/JetWay remote. */
-	{ 0x86, 0x6b, 0x12, KEY_POWER },
-	{ 0x86, 0x6b, 0x0f, KEY_SELECT }, /* source */
-	{ 0x86, 0x6b, 0x0c, KEY_UNKNOWN }, /* scan */
-	{ 0x86, 0x6b, 0x0b, KEY_EPG },
-	{ 0x86, 0x6b, 0x10, KEY_MUTE },
-	{ 0x86, 0x6b, 0x01, KEY_1 },
-	{ 0x86, 0x6b, 0x02, KEY_2 },
-	{ 0x86, 0x6b, 0x03, KEY_3 },
-	{ 0x86, 0x6b, 0x04, KEY_4 },
-	{ 0x86, 0x6b, 0x05, KEY_5 },
-	{ 0x86, 0x6b, 0x06, KEY_6 },
-	{ 0x86, 0x6b, 0x07, KEY_7 },
-	{ 0x86, 0x6b, 0x08, KEY_8 },
-	{ 0x86, 0x6b, 0x09, KEY_9 },
-	{ 0x86, 0x6b, 0x0a, KEY_0 },
-	{ 0x86, 0x6b, 0x18, KEY_ZOOM },
-	{ 0x86, 0x6b, 0x1c, KEY_UNKNOWN }, /* preview */
-	{ 0x86, 0x6b, 0x13, KEY_UNKNOWN }, /* snap */
-	{ 0x86, 0x6b, 0x00, KEY_UNDO },
-	{ 0x86, 0x6b, 0x1d, KEY_RECORD },
-	{ 0x86, 0x6b, 0x0d, KEY_STOP },
-	{ 0x86, 0x6b, 0x0e, KEY_PAUSE },
-	{ 0x86, 0x6b, 0x16, KEY_PLAY },
-	{ 0x86, 0x6b, 0x11, KEY_BACK },
-	{ 0x86, 0x6b, 0x19, KEY_FORWARD },
-	{ 0x86, 0x6b, 0x14, KEY_UNKNOWN }, /* pip */
-	{ 0x86, 0x6b, 0x15, KEY_ESC },
-	{ 0x86, 0x6b, 0x1a, KEY_UP },
-	{ 0x86, 0x6b, 0x1e, KEY_DOWN },
-	{ 0x86, 0x6b, 0x1f, KEY_LEFT },
-	{ 0x86, 0x6b, 0x1b, KEY_RIGHT },
-};
-
-/* Hauppauge NOVA-T USB2 keys */
-static const struct { u16 raw; uint32_t key; } haupp_rc_keys [] = {
-	{ 0xddf, KEY_GOTO },
-	{ 0xdef, KEY_POWER },
-	{ 0xce7, KEY_TV },
-	{ 0xcc7, KEY_VIDEO },
-	{ 0xccf, KEY_AUDIO },
-	{ 0xcd7, KEY_MEDIA },
-	{ 0xcdf, KEY_EPG },
-	{ 0xca7, KEY_UP },
-	{ 0xc67, KEY_RADIO },
-	{ 0xcb7, KEY_LEFT },
-	{ 0xd2f, KEY_OK },
-	{ 0xcbf, KEY_RIGHT },
-	{ 0xcff, KEY_BACK },
-	{ 0xcaf, KEY_DOWN },
-	{ 0xc6f, KEY_MENU },
-	{ 0xc87, KEY_VOLUMEUP },
-	{ 0xc8f, KEY_VOLUMEDOWN },
-	{ 0xc97, KEY_CHANNEL },
-	{ 0xc7f, KEY_MUTE },
-	{ 0xd07, KEY_CHANNELUP },
-	{ 0xd0f, KEY_CHANNELDOWN },
-	{ 0xdbf, KEY_RECORD },
-	{ 0xdb7, KEY_STOP },
-	{ 0xd97, KEY_REWIND },
-	{ 0xdaf, KEY_PLAY },
-	{ 0xda7, KEY_FASTFORWARD },
-	{ 0xd27, KEY_LAST }, /* Skip backwards */
-	{ 0xd87, KEY_PAUSE },
-	{ 0xcf7, KEY_NEXT },
-	{ 0xc07, KEY_0 },
-	{ 0xc0f, KEY_1 },
-	{ 0xc17, KEY_2 },
-	{ 0xc1f, KEY_3 },
-	{ 0xc27, KEY_4 },
-	{ 0xc2f, KEY_5 },
-	{ 0xc37, KEY_6 },
-	{ 0xc3f, KEY_7 },
-	{ 0xc47, KEY_8 },
-	{ 0xc4f, KEY_9 },
-	{ 0xc57, KEY_KPASTERISK },
-	{ 0xc77, KEY_GRAVE }, /* # */
-	{ 0xc5f, KEY_RED },
-	{ 0xd77, KEY_GREEN },
-	{ 0xdc7, KEY_YELLOW },
-	{ 0xd4f, KEY_BLUE},
-};
-
-static int dibusb_key2event_nec(struct usb_dibusb *dib,u8 rb[5])
-{
-	int i;
-	switch (rb[0]) {
-		case DIBUSB_RC_NEC_KEY_PRESSED:
-			/* rb[1-3] is the actual key, rb[4] is a checksum */
-			deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
-				rb[1], rb[2], rb[3], rb[4]);
-
-			if ((0xff - rb[3]) != rb[4]) {
-				deb_rc("remote control checksum failed.\n");
-				break;
-			}
-
-			/* See if we can match the raw key code. */
-			for (i = 0; i < sizeof(nec_rc_keys)/sizeof(nec_rc_keys[0]); i++) {
-				if (nec_rc_keys[i].c0 == rb[1] &&
-					nec_rc_keys[i].c1 == rb[2] &&
-					nec_rc_keys[i].c2 == rb[3]) {
-
-					dib->last_event = nec_rc_keys[i].key;
-					return 1;
-				}
-			}
-			break;
-		case DIBUSB_RC_NEC_KEY_REPEATED:
-			/* rb[1]..rb[4] are always zero.*/
-			/* Repeats often seem to occur so for the moment just ignore this. */
-			return 0;
-		case DIBUSB_RC_NEC_EMPTY: /* No (more) remote control keys. */
-		default:
-			break;
-	}
-	return -1;
-}
-
-static int dibusb_key2event_hauppauge(struct usb_dibusb *dib,u8 rb[4])
-{
-	u16 raw;
-	int i,state;
-	switch (rb[0]) {
-		case DIBUSB_RC_HAUPPAUGE_KEY_PRESSED:
-			raw = ((rb[1] & 0x0f) << 8) | rb[2];
-
-			state = !!(rb[1] & 0x40);
-
-			deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to %04x state: %d\n",rb[1],rb[2],rb[3],raw,state);
-			for (i = 0; i < sizeof(haupp_rc_keys)/sizeof(haupp_rc_keys[0]); i++) {
-				if (haupp_rc_keys[i].raw == raw) {
-					if (dib->last_event == haupp_rc_keys[i].key &&
-						dib->last_state == state) {
-						deb_rc("key repeat\n");
-						return 0;
-					} else {
-						dib->last_event = haupp_rc_keys[i].key;
-						dib->last_state = state;
-						return 1;
-					}
-				}
-			}
-
-			break;
-		case DIBUSB_RC_HAUPPAUGE_KEY_EMPTY:
-		default:
-			break;
-	}
-	return -1;
-}
-
-/*
- * Read the remote control and feed the appropriate event.
- * NEC protocol is used for remote controls
- */
-static int dibusb_read_remote_control(struct usb_dibusb *dib)
-{
-	u8 b[1] = { DIBUSB_REQ_POLL_REMOTE }, rb[5];
-	int ret,event = 0;
-
-	if ((ret = dibusb_readwrite_usb(dib,b,1,rb,5)))
-		return ret;
-
-	switch (dib->dibdev->dev_cl->remote_type) {
-		case DIBUSB_RC_NEC_PROTOCOL:
-			event = dibusb_key2event_nec(dib,rb);
-			break;
-		case DIBUSB_RC_HAUPPAUGE_PROTO:
-			event = dibusb_key2event_hauppauge(dib,rb);
-		default:
-			break;
-	}
-
-	/* key repeat */
-	if (event == 0)
-		if (++dib->repeat_key_count < dib->rc_key_repeat_count) {
-			deb_rc("key repeat dropped. (%d)\n",dib->repeat_key_count);
-			event = -1; /* skip this key repeat */
-		}
-
-	if (event == 1 || event == 0) {
-		deb_rc("Translated key 0x%04x\n",event);
-
-		/* Signal down and up events for this key. */
-		input_report_key(&dib->rc_input_dev, dib->last_event, 1);
-		input_report_key(&dib->rc_input_dev, dib->last_event, 0);
-		input_sync(&dib->rc_input_dev);
-
-		if (event == 1)
-			dib->repeat_key_count = 0;
-	}
-	return 0;
-}
-
-/* Remote-control poll function - called every dib->rc_query_interval ms to see
-   whether the remote control has received anything. */
-static void dibusb_remote_query(void *data)
-{
-	struct usb_dibusb *dib = (struct usb_dibusb *) data;
-	/* TODO: need a lock here.  We can simply skip checking for the remote control
-	   if we're busy. */
-	dibusb_read_remote_control(dib);
-	schedule_delayed_work(&dib->rc_query_work,
-			      msecs_to_jiffies(dib->rc_query_interval));
-}
-
-int dibusb_remote_init(struct usb_dibusb *dib)
-{
-	int i;
-
-	if (dib->dibdev->dev_cl->remote_type == DIBUSB_RC_NO)
-		return 0;
-	
-	/* Initialise the remote-control structures.*/
-	init_input_dev(&dib->rc_input_dev);
-
-	dib->rc_input_dev.evbit[0] = BIT(EV_KEY);
-	dib->rc_input_dev.keycodesize = sizeof(unsigned char);
-	dib->rc_input_dev.keycodemax = KEY_MAX;
-	dib->rc_input_dev.name = DRIVER_DESC " remote control";
-
-	switch (dib->dibdev->dev_cl->remote_type) {
-		case DIBUSB_RC_NEC_PROTOCOL:
-			for (i=0; i<sizeof(nec_rc_keys)/sizeof(nec_rc_keys[0]); i++)
-				set_bit(nec_rc_keys[i].key, dib->rc_input_dev.keybit);
-			break;
-		case DIBUSB_RC_HAUPPAUGE_PROTO:
-			for (i=0; i<sizeof(haupp_rc_keys)/sizeof(haupp_rc_keys[0]); i++)
-				set_bit(haupp_rc_keys[i].key, dib->rc_input_dev.keybit);
-			break;
-		default:
-			break;
-	}
-
-
-	input_register_device(&dib->rc_input_dev);
-
-	INIT_WORK(&dib->rc_query_work, dibusb_remote_query, dib);
-
-	/* Start the remote-control polling. */
-	if (dib->rc_query_interval < 40)
-		dib->rc_query_interval = 100; /* default */
-
-	info("schedule remote query interval to %d msecs.",dib->rc_query_interval);
-	schedule_delayed_work(&dib->rc_query_work,msecs_to_jiffies(dib->rc_query_interval));
-
-	dib->init_state |= DIBUSB_STATE_REMOTE;
-	
-	return 0;
-}
-
-int dibusb_remote_exit(struct usb_dibusb *dib)
-{
-	if (dib->dibdev->dev_cl->remote_type == DIBUSB_RC_NO)
-		return 0;
-
-	if (dib->init_state & DIBUSB_STATE_REMOTE) {
-		cancel_delayed_work(&dib->rc_query_work);
-		flush_scheduled_work();
-		input_unregister_device(&dib->rc_input_dev);
-	}
-	dib->init_state &= ~DIBUSB_STATE_REMOTE;
-	return 0;
-}
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb-usb.c b/drivers/media/dvb/dibusb/dvb-dibusb-usb.c
deleted file mode 100644
index 642f059..0000000
--- a/drivers/media/dvb/dibusb/dvb-dibusb-usb.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * dvb-dibusb-usb.c is part of the driver for mobile USB Budget DVB-T devices
- * based on reference design made by DiBcom (http://www.dibcom.fr/)
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- * see dvb-dibusb-core.c for more copyright details.
- *
- * This file contains functions for initializing and handling the
- * usb specific stuff.
- */
-#include "dvb-dibusb.h"
-
-#include <linux/version.h>
-#include <linux/pci.h>
-
-int dibusb_readwrite_usb(struct usb_dibusb *dib, u8 *wbuf, u16 wlen, u8 *rbuf,
-		u16 rlen)
-{
-	int actlen,ret = -ENOMEM;
-
-	if (wbuf == NULL || wlen == 0)
-		return -EINVAL;
-
-	if ((ret = down_interruptible(&dib->usb_sem)))
-		return ret;
-
-	debug_dump(wbuf,wlen);
-
-	ret = usb_bulk_msg(dib->udev,usb_sndbulkpipe(dib->udev,
-			dib->dibdev->dev_cl->pipe_cmd), wbuf,wlen,&actlen,
-			DIBUSB_I2C_TIMEOUT);
-
-	if (ret)
-		err("bulk message failed: %d (%d/%d)",ret,wlen,actlen);
-	else
-		ret = actlen != wlen ? -1 : 0;
-
-	/* an answer is expected, and no error before */
-	if (!ret && rbuf && rlen) {
-		ret = usb_bulk_msg(dib->udev,usb_rcvbulkpipe(dib->udev,
-				dib->dibdev->dev_cl->pipe_cmd),rbuf,rlen,&actlen,
-				DIBUSB_I2C_TIMEOUT);
-
-		if (ret)
-			err("recv bulk message failed: %d",ret);
-		else {
-			deb_alot("rlen: %d\n",rlen);
-			debug_dump(rbuf,actlen);
-		}
-	}
-
-	up(&dib->usb_sem);
-	return ret;
-}
-
-/*
- * Cypress controls
- */
-int dibusb_write_usb(struct usb_dibusb *dib, u8 *buf, u16 len)
-{
-	return dibusb_readwrite_usb(dib,buf,len,NULL,0);
-}
-
-#if 0
-/*
- * #if 0'ing the following functions as they are not in use _now_,
- * but probably will be sometime.
- */
-/*
- * do not use this, just a workaround for a bug,
- * which will hopefully never occur :).
- */
-int dibusb_interrupt_read_loop(struct usb_dibusb *dib)
-{
-	u8 b[1] = { DIBUSB_REQ_INTR_READ };
-	return dibusb_write_usb(dib,b,1);
-}
-#endif
-
-/*
- * ioctl for the firmware
- */
-static int dibusb_ioctl_cmd(struct usb_dibusb *dib, u8 cmd, u8 *param, int plen)
-{
-	u8 b[34];
-	int size = plen > 32 ? 32 : plen;
-	memset(b,0,34);
-	b[0] = DIBUSB_REQ_SET_IOCTL;
-	b[1] = cmd;
-
-	if (size > 0)
-		memcpy(&b[2],param,size);
-
-	return dibusb_write_usb(dib,b,34); //2+size);
-}
-
-/*
- * ioctl for power control
- */
-int dibusb_hw_wakeup(struct dvb_frontend *fe)
-{
-	struct usb_dibusb *dib = (struct usb_dibusb *) fe->dvb->priv;
-	u8 b[1] = { DIBUSB_IOCTL_POWER_WAKEUP };
-	deb_info("dibusb-device is getting up.\n");
-
-	switch (dib->dibdev->dev_cl->id) {
-		case DTT200U:
-			break;
-		default:
-			dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1);
-			break;
-	}
-
-	if (dib->fe_init)
-		return dib->fe_init(fe);
-
-	return 0;
-}
-
-int dibusb_hw_sleep(struct dvb_frontend *fe)
-{
-	struct usb_dibusb *dib = (struct usb_dibusb *) fe->dvb->priv;
-	u8 b[1] = { DIBUSB_IOCTL_POWER_SLEEP };
-	deb_info("dibusb-device is going to bed.\n");
-	/* workaround, something is wrong, when dibusb 1.1 device are going to bed too late */
-	switch (dib->dibdev->dev_cl->id) {
-		case DIBUSB1_1:
-		case NOVAT_USB2:
-		case DTT200U:
-			break;
-		default:
-			dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_POWER_MODE, b,1);
-			break;
-	}
-	if (dib->fe_sleep)
-		return dib->fe_sleep(fe);
-
-	return 0;
-}
-
-int dibusb_set_streaming_mode(struct usb_dibusb *dib,u8 mode)
-{
-	u8 b[2] = { DIBUSB_REQ_SET_STREAMING_MODE, mode };
-	return dibusb_readwrite_usb(dib,b,2,NULL,0);
-}
-
-static int dibusb_urb_kill(struct usb_dibusb *dib)
-{
-	int i;
-deb_info("trying to kill urbs\n");
-	if (dib->init_state & DIBUSB_STATE_URB_SUBMIT) {
-		for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) {
-			deb_info("killing URB no. %d.\n",i);
-
-			/* stop the URB */
-			usb_kill_urb(dib->urb_list[i]);
-		}
-	} else
-	deb_info(" URBs not killed.\n");
-	dib->init_state &= ~DIBUSB_STATE_URB_SUBMIT;
-	return 0;
-}
-
-static int dibusb_urb_submit(struct usb_dibusb *dib)
-{
-	int i,ret;
-	if (dib->init_state & DIBUSB_STATE_URB_INIT) {
-		for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) {
-			deb_info("submitting URB no. %d\n",i);
-			if ((ret = usb_submit_urb(dib->urb_list[i],GFP_ATOMIC))) {
-				err("could not submit buffer urb no. %d - get them all back\n",i);
-				dibusb_urb_kill(dib);
-				return ret;
-			}
-			dib->init_state |= DIBUSB_STATE_URB_SUBMIT;
-		}
-	}
-	return 0;
-}
-
-int dibusb_streaming(struct usb_dibusb *dib,int onoff)
-{
-	if (onoff)
-		dibusb_urb_submit(dib);
-	else
-		dibusb_urb_kill(dib);
-
-	switch (dib->dibdev->dev_cl->id) {
-		case DIBUSB2_0:
-		case DIBUSB2_0B:
-		case NOVAT_USB2:
-		case UMT2_0:
-			if (onoff)
-				return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_ENABLE_STREAM,NULL,0);
-			else
-				return dibusb_ioctl_cmd(dib,DIBUSB_IOCTL_CMD_DISABLE_STREAM,NULL,0);
-			break;
-		default:
-			break;
-	}
-	return 0;
-}
-
-int dibusb_urb_init(struct usb_dibusb *dib)
-{
-	int i,bufsize,def_pid_parse = 1;
-
-	/*
-	 * when reloading the driver w/o replugging the device
-	 * a timeout occures, this helps
-	 */
-	usb_clear_halt(dib->udev,usb_sndbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_cmd));
-	usb_clear_halt(dib->udev,usb_rcvbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_cmd));
-	usb_clear_halt(dib->udev,usb_rcvbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_data));
-
-	/* allocate the array for the data transfer URBs */
-	dib->urb_list = kmalloc(dib->dibdev->dev_cl->urb_count*sizeof(struct urb *),GFP_KERNEL);
-	if (dib->urb_list == NULL)
-		return -ENOMEM;
-	memset(dib->urb_list,0,dib->dibdev->dev_cl->urb_count*sizeof(struct urb *));
-
-	dib->init_state |= DIBUSB_STATE_URB_LIST;
-
-	bufsize = dib->dibdev->dev_cl->urb_count*dib->dibdev->dev_cl->urb_buffer_size;
-	deb_info("allocate %d bytes as buffersize for all URBs\n",bufsize);
-	/* allocate the actual buffer for the URBs */
-	if ((dib->buffer = pci_alloc_consistent(NULL,bufsize,&dib->dma_handle)) == NULL) {
-		deb_info("not enough memory.\n");
-		return -ENOMEM;
-	}
-	deb_info("allocation complete\n");
-	memset(dib->buffer,0,bufsize);
-
-	dib->init_state |= DIBUSB_STATE_URB_BUF;
-
-	/* allocate and submit the URBs */
-	for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) {
-		if (!(dib->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC))) {
-			return -ENOMEM;
-		}
-
-		usb_fill_bulk_urb( dib->urb_list[i], dib->udev,
-				usb_rcvbulkpipe(dib->udev,dib->dibdev->dev_cl->pipe_data),
-				&dib->buffer[i*dib->dibdev->dev_cl->urb_buffer_size],
-				dib->dibdev->dev_cl->urb_buffer_size,
-				dibusb_urb_complete, dib);
-
-		dib->urb_list[i]->transfer_flags = 0;
-
-		dib->init_state |= DIBUSB_STATE_URB_INIT;
-	}
-
-	/* dib->pid_parse here contains the value of the module parameter */
-	/* decide if pid parsing can be deactivated:
-	 * is possible (by device type) and wanted (by user)
-	 */
-	switch (dib->dibdev->dev_cl->id) {
-		case DIBUSB2_0:
-		case DIBUSB2_0B:
-			if (dib->udev->speed == USB_SPEED_HIGH && !dib->pid_parse) {
-				def_pid_parse = 0;
-				info("running at HIGH speed, will deliver the complete TS.");
-			} else
-				info("will use pid_parsing.");
-			break;
-		default:
-			break;
-	}
-	/* from here on it contains the device and user decision */
-	dib->pid_parse = def_pid_parse;
-
-	return 0;
-}
-
-int dibusb_urb_exit(struct usb_dibusb *dib)
-{
-	int i;
-
-	dibusb_urb_kill(dib);
-
-	if (dib->init_state & DIBUSB_STATE_URB_LIST) {
-		for (i = 0; i < dib->dibdev->dev_cl->urb_count; i++) {
-			if (dib->urb_list[i] != NULL) {
-				deb_info("freeing URB no. %d.\n",i);
-				/* free the URBs */
-				usb_free_urb(dib->urb_list[i]);
-			}
-		}
-		/* free the urb array */
-		kfree(dib->urb_list);
-		dib->init_state &= ~DIBUSB_STATE_URB_LIST;
-	}
-
-	if (dib->init_state & DIBUSB_STATE_URB_BUF)
-		pci_free_consistent(NULL,
-			dib->dibdev->dev_cl->urb_buffer_size*dib->dibdev->dev_cl->urb_count,
-			dib->buffer,dib->dma_handle);
-
-	dib->init_state &= ~DIBUSB_STATE_URB_BUF;
-	dib->init_state &= ~DIBUSB_STATE_URB_INIT;
-	return 0;
-}
diff --git a/drivers/media/dvb/dibusb/dvb-dibusb.h b/drivers/media/dvb/dibusb/dvb-dibusb.h
deleted file mode 100644
index c965b64..0000000
--- a/drivers/media/dvb/dibusb/dvb-dibusb.h
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- * dvb-dibusb.h
- *
- * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
- *
- *	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.
- *
- * for more information see dvb-dibusb-core.c .
- */
-#ifndef __DVB_DIBUSB_H__
-#define __DVB_DIBUSB_H__
-
-#include <linux/input.h>
-#include <linux/config.h>
-#include <linux/usb.h>
-
-#include "dvb_frontend.h"
-#include "dvb_demux.h"
-#include "dvb_net.h"
-#include "dmxdev.h"
-
-#include "dib3000.h"
-#include "mt352.h"
-
-/* debug */
-#ifdef CONFIG_DVB_DIBCOM_DEBUG
-#define dprintk(level,args...) \
-	    do { if ((dvb_dibusb_debug & level)) { printk(args); } } while (0)
-
-#define debug_dump(b,l) {\
-	int i; \
-	for (i = 0; i < l; i++) deb_xfer("%02x ", b[i]); \
-	deb_xfer("\n");\
-}
-
-#else
-#define dprintk(args...)
-#define debug_dump(b,l)
-#endif
-
-extern int dvb_dibusb_debug;
-
-/* Version information */
-#define DRIVER_VERSION "0.3"
-#define DRIVER_DESC "DiBcom based USB Budget DVB-T device"
-#define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de"
-
-#define deb_info(args...) dprintk(0x01,args)
-#define deb_xfer(args...) dprintk(0x02,args)
-#define deb_alot(args...) dprintk(0x04,args)
-#define deb_ts(args...)   dprintk(0x08,args)
-#define deb_err(args...)  dprintk(0x10,args)
-#define deb_rc(args...)   dprintk(0x20,args)
-
-/* generic log methods - taken from usb.h */
-#undef err
-#define err(format, arg...)  printk(KERN_ERR     "dvb-dibusb: " format "\n" , ## arg)
-#undef info
-#define info(format, arg...) printk(KERN_INFO    "dvb-dibusb: " format "\n" , ## arg)
-#undef warn
-#define warn(format, arg...) printk(KERN_WARNING "dvb-dibusb: " format "\n" , ## arg)
-
-struct dibusb_usb_controller {
-	const char *name;       /* name of the usb controller */
-	u16 cpu_cs_register;    /* needs to be restarted, when the firmware has been downloaded. */
-};
-
-typedef enum {
-	DIBUSB1_1 = 0,
-	DIBUSB1_1_AN2235,
-	DIBUSB2_0,
-	UMT2_0,
-	DIBUSB2_0B,
-	NOVAT_USB2,
-	DTT200U,
-} dibusb_class_t;
-
-typedef enum {
-	DIBUSB_TUNER_CABLE_THOMSON = 0,
-	DIBUSB_TUNER_COFDM_PANASONIC_ENV57H1XD5,
-	DIBUSB_TUNER_CABLE_LG_TDTP_E102P,
-	DIBUSB_TUNER_COFDM_PANASONIC_ENV77H11D5,
-} dibusb_tuner_t;
-
-typedef enum {
-	DIBUSB_DIB3000MB = 0,
-	DIBUSB_DIB3000MC,
-	DIBUSB_MT352,
-	DTT200U_FE,
-} dibusb_demodulator_t;
-
-typedef enum {
-	DIBUSB_RC_NO = 0,
-	DIBUSB_RC_NEC_PROTOCOL,
-	DIBUSB_RC_HAUPPAUGE_PROTO,
-} dibusb_remote_t;
-
-struct dibusb_tuner {
-	dibusb_tuner_t id;
-
-	u8 pll_addr;       /* tuner i2c address */
-};
-extern struct dibusb_tuner dibusb_tuner[];
-
-#define DIBUSB_POSSIBLE_I2C_ADDR_NUM 4
-struct dibusb_demod {
-	dibusb_demodulator_t id;
-
-	int pid_filter_count;                       /* counter of the internal pid_filter */
-	u8 i2c_addrs[DIBUSB_POSSIBLE_I2C_ADDR_NUM]; /* list of possible i2c addresses of the demod */
-};
-
-#define DIBUSB_MAX_TUNER_NUM 2
-struct dibusb_device_class {
-	dibusb_class_t id;
-
-	const struct dibusb_usb_controller *usb_ctrl; /* usb controller */
-	const char *firmware;                         /* valid firmware filenames */
-
-	int pipe_cmd;                                 /* command pipe (read/write) */
-	int pipe_data;                                /* data pipe */
-
-	int urb_count;                                /* number of data URBs to be submitted */
-	int urb_buffer_size;                          /* the size of the buffer for each URB */
-
-	dibusb_remote_t remote_type;                  /* does this device have a ir-receiver */
-
-	struct dibusb_demod *demod;                   /* which demodulator is mount */
-	struct dibusb_tuner *tuner;                   /* which tuner can be found here */
-};
-
-#define DIBUSB_ID_MAX_NUM 15
-struct dibusb_usb_device {
-	const char *name;                                 /* real name of the box */
-	struct dibusb_device_class *dev_cl;               /* which dibusb_device_class is this device part of */
-
-	struct usb_device_id *cold_ids[DIBUSB_ID_MAX_NUM]; /* list of USB ids when this device is at pre firmware state */
-	struct usb_device_id *warm_ids[DIBUSB_ID_MAX_NUM]; /* list of USB ids when this device is at post firmware state */
-};
-
-/* a PID for the pid_filter list, when in use */
-struct dibusb_pid
-{
-	int index;
-	u16 pid;
-	int active;
-};
-
-struct usb_dibusb {
-	/* usb */
-	struct usb_device * udev;
-
-	struct dibusb_usb_device * dibdev;
-
-#define DIBUSB_STATE_INIT       0x000
-#define DIBUSB_STATE_URB_LIST   0x001
-#define DIBUSB_STATE_URB_BUF    0x002
-#define DIBUSB_STATE_URB_INIT	0x004
-#define DIBUSB_STATE_DVB        0x008
-#define DIBUSB_STATE_I2C        0x010
-#define DIBUSB_STATE_REMOTE		0x020
-#define DIBUSB_STATE_URB_SUBMIT 0x040
-	int init_state;
-
-	int feedcount;
-	struct dib_fe_xfer_ops xfer_ops;
-
-	struct dibusb_tuner *tuner;
-
-	struct urb **urb_list;
-	u8 *buffer;
-	dma_addr_t dma_handle;
-
-	/* I2C */
-	struct i2c_adapter i2c_adap;
-
-	/* locking */
-	struct semaphore usb_sem;
-	struct semaphore i2c_sem;
-
-	/* dvb */
-	struct dvb_adapter adapter;
-	struct dmxdev dmxdev;
-	struct dvb_demux demux;
-	struct dvb_net dvb_net;
-	struct dvb_frontend* fe;
-
-	int (*fe_sleep) (struct dvb_frontend *);
-	int (*fe_init) (struct dvb_frontend *);
-
-	/* remote control */
-	struct input_dev rc_input_dev;
-	struct work_struct rc_query_work;
-	int last_event;
-	int last_state; /* for Hauppauge RC protocol */
-	int repeat_key_count;
-	int rc_key_repeat_count; /* module parameter */
-
-	/* module parameters */
-	int pid_parse;
-	int rc_query_interval;
-};
-
-/* commonly used functions in the separated files */
-
-/* dvb-dibusb-firmware.c */
-int dibusb_loadfirmware(struct usb_device *udev, struct dibusb_usb_device *dibdev);
-
-/* dvb-dibusb-remote.c */
-int dibusb_remote_exit(struct usb_dibusb *dib);
-int dibusb_remote_init(struct usb_dibusb *dib);
-
-/* dvb-dibusb-fe-i2c.c */
-int dibusb_fe_init(struct usb_dibusb* dib);
-int dibusb_fe_exit(struct usb_dibusb *dib);
-int dibusb_i2c_init(struct usb_dibusb *dib);
-int dibusb_i2c_exit(struct usb_dibusb *dib);
-
-/* dvb-dibusb-dvb.c */
-void dibusb_urb_complete(struct urb *urb, struct pt_regs *ptregs);
-int dibusb_dvb_init(struct usb_dibusb *dib);
-int dibusb_dvb_exit(struct usb_dibusb *dib);
-
-/* dvb-dibusb-usb.c */
-int dibusb_readwrite_usb(struct usb_dibusb *dib, u8 *wbuf, u16 wlen, u8 *rbuf,
-	u16 rlen);
-int dibusb_write_usb(struct usb_dibusb *dib, u8 *buf, u16 len);
-
-int dibusb_hw_wakeup(struct dvb_frontend *);
-int dibusb_hw_sleep(struct dvb_frontend *);
-int dibusb_set_streaming_mode(struct usb_dibusb *,u8);
-int dibusb_streaming(struct usb_dibusb *,int);
-
-int dibusb_urb_init(struct usb_dibusb *);
-int dibusb_urb_exit(struct usb_dibusb *);
-
-/* dvb-fe-dtt200u.c */
-struct dvb_frontend* dtt200u_fe_attach(struct usb_dibusb *,struct dib_fe_xfer_ops *);
-
-/* i2c and transfer stuff */
-#define DIBUSB_I2C_TIMEOUT				5000
-
-/*
- * protocol of all dibusb related devices
- */
-
-/*
- * bulk msg to/from endpoint 0x01
- *
- * general structure:
- * request_byte parameter_bytes
- */
-
-#define DIBUSB_REQ_START_READ			0x00
-#define DIBUSB_REQ_START_DEMOD			0x01
-
-/*
- * i2c read
- * bulk write: 0x02 ((7bit i2c_addr << 1) & 0x01) register_bytes length_word
- * bulk read:  byte_buffer (length_word bytes)
- */
-#define DIBUSB_REQ_I2C_READ			0x02
-
-/*
- * i2c write
- * bulk write: 0x03 (7bit i2c_addr << 1) register_bytes value_bytes
- */
-#define DIBUSB_REQ_I2C_WRITE			0x03
-
-/*
- * polling the value of the remote control
- * bulk write: 0x04
- * bulk read:  byte_buffer (5 bytes)
- *
- * first byte of byte_buffer shows the status (0x00, 0x01, 0x02)
- */
-#define DIBUSB_REQ_POLL_REMOTE			0x04
-
-#define DIBUSB_RC_NEC_EMPTY				0x00
-#define DIBUSB_RC_NEC_KEY_PRESSED		0x01
-#define DIBUSB_RC_NEC_KEY_REPEATED		0x02
-
-/* additional status values for Hauppauge Remote Control Protocol */
-#define DIBUSB_RC_HAUPPAUGE_KEY_PRESSED	0x01
-#define DIBUSB_RC_HAUPPAUGE_KEY_EMPTY	0x03
-
-/* streaming mode:
- * bulk write: 0x05 mode_byte
- *
- * mode_byte is mostly 0x00
- */
-#define DIBUSB_REQ_SET_STREAMING_MODE	0x05
-
-/* interrupt the internal read loop, when blocking */
-#define DIBUSB_REQ_INTR_READ			0x06
-
-/* io control
- * 0x07 cmd_byte param_bytes
- *
- * param_bytes can be up to 32 bytes
- *
- * cmd_byte function    parameter name
- * 0x00     power mode
- *                      0x00      sleep
- *                      0x01      wakeup
- *
- * 0x01     enable streaming
- * 0x02     disable streaming
- *
- *
- */
-#define DIBUSB_REQ_SET_IOCTL			0x07
-
-/* IOCTL commands */
-
-/* change the power mode in firmware */
-#define DIBUSB_IOCTL_CMD_POWER_MODE		0x00
-#define DIBUSB_IOCTL_POWER_SLEEP			0x00
-#define DIBUSB_IOCTL_POWER_WAKEUP			0x01
-
-/* modify streaming of the FX2 */
-#define DIBUSB_IOCTL_CMD_ENABLE_STREAM	0x01
-#define DIBUSB_IOCTL_CMD_DISABLE_STREAM	0x02
-
-#endif
diff --git a/drivers/media/dvb/dibusb/dvb-fe-dtt200u.c b/drivers/media/dvb/dibusb/dvb-fe-dtt200u.c
deleted file mode 100644
index 1872aa6..0000000
--- a/drivers/media/dvb/dibusb/dvb-fe-dtt200u.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * dvb-dtt200u-fe.c is a driver which implements the frontend-part of the
- * Yakumo/Typhoon/Hama USB2.0 boxes. It is hard-wired to the dibusb-driver as
- * it uses the usb-transfer functions directly (maybe creating a
- * generic-dvb-usb-lib for all usb-drivers will be reduce some more code.)
- *
- * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de>
- *
- * see dvb-dibusb-core.c for copyright details.
- */
-
-/* guessed protocol description (reverse engineered):
- * read
- *  00 - USB type 0x02 for usb2.0, 0x01 for usb1.1
- *  81 - <TS_LOCK> <current frequency divided by 250000>
- *  82 - crash - do not touch
- *  83 - crash - do not touch
- *  84 - remote control
- *  85 - crash - do not touch (OK, stop testing here)
- *  88 - locking 2 bytes (0x80 0x40 == no signal, 0x89 0x20 == nice signal)
- *  89 - noise-to-signal
- *	8a - unkown 1 byte - signal_strength
- *  8c - ber ???
- *  8d - ber
- *  8e - unc
- *
- * write
- *  02 - bandwidth
- *  03 - frequency (divided by 250000)
- *  04 - pid table (index pid(7:0) pid(12:8))
- *  05 - reset the pid table
- *  08 - demod transfer enabled or not (FX2 transfer is enabled by default)
- */
-
-#include "dvb-dibusb.h"
-#include "dvb_frontend.h"
-
-struct dtt200u_fe_state {
-	struct usb_dibusb *dib;
-
-	struct dvb_frontend_parameters fep;
-	struct dvb_frontend frontend;
-};
-
-#define moan(which,what) info("unexpected value in '%s' for cmd '%02x' - please report to linux-dvb@linuxtv.org",which,what)
-
-static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat)
-{
-	struct dtt200u_fe_state *state = fe->demodulator_priv;
-	u8 bw[1] = { 0x81 };
-	u8 br[3] = { 0 };
-//	u8 bdeb[5] = { 0 };
-
-	dibusb_readwrite_usb(state->dib,bw,1,br,3);
-	switch (br[0]) {
-		case 0x01:
-			*stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
-			break;
-		case 0x00:
-			*stat = 0;
-			break;
-		default:
-			moan("br[0]",0x81);
-			break;
-	}
-
-//	bw[0] = 0x88;
-//	dibusb_readwrite_usb(state->dib,bw,1,bdeb,5);
-
-//	deb_info("%02x: %02x %02x %02x %02x %02x\n",bw[0],bdeb[0],bdeb[1],bdeb[2],bdeb[3],bdeb[4]);
-
-	return 0;
-}
-static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
-{
-	struct dtt200u_fe_state *state = fe->demodulator_priv;
-	u8 bw[1] = { 0x8d };
-	*ber = 0;
-	dibusb_readwrite_usb(state->dib,bw,1,(u8*) ber, 3);
-	return 0;
-}
-
-static int dtt200u_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
-{
-	struct dtt200u_fe_state *state = fe->demodulator_priv;
-	u8 bw[1] = { 0x8c };
-	*unc = 0;
-	dibusb_readwrite_usb(state->dib,bw,1,(u8*) unc, 3);
-	return 0;
-}
-
-static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
-{
-	struct dtt200u_fe_state *state = fe->demodulator_priv;
-	u8 bw[1] = { 0x8a };
-	u8 b;
-	dibusb_readwrite_usb(state->dib,bw,1,&b, 1);
-	*strength = (b << 8) | b;
-	return 0;
-}
-
-static int dtt200u_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
-{
-	struct dtt200u_fe_state *state = fe->demodulator_priv;
-	u8 bw[1] = { 0x89 };
-	u8 br[1] = { 0 };
-	dibusb_readwrite_usb(state->dib,bw,1,br,1);
-	*snr = ((0xff - br[0]) << 8) | (0xff - br[0]);
-	return 0;
-}
-
-static int dtt200u_fe_init(struct dvb_frontend* fe)
-{
-	struct dtt200u_fe_state *state = fe->demodulator_priv;
-	u8 b[] = { 0x01 };
-	return dibusb_write_usb(state->dib,b,1);
-}
-
-static int dtt200u_fe_sleep(struct dvb_frontend* fe)
-{
-	return dtt200u_fe_init(fe);
-}
-
-static int dtt200u_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
-{
-	tune->min_delay_ms = 1500;
-	tune->step_size = 166667;
-	tune->max_drift = 166667 * 2;
-	return 0;
-}
-
-static int dtt200u_fe_set_frontend(struct dvb_frontend* fe,
-				  struct dvb_frontend_parameters *fep)
-{
-	struct dtt200u_fe_state *state = fe->demodulator_priv;
-	u16 freq = fep->frequency / 250000;
-	u8 bw,bwbuf[2] = { 0x03, 0 }, freqbuf[3] = { 0x02, 0, 0 };
-
-	switch (fep->u.ofdm.bandwidth) {
-		case BANDWIDTH_8_MHZ: bw = 8; break;
-		case BANDWIDTH_7_MHZ: bw = 7; break;
-		case BANDWIDTH_6_MHZ: bw = 6; break;
-		case BANDWIDTH_AUTO: return -EOPNOTSUPP;
-		default:
-			return -EINVAL;
-	}
-	deb_info("set_frontend\n");
-
-	bwbuf[1] = bw;
-	dibusb_write_usb(state->dib,bwbuf,2);
-
-	freqbuf[1] = freq & 0xff;
-	freqbuf[2] = (freq >> 8) & 0xff;
-	dibusb_write_usb(state->dib,freqbuf,3);
-
-	memcpy(&state->fep,fep,sizeof(struct dvb_frontend_parameters));
-
-	return 0;
-}
-
-static int dtt200u_fe_get_frontend(struct dvb_frontend* fe,
-				  struct dvb_frontend_parameters *fep)
-{
-	struct dtt200u_fe_state *state = fe->demodulator_priv;
-	memcpy(fep,&state->fep,sizeof(struct dvb_frontend_parameters));
-	return 0;
-}
-
-static void dtt200u_fe_release(struct dvb_frontend* fe)
-{
-	struct dtt200u_fe_state *state = (struct dtt200u_fe_state*) fe->demodulator_priv;
-	kfree(state);
-}
-
-static int dtt200u_pid_control(struct dvb_frontend *fe,int index, int pid,int onoff)
-{
-	struct dtt200u_fe_state *state = (struct dtt200u_fe_state*) fe->demodulator_priv;
-	u8 b_pid[4];
-	pid = onoff ? pid : 0;
-
-	b_pid[0] = 0x04;
-	b_pid[1] = index;
-	b_pid[2] = pid & 0xff;
-	b_pid[3] = (pid >> 8) & 0xff;
-
-	dibusb_write_usb(state->dib,b_pid,4);
-	return 0;
-}
-
-static int dtt200u_fifo_control(struct dvb_frontend *fe, int onoff)
-{
-	struct dtt200u_fe_state *state = (struct dtt200u_fe_state*) fe->demodulator_priv;
-	u8 b_streaming[2] = { 0x08, onoff };
-	u8 b_rst_pid[1] = { 0x05 };
-
-	dibusb_write_usb(state->dib,b_streaming,2);
-
-	if (!onoff)
-		dibusb_write_usb(state->dib,b_rst_pid,1);
-	return 0;
-}
-
-static struct dvb_frontend_ops dtt200u_fe_ops;
-
-struct dvb_frontend* dtt200u_fe_attach(struct usb_dibusb *dib, struct dib_fe_xfer_ops *xfer_ops)
-{
-	struct dtt200u_fe_state* state = NULL;
-
-	/* allocate memory for the internal state */
-	state = (struct dtt200u_fe_state*) kmalloc(sizeof(struct dtt200u_fe_state), GFP_KERNEL);
-	if (state == NULL)
-		goto error;
-	memset(state,0,sizeof(struct dtt200u_fe_state));
-
-	deb_info("attaching frontend dtt200u\n");
-
-	state->dib = dib;
-
-	state->frontend.ops = &dtt200u_fe_ops;
-	state->frontend.demodulator_priv = state;
-
-	xfer_ops->fifo_ctrl = dtt200u_fifo_control;
-	xfer_ops->pid_ctrl = dtt200u_pid_control;
-
-	goto success;
-error:
-	return NULL;
-success:
-	return &state->frontend;
-}
-
-static struct dvb_frontend_ops dtt200u_fe_ops = {
-	.info = {
-		.name			= "DTT200U (Yakumo/Typhoon/Hama) DVB-T",
-		.type			= FE_OFDM,
-		.frequency_min		= 44250000,
-		.frequency_max		= 867250000,
-		.frequency_stepsize	= 250000,
-		.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 | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-				FE_CAN_TRANSMISSION_MODE_AUTO |
-				FE_CAN_GUARD_INTERVAL_AUTO |
-				FE_CAN_RECOVER |
-				FE_CAN_HIERARCHY_AUTO,
-	},
-
-	.release = dtt200u_fe_release,
-
-	.init = dtt200u_fe_init,
-	.sleep = dtt200u_fe_sleep,
-
-	.set_frontend = dtt200u_fe_set_frontend,
-	.get_frontend = dtt200u_fe_get_frontend,
-	.get_tune_settings = dtt200u_fe_get_tune_settings,
-
-	.read_status = dtt200u_fe_read_status,
-	.read_ber = dtt200u_fe_read_ber,
-	.read_signal_strength = dtt200u_fe_read_signal_strength,
-	.read_snr = dtt200u_fe_read_snr,
-	.read_ucblocks = dtt200u_fe_read_unc_blocks,
-};
diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c
index d19301d..f11daae 100644
--- a/drivers/media/dvb/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb/dvb-core/dvb_frontend.c
@@ -35,6 +35,7 @@
 #include <linux/moduleparam.h>
 #include <linux/list.h>
 #include <linux/suspend.h>
+#include <linux/jiffies.h>
 #include <asm/processor.h>
 #include <asm/semaphore.h>
 
@@ -327,7 +328,8 @@
 		return 1;
 
 	if (fepriv->dvbdev->writers == 1)
-		if (jiffies - fepriv->release_jiffies > dvb_shutdown_timeout * HZ)
+		if (time_after(jiffies, fepriv->release_jiffies +
+					dvb_shutdown_timeout * HZ))
 			return 1;
 
 	return 0;
@@ -389,8 +391,7 @@
 			break;
 		}
 
-		if (current->flags & PF_FREEZE)
-			refrigerator(PF_FREEZE);
+		try_to_freeze();
 
 		if (down_interruptible(&fepriv->sem))
 			break;
diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c
index 9d9662f..4b7adca 100644
--- a/drivers/media/dvb/dvb-core/dvbdev.c
+++ b/drivers/media/dvb/dvb-core/dvbdev.c
@@ -56,8 +56,7 @@
 #define nums2minor(num,type,id)	((num << 6) | (id << 4) | type)
 #define MAX_DVB_MINORS		(DVB_MAX_ADAPTERS*64)
 
-struct class_simple *dvb_class;
-EXPORT_SYMBOL(dvb_class);
+static struct class *dvb_class;
 
 static struct dvb_device* dvbdev_find_device (int minor)
 {
@@ -236,8 +235,8 @@
 			S_IFCHR | S_IRUSR | S_IWUSR,
 			"dvb/adapter%d/%s%d", adap->num, dnames[type], id);
 
-	class_simple_device_add(dvb_class, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
-				NULL, "dvb%d.%s%d", adap->num, dnames[type], id);
+	class_device_create(dvb_class, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)),
+			    NULL, "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),
@@ -256,7 +255,7 @@
 	devfs_remove("dvb/adapter%d/%s%d", dvbdev->adapter->num,
 			dnames[dvbdev->type], dvbdev->id);
 
-	class_simple_device_remove(MKDEV(DVB_MAJOR, nums2minor(dvbdev->adapter->num,
+	class_device_destroy(dvb_class, MKDEV(DVB_MAJOR, nums2minor(dvbdev->adapter->num,
 					dvbdev->type, dvbdev->id)));
 
 	list_del (&dvbdev->list_head);
@@ -412,7 +411,7 @@
 
 	devfs_mk_dir("dvb");
 
-	dvb_class = class_simple_create(THIS_MODULE, "dvb");
+	dvb_class = class_create(THIS_MODULE, "dvb");
 	if (IS_ERR(dvb_class)) {
 		retval = PTR_ERR(dvb_class);
 		goto error;
@@ -429,7 +428,7 @@
 static void __exit exit_dvbdev(void)
 {
         devfs_remove("dvb");
-	class_simple_destroy(dvb_class);
+	class_destroy(dvb_class);
 	cdev_del(&dvb_device_cdev);
         unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS);
 }
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
new file mode 100644
index 0000000..8aa32f6
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/Kconfig
@@ -0,0 +1,99 @@
+config DVB_USB
+	tristate "Support for various USB DVB devices"
+	depends on DVB_CORE && USB
+	select FW_LOADER
+	help
+	  By enabling this you will be able to choose the various USB 1.1 and
+	  USB2.0 DVB devices.
+
+	  Almost every USB device needs a firmware, please look into
+	  <file:Documentation/dvb/README.dvb-usb>
+
+	  Say Y if you own an USB DVB device.
+
+config DVB_USB_DEBUG
+	bool "Enable extended debug support for all DVB-USB devices"
+	depends on DVB_USB
+	help
+	  Say Y if you want to enable debuging. See modinfo dvb-usb (and the
+	  appropriate drivers) for debug levels.
+
+config DVB_USB_A800
+	tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)"
+	depends on DVB_USB
+	help
+	  Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver.
+
+config DVB_USB_DIBUSB_MB
+	tristate "DiBcom USB DVB-T devices (based on the DiB3000M-B) (see help for device list)"
+	depends on DVB_USB
+	help
+	  Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by
+	  DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
+
+	  Devices supported by this driver:
+	    TwinhanDTV USB-Ter (VP7041)
+	    TwinhanDTV Magic Box (VP7041e)
+	    KWorld/JetWay/ADSTech V-Stream XPERT DTV - DVB-T USB1.1 and USB2.0
+	    Hama DVB-T USB1.1-Box
+	    DiBcom USB1.1 reference devices (non-public)
+	    Ultima Electronic/Artec T1 USB TVBOX
+	    Compro Videomate DVB-U2000 - DVB-T USB
+	    Grandtec DVB-T USB
+	    Avermedia AverTV DVBT USB1.1
+	    Artec T1 USB1.1 boxes
+
+	  The VP7041 seems to be identical to "CTS Portable" (Chinese
+	  Television System).
+
+	  Say Y if you own such a device and want to use it. You should build it as
+	  a module.
+
+config DVB_USB_DIBUSB_MC
+	tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)"
+	depends on DVB_USB
+	help
+	  Support for 2.0 DVB-T receivers based on reference designs made by
+	  DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator.
+
+	  Devices supported by this driver:
+	    DiBcom USB2.0 reference devices (non-public)
+	    Artec T1 USB2.0 boxes
+
+	  Say Y if you own such a device and want to use it. You should build it as
+	  a module.
+
+config DVB_USB_UMT_010
+	tristate "HanfTek UMT-010 DVB-T USB2.0 support"
+	depends on DVB_USB
+	help
+	  Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver.
+
+config DVB_USB_DIGITV
+	tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support"
+	depends on DVB_USB
+	help
+	  Say Y here to support the Nebula Electronics uDigitV USB2.0 DVB-T receiver.
+
+config DVB_USB_VP7045
+	tristate "TwinhanDTV Alpha/MagicBoxII and DNTV tinyUSB2 DVB-T USB2.0 support"
+	depends on DVB_USB
+	help
+	  Say Y here to support the
+	    TwinhanDTV Alpha (stick) (VP-7045),
+		TwinhanDTV MagicBox II (VP-7046) and
+		DigitalNow TinyUSB 2 DVB-t DVB-T USB2.0 receivers.
+
+config DVB_USB_NOVA_T_USB2
+	tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
+	depends on DVB_USB
+	help
+	  Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver.
+
+config DVB_USB_DTT200U
+	tristate "Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 support"
+	depends on DVB_USB
+	help
+	  Say Y here to support the Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 receiver.
+
+	  The receivers are also known as DTT200U (Yakumo) and UB300 (Yuan).
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
new file mode 100644
index 0000000..d65b50f
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/Makefile
@@ -0,0 +1,30 @@
+dvb-usb-objs = dvb-usb-firmware.o dvb-usb-init.o dvb-usb-urb.o dvb-usb-i2c.o dvb-usb-dvb.o dvb-usb-remote.o
+obj-$(CONFIG_DVB_USB) += dvb-usb.o
+
+dvb-usb-vp7045-objs = vp7045.o vp7045-fe.o
+obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o
+
+dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o
+obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o
+
+dvb-usb-dibusb-common-objs = dibusb-common.o
+
+dvb-usb-a800-objs = a800.o
+obj-$(CONFIG_DVB_USB_A800) += dvb-usb-dibusb-common.o dvb-usb-a800.o
+
+dvb-usb-dibusb-mb-objs = dibusb-mb.o
+obj-$(CONFIG_DVB_USB_DIBUSB_MB) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mb.o
+
+dvb-usb-dibusb-mc-objs = dibusb-mc.o
+obj-$(CONFIG_DVB_USB_DIBUSB_MC) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mc.o
+
+dvb-usb-nova-t-usb2-objs = nova-t-usb2.o
+obj-$(CONFIG_DVB_USB_NOVA_T_USB2) += dvb-usb-dibusb-common.o dvb-usb-nova-t-usb2.o
+
+dvb-usb-umt-010-objs = umt-010.o
+obj-$(CONFIG_DVB_USB_UMT_010) += dvb-usb-dibusb-common.o dvb-usb-umt-010.o
+
+dvb-usb-digitv-objs = digitv.o
+obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o
+
+EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/drivers/media/dvb/dvb-usb/a800.c b/drivers/media/dvb/dvb-usb/a800.c
new file mode 100644
index 0000000..a354293
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/a800.c
@@ -0,0 +1,176 @@
+/* DVB USB framework compliant Linux driver for the AVerMedia AverTV DVB-T
+ * USB2.0 (A800) DVB-T receiver.
+ *
+ * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * Thanks to
+ *   - AVerMedia who kindly provided information and
+ *   - Glen Harris who suffered from my mistakes during development.
+ *
+ *	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 "dibusb.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (rc=1 (or-able))." DVB_USB_DEBUG_STATUS);
+#define deb_rc(args...)   dprintk(debug,0x01,args)
+
+static int a800_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	/* do nothing for the AVerMedia */
+	return 0;
+}
+
+static struct dvb_usb_rc_key a800_rc_keys[] = {
+	{ 0x02, 0x01, KEY_PROG1 },       /* SOURCE */
+	{ 0x02, 0x00, KEY_POWER },       /* POWER */
+	{ 0x02, 0x05, KEY_1 },           /* 1 */
+	{ 0x02, 0x06, KEY_2 },           /* 2 */
+	{ 0x02, 0x07, KEY_3 },           /* 3 */
+	{ 0x02, 0x09, KEY_4 },           /* 4 */
+	{ 0x02, 0x0a, KEY_5 },           /* 5 */
+	{ 0x02, 0x0b, KEY_6 },           /* 6 */
+	{ 0x02, 0x0d, KEY_7 },           /* 7 */
+	{ 0x02, 0x0e, KEY_8 },           /* 8 */
+	{ 0x02, 0x0f, KEY_9 },           /* 9 */
+	{ 0x02, 0x12, KEY_LEFT },        /* L / DISPLAY */
+	{ 0x02, 0x11, KEY_0 },           /* 0 */
+	{ 0x02, 0x13, KEY_RIGHT },       /* R / CH RTN */
+	{ 0x02, 0x17, KEY_PROG2 },       /* SNAP SHOT */
+	{ 0x02, 0x10, KEY_PROG3 },       /* 16-CH PREV */
+	{ 0x02, 0x03, KEY_CHANNELUP },   /* CH UP */
+	{ 0x02, 0x1e, KEY_VOLUMEDOWN },  /* VOL DOWN */
+	{ 0x02, 0x0c, KEY_ZOOM },        /* FULL SCREEN */
+	{ 0x02, 0x1f, KEY_VOLUMEUP },    /* VOL UP */
+	{ 0x02, 0x02, KEY_CHANNELDOWN }, /* CH DOWN */
+	{ 0x02, 0x14, KEY_MUTE },        /* MUTE */
+	{ 0x02, 0x08, KEY_AUDIO },       /* AUDIO */
+	{ 0x02, 0x19, KEY_RECORD },      /* RECORD */
+	{ 0x02, 0x18, KEY_PLAY },        /* PLAY */
+	{ 0x02, 0x1b, KEY_STOP },        /* STOP */
+	{ 0x02, 0x1a, KEY_PLAYPAUSE },   /* TIMESHIFT / PAUSE */
+	{ 0x02, 0x1d, KEY_BACK },        /* << / RED */
+	{ 0x02, 0x1c, KEY_FORWARD },     /* >> / YELLOW */
+	{ 0x02, 0x03, KEY_TEXT },        /* TELETEXT */
+	{ 0x02, 0x01, KEY_FIRST },       /* |<< / GREEN */
+	{ 0x02, 0x00, KEY_LAST },        /* >>| / BLUE */
+	{ 0x02, 0x04, KEY_EPG },         /* EPG */
+	{ 0x02, 0x15, KEY_MENU },        /* MENU */
+};
+
+int a800_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+	u8 key[5];
+	if (usb_control_msg(d->udev,usb_rcvctrlpipe(d->udev,0),
+				0x04, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, key, 5,
+				2*HZ) != 5)
+		return -ENODEV;
+
+	/* call the universal NEC remote processor, to find out the key's state and event */
+	dvb_usb_nec_rc_key_to_event(d,key,event,state);
+	if (key[0] != 0)
+		deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
+	return 0;
+}
+
+/* USB Driver stuff */
+static struct dvb_usb_properties a800_properties;
+
+static int a800_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	return dvb_usb_device_init(intf,&a800_properties,THIS_MODULE);
+}
+
+/* do not change the order of the ID table */
+static struct usb_device_id a800_table [] = {
+/* 00 */	{ USB_DEVICE(USB_VID_AVERMEDIA,     USB_PID_AVERMEDIA_DVBT_USB2_COLD) },
+/* 01 */	{ USB_DEVICE(USB_VID_AVERMEDIA,     USB_PID_AVERMEDIA_DVBT_USB2_WARM) },
+			{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, a800_table);
+
+static struct dvb_usb_properties a800_properties = {
+	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
+	.pid_filter_count = 32,
+
+	.usb_ctrl = CYPRESS_FX2,
+
+	.firmware = "dvb-usb-avertv-a800-02.fw",
+
+	.size_of_priv     = sizeof(struct dibusb_state),
+
+	.streaming_ctrl   = dibusb2_0_streaming_ctrl,
+	.pid_filter       = dibusb_pid_filter,
+	.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
+	.power_ctrl       = a800_power_ctrl,
+	.frontend_attach  = dibusb_dib3000mc_frontend_attach,
+	.tuner_attach     = dibusb_dib3000mc_tuner_attach,
+
+	.rc_interval      = DEFAULT_RC_INTERVAL,
+	.rc_key_map       = a800_rc_keys,
+	.rc_key_map_size  = ARRAY_SIZE(a800_rc_keys),
+	.rc_query         = a800_rc_query,
+
+	.i2c_algo         = &dibusb_i2c_algo,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
+	/* parameter for the MPEG2-data transfer */
+	.urb = {
+		.type = DVB_USB_BULK,
+		.count = 7,
+		.endpoint = 0x06,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+
+	.num_device_descs = 1,
+	.devices = {
+		{   "AVerMedia AverTV DVB-T USB 2.0 (A800)",
+			{ &a800_table[0], NULL },
+			{ &a800_table[1], NULL },
+		},
+	}
+};
+
+static struct usb_driver a800_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "AVerMedia AverTV DVB-T USB 2.0 (A800)",
+	.probe		= a800_probe,
+	.disconnect = dvb_usb_device_exit,
+	.id_table	= a800_table,
+};
+
+/* module stuff */
+static int __init a800_module_init(void)
+{
+	int result;
+	if ((result = usb_register(&a800_driver))) {
+		err("usb_register failed. Error number %d",result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void __exit a800_module_exit(void)
+{
+	/* deregister this driver from the USB subsystem */
+	usb_deregister(&a800_driver);
+}
+
+module_init (a800_module_init);
+module_exit (a800_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("AVerMedia AverTV DVB-T USB 2.0 (A800)");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dibusb-common.c b/drivers/media/dvb/dvb-usb/dibusb-common.c
new file mode 100644
index 0000000..63b626f
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dibusb-common.c
@@ -0,0 +1,272 @@
+/* Common methods for dibusb-based-receivers.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ *	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 "dibusb.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info (|-able))." DVB_USB_DEBUG_STATUS);
+MODULE_LICENSE("GPL");
+
+#define deb_info(args...) dprintk(debug,0x01,args)
+
+/* common stuff used by the different dibusb modules */
+int dibusb_streaming_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	if (d->priv != NULL) {
+		struct dib_fe_xfer_ops *ops = d->priv;
+		if (ops->fifo_ctrl != NULL)
+			if (ops->fifo_ctrl(d->fe,onoff)) {
+				err("error while controlling the fifo of the demod.");
+				return -ENODEV;
+			}
+	}
+	return 0;
+}
+EXPORT_SYMBOL(dibusb_streaming_ctrl);
+
+int dibusb_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff)
+{
+	if (d->priv != NULL) {
+		struct dib_fe_xfer_ops *ops = d->priv;
+		if (d->pid_filtering && ops->pid_ctrl != NULL)
+			ops->pid_ctrl(d->fe,index,pid,onoff);
+	}
+	return 0;
+}
+EXPORT_SYMBOL(dibusb_pid_filter);
+
+int dibusb_pid_filter_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	if (d->priv != NULL) {
+		struct dib_fe_xfer_ops *ops = d->priv;
+		if (ops->pid_parse != NULL)
+			if (ops->pid_parse(d->fe,onoff) < 0)
+				err("could not handle pid_parser");
+	}
+	return 0;
+}
+EXPORT_SYMBOL(dibusb_pid_filter_ctrl);
+
+int dibusb_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	u8 b[3];
+	int ret;
+	b[0] = DIBUSB_REQ_SET_IOCTL;
+	b[1] = DIBUSB_IOCTL_CMD_POWER_MODE;
+	b[2] = onoff ? DIBUSB_IOCTL_POWER_WAKEUP : DIBUSB_IOCTL_POWER_SLEEP;
+	ret = dvb_usb_generic_write(d,b,3);
+	msleep(10);
+	return ret;
+}
+EXPORT_SYMBOL(dibusb_power_ctrl);
+
+int dibusb2_0_streaming_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	u8 b[2];
+	b[0] = DIBUSB_REQ_SET_IOCTL;
+	b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM;
+
+	dvb_usb_generic_write(d,b,3);
+
+	return dibusb_streaming_ctrl(d,onoff);
+}
+EXPORT_SYMBOL(dibusb2_0_streaming_ctrl);
+
+int dibusb2_0_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	if (onoff) {
+		u8 b[3] = { DIBUSB_REQ_SET_IOCTL, DIBUSB_IOCTL_CMD_POWER_MODE, DIBUSB_IOCTL_POWER_WAKEUP };
+		return dvb_usb_generic_write(d,b,3);
+	} else
+		return 0;
+}
+EXPORT_SYMBOL(dibusb2_0_power_ctrl);
+
+static int dibusb_i2c_msg(struct dvb_usb_device *d, u8 addr,
+			  u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
+{
+	u8 sndbuf[wlen+4]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */
+	/* write only ? */
+	int wo = (rbuf == NULL || rlen == 0),
+		len = 2 + wlen + (wo ? 0 : 2);
+
+	sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ;
+	sndbuf[1] = (addr << 1) | (wo ? 0 : 1);
+
+	memcpy(&sndbuf[2],wbuf,wlen);
+
+	if (!wo) {
+		sndbuf[wlen+2] = (rlen >> 8) & 0xff;
+		sndbuf[wlen+3] = rlen & 0xff;
+	}
+
+	return dvb_usb_generic_rw(d,sndbuf,len,rbuf,rlen,0);
+}
+
+/*
+ * I2C master xfer function
+ */
+static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
+{
+	struct dvb_usb_device *d = i2c_get_adapdata(adap);
+	int i;
+
+	if (down_interruptible(&d->i2c_sem) < 0)
+		return -EAGAIN;
+
+	if (num > 2)
+		warn("more than 2 i2c messages at a time is not handled yet. TODO.");
+
+	for (i = 0; i < num; i++) {
+		/* write/read request */
+		if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
+			if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,
+						msg[i+1].buf,msg[i+1].len) < 0)
+				break;
+			i++;
+		} else
+			if (dibusb_i2c_msg(d, msg[i].addr, msg[i].buf,msg[i].len,NULL,0) < 0)
+				break;
+	}
+
+	up(&d->i2c_sem);
+	return i;
+}
+
+static u32 dibusb_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+struct i2c_algorithm dibusb_i2c_algo = {
+	.name          = "DiBcom USB I2C algorithm",
+	.id            = I2C_ALGO_BIT,
+	.master_xfer   = dibusb_i2c_xfer,
+	.functionality = dibusb_i2c_func,
+};
+EXPORT_SYMBOL(dibusb_i2c_algo);
+
+int dibusb_read_eeprom_byte(struct dvb_usb_device *d, u8 offs, u8 *val)
+{
+	u8 wbuf[1] = { offs };
+	return dibusb_i2c_msg(d, 0x50, wbuf, 1, val, 1);
+}
+EXPORT_SYMBOL(dibusb_read_eeprom_byte);
+
+int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *d)
+{
+	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->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
+			return 0;
+		}
+
+	return -ENODEV;
+}
+EXPORT_SYMBOL(dibusb_dib3000mc_frontend_attach);
+
+int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *d)
+{
+	d->pll_addr = 0x60;
+	d->pll_desc = &dvb_pll_env57h1xd5;
+	return 0;
+}
+EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach);
+
+/*
+ * common remote control stuff
+ */
+struct dvb_usb_rc_key dibusb_rc_keys[] = {
+	/* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */
+	{ 0x00, 0x16, KEY_POWER },
+	{ 0x00, 0x10, KEY_MUTE },
+	{ 0x00, 0x03, KEY_1 },
+	{ 0x00, 0x01, KEY_2 },
+	{ 0x00, 0x06, KEY_3 },
+	{ 0x00, 0x09, KEY_4 },
+	{ 0x00, 0x1d, KEY_5 },
+	{ 0x00, 0x1f, KEY_6 },
+	{ 0x00, 0x0d, KEY_7 },
+	{ 0x00, 0x19, KEY_8 },
+	{ 0x00, 0x1b, KEY_9 },
+	{ 0x00, 0x15, KEY_0 },
+	{ 0x00, 0x05, KEY_CHANNELUP },
+	{ 0x00, 0x02, KEY_CHANNELDOWN },
+	{ 0x00, 0x1e, KEY_VOLUMEUP },
+	{ 0x00, 0x0a, KEY_VOLUMEDOWN },
+	{ 0x00, 0x11, KEY_RECORD },
+	{ 0x00, 0x17, KEY_FAVORITES }, /* Heart symbol - Channel list. */
+	{ 0x00, 0x14, KEY_PLAY },
+	{ 0x00, 0x1a, KEY_STOP },
+	{ 0x00, 0x40, KEY_REWIND },
+	{ 0x00, 0x12, KEY_FASTFORWARD },
+	{ 0x00, 0x0e, KEY_PREVIOUS }, /* Recall - Previous channel. */
+	{ 0x00, 0x4c, KEY_PAUSE },
+	{ 0x00, 0x4d, KEY_SCREEN }, /* Full screen mode. */
+	{ 0x00, 0x54, KEY_AUDIO }, /* MTS - Switch to secondary audio. */
+	/* additional keys TwinHan VisionPlus, the Artec seemingly not have */
+	{ 0x00, 0x0c, KEY_CANCEL }, /* Cancel */
+	{ 0x00, 0x1c, KEY_EPG }, /* EPG */
+	{ 0x00, 0x00, KEY_TAB }, /* Tab */
+	{ 0x00, 0x48, KEY_INFO }, /* Preview */
+	{ 0x00, 0x04, KEY_LIST }, /* RecordList */
+	{ 0x00, 0x0f, KEY_TEXT }, /* Teletext */
+	/* Key codes for the KWorld/ADSTech/JetWay remote. */
+	{ 0x86, 0x12, KEY_POWER },
+	{ 0x86, 0x0f, KEY_SELECT }, /* source */
+	{ 0x86, 0x0c, KEY_UNKNOWN }, /* scan */
+	{ 0x86, 0x0b, KEY_EPG },
+	{ 0x86, 0x10, KEY_MUTE },
+	{ 0x86, 0x01, KEY_1 },
+	{ 0x86, 0x02, KEY_2 },
+	{ 0x86, 0x03, KEY_3 },
+	{ 0x86, 0x04, KEY_4 },
+	{ 0x86, 0x05, KEY_5 },
+	{ 0x86, 0x06, KEY_6 },
+	{ 0x86, 0x07, KEY_7 },
+	{ 0x86, 0x08, KEY_8 },
+	{ 0x86, 0x09, KEY_9 },
+	{ 0x86, 0x0a, KEY_0 },
+	{ 0x86, 0x18, KEY_ZOOM },
+	{ 0x86, 0x1c, KEY_UNKNOWN }, /* preview */
+	{ 0x86, 0x13, KEY_UNKNOWN }, /* snap */
+	{ 0x86, 0x00, KEY_UNDO },
+	{ 0x86, 0x1d, KEY_RECORD },
+	{ 0x86, 0x0d, KEY_STOP },
+	{ 0x86, 0x0e, KEY_PAUSE },
+	{ 0x86, 0x16, KEY_PLAY },
+	{ 0x86, 0x11, KEY_BACK },
+	{ 0x86, 0x19, KEY_FORWARD },
+	{ 0x86, 0x14, KEY_UNKNOWN }, /* pip */
+	{ 0x86, 0x15, KEY_ESC },
+	{ 0x86, 0x1a, KEY_UP },
+	{ 0x86, 0x1e, KEY_DOWN },
+	{ 0x86, 0x1f, KEY_LEFT },
+	{ 0x86, 0x1b, KEY_RIGHT },
+};
+EXPORT_SYMBOL(dibusb_rc_keys);
+
+int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+	u8 key[5],cmd = DIBUSB_REQ_POLL_REMOTE;
+	dvb_usb_generic_rw(d,&cmd,1,key,5,0);
+	dvb_usb_nec_rc_key_to_event(d,key,event,state);
+	if (key[0] != 0)
+		deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
+	return 0;
+}
+EXPORT_SYMBOL(dibusb_rc_query);
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mb.c b/drivers/media/dvb/dvb-usb/dibusb-mb.c
new file mode 100644
index 0000000..a0ffbb5
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dibusb-mb.c
@@ -0,0 +1,316 @@
+/* DVB USB compliant linux driver for mobile DVB-T USB devices based on
+ * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-B)
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * based on GPL code from DiBcom, which has
+ * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "dibusb.h"
+
+static int dibusb_dib3000mb_frontend_attach(struct dvb_usb_device *d)
+{
+	struct dib3000_config demod_cfg;
+	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)
+		return -ENODEV;
+
+	d->tuner_pass_ctrl = st->ops.tuner_pass_ctrl;
+
+	return 0;
+}
+
+/* some of the dibusb 1.1 device aren't equipped with the default tuner
+ * (Thomson Cable), but with a Panasonic ENV77H11D5.  This function figures
+ * this out. */
+static int dibusb_dib3000mb_tuner_attach (struct dvb_usb_device *d)
+{
+	u8 b[2] = { 0,0 }, b2[1];
+	int ret = 0;
+	struct i2c_msg msg[2] = {
+		{ .flags = 0,        .buf = b,  .len = 2 },
+		{ .flags = I2C_M_RD, .buf = b2, .len = 1 },
+	};
+
+	/* the Panasonic sits on I2C addrass 0x60, the Thomson on 0x61 */
+	msg[0].addr = msg[1].addr = 0x60;
+
+	if (d->tuner_pass_ctrl)
+		d->tuner_pass_ctrl(d->fe,1,msg[0].addr);
+
+	if (i2c_transfer (&d->i2c_adap, msg, 2) != 2) {
+		err("tuner i2c write failed.");
+		ret = -EREMOTEIO;
+	}
+
+	if (d->tuner_pass_ctrl)
+		d->tuner_pass_ctrl(d->fe,0,msg[0].addr);
+
+	if (b2[0] == 0xfe) {
+		info("this device has the Thomson Cable onboard. Which is default.");
+		d->pll_addr = 0x61;
+		d->pll_desc = &dvb_pll_tua6010xs;
+	} else {
+		u8 bpll[4] = { 0x0b, 0xf5, 0x85, 0xab };
+		info("this device has the Panasonic ENV77H11D5 onboard.");
+		d->pll_addr = 0x60;
+		memcpy(d->pll_init,bpll,4);
+		d->pll_desc = &dvb_pll_tda665x;
+	}
+
+	return ret;
+}
+
+/* USB Driver stuff */
+static struct dvb_usb_properties dibusb1_1_properties;
+static struct dvb_usb_properties dibusb1_1_an2235_properties;
+static struct dvb_usb_properties dibusb2_0b_properties;
+
+static int dibusb_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	if (dvb_usb_device_init(intf,&dibusb1_1_properties,THIS_MODULE) == 0 ||
+		dvb_usb_device_init(intf,&dibusb1_1_an2235_properties,THIS_MODULE) == 0 ||
+		dvb_usb_device_init(intf,&dibusb2_0b_properties,THIS_MODULE) == 0)
+		return 0;
+
+	return -EINVAL;
+}
+
+/* do not change the order of the ID table */
+static struct usb_device_id dibusb_dib3000mb_table [] = {
+/* 00 */	{ USB_DEVICE(USB_VID_AVERMEDIA_UNK,	USB_PID_AVERMEDIA_DVBT_USB_COLD)},
+/* 01 */	{ USB_DEVICE(USB_VID_AVERMEDIA_UNK,	USB_PID_AVERMEDIA_DVBT_USB_WARM)},
+/* 02 */	{ USB_DEVICE(USB_VID_COMPRO,		USB_PID_COMPRO_DVBU2000_COLD) },
+/* 03 */	{ USB_DEVICE(USB_VID_COMPRO,		USB_PID_COMPRO_DVBU2000_WARM) },
+/* 04 */	{ USB_DEVICE(USB_VID_COMPRO_UNK,	USB_PID_COMPRO_DVBU2000_UNK_COLD) },
+/* 05 */	{ USB_DEVICE(USB_VID_DIBCOM,		USB_PID_DIBCOM_MOD3000_COLD) },
+/* 06 */	{ USB_DEVICE(USB_VID_DIBCOM,		USB_PID_DIBCOM_MOD3000_WARM) },
+/* 07 */	{ USB_DEVICE(USB_VID_EMPIA,			USB_PID_KWORLD_VSTREAM_COLD) },
+/* 08 */	{ USB_DEVICE(USB_VID_EMPIA,			USB_PID_KWORLD_VSTREAM_WARM) },
+/* 09 */	{ USB_DEVICE(USB_VID_GRANDTEC,		USB_PID_GRANDTEC_DVBT_USB_COLD) },
+/* 10 */	{ USB_DEVICE(USB_VID_GRANDTEC,		USB_PID_GRANDTEC_DVBT_USB_WARM) },
+/* 11 */	{ USB_DEVICE(USB_VID_GRANDTEC,		USB_PID_DIBCOM_MOD3000_COLD) },
+/* 12 */	{ USB_DEVICE(USB_VID_GRANDTEC,		USB_PID_DIBCOM_MOD3000_WARM) },
+/* 13 */	{ USB_DEVICE(USB_VID_HYPER_PALTEK,	USB_PID_UNK_HYPER_PALTEK_COLD) },
+/* 14 */	{ USB_DEVICE(USB_VID_HYPER_PALTEK,	USB_PID_UNK_HYPER_PALTEK_WARM) },
+/* 15 */	{ USB_DEVICE(USB_VID_VISIONPLUS,	USB_PID_TWINHAN_VP7041_COLD) },
+/* 16 */	{ USB_DEVICE(USB_VID_VISIONPLUS,	USB_PID_TWINHAN_VP7041_WARM) },
+/* 17 */	{ USB_DEVICE(USB_VID_TWINHAN,		USB_PID_TWINHAN_VP7041_COLD) },
+/* 18 */	{ USB_DEVICE(USB_VID_TWINHAN,		USB_PID_TWINHAN_VP7041_WARM) },
+/* 19 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_COLD) },
+/* 20 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_WARM) },
+/* 21 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_COLD) },
+/* 22 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC, USB_PID_ULTIMA_TVBOX_AN2235_WARM) },
+/* 23 */	{ USB_DEVICE(USB_VID_ADSTECH,		USB_PID_ADSTECH_USB2_COLD) },
+/* 24 */	{ USB_DEVICE(USB_VID_ADSTECH,		USB_PID_ADSTECH_USB2_WARM) },
+			{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, dibusb_dib3000mb_table);
+
+static struct dvb_usb_properties dibusb1_1_properties = {
+	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
+	.pid_filter_count = 16,
+
+	.usb_ctrl = CYPRESS_AN2135,
+
+	.firmware = "dvb-usb-dibusb-5.0.0.11.fw",
+
+	.size_of_priv     = sizeof(struct dibusb_state),
+
+	.streaming_ctrl   = dibusb_streaming_ctrl,
+	.pid_filter       = dibusb_pid_filter,
+	.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
+	.power_ctrl       = dibusb_power_ctrl,
+	.frontend_attach  = dibusb_dib3000mb_frontend_attach,
+	.tuner_attach     = dibusb_dib3000mb_tuner_attach,
+
+	.rc_interval      = DEFAULT_RC_INTERVAL,
+	.rc_key_map       = dibusb_rc_keys,
+	.rc_key_map_size  = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
+	.rc_query         = dibusb_rc_query,
+
+	.i2c_algo         = &dibusb_i2c_algo,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
+	/* parameter for the MPEG2-data transfer */
+	.urb = {
+		.type = DVB_USB_BULK,
+		.count = 7,
+		.endpoint = 0x02,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+
+	.num_device_descs = 8,
+	.devices = {
+		{	"AVerMedia AverTV DVBT USB1.1",
+			{ &dibusb_dib3000mb_table[0],  NULL },
+			{ &dibusb_dib3000mb_table[1],  NULL },
+		},
+		{	"Compro Videomate DVB-U2000 - DVB-T USB1.1 (please confirm to linux-dvb)",
+			{ &dibusb_dib3000mb_table[2], &dibusb_dib3000mb_table[4], NULL},
+			{ &dibusb_dib3000mb_table[3], NULL },
+		},
+		{	"DiBcom USB1.1 DVB-T reference design (MOD3000)",
+			{ &dibusb_dib3000mb_table[5],  NULL },
+			{ &dibusb_dib3000mb_table[6],  NULL },
+		},
+		{	"KWorld V-Stream XPERT DTV - DVB-T USB1.1",
+			{ &dibusb_dib3000mb_table[7], NULL },
+			{ &dibusb_dib3000mb_table[8], NULL },
+		},
+		{	"Grandtec USB1.1 DVB-T",
+			{ &dibusb_dib3000mb_table[9],  &dibusb_dib3000mb_table[11], NULL },
+			{ &dibusb_dib3000mb_table[10], &dibusb_dib3000mb_table[12], NULL },
+		},
+		{	"Unkown USB1.1 DVB-T device ???? please report the name to the author",
+			{ &dibusb_dib3000mb_table[13], NULL },
+			{ &dibusb_dib3000mb_table[14], NULL },
+		},
+		{	"TwinhanDTV USB-Ter USB1.1 / Magic Box I / HAMA USB1.1 DVB-T device",
+			{ &dibusb_dib3000mb_table[15], &dibusb_dib3000mb_table[17], NULL},
+			{ &dibusb_dib3000mb_table[16], &dibusb_dib3000mb_table[18], NULL},
+		},
+		{	"Artec T1 USB1.1 TVBOX with AN2135",
+			{ &dibusb_dib3000mb_table[19], NULL },
+			{ &dibusb_dib3000mb_table[20], NULL },
+		},
+	}
+};
+
+static struct dvb_usb_properties dibusb1_1_an2235_properties = {
+	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
+	.usb_ctrl = CYPRESS_AN2235,
+
+	.firmware = "dvb-usb-dibusb-an2235-01.fw",
+
+	.size_of_priv     = sizeof(struct dibusb_state),
+
+	.streaming_ctrl   = dibusb_streaming_ctrl,
+	.pid_filter       = dibusb_pid_filter,
+	.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
+	.power_ctrl       = dibusb_power_ctrl,
+	.frontend_attach  = dibusb_dib3000mb_frontend_attach,
+	.tuner_attach     = dibusb_dib3000mb_tuner_attach,
+
+	.rc_interval      = DEFAULT_RC_INTERVAL,
+	.rc_key_map       = dibusb_rc_keys,
+	.rc_key_map_size  = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
+	.rc_query         = dibusb_rc_query,
+
+	.i2c_algo         = &dibusb_i2c_algo,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
+	/* parameter for the MPEG2-data transfer */
+	.urb = {
+		.type = DVB_USB_BULK,
+		.count = 7,
+		.endpoint = 0x02,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+
+	.num_device_descs = 1,
+	.devices = {
+		{	"Artec T1 USB1.1 TVBOX with AN2235",
+			{ &dibusb_dib3000mb_table[20], NULL },
+			{ &dibusb_dib3000mb_table[21], NULL },
+		},
+	}
+};
+
+static struct dvb_usb_properties dibusb2_0b_properties = {
+	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
+	.usb_ctrl = CYPRESS_FX2,
+
+	.firmware = "dvb-usb-adstech-usb2-01.fw",
+
+	.size_of_priv     = sizeof(struct dibusb_state),
+
+	.streaming_ctrl   = dibusb2_0_streaming_ctrl,
+	.pid_filter       = dibusb_pid_filter,
+	.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
+	.power_ctrl       = dibusb2_0_power_ctrl,
+	.frontend_attach  = dibusb_dib3000mb_frontend_attach,
+	.tuner_attach     = dibusb_dib3000mb_tuner_attach,
+
+	.rc_interval      = DEFAULT_RC_INTERVAL,
+	.rc_key_map       = dibusb_rc_keys,
+	.rc_key_map_size  = 63, /* wow, that is ugly ... I want to load it to the driver dynamically */
+	.rc_query         = dibusb_rc_query,
+
+	.i2c_algo         = &dibusb_i2c_algo,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
+	/* parameter for the MPEG2-data transfer */
+	.urb = {
+		.type = DVB_USB_BULK,
+		.count = 7,
+		.endpoint = 0x06,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+
+	.num_device_descs = 2,
+	.devices = {
+		{	"KWorld/ADSTech Instant DVB-T USB 2.0",
+			{ &dibusb_dib3000mb_table[23], NULL },
+			{ &dibusb_dib3000mb_table[24], NULL }, /* device ID with default DIBUSB2_0-firmware */
+		},
+	}
+};
+
+static struct usb_driver dibusb_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "DiBcom based USB DVB-T devices (DiB3000M-B based)",
+	.probe		= dibusb_probe,
+	.disconnect = dvb_usb_device_exit,
+	.id_table	= dibusb_dib3000mb_table,
+};
+
+/* module stuff */
+static int __init dibusb_module_init(void)
+{
+	int result;
+	if ((result = usb_register(&dibusb_driver))) {
+		err("usb_register failed. Error number %d",result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void __exit dibusb_module_exit(void)
+{
+	/* deregister this driver from the USB subsystem */
+	usb_deregister(&dibusb_driver);
+}
+
+module_init (dibusb_module_init);
+module_exit (dibusb_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("Driver for DiBcom USB DVB-T devices (DiB3000M-B based)");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dibusb-mc.c b/drivers/media/dvb/dvb-usb/dibusb-mc.c
new file mode 100644
index 0000000..aad8ed3
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dibusb-mc.c
@@ -0,0 +1,116 @@
+/* DVB USB compliant linux driver for mobile DVB-T USB devices based on
+ * reference designs made by DiBcom (http://www.dibcom.fr/) (DiB3000M-C/P)
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * based on GPL code from DiBcom, which has
+ * Copyright (C) 2004 Amaury Demol for DiBcom (ademol@dibcom.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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+#include "dibusb.h"
+
+/* USB Driver stuff */
+static struct dvb_usb_properties dibusb_mc_properties;
+
+static int dibusb_mc_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	return dvb_usb_device_init(intf,&dibusb_mc_properties,THIS_MODULE);
+}
+
+/* do not change the order of the ID table */
+static struct usb_device_id dibusb_dib3000mc_table [] = {
+/* 00 */	{ USB_DEVICE(USB_VID_DIBCOM,		USB_PID_DIBCOM_MOD3001_COLD) },
+/* 01 */	{ USB_DEVICE(USB_VID_DIBCOM,		USB_PID_DIBCOM_MOD3001_WARM) },
+/* 02 */	{ USB_DEVICE(USB_VID_ULTIMA_ELECTRONIC,	USB_PID_ULTIMA_TVBOX_USB2_COLD) },
+			{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, dibusb_dib3000mc_table);
+
+static struct dvb_usb_properties dibusb_mc_properties = {
+	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
+	.pid_filter_count = 32,
+
+	.usb_ctrl = CYPRESS_FX2,
+	.firmware = "dvb-usb-dibusb-6.0.0.8.fw",
+
+	.size_of_priv     = sizeof(struct dibusb_state),
+
+	.streaming_ctrl   = dibusb2_0_streaming_ctrl,
+	.pid_filter       = dibusb_pid_filter,
+	.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
+	.power_ctrl       = dibusb2_0_power_ctrl,
+	.frontend_attach  = dibusb_dib3000mc_frontend_attach,
+	.tuner_attach     = dibusb_dib3000mc_tuner_attach,
+
+	.rc_interval      = DEFAULT_RC_INTERVAL,
+	.rc_key_map       = dibusb_rc_keys,
+	.rc_key_map_size  = 63, /* FIXME */
+	.rc_query         = dibusb_rc_query,
+
+	.i2c_algo         = &dibusb_i2c_algo,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
+	/* parameter for the MPEG2-data transfer */
+	.urb = {
+		.type = DVB_USB_BULK,
+		.count = 7,
+		.endpoint = 0x06,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+
+	.num_device_descs = 2,
+	.devices = {
+		{   "DiBcom USB2.0 DVB-T reference design (MOD3000P)",
+			{ &dibusb_dib3000mc_table[0], NULL },
+			{ &dibusb_dib3000mc_table[1], NULL },
+		},
+		{   "Artec T1 USB2.0 TVBOX (please report the warm ID)",
+			{ &dibusb_dib3000mc_table[2], NULL },
+			{ NULL },
+		},
+	}
+};
+
+static struct usb_driver dibusb_mc_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "DiBcom based USB2.0 DVB-T (DiB3000M-C/P based) devices",
+	.probe		= dibusb_mc_probe,
+	.disconnect = dvb_usb_device_exit,
+	.id_table	= dibusb_dib3000mc_table,
+};
+
+/* module stuff */
+static int __init dibusb_mc_module_init(void)
+{
+	int result;
+	if ((result = usb_register(&dibusb_mc_driver))) {
+		err("usb_register failed. Error number %d",result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void __exit dibusb_mc_module_exit(void)
+{
+	/* deregister this driver from the USB subsystem */
+	usb_deregister(&dibusb_mc_driver);
+}
+
+module_init (dibusb_mc_module_init);
+module_exit (dibusb_mc_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("Driver for DiBcom USB2.0 DVB-T (DiB3000M-C/P based) devices");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dibusb.h b/drivers/media/dvb/dvb-usb/dibusb.h
new file mode 100644
index 0000000..6611f62
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dibusb.h
@@ -0,0 +1,122 @@
+/* Header file for all dibusb-based-receivers.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ *	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_DIBUSB_H_
+#define _DVB_USB_DIBUSB_H_
+
+#define DVB_USB_LOG_PREFIX "dibusb"
+#include "dvb-usb.h"
+
+#include "dib3000.h"
+
+/*
+ * protocol of all dibusb related devices
+ */
+
+/*
+ * bulk msg to/from endpoint 0x01
+ *
+ * general structure:
+ * request_byte parameter_bytes
+ */
+
+#define DIBUSB_REQ_START_READ			0x00
+#define DIBUSB_REQ_START_DEMOD			0x01
+
+/*
+ * i2c read
+ * bulk write: 0x02 ((7bit i2c_addr << 1) & 0x01) register_bytes length_word
+ * bulk read:  byte_buffer (length_word bytes)
+ */
+#define DIBUSB_REQ_I2C_READ			0x02
+
+/*
+ * i2c write
+ * bulk write: 0x03 (7bit i2c_addr << 1) register_bytes value_bytes
+ */
+#define DIBUSB_REQ_I2C_WRITE			0x03
+
+/*
+ * polling the value of the remote control
+ * bulk write: 0x04
+ * bulk read:  byte_buffer (5 bytes)
+ */
+#define DIBUSB_REQ_POLL_REMOTE       0x04
+
+/* additional status values for Hauppauge Remote Control Protocol */
+#define DIBUSB_RC_HAUPPAUGE_KEY_PRESSED	0x01
+#define DIBUSB_RC_HAUPPAUGE_KEY_EMPTY	0x03
+
+/* streaming mode:
+ * bulk write: 0x05 mode_byte
+ *
+ * mode_byte is mostly 0x00
+ */
+#define DIBUSB_REQ_SET_STREAMING_MODE	0x05
+
+/* interrupt the internal read loop, when blocking */
+#define DIBUSB_REQ_INTR_READ			0x06
+
+/* io control
+ * 0x07 cmd_byte param_bytes
+ *
+ * param_bytes can be up to 32 bytes
+ *
+ * cmd_byte function    parameter name
+ * 0x00     power mode
+ *                      0x00      sleep
+ *                      0x01      wakeup
+ *
+ * 0x01     enable streaming
+ * 0x02     disable streaming
+ *
+ *
+ */
+#define DIBUSB_REQ_SET_IOCTL			0x07
+
+/* IOCTL commands */
+
+/* change the power mode in firmware */
+#define DIBUSB_IOCTL_CMD_POWER_MODE		0x00
+#define DIBUSB_IOCTL_POWER_SLEEP			0x00
+#define DIBUSB_IOCTL_POWER_WAKEUP			0x01
+
+/* modify streaming of the FX2 */
+#define DIBUSB_IOCTL_CMD_ENABLE_STREAM	0x01
+#define DIBUSB_IOCTL_CMD_DISABLE_STREAM	0x02
+
+struct dibusb_state {
+	struct dib_fe_xfer_ops ops;
+
+	/* for RC5 remote control */
+	int old_toggle;
+	int last_repeat_count;
+};
+
+extern struct i2c_algorithm dibusb_i2c_algo;
+
+extern int dibusb_dib3000mc_frontend_attach(struct dvb_usb_device *);
+extern int dibusb_dib3000mc_tuner_attach (struct dvb_usb_device *);
+
+extern int dibusb_streaming_ctrl(struct dvb_usb_device *, int);
+extern int dibusb_pid_filter(struct dvb_usb_device *, int, u16, int);
+extern int dibusb_pid_filter_ctrl(struct dvb_usb_device *, int);
+extern int dibusb_power_ctrl(struct dvb_usb_device *, int);
+extern int dibusb2_0_streaming_ctrl(struct dvb_usb_device *, int);
+extern int dibusb2_0_power_ctrl(struct dvb_usb_device *, int);
+
+#define DEFAULT_RC_INTERVAL 150
+//#define DEFAULT_RC_INTERVAL 100000
+
+extern struct dvb_usb_rc_key dibusb_rc_keys[];
+extern int dibusb_rc_query(struct dvb_usb_device *, u32 *, int *);
+extern int dibusb_read_eeprom_byte(struct dvb_usb_device *, u8, u8 *);
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/digitv.c b/drivers/media/dvb/dvb-usb/digitv.c
new file mode 100644
index 0000000..5acf3fd
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/digitv.c
@@ -0,0 +1,282 @@
+/* DVB USB compliant linux driver for Nebula Electronics uDigiTV DVB-T USB2.0
+ * receiver
+ *
+ * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@desy.de) and
+ *                    Allan Third (allan.third@cs.man.ac.uk)
+ *
+ * partly based on the SDK published by Nebula Electronics (TODO do we want this line ?)
+ *
+ *	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 "digitv.h"
+
+#include "mt352.h"
+#include "nxt6000.h"
+
+/* debug */
+int dvb_usb_digitv_debug;
+module_param_named(debug,dvb_usb_digitv_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
+
+static int digitv_ctrl_msg(struct dvb_usb_device *d,
+		u8 cmd, u8 vv, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
+{
+	int wo = (rbuf == NULL || rlen == 0); /* write-only */
+	u8 sndbuf[7],rcvbuf[7];
+	memset(sndbuf,0,7); memset(rcvbuf,0,7);
+
+	sndbuf[0] = cmd;
+	sndbuf[1] = vv;
+	sndbuf[2] = wo ? wlen : rlen;
+
+	if (!wo) {
+		memcpy(&sndbuf[3],wbuf,wlen);
+		dvb_usb_generic_write(d,sndbuf,7);
+	} else {
+		dvb_usb_generic_rw(d,sndbuf,7,rcvbuf,7,10);
+		memcpy(&rbuf,&rcvbuf[3],rlen);
+	}
+	return 0;
+}
+
+/* I2C */
+static int digitv_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
+{
+	struct dvb_usb_device *d = i2c_get_adapdata(adap);
+	int i;
+
+	if (down_interruptible(&d->i2c_sem) < 0)
+		return -EAGAIN;
+
+	if (num > 2)
+		warn("more than 2 i2c messages at a time is not handled yet. TODO.");
+
+	for (i = 0; i < num; i++) {
+		/* write/read request */
+		if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
+			if (digitv_ctrl_msg(d, USB_READ_COFDM, msg[i].buf[0], NULL, 0,
+						msg[i+1].buf,msg[i+1].len) < 0)
+				break;
+			i++;
+		} else
+			if (digitv_ctrl_msg(d,USB_WRITE_COFDM, msg[i].buf[0],
+						&msg[i].buf[1],msg[i].len-1,NULL,0) < 0)
+				break;
+	}
+
+	up(&d->i2c_sem);
+	return i;
+}
+
+static u32 digitv_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm digitv_i2c_algo = {
+	.name          = "Nebula DigiTV USB I2C algorithm",
+	.id            = I2C_ALGO_BIT,
+	.master_xfer   = digitv_i2c_xfer,
+	.functionality = digitv_i2c_func,
+};
+
+/* Callbacks for DVB USB */
+static int digitv_identify_state (struct usb_device *udev, struct
+		dvb_usb_properties *props, struct dvb_usb_device_description **desc,
+		int *cold)
+{
+	*cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0;
+	return 0;
+}
+
+static int digitv_mt352_demod_init(struct dvb_frontend *fe)
+{
+	static u8 mt352_clock_config[] = { 0x89, 0x38, 0x2d };
+	static u8 mt352_reset[] = { 0x50, 0x80 };
+	static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 };
+
+	static u8 mt352_agc_cfg[] = { 0x68, 0xa0 };
+	static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0xa0 };
+	static u8 mt352_acq_ctl[] = { 0x53, 0x50 };
+	static u8 mt352_agc_target[] = { 0x67, 0x20 };
+
+	static u8 mt352_rs_err_per[] = { 0x7c, 0x00, 0x01 };
+	static u8 mt352_snr_select[] = { 0x79, 0x00, 0x20 };
+
+	static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x05 };
+
+	static u8 mt352_scan_ctl[] = { 0x88, 0x0f };
+	static u8 mt352_capt_range[] = { 0x75, 0x32 };
+
+	mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
+	mt352_write(fe, mt352_reset, sizeof(mt352_reset));
+	msleep(1);
+	mt352_write(fe, mt352_mclk_ratio, sizeof(mt352_mclk_ratio));
+
+	mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
+	mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
+	mt352_write(fe, mt352_acq_ctl, sizeof(mt352_acq_ctl));
+	mt352_write(fe, mt352_agc_target, sizeof(mt352_agc_target));
+
+
+	mt352_write(fe, mt352_rs_err_per, sizeof(mt352_rs_err_per));
+	mt352_write(fe, mt352_snr_select, sizeof(mt352_snr_select));
+
+	mt352_write(fe, mt352_input_freq_1, sizeof(mt352_input_freq_1));
+
+	mt352_write(fe, mt352_scan_ctl, sizeof(mt352_scan_ctl));
+	mt352_write(fe, mt352_capt_range, sizeof(mt352_capt_range));
+
+	return 0;
+}
+
+static struct mt352_config digitv_mt352_config = {
+	.demod_address = 0x0, /* ignored by the digitv anyway */
+	.demod_init = digitv_mt352_demod_init,
+	.pll_set = NULL, /* TODO */
+};
+
+static struct nxt6000_config digitv_nxt6000_config = {
+	.demod_address = 0x0, /* ignored by the digitv anyway */
+	.clock_inversion = 0x0,
+
+	.pll_init = NULL,
+	.pll_set = NULL,
+};
+
+static int digitv_frontend_attach(struct dvb_usb_device *d)
+{
+	if ((d->fe = mt352_attach(&digitv_mt352_config, &d->i2c_adap)) == NULL)
+		return 0;
+	if ((d->fe = nxt6000_attach(&digitv_nxt6000_config, &d->i2c_adap)) == NULL) {
+
+		warn("nxt6000 support is not done yet, in fact you are one of the first "
+				"person who wants to use this device in Linux. Please report to "
+				"linux-dvb@linuxtv.org");
+
+		return 0;
+	}
+	return -EIO;
+}
+
+static struct dvb_usb_rc_key digitv_rc_keys[] = {
+	{ 0x00, 0x16, KEY_POWER }, /* dummy key */
+};
+
+/* TODO is it really the NEC protocol ? */
+int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+	u8 key[5];
+
+	digitv_ctrl_msg(d,USB_READ_REMOTE,0,NULL,0,&key[1],4);
+	/* TODO state, maybe it is VV ? */
+	if (key[1] != 0)
+		key[0] = 0x01; /* if something is inside the buffer, simulate key press */
+
+	/* call the universal NEC remote processor, to find out the key's state and event */
+	dvb_usb_nec_rc_key_to_event(d,key,event,state);
+	if (key[0] != 0)
+		deb_rc("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
+	return 0;
+}
+
+
+/* DVB USB Driver stuff */
+static struct dvb_usb_properties digitv_properties;
+
+static int digitv_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	return dvb_usb_device_init(intf,&digitv_properties,THIS_MODULE);
+}
+
+static struct usb_device_id digitv_table [] = {
+		{ USB_DEVICE(USB_VID_ANCHOR, USB_PID_NEBULA_DIGITV) },
+		{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, digitv_table);
+
+static struct dvb_usb_properties digitv_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+	.usb_ctrl = CYPRESS_FX2,
+	.firmware = "dvb-usb-digitv-01.fw",
+
+	.size_of_priv     = 0,
+
+	.streaming_ctrl   = NULL,
+	.pid_filter       = NULL,
+	.pid_filter_ctrl  = NULL,
+	.power_ctrl       = NULL,
+	.frontend_attach  = digitv_frontend_attach,
+	.tuner_attach     = NULL, // digitv_tuner_attach,
+	.read_mac_address = NULL,
+
+	.rc_interval      = 1000,
+	.rc_key_map       = digitv_rc_keys,
+	.rc_key_map_size  = ARRAY_SIZE(digitv_rc_keys),
+	.rc_query         = digitv_rc_query,
+
+	.identify_state   = digitv_identify_state,
+
+	.i2c_algo         = &digitv_i2c_algo,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
+	/* parameter for the MPEG2-data transfer */
+	.urb = {
+		.type = DVB_USB_BULK,
+		.count = 7,
+		.endpoint = 0x02,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+
+	.num_device_descs = 2,
+	.devices = {
+		{   "Nebula Electronics uDigiTV DVB-T USB2.0)",
+			{ &digitv_table[0], NULL },
+			{ NULL },
+		},
+	}
+};
+
+static struct usb_driver digitv_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "Nebula Electronics uDigiTV DVB-T USB2.0 device",
+	.probe		= digitv_probe,
+	.disconnect = dvb_usb_device_exit,
+	.id_table	= digitv_table,
+};
+
+/* module stuff */
+static int __init digitv_module_init(void)
+{
+	int result;
+	if ((result = usb_register(&digitv_driver))) {
+		err("usb_register failed. Error number %d",result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void __exit digitv_module_exit(void)
+{
+	/* deregister this driver from the USB subsystem */
+	usb_deregister(&digitv_driver);
+}
+
+module_init (digitv_module_init);
+module_exit (digitv_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("Driver for Nebula Electronics uDigiTV DVB-T USB2.0");
+MODULE_VERSION("1.0-alpha");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/digitv.h b/drivers/media/dvb/dvb-usb/digitv.h
new file mode 100644
index 0000000..477ee42
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/digitv.h
@@ -0,0 +1,65 @@
+#ifndef _DVB_USB_DIGITV_H_
+#define _DVB_USB_DIGITV_H_
+
+#define DVB_USB_LOG_PREFIX "digitv"
+#include "dvb-usb.h"
+
+extern int dvb_usb_digitv_debug;
+#define deb_rc(args...)   dprintk(dvb_usb_digitv_debug,0x01,args)
+
+/* protocol (from usblogging and the SDK:
+ *
+ * Always 7 bytes bulk message(s) for controlling
+ *
+ * First byte describes the command. Reads are 2 consecutive transfer (as always).
+ *
+ * General structure:
+ *
+ * write or first message of a read:
+ * <cmdbyte> VV <len> B0 B1 B2 B3
+ *
+ * second message of a read
+ * <cmdbyte> VV <len> R0 R1 R2 R3
+ *
+ * whereas 0 < len <= 4
+ *
+ * I2C address is stored somewhere inside the device.
+ *
+ * 0x01 read from EEPROM
+ *  VV = offset; B* = 0; R* = value(s)
+ *
+ * 0x02 read register of the COFDM
+ *  VV = register; B* = 0; R* = value(s)
+ *
+ * 0x05 write register of the COFDM
+ *  VV = register; B* = value(s);
+ *
+ * 0x06 write to the tuner (only for NXT6000)
+ *  VV = 0; B* = PLL data; len = 4;
+ *
+ * 0x03 read remote control
+ *  VV = 0; B* = 0; len = 4; R* = key
+ *
+ * 0x07 write to the remote (don't know why one should this, resetting ?)
+ *  VV = 0; B* = key; len = 4;
+ *
+ * 0x08 write remote type
+ *  VV = 0; B[0] = 0x01, len = 4
+ *
+ * 0x09 write device init
+ *  TODO
+ */
+#define USB_READ_EEPROM         1
+
+#define USB_READ_COFDM          2
+#define USB_WRITE_COFDM         5
+
+#define USB_WRITE_TUNER         6
+
+#define USB_READ_REMOTE         3
+#define USB_WRITE_REMOTE        7
+#define USB_WRITE_REMOTE_TYPE   8
+
+#define USB_DEV_INIT            9
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/dtt200u-fe.c b/drivers/media/dvb/dvb-usb/dtt200u-fe.c
new file mode 100644
index 0000000..d17d768
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dtt200u-fe.c
@@ -0,0 +1,206 @@
+/* Frontend part of the Linux driver for the Yakumo/Hama/Typhoon DVB-T
+ * USB2.0 receiver.
+ *
+ * Copyright (C) 2005 Patrick Boettcher <patrick.boettcher@desy.de>
+ *
+ *	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 "dtt200u.h"
+
+struct dtt200u_fe_state {
+	struct dvb_usb_device *d;
+
+	struct dvb_frontend_parameters fep;
+	struct dvb_frontend frontend;
+};
+
+#define moan(which,what) info("unexpected value in '%s' for cmd '%02x' - please report to linux-dvb@linuxtv.org",which,what)
+
+static int dtt200u_fe_read_status(struct dvb_frontend* fe, fe_status_t *stat)
+{
+	struct dtt200u_fe_state *state = fe->demodulator_priv;
+	u8 bw = GET_TUNE_STAT;
+	u8 br[3] = { 0 };
+//	u8 bdeb[5] = { 0 };
+
+	dvb_usb_generic_rw(state->d,&bw,1,br,3,0);
+	switch (br[0]) {
+		case 0x01:
+			*stat = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK;
+			break;
+		case 0x00:
+			*stat = 0;
+			break;
+		default:
+			moan("br[0]",GET_TUNE_STAT);
+			break;
+	}
+
+//	bw[0] = 0x88;
+//	dvb_usb_generic_rw(state->d,bw,1,bdeb,5,0);
+
+//	deb_info("%02x: %02x %02x %02x %02x %02x\n",bw[0],bdeb[0],bdeb[1],bdeb[2],bdeb[3],bdeb[4]);
+
+	return 0;
+}
+static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
+{
+	struct dtt200u_fe_state *state = fe->demodulator_priv;
+	u8 bw = GET_BER;
+	*ber = 0;
+	dvb_usb_generic_rw(state->d,&bw,1,(u8*) ber,3,0);
+	return 0;
+}
+
+static int dtt200u_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
+{
+	struct dtt200u_fe_state *state = fe->demodulator_priv;
+	u8 bw = GET_UNK;
+	*unc = 0;
+	dvb_usb_generic_rw(state->d,&bw,1,(u8*) unc,3,0);
+	return 0;
+}
+
+static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
+{
+	struct dtt200u_fe_state *state = fe->demodulator_priv;
+	u8 bw = GET_SIG_STRENGTH, b;
+	dvb_usb_generic_rw(state->d,&bw,1,&b,1,0);
+	*strength = (b << 8) | b;
+	return 0;
+}
+
+static int dtt200u_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
+{
+	struct dtt200u_fe_state *state = fe->demodulator_priv;
+	u8 bw = GET_SNR,br;
+	dvb_usb_generic_rw(state->d,&bw,1,&br,1,0);
+	*snr = ~((br << 8) | br);
+	return 0;
+}
+
+static int dtt200u_fe_init(struct dvb_frontend* fe)
+{
+	struct dtt200u_fe_state *state = fe->demodulator_priv;
+	u8 b = RESET_DEMOD;
+	return dvb_usb_generic_write(state->d,&b,1);
+}
+
+static int dtt200u_fe_sleep(struct dvb_frontend* fe)
+{
+	return dtt200u_fe_init(fe);
+}
+
+static int dtt200u_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+	tune->min_delay_ms = 1500;
+	tune->step_size = 166667;
+	tune->max_drift = 166667 * 2;
+	return 0;
+}
+
+static int dtt200u_fe_set_frontend(struct dvb_frontend* fe,
+				  struct dvb_frontend_parameters *fep)
+{
+	struct dtt200u_fe_state *state = fe->demodulator_priv;
+	u16 freq = fep->frequency / 250000;
+	u8 bw,bwbuf[2] = { SET_BANDWIDTH, 0 }, freqbuf[3] = { SET_FREQUENCY, 0, 0 };
+
+	switch (fep->u.ofdm.bandwidth) {
+		case BANDWIDTH_8_MHZ: bw = 8; break;
+		case BANDWIDTH_7_MHZ: bw = 7; break;
+		case BANDWIDTH_6_MHZ: bw = 6; break;
+		case BANDWIDTH_AUTO: return -EOPNOTSUPP;
+		default:
+			return -EINVAL;
+	}
+	deb_info("set_frontend\n");
+
+	bwbuf[1] = bw;
+	dvb_usb_generic_write(state->d,bwbuf,2);
+
+	freqbuf[1] = freq & 0xff;
+	freqbuf[2] = (freq >> 8) & 0xff;
+	dvb_usb_generic_write(state->d,freqbuf,3);
+
+	memcpy(&state->fep,fep,sizeof(struct dvb_frontend_parameters));
+
+	return 0;
+}
+
+static int dtt200u_fe_get_frontend(struct dvb_frontend* fe,
+				  struct dvb_frontend_parameters *fep)
+{
+	struct dtt200u_fe_state *state = fe->demodulator_priv;
+	memcpy(fep,&state->fep,sizeof(struct dvb_frontend_parameters));
+	return 0;
+}
+
+static void dtt200u_fe_release(struct dvb_frontend* fe)
+{
+	struct dtt200u_fe_state *state = (struct dtt200u_fe_state*) fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops dtt200u_fe_ops;
+
+struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d)
+{
+	struct dtt200u_fe_state* state = NULL;
+
+	/* allocate memory for the internal state */
+	state = (struct dtt200u_fe_state*) kmalloc(sizeof(struct dtt200u_fe_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+	memset(state,0,sizeof(struct dtt200u_fe_state));
+
+	deb_info("attaching frontend dtt200u\n");
+
+	state->d = d;
+
+	state->frontend.ops = &dtt200u_fe_ops;
+	state->frontend.demodulator_priv = state;
+
+	goto success;
+error:
+	return NULL;
+success:
+	return &state->frontend;
+}
+
+static struct dvb_frontend_ops dtt200u_fe_ops = {
+	.info = {
+		.name			= "DTT200U (Yakumo/Typhoon/Hama) DVB-T",
+		.type			= FE_OFDM,
+		.frequency_min		= 44250000,
+		.frequency_max		= 867250000,
+		.frequency_stepsize	= 250000,
+		.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 | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+				FE_CAN_TRANSMISSION_MODE_AUTO |
+				FE_CAN_GUARD_INTERVAL_AUTO |
+				FE_CAN_RECOVER |
+				FE_CAN_HIERARCHY_AUTO,
+	},
+
+	.release = dtt200u_fe_release,
+
+	.init = dtt200u_fe_init,
+	.sleep = dtt200u_fe_sleep,
+
+	.set_frontend = dtt200u_fe_set_frontend,
+	.get_frontend = dtt200u_fe_get_frontend,
+	.get_tune_settings = dtt200u_fe_get_tune_settings,
+
+	.read_status = dtt200u_fe_read_status,
+	.read_ber = dtt200u_fe_read_ber,
+	.read_signal_strength = dtt200u_fe_read_signal_strength,
+	.read_snr = dtt200u_fe_read_snr,
+	.read_ucblocks = dtt200u_fe_read_unc_blocks,
+};
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.c b/drivers/media/dvb/dvb-usb/dtt200u.c
new file mode 100644
index 0000000..fb2b5a2
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dtt200u.c
@@ -0,0 +1,171 @@
+/* DVB USB library compliant Linux driver for the Yakumo/Hama/Typhoon DVB-T
+ * USB2.0 receiver.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ *	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 "dtt200u.h"
+
+/* debug */
+int dvb_usb_dtt200u_debug;
+module_param_named(debug,dvb_usb_dtt200u_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB_DEBUG_STATUS);
+
+static int dtt200u_streaming_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	u8 b_streaming[2] = { SET_TS_CTRL, onoff };
+	u8 b_rst_pid = RESET_PID_FILTER;
+
+	dvb_usb_generic_write(d,b_streaming,2);
+
+	if (!onoff)
+		dvb_usb_generic_write(d,&b_rst_pid,1);
+	return 0;
+}
+
+static int dtt200u_pid_filter(struct dvb_usb_device *d, int index, u16 pid, int onoff)
+{
+	u8 b_pid[4];
+	pid = onoff ? pid : 0;
+
+	b_pid[0] = SET_PID_FILTER;
+	b_pid[1] = index;
+	b_pid[2] = pid & 0xff;
+	b_pid[3] = (pid >> 8) & 0xff;
+
+	return dvb_usb_generic_write(d,b_pid,4);
+}
+
+/* remote control */
+/* key list for the tiny remote control (Yakumo, don't know about the others) */
+static struct dvb_usb_rc_key dtt200u_rc_keys[] = {
+	{ 0x80, 0x01, KEY_MUTE },
+	{ 0x80, 0x02, KEY_CHANNELDOWN },
+	{ 0x80, 0x03, KEY_VOLUMEDOWN },
+	{ 0x80, 0x04, KEY_1 },
+	{ 0x80, 0x05, KEY_2 },
+	{ 0x80, 0x06, KEY_3 },
+	{ 0x80, 0x07, KEY_4 },
+	{ 0x80, 0x08, KEY_5 },
+	{ 0x80, 0x09, KEY_6 },
+	{ 0x80, 0x0a, KEY_7 },
+	{ 0x00, 0x0c, KEY_ZOOM },
+	{ 0x80, 0x0d, KEY_0 },
+	{ 0x00, 0x0e, KEY_SELECT },
+	{ 0x80, 0x12, KEY_POWER },
+	{ 0x80, 0x1a, KEY_CHANNELUP },
+	{ 0x80, 0x1b, KEY_8 },
+	{ 0x80, 0x1e, KEY_VOLUMEUP },
+	{ 0x80, 0x1f, KEY_9 },
+};
+
+static int dtt200u_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+	u8 key[5],cmd = GET_RC_KEY;
+	dvb_usb_generic_rw(d,&cmd,1,key,5,0);
+	dvb_usb_nec_rc_key_to_event(d,key,event,state);
+	if (key[0] != 0)
+		deb_info("key: %x %x %x %x %x\n",key[0],key[1],key[2],key[3],key[4]);
+	return 0;
+}
+
+static int dtt200u_frontend_attach(struct dvb_usb_device *d)
+{
+	d->fe = dtt200u_fe_attach(d);
+	return 0;
+}
+
+static struct dvb_usb_properties dtt200u_properties;
+
+static int dtt200u_usb_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	return dvb_usb_device_init(intf,&dtt200u_properties,THIS_MODULE);
+}
+
+static struct usb_device_id dtt200u_usb_table [] = {
+	    { USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_DTT200U_COLD) },
+	    { USB_DEVICE(USB_VID_AVERMEDIA_UNK, USB_PID_DTT200U_WARM) },
+	    { 0 },
+};
+MODULE_DEVICE_TABLE(usb, dtt200u_usb_table);
+
+static struct dvb_usb_properties dtt200u_properties = {
+	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_NEED_PID_FILTERING,
+	.pid_filter_count = 255, /* It is a guess, but there are at least 10 */
+
+	.usb_ctrl = CYPRESS_FX2,
+	.firmware = "dvb-usb-dtt200u-01.fw",
+
+	.streaming_ctrl  = dtt200u_streaming_ctrl,
+	.pid_filter      = dtt200u_pid_filter,
+	.frontend_attach = dtt200u_frontend_attach,
+
+	.rc_interval     = 200,
+	.rc_key_map      = dtt200u_rc_keys,
+	.rc_key_map_size = ARRAY_SIZE(dtt200u_rc_keys),
+	.rc_query        = dtt200u_rc_query,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
+
+	/* parameter for the MPEG2-data transfer */
+	.urb = {
+		.type = DVB_USB_BULK,
+		.count = 7,
+		.endpoint = 0x02,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+
+	.num_device_descs = 1,
+	.devices = {
+		{ .name = "Yakumo/Hama/Typhoon DVB-T USB2.0)",
+		  .cold_ids = { &dtt200u_usb_table[0], &dtt200u_usb_table[2] },
+		  .warm_ids = { &dtt200u_usb_table[1], NULL },
+		},
+		{ 0 },
+	}
+};
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver dtt200u_usb_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "Yakumo/Hama/Typhoon DVB-T USB2.0",
+	.probe 		= dtt200u_usb_probe,
+	.disconnect = dvb_usb_device_exit,
+	.id_table 	= dtt200u_usb_table,
+};
+
+/* module stuff */
+static int __init dtt200u_usb_module_init(void)
+{
+	int result;
+	if ((result = usb_register(&dtt200u_usb_driver))) {
+		err("usb_register failed. (%d)",result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void __exit dtt200u_usb_module_exit(void)
+{
+	/* deregister this driver from the USB subsystem */
+	usb_deregister(&dtt200u_usb_driver);
+}
+
+module_init(dtt200u_usb_module_init);
+module_exit(dtt200u_usb_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("Driver for the Yakumo/Hama/Typhoon DVB-T USB2.0 device");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dtt200u.h b/drivers/media/dvb/dvb-usb/dtt200u.h
new file mode 100644
index 0000000..ed41420
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dtt200u.h
@@ -0,0 +1,66 @@
+/* Common header file of Linux driver for the Yakumo/Hama/Typhoon DVB-T
+ * USB2.0 receiver.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ *	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_DTT200U_H_
+#define _DVB_USB_DTT200U_H_
+
+#define DVB_USB_LOG_PREFIX "dtt200u"
+#include "dvb-usb.h"
+
+extern int dvb_usb_dtt200u_debug;
+#define deb_info(args...) dprintk(dvb_usb_dtt200u_debug,0x01,args)
+#define deb_xfer(args...) dprintk(dvb_usb_dtt200u_debug,0x02,args)
+
+/* guessed protocol description (reverse engineered):
+ * read
+ *  00 - USB type 0x02 for usb2.0, 0x01 for usb1.1
+ *  81 - <TS_LOCK> <current frequency divided by 250000>
+ *  82 - crash - do not touch
+ *  83 - crash - do not touch
+ *  84 - remote control
+ *  85 - crash - do not touch (OK, stop testing here)
+ *  88 - locking 2 bytes (0x80 0x40 == no signal, 0x89 0x20 == nice signal)
+ *  89 - noise-to-signal
+ *	8a - unkown 1 byte - signal_strength
+ *  8c - ber ???
+ *  8d - ber
+ *  8e - unc
+ */
+
+#define GET_SPEED        0x00
+#define GET_TUNE_STAT    0x81
+#define GET_RC_KEY       0x84
+#define GET_STATUS       0x88
+#define GET_SNR          0x89
+#define GET_SIG_STRENGTH 0x8a
+#define GET_UNK          0x8c
+#define GET_BER          0x8d
+#define GET_UNC          0x8e
+
+/* write
+ *  01 - reset the demod
+ *  02 - frequency (divided by 250000)
+ *  03 - bandwidth
+ *  04 - pid table (index pid(7:0) pid(12:8))
+ *  05 - reset the pid table
+ *  08 - demod transfer enabled or not (FX2 transfer is enabled by default)
+ */
+
+#define RESET_DEMOD      0x01
+#define SET_FREQUENCY    0x02
+#define SET_BANDWIDTH    0x03
+#define SET_PID_FILTER   0x04
+#define RESET_PID_FILTER 0x05
+#define SET_TS_CTRL      0x08
+
+extern struct dvb_frontend * dtt200u_fe_attach(struct dvb_usb_device *d);
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-common.h b/drivers/media/dvb/dvb-usb/dvb-usb-common.h
new file mode 100644
index 0000000..67e0d73
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-common.h
@@ -0,0 +1,44 @@
+/* dvb-usb-common.h is part of the DVB USB library.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ * see dvb-usb-init.c for copyright information.
+ *
+ * a header file containing prototypes and types for internal use of the dvb-usb-lib
+ */
+#ifndef _DVB_USB_COMMON_H_
+#define _DVB_USB_COMMON_H_
+
+#define DVB_USB_LOG_PREFIX "dvb-usb"
+#include "dvb-usb.h"
+
+extern int dvb_usb_debug;
+
+#define deb_info(args...) dprintk(dvb_usb_debug,0x01,args)
+#define deb_xfer(args...) dprintk(dvb_usb_debug,0x02,args)
+#define deb_pll(args...) dprintk(dvb_usb_debug,0x04,args)
+#define deb_ts(args...)   dprintk(dvb_usb_debug,0x08,args)
+#define deb_err(args...)  dprintk(dvb_usb_debug,0x10,args)
+#define deb_rc(args...)   dprintk(dvb_usb_debug,0x20,args)
+#define deb_fw(args...)   dprintk(dvb_usb_debug,0x40,args)
+
+/* commonly used  methods */
+extern int usb_cypress_load_firmware(struct usb_device *, const char *, int);
+
+extern int dvb_usb_urb_submit(struct dvb_usb_device *);
+extern int dvb_usb_urb_kill(struct dvb_usb_device *);
+extern int dvb_usb_urb_init(struct dvb_usb_device *);
+extern int dvb_usb_urb_exit(struct dvb_usb_device *);
+
+extern int dvb_usb_i2c_init(struct dvb_usb_device *);
+extern int dvb_usb_i2c_exit(struct dvb_usb_device *);
+
+extern int dvb_usb_dvb_init(struct dvb_usb_device *);
+extern int dvb_usb_dvb_exit(struct dvb_usb_device *);
+
+extern int dvb_usb_fe_init(struct dvb_usb_device *);
+extern int dvb_usb_fe_exit(struct dvb_usb_device *);
+
+extern int dvb_usb_remote_init(struct dvb_usb_device *);
+extern int dvb_usb_remote_exit(struct dvb_usb_device *);
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
new file mode 100644
index 0000000..bdd72f7
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
@@ -0,0 +1,210 @@
+/* dvb-usb-dvb.c is part of the DVB USB library.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ * see dvb-usb-init.c for copyright information.
+ *
+ * This file contains functions for initializing and handling the
+ * linux-dvb API.
+ */
+#include "dvb-usb-common.h"
+
+static int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed, int onoff)
+{
+	struct dvb_usb_device *d = dvbdmxfeed->demux->priv;
+	int newfeedcount,ret;
+
+	if (d == NULL)
+		return -ENODEV;
+
+	newfeedcount = d->feedcount + (onoff ? 1 : -1);
+
+	/*
+	 * stop feed before setting a new pid if there will be no pid anymore
+	 */
+	if (newfeedcount == 0) {
+		deb_ts("stop feeding\n");
+
+		if (d->props.streaming_ctrl != NULL)
+			if ((ret = d->props.streaming_ctrl(d,0)))
+				err("error while stopping stream.");
+
+		dvb_usb_urb_kill(d);
+	}
+
+	d->feedcount = newfeedcount;
+
+	/* activate the pid on the device specific pid_filter */
+	deb_ts("setting pid: %5d %04x at index %d '%s'\n",dvbdmxfeed->pid,dvbdmxfeed->pid,dvbdmxfeed->index,onoff ? "on" : "off");
+	if (d->props.caps & DVB_USB_HAS_PID_FILTER &&
+		d->pid_filtering &&
+		d->props.pid_filter != NULL)
+		d->props.pid_filter(d,dvbdmxfeed->index,dvbdmxfeed->pid,onoff);
+
+	/* start the feed if this was the first feed and there is still a feed
+	 * for reception.
+	 */
+	if (d->feedcount == onoff && d->feedcount > 0) {
+
+		deb_ts("controlling pid parser\n");
+		if (d->props.caps & DVB_USB_HAS_PID_FILTER &&
+			d->props.caps & DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF &&
+			d->props.pid_filter_ctrl != NULL)
+			if (d->props.pid_filter_ctrl(d,d->pid_filtering) < 0)
+				err("could not handle pid_parser");
+
+		deb_ts("start feeding\n");
+		if (d->props.streaming_ctrl != NULL)
+			if (d->props.streaming_ctrl(d,1)) {
+				err("error while enabling fifo.");
+				return -ENODEV;
+			}
+
+		dvb_usb_urb_submit(d);
+	}
+	return 0;
+}
+
+static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	deb_ts("start pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid,dvbdmxfeed->type);
+	return dvb_usb_ctrl_feed(dvbdmxfeed,1);
+}
+
+static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+	deb_ts("stop pid: 0x%04x, feedtype: %d\n", dvbdmxfeed->pid, dvbdmxfeed->type);
+	return dvb_usb_ctrl_feed(dvbdmxfeed,0);
+}
+
+int dvb_usb_dvb_init(struct dvb_usb_device *d)
+{
+	int ret;
+
+	if ((ret = dvb_register_adapter(&d->dvb_adap, d->desc->name,
+			d->owner)) < 0) {
+		deb_info("dvb_register_adapter failed: error %d", ret);
+		goto err;
+	}
+	d->dvb_adap.priv = d;
+
+	if (d->props.read_mac_address) {
+		if (d->props.read_mac_address(d,d->dvb_adap.proposed_mac) == 0)
+			info("MAC address: %02x:%02x:%02x:%02x:%02x:%02x",d->dvb_adap.proposed_mac[0],
+					d->dvb_adap.proposed_mac[1],d->dvb_adap.proposed_mac[2],
+					d->dvb_adap.proposed_mac[3],d->dvb_adap.proposed_mac[4],
+					d->dvb_adap.proposed_mac[5]);
+		else
+			err("MAC address reading failed.");
+	}
+
+
+	d->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
+	d->demux.priv = d;
+
+	d->demux.feednum = d->demux.filternum = d->max_feed_count;
+	d->demux.start_feed = dvb_usb_start_feed;
+	d->demux.stop_feed  = dvb_usb_stop_feed;
+	d->demux.write_to_decoder = NULL;
+	if ((ret = dvb_dmx_init(&d->demux)) < 0) {
+		err("dvb_dmx_init failed: error %d",ret);
+		goto err_dmx;
+	}
+
+	d->dmxdev.filternum = d->demux.filternum;
+	d->dmxdev.demux = &d->demux.dmx;
+	d->dmxdev.capabilities = 0;
+	if ((ret = dvb_dmxdev_init(&d->dmxdev, &d->dvb_adap)) < 0) {
+		err("dvb_dmxdev_init failed: error %d",ret);
+		goto err_dmx_dev;
+	}
+
+	dvb_net_init(&d->dvb_adap, &d->dvb_net, &d->demux.dmx);
+
+	goto success;
+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)
+{
+	if (d->state & DVB_USB_STATE_DVB) {
+		deb_info("unregistering DVB part\n");
+		dvb_net_release(&d->dvb_net);
+		d->demux.dmx.close(&d->demux.dmx);
+		dvb_dmxdev_release(&d->dmxdev);
+		dvb_dmx_release(&d->demux);
+		dvb_unregister_adapter(&d->dvb_adap);
+		d->state &= ~DVB_USB_STATE_DVB;
+	}
+	return 0;
+}
+
+static int dvb_usb_fe_wakeup(struct dvb_frontend *fe)
+{
+	struct dvb_usb_device *d = fe->dvb->priv;
+
+	if (d->props.power_ctrl)
+		d->props.power_ctrl(d,1);
+
+	if (d->fe_init)
+		d->fe_init(fe);
+
+	return 0;
+}
+
+static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
+{
+	struct dvb_usb_device *d = fe->dvb->priv;
+
+	if (d->fe_sleep)
+		d->fe_sleep(fe);
+
+	if (d->props.power_ctrl)
+		d->props.power_ctrl(d,0);
+
+	return 0;
+}
+
+int dvb_usb_fe_init(struct dvb_usb_device* d)
+{
+	if (d->props.frontend_attach == NULL) {
+		err("strange '%s' don't want to attach a frontend.",d->desc->name);
+		return 0;
+	}
+
+	d->props.frontend_attach(d);
+
+	/* 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;
+
+		if (dvb_register_frontend(&d->dvb_adap, d->fe)) {
+			err("Frontend registration failed.");
+			if (d->fe->ops->release)
+				d->fe->ops->release(d->fe);
+			d->fe = NULL;
+			return -ENODEV;
+		}
+	} else
+		err("no frontend was attached by '%s'",d->desc->name);
+
+	if (d->props.tuner_attach != NULL)
+		d->props.tuner_attach(d);
+
+	return 0;
+}
+
+int dvb_usb_fe_exit(struct dvb_usb_device *d)
+{
+	if (d->fe != NULL)
+		dvb_unregister_frontend(d->fe);
+	return 0;
+}
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
new file mode 100644
index 0000000..5244e39
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-firmware.c
@@ -0,0 +1,100 @@
+/* dvb-usb-firmware.c is part of the DVB USB library.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ * see dvb-usb-init.c for copyright information.
+ *
+ * This file contains functions for downloading the firmware to Cypress FX 1 and 2 based devices.
+ *
+ * FIXME: This part does actually not belong to dvb-usb, but to the usb-subsystem.
+ */
+#include "dvb-usb-common.h"
+
+#include <linux/firmware.h>
+#include <linux/usb.h>
+
+struct usb_cypress_controller {
+	int id;
+	const char *name;       /* name of the usb controller */
+	u16 cpu_cs_register;    /* needs to be restarted, when the firmware has been downloaded. */
+};
+
+static struct usb_cypress_controller cypress[] = {
+	{ .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cpu_cs_register = 0x7f92 },
+	{ .id = CYPRESS_AN2235, .name = "Cypress AN2235", .cpu_cs_register = 0x7f92 },
+	{ .id = CYPRESS_FX2,    .name = "Cypress FX2",    .cpu_cs_register = 0xe600 },
+};
+
+/*
+ * load a firmware packet to the device
+ */
+static int usb_cypress_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 len)
+{
+	return usb_control_msg(udev, usb_sndctrlpipe(udev,0),
+			0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5*HZ);
+}
+
+int usb_cypress_load_firmware(struct usb_device *udev, const char *filename, int type)
+{
+	const struct firmware *fw = NULL;
+	u16 addr;
+	u8 *b,*p;
+	int ret = 0,i;
+
+	if ((ret = request_firmware(&fw, filename, &udev->dev)) != 0) {
+		err("did not find the firmware file. (%s) "
+			"Please see linux/Documentation/dvb/ for more details on firmware-problems.",
+			filename);
+		return ret;
+	}
+
+	info("downloading firmware from file '%s' to the '%s'",filename,cypress[type].name);
+
+	p = kmalloc(fw->size,GFP_KERNEL);
+	if (p != NULL) {
+		u8 reset;
+		/*
+		 * you cannot use the fw->data as buffer for
+		 * usb_control_msg, a new buffer has to be
+		 * created
+		 */
+		memcpy(p,fw->data,fw->size);
+
+		/* stop the CPU */
+		reset = 1;
+		if ((ret = usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1)) != 1)
+			err("could not stop the USB controller CPU.");
+		for(i = 0; p[i+3] == 0 && i < fw->size; ) {
+			b = (u8 *) &p[i];
+			addr = cpu_to_le16( *((u16 *) &b[1]) );
+
+			deb_fw("writing to address 0x%04x (buffer: 0x%02x%02x)\n",addr,b[1],b[2]);
+
+			ret = usb_cypress_writemem(udev,addr,&b[4],b[0]);
+
+			if (ret != b[0]) {
+				err("error while transferring firmware "
+					"(transferred size: %d, block size: %d)",
+					ret,b[0]);
+				ret = -EINVAL;
+				break;
+			}
+			i += 5 + b[0];
+		}
+		/* length in ret */
+		if (ret > 0)
+			ret = 0;
+		/* restart the CPU */
+		reset = 0;
+		if (ret || usb_cypress_writemem(udev,cypress[type].cpu_cs_register,&reset,1) != 1) {
+			err("could not restart the USB controller CPU.");
+			ret = -EINVAL;
+		}
+
+		kfree(p);
+	} else {
+		ret = -ENOMEM;
+	}
+	release_firmware(fw);
+
+	return ret;
+}
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
new file mode 100644
index 0000000..9f0a8d9
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
@@ -0,0 +1,118 @@
+/* dvb-usb-i2c.c is part of the DVB USB library.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ * see dvb-usb-init.c for copyright information.
+ *
+ * This file contains functions for (de-)initializing an I2C adapter.
+ */
+#include "dvb-usb-common.h"
+
+int dvb_usb_i2c_init(struct dvb_usb_device *d)
+{
+	int ret = 0;
+
+	if (!(d->props.caps & DVB_USB_IS_AN_I2C_ADAPTER))
+		return 0;
+
+	if (d->props.i2c_algo == NULL) {
+		err("no i2c algorithm specified");
+		return -EINVAL;
+	}
+
+	strncpy(d->i2c_adap.name,d->desc->name,I2C_NAME_SIZE);
+#ifdef I2C_ADAP_CLASS_TV_DIGITAL
+	d->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL,
+#else
+	d->i2c_adap.class = I2C_CLASS_TV_DIGITAL,
+#endif
+	d->i2c_adap.algo      = d->props.i2c_algo;
+	d->i2c_adap.algo_data = NULL;
+	d->i2c_adap.id        = I2C_ALGO_BIT;
+
+	i2c_set_adapdata(&d->i2c_adap, d);
+
+	if ((ret = i2c_add_adapter(&d->i2c_adap)) < 0)
+		err("could not add i2c adapter");
+
+	d->state |= DVB_USB_STATE_I2C;
+
+	return ret;
+}
+
+int dvb_usb_i2c_exit(struct dvb_usb_device *d)
+{
+	if (d->state & DVB_USB_STATE_I2C)
+		i2c_del_adapter(&d->i2c_adap);
+	d->state &= ~DVB_USB_STATE_I2C;
+	return 0;
+}
+
+int dvb_usb_pll_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 };
+	int ret = 0;
+
+	/* if there is nothing to initialize */
+	if (d->pll_init[0] == 0x00 && d->pll_init[1] == 0x00 &&
+		d->pll_init[2] == 0x00 && d->pll_init[3] == 0x00)
+		return 0;
+
+	if (d->tuner_pass_ctrl)
+		d->tuner_pass_ctrl(fe,1,d->pll_addr);
+
+	deb_pll("pll init: %x\n",d->pll_addr);
+	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 (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) {
+		err("tuner i2c write failed for pll_init.");
+		ret = -EREMOTEIO;
+	}
+	msleep(1);
+
+	if (d->tuner_pass_ctrl)
+		d->tuner_pass_ctrl(fe,0,d->pll_addr);
+	return ret;
+}
+EXPORT_SYMBOL(dvb_usb_pll_init_i2c);
+
+int dvb_usb_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep, u8 b[5])
+{
+	struct dvb_usb_device *d = fe->dvb->priv;
+
+	deb_pll("pll addr: %x, freq: %d %p\n",d->pll_addr,fep->frequency,d->pll_desc);
+
+	b[0] = d->pll_addr << 1;
+	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;
+}
+EXPORT_SYMBOL(dvb_usb_pll_set);
+
+int dvb_usb_pll_set_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);
+
+	if (d->tuner_pass_ctrl)
+		d->tuner_pass_ctrl(fe,1,d->pll_addr);
+
+	if (i2c_transfer (&d->i2c_adap, &msg, 1) != 1) {
+		err("tuner i2c write failed for pll_set.");
+		ret = -EREMOTEIO;
+	}
+	msleep(1);
+
+	if (d->tuner_pass_ctrl)
+		d->tuner_pass_ctrl(fe,0,d->pll_addr);
+
+	return ret;
+}
+EXPORT_SYMBOL(dvb_usb_pll_set_i2c);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-ids.h b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
new file mode 100644
index 0000000..bcb3419
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
@@ -0,0 +1,83 @@
+/* dvb-usb-ids.h is part of the DVB USB library.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de) see
+ * dvb-usb-init.c for copyright information.
+ *
+ * a header file containing define's for the USB device supported by the
+ * various drivers.
+ */
+#ifndef _DVB_USB_IDS_H_
+#define _DVB_USB_IDS_H_
+
+/* Vendor IDs */
+#define USB_VID_ADSTECH						0x06e1
+#define USB_VID_ANCHOR						0x0547
+#define USB_VID_AVERMEDIA_UNK				0x14aa
+#define USB_VID_AVERMEDIA					0x07ca
+#define USB_VID_COMPRO						0x185b
+#define USB_VID_COMPRO_UNK					0x145f
+#define USB_VID_CYPRESS						0x04b4
+#define USB_VID_DIBCOM						0x10b8
+#define USB_VID_DVICO						0x0fe9
+#define USB_VID_EMPIA						0xeb1a
+#define USB_VID_GRANDTEC					0x5032
+#define USB_VID_HANFTEK						0x15f4
+#define USB_VID_HAUPPAUGE					0x2040
+#define USB_VID_HYPER_PALTEK				0x1025
+#define USB_VID_VISIONPLUS					0x13d3
+#define USB_VID_TWINHAN						0x1822
+#define USB_VID_ULTIMA_ELECTRONIC			0x05d8
+
+/* Product IDs */
+#define USB_PID_ADSTECH_USB2_COLD			0xa333
+#define USB_PID_ADSTECH_USB2_WARM			0xa334
+#define USB_PID_AVERMEDIA_DVBT_USB_COLD		0x0001
+#define USB_PID_AVERMEDIA_DVBT_USB_WARM		0x0002
+#define USB_PID_AVERMEDIA_DVBT_USB2_COLD	0xa800
+#define USB_PID_AVERMEDIA_DVBT_USB2_WARM	0xa801
+#define USB_PID_COMPRO_DVBU2000_COLD		0xd000
+#define USB_PID_COMPRO_DVBU2000_WARM		0xd001
+#define USB_PID_COMPRO_DVBU2000_UNK_COLD	0x010c
+#define USB_PID_COMPRO_DVBU2000_UNK_WARM	0x010d
+#define USB_PID_DIBCOM_MOD3000_COLD			0x0bb8
+#define USB_PID_DIBCOM_MOD3000_WARM			0x0bb9
+#define USB_PID_DIBCOM_MOD3001_COLD			0x0bc6
+#define USB_PID_DIBCOM_MOD3001_WARM			0x0bc7
+#define USB_PID_DIBCOM_ANCHOR_2135_COLD		0x2131
+#define USB_PID_GRANDTEC_DVBT_USB_COLD		0x0fa0
+#define USB_PID_GRANDTEC_DVBT_USB_WARM		0x0fa1
+#define USB_PID_KWORLD_VSTREAM_COLD			0x17de
+#define USB_PID_KWORLD_VSTREAM_WARM			0x17df
+#define USB_PID_TWINHAN_VP7041_COLD			0x3201
+#define USB_PID_TWINHAN_VP7041_WARM			0x3202
+#define USB_PID_TWINHAN_VP7045_COLD			0x3205
+#define USB_PID_TWINHAN_VP7045_WARM			0x3206
+#define USB_PID_DNTV_TINYUSB2_COLD			0x3223
+#define USB_PID_DNTV_TINYUSB2_WARM			0x3224
+#define USB_PID_TWINHAN_VP7021_COLD			0x3207
+#define USB_PID_TWINHAN_VP7021_WARM			0x3208
+#define USB_PID_ULTIMA_TVBOX_COLD			0x8105
+#define USB_PID_ULTIMA_TVBOX_WARM			0x8106
+#define USB_PID_ULTIMA_TVBOX_AN2235_COLD	0x8107
+#define USB_PID_ULTIMA_TVBOX_AN2235_WARM	0x8108
+#define USB_PID_ULTIMA_TVBOX_ANCHOR_COLD	0x2235
+#define USB_PID_ULTIMA_TVBOX_USB2_COLD		0x8109
+#define USB_PID_ULTIMA_TVBOX_USB2_FX_COLD	0x8613
+#define USB_PID_ULTIMA_TVBOX_USB2_FX_WARM	0x1002
+#define USB_PID_UNK_HYPER_PALTEK_COLD		0x005e
+#define USB_PID_UNK_HYPER_PALTEK_WARM		0x005f
+#define USB_PID_HANFTEK_UMT_010_COLD		0x0001
+#define USB_PID_HANFTEK_UMT_010_WARM		0x0015
+#define USB_PID_DTT200U_COLD				0x0201
+#define USB_PID_DTT200U_WARM				0x0301
+#define USB_PID_WINTV_NOVA_T_USB2_COLD		0x9300
+#define USB_PID_WINTV_NOVA_T_USB2_WARM		0x9301
+#define USB_PID_NEBULA_DIGITV				0x0201
+#define USB_PID_DVICO_BLUEBIRD_LGZ201		0xdb00
+#define USB_PID_DVICO_BLUEBIRD_TH7579		0xdb10
+#define USB_PID_DVICO_BLUEBIRD_LGDT			0xd820
+#define USB_PID_DVICO_BLUEBIRD_LGZ201_1		0xdb01
+#define USB_PID_DVICO_BLUEBIRD_TH7579_2		0xdb11
+
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-init.c b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
new file mode 100644
index 0000000..3aadec9
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-init.c
@@ -0,0 +1,211 @@
+/*
+ * DVB USB library - provides a generic interface for a DVB USB device driver.
+ *
+ * dvb-usb-init.c
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ *	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 "dvb-usb-common.h"
+
+/* debug */
+int dvb_usb_debug;
+module_param_named(debug,dvb_usb_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64 (or-able))." DVB_USB_DEBUG_STATUS);
+
+/* general initialization functions */
+int dvb_usb_exit(struct dvb_usb_device *d)
+{
+	deb_info("state before exiting everything: %x\n",d->state);
+	dvb_usb_remote_exit(d);
+	dvb_usb_fe_exit(d);
+	dvb_usb_i2c_exit(d);
+	dvb_usb_dvb_exit(d);
+	dvb_usb_urb_exit(d);
+	deb_info("state should be zero now: %x\n",d->state);
+	d->state = DVB_USB_STATE_INIT;
+	kfree(d->priv);
+	kfree(d);
+	return 0;
+}
+
+static int dvb_usb_init(struct dvb_usb_device *d)
+{
+	int ret = 0;
+
+	sema_init(&d->usb_sem, 1);
+	sema_init(&d->i2c_sem, 1);
+
+	d->state = DVB_USB_STATE_INIT;
+
+/* check the capabilites and set appropriate variables */
+
+/* speed - when running at FULL speed we need a HW PID filter */
+	if (d->udev->speed == USB_SPEED_FULL && !(d->props.caps & DVB_USB_HAS_PID_FILTER)) {
+		err("This USB2.0 device cannot be run on a USB1.1 port. (it lacks a HW PID filter)");
+		return -ENODEV;
+	}
+
+	if ((d->udev->speed == USB_SPEED_FULL && d->props.caps & DVB_USB_HAS_PID_FILTER) ||
+		(d->props.caps & DVB_USB_NEED_PID_FILTERING)) {
+		info("will use the device's hw PID filter.");
+		d->pid_filtering = 1;
+		d->max_feed_count = d->props.pid_filter_count;
+	} else {
+		info("will pass the complete MPEG2 transport stream to the demuxer.");
+		d->pid_filtering = 0;
+		d->max_feed_count = 255;
+	}
+
+	if (d->props.power_ctrl)
+		d->props.power_ctrl(d,1);
+
+	if ((ret = dvb_usb_urb_init(d)) ||
+		(ret = dvb_usb_dvb_init(d)) ||
+		(ret = dvb_usb_i2c_init(d)) ||
+		(ret = dvb_usb_fe_init(d))) {
+		dvb_usb_exit(d);
+		return ret;
+	}
+
+	if ((ret = dvb_usb_remote_init(d)))
+		err("could not initialize remote control.");
+
+	if (d->props.power_ctrl)
+		d->props.power_ctrl(d,0);
+
+	return 0;
+}
+
+/* determine the name and the state of the just found USB device */
+static struct dvb_usb_device_description * dvb_usb_find_device(struct usb_device *udev,struct dvb_usb_properties *props, int *cold)
+{
+	int i,j;
+	struct dvb_usb_device_description *desc = NULL;
+	*cold = -1;
+
+	for (i = 0; i < props->num_device_descs; i++) {
+
+		for (j = 0; j < DVB_USB_ID_MAX_NUM && props->devices[i].cold_ids[j] != NULL; j++) {
+			deb_info("check for cold %x %x\n",props->devices[i].cold_ids[j]->idVendor, props->devices[i].cold_ids[j]->idProduct);
+			if (props->devices[i].cold_ids[j]->idVendor  == le16_to_cpu(udev->descriptor.idVendor) &&
+				props->devices[i].cold_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
+				*cold = 1;
+				desc = &props->devices[i];
+				break;
+			}
+		}
+
+		if (desc != NULL)
+			break;
+
+		for (j = 0; j < DVB_USB_ID_MAX_NUM && props->devices[i].warm_ids[j] != NULL; j++) {
+			deb_info("check for warm %x %x\n",props->devices[i].warm_ids[j]->idVendor, props->devices[i].warm_ids[j]->idProduct);
+			if (props->devices[i].warm_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) &&
+				props->devices[i].warm_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
+				*cold = 0;
+				desc = &props->devices[i];
+				break;
+			}
+		}
+	}
+
+	if (desc != NULL && props->identify_state != NULL)
+		props->identify_state(udev,props,&desc,cold);
+
+	return desc;
+}
+
+/*
+ * USB
+ */
+int dvb_usb_device_init(struct usb_interface *intf, struct dvb_usb_properties *props, struct module *owner)
+{
+	struct usb_device *udev = interface_to_usbdev(intf);
+	struct dvb_usb_device *d = NULL;
+	struct dvb_usb_device_description *desc = NULL;
+
+	int ret = -ENOMEM,cold=0;
+
+	if ((desc = dvb_usb_find_device(udev,props,&cold)) == NULL) {
+		deb_err("something went very wrong, device was not found in current device list - let's see what comes next.\n");
+		return -ENODEV;
+	}
+
+	if (cold) {
+		info("found a '%s' in cold state, will try to load a firmware",desc->name);
+		ret = usb_cypress_load_firmware(udev,props->firmware,props->usb_ctrl);
+	} else {
+		info("found a '%s' in warm state.",desc->name);
+		d = kmalloc(sizeof(struct dvb_usb_device),GFP_KERNEL);
+		if (d == NULL) {
+			err("no memory for 'struct dvb_usb_device'");
+			return ret;
+		}
+		memset(d,0,sizeof(struct dvb_usb_device));
+
+		d->udev = udev;
+		memcpy(&d->props,props,sizeof(struct dvb_usb_properties));
+		d->desc = desc;
+		d->owner = owner;
+
+		if (d->props.size_of_priv > 0) {
+			d->priv = kmalloc(d->props.size_of_priv,GFP_KERNEL);
+			if (d->priv == NULL) {
+				err("no memory for priv in 'struct dvb_usb_device'");
+				kfree(d);
+				return -ENOMEM;
+			}
+			memset(d->priv,0,d->props.size_of_priv);
+		}
+
+		usb_set_intfdata(intf, d);
+
+		ret = dvb_usb_init(d);
+	}
+
+	if (ret == 0)
+		info("%s successfully initialized and connected.",desc->name);
+	else
+		info("%s error while loading driver (%d)",desc->name,ret);
+	return ret;
+}
+EXPORT_SYMBOL(dvb_usb_device_init);
+
+void dvb_usb_device_exit(struct usb_interface *intf)
+{
+	struct dvb_usb_device *d = usb_get_intfdata(intf);
+	const char *name = "generic DVB-USB module";
+
+	usb_set_intfdata(intf,NULL);
+	if (d != NULL && d->desc != NULL) {
+		name = d->desc->name;
+		dvb_usb_exit(d);
+	}
+	info("%s successfully deinitialized and disconnected.",name);
+
+}
+EXPORT_SYMBOL(dvb_usb_device_exit);
+
+/* module stuff */
+static int __init dvb_usb_module_init(void)
+{
+	return 0;
+}
+
+static void __exit dvb_usb_module_exit(void)
+{
+}
+
+module_init (dvb_usb_module_init);
+module_exit (dvb_usb_module_exit);
+
+MODULE_VERSION("0.3");
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("A library module containing commonly used USB and DVB function USB DVB devices");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
new file mode 100644
index 0000000..9f1e23f
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
@@ -0,0 +1,175 @@
+/* dvb-usb-remote.c is part of the DVB USB library.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ * see dvb-usb-init.c for copyright information.
+ *
+ * This file contains functions for initializing the the input-device and for handling remote-control-queries.
+ */
+#include "dvb-usb-common.h"
+
+/* Remote-control poll function - called every dib->rc_query_interval ms to see
+ * whether the remote control has received anything.
+ *
+ * TODO: Fix the repeat rate of the input device.
+ */
+static void dvb_usb_read_remote_control(void *data)
+{
+	struct dvb_usb_device *d = data;
+	u32 event;
+	int state;
+
+	/* TODO: need a lock here.  We can simply skip checking for the remote control
+	   if we're busy. */
+
+	if (d->props.rc_query(d,&event,&state)) {
+		err("error while querying for an remote control event.");
+		goto schedule;
+	}
+
+
+	switch (state) {
+		case REMOTE_NO_KEY_PRESSED:
+			break;
+		case REMOTE_KEY_PRESSED:
+			deb_rc("key pressed\n");
+			d->last_event = event;
+		case REMOTE_KEY_REPEAT:
+			deb_rc("key repeated\n");
+			input_event(&d->rc_input_dev, EV_KEY, event, 1);
+			input_event(&d->rc_input_dev, EV_KEY, d->last_event, 0);
+			input_sync(&d->rc_input_dev);
+			break;
+		default:
+			break;
+	}
+
+/* improved repeat handling ???
+	switch (state) {
+		case REMOTE_NO_KEY_PRESSED:
+			deb_rc("NO KEY PRESSED\n");
+			if (d->last_state != REMOTE_NO_KEY_PRESSED) {
+				deb_rc("releasing event %d\n",d->last_event);
+				input_event(&d->rc_input_dev, EV_KEY, d->last_event, 0);
+				input_sync(&d->rc_input_dev);
+			}
+			d->last_state = REMOTE_NO_KEY_PRESSED;
+			d->last_event = 0;
+			break;
+		case REMOTE_KEY_PRESSED:
+			deb_rc("KEY PRESSED\n");
+			deb_rc("pressing event %d\n",event);
+
+			input_event(&d->rc_input_dev, EV_KEY, event, 1);
+			input_sync(&d->rc_input_dev);
+
+			d->last_event = event;
+			d->last_state = REMOTE_KEY_PRESSED;
+			break;
+		case REMOTE_KEY_REPEAT:
+			deb_rc("KEY_REPEAT\n");
+			if (d->last_state != REMOTE_NO_KEY_PRESSED) {
+				deb_rc("repeating event %d\n",d->last_event);
+				input_event(&d->rc_input_dev, EV_KEY, d->last_event, 2);
+				input_sync(&d->rc_input_dev);
+				d->last_state = REMOTE_KEY_REPEAT;
+			}
+		default:
+			break;
+	}
+*/
+
+schedule:
+	schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval));
+}
+
+int dvb_usb_remote_init(struct dvb_usb_device *d)
+{
+	int i;
+	if (d->props.rc_key_map == NULL)
+		return 0;
+
+	/* Initialise the remote-control structures.*/
+	init_input_dev(&d->rc_input_dev);
+
+	d->rc_input_dev.evbit[0] = BIT(EV_KEY);
+	d->rc_input_dev.keycodesize = sizeof(unsigned char);
+	d->rc_input_dev.keycodemax = KEY_MAX;
+	d->rc_input_dev.name = "IR-receiver inside an USB DVB receiver";
+
+	/* set the bits for the keys */
+	deb_rc("key map size: %d\n",d->props.rc_key_map_size);
+	for (i = 0; i < d->props.rc_key_map_size; i++) {
+		deb_rc("setting bit for event %d item %d\n",d->props.rc_key_map[i].event, i);
+		set_bit(d->props.rc_key_map[i].event, d->rc_input_dev.keybit);
+	}
+
+	/* Start the remote-control polling. */
+	if (d->props.rc_interval < 40)
+		d->props.rc_interval = 100; /* default */
+
+	/* setting these two values to non-zero, we have to manage key repeats */
+	d->rc_input_dev.rep[REP_PERIOD] = d->props.rc_interval;
+	d->rc_input_dev.rep[REP_DELAY]  = d->props.rc_interval + 150;
+
+	input_register_device(&d->rc_input_dev);
+
+	INIT_WORK(&d->rc_query_work, dvb_usb_read_remote_control, d);
+
+	info("schedule remote query interval to %d msecs.",d->props.rc_interval);
+	schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval));
+
+	d->state |= DVB_USB_STATE_REMOTE;
+
+	return 0;
+}
+
+int dvb_usb_remote_exit(struct dvb_usb_device *d)
+{
+	if (d->state & DVB_USB_STATE_REMOTE) {
+		cancel_delayed_work(&d->rc_query_work);
+		flush_scheduled_work();
+		input_unregister_device(&d->rc_input_dev);
+	}
+	d->state &= ~DVB_USB_STATE_REMOTE;
+	return 0;
+}
+
+#define DVB_USB_RC_NEC_EMPTY           0x00
+#define DVB_USB_RC_NEC_KEY_PRESSED     0x01
+#define DVB_USB_RC_NEC_KEY_REPEATED    0x02
+int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d,
+		u8 keybuf[5], u32 *event, int *state)
+{
+	int i;
+	struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
+	*event = 0;
+	*state = REMOTE_NO_KEY_PRESSED;
+	switch (keybuf[0]) {
+		case DVB_USB_RC_NEC_EMPTY:
+			break;
+		case DVB_USB_RC_NEC_KEY_PRESSED:
+			if ((u8) ~keybuf[1] != keybuf[2] ||
+				(u8) ~keybuf[3] != keybuf[4]) {
+				deb_err("remote control checksum failed.\n");
+				break;
+			}
+			/* See if we can match the raw key code. */
+			for (i = 0; i < sizeof(keymap)/sizeof(struct dvb_usb_rc_key); i++)
+				if (keymap[i].custom == keybuf[1] &&
+					keymap[i].data == keybuf[3]) {
+					*event = keymap[i].event;
+					*state = REMOTE_KEY_PRESSED;
+					break;
+				}
+			deb_err("key mapping failed - no appropriate key found in keymapping\n");
+			break;
+		case DVB_USB_RC_NEC_KEY_REPEATED:
+			*state = REMOTE_KEY_REPEAT;
+			break;
+		default:
+			deb_err("unkown type of remote status: %d\n",keybuf[0]);
+			break;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(dvb_usb_nec_rc_key_to_event);
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-urb.c b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
new file mode 100644
index 0000000..83d476f
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb-urb.c
@@ -0,0 +1,211 @@
+/* dvb-usb-urb.c is part of the DVB USB library.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ * see dvb-usb-init.c for copyright information.
+ *
+ * This file contains functions for initializing and handling the
+ * USB and URB stuff.
+ */
+#include "dvb-usb-common.h"
+
+int dvb_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf,
+	u16 rlen, int delay_ms)
+{
+	int actlen,ret = -ENOMEM;
+
+	if (d->props.generic_bulk_ctrl_endpoint == 0) {
+		err("endpoint for generic control not specified.");
+		return -EINVAL;
+	}
+
+	if (wbuf == NULL || wlen == 0)
+		return -EINVAL;
+
+	if ((ret = down_interruptible(&d->usb_sem)))
+		return ret;
+
+	debug_dump(wbuf,wlen,deb_xfer);
+
+	ret = usb_bulk_msg(d->udev,usb_sndbulkpipe(d->udev,
+			d->props.generic_bulk_ctrl_endpoint), wbuf,wlen,&actlen,
+			2*HZ);
+
+	if (ret)
+		err("bulk message failed: %d (%d/%d)",ret,wlen,actlen);
+	else
+		ret = actlen != wlen ? -1 : 0;
+
+	/* an answer is expected, and no error before */
+	if (!ret && rbuf && rlen) {
+		if (delay_ms)
+			msleep(delay_ms);
+
+		ret = usb_bulk_msg(d->udev,usb_rcvbulkpipe(d->udev,
+				d->props.generic_bulk_ctrl_endpoint),rbuf,rlen,&actlen,
+				2*HZ);
+
+		if (ret)
+			err("recv bulk message failed: %d",ret);
+		else
+			debug_dump(rbuf,actlen,deb_xfer);
+	}
+
+	up(&d->usb_sem);
+	return ret;
+}
+EXPORT_SYMBOL(dvb_usb_generic_rw);
+
+int dvb_usb_generic_write(struct dvb_usb_device *d, u8 *buf, u16 len)
+{
+	return dvb_usb_generic_rw(d,buf,len,NULL,0,0);
+}
+EXPORT_SYMBOL(dvb_usb_generic_write);
+
+static void dvb_usb_bulk_urb_complete(struct urb *urb, struct pt_regs *ptregs)
+{
+	struct dvb_usb_device *d = urb->context;
+
+	deb_ts("bulk urb completed. feedcount: %d, status: %d, length: %d\n",d->feedcount,urb->status,
+			urb->actual_length);
+
+	switch (urb->status) {
+		case 0:         /* success */
+		case -ETIMEDOUT:    /* NAK */
+			break;
+		case -ECONNRESET:   /* kill */
+		case -ENOENT:
+		case -ESHUTDOWN:
+			return;
+		default:        /* error */
+			deb_ts("urb completition error %d.", urb->status);
+			break;
+	}
+
+	if (d->feedcount > 0 && urb->actual_length > 0) {
+		if (d->state & DVB_USB_STATE_DVB)
+			dvb_dmx_swfilter(&d->demux, (u8*) urb->transfer_buffer,urb->actual_length);
+	} else
+		deb_ts("URB dropped because of feedcount.\n");
+
+	usb_submit_urb(urb,GFP_ATOMIC);
+}
+
+int dvb_usb_urb_kill(struct dvb_usb_device *d)
+{
+	int i;
+	for (i = 0; i < d->urbs_submitted; i++) {
+		deb_info("killing URB no. %d.\n",i);
+
+		/* stop the URB */
+		usb_kill_urb(d->urb_list[i]);
+	}
+	d->urbs_submitted = 0;
+	return 0;
+}
+
+int dvb_usb_urb_submit(struct dvb_usb_device *d)
+{
+	int i,ret;
+	for (i = 0; i < d->urbs_initialized; i++) {
+		deb_info("submitting URB no. %d\n",i);
+		if ((ret = usb_submit_urb(d->urb_list[i],GFP_ATOMIC))) {
+			err("could not submit URB no. %d - get them all back\n",i);
+			dvb_usb_urb_kill(d);
+			return ret;
+		}
+		d->urbs_submitted++;
+	}
+	return 0;
+}
+
+static int dvb_usb_bulk_urb_init(struct dvb_usb_device *d)
+{
+	int i,bufsize = d->props.urb.count * d->props.urb.u.bulk.buffersize;
+
+	deb_info("allocate %d bytes as buffersize for all URBs\n",bufsize);
+	/* allocate the actual buffer for the URBs */
+	if ((d->buffer =  usb_buffer_alloc(d->udev, bufsize, SLAB_ATOMIC, &d->dma_handle)) == NULL) {
+		deb_info("not enough memory for urb-buffer allocation.\n");
+		return -ENOMEM;
+	}
+	deb_info("allocation successful\n");
+	memset(d->buffer,0,bufsize);
+
+	d->state |= DVB_USB_STATE_URB_BUF;
+
+	/* allocate the URBs */
+	for (i = 0; i < d->props.urb.count; i++) {
+		if (!(d->urb_list[i] = usb_alloc_urb(0,GFP_ATOMIC))) {
+			return -ENOMEM;
+		}
+
+		usb_fill_bulk_urb( d->urb_list[i], d->udev,
+				usb_rcvbulkpipe(d->udev,d->props.urb.endpoint),
+				&d->buffer[i*d->props.urb.u.bulk.buffersize],
+				d->props.urb.u.bulk.buffersize,
+				dvb_usb_bulk_urb_complete, d);
+
+		d->urb_list[i]->transfer_flags = 0;
+		d->urbs_initialized++;
+	}
+	return 0;
+}
+
+int dvb_usb_urb_init(struct dvb_usb_device *d)
+{
+	/*
+	 * when reloading the driver w/o replugging the device
+	 * sometimes a timeout occures, this helps
+	 */
+	if (d->props.generic_bulk_ctrl_endpoint != 0) {
+		usb_clear_halt(d->udev,usb_sndbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
+		usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
+	}
+	usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.urb.endpoint));
+
+	/* allocate the array for the data transfer URBs */
+	d->urb_list = kmalloc(d->props.urb.count * sizeof(struct urb *),GFP_KERNEL);
+	if (d->urb_list == NULL)
+		return -ENOMEM;
+	memset(d->urb_list,0,d->props.urb.count * sizeof(struct urb *));
+	d->state |= DVB_USB_STATE_URB_LIST;
+
+	switch (d->props.urb.type) {
+		case DVB_USB_BULK:
+			return dvb_usb_bulk_urb_init(d);
+		case DVB_USB_ISOC:
+			err("isochronous transfer not yet implemented in dvb-usb.");
+			return -EINVAL;
+		default:
+			err("unkown URB-type for data transfer.");
+			return -EINVAL;
+	}
+}
+
+int dvb_usb_urb_exit(struct dvb_usb_device *d)
+{
+	int i;
+
+	dvb_usb_urb_kill(d);
+
+	if (d->state & DVB_USB_STATE_URB_LIST) {
+		for (i = 0; i < d->urbs_initialized; i++) {
+			if (d->urb_list[i] != NULL) {
+				deb_info("freeing URB no. %d.\n",i);
+				/* free the URBs */
+				usb_free_urb(d->urb_list[i]);
+			}
+		}
+		d->urbs_initialized = 0;
+		/* free the urb array */
+		kfree(d->urb_list);
+		d->state &= ~DVB_USB_STATE_URB_LIST;
+	}
+
+	if (d->state & DVB_USB_STATE_URB_BUF)
+		usb_buffer_free(d->udev, d->props.urb.u.bulk.buffersize * d->props.urb.count,
+				d->buffer, d->dma_handle);
+
+	d->state &= ~DVB_USB_STATE_URB_BUF;
+	return 0;
+}
diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h
new file mode 100644
index 0000000..abcee19
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/dvb-usb.h
@@ -0,0 +1,315 @@
+/* dvb-usb.h is part of the DVB USB library.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ * see dvb-usb-init.c for copyright information.
+ *
+ * the headerfile, all dvb-usb-drivers have to include.
+ */
+#ifndef __DVB_USB_H__
+#define __DVB_USB_H__
+
+#include <linux/config.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+
+#include "dvb_frontend.h"
+#include "dvb_demux.h"
+#include "dvb_net.h"
+#include "dmxdev.h"
+
+#include "dvb-pll.h"
+
+#include "dvb-usb-ids.h"
+
+/* debug */
+#ifdef CONFIG_DVB_USB_DEBUG
+#define dprintk(var,level,args...) \
+	    do { if ((var & level)) { printk(args); } } while (0)
+
+#define debug_dump(b,l,func) {\
+	int loop_; \
+	for (loop_ = 0; loop_ < l; loop_++) func("%02x ", b[loop_]); \
+	func("\n");\
+}
+#define DVB_USB_DEBUG_STATUS
+#else
+#define dprintk(args...)
+#define debug_dump(b,l,func)
+
+#define DVB_USB_DEBUG_STATUS " (debugging is not enabled)"
+
+#endif
+
+/* generic log methods - taken from usb.h */
+#ifndef DVB_USB_LOG_PREFIX
+ #define DVB_USB_LOG_PREFIX "dvb-usb (please define a log prefix)"
+#endif
+
+#undef err
+#define err(format, arg...)  printk(KERN_ERR     DVB_USB_LOG_PREFIX ": " format "\n" , ## arg)
+#undef info
+#define info(format, arg...) printk(KERN_INFO    DVB_USB_LOG_PREFIX ": " format "\n" , ## arg)
+#undef warn
+#define warn(format, arg...) printk(KERN_WARNING DVB_USB_LOG_PREFIX ": " format "\n" , ## arg)
+
+/**
+ * struct dvb_usb_device_description - name and its according USB IDs
+ * @name: real name of the box, regardless which DVB USB device class is in use
+ * @cold_ids: array of struct usb_device_id which describe the device in
+ *  pre-firmware state
+ * @warm_ids: array of struct usb_device_id which describe the device in
+ *  post-firmware state
+ *
+ * Each DVB USB device class can have one or more actual devices, this struct
+ * assigns a name to it.
+ */
+struct dvb_usb_device_description {
+	const char *name;
+
+#define DVB_USB_ID_MAX_NUM 15
+	struct usb_device_id *cold_ids[DVB_USB_ID_MAX_NUM];
+	struct usb_device_id *warm_ids[DVB_USB_ID_MAX_NUM];
+};
+
+/**
+ * struct dvb_usb_rc_key - a remote control key and its input-event
+ * @custom: the vendor/custom part of the key
+ * @data: the actual key part
+ * @event: the input event assigned to key identified by custom and data
+ */
+struct dvb_usb_rc_key {
+	u8 custom,data;
+	u32 event;
+};
+
+struct dvb_usb_device;
+
+/**
+ * struct dvb_usb_properties - properties of a dvb-usb-device
+ * @caps: capabilites of the DVB USB device.
+ * @pid_filter_count: number of PID filter position in the optional hardware
+ *  PID-filter.
+ *
+ * @usb_ctrl: which USB device-side controller is in use. Needed for firmware
+ *  download.
+ * @firmware: name of the firmware file.
+ *
+ * @size_of_priv: how many bytes shall be allocated for the private field
+ *  of struct dvb_usb_device.
+ *
+ * @power_ctrl: called to enable/disable power of the device.
+ * @streaming_crtl: called to start and stop the MPEG2-TS streaming of the
+ *  device (not URB submitting/killing).
+ * @pid_filter_ctrl: called to en/disable the PID filter, if any.
+ * @pid_filter: called to set/unset a PID for filtering.
+ *
+ * @read_mac_address: called to read the MAC address of the device.
+ *
+ * @frontend_attach: called to attach the possible frontends (fill fe-field
+ *  of struct dvb_usb_device).
+ * @tuner_attach: called to attach the correct tuner and to fill pll_addr,
+ *  pll_desc and pll_init_buf of struct dvb_usb_device).
+ * @identify_state: called to determine the state (cold or warm), when it
+ *  is not distinguishable by the USB IDs.
+ *
+ * @rc_key_map: a hard-wired array of struct dvb_usb_rc_key (NULL to disable
+ *  remote control handling).
+ * @rc_key_map_size: number of items in @rc_key_map.
+ * @rc_query: called to query an event event.
+ * @rc_interval: time in ms between two queries.
+ *
+ * @i2c_algo: i2c_algorithm if the device has I2CoverUSB.
+ *
+ * @generic_bulk_ctrl_endpoint: most of the DVB USB devices have a generic
+ *  endpoint which received control messages with bulk transfers. When this
+ *  is non-zero, one can use dvb_usb_generic_rw and dvb_usb_generic_write-
+ *  helper functions.
+ *
+ * @urb: describes the kind of USB transfer used for MPEG2-TS-streaming.
+ *  Currently only BULK is implemented
+ *
+ * @num_device_descs: number of struct dvb_usb_device_description in @devices
+ * @devices: array of struct dvb_usb_device_description compatibles with these
+ *  properties.
+ */
+struct dvb_usb_properties {
+
+#define DVB_USB_HAS_PID_FILTER               0x01
+#define DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF 0x02
+#define DVB_USB_NEED_PID_FILTERING           0x04
+#define DVB_USB_IS_AN_I2C_ADAPTER            0x08
+	int caps;
+	int pid_filter_count;
+
+#define CYPRESS_AN2135  0
+#define CYPRESS_AN2235  1
+#define CYPRESS_FX2     2
+	int usb_ctrl;
+	const char *firmware;
+
+	int size_of_priv;
+
+	int (*power_ctrl) (struct dvb_usb_device *, int);
+	int (*streaming_ctrl) (struct dvb_usb_device *, int);
+	int (*pid_filter_ctrl) (struct dvb_usb_device *, int);
+	int (*pid_filter) (struct dvb_usb_device *, int, u16, int);
+
+	int (*read_mac_address) (struct dvb_usb_device *, u8 []);
+	int (*frontend_attach) (struct dvb_usb_device *);
+	int (*tuner_attach) (struct dvb_usb_device *);
+
+	int (*identify_state) (struct usb_device *, struct dvb_usb_properties *,
+			struct dvb_usb_device_description **, int *);
+
+/* remote control properties */
+#define REMOTE_NO_KEY_PRESSED      0x00
+#define REMOTE_KEY_PRESSED         0x01
+#define REMOTE_KEY_REPEAT          0x02
+	struct dvb_usb_rc_key *rc_key_map;
+	int rc_key_map_size;
+	int (*rc_query) (struct dvb_usb_device *, u32 *, int *);
+	int rc_interval;
+
+	struct i2c_algorithm *i2c_algo;
+
+	int generic_bulk_ctrl_endpoint;
+
+	struct {
+#define DVB_USB_BULK  1
+#define DVB_USB_ISOC  2
+		int type;
+		int count;
+		int endpoint;
+
+		union {
+			struct {
+				int buffersize; /* per URB */
+			} bulk;
+			struct {
+				int framesperurb;
+				int framesize;
+			} isoc;
+		} u;
+	} urb;
+
+	int num_device_descs;
+	struct dvb_usb_device_description devices[8];
+};
+
+
+/**
+ * struct dvb_usb_device - object of a DVB USB device
+ * @props: copy of the struct dvb_usb_properties this device belongs to.
+ * @desc: pointer to the device's struct dvb_usb_device_description.
+ * @state: initialization and runtime state of the device.
+ *
+ * @udev: pointer to the device's struct usb_device.
+ * @urb_list: array of dynamically allocated struct urb for the MPEG2-TS-
+ *  streaming.
+ * @buffer: buffer used to streaming.
+ * @dma_handle: dma_addr_t for buffer.
+ * @urbs_initialized: number of URBs initialized.
+ * @urbs_submitted: number of URBs submitted.
+ * @feedcount: number of reqested feeds (used for streaming-activation)
+ * @pid_filtering: is hardware pid_filtering used or not.
+ * @usb_sem: semaphore of USB control messages (reading needs two messages)
+ * @i2c_sem: semaphore for i2c-transfers
+ * @i2c_adap: device's i2c_adapter if it uses I2CoverUSB
+ * @pll_addr: I2C address of the tuner for programming
+ * @pll_init: array containing the initialization buffer
+ * @pll_desc: pointer to the appropriate struct dvb_pll_desc
+ * @tuner_pass_ctrl: called to (de)activate tuner passthru of the demod
+ * @dvb_adap: device's dvb_adapter.
+ * @dmxdev: device's dmxdev.
+ * @demux: device's software demuxer.
+ * @dvb_net: device's dvb_net interfaces.
+ * @dvb_frontend: device's frontend.
+ * @max_feed_count: how many feeds can be handled simultaneously by this
+ *  device
+ * @fe_sleep: rerouted frontend-sleep function.
+ * @fe_init: rerouted frontend-init (wakeup) function.
+ * @rc_input_dev: input device for the remote control.
+ * @rc_query_work: struct work_struct frequent rc queries
+ * @last_event: last triggered event
+ * @last_state: last state (no, pressed, repeat)
+ * @owner: owner of the dvb_adapter
+ * @priv: private data of the actual driver (allocate by dvb-usb, size defined
+ *  in size_of_priv of dvb_usb_properties).
+ */
+struct dvb_usb_device {
+	struct dvb_usb_properties props;
+	struct dvb_usb_device_description *desc;
+
+#define DVB_USB_STATE_INIT        0x000
+#define DVB_USB_STATE_URB_LIST    0x001
+#define DVB_USB_STATE_URB_BUF     0x002
+#define DVB_USB_STATE_DVB         0x004
+#define DVB_USB_STATE_I2C         0x008
+#define DVB_USB_STATE_REMOTE      0x010
+#define DVB_USB_STATE_URB_SUBMIT  0x020
+	int state;
+
+	/* usb */
+	struct usb_device *udev;
+	struct urb **urb_list;
+	u8 *buffer;
+	dma_addr_t dma_handle;
+	int urbs_initialized;
+	int urbs_submitted;
+
+	int feedcount;
+	int pid_filtering;
+
+	/* locking */
+	struct semaphore usb_sem;
+
+	/* i2c */
+	struct semaphore i2c_sem;
+	struct i2c_adapter i2c_adap;
+
+	/* tuner programming information */
+	u8 pll_addr;
+	u8 pll_init[4];
+	struct dvb_pll_desc *pll_desc;
+	int (*tuner_pass_ctrl)(struct dvb_frontend *, int, u8);
+
+	/* dvb */
+	struct dvb_adapter dvb_adap;
+	struct dmxdev dmxdev;
+	struct dvb_demux demux;
+	struct dvb_net dvb_net;
+	struct dvb_frontend* fe;
+	int max_feed_count;
+
+	int (*fe_sleep) (struct dvb_frontend *);
+	int (*fe_init)  (struct dvb_frontend *);
+
+	/* remote control */
+	struct input_dev rc_input_dev;
+	struct work_struct rc_query_work;
+	u32 last_event;
+	int last_state;
+
+	struct module *owner;
+
+	void *priv;
+};
+
+extern int dvb_usb_device_init(struct usb_interface *, struct dvb_usb_properties *, struct module *);
+extern void dvb_usb_device_exit(struct usb_interface *);
+
+/* the generic read/write method for device control */
+extern int dvb_usb_generic_rw(struct dvb_usb_device *, u8 *, u16, u8 *, u16,int);
+extern int dvb_usb_generic_write(struct dvb_usb_device *, u8 *, u16);
+
+/* commonly used remote control parsing */
+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 *);
+
+
+#endif
diff --git a/drivers/media/dvb/dvb-usb/nova-t-usb2.c b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
new file mode 100644
index 0000000..9d83781
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/nova-t-usb2.c
@@ -0,0 +1,236 @@
+/* DVB USB framework compliant Linux driver for the Hauppauge WinTV-NOVA-T usb2
+ * DVB-T receiver.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ *	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 "dibusb.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=rc,2=eeprom (|-able))." DVB_USB_DEBUG_STATUS);
+
+#define deb_rc(args...) dprintk(debug,0x01,args)
+#define deb_ee(args...) dprintk(debug,0x02,args)
+
+/* Hauppauge NOVA-T USB2 keys */
+static struct dvb_usb_rc_key haupp_rc_keys [] = {
+	{ 0x1e, 0x00, KEY_0 },
+	{ 0x1e, 0x01, KEY_1 },
+	{ 0x1e, 0x02, KEY_2 },
+	{ 0x1e, 0x03, KEY_3 },
+	{ 0x1e, 0x04, KEY_4 },
+	{ 0x1e, 0x05, KEY_5 },
+	{ 0x1e, 0x06, KEY_6 },
+	{ 0x1e, 0x07, KEY_7 },
+	{ 0x1e, 0x08, KEY_8 },
+	{ 0x1e, 0x09, KEY_9 },
+	{ 0x1e, 0x0a, KEY_KPASTERISK },
+	{ 0x1e, 0x0b, KEY_RED },
+	{ 0x1e, 0x0c, KEY_RADIO },
+	{ 0x1e, 0x0d, KEY_MENU },
+	{ 0x1e, 0x0e, KEY_GRAVE }, /* # */
+	{ 0x1e, 0x0f, KEY_MUTE },
+	{ 0x1e, 0x10, KEY_VOLUMEUP },
+	{ 0x1e, 0x11, KEY_VOLUMEDOWN },
+	{ 0x1e, 0x12, KEY_CHANNEL },
+	{ 0x1e, 0x14, KEY_UP },
+	{ 0x1e, 0x15, KEY_DOWN },
+	{ 0x1e, 0x16, KEY_LEFT },
+	{ 0x1e, 0x17, KEY_RIGHT },
+	{ 0x1e, 0x18, KEY_VIDEO },
+	{ 0x1e, 0x19, KEY_AUDIO },
+	{ 0x1e, 0x1a, KEY_MEDIA },
+	{ 0x1e, 0x1b, KEY_EPG },
+	{ 0x1e, 0x1c, KEY_TV },
+	{ 0x1e, 0x1e, KEY_NEXT },
+	{ 0x1e, 0x1f, KEY_BACK },
+	{ 0x1e, 0x20, KEY_CHANNELUP },
+	{ 0x1e, 0x21, KEY_CHANNELDOWN },
+	{ 0x1e, 0x24, KEY_LAST }, /* Skip backwards */
+	{ 0x1e, 0x25, KEY_OK },
+	{ 0x1e, 0x29, KEY_BLUE},
+	{ 0x1e, 0x2e, KEY_GREEN },
+	{ 0x1e, 0x30, KEY_PAUSE },
+	{ 0x1e, 0x32, KEY_REWIND },
+	{ 0x1e, 0x34, KEY_FASTFORWARD },
+	{ 0x1e, 0x35, KEY_PLAY },
+	{ 0x1e, 0x36, KEY_STOP },
+	{ 0x1e, 0x37, KEY_RECORD },
+	{ 0x1e, 0x38, KEY_YELLOW },
+	{ 0x1e, 0x3b, KEY_GOTO },
+	{ 0x1e, 0x3d, KEY_POWER },
+};
+
+/* Firmware bug? sometimes, when a new key is pressed, the previous pressed key
+ * is delivered. No workaround yet, maybe a new firmware.
+ */
+static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
+{
+	u8 key[5],cmd[2] = { DIBUSB_REQ_POLL_REMOTE, 0x35 }, data,toggle,custom;
+	u16 raw;
+	int i;
+	struct dibusb_state *st = d->priv;
+
+	dvb_usb_generic_rw(d,cmd,2,key,5,0);
+
+	*state = REMOTE_NO_KEY_PRESSED;
+	switch (key[0]) {
+		case DIBUSB_RC_HAUPPAUGE_KEY_PRESSED:
+			raw = ((key[1] << 8) | key[2]) >> 3;
+			toggle = !!(raw & 0x800);
+			data = raw & 0x3f;
+			custom = (raw >> 6) & 0x1f;
+
+			deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to c: %02x d: %02x toggle: %d\n",key[1],key[2],key[3],custom,data,toggle);
+
+			for (i = 0; i < ARRAY_SIZE(haupp_rc_keys); i++) {
+				deb_rc("c: %x, d: %x\n",haupp_rc_keys[i].data,haupp_rc_keys[i].custom);
+				if (haupp_rc_keys[i].data == data &&
+					haupp_rc_keys[i].custom == custom) {
+					*event = haupp_rc_keys[i].event;
+					*state = REMOTE_KEY_PRESSED;
+					if (st->old_toggle == toggle) {
+						if (st->last_repeat_count++ < 2)
+							*state = REMOTE_NO_KEY_PRESSED;
+					} else {
+						st->last_repeat_count = 0;
+						st->old_toggle = toggle;
+					}
+					break;
+				}
+			}
+
+			break;
+		case DIBUSB_RC_HAUPPAUGE_KEY_EMPTY:
+		default:
+			break;
+	}
+
+	return 0;
+}
+
+static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6])
+{
+	int i;
+	u8 b;
+
+	mac[0] = 0x00;
+	mac[1] = 0x0d;
+	mac[2] = 0xfe;
+
+	/* this is a complete guess, but works for my box */
+	for (i = 136; i < 139; i++) {
+		dibusb_read_eeprom_byte(d,i, &b);
+
+		mac[5 - (i - 136)] = b;
+
+/*		deb_ee("%02x ",b);
+		if ((i+1) % 16 == 0)
+			deb_ee("\n");*/
+	}
+
+	return 0;
+}
+
+/* USB Driver stuff */
+static struct dvb_usb_properties nova_t_properties;
+
+static int nova_t_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	return dvb_usb_device_init(intf,&nova_t_properties,THIS_MODULE);
+}
+
+/* do not change the order of the ID table */
+static struct usb_device_id nova_t_table [] = {
+/* 00 */	{ USB_DEVICE(USB_VID_HAUPPAUGE,     USB_PID_WINTV_NOVA_T_USB2_COLD) },
+/* 01 */	{ USB_DEVICE(USB_VID_HAUPPAUGE,     USB_PID_WINTV_NOVA_T_USB2_WARM) },
+			{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, nova_t_table);
+
+static struct dvb_usb_properties nova_t_properties = {
+	.caps = DVB_USB_HAS_PID_FILTER | DVB_USB_PID_FILTER_CAN_BE_TURNED_OFF | DVB_USB_IS_AN_I2C_ADAPTER,
+	.pid_filter_count = 32,
+
+	.usb_ctrl = CYPRESS_FX2,
+	.firmware = "dvb-usb-nova-t-usb2-01.fw",
+
+	.size_of_priv     = sizeof(struct dibusb_state),
+
+	.streaming_ctrl   = dibusb2_0_streaming_ctrl,
+	.pid_filter       = dibusb_pid_filter,
+	.pid_filter_ctrl  = dibusb_pid_filter_ctrl,
+	.power_ctrl       = dibusb2_0_power_ctrl,
+	.frontend_attach  = dibusb_dib3000mc_frontend_attach,
+	.tuner_attach     = dibusb_dib3000mc_tuner_attach,
+	.read_mac_address = nova_t_read_mac_address,
+
+	.rc_interval      = 100,
+	.rc_key_map       = haupp_rc_keys,
+	.rc_key_map_size  = ARRAY_SIZE(haupp_rc_keys),
+	.rc_query         = nova_t_rc_query,
+
+	.i2c_algo         = &dibusb_i2c_algo,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
+	/* parameter for the MPEG2-data transfer */
+	.urb = {
+		.type = DVB_USB_BULK,
+		.count = 7,
+		.endpoint = 0x06,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+
+	.num_device_descs = 1,
+	.devices = {
+		{   "Hauppauge WinTV-NOVA-T usb2",
+			{ &nova_t_table[0], NULL },
+			{ &nova_t_table[1], NULL },
+		},
+	}
+};
+
+static struct usb_driver nova_t_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "Hauppauge WinTV-NOVA-T usb2",
+	.probe		= nova_t_probe,
+	.disconnect = dvb_usb_device_exit,
+	.id_table	= nova_t_table,
+};
+
+/* module stuff */
+static int __init nova_t_module_init(void)
+{
+	int result;
+	if ((result = usb_register(&nova_t_driver))) {
+		err("usb_register failed. Error number %d",result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void __exit nova_t_module_exit(void)
+{
+	/* deregister this driver from the USB subsystem */
+	usb_deregister(&nova_t_driver);
+}
+
+module_init (nova_t_module_init);
+module_exit (nova_t_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("Hauppauge WinTV-NOVA-T usb2");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/umt-010.c b/drivers/media/dvb/dvb-usb/umt-010.c
new file mode 100644
index 0000000..aa56042
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/umt-010.c
@@ -0,0 +1,162 @@
+/* DVB USB framework compliant Linux driver for the HanfTek UMT-010 USB2.0
+ * DVB-T receiver.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ *	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 "dibusb.h"
+
+#include "mt352.h"
+
+static int umt_mt352_demod_init(struct dvb_frontend *fe)
+{
+	static u8 mt352_clock_config[] = { 0x89, 0xb8, 0x2d };
+	static u8 mt352_reset[] = { 0x50, 0x80 };
+	static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 };
+	static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 };
+	static u8 mt352_agc_cfg[] = { 0x67, 0x10, 0xa0 };
+
+	static u8 mt352_sec_agc_cfg1[] = { 0x6a, 0xff };
+	static u8 mt352_sec_agc_cfg2[] = { 0x6d, 0xff };
+	static u8 mt352_sec_agc_cfg3[] = { 0x70, 0x40 };
+	static u8 mt352_sec_agc_cfg4[] = { 0x7b, 0x03 };
+	static u8 mt352_sec_agc_cfg5[] = { 0x7d, 0x0f };
+
+	static u8 mt352_acq_ctl[] = { 0x53, 0x50 };
+	static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x06 };
+
+	mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config));
+	udelay(2000);
+	mt352_write(fe, mt352_reset, sizeof(mt352_reset));
+	mt352_write(fe, mt352_mclk_ratio, sizeof(mt352_mclk_ratio));
+
+	mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg));
+	mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg));
+
+	mt352_write(fe, mt352_sec_agc_cfg1, sizeof(mt352_sec_agc_cfg1));
+	mt352_write(fe, mt352_sec_agc_cfg2, sizeof(mt352_sec_agc_cfg2));
+	mt352_write(fe, mt352_sec_agc_cfg3, sizeof(mt352_sec_agc_cfg3));
+	mt352_write(fe, mt352_sec_agc_cfg4, sizeof(mt352_sec_agc_cfg4));
+	mt352_write(fe, mt352_sec_agc_cfg5, sizeof(mt352_sec_agc_cfg5));
+
+	mt352_write(fe, mt352_acq_ctl, sizeof(mt352_acq_ctl));
+	mt352_write(fe, mt352_input_freq_1, sizeof(mt352_input_freq_1));
+
+	return 0;
+}
+
+static int umt_mt352_frontend_attach(struct dvb_usb_device *d)
+{
+	struct mt352_config umt_config;
+
+	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);
+
+	return 0;
+}
+
+static int umt_tuner_attach (struct dvb_usb_device *d)
+{
+	d->pll_addr = 0x61;
+	d->pll_desc = &dvb_pll_tua6034;
+	return 0;
+}
+
+/* USB Driver stuff */
+static struct dvb_usb_properties umt_properties;
+
+static int umt_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	if (dvb_usb_device_init(intf,&umt_properties,THIS_MODULE) == 0)
+		return 0;
+	return -EINVAL;
+}
+
+/* do not change the order of the ID table */
+static struct usb_device_id umt_table [] = {
+/* 00 */	{ USB_DEVICE(USB_VID_HANFTEK,		USB_PID_HANFTEK_UMT_010_COLD) },
+/* 01 */	{ USB_DEVICE(USB_VID_HANFTEK,		USB_PID_HANFTEK_UMT_010_WARM) },
+			{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE (usb, umt_table);
+
+static struct dvb_usb_properties umt_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+	.usb_ctrl = CYPRESS_FX2,
+	.firmware = "dvb-usb-umt-010-02.fw",
+
+	.size_of_priv     = sizeof(struct dibusb_state),
+
+	.streaming_ctrl   = dibusb2_0_streaming_ctrl,
+	.power_ctrl       = dibusb_power_ctrl,
+	.frontend_attach  = umt_mt352_frontend_attach,
+	.tuner_attach     = umt_tuner_attach,
+
+	.i2c_algo         = &dibusb_i2c_algo,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
+	/* parameter for the MPEG2-data transfer */
+	.urb = {
+		.type = DVB_USB_BULK,
+		.count = 20,
+		.endpoint = 0x06,
+		.u = {
+			.bulk = {
+				.buffersize = 512,
+			}
+		}
+	},
+
+	.num_device_descs = 1,
+	.devices = {
+		{	"Hanftek UMT-010 DVB-T USB2.0",
+			{ &umt_table[0], NULL },
+			{ &umt_table[1], NULL },
+		},
+	}
+};
+
+static struct usb_driver umt_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "HanfTek UMT-010 USB2.0 DVB-T devices",
+	.probe		= umt_probe,
+	.disconnect = dvb_usb_device_exit,
+	.id_table	= umt_table,
+};
+
+/* module stuff */
+static int __init umt_module_init(void)
+{
+	int result;
+	if ((result = usb_register(&umt_driver))) {
+		err("usb_register failed. Error number %d",result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void __exit umt_module_exit(void)
+{
+	/* deregister this driver from the USB subsystem */
+	usb_deregister(&umt_driver);
+}
+
+module_init (umt_module_init);
+module_exit (umt_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("Driver for HanfTek UMT 010 USB2.0 DVB-T device");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/vp7045-fe.c b/drivers/media/dvb/dvb-usb/vp7045-fe.c
new file mode 100644
index 0000000..2746edf
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/vp7045-fe.c
@@ -0,0 +1,196 @@
+/* DVB frontend part of the Linux driver for TwinhanDTV Alpha/MagicBoxII USB2.0
+ * DVB-T receiver.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * Thanks to Twinhan who kindly provided hardware and information.
+ *
+ *	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 "vp7045.h"
+
+/* It is a Zarlink MT352 within a Samsung Tuner (DNOS404ZH102A) - 040929 - AAT
+ *
+ * Programming is hidden inside the firmware, so set_frontend is very easy.
+ * Even though there is a Firmware command that one can use to access the demod
+ * via its registers. This is used for status information.
+ */
+
+struct vp7045_fe_state {
+	struct dvb_frontend fe;
+	struct dvb_usb_device *d;
+};
+
+
+static int vp7045_fe_read_status(struct dvb_frontend* fe, fe_status_t *status)
+{
+	struct vp7045_fe_state *state = fe->demodulator_priv;
+	u8 s0 = vp7045_read_reg(state->d,0x00),
+	   s1 = vp7045_read_reg(state->d,0x01),
+	   s3 = vp7045_read_reg(state->d,0x03);
+
+	*status = 0;
+	if (s0 & (1 << 4))
+		*status |= FE_HAS_CARRIER;
+	if (s0 & (1 << 1))
+		*status |= FE_HAS_VITERBI;
+	if (s0 & (1 << 5))
+		*status |= FE_HAS_LOCK;
+	if (s1 & (1 << 1))
+		*status |= FE_HAS_SYNC;
+	if (s3 & (1 << 6))
+		*status |= FE_HAS_SIGNAL;
+
+	if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) !=
+			(FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC))
+		*status &= ~FE_HAS_LOCK;
+
+	return 0;
+}
+
+static int vp7045_fe_read_ber(struct dvb_frontend* fe, u32 *ber)
+{
+	struct vp7045_fe_state *state = fe->demodulator_priv;
+	*ber = (vp7045_read_reg(state->d, 0x0D) << 16) |
+	       (vp7045_read_reg(state->d, 0x0E) << 8) |
+	        vp7045_read_reg(state->d, 0x0F);
+	return 0;
+}
+
+static int vp7045_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)
+{
+	struct vp7045_fe_state *state = fe->demodulator_priv;
+	*unc = (vp7045_read_reg(state->d, 0x10) << 8) |
+		    vp7045_read_reg(state->d, 0x11);
+	return 0;
+}
+
+static int vp7045_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)
+{
+	struct vp7045_fe_state *state = fe->demodulator_priv;
+	u16 signal = (vp7045_read_reg(state->d, 0x14) << 8) |
+		vp7045_read_reg(state->d, 0x15);
+
+	*strength = ~signal;
+	return 0;
+}
+
+static int vp7045_fe_read_snr(struct dvb_frontend* fe, u16 *snr)
+{
+	struct vp7045_fe_state *state = fe->demodulator_priv;
+	u8 _snr = vp7045_read_reg(state->d, 0x09);
+	*snr = (_snr << 8) | _snr;
+	return 0;
+}
+
+static int vp7045_fe_init(struct dvb_frontend* fe)
+{
+	return 0;
+}
+
+static int vp7045_fe_sleep(struct dvb_frontend* fe)
+{
+	return 0;
+}
+
+static int vp7045_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+{
+	tune->min_delay_ms = 800;
+	return 0;
+}
+
+static int vp7045_fe_set_frontend(struct dvb_frontend* fe,
+				  struct dvb_frontend_parameters *fep)
+{
+	struct vp7045_fe_state *state = fe->demodulator_priv;
+	u8 buf[5];
+	u32 freq = fep->frequency / 1000;
+
+	buf[0] = (freq >> 16) & 0xff;
+	buf[1] = (freq >>  8) & 0xff;
+	buf[2] =  freq        & 0xff;
+	buf[3] = 0;
+
+	switch (fep->u.ofdm.bandwidth) {
+		case BANDWIDTH_8_MHZ: buf[4] = 8; break;
+		case BANDWIDTH_7_MHZ: buf[4] = 7; break;
+		case BANDWIDTH_6_MHZ: buf[4] = 6; break;
+		case BANDWIDTH_AUTO: return -EOPNOTSUPP;
+		default:
+			return -EINVAL;
+	}
+
+	vp7045_usb_op(state->d,LOCK_TUNER_COMMAND,buf,5,NULL,0,200);
+	return 0;
+}
+
+static int vp7045_fe_get_frontend(struct dvb_frontend* fe,
+				  struct dvb_frontend_parameters *fep)
+{
+	return 0;
+}
+
+static void vp7045_fe_release(struct dvb_frontend* fe)
+{
+	struct vp7045_fe_state *state = fe->demodulator_priv;
+	kfree(state);
+}
+
+static struct dvb_frontend_ops vp7045_fe_ops;
+
+struct dvb_frontend * vp7045_fe_attach(struct dvb_usb_device *d)
+{
+	struct vp7045_fe_state *s = kmalloc(sizeof(struct vp7045_fe_state), GFP_KERNEL);
+	if (s == NULL)
+		goto error;
+	memset(s,0,sizeof(struct vp7045_fe_state));
+
+	s->d = d;
+	s->fe.ops = &vp7045_fe_ops;
+	s->fe.demodulator_priv = s;
+
+	goto success;
+error:
+	return NULL;
+success:
+	return &s->fe;
+}
+
+
+static struct dvb_frontend_ops vp7045_fe_ops = {
+	.info = {
+		.name			= "Twinhan VP7045/46 USB DVB-T",
+		.type			= FE_OFDM,
+		.frequency_min		= 44250000,
+		.frequency_max		= 867250000,
+		.frequency_stepsize	= 1000,
+		.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 | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+				FE_CAN_TRANSMISSION_MODE_AUTO |
+				FE_CAN_GUARD_INTERVAL_AUTO |
+				FE_CAN_RECOVER |
+				FE_CAN_HIERARCHY_AUTO,
+	},
+
+	.release = vp7045_fe_release,
+
+	.init = vp7045_fe_init,
+	.sleep = vp7045_fe_sleep,
+
+	.set_frontend = vp7045_fe_set_frontend,
+	.get_frontend = vp7045_fe_get_frontend,
+	.get_tune_settings = vp7045_fe_get_tune_settings,
+
+	.read_status = vp7045_fe_read_status,
+	.read_ber = vp7045_fe_read_ber,
+	.read_signal_strength = vp7045_fe_read_signal_strength,
+	.read_snr = vp7045_fe_read_snr,
+	.read_ucblocks = vp7045_fe_read_unc_blocks,
+};
diff --git a/drivers/media/dvb/dvb-usb/vp7045.c b/drivers/media/dvb/dvb-usb/vp7045.c
new file mode 100644
index 0000000..02ecc9a
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/vp7045.c
@@ -0,0 +1,263 @@
+/* DVB USB compliant Linux driver for the
+ *  - TwinhanDTV Alpha/MagicBoxII USB2.0 DVB-T receiver
+ *  - DigitalNow TinyUSB2 DVB-t receiver
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * Thanks to Twinhan who kindly provided hardware and information.
+ *
+ *	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 "vp7045.h"
+
+/* debug */
+int dvb_usb_vp7045_debug;
+module_param_named(debug,dvb_usb_vp7045_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DVB_USB_DEBUG_STATUS);
+
+int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen, int msec)
+{
+	int ret = 0;
+	u8 inbuf[12] = { 0 }, outbuf[20] = { 0 };
+
+	outbuf[0] = cmd;
+
+	if (outlen > 19)
+		outlen = 19;
+
+	if (inlen > 11)
+		inlen = 11;
+
+	if (out != NULL && outlen > 0)
+		memcpy(&outbuf[1], out, outlen);
+
+	deb_xfer("out buffer: ");
+	debug_dump(outbuf,outlen+1,deb_xfer);
+
+	if ((ret = down_interruptible(&d->usb_sem)))
+		return ret;
+
+	if (usb_control_msg(d->udev,
+			usb_sndctrlpipe(d->udev,0),
+			TH_COMMAND_OUT, USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0,
+			outbuf, 20, 2*HZ) != 20) {
+		err("USB control message 'out' went wrong.");
+		ret = -EIO;
+		goto unlock;
+	}
+
+	msleep(msec);
+
+	if (usb_control_msg(d->udev,
+			usb_rcvctrlpipe(d->udev,0),
+			TH_COMMAND_IN, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
+			inbuf, 12, 2*HZ) != 12) {
+		err("USB control message 'in' went wrong.");
+		ret = -EIO;
+		goto unlock;
+	}
+
+	deb_xfer("in buffer: ");
+	debug_dump(inbuf,12,deb_xfer);
+
+	if (in != NULL && inlen > 0)
+		memcpy(in,&inbuf[1],inlen);
+
+unlock:
+	up(&d->usb_sem);
+
+	return ret;
+}
+
+u8 vp7045_read_reg(struct dvb_usb_device *d, u8 reg)
+{
+	u8 obuf[2] = { 0 },v;
+	obuf[1] = reg;
+
+	vp7045_usb_op(d,TUNER_REG_READ,obuf,2,&v,1,30);
+
+	return v;
+}
+
+static int vp7045_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+	u8 v = onoff;
+	return vp7045_usb_op(d,SET_TUNER_POWER,&v,1,NULL,0,150);
+}
+
+/* remote control stuff */
+
+/* The keymapping struct. Somehow this should be loaded to the driver, but
+ * currently it is hardcoded. */
+static struct dvb_usb_rc_key vp7045_rc_keys[] = {
+	/* insert the keys like this. to make the raw keys visible, enable
+	 * debug=0x04 when loading dvb-usb-vp7045. */
+
+	/* these keys are probably wrong. I don't have a working IR-receiver on my
+	 * vp7045, so I can't test it.  Patches are welcome. */
+	{ 0x00, 0x01, KEY_1 },
+	{ 0x00, 0x02, KEY_2 },
+};
+
+static int vp7045_rc_query(struct dvb_usb_device *d, u32 *key_buf, int *state)
+{
+	u8 key;
+	int i;
+	vp7045_usb_op(d,RC_VAL_READ,NULL,0,&key,1,20);
+
+	deb_rc("remote query key: %x %d\n",key,key);
+
+	if (key == 0x44) {
+		*state = REMOTE_NO_KEY_PRESSED;
+		return 0;
+	}
+
+	for (i = 0; i < sizeof(vp7045_rc_keys)/sizeof(struct dvb_usb_rc_key); i++)
+		if (vp7045_rc_keys[i].data == key) {
+			*state = REMOTE_KEY_PRESSED;
+			*key_buf = vp7045_rc_keys[i].event;
+			break;
+		}
+	return 0;
+}
+
+static int vp7045_read_eeprom(struct dvb_usb_device *d,u8 *buf, int len, int offset)
+{
+	int i = 0;
+	u8 v,br[2];
+	for (i=0; i < len; i++) {
+		v = offset + i;
+		vp7045_usb_op(d,GET_EE_VALUE,&v,1,br,2,5);
+		buf[i] = br[1];
+	}
+	deb_info("VP7045 EEPROM read (offs: %d, len: %d) : ",offset, i);
+	debug_dump(buf,i,deb_info);
+	return 0;
+}
+
+
+static int vp7045_read_mac_addr(struct dvb_usb_device *d,u8 mac[6])
+{
+	return vp7045_read_eeprom(d,mac, 6, MAC_0_ADDR);
+}
+
+static int vp7045_frontend_attach(struct dvb_usb_device *d)
+{
+	u8 buf[255] = { 0 };
+
+	vp7045_usb_op(d,VENDOR_STRING_READ,NULL,0,buf,20,0);
+	buf[10] = '\0';
+	deb_info("firmware says: %s ",buf);
+
+	vp7045_usb_op(d,PRODUCT_STRING_READ,NULL,0,buf,20,0);
+	buf[10] = '\0';
+	deb_info("%s ",buf);
+
+	vp7045_usb_op(d,FW_VERSION_READ,NULL,0,buf,20,0);
+	buf[10] = '\0';
+	deb_info("v%s\n",buf);
+
+/*	Dump the EEPROM */
+/*	vp7045_read_eeprom(d,buf, 255, FX2_ID_ADDR); */
+
+	d->fe = vp7045_fe_attach(d);
+
+	return 0;
+}
+
+static struct dvb_usb_properties vp7045_properties;
+
+static int vp7045_usb_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	return dvb_usb_device_init(intf,&vp7045_properties,THIS_MODULE);
+}
+
+static struct usb_device_id vp7045_usb_table [] = {
+	    { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7045_COLD) },
+	    { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TWINHAN_VP7045_WARM) },
+	    { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_DNTV_TINYUSB2_COLD) },
+	    { USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_DNTV_TINYUSB2_WARM) },
+	    { 0 },
+};
+MODULE_DEVICE_TABLE(usb, vp7045_usb_table);
+
+static struct dvb_usb_properties vp7045_properties = {
+	.caps = 0,
+
+	.usb_ctrl = CYPRESS_FX2,
+	.firmware = "dvb-usb-vp7045-01.fw",
+
+	.power_ctrl       = vp7045_power_ctrl,
+	.frontend_attach  = vp7045_frontend_attach,
+	.read_mac_address = vp7045_read_mac_addr,
+
+	.rc_interval      = 400,
+	.rc_key_map       = vp7045_rc_keys,
+	.rc_key_map_size  = ARRAY_SIZE(vp7045_rc_keys),
+	.rc_query         = vp7045_rc_query,
+
+	/* parameter for the MPEG2-data transfer */
+	.urb = {
+		.type = DVB_USB_BULK,
+		.count = 7,
+		.endpoint = 0x02,
+		.u = {
+			.bulk = {
+				.buffersize = 4096,
+			}
+		}
+	},
+
+	.num_device_descs = 2,
+	.devices = {
+		{ .name = "Twinhan USB2.0 DVB-T receiver (TwinhanDTV Alpha/MagicBox II)",
+		  .cold_ids = { &vp7045_usb_table[0], NULL },
+		  .warm_ids = { &vp7045_usb_table[1], NULL },
+		},
+		{ .name = "DigitalNow TinyUSB 2 DVB-t Receiver",
+		  .cold_ids = { &vp7045_usb_table[2], NULL },
+		  .warm_ids = { &vp7045_usb_table[3], NULL },
+		},
+		{ 0 },
+	}
+};
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver vp7045_usb_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "dvb-usb-vp7045",
+	.probe 		= vp7045_usb_probe,
+	.disconnect = dvb_usb_device_exit,
+	.id_table 	= vp7045_usb_table,
+};
+
+/* module stuff */
+static int __init vp7045_usb_module_init(void)
+{
+	int result;
+	if ((result = usb_register(&vp7045_usb_driver))) {
+		err("usb_register failed. (%d)",result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void __exit vp7045_usb_module_exit(void)
+{
+	/* deregister this driver from the USB subsystem */
+	usb_deregister(&vp7045_usb_driver);
+}
+
+module_init(vp7045_usb_module_init);
+module_exit(vp7045_usb_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_DESCRIPTION("Driver for Twinhan MagicBox/Alpha and DNTV tinyUSB2 DVB-T USB2.0");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/vp7045.h b/drivers/media/dvb/dvb-usb/vp7045.h
new file mode 100644
index 0000000..9ce21a2
--- /dev/null
+++ b/drivers/media/dvb/dvb-usb/vp7045.h
@@ -0,0 +1,78 @@
+/* Common header-file of the Linux driver for the TwinhanDTV Alpha/MagicBoxII
+ * USB2.0 DVB-T receiver.
+ *
+ * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@desy.de)
+ *
+ * Thanks to Twinhan who kindly provided hardware and information.
+ *
+ *	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_VP7045_H_
+#define _DVB_USB_VP7045_H_
+
+#define DVB_USB_LOG_PREFIX "vp7045"
+#include "dvb-usb.h"
+
+extern int dvb_usb_vp7045_debug;
+#define deb_info(args...) dprintk(dvb_usb_vp7045_debug,0x01,args)
+#define deb_xfer(args...) dprintk(dvb_usb_vp7045_debug,0x02,args)
+#define deb_rc(args...)   dprintk(dvb_usb_vp7045_debug,0x04,args)
+
+/* vp7045 commands */
+
+/* Twinhan Vendor requests */
+#define TH_COMMAND_IN                     0xC0
+#define TH_COMMAND_OUT                    0xC1
+
+/* command bytes */
+#define TUNER_REG_READ                    0x03
+#define TUNER_REG_WRITE                   0x04
+
+#define RC_VAL_READ                       0x05
+ #define RC_NO_KEY                        0x44
+
+#define SET_TUNER_POWER                   0x06
+#define CHECK_TUNER_POWER                 0x12
+ #define Tuner_Power_ON                   1
+ #define Tuner_Power_OFF                  0
+
+#define GET_USB_SPEED                     0x07
+ #define USB_SPEED_LOW                    0
+ #define USB_SPEED_FULL                   1
+ #define USB_SPEED_HIGH                   2
+
+#define LOCK_TUNER_COMMAND                0x09
+
+#define TUNER_SIGNAL_READ                 0x0A
+
+/* FX2 eeprom */
+#define SET_EE_VALUE                      0x10
+#define GET_EE_VALUE                      0x11
+ #define FX2_ID_ADDR                      0x00
+ #define VID_MSB_ADDR                     0x02
+ #define VID_LSB_ADDR                     0x01
+ #define PID_MSB_ADDR                     0x04
+ #define PID_LSB_ADDR                     0x03
+ #define MAC_0_ADDR                       0x07
+ #define MAC_1_ADDR                       0x08
+ #define MAC_2_ADDR                       0x09
+ #define MAC_3_ADDR                       0x0a
+ #define MAC_4_ADDR                       0x0b
+ #define MAC_5_ADDR                       0x0c
+
+#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 * vp7045_fe_attach(struct dvb_usb_device *d);
+extern int vp7045_usb_op(struct dvb_usb_device *d, u8 cmd, u8 *out, int outlen, u8 *in, int inlen,int msec);
+extern u8 vp7045_read_reg(struct dvb_usb_device *d, u8 reg);
+
+#endif
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 75fb556..b4fddf5 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -173,4 +173,12 @@
 	  An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
 	  to support this frontend.
 
+config DVB_BCM3510
+	tristate "Broadcom BCM3510"
+	depends on DVB_CORE
+	select FW_LOADER
+	help
+	  An ATSC 8VSB/16VSB and QAM64/256 tuner module. Say Y when you want to
+	  support this frontend.
+
 endmenu
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index 7f87848..91d6d35 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -28,3 +28,4 @@
 obj-$(CONFIG_DVB_NXT2002) += nxt2002.o
 obj-$(CONFIG_DVB_OR51211) += or51211.o
 obj-$(CONFIG_DVB_OR51132) += or51132.o
+obj-$(CONFIG_DVB_BCM3510) += bcm3510.o
diff --git a/drivers/media/dvb/frontends/bcm3510.c b/drivers/media/dvb/frontends/bcm3510.c
new file mode 100644
index 0000000..f5fdc5c
--- /dev/null
+++ b/drivers/media/dvb/frontends/bcm3510.c
@@ -0,0 +1,853 @@
+/*
+ * Support for the Broadcom BCM3510 ATSC demodulator (1st generation Air2PC)
+ *
+ *  Copyright (C) 2001-5, B2C2 inc.
+ *
+ *  GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.de>
+ *
+ *  This driver is "hard-coded" to be used with the 1st generation of
+ *  Technisat/B2C2's Air2PC ATSC PCI/USB cards/boxes. The pll-programming
+ *  (Panasonic CT10S) is located here, which is actually wrong. Unless there is
+ *  another device with a BCM3510, this is no problem.
+ *
+ *  The driver works also with QAM64 DVB-C, but had an unreasonable high
+ *  UNC. (Tested with the Air2PC ATSC 1st generation)
+ *
+ *  You'll need a firmware for this driver in order to get it running. It is
+ *  called "dvb-fe-bcm3510-01.fw".
+ *
+ * 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/moduleparam.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+
+#include "dvb_frontend.h"
+#include "bcm3510.h"
+#include "bcm3510_priv.h"
+
+struct bcm3510_state {
+
+	struct i2c_adapter* i2c;
+	struct dvb_frontend_ops ops;
+	const struct bcm3510_config* config;
+	struct dvb_frontend frontend;
+
+	/* demodulator private data */
+	struct semaphore hab_sem;
+	u8 firmware_loaded:1;
+
+	unsigned long next_status_check;
+	unsigned long status_check_interval;
+	struct bcm3510_hab_cmd_status1 status1;
+	struct bcm3510_hab_cmd_status2 status2;
+};
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info,2=i2c (|-able)).");
+
+#define dprintk(level,x...) if (level & debug) printk(x)
+#define dbufout(b,l,m) {\
+	    int i; \
+	    for (i = 0; i < l; i++) \
+	        m("%02x ",b[i]); \
+}
+#define deb_info(args...) dprintk(0x01,args)
+#define deb_i2c(args...)  dprintk(0x02,args)
+#define deb_hab(args...)  dprintk(0x04,args)
+
+/* transfer functions */
+static int bcm3510_writebytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 len)
+{
+	u8 b[256];
+	int err;
+	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = b, .len = len + 1 };
+
+	b[0] = reg;
+	memcpy(&b[1],buf,len);
+
+	deb_i2c("i2c wr %02x: ",reg);
+	dbufout(buf,len,deb_i2c);
+	deb_i2c("\n");
+
+	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
+
+		deb_info("%s: i2c write error (addr %02x, reg %02x, err == %i)\n",
+			__FUNCTION__, state->config->demod_address, reg,  err);
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+static int bcm3510_readbytes (struct bcm3510_state *state, u8 reg, u8 *buf, u8 len)
+{
+	struct i2c_msg msg[] = {
+		{ .addr = state->config->demod_address, .flags = 0,        .buf = &reg, .len = 1 },
+		{ .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = buf,  .len = len }
+	};
+	int err;
+
+	memset(buf,0,len);
+
+	if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
+		deb_info("%s: i2c read error (addr %02x, reg %02x, err == %i)\n",
+			__FUNCTION__, state->config->demod_address, reg,  err);
+		return -EREMOTEIO;
+	}
+	deb_i2c("i2c rd %02x: ",reg);
+	dbufout(buf,len,deb_i2c);
+	deb_i2c("\n");
+
+	return 0;
+}
+
+static int bcm3510_writeB(struct bcm3510_state *state, u8 reg, bcm3510_register_value v)
+{
+	return bcm3510_writebytes(state,reg,&v.raw,1);
+}
+
+static int bcm3510_readB(struct bcm3510_state *state, u8 reg, bcm3510_register_value *v)
+{
+	return bcm3510_readbytes(state,reg,&v->raw,1);
+}
+
+/* Host Access Buffer transfers */
+static int bcm3510_hab_get_response(struct bcm3510_state *st, u8 *buf, int len)
+{
+	bcm3510_register_value v;
+	int ret,i;
+
+	v.HABADR_a6.HABADR = 0;
+	if ((ret = bcm3510_writeB(st,0xa6,v)) < 0)
+		return ret;
+
+	for (i = 0; i < len; i++) {
+		if ((ret = bcm3510_readB(st,0xa7,&v)) < 0)
+			return ret;
+		buf[i] = v.HABDATA_a7;
+	}
+	return 0;
+}
+
+static int bcm3510_hab_send_request(struct bcm3510_state *st, u8 *buf, int len)
+{
+	bcm3510_register_value v,hab;
+	int ret,i;
+	unsigned long t;
+
+/* Check if any previous HAB request still needs to be serviced by the
+ * Aquisition Processor before sending new request */
+	if ((ret = bcm3510_readB(st,0xa8,&v)) < 0)
+		return ret;
+	if (v.HABSTAT_a8.HABR) {
+		deb_info("HAB is running already - clearing it.\n");
+		v.HABSTAT_a8.HABR = 0;
+		bcm3510_writeB(st,0xa8,v);
+//		return -EBUSY;
+	}
+
+/* Send the start HAB Address (automatically incremented after write of
+ * HABDATA) and write the HAB Data */
+	hab.HABADR_a6.HABADR = 0;
+	if ((ret = bcm3510_writeB(st,0xa6,hab)) < 0)
+		return ret;
+
+	for (i = 0; i < len; i++) {
+		hab.HABDATA_a7 = buf[i];
+		if ((ret = bcm3510_writeB(st,0xa7,hab)) < 0)
+			return ret;
+	}
+
+/* Set the HABR bit to indicate AP request in progress (LBHABR allows HABR to
+ * be written) */
+	v.raw = 0; v.HABSTAT_a8.HABR = 1; v.HABSTAT_a8.LDHABR = 1;
+	if ((ret = bcm3510_writeB(st,0xa8,v)) < 0)
+		return ret;
+
+/* Polling method: Wait until the AP finishes processing the HAB request */
+	t = jiffies + 1*HZ;
+	while (time_before(jiffies, t)) {
+		deb_info("waiting for HAB to complete\n");
+		msleep(10);
+		if ((ret = bcm3510_readB(st,0xa8,&v)) < 0)
+			return ret;
+
+		if (!v.HABSTAT_a8.HABR)
+			return 0;
+	}
+
+	deb_info("send_request execution timed out.\n");
+	return -ETIMEDOUT;
+}
+
+static int bcm3510_do_hab_cmd(struct bcm3510_state *st, u8 cmd, u8 msgid, u8 *obuf, u8 olen, u8 *ibuf, u8 ilen)
+{
+	u8 ob[olen+2],ib[ilen+2];
+	int ret = 0;
+
+	ob[0] = cmd;
+	ob[1] = msgid;
+	memcpy(&ob[2],obuf,olen);
+
+	deb_hab("hab snd: ");
+	dbufout(ob,olen+2,deb_hab);
+	deb_hab("\n");
+
+	if (down_interruptible(&st->hab_sem) < 0)
+		return -EAGAIN;
+
+	if ((ret = bcm3510_hab_send_request(st, ob, olen+2)) < 0 ||
+		(ret = bcm3510_hab_get_response(st, ib, ilen+2)) < 0)
+		goto error;
+
+	deb_hab("hab get: ");
+	dbufout(ib,ilen+2,deb_hab);
+	deb_hab("\n");
+
+	memcpy(ibuf,&ib[2],ilen);
+error:
+	up(&st->hab_sem);
+	return ret;
+}
+
+#if 0
+/* not needed, we use a semaphore to prevent HAB races */
+static int bcm3510_is_ap_ready(struct bcm3510_state *st)
+{
+	bcm3510_register_value ap,hab;
+	int ret;
+
+	if ((ret = bcm3510_readB(st,0xa8,&hab)) < 0 ||
+		(ret = bcm3510_readB(st,0xa2,&ap) < 0))
+		return ret;
+
+	if (ap.APSTAT1_a2.RESET || ap.APSTAT1_a2.IDLE || ap.APSTAT1_a2.STOP || hab.HABSTAT_a8.HABR) {
+		deb_info("AP is busy\n");
+		return -EBUSY;
+	}
+
+	return 0;
+}
+#endif
+
+static int bcm3510_bert_reset(struct bcm3510_state *st)
+{
+	bcm3510_register_value b;
+	int ret;
+
+	if ((ret < bcm3510_readB(st,0xfa,&b)) < 0)
+		return ret;
+
+	b.BERCTL_fa.RESYNC = 0; bcm3510_writeB(st,0xfa,b);
+	b.BERCTL_fa.RESYNC = 1; bcm3510_writeB(st,0xfa,b);
+	b.BERCTL_fa.RESYNC = 0; bcm3510_writeB(st,0xfa,b);
+	b.BERCTL_fa.CNTCTL = 1; b.BERCTL_fa.BITCNT = 1; bcm3510_writeB(st,0xfa,b);
+
+	/* clear residual bit counter TODO  */
+	return 0;
+}
+
+static int bcm3510_refresh_state(struct bcm3510_state *st)
+{
+	if (time_after(jiffies,st->next_status_check)) {
+		bcm3510_do_hab_cmd(st, CMD_STATUS, MSGID_STATUS1, NULL,0, (u8 *)&st->status1, sizeof(st->status1));
+		bcm3510_do_hab_cmd(st, CMD_STATUS, MSGID_STATUS2, NULL,0, (u8 *)&st->status2, sizeof(st->status2));
+		st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000;
+	}
+	return 0;
+}
+
+static int bcm3510_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct bcm3510_state* st = fe->demodulator_priv;
+	bcm3510_refresh_state(st);
+
+	*status = 0;
+	if (st->status1.STATUS1.RECEIVER_LOCK)
+		*status |= FE_HAS_LOCK | FE_HAS_SYNC;
+
+	if (st->status1.STATUS1.FEC_LOCK)
+		*status |= FE_HAS_VITERBI;
+
+	if (st->status1.STATUS1.OUT_PLL_LOCK)
+		*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
+
+	if (*status & FE_HAS_LOCK)
+		st->status_check_interval = 1500;
+	else /* more frequently checks if no lock has been achieved yet */
+		st->status_check_interval = 500;
+
+	deb_info("real_status: %02x\n",*status);
+	return 0;
+}
+
+static int bcm3510_read_ber(struct dvb_frontend* fe, u32* ber)
+{
+	struct bcm3510_state* st = fe->demodulator_priv;
+	bcm3510_refresh_state(st);
+
+	*ber = (st->status2.LDBER0 << 16) | (st->status2.LDBER1 << 8) | st->status2.LDBER2;
+	return 0;
+}
+
+static int bcm3510_read_unc(struct dvb_frontend* fe, u32* unc)
+{
+	struct bcm3510_state* st = fe->demodulator_priv;
+	bcm3510_refresh_state(st);
+	*unc = (st->status2.LDUERC0 << 8) | st->status2.LDUERC1;
+	return 0;
+}
+
+static int bcm3510_read_signal_strength(struct dvb_frontend* fe, u16* strength)
+{
+	struct bcm3510_state* st = fe->demodulator_priv;
+	s32 t;
+
+	bcm3510_refresh_state(st);
+	t = st->status2.SIGNAL;
+
+	if (t > 190)
+		t = 190;
+	if (t < 90)
+		t = 90;
+
+	t -= 90;
+	t = t * 0xff / 100;
+	/* normalize if necessary */
+	*strength = (t << 8) | t;
+	return 0;
+}
+
+static int bcm3510_read_snr(struct dvb_frontend* fe, u16* snr)
+{
+	struct bcm3510_state* st = fe->demodulator_priv;
+	bcm3510_refresh_state(st);
+
+	*snr = st->status1.SNR_EST0*1000 + ((st->status1.SNR_EST1*1000) >> 8);
+	return 0;
+}
+
+/* tuner frontend programming */
+static int bcm3510_tuner_cmd(struct bcm3510_state* st,u8 bc, u16 n, u8 a)
+{
+	struct bcm3510_hab_cmd_tune c;
+	memset(&c,0,sizeof(struct bcm3510_hab_cmd_tune));
+
+/* I2C Mode disabled,  set 16 control / Data pairs */
+	c.length = 0x10;
+	c.clock_width = 0;
+/* CS1, CS0, DATA, CLK bits control the tuner RF_AGC_SEL pin is set to
+ * logic high (as Configuration) */
+	c.misc = 0x10;
+/* Set duration of the initial state of TUNCTL = 3.34 micro Sec */
+	c.TUNCTL_state = 0x40;
+
+/* PRESCALER DEVIDE RATIO | BC1_2_3_4; (band switch), 1stosc REFERENCE COUNTER REF_S12 and REF_S11 */
+	c.ctl_dat[0].ctrl.size = BITS_8;
+	c.ctl_dat[0].data      = 0x80 | bc;
+
+/* Control DATA pin, 1stosc REFERENCE COUNTER REF_S10 to REF_S3 */
+	c.ctl_dat[1].ctrl.size = BITS_8;
+	c.ctl_dat[1].data      = 4;
+
+/* set CONTROL BIT 1 to 1, 1stosc REFERENCE COUNTER REF_S2 to REF_S1 */
+	c.ctl_dat[2].ctrl.size = BITS_3;
+	c.ctl_dat[2].data      = 0x20;
+
+/* control CS0 pin, pulse byte ? */
+	c.ctl_dat[3].ctrl.size = BITS_3;
+	c.ctl_dat[3].ctrl.clk_off = 1;
+	c.ctl_dat[3].ctrl.cs0  = 1;
+	c.ctl_dat[3].data      = 0x40;
+
+/* PGM_S18 to PGM_S11 */
+	c.ctl_dat[4].ctrl.size = BITS_8;
+	c.ctl_dat[4].data      = n >> 3;
+
+/* PGM_S10 to PGM_S8, SWL_S7 to SWL_S3 */
+	c.ctl_dat[5].ctrl.size = BITS_8;
+	c.ctl_dat[5].data      = ((n & 0x7) << 5) | (a >> 2);
+
+/* SWL_S2 and SWL_S1, set CONTROL BIT 2 to 0 */
+	c.ctl_dat[6].ctrl.size = BITS_3;
+	c.ctl_dat[6].data      = (a << 6) & 0xdf;
+
+/* control CS0 pin, pulse byte ? */
+	c.ctl_dat[7].ctrl.size = BITS_3;
+	c.ctl_dat[7].ctrl.clk_off = 1;
+	c.ctl_dat[7].ctrl.cs0  = 1;
+	c.ctl_dat[7].data      = 0x40;
+
+/* PRESCALER DEVIDE RATIO, 2ndosc REFERENCE COUNTER REF_S12 and REF_S11 */
+	c.ctl_dat[8].ctrl.size = BITS_8;
+	c.ctl_dat[8].data      = 0x80;
+
+/* 2ndosc REFERENCE COUNTER REF_S10 to REF_S3 */
+	c.ctl_dat[9].ctrl.size = BITS_8;
+	c.ctl_dat[9].data      = 0x10;
+
+/* set CONTROL BIT 1 to 1, 2ndosc REFERENCE COUNTER REF_S2 to REF_S1 */
+	c.ctl_dat[10].ctrl.size = BITS_3;
+	c.ctl_dat[10].data      = 0x20;
+
+/* pulse byte */
+	c.ctl_dat[11].ctrl.size = BITS_3;
+	c.ctl_dat[11].ctrl.clk_off = 1;
+	c.ctl_dat[11].ctrl.cs1  = 1;
+	c.ctl_dat[11].data      = 0x40;
+
+/* PGM_S18 to PGM_S11 */
+	c.ctl_dat[12].ctrl.size = BITS_8;
+	c.ctl_dat[12].data      = 0x2a;
+
+/* PGM_S10 to PGM_S8 and SWL_S7 to SWL_S3 */
+	c.ctl_dat[13].ctrl.size = BITS_8;
+	c.ctl_dat[13].data      = 0x8e;
+
+/* SWL_S2 and SWL_S1 and set CONTROL BIT 2 to 0 */
+	c.ctl_dat[14].ctrl.size = BITS_3;
+	c.ctl_dat[14].data      = 0;
+
+/* Pulse Byte */
+	c.ctl_dat[15].ctrl.size = BITS_3;
+	c.ctl_dat[15].ctrl.clk_off = 1;
+	c.ctl_dat[15].ctrl.cs1  = 1;
+	c.ctl_dat[15].data      = 0x40;
+
+	return bcm3510_do_hab_cmd(st,CMD_TUNE, MSGID_TUNE,(u8 *) &c,sizeof(c), NULL, 0);
+}
+
+static int bcm3510_set_freq(struct bcm3510_state* st,u32 freq)
+{
+	u8 bc,a;
+	u16 n;
+	s32 YIntercept,Tfvco1;
+
+	freq /= 1000;
+
+	deb_info("%dkHz:",freq);
+	/* set Band Switch */
+	if (freq <= 168000)
+		bc = 0x1c;
+	else if (freq <= 378000)
+		bc = 0x2c;
+	else
+		bc = 0x30;
+
+	if (freq >= 470000) {
+		freq -= 470001;
+		YIntercept = 18805;
+	} else if (freq >= 90000) {
+		freq -= 90001;
+		YIntercept = 15005;
+	} else if (freq >= 76000){
+		freq -= 76001;
+		YIntercept = 14865;
+	} else {
+		freq -= 54001;
+		YIntercept = 14645;
+	}
+
+	Tfvco1 = (((freq/6000)*60 + YIntercept)*4)/10;
+
+	n = Tfvco1 >> 6;
+	a = Tfvco1 & 0x3f;
+
+	deb_info(" BC1_2_3_4: %x, N: %x A: %x\n", bc, n, a);
+	if (n >= 16 && n <= 2047)
+		return bcm3510_tuner_cmd(st,bc,n,a);
+
+	return -EINVAL;
+}
+
+static int bcm3510_set_frontend(struct dvb_frontend* fe,
+					     struct dvb_frontend_parameters *p)
+{
+	struct bcm3510_state* st = fe->demodulator_priv;
+	struct bcm3510_hab_cmd_ext_acquire cmd;
+	struct bcm3510_hab_cmd_bert_control bert;
+	int ret;
+
+	memset(&cmd,0,sizeof(cmd));
+	switch (p->u.vsb.modulation) {
+		case QAM_256:
+			cmd.ACQUIRE0.MODE = 0x1;
+			cmd.ACQUIRE1.SYM_RATE = 0x1;
+			cmd.ACQUIRE1.IF_FREQ = 0x1;
+			break;
+		case QAM_64:
+			cmd.ACQUIRE0.MODE = 0x2;
+			cmd.ACQUIRE1.SYM_RATE = 0x2;
+			cmd.ACQUIRE1.IF_FREQ = 0x1;
+			break;
+/*		case QAM_256:
+			cmd.ACQUIRE0.MODE = 0x3;
+			break;
+		case QAM_128:
+			cmd.ACQUIRE0.MODE = 0x4;
+			break;
+		case QAM_64:
+			cmd.ACQUIRE0.MODE = 0x5;
+			break;
+		case QAM_32:
+			cmd.ACQUIRE0.MODE = 0x6;
+			break;
+		case QAM_16:
+			cmd.ACQUIRE0.MODE = 0x7;
+			break;*/
+		case VSB_8:
+			cmd.ACQUIRE0.MODE = 0x8;
+			cmd.ACQUIRE1.SYM_RATE = 0x0;
+			cmd.ACQUIRE1.IF_FREQ = 0x0;
+			break;
+		case VSB_16:
+			cmd.ACQUIRE0.MODE = 0x9;
+			cmd.ACQUIRE1.SYM_RATE = 0x0;
+			cmd.ACQUIRE1.IF_FREQ = 0x0;
+		default:
+			return -EINVAL;
+	};
+	cmd.ACQUIRE0.OFFSET = 0;
+	cmd.ACQUIRE0.NTSCSWEEP = 1;
+	cmd.ACQUIRE0.FA = 1;
+	cmd.ACQUIRE0.BW = 0;
+
+/*	if (enableOffset) {
+		cmd.IF_OFFSET0 = xx;
+		cmd.IF_OFFSET1 = xx;
+
+		cmd.SYM_OFFSET0 = xx;
+		cmd.SYM_OFFSET1 = xx;
+		if (enableNtscSweep) {
+			cmd.NTSC_OFFSET0;
+			cmd.NTSC_OFFSET1;
+		}
+	} */
+	bcm3510_do_hab_cmd(st, CMD_ACQUIRE, MSGID_EXT_TUNER_ACQUIRE, (u8 *) &cmd, sizeof(cmd), NULL, 0);
+
+/* doing it with different MSGIDs, data book and source differs */
+	bert.BE = 0;
+	bert.unused = 0;
+	bcm3510_do_hab_cmd(st, CMD_STATE_CONTROL, MSGID_BERT_CONTROL, (u8 *) &bert, sizeof(bert), NULL, 0);
+	bcm3510_do_hab_cmd(st, CMD_STATE_CONTROL, MSGID_BERT_SET, (u8 *) &bert, sizeof(bert), NULL, 0);
+
+	bcm3510_bert_reset(st);
+
+	if ((ret = bcm3510_set_freq(st,p->frequency)) < 0)
+		return ret;
+
+	memset(&st->status1,0,sizeof(st->status1));
+	memset(&st->status2,0,sizeof(st->status2));
+	st->status_check_interval = 500;
+
+/* Give the AP some time */
+	msleep(200);
+
+	return 0;
+}
+
+static int bcm3510_sleep(struct dvb_frontend* fe)
+{
+	return 0;
+}
+
+static int bcm3510_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *s)
+{
+	s->min_delay_ms = 1000;
+	s->step_size = 0;
+	s->max_drift = 0;
+	return 0;
+}
+
+static void bcm3510_release(struct dvb_frontend* fe)
+{
+	struct bcm3510_state* state = fe->demodulator_priv;
+	kfree(state);
+}
+
+/* firmware download:
+ * firmware file is build up like this:
+ * 16bit addr, 16bit length, 8byte of length
+ */
+#define BCM3510_DEFAULT_FIRMWARE "dvb-fe-bcm3510-01.fw"
+
+static int bcm3510_write_ram(struct bcm3510_state *st, u16 addr, u8 *b, u16 len)
+{
+	int ret = 0,i;
+	bcm3510_register_value vH, vL,vD;
+
+	vH.MADRH_a9 = addr >> 8;
+	vL.MADRL_aa = addr;
+	if ((ret = bcm3510_writeB(st,0xa9,vH)) < 0) return ret;
+	if ((ret = bcm3510_writeB(st,0xaa,vL)) < 0) return ret;
+
+	for (i = 0; i < len; i++) {
+		vD.MDATA_ab = b[i];
+		if ((ret = bcm3510_writeB(st,0xab,vD)) < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int bcm3510_download_firmware(struct dvb_frontend* fe)
+{
+	struct bcm3510_state* st = fe->demodulator_priv;
+	const struct firmware *fw;
+	u16 addr,len;
+	u8  *b;
+	int ret,i;
+
+	deb_info("requesting firmware\n");
+	if ((ret = st->config->request_firmware(fe, &fw, BCM3510_DEFAULT_FIRMWARE)) < 0) {
+		err("could not load firmware (%s): %d",BCM3510_DEFAULT_FIRMWARE,ret);
+		return ret;
+	}
+	deb_info("got firmware: %d\n",fw->size);
+
+	b = fw->data;
+	for (i = 0; i < fw->size;) {
+		addr = le16_to_cpu( *( (u16 *)&b[i] ) );
+		len  = le16_to_cpu( *( (u16 *)&b[i+2] ) );
+		deb_info("firmware chunk, addr: 0x%04x, len: 0x%04x, total length: 0x%04x\n",addr,len,fw->size);
+		if ((ret = bcm3510_write_ram(st,addr,&b[i+4],len)) < 0) {
+			err("firmware download failed: %d\n",ret);
+			return ret;
+		}
+		i += 4 + len;
+	}
+	release_firmware(fw);
+	deb_info("firmware download successfully completed\n");
+	return 0;
+}
+
+static int bcm3510_check_firmware_version(struct bcm3510_state *st)
+{
+	struct bcm3510_hab_cmd_get_version_info ver;
+	bcm3510_do_hab_cmd(st,CMD_GET_VERSION_INFO,MSGID_GET_VERSION_INFO,NULL,0,(u8*)&ver,sizeof(ver));
+
+	deb_info("Version information: 0x%02x 0x%02x 0x%02x 0x%02x\n",
+		ver.microcode_version, ver.script_version, ver.config_version, ver.demod_version);
+
+	if (ver.script_version == BCM3510_DEF_SCRIPT_VERSION &&
+		ver.config_version == BCM3510_DEF_CONFIG_VERSION &&
+		ver.demod_version  == BCM3510_DEF_DEMOD_VERSION)
+		return 0;
+
+	deb_info("version check failed\n");
+	return -ENODEV;
+}
+
+/* (un)resetting the AP */
+static int bcm3510_reset(struct bcm3510_state *st)
+{
+	int ret;
+	unsigned long  t;
+	bcm3510_register_value v;
+
+	bcm3510_readB(st,0xa0,&v); v.HCTL1_a0.RESET = 1;
+	if ((ret = bcm3510_writeB(st,0xa0,v)) < 0)
+		return ret;
+
+    t = jiffies + 3*HZ;
+	while (time_before(jiffies, t)) {
+		msleep(10);
+		if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
+			return ret;
+
+		if (v.APSTAT1_a2.RESET)
+			return 0;
+	}
+	deb_info("reset timed out\n");
+	return -ETIMEDOUT;
+}
+
+static int bcm3510_clear_reset(struct bcm3510_state *st)
+{
+	bcm3510_register_value v;
+	int ret;
+	unsigned long t;
+
+	v.raw = 0;
+	if ((ret = bcm3510_writeB(st,0xa0,v)) < 0)
+		return ret;
+
+    t = jiffies + 3*HZ;
+	while (time_before(jiffies, t)) {
+		msleep(10);
+		if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
+			return ret;
+
+		/* verify that reset is cleared */
+		if (!v.APSTAT1_a2.RESET)
+			return 0;
+	}
+	deb_info("reset clear timed out\n");
+	return -ETIMEDOUT;
+}
+
+static int bcm3510_init_cold(struct bcm3510_state *st)
+{
+	int ret;
+	bcm3510_register_value v;
+
+	/* read Acquisation Processor status register and check it is not in RUN mode */
+	if ((ret = bcm3510_readB(st,0xa2,&v)) < 0)
+		return ret;
+	if (v.APSTAT1_a2.RUN) {
+		deb_info("AP is already running - firmware already loaded.\n");
+		return 0;
+	}
+
+	deb_info("reset?\n");
+	if ((ret = bcm3510_reset(st)) < 0)
+		return ret;
+
+	deb_info("tristate?\n");
+	/* tri-state */
+	v.TSTCTL_2e.CTL = 0;
+	if ((ret = bcm3510_writeB(st,0x2e,v)) < 0)
+		return ret;
+
+	deb_info("firmware?\n");
+	if ((ret = bcm3510_download_firmware(&st->frontend)) < 0 ||
+		(ret = bcm3510_clear_reset(st)) < 0)
+		return ret;
+
+	/* anything left here to Let the acquisition processor begin execution at program counter 0000 ??? */
+
+	return 0;
+}
+
+static int bcm3510_init(struct dvb_frontend* fe)
+{
+	struct bcm3510_state* st = fe->demodulator_priv;
+	bcm3510_register_value j;
+	struct bcm3510_hab_cmd_set_agc c;
+	int ret;
+
+	if ((ret = bcm3510_readB(st,0xca,&j)) < 0)
+		return ret;
+
+	deb_info("JDEC: %02x\n",j.raw);
+
+	switch (j.JDEC_ca.JDEC) {
+		case JDEC_WAIT_AT_RAM:
+			deb_info("attempting to download firmware\n");
+			if ((ret = bcm3510_init_cold(st)) < 0)
+				return ret;
+		case JDEC_EEPROM_LOAD_WAIT: /* fall-through is wanted */
+			deb_info("firmware is loaded\n");
+			bcm3510_check_firmware_version(st);
+			break;
+		default:
+			return -ENODEV;
+	}
+
+	memset(&c,0,1);
+	c.SEL = 1;
+	bcm3510_do_hab_cmd(st,CMD_AUTO_PARAM,MSGID_SET_RF_AGC_SEL,(u8 *)&c,sizeof(c),NULL,0);
+
+	return 0;
+}
+
+
+static struct dvb_frontend_ops bcm3510_ops;
+
+struct dvb_frontend* bcm3510_attach(const struct bcm3510_config *config,
+				   struct i2c_adapter *i2c)
+{
+	struct bcm3510_state* state = NULL;
+	int ret;
+	bcm3510_register_value v;
+
+	/* allocate memory for the internal state */
+	state = kmalloc(sizeof(struct bcm3510_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+	memset(state,0,sizeof(struct bcm3510_state));
+
+	/* setup the state */
+
+	state->config = config;
+	state->i2c = i2c;
+	memcpy(&state->ops, &bcm3510_ops, sizeof(struct dvb_frontend_ops));
+
+	/* create dvb_frontend */
+	state->frontend.ops = &state->ops;
+	state->frontend.demodulator_priv = state;
+
+	sema_init(&state->hab_sem, 1);
+
+	if ((ret = bcm3510_readB(state,0xe0,&v)) < 0)
+		goto error;
+
+	deb_info("Revision: 0x%1x, Layer: 0x%1x.\n",v.REVID_e0.REV,v.REVID_e0.LAYER);
+
+	if ((v.REVID_e0.REV != 0x1 && v.REVID_e0.LAYER != 0xb) && /* cold */
+		(v.REVID_e0.REV != 0x8 && v.REVID_e0.LAYER != 0x0))   /* warm */
+		goto error;
+
+	info("Revision: 0x%1x, Layer: 0x%1x.",v.REVID_e0.REV,v.REVID_e0.LAYER);
+
+	bcm3510_reset(state);
+
+	return &state->frontend;
+
+error:
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(bcm3510_attach);
+
+static struct dvb_frontend_ops bcm3510_ops = {
+
+	.info = {
+		.name = "Broadcom BCM3510 VSB/QAM frontend",
+		.type = FE_ATSC,
+		.frequency_min =  54000000,
+		.frequency_max = 803000000,
+                /* stepsize is just a guess */
+		.frequency_stepsize = 0,
+		.caps =
+			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_8VSB | FE_CAN_16VSB |
+			FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256
+	},
+
+	.release = bcm3510_release,
+
+	.init = bcm3510_init,
+	.sleep = bcm3510_sleep,
+
+	.set_frontend = bcm3510_set_frontend,
+	.get_tune_settings = bcm3510_get_tune_settings,
+
+	.read_status = bcm3510_read_status,
+	.read_ber = bcm3510_read_ber,
+	.read_signal_strength = bcm3510_read_signal_strength,
+	.read_snr = bcm3510_read_snr,
+	.read_ucblocks = bcm3510_read_unc,
+};
+
+MODULE_DESCRIPTION("Broadcom BCM3510 ATSC (8VSB/16VSB & ITU J83 AnnexB FEC QAM64/256) demodulator driver");
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/bcm3510.h b/drivers/media/dvb/frontends/bcm3510.h
new file mode 100644
index 0000000..80f5d09
--- /dev/null
+++ b/drivers/media/dvb/frontends/bcm3510.h
@@ -0,0 +1,40 @@
+/*
+ * Support for the Broadcom BCM3510 ATSC demodulator (1st generation Air2PC)
+ *
+ *  Copyright (C) 2001-5, B2C2 inc.
+ *
+ *  GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.de>
+ *
+ * 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 BCM3510_H
+#define BCM3510_H
+
+#include <linux/dvb/frontend.h>
+#include <linux/firmware.h>
+
+struct bcm3510_config
+{
+	/* the demodulator's i2c address */
+	u8 demod_address;
+
+	/* request firmware for device */
+	int (*request_firmware)(struct dvb_frontend* fe, const struct firmware **fw, char* name);
+};
+
+extern struct dvb_frontend* bcm3510_attach(const struct bcm3510_config* config,
+					   struct i2c_adapter* i2c);
+
+#endif
diff --git a/drivers/media/dvb/frontends/bcm3510_priv.h b/drivers/media/dvb/frontends/bcm3510_priv.h
new file mode 100644
index 0000000..3bb1bc2
--- /dev/null
+++ b/drivers/media/dvb/frontends/bcm3510_priv.h
@@ -0,0 +1,460 @@
+/*
+ * Support for the Broadcom BCM3510 ATSC demodulator (1st generation Air2PC)
+ *
+ *  Copyright (C) 2001-5, B2C2 inc.
+ *
+ *  GPL/Linux driver written by Patrick Boettcher <patrick.boettcher@desy.de>
+ *
+ * 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 __BCM3510_PRIV_H__
+#define __BCM3510_PRIV_H__
+
+#define PACKED __attribute__((packed))
+
+#undef err
+#define err(format, arg...)  printk(KERN_ERR     "bcm3510: " format "\n" , ## arg)
+#undef info
+#define info(format, arg...) printk(KERN_INFO    "bcm3510: " format "\n" , ## arg)
+#undef warn
+#define warn(format, arg...) printk(KERN_WARNING "bcm3510: " format "\n" , ## arg)
+
+
+#define PANASONIC_FIRST_IF_BASE_IN_KHz  1407500
+#define BCM3510_SYMBOL_RATE             5381000
+
+typedef union {
+	u8 raw;
+
+	struct {
+		u8 CTL   :8;
+	} TSTCTL_2e;
+
+	u8 LDCERC_4e;
+	u8 LDUERC_4f;
+	u8 LD_BER0_65;
+	u8 LD_BER1_66;
+	u8 LD_BER2_67;
+	u8 LD_BER3_68;
+
+	struct {
+		u8 RESET :1;
+		u8 IDLE  :1;
+		u8 STOP  :1;
+		u8 HIRQ0 :1;
+		u8 HIRQ1 :1;
+		u8 na0   :1;
+		u8 HABAV :1;
+		u8 na1   :1;
+	} HCTL1_a0;
+
+	struct {
+		u8 na0    :1;
+		u8 IDLMSK :1;
+		u8 STMSK  :1;
+		u8 I0MSK  :1;
+		u8 I1MSK  :1;
+		u8 na1    :1;
+		u8 HABMSK :1;
+		u8 na2    :1;
+	} HCTLMSK_a1;
+
+	struct {
+		u8 RESET  :1;
+		u8 IDLE   :1;
+		u8 STOP   :1;
+		u8 RUN    :1;
+		u8 HABAV  :1;
+		u8 MEMAV  :1;
+		u8 ALDONE :1;
+		u8 REIRQ  :1;
+	} APSTAT1_a2;
+
+	struct {
+		u8 RSTMSK :1;
+		u8 IMSK   :1;
+		u8 SMSK   :1;
+		u8 RMSK   :1;
+		u8 HABMSK :1;
+		u8 MAVMSK :1;
+		u8 ALDMSK :1;
+		u8 REMSK  :1;
+	} APMSK1_a3;
+
+	u8 APSTAT2_a4;
+	u8 APMSK2_a5;
+
+	struct {
+		u8 HABADR :7;
+		u8 na     :1;
+	} HABADR_a6;
+
+	u8 HABDATA_a7;
+
+	struct {
+		u8 HABR   :1;
+		u8 LDHABR :1;
+		u8 APMSK  :1;
+		u8 HMSK   :1;
+		u8 LDMSK  :1;
+		u8 na     :3;
+	} HABSTAT_a8;
+
+	u8 MADRH_a9;
+	u8 MADRL_aa;
+	u8 MDATA_ab;
+
+	struct {
+#define JDEC_WAIT_AT_RAM      0x7
+#define JDEC_EEPROM_LOAD_WAIT 0x4
+		u8 JDEC   :3;
+		u8 na     :5;
+	} JDEC_ca;
+
+	struct {
+		u8 REV   :4;
+		u8 LAYER :4;
+	} REVID_e0;
+
+	struct {
+		u8 unk0   :1;
+		u8 CNTCTL :1;
+		u8 BITCNT :1;
+		u8 unk1   :1;
+		u8 RESYNC :1;
+		u8 unk2   :3;
+	} BERCTL_fa;
+
+	struct {
+		u8 CSEL0  :1;
+		u8 CLKED0 :1;
+		u8 CSEL1  :1;
+		u8 CLKED1 :1;
+		u8 CLKLEV :1;
+		u8 SPIVAR :1;
+		u8 na     :2;
+	} TUNSET_fc;
+
+	struct {
+		u8 CLK    :1;
+		u8 DATA   :1;
+		u8 CS0    :1;
+		u8 CS1    :1;
+		u8 AGCSEL :1;
+		u8 na0    :1;
+		u8 TUNSEL :1;
+		u8 na1    :1;
+	} TUNCTL_fd;
+
+	u8 TUNSEL0_fe;
+	u8 TUNSEL1_ff;
+
+} bcm3510_register_value;
+
+/* HAB commands */
+
+/* version */
+#define CMD_GET_VERSION_INFO   0x3D
+#define MSGID_GET_VERSION_INFO 0x15
+struct bcm3510_hab_cmd_get_version_info {
+	u8 microcode_version;
+	u8 script_version;
+	u8 config_version;
+	u8 demod_version;
+} PACKED;
+
+#define BCM3510_DEF_MICROCODE_VERSION 0x0E
+#define BCM3510_DEF_SCRIPT_VERSION    0x06
+#define BCM3510_DEF_CONFIG_VERSION    0x01
+#define BCM3510_DEF_DEMOD_VERSION     0xB1
+
+/* acquire */
+#define CMD_ACQUIRE            0x38
+
+#define MSGID_EXT_TUNER_ACQUIRE 0x0A
+struct bcm3510_hab_cmd_ext_acquire {
+	struct {
+		u8 MODE      :4;
+		u8 BW        :1;
+		u8 FA        :1;
+		u8 NTSCSWEEP :1;
+		u8 OFFSET    :1;
+	} PACKED ACQUIRE0; /* control_byte */
+
+	struct {
+		u8 IF_FREQ  :3;
+		u8 zero0    :1;
+		u8 SYM_RATE :3;
+		u8 zero1    :1;
+	} PACKED ACQUIRE1; /* sym_if */
+
+	u8 IF_OFFSET0;   /* IF_Offset_10hz */
+	u8 IF_OFFSET1;
+	u8 SYM_OFFSET0;  /* SymbolRateOffset */
+	u8 SYM_OFFSET1;
+	u8 NTSC_OFFSET0; /* NTSC_Offset_10hz */
+	u8 NTSC_OFFSET1;
+} PACKED;
+
+#define MSGID_INT_TUNER_ACQUIRE 0x0B
+struct bcm3510_hab_cmd_int_acquire {
+	struct {
+		u8 MODE      :4;
+		u8 BW        :1;
+		u8 FA        :1;
+		u8 NTSCSWEEP :1;
+		u8 OFFSET    :1;
+	} PACKED ACQUIRE0; /* control_byte */
+
+	struct {
+		u8 IF_FREQ  :3;
+		u8 zero0    :1;
+		u8 SYM_RATE :3;
+		u8 zero1    :1;
+	} PACKED ACQUIRE1; /* sym_if */
+
+	u8 TUNER_FREQ0;
+	u8 TUNER_FREQ1;
+	u8 TUNER_FREQ2;
+	u8 TUNER_FREQ3;
+	u8 IF_OFFSET0;   /* IF_Offset_10hz */
+	u8 IF_OFFSET1;
+	u8 SYM_OFFSET0;  /* SymbolRateOffset */
+	u8 SYM_OFFSET1;
+	u8 NTSC_OFFSET0; /* NTSC_Offset_10hz */
+	u8 NTSC_OFFSET1;
+} PACKED;
+
+/* modes */
+#define BCM3510_QAM16           =   0x01
+#define BCM3510_QAM32           =   0x02
+#define BCM3510_QAM64           =   0x03
+#define BCM3510_QAM128          =   0x04
+#define BCM3510_QAM256          =   0x05
+#define BCM3510_8VSB            =   0x0B
+#define BCM3510_16VSB           =   0x0D
+
+/* IF_FREQS */
+#define BCM3510_IF_TERRESTRIAL 0x0
+#define BCM3510_IF_CABLE       0x1
+#define BCM3510_IF_USE_CMD     0x7
+
+/* SYM_RATE */
+#define BCM3510_SR_8VSB        0x0 /* 5381119 s/sec */
+#define BCM3510_SR_256QAM      0x1 /* 5360537 s/sec */
+#define BCM3510_SR_16QAM       0x2 /* 5056971 s/sec */
+#define BCM3510_SR_MISC        0x3 /* 5000000 s/sec */
+#define BCM3510_SR_USE_CMD     0x7
+
+/* special symbol rate */
+#define CMD_SET_VALUE_NOT_LISTED  0x2d
+#define MSGID_SET_SYMBOL_RATE_NOT_LISTED 0x0c
+struct bcm3510_hab_cmd_set_sr_not_listed {
+	u8 HOST_SYM_RATE0;
+	u8 HOST_SYM_RATE1;
+	u8 HOST_SYM_RATE2;
+	u8 HOST_SYM_RATE3;
+} PACKED;
+
+/* special IF */
+#define MSGID_SET_IF_FREQ_NOT_LISTED 0x0d
+struct bcm3510_hab_cmd_set_if_freq_not_listed {
+	u8 HOST_IF_FREQ0;
+	u8 HOST_IF_FREQ1;
+	u8 HOST_IF_FREQ2;
+	u8 HOST_IF_FREQ3;
+} PACKED;
+
+/* auto reacquire */
+#define CMD_AUTO_PARAM       0x2a
+#define MSGID_AUTO_REACQUIRE 0x0e
+struct bcm3510_hab_cmd_auto_reacquire {
+	u8 ACQ    :1; /* on/off*/
+	u8 unused :7;
+} PACKED;
+
+#define MSGID_SET_RF_AGC_SEL 0x12
+struct bcm3510_hab_cmd_set_agc {
+	u8 LVL    :1;
+	u8 unused :6;
+	u8 SEL    :1;
+} PACKED;
+
+#define MSGID_SET_AUTO_INVERSION 0x14
+struct bcm3510_hab_cmd_auto_inversion {
+	u8 AI     :1;
+	u8 unused :7;
+} PACKED;
+
+
+/* bert control */
+#define CMD_STATE_CONTROL  0x12
+#define MSGID_BERT_CONTROL 0x0e
+#define MSGID_BERT_SET     0xfa
+struct bcm3510_hab_cmd_bert_control {
+	u8 BE     :1;
+	u8 unused :7;
+} PACKED;
+
+#define MSGID_TRI_STATE 0x2e
+struct bcm3510_hab_cmd_tri_state {
+	u8 RE :1; /* a/d ram port pins */
+	u8 PE :1; /* baud clock pin */
+	u8 AC :1; /* a/d clock pin */
+	u8 BE :1; /* baud clock pin */
+	u8 unused :4;
+} PACKED;
+
+
+/* tune */
+#define CMD_TUNE   0x38
+#define MSGID_TUNE 0x16
+struct bcm3510_hab_cmd_tune_ctrl_data_pair {
+	struct {
+#define BITS_8 0x07
+#define BITS_7 0x06
+#define BITS_6 0x05
+#define BITS_5 0x04
+#define BITS_4 0x03
+#define BITS_3 0x02
+#define BITS_2 0x01
+#define BITS_1 0x00
+		u8 size    :3;
+		u8 unk     :2;
+		u8 clk_off :1;
+		u8 cs0     :1;
+		u8 cs1     :1;
+
+	} PACKED ctrl;
+
+	u8 data;
+} PACKED;
+
+struct bcm3510_hab_cmd_tune {
+	u8 length;
+	u8 clock_width;
+	u8 misc;
+	u8 TUNCTL_state;
+
+	struct bcm3510_hab_cmd_tune_ctrl_data_pair ctl_dat[16];
+} PACKED;
+
+#define CMD_STATUS    0x38
+#define MSGID_STATUS1 0x08
+struct bcm3510_hab_cmd_status1 {
+	struct {
+		u8 EQ_MODE       :4;
+		u8 reserved      :2;
+		u8 QRE           :1; /* if QSE and the spectrum is inversed */
+		u8 QSE           :1; /* automatic spectral inversion */
+	} PACKED STATUS0;
+
+	struct {
+		u8 RECEIVER_LOCK :1;
+		u8 FEC_LOCK      :1;
+		u8 OUT_PLL_LOCK  :1;
+		u8 reserved      :5;
+	} PACKED STATUS1;
+
+	struct {
+		u8 reserved      :2;
+		u8 BW            :1;
+		u8 NTE           :1; /* NTSC filter sweep enabled */
+		u8 AQI           :1; /* currently acquiring */
+		u8 FA            :1; /* fast acquisition */
+		u8 ARI           :1; /* auto reacquire */
+		u8 TI            :1; /* programming the tuner */
+	} PACKED STATUS2;
+	u8 STATUS3;
+	u8 SNR_EST0;
+	u8 SNR_EST1;
+	u8 TUNER_FREQ0;
+	u8 TUNER_FREQ1;
+	u8 TUNER_FREQ2;
+	u8 TUNER_FREQ3;
+	u8 SYM_RATE0;
+	u8 SYM_RATE1;
+	u8 SYM_RATE2;
+	u8 SYM_RATE3;
+	u8 SYM_OFFSET0;
+	u8 SYM_OFFSET1;
+	u8 SYM_ERROR0;
+	u8 SYM_ERROR1;
+	u8 IF_FREQ0;
+	u8 IF_FREQ1;
+	u8 IF_FREQ2;
+	u8 IF_FREQ3;
+	u8 IF_OFFSET0;
+	u8 IF_OFFSET1;
+	u8 IF_ERROR0;
+	u8 IF_ERROR1;
+	u8 NTSC_FILTER0;
+	u8 NTSC_FILTER1;
+	u8 NTSC_FILTER2;
+	u8 NTSC_FILTER3;
+	u8 NTSC_OFFSET0;
+	u8 NTSC_OFFSET1;
+	u8 NTSC_ERROR0;
+	u8 NTSC_ERROR1;
+	u8 INT_AGC_LEVEL0;
+	u8 INT_AGC_LEVEL1;
+	u8 EXT_AGC_LEVEL0;
+	u8 EXT_AGC_LEVEL1;
+} PACKED;
+
+#define MSGID_STATUS2 0x14
+struct bcm3510_hab_cmd_status2 {
+	struct {
+		u8 EQ_MODE  :4;
+		u8 reserved :2;
+		u8 QRE      :1;
+		u8 QSR      :1;
+	} PACKED STATUS0;
+	struct {
+		u8 RL       :1;
+		u8 FL       :1;
+		u8 OL       :1;
+		u8 reserved :5;
+	} PACKED STATUS1;
+	u8 SYMBOL_RATE0;
+	u8 SYMBOL_RATE1;
+	u8 SYMBOL_RATE2;
+	u8 SYMBOL_RATE3;
+	u8 LDCERC0;
+	u8 LDCERC1;
+	u8 LDCERC2;
+	u8 LDCERC3;
+	u8 LDUERC0;
+	u8 LDUERC1;
+	u8 LDUERC2;
+	u8 LDUERC3;
+	u8 LDBER0;
+	u8 LDBER1;
+	u8 LDBER2;
+	u8 LDBER3;
+	struct {
+		u8 MODE_TYPE :4; /* acquire mode 0 */
+		u8 reservd   :4;
+	} MODE_TYPE;
+	u8 SNR_EST0;
+	u8 SNR_EST1;
+	u8 SIGNAL;
+} PACKED;
+
+#define CMD_SET_RF_BW_NOT_LISTED   0x3f
+#define MSGID_SET_RF_BW_NOT_LISTED 0x11
+/* TODO */
+
+#endif
diff --git a/drivers/media/dvb/frontends/dib3000-common.c b/drivers/media/dvb/frontends/dib3000-common.c
index 47ab02e..1a4f1f7 100644
--- a/drivers/media/dvb/frontends/dib3000-common.c
+++ b/drivers/media/dvb/frontends/dib3000-common.c
@@ -73,7 +73,7 @@
 	};
 
 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de");
-MODULE_DESCRIPTION("Common functions for the dib3000mb/dib3000mc dvb-frontend drivers");
+MODULE_DESCRIPTION("Common functions for the dib3000mb/dib3000mc dvb frontend drivers");
 MODULE_LICENSE("GPL");
 
 EXPORT_SYMBOL(dib3000_seq);
diff --git a/drivers/media/dvb/frontends/dib3000.h b/drivers/media/dvb/frontends/dib3000.h
index 80687c1..2d5475b 100644
--- a/drivers/media/dvb/frontends/dib3000.h
+++ b/drivers/media/dvb/frontends/dib3000.h
@@ -32,9 +32,8 @@
 	u8 demod_address;
 
 	/* PLL maintenance and the i2c address of the PLL */
-	u8 (*pll_addr)(struct dvb_frontend *fe);
-	int (*pll_init)(struct dvb_frontend *fe, u8 pll_buf[5]);
-	int (*pll_set)(struct dvb_frontend *fe, struct dvb_frontend_parameters* params, u8 pll_buf[5]);
+	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 6f52d64..cd434b7 100644
--- a/drivers/media/dvb/frontends/dib3000mb.c
+++ b/drivers/media/dvb/frontends/dib3000mb.c
@@ -48,8 +48,6 @@
 #define deb_setf(args...) dprintk(0x04,args)
 #define deb_getf(args...) dprintk(0x08,args)
 
-static int dib3000mb_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr);
-
 static int dib3000mb_get_frontend(struct dvb_frontend* fe,
 				  struct dvb_frontend_parameters *fep);
 
@@ -61,10 +59,8 @@
 	fe_code_rate_t fe_cr = FEC_NONE;
 	int search_state, seq;
 
-	if (tuner && state->config.pll_addr && state->config.pll_set) {
-		dib3000mb_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe));
-		state->config.pll_set(fe, fep, NULL);
-		dib3000mb_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe));
+	if (tuner && state->config.pll_set) {
+		state->config.pll_set(fe, fep);
 
 		deb_setf("bandwidth: ");
 		switch (ofdm->bandwidth) {
@@ -389,11 +385,8 @@
 
 	wr(DIB3000MB_REG_DATA_IN_DIVERSITY, DIB3000MB_DATA_DIVERSITY_IN_OFF);
 
-	if (state->config.pll_init) {
-		dib3000mb_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe));
-		state->config.pll_init(fe,NULL);
-		dib3000mb_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe));
-	}
+	if (state->config.pll_init)
+		state->config.pll_init(fe);
 
 	return 0;
 }
@@ -623,7 +616,7 @@
 {
 	struct dib3000_state* state = fe->demodulator_priv;
 
-	*unc = rd(DIB3000MB_REG_UNC);
+	*unc = rd(DIB3000MB_REG_PACKET_ERROR_RATE);
 	return 0;
 }
 
@@ -638,9 +631,6 @@
 static int dib3000mb_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
 {
 	tune->min_delay_ms = 800;
-	tune->step_size = 166667;
-	tune->max_drift = 166667 * 2;
-
 	return 0;
 }
 
diff --git a/drivers/media/dvb/frontends/dib3000mb_priv.h b/drivers/media/dvb/frontends/dib3000mb_priv.h
index 57e61aa..999b190 100644
--- a/drivers/media/dvb/frontends/dib3000mb_priv.h
+++ b/drivers/media/dvb/frontends/dib3000mb_priv.h
@@ -294,7 +294,7 @@
 
 static u16 dib3000mb_filter_coeffs[] = {
 	 226,  160,   29,
- 	 979,  998,   19,
+	 979,  998,   19,
 	  22, 1019, 1006,
 	1022,   12,    6,
 	1017, 1017,    3,
diff --git a/drivers/media/dvb/frontends/dib3000mc.c b/drivers/media/dvb/frontends/dib3000mc.c
index 888f10a..cd33705 100644
--- a/drivers/media/dvb/frontends/dib3000mc.c
+++ b/drivers/media/dvb/frontends/dib3000mc.c
@@ -48,8 +48,6 @@
 #define deb_getf(args...) dprintk(0x08,args)
 #define deb_stat(args...) dprintk(0x10,args)
 
-static int dib3000mc_tuner_pass_ctrl(struct dvb_frontend *fe, int onoff, u8 pll_addr);
-
 static int dib3000mc_set_impulse_noise(struct dib3000_state * state, int mode,
 	fe_transmit_mode_t transmission_mode, fe_bandwidth_t bandwidth)
 {
@@ -463,10 +461,8 @@
 	int search_state,auto_val;
 	u16 val;
 
-	if (tuner && state->config.pll_addr && state->config.pll_set) { /* initial call from dvb */
-		dib3000mc_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe));
-		state->config.pll_set(fe,fep,NULL);
-		dib3000mc_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe));
+	if (tuner && state->config.pll_set) { /* initial call from dvb */
+		state->config.pll_set(fe,fep);
 
 		state->last_tuned_freq = fep->frequency;
 	//	if (!scanboost) {
@@ -554,19 +550,15 @@
 			dib3000mc_set_adp_cfg(state,ofdm->constellation);
 		wr_foreach(dib3000mc_reg_offset,
 				dib3000mc_offset[(ofdm->transmission_mode == TRANSMISSION_MODE_8K)+1]);
-
-
 	}
 	return 0;
 }
 
 static int dib3000mc_fe_init(struct dvb_frontend* fe, int mobile_mode)
 {
-	struct dib3000_state *state;
-
+	struct dib3000_state *state = fe->demodulator_priv;
 	deb_info("init start\n");
 
-	state = fe->demodulator_priv;
 	state->timing_offset = 0;
 	state->timing_offset_comp_done = 0;
 
@@ -649,11 +641,9 @@
 
 	set_or(DIB3000MC_REG_CLK_CFG_7,DIB3000MC_CLK_CFG_7_DIV_IN_OFF);
 
-/*	if (state->config->pll_init) {
-		dib3000mc_tuner_pass_ctrl(fe,1,state->config.pll_addr(fe));
-		state->config->pll_init(fe,NULL);
-		dib3000mc_tuner_pass_ctrl(fe,0,state->config.pll_addr(fe));
-	}*/
+	if (state->config.pll_init)
+		state->config.pll_init(fe);
+
 	deb_info("init end\n");
 	return 0;
 }
@@ -688,7 +678,7 @@
 {
 	struct dib3000_state* state = fe->demodulator_priv;
 
-	*unc = rd(DIB3000MC_REG_PACKET_ERROR_COUNT);
+	*unc = rd(DIB3000MC_REG_PACKET_ERRORS);
 	return 0;
 }
 
@@ -737,10 +727,7 @@
 
 static int dib3000mc_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
 {
-	tune->min_delay_ms = 2000;
-	tune->step_size = 166667;
-	tune->max_drift = 166667 * 2;
-
+	tune->min_delay_ms = 1000;
 	return 0;
 }
 
diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c
index 2a3c2ce..f73b5f4 100644
--- a/drivers/media/dvb/frontends/dvb-pll.c
+++ b/drivers/media/dvb/frontends/dvb-pll.c
@@ -1,6 +1,4 @@
 /*
- * $Id: dvb-pll.c,v 1.7 2005/02/10 11:52:02 kraxel Exp $
- *
  * descriptions + helper functions for simple dvb plls.
  *
  * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
@@ -114,6 +112,92 @@
 };
 EXPORT_SYMBOL(dvb_pll_unknown_1);
 
+/* Infineon TUA6010XS
+ * used in Thomson Cable Tuner
+ */
+struct dvb_pll_desc dvb_pll_tua6010xs = {
+	.name  = "Infineon TUA6010XS",
+	.min   =  44250000,
+	.max   = 858000000,
+	.count = 3,
+	.entries = {
+		{  115750000, 36125000, 62500, 0x8e, 0x03 },
+		{  403250000, 36125000, 62500, 0x8e, 0x06 },
+		{  999999999, 36125000, 62500, 0x8e, 0x85 },
+	},
+};
+EXPORT_SYMBOL(dvb_pll_tua6010xs);
+
+/* Panasonic env57h1xd5 (some Philips PLL ?) */
+struct dvb_pll_desc dvb_pll_env57h1xd5 = {
+	.name  = "Panasonic ENV57H1XD5",
+	.min   =  44250000,
+	.max   = 858000000,
+	.count = 4,
+	.entries = {
+		{  153000000, 36291666, 166666, 0xc2, 0x41 },
+		{  470000000, 36291666, 166666, 0xc2, 0x42 },
+		{  526000000, 36291666, 166666, 0xc2, 0x84 },
+		{  999999999, 36291666, 166666, 0xc2, 0xa4 },
+	},
+};
+EXPORT_SYMBOL(dvb_pll_env57h1xd5);
+
+/* Philips TDA6650/TDA6651
+ * used in Panasonic ENV77H11D5
+ */
+static void tda665x_bw(u8 *buf, int bandwidth)
+{
+	if (bandwidth == BANDWIDTH_8_MHZ)
+		buf[3] |= 0x08;
+}
+
+struct dvb_pll_desc dvb_pll_tda665x = {
+	.name  = "Philips TDA6650/TDA6651",
+	.min   =  44250000,
+	.max   = 858000000,
+	.setbw = tda665x_bw,
+	.count = 12,
+	.entries = {
+		{   93834000, 36249333, 166667, 0xca, 0x61 /* 011 0 0 0  01 */ },
+		{  123834000, 36249333, 166667, 0xca, 0xa1 /* 101 0 0 0  01 */ },
+		{  161000000, 36249333, 166667, 0xca, 0xa1 /* 101 0 0 0  01 */ },
+		{  163834000, 36249333, 166667, 0xca, 0xc2 /* 110 0 0 0  10 */ },
+		{  253834000, 36249333, 166667, 0xca, 0x62 /* 011 0 0 0  10 */ },
+		{  383834000, 36249333, 166667, 0xca, 0xa2 /* 101 0 0 0  10 */ },
+		{  443834000, 36249333, 166667, 0xca, 0xc2 /* 110 0 0 0  10 */ },
+		{  444000000, 36249333, 166667, 0xca, 0xc3 /* 110 0 0 0  11 */ },
+		{  583834000, 36249333, 166667, 0xca, 0x63 /* 011 0 0 0  11 */ },
+		{  793834000, 36249333, 166667, 0xca, 0xa3 /* 101 0 0 0  11 */ },
+		{  444834000, 36249333, 166667, 0xca, 0xc3 /* 110 0 0 0  11 */ },
+		{  861000000, 36249333, 166667, 0xca, 0xe3 /* 111 0 0 0  11 */ },
+	}
+};
+EXPORT_SYMBOL(dvb_pll_tda665x);
+
+/* Infineon TUA6034
+ * used in LG TDTP E102P
+ */
+static void tua6034_bw(u8 *buf, int bandwidth)
+{
+	if (BANDWIDTH_7_MHZ != bandwidth)
+		buf[3] |= 0x08;
+}
+
+struct dvb_pll_desc dvb_pll_tua6034 = {
+	.name  = "Infineon TUA6034",
+	.min   =  44250000,
+	.max   = 858000000,
+	.count = 3,
+	.setbw = tua6034_bw,
+	.entries = {
+		{  174500000, 36166667, 62500, 0xce, 0x01 },
+		{  230000000, 36166667, 62500, 0xce, 0x02 },
+		{  999999999, 36166667, 62500, 0xce, 0x04 },
+	},
+};
+EXPORT_SYMBOL(dvb_pll_tua6034);
+
 /* ----------------------------------------------------------- */
 /* code                                                        */
 
@@ -160,9 +244,3 @@
 MODULE_DESCRIPTION("dvb pll library");
 MODULE_AUTHOR("Gerd Knorr");
 MODULE_LICENSE("GPL");
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/frontends/dvb-pll.h b/drivers/media/dvb/frontends/dvb-pll.h
index c4c3c56..b796778 100644
--- a/drivers/media/dvb/frontends/dvb-pll.h
+++ b/drivers/media/dvb/frontends/dvb-pll.h
@@ -1,5 +1,5 @@
 /*
- * $Id: dvb-pll.h,v 1.2 2005/02/10 11:43:41 kraxel Exp $
+ * descriptions + helper functions for simple dvb plls.
  */
 
 #ifndef __DVB_PLL_H__
@@ -17,7 +17,7 @@
 		u32 stepsize;
 		u8  cb1;
 		u8  cb2;
-	} entries[9];
+	} entries[12];
 };
 
 extern struct dvb_pll_desc dvb_pll_thomson_dtt7579;
@@ -26,6 +26,11 @@
 extern struct dvb_pll_desc dvb_pll_lg_z201;
 extern struct dvb_pll_desc dvb_pll_unknown_1;
 
+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_tda665x;
+
 int dvb_pll_configure(struct dvb_pll_desc *desc, u8 *buf,
 		      u32 freq, int bandwidth);
 
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 6c05fdd..1b70f8b 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -7,6 +7,19 @@
 
 comment "Video Adapters"
 
+config TUNER_MULTI_I2C
+	bool "Enable support for multiple I2C devices on Video Adapters (EXPERIMENTAL)"
+	depends on VIDEO_DEV && EXPERIMENTAL
+	---help---
+	  Some video adapters have more than one tuner inside. This patch
+	  enables support for using more than one tuner. This is required
+	  for some cards to allow tunning  both video and radio.
+	  It also improves I2C autodetection for these cards.
+
+	  Only few tuners currently is supporting this. More to come.
+
+	  It is safe to say 'Y' here even if your card has only one I2C tuner.
+
 config VIDEO_BT848
 	tristate "BT848 Video For Linux"
 	depends on VIDEO_DEV && PCI && I2C
@@ -330,6 +343,7 @@
 	select VIDEO_BUF_DVB
 	select DVB_MT352
 	select DVB_OR51132
+	select DVB_CX22702
 	---help---
 	  This adds support for DVB/ATSC cards based on the
 	  Connexant 2388x chip.
diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c
index 80254ca..48989ed 100644
--- a/drivers/media/video/adv7170.c
+++ b/drivers/media/video/adv7170.c
@@ -384,22 +384,14 @@
 	I2C_ADV7171 >> 1, (I2C_ADV7171 >> 1) + 1,
 	I2C_CLIENT_END
 };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
                                                                                 
 static struct i2c_client_address_data addr_data = {
 	.normal_i2c		= normal_i2c,
-	.normal_i2c_range	= normal_i2c_range,
-	.probe			= probe,
-	.probe_range		= probe_range,
-	.ignore			= ignore,
-	.ignore_range		= ignore_range,
-	.force			= force
+	.probe			= &ignore,
+	.ignore			= &ignore,
+	.force			= &ignore,
 };
 
 static struct i2c_driver i2c_driver_adv7170;
diff --git a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
index 95d0974..f898b65 100644
--- a/drivers/media/video/adv7175.c
+++ b/drivers/media/video/adv7175.c
@@ -434,22 +434,14 @@
 	I2C_ADV7176 >> 1, (I2C_ADV7176 >> 1) + 1,
 	I2C_CLIENT_END
 };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
                                                                                 
 static struct i2c_client_address_data addr_data = {
 	.normal_i2c		= normal_i2c,
-	.normal_i2c_range	= normal_i2c_range,
-	.probe			= probe,
-	.probe_range		= probe_range,
-	.ignore			= ignore,
-	.ignore_range		= ignore_range,
-	.force			= force
+	.probe			= &ignore,
+	.ignore			= &ignore,
+	.force			= &ignore,
 };
 
 static struct i2c_driver i2c_driver_adv7175;
diff --git a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c
index cf0db25..8733588 100644
--- a/drivers/media/video/bt819.c
+++ b/drivers/media/video/bt819.c
@@ -500,22 +500,14 @@
 	I2C_BT819 >> 1,
 	I2C_CLIENT_END,
 };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
                                                                                 
 static struct i2c_client_address_data addr_data = {
 	.normal_i2c		= normal_i2c,
-	.normal_i2c_range	= normal_i2c_range,
-	.probe			= probe,
-	.probe_range		= probe_range,
-	.ignore			= ignore,
-	.ignore_range		= ignore_range,
-	.force			= force
+	.probe			= &ignore,
+	.ignore			= &ignore,
+	.force			= &ignore,
 };
 
 static struct i2c_driver i2c_driver_bt819;
diff --git a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c
index efe605a..9a642c7d 100644
--- a/drivers/media/video/bt832.c
+++ b/drivers/media/video/bt832.c
@@ -6,7 +6,7 @@
   It outputs an 8-bit 4:2:2 YUV or YCrCb video signal which can be directly
   connected to bt848/bt878 GPIO pins on this purpose.
   (see: VLSI Vision Ltd. www.vvl.co.uk for camera datasheets)
-  
+
   Supported Cards:
   -  Pixelview Rev.4E: 0x8a
 		GPIO 0x400000 toggles Bt832 RESET, and the chip changes to i2c 0x88 !
@@ -31,16 +31,16 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 
-#include "id.h"
-#include "audiochip.h"
+#include <media/audiochip.h>
+#include <media/id.h>
 #include "bttv.h"
 #include "bt832.h"
 
 MODULE_LICENSE("GPL");
 
 /* Addresses to scan */
-static unsigned short normal_i2c[] = {I2C_CLIENT_END};
-static unsigned short normal_i2c_range[] = {I2C_BT832_ALT1>>1,I2C_BT832_ALT2>>1,I2C_CLIENT_END};
+static unsigned short normal_i2c[] = { I2C_BT832_ALT1>>1, I2C_BT832_ALT2>>1,
+				       I2C_CLIENT_END };
 I2C_CLIENT_INSMOD;
 
 /* ---------------------------------------------------------------------- */
@@ -95,7 +95,7 @@
 
 	buf=kmalloc(65,GFP_KERNEL);
 	bt832_hexdump(i2c_client_s,buf);
-	
+
 	if(buf[0x40] != 0x31) {
 		printk("bt832: this i2c chip is no bt832 (id=%02x). Detaching.\n",buf[0x40]);
 		kfree(buf);
@@ -135,7 +135,7 @@
 	buf[1]= 0x27 & (~0x01); // Default | !skip
 	if (2 != (rc = i2c_master_send(i2c_client_s,buf,2)))
                 printk("bt832: i2c i/o error EO: rc == %d (should be 2)\n",rc);
-	
+
         bt832_hexdump(i2c_client_s,buf);
 
 #if 0
@@ -168,8 +168,7 @@
 
 
 
-static int bt832_attach(struct i2c_adapter *adap, int addr,
-			  unsigned short flags, int kind)
+static int bt832_attach(struct i2c_adapter *adap, int addr, int kind)
 {
 	struct bt832 *t;
 
@@ -184,27 +183,32 @@
                 return -ENOMEM;
 	memset(t,0,sizeof(*t));
 	t->client = client_template;
-        t->client.data = t;
+        i2c_set_clientdata(&t->client, t);
         i2c_attach_client(&t->client);
 
 	if(! bt832_init(&t->client)) {
 		bt832_detach(&t->client);
 		return -1;
 	}
-        
+
 	return 0;
 }
 
 static int bt832_probe(struct i2c_adapter *adap)
 {
+#ifdef I2C_CLASS_TV_ANALOG
 	if (adap->class & I2C_CLASS_TV_ANALOG)
 		return i2c_probe(adap, &addr_data, bt832_attach);
+#else
+	if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
+		return i2c_probe(adap, &addr_data, bt832_attach);
+#endif
 	return 0;
 }
 
 static int bt832_detach(struct i2c_client *client)
 {
-	struct bt832 *t = (struct bt832*)client->data;
+	struct bt832 *t = i2c_get_clientdata(client);
 
 	printk("bt832: detach.\n");
 	i2c_detach_client(client);
@@ -215,7 +219,7 @@
 static int
 bt832_command(struct i2c_client *client, unsigned int cmd, void *arg)
 {
-	struct bt832 *t = (struct bt832*)client->data;
+	struct bt832 *t = i2c_get_clientdata(client);
 
 	printk("bt832: command %x\n",cmd);
 
@@ -249,19 +253,18 @@
 };
 static struct i2c_client client_template =
 {
-        .name   = "bt832",
-	.flags  = I2C_CLIENT_ALLOW_USE,
-        .driver = &driver,
+	I2C_DEVNAME("bt832"),
+	.flags      = I2C_CLIENT_ALLOW_USE,
+        .driver     = &driver,
 };
 
 
-int bt832_init_module(void)
+static int __init bt832_init_module(void)
 {
-	i2c_add_driver(&driver);
-	return 0;
+	return i2c_add_driver(&driver);
 }
 
-static void bt832_cleanup_module(void)
+static void __exit bt832_cleanup_module(void)
 {
 	i2c_del_driver(&driver);
 }
@@ -269,3 +272,10 @@
 module_init(bt832_init_module);
 module_exit(bt832_cleanup_module);
 
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/video/bt832.h b/drivers/media/video/bt832.h
index 7a98c06..9b6a8d2 100644
--- a/drivers/media/video/bt832.h
+++ b/drivers/media/video/bt832.h
@@ -1,6 +1,6 @@
 /* Bt832 CMOS Camera Video Processor (VP)
 
- The Bt832 CMOS Camera Video Processor chip connects a Quartsight CMOS 
+ The Bt832 CMOS Camera Video Processor chip connects a Quartsight CMOS
   color digital camera directly to video capture devices via an 8-bit,
   4:2:2 YUV or YCrCb video interface.
 
@@ -85,7 +85,7 @@
 #define BT832_DEVICE_ID		63
 # define BT832_DEVICE_ID__31		0x31 // Bt832 has ID 0x31
 
-/* STMicroelectronivcs VV5404 camera module 
+/* STMicroelectronivcs VV5404 camera module
    i2c: 0x20: sensor address
    i2c: 0xa0: eeprom for ccd defect map
  */
@@ -256,26 +256,26 @@
 //===========================================================================
 // Timing generator SRAM table values for CCIR601 720x480 NTSC
 //===========================================================================
-// For NTSC CCIR656 
+// For NTSC CCIR656
 BYTE BtCard::SRAMTable_NTSC[] =
 {
     // SRAM Timing Table for NTSC
-    0x0c, 0xc0, 0x00, 
-    0x00, 0x90, 0xc2, 
-    0x03, 0x10, 0x03, 
-    0x06, 0x10, 0x34, 
-    0x12, 0x12, 0x65, 
-    0x02, 0x13, 0x24, 
-    0x19, 0x00, 0x24, 
-    0x39, 0x00, 0x96, 
-    0x59, 0x08, 0x93, 
+    0x0c, 0xc0, 0x00,
+    0x00, 0x90, 0xc2,
+    0x03, 0x10, 0x03,
+    0x06, 0x10, 0x34,
+    0x12, 0x12, 0x65,
+    0x02, 0x13, 0x24,
+    0x19, 0x00, 0x24,
+    0x39, 0x00, 0x96,
+    0x59, 0x08, 0x93,
     0x83, 0x08, 0x97,
-    0x03, 0x50, 0x30, 
-    0xc0, 0x40, 0x30, 
-    0x86, 0x01, 0x01, 
-    0xa6, 0x0d, 0x62, 
-    0x03, 0x11, 0x61, 
-    0x05, 0x37, 0x30, 
+    0x03, 0x50, 0x30,
+    0xc0, 0x40, 0x30,
+    0x86, 0x01, 0x01,
+    0xa6, 0x0d, 0x62,
+    0x03, 0x11, 0x61,
+    0x05, 0x37, 0x30,
     0xac, 0x21, 0x50
 };
 
diff --git a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c
index 72c7eb0..a5d529c 100644
--- a/drivers/media/video/bt856.c
+++ b/drivers/media/video/bt856.c
@@ -288,22 +288,14 @@
  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
  */
 static unsigned short normal_i2c[] = { I2C_BT856 >> 1, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
                                                                                 
 static struct i2c_client_address_data addr_data = {
 	.normal_i2c		= normal_i2c,
-	.normal_i2c_range	= normal_i2c_range,
-	.probe			= probe,
-	.probe_range		= probe_range,
-	.ignore			= ignore,
-	.ignore_range		= ignore_range,
-	.force			= force
+	.probe			= &ignore,
+	.ignore			= &ignore,
+	.force			= &ignore,
 };
 
 static struct i2c_driver i2c_driver_bt856;
diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c
index 6334122..251092e 100644
--- a/drivers/media/video/bttv-cards.c
+++ b/drivers/media/video/bttv-cards.c
@@ -1,5 +1,5 @@
 /*
-    $Id: bttv-cards.c,v 1.47 2005/02/22 14:06:32 kraxel Exp $
+    $Id: bttv-cards.c,v 1.49 2005/06/10 17:20:24 mchehab Exp $
 
     bttv-cards.c
 
@@ -51,6 +51,7 @@
 static void osprey_eeprom(struct bttv *btv);
 static void modtec_eeprom(struct bttv *btv);
 static void init_PXC200(struct bttv *btv);
+static void init_RTV24(struct bttv *btv);
 
 static void winview_audio(struct bttv *btv, struct video_audio *v, int set);
 static void lt9415_audio(struct bttv *btv, struct video_audio *v, int set);
@@ -2251,6 +2252,20 @@
 	.no_tda7432	= 1,
 	.no_tda9875	= 1,
 	.muxsel_hook	= kodicom4400r_muxsel,
+},
+{
+        /* ---- card 0x85---------------------------------- */
+        /* Michael Henson <mhenson@clarityvi.com> */
+        /* Adlink RTV24 with special unlock codes */
+        .name           = "Adlink RTV24",
+        .video_inputs   = 4,
+        .audio_inputs   = 1,
+        .tuner          = 0,
+        .svhs           = 2,
+        .muxsel         = { 2, 3, 1, 0},
+        .tuner_type     = -1,
+        .pll            = PLL_28,
+
 }};
 
 static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards);
@@ -2636,6 +2651,10 @@
 	case BTTV_AVDVBT_771:
 		btv->use_i2c_hw = 1;
 		break;
+        case BTTV_ADLINK_RTV24:
+                init_RTV24( btv );
+                break;
+
 	}
 	if (!bttv_tvcards[btv->c.type].has_dvb)
 		bttv_reset_audio(btv);
@@ -2784,6 +2803,8 @@
         }
 	btv->pll.pll_current = -1;
 
+	bttv_reset_audio(btv);
+
 	/* tuner configuration (from card list / autodetect / insmod option) */
  	if (UNSET != bttv_tvcards[btv->c.type].tuner_type)
 		if(UNSET == btv->tuner_type)
@@ -3304,6 +3325,83 @@
 }
 
 
+
+/* ----------------------------------------------------------------------- */
+/*
+ *  The Adlink RTV-24 (aka Angelo) has some special initialisation to unlock
+ *  it. This apparently involves the following procedure for each 878 chip:
+ *
+ *  1) write 0x00C3FEFF to the GPIO_OUT_EN register
+ *
+ *  2)  write to GPIO_DATA
+ *      - 0x0E
+ *      - sleep 1ms
+ *      - 0x10 + 0x0E
+ *      - sleep 10ms
+ *      - 0x0E
+ *     read from GPIO_DATA into buf (uint_32)
+ *      - if ( data>>18 & 0x01 != 0) || ( buf>>19 & 0x01 != 1 )
+ *                 error. ERROR_CPLD_Check_Failed stop.
+ *
+ *  3) write to GPIO_DATA
+ *      - write 0x4400 + 0x0E
+ *      - sleep 10ms
+ *      - write 0x4410 + 0x0E
+ *      - sleep 1ms
+ *      - write 0x0E
+ *     read from GPIO_DATA into buf (uint_32)
+ *      - if ( buf>>18 & 0x01 ) || ( buf>>19 && 0x01 != 0 )
+ *                error. ERROR_CPLD_Check_Failed.
+ */
+/* ----------------------------------------------------------------------- */
+void
+init_RTV24 (struct bttv *btv)
+{
+	uint32_t dataRead = 0;
+	long watchdog_value = 0x0E;
+
+	printk (KERN_INFO
+		"bttv%d: Adlink RTV-24 initialisation in progress ...\n",
+		btv->c.nr);
+
+	btwrite (0x00c3feff, BT848_GPIO_OUT_EN);
+
+	btwrite (0 + watchdog_value, BT848_GPIO_DATA);
+	msleep (1);
+	btwrite (0x10 + watchdog_value, BT848_GPIO_DATA);
+	msleep (10);
+	btwrite (0 + watchdog_value, BT848_GPIO_DATA);
+
+	dataRead = btread (BT848_GPIO_DATA);
+
+	if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 1)) {
+		printk (KERN_INFO
+			"bttv%d: Adlink RTV-24 initialisation(1) ERROR_CPLD_Check_Failed (read %d)\n",
+			btv->c.nr, dataRead);
+	}
+
+	btwrite (0x4400 + watchdog_value, BT848_GPIO_DATA);
+	msleep (10);
+	btwrite (0x4410 + watchdog_value, BT848_GPIO_DATA);
+	msleep (1);
+	btwrite (watchdog_value, BT848_GPIO_DATA);
+	msleep (1);
+	dataRead = btread (BT848_GPIO_DATA);
+
+	if ((((dataRead >> 18) & 0x01) != 0) || (((dataRead >> 19) & 0x01) != 0)) {
+		printk (KERN_INFO
+			"bttv%d: Adlink RTV-24 initialisation(2) ERROR_CPLD_Check_Failed (read %d)\n",
+			btv->c.nr, dataRead);
+
+		return;
+	}
+
+	printk (KERN_INFO
+		"bttv%d: Adlink RTV-24 initialisation complete.\n", btv->c.nr);
+}
+
+
+
 /* ----------------------------------------------------------------------- */
 /* Miro Pro radio stuff -- the tea5757 is connected to some GPIO ports     */
 /*
diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
index 033cc54..290289a 100644
--- a/drivers/media/video/bttv-driver.c
+++ b/drivers/media/video/bttv-driver.c
@@ -1,5 +1,5 @@
 /*
-    $Id: bttv-driver.c,v 1.37 2005/02/21 13:57:59 kraxel Exp $
+    $Id: bttv-driver.c,v 1.38 2005/06/10 17:20:24 mchehab Exp $
 
     bttv - Bt848 frame grabber driver
 
diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c
index c2368bc..da448a5 100644
--- a/drivers/media/video/bttv-i2c.c
+++ b/drivers/media/video/bttv-i2c.c
@@ -1,5 +1,5 @@
 /*
-    $Id: bttv-i2c.c,v 1.18 2005/02/16 12:14:10 kraxel Exp $
+    $Id: bttv-i2c.c,v 1.21 2005/06/10 17:20:24 mchehab Exp $
 
     bttv-i2c.c  --  all the i2c code is here
 
diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h
index 8322b66..191eaf1 100644
--- a/drivers/media/video/bttv.h
+++ b/drivers/media/video/bttv.h
@@ -1,5 +1,5 @@
 /*
- * $Id: bttv.h,v 1.17 2005/02/22 14:06:32 kraxel Exp $
+ * $Id: bttv.h,v 1.18 2005/05/24 23:41:42 nsh Exp $
  *
  *  bttv - Bt848 frame grabber driver
  *
@@ -135,6 +135,7 @@
 #define BTTV_DVICO_DVBT_LITE  0x80
 #define BTTV_TIBET_CS16  0x83
 #define BTTV_KODICOM_4400R  0x84
+#define BTTV_ADLINK_RTV24   0x85
 
 /* i2c address list */
 #define I2C_TSA5522        0xc2
diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h
index 1a9ba7e..7b6f1e8 100644
--- a/drivers/media/video/bttvp.h
+++ b/drivers/media/video/bttvp.h
@@ -226,10 +226,6 @@
 #define dprintk  if (bttv_debug >= 1) printk
 #define d2printk if (bttv_debug >= 2) printk
 
-/* our devices */
-#define BTTV_MAX 16
-extern unsigned int bttv_num;
-
 #define BTTV_MAX_FBUF   0x208000
 #define VBIBUF_SIZE     (2048*VBI_MAXLINES*2)
 #define BTTV_TIMEOUT    (HZ/2) /* 0.5 seconds */
@@ -375,6 +371,10 @@
 	unsigned int users;
 	struct bttv_fh init;
 };
+
+/* our devices */
+#define BTTV_MAX 16
+extern unsigned int bttv_num;
 extern struct bttv bttvs[BTTV_MAX];
 
 /* private ioctls */
diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
index 46d6778..91f8afe 100644
--- a/drivers/media/video/cx88/cx88-blackbird.c
+++ b/drivers/media/video/cx88/cx88-blackbird.c
@@ -1,5 +1,5 @@
 /*
- * $Id: cx88-blackbird.c,v 1.26 2005/03/07 15:58:05 kraxel Exp $
+ * $Id: cx88-blackbird.c,v 1.27 2005/06/03 13:31:50 mchehab Exp $
  *
  *  Support for a cx23416 mpeg encoder via cx2388x host port.
  *  "blackbird" reference design.
@@ -61,37 +61,304 @@
 
 #define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
 
-/*Firmware API commands*/
-#define IVTV_API_ENC_PING_FW 0x00000080
-#define IVTV_API_ENC_GETVER 0x000000C4
-#define IVTV_API_ENC_HALT_FW 0x000000C3
-#define IVTV_API_STD_TIMEOUT 0x00010000 /*units??*/
-//#define IVTV_API_ASSIGN_PGM_INDEX_INFO 0x000000c7
-#define IVTV_API_ASSIGN_STREAM_TYPE 0x000000b9
-#define IVTV_API_ASSIGN_OUTPUT_PORT 0x000000bb
-#define IVTV_API_ASSIGN_FRAMERATE 0x0000008f
-#define IVTV_API_ASSIGN_FRAME_SIZE 0x00000091
-#define IVTV_API_ASSIGN_ASPECT_RATIO 0x00000099
-#define IVTV_API_ASSIGN_BITRATES 0x00000095
-#define IVTV_API_ASSIGN_GOP_PROPERTIES 0x00000097
-#define IVTV_API_ASSIGN_3_2_PULLDOWN 0x000000b1
-#define IVTV_API_ASSIGN_GOP_CLOSURE 0x000000c5
-#define IVTV_API_ASSIGN_AUDIO_PROPERTIES 0x000000bd
-#define IVTV_API_ASSIGN_DNR_FILTER_MODE 0x0000009b
-#define IVTV_API_ASSIGN_DNR_FILTER_PROPS 0x0000009d
-#define IVTV_API_ASSIGN_CORING_LEVELS 0x0000009f
-#define IVTV_API_ASSIGN_SPATIAL_FILTER_TYPE 0x000000a1
-#define IVTV_API_ASSIGN_FRAME_DROP_RATE 0x000000d0
-#define IVTV_API_ASSIGN_PLACEHOLDER 0x000000d8
-#define IVTV_API_MUTE_VIDEO 0x000000d9
-#define IVTV_API_MUTE_AUDIO 0x000000da
-#define IVTV_API_INITIALIZE_INPUT 0x000000cd
-#define IVTV_API_REFRESH_INPUT 0x000000d3
-#define IVTV_API_ASSIGN_NUM_VSYNC_LINES 0x000000d6
-#define IVTV_API_BEGIN_CAPTURE 0x00000081
-//#define IVTV_API_PAUSE_ENCODER 0x000000d2
-//#define IVTV_API_EVENT_NOTIFICATION 0x000000d5
-#define IVTV_API_END_CAPTURE 0x00000082
+/* Firmware API commands */
+/* #define IVTV_API_STD_TIMEOUT 0x00010000 // 65536, units?? */
+#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,
+	BLACKBIRD_RAW_PASSTHRU_CAPTURE
+};
+enum blackbird_capture_bits {
+	BLACKBIRD_RAW_BITS_NONE             = 0x00,
+	BLACKBIRD_RAW_BITS_YUV_CAPTURE      = 0x01,
+	BLACKBIRD_RAW_BITS_PCM_CAPTURE      = 0x02,
+	BLACKBIRD_RAW_BITS_VBI_CAPTURE      = 0x04,
+	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,
+};
+enum blackbird_vbi_insertion_bits {
+	BLACKBIRD_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,
+	BLACKBIRD_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,
+	BLACKBIRD_VBI_BITS_SEPARATE_STREAM = 0x2 << 1,
+	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,
+};
+enum blackbird_notification_status {
+	BLACKBIRD_NOTIFICATION_OFF,
+	BLACKBIRD_NOTIFICATION_ON,
+};
+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 */
+	BLACKBIRD_FIELD1_MICRONAS = 0x0105, /* 261 */
+};
+enum blackbird_field2_lines {
+	BLACKBIRD_FIELD2_SAA7114 = 0x00EF, /* 239 */
+	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,
+};
+enum blackbird_mute_video_mask {
+	BLACKBIRD_MUTE_VIDEO_V_MASK = 0x0000FF00,
+	BLACKBIRD_MUTE_VIDEO_U_MASK = 0x00FF0000,
+	BLACKBIRD_MUTE_VIDEO_Y_MASK = 0xFF000000,
+};
+enum blackbird_mute_video_shift {
+	BLACKBIRD_MUTE_VIDEO_V_SHIFT = 8,
+	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*/)
@@ -405,68 +672,100 @@
 	return 0;
 }
 
+/**
+ Settings used by the windows tv app for PVR2000:
+=================================================================================================================
+Profile | Codec | Resolution | CBR/VBR | Video Qlty   | V. Bitrate | Frmrate | Audio Codec | A. Bitrate | A. Mode
+-----------------------------------------------------------------------------------------------------------------
+MPEG-1  | MPEG1 | 352x288PAL | (CBR)   | 1000:Optimal | 2000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
+MPEG-2  | MPEG2 | 720x576PAL | VBR     | 600 :Good    | 4000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
+VCD     | MPEG1 | 352x288PAL | (CBR)   | 1000:Optimal | 1150 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
+DVD     | MPEG2 | 720x576PAL | VBR     | 600 :Good    | 6000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
+DB* DVD | MPEG2 | 720x576PAL | CBR     | 600 :Good    | 6000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
+=================================================================================================================
+*DB: "DirectBurn"
+*/
 static void blackbird_codec_settings(struct cx8802_dev *dev)
 {
 	int bitrate_mode = 1;
 	int bitrate = 7500000;
 	int bitrate_peak = 7500000;
+#if 1
+	bitrate_mode = BLACKBIRD_VIDEO_CBR;
+	bitrate = 4000*1024;
+	bitrate_peak = 4000*1024;
+#endif
 
 	/* assign stream type */
-        blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 0); /* program stream */
-        //blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 2); /* MPEG1 stream */
-        //blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 3); /* PES A/V */
-        //blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 10); /* DVD stream */
+	blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, BLACKBIRD_STREAM_PROGRAM);
+	/* blackbird_api_cmd(dev, BLACKBIRD_API_SET_STREAM_TYPE, 1, 0, BLACKBIRD_STREAM_TRANSPORT); */
 
-        /* assign output port */
-        blackbird_api_cmd(dev, IVTV_API_ASSIGN_OUTPUT_PORT, 1, 0, 1); /* 1 = Host */
+	/* assign output port */
+	blackbird_api_cmd(dev, BLACKBIRD_API_SET_OUTPUT_PORT, 1, 0, BLACKBIRD_OUTPUT_PORT_STREAMING); /* Host */
 
-        /* assign framerate */
-        blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAMERATE, 1, 0, 0);
+	/* assign framerate */
+	blackbird_api_cmd(dev, BLACKBIRD_API_SET_FRAMERATE, 1, 0, BLACKBIRD_FRAMERATE_PAL_25);
 
-        /* assign frame size */
-        blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_SIZE, 2, 0,
+	/* assign frame size */
+	blackbird_api_cmd(dev, BLACKBIRD_API_SET_RESOLUTION, 2, 0,
 			  dev->height, dev->width);
 
-        /* assign aspect ratio */
-        blackbird_api_cmd(dev, IVTV_API_ASSIGN_ASPECT_RATIO, 1, 0, 2);
+	/* assign aspect ratio */
+	blackbird_api_cmd(dev, BLACKBIRD_API_SET_ASPECT_RATIO, 1, 0, BLACKBIRD_ASPECT_RATIO_4_3);
 
-        /* assign bitrates */
-        blackbird_api_cmd(dev, IVTV_API_ASSIGN_BITRATES, 5, 0,
+	/* assign bitrates */
+	blackbird_api_cmd(dev, BLACKBIRD_API_SET_VIDEO_BITRATE, 5, 0,
 			 bitrate_mode,         /* mode */
 			 bitrate,              /* bps */
-			 bitrate_peak / 400,   /* peak/400 */
-			 0, 0x70);             /* encoding buffer, ckennedy */
+			 bitrate_peak / BLACKBIRD_PEAK_RATE_DIVISOR,   /* peak/400 */
+			 BLACKBIRD_MUX_RATE_DEFAULT /*, 0x70*/);             /* encoding buffer, ckennedy */
 
-        /* assign gop properties */
-        blackbird_api_cmd(dev, IVTV_API_ASSIGN_GOP_PROPERTIES, 2, 0, 15, 3);
-        //blackbird_api_cmd(dev, IVTV_API_ASSIGN_GOP_PROPERTIES, 2, 0, 2, 1);
+	/* assign gop properties */
+	blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_STRUCTURE, 2, 0, 15, 3);
 
-        /* assign 3 2 pulldown */
-        blackbird_api_cmd(dev, IVTV_API_ASSIGN_3_2_PULLDOWN, 1, 0, 0);
+	/* assign 3 2 pulldown */
+	blackbird_api_cmd(dev, BLACKBIRD_API_SET_3_2_PULLDOWN, 1, 0, BLACKBIRD_3_2_PULLDOWN_DISABLED);
 
-        /* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */
-	blackbird_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, (2<<2) | (8<<4));
+	/* assign audio properties */
+	/* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */
+	/* blackbird_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, (2<<2) | (8<<4));
+	   blackbird_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, 0 | (2 << 2) | (14 << 4)); */
+	blackbird_api_cmd(dev, BLACKBIRD_API_SET_AUDIO_PARAMS, 1, 0,
+			BLACKBIRD_AUDIO_BITS_44100HZ |
+			BLACKBIRD_AUDIO_BITS_LAYER_2 |
+			BLACKBIRD_AUDIO_BITS_LAYER_2_224 |
+			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
+		);
 
 	/* assign gop closure */
-        blackbird_api_cmd(dev, IVTV_API_ASSIGN_GOP_CLOSURE, 1, 0, 0);
+	blackbird_api_cmd(dev, BLACKBIRD_API_SET_GOP_CLOSURE, 1, 0, BLACKBIRD_GOP_CLOSURE_OFF);
 
-        /* assign audio properties */
-        blackbird_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, 0 | (2 << 2) | (14 << 4));
 
-        /* assign dnr filter mode */
-        blackbird_api_cmd(dev, IVTV_API_ASSIGN_DNR_FILTER_MODE, 2, 0, 0, 0);
+	/* assign dnr filter mode */
+	blackbird_api_cmd(dev, BLACKBIRD_API_SET_DNR_MODE, 2, 0,
+			BLACKBIRD_DNR_BITS_MANUAL,
+			BLACKBIRD_MEDIAN_FILTER_DISABLED
+		);
 
-        /* assign dnr filter props*/
-        blackbird_api_cmd(dev, IVTV_API_ASSIGN_DNR_FILTER_PROPS, 2, 0, 0, 0);
+	/* assign dnr filter props*/
+	blackbird_api_cmd(dev, BLACKBIRD_API_SET_MANUAL_DNR, 2, 0, 0, 0);
 
-        /* assign coring levels (luma_h, luma_l, chroma_h, chroma_l) */
-        blackbird_api_cmd(dev, IVTV_API_ASSIGN_CORING_LEVELS, 4, 0, 0, 255, 0, 255);
+	/* 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: 1 = horiz_only, chroma_t: 1 = horiz_only */
-        blackbird_api_cmd(dev, IVTV_API_ASSIGN_SPATIAL_FILTER_TYPE, 2, 0, 1, 1);
+	/* 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);
+	/* assign frame drop rate */
+	/* blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_DROP_RATE, 1, 0, 0); */
 }
 
 static int blackbird_initialize_codec(struct cx8802_dev *dev)
@@ -476,7 +775,7 @@
 	int retval;
 
 	dprintk(1,"Initialize codec\n");
-	retval = blackbird_api_cmd(dev, IVTV_API_ENC_PING_FW, 0, 0); /* ping */
+	retval = blackbird_api_cmd(dev, BLACKBIRD_API_PING, 0, 0); /* ping */
 	if (retval < 0) {
 		/* ping was not successful, reset and upload firmware */
 		cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */
@@ -491,13 +790,13 @@
 		if (dev->mailbox < 0)
 			return -1;
 
-		retval = blackbird_api_cmd(dev, IVTV_API_ENC_PING_FW, 0, 0); /* ping */
+		retval = blackbird_api_cmd(dev, BLACKBIRD_API_PING, 0, 0); /* ping */
 		if (retval < 0) {
 			dprintk(0, "ERROR: Firmware ping failed!\n");
 			return -1;
 		}
 
-		retval = blackbird_api_cmd(dev, IVTV_API_ENC_GETVER, 0, 1, &version);
+		retval = blackbird_api_cmd(dev, BLACKBIRD_API_GET_VERSION, 0, 1, &version);
 		if (retval < 0) {
 			dprintk(0, "ERROR: Firmware get encoder version failed!\n");
 			return -1;
@@ -517,25 +816,36 @@
 	blackbird_codec_settings(dev);
 	msleep(1);
 
-	//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, IVTV_API_ASSIGN_PLACEHOLDER, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+	/* 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_FIELD1_SAA7115,
+			BLACKBIRD_FIELD1_SAA7115
+		);
 
-	blackbird_api_cmd(dev, IVTV_API_INITIALIZE_INPUT, 0, 0); /* initialize the video input */
+	/* 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_CUSTOM_EXTENSION_USR_DATA,
+			0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+
+	blackbird_api_cmd(dev, BLACKBIRD_API_INIT_VIDEO_INPUT, 0, 0); /* initialize the video input */
 
 	msleep(1);
 
-        blackbird_api_cmd(dev, IVTV_API_MUTE_VIDEO, 1, 0, 0);
+	blackbird_api_cmd(dev, BLACKBIRD_API_MUTE_VIDEO, 1, 0, BLACKBIRD_UNMUTE);
 	msleep(1);
-        blackbird_api_cmd(dev, IVTV_API_MUTE_AUDIO, 1, 0, 0);
+	blackbird_api_cmd(dev, BLACKBIRD_API_MUTE_AUDIO, 1, 0, BLACKBIRD_UNMUTE);
 	msleep(1);
 
-	blackbird_api_cmd(dev, IVTV_API_BEGIN_CAPTURE, 2, 0, 0, 0x13); /* start capturing to the host interface */
-	//blackbird_api_cmd(dev, IVTV_API_BEGIN_CAPTURE, 2, 0, 0, 0); /* start capturing to the host interface */
-	msleep(1);
+	/* blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0, 0, 0x13); // start capturing to the host interface */
+	blackbird_api_cmd(dev, BLACKBIRD_API_BEGIN_CAPTURE, 2, 0,
+			BLACKBIRD_MPEG_CAPTURE,
+			BLACKBIRD_RAW_BITS_NONE
+		); /* start capturing to the host interface */
+	msleep(10);
 
-	blackbird_api_cmd(dev, IVTV_API_REFRESH_INPUT, 0,0);
+	blackbird_api_cmd(dev, BLACKBIRD_API_REFRESH_INPUT, 0,0);
 	return 0;
 }
 
@@ -709,7 +1019,12 @@
 {
 	struct cx8802_fh  *fh  = file->private_data;
 
-	blackbird_api_cmd(fh->dev, IVTV_API_END_CAPTURE, 3, 0, 1, 0, 0x13);
+	/* 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_END_NOW,
+			BLACKBIRD_MPEG_CAPTURE,
+			BLACKBIRD_RAW_BITS_NONE
+		);
 
 	/* stop mpeg capture */
 	if (fh->mpegq.streaming)
@@ -908,4 +1223,5 @@
  * Local variables:
  * c-basic-offset: 8
  * End:
+ * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
  */
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c
index 3676248..b3fb043 100644
--- a/drivers/media/video/cx88/cx88-cards.c
+++ b/drivers/media/video/cx88/cx88-cards.c
@@ -1,5 +1,5 @@
 /*
- * $Id: cx88-cards.c,v 1.66 2005/03/04 09:12:23 kraxel Exp $
+ * $Id: cx88-cards.c,v 1.76 2005/06/08 01:28:09 mchehab Exp $
  *
  * device driver for Conexant 2388x based TV cards
  * card-specific stuff.
@@ -35,6 +35,9 @@
 	[CX88_BOARD_UNKNOWN] = {
 		.name		= "UNKNOWN/GENERIC",
 		.tuner_type     = UNSET,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
 		.input          = {{
 			.type   = CX88_VMUX_COMPOSITE1,
 			.vmux   = 0,
@@ -52,6 +55,9 @@
 	[CX88_BOARD_HAUPPAUGE] = {
 		.name		= "Hauppauge WinTV 34xxx models",
 		.tuner_type     = UNSET,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
 		.tda9887_conf   = TDA9887_PRESENT,
 		.input          = {{
 			.type   = CX88_VMUX_TELEVISION,
@@ -78,6 +84,9 @@
 	[CX88_BOARD_GDI] = {
 		.name		= "GDI Black Gold",
 		.tuner_type     = UNSET,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
 		.input          = {{
 			.type   = CX88_VMUX_TELEVISION,
 			.vmux   = 0,
@@ -85,7 +94,10 @@
 	},
 	[CX88_BOARD_PIXELVIEW] = {
 		.name           = "PixelView",
-		.tuner_type     = 5,
+		.tuner_type     = TUNER_PHILIPS_PAL,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
 		.input          = {{
 			.type   = CX88_VMUX_TELEVISION,
 			.vmux   = 0,
@@ -104,7 +116,10 @@
 	},
 	[CX88_BOARD_ATI_WONDER_PRO] = {
 		.name           = "ATI TV Wonder Pro",
-		.tuner_type     = 44,
+		.tuner_type     = TUNER_PHILIPS_4IN1,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
 		.tda9887_conf   = TDA9887_PRESENT | TDA9887_INTERCARRIER,
 		.input          = {{
 			.type   = CX88_VMUX_TELEVISION,
@@ -122,7 +137,10 @@
 	},
         [CX88_BOARD_WINFAST2000XP_EXPERT] = {
                 .name           = "Leadtek Winfast 2000XP Expert",
-                .tuner_type     = 44,
+                .tuner_type     = TUNER_PHILIPS_4IN1,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
 		.tda9887_conf   = TDA9887_PRESENT,
                 .input          = {{
                         .type   = CX88_VMUX_TELEVISION,
@@ -156,7 +174,10 @@
         },
 	[CX88_BOARD_AVERTV_303] = {
 		.name           = "AverTV Studio 303 (M126)",
-		.tuner_type     = 38,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
 		.tda9887_conf   = TDA9887_PRESENT,
 		.input          = {{
 			.type   = CX88_VMUX_TELEVISION,
@@ -179,7 +200,10 @@
 		// added gpio values thanks to Michal
 		// values for PAL from DScaler
 		.name           = "MSI TV-@nywhere Master",
-		.tuner_type     = 33,
+		.tuner_type     = TUNER_MT2032,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
 		.tda9887_conf	= TDA9887_PRESENT,
 		.input          = {{
 			.type   = CX88_VMUX_TELEVISION,
@@ -206,7 +230,10 @@
 	},
 	[CX88_BOARD_WINFAST_DV2000] = {
                 .name           = "Leadtek Winfast DV2000",
-                .tuner_type     = 38,
+                .tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
 		.tda9887_conf   = TDA9887_PRESENT,
                 .input          = {{
                         .type   = CX88_VMUX_TELEVISION,
@@ -239,34 +266,40 @@
 			.gpio3  = 0x02000000,
 		 },
         },
-        [CX88_BOARD_LEADTEK_PVR2000] = {
+	[CX88_BOARD_LEADTEK_PVR2000] = {
 		// gpio values for PAL version from regspy by DScaler
-                .name           = "Leadtek PVR 2000",
-                .tuner_type     = 38,
+		.name           = "Leadtek PVR 2000",
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
 		.tda9887_conf   = TDA9887_PRESENT,
-                .input          = {{
-                        .type   = CX88_VMUX_TELEVISION,
-                        .vmux   = 0,
-                        .gpio0  = 0x0000bde6,
-                },{
-                        .type   = CX88_VMUX_COMPOSITE1,
-                        .vmux   = 1,
-                        .gpio0  = 0x0000bde6,
-                },{
-                        .type   = CX88_VMUX_SVIDEO,
-                        .vmux   = 2,
-                        .gpio0  = 0x0000bde6,
-                }},
-                .radio = {
-                        .type   = CX88_RADIO,
-                        .gpio0  = 0x0000bd62,
-                },
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0x0000bde2,
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0  = 0x0000bde6,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0  = 0x0000bde6,
+		}},
+		.radio = {
+			.type   = CX88_RADIO,
+			.gpio0  = 0x0000bd62,
+		},
 		.blackbird = 1,
-        },
+	},
 	[CX88_BOARD_IODATA_GVVCP3PCI] = {
  		.name		= "IODATA GV-VCP3/PCI",
 		.tuner_type     = TUNER_ABSENT,
- 		.input          = {{
+ 		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
  			.type   = CX88_VMUX_COMPOSITE1,
  			.vmux   = 0,
  		},{
@@ -279,7 +312,10 @@
  	},
 	[CX88_BOARD_PROLINK_PLAYTVPVR] = {
                 .name           = "Prolink PlayTV PVR",
-                .tuner_type     = 43,
+                .tuner_type     = TUNER_PHILIPS_FM1236_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
 		.tda9887_conf	= TDA9887_PRESENT,
 		.input          = {{
 			.type   = CX88_VMUX_TELEVISION,
@@ -301,8 +337,11 @@
 	},
 	[CX88_BOARD_ASUS_PVR_416] = {
 		.name		= "ASUS PVR-416",
-		.tuner_type     = 43,
-                .tda9887_conf   = TDA9887_PRESENT,
+		.tuner_type     = TUNER_PHILIPS_FM1236_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.tda9887_conf   = TDA9887_PRESENT,
 		.input          = {{
 			.type   = CX88_VMUX_TELEVISION,
 			.vmux   = 0,
@@ -320,7 +359,10 @@
 	},
 	[CX88_BOARD_MSI_TVANYWHERE] = {
 		.name           = "MSI TV-@nywhere",
-		.tuner_type     = 33,
+		.tuner_type     = TUNER_MT2032,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
 		.tda9887_conf   = TDA9887_PRESENT,
 		.input          = {{
 			.type   = CX88_VMUX_TELEVISION,
@@ -342,6 +384,9 @@
         [CX88_BOARD_KWORLD_DVB_T] = {
                 .name           = "KWorld/VStream XPert DVB-T",
 		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
                 .input          = {{
                         .type   = CX88_VMUX_COMPOSITE1,
                         .vmux   = 1,
@@ -358,6 +403,9 @@
 	[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1] = {
 		.name           = "DVICO FusionHDTV DVB-T1",
 		.tuner_type     = TUNER_ABSENT, /* No analog tuner */
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
 		.input          = {{
 			.type   = CX88_VMUX_COMPOSITE1,
 			.vmux   = 1,
@@ -371,7 +419,10 @@
 	},
 	[CX88_BOARD_KWORLD_LTV883] = {
 		.name           = "KWorld LTV883RF",
-                .tuner_type     = 48,
+		.tuner_type     = TUNER_TNF_8831BGFF,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
                 .input          = {{
                         .type   = CX88_VMUX_TELEVISION,
                         .vmux   = 0,
@@ -397,6 +448,9 @@
 	[CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD] = {
 		.name		= "DViCO - FusionHDTV 3 Gold",
 		.tuner_type     = TUNER_MICROTUNE_4042FI5,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
 		/*
 		   GPIO[0] resets DT3302 DTV receiver
 		    0 - reset asserted
@@ -428,17 +482,14 @@
 			.vmux   = 2,
 			.gpio0	= 0x0f00,
 		}},
-#if 0
-		.ts             = {
-			 .type   = CX88_TS,
-			 .gpio0  = 0x00000f01,   /* Hooked to tuner reset bit */
-		 }
-#endif
 	},
         [CX88_BOARD_HAUPPAUGE_DVB_T1] = {
-                .name           = "Hauppauge Nova-T DVB-T",
+		.name           = "Hauppauge Nova-T DVB-T",
 		.tuner_type     = TUNER_ABSENT,
-                .input          = {{
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		.input          = {{
                         .type   = CX88_VMUX_DVB,
                         .vmux   = 0,
                 }},
@@ -447,6 +498,9 @@
         [CX88_BOARD_CONEXANT_DVB_T1] = {
 		.name           = "Conexant DVB-T reference design",
 		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
                 .input          = {{
                         .type   = CX88_VMUX_DVB,
                         .vmux   = 0,
@@ -456,6 +510,9 @@
 	[CX88_BOARD_PROVIDEO_PV259] = {
 		.name		= "Provideo PV259",
 		.tuner_type     = TUNER_PHILIPS_FQ1216ME,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
 		.input          = {{
 			.type   = CX88_VMUX_TELEVISION,
 			.vmux   = 0,
@@ -465,6 +522,9 @@
 	[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS] = {
 		.name           = "DVICO FusionHDTV DVB-T Plus",
 		.tuner_type     = TUNER_ABSENT, /* No analog tuner */
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
 		.input          = {{
 			.type   = CX88_VMUX_COMPOSITE1,
 			.vmux   = 1,
@@ -479,6 +539,9 @@
 	[CX88_BOARD_DNTV_LIVE_DVB_T] = {
 		.name	        = "digitalnow DNTV Live! DVB-T",
 		.tuner_type     = TUNER_ABSENT,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
 		.input	        = {{
 			.type   = CX88_VMUX_COMPOSITE1,
 			.vmux   = 1,
@@ -495,6 +558,9 @@
 	[CX88_BOARD_PCHDTV_HD3000] = {
 		.name           = "pcHDTV HD3000 HDTV",
 		.tuner_type     = TUNER_THOMSON_DTT7610,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
 		.input          = {{
 			.type   = CX88_VMUX_TELEVISION,
 			.vmux   = 0,
@@ -530,8 +596,11 @@
 	[CX88_BOARD_HAUPPAUGE_ROSLYN] = {
 		// entry added by Kaustubh D. Bhalerao <bhalerao.1@osu.edu>
 		// GPIO values obtained from regspy, courtesy Sean Covel
-		.name        = "Hauppauge WinTV 28xxx (Roslyn) models",
-		.tuner_type  = UNSET,
+		.name           = "Hauppauge WinTV 28xxx (Roslyn) models",
+		.tuner_type     = UNSET,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
 		.input          = {{
 			.type   = CX88_VMUX_TELEVISION,
 			.vmux   = 0,
@@ -559,33 +628,37 @@
 		.blackbird = 1,
 	},
 	[CX88_BOARD_DIGITALLOGIC_MEC] = {
-		/* params copied over from Leadtek PVR 2000 */
 		.name           = "Digital-Logic MICROSPACE Entertainment Center (MEC)",
-		/* not sure yet about the tuner type */
-		.tuner_type     = 38,
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
 		.tda9887_conf   = TDA9887_PRESENT,
 		.input          = {{
 			.type   = CX88_VMUX_TELEVISION,
 			.vmux   = 0,
-			.gpio0  = 0x0000bde6,
+			.gpio0  = 0x00009d80,
 		},{
 			.type   = CX88_VMUX_COMPOSITE1,
 			.vmux   = 1,
-			.gpio0  = 0x0000bde6,
+			.gpio0  = 0x00009d76,
 		},{
 			.type   = CX88_VMUX_SVIDEO,
 			.vmux   = 2,
-			.gpio0  = 0x0000bde6,
+			.gpio0  = 0x00009d76,
 		}},
 		.radio = {
 			.type   = CX88_RADIO,
-			.gpio0  = 0x0000bd62,
+			.gpio0  = 0x00009d00,
 		},
 		.blackbird = 1,
 	},
 	[CX88_BOARD_IODATA_GVBCTV7E] = {
 		.name           = "IODATA GV/BCTV7E",
 		.tuner_type     = TUNER_PHILIPS_FQ1286,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
 		.tda9887_conf   = TDA9887_PRESENT,
 		.input          = {{
 			.type   = CX88_VMUX_TELEVISION,
@@ -601,6 +674,56 @@
 			.gpio1  = 0x0000e07f,
 		}}
 	},
+	[CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO] = {
+		.name           = "PixelView PlayTV Ultra Pro (Stereo)",
+		/* May be also TUNER_YMEC_TVF_5533MF for NTSC/M or PAL/M */
+		.tuner_type     = TUNER_PHILIPS_FM1216ME_MK3,
+		.radio_type     = TUNER_TEA5767,
+		.tuner_addr	= 0xc2>>1,
+		.radio_addr	= 0xc0>>1,
+		.input          = {{
+			.type   = CX88_VMUX_TELEVISION,
+			.vmux   = 0,
+			.gpio0  = 0xbf61,  /* internal decoder */
+		},{
+			.type   = CX88_VMUX_COMPOSITE1,
+			.vmux   = 1,
+			.gpio0	= 0xbf63,
+		},{
+			.type   = CX88_VMUX_SVIDEO,
+			.vmux   = 2,
+			.gpio0	= 0xbf63,
+		}},
+		.radio = {
+			 .type  = CX88_RADIO,
+			 .gpio0 = 0xbf60,
+		 },
+	},
+        [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T] = {
+                .name           = "DViCO - FusionHDTV 3 Gold-T",
+		.tuner_type     = TUNER_THOMSON_DTT7611,
+		.radio_type     = UNSET,
+		.tuner_addr	= ADDR_UNSET,
+		.radio_addr	= ADDR_UNSET,
+		/*  See DViCO FusionHDTV 3 Gold for GPIO documentation.  */
+                .input          = {{
+                        .type   = CX88_VMUX_TELEVISION,
+                        .vmux   = 0,
+                        .gpio0  = 0x0f0d,
+                },{
+                        .type   = CX88_VMUX_CABLE,
+                        .vmux   = 0,
+                        .gpio0  = 0x0f05,
+                },{
+                        .type   = CX88_VMUX_COMPOSITE1,
+                        .vmux   = 1,
+                        .gpio0  = 0x0f00,
+                },{
+                        .type   = CX88_VMUX_SVIDEO,
+                        .vmux   = 2,
+                        .gpio0  = 0x0f00,
+                }},
+        },
 };
 const unsigned int cx88_bcount = ARRAY_SIZE(cx88_boards);
 
@@ -673,6 +796,10 @@
 		.subdevice = 0xd810,
 		.card      = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD,
 	},{
+		.subvendor = 0x18ac,
+		.subdevice = 0xd820,
+		.card      = CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T,
+	},{
 		.subvendor = 0x18AC,
 		.subdevice = 0xDB00,
 		.card      = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1,
@@ -935,4 +1062,5 @@
  * Local variables:
  * c-basic-offset: 8
  * End:
+ * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
  */
diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c
index 1ff79b5..c046a23 100644
--- a/drivers/media/video/cx88/cx88-core.c
+++ b/drivers/media/video/cx88/cx88-core.c
@@ -1,5 +1,5 @@
 /*
- * $Id: cx88-core.c,v 1.24 2005/01/19 12:01:55 kraxel Exp $
+ * $Id: cx88-core.c,v 1.28 2005/06/12 04:19:19 mchehab Exp $
  *
  * device driver for Conexant 2388x based TV cards
  * driver core
@@ -51,12 +51,15 @@
 MODULE_PARM_DESC(latency,"pci latency timer");
 
 static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
+static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
 static unsigned int card[]  = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET };
 
 module_param_array(tuner, int, NULL, 0444);
+module_param_array(radio, int, NULL, 0444);
 module_param_array(card,  int, NULL, 0444);
 
 MODULE_PARM_DESC(tuner,"tuner type");
+MODULE_PARM_DESC(radio,"radio tuner type");
 MODULE_PARM_DESC(card,"card type");
 
 static unsigned int nicam = 0;
@@ -429,7 +432,7 @@
 /* ------------------------------------------------------------------ */
 /* debug helper code                                                  */
 
-static int cx88_risc_decode(u32 risc)
+int cx88_risc_decode(u32 risc)
 {
 	static char *instr[16] = {
 		[ RISC_SYNC    >> 28 ] = "sync",
@@ -736,6 +739,10 @@
 {
 	static const unsigned int ntsc = 28636360;
 	static const unsigned int pal  = 35468950;
+	static const unsigned int palm  = 28604892;
+
+	if (norm->id & V4L2_STD_PAL_M)
+		return palm;
 
 	return (norm->id & V4L2_STD_625_50) ? pal : ntsc;
 }
@@ -749,6 +756,11 @@
 
 static unsigned int inline norm_htotal(struct cx88_tvnorm *norm)
 {
+	/* Should always be Line Draw Time / (4*FSC) */
+
+	if (norm->id & V4L2_STD_PAL_M)
+		return 909;
+
 	return (norm->id & V4L2_STD_625_50) ? 1135 : 910;
 }
 
@@ -1164,8 +1176,20 @@
 	       "insmod option" : "autodetected");
 
 	core->tuner_type = tuner[core->nr];
+	core->radio_type = radio[core->nr];
 	if (UNSET == core->tuner_type)
 		core->tuner_type = cx88_boards[core->board].tuner_type;
+	if (UNSET == core->radio_type)
+		core->radio_type = cx88_boards[core->board].radio_type;
+	if (!core->tuner_addr)
+		core->tuner_addr = cx88_boards[core->board].tuner_addr;
+	if (!core->radio_addr)
+		core->radio_addr = cx88_boards[core->board].radio_addr;
+
+        printk(KERN_INFO "TV tuner %d at 0x%02x, Radio tuner %d at 0x%02x\n",
+		core->tuner_type, core->tuner_addr<<1,
+		core->radio_type, core->radio_addr<<1);
+
 	core->tda9887_conf = cx88_boards[core->board].tda9887_conf;
 
 	/* init hardware */
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
index 9d15d3d..1a259c3 100644
--- a/drivers/media/video/cx88/cx88-dvb.c
+++ b/drivers/media/video/cx88/cx88-dvb.c
@@ -1,5 +1,5 @@
 /*
- * $Id: cx88-dvb.c,v 1.31 2005/03/07 15:58:05 kraxel Exp $
+ * $Id: cx88-dvb.c,v 1.33 2005/06/12 04:19:19 mchehab Exp $
  *
  * device driver for Conexant 2388x based TV cards
  * MPEG Transport Stream (DVB) routines
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
index 0725b12..e20adef 100644
--- a/drivers/media/video/cx88/cx88-i2c.c
+++ b/drivers/media/video/cx88/cx88-i2c.c
@@ -1,5 +1,5 @@
 /*
-    $Id: cx88-i2c.c,v 1.20 2005/02/15 15:59:35 kraxel Exp $
+    $Id: cx88-i2c.c,v 1.23 2005/06/12 04:19:19 mchehab Exp $
 
     cx88-i2c.c  --  all the i2c code is here
 
@@ -91,6 +91,7 @@
 
 static int attach_inform(struct i2c_client *client)
 {
+        struct tuner_addr tun_addr;
 	struct cx88_core *core = i2c_get_adapdata(client->adapter);
 
 	dprintk(1, "i2c attach [addr=0x%x,client=%s]\n",
@@ -98,8 +99,19 @@
 	if (!client->driver->command)
 		return 0;
 
-	if (core->tuner_type != UNSET)
-		client->driver->command(client, TUNER_SET_TYPE, &core->tuner_type);
+        if (core->radio_type != UNSET) {
+                tun_addr.v4l2_tuner = V4L2_TUNER_RADIO;
+                tun_addr.type = core->radio_type;
+                tun_addr.addr = core->radio_addr;
+                client->driver->command(client,TUNER_SET_TYPE_ADDR, &tun_addr);
+        }
+        if (core->tuner_type != UNSET) {
+                tun_addr.v4l2_tuner = V4L2_TUNER_ANALOG_TV;
+                tun_addr.type = core->tuner_type;
+                tun_addr.addr = core->tuner_addr;
+                client->driver->command(client,TUNER_SET_TYPE_ADDR, &tun_addr);
+        }
+
 	if (core->tda9887_conf)
 		client->driver->command(client, TDA9887_SET_CONFIG, &core->tda9887_conf);
 	return 0;
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c
index af6ad8c..dc0dcf2 100644
--- a/drivers/media/video/cx88/cx88-input.c
+++ b/drivers/media/video/cx88/cx88-input.c
@@ -1,5 +1,5 @@
 /*
- * $Id: cx88-input.c,v 1.9 2005/03/04 09:12:23 kraxel Exp $
+ * $Id: cx88-input.c,v 1.11 2005/05/22 20:57:56 nsh Exp $
  *
  * Device driver for GPIO attached remote control interfaces
  * on Conexant 2388x based TV/DVB cards.
@@ -235,6 +235,7 @@
 	/* detect & configure */
 	switch (core->board) {
 	case CX88_BOARD_DNTV_LIVE_DVB_T:
+	case CX88_BOARD_KWORLD_DVB_T:
 		ir_codes         = ir_codes_dntv_live_dvb_t;
 		ir->gpio_addr    = MO_GP1_IO;
 		ir->mask_keycode = 0x1f;
@@ -261,7 +262,15 @@
 		ir->mask_keydown = 0x02;
 		ir->polling      = 5; // ms
 		break;
+	case CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO:
+		ir_codes         = ir_codes_pixelview;
+		ir->gpio_addr    = MO_GP1_IO;
+		ir->mask_keycode = 0x1f;
+		ir->mask_keyup   = 0x80;
+		ir->polling      = 1; // ms
+		break;
 	}
+
 	if (NULL == ir_codes) {
 		kfree(ir);
 		return -ENODEV;
diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
index 07aae18..9ade2ae 100644
--- a/drivers/media/video/cx88/cx88-mpeg.c
+++ b/drivers/media/video/cx88/cx88-mpeg.c
@@ -1,5 +1,5 @@
 /*
- * $Id: cx88-mpeg.c,v 1.25 2005/03/07 14:18:00 kraxel Exp $
+ * $Id: cx88-mpeg.c,v 1.26 2005/06/03 13:31:51 mchehab Exp $
  *
  *  Support for the mpeg transport stream transfers
  *  PCI function #2 of the cx2388x.
@@ -55,7 +55,7 @@
 {
 	struct cx88_core *core = dev->core;
 
-	dprintk(1, "cx8802_start_mpegport_dma %d\n", buf->vb.width);
+	dprintk(0, "cx8802_start_dma %d\n", buf->vb.width);
 
 	/* setup fifo + format */
 	cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28],
@@ -100,18 +100,21 @@
 	q->count = 1;
 
 	/* enable irqs */
+	dprintk( 0, "setting the interrupt mask\n" );
 	cx_set(MO_PCI_INTMSK, core->pci_irqmask | 0x04);
-	cx_write(MO_TS_INTMSK,  0x1f0011);
+	cx_set(MO_TS_INTMSK,  0x1f0011);
+	//cx_write(MO_TS_INTMSK,  0x0f0011);
 
 	/* start dma */
-	cx_write(MO_DEV_CNTRL2, (1<<5)); /* FIXME: s/write/set/ ??? */
-	cx_write(MO_TS_DMACNTRL, 0x11);
+	cx_set(MO_DEV_CNTRL2, (1<<5));
+	cx_set(MO_TS_DMACNTRL, 0x11);
 	return 0;
 }
 
 static int cx8802_stop_dma(struct cx8802_dev *dev)
 {
 	struct cx88_core *core = dev->core;
+	dprintk( 0, "cx8802_stop_dma\n" );
 
 	/* stop dma */
 	cx_clear(MO_TS_DMACNTRL, 0x11);
@@ -131,8 +134,12 @@
 	struct cx88_buffer *buf;
 	struct list_head *item;
 
+	dprintk( 0, "cx8802_restart_queue\n" );
 	if (list_empty(&q->active))
+	{
+		dprintk( 0, "cx8802_restart_queue: queue is empty\n" );
 		return 0;
+	}
 
 	buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
 	dprintk(2,"restart_queue [%p/%d]: restart dma\n",
@@ -182,27 +189,32 @@
 	struct cx88_buffer    *prev;
 	struct cx88_dmaqueue  *q    = &dev->mpegq;
 
+	dprintk( 1, "cx8802_buf_queue\n" );
 	/* add jump to stopper */
 	buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
 	buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
 
 	if (list_empty(&q->active)) {
+		dprintk( 0, "queue is empty - first active\n" );
 		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(2,"[%p/%d] %s - first active\n",
+		dprintk(0,"[%p/%d] %s - first active\n",
 			buf, buf->vb.i, __FUNCTION__);
+		//udelay(100);
 
 	} else {
+		dprintk( 1, "queue is not empty - append to active\n" );
 		prev = list_entry(q->active.prev, struct cx88_buffer, 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(2,"[%p/%d] %s - append to active\n",
+		dprintk( 1, "[%p/%d] %s - append to active\n",
 			buf, buf->vb.i, __FUNCTION__);
+		//udelay(100);
 	}
 }
 
@@ -224,7 +236,10 @@
 			buf, buf->vb.i, reason, (unsigned long)buf->risc.dma);
 	}
 	if (restart)
+	{
+		dprintk(0, "restarting queue\n" );
 		cx8802_restart_queue(dev,q);
+	}
 	spin_unlock_irqrestore(&dev->slock,flags);
 }
 
@@ -232,6 +247,7 @@
 {
 	struct cx88_dmaqueue *q = &dev->mpegq;
 
+	dprintk( 1, "cx8802_cancel_buffers" );
 	del_timer_sync(&q->timeout);
 	cx8802_stop_dma(dev);
 	do_cancel_buffers(dev,"cancel",0);
@@ -241,7 +257,7 @@
 {
 	struct cx8802_dev *dev = (struct cx8802_dev*)data;
 
-	dprintk(1, "%s\n",__FUNCTION__);
+	dprintk(0, "%s\n",__FUNCTION__);
 
 	if (debug)
 		cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
@@ -254,12 +270,17 @@
 	struct cx88_core *core = dev->core;
 	u32 status, mask, count;
 
+	dprintk( 1, "cx8802_mpeg_irq\n" );
 	status = cx_read(MO_TS_INTSTAT);
 	mask   = cx_read(MO_TS_INTMSK);
 	if (0 == (status & mask))
 		return;
 
 	cx_write(MO_TS_INTSTAT, status);
+#if 0
+	cx88_print_irqbits(core->name, "irq mpeg ",
+			cx88_mpeg_irqs, status, mask);
+#endif
 	if (debug || (status & mask & ~0xff))
 		cx88_print_irqbits(core->name, "irq mpeg ",
 				   cx88_mpeg_irqs, status, mask);
@@ -273,6 +294,7 @@
 
 	/* risc1 y */
 	if (status & 0x01) {
+		dprintk( 1, "wake up\n" );
 		spin_lock(&dev->slock);
 		count = cx_read(MO_TS_GPCNT);
 		cx88_wakeup(dev->core, &dev->mpegq, count);
@@ -288,6 +310,7 @@
 
         /* other general errors */
         if (status & 0x1f0100) {
+		dprintk( 0, "general errors: 0x%08x\n", status & 0x1f0100 );
                 spin_lock(&dev->slock);
 		cx8802_stop_dma(dev);
                 cx8802_restart_queue(dev,&dev->mpegq);
@@ -295,6 +318,8 @@
         }
 }
 
+#define MAX_IRQ_LOOP 10
+
 static irqreturn_t cx8802_irq(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct cx8802_dev *dev = dev_id;
@@ -302,10 +327,13 @@
 	u32 status;
 	int loop, handled = 0;
 
-	for (loop = 0; loop < 10; loop++) {
+	for (loop = 0; loop < MAX_IRQ_LOOP; loop++) {
 		status = cx_read(MO_PCI_INTSTAT) & (core->pci_irqmask | 0x04);
 		if (0 == status)
 			goto out;
+		dprintk( 1, "cx8802_irq\n" );
+		dprintk( 1, "    loop: %d/%d\n", loop, MAX_IRQ_LOOP );
+		dprintk( 1, "    status: %d\n", status );
 		handled = 1;
 		cx_write(MO_PCI_INTSTAT, status);
 
@@ -314,7 +342,8 @@
 		if (status & 0x04)
 			cx8802_mpeg_irq(dev);
 	};
-	if (10 == loop) {
+	if (MAX_IRQ_LOOP == loop) {
+		dprintk( 0, "clearing mask\n" );
 		printk(KERN_WARNING "%s/0: irq loop -- clearing mask\n",
 		       core->name);
 		cx_write(MO_PCI_INTMSK,0);
@@ -378,6 +407,7 @@
 
 void cx8802_fini_common(struct cx8802_dev *dev)
 {
+	dprintk( 2, "cx8802_fini_common\n" );
 	cx8802_stop_dma(dev);
 	pci_disable_device(dev->pci);
 
@@ -399,6 +429,7 @@
 	/* stop mpeg dma */
 	spin_lock(&dev->slock);
 	if (!list_empty(&dev->mpegq.active)) {
+		dprintk( 2, "suspend\n" );
 		printk("%s: suspend mpeg\n", core->name);
 		cx8802_stop_dma(dev);
 		del_timer(&dev->mpegq.timeout);
@@ -463,4 +494,5 @@
  * Local variables:
  * c-basic-offset: 8
  * End:
+ * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
  */
diff --git a/drivers/media/video/cx88/cx88-reg.h b/drivers/media/video/cx88/cx88-reg.h
index 8638ce5..63ad33f 100644
--- a/drivers/media/video/cx88/cx88-reg.h
+++ b/drivers/media/video/cx88/cx88-reg.h
@@ -1,5 +1,5 @@
 /*
-    $Id: cx88-reg.h,v 1.6 2004/10/13 10:39:00 kraxel Exp $
+    $Id: cx88-reg.h,v 1.7 2005/06/03 13:31:51 mchehab Exp $
 
     cx88x-hw.h - CX2388x register offsets
 
@@ -397,6 +397,7 @@
 #define AUD_RATE_ADJ4            0x3205e4
 #define AUD_RATE_ADJ5            0x3205e8
 #define AUD_APB_IN_RATE_ADJ      0x3205ec
+#define AUD_I2SCNTL              0x3205ec
 #define AUD_PHASE_FIX_CTL        0x3205f0
 #define AUD_PLL_PRESCALE         0x320600
 #define AUD_PLL_DDS              0x320604
diff --git a/drivers/media/video/cx88/cx88-tvaudio.c b/drivers/media/video/cx88/cx88-tvaudio.c
index f2a9475..46d78b1 100644
--- a/drivers/media/video/cx88/cx88-tvaudio.c
+++ b/drivers/media/video/cx88/cx88-tvaudio.c
@@ -1,5 +1,5 @@
 /*
-    $Id: cx88-tvaudio.c,v 1.34 2005/03/07 16:10:51 kraxel Exp $
+    $Id: cx88-tvaudio.c,v 1.36 2005/06/05 05:53:45 mchehab Exp $
 
     cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver
 
@@ -127,7 +127,8 @@
 	cx_write(AUD_VOL_CTL,       (1 << 6));
 
 	//  increase level of input by 12dB
-	cx_write(AUD_AFE_12DB_EN,   0x0001);
+//	cx_write(AUD_AFE_12DB_EN,   0x0001);
+	cx_write(AUD_AFE_12DB_EN,   0x0000);
 
 	// start programming
 	cx_write(AUD_CTL,           0x0000);
@@ -143,9 +144,15 @@
 	u32 volume;
 
 	if (cx88_boards[core->board].blackbird) {
+		// sets sound input from external adc
+		cx_set(AUD_CTL, EN_I2SIN_ENABLE);
+		//cx_write(AUD_I2SINPUTCNTL, 0);
+		cx_write(AUD_I2SINPUTCNTL, 4);
+		cx_write(AUD_BAUDRATE, 1);
 		// 'pass-thru mode': this enables the i2s output to the mpeg encoder
-		cx_set(AUD_CTL, 0x2000);
+		cx_set(AUD_CTL, EN_I2SOUT_ENABLE);
 		cx_write(AUD_I2SOUTPUTCNTL, 1);
+		cx_write(AUD_I2SCNTL, 0);
 		//cx_write(AUD_APB_IN_RATE_ADJ, 0);
 	}
 
@@ -707,50 +714,65 @@
 	set_audio_finish(core);
 }
 
-static void set_audio_standard_FM(struct cx88_core *core)
+static void set_audio_standard_FM(struct cx88_core *core, enum cx88_deemph_type deemph)
 {
-#if 0 /* FIXME */
-	switch (dev->audio_properties.FM_deemphasis)
-	{
-		case WW_FM_DEEMPH_50:
-			//Set De-emphasis filter coefficients for 50 usec
-			cx_write(AUD_DEEMPH0_G0, 0x0C45);
-			cx_write(AUD_DEEMPH0_A0, 0x6262);
-			cx_write(AUD_DEEMPH0_B0, 0x1C29);
-			cx_write(AUD_DEEMPH0_A1, 0x3FC66);
-			cx_write(AUD_DEEMPH0_B1, 0x399A);
+	static const struct rlist fm_deemph_50[] = {
+		{ AUD_DEEMPH0_G0,	0x0C45 },
+		{ AUD_DEEMPH0_A0,	0x6262 },
+		{ AUD_DEEMPH0_B0,	0x1C29 },
+		{ AUD_DEEMPH0_A1,	0x3FC66},
+		{ AUD_DEEMPH0_B1,	0x399A },
 
-			cx_write(AUD_DEEMPH1_G0, 0x0D80);
-			cx_write(AUD_DEEMPH1_A0, 0x6262);
-			cx_write(AUD_DEEMPH1_B0, 0x1C29);
-			cx_write(AUD_DEEMPH1_A1, 0x3FC66);
-			cx_write(AUD_DEEMPH1_B1, 0x399A);
+		{ AUD_DEEMPH1_G0,	0x0D80 },
+		{ AUD_DEEMPH1_A0,	0x6262 },
+		{ AUD_DEEMPH1_B0,	0x1C29 },
+		{ AUD_DEEMPH1_A1,	0x3FC66},
+		{ AUD_DEEMPH1_B1,	0x399A},
 
-			break;
+		{ AUD_POLYPH80SCALEFAC,	0x0003},
+		{ /* end of list */ },
+	};
+	static const struct rlist fm_deemph_75[] = {
+		{ AUD_DEEMPH0_G0,	0x091B },
+		{ AUD_DEEMPH0_A0,	0x6B68 },
+		{ AUD_DEEMPH0_B0,	0x11EC },
+		{ AUD_DEEMPH0_A1,	0x3FC66},
+		{ AUD_DEEMPH0_B1,	0x399A },
 
-		case WW_FM_DEEMPH_75:
-			//Set De-emphasis filter coefficients for 75 usec
-			cx_write(AUD_DEEMPH0_G0, 0x91B );
-			cx_write(AUD_DEEMPH0_A0, 0x6B68);
-			cx_write(AUD_DEEMPH0_B0, 0x11EC);
-			cx_write(AUD_DEEMPH0_A1, 0x3FC66);
-			cx_write(AUD_DEEMPH0_B1, 0x399A);
+		{ AUD_DEEMPH1_G0,	0x0AA0 },
+		{ AUD_DEEMPH1_A0,	0x6B68 },
+		{ AUD_DEEMPH1_B0,	0x11EC },
+		{ AUD_DEEMPH1_A1,	0x3FC66},
+		{ AUD_DEEMPH1_B1,	0x399A},
 
-			cx_write(AUD_DEEMPH1_G0, 0xAA0 );
-			cx_write(AUD_DEEMPH1_A0, 0x6B68);
-			cx_write(AUD_DEEMPH1_B0, 0x11EC);
-			cx_write(AUD_DEEMPH1_A1, 0x3FC66);
-			cx_write(AUD_DEEMPH1_B1, 0x399A);
+		{ AUD_POLYPH80SCALEFAC,	0x0003},
+		{ /* end of list */ },
+	};
 
-			break;
-	}
-#endif
+	/* It is enough to leave default values? */
+	static const struct rlist fm_no_deemph[] = {
+
+		{ AUD_POLYPH80SCALEFAC,	0x0003},
+		{ /* end of list */ },
+	};
 
 	dprintk("%s (status: unknown)\n",__FUNCTION__);
 	set_audio_start(core, 0x0020, EN_FMRADIO_AUTO_STEREO);
 
-	// AB: 10/2/01: this register is not being reset appropriately on occasion.
-	cx_write(AUD_POLYPH80SCALEFAC,3);
+	switch (deemph)
+	{
+		case FM_NO_DEEMPH:
+			set_audio_registers(core, fm_no_deemph);
+			break;
+
+		case FM_DEEMPH_50:
+			set_audio_registers(core, fm_deemph_50);
+			break;
+
+		case FM_DEEMPH_75:
+			set_audio_registers(core, fm_deemph_75);
+			break;
+	}
 
 	set_audio_finish(core);
 }
@@ -778,7 +800,7 @@
 		set_audio_standard_EIAJ(core);
 		break;
 	case WW_FM:
-		set_audio_standard_FM(core);
+		set_audio_standard_FM(core,FM_NO_DEEMPH);
 		break;
 	case WW_SYSTEM_L_AM:
 		set_audio_standard_NICAM_L(core, 1);
@@ -1029,4 +1051,5 @@
  * Local variables:
  * c-basic-offset: 8
  * End:
+ * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
  */
diff --git a/drivers/media/video/cx88/cx88-vbi.c b/drivers/media/video/cx88/cx88-vbi.c
index 0584ff4..320d578 100644
--- a/drivers/media/video/cx88/cx88-vbi.c
+++ b/drivers/media/video/cx88/cx88-vbi.c
@@ -1,5 +1,5 @@
 /*
- * $Id: cx88-vbi.c,v 1.16 2004/12/10 12:33:39 kraxel Exp $
+ * $Id: cx88-vbi.c,v 1.17 2005/06/12 04:19:19 mchehab Exp $
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -47,8 +47,8 @@
 }
 
 static int cx8800_start_vbi_dma(struct cx8800_dev    *dev,
-				struct cx88_dmaqueue *q,
-				struct cx88_buffer   *buf)
+			 struct cx88_dmaqueue *q,
+			 struct cx88_buffer   *buf)
 {
 	struct cx88_core *core = dev->core;
 
diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c
index d1f5c92..e4ca735 100644
--- a/drivers/media/video/cx88/cx88-video.c
+++ b/drivers/media/video/cx88/cx88-video.c
@@ -1,5 +1,5 @@
 /*
- * $Id: cx88-video.c,v 1.58 2005/03/07 15:58:05 kraxel Exp $
+ * $Id: cx88-video.c,v 1.63 2005/06/12 04:19:19 mchehab Exp $
  *
  * device driver for Conexant 2388x based TV cards
  * video4linux video interface
@@ -1187,9 +1187,24 @@
 		.id    = V4L2_CID_AUDIO_VOLUME,
 		.value = 0x3f,
 	};
+	static struct v4l2_control hue = {
+		.id    = V4L2_CID_HUE,
+		.value = 0x80,
+	};
+	static struct v4l2_control contrast = {
+		.id    = V4L2_CID_CONTRAST,
+		.value = 0x80,
+	};
+	static struct v4l2_control brightness = {
+		.id    = V4L2_CID_BRIGHTNESS,
+		.value = 0x80,
+	};
 
 	set_control(dev,&mute);
 	set_control(dev,&volume);
+	set_control(dev,&hue);
+	set_control(dev,&contrast);
+	set_control(dev,&brightness);
 }
 
 /* ------------------------------------------------------------------ */
@@ -1336,6 +1351,9 @@
 			V4L2_CAP_STREAMING     |
 			V4L2_CAP_VBI_CAPTURE   |
 #if 0
+			V4L2_TUNER_CAP_LOW     |
+#endif
+#if 0
 			V4L2_CAP_VIDEO_OVERLAY |
 #endif
 			0;
@@ -1696,7 +1714,11 @@
 			sizeof(cap->card));
 		sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci));
 		cap->version = CX88_VERSION_CODE;
-		cap->capabilities = V4L2_CAP_TUNER;
+		cap->capabilities = V4L2_CAP_TUNER
+#if 0
+				    | V4L2_TUNER_CAP_LOW
+#endif
+				    ;
 		return 0;
 	}
 	case VIDIOC_G_TUNER:
@@ -1992,6 +2014,7 @@
 {
 	struct cx8800_dev *dev;
 	struct cx88_core *core;
+	struct tuner_addr tun_addr;
 	int err;
 
 	dev = kmalloc(sizeof(*dev),GFP_KERNEL);
@@ -2065,8 +2088,19 @@
 		request_module("tuner");
 	if (core->tda9887_conf)
 		request_module("tda9887");
-	if (core->tuner_type != UNSET)
-		cx88_call_i2c_clients(dev->core,TUNER_SET_TYPE,&core->tuner_type);
+	if (core->radio_type != UNSET) {
+	        tun_addr.v4l2_tuner = V4L2_TUNER_RADIO;
+		tun_addr.type = core->radio_type;
+		tun_addr.addr = core->radio_addr;
+		cx88_call_i2c_clients(dev->core,TUNER_SET_TYPE_ADDR, &tun_addr);
+	}
+	if (core->tuner_type != UNSET) {
+	        tun_addr.v4l2_tuner = V4L2_TUNER_ANALOG_TV;
+		tun_addr.type = core->tuner_type;
+		tun_addr.addr = core->tuner_addr;
+		cx88_call_i2c_clients(dev->core,TUNER_SET_TYPE_ADDR, &tun_addr);
+	}
+
 	if (core->tda9887_conf)
 		cx88_call_i2c_clients(dev->core,TDA9887_SET_CONFIG,&core->tda9887_conf);
 
@@ -2162,7 +2196,7 @@
 
 static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state)
 {
-        struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
+	struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
 	struct cx88_core *core = dev->core;
 
 	/* stop video+vbi capture */
@@ -2194,7 +2228,7 @@
 
 static int cx8800_resume(struct pci_dev *pci_dev)
 {
-        struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
+	struct cx8800_dev *dev = pci_get_drvdata(pci_dev);
 	struct cx88_core *core = dev->core;
 
 	if (dev->state.disabled) {
@@ -2230,8 +2264,8 @@
 	{
 		.vendor       = 0x14f1,
 		.device       = 0x8800,
-                .subvendor    = PCI_ANY_ID,
-                .subdevice    = PCI_ANY_ID,
+		.subvendor    = PCI_ANY_ID,
+		.subdevice    = PCI_ANY_ID,
 	},{
 		/* --- end of list --- */
 	}
@@ -2239,10 +2273,10 @@
 MODULE_DEVICE_TABLE(pci, cx8800_pci_tbl);
 
 static struct pci_driver cx8800_pci_driver = {
-        .name     = "cx8800",
-        .id_table = cx8800_pci_tbl,
-        .probe    = cx8800_initdev,
-        .remove   = __devexit_p(cx8800_finidev),
+	.name     = "cx8800",
+	.id_table = cx8800_pci_tbl,
+	.probe    = cx8800_initdev,
+	.remove   = __devexit_p(cx8800_finidev),
 
 	.suspend  = cx8800_suspend,
 	.resume   = cx8800_resume,
@@ -2274,4 +2308,5 @@
  * Local variables:
  * c-basic-offset: 8
  * End:
+ * kate: eol "unix"; indent-width 3; remove-trailing-space on; replace-trailing-space-save on; tab-width 8; replace-tabs off; space-indent off; mixed-indent off
  */
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
index 88eaaab..867e988 100644
--- a/drivers/media/video/cx88/cx88.h
+++ b/drivers/media/video/cx88/cx88.h
@@ -1,5 +1,5 @@
 /*
- * $Id: cx88.h,v 1.56 2005/03/04 09:12:23 kraxel Exp $
+ * $Id: cx88.h,v 1.62 2005/06/12 04:19:19 mchehab Exp $
  *
  * v4l2 device driver for cx2388x based TV cards
  *
@@ -64,6 +64,13 @@
 #define SHADOW_AUD_BAL_CTL           2
 #define SHADOW_MAX                   2
 
+/* FM Radio deemphasis type */
+enum cx88_deemph_type {
+	FM_NO_DEEMPH = 0,
+	FM_DEEMPH_50,
+	FM_DEEMPH_75
+};
+
 /* ----------------------------------------------------------- */
 /* tv norms                                                    */
 
@@ -162,6 +169,8 @@
 #define CX88_BOARD_HAUPPAUGE_ROSLYN        24
 #define CX88_BOARD_DIGITALLOGIC_MEC	       25
 #define CX88_BOARD_IODATA_GVBCTV7E         26
+#define CX88_BOARD_PIXELVIEW_PLAYTV_ULTRA_PRO 27
+#define CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T  28
 
 enum cx88_itype {
 	CX88_VMUX_COMPOSITE1 = 1,
@@ -185,6 +194,9 @@
 struct cx88_board {
 	char                    *name;
 	unsigned int            tuner_type;
+	unsigned int		radio_type;
+	unsigned char		tuner_addr;
+	unsigned char		radio_addr;
 	int                     tda9887_conf;
 	struct cx88_input       input[8];
 	struct cx88_input       radio;
@@ -255,6 +267,9 @@
 	/* config info -- analog */
 	unsigned int               board;
 	unsigned int               tuner_type;
+	unsigned int               radio_type;
+	unsigned char              tuner_addr;
+	unsigned char              radio_addr;
 	unsigned int               tda9887_conf;
 	unsigned int               has_radio;
 
@@ -471,6 +486,11 @@
 /* cx88-vbi.c                                                  */
 
 void cx8800_vbi_fmt(struct cx8800_dev *dev, struct v4l2_format *f);
+/*
+int cx8800_start_vbi_dma(struct cx8800_dev    *dev,
+			 struct cx88_dmaqueue *q,
+			 struct cx88_buffer   *buf);
+*/
 int cx8800_stop_vbi_dma(struct cx8800_dev *dev);
 int cx8800_restart_vbi_queue(struct cx8800_dev    *dev,
 			     struct cx88_dmaqueue *q);
diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c
index ab6620d..a565823 100644
--- a/drivers/media/video/ir-kbd-gpio.c
+++ b/drivers/media/video/ir-kbd-gpio.c
@@ -1,5 +1,5 @@
 /*
- * $Id: ir-kbd-gpio.c,v 1.12 2005/02/22 12:28:40 kraxel Exp $
+ * $Id: ir-kbd-gpio.c,v 1.13 2005/05/15 19:01:26 mchehab Exp $
  *
  * Copyright (c) 2003 Gerd Knorr
  * Copyright (c) 2003 Pavel Machek
@@ -114,38 +114,6 @@
 	[ 0x3e ] = KEY_VOLUMEUP,    // 'volume +'
 };
 
-static IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE] = {
-	[  2 ] = KEY_KP0,
-	[  1 ] = KEY_KP1,
-	[ 11 ] = KEY_KP2,
-	[ 27 ] = KEY_KP3,
-	[  5 ] = KEY_KP4,
-	[  9 ] = KEY_KP5,
-	[ 21 ] = KEY_KP6,
-	[  6 ] = KEY_KP7,
-	[ 10 ] = KEY_KP8,
-	[ 18 ] = KEY_KP9,
-
-	[  3 ] = KEY_TUNER,       // TV/FM
-	[  7 ] = KEY_SEARCH,      // scan
-	[ 28 ] = KEY_ZOOM,        // full screen
-	[ 30 ] = KEY_POWER,
-	[ 23 ] = KEY_VOLUMEDOWN,
-	[ 31 ] = KEY_VOLUMEUP,
-	[ 20 ] = KEY_CHANNELDOWN,
-	[ 22 ] = KEY_CHANNELUP,
-	[ 24 ] = KEY_MUTE,
-
-	[  0 ] = KEY_LIST,        // source
-	[ 19 ] = KEY_INFO,        // loop
-	[ 16 ] = KEY_LAST,        // +100
-	[ 13 ] = KEY_CLEAR,       // reset
-	[ 12 ] = BTN_RIGHT,       // fun++
-	[  4 ] = BTN_LEFT,        // fun--
-	[ 14 ] = KEY_GOTO,        // function
-	[ 15 ] = KEY_STOP,         // freeze
-};
-
 /* Attila Kondoros <attila.kondoros@chello.hu> */
 static IR_KEYTAB_TYPE ir_codes_apac_viewcomp[IR_KEYTAB_SIZE] = {
 
diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c
index 7fbb858..b4ee9df 100644
--- a/drivers/media/video/msp3400.c
+++ b/drivers/media/video/msp3400.c
@@ -147,7 +147,6 @@
 	I2C_MSP3400C_ALT  >> 1,
 	I2C_CLIENT_END
 };
-static unsigned short normal_i2c_range[] = {I2C_CLIENT_END,I2C_CLIENT_END};
 I2C_CLIENT_INSMOD;
 
 /* ----------------------------------------------------------------------- */
@@ -736,7 +735,6 @@
 {
 	DECLARE_WAITQUEUE(wait, current);
 
-again:
 	add_wait_queue(&msp->wq, &wait);
 	if (!kthread_should_stop()) {
 		if (timeout < 0) {
@@ -752,12 +750,8 @@
 #endif
 		}
 	}
-
+	try_to_freeze();
 	remove_wait_queue(&msp->wq, &wait);
-
-	if (try_to_freeze(PF_FREEZE))
-		goto again;
-
 	return msp->restart;
 }
 
@@ -1437,7 +1431,7 @@
 static int msp_probe(struct i2c_adapter *adap);
 static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg);
 
-static int msp_suspend(struct device * dev, pm_message_t state, u32 level);
+static int msp_suspend(struct device * dev, u32 state, u32 level);
 static int msp_resume(struct device * dev, u32 level);
 
 static void msp_wake_thread(struct i2c_client *client);
@@ -1842,7 +1836,7 @@
 	return 0;
 }
 
-static int msp_suspend(struct device * dev, pm_message_t state, u32 level)
+static int msp_suspend(struct device * dev, u32 state, u32 level)
 {
 	struct i2c_client *c = container_of(dev, struct i2c_client, dev);
 
diff --git a/drivers/media/video/msp3400.h b/drivers/media/video/msp3400.h
index d70a954..023f330 100644
--- a/drivers/media/video/msp3400.h
+++ b/drivers/media/video/msp3400.h
@@ -1,3 +1,7 @@
+/*
+ * $Id: msp3400.h,v 1.3 2005/06/12 04:19:19 mchehab Exp $
+ */
+
 #ifndef MSP3400_H
 #define MSP3400_H
 
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c
index ba69f09..b8054da 100644
--- a/drivers/media/video/saa5246a.c
+++ b/drivers/media/video/saa5246a.c
@@ -64,7 +64,6 @@
 
 /* Addresses to scan */
 static unsigned short normal_i2c[]	 = { I2C_ADDRESS, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 I2C_CLIENT_INSMOD;
 
 static struct i2c_client client_template;
diff --git a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c
index d74caa1..7ffa2e9 100644
--- a/drivers/media/video/saa5249.c
+++ b/drivers/media/video/saa5249.c
@@ -132,7 +132,6 @@
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = {34>>1,I2C_CLIENT_END};
-static unsigned short normal_i2c_range[] = {I2C_CLIENT_END};
 I2C_CLIENT_INSMOD;
 
 static struct i2c_client client_template;
diff --git a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c
index 64273b4..22d055d 100644
--- a/drivers/media/video/saa7110.c
+++ b/drivers/media/video/saa7110.c
@@ -463,22 +463,14 @@
 	(I2C_SAA7110 >> 1) + 1,
 	I2C_CLIENT_END
 };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
                                                                                 
 static struct i2c_client_address_data addr_data = {
 	.normal_i2c		= normal_i2c,
-	.normal_i2c_range	= normal_i2c_range,
-	.probe			= probe,
-	.probe_range		= probe_range,
-	.ignore			= ignore,
-	.ignore_range		= ignore_range,
-	.force			= force
+	.probe			= &ignore,
+	.ignore			= &ignore,
+	.force			= &ignore,
 };
 
 static struct i2c_driver i2c_driver_saa7110;
diff --git a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
index 0a87311..fcd8973 100644
--- a/drivers/media/video/saa7111.c
+++ b/drivers/media/video/saa7111.c
@@ -482,22 +482,14 @@
  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
  */
 static unsigned short normal_i2c[] = { I2C_SAA7111 >> 1, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
                                                                                 
 static struct i2c_client_address_data addr_data = {
 	.normal_i2c		= normal_i2c,
-	.normal_i2c_range	= normal_i2c_range,
-	.probe			= probe,
-	.probe_range		= probe_range,
-	.ignore			= ignore,
-	.ignore_range		= ignore_range,
-	.force			= force
+	.probe			= &ignore,
+	.ignore			= &ignore,
+	.force			= &ignore,
 };
 
 static struct i2c_driver i2c_driver_saa7111;
diff --git a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c
index e730236..2ba997f 100644
--- a/drivers/media/video/saa7114.c
+++ b/drivers/media/video/saa7114.c
@@ -820,22 +820,14 @@
  */
 static unsigned short normal_i2c[] =
     { I2C_SAA7114 >> 1, I2C_SAA7114A >> 1, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
                                                                                 
 static struct i2c_client_address_data addr_data = {
 	.normal_i2c		= normal_i2c,
-	.normal_i2c_range	= normal_i2c_range,
-	.probe			= probe,
-	.probe_range		= probe_range,
-	.ignore			= ignore,
-	.ignore_range		= ignore_range,
-	.force			= force
+	.probe			= &ignore,
+	.ignore			= &ignore,
+	.force			= &ignore,
 };
 
 static struct i2c_driver i2c_driver_saa7114;
diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c
index 1db0226..e6d0a18 100644
--- a/drivers/media/video/saa7134/saa6752hs.c
+++ b/drivers/media/video/saa7134/saa6752hs.c
@@ -22,7 +22,6 @@
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = {0x20, I2C_CLIENT_END};
-static unsigned short normal_i2c_range[] = {I2C_CLIENT_END};
 I2C_CLIENT_INSMOD;
 
 MODULE_DESCRIPTION("device driver for saa6752hs MPEG2 encoder");
@@ -42,16 +41,16 @@
 
 static const struct v4l2_format v4l2_format_table[] =
 {
-	[SAA6752HS_VF_D1] = {
-		.fmt = { .pix = { .width = 720, .height = 576 }, }, },
-	[SAA6752HS_VF_2_3_D1] = {
-		.fmt = { .pix = { .width = 480, .height = 576 }, }, },
-	[SAA6752HS_VF_1_2_D1] = {
-		.fmt = { .pix = { .width = 352, .height = 576 }, }, },
-	[SAA6752HS_VF_SIF] = {
-		.fmt = { .pix = { .width = 352, .height = 288 }, }, },
-	[SAA6752HS_VF_UNKNOWN] = {
-		.fmt = { .pix = { .width = 0, .height = 0 }, }, },
+	[SAA6752HS_VF_D1] =
+		{ .fmt = { .pix = { .width = 720, .height = 576 }}},
+	[SAA6752HS_VF_2_3_D1] =
+		{ .fmt = { .pix = { .width = 480, .height = 576 }}},
+	[SAA6752HS_VF_1_2_D1] =
+		{ .fmt = { .pix = { .width = 352, .height = 576 }}},
+	[SAA6752HS_VF_SIF] =
+		{ .fmt = { .pix = { .width = 352, .height = 288 }}},
+	[SAA6752HS_VF_UNKNOWN] =
+		{ .fmt = { .pix = { .width = 0, .height = 0}}},
 };
 
 struct saa6752hs_state {
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c
index c51eb7f..0c781e2 100644
--- a/drivers/media/video/saa7134/saa7134-cards.c
+++ b/drivers/media/video/saa7134/saa7134-cards.c
@@ -1,6 +1,6 @@
 
 /*
- * $Id: saa7134-cards.c,v 1.54 2005/03/07 12:01:51 kraxel Exp $
+ * $Id: saa7134-cards.c,v 1.58 2005/06/07 18:05:00 nsh Exp $
  *
  * device driver for philips saa7134 based TV cards
  * card-specific stuff.
@@ -165,7 +165,7 @@
 		.inputs         = {{
 			.name = name_tv,
 			.vmux = 1,
-			.amux = LINE2,
+			.amux = TV,
 			.tv   = 1,
 		},{
 			.name = name_comp1,
@@ -878,7 +878,7 @@
         },
 	[SAA7134_BOARD_MANLI_MTV002] = {
 		/* Ognjen Nastic <ognjen@logosoft.ba> */
-		.name           = "Manli MuchTV M-TV002",
+		.name           = "Manli MuchTV M-TV002/Behold TV 403 FM",
 		.audio_clock    = 0x00200000,
 		.tuner_type     = TUNER_PHILIPS_PAL,
 		.inputs         = {{
@@ -899,14 +899,10 @@
 			.name = name_radio,
 			.amux = LINE2,
 		},
-		.mute = {
-			.name = name_mute,
-                        .amux = LINE1,
-		},
 	},
 	[SAA7134_BOARD_MANLI_MTV001] = {
 		/* Ognjen Nastic <ognjen@logosoft.ba> UNTESTED */
-		.name           = "Manli MuchTV M-TV001",
+		.name           = "Manli MuchTV M-TV001/Behold TV 401",
 		.audio_clock    = 0x00200000,
 		.tuner_type     = TUNER_PHILIPS_PAL,
 		.inputs         = {{
@@ -923,6 +919,10 @@
 			.amux = LINE2,
 			.tv   = 1,
 		}},
+		.mute = {
+			.name = name_mute,
+                        .amux = LINE1,
+		},
         },
 	[SAA7134_BOARD_TG3000TV] = {
 		/* TransGear 3000TV */
@@ -1078,7 +1078,6 @@
 		.audio_clock    = 0x00187de7,
 		.tuner_type     = TUNER_PHILIPS_FM1256_IH3,
 		.tda9887_conf   = TDA9887_PRESENT,
-		.gpiomask = 0x3,
 		.inputs         = {{
 			.name = name_tv,
 			.vmux = 1,
@@ -1285,7 +1284,7 @@
 			 .gpio =0x8000,
 		 }
 	},
-        [SAA7134_BOARD_AVERMEDIA_307] = {
+        [SAA7134_BOARD_AVERMEDIA_STUDIO_307] = {
 		/*
 		Nickolay V. Shmyrev <nshmyrev@yandex.ru>
 		Lots of thanks to Andrey Zolotarev <zolotarev_andrey@mail.ru>
@@ -1323,6 +1322,35 @@
 			.gpio = 0x01,
 		},
         },
+        [SAA7134_BOARD_AVERMEDIA_GO_007_FM] = {
+		.name           = "Avermedia AVerTV GO 007 FM",
+		.audio_clock    = 0x00187de7,
+		.tuner_type     = TUNER_PHILIPS_TDA8290,
+		.gpiomask       = 0x00300003,
+//		.gpiomask       = 0x8c240003,
+		.inputs         = {{
+			.name = name_tv,
+			.vmux = 1,
+			.amux = TV,
+			.tv   = 1,
+			.gpio = 0x01,
+		},{
+			.name = name_comp1,
+			.vmux = 0,
+			.amux = LINE2,
+			.gpio = 0x02,
+		},{
+			.name = name_svideo,
+			.vmux = 6,
+			.amux = LINE2,
+			.gpio = 0x02,
+		}},
+		.radio = {
+			.name = name_radio,
+			.amux = LINE1,
+			.gpio = 0x00300001,
+		},
+        },
 	[SAA7134_BOARD_AVERMEDIA_CARDBUS] = {
 		/* Jon Westgate <oryn@oryn.fsck.tv> */
 		.name           = "AVerMedia Cardbus TV/Radio",
@@ -1492,7 +1520,6 @@
 		.audio_clock    = 0x00187de7,
 		.tuner_type     = TUNER_PHILIPS_FQ1216ME,
 		.tda9887_conf   = TDA9887_PRESENT,
-		.gpiomask = 0x3,
 		.inputs         = {{
 			.name = name_tv,
 			.vmux = 1,
@@ -1546,7 +1573,82 @@
 //			.gpio = 0x4000,
 		}},
 	},
-};
+        [SAA7134_BOARD_AVERMEDIA_307] = {
+               /*
+                 Davydov Vladimir <vladimir@iqmedia.com>
+               */
+               .name           = "Avermedia AVerTV 307",
+               .audio_clock    = 0x00187de7,
+               .tuner_type     = TUNER_PHILIPS_FQ1216ME,
+               .tda9887_conf   = TDA9887_PRESENT,
+               .inputs         = {{
+                       .name = name_tv,
+                       .vmux = 1,
+                       .amux = TV,
+                       .tv   = 1,
+               },{
+                       .name = name_comp1,
+                       .vmux = 0,
+                       .amux = LINE1,
+               },{
+                       .name = name_comp2,
+                       .vmux = 3,
+                       .amux = LINE1,
+               },{
+                       .name = name_svideo,
+                       .vmux = 8,
+                       .amux = LINE1,
+               }},
+        },
+	[SAA7134_BOARD_ADS_INSTANT_TV] = {
+                .name           = "ADS Tech Instant TV (saa7135)",
+		.audio_clock    = 0x00187de7,
+                .tuner_type     = TUNER_PHILIPS_TDA8290,
+                .inputs         = {{
+                        .name = name_tv,
+                        .vmux = 1,
+                        .amux = TV,
+                        .tv   = 1,
+                },{
+                        .name = name_comp1,
+                        .vmux = 3,
+                        .amux = LINE2,
+                },{
+                        .name = name_svideo,
+                        .vmux = 8,
+                        .amux = LINE2,
+                }},
+	},
+ 	[SAA7134_BOARD_KWORLD_VSTREAM_XPERT] = {
+ 		.name           = "Kworld/Tevion V-Stream Xpert TV PVR7134",
+ 		.audio_clock    = 0x00187de7,
+ 		.tuner_type     = TUNER_PHILIPS_PAL_I,
+ 		.gpiomask	= 0x0700,
+ 		.inputs = {{
+ 			.name   = name_tv,
+ 			.vmux   = 1,
+ 			.amux   = TV,
+ 			.tv     = 1,
+ 			.gpio   = 0x000,
+ 		},{
+ 			.name   = name_comp1,
+ 			.vmux   = 3,
+ 			.amux   = LINE1,
+ 			.gpio   = 0x200,		//gpio by DScaler
+ 		},{
+ 			.name   = name_svideo,
+ 			.vmux   = 0,
+ 			.amux   = LINE1,
+ 			.gpio   = 0x200,
+ 		}},
+ 		.radio = {
+ 			.name   = name_radio,
+ 			.amux   = LINE1,
+ 			.gpio   = 0x100,
+ 		},
+ 	},
+ };
+
 const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards);
 
 /* ------------------------------------------------------------------ */
@@ -1663,7 +1765,7 @@
                 .driver_data  = SAA7134_BOARD_ASUSTeK_TVFM7134,
 	},{
                 .vendor       = PCI_VENDOR_ID_PHILIPS,
-                .device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+                .device       = PCI_DEVICE_ID_PHILIPS_SAA7135,
                 .subvendor    = PCI_VENDOR_ID_ASUSTEK,
                 .subdevice    = 0x4845,
                 .driver_data  = SAA7135_BOARD_ASUSTeK_TVFM7135,
@@ -1824,6 +1926,12 @@
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
 		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
 		.subdevice    = 0x9715,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_STUDIO_307,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0xa70a,
 		.driver_data  = SAA7134_BOARD_AVERMEDIA_307,
 	},{
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
@@ -1844,6 +1952,26 @@
 		.subvendor    = 0x5168,
 		.subdevice    = 0x0306,
 		.driver_data  = SAA7134_BOARD_FLYDVBTDUO,
+	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
+		.subvendor    = 0x1461, /* Avermedia Technologies Inc */
+		.subdevice    = 0xf31f,
+		.driver_data  = SAA7134_BOARD_AVERMEDIA_GO_007_FM,
+
+ 	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7135,
+		.subvendor    = 0x1421,
+		.subdevice    = 0x0350,		/* PCI version */
+		.driver_data  = SAA7134_BOARD_ADS_INSTANT_TV,
+
+ 	},{
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7135,
+		.subvendor    = 0x1421,
+		.subdevice    = 0x0370,		/* cardbus version */
+		.driver_data  = SAA7134_BOARD_ADS_INSTANT_TV,
 
  	},{
 		/* --- boards without eeprom + subsystem ID --- */
@@ -1954,20 +2082,23 @@
 		dev->has_remote = 1;
 		board_flyvideo(dev);
 		break;
-	case SAA7134_BOARD_FLYTVPLATINUM_FM:
+        case SAA7134_BOARD_FLYTVPLATINUM_FM:
 	case SAA7134_BOARD_CINERGY400:
 	case SAA7134_BOARD_CINERGY600:
 	case SAA7134_BOARD_CINERGY600_MK3:
 	case SAA7134_BOARD_ECS_TVP3XP:
 	case SAA7134_BOARD_ECS_TVP3XP_4CB5:
 	case SAA7134_BOARD_MD2819:
+	case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
 	case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
 	case SAA7134_BOARD_AVERMEDIA_305:
+	case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
 	case SAA7134_BOARD_AVERMEDIA_307:
+	case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
 //	case SAA7134_BOARD_SABRENT_SBTTVFM:  /* not finished yet */
 	case SAA7134_BOARD_VIDEOMATE_TV_PVR:
-		dev->has_remote = 1;
-		break;
+ 	case SAA7134_BOARD_MANLI_MTV001:
+ 	case SAA7134_BOARD_MANLI_MTV002:
 	case SAA7134_BOARD_AVACSSMARTTV:
 		dev->has_remote = 1;
 		break;
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c
index d506caf..f61ed18 100644
--- a/drivers/media/video/saa7134/saa7134-core.c
+++ b/drivers/media/video/saa7134/saa7134-core.c
@@ -1,5 +1,5 @@
 /*
- * $Id: saa7134-core.c,v 1.28 2005/02/22 09:56:29 kraxel Exp $
+ * $Id: saa7134-core.c,v 1.30 2005/05/22 19:23:39 nsh Exp $
  *
  * device driver for philips saa7134 based TV cards
  * driver core
@@ -316,7 +316,7 @@
 
 int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt)
 {
-        u32          *cpu;
+        __le32       *cpu;
         dma_addr_t   dma_addr;
 
 	cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr);
@@ -332,7 +332,7 @@
 			  struct scatterlist *list, unsigned int length,
 			  unsigned int startpage)
 {
-	u32           *ptr;
+	__le32        *ptr;
 	unsigned int  i,p;
 
 	BUG_ON(NULL == pt || NULL == pt->cpu);
@@ -340,7 +340,7 @@
 	ptr = pt->cpu + startpage;
 	for (i = 0; i < length; i++, list++)
 		for (p = 0; p * 4096 < list->length; p++, ptr++)
-			*ptr = sg_dma_address(list) - list->offset;
+			*ptr = cpu_to_le32(sg_dma_address(list) - list->offset);
 	return 0;
 }
 
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c
index c2873ae..aa8e2cf 100644
--- a/drivers/media/video/saa7134/saa7134-dvb.c
+++ b/drivers/media/video/saa7134/saa7134-dvb.c
@@ -1,5 +1,5 @@
 /*
- * $Id: saa7134-dvb.c,v 1.12 2005/02/18 12:28:29 kraxel Exp $
+ * $Id: saa7134-dvb.c,v 1.13 2005/06/12 04:19:19 mchehab Exp $
  *
  * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
  *
diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c
index fa13573..c85348d0 100644
--- a/drivers/media/video/saa7134/saa7134-empress.c
+++ b/drivers/media/video/saa7134/saa7134-empress.c
@@ -1,5 +1,5 @@
 /*
- * $Id: saa7134-empress.c,v 1.10 2005/02/03 10:24:33 kraxel Exp $
+ * $Id: saa7134-empress.c,v 1.11 2005/05/22 19:23:39 nsh Exp $
  *
  * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
  *
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
index 702bb63..b6f002e 100644
--- a/drivers/media/video/saa7134/saa7134-i2c.c
+++ b/drivers/media/video/saa7134/saa7134-i2c.c
@@ -1,5 +1,5 @@
 /*
- * $Id: saa7134-i2c.c,v 1.10 2005/01/24 17:37:23 kraxel Exp $
+ * $Id: saa7134-i2c.c,v 1.11 2005/06/12 01:36:14 mchehab Exp $
  *
  * device driver for philips saa7134 based TV cards
  * i2c interface support
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
index ca50cf5..aba2b9d 100644
--- a/drivers/media/video/saa7134/saa7134-input.c
+++ b/drivers/media/video/saa7134/saa7134-input.c
@@ -1,5 +1,5 @@
 /*
- * $Id: saa7134-input.c,v 1.16 2004/12/10 12:33:39 kraxel Exp $
+ * $Id: saa7134-input.c,v 1.19 2005/06/07 18:02:26 nsh Exp $
  *
  * handle saa7134 IR remotes via linux kernel input layer.
  *
@@ -308,6 +308,102 @@
 	[ 32 ] = KEY_LANGUAGE,
 	[ 33 ] = KEY_SLEEP,
 };
+
+/* Michael Tokarev <mjt@tls.msk.ru>
+   http://www.corpit.ru/mjt/beholdTV/remote_control.jpg
+   keytable is used by MANLI MTV00[12] and BeholdTV 40[13] at
+   least, and probably other cards too.
+   The "ascii-art picture" below (in comments, first row
+   is the keycode in hex, and subsequent row(s) shows
+   the button labels (several variants when appropriate)
+   helps to descide which keycodes to assign to the buttons.
+ */
+static IR_KEYTAB_TYPE manli_codes[IR_KEYTAB_SIZE] = {
+
+	/*  0x1c            0x12  *
+	 * FUNCTION         POWER *
+	 *   FM              (|)  *
+	 *                        */
+	[ 0x1c ] = KEY_RADIO,	/*XXX*/
+	[ 0x12 ] = KEY_POWER,
+
+	/*  0x01    0x02    0x03  *
+	 *   1       2       3    *
+	 *                        *
+	 *  0x04    0x05    0x06  *
+	 *   4       5       6    *
+	 *                        *
+	 *  0x07    0x08    0x09  *
+	 *   7       8       9    *
+	 *                        */
+	[ 0x01 ] = KEY_KP1,
+	[ 0x02 ] = KEY_KP2,
+	[ 0x03 ] = KEY_KP3,
+	[ 0x04 ] = KEY_KP4,
+	[ 0x05 ] = KEY_KP5,
+	[ 0x06 ] = KEY_KP6,
+	[ 0x07 ] = KEY_KP7,
+	[ 0x08 ] = KEY_KP8,
+	[ 0x09 ] = KEY_KP9,
+
+	/*  0x0a    0x00    0x17  *
+	 * RECALL    0      +100  *
+	 *                  PLUS  *
+	 *                        */
+	[ 0x0a ] = KEY_AGAIN,	/*XXX KEY_REWIND? */
+	[ 0x00 ] = KEY_KP0,
+	[ 0x17 ] = KEY_DIGITS,	/*XXX*/
+
+	/*  0x14            0x10  *
+	 *  MENU            INFO  *
+	 *  OSD                   */
+	[ 0x14 ] = KEY_MENU,
+	[ 0x10 ] = KEY_INFO,
+
+	/*          0x0b          *
+	 *           Up           *
+	 *                        *
+	 *  0x18    0x16    0x0c  *
+	 *  Left     Ok     Right *
+	 *                        *
+	 *         0x015          *
+	 *         Down           *
+	 *                        */
+	[ 0x0b ] = KEY_UP,	/*XXX KEY_SCROLLUP? */
+	[ 0x18 ] = KEY_LEFT,	/*XXX KEY_BACK? */
+	[ 0x16 ] = KEY_OK,	/*XXX KEY_SELECT? KEY_ENTER? */
+	[ 0x0c ] = KEY_RIGHT,	/*XXX KEY_FORWARD? */
+	[ 0x15 ] = KEY_DOWN,	/*XXX KEY_SCROLLDOWN? */
+
+	/*  0x11            0x0d  *
+	 *  TV/AV           MODE  *
+	 *  SOURCE         STEREO *
+	 *                        */
+	[ 0x11 ] = KEY_TV,	/*XXX*/
+	[ 0x0d ] = KEY_MODE,	/*XXX there's no KEY_STEREO */
+
+	/*  0x0f    0x1b    0x1a  *
+	 *  AUDIO   Vol+    Chan+ *
+	 *        TIMESHIFT???    *
+	 *                        *
+	 *  0x0e    0x1f    0x1e  *
+	 *  SLEEP   Vol-    Chan- *
+	 *                        */
+	[ 0x0f ] = KEY_AUDIO,
+	[ 0x1b ] = KEY_VOLUMEUP,
+	[ 0x1a ] = KEY_CHANNELUP,
+	[ 0x0e ] = KEY_SLEEP,	/*XXX maybe KEY_PAUSE */
+	[ 0x1f ] = KEY_VOLUMEDOWN,
+	[ 0x1e ] = KEY_CHANNELDOWN,
+
+	/*         0x13     0x19  *
+	 *         MUTE   SNAPSHOT*
+	 *                        */
+	[ 0x13 ] = KEY_MUTE,
+	[ 0x19 ] = KEY_RECORD,	/*XXX*/
+
+	// 0x1d unused ?
+};
 /* ---------------------------------------------------------------------- */
 
 static int build_key(struct saa7134_dev *dev)
@@ -379,7 +475,7 @@
 	switch (dev->board) {
 	case SAA7134_BOARD_FLYVIDEO2000:
 	case SAA7134_BOARD_FLYVIDEO3000:
-	case SAA7134_BOARD_FLYTVPLATINUM_FM:
+        case SAA7134_BOARD_FLYTVPLATINUM_FM:
 		ir_codes     = flyvideo_codes;
 		mask_keycode = 0xEC00000;
 		mask_keydown = 0x0040000;
@@ -405,8 +501,12 @@
 		polling      = 50; // ms
 		break;
 	case SAA7134_BOARD_MD2819:
+	case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
 	case SAA7134_BOARD_AVERMEDIA_305:
 	case SAA7134_BOARD_AVERMEDIA_307:
+	case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
+	case SAA7134_BOARD_AVERMEDIA_STUDIO_307:
+	case SAA7134_BOARD_AVERMEDIA_GO_007_FM:
 		ir_codes     = md2819_codes;
 		mask_keycode = 0x0007C8;
 		mask_keydown = 0x000010;
@@ -415,6 +515,14 @@
 		saa_setb(SAA7134_GPIO_GPMODE0, 0x4);
 		saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4);
 		break;
+	case SAA7134_BOARD_MANLI_MTV001:
+	case SAA7134_BOARD_MANLI_MTV002:
+		ir_codes     = manli_codes;
+		mask_keycode = 0x001f00;
+		mask_keyup   = 0x004000;
+		mask_keydown = 0x002000;
+		polling      = 50; // ms
+		break;
 	case SAA7134_BOARD_VIDEOMATE_TV_PVR:
 		ir_codes     = videomate_tv_pvr_codes;
 		mask_keycode = 0x00003F;
diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c
index 6b6a643..8173290 100644
--- a/drivers/media/video/saa7134/saa7134-oss.c
+++ b/drivers/media/video/saa7134/saa7134-oss.c
@@ -1,5 +1,5 @@
 /*
- * $Id: saa7134-oss.c,v 1.13 2004/12/10 12:33:39 kraxel Exp $
+ * $Id: saa7134-oss.c,v 1.14 2005/05/18 22:45:16 hhackmann Exp $
  *
  * device driver for philips saa7134 based TV cards
  * oss dsp interface
@@ -49,7 +49,6 @@
 
 static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks)
 {
-	blksize &= ~0xff;
 	if (blksize < 0x100)
 		blksize = 0x100;
 	if (blksize > 0x10000)
@@ -57,8 +56,6 @@
 
 	if (blocks < 2)
 		blocks = 2;
-        while ((blksize * blocks) & ~PAGE_MASK)
-		blocks++;
 	if ((blksize * blocks) > 1024*1024)
 		blocks = 1024*1024 / blksize;
 
@@ -79,7 +76,7 @@
 		BUG();
 	videobuf_dma_init(&dev->oss.dma);
 	err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE,
-				       dev->oss.bufsize >> PAGE_SHIFT);
+				       (dev->oss.bufsize + PAGE_SIZE) >> PAGE_SHIFT);
 	if (0 != err)
 		return err;
 	return 0;
@@ -163,10 +160,11 @@
 			fmt |= 0x04;
 		fmt |= (TV == dev->oss.input) ? 0xc0 : 0x80;
 
-		saa_writeb(SAA7134_NUM_SAMPLES0, (dev->oss.blksize & 0x0000ff));
-		saa_writeb(SAA7134_NUM_SAMPLES1, (dev->oss.blksize & 0x00ff00) >>  8);
-		saa_writeb(SAA7134_NUM_SAMPLES2, (dev->oss.blksize & 0xff0000) >> 16);
+		saa_writeb(SAA7134_NUM_SAMPLES0, ((dev->oss.blksize - 1) & 0x0000ff));
+		saa_writeb(SAA7134_NUM_SAMPLES1, ((dev->oss.blksize - 1) & 0x00ff00) >>  8);
+		saa_writeb(SAA7134_NUM_SAMPLES2, ((dev->oss.blksize - 1) & 0xff0000) >> 16);
 		saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt);
+
 		break;
 	case PCI_DEVICE_ID_PHILIPS_SAA7133:
 	case PCI_DEVICE_ID_PHILIPS_SAA7135:
@@ -817,7 +815,7 @@
 			reg = SAA7134_RS_BA1(6);
 	} else {
 		/* even */
-		if (0 == (dev->oss.dma_blk & 0x00))
+		if (1 == (dev->oss.dma_blk & 0x01))
 			reg = SAA7134_RS_BA2(6);
 	}
 	if (0 == reg) {
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c
index ecac13c..3617e7f 100644
--- a/drivers/media/video/saa7134/saa7134-tvaudio.c
+++ b/drivers/media/video/saa7134/saa7134-tvaudio.c
@@ -1,5 +1,5 @@
 /*
- * $Id: saa7134-tvaudio.c,v 1.22 2005/01/07 13:11:19 kraxel Exp $
+ * $Id: saa7134-tvaudio.c,v 1.25 2005/06/07 19:00:38 nsh Exp $
  *
  * device driver for philips saa7134 based TV cards
  * tv audio decoder (fm stereo, nicam, ...)
@@ -181,7 +181,8 @@
 	saa_writeb(SAA7134_AUDIO_CLOCK0,      clock        & 0xff);
 	saa_writeb(SAA7134_AUDIO_CLOCK1,     (clock >>  8) & 0xff);
 	saa_writeb(SAA7134_AUDIO_CLOCK2,     (clock >> 16) & 0xff);
-	saa_writeb(SAA7134_AUDIO_PLL_CTRL,   0x01);
+	// frame locked audio was reported not to be reliable
+	saa_writeb(SAA7134_AUDIO_PLL_CTRL,   0x02);
 
 	saa_writeb(SAA7134_NICAM_ERROR_LOW,  0x14);
 	saa_writeb(SAA7134_NICAM_ERROR_HIGH, 0x50);
@@ -250,6 +251,11 @@
 	saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, ausel);
 	saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, ics);
 	saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x07, ocs);
+	// for oss, we need to change the clock configuration
+	if (in->amux == TV)
+		saa_andorb(SAA7134_SIF_SAMPLE_FREQ,   0x03, 0x00);
+	else
+		saa_andorb(SAA7134_SIF_SAMPLE_FREQ,   0x03, 0x01);
 
 	/* switch gpio-connected external audio mux */
 	if (0 == card(dev).gpiomask)
@@ -439,16 +445,15 @@
 		nicam = saa_readb(SAA7134_NICAM_STATUS);
 		dprintk("getstereo: nicam=0x%x\n",nicam);
 		switch (nicam & 0x0b) {
+		case 0x08:
+			retval = V4L2_TUNER_SUB_MONO;
+			break;
 		case 0x09:
 			retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;
 			break;
 		case 0x0a:
 			retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
 			break;
-		case 0x08:
-		default:
-			retval = V4L2_TUNER_SUB_MONO;
-			break;
 		}
 		break;
 	}
@@ -572,14 +577,14 @@
 		} else if (0 != dev->last_carrier) {
 			/* no carrier -- try last detected one as fallback */
 			carrier = dev->last_carrier;
-			printk(KERN_WARNING "%s/audio: audio carrier scan failed, "
+			dprintk(KERN_WARNING "%s/audio: audio carrier scan failed, "
 			       "using %d.%03d MHz [last detected]\n",
 			       dev->name, carrier/1000, carrier%1000);
 
 		} else {
 			/* no carrier + no fallback -- use default */
 			carrier = default_carrier;
-			printk(KERN_WARNING "%s/audio: audio carrier scan failed, "
+			dprintk(KERN_WARNING "%s/audio: audio carrier scan failed, "
 			       "using %d.%03d MHz [default]\n",
 			       dev->name, carrier/1000, carrier%1000);
 		}
diff --git a/drivers/media/video/saa7134/saa7134-vbi.c b/drivers/media/video/saa7134/saa7134-vbi.c
index 86954cc..3c33c59 100644
--- a/drivers/media/video/saa7134/saa7134-vbi.c
+++ b/drivers/media/video/saa7134/saa7134-vbi.c
@@ -1,5 +1,5 @@
 /*
- * $Id: saa7134-vbi.c,v 1.6 2004/12/10 12:33:39 kraxel Exp $
+ * $Id: saa7134-vbi.c,v 1.7 2005/05/24 23:13:06 nsh Exp $
  *
  * device driver for philips saa7134 based TV cards
  * video4linux video interface
@@ -60,10 +60,10 @@
 	saa_writeb(SAA7134_VBI_H_START2(task), norm->h_start     >> 8);
 	saa_writeb(SAA7134_VBI_H_STOP1(task),  norm->h_stop      &  0xff);
 	saa_writeb(SAA7134_VBI_H_STOP2(task),  norm->h_stop      >> 8);
-	saa_writeb(SAA7134_VBI_V_START1(task), norm->vbi_v_start &  0xff);
-	saa_writeb(SAA7134_VBI_V_START2(task), norm->vbi_v_start >> 8);
-	saa_writeb(SAA7134_VBI_V_STOP1(task),  norm->vbi_v_stop  &  0xff);
-	saa_writeb(SAA7134_VBI_V_STOP2(task),  norm->vbi_v_stop  >> 8);
+	saa_writeb(SAA7134_VBI_V_START1(task), norm->vbi_v_start_0 &  0xff);
+	saa_writeb(SAA7134_VBI_V_START2(task), norm->vbi_v_start_0 >> 8);
+	saa_writeb(SAA7134_VBI_V_STOP1(task),  norm->vbi_v_stop_0  &  0xff);
+	saa_writeb(SAA7134_VBI_V_STOP2(task),  norm->vbi_v_stop_0  >> 8);
 
 	saa_writeb(SAA7134_VBI_H_SCALE_INC1(task),        VBI_SCALE & 0xff);
 	saa_writeb(SAA7134_VBI_H_SCALE_INC2(task),        VBI_SCALE >> 8);
@@ -127,7 +127,7 @@
 	unsigned int lines, llength, size;
 	int err;
 
-	lines   = norm->vbi_v_stop - norm->vbi_v_start +1;
+	lines   = norm->vbi_v_stop_0 - norm->vbi_v_start_0 +1;
 	if (lines > VBI_LINE_COUNT)
 		lines = VBI_LINE_COUNT;
 #if 1
@@ -177,7 +177,7 @@
 	struct saa7134_dev *dev = fh->dev;
 	int llength,lines;
 
-	lines   = dev->tvnorm->vbi_v_stop - dev->tvnorm->vbi_v_start +1;
+	lines   = dev->tvnorm->vbi_v_stop_0 - dev->tvnorm->vbi_v_start_0 +1;
 #if 1
 	llength = VBI_LINE_LENGTH;
 #else
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c
index 5d66060..c0a2ee5 100644
--- a/drivers/media/video/saa7134/saa7134-video.c
+++ b/drivers/media/video/saa7134/saa7134-video.c
@@ -1,5 +1,5 @@
 /*
- * $Id: saa7134-video.c,v 1.28 2005/02/15 15:59:35 kraxel Exp $
+ * $Id: saa7134-video.c,v 1.30 2005/06/07 19:00:38 nsh Exp $
  *
  * device driver for philips saa7134 based TV cards
  * video4linux video interface
@@ -31,8 +31,6 @@
 #include "saa7134-reg.h"
 #include "saa7134.h"
 
-#define V4L2_I2C_CLIENTS 1
-
 /* ------------------------------------------------------------------ */
 
 static unsigned int video_debug   = 0;
@@ -158,18 +156,20 @@
 		.h_stop        = 719,	\
 		.video_v_start = 24,	\
 		.video_v_stop  = 311,	\
-		.vbi_v_start   = 7,	\
-		.vbi_v_stop    = 22,	\
+		.vbi_v_start_0 = 7,	\
+		.vbi_v_stop_0  = 22,	\
+		.vbi_v_start_1 = 319,   \
 		.src_timing    = 4
 
 #define NORM_525_60			\
 		.h_start       = 0,	\
 		.h_stop        = 703,	\
-		.video_v_start = 22,	\
-		.video_v_stop  = 22+239, \
-		.vbi_v_start   = 10, /* FIXME */ \
-		.vbi_v_stop    = 21, /* FIXME */ \
-		.src_timing    = 1
+		.video_v_start = 23,	\
+		.video_v_stop  = 262,	\
+		.vbi_v_start_0 = 10,	\
+		.vbi_v_stop_0  = 21,	\
+		.vbi_v_start_1 = 273,	\
+		.src_timing    = 7
 
 static struct saa7134_tvnorm tvnorms[] = {
 	{
@@ -274,11 +274,12 @@
 
 		.h_start       = 0,
 		.h_stop        = 719,
-		.video_v_start = 22,
-		.video_v_stop  = 22+239,
-		.vbi_v_start   = 10, /* FIXME */
-		.vbi_v_stop    = 21, /* FIXME */
-		.src_timing    = 1,
+		.video_v_start = 23,
+  		.video_v_stop  = 262,
+  		.vbi_v_start_0 = 10,
+  		.vbi_v_stop_0  = 21,
+  		.vbi_v_start_1 = 273,
+  		.src_timing    = 7,
 
 		.sync_control  = 0x18,
 		.luma_control  = 0x40,
@@ -335,8 +336,8 @@
 		.default_value = 0,
 		.type          = V4L2_CTRL_TYPE_INTEGER,
 	},{
-		.id            = V4L2_CID_VFLIP,
-		.name          = "vertical flip",
+		.id            = V4L2_CID_HFLIP,
+		.name          = "Mirror",
 		.minimum       = 0,
 		.maximum       = 1,
 		.type          = V4L2_CTRL_TYPE_BOOLEAN,
@@ -482,7 +483,7 @@
 	dev->crop_bounds.width   = norm->h_stop - norm->h_start +1;
 	dev->crop_defrect.width  = norm->h_stop - norm->h_start +1;
 
-	dev->crop_bounds.top     = (norm->vbi_v_stop+1)*2;
+	dev->crop_bounds.top     = (norm->vbi_v_stop_0+1)*2;
 	dev->crop_defrect.top    = norm->video_v_start*2;
 	dev->crop_bounds.height  = ((norm->id & V4L2_STD_525_60) ? 524 : 624)
 		- dev->crop_bounds.top;
@@ -521,22 +522,7 @@
 	saa_writeb(SAA7134_RAW_DATA_GAIN,         0x40);
 	saa_writeb(SAA7134_RAW_DATA_OFFSET,       0x80);
 
-#ifdef V4L2_I2C_CLIENTS
 	saa7134_i2c_call_clients(dev,VIDIOC_S_STD,&norm->id);
-#else
-	{
-		/* pass down info to the i2c chips (v4l1) */
-		struct video_channel c;
-		memset(&c,0,sizeof(c));
-		c.channel = dev->ctl_input;
-		c.norm = VIDEO_MODE_PAL;
-		if (norm->id & V4L2_STD_NTSC)
-			c.norm = VIDEO_MODE_NTSC;
-		if (norm->id & V4L2_STD_SECAM)
-			c.norm = VIDEO_MODE_SECAM;
-		saa7134_i2c_call_clients(dev,VIDIOCSCHAN,&c);
-	}
-#endif
 }
 
 static void video_mux(struct saa7134_dev *dev, int input)
@@ -1064,7 +1050,7 @@
 	case V4L2_CID_PRIVATE_INVERT:
 		c->value = dev->ctl_invert;
 		break;
-	case V4L2_CID_VFLIP:
+	case V4L2_CID_HFLIP:
 		c->value = dev->ctl_mirror;
 		break;
 	case V4L2_CID_PRIVATE_Y_EVEN:
@@ -1139,7 +1125,7 @@
 		saa_writeb(SAA7134_DEC_CHROMA_SATURATION,
 			   dev->ctl_invert ? -dev->ctl_saturation : dev->ctl_saturation);
 		break;
-	case V4L2_CID_VFLIP:
+	case V4L2_CID_HFLIP:
 		dev->ctl_mirror = c->value;
 		restart_overlay = 1;
 		break;
@@ -1407,9 +1393,9 @@
 	f->fmt.vbi.samples_per_line = 2048 /* VBI_LINE_LENGTH */;
 	f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
 	f->fmt.vbi.offset = 64 * 4;
-	f->fmt.vbi.start[0] = norm->vbi_v_start;
-	f->fmt.vbi.count[0] = norm->vbi_v_stop - norm->vbi_v_start +1;
-	f->fmt.vbi.start[1] = norm->video_v_stop + norm->vbi_v_start +1;
+	f->fmt.vbi.start[0] = norm->vbi_v_start_0;
+	f->fmt.vbi.count[0] = norm->vbi_v_stop_0 - norm->vbi_v_start_0 +1;
+	f->fmt.vbi.start[1] = norm->vbi_v_start_1;
 	f->fmt.vbi.count[1] = f->fmt.vbi.count[0];
 	f->fmt.vbi.flags = 0; /* VBI_UNSYNC VBI_INTERLACED */
 
@@ -1880,11 +1866,9 @@
 			return -EINVAL;
 		down(&dev->lock);
 		dev->ctl_freq = f->frequency;
-#ifdef V4L2_I2C_CLIENTS
+
 		saa7134_i2c_call_clients(dev,VIDIOC_S_FREQUENCY,f);
-#else
-		saa7134_i2c_call_clients(dev,VIDIOCSFREQ,&dev->ctl_freq);
-#endif
+
 		saa7134_tvaudio_do_scan(dev);
 		up(&dev->lock);
 		return 0;
@@ -2139,16 +2123,19 @@
                 t->rangelow  = (int)(65*16);
                 t->rangehigh = (int)(108*16);
 
-#ifdef V4L2_I2C_CLIENTS
-		saa7134_i2c_call_clients(dev,VIDIOC_G_TUNER,t);
-#else
-		{
-			struct video_tuner vt;
-			memset(&vt,0,sizeof(vt));
-			saa7134_i2c_call_clients(dev,VIDIOCGTUNER,&vt);
-			t->signal = vt.signal;
-		}
-#endif
+		saa7134_i2c_call_clients(dev, VIDIOC_G_TUNER, t);
+
+		return 0;
+	}
+	case VIDIOC_S_TUNER:
+	{
+		struct v4l2_tuner *t = arg;
+
+		if (0 != t->index)
+			return -EINVAL;
+
+		saa7134_i2c_call_clients(dev,VIDIOC_S_TUNER,t);
+
 		return 0;
 	}
 	case VIDIOC_ENUMINPUT:
@@ -2182,7 +2169,6 @@
 		return 0;
 	}
 	case VIDIOC_S_AUDIO:
-	case VIDIOC_S_TUNER:
 	case VIDIOC_S_INPUT:
 	case VIDIOC_S_STD:
 		return 0;
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h
index ac90a98..d6b1c0d 100644
--- a/drivers/media/video/saa7134/saa7134.h
+++ b/drivers/media/video/saa7134/saa7134.h
@@ -1,5 +1,5 @@
 /*
- * $Id: saa7134.h,v 1.38 2005/03/07 12:01:51 kraxel Exp $
+ * $Id: saa7134.h,v 1.41 2005/06/07 18:02:26 nsh Exp $
  *
  * v4l2 device driver for philips saa7134 based TV cards
  *
@@ -21,7 +21,7 @@
  */
 
 #include <linux/version.h>
-#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,12)
+#define SAA7134_VERSION_CODE KERNEL_VERSION(0,2,13)
 
 #include <linux/pci.h>
 #include <linux/i2c.h>
@@ -91,9 +91,10 @@
 	unsigned int  h_stop;
 	unsigned int  video_v_start;
 	unsigned int  video_v_stop;
-	unsigned int  vbi_v_start;
-	unsigned int  vbi_v_stop;
+	unsigned int  vbi_v_start_0;
+	unsigned int  vbi_v_stop_0;
 	unsigned int  src_timing;
+	unsigned int  vbi_v_start_1;
 };
 
 struct saa7134_tvaudio {
@@ -167,7 +168,7 @@
 #define SAA7134_BOARD_SABRENT_SBTTVFM  42
 #define SAA7134_BOARD_ZOLID_XPERT_TV7134 43
 #define SAA7134_BOARD_EMPIRE_PCI_TV_RADIO_LE 44
-#define SAA7134_BOARD_AVERMEDIA_307    45
+#define SAA7134_BOARD_AVERMEDIA_STUDIO_307    45
 #define SAA7134_BOARD_AVERMEDIA_CARDBUS 46
 #define SAA7134_BOARD_CINERGY400_CARDBUS 47
 #define SAA7134_BOARD_CINERGY600_MK3   48
@@ -178,6 +179,10 @@
 #define SAA7135_BOARD_ASUSTeK_TVFM7135 53
 #define SAA7134_BOARD_FLYTVPLATINUM_FM 54
 #define SAA7134_BOARD_FLYDVBTDUO 55
+#define SAA7134_BOARD_AVERMEDIA_307    56
+#define SAA7134_BOARD_AVERMEDIA_GO_007_FM 57
+#define SAA7134_BOARD_ADS_INSTANT_TV 58
+#define SAA7134_BOARD_KWORLD_VSTREAM_XPERT 59
 
 #define SAA7134_MAXBOARDS 8
 #define SAA7134_INPUT_MAX 8
@@ -241,7 +246,7 @@
 /* saa7134 page table */
 struct saa7134_pgtable {
 	unsigned int               size;
-	u32                        *cpu;
+	__le32                     *cpu;
 	dma_addr_t                 dma;
 };
 
diff --git a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c
index 5f0b224..108e7a4 100644
--- a/drivers/media/video/saa7185.c
+++ b/drivers/media/video/saa7185.c
@@ -380,22 +380,14 @@
  * concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
  */
 static unsigned short normal_i2c[] = { I2C_SAA7185 >> 1, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
                                                                                 
 static struct i2c_client_address_data addr_data = {
 	.normal_i2c		= normal_i2c,
-	.normal_i2c_range	= normal_i2c_range,
-	.probe			= probe,
-	.probe_range		= probe_range,
-	.ignore			= ignore,
-	.ignore_range		= ignore_range,
-	.force			= force
+	.probe			= &ignore,
+	.ignore			= &ignore,
+	.force			= &ignore,
 };
 
 static struct i2c_driver i2c_driver_saa7185;
diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c
index 376a4a4..07ba6d3 100644
--- a/drivers/media/video/tda7432.c
+++ b/drivers/media/video/tda7432.c
@@ -74,7 +74,6 @@
 	I2C_TDA7432 >> 1,
 	I2C_CLIENT_END,
 };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END, I2C_CLIENT_END };
 I2C_CLIENT_INSMOD;
 
 /* Structure of address and subaddresses for the tda7432 */
diff --git a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c
index b5177c6..c29bdfc 100644
--- a/drivers/media/video/tda9840.c
+++ b/drivers/media/video/tda9840.c
@@ -43,7 +43,6 @@
 
 /* addresses to scan, found only at 0x42 (7-Bit) */
 static unsigned short normal_i2c[] = { I2C_TDA9840, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
 /* magic definition of all other variables and things */
 I2C_CLIENT_INSMOD;
diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c
index 4f1114c..97b113e 100644
--- a/drivers/media/video/tda9875.c
+++ b/drivers/media/video/tda9875.c
@@ -44,7 +44,6 @@
     I2C_TDA9875 >> 1,
     I2C_CLIENT_END
 };
-static unsigned short normal_i2c_range[] = {I2C_CLIENT_END};
 I2C_CLIENT_INSMOD;
 
 /* This is a superset of the TDA9875 */
diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
index debef19..3977363 100644
--- a/drivers/media/video/tda9887.c
+++ b/drivers/media/video/tda9887.c
@@ -33,7 +33,6 @@
 	0x96 >>1,
 	I2C_CLIENT_END,
 };
-static unsigned short normal_i2c_range[] = {I2C_CLIENT_END,I2C_CLIENT_END};
 I2C_CLIENT_INSMOD;
 
 /* insmod options */
@@ -54,6 +53,7 @@
 	unsigned int       config;
 	unsigned int       pinnacle_id;
 	unsigned int       using_v4l2;
+	unsigned int 	   radio_mode;
 };
 
 struct tvnorm {
@@ -213,12 +213,22 @@
 	}
 };
 
-static struct tvnorm radio = {
-	.name = "radio",
+static struct tvnorm radio_stereo = {
+	.name = "Radio Stereo",
+	.b    = ( cFmRadio       |
+		  cQSS           ),
+	.c    = ( cDeemphasisOFF |
+		  cAudioGain6 ),
+	.e    = ( cAudioIF_5_5   |
+		  cRadioIF_38_90 ),
+};
+
+static struct tvnorm radio_mono = {
+	.name = "Radio Mono",
 	.b    = ( cFmRadio       |
 		  cQSS           ),
 	.c    = ( cDeemphasisON  |
-		  cDeemphasis50  ),
+		  cDeemphasis50),
 	.e    = ( cAudioIF_5_5   |
 		  cRadioIF_38_90 ),
 };
@@ -355,7 +365,10 @@
 	int i;
 
 	if (t->radio) {
-		norm = &radio;
+		if (t->radio_mode == V4L2_TUNER_MODE_MONO)
+			norm = &radio_mono;
+		else
+		        norm = &radio_stereo;
 	} else {
 		for (i = 0; i < ARRAY_SIZE(tvnorms); i++) {
 			if (tvnorms[i].std & t->std) {
@@ -546,11 +559,14 @@
 
 	memset(buf,0,sizeof(buf));
 	tda9887_set_tvnorm(t,buf);
+
 	buf[1] |= cOutputPort1Inactive;
 	buf[1] |= cOutputPort2Inactive;
+
 	if (UNSET != t->pinnacle_id) {
 		tda9887_set_pinnacle(t,buf);
 	}
+
 	tda9887_set_config(t,buf);
 	tda9887_set_insmod(t,buf);
 
@@ -593,9 +609,12 @@
         if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL)))
                 return -ENOMEM;
 	memset(t,0,sizeof(*t));
+
 	t->client      = client_template;
 	t->std         = 0;
 	t->pinnacle_id = UNSET;
+	t->radio_mode = V4L2_TUNER_MODE_STEREO;
+
         i2c_set_clientdata(&t->client, t);
         i2c_attach_client(&t->client);
 
@@ -734,6 +753,16 @@
 		}
 		break;
 	}
+	case VIDIOC_S_TUNER:
+	{
+		struct v4l2_tuner* tuner = arg;
+
+		if (t->radio) {
+			t->radio_mode = tuner->audmode;
+			tda9887_configure (t);
+		}
+		break;
+	}
 	default:
 		/* nothing */
 		break;
@@ -741,7 +770,7 @@
 	return 0;
 }
 
-static int tda9887_suspend(struct device * dev, pm_message_t state, u32 level)
+static int tda9887_suspend(struct device * dev, u32 state, u32 level)
 {
 	dprintk("tda9887: suspend\n");
 	return 0;
diff --git a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c
index 3ec3955..b44db8a 100644
--- a/drivers/media/video/tea6415c.c
+++ b/drivers/media/video/tea6415c.c
@@ -43,7 +43,6 @@
 
 /* addresses to scan, found only at 0x03 and/or 0x43 (7-bit) */
 static unsigned short normal_i2c[] = { I2C_TEA6415C_1, I2C_TEA6415C_2, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
 /* magic definition of all other variables and things */
 I2C_CLIENT_INSMOD;
diff --git a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c
index bd10710..48d4db7 100644
--- a/drivers/media/video/tea6420.c
+++ b/drivers/media/video/tea6420.c
@@ -40,7 +40,6 @@
 
 /* addresses to scan, found only at 0x4c and/or 0x4d (7-Bit) */
 static unsigned short normal_i2c[] = { I2C_TEA6420_1, I2C_TEA6420_2, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
 /* magic definition of all other variables and things */
 I2C_CLIENT_INSMOD;
diff --git a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c
index 6b20aa9..51748c6 100644
--- a/drivers/media/video/tuner-3036.c
+++ b/drivers/media/video/tuner-3036.c
@@ -34,19 +34,14 @@
 static struct i2c_client client_template;
 
 /* Addresses to scan */
-static unsigned short normal_i2c[] = {I2C_CLIENT_END};
-static unsigned short normal_i2c_range[] = {0x60, 0x61, I2C_CLIENT_END};
-static unsigned short probe[2]        = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2]  = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2]       = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2]        = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short normal_i2c[] = { 0x60, 0x61, I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
 
 static struct i2c_client_address_data addr_data = {
-	normal_i2c, normal_i2c_range, 
-	probe, probe_range, 
-	ignore, ignore_range, 
-	force
+	.normal_i2c	= normal_i2c,
+	.probe		= &ignore,
+	.ignore		= &ignore,
+	.force		= &ignore,
 };
 
 /* ---------------------------------------------------------------------- */
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
index 6212388e..eaabfc8 100644
--- a/drivers/media/video/tuner-core.c
+++ b/drivers/media/video/tuner-core.c
@@ -1,5 +1,5 @@
 /*
- * $Id: tuner-core.c,v 1.5 2005/02/15 15:59:35 kraxel Exp $
+ * $Id: tuner-core.c,v 1.15 2005/06/12 01:36:14 mchehab Exp $
  *
  * i2c tv tuner chip device driver
  * core core, i.e. kernel interfaces, registering and so on
@@ -23,15 +23,18 @@
 #include <media/tuner.h>
 #include <media/audiochip.h>
 
+/*
+ * comment line bellow to return to old behavor, where only one I2C device is supported
+ */
+#define CONFIG_TUNER_MULTI_I2C /**/
+
 #define UNSET (-1U)
 
 /* standard i2c insmod options */
 static unsigned short normal_i2c[] = {
 	0x4b, /* tda8290 */
-	I2C_CLIENT_END
-};
-static unsigned short normal_i2c_range[] = {
-	0x60, 0x6f,
+	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
 	I2C_CLIENT_END
 };
 I2C_CLIENT_INSMOD;
@@ -55,13 +58,16 @@
 MODULE_LICENSE("GPL");
 
 static int this_adap;
+#ifdef CONFIG_TUNER_MULTI_I2C
+static unsigned short first_tuner, tv_tuner, radio_tuner;
+#endif
 
 static struct i2c_driver driver;
 static struct i2c_client client_template;
 
 /* ---------------------------------------------------------------------- */
 
-// Set tuner frequency,  freq in Units of 62.5kHz = 1/16MHz
+/* Set tuner frequency,  freq in Units of 62.5kHz = 1/16MHz */
 static void set_tv_freq(struct i2c_client *c, unsigned int freq)
 {
 	struct tuner *t = i2c_get_clientdata(c);
@@ -75,14 +81,26 @@
 		return;
 	}
 	if (freq < tv_range[0]*16 || freq > tv_range[1]*16) {
-		/* FIXME: better do that chip-specific, but
-		   right now we don't have that in the config
-		   struct and this way is still better than no
-		   check at all */
-		tuner_info("TV freq (%d.%02d) out of range (%d-%d)\n",
-			   freq/16,freq%16*100/16,tv_range[0],tv_range[1]);
-		return;
+
+		if (freq >= tv_range[0]*16364 && freq <= tv_range[1]*16384) {
+			/* V4L2_TUNER_CAP_LOW frequency */
+
+			tuner_dbg("V4L2_TUNER_CAP_LOW freq selected for TV. Tuners yet doesn't support converting it to valid freq.\n");
+
+			t->tv_freq(c,freq>>10);
+
+			return;
+                } else {
+			/* FIXME: better do that chip-specific, but
+			   right now we don't have that in the config
+			   struct and this way is still better than no
+			   check at all */
+			tuner_info("TV freq (%d.%02d) out of range (%d-%d)\n",
+				   freq/16,freq%16*100/16,tv_range[0],tv_range[1]);
+			return;
+		}
 	}
+	tuner_dbg("62.5 Khz freq step selected for TV.\n");
 	t->tv_freq(c,freq);
 }
 
@@ -99,11 +117,29 @@
 		return;
 	}
 	if (freq < radio_range[0]*16 || freq > radio_range[1]*16) {
-		tuner_info("radio freq (%d.%02d) out of range (%d-%d)\n",
+		if (freq >= tv_range[0]*16364 && freq <= tv_range[1]*16384) {
+			/* V4L2_TUNER_CAP_LOW frequency */
+			if (t->type == TUNER_TEA5767) {
+				tuner_info("radio freq step 62.5Hz (%d.%06d)\n",(freq>>14),freq%(1<<14)*10000);
+				t->radio_freq(c,freq>>10);
+				return;
+			}
+
+			tuner_dbg("V4L2_TUNER_CAP_LOW freq selected for Radio. Tuners yet doesn't support converting it to valid freq.\n");
+
+			tuner_info("radio freq (%d.%06d)\n",(freq>>14),freq%(1<<14)*10000);
+
+			t->radio_freq(c,freq>>10);
+			return;
+
+                } else {
+			tuner_info("radio freq (%d.%02d) out of range (%d-%d)\n",
 			   freq/16,freq%16*100/16,
-			   radio_range[0],radio_range[1]);
-		return;
+				   radio_range[0],radio_range[1]);
+			return;
+		}
 	}
+	tuner_dbg("62.5 Khz freq step selected for Radio.\n");
 	t->radio_freq(c,freq);
 }
 
@@ -131,8 +167,9 @@
 {
 	struct tuner *t = i2c_get_clientdata(c);
 
+	tuner_dbg ("I2C addr 0x%02x with type %d\n",c->addr<<1,type);
 	/* sanity check */
-	if (type == UNSET  ||  type == TUNER_ABSENT)
+	if (type == UNSET || type == TUNER_ABSENT)
 		return;
 	if (type >= tuner_count)
 		return;
@@ -147,6 +184,7 @@
 		return;
 
 	t->initialized = 1;
+
 	t->type = type;
 	switch (t->type) {
 	case TUNER_MT2032:
@@ -161,6 +199,53 @@
 	}
 }
 
+#ifdef CONFIG_TUNER_MULTI_I2C
+#define CHECK_ADDR(tp,cmd,tun)	if (client->addr!=tp) { \
+			  return 0; } else \
+			  tuner_info ("Cmd %s accepted to "tun"\n",cmd);
+#define CHECK_MODE(cmd)	if (t->mode == V4L2_TUNER_RADIO) { \
+		 	CHECK_ADDR(radio_tuner,cmd,"radio") } else \
+			{ CHECK_ADDR(tv_tuner,cmd,"TV"); }
+#else
+#define CHECK_ADDR(tp,cmd,tun) tuner_info ("Cmd %s accepted to "tun"\n",cmd);
+#define CHECK_MODE(cmd) tuner_info ("Cmd %s accepted\n",cmd);
+#endif
+
+#ifdef CONFIG_TUNER_MULTI_I2C
+
+static void set_addr(struct i2c_client *c, struct tuner_addr *tun_addr)
+{
+	/* ADDR_UNSET defaults to first available tuner */
+	if ( tun_addr->addr == ADDR_UNSET ) {
+		if (first_tuner != c->addr)
+			return;
+		switch (tun_addr->v4l2_tuner) {
+		case V4L2_TUNER_RADIO:
+	 		radio_tuner=c->addr;
+			break;
+		default:
+			tv_tuner=c->addr;
+			break;
+		}
+	} else {
+		/* Sets tuner to its configured value */
+		switch (tun_addr->v4l2_tuner) {
+		case V4L2_TUNER_RADIO:
+ 			radio_tuner=tun_addr->addr;
+			if ( tun_addr->addr == c->addr ) set_type(c,tun_addr->type);
+			return;
+		default:
+			tv_tuner=tun_addr->addr;
+			if ( tun_addr->addr == c->addr ) set_type(c,tun_addr->type);
+			return;
+		}
+	}
+	set_type(c,tun_addr->type);
+}
+#else
+#define set_addr(c,tun_addr) set_type(c,(tun_addr)->type)
+#endif
+
 static char pal[] = "-";
 module_param_string(pal, pal, sizeof(pal), 0644);
 
@@ -199,8 +284,17 @@
 {
 	struct tuner *t;
 
+#ifndef CONFIG_TUNER_MULTI_I2C
 	if (this_adap > 0)
 		return -1;
+#else
+	/* by default, first I2C card is both tv and radio tuner */
+	if (this_adap == 0) {
+		first_tuner = addr;
+		tv_tuner = addr;
+		radio_tuner = addr;
+	}
+#endif
 	this_adap++;
 
         client_template.adapter = adap;
@@ -213,11 +307,12 @@
         memcpy(&t->i2c,&client_template,sizeof(struct i2c_client));
 	i2c_set_clientdata(&t->i2c, t);
 	t->type       = UNSET;
-	t->radio_if2  = 10700*1000; // 10.7MHz - FM radio
+	t->radio_if2  = 10700*1000; /* 10.7MHz - FM radio */
 
         i2c_attach_client(&t->i2c);
 	tuner_info("chip found @ 0x%x (%s)\n",
 		   addr << 1, adap->name);
+
 	set_type(&t->i2c, t->type);
 	return 0;
 }
@@ -225,12 +320,17 @@
 static int tuner_probe(struct i2c_adapter *adap)
 {
 	if (0 != addr) {
-		normal_i2c[0]       = addr;
-		normal_i2c_range[0] = addr;
-		normal_i2c_range[1] = addr;
+		normal_i2c[0] = addr;
+		normal_i2c[1] = I2C_CLIENT_END;
 	}
 	this_adap = 0;
 
+#ifdef CONFIG_TUNER_MULTI_I2C
+	first_tuner = 0;
+	tv_tuner = 0;
+	radio_tuner = 0;
+#endif
+
 	if (adap->class & I2C_CLASS_TV_ANALOG)
 		return i2c_probe(adap, &addr_data, tuner_attach);
 	return 0;
@@ -239,8 +339,14 @@
 static int tuner_detach(struct i2c_client *client)
 {
 	struct tuner *t = i2c_get_clientdata(client);
+	int err;
 
-	i2c_detach_client(&t->i2c);
+	err=i2c_detach_client(&t->i2c);
+	if (err) {
+		tuner_warn ("Client deregistration failed, client not detached.\n");
+		return err;
+	}
+
 	kfree(t);
 	return 0;
 }
@@ -259,18 +365,23 @@
         unsigned int *iarg = (int*)arg;
 
         switch (cmd) {
-
 	/* --- configuration --- */
 	case TUNER_SET_TYPE:
 		set_type(client,*iarg);
 		break;
+	case TUNER_SET_TYPE_ADDR:
+		set_addr(client,(struct tuner_addr *)arg);
+		break;
 	case AUDC_SET_RADIO:
+		t->mode = V4L2_TUNER_RADIO;
+		CHECK_ADDR(tv_tuner,"AUDC_SET_RADIO","TV");
+
 		if (V4L2_TUNER_RADIO != t->mode) {
 			set_tv_freq(client,400 * 16);
-			t->mode = V4L2_TUNER_RADIO;
 		}
 		break;
 	case AUDC_CONFIG_PINNACLE:
+		CHECK_ADDR(tv_tuner,"AUDC_CONFIG_PINNACLE","TV");
 		switch (*iarg) {
 		case 2:
 			tuner_dbg("pinnacle pal\n");
@@ -300,6 +411,8 @@
 
 		CHECK_V4L2;
 		t->mode = V4L2_TUNER_ANALOG_TV;
+		CHECK_ADDR(tv_tuner,"VIDIOCSCHAN","TV");
+
 		if (vc->norm < ARRAY_SIZE(map))
 			t->std = map[vc->norm];
 		tuner_fixup_std(t);
@@ -311,6 +424,7 @@
 	{
 		unsigned long *v = arg;
 
+		CHECK_MODE("VIDIOCSFREQ");
 		CHECK_V4L2;
 		set_freq(client,*v);
 		return 0;
@@ -319,15 +433,27 @@
 	{
 		struct video_tuner *vt = arg;
 
+		CHECK_ADDR(radio_tuner,"VIDIOCGTUNER","radio");
 		CHECK_V4L2;
-		if (V4L2_TUNER_RADIO == t->mode  &&  t->has_signal)
-			vt->signal = t->has_signal(client);
+		if (V4L2_TUNER_RADIO == t->mode) {
+			if (t->has_signal)
+				vt->signal = t->has_signal(client);
+			if (t->is_stereo) {
+				if (t->is_stereo(client))
+					vt-> flags |= VIDEO_TUNER_STEREO_ON;
+				else
+					vt-> flags &= 0xffff ^ VIDEO_TUNER_STEREO_ON;
+			}
+			vt->flags |= V4L2_TUNER_CAP_LOW; /* Allow freqs at 62.5 Hz */
+		}
+
 		return 0;
 	}
 	case VIDIOCGAUDIO:
 	{
 		struct video_audio *va = arg;
 
+		CHECK_ADDR(radio_tuner,"VIDIOCGAUDIO","radio");
 		CHECK_V4L2;
 		if (V4L2_TUNER_RADIO == t->mode  &&  t->is_stereo)
 			va->mode = t->is_stereo(client)
@@ -342,6 +468,8 @@
 
 		SWITCH_V4L2;
 		t->mode = V4L2_TUNER_ANALOG_TV;
+		CHECK_ADDR(tv_tuner,"VIDIOC_S_STD","TV");
+
 		t->std = *id;
 		tuner_fixup_std(t);
 		if (t->freq)
@@ -352,6 +480,7 @@
 	{
 		struct v4l2_frequency *f = arg;
 
+		CHECK_MODE("VIDIOC_S_FREQUENCY");
 		SWITCH_V4L2;
 		if (V4L2_TUNER_RADIO == f->type &&
 		    V4L2_TUNER_RADIO != t->mode)
@@ -364,6 +493,7 @@
 	{
 		struct v4l2_frequency *f = arg;
 
+		CHECK_MODE("VIDIOC_G_FREQUENCY");
 		SWITCH_V4L2;
 		f->type = t->mode;
 		f->frequency = t->freq;
@@ -373,14 +503,29 @@
 	{
 		struct v4l2_tuner *tuner = arg;
 
+		CHECK_MODE("VIDIOC_G_TUNER");
 		SWITCH_V4L2;
-		if (V4L2_TUNER_RADIO == t->mode  &&  t->has_signal)
-			tuner->signal = t->has_signal(client);
+		if (V4L2_TUNER_RADIO == t->mode) {
+			if (t->has_signal)
+				tuner -> signal = t->has_signal(client);
+			if (t->is_stereo) {
+				if (t->is_stereo(client)) {
+					tuner -> capability |= V4L2_TUNER_CAP_STEREO;
+					tuner -> rxsubchans |= V4L2_TUNER_SUB_STEREO;
+				} else {
+					tuner -> rxsubchans &= 0xffff ^ V4L2_TUNER_SUB_STEREO;
+				}
+			}
+		}
+		/* Wow to deal with V4L2_TUNER_CAP_LOW ? For now, it accepts from low at 62.5KHz step  to high at 62.5 Hz */
 		tuner->rangelow = tv_range[0] * 16;
-		tuner->rangehigh = tv_range[1] * 16;
+//		tuner->rangehigh = tv_range[1] * 16;
+//		tuner->rangelow = tv_range[0] * 16384;
+		tuner->rangehigh = tv_range[1] * 16384;
 		break;
 	}
 	default:
+		tuner_dbg ("Unimplemented IOCTL 0x%08x called to tuner.\n", cmd);
 		/* nothing */
 		break;
 	}
@@ -388,7 +533,7 @@
 	return 0;
 }
 
-static int tuner_suspend(struct device * dev, pm_message_t state, u32 level)
+static int tuner_suspend(struct device * dev, u32 state, u32 level)
 {
 	struct i2c_client *c = container_of(dev, struct i2c_client, dev);
 	struct tuner *t = i2c_get_clientdata(c);
diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c
index 48c6cef..539f305 100644
--- a/drivers/media/video/tuner-simple.c
+++ b/drivers/media/video/tuner-simple.c
@@ -1,5 +1,5 @@
 /*
- * $Id: tuner-simple.c,v 1.10 2005/03/08 08:38:00 kraxel Exp $
+ * $Id: tuner-simple.c,v 1.21 2005/06/10 19:53:26 nsh Exp $
  *
  * i2c tv tuner chip device driver
  * controls all those simple 4-control-bytes style tuners.
@@ -212,7 +212,25 @@
         { "Philips FQ1236A MK4", Philips, NTSC,
           16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 },
 
+	/* Should work for TVF8531MF, TVF8831MF, TVF8731MF */
+	{ "Ymec TVision TVF-8531MF", Philips, NTSC,
+	  16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732},
+	{ "Ymec TVision TVF-5533MF", Philips, NTSC,
+	  16*160.00,16*454.00,0x01,0x02,0x04,0x8e,732},
+
+	{ "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC,
+	  16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732},
+	{ "Tena TNF9533-D/IF", LGINNOTEK, PAL,
+	  16*160.25, 16*464.25, 0x01,0x02,0x08,0x8e,623},
+
+	/*
+	 * This entry is for TEA5767 FM radio only chip used on several boards
+	 * w/TV tuner
+	 */
+	{ TEA5767_TUNER_NAME, Philips, RADIO,
+	  -1, -1, 0, 0, 0, TEA5767_LOW_LO_32768,0},
 };
+
 unsigned const int tuner_count = ARRAY_SIZE(tuners);
 
 /* ---------------------------------------------------------------------- */
@@ -223,6 +241,7 @@
 
 	if (1 != i2c_master_recv(c,&byte,1))
 		return 0;
+
 	return byte;
 }
 
@@ -231,17 +250,33 @@
 #define TUNER_MODE      0x38
 #define TUNER_AFC       0x07
 
-#define TUNER_STEREO    0x10 /* radio mode */
-#define TUNER_SIGNAL    0x07 /* radio mode */
+#define TUNER_STEREO       0x10 /* radio mode */
+#define TUNER_STEREO_MK3   0x04 /* radio mode */
+#define TUNER_SIGNAL       0x07 /* radio mode */
 
 static int tuner_signal(struct i2c_client *c)
 {
-	return (tuner_getstatus(c) & TUNER_SIGNAL)<<13;
+	return (tuner_getstatus(c) & TUNER_SIGNAL) << 13;
 }
 
 static int tuner_stereo(struct i2c_client *c)
 {
-	return (tuner_getstatus (c) & TUNER_STEREO);
+	int stereo, status;
+	struct tuner *t = i2c_get_clientdata(c);
+
+	status = tuner_getstatus (c);
+
+	switch (t->type) {
+        	case TUNER_PHILIPS_FM1216ME_MK3:
+    		case TUNER_PHILIPS_FM1236_MK3:
+		case TUNER_PHILIPS_FM1256_IH3:
+			stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3);
+			break;
+		default:
+			stereo = status & TUNER_STEREO;
+	}
+
+	return stereo;
 }
 
 #if 0 /* unused */
@@ -424,6 +459,14 @@
 	buffer[2] = tun->config;
 
 	switch (t->type) {
+	case TUNER_TENA_9533_DI:
+	case TUNER_YMEC_TVF_5533MF:
+
+		/*These values are empirically determinated */
+		div = (freq*122)/16 - 20;
+		buffer[2] = 0x88; /* could be also 0x80 */
+		buffer[3] = 0x19; /* could be also 0x10, 0x18, 0x99 */
+		break;
 	case TUNER_PHILIPS_FM1216ME_MK3:
 	case TUNER_PHILIPS_FM1236_MK3:
 		buffer[3] = 0x19;
diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c
index 80dc34f..9a493be 100644
--- a/drivers/media/video/tvaudio.c
+++ b/drivers/media/video/tvaudio.c
@@ -148,7 +148,6 @@
 	I2C_TDA9874   >> 1,
 	I2C_PIC16C54  >> 1,
 	I2C_CLIENT_END };
-static unsigned short normal_i2c_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
 I2C_CLIENT_INSMOD;
 
 static struct i2c_driver driver;
@@ -286,7 +285,6 @@
 			schedule();
 		}
 		remove_wait_queue(&chip->wq, &wait);
-		try_to_freeze(PF_FREEZE);
 		if (chip->done || signal_pending(current))
 			break;
 		dprintk("%s: thread wakeup\n", i2c_clientname(&chip->c));
@@ -1238,17 +1236,17 @@
 /* audio chip descriptions - struct CHIPDESC                              */
 
 /* insmod options to enable/disable individual audio chips */
-int tda8425  = 1;
-int tda9840  = 1;
-int tda9850  = 1;
-int tda9855  = 1;
-int tda9873  = 1;
-int tda9874a = 1;
-int tea6300  = 0;  // address clash with msp34xx
-int tea6320  = 0;  // address clash with msp34xx
-int tea6420  = 1;
-int pic16c54 = 1;
-int ta8874z  = 0;  // address clash with tda9840
+static int tda8425  = 1;
+static int tda9840  = 1;
+static int tda9850  = 1;
+static int tda9855  = 1;
+static int tda9873  = 1;
+static int tda9874a = 1;
+static int tea6300  = 0;  // address clash with msp34xx
+static int tea6320  = 0;  // address clash with msp34xx
+static int tea6420  = 1;
+static int pic16c54 = 1;
+static int ta8874z  = 0;  // address clash with tda9840
 
 module_param(tda8425, int, 0444);
 module_param(tda9840, int, 0444);
diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
index e1443a0..0f03c25 100644
--- a/drivers/media/video/tveeprom.c
+++ b/drivers/media/video/tveeprom.c
@@ -75,7 +75,7 @@
 	{ 0x00000007, "PAL(B/G)" },
 	{ 0x00001000, "NTSC(M)" },
 	{ 0x00000010, "PAL(I)" },
-	{ 0x00400000, "SECAM(L/L�)" },
+	{ 0x00400000, "SECAM(L/L´)" },
 	{ 0x00000e00, "PAL(D/K)" },
 	{ 0x03000000, "ATSC Digital" },
 };
@@ -482,7 +482,6 @@
 	0xa0 >> 1,
 	I2C_CLIENT_END,
 };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 I2C_CLIENT_INSMOD;
 
 struct i2c_driver i2c_driver_tveeprom;
diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c
index eafd706..51b99cd 100644
--- a/drivers/media/video/tvmixer.c
+++ b/drivers/media/video/tvmixer.c
@@ -1,3 +1,7 @@
+/*
+ * $Id: tvmixer.c,v 1.8 2005/06/12 04:19:19 mchehab Exp $
+ */
+
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c
index b0d4bcb..70ecbdb 100644
--- a/drivers/media/video/v4l1-compat.c
+++ b/drivers/media/video/v4l1-compat.c
@@ -1,4 +1,6 @@
 /*
+ * $Id: v4l1-compat.c,v 1.9 2005/06/12 04:19:19 mchehab Exp $
+ *
  *	Video for Linux Two
  *	Backward Compatibility Layer
  *
@@ -15,14 +17,11 @@
  *
  */
 
-#ifndef __KERNEL__
-#define __KERNEL__
-#endif
-
 #include <linux/config.h>
 
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -787,12 +786,15 @@
 		    !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
 			aud->step = qctrl2.step;
 		aud->mode = 0;
+
+		memset(&tun2,0,sizeof(tun2));
 		err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
 		if (err < 0) {
 			dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n",err);
 			err = 0;
 			break;
 		}
+
 		if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2)
 			aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
 		else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
diff --git a/drivers/media/video/video-buf-dvb.c b/drivers/media/video/video-buf-dvb.c
index 5f87007..15f5bb4 100644
--- a/drivers/media/video/video-buf-dvb.c
+++ b/drivers/media/video/video-buf-dvb.c
@@ -62,8 +62,7 @@
 			break;
 		if (kthread_should_stop())
 			break;
-		if (current->flags & PF_FREEZE)
-			refrigerator(PF_FREEZE);
+		try_to_freeze();
 
 		/* feed buffer data to demux */
 		if (buf->state == STATE_DONE)
diff --git a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c
index 0fd6c9a..5dbd9f6 100644
--- a/drivers/media/video/vpx3220.c
+++ b/drivers/media/video/vpx3220.c
@@ -569,22 +569,14 @@
     { I2C_VPX3220 >> 1, (I2C_VPX3220 >> 1) + 4,
 	I2C_CLIENT_END
 };
-static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
 
-static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
-static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };
+static unsigned short ignore = I2C_CLIENT_END;
                                                                                 
 static struct i2c_client_address_data addr_data = {
 	.normal_i2c		= normal_i2c,
-	.normal_i2c_range	= normal_i2c_range,
-	.probe			= probe,
-	.probe_range		= probe_range,
-	.ignore			= ignore,
-	.ignore_range		= ignore_range,
-	.force			= force
+	.probe			= &ignore,
+	.ignore			= &ignore,
+	.force			= &ignore,
 };
 
 static struct i2c_driver vpx3220_i2c_driver;
diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig
index 452418b..33f209a 100644
--- a/drivers/message/fusion/Kconfig
+++ b/drivers/message/fusion/Kconfig
@@ -2,34 +2,54 @@
 menu "Fusion MPT device support"
 
 config FUSION
-	tristate "Fusion MPT (base + ScsiHost) drivers"
-	depends on PCI && SCSI
-	---help---
-	  LSI Logic Fusion(TM) Message Passing Technology (MPT) device support
-	  provides high performance SCSI host initiator, and LAN [1] interface
-	  services to a host system.  The Fusion architecture is capable of
-	  duplexing these protocols on high-speed Fibre Channel
-	  (up to 2 GHz x 2 ports = 4 GHz) and parallel SCSI (up to Ultra-320)
-	  physical medium.
+	bool
+	default n
 
-	  [1] LAN is not supported on parallel SCSI medium.
+config FUSION_SPI
+	tristate "Fusion MPT ScsiHost drivers for SPI"
+	depends on PCI && SCSI
+	select FUSION
+	---help---
+	  SCSI HOST support for a parallel SCSI host adapters.
+
+	  List of supported controllers:
+
+	  LSI53C1020
+	  LSI53C1020A
+	  LSI53C1030
+	  LSI53C1035
+
+config FUSION_FC
+	tristate "Fusion MPT ScsiHost drivers for FC"
+	depends on PCI && SCSI
+	select FUSION
+	---help---
+	  SCSI HOST support for a Fiber Channel host adapters.
+
+	  List of supported controllers:
+
+	  LSIFC909
+	  LSIFC919
+	  LSIFC919X
+	  LSIFC929
+	  LSIFC929X
+	  LSIFC929XL
 
 config FUSION_MAX_SGE
-	int "Maximum number of scatter gather entries"
+	int "Maximum number of scatter gather entries (16 - 128)"
 	depends on FUSION
-	default "40"
+	default "128"
+	range 16 128
 	help
 	  This option allows you to specify the maximum number of scatter-
-	  gather entries per I/O. The driver defaults to 40, a reasonable number
-	  for most systems. However, the user may increase this up to 128.
-	  Increasing this parameter will require significantly more memory 
-	  on a per controller instance. Increasing the parameter is not
-	  necessary (or recommended) unless the user will be running 
-	  large I/O's via the raw interface.
+	  gather entries per I/O. The driver default is 128, which matches
+	  SCSI_MAX_PHYS_SEGMENTS. However, it may decreased down to 16.
+	  Decreasing this parameter will reduce memory requirements
+	  on a per controller instance.
 
 config FUSION_CTL
 	tristate "Fusion MPT misc device (ioctl) driver"
-	depends on FUSION
+	depends on FUSION_SPI || FUSION_FC
 	---help---
 	  The Fusion MPT misc device driver provides specialized control
 	  of MPT adapters via system ioctl calls.  Use of ioctl calls to
@@ -48,7 +68,7 @@
 
 config FUSION_LAN
 	tristate "Fusion MPT LAN driver"
-	depends on FUSION && NET_FC
+	depends on FUSION_FC && NET_FC
 	---help---
 	  This module supports LAN IP traffic over Fibre Channel port(s)
 	  on Fusion MPT compatible hardware (LSIFC9xx chips).
diff --git a/drivers/message/fusion/Makefile b/drivers/message/fusion/Makefile
index f6fdcaae..1d2f9db 100644
--- a/drivers/message/fusion/Makefile
+++ b/drivers/message/fusion/Makefile
@@ -1,52 +1,38 @@
-#
-# Makefile for the LSI Logic Fusion MPT (Message Passing Technology) drivers.
-#
-# Note! If you want to turn on various debug defines for an extended period of
-# time but don't want them lingering around in the Makefile when you pass it on
-# to someone else, use the MPT_CFLAGS env variable (thanks Steve). -nromer
-
-#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-{ LSI_LOGIC
-
-#  Architecture-specific...
-#			# intel
-#EXTRA_CFLAGS += -g
-#			# sparc64
-#EXTRA_CFLAGS += -gstabs+
-
-EXTRA_CFLAGS += ${MPT_CFLAGS}
-
 # Fusion MPT drivers; recognized debug defines...
 #  MPT general:
-#EXTRA_CFLAGS += -DMPT_DEBUG_SCSI
 #EXTRA_CFLAGS += -DMPT_DEBUG
 #EXTRA_CFLAGS += -DMPT_DEBUG_MSG_FRAME
 #EXTRA_CFLAGS += -DMPT_DEBUG_SG
+#EXTRA_CFLAGS += -DMPT_DEBUG_EVENTS
+#EXTRA_CFLAGS += -DMPT_DEBUG_INIT
+#EXTRA_CFLAGS += -DMPT_DEBUG_EXIT
+#EXTRA_CFLAGS += -DMPT_DEBUG_FAIL
+
 
 #
 # driver/module specifics...
 #
 #  For mptbase:
 #CFLAGS_mptbase.o += -DMPT_DEBUG_HANDSHAKE
+#CFLAGS_mptbase.o += -DMPT_DEBUG_CONFIG
+#CFLAGS_mptbase.o += -DMPT_DEBUG_DL
 #CFLAGS_mptbase.o += -DMPT_DEBUG_IRQ
+#CFLAGS_mptbase.o += -DMPT_DEBUG_RESET
 #
 #  For mptscsih:
-#CFLAGS_mptscsih.o += -DMPT_DEBUG_SCANDV
-#CFLAGS_mptscsih.o += -DMPT_DEBUG_RESET
-#CFLAGS_mptscsih.o += -DMPT_DEBUG_NEH
+#CFLAGS_mptscsih.o += -DMPT_DEBUG_DV
+#CFLAGS_mptscsih.o += -DMPT_DEBUG_NEGO
+#CFLAGS_mptscsih.o += -DMPT_DEBUG_TM
+#CFLAGS_mptscsih.o += -DMPT_DEBUG_SCSI
+#CFLAGS_mptscsih.o += -DMPT_DEBUG_REPLY
 #
 #  For mptctl:
 #CFLAGS_mptctl.o += -DMPT_DEBUG_IOCTL
 #
-#  For mptlan:
-#CFLAGS_mptlan.o += -DMPT_LAN_IO_DEBUG
-#
-#  For isense:
-
-#  EXP...
-##mptscsih-objs	:= scsihost.o scsiherr.o
 
 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC
 
-obj-$(CONFIG_FUSION)		+= mptbase.o mptscsih.o
+obj-$(CONFIG_FUSION_SPI)	+= mptbase.o mptscsih.o mptspi.o
+obj-$(CONFIG_FUSION_FC)		+= mptbase.o mptscsih.o mptfc.o
 obj-$(CONFIG_FUSION_CTL)	+= mptctl.o
 obj-$(CONFIG_FUSION_LAN)	+= mptlan.o
diff --git a/drivers/message/fusion/lsi/mpi.h b/drivers/message/fusion/lsi/mpi.h
index 9dbb061..9f98334 100644
--- a/drivers/message/fusion/lsi/mpi.h
+++ b/drivers/message/fusion/lsi/mpi.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2003 LSI Logic Corporation.
+ *  Copyright (c) 2000-2005 LSI Logic Corporation.
  *
  *
  *           Name:  mpi.h
  *          Title:  MPI Message independent structures and definitions
  *  Creation Date:  July 27, 2000
  *
- *    mpi.h Version:  01.05.xx
+ *    mpi.h Version:  01.05.07
  *
  *  Version History
  *  ---------------
@@ -52,6 +52,25 @@
  *                      obsoleted define MPI_IOCSTATUS_TARGET_INVALID_IOCINDEX.
  *  04-01-03  01.02.09  New IOCStatus code: MPI_IOCSTATUS_FC_EXCHANGE_CANCELED
  *  06-26-03  01.02.10  Bumped MPI_HEADER_VERSION_UNIT value.
+ *  01-16-04  01.02.11  Added define for MPI_IOCLOGINFO_TYPE_SHIFT.
+ *  04-29-04  01.02.12  Added function codes for MPI_FUNCTION_DIAG_BUFFER_POST
+ *                      and MPI_FUNCTION_DIAG_RELEASE.
+ *                      Added MPI_IOCSTATUS_DIAGNOSTIC_RELEASED define.
+ *                      Bumped MPI_HEADER_VERSION_UNIT value.
+ *  05-11-04  01.03.01  Bumped MPI_VERSION_MINOR for MPI v1.3.
+ *                      Added codes for Inband.
+ *  08-19-04  01.05.01  Added defines for Host Buffer Access Control doorbell.
+ *                      Added define for offset of High Priority Request Queue.
+ *                      Added new function codes and new IOCStatus codes.
+ *                      Added a IOCLogInfo type of SAS.
+ *  12-07-04  01.05.02  Bumped MPI_HEADER_VERSION_UNIT.
+ *  12-09-04  01.05.03  Bumped MPI_HEADER_VERSION_UNIT.
+ *  01-15-05  01.05.04  Bumped MPI_HEADER_VERSION_UNIT.
+ *  02-09-05  01.05.05  Bumped MPI_HEADER_VERSION_UNIT.
+ *  02-22-05  01.05.06  Bumped MPI_HEADER_VERSION_UNIT.
+ *  03-11-05  01.05.07  Removed function codes for SCSI IO 32 and
+ *                      TargetAssistExtended requests.
+ *                      Removed EEDP IOCStatus codes.
  *  --------------------------------------------------------------------------
  */
 
@@ -82,7 +101,7 @@
 /* Note: The major versions of 0xe0 through 0xff are reserved */
 
 /* versioning for this MPI header set */
-#define MPI_HEADER_VERSION_UNIT             (0x00)
+#define MPI_HEADER_VERSION_UNIT             (0x09)
 #define MPI_HEADER_VERSION_DEV              (0x00)
 #define MPI_HEADER_VERSION_UNIT_MASK        (0xFF00)
 #define MPI_HEADER_VERSION_UNIT_SHIFT       (8)
@@ -122,7 +141,11 @@
 *
 *****************************************************************************/
 
-/* S y s t e m    D o o r b e l l */
+/*
+ * Defines for working with the System Doorbell register.
+ * Values for doorbell function codes are included in the section that defines
+ * all the function codes (further on in this file).
+ */
 #define MPI_DOORBELL_OFFSET                 (0x00000000)
 #define MPI_DOORBELL_ACTIVE                 (0x08000000) /* DoorbellUsed */
 #define MPI_DOORBELL_USED                   (MPI_DOORBELL_ACTIVE)
@@ -134,6 +157,13 @@
 #define MPI_DOORBELL_ADD_DWORDS_MASK        (0x00FF0000)
 #define MPI_DOORBELL_ADD_DWORDS_SHIFT       (16)
 #define MPI_DOORBELL_DATA_MASK              (0x0000FFFF)
+#define MPI_DOORBELL_FUNCTION_SPECIFIC_MASK (0x0000FFFF)
+
+/* values for Host Buffer Access Control doorbell function */
+#define MPI_DB_HPBAC_VALUE_MASK             (0x0000F000)
+#define MPI_DB_HPBAC_ENABLE_ACCESS          (0x01)
+#define MPI_DB_HPBAC_DISABLE_ACCESS         (0x02)
+#define MPI_DB_HPBAC_FREE_BUFFER            (0x03)
 
 
 #define MPI_WRITE_SEQUENCE_OFFSET           (0x00000004)
@@ -257,16 +287,18 @@
 
 #define MPI_FUNCTION_SMP_PASSTHROUGH                (0x1A)
 #define MPI_FUNCTION_SAS_IO_UNIT_CONTROL            (0x1B)
+#define MPI_FUNCTION_SATA_PASSTHROUGH               (0x1C)
 
-#define MPI_DIAG_BUFFER_POST                        (0x1D)
-#define MPI_DIAG_RELEASE                            (0x1E)
-
-#define MPI_FUNCTION_SCSI_IO_32                     (0x1F)
+#define MPI_FUNCTION_DIAG_BUFFER_POST               (0x1D)
+#define MPI_FUNCTION_DIAG_RELEASE                   (0x1E)
 
 #define MPI_FUNCTION_LAN_SEND                       (0x20)
 #define MPI_FUNCTION_LAN_RECEIVE                    (0x21)
 #define MPI_FUNCTION_LAN_RESET                      (0x22)
 
+#define MPI_FUNCTION_TARGET_CMD_BUF_BASE_POST       (0x24)
+#define MPI_FUNCTION_TARGET_CMD_BUF_LIST_POST       (0x25)
+
 #define MPI_FUNCTION_INBAND_BUFFER_POST             (0x28)
 #define MPI_FUNCTION_INBAND_SEND                    (0x29)
 #define MPI_FUNCTION_INBAND_RSP                     (0x2A)
@@ -276,6 +308,7 @@
 #define MPI_FUNCTION_IO_UNIT_RESET                  (0x41)
 #define MPI_FUNCTION_HANDSHAKE                      (0x42)
 #define MPI_FUNCTION_REPLY_FRAME_REMOVAL            (0x43)
+#define MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL    (0x44)
 
 
 /* standard version format */
@@ -328,8 +361,8 @@
         U32                 Address32;
         U64                 Address64;
     }u;
-} SGESimpleUnion_t, MPI_POINTER pSGESimpleUnion_t,
-  SGE_SIMPLE_UNION, MPI_POINTER PTR_SGE_SIMPLE_UNION;
+} SGE_SIMPLE_UNION, MPI_POINTER PTR_SGE_SIMPLE_UNION,
+  SGESimpleUnion_t, MPI_POINTER pSGESimpleUnion_t;
 
 /****************************************************************************/
 /*  Chain element structures                                                */
@@ -648,27 +681,21 @@
 #define MPI_IOCSTATUS_SCSI_EXT_TERMINATED       (0x004C)
 
 /****************************************************************************/
-/*  For use by SCSI Initiator and SCSI Target end-to-end data protection    */
-/****************************************************************************/
-
-#define MPI_IOCSTATUS_EEDP_CRC_ERROR            (0x004D)
-#define MPI_IOCSTATUS_EEDP_LBA_TAG_ERROR        (0x004E)
-#define MPI_IOCSTATUS_EEDP_APP_TAG_ERROR        (0x004F)
-
-
-/****************************************************************************/
-/*  SCSI (SPI & FCP) target values                                          */
+/*  SCSI Target values                                                      */
 /****************************************************************************/
 
 #define MPI_IOCSTATUS_TARGET_PRIORITY_IO         (0x0060)
 #define MPI_IOCSTATUS_TARGET_INVALID_PORT        (0x0061)
-#define MPI_IOCSTATUS_TARGET_INVALID_IOCINDEX    (0x0062)   /* obsolete */
+#define MPI_IOCSTATUS_TARGET_INVALID_IOCINDEX    (0x0062)   /* obsolete name */
 #define MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX    (0x0062)
 #define MPI_IOCSTATUS_TARGET_ABORTED             (0x0063)
 #define MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE   (0x0064)
 #define MPI_IOCSTATUS_TARGET_NO_CONNECTION       (0x0065)
 #define MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH (0x006A)
 #define MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT   (0x006B)
+#define MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR   (0x006D)
+#define MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E)
+#define MPI_IOCSTATUS_TARGET_IU_TOO_SHORT        (0x006F)
 
 /****************************************************************************/
 /*  Additional FCP target values (obsolete)                                 */
@@ -707,6 +734,7 @@
 /****************************************************************************/
 
 #define MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED    (0x0090)
+#define MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN      (0x0091)
 
 /****************************************************************************/
 /*  Inband values                                                           */
diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h
index a5680d8..15b12b0 100644
--- a/drivers/message/fusion/lsi/mpi_cnfg.h
+++ b/drivers/message/fusion/lsi/mpi_cnfg.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2003 LSI Logic Corporation.
+ *  Copyright (c) 2000-2005 LSI Logic Corporation.
  *
  *
  *           Name:  mpi_cnfg.h
  *          Title:  MPI Config message, structures, and Pages
  *  Creation Date:  July 27, 2000
  *
- *    mpi_cnfg.h Version:  01.05.xx
+ *    mpi_cnfg.h Version:  01.05.08
  *
  *  Version History
  *  ---------------
@@ -145,6 +145,93 @@
  *                      In CONFIG_PAGE_FC_DEVICE_0, replaced Reserved1 field
  *                      with ADISCHardALPA.
  *                      Added MPI_FC_DEVICE_PAGE0_PROT_FCP_RETRY define.
+ *  01-16-04 01.02.13   Added InitiatorDeviceTimeout and InitiatorIoPendTimeout
+ *                      fields and related defines to CONFIG_PAGE_FC_PORT_1.
+ *                      Added define for
+ *                      MPI_FCPORTPAGE1_FLAGS_SOFT_ALPA_FALLBACK.
+ *                      Added new fields to the substructures of
+ *                      CONFIG_PAGE_FC_PORT_10.
+ *  04-29-04 01.02.14   Added define for IDP bit for CONFIG_PAGE_SCSI_PORT_0,
+ *                      CONFIG_PAGE_SCSI_DEVICE_0, and
+ *                      CONFIG_PAGE_SCSI_DEVICE_1. Also bumped Page Version for
+ *                      these pages.
+ *  05-11-04 01.03.01   Added structure for CONFIG_PAGE_INBAND_0.
+ *  08-19-04 01.05.01   Modified MSG_CONFIG request to support extended config
+ *                      pages.
+ *                      Added a new structure for extended config page header.
+ *                      Added new extended config pages types and structures for
+ *                      SAS IO Unit, SAS Expander, SAS Device, and SAS PHY.
+ *                      Replaced a reserved byte in CONFIG_PAGE_MANUFACTURING_4
+ *                      to add a Flags field.
+ *                      Two new Manufacturing config pages (5 and 6).
+ *                      Two new bits defined for IO Unit Page 1 Flags field.
+ *                      Modified CONFIG_PAGE_IO_UNIT_2 to add three new fields
+ *                      to specify the BIOS boot device.
+ *                      Four new Flags bits defined for IO Unit Page 2.
+ *                      Added IO Unit Page 4.
+ *                      Added EEDP Flags settings to IOC Page 1.
+ *                      Added new BIOS Page 1 config page.
+ *  10-05-04 01.05.02   Added define for
+ *                      MPI_IOCPAGE1_INITIATOR_CONTEXT_REPLY_DISABLE.
+ *                      Added new Flags field to CONFIG_PAGE_MANUFACTURING_5 and
+ *                      associated defines.
+ *                      Added more defines for SAS IO Unit Page 0
+ *                      DiscoveryStatus field.
+ *                      Added define for MPI_SAS_IOUNIT0_DS_SUBTRACTIVE_LINK
+ *                      and MPI_SAS_IOUNIT0_DS_TABLE_LINK.
+ *                      Added defines for Physical Mapping Modes to SAS IO Unit
+ *                      Page 2.
+ *                      Added define for
+ *                      MPI_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH.
+ *  10-27-04 01.05.03   Added defines for new SAS PHY page addressing mode.
+ *                      Added defines for MaxTargetSpinUp to BIOS Page 1.
+ *                      Added 5 new ControlFlags defines for SAS IO Unit
+ *                      Page 1.
+ *                      Added MaxNumPhysicalMappedIDs field to SAS IO Unit
+ *                      Page 2.
+ *                      Added AccessStatus field to SAS Device Page 0 and added
+ *                      new Flags bits for supported SATA features.
+ *  12-07-04  01.05.04  Added config page structures for BIOS Page 2, RAID
+ *                      Volume Page 1, and RAID Physical Disk Page 1.
+ *                      Replaced IO Unit Page 1 BootTargetID,BootBus, and
+ *                      BootAdapterNum with reserved field.
+ *                      Added DataScrubRate and ResyncRate to RAID Volume
+ *                      Page 0.
+ *                      Added MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT
+ *                      define.
+ *  12-09-04  01.05.05  Added Target Mode Large CDB Enable to FC Port Page 1
+ *                      Flags field.
+ *                      Added Auto Port Config flag define for SAS IOUNIT
+ *                      Page 1 ControlFlags.
+ *                      Added Disabled bad Phy define to Expander Page 1
+ *                      Discovery Info field.
+ *                      Added SAS/SATA device support to SAS IOUnit Page 1
+ *                      ControlFlags.
+ *                      Added Unsupported device to SAS Dev Page 0 Flags field
+ *                      Added disable use SATA Hash Address for SAS IOUNIT
+ *                      page 1 in ControlFields.
+ *  01-15-05  01.05.06  Added defaults for data scrub rate and resync rate to
+ *                      Manufacturing Page 4.
+ *                      Added new defines for BIOS Page 1 IOCSettings field.
+ *                      Added ExtDiskIdentifier field to RAID Physical Disk
+ *                      Page 0.
+ *                      Added new defines for SAS IO Unit Page 1 ControlFlags
+ *                      and to SAS Device Page 0 Flags to control SATA devices.
+ *                      Added defines and structures for the new Log Page 0, a
+ *                      new type of configuration page.
+ *  02-09-05  01.05.07  Added InactiveStatus field to RAID Volume Page 0.
+ *                      Added WWID field to RAID Volume Page 1.
+ *                      Added PhysicalPort field to SAS Expander pages 0 and 1.
+ *  03-11-05  01.05.08  Removed the EEDP flags from IOC Page 1.
+ *                      Added Enclosure/Slot boot device format to BIOS Page 2.
+ *                      New status value for RAID Volume Page 0 VolumeStatus
+ *                      (VolumeState subfield).
+ *                      New value for RAID Physical Page 0 InactiveStatus.
+ *                      Added Inactive Volume Member flag RAID Physical Disk
+ *                      Page 0 PhysDiskStatus field.
+ *                      New physical mapping mode in SAS IO Unit Page 2.
+ *                      Added CONFIG_PAGE_SAS_ENCLOSURE_0.
+ *                      Added Slot and Enclosure fields to SAS Device Page 0.
  *  --------------------------------------------------------------------------
  */
 
@@ -164,7 +251,7 @@
     U8                      PageLength;                 /* 01h */
     U8                      PageNumber;                 /* 02h */
     U8                      PageType;                   /* 03h */
-} fCONFIG_PAGE_HEADER, MPI_POINTER PTR_CONFIG_PAGE_HEADER,
+} CONFIG_PAGE_HEADER, MPI_POINTER PTR_CONFIG_PAGE_HEADER,
   ConfigPageHeader_t, MPI_POINTER pConfigPageHeader_t;
 
 typedef union _CONFIG_PAGE_HEADER_UNION
@@ -174,7 +261,7 @@
    U16                 Word16[2];
    U32                 Word32;
 } ConfigPageHeaderUnion, MPI_POINTER pConfigPageHeaderUnion,
-  fCONFIG_PAGE_HEADER_UNION, MPI_POINTER PTR_CONFIG_PAGE_HEADER_UNION;
+  CONFIG_PAGE_HEADER_UNION, MPI_POINTER PTR_CONFIG_PAGE_HEADER_UNION;
 
 typedef struct _CONFIG_EXTENDED_PAGE_HEADER
 {
@@ -185,7 +272,7 @@
     U16                 ExtPageLength;              /* 04h */
     U8                  ExtPageType;                /* 06h */
     U8                  Reserved2;                  /* 07h */
-} fCONFIG_EXTENDED_PAGE_HEADER, MPI_POINTER PTR_CONFIG_EXTENDED_PAGE_HEADER,
+} CONFIG_EXTENDED_PAGE_HEADER, MPI_POINTER PTR_CONFIG_EXTENDED_PAGE_HEADER,
   ConfigExtendedPageHeader_t, MPI_POINTER pConfigExtendedPageHeader_t;
 
 
@@ -224,6 +311,8 @@
 #define MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER         (0x11)
 #define MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE           (0x12)
 #define MPI_CONFIG_EXTPAGETYPE_SAS_PHY              (0x13)
+#define MPI_CONFIG_EXTPAGETYPE_LOG                  (0x14)
+#define MPI_CONFIG_EXTPAGETYPE_ENCLOSURE            (0x15)
 
 
 /****************************************************************************
@@ -231,10 +320,19 @@
 ****************************************************************************/
 #define MPI_SCSI_PORT_PGAD_PORT_MASK                (0x000000FF)
 
+#define MPI_SCSI_DEVICE_FORM_MASK                   (0xF0000000)
+#define MPI_SCSI_DEVICE_FORM_BUS_TID                (0x00000000)
 #define MPI_SCSI_DEVICE_TARGET_ID_MASK              (0x000000FF)
 #define MPI_SCSI_DEVICE_TARGET_ID_SHIFT             (0)
 #define MPI_SCSI_DEVICE_BUS_MASK                    (0x0000FF00)
 #define MPI_SCSI_DEVICE_BUS_SHIFT                   (8)
+#define MPI_SCSI_DEVICE_FORM_TARGET_MODE            (0x10000000)
+#define MPI_SCSI_DEVICE_TM_RESPOND_ID_MASK          (0x000000FF)
+#define MPI_SCSI_DEVICE_TM_RESPOND_ID_SHIFT         (0)
+#define MPI_SCSI_DEVICE_TM_BUS_MASK                 (0x0000FF00)
+#define MPI_SCSI_DEVICE_TM_BUS_SHIFT                (8)
+#define MPI_SCSI_DEVICE_TM_INIT_ID_MASK             (0x00FF0000)
+#define MPI_SCSI_DEVICE_TM_INIT_ID_SHIFT            (16)
 
 #define MPI_FC_PORT_PGAD_PORT_MASK                  (0xF0000000)
 #define MPI_FC_PORT_PGAD_PORT_SHIFT                 (28)
@@ -260,6 +358,20 @@
 #define MPI_PHYSDISK_PGAD_PHYSDISKNUM_MASK          (0x000000FF)
 #define MPI_PHYSDISK_PGAD_PHYSDISKNUM_SHIFT         (0)
 
+#define MPI_SAS_EXPAND_PGAD_FORM_MASK             (0xF0000000)
+#define MPI_SAS_EXPAND_PGAD_FORM_SHIFT            (28)
+#define MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE  (0x00000000)
+#define MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM   (0x00000001)
+#define MPI_SAS_EXPAND_PGAD_FORM_HANDLE           (0x00000002)
+#define MPI_SAS_EXPAND_PGAD_GNH_MASK_HANDLE       (0x0000FFFF)
+#define MPI_SAS_EXPAND_PGAD_GNH_SHIFT_HANDLE      (0)
+#define MPI_SAS_EXPAND_PGAD_HPN_MASK_PHY          (0x00FF0000)
+#define MPI_SAS_EXPAND_PGAD_HPN_SHIFT_PHY         (16)
+#define MPI_SAS_EXPAND_PGAD_HPN_MASK_HANDLE       (0x0000FFFF)
+#define MPI_SAS_EXPAND_PGAD_HPN_SHIFT_HANDLE      (0)
+#define MPI_SAS_EXPAND_PGAD_H_MASK_HANDLE         (0x0000FFFF)
+#define MPI_SAS_EXPAND_PGAD_H_SHIFT_HANDLE        (0)
+
 #define MPI_SAS_DEVICE_PGAD_FORM_MASK               (0xF0000000)
 #define MPI_SAS_DEVICE_PGAD_FORM_SHIFT              (28)
 #define MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE    (0x00000000)
@@ -274,10 +386,24 @@
 #define MPI_SAS_DEVICE_PGAD_H_HANDLE_MASK           (0x0000FFFF)
 #define MPI_SAS_DEVICE_PGAD_H_HANDLE_SHIFT          (0)
 
-#define MPI_SAS_PHY_PGAD_PHY_NUMBER_MASK            (0x00FF0000)
-#define MPI_SAS_PHY_PGAD_PHY_NUMBER_SHIFT           (16)
-#define MPI_SAS_PHY_PGAD_DEVHANDLE_MASK             (0x0000FFFF)
-#define MPI_SAS_PHY_PGAD_DEVHANDLE_SHIFT            (0)
+#define MPI_SAS_PHY_PGAD_FORM_MASK                  (0xF0000000)
+#define MPI_SAS_PHY_PGAD_FORM_SHIFT                 (28)
+#define MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER            (0x0)
+#define MPI_SAS_PHY_PGAD_FORM_PHY_TBL_INDEX         (0x1)
+#define MPI_SAS_PHY_PGAD_PHY_NUMBER_MASK            (0x000000FF)
+#define MPI_SAS_PHY_PGAD_PHY_NUMBER_SHIFT           (0)
+#define MPI_SAS_PHY_PGAD_PHY_TBL_INDEX_MASK         (0x0000FFFF)
+#define MPI_SAS_PHY_PGAD_PHY_TBL_INDEX_SHIFT        (0)
+
+#define MPI_SAS_ENCLOS_PGAD_FORM_MASK               (0xF0000000)
+#define MPI_SAS_ENCLOS_PGAD_FORM_SHIFT              (28)
+#define MPI_SAS_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE    (0x00000000)
+#define MPI_SAS_ENCLOS_PGAD_FORM_HANDLE             (0x00000001)
+#define MPI_SAS_ENCLOS_PGAD_GNH_HANDLE_MASK         (0x0000FFFF)
+#define MPI_SAS_ENCLOS_PGAD_GNH_HANDLE_SHIFT        (0)
+#define MPI_SAS_ENCLOS_PGAD_H_HANDLE_MASK           (0x0000FFFF)
+#define MPI_SAS_ENCLOS_PGAD_H_HANDLE_SHIFT          (0)
+
 
 
 /****************************************************************************
@@ -294,7 +420,7 @@
     U8                      MsgFlags;                   /* 07h */
     U32                     MsgContext;                 /* 08h */
     U8                      Reserved2[8];               /* 0Ch */
-    fCONFIG_PAGE_HEADER      Header;                     /* 14h */
+    CONFIG_PAGE_HEADER      Header;                     /* 14h */
     U32                     PageAddress;                /* 18h */
     SGE_IO_UNION            PageBufferSGE;              /* 1Ch */
 } MSG_CONFIG, MPI_POINTER PTR_MSG_CONFIG,
@@ -327,7 +453,7 @@
     U8                      Reserved2[2];               /* 0Ch */
     U16                     IOCStatus;                  /* 0Eh */
     U32                     IOCLogInfo;                 /* 10h */
-    fCONFIG_PAGE_HEADER      Header;                     /* 14h */
+    CONFIG_PAGE_HEADER      Header;                     /* 14h */
 } MSG_CONFIG_REPLY, MPI_POINTER PTR_MSG_CONFIG_REPLY,
   ConfigReply_t, MPI_POINTER pConfigReply_t;
 
@@ -349,6 +475,8 @@
 #define MPI_MANUFACTPAGE_DEVICEID_FC929             (0x0622)
 #define MPI_MANUFACTPAGE_DEVICEID_FC919X            (0x0628)
 #define MPI_MANUFACTPAGE_DEVICEID_FC929X            (0x0626)
+#define MPI_MANUFACTPAGE_DEVICEID_FC939X            (0x0642)
+#define MPI_MANUFACTPAGE_DEVICEID_FC949X            (0x0640)
 /* SCSI */
 #define MPI_MANUFACTPAGE_DEVID_53C1030              (0x0030)
 #define MPI_MANUFACTPAGE_DEVID_53C1030ZC            (0x0031)
@@ -358,18 +486,25 @@
 #define MPI_MANUFACTPAGE_DEVID_53C1035ZC            (0x0041)
 /* SAS */
 #define MPI_MANUFACTPAGE_DEVID_SAS1064              (0x0050)
+#define MPI_MANUFACTPAGE_DEVID_SAS1064A             (0x005C)
+#define MPI_MANUFACTPAGE_DEVID_SAS1064E             (0x0056)
+#define MPI_MANUFACTPAGE_DEVID_SAS1066              (0x005E)
+#define MPI_MANUFACTPAGE_DEVID_SAS1066E             (0x005A)
+#define MPI_MANUFACTPAGE_DEVID_SAS1068              (0x0054)
+#define MPI_MANUFACTPAGE_DEVID_SAS1068E             (0x0058)
+#define MPI_MANUFACTPAGE_DEVID_SAS1078              (0x0060)
 
 
 typedef struct _CONFIG_PAGE_MANUFACTURING_0
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     U8                      ChipName[16];               /* 04h */
     U8                      ChipRevision[8];            /* 14h */
     U8                      BoardName[16];              /* 1Ch */
     U8                      BoardAssembly[16];          /* 2Ch */
     U8                      BoardTracerNumber[16];      /* 3Ch */
 
-} fCONFIG_PAGE_MANUFACTURING_0, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_0,
+} CONFIG_PAGE_MANUFACTURING_0, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_0,
   ManufacturingPage0_t, MPI_POINTER pManufacturingPage0_t;
 
 #define MPI_MANUFACTURING0_PAGEVERSION                 (0x00)
@@ -377,9 +512,9 @@
 
 typedef struct _CONFIG_PAGE_MANUFACTURING_1
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     U8                      VPD[256];                   /* 04h */
-} fCONFIG_PAGE_MANUFACTURING_1, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_1,
+} CONFIG_PAGE_MANUFACTURING_1, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_1,
   ManufacturingPage1_t, MPI_POINTER pManufacturingPage1_t;
 
 #define MPI_MANUFACTURING1_PAGEVERSION                 (0x00)
@@ -404,10 +539,10 @@
 
 typedef struct _CONFIG_PAGE_MANUFACTURING_2
 {
-    fCONFIG_PAGE_HEADER      Header;                                 /* 00h */
+    CONFIG_PAGE_HEADER      Header;                                 /* 00h */
     MPI_CHIP_REVISION_ID    ChipId;                                 /* 04h */
     U32                     HwSettings[MPI_MAN_PAGE_2_HW_SETTINGS_WORDS];/* 08h */
-} fCONFIG_PAGE_MANUFACTURING_2, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_2,
+} CONFIG_PAGE_MANUFACTURING_2, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_2,
   ManufacturingPage2_t, MPI_POINTER pManufacturingPage2_t;
 
 #define MPI_MANUFACTURING2_PAGEVERSION                  (0x00)
@@ -423,10 +558,10 @@
 
 typedef struct _CONFIG_PAGE_MANUFACTURING_3
 {
-    fCONFIG_PAGE_HEADER                  Header;                     /* 00h */
+    CONFIG_PAGE_HEADER                  Header;                     /* 00h */
     MPI_CHIP_REVISION_ID                ChipId;                     /* 04h */
     U32                                 Info[MPI_MAN_PAGE_3_INFO_WORDS];/* 08h */
-} fCONFIG_PAGE_MANUFACTURING_3, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_3,
+} CONFIG_PAGE_MANUFACTURING_3, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_3,
   ManufacturingPage3_t, MPI_POINTER pManufacturingPage3_t;
 
 #define MPI_MANUFACTURING3_PAGEVERSION                  (0x00)
@@ -434,7 +569,7 @@
 
 typedef struct _CONFIG_PAGE_MANUFACTURING_4
 {
-    fCONFIG_PAGE_HEADER              Header;             /* 00h */
+    CONFIG_PAGE_HEADER              Header;             /* 00h */
     U32                             Reserved1;          /* 04h */
     U8                              InfoOffset0;        /* 08h */
     U8                              InfoSize0;          /* 09h */
@@ -447,10 +582,23 @@
     U32                             ISVolumeSettings;   /* 48h */
     U32                             IMEVolumeSettings;  /* 4Ch */
     U32                             IMVolumeSettings;   /* 50h */
-} fCONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4,
+    U32                             Reserved3;          /* 54h */
+    U32                             Reserved4;          /* 58h */
+    U8                              ISDataScrubRate;    /* 5Ch */
+    U8                              ISResyncRate;       /* 5Dh */
+    U16                             Reserved5;          /* 5Eh */
+    U8                              IMEDataScrubRate;   /* 60h */
+    U8                              IMEResyncRate;      /* 61h */
+    U16                             Reserved6;          /* 62h */
+    U8                              IMDataScrubRate;    /* 64h */
+    U8                              IMResyncRate;       /* 65h */
+    U16                             Reserved7;          /* 66h */
+    U32                             Reserved8;          /* 68h */
+    U32                             Reserved9;          /* 6Ch */
+} CONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4,
   ManufacturingPage4_t, MPI_POINTER pManufacturingPage4_t;
 
-#define MPI_MANUFACTURING4_PAGEVERSION                  (0x01)
+#define MPI_MANUFACTURING4_PAGEVERSION                  (0x02)
 
 /* defines for the Flags field */
 #define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA                 (0x01)
@@ -458,19 +606,25 @@
 
 typedef struct _CONFIG_PAGE_MANUFACTURING_5
 {
-    fCONFIG_PAGE_HEADER              Header;             /* 00h */
+    CONFIG_PAGE_HEADER              Header;             /* 00h */
     U64                             BaseWWID;           /* 04h */
-} fCONFIG_PAGE_MANUFACTURING_5, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_5,
+    U8                              Flags;              /* 0Ch */
+    U8                              Reserved1;          /* 0Dh */
+    U16                             Reserved2;          /* 0Eh */
+} CONFIG_PAGE_MANUFACTURING_5, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_5,
   ManufacturingPage5_t, MPI_POINTER pManufacturingPage5_t;
 
-#define MPI_MANUFACTURING5_PAGEVERSION                  (0x00)
+#define MPI_MANUFACTURING5_PAGEVERSION                  (0x01)
+
+/* defines for the Flags field */
+#define MPI_MANPAGE5_TWO_WWID_PER_PHY                   (0x01)
 
 
 typedef struct _CONFIG_PAGE_MANUFACTURING_6
 {
-    fCONFIG_PAGE_HEADER              Header;             /* 00h */
+    CONFIG_PAGE_HEADER              Header;             /* 00h */
     U32                             ProductSpecificInfo;/* 04h */
-} fCONFIG_PAGE_MANUFACTURING_6, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_6,
+} CONFIG_PAGE_MANUFACTURING_6, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_6,
   ManufacturingPage6_t, MPI_POINTER pManufacturingPage6_t;
 
 #define MPI_MANUFACTURING6_PAGEVERSION                  (0x00)
@@ -482,9 +636,9 @@
 
 typedef struct _CONFIG_PAGE_IO_UNIT_0
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     U64                     UniqueValue;                /* 04h */
-} fCONFIG_PAGE_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_0,
+} CONFIG_PAGE_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_0,
   IOUnitPage0_t, MPI_POINTER pIOUnitPage0_t;
 
 #define MPI_IOUNITPAGE0_PAGEVERSION                     (0x00)
@@ -492,9 +646,9 @@
 
 typedef struct _CONFIG_PAGE_IO_UNIT_1
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     U32                     Flags;                      /* 04h */
-} fCONFIG_PAGE_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_1,
+} CONFIG_PAGE_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_1,
   IOUnitPage1_t, MPI_POINTER pIOUnitPage1_t;
 
 #define MPI_IOUNITPAGE1_PAGEVERSION                     (0x01)
@@ -524,14 +678,15 @@
 
 typedef struct _CONFIG_PAGE_IO_UNIT_2
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     U32                     Flags;                      /* 04h */
     U32                     BiosVersion;                /* 08h */
     MPI_ADAPTER_INFO        AdapterOrder[4];            /* 0Ch */
-} fCONFIG_PAGE_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_2,
+    U32                     Reserved1;                  /* 1Ch */
+} CONFIG_PAGE_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_2,
   IOUnitPage2_t, MPI_POINTER pIOUnitPage2_t;
 
-#define MPI_IOUNITPAGE2_PAGEVERSION                     (0x00)
+#define MPI_IOUNITPAGE2_PAGEVERSION                     (0x02)
 
 #define MPI_IOUNITPAGE2_FLAGS_PAUSE_ON_ERROR            (0x00000002)
 #define MPI_IOUNITPAGE2_FLAGS_VERBOSE_ENABLE            (0x00000004)
@@ -554,12 +709,12 @@
 
 typedef struct _CONFIG_PAGE_IO_UNIT_3
 {
-    fCONFIG_PAGE_HEADER      Header;                                   /* 00h */
+    CONFIG_PAGE_HEADER      Header;                                   /* 00h */
     U8                      GPIOCount;                                /* 04h */
     U8                      Reserved1;                                /* 05h */
     U16                     Reserved2;                                /* 06h */
     U16                     GPIOVal[MPI_IO_UNIT_PAGE_3_GPIO_VAL_MAX]; /* 08h */
-} fCONFIG_PAGE_IO_UNIT_3, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_3,
+} CONFIG_PAGE_IO_UNIT_3, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_3,
   IOUnitPage3_t, MPI_POINTER pIOUnitPage3_t;
 
 #define MPI_IOUNITPAGE3_PAGEVERSION                     (0x01)
@@ -570,13 +725,24 @@
 #define MPI_IOUNITPAGE3_GPIO_SETTING_ON                 (0x01)
 
 
+typedef struct _CONFIG_PAGE_IO_UNIT_4
+{
+    CONFIG_PAGE_HEADER      Header;                                   /* 00h */
+    U32                     Reserved1;                                /* 04h */
+    SGE_SIMPLE_UNION        FWImageSGE;                               /* 08h */
+} CONFIG_PAGE_IO_UNIT_4, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_4,
+  IOUnitPage4_t, MPI_POINTER pIOUnitPage4_t;
+
+#define MPI_IOUNITPAGE4_PAGEVERSION                     (0x00)
+
+
 /****************************************************************************
 *   IOC Config Pages
 ****************************************************************************/
 
 typedef struct _CONFIG_PAGE_IOC_0
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     U32                     TotalNVStore;               /* 04h */
     U32                     FreeNVStore;                /* 08h */
     U16                     VendorID;                   /* 0Ch */
@@ -586,7 +752,7 @@
     U32                     ClassCode;                  /* 14h */
     U16                     SubsystemVendorID;          /* 18h */
     U16                     SubsystemID;                /* 1Ah */
-} fCONFIG_PAGE_IOC_0, MPI_POINTER PTR_CONFIG_PAGE_IOC_0,
+} CONFIG_PAGE_IOC_0, MPI_POINTER PTR_CONFIG_PAGE_IOC_0,
   IOCPage0_t, MPI_POINTER pIOCPage0_t;
 
 #define MPI_IOCPAGE0_PAGEVERSION                        (0x01)
@@ -594,23 +760,19 @@
 
 typedef struct _CONFIG_PAGE_IOC_1
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     U32                     Flags;                      /* 04h */
     U32                     CoalescingTimeout;          /* 08h */
     U8                      CoalescingDepth;            /* 0Ch */
     U8                      PCISlotNum;                 /* 0Dh */
     U8                      Reserved[2];                /* 0Eh */
-} fCONFIG_PAGE_IOC_1, MPI_POINTER PTR_CONFIG_PAGE_IOC_1,
+} CONFIG_PAGE_IOC_1, MPI_POINTER PTR_CONFIG_PAGE_IOC_1,
   IOCPage1_t, MPI_POINTER pIOCPage1_t;
 
-#define MPI_IOCPAGE1_PAGEVERSION                        (0x01)
+#define MPI_IOCPAGE1_PAGEVERSION                        (0x02)
 
 /* defines for the Flags field */
-#define MPI_IOCPAGE1_EEDP_HOST_SUPPORTS_DIF             (0x08000000)
-#define MPI_IOCPAGE1_EEDP_MODE_MASK                     (0x07000000)
-#define MPI_IOCPAGE1_EEDP_MODE_OFF                      (0x00000000)
-#define MPI_IOCPAGE1_EEDP_MODE_T10                      (0x01000000)
-#define MPI_IOCPAGE1_EEDP_MODE_LSI_1                    (0x02000000)
+#define MPI_IOCPAGE1_INITIATOR_CONTEXT_REPLY_DISABLE    (0x00000010)
 #define MPI_IOCPAGE1_REPLY_COALESCING                   (0x00000001)
 
 #define MPI_IOCPAGE1_PCISLOTNUM_UNKNOWN                 (0xFF)
@@ -625,7 +787,7 @@
     U8                          VolumeType;             /* 04h */
     U8                          Flags;                  /* 05h */
     U16                         Reserved3;              /* 06h */
-} fCONFIG_PAGE_IOC_2_RAID_VOL, MPI_POINTER PTR_CONFIG_PAGE_IOC_2_RAID_VOL,
+} CONFIG_PAGE_IOC_2_RAID_VOL, MPI_POINTER PTR_CONFIG_PAGE_IOC_2_RAID_VOL,
   ConfigPageIoc2RaidVol_t, MPI_POINTER pConfigPageIoc2RaidVol_t;
 
 /* IOC Page 2 Volume RAID Type values, also used in RAID Volume pages */
@@ -648,14 +810,14 @@
 
 typedef struct _CONFIG_PAGE_IOC_2
 {
-    fCONFIG_PAGE_HEADER          Header;                              /* 00h */
+    CONFIG_PAGE_HEADER          Header;                              /* 00h */
     U32                         CapabilitiesFlags;                   /* 04h */
     U8                          NumActiveVolumes;                    /* 08h */
     U8                          MaxVolumes;                          /* 09h */
     U8                          NumActivePhysDisks;                  /* 0Ah */
     U8                          MaxPhysDisks;                        /* 0Bh */
-    fCONFIG_PAGE_IOC_2_RAID_VOL  RaidVolume[MPI_IOC_PAGE_2_RAID_VOLUME_MAX];/* 0Ch */
-} fCONFIG_PAGE_IOC_2, MPI_POINTER PTR_CONFIG_PAGE_IOC_2,
+    CONFIG_PAGE_IOC_2_RAID_VOL  RaidVolume[MPI_IOC_PAGE_2_RAID_VOLUME_MAX];/* 0Ch */
+} CONFIG_PAGE_IOC_2, MPI_POINTER PTR_CONFIG_PAGE_IOC_2,
   IOCPage2_t, MPI_POINTER pIOCPage2_t;
 
 #define MPI_IOCPAGE2_PAGEVERSION                        (0x02)
@@ -689,12 +851,12 @@
 
 typedef struct _CONFIG_PAGE_IOC_3
 {
-    fCONFIG_PAGE_HEADER          Header;                                /* 00h */
+    CONFIG_PAGE_HEADER          Header;                                /* 00h */
     U8                          NumPhysDisks;                          /* 04h */
     U8                          Reserved1;                             /* 05h */
     U16                         Reserved2;                             /* 06h */
     IOC_3_PHYS_DISK             PhysDisk[MPI_IOC_PAGE_3_PHYSDISK_MAX]; /* 08h */
-} fCONFIG_PAGE_IOC_3, MPI_POINTER PTR_CONFIG_PAGE_IOC_3,
+} CONFIG_PAGE_IOC_3, MPI_POINTER PTR_CONFIG_PAGE_IOC_3,
   IOCPage3_t, MPI_POINTER pIOCPage3_t;
 
 #define MPI_IOCPAGE3_PAGEVERSION                        (0x00)
@@ -718,12 +880,12 @@
 
 typedef struct _CONFIG_PAGE_IOC_4
 {
-    fCONFIG_PAGE_HEADER          Header;                         /* 00h */
+    CONFIG_PAGE_HEADER          Header;                         /* 00h */
     U8                          ActiveSEP;                      /* 04h */
     U8                          MaxSEP;                         /* 05h */
     U16                         Reserved1;                      /* 06h */
     IOC_4_SEP                   SEP[MPI_IOC_PAGE_4_SEP_MAX];    /* 08h */
-} fCONFIG_PAGE_IOC_4, MPI_POINTER PTR_CONFIG_PAGE_IOC_4,
+} CONFIG_PAGE_IOC_4, MPI_POINTER PTR_CONFIG_PAGE_IOC_4,
   IOCPage4_t, MPI_POINTER pIOCPage4_t;
 
 #define MPI_IOCPAGE4_PAGEVERSION                        (0x00)
@@ -751,25 +913,25 @@
 
 typedef struct _CONFIG_PAGE_IOC_5
 {
-    fCONFIG_PAGE_HEADER          Header;                         /* 00h */
+    CONFIG_PAGE_HEADER          Header;                         /* 00h */
     U32                         Reserved1;                      /* 04h */
     U8                          NumHotSpares;                   /* 08h */
     U8                          Reserved2;                      /* 09h */
     U16                         Reserved3;                      /* 0Ah */
     IOC_5_HOT_SPARE             HotSpare[MPI_IOC_PAGE_5_HOT_SPARE_MAX]; /* 0Ch */
-} fCONFIG_PAGE_IOC_5, MPI_POINTER PTR_CONFIG_PAGE_IOC_5,
+} CONFIG_PAGE_IOC_5, MPI_POINTER PTR_CONFIG_PAGE_IOC_5,
   IOCPage5_t, MPI_POINTER pIOCPage5_t;
 
 #define MPI_IOCPAGE5_PAGEVERSION                        (0x00)
 
 
 /****************************************************************************
-*   BIOS Port Config Pages
+*   BIOS Config Pages
 ****************************************************************************/
 
 typedef struct _CONFIG_PAGE_BIOS_1
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     U32                     BiosOptions;                /* 04h */
     U32                     IOCSettings;                /* 08h */
     U32                     Reserved1;                  /* 0Ch */
@@ -780,10 +942,10 @@
     U16                     IOTimeoutSequential;        /* 1Ah */
     U16                     IOTimeoutOther;             /* 1Ch */
     U16                     IOTimeoutBlockDevicesRM;    /* 1Eh */
-} fCONFIG_PAGE_BIOS_1, MPI_POINTER PTR_CONFIG_PAGE_BIOS_1,
+} CONFIG_PAGE_BIOS_1, MPI_POINTER PTR_CONFIG_PAGE_BIOS_1,
   BIOSPage1_t, MPI_POINTER pBIOSPage1_t;
 
-#define MPI_BIOSPAGE1_PAGEVERSION                       (0x00)
+#define MPI_BIOSPAGE1_PAGEVERSION                       (0x01)
 
 /* values for the BiosOptions field */
 #define MPI_BIOSPAGE1_OPTIONS_SPI_ENABLE                (0x00000400)
@@ -792,6 +954,13 @@
 #define MPI_BIOSPAGE1_OPTIONS_DISABLE_BIOS              (0x00000001)
 
 /* values for the IOCSettings field */
+#define MPI_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE       (0x00030000)
+#define MPI_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT        (0x00000000)
+#define MPI_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT           (0x00010000)
+
+#define MPI_BIOSPAGE1_IOCSET_MASK_MAX_TARGET_SPIN_UP    (0x0000F000)
+#define MPI_BIOSPAGE1_IOCSET_SHIFT_MAX_TARGET_SPIN_UP   (12)
+
 #define MPI_BIOSPAGE1_IOCSET_MASK_SPINUP_DELAY          (0x00000F00)
 #define MPI_BIOSPAGE1_IOCSET_SHIFT_SPINUP_DELAY         (8)
 
@@ -814,6 +983,191 @@
 #define MPI_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN         (0x00000002)
 #define MPI_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN          (0x00000001)
 
+typedef struct _MPI_BOOT_DEVICE_ADAPTER_ORDER
+{
+    U32         Reserved1;                              /* 00h */
+    U32         Reserved2;                              /* 04h */
+    U32         Reserved3;                              /* 08h */
+    U32         Reserved4;                              /* 0Ch */
+    U32         Reserved5;                              /* 10h */
+    U32         Reserved6;                              /* 14h */
+    U32         Reserved7;                              /* 18h */
+    U32         Reserved8;                              /* 1Ch */
+    U32         Reserved9;                              /* 20h */
+    U32         Reserved10;                             /* 24h */
+    U32         Reserved11;                             /* 28h */
+    U32         Reserved12;                             /* 2Ch */
+    U32         Reserved13;                             /* 30h */
+    U32         Reserved14;                             /* 34h */
+    U32         Reserved15;                             /* 38h */
+    U32         Reserved16;                             /* 3Ch */
+    U32         Reserved17;                             /* 40h */
+} MPI_BOOT_DEVICE_ADAPTER_ORDER, MPI_POINTER PTR_MPI_BOOT_DEVICE_ADAPTER_ORDER;
+
+typedef struct _MPI_BOOT_DEVICE_ADAPTER_NUMBER
+{
+    U8          TargetID;                               /* 00h */
+    U8          Bus;                                    /* 01h */
+    U8          AdapterNumber;                          /* 02h */
+    U8          Reserved1;                              /* 03h */
+    U32         Reserved2;                              /* 04h */
+    U32         Reserved3;                              /* 08h */
+    U32         Reserved4;                              /* 0Ch */
+    U8          LUN[8];                                 /* 10h */
+    U32         Reserved5;                              /* 18h */
+    U32         Reserved6;                              /* 1Ch */
+    U32         Reserved7;                              /* 20h */
+    U32         Reserved8;                              /* 24h */
+    U32         Reserved9;                              /* 28h */
+    U32         Reserved10;                             /* 2Ch */
+    U32         Reserved11;                             /* 30h */
+    U32         Reserved12;                             /* 34h */
+    U32         Reserved13;                             /* 38h */
+    U32         Reserved14;                             /* 3Ch */
+    U32         Reserved15;                             /* 40h */
+} MPI_BOOT_DEVICE_ADAPTER_NUMBER, MPI_POINTER PTR_MPI_BOOT_DEVICE_ADAPTER_NUMBER;
+
+typedef struct _MPI_BOOT_DEVICE_PCI_ADDRESS
+{
+    U8          TargetID;                               /* 00h */
+    U8          Bus;                                    /* 01h */
+    U16         PCIAddress;                             /* 02h */
+    U32         Reserved1;                              /* 04h */
+    U32         Reserved2;                              /* 08h */
+    U32         Reserved3;                              /* 0Ch */
+    U8          LUN[8];                                 /* 10h */
+    U32         Reserved4;                              /* 18h */
+    U32         Reserved5;                              /* 1Ch */
+    U32         Reserved6;                              /* 20h */
+    U32         Reserved7;                              /* 24h */
+    U32         Reserved8;                              /* 28h */
+    U32         Reserved9;                              /* 2Ch */
+    U32         Reserved10;                             /* 30h */
+    U32         Reserved11;                             /* 34h */
+    U32         Reserved12;                             /* 38h */
+    U32         Reserved13;                             /* 3Ch */
+    U32         Reserved14;                             /* 40h */
+} MPI_BOOT_DEVICE_PCI_ADDRESS, MPI_POINTER PTR_MPI_BOOT_DEVICE_PCI_ADDRESS;
+
+typedef struct _MPI_BOOT_DEVICE_SLOT_NUMBER
+{
+    U8          TargetID;                               /* 00h */
+    U8          Bus;                                    /* 01h */
+    U8          PCISlotNumber;                          /* 02h */
+    U8          Reserved1;                              /* 03h */
+    U32         Reserved2;                              /* 04h */
+    U32         Reserved3;                              /* 08h */
+    U32         Reserved4;                              /* 0Ch */
+    U8          LUN[8];                                 /* 10h */
+    U32         Reserved5;                              /* 18h */
+    U32         Reserved6;                              /* 1Ch */
+    U32         Reserved7;                              /* 20h */
+    U32         Reserved8;                              /* 24h */
+    U32         Reserved9;                              /* 28h */
+    U32         Reserved10;                             /* 2Ch */
+    U32         Reserved11;                             /* 30h */
+    U32         Reserved12;                             /* 34h */
+    U32         Reserved13;                             /* 38h */
+    U32         Reserved14;                             /* 3Ch */
+    U32         Reserved15;                             /* 40h */
+} MPI_BOOT_DEVICE_PCI_SLOT_NUMBER, MPI_POINTER PTR_MPI_BOOT_DEVICE_PCI_SLOT_NUMBER;
+
+typedef struct _MPI_BOOT_DEVICE_FC_WWN
+{
+    U64         WWPN;                                   /* 00h */
+    U32         Reserved1;                              /* 08h */
+    U32         Reserved2;                              /* 0Ch */
+    U8          LUN[8];                                 /* 10h */
+    U32         Reserved3;                              /* 18h */
+    U32         Reserved4;                              /* 1Ch */
+    U32         Reserved5;                              /* 20h */
+    U32         Reserved6;                              /* 24h */
+    U32         Reserved7;                              /* 28h */
+    U32         Reserved8;                              /* 2Ch */
+    U32         Reserved9;                              /* 30h */
+    U32         Reserved10;                             /* 34h */
+    U32         Reserved11;                             /* 38h */
+    U32         Reserved12;                             /* 3Ch */
+    U32         Reserved13;                             /* 40h */
+} MPI_BOOT_DEVICE_FC_WWN, MPI_POINTER PTR_MPI_BOOT_DEVICE_FC_WWN;
+
+typedef struct _MPI_BOOT_DEVICE_SAS_WWN
+{
+    U64         SASAddress;                             /* 00h */
+    U32         Reserved1;                              /* 08h */
+    U32         Reserved2;                              /* 0Ch */
+    U8          LUN[8];                                 /* 10h */
+    U32         Reserved3;                              /* 18h */
+    U32         Reserved4;                              /* 1Ch */
+    U32         Reserved5;                              /* 20h */
+    U32         Reserved6;                              /* 24h */
+    U32         Reserved7;                              /* 28h */
+    U32         Reserved8;                              /* 2Ch */
+    U32         Reserved9;                              /* 30h */
+    U32         Reserved10;                             /* 34h */
+    U32         Reserved11;                             /* 38h */
+    U32         Reserved12;                             /* 3Ch */
+    U32         Reserved13;                             /* 40h */
+} MPI_BOOT_DEVICE_SAS_WWN, MPI_POINTER PTR_MPI_BOOT_DEVICE_SAS_WWN;
+
+typedef struct _MPI_BOOT_DEVICE_ENCLOSURE_SLOT
+{
+    U64         EnclosureLogicalID;                     /* 00h */
+    U32         Reserved1;                              /* 08h */
+    U32         Reserved2;                              /* 0Ch */
+    U8          LUN[8];                                 /* 10h */
+    U16         SlotNumber;                             /* 18h */
+    U16         Reserved3;                              /* 1Ah */
+    U32         Reserved4;                              /* 1Ch */
+    U32         Reserved5;                              /* 20h */
+    U32         Reserved6;                              /* 24h */
+    U32         Reserved7;                              /* 28h */
+    U32         Reserved8;                              /* 2Ch */
+    U32         Reserved9;                              /* 30h */
+    U32         Reserved10;                             /* 34h */
+    U32         Reserved11;                             /* 38h */
+    U32         Reserved12;                             /* 3Ch */
+    U32         Reserved13;                             /* 40h */
+} MPI_BOOT_DEVICE_ENCLOSURE_SLOT,
+  MPI_POINTER PTR_MPI_BOOT_DEVICE_ENCLOSURE_SLOT;
+
+typedef union _MPI_BIOSPAGE2_BOOT_DEVICE
+{
+    MPI_BOOT_DEVICE_ADAPTER_ORDER   AdapterOrder;
+    MPI_BOOT_DEVICE_ADAPTER_NUMBER  AdapterNumber;
+    MPI_BOOT_DEVICE_PCI_ADDRESS     PCIAddress;
+    MPI_BOOT_DEVICE_PCI_SLOT_NUMBER PCISlotNumber;
+    MPI_BOOT_DEVICE_FC_WWN          FcWwn;
+    MPI_BOOT_DEVICE_SAS_WWN         SasWwn;
+    MPI_BOOT_DEVICE_ENCLOSURE_SLOT  EnclosureSlot;
+} MPI_BIOSPAGE2_BOOT_DEVICE, MPI_POINTER PTR_MPI_BIOSPAGE2_BOOT_DEVICE;
+
+typedef struct _CONFIG_PAGE_BIOS_2
+{
+    CONFIG_PAGE_HEADER          Header;                 /* 00h */
+    U32                         Reserved1;              /* 04h */
+    U32                         Reserved2;              /* 08h */
+    U32                         Reserved3;              /* 0Ch */
+    U32                         Reserved4;              /* 10h */
+    U32                         Reserved5;              /* 14h */
+    U32                         Reserved6;              /* 18h */
+    U8                          BootDeviceForm;         /* 1Ch */
+    U8                          Reserved7;              /* 1Dh */
+    U16                         Reserved8;              /* 1Eh */
+    MPI_BIOSPAGE2_BOOT_DEVICE   BootDevice;             /* 20h */
+} CONFIG_PAGE_BIOS_2, MPI_POINTER PTR_CONFIG_PAGE_BIOS_2,
+  BIOSPage2_t, MPI_POINTER pBIOSPage2_t;
+
+#define MPI_BIOSPAGE2_PAGEVERSION                       (0x01)
+
+#define MPI_BIOSPAGE2_FORM_MASK                         (0x0F)
+#define MPI_BIOSPAGE2_FORM_ADAPTER_ORDER                (0x00)
+#define MPI_BIOSPAGE2_FORM_ADAPTER_NUMBER               (0x01)
+#define MPI_BIOSPAGE2_FORM_PCI_ADDRESS                  (0x02)
+#define MPI_BIOSPAGE2_FORM_PCI_SLOT_NUMBER              (0x03)
+#define MPI_BIOSPAGE2_FORM_FC_WWN                       (0x04)
+#define MPI_BIOSPAGE2_FORM_SAS_WWN                      (0x05)
+
 
 /****************************************************************************
 *   SCSI Port Config Pages
@@ -821,13 +1175,13 @@
 
 typedef struct _CONFIG_PAGE_SCSI_PORT_0
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     U32                     Capabilities;               /* 04h */
     U32                     PhysicalInterface;          /* 08h */
-} fCONFIG_PAGE_SCSI_PORT_0, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_0,
+} CONFIG_PAGE_SCSI_PORT_0, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_0,
   SCSIPortPage0_t, MPI_POINTER pSCSIPortPage0_t;
 
-#define MPI_SCSIPORTPAGE0_PAGEVERSION                   (0x01)
+#define MPI_SCSIPORTPAGE0_PAGEVERSION                   (0x02)
 
 #define MPI_SCSIPORTPAGE0_CAP_IU                        (0x00000001)
 #define MPI_SCSIPORTPAGE0_CAP_DT                        (0x00000002)
@@ -854,6 +1208,7 @@
     (  ((Cap) & MPI_SCSIPORTPAGE0_CAP_MASK_MAX_SYNC_OFFSET) \
     >> MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET          \
     )
+#define MPI_SCSIPORTPAGE0_CAP_IDP                       (0x08000000)
 #define MPI_SCSIPORTPAGE0_CAP_WIDE                      (0x20000000)
 #define MPI_SCSIPORTPAGE0_CAP_AIP                       (0x80000000)
 
@@ -869,13 +1224,13 @@
 
 typedef struct _CONFIG_PAGE_SCSI_PORT_1
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     U32                     Configuration;              /* 04h */
     U32                     OnBusTimerValue;            /* 08h */
     U8                      TargetConfig;               /* 0Ch */
     U8                      Reserved1;                  /* 0Dh */
     U16                     IDConfig;                   /* 0Eh */
-} fCONFIG_PAGE_SCSI_PORT_1, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_1,
+} CONFIG_PAGE_SCSI_PORT_1, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_1,
   SCSIPortPage1_t, MPI_POINTER pSCSIPortPage1_t;
 
 #define MPI_SCSIPORTPAGE1_PAGEVERSION                   (0x03)
@@ -900,11 +1255,11 @@
 
 typedef struct _CONFIG_PAGE_SCSI_PORT_2
 {
-    fCONFIG_PAGE_HEADER  Header;                         /* 00h */
+    CONFIG_PAGE_HEADER  Header;                         /* 00h */
     U32                 PortFlags;                      /* 04h */
     U32                 PortSettings;                   /* 08h */
     MPI_DEVICE_INFO     DeviceSettings[16];             /* 0Ch */
-} fCONFIG_PAGE_SCSI_PORT_2, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_2,
+} CONFIG_PAGE_SCSI_PORT_2, MPI_POINTER PTR_CONFIG_PAGE_SCSI_PORT_2,
   SCSIPortPage2_t, MPI_POINTER pSCSIPortPage2_t;
 
 #define MPI_SCSIPORTPAGE2_PAGEVERSION                       (0x02)
@@ -953,13 +1308,13 @@
 
 typedef struct _CONFIG_PAGE_SCSI_DEVICE_0
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     U32                     NegotiatedParameters;       /* 04h */
     U32                     Information;                /* 08h */
-} fCONFIG_PAGE_SCSI_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_0,
+} CONFIG_PAGE_SCSI_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_0,
   SCSIDevicePage0_t, MPI_POINTER pSCSIDevicePage0_t;
 
-#define MPI_SCSIDEVPAGE0_PAGEVERSION                    (0x03)
+#define MPI_SCSIDEVPAGE0_PAGEVERSION                    (0x04)
 
 #define MPI_SCSIDEVPAGE0_NP_IU                          (0x00000001)
 #define MPI_SCSIDEVPAGE0_NP_DT                          (0x00000002)
@@ -973,6 +1328,7 @@
 #define MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_PERIOD           (8)
 #define MPI_SCSIDEVPAGE0_NP_NEG_SYNC_OFFSET_MASK        (0x00FF0000)
 #define MPI_SCSIDEVPAGE0_NP_SHIFT_SYNC_OFFSET           (16)
+#define MPI_SCSIDEVPAGE0_NP_IDP                         (0x08000000)
 #define MPI_SCSIDEVPAGE0_NP_WIDE                        (0x20000000)
 #define MPI_SCSIDEVPAGE0_NP_AIP                         (0x80000000)
 
@@ -984,14 +1340,14 @@
 
 typedef struct _CONFIG_PAGE_SCSI_DEVICE_1
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     U32                     RequestedParameters;        /* 04h */
     U32                     Reserved;                   /* 08h */
     U32                     Configuration;              /* 0Ch */
-} fCONFIG_PAGE_SCSI_DEVICE_1, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_1,
+} CONFIG_PAGE_SCSI_DEVICE_1, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_1,
   SCSIDevicePage1_t, MPI_POINTER pSCSIDevicePage1_t;
 
-#define MPI_SCSIDEVPAGE1_PAGEVERSION                    (0x04)
+#define MPI_SCSIDEVPAGE1_PAGEVERSION                    (0x05)
 
 #define MPI_SCSIDEVPAGE1_RP_IU                          (0x00000001)
 #define MPI_SCSIDEVPAGE1_RP_DT                          (0x00000002)
@@ -1005,6 +1361,7 @@
 #define MPI_SCSIDEVPAGE1_RP_SHIFT_MIN_SYNC_PERIOD       (8)
 #define MPI_SCSIDEVPAGE1_RP_MAX_SYNC_OFFSET_MASK        (0x00FF0000)
 #define MPI_SCSIDEVPAGE1_RP_SHIFT_MAX_SYNC_OFFSET       (16)
+#define MPI_SCSIDEVPAGE1_RP_IDP                         (0x08000000)
 #define MPI_SCSIDEVPAGE1_RP_WIDE                        (0x20000000)
 #define MPI_SCSIDEVPAGE1_RP_AIP                         (0x80000000)
 
@@ -1016,11 +1373,11 @@
 
 typedef struct _CONFIG_PAGE_SCSI_DEVICE_2
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     U32                     DomainValidation;           /* 04h */
     U32                     ParityPipeSelect;           /* 08h */
     U32                     DataPipeSelect;             /* 0Ch */
-} fCONFIG_PAGE_SCSI_DEVICE_2, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_2,
+} CONFIG_PAGE_SCSI_DEVICE_2, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_2,
   SCSIDevicePage2_t, MPI_POINTER pSCSIDevicePage2_t;
 
 #define MPI_SCSIDEVPAGE2_PAGEVERSION                    (0x01)
@@ -1057,12 +1414,12 @@
 
 typedef struct _CONFIG_PAGE_SCSI_DEVICE_3
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     U16                     MsgRejectCount;             /* 04h */
     U16                     PhaseErrorCount;            /* 06h */
     U16                     ParityErrorCount;           /* 08h */
     U16                     Reserved;                   /* 0Ah */
-} fCONFIG_PAGE_SCSI_DEVICE_3, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_3,
+} CONFIG_PAGE_SCSI_DEVICE_3, MPI_POINTER PTR_CONFIG_PAGE_SCSI_DEVICE_3,
   SCSIDevicePage3_t, MPI_POINTER pSCSIDevicePage3_t;
 
 #define MPI_SCSIDEVPAGE3_PAGEVERSION                    (0x00)
@@ -1077,7 +1434,7 @@
 
 typedef struct _CONFIG_PAGE_FC_PORT_0
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     U32                     Flags;                      /* 04h */
     U8                      MPIPortNumber;              /* 08h */
     U8                      LinkType;                   /* 09h */
@@ -1098,7 +1455,7 @@
     U8                      MaxHardAliasesSupported;    /* 49h */
     U8                      NumCurrentAliases;          /* 4Ah */
     U8                      Reserved1;                  /* 4Bh */
-} fCONFIG_PAGE_FC_PORT_0, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_0,
+} CONFIG_PAGE_FC_PORT_0, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_0,
   FCPortPage0_t, MPI_POINTER pFCPortPage0_t;
 
 #define MPI_FCPORTPAGE0_PAGEVERSION                     (0x02)
@@ -1164,10 +1521,9 @@
 #define MPI_FCPORTPAGE0_CURRENT_SPEED_NOT_NEGOTIATED    (0x00008000)        /* (SNIA)HBA_PORTSPEED_NOT_NEGOTIATED (1<<15) Speed not established */
 
 
-
 typedef struct _CONFIG_PAGE_FC_PORT_1
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     U32                     Flags;                      /* 04h */
     U64                     NoSEEPROMWWNN;              /* 08h */
     U64                     NoSEEPROMWWPN;              /* 10h */
@@ -1179,7 +1535,7 @@
     U8                      RR_TOV;                     /* 1Dh */
     U8                      InitiatorDeviceTimeout;     /* 1Eh */
     U8                      InitiatorIoPendTimeout;     /* 1Fh */
-} fCONFIG_PAGE_FC_PORT_1, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_1,
+} CONFIG_PAGE_FC_PORT_1, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_1,
   FCPortPage1_t, MPI_POINTER pFCPortPage1_t;
 
 #define MPI_FCPORTPAGE1_PAGEVERSION                     (0x06)
@@ -1191,6 +1547,7 @@
 #define MPI_FCPORTPAGE1_FLAGS_TARGET_MODE_OXID          (0x00800000)
 #define MPI_FCPORTPAGE1_FLAGS_PORT_OFFLINE              (0x00400000)
 #define MPI_FCPORTPAGE1_FLAGS_SOFT_ALPA_FALLBACK        (0x00200000)
+#define MPI_FCPORTPAGE1_FLAGS_TARGET_LARGE_CDB_ENABLE   (0x00000080)
 #define MPI_FCPORTPAGE1_FLAGS_MASK_RR_TOV_UNITS         (0x00000070)
 #define MPI_FCPORTPAGE1_FLAGS_SUPPRESS_PROT_REG         (0x00000008)
 #define MPI_FCPORTPAGE1_FLAGS_PLOGI_ON_LOGO             (0x00000004)
@@ -1227,14 +1584,15 @@
 #define MPI_FCPORTPAGE1_ALT_CONN_UNKNOWN                (0x00)
 
 #define MPI_FCPORTPAGE1_INITIATOR_DEV_TIMEOUT_MASK      (0x7F)
+#define MPI_FCPORTPAGE1_INITIATOR_DEV_UNIT_16           (0x80)
 
 
 typedef struct _CONFIG_PAGE_FC_PORT_2
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     U8                      NumberActive;               /* 04h */
     U8                      ALPA[127];                  /* 05h */
-} fCONFIG_PAGE_FC_PORT_2, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_2,
+} CONFIG_PAGE_FC_PORT_2, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_2,
   FCPortPage2_t, MPI_POINTER pFCPortPage2_t;
 
 #define MPI_FCPORTPAGE2_PAGEVERSION                     (0x01)
@@ -1280,9 +1638,9 @@
 
 typedef struct _CONFIG_PAGE_FC_PORT_3
 {
-    fCONFIG_PAGE_HEADER      Header;                                 /* 00h */
+    CONFIG_PAGE_HEADER      Header;                                 /* 00h */
     FC_PORT_PERSISTENT      Entry[MPI_FC_PORT_PAGE_3_ENTRY_MAX];    /* 04h */
-} fCONFIG_PAGE_FC_PORT_3, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_3,
+} CONFIG_PAGE_FC_PORT_3, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_3,
   FCPortPage3_t, MPI_POINTER pFCPortPage3_t;
 
 #define MPI_FCPORTPAGE3_PAGEVERSION                     (0x01)
@@ -1290,10 +1648,10 @@
 
 typedef struct _CONFIG_PAGE_FC_PORT_4
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     U32                     PortFlags;                  /* 04h */
     U32                     PortSettings;               /* 08h */
-} fCONFIG_PAGE_FC_PORT_4, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_4,
+} CONFIG_PAGE_FC_PORT_4, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_4,
   FCPortPage4_t, MPI_POINTER pFCPortPage4_t;
 
 #define MPI_FCPORTPAGE4_PAGEVERSION                     (0x00)
@@ -1316,15 +1674,15 @@
     U16     Reserved;                                   /* 02h */
     U64     AliasWWNN;                                  /* 04h */
     U64     AliasWWPN;                                  /* 0Ch */
-} fCONFIG_PAGE_FC_PORT_5_ALIAS_INFO,
+} CONFIG_PAGE_FC_PORT_5_ALIAS_INFO,
   MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_5_ALIAS_INFO,
   FcPortPage5AliasInfo_t, MPI_POINTER pFcPortPage5AliasInfo_t;
 
 typedef struct _CONFIG_PAGE_FC_PORT_5
 {
-    fCONFIG_PAGE_HEADER                  Header;         /* 00h */
-    fCONFIG_PAGE_FC_PORT_5_ALIAS_INFO    AliasInfo;      /* 04h */
-} fCONFIG_PAGE_FC_PORT_5, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_5,
+    CONFIG_PAGE_HEADER                  Header;         /* 00h */
+    CONFIG_PAGE_FC_PORT_5_ALIAS_INFO    AliasInfo;      /* 04h */
+} CONFIG_PAGE_FC_PORT_5, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_5,
   FCPortPage5_t, MPI_POINTER pFCPortPage5_t;
 
 #define MPI_FCPORTPAGE5_PAGEVERSION                     (0x02)
@@ -1337,7 +1695,7 @@
 
 typedef struct _CONFIG_PAGE_FC_PORT_6
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     U32                     Reserved;                   /* 04h */
     U64                     TimeSinceReset;             /* 08h */
     U64                     TxFrames;                   /* 10h */
@@ -1355,7 +1713,7 @@
     U64                     InvalidTxWordCount;         /* 70h */
     U64                     InvalidCrcCount;            /* 78h */
     U64                     FcpInitiatorIoCount;        /* 80h */
-} fCONFIG_PAGE_FC_PORT_6, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_6,
+} CONFIG_PAGE_FC_PORT_6, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_6,
   FCPortPage6_t, MPI_POINTER pFCPortPage6_t;
 
 #define MPI_FCPORTPAGE6_PAGEVERSION                     (0x00)
@@ -1363,10 +1721,10 @@
 
 typedef struct _CONFIG_PAGE_FC_PORT_7
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     U32                     Reserved;                   /* 04h */
     U8                      PortSymbolicName[256];      /* 08h */
-} fCONFIG_PAGE_FC_PORT_7, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_7,
+} CONFIG_PAGE_FC_PORT_7, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_7,
   FCPortPage7_t, MPI_POINTER pFCPortPage7_t;
 
 #define MPI_FCPORTPAGE7_PAGEVERSION                     (0x00)
@@ -1374,9 +1732,9 @@
 
 typedef struct _CONFIG_PAGE_FC_PORT_8
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     U32                     BitVector[8];               /* 04h */
-} fCONFIG_PAGE_FC_PORT_8, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_8,
+} CONFIG_PAGE_FC_PORT_8, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_8,
   FCPortPage8_t, MPI_POINTER pFCPortPage8_t;
 
 #define MPI_FCPORTPAGE8_PAGEVERSION                     (0x00)
@@ -1384,7 +1742,7 @@
 
 typedef struct _CONFIG_PAGE_FC_PORT_9
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     U32                     Reserved;                   /* 04h */
     U64                     GlobalWWPN;                 /* 08h */
     U64                     GlobalWWNN;                 /* 10h */
@@ -1396,7 +1754,7 @@
     U8                      IPAddress[16];              /* 28h */
     U16                     Reserved1;                  /* 38h */
     U16                     TopologyDiscoveryFlags;     /* 3Ah */
-} fCONFIG_PAGE_FC_PORT_9, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_9,
+} CONFIG_PAGE_FC_PORT_9, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_9,
   FCPortPage9_t, MPI_POINTER pFCPortPage9_t;
 
 #define MPI_FCPORTPAGE9_PAGEVERSION                     (0x00)
@@ -1422,10 +1780,10 @@
     U8                      VendorOUI[3];               /* 35h */
     U8                      VendorPN[16];               /* 38h */
     U8                      VendorRev[4];               /* 48h */
-    U16                     Reserved4;                  /* 4Ch */
-    U8                      Reserved5;                  /* 4Eh */
+    U16                     Wavelength;                 /* 4Ch */
+    U8                      Reserved4;                  /* 4Eh */
     U8                      CC_BASE;                    /* 4Fh */
-} fCONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA,
+} CONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA,
   MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA,
   FCPortPage10BaseSfpData_t, MPI_POINTER pFCPortPage10BaseSfpData_t;
 
@@ -1481,9 +1839,11 @@
     U8                      BitRateMin;                 /* 53h */
     U8                      VendorSN[16];               /* 54h */
     U8                      DateCode[8];                /* 64h */
-    U8                      Reserved5[3];               /* 6Ch */
+    U8                      DiagMonitoringType;         /* 6Ch */
+    U8                      EnhancedOptions;            /* 6Dh */
+    U8                      SFF8472Compliance;          /* 6Eh */
     U8                      CC_EXT;                     /* 6Fh */
-} fCONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA,
+} CONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA,
   MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA,
   FCPortPage10ExtendedSfpData_t, MPI_POINTER pFCPortPage10ExtendedSfpData_t;
 
@@ -1496,19 +1856,19 @@
 
 typedef struct _CONFIG_PAGE_FC_PORT_10
 {
-    fCONFIG_PAGE_HEADER                          Header;             /* 00h */
+    CONFIG_PAGE_HEADER                          Header;             /* 00h */
     U8                                          Flags;              /* 04h */
     U8                                          Reserved1;          /* 05h */
     U16                                         Reserved2;          /* 06h */
     U32                                         HwConfig1;          /* 08h */
     U32                                         HwConfig2;          /* 0Ch */
-    fCONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA        Base;               /* 10h */
-    fCONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA    Extended;           /* 50h */
+    CONFIG_PAGE_FC_PORT_10_BASE_SFP_DATA        Base;               /* 10h */
+    CONFIG_PAGE_FC_PORT_10_EXTENDED_SFP_DATA    Extended;           /* 50h */
     U8                                          VendorSpecific[32]; /* 70h */
-} fCONFIG_PAGE_FC_PORT_10, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_10,
+} CONFIG_PAGE_FC_PORT_10, MPI_POINTER PTR_CONFIG_PAGE_FC_PORT_10,
   FCPortPage10_t, MPI_POINTER pFCPortPage10_t;
 
-#define MPI_FCPORTPAGE10_PAGEVERSION                    (0x00)
+#define MPI_FCPORTPAGE10_PAGEVERSION                    (0x01)
 
 /* standard MODDEF pin definitions (from GBIC spec.) */
 #define MPI_FCPORTPAGE10_FLAGS_MODDEF_MASK              (0x00000007)
@@ -1534,7 +1894,7 @@
 
 typedef struct _CONFIG_PAGE_FC_DEVICE_0
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     U64                     WWNN;                       /* 04h */
     U64                     WWPN;                       /* 0Ch */
     U32                     PortIdentifier;             /* 14h */
@@ -1548,7 +1908,7 @@
     U8                      FcPhHighestVersion;         /* 21h */
     U8                      CurrentTargetID;            /* 22h */
     U8                      CurrentBus;                 /* 23h */
-} fCONFIG_PAGE_FC_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_FC_DEVICE_0,
+} CONFIG_PAGE_FC_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_FC_DEVICE_0,
   FCDevicePage0_t, MPI_POINTER pFCDevicePage0_t;
 
 #define MPI_FC_DEVICE_PAGE0_PAGEVERSION                 (0x03)
@@ -1606,6 +1966,7 @@
 #define MPI_RAIDVOL0_STATUS_STATE_OPTIMAL               (0x00)
 #define MPI_RAIDVOL0_STATUS_STATE_DEGRADED              (0x01)
 #define MPI_RAIDVOL0_STATUS_STATE_FAILED                (0x02)
+#define MPI_RAIDVOL0_STATUS_STATE_MISSING               (0x03)
 
 typedef struct _RAID_VOL0_SETTINGS
 {
@@ -1616,11 +1977,11 @@
   RaidVol0Settings, MPI_POINTER pRaidVol0Settings;
 
 /* RAID Volume Page 0 VolumeSettings defines */
-
 #define MPI_RAIDVOL0_SETTING_WRITE_CACHING_ENABLE       (0x0001)
 #define MPI_RAIDVOL0_SETTING_OFFLINE_ON_SMART           (0x0002)
 #define MPI_RAIDVOL0_SETTING_AUTO_CONFIGURE             (0x0004)
 #define MPI_RAIDVOL0_SETTING_PRIORITY_RESYNC            (0x0008)
+#define MPI_RAIDVOL0_SETTING_FAST_DATA_SCRUBBING_0102   (0x0020) /* obsolete */
 #define MPI_RAIDVOL0_SETTING_USE_PRODUCT_ID_SUFFIX      (0x0010)
 #define MPI_RAIDVOL0_SETTING_USE_DEFAULTS               (0x8000)
 
@@ -1644,7 +2005,7 @@
 
 typedef struct _CONFIG_PAGE_RAID_VOL_0
 {
-    fCONFIG_PAGE_HEADER      Header;         /* 00h */
+    CONFIG_PAGE_HEADER      Header;         /* 00h */
     U8                      VolumeID;       /* 04h */
     U8                      VolumeBus;      /* 05h */
     U8                      VolumeIOC;      /* 06h */
@@ -1657,13 +2018,41 @@
     U32                     Reserved2;      /* 1Ch */
     U32                     Reserved3;      /* 20h */
     U8                      NumPhysDisks;   /* 24h */
-    U8                      Reserved4;      /* 25h */
-    U16                     Reserved5;      /* 26h */
+    U8                      DataScrubRate;  /* 25h */
+    U8                      ResyncRate;     /* 26h */
+    U8                      InactiveStatus; /* 27h */
     RAID_VOL0_PHYS_DISK     PhysDisk[MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX];/* 28h */
-} fCONFIG_PAGE_RAID_VOL_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_0,
+} CONFIG_PAGE_RAID_VOL_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_0,
   RaidVolumePage0_t, MPI_POINTER pRaidVolumePage0_t;
 
-#define MPI_RAIDVOLPAGE0_PAGEVERSION                    (0x01)
+#define MPI_RAIDVOLPAGE0_PAGEVERSION                    (0x04)
+
+/* values for RAID Volume Page 0 InactiveStatus field */
+#define MPI_RAIDVOLPAGE0_UNKNOWN_INACTIVE               (0x00)
+#define MPI_RAIDVOLPAGE0_STALE_METADATA_INACTIVE        (0x01)
+#define MPI_RAIDVOLPAGE0_FOREIGN_VOLUME_INACTIVE        (0x02)
+#define MPI_RAIDVOLPAGE0_INSUFFICIENT_RESOURCE_INACTIVE (0x03)
+#define MPI_RAIDVOLPAGE0_CLONE_VOLUME_INACTIVE          (0x04)
+#define MPI_RAIDVOLPAGE0_INSUFFICIENT_METADATA_INACTIVE (0x05)
+#define MPI_RAIDVOLPAGE0_PREVIOUSLY_DELETED             (0x06)
+
+
+typedef struct _CONFIG_PAGE_RAID_VOL_1
+{
+    CONFIG_PAGE_HEADER      Header;         /* 00h */
+    U8                      VolumeID;       /* 01h */
+    U8                      VolumeBus;      /* 02h */
+    U8                      VolumeIOC;      /* 03h */
+    U8                      Reserved0;      /* 04h */
+    U8                      GUID[24];       /* 05h */
+    U8                      Name[32];       /* 20h */
+    U64                     WWID;           /* 40h */
+    U32                     Reserved1;      /* 48h */
+    U32                     Reserved2;      /* 4Ch */
+} CONFIG_PAGE_RAID_VOL_1, MPI_POINTER PTR_CONFIG_PAGE_RAID_VOL_1,
+  RaidVolumePage1_t, MPI_POINTER pRaidVolumePage1_t;
+
+#define MPI_RAIDVOLPAGE1_PAGEVERSION                    (0x01)
 
 
 /****************************************************************************
@@ -1714,6 +2103,7 @@
 
 #define MPI_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC           (0x01)
 #define MPI_PHYSDISK0_STATUS_FLAG_QUIESCED              (0x02)
+#define MPI_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME       (0x04)
 
 #define MPI_PHYSDISK0_STATUS_ONLINE                     (0x00)
 #define MPI_PHYSDISK0_STATUS_MISSING                    (0x01)
@@ -1726,24 +2116,54 @@
 
 typedef struct _CONFIG_PAGE_RAID_PHYS_DISK_0
 {
-    fCONFIG_PAGE_HEADER              Header;             /* 00h */
+    CONFIG_PAGE_HEADER              Header;             /* 00h */
     U8                              PhysDiskID;         /* 04h */
     U8                              PhysDiskBus;        /* 05h */
     U8                              PhysDiskIOC;        /* 06h */
     U8                              PhysDiskNum;        /* 07h */
     RAID_PHYS_DISK0_SETTINGS        PhysDiskSettings;   /* 08h */
     U32                             Reserved1;          /* 0Ch */
-    U32                             Reserved2;          /* 10h */
-    U32                             Reserved3;          /* 14h */
+    U8                              ExtDiskIdentifier[8]; /* 10h */
     U8                              DiskIdentifier[16]; /* 18h */
     RAID_PHYS_DISK0_INQUIRY_DATA    InquiryData;        /* 28h */
     RAID_PHYS_DISK0_STATUS          PhysDiskStatus;     /* 64h */
     U32                             MaxLBA;             /* 68h */
     RAID_PHYS_DISK0_ERROR_DATA      ErrorData;          /* 6Ch */
-} fCONFIG_PAGE_RAID_PHYS_DISK_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_PHYS_DISK_0,
+} CONFIG_PAGE_RAID_PHYS_DISK_0, MPI_POINTER PTR_CONFIG_PAGE_RAID_PHYS_DISK_0,
   RaidPhysDiskPage0_t, MPI_POINTER pRaidPhysDiskPage0_t;
 
-#define MPI_RAIDPHYSDISKPAGE0_PAGEVERSION           (0x00)
+#define MPI_RAIDPHYSDISKPAGE0_PAGEVERSION           (0x01)
+
+
+typedef struct _RAID_PHYS_DISK1_PATH
+{
+    U8                              PhysDiskID;         /* 00h */
+    U8                              PhysDiskBus;        /* 01h */
+    U16                             Reserved1;          /* 02h */
+    U64                             WWID;               /* 04h */
+    U64                             OwnerWWID;          /* 0Ch */
+    U8                              OwnerIdentifier;    /* 14h */
+    U8                              Reserved2;          /* 15h */
+    U16                             Flags;              /* 16h */
+} RAID_PHYS_DISK1_PATH, MPI_POINTER PTR_RAID_PHYS_DISK1_PATH,
+  RaidPhysDisk1Path_t, MPI_POINTER pRaidPhysDisk1Path_t;
+
+/* RAID Physical Disk Page 1 Flags field defines */
+#define MPI_RAID_PHYSDISK1_FLAG_BROKEN          (0x0002)
+#define MPI_RAID_PHYSDISK1_FLAG_INVALID         (0x0001)
+
+typedef struct _CONFIG_PAGE_RAID_PHYS_DISK_1
+{
+    CONFIG_PAGE_HEADER              Header;             /* 00h */
+    U8                              NumPhysDiskPaths;   /* 04h */
+    U8                              PhysDiskNum;        /* 05h */
+    U16                             Reserved2;          /* 06h */
+    U32                             Reserved1;          /* 08h */
+    RAID_PHYS_DISK1_PATH            Path[1];            /* 0Ch */
+} CONFIG_PAGE_RAID_PHYS_DISK_1, MPI_POINTER PTR_CONFIG_PAGE_RAID_PHYS_DISK_1,
+  RaidPhysDiskPage1_t, MPI_POINTER pRaidPhysDiskPage1_t;
+
+#define MPI_RAIDPHYSDISKPAGE1_PAGEVERSION       (0x00)
 
 
 /****************************************************************************
@@ -1756,7 +2176,7 @@
     U16                     TxRxModes;                  /* 04h */
     U16                     Reserved;                   /* 06h */
     U32                     PacketPrePad;               /* 08h */
-} fCONFIG_PAGE_LAN_0, MPI_POINTER PTR_CONFIG_PAGE_LAN_0,
+} CONFIG_PAGE_LAN_0, MPI_POINTER PTR_CONFIG_PAGE_LAN_0,
   LANPage0_t, MPI_POINTER pLANPage0_t;
 
 #define MPI_LAN_PAGE0_PAGEVERSION                       (0x01)
@@ -1781,7 +2201,7 @@
     U32                     MaxReplySize;               /* 24h */
     U32                     NegWireSpeedLow;            /* 28h */
     U32                     NegWireSpeedHigh;           /* 2Ch */
-} fCONFIG_PAGE_LAN_1, MPI_POINTER PTR_CONFIG_PAGE_LAN_1,
+} CONFIG_PAGE_LAN_1, MPI_POINTER PTR_CONFIG_PAGE_LAN_1,
   LANPage1_t, MPI_POINTER pLANPage1_t;
 
 #define MPI_LAN_PAGE1_PAGEVERSION                       (0x03)
@@ -1796,11 +2216,11 @@
 
 typedef struct _CONFIG_PAGE_INBAND_0
 {
-    fCONFIG_PAGE_HEADER      Header;                     /* 00h */
+    CONFIG_PAGE_HEADER      Header;                     /* 00h */
     MPI_VERSION_FORMAT      InbandVersion;              /* 04h */
     U16                     MaximumBuffers;             /* 08h */
     U16                     Reserved1;                  /* 0Ah */
-} fCONFIG_PAGE_INBAND_0, MPI_POINTER PTR_CONFIG_PAGE_INBAND_0,
+} CONFIG_PAGE_INBAND_0, MPI_POINTER PTR_CONFIG_PAGE_INBAND_0,
   InbandPage0_t, MPI_POINTER pInbandPage0_t;
 
 #define MPI_INBAND_PAGEVERSION          (0x00)
@@ -1820,7 +2240,7 @@
     U32         ControllerPhyDeviceInfo;/* 04h */
     U16         AttachedDeviceHandle;   /* 08h */
     U16         ControllerDevHandle;    /* 0Ah */
-    U32         Reserved2;              /* 0Ch */
+    U32         DiscoveryStatus;        /* 0Ch */
 } MPI_SAS_IO_UNIT0_PHY_DATA, MPI_POINTER PTR_MPI_SAS_IO_UNIT0_PHY_DATA,
   SasIOUnit0PhyData, MPI_POINTER pSasIOUnit0PhyData;
 
@@ -1834,22 +2254,21 @@
 
 typedef struct _CONFIG_PAGE_SAS_IO_UNIT_0
 {
-    fCONFIG_EXTENDED_PAGE_HEADER     Header;                             /* 00h */
+    CONFIG_EXTENDED_PAGE_HEADER     Header;                             /* 00h */
     U32                             Reserved1;                          /* 08h */
     U8                              NumPhys;                            /* 0Ch */
     U8                              Reserved2;                          /* 0Dh */
     U16                             Reserved3;                          /* 0Eh */
     MPI_SAS_IO_UNIT0_PHY_DATA       PhyData[MPI_SAS_IOUNIT0_PHY_MAX];   /* 10h */
-} fCONFIG_PAGE_SAS_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_0,
+} CONFIG_PAGE_SAS_IO_UNIT_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_0,
   SasIOUnitPage0_t, MPI_POINTER pSasIOUnitPage0_t;
 
-#define MPI_SASIOUNITPAGE0_PAGEVERSION      (0x00)
+#define MPI_SASIOUNITPAGE0_PAGEVERSION      (0x02)
 
 /* values for SAS IO Unit Page 0 PortFlags */
 #define MPI_SAS_IOUNIT0_PORT_FLAGS_DISCOVERY_IN_PROGRESS    (0x08)
 #define MPI_SAS_IOUNIT0_PORT_FLAGS_0_TARGET_IOC_NUM         (0x00)
 #define MPI_SAS_IOUNIT0_PORT_FLAGS_1_TARGET_IOC_NUM         (0x04)
-#define MPI_SAS_IOUNIT0_PORT_FLAGS_WAIT_FOR_PORTENABLE      (0x02)
 #define MPI_SAS_IOUNIT0_PORT_FLAGS_AUTO_PORT_CONFIG         (0x01)
 
 /* values for SAS IO Unit Page 0 PhyFlags */
@@ -1867,6 +2286,20 @@
 
 /* see mpi_sas.h for values for SAS IO Unit Page 0 ControllerPhyDeviceInfo values */
 
+/* values for SAS IO Unit Page 0 DiscoveryStatus */
+#define MPI_SAS_IOUNIT0_DS_LOOP_DETECTED                    (0x00000001)
+#define MPI_SAS_IOUNIT0_DS_UNADDRESSABLE_DEVICE             (0x00000002)
+#define MPI_SAS_IOUNIT0_DS_MULTIPLE_PORTS                   (0x00000004)
+#define MPI_SAS_IOUNIT0_DS_EXPANDER_ERR                     (0x00000008)
+#define MPI_SAS_IOUNIT0_DS_SMP_TIMEOUT                      (0x00000010)
+#define MPI_SAS_IOUNIT0_DS_OUT_ROUTE_ENTRIES                (0x00000020)
+#define MPI_SAS_IOUNIT0_DS_INDEX_NOT_EXIST                  (0x00000040)
+#define MPI_SAS_IOUNIT0_DS_SMP_FUNCTION_FAILED              (0x00000080)
+#define MPI_SAS_IOUNIT0_DS_SMP_CRC_ERROR                    (0x00000100)
+#define MPI_SAS_IOUNIT0_DS_SUBTRACTIVE_LINK                 (0x00000200)
+#define MPI_SAS_IOUNIT0_DS_TABLE_LINK                       (0x00000400)
+#define MPI_SAS_IOUNIT0_DS_UNSUPPORTED_DEVICE               (0x00000800)
+
 
 typedef struct _MPI_SAS_IO_UNIT1_PHY_DATA
 {
@@ -1889,52 +2322,75 @@
 
 typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1
 {
-    fCONFIG_EXTENDED_PAGE_HEADER Header;                             /* 00h */
-    U32                         Reserved1;                          /* 08h */
-    U8                          NumPhys;                            /* 0Ch */
-    U8                          Reserved2;                          /* 0Dh */
-    U16                         Reserved3;                          /* 0Eh */
-    MPI_SAS_IO_UNIT1_PHY_DATA   PhyData[MPI_SAS_IOUNIT1_PHY_MAX];   /* 10h */
-} fCONFIG_PAGE_SAS_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_1,
+    CONFIG_EXTENDED_PAGE_HEADER Header;                             /* 00h */
+    U16                         ControlFlags;                       /* 08h */
+    U16                         MaxNumSATATargets;                  /* 0Ah */
+    U32                         Reserved1;                          /* 0Ch */
+    U8                          NumPhys;                            /* 10h */
+    U8                          SATAMaxQDepth;                      /* 11h */
+    U16                         Reserved2;                          /* 12h */
+    MPI_SAS_IO_UNIT1_PHY_DATA   PhyData[MPI_SAS_IOUNIT1_PHY_MAX];   /* 14h */
+} CONFIG_PAGE_SAS_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_1,
   SasIOUnitPage1_t, MPI_POINTER pSasIOUnitPage1_t;
 
-#define MPI_SASIOUNITPAGE1_PAGEVERSION      (0x00)
+#define MPI_SASIOUNITPAGE1_PAGEVERSION      (0x04)
 
-/* values for SAS IO Unit Page 0 PortFlags */
-#define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM         (0x00)
-#define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM         (0x04)
-#define MPI_SAS_IOUNIT1_PORT_FLAGS_WAIT_FOR_PORTENABLE      (0x02)
-#define MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG         (0x01)
+/* values for SAS IO Unit Page 1 ControlFlags */
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_3_0_MAX            (0x4000)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_1_5_MAX            (0x2000)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_SW_PRESERVE        (0x1000)
+#define MPI_SAS_IOUNIT1_CONTROL_DISABLE_SAS_HASH        (0x0800)
+
+#define MPI_SAS_IOUNIT1_CONTROL_MASK_DEV_SUPPORT        (0x0600)
+#define MPI_SAS_IOUNIT1_CONTROL_SHIFT_DEV_SUPPORT       (9)
+#define MPI_SAS_IOUNIT1_CONTROL_DEV_SUPPORT_BOTH        (0x00)
+#define MPI_SAS_IOUNIT1_CONTROL_DEV_SAS_SUPPORT         (0x01)
+#define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT        (0x10)
+
+#define MPI_SAS_IOUNIT1_CONTROL_AUTO_PORT_SAME_SAS_ADDR (0x0100)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_SMART_REQUIRED     (0x0040)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_NCQ_REQUIRED       (0x0020)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_FUA_REQUIRED       (0x0010)
+#define MPI_SAS_IOUNIT1_CONTROL_PHY_ENABLE_ORDER_HIGH   (0x0008)
+#define MPI_SAS_IOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL     (0x0004)
+#define MPI_SAS_IOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY     (0x0002)
+#define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION       (0x0001)
+
+/* values for SAS IO Unit Page 1 PortFlags */
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM     (0x00)
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM     (0x04)
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG     (0x01)
 
 /* values for SAS IO Unit Page 0 PhyFlags */
-#define MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE               (0x04)
-#define MPI_SAS_IOUNIT1_PHY_FLAGS_TX_INVERT                 (0x02)
-#define MPI_SAS_IOUNIT1_PHY_FLAGS_RX_INVERT                 (0x01)
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE           (0x04)
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_TX_INVERT             (0x02)
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_RX_INVERT             (0x01)
 
 /* values for SAS IO Unit Page 0 MaxMinLinkRate */
-#define MPI_SAS_IOUNIT1_MAX_RATE_MASK                       (0xF0)
-#define MPI_SAS_IOUNIT1_MAX_RATE_1_5                        (0x80)
-#define MPI_SAS_IOUNIT1_MAX_RATE_3_0                        (0x90)
-#define MPI_SAS_IOUNIT1_MIN_RATE_MASK                       (0x0F)
-#define MPI_SAS_IOUNIT1_MIN_RATE_1_5                        (0x08)
-#define MPI_SAS_IOUNIT1_MIN_RATE_3_0                        (0x09)
+#define MPI_SAS_IOUNIT1_MAX_RATE_MASK                   (0xF0)
+#define MPI_SAS_IOUNIT1_MAX_RATE_1_5                    (0x80)
+#define MPI_SAS_IOUNIT1_MAX_RATE_3_0                    (0x90)
+#define MPI_SAS_IOUNIT1_MIN_RATE_MASK                   (0x0F)
+#define MPI_SAS_IOUNIT1_MIN_RATE_1_5                    (0x08)
+#define MPI_SAS_IOUNIT1_MIN_RATE_3_0                    (0x09)
 
 /* see mpi_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */
 
 
 typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2
 {
-    fCONFIG_EXTENDED_PAGE_HEADER         Header;                 /* 00h */
+    CONFIG_EXTENDED_PAGE_HEADER         Header;                 /* 00h */
     U32                                 Reserved1;              /* 08h */
     U16                                 MaxPersistentIDs;       /* 0Ch */
     U16                                 NumPersistentIDsUsed;   /* 0Eh */
     U8                                  Status;                 /* 10h */
     U8                                  Flags;                  /* 11h */
-    U16                                 Reserved2;              /* 12h */
-} fCONFIG_PAGE_SAS_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_2,
+    U16                                 MaxNumPhysicalMappedIDs;/* 12h */              /* 12h */
+} CONFIG_PAGE_SAS_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_2,
   SasIOUnitPage2_t, MPI_POINTER pSasIOUnitPage2_t;
 
-#define MPI_SASIOUNITPAGE2_PAGEVERSION      (0x00)
+#define MPI_SASIOUNITPAGE2_PAGEVERSION      (0x03)
 
 /* values for SAS IO Unit Page 2 Status field */
 #define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02)
@@ -1942,11 +2398,19 @@
 
 /* values for SAS IO Unit Page 2 Flags field */
 #define MPI_SAS_IOUNIT2_FLAGS_DISABLE_PERSISTENT_MAPPINGS   (0x01)
+/* Physical Mapping Modes */
+#define MPI_SAS_IOUNIT2_FLAGS_MASK_PHYS_MAP_MODE            (0x0E)
+#define MPI_SAS_IOUNIT2_FLAGS_SHIFT_PHYS_MAP_MODE           (1)
+#define MPI_SAS_IOUNIT2_FLAGS_NO_PHYS_MAP                   (0x00)
+#define MPI_SAS_IOUNIT2_FLAGS_DIRECT_ATTACH_PHYS_MAP        (0x01)
+#define MPI_SAS_IOUNIT2_FLAGS_ENCLOSURE_SLOT_PHYS_MAP       (0x02)
+
+#define MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT         (0x10)
 
 
 typedef struct _CONFIG_PAGE_SAS_IO_UNIT_3
 {
-    fCONFIG_EXTENDED_PAGE_HEADER Header;                         /* 00h */
+    CONFIG_EXTENDED_PAGE_HEADER Header;                         /* 00h */
     U32                         Reserved1;                      /* 08h */
     U32                         MaxInvalidDwordCount;           /* 0Ch */
     U32                         InvalidDwordCountTime;          /* 10h */
@@ -1956,18 +2420,24 @@
     U32                         LossDwordSynchCountTime;        /* 20h */
     U32                         MaxPhyResetProblemCount;        /* 24h */
     U32                         PhyResetProblemTime;            /* 28h */
-} fCONFIG_PAGE_SAS_IO_UNIT_3, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_3,
+} CONFIG_PAGE_SAS_IO_UNIT_3, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_3,
   SasIOUnitPage3_t, MPI_POINTER pSasIOUnitPage3_t;
 
 #define MPI_SASIOUNITPAGE3_PAGEVERSION      (0x00)
 
 
+/****************************************************************************
+*   SAS Expander Config Pages
+****************************************************************************/
+
 typedef struct _CONFIG_PAGE_SAS_EXPANDER_0
 {
-    fCONFIG_EXTENDED_PAGE_HEADER         Header;                 /* 00h */
-    U32                                 Reserved1;              /* 08h */
+    CONFIG_EXTENDED_PAGE_HEADER         Header;                 /* 00h */
+    U8                                  PhysicalPort;           /* 08h */
+    U8                                  Reserved1;              /* 09h */
+    U16                                 Reserved2;              /* 0Ah */
     U64                                 SASAddress;             /* 0Ch */
-    U32                                 Reserved2;              /* 14h */
+    U32                                 DiscoveryStatus;        /* 14h */
     U16                                 DevHandle;              /* 18h */
     U16                                 ParentDevHandle;        /* 1Ah */
     U16                                 ExpanderChangeCount;    /* 1Ch */
@@ -1976,45 +2446,127 @@
     U8                                  SASLevel;               /* 21h */
     U8                                  Flags;                  /* 22h */
     U8                                  Reserved3;              /* 23h */
-} fCONFIG_PAGE_SAS_EXPANDER_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_0,
+} CONFIG_PAGE_SAS_EXPANDER_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_0,
   SasExpanderPage0_t, MPI_POINTER pSasExpanderPage0_t;
 
-#define MPI_SASEXPANDER0_PAGEVERSION        (0x00)
+#define MPI_SASEXPANDER0_PAGEVERSION        (0x02)
+
+/* values for SAS Expander Page 0 DiscoveryStatus field */
+#define MPI_SAS_EXPANDER0_DS_LOOP_DETECTED              (0x00000001)
+#define MPI_SAS_EXPANDER0_DS_UNADDRESSABLE_DEVICE       (0x00000002)
+#define MPI_SAS_EXPANDER0_DS_MULTIPLE_PORTS             (0x00000004)
+#define MPI_SAS_EXPANDER0_DS_EXPANDER_ERR               (0x00000008)
+#define MPI_SAS_EXPANDER0_DS_SMP_TIMEOUT                (0x00000010)
+#define MPI_SAS_EXPANDER0_DS_OUT_ROUTE_ENTRIES          (0x00000020)
+#define MPI_SAS_EXPANDER0_DS_INDEX_NOT_EXIST            (0x00000040)
+#define MPI_SAS_EXPANDER0_DS_SMP_FUNCTION_FAILED        (0x00000080)
+#define MPI_SAS_EXPANDER0_DS_SMP_CRC_ERROR              (0x00000100)
+#define MPI_SAS_EXPANDER0_DS_SUBTRACTIVE_LINK           (0x00000200)
+#define MPI_SAS_EXPANDER0_DS_TABLE_LINK                 (0x00000400)
+#define MPI_SAS_EXPANDER0_DS_UNSUPPORTED_DEVICE         (0x00000800)
 
 /* values for SAS Expander Page 0 Flags field */
 #define MPI_SAS_EXPANDER0_FLAGS_ROUTE_TABLE_CONFIG      (0x02)
 #define MPI_SAS_EXPANDER0_FLAGS_CONFIG_IN_PROGRESS      (0x01)
 
 
+typedef struct _CONFIG_PAGE_SAS_EXPANDER_1
+{
+    CONFIG_EXTENDED_PAGE_HEADER Header;                 /* 00h */
+    U8                          PhysicalPort;           /* 08h */
+    U8                          Reserved1;              /* 09h */
+    U16                         Reserved2;              /* 0Ah */
+    U8                          NumPhys;                /* 0Ch */
+    U8                          Phy;                    /* 0Dh */
+    U16                         NumTableEntriesProgrammed; /* 0Eh */
+    U8                          ProgrammedLinkRate;     /* 10h */
+    U8                          HwLinkRate;             /* 11h */
+    U16                         AttachedDevHandle;      /* 12h */
+    U32                         PhyInfo;                /* 14h */
+    U32                         AttachedDeviceInfo;     /* 18h */
+    U16                         OwnerDevHandle;         /* 1Ch */
+    U8                          ChangeCount;            /* 1Eh */
+    U8                          NegotiatedLinkRate;     /* 1Fh */
+    U8                          PhyIdentifier;          /* 20h */
+    U8                          AttachedPhyIdentifier;  /* 21h */
+    U8                          NumTableEntriesProg;    /* 22h */
+    U8                          DiscoveryInfo;          /* 23h */
+    U32                         Reserved3;              /* 24h */
+} CONFIG_PAGE_SAS_EXPANDER_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_1,
+  SasExpanderPage1_t, MPI_POINTER pSasExpanderPage1_t;
+
+#define MPI_SASEXPANDER1_PAGEVERSION        (0x01)
+
+/* use MPI_SAS_PHY0_PRATE_ defines for ProgrammedLinkRate */
+
+/* use MPI_SAS_PHY0_HWRATE_ defines for HwLinkRate */
+
+/* use MPI_SAS_PHY0_PHYINFO_ defines for PhyInfo */
+
+/* see mpi_sas.h for values for SAS Expander Page 1 AttachedDeviceInfo values */
+
+/* values for SAS Expander Page 1 DiscoveryInfo field */
+#define MPI_SAS_EXPANDER1_DISCINFO_BAD_PHY DISABLED     (0x04)
+#define MPI_SAS_EXPANDER1_DISCINFO_LINK_STATUS_CHANGE   (0x02)
+#define MPI_SAS_EXPANDER1_DISCINFO_NO_ROUTING_ENTRIES   (0x01)
+
+/* values for SAS Expander Page 1 NegotiatedLinkRate field */
+#define MPI_SAS_EXPANDER1_NEG_RATE_UNKNOWN              (0x00)
+#define MPI_SAS_EXPANDER1_NEG_RATE_PHY_DISABLED         (0x01)
+#define MPI_SAS_EXPANDER1_NEG_RATE_FAILED_NEGOTIATION   (0x02)
+#define MPI_SAS_EXPANDER1_NEG_RATE_SATA_OOB_COMPLETE    (0x03)
+#define MPI_SAS_EXPANDER1_NEG_RATE_1_5                  (0x08)
+#define MPI_SAS_EXPANDER1_NEG_RATE_3_0                  (0x09)
+
+
+/****************************************************************************
+*   SAS Device Config Pages
+****************************************************************************/
+
 typedef struct _CONFIG_PAGE_SAS_DEVICE_0
 {
-    fCONFIG_EXTENDED_PAGE_HEADER         Header;                 /* 00h */
-    U32                                 Reserved1;              /* 08h */
+    CONFIG_EXTENDED_PAGE_HEADER         Header;                 /* 00h */
+    U16                                 Slot;                   /* 08h */
+    U16                                 EnclosureHandle;        /* 0Ah */
     U64                                 SASAddress;             /* 0Ch */
-    U32                                 Reserved2;              /* 14h */
+    U16                                 ParentDevHandle;        /* 14h */
+    U8                                  PhyNum;                 /* 16h */
+    U8                                  AccessStatus;           /* 17h */
     U16                                 DevHandle;              /* 18h */
     U8                                  TargetID;               /* 1Ah */
     U8                                  Bus;                    /* 1Bh */
     U32                                 DeviceInfo;             /* 1Ch */
     U16                                 Flags;                  /* 20h */
     U8                                  PhysicalPort;           /* 22h */
-    U8                                  Reserved3;              /* 23h */
-} fCONFIG_PAGE_SAS_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_0,
+    U8                                  Reserved2;              /* 23h */
+} CONFIG_PAGE_SAS_DEVICE_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_0,
   SasDevicePage0_t, MPI_POINTER pSasDevicePage0_t;
 
-#define MPI_SASDEVICE0_PAGEVERSION          (0x00)
+#define MPI_SASDEVICE0_PAGEVERSION          (0x04)
+
+/* values for SAS Device Page 0 AccessStatus field */
+#define MPI_SAS_DEVICE0_ASTATUS_NO_ERRORS               (0x00)
+#define MPI_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED        (0x01)
+#define MPI_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED  (0x02)
 
 /* values for SAS Device Page 0 Flags field */
-#define MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT    (0x04)
-#define MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED         (0x02)
-#define MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT        (0x01)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE          (0x0200)
+#define MPI_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE        (0x0100)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED  (0x0080)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED      (0x0040)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED        (0x0020)
+#define MPI_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED        (0x0010)
+#define MPI_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH      (0x0008)
+#define MPI_SAS_DEVICE0_FLAGS_MAPPING_PERSISTENT        (0x0004)
+#define MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED             (0x0002)
+#define MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT            (0x0001)
 
 /* see mpi_sas.h for values for SAS Device Page 0 DeviceInfo values */
 
 
 typedef struct _CONFIG_PAGE_SAS_DEVICE_1
 {
-    fCONFIG_EXTENDED_PAGE_HEADER         Header;                 /* 00h */
+    CONFIG_EXTENDED_PAGE_HEADER         Header;                 /* 00h */
     U32                                 Reserved1;              /* 08h */
     U64                                 SASAddress;             /* 0Ch */
     U32                                 Reserved2;              /* 14h */
@@ -2022,15 +2574,30 @@
     U8                                  TargetID;               /* 1Ah */
     U8                                  Bus;                    /* 1Bh */
     U8                                  InitialRegDeviceFIS[20];/* 1Ch */
-} fCONFIG_PAGE_SAS_DEVICE_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_1,
+} CONFIG_PAGE_SAS_DEVICE_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_1,
   SasDevicePage1_t, MPI_POINTER pSasDevicePage1_t;
 
 #define MPI_SASDEVICE1_PAGEVERSION          (0x00)
 
 
+typedef struct _CONFIG_PAGE_SAS_DEVICE_2
+{
+    CONFIG_EXTENDED_PAGE_HEADER         Header;                 /* 00h */
+    U64                                 PhysicalIdentifier;     /* 08h */
+    U32                                 Reserved1;              /* 10h */
+} CONFIG_PAGE_SAS_DEVICE_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_DEVICE_2,
+  SasDevicePage2_t, MPI_POINTER pSasDevicePage2_t;
+
+#define MPI_SASDEVICE2_PAGEVERSION          (0x00)
+
+
+/****************************************************************************
+*   SAS PHY Config Pages
+****************************************************************************/
+
 typedef struct _CONFIG_PAGE_SAS_PHY_0
 {
-    fCONFIG_EXTENDED_PAGE_HEADER         Header;                 /* 00h */
+    CONFIG_EXTENDED_PAGE_HEADER         Header;                 /* 00h */
     U32                                 Reserved1;              /* 08h */
     U64                                 SASAddress;             /* 0Ch */
     U16                                 AttachedDevHandle;      /* 14h */
@@ -2042,7 +2609,7 @@
     U8                                  ChangeCount;            /* 22h */
     U8                                  Reserved3;              /* 23h */
     U32                                 PhyInfo;                /* 24h */
-} fCONFIG_PAGE_SAS_PHY_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_0,
+} CONFIG_PAGE_SAS_PHY_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_0,
   SasPhyPage0_t, MPI_POINTER pSasPhyPage0_t;
 
 #define MPI_SASPHY0_PAGEVERSION             (0x00)
@@ -2089,17 +2656,95 @@
 
 typedef struct _CONFIG_PAGE_SAS_PHY_1
 {
-    fCONFIG_EXTENDED_PAGE_HEADER Header;                     /* 00h */
+    CONFIG_EXTENDED_PAGE_HEADER Header;                     /* 00h */
     U32                         Reserved1;                  /* 08h */
     U32                         InvalidDwordCount;          /* 0Ch */
     U32                         RunningDisparityErrorCount; /* 10h */
     U32                         LossDwordSynchCount;        /* 14h */
     U32                         PhyResetProblemCount;       /* 18h */
-} fCONFIG_PAGE_SAS_PHY_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_1,
+} CONFIG_PAGE_SAS_PHY_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_PHY_1,
   SasPhyPage1_t, MPI_POINTER pSasPhyPage1_t;
 
 #define MPI_SASPHY1_PAGEVERSION             (0x00)
 
 
+/****************************************************************************
+*   SAS Enclosure Config Pages
+****************************************************************************/
+
+typedef struct _CONFIG_PAGE_SAS_ENCLOSURE_0
+{
+    CONFIG_EXTENDED_PAGE_HEADER         Header;                 /* 00h */
+    U32                                 Reserved1;              /* 08h */
+    U64                                 EnclosureLogicalID;     /* 0Ch */
+    U16                                 Flags;                  /* 14h */
+    U16                                 EnclosureHandle;        /* 16h */
+    U16                                 NumSlots;               /* 18h */
+    U16                                 StartSlot;              /* 1Ah */
+    U8                                  StartTargetID;          /* 1Ch */
+    U8                                  StartBus;               /* 1Dh */
+    U8                                  SEPTargetID;            /* 1Eh */
+    U8                                  SEPBus;                 /* 1Fh */
+    U32                                 Reserved2;              /* 20h */
+    U32                                 Reserved3;              /* 24h */
+} CONFIG_PAGE_SAS_ENCLOSURE_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_ENCLOSURE_0,
+  SasEnclosurePage0_t, MPI_POINTER pSasEnclosurePage0_t;
+
+#define MPI_SASENCLOSURE0_PAGEVERSION       (0x00)
+
+/* values for SAS Enclosure Page 0 Flags field */
+#define MPI_SAS_ENCLS0_FLAGS_SEP_BUS_ID_VALID       (0x0020)
+#define MPI_SAS_ENCLS0_FLAGS_START_BUS_ID_VALID     (0x0010)
+
+#define MPI_SAS_ENCLS0_FLAGS_MNG_MASK               (0x000F)
+#define MPI_SAS_ENCLS0_FLAGS_MNG_UNKNOWN            (0x0000)
+#define MPI_SAS_ENCLS0_FLAGS_MNG_IOC_SES            (0x0001)
+#define MPI_SAS_ENCLS0_FLAGS_MNG_IOC_SGPIO          (0x0002)
+#define MPI_SAS_ENCLS0_FLAGS_MNG_EXP_SGPIO          (0x0003)
+#define MPI_SAS_ENCLS0_FLAGS_MNG_SES_ENCLOSURE      (0x0004)
+
+
+/****************************************************************************
+*   Log Config Pages
+****************************************************************************/
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check NumLogEntries at runtime.
+ */
+#ifndef MPI_LOG_0_NUM_LOG_ENTRIES
+#define MPI_LOG_0_NUM_LOG_ENTRIES        (1)
+#endif
+
+#define MPI_LOG_0_LOG_DATA_LENGTH        (20)
+
+typedef struct _MPI_LOG_0_ENTRY
+{
+    U64         WWID;                               /* 00h */
+    U32         TimeStamp;                          /* 08h */
+    U32         Reserved1;                          /* 0Ch */
+    U16         LogSequence;                        /* 10h */
+    U16         LogEntryQualifier;                  /* 12h */
+    U8          LogData[MPI_LOG_0_LOG_DATA_LENGTH]; /* 14h */
+} MPI_LOG_0_ENTRY, MPI_POINTER PTR_MPI_LOG_0_ENTRY,
+  MpiLog0Entry_t, MPI_POINTER pMpiLog0Entry_t;
+
+/* values for Log Page 0 LogEntry LogEntryQualifier field */
+#define MPI_LOG_0_ENTRY_QUAL_ENTRY_UNUSED           (0x0000)
+#define MPI_LOG_0_ENTRY_QUAL_POWER_ON_RESET         (0x0001)
+
+typedef struct _CONFIG_PAGE_LOG_0
+{
+    CONFIG_EXTENDED_PAGE_HEADER Header;                     /* 00h */
+    U32                         Reserved1;                  /* 08h */
+    U32                         Reserved2;                  /* 0Ch */
+    U16                         NumLogEntries;              /* 10h */
+    U16                         Reserved3;                  /* 12h */
+    MPI_LOG_0_ENTRY             LogEntry[MPI_LOG_0_NUM_LOG_ENTRIES]; /* 14h */
+} CONFIG_PAGE_LOG_0, MPI_POINTER PTR_CONFIG_PAGE_LOG_0,
+  LogPage0_t, MPI_POINTER pLogPage0_t;
+
+#define MPI_LOG_0_PAGEVERSION               (0x00)
+
+
 #endif
 
diff --git a/drivers/message/fusion/lsi/mpi_fc.h b/drivers/message/fusion/lsi/mpi_fc.h
index ea266b2..51a6aeb 100644
--- a/drivers/message/fusion/lsi/mpi_fc.h
+++ b/drivers/message/fusion/lsi/mpi_fc.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2003 LSI Logic Corporation.
+ *  Copyright (c) 2000-2004 LSI Logic Corporation.
  *
  *
  *           Name:  mpi_fc.h
  *          Title:  MPI Fibre Channel messages and structures
  *  Creation Date:  June 12, 2000
  *
- *    mpi_fc.h Version:  01.05.xx
+ *    mpi_fc.h Version:  01.05.01
  *
  *  Version History
  *  ---------------
@@ -36,6 +36,9 @@
  *  09-28-01  01.02.02  Change name of reserved field in
  *                      MSG_LINK_SERVICE_RSP_REPLY.
  *  05-31-02  01.02.03  Adding AliasIndex to FC Direct Access requests.
+ *  01-16-04  01.02.04  Added define for MPI_FC_PRIM_SEND_FLAGS_ML_RESET_LINK.
+ *  05-11-04  01.03.01  Original release for MPI v1.3.
+ *  08-19-04  01.05.01  Original release for MPI v1.5.
  *  --------------------------------------------------------------------------
  */
 
diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt
index 0deb772..c9edbee 100644
--- a/drivers/message/fusion/lsi/mpi_history.txt
+++ b/drivers/message/fusion/lsi/mpi_history.txt
@@ -3,25 +3,28 @@
  MPI Header File Change History
  ==============================
 
- Copyright (c) 2000-2001 LSI Logic Corporation.
+ Copyright (c) 2000-2005 LSI Logic Corporation.
 
  ---------------------------------------
- Header Set Release Version:    01.01.10
- Header Set Release Date:       04-09-01
+ Header Set Release Version:    01.05.09
+ Header Set Release Date:       03-11-05
  ---------------------------------------
 
  Filename               Current version     Prior version
  ----------             ---------------     -------------
- mpi.h                  01.01.07            01.01.06
- mpi_ioc.h              01.01.07            01.01.06
- mpi_cnfg.h             01.01.11            01.01.10
- mpi_init.h             01.01.05            01.01.04
- mpi_targ.h             01.01.04            01.01.04
- mpi_fc.h               01.01.07            01.01.06
- mpi_lan.h              01.01.03            01.01.03
- mpi_raid.h             01.01.02            01.01.02
- mpi_type.h             01.01.02            01.01.02
- mpi_history.txt        01.01.09            01.01.09
+ mpi.h                  01.05.07            01.05.06
+ mpi_ioc.h              01.05.08            01.05.07
+ mpi_cnfg.h             01.05.08            01.05.07
+ mpi_init.h             01.05.04            01.05.03
+ mpi_targ.h             01.05.04            01.05.03
+ mpi_fc.h               01.05.01            01.05.01
+ mpi_lan.h              01.05.01            01.05.01
+ mpi_raid.h             01.05.02            01.05.02
+ mpi_tool.h             01.05.03            01.05.03
+ mpi_inb.h              01.05.01            01.05.01
+ mpi_sas.h              01.05.01            01.05.01
+ mpi_type.h             01.05.01            01.05.01
+ mpi_history.txt        01.05.09            01.05.08
 
 
  *  Date      Version   Description
@@ -53,6 +56,38 @@
  *                      Added function codes for RAID.
  *  04-09-01  01.01.07  Added alternate define for MPI_DOORBELL_ACTIVE,
  *                      MPI_DOORBELL_USED, to better match the spec.
+ *  08-08-01  01.02.01  Original release for v1.2 work.
+ *                      Changed MPI_VERSION_MINOR from 0x01 to 0x02.
+ *                      Added define MPI_FUNCTION_TOOLBOX.
+ *  09-28-01  01.02.02  New function code MPI_SCSI_ENCLOSURE_PROCESSOR.
+ *  11-01-01  01.02.03  Changed name to MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR.
+ *  03-14-02  01.02.04  Added MPI_HEADER_VERSION_ defines.
+ *  05-31-02  01.02.05  Bumped MPI_HEADER_VERSION_UNIT.
+ *  07-12-02  01.02.06  Added define for MPI_FUNCTION_MAILBOX.
+ *  09-16-02  01.02.07  Bumped value for MPI_HEADER_VERSION_UNIT.
+ *  11-15-02  01.02.08  Added define MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX and
+ *                      obsoleted define MPI_IOCSTATUS_TARGET_INVALID_IOCINDEX.
+ *  04-01-03  01.02.09  New IOCStatus code: MPI_IOCSTATUS_FC_EXCHANGE_CANCELED
+ *  06-26-03  01.02.10  Bumped MPI_HEADER_VERSION_UNIT value.
+ *  01-16-04  01.02.11  Added define for MPI_IOCLOGINFO_TYPE_SHIFT.
+ *  04-29-04  01.02.12  Added function codes for MPI_FUNCTION_DIAG_BUFFER_POST
+ *                      and MPI_FUNCTION_DIAG_RELEASE.
+ *                      Added MPI_IOCSTATUS_DIAGNOSTIC_RELEASED define.
+ *                      Bumped MPI_HEADER_VERSION_UNIT value.
+ *  05-11-04  01.03.01  Bumped MPI_VERSION_MINOR for MPI v1.3.
+ *                      Added codes for Inband.
+ *  08-19-04  01.05.01  Added defines for Host Buffer Access Control doorbell.
+ *                      Added define for offset of High Priority Request Queue.
+ *                      Added new function codes and new IOCStatus codes.
+ *                      Added a IOCLogInfo type of SAS.
+ *  12-07-04  01.05.02  Bumped MPI_HEADER_VERSION_UNIT.
+ *  12-09-04  01.05.03  Bumped MPI_HEADER_VERSION_UNIT.
+ *  01-15-05  01.05.04  Bumped MPI_HEADER_VERSION_UNIT.
+ *  02-09-05  01.05.05  Bumped MPI_HEADER_VERSION_UNIT.
+ *  02-22-05  01.05.06  Bumped MPI_HEADER_VERSION_UNIT.
+ *  03-11-05  01.05.07  Removed function codes for SCSI IO 32 and
+ *                      TargetAssistExtended requests.
+ *                      Removed EEDP IOCStatus codes.
  *  --------------------------------------------------------------------------
 
 mpi_ioc.h
@@ -81,6 +116,49 @@
  *  03-27-01  01.01.06  Added defines for ProductId field of MPI_FW_HEADER.
  *                      Added structure offset comments.
  *  04-09-01  01.01.07  Added structure EVENT_DATA_EVENT_CHANGE.
+ *  08-08-01  01.02.01  Original release for v1.2 work.
+ *                      New format for FWVersion and ProductId in
+ *                      MSG_IOC_FACTS_REPLY and MPI_FW_HEADER.
+ *  08-31-01  01.02.02  Addded event MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE and
+ *                      related structure and defines.
+ *                      Added event MPI_EVENT_ON_BUS_TIMER_EXPIRED.
+ *                      Added MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE.
+ *                      Replaced a reserved field in MSG_IOC_FACTS_REPLY with
+ *                      IOCExceptions and changed DataImageSize to reserved.
+ *                      Added MPI_FW_DOWNLOAD_ITYPE_NVSTORE_DATA and
+ *                      MPI_FW_UPLOAD_ITYPE_NVDATA.
+ *  09-28-01  01.02.03  Modified Event Data for Integrated RAID.
+ *  11-01-01  01.02.04  Added defines for MPI_EXT_IMAGE_HEADER ImageType field.
+ *  03-14-02  01.02.05  Added HeaderVersion field to MSG_IOC_FACTS_REPLY.
+ *  05-31-02  01.02.06  Added define for
+ *                      MPI_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID.
+ *                      Added AliasIndex to EVENT_DATA_LOGOUT structure.
+ *  04-01-03  01.02.07  Added defines for MPI_FW_HEADER_SIGNATURE_.
+ *  06-26-03  01.02.08  Added new values to the product family defines.
+ *  04-29-04  01.02.09  Added IOCCapabilities field to MSG_IOC_FACTS_REPLY and
+ *                      added related defines.
+ *  05-11-04  01.03.01  Original release for MPI v1.3.
+ *  08-19-04  01.05.01  Added four new fields to MSG_IOC_INIT.
+ *                      Added three new fields to MSG_IOC_FACTS_REPLY.
+ *                      Defined four new bits for the IOCCapabilities field of
+ *                      the IOCFacts reply.
+ *                      Added two new PortTypes for the PortFacts reply.
+ *                      Added six new events along with their EventData
+ *                      structures.
+ *                      Added a new MsgFlag to the FwDownload request to
+ *                      indicate last segment.
+ *                      Defined a new image type of boot loader.
+ *                      Added FW family codes for SAS product families.
+ *  10-05-04  01.05.02  Added ReplyFifoHostSignalingAddr field to
+ *                      MSG_IOC_FACTS_REPLY.
+ *  12-07-04  01.05.03  Added more defines for SAS Discovery Error event.
+ *  12-09-04  01.05.04  Added Unsupported device to SAS Device event.
+ *  01-15-05  01.05.05  Added event data for SAS SES Event.
+ *  02-09-05  01.05.06  Added MPI_FW_UPLOAD_ITYPE_FW_BACKUP define.
+ *  02-22-05  01.05.07  Added Host Page Buffer Persistent flag to IOC Facts
+ *                      Reply and IOC Init Request.
+ *  03-11-05  01.05.08  Added family code for 1068E family.
+ *                      Removed IOCFacts Reply EEDP Capability bit.
  *  --------------------------------------------------------------------------
 
 mpi_cnfg.h
@@ -142,6 +220,166 @@
  *                      Added IO Unit Page 3.
  *                      Modified defines for Scsi Port Page 2.
  *                      Modified RAID Volume Pages.
+ *  08-08-01  01.02.01  Original release for v1.2 work.
+ *                      Added SepID and SepBus to RVP2 IMPhysicalDisk struct.
+ *                      Added defines for the SEP bits in RVP2 VolumeSettings.
+ *                      Modified the DeviceSettings field in RVP2 to use the
+ *                      proper structure.
+ *                      Added defines for SES, SAF-TE, and cross channel for
+ *                      IOCPage2 CapabilitiesFlags.
+ *                      Removed define for MPI_IOUNITPAGE2_FLAGS_RAID_DISABLE.
+ *                      Removed define for
+ *                      MPI_SCSIPORTPAGE2_PORT_FLAGS_PARITY_ENABLE.
+ *                      Added define for MPI_CONFIG_PAGEATTR_RO_PERSISTENT.
+ *  08-29-01 01.02.02   Fixed value for MPI_MANUFACTPAGE_DEVID_53C1035.
+ *                      Added defines for MPI_FCPORTPAGE1_FLAGS_HARD_ALPA_ONLY
+ *                      and MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY.
+ *                      Removed MPI_SCSIPORTPAGE0_CAP_PACING_TRANSFERS,
+ *                      MPI_SCSIDEVPAGE0_NP_PACING_TRANSFERS, and
+ *                      MPI_SCSIDEVPAGE1_RP_PACING_TRANSFERS, and
+ *                      MPI_SCSIDEVPAGE1_CONF_PPR_ALLOWED.
+ *                      Added defines for MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED
+ *                      and MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED.
+ *                      Added OnBusTimerValue to CONFIG_PAGE_SCSI_PORT_1.
+ *                      Added rejected bits to SCSI Device Page 0 Information.
+ *                      Increased size of ALPA array in FC Port Page 2 by one
+ *                      and removed a one byte reserved field.
+ *  09-28-01 01.02.03   Swapped NegWireSpeedLow and NegWireSpeedLow in
+ *                      CONFIG_PAGE_LAN_1 to match preferred 64-bit ordering.
+ *                      Added structures for Manufacturing Page 4, IO Unit
+ *                      Page 3, IOC Page 3, IOC Page 4, RAID Volume Page 0, and
+ *                      RAID PhysDisk Page 0.
+ *  10-04-01 01.02.04   Added define for MPI_CONFIG_PAGETYPE_RAID_PHYSDISK.
+ *                      Modified some of the new defines to make them 32
+ *                      character unique.
+ *                      Modified how variable length pages (arrays) are defined.
+ *                      Added generic defines for hot spare pools and RAID
+ *                      volume types.
+ *  11-01-01 01.02.05   Added define for MPI_IOUNITPAGE1_DISABLE_IR.
+ *  03-14-02 01.02.06   Added PCISlotNum field to CONFIG_PAGE_IOC_1 along with
+ *                      related define, and bumped the page version define.
+ *  05-31-02 01.02.07   Added a Flags field to CONFIG_PAGE_IOC_2_RAID_VOL in a
+ *                      reserved byte and added a define.
+ *                      Added define for
+ *                      MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE.
+ *                      Added new config page: CONFIG_PAGE_IOC_5.
+ *                      Added MaxAliases, MaxHardAliases, and NumCurrentAliases
+ *                      fields to CONFIG_PAGE_FC_PORT_0.
+ *                      Added AltConnector and NumRequestedAliases fields to
+ *                      CONFIG_PAGE_FC_PORT_1.
+ *                      Added new config page: CONFIG_PAGE_FC_PORT_10.
+ *  07-12-02 01.02.08   Added more MPI_MANUFACTPAGE_DEVID_ defines.
+ *                      Added additional MPI_SCSIDEVPAGE0_NP_ defines.
+ *                      Added more MPI_SCSIDEVPAGE1_RP_ defines.
+ *                      Added define for
+ *                      MPI_SCSIDEVPAGE1_CONF_EXTENDED_PARAMS_ENABLE.
+ *                      Added new config page: CONFIG_PAGE_SCSI_DEVICE_3.
+ *                      Modified MPI_FCPORTPAGE5_FLAGS_ defines.
+ *  09-16-02 01.02.09   Added MPI_SCSIDEVPAGE1_CONF_FORCE_PPR_MSG define.
+ *  11-15-02 01.02.10   Added ConnectedID defines for CONFIG_PAGE_SCSI_PORT_0.
+ *                      Added more Flags defines for CONFIG_PAGE_FC_PORT_1.
+ *                      Added more Flags defines for CONFIG_PAGE_FC_DEVICE_0.
+ *  04-01-03 01.02.11   Added RR_TOV field and additional Flags defines for
+ *                      CONFIG_PAGE_FC_PORT_1.
+ *                      Added define MPI_FCPORTPAGE5_FLAGS_DISABLE to disable
+ *                      an alias.
+ *                      Added more device id defines.
+ *  06-26-03 01.02.12   Added MPI_IOUNITPAGE1_IR_USE_STATIC_VOLUME_ID define.
+ *                      Added TargetConfig and IDConfig fields to
+ *                      CONFIG_PAGE_SCSI_PORT_1.
+ *                      Added more PortFlags defines for CONFIG_PAGE_SCSI_PORT_2
+ *                      to control DV.
+ *                      Added more Flags defines for CONFIG_PAGE_FC_PORT_1.
+ *                      In CONFIG_PAGE_FC_DEVICE_0, replaced Reserved1 field
+ *                      with ADISCHardALPA.
+ *                      Added MPI_FC_DEVICE_PAGE0_PROT_FCP_RETRY define.
+ *  01-16-04  01.02.13  Added InitiatorDeviceTimeout and InitiatorIoPendTimeout
+ *                      fields and related defines to CONFIG_PAGE_FC_PORT_1.
+ *                      Added define for
+ *                      MPI_FCPORTPAGE1_FLAGS_SOFT_ALPA_FALLBACK.
+ *                      Added new fields to the substructures of
+ *                      CONFIG_PAGE_FC_PORT_10.
+ *  04-29-04 01.02.14   Added define for IDP bit for CONFIG_PAGE_SCSI_PORT_0,
+ *                      CONFIG_PAGE_SCSI_DEVICE_0, and
+ *                      CONFIG_PAGE_SCSI_DEVICE_1. Also bumped Page Version for
+ *                      these pages.
+ *  05-11-04 01.03.01   Added structure for CONFIG_PAGE_INBAND_0.
+ *  08-19-04 01.05.01   Modified MSG_CONFIG request to support extended config
+ *                      pages.
+ *                      Added a new structure for extended config page header.
+ *                      Added new extended config pages types and structures for
+ *                      SAS IO Unit, SAS Expander, SAS Device, and SAS PHY.
+ *                      Replaced a reserved byte in CONFIG_PAGE_MANUFACTURING_4
+ *                      to add a Flags field.
+ *                      Two new Manufacturing config pages (5 and 6).
+ *                      Two new bits defined for IO Unit Page 1 Flags field.
+ *                      Modified CONFIG_PAGE_IO_UNIT_2 to add three new fields
+ *                      to specify the BIOS boot device.
+ *                      Four new Flags bits defined for IO Unit Page 2.
+ *                      Added IO Unit Page 4.
+ *                      Added EEDP Flags settings to IOC Page 1.
+ *                      Added new BIOS Page 1 config page.
+ *  10-05-04 01.05.02   Added define for
+ *                      MPI_IOCPAGE1_INITIATOR_CONTEXT_REPLY_DISABLE.
+ *                      Added new Flags field to CONFIG_PAGE_MANUFACTURING_5 and
+ *                      associated defines.
+ *                      Added more defines for SAS IO Unit Page 0
+ *                      DiscoveryStatus field.
+ *                      Added define for MPI_SAS_IOUNIT0_DS_SUBTRACTIVE_LINK
+ *                      and MPI_SAS_IOUNIT0_DS_TABLE_LINK.
+ *                      Added defines for Physical Mapping Modes to SAS IO Unit
+ *                      Page 2.
+ *                      Added define for
+ *                      MPI_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH.
+ *  10-27-04 01.05.03   Added defines for new SAS PHY page addressing mode.
+ *                      Added defines for MaxTargetSpinUp to BIOS Page 1.
+ *                      Added 5 new ControlFlags defines for SAS IO Unit
+ *                      Page 1.
+ *                      Added MaxNumPhysicalMappedIDs field to SAS IO Unit
+ *                      Page 2.
+ *                      Added AccessStatus field to SAS Device Page 0 and added
+ *                      new Flags bits for supported SATA features.
+ *  12-07-04  01.05.04  Added config page structures for BIOS Page 2, RAID
+ *                      Volume Page 1, and RAID Physical Disk Page 1.
+ *                      Replaced IO Unit Page 1 BootTargetID,BootBus, and
+ *                      BootAdapterNum with reserved field.
+ *                      Added DataScrubRate and ResyncRate to RAID Volume
+ *                      Page 0.
+ *                      Added MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT
+ *                      define.
+ *  12-09-04  01.05.05  Added Target Mode Large CDB Enable to FC Port Page 1
+ *                      Flags field.
+ *                      Added Auto Port Config flag define for SAS IOUNIT
+ *                      Page 1 ControlFlags.
+ *                      Added Disabled bad Phy define to Expander Page 1
+ *                      Discovery Info field.
+ *                      Added SAS/SATA device support to SAS IOUnit Page 1
+ *                      ControlFlags.
+ *                      Added Unsupported device to SAS Dev Page 0 Flags field
+ *                      Added disable use SATA Hash Address for SAS IOUNIT
+ *                      page 1 in ControlFields.
+ *  01-15-05  01.05.06  Added defaults for data scrub rate and resync rate to
+ *                      Manufacturing Page 4.
+ *                      Added new defines for BIOS Page 1 IOCSettings field.
+ *                      Added ExtDiskIdentifier field to RAID Physical Disk
+ *                      Page 0.
+ *                      Added new defines for SAS IO Unit Page 1 ControlFlags
+ *                      and to SAS Device Page 0 Flags to control SATA devices.
+ *                      Added defines and structures for the new Log Page 0, a
+ *                      new type of configuration page.
+ *  02-09-05  01.05.07  Added InactiveStatus field to RAID Volume Page 0.
+ *                      Added WWID field to RAID Volume Page 1.
+ *                      Added PhysicalPort field to SAS Expander pages 0 and 1.
+ *  03-11-05  01.05.08  Removed the EEDP flags from IOC Page 1.
+ *                      Added Enclosure/Slot boot device format to BIOS Page 2.
+ *                      New status value for RAID Volume Page 0 VolumeStatus
+ *                      (VolumeState subfield).
+ *                      New value for RAID Physical Page 0 InactiveStatus.
+ *                      Added Inactive Volume Member flag RAID Physical Disk
+ *                      Page 0 PhysDiskStatus field.
+ *                      New physical mapping mode in SAS IO Unit Page 2.
+ *                      Added CONFIG_PAGE_SAS_ENCLOSURE_0.
+ *                      Added Slot and Enclosure fields to SAS Device Page 0.
  *  --------------------------------------------------------------------------
 
 mpi_init.h
@@ -154,6 +392,32 @@
  *  02-20-01  01.01.03  Started using MPI_POINTER.
  *  03-27-01  01.01.04  Added structure offset comments.
  *  04-10-01  01.01.05  Added new MsgFlag for MSG_SCSI_TASK_MGMT.
+ *  08-08-01  01.02.01  Original release for v1.2 work.
+ *  08-29-01  01.02.02  Added MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET.
+ *                      Added MPI_SCSI_STATE_QUEUE_TAG_REJECTED for
+ *                      MSG_SCSI_IO_REPLY.
+ *  09-28-01  01.02.03  Added structures and defines for SCSI Enclosure
+ *                      Processor messages.
+ *  10-04-01  01.02.04  Added defines for SEP request Action field.
+ *  05-31-02  01.02.05  Added MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR define
+ *                      for SCSI IO requests.
+ *  11-15-02  01.02.06  Added special extended SCSI Status defines for FCP.
+ *  06-26-03  01.02.07  Added MPI_SCSI_STATUS_FCPEXT_UNASSIGNED define.
+ *  05-11-04  01.03.01  Original release for MPI v1.3.
+ *  08-19-04  01.05.01  Added MsgFlags defines for EEDP to SCSI IO request.
+ *                      Added new word to MSG_SCSI_IO_REPLY to add TaskTag field
+ *                      and a reserved U16.
+ *                      Added new MSG_SCSI_IO32_REQUEST structure.
+ *                      Added a TaskType of Clear Task Set to SCSI
+ *                      Task Management request.
+ *  12-07-04  01.05.02  Added support for Task Management Query Task.
+ *  01-15-05  01.05.03  Modified SCSI Enclosure Processor Request to support
+ *                      WWID addressing.
+ *  03-11-05  01.05.04  Removed EEDP flags from SCSI IO Request.
+ *                      Removed SCSI IO 32 Request.
+ *                      Modified SCSI Enclosure Processor Request and Reply to
+ *                      support Enclosure/Slot addressing rather than WWID
+ *                      addressing.
  *  --------------------------------------------------------------------------
 
 mpi_targ.h
@@ -170,6 +434,33 @@
  *                      Added structures for MPI_TARGET_SCSI_SPI_CMD_BUFFER and
  *                      MPI_TARGET_FCP_CMD_BUFFER.
  *  03-27-01  01.01.04  Added structure offset comments.
+ *  08-08-01  01.02.01  Original release for v1.2 work.
+ *  09-28-01  01.02.02  Added structure for MPI_TARGET_SCSI_SPI_STATUS_IU.
+ *                      Added PriorityReason field to some replies and
+ *                      defined more PriorityReason codes.
+ *                      Added some defines for to support previous version
+ *                      of MPI.
+ *  10-04-01  01.02.03  Added PriorityReason to MSG_TARGET_ERROR_REPLY.
+ *  11-01-01  01.02.04  Added define for TARGET_STATUS_SEND_FLAGS_HIGH_PRIORITY.
+ *  03-14-02  01.02.05  Modified MPI_TARGET_FCP_RSP_BUFFER to get the proper
+ *                      byte ordering.
+ *  05-31-02  01.02.06  Modified TARGET_MODE_REPLY_ALIAS_MASK to only include
+ *                      one bit.
+ *                      Added AliasIndex field to MPI_TARGET_FCP_CMD_BUFFER.
+ *  09-16-02  01.02.07  Added flags for confirmed completion.
+ *                      Added PRIORITY_REASON_TARGET_BUSY.
+ *  11-15-02  01.02.08  Added AliasID field to MPI_TARGET_SCSI_SPI_CMD_BUFFER.
+ *  04-01-03  01.02.09  Added OptionalOxid field to MPI_TARGET_FCP_CMD_BUFFER.
+ *  05-11-04  01.03.01  Original release for MPI v1.3.
+ *  08-19-04  01.05.01  Added new request message structures for
+ *                      MSG_TARGET_CMD_BUF_POST_BASE_REQUEST,
+ *                      MSG_TARGET_CMD_BUF_POST_LIST_REQUEST, and
+ *                      MSG_TARGET_ASSIST_EXT_REQUEST.
+ *                      Added new structures for SAS SSP Command buffer, SSP
+ *                      Task buffer, and SSP Status IU.
+ *  10-05-04  01.05.02  MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY added.
+ *  02-22-05  01.05.03  Changed a comment.
+ *  03-11-05  01.05.04  Removed TargetAssistExtended Request.
  *  --------------------------------------------------------------------------
 
 mpi_fc.h
@@ -192,6 +483,13 @@
  *                      Added MPI_FC_PRIM_SEND_FLAGS_RESET_LINK define.
  *                      Added structure offset comments.
  *  04-09-01  01.01.07  Added RspLength field to MSG_LINK_SERVICE_RSP_REQUEST.
+ *  08-08-01  01.02.01  Original release for v1.2 work.
+ *  09-28-01  01.02.02  Change name of reserved field in
+ *                      MSG_LINK_SERVICE_RSP_REPLY.
+ *  05-31-02  01.02.03  Adding AliasIndex to FC Direct Access requests.
+ *  01-16-04  01.02.04  Added define for MPI_FC_PRIM_SEND_FLAGS_ML_RESET_LINK.
+ *  05-11-04  01.03.01  Original release for MPI v1.3.
+ *  08-19-04  01.05.01  Original release for MPI v1.5.
  *  --------------------------------------------------------------------------
 
 mpi_lan.h
@@ -209,11 +507,56 @@
  *  11-02-00  01.01.01  Original release for post 1.0 work
  *  02-20-01  01.01.02  Started using MPI_POINTER.
  *  03-27-01  01.01.03  Added structure offset comments.
+ *  08-08-01  01.02.01  Original release for v1.2 work.
+ *  05-11-04  01.03.01  Original release for MPI v1.3.
+ *  08-19-04  01.05.01  Original release for MPI v1.5.
  *  --------------------------------------------------------------------------
 
 mpi_raid.h
  *  02-27-01  01.01.01  Original release for this file.
  *  03-27-01  01.01.02  Added structure offset comments.
+ *  08-08-01  01.02.01  Original release for v1.2 work.
+ *  08-29-01  01.02.02  Added DIAG_DATA_UPLOAD_HEADER and related defines.
+ *  09-28-01  01.02.02  Major rework for MPI v1.2 Integrated RAID changes.
+ *  10-04-01  01.02.03  Added ActionData defines for
+ *                      MPI_RAID_ACTION_DELETE_VOLUME action.
+ *  11-01-01  01.02.04  Added define for MPI_RAID_ACTION_ADATA_DO_NOT_SYNC.
+ *  03-14-02  01.02.05  Added define for MPI_RAID_ACTION_ADATA_LOW_LEVEL_INIT.
+ *  05-07-02  01.02.06  Added define for MPI_RAID_ACTION_ACTIVATE_VOLUME,
+ *                      MPI_RAID_ACTION_INACTIVATE_VOLUME, and
+ *                      MPI_RAID_ACTION_ADATA_INACTIVATE_ALL.
+ *  07-12-02  01.02.07  Added structures for Mailbox request and reply.
+ *  11-15-02  01.02.08  Added missing MsgContext field to MSG_MAILBOX_REQUEST.
+ *  04-01-03  01.02.09  New action data option flag for
+ *                      MPI_RAID_ACTION_DELETE_VOLUME.
+ *  05-11-04  01.03.01  Original release for MPI v1.3.
+ *  08-19-04  01.05.01  Original release for MPI v1.5.
+ *  01-15-05  01.05.02  Added defines for the two new RAID Actions for
+ *                      _SET_RESYNC_RATE and _SET_DATA_SCRUB_RATE.
+ *  --------------------------------------------------------------------------
+
+mpi_tool.h
+ *  08-08-01  01.02.01  Original release.
+ *  08-29-01  01.02.02  Added DIAG_DATA_UPLOAD_HEADER and related defines.
+ *  01-16-04  01.02.03  Added defines and structures for new tools
+ *.                     MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL and
+ *                      MPI_TOOLBOX_FC_MANAGEMENT_TOOL.
+ *  04-29-04  01.02.04  Added message structures for Diagnostic Buffer Post and
+ *                      Diagnostic Release requests and replies.
+ *  05-11-04  01.03.01  Original release for MPI v1.3.
+ *  08-19-04  01.05.01  Original release for MPI v1.5.
+ *  10-06-04  01.05.02  Added define for MPI_DIAG_BUF_TYPE_COUNT.
+ *  02-09-05  01.05.03  Added frame size option to FC management tool.
+ *                      Added Beacon tool to the Toolbox.
+ *  --------------------------------------------------------------------------
+
+mpi_inb.h
+ *  05-11-04  01.03.01  Original release.
+ *  08-19-04  01.05.01  Original release for MPI v1.5.
+ *  --------------------------------------------------------------------------
+
+mpi_sas.h
+ *  08-19-04  01.05.01  Original release.
  *  --------------------------------------------------------------------------
 
 mpi_type.h
@@ -221,21 +564,83 @@
  *  06-06-00  01.00.01  Update version number for 1.0 release.
  *  11-02-00  01.01.01  Original release for post 1.0 work
  *  02-20-01  01.01.02  Added define and ifdef for MPI_POINTER.
+ *  08-08-01  01.02.01  Original release for v1.2 work.
+ *  05-11-04  01.03.01  Original release for MPI v1.3.
+ *  08-19-04  01.05.01  Original release for MPI v1.5.
  *  --------------------------------------------------------------------------
 
 mpi_history.txt         Parts list history
 
-Filename    01.01.10
+Filename    01.05.09
 ----------  --------
-mpi.h       01.01.07
-mpi_ioc.h   01.01.07
-mpi_cnfg.h  01.01.11
-mpi_init.h  01.01.05
-mpi_targ.h  01.01.04
-mpi_fc.h    01.01.07
-mpi_lan.h   01.01.03
-mpi_raid.h  01.01.02
-mpi_type.h  01.01.02
+mpi.h       01.05.07
+mpi_ioc.h   01.05.08
+mpi_cnfg.h  01.05.08
+mpi_init.h  01.05.04
+mpi_targ.h  01.05.04
+mpi_fc.h    01.05.01
+mpi_lan.h   01.05.01
+mpi_raid.h  01.05.02
+mpi_tool.h  01.05.03
+mpi_inb.h   01.05.01
+mpi_sas.h   01.05.01
+mpi_type.h  01.05.01
+
+Filename    01.05.08   01.05.07   01.05.06   01.05.05   01.05.04   01.05.03
+----------  --------   --------   --------   --------   --------   --------
+mpi.h       01.05.06   01.05.05   01.05.04   01.05.03   01.05.02   01.05.01
+mpi_ioc.h   01.05.07   01.05.06   01.05.05   01.05.04   01.05.03   01.05.02
+mpi_cnfg.h  01.05.07   01.05.07   01.05.06   01.05.05   01.05.04   01.05.03
+mpi_init.h  01.05.03   01.05.03   01.05.03   01.05.02   01.05.02   01.05.01
+mpi_targ.h  01.05.03   01.05.02   01.05.02   01.05.02   01.05.02   01.05.02
+mpi_fc.h    01.05.01   01.05.01   01.05.01   01.05.01   01.05.01   01.05.01
+mpi_lan.h   01.05.01   01.05.01   01.05.01   01.05.01   01.05.01   01.05.01
+mpi_raid.h  01.05.02   01.05.02   01.05.02   01.05.01   01.05.01   01.05.01
+mpi_tool.h  01.05.03   01.05.03   01.05.02   01.05.02   01.05.02   01.05.02
+mpi_inb.h   01.05.01   01.05.01   01.05.01   01.05.01   01.05.01   01.05.01
+mpi_sas.h   01.05.01   01.05.01   01.05.01   01.05.01   01.05.01   01.05.01
+mpi_type.h  01.05.01   01.05.01   01.05.01   01.05.01   01.05.01   01.05.01
+
+Filename    01.05.02   01.05.01   01.03.01   01.02.14   01.02.13   01.02.12
+----------  --------   --------   --------   --------   --------   --------
+mpi.h       01.05.01   01.05.01   01.03.01   01.02.12   01.02.11   01.02.10
+mpi_ioc.h   01.05.02   01.05.01   01.03.01   01.02.09   01.02.08   01.02.08
+mpi_cnfg.h  01.05.02   01.05.01   01.03.01   01.02.14   01.02.13   01.02.12
+mpi_init.h  01.05.01   01.05.01   01.03.01   01.02.07   01.02.07   01.02.07
+mpi_targ.h  01.05.02   01.05.01   01.03.01   01.02.09   01.02.09   01.02.09
+mpi_fc.h    01.05.01   01.05.01   01.03.01   01.02.04   01.02.04   01.02.03
+mpi_lan.h   01.05.01   01.05.01   01.03.01   01.02.01   01.02.01   01.02.01
+mpi_raid.h  01.05.01   01.05.01   01.03.01   01.02.09   01.02.09   01.02.09
+mpi_tool.h  01.05.02   01.05.01   01.03.01   01.02.01   01.02.01   01.02.01
+mpi_inb.h   01.05.01   01.05.01   01.03.01
+mpi_sas.h   01.05.01   01.05.01
+mpi_type.h  01.05.01   01.05.01   01.03.01   01.02.04   01.02.03   01.02.02
+
+Filename    01.02.11   01.02.10   01.02.09   01.02.08   01.02.07   01.02.06
+----------  --------   --------   --------   --------   --------   --------
+mpi.h       01.02.09   01.02.08   01.02.07   01.02.06   01.02.05   01.02.04
+mpi_ioc.h   01.02.07   01.02.06   01.02.06   01.02.06   01.02.06   01.02.05
+mpi_cnfg.h  01.02.11   01.02.10   01.02.09   01.02.08   01.02.07   01.02.06
+mpi_init.h  01.02.06   01.02.06   01.02.05   01.02.05   01.02.05   01.02.04
+mpi_targ.h  01.02.09   01.02.08   01.02.07   01.02.06   01.02.06   01.02.05
+mpi_fc.h    01.02.03   01.02.03   01.02.03   01.02.03   01.02.03   01.02.02
+mpi_lan.h   01.02.01   01.02.01   01.02.01   01.02.01   01.02.01   01.02.01
+mpi_raid.h  01.02.09   01.02.08   01.02.07   01.02.07   01.02.06   01.02.05
+mpi_tool.h  01.02.01   01.02.01   01.02.01   01.02.01   01.02.01   01.02.01
+mpi_type.h  01.02.02   01.02.02   01.02.02   01.02.02   01.02.02   01.02.02
+
+Filename    01.02.05   01.02.04   01.02.03   01.02.02   01.02.01   01.01.10
+----------  --------   --------   --------   --------   --------   --------
+mpi.h       01.02.03   01.02.02   01.02.02   01.02.01   01.02.01   01.01.07
+mpi_ioc.h   01.02.04   01.02.03   01.02.03   01.02.02   01.02.01   01.01.07
+mpi_cnfg.h  01.02.05   01.02.04   01.02.03   01.02.02   01.02.01   01.01.11
+mpi_init.h  01.02.04   01.02.04   01.02.03   01.02.02   01.02.01   01.01.05
+mpi_targ.h  01.02.04   01.02.03   01.02.02   01.02.01   01.02.01   01.01.04
+mpi_fc.h    01.02.02   01.02.02   01.02.02   01.02.01   01.02.01   01.01.07
+mpi_lan.h   01.02.01   01.02.01   01.02.01   01.02.01   01.02.01   01.01.03
+mpi_raid.h  01.02.04   01.02.03   01.02.02   01.02.01   01.02.01   01.01.02
+mpi_tool.h  01.02.02   01.02.02   01.02.02   01.02.02   01.02.01
+mpi_type.h  01.02.02   01.02.02   01.02.02   01.02.02   01.02.01   01.01.02
 
 Filename    01.01.09   01.01.08   01.01.07   01.01.06   01.01.05   01.01.04
 ----------  --------   --------   --------   --------   --------   --------
diff --git a/drivers/message/fusion/lsi/mpi_inb.h b/drivers/message/fusion/lsi/mpi_inb.h
index dae29fb..ff16730 100644
--- a/drivers/message/fusion/lsi/mpi_inb.h
+++ b/drivers/message/fusion/lsi/mpi_inb.h
@@ -1,19 +1,20 @@
 /*
- *  Copyright (c) 2003 LSI Logic Corporation.
+ *  Copyright (c) 2003-2004 LSI Logic Corporation.
  *
  *
  *           Name:  mpi_inb.h
  *          Title:  MPI Inband structures and definitions
  *  Creation Date:  September 30, 2003
  *
- *    mpi_inb.h Version:  01.03.xx
+ *    mpi_inb.h Version:  01.05.01
  *
  *  Version History
  *  ---------------
  *
  *  Date      Version   Description
  *  --------  --------  ------------------------------------------------------
- *  ??-??-??  01.03.01  Original release.
+ *  05-11-04  01.03.01  Original release.
+ *  08-19-04  01.05.01  Original release for MPI v1.5.
  *  --------------------------------------------------------------------------
  */
 
diff --git a/drivers/message/fusion/lsi/mpi_init.h b/drivers/message/fusion/lsi/mpi_init.h
index b3c95fd..aca0358 100644
--- a/drivers/message/fusion/lsi/mpi_init.h
+++ b/drivers/message/fusion/lsi/mpi_init.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2003 LSI Logic Corporation.
+ *  Copyright (c) 2000-2005 LSI Logic Corporation.
  *
  *
  *           Name:  mpi_init.h
  *          Title:  MPI initiator mode messages and structures
  *  Creation Date:  June 8, 2000
  *
- *    mpi_init.h Version:  01.05.xx
+ *    mpi_init.h Version:  01.05.04
  *
  *  Version History
  *  ---------------
@@ -33,6 +33,21 @@
  *                      for SCSI IO requests.
  *  11-15-02  01.02.06  Added special extended SCSI Status defines for FCP.
  *  06-26-03  01.02.07  Added MPI_SCSI_STATUS_FCPEXT_UNASSIGNED define.
+ *  05-11-04  01.03.01  Original release for MPI v1.3.
+ *  08-19-04  01.05.01  Added MsgFlags defines for EEDP to SCSI IO request.
+ *                      Added new word to MSG_SCSI_IO_REPLY to add TaskTag field
+ *                      and a reserved U16.
+ *                      Added new MSG_SCSI_IO32_REQUEST structure.
+ *                      Added a TaskType of Clear Task Set to SCSI
+ *                      Task Management request.
+ *  12-07-04  01.05.02  Added support for Task Management Query Task.
+ *  01-15-05  01.05.03  Modified SCSI Enclosure Processor Request to support
+ *                      WWID addressing.
+ *  03-11-05  01.05.04  Removed EEDP flags from SCSI IO Request.
+ *                      Removed SCSI IO 32 Request.
+ *                      Modified SCSI Enclosure Processor Request and Reply to
+ *                      support Enclosure/Slot addressing rather than WWID
+ *                      addressing.
  *  --------------------------------------------------------------------------
  */
 
@@ -76,20 +91,12 @@
 #define MPI_SCSIIO_MSGFLGS_SENSE_WIDTH              (0x01)
 #define MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_32           (0x00)
 #define MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64           (0x01)
+
 #define MPI_SCSIIO_MSGFLGS_SENSE_LOCATION           (0x02)
 #define MPI_SCSIIO_MSGFLGS_SENSE_LOC_HOST           (0x00)
 #define MPI_SCSIIO_MSGFLGS_SENSE_LOC_IOC            (0x02)
-#define MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR  (0x04)
-#define MPI_SCSIIO_MSGFLGS_EEDP_TYPE_MASK           (0xE0)
-#define MPI_SCSIIO_MSGFLGS_EEDP_NONE                (0x00)
-#define MPI_SCSIIO_MSGFLGS_EEDP_RDPROTECT_T10       (0x20)
-#define MPI_SCSIIO_MSGFLGS_EEDP_VRPROTECT_T10       (0x40)
-#define MPI_SCSIIO_MSGFLGS_EEDP_WRPROTECT_T10       (0x60)
-#define MPI_SCSIIO_MSGFLGS_EEDP_520_READ_MODE1      (0x20)
-#define MPI_SCSIIO_MSGFLGS_EEDP_520_WRITE_MODE1     (0x40)
-#define MPI_SCSIIO_MSGFLGS_EEDP_8_9_READ_MODE1      (0x60)
-#define MPI_SCSIIO_MSGFLGS_EEDP_8_9_WRITE_MODE1     (0x80)
 
+#define MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR  (0x04)
 
 /* SCSI IO LUN fields */
 
@@ -148,6 +155,8 @@
     U32                     TransferCount;      /* 14h */
     U32                     SenseCount;         /* 18h */
     U32                     ResponseInfo;       /* 1Ch */
+    U16                     TaskTag;            /* 20h */
+    U16                     Reserved1;          /* 22h */
 } MSG_SCSI_IO_REPLY, MPI_POINTER PTR_MSG_SCSI_IO_REPLY,
   SCSIIOReply_t, MPI_POINTER pSCSIIOReply_t;
 
@@ -190,32 +199,7 @@
 #define MPI_SCSI_RSP_INFO_TASK_MGMT_FAILED      (0x05000000)
 #define MPI_SCSI_RSP_INFO_SPI_LQ_INVALID_TYPE   (0x06000000)
 
-
-/****************************************************************************/
-/*  SCSI IO 32 Request message structure                                    */
-/****************************************************************************/
-
-typedef struct _MSG_SCSI_IO32_REQUEST
-{
-    U8                      TargetID;           /* 00h */
-    U8                      Bus;                /* 01h */
-    U8                      ChainOffset;        /* 02h */
-    U8                      Function;           /* 03h */
-    U8                      CDBLength;          /* 04h */
-    U8                      SenseBufferLength;  /* 05h */
-    U8                      Reserved;           /* 06h */
-    U8                      MsgFlags;           /* 07h */
-    U32                     MsgContext;         /* 08h */
-    U8                      LUN[8];             /* 0Ch */
-    U32                     Control;            /* 14h */
-    U8                      CDB[32];            /* 18h */
-    U32                     DataLength;         /* 38h */
-    U32                     SenseBufferLowAddr; /* 3Ch */
-    SGE_IO_UNION            SGL;                /* 40h */
-} MSG_SCSI_IO32_REQUEST, MPI_POINTER PTR_MSG_SCSI_IO32_REQUEST,
-  SCSIIO32Request_t, MPI_POINTER pSCSIIO32Request_t;
-
-/* SCSI IO 32 uses the same defines as above for SCSI IO */
+#define MPI_SCSI_TASKTAG_UNKNOWN                (0xFFFF)
 
 
 /****************************************************************************/
@@ -247,6 +231,7 @@
 #define MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS             (0x04)
 #define MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET    (0x05)
 #define MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET        (0x06)
+#define MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK            (0x07)
 
 /* MsgFlags bits */
 #define MPI_SCSITASKMGMT_MSGFLAGS_TARGET_RESET_OPTION   (0x00)
@@ -260,7 +245,7 @@
     U8                      Bus;                /* 01h */
     U8                      MsgLength;          /* 02h */
     U8                      Function;           /* 03h */
-    U8                      Reserved;           /* 04h */
+    U8                      ResponseCode;       /* 04h */
     U8                      TaskType;           /* 05h */
     U8                      Reserved1;          /* 06h */
     U8                      MsgFlags;           /* 07h */
@@ -272,6 +257,15 @@
 } MSG_SCSI_TASK_MGMT_REPLY, MPI_POINTER PTR_MSG_SCSI_TASK_MGMT_REPLY,
   SCSITaskMgmtReply_t, MPI_POINTER pSCSITaskMgmtReply_t;
 
+/* ResponseCode values */
+#define MPI_SCSITASKMGMT_RSP_TM_COMPLETE                (0x00)
+#define MPI_SCSITASKMGMT_RSP_INVALID_FRAME              (0x02)
+#define MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED           (0x04)
+#define MPI_SCSITASKMGMT_RSP_TM_FAILED                  (0x05)
+#define MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED               (0x08)
+#define MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN             (0x09)
+#define MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC           (0x80)
+
 
 /****************************************************************************/
 /*  SCSI Enclosure Processor messages                                       */
@@ -284,11 +278,16 @@
     U8                      ChainOffset;        /* 02h */
     U8                      Function;           /* 03h */
     U8                      Action;             /* 04h */
-    U8                      Reserved1;          /* 05h */
-    U8                      Reserved2;          /* 06h */
+    U8                      Flags;              /* 05h */
+    U8                      Reserved1;          /* 06h */
     U8                      MsgFlags;           /* 07h */
     U32                     MsgContext;         /* 08h */
     U32                     SlotStatus;         /* 0Ch */
+    U32                     Reserved2;          /* 10h */
+    U32                     Reserved3;          /* 14h */
+    U32                     Reserved4;          /* 18h */
+    U16                     Slot;               /* 1Ch */
+    U16                     EnclosureHandle;    /* 1Eh */
 } MSG_SEP_REQUEST, MPI_POINTER PTR_MSG_SEP_REQUEST,
   SEPRequest_t, MPI_POINTER pSEPRequest_t;
 
@@ -296,6 +295,10 @@
 #define MPI_SEP_REQ_ACTION_WRITE_STATUS                 (0x00)
 #define MPI_SEP_REQ_ACTION_READ_STATUS                  (0x01)
 
+/* Flags defines */
+#define MPI_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS        (0x01)
+#define MPI_SEP_REQ_FLAGS_BUS_TARGETID_ADDRESS          (0x00)
+
 /* SlotStatus bits for MSG_SEP_REQUEST */
 #define MPI_SEP_REQ_SLOTSTATUS_NO_ERROR                 (0x00000001)
 #define MPI_SEP_REQ_SLOTSTATUS_DEV_FAULTY               (0x00000002)
@@ -332,6 +335,9 @@
     U16                     IOCStatus;          /* 0Eh */
     U32                     IOCLogInfo;         /* 10h */
     U32                     SlotStatus;         /* 14h */
+    U32                     Reserved4;          /* 18h */
+    U16                     Slot;               /* 1Ch */
+    U16                     EnclosureHandle;    /* 1Eh */
 } MSG_SEP_REPLY, MPI_POINTER PTR_MSG_SEP_REPLY,
   SEPReply_t, MPI_POINTER pSEPReply_t;
 
diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h
index 82445d1..f91eb4e 100644
--- a/drivers/message/fusion/lsi/mpi_ioc.h
+++ b/drivers/message/fusion/lsi/mpi_ioc.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2003 LSI Logic Corporation.
+ *  Copyright (c) 2000-2005 LSI Logic Corporation.
  *
  *
  *           Name:  mpi_ioc.h
  *          Title:  MPI IOC, Port, Event, FW Download, and FW Upload messages
  *  Creation Date:  August 11, 2000
  *
- *    mpi_ioc.h Version:  01.05.xx
+ *    mpi_ioc.h Version:  01.05.08
  *
  *  Version History
  *  ---------------
@@ -57,6 +57,30 @@
  *                      Added AliasIndex to EVENT_DATA_LOGOUT structure.
  *  04-01-03  01.02.07  Added defines for MPI_FW_HEADER_SIGNATURE_.
  *  06-26-03  01.02.08  Added new values to the product family defines.
+ *  04-29-04  01.02.09  Added IOCCapabilities field to MSG_IOC_FACTS_REPLY and
+ *                      added related defines.
+ *  05-11-04  01.03.01  Original release for MPI v1.3.
+ *  08-19-04  01.05.01  Added four new fields to MSG_IOC_INIT.
+ *                      Added three new fields to MSG_IOC_FACTS_REPLY.
+ *                      Defined four new bits for the IOCCapabilities field of
+ *                      the IOCFacts reply.
+ *                      Added two new PortTypes for the PortFacts reply.
+ *                      Added six new events along with their EventData
+ *                      structures.
+ *                      Added a new MsgFlag to the FwDownload request to
+ *                      indicate last segment.
+ *                      Defined a new image type of boot loader.
+ *                      Added FW family codes for SAS product families.
+ *  10-05-04  01.05.02  Added ReplyFifoHostSignalingAddr field to
+ *                      MSG_IOC_FACTS_REPLY.
+ *  12-07-04  01.05.03  Added more defines for SAS Discovery Error event.
+ *  12-09-04  01.05.04  Added Unsupported device to SAS Device event.
+ *  01-15-05  01.05.05  Added event data for SAS SES Event.
+ *  02-09-05  01.05.06  Added MPI_FW_UPLOAD_ITYPE_FW_BACKUP define.
+ *  02-22-05  01.05.07  Added Host Page Buffer Persistent flag to IOC Facts
+ *                      Reply and IOC Init Request.
+ *  03-11-05  01.05.08  Added family code for 1068E family.
+ *                      Removed IOCFacts Reply EEDP Capability bit.
  *  --------------------------------------------------------------------------
  */
 
@@ -90,20 +114,37 @@
     U32                     HostMfaHighAddr;            /* 10h */
     U32                     SenseBufferHighAddr;        /* 14h */
     U32                     ReplyFifoHostSignalingAddr; /* 18h */
+    SGE_SIMPLE_UNION        HostPageBufferSGE;          /* 1Ch */
+    U16                     MsgVersion;                 /* 28h */
+    U16                     HeaderVersion;              /* 2Ah */
 } MSG_IOC_INIT, MPI_POINTER PTR_MSG_IOC_INIT,
   IOCInit_t, MPI_POINTER pIOCInit_t;
 
 /* WhoInit values */
-#define MPI_WHOINIT_NO_ONE                          (0x00)
-#define MPI_WHOINIT_SYSTEM_BIOS                     (0x01)
-#define MPI_WHOINIT_ROM_BIOS                        (0x02)
-#define MPI_WHOINIT_PCI_PEER                        (0x03)
-#define MPI_WHOINIT_HOST_DRIVER                     (0x04)
-#define MPI_WHOINIT_MANUFACTURER                    (0x05)
+#define MPI_WHOINIT_NO_ONE                              (0x00)
+#define MPI_WHOINIT_SYSTEM_BIOS                         (0x01)
+#define MPI_WHOINIT_ROM_BIOS                            (0x02)
+#define MPI_WHOINIT_PCI_PEER                            (0x03)
+#define MPI_WHOINIT_HOST_DRIVER                         (0x04)
+#define MPI_WHOINIT_MANUFACTURER                        (0x05)
 
 /* Flags values */
-#define MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE          (0x01)
-#define MPI_IOCINIT_FLAGS_REPLY_FIFO_HOST_SIGNAL    (0x02)
+#define MPI_IOCINIT_FLAGS_HOST_PAGE_BUFFER_PERSISTENT   (0x04)
+#define MPI_IOCINIT_FLAGS_REPLY_FIFO_HOST_SIGNAL        (0x02)
+#define MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE              (0x01)
+
+/* MsgVersion */
+#define MPI_IOCINIT_MSGVERSION_MAJOR_MASK               (0xFF00)
+#define MPI_IOCINIT_MSGVERSION_MAJOR_SHIFT              (8)
+#define MPI_IOCINIT_MSGVERSION_MINOR_MASK               (0x00FF)
+#define MPI_IOCINIT_MSGVERSION_MINOR_SHIFT              (0)
+
+/* HeaderVersion */
+#define MPI_IOCINIT_HEADERVERSION_UNIT_MASK             (0xFF00)
+#define MPI_IOCINIT_HEADERVERSION_UNIT_SHIFT            (8)
+#define MPI_IOCINIT_HEADERVERSION_DEV_MASK              (0x00FF)
+#define MPI_IOCINIT_HEADERVERSION_DEV_SHIFT             (0)
+
 
 typedef struct _MSG_IOC_INIT_REPLY
 {
@@ -187,32 +228,39 @@
     MPI_FW_VERSION          FWVersion;                  /* 38h */
     U16                     HighPriorityQueueDepth;     /* 3Ch */
     U16                     Reserved2;                  /* 3Eh */
+    SGE_SIMPLE_UNION        HostPageBufferSGE;          /* 40h */
+    U32                     ReplyFifoHostSignalingAddr; /* 4Ch */
 } MSG_IOC_FACTS_REPLY, MPI_POINTER PTR_MSG_IOC_FACTS_REPLY,
   IOCFactsReply_t, MPI_POINTER pIOCFactsReply_t;
 
-#define MPI_IOCFACTS_MSGVERSION_MAJOR_MASK          (0xFF00)
-#define MPI_IOCFACTS_MSGVERSION_MINOR_MASK          (0x00FF)
+#define MPI_IOCFACTS_MSGVERSION_MAJOR_MASK              (0xFF00)
+#define MPI_IOCFACTS_MSGVERSION_MAJOR_SHIFT             (8)
+#define MPI_IOCFACTS_MSGVERSION_MINOR_MASK              (0x00FF)
+#define MPI_IOCFACTS_MSGVERSION_MINOR_SHIFT             (0)
 
-#define MPI_IOCFACTS_HEADERVERSION_UNIT_MASK        (0xFF00)
-#define MPI_IOCFACTS_HEADERVERSION_DEV_MASK         (0x00FF)
+#define MPI_IOCFACTS_HDRVERSION_UNIT_MASK               (0xFF00)
+#define MPI_IOCFACTS_HDRVERSION_UNIT_SHIFT              (8)
+#define MPI_IOCFACTS_HDRVERSION_DEV_MASK                (0x00FF)
+#define MPI_IOCFACTS_HDRVERSION_DEV_SHIFT               (0)
 
-#define MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL    (0x0001)
-#define MPI_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID     (0x0002)
-#define MPI_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL        (0x0004)
-#define MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL   (0x0008)
+#define MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL        (0x0001)
+#define MPI_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID         (0x0002)
+#define MPI_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL            (0x0004)
+#define MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL       (0x0008)
 
-#define MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT         (0x01)
+#define MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT             (0x01)
+#define MPI_IOCFACTS_FLAGS_REPLY_FIFO_HOST_SIGNAL       (0x02)
+#define MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT  (0x04)
 
-#define MPI_IOCFACTS_EVENTSTATE_DISABLED            (0x00)
-#define MPI_IOCFACTS_EVENTSTATE_ENABLED             (0x01)
+#define MPI_IOCFACTS_EVENTSTATE_DISABLED                (0x00)
+#define MPI_IOCFACTS_EVENTSTATE_ENABLED                 (0x01)
 
-#define MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q          (0x00000001)
-#define MPI_IOCFACTS_CAPABILITY_REPLY_HOST_SIGNAL   (0x00000002)
-#define MPI_IOCFACTS_CAPABILITY_QUEUE_FULL_HANDLING (0x00000004)
-#define MPI_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER   (0x00000008)
-#define MPI_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER     (0x00000010)
-#define MPI_IOCFACTS_CAPABILITY_EXTENDED_BUFFER     (0x00000020)
-#define MPI_IOCFACTS_CAPABILITY_EEDP                (0x00000040)
+#define MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q              (0x00000001)
+#define MPI_IOCFACTS_CAPABILITY_REPLY_HOST_SIGNAL       (0x00000002)
+#define MPI_IOCFACTS_CAPABILITY_QUEUE_FULL_HANDLING     (0x00000004)
+#define MPI_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER       (0x00000008)
+#define MPI_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER         (0x00000010)
+#define MPI_IOCFACTS_CAPABILITY_EXTENDED_BUFFER         (0x00000020)
 
 
 
@@ -408,6 +456,8 @@
 #define MPI_EVENT_SAS_DEVICE_STATUS_CHANGE  (0x0000000F)
 #define MPI_EVENT_SAS_SES                   (0x00000010)
 #define MPI_EVENT_PERSISTENT_TABLE_FULL     (0x00000011)
+#define MPI_EVENT_SAS_PHY_LINK_STATUS       (0x00000012)
+#define MPI_EVENT_SAS_DISCOVERY_ERROR       (0x00000013)
 
 /* AckRequired field values */
 
@@ -467,6 +517,10 @@
     U8                      ASCQ;                       /* 05h */
     U16                     DevHandle;                  /* 06h */
     U32                     DeviceInfo;                 /* 08h */
+    U16                     ParentDevHandle;            /* 0Ch */
+    U8                      PhyNum;                     /* 0Eh */
+    U8                      Reserved1;                  /* 0Fh */
+    U64                     SASAddress;                 /* 10h */
 } EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
   MPI_POINTER PTR_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
   MpiEventDataSasDeviceStatusChange_t,
@@ -477,6 +531,8 @@
 #define MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING        (0x04)
 #define MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA            (0x05)
 #define MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED      (0x06)
+#define MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED           (0x07)
+
 
 /* SCSI Event data for Queue Full event */
 
@@ -488,6 +544,35 @@
 } EVENT_DATA_QUEUE_FULL, MPI_POINTER PTR_EVENT_DATA_QUEUE_FULL,
   EventDataQueueFull_t, MPI_POINTER pEventDataQueueFull_t;
 
+/* MPI Integrated RAID Event data */
+
+typedef struct _EVENT_DATA_RAID
+{
+    U8                      VolumeID;                   /* 00h */
+    U8                      VolumeBus;                  /* 01h */
+    U8                      ReasonCode;                 /* 02h */
+    U8                      PhysDiskNum;                /* 03h */
+    U8                      ASC;                        /* 04h */
+    U8                      ASCQ;                       /* 05h */
+    U16                     Reserved;                   /* 06h */
+    U32                     SettingsStatus;             /* 08h */
+} EVENT_DATA_RAID, MPI_POINTER PTR_EVENT_DATA_RAID,
+  MpiEventDataRaid_t, MPI_POINTER pMpiEventDataRaid_t;
+
+/* MPI Integrated RAID Event data ReasonCode values */
+#define MPI_EVENT_RAID_RC_VOLUME_CREATED                (0x00)
+#define MPI_EVENT_RAID_RC_VOLUME_DELETED                (0x01)
+#define MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED       (0x02)
+#define MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED         (0x03)
+#define MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED       (0x04)
+#define MPI_EVENT_RAID_RC_PHYSDISK_CREATED              (0x05)
+#define MPI_EVENT_RAID_RC_PHYSDISK_DELETED              (0x06)
+#define MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED     (0x07)
+#define MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED       (0x08)
+#define MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED             (0x09)
+#define MPI_EVENT_RAID_RC_SMART_DATA                    (0x0A)
+#define MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED        (0x0B)
+
 /* MPI Link Status Change Event data */
 
 typedef struct _EVENT_DATA_LINK_STATUS
@@ -535,35 +620,63 @@
 
 #define MPI_EVENT_LOGOUT_ALL_ALIASES        (0xFF)
 
+/* SAS SES Event data */
 
-/* MPI Integrated RAID Event data */
-
-typedef struct _EVENT_DATA_RAID
+typedef struct _EVENT_DATA_SAS_SES
 {
-    U8                      VolumeID;                   /* 00h */
-    U8                      VolumeBus;                  /* 01h */
-    U8                      ReasonCode;                 /* 02h */
-    U8                      PhysDiskNum;                /* 03h */
-    U8                      ASC;                        /* 04h */
-    U8                      ASCQ;                       /* 05h */
-    U16                     Reserved;                   /* 06h */
-    U32                     SettingsStatus;             /* 08h */
-} EVENT_DATA_RAID, MPI_POINTER PTR_EVENT_DATA_RAID,
-  MpiEventDataRaid_t, MPI_POINTER pMpiEventDataRaid_t;
+    U8                      PhyNum;                     /* 00h */
+    U8                      Port;                       /* 01h */
+    U8                      PortWidth;                  /* 02h */
+    U8                      Reserved1;                  /* 04h */
+} EVENT_DATA_SAS_SES, MPI_POINTER PTR_EVENT_DATA_SAS_SES,
+  MpiEventDataSasSes_t, MPI_POINTER pMpiEventDataSasSes_t;
 
-/* MPI Integrated RAID Event data ReasonCode values */
-#define MPI_EVENT_RAID_RC_VOLUME_CREATED                (0x00)
-#define MPI_EVENT_RAID_RC_VOLUME_DELETED                (0x01)
-#define MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED       (0x02)
-#define MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED         (0x03)
-#define MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED       (0x04)
-#define MPI_EVENT_RAID_RC_PHYSDISK_CREATED              (0x05)
-#define MPI_EVENT_RAID_RC_PHYSDISK_DELETED              (0x06)
-#define MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED     (0x07)
-#define MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED       (0x08)
-#define MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED             (0x09)
-#define MPI_EVENT_RAID_RC_SMART_DATA                    (0x0A)
-#define MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED        (0x0B)
+/* SAS Phy Link Status Event data */
+
+typedef struct _EVENT_DATA_SAS_PHY_LINK_STATUS
+{
+    U8                      PhyNum;                     /* 00h */
+    U8                      LinkRates;                  /* 01h */
+    U16                     DevHandle;                  /* 02h */
+    U64                     SASAddress;                 /* 04h */
+} EVENT_DATA_SAS_PHY_LINK_STATUS, MPI_POINTER PTR_EVENT_DATA_SAS_PHY_LINK_STATUS,
+  MpiEventDataSasPhyLinkStatus_t, MPI_POINTER pMpiEventDataSasPhyLinkStatus_t;
+
+/* defines for the LinkRates field of the SAS PHY Link Status event */
+#define MPI_EVENT_SAS_PLS_LR_CURRENT_MASK                   (0xF0)
+#define MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT                  (4)
+#define MPI_EVENT_SAS_PLS_LR_PREVIOUS_MASK                  (0x0F)
+#define MPI_EVENT_SAS_PLS_LR_PREVIOUS_SHIFT                 (0)
+#define MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN                   (0x00)
+#define MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED              (0x01)
+#define MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION  (0x02)
+#define MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE         (0x03)
+#define MPI_EVENT_SAS_PLS_LR_RATE_1_5                       (0x08)
+#define MPI_EVENT_SAS_PLS_LR_RATE_3_0                       (0x09)
+
+/* SAS Discovery Errror Event data */
+
+typedef struct _EVENT_DATA_DISCOVERY_ERROR
+{
+    U32                     DiscoveryStatus;            /* 00h */
+    U8                      Port;                       /* 04h */
+    U8                      Reserved1;                  /* 05h */
+    U16                     Reserved2;                  /* 06h */
+} EVENT_DATA_DISCOVERY_ERROR, MPI_POINTER PTR_EVENT_DATA_DISCOVERY_ERROR,
+  EventDataDiscoveryError_t, MPI_POINTER pEventDataDiscoveryError_t;
+
+#define MPI_EVENT_DSCVRY_ERR_DS_LOOP_DETECTED               (0x00000001)
+#define MPI_EVENT_DSCVRY_ERR_DS_UNADDRESSABLE_DEVICE        (0x00000002)
+#define MPI_EVENT_DSCVRY_ERR_DS_MULTIPLE_PORTS              (0x00000004)
+#define MPI_EVENT_DSCVRY_ERR_DS_EXPANDER_ERR                (0x00000008)
+#define MPI_EVENT_DSCVRY_ERR_DS_SMP_TIMEOUT                 (0x00000010)
+#define MPI_EVENT_DSCVRY_ERR_DS_OUT_ROUTE_ENTRIES           (0x00000020)
+#define MPI_EVENT_DSCVRY_ERR_DS_INDEX_NOT_EXIST             (0x00000040)
+#define MPI_EVENT_DSCVRY_ERR_DS_SMP_FUNCTION_FAILED         (0x00000080)
+#define MPI_EVENT_DSCVRY_ERR_DS_SMP_CRC_ERROR               (0x00000100)
+#define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_SUBTRACTIVE          (0x00000200)
+#define MPI_EVENT_DSCVRY_ERR_DS_TABLE_TO_TABLE              (0x00000400)
+#define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_PATHS                (0x00000800)
 
 
 /*****************************************************************************
@@ -589,11 +702,13 @@
 } MSG_FW_DOWNLOAD, MPI_POINTER PTR_MSG_FW_DOWNLOAD,
   FWDownload_t, MPI_POINTER pFWDownload_t;
 
-#define MPI_FW_DOWNLOAD_ITYPE_RESERVED      (0x00)
-#define MPI_FW_DOWNLOAD_ITYPE_FW            (0x01)
-#define MPI_FW_DOWNLOAD_ITYPE_BIOS          (0x02)
-#define MPI_FW_DOWNLOAD_ITYPE_NVDATA        (0x03)
-#define MPI_FW_DOWNLOAD_ITYPE_BOOTLOADER    (0x04)
+#define MPI_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT    (0x01)
+
+#define MPI_FW_DOWNLOAD_ITYPE_RESERVED          (0x00)
+#define MPI_FW_DOWNLOAD_ITYPE_FW                (0x01)
+#define MPI_FW_DOWNLOAD_ITYPE_BIOS              (0x02)
+#define MPI_FW_DOWNLOAD_ITYPE_NVDATA            (0x03)
+#define MPI_FW_DOWNLOAD_ITYPE_BOOTLOADER        (0x04)
 
 
 typedef struct _FWDownloadTCSGE
@@ -647,6 +762,7 @@
 #define MPI_FW_UPLOAD_ITYPE_BIOS_FLASH      (0x02)
 #define MPI_FW_UPLOAD_ITYPE_NVDATA          (0x03)
 #define MPI_FW_UPLOAD_ITYPE_BOOTLOADER      (0x04)
+#define MPI_FW_UPLOAD_ITYPE_FW_BACKUP       (0x05)
 
 typedef struct _FWUploadTCSGE
 {
@@ -723,6 +839,7 @@
 #define MPI_FW_HEADER_PID_PROD_IM_SCSI                  (0x0400)
 #define MPI_FW_HEADER_PID_PROD_IS_SCSI                  (0x0500)
 #define MPI_FW_HEADER_PID_PROD_CTX_SCSI                 (0x0600)
+#define MPI_FW_HEADER_PID_PROD_IR_SCSI                  (0x0700)
 
 #define MPI_FW_HEADER_PID_FAMILY_MASK           (0x00FF)
 /* SCSI */
@@ -740,13 +857,16 @@
 #define MPI_FW_HEADER_PID_FAMILY_1020TA0_SCSI   (0x000C)
 /* Fibre Channel */
 #define MPI_FW_HEADER_PID_FAMILY_909_FC         (0x0000)
-#define MPI_FW_HEADER_PID_FAMILY_919_FC         (0x0001)
-#define MPI_FW_HEADER_PID_FAMILY_919X_FC        (0x0002)
-#define MPI_FW_HEADER_PID_FAMILY_919XL_FC       (0x0003)
-#define MPI_FW_HEADER_PID_FAMILY_949_FC         (0x0004)
+#define MPI_FW_HEADER_PID_FAMILY_919_FC         (0x0001) /* 919 and 929     */
+#define MPI_FW_HEADER_PID_FAMILY_919X_FC        (0x0002) /* 919X and 929X   */
+#define MPI_FW_HEADER_PID_FAMILY_919XL_FC       (0x0003) /* 919XL and 929XL */
+#define MPI_FW_HEADER_PID_FAMILY_939X_FC        (0x0004) /* 939X and 949X   */
 #define MPI_FW_HEADER_PID_FAMILY_959_FC         (0x0005)
 /* SAS */
 #define MPI_FW_HEADER_PID_FAMILY_1064_SAS       (0x0001)
+#define MPI_FW_HEADER_PID_FAMILY_1068_SAS       (0x0002)
+#define MPI_FW_HEADER_PID_FAMILY_1078_SAS       (0x0003)
+#define MPI_FW_HEADER_PID_FAMILY_106xE_SAS      (0x0004) /* 1068E, 1066E, and 1064E */
 
 typedef struct _MPI_EXT_IMAGE_HEADER
 {
diff --git a/drivers/message/fusion/lsi/mpi_lan.h b/drivers/message/fusion/lsi/mpi_lan.h
index 3ced127..dc0b52a 100644
--- a/drivers/message/fusion/lsi/mpi_lan.h
+++ b/drivers/message/fusion/lsi/mpi_lan.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2003 LSI Logic Corporation.
+ *  Copyright (c) 2000-2004 LSI Logic Corporation.
  *
  *
  *           Name:  mpi_lan.h
  *          Title:  MPI LAN messages and structures
  *  Creation Date:  June 30, 2000
  *
- *    mpi_lan.h Version:  01.05.xx
+ *    mpi_lan.h Version:  01.05.01
  *
  *  Version History
  *  ---------------
@@ -28,6 +28,8 @@
  *  02-20-01  01.01.02  Started using MPI_POINTER.
  *  03-27-01  01.01.03  Added structure offset comments.
  *  08-08-01  01.02.01  Original release for v1.2 work.
+ *  05-11-04  01.03.01  Original release for MPI v1.3.
+ *  08-19-04  01.05.01  Original release for MPI v1.5.
  *  --------------------------------------------------------------------------
  */
 
diff --git a/drivers/message/fusion/lsi/mpi_raid.h b/drivers/message/fusion/lsi/mpi_raid.h
index 9580a9d..802255d 100644
--- a/drivers/message/fusion/lsi/mpi_raid.h
+++ b/drivers/message/fusion/lsi/mpi_raid.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2001-2003 LSI Logic Corporation.
+ *  Copyright (c) 2001-2005 LSI Logic Corporation.
  *
  *
  *           Name:  mpi_raid.h
  *          Title:  MPI RAID message and structures
  *  Creation Date:  February 27, 2001
  *
- *    mpi_raid.h Version:  01.05.xx
+ *    mpi_raid.h Version:  01.05.02
  *
  *  Version History
  *  ---------------
@@ -28,6 +28,10 @@
  *  11-15-02  01.02.08  Added missing MsgContext field to MSG_MAILBOX_REQUEST.
  *  04-01-03  01.02.09  New action data option flag for
  *                      MPI_RAID_ACTION_DELETE_VOLUME.
+ *  05-11-04  01.03.01  Original release for MPI v1.3.
+ *  08-19-04  01.05.01  Original release for MPI v1.5.
+ *  01-15-05  01.05.02  Added defines for the two new RAID Actions for
+ *                      _SET_RESYNC_RATE and _SET_DATA_SCRUB_RATE.
  *  --------------------------------------------------------------------------
  */
 
@@ -84,6 +88,8 @@
 #define MPI_RAID_ACTION_REPLACE_PHYSDISK            (0x10)
 #define MPI_RAID_ACTION_ACTIVATE_VOLUME             (0x11)
 #define MPI_RAID_ACTION_INACTIVATE_VOLUME           (0x12)
+#define MPI_RAID_ACTION_SET_RESYNC_RATE             (0x13)
+#define MPI_RAID_ACTION_SET_DATA_SCRUB_RATE         (0x14)
 
 /* ActionDataWord defines for use with MPI_RAID_ACTION_CREATE_VOLUME action */
 #define MPI_RAID_ACTION_ADATA_DO_NOT_SYNC           (0x00000001)
@@ -99,6 +105,13 @@
 /* ActionDataWord defines for use with MPI_RAID_ACTION_ACTIVATE_VOLUME action */
 #define MPI_RAID_ACTION_ADATA_INACTIVATE_ALL        (0x00000001)
 
+/* ActionDataWord defines for use with MPI_RAID_ACTION_SET_RESYNC_RATE action */
+#define MPI_RAID_ACTION_ADATA_RESYNC_RATE_MASK      (0x000000FF)
+
+/* ActionDataWord defines for use with MPI_RAID_ACTION_SET_DATA_SCRUB_RATE action */
+#define MPI_RAID_ACTION_ADATA_DATA_SCRUB_RATE_MASK  (0x000000FF)
+
+
 
 /* RAID Action reply message */
 
diff --git a/drivers/message/fusion/lsi/mpi_sas.h b/drivers/message/fusion/lsi/mpi_sas.h
index cb878f9..230fa69 100644
--- a/drivers/message/fusion/lsi/mpi_sas.h
+++ b/drivers/message/fusion/lsi/mpi_sas.h
@@ -1,83 +1,29 @@
 /*
- *  Copyright (c) 2003 LSI Logic Corporation.
+ *  Copyright (c) 2004 LSI Logic Corporation.
  *
  *
  *           Name:  mpi_sas.h
  *          Title:  MPI Serial Attached SCSI structures and definitions
- *  Creation Date:  April 23, 2003
+ *  Creation Date:  August 19, 2004
  *
- *    mpi_sas.h Version:  01.05.xx
+ *    mpi_sas.h Version:  01.05.01
  *
  *  Version History
  *  ---------------
  *
  *  Date      Version   Description
  *  --------  --------  ------------------------------------------------------
- *  xx-yy-zz  01.05.01  Original release.
+ *  08-19-04  01.05.01  Original release.
  *  --------------------------------------------------------------------------
  */
 
 #ifndef MPI_SAS_H
 #define MPI_SAS_H
 
-/*****************************************************************************
-*
-*        S e r i a l    A t t a c h e d    S C S I     M e s s a g e s
-*
-*****************************************************************************/
 
-/****************************************************************************/
-/* Serial Management Protocol Passthrough Request                           */
-/****************************************************************************/
-
-typedef struct _MSG_SMP_PASSTHROUGH_REQUEST
-{
-    U8                      PassthroughFlags;   /* 00h */
-    U8                      PhysicalPort;       /* 01h */
-    U8                      ChainOffset;        /* 02h */
-    U8                      Function;           /* 03h */
-    U16                     RequestDataLength;  /* 04h */
-    U8                      ConnectionRate;     /* 06h */
-    U8                      MsgFlags;           /* 07h */
-    U32                     MsgContext;         /* 08h */
-    U32                     Reserved1;          /* 0Ch */
-    U64                     SASAddress;         /* 10h */
-    U32                     Reserved2;          /* 18h */
-    U32                     Reserved3;          /* 1Ch */
-    SGE_SIMPLE_UNION        SGL;                /* 20h */
-} MSG_SMP_PASSTHROUGH_REQUEST, MPI_POINTER PTR_MSG_SMP_PASSTHROUGH_REQUEST,
-  SmpPassthroughRequest_t, MPI_POINTER pSmpPassthroughRequest_t;
-
-#define MPI_SMP_PT_REQ_PT_FLAGS_IMMEDIATE       (0x80)
-
-#define MPI_SMP_PT_REQ_CONNECT_RATE_NEGOTIATED  (0x00)
-#define MPI_SMP_PT_REQ_CONNECT_RATE_1_5         (0x08)
-#define MPI_SMP_PT_REQ_CONNECT_RATE_3_0         (0x09)
-
-
-/* Serial Management Protocol Passthrough Reply */
-typedef struct _MSG_SMP_PASSTHROUGH_REPLY
-{
-    U8                      PassthroughFlags;   /* 00h */
-    U8                      PhysicalPort;       /* 01h */
-    U8                      MsgLength;          /* 02h */
-    U8                      Function;           /* 03h */
-    U16                     ResponseDataLength; /* 04h */
-    U8                      Reserved1;          /* 06h */
-    U8                      MsgFlags;           /* 07h */
-    U32                     MsgContext;         /* 08h */
-    U8                      Reserved2;          /* 0Ch */
-    U8                      SASStatus;          /* 0Dh */
-    U16                     IOCStatus;          /* 0Eh */
-    U32                     IOCLogInfo;         /* 10h */
-    U32                     Reserved3;          /* 14h */
-    U8                      ResponseData[4];    /* 18h */
-} MSG_SMP_PASSTHROUGH_REPLY, MPI_POINTER PTR_MSG_SMP_PASSTHROUGH_REPLY,
-  SmpPassthroughReply_t, MPI_POINTER pSmpPassthroughReply_t;
-
-#define MPI_SMP_PT_REPLY_PT_FLAGS_IMMEDIATE     (0x80)
-
-/* values for the SASStatus field */
+/*
+ * Values for SASStatus.
+ */
 #define MPI_SASSTATUS_SUCCESS                           (0x00)
 #define MPI_SASSTATUS_UNKNOWN_ERROR                     (0x01)
 #define MPI_SASSTATUS_INVALID_FRAME                     (0x02)
@@ -124,6 +70,131 @@
 #define MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER     (0x00000003)
 
 
+
+/*****************************************************************************
+*
+*        S e r i a l    A t t a c h e d    S C S I     M e s s a g e s
+*
+*****************************************************************************/
+
+/****************************************************************************/
+/* Serial Management Protocol Passthrough Request                           */
+/****************************************************************************/
+
+typedef struct _MSG_SMP_PASSTHROUGH_REQUEST
+{
+    U8                      PassthroughFlags;   /* 00h */
+    U8                      PhysicalPort;       /* 01h */
+    U8                      ChainOffset;        /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     RequestDataLength;  /* 04h */
+    U8                      ConnectionRate;     /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U32                     Reserved1;          /* 0Ch */
+    U64                     SASAddress;         /* 10h */
+    U32                     Reserved2;          /* 18h */
+    U32                     Reserved3;          /* 1Ch */
+    SGE_SIMPLE_UNION        SGL;                /* 20h */
+} MSG_SMP_PASSTHROUGH_REQUEST, MPI_POINTER PTR_MSG_SMP_PASSTHROUGH_REQUEST,
+  SmpPassthroughRequest_t, MPI_POINTER pSmpPassthroughRequest_t;
+
+/* values for PassthroughFlags field */
+#define MPI_SMP_PT_REQ_PT_FLAGS_IMMEDIATE       (0x80)
+
+/* values for ConnectionRate field */
+#define MPI_SMP_PT_REQ_CONNECT_RATE_NEGOTIATED  (0x00)
+#define MPI_SMP_PT_REQ_CONNECT_RATE_1_5         (0x08)
+#define MPI_SMP_PT_REQ_CONNECT_RATE_3_0         (0x09)
+
+
+/* Serial Management Protocol Passthrough Reply */
+typedef struct _MSG_SMP_PASSTHROUGH_REPLY
+{
+    U8                      PassthroughFlags;   /* 00h */
+    U8                      PhysicalPort;       /* 01h */
+    U8                      MsgLength;          /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     ResponseDataLength; /* 04h */
+    U8                      Reserved1;          /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U8                      Reserved2;          /* 0Ch */
+    U8                      SASStatus;          /* 0Dh */
+    U16                     IOCStatus;          /* 0Eh */
+    U32                     IOCLogInfo;         /* 10h */
+    U32                     Reserved3;          /* 14h */
+    U8                      ResponseData[4];    /* 18h */
+} MSG_SMP_PASSTHROUGH_REPLY, MPI_POINTER PTR_MSG_SMP_PASSTHROUGH_REPLY,
+  SmpPassthroughReply_t, MPI_POINTER pSmpPassthroughReply_t;
+
+#define MPI_SMP_PT_REPLY_PT_FLAGS_IMMEDIATE     (0x80)
+
+
+/****************************************************************************/
+/* SATA Passthrough Request                                                 */
+/****************************************************************************/
+
+typedef struct _MSG_SATA_PASSTHROUGH_REQUEST
+{
+    U8                      TargetID;           /* 00h */
+    U8                      Bus;                /* 01h */
+    U8                      ChainOffset;        /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     PassthroughFlags;   /* 04h */
+    U8                      ConnectionRate;     /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U32                     Reserved1;          /* 0Ch */
+    U32                     Reserved2;          /* 10h */
+    U32                     Reserved3;          /* 14h */
+    U32                     DataLength;         /* 18h */
+    U8                      CommandFIS[20];     /* 1Ch */
+    SGE_SIMPLE_UNION        SGL;                /* 30h */
+} MSG_SATA_PASSTHROUGH_REQUEST, MPI_POINTER PTR_MSG_SATA_PASSTHROUGH_REQUEST,
+  SataPassthroughRequest_t, MPI_POINTER pSataPassthroughRequest_t;
+
+/* values for PassthroughFlags field */
+#define MPI_SATA_PT_REQ_PT_FLAGS_RESET_DEVICE   (0x0200)
+#define MPI_SATA_PT_REQ_PT_FLAGS_EXECUTE_DIAG   (0x0100)
+#define MPI_SATA_PT_REQ_PT_FLAGS_DMA_QUEUED     (0x0080)
+#define MPI_SATA_PT_REQ_PT_FLAGS_PACKET_COMMAND (0x0040)
+#define MPI_SATA_PT_REQ_PT_FLAGS_DMA            (0x0020)
+#define MPI_SATA_PT_REQ_PT_FLAGS_PIO            (0x0010)
+#define MPI_SATA_PT_REQ_PT_FLAGS_UNSPECIFIED_VU (0x0004)
+#define MPI_SATA_PT_REQ_PT_FLAGS_WRITE          (0x0002)
+#define MPI_SATA_PT_REQ_PT_FLAGS_READ           (0x0001)
+
+/* values for ConnectionRate field */
+#define MPI_SATA_PT_REQ_CONNECT_RATE_NEGOTIATED (0x00)
+#define MPI_SATA_PT_REQ_CONNECT_RATE_1_5        (0x08)
+#define MPI_SATA_PT_REQ_CONNECT_RATE_3_0        (0x09)
+
+
+/* SATA Passthrough Reply */
+typedef struct _MSG_SATA_PASSTHROUGH_REPLY
+{
+    U8                      TargetID;           /* 00h */
+    U8                      Bus;                /* 01h */
+    U8                      MsgLength;          /* 02h */
+    U8                      Function;           /* 03h */
+    U16                     PassthroughFlags;   /* 04h */
+    U8                      Reserved1;          /* 06h */
+    U8                      MsgFlags;           /* 07h */
+    U32                     MsgContext;         /* 08h */
+    U8                      Reserved2;          /* 0Ch */
+    U8                      SASStatus;          /* 0Dh */
+    U16                     IOCStatus;          /* 0Eh */
+    U32                     IOCLogInfo;         /* 10h */
+    U8                      StatusFIS[20];      /* 14h */
+    U32                     StatusControlRegisters; /* 28h */
+    U32                     TransferCount;      /* 2Ch */
+} MSG_SATA_PASSTHROUGH_REPLY, MPI_POINTER PTR_MSG_SATA_PASSTHROUGH_REPLY,
+  SataPassthroughReply_t, MPI_POINTER pSataPassthroughReply_t;
+
+
+
+
 /****************************************************************************/
 /* SAS IO Unit Control Request                                              */
 /****************************************************************************/
@@ -148,15 +219,13 @@
 } MSG_SAS_IOUNIT_CONTROL_REQUEST, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REQUEST,
   SasIoUnitControlRequest_t, MPI_POINTER pSasIoUnitControlRequest_t;
 
-/* values for the ... field */
+/* values for the Operation field */
 #define MPI_SAS_OP_CLEAR_NOT_PRESENT             (0x01)
-#define MPI_SAS_OP_CLEAR_ALL                     (0x02)
-#define MPI_SAS_OP_MAP                           (0x03)
-#define MPI_SAS_OP_MOVE                          (0x04)
-#define MPI_SAS_OP_CLEAR                         (0x05)
+#define MPI_SAS_OP_CLEAR_ALL_PERSISTENT          (0x02)
 #define MPI_SAS_OP_PHY_LINK_RESET                (0x06)
 #define MPI_SAS_OP_PHY_HARD_RESET                (0x07)
 #define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG           (0x08)
+#define MPI_SAS_OP_MAP_CURRENT                   (0x09)
 
 
 /* SAS IO Unit Control Reply */
diff --git a/drivers/message/fusion/lsi/mpi_targ.h b/drivers/message/fusion/lsi/mpi_targ.h
index 804dc85..623901f 100644
--- a/drivers/message/fusion/lsi/mpi_targ.h
+++ b/drivers/message/fusion/lsi/mpi_targ.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2003 LSI Logic Corporation.
+ *  Copyright (c) 2000-2004 LSI Logic Corporation.
  *
  *
  *           Name:  mpi_targ.h
  *          Title:  MPI Target mode messages and structures
  *  Creation Date:  June 22, 2000
  *
- *    mpi_targ.h Version:  01.05.xx
+ *    mpi_targ.h Version:  01.05.04
  *
  *  Version History
  *  ---------------
@@ -43,6 +43,16 @@
  *                      Added PRIORITY_REASON_TARGET_BUSY.
  *  11-15-02  01.02.08  Added AliasID field to MPI_TARGET_SCSI_SPI_CMD_BUFFER.
  *  04-01-03  01.02.09  Added OptionalOxid field to MPI_TARGET_FCP_CMD_BUFFER.
+ *  05-11-04  01.03.01  Original release for MPI v1.3.
+ *  08-19-04  01.05.01  Added new request message structures for
+ *                      MSG_TARGET_CMD_BUF_POST_BASE_REQUEST,
+ *                      MSG_TARGET_CMD_BUF_POST_LIST_REQUEST, and
+ *                      MSG_TARGET_ASSIST_EXT_REQUEST.
+ *                      Added new structures for SAS SSP Command buffer, SSP
+ *                      Task buffer, and SSP Status IU.
+ *  10-05-04  01.05.02  MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY added.
+ *  02-22-05  01.05.03  Changed a comment.
+ *  03-11-05  01.05.04  Removed TargetAssistExtended Request.
  *  --------------------------------------------------------------------------
  */
 
@@ -133,18 +143,6 @@
 } MSG_PRIORITY_CMD_RECEIVED_REPLY, MPI_POINTER PTR_MSG_PRIORITY_CMD_RECEIVED_REPLY,
   PriorityCommandReceivedReply_t, MPI_POINTER pPriorityCommandReceivedReply_t;
 
-#define PRIORITY_REASON_NO_DISCONNECT           (0x00)
-#define PRIORITY_REASON_SCSI_TASK_MANAGEMENT    (0x01)
-#define PRIORITY_REASON_CMD_PARITY_ERR          (0x02)
-#define PRIORITY_REASON_MSG_OUT_PARITY_ERR      (0x03)
-#define PRIORITY_REASON_LQ_CRC_ERR              (0x04)
-#define PRIORITY_REASON_CMD_CRC_ERR             (0x05)
-#define PRIORITY_REASON_PROTOCOL_ERR            (0x06)
-#define PRIORITY_REASON_DATA_OUT_PARITY_ERR     (0x07)
-#define PRIORITY_REASON_DATA_OUT_CRC_ERR        (0x08)
-#define PRIORITY_REASON_TARGET_BUSY             (0x09)
-#define PRIORITY_REASON_UNKNOWN                 (0xFF)
-
 
 typedef struct _MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY
 {
@@ -164,6 +162,89 @@
   MPI_POINTER PTR_MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY,
   TargetCmdBufferPostErrorReply_t, MPI_POINTER pTargetCmdBufferPostErrorReply_t;
 
+#define PRIORITY_REASON_NO_DISCONNECT           (0x00)
+#define PRIORITY_REASON_SCSI_TASK_MANAGEMENT    (0x01)
+#define PRIORITY_REASON_CMD_PARITY_ERR          (0x02)
+#define PRIORITY_REASON_MSG_OUT_PARITY_ERR      (0x03)
+#define PRIORITY_REASON_LQ_CRC_ERR              (0x04)
+#define PRIORITY_REASON_CMD_CRC_ERR             (0x05)
+#define PRIORITY_REASON_PROTOCOL_ERR            (0x06)
+#define PRIORITY_REASON_DATA_OUT_PARITY_ERR     (0x07)
+#define PRIORITY_REASON_DATA_OUT_CRC_ERR        (0x08)
+#define PRIORITY_REASON_TARGET_BUSY             (0x09)
+#define PRIORITY_REASON_UNKNOWN                 (0xFF)
+
+
+/****************************************************************************/
+/* Target Command Buffer Post Base Request                                  */
+/****************************************************************************/
+
+typedef struct _MSG_TARGET_CMD_BUF_POST_BASE_REQUEST
+{
+    U8                      BufferPostFlags;            /* 00h */
+    U8                      PortNumber;                 /* 01h */
+    U8                      ChainOffset;                /* 02h */
+    U8                      Function;                   /* 03h */
+    U16                     TotalCmdBuffers;            /* 04h */
+    U8                      Reserved;                   /* 06h */
+    U8                      MsgFlags;                   /* 07h */
+    U32                     MsgContext;                 /* 08h */
+    U32                     Reserved1;                  /* 0Ch */
+    U16                     CmdBufferLength;            /* 10h */
+    U16                     NextCmdBufferOffset;        /* 12h */
+    U32                     BaseAddressLow;             /* 14h */
+    U32                     BaseAddressHigh;            /* 18h */
+} MSG_TARGET_CMD_BUF_POST_BASE_REQUEST,
+  MPI_POINTER PTR__MSG_TARGET_CMD_BUF_POST_BASE_REQUEST,
+  TargetCmdBufferPostBaseRequest_t,
+  MPI_POINTER pTargetCmdBufferPostBaseRequest_t;
+
+#define CMD_BUFFER_POST_BASE_FLAGS_AUTO_POST_ALL    (0x01)
+
+
+typedef struct _MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY
+{
+    U16                     Reserved;                   /* 00h */
+    U8                      MsgLength;                  /* 02h */
+    U8                      Function;                   /* 03h */
+    U16                     Reserved1;                  /* 04h */
+    U8                      Reserved2;                  /* 06h */
+    U8                      MsgFlags;                   /* 07h */
+    U32                     MsgContext;                 /* 08h */
+    U16                     Reserved3;                  /* 0Ch */
+    U16                     IOCStatus;                  /* 0Eh */
+    U32                     IOCLogInfo;                 /* 10h */
+} MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY,
+  MPI_POINTER PTR_MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY,
+  TargetCmdBufferPostBaseListReply_t,
+  MPI_POINTER pTargetCmdBufferPostBaseListReply_t;
+
+
+/****************************************************************************/
+/* Target Command Buffer Post List Request                                  */
+/****************************************************************************/
+
+typedef struct _MSG_TARGET_CMD_BUF_POST_LIST_REQUEST
+{
+    U8                      Reserved;                   /* 00h */
+    U8                      PortNumber;                 /* 01h */
+    U8                      ChainOffset;                /* 02h */
+    U8                      Function;                   /* 03h */
+    U16                     CmdBufferCount;             /* 04h */
+    U8                      Reserved1;                  /* 06h */
+    U8                      MsgFlags;                   /* 07h */
+    U32                     MsgContext;                 /* 08h */
+    U32                     Reserved2;                  /* 0Ch */
+    U16                     IoIndex[2];                 /* 10h */
+} MSG_TARGET_CMD_BUF_POST_LIST_REQUEST,
+  MPI_POINTER PTR_MSG_TARGET_CMD_BUF_POST_LIST_REQUEST,
+  TargetCmdBufferPostListRequest_t,
+  MPI_POINTER pTargetCmdBufferPostListRequest_t;
+
+
+/****************************************************************************/
+/* Command Buffer Formats (with 16 byte CDB)                                */
+/****************************************************************************/
 
 typedef struct _MPI_TARGET_FCP_CMD_BUFFER
 {
@@ -201,6 +282,46 @@
   MpiTargetScsiSpiCmdBuffer, MPI_POINTER pMpiTargetScsiSpiCmdBuffer;
 
 
+typedef struct _MPI_TARGET_SSP_CMD_BUFFER
+{
+    U8      FrameType;                                  /* 00h */
+    U8      Reserved1;                                  /* 01h */
+    U16     Reserved2;                                  /* 02h */
+    U16     InitiatorTag;                               /* 04h */
+    U16     DevHandle;                                  /* 06h */
+    /* COMMAND information unit starts here */
+    U8      LogicalUnitNumber[8];                       /* 08h */
+    U8      Reserved3;                                  /* 10h */
+    U8      TaskAttribute; /* lower 3 bits */           /* 11h */
+    U8      Reserved4;                                  /* 12h */
+    U8      AdditionalCDBLength; /* upper 5 bits */     /* 13h */
+    U8      CDB[16];                                    /* 14h */
+    /* Additional CDB bytes extend past the CDB field */
+} MPI_TARGET_SSP_CMD_BUFFER, MPI_POINTER PTR_MPI_TARGET_SSP_CMD_BUFFER,
+  MpiTargetSspCmdBuffer, MPI_POINTER pMpiTargetSspCmdBuffer;
+
+typedef struct _MPI_TARGET_SSP_TASK_BUFFER
+{
+    U8      FrameType;                                  /* 00h */
+    U8      Reserved1;                                  /* 01h */
+    U16     Reserved2;                                  /* 02h */
+    U16     InitiatorTag;                               /* 04h */
+    U16     DevHandle;                                  /* 06h */
+    /* TASK information unit starts here */
+    U8      LogicalUnitNumber[8];                       /* 08h */
+    U8      Reserved3;                                  /* 10h */
+    U8      Reserved4;                                  /* 11h */
+    U8      TaskManagementFunction;                     /* 12h */
+    U8      Reserved5;                                  /* 13h */
+    U16     ManagedTaskTag;                             /* 14h */
+    U16     Reserved6;                                  /* 16h */
+    U32     Reserved7;                                  /* 18h */
+    U32     Reserved8;                                  /* 1Ch */
+    U32     Reserved9;                                  /* 20h */
+} MPI_TARGET_SSP_TASK_BUFFER, MPI_POINTER PTR_MPI_TARGET_SSP_TASK_BUFFER,
+  MpiTargetSspTaskBuffer, MPI_POINTER pMpiTargetSspTaskBuffer;
+
+
 /****************************************************************************/
 /* Target Assist Request                                                    */
 /****************************************************************************/
@@ -308,6 +429,27 @@
 } MPI_TARGET_SCSI_SPI_STATUS_IU, MPI_POINTER PTR_MPI_TARGET_SCSI_SPI_STATUS_IU,
   TargetScsiSpiStatusIU_t, MPI_POINTER pTargetScsiSpiStatusIU_t;
 
+/*
+ * NOTE: The SSP status IU is big-endian. When used on a little-endian system,
+ * this structure properly orders the bytes.
+ */
+typedef struct _MPI_TARGET_SSP_RSP_IU
+{
+    U32     Reserved0[6]; /* reserved for SSP header */ /* 00h */
+    /* start of RESPONSE information unit */
+    U32     Reserved1;                                  /* 18h */
+    U32     Reserved2;                                  /* 1Ch */
+    U16     Reserved3;                                  /* 20h */
+    U8      DataPres; /* lower 2 bits */                /* 22h */
+    U8      Status;                                     /* 23h */
+    U32     Reserved4;                                  /* 24h */
+    U32     SenseDataLength;                            /* 28h */
+    U32     ResponseDataLength;                         /* 2Ch */
+    U8      ResponseSenseData[4];                       /* 30h */
+} MPI_TARGET_SSP_RSP_IU, MPI_POINTER PTR_MPI_TARGET_SSP_RSP_IU,
+  MpiTargetSspRspIu_t, MPI_POINTER pMpiTargetSspRspIu_t;
+
+
 /****************************************************************************/
 /* Target Mode Abort Request                                                */
 /****************************************************************************/
diff --git a/drivers/message/fusion/lsi/mpi_tool.h b/drivers/message/fusion/lsi/mpi_tool.h
index 536d197..aa9053d 100644
--- a/drivers/message/fusion/lsi/mpi_tool.h
+++ b/drivers/message/fusion/lsi/mpi_tool.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2001-2003 LSI Logic Corporation.
+ *  Copyright (c) 2001-2005 LSI Logic Corporation.
  *
  *
  *           Name:  mpi_tool.h
  *          Title:  MPI Toolbox structures and definitions
  *  Creation Date:  July 30, 2001
  *
- *    mpi_tool.h Version:  01.05.xx
+ *    mpi_tool.h Version:  01.05.03
  *
  *  Version History
  *  ---------------
@@ -15,6 +15,16 @@
  *  --------  --------  ------------------------------------------------------
  *  08-08-01  01.02.01  Original release.
  *  08-29-01  01.02.02  Added DIAG_DATA_UPLOAD_HEADER and related defines.
+ *  01-16-04  01.02.03  Added defines and structures for new tools
+ *.                     MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL and
+ *                      MPI_TOOLBOX_FC_MANAGEMENT_TOOL.
+ *  04-29-04  01.02.04  Added message structures for Diagnostic Buffer Post and
+ *                      Diagnostic Release requests and replies.
+ *  05-11-04  01.03.01  Original release for MPI v1.3.
+ *  08-19-04  01.05.01  Original release for MPI v1.5.
+ *  10-06-04  01.05.02  Added define for MPI_DIAG_BUF_TYPE_COUNT.
+ *  02-09-05  01.05.03  Added frame size option to FC management tool.
+ *                      Added Beacon tool to the Toolbox.
  *  --------------------------------------------------------------------------
  */
 
@@ -26,6 +36,7 @@
 #define MPI_TOOLBOX_DIAG_DATA_UPLOAD_TOOL           (0x02)
 #define MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL           (0x03)
 #define MPI_TOOLBOX_FC_MANAGEMENT_TOOL              (0x04)
+#define MPI_TOOLBOX_BEACON_TOOL                     (0x05)
 
 
 /****************************************************************************/
@@ -185,11 +196,21 @@
 } MPI_TB_FC_MANAGE_PID_AI, MPI_POINTER PTR_MPI_TB_FC_MANAGE_PID_AI,
   MpiTbFcManagePidAi_t, MPI_POINTER pMpiTbFcManagePidAi_t;
 
+/* ActionInfo for set max frame size */
+typedef struct _MPI_TB_FC_MANAGE_FRAME_SIZE_AI
+{
+    U16                     FrameSize;                  /* 00h */
+    U8                      PortNum;                    /* 02h */
+    U8                      Reserved1;                  /* 03h */
+} MPI_TB_FC_MANAGE_FRAME_SIZE_AI, MPI_POINTER PTR_MPI_TB_FC_MANAGE_FRAME_SIZE_AI,
+  MpiTbFcManageFrameSizeAi_t, MPI_POINTER pMpiTbFcManageFrameSizeAi_t;
+
 /* union of ActionInfo */
 typedef union _MPI_TB_FC_MANAGE_AI_UNION
 {
     MPI_TB_FC_MANAGE_BUS_TID_AI     BusTid;
     MPI_TB_FC_MANAGE_PID_AI         Port;
+    MPI_TB_FC_MANAGE_FRAME_SIZE_AI  FrameSize;
 } MPI_TB_FC_MANAGE_AI_UNION, MPI_POINTER PTR_MPI_TB_FC_MANAGE_AI_UNION,
   MpiTbFcManageAiUnion_t, MPI_POINTER pMpiTbFcManageAiUnion_t;
 
@@ -214,6 +235,32 @@
 #define MPI_TB_FC_MANAGE_ACTION_DISC_ALL            (0x00)
 #define MPI_TB_FC_MANAGE_ACTION_DISC_PID            (0x01)
 #define MPI_TB_FC_MANAGE_ACTION_DISC_BUS_TID        (0x02)
+#define MPI_TB_FC_MANAGE_ACTION_SET_MAX_FRAME_SIZE  (0x03)
+
+
+/****************************************************************************/
+/* Toolbox Beacon Tool request                                               */
+/****************************************************************************/
+
+typedef struct _MSG_TOOLBOX_BEACON_REQUEST
+{
+    U8                      Tool;                       /* 00h */
+    U8                      Reserved;                   /* 01h */
+    U8                      ChainOffset;                /* 02h */
+    U8                      Function;                   /* 03h */
+    U16                     Reserved1;                  /* 04h */
+    U8                      Reserved2;                  /* 06h */
+    U8                      MsgFlags;                   /* 07h */
+    U32                     MsgContext;                 /* 08h */
+    U8                      ConnectNum;                 /* 0Ch */
+    U8                      PortNum;                    /* 0Dh */
+    U8                      Reserved3;                  /* 0Eh */
+    U8                      Flags;                      /* 0Fh */
+} MSG_TOOLBOX_BEACON_REQUEST, MPI_POINTER PTR_MSG_TOOLBOX_BEACON_REQUEST,
+  ToolboxBeaconRequest_t, MPI_POINTER pToolboxBeaconRequest_t;
+
+#define MPI_TOOLBOX_FLAGS_BEACON_MODE_OFF       (0x00)
+#define MPI_TOOLBOX_FLAGS_BEACON_MODE_ON        (0x01)
 
 
 /****************************************************************************/
@@ -233,14 +280,16 @@
     U32                     ExtendedType;               /* 0Ch */
     U32                     BufferLength;               /* 10h */
     U32                     ProductSpecific[4];         /* 14h */
-    U32                     Reserved3;                  /* 18h */
-    SGE_SIMPLE_UNION        SGL;                        /* 28h */
+    U32                     Reserved3;                  /* 24h */
+    U64                     BufferAddress;              /* 28h */
 } MSG_DIAG_BUFFER_POST_REQUEST, MPI_POINTER PTR_MSG_DIAG_BUFFER_POST_REQUEST,
   DiagBufferPostRequest_t, MPI_POINTER pDiagBufferPostRequest_t;
 
 #define MPI_DIAG_BUF_TYPE_TRACE                     (0x00)
 #define MPI_DIAG_BUF_TYPE_SNAPSHOT                  (0x01)
 #define MPI_DIAG_BUF_TYPE_EXTENDED                  (0x02)
+/* count of the number of buffer types */
+#define MPI_DIAG_BUF_TYPE_COUNT                     (0x03)
 
 #define MPI_DIAG_EXTENDED_QTAG                      (0x00000001)
 
diff --git a/drivers/message/fusion/lsi/mpi_type.h b/drivers/message/fusion/lsi/mpi_type.h
index 239328a..32cc9b1 100644
--- a/drivers/message/fusion/lsi/mpi_type.h
+++ b/drivers/message/fusion/lsi/mpi_type.h
@@ -1,12 +1,12 @@
 /*
- *  Copyright (c) 2000-2003 LSI Logic Corporation.
+ *  Copyright (c) 2000-2004 LSI Logic Corporation.
  *
  *
  *           Name:  mpi_type.h
  *          Title:  MPI Basic type definitions
  *  Creation Date:  June 6, 2000
  *
- *    mpi_type.h Version:  01.05.xx
+ *    mpi_type.h Version:  01.05.01
  *
  *  Version History
  *  ---------------
@@ -18,6 +18,8 @@
  *  11-02-00  01.01.01  Original release for post 1.0 work
  *  02-20-01  01.01.02  Added define and ifdef for MPI_POINTER.
  *  08-08-01  01.02.01  Original release for v1.2 work.
+ *  05-11-04  01.03.01  Original release for MPI v1.3.
+ *  08-19-04  01.05.01  Original release for MPI v1.5.
  *  --------------------------------------------------------------------------
  */
 
@@ -50,11 +52,6 @@
 typedef int32_t   S32;
 typedef u_int32_t U32;
 
-/*
- *  The only way crap below could work on big-endian boxen would be if it
- *  wasn't used at all.
- */
-
 typedef struct _S64
 {
     U32          Low;
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index 8b22630..8b62327 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -1,55 +1,13 @@
 /*
  *  linux/drivers/message/fusion/mptbase.c
- *      High performance SCSI + LAN / Fibre Channel device drivers.
  *      This is the Fusion MPT base driver which supports multiple
  *      (SCSI + LAN) specialized protocol drivers.
- *      For use with PCI chip/adapter(s):
- *          LSIFC9xx/LSI409xx Fibre Channel
+ *      For use with LSI Logic PCI chip/adapter(s)
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
- *  Credits:
- *      There are lots of people not mentioned below that deserve credit
- *      and thanks but won't get it here - sorry in advance that you
- *      got overlooked.
- *
- *      This driver would not exist if not for Alan Cox's development
- *      of the linux i2o driver.
- *
- *      A special thanks to Noah Romer (LSI Logic) for tons of work
- *      and tough debugging on the LAN driver, especially early on;-)
- *      And to Roger Hickerson (LSI Logic) for tirelessly supporting
- *      this driver project.
- *
- *      A special thanks to Pamela Delaney (LSI Logic) for tons of work
- *      and countless enhancements while adding support for the 1030
- *      chip family.  Pam has been instrumental in the development of
- *      of the 2.xx.xx series fusion drivers, and her contributions are
- *      far too numerous to hope to list in one place.
- *
- *      All manner of help from Stephen Shirron (LSI Logic):
- *      low-level FC analysis, debug + various fixes in FCxx firmware,
- *      initial port to alpha platform, various driver code optimizations,
- *      being a faithful sounding board on all sorts of issues & ideas,
- *      etc.
- *
- *      A huge debt of gratitude is owed to David S. Miller (DaveM)
- *      for fixing much of the stupid and broken stuff in the early
- *      driver while porting to sparc64 platform.  THANK YOU!
- *
- *      Special thanks goes to the I2O LAN driver people at the
- *      University of Helsinki, who, unbeknownst to them, provided
- *      the inspiration and initial structure for this driver.
- *
- *      A really huge debt of gratitude is owed to Eddie C. Dost
- *      for gobs of hard work fixing and optimizing LAN code.
- *      THANK YOU!
- *
- *  Copyright (c) 1999-2004 LSI Logic Corporation
- *  Originally By: Steven J. Ralston
- *  (mailto:sjralston1@netscape.net)
+ *  Copyright (c) 1999-2005 LSI Logic Corporation
  *  (mailto:mpt_linux_developer@lsil.com)
  *
- *  $Id: mptbase.c,v 1.126 2002/12/16 15:28:45 pdelaney Exp $
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -101,6 +59,7 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>		/* needed for in_interrupt() proto */
+#include <linux/dma-mapping.h>
 #include <asm/io.h>
 #ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
@@ -218,41 +177,35 @@
 static void	mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info);
 
 /* module entry point */
-static int  __devinit mptbase_probe (struct pci_dev *, const struct pci_device_id *);
-static void __devexit mptbase_remove(struct pci_dev *);
-static void mptbase_shutdown(struct device * );
 static int  __init    fusion_init  (void);
 static void __exit    fusion_exit  (void);
 
-/****************************************************************************
- * Supported hardware
- */
-
-static struct pci_device_id mptbase_pci_table[] = {
-	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909,
-		PCI_ANY_ID, PCI_ANY_ID },
-	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929,
-		PCI_ANY_ID, PCI_ANY_ID },
-	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919,
-		PCI_ANY_ID, PCI_ANY_ID },
-	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X,
-		PCI_ANY_ID, PCI_ANY_ID },
-	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X,
-		PCI_ANY_ID, PCI_ANY_ID },
-	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1030,
-		PCI_ANY_ID, PCI_ANY_ID },
-	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_1030_53C1035,
-		PCI_ANY_ID, PCI_ANY_ID },
-	{0}	/* Terminating entry */
-};
-MODULE_DEVICE_TABLE(pci, mptbase_pci_table);
-
 #define CHIPREG_READ32(addr) 		readl_relaxed(addr)
 #define CHIPREG_READ32_dmasync(addr)	readl(addr)
 #define CHIPREG_WRITE32(addr,val) 	writel(val, addr)
 #define CHIPREG_PIO_WRITE32(addr,val)	outl(val, (unsigned long)addr)
 #define CHIPREG_PIO_READ32(addr) 	inl((unsigned long)addr)
 
+static void
+pci_disable_io_access(struct pci_dev *pdev)
+{
+	u16 command_reg;
+
+	pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
+	command_reg &= ~1;
+	pci_write_config_word(pdev, PCI_COMMAND, command_reg);
+}
+
+static void
+pci_enable_io_access(struct pci_dev *pdev)
+{
+	u16 command_reg;
+
+	pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
+	command_reg |= 1;
+	pci_write_config_word(pdev, PCI_COMMAND, command_reg);
+}
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *	mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
@@ -330,8 +283,7 @@
 					ioc->name, mr, req_idx));
 			DBG_DUMP_REPLY_FRAME(mr)
 
-			/* NEW!  20010301 -sralston
-			 *  Check/log IOC log info
+			/*  Check/log IOC log info
 			 */
 			ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
 			if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
@@ -357,9 +309,7 @@
 				mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
 			} else if (type == MPI_CONTEXT_REPLY_TYPE_LAN) {
 				cb_idx = mpt_lan_index;
-				/*
-				 * BUG FIX!  20001218 -sralston
-				 *  Blind set of mf to NULL here was fatal
+				 /*  Blind set of mf to NULL here was fatal
 				 *  after lan_reply says "freeme"
 				 *  Fix sort of combined with an optimization here;
 				 *  added explicit check for case where lan_reply
@@ -430,15 +380,8 @@
 		}
 
 		if (freeme) {
-			unsigned long flags;
-
 			/*  Put Request back on FreeQ!  */
-			spin_lock_irqsave(&ioc->FreeQlock, flags);
-			list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
-#ifdef MFCNT
-			ioc->mfcnt--;
-#endif
-			spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+			mpt_free_msg_frame(ioc, mf);
 		}
 
 		mb();
@@ -725,11 +668,9 @@
 mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
 {
 	MPT_ADAPTER	*ioc;
-	int 		error=0;
 
 	if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) {
-		error= -EINVAL;
-		return error;
+		return -EINVAL;
 	}
 
 	MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
@@ -737,14 +678,12 @@
 	/* call per pci device probe entry point */
 	list_for_each_entry(ioc, &ioc_list, list) {
 		if(dd_cbfunc->probe) {
-			error = dd_cbfunc->probe(ioc->pcidev,
+			dd_cbfunc->probe(ioc->pcidev,
 			  ioc->pcidev->driver->id_table);
-			if(error != 0)
-				return error;
   		}
 	 }
 
-	return error;
+	return 0;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -809,8 +748,8 @@
 		mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;	/* byte */
 		req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
 								/* u16! */
-		req_idx = cpu_to_le16(req_offset / ioc->req_sz);
-		mf->u.frame.hwhdr.msgctxu.fld.req_idx = req_idx;
+		req_idx = req_offset / ioc->req_sz;
+		mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
 		mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
 		ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */
 #ifdef MFCNT
@@ -856,8 +795,8 @@
 	mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle;		/* byte */
 	req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
 								/* u16! */
-	req_idx = cpu_to_le16(req_offset / ioc->req_sz);
-	mf->u.frame.hwhdr.msgctxu.fld.req_idx = req_idx;
+	req_idx = req_offset / ioc->req_sz;
+	mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
 	mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
 
 #ifdef MPT_DEBUG_MSG_FRAME
@@ -1058,7 +997,7 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *	mptbase_probe - Install a PCI intelligent MPT adapter.
+ *	mpt_attach - Install a PCI intelligent MPT adapter.
  *	@pdev: Pointer to pci_dev structure
  *
  *	This routine performs all the steps necessary to bring the IOC of
@@ -1073,8 +1012,8 @@
  *
  *	TODO: Add support for polled controllers
  */
-static int __devinit
-mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+int
+mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	MPT_ADAPTER	*ioc;
 	u8		__iomem *mem;
@@ -1084,7 +1023,6 @@
 	u32		 psize;
 	int		 ii;
 	int		 r = -ENODEV;
-	u64		 mask = 0xffffffffffffffffULL;
 	u8		 revision;
 	u8		 pcixcmd;
 	static int	 mpt_ids = 0;
@@ -1097,15 +1035,15 @@
 	
 	dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n"));
 	
-	if (!pci_set_dma_mask(pdev, mask)) {
+	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
 		dprintk((KERN_INFO MYNAM
 			": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
-	} else if (pci_set_dma_mask(pdev, (u64) 0xffffffff)) {
+	} else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
 		printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");
 		return r;
 	}
 
-	if (!pci_set_consistent_dma_mask(pdev, mask))
+	if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
 		dprintk((KERN_INFO MYNAM
 			": Using 64 bit consistent mask\n"));
 	else
@@ -1243,6 +1181,16 @@
 		pcixcmd &= 0x8F;
 		pci_write_config_byte(pdev, 0x6a, pcixcmd);
 	}
+	else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC939X) {
+		ioc->prod_name = "LSIFC939X";
+		ioc->bus_type = FC;
+		ioc->errata_flag_1064 = 1;
+	}
+	else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949X) {
+		ioc->prod_name = "LSIFC949X";
+		ioc->bus_type = FC;
+		ioc->errata_flag_1064 = 1;
+	}
 	else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
 		ioc->prod_name = "LSI53C1030";
 		ioc->bus_type = SCSI;
@@ -1261,6 +1209,9 @@
 		ioc->bus_type = SCSI;
 	}
 
+	if (ioc->errata_flag_1064)
+		pci_disable_io_access(pdev);
+
 	sprintf(ioc->name, "ioc%d", ioc->id);
 
 	spin_lock_init(&ioc->FreeQlock);
@@ -1303,8 +1254,7 @@
 #endif
 	}
 
-	/* NEW!  20010220 -sralston
-	 * Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
+	/* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
 	 */
 	mpt_detect_bound_ports(ioc, pdev);
 
@@ -1354,13 +1304,13 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *	mptbase_remove - Remove a PCI intelligent MPT adapter.
+ *	mpt_detach - Remove a PCI intelligent MPT adapter.
  *	@pdev: Pointer to pci_dev structure
  *
  */
 
-static void __devexit
-mptbase_remove(struct pci_dev *pdev)
+void
+mpt_detach(struct pci_dev *pdev)
 {
 	MPT_ADAPTER 	*ioc = pci_get_drvdata(pdev);
 	char pname[32];
@@ -1397,43 +1347,21 @@
 	pci_set_drvdata(pdev, NULL);
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *	mptbase_shutdown -
- *
- */
-static void
-mptbase_shutdown(struct device * dev)
-{
-	int ii;
-
-	/* call per device driver shutdown entry point */
-	for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
-		if(MptDeviceDriverHandlers[ii] &&
-		  MptDeviceDriverHandlers[ii]->shutdown) {
-			MptDeviceDriverHandlers[ii]->shutdown(dev);
-		}
-	}
-
-}
-
-
 /**************************************************************************
  * Power Management
  */
 #ifdef CONFIG_PM
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *	mptbase_suspend - Fusion MPT base driver suspend routine.
+ *	mpt_suspend - Fusion MPT base driver suspend routine.
  *
  *
  */
-static int
-mptbase_suspend(struct pci_dev *pdev, pm_message_t state)
+int
+mpt_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	u32 device_state;
 	MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
-	int ii;
 
 	switch(state)
 	{
@@ -1453,14 +1381,6 @@
 	"pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n",
 		ioc->name, pdev, pci_name(pdev), device_state);
 
-	/* call per device driver suspend entry point */
-	for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
-		if(MptDeviceDriverHandlers[ii] &&
-		  MptDeviceDriverHandlers[ii]->suspend) {
-			MptDeviceDriverHandlers[ii]->suspend(pdev, state);
-		}
-	}
-
 	pci_save_state(pdev);
 
 	/* put ioc into READY_STATE */
@@ -1484,18 +1404,18 @@
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *	mptbase_resume - Fusion MPT base driver resume routine.
+ *	mpt_resume - Fusion MPT base driver resume routine.
  *
  *
  */
-static int
-mptbase_resume(struct pci_dev *pdev)
+int
+mpt_resume(struct pci_dev *pdev)
 {
 	MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
 	u32 device_state = pdev->current_state;
 	int recovery_state;
 	int ii;
-
+	
 	printk(MYIOC_s_INFO_FMT
 	"pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
 		ioc->name, pdev, pci_name(pdev), device_state);
@@ -1533,14 +1453,6 @@
 			"pci-resume: success\n", ioc->name);
 	}
 
-	/* call per device driver resume entry point */
-	for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
-		if(MptDeviceDriverHandlers[ii] &&
-		  MptDeviceDriverHandlers[ii]->resume) {
-			MptDeviceDriverHandlers[ii]->resume(pdev);
-		}
-	}
-
 	return 0;
 }
 #endif
@@ -1719,8 +1631,7 @@
 		ioc->alt_ioc->active = 1;
 	}
 
-	/* NEW!  20010120 -sralston
-	 *  Enable MPT base driver management of EventNotification
+	/*  Enable MPT base driver management of EventNotification
 	 *  and EventAck handling.
 	 */
 	if ((ret == 0) && (!ioc->facts.EventState))
@@ -1729,9 +1640,7 @@
 	if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
 		(void) SendEventNotification(ioc->alt_ioc, 1);	/* 1=Enable EventNotification */
 
-	/* (Bugzilla:fibrebugs, #513)
-	 * Bug fix (part 2)!  20010905 -sralston
-	 *	Add additional "reason" check before call to GetLanConfigPages
+	/*	Add additional "reason" check before call to GetLanConfigPages
 	 *	(combined with GetIoUnitPage2 call).  This prevents a somewhat
 	 *	recursive scenario; GetLanConfigPages times out, timer expired
 	 *	routine calls HardResetHandler, which calls into here again,
@@ -1829,37 +1738,43 @@
 static void
 mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
 {
-	unsigned int match_lo, match_hi;
+	struct pci_dev *peer=NULL;
+	unsigned int slot = PCI_SLOT(pdev->devfn);
+	unsigned int func = PCI_FUNC(pdev->devfn);
 	MPT_ADAPTER *ioc_srch;
 
-	match_lo = pdev->devfn-1;
-	match_hi = pdev->devfn+1;
-	dprintk((MYIOC_s_INFO_FMT "PCI bus/devfn=%x/%x, searching for devfn match on %x or %x\n",
-			ioc->name, pdev->bus->number, pdev->devfn, match_lo, match_hi));
+	dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x,"
+	    " searching for devfn match on %x or %x\n",
+		ioc->name, pci_name(pdev), pdev->devfn,
+		func-1, func+1));
+
+	peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
+	if (!peer) {
+		peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
+		if (!peer)
+			return;
+	}
 
 	list_for_each_entry(ioc_srch, &ioc_list, list) {
 		struct pci_dev *_pcidev = ioc_srch->pcidev;
-
-		if ((_pcidev->device == pdev->device) &&
-		    (_pcidev->bus->number == pdev->bus->number) &&
-		    (_pcidev->devfn == match_lo || _pcidev->devfn == match_hi) ) {
+		if (_pcidev == peer) {
 			/* Paranoia checks */
 			if (ioc->alt_ioc != NULL) {
 				printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
-						ioc->name, ioc->alt_ioc->name);
+					ioc->name, ioc->alt_ioc->name);
 				break;
 			} else if (ioc_srch->alt_ioc != NULL) {
 				printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
-						ioc_srch->name, ioc_srch->alt_ioc->name);
+					ioc_srch->name, ioc_srch->alt_ioc->name);
 				break;
 			}
 			dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
-					ioc->name, ioc_srch->name));
+				ioc->name, ioc_srch->name));
 			ioc_srch->alt_ioc = ioc;
 			ioc->alt_ioc = ioc_srch;
-			break;
 		}
 	}
+	pci_dev_put(peer);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1922,15 +1837,10 @@
 		ioc->alloc_total -= sz;
 	}
 
-	if (ioc->spi_data.nvram != NULL) {
-		kfree(ioc->spi_data.nvram);
-		ioc->spi_data.nvram = NULL;
-	}
-
-	if (ioc->spi_data.pIocPg3 != NULL) {
-		kfree(ioc->spi_data.pIocPg3);
-		ioc->spi_data.pIocPg3 = NULL;
-	}
+	kfree(ioc->spi_data.nvram);
+	kfree(ioc->spi_data.pIocPg3);
+	ioc->spi_data.nvram = NULL;
+	ioc->spi_data.pIocPg3 = NULL;
 
 	if (ioc->spi_data.pIocPg4 != NULL) {
 		sz = ioc->spi_data.IocPg4Sz;
@@ -1947,10 +1857,8 @@
 		ioc->ReqToChain = NULL;
 	}
 
-	if (ioc->ChainToChain != NULL) {
-		kfree(ioc->ChainToChain);
-		ioc->ChainToChain = NULL;
-	}
+	kfree(ioc->ChainToChain);
+	ioc->ChainToChain = NULL;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2333,7 +2241,7 @@
 			return -55;
 		}
 
-		r = sz = le32_to_cpu(facts->BlockSize);
+		r = sz = facts->BlockSize;
 		vv = ((63 / (sz * 4)) + 1) & 0x03;
 		ioc->NB_for_64_byte_frame = vv;
 		while ( sz )
@@ -2785,7 +2693,7 @@
 	/* prevent a second downloadboot and memory free with alt_ioc */
 	if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
 		ioc->alt_ioc->cached_fw = NULL;
-	
+
 	CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
 	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
 	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
@@ -2843,6 +2751,9 @@
 	/* Write the LoadStartAddress to the DiagRw Address Register
 	 * using Programmed IO
 	 */
+	if (ioc->errata_flag_1064)
+		pci_enable_io_access(ioc->pcidev);
+
 	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
 	ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
 		ioc->name, pFwHeader->LoadStartAddress));
@@ -2889,6 +2800,9 @@
 	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
 	CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
 
+	if (ioc->errata_flag_1064)
+		pci_disable_io_access(ioc->pcidev);
+
 	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
 	ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT, DISABLE_ARM\n",
 		ioc->name, diag0val));
@@ -4250,7 +4164,7 @@
 				if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
 					(ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE))  {
 
-					if (ioc->spi_data.minSyncFactor < MPT_ULTRA)
+				if (ioc->spi_data.minSyncFactor < MPT_ULTRA)
 						ioc->spi_data.minSyncFactor = MPT_ULTRA;
 				}
 			}
@@ -4482,10 +4396,8 @@
 
 	/* Free the old page
 	 */
-	if (ioc->spi_data.pIocPg3) {
-		kfree(ioc->spi_data.pIocPg3);
-		ioc->spi_data.pIocPg3 = NULL;
-	}
+	kfree(ioc->spi_data.pIocPg3);
+	ioc->spi_data.pIocPg3 = NULL;
 
 	/* There is at least one physical disk.
 	 * Read and save IOC Page 3
@@ -4753,9 +4665,7 @@
 	u32		 flagsLength;
 	int		 in_isr;
 
-	/* (Bugzilla:fibrebugs, #513)
-	 * Bug fix (part 1)!  20010905 -sralston
-	 *	Prevent calling wait_event() (below), if caller happens
+	/*	Prevent calling wait_event() (below), if caller happens
 	 *	to be in ISR context, because that is fatal!
 	 */
 	in_isr = in_interrupt();
@@ -4861,9 +4771,7 @@
 	u32		 flagsLength;
 	int		 in_isr;
 
-	/* (Bugzilla:fibrebugs, #513)
-	 * Bug fix (part 1)!  20010905 -sralston
-	 *	Prevent calling wait_event() (below), if caller happens
+	/*	Prevent calling wait_event() (below), if caller happens
 	 *	to be in ISR context, because that is fatal!
 	 */
 	in_isr = in_interrupt();
@@ -5130,20 +5038,26 @@
 procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
 {
 	int	 ii;
-	int	 scsi, lan, ctl, targ, dmp;
+	int	 scsi, fc, sas, lan, ctl, targ, dmp;
 	char	*drvname;
 	int	 len;
 
 	len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
 	len += sprintf(buf+len, "  Fusion MPT base driver\n");
 
-	scsi = lan = ctl = targ = dmp = 0;
+	scsi = fc = sas = lan = ctl = targ = dmp = 0;
 	for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
 		drvname = NULL;
 		if (MptCallbacks[ii]) {
 			switch (MptDriverClass[ii]) {
-			case MPTSCSIH_DRIVER:
-				if (!scsi++) drvname = "SCSI host";
+			case MPTSPI_DRIVER:
+				if (!scsi++) drvname = "SPI host";
+				break;
+			case MPTFC_DRIVER:
+				if (!fc++) drvname = "FC host";
+				break;
+			case MPTSAS_DRIVER:
+				if (!sas++) drvname = "SAS host";
 				break;
 			case MPTLAN_DRIVER:
 				if (!lan++) drvname = "LAN";
@@ -5832,6 +5746,12 @@
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+EXPORT_SYMBOL(mpt_attach);
+EXPORT_SYMBOL(mpt_detach);
+#ifdef CONFIG_PM
+EXPORT_SYMBOL(mpt_resume);
+EXPORT_SYMBOL(mpt_suspend);
+#endif
 EXPORT_SYMBOL(ioc_list);
 EXPORT_SYMBOL(mpt_proc_root_dir);
 EXPORT_SYMBOL(mpt_register);
@@ -5860,19 +5780,6 @@
 EXPORT_SYMBOL(mpt_alloc_fw_memory);
 EXPORT_SYMBOL(mpt_free_fw_memory);
 
-static struct pci_driver mptbase_driver = {
-	.name		= "mptbase",
-	.id_table	= mptbase_pci_table,
-	.probe		= mptbase_probe,
-	.remove		= __devexit_p(mptbase_remove),
-	.driver         = {
-		.shutdown = mptbase_shutdown,
-        },
-#ifdef CONFIG_PM
-	.suspend	= mptbase_suspend,
-	.resume		= mptbase_resume,
-#endif
-};
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -5884,7 +5791,6 @@
 fusion_init(void)
 {
 	int i;
-	int r;
 
 	show_mptmod_ver(my_NAME, my_VERSION);
 	printk(KERN_INFO COPYRIGHT "\n");
@@ -5896,8 +5802,7 @@
 		MptResetHandlers[i] = NULL;
 	}
 
-	/* NEW!  20010120 -sralston
-	 *  Register ourselves (mptbase) in order to facilitate
+	/*  Register ourselves (mptbase) in order to facilitate
 	 *  EventNotification handling.
 	 */
 	mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
@@ -5913,11 +5818,7 @@
 #ifdef CONFIG_PROC_FS
 	(void) procmpt_create();
 #endif
-	r = pci_register_driver(&mptbase_driver);
-	if(r)
-		return(r);
-
-	return r;
+	return 0;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -5933,7 +5834,6 @@
 
 	dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
 
-	pci_unregister_driver(&mptbase_driver);
 	mpt_reset_deregister(mpt_base_index);
 
 #ifdef CONFIG_PROC_FS
@@ -5941,6 +5841,5 @@
 #endif
 }
 
-
 module_init(fusion_init);
 module_exit(fusion_exit);
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
index 6d16acc..848fb236 100644
--- a/drivers/message/fusion/mptbase.h
+++ b/drivers/message/fusion/mptbase.h
@@ -5,15 +5,9 @@
  *          LSIFC9xx/LSI409xx Fibre Channel
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
- *  Credits:
- *     (see mptbase.c)
- *
- *  Copyright (c) 1999-2004 LSI Logic Corporation
- *  Originally By: Steven J. Ralston
- *  (mailto:sjralston1@netscape.net)
+ *  Copyright (c) 1999-2005 LSI Logic Corporation
  *  (mailto:mpt_linux_developer@lsil.com)
  *
- *  $Id: mptbase.h,v 1.144 2003/01/28 21:31:56 pdelaney Exp $
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -71,7 +65,6 @@
 #include "lsi/mpi_fc.h"		/* Fibre Channel (lowlevel) support */
 #include "lsi/mpi_targ.h"	/* SCSI/FCP Target protcol support */
 #include "lsi/mpi_tool.h"	/* Tools support */
-#include "lsi/fc_log.h"
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
@@ -80,11 +73,11 @@
 #endif
 
 #ifndef COPYRIGHT
-#define COPYRIGHT	"Copyright (c) 1999-2004 " MODULEAUTHOR
+#define COPYRIGHT	"Copyright (c) 1999-2005 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON	"3.01.20"
-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.01.20"
+#define MPT_LINUX_VERSION_COMMON	"3.03.02"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.03.02"
 #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -203,7 +196,9 @@
 typedef enum {
 	MPTBASE_DRIVER,		/* MPT base class */
 	MPTCTL_DRIVER,		/* MPT ioctl class */
-	MPTSCSIH_DRIVER,	/* MPT SCSI host (initiator) class */
+	MPTSPI_DRIVER,		/* MPT SPI host class */
+	MPTFC_DRIVER,		/* MPT FC host class */
+	MPTSAS_DRIVER,		/* MPT SAS host class */
 	MPTLAN_DRIVER,		/* MPT LAN class */
 	MPTSTM_DRIVER,		/* MPT SCSI target mode class */
 	MPTUNKNOWN_DRIVER
@@ -212,11 +207,6 @@
 struct mpt_pci_driver{
 	int  (*probe) (struct pci_dev *dev, const struct pci_device_id *id);
 	void (*remove) (struct pci_dev *dev);
-	void (*shutdown) (struct device * dev);
-#ifdef CONFIG_PM
-	int  (*resume) (struct pci_dev *dev);
-	int  (*suspend) (struct pci_dev *dev, pm_message_t state);
-#endif
 };
 
 /*
@@ -483,6 +473,7 @@
 	u8		 forceDv;		/* 1 to force DV scheduling */
 	u8		 noQas;			/* Disable QAS for this adapter */
 	u8		 Saf_Te;		/* 1 to force all Processors as SAF-TE if Inquiry data length is too short to check for SAF-TE */
+	u8		 mpt_dv;		/* command line option: enhanced=1, basic=0 */
 	u8		 rsvd[1];
 } ScsiCfgData;
 
@@ -571,11 +562,21 @@
 	FCPortPage0_t		 fc_port_page0[2];
 	LANPage0_t		 lan_cnfg_page0;
 	LANPage1_t		 lan_cnfg_page1;
+	/*  
+	 * Description: errata_flag_1064
+	 * If a PCIX read occurs within 1 or 2 cycles after the chip receives
+	 * a split completion for a read data, an internal address pointer incorrectly
+	 * increments by 32 bytes
+	 */
+	int			 errata_flag_1064;	
 	u8			 FirstWhoInit;
 	u8			 upload_fw;	/* If set, do a fw upload */
 	u8			 reload_fw;	/* Force a FW Reload on next reset */
 	u8			 NBShiftFactor;  /* NB Shift Factor based on Block Size (Facts)  */     
 	u8			 pad1[4];
+	int			 DoneCtx;
+	int			 TaskCtx;
+	int			 InternalCtx;
 	struct list_head	 list; 
 	struct net_device	*netdev;
 } MPT_ADAPTER;
@@ -773,12 +774,6 @@
 #define DBG_DUMP_TM_REPLY_FRAME(mfp)
 #endif
 
-#ifdef MPT_DEBUG_NEH
-#define nehprintk(x) printk x
-#else
-#define nehprintk(x)
-#endif
-
 #if defined(MPT_DEBUG_CONFIG) || defined(MPT_DEBUG)
 #define dcprintk(x) printk x
 #else
@@ -898,6 +893,11 @@
 	unsigned long		  soft_resets;		/* fw/external bus resets count */
 	unsigned long		  timeouts;		/* cmd timeouts */
 	ushort			  sel_timeout[MPT_MAX_FC_DEVICES];
+	char 			  *info_kbuf;
+	wait_queue_head_t	  scandv_waitq;
+	int			  scandv_wait_done;
+	long			  last_queue_full;
+	u8		 	  mpt_pq_filter;
 } MPT_SCSI_HOST;
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -931,6 +931,12 @@
 /*
  *  Public entry points...
  */
+extern int	 mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id);
+extern void	 mpt_detach(struct pci_dev *pdev);
+#ifdef CONFIG_PM
+extern int	 mpt_suspend(struct pci_dev *pdev, pm_message_t state);
+extern int	 mpt_resume(struct pci_dev *pdev);
+#endif
 extern int	 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass);
 extern void	 mpt_deregister(int cb_idx);
 extern int	 mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc);
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 70b0cfb..05ea594 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -1,40 +1,12 @@
 /*
  *  linux/drivers/message/fusion/mptctl.c
- *      Fusion MPT misc device (ioctl) driver.
- *      For use with PCI chip/adapter(s):
- *          LSIFC9xx/LSI409xx Fibre Channel
+ *      mpt Ioctl driver.
+ *      For use with LSI Logic PCI chip/adapters
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
- *  Credits:
- *      This driver would not exist if not for Alan Cox's development
- *      of the linux i2o driver.
- *
- *      A special thanks to Pamela Delaney (LSI Logic) for tons of work
- *      and countless enhancements while adding support for the 1030
- *      chip family.  Pam has been instrumental in the development of
- *      of the 2.xx.xx series fusion drivers, and her contributions are
- *      far too numerous to hope to list in one place.
- *
- *      A huge debt of gratitude is owed to David S. Miller (DaveM)
- *      for fixing much of the stupid and broken stuff in the early
- *      driver while porting to sparc64 platform.  THANK YOU!
- *
- *      A big THANKS to Eddie C. Dost for fixing the ioctl path
- *      and most importantly f/w download on sparc64 platform!
- *      (plus Eddie's other helpful hints and insights)
- *
- *      Thanks to Arnaldo Carvalho de Melo for finding and patching
- *      a potential memory leak in mptctl_do_fw_download(),
- *      and for some kmalloc insight:-)
- *
- *      (see also mptbase.c)
- *
- *  Copyright (c) 1999-2004 LSI Logic Corporation
- *  Originally By: Steven J. Ralston, Noah Romer
- *  (mailto:sjralston1@netscape.net)
+ *  Copyright (c) 1999-2005 LSI Logic Corporation
  *  (mailto:mpt_linux_developer@lsil.com)
  *
- *  $Id: mptctl.c,v 1.63 2002/12/03 21:26:33 pdelaney Exp $
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -95,8 +67,8 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
 
-#define COPYRIGHT	"Copyright (c) 1999-2004 LSI Logic Corporation"
-#define MODULEAUTHOR	"Steven J. Ralston, Noah Romer, Pamela Delaney"
+#define COPYRIGHT	"Copyright (c) 1999-2005 LSI Logic Corporation"
+#define MODULEAUTHOR	"LSI Logic Corporation"
 #include "mptbase.h"
 #include "mptctl.h"
 
@@ -127,14 +99,14 @@
  * arg contents specific to function.
  */
 static int mptctl_fw_download(unsigned long arg);
-static int mptctl_getiocinfo (unsigned long arg, unsigned int cmd);
-static int mptctl_gettargetinfo (unsigned long arg);
-static int mptctl_readtest (unsigned long arg);
-static int mptctl_mpt_command (unsigned long arg);
-static int mptctl_eventquery (unsigned long arg);
-static int mptctl_eventenable (unsigned long arg);
-static int mptctl_eventreport (unsigned long arg);
-static int mptctl_replace_fw (unsigned long arg);
+static int mptctl_getiocinfo(unsigned long arg, unsigned int cmd);
+static int mptctl_gettargetinfo(unsigned long arg);
+static int mptctl_readtest(unsigned long arg);
+static int mptctl_mpt_command(unsigned long arg);
+static int mptctl_eventquery(unsigned long arg);
+static int mptctl_eventenable(unsigned long arg);
+static int mptctl_eventreport(unsigned long arg);
+static int mptctl_replace_fw(unsigned long arg);
 
 static int mptctl_do_reset(unsigned long arg);
 static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd);
@@ -149,11 +121,11 @@
 /*
  * Private function calls.
  */
-static int mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr);
+static int mptctl_do_mpt_command(struct mpt_ioctl_command karg, void __user *mfPtr);
 static int mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen);
-static MptSge_t *kbuf_alloc_2_sgl( int bytes, u32 dir, int sge_offset, int *frags,
+static MptSge_t *kbuf_alloc_2_sgl(int bytes, u32 dir, int sge_offset, int *frags,
 		struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);
-static void kfree_sgl( MptSge_t *sgl, dma_addr_t sgl_dma,
+static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma,
 		struct buflist *buflist, MPT_ADAPTER *ioc);
 static void mptctl_timeout_expired (MPT_IOCTL *ioctl);
 static int  mptctl_bus_reset(MPT_IOCTL *ioctl);
@@ -1119,7 +1091,7 @@
 	int			numDevices = 0;
 	unsigned int		max_id;
 	int			ii;
-	int			port;
+	unsigned int		port;
 	int			cim_rev;
 	u8			revision;
 
@@ -1162,9 +1134,7 @@
 		return -ENODEV;
 	}
 
-	/* Verify the data transfer size is correct.
-	 * Ignore the port setting.
-	 */
+	/* Verify the data transfer size is correct. */
 	if (karg->hdr.maxDataSize != data_size) {
 		printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
 			"Structure size mismatch. Command not completed.\n",
@@ -1181,6 +1151,8 @@
 	else
 		karg->adapterType = MPT_IOCTL_INTERFACE_SCSI;
 
+	if (karg->hdr.port > 1)
+		return -EINVAL;
 	port = karg->hdr.port;
 
 	karg->port = port;
diff --git a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h
index cc4ecf0..28754a9 100644
--- a/drivers/message/fusion/mptctl.h
+++ b/drivers/message/fusion/mptctl.h
@@ -5,22 +5,9 @@
  *          LSIFC9xx/LSI409xx Fibre Channel
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
- *  Credits:
- *      This driver would not exist if not for Alan Cox's development
- *      of the linux i2o driver.
- *
- *      A huge debt of gratitude is owed to David S. Miller (DaveM)
- *      for fixing much of the stupid and broken stuff in the early
- *      driver while porting to sparc64 platform.  THANK YOU!
- *
- *      (see also mptbase.c)
- *
- *  Copyright (c) 1999-2004 LSI Logic Corporation
- *  Originally By: Steven J. Ralston
- *  (mailto:sjralston1@netscape.net)
+ *  Copyright (c) 1999-2005 LSI Logic Corporation
  *  (mailto:mpt_linux_developer@lsil.com)
  *
- *  $Id: mptctl.h,v 1.13 2002/12/03 21:26:33 pdelaney Exp $
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
new file mode 100644
index 0000000..d8d6539
--- /dev/null
+++ b/drivers/message/fusion/mptfc.c
@@ -0,0 +1,431 @@
+/*
+ *  linux/drivers/message/fusion/mptfc.c
+ *      For use with LSI Logic PCI chip/adapter(s)
+ *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *
+ *  Copyright (c) 1999-2005 LSI Logic Corporation
+ *  (mailto:mpt_linux_developer@lsil.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; 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.
+
+    NO WARRANTY
+    THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+    CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+    LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+    solely responsible for determining the appropriateness of using and
+    distributing the Program and assumes all risks associated with its
+    exercise of rights under this Agreement, including but not limited to
+    the risks and costs of program errors, damage to or loss of data,
+    programs or equipment, and unavailability or interruption of operations.
+
+    DISCLAIMER OF LIABILITY
+    NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+    HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+    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_compat.h"	/* linux-2.6 tweaks */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/kdev_t.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>	/* for mdelay */
+#include <linux/interrupt.h>	/* needed for in_interrupt() proto */
+#include <linux/reboot.h>	/* notifier code */
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+
+#include "mptbase.h"
+#include "mptscsih.h"
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+#define my_NAME		"Fusion MPT FC Host driver"
+#define my_VERSION	MPT_LINUX_VERSION_COMMON
+#define MYNAM		"mptfc"
+
+MODULE_AUTHOR(MODULEAUTHOR);
+MODULE_DESCRIPTION(my_NAME);
+MODULE_LICENSE("GPL");
+
+/* Command line args */
+static int mpt_pq_filter = 0;
+module_param(mpt_pq_filter, int, 0);
+MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1  (default=0)");
+
+static int	mptfcDoneCtx = -1;
+static int	mptfcTaskCtx = -1;
+static int	mptfcInternalCtx = -1; /* Used only for internal commands */
+
+static struct device_attribute mptfc_queue_depth_attr = {
+	.attr = {
+		.name = 	"queue_depth",
+		.mode =		S_IWUSR,
+	},
+	.store = mptscsih_store_queue_depth,
+};
+
+static struct device_attribute *mptfc_dev_attrs[] = {
+	&mptfc_queue_depth_attr,
+	NULL,
+};
+
+static struct scsi_host_template mptfc_driver_template = {
+	.proc_name			= "mptfc",
+	.proc_info			= mptscsih_proc_info,
+	.name				= "MPT FC Host",
+	.info				= mptscsih_info,
+	.queuecommand			= mptscsih_qcmd,
+	.slave_alloc			= mptscsih_slave_alloc,
+	.slave_configure		= mptscsih_slave_configure,
+	.slave_destroy			= mptscsih_slave_destroy,
+	.eh_abort_handler		= mptscsih_abort,
+	.eh_device_reset_handler	= mptscsih_dev_reset,
+	.eh_bus_reset_handler		= mptscsih_bus_reset,
+	.eh_host_reset_handler		= mptscsih_host_reset,
+	.bios_param			= mptscsih_bios_param,
+	.can_queue			= MPT_FC_CAN_QUEUE,
+	.this_id			= -1,
+	.sg_tablesize			= MPT_SCSI_SG_DEPTH,
+	.max_sectors			= 8192,
+	.cmd_per_lun			= 7,
+	.use_clustering			= ENABLE_CLUSTERING,
+	.sdev_attrs			= mptfc_dev_attrs,
+};
+
+/****************************************************************************
+ * Supported hardware
+ */
+
+static struct pci_device_id mptfc_pci_table[] = {
+	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909,
+		PCI_ANY_ID, PCI_ANY_ID },
+	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919,
+		PCI_ANY_ID, PCI_ANY_ID },
+	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929,
+		PCI_ANY_ID, PCI_ANY_ID },
+	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X,
+		PCI_ANY_ID, PCI_ANY_ID },
+	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X,
+		PCI_ANY_ID, PCI_ANY_ID },
+	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC939X,
+		PCI_ANY_ID, PCI_ANY_ID },
+	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X,
+		PCI_ANY_ID, PCI_ANY_ID },
+	{0}	/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	mptfc_probe - Installs scsi devices per bus.
+ *	@pdev: Pointer to pci_dev structure
+ *
+ *	Returns 0 for success, non-zero for failure.
+ *
+ */
+static int
+mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct Scsi_Host	*sh;
+	MPT_SCSI_HOST		*hd;
+	MPT_ADAPTER 		*ioc;
+	unsigned long		 flags;
+	int			 sz, ii;
+	int			 numSGE = 0;
+	int			 scale;
+	int			 ioc_cap;
+	u8			*mem;
+	int			error=0;
+	int			r;
+		
+	if ((r = mpt_attach(pdev,id)) != 0)
+		return r;
+	
+	ioc = pci_get_drvdata(pdev);
+	ioc->DoneCtx = mptfcDoneCtx;
+	ioc->TaskCtx = mptfcTaskCtx;
+	ioc->InternalCtx = mptfcInternalCtx;
+
+	/*  Added sanity check on readiness of the MPT adapter.
+	 */
+	if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
+		printk(MYIOC_s_WARN_FMT
+		  "Skipping because it's not operational!\n",
+		  ioc->name);
+		return -ENODEV;
+	}
+
+	if (!ioc->active) {
+		printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
+		  ioc->name);
+		return -ENODEV;
+	}
+
+	/*  Sanity check - ensure at least 1 port is INITIATOR capable
+	 */
+	ioc_cap = 0;
+	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
+		if (ioc->pfacts[ii].ProtocolFlags &
+		    MPI_PORTFACTS_PROTOCOL_INITIATOR)
+			ioc_cap ++;
+	}
+
+	if (!ioc_cap) {
+		printk(MYIOC_s_WARN_FMT
+			"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
+			ioc->name, ioc);
+		return -ENODEV;
+	}
+
+	sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
+
+	if (!sh) {
+		printk(MYIOC_s_WARN_FMT
+			"Unable to register controller with SCSI subsystem\n",
+			ioc->name);
+                return -1;
+        }
+
+	spin_lock_irqsave(&ioc->FreeQlock, flags);
+
+	/* Attach the SCSI Host to the IOC structure
+	 */
+	ioc->sh = sh;
+
+	sh->io_port = 0;
+	sh->n_io_port = 0;
+	sh->irq = 0;
+
+	/* set 16 byte cdb's */
+	sh->max_cmd_len = 16;
+
+	sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
+
+	sh->max_lun = MPT_LAST_LUN + 1;
+	sh->max_channel = 0;
+	sh->this_id = ioc->pfacts[0].PortSCSIID;
+
+	/* Required entry.
+	 */
+	sh->unique_id = ioc->id;
+
+	/* Verify that we won't exceed the maximum
+	 * number of chain buffers
+	 * We can optimize:  ZZ = req_sz/sizeof(SGE)
+	 * For 32bit SGE's:
+	 *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
+	 *               + (req_sz - 64)/sizeof(SGE)
+	 * A slightly different algorithm is required for
+	 * 64bit SGEs.
+	 */
+	scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
+	if (sizeof(dma_addr_t) == sizeof(u64)) {
+		numSGE = (scale - 1) *
+		  (ioc->facts.MaxChainDepth-1) + scale +
+		  (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
+		  sizeof(u32));
+	} else {
+		numSGE = 1 + (scale - 1) *
+		  (ioc->facts.MaxChainDepth-1) + scale +
+		  (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
+		  sizeof(u32));
+	}
+
+	if (numSGE < sh->sg_tablesize) {
+		/* Reset this value */
+		dprintk((MYIOC_s_INFO_FMT
+		  "Resetting sg_tablesize to %d from %d\n",
+		  ioc->name, numSGE, sh->sg_tablesize));
+		sh->sg_tablesize = numSGE;
+	}
+
+	/* Set the pci device pointer in Scsi_Host structure.
+	 */
+	scsi_set_device(sh, &ioc->pcidev->dev);
+
+	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+
+	hd = (MPT_SCSI_HOST *) sh->hostdata;
+	hd->ioc = ioc;
+
+	/* SCSI needs scsi_cmnd lookup table!
+	 * (with size equal to req_depth*PtrSz!)
+	 */
+	sz = ioc->req_depth * sizeof(void *);
+	mem = kmalloc(sz, GFP_ATOMIC);
+	if (mem == NULL) {
+		error = -ENOMEM;
+		goto mptfc_probe_failed;
+	}
+
+	memset(mem, 0, sz);
+	hd->ScsiLookup = (struct scsi_cmnd **) mem;
+
+	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
+		 ioc->name, hd->ScsiLookup, sz));
+
+	/* Allocate memory for the device structures.
+	 * A non-Null pointer at an offset
+	 * indicates a device exists.
+	 * max_id = 1 + maximum id (hosts.h)
+	 */
+	sz = sh->max_id * sizeof(void *);
+	mem = kmalloc(sz, GFP_ATOMIC);
+	if (mem == NULL) {
+		error = -ENOMEM;
+		goto mptfc_probe_failed;
+	}
+
+	memset(mem, 0, sz);
+	hd->Targets = (VirtDevice **) mem;
+
+	dprintk((KERN_INFO
+	  "  Targets @ %p, sz=%d\n", hd->Targets, sz));
+
+	/* Clear the TM flags
+	 */
+	hd->tmPending = 0;
+	hd->tmState = TM_STATE_NONE;
+	hd->resetPending = 0;
+	hd->abortSCpnt = NULL;
+
+	/* Clear the pointer used to store
+	 * single-threaded commands, i.e., those
+	 * issued during a bus scan, dv and
+	 * configuration pages.
+	 */
+	hd->cmdPtr = NULL;
+
+	/* Initialize this SCSI Hosts' timers
+	 * To use, set the timer expires field
+	 * and add_timer
+	 */
+	init_timer(&hd->timer);
+	hd->timer.data = (unsigned long) hd;
+	hd->timer.function = mptscsih_timer_expired;
+
+	hd->mpt_pq_filter = mpt_pq_filter;
+
+	ddvprintk((MYIOC_s_INFO_FMT
+		"mpt_pq_filter %x\n",
+		ioc->name, 
+		mpt_pq_filter));
+
+	init_waitqueue_head(&hd->scandv_waitq);
+	hd->scandv_wait_done = 0;
+	hd->last_queue_full = 0;
+
+	error = scsi_add_host (sh, &ioc->pcidev->dev);
+	if(error) {
+		dprintk((KERN_ERR MYNAM
+		  "scsi_add_host failed\n"));
+		goto mptfc_probe_failed;
+	}
+
+	scsi_scan_host(sh);
+	return 0;
+
+mptfc_probe_failed:
+
+	mptscsih_remove(pdev);
+	return error;
+}
+
+static struct pci_driver mptfc_driver = {
+	.name		= "mptfc",
+	.id_table	= mptfc_pci_table,
+	.probe		= mptfc_probe,
+	.remove		= __devexit_p(mptscsih_remove),
+	.driver         = {
+		.shutdown = mptscsih_shutdown,
+        },
+#ifdef CONFIG_PM
+	.suspend	= mptscsih_suspend,
+	.resume		= mptscsih_resume,
+#endif
+};
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mptfc_init - Register MPT adapter(s) as SCSI host(s) with
+ *	linux scsi mid-layer.
+ *
+ *	Returns 0 for success, non-zero for failure.
+ */
+static int __init
+mptfc_init(void)
+{
+
+	show_mptmod_ver(my_NAME, my_VERSION);
+
+	mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);
+	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) {
+		devtprintk((KERN_INFO MYNAM
+		  ": Registered for IOC event notifications\n"));
+	}
+
+	if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) {
+		dprintk((KERN_INFO MYNAM
+		  ": Registered for IOC reset notifications\n"));
+	}
+
+	return pci_register_driver(&mptfc_driver);
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mptfc_exit - Unregisters MPT adapter(s)
+ *
+ */
+static void __exit
+mptfc_exit(void)
+{
+	pci_unregister_driver(&mptfc_driver);
+	
+	mpt_reset_deregister(mptfcDoneCtx);
+	dprintk((KERN_INFO MYNAM
+	  ": Deregistered for IOC reset notifications\n"));
+
+	mpt_event_deregister(mptfcDoneCtx);
+	dprintk((KERN_INFO MYNAM
+	  ": Deregistered for IOC event notifications\n"));
+
+	mpt_deregister(mptfcInternalCtx);
+	mpt_deregister(mptfcTaskCtx);
+	mpt_deregister(mptfcDoneCtx);
+}
+
+module_init(mptfc_init);
+module_exit(mptfc_exit);
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
index ef2713b..52794be 100644
--- a/drivers/message/fusion/mptlan.c
+++ b/drivers/message/fusion/mptlan.c
@@ -1,33 +1,11 @@
 /*
  *  linux/drivers/message/fusion/mptlan.c
  *      IP Over Fibre Channel device driver.
- *      For use with PCI chip/adapter(s):
- *          LSIFC9xx/LSI409xx Fibre Channel
+ *      For use with LSI Logic Fibre Channel PCI chip/adapters
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
- *  Credits:
- *      This driver would not exist if not for Alan Cox's development
- *      of the linux i2o driver.
+ *  Copyright (c) 2000-2005 LSI Logic Corporation
  *
- *      Special thanks goes to the I2O LAN driver people at the
- *      University of Helsinki, who, unbeknownst to them, provided
- *      the inspiration and initial structure for this driver.
- *
- *      A huge debt of gratitude is owed to David S. Miller (DaveM)
- *      for fixing much of the stupid and broken stuff in the early
- *      driver while porting to sparc64 platform.  THANK YOU!
- *
- *      A really huge debt of gratitude is owed to Eddie C. Dost
- *      for gobs of hard work fixing and optimizing LAN code.
- *      THANK YOU!
- *
- *      (see also mptbase.c)
- *
- *  Copyright (c) 2000-2004 LSI Logic Corporation
- *  Originally By: Noah Romer
- *  (mailto:mpt_linux_developer@lsil.com)
- *
- *  $Id: mptlan.c,v 1.53 2002/10/17 20:15:58 pdelaney Exp $
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -221,7 +199,7 @@
 
 		// NOTE!  (Optimization) First case here is now caught in
 		//  mptbase.c::mpt_interrupt() routine and callcack here
-		//  is now skipped for this case!  20001218 -sralston
+		//  is now skipped for this case!
 #if 0
 		case LAN_REPLY_FORM_MESSAGE_CONTEXT:
 //			dioprintk((KERN_INFO MYNAM "/lan_reply: "
@@ -234,7 +212,7 @@
 //			dioprintk((MYNAM "/lan_reply: "
 //				  "calling mpt_lan_send_reply (turbo)\n"));
 
-			// Potential BUG here?  -sralston
+			// Potential BUG here?
 			//	FreeReqFrame = mpt_lan_send_turbo(dev, tmsg);
 			//  If/when mpt_lan_send_turbo would return 1 here,
 			//  calling routine (mptbase.c|mpt_interrupt)
@@ -310,8 +288,7 @@
 
 	case MPI_FUNCTION_EVENT_NOTIFICATION:
 	case MPI_FUNCTION_EVENT_ACK:
-		/* UPDATE!  20010120 -sralston
-		 *  _EVENT_NOTIFICATION should NOT come down this path any more.
+		/*  _EVENT_NOTIFICATION should NOT come down this path any more.
 		 *  Should be routed to mpt_lan_event_process(), but just in case...
 		 */
 		FreeReqFrame = 1;
@@ -561,8 +538,8 @@
 		}
 	}
 
-	kfree (priv->RcvCtl);
-	kfree (priv->mpt_rxfidx);
+	kfree(priv->RcvCtl);
+	kfree(priv->mpt_rxfidx);
 
 	for (i = 0; i < priv->tx_max_out; i++) {
 		if (priv->SendCtl[i].skb != NULL) {
diff --git a/drivers/message/fusion/mptlan.h b/drivers/message/fusion/mptlan.h
index 0579042..750e343 100644
--- a/drivers/message/fusion/mptlan.h
+++ b/drivers/message/fusion/mptlan.h
@@ -1,3 +1,49 @@
+/*
+ *  linux/drivers/message/fusion/mptlan.h
+ *      IP Over Fibre Channel device driver.
+ *      For use with LSI Logic Fibre Channel PCI chip/adapters
+ *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *
+ *  Copyright (c) 2000-2005 LSI Logic 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; 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.
+
+    NO WARRANTY
+    THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+    CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+    LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+    solely responsible for determining the appropriateness of using and
+    distributing the Program and assumes all risks associated with its
+    exercise of rights under this Agreement, including but not limited to
+    the risks and costs of program errors, damage to or loss of data,
+    programs or equipment, and unavailability or interruption of operations.
+
+    DISCLAIMER OF LIABILITY
+    NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+    HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+    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
+*/
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+
 /* mptlan.h */
 
 #ifndef LINUX_MPTLAN_H_INCLUDED
@@ -29,7 +75,7 @@
 #include <asm/io.h>
 
     /* Override mptbase.h by pre-defining these! */
-    #define MODULEAUTHOR "Noah Romer, Eddie C. Dost"
+#define MODULEAUTHOR	"LSI Logic Corporation"
 
 #include "mptbase.h"
 
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
index 3a3ef12..a0078ae 100644
--- a/drivers/message/fusion/mptscsih.c
+++ b/drivers/message/fusion/mptscsih.c
@@ -1,32 +1,11 @@
 /*
  *  linux/drivers/message/fusion/mptscsih.c
- *      High performance SCSI / Fibre Channel SCSI Host device driver.
- *      For use with PCI chip/adapter(s):
- *          LSIFC9xx/LSI409xx Fibre Channel
+ *      For use with LSI Logic PCI chip/adapter(s)
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
- *  Credits:
- *      This driver would not exist if not for Alan Cox's development
- *      of the linux i2o driver.
- *
- *      A special thanks to Pamela Delaney (LSI Logic) for tons of work
- *      and countless enhancements while adding support for the 1030
- *      chip family.  Pam has been instrumental in the development of
- *      of the 2.xx.xx series fusion drivers, and her contributions are
- *      far too numerous to hope to list in one place.
- *
- *      A huge debt of gratitude is owed to David S. Miller (DaveM)
- *      for fixing much of the stupid and broken stuff in the early
- *      driver while porting to sparc64 platform.  THANK YOU!
- *
- *      (see mptbase.c)
- *
- *  Copyright (c) 1999-2004 LSI Logic Corporation
- *  Original author: Steven J. Ralston
- *  (mailto:sjralston1@netscape.net)
+ *  Copyright (c) 1999-2005 LSI Logic Corporation
  *  (mailto:mpt_linux_developer@lsil.com)
  *
- *  $Id: mptscsih.c,v 1.104 2002/12/03 21:26:34 pdelaney Exp $
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -96,27 +75,6 @@
 MODULE_DESCRIPTION(my_NAME);
 MODULE_LICENSE("GPL");
 
-/* Command line args */
-static int mpt_dv = MPTSCSIH_DOMAIN_VALIDATION;
-MODULE_PARM(mpt_dv, "i");
-MODULE_PARM_DESC(mpt_dv, " DV Algorithm: enhanced=1, basic=0 (default=MPTSCSIH_DOMAIN_VALIDATION=1)");
-
-static int mpt_width = MPTSCSIH_MAX_WIDTH;
-MODULE_PARM(mpt_width, "i");
-MODULE_PARM_DESC(mpt_width, " Max Bus Width: wide=1, narrow=0 (default=MPTSCSIH_MAX_WIDTH=1)");
-
-static int mpt_factor = MPTSCSIH_MIN_SYNC;
-MODULE_PARM(mpt_factor, "h");
-MODULE_PARM_DESC(mpt_factor, " Min Sync Factor (default=MPTSCSIH_MIN_SYNC=0x08)");
-
-static int mpt_saf_te = MPTSCSIH_SAF_TE;
-MODULE_PARM(mpt_saf_te, "i");
-MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1  (default=MPTSCSIH_SAF_TE=0)");
-
-static int mpt_pq_filter = 0;
-MODULE_PARM(mpt_pq_filter, "i");
-MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1  (default=0)");
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
 typedef struct _BIG_SENSE_BUF {
@@ -169,18 +127,17 @@
 	u16		 pad1;
 } DVPARAMETERS;
 
-
 /*
  *  Other private/forward protos...
  */
-static int	mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
+int		mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
 static void	mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq);
-static int	mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
+int		mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
 
 static int	mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,
 				 SCSIIORequest_t *pReq, int req_idx);
 static void	mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx);
-static void	copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
+static void	mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply);
 static int	mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd);
 static int	mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout );
 static u32	SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc);
@@ -188,8 +145,8 @@
 static int	mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
 static int	mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 target, u8 lun, int ctx2abort, ulong timeout);
 
-static int	mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
-static int	mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
+int		mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
+int		mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
 
 static void	mptscsih_initTarget(MPT_SCSI_HOST *hd, int bus_id, int target_id, u8 lun, char *data, int dlen);
 static void	mptscsih_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtDevice *target, char byte56);
@@ -198,8 +155,7 @@
 static void	mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id);
 static int	mptscsih_writeSDP1(MPT_SCSI_HOST *hd, int portnum, int target, int flags);
 static int	mptscsih_writeIOCPage4(MPT_SCSI_HOST *hd, int target_id, int bus);
-static int	mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
-static void	mptscsih_timer_expired(unsigned long data);
+int		mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
 static int	mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *iocmd);
 static int	mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, int portnum);
 
@@ -212,29 +168,14 @@
 static void	mptscsih_dv_parms(MPT_SCSI_HOST *hd, DVPARAMETERS *dv,void *pPage);
 static void	mptscsih_fillbuf(char *buffer, int size, int index, int width);
 #endif
-/* module entry point */
-static int  __init   mptscsih_init  (void);
-static void __exit   mptscsih_exit  (void);
 
-static int  mptscsih_probe (struct pci_dev *, const struct pci_device_id *);
-static void mptscsih_remove(struct pci_dev *);
-static void mptscsih_shutdown(struct device *);
+void 		mptscsih_remove(struct pci_dev *);
+void 		mptscsih_shutdown(struct device *);
 #ifdef CONFIG_PM
-static int mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
-static int mptscsih_resume(struct pci_dev *pdev);
+int 		mptscsih_suspend(struct pci_dev *pdev, pm_message_t state);
+int 		mptscsih_resume(struct pci_dev *pdev);
 #endif
 
-
-/*
- *	Private data...
- */
-
-static int	mpt_scsi_hosts = 0;
-
-static int	ScsiDoneCtx = -1;
-static int	ScsiTaskCtx = -1;
-static int	ScsiScanDvCtx = -1; /* Used only for bus scan and dv */
-
 #define SNS_LEN(scp)	sizeof((scp)->sense_buffer)
 
 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
@@ -244,20 +185,9 @@
 static DEFINE_SPINLOCK(dvtaskQ_lock);
 static int dvtaskQ_active = 0;
 static int dvtaskQ_release = 0;
-static struct work_struct	mptscsih_dvTask;
+static struct work_struct	dvTaskQ_task;
 #endif
 
-/*
- * Wait Queue setup
- */
-static DECLARE_WAIT_QUEUE_HEAD (scandv_waitq);
-static int scandv_wait_done = 1;
-
-
-/* Driver command line structure
- */
-static struct scsi_host_template driver_template;
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *	mptscsih_add_sge - Place a simple SGE at address pAddr.
@@ -619,7 +549,7 @@
  *
  *	Returns 1 indicating alloc'd request frame ptr should be freed.
  */
-static int
+int
 mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 {
 	struct scsi_cmnd	*sc;
@@ -677,8 +607,8 @@
 			sc->request_bufflen, xfer_cnt));
 
 		if (scsi_state & MPI_SCSI_STATE_AUTOSENSE_VALID)
-			copy_sense_data(sc, hd, mf, pScsiReply);
-                
+			mptscsih_copy_sense_data(sc, hd, mf, pScsiReply);
+
 		/*
 		 *  Look for + dump FCP ResponseInfo[]!
 		 */
@@ -740,7 +670,7 @@
 			}
 			dreplyprintk((KERN_NOTICE "RESIDUAL_MISMATCH: result=%x on id=%d\n", sc->result, sc->target));
 			break;
-		
+
 		case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN:		/* 0x0045 */
 			/*
 			 *  Do upfront check for valid SenseData and give it
@@ -773,7 +703,7 @@
 			 */
 			if (scsi_status == MPI_SCSI_STATUS_TASK_SET_FULL)
 				mptscsih_report_queue_full(sc, pScsiReply, pScsiReq);
-			
+
 			break;
 
 		case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR:	/* 0x0040 */
@@ -905,18 +835,16 @@
 			 * Do OS callback
 			 * Free driver resources (chain, msg buffers)
 			 */
-			if (scsi_device_online(SCpnt->device)) {
-				if (SCpnt->use_sg) {
-					pci_unmap_sg(ioc->pcidev,
-						(struct scatterlist *) SCpnt->request_buffer,
-						SCpnt->use_sg,
-						SCpnt->sc_data_direction);
-				} else if (SCpnt->request_bufflen) {
-					pci_unmap_single(ioc->pcidev,
-						SCpnt->SCp.dma_handle,
-						SCpnt->request_bufflen,
-						SCpnt->sc_data_direction);
-				}
+			if (SCpnt->use_sg) {
+				pci_unmap_sg(ioc->pcidev,
+					(struct scatterlist *) SCpnt->request_buffer,
+					SCpnt->use_sg,
+					SCpnt->sc_data_direction);
+			} else if (SCpnt->request_bufflen) {
+				pci_unmap_single(ioc->pcidev,
+					SCpnt->SCp.dma_handle,
+					SCpnt->request_bufflen,
+					SCpnt->sc_data_direction);
 			}
 			SCpnt->result = DID_RESET << 16;
 			SCpnt->host_scribble = NULL;
@@ -981,11 +909,6 @@
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *  Hack! It might be nice to report if a device is returning QUEUE_FULL
- *  but maybe not each and every time...
- */
-static long last_queue_full = 0;
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -1003,280 +926,20 @@
 mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq)
 {
 	long time = jiffies;
-
-	if (time - last_queue_full > 10 * HZ) {
-		char *ioc_str = "ioc?";
-
-		if (sc->device && sc->device->host != NULL && sc->device->host->hostdata != NULL)
-			ioc_str = ((MPT_SCSI_HOST *)sc->device->host->hostdata)->ioc->name;
-		dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
-				ioc_str, 0, sc->device->id, sc->device->lun));
-		last_queue_full = time;
-	}
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static char *info_kbuf = NULL;
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*
- *	mptscsih_probe - Installs scsi devices per bus.
- *	@pdev: Pointer to pci_dev structure
- *
- *	Returns 0 for success, non-zero for failure.
- *
- */
-
-static int
-mptscsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
-	struct Scsi_Host	*sh;
 	MPT_SCSI_HOST		*hd;
-	MPT_ADAPTER 		*ioc = pci_get_drvdata(pdev);
-	unsigned long		 flags;
-	int			 sz, ii;
-	int			 numSGE = 0;
-	int			 scale;
-	int			 ioc_cap;
-	u8			*mem;
-	int			error=0;
 
+	if (sc->device == NULL)
+		return;
+	if (sc->device->host == NULL)
+		return;
+	if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL)
+		return;
 
-	/* 20010202 -sralston
-	 *  Added sanity check on readiness of the MPT adapter.
-	 */
-	if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
-		printk(MYIOC_s_WARN_FMT
-		  "Skipping because it's not operational!\n",
-		  ioc->name);
-		return -ENODEV;
+	if (time - hd->last_queue_full > 10 * HZ) {
+		dprintk((MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n",
+				hd->ioc->name, 0, sc->device->id, sc->device->lun));
+		hd->last_queue_full = time;
 	}
-
-	if (!ioc->active) {
-		printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
-		  ioc->name);
-		return -ENODEV;
-	}
-
-	/*  Sanity check - ensure at least 1 port is INITIATOR capable
-	 */
-	ioc_cap = 0;
-	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
-		if (ioc->pfacts[ii].ProtocolFlags &
-		    MPI_PORTFACTS_PROTOCOL_INITIATOR)
-			ioc_cap ++;
-	}
-
-	if (!ioc_cap) {
-		printk(MYIOC_s_WARN_FMT
-			"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
-			ioc->name, ioc);
-		return -ENODEV;
-	}
-
-	sh = scsi_host_alloc(&driver_template, sizeof(MPT_SCSI_HOST));
-        
-	if (!sh) {
-		printk(MYIOC_s_WARN_FMT
-			"Unable to register controller with SCSI subsystem\n",
-			ioc->name);
-                return -1;
-        }
-	
-	spin_lock_irqsave(&ioc->FreeQlock, flags);
-
-	/* Attach the SCSI Host to the IOC structure
-	 */
-	ioc->sh = sh;
-
-	sh->io_port = 0;
-	sh->n_io_port = 0;
-	sh->irq = 0;
-
-	/* set 16 byte cdb's */
-	sh->max_cmd_len = 16;
-
-	/* Yikes!  This is important!
-	 * Otherwise, by default, linux
-	 * only scans target IDs 0-7!
-	 * pfactsN->MaxDevices unreliable
-	 * (not supported in early
-	 *	versions of the FW).
-	 * max_id = 1 + actual max id,
-	 * max_lun = 1 + actual last lun,
-	 *	see hosts.h :o(
-	 */
-	if (ioc->bus_type == SCSI) {
-		sh->max_id = MPT_MAX_SCSI_DEVICES;
-	} else {
-	/* For FC, increase the queue depth
-	 * from MPT_SCSI_CAN_QUEUE (31)
-	 * to MPT_FC_CAN_QUEUE (63).
-	 */
-		sh->can_queue = MPT_FC_CAN_QUEUE;
-		sh->max_id =
-		  MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
-	}
-		
-	sh->max_lun = MPT_LAST_LUN + 1;
-	sh->max_channel = 0;
-	sh->this_id = ioc->pfacts[0].PortSCSIID;
-		
-	/* Required entry.
-	 */
-	sh->unique_id = ioc->id;
-
-	/* Verify that we won't exceed the maximum
-	 * number of chain buffers
-	 * We can optimize:  ZZ = req_sz/sizeof(SGE)
-	 * For 32bit SGE's:
-	 *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
-	 *               + (req_sz - 64)/sizeof(SGE)
-	 * A slightly different algorithm is required for
-	 * 64bit SGEs.
-	 */
-	scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
-	if (sizeof(dma_addr_t) == sizeof(u64)) {
-		numSGE = (scale - 1) *
-		  (ioc->facts.MaxChainDepth-1) + scale +
-		  (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
-		  sizeof(u32));
-	} else {
-		numSGE = 1 + (scale - 1) *
-		  (ioc->facts.MaxChainDepth-1) + scale +
-		  (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
-		  sizeof(u32));
-	}
-		
-	if (numSGE < sh->sg_tablesize) {
-		/* Reset this value */
-		dprintk((MYIOC_s_INFO_FMT
-		  "Resetting sg_tablesize to %d from %d\n",
-		  ioc->name, numSGE, sh->sg_tablesize));
-		sh->sg_tablesize = numSGE;
-	}
-
-	/* Set the pci device pointer in Scsi_Host structure.
-	 */
-	scsi_set_device(sh, &ioc->pcidev->dev);
-
-	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
-
-	hd = (MPT_SCSI_HOST *) sh->hostdata;
-	hd->ioc = ioc;
-
-	/* SCSI needs scsi_cmnd lookup table!
-	 * (with size equal to req_depth*PtrSz!)
-	 */
-	sz = ioc->req_depth * sizeof(void *);
-	mem = kmalloc(sz, GFP_ATOMIC);
-	if (mem == NULL) {
-		error = -ENOMEM;
-		goto mptscsih_probe_failed;
-	}
-
-	memset(mem, 0, sz);
-	hd->ScsiLookup = (struct scsi_cmnd **) mem;
-
-	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
-		 ioc->name, hd->ScsiLookup, sz));
-		
-	/* Allocate memory for the device structures.
-	 * A non-Null pointer at an offset
-	 * indicates a device exists.
-	 * max_id = 1 + maximum id (hosts.h)
-	 */
-	sz = sh->max_id * sizeof(void *);
-	mem = kmalloc(sz, GFP_ATOMIC);
-	if (mem == NULL) {
-		error = -ENOMEM;
-		goto mptscsih_probe_failed;
-	}
-
-	memset(mem, 0, sz);
-	hd->Targets = (VirtDevice **) mem;
-
-	dprintk((KERN_INFO
-	  "  Targets @ %p, sz=%d\n", hd->Targets, sz));
-
-	/* Clear the TM flags
-	 */
-	hd->tmPending = 0;
-	hd->tmState = TM_STATE_NONE;
-	hd->resetPending = 0;
-	hd->abortSCpnt = NULL;
-
-	/* Clear the pointer used to store
-	 * single-threaded commands, i.e., those
-	 * issued during a bus scan, dv and
-	 * configuration pages.
-	 */
-	hd->cmdPtr = NULL;
-
-	/* Initialize this SCSI Hosts' timers
-	 * To use, set the timer expires field
-	 * and add_timer
-	 */
-	init_timer(&hd->timer);
-	hd->timer.data = (unsigned long) hd;
-	hd->timer.function = mptscsih_timer_expired;
-
-	if (ioc->bus_type == SCSI) {
-		/* Update with the driver setup
-		 * values.
-		 */
-		if (ioc->spi_data.maxBusWidth > mpt_width)
-			ioc->spi_data.maxBusWidth = mpt_width;
-		if (ioc->spi_data.minSyncFactor < mpt_factor)
-			ioc->spi_data.minSyncFactor = mpt_factor;
-
-		if (ioc->spi_data.minSyncFactor == MPT_ASYNC) {
-			ioc->spi_data.maxSyncOffset = 0;
-		}
-
-		ioc->spi_data.Saf_Te = mpt_saf_te;
-
-		hd->negoNvram = 0;
-#ifndef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
-		hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
-#endif
-		ioc->spi_data.forceDv = 0;
-		ioc->spi_data.noQas = 0;
-		for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
-			ioc->spi_data.dvStatus[ii] =
-			  MPT_SCSICFG_NEGOTIATE;
-		}
-
-		for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
-			ioc->spi_data.dvStatus[ii] |=
-			  MPT_SCSICFG_DV_NOT_DONE;
-
-		dinitprintk((MYIOC_s_INFO_FMT
-			"dv %x width %x factor %x saf_te %x\n",
-			ioc->name, mpt_dv,
-			mpt_width,
-			mpt_factor,
-			mpt_saf_te));
-	}
-
-	mpt_scsi_hosts++;
-
-	error = scsi_add_host (sh, &ioc->pcidev->dev);
-	if(error) {
-		dprintk((KERN_ERR MYNAM
-		  "scsi_add_host failed\n"));
-		goto mptscsih_probe_failed;
-	}
-
-	scsi_scan_host(sh);
-	return 0;
-
-mptscsih_probe_failed:
-
-	mptscsih_remove(pdev);
-	return error;
-
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1286,7 +949,7 @@
  *
  *
  */
-static void
+void
 mptscsih_remove(struct pci_dev *pdev)
 {
 	MPT_ADAPTER 		*ioc = pci_get_drvdata(pdev);
@@ -1294,12 +957,16 @@
 	MPT_SCSI_HOST		*hd;
 	int 		 	count;
 	unsigned long	 	flags;
+	int sz1;
 
 	if(!host)
 		return;
 
 	scsi_remove_host(host);
 
+	if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL)
+		return;
+
 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
 	/* Check DV thread active */
 	count = 10 * HZ;
@@ -1321,40 +988,36 @@
 #endif
 #endif
 
-	hd = (MPT_SCSI_HOST *)host->hostdata;
-	if (hd != NULL) {
-		int sz1;
+	mptscsih_shutdown(&pdev->dev);
 
-		mptscsih_shutdown(&pdev->dev);
+	sz1=0;
 
-		sz1=0;
-
-		if (hd->ScsiLookup != NULL) {
-			sz1 = hd->ioc->req_depth * sizeof(void *);
-			kfree(hd->ScsiLookup);
-			hd->ScsiLookup = NULL;
-		}
-
-		if (hd->Targets != NULL) {
-			/*
-			 * Free pointer array.
-			 */
-			kfree(hd->Targets);
-			hd->Targets = NULL;
-		}
-
-		dprintk((MYIOC_s_INFO_FMT 
-		    "Free'd ScsiLookup (%d) memory\n",
-		    hd->ioc->name, sz1));
-
-		/* NULL the Scsi_Host pointer
-		 */
-		hd->ioc->sh = NULL;
+	if (hd->ScsiLookup != NULL) {
+		sz1 = hd->ioc->req_depth * sizeof(void *);
+		kfree(hd->ScsiLookup);
+		hd->ScsiLookup = NULL;
 	}
 
-	scsi_host_put(host);
-	mpt_scsi_hosts--;
+	/*
+	 * Free pointer array.
+	 */
+	kfree(hd->Targets);
+	hd->Targets = NULL;
 
+	dprintk((MYIOC_s_INFO_FMT
+	    "Free'd ScsiLookup (%d) memory\n",
+	    hd->ioc->name, sz1));
+
+	kfree(hd->info_kbuf);
+
+	/* NULL the Scsi_Host pointer
+	 */
+	hd->ioc->sh = NULL;
+
+	scsi_host_put(host);
+
+	mpt_detach(pdev);
+	
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1362,7 +1025,7 @@
  *	mptscsih_shutdown - reboot notifier
  *
  */
-static void
+void
 mptscsih_shutdown(struct device * dev)
 {
 	MPT_ADAPTER 		*ioc = pci_get_drvdata(to_pci_dev(dev));
@@ -1384,15 +1047,15 @@
 #ifdef CONFIG_PM
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *	mptscsih_suspend - Fusion MPT scsie driver suspend routine.
+ *	mptscsih_suspend - Fusion MPT scsi driver suspend routine.
  *
  *
  */
-static int
+int
 mptscsih_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	mptscsih_shutdown(&pdev->dev);
-	return 0;
+	return mpt_suspend(pdev,state);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -1401,13 +1064,15 @@
  *
  *
  */
-static int
+int
 mptscsih_resume(struct pci_dev *pdev)
 {
 	MPT_ADAPTER 		*ioc = pci_get_drvdata(pdev);
 	struct Scsi_Host 	*host = ioc->sh;
 	MPT_SCSI_HOST		*hd;
 
+	mpt_resume(pdev);
+	
 	if(!host)
 		return 0;
 
@@ -1422,9 +1087,9 @@
 	if (!dvtaskQ_active) {
 		dvtaskQ_active = 1;
 		spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
-		INIT_WORK(&mptscsih_dvTask,
+		INIT_WORK(&dvTaskQ_task,
 		  mptscsih_domainValidation, (void *) hd);
-		schedule_work(&mptscsih_dvTask);
+		schedule_work(&dvTaskQ_task);
 	} else {
 		spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
 	}
@@ -1435,82 +1100,6 @@
 
 #endif
 
-static struct mpt_pci_driver mptscsih_driver = {
-	.probe		= mptscsih_probe,
-	.remove		= mptscsih_remove,
-	.shutdown	= mptscsih_shutdown,
-#ifdef CONFIG_PM
-	.suspend	= mptscsih_suspend,
-	.resume		= mptscsih_resume,
-#endif
-};
-
-/*  SCSI host fops start here...  */
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *	mptscsih_init - Register MPT adapter(s) as SCSI host(s) with
- *	linux scsi mid-layer.
- *
- *	Returns 0 for success, non-zero for failure.
- */
-static int __init
-mptscsih_init(void)
-{
-
-	show_mptmod_ver(my_NAME, my_VERSION);
-
-	ScsiDoneCtx = mpt_register(mptscsih_io_done, MPTSCSIH_DRIVER);
-	ScsiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSCSIH_DRIVER);
-	ScsiScanDvCtx = mpt_register(mptscsih_scandv_complete, MPTSCSIH_DRIVER);
-
-	if (mpt_event_register(ScsiDoneCtx, mptscsih_event_process) == 0) {
-		devtprintk((KERN_INFO MYNAM
-		  ": Registered for IOC event notifications\n"));
-	}
-
-	if (mpt_reset_register(ScsiDoneCtx, mptscsih_ioc_reset) == 0) {
-		dprintk((KERN_INFO MYNAM
-		  ": Registered for IOC reset notifications\n"));
-	}
-
-	if(mpt_device_driver_register(&mptscsih_driver,
-	  MPTSCSIH_DRIVER) != 0 ) {
-		dprintk((KERN_INFO MYNAM
-		": failed to register dd callbacks\n"));
-	}
-
-	return 0;
-
-}
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/**
- *	mptscsih_exit - Unregisters MPT adapter(s)
- *
- */
-static void __exit
-mptscsih_exit(void)
-{
-	mpt_device_driver_deregister(MPTSCSIH_DRIVER);
-
-	mpt_reset_deregister(ScsiDoneCtx);
-	dprintk((KERN_INFO MYNAM
-	  ": Deregistered for IOC reset notifications\n"));
-
-	mpt_event_deregister(ScsiDoneCtx);
-	dprintk((KERN_INFO MYNAM
-	  ": Deregistered for IOC event notifications\n"));
-
-	mpt_deregister(ScsiScanDvCtx);
-	mpt_deregister(ScsiTaskCtx);
-	mpt_deregister(ScsiDoneCtx);
-
-	if (info_kbuf != NULL)
-		kfree(info_kbuf);
-
-}
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /**
  *	mptscsih_info - Return information about MPT adapter
@@ -1520,24 +1109,25 @@
  *
  *	Returns pointer to buffer where information was written.
  */
-static const char *
+const char *
 mptscsih_info(struct Scsi_Host *SChost)
 {
 	MPT_SCSI_HOST *h;
 	int size = 0;
 
-	if (info_kbuf == NULL)
-		if ((info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
-			return info_kbuf;
-
 	h = (MPT_SCSI_HOST *)SChost->hostdata;
-	info_kbuf[0] = '\0';
+
 	if (h) {
-		mpt_print_ioc_summary(h->ioc, info_kbuf, &size, 0, 0);
-		info_kbuf[size-1] = '\0';
+		if (h->info_kbuf == NULL)
+			if ((h->info_kbuf = kmalloc(0x1000 /* 4Kb */, GFP_KERNEL)) == NULL)
+				return h->info_kbuf;
+		h->info_kbuf[0] = '\0';
+
+		mpt_print_ioc_summary(h->ioc, h->info_kbuf, &size, 0, 0);
+		h->info_kbuf[size-1] = '\0';
 	}
 
-	return info_kbuf;
+	return h->info_kbuf;
 }
 
 struct info_str {
@@ -1547,7 +1137,8 @@
 	int   pos;
 };
 
-static void copy_mem_info(struct info_str *info, char *data, int len)
+static void
+mptscsih_copy_mem_info(struct info_str *info, char *data, int len)
 {
 	if (info->pos + len > info->length)
 		len = info->length - info->pos;
@@ -1568,7 +1159,8 @@
 	}
 }
 
-static int copy_info(struct info_str *info, char *fmt, ...)
+static int
+mptscsih_copy_info(struct info_str *info, char *fmt, ...)
 {
 	va_list args;
 	char buf[81];
@@ -1578,11 +1170,12 @@
 	len = vsprintf(buf, fmt, args);
 	va_end(args);
 
-	copy_mem_info(info, buf, len);
+	mptscsih_copy_mem_info(info, buf, len);
 	return len;
 }
 
-static int mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
+static int
+mptscsih_host_info(MPT_ADAPTER *ioc, char *pbuf, off_t offset, int len)
 {
 	struct info_str info;
 
@@ -1591,10 +1184,10 @@
 	info.offset	= offset;
 	info.pos	= 0;
 
-	copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
-	copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
-	copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
-	copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
+	mptscsih_copy_info(&info, "%s: %s, ", ioc->name, ioc->prod_name);
+	mptscsih_copy_info(&info, "%s%08xh, ", MPT_FW_REV_MAGIC_ID_STRING, ioc->facts.FWVersion.Word);
+	mptscsih_copy_info(&info, "Ports=%d, ", ioc->facts.NumberOfPorts);
+	mptscsih_copy_info(&info, "MaxQ=%d\n", ioc->req_depth);
 
 	return ((info.pos > info.offset) ? info.pos - info.offset : 0);
 }
@@ -1612,7 +1205,7 @@
  * 	hostno: scsi host number
  *	func:   if write = 1; if read = 0
  */
-static int
+int
 mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset,
 			int length, int func)
 {
@@ -1649,7 +1242,7 @@
  *
  *	Returns 0. (rtn value discarded by linux scsi mid-layer)
  */
-static int
+int
 mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
 {
 	MPT_SCSI_HOST		*hd;
@@ -1684,7 +1277,7 @@
 	/*
 	 *  Put together a MPT SCSI request...
 	 */
-	if ((mf = mpt_get_msg_frame(ScsiDoneCtx, hd->ioc)) == NULL) {
+	if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) {
 		dprintk((MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n",
 				hd->ioc->name));
 		return SCSI_MLQUEUE_HOST_BUSY;
@@ -1696,8 +1289,7 @@
 
 	ADD_INDEX_LOG(my_idx);
 
-	/*  BUG FIX!  19991030 -sralston
-	 *    TUR's being issued with scsictl=0x02000000 (DATA_IN)!
+	/*    TUR's being issued with scsictl=0x02000000 (DATA_IN)!
 	 *    Seems we may receive a buffer (datalen>0) even when there
 	 *    will be no data transfer!  GRRRRR...
 	 */
@@ -1791,9 +1383,9 @@
 				if (!dvtaskQ_active) {
 					dvtaskQ_active = 1;
 					spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
-					INIT_WORK(&mptscsih_dvTask, mptscsih_domainValidation, (void *) hd);
+					INIT_WORK(&dvTaskQ_task, mptscsih_domainValidation, (void *) hd);
 
-					schedule_work(&mptscsih_dvTask);
+					schedule_work(&dvTaskQ_task);
 				} else {
 					spin_unlock_irqrestore(&dvtaskQ_lock, lflags);
 				}
@@ -1819,7 +1411,7 @@
 	}
 #endif
 
-	mpt_put_msg_frame(ScsiDoneCtx, hd->ioc, mf);
+	mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf);
 	dmfprintk((MYIOC_s_INFO_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n",
 			hd->ioc->name, SCpnt, mf, my_idx));
 	DBG_DUMP_REQUEST_FRAME(mf)
@@ -2036,7 +1628,7 @@
 
 	/* Return Fail to calling function if no message frames available.
 	 */
-	if ((mf = mpt_get_msg_frame(ScsiTaskCtx, hd->ioc)) == NULL) {
+	if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) {
 		dfailprintk((MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n",
 				hd->ioc->name));
 		//return FAILED;
@@ -2075,7 +1667,7 @@
 
 	DBG_DUMP_TM_REQUEST_FRAME((u32 *)pScsiTm);
 
-	if ((retval = mpt_send_handshake_request(ScsiTaskCtx, hd->ioc,
+	if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc,
 		sizeof(SCSITaskMgmt_t), (u32*)pScsiTm,
 		CAN_SLEEP)) != 0) {
 		dfailprintk((MYIOC_s_ERR_FMT "_send_handshake FAILED!"
@@ -2107,7 +1699,7 @@
  *
  *	Returns SUCCESS or FAILED.
  */
-static int
+int
 mptscsih_abort(struct scsi_cmnd * SCpnt)
 {
 	MPT_SCSI_HOST	*hd;
@@ -2115,7 +1707,6 @@
 	MPT_FRAME_HDR	*mf;
 	u32		 ctx2abort;
 	int		 scpnt_idx;
-	spinlock_t	*host_lock = SCpnt->device->host->host_lock;
 
 	/* If we can't locate our host adapter structure, return FAILED status.
 	 */
@@ -2163,7 +1754,6 @@
 
 	hd->abortSCpnt = SCpnt;
 
-	spin_unlock_irq(host_lock);
 	if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
 		SCpnt->device->channel, SCpnt->device->id, SCpnt->device->lun,
 		ctx2abort, 2 /* 2 second timeout */)
@@ -2180,8 +1770,6 @@
 		hd->tmPending = 0;
 		hd->tmState = TM_STATE_NONE;
 
-		spin_lock_irq(host_lock);
-
 		/* Unmap the DMA buffers, if any. */
 		if (SCpnt->use_sg) {
 			pci_unmap_sg(ioc->pcidev, (struct scatterlist *) SCpnt->request_buffer,
@@ -2197,7 +1785,6 @@
 		mpt_free_msg_frame(ioc, mf);
 		return FAILED;
 	}
-	spin_lock_irq(host_lock);
 	return SUCCESS;
 }
 
@@ -2210,11 +1797,10 @@
  *
  *	Returns SUCCESS or FAILED.
  */
-static int
+int
 mptscsih_dev_reset(struct scsi_cmnd * SCpnt)
 {
 	MPT_SCSI_HOST	*hd;
-	spinlock_t	*host_lock = SCpnt->device->host->host_lock;
 
 	/* If we can't locate our host adapter structure, return FAILED status.
 	 */
@@ -2231,7 +1817,6 @@
 	printk(KERN_WARNING MYNAM ": %s: >> Attempting target reset! (sc=%p)\n",
 	       hd->ioc->name, SCpnt);
 
-	spin_unlock_irq(host_lock);
 	if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
 		SCpnt->device->channel, SCpnt->device->id,
 		0, 0, 5 /* 5 second timeout */)
@@ -2243,12 +1828,10 @@
 		 		hd->ioc->name, SCpnt);
 		hd->tmPending = 0;
 		hd->tmState = TM_STATE_NONE;
-		spin_lock_irq(host_lock);
 		return FAILED;
 	}
-	spin_lock_irq(host_lock);
-	return SUCCESS;
 
+	return SUCCESS;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -2260,7 +1843,7 @@
  *
  *	Returns SUCCESS or FAILED.
  */
-static int
+int
 mptscsih_bus_reset(struct scsi_cmnd * SCpnt)
 {
 	MPT_SCSI_HOST	*hd;
@@ -2282,7 +1865,6 @@
 		hd->timeouts++;
 
 	/* We are now ready to execute the task management request. */
-	spin_unlock_irq(host_lock);
 	if (mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS,
 		SCpnt->device->channel, 0, 0, 0, 5 /* 5 second timeout */)
 	    < 0){
@@ -2298,7 +1880,7 @@
 		spin_lock_irq(host_lock);
 		return FAILED;
 	}
-	spin_lock_irq(host_lock);
+
 	return SUCCESS;
 }
 
@@ -2312,12 +1894,11 @@
  *
  *	Returns SUCCESS or FAILED.
  */
-static int
+int
 mptscsih_host_reset(struct scsi_cmnd *SCpnt)
 {
 	MPT_SCSI_HOST *  hd;
 	int              status = SUCCESS;
-	spinlock_t	*host_lock = SCpnt->device->host->host_lock;
 
 	/*  If we can't locate the host to reset, then we failed. */
 	if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){
@@ -2333,7 +1914,6 @@
 	/*  If our attempts to reset the host failed, then return a failed
 	 *  status.  The host will be taken off line by the SCSI mid-layer.
 	 */
-	spin_unlock_irq(host_lock);
 	if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0){
 		status = FAILED;
 	} else {
@@ -2343,8 +1923,6 @@
 		hd->tmPending = 0;
 		hd->tmState = TM_STATE_NONE;
 	}
-	spin_lock_irq(host_lock);
-
 
 	dtmprintk( ( KERN_WARNING MYNAM ": mptscsih_host_reset: "
 		     "Status = %s\n",
@@ -2426,7 +2004,7 @@
  *
  *	Returns 1 indicating alloc'd request frame ptr should be freed.
  */
-static int
+int
 mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 {
 	SCSITaskMgmtReply_t	*pScsiTmReply;
@@ -2509,7 +2087,7 @@
 /*
  *	This is anyones guess quite frankly.
  */
-static int
+int
 mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev,
 		sector_t capacity, int geom[])
 {
@@ -2556,7 +2134,7 @@
  *	Return non-zero if allocation fails.
  *	Init memory once per id (not LUN).
  */
-static int
+int
 mptscsih_slave_alloc(struct scsi_device *device)
 {
 	struct Scsi_Host	*host = device->host;
@@ -2599,7 +2177,8 @@
 	return 0;
 }
 
-static int mptscsih_is_raid_volume(MPT_SCSI_HOST *hd, uint id)
+static int 
+mptscsih_is_raid_volume(MPT_SCSI_HOST *hd, uint id)
 {
 	int i;
 
@@ -2618,7 +2197,7 @@
  *	OS entry point to allow for host driver to free allocated memory
  *	Called if no device present or device being unloaded
  */
-static void
+void
 mptscsih_slave_destroy(struct scsi_device *device)
 {
 	struct Scsi_Host	*host = device->host;
@@ -2639,7 +2218,7 @@
 
 	kfree(hd->Targets[target]);
 	hd->Targets[target] = NULL;
-	
+
 	if (hd->ioc->bus_type == SCSI) {
 		if (mptscsih_is_raid_volume(hd, target)) {
 			hd->ioc->spi_data.forceDv |= MPT_SCSICFG_RELOAD_IOC_PG3;
@@ -2695,7 +2274,7 @@
  *	member to 1 if a device does not support Q tags.
  *	Return non-zero if fails.
  */
-static int
+int
 mptscsih_slave_configure(struct scsi_device *device)
 {
 	struct Scsi_Host	*sh = device->host;
@@ -2758,8 +2337,8 @@
 	return 0;
 }
 
-static ssize_t
-mptscsih_store_queue_depth(struct device *dev, const char *buf, size_t count)
+ssize_t
+mptscsih_store_queue_depth(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	int			 depth;
 	struct scsi_device	*sdev = to_scsi_device(dev);
@@ -2788,7 +2367,7 @@
  *
  */
 static void
-copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
+mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply)
 {
 	VirtDevice	*target;
 	SCSIIORequest_t	*pReq;
@@ -2854,7 +2433,7 @@
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int
+int
 mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 {
 	MPT_SCSI_HOST	*hd;
@@ -2949,8 +2528,8 @@
 			 */
 			hd->pLocal = &hd->localReply;
 			hd->pLocal->completion = MPT_SCANDV_DID_RESET;
-			scandv_wait_done = 1;
-			wake_up(&scandv_waitq);
+			hd->scandv_wait_done = 1;
+			wake_up(&hd->scandv_waitq);
 			hd->cmdPtr = NULL;
 		}
 
@@ -2969,7 +2548,7 @@
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int
+int
 mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 {
 	MPT_SCSI_HOST *hd;
@@ -3085,42 +2664,6 @@
 	return 1;		/* currently means nothing really */
 }
 
-static struct device_attribute mptscsih_queue_depth_attr = {
-	.attr = {
-		.name = 	"queue_depth",
-		.mode =		S_IWUSR,
-	},
-	.store = mptscsih_store_queue_depth,
-};
-
-static struct device_attribute *mptscsih_dev_attrs[] = {
-	&mptscsih_queue_depth_attr,
-	NULL,
-};
-
-static struct scsi_host_template driver_template = {
-	.proc_name			= "mptscsih",
-	.proc_info			= mptscsih_proc_info,
-	.name				= "MPT SCSI Host",
-	.info				= mptscsih_info,
-	.queuecommand			= mptscsih_qcmd,
-	.slave_alloc			= mptscsih_slave_alloc,
-	.slave_configure		= mptscsih_slave_configure,
-	.slave_destroy			= mptscsih_slave_destroy,
-	.eh_abort_handler		= mptscsih_abort,
-	.eh_device_reset_handler	= mptscsih_dev_reset,
-	.eh_bus_reset_handler		= mptscsih_bus_reset,
-	.eh_host_reset_handler		= mptscsih_host_reset,
-	.bios_param			= mptscsih_bios_param,
-	.can_queue			= MPT_SCSI_CAN_QUEUE,
-	.this_id			= -1,
-	.sg_tablesize			= MPT_SCSI_SG_DEPTH,
-	.max_sectors			= 8192,
-	.cmd_per_lun			= 7,
-	.use_clustering			= ENABLE_CLUSTERING,
-	.sdev_attrs			= mptscsih_dev_attrs,
-};
-
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
  *	mptscsih_initTarget - Target, LUN alloc/free functionality.
@@ -3158,9 +2701,9 @@
 	 * around a bug in th emid-layer in some distributions in which the mid-layer will
 	 * continue to try to communicate to the LUN and evntually create a dummy LUN.
 	*/
-	if (mpt_pq_filter && dlen && (data[0] & 0xE0))
+	if (hd->mpt_pq_filter && dlen && (data[0] & 0xE0))
 		data[0] |= 0x40;
-	
+
 	/* Is LUN supported? If so, upper 2 bits will be 0
 	* in first byte of inquiry data.
 	*/
@@ -3307,7 +2850,7 @@
 				ddvtprintk((KERN_INFO "Enabling QAS on id=%d due to ~TARGET_FLAGS_VALID_56!\n", id));
 				noQas = 0;
 			}
-				
+
 			offset = pspi_data->maxSyncOffset;
 
 			/* If RAID, never disable QAS
@@ -3401,7 +2944,7 @@
 				if ( (vdev = hd->Targets[ii]) ) {
 					vdev->negoFlags |= MPT_TARGET_NO_NEGO_QAS;
 					mptscsih_writeSDP1(hd, 0, ii, vdev->negoFlags);
-				}	
+				}
 			}
 		}
 	}
@@ -3426,14 +2969,15 @@
  * Tapes, initTarget will set this flag on completion of Inquiry command.
  * Called only if DV_NOT_DONE flag is set
  */
-static void mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
+static void
+mptscsih_set_dvflags(MPT_SCSI_HOST *hd, SCSIIORequest_t *pReq)
 {
 	u8 cmd;
 	ScsiCfgData *pSpi;
 
 	ddvtprintk((" set_dvflags: id=%d lun=%d negoNvram=%x cmd=%x\n", 
 		pReq->TargetID, pReq->LUN[1], hd->negoNvram, pReq->CDB[0]));
-	
+
 	if ((pReq->LUN[1] != 0) || (hd->negoNvram != 0))
 		return;
 
@@ -3464,7 +3008,8 @@
  * If no Target, bus reset on 1st I/O. Set the flag to
  * prevent any future negotiations to this device.
  */
-static void mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id)
+static void
+mptscsih_no_negotiate(MPT_SCSI_HOST *hd, int target_id)
 {
 
 	if ((hd->Targets) && (hd->Targets[target_id] == NULL))
@@ -3631,7 +3176,7 @@
 			offset = pTarget->maxOffset;
 			negoFlags = pTarget->negoFlags;
 		}
-		
+
 #ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
 		/* Force to async and narrow if DV has not been executed
 		 * for this ID
@@ -3653,7 +3198,7 @@
 
 		/* Get a MF for this command.
 		 */
-		if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc)) == NULL) {
+		if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
 			dprintk((MYIOC_s_WARN_FMT "write SDP1: no msg frames!\n",
 						ioc->name));
 			return -EAGAIN;
@@ -3717,7 +3262,7 @@
 				ioc->name, id, (id | (bus<<8)),
 				requested, configuration));
 
-		mpt_put_msg_frame(ScsiDoneCtx, ioc, mf);
+		mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
 	}
 
 	return 0;
@@ -3748,7 +3293,7 @@
 
 	/* Get a MF for this command.
 	 */
-	if ((mf = mpt_get_msg_frame(ScsiDoneCtx, ioc)) == NULL) {
+	if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) {
 		dprintk((MYIOC_s_WARN_FMT "writeIOCPage4 : no msg frames!\n",
 					ioc->name));
 		return -EAGAIN;
@@ -3794,7 +3339,7 @@
 		"writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n",
 			ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, target_id, bus));
 
-	mpt_put_msg_frame(ScsiDoneCtx, ioc, mf);
+	mpt_put_msg_frame(ioc->DoneCtx, ioc, mf);
 
 	return 0;
 }
@@ -3824,7 +3369,7 @@
  *	in the IOC member localReply structure.
  *	Used ONLY for DV and other internal commands.
  */
-static int
+int
 mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
 {
 	MPT_SCSI_HOST	*hd;
@@ -3832,6 +3377,8 @@
 	int		 completionCode;
 	u16		 req_idx;
 
+	hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
+
 	if ((mf == NULL) ||
 	    (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) {
 		printk(MYIOC_s_ERR_FMT
@@ -3840,7 +3387,6 @@
 		goto wakeup;
 	}
 
-	hd = (MPT_SCSI_HOST *) ioc->sh->hostdata;
 	del_timer(&hd->timer);
 	req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx);
 	hd->ScsiLookup[req_idx] = NULL;
@@ -3972,8 +3518,8 @@
 	/*
 	 * Wake up the original calling thread
 	 */
-	scandv_wait_done = 1;
-	wake_up(&scandv_waitq);
+	hd->scandv_wait_done = 1;
+	wake_up(&hd->scandv_waitq);
 
 	return 1;
 }
@@ -3984,7 +3530,8 @@
  *	@data: Pointer to MPT_SCSI_HOST recast as an unsigned long
  *
  */
-static void mptscsih_timer_expired(unsigned long data)
+void
+mptscsih_timer_expired(unsigned long data)
 {
 	MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data;
 
@@ -4051,7 +3598,7 @@
 
 	/* Get and Populate a free Frame
 	 */
-	if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc)) == NULL) {
+	if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
 		ddvprintk((MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n",
 					hd->ioc->name));
 		return -EAGAIN;
@@ -4077,7 +3624,7 @@
 
 	hd->pLocal = NULL;
 	hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */
-	scandv_wait_done = 0;
+	hd->scandv_wait_done = 0;
 
 	/* Save cmd pointer, for resource free if timeout or
 	 * FW reload occurs
@@ -4085,8 +3632,8 @@
 	hd->cmdPtr = mf;
 
 	add_timer(&hd->timer);
-	mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc, mf);
-	wait_event(scandv_waitq, scandv_wait_done);
+	mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
+	wait_event(hd->scandv_waitq, hd->scandv_wait_done);
 
 	if ((hd->pLocal == NULL) || (hd->pLocal->completion != MPT_SCANDV_GOOD))
 		return -1;
@@ -4232,7 +3779,7 @@
 
 	/* Get and Populate a free Frame
 	 */
-	if ((mf = mpt_get_msg_frame(ScsiScanDvCtx, hd->ioc)) == NULL) {
+	if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) {
 		ddvprintk((MYIOC_s_WARN_FMT "No msg frames!\n",
 					hd->ioc->name));
 		return -EBUSY;
@@ -4314,7 +3861,7 @@
 	 */
 	hd->pLocal = NULL;
 	hd->timer.expires = jiffies + HZ*cmdTimeout;
-	scandv_wait_done = 0;
+	hd->scandv_wait_done = 0;
 
 	/* Save cmd pointer, for resource free if timeout or
 	 * FW reload occurs
@@ -4322,8 +3869,8 @@
 	hd->cmdPtr = mf;
 
 	add_timer(&hd->timer);
-	mpt_put_msg_frame(ScsiScanDvCtx, hd->ioc, mf);
-	wait_event(scandv_waitq, scandv_wait_done);
+	mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf);
+	wait_event(hd->scandv_waitq, hd->scandv_wait_done);
 
 	if (hd->pLocal) {
 		rc = hd->pLocal->completion;
@@ -4640,7 +4187,8 @@
 
 /* Search IOC page 3 to determine if this is hidden physical disk
  */
-static int mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
+static int 
+mptscsih_is_phys_disk(MPT_ADAPTER *ioc, int id)
 {
 	if (ioc->spi_data.pIocPg3) {
 		Ioc3PhysDisk_t *pPDisk =  ioc->spi_data.pIocPg3->PhysDisk;
@@ -4659,7 +4207,8 @@
 
 /* Write SDP1 if no QAS has been enabled
  */
-static void mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
+static void
+mptscsih_qas_check(MPT_SCSI_HOST *hd, int id)
 {
 	VirtDevice *pTarget;
 	int ii;
@@ -5157,7 +4706,7 @@
 	}
 	ddvprintk((MYIOC_s_NOTE_FMT "DV: Basic test on id=%d completed OK.\n", ioc->name, id));
 
-	if (mpt_dv == 0)
+	if (ioc->spi_data.mpt_dv == 0)
 		goto target_done;
 
 	inq0 = (*pbuf1) & 0x1F;
@@ -6015,7 +5564,29 @@
 }
 #endif /* ~MPTSCSIH_ENABLE_DOMAIN_VALIDATION */
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+EXPORT_SYMBOL(mptscsih_remove);
+EXPORT_SYMBOL(mptscsih_shutdown);
+#ifdef CONFIG_PM
+EXPORT_SYMBOL(mptscsih_suspend);
+EXPORT_SYMBOL(mptscsih_resume);
+#endif
+EXPORT_SYMBOL(mptscsih_proc_info);
+EXPORT_SYMBOL(mptscsih_info);
+EXPORT_SYMBOL(mptscsih_qcmd);
+EXPORT_SYMBOL(mptscsih_slave_alloc);
+EXPORT_SYMBOL(mptscsih_slave_destroy);
+EXPORT_SYMBOL(mptscsih_slave_configure);
+EXPORT_SYMBOL(mptscsih_abort);
+EXPORT_SYMBOL(mptscsih_dev_reset);
+EXPORT_SYMBOL(mptscsih_bus_reset);
+EXPORT_SYMBOL(mptscsih_host_reset);
+EXPORT_SYMBOL(mptscsih_bios_param);
+EXPORT_SYMBOL(mptscsih_io_done);
+EXPORT_SYMBOL(mptscsih_taskmgmt_complete);
+EXPORT_SYMBOL(mptscsih_scandv_complete);
+EXPORT_SYMBOL(mptscsih_event_process);
+EXPORT_SYMBOL(mptscsih_ioc_reset);
+EXPORT_SYMBOL(mptscsih_store_queue_depth);
+EXPORT_SYMBOL(mptscsih_timer_expired);
 
-module_init(mptscsih_init);
-module_exit(mptscsih_exit);
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h
index 5cb2fd4..d73aec3 100644
--- a/drivers/message/fusion/mptscsih.h
+++ b/drivers/message/fusion/mptscsih.h
@@ -1,26 +1,13 @@
 /*
- *  linux/drivers/message/fusion/mptscsih.h
+ *  linux/drivers/message/fusion/mptscsi.h
  *      High performance SCSI / Fibre Channel SCSI Host device driver.
  *      For use with PCI chip/adapter(s):
  *          LSIFC9xx/LSI409xx Fibre Channel
  *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
  *
- *  Credits:
- *      This driver would not exist if not for Alan Cox's development
- *      of the linux i2o driver.
- *
- *      A huge debt of gratitude is owed to David S. Miller (DaveM)
- *      for fixing much of the stupid and broken stuff in the early
- *      driver while porting to sparc64 platform.  THANK YOU!
- *
- *      (see also mptbase.c)
- *
- *  Copyright (c) 1999-2004 LSI Logic Corporation
- *  Originally By: Steven J. Ralston
- *  (mailto:netscape.net)
+ *  Copyright (c) 1999-2005 LSI Logic Corporation
  *  (mailto:mpt_linux_developer@lsil.com)
  *
- *  $Id: mptscsih.h,v 1.21 2002/12/03 21:26:35 pdelaney Exp $
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -91,4 +78,30 @@
 #define MPTSCSIH_MIN_SYNC               0x08
 #define MPTSCSIH_SAF_TE                 0
 
+
 #endif
+
+extern void mptscsih_remove(struct pci_dev *);
+extern void mptscsih_shutdown(struct device *);
+#ifdef CONFIG_PM
+extern int mptscsih_suspend(struct pci_dev *pdev, u32 state);
+extern int mptscsih_resume(struct pci_dev *pdev);
+#endif
+extern int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func);
+extern const char * mptscsih_info(struct Scsi_Host *SChost);
+extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *));
+extern int mptscsih_slave_alloc(struct scsi_device *device);
+extern void mptscsih_slave_destroy(struct scsi_device *device);
+extern int mptscsih_slave_configure(struct scsi_device *device);
+extern int mptscsih_abort(struct scsi_cmnd * SCpnt);
+extern int mptscsih_dev_reset(struct scsi_cmnd * SCpnt);
+extern int mptscsih_bus_reset(struct scsi_cmnd * SCpnt);
+extern int mptscsih_host_reset(struct scsi_cmnd *SCpnt);
+extern int mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, sector_t capacity, int geom[]);
+extern int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
+extern int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
+extern int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
+extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
+extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
+extern ssize_t mptscsih_store_queue_depth(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+extern void mptscsih_timer_expired(unsigned long data);
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
new file mode 100644
index 0000000..5f9a61b
--- /dev/null
+++ b/drivers/message/fusion/mptspi.c
@@ -0,0 +1,486 @@
+/*
+ *  linux/drivers/message/fusion/mptspi.c
+ *      For use with LSI Logic PCI chip/adapter(s)
+ *      running LSI Logic Fusion MPT (Message Passing Technology) firmware.
+ *
+ *  Copyright (c) 1999-2005 LSI Logic Corporation
+ *  (mailto:mpt_linux_developer@lsil.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; 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.
+
+    NO WARRANTY
+    THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+    CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+    LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+    MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+    solely responsible for determining the appropriateness of using and
+    distributing the Program and assumes all risks associated with its
+    exercise of rights under this Agreement, including but not limited to
+    the risks and costs of program errors, damage to or loss of data,
+    programs or equipment, and unavailability or interruption of operations.
+
+    DISCLAIMER OF LIABILITY
+    NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+    HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+    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_compat.h"	/* linux-2.6 tweaks */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/kdev_t.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>	/* for mdelay */
+#include <linux/interrupt.h>	/* needed for in_interrupt() proto */
+#include <linux/reboot.h>	/* notifier code */
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+
+#include "mptbase.h"
+#include "mptscsih.h"
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+#define my_NAME		"Fusion MPT SPI Host driver"
+#define my_VERSION	MPT_LINUX_VERSION_COMMON
+#define MYNAM		"mptspi"
+
+MODULE_AUTHOR(MODULEAUTHOR);
+MODULE_DESCRIPTION(my_NAME);
+MODULE_LICENSE("GPL");
+
+/* Command line args */
+#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
+static int mpt_dv = MPTSCSIH_DOMAIN_VALIDATION;
+module_param(mpt_dv, int, 0);
+MODULE_PARM_DESC(mpt_dv, " DV Algorithm: enhanced=1, basic=0 (default=MPTSCSIH_DOMAIN_VALIDATION=1)");
+
+static int mpt_width = MPTSCSIH_MAX_WIDTH;
+module_param(mpt_width, int, 0);
+MODULE_PARM_DESC(mpt_width, " Max Bus Width: wide=1, narrow=0 (default=MPTSCSIH_MAX_WIDTH=1)");
+
+static ushort mpt_factor = MPTSCSIH_MIN_SYNC;
+module_param(mpt_factor, ushort, 0);
+MODULE_PARM_DESC(mpt_factor, " Min Sync Factor (default=MPTSCSIH_MIN_SYNC=0x08)");
+#endif
+
+static int mpt_saf_te = MPTSCSIH_SAF_TE;
+module_param(mpt_saf_te, int, 0);
+MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1  (default=MPTSCSIH_SAF_TE=0)");
+
+static int mpt_pq_filter = 0;
+module_param(mpt_pq_filter, int, 0);
+MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1  (default=0)");
+
+static int	mptspiDoneCtx = -1;
+static int	mptspiTaskCtx = -1;
+static int	mptspiInternalCtx = -1; /* Used only for internal commands */
+
+static struct device_attribute mptspi_queue_depth_attr = {
+	.attr = {
+		.name = 	"queue_depth",
+		.mode =		S_IWUSR,
+	},
+	.store = mptscsih_store_queue_depth,
+};
+
+static struct device_attribute *mptspi_dev_attrs[] = {
+	&mptspi_queue_depth_attr,
+	NULL,
+};
+
+static struct scsi_host_template mptspi_driver_template = {
+	.proc_name			= "mptspi",
+	.proc_info			= mptscsih_proc_info,
+	.name				= "MPT SPI Host",
+	.info				= mptscsih_info,
+	.queuecommand			= mptscsih_qcmd,
+	.slave_alloc			= mptscsih_slave_alloc,
+	.slave_configure		= mptscsih_slave_configure,
+	.slave_destroy			= mptscsih_slave_destroy,
+	.eh_abort_handler		= mptscsih_abort,
+	.eh_device_reset_handler	= mptscsih_dev_reset,
+	.eh_bus_reset_handler		= mptscsih_bus_reset,
+	.eh_host_reset_handler		= mptscsih_host_reset,
+	.bios_param			= mptscsih_bios_param,
+	.can_queue			= MPT_SCSI_CAN_QUEUE,
+	.this_id			= -1,
+	.sg_tablesize			= MPT_SCSI_SG_DEPTH,
+	.max_sectors			= 8192,
+	.cmd_per_lun			= 7,
+	.use_clustering			= ENABLE_CLUSTERING,
+	.sdev_attrs			= mptspi_dev_attrs,
+};
+
+
+/****************************************************************************
+ * Supported hardware
+ */
+
+static struct pci_device_id mptspi_pci_table[] = {
+	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1030,
+		PCI_ANY_ID, PCI_ANY_ID },
+	{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_1030_53C1035,
+		PCI_ANY_ID, PCI_ANY_ID },
+	{0}	/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, mptspi_pci_table);
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	mptspi_probe - Installs scsi devices per bus.
+ *	@pdev: Pointer to pci_dev structure
+ *
+ *	Returns 0 for success, non-zero for failure.
+ *
+ */
+static int
+mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct Scsi_Host	*sh;
+	MPT_SCSI_HOST		*hd;
+	MPT_ADAPTER 		*ioc;
+	unsigned long		 flags;
+	int			 sz, ii;
+	int			 numSGE = 0;
+	int			 scale;
+	int			 ioc_cap;
+	u8			*mem;
+	int			error=0;
+	int			r;
+	
+	if ((r = mpt_attach(pdev,id)) != 0)
+		return r;
+	
+	ioc = pci_get_drvdata(pdev);
+	ioc->DoneCtx = mptspiDoneCtx;
+	ioc->TaskCtx = mptspiTaskCtx;
+	ioc->InternalCtx = mptspiInternalCtx;
+	
+	/*  Added sanity check on readiness of the MPT adapter.
+	 */
+	if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
+		printk(MYIOC_s_WARN_FMT
+		  "Skipping because it's not operational!\n",
+		  ioc->name);
+		return -ENODEV;
+	}
+
+	if (!ioc->active) {
+		printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
+		  ioc->name);
+		return -ENODEV;
+	}
+
+	/*  Sanity check - ensure at least 1 port is INITIATOR capable
+	 */
+	ioc_cap = 0;
+	for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
+		if (ioc->pfacts[ii].ProtocolFlags &
+		    MPI_PORTFACTS_PROTOCOL_INITIATOR)
+			ioc_cap ++;
+	}
+
+	if (!ioc_cap) {
+		printk(MYIOC_s_WARN_FMT
+			"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
+			ioc->name, ioc);
+		return -ENODEV;
+	}
+
+	sh = scsi_host_alloc(&mptspi_driver_template, sizeof(MPT_SCSI_HOST));
+
+	if (!sh) {
+		printk(MYIOC_s_WARN_FMT
+			"Unable to register controller with SCSI subsystem\n",
+			ioc->name);
+                return -1;
+        }
+
+	spin_lock_irqsave(&ioc->FreeQlock, flags);
+
+	/* Attach the SCSI Host to the IOC structure
+	 */
+	ioc->sh = sh;
+
+	sh->io_port = 0;
+	sh->n_io_port = 0;
+	sh->irq = 0;
+
+	/* set 16 byte cdb's */
+	sh->max_cmd_len = 16;
+
+	/* Yikes!  This is important!
+	 * Otherwise, by default, linux
+	 * only scans target IDs 0-7!
+	 * pfactsN->MaxDevices unreliable
+	 * (not supported in early
+	 *	versions of the FW).
+	 * max_id = 1 + actual max id,
+	 * max_lun = 1 + actual last lun,
+	 *	see hosts.h :o(
+	 */
+	sh->max_id = MPT_MAX_SCSI_DEVICES;
+
+	sh->max_lun = MPT_LAST_LUN + 1;
+	sh->max_channel = 0;
+	sh->this_id = ioc->pfacts[0].PortSCSIID;
+
+	/* Required entry.
+	 */
+	sh->unique_id = ioc->id;
+
+	/* Verify that we won't exceed the maximum
+	 * number of chain buffers
+	 * We can optimize:  ZZ = req_sz/sizeof(SGE)
+	 * For 32bit SGE's:
+	 *  numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
+	 *               + (req_sz - 64)/sizeof(SGE)
+	 * A slightly different algorithm is required for
+	 * 64bit SGEs.
+	 */
+	scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
+	if (sizeof(dma_addr_t) == sizeof(u64)) {
+		numSGE = (scale - 1) *
+		  (ioc->facts.MaxChainDepth-1) + scale +
+		  (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
+		  sizeof(u32));
+	} else {
+		numSGE = 1 + (scale - 1) *
+		  (ioc->facts.MaxChainDepth-1) + scale +
+		  (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
+		  sizeof(u32));
+	}
+
+	if (numSGE < sh->sg_tablesize) {
+		/* Reset this value */
+		dprintk((MYIOC_s_INFO_FMT
+		  "Resetting sg_tablesize to %d from %d\n",
+		  ioc->name, numSGE, sh->sg_tablesize));
+		sh->sg_tablesize = numSGE;
+	}
+
+	/* Set the pci device pointer in Scsi_Host structure.
+	 */
+	scsi_set_device(sh, &ioc->pcidev->dev);
+
+	spin_unlock_irqrestore(&ioc->FreeQlock, flags);
+
+	hd = (MPT_SCSI_HOST *) sh->hostdata;
+	hd->ioc = ioc;
+
+	/* SCSI needs scsi_cmnd lookup table!
+	 * (with size equal to req_depth*PtrSz!)
+	 */
+	sz = ioc->req_depth * sizeof(void *);
+	mem = kmalloc(sz, GFP_ATOMIC);
+	if (mem == NULL) {
+		error = -ENOMEM;
+		goto mptspi_probe_failed;
+	}
+
+	memset(mem, 0, sz);
+	hd->ScsiLookup = (struct scsi_cmnd **) mem;
+
+	dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
+		 ioc->name, hd->ScsiLookup, sz));
+
+	/* Allocate memory for the device structures.
+	 * A non-Null pointer at an offset
+	 * indicates a device exists.
+	 * max_id = 1 + maximum id (hosts.h)
+	 */
+	sz = sh->max_id * sizeof(void *);
+	mem = kmalloc(sz, GFP_ATOMIC);
+	if (mem == NULL) {
+		error = -ENOMEM;
+		goto mptspi_probe_failed;
+	}
+
+	memset(mem, 0, sz);
+	hd->Targets = (VirtDevice **) mem;
+
+	dprintk((KERN_INFO
+	  "  Targets @ %p, sz=%d\n", hd->Targets, sz));
+
+	/* Clear the TM flags
+	 */
+	hd->tmPending = 0;
+	hd->tmState = TM_STATE_NONE;
+	hd->resetPending = 0;
+	hd->abortSCpnt = NULL;
+
+	/* Clear the pointer used to store
+	 * single-threaded commands, i.e., those
+	 * issued during a bus scan, dv and
+	 * configuration pages.
+	 */
+	hd->cmdPtr = NULL;
+
+	/* Initialize this SCSI Hosts' timers
+	 * To use, set the timer expires field
+	 * and add_timer
+	 */
+	init_timer(&hd->timer);
+	hd->timer.data = (unsigned long) hd;
+	hd->timer.function = mptscsih_timer_expired;
+
+	ioc->spi_data.Saf_Te = mpt_saf_te;
+	hd->mpt_pq_filter = mpt_pq_filter;
+
+#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
+	if (ioc->spi_data.maxBusWidth > mpt_width)
+		ioc->spi_data.maxBusWidth = mpt_width;
+	if (ioc->spi_data.minSyncFactor < mpt_factor)
+		ioc->spi_data.minSyncFactor = mpt_factor;
+	if (ioc->spi_data.minSyncFactor == MPT_ASYNC) {
+		ioc->spi_data.maxSyncOffset = 0;
+	}
+	ioc->spi_data.mpt_dv = mpt_dv;
+	hd->negoNvram = 0;
+
+	ddvprintk((MYIOC_s_INFO_FMT
+		"dv %x width %x factor %x saf_te %x mpt_pq_filter %x\n",
+		ioc->name,
+		mpt_dv,
+		mpt_width,
+		mpt_factor,
+		mpt_saf_te,
+		mpt_pq_filter));
+#else
+	hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
+	ddvprintk((MYIOC_s_INFO_FMT
+		"saf_te %x mpt_pq_filter %x\n",
+		ioc->name,
+		mpt_saf_te,
+		mpt_pq_filter));
+#endif
+
+	ioc->spi_data.forceDv = 0;
+	ioc->spi_data.noQas = 0;
+
+	for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
+		ioc->spi_data.dvStatus[ii] =
+		  MPT_SCSICFG_NEGOTIATE;
+
+	for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
+		ioc->spi_data.dvStatus[ii] |=
+		  MPT_SCSICFG_DV_NOT_DONE;
+
+	init_waitqueue_head(&hd->scandv_waitq);
+	hd->scandv_wait_done = 0;
+	hd->last_queue_full = 0;
+
+	error = scsi_add_host (sh, &ioc->pcidev->dev);
+	if(error) {
+		dprintk((KERN_ERR MYNAM
+		  "scsi_add_host failed\n"));
+		goto mptspi_probe_failed;
+	}
+
+	scsi_scan_host(sh);
+	return 0;
+
+mptspi_probe_failed:
+
+	mptscsih_remove(pdev);
+	return error;
+}
+
+static struct pci_driver mptspi_driver = {
+	.name		= "mptspi",
+	.id_table	= mptspi_pci_table,
+	.probe		= mptspi_probe,
+	.remove		= __devexit_p(mptscsih_remove),
+	.driver         = {
+		.shutdown = mptscsih_shutdown,
+        },
+#ifdef CONFIG_PM
+	.suspend	= mptscsih_suspend,
+	.resume		= mptscsih_resume,
+#endif
+};
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mptspi_init - Register MPT adapter(s) as SCSI host(s) with
+ *	linux scsi mid-layer.
+ *
+ *	Returns 0 for success, non-zero for failure.
+ */
+static int __init
+mptspi_init(void)
+{
+
+	show_mptmod_ver(my_NAME, my_VERSION);
+
+	mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER);
+	mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER);
+	mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER);
+
+	if (mpt_event_register(mptspiDoneCtx, mptscsih_event_process) == 0) {
+		devtprintk((KERN_INFO MYNAM
+		  ": Registered for IOC event notifications\n"));
+	}
+
+	if (mpt_reset_register(mptspiDoneCtx, mptscsih_ioc_reset) == 0) {
+		dprintk((KERN_INFO MYNAM
+		  ": Registered for IOC reset notifications\n"));
+	}
+
+	return pci_register_driver(&mptspi_driver);
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *	mptspi_exit - Unregisters MPT adapter(s)
+ *
+ */
+static void __exit
+mptspi_exit(void)
+{
+	pci_unregister_driver(&mptspi_driver);
+	
+	mpt_reset_deregister(mptspiDoneCtx);
+	dprintk((KERN_INFO MYNAM
+	  ": Deregistered for IOC reset notifications\n"));
+
+	mpt_event_deregister(mptspiDoneCtx);
+	dprintk((KERN_INFO MYNAM
+	  ": Deregistered for IOC event notifications\n"));
+
+	mpt_deregister(mptspiInternalCtx);
+	mpt_deregister(mptspiTaskCtx);
+	mpt_deregister(mptspiDoneCtx);
+}
+
+module_init(mptspi_init);
+module_exit(mptspi_exit);
diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig
index 8d132b0..06e8eb1 100644
--- a/drivers/message/i2o/Kconfig
+++ b/drivers/message/i2o/Kconfig
@@ -24,10 +24,28 @@
 
 	  If unsure, say N.
 
+config I2O_EXT_ADAPTEC
+	bool "Enable Adaptec extensions"
+	depends on I2O
+	default y
+	---help---
+	  Say Y for support of raidutils for Adaptec I2O controllers. You also
+	  have to say Y to "I2O Configuration support", "I2O SCSI OSM" below
+	  and to "SCSI generic support" under "SCSI device configuration".
+
+config I2O_EXT_ADAPTEC_DMA64
+	bool "Enable 64-bit DMA"
+	depends on I2O_EXT_ADAPTEC && ( 64BIT || HIGHMEM64G )
+	default y
+	---help---
+	  Say Y for support of 64-bit DMA transfer mode on Adaptec I2O
+	  controllers.
+	  Note: You need at least firmware version 3709.
+
 config I2O_CONFIG
 	tristate "I2O Configuration support"
-	depends on PCI && I2O
-	help
+	depends on I2O
+	---help---
 	  Say Y for support of the configuration interface for the I2O adapters.
 	  If you have a RAID controller from Adaptec and you want to use the
 	  raidutils to manage your RAID array, you have to say Y here.
@@ -35,10 +53,28 @@
 	  To compile this support as a module, choose M here: the
 	  module will be called i2o_config.
 
+config I2O_CONFIG_OLD_IOCTL
+	bool "Enable ioctls (OBSOLETE)"
+	depends on I2O_CONFIG
+	default y
+	---help---
+	  Enables old ioctls.
+
+config I2O_BUS
+	tristate "I2O Bus Adapter OSM"
+	depends on I2O
+	---help---
+	  Include support for the I2O Bus Adapter OSM. The Bus Adapter OSM
+	  provides access to the busses on the I2O controller. The main purpose
+	  is to rescan the bus to find new devices.
+
+	  To compile this support as a module, choose M here: the
+	  module will be called i2o_bus.
+
 config I2O_BLOCK
 	tristate "I2O Block OSM"
 	depends on I2O
-	help
+	---help---
 	  Include support for the I2O Block OSM. The Block OSM presents disk
 	  and other structured block devices to the operating system. If you
 	  are using an RAID controller, you could access the array only by
@@ -51,7 +87,7 @@
 config I2O_SCSI
 	tristate "I2O SCSI OSM"
 	depends on I2O && SCSI
-	help
+	---help---
 	  Allows direct SCSI access to SCSI devices on a SCSI or FibreChannel
 	  I2O controller. You can use both the SCSI and Block OSM together if
 	  you wish. To access a RAID array, you must use the Block OSM driver.
@@ -63,7 +99,7 @@
 config I2O_PROC
 	tristate "I2O /proc support"
 	depends on I2O
-	help
+	---help---
 	  If you say Y here and to "/proc file system support", you will be
 	  able to read I2O related information from the virtual directory
 	  /proc/i2o.
diff --git a/drivers/message/i2o/Makefile b/drivers/message/i2o/Makefile
index aabc6cd..2c2e39a 100644
--- a/drivers/message/i2o/Makefile
+++ b/drivers/message/i2o/Makefile
@@ -6,8 +6,11 @@
 #
 
 i2o_core-y		+= iop.o driver.o device.o debug.o pci.o exec-osm.o
+i2o_bus-y		+= bus-osm.o
+i2o_config-y		+= config-osm.o
 obj-$(CONFIG_I2O)	+= i2o_core.o
 obj-$(CONFIG_I2O_CONFIG)+= i2o_config.o
+obj-$(CONFIG_I2O_BUS)	+= i2o_bus.o
 obj-$(CONFIG_I2O_BLOCK)	+= i2o_block.o
 obj-$(CONFIG_I2O_SCSI)	+= i2o_scsi.o
 obj-$(CONFIG_I2O_PROC)	+= i2o_proc.o
diff --git a/drivers/message/i2o/bus-osm.c b/drivers/message/i2o/bus-osm.c
new file mode 100644
index 0000000..151b228
--- /dev/null
+++ b/drivers/message/i2o/bus-osm.c
@@ -0,0 +1,164 @@
+/*
+ *	Bus Adapter OSM
+ *
+ *	Copyright (C) 2005	Markus Lidel <Markus.Lidel@shadowconnect.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.
+ *
+ *	Fixes/additions:
+ *		Markus Lidel <Markus.Lidel@shadowconnect.com>
+ *			initial version.
+ */
+
+#include <linux/module.h>
+#include <linux/i2o.h>
+
+#define OSM_NAME	"bus-osm"
+#define OSM_VERSION	"$Rev$"
+#define OSM_DESCRIPTION	"I2O Bus Adapter OSM"
+
+static struct i2o_driver i2o_bus_driver;
+
+/* Bus OSM class handling definition */
+static struct i2o_class_id i2o_bus_class_id[] = {
+	{I2O_CLASS_BUS_ADAPTER},
+	{I2O_CLASS_END}
+};
+
+/**
+ *	i2o_bus_scan - Scan the bus for new devices
+ *	@dev: I2O device of the bus, which should be scanned
+ *
+ *	Scans the bus dev for new / removed devices. After the scan a new LCT
+ *	will be fetched automatically.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int i2o_bus_scan(struct i2o_device *dev)
+{
+	struct i2o_message __iomem *msg;
+	u32 m;
+
+	m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -ETIMEDOUT;
+
+	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
+	writel(I2O_CMD_BUS_SCAN << 24 | HOST_TID << 12 | dev->lct_data.tid,
+	       &msg->u.head[1]);
+
+	return i2o_msg_post_wait(dev->iop, m, 60);
+};
+
+/**
+ *	i2o_bus_store_scan - Scan the I2O Bus Adapter
+ *	@d: device which should be scanned
+ *
+ *	Returns count.
+ */
+static ssize_t i2o_bus_store_scan(struct device *d, struct device_attribute *attr, const char *buf,
+				  size_t count)
+{
+	struct i2o_device *i2o_dev = to_i2o_device(d);
+	int rc;
+
+	if ((rc = i2o_bus_scan(i2o_dev)))
+		osm_warn("bus scan failed %d\n", rc);
+
+	return count;
+}
+
+/* Bus Adapter OSM device attributes */
+static DEVICE_ATTR(scan, S_IWUSR, NULL, i2o_bus_store_scan);
+
+/**
+ *	i2o_bus_probe - verify if dev is a I2O Bus Adapter device and install it
+ *	@dev: device to verify if it is a I2O Bus Adapter device
+ *
+ *	Because we want all Bus Adapters always return 0.
+ *
+ *	Returns 0.
+ */
+static int i2o_bus_probe(struct device *dev)
+{
+	struct i2o_device *i2o_dev = to_i2o_device(get_device(dev));
+
+	device_create_file(dev, &dev_attr_scan);
+
+	osm_info("device added (TID: %03x)\n", i2o_dev->lct_data.tid);
+
+	return 0;
+};
+
+/**
+ *	i2o_bus_remove - remove the I2O Bus Adapter device from the system again
+ *	@dev: I2O Bus Adapter device which should be removed
+ *
+ *	Always returns 0.
+ */
+static int i2o_bus_remove(struct device *dev)
+{
+	struct i2o_device *i2o_dev = to_i2o_device(dev);
+
+	device_remove_file(dev, &dev_attr_scan);
+
+	put_device(dev);
+
+	osm_info("device removed (TID: %03x)\n", i2o_dev->lct_data.tid);
+
+	return 0;
+};
+
+/* Bus Adapter OSM driver struct */
+static struct i2o_driver i2o_bus_driver = {
+	.name = OSM_NAME,
+	.classes = i2o_bus_class_id,
+	.driver = {
+		   .probe = i2o_bus_probe,
+		   .remove = i2o_bus_remove,
+		   },
+};
+
+/**
+ *	i2o_bus_init - Bus Adapter OSM initialization function
+ *
+ *	Only register the Bus Adapter OSM in the I2O core.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int __init i2o_bus_init(void)
+{
+	int rc;
+
+	printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");
+
+	/* Register Bus Adapter OSM into I2O core */
+	rc = i2o_driver_register(&i2o_bus_driver);
+	if (rc) {
+		osm_err("Could not register Bus Adapter OSM\n");
+		return rc;
+	}
+
+	return 0;
+};
+
+/**
+ *	i2o_bus_exit - Bus Adapter OSM exit function
+ *
+ *	Unregisters Bus Adapter OSM from I2O core.
+ */
+static void __exit i2o_bus_exit(void)
+{
+	i2o_driver_unregister(&i2o_bus_driver);
+};
+
+MODULE_AUTHOR("Markus Lidel <Markus.Lidel@shadowconnect.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(OSM_DESCRIPTION);
+MODULE_VERSION(OSM_VERSION);
+
+module_init(i2o_bus_init);
+module_exit(i2o_bus_exit);
diff --git a/drivers/message/i2o/config-osm.c b/drivers/message/i2o/config-osm.c
new file mode 100644
index 0000000..d026760
--- /dev/null
+++ b/drivers/message/i2o/config-osm.c
@@ -0,0 +1,579 @@
+/*
+ *	Configuration OSM
+ *
+ *	Copyright (C) 2005	Markus Lidel <Markus.Lidel@shadowconnect.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.
+ *
+ *	Fixes/additions:
+ *		Markus Lidel <Markus.Lidel@shadowconnect.com>
+ *			initial version.
+ */
+
+#include <linux/module.h>
+#include <linux/i2o.h>
+#include <linux/namei.h>
+
+#include <asm/uaccess.h>
+
+#define OSM_NAME	"config-osm"
+#define OSM_VERSION	"1.248"
+#define OSM_DESCRIPTION	"I2O Configuration OSM"
+
+/* access mode user rw */
+#define S_IWRSR (S_IRUSR | S_IWUSR)
+
+static struct i2o_driver i2o_config_driver;
+
+/* Special file operations for sysfs */
+struct fops_attribute {
+	struct bin_attribute bin;
+	struct file_operations fops;
+};
+
+/**
+ *	sysfs_read_dummy
+ */
+static ssize_t sysfs_read_dummy(struct kobject *kobj, char *buf, loff_t offset,
+				size_t count)
+{
+	return 0;
+};
+
+/**
+ *	sysfs_write_dummy
+ */
+static ssize_t sysfs_write_dummy(struct kobject *kobj, char *buf, loff_t offset,
+				 size_t count)
+{
+	return 0;
+};
+
+/**
+ *	sysfs_create_fops_file - Creates attribute with special file operations
+ *	@kobj: kobject which should contains the attribute
+ *	@attr: attributes which should be used to create file
+ *
+ *	First creates attribute @attr in kobject @kobj. If it is the first time
+ *	this function is called, merge old fops from sysfs with new one and
+ *	write it back. Afterwords the new fops will be set for the created
+ *	attribute.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int sysfs_create_fops_file(struct kobject *kobj,
+				  struct fops_attribute *attr)
+{
+	struct file_operations tmp, *fops;
+	struct dentry *d;
+	struct qstr qstr;
+	int rc;
+
+	fops = &attr->fops;
+
+	if (fops->read)
+		attr->bin.read = sysfs_read_dummy;
+
+	if (fops->write)
+		attr->bin.write = sysfs_write_dummy;
+
+	if ((rc = sysfs_create_bin_file(kobj, &attr->bin)))
+		return rc;
+
+	qstr.name = attr->bin.attr.name;
+	qstr.len = strlen(qstr.name);
+	qstr.hash = full_name_hash(qstr.name, qstr.len);
+
+	if ((d = lookup_hash(&qstr, kobj->dentry))) {
+		if (!fops->owner) {
+			memcpy(&tmp, d->d_inode->i_fop, sizeof(tmp));
+			if (fops->read)
+				tmp.read = fops->read;
+			if (fops->write)
+				tmp.write = fops->write;
+			memcpy(fops, &tmp, sizeof(tmp));
+		}
+
+		d->d_inode->i_fop = fops;
+	} else
+		sysfs_remove_bin_file(kobj, &attr->bin);
+
+	return -ENOENT;
+};
+
+/**
+ *	sysfs_remove_fops_file - Remove attribute with special file operations
+ *	@kobj: kobject which contains the attribute
+ *	@attr: attributes which are used to create file
+ *
+ *	Only wrapper arround sysfs_remove_bin_file()
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static inline int sysfs_remove_fops_file(struct kobject *kobj,
+					 struct fops_attribute *attr)
+{
+	return sysfs_remove_bin_file(kobj, &attr->bin);
+};
+
+/**
+ *	i2o_config_read_hrt - Returns the HRT of the controller
+ *	@kob: kernel object handle
+ *	@buf: buffer into which the HRT should be copied
+ *	@off: file offset
+ *	@count: number of bytes to read
+ *
+ *	Put @count bytes starting at @off into @buf from the HRT of the I2O
+ *	controller corresponding to @kobj.
+ *
+ *	Returns number of bytes copied into buffer.
+ */
+static ssize_t i2o_config_read_hrt(struct kobject *kobj, char *buf,
+				   loff_t offset, size_t count)
+{
+	struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
+	i2o_hrt *hrt = c->hrt.virt;
+
+	u32 size = (hrt->num_entries * hrt->entry_len + 2) * 4;
+
+	if (offset > size)
+		return 0;
+
+	if (offset + count > size)
+		count = size - offset;
+
+	memcpy(buf, (u8 *) hrt + offset, count);
+
+	return count;
+};
+
+/**
+ *	i2o_config_read_lct - Returns the LCT of the controller
+ *	@kob: kernel object handle
+ *	@buf: buffer into which the LCT should be copied
+ *	@off: file offset
+ *	@count: number of bytes to read
+ *
+ *	Put @count bytes starting at @off into @buf from the LCT of the I2O
+ *	controller corresponding to @kobj.
+ *
+ *	Returns number of bytes copied into buffer.
+ */
+static ssize_t i2o_config_read_lct(struct kobject *kobj, char *buf,
+				   loff_t offset, size_t count)
+{
+	struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
+	u32 size = c->lct->table_size * 4;
+
+	if (offset > size)
+		return 0;
+
+	if (offset + count > size)
+		count = size - offset;
+
+	memcpy(buf, (u8 *) c->lct + offset, count);
+
+	return count;
+};
+
+#define I2O_CONFIG_SW_ATTR(_name,_mode,_type,_swid) \
+static ssize_t i2o_config_##_name##_read(struct file *file, char __user *buf, size_t count, loff_t * offset) { \
+	return i2o_config_sw_read(file, buf, count, offset, _type, _swid); \
+};\
+\
+static ssize_t i2o_config_##_name##_write(struct file *file, const char __user *buf, size_t count, loff_t * offset) { \
+	return i2o_config_sw_write(file, buf, count, offset, _type, _swid); \
+}; \
+\
+static struct fops_attribute i2o_config_attr_##_name = { \
+	.bin = { .attr = { .name = __stringify(_name), .mode = _mode, \
+			   .owner = THIS_MODULE }, \
+		 .size = 0, }, \
+	.fops = { .write = i2o_config_##_name##_write, \
+		  .read = i2o_config_##_name##_read} \
+};
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+
+/**
+ *	i2o_config_dpt_reagion - Converts type and id to flash region
+ *	@swtype: type of software module reading
+ *	@swid: id of software which should be read
+ *
+ *	Converts type and id from I2O spec to the matching region for DPT /
+ *	Adaptec controllers.
+ *
+ *	Returns region which match type and id or -1 on error.
+ */
+static u32 i2o_config_dpt_region(u8 swtype, u8 swid)
+{
+	switch (swtype) {
+	case I2O_SOFTWARE_MODULE_IRTOS:
+		/*
+		 * content: operation firmware
+		 * region size:
+		 *      0xbc000 for 2554, 3754, 2564, 3757
+		 *      0x170000 for 2865
+		 *      0x17c000 for 3966
+		 */
+		if (!swid)
+			return 0;
+
+		break;
+
+	case I2O_SOFTWARE_MODULE_IOP_PRIVATE:
+		/*
+		 * content: BIOS and SMOR
+		 * BIOS size: first 0x8000 bytes
+		 * region size:
+		 *      0x40000 for 2554, 3754, 2564, 3757
+		 *      0x80000 for 2865, 3966
+		 */
+		if (!swid)
+			return 1;
+
+		break;
+
+	case I2O_SOFTWARE_MODULE_IOP_CONFIG:
+		switch (swid) {
+		case 0:
+			/*
+			 * content: NVRAM defaults
+			 * region size: 0x2000 bytes
+			 */
+			return 2;
+		case 1:
+			/*
+			 * content: serial number
+			 * region size: 0x2000 bytes
+			 */
+			return 3;
+		}
+		break;
+	}
+
+	return -1;
+};
+
+#endif
+
+/**
+ *	i2o_config_sw_read - Read a software module from controller
+ *	@file: file pointer
+ *	@buf: buffer into which the data should be copied
+ *	@count: number of bytes to read
+ *	@off: file offset
+ *	@swtype: type of software module reading
+ *	@swid: id of software which should be read
+ *
+ *	Transfers @count bytes at offset @offset from IOP into buffer using
+ *	type @swtype and id @swid as described in I2O spec.
+ *
+ *	Returns number of bytes copied into buffer or error code on failure.
+ */
+static ssize_t i2o_config_sw_read(struct file *file, char __user * buf,
+				  size_t count, loff_t * offset, u8 swtype,
+				  u32 swid)
+{
+	struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata;
+	struct kobject *kobj = sd->s_element;
+	struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
+	u32 m, function = I2O_CMD_SW_UPLOAD;
+	struct i2o_dma buffer;
+	struct i2o_message __iomem *msg;
+	u32 __iomem *mptr;
+	int rc, status;
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -EBUSY;
+
+	mptr = &msg->body[3];
+
+	if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL))) {
+		i2o_msg_nop(c, m);
+		return rc;
+	}
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+	if (c->adaptec) {
+		mptr = &msg->body[4];
+		function = I2O_CMD_PRIVATE;
+
+		writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]);
+
+		writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_READ,
+		       &msg->body[0]);
+		writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]);
+		writel(*offset, &msg->body[2]);
+		writel(count, &msg->body[3]);
+	} else
+#endif
+		writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
+
+	writel(0xD0000000 | count, mptr++);
+	writel(buffer.phys, mptr);
+
+	writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]);
+	writel(i2o_config_driver.context, &msg->u.head[2]);
+	writel(0, &msg->u.head[3]);
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+	if (!c->adaptec)
+#endif
+	{
+		writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]);
+		writel(0, &msg->body[1]);
+		writel(swid, &msg->body[2]);
+	}
+
+	status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
+
+	if (status == I2O_POST_WAIT_OK) {
+		if (!(rc = copy_to_user(buf, buffer.virt, count))) {
+			rc = count;
+			*offset += count;
+		}
+	} else
+		rc = -EIO;
+
+	if (status != -ETIMEDOUT)
+		i2o_dma_free(&c->pdev->dev, &buffer);
+
+	return rc;
+};
+
+/**
+ *	i2o_config_sw_write - Write a software module to controller
+ *	@file: file pointer
+ *	@buf: buffer into which the data should be copied
+ *	@count: number of bytes to read
+ *	@off: file offset
+ *	@swtype: type of software module writing
+ *	@swid: id of software which should be written
+ *
+ *	Transfers @count bytes at offset @offset from buffer to IOP using
+ *	type @swtype and id @swid as described in I2O spec.
+ *
+ *	Returns number of bytes copied from buffer or error code on failure.
+ */
+static ssize_t i2o_config_sw_write(struct file *file, const char __user * buf,
+				   size_t count, loff_t * offset, u8 swtype,
+				   u32 swid)
+{
+	struct sysfs_dirent *sd = file->f_dentry->d_parent->d_fsdata;
+	struct kobject *kobj = sd->s_element;
+	struct i2o_controller *c = kobj_to_i2o_device(kobj)->iop;
+	u32 m, function = I2O_CMD_SW_DOWNLOAD;
+	struct i2o_dma buffer;
+	struct i2o_message __iomem *msg;
+	u32 __iomem *mptr;
+	int rc, status;
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -EBUSY;
+
+	mptr = &msg->body[3];
+
+	if ((rc = i2o_dma_alloc(&c->pdev->dev, &buffer, count, GFP_KERNEL)))
+		goto nop_msg;
+
+	if ((rc = copy_from_user(buffer.virt, buf, count)))
+		goto free_buffer;
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+	if (c->adaptec) {
+		mptr = &msg->body[4];
+		function = I2O_CMD_PRIVATE;
+
+		writel(TEN_WORD_MSG_SIZE | SGL_OFFSET_8, &msg->u.head[0]);
+
+		writel(I2O_VENDOR_DPT << 16 | I2O_DPT_FLASH_WRITE,
+		       &msg->body[0]);
+		writel(i2o_config_dpt_region(swtype, swid), &msg->body[1]);
+		writel(*offset, &msg->body[2]);
+		writel(count, &msg->body[3]);
+	} else
+#endif
+		writel(NINE_WORD_MSG_SIZE | SGL_OFFSET_7, &msg->u.head[0]);
+
+	writel(0xD4000000 | count, mptr++);
+	writel(buffer.phys, mptr);
+
+	writel(function << 24 | HOST_TID << 12 | ADAPTER_TID, &msg->u.head[1]);
+	writel(i2o_config_driver.context, &msg->u.head[2]);
+	writel(0, &msg->u.head[3]);
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+	if (!c->adaptec)
+#endif
+	{
+		writel((u32) swtype << 16 | (u32) 1 << 8, &msg->body[0]);
+		writel(0, &msg->body[1]);
+		writel(swid, &msg->body[2]);
+	}
+
+	status = i2o_msg_post_wait_mem(c, m, 60, &buffer);
+
+	if (status != -ETIMEDOUT)
+		i2o_dma_free(&c->pdev->dev, &buffer);
+
+	if (status != I2O_POST_WAIT_OK)
+		return -EIO;
+
+	*offset += count;
+
+	return count;
+
+      free_buffer:
+	i2o_dma_free(&c->pdev->dev, &buffer);
+
+      nop_msg:
+	i2o_msg_nop(c, m);
+
+	return rc;
+};
+
+/* attribute for HRT in sysfs */
+static struct bin_attribute i2o_config_hrt_attr = {
+	.attr = {
+		 .name = "hrt",
+		 .mode = S_IRUGO,
+		 .owner = THIS_MODULE},
+	.size = 0,
+	.read = i2o_config_read_hrt
+};
+
+/* attribute for LCT in sysfs */
+static struct bin_attribute i2o_config_lct_attr = {
+	.attr = {
+		 .name = "lct",
+		 .mode = S_IRUGO,
+		 .owner = THIS_MODULE},
+	.size = 0,
+	.read = i2o_config_read_lct
+};
+
+/* IRTOS firmware access */
+I2O_CONFIG_SW_ATTR(irtos, S_IWRSR, I2O_SOFTWARE_MODULE_IRTOS, 0);
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+
+/*
+ * attribute for BIOS / SMOR, nvram and serial number access on DPT / Adaptec
+ * controllers
+ */
+I2O_CONFIG_SW_ATTR(bios, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_PRIVATE, 0);
+I2O_CONFIG_SW_ATTR(nvram, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 0);
+I2O_CONFIG_SW_ATTR(serial, S_IWRSR, I2O_SOFTWARE_MODULE_IOP_CONFIG, 1);
+
+#endif
+
+/**
+ *	i2o_config_notify_controller_add - Notify of added controller
+ *	@c: the controller which was added
+ *
+ *	If a I2O controller is added, we catch the notification to add sysfs
+ *	entries.
+ */
+static void i2o_config_notify_controller_add(struct i2o_controller *c)
+{
+	struct kobject *kobj = &c->exec->device.kobj;
+
+	sysfs_create_bin_file(kobj, &i2o_config_hrt_attr);
+	sysfs_create_bin_file(kobj, &i2o_config_lct_attr);
+
+	sysfs_create_fops_file(kobj, &i2o_config_attr_irtos);
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+	if (c->adaptec) {
+		sysfs_create_fops_file(kobj, &i2o_config_attr_bios);
+		sysfs_create_fops_file(kobj, &i2o_config_attr_nvram);
+		sysfs_create_fops_file(kobj, &i2o_config_attr_serial);
+	}
+#endif
+};
+
+/**
+ *	i2o_config_notify_controller_remove - Notify of removed controller
+ *	@c: the controller which was removed
+ *
+ *	If a I2O controller is removed, we catch the notification to remove the
+ *	sysfs entries.
+ */
+static void i2o_config_notify_controller_remove(struct i2o_controller *c)
+{
+	struct kobject *kobj = &c->exec->device.kobj;
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+	if (c->adaptec) {
+		sysfs_remove_fops_file(kobj, &i2o_config_attr_serial);
+		sysfs_remove_fops_file(kobj, &i2o_config_attr_nvram);
+		sysfs_remove_fops_file(kobj, &i2o_config_attr_bios);
+	}
+#endif
+	sysfs_remove_fops_file(kobj, &i2o_config_attr_irtos);
+
+	sysfs_remove_bin_file(kobj, &i2o_config_lct_attr);
+	sysfs_remove_bin_file(kobj, &i2o_config_hrt_attr);
+};
+
+/* Config OSM driver struct */
+static struct i2o_driver i2o_config_driver = {
+	.name = OSM_NAME,
+	.notify_controller_add = i2o_config_notify_controller_add,
+	.notify_controller_remove = i2o_config_notify_controller_remove
+};
+
+#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL
+#include "i2o_config.c"
+#endif
+
+/**
+ *	i2o_config_init - Configuration OSM initialization function
+ *
+ *	Registers Configuration OSM in the I2O core and if old ioctl's are
+ *	compiled in initialize them.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+static int __init i2o_config_init(void)
+{
+	printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");
+
+	if (i2o_driver_register(&i2o_config_driver)) {
+		osm_err("handler register failed.\n");
+		return -EBUSY;
+	}
+#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL
+	if (i2o_config_old_init())
+		i2o_driver_unregister(&i2o_config_driver);
+#endif
+
+	return 0;
+}
+
+/**
+ *	i2o_config_exit - Configuration OSM exit function
+ *
+ *	If old ioctl's are compiled in exit remove them and unregisters
+ *	Configuration OSM from I2O core.
+ */
+static void i2o_config_exit(void)
+{
+#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL
+	i2o_config_old_exit();
+#endif
+
+	i2o_driver_unregister(&i2o_config_driver);
+}
+
+MODULE_AUTHOR("Markus Lidel <Markus.Lidel@shadowconnect.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(OSM_DESCRIPTION);
+MODULE_VERSION(OSM_VERSION);
+
+module_init(i2o_config_init);
+module_exit(i2o_config_exit);
diff --git a/drivers/message/i2o/core.h b/drivers/message/i2o/core.h
new file mode 100644
index 0000000..c5bcfd7
--- /dev/null
+++ b/drivers/message/i2o/core.h
@@ -0,0 +1,58 @@
+/*
+ *	I2O core internal declarations
+ *
+ *	Copyright (C) 2005	Markus Lidel <Markus.Lidel@shadowconnect.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.
+ *
+ *	Fixes/additions:
+ *		Markus Lidel <Markus.Lidel@shadowconnect.com>
+ *			initial version.
+ */
+
+/* Exec-OSM */
+extern struct bus_type i2o_bus_type;
+
+extern struct i2o_driver i2o_exec_driver;
+extern int i2o_exec_lct_get(struct i2o_controller *);
+
+extern int __init i2o_exec_init(void);
+extern void __exit i2o_exec_exit(void);
+
+/* driver */
+extern int i2o_driver_dispatch(struct i2o_controller *, u32);
+
+extern int __init i2o_driver_init(void);
+extern void __exit i2o_driver_exit(void);
+
+/* PCI */
+extern int __init i2o_pci_init(void);
+extern void __exit i2o_pci_exit(void);
+
+/* device */
+extern void i2o_device_remove(struct i2o_device *);
+extern int i2o_device_parse_lct(struct i2o_controller *);
+
+extern int i2o_device_init(void);
+extern void i2o_device_exit(void);
+
+/* IOP */
+extern struct i2o_controller *i2o_iop_alloc(void);
+extern void i2o_iop_free(struct i2o_controller *);
+
+extern int i2o_iop_add(struct i2o_controller *);
+extern void i2o_iop_remove(struct i2o_controller *);
+
+/* config */
+extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int);
+
+/* control registers relative to c->base */
+#define I2O_IRQ_STATUS	0x30
+#define I2O_IRQ_MASK	0x34
+#define I2O_IN_PORT	0x40
+#define I2O_OUT_PORT	0x44
+
+#define I2O_IRQ_OUTBOUND_POST	0x00000008
diff --git a/drivers/message/i2o/debug.c b/drivers/message/i2o/debug.c
index 2a5d478..018ca88 100644
--- a/drivers/message/i2o/debug.c
+++ b/drivers/message/i2o/debug.c
@@ -4,8 +4,6 @@
 #include <linux/pci.h>
 #include <linux/i2o.h>
 
-extern struct i2o_driver **i2o_drivers;
-extern unsigned int i2o_max_drivers;
 static void i2o_report_util_cmd(u8 cmd);
 static void i2o_report_exec_cmd(u8 cmd);
 static void i2o_report_fail_status(u8 req_status, u32 * msg);
@@ -23,7 +21,6 @@
 	u8 cmd = (msg[1] >> 24) & 0xFF;
 	u8 req_status = (msg[4] >> 24) & 0xFF;
 	u16 detailed_status = msg[4] & 0xFFFF;
-	//struct i2o_driver *h = i2o_drivers[msg[2] & (i2o_max_drivers-1)];
 
 	if (cmd == I2O_CMD_UTIL_EVT_REGISTER)
 		return;		// No status in this reply
diff --git a/drivers/message/i2o/device.c b/drivers/message/i2o/device.c
index eb907e8..21f16ba 100644
--- a/drivers/message/i2o/device.c
+++ b/drivers/message/i2o/device.c
@@ -16,9 +16,7 @@
 #include <linux/module.h>
 #include <linux/i2o.h>
 #include <linux/delay.h>
-
-/* Exec OSM functions */
-extern struct bus_type i2o_bus_type;
+#include "core.h"
 
 /**
  *	i2o_device_issue_claim - claim or release a device
@@ -282,8 +280,7 @@
 
 	down(&c->lct_lock);
 
-	if (c->lct)
-		kfree(c->lct);
+	kfree(c->lct);
 
 	lct = c->dlct.virt;
 
@@ -294,12 +291,12 @@
 	}
 
 	if (lct->table_size * 4 > c->dlct.len) {
-		memcpy_fromio(c->lct, c->dlct.virt, c->dlct.len);
+		memcpy(c->lct, c->dlct.virt, c->dlct.len);
 		up(&c->lct_lock);
 		return -EAGAIN;
 	}
 
-	memcpy_fromio(c->lct, c->dlct.virt, lct->table_size * 4);
+	memcpy(c->lct, c->dlct.virt, lct->table_size * 4);
 
 	lct = c->lct;
 
@@ -354,7 +351,7 @@
 {
 	struct i2o_device *dev = to_i2o_device(cd->dev);
 
-	sprintf(buf, "%03x\n", dev->lct_data.class_id);
+	sprintf(buf, "0x%03x\n", dev->lct_data.class_id);
 	return strlen(buf) + 1;
 };
 
@@ -369,7 +366,7 @@
 {
 	struct i2o_device *dev = to_i2o_device(cd->dev);
 
-	sprintf(buf, "%03x\n", dev->lct_data.tid);
+	sprintf(buf, "0x%03x\n", dev->lct_data.tid);
 	return strlen(buf) + 1;
 };
 
@@ -401,25 +398,27 @@
 
 	/* create user entries for this device */
 	tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid);
-	if (tmp)
+	if (tmp && (tmp != i2o_dev))
 		sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
 				  "user");
 
 	/* create user entries refering to this device */
 	list_for_each_entry(tmp, &c->devices, list)
-	    if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
+	    if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
+		&& (tmp != i2o_dev))
 		sysfs_create_link(&tmp->device.kobj,
 				  &i2o_dev->device.kobj, "user");
 
 	/* create parent entries for this device */
 	tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid);
-	if (tmp)
+	if (tmp && (tmp != i2o_dev))
 		sysfs_create_link(&i2o_dev->device.kobj, &tmp->device.kobj,
 				  "parent");
 
 	/* create parent entries refering to this device */
 	list_for_each_entry(tmp, &c->devices, list)
-	    if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
+	    if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
+		&& (tmp != i2o_dev))
 		sysfs_create_link(&tmp->device.kobj,
 				  &i2o_dev->device.kobj, "parent");
 
@@ -444,9 +443,8 @@
  *	Note that the minimum sized reslist is 8 bytes and contains
  *	ResultCount, ErrorInfoSize, BlockStatus and BlockSize.
  */
-
 int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
-		   int oplen, void *reslist, int reslen)
+			  int oplen, void *reslist, int reslen)
 {
 	struct i2o_message __iomem *msg;
 	u32 m;
@@ -489,7 +487,7 @@
 	if (rc == -ETIMEDOUT)
 		return rc;
 
-	memcpy_fromio(reslist, res.virt, res.len);
+	memcpy(reslist, res.virt, res.len);
 	i2o_dma_free(dev, &res);
 
 	/* Query failed */
@@ -531,17 +529,23 @@
 		       void *buf, int buflen)
 {
 	u16 opblk[] = { 1, 0, I2O_PARAMS_FIELD_GET, group, 1, field };
-	u8 resblk[8 + buflen];	/* 8 bytes for header */
+	u8 *resblk;		/* 8 bytes for header */
 	int size;
 
 	if (field == -1)	/* whole group */
 		opblk[4] = -1;
 
+	resblk = kmalloc(buflen + 8, GFP_KERNEL | GFP_ATOMIC);
+	if (!resblk)
+		return -ENOMEM;
+
 	size = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk,
-			      sizeof(opblk), resblk, sizeof(resblk));
+			      sizeof(opblk), resblk, buflen + 8);
 
 	memcpy(buf, resblk + 8, buflen);	/* cut off header */
 
+	kfree(resblk);
+
 	if (size > buflen)
 		return buflen;
 
diff --git a/drivers/message/i2o/driver.c b/drivers/message/i2o/driver.c
index 91f4edb..739bfde 100644
--- a/drivers/message/i2o/driver.c
+++ b/drivers/message/i2o/driver.c
@@ -17,9 +17,12 @@
 #include <linux/module.h>
 #include <linux/rwsem.h>
 #include <linux/i2o.h>
+#include "core.h"
+
+#define OSM_NAME	"i2o"
 
 /* max_drivers - Maximum I2O drivers (OSMs) which could be registered */
-unsigned int i2o_max_drivers = I2O_MAX_DRIVERS;
+static unsigned int i2o_max_drivers = I2O_MAX_DRIVERS;
 module_param_named(max_drivers, i2o_max_drivers, uint, 0);
 MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support");
 
@@ -76,17 +79,16 @@
 	int rc = 0;
 	unsigned long flags;
 
-	pr_debug("i2o: Register driver %s\n", drv->name);
+	osm_debug("Register driver %s\n", drv->name);
 
 	if (drv->event) {
 		drv->event_queue = create_workqueue(drv->name);
 		if (!drv->event_queue) {
-			printk(KERN_ERR "i2o: Could not initialize event queue "
-			       "for driver %s\n", drv->name);
+			osm_err("Could not initialize event queue for driver "
+				"%s\n", drv->name);
 			return -EFAULT;
 		}
-		pr_debug("i2o: Event queue initialized for driver %s\n",
-			 drv->name);
+		osm_debug("Event queue initialized for driver %s\n", drv->name);
 	} else
 		drv->event_queue = NULL;
 
@@ -97,8 +99,8 @@
 
 	for (i = 0; i2o_drivers[i]; i++)
 		if (i >= i2o_max_drivers) {
-			printk(KERN_ERR "i2o: too many drivers registered, "
-			       "increase max_drivers\n");
+			osm_err("too many drivers registered, increase "
+				"max_drivers\n");
 			spin_unlock_irqrestore(&i2o_drivers_lock, flags);
 			return -EFAULT;
 		}
@@ -108,18 +110,16 @@
 
 	spin_unlock_irqrestore(&i2o_drivers_lock, flags);
 
-	pr_debug("i2o: driver %s gets context id %d\n", drv->name,
-		 drv->context);
+	osm_debug("driver %s gets context id %d\n", drv->name, drv->context);
 
 	list_for_each_entry(c, &i2o_controllers, list) {
 		struct i2o_device *i2o_dev;
 
 		i2o_driver_notify_controller_add(drv, c);
 		list_for_each_entry(i2o_dev, &c->devices, list)
-			i2o_driver_notify_device_add(drv, i2o_dev);
+		    i2o_driver_notify_device_add(drv, i2o_dev);
 	}
 
-
 	rc = driver_register(&drv->driver);
 	if (rc)
 		destroy_workqueue(drv->event_queue);
@@ -139,7 +139,7 @@
 	struct i2o_controller *c;
 	unsigned long flags;
 
-	pr_debug("i2o: unregister driver %s\n", drv->name);
+	osm_debug("unregister driver %s\n", drv->name);
 
 	driver_unregister(&drv->driver);
 
@@ -159,7 +159,7 @@
 	if (drv->event_queue) {
 		destroy_workqueue(drv->event_queue);
 		drv->event_queue = NULL;
-		pr_debug("i2o: event queue removed for %s\n", drv->name);
+		osm_debug("event queue removed for %s\n", drv->name);
 	}
 };
 
@@ -176,68 +176,70 @@
  *	on success and if the message should be flushed afterwords. Returns
  *	negative error code on failure (the message will be flushed too).
  */
-int i2o_driver_dispatch(struct i2o_controller *c, u32 m,
-			struct i2o_message __iomem *msg)
+int i2o_driver_dispatch(struct i2o_controller *c, u32 m)
 {
 	struct i2o_driver *drv;
-	u32 context = readl(&msg->u.s.icntxt);
+	struct i2o_message *msg = i2o_msg_out_to_virt(c, m);
+	u32 context = le32_to_cpu(msg->u.s.icntxt);
+	unsigned long flags;
 
-	if (likely(context < i2o_max_drivers)) {
-		spin_lock(&i2o_drivers_lock);
-		drv = i2o_drivers[context];
-		spin_unlock(&i2o_drivers_lock);
-
-		if (unlikely(!drv)) {
-			printk(KERN_WARNING "%s: Spurious reply to unknown "
-			       "driver %d\n", c->name, context);
-			return -EIO;
-		}
-
-		if ((readl(&msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) {
-			struct i2o_device *dev, *tmp;
-			struct i2o_event *evt;
-			u16 size;
-			u16 tid;
-
-			tid = readl(&msg->u.head[1]) & 0x1fff;
-
-			pr_debug("%s: event received from device %d\n", c->name,
-				 tid);
-
-			/* cut of header from message size (in 32-bit words) */
-			size = (readl(&msg->u.head[0]) >> 16) - 5;
-
-			evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC);
-			if (!evt)
-				return -ENOMEM;
-			memset(evt, 0, size * 4 + sizeof(*evt));
-
-			evt->size = size;
-			memcpy_fromio(&evt->tcntxt, &msg->u.s.tcntxt,
-				      (size + 2) * 4);
-
-			list_for_each_entry_safe(dev, tmp, &c->devices, list)
-			    if (dev->lct_data.tid == tid) {
-				evt->i2o_dev = dev;
-				break;
-			}
-
-			INIT_WORK(&evt->work, (void (*)(void *))drv->event,
-				  evt);
-			queue_work(drv->event_queue, &evt->work);
-			return 1;
-		}
-
-		if (likely(drv->reply))
-			return drv->reply(c, m, msg);
-		else
-			pr_debug("%s: Reply to driver %s, but no reply function"
-				 " defined!\n", c->name, drv->name);
+	if (unlikely(context >= i2o_max_drivers)) {
+		osm_warn("%s: Spurious reply to unknown driver %d\n", c->name,
+			 context);
 		return -EIO;
-	} else
-		printk(KERN_WARNING "%s: Spurious reply to unknown driver "
-		       "%d\n", c->name, readl(&msg->u.s.icntxt));
-	return -EIO;
+	}
+
+	spin_lock_irqsave(&i2o_drivers_lock, flags);
+	drv = i2o_drivers[context];
+	spin_unlock_irqrestore(&i2o_drivers_lock, flags);
+
+	if (unlikely(!drv)) {
+		osm_warn("%s: Spurious reply to unknown driver %d\n", c->name,
+			 context);
+		return -EIO;
+	}
+
+	if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) {
+		struct i2o_device *dev, *tmp;
+		struct i2o_event *evt;
+		u16 size;
+		u16 tid = le32_to_cpu(msg->u.head[1]) & 0xfff;
+
+		osm_debug("event received from device %d\n", tid);
+
+		if (!drv->event)
+			return -EIO;
+
+		/* cut of header from message size (in 32-bit words) */
+		size = (le32_to_cpu(msg->u.head[0]) >> 16) - 5;
+
+		evt = kmalloc(size * 4 + sizeof(*evt), GFP_ATOMIC | __GFP_ZERO);
+		if (!evt)
+			return -ENOMEM;
+
+		evt->size = size;
+		evt->tcntxt = le32_to_cpu(msg->u.s.tcntxt);
+		evt->event_indicator = le32_to_cpu(msg->body[0]);
+		memcpy(&evt->tcntxt, &msg->u.s.tcntxt, size * 4);
+
+		list_for_each_entry_safe(dev, tmp, &c->devices, list)
+		    if (dev->lct_data.tid == tid) {
+			evt->i2o_dev = dev;
+			break;
+		}
+
+		INIT_WORK(&evt->work, (void (*)(void *))drv->event, evt);
+		queue_work(drv->event_queue, &evt->work);
+		return 1;
+	}
+
+	if (unlikely(!drv->reply)) {
+		osm_debug("%s: Reply to driver %s, but no reply function"
+			  " defined!\n", c->name, drv->name);
+		return -EIO;
+	}
+
+	return drv->reply(c, m, msg);
 }
 
 /**
@@ -334,11 +336,11 @@
 	if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64) ||
 	    ((i2o_max_drivers ^ (i2o_max_drivers - 1)) !=
 	     (2 * i2o_max_drivers - 1))) {
-		printk(KERN_WARNING "i2o: max_drivers set to %d, but must be "
-		       ">=2 and <= 64 and a power of 2\n", i2o_max_drivers);
+		osm_warn("max_drivers set to %d, but must be >=2 and <= 64 and "
+			 "a power of 2\n", i2o_max_drivers);
 		i2o_max_drivers = I2O_MAX_DRIVERS;
 	}
-	printk(KERN_INFO "i2o: max drivers = %d\n", i2o_max_drivers);
+	osm_info("max drivers = %d\n", i2o_max_drivers);
 
 	i2o_drivers =
 	    kmalloc(i2o_max_drivers * sizeof(*i2o_drivers), GFP_KERNEL);
diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c
index 79c1cbf..bda2c62 100644
--- a/drivers/message/i2o/exec-osm.c
+++ b/drivers/message/i2o/exec-osm.c
@@ -30,6 +30,7 @@
 #include <linux/module.h>
 #include <linux/i2o.h>
 #include <linux/delay.h>
+#include "core.h"
 
 #define OSM_NAME "exec-osm"
 
@@ -37,9 +38,6 @@
 
 static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind);
 
-/* Module internal functions from other sources */
-extern int i2o_device_parse_lct(struct i2o_controller *);
-
 /* global wait list for POST WAIT */
 static LIST_HEAD(i2o_exec_wait_list);
 
@@ -50,7 +48,7 @@
 	u32 tcntxt;		/* transaction context from reply */
 	int complete;		/* 1 if reply received otherwise 0 */
 	u32 m;			/* message id */
-	struct i2o_message __iomem *msg;	/* pointer to the reply message */
+	struct i2o_message *msg;	/* pointer to the reply message */
 	struct list_head list;	/* node in global wait list */
 };
 
@@ -108,7 +106,8 @@
  *	buffer must not be freed. Instead the event completion will free them
  *	for you. In all other cases the buffer are your problem.
  *
- *	Returns 0 on success or negative error code on failure.
+ *	Returns 0 on success, negative error code on timeout or positive error
+ *	code from reply.
  */
 int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
 			  timeout, struct i2o_dma *dma)
@@ -116,7 +115,7 @@
 	DECLARE_WAIT_QUEUE_HEAD(wq);
 	struct i2o_exec_wait *wait;
 	static u32 tcntxt = 0x80000000;
-	struct i2o_message __iomem *msg = c->in_queue.virt + m;
+	struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m);
 	int rc = 0;
 
 	wait = i2o_exec_wait_alloc();
@@ -153,7 +152,7 @@
 		list_add(&wait->list, &i2o_exec_wait_list);
 
 		wait_event_interruptible_timeout(wq, wait->complete,
-			timeout * HZ);
+						 timeout * HZ);
 
 		wait->wq = NULL;
 	}
@@ -161,8 +160,7 @@
 	barrier();
 
 	if (wait->complete) {
-		if (readl(&wait->msg->body[0]) >> 24)
-			rc = readl(&wait->msg->body[0]) & 0xff;
+		rc = le32_to_cpu(wait->msg->body[0]) >> 24;
 		i2o_flush_reply(c, wait->m);
 		i2o_exec_wait_free(wait);
 	} else {
@@ -187,6 +185,7 @@
  *	@c: I2O controller which answers
  *	@m: message id
  *	@msg: pointer to the I2O reply message
+ *	@context: transaction context of request
  *
  *	This function is called in interrupt context only. If the reply reached
  *	before the timeout, the i2o_exec_wait struct is filled with the message
@@ -201,16 +200,12 @@
  *	message must also be given back to the controller.
  */
 static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
-				      struct i2o_message __iomem *msg)
+				      struct i2o_message *msg, u32 context)
 {
 	struct i2o_exec_wait *wait, *tmp;
-	static spinlock_t lock;
+	unsigned long flags;
+	static spinlock_t lock = SPIN_LOCK_UNLOCKED;
 	int rc = 1;
-	u32 context;
-
-	spin_lock_init(&lock);
-
-	context = readl(&msg->u.s.tcntxt);
 
 	/*
 	 * We need to search through the i2o_exec_wait_list to see if the given
@@ -219,11 +214,13 @@
 	 * already expired. Not much we can do about that except log it for
 	 * debug purposes, increase timeout, and recompile.
 	 */
-	spin_lock(&lock);
+	spin_lock_irqsave(&lock, flags);
 	list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) {
 		if (wait->tcntxt == context) {
 			list_del(&wait->list);
 
+			spin_unlock_irqrestore(&lock, flags);
+
 			wait->m = m;
 			wait->msg = msg;
 			wait->complete = 1;
@@ -245,21 +242,63 @@
 				rc = -1;
 			}
 
-			spin_unlock(&lock);
-
 			return rc;
 		}
 	}
 
-	spin_unlock(&lock);
+	spin_unlock_irqrestore(&lock, flags);
 
-	pr_debug("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name,
+	osm_warn("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name,
 		 context);
 
 	return -1;
 };
 
 /**
+ *	i2o_exec_show_vendor_id - Displays Vendor ID of controller
+ *	@d: device of which the Vendor ID should be displayed
+ *	@buf: buffer into which the Vendor ID should be printed
+ *
+ *	Returns number of bytes printed into buffer.
+ */
+static ssize_t i2o_exec_show_vendor_id(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct i2o_device *dev = to_i2o_device(d);
+	u16 id;
+
+	if (i2o_parm_field_get(dev, 0x0000, 0, &id, 2)) {
+		sprintf(buf, "0x%04x", id);
+		return strlen(buf) + 1;
+	}
+
+	return 0;
+};
+
+/**
+ *	i2o_exec_show_product_id - Displays Product ID of controller
+ *	@d: device of which the Product ID should be displayed
+ *	@buf: buffer into which the Product ID should be printed
+ *
+ *	Returns number of bytes printed into buffer.
+ */
+static ssize_t i2o_exec_show_product_id(struct device *d, struct device_attribute *attr, char *buf)
+{
+	struct i2o_device *dev = to_i2o_device(d);
+	u16 id;
+
+	if (i2o_parm_field_get(dev, 0x0000, 1, &id, 2)) {
+		sprintf(buf, "0x%04x", id);
+		return strlen(buf) + 1;
+	}
+
+	return 0;
+};
+
+/* Exec-OSM device attributes */
+static DEVICE_ATTR(vendor_id, S_IRUGO, i2o_exec_show_vendor_id, NULL);
+static DEVICE_ATTR(product_id, S_IRUGO, i2o_exec_show_product_id, NULL);
+
+/**
  *	i2o_exec_probe - Called if a new I2O device (executive class) appears
  *	@dev: I2O device which should be probed
  *
@@ -271,10 +310,16 @@
 static int i2o_exec_probe(struct device *dev)
 {
 	struct i2o_device *i2o_dev = to_i2o_device(dev);
+	struct i2o_controller *c = i2o_dev->iop;
 
 	i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff);
 
-	i2o_dev->iop->exec = i2o_dev;
+	c->exec = i2o_dev;
+
+	i2o_exec_lct_notify(c, c->lct->change_ind + 1);
+
+	device_create_file(dev, &dev_attr_vendor_id);
+	device_create_file(dev, &dev_attr_product_id);
 
 	return 0;
 };
@@ -289,6 +334,9 @@
  */
 static int i2o_exec_remove(struct device *dev)
 {
+	device_remove_file(dev, &dev_attr_product_id);
+	device_remove_file(dev, &dev_attr_vendor_id);
+
 	i2o_event_register(to_i2o_device(dev), &i2o_exec_driver, 0, 0);
 
 	return 0;
@@ -300,12 +348,16 @@
  *
  *	This function handles asynchronus LCT NOTIFY replies. It parses the
  *	new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY
- *	again.
+ *	again, otherwise send LCT NOTIFY to get informed on next LCT change.
  */
 static void i2o_exec_lct_modified(struct i2o_controller *c)
 {
-	if (i2o_device_parse_lct(c) == -EAGAIN)
-		i2o_exec_lct_notify(c, 0);
+	u32 change_ind = 0;
+
+	if (i2o_device_parse_lct(c) != -EAGAIN)
+		change_ind = c->lct->change_ind + 1;
+
+	i2o_exec_lct_notify(c, change_ind);
 };
 
 /**
@@ -325,8 +377,14 @@
 static int i2o_exec_reply(struct i2o_controller *c, u32 m,
 			  struct i2o_message *msg)
 {
-	if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) {	// Fail bit is set
-		struct i2o_message __iomem *pmsg;	/* preserved message */
+	u32 context;
+
+	if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) {
+		/*
+		 * If Fail bit is set we must take the transaction context of
+		 * the preserved message to find the right request again.
+		 */
+		struct i2o_message __iomem *pmsg;
 		u32 pm;
 
 		pm = le32_to_cpu(msg->body[3]);
@@ -335,15 +393,15 @@
 
 		i2o_report_status(KERN_INFO, "i2o_core", msg);
 
-		/* Release the preserved msg by resubmitting it as a NOP */
+		context = readl(&pmsg->u.s.tcntxt);
+
+		/* Release the preserved msg */
 		i2o_msg_nop(c, pm);
+	} else
+		context = le32_to_cpu(msg->u.s.tcntxt);
 
-		/* If reply to i2o_post_wait failed, return causes a timeout */
-		return -1;
-	}
-
-	if (le32_to_cpu(msg->u.s.tcntxt) & 0x80000000)
-		return i2o_msg_post_wait_complete(c, m, msg);
+	if (context & 0x80000000)
+		return i2o_msg_post_wait_complete(c, m, msg, context);
 
 	if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) {
 		struct work_struct *work;
@@ -381,8 +439,9 @@
  */
 static void i2o_exec_event(struct i2o_event *evt)
 {
-	osm_info("Event received from device: %d\n",
-		 evt->i2o_dev->lct_data.tid);
+	if (likely(evt->i2o_dev))
+		osm_debug("Event received from device: %d\n",
+			  evt->i2o_dev->lct_data.tid);
 	kfree(evt);
 };
 
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c
index 7b74c87..f283b5b 100644
--- a/drivers/message/i2o/i2o_block.c
+++ b/drivers/message/i2o/i2o_block.c
@@ -62,7 +62,7 @@
 #include "i2o_block.h"
 
 #define OSM_NAME	"block-osm"
-#define OSM_VERSION	"$Rev$"
+#define OSM_VERSION	"1.287"
 #define OSM_DESCRIPTION	"I2O Block Device OSM"
 
 static struct i2o_driver i2o_block_driver;
@@ -104,7 +104,8 @@
 	struct i2o_device *i2o_dev = to_i2o_device(dev);
 	struct i2o_block_device *i2o_blk_dev = dev_get_drvdata(dev);
 
-	osm_info("Device removed %s\n", i2o_blk_dev->gd->disk_name);
+	osm_info("device removed (TID: %03x): %s\n", i2o_dev->lct_data.tid,
+		 i2o_blk_dev->gd->disk_name);
 
 	i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0);
 
@@ -146,6 +147,29 @@
 };
 
 /**
+ *	i2o_block_issue_flush - device-flush interface for block-layer
+ *	@queue: the request queue of the device which should be flushed
+ *	@disk: gendisk
+ *	@error_sector: error offset
+ *
+ *	Helper function to provide flush functionality to block-layer.
+ *
+ *	Returns 0 on success or negative error code on failure.
+ */
+
+static int i2o_block_issue_flush(request_queue_t * queue, struct gendisk *disk,
+				 sector_t * error_sector)
+{
+	struct i2o_block_device *i2o_blk_dev = queue->queuedata;
+	int rc = -ENODEV;
+
+	if (likely(i2o_blk_dev))
+		rc = i2o_block_device_flush(i2o_blk_dev->i2o_dev);
+
+	return rc;
+}
+
+/**
  *	i2o_block_device_mount - Mount (load) the media of device dev
  *	@dev: I2O device which should receive the mount request
  *	@media_id: Media Identifier
@@ -298,28 +322,31 @@
 
 /**
  *	i2o_block_sglist_alloc - Allocate the SG list and map it
+ *	@c: I2O controller to which the request belongs
  *	@ireq: I2O block request
  *
- *	Builds the SG list and map it into to be accessable by the controller.
+ *	Builds the SG list and map it to be accessable by the controller.
  *
- *	Returns the number of elements in the SG list or 0 on failure.
+ *	Returns 0 on failure or 1 on success.
  */
-static inline int i2o_block_sglist_alloc(struct i2o_block_request *ireq)
+static inline int i2o_block_sglist_alloc(struct i2o_controller *c,
+					 struct i2o_block_request *ireq,
+					 u32 __iomem ** mptr)
 {
-	struct device *dev = &ireq->i2o_blk_dev->i2o_dev->iop->pdev->dev;
 	int nents;
+	enum dma_data_direction direction;
 
+	ireq->dev = &c->pdev->dev;
 	nents = blk_rq_map_sg(ireq->req->q, ireq->req, ireq->sg_table);
 
 	if (rq_data_dir(ireq->req) == READ)
-		ireq->sg_dma_direction = PCI_DMA_FROMDEVICE;
+		direction = PCI_DMA_FROMDEVICE;
 	else
-		ireq->sg_dma_direction = PCI_DMA_TODEVICE;
+		direction = PCI_DMA_TODEVICE;
 
-	ireq->sg_nents = dma_map_sg(dev, ireq->sg_table, nents,
-				    ireq->sg_dma_direction);
+	ireq->sg_nents = nents;
 
-	return ireq->sg_nents;
+	return i2o_dma_map_sg(c, ireq->sg_table, nents, direction, mptr);
 };
 
 /**
@@ -330,10 +357,14 @@
  */
 static inline void i2o_block_sglist_free(struct i2o_block_request *ireq)
 {
-	struct device *dev = &ireq->i2o_blk_dev->i2o_dev->iop->pdev->dev;
+	enum dma_data_direction direction;
 
-	dma_unmap_sg(dev, ireq->sg_table, ireq->sg_nents,
-		     ireq->sg_dma_direction);
+	if (rq_data_dir(ireq->req) == READ)
+		direction = PCI_DMA_FROMDEVICE;
+	else
+		direction = PCI_DMA_TODEVICE;
+
+	dma_unmap_sg(ireq->dev, ireq->sg_table, ireq->sg_nents, direction);
 };
 
 /**
@@ -351,6 +382,11 @@
 	struct i2o_block_device *i2o_blk_dev = q->queuedata;
 	struct i2o_block_request *ireq;
 
+	if (unlikely(!i2o_blk_dev)) {
+		osm_err("block device already removed\n");
+		return BLKPREP_KILL;
+	}
+
 	/* request is already processed by us, so return */
 	if (req->flags & REQ_SPECIAL) {
 		osm_debug("REQ_SPECIAL already set!\n");
@@ -400,6 +436,52 @@
 };
 
 /**
+ *	i2o_block_end_request - Post-processing of completed commands
+ *	@req: request which should be completed
+ *	@uptodate: 1 for success, 0 for I/O error, < 0 for specific error
+ *	@nr_bytes: number of bytes to complete
+ *
+ *	Mark the request as complete. The lock must not be held when entering.
+ *
+ */
+static void i2o_block_end_request(struct request *req, int uptodate,
+				  int nr_bytes)
+{
+	struct i2o_block_request *ireq = req->special;
+	struct i2o_block_device *dev = ireq->i2o_blk_dev;
+	request_queue_t *q = req->q;
+	unsigned long flags;
+
+	if (end_that_request_chunk(req, uptodate, nr_bytes)) {
+		int leftover = (req->hard_nr_sectors << KERNEL_SECTOR_SHIFT);
+
+		if (blk_pc_request(req))
+			leftover = req->data_len;
+
+		if (end_io_error(uptodate))
+			end_that_request_chunk(req, 0, leftover);
+	}
+
+	add_disk_randomness(req->rq_disk);
+
+	spin_lock_irqsave(q->queue_lock, flags);
+
+	end_that_request_last(req);
+
+	if (likely(dev)) {
+		dev->open_queue_depth--;
+		list_del(&ireq->queue);
+	}
+
+	blk_start_queue(q);
+
+	spin_unlock_irqrestore(q->queue_lock, flags);
+
+	i2o_block_sglist_free(ireq);
+	i2o_block_request_free(ireq);
+};
+
+/**
  *	i2o_block_reply - Block OSM reply handler.
  *	@c: I2O controller from which the message arrives
  *	@m: message id of reply
@@ -411,60 +493,8 @@
 static int i2o_block_reply(struct i2o_controller *c, u32 m,
 			   struct i2o_message *msg)
 {
-	struct i2o_block_request *ireq;
 	struct request *req;
-	struct i2o_block_device *dev;
-	struct request_queue *q;
-	u8 st;
-	unsigned long flags;
-
-	/* FAILed message */
-	if (unlikely(le32_to_cpu(msg->u.head[0]) & (1 << 13))) {
-		struct i2o_message *pmsg;
-		u32 pm;
-
-		/*
-		 * FAILed message from controller
-		 * We increment the error count and abort it
-		 *
-		 * In theory this will never happen.  The I2O block class
-		 * specification states that block devices never return
-		 * FAILs but instead use the REQ status field...but
-		 * better be on the safe side since no one really follows
-		 * the spec to the book :)
-		 */
-		pm = le32_to_cpu(msg->body[3]);
-		pmsg = i2o_msg_in_to_virt(c, pm);
-
-		req = i2o_cntxt_list_get(c, le32_to_cpu(pmsg->u.s.tcntxt));
-		if (unlikely(!req)) {
-			osm_err("NULL reply received!\n");
-			return -1;
-		}
-
-		ireq = req->special;
-		dev = ireq->i2o_blk_dev;
-		q = dev->gd->queue;
-
-		req->errors++;
-
-		spin_lock_irqsave(q->queue_lock, flags);
-
-		while (end_that_request_chunk(req, !req->errors,
-					      le32_to_cpu(pmsg->body[1]))) ;
-		end_that_request_last(req);
-
-		dev->open_queue_depth--;
-		list_del(&ireq->queue);
-		blk_start_queue(q);
-
-		spin_unlock_irqrestore(q->queue_lock, flags);
-
-		/* Now flush the message by making it a NOP */
-		i2o_msg_nop(c, pm);
-
-		return -1;
-	}
+	int uptodate = 1;
 
 	req = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt));
 	if (unlikely(!req)) {
@@ -472,61 +502,13 @@
 		return -1;
 	}
 
-	ireq = req->special;
-	dev = ireq->i2o_blk_dev;
-	q = dev->gd->queue;
-
-	if (unlikely(!dev->i2o_dev)) {
-		/*
-		 * This is HACK, but Intel Integrated RAID allows user
-		 * to delete a volume that is claimed, locked, and in use
-		 * by the OS. We have to check for a reply from a
-		 * non-existent device and flag it as an error or the system
-		 * goes kaput...
-		 */
-		req->errors++;
-		osm_warn("Data transfer to deleted device!\n");
-		spin_lock_irqsave(q->queue_lock, flags);
-		while (end_that_request_chunk
-		       (req, !req->errors, le32_to_cpu(msg->body[1]))) ;
-		end_that_request_last(req);
-
-		dev->open_queue_depth--;
-		list_del(&ireq->queue);
-		blk_start_queue(q);
-
-		spin_unlock_irqrestore(q->queue_lock, flags);
-		return -1;
-	}
-
 	/*
 	 *      Lets see what is cooking. We stuffed the
 	 *      request in the context.
 	 */
 
-	st = le32_to_cpu(msg->body[0]) >> 24;
-
-	if (st != 0) {
-		int err;
-		char *bsa_errors[] = {
-			"Success",
-			"Media Error",
-			"Failure communicating to device",
-			"Device Failure",
-			"Device is not ready",
-			"Media not present",
-			"Media is locked by another user",
-			"Media has failed",
-			"Failure communicating to device",
-			"Device bus failure",
-			"Device is locked by another user",
-			"Device is write protected",
-			"Device has reset",
-			"Volume has changed, waiting for acknowledgement"
-		};
-
-		err = le32_to_cpu(msg->body[0]) & 0xffff;
-
+	if ((le32_to_cpu(msg->body[0]) >> 24) != 0) {
+		u32 status = le32_to_cpu(msg->body[0]);
 		/*
 		 *      Device not ready means two things. One is that the
 		 *      the thing went offline (but not a removal media)
@@ -539,40 +521,24 @@
 		 *      Don't stick a supertrak100 into cache aggressive modes
 		 */
 
-		osm_err("block-osm: /dev/%s error: %s", dev->gd->disk_name,
-			bsa_errors[le32_to_cpu(msg->body[0]) & 0xffff]);
-		if (le32_to_cpu(msg->body[0]) & 0x00ff0000)
-			printk(KERN_ERR " - DDM attempted %d retries",
-			       (le32_to_cpu(msg->body[0]) >> 16) & 0x00ff);
-		printk(KERN_ERR ".\n");
+		osm_err("TID %03x error status: 0x%02x, detailed status: "
+			"0x%04x\n", (le32_to_cpu(msg->u.head[1]) >> 12 & 0xfff),
+			status >> 24, status & 0xffff);
+
 		req->errors++;
-	} else
-		req->errors = 0;
 
-	if (!end_that_request_chunk
-	    (req, !req->errors, le32_to_cpu(msg->body[1]))) {
-		add_disk_randomness(req->rq_disk);
-		spin_lock_irqsave(q->queue_lock, flags);
+		uptodate = 0;
+	}
 
-		end_that_request_last(req);
-
-		dev->open_queue_depth--;
-		list_del(&ireq->queue);
-		blk_start_queue(q);
-
-		spin_unlock_irqrestore(q->queue_lock, flags);
-
-		i2o_block_sglist_free(ireq);
-		i2o_block_request_free(ireq);
-	} else
-		osm_err("still remaining chunks\n");
+	i2o_block_end_request(req, uptodate, le32_to_cpu(msg->body[1]));
 
 	return 1;
 };
 
 static void i2o_block_event(struct i2o_event *evt)
 {
-	osm_info("block-osm: event received\n");
+	osm_debug("event received\n");
+	kfree(evt);
 };
 
 /*
@@ -777,18 +743,25 @@
 static int i2o_block_transfer(struct request *req)
 {
 	struct i2o_block_device *dev = req->rq_disk->private_data;
-	struct i2o_controller *c = dev->i2o_dev->iop;
+	struct i2o_controller *c;
 	int tid = dev->i2o_dev->lct_data.tid;
 	struct i2o_message __iomem *msg;
-	void __iomem *mptr;
+	u32 __iomem *mptr;
 	struct i2o_block_request *ireq = req->special;
-	struct scatterlist *sg;
-	int sgnum;
-	int i;
 	u32 m;
 	u32 tcntxt;
-	u32 sg_flags;
+	u32 sgl_offset = SGL_OFFSET_8;
+	u32 ctl_flags = 0x00000000;
 	int rc;
+	u32 cmd;
+
+	if (unlikely(!dev->i2o_dev)) {
+		osm_err("transfer to removed drive\n");
+		rc = -ENODEV;
+		goto exit;
+	}
+
+	c = dev->i2o_dev->iop;
 
 	m = i2o_msg_get(c, &msg);
 	if (m == I2O_QUEUE_EMPTY) {
@@ -802,82 +775,109 @@
 		goto nop_msg;
 	}
 
-	if ((sgnum = i2o_block_sglist_alloc(ireq)) <= 0) {
+	writel(i2o_block_driver.context, &msg->u.s.icntxt);
+	writel(tcntxt, &msg->u.s.tcntxt);
+
+	mptr = &msg->body[0];
+
+	if (rq_data_dir(req) == READ) {
+		cmd = I2O_CMD_BLOCK_READ << 24;
+
+		switch (dev->rcache) {
+		case CACHE_PREFETCH:
+			ctl_flags = 0x201F0008;
+			break;
+
+		case CACHE_SMARTFETCH:
+			if (req->nr_sectors > 16)
+				ctl_flags = 0x201F0008;
+			else
+				ctl_flags = 0x001F0000;
+			break;
+
+		default:
+			break;
+		}
+	} else {
+		cmd = I2O_CMD_BLOCK_WRITE << 24;
+
+		switch (dev->wcache) {
+		case CACHE_WRITETHROUGH:
+			ctl_flags = 0x001F0008;
+			break;
+		case CACHE_WRITEBACK:
+			ctl_flags = 0x001F0010;
+			break;
+		case CACHE_SMARTBACK:
+			if (req->nr_sectors > 16)
+				ctl_flags = 0x001F0004;
+			else
+				ctl_flags = 0x001F0010;
+			break;
+		case CACHE_SMARTTHROUGH:
+			if (req->nr_sectors > 16)
+				ctl_flags = 0x001F0004;
+			else
+				ctl_flags = 0x001F0010;
+		default:
+			break;
+		}
+	}
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+	if (c->adaptec) {
+		u8 cmd[10];
+		u32 scsi_flags;
+		u16 hwsec = queue_hardsect_size(req->q) >> KERNEL_SECTOR_SHIFT;
+
+		memset(cmd, 0, 10);
+
+		sgl_offset = SGL_OFFSET_12;
+
+		writel(I2O_CMD_PRIVATE << 24 | HOST_TID << 12 | tid,
+		       &msg->u.head[1]);
+
+		writel(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC, mptr++);
+		writel(tid, mptr++);
+
+		/*
+		 * ENABLE_DISCONNECT
+		 * SIMPLE_TAG
+		 * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME
+		 */
+		if (rq_data_dir(req) == READ) {
+			cmd[0] = 0x28;
+			scsi_flags = 0x60a0000a;
+		} else {
+			cmd[0] = 0x2A;
+			scsi_flags = 0xa0a0000a;
+		}
+
+		writel(scsi_flags, mptr++);
+
+		*((u32 *) & cmd[2]) = cpu_to_be32(req->sector * hwsec);
+		*((u16 *) & cmd[7]) = cpu_to_be16(req->nr_sectors * hwsec);
+
+		memcpy_toio(mptr, cmd, 10);
+		mptr += 4;
+		writel(req->nr_sectors << KERNEL_SECTOR_SHIFT, mptr++);
+	} else
+#endif
+	{
+		writel(cmd | HOST_TID << 12 | tid, &msg->u.head[1]);
+		writel(ctl_flags, mptr++);
+		writel(req->nr_sectors << KERNEL_SECTOR_SHIFT, mptr++);
+		writel((u32) (req->sector << KERNEL_SECTOR_SHIFT), mptr++);
+		writel(req->sector >> (32 - KERNEL_SECTOR_SHIFT), mptr++);
+	}
+
+	if (!i2o_block_sglist_alloc(c, ireq, &mptr)) {
 		rc = -ENOMEM;
 		goto context_remove;
 	}
 
-	/* Build the message based on the request. */
-	writel(i2o_block_driver.context, &msg->u.s.icntxt);
-	writel(tcntxt, &msg->u.s.tcntxt);
-	writel(req->nr_sectors << 9, &msg->body[1]);
-
-	writel((((u64) req->sector) << 9) & 0xffffffff, &msg->body[2]);
-	writel(req->sector >> 23, &msg->body[3]);
-
-	mptr = &msg->body[4];
-
-	sg = ireq->sg_table;
-
-	if (rq_data_dir(req) == READ) {
-		writel(I2O_CMD_BLOCK_READ << 24 | HOST_TID << 12 | tid,
-		       &msg->u.head[1]);
-		sg_flags = 0x10000000;
-		switch (dev->rcache) {
-		case CACHE_NULL:
-			writel(0, &msg->body[0]);
-			break;
-		case CACHE_PREFETCH:
-			writel(0x201F0008, &msg->body[0]);
-			break;
-		case CACHE_SMARTFETCH:
-			if (req->nr_sectors > 16)
-				writel(0x201F0008, &msg->body[0]);
-			else
-				writel(0x001F0000, &msg->body[0]);
-			break;
-		}
-	} else {
-		writel(I2O_CMD_BLOCK_WRITE << 24 | HOST_TID << 12 | tid,
-		       &msg->u.head[1]);
-		sg_flags = 0x14000000;
-		switch (dev->wcache) {
-		case CACHE_NULL:
-			writel(0, &msg->body[0]);
-			break;
-		case CACHE_WRITETHROUGH:
-			writel(0x001F0008, &msg->body[0]);
-			break;
-		case CACHE_WRITEBACK:
-			writel(0x001F0010, &msg->body[0]);
-			break;
-		case CACHE_SMARTBACK:
-			if (req->nr_sectors > 16)
-				writel(0x001F0004, &msg->body[0]);
-			else
-				writel(0x001F0010, &msg->body[0]);
-			break;
-		case CACHE_SMARTTHROUGH:
-			if (req->nr_sectors > 16)
-				writel(0x001F0004, &msg->body[0]);
-			else
-				writel(0x001F0010, &msg->body[0]);
-		}
-	}
-
-	for (i = sgnum; i > 0; i--) {
-		if (i == 1)
-			sg_flags |= 0x80000000;
-		writel(sg_flags | sg_dma_len(sg), mptr);
-		writel(sg_dma_address(sg), mptr + 4);
-		mptr += 8;
-		sg++;
-	}
-
-	writel(I2O_MESSAGE_SIZE
-	       (((unsigned long)mptr -
-		 (unsigned long)&msg->u.head[0]) >> 2) | SGL_OFFSET_8,
-	       &msg->u.head[0]);
+	writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) |
+	       sgl_offset, &msg->u.head[0]);
 
 	list_add_tail(&ireq->queue, &dev->open_queue);
 	dev->open_queue_depth++;
@@ -920,11 +920,13 @@
 
 			queue_depth = ireq->i2o_blk_dev->open_queue_depth;
 
-			if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS)
+			if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS) {
 				if (!i2o_block_transfer(req)) {
 					blkdev_dequeue_request(req);
 					continue;
-				}
+				} else
+					osm_info("transfer error\n");
+			}
 
 			if (queue_depth)
 				break;
@@ -938,7 +940,6 @@
 			INIT_WORK(&dreq->work, i2o_block_delayed_request_fn,
 				  dreq);
 
-			osm_info("transfer error\n");
 			if (!queue_delayed_work(i2o_block_driver.event_queue,
 						&dreq->work,
 						I2O_BLOCK_RETRY_TIME))
@@ -1007,6 +1008,7 @@
 	}
 
 	blk_queue_prep_rq(queue, i2o_block_prep_req_fn);
+	blk_queue_issue_flush_fn(queue, i2o_block_issue_flush);
 
 	gd->major = I2O_MAJOR;
 	gd->queue = queue;
@@ -1039,17 +1041,27 @@
 static int i2o_block_probe(struct device *dev)
 {
 	struct i2o_device *i2o_dev = to_i2o_device(dev);
-	struct i2o_block_device *i2o_blk_dev;
 	struct i2o_controller *c = i2o_dev->iop;
+	struct i2o_block_device *i2o_blk_dev;
 	struct gendisk *gd;
 	struct request_queue *queue;
 	static int unit = 0;
 	int rc;
 	u64 size;
 	u32 blocksize;
-	u16 power;
 	u32 flags, status;
-	int segments;
+	u16 body_size = 4;
+	unsigned short max_sectors;
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+	if (c->adaptec)
+		body_size = 8;
+#endif
+
+	if (c->limit_sectors)
+		max_sectors = I2O_MAX_SECTORS_LIMITED;
+	else
+		max_sectors = I2O_MAX_SECTORS;
 
 	/* skip devices which are used by IOP */
 	if (i2o_dev->lct_data.user_tid != 0xfff) {
@@ -1057,8 +1069,6 @@
 		return -ENODEV;
 	}
 
-	osm_info("New device detected (TID: %03x)\n", i2o_dev->lct_data.tid);
-
 	if (i2o_device_claim(i2o_dev)) {
 		osm_warn("Unable to claim device. Installation aborted\n");
 		rc = -EFAULT;
@@ -1086,50 +1096,44 @@
 	queue = gd->queue;
 	queue->queuedata = i2o_blk_dev;
 
-	blk_queue_max_phys_segments(queue, I2O_MAX_SEGMENTS);
-	blk_queue_max_sectors(queue, I2O_MAX_SECTORS);
+	blk_queue_max_phys_segments(queue, I2O_MAX_PHYS_SEGMENTS);
+	blk_queue_max_sectors(queue, max_sectors);
+	blk_queue_max_hw_segments(queue, i2o_sg_tablesize(c, body_size));
 
-	if (c->short_req)
-		segments = 8;
-	else {
-		i2o_status_block *sb;
-
-		sb = c->status_block.virt;
-
-		segments = (sb->inbound_frame_size -
-			    sizeof(struct i2o_message) / 4 - 4) / 2;
-	}
-
-	blk_queue_max_hw_segments(queue, segments);
-
-	osm_debug("max sectors = %d\n", I2O_MAX_SECTORS);
-	osm_debug("phys segments = %d\n", I2O_MAX_SEGMENTS);
-	osm_debug("hw segments = %d\n", segments);
+	osm_debug("max sectors = %d\n", queue->max_phys_segments);
+	osm_debug("phys segments = %d\n", queue->max_sectors);
+	osm_debug("max hw segments = %d\n", queue->max_hw_segments);
 
 	/*
 	 *      Ask for the current media data. If that isn't supported
 	 *      then we ask for the device capacity data
 	 */
-	if (i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) != 0
-	    || i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) != 0) {
-		i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4);
-		i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8);
-	}
-	osm_debug("blocksize = %d\n", blocksize);
+	if (i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) ||
+	    i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) {
+		blk_queue_hardsect_size(queue, blocksize);
+	} else
+		osm_warn("unable to get blocksize of %s\n", gd->disk_name);
 
-	if (i2o_parm_field_get(i2o_dev, 0x0000, 2, &power, 2))
-		power = 0;
+	if (i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) ||
+	    i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) {
+		set_capacity(gd, size >> KERNEL_SECTOR_SHIFT);
+	} else
+		osm_warn("could not get size of %s\n", gd->disk_name);
+
+	if (!i2o_parm_field_get(i2o_dev, 0x0000, 2, &i2o_blk_dev->power, 2))
+		i2o_blk_dev->power = 0;
 	i2o_parm_field_get(i2o_dev, 0x0000, 5, &flags, 4);
 	i2o_parm_field_get(i2o_dev, 0x0000, 6, &status, 4);
 
-	set_capacity(gd, size >> 9);
-
 	i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0xffffffff);
 
 	add_disk(gd);
 
 	unit++;
 
+	osm_info("device added (TID: %03x): %s\n", i2o_dev->lct_data.tid,
+		 i2o_blk_dev->gd->disk_name);
+
 	return 0;
 
       claim_release:
@@ -1177,7 +1181,7 @@
 		goto exit;
 	}
 
-	i2o_blk_req_pool.pool = mempool_create(I2O_REQ_MEMPOOL_SIZE,
+	i2o_blk_req_pool.pool = mempool_create(I2O_BLOCK_REQ_MEMPOOL_SIZE,
 					       mempool_alloc_slab,
 					       mempool_free_slab,
 					       i2o_blk_req_pool.slab);
diff --git a/drivers/message/i2o/i2o_block.h b/drivers/message/i2o/i2o_block.h
index ddd9a15..4fdaa5b 100644
--- a/drivers/message/i2o/i2o_block.h
+++ b/drivers/message/i2o/i2o_block.h
@@ -56,42 +56,46 @@
 #define I2O_BLOCK_RETRY_TIME HZ/4
 #define I2O_BLOCK_MAX_OPEN_REQUESTS 50
 
+/* request queue sizes */
+#define I2O_BLOCK_REQ_MEMPOOL_SIZE		32
+
+#define KERNEL_SECTOR_SHIFT 9
+#define KERNEL_SECTOR_SIZE (1 << KERNEL_SECTOR_SHIFT)
+
 /* I2O Block OSM mempool struct */
 struct i2o_block_mempool {
-	kmem_cache_t	*slab;
-	mempool_t	*pool;
+	kmem_cache_t *slab;
+	mempool_t *pool;
 };
 
 /* I2O Block device descriptor */
 struct i2o_block_device {
 	struct i2o_device *i2o_dev;	/* pointer to I2O device */
 	struct gendisk *gd;
-	spinlock_t lock;		/* queue lock */
+	spinlock_t lock;	/* queue lock */
 	struct list_head open_queue;	/* list of transfered, but unfinished
 					   requests */
 	unsigned int open_queue_depth;	/* number of requests in the queue */
 
-	int rcache;			/* read cache flags */
-	int wcache;			/* write cache flags */
+	int rcache;		/* read cache flags */
+	int wcache;		/* write cache flags */
 	int flags;
-	int power;			/* power state */
-	int media_change_flag;		/* media changed flag */
+	u16 power;		/* power state */
+	int media_change_flag;	/* media changed flag */
 };
 
 /* I2O Block device request */
-struct i2o_block_request
-{
+struct i2o_block_request {
 	struct list_head queue;
-	struct request *req;		/* corresponding request */
+	struct request *req;	/* corresponding request */
 	struct i2o_block_device *i2o_blk_dev;	/* I2O block device */
-	int sg_dma_direction;		/* direction of DMA buffer read/write */
-	int sg_nents;			/* number of SG elements */
-	struct scatterlist sg_table[I2O_MAX_SEGMENTS]; /* SG table */
+	struct device *dev;	/* device used for DMA */
+	int sg_nents;		/* number of SG elements */
+	struct scatterlist sg_table[I2O_MAX_PHYS_SEGMENTS];	/* SG table */
 };
 
 /* I2O Block device delayed request */
-struct i2o_block_delayed_request
-{
+struct i2o_block_delayed_request {
 	struct work_struct work;
 	struct request_queue *queue;
 };
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c
index 1fb5cdf..3c3a7ab 100644
--- a/drivers/message/i2o/i2o_config.c
+++ b/drivers/message/i2o/i2o_config.c
@@ -30,29 +30,15 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/i2o.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
 #include <linux/miscdevice.h>
-#include <linux/mm.h>
-#include <linux/spinlock.h>
 #include <linux/smp_lock.h>
-#include <linux/ioctl32.h>
 #include <linux/compat.h>
-#include <linux/syscalls.h>
 
 #include <asm/uaccess.h>
-#include <asm/io.h>
 
-#define OSM_NAME	"config-osm"
-#define OSM_VERSION	"$Rev$"
-#define OSM_DESCRIPTION	"I2O Configuration OSM"
+#include "core.h"
 
-extern int i2o_parm_issue(struct i2o_device *, int, void *, int, void *, int);
+#define SG_TABLESIZE		30
 
 static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd,
 			 unsigned long arg);
@@ -80,15 +66,6 @@
 static struct i2o_cfg_info *open_files = NULL;
 static ulong i2o_cfg_info_id = 0;
 
-/*
- *	Each of these describes an i2o message handler. They are
- *	multiplexed by the i2o_core code
- */
-
-static struct i2o_driver i2o_config_driver = {
-	.name = OSM_NAME
-};
-
 static int i2o_cfg_getiops(unsigned long arg)
 {
 	struct i2o_controller *c;
@@ -391,9 +368,9 @@
 
 	i2o_dma_free(&c->pdev->dev, &buffer);
 
-return_ret:
+      return_ret:
 	return ret;
-return_fault:
+      return_fault:
 	ret = -EFAULT;
 	goto return_ret;
 };
@@ -540,8 +517,10 @@
 	return 0;
 }
 
+#ifdef CONFIG_I2O_EXT_ADAPTEC
 #ifdef CONFIG_COMPAT
-static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long arg)
+static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
+			      unsigned long arg)
 {
 	struct i2o_cmd_passthru32 __user *cmd;
 	struct i2o_controller *c;
@@ -555,6 +534,7 @@
 	u32 sg_offset = 0;
 	u32 sg_count = 0;
 	u32 i = 0;
+	u32 sg_index = 0;
 	i2o_status_block *sb;
 	struct i2o_message *msg;
 	u32 m;
@@ -634,8 +614,8 @@
 		if (sg_count > SG_TABLESIZE) {
 			printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n",
 			       c->name, sg_count);
-			kfree(reply);
-			return -EINVAL;
+			rcode = -EINVAL;
+			goto cleanup;
 		}
 
 		for (i = 0; i < sg_count; i++) {
@@ -651,7 +631,7 @@
 				goto cleanup;
 			}
 			sg_size = sg[i].flag_count & 0xffffff;
-			p = &(sg_list[i]);
+			p = &(sg_list[sg_index++]);
 			/* Allocate memory for the transfer */
 			if (i2o_dma_alloc
 			    (&c->pdev->dev, p, sg_size,
@@ -660,20 +640,21 @@
 				       "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
 				       c->name, sg_size, i, sg_count);
 				rcode = -ENOMEM;
-				goto cleanup;
+				goto sg_list_cleanup;
 			}
 			/* Copy in the user's SG buffer if necessary */
 			if (sg[i].
 			    flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) {
 				// TODO 64bit fix
 				if (copy_from_user
-				    (p->virt, (void __user *)(unsigned long)sg[i].addr_bus,
-				     sg_size)) {
+				    (p->virt,
+				     (void __user *)(unsigned long)sg[i].
+				     addr_bus, sg_size)) {
 					printk(KERN_DEBUG
 					       "%s: Could not copy SG buf %d FROM user\n",
 					       c->name, i);
 					rcode = -EFAULT;
-					goto cleanup;
+					goto sg_list_cleanup;
 				}
 			}
 			//TODO 64bit fix
@@ -683,10 +664,10 @@
 
 	rcode = i2o_msg_post_wait(c, m, 60);
 	if (rcode)
-		goto cleanup;
+		goto sg_list_cleanup;
 
 	if (sg_offset) {
-		u32 msg[128];
+		u32 msg[I2O_OUTBOUND_MSG_FRAME_SIZE];
 		/* Copy back the Scatter Gather buffers back to user space */
 		u32 j;
 		// TODO 64bit fix
@@ -694,18 +675,18 @@
 		int sg_size;
 
 		// re-acquire the original message to handle correctly the sg copy operation
-		memset(&msg, 0, MSG_FRAME_SIZE * 4);
+		memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
 		// get user msg size in u32s
 		if (get_user(size, &user_msg[0])) {
 			rcode = -EFAULT;
-			goto cleanup;
+			goto sg_list_cleanup;
 		}
 		size = size >> 16;
 		size *= 4;
 		/* Copy in the user's I2O command */
 		if (copy_from_user(msg, user_msg, size)) {
 			rcode = -EFAULT;
-			goto cleanup;
+			goto sg_list_cleanup;
 		}
 		sg_count =
 		    (size - sg_offset * 4) / sizeof(struct sg_simple_element);
@@ -727,7 +708,7 @@
 					       c->name, sg_list[j].virt,
 					       sg[j].addr_bus);
 					rcode = -EFAULT;
-					goto cleanup;
+					goto sg_list_cleanup;
 				}
 			}
 		}
@@ -741,6 +722,7 @@
 			       "%s: Could not copy message context FROM user\n",
 			       c->name);
 			rcode = -EFAULT;
+			goto sg_list_cleanup;
 		}
 		if (copy_to_user(user_reply, reply, reply_size)) {
 			printk(KERN_WARNING
@@ -749,16 +731,21 @@
 		}
 	}
 
+      sg_list_cleanup:
+	for (i = 0; i < sg_index; i++)
+		i2o_dma_free(&c->pdev->dev, &sg_list[i]);
+
       cleanup:
 	kfree(reply);
 	return rcode;
 }
 
-static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
+static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd,
+				 unsigned long arg)
 {
 	int ret;
-	lock_kernel();		
-	switch (cmd) { 
+	lock_kernel();
+	switch (cmd) {
 	case I2OGETIOPS:
 		ret = i2o_cfg_ioctl(NULL, file, cmd, arg);
 		break;
@@ -862,8 +849,8 @@
 		if (sg_count > SG_TABLESIZE) {
 			printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n",
 			       c->name, sg_count);
-			kfree(reply);
-			return -EINVAL;
+			rcode = -EINVAL;
+			goto cleanup;
 		}
 
 		for (i = 0; i < sg_count; i++) {
@@ -875,7 +862,7 @@
 				       "%s:Bad SG element %d - not simple (%x)\n",
 				       c->name, i, sg[i].flag_count);
 				rcode = -EINVAL;
-				goto cleanup;
+				goto sg_list_cleanup;
 			}
 			sg_size = sg[i].flag_count & 0xffffff;
 			/* Allocate memory for the transfer */
@@ -885,7 +872,7 @@
 				       "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
 				       c->name, sg_size, i, sg_count);
 				rcode = -ENOMEM;
-				goto cleanup;
+				goto sg_list_cleanup;
 			}
 			sg_list[sg_index++] = p;	// sglist indexed with input frame, not our internal frame.
 			/* Copy in the user's SG buffer if necessary */
@@ -899,7 +886,7 @@
 					       "%s: Could not copy SG buf %d FROM user\n",
 					       c->name, i);
 					rcode = -EFAULT;
-					goto cleanup;
+					goto sg_list_cleanup;
 				}
 			}
 			//TODO 64bit fix
@@ -909,7 +896,7 @@
 
 	rcode = i2o_msg_post_wait(c, m, 60);
 	if (rcode)
-		goto cleanup;
+		goto sg_list_cleanup;
 
 	if (sg_offset) {
 		u32 msg[128];
@@ -920,18 +907,18 @@
 		int sg_size;
 
 		// re-acquire the original message to handle correctly the sg copy operation
-		memset(&msg, 0, MSG_FRAME_SIZE * 4);
+		memset(&msg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
 		// get user msg size in u32s
 		if (get_user(size, &user_msg[0])) {
 			rcode = -EFAULT;
-			goto cleanup;
+			goto sg_list_cleanup;
 		}
 		size = size >> 16;
 		size *= 4;
 		/* Copy in the user's I2O command */
 		if (copy_from_user(msg, user_msg, size)) {
 			rcode = -EFAULT;
-			goto cleanup;
+			goto sg_list_cleanup;
 		}
 		sg_count =
 		    (size - sg_offset * 4) / sizeof(struct sg_simple_element);
@@ -953,7 +940,7 @@
 					       c->name, sg_list[j],
 					       sg[j].addr_bus);
 					rcode = -EFAULT;
-					goto cleanup;
+					goto sg_list_cleanup;
 				}
 			}
 		}
@@ -975,10 +962,15 @@
 		}
 	}
 
+      sg_list_cleanup:
+	for (i = 0; i < sg_index; i++)
+		kfree(sg_list[i]);
+
       cleanup:
 	kfree(reply);
 	return rcode;
 }
+#endif
 
 /*
  * IOCTL Handler
@@ -1033,9 +1025,11 @@
 		ret = i2o_cfg_evt_get(arg, fp);
 		break;
 
+#ifdef CONFIG_I2O_EXT_ADAPTEC
 	case I2OPASSTHRU:
 		ret = i2o_cfg_passthru(arg);
 		break;
+#endif
 
 	default:
 		osm_debug("unknown ioctl called!\n");
@@ -1137,37 +1131,21 @@
 	&config_fops
 };
 
-static int __init i2o_config_init(void)
+static int __init i2o_config_old_init(void)
 {
-	printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");
-
 	spin_lock_init(&i2o_config_lock);
 
 	if (misc_register(&i2o_miscdev) < 0) {
 		osm_err("can't register device.\n");
 		return -EBUSY;
 	}
-	/*
-	 *      Install our handler
-	 */
-	if (i2o_driver_register(&i2o_config_driver)) {
-		osm_err("handler register failed.\n");
-		misc_deregister(&i2o_miscdev);
-		return -EBUSY;
-	}
+
 	return 0;
 }
 
-static void i2o_config_exit(void)
+static void i2o_config_old_exit(void)
 {
 	misc_deregister(&i2o_miscdev);
-	i2o_driver_unregister(&i2o_config_driver);
 }
 
 MODULE_AUTHOR("Red Hat Software");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION(OSM_DESCRIPTION);
-MODULE_VERSION(OSM_VERSION);
-
-module_init(i2o_config_init);
-module_exit(i2o_config_exit);
diff --git a/drivers/message/i2o/i2o_proc.c b/drivers/message/i2o/i2o_proc.c
index b176d0e..d559a17 100644
--- a/drivers/message/i2o/i2o_proc.c
+++ b/drivers/message/i2o/i2o_proc.c
@@ -28,7 +28,7 @@
  */
 
 #define OSM_NAME	"proc-osm"
-#define OSM_VERSION	"$Rev$"
+#define OSM_VERSION	"1.145"
 #define OSM_DESCRIPTION	"I2O ProcFS OSM"
 
 #define I2O_MAX_MODULES 4
@@ -228,7 +228,7 @@
 	case I2O_CLASS_FLOPPY_DEVICE:
 		idx = 12;
 		break;
-	case I2O_CLASS_BUS_ADAPTER_PORT:
+	case I2O_CLASS_BUS_ADAPTER:
 		idx = 13;
 		break;
 	case I2O_CLASS_PEER_TRANSPORT_AGENT:
@@ -490,7 +490,7 @@
 				seq_printf(seq, ", Unknown Device Type");
 			break;
 
-		case I2O_CLASS_BUS_ADAPTER_PORT:
+		case I2O_CLASS_BUS_ADAPTER:
 			if (lct->lct_entry[i].sub_class < BUS_TABLE_SIZE)
 				seq_printf(seq, ", %s",
 					   bus_ports[lct->lct_entry[i].
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c
index 43f5875..9f1744c 100644
--- a/drivers/message/i2o/i2o_scsi.c
+++ b/drivers/message/i2o/i2o_scsi.c
@@ -54,6 +54,7 @@
 #include <linux/pci.h>
 #include <linux/blkdev.h>
 #include <linux/i2o.h>
+#include <linux/scatterlist.h>
 
 #include <asm/dma.h>
 #include <asm/system.h>
@@ -64,19 +65,23 @@
 #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	"$Rev$"
+#define OSM_VERSION	"1.282"
 #define OSM_DESCRIPTION	"I2O SCSI Peripheral OSM"
 
 static struct i2o_driver i2o_scsi_driver;
 
-static int i2o_scsi_max_id = 16;
-static int i2o_scsi_max_lun = 8;
+static unsigned int i2o_scsi_max_id = 16;
+static unsigned int i2o_scsi_max_lun = 255;
 
 struct i2o_scsi_host {
 	struct Scsi_Host *scsi_host;	/* pointer to the SCSI host */
 	struct i2o_controller *iop;	/* pointer to the I2O controller */
+	unsigned int lun;	/* lun's used for block devices */
 	struct i2o_device *channel[0];	/* channel->i2o_dev mapping table */
 };
 
@@ -99,11 +104,17 @@
 	u8 type;
 	int i;
 	size_t size;
-	i2o_status_block *sb;
+	u16 body_size = 6;
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+	if (c->adaptec)
+		body_size = 8;
+#endif
 
 	list_for_each_entry(i2o_dev, &c->devices, list)
-	    if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT) {
-		if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) || (type == 1))	/* SCSI bus */
+	    if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) {
+		if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1)
+		    && (type == 0x01))	/* SCSI bus */
 			max_channel++;
 	}
 
@@ -125,20 +136,18 @@
 	scsi_host->max_id = i2o_scsi_max_id;
 	scsi_host->max_lun = i2o_scsi_max_lun;
 	scsi_host->this_id = c->unit;
-
-	sb = c->status_block.virt;
-
-	scsi_host->sg_tablesize = (sb->inbound_frame_size -
-				   sizeof(struct i2o_message) / 4 - 6) / 2;
+	scsi_host->sg_tablesize = i2o_sg_tablesize(c, body_size);
 
 	i2o_shost = (struct i2o_scsi_host *)scsi_host->hostdata;
 	i2o_shost->scsi_host = scsi_host;
 	i2o_shost->iop = c;
+	i2o_shost->lun = 1;
 
 	i = 0;
 	list_for_each_entry(i2o_dev, &c->devices, list)
-	    if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER_PORT) {
-		if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) || (type == 1))	/* only SCSI bus */
+	    if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) {
+		if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1)
+		    && (type == 0x01))	/* only SCSI bus */
 			i2o_shost->channel[i++] = i2o_dev;
 
 		if (i >= max_channel)
@@ -178,10 +187,13 @@
 	struct i2o_scsi_host *i2o_shost;
 	struct scsi_device *scsi_dev;
 
+	osm_info("device removed (TID: %03x)\n", i2o_dev->lct_data.tid);
+
 	i2o_shost = i2o_scsi_get_host(c);
 
 	shost_for_each_device(scsi_dev, i2o_shost->scsi_host)
 	    if (scsi_dev->hostdata == i2o_dev) {
+		sysfs_remove_link(&i2o_dev->device.kobj, "scsi");
 		scsi_remove_device(scsi_dev);
 		scsi_device_put(scsi_dev);
 		break;
@@ -207,8 +219,8 @@
 	struct Scsi_Host *scsi_host;
 	struct i2o_device *parent;
 	struct scsi_device *scsi_dev;
-	u32 id;
-	u64 lun;
+	u32 id = -1;
+	u64 lun = -1;
 	int channel = -1;
 	int i;
 
@@ -218,51 +230,83 @@
 
 	scsi_host = i2o_shost->scsi_host;
 
-	if (i2o_parm_field_get(i2o_dev, 0, 3, &id, 4) < 0)
-		return -EFAULT;
+	switch (i2o_dev->lct_data.class_id) {
+	case I2O_CLASS_RANDOM_BLOCK_STORAGE:
+	case I2O_CLASS_EXECUTIVE:
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+		if (c->adaptec) {
+			u8 type;
+			struct i2o_device *d = i2o_shost->channel[0];
 
-	if (id >= scsi_host->max_id) {
-		osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)", id,
-			 scsi_host->max_id);
+			if (i2o_parm_field_get(d, 0x0000, 0, &type, 1)
+			    && (type == 0x01))	/* SCSI bus */
+				if (i2o_parm_field_get(d, 0x0200, 4, &id, 4)) {
+					channel = 0;
+					if (i2o_dev->lct_data.class_id ==
+					    I2O_CLASS_RANDOM_BLOCK_STORAGE)
+						lun = i2o_shost->lun++;
+					else
+						lun = 0;
+				}
+		}
+#endif
+		break;
+
+	case I2O_CLASS_SCSI_PERIPHERAL:
+		if (i2o_parm_field_get(i2o_dev, 0x0000, 3, &id, 4) < 0)
+			return -EFAULT;
+
+		if (i2o_parm_field_get(i2o_dev, 0x0000, 4, &lun, 8) < 0)
+			return -EFAULT;
+
+		parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid);
+		if (!parent) {
+			osm_warn("can not find parent of device %03x\n",
+				 i2o_dev->lct_data.tid);
+			return -EFAULT;
+		}
+
+		for (i = 0; i <= i2o_shost->scsi_host->max_channel; i++)
+			if (i2o_shost->channel[i] == parent)
+				channel = i;
+		break;
+
+	default:
 		return -EFAULT;
 	}
 
-	if (i2o_parm_field_get(i2o_dev, 0, 4, &lun, 8) < 0)
-		return -EFAULT;
-	if (lun >= scsi_host->max_lun) {
-		osm_warn("SCSI device id (%d) >= max_lun of I2O host (%d)",
-			 (unsigned int)lun, scsi_host->max_lun);
-		return -EFAULT;
-	}
-
-	parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid);
-	if (!parent) {
-		osm_warn("can not find parent of device %03x\n",
-			 i2o_dev->lct_data.tid);
-		return -EFAULT;
-	}
-
-	for (i = 0; i <= i2o_shost->scsi_host->max_channel; i++)
-		if (i2o_shost->channel[i] == parent)
-			channel = i;
-
 	if (channel == -1) {
 		osm_warn("can not find channel of device %03x\n",
 			 i2o_dev->lct_data.tid);
 		return -EFAULT;
 	}
 
-	scsi_dev =
-	    __scsi_add_device(i2o_shost->scsi_host, channel, id, lun, i2o_dev);
-
-	if (!scsi_dev) {
-		osm_warn("can not add SCSI device %03x\n",
-			 i2o_dev->lct_data.tid);
+	if (id >= scsi_host->max_id) {
+		osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)", id,
+			 scsi_host->max_id);
 		return -EFAULT;
 	}
 
-	osm_debug("added new SCSI device %03x (cannel: %d, id: %d, lun: %d)\n",
-		  i2o_dev->lct_data.tid, channel, id, (unsigned int)lun);
+	if (lun >= scsi_host->max_lun) {
+		osm_warn("SCSI device id (%d) >= max_lun of I2O host (%d)",
+			 (unsigned int)lun, scsi_host->max_lun);
+		return -EFAULT;
+	}
+
+	scsi_dev =
+	    __scsi_add_device(i2o_shost->scsi_host, channel, id, lun, i2o_dev);
+
+	if (IS_ERR(scsi_dev)) {
+		osm_warn("can not add SCSI device %03x\n",
+			 i2o_dev->lct_data.tid);
+		return PTR_ERR(scsi_dev);
+	}
+
+	sysfs_create_link(&i2o_dev->device.kobj, &scsi_dev->sdev_gendev.kobj,
+			  "scsi");
+
+	osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %d\n",
+		 i2o_dev->lct_data.tid, channel, id, (unsigned int)lun);
 
 	return 0;
 };
@@ -293,165 +337,92 @@
 			  struct i2o_message *msg)
 {
 	struct scsi_cmnd *cmd;
+	u32 error;
 	struct device *dev;
-	u8 as, ds, st;
 
 	cmd = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt));
-
-	if (msg->u.head[0] & (1 << 13)) {
-		struct i2o_message __iomem *pmsg;	/* preserved message */
-		u32 pm;
-		int err = DID_ERROR;
-
-		pm = le32_to_cpu(msg->body[3]);
-
-		pmsg = i2o_msg_in_to_virt(c, pm);
-
-		osm_err("IOP fail.\n");
-		osm_err("From %d To %d Cmd %d.\n",
-			(msg->u.head[1] >> 12) & 0xFFF,
-			msg->u.head[1] & 0xFFF, msg->u.head[1] >> 24);
-		osm_err("Failure Code %d.\n", msg->body[0] >> 24);
-		if (msg->body[0] & (1 << 16))
-			osm_err("Format error.\n");
-		if (msg->body[0] & (1 << 17))
-			osm_err("Path error.\n");
-		if (msg->body[0] & (1 << 18))
-			osm_err("Path State.\n");
-		if (msg->body[0] & (1 << 18))
-		{
-			osm_err("Congestion.\n");
-			err = DID_BUS_BUSY;
-		}
-
-		osm_debug("Failing message is %p.\n", pmsg);
-
-		cmd = i2o_cntxt_list_get(c, readl(&pmsg->u.s.tcntxt));
-		if (!cmd)
-			return 1;
-
-		cmd->result = err << 16;
-		cmd->scsi_done(cmd);
-
-		/* Now flush the message by making it a NOP */
-		i2o_msg_nop(c, pm);
-
-		return 1;
+	if (unlikely(!cmd)) {
+		osm_err("NULL reply received!\n");
+		return -1;
 	}
 
 	/*
 	 *      Low byte is device status, next is adapter status,
 	 *      (then one byte reserved), then request status.
 	 */
-	ds = (u8) le32_to_cpu(msg->body[0]);
-	as = (u8) (le32_to_cpu(msg->body[0]) >> 8);
-	st = (u8) (le32_to_cpu(msg->body[0]) >> 24);
-
-	/*
-	 *      Is this a control request coming back - eg an abort ?
-	 */
-
-	if (!cmd) {
-		if (st)
-			osm_warn("SCSI abort: %08X", le32_to_cpu(msg->body[0]));
-		osm_info("SCSI abort completed.\n");
-		return -EFAULT;
-	}
+	error = le32_to_cpu(msg->body[0]);
 
 	osm_debug("Completed %ld\n", cmd->serial_number);
 
-	if (st) {
-		u32 count, error;
-		/* An error has occurred */
+	cmd->result = error & 0xff;
+	/*
+	 * if DeviceStatus is not SCSI_SUCCESS copy over the sense data and let
+	 * the SCSI layer handle the error
+	 */
+	if (cmd->result)
+		memcpy(cmd->sense_buffer, &msg->body[3],
+		       min(sizeof(cmd->sense_buffer), (size_t) 40));
 
-		switch (st) {
-		case 0x06:
-			count = le32_to_cpu(msg->body[1]);
-			if (count < cmd->underflow) {
-				int i;
-
-				osm_err("SCSI underflow 0x%08X 0x%08X\n", count,
-					cmd->underflow);
-				osm_debug("Cmd: ");
-				for (i = 0; i < 15; i++)
-					pr_debug("%02X ", cmd->cmnd[i]);
-				pr_debug(".\n");
-				cmd->result = (DID_ERROR << 16);
-			}
-			break;
-
-		default:
-			error = le32_to_cpu(msg->body[0]);
-
-			osm_err("SCSI error %08x\n", error);
-
-			if ((error & 0xff) == 0x02 /*CHECK_CONDITION */ ) {
-				int i;
-				u32 len = sizeof(cmd->sense_buffer);
-				len = (len > 40) ? 40 : len;
-				// Copy over the sense data
-				memcpy(cmd->sense_buffer, (void *)&msg->body[3],
-				       len);
-				for (i = 0; i <= len; i++)
-					osm_info("%02x\n",
-						 cmd->sense_buffer[i]);
-				if (cmd->sense_buffer[0] == 0x70
-				    && cmd->sense_buffer[2] == DATA_PROTECT) {
-					/* This is to handle an array failed */
-					cmd->result = (DID_TIME_OUT << 16);
-					printk(KERN_WARNING "%s: SCSI Data "
-					       "Protect-Device (%d,%d,%d) "
-					       "hba_status=0x%x, dev_status="
-					       "0x%x, cmd=0x%x\n", c->name,
-					       (u32) cmd->device->channel,
-					       (u32) cmd->device->id,
-					       (u32) cmd->device->lun,
-					       (error >> 8) & 0xff,
-					       error & 0xff, cmd->cmnd[0]);
-				} else
-					cmd->result = (DID_ERROR << 16);
-
-				break;
-			}
-
-			switch (as) {
-			case 0x0E:
-				/* SCSI Reset */
-				cmd->result = DID_RESET << 16;
-				break;
-
-			case 0x0F:
-				cmd->result = DID_PARITY << 16;
-				break;
-
-			default:
-				cmd->result = DID_ERROR << 16;
-				break;
-			}
-
-			break;
-		}
-
-		cmd->scsi_done(cmd);
-		return 1;
-	}
-
-	cmd->result = DID_OK << 16 | ds;
-
-	cmd->scsi_done(cmd);
+	/* only output error code if AdapterStatus is not HBA_SUCCESS */
+	if ((error >> 8) & 0xff)
+		osm_err("SCSI error %08x\n", error);
 
 	dev = &c->pdev->dev;
 	if (cmd->use_sg)
-		dma_unmap_sg(dev, (struct scatterlist *)cmd->buffer,
-			     cmd->use_sg, cmd->sc_data_direction);
-	else if (cmd->request_bufflen)
-		dma_unmap_single(dev, (dma_addr_t) ((long)cmd->SCp.ptr),
-				 cmd->request_bufflen, cmd->sc_data_direction);
+		dma_unmap_sg(dev, cmd->request_buffer, cmd->use_sg,
+			     cmd->sc_data_direction);
+	else if (cmd->SCp.dma_handle)
+		dma_unmap_single(dev, cmd->SCp.dma_handle, cmd->request_bufflen,
+				 cmd->sc_data_direction);
+
+	cmd->scsi_done(cmd);
 
 	return 1;
 };
 
 /**
+ *	i2o_scsi_notify_device_add - Retrieve notifications of added devices
+ *	@i2o_dev: the I2O device which was added
+ *
+ *	If a I2O device is added we catch the notification, because I2O classes
+ *	other then SCSI peripheral will not be received through
+ *	i2o_scsi_probe().
+ */
+static void i2o_scsi_notify_device_add(struct i2o_device *i2o_dev)
+{
+	switch (i2o_dev->lct_data.class_id) {
+	case I2O_CLASS_EXECUTIVE:
+	case I2O_CLASS_RANDOM_BLOCK_STORAGE:
+		i2o_scsi_probe(&i2o_dev->device);
+		break;
+
+	default:
+		break;
+	}
+};
+
+/**
+ *	i2o_scsi_notify_device_remove - Retrieve notifications of removed
+ *				        devices
+ *	@i2o_dev: the I2O device which was removed
+ *
+ *	If a I2O device is removed, we catch the notification to remove the
+ *	corresponding SCSI device.
+ */
+static void i2o_scsi_notify_device_remove(struct i2o_device *i2o_dev)
+{
+	switch (i2o_dev->lct_data.class_id) {
+	case I2O_CLASS_EXECUTIVE:
+	case I2O_CLASS_RANDOM_BLOCK_STORAGE:
+		i2o_scsi_remove(&i2o_dev->device);
+		break;
+
+	default:
+		break;
+	}
+};
+
+/**
  *	i2o_scsi_notify_controller_add - Retrieve notifications of added
  *					 controllers
  *	@c: the controller which was added
@@ -501,7 +472,7 @@
 
 	scsi_remove_host(i2o_shost->scsi_host);
 	scsi_host_put(i2o_shost->scsi_host);
-	pr_info("I2O SCSI host removed\n");
+	osm_debug("I2O SCSI host removed\n");
 };
 
 /* SCSI OSM driver struct */
@@ -509,6 +480,8 @@
 	.name = OSM_NAME,
 	.reply = i2o_scsi_reply,
 	.classes = i2o_scsi_class_id,
+	.notify_device_add = i2o_scsi_notify_device_add,
+	.notify_device_remove = i2o_scsi_notify_device_remove,
 	.notify_controller_add = i2o_scsi_notify_controller_add,
 	.notify_controller_remove = i2o_scsi_notify_controller_remove,
 	.driver = {
@@ -535,26 +508,26 @@
 				 void (*done) (struct scsi_cmnd *))
 {
 	struct i2o_controller *c;
-	struct Scsi_Host *host;
 	struct i2o_device *i2o_dev;
-	struct device *dev;
 	int tid;
 	struct i2o_message __iomem *msg;
 	u32 m;
-	u32 scsi_flags, sg_flags;
+	/*
+	 * ENABLE_DISCONNECT
+	 * SIMPLE_TAG
+	 * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME
+	 */
+	u32 scsi_flags = 0x20a00000;
+	u32 sgl_offset;
 	u32 __iomem *mptr;
-	u32 __iomem *lenptr;
-	u32 len, reqlen;
-	int i;
+	u32 cmd = I2O_CMD_SCSI_EXEC << 24;
+	int rc = 0;
 
 	/*
 	 *      Do the incoming paperwork
 	 */
-
 	i2o_dev = SCpnt->device->hostdata;
-	host = SCpnt->device->host;
 	c = i2o_dev->iop;
-	dev = &c->pdev->dev;
 
 	SCpnt->scsi_done = done;
 
@@ -562,7 +535,7 @@
 		osm_warn("no I2O device in request\n");
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
-		return 0;
+		goto exit;
 	}
 
 	tid = i2o_dev->lct_data.tid;
@@ -571,44 +544,85 @@
 	osm_debug("Real scsi messages.\n");
 
 	/*
-	 *      Obtain an I2O message. If there are none free then
-	 *      throw it back to the scsi layer
-	 */
-
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return SCSI_MLQUEUE_HOST_BUSY;
-
-	/*
 	 *      Put together a scsi execscb message
 	 */
-
-	len = SCpnt->request_bufflen;
-
 	switch (SCpnt->sc_data_direction) {
 	case PCI_DMA_NONE:
-		scsi_flags = 0x00000000;	// DATA NO XFER
-		sg_flags = 0x00000000;
+		/* DATA NO XFER */
+		sgl_offset = SGL_OFFSET_0;
 		break;
 
 	case PCI_DMA_TODEVICE:
-		scsi_flags = 0x80000000;	// DATA OUT (iop-->dev)
-		sg_flags = 0x14000000;
+		/* DATA OUT (iop-->dev) */
+		scsi_flags |= 0x80000000;
+		sgl_offset = SGL_OFFSET_10;
 		break;
 
 	case PCI_DMA_FROMDEVICE:
-		scsi_flags = 0x40000000;	// DATA IN  (iop<--dev)
-		sg_flags = 0x10000000;
+		/* DATA IN  (iop<--dev) */
+		scsi_flags |= 0x40000000;
+		sgl_offset = SGL_OFFSET_10;
 		break;
 
 	default:
 		/* Unknown - kill the command */
 		SCpnt->result = DID_NO_CONNECT << 16;
 		done(SCpnt);
-		return 0;
+		goto exit;
 	}
 
-	writel(I2O_CMD_SCSI_EXEC << 24 | HOST_TID << 12 | tid, &msg->u.head[1]);
+	/*
+	 *      Obtain an I2O message. If there are none free then
+	 *      throw it back to the scsi layer
+	 */
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY) {
+		rc = SCSI_MLQUEUE_HOST_BUSY;
+		goto exit;
+	}
+
+	mptr = &msg->body[0];
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC
+	if (c->adaptec) {
+		u32 adpt_flags = 0;
+
+		if (SCpnt->sc_request && SCpnt->sc_request->upper_private_data) {
+			i2o_sg_io_hdr_t __user *usr_ptr =
+			    ((Sg_request *) (SCpnt->sc_request->
+					     upper_private_data))->header.
+			    usr_ptr;
+
+			if (usr_ptr)
+				get_user(adpt_flags, &usr_ptr->flags);
+		}
+
+		switch (i2o_dev->lct_data.class_id) {
+		case I2O_CLASS_EXECUTIVE:
+		case I2O_CLASS_RANDOM_BLOCK_STORAGE:
+			/* interpret flag has to be set for executive */
+			adpt_flags ^= I2O_DPT_SG_FLAG_INTERPRET;
+			break;
+
+		default:
+			break;
+		}
+
+		/*
+		 * for Adaptec controllers we use the PRIVATE command, because
+		 * the normal SCSI EXEC doesn't support all SCSI commands on
+		 * all controllers (for example READ CAPACITY).
+		 */
+		if (sgl_offset == SGL_OFFSET_10)
+			sgl_offset = SGL_OFFSET_12;
+		cmd = I2O_CMD_PRIVATE << 24;
+		writel(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC, mptr++);
+		writel(adpt_flags | tid, mptr++);
+	}
+#endif
+
+	writel(cmd | HOST_TID << 12 | tid, &msg->u.head[1]);
 	writel(i2o_scsi_driver.context, &msg->u.s.icntxt);
 
 	/* We want the SCSI control block back */
@@ -626,7 +640,7 @@
 	 */
 
 	/* Attach tags to the devices */
-	/*
+	/* FIXME: implement
 	   if(SCpnt->device->tagged_supported) {
 	   if(SCpnt->tag == HEAD_OF_QUEUE_TAG)
 	   scsi_flags |= 0x01000000;
@@ -635,67 +649,35 @@
 	   }
 	 */
 
-	/* Direction, disconnect ok, tag, CDBLen */
-	writel(scsi_flags | 0x20200000 | SCpnt->cmd_len, &msg->body[0]);
-
-	mptr = &msg->body[1];
+	writel(scsi_flags | SCpnt->cmd_len, mptr++);
 
 	/* Write SCSI command into the message - always 16 byte block */
 	memcpy_toio(mptr, SCpnt->cmnd, 16);
 	mptr += 4;
-	lenptr = mptr++;	/* Remember me - fill in when we know */
 
-	reqlen = 12;		// SINGLE SGE
+	if (sgl_offset != SGL_OFFSET_0) {
+		/* write size of data addressed by SGL */
+		writel(SCpnt->request_bufflen, mptr++);
 
-	/* Now fill in the SGList and command */
-	if (SCpnt->use_sg) {
-		struct scatterlist *sg;
-		int sg_count;
-
-		sg = SCpnt->request_buffer;
-		len = 0;
-
-		sg_count = dma_map_sg(dev, sg, SCpnt->use_sg,
-				      SCpnt->sc_data_direction);
-
-		if (unlikely(sg_count <= 0))
-			return -ENOMEM;
-
-		for (i = SCpnt->use_sg; i > 0; i--) {
-			if (i == 1)
-				sg_flags |= 0xC0000000;
-			writel(sg_flags | sg_dma_len(sg), mptr++);
-			writel(sg_dma_address(sg), mptr++);
-			len += sg_dma_len(sg);
-			sg++;
+		/* Now fill in the SGList and command */
+		if (SCpnt->use_sg) {
+			if (!i2o_dma_map_sg(c, SCpnt->request_buffer,
+					    SCpnt->use_sg,
+					    SCpnt->sc_data_direction, &mptr))
+				goto nomem;
+		} else {
+			SCpnt->SCp.dma_handle =
+			    i2o_dma_map_single(c, SCpnt->request_buffer,
+					       SCpnt->request_bufflen,
+					       SCpnt->sc_data_direction, &mptr);
+			if (dma_mapping_error(SCpnt->SCp.dma_handle))
+				goto nomem;
 		}
-
-		reqlen = mptr - &msg->u.head[0];
-		writel(len, lenptr);
-	} else {
-		len = SCpnt->request_bufflen;
-
-		writel(len, lenptr);
-
-		if (len > 0) {
-			dma_addr_t dma_addr;
-
-			dma_addr = dma_map_single(dev, SCpnt->request_buffer,
-						  SCpnt->request_bufflen,
-						  SCpnt->sc_data_direction);
-			if (!dma_addr)
-				return -ENOMEM;
-
-			SCpnt->SCp.ptr = (void *)(unsigned long)dma_addr;
-			sg_flags |= 0xC0000000;
-			writel(sg_flags | SCpnt->request_bufflen, mptr++);
-			writel(dma_addr, mptr++);
-		} else
-			reqlen = 9;
 	}
 
 	/* Stick the headers on */
-	writel(reqlen << 16 | SGL_OFFSET_10, &msg->u.head[0]);
+	writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset,
+	       &msg->u.head[0]);
 
 	/* Queue the message */
 	i2o_msg_post(c, m);
@@ -703,6 +685,13 @@
 	osm_debug("Issued %ld\n", SCpnt->serial_number);
 
 	return 0;
+
+      nomem:
+	rc = -ENOMEM;
+	i2o_msg_nop(c, m);
+
+      exit:
+	return rc;
 };
 
 /**
diff --git a/drivers/message/i2o/iop.c b/drivers/message/i2o/iop.c
index 50c8ced..42f8b81 100644
--- a/drivers/message/i2o/iop.c
+++ b/drivers/message/i2o/iop.c
@@ -28,8 +28,10 @@
 #include <linux/module.h>
 #include <linux/i2o.h>
 #include <linux/delay.h>
+#include "core.h"
 
-#define OSM_VERSION	"$Rev$"
+#define OSM_NAME	"i2o"
+#define OSM_VERSION	"1.288"
 #define OSM_DESCRIPTION	"I2O subsystem"
 
 /* global I2O controller list */
@@ -43,20 +45,6 @@
 
 static int i2o_hrt_get(struct i2o_controller *c);
 
-/* Module internal functions from other sources */
-extern struct i2o_driver i2o_exec_driver;
-extern int i2o_exec_lct_get(struct i2o_controller *);
-extern void i2o_device_remove(struct i2o_device *);
-
-extern int __init i2o_driver_init(void);
-extern void __exit i2o_driver_exit(void);
-extern int __init i2o_exec_init(void);
-extern void __exit i2o_exec_exit(void);
-extern int __init i2o_pci_init(void);
-extern void __exit i2o_pci_exit(void);
-extern int i2o_device_init(void);
-extern void i2o_device_exit(void);
-
 /**
  *	i2o_msg_nop - Returns a message which is not used
  *	@c: I2O controller from which the message was created
@@ -68,7 +56,7 @@
  */
 void i2o_msg_nop(struct i2o_controller *c, u32 m)
 {
-	struct i2o_message __iomem *msg = c->in_queue.virt + m;
+	struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m);
 
 	writel(THREE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);
 	writel(I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID,
@@ -92,16 +80,16 @@
  *	address from the read port (see the i2o spec). If no message is
  *	available returns I2O_QUEUE_EMPTY and msg is leaved untouched.
  */
-u32 i2o_msg_get_wait(struct i2o_controller *c, struct i2o_message __iomem **msg,
-		     int wait)
+u32 i2o_msg_get_wait(struct i2o_controller *c,
+		     struct i2o_message __iomem ** msg, int wait)
 {
 	unsigned long timeout = jiffies + wait * HZ;
 	u32 m;
 
 	while ((m = i2o_msg_get(c, msg)) == I2O_QUEUE_EMPTY) {
 		if (time_after(jiffies, timeout)) {
-			pr_debug("%s: Timeout waiting for message frame.\n",
-				 c->name);
+			osm_debug("%s: Timeout waiting for message frame.\n",
+				  c->name);
 			return I2O_QUEUE_EMPTY;
 		}
 		set_current_state(TASK_UNINTERRUPTIBLE);
@@ -129,13 +117,13 @@
 	unsigned long flags;
 
 	if (!ptr)
-		printk(KERN_ERR "%s: couldn't add NULL pointer to context list!"
-		       "\n", c->name);
+		osm_err("%s: couldn't add NULL pointer to context list!\n",
+			c->name);
 
 	entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
 	if (!entry) {
-		printk(KERN_ERR "%s: Could not allocate memory for context "
-		       "list element\n", c->name);
+		osm_err("%s: Could not allocate memory for context list element"
+			"\n", c->name);
 		return 0;
 	}
 
@@ -154,7 +142,7 @@
 
 	spin_unlock_irqrestore(&c->context_list_lock, flags);
 
-	pr_debug("%s: Add context to list %p -> %d\n", c->name, ptr, context);
+	osm_debug("%s: Add context to list %p -> %d\n", c->name, ptr, context);
 
 	return entry->context;
 };
@@ -186,11 +174,11 @@
 	spin_unlock_irqrestore(&c->context_list_lock, flags);
 
 	if (!context)
-		printk(KERN_WARNING "%s: Could not remove nonexistent ptr "
-		       "%p\n", c->name, ptr);
+		osm_warn("%s: Could not remove nonexistent ptr %p\n", c->name,
+			 ptr);
 
-	pr_debug("%s: remove ptr from context list %d -> %p\n", c->name,
-		 context, ptr);
+	osm_debug("%s: remove ptr from context list %d -> %p\n", c->name,
+		  context, ptr);
 
 	return context;
 };
@@ -220,11 +208,10 @@
 	spin_unlock_irqrestore(&c->context_list_lock, flags);
 
 	if (!ptr)
-		printk(KERN_WARNING "%s: context id %d not found\n", c->name,
-		       context);
+		osm_warn("%s: context id %d not found\n", c->name, context);
 
-	pr_debug("%s: get ptr from context list %d -> %p\n", c->name, context,
-		 ptr);
+	osm_debug("%s: get ptr from context list %d -> %p\n", c->name, context,
+		  ptr);
 
 	return ptr;
 };
@@ -252,11 +239,11 @@
 	spin_unlock_irqrestore(&c->context_list_lock, flags);
 
 	if (!context)
-		printk(KERN_WARNING "%s: Could not find nonexistent ptr "
-		       "%p\n", c->name, ptr);
+		osm_warn("%s: Could not find nonexistent ptr %p\n", c->name,
+			 ptr);
 
-	pr_debug("%s: get context id from context list %p -> %d\n", c->name,
-		 ptr, context);
+	osm_debug("%s: get context id from context list %p -> %d\n", c->name,
+		  ptr, context);
 
 	return context;
 };
@@ -336,10 +323,9 @@
 
 	/* Long timeout needed for quiesce if lots of devices */
 	if ((rc = i2o_msg_post_wait(c, m, 240)))
-		printk(KERN_INFO "%s: Unable to quiesce (status=%#x).\n",
-		       c->name, -rc);
+		osm_info("%s: Unable to quiesce (status=%#x).\n", c->name, -rc);
 	else
-		pr_debug("%s: Quiesced.\n", c->name);
+		osm_debug("%s: Quiesced.\n", c->name);
 
 	i2o_status_get(c);	// Entered READY state
 
@@ -377,10 +363,9 @@
 
 	/* How long of a timeout do we need? */
 	if ((rc = i2o_msg_post_wait(c, m, 240)))
-		printk(KERN_ERR "%s: Could not enable (status=%#x).\n",
-		       c->name, -rc);
+		osm_err("%s: Could not enable (status=%#x).\n", c->name, -rc);
 	else
-		pr_debug("%s: Enabled.\n", c->name);
+		osm_debug("%s: Enabled.\n", c->name);
 
 	i2o_status_get(c);	// entered OPERATIONAL state
 
@@ -444,20 +429,78 @@
 	       &msg->u.head[1]);
 
 	if ((rc = i2o_msg_post_wait(c, m, 30)))
-		printk(KERN_INFO "%s: Unable to clear (status=%#x).\n",
-		       c->name, -rc);
+		osm_info("%s: Unable to clear (status=%#x).\n", c->name, -rc);
 	else
-		pr_debug("%s: Cleared.\n", c->name);
+		osm_debug("%s: Cleared.\n", c->name);
 
 	/* Enable all IOPs */
 	i2o_iop_enable_all();
 
-	i2o_status_get(c);
-
 	return rc;
 }
 
 /**
+ *	i2o_iop_init_outbound_queue - setup the outbound message queue
+ *	@c: I2O controller
+ *
+ *	Clear and (re)initialize IOP's outbound queue and post the message
+ *	frames to the IOP.
+ *
+ *	Returns 0 on success or a negative errno code on failure.
+ */
+static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
+{
+	volatile u8 *status = c->status.virt;
+	u32 m;
+	struct i2o_message __iomem *msg;
+	ulong timeout;
+	int i;
+
+	osm_debug("%s: Initializing Outbound Queue...\n", c->name);
+
+	memset(c->status.virt, 0, 4);
+
+	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
+	if (m == I2O_QUEUE_EMPTY)
+		return -ETIMEDOUT;
+
+	writel(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6, &msg->u.head[0]);
+	writel(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | ADAPTER_TID,
+	       &msg->u.head[1]);
+	writel(i2o_exec_driver.context, &msg->u.s.icntxt);
+	writel(0x00000000, &msg->u.s.tcntxt);
+	writel(PAGE_SIZE, &msg->body[0]);
+	/* Outbound msg frame size in words and Initcode */
+	writel(I2O_OUTBOUND_MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]);
+	writel(0xd0000004, &msg->body[2]);
+	writel(i2o_dma_low(c->status.phys), &msg->body[3]);
+	writel(i2o_dma_high(c->status.phys), &msg->body[4]);
+
+	i2o_msg_post(c, m);
+
+	timeout = jiffies + I2O_TIMEOUT_INIT_OUTBOUND_QUEUE * HZ;
+	while (*status <= I2O_CMD_IN_PROGRESS) {
+		if (time_after(jiffies, timeout)) {
+			osm_warn("%s: Timeout Initializing\n", c->name);
+			return -ETIMEDOUT;
+		}
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(1);
+	}
+
+	m = c->out_queue.phys;
+
+	/* Post frames */
+	for (i = 0; i < I2O_MAX_OUTBOUND_MSG_FRAMES; i++) {
+		i2o_flush_reply(c, m);
+		udelay(1);	/* Promise */
+		m += I2O_OUTBOUND_MSG_FRAME_SIZE * sizeof(u32);
+	}
+
+	return 0;
+}
+
+/**
  *	i2o_iop_reset - reset an I2O controller
  *	@c: controller to reset
  *
@@ -468,20 +511,20 @@
  */
 static int i2o_iop_reset(struct i2o_controller *c)
 {
-	u8 *status = c->status.virt;
+	volatile u8 *status = c->status.virt;
 	struct i2o_message __iomem *msg;
 	u32 m;
 	unsigned long timeout;
 	i2o_status_block *sb = c->status_block.virt;
 	int rc = 0;
 
-	pr_debug("%s: Resetting controller\n", c->name);
+	osm_debug("%s: Resetting controller\n", c->name);
 
 	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
 	if (m == I2O_QUEUE_EMPTY)
 		return -ETIMEDOUT;
 
-	memset(status, 0, 8);
+	memset(c->status_block.virt, 0, 8);
 
 	/* Quiesce all IOPs first */
 	i2o_iop_quiesce_all();
@@ -493,49 +536,43 @@
 	writel(0, &msg->u.s.tcntxt);	//FIXME: use reasonable transaction context
 	writel(0, &msg->body[0]);
 	writel(0, &msg->body[1]);
-	writel(i2o_ptr_low((void *)c->status.phys), &msg->body[2]);
-	writel(i2o_ptr_high((void *)c->status.phys), &msg->body[3]);
+	writel(i2o_dma_low(c->status.phys), &msg->body[2]);
+	writel(i2o_dma_high(c->status.phys), &msg->body[3]);
 
 	i2o_msg_post(c, m);
 
 	/* Wait for a reply */
 	timeout = jiffies + I2O_TIMEOUT_RESET * HZ;
 	while (!*status) {
-		if (time_after(jiffies, timeout)) {
-			printk(KERN_ERR "%s: IOP reset timeout.\n", c->name);
-			rc = -ETIMEDOUT;
-			goto exit;
-		}
-
-		/* Promise bug */
-		if (status[1] || status[4]) {
-			*status = 0;
+		if (time_after(jiffies, timeout))
 			break;
-		}
 
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		schedule_timeout(1);
-
-		rmb();
 	}
 
-	if (*status == I2O_CMD_IN_PROGRESS) {
+	switch (*status) {
+	case I2O_CMD_REJECTED:
+		osm_warn("%s: IOP reset rejected\n", c->name);
+		rc = -EPERM;
+		break;
+
+	case I2O_CMD_IN_PROGRESS:
 		/*
 		 * Once the reset is sent, the IOP goes into the INIT state
-		 * which is indeterminate.  We need to wait until the IOP
-		 * has rebooted before we can let the system talk to
-		 * it. We read the inbound Free_List until a message is
-		 * available. If we can't read one in the given ammount of
-		 * time, we assume the IOP could not reboot properly.
+		 * which is indeterminate. We need to wait until the IOP has
+		 * rebooted before we can let the system talk to it. We read
+		 * the inbound Free_List until a message is available. If we
+		 * can't read one in the given ammount of time, we assume the
+		 * IOP could not reboot properly.
 		 */
-		pr_debug("%s: Reset in progress, waiting for reboot...\n",
-			 c->name);
+		osm_debug("%s: Reset in progress, waiting for reboot...\n",
+			  c->name);
 
 		m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET);
 		while (m == I2O_QUEUE_EMPTY) {
 			if (time_after(jiffies, timeout)) {
-				printk(KERN_ERR "%s: IOP reset timeout.\n",
-				       c->name);
+				osm_err("%s: IOP reset timeout.\n", c->name);
 				rc = -ETIMEDOUT;
 				goto exit;
 			}
@@ -545,20 +582,27 @@
 			m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_RESET);
 		}
 		i2o_msg_nop(c, m);
+
+		/* from here all quiesce commands are safe */
+		c->no_quiesce = 0;
+
+		/* verify if controller is in state RESET */
+		i2o_status_get(c);
+
+		if (!c->promise && (sb->iop_state != ADAPTER_STATE_RESET))
+			osm_warn("%s: reset completed, but adapter not in RESET"
+				 " state.\n", c->name);
+		else
+			osm_debug("%s: reset completed.\n", c->name);
+
+		break;
+
+	default:
+		osm_err("%s: IOP reset timeout.\n", c->name);
+		rc = -ETIMEDOUT;
+		break;
 	}
 
-	/* from here all quiesce commands are safe */
-	c->no_quiesce = 0;
-
-	/* If IopReset was rejected or didn't perform reset, try IopClear */
-	i2o_status_get(c);
-	if (*status == I2O_CMD_REJECTED || sb->iop_state != ADAPTER_STATE_RESET) {
-		printk(KERN_WARNING "%s: Reset rejected, trying to clear\n",
-		       c->name);
-		i2o_iop_clear(c);
-	} else
-		pr_debug("%s: Reset completed.\n", c->name);
-
       exit:
 	/* Enable all IOPs */
 	i2o_iop_enable_all();
@@ -567,88 +611,6 @@
 };
 
 /**
- *	i2o_iop_init_outbound_queue - setup the outbound message queue
- *	@c: I2O controller
- *
- *	Clear and (re)initialize IOP's outbound queue and post the message
- *	frames to the IOP.
- *
- *	Returns 0 on success or a negative errno code on failure.
- */
-static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
-{
-	u8 *status = c->status.virt;
-	u32 m;
-	struct i2o_message __iomem *msg;
-	ulong timeout;
-	int i;
-
-	pr_debug("%s: Initializing Outbound Queue...\n", c->name);
-
-	memset(status, 0, 4);
-
-	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
-	if (m == I2O_QUEUE_EMPTY)
-		return -ETIMEDOUT;
-
-	writel(EIGHT_WORD_MSG_SIZE | TRL_OFFSET_6, &msg->u.head[0]);
-	writel(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | ADAPTER_TID,
-	       &msg->u.head[1]);
-	writel(i2o_exec_driver.context, &msg->u.s.icntxt);
-	writel(0x0106, &msg->u.s.tcntxt);	/* FIXME: why 0x0106, maybe in
-						   Spec? */
-	writel(PAGE_SIZE, &msg->body[0]);
-	writel(MSG_FRAME_SIZE << 16 | 0x80, &msg->body[1]);	/* Outbound msg frame
-								   size in words and Initcode */
-	writel(0xd0000004, &msg->body[2]);
-	writel(i2o_ptr_low((void *)c->status.phys), &msg->body[3]);
-	writel(i2o_ptr_high((void *)c->status.phys), &msg->body[4]);
-
-	i2o_msg_post(c, m);
-
-	timeout = jiffies + I2O_TIMEOUT_INIT_OUTBOUND_QUEUE * HZ;
-	while (*status <= I2O_CMD_IN_PROGRESS) {
-		if (time_after(jiffies, timeout)) {
-			printk(KERN_WARNING "%s: Timeout Initializing\n",
-			       c->name);
-			return -ETIMEDOUT;
-		}
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(1);
-
-		rmb();
-	}
-
-	m = c->out_queue.phys;
-
-	/* Post frames */
-	for (i = 0; i < NMBR_MSG_FRAMES; i++) {
-		i2o_flush_reply(c, m);
-		udelay(1);	/* Promise */
-		m += MSG_FRAME_SIZE * 4;
-	}
-
-	return 0;
-}
-
-/**
- *	i2o_iop_send_nop - send a core NOP message
- *	@c: controller
- *
- *	Send a no-operation message with a reply set to cause no
- *	action either. Needed for bringing up promise controllers.
- */
-static int i2o_iop_send_nop(struct i2o_controller *c)
-{
-	struct i2o_message __iomem *msg;
-	u32 m = i2o_msg_get_wait(c, &msg, HZ);
-	if (m == I2O_QUEUE_EMPTY)
-		return -ETIMEDOUT;
-	i2o_msg_nop(c, m);
-	return 0;
-}
-
-/**
  *	i2o_iop_activate - Bring controller up to HOLD
  *	@c: controller
  *
@@ -659,78 +621,62 @@
  */
 static int i2o_iop_activate(struct i2o_controller *c)
 {
-	struct pci_dev *i960 = NULL;
 	i2o_status_block *sb = c->status_block.virt;
 	int rc;
-
-	if (c->promise) {
-		/* Beat up the hardware first of all */
-		i960 =
-		    pci_find_slot(c->pdev->bus->number,
-				  PCI_DEVFN(PCI_SLOT(c->pdev->devfn), 0));
-		if (i960)
-			pci_write_config_word(i960, 0x42, 0);
-
-		/* Follow this sequence precisely or the controller
-		   ceases to perform useful functions until reboot */
-		if ((rc = i2o_iop_send_nop(c)))
-			return rc;
-
-		if ((rc = i2o_iop_reset(c)))
-			return rc;
-	}
+	int state;
 
 	/* In INIT state, Wait Inbound Q to initialize (in i2o_status_get) */
 	/* In READY state, Get status */
 
 	rc = i2o_status_get(c);
 	if (rc) {
-		printk(KERN_INFO "%s: Unable to obtain status, "
-		       "attempting a reset.\n", c->name);
-		if (i2o_iop_reset(c))
+		osm_info("%s: Unable to obtain status, attempting a reset.\n",
+			 c->name);
+		rc = i2o_iop_reset(c);
+		if (rc)
 			return rc;
 	}
 
 	if (sb->i2o_version > I2OVER15) {
-		printk(KERN_ERR "%s: Not running version 1.5 of the I2O "
-		       "Specification.\n", c->name);
+		osm_err("%s: Not running version 1.5 of the I2O Specification."
+			"\n", c->name);
 		return -ENODEV;
 	}
 
 	switch (sb->iop_state) {
 	case ADAPTER_STATE_FAULTED:
-		printk(KERN_CRIT "%s: hardware fault\n", c->name);
-		return -ENODEV;
+		osm_err("%s: hardware fault\n", c->name);
+		return -EFAULT;
 
 	case ADAPTER_STATE_READY:
 	case ADAPTER_STATE_OPERATIONAL:
 	case ADAPTER_STATE_HOLD:
 	case ADAPTER_STATE_FAILED:
-		pr_debug("%s: already running, trying to reset...\n", c->name);
-		if (i2o_iop_reset(c))
-			return -ENODEV;
+		osm_debug("%s: already running, trying to reset...\n", c->name);
+		rc = i2o_iop_reset(c);
+		if (rc)
+			return rc;
 	}
 
+	/* preserve state */
+	state = sb->iop_state;
+
 	rc = i2o_iop_init_outbound_queue(c);
 	if (rc)
 		return rc;
 
-	if (c->promise) {
-		if ((rc = i2o_iop_send_nop(c)))
-			return rc;
+	/* if adapter was not in RESET state clear now */
+	if (state != ADAPTER_STATE_RESET)
+		i2o_iop_clear(c);
 
-		if ((rc = i2o_status_get(c)))
-			return rc;
+	i2o_status_get(c);
 
-		if (i960)
-			pci_write_config_word(i960, 0x42, 0x3FF);
+	if (sb->iop_state != ADAPTER_STATE_HOLD) {
+		osm_err("%s: failed to bring IOP into HOLD state\n", c->name);
+		return -EIO;
 	}
 
-	/* In HOLD state */
-
-	rc = i2o_hrt_get(c);
-
-	return rc;
+	return i2o_hrt_get(c);
 };
 
 /**
@@ -756,20 +702,18 @@
 		res->flags = IORESOURCE_MEM;
 		res->start = 0;
 		res->end = 0;
-		printk(KERN_INFO "%s: requires private memory resources.\n",
-		       c->name);
+		osm_info("%s: requires private memory resources.\n", c->name);
 		root = pci_find_parent_resource(c->pdev, res);
 		if (root == NULL)
-			printk(KERN_WARNING "%s: Can't find parent resource!\n",
-			       c->name);
+			osm_warn("%s: Can't find parent resource!\n", c->name);
 		if (root && allocate_resource(root, res, sb->desired_mem_size, sb->desired_mem_size, sb->desired_mem_size, 1 << 20,	/* Unspecified, so use 1Mb and play safe */
 					      NULL, NULL) >= 0) {
 			c->mem_alloc = 1;
 			sb->current_mem_size = 1 + res->end - res->start;
 			sb->current_mem_base = res->start;
-			printk(KERN_INFO "%s: allocated %ld bytes of PCI memory"
-			       " at 0x%08lX.\n", c->name,
-			       1 + res->end - res->start, res->start);
+			osm_info("%s: allocated %ld bytes of PCI memory at "
+				 "0x%08lX.\n", c->name,
+				 1 + res->end - res->start, res->start);
 		}
 	}
 
@@ -779,20 +723,18 @@
 		res->flags = IORESOURCE_IO;
 		res->start = 0;
 		res->end = 0;
-		printk(KERN_INFO "%s: requires private memory resources.\n",
-		       c->name);
+		osm_info("%s: requires private memory resources.\n", c->name);
 		root = pci_find_parent_resource(c->pdev, res);
 		if (root == NULL)
-			printk(KERN_WARNING "%s: Can't find parent resource!\n",
-			       c->name);
+			osm_warn("%s: Can't find parent resource!\n", c->name);
 		if (root && allocate_resource(root, res, sb->desired_io_size, sb->desired_io_size, sb->desired_io_size, 1 << 20,	/* Unspecified, so use 1Mb and play safe */
 					      NULL, NULL) >= 0) {
 			c->io_alloc = 1;
 			sb->current_io_size = 1 + res->end - res->start;
 			sb->current_mem_base = res->start;
-			printk(KERN_INFO "%s: allocated %ld bytes of PCI I/O at"
-			       " 0x%08lX.\n", c->name,
-			       1 + res->end - res->start, res->start);
+			osm_info("%s: allocated %ld bytes of PCI I/O at 0x%08lX"
+				 ".\n", c->name, 1 + res->end - res->start,
+				 res->start);
 		}
 	}
 
@@ -836,10 +778,10 @@
 			 PCI_DMA_TODEVICE);
 
 	if (rc < 0)
-		printk(KERN_ERR "%s: Unable to set SysTab (status=%#x).\n",
-		       c->name, -rc);
+		osm_err("%s: Unable to set SysTab (status=%#x).\n", c->name,
+			-rc);
 	else
-		pr_debug("%s: SysTab set.\n", c->name);
+		osm_debug("%s: SysTab set.\n", c->name);
 
 	i2o_status_get(c);	// Entered READY state
 
@@ -863,7 +805,7 @@
 		return rc;
 
 	/* In READY state */
-	pr_debug("%s: Attempting to enable...\n", c->name);
+	osm_debug("%s: Attempting to enable...\n", c->name);
 	rc = i2o_iop_enable(c);
 	if (rc)
 		return rc;
@@ -882,7 +824,7 @@
 {
 	struct i2o_device *dev, *tmp;
 
-	pr_debug("%s: deleting controller\n", c->name);
+	osm_debug("%s: deleting controller\n", c->name);
 
 	i2o_driver_notify_controller_remove_all(c);
 
@@ -891,8 +833,12 @@
 	list_for_each_entry_safe(dev, tmp, &c->devices, list)
 	    i2o_device_remove(dev);
 
+	device_del(&c->device);
+
 	/* Ask the IOP to switch to RESET state */
 	i2o_iop_reset(c);
+
+	put_device(&c->device);
 }
 
 /**
@@ -927,8 +873,7 @@
 
 	systab = i2o_systab.virt = kmalloc(i2o_systab.len, GFP_KERNEL);
 	if (!systab) {
-		printk(KERN_ERR "i2o: unable to allocate memory for System "
-		       "Table\n");
+		osm_err("unable to allocate memory for System Table\n");
 		return -ENOMEM;
 	}
 	memset(systab, 0, i2o_systab.len);
@@ -940,8 +885,8 @@
 		i2o_status_block *sb;
 
 		if (count >= num_controllers) {
-			printk(KERN_ERR "i2o: controller added while building "
-			       "system table\n");
+			osm_err("controller added while building system table"
+				"\n");
 			break;
 		}
 
@@ -955,9 +900,8 @@
 		 * it is techninically not part of the I2O subsystem...
 		 */
 		if (unlikely(i2o_status_get(c))) {
-			printk(KERN_ERR "%s: Deleting b/c could not get status"
-			       " while attempting to build system table\n",
-			       c->name);
+			osm_err("%s: Deleting b/c could not get status while "
+				"attempting to build system table\n", c->name);
 			i2o_iop_remove(c);
 			continue;	// try the next one
 		}
@@ -971,8 +915,10 @@
 		systab->iops[count].frame_size = sb->inbound_frame_size;
 		systab->iops[count].last_changed = change_ind;
 		systab->iops[count].iop_capabilities = sb->iop_capabilities;
-		systab->iops[count].inbound_low = i2o_ptr_low(c->post_port);
-		systab->iops[count].inbound_high = i2o_ptr_high(c->post_port);
+		systab->iops[count].inbound_low =
+		    i2o_dma_low(c->base.phys + I2O_IN_PORT);
+		systab->iops[count].inbound_high =
+		    i2o_dma_high(c->base.phys + I2O_IN_PORT);
 
 		count++;
 	}
@@ -1010,11 +956,11 @@
 {
 	struct i2o_message __iomem *msg;
 	u32 m;
-	u8 *status_block;
+	volatile u8 *status_block;
 	unsigned long timeout;
 
 	status_block = (u8 *) c->status_block.virt;
-	memset(status_block, 0, sizeof(i2o_status_block));
+	memset(c->status_block.virt, 0, sizeof(i2o_status_block));
 
 	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);
 	if (m == I2O_QUEUE_EMPTY)
@@ -1027,8 +973,8 @@
 	writel(0, &msg->u.s.tcntxt);	// FIXME: use resonable transaction context
 	writel(0, &msg->body[0]);
 	writel(0, &msg->body[1]);
-	writel(i2o_ptr_low((void *)c->status_block.phys), &msg->body[2]);
-	writel(i2o_ptr_high((void *)c->status_block.phys), &msg->body[3]);
+	writel(i2o_dma_low(c->status_block.phys), &msg->body[2]);
+	writel(i2o_dma_high(c->status_block.phys), &msg->body[3]);
 	writel(sizeof(i2o_status_block), &msg->body[4]);	/* always 88 bytes */
 
 	i2o_msg_post(c, m);
@@ -1037,14 +983,12 @@
 	timeout = jiffies + I2O_TIMEOUT_STATUS_GET * HZ;
 	while (status_block[87] != 0xFF) {
 		if (time_after(jiffies, timeout)) {
-			printk(KERN_ERR "%s: Get status timeout.\n", c->name);
+			osm_err("%s: Get status timeout.\n", c->name);
 			return -ETIMEDOUT;
 		}
 
 		set_current_state(TASK_UNINTERRUPTIBLE);
 		schedule_timeout(1);
-
-		rmb();
 	}
 
 #ifdef DEBUG
@@ -1088,8 +1032,8 @@
 		rc = i2o_msg_post_wait_mem(c, m, 20, &c->hrt);
 
 		if (rc < 0) {
-			printk(KERN_ERR "%s: Unable to get HRT (status=%#x)\n",
-			       c->name, -rc);
+			osm_err("%s: Unable to get HRT (status=%#x)\n", c->name,
+				-rc);
 			return rc;
 		}
 
@@ -1103,13 +1047,41 @@
 			return i2o_parse_hrt(c);
 	}
 
-	printk(KERN_ERR "%s: Unable to get HRT after %d tries, giving up\n",
-	       c->name, I2O_HRT_GET_TRIES);
+	osm_err("%s: Unable to get HRT after %d tries, giving up\n", c->name,
+		I2O_HRT_GET_TRIES);
 
 	return -EBUSY;
 }
 
 /**
+ *	i2o_iop_free - Free the i2o_controller struct
+ *	@c: I2O controller to free
+ */
+void i2o_iop_free(struct i2o_controller *c)
+{
+	kfree(c);
+};
+
+/**
+ *	i2o_iop_release - release the memory for a I2O controller
+ *	@dev: I2O controller which should be released
+ *
+ *	Release the allocated memory. This function is called if refcount of
+ *	device reaches 0 automatically.
+ */
+static void i2o_iop_release(struct device *dev)
+{
+	struct i2o_controller *c = to_i2o_controller(dev);
+
+	i2o_iop_free(c);
+};
+
+/* I2O controller class */
+static struct class i2o_controller_class = {
+	.name = "i2o_controller",
+};
+
+/**
  *	i2o_iop_alloc - Allocate and initialize a i2o_controller struct
  *
  *	Allocate the necessary memory for a i2o_controller struct and
@@ -1125,8 +1097,8 @@
 
 	c = kmalloc(sizeof(*c), GFP_KERNEL);
 	if (!c) {
-		printk(KERN_ERR "i2o: Insufficient memory to allocate a I2O "
-		       "controller.\n");
+		osm_err("i2o: Insufficient memory to allocate a I2O controller."
+			"\n");
 		return ERR_PTR(-ENOMEM);
 	}
 	memset(c, 0, sizeof(*c));
@@ -1137,6 +1109,16 @@
 	c->unit = unit++;
 	sprintf(c->name, "iop%d", c->unit);
 
+	device_initialize(&c->device);
+	class_device_initialize(&c->classdev);
+
+	c->device.release = &i2o_iop_release;
+	c->classdev.class = &i2o_controller_class;
+	c->classdev.dev = &c->device;
+
+	snprintf(c->device.bus_id, BUS_ID_SIZE, "iop%d", c->unit);
+	snprintf(c->classdev.class_id, BUS_ID_SIZE, "iop%d", c->unit);
+
 #if BITS_PER_LONG == 64
 	spin_lock_init(&c->context_list_lock);
 	atomic_set(&c->context_list_counter, 0);
@@ -1147,15 +1129,6 @@
 };
 
 /**
- *	i2o_iop_free - Free the i2o_controller struct
- *	@c: I2O controller to free
- */
-void i2o_iop_free(struct i2o_controller *c)
-{
-	kfree(c);
-};
-
-/**
  *	i2o_iop_add - Initialize the I2O controller and add him to the I2O core
  *	@c: controller
  *
@@ -1168,45 +1141,58 @@
 {
 	int rc;
 
-	printk(KERN_INFO "%s: Activating I2O controller...\n", c->name);
-	printk(KERN_INFO "%s: This may take a few minutes if there are many "
-	       "devices\n", c->name);
+	if ((rc = device_add(&c->device))) {
+		osm_err("%s: could not add controller\n", c->name);
+		goto iop_reset;
+	}
+
+	if ((rc = class_device_add(&c->classdev))) {
+		osm_err("%s: could not add controller class\n", c->name);
+		goto device_del;
+	}
+
+	osm_info("%s: Activating I2O controller...\n", c->name);
+	osm_info("%s: This may take a few minutes if there are many devices\n",
+		 c->name);
 
 	if ((rc = i2o_iop_activate(c))) {
-		printk(KERN_ERR "%s: could not activate controller\n",
-		       c->name);
-		i2o_iop_reset(c);
-		return rc;
+		osm_err("%s: could not activate controller\n", c->name);
+		goto class_del;
 	}
 
-	pr_debug("%s: building sys table...\n", c->name);
+	osm_debug("%s: building sys table...\n", c->name);
 
-	if ((rc = i2o_systab_build())) {
-		i2o_iop_reset(c);
-		return rc;
-	}
+	if ((rc = i2o_systab_build()))
+		goto class_del;
 
-	pr_debug("%s: online controller...\n", c->name);
+	osm_debug("%s: online controller...\n", c->name);
 
-	if ((rc = i2o_iop_online(c))) {
-		i2o_iop_reset(c);
-		return rc;
-	}
+	if ((rc = i2o_iop_online(c)))
+		goto class_del;
 
-	pr_debug("%s: getting LCT...\n", c->name);
+	osm_debug("%s: getting LCT...\n", c->name);
 
-	if ((rc = i2o_exec_lct_get(c))) {
-		i2o_iop_reset(c);
-		return rc;
-	}
+	if ((rc = i2o_exec_lct_get(c)))
+		goto class_del;
 
 	list_add(&c->list, &i2o_controllers);
 
 	i2o_driver_notify_controller_add_all(c);
 
-	printk(KERN_INFO "%s: Controller added\n", c->name);
+	osm_info("%s: Controller added\n", c->name);
 
 	return 0;
+
+      class_del:
+	class_device_del(&c->classdev);
+
+      device_del:
+	device_del(&c->device);
+
+      iop_reset:
+	i2o_iop_reset(c);
+
+	return rc;
 };
 
 /**
@@ -1264,16 +1250,18 @@
 	if (rc)
 		goto exit;
 
-	rc = i2o_driver_init();
-	if (rc)
+	if ((rc = class_register(&i2o_controller_class))) {
+		osm_err("can't register class i2o_controller\n");
 		goto device_exit;
+	}
 
-	rc = i2o_exec_init();
-	if (rc)
+	if ((rc = i2o_driver_init()))
+		goto class_exit;
+
+	if ((rc = i2o_exec_init()))
 		goto driver_exit;
 
-	rc = i2o_pci_init();
-	if (rc < 0)
+	if ((rc = i2o_pci_init()))
 		goto exec_exit;
 
 	return 0;
@@ -1284,6 +1272,9 @@
       driver_exit:
 	i2o_driver_exit();
 
+      class_exit:
+	class_unregister(&i2o_controller_class);
+
       device_exit:
 	i2o_device_exit();
 
@@ -1301,6 +1292,7 @@
 	i2o_pci_exit();
 	i2o_exec_exit();
 	i2o_driver_exit();
+	class_unregister(&i2o_controller_class);
 	i2o_device_exit();
 };
 
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c
index e772752..7a60fd7 100644
--- a/drivers/message/i2o/pci.c
+++ b/drivers/message/i2o/pci.c
@@ -30,53 +30,18 @@
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/i2o.h>
-
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif				// CONFIG_MTRR
-
-/* Module internal functions from other sources */
-extern struct i2o_controller *i2o_iop_alloc(void);
-extern void i2o_iop_free(struct i2o_controller *);
-
-extern int i2o_iop_add(struct i2o_controller *);
-extern void i2o_iop_remove(struct i2o_controller *);
-
-extern int i2o_driver_dispatch(struct i2o_controller *, u32,
-			       struct i2o_message *);
+#include "core.h"
 
 /* PCI device id table for all I2O controllers */
 static struct pci_device_id __devinitdata i2o_pci_ids[] = {
 	{PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)},
 	{PCI_DEVICE(PCI_VENDOR_ID_DPT, 0xa511)},
+	{.vendor = PCI_VENDOR_ID_INTEL,.device = 0x1962,
+	 .subvendor = PCI_VENDOR_ID_PROMISE,.subdevice = PCI_ANY_ID},
 	{0}
 };
 
 /**
- *	i2o_dma_realloc - Realloc DMA memory
- *	@dev: struct device pointer to the PCI device of the I2O controller
- *	@addr: pointer to a i2o_dma struct DMA buffer
- *	@len: new length of memory
- *	@gfp_mask: GFP mask
- *
- *	If there was something allocated in the addr, free it first. If len > 0
- *	than try to allocate it and write the addresses back to the addr
- *	structure. If len == 0 set the virtual address to NULL.
- *
- *	Returns the 0 on success or negative error code on failure.
- */
-int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr, size_t len,
-		    unsigned int gfp_mask)
-{
-	i2o_dma_free(dev, addr);
-
-	if (len)
-		return i2o_dma_alloc(dev, addr, len, gfp_mask);
-
-	return 0;
-};
-
-/**
  *	i2o_pci_free - Frees the DMA memory for the I2O controller
  *	@c: I2O controller to free
  *
@@ -91,19 +56,11 @@
 
 	i2o_dma_free(dev, &c->out_queue);
 	i2o_dma_free(dev, &c->status_block);
-	if (c->lct)
-		kfree(c->lct);
+	kfree(c->lct);
 	i2o_dma_free(dev, &c->dlct);
 	i2o_dma_free(dev, &c->hrt);
 	i2o_dma_free(dev, &c->status);
 
-#ifdef CONFIG_MTRR
-	if (c->mtrr_reg0 >= 0)
-		mtrr_del(c->mtrr_reg0, 0, 0);
-	if (c->mtrr_reg1 >= 0)
-		mtrr_del(c->mtrr_reg1, 0, 0);
-#endif
-
 	if (c->raptor && c->in_queue.virt)
 		iounmap(c->in_queue.virt);
 
@@ -178,14 +135,15 @@
 		       c->name, (unsigned long)c->base.phys,
 		       (unsigned long)c->base.len);
 
-	c->base.virt = ioremap(c->base.phys, c->base.len);
+	c->base.virt = ioremap_nocache(c->base.phys, c->base.len);
 	if (!c->base.virt) {
 		printk(KERN_ERR "%s: Unable to map controller.\n", c->name);
 		return -ENOMEM;
 	}
 
 	if (c->raptor) {
-		c->in_queue.virt = ioremap(c->in_queue.phys, c->in_queue.len);
+		c->in_queue.virt =
+		    ioremap_nocache(c->in_queue.phys, c->in_queue.len);
 		if (!c->in_queue.virt) {
 			printk(KERN_ERR "%s: Unable to map controller.\n",
 			       c->name);
@@ -195,43 +153,10 @@
 	} else
 		c->in_queue = c->base;
 
-	c->irq_mask = c->base.virt + 0x34;
-	c->post_port = c->base.virt + 0x40;
-	c->reply_port = c->base.virt + 0x44;
-
-#ifdef CONFIG_MTRR
-	/* Enable Write Combining MTRR for IOP's memory region */
-	c->mtrr_reg0 = mtrr_add(c->in_queue.phys, c->in_queue.len,
-				MTRR_TYPE_WRCOMB, 1);
-	c->mtrr_reg1 = -1;
-
-	if (c->mtrr_reg0 < 0)
-		printk(KERN_WARNING "%s: could not enable write combining "
-		       "MTRR\n", c->name);
-	else
-		printk(KERN_INFO "%s: using write combining MTRR\n", c->name);
-
-	/*
-	 * If it is an INTEL i960 I/O processor then set the first 64K to
-	 * Uncacheable since the region contains the messaging unit which
-	 * shouldn't be cached.
-	 */
-	if ((pdev->vendor == PCI_VENDOR_ID_INTEL ||
-	     pdev->vendor == PCI_VENDOR_ID_DPT) && !c->raptor) {
-		printk(KERN_INFO "%s: MTRR workaround for Intel i960 processor"
-		       "\n", c->name);
-		c->mtrr_reg1 = mtrr_add(c->base.phys, 0x10000,
-					MTRR_TYPE_UNCACHABLE, 1);
-
-		if (c->mtrr_reg1 < 0) {
-			printk(KERN_WARNING "%s: Error in setting "
-			       "MTRR_TYPE_UNCACHABLE\n", c->name);
-			mtrr_del(c->mtrr_reg0, c->in_queue.phys,
-				 c->in_queue.len);
-			c->mtrr_reg0 = -1;
-		}
-	}
-#endif
+	c->irq_status = c->base.virt + I2O_IRQ_STATUS;
+	c->irq_mask = c->base.virt + I2O_IRQ_MASK;
+	c->in_port = c->base.virt + I2O_IN_PORT;
+	c->out_port = c->base.virt + I2O_OUT_PORT;
 
 	if (i2o_dma_alloc(dev, &c->status, 8, GFP_KERNEL)) {
 		i2o_pci_free(c);
@@ -254,7 +179,10 @@
 		return -ENOMEM;
 	}
 
-	if (i2o_dma_alloc(dev, &c->out_queue, MSG_POOL_SIZE, GFP_KERNEL)) {
+	if (i2o_dma_alloc
+	    (dev, &c->out_queue,
+	     I2O_MAX_OUTBOUND_MSG_FRAMES * I2O_OUTBOUND_MSG_FRAME_SIZE *
+	     sizeof(u32), GFP_KERNEL)) {
 		i2o_pci_free(c);
 		return -ENOMEM;
 	}
@@ -276,51 +204,30 @@
 static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id, struct pt_regs *r)
 {
 	struct i2o_controller *c = dev_id;
-	struct device *dev = &c->pdev->dev;
-	struct i2o_message *m;
-	u32 mv;
+	u32 m;
+	irqreturn_t rc = IRQ_NONE;
 
-	/*
-	 * Old 960 steppings had a bug in the I2O unit that caused
-	 * the queue to appear empty when it wasn't.
-	 */
-	mv = I2O_REPLY_READ32(c);
-	if (mv == I2O_QUEUE_EMPTY) {
-		mv = I2O_REPLY_READ32(c);
-		if (unlikely(mv == I2O_QUEUE_EMPTY)) {
-			return IRQ_NONE;
-		} else
-			pr_debug("%s: 960 bug detected\n", c->name);
-	}
-
-	while (mv != I2O_QUEUE_EMPTY) {
-		/*
-		 * Map the message from the page frame map to kernel virtual.
-		 * Because bus_to_virt is deprecated, we have calculate the
-		 * location by ourself!
-		 */
-		m = i2o_msg_out_to_virt(c, mv);
-
-		/*
-		 *      Ensure this message is seen coherently but cachably by
-		 *      the processor
-		 */
-		dma_sync_single_for_cpu(dev, mv, MSG_FRAME_SIZE * 4,
-					PCI_DMA_FROMDEVICE);
+	while (readl(c->irq_status) & I2O_IRQ_OUTBOUND_POST) {
+		m = readl(c->out_port);
+		if (m == I2O_QUEUE_EMPTY) {
+			/*
+			 * Old 960 steppings had a bug in the I2O unit that
+			 * caused the queue to appear empty when it wasn't.
+			 */
+			m = readl(c->out_port);
+			if (unlikely(m == I2O_QUEUE_EMPTY))
+				break;
+		}
 
 		/* dispatch it */
-		if (i2o_driver_dispatch(c, mv, m))
+		if (i2o_driver_dispatch(c, m))
 			/* flush it if result != 0 */
-			i2o_flush_reply(c, mv);
+			i2o_flush_reply(c, m);
 
-		/*
-		 * That 960 bug again...
-		 */
-		mv = I2O_REPLY_READ32(c);
-		if (mv == I2O_QUEUE_EMPTY)
-			mv = I2O_REPLY_READ32(c);
+		rc = IRQ_HANDLED;
 	}
-	return IRQ_HANDLED;
+
+	return rc;
 }
 
 /**
@@ -336,7 +243,7 @@
 	struct pci_dev *pdev = c->pdev;
 	int rc;
 
-	I2O_IRQ_WRITE32(c, 0xffffffff);
+	writel(0xffffffff, c->irq_mask);
 
 	if (pdev->irq) {
 		rc = request_irq(pdev->irq, i2o_pci_interrupt, SA_SHIRQ,
@@ -348,7 +255,7 @@
 		}
 	}
 
-	I2O_IRQ_WRITE32(c, 0x00000000);
+	writel(0x00000000, c->irq_mask);
 
 	printk(KERN_INFO "%s: Installed at IRQ %d\n", c->name, pdev->irq);
 
@@ -363,7 +270,7 @@
  */
 static void i2o_pci_irq_disable(struct i2o_controller *c)
 {
-	I2O_IRQ_WRITE32(c, 0xffffffff);
+	writel(0xffffffff, c->irq_mask);
 
 	if (c->pdev->irq > 0)
 		free_irq(c->pdev->irq, c);
@@ -385,28 +292,25 @@
 {
 	struct i2o_controller *c;
 	int rc;
+	struct pci_dev *i960 = NULL;
 
 	printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n");
 
 	if ((pdev->class & 0xff) > 1) {
-		printk(KERN_WARNING "i2o: I2O controller found but does not "
-		       "support I2O 1.5 (skipping).\n");
+		printk(KERN_WARNING "i2o: %s does not support I2O 1.5 "
+		       "(skipping).\n", pci_name(pdev));
 		return -ENODEV;
 	}
 
 	if ((rc = pci_enable_device(pdev))) {
-		printk(KERN_WARNING "i2o: I2O controller found but could not be"
-		       " enabled.\n");
+		printk(KERN_WARNING "i2o: couldn't enable device %s\n",
+		       pci_name(pdev));
 		return rc;
 	}
 
-	printk(KERN_INFO "i2o: I2O controller found on bus %d at %d.\n",
-	       pdev->bus->number, pdev->devfn);
-
 	if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
-		printk(KERN_WARNING "i2o: I2O controller on bus %d at %d: No "
-		       "suitable DMA available!\n", pdev->bus->number,
-		       pdev->devfn);
+		printk(KERN_WARNING "i2o: no suitable DMA found for %s\n",
+		       pci_name(pdev));
 		rc = -ENODEV;
 		goto disable;
 	}
@@ -415,14 +319,16 @@
 
 	c = i2o_iop_alloc();
 	if (IS_ERR(c)) {
-		printk(KERN_ERR "i2o: memory for I2O controller could not be "
-		       "allocated\n");
+		printk(KERN_ERR "i2o: couldn't allocate memory for %s\n",
+		       pci_name(pdev));
 		rc = PTR_ERR(c);
 		goto disable;
-	}
+	} else
+		printk(KERN_INFO "%s: controller found (%s)\n", c->name,
+		       pci_name(pdev));
 
 	c->pdev = pdev;
-	c->device = pdev->dev;
+	c->device.parent = get_device(&pdev->dev);
 
 	/* Cards that fall apart if you hit them with large I/O loads... */
 	if (pdev->vendor == PCI_VENDOR_ID_NCR && pdev->device == 0x0630) {
@@ -432,16 +338,48 @@
 	}
 
 	if (pdev->subsystem_vendor == PCI_VENDOR_ID_PROMISE) {
+		/*
+		 * Expose the ship behind i960 for initialization, or it will
+		 * failed
+		 */
+		i960 =
+		    pci_find_slot(c->pdev->bus->number,
+				  PCI_DEVFN(PCI_SLOT(c->pdev->devfn), 0));
+
+		if (i960)
+			pci_write_config_word(i960, 0x42, 0);
+
 		c->promise = 1;
-		printk(KERN_INFO "%s: Promise workarounds activated.\n",
-		       c->name);
+		c->limit_sectors = 1;
 	}
 
+	if (pdev->subsystem_vendor == PCI_VENDOR_ID_DPT)
+		c->adaptec = 1;
+
 	/* Cards that go bananas if you quiesce them before you reset them. */
 	if (pdev->vendor == PCI_VENDOR_ID_DPT) {
 		c->no_quiesce = 1;
 		if (pdev->device == 0xa511)
 			c->raptor = 1;
+
+		if (pdev->subsystem_device == 0xc05a) {
+			c->limit_sectors = 1;
+			printk(KERN_INFO
+			       "%s: limit sectors per request to %d\n", c->name,
+			       I2O_MAX_SECTORS_LIMITED);
+		}
+#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
+		if (sizeof(dma_addr_t) > 4) {
+			if (pci_set_dma_mask(pdev, DMA_64BIT_MASK))
+				printk(KERN_INFO "%s: 64-bit DMA unavailable\n",
+				       c->name);
+			else {
+				c->pae_support = 1;
+				printk(KERN_INFO "%s: using 64-bit DMA\n",
+				       c->name);
+			}
+		}
+#endif
 	}
 
 	if ((rc = i2o_pci_alloc(c))) {
@@ -459,6 +397,11 @@
 	if ((rc = i2o_iop_add(c)))
 		goto uninstall;
 
+	get_device(&c->device);
+
+	if (i960)
+		pci_write_config_word(i960, 0x42, 0x03ff);
+
 	return 0;
 
       uninstall:
@@ -469,6 +412,7 @@
 
       free_controller:
 	i2o_iop_free(c);
+	put_device(c->device.parent);
 
       disable:
 	pci_disable_device(pdev);
@@ -492,15 +436,17 @@
 	i2o_pci_irq_disable(c);
 	i2o_pci_free(c);
 
+	pci_disable_device(pdev);
+
 	printk(KERN_INFO "%s: Controller removed.\n", c->name);
 
-	i2o_iop_free(c);
-	pci_disable_device(pdev);
+	put_device(c->device.parent);
+	put_device(&c->device);
 };
 
 /* PCI driver for I2O controller */
 static struct pci_driver i2o_pci_driver = {
-	.name = "I2O controller",
+	.name = "PCI_I2O",
 	.id_table = i2o_pci_ids,
 	.probe = i2o_pci_probe,
 	.remove = __devexit_p(i2o_pci_remove),
@@ -523,6 +469,4 @@
 {
 	pci_unregister_driver(&i2o_pci_driver);
 };
-
-EXPORT_SYMBOL(i2o_dma_realloc);
 MODULE_DEVICE_TABLE(pci, i2o_pci_ids);
diff --git a/drivers/misc/ibmasm/command.c b/drivers/misc/ibmasm/command.c
index 245b005..07a085c 100644
--- a/drivers/misc/ibmasm/command.c
+++ b/drivers/misc/ibmasm/command.c
@@ -23,6 +23,7 @@
  */
 
 #include "ibmasm.h"
+#include "lowlevel.h"
 
 static void exec_next_command(struct service_processor *sp);
 static void free_command(struct kobject *kobj);
@@ -31,8 +32,9 @@
 	.release = free_command,
 };
 
+static atomic_t command_count = ATOMIC_INIT(0);
 
-struct command *ibmasm_new_command(size_t buffer_size)
+struct command *ibmasm_new_command(struct service_processor *sp, size_t buffer_size)
 {
 	struct command *cmd;
 
@@ -55,11 +57,15 @@
 
 	kobject_init(&cmd->kobj);
 	cmd->kobj.ktype = &ibmasm_cmd_kobj_type;
+	cmd->lock = &sp->lock;
 
 	cmd->status = IBMASM_CMD_PENDING;
 	init_waitqueue_head(&cmd->wait);
 	INIT_LIST_HEAD(&cmd->queue_node);
 
+	atomic_inc(&command_count);
+	dbg("command count: %d\n", atomic_read(&command_count));
+
 	return cmd;
 }
 
@@ -68,6 +74,8 @@
 	struct command *cmd = to_command(kobj);
  
 	list_del(&cmd->queue_node);
+	atomic_dec(&command_count);
+	dbg("command count: %d\n", atomic_read(&command_count));
 	kfree(cmd->buffer);
 	kfree(cmd);
 }
@@ -94,8 +102,14 @@
 
 static inline void do_exec_command(struct service_processor *sp)
 {
+	char tsbuf[32];
+
+	dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
+
 	if (ibmasm_send_i2o_message(sp)) {
 		sp->current_command->status = IBMASM_CMD_FAILED;
+		wake_up(&sp->current_command->wait);
+		command_put(sp->current_command);
 		exec_next_command(sp);
 	}
 }
@@ -111,14 +125,16 @@
 void ibmasm_exec_command(struct service_processor *sp, struct command *cmd)
 {
 	unsigned long flags;
+	char tsbuf[32];
+
+	dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
 
 	spin_lock_irqsave(&sp->lock, flags);
 
 	if (!sp->current_command) {
-		command_get(cmd);
 		sp->current_command = cmd;
+		command_get(sp->current_command);
 		spin_unlock_irqrestore(&sp->lock, flags);
-
 		do_exec_command(sp);
 	} else {
 		enqueue_command(sp, cmd);
@@ -129,9 +145,9 @@
 static void exec_next_command(struct service_processor *sp)
 {
 	unsigned long flags;
+	char tsbuf[32];
 
-	wake_up(&sp->current_command->wait);
-	command_put(sp->current_command);
+	dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
 
 	spin_lock_irqsave(&sp->lock, flags);
 	sp->current_command = dequeue_command(sp);
@@ -169,7 +185,9 @@
 	if (!sp->current_command) 
 		return; 
 
-	memcpy(cmd->buffer, response, min(size, cmd->buffer_size));
+	memcpy_fromio(cmd->buffer, response, min(size, cmd->buffer_size));
 	cmd->status = IBMASM_CMD_COMPLETE;
+	wake_up(&sp->current_command->wait);
+	command_put(sp->current_command);
 	exec_next_command(sp);
 }
diff --git a/drivers/misc/ibmasm/dot_command.c b/drivers/misc/ibmasm/dot_command.c
index 478a8d8..13c52f8 100644
--- a/drivers/misc/ibmasm/dot_command.c
+++ b/drivers/misc/ibmasm/dot_command.c
@@ -33,7 +33,13 @@
 	u32 size;
 	struct dot_command_header *header = (struct dot_command_header *)message;
 
+	if (message_size == 0)
+		return;
+
 	size = get_dot_command_size(message);
+	if (size == 0)
+		return;
+
 	if (size > message_size)
 		size = message_size;
 
@@ -67,7 +73,7 @@
 	u8 *vpd_data;
 	int result = 0;
 
-	command = ibmasm_new_command(INIT_BUFFER_SIZE);
+	command = ibmasm_new_command(sp, INIT_BUFFER_SIZE);
 	if (command == NULL)
 		return -ENOMEM;
 
@@ -121,7 +127,7 @@
 	struct os_state_command *os_state_cmd;
 	int result = 0;
 
-	cmd = ibmasm_new_command(sizeof(struct os_state_command));
+	cmd = ibmasm_new_command(sp, sizeof(struct os_state_command));
 	if (cmd == NULL)
 		return -ENOMEM;
 
diff --git a/drivers/misc/ibmasm/event.c b/drivers/misc/ibmasm/event.c
index e100f34..fe1e819 100644
--- a/drivers/misc/ibmasm/event.c
+++ b/drivers/misc/ibmasm/event.c
@@ -23,6 +23,7 @@
  */
 
 #include "ibmasm.h"
+#include "lowlevel.h"
 
 /*
  * ASM service processor event handling routines.
@@ -34,7 +35,6 @@
  * circular buffer.
  */
 
-
 static void wake_up_event_readers(struct service_processor *sp)
 {
 	struct event_reader *reader;
@@ -63,7 +63,7 @@
 	spin_lock_irqsave(&sp->lock, flags);
 	/* copy the event into the next slot in the circular buffer */
 	event = &buffer->events[buffer->next_index];
-	memcpy(event->data, data, data_size);
+	memcpy_fromio(event->data, data, data_size);
 	event->data_size = data_size;
 	event->serial_number = buffer->next_serial_number;
 
@@ -93,7 +93,10 @@
 	unsigned int index;
 	unsigned long flags;
 
-	if (wait_event_interruptible(reader->wait, event_available(buffer, reader)))
+	reader->cancelled = 0;
+
+	if (wait_event_interruptible(reader->wait,
+			event_available(buffer, reader) || reader->cancelled))
 		return -ERESTARTSYS;
 
 	if (!event_available(buffer, reader))
@@ -116,6 +119,12 @@
 	return event->data_size;
 }
 
+void ibmasm_cancel_next_event(struct event_reader *reader)
+{
+        reader->cancelled = 1;
+        wake_up_interruptible(&reader->wait);
+}
+
 void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader)
 {
 	unsigned long flags;
@@ -131,8 +140,6 @@
 {
 	unsigned long flags;
 
-	wake_up_interruptible(&reader->wait);
-
 	spin_lock_irqsave(&sp->lock, flags);
 	list_del(&reader->node);
 	spin_unlock_irqrestore(&sp->lock, flags);
@@ -164,6 +171,5 @@
 
 void ibmasm_event_buffer_exit(struct service_processor *sp)
 {
-	wake_up_event_readers(sp);
 	kfree(sp->event_buffer);
 }
diff --git a/drivers/misc/ibmasm/heartbeat.c b/drivers/misc/ibmasm/heartbeat.c
index ce09309..f295401 100644
--- a/drivers/misc/ibmasm/heartbeat.c
+++ b/drivers/misc/ibmasm/heartbeat.c
@@ -25,6 +25,7 @@
 #include <linux/notifier.h>
 #include "ibmasm.h"
 #include "dot_command.h"
+#include "lowlevel.h"
 
 static int suspend_heartbeats = 0;
 
@@ -62,7 +63,7 @@
 
 int ibmasm_heartbeat_init(struct service_processor *sp)
 {
-	sp->heartbeat = ibmasm_new_command(HEARTBEAT_BUFFER_SIZE);
+	sp->heartbeat = ibmasm_new_command(sp, HEARTBEAT_BUFFER_SIZE);
 	if (sp->heartbeat == NULL)
 		return -ENOMEM;
 
@@ -71,6 +72,12 @@
 
 void ibmasm_heartbeat_exit(struct service_processor *sp)
 {
+	char tsbuf[32];
+
+	dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
+	ibmasm_wait_for_response(sp->heartbeat, IBMASM_CMD_TIMEOUT_NORMAL);
+	dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
+	suspend_heartbeats = 1;
 	command_put(sp->heartbeat);
 }
 
@@ -78,14 +85,16 @@
 {
 	struct command *cmd = sp->heartbeat;
 	struct dot_command_header *header = (struct dot_command_header *)cmd->buffer;
+	char tsbuf[32];
 
+	dbg("%s:%d at %s\n", __FUNCTION__, __LINE__, get_timestamp(tsbuf));
 	if (suspend_heartbeats)
 		return;
 
 	/* return the received dot command to sender */
 	cmd->status = IBMASM_CMD_PENDING;
 	size = min(size, cmd->buffer_size);
-	memcpy(cmd->buffer, message, size);
+	memcpy_fromio(cmd->buffer, message, size);
 	header->type = sp_write;
 	ibmasm_exec_command(sp, cmd);
 }
diff --git a/drivers/misc/ibmasm/ibmasm.h b/drivers/misc/ibmasm/ibmasm.h
index 6fec7fd..ecce4ff 100644
--- a/drivers/misc/ibmasm/ibmasm.h
+++ b/drivers/misc/ibmasm/ibmasm.h
@@ -34,16 +34,31 @@
 #include <linux/version.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
+#include <linux/input.h>
 
 /* Driver identification */
 #define DRIVER_NAME	"ibmasm"
-#define DRIVER_VERSION  "0.4"
-#define DRIVER_AUTHOR   "Max Asbock"
+#define DRIVER_VERSION  "1.0"
+#define DRIVER_AUTHOR   "Max Asbock <masbock@us.ibm.com>, Vernon Mauery <vernux@us.ibm.com>"
 #define DRIVER_DESC     "IBM ASM Service Processor Driver"
 
 #define err(msg) printk(KERN_ERR "%s: " msg "\n", DRIVER_NAME)
 #define info(msg) printk(KERN_INFO "%s: " msg "\n", DRIVER_NAME)
 
+extern int ibmasm_debug;
+#define dbg(STR, ARGS...)					\
+	do {							\
+		if (ibmasm_debug)				\
+			printk(KERN_DEBUG STR , ##ARGS);	\
+	} while (0)
+
+static inline char *get_timestamp(char *buf)
+{
+	struct timeval now;
+	do_gettimeofday(&now);
+	sprintf(buf, "%lu.%lu", now.tv_sec, now.tv_usec);
+	return buf;
+}
 
 #define IBMASM_CMD_PENDING	0	
 #define IBMASM_CMD_COMPLETE	1	
@@ -52,7 +67,7 @@
 #define IBMASM_CMD_TIMEOUT_NORMAL	45
 #define IBMASM_CMD_TIMEOUT_EXTRA	240
 
-#define IBMASM_CMD_MAX_BUFFER_SIZE	0x4000
+#define IBMASM_CMD_MAX_BUFFER_SIZE	0x8000
 
 #define REVERSE_HEARTBEAT_TIMEOUT	120
 
@@ -80,12 +95,17 @@
 	size_t			buffer_size;
 	int			status;
 	struct kobject		kobj;
+	spinlock_t		*lock;
 };
 #define to_command(c) container_of(c, struct command, kobj)
 
 static inline void command_put(struct command *cmd)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(cmd->lock, flags);
         kobject_put(&cmd->kobj);
+	spin_unlock_irqrestore(cmd->lock, flags);
 }
 
 static inline void command_get(struct command *cmd)
@@ -108,6 +128,7 @@
 };
 
 struct event_reader {
+	int			cancelled;
 	unsigned int		next_serial_number;
 	wait_queue_head_t	wait;
 	struct list_head	node;
@@ -120,41 +141,11 @@
 	unsigned int		stopped;
 };
 
-
-/* remote console events */
-struct mouse_event {
-	long		x;
-	long		y;
-	unsigned char	buttons;
-	unsigned char	transitions;
+struct ibmasm_remote {
+	struct input_dev keybd_dev;
+	struct input_dev mouse_dev;
 };
 
-struct keyboard_event {
-	unsigned long	key_code;
-	unsigned char	key_down;
-};
-
-struct remote_event {
-	unsigned long	type;
-	union {
-		struct mouse_event	mouse;
-		struct keyboard_event	keyboard;
-	} data;
-};
-
-#define DRIVER_REMOTE_QUEUE_SIZE 240
-
-struct remote_queue {
-	struct remote_event	*start;
-	struct remote_event	*end;
-	struct remote_event	*reader;
-	struct remote_event	*writer;
-	unsigned int		size;
-	int			open;
-	wait_queue_head_t	wait;
-};
-
-
 struct service_processor {
 	struct list_head	node;
 	spinlock_t		lock;
@@ -167,13 +158,13 @@
 	char			dirname[IBMASM_NAME_SIZE];
 	char			devname[IBMASM_NAME_SIZE];
 	unsigned int		number;
-	struct remote_queue	remote_queue;
+	struct ibmasm_remote	*remote;
 	int			serial_line;
 	struct device		*dev;
 };
 
 /* command processing */
-extern struct command *ibmasm_new_command(size_t buffer_size);
+extern struct command *ibmasm_new_command(struct service_processor *sp, size_t buffer_size);
 extern void ibmasm_exec_command(struct service_processor *sp, struct command *cmd);
 extern void ibmasm_wait_for_response(struct command *cmd, int timeout);
 extern void ibmasm_receive_command_response(struct service_processor *sp, void *response,  size_t size);
@@ -185,6 +176,7 @@
 extern void ibmasm_event_reader_register(struct service_processor *sp, struct event_reader *reader);
 extern void ibmasm_event_reader_unregister(struct service_processor *sp, struct event_reader *reader);
 extern int ibmasm_get_next_event(struct service_processor *sp, struct event_reader *reader);
+extern void ibmasm_cancel_next_event(struct event_reader *reader);
 
 /* heartbeat - from SP to OS */
 extern void ibmasm_register_panic_notifier(void);
@@ -208,11 +200,9 @@
 extern irqreturn_t ibmasm_interrupt_handler(int irq, void * dev_id, struct pt_regs *regs);
 
 /* remote console */
-extern void ibmasm_handle_mouse_interrupt(struct service_processor *sp);
-extern int ibmasm_init_remote_queue(struct service_processor *sp);
-extern void ibmasm_free_remote_queue(struct service_processor *sp);
-extern void ibmasm_advance_reader(struct remote_queue *q, unsigned int n);
-extern size_t ibmasm_events_available(struct remote_queue *q);
+extern void ibmasm_handle_mouse_interrupt(struct service_processor *sp, struct pt_regs *regs);
+extern int ibmasm_init_remote_input_dev(struct service_processor *sp);
+extern void ibmasm_free_remote_input_dev(struct service_processor *sp);
 
 /* file system */
 extern int ibmasmfs_register(void);
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c
index 866e867..5c550fc 100644
--- a/drivers/misc/ibmasm/ibmasmfs.c
+++ b/drivers/misc/ibmasm/ibmasmfs.c
@@ -37,9 +37,7 @@
  *    |   |-- event
  *    |   |-- reverse_heartbeat
  *    |   `-- remote_video
- *    |       |-- connected
  *    |       |-- depth
- *    |       |-- events
  *    |       |-- height
  *    |       `-- width
  *    .
@@ -50,9 +48,7 @@
  *        |-- event
  *        |-- reverse_heartbeat
  *        `-- remote_video
- *            |-- connected
  *            |-- depth
- *            |-- events
  *            |-- height
  *            `-- width
  *
@@ -75,14 +71,6 @@
  * remote_video/width: control remote display settings
  * 	write: set value
  * 	read: read value
- *
- * remote_video/connected
- * 	read: return "1" if web browser VNC java applet is connected, 
- * 		"0" otherwise
- *
- * remote_video/events
- * 	read: sleep until a remote mouse or keyboard event occurs, then return
- * 		then event.
  */
 
 #include <linux/fs.h>
@@ -333,7 +321,7 @@
 	if (command_data->command)
 		return -EAGAIN;
 
-	cmd = ibmasm_new_command(count);
+	cmd = ibmasm_new_command(command_data->sp, count);
 	if (!cmd)
 		return -ENOMEM;
 
@@ -374,6 +362,7 @@
 	ibmasm_event_reader_register(sp, &event_data->reader);
 
 	event_data->sp = sp;
+	event_data->active = 0;
 	file->private_data = event_data;
 	return 0;
 }
@@ -391,7 +380,9 @@
 {
 	struct ibmasmfs_event_data *event_data = file->private_data;
 	struct event_reader *reader = &event_data->reader;
+	struct service_processor *sp = event_data->sp;
 	int ret;
+	unsigned long flags;
 
 	if (*offset < 0)
 		return -EINVAL;
@@ -400,17 +391,32 @@
 	if (*offset != 0)
 		return 0;
 
-	ret = ibmasm_get_next_event(event_data->sp, reader);
+	spin_lock_irqsave(&sp->lock, flags);
+	if (event_data->active) {
+		spin_unlock_irqrestore(&sp->lock, flags);
+		return -EBUSY;
+	}
+	event_data->active = 1;
+	spin_unlock_irqrestore(&sp->lock, flags);
+
+	ret = ibmasm_get_next_event(sp, reader);
 	if (ret <= 0)
-		return ret;
+		goto out;
 
-	if (count < reader->data_size)
-		return -EINVAL;
+	if (count < reader->data_size) {
+		ret = -EINVAL;
+		goto out;
+	}
 
-        if (copy_to_user(buf, reader->data, reader->data_size))
-		return -EFAULT;
+        if (copy_to_user(buf, reader->data, reader->data_size)) {
+		ret = -EFAULT;
+		goto out;
+	}
+	ret = reader->data_size;
 
-	return reader->data_size;
+out:
+	event_data->active = 0;
+	return ret;
 }
 
 static ssize_t event_file_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
@@ -424,7 +430,7 @@
 	if (*offset != 0)
 		return 0;
 
-	wake_up_interruptible(&event_data->reader.wait);
+	ibmasm_cancel_next_event(&event_data->reader);
 	return 0;
 }
 
@@ -575,75 +581,6 @@
 	return count;
 }
 
-static int remote_event_file_open(struct inode *inode, struct file *file)
-{
-	struct service_processor *sp;
-	unsigned long flags;
-	struct remote_queue *q;
-	
-	file->private_data = inode->u.generic_ip;
-	sp = file->private_data;
-	q = &sp->remote_queue;
-
-	/* allow only one event reader */
-	spin_lock_irqsave(&sp->lock, flags);
-	if (q->open) {
-		spin_unlock_irqrestore(&sp->lock, flags);
-		return -EBUSY;
-	}
-	q->open = 1;
-	spin_unlock_irqrestore(&sp->lock, flags);
-
-	enable_mouse_interrupts(sp);
-	
-	return 0;
-}
-
-static int remote_event_file_close(struct inode *inode, struct file *file)
-{
-	struct service_processor *sp = file->private_data;
-
-	disable_mouse_interrupts(sp);
-	wake_up_interruptible(&sp->remote_queue.wait);
-	sp->remote_queue.open = 0;
-
-	return 0;
-}
-
-static ssize_t remote_event_file_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
-{
-	struct service_processor *sp = file->private_data;
-	struct remote_queue *q = &sp->remote_queue;
-	size_t data_size;
-	struct remote_event *reader = q->reader;
-	size_t num_events;
-
-	if (*offset < 0)
-		return -EINVAL;
-	if (count == 0 || count > 1024)
-		return 0;
-	if (*offset != 0)
-		return 0;
-
-	if (wait_event_interruptible(q->wait, q->reader != q->writer))
-		return -ERESTARTSYS;
-
-	/* only get multiples of struct remote_event */
-	num_events = min((count/sizeof(struct remote_event)), ibmasm_events_available(q));
-	if (!num_events)
-		return 0;
-
-	data_size = num_events * sizeof(struct remote_event);
-
-	if (copy_to_user(buf, reader, data_size))
-		return -EFAULT;
-
-	ibmasm_advance_reader(q, num_events);
-
-	return data_size;
-}
-
-
 static struct file_operations command_fops = {
 	.open =		command_file_open,
 	.release =	command_file_close,
@@ -672,12 +609,6 @@
 	.write =	remote_settings_file_write,
 };
 
-static struct file_operations remote_event_fops = {
-	.open =		remote_event_file_open,
-	.release =	remote_event_file_close,
-	.read =		remote_event_file_read,
-};
-
 
 static void ibmasmfs_create_files (struct super_block *sb, struct dentry *root)
 {
@@ -703,7 +634,5 @@
 		ibmasmfs_create_file(sb, remote_dir, "width", &remote_settings_fops, (void *)display_width(sp), S_IRUSR|S_IWUSR);
 		ibmasmfs_create_file(sb, remote_dir, "height", &remote_settings_fops, (void *)display_height(sp), S_IRUSR|S_IWUSR);
 		ibmasmfs_create_file(sb, remote_dir, "depth", &remote_settings_fops, (void *)display_depth(sp), S_IRUSR|S_IWUSR);
-		ibmasmfs_create_file(sb, remote_dir, "connected", &remote_settings_fops, (void *)vnc_status(sp), S_IRUSR);
-		ibmasmfs_create_file(sb, remote_dir, "events", &remote_event_fops, (void *)sp, S_IRUSR);
 	}
 }
diff --git a/drivers/misc/ibmasm/lowlevel.c b/drivers/misc/ibmasm/lowlevel.c
index 5156de2..47949a2 100644
--- a/drivers/misc/ibmasm/lowlevel.c
+++ b/drivers/misc/ibmasm/lowlevel.c
@@ -46,8 +46,8 @@
 
 	message = get_i2o_message(sp->base_address, mfa);
 
-	memcpy(&message->header, &header, sizeof(struct i2o_header));
-	memcpy(&message->data, command->buffer, command_size);
+	memcpy_toio(&message->header, &header, sizeof(struct i2o_header));
+	memcpy_toio(&message->data, command->buffer, command_size);
 
 	set_mfa_inbound(sp->base_address, mfa);
 
@@ -59,23 +59,27 @@
 	u32	mfa;
 	struct service_processor *sp = (struct service_processor *)dev_id;
 	void __iomem *base_address = sp->base_address;
+	char tsbuf[32];
 
 	if (!sp_interrupt_pending(base_address))
 		return IRQ_NONE;
 
+	dbg("respond to interrupt at %s\n", get_timestamp(tsbuf));
+
 	if (mouse_interrupt_pending(sp)) {
-		ibmasm_handle_mouse_interrupt(sp);
-		mfa = get_mfa_outbound(base_address);
+		ibmasm_handle_mouse_interrupt(sp, regs);
 		clear_mouse_interrupt(sp);
-		set_mfa_outbound(base_address, mfa);
-		return IRQ_HANDLED;
 	}
 
 	mfa = get_mfa_outbound(base_address);
 	if (valid_mfa(mfa)) {
 		struct i2o_message *msg = get_i2o_message(base_address, mfa);
 		ibmasm_receive_message(sp, &msg->data, incoming_data_size(msg));
-	}
+	} else
+		dbg("didn't get a valid MFA\n");
+
 	set_mfa_outbound(base_address, mfa);
+	dbg("finished interrupt at   %s\n", get_timestamp(tsbuf));
+
 	return IRQ_HANDLED;
 }
diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c
index 777432a..1fdf03f 100644
--- a/drivers/misc/ibmasm/module.c
+++ b/drivers/misc/ibmasm/module.c
@@ -56,17 +56,26 @@
 #include "lowlevel.h"
 #include "remote.h"
 
+int ibmasm_debug = 0;
+module_param(ibmasm_debug, int , S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ibmasm_debug, " Set debug mode on or off");
+
 
 static int __devinit ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
-	int err, result = -ENOMEM;
+	int result;
 	struct service_processor *sp;
 
-	if ((err = pci_enable_device(pdev))) {
-		printk(KERN_ERR "%s: can't enable PCI device at %s\n",
-			DRIVER_NAME, pci_name(pdev));
-		return err;
+	if ((result = pci_enable_device(pdev))) {
+		dev_err(&pdev->dev, "Failed to enable PCI device\n");
+		return result;
 	}
+	if ((result = pci_request_regions(pdev, DRIVER_NAME))) {
+		dev_err(&pdev->dev, "Failed to allocate PCI resources\n");
+		goto error_resources;
+	}
+	/* vnc client won't work without bus-mastering */
+	pci_set_master(pdev);
 
 	sp = kmalloc(sizeof(struct service_processor), GFP_KERNEL);
 	if (sp == NULL) {
@@ -76,6 +85,9 @@
 	}
 	memset(sp, 0, sizeof(struct service_processor));
 
+	sp->lock = SPIN_LOCK_UNLOCKED;
+	INIT_LIST_HEAD(&sp->command_queue);
+
 	pci_set_drvdata(pdev, (void *)sp);
 	sp->dev = &pdev->dev;
 	sp->number = pdev->bus->number;
@@ -101,15 +113,6 @@
 		goto error_ioremap;
 	}
 
-	result = ibmasm_init_remote_queue(sp);
-	if (result) {
-		dev_err(sp->dev, "Failed to initialize remote queue\n");
-		goto error_remote_queue;
-	}
-
-	spin_lock_init(&sp->lock);
-	INIT_LIST_HEAD(&sp->command_queue);
-
 	result = request_irq(sp->irq, ibmasm_interrupt_handler, SA_SHIRQ, sp->devname, (void*)sp);
 	if (result) {
 		dev_err(sp->dev, "Failed to register interrupt handler\n");
@@ -117,7 +120,12 @@
 	}
 
 	enable_sp_interrupts(sp->base_address);
-	disable_mouse_interrupts(sp);
+
+	result = ibmasm_init_remote_input_dev(sp);
+	if (result) {
+		dev_err(sp->dev, "Failed to initialize remote queue\n");
+		goto error_send_message;
+	}
 
 	result = ibmasm_send_driver_vpd(sp);
 	if (result) {
@@ -133,30 +141,25 @@
 
 	ibmasm_register_uart(sp);
 
-	dev_printk(KERN_DEBUG, &pdev->dev, "WARNING: This software may not be supported or function\n");
-	dev_printk(KERN_DEBUG, &pdev->dev, "correctly on your IBM server. Please consult the IBM\n");
-	dev_printk(KERN_DEBUG, &pdev->dev, "ServerProven website\n");
-	dev_printk(KERN_DEBUG, &pdev->dev, "http://www.pc.ibm.com/ww/eserver/xseries/serverproven\n");
-	dev_printk(KERN_DEBUG, &pdev->dev, "for information on the specific driver level and support\n");
-	dev_printk(KERN_DEBUG, &pdev->dev, "statement for your IBM server.\n");
-
 	return 0;
 
 error_send_message:
 	disable_sp_interrupts(sp->base_address);
+	ibmasm_free_remote_input_dev(sp);
 	free_irq(sp->irq, (void *)sp);
 error_request_irq:
-	ibmasm_free_remote_queue(sp);
-error_remote_queue:
 	iounmap(sp->base_address);
 error_ioremap:
 	ibmasm_heartbeat_exit(sp);
 error_heartbeat:
 	ibmasm_event_buffer_exit(sp);
 error_eventbuffer:
+	pci_set_drvdata(pdev, NULL);
 	kfree(sp);
 error_kmalloc:
-	pci_disable_device(pdev);
+        pci_release_regions(pdev);
+error_resources:
+        pci_disable_device(pdev);
 
 	return result;
 }
@@ -165,16 +168,24 @@
 {
 	struct service_processor *sp = (struct service_processor *)pci_get_drvdata(pdev);
 
+	dbg("Unregistering UART\n");
 	ibmasm_unregister_uart(sp);
-	ibmasm_send_os_state(sp, SYSTEM_STATE_OS_DOWN);
-	disable_sp_interrupts(sp->base_address);
-	disable_mouse_interrupts(sp);
-	free_irq(sp->irq, (void *)sp);
+	dbg("Sending OS down message\n");
+	if (ibmasm_send_os_state(sp, SYSTEM_STATE_OS_DOWN))
+		err("failed to get repsonse to 'Send OS State' command\n");
+	dbg("Disabling heartbeats\n");
 	ibmasm_heartbeat_exit(sp);
-	ibmasm_free_remote_queue(sp);
+	dbg("Disabling interrupts\n");
+	disable_sp_interrupts(sp->base_address);
+	dbg("Freeing SP irq\n");
+	free_irq(sp->irq, (void *)sp);
+	dbg("Cleaning up\n");
+	ibmasm_free_remote_input_dev(sp);
 	iounmap(sp->base_address);
 	ibmasm_event_buffer_exit(sp);
+	pci_set_drvdata(pdev, NULL);
 	kfree(sp);
+	pci_release_regions(pdev);
 	pci_disable_device(pdev);
 }
 
diff --git a/drivers/misc/ibmasm/r_heartbeat.c b/drivers/misc/ibmasm/r_heartbeat.c
index 93d9c1b..f8fdb2d 100644
--- a/drivers/misc/ibmasm/r_heartbeat.c
+++ b/drivers/misc/ibmasm/r_heartbeat.c
@@ -63,7 +63,7 @@
 	int times_failed = 0;
 	int result = 1;
 
-	cmd = ibmasm_new_command(sizeof rhb_dot_cmd);
+	cmd = ibmasm_new_command(sp, sizeof rhb_dot_cmd);
 	if (!cmd)
 		return -ENOMEM;
 
diff --git a/drivers/misc/ibmasm/remote.c b/drivers/misc/ibmasm/remote.c
index 520c3f1..d3c48d2 100644
--- a/drivers/misc/ibmasm/remote.c
+++ b/drivers/misc/ibmasm/remote.c
@@ -1,4 +1,3 @@
-
 /*
  * IBM ASM Service Processor Device Driver
  *
@@ -18,120 +17,178 @@
  *
  * Copyright (C) IBM Corporation, 2004
  *
- * Author: Max Asböck <amax@us.ibm.com> 
+ * Authors: Max Asböck <amax@us.ibm.com>
+ *          Vernon Mauery <vernux@us.ibm.com>
  *
  */
 
 /* Remote mouse and keyboard event handling functions */
 
+#include <linux/pci.h>
 #include "ibmasm.h"
 #include "remote.h"
 
-int ibmasm_init_remote_queue(struct service_processor *sp)
+static int xmax = 1600;
+static int ymax = 1200;
+
+
+static unsigned short xlate_high[XLATE_SIZE] = {
+	[KEY_SYM_ENTER & 0xff] = KEY_ENTER,
+	[KEY_SYM_KPSLASH & 0xff] = KEY_KPSLASH,
+	[KEY_SYM_KPSTAR & 0xff] = KEY_KPASTERISK,
+	[KEY_SYM_KPMINUS & 0xff] = KEY_KPMINUS,
+	[KEY_SYM_KPDOT & 0xff] = KEY_KPDOT,
+	[KEY_SYM_KPPLUS & 0xff] = KEY_KPPLUS,
+	[KEY_SYM_KP0 & 0xff] = KEY_KP0,
+	[KEY_SYM_KP1 & 0xff] = KEY_KP1,
+	[KEY_SYM_KP2 & 0xff] = KEY_KP2, [KEY_SYM_KPDOWN & 0xff] = KEY_KP2,
+	[KEY_SYM_KP3 & 0xff] = KEY_KP3,
+	[KEY_SYM_KP4 & 0xff] = KEY_KP4, [KEY_SYM_KPLEFT & 0xff] = KEY_KP4,
+	[KEY_SYM_KP5 & 0xff] = KEY_KP5,
+	[KEY_SYM_KP6 & 0xff] = KEY_KP6, [KEY_SYM_KPRIGHT & 0xff] = KEY_KP6,
+	[KEY_SYM_KP7 & 0xff] = KEY_KP7,
+	[KEY_SYM_KP8 & 0xff] = KEY_KP8, [KEY_SYM_KPUP & 0xff] = KEY_KP8,
+	[KEY_SYM_KP9 & 0xff] = KEY_KP9,
+	[KEY_SYM_BK_SPC & 0xff] = KEY_BACKSPACE,
+	[KEY_SYM_TAB & 0xff] = KEY_TAB,
+	[KEY_SYM_CTRL & 0xff] = KEY_LEFTCTRL,
+	[KEY_SYM_ALT & 0xff] = KEY_LEFTALT,
+	[KEY_SYM_INSERT & 0xff] = KEY_INSERT,
+	[KEY_SYM_DELETE & 0xff] = KEY_DELETE,
+	[KEY_SYM_SHIFT & 0xff] = KEY_LEFTSHIFT,
+	[KEY_SYM_UARROW & 0xff] = KEY_UP,
+	[KEY_SYM_DARROW & 0xff] = KEY_DOWN,
+	[KEY_SYM_LARROW & 0xff] = KEY_LEFT,
+	[KEY_SYM_RARROW & 0xff] = KEY_RIGHT,
+	[KEY_SYM_ESCAPE & 0xff] = KEY_ESC,
+        [KEY_SYM_PAGEUP & 0xff] = KEY_PAGEUP,
+        [KEY_SYM_PAGEDOWN & 0xff] = KEY_PAGEDOWN,
+        [KEY_SYM_HOME & 0xff] = KEY_HOME,
+        [KEY_SYM_END & 0xff] = KEY_END,
+	[KEY_SYM_F1 & 0xff] = KEY_F1,
+	[KEY_SYM_F2 & 0xff] = KEY_F2,
+	[KEY_SYM_F3 & 0xff] = KEY_F3,
+	[KEY_SYM_F4 & 0xff] = KEY_F4,
+	[KEY_SYM_F5 & 0xff] = KEY_F5,
+	[KEY_SYM_F6 & 0xff] = KEY_F6,
+	[KEY_SYM_F7 & 0xff] = KEY_F7,
+	[KEY_SYM_F8 & 0xff] = KEY_F8,
+	[KEY_SYM_F9 & 0xff] = KEY_F9,
+	[KEY_SYM_F10 & 0xff] = KEY_F10,
+	[KEY_SYM_F11 & 0xff] = KEY_F11,
+	[KEY_SYM_F12 & 0xff] = KEY_F12,
+	[KEY_SYM_CAP_LOCK & 0xff] = KEY_CAPSLOCK,
+	[KEY_SYM_NUM_LOCK & 0xff] = KEY_NUMLOCK,
+	[KEY_SYM_SCR_LOCK & 0xff] = KEY_SCROLLLOCK,
+};
+static unsigned short xlate[XLATE_SIZE] = {
+	[NO_KEYCODE] = KEY_RESERVED,
+	[KEY_SYM_SPACE] = KEY_SPACE,
+	[KEY_SYM_TILDE] = KEY_GRAVE,        [KEY_SYM_BKTIC] = KEY_GRAVE,
+	[KEY_SYM_ONE] = KEY_1,              [KEY_SYM_BANG] = KEY_1,
+	[KEY_SYM_TWO] = KEY_2,              [KEY_SYM_AT] = KEY_2,
+	[KEY_SYM_THREE] = KEY_3,            [KEY_SYM_POUND] = KEY_3,
+	[KEY_SYM_FOUR] = KEY_4,             [KEY_SYM_DOLLAR] = KEY_4,
+	[KEY_SYM_FIVE] = KEY_5,             [KEY_SYM_PERCENT] = KEY_5,
+	[KEY_SYM_SIX] = KEY_6,              [KEY_SYM_CARAT] = KEY_6,
+	[KEY_SYM_SEVEN] = KEY_7,            [KEY_SYM_AMPER] = KEY_7,
+	[KEY_SYM_EIGHT] = KEY_8,            [KEY_SYM_STAR] = KEY_8,
+	[KEY_SYM_NINE] = KEY_9,             [KEY_SYM_LPAREN] = KEY_9,
+	[KEY_SYM_ZERO] = KEY_0,             [KEY_SYM_RPAREN] = KEY_0,
+	[KEY_SYM_MINUS] = KEY_MINUS,        [KEY_SYM_USCORE] = KEY_MINUS,
+	[KEY_SYM_EQUAL] = KEY_EQUAL,        [KEY_SYM_PLUS] = KEY_EQUAL,
+	[KEY_SYM_LBRKT] = KEY_LEFTBRACE,    [KEY_SYM_LCURLY] = KEY_LEFTBRACE,
+	[KEY_SYM_RBRKT] = KEY_RIGHTBRACE,   [KEY_SYM_RCURLY] = KEY_RIGHTBRACE,
+	[KEY_SYM_SLASH] = KEY_BACKSLASH,    [KEY_SYM_PIPE] = KEY_BACKSLASH,
+	[KEY_SYM_TIC] = KEY_APOSTROPHE,     [KEY_SYM_QUOTE] = KEY_APOSTROPHE,
+	[KEY_SYM_SEMIC] = KEY_SEMICOLON,    [KEY_SYM_COLON] = KEY_SEMICOLON,
+	[KEY_SYM_COMMA] = KEY_COMMA,        [KEY_SYM_LT] = KEY_COMMA,
+	[KEY_SYM_PERIOD] = KEY_DOT,         [KEY_SYM_GT] = KEY_DOT,
+	[KEY_SYM_BSLASH] = KEY_SLASH,       [KEY_SYM_QMARK] = KEY_SLASH,
+	[KEY_SYM_A] = KEY_A,                [KEY_SYM_a] = KEY_A,
+	[KEY_SYM_B] = KEY_B,                [KEY_SYM_b] = KEY_B,
+	[KEY_SYM_C] = KEY_C,                [KEY_SYM_c] = KEY_C,
+	[KEY_SYM_D] = KEY_D,                [KEY_SYM_d] = KEY_D,
+	[KEY_SYM_E] = KEY_E,                [KEY_SYM_e] = KEY_E,
+	[KEY_SYM_F] = KEY_F,                [KEY_SYM_f] = KEY_F,
+	[KEY_SYM_G] = KEY_G,                [KEY_SYM_g] = KEY_G,
+	[KEY_SYM_H] = KEY_H,                [KEY_SYM_h] = KEY_H,
+	[KEY_SYM_I] = KEY_I,                [KEY_SYM_i] = KEY_I,
+	[KEY_SYM_J] = KEY_J,                [KEY_SYM_j] = KEY_J,
+	[KEY_SYM_K] = KEY_K,                [KEY_SYM_k] = KEY_K,
+	[KEY_SYM_L] = KEY_L,                [KEY_SYM_l] = KEY_L,
+	[KEY_SYM_M] = KEY_M,                [KEY_SYM_m] = KEY_M,
+	[KEY_SYM_N] = KEY_N,                [KEY_SYM_n] = KEY_N,
+	[KEY_SYM_O] = KEY_O,                [KEY_SYM_o] = KEY_O,
+	[KEY_SYM_P] = KEY_P,                [KEY_SYM_p] = KEY_P,
+	[KEY_SYM_Q] = KEY_Q,                [KEY_SYM_q] = KEY_Q,
+	[KEY_SYM_R] = KEY_R,                [KEY_SYM_r] = KEY_R,
+	[KEY_SYM_S] = KEY_S,                [KEY_SYM_s] = KEY_S,
+	[KEY_SYM_T] = KEY_T,                [KEY_SYM_t] = KEY_T,
+	[KEY_SYM_U] = KEY_U,                [KEY_SYM_u] = KEY_U,
+	[KEY_SYM_V] = KEY_V,                [KEY_SYM_v] = KEY_V,
+	[KEY_SYM_W] = KEY_W,                [KEY_SYM_w] = KEY_W,
+	[KEY_SYM_X] = KEY_X,                [KEY_SYM_x] = KEY_X,
+	[KEY_SYM_Y] = KEY_Y,                [KEY_SYM_y] = KEY_Y,
+	[KEY_SYM_Z] = KEY_Z,                [KEY_SYM_z] = KEY_Z,
+};
+
+static char remote_mouse_name[] = "ibmasm RSA I remote mouse";
+static char remote_keybd_name[] = "ibmasm RSA I remote keyboard";
+
+static void print_input(struct remote_input *input)
 {
-	struct remote_queue *q = &sp->remote_queue;
-
-	disable_mouse_interrupts(sp);
-
-	q->open = 0;
-	q->size = 0;
-
-	q->start = kmalloc(DRIVER_REMOTE_QUEUE_SIZE * sizeof(struct remote_event), GFP_KERNEL);
-        if (q->start == 0)
-                return -ENOMEM;
-
-	q->end = q->start + DRIVER_REMOTE_QUEUE_SIZE;
-	q->reader = q->start;
-	q->writer = q->start;
-	q->size = DRIVER_REMOTE_QUEUE_SIZE;
-	init_waitqueue_head(&q->wait);
-
-	return 0;
-}
-
-void ibmasm_free_remote_queue(struct service_processor *sp)
-{
-	kfree(sp->remote_queue.start);
-}
-
-void ibmasm_advance_reader(struct remote_queue *q, unsigned int n)
-{
-	q->reader += n;
-	if (q->reader >= q->end)
-		q->reader -= q->size;
-}
-
-size_t ibmasm_events_available(struct remote_queue *q)
-{
-	ssize_t diff = q->writer - q->reader;
- 
-	return (diff >= 0) ? diff : q->end - q->reader;	
-}
-	
-
-static int space_free(struct remote_queue *q)
-{
-	if (q->reader == q->writer)
-		return q->size - 1;
-
-	return ( (q->reader + q->size - q->writer) % q->size ) - 1;
-}
-
-static void set_mouse_event(struct remote_input *input, struct mouse_event *mouse)
-{
-	static char last_buttons = 0;
-
-	mouse->x = input->data.mouse.x;
-	mouse->y = input->data.mouse.y;
-
-	if (input->mouse_buttons == REMOTE_MOUSE_DOUBLE_CLICK) {
-		mouse->buttons = REMOTE_MOUSE_DOUBLE_CLICK;
-		last_buttons = 0;
-		return;
+	if (input->type == INPUT_TYPE_MOUSE) {
+		unsigned char buttons = input->mouse_buttons;
+		dbg("remote mouse movement: (x,y)=(%d,%d)%s%s%s%s\n",
+			input->data.mouse.x, input->data.mouse.y,
+			(buttons)?" -- buttons:":"",
+			(buttons & REMOTE_BUTTON_LEFT)?"left ":"",
+			(buttons & REMOTE_BUTTON_MIDDLE)?"middle ":"",
+			(buttons & REMOTE_BUTTON_RIGHT)?"right":""
+		      );
+	} else {
+		dbg("remote keypress (code, flag, down):"
+			   "%d (0x%x) [0x%x] [0x%x]\n",
+				input->data.keyboard.key_code,
+				input->data.keyboard.key_code,
+				input->data.keyboard.key_flag,
+				input->data.keyboard.key_down
+		      );
 	}
-	mouse->transitions = last_buttons ^ input->mouse_buttons;
-	mouse->buttons = input->mouse_buttons;
-
-	last_buttons = input->mouse_buttons;
 }
 
-static void set_keyboard_event(struct remote_input *input, struct keyboard_event *keyboard)
+static void send_mouse_event(struct input_dev *dev, struct pt_regs *regs,
+		struct remote_input *input)
 {
-	keyboard->key_code = input->data.keyboard.key_code;
-	keyboard->key_down = input->data.keyboard.key_down;
+	unsigned char buttons = input->mouse_buttons;
+
+	input_regs(dev, regs);
+	input_report_abs(dev, ABS_X, input->data.mouse.x);
+	input_report_abs(dev, ABS_Y, input->data.mouse.y);
+	input_report_key(dev, BTN_LEFT, buttons & REMOTE_BUTTON_LEFT);
+	input_report_key(dev, BTN_MIDDLE, buttons & REMOTE_BUTTON_MIDDLE);
+	input_report_key(dev, BTN_RIGHT, buttons & REMOTE_BUTTON_RIGHT);
+	input_sync(dev);
 }
 
-static int add_to_driver_queue(struct remote_queue *q, struct remote_input *input)
+static void send_keyboard_event(struct input_dev *dev, struct pt_regs *regs,
+		struct remote_input *input)
 {
-	struct remote_event *event = q->writer;
+	unsigned int key;
+	unsigned short code = input->data.keyboard.key_code;
 
-	if (space_free(q) < 1) {
-		return 1;
-	}
-
-	switch(input->type) {
-	case (INPUT_TYPE_MOUSE):
-		event->type = INPUT_TYPE_MOUSE;
-		set_mouse_event(input, &event->data.mouse);
-		break;
-	case (INPUT_TYPE_KEYBOARD):
-		event->type = INPUT_TYPE_KEYBOARD;
-		set_keyboard_event(input, &event->data.keyboard);
-		break;
-	default:
-		return 0;
-	}
-	event->type = input->type;
-
-	q->writer++;
-	if (q->writer == q->end)
-		q->writer = q->start;
-
-	return 0;
+	if (code & 0xff00)
+		key = xlate_high[code & 0xff];
+	else
+		key = xlate[code];
+	input_regs(dev, regs);
+	input_report_key(dev, key, (input->data.keyboard.key_down) ? 1 : 0);
+	input_sync(dev);
 }
-	
 
-void ibmasm_handle_mouse_interrupt(struct service_processor *sp)
+void ibmasm_handle_mouse_interrupt(struct service_processor *sp,
+		struct pt_regs *regs)
 {
 	unsigned long reader;
 	unsigned long writer;
@@ -141,12 +198,75 @@
 	writer = get_queue_writer(sp);
 
 	while (reader != writer) {
-		memcpy(&input, (void *)get_queue_entry(sp, reader), sizeof(struct remote_input));
+		memcpy_fromio(&input, get_queue_entry(sp, reader),
+				sizeof(struct remote_input));
 
-		if (add_to_driver_queue(&sp->remote_queue, &input))
+		print_input(&input);
+		if (input.type == INPUT_TYPE_MOUSE) {
+			send_mouse_event(&sp->remote->mouse_dev, regs, &input);
+		} else if (input.type == INPUT_TYPE_KEYBOARD) {
+			send_keyboard_event(&sp->remote->keybd_dev, regs, &input);
+		} else
 			break;
 
 		reader = advance_queue_reader(sp, reader);
+		writer = get_queue_writer(sp);
 	}
-	wake_up_interruptible(&sp->remote_queue.wait);
 }
+
+int ibmasm_init_remote_input_dev(struct service_processor *sp)
+{
+	/* set up the mouse input device */
+	struct ibmasm_remote *remote;
+	struct pci_dev *pdev = to_pci_dev(sp->dev);
+	int i;
+
+	sp->remote = remote = kmalloc(sizeof(*remote), GFP_KERNEL);
+	if (!remote)
+		return -ENOMEM;
+
+	memset(remote, 0, sizeof(*remote));
+
+	remote->mouse_dev.private = remote;
+	init_input_dev(&remote->mouse_dev);
+	remote->mouse_dev.id.vendor = pdev->vendor;
+	remote->mouse_dev.id.product = pdev->device;
+	remote->mouse_dev.evbit[0]  = BIT(EV_KEY) | BIT(EV_ABS);
+	remote->mouse_dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) |
+		BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
+	set_bit(BTN_TOUCH, remote->mouse_dev.keybit);
+	remote->mouse_dev.name = remote_mouse_name;
+	input_set_abs_params(&remote->mouse_dev, ABS_X, 0, xmax, 0, 0);
+	input_set_abs_params(&remote->mouse_dev, ABS_Y, 0, ymax, 0, 0);
+
+	remote->keybd_dev.private = remote;
+	init_input_dev(&remote->keybd_dev);
+	remote->keybd_dev.id.vendor = pdev->vendor;
+	remote->keybd_dev.id.product = pdev->device;
+	remote->keybd_dev.evbit[0]  = BIT(EV_KEY);
+	remote->keybd_dev.name = remote_keybd_name;
+
+	for (i=0; i<XLATE_SIZE; i++) {
+		if (xlate_high[i])
+			set_bit(xlate_high[i], remote->keybd_dev.keybit);
+		if (xlate[i])
+			set_bit(xlate[i], remote->keybd_dev.keybit);
+	}
+
+	input_register_device(&remote->mouse_dev);
+	input_register_device(&remote->keybd_dev);
+	enable_mouse_interrupts(sp);
+
+	printk(KERN_INFO "ibmasm remote responding to events on RSA card %d\n", sp->number);
+
+	return 0;
+}
+
+void ibmasm_free_remote_input_dev(struct service_processor *sp)
+{
+	disable_mouse_interrupts(sp);
+	input_unregister_device(&sp->remote->keybd_dev);
+	input_unregister_device(&sp->remote->mouse_dev);
+	kfree(sp->remote);
+}
+
diff --git a/drivers/misc/ibmasm/remote.h b/drivers/misc/ibmasm/remote.h
index a8eb19f..b7076a8 100644
--- a/drivers/misc/ibmasm/remote.h
+++ b/drivers/misc/ibmasm/remote.h
@@ -51,11 +51,13 @@
 
 
 /* mouse button states received from SP */
-#define REMOTE_MOUSE_DOUBLE_CLICK	0xF0
-#define REMOTE_MOUSE_BUTTON_LEFT	0x01
-#define REMOTE_MOUSE_BUTTON_MIDDLE	0x02
-#define REMOTE_MOUSE_BUTTON_RIGHT	0x04
+#define REMOTE_DOUBLE_CLICK	0xF0
+#define REMOTE_BUTTON_LEFT	0x01
+#define REMOTE_BUTTON_MIDDLE	0x02
+#define REMOTE_BUTTON_RIGHT	0x04
 
+/* size of keysym/keycode translation matricies */
+#define XLATE_SIZE 256
 
 struct mouse_input {
 	unsigned short	y;
@@ -83,11 +85,13 @@
 	unsigned char	pad3;
 };
 
-#define mouse_addr(sp) 		sp->base_address + CONDOR_MOUSE_DATA
-#define display_width(sp)	mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESX
-#define display_height(sp)	mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESY
-#define display_depth(sp)	mouse_addr(sp) + CONDOR_INPUT_DISPLAY_BITS
-#define vnc_status(sp)		mouse_addr(sp) + CONDOR_OUTPUT_VNC_STATUS
+#define mouse_addr(sp) 		(sp->base_address + CONDOR_MOUSE_DATA)
+#define display_width(sp)	(mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESX)
+#define display_height(sp)	(mouse_addr(sp) + CONDOR_INPUT_DISPLAY_RESY)
+#define display_depth(sp)	(mouse_addr(sp) + CONDOR_INPUT_DISPLAY_BITS)
+#define desktop_info(sp)	(mouse_addr(sp) + CONDOR_INPUT_DESKTOP_INFO)
+#define vnc_status(sp)		(mouse_addr(sp) + CONDOR_OUTPUT_VNC_STATUS)
+#define isr_control(sp)		(mouse_addr(sp) + CONDOR_MOUSE_ISR_CONTROL)
 
 #define mouse_interrupt_pending(sp) 	readl(mouse_addr(sp) + CONDOR_MOUSE_ISR_STATUS)
 #define clear_mouse_interrupt(sp)	writel(0, mouse_addr(sp) + CONDOR_MOUSE_ISR_STATUS)
@@ -101,10 +105,10 @@
 #define get_queue_reader(sp)	readl(mouse_addr(sp) + CONDOR_MOUSE_Q_READER)
 #define set_queue_reader(sp, reader)	writel(reader, mouse_addr(sp) + CONDOR_MOUSE_Q_READER)
 
-#define queue_begin	mouse_addr(sp) + CONDOR_MOUSE_Q_BEGIN
+#define queue_begin	(mouse_addr(sp) + CONDOR_MOUSE_Q_BEGIN)
 
 #define get_queue_entry(sp, read_index) \
-	queue_begin + read_index * sizeof(struct remote_input)
+	((void*)(queue_begin + read_index * sizeof(struct remote_input)))
 
 static inline int advance_queue_reader(struct service_processor *sp, unsigned long reader)
 {
@@ -116,4 +120,151 @@
 	return reader;
 }
 
+#define NO_KEYCODE 0
+#define KEY_SYM_BK_SPC   0xFF08
+#define KEY_SYM_TAB      0xFF09
+#define KEY_SYM_ENTER    0xFF0D
+#define KEY_SYM_SCR_LOCK 0xFF14
+#define KEY_SYM_ESCAPE   0xFF1B
+#define KEY_SYM_HOME     0xFF50
+#define KEY_SYM_LARROW   0xFF51
+#define KEY_SYM_UARROW   0xFF52
+#define KEY_SYM_RARROW   0xFF53
+#define KEY_SYM_DARROW   0xFF54
+#define KEY_SYM_PAGEUP   0xFF55
+#define KEY_SYM_PAGEDOWN 0xFF56
+#define KEY_SYM_END      0xFF57
+#define KEY_SYM_INSERT   0xFF63
+#define KEY_SYM_NUM_LOCK 0xFF7F
+#define KEY_SYM_KPSTAR   0xFFAA
+#define KEY_SYM_KPPLUS   0xFFAB
+#define KEY_SYM_KPMINUS  0xFFAD
+#define KEY_SYM_KPDOT    0xFFAE
+#define KEY_SYM_KPSLASH  0xFFAF
+#define KEY_SYM_KPRIGHT  0xFF96
+#define KEY_SYM_KPUP     0xFF97
+#define KEY_SYM_KPLEFT   0xFF98
+#define KEY_SYM_KPDOWN   0xFF99
+#define KEY_SYM_KP0      0xFFB0
+#define KEY_SYM_KP1      0xFFB1
+#define KEY_SYM_KP2      0xFFB2
+#define KEY_SYM_KP3      0xFFB3
+#define KEY_SYM_KP4      0xFFB4
+#define KEY_SYM_KP5      0xFFB5
+#define KEY_SYM_KP6      0xFFB6
+#define KEY_SYM_KP7      0xFFB7
+#define KEY_SYM_KP8      0xFFB8
+#define KEY_SYM_KP9      0xFFB9
+#define KEY_SYM_F1       0xFFBE      // 1B 5B 5B 41
+#define KEY_SYM_F2       0xFFBF      // 1B 5B 5B 42
+#define KEY_SYM_F3       0xFFC0      // 1B 5B 5B 43
+#define KEY_SYM_F4       0xFFC1      // 1B 5B 5B 44
+#define KEY_SYM_F5       0xFFC2      // 1B 5B 5B 45
+#define KEY_SYM_F6       0xFFC3      // 1B 5B 31 37 7E
+#define KEY_SYM_F7       0xFFC4      // 1B 5B 31 38 7E
+#define KEY_SYM_F8       0xFFC5      // 1B 5B 31 39 7E
+#define KEY_SYM_F9       0xFFC6      // 1B 5B 32 30 7E
+#define KEY_SYM_F10      0xFFC7      // 1B 5B 32 31 7E
+#define KEY_SYM_F11      0xFFC8      // 1B 5B 32 33 7E
+#define KEY_SYM_F12      0xFFC9      // 1B 5B 32 34 7E
+#define KEY_SYM_SHIFT    0xFFE1
+#define KEY_SYM_CTRL     0xFFE3
+#define KEY_SYM_ALT      0xFFE9
+#define KEY_SYM_CAP_LOCK 0xFFE5
+#define KEY_SYM_DELETE   0xFFFF
+#define KEY_SYM_TILDE    0x60
+#define KEY_SYM_BKTIC    0x7E
+#define KEY_SYM_ONE      0x31
+#define KEY_SYM_BANG     0x21
+#define KEY_SYM_TWO      0x32
+#define KEY_SYM_AT       0x40
+#define KEY_SYM_THREE    0x33
+#define KEY_SYM_POUND    0x23
+#define KEY_SYM_FOUR     0x34
+#define KEY_SYM_DOLLAR   0x24
+#define KEY_SYM_FIVE     0x35
+#define KEY_SYM_PERCENT  0x25
+#define KEY_SYM_SIX      0x36
+#define KEY_SYM_CARAT    0x5E
+#define KEY_SYM_SEVEN    0x37
+#define KEY_SYM_AMPER    0x26
+#define KEY_SYM_EIGHT    0x38
+#define KEY_SYM_STAR     0x2A
+#define KEY_SYM_NINE     0x39
+#define KEY_SYM_LPAREN   0x28
+#define KEY_SYM_ZERO     0x30
+#define KEY_SYM_RPAREN   0x29
+#define KEY_SYM_MINUS    0x2D
+#define KEY_SYM_USCORE   0x5F
+#define KEY_SYM_EQUAL    0x2B
+#define KEY_SYM_PLUS     0x3D
+#define KEY_SYM_LBRKT    0x5B
+#define KEY_SYM_LCURLY   0x7B
+#define KEY_SYM_RBRKT    0x5D
+#define KEY_SYM_RCURLY   0x7D
+#define KEY_SYM_SLASH    0x5C
+#define KEY_SYM_PIPE     0x7C
+#define KEY_SYM_TIC      0x27
+#define KEY_SYM_QUOTE    0x22
+#define KEY_SYM_SEMIC    0x3B
+#define KEY_SYM_COLON    0x3A
+#define KEY_SYM_COMMA    0x2C
+#define KEY_SYM_LT       0x3C
+#define KEY_SYM_PERIOD   0x2E
+#define KEY_SYM_GT       0x3E
+#define KEY_SYM_BSLASH   0x2F
+#define KEY_SYM_QMARK    0x3F
+#define KEY_SYM_A        0x41
+#define KEY_SYM_B        0x42
+#define KEY_SYM_C        0x43
+#define KEY_SYM_D        0x44
+#define KEY_SYM_E        0x45
+#define KEY_SYM_F        0x46
+#define KEY_SYM_G        0x47
+#define KEY_SYM_H        0x48
+#define KEY_SYM_I        0x49
+#define KEY_SYM_J        0x4A
+#define KEY_SYM_K        0x4B
+#define KEY_SYM_L        0x4C
+#define KEY_SYM_M        0x4D
+#define KEY_SYM_N        0x4E
+#define KEY_SYM_O        0x4F
+#define KEY_SYM_P        0x50
+#define KEY_SYM_Q        0x51
+#define KEY_SYM_R        0x52
+#define KEY_SYM_S        0x53
+#define KEY_SYM_T        0x54
+#define KEY_SYM_U        0x55
+#define KEY_SYM_V        0x56
+#define KEY_SYM_W        0x57
+#define KEY_SYM_X        0x58
+#define KEY_SYM_Y        0x59
+#define KEY_SYM_Z        0x5A
+#define KEY_SYM_a        0x61
+#define KEY_SYM_b        0x62
+#define KEY_SYM_c        0x63
+#define KEY_SYM_d        0x64
+#define KEY_SYM_e        0x65
+#define KEY_SYM_f        0x66
+#define KEY_SYM_g        0x67
+#define KEY_SYM_h        0x68
+#define KEY_SYM_i        0x69
+#define KEY_SYM_j        0x6A
+#define KEY_SYM_k        0x6B
+#define KEY_SYM_l        0x6C
+#define KEY_SYM_m        0x6D
+#define KEY_SYM_n        0x6E
+#define KEY_SYM_o        0x6F
+#define KEY_SYM_p        0x70
+#define KEY_SYM_q        0x71
+#define KEY_SYM_r        0x72
+#define KEY_SYM_s        0x73
+#define KEY_SYM_t        0x74
+#define KEY_SYM_u        0x75
+#define KEY_SYM_v        0x76
+#define KEY_SYM_w        0x77
+#define KEY_SYM_x        0x78
+#define KEY_SYM_y        0x79
+#define KEY_SYM_z        0x7A
+#define KEY_SYM_SPACE    0x20
 #endif /* _IBMASM_REMOTE_H_ */
diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c
index 29a56e9..5556cd3 100644
--- a/drivers/mmc/mmc_sysfs.c
+++ b/drivers/mmc/mmc_sysfs.c
@@ -22,7 +22,7 @@
 #define to_mmc_driver(d)	container_of(d, struct mmc_driver, drv)
 
 #define MMC_ATTR(name, fmt, args...)					\
-static ssize_t mmc_##name##_show (struct device *dev, char *buf)	\
+static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf)	\
 {									\
 	struct mmc_card *card = dev_to_mmc_card(dev);			\
 	return sprintf(buf, fmt, args);					\
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c
index 29dfd47..5c5eebd 100644
--- a/drivers/net/3c503.c
+++ b/drivers/net/3c503.c
@@ -171,12 +171,7 @@
 	err = do_el2_probe(dev);
 	if (err)
 		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
 	return dev;
-out1:
-	cleanup_card(dev);
 out:
 	free_netdev(dev);
 	return ERR_PTR(err);
@@ -356,6 +351,10 @@
     dev->poll_controller = ei_poll;
 #endif
 
+    retval = register_netdev(dev);
+    if (retval)
+	goto out1;
+
     if (dev->mem_start)
 	printk("%s: %s - %dkB RAM, 8kB shared mem window at %#6lx-%#6lx.\n",
 		dev->name, ei_status.name, (wordlength+1)<<3,
@@ -715,11 +714,8 @@
 		dev->base_addr = io[this_dev];
 		dev->mem_end = xcvr[this_dev];	/* low 4bits = xcvr sel. */
 		if (do_el2_probe(dev) == 0) {
-			if (register_netdev(dev) == 0) {
-				dev_el2[found++] = dev;
-				continue;
-			}
-			cleanup_card(dev);
+			dev_el2[found++] = dev;
+			continue;
 		}
 		free_netdev(dev);
 		printk(KERN_WARNING "3c503.c: No 3c503 card found (i/o = 0x%x).\n", io[this_dev]);
diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c
index 76fa8cc..ad17f17 100644
--- a/drivers/net/3c505.c
+++ b/drivers/net/3c505.c
@@ -1317,8 +1317,7 @@
 	if (orig_HSR & DIR) {
 		/* If HCR.DIR is up, we pull it down. HSR.DIR should follow. */
 		outb(0, dev->base_addr + PORT_CONTROL);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(30*HZ/100);
+		msleep(300);
 		if (inb_status(addr) & DIR) {
 			if (elp_debug > 0)
 				printk(notfound_msg, 2);
@@ -1327,8 +1326,7 @@
 	} else {
 		/* If HCR.DIR is down, we pull it up. HSR.DIR should follow. */
 		outb(DIR, dev->base_addr + PORT_CONTROL);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(30*HZ/100);
+		msleep(300);
 		if (!(inb_status(addr) & DIR)) {
 			if (elp_debug > 0)
 				printk(notfound_msg, 3);
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c
index e843109..977935a 100644
--- a/drivers/net/3c509.c
+++ b/drivers/net/3c509.c
@@ -217,6 +217,7 @@
 static struct eisa_device_id el3_eisa_ids[] = {
 		{ "TCM5092" },
 		{ "TCM5093" },
+		{ "TCM5095" },
 		{ "" }
 };
 
diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c
index c4cf4fc..d272ea3 100644
--- a/drivers/net/3c515.c
+++ b/drivers/net/3c515.c
@@ -365,7 +365,7 @@
 #endif /* __ISAPNP__ */
 
 static struct net_device *corkscrew_scan(int unit);
-static void corkscrew_setup(struct net_device *dev, int ioaddr,
+static int corkscrew_setup(struct net_device *dev, int ioaddr,
 			    struct pnp_dev *idev, int card_number);
 static int corkscrew_open(struct net_device *dev);
 static void corkscrew_timer(unsigned long arg);
@@ -539,10 +539,9 @@
 			printk(KERN_INFO "3c515 Resource configuration register %#4.4x, DCR %4.4x.\n",
 		     		inl(ioaddr + 0x2002), inw(ioaddr + 0x2000));
 			/* irq = inw(ioaddr + 0x2002) & 15; */ /* Use the irq from isapnp */
-			corkscrew_setup(dev, ioaddr, idev, cards_found++);
 			SET_NETDEV_DEV(dev, &idev->dev);
 			pnp_cards++;
-			err = register_netdev(dev);
+			err = corkscrew_setup(dev, ioaddr, idev, cards_found++);
 			if (!err)
 				return dev;
 			cleanup_card(dev);
@@ -558,8 +557,7 @@
 
 		printk(KERN_INFO "3c515 Resource configuration register %#4.4x, DCR %4.4x.\n",
 		     inl(ioaddr + 0x2002), inw(ioaddr + 0x2000));
-		corkscrew_setup(dev, ioaddr, NULL, cards_found++);
-		err = register_netdev(dev);
+		err = corkscrew_setup(dev, ioaddr, NULL, cards_found++);
 		if (!err)
 			return dev;
 		cleanup_card(dev);
@@ -568,7 +566,7 @@
 	return NULL;
 }
 
-static void corkscrew_setup(struct net_device *dev, int ioaddr,
+static int corkscrew_setup(struct net_device *dev, int ioaddr,
 			    struct pnp_dev *idev, int card_number)
 {
 	struct corkscrew_private *vp = netdev_priv(dev);
@@ -691,6 +689,8 @@
 	dev->get_stats = &corkscrew_get_stats;
 	dev->set_multicast_list = &set_rx_mode;
 	dev->ethtool_ops = &netdev_ethtool_ops;
+
+	return register_netdev(dev);
 }
 
 
diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c
index 8f6b2fa..1247a25 100644
--- a/drivers/net/3c523.c
+++ b/drivers/net/3c523.c
@@ -572,6 +572,10 @@
         dev->flags&=~IFF_MULTICAST;     /* Multicast doesn't work */
 #endif
 
+	retval = register_netdev(dev);
+	if (retval)
+		goto err_out;
+
 	return 0;
 err_out:
 	mca_set_adapter_procfn(slot, NULL, NULL);
@@ -600,12 +604,7 @@
 	err = do_elmc_probe(dev);
 	if (err)
 		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
 	return dev;
-out1:
-	cleanup_card(dev);
 out:
 	free_netdev(dev);
 	return ERR_PTR(err);
@@ -1288,12 +1287,9 @@
 		dev->irq=irq[this_dev];
 		dev->base_addr=io[this_dev];
 		if (do_elmc_probe(dev) == 0) {
-			if (register_netdev(dev) == 0) {
-				dev_elmc[this_dev] = dev;
-				found++;
-				continue;
-			}
-			cleanup_card(dev);
+			dev_elmc[this_dev] = dev;
+			found++;
+			continue;
 		}
 		free_netdev(dev);
 		if (io[this_dev]==0)
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index b5e0760..80ec9aa 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -2202,9 +2202,8 @@
 
 	if (vortex_debug > 6) {
 		printk(KERN_DEBUG "boomerang_start_xmit()\n");
-		if (vortex_debug > 3)
-			printk(KERN_DEBUG "%s: Trying to send a packet, Tx index %d.\n",
-				   dev->name, vp->cur_tx);
+		printk(KERN_DEBUG "%s: Trying to send a packet, Tx index %d.\n",
+			   dev->name, vp->cur_tx);
 	}
 
 	if (vp->cur_tx - vp->dirty_tx >= TX_RING_SIZE) {
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index d639cb8..e4b3c5c 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -54,12 +54,14 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/compiler.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include <linux/delay.h>
 #include <linux/ethtool.h>
 #include <linux/mii.h>
@@ -91,16 +93,17 @@
 
 MODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>");
 MODULE_DESCRIPTION("RealTek RTL-8139C+ series 10/100 PCI Ethernet driver");
+MODULE_VERSION(DRV_VERSION);
 MODULE_LICENSE("GPL");
 
 static int debug = -1;
-MODULE_PARM (debug, "i");
+module_param(debug, int, 0);
 MODULE_PARM_DESC (debug, "8139cp: bitmapped message enable number");
 
 /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
    The RTL chips use a 64 element hash table based on the Ethernet CRC.  */
 static int multicast_filter_limit = 32;
-MODULE_PARM (multicast_filter_limit, "i");
+module_param(multicast_filter_limit, int, 0);
 MODULE_PARM_DESC (multicast_filter_limit, "8139cp: maximum number of filtered multicast addresses");
 
 #define PFX			DRV_NAME ": "
@@ -186,6 +189,9 @@
 	RingEnd		= (1 << 30), /* End of descriptor ring */
 	FirstFrag	= (1 << 29), /* First segment of a packet */
 	LastFrag	= (1 << 28), /* Final segment of a packet */
+	LargeSend	= (1 << 27), /* TCP Large Send Offload (TSO) */
+	MSSShift	= 16,	     /* MSS value position */
+	MSSMask		= 0xfff,     /* MSS value: 11 bits */
 	TxError		= (1 << 23), /* Tx error summary */
 	RxError		= (1 << 20), /* Rx error summary */
 	IPCS		= (1 << 18), /* Calculate IP checksum */
@@ -312,7 +318,7 @@
 struct ring_info {
 	struct sk_buff		*skb;
 	dma_addr_t		mapping;
-	unsigned		frag;
+	u32			len;
 };
 
 struct cp_dma_stats {
@@ -394,6 +400,9 @@
 static void __cp_set_rx_mode (struct net_device *dev);
 static void cp_tx (struct cp_private *cp);
 static void cp_clean_rings (struct cp_private *cp);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void cp_poll_controller(struct net_device *dev);
+#endif
 
 static struct pci_device_id cp_pci_tbl[] = {
 	{ PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139,
@@ -688,6 +697,19 @@
 	return IRQ_HANDLED;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling receive - used by netconsole and other diagnostic tools
+ * to allow network i/o with interrupts disabled.
+ */
+static void cp_poll_controller(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	cp_interrupt(dev->irq, dev, NULL);
+	enable_irq(dev->irq);
+}
+#endif
+
 static void cp_tx (struct cp_private *cp)
 {
 	unsigned tx_head = cp->tx_head;
@@ -707,7 +729,7 @@
 			BUG();
 
 		pci_unmap_single(cp->pdev, cp->tx_skb[tx_tail].mapping,
-					skb->len, PCI_DMA_TODEVICE);
+				 cp->tx_skb[tx_tail].len, PCI_DMA_TODEVICE);
 
 		if (status & LastFrag) {
 			if (status & (TxError | TxFIFOUnder)) {
@@ -749,10 +771,11 @@
 {
 	struct cp_private *cp = netdev_priv(dev);
 	unsigned entry;
-	u32 eor;
+	u32 eor, flags;
 #if CP_VLAN_TAG_USED
 	u32 vlan_tag = 0;
 #endif
+	int mss = 0;
 
 	spin_lock_irq(&cp->lock);
 
@@ -772,6 +795,9 @@
 
 	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;
+
 	if (skb_shinfo(skb)->nr_frags == 0) {
 		struct cp_desc *txd = &cp->tx_ring[entry];
 		u32 len;
@@ -783,26 +809,26 @@
 		txd->addr = cpu_to_le64(mapping);
 		wmb();
 
-		if (skb->ip_summed == CHECKSUM_HW) {
+		flags = eor | len | DescOwn | FirstFrag | LastFrag;
+
+		if (mss)
+			flags |= LargeSend | ((mss & MSSMask) << MSSShift);
+		else if (skb->ip_summed == CHECKSUM_HW) {
 			const struct iphdr *ip = skb->nh.iph;
 			if (ip->protocol == IPPROTO_TCP)
-				txd->opts1 = cpu_to_le32(eor | len | DescOwn |
-							 FirstFrag | LastFrag |
-							 IPCS | TCPCS);
+				flags |= IPCS | TCPCS;
 			else if (ip->protocol == IPPROTO_UDP)
-				txd->opts1 = cpu_to_le32(eor | len | DescOwn |
-							 FirstFrag | LastFrag |
-							 IPCS | UDPCS);
+				flags |= IPCS | UDPCS;
 			else
-				BUG();
-		} else
-			txd->opts1 = cpu_to_le32(eor | len | DescOwn |
-						 FirstFrag | LastFrag);
+				WARN_ON(1);	/* we need a WARN() */
+		}
+
+		txd->opts1 = cpu_to_le32(flags);
 		wmb();
 
 		cp->tx_skb[entry].skb = skb;
 		cp->tx_skb[entry].mapping = mapping;
-		cp->tx_skb[entry].frag = 0;
+		cp->tx_skb[entry].len = len;
 		entry = NEXT_TX(entry);
 	} else {
 		struct cp_desc *txd;
@@ -820,7 +846,7 @@
 					       first_len, PCI_DMA_TODEVICE);
 		cp->tx_skb[entry].skb = skb;
 		cp->tx_skb[entry].mapping = first_mapping;
-		cp->tx_skb[entry].frag = 1;
+		cp->tx_skb[entry].len = first_len;
 		entry = NEXT_TX(entry);
 
 		for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
@@ -836,16 +862,19 @@
 						 len, PCI_DMA_TODEVICE);
 			eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
 
-			if (skb->ip_summed == CHECKSUM_HW) {
-				ctrl = eor | len | DescOwn | IPCS;
+			ctrl = eor | len | DescOwn;
+
+			if (mss)
+				ctrl |= LargeSend |
+					((mss & MSSMask) << MSSShift);
+			else if (skb->ip_summed == CHECKSUM_HW) {
 				if (ip->protocol == IPPROTO_TCP)
-					ctrl |= TCPCS;
+					ctrl |= IPCS | TCPCS;
 				else if (ip->protocol == IPPROTO_UDP)
-					ctrl |= UDPCS;
+					ctrl |= IPCS | UDPCS;
 				else
 					BUG();
-			} else
-				ctrl = eor | len | DescOwn;
+			}
 
 			if (frag == skb_shinfo(skb)->nr_frags - 1)
 				ctrl |= LastFrag;
@@ -860,7 +889,7 @@
 
 			cp->tx_skb[entry].skb = skb;
 			cp->tx_skb[entry].mapping = mapping;
-			cp->tx_skb[entry].frag = frag + 2;
+			cp->tx_skb[entry].len = len;
 			entry = NEXT_TX(entry);
 		}
 
@@ -1074,7 +1103,6 @@
 		cp->rx_skb[i].mapping = pci_map_single(cp->pdev,
 			skb->tail, cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
 		cp->rx_skb[i].skb = skb;
-		cp->rx_skb[i].frag = 0;
 
 		cp->rx_ring[i].opts2 = 0;
 		cp->rx_ring[i].addr = cpu_to_le64(cp->rx_skb[i].mapping);
@@ -1126,9 +1154,6 @@
 {
 	unsigned i;
 
-	memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
-	memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
-
 	for (i = 0; i < CP_RX_RING_SIZE; i++) {
 		if (cp->rx_skb[i].skb) {
 			pci_unmap_single(cp->pdev, cp->rx_skb[i].mapping,
@@ -1140,13 +1165,18 @@
 	for (i = 0; i < CP_TX_RING_SIZE; i++) {
 		if (cp->tx_skb[i].skb) {
 			struct sk_buff *skb = cp->tx_skb[i].skb;
+
 			pci_unmap_single(cp->pdev, cp->tx_skb[i].mapping,
-					 skb->len, PCI_DMA_TODEVICE);
-			dev_kfree_skb(skb);
+				 	 cp->tx_skb[i].len, PCI_DMA_TODEVICE);
+			if (le32_to_cpu(cp->tx_ring[i].opts1) & LastFrag)
+				dev_kfree_skb(skb);
 			cp->net_stats.tx_dropped++;
 		}
 	}
 
+	memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
+	memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
+
 	memset(&cp->rx_skb, 0, sizeof(struct ring_info) * CP_RX_RING_SIZE);
 	memset(&cp->tx_skb, 0, sizeof(struct ring_info) * CP_TX_RING_SIZE);
 }
@@ -1486,22 +1516,22 @@
 				  struct ethtool_stats *estats, u64 *tmp_stats)
 {
 	struct cp_private *cp = netdev_priv(dev);
-	unsigned int work = 100;
 	int i;
 
+	memset(cp->nic_stats, 0, sizeof(struct cp_dma_stats));
+
 	/* begin NIC statistics dump */
 	cpw32(StatsAddr + 4, (cp->nic_stats_dma >> 16) >> 16);
 	cpw32(StatsAddr, (cp->nic_stats_dma & 0xffffffff) | DumpStats);
 	cpr32(StatsAddr);
 
-	while (work-- > 0) {
+	for (i = 0; i < 1000; i++) {
 		if ((cpr32(StatsAddr) & DumpStats) == 0)
 			break;
-		cpu_relax();
+		udelay(10);
 	}
-
-	if (cpr32(StatsAddr) & DumpStats)
-		return /* -EIO */;
+	cpw32(StatsAddr, 0);
+	cpw32(StatsAddr + 4, 0);
 
 	i = 0;
 	tmp_stats[i++] = le64_to_cpu(cp->nic_stats->tx_ok);
@@ -1538,6 +1568,8 @@
 	.set_tx_csum		= ethtool_op_set_tx_csum, /* local! */
 	.get_sg			= ethtool_op_get_sg,
 	.set_sg			= ethtool_op_set_sg,
+	.get_tso		= ethtool_op_get_tso,
+	.set_tso		= ethtool_op_set_tso,
 	.get_regs		= cp_get_regs,
 	.get_wol		= cp_get_wol,
 	.set_wol		= cp_set_wol,
@@ -1701,19 +1733,19 @@
 
 	/* Configure DMA attributes. */
 	if ((sizeof(dma_addr_t) > 4) &&
-	    !pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL) &&
-	    !pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) {
+	    !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK) &&
+	    !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
 		pci_using_dac = 1;
 	} else {
 		pci_using_dac = 0;
 
-		rc = pci_set_dma_mask(pdev, 0xffffffffULL);
+		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
 		if (rc) {
 			printk(KERN_ERR PFX "No usable DMA configuration, "
 			       "aborting.\n");
 			goto err_out_res;
 		}
-		rc = pci_set_consistent_dma_mask(pdev, 0xffffffffULL);
+		rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
 		if (rc) {
 			printk(KERN_ERR PFX "No usable consistent DMA configuration, "
 			       "aborting.\n");
@@ -1749,6 +1781,9 @@
 	dev->get_stats = cp_get_stats;
 	dev->do_ioctl = cp_ioctl;
 	dev->poll = cp_rx_poll;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = cp_poll_controller;
+#endif
 	dev->weight = 16;	/* arbitrary? from NAPI_HOWTO.txt. */
 #ifdef BROKEN
 	dev->change_mtu = cp_change_mtu;
@@ -1768,6 +1803,10 @@
 	if (pci_using_dac)
 		dev->features |= NETIF_F_HIGHDMA;
 
+#if 0 /* disabled by default until verified */
+	dev->features |= NETIF_F_TSO;
+#endif
+
 	dev->irq = pdev->irq;
 
 	rc = register_netdev(dev);
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index d4bd20c..5a4a08a 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -569,7 +569,7 @@
 };
 
 struct rtl8139_private {
-	void *mmio_addr;
+	void __iomem *mmio_addr;
 	int drv_flags;
 	struct pci_dev *pci_dev;
 	u32 msg_enable;
@@ -614,7 +614,7 @@
 MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps");
 MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)");
 
-static int read_eeprom (void *ioaddr, int location, int addr_len);
+static int read_eeprom (void __iomem *ioaddr, int location, int addr_len);
 static int rtl8139_open (struct net_device *dev);
 static int mdio_read (struct net_device *dev, int phy_id, int location);
 static void mdio_write (struct net_device *dev, int phy_id, int location,
@@ -638,46 +638,20 @@
 static void rtl8139_hw_start (struct net_device *dev);
 static struct ethtool_ops rtl8139_ethtool_ops;
 
-#ifdef USE_IO_OPS
-
-#define RTL_R8(reg)		inb (((unsigned long)ioaddr) + (reg))
-#define RTL_R16(reg)		inw (((unsigned long)ioaddr) + (reg))
-#define RTL_R32(reg)		((unsigned long) inl (((unsigned long)ioaddr) + (reg)))
-#define RTL_W8(reg, val8)	outb ((val8), ((unsigned long)ioaddr) + (reg))
-#define RTL_W16(reg, val16)	outw ((val16), ((unsigned long)ioaddr) + (reg))
-#define RTL_W32(reg, val32)	outl ((val32), ((unsigned long)ioaddr) + (reg))
-#define RTL_W8_F		RTL_W8
-#define RTL_W16_F		RTL_W16
-#define RTL_W32_F		RTL_W32
-#undef readb
-#undef readw
-#undef readl
-#undef writeb
-#undef writew
-#undef writel
-#define readb(addr) inb((unsigned long)(addr))
-#define readw(addr) inw((unsigned long)(addr))
-#define readl(addr) inl((unsigned long)(addr))
-#define writeb(val,addr) outb((val),(unsigned long)(addr))
-#define writew(val,addr) outw((val),(unsigned long)(addr))
-#define writel(val,addr) outl((val),(unsigned long)(addr))
-
-#else
-
 /* write MMIO register, with flush */
 /* Flush avoids rtl8139 bug w/ posted MMIO writes */
-#define RTL_W8_F(reg, val8)	do { writeb ((val8), ioaddr + (reg)); readb (ioaddr + (reg)); } while (0)
-#define RTL_W16_F(reg, val16)	do { writew ((val16), ioaddr + (reg)); readw (ioaddr + (reg)); } while (0)
-#define RTL_W32_F(reg, val32)	do { writel ((val32), ioaddr + (reg)); readl (ioaddr + (reg)); } while (0)
+#define RTL_W8_F(reg, val8)	do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0)
+#define RTL_W16_F(reg, val16)	do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0)
+#define RTL_W32_F(reg, val32)	do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0)
 
 
 #define MMIO_FLUSH_AUDIT_COMPLETE 1
 #if MMIO_FLUSH_AUDIT_COMPLETE
 
 /* write MMIO register */
-#define RTL_W8(reg, val8)	writeb ((val8), ioaddr + (reg))
-#define RTL_W16(reg, val16)	writew ((val16), ioaddr + (reg))
-#define RTL_W32(reg, val32)	writel ((val32), ioaddr + (reg))
+#define RTL_W8(reg, val8)	iowrite8 ((val8), ioaddr + (reg))
+#define RTL_W16(reg, val16)	iowrite16 ((val16), ioaddr + (reg))
+#define RTL_W32(reg, val32)	iowrite32 ((val32), ioaddr + (reg))
 
 #else
 
@@ -689,11 +663,9 @@
 #endif /* MMIO_FLUSH_AUDIT_COMPLETE */
 
 /* read MMIO register */
-#define RTL_R8(reg)		readb (ioaddr + (reg))
-#define RTL_R16(reg)		readw (ioaddr + (reg))
-#define RTL_R32(reg)		((unsigned long) readl (ioaddr + (reg)))
-
-#endif /* USE_IO_OPS */
+#define RTL_R8(reg)		ioread8 (ioaddr + (reg))
+#define RTL_R16(reg)		ioread16 (ioaddr + (reg))
+#define RTL_R32(reg)		((unsigned long) ioread32 (ioaddr + (reg)))
 
 
 static const u16 rtl8139_intr_mask =
@@ -740,10 +712,13 @@
 	assert (tp->pci_dev != NULL);
 	pdev = tp->pci_dev;
 
-#ifndef USE_IO_OPS
+#ifdef USE_IO_OPS
 	if (tp->mmio_addr)
-		iounmap (tp->mmio_addr);
-#endif /* !USE_IO_OPS */
+		ioport_unmap (tp->mmio_addr);
+#else
+	if (tp->mmio_addr)
+		pci_iounmap (pdev, tp->mmio_addr);
+#endif /* USE_IO_OPS */
 
 	/* it's ok to call this even if we have no regions to free */
 	pci_release_regions (pdev);
@@ -753,7 +728,7 @@
 }
 
 
-static void rtl8139_chip_reset (void *ioaddr)
+static void rtl8139_chip_reset (void __iomem *ioaddr)
 {
 	int i;
 
@@ -773,7 +748,7 @@
 static int __devinit rtl8139_init_board (struct pci_dev *pdev,
 					 struct net_device **dev_out)
 {
-	void *ioaddr;
+	void __iomem *ioaddr;
 	struct net_device *dev;
 	struct rtl8139_private *tp;
 	u8 tmp8;
@@ -855,13 +830,18 @@
 	pci_set_master (pdev);
 
 #ifdef USE_IO_OPS
-	ioaddr = (void *) pio_start;
+	ioaddr = ioport_map(pio_start, pio_len);
+	if (!ioaddr) {
+		printk (KERN_ERR PFX "%s: cannot map PIO, aborting\n", pci_name(pdev));
+		rc = -EIO;
+		goto err_out;
+	}
 	dev->base_addr = pio_start;
 	tp->mmio_addr = ioaddr;
 	tp->regs_len = pio_len;
 #else
 	/* ioremap MMIO region */
-	ioaddr = ioremap (mmio_start, mmio_len);
+	ioaddr = pci_iomap(pdev, 1, 0);
 	if (ioaddr == NULL) {
 		printk (KERN_ERR PFX "%s: cannot remap MMIO, aborting\n", pci_name(pdev));
 		rc = -EIO;
@@ -947,7 +927,7 @@
 	struct net_device *dev = NULL;
 	struct rtl8139_private *tp;
 	int i, addr_len, option;
-	void *ioaddr;
+	void __iomem *ioaddr;
 	static int board_idx = -1;
 	u8 pci_rev;
 
@@ -1147,47 +1127,46 @@
    No extra delay is needed with 33Mhz PCI, but 66Mhz may change this.
  */
 
-#define eeprom_delay()	readl(ee_addr)
+#define eeprom_delay()	RTL_R32(Cfg9346)
 
 /* The EEPROM commands include the alway-set leading bit. */
 #define EE_WRITE_CMD	(5)
 #define EE_READ_CMD		(6)
 #define EE_ERASE_CMD	(7)
 
-static int __devinit read_eeprom (void *ioaddr, int location, int addr_len)
+static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len)
 {
 	int i;
 	unsigned retval = 0;
-	void *ee_addr = ioaddr + Cfg9346;
 	int read_cmd = location | (EE_READ_CMD << addr_len);
 
-	writeb (EE_ENB & ~EE_CS, ee_addr);
-	writeb (EE_ENB, ee_addr);
+	RTL_W8 (Cfg9346, EE_ENB & ~EE_CS);
+	RTL_W8 (Cfg9346, EE_ENB);
 	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;
-		writeb (EE_ENB | dataval, ee_addr);
+		RTL_W8 (Cfg9346, EE_ENB | dataval);
 		eeprom_delay ();
-		writeb (EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
+		RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK);
 		eeprom_delay ();
 	}
-	writeb (EE_ENB, ee_addr);
+	RTL_W8 (Cfg9346, EE_ENB);
 	eeprom_delay ();
 
 	for (i = 16; i > 0; i--) {
-		writeb (EE_ENB | EE_SHIFT_CLK, ee_addr);
+		RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK);
 		eeprom_delay ();
 		retval =
-		    (retval << 1) | ((readb (ee_addr) & EE_DATA_READ) ? 1 :
+		    (retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 :
 				     0);
-		writeb (EE_ENB, ee_addr);
+		RTL_W8 (Cfg9346, EE_ENB);
 		eeprom_delay ();
 	}
 
 	/* Terminate the EEPROM access. */
-	writeb (~EE_CS, ee_addr);
+	RTL_W8 (Cfg9346, ~EE_CS);
 	eeprom_delay ();
 
 	return retval;
@@ -1206,7 +1185,7 @@
 #define MDIO_WRITE0 (MDIO_DIR)
 #define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT)
 
-#define mdio_delay(mdio_addr)	readb(mdio_addr)
+#define mdio_delay()	RTL_R8(Config4)
 
 
 static char mii_2_8139_map[8] = {
@@ -1223,15 +1202,15 @@
 
 #ifdef CONFIG_8139TOO_8129
 /* Syncronize the MII management interface by shifting 32 one bits out. */
-static void mdio_sync (void *mdio_addr)
+static void mdio_sync (void __iomem *ioaddr)
 {
 	int i;
 
 	for (i = 32; i >= 0; i--) {
-		writeb (MDIO_WRITE1, mdio_addr);
-		mdio_delay (mdio_addr);
-		writeb (MDIO_WRITE1 | MDIO_CLK, mdio_addr);
-		mdio_delay (mdio_addr);
+		RTL_W8 (Config4, MDIO_WRITE1);
+		mdio_delay ();
+		RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK);
+		mdio_delay ();
 	}
 }
 #endif
@@ -1241,35 +1220,36 @@
 	struct rtl8139_private *tp = netdev_priv(dev);
 	int retval = 0;
 #ifdef CONFIG_8139TOO_8129
-	void *mdio_addr = tp->mmio_addr + Config4;
+	void __iomem *ioaddr = tp->mmio_addr;
 	int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
 	int i;
 #endif
 
 	if (phy_id > 31) {	/* Really a 8139.  Use internal registers. */
+		void __iomem *ioaddr = tp->mmio_addr;
 		return location < 8 && mii_2_8139_map[location] ?
-		    readw (tp->mmio_addr + mii_2_8139_map[location]) : 0;
+		    RTL_R16 (mii_2_8139_map[location]) : 0;
 	}
 
 #ifdef CONFIG_8139TOO_8129
-	mdio_sync (mdio_addr);
+	mdio_sync (ioaddr);
 	/* Shift the read command bits out. */
 	for (i = 15; i >= 0; i--) {
 		int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0;
 
-		writeb (MDIO_DIR | dataval, mdio_addr);
-		mdio_delay (mdio_addr);
-		writeb (MDIO_DIR | dataval | MDIO_CLK, mdio_addr);
-		mdio_delay (mdio_addr);
+		RTL_W8 (Config4, MDIO_DIR | dataval);
+		mdio_delay ();
+		RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK);
+		mdio_delay ();
 	}
 
 	/* Read the two transition, 16 data, and wire-idle bits. */
 	for (i = 19; i > 0; i--) {
-		writeb (0, mdio_addr);
-		mdio_delay (mdio_addr);
-		retval = (retval << 1) | ((readb (mdio_addr) & MDIO_DATA_IN) ? 1 : 0);
-		writeb (MDIO_CLK, mdio_addr);
-		mdio_delay (mdio_addr);
+		RTL_W8 (Config4, 0);
+		mdio_delay ();
+		retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0);
+		RTL_W8 (Config4, MDIO_CLK);
+		mdio_delay ();
 	}
 #endif
 
@@ -1282,13 +1262,13 @@
 {
 	struct rtl8139_private *tp = netdev_priv(dev);
 #ifdef CONFIG_8139TOO_8129
-	void *mdio_addr = tp->mmio_addr + Config4;
+	void __iomem *ioaddr = tp->mmio_addr;
 	int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
 	int i;
 #endif
 
 	if (phy_id > 31) {	/* Really a 8139.  Use internal registers. */
-		void *ioaddr = tp->mmio_addr;
+		void __iomem *ioaddr = tp->mmio_addr;
 		if (location == 0) {
 			RTL_W8 (Cfg9346, Cfg9346_Unlock);
 			RTL_W16 (BasicModeCtrl, value);
@@ -1299,23 +1279,23 @@
 	}
 
 #ifdef CONFIG_8139TOO_8129
-	mdio_sync (mdio_addr);
+	mdio_sync (ioaddr);
 
 	/* Shift the command bits out. */
 	for (i = 31; i >= 0; i--) {
 		int dataval =
 		    (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
-		writeb (dataval, mdio_addr);
-		mdio_delay (mdio_addr);
-		writeb (dataval | MDIO_CLK, mdio_addr);
-		mdio_delay (mdio_addr);
+		RTL_W8 (Config4, dataval);
+		mdio_delay ();
+		RTL_W8 (Config4, dataval | MDIO_CLK);
+		mdio_delay ();
 	}
 	/* Clear out extra bits. */
 	for (i = 2; i > 0; i--) {
-		writeb (0, mdio_addr);
-		mdio_delay (mdio_addr);
-		writeb (MDIO_CLK, mdio_addr);
-		mdio_delay (mdio_addr);
+		RTL_W8 (Config4, 0);
+		mdio_delay ();
+		RTL_W8 (Config4, MDIO_CLK);
+		mdio_delay ();
 	}
 #endif
 }
@@ -1325,7 +1305,7 @@
 {
 	struct rtl8139_private *tp = netdev_priv(dev);
 	int retval;
-	void *ioaddr = tp->mmio_addr;
+	void __iomem *ioaddr = tp->mmio_addr;
 
 	retval = request_irq (dev->irq, rtl8139_interrupt, SA_SHIRQ, dev->name, dev);
 	if (retval)
@@ -1382,7 +1362,7 @@
 static void rtl8139_hw_start (struct net_device *dev)
 {
 	struct rtl8139_private *tp = netdev_priv(dev);
-	void *ioaddr = tp->mmio_addr;
+	void __iomem *ioaddr = tp->mmio_addr;
 	u32 i;
 	u8 tmp;
 
@@ -1484,7 +1464,7 @@
 				  struct rtl8139_private *tp)
 {
 	int linkcase;
-	void *ioaddr = tp->mmio_addr;
+	void __iomem *ioaddr = tp->mmio_addr;
 
 	/* This is a complicated state machine to configure the "twister" for
 	   impedance/echos based on the cable length.
@@ -1568,7 +1548,7 @@
 
 static inline void rtl8139_thread_iter (struct net_device *dev,
 				 struct rtl8139_private *tp,
-				 void *ioaddr)
+				 void __iomem *ioaddr)
 {
 	int mii_lpa;
 
@@ -1626,7 +1606,7 @@
 		do {
 			timeout = interruptible_sleep_on_timeout (&tp->thr_wait, timeout);
 			/* make swsusp happy with our thread */
-			try_to_freeze(PF_FREEZE);
+			try_to_freeze();
 		} while (!signal_pending (current) && (timeout > 0));
 
 		if (signal_pending (current)) {
@@ -1676,7 +1656,7 @@
 static void rtl8139_tx_timeout (struct net_device *dev)
 {
 	struct rtl8139_private *tp = netdev_priv(dev);
-	void *ioaddr = tp->mmio_addr;
+	void __iomem *ioaddr = tp->mmio_addr;
 	int i;
 	u8 tmp8;
 	unsigned long flags;
@@ -1721,7 +1701,7 @@
 static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
 {
 	struct rtl8139_private *tp = netdev_priv(dev);
-	void *ioaddr = tp->mmio_addr;
+	void __iomem *ioaddr = tp->mmio_addr;
 	unsigned int entry;
 	unsigned int len = skb->len;
 
@@ -1763,7 +1743,7 @@
 
 static void rtl8139_tx_interrupt (struct net_device *dev,
 				  struct rtl8139_private *tp,
-				  void *ioaddr)
+				  void __iomem *ioaddr)
 {
 	unsigned long dirty_tx, tx_left;
 
@@ -1833,7 +1813,7 @@
 
 /* TODO: clean this up!  Rx reset need not be this intensive */
 static void rtl8139_rx_err (u32 rx_status, struct net_device *dev,
-			    struct rtl8139_private *tp, void *ioaddr)
+			    struct rtl8139_private *tp, void __iomem *ioaddr)
 {
 	u8 tmp8;
 #ifdef CONFIG_8139_OLD_RX_RESET
@@ -1930,7 +1910,7 @@
 
 static void rtl8139_isr_ack(struct rtl8139_private *tp)
 {
-	void *ioaddr = tp->mmio_addr;
+	void __iomem *ioaddr = tp->mmio_addr;
 	u16 status;
 
 	status = RTL_R16 (IntrStatus) & RxAckBits;
@@ -1949,7 +1929,7 @@
 static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
 		      int budget)
 {
-	void *ioaddr = tp->mmio_addr;
+	void __iomem *ioaddr = tp->mmio_addr;
 	int received = 0;
 	unsigned char *rx_ring = tp->rx_ring;
 	unsigned int cur_rx = tp->cur_rx;
@@ -2087,7 +2067,7 @@
 
 static void rtl8139_weird_interrupt (struct net_device *dev,
 				     struct rtl8139_private *tp,
-				     void *ioaddr,
+				     void __iomem *ioaddr,
 				     int status, int link_changed)
 {
 	DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n",
@@ -2127,7 +2107,7 @@
 static int rtl8139_poll(struct net_device *dev, int *budget)
 {
 	struct rtl8139_private *tp = netdev_priv(dev);
-	void *ioaddr = tp->mmio_addr;
+	void __iomem *ioaddr = tp->mmio_addr;
 	int orig_budget = min(*budget, dev->quota);
 	int done = 1;
 
@@ -2165,7 +2145,7 @@
 {
 	struct net_device *dev = (struct net_device *) dev_instance;
 	struct rtl8139_private *tp = netdev_priv(dev);
-	void *ioaddr = tp->mmio_addr;
+	void __iomem *ioaddr = tp->mmio_addr;
 	u16 status, ackstat;
 	int link_changed = 0; /* avoid bogus "uninit" warning */
 	int handled = 0;
@@ -2241,7 +2221,7 @@
 static int rtl8139_close (struct net_device *dev)
 {
 	struct rtl8139_private *tp = netdev_priv(dev);
-	void *ioaddr = tp->mmio_addr;
+	void __iomem *ioaddr = tp->mmio_addr;
 	int ret = 0;
 	unsigned long flags;
 
@@ -2304,7 +2284,7 @@
 static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
 	struct rtl8139_private *np = netdev_priv(dev);
-	void *ioaddr = np->mmio_addr;
+	void __iomem *ioaddr = np->mmio_addr;
 
 	spin_lock_irq(&np->lock);
 	if (rtl_chip_info[np->chipset].flags & HasLWake) {
@@ -2338,7 +2318,7 @@
 static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
 	struct rtl8139_private *np = netdev_priv(dev);
-	void *ioaddr = np->mmio_addr;
+	void __iomem *ioaddr = np->mmio_addr;
 	u32 support;
 	u8 cfg3, cfg5;
 
@@ -2506,7 +2486,7 @@
 static struct net_device_stats *rtl8139_get_stats (struct net_device *dev)
 {
 	struct rtl8139_private *tp = netdev_priv(dev);
-	void *ioaddr = tp->mmio_addr;
+	void __iomem *ioaddr = tp->mmio_addr;
 	unsigned long flags;
 
 	if (netif_running(dev)) {
@@ -2525,7 +2505,7 @@
 static void __set_rx_mode (struct net_device *dev)
 {
 	struct rtl8139_private *tp = netdev_priv(dev);
-	void *ioaddr = tp->mmio_addr;
+	void __iomem *ioaddr = tp->mmio_addr;
 	u32 mc_filter[2];	/* Multicast hash filter */
 	int i, rx_mode;
 	u32 tmp;
@@ -2586,7 +2566,7 @@
 {
 	struct net_device *dev = pci_get_drvdata (pdev);
 	struct rtl8139_private *tp = netdev_priv(dev);
-	void *ioaddr = tp->mmio_addr;
+	void __iomem *ioaddr = tp->mmio_addr;
 	unsigned long flags;
 
 	pci_save_state (pdev);
diff --git a/drivers/net/8390.c b/drivers/net/8390.c
index bab16bc..6d76f3a 100644
--- a/drivers/net/8390.c
+++ b/drivers/net/8390.c
@@ -225,9 +225,9 @@
 	unsigned long icucr;
 
 	local_irq_save(flags);
-	icucr = inl(ICUCR1);
+	icucr = inl(M32R_ICU_CR1_PORTL);
 	icucr |= M32R_ICUCR_ISMOD11;
-	outl(icucr, ICUCR1);
+	outl(icucr, M32R_ICU_CR1_PORTL);
 	local_irq_restore(flags);
 #endif
 	ei_local->stat.tx_errors++;
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index f08e01b..47e158f 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -824,6 +824,18 @@
 	  <file:Documentation/networking/net-modules.txt>. The module
 	  will be called smc9194.
 
+config DM9000
+	tristate "DM9000 support"
+	depends on ARM && NET_ETHERNET
+	select CRC32
+	select MII
+	---help---
+	  Support for DM9000 chipset.
+
+	  To compile this driver as a module, choose M here and read
+	  <file:Documentation/networking/net-modules.txt>.  The module will be
+	  called dm9000.
+
 config NET_VENDOR_RACAL
 	bool "Racal-Interlan (Micom) NI cards"
 	depends on NET_ETHERNET && ISA
@@ -989,21 +1001,6 @@
 	  <file:Documentation/networking/net-modules.txt>. The module
 	  will be called eepro.
 
-config FMV18X
-	tristate "FMV-181/182/183/184 support (OBSOLETE)"
-	depends on NET_ISA && OBSOLETE
-	---help---
-	  If you have a Fujitsu FMV-181/182/183/184 network (Ethernet) card,
-	  say Y and read the Ethernet-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>.
-
-	  If you use an FMV-183 or FMV-184 and it is not working, you may need
-	  to disable Plug & Play mode of the card.
-
-	  To compile this driver as a module, choose M here and read
-	  <file:Documentation/networking/net-modules.txt>. The module
-	  will be called fmv18x.
-
 config HPLAN_PLUS
 	tristate "HP PCLAN+ (27247B and 27252A) support"
 	depends on NET_ISA
@@ -1092,14 +1089,6 @@
 	  <file:Documentation/networking/net-modules.txt>. The module
 	  will be called seeq8005.
 
-config SK_G16
-	tristate "SK_G16 support (OBSOLETE)"
-	depends on NET_ISA && OBSOLETE
-	help
-	  If you have a network (Ethernet) card of this type, say Y and read
-	  the Ethernet-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>.
-
 config SKMC
 	tristate "SKnet MCA support"
 	depends on NET_ETHERNET && MCA && BROKEN
@@ -1499,14 +1488,14 @@
 	  will be called 8139cp.  This is recommended.
 
 config 8139TOO
-	tristate "RealTek RTL-8139 PCI Fast Ethernet Adapter support"
+	tristate "RealTek RTL-8129/8130/8139 PCI Fast Ethernet Adapter support"
 	depends on NET_PCI && PCI
 	select CRC32
 	select MII
 	---help---
 	  This is a driver for the Fast Ethernet PCI network cards based on
-	  the RTL8139 chips. If you have one of those, say Y and read
-	  the Ethernet-HOWTO <http://www.tldp.org/docs.html#howto>.
+	  the RTL 8129/8130/8139 chips. If you have one of those, say Y and
+	  read the Ethernet-HOWTO <http://www.tldp.org/docs.html#howto>.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called 8139too.  This is recommended.
@@ -1932,6 +1921,18 @@
 	  
 	  If in doubt, say Y.
 
+config SKGE
+	tristate "New SysKonnect GigaEthernet support (EXPERIMENTAL)"
+	depends on PCI && EXPERIMENTAL
+	select CRC32
+	---help---
+	  This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx
+	  and related Gigabit Ethernet adapters. It is a new smaller driver
+	  driver with better performance and more complete ethtool support.
+
+	  It does not support the link failover and network management 
+	  features that "portable" vendor supplied sk98lin driver does.
+	
 config SK98LIN
 	tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support"
 	depends on PCI
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 30c7567..63c6d1e 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -53,6 +53,7 @@
 obj-$(CONFIG_TIGON3) += tg3.o
 obj-$(CONFIG_BNX2) += bnx2.o
 obj-$(CONFIG_TC35815) += tc35815.o
+obj-$(CONFIG_SKGE) += skge.o
 obj-$(CONFIG_SK98LIN) += sk98lin/
 obj-$(CONFIG_SKFP) += skfp/
 obj-$(CONFIG_VIA_RHINE) += via-rhine.o
@@ -74,7 +75,6 @@
 obj-$(CONFIG_APNE) += apne.o 8390.o
 obj-$(CONFIG_PCMCIA_PCNET) += 8390.o
 obj-$(CONFIG_SHAPER) += shaper.o
-obj-$(CONFIG_SK_G16) += sk_g16.o
 obj-$(CONFIG_HP100) += hp100.o
 obj-$(CONFIG_SMC9194) += smc9194.o
 obj-$(CONFIG_FEC) += fec.o
@@ -122,7 +122,6 @@
 obj-$(CONFIG_SGISEEQ) += sgiseeq.o
 obj-$(CONFIG_SGI_O2MACE_ETH) += meth.o
 obj-$(CONFIG_AT1700) += at1700.o
-obj-$(CONFIG_FMV18X) += fmv18x.o
 obj-$(CONFIG_EL1) += 3c501.o
 obj-$(CONFIG_EL16) += 3c507.o
 obj-$(CONFIG_ELMC) += 3c523.o
@@ -180,6 +179,7 @@
 obj-$(CONFIG_IBMVETH) += ibmveth.o
 obj-$(CONFIG_S2IO) += s2io.o
 obj-$(CONFIG_SMC91X) += smc91x.o
+obj-$(CONFIG_DM9000) += dm9000.o
 obj-$(CONFIG_FEC_8XX) += fec_8xx/
 
 obj-$(CONFIG_ARM) += arm/
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index fb43332..3707df6 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -210,9 +210,6 @@
 #ifdef CONFIG_AT1700
 	{at1700_probe, 0},
 #endif
-#ifdef CONFIG_FMV18X		/* Fujitsu FMV-181/182 */
-	{fmv18x_probe, 0},
-#endif
 #ifdef CONFIG_ETH16I
 	{eth16i_probe, 0},	/* ICL EtherTeam 16i/32 */
 #endif
@@ -243,9 +240,6 @@
 #ifdef CONFIG_ELPLUS		/* 3c505 */
 	{elplus_probe, 0},
 #endif
-#ifdef CONFIG_SK_G16
-	{SK_init, 0},
-#endif
 #ifdef CONFIG_NI5010
 	{ni5010_probe, 0},
 #endif
diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c
index 24fba36..91791ba 100644
--- a/drivers/net/ac3200.c
+++ b/drivers/net/ac3200.c
@@ -146,12 +146,7 @@
 	err = do_ac3200_probe(dev);
 	if (err)
 		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
 	return dev;
-out1:
-	cleanup_card(dev);
 out:
 	free_netdev(dev);
 	return ERR_PTR(err);
@@ -273,7 +268,14 @@
 	dev->poll_controller = ei_poll;
 #endif
 	NS8390_init(dev, 0);
+
+	retval = register_netdev(dev);
+	if (retval)
+		goto out2;
 	return 0;
+out2:
+	if (ei_status.reg0)
+		iounmap((void *)dev->mem_start);
 out1:
 	free_irq(dev->irq, dev);
 out:
@@ -392,11 +394,8 @@
 		dev->base_addr = io[this_dev];
 		dev->mem_start = mem[this_dev];		/* Currently ignored by driver */
 		if (do_ac3200_probe(dev) == 0) {
-			if (register_netdev(dev) == 0) {
-				dev_ac32[found++] = dev;
-				continue;
-			}
-			cleanup_card(dev);
+			dev_ac32[found++] = dev;
+			continue;
 		}
 		free_netdev(dev);
 		printk(KERN_WARNING "ac3200.c: No ac3200 card found (i/o = 0x%x).\n", io[this_dev]);
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index 6eea3a8..dbecc6b 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -58,6 +58,7 @@
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -1167,9 +1168,9 @@
 	/*
 	 * Configure DMA attributes.
 	 */
-	if (!pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) {
+	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
 		ap->pci_using_dac = 1;
-	} else if (!pci_set_dma_mask(pdev, 0xffffffffULL)) {
+	} else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
 		ap->pci_using_dac = 0;
 	} else {
 		ecode = -ENODEV;
diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c
index db4f369..d5666c3 100644
--- a/drivers/net/appletalk/ltpc.c
+++ b/drivers/net/appletalk/ltpc.c
@@ -1109,8 +1109,7 @@
 	inb_p(io+1);
 	inb_p(io+3);
 
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(2*HZ/100);
+	msleep(20);
 
 	inb_p(io+0);
 	inb_p(io+2);
@@ -1120,8 +1119,7 @@
 	inb_p(io+5); /* enable dma */
 	inb_p(io+6); /* tri-state interrupt line */
 
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ);
+	ssleep(1);
 	
 	/* now, figure out which dma channel we're using, unless it's
 	   already been specified */
diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c
index 942a281..2e28c20 100644
--- a/drivers/net/arm/etherh.c
+++ b/drivers/net/arm/etherh.c
@@ -68,6 +68,7 @@
 	void __iomem	*dma_base;
 	unsigned int	id;
 	void __iomem	*ctrl_port;
+	void __iomem	*base;
 	unsigned char	ctrl;
 	u32		supported;
 };
@@ -177,7 +178,7 @@
 	switch (etherh_priv(dev)->id) {
 	case PROD_I3_ETHERLAN600:
 	case PROD_I3_ETHERLAN600A:
-		addr = (void *)dev->base_addr + EN0_RCNTHI;
+		addr = etherh_priv(dev)->base + EN0_RCNTHI;
 
 		switch (dev->if_port) {
 		case IF_PORT_10BASE2:
@@ -218,7 +219,7 @@
 	switch (etherh_priv(dev)->id) {
 	case PROD_I3_ETHERLAN600:
 	case PROD_I3_ETHERLAN600A:
-		addr = (void *)dev->base_addr + EN0_RCNTHI;
+		addr = etherh_priv(dev)->base + EN0_RCNTHI;
 		switch (dev->if_port) {
 		case IF_PORT_10BASE2:
 			stat = 1;
@@ -281,7 +282,7 @@
 etherh_reset(struct net_device *dev)
 {
 	struct ei_device *ei_local = netdev_priv(dev);
-	void __iomem *addr = (void *)dev->base_addr;
+	void __iomem *addr = etherh_priv(dev)->base;
 
 	writeb(E8390_NODMA+E8390_PAGE0+E8390_STOP, addr);
 
@@ -327,7 +328,7 @@
 
 	ei_local->dmaing = 1;
 
-	addr = (void *)dev->base_addr;
+	addr = etherh_priv(dev)->base;
 	dma_base = etherh_priv(dev)->dma_base;
 
 	count = (count + 1) & ~1;
@@ -387,7 +388,7 @@
 
 	ei_local->dmaing = 1;
 
-	addr = (void *)dev->base_addr;
+	addr = etherh_priv(dev)->base;
 	dma_base = etherh_priv(dev)->dma_base;
 
 	buf = skb->data;
@@ -427,7 +428,7 @@
 
 	ei_local->dmaing = 1;
 
-	addr = (void *)dev->base_addr;
+	addr = etherh_priv(dev)->base;
 	dma_base = etherh_priv(dev)->dma_base;
 
 	writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
@@ -696,7 +697,8 @@
 		eh->ctrl_port = eh->ioc_fast;
 	}
 
-	dev->base_addr = (unsigned long)eh->memc + data->ns8390_offset;
+	eh->base = eh->memc + data->ns8390_offset;
+	dev->base_addr = (unsigned long)eh->base;
 	eh->dma_base = eh->memc + data->dataport_offset;
 	eh->ctrl_port += data->ctrlport_offset;
 
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index 5a2efd3..c82b9cd 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -1681,10 +1681,6 @@
 		control |= MAC_FULL_DUPLEX;
 	}
 
-	/* fix for startup without cable */
-	if (!link) 
-		dev->flags &= ~IFF_RUNNING;
-
 	aup->mac->control = control;
 	aup->mac->vlan1_tag = 0x8100; /* activate vlan support */
 	au_sync();
@@ -1709,16 +1705,14 @@
 	if_port = dev->if_port;
 	if (aup->phy_ops->phy_status(dev, aup->phy_addr, &link, &speed) == 0) {
 		if (link) {
-			if (!(dev->flags & IFF_RUNNING)) {
+			if (!netif_carrier_ok(dev)) {
 				netif_carrier_on(dev);
-				dev->flags |= IFF_RUNNING;
 				printk(KERN_INFO "%s: link up\n", dev->name);
 			}
 		}
 		else {
-			if (dev->flags & IFF_RUNNING) {
+			if (netif_carrier_ok(dev)) {
 				netif_carrier_off(dev);
-				dev->flags &= ~IFF_RUNNING;
 				dev->if_port = 0;
 				printk(KERN_INFO "%s: link down\n", dev->name);
 			}
diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c
index 734bd4e..00e5257 100644
--- a/drivers/net/bmac.c
+++ b/drivers/net/bmac.c
@@ -1412,7 +1412,6 @@
 	bp->opened = 1;
 	bmac_reset_and_enable(dev);
 	enable_irq(dev->irq);
-	dev->flags |= IFF_RUNNING;
 	return 0;
 }
 
@@ -1425,7 +1424,6 @@
 	int i;
 
 	bp->sleeping = 1;
-	dev->flags &= ~(IFF_UP | IFF_RUNNING);
 
 	/* disable rx and tx */
 	config = bmread(dev, RXCFG);
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 6233c4f..a2e8dda 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2346,7 +2346,6 @@
 {
 	struct slave *slave, *start_at;
 	struct bonding *bond = dev->priv;
-	struct ethhdr *data = (struct ethhdr *)skb->data;
 	int slave_agg_no;
 	int slaves_in_agg;
 	int agg_id;
@@ -2377,7 +2376,7 @@
 		goto out;
 	}
 
-	slave_agg_no = (data->h_dest[5]^bond->dev->dev_addr[5]) % slaves_in_agg;
+	slave_agg_no = bond->xmit_hash_policy(skb, dev, slaves_in_agg);
 
 	bond_for_each_slave(bond, slave, i) {
 		struct aggregator *agg = SLAVE_AD_INFO(slave).port.aggregator;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 269a5e4..2c930da 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -475,7 +475,18 @@
  *        Solution is to move call to dev_remove_pack outside of the
  *        spinlock.
  *        Set version to 2.6.1.
- *
+ * 2005/06/05 - Jay Vosburgh <fubar@us.ibm.com>
+ * 	- Support for generating gratuitous ARPs in active-backup mode.
+ * 	  Includes support for VLAN tagging all bonding-generated ARPs
+ * 	  as needed.  Set version to 2.6.2.
+ * 2005/06/08 - Jason Gabler <jygabler at lbl dot gov>
+ *	- alternate hashing policy support for mode 2
+ *	  * Added kernel parameter "xmit_hash_policy" to allow the selection
+ *	    of different hashing policies for mode 2.  The original mode 2
+ *	    policy is the default, now found in xmit_hash_policy_layer2().
+ *	  * Added xmit_hash_policy_layer34()
+ *	- Modified by Jay Vosburgh <fubar@us.ibm.com> to also support mode 4.
+ *	  Set version to 2.6.3.
  */
 
 //#define BONDING_DEBUG 1
@@ -490,7 +501,10 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
+#include <net/ip.h>
 #include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/init.h>
@@ -519,6 +533,7 @@
 #include <linux/ethtool.h>
 #include <linux/if_vlan.h>
 #include <linux/if_bonding.h>
+#include <net/route.h>
 #include "bonding.h"
 #include "bond_3ad.h"
 #include "bond_alb.h"
@@ -537,6 +552,7 @@
 static char *mode	= NULL;
 static char *primary	= NULL;
 static char *lacp_rate	= NULL;
+static char *xmit_hash_policy = NULL;
 static int arp_interval = BOND_LINK_ARP_INTERV;
 static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, };
 
@@ -556,6 +572,8 @@
 MODULE_PARM_DESC(primary, "Primary network device to use");
 module_param(lacp_rate, charp, 0);
 MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner (slow/fast)");
+module_param(xmit_hash_policy, charp, 0);
+MODULE_PARM_DESC(xmit_hash_policy, "XOR hashing method : 0 for layer 2 (default), 1 for layer 3+4");
 module_param(arp_interval, int, 0);
 MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds");
 module_param_array(arp_ip_target, charp, NULL, 0);
@@ -574,8 +592,8 @@
 
 static u32 arp_target[BOND_MAX_ARP_TARGETS] = { 0, } ;
 static int arp_ip_count	= 0;
-static u32 my_ip	= 0;
 static int bond_mode	= BOND_MODE_ROUNDROBIN;
+static int xmit_hashtype= BOND_XMIT_POLICY_LAYER2;
 static int lacp_fast	= 0;
 static int app_abi_ver	= 0;
 static int orig_app_abi_ver = -1; /* This is used to save the first ABI version
@@ -585,7 +603,6 @@
 				   * command comes from an application using
 				   * another ABI version.
 				   */
-
 struct bond_parm_tbl {
 	char *modename;
 	int mode;
@@ -608,9 +625,16 @@
 {	NULL,			-1},
 };
 
+static struct bond_parm_tbl xmit_hashtype_tbl[] = {
+{	"layer2",		BOND_XMIT_POLICY_LAYER2},
+{	"layer3+4",		BOND_XMIT_POLICY_LAYER34},
+{	NULL,			-1},
+};
+
 /*-------------------------- Forward declarations ---------------------------*/
 
-static inline void bond_set_mode_ops(struct net_device *bond_dev, int mode);
+static inline void bond_set_mode_ops(struct bonding *bond, int mode);
+static void bond_send_gratuitous_arp(struct bonding *bond);
 
 /*---------------------------- General routines -----------------------------*/
 
@@ -659,6 +683,7 @@
 
 	INIT_LIST_HEAD(&vlan->vlan_list);
 	vlan->vlan_id = vlan_id;
+	vlan->vlan_ip = 0;
 
 	write_lock_bh(&bond->lock);
 
@@ -1468,16 +1493,6 @@
 		}
 	}
 
-	if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
-		if (old_active) {
-			bond_set_slave_inactive_flags(old_active);
-		}
-
-		if (new_active) {
-			bond_set_slave_active_flags(new_active);
-		}
-	}
-
 	if (USES_PRIMARY(bond->params.mode)) {
 		bond_mc_swap(bond, new_active, old_active);
 	}
@@ -1488,6 +1503,17 @@
 	} else {
 		bond->curr_active_slave = new_active;
 	}
+
+	if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) {
+		if (old_active) {
+			bond_set_slave_inactive_flags(old_active);
+		}
+
+		if (new_active) {
+			bond_set_slave_active_flags(new_active);
+		}
+		bond_send_gratuitous_arp(bond);
+	}
 }
 
 /**
@@ -2694,15 +2720,180 @@
 	read_unlock(&bond->lock);
 }
 
+
+static u32 bond_glean_dev_ip(struct net_device *dev)
+{
+	struct in_device *idev;
+	struct in_ifaddr *ifa;
+	u32 addr = 0;
+
+	if (!dev)
+		return 0;
+
+	rcu_read_lock();
+	idev = __in_dev_get(dev);
+	if (!idev)
+		goto out;
+
+	ifa = idev->ifa_list;
+	if (!ifa)
+		goto out;
+
+	addr = ifa->ifa_local;
+out:
+	rcu_read_unlock();
+	return addr;
+}
+
+static int bond_has_ip(struct bonding *bond)
+{
+	struct vlan_entry *vlan, *vlan_next;
+
+	if (bond->master_ip)
+		return 1;
+
+	if (list_empty(&bond->vlan_list))
+		return 0;
+
+	list_for_each_entry_safe(vlan, vlan_next, &bond->vlan_list,
+				 vlan_list) {
+		if (vlan->vlan_ip)
+			return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * We go to the (large) trouble of VLAN tagging ARP frames because
+ * switches in VLAN mode (especially if ports are configured as
+ * "native" to a VLAN) might not pass non-tagged frames.
+ */
+static void bond_arp_send(struct net_device *slave_dev, int arp_op, u32 dest_ip, u32 src_ip, unsigned short vlan_id)
+{
+	struct sk_buff *skb;
+
+	dprintk("arp %d on slave %s: dst %x src %x vid %d\n", arp_op,
+	       slave_dev->name, dest_ip, src_ip, vlan_id);
+	       
+	skb = arp_create(arp_op, ETH_P_ARP, dest_ip, slave_dev, src_ip,
+			 NULL, slave_dev->dev_addr, NULL);
+
+	if (!skb) {
+		printk(KERN_ERR DRV_NAME ": ARP packet allocation failed\n");
+		return;
+	}
+	if (vlan_id) {
+		skb = vlan_put_tag(skb, vlan_id);
+		if (!skb) {
+			printk(KERN_ERR DRV_NAME ": failed to insert VLAN tag\n");
+			return;
+		}
+	}
+	arp_xmit(skb);
+}
+
+
 static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
 {
-	int i;
+	int i, vlan_id, rv;
 	u32 *targets = bond->params.arp_targets;
+	struct vlan_entry *vlan, *vlan_next;
+	struct net_device *vlan_dev;
+	struct flowi fl;
+	struct rtable *rt;
 
 	for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) {
-		arp_send(ARPOP_REQUEST, ETH_P_ARP, targets[i], slave->dev,
-			 my_ip, NULL, slave->dev->dev_addr,
-			 NULL);
+		dprintk("basa: target %x\n", targets[i]);
+		if (list_empty(&bond->vlan_list)) {
+			dprintk("basa: empty vlan: arp_send\n");
+			bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
+				      bond->master_ip, 0);
+			continue;
+		}
+
+		/*
+		 * If VLANs are configured, we do a route lookup to
+		 * determine which VLAN interface would be used, so we
+		 * can tag the ARP with the proper VLAN tag.
+		 */
+		memset(&fl, 0, sizeof(fl));
+		fl.fl4_dst = targets[i];
+		fl.fl4_tos = RTO_ONLINK;
+
+		rv = ip_route_output_key(&rt, &fl);
+		if (rv) {
+			if (net_ratelimit()) {
+				printk(KERN_WARNING DRV_NAME
+			     ": %s: no route to arp_ip_target %u.%u.%u.%u\n",
+				       bond->dev->name, NIPQUAD(fl.fl4_dst));
+			}
+			continue;
+		}
+
+		/*
+		 * This target is not on a VLAN
+		 */
+		if (rt->u.dst.dev == bond->dev) {
+			dprintk("basa: rtdev == bond->dev: arp_send\n");
+			bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
+				      bond->master_ip, 0);
+			continue;
+		}
+
+		vlan_id = 0;
+		list_for_each_entry_safe(vlan, vlan_next, &bond->vlan_list,
+					 vlan_list) {
+			vlan_dev = bond->vlgrp->vlan_devices[vlan->vlan_id];
+			if (vlan_dev == rt->u.dst.dev) {
+				vlan_id = vlan->vlan_id;
+				dprintk("basa: vlan match on %s %d\n",
+				       vlan_dev->name, vlan_id);
+				break;
+			}
+		}
+
+		if (vlan_id) {
+			bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
+				      vlan->vlan_ip, vlan_id);
+			continue;
+		}
+
+		if (net_ratelimit()) {
+			printk(KERN_WARNING DRV_NAME
+	       ": %s: no path to arp_ip_target %u.%u.%u.%u via rt.dev %s\n",
+			       bond->dev->name, NIPQUAD(fl.fl4_dst),
+			       rt->u.dst.dev ? rt->u.dst.dev->name : "NULL");
+		}
+	}
+}
+
+/*
+ * Kick out a gratuitous ARP for an IP on the bonding master plus one
+ * for each VLAN above us.
+ */
+static void bond_send_gratuitous_arp(struct bonding *bond)
+{
+	struct slave *slave = bond->curr_active_slave;
+	struct vlan_entry *vlan;
+	struct net_device *vlan_dev;
+
+	dprintk("bond_send_grat_arp: bond %s slave %s\n", bond->dev->name,
+				slave ? slave->dev->name : "NULL");
+	if (!slave)
+		return;
+
+	if (bond->master_ip) {
+		bond_arp_send(slave->dev, ARPOP_REPLY, bond->master_ip,
+				  bond->master_ip, 0);
+	}
+
+	list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
+		vlan_dev = bond->vlgrp->vlan_devices[vlan->vlan_id];
+		if (vlan->vlan_ip) {
+			bond_arp_send(slave->dev, ARPOP_REPLY, vlan->vlan_ip,
+				      vlan->vlan_ip, vlan->vlan_id);
+		}
 	}
 }
 
@@ -2781,7 +2972,7 @@
 			 */
 			if (((jiffies - slave->dev->trans_start) >= (2*delta_in_ticks)) ||
 			    (((jiffies - slave->dev->last_rx) >= (2*delta_in_ticks)) &&
-			     my_ip)) {
+			     bond_has_ip(bond))) {
 
 				slave->link  = BOND_LINK_DOWN;
 				slave->state = BOND_STATE_BACKUP;
@@ -2920,7 +3111,7 @@
 			if ((slave != bond->curr_active_slave) &&
 			    (!bond->current_arp_slave) &&
 			    (((jiffies - slave->dev->last_rx) >= 3*delta_in_ticks) &&
-			     my_ip)) {
+			     bond_has_ip(bond))) {
 				/* a backup slave has gone down; three times
 				 * the delta allows the current slave to be
 				 * taken out before the backup slave.
@@ -2966,8 +3157,8 @@
 		 * if it is up and needs to take over as the curr_active_slave
 		 */
 		if ((((jiffies - slave->dev->trans_start) >= (2*delta_in_ticks)) ||
-		     (((jiffies - slave->dev->last_rx) >= (2*delta_in_ticks)) &&
-		      my_ip)) &&
+	    (((jiffies - slave->dev->last_rx) >= (2*delta_in_ticks)) &&
+	     bond_has_ip(bond))) &&
 		    ((jiffies - slave->jiffies) >= 2*delta_in_ticks)) {
 
 			slave->link  = BOND_LINK_DOWN;
@@ -3019,7 +3210,7 @@
 		/* the current slave must tx an arp to ensure backup slaves
 		 * rx traffic
 		 */
-		if (slave && my_ip) {
+		if (slave && bond_has_ip(bond)) {
 			bond_arp_send_all(bond, slave);
 		}
 	}
@@ -3471,10 +3662,67 @@
 	return NOTIFY_DONE;
 }
 
+/*
+ * bond_inetaddr_event: handle inetaddr notifier chain events.
+ *
+ * We keep track of device IPs primarily to use as source addresses in
+ * ARP monitor probes (rather than spewing out broadcasts all the time).
+ *
+ * We track one IP for the main device (if it has one), plus one per VLAN.
+ */
+static int bond_inetaddr_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+	struct in_ifaddr *ifa = ptr;
+	struct net_device *vlan_dev, *event_dev = ifa->ifa_dev->dev;
+	struct bonding *bond, *bond_next;
+	struct vlan_entry *vlan, *vlan_next;
+
+	list_for_each_entry_safe(bond, bond_next, &bond_dev_list, bond_list) {
+		if (bond->dev == event_dev) {
+			switch (event) {
+			case NETDEV_UP:
+				bond->master_ip = ifa->ifa_local;
+				return NOTIFY_OK;
+			case NETDEV_DOWN:
+				bond->master_ip = bond_glean_dev_ip(bond->dev);
+				return NOTIFY_OK;
+			default:
+				return NOTIFY_DONE;
+			}
+		}
+
+		if (list_empty(&bond->vlan_list))
+			continue;
+
+		list_for_each_entry_safe(vlan, vlan_next, &bond->vlan_list,
+					 vlan_list) {
+			vlan_dev = bond->vlgrp->vlan_devices[vlan->vlan_id];
+			if (vlan_dev == event_dev) {
+				switch (event) {
+				case NETDEV_UP:
+					vlan->vlan_ip = ifa->ifa_local;
+					return NOTIFY_OK;
+				case NETDEV_DOWN:
+					vlan->vlan_ip =
+						bond_glean_dev_ip(vlan_dev);
+					return NOTIFY_OK;
+				default:
+					return NOTIFY_DONE;
+				}
+			}
+		}
+	}
+	return NOTIFY_DONE;
+}
+
 static struct notifier_block bond_netdev_notifier = {
 	.notifier_call = bond_netdev_event,
 };
 
+static struct notifier_block bond_inetaddr_notifier = {
+	.notifier_call = bond_inetaddr_event,
+};
+
 /*-------------------------- Packet type handling ---------------------------*/
 
 /* register to receive lacpdus on a bond */
@@ -3496,6 +3744,46 @@
 	dev_remove_pack(&(BOND_AD_INFO(bond).ad_pkt_type));
 }
 
+/*---------------------------- Hashing Policies -----------------------------*/
+
+/*
+ * Hash for the the output device based upon layer 3 and layer 4 data. If
+ * the packet is a frag or not TCP or UDP, just use layer 3 data.  If it is
+ * altogether not IP, mimic bond_xmit_hash_policy_l2()
+ */
+static int bond_xmit_hash_policy_l34(struct sk_buff *skb,
+				    struct net_device *bond_dev, int count)
+{
+	struct ethhdr *data = (struct ethhdr *)skb->data;
+	struct iphdr *iph = skb->nh.iph;
+	u16 *layer4hdr = (u16 *)((u32 *)iph + iph->ihl);
+	int layer4_xor = 0;
+
+	if (skb->protocol == __constant_htons(ETH_P_IP)) {
+		if (!(iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) &&
+		    (iph->protocol == IPPROTO_TCP ||
+		     iph->protocol == IPPROTO_UDP)) {
+			layer4_xor = htons((*layer4hdr ^ *(layer4hdr + 1)));
+		}
+		return (layer4_xor ^
+			((ntohl(iph->saddr ^ iph->daddr)) & 0xffff)) % count;
+
+	}
+
+	return (data->h_dest[5] ^ bond_dev->dev_addr[5]) % count;
+}
+
+/*
+ * Hash for the output device based upon layer 2 data
+ */
+static int bond_xmit_hash_policy_l2(struct sk_buff *skb,
+				   struct net_device *bond_dev, int count)
+{
+	struct ethhdr *data = (struct ethhdr *)skb->data;
+
+	return (data->h_dest[5] ^ bond_dev->dev_addr[5]) % count;
+}
+
 /*-------------------------- Device entry points ----------------------------*/
 
 static int bond_open(struct net_device *bond_dev)
@@ -4060,17 +4348,6 @@
 	struct bonding *bond = bond_dev->priv;
 	int res = 1;
 
-	/* if we are sending arp packets, try to at least
-	   identify our own ip address */
-	if (bond->params.arp_interval && !my_ip &&
-		(skb->protocol == __constant_htons(ETH_P_ARP))) {
-		char *the_ip = (char *)skb->data +
-				sizeof(struct ethhdr) +
-				sizeof(struct arphdr) +
-				ETH_ALEN;
-		memcpy(&my_ip, the_ip, 4);
-	}
-
 	read_lock(&bond->lock);
 	read_lock(&bond->curr_slave_lock);
 
@@ -4093,14 +4370,13 @@
 }
 
 /*
- * in XOR mode, we determine the output device by performing xor on
- * the source and destination hw adresses.  If this device is not
- * enabled, find the next slave following this xor slave.
+ * In bond_xmit_xor() , we determine the output device by using a pre-
+ * determined xmit_hash_policy(), If the selected device is not enabled,
+ * find the next active slave.
  */
 static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev)
 {
 	struct bonding *bond = bond_dev->priv;
-	struct ethhdr *data = (struct ethhdr *)skb->data;
 	struct slave *slave, *start_at;
 	int slave_no;
 	int i;
@@ -4112,7 +4388,7 @@
 		goto out;
 	}
 
-	slave_no = (data->h_dest[5]^bond_dev->dev_addr[5]) % bond->slave_cnt;
+	slave_no = bond->xmit_hash_policy(skb, bond_dev, bond->slave_cnt);
 
 	bond_for_each_slave(bond, slave, i) {
 		slave_no--;
@@ -4208,8 +4484,10 @@
 /*
  * set bond mode specific net device operations
  */
-static inline void bond_set_mode_ops(struct net_device *bond_dev, int mode)
+static inline void bond_set_mode_ops(struct bonding *bond, int mode)
 {
+	struct net_device *bond_dev = bond->dev;
+
 	switch (mode) {
 	case BOND_MODE_ROUNDROBIN:
 		bond_dev->hard_start_xmit = bond_xmit_roundrobin;
@@ -4219,12 +4497,20 @@
 		break;
 	case BOND_MODE_XOR:
 		bond_dev->hard_start_xmit = bond_xmit_xor;
+		if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER34)
+			bond->xmit_hash_policy = bond_xmit_hash_policy_l34;
+		else
+			bond->xmit_hash_policy = bond_xmit_hash_policy_l2;
 		break;
 	case BOND_MODE_BROADCAST:
 		bond_dev->hard_start_xmit = bond_xmit_broadcast;
 		break;
 	case BOND_MODE_8023AD:
 		bond_dev->hard_start_xmit = bond_3ad_xmit_xor;
+		if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER34)
+			bond->xmit_hash_policy = bond_xmit_hash_policy_l34;
+		else
+			bond->xmit_hash_policy = bond_xmit_hash_policy_l2;
 		break;
 	case BOND_MODE_TLB:
 	case BOND_MODE_ALB:
@@ -4273,7 +4559,7 @@
 	bond_dev->change_mtu = bond_change_mtu;
 	bond_dev->set_mac_address = bond_set_mac_address;
 
-	bond_set_mode_ops(bond_dev, bond->params.mode);
+	bond_set_mode_ops(bond, bond->params.mode);
 
 	bond_dev->destructor = free_netdev;
 
@@ -4384,6 +4670,25 @@
 		}
 	}
 
+	if (xmit_hash_policy) {
+		if ((bond_mode != BOND_MODE_XOR) &&
+		    (bond_mode != BOND_MODE_8023AD)) {
+			printk(KERN_INFO DRV_NAME
+			       ": xor_mode param is irrelevant in mode %s\n",
+			       bond_mode_name(bond_mode));
+		} else {
+			xmit_hashtype = bond_parse_parm(xmit_hash_policy,
+							xmit_hashtype_tbl);
+			if (xmit_hashtype == -1) {
+				printk(KERN_ERR DRV_NAME
+			       	": Error: Invalid xmit_hash_policy \"%s\"\n",
+			       	xmit_hash_policy == NULL ? "NULL" :
+				       xmit_hash_policy);
+				return -EINVAL;
+			}
+		}
+	}
+
 	if (lacp_rate) {
 		if (bond_mode != BOND_MODE_8023AD) {
 			printk(KERN_INFO DRV_NAME
@@ -4595,6 +4900,7 @@
 
 	/* fill params struct with the proper values */
 	params->mode = bond_mode;
+	params->xmit_policy = xmit_hashtype;
 	params->miimon = miimon;
 	params->arp_interval = arp_interval;
 	params->updelay = updelay;
@@ -4669,6 +4975,7 @@
 
 	rtnl_unlock();
 	register_netdevice_notifier(&bond_netdev_notifier);
+	register_inetaddr_notifier(&bond_inetaddr_notifier);
 
 	return 0;
 
@@ -4684,6 +4991,7 @@
 static void __exit bonding_exit(void)
 {
 	unregister_netdevice_notifier(&bond_netdev_notifier);
+	unregister_inetaddr_notifier(&bond_inetaddr_notifier);
 
 	rtnl_lock();
 	bond_free_all();
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 8c32530..d27f377 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -25,6 +25,10 @@
  *
  * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
  *	- Code cleanup and style changes
+ *
+ * 2005/05/05 - Jason Gabler <jygabler at lbl dot gov>
+ *      - added "xmit_policy" kernel parameter for alternate hashing policy
+ *	  support for mode 2
  */
 
 #ifndef _LINUX_BONDING_H
@@ -36,8 +40,8 @@
 #include "bond_3ad.h"
 #include "bond_alb.h"
 
-#define DRV_VERSION	"2.6.1"
-#define DRV_RELDATE	"October 29, 2004"
+#define DRV_VERSION	"2.6.3"
+#define DRV_RELDATE	"June 8, 2005"
 #define DRV_NAME	"bonding"
 #define DRV_DESCRIPTION	"Ethernet Channel Bonding Driver"
 
@@ -137,6 +141,7 @@
 
 struct bond_params {
 	int mode;
+	int xmit_policy;
 	int miimon;
 	int arp_interval;
 	int use_carrier;
@@ -149,6 +154,7 @@
 
 struct vlan_entry {
 	struct list_head vlan_list;
+	u32 vlan_ip;
 	unsigned short vlan_id;
 };
 
@@ -197,6 +203,8 @@
 #endif /* CONFIG_PROC_FS */
 	struct   list_head bond_list;
 	struct   dev_mc_list *mc_list;
+	int      (*xmit_hash_policy)(struct sk_buff *, struct net_device *, int);
+	u32      master_ip;
 	u16      flags;
 	struct   ad_bond_info ad_info;
 	struct   alb_bond_info alb_info;
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index 5c5f540..25e4495 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -319,13 +319,7 @@
 	}
 	if (err)
 		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
 	return dev;
-out1:
-	outw(PP_ChipID, dev->base_addr + ADD_PORT);
-	release_region(dev->base_addr, NETCARD_IO_EXTENT);
 out:
 	free_netdev(dev);
 	printk(KERN_WARNING "cs89x0: no cs8900 or cs8920 detected.  Be sure to disable PnP with SETUP\n");
@@ -735,7 +729,13 @@
 	printk("\n");
 	if (net_debug)
 		printk("cs89x0_probe1() successful\n");
+
+	retval = register_netdev(dev);
+	if (retval)
+		goto out3;
 	return 0;
+out3:
+	outw(PP_ChipID, dev->base_addr + ADD_PORT);
 out2:
 	release_region(ioaddr & ~3, NETCARD_IO_EXTENT);
 out1:
@@ -1831,13 +1831,6 @@
 	if (ret)
 		goto out;
 
-        if (register_netdev(dev) != 0) {
-                printk(KERN_ERR "cs89x0.c: No card found at 0x%x\n", io);
-                ret = -ENXIO;
-		outw(PP_ChipID, dev->base_addr + ADD_PORT);
-		release_region(dev->base_addr, NETCARD_IO_EXTENT);
-		goto out;
-        }
 	dev_cs89x0 = dev;
 	return 0;
 out:
diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
index a6aa565..5acd35c 100644
--- a/drivers/net/defxx.c
+++ b/drivers/net/defxx.c
@@ -191,6 +191,7 @@
  *		Feb 2001	davej		PCI enable cleanups.
  *		04 Aug 2003	macro		Converted to the DMA API.
  *		14 Aug 2004	macro		Fix device names reported.
+ *		14 Jun 2005	macro		Use irqreturn_t.
  */
 
 /* Include files */
@@ -217,8 +218,8 @@
 
 /* Version information string should be updated prior to each new release!  */
 #define DRV_NAME "defxx"
-#define DRV_VERSION "v1.07"
-#define DRV_RELDATE "2004/08/14"
+#define DRV_VERSION "v1.08"
+#define DRV_RELDATE "2005/06/14"
 
 static char version[] __devinitdata =
 	DRV_NAME ": " DRV_VERSION " " DRV_RELDATE
@@ -247,7 +248,8 @@
 static void		dfx_int_pr_halt_id(DFX_board_t *bp);
 static void		dfx_int_type_0_process(DFX_board_t *bp);
 static void		dfx_int_common(struct net_device *dev);
-static void		dfx_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t	dfx_interrupt(int irq, void *dev_id,
+				      struct pt_regs *regs);
 
 static struct		net_device_stats *dfx_ctl_get_stats(struct net_device *dev);
 static void		dfx_ctl_set_multicast_list(struct net_device *dev);
@@ -437,7 +439,8 @@
 	}
 
 	SET_MODULE_OWNER(dev);
-	SET_NETDEV_DEV(dev, &pdev->dev);
+	if (pdev != NULL)
+		SET_NETDEV_DEV(dev, &pdev->dev);
 
 	bp = dev->priv;
 
@@ -1225,7 +1228,7 @@
 	
 	/* Register IRQ - support shared interrupts by passing device ptr */
 
-	ret = request_irq(dev->irq, (void *)dfx_interrupt, SA_SHIRQ, dev->name, dev);
+	ret = request_irq(dev->irq, dfx_interrupt, SA_SHIRQ, dev->name, dev);
 	if (ret) {
 		printk(KERN_ERR "%s: Requested IRQ %d is busy\n", dev->name, dev->irq);
 		return ret;
@@ -1680,13 +1683,13 @@
  * =================
  * = dfx_interrupt =
  * =================
- *   
+ *
  * Overview:
  *   Interrupt processing routine
- *  
+ *
  * Returns:
- *   None
- *       
+ *   Whether a valid interrupt was seen.
+ *
  * Arguments:
  *   irq	- interrupt vector
  *   dev_id	- pointer to device information
@@ -1699,7 +1702,8 @@
  *   structure context.
  *
  * Return Codes:
- *   None
+ *   IRQ_HANDLED - an IRQ was handled.
+ *   IRQ_NONE    - no IRQ was handled.
  *
  * Assumptions:
  *   The interrupt acknowledgement at the hardware level (eg. ACKing the PIC
@@ -1712,60 +1716,70 @@
  *   Interrupts are disabled, then reenabled at the adapter.
  */
 
-static void dfx_interrupt(int irq, void *dev_id, struct pt_regs	*regs)
-	{
+static irqreturn_t dfx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
 	struct net_device	*dev = dev_id;
 	DFX_board_t		*bp;	/* private board structure pointer */
-	u8				tmp;	/* used for disabling/enabling ints */
 
 	/* Get board pointer only if device structure is valid */
 
 	bp = dev->priv;
 
-	spin_lock(&bp->lock);
-	
 	/* See if we're already servicing an interrupt */
 
 	/* Service adapter interrupts */
 
-	if (bp->bus_type == DFX_BUS_TYPE_PCI)
-		{
-		/* Disable PDQ-PFI interrupts at PFI */
+	if (bp->bus_type == DFX_BUS_TYPE_PCI) {
+		u32 status;
 
-		dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, PFI_MODE_M_DMA_ENB);
+		dfx_port_read_long(bp, PFI_K_REG_STATUS, &status);
+		if (!(status & PFI_STATUS_M_PDQ_INT))
+			return IRQ_NONE;
+
+		spin_lock(&bp->lock);
+
+		/* Disable PDQ-PFI interrupts at PFI */
+		dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL,
+				    PFI_MODE_M_DMA_ENB);
 
 		/* Call interrupt service routine for this adapter */
-
 		dfx_int_common(dev);
 
 		/* Clear PDQ interrupt status bit and reenable interrupts */
-
-		dfx_port_write_long(bp, PFI_K_REG_STATUS, PFI_STATUS_M_PDQ_INT);
+		dfx_port_write_long(bp, PFI_K_REG_STATUS,
+				    PFI_STATUS_M_PDQ_INT);
 		dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL,
-					(PFI_MODE_M_PDQ_INT_ENB + PFI_MODE_M_DMA_ENB));
-		}
-	else
-		{
-		/* Disable interrupts at the ESIC */
+				    (PFI_MODE_M_PDQ_INT_ENB |
+				     PFI_MODE_M_DMA_ENB));
 
-		dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &tmp);
-		tmp &= ~PI_CONFIG_STAT_0_M_INT_ENB;
-		dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, tmp);
+		spin_unlock(&bp->lock);
+	} else {
+		u8 status;
+
+		dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &status);
+		if (!(status & PI_CONFIG_STAT_0_M_PEND))
+			return IRQ_NONE;
+
+		spin_lock(&bp->lock);
+
+		/* Disable interrupts at the ESIC */
+		status &= ~PI_CONFIG_STAT_0_M_INT_ENB;
+		dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, status);
 
 		/* Call interrupt service routine for this adapter */
-
 		dfx_int_common(dev);
 
 		/* Reenable interrupts at the ESIC */
+		dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &status);
+		status |= PI_CONFIG_STAT_0_M_INT_ENB;
+		dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, status);
 
-		dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &tmp);
-		tmp |= PI_CONFIG_STAT_0_M_INT_ENB;
-		dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, tmp);
-		}
-
-	spin_unlock(&bp->lock);
+		spin_unlock(&bp->lock);
 	}
 
+	return IRQ_HANDLED;
+}
+
 
 /*
  * =====================
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
new file mode 100644
index 0000000..5fddc0f
--- /dev/null
+++ b/drivers/net/dm9000.c
@@ -0,0 +1,1219 @@
+/*
+ *   dm9000.c: Version 1.2 03/18/2003
+ *
+ *         A Davicom DM9000 ISA NIC fast Ethernet driver for Linux.
+ * 	Copyright (C) 1997  Sten Wang
+ *
+ * 	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.
+ *
+ *   (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
+ *
+ * V0.11	06/20/2001	REG_0A bit3=1, default enable BP with DA match
+ * 	06/22/2001 	Support DM9801 progrmming
+ * 	 	 	E3: R25 = ((R24 + NF) & 0x00ff) | 0xf000
+ * 		 	E4: R25 = ((R24 + NF) & 0x00ff) | 0xc200
+ * 		     		R17 = (R17 & 0xfff0) | NF + 3
+ * 		 	E5: R25 = ((R24 + NF - 3) & 0x00ff) | 0xc200
+ * 		     		R17 = (R17 & 0xfff0) | NF
+ *
+ * v1.00               	modify by simon 2001.9.5
+ *                         change for kernel 2.4.x
+ *
+ * v1.1   11/09/2001      	fix force mode bug
+ *
+ * v1.2   03/18/2003       Weilun Huang <weilun_huang@davicom.com.tw>:
+ * 			Fixed phy reset.
+ * 			Added tx/rx 32 bit mode.
+ * 			Cleaned up for kernel merge.
+ *
+ *        03/03/2004    Sascha Hauer <s.hauer@pengutronix.de>
+ *                      Port to 2.6 kernel
+ *
+ *	  24-Sep-2004   Ben Dooks <ben@simtec.co.uk>
+ *			Cleanup of code to remove ifdefs
+ *			Allowed platform device data to influence access width
+ *			Reformatting areas of code
+ *
+ *        17-Mar-2005   Sascha Hauer <s.hauer@pengutronix.de>
+ *                      * removed 2.4 style module parameters
+ *                      * removed removed unused stat counter and fixed
+ *                        net_device_stats
+ *                      * introduced tx_timeout function
+ *                      * reworked locking
+ */
+
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/version.h>
+#include <linux/spinlock.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/dm9000.h>
+#include <linux/delay.h>
+
+#include <asm/delay.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include "dm9000.h"
+
+/* Board/System/Debug information/definition ---------------- */
+
+#define DM9000_PHY		0x40	/* PHY address 0x01 */
+
+#define TRUE			1
+#define FALSE			0
+
+#define CARDNAME "dm9000"
+#define PFX CARDNAME ": "
+
+#define DM9000_TIMER_WUT  jiffies+(HZ*2)	/* timer wakeup time : 2 second */
+
+#define DM9000_DEBUG 0
+
+#if DM9000_DEBUG > 2
+#define PRINTK3(args...)  printk(CARDNAME ": " args)
+#else
+#define PRINTK3(args...)  do { } while(0)
+#endif
+
+#if DM9000_DEBUG > 1
+#define PRINTK2(args...)  printk(CARDNAME ": " args)
+#else
+#define PRINTK2(args...)  do { } while(0)
+#endif
+
+#if DM9000_DEBUG > 0
+#define PRINTK1(args...)  printk(CARDNAME ": " args)
+#define PRINTK(args...)   printk(CARDNAME ": " args)
+#else
+#define PRINTK1(args...)  do { } while(0)
+#define PRINTK(args...)   printk(KERN_DEBUG args)
+#endif
+
+/*
+ * Transmit timeout, default 5 seconds.
+ */
+static int watchdog = 5000;
+module_param(watchdog, int, 0400);
+MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
+
+/* Structure/enum declaration ------------------------------- */
+typedef struct board_info {
+
+	void __iomem *io_addr;	/* Register I/O base address */
+	void __iomem *io_data;	/* Data I/O address */
+	u16 irq;		/* IRQ */
+
+	u16 tx_pkt_cnt;
+	u16 queue_pkt_len;
+	u16 queue_start_addr;
+	u16 dbug_cnt;
+	u8 io_mode;		/* 0:word, 2:byte */
+	u8 phy_addr;
+
+	void (*inblk)(void __iomem *port, void *data, int length);
+	void (*outblk)(void __iomem *port, void *data, int length);
+	void (*dumpblk)(void __iomem *port, int length);
+
+	struct resource	*addr_res;   /* resources found */
+	struct resource *data_res;
+	struct resource	*addr_req;   /* resources requested */
+	struct resource *data_req;
+	struct resource *irq_res;
+
+	struct timer_list timer;
+	struct net_device_stats stats;
+	unsigned char srom[128];
+	spinlock_t lock;
+
+	struct mii_if_info mii;
+	u32 msg_enable;
+} board_info_t;
+
+/* function declaration ------------------------------------- */
+static int dm9000_probe(struct device *);
+static int dm9000_open(struct net_device *);
+static int dm9000_start_xmit(struct sk_buff *, struct net_device *);
+static int dm9000_stop(struct net_device *);
+static int dm9000_do_ioctl(struct net_device *, struct ifreq *, int);
+
+
+static void dm9000_timer(unsigned long);
+static void dm9000_init_dm9000(struct net_device *);
+
+static struct net_device_stats *dm9000_get_stats(struct net_device *);
+
+static irqreturn_t dm9000_interrupt(int, void *, struct pt_regs *);
+
+static int dm9000_phy_read(struct net_device *dev, int phyaddr_unsused, int reg);
+static void dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg,
+			   int value);
+static u16 read_srom_word(board_info_t *, int);
+static void dm9000_rx(struct net_device *);
+static void dm9000_hash_table(struct net_device *);
+
+//#define DM9000_PROGRAM_EEPROM
+#ifdef DM9000_PROGRAM_EEPROM
+static void program_eeprom(board_info_t * db);
+#endif
+/* DM9000 network board routine ---------------------------- */
+
+static void
+dm9000_reset(board_info_t * db)
+{
+	PRINTK1("dm9000x: resetting\n");
+	/* RESET device */
+	writeb(DM9000_NCR, db->io_addr);
+	udelay(200);
+	writeb(NCR_RST, db->io_data);
+	udelay(200);
+}
+
+/*
+ *   Read a byte from I/O port
+ */
+static u8
+ior(board_info_t * db, int reg)
+{
+	writeb(reg, db->io_addr);
+	return readb(db->io_data);
+}
+
+/*
+ *   Write a byte to I/O port
+ */
+
+static void
+iow(board_info_t * db, int reg, int value)
+{
+	writeb(reg, db->io_addr);
+	writeb(value, db->io_data);
+}
+
+/* routines for sending block to chip */
+
+static void dm9000_outblk_8bit(void __iomem *reg, void *data, int count)
+{
+	writesb(reg, data, count);
+}
+
+static void dm9000_outblk_16bit(void __iomem *reg, void *data, int count)
+{
+	writesw(reg, data, (count+1) >> 1);
+}
+
+static void dm9000_outblk_32bit(void __iomem *reg, void *data, int count)
+{
+	writesl(reg, data, (count+3) >> 2);
+}
+
+/* input block from chip to memory */
+
+static void dm9000_inblk_8bit(void __iomem *reg, void *data, int count)
+{
+	readsb(reg, data, count);
+}
+
+
+static void dm9000_inblk_16bit(void __iomem *reg, void *data, int count)
+{
+	readsw(reg, data, (count+1) >> 1);
+}
+
+static void dm9000_inblk_32bit(void __iomem *reg, void *data, int count)
+{
+	readsl(reg, data, (count+3) >> 2);
+}
+
+/* dump block from chip to null */
+
+static void dm9000_dumpblk_8bit(void __iomem *reg, int count)
+{
+	int i;
+	int tmp;
+
+	for (i = 0; i < count; i++)
+		tmp = readb(reg);
+}
+
+static void dm9000_dumpblk_16bit(void __iomem *reg, int count)
+{
+	int i;
+	int tmp;
+
+	count = (count + 1) >> 1;
+
+	for (i = 0; i < count; i++)
+		tmp = readw(reg);
+}
+
+static void dm9000_dumpblk_32bit(void __iomem *reg, int count)
+{
+	int i;
+	int tmp;
+
+	count = (count + 3) >> 2;
+
+	for (i = 0; i < count; i++)
+		tmp = readl(reg);
+}
+
+/* dm9000_set_io
+ *
+ * select the specified set of io routines to use with the
+ * device
+ */
+
+static void dm9000_set_io(struct board_info *db, int byte_width)
+{
+	/* use the size of the data resource to work out what IO
+	 * routines we want to use
+	 */
+
+	switch (byte_width) {
+	case 1:
+		db->dumpblk = dm9000_dumpblk_8bit;
+		db->outblk  = dm9000_outblk_8bit;
+		db->inblk   = dm9000_inblk_8bit;
+		break;
+
+	case 2:
+		db->dumpblk = dm9000_dumpblk_16bit;
+		db->outblk  = dm9000_outblk_16bit;
+		db->inblk   = dm9000_inblk_16bit;
+		break;
+
+	case 3:
+		printk(KERN_ERR PFX ": 3 byte IO, falling back to 16bit\n");
+		db->dumpblk = dm9000_dumpblk_16bit;
+		db->outblk  = dm9000_outblk_16bit;
+		db->inblk   = dm9000_inblk_16bit;
+		break;
+
+	case 4:
+	default:
+		db->dumpblk = dm9000_dumpblk_32bit;
+		db->outblk  = dm9000_outblk_32bit;
+		db->inblk   = dm9000_inblk_32bit;
+		break;
+	}
+}
+
+
+/* Our watchdog timed out. Called by the networking layer */
+static void dm9000_timeout(struct net_device *dev)
+{
+	board_info_t *db = (board_info_t *) dev->priv;
+	u8 reg_save;
+	unsigned long flags;
+
+	/* Save previous register address */
+	reg_save = readb(db->io_addr);
+	spin_lock_irqsave(db->lock,flags);
+
+	netif_stop_queue(dev);
+	dm9000_reset(db);
+	dm9000_init_dm9000(dev);
+	/* We can accept TX packets again */
+	dev->trans_start = jiffies;
+	netif_wake_queue(dev);
+
+	/* Restore previous register address */
+	writeb(reg_save, db->io_addr);
+	spin_unlock_irqrestore(db->lock,flags);
+}
+
+
+/* dm9000_release_board
+ *
+ * release a board, and any mapped resources
+ */
+
+static void
+dm9000_release_board(struct platform_device *pdev, struct board_info *db)
+{
+	if (db->data_res == NULL) {
+		if (db->addr_res != NULL)
+			release_mem_region((unsigned long)db->io_addr, 4);
+		return;
+	}
+
+	/* unmap our resources */
+
+	iounmap(db->io_addr);
+	iounmap(db->io_data);
+
+	/* release the resources */
+
+	if (db->data_req != NULL) {
+		release_resource(db->data_req);
+		kfree(db->data_req);
+	}
+
+	if (db->addr_res != NULL) {
+		release_resource(db->addr_res);
+		kfree(db->addr_req);
+	}
+}
+
+#define res_size(_r) (((_r)->end - (_r)->start) + 1)
+
+/*
+ * Search DM9000 board, allocate space and register it
+ */
+static int
+dm9000_probe(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct dm9000_plat_data *pdata = pdev->dev.platform_data;
+	struct board_info *db;	/* Point a board information structure */
+	struct net_device *ndev;
+	unsigned long base;
+	int ret = 0;
+	int iosize;
+	int i;
+	u32 id_val;
+
+	printk(KERN_INFO "%s Ethernet Driver\n", CARDNAME);
+
+	/* Init network device */
+	ndev = alloc_etherdev(sizeof (struct board_info));
+	if (!ndev) {
+		printk("%s: could not allocate device.\n", CARDNAME);
+		return -ENOMEM;
+	}
+
+	SET_MODULE_OWNER(ndev);
+	SET_NETDEV_DEV(ndev, dev);
+
+	PRINTK2("dm9000_probe()");
+
+	/* setup board info structure */
+	db = (struct board_info *) ndev->priv;
+	memset(db, 0, sizeof (*db));
+
+	if (pdev->num_resources < 2) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	switch (pdev->num_resources) {
+	case 2:
+		base = pdev->resource[0].start;
+
+		if (!request_mem_region(base, 4, ndev->name)) {
+			ret = -EBUSY;
+			goto out;
+		}
+
+		ndev->base_addr = base;
+		ndev->irq = pdev->resource[1].start;
+		db->io_addr = (void *)base;
+		db->io_data = (void *)(base + 4);
+
+		break;
+
+	case 3:
+		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) {
+			printk(KERN_ERR PFX "insufficient resources\n");
+			ret = -ENOENT;
+			goto out;
+		}
+
+		i = res_size(db->addr_res);
+		db->addr_req = request_mem_region(db->addr_res->start, i,
+						  pdev->name);
+
+		if (db->addr_req == NULL) {
+			printk(KERN_ERR PFX "cannot claim address reg area\n");
+			ret = -EIO;
+			goto out;
+		}
+
+		db->io_addr = ioremap(db->addr_res->start, i);
+
+		if (db->io_addr == NULL) {
+			printk(KERN_ERR "failed to ioremap address reg\n");
+			ret = -EINVAL;
+			goto out;
+		}
+
+		iosize = res_size(db->data_res);
+		db->data_req = request_mem_region(db->data_res->start, iosize,
+						  pdev->name);
+
+		if (db->data_req == NULL) {
+			printk(KERN_ERR PFX "cannot claim data reg area\n");
+			ret = -EIO;
+			goto out;
+		}
+
+		db->io_data = ioremap(db->data_res->start, iosize);
+
+		if (db->io_data == NULL) {
+			printk(KERN_ERR "failed to ioremap data reg\n");
+			ret = -EINVAL;
+			goto out;
+		}
+
+		/* fill in parameters for net-dev structure */
+
+		ndev->base_addr = (unsigned long)db->io_addr;
+		ndev->irq	= db->irq_res->start;
+
+		/* 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 */
+	if (pdata != NULL) {
+		/* check to see if the driver wants to over-ride the
+		 * default IO width */
+
+		if (pdata->flags & DM9000_PLATF_8BITONLY)
+			dm9000_set_io(db, 1);
+
+		if (pdata->flags & DM9000_PLATF_16BITONLY)
+			dm9000_set_io(db, 2);
+
+		if (pdata->flags & DM9000_PLATF_32BITONLY)
+			dm9000_set_io(db, 4);
+
+		/* check to see if there are any IO routine
+		 * over-rides */
+
+		if (pdata->inblk != NULL)
+			db->inblk = pdata->inblk;
+
+		if (pdata->outblk != NULL)
+			db->outblk = pdata->outblk;
+
+		if (pdata->dumpblk != NULL)
+			db->dumpblk = pdata->dumpblk;
+	}
+
+	dm9000_reset(db);
+
+	/* try two times, DM9000 sometimes gets the first read wrong */
+	for (i = 0; i < 2; i++) {
+		id_val  = ior(db, DM9000_VIDL);
+		id_val |= (u32)ior(db, DM9000_VIDH) << 8;
+		id_val |= (u32)ior(db, DM9000_PIDL) << 16;
+		id_val |= (u32)ior(db, DM9000_PIDH) << 24;
+
+		if (id_val == DM9000_ID)
+			break;
+		printk("%s: read wrong id 0x%08x\n", CARDNAME, id_val);
+	}
+
+	if (id_val != DM9000_ID) {
+		printk("%s: wrong id: 0x%08x\n", CARDNAME, id_val);
+		goto release;
+	}
+
+	/* from this point we assume that we have found a DM9000 */
+
+	/* driver system function */
+	ether_setup(ndev);
+
+	ndev->open		 = &dm9000_open;
+	ndev->hard_start_xmit    = &dm9000_start_xmit;
+	ndev->tx_timeout         = &dm9000_timeout;
+	ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
+	ndev->stop		 = &dm9000_stop;
+	ndev->get_stats		 = &dm9000_get_stats;
+	ndev->set_multicast_list = &dm9000_hash_table;
+	ndev->do_ioctl		 = &dm9000_do_ioctl;
+
+#ifdef DM9000_PROGRAM_EEPROM
+	program_eeprom(db);
+#endif
+	db->msg_enable       = NETIF_MSG_LINK;
+	db->mii.phy_id_mask  = 0x1f;
+	db->mii.reg_num_mask = 0x1f;
+	db->mii.force_media  = 0;
+	db->mii.full_duplex  = 0;
+	db->mii.dev	     = ndev;
+	db->mii.mdio_read    = dm9000_phy_read;
+	db->mii.mdio_write   = dm9000_phy_write;
+
+	/* Read SROM content */
+	for (i = 0; i < 64; i++)
+		((u16 *) db->srom)[i] = read_srom_word(db, i);
+
+	/* Set Node Address */
+	for (i = 0; i < 6; i++)
+		ndev->dev_addr[i] = db->srom[i];
+
+	if (!is_valid_ether_addr(ndev->dev_addr))
+		printk("%s: Invalid ethernet MAC address.  Please "
+		       "set using ifconfig\n", ndev->name);
+
+	dev_set_drvdata(dev, ndev);
+	ret = register_netdev(ndev);
+
+	if (ret == 0) {
+		printk("%s: dm9000 at %p,%p IRQ %d MAC: ",
+		       ndev->name,  db->io_addr, db->io_data, ndev->irq);
+		for (i = 0; i < 5; i++)
+			printk("%02x:", ndev->dev_addr[i]);
+		printk("%02x\n", ndev->dev_addr[5]);
+	}
+	return 0;
+
+ release:
+ out:
+	printk("%s: not found (%d).\n", CARDNAME, ret);
+
+	dm9000_release_board(pdev, db);
+	kfree(ndev);
+
+	return ret;
+}
+
+/*
+ *  Open the interface.
+ *  The interface is opened whenever "ifconfig" actives it.
+ */
+static int
+dm9000_open(struct net_device *dev)
+{
+	board_info_t *db = (board_info_t *) dev->priv;
+
+	PRINTK2("entering dm9000_open\n");
+
+	if (request_irq(dev->irq, &dm9000_interrupt, SA_SHIRQ, dev->name, dev))
+		return -EAGAIN;
+
+	/* Initialize DM9000 board */
+	dm9000_reset(db);
+	dm9000_init_dm9000(dev);
+
+	/* Init driver variable */
+	db->dbug_cnt = 0;
+
+	/* set and active a timer process */
+	init_timer(&db->timer);
+	db->timer.expires  = DM9000_TIMER_WUT * 2;
+	db->timer.data     = (unsigned long) dev;
+	db->timer.function = &dm9000_timer;
+	add_timer(&db->timer);
+
+	mii_check_media(&db->mii, netif_msg_link(db), 1);
+	netif_start_queue(dev);
+
+	return 0;
+}
+
+/*
+ * Initilize dm9000 board
+ */
+static void
+dm9000_init_dm9000(struct net_device *dev)
+{
+	board_info_t *db = (board_info_t *) dev->priv;
+
+	PRINTK1("entering %s\n",__FUNCTION__);
+
+	/* I/O mode */
+	db->io_mode = ior(db, DM9000_ISR) >> 6;	/* ISR bit7:6 keeps I/O mode */
+
+	/* GPIO0 on pre-activate PHY */
+	iow(db, DM9000_GPR, 0);	/* REG_1F bit0 activate phyxcer */
+	iow(db, DM9000_GPCR, GPCR_GEP_CNTL);	/* Let GPIO0 output */
+	iow(db, DM9000_GPR, 0);	/* Enable PHY */
+
+	/* Program operating register */
+	iow(db, DM9000_TCR, 0);	        /* TX Polling clear */
+	iow(db, DM9000_BPTR, 0x3f);	/* Less 3Kb, 200us */
+	iow(db, DM9000_FCR, 0xff);	/* Flow Control */
+	iow(db, DM9000_SMCR, 0);        /* Special Mode */
+	/* clear TX status */
+	iow(db, DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
+	iow(db, DM9000_ISR, ISR_CLR_STATUS); /* Clear interrupt status */
+
+	/* Set address filter table */
+	dm9000_hash_table(dev);
+
+	/* Activate DM9000 */
+	iow(db, DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
+	/* Enable TX/RX interrupt mask */
+	iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM);
+
+	/* Init Driver variable */
+	db->tx_pkt_cnt = 0;
+	db->queue_pkt_len = 0;
+	dev->trans_start = 0;
+	spin_lock_init(&db->lock);
+}
+
+/*
+ *  Hardware start transmission.
+ *  Send a packet to media from the upper layer.
+ */
+static int
+dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	board_info_t *db = (board_info_t *) dev->priv;
+
+	PRINTK3("dm9000_start_xmit\n");
+
+	if (db->tx_pkt_cnt > 1)
+		return 1;
+
+	netif_stop_queue(dev);
+
+	/* Disable all interrupts */
+	iow(db, DM9000_IMR, IMR_PAR);
+
+	/* Move data to DM9000 TX RAM */
+	writeb(DM9000_MWCMD, db->io_addr);
+
+	(db->outblk)(db->io_data, skb->data, skb->len);
+	db->stats.tx_bytes += skb->len;
+
+	/* TX control: First packet immediately send, second packet queue */
+	if (db->tx_pkt_cnt == 0) {
+
+		/* First Packet */
+		db->tx_pkt_cnt++;
+
+		/* Set TX length to DM9000 */
+		iow(db, DM9000_TXPLL, skb->len & 0xff);
+		iow(db, DM9000_TXPLH, (skb->len >> 8) & 0xff);
+
+		/* Issue TX polling command */
+		iow(db, DM9000_TCR, TCR_TXREQ);	/* Cleared after TX complete */
+
+		dev->trans_start = jiffies;	/* save the time stamp */
+
+	} else {
+		/* Second packet */
+		db->tx_pkt_cnt++;
+		db->queue_pkt_len = skb->len;
+	}
+
+	/* free this SKB */
+	dev_kfree_skb(skb);
+
+	/* Re-enable resource check */
+	if (db->tx_pkt_cnt == 1)
+		netif_wake_queue(dev);
+
+	/* Re-enable interrupt */
+	iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM);
+
+	return 0;
+}
+
+static void
+dm9000_shutdown(struct net_device *dev)
+{
+	board_info_t *db = (board_info_t *) dev->priv;
+
+	/* RESET device */
+	dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET);	/* PHY RESET */
+	iow(db, DM9000_GPR, 0x01);	/* Power-Down PHY */
+	iow(db, DM9000_IMR, IMR_PAR);	/* Disable all interrupt */
+	iow(db, DM9000_RCR, 0x00);	/* Disable RX */
+}
+
+/*
+ * Stop the interface.
+ * The interface is stopped when it is brought.
+ */
+static int
+dm9000_stop(struct net_device *ndev)
+{
+	board_info_t *db = (board_info_t *) ndev->priv;
+
+	PRINTK1("entering %s\n",__FUNCTION__);
+
+	/* deleted timer */
+	del_timer(&db->timer);
+
+	netif_stop_queue(ndev);
+	netif_carrier_off(ndev);
+
+	/* free interrupt */
+	free_irq(ndev->irq, ndev);
+
+	dm9000_shutdown(ndev);
+
+	return 0;
+}
+
+/*
+ * DM9000 interrupt handler
+ * receive the packet to upper layer, free the transmitted packet
+ */
+
+void
+dm9000_tx_done(struct net_device *dev, board_info_t * db)
+{
+	int tx_status = ior(db, DM9000_NSR);	/* Got TX status */
+
+	if (tx_status & (NSR_TX2END | NSR_TX1END)) {
+		/* One packet sent complete */
+		db->tx_pkt_cnt--;
+		db->stats.tx_packets++;
+
+		/* Queue packet check & send */
+		if (db->tx_pkt_cnt > 0) {
+			iow(db, DM9000_TXPLL, db->queue_pkt_len & 0xff);
+			iow(db, DM9000_TXPLH, (db->queue_pkt_len >> 8) & 0xff);
+			iow(db, DM9000_TCR, TCR_TXREQ);
+			dev->trans_start = jiffies;
+		}
+		netif_wake_queue(dev);
+	}
+}
+
+static irqreturn_t
+dm9000_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = dev_id;
+	board_info_t *db;
+	int int_status;
+	u8 reg_save;
+
+	PRINTK3("entering %s\n",__FUNCTION__);
+
+	if (!dev) {
+		PRINTK1("dm9000_interrupt() without DEVICE arg\n");
+		return IRQ_HANDLED;
+	}
+
+	/* A real interrupt coming */
+	db = (board_info_t *) dev->priv;
+	spin_lock(&db->lock);
+
+	/* Save previous register address */
+	reg_save = readb(db->io_addr);
+
+	/* Disable all interrupts */
+	iow(db, DM9000_IMR, IMR_PAR);
+
+	/* Got DM9000 interrupt status */
+	int_status = ior(db, DM9000_ISR);	/* Got ISR */
+	iow(db, DM9000_ISR, int_status);	/* Clear ISR status */
+
+	/* Received the coming packet */
+	if (int_status & ISR_PRS)
+		dm9000_rx(dev);
+
+	/* Trnasmit Interrupt check */
+	if (int_status & ISR_PTS)
+		dm9000_tx_done(dev, db);
+
+	/* Re-enable interrupt mask */
+	iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM);
+
+	/* Restore previous register address */
+	writeb(reg_save, db->io_addr);
+
+	spin_unlock(&db->lock);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ *  Get statistics from driver.
+ */
+static struct net_device_stats *
+dm9000_get_stats(struct net_device *dev)
+{
+	board_info_t *db = (board_info_t *) dev->priv;
+	return &db->stats;
+}
+
+/*
+ *  Process the upper socket ioctl command
+ */
+static int
+dm9000_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+	PRINTK1("entering %s\n",__FUNCTION__);
+	return 0;
+}
+
+/*
+ *  A periodic timer routine
+ *  Dynamic media sense, allocated Rx buffer...
+ */
+static void
+dm9000_timer(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *) data;
+	board_info_t *db = (board_info_t *) dev->priv;
+	u8 reg_save;
+	unsigned long flags;
+
+	PRINTK3("dm9000_timer()\n");
+
+	spin_lock_irqsave(db->lock,flags);
+	/* Save previous register address */
+	reg_save = readb(db->io_addr);
+
+	mii_check_media(&db->mii, netif_msg_link(db), 0);
+
+	/* Restore previous register address */
+	writeb(reg_save, db->io_addr);
+	spin_unlock_irqrestore(db->lock,flags);
+
+	/* Set timer again */
+	db->timer.expires = DM9000_TIMER_WUT;
+	add_timer(&db->timer);
+}
+
+struct dm9000_rxhdr {
+	u16	RxStatus;
+	u16	RxLen;
+} __attribute__((__packed__));
+
+/*
+ *  Received a packet and pass to upper layer
+ */
+static void
+dm9000_rx(struct net_device *dev)
+{
+	board_info_t *db = (board_info_t *) dev->priv;
+	struct dm9000_rxhdr rxhdr;
+	struct sk_buff *skb;
+	u8 rxbyte, *rdptr;
+	int GoodPacket;
+	int RxLen;
+
+	/* Check packet ready or not */
+	do {
+		ior(db, DM9000_MRCMDX);	/* Dummy read */
+
+		/* Get most updated data */
+		rxbyte = readb(db->io_data);
+
+		/* Status check: this byte must be 0 or 1 */
+		if (rxbyte > DM9000_PKT_RDY) {
+			printk("status check failed: %d\n", rxbyte);
+			iow(db, DM9000_RCR, 0x00);	/* Stop Device */
+			iow(db, DM9000_ISR, IMR_PAR);	/* Stop INT request */
+			return;
+		}
+
+		if (rxbyte != DM9000_PKT_RDY)
+			return;
+
+		/* A packet ready now  & Get status/length */
+		GoodPacket = TRUE;
+		writeb(DM9000_MRCMD, db->io_addr);
+
+		(db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr));
+
+		RxLen = rxhdr.RxLen;
+
+		/* Packet Status check */
+		if (RxLen < 0x40) {
+			GoodPacket = FALSE;
+			PRINTK1("Bad Packet received (runt)\n");
+		}
+
+		if (RxLen > DM9000_PKT_MAX) {
+			PRINTK1("RST: RX Len:%x\n", RxLen);
+		}
+
+		if (rxhdr.RxStatus & 0xbf00) {
+			GoodPacket = FALSE;
+			if (rxhdr.RxStatus & 0x100) {
+				PRINTK1("fifo error\n");
+				db->stats.rx_fifo_errors++;
+			}
+			if (rxhdr.RxStatus & 0x200) {
+				PRINTK1("crc error\n");
+				db->stats.rx_crc_errors++;
+			}
+			if (rxhdr.RxStatus & 0x8000) {
+				PRINTK1("length error\n");
+				db->stats.rx_length_errors++;
+			}
+		}
+
+		/* Move data from DM9000 */
+		if (GoodPacket
+		    && ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) {
+			skb->dev = dev;
+			skb_reserve(skb, 2);
+			rdptr = (u8 *) skb_put(skb, RxLen - 4);
+
+			/* Read received packet from RX SRAM */
+
+			(db->inblk)(db->io_data, rdptr, RxLen);
+			db->stats.rx_bytes += RxLen;
+
+			/* Pass to upper layer */
+			skb->protocol = eth_type_trans(skb, dev);
+			netif_rx(skb);
+			db->stats.rx_packets++;
+
+		} else {
+			/* need to dump the packet's data */
+
+			(db->dumpblk)(db->io_data, RxLen);
+		}
+	} while (rxbyte == DM9000_PKT_RDY);
+}
+
+/*
+ *  Read a word data from SROM
+ */
+static u16
+read_srom_word(board_info_t * db, int offset)
+{
+	iow(db, DM9000_EPAR, offset);
+	iow(db, DM9000_EPCR, EPCR_ERPRR);
+	mdelay(8);		/* according to the datasheet 200us should be enough,
+				   but it doesn't work */
+	iow(db, DM9000_EPCR, 0x0);
+	return (ior(db, DM9000_EPDRL) + (ior(db, DM9000_EPDRH) << 8));
+}
+
+#ifdef DM9000_PROGRAM_EEPROM
+/*
+ * Write a word data to SROM
+ */
+static void
+write_srom_word(board_info_t * db, int offset, u16 val)
+{
+	iow(db, DM9000_EPAR, offset);
+	iow(db, DM9000_EPDRH, ((val >> 8) & 0xff));
+	iow(db, DM9000_EPDRL, (val & 0xff));
+	iow(db, DM9000_EPCR, EPCR_WEP | EPCR_ERPRW);
+	mdelay(8);		/* same shit */
+	iow(db, DM9000_EPCR, 0);
+}
+
+/*
+ * Only for development:
+ * Here we write static data to the eeprom in case
+ * we don't have valid content on a new board
+ */
+static void
+program_eeprom(board_info_t * db)
+{
+	u16 eeprom[] = { 0x0c00, 0x007f, 0x1300,	/* MAC Address */
+		0x0000,		/* Autoload: accept nothing */
+		0x0a46, 0x9000,	/* Vendor / Product ID */
+		0x0000,		/* pin control */
+		0x0000,
+	};			/* Wake-up mode control */
+	int i;
+	for (i = 0; i < 8; i++)
+		write_srom_word(db, i, eeprom[i]);
+}
+#endif
+
+
+/*
+ *  Calculate the CRC valude of the Rx packet
+ *  flag = 1 : return the reverse CRC (for the received packet CRC)
+ *         0 : return the normal CRC (for Hash Table index)
+ */
+
+static unsigned long
+cal_CRC(unsigned char *Data, unsigned int Len, u8 flag)
+{
+
+       u32 crc = ether_crc_le(Len, Data);
+
+       if (flag)
+               return ~crc;
+
+       return crc;
+}
+
+/*
+ *  Set DM9000 multicast address
+ */
+static void
+dm9000_hash_table(struct net_device *dev)
+{
+	board_info_t *db = (board_info_t *) dev->priv;
+	struct dev_mc_list *mcptr = dev->mc_list;
+	int mc_cnt = dev->mc_count;
+	u32 hash_val;
+	u16 i, oft, hash_table[4];
+	unsigned long flags;
+
+	PRINTK2("dm9000_hash_table()\n");
+
+	spin_lock_irqsave(&db->lock,flags);
+
+	for (i = 0, oft = 0x10; i < 6; i++, oft++)
+		iow(db, oft, dev->dev_addr[i]);
+
+	/* Clear Hash Table */
+	for (i = 0; i < 4; i++)
+		hash_table[i] = 0x0;
+
+	/* broadcast address */
+	hash_table[3] = 0x8000;
+
+	/* the multicast address in Hash Table : 64 bits */
+	for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
+		hash_val = cal_CRC((char *) mcptr->dmi_addr, 6, 0) & 0x3f;
+		hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16);
+	}
+
+	/* Write the hash table to MAC MD table */
+	for (i = 0, oft = 0x16; i < 4; i++) {
+		iow(db, oft++, hash_table[i] & 0xff);
+		iow(db, oft++, (hash_table[i] >> 8) & 0xff);
+	}
+
+	spin_unlock_irqrestore(&db->lock,flags);
+}
+
+
+/*
+ *   Read a word from phyxcer
+ */
+static int
+dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
+{
+	board_info_t *db = (board_info_t *) dev->priv;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&db->lock,flags);
+	/* Fill the phyxcer register into REG_0C */
+	iow(db, DM9000_EPAR, DM9000_PHY | reg);
+
+	iow(db, DM9000_EPCR, 0xc);	/* Issue phyxcer read command */
+	udelay(100);		/* Wait read complete */
+	iow(db, DM9000_EPCR, 0x0);	/* Clear phyxcer read command */
+
+	/* The read data keeps on REG_0D & REG_0E */
+	ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL);
+
+	spin_unlock_irqrestore(&db->lock,flags);
+
+	return ret;
+}
+
+/*
+ *   Write a word to phyxcer
+ */
+static void
+dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value)
+{
+	board_info_t *db = (board_info_t *) dev->priv;
+	unsigned long flags;
+
+	spin_lock_irqsave(&db->lock,flags);
+
+	/* Fill the phyxcer register into REG_0C */
+	iow(db, DM9000_EPAR, DM9000_PHY | reg);
+
+	/* Fill the written data into REG_0D & REG_0E */
+	iow(db, DM9000_EPDRL, (value & 0xff));
+	iow(db, DM9000_EPDRH, ((value >> 8) & 0xff));
+
+	iow(db, DM9000_EPCR, 0xa);	/* Issue phyxcer write command */
+	udelay(500);		/* Wait write complete */
+	iow(db, DM9000_EPCR, 0x0);	/* Clear phyxcer write command */
+
+	spin_unlock_irqrestore(&db->lock,flags);
+}
+
+static int
+dm9000_drv_suspend(struct device *dev, u32 state, u32 level)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+
+	if (ndev && level == SUSPEND_DISABLE) {
+		if (netif_running(ndev)) {
+			netif_device_detach(ndev);
+			dm9000_shutdown(ndev);
+		}
+	}
+	return 0;
+}
+
+static int
+dm9000_drv_resume(struct device *dev, u32 level)
+{
+	struct net_device *ndev = dev_get_drvdata(dev);
+	board_info_t *db = (board_info_t *) ndev->priv;
+
+	if (ndev && level == RESUME_ENABLE) {
+
+		if (netif_running(ndev)) {
+			dm9000_reset(db);
+			dm9000_init_dm9000(ndev);
+
+			netif_device_attach(ndev);
+		}
+	}
+	return 0;
+}
+
+static int
+dm9000_drv_remove(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct net_device *ndev = dev_get_drvdata(dev);
+
+	dev_set_drvdata(dev, NULL);
+
+	unregister_netdev(ndev);
+	dm9000_release_board(pdev, (board_info_t *) ndev->priv);
+	kfree(ndev);		/* free device structure */
+
+	PRINTK1("clean_module() exit\n");
+
+	return 0;
+}
+
+static struct device_driver dm9000_driver = {
+	.name    = "dm9000",
+	.bus     = &platform_bus_type,
+	.probe   = dm9000_probe,
+	.remove  = dm9000_drv_remove,
+	.suspend = dm9000_drv_suspend,
+	.resume  = dm9000_drv_resume,
+};
+
+static int __init
+dm9000_init(void)
+{
+	return driver_register(&dm9000_driver);	/* search board and register */
+}
+
+static void __exit
+dm9000_cleanup(void)
+{
+	driver_unregister(&dm9000_driver);
+}
+
+module_init(dm9000_init);
+module_exit(dm9000_cleanup);
+
+MODULE_AUTHOR("Sascha Hauer, Ben Dooks");
+MODULE_DESCRIPTION("Davicom DM9000 network driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/dm9000.h b/drivers/net/dm9000.h
new file mode 100644
index 0000000..82cad36
--- /dev/null
+++ b/drivers/net/dm9000.h
@@ -0,0 +1,135 @@
+/*
+ * dm9000 Ethernet
+ */
+
+#ifndef _DM9000X_H_
+#define _DM9000X_H_
+
+#define DM9000_ID		0x90000A46
+
+/* although the registers are 16 bit, they are 32-bit aligned.
+ */
+
+#define DM9000_NCR             0x00
+#define DM9000_NSR             0x01
+#define DM9000_TCR             0x02
+#define DM9000_TSR1            0x03
+#define DM9000_TSR2            0x04
+#define DM9000_RCR             0x05
+#define DM9000_RSR             0x06
+#define DM9000_ROCR            0x07
+#define DM9000_BPTR            0x08
+#define DM9000_FCTR            0x09
+#define DM9000_FCR             0x0A
+#define DM9000_EPCR            0x0B
+#define DM9000_EPAR            0x0C
+#define DM9000_EPDRL           0x0D
+#define DM9000_EPDRH           0x0E
+#define DM9000_WCR             0x0F
+
+#define DM9000_PAR             0x10
+#define DM9000_MAR             0x16
+
+#define DM9000_GPCR	       0x1e
+#define DM9000_GPR             0x1f
+#define DM9000_TRPAL           0x22
+#define DM9000_TRPAH           0x23
+#define DM9000_RWPAL           0x24
+#define DM9000_RWPAH           0x25
+
+#define DM9000_VIDL            0x28
+#define DM9000_VIDH            0x29
+#define DM9000_PIDL            0x2A
+#define DM9000_PIDH            0x2B
+
+#define DM9000_CHIPR           0x2C
+#define DM9000_SMCR            0x2F
+
+#define DM9000_MRCMDX          0xF0
+#define DM9000_MRCMD           0xF2
+#define DM9000_MRRL            0xF4
+#define DM9000_MRRH            0xF5
+#define DM9000_MWCMDX          0xF6
+#define DM9000_MWCMD           0xF8
+#define DM9000_MWRL            0xFA
+#define DM9000_MWRH            0xFB
+#define DM9000_TXPLL           0xFC
+#define DM9000_TXPLH           0xFD
+#define DM9000_ISR             0xFE
+#define DM9000_IMR             0xFF
+
+#define NCR_EXT_PHY         (1<<7)
+#define NCR_WAKEEN          (1<<6)
+#define NCR_FCOL            (1<<4)
+#define NCR_FDX             (1<<3)
+#define NCR_LBK             (3<<1)
+#define NCR_RST	            (1<<0)
+
+#define NSR_SPEED           (1<<7)
+#define NSR_LINKST          (1<<6)
+#define NSR_WAKEST          (1<<5)
+#define NSR_TX2END          (1<<3)
+#define NSR_TX1END          (1<<2)
+#define NSR_RXOV            (1<<1)
+
+#define TCR_TJDIS           (1<<6)
+#define TCR_EXCECM          (1<<5)
+#define TCR_PAD_DIS2        (1<<4)
+#define TCR_CRC_DIS2        (1<<3)
+#define TCR_PAD_DIS1        (1<<2)
+#define TCR_CRC_DIS1        (1<<1)
+#define TCR_TXREQ           (1<<0)
+
+#define TSR_TJTO            (1<<7)
+#define TSR_LC              (1<<6)
+#define TSR_NC              (1<<5)
+#define TSR_LCOL            (1<<4)
+#define TSR_COL             (1<<3)
+#define TSR_EC              (1<<2)
+
+#define RCR_WTDIS           (1<<6)
+#define RCR_DIS_LONG        (1<<5)
+#define RCR_DIS_CRC         (1<<4)
+#define RCR_ALL	            (1<<3)
+#define RCR_RUNT            (1<<2)
+#define RCR_PRMSC           (1<<1)
+#define RCR_RXEN            (1<<0)
+
+#define RSR_RF              (1<<7)
+#define RSR_MF              (1<<6)
+#define RSR_LCS             (1<<5)
+#define RSR_RWTO            (1<<4)
+#define RSR_PLE             (1<<3)
+#define RSR_AE              (1<<2)
+#define RSR_CE              (1<<1)
+#define RSR_FOE             (1<<0)
+
+#define FCTR_HWOT(ot)	(( ot & 0xf ) << 4 )
+#define FCTR_LWOT(ot)	( ot & 0xf )
+
+#define IMR_PAR             (1<<7)
+#define IMR_ROOM            (1<<3)
+#define IMR_ROM             (1<<2)
+#define IMR_PTM             (1<<1)
+#define IMR_PRM             (1<<0)
+
+#define ISR_ROOS            (1<<3)
+#define ISR_ROS             (1<<2)
+#define ISR_PTS             (1<<1)
+#define ISR_PRS             (1<<0)
+#define ISR_CLR_STATUS      (ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS)
+
+#define EPCR_REEP           (1<<5)
+#define EPCR_WEP            (1<<4)
+#define EPCR_EPOS           (1<<3)
+#define EPCR_ERPRR          (1<<2)
+#define EPCR_ERPRW          (1<<1)
+#define EPCR_ERRE           (1<<0)
+
+#define GPCR_GEP_CNTL       (1<<0)
+
+#define DM9000_PKT_RDY		0x01	/* Packet ready to receive */
+#define DM9000_PKT_MAX		1536	/* Received packet max size */
+
+#endif /* _DM9000X_H_ */
+
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 4a47df5..cfaa6b2 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -143,6 +143,7 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/mii.h>
@@ -2286,7 +2287,7 @@
 		goto err_out_disable_pdev;
 	}
 
-	if((err = pci_set_dma_mask(pdev, 0xFFFFFFFFULL))) {
+	if((err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
 		DPRINTK(PROBE, ERR, "No usable DMA configuration, aborting.\n");
 		goto err_out_free_res;
 	}
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 325495b..137226d 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -2307,6 +2307,7 @@
 	tso = e1000_tso(adapter, skb);
 	if (tso < 0) {
 		dev_kfree_skb_any(skb);
+		spin_unlock_irqrestore(&adapter->tx_lock, flags);
 		return NETDEV_TX_OK;
 	}
 
diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c
index 51c9fa2..f5a4dd7 100644
--- a/drivers/net/e2100.c
+++ b/drivers/net/e2100.c
@@ -162,12 +162,7 @@
 	err = do_e2100_probe(dev);
 	if (err)
 		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
 	return dev;
-out1:
-	cleanup_card(dev);
 out:
 	free_netdev(dev);
 	return ERR_PTR(err);
@@ -286,6 +281,9 @@
 #endif
 	NS8390_init(dev, 0);
 
+	retval = register_netdev(dev);
+	if (retval)
+		goto out;
 	return 0;
 out:
 	release_region(ioaddr, E21_IO_EXTENT);
@@ -453,11 +451,8 @@
 		dev->mem_start = mem[this_dev];
 		dev->mem_end = xcvr[this_dev];	/* low 4bits = xcvr sel. */
 		if (do_e2100_probe(dev) == 0) {
-			if (register_netdev(dev) == 0) {
-				dev_e21[found++] = dev;
-				continue;
-			}
-			cleanup_card(dev);
+			dev_e21[found++] = dev;
+			continue;
 		}
 		free_netdev(dev);
 		printk(KERN_WARNING "e2100.c: No E2100 card found (i/o = 0x%x).\n", io[this_dev]);
diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c
index cd24756..dcb3028 100644
--- a/drivers/net/eepro.c
+++ b/drivers/net/eepro.c
@@ -600,12 +600,7 @@
 	err = do_eepro_probe(dev);
 	if (err)
 		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
 	return dev;
-out1:
-	release_region(dev->base_addr, EEPRO_IO_EXTENT);
 out:
 	free_netdev(dev);
 	return ERR_PTR(err);
@@ -758,6 +753,7 @@
 	int i;
 	struct eepro_local *lp;
 	int ioaddr = dev->base_addr;
+	int err;
 
 	/* Grab the region so we can find another board if autoIRQ fails. */
 	if (!request_region(ioaddr, EEPRO_IO_EXTENT, DRV_NAME)) { 
@@ -873,10 +869,16 @@
 
 	/* reset 82595 */
 	eepro_reset(ioaddr);
+
+	err = register_netdev(dev);
+	if (err)
+		goto err;
 	return 0;
 exit:
+	err = -ENODEV;
+err:
  	release_region(dev->base_addr, EEPRO_IO_EXTENT);
- 	return -ENODEV;
+ 	return err;
 }
 
 /* Open/initialize the board.  This is called (in the current kernel)
@@ -1834,11 +1836,8 @@
 		dev->irq = irq[i];
 
 		if (do_eepro_probe(dev) == 0) {
-			if (register_netdev(dev) == 0) {
-				dev_eepro[n_eepro++] = dev;
-				continue;
-			}
-			release_region(dev->base_addr, EEPRO_IO_EXTENT);
+			dev_eepro[n_eepro++] = dev;
+			continue;
 		}
 		free_netdev(dev);
 		break;
diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c
index fc8e794..82bd356 100644
--- a/drivers/net/eexpress.c
+++ b/drivers/net/eexpress.c
@@ -436,11 +436,8 @@
 	netdev_boot_setup_check(dev);
 
 	err = do_express_probe(dev);
-	if (!err) {
-		err = register_netdev(dev);
-		if (!err)
-			return dev;
-	}
+	if (!err)
+		return dev;
 	free_netdev(dev);
 	return ERR_PTR(err);
 }
@@ -1205,7 +1202,8 @@
 	dev->set_multicast_list = &eexp_set_multicast;
 	dev->tx_timeout = eexp_timeout;
 	dev->watchdog_timeo = 2*HZ;
-	return 0;
+
+	return register_netdev(dev);
 }
 
 /*
@@ -1716,7 +1714,7 @@
 				break;
 			printk(KERN_NOTICE "eexpress.c: Module autoprobe not recommended, give io=xx.\n");
 		}
-		if (do_express_probe(dev) == 0 && register_netdev(dev) == 0) {
+		if (do_express_probe(dev) == 0) {
 			dev_eexp[this_dev] = dev;
 			found++;
 			continue;
diff --git a/drivers/net/es3210.c b/drivers/net/es3210.c
index f1e8150..50f8e23 100644
--- a/drivers/net/es3210.c
+++ b/drivers/net/es3210.c
@@ -177,12 +177,7 @@
 	err = do_es_probe(dev);
 	if (err)
 		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
 	return dev;
-out1:
-	cleanup_card(dev);
 out:
 	free_netdev(dev);
 	return ERR_PTR(err);
@@ -310,6 +305,10 @@
 	dev->poll_controller = ei_poll;
 #endif
 	NS8390_init(dev, 0);
+
+	retval = register_netdev(dev);
+	if (retval)
+		goto out1;
 	return 0;
 out1:
 	free_irq(dev->irq, dev);
@@ -445,11 +444,8 @@
 		dev->base_addr = io[this_dev];
 		dev->mem_start = mem[this_dev];
 		if (do_es_probe(dev) == 0) {
-			if (register_netdev(dev) == 0) {
-				dev_es3210[found++] = dev;
-				continue;
-			}
-			cleanup_card(dev);
+			dev_es3210[found++] = dev;
+			continue;
 		}
 		free_netdev(dev);
 		printk(KERN_WARNING "es3210.c: No es3210 card found (i/o = 0x%x).\n", io[this_dev]);
diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c
index ccae6ba..f32a6b3 100644
--- a/drivers/net/eth16i.c
+++ b/drivers/net/eth16i.c
@@ -473,13 +473,7 @@
 	err = do_eth16i_probe(dev);
 	if (err)
 		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
 	return dev;
-out1:
-	free_irq(dev->irq, dev);
-	release_region(dev->base_addr, ETH16I_IO_EXTENT);
 out:
 	free_netdev(dev);
 	return ERR_PTR(err);
@@ -569,7 +563,13 @@
 	dev->tx_timeout 	= eth16i_timeout;
 	dev->watchdog_timeo	= TX_TIMEOUT;
 	spin_lock_init(&lp->lock);
+
+	retval = register_netdev(dev);
+	if (retval)
+		goto out1;
 	return 0;
+out1:
+	free_irq(dev->irq, dev);
 out:
 	release_region(ioaddr, ETH16I_IO_EXTENT);
 	return retval;
@@ -1462,12 +1462,8 @@
 		}
 
 		if (do_eth16i_probe(dev) == 0) {
-			if (register_netdev(dev) == 0) {
-				dev_eth16i[found++] = dev;
-				continue;
-			}
-			free_irq(dev->irq, dev);
-			release_region(dev->base_addr, ETH16I_IO_EXTENT);
+			dev_eth16i[found++] = dev;
+			continue;
 		}
 		printk(KERN_WARNING "eth16i.c No Eth16i card found (i/o = 0x%x).\n",
 		       io[this_dev]);
diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c
index dcf969b..b987f94 100644
--- a/drivers/net/ewrk3.c
+++ b/drivers/net/ewrk3.c
@@ -1308,15 +1308,9 @@
 	if (ioaddr < 0x1000)
 		goto out;
 
-	if (ioaddr == 0) {	/* Autoprobing */
-		iobase = EISA_SLOT_INC;		/* Get the first slot address */
-		i = 1;
-		maxSlots = MAX_EISA_SLOTS;
-	} else {		/* Probe a specific location */
-		iobase = ioaddr;
-		i = (ioaddr >> 12);
-		maxSlots = i + 1;
-	}
+	iobase = ioaddr;
+	i = (ioaddr >> 12);
+	maxSlots = i + 1;
 
 	for (i = 1; (i < maxSlots) && (dev != NULL); i++, iobase += EISA_SLOT_INC) {
 		if (EISA_signature(name, EISA_ID) == 0) {
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index d05e9dd..9e0303f 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -1423,8 +1423,7 @@
 		if (cur->skbuff) {
 			pci_unmap_single(np->pci_dev, cur->buffer,
 				cur->skbuff->len, PCI_DMA_TODEVICE);
-			dev_kfree_skb(cur->skbuff);
-			/* or dev_kfree_skb_irq(cur->skbuff); ? */
+			dev_kfree_skb_any(cur->skbuff);
 			cur->skbuff = NULL;
 		}
 		cur->status = 0;
diff --git a/drivers/net/fmv18x.c b/drivers/net/fmv18x.c
deleted file mode 100644
index 04c7485..0000000
--- a/drivers/net/fmv18x.c
+++ /dev/null
@@ -1,689 +0,0 @@
-/* fmv18x.c: A network device driver for the Fujitsu FMV-181/182/183/184.
-
-	Original: at1700.c (1993-94 by Donald Becker).
-		Copyright 1993 United States Government as represented by the
-		Director, National Security Agency.
-		The author may be reached as becker@scyld.com, or C/O
-			Scyld Computing Corporation
-			410 Severn Ave., Suite 210
-			Annapolis MD 21403
-
-	Modified by Yutaka TAMIYA (tamy@flab.fujitsu.co.jp)
-		Copyright 1994 Fujitsu Laboratories Ltd.
-	Special thanks to:
-		Masayoshi UTAKA (utaka@ace.yk.fujitsu.co.jp)
-			for testing this driver.
-		H. NEGISHI (agy, negishi@sun45.psd.cs.fujitsu.co.jp)
-			for suggestion of some program modification.
-		Masahiro SEKIGUCHI <seki@sysrap.cs.fujitsu.co.jp>
-			for suggestion of some program modification.
-		Kazutoshi MORIOKA (morioka@aurora.oaks.cs.fujitsu.co.jp)
-			for testing this driver.
-
-	This software may be used and distributed according to the terms
-	of the GNU General Public License, incorporated herein by reference.
-
-	This is a device driver for the Fujitsu FMV-181/182/183/184, which
-	is a straight-forward Fujitsu MB86965 implementation.
-
-  Sources:
-    at1700.c
-    The Fujitsu MB86965 datasheet.
-    The Fujitsu FMV-181/182 user's guide
-*/
-
-static const char version[] =
-	"fmv18x.c:v2.2.0 09/24/98  Yutaka TAMIYA (tamy@flab.fujitsu.co.jp)\n";
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/in.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/errno.h>
-#include <linux/spinlock.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/delay.h>
-#include <linux/bitops.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-
-#define DRV_NAME "fmv18x"
-
-static unsigned fmv18x_probe_list[] __initdata = {
-	0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0
-};
-
-/* use 0 for production, 1 for verification, >2 for debug */
-#ifndef NET_DEBUG
-#define NET_DEBUG 1
-#endif
-static unsigned int net_debug = NET_DEBUG;
-
-typedef unsigned char uchar;
-
-/* Information that need to be kept for each board. */
-struct net_local {
-	struct net_device_stats stats;
-	long open_time;				/* Useless example local info. */
-	uint tx_started:1;			/* Number of packet on the Tx queue. */
-	uint tx_queue_ready:1;		/* Tx queue is ready to be sent. */
-	uint rx_started:1;			/* Packets are Rxing. */
-	uchar tx_queue;				/* Number of packet on the Tx queue. */
-	ushort tx_queue_len;		/* Current length of the Tx queue. */
-	spinlock_t lock;
-};
-
-
-/* Offsets from the base address. */
-#define STATUS			0
-#define TX_STATUS		0
-#define RX_STATUS		1
-#define TX_INTR			2		/* Bit-mapped interrupt enable registers. */
-#define RX_INTR			3
-#define TX_MODE			4
-#define RX_MODE			5
-#define CONFIG_0		6		/* Misc. configuration settings. */
-#define CONFIG_1		7
-/* Run-time register bank 2 definitions. */
-#define DATAPORT		8		/* Word-wide DMA or programmed-I/O dataport. */
-#define TX_START		10
-#define COL16CNTL		11		/* Controll Reg for 16 collisions */
-#define MODE13			13
-/* Fujitsu FMV-18x Card Configuration */
-#define	FJ_STATUS0		0x10
-#define	FJ_STATUS1		0x11
-#define	FJ_CONFIG0		0x12
-#define	FJ_CONFIG1		0x13
-#define	FJ_MACADDR		0x14	/* 0x14 - 0x19 */
-#define	FJ_BUFCNTL		0x1A
-#define	FJ_BUFDATA		0x1C
-#define FMV18X_IO_EXTENT	32
-
-/* Index to functions, as function prototypes. */
-
-static int fmv18x_probe1(struct net_device *dev, short ioaddr);
-static int net_open(struct net_device *dev);
-static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void net_rx(struct net_device *dev);
-static void net_timeout(struct net_device *dev);
-static int net_close(struct net_device *dev);
-static struct net_device_stats *net_get_stats(struct net_device *dev);
-static void set_multicast_list(struct net_device *dev);
-
-
-/* Check for a network adaptor of this type, and return '0' iff one exists.
-   If dev->base_addr == 0, probe all likely locations.
-   If dev->base_addr == 1, always return failure.
-   If dev->base_addr == 2, allocate space for the device and return success
-   (detachable devices only).
-   */
-
-static int io = 0x220;
-static int irq;
-
-struct net_device * __init fmv18x_probe(int unit)
-{
-	struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
-	unsigned *port;
-	int err = 0;
-
-	if (!dev)
-		return ERR_PTR(-ENODEV);
-
-	if (unit >= 0) {
-		sprintf(dev->name, "eth%d", unit);
-		netdev_boot_setup_check(dev);
-		io = dev->base_addr;
-		irq = dev->irq;
-	}
-
-	SET_MODULE_OWNER(dev);
-
-	if (io > 0x1ff) {	/* Check a single specified location. */
-		err = fmv18x_probe1(dev, io);
-	} else if (io != 0) {	/* Don't probe at all. */
-		err = -ENXIO;
-	} else {
-		for (port = fmv18x_probe_list; *port; port++)
-			if (fmv18x_probe1(dev, *port) == 0)
-				break;
-		if (!*port)
-			err = -ENODEV;
-	}
-	if (err)
-		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
-	return dev;
-out1:
-	free_irq(dev->irq, dev);
-	release_region(dev->base_addr, FMV18X_IO_EXTENT);
-out:
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-
-/* The Fujitsu datasheet suggests that the NIC be probed for by checking its
-   "signature", the default bit pattern after a reset.  This *doesn't* work --
-   there is no way to reset the bus interface without a complete power-cycle!
-
-   It turns out that ATI came to the same conclusion I did: the only thing
-   that can be done is checking a few bits and then diving right into MAC
-   address check. */
-
-static int __init fmv18x_probe1(struct net_device *dev, short ioaddr)
-{
-	char irqmap[4] = {3, 7, 10, 15};
-	char irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15};
-	unsigned int i, retval;
-	struct net_local *lp;
-
-	/* Resetting the chip doesn't reset the ISA interface, so don't bother.
-	   That means we have to be careful with the register values we probe for.
-	   */
-
-	if (!request_region(ioaddr, FMV18X_IO_EXTENT, DRV_NAME))
-		return -EBUSY;
-
-	dev->irq = irq;
-	dev->base_addr = ioaddr;
-
-	/* Check I/O address configuration and Fujitsu vendor code */
-	if (inb(ioaddr+FJ_MACADDR  ) != 0x00
-	||  inb(ioaddr+FJ_MACADDR+1) != 0x00
-	||  inb(ioaddr+FJ_MACADDR+2) != 0x0e) {
-		retval = -ENODEV;
-		goto out;
-	}
-
-	/* Check PnP mode for FMV-183/184/183A/184A. */
-	/* This PnP routine is very poor. IO and IRQ should be known. */
-	if (inb(ioaddr + FJ_STATUS1) & 0x20) {
-		for (i = 0; i < 8; i++) {
-			if (dev->irq == irqmap_pnp[i])
-				break;
-		}
-		if (i == 8) {
-			retval = -ENODEV;
-			goto out;
-		}
-	} else {
-		if (fmv18x_probe_list[inb(ioaddr + FJ_CONFIG0) & 0x07] != ioaddr)
-			return -ENODEV;
-		dev->irq = irqmap[(inb(ioaddr + FJ_CONFIG0)>>6) & 0x03];
-	}
-
-	/* Snarf the interrupt vector now. */
-	retval = request_irq(dev->irq, &net_interrupt, 0, DRV_NAME, dev);
-	if (retval) {
-		printk ("FMV-18x found at %#3x, but it's unusable due to a conflict on"
-				"IRQ %d.\n", ioaddr, dev->irq);
-		goto out;
-	}
-
-	printk("%s: FMV-18x found at %#3x, IRQ %d, address ", dev->name,
-		   ioaddr, dev->irq);
-
-	for(i = 0; i < 6; i++) {
-		unsigned char val = inb(ioaddr + FJ_MACADDR + i);
-		printk("%02x", val);
-		dev->dev_addr[i] = val;
-	}
-
-	/* "FJ_STATUS0" 12 bit 0x0400 means use regular 100 ohm 10baseT signals,
-	   rather than 150 ohm shielded twisted pair compensation.
-	   0x0000 == auto-sense the interface
-	   0x0800 == use TP interface
-	   0x1800 == use coax interface
-	   */
-	{
-		const char *porttype[] = {"auto-sense", "10baseT", "auto-sense", "10base2/5"};
-		ushort setup_value = inb(ioaddr + FJ_STATUS0);
-
-		switch( setup_value & 0x07 ){
-		case 0x01 /* 10base5 */:
-		case 0x02 /* 10base2 */: dev->if_port = 0x18; break;
-		case 0x04 /* 10baseT */: dev->if_port = 0x08; break;
-		default /* auto-sense*/: dev->if_port = 0x00; break;
-		}
-		printk(" %s interface.\n", porttype[(dev->if_port>>3) & 3]);
-	}
-
-	/* Initialize LAN Controller and LAN Card */
-	outb(0xda, ioaddr + CONFIG_0);	 /* Initialize LAN Controller */
-	outb(0x00, ioaddr + CONFIG_1);	 /* Stand by mode */
-	outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */
-	outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure (TAMIYA) */
-
-	/* wait for a while */
-	udelay(200);
-
-	/* Set the station address in bank zero. */
-	outb(0x00, ioaddr + CONFIG_1);
-	for (i = 0; i < 6; i++)
-		outb(dev->dev_addr[i], ioaddr + 8 + i);
-
-	/* Switch to bank 1 and set the multicast table to accept none. */
-	outb(0x04, ioaddr + CONFIG_1);
-	for (i = 0; i < 8; i++)
-		outb(0x00, ioaddr + 8 + i);
-
-	/* Switch to bank 2 and lock our I/O address. */
-	outb(0x08, ioaddr + CONFIG_1);
-	outb(dev->if_port, ioaddr + MODE13);
-	outb(0x00, ioaddr + COL16CNTL);
-
-	if (net_debug)
-		printk(version);
-
-	/* Initialize the device structure. */
-	dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
-	if (!dev->priv) {
-		retval = -ENOMEM;
-		goto out_irq;
-	}
-	memset(dev->priv, 0, sizeof(struct net_local));
-	lp = dev->priv;
-	spin_lock_init(&lp->lock);
-
-	dev->open		= net_open;
-	dev->stop		= net_close;
-	dev->hard_start_xmit	= net_send_packet;
-	dev->tx_timeout		= net_timeout;
-	dev->watchdog_timeo	= HZ/10;
-	dev->get_stats		= net_get_stats;
-	dev->set_multicast_list = set_multicast_list;
-	return 0;
-
-out_irq:
-	free_irq(dev->irq, dev);
-out:
-	release_region(ioaddr, FMV18X_IO_EXTENT);
-	return retval;
-}
-
-
-static int net_open(struct net_device *dev)
-{
-	struct net_local *lp = dev->priv;
-	int ioaddr = dev->base_addr;
-
-	/* Set the configuration register 0 to 32K 100ns. byte-wide memory,
-	   16 bit bus access, and two 4K Tx, enable the Rx and Tx. */
-	outb(0x5a, ioaddr + CONFIG_0);
-
-	/* Powerup and switch to register bank 2 for the run-time registers. */
-	outb(0xe8, ioaddr + CONFIG_1);
-
-	lp->tx_started = 0;
-	lp->tx_queue_ready = 1;
-	lp->rx_started = 0;
-	lp->tx_queue = 0;
-	lp->tx_queue_len = 0;
-
-	/* Clear Tx and Rx Status */
-	outb(0xff, ioaddr + TX_STATUS);
-	outb(0xff, ioaddr + RX_STATUS);
-	lp->open_time = jiffies;
-
-	netif_start_queue(dev);
-	
-	/* Enable the IRQ of the LAN Card */
-	outb(0x80, ioaddr + FJ_CONFIG1);
-
-	/* Enable both Tx and Rx interrupts */
-	outw(0x8182, ioaddr+TX_INTR);
-
-	return 0;
-}
-
-static void net_timeout(struct net_device *dev)
-{
-	struct net_local *lp = dev->priv;
-	int ioaddr = dev->base_addr;
-	unsigned long flags;
-	
-	
-	printk(KERN_WARNING "%s: transmit timed out with status %04x, %s?\n", dev->name,
-		   htons(inw(ioaddr + TX_STATUS)),
-		   inb(ioaddr + TX_STATUS) & 0x80
-		   ? "IRQ conflict" : "network cable problem");
-	printk(KERN_WARNING "%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n",
-		   dev->name, htons(inw(ioaddr + 0)),
-		   htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)),
-		   htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)),
-		   htons(inw(ioaddr +10)), htons(inw(ioaddr +12)),
-		   htons(inw(ioaddr +14)));
-	printk(KERN_WARNING "eth card: %04x %04x\n",
-		htons(inw(ioaddr+FJ_STATUS0)),
-		htons(inw(ioaddr+FJ_CONFIG0)));
-	lp->stats.tx_errors++;
-	/* ToDo: We should try to restart the adaptor... */
-	spin_lock_irqsave(&lp->lock, flags);
-
-	/* Initialize LAN Controller and LAN Card */
-	outb(0xda, ioaddr + CONFIG_0);   /* Initialize LAN Controller */
-	outb(0x00, ioaddr + CONFIG_1);   /* Stand by mode */
-	outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */
-	outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure */
-	net_open(dev);
-	spin_unlock_irqrestore(&lp->lock, flags);
-
-	netif_wake_queue(dev);
-}
-
-static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
-{
-	struct net_local *lp = dev->priv;
-	int ioaddr = dev->base_addr;
-	short length = skb->len;
-	unsigned char *buf;
-	unsigned long flags;
-
-	/* Block a transmit from overlapping.  */
-	
-	if (length > ETH_FRAME_LEN) {
-		if (net_debug)
-			printk("%s: Attempting to send a large packet (%d bytes).\n",
-				dev->name, length);
-		return 1;
-	}
-	
-	if (length < ETH_ZLEN) {
-		skb = skb_padto(skb, ETH_ZLEN);
-		if (skb == NULL)
-			return 0;
-		length = ETH_ZLEN;
-	}
-	buf = skb->data;
-	
-	if (net_debug > 4)
-		printk("%s: Transmitting a packet of length %lu.\n", dev->name,
-			   (unsigned long)skb->len);
-	/* We may not start transmitting unless we finish transferring
-	   a packet into the Tx queue. During executing the following
-	   codes we possibly catch a Tx interrupt. Thus we flag off
-	   tx_queue_ready, so that we prevent the interrupt routine
-	   (net_interrupt) to start transmitting. */
-	spin_lock_irqsave(&lp->lock, flags);
-	lp->tx_queue_ready = 0;
-	{
-		outw(length, ioaddr + DATAPORT);
-		outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
-		lp->tx_queue++;
-		lp->tx_queue_len += length + 2;
-	}
-	lp->tx_queue_ready = 1;
-	spin_unlock_irqrestore(&lp->lock, flags);
-
-	if (lp->tx_started == 0) {
-		/* If the Tx is idle, always trigger a transmit. */
-		outb(0x80 | lp->tx_queue, ioaddr + TX_START);
-		lp->tx_queue = 0;
-		lp->tx_queue_len = 0;
-		dev->trans_start = jiffies;
-		lp->tx_started = 1;
-	} else if (lp->tx_queue_len >= 4096 - 1502) /* No room for a packet */
-		netif_stop_queue(dev);
-
-	dev_kfree_skb(skb);
-	return 0;
-}
-
-/* The typical workload of the driver:
-   Handle the network interface interrupts. */
-static irqreturn_t
-net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct net_device *dev = dev_id;
-	struct net_local *lp;
-	int ioaddr, status;
-
-	ioaddr = dev->base_addr;
-	lp = dev->priv;
-	status = inw(ioaddr + TX_STATUS);
-	outw(status, ioaddr + TX_STATUS);
-
-	if (net_debug > 4)
-		printk("%s: Interrupt with status %04x.\n", dev->name, status);
-	if (lp->rx_started == 0 &&
-		(status & 0xff00 || (inb(ioaddr + RX_MODE) & 0x40) == 0)) {
-		/* Got a packet(s).
-		   We cannot execute net_rx more than once at the same time for
-		   the same device. During executing net_rx, we possibly catch a
-		   Tx interrupt. Thus we flag on rx_started, so that we prevent
-		   the interrupt routine (net_interrupt) to dive into net_rx
-		   again. */
-		lp->rx_started = 1;
-		outb(0x00, ioaddr + RX_INTR);	/* Disable RX intr. */
-		net_rx(dev);
-		outb(0x81, ioaddr + RX_INTR);	/* Enable  RX intr. */
-		lp->rx_started = 0;
-	}
-	if (status & 0x00ff) {
-		if (status & 0x02) {
-			/* More than 16 collisions occurred */
-			if (net_debug > 4)
-				printk("%s: 16 Collision occur during Txing.\n", dev->name);
-			/* Cancel sending a packet. */
-			outb(0x03, ioaddr + COL16CNTL);
-			lp->stats.collisions++;
-		}
-		if (status & 0x82) {
-			spin_lock(&lp->lock);
-			lp->stats.tx_packets++;
-			if (lp->tx_queue && lp->tx_queue_ready) {
-				outb(0x80 | lp->tx_queue, ioaddr + TX_START);
-				lp->tx_queue = 0;
-				lp->tx_queue_len = 0;
-				dev->trans_start = jiffies;
-				netif_wake_queue(dev);	/* Inform upper layers. */
-			} else {
-				lp->tx_started = 0;
-				netif_wake_queue(dev);	/* Inform upper layers. */
-			}
-			spin_unlock(&lp->lock);
-		}
-	}
-	return IRQ_RETVAL(status);
-}
-
-/* We have a good packet(s), get it/them out of the buffers. */
-static void net_rx(struct net_device *dev)
-{
-	struct net_local *lp = dev->priv;
-	int ioaddr = dev->base_addr;
-	int boguscount = 5;
-
-	while ((inb(ioaddr + RX_MODE) & 0x40) == 0) {
-		/* Clear PKT_RDY bit: by agy 19940922 */
-		/* outb(0x80, ioaddr + RX_STATUS); */
-		ushort status = inw(ioaddr + DATAPORT);
-
-		if (net_debug > 4)
-			printk("%s: Rxing packet mode %02x status %04x.\n",
-				   dev->name, inb(ioaddr + RX_MODE), status);
-#ifndef final_version
-		if (status == 0) {
-			outb(0x05, ioaddr + 14);
-			break;
-		}
-#endif
-
-		if ((status & 0xF0) != 0x20) {	/* There was an error. */
-			lp->stats.rx_errors++;
-			if (status & 0x08) lp->stats.rx_length_errors++;
-			if (status & 0x04) lp->stats.rx_frame_errors++;
-			if (status & 0x02) lp->stats.rx_crc_errors++;
-			if (status & 0x01) lp->stats.rx_over_errors++;
-		} else {
-			ushort pkt_len = inw(ioaddr + DATAPORT);
-			/* Malloc up new buffer. */
-			struct sk_buff *skb;
-
-			if (pkt_len > 1550) {
-				printk("%s: The FMV-18x claimed a very large packet, size %d.\n",
-					   dev->name, pkt_len);
-				outb(0x05, ioaddr + 14);
-				lp->stats.rx_errors++;
-				break;
-			}
-			skb = dev_alloc_skb(pkt_len+3);
-			if (skb == NULL) {
-				printk("%s: Memory squeeze, dropping packet (len %d).\n",
-					   dev->name, pkt_len);
-				outb(0x05, ioaddr + 14);
-				lp->stats.rx_dropped++;
-				break;
-			}
-			skb->dev = dev;
-			skb_reserve(skb,2);
-
-			insw(ioaddr + DATAPORT, skb_put(skb,pkt_len), (pkt_len + 1) >> 1);
-
-			if (net_debug > 5) {
-				int i;
-				printk("%s: Rxed packet of length %d: ", dev->name, pkt_len);
-				for (i = 0; i < 14; i++)
-					printk(" %02x", skb->data[i]);
-				printk(".\n");
-			}
-
-			skb->protocol=eth_type_trans(skb, dev);
-			netif_rx(skb);
-			dev->last_rx = jiffies;
-			lp->stats.rx_packets++;
-			lp->stats.rx_bytes += pkt_len;
-		}
-		if (--boguscount <= 0)
-			break;
-	}
-
-	/* If any worth-while packets have been received, dev_rint()
-	   has done a mark_bh(NET_BH) for us and will work on them
-	   when we get to the bottom-half routine. */
-	{
-		int i;
-		for (i = 0; i < 20; i++) {
-			if ((inb(ioaddr + RX_MODE) & 0x40) == 0x40)
-				break;
-			(void)inw(ioaddr + DATAPORT);				/* dummy status read */
-			outb(0x05, ioaddr + 14);
-		}
-
-		if (net_debug > 5 && i > 0)
-			printk("%s: Exint Rx packet with mode %02x after %d ticks.\n",
-				   dev->name, inb(ioaddr + RX_MODE), i);
-	}
-
-	return;
-}
-
-/* The inverse routine to net_open(). */
-static int net_close(struct net_device *dev)
-{
-	int ioaddr = dev->base_addr;
-
-	((struct net_local *)dev->priv)->open_time = 0;
-
-	netif_stop_queue(dev);
-	
-	/* Set configuration register 0 to disable Tx and Rx. */
-	outb(0xda, ioaddr + CONFIG_0);
-
-	/* Update the statistics -- ToDo. */
-
-	/* Power-down the chip.  Green, green, green! */
-	outb(0x00, ioaddr + CONFIG_1);
-
-	/* Set the ethernet adaptor disable IRQ */
-	outb(0x00, ioaddr + FJ_CONFIG1);
-
-	return 0;
-}
-
-/* Get the current statistics.	This may be called with the card open or
-   closed. */
-static struct net_device_stats *net_get_stats(struct net_device *dev)
-{
-	struct net_local *lp = dev->priv;
-	return &lp->stats;
-}
-
-/* Set or clear the multicast filter for this adaptor.
-   num_addrs == -1	Promiscuous mode, receive all packets
-   num_addrs == 0	Normal mode, clear multicast list
-   num_addrs > 0	Multicast mode, receive normal and MC packets, and do
-			best-effort filtering.
- */
- 
-static void set_multicast_list(struct net_device *dev)
-{
-	short ioaddr = dev->base_addr;
-	if (dev->mc_count || dev->flags&(IFF_PROMISC|IFF_ALLMULTI))
-	{
-		/*
-		 *	We must make the kernel realise we had to move
-		 *	into promisc mode or we start all out war on
-		 *	the cable. - AC
-		 */
-		dev->flags|=IFF_PROMISC;
-
-		outb(3, ioaddr + RX_MODE);	/* Enable promiscuous mode */
-	}
-	else
-		outb(2, ioaddr + RX_MODE);	/* Disable promiscuous, use normal mode */
-}
-
-#ifdef MODULE
-static struct net_device *dev_fmv18x;
-
-MODULE_PARM(io, "i");
-MODULE_PARM(irq, "i");
-MODULE_PARM(net_debug, "i");
-MODULE_PARM_DESC(io, "FMV-18X I/O address");
-MODULE_PARM_DESC(irq, "FMV-18X IRQ number");
-MODULE_PARM_DESC(net_debug, "FMV-18X debug level (0-1,5-6)");
-MODULE_LICENSE("GPL");
-
-int init_module(void)
-{
-	if (io == 0)
-		printk("fmv18x: You should not use auto-probing with insmod!\n");
-	dev_fmv18x = fmv18x_probe(-1);
-	if (IS_ERR(dev_fmv18x))
-		return PTR_ERR(dev_fmv18x);
-	return 0;
-}
-
-void
-cleanup_module(void)
-{
-	unregister_netdev(dev_fmv18x);
-	free_irq(dev_fmv18x->irq, dev_fmv18x);
-	release_region(dev_fmv18x->base_addr, FMV18X_IO_EXTENT);
-	free_netdev(dev_fmv18x);
-}
-#endif /* MODULE */
-
-/*
- * Local variables:
- *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c fmv18x.c"
- *  version-control: t
- *  kept-new-versions: 5
- *  tab-width: 4
- *  c-indent-level: 4
- * End:
- */
diff --git a/drivers/net/gianfar_phy.c b/drivers/net/gianfar_phy.c
index 02b16ab..7c965f2 100644
--- a/drivers/net/gianfar_phy.c
+++ b/drivers/net/gianfar_phy.c
@@ -572,7 +572,7 @@
 static struct phy_info phy_info_marvell = {
 	.phy_id		= 0x01410c00,
 	.phy_id_mask	= 0xffffff00,
-	.name		= "Marvell 88E1101",
+	.name		= "Marvell 88E1101/88E1111",
 	.features	= MII_GBIT_FEATURES,
 	.config_aneg	= &marvell_config_aneg,
 	.read_status	= &marvell_read_status,
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 8945491..e44f8e9 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -848,7 +848,7 @@
 {
 	int ret;
 
-	if ((ret = tty_register_ldisc(N_6PACK, NULL)))
+	if ((ret = tty_unregister_ldisc(N_6PACK)))
 		printk(msg_unregfail, ret);
 }
 
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index 6279051..3035422 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -934,7 +934,7 @@
 	kfree(ax25_ctrls);
 	ax25_ctrls = NULL;
 
-	if ((i = tty_register_ldisc(N_AX25, NULL)))
+	if ((i = tty_unregister_ldisc(N_AX25)))
 		printk(KERN_ERR "mkiss: can't unregister line discipline (err = %d)\n", i);
 }
 
diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
index 4834314..0abf5dd 100644
--- a/drivers/net/hp-plus.c
+++ b/drivers/net/hp-plus.c
@@ -159,12 +159,7 @@
 	err = do_hpp_probe(dev);
 	if (err)
 		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
 	return dev;
-out1:
-	cleanup_card(dev);
 out:
 	free_netdev(dev);
 	return ERR_PTR(err);
@@ -271,6 +266,9 @@
 	/* Leave the 8390 and HP chip reset. */
 	outw(inw(ioaddr + HPP_OPTION) & ~EnableIRQ, ioaddr + HPP_OPTION);
 
+	retval = register_netdev(dev);
+	if (retval)
+		goto out;
 	return 0;
 out:
 	release_region(ioaddr, HP_IO_EXTENT);
@@ -463,11 +461,8 @@
 		dev->irq = irq[this_dev];
 		dev->base_addr = io[this_dev];
 		if (do_hpp_probe(dev) == 0) {
-			if (register_netdev(dev) == 0) {
-				dev_hpp[found++] = dev;
-				continue;
-			}
-			cleanup_card(dev);
+			dev_hpp[found++] = dev;
+			continue;
 		}
 		free_netdev(dev);
 		printk(KERN_WARNING "hp-plus.c: No HP-Plus card found (i/o = 0x%x).\n", io[this_dev]);
diff --git a/drivers/net/hp.c b/drivers/net/hp.c
index 0268886..59cf841 100644
--- a/drivers/net/hp.c
+++ b/drivers/net/hp.c
@@ -123,12 +123,7 @@
 	err = do_hp_probe(dev);
 	if (err)
 		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
 	return dev;
-out1:
-	cleanup_card(dev);
 out:
 	free_netdev(dev);
 	return ERR_PTR(err);
@@ -227,7 +222,12 @@
 	ei_status.block_output = &hp_block_output;
 	hp_init_card(dev);
 
+	retval = register_netdev(dev);
+	if (retval)
+		goto out1;
 	return 0;
+out1:
+	free_irq(dev->irq, dev);
 out:
 	release_region(ioaddr, HP_IO_EXTENT);
 	return retval;
@@ -432,11 +432,8 @@
 		dev->irq = irq[this_dev];
 		dev->base_addr = io[this_dev];
 		if (do_hp_probe(dev) == 0) {
-			if (register_netdev(dev) == 0) {
-				dev_hp[found++] = dev;
-				continue;
-			}
-			cleanup_card(dev);
+			dev_hp[found++] = dev;
+			continue;
 		}
 		free_netdev(dev);
 		printk(KERN_WARNING "hp.c: No HP card found (i/o = 0x%x).\n", io[this_dev]);
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index b3a898c..cf0ac6f 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -106,6 +106,7 @@
 #include <linux/interrupt.h>
 #include <linux/eisa.h>
 #include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include <linux/spinlock.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -417,12 +418,7 @@
 	if (err)
 		goto out;
 
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
 	return dev;
- out1:
-	release_region(dev->base_addr, HP100_REGION_SIZE);
  out:
 	free_netdev(dev);
 	return ERR_PTR(err);
@@ -562,7 +558,7 @@
 			 * Also, we can have EISA Busmaster cards (not tested),
 			 * so beware !!! - Jean II */
 			if((bus == HP100_BUS_PCI) &&
-			   (pci_set_dma_mask(pci_dev, 0xffffffff))) {
+			   (pci_set_dma_mask(pci_dev, DMA_32BIT_MASK))) {
 				/* Gracefully fallback to shared memory */
 				goto busmasterfail;
 			}
@@ -776,11 +772,22 @@
 		printk("Warning! Link down.\n");
 	}
 
+	err = register_netdev(dev);
+	if (err)
+		goto out3;
+
 	return 0;
+out3:
+	if (local_mode == 1)
+		pci_free_consistent(lp->pci_dev, MAX_RINGSIZE + 0x0f, 
+				    lp->page_vaddr_algn, 
+				    virt_to_whatever(dev, lp->page_vaddr_algn));
+	if (mem_ptr_virt)
+		iounmap(mem_ptr_virt);
 out2:
 	release_region(ioaddr, HP100_REGION_SIZE);
 out1:
-	return -ENODEV;
+	return err;
 }
 
 /* This procedure puts the card into a stable init state */
@@ -2875,18 +2882,12 @@
 	if (err)
 		goto out1;
 
-	err = register_netdev(dev);
-	if (err)
-		goto out2;
-	
 #ifdef HP100_DEBUG
 	printk("hp100: %s: EISA adapter found at 0x%x\n", dev->name, 
 	       dev->base_addr);
 #endif
 	gendev->driver_data = dev;
 	return 0;
- out2:
-	release_region(dev->base_addr, HP100_REGION_SIZE);
  out1:
 	free_netdev(dev);
 	return err;
@@ -2951,17 +2952,12 @@
 	err = hp100_probe1(dev, ioaddr, HP100_BUS_PCI, pdev);
 	if (err) 
 		goto out1;
-	err = register_netdev(dev);
-	if (err)
-		goto out2;
 	
 #ifdef HP100_DEBUG
 	printk("hp100: %s: PCI adapter found at 0x%x\n", dev->name, ioaddr);
 #endif
 	pci_set_drvdata(pdev, dev);
 	return 0;
- out2:
-	release_region(dev->base_addr, HP100_REGION_SIZE);
  out1:
 	free_netdev(dev);
  out0:
@@ -3032,15 +3028,9 @@
 		SET_MODULE_OWNER(dev);
 
 		err = hp100_isa_probe(dev, hp100_port[i]);
-		if (!err) {
-			err = register_netdev(dev);
-			if (!err) 
-				hp100_devlist[cards++] = dev;
-			else
-				release_region(dev->base_addr, HP100_REGION_SIZE);
-		}
-
-		if (err)
+		if (!err)
+			hp100_devlist[cards++] = dev;
+		else
 			free_netdev(dev);
 	}
 
diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig
index 1c553d7..ca59140 100644
--- a/drivers/net/irda/Kconfig
+++ b/drivers/net/irda/Kconfig
@@ -389,7 +389,7 @@
 	help
 	  Say Y here if you want to build support for the VIA VT8231
 	  and VIA VT1211 IrDA controllers, found on the motherboards using
-	  those those VIA chipsets. To use this controller, you will need
+	  those VIA chipsets. To use this controller, you will need
 	  to plug a specific 5 pins FIR IrDA dongle in the specific
 	  motherboard connector. The driver provides support for SIR, MIR
 	  and FIR (4Mbps) speeds.
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
index 7d23aa3..b8d1123 100644
--- a/drivers/net/irda/irtty-sir.c
+++ b/drivers/net/irda/irtty-sir.c
@@ -626,7 +626,7 @@
 {
 	int err;
 
-	if ((err = tty_register_ldisc(N_IRDA, NULL))) {
+	if ((err = tty_unregister_ldisc(N_IRDA))) {
 		IRDA_ERROR("%s(), can't unregister line discipline (err = %d)\n",
 			   __FUNCTION__, err);
 	}
diff --git a/drivers/net/irda/sir_kthread.c b/drivers/net/irda/sir_kthread.c
index 18cea10..c650543 100644
--- a/drivers/net/irda/sir_kthread.c
+++ b/drivers/net/irda/sir_kthread.c
@@ -135,8 +135,7 @@
 		remove_wait_queue(&irda_rq_queue.kick, &wait);
 
 		/* make swsusp happy with our thread */
-		if (current->flags & PF_FREEZE)
-			refrigerator(PF_FREEZE);
+		try_to_freeze();
 
 		run_irda_queue();
 	}
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index 66f488c..15f2073 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -763,7 +763,7 @@
 	{
 #ifdef CONFIG_PM
 		/* if suspending, then power off and wait */
-		if (unlikely(current->flags & PF_FREEZE)) {
+		if (unlikely(freezing(current))) {
 			if (stir->receiving)
 				receive_stop(stir);
 			else
@@ -771,7 +771,7 @@
 
 			write_reg(stir, REG_CTRL1, CTRL1_TXPWD|CTRL1_RXPWD);
 
-			refrigerator(PF_FREEZE);
+			refrigerator();
 
 			if (change_speed(stir, stir->speed))
 				break;
diff --git a/drivers/net/isa-skeleton.c b/drivers/net/isa-skeleton.c
index 50bebb5..88ae8a0 100644
--- a/drivers/net/isa-skeleton.c
+++ b/drivers/net/isa-skeleton.c
@@ -176,12 +176,7 @@
 	err = do_netcard_probe(dev);
 	if (err)
 		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
 	return dev;
-out1:
-	cleanup_card(dev);
 out:
 	free_netdev(dev);
 	return ERR_PTR(err);
@@ -316,7 +311,15 @@
 
         dev->tx_timeout		= &net_tx_timeout;
         dev->watchdog_timeo	= MY_TX_TIMEOUT; 
+
+	err = register_netdev(dev);
+	if (err)
+		goto out2;
 	return 0;
+out2:
+#ifdef jumpered_dma
+	free_dma(dev->dma);
+#endif
 out1:
 #ifdef jumpered_interrupts
 	free_irq(dev->irq, dev);
@@ -691,11 +694,8 @@
 	dev->dma       = dma;
 	dev->mem_start = mem;
 	if (do_netcard_probe(dev) == 0) {
-		if (register_netdev(dev) == 0)
-			this_device = dev;
-			return 0;
-		}
-		cleanup_card(dev);
+		this_device = dev;
+		return 0;
 	}
 	free_netdev(dev);
 	return -ENXIO;
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index 13ed8dc..55af32e 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -802,13 +802,14 @@
 
 	spin_lock_irqsave(&port->pending_gate, flags);
 
+	if (!port->pending_lpmask) {
+		spin_unlock_irqrestore(&port->pending_gate, flags);
+		return;
+	}
+
 	printk(KERN_WARNING "%s: Tx timeout!  Resetting lp connections: %08x\n",
 	       dev->name, port->pending_lpmask);
 
-	/* If we've timed out the queue must be stopped, which should
-	 * only ever happen when there is a pending packet. */
-	WARN_ON(! port->pending_lpmask);
-
 	for (i = 0; i < HVMAXARCHITECTEDLPS; i++) {
 		struct veth_lpar_connection *cnx = veth_cnx[i];
 
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index 35f6a7c..097b90c 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -47,7 +47,9 @@
 #else
 #define DRIVERNAPI "-NAPI"
 #endif
-char ixgb_driver_version[] = "1.0.95-k2"DRIVERNAPI;
+
+#define DRV_VERSION "1.0.95-k2"DRIVERNAPI
+char ixgb_driver_version[] = DRV_VERSION;
 char ixgb_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
 
 /* ixgb_pci_tbl - PCI Device ID Table
@@ -140,6 +142,7 @@
 MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
 MODULE_DESCRIPTION("Intel(R) PRO/10GbE Network Driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
 
 /* some defines for controlling descriptor fetches in h/w */
 #define RXDCTL_PTHRESH_DEFAULT 128	/* chip considers prefech below this */
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index dec557f..ca90f0d 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -356,11 +356,8 @@
 		dev->base_addr = io[this_dev];
 		dev->dma = dma[this_dev];
 		if (do_lance_probe(dev) == 0) {
-			if (register_netdev(dev) == 0) {
-				dev_lance[found++] = dev;
-				continue;
-			}
-			cleanup_card(dev);
+			dev_lance[found++] = dev;
+			continue;
 		}
 		free_netdev(dev);
 		break;
@@ -448,12 +445,7 @@
 	err = do_lance_probe(dev);
 	if (err)
 		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
 	return dev;
-out1:
-	cleanup_card(dev);
 out:
 	free_netdev(dev);
 	return ERR_PTR(err);
@@ -724,6 +716,9 @@
 	dev->tx_timeout = lance_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
 
+	err = register_netdev(dev);
+	if (err)
+		goto out_dma;
 	return 0;
 out_dma:
 	if (dev->dma != 4)
diff --git a/drivers/net/lne390.c b/drivers/net/lne390.c
index 179a97c..27f0d8a 100644
--- a/drivers/net/lne390.c
+++ b/drivers/net/lne390.c
@@ -167,12 +167,7 @@
 	err = do_lne390_probe(dev);
 	if (err)
 		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
 	return dev;
-out1:
-	cleanup_card(dev);
 out:
 	free_netdev(dev);
 	return ERR_PTR(err);
@@ -296,7 +291,14 @@
 	dev->poll_controller = ei_poll;
 #endif
 	NS8390_init(dev, 0);
+
+	ret = register_netdev(dev);
+	if (ret)
+		goto unmap;
 	return 0;
+unmap:
+	if (ei_status.reg0)
+		iounmap((void *)dev->mem_start);
 cleanup:
 	free_irq(dev->irq, dev);
 	return ret;
@@ -426,11 +428,8 @@
 		dev->base_addr = io[this_dev];
 		dev->mem_start = mem[this_dev];
 		if (do_lne390_probe(dev) == 0) {
-			if (register_netdev(dev) == 0) {
-				dev_lne[found++] = dev;
-				continue;
-			}
-			cleanup_card(dev);
+			dev_lne[found++] = dev;
+			continue;
 		}
 		free_netdev(dev);
 		printk(KERN_WARNING "lne390.c: No LNE390 card found (i/o = 0x%x).\n", io[this_dev]);
diff --git a/drivers/net/myri_code.h b/drivers/net/myri_code.h
index 851eba8..e9c6e56 100644
--- a/drivers/net/myri_code.h
+++ b/drivers/net/myri_code.h
@@ -4775,1288 +4775,7 @@
 /* This is the LANai data */ 
 
 static unsigned int lanai4_data_off = 0x94F0; /* half-word offset */
-static unsigned char lanai4_data[20472] __initdata = {
-0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x01, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 
-0x00,0x00, 0x00,0x00, 0x00,0x00, } ;
+static unsigned char lanai4_data[20472] __initdata;
 
 
 #ifdef SYMBOL_DEFINES_COMPILED
diff --git a/drivers/net/ne-h8300.c b/drivers/net/ne-h8300.c
index 84e291e..8f40368 100644
--- a/drivers/net/ne-h8300.c
+++ b/drivers/net/ne-h8300.c
@@ -180,12 +180,7 @@
 	err = do_ne_probe(dev);
 	if (err)
 		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
 	return dev;
-out1:
-	cleanup_card(dev);
 out:
 	free_netdev(dev);
 	return ERR_PTR(err);
@@ -325,8 +320,13 @@
 	dev->poll_controller = ei_poll;
 #endif
 	NS8390_init(dev, 0);
-	return 0;
 
+	ret = register_netdev(dev);
+	if (ret)
+		goto out_irq;
+	return 0;
+out_irq:
+	free_irq(dev->irq, dev);
 err_out:
 	release_region(ioaddr, NE_IO_EXTENT);
 	return ret;
@@ -633,11 +633,8 @@
 		err = init_reg_offset(dev, dev->base_addr);
 		if (!err) {
 			if (do_ne_probe(dev) == 0) {
-				if (register_netdev(dev) == 0) {
-					dev_ne[found++] = dev;
-					continue;
-				}
-				cleanup_card(dev);
+				dev_ne[found++] = dev;
+				continue;
 			}
 		}
 		free_netdev(dev);
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index 4964339..6c57096 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -229,12 +229,7 @@
 	err = do_ne_probe(dev);
 	if (err)
 		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
 	return dev;
-out1:
-	cleanup_card(dev);
 out:
 	free_netdev(dev);
 	return ERR_PTR(err);
@@ -534,8 +529,14 @@
 	dev->poll_controller = ei_poll;
 #endif
 	NS8390_init(dev, 0);
+
+	ret = register_netdev(dev);
+	if (ret)
+		goto out_irq;
 	return 0;
 
+out_irq:
+	free_irq(dev->irq, dev);
 err_out:
 	release_region(ioaddr, NE_IO_EXTENT);
 	return ret;
@@ -826,11 +827,8 @@
 		dev->mem_end = bad[this_dev];
 		dev->base_addr = io[this_dev];
 		if (do_ne_probe(dev) == 0) {
-			if (register_netdev(dev) == 0) {
-				dev_ne[found++] = dev;
-				continue;
-			}
-			cleanup_card(dev);
+			dev_ne[found++] = dev;
+			continue;
 		}
 		free_netdev(dev);
 		if (found)
diff --git a/drivers/net/ne2.c b/drivers/net/ne2.c
index 6ebef27..6d62ada 100644
--- a/drivers/net/ne2.c
+++ b/drivers/net/ne2.c
@@ -301,12 +301,7 @@
 	err = do_ne2_probe(dev);
 	if (err)
 		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
 	return dev;
-out1:
-	cleanup_card(dev);
 out:
 	free_netdev(dev);
 	return ERR_PTR(err);
@@ -517,7 +512,14 @@
 	dev->poll_controller = ei_poll;
 #endif
 	NS8390_init(dev, 0);
+
+	retval = register_netdev(dev);
+	if (retval)
+		goto out1;
 	return 0;
+out1:
+	mca_set_adapter_procfn( ei_status.priv, NULL, NULL);
+	free_irq(dev->irq, dev);
 out:
 	release_region(base_addr, NE_IO_EXTENT);
 	return retval;
@@ -798,11 +800,8 @@
 		dev->mem_end = bad[this_dev];
 		dev->base_addr = io[this_dev];
 		if (do_ne2_probe(dev) == 0) {
-			if (register_netdev(dev) == 0) {
-				dev_ne[found++] = dev;
-				continue;
-			}
-			cleanup_card(dev);
+			dev_ne[found++] = dev;
+			continue;
 		}
 		free_netdev(dev);
 		break;
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index c336b46..cc796527 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -101,6 +101,7 @@
 #include <linux/moduleparam.h>
 #include <linux/types.h>
 #include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
index 3107ccf..f0ff06e 100644
--- a/drivers/net/pcmcia/ibmtr_cs.c
+++ b/drivers/net/pcmcia/ibmtr_cs.c
@@ -119,9 +119,6 @@
 
 static dev_link_t *dev_list;
 
-extern int ibmtr_probe_card(struct net_device *dev);
-extern irqreturn_t tok_interrupt (int irq, void *dev_id, struct pt_regs *regs);
-
 /*====================================================================*/
 
 typedef struct ibmtr_dev_t {
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index b012630..f3ea4a9 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -1155,11 +1155,13 @@
 static irqreturn_t ei_irq_wrapper(int irq, void *dev_id, struct pt_regs *regs)
 {
     struct net_device *dev = dev_id;
-    pcnet_dev_t *info = PRIV(dev);
+    pcnet_dev_t *info;
     irqreturn_t ret = ei_interrupt(irq, dev_id, regs);
 
-    if (ret == IRQ_HANDLED)
+    if (ret == IRQ_HANDLED) {
+	    info = PRIV(dev);
 	    info->stale = 0;
+    }
     return ret;
 }
 
@@ -1350,7 +1352,7 @@
     if (count & 0x01)
 	buf[count-1] = inb(nic_base + PCNET_DATAPORT), xfer_count++;
 
-    /* This was for the ALPHA version only, but enough people have
+    /* This was for the ALPHA version only, but enough people have been
        encountering problems that it is still here. */
 #ifdef PCMCIA_DEBUG
     if (ei_debug > 4) {		/* DMA termination address check... */
@@ -1424,7 +1426,7 @@
     dma_start = jiffies;
 
 #ifdef PCMCIA_DEBUG
-    /* This was for the ALPHA version only, but enough people have
+    /* This was for the ALPHA version only, but enough people have been
        encountering problems that it is still here. */
     if (ei_debug > 4) {	/* DMA termination address check... */
 	int addr, tries = 20;
@@ -1537,20 +1539,20 @@
 static void shmem_block_input(struct net_device *dev, int count,
 			      struct sk_buff *skb, int ring_offset)
 {
-    void __iomem *xfer_start = ei_status.mem + (TX_PAGES<<8)
-				+ ring_offset
+    void __iomem *base = ei_status.mem;
+    unsigned long offset = (TX_PAGES<<8) + ring_offset
 				- (ei_status.rx_start_page << 8);
     char *buf = skb->data;
     
-    if (xfer_start + count > (void __iomem *)ei_status.rmem_end) {
+    if (offset + count > ei_status.priv) {
 	/* We must wrap the input move. */
-	int semi_count = (void __iomem *)ei_status.rmem_end - xfer_start;
-	copyin(buf, xfer_start, semi_count);
+	int semi_count = ei_status.priv - offset;
+	copyin(buf, base + offset, semi_count);
 	buf += semi_count;
-	xfer_start = ei_status.mem + (TX_PAGES<<8);
+	offset = TX_PAGES<<8;
 	count -= semi_count;
     }
-    copyin(buf, xfer_start, count);
+    copyin(buf, base + offset, count);
 }
 
 /*====================================================================*/
@@ -1611,8 +1613,9 @@
     }
     
     ei_status.mem = info->base + offset;
+    ei_status.priv = req.Size;
     dev->mem_start = (u_long)ei_status.mem;
-    dev->mem_end = ei_status.rmem_end = (u_long)info->base + req.Size;
+    dev->mem_end = dev->mem_start + req.Size;
 
     ei_status.tx_start_page = start_pg;
     ei_status.rx_start_page = start_pg + TX_PAGES;
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index 85a1521..8a5e52c 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -127,6 +127,12 @@
     int				rx_ovrn;
 };
 
+struct smc_cfg_mem {
+    tuple_t tuple;
+    cisparse_t parse;
+    u_char buf[255];
+};
+
 /* Special definitions for Megahertz multifunction cards */
 #define MEGAHERTZ_ISR		0x0380
 
@@ -498,14 +504,24 @@
 {
     struct net_device *dev = link->priv;
     struct smc_private *smc = netdev_priv(dev);
-    tuple_t tuple;
-    cisparse_t parse;
-    u_char buf[255];
-    cistpl_cftable_entry_t *cf = &parse.cftable_entry;
+    struct smc_cfg_mem *cfg_mem;
+    tuple_t *tuple;
+    cisparse_t *parse;
+    cistpl_cftable_entry_t *cf;
+    u_char *buf;
     win_req_t req;
     memreq_t mem;
     int i, k;
 
+    cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
+    if (!cfg_mem)
+        return CS_OUT_OF_RESOURCE;
+
+    tuple = &cfg_mem->tuple;
+    parse = &cfg_mem->parse;
+    cf = &parse->cftable_entry;
+    buf = cfg_mem->buf;
+
     link->conf.Attributes |= CONF_ENABLE_SPKR;
     link->conf.Status = CCSR_AUDIO_ENA;
     link->irq.Attributes =
@@ -514,12 +530,12 @@
     link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
     link->io.NumPorts2 = 8;
 
-    tuple.Attributes = tuple.TupleOffset = 0;
-    tuple.TupleData = (cisdata_t *)buf;
-    tuple.TupleDataMax = sizeof(buf);
-    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+    tuple->Attributes = tuple->TupleOffset = 0;
+    tuple->TupleData = (cisdata_t *)buf;
+    tuple->TupleDataMax = 255;
+    tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
 
-    i = first_tuple(link->handle, &tuple, &parse);
+    i = first_tuple(link->handle, tuple, parse);
     /* The Megahertz combo cards have modem-like CIS entries, so
        we have to explicitly try a bunch of port combinations. */
     while (i == CS_SUCCESS) {
@@ -532,10 +548,10 @@
 	    if (i == CS_SUCCESS) break;
 	}
 	if (i == CS_SUCCESS) break;
-	i = next_tuple(link->handle, &tuple, &parse);
+	i = next_tuple(link->handle, tuple, parse);
     }
     if (i != CS_SUCCESS)
-	return i;
+	goto free_cfg_mem;
     dev->base_addr = link->io.BasePort1;
 
     /* Allocate a memory window, for accessing the ISR */
@@ -544,7 +560,7 @@
     req.AccessSpeed = 0;
     i = pcmcia_request_window(&link->handle, &req, &link->win);
     if (i != CS_SUCCESS)
-	return i;
+	goto free_cfg_mem;
     smc->base = ioremap(req.Base, req.Size);
     mem.CardOffset = mem.Page = 0;
     if (smc->manfid == MANFID_MOTOROLA)
@@ -556,6 +572,8 @@
 	&& (smc->cardid == PRODID_MEGAHERTZ_EM3288))
 	mhz_3288_power(link);
 
+free_cfg_mem:
+    kfree(cfg_mem);
     return i;
 }
 
@@ -563,39 +581,61 @@
 {
     client_handle_t handle = link->handle;
     struct net_device *dev = link->priv;
-    tuple_t tuple;
-    cisparse_t parse;
-    u_char buf[255], *station_addr;
+    struct smc_cfg_mem *cfg_mem;
+    tuple_t *tuple;
+    cisparse_t *parse;
+    u_char *buf, *station_addr;
+    int rc;
 
-    tuple.Attributes = tuple.TupleOffset = 0;
-    tuple.TupleData = buf;
-    tuple.TupleDataMax = sizeof(buf);
+    cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
+    if (!cfg_mem)
+	return -1;
+
+    tuple = &cfg_mem->tuple;
+    parse = &cfg_mem->parse;
+    buf = cfg_mem->buf;
+
+    tuple->Attributes = tuple->TupleOffset = 0;
+    tuple->TupleData = (cisdata_t *)buf;
+    tuple->TupleDataMax = 255;
 
     /* Read the station address from the CIS.  It is stored as the last
        (fourth) string in the Version 1 Version/ID tuple. */
-    tuple.DesiredTuple = CISTPL_VERS_1;
-    if (first_tuple(handle, &tuple, &parse) != CS_SUCCESS)
-	return -1;
+    tuple->DesiredTuple = CISTPL_VERS_1;
+    if (first_tuple(handle, tuple, parse) != CS_SUCCESS) {
+	rc = -1;
+	goto free_cfg_mem;
+    }
     /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */
-    if (next_tuple(handle, &tuple, &parse) != CS_SUCCESS)
-	first_tuple(handle, &tuple, &parse);
-    if (parse.version_1.ns > 3) {
-	station_addr = parse.version_1.str + parse.version_1.ofs[3];
-	if (cvt_ascii_address(dev, station_addr) == 0)
-	    return 0;
+    if (next_tuple(handle, tuple, parse) != CS_SUCCESS)
+	first_tuple(handle, tuple, parse);
+    if (parse->version_1.ns > 3) {
+	station_addr = parse->version_1.str + parse->version_1.ofs[3];
+	if (cvt_ascii_address(dev, station_addr) == 0) {
+		rc = 0;
+		goto free_cfg_mem;
+	}
     }
 
     /* Another possibility: for the EM3288, in a special tuple */
-    tuple.DesiredTuple = 0x81;
-    if (pcmcia_get_first_tuple(handle, &tuple) != CS_SUCCESS)
-	return -1;
-    if (pcmcia_get_tuple_data(handle, &tuple) != CS_SUCCESS)
-	return -1;
+    tuple->DesiredTuple = 0x81;
+    if (pcmcia_get_first_tuple(handle, tuple) != CS_SUCCESS) {
+	rc = -1;
+	goto free_cfg_mem;
+    }
+    if (pcmcia_get_tuple_data(handle, tuple) != CS_SUCCESS) {
+	rc = -1;
+	goto free_cfg_mem;
+    }
     buf[12] = '\0';
-    if (cvt_ascii_address(dev, buf) == 0)
-	return 0;
-
-    return -1;
+    if (cvt_ascii_address(dev, buf) == 0) {
+	rc = 0;
+	goto free_cfg_mem;
+   }
+    rc = -1;
+free_cfg_mem:
+   kfree(cfg_mem);
+   return rc;
 }
 
 /*======================================================================
@@ -665,19 +705,29 @@
 static int smc_config(dev_link_t *link)
 {
     struct net_device *dev = link->priv;
-    tuple_t tuple;
-    cisparse_t parse;
-    u_char buf[255];
-    cistpl_cftable_entry_t *cf = &parse.cftable_entry;
+    struct smc_cfg_mem *cfg_mem;
+    tuple_t *tuple;
+    cisparse_t *parse;
+    cistpl_cftable_entry_t *cf;
+    u_char *buf;
     int i;
 
-    tuple.Attributes = tuple.TupleOffset = 0;
-    tuple.TupleData = (cisdata_t *)buf;
-    tuple.TupleDataMax = sizeof(buf);
-    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
+    cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
+    if (!cfg_mem)
+	return CS_OUT_OF_RESOURCE;
+
+    tuple = &cfg_mem->tuple;
+    parse = &cfg_mem->parse;
+    cf = &parse->cftable_entry;
+    buf = cfg_mem->buf;
+
+    tuple->Attributes = tuple->TupleOffset = 0;
+    tuple->TupleData = (cisdata_t *)buf;
+    tuple->TupleDataMax = 255;
+    tuple->DesiredTuple = CISTPL_CFTABLE_ENTRY;
 
     link->io.NumPorts1 = 16;
-    i = first_tuple(link->handle, &tuple, &parse);
+    i = first_tuple(link->handle, tuple, parse);
     while (i != CS_NO_MORE_ITEMS) {
 	if (i == CS_SUCCESS) {
 	    link->conf.ConfigIndex = cf->index;
@@ -686,10 +736,12 @@
 	    i = pcmcia_request_io(link->handle, &link->io);
 	    if (i == CS_SUCCESS) break;
 	}
-	i = next_tuple(link->handle, &tuple, &parse);
+	i = next_tuple(link->handle, tuple, parse);
     }
     if (i == CS_SUCCESS)
 	dev->base_addr = link->io.BasePort1;
+
+    kfree(cfg_mem);
     return i;
 }
 
@@ -697,41 +749,58 @@
 {
     client_handle_t handle = link->handle;
     struct net_device *dev = link->priv;
-    tuple_t tuple;
-    cisparse_t parse;
+    struct smc_cfg_mem *cfg_mem;
+    tuple_t *tuple;
+    cisparse_t *parse;
     cistpl_lan_node_id_t *node_id;
-    u_char buf[255], *station_addr;
-    int i;
+    u_char *buf, *station_addr;
+    int i, rc;
 
-    tuple.Attributes = tuple.TupleOffset = 0;
-    tuple.TupleData = buf;
-    tuple.TupleDataMax = sizeof(buf);
+    cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
+    if (!cfg_mem)
+	return CS_OUT_OF_RESOURCE;
+
+    tuple = &cfg_mem->tuple;
+    parse = &cfg_mem->parse;
+    buf = cfg_mem->buf;
+
+    tuple->Attributes = tuple->TupleOffset = 0;
+    tuple->TupleData = (cisdata_t *)buf;
+    tuple->TupleDataMax = 255;
 
     /* Check for a LAN function extension tuple */
-    tuple.DesiredTuple = CISTPL_FUNCE;
-    i = first_tuple(handle, &tuple, &parse);
+    tuple->DesiredTuple = CISTPL_FUNCE;
+    i = first_tuple(handle, tuple, parse);
     while (i == CS_SUCCESS) {
-	if (parse.funce.type == CISTPL_FUNCE_LAN_NODE_ID)
+	if (parse->funce.type == CISTPL_FUNCE_LAN_NODE_ID)
 	    break;
-	i = next_tuple(handle, &tuple, &parse);
+	i = next_tuple(handle, tuple, parse);
     }
     if (i == CS_SUCCESS) {
-	node_id = (cistpl_lan_node_id_t *)parse.funce.data;
+	node_id = (cistpl_lan_node_id_t *)parse->funce.data;
 	if (node_id->nb == 6) {
 	    for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = node_id->id[i];
-	    return 0;
+	    rc = 0;
+	    goto free_cfg_mem;
 	}
     }
     /* Try the third string in the Version 1 Version/ID tuple. */
-    tuple.DesiredTuple = CISTPL_VERS_1;
-    if (first_tuple(handle, &tuple, &parse) != CS_SUCCESS)
-	return -1;
-    station_addr = parse.version_1.str + parse.version_1.ofs[2];
-    if (cvt_ascii_address(dev, station_addr) == 0)
-	return 0;
+    tuple->DesiredTuple = CISTPL_VERS_1;
+    if (first_tuple(handle, tuple, parse) != CS_SUCCESS) {
+	rc = -1;
+	goto free_cfg_mem;
+    }
+    station_addr = parse->version_1.str + parse->version_1.ofs[2];
+    if (cvt_ascii_address(dev, station_addr) == 0) {
+	rc = 0;
+	goto free_cfg_mem;
+    }
 
-    return -1;
+    rc = -1;
+free_cfg_mem:
+    kfree(cfg_mem);
+    return rc;
 }
 
 /*====================================================================*/
@@ -773,26 +842,36 @@
 {
     client_handle_t handle = link->handle;
     struct net_device *dev = link->priv;
-    tuple_t tuple;
-    u_char buf[255];
-    int i;
+    struct smc_cfg_mem *cfg_mem;
+    tuple_t *tuple;
+    u_char *buf;
+    int i, rc;
 
-    tuple.Attributes = TUPLE_RETURN_COMMON;
-    tuple.TupleData = buf;
-    tuple.TupleDataMax = sizeof(buf);
-    tuple.TupleOffset = 0;
+    cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
+    if (!cfg_mem)
+        return -1;
+
+    tuple = &cfg_mem->tuple;
+    buf = cfg_mem->buf;
+
+    tuple->Attributes = TUPLE_RETURN_COMMON;
+    tuple->TupleData = (cisdata_t *)buf;
+    tuple->TupleDataMax = 255;
+    tuple->TupleOffset = 0;
 
     /* Read the station address from tuple 0x90, subtuple 0x04 */
-    tuple.DesiredTuple = 0x90;
-    i = pcmcia_get_first_tuple(handle, &tuple);
+    tuple->DesiredTuple = 0x90;
+    i = pcmcia_get_first_tuple(handle, tuple);
     while (i == CS_SUCCESS) {
-	i = pcmcia_get_tuple_data(handle, &tuple);
+	i = pcmcia_get_tuple_data(handle, tuple);
 	if ((i != CS_SUCCESS) || (buf[0] == 0x04))
 	    break;
-	i = pcmcia_get_next_tuple(handle, &tuple);
+	i = pcmcia_get_next_tuple(handle, tuple);
     }
-    if (i != CS_SUCCESS)
-	return -1;
+    if (i != CS_SUCCESS) {
+	rc = -1;
+	goto free_cfg_mem;
+    }
     for (i = 0; i < 6; i++)
 	dev->dev_addr[i] = buf[i+2];
 
@@ -814,8 +893,10 @@
 	      inw(link->io.BasePort1 + OSITECH_AUI_PWR),
 	      inw(link->io.BasePort1 + OSITECH_RESET_ISR));
     }
-
-    return 0;
+    rc = 0;
+free_cfg_mem:
+   kfree(cfg_mem);
+   return rc;
 }
 
 /*======================================================================
@@ -887,9 +968,10 @@
     client_handle_t handle = link->handle;
     struct net_device *dev = link->priv;
     struct smc_private *smc = netdev_priv(dev);
-    tuple_t tuple;
-    cisparse_t parse;
-    u_short buf[32];
+    struct smc_cfg_mem *cfg_mem;
+    tuple_t *tuple;
+    cisparse_t *parse;
+    u_char *buf;
     char *name;
     int i, j, rev;
     kio_addr_t ioaddr;
@@ -897,21 +979,29 @@
 
     DEBUG(0, "smc91c92_config(0x%p)\n", link);
 
-    tuple.Attributes = tuple.TupleOffset = 0;
-    tuple.TupleData = (cisdata_t *)buf;
-    tuple.TupleDataMax = sizeof(buf);
+    cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
+    if (!cfg_mem)
+	goto config_failed;
 
-    tuple.DesiredTuple = CISTPL_CONFIG;
-    i = first_tuple(handle, &tuple, &parse);
+    tuple = &cfg_mem->tuple;
+    parse = &cfg_mem->parse;
+    buf = cfg_mem->buf;
+
+    tuple->Attributes = tuple->TupleOffset = 0;
+    tuple->TupleData = (cisdata_t *)buf;
+    tuple->TupleDataMax = 64;
+
+    tuple->DesiredTuple = CISTPL_CONFIG;
+    i = first_tuple(handle, tuple, parse);
     CS_EXIT_TEST(i, ParseTuple, config_failed);
-    link->conf.ConfigBase = parse.config.base;
-    link->conf.Present = parse.config.rmask[0];
+    link->conf.ConfigBase = parse->config.base;
+    link->conf.Present = parse->config.rmask[0];
 
-    tuple.DesiredTuple = CISTPL_MANFID;
-    tuple.Attributes = TUPLE_RETURN_COMMON;
-    if (first_tuple(handle, &tuple, &parse) == CS_SUCCESS) {
-	smc->manfid = parse.manfid.manf;
-	smc->cardid = parse.manfid.card;
+    tuple->DesiredTuple = CISTPL_MANFID;
+    tuple->Attributes = TUPLE_RETURN_COMMON;
+    if (first_tuple(handle, tuple, parse) == CS_SUCCESS) {
+	smc->manfid = parse->manfid.manf;
+	smc->cardid = parse->manfid.card;
     }
 
     /* Configure card */
@@ -1046,7 +1136,7 @@
     	    printk(KERN_NOTICE "  No MII transceivers found!\n");
 	}
     }
-
+    kfree(cfg_mem);
     return;
 
 config_undo:
@@ -1054,6 +1144,7 @@
 config_failed:			/* CS_EXIT_TEST() calls jump to here... */
     smc91c92_release(link);
     link->state &= ~DEV_CONFIG_PENDING;
+    kfree(cfg_mem);
 
 } /* smc91c92_config */
 
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
index 33b9d79..5e48b9a 100644
--- a/drivers/net/ppp_async.c
+++ b/drivers/net/ppp_async.c
@@ -1025,7 +1025,7 @@
 
 static void __exit ppp_async_cleanup(void)
 {
-	if (tty_register_ldisc(N_PPP, NULL) != 0)
+	if (tty_unregister_ldisc(N_PPP) != 0)
 		printk(KERN_ERR "failed to unregister PPP line discipline\n");
 }
 
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 3b377f6..ab726ab 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -273,7 +273,7 @@
 static int ppp_disconnect_channel(struct channel *pch);
 static void ppp_destroy_channel(struct channel *pch);
 
-static struct class_simple *ppp_class;
+static struct class *ppp_class;
 
 /* Translates a PPP protocol number to a NP index (NP == network protocol) */
 static inline int proto_to_npindex(int proto)
@@ -858,12 +858,12 @@
 	printk(KERN_INFO "PPP generic driver version " PPP_VERSION "\n");
 	err = register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops);
 	if (!err) {
-		ppp_class = class_simple_create(THIS_MODULE, "ppp");
+		ppp_class = class_create(THIS_MODULE, "ppp");
 		if (IS_ERR(ppp_class)) {
 			err = PTR_ERR(ppp_class);
 			goto out_chrdev;
 		}
-		class_simple_device_add(ppp_class, MKDEV(PPP_MAJOR, 0), NULL, "ppp");
+		class_device_create(ppp_class, MKDEV(PPP_MAJOR, 0), NULL, "ppp");
 		err = devfs_mk_cdev(MKDEV(PPP_MAJOR, 0),
 				S_IFCHR|S_IRUSR|S_IWUSR, "ppp");
 		if (err)
@@ -876,8 +876,8 @@
 	return err;
 
 out_class:
-	class_simple_device_remove(MKDEV(PPP_MAJOR,0));
-	class_simple_destroy(ppp_class);
+	class_device_destroy(ppp_class, MKDEV(PPP_MAJOR,0));
+	class_destroy(ppp_class);
 out_chrdev:
 	unregister_chrdev(PPP_MAJOR, "ppp");
 	goto out;
@@ -1217,36 +1217,43 @@
  */
 static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
 {
-	int nch, len, fragsize;
+	int len, fragsize;
 	int i, bits, hdrlen, mtu;
-	int flen, fnb;
+	int flen;
+	int navail, nfree;
+	int nbigger;
 	unsigned char *p, *q;
 	struct list_head *list;
 	struct channel *pch;
 	struct sk_buff *frag;
 	struct ppp_channel *chan;
 
-	nch = 0;
+	nfree = 0;	/* # channels which have no packet already queued */
+	navail = 0;	/* total # of usable channels (not deregistered) */
 	hdrlen = (ppp->flags & SC_MP_XSHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN;
+	i = 0;
 	list = &ppp->channels;
 	while ((list = list->next) != &ppp->channels) {
 		pch = list_entry(list, struct channel, clist);
-		nch += pch->avail = (skb_queue_len(&pch->file.xq) == 0);
-		/*
-		 * If a channel hasn't had a fragment yet, it has to get
-		 * one before we send any fragments on later channels.
-		 * If it can't take a fragment now, don't give any
-		 * to subsequent channels.
-		 */
-		if (!pch->had_frag && !pch->avail) {
-			while ((list = list->next) != &ppp->channels) {
-				pch = list_entry(list, struct channel, clist);
-				pch->avail = 0;
+		navail += pch->avail = (pch->chan != NULL);
+		if (pch->avail) {
+			if (skb_queue_len(&pch->file.xq) == 0
+			    || !pch->had_frag) {
+				pch->avail = 2;
+				++nfree;
 			}
-			break;
+			if (!pch->had_frag && i < ppp->nxchan)
+				ppp->nxchan = i;
 		}
+		++i;
 	}
-	if (nch == 0)
+
+	/*
+	 * Don't start sending this packet unless at least half of
+	 * the channels are free.  This gives much better TCP
+	 * performance if we have a lot of channels.
+	 */
+	if (nfree == 0 || nfree < navail / 2)
 		return 0;	/* can't take now, leave it in xmit_pending */
 
 	/* Do protocol field compression (XXX this should be optional) */
@@ -1257,14 +1264,19 @@
 		--len;
 	}
 
-	/* decide on fragment size */
+	/*
+	 * Decide on fragment size.
+	 * We create a fragment for each free channel regardless of
+	 * how small they are (i.e. even 0 length) in order to minimize
+	 * the time that it will take to detect when a channel drops
+	 * a fragment.
+	 */
 	fragsize = len;
-	if (nch > 1) {
-		int maxch = ROUNDUP(len, MIN_FRAG_SIZE);
-		if (nch > maxch)
-			nch = maxch;
-		fragsize = ROUNDUP(fragsize, nch);
-	}
+	if (nfree > 1)
+		fragsize = ROUNDUP(fragsize, nfree);
+	/* nbigger channels get fragsize bytes, the rest get fragsize-1,
+	   except if nbigger==0, then they all get fragsize. */
+	nbigger = len % nfree;
 
 	/* skip to the channel after the one we last used
 	   and start at that one */
@@ -1278,7 +1290,7 @@
 
 	/* create a fragment for each channel */
 	bits = B;
-	do {
+	while (nfree > 0 || len > 0) {
 		list = list->next;
 		if (list == &ppp->channels) {
 			i = 0;
@@ -1289,61 +1301,92 @@
 		if (!pch->avail)
 			continue;
 
+		/*
+		 * Skip this channel if it has a fragment pending already and
+		 * we haven't given a fragment to all of the free channels.
+		 */
+		if (pch->avail == 1) {
+			if (nfree > 0)
+				continue;
+		} else {
+			--nfree;
+			pch->avail = 1;
+		}
+
 		/* check the channel's mtu and whether it is still attached. */
 		spin_lock_bh(&pch->downl);
-		if (pch->chan == 0 || (mtu = pch->chan->mtu) < hdrlen) {
-			/* can't use this channel */
+		if (pch->chan == NULL) {
+			/* can't use this channel, it's being deregistered */
 			spin_unlock_bh(&pch->downl);
 			pch->avail = 0;
-			if (--nch == 0)
+			if (--navail == 0)
 				break;
 			continue;
 		}
 
 		/*
-		 * We have to create multiple fragments for this channel
-		 * if fragsize is greater than the channel's mtu.
+		 * Create a fragment for this channel of
+		 * min(max(mtu+2-hdrlen, 4), fragsize, len) bytes.
+		 * If mtu+2-hdrlen < 4, that is a ridiculously small
+		 * MTU, so we use mtu = 2 + hdrlen.
 		 */
 		if (fragsize > len)
 			fragsize = len;
-		for (flen = fragsize; flen > 0; flen -= fnb) {
-			fnb = flen;
-			if (fnb > mtu + 2 - hdrlen)
-				fnb = mtu + 2 - hdrlen;
-			if (fnb >= len)
-				bits |= E;
-			frag = alloc_skb(fnb + hdrlen, GFP_ATOMIC);
-			if (frag == 0)
-				goto noskb;
-			q = skb_put(frag, fnb + hdrlen);
-			/* make the MP header */
-			q[0] = PPP_MP >> 8;
-			q[1] = PPP_MP;
-			if (ppp->flags & SC_MP_XSHORTSEQ) {
-				q[2] = bits + ((ppp->nxseq >> 8) & 0xf);
-				q[3] = ppp->nxseq;
-			} else {
-				q[2] = bits;
-				q[3] = ppp->nxseq >> 16;
-				q[4] = ppp->nxseq >> 8;
-				q[5] = ppp->nxseq;
-			}
+		flen = fragsize;
+		mtu = pch->chan->mtu + 2 - hdrlen;
+		if (mtu < 4)
+			mtu = 4;
+		if (flen > mtu)
+			flen = mtu;
+		if (flen == len && nfree == 0)
+			bits |= E;
+		frag = alloc_skb(flen + hdrlen + (flen == 0), GFP_ATOMIC);
+		if (frag == 0)
+			goto noskb;
+		q = skb_put(frag, flen + hdrlen);
 
-			/* copy the data in */
-			memcpy(q + hdrlen, p, fnb);
-
-			/* try to send it down the channel */
-			chan = pch->chan;
-			if (!chan->ops->start_xmit(chan, frag))
-				skb_queue_tail(&pch->file.xq, frag);
-			pch->had_frag = 1;
-			p += fnb;
-			len -= fnb;
-			++ppp->nxseq;
-			bits = 0;
+		/* make the MP header */
+		q[0] = PPP_MP >> 8;
+		q[1] = PPP_MP;
+		if (ppp->flags & SC_MP_XSHORTSEQ) {
+			q[2] = bits + ((ppp->nxseq >> 8) & 0xf);
+			q[3] = ppp->nxseq;
+		} else {
+			q[2] = bits;
+			q[3] = ppp->nxseq >> 16;
+			q[4] = ppp->nxseq >> 8;
+			q[5] = ppp->nxseq;
 		}
+
+		/*
+		 * Copy the data in.
+		 * Unfortunately there is a bug in older versions of
+		 * the Linux PPP multilink reconstruction code where it
+		 * drops 0-length fragments.  Therefore we make sure the
+		 * fragment has at least one byte of data.  Any bytes
+		 * we add in this situation will end up as padding on the
+		 * end of the reconstructed packet.
+		 */
+		if (flen == 0)
+			*skb_put(frag, 1) = 0;
+		else
+			memcpy(q + hdrlen, p, flen);
+
+		/* try to send it down the channel */
+		chan = pch->chan;
+		if (skb_queue_len(&pch->file.xq)
+		    || !chan->ops->start_xmit(chan, frag))
+			skb_queue_tail(&pch->file.xq, frag);
+		pch->had_frag = 1;
+		p += flen;
+		len -= flen;
+		++ppp->nxseq;
+		bits = 0;
 		spin_unlock_bh(&pch->downl);
-	} while (len > 0);
+
+		if (--nbigger == 0 && fragsize > 0)
+			--fragsize;
+	}
 	ppp->nxchan = i;
 
 	return 1;
@@ -1422,7 +1465,7 @@
 		kfree_skb(skb);
 		return;
 	}
-	
+
 	proto = PPP_PROTO(skb);
 	read_lock_bh(&pch->upl);
 	if (pch->ppp == 0 || proto >= 0xc000 || proto == PPP_CCPFRAG) {
@@ -1691,7 +1734,7 @@
 	struct list_head *l;
 	int mphdrlen = (ppp->flags & SC_MP_SHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN;
 
-	if (!pskb_may_pull(skb, mphdrlen + 1) || ppp->mrru == 0)
+	if (!pskb_may_pull(skb, mphdrlen) || ppp->mrru == 0)
 		goto err;		/* no good, throw it away */
 
 	/* Decode sequence number and begin/end bits */
@@ -2611,8 +2654,8 @@
 	if (unregister_chrdev(PPP_MAJOR, "ppp") != 0)
 		printk(KERN_ERR "PPP: failed to unregister PPP device\n");
 	devfs_remove("ppp");
-	class_simple_device_remove(MKDEV(PPP_MAJOR, 0));
-	class_simple_destroy(ppp_class);
+	class_device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0));
+	class_destroy(ppp_class);
 }
 
 /*
diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c
index 7d0150b..fd9f501 100644
--- a/drivers/net/ppp_synctty.c
+++ b/drivers/net/ppp_synctty.c
@@ -793,7 +793,7 @@
 static void __exit
 ppp_sync_cleanup(void)
 {
-	if (tty_register_ldisc(N_SYNC_PPP, NULL) != 0)
+	if (tty_unregister_ldisc(N_SYNC_PPP) != 0)
 		printk(KERN_ERR "failed to unregister Sync PPP line discipline\n");
 }
 
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index b3768d8..ce449fe 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -69,7 +69,13 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 
-#define RTL8169_VERSION "2.2LK"
+#ifdef CONFIG_R8169_NAPI
+#define NAPI_SUFFIX	"-NAPI"
+#else
+#define NAPI_SUFFIX	""
+#endif
+
+#define RTL8169_VERSION "2.2LK" NAPI_SUFFIX
 #define MODULENAME "r8169"
 #define PFX MODULENAME ": "
 
@@ -85,6 +91,10 @@
 #define dprintk(fmt, args...)	do {} while (0)
 #endif /* RTL8169_DEBUG */
 
+#define R8169_MSG_DEFAULT \
+	(NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | NETIF_MSG_IFUP | \
+	 NETIF_MSG_IFDOWN)
+
 #define TX_BUFFS_AVAIL(tp) \
 	(tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1)
 
@@ -174,8 +184,9 @@
 #undef _R
 
 static struct pci_device_id rtl8169_pci_tbl[] = {
-	{0x10ec, 0x8169, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0x1186, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK,	0x8169), },
+	{ PCI_DEVICE(PCI_VENDOR_ID_DLINK,	0x4300), },
+	{ PCI_DEVICE(0x16ec,			0x0116), },
 	{0,},
 };
 
@@ -183,10 +194,15 @@
 
 static int rx_copybreak = 200;
 static int use_dac;
+static struct {
+	u32 msg_enable;
+} debug = { -1 };
 
 enum RTL8169_registers {
 	MAC0 = 0,		/* Ethernet hardware address. */
 	MAR0 = 8,		/* Multicast filter. */
+	CounterAddrLow = 0x10,
+	CounterAddrHigh = 0x14,
 	TxDescStartAddrLow = 0x20,
 	TxDescStartAddrHigh = 0x24,
 	TxHDescStartAddrLow = 0x28,
@@ -328,6 +344,9 @@
 
 	/* _TBICSRBit */
 	TBILinkOK = 0x02000000,
+
+	/* DumpCounterCommand */
+	CounterDump = 0x8,
 };
 
 enum _DescStatusBit {
@@ -385,6 +404,7 @@
 	struct pci_dev *pci_dev;	/* Index of PCI device */
 	struct net_device_stats stats;	/* statistics of net device */
 	spinlock_t lock;		/* spin lock flag */
+	u32 msg_enable;
 	int chipset;
 	int mac_version;
 	int phy_version;
@@ -415,12 +435,16 @@
 	struct work_struct task;
 };
 
-MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@oss.sgi.com>");
+MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
 MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
 module_param_array(media, int, &num_media, 0);
+MODULE_PARM_DESC(media, "force phy operation. Deprecated by ethtool (8).");
 module_param(rx_copybreak, int, 0);
+MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
 module_param(use_dac, int, 0);
 MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
+module_param_named(debug, debug.msg_enable, int, 0);
+MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(RTL8169_VERSION);
 
@@ -433,10 +457,10 @@
 static int rtl8169_close(struct net_device *dev);
 static void rtl8169_set_rx_mode(struct net_device *dev);
 static void rtl8169_tx_timeout(struct net_device *dev);
-static struct net_device_stats *rtl8169_get_stats(struct net_device *netdev);
+static struct net_device_stats *rtl8169_get_stats(struct net_device *dev);
 static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *,
 				void __iomem *);
-static int rtl8169_change_mtu(struct net_device *netdev, int new_mtu);
+static int rtl8169_change_mtu(struct net_device *dev, int new_mtu);
 static void rtl8169_down(struct net_device *dev);
 
 #ifdef CONFIG_R8169_NAPI
@@ -543,9 +567,13 @@
 	spin_lock_irqsave(&tp->lock, flags);
 	if (tp->link_ok(ioaddr)) {
 		netif_carrier_on(dev);
-		printk(KERN_INFO PFX "%s: link up\n", dev->name);
-	} else
+		if (netif_msg_ifup(tp))
+			printk(KERN_INFO PFX "%s: link up\n", dev->name);
+	} else {
+		if (netif_msg_ifdown(tp))
+			printk(KERN_INFO PFX "%s: link down\n", dev->name);
 		netif_carrier_off(dev);
+	}
 	spin_unlock_irqrestore(&tp->lock, flags);
 }
 
@@ -569,7 +597,7 @@
 	
 	option = ((idx < MAX_UNITS) && (idx >= 0)) ? media[idx] : 0xff;
 
-	if ((option != 0xff) && !idx)
+	if ((option != 0xff) && !idx && netif_msg_drv(&debug))
 		printk(KERN_WARNING PFX "media option is deprecated.\n");
 
 	for (p = link_settings; p->media != 0xff; p++) {
@@ -611,9 +639,11 @@
 	} else if (autoneg == AUTONEG_ENABLE)
 		RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart);
 	else {
-		printk(KERN_WARNING PFX
-		       "%s: incorrect speed setting refused in TBI mode\n",
-		       dev->name);
+		if (netif_msg_link(tp)) {
+			printk(KERN_WARNING "%s: "
+			       "incorrect speed setting refused in TBI mode\n",
+			       dev->name);
+		}
 		ret = -EOPNOTSUPP;
 	}
 
@@ -871,12 +901,120 @@
         spin_unlock_irqrestore(&tp->lock, flags);
 }
 
+static u32 rtl8169_get_msglevel(struct net_device *dev)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+
+	return tp->msg_enable;
+}
+
+static void rtl8169_set_msglevel(struct net_device *dev, u32 value)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+
+	tp->msg_enable = value;
+}
+
+static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = {
+	"tx_packets",
+	"rx_packets",
+	"tx_errors",
+	"rx_errors",
+	"rx_missed",
+	"align_errors",
+	"tx_single_collisions",
+	"tx_multi_collisions",
+	"unicast",
+	"broadcast",
+	"multicast",
+	"tx_aborted",
+	"tx_underrun",
+};
+
+struct rtl8169_counters {
+	u64	tx_packets;
+	u64	rx_packets;
+	u64	tx_errors;
+	u32	rx_errors;
+	u16	rx_missed;
+	u16	align_errors;
+	u32	tx_one_collision;
+	u32	tx_multi_collision;
+	u64	rx_unicast;
+	u64	rx_broadcast;
+	u32	rx_multicast;
+	u16	tx_aborted;
+	u16	tx_underun;
+};
+
+static int rtl8169_get_stats_count(struct net_device *dev)
+{
+	return ARRAY_SIZE(rtl8169_gstrings);
+}
+
+static void rtl8169_get_ethtool_stats(struct net_device *dev,
+				      struct ethtool_stats *stats, u64 *data)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	void __iomem *ioaddr = tp->mmio_addr;
+	struct rtl8169_counters *counters;
+	dma_addr_t paddr;
+	u32 cmd;
+
+	ASSERT_RTNL();
+
+	counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr);
+	if (!counters)
+		return;
+
+	RTL_W32(CounterAddrHigh, (u64)paddr >> 32);
+	cmd = (u64)paddr & DMA_32BIT_MASK;
+	RTL_W32(CounterAddrLow, cmd);
+	RTL_W32(CounterAddrLow, cmd | CounterDump);
+
+	while (RTL_R32(CounterAddrLow) & CounterDump) {
+		if (msleep_interruptible(1))
+			break;
+	}
+
+	RTL_W32(CounterAddrLow, 0);
+	RTL_W32(CounterAddrHigh, 0);
+
+	data[0]	= le64_to_cpu(counters->tx_packets);
+	data[1] = le64_to_cpu(counters->rx_packets);
+	data[2] = le64_to_cpu(counters->tx_errors);
+	data[3] = le32_to_cpu(counters->rx_errors);
+	data[4] = le16_to_cpu(counters->rx_missed);
+	data[5] = le16_to_cpu(counters->align_errors);
+	data[6] = le32_to_cpu(counters->tx_one_collision);
+	data[7] = le32_to_cpu(counters->tx_multi_collision);
+	data[8] = le64_to_cpu(counters->rx_unicast);
+	data[9] = le64_to_cpu(counters->rx_broadcast);
+	data[10] = le32_to_cpu(counters->rx_multicast);
+	data[11] = le16_to_cpu(counters->tx_aborted);
+	data[12] = le16_to_cpu(counters->tx_underun);
+
+	pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr);
+}
+
+static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+{
+	switch(stringset) {
+	case ETH_SS_STATS:
+		memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings));
+		break;
+	}
+}
+
+
 static struct ethtool_ops rtl8169_ethtool_ops = {
 	.get_drvinfo		= rtl8169_get_drvinfo,
 	.get_regs_len		= rtl8169_get_regs_len,
 	.get_link		= ethtool_op_get_link,
 	.get_settings		= rtl8169_get_settings,
 	.set_settings		= rtl8169_set_settings,
+	.get_msglevel		= rtl8169_get_msglevel,
+	.set_msglevel		= rtl8169_set_msglevel,
 	.get_rx_csum		= rtl8169_get_rx_csum,
 	.set_rx_csum		= rtl8169_set_rx_csum,
 	.get_tx_csum		= ethtool_op_get_tx_csum,
@@ -886,6 +1024,9 @@
 	.get_tso		= ethtool_op_get_tso,
 	.set_tso		= ethtool_op_set_tso,
 	.get_regs		= rtl8169_get_regs,
+	.get_strings		= rtl8169_get_strings,
+	.get_stats_count	= rtl8169_get_stats_count,
+	.get_ethtool_stats	= rtl8169_get_ethtool_stats,
 };
 
 static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum,
@@ -1091,7 +1232,8 @@
 	if (tp->link_ok(ioaddr))
 		goto out_unlock;
 
-	printk(KERN_WARNING PFX "%s: PHY reset until link up\n", dev->name);
+	if (netif_msg_link(tp))
+		printk(KERN_WARNING "%s: PHY reset until link up\n", dev->name);
 
 	tp->phy_reset_enable(ioaddr);
 
@@ -1169,18 +1311,23 @@
 	/* dev zeroed in alloc_etherdev */
 	dev = alloc_etherdev(sizeof (*tp));
 	if (dev == NULL) {
-		printk(KERN_ERR PFX "unable to alloc new ethernet\n");
+		if (netif_msg_drv(&debug))
+			printk(KERN_ERR PFX "unable to alloc new ethernet\n");
 		goto err_out;
 	}
 
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 	tp = netdev_priv(dev);
+	tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT);
 
 	/* enable device (incl. PCI PM wakeup and hotplug setup) */
 	rc = pci_enable_device(pdev);
-	if (rc) {
-		printk(KERN_ERR PFX "%s: enable failure\n", pci_name(pdev));
+	if (rc < 0) {
+		if (netif_msg_probe(tp)) {
+			printk(KERN_ERR PFX "%s: enable failure\n",
+			       pci_name(pdev));
+		}
 		goto err_out_free_dev;
 	}
 
@@ -1196,29 +1343,39 @@
 		pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command);
 		acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
 	} else {
-		printk(KERN_ERR PFX
-		       "Cannot find PowerManagement capability, aborting.\n");
+		if (netif_msg_probe(tp)) {
+			printk(KERN_ERR PFX
+			       "Cannot find PowerManagement capability. "
+			       "Aborting.\n");
+		}
 		goto err_out_mwi;
 	}
 
 	/* make sure PCI base addr 1 is MMIO */
 	if (!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
-		printk(KERN_ERR PFX
-		       "region #1 not an MMIO resource, aborting\n");
+		if (netif_msg_probe(tp)) {
+			printk(KERN_ERR PFX
+			       "region #1 not an MMIO resource, aborting\n");
+		}
 		rc = -ENODEV;
 		goto err_out_mwi;
 	}
 	/* check for weird/broken PCI region reporting */
 	if (pci_resource_len(pdev, 1) < R8169_REGS_SIZE) {
-		printk(KERN_ERR PFX "Invalid PCI region size(s), aborting\n");
+		if (netif_msg_probe(tp)) {
+			printk(KERN_ERR PFX
+			       "Invalid PCI region size(s), aborting\n");
+		}
 		rc = -ENODEV;
 		goto err_out_mwi;
 	}
 
 	rc = pci_request_regions(pdev, MODULENAME);
-	if (rc) {
-		printk(KERN_ERR PFX "%s: could not request regions.\n",
-		       pci_name(pdev));
+	if (rc < 0) {
+		if (netif_msg_probe(tp)) {
+			printk(KERN_ERR PFX "%s: could not request regions.\n",
+			       pci_name(pdev));
+		}
 		goto err_out_mwi;
 	}
 
@@ -1231,7 +1388,10 @@
 	} else {
 		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
 		if (rc < 0) {
-			printk(KERN_ERR PFX "DMA configuration failed.\n");
+			if (netif_msg_probe(tp)) {
+				printk(KERN_ERR PFX
+				       "DMA configuration failed.\n");
+			}
 			goto err_out_free_res;
 		}
 	}
@@ -1241,7 +1401,8 @@
 	/* ioremap MMIO region */
 	ioaddr = ioremap(pci_resource_start(pdev, 1), R8169_REGS_SIZE);
 	if (ioaddr == NULL) {
-		printk(KERN_ERR PFX "cannot remap MMIO, aborting\n");
+		if (netif_msg_probe(tp))
+			printk(KERN_ERR PFX "cannot remap MMIO, aborting\n");
 		rc = -EIO;
 		goto err_out_free_res;
 	}
@@ -1272,9 +1433,11 @@
 	}
 	if (i < 0) {
 		/* Unknown chip: assume array element #0, original RTL-8169 */
-		printk(KERN_DEBUG PFX
-		       "PCI device %s: unknown chip version, assuming %s\n",
-		       pci_name(pdev), rtl_chip_info[0].name);
+		if (netif_msg_probe(tp)) {
+			printk(KERN_DEBUG PFX "PCI device %s: "
+			       "unknown chip version, assuming %s\n",
+			       pci_name(pdev), rtl_chip_info[0].name);
+		}
 		i++;
 	}
 	tp->chipset = i;
@@ -1308,7 +1471,6 @@
 	struct rtl8169_private *tp;
 	void __iomem *ioaddr = NULL;
 	static int board_idx = -1;
-	static int printed_version = 0;
 	u8 autoneg, duplex;
 	u16 speed;
 	int i, rc;
@@ -1318,10 +1480,9 @@
 
 	board_idx++;
 
-	if (!printed_version) {
+	if (netif_msg_drv(&debug)) {
 		printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
 		       MODULENAME, RTL8169_VERSION);
-		printed_version = 1;
 	}
 
 	rc = rtl8169_init_board(pdev, &dev, &ioaddr);
@@ -1366,7 +1527,6 @@
 #ifdef CONFIG_R8169_NAPI
 	dev->poll = rtl8169_poll;
 	dev->weight = R8169_NAPI_WEIGHT;
-	printk(KERN_INFO PFX "NAPI enabled\n");
 #endif
 
 #ifdef CONFIG_R8169_VLAN
@@ -1391,20 +1551,24 @@
 		return rc;
 	}
 
-	printk(KERN_DEBUG "%s: Identified chip type is '%s'.\n", dev->name,
-	       rtl_chip_info[tp->chipset].name);
+	if (netif_msg_probe(tp)) {
+		printk(KERN_DEBUG "%s: Identified chip type is '%s'.\n",
+		       dev->name, rtl_chip_info[tp->chipset].name);
+	}
 
 	pci_set_drvdata(pdev, dev);
 
-	printk(KERN_INFO "%s: %s at 0x%lx, "
-	       "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
-	       "IRQ %d\n",
-	       dev->name,
-	       rtl_chip_info[ent->driver_data].name,
-	       dev->base_addr,
-	       dev->dev_addr[0], dev->dev_addr[1],
-	       dev->dev_addr[2], dev->dev_addr[3],
-	       dev->dev_addr[4], dev->dev_addr[5], dev->irq);
+	if (netif_msg_probe(tp)) {
+		printk(KERN_INFO "%s: %s at 0x%lx, "
+		       "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
+		       "IRQ %d\n",
+		       dev->name,
+		       rtl_chip_info[ent->driver_data].name,
+		       dev->base_addr,
+		       dev->dev_addr[0], dev->dev_addr[1],
+		       dev->dev_addr[2], dev->dev_addr[3],
+		       dev->dev_addr[4], dev->dev_addr[5], dev->irq);
+	}
 
 	rtl8169_hw_phy_config(dev);
 
@@ -1427,7 +1591,7 @@
 
 	rtl8169_set_speed(dev, autoneg, speed, duplex);
 	
-	if (RTL_R8(PHYstatus) & TBI_Enable)
+	if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp))
 		printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name);
 
 	return 0;
@@ -1860,8 +2024,13 @@
 	ret = rtl8169_open(dev);
 	if (unlikely(ret < 0)) {
 		if (net_ratelimit()) {
-			printk(PFX KERN_ERR "%s: reinit failure (status = %d)."
-			       " Rescheduling.\n", dev->name, ret);
+			struct rtl8169_private *tp = netdev_priv(dev);
+
+			if (netif_msg_drv(tp)) {
+				printk(PFX KERN_ERR
+				       "%s: reinit failure (status = %d)."
+				       " Rescheduling.\n", dev->name, ret);
+			}
 		}
 		rtl8169_schedule_work(dev, rtl8169_reinit_task);
 	}
@@ -1886,8 +2055,12 @@
 		netif_wake_queue(dev);
 	} else {
 		if (net_ratelimit()) {
-			printk(PFX KERN_EMERG "%s: Rx buffers shortage\n",
-			       dev->name);
+			struct rtl8169_private *tp = netdev_priv(dev);
+
+			if (netif_msg_intr(tp)) {
+				printk(PFX KERN_EMERG
+				       "%s: Rx buffers shortage\n", dev->name);
+			}
 		}
 		rtl8169_schedule_work(dev, rtl8169_reset_task);
 	}
@@ -1973,8 +2146,11 @@
 	int ret = 0;
 	
 	if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) {
-		printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
-		       dev->name);
+		if (netif_msg_drv(tp)) {
+			printk(KERN_ERR
+			       "%s: BUG! Tx Ring full when queue awake!\n",
+			       dev->name);
+		}
 		goto err_stop;
 	}
 
@@ -2049,8 +2225,11 @@
 	pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
 	pci_read_config_word(pdev, PCI_STATUS, &pci_status);
 
-	printk(KERN_ERR PFX "%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n",
-	       dev->name, pci_cmd, pci_status);
+	if (netif_msg_intr(tp)) {
+		printk(KERN_ERR
+		       "%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n",
+		       dev->name, pci_cmd, pci_status);
+	}
 
 	/*
 	 * The recovery sequence below admits a very elaborated explanation:
@@ -2069,7 +2248,8 @@
 
 	/* The infamous DAC f*ckup only happens at boot time */
 	if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) {
-		printk(KERN_INFO PFX "%s: disabling PCI DAC.\n", dev->name);
+		if (netif_msg_intr(tp))
+			printk(KERN_INFO "%s: disabling PCI DAC.\n", dev->name);
 		tp->cp_cmd &= ~PCIDAC;
 		RTL_W16(CPlusCmd, tp->cp_cmd);
 		dev->features &= ~NETIF_F_HIGHDMA;
@@ -2180,7 +2360,7 @@
 	rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
 	rx_left = rtl8169_rx_quota(rx_left, (u32) dev->quota);
 
-	while (rx_left > 0) {
+	for (; rx_left > 0; rx_left--, cur_rx++) {
 		unsigned int entry = cur_rx % NUM_RX_DESC;
 		struct RxDesc *desc = tp->RxDescArray + entry;
 		u32 status;
@@ -2190,9 +2370,12 @@
 
 		if (status & DescOwn)
 			break;
-		if (status & RxRES) {
-			printk(KERN_INFO "%s: Rx ERROR. status = %08x\n",
-			       dev->name, status);
+		if (unlikely(status & RxRES)) {
+			if (netif_msg_rx_err(tp)) {
+				printk(KERN_INFO
+				       "%s: Rx ERROR. status = %08x\n",
+				       dev->name, status);
+			}
 			tp->stats.rx_errors++;
 			if (status & (RxRWT | RxRUNT))
 				tp->stats.rx_length_errors++;
@@ -2214,7 +2397,7 @@
 				tp->stats.rx_dropped++;
 				tp->stats.rx_length_errors++;
 				rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
-				goto move_on;
+				continue;
 			}
 
 			rtl8169_rx_csum(skb, desc);
@@ -2243,16 +2426,13 @@
 			tp->stats.rx_bytes += pkt_size;
 			tp->stats.rx_packets++;
 		}
-move_on:		
-		cur_rx++; 
-		rx_left--;
 	}
 
 	count = cur_rx - tp->cur_rx;
 	tp->cur_rx = cur_rx;
 
 	delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx);
-	if (!delta && count)
+	if (!delta && count && netif_msg_intr(tp))
 		printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name);
 	tp->dirty_rx += delta;
 
@@ -2263,7 +2443,7 @@
 	 *   after refill ?
 	 * - how do others driver handle this condition (Uh oh...).
 	 */
-	if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx)
+	if ((tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) && netif_msg_intr(tp))
 		printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name);
 
 	return count;
@@ -2315,7 +2495,7 @@
 
 		if (likely(netif_rx_schedule_prep(dev)))
 			__netif_rx_schedule(dev);
-		else {
+		else if (netif_msg_intr(tp)) {
 			printk(KERN_INFO "%s: interrupt %04x taken in poll\n",
 			       dev->name, status);	
 		}
@@ -2334,8 +2514,10 @@
 	} while (boguscnt > 0);
 
 	if (boguscnt <= 0) {
-		printk(KERN_WARNING "%s: Too much work at interrupt!\n",
-		       dev->name);
+		if (net_ratelimit() && netif_msg_intr(tp)) {
+			printk(KERN_WARNING
+			       "%s: Too much work at interrupt!\n", dev->name);
+		}
 		/* Clear all interrupt sources. */
 		RTL_W16(IntrStatus, 0xffff);
 	}
@@ -2458,8 +2640,10 @@
 
 	if (dev->flags & IFF_PROMISC) {
 		/* Unconditionally log net taps. */
-		printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n",
-		       dev->name);
+		if (netif_msg_link(tp)) {
+			printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n",
+			       dev->name);
+		}
 		rx_mode =
 		    AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
 		    AcceptAllPhys;
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 9c224eb..bb639a8 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -42,6 +42,7 @@
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -4593,19 +4594,19 @@
 		return ret;
 	}
 
-	if (!pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) {
+	if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
 		DBG_PRINT(INIT_DBG, "s2io_init_nic: Using 64bit DMA\n");
 		dma_flag = TRUE;
 
 		if (pci_set_consistent_dma_mask
-		    (pdev, 0xffffffffffffffffULL)) {
+		    (pdev, DMA_64BIT_MASK)) {
 			DBG_PRINT(ERR_DBG,
 				  "Unable to obtain 64bit DMA for \
 					consistent allocations\n");
 			pci_disable_device(pdev);
 			return -ENOMEM;
 		}
-	} else if (!pci_set_dma_mask(pdev, 0xffffffffUL)) {
+	} else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
 		DBG_PRINT(INIT_DBG, "s2io_init_nic: Using 32bit DMA\n");
 	} else {
 		pci_disable_device(pdev);
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 3107aed..127324f 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -66,6 +66,7 @@
 #include <linux/ethtool.h>
 #include <linux/crc32.h>
 #include <linux/bitops.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/processor.h>      /* Processor type for cache alignment. */
 #include <asm/io.h>
@@ -93,8 +94,6 @@
 
 /* Time in jiffies before concluding the transmitter is hung. */
 #define TX_TIMEOUT  (4*HZ)
-/* SiS 900 is capable of 32 bits BM DMA */
-#define SIS900_DMA_MASK 0xffffffff
 
 enum {
 	SIS_900 = 0,
@@ -414,7 +413,7 @@
 	ret = pci_enable_device(pci_dev);
 	if(ret) return ret;
 	
-	i = pci_set_dma_mask(pci_dev, SIS900_DMA_MASK);
+	i = pci_set_dma_mask(pci_dev, DMA_32BIT_MASK);
 	if(i){
 		printk(KERN_ERR "sis900.c: architecture does not support"
 			"32bit PCI busmaster DMA\n");
diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
index 05b827f..82570ec 100644
--- a/drivers/net/sk98lin/skge.c
+++ b/drivers/net/sk98lin/skge.c
@@ -112,6 +112,7 @@
 #include	<linux/moduleparam.h>
 #include	<linux/init.h>
 #include 	<linux/proc_fs.h>
+#include	<linux/dma-mapping.h>
 
 #include	"h/skdrv1st.h"
 #include	"h/skdrv2nd.h"
@@ -4212,7 +4213,7 @@
 			Flags);
 
 		SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST);
-		pAC->dev[Param.Para32[0]]->flags &= ~IFF_RUNNING;
+		netif_carrier_off(pAC->dev[Param.Para32[0]]);
 		spin_unlock_irqrestore(
 			&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
 			Flags);
@@ -4355,7 +4356,7 @@
 		}
 
 		/* Inform the world that link protocol is up. */
-		pAC->dev[Param.Para32[0]]->flags |= IFF_RUNNING;
+		netif_carrier_on(pAC->dev[Param.Para32[0]]);
 
 		break;
 	case SK_DRV_NET_DOWN:	 /* SK_U32 Reason */
@@ -4368,7 +4369,7 @@
 		} else {
 			DoPrintInterfaceChange = SK_TRUE;
 		}
-		pAC->dev[Param.Para32[1]]->flags &= ~IFF_RUNNING;
+		netif_carrier_off(pAC->dev[Param.Para32[1]]);
 		break;
 	case SK_DRV_SWITCH_HARD: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
 		SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
@@ -4912,8 +4913,8 @@
 		goto out;
  
 	/* Configure DMA attributes. */
-	if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL) &&
-	    pci_set_dma_mask(pdev, (u64) 0xffffffff))
+	if (pci_set_dma_mask(pdev, DMA_64BIT_MASK) &&
+	    pci_set_dma_mask(pdev, DMA_32BIT_MASK))
 		goto out_disable_device;
 
 
@@ -4961,7 +4962,6 @@
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	dev->poll_controller =	&SkGePollController;
 #endif
-	dev->flags &= 		~IFF_RUNNING;
 	SET_NETDEV_DEV(dev, &pdev->dev);
 	SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
 
@@ -5035,7 +5035,6 @@
 		dev->set_mac_address    = &SkGeSetMacAddr;
 		dev->do_ioctl           = &SkGeIoctl;
 		dev->change_mtu         = &SkGeChangeMtu;
-		dev->flags             &= ~IFF_RUNNING;
 		SET_NETDEV_DEV(dev, &pdev->dev);
 		SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
 
diff --git a/drivers/net/sk_g16.c b/drivers/net/sk_g16.c
deleted file mode 100644
index 134ae0e..0000000
--- a/drivers/net/sk_g16.c
+++ /dev/null
@@ -1,2066 +0,0 @@
-/*-
- * Copyright (C) 1994 by PJD Weichmann & SWS Bern, Switzerland
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * Module         : sk_g16.c
- *
- * Version        : $Revision: 1.1 $
- *
- * Author         : Patrick J.D. Weichmann
- *
- * Date Created   : 94/05/26
- * Last Updated   : $Date: 1994/06/30 16:25:15 $
- *
- * Description    : Schneider & Koch G16 Ethernet Device Driver for
- *                  Linux Kernel >= 1.1.22
- * Update History :
- *                  Paul Gortmaker, 03/97: Fix for v2.1.x to use read{b,w}
- *                  write{b,w} and memcpy -> memcpy_{to,from}io
- *
- *		    Jeff Garzik, 06/2000, Modularize
- *
--*/
-
-static const char rcsid[] = "$Id: sk_g16.c,v 1.1 1994/06/30 16:25:15 root Exp $";
-
-/*
- * The Schneider & Koch (SK) G16 Network device driver is based
- * on the 'ni6510' driver from Michael Hipp which can be found at
- * ftp://sunsite.unc.edu/pub/Linux/system/Network/drivers/nidrivers.tar.gz
- * 
- * Sources: 1) ni6510.c by M. Hipp
- *          2) depca.c  by D.C. Davies
- *          3) skeleton.c by D. Becker
- *          4) Am7990 Local Area Network Controller for Ethernet (LANCE),
- *             AMD, Pub. #05698, June 1989
- *
- * Many Thanks for helping me to get things working to: 
- *                 
- *                 A. Cox (A.Cox@swansea.ac.uk)
- *                 M. Hipp (mhipp@student.uni-tuebingen.de)
- *                 R. Bolz (Schneider & Koch, Germany)
- *
- * To Do: 
- *        - Support of SK_G8 and other SK Network Cards.
- *        - Autoset memory mapped RAM. Check for free memory and then
- *          configure RAM correctly. 
- *        - SK_close should really set card in to initial state.
- *        - Test if IRQ 3 is not switched off. Use autoirq() functionality.
- *          (as in /drivers/net/skeleton.c)
- *        - Implement Multicast addressing. At minimum something like
- *          in depca.c. 
- *        - Redo the statistics part.
- *        - Try to find out if the board is in 8 Bit or 16 Bit slot.
- *          If in 8 Bit mode don't use IRQ 11.
- *        - (Try to make it slightly faster.) 
- *	  - Power management support
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/fcntl.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/string.h> 
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/bitops.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include "sk_g16.h"
-
-/* 
- * Schneider & Koch Card Definitions 
- * =================================
- */  
-
-#define SK_NAME   "SK_G16"
-
-/*
- * SK_G16 Configuration
- * --------------------
- */ 
-
-/* 
- * Abbreviations
- * -------------
- *  
- * RAM - used for the 16KB shared memory 
- * Boot_ROM, ROM - are used for referencing the BootEPROM
- *
- * SK_BOOT_ROM and SK_ADDR are symbolic constants used to configure
- * the behaviour of the driver and the SK_G16.
- *
- * ! See sk_g16.install on how to install and configure the driver !   
- *
- * SK_BOOT_ROM defines if the Boot_ROM should be switched off or not.
- *
- * SK_ADDR defines the address where the RAM will be mapped into the real
- *         host memory.
- *         valid addresses are from 0xa0000 to 0xfc000 in 16Kbyte steps.
- */  
- 
-#define SK_BOOT_ROM     1              /* 1=BootROM on 0=off */
-
-#define SK_ADDR         0xcc000
-
-/* 
- * In POS3 are bits A14-A19 of the address bus. These bits can be set
- * to choose the RAM address. That's why we only can choose the RAM address
- * in 16KB steps.
- */
-
-#define POS_ADDR       (rom_addr>>14)  /* Do not change this line */
-
-/* 
- * SK_G16 I/O PORT's + IRQ's + Boot_ROM locations
- * ----------------------------------------------
- */
-
-/* 
- * As nearly every card has also SK_G16 a specified I/O Port region and
- * only a few possible IRQ's.
- * In the Installation Guide from Schneider & Koch is listed a possible
- * Interrupt IRQ2. IRQ2 is always IRQ9 in boards with two cascaded interrupt
- * controllers. So we use in SK_IRQS IRQ9.
- */
-
-/* Don't touch any of the following #defines. */
-
-#define SK_IO_PORTS     { 0x100, 0x180, 0x208, 0x220, 0x288, 0x320, 0x328, 0x390, 0 }
-
-#define SK_IRQS         { 3, 5, 9, 11, 0 }
-
-#define SK_BOOT_ROM_LOCATIONS { 0xc0000, 0xc4000, 0xc8000, 0xcc000, 0xd0000, 0xd4000, 0xd8000, 0xdc000, 0 }
-
-#define SK_BOOT_ROM_ID  { 0x55, 0xaa, 0x10, 0x50, 0x06, 0x33 }
-
-/* 
- * SK_G16 POS REGISTERS 
- * --------------------
- */
-
-/*
- * SK_G16 has a Programmable Option Select (POS) Register.
- * The POS is composed of 8 separate registers (POS0-7) which 
- * are I/O mapped on an address set by the W1 switch.                    
- *
- */
-
-#define SK_POS_SIZE 8           /* 8 I/O Ports are used by SK_G16 */
-
-#define SK_POS0     ioaddr      /* Card-ID Low (R) */
-#define SK_POS1     ioaddr+1    /* Card-ID High (R) */
-#define SK_POS2     ioaddr+2    /* Card-Enable, Boot-ROM Disable (RW) */
-#define SK_POS3     ioaddr+3    /* Base address of RAM */
-#define SK_POS4     ioaddr+4    /* IRQ */
-
-/* POS5 - POS7 are unused */
-
-/* 
- * SK_G16 MAC PREFIX 
- * -----------------
- */
-
-/* 
- * Scheider & Koch manufacturer code (00:00:a5).
- * This must be checked, that we are sure it is a SK card.
- */
-
-#define SK_MAC0         0x00
-#define SK_MAC1         0x00
-#define SK_MAC2         0x5a
-
-/* 
- * SK_G16 ID 
- * ---------
- */ 
-
-/* 
- * If POS0,POS1 contain the following ID, then we know
- * at which I/O Port Address we are. 
- */
-
-#define SK_IDLOW  0xfd 
-#define SK_IDHIGH 0x6a
-
-
-/* 
- * LANCE POS Bit definitions 
- * -------------------------
- */
-
-#define SK_ROM_RAM_ON  (POS2_CARD)
-#define SK_ROM_RAM_OFF (POS2_EPROM)
-#define SK_ROM_ON      (inb(SK_POS2) & POS2_CARD)
-#define SK_ROM_OFF     (inb(SK_POS2) | POS2_EPROM)
-#define SK_RAM_ON      (inb(SK_POS2) | POS2_CARD)
-#define SK_RAM_OFF     (inb(SK_POS2) & POS2_EPROM) 
-
-#define POS2_CARD  0x0001              /* 1 = SK_G16 on      0 = off */
-#define POS2_EPROM 0x0002              /* 1 = Boot EPROM off 0 = on */ 
-
-/* 
- * SK_G16 Memory mapped Registers
- * ------------------------------
- *
- */ 
-
-#define SK_IOREG        (&board->ioreg) /* LANCE data registers.     */ 
-#define SK_PORT         (&board->port)  /* Control, Status register  */
-#define SK_IOCOM        (&board->iocom) /* I/O Command               */
-
-/* 
- * SK_G16 Status/Control Register bits
- * -----------------------------------
- *
- * (C) Controlreg (S) Statusreg 
- */
-
-/* 
- * Register transfer: 0 = no transfer
- *                    1 = transferring data between LANCE and I/O reg 
- */
-#define SK_IORUN        0x20   
-
-/* 
- * LANCE interrupt: 0 = LANCE interrupt occurred	
- *                  1 = no LANCE interrupt occurred
- */
-#define SK_IRQ          0x10   
-			
-#define SK_RESET        0x08   /* Reset SK_CARD: 0 = RESET 1 = normal */
-#define SK_RW           0x02   /* 0 = write to 1 = read from */
-#define SK_ADR          0x01   /* 0 = REG DataPort 1 = RAP Reg addr port */
-
-  
-#define SK_RREG         SK_RW  /* Transferdirection to read from lance */
-#define SK_WREG         0      /* Transferdirection to write to lance */
-#define SK_RAP          SK_ADR /* Destination Register RAP */
-#define SK_RDATA        0      /* Destination Register REG DataPort */
-
-/* 
- * SK_G16 I/O Command 
- * ------------------
- */
-
-/* 
- * Any bitcombination sets the internal I/O bit (transfer will start) 
- * when written to I/O Command
- */
-
-#define SK_DOIO         0x80   /* Do Transfer */ 
- 
-/* 
- * LANCE RAP (Register Address Port). 
- * ---------------------------------
- */
-
-/*   
- * The LANCE internal registers are selected through the RAP. 
- * The Registers are:
- *
- * CSR0 - Status and Control flags 
- * CSR1 - Low order bits of initialize block (bits 15:00)
- * CSR2 - High order bits of initialize block (bits 07:00, 15:08 are reserved)
- * CSR3 - Allows redefinition of the Bus Master Interface.
- *        This register must be set to 0x0002, which means BSWAP = 0,
- *        ACON = 1, BCON = 0;
- *
- */
- 
-#define CSR0            0x00   
-#define CSR1            0x01  
-#define CSR2            0x02 
-#define CSR3            0x03
-
-/* 
- * General Definitions 
- * ===================
- */
-
-/* 
- * Set the number of Tx and Rx buffers, using Log_2(# buffers).
- * We have 16KB RAM which can be accessed by the LANCE. In the 
- * memory are not only the buffers but also the ring descriptors and
- * the initialize block. 
- * Don't change anything unless you really know what you do.
- */
-
-#define LC_LOG_TX_BUFFERS 1               /* (2 == 2^^1) 2 Transmit buffers */
-#define LC_LOG_RX_BUFFERS 3               /* (8 == 2^^3) 8 Receive buffers */
-
-/* Descriptor ring sizes */
-
-#define TMDNUM (1 << (LC_LOG_TX_BUFFERS)) /* 2 Transmit descriptor rings */
-#define RMDNUM (1 << (LC_LOG_RX_BUFFERS)) /* 8 Receive Buffers */
-
-/* Define Mask for setting RMD, TMD length in the LANCE init_block */
-
-#define TMDNUMMASK (LC_LOG_TX_BUFFERS << 29)
-#define RMDNUMMASK (LC_LOG_RX_BUFFERS << 29)
-
-/*
- * Data Buffer size is set to maximum packet length.
- */
-
-#define PKT_BUF_SZ              1518 
-
-/* 
- * The number of low I/O ports used by the ethercard. 
- */
-
-#define ETHERCARD_TOTAL_SIZE    SK_POS_SIZE
-
-/* 
- * SK_DEBUG
- *
- * Here you can choose what level of debugging wanted.
- *
- * If SK_DEBUG and SK_DEBUG2 are undefined, then only the
- *  necessary messages will be printed.
- *
- * If SK_DEBUG is defined, there will be many debugging prints
- *  which can help to find some mistakes in configuration or even
- *  in the driver code.
- *
- * If SK_DEBUG2 is defined, many many messages will be printed 
- *  which normally you don't need. I used this to check the interrupt
- *  routine. 
- *
- * (If you define only SK_DEBUG2 then only the messages for 
- *  checking interrupts will be printed!)
- *
- * Normal way of live is: 
- *
- * For the whole thing get going let both symbolic constants
- * undefined. If you face any problems and you know what's going
- * on (you know something about the card and you can interpret some
- * hex LANCE register output) then define SK_DEBUG
- * 
- */
-
-#undef  SK_DEBUG	/* debugging */
-#undef  SK_DEBUG2	/* debugging with more verbose report */
-
-#ifdef SK_DEBUG
-#define PRINTK(x) printk x
-#else
-#define PRINTK(x) /**/
-#endif
-
-#ifdef SK_DEBUG2
-#define PRINTK2(x) printk x
-#else
-#define PRINTK2(x) /**/
-#endif
-
-/* 
- * SK_G16 RAM
- *
- * The components are memory mapped and can be set in a region from
- * 0x00000 through 0xfc000 in 16KB steps. 
- *
- * The Network components are: dual ported RAM, Prom, I/O Reg, Status-,
- * Controlregister and I/O Command.
- *
- * dual ported RAM: This is the only memory region which the LANCE chip
- *      has access to. From the Lance it is addressed from 0x0000 to
- *      0x3fbf. The host accesses it normally.
- *
- * PROM: The PROM obtains the ETHERNET-MAC-Address. It is realised as a
- *       8-Bit PROM, this means only the 16 even addresses are used of the
- *       32 Byte Address region. Access to an odd address results in invalid
- *       data.
- * 
- * LANCE I/O Reg: The I/O Reg is build of 4 single Registers, Low-Byte Write,
- *       Hi-Byte Write, Low-Byte Read, Hi-Byte Read.
- *       Transfer from or to the LANCE is always in 16Bit so Low and High
- *       registers are always relevant.
- *
- *       The Data from the Readregister is not the data in the Writeregister!!
- *       
- * Port: Status- and Controlregister. 
- *       Two different registers which share the same address, Status is 
- *       read-only, Control is write-only.
- *    
- * I/O Command: 
- *       Any bitcombination written in here starts the transmission between
- *       Host and LANCE.
- */
-
-typedef struct
-{
-	unsigned char  ram[0x3fc0];   /* 16KB dual ported ram */
-	unsigned char  rom[0x0020];   /* 32Byte PROM containing 6Byte MAC */
-	unsigned char  res1[0x0010];  /* reserved */
-	unsigned volatile short ioreg;/* LANCE I/O Register */
-	unsigned volatile char  port; /* Statusregister and Controlregister */
-	unsigned char  iocom;         /* I/O Command Register */
-} SK_RAM;
-
-/* struct  */
-
-/* 
- * This is the structure for the dual ported ram. We
- * have exactly 16 320 Bytes. In here there must be:
- *
- *     - Initialize Block   (starting at a word boundary)
- *     - Receive and Transmit Descriptor Rings (quadword boundary)
- *     - Data Buffers (arbitrary boundary)
- *
- * This is because LANCE has on SK_G16 only access to the dual ported
- * RAM and nowhere else.
- */
-
-struct SK_ram
-{
-    struct init_block ib;
-    struct tmd tmde[TMDNUM];
-    struct rmd rmde[RMDNUM];
-    char tmdbuf[TMDNUM][PKT_BUF_SZ];
-    char rmdbuf[RMDNUM][PKT_BUF_SZ];
-};
-
-/* 
- * Structure where all necessary information is for ring buffer 
- * management and statistics.
- */
-
-struct priv
-{
-    struct SK_ram *ram;  /* dual ported ram structure */
-    struct rmd *rmdhead; /* start of receive ring descriptors */
-    struct tmd *tmdhead; /* start of transmit ring descriptors */
-    int        rmdnum;   /* actual used ring descriptor */
-    int        tmdnum;   /* actual transmit descriptor for transmitting data */
-    int        tmdlast;  /* last sent descriptor used for error handling, etc */
-    void       *rmdbufs[RMDNUM]; /* pointer to the receive buffers */
-    void       *tmdbufs[TMDNUM]; /* pointer to the transmit buffers */
-    struct net_device_stats stats; /* Device driver statistics */
-};
-
-/* global variable declaration */
-
-/* IRQ map used to reserve a IRQ (see SK_open()) */
-
-/* static variables */
-
-static SK_RAM *board;  /* pointer to our memory mapped board components */
-static DEFINE_SPINLOCK(SK_lock);
-
-/* Macros */
-
-
-/* Function Prototypes */
-
-/*
- * Device Driver functions
- * -----------------------
- * See for short explanation of each function its definitions header.
- */
-
-static int   SK_probe(struct net_device *dev, short ioaddr);
-
-static void  SK_timeout(struct net_device *dev);
-static int   SK_open(struct net_device *dev);
-static int   SK_send_packet(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t SK_interrupt(int irq, void *dev_id, struct pt_regs * regs);
-static void  SK_rxintr(struct net_device *dev);
-static void  SK_txintr(struct net_device *dev);
-static int   SK_close(struct net_device *dev);
-
-static struct net_device_stats *SK_get_stats(struct net_device *dev);
-
-unsigned int SK_rom_addr(void);
-
-static void set_multicast_list(struct net_device *dev);
-
-/*
- * LANCE Functions
- * ---------------
- */
-
-static int SK_lance_init(struct net_device *dev, unsigned short mode);
-void   SK_reset_board(void);
-void   SK_set_RAP(int reg_number);
-int    SK_read_reg(int reg_number);
-int    SK_rread_reg(void);
-void   SK_write_reg(int reg_number, int value);
-
-/* 
- * Debugging functions
- * -------------------
- */
-
-void SK_print_pos(struct net_device *dev, char *text);
-void SK_print_dev(struct net_device *dev, char *text);
-void SK_print_ram(struct net_device *dev);
-
-
-/*-
- * Function       : SK_init
- * Author         : Patrick J.D. Weichmann
- * Date Created   : 94/05/26
- *
- * Description    : Check for a SK_G16 network adaptor and initialize it.
- *                  This function gets called by dev_init which initializes
- *                  all Network devices.
- *
- * Parameters     : I : struct net_device *dev - structure preconfigured 
- *                                           from Space.c
- * Return Value   : 0 = Driver Found and initialized 
- * Errors         : ENODEV - no device found
- *                  ENXIO  - not probed
- * Globals        : None
- * Update History :
- *     YY/MM/DD  uid  Description
--*/
-
-static int io;	/* 0 == probe */
-
-/* 
- * Check for a network adaptor of this type, and return '0' if one exists.
- * If dev->base_addr == 0, probe all likely locations.
- * If dev->base_addr == 1, always return failure.
- */
-
-struct net_device * __init SK_init(int unit)
-{
-	int *port, ports[] = SK_IO_PORTS;  /* SK_G16 supported ports */
-	static unsigned version_printed;
-	struct net_device *dev = alloc_etherdev(sizeof(struct priv));
-	int err = -ENODEV;
-
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-
-	if (unit >= 0) {
-		sprintf(dev->name, "eth%d", unit);
-		netdev_boot_setup_check(dev);
-		io = dev->base_addr;
-	}
-
-	if (version_printed++ == 0)
-	        PRINTK(("%s: %s", SK_NAME, rcsid));
-
-	if (io > 0xff) {        /* Check a single specified address */
-		err = -EBUSY;
-		/* Check if on specified address is a SK_G16 */
-		if (request_region(io, ETHERCARD_TOTAL_SIZE, "sk_g16")) {
-			err = SK_probe(dev, io);
-			if (!err)
-				goto got_it;
-			release_region(io, ETHERCARD_TOTAL_SIZE);
-		}
-	} else if (io > 0) {       /* Don't probe at all */
-		err = -ENXIO;
-	} else {
-		/* Autoprobe base_addr */
-		for (port = &ports[0]; *port; port++) {
-			io = *port;
-
-			/* Check if I/O Port region is used by another board */
-			if (!request_region(io, ETHERCARD_TOTAL_SIZE, "sk_g16"))
-				continue;       /* Try next Port address */
-
-			/* Check if at ioaddr is a SK_G16 */
-			if (SK_probe(dev, io) == 0)
-				goto got_it;
-
-			release_region(io, ETHERCARD_TOTAL_SIZE);
-		}
-	}
-err_out:
-	free_netdev(dev);
-	return ERR_PTR(err);
-
-got_it:
-	err = register_netdev(dev);
-	if (err) {
-		release_region(dev->base_addr, ETHERCARD_TOTAL_SIZE);
-		goto err_out;
-	}
-	return dev;
-
-} /* End of SK_init */
-
-
-MODULE_AUTHOR("Patrick J.D. Weichmann");
-MODULE_DESCRIPTION("Schneider & Koch G16 Ethernet Device Driver");
-MODULE_LICENSE("GPL");
-MODULE_PARM(io, "i");
-MODULE_PARM_DESC(io, "0 to probe common ports (unsafe), or the I/O base of the board");
-
-
-#ifdef MODULE
-
-static struct net_device *SK_dev;
-
-static int __init SK_init_module (void)
-{
- 	SK_dev = SK_init(-1);
- 	return IS_ERR(SK_dev) ? PTR_ERR(SK_dev) : 0;
-}
-
-static void __exit SK_cleanup_module (void)
-{
- 	unregister_netdev(SK_dev);
- 	release_region(SK_dev->base_addr, ETHERCARD_TOTAL_SIZE);
- 	free_netdev(SK_dev);
-}
-
-module_init(SK_init_module);
-module_exit(SK_cleanup_module);
-#endif
-
-
-/*-
- * Function       : SK_probe
- * Author         : Patrick J.D. Weichmann
- * Date Created   : 94/05/26
- *
- * Description    : This function is called by SK_init and 
- *                  does the main part of initialization.
- *                  
- * Parameters     : I : struct net_device *dev - SK_G16 device structure
- *                  I : short ioaddr       - I/O Port address where POS is.
- * Return Value   : 0 = Initialization done             
- * Errors         : ENODEV - No SK_G16 found
- *                  -1     - Configuration problem
- * Globals        : board       - pointer to SK_RAM
- * Update History :
- *     YY/MM/DD  uid  Description
- *     94/06/30  pwe  SK_ADDR now checked and at the correct place
--*/
-
-int __init SK_probe(struct net_device *dev, short ioaddr)
-{
-    int i,j;                /* Counters */
-    int sk_addr_flag = 0;   /* SK ADDR correct? 1 - no, 0 - yes */
-    unsigned int rom_addr;  /* used to store RAM address used for POS_ADDR */
-
-    struct priv *p = netdev_priv(dev);	/* SK_G16 private structure */
-
-    if (inb(SK_POS0) != SK_IDLOW || inb(SK_POS1) != SK_IDHIGH)
-	return -ENODEV;
-    dev->base_addr = ioaddr;
-
-    if (SK_ADDR & 0x3fff || SK_ADDR < 0xa0000)
-    {
-      
-       sk_addr_flag = 1;
-
-       /* 
-        * Now here we could use a routine which searches for a free
-        * place in the ram and set SK_ADDR if found. TODO. 
-        */
-    }
-
-    if (SK_BOOT_ROM)            /* Shall we keep Boot_ROM on ? */
-    {
-        PRINTK(("## %s: SK_BOOT_ROM is set.\n", SK_NAME));
-
-        rom_addr = SK_rom_addr();
-
-	if (rom_addr == 0)      /* No Boot_ROM found */
-	{
-            if (sk_addr_flag)   /* No or Invalid SK_ADDR is defined */ 
-            {
-                printk("%s: SK_ADDR %#08x is not valid. Check configuration.\n",
-                       dev->name, SK_ADDR);
-                return -1;
-            }
-
-	    rom_addr = SK_ADDR; /* assign predefined address */
-
-	    PRINTK(("## %s: NO Bootrom found \n", SK_NAME));
-
-	    outb(SK_ROM_RAM_OFF, SK_POS2); /* Boot_ROM + RAM off */
-	    outb(POS_ADDR, SK_POS3);       /* Set RAM address */
-	    outb(SK_RAM_ON, SK_POS2);      /* enable RAM */
-	}
-	else if (rom_addr == SK_ADDR) 
-	{
-            printk("%s: RAM + ROM are set to the same address %#08x\n"
-                   "   Check configuration. Now switching off Boot_ROM\n",
-                   SK_NAME, rom_addr);
-
-	    outb(SK_ROM_RAM_OFF, SK_POS2); /* Boot_ROM + RAM off*/
-	    outb(POS_ADDR, SK_POS3);       /* Set RAM address */
-	    outb(SK_RAM_ON, SK_POS2);      /* enable RAM */
-	}
-	else
-	{
-            PRINTK(("## %s: Found ROM at %#08x\n", SK_NAME, rom_addr));
-	    PRINTK(("## %s: Keeping Boot_ROM on\n", SK_NAME));
-
-            if (sk_addr_flag)       /* No or Invalid SK_ADDR is defined */ 
-            {
-                printk("%s: SK_ADDR %#08x is not valid. Check configuration.\n",
-                       dev->name, SK_ADDR);
-                return -1;
-            }
-
-	    rom_addr = SK_ADDR;
-
-	    outb(SK_ROM_RAM_OFF, SK_POS2); /* Boot_ROM + RAM off */ 
-	    outb(POS_ADDR, SK_POS3);       /* Set RAM address */
-	    outb(SK_ROM_RAM_ON, SK_POS2);  /* RAM on, BOOT_ROM on */
-	}
-    }
-    else /* Don't keep Boot_ROM */
-    {
-        PRINTK(("## %s: SK_BOOT_ROM is not set.\n", SK_NAME));
-
-        if (sk_addr_flag)           /* No or Invalid SK_ADDR is defined */ 
-        {
-            printk("%s: SK_ADDR %#08x is not valid. Check configuration.\n",
-                   dev->name, SK_ADDR);
-            return -1;
-        }
-
-	rom_addr = SK_rom_addr();          /* Try to find a Boot_ROM */
-
-	/* IF we find a Boot_ROM disable it */
-
-	outb(SK_ROM_RAM_OFF, SK_POS2);     /* Boot_ROM + RAM off */  
-
-        /* We found a Boot_ROM and it's gone. Set RAM address on
-         * Boot_ROM address. 
-         */ 
-
-	if (rom_addr) 
-	{
-            printk("%s: We found Boot_ROM at %#08x. Now setting RAM on"
-                   "that address\n", SK_NAME, rom_addr);
-
-	    outb(POS_ADDR, SK_POS3);       /* Set RAM on Boot_ROM address */
-	}
-	else /* We did not find a Boot_ROM, use predefined SK_ADDR for ram */
-	{
-            if (sk_addr_flag)       /* No or Invalid SK_ADDR is defined */ 
-            {
-                printk("%s: SK_ADDR %#08x is not valid. Check configuration.\n",
-                       dev->name, SK_ADDR);
-                return -1;
-            }
-
-	    rom_addr = SK_ADDR;
-
-	    outb(POS_ADDR, SK_POS3);       /* Set RAM address */ 
-	}
-	outb(SK_RAM_ON, SK_POS2);          /* enable RAM */
-    }
-
-#ifdef SK_DEBUG
-    SK_print_pos(dev, "POS registers after ROM, RAM config");
-#endif
-
-    board = (SK_RAM *) isa_bus_to_virt(rom_addr);
-
-    /* Read in station address */
-    for (i = 0, j = 0; i < ETH_ALEN; i++, j+=2)
-    {
-	dev->dev_addr[i] = readb(board->rom+j);          
-    }
-
-    /* Check for manufacturer code */
-    if (!(dev->dev_addr[0] == SK_MAC0 &&
-	  dev->dev_addr[1] == SK_MAC1 &&
-	  dev->dev_addr[2] == SK_MAC2) )
-    {
-        PRINTK(("## %s: We did not find SK_G16 at RAM location.\n",
-                SK_NAME)); 
-	return -ENODEV;                     /* NO SK_G16 found */
-    }
-
-    printk("%s: %s found at %#3x, HW addr: %#04x:%02x:%02x:%02x:%02x:%02x\n",
-	    dev->name,
-	    "Schneider & Koch Netcard",
-	    (unsigned int) dev->base_addr,
-	    dev->dev_addr[0],
-	    dev->dev_addr[1],
-	    dev->dev_addr[2],
-	    dev->dev_addr[3],
-	    dev->dev_addr[4],
-	    dev->dev_addr[5]);
-
-    memset((char *) dev->priv, 0, sizeof(struct priv)); /* clear memory */
-
-    /* Assign our Device Driver functions */
-
-    dev->open                   = SK_open;
-    dev->stop                   = SK_close;
-    dev->hard_start_xmit        = SK_send_packet;
-    dev->get_stats              = SK_get_stats;
-    dev->set_multicast_list     = set_multicast_list;
-    dev->tx_timeout		= SK_timeout;
-    dev->watchdog_timeo		= HZ/7;
-
-
-    dev->flags &= ~IFF_MULTICAST;
-
-    /* Initialize private structure */
-
-    p->ram = (struct SK_ram *) rom_addr; /* Set dual ported RAM addr */
-    p->tmdhead = &(p->ram)->tmde[0];     /* Set TMD head */
-    p->rmdhead = &(p->ram)->rmde[0];     /* Set RMD head */
-
-    /* Initialize buffer pointers */
-
-    for (i = 0; i < TMDNUM; i++)
-    {
-	p->tmdbufs[i] = &(p->ram)->tmdbuf[i];
-    }
-
-    for (i = 0; i < RMDNUM; i++)
-    {
-	p->rmdbufs[i] = &(p->ram)->rmdbuf[i]; 
-    }
-
-#ifdef SK_DEBUG
-    SK_print_pos(dev, "End of SK_probe");
-    SK_print_ram(dev);
-#endif 
-    return 0;                            /* Initialization done */
-} /* End of SK_probe() */
-
-
-/*- 
- * Function       : SK_open
- * Author         : Patrick J.D. Weichmann
- * Date Created   : 94/05/26
- *
- * Description    : This function is called sometimes after booting 
- *                  when ifconfig program is run.
- *
- *                  This function requests an IRQ, sets the correct
- *                  IRQ in the card. Then calls SK_lance_init() to 
- *                  init and start the LANCE chip. Then if everything is 
- *                  ok returns with 0 (OK), which means SK_G16 is now
- *                  opened and operational.
- *
- *                  (Called by dev_open() /net/inet/dev.c)
- *
- * Parameters     : I : struct net_device *dev - SK_G16 device structure
- * Return Value   : 0 - Device opened
- * Errors         : -EAGAIN - Open failed
- * Side Effects   : None
- * Update History :
- *     YY/MM/DD  uid  Description
--*/
-
-static int SK_open(struct net_device *dev)
-{
-    int i = 0;
-    int irqval = 0;
-    int ioaddr = dev->base_addr;
-
-    int irqtab[] = SK_IRQS; 
-
-    struct priv *p = netdev_priv(dev);
-
-    PRINTK(("## %s: At beginning of SK_open(). CSR0: %#06x\n", 
-           SK_NAME, SK_read_reg(CSR0)));
-
-    if (dev->irq == 0) /* Autoirq */
-    {
-	i = 0;
-
-	/* 
-         * Check if one IRQ out of SK_IRQS is free and install 
-	 * interrupt handler.
-	 * Most done by request_irq(). 
-	 * irqval: 0       - interrupt handler installed for IRQ irqtab[i]
-	 *         -EBUSY  - interrupt busy 
-         *         -EINVAL - irq > 15 or handler = NULL
-	 */
-
-	do
-	{
-	  irqval = request_irq(irqtab[i], &SK_interrupt, 0, "sk_g16", dev);
-	  i++;
-	} while (irqval && irqtab[i]);
-
-	if (irqval) /* We tried every possible IRQ but no success */
-	{
-	    printk("%s: unable to get an IRQ\n", dev->name);
-	    return -EAGAIN;
-	}
-
-	dev->irq = irqtab[--i]; 
-	
-	outb(i<<2, SK_POS4);           /* Set Card on probed IRQ */
-
-    }
-    else if (dev->irq == 2) /* IRQ2 is always IRQ9 */
-    {
-	if (request_irq(9, &SK_interrupt, 0, "sk_g16", dev))
-	{
-	    printk("%s: unable to get IRQ 9\n", dev->name);
-	    return -EAGAIN;
-	} 
-	dev->irq = 9;
-	
-        /* 
-         * Now we set card on IRQ2.
-         * This can be confusing, but remember that IRQ2 on the network
-         * card is in reality IRQ9
-         */
-	outb(0x08, SK_POS4);           /* set card to IRQ2 */
-
-    }
-    else  /* Check IRQ as defined in Space.c */
-    {
-	int i = 0;
-
-	/* check if IRQ free and valid. Then install Interrupt handler */
-
-	if (request_irq(dev->irq, &SK_interrupt, 0, "sk_g16", dev))
-	{
-	    printk("%s: unable to get selected IRQ\n", dev->name);
-	    return -EAGAIN;
-	}
-
-	switch(dev->irq)
-	{
-	    case 3: i = 0;
-		    break;
-	    case 5: i = 1;
-		    break;
-	    case 2: i = 2;
-		    break;
-	    case 11:i = 3;
-		    break;
-	    default: 
-		printk("%s: Preselected IRQ %d is invalid for %s boards",
-		       dev->name,
-		       dev->irq,
-                       SK_NAME);
-		return -EAGAIN;
-	}      
-  
-	outb(i<<2, SK_POS4);           /* Set IRQ on card */
-    }
-
-    printk("%s: Schneider & Koch G16 at %#3x, IRQ %d, shared mem at %#08x\n",
-	    dev->name, (unsigned int)dev->base_addr, 
-	    (int) dev->irq, (unsigned int) p->ram);
-
-    if (!(i = SK_lance_init(dev, 0)))  /* LANCE init OK? */
-    {
-	netif_start_queue(dev);
-
-#ifdef SK_DEBUG
-
-        /* 
-         * This debug block tries to stop LANCE,
-         * reinit LANCE with transmitter and receiver disabled,
-         * then stop again and reinit with NORMAL_MODE
-         */
-
-        printk("## %s: After lance init. CSR0: %#06x\n", 
-               SK_NAME, SK_read_reg(CSR0));
-        SK_write_reg(CSR0, CSR0_STOP);
-        printk("## %s: LANCE stopped. CSR0: %#06x\n", 
-               SK_NAME, SK_read_reg(CSR0));
-        SK_lance_init(dev, MODE_DTX | MODE_DRX);
-        printk("## %s: Reinit with DTX + DRX off. CSR0: %#06x\n", 
-               SK_NAME, SK_read_reg(CSR0));
-        SK_write_reg(CSR0, CSR0_STOP);
-        printk("## %s: LANCE stopped. CSR0: %#06x\n", 
-               SK_NAME, SK_read_reg(CSR0));
-        SK_lance_init(dev, MODE_NORMAL);
-        printk("## %s: LANCE back to normal mode. CSR0: %#06x\n", 
-               SK_NAME, SK_read_reg(CSR0));
-        SK_print_pos(dev, "POS regs before returning OK");
-
-#endif /* SK_DEBUG */
-       
-	return 0;              /* SK_open() is successful */
-    }
-    else /* LANCE init failed */
-    {
-
-	PRINTK(("## %s: LANCE init failed: CSR0: %#06x\n", 
-               SK_NAME, SK_read_reg(CSR0)));
-
-	return -EAGAIN;
-    }
-
-} /* End of SK_open() */
-
-
-/*-
- * Function       : SK_lance_init
- * Author         : Patrick J.D. Weichmann
- * Date Created   : 94/05/26
- *
- * Description    : Reset LANCE chip, fill RMD, TMD structures with
- *                  start values and Start LANCE.
- *
- * Parameters     : I : struct net_device *dev - SK_G16 device structure
- *                  I : int mode - put LANCE into "mode" see data-sheet for
- *                                 more info.
- * Return Value   : 0  - Init done
- * Errors         : -1 - Init failed
- * Update History :
- *     YY/MM/DD  uid  Description
--*/
-
-static int SK_lance_init(struct net_device *dev, unsigned short mode)
-{
-    int i;
-    unsigned long flags;
-    struct priv *p = netdev_priv(dev);
-    struct tmd  *tmdp;
-    struct rmd  *rmdp;
-
-    PRINTK(("## %s: At beginning of LANCE init. CSR0: %#06x\n", 
-           SK_NAME, SK_read_reg(CSR0)));
-
-    /* Reset LANCE */
-    SK_reset_board();
-
-    /* Initialize TMD's with start values */
-    p->tmdnum = 0;                   /* First descriptor for transmitting */ 
-    p->tmdlast = 0;                  /* First descriptor for reading stats */
-
-    for (i = 0; i < TMDNUM; i++)     /* Init all TMD's */
-    {
-	tmdp = p->tmdhead + i; 
-   
-	writel((unsigned long) p->tmdbufs[i], tmdp->u.buffer); /* assign buffer */
-	
-	/* Mark TMD as start and end of packet */
-	writeb(TX_STP | TX_ENP, &tmdp->u.s.status);
-    }
-
-
-    /* Initialize RMD's with start values */
-
-    p->rmdnum = 0;                   /* First RMD which will be used */
- 
-    for (i = 0; i < RMDNUM; i++)     /* Init all RMD's */
-    {
-	rmdp = p->rmdhead + i;
-
-	
-	writel((unsigned long) p->rmdbufs[i], rmdp->u.buffer); /* assign buffer */
-	
-	/* 
-         * LANCE must be owner at beginning so that he can fill in 
-	 * receiving packets, set status and release RMD 
-	 */
-
-	writeb(RX_OWN, &rmdp->u.s.status);
-
-	writew(-PKT_BUF_SZ, &rmdp->blen); /* Buffer Size (two's complement) */
-
-	writeb(0, &rmdp->mlen);           /* init message length */       
-	
-    }
-
-    /* Fill LANCE Initialize Block */
-
-    writew(mode, (&((p->ram)->ib.mode))); /* Set operation mode */
-
-    for (i = 0; i < ETH_ALEN; i++)   /* Set physical address */
-    {
-	writeb(dev->dev_addr[i], (&((p->ram)->ib.paddr[i]))); 
-    }
-
-    for (i = 0; i < 8; i++)          /* Set multicast, logical address */
-    {
-	writeb(0, (&((p->ram)->ib.laddr[i]))); /* We do not use logical addressing */
-    } 
-
-    /* Set ring descriptor pointers and set number of descriptors */
-
-    writel((int)p->rmdhead | RMDNUMMASK, (&((p->ram)->ib.rdrp)));
-    writel((int)p->tmdhead | TMDNUMMASK, (&((p->ram)->ib.tdrp)));
-
-    /* Prepare LANCE Control and Status Registers */
-
-    spin_lock_irqsave(&SK_lock, flags);
-
-    SK_write_reg(CSR3, CSR3_ACON);   /* Ale Control !!!THIS MUST BE SET!!!! */
- 
-    /* 
-     * LANCE addresses the RAM from 0x0000 to 0x3fbf and has no access to
-     * PC Memory locations.
-     *
-     * In structure SK_ram is defined that the first thing in ram
-     * is the initialization block. So his address is for LANCE always
-     * 0x0000
-     *
-     * CSR1 contains low order bits 15:0 of initialization block address
-     * CSR2 is built of: 
-     *    7:0  High order bits 23:16 of initialization block address
-     *   15:8  reserved, must be 0
-     */
-    
-    /* Set initialization block address (must be on word boundary) */
-    SK_write_reg(CSR1, 0);          /* Set low order bits 15:0 */
-    SK_write_reg(CSR2, 0);          /* Set high order bits 23:16 */ 
-    
-
-    PRINTK(("## %s: After setting CSR1-3. CSR0: %#06x\n", 
-           SK_NAME, SK_read_reg(CSR0)));
-
-    /* Initialize LANCE */
-
-    /* 
-     * INIT = Initialize, when set, causes the LANCE to begin the
-     * initialization procedure and access the Init Block.
-     */
-
-    SK_write_reg(CSR0, CSR0_INIT); 
-
-    spin_unlock_irqrestore(&SK_lock, flags);
-
-    /* Wait until LANCE finished initialization */
-    
-    SK_set_RAP(CSR0);              /* Register Address Pointer to CSR0 */
-
-    for (i = 0; (i < 100) && !(SK_rread_reg() & CSR0_IDON); i++) 
-	; /* Wait until init done or go ahead if problems (i>=100) */
-
-    if (i >= 100) /* Something is wrong ! */
-    {
-	printk("%s: can't init am7990, status: %04x "
-	       "init_block: %#08x\n", 
-		dev->name, (int) SK_read_reg(CSR0), 
-		(unsigned int) &(p->ram)->ib);
-
-#ifdef SK_DEBUG
-	SK_print_pos(dev, "LANCE INIT failed");
-	SK_print_dev(dev,"Device Structure:");
-#endif
-
-	return -1;                 /* LANCE init failed */
-    }
-
-    PRINTK(("## %s: init done after %d ticks\n", SK_NAME, i));
-
-    /* Clear Initialize done, enable Interrupts, start LANCE */
-
-    SK_write_reg(CSR0, CSR0_IDON | CSR0_INEA | CSR0_STRT);
-
-    PRINTK(("## %s: LANCE started. CSR0: %#06x\n", SK_NAME, 
-            SK_read_reg(CSR0)));
-
-    return 0;                      /* LANCE is up and running */
-
-} /* End of SK_lance_init() */
-
-
-
-/*-
- * Function       : SK_send_packet
- * Author         : Patrick J.D. Weichmann
- * Date Created   : 94/05/27
- *
- * Description    : Writes an socket buffer into a transmit descriptor
- *                  and starts transmission.
- *
- * Parameters     : I : struct sk_buff *skb - packet to transfer
- *                  I : struct net_device *dev  - SK_G16 device structure
- * Return Value   : 0 - OK
- *                  1 - Could not transmit (dev_queue_xmit will queue it)
- *                      and try to sent it later
- * Globals        : None
- * Side Effects   : None
- * Update History :
- *     YY/MM/DD  uid  Description
--*/
-
-static void SK_timeout(struct net_device *dev)
-{
-	printk(KERN_WARNING "%s: xmitter timed out, try to restart!\n", dev->name);
-	SK_lance_init(dev, MODE_NORMAL); /* Reinit LANCE */
-	netif_wake_queue(dev);		 /* Clear Transmitter flag */
-	dev->trans_start = jiffies;      /* Mark Start of transmission */
-}
-
-static int SK_send_packet(struct sk_buff *skb, struct net_device *dev)
-{
-    struct priv *p = netdev_priv(dev);
-    struct tmd *tmdp;
-    static char pad[64];
-
-    PRINTK2(("## %s: SK_send_packet() called, CSR0 %#04x.\n", 
-	    SK_NAME, SK_read_reg(CSR0)));
-
-
-    /* 
-     * Block a timer-based transmit from overlapping. 
-     * This means check if we are already in. 
-     */
-
-    netif_stop_queue (dev);
-
-    {
-
-	/* Evaluate Packet length */
-	short len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; 
-       
-	tmdp = p->tmdhead + p->tmdnum; /* Which descriptor for transmitting */
-
-	/* Fill in Transmit Message Descriptor */
-
-	/* Copy data into dual ported ram */
-
-	memcpy_toio((tmdp->u.buffer & 0x00ffffff), skb->data, skb->len);
-	if (len != skb->len)
-		memcpy_toio((tmdp->u.buffer & 0x00ffffff) + skb->len, pad, len-skb->len);
-
-	writew(-len, &tmdp->blen);            /* set length to transmit */
-
-	/* 
-	 * Packet start and end is always set because we use the maximum
-	 * packet length as buffer length.
-	 * Relinquish ownership to LANCE
-	 */
-
-	writeb(TX_OWN | TX_STP | TX_ENP, &tmdp->u.s.status);
-	
-	/* Start Demand Transmission */
-	SK_write_reg(CSR0, CSR0_TDMD | CSR0_INEA);
-
-	dev->trans_start = jiffies;   /* Mark start of transmission */
-
-	/* Set pointer to next transmit buffer */
-	p->tmdnum++; 
-	p->tmdnum &= TMDNUM-1; 
-
-	/* Do we own the next transmit buffer ? */
-	if (! (readb(&((p->tmdhead + p->tmdnum)->u.s.status)) & TX_OWN) )
-	{
-	   /* 
-	    * We own next buffer and are ready to transmit, so
-	    * clear busy flag
-	    */
-	   netif_start_queue(dev);
-	}
-
-	p->stats.tx_bytes += skb->len;
-
-    }
-
-    dev_kfree_skb(skb);
-    return 0;  
-} /* End of SK_send_packet */
-
-
-/*-
- * Function       : SK_interrupt
- * Author         : Patrick J.D. Weichmann
- * Date Created   : 94/05/27
- *
- * Description    : SK_G16 interrupt handler which checks for LANCE
- *                  Errors, handles transmit and receive interrupts
- *
- * Parameters     : I : int irq, void *dev_id, struct pt_regs * regs -
- * Return Value   : None
- * Errors         : None
- * Globals        : None
- * Side Effects   : None
- * Update History :
- *     YY/MM/DD  uid  Description
--*/
-
-static irqreturn_t SK_interrupt(int irq, void *dev_id, struct pt_regs * regs)
-{
-    int csr0;
-    struct net_device *dev = dev_id;
-    struct priv *p = netdev_priv(dev);
-
-
-    PRINTK2(("## %s: SK_interrupt(). status: %#06x\n", 
-            SK_NAME, SK_read_reg(CSR0)));
-
-    if (dev == NULL)
-    {
-	printk("SK_interrupt(): IRQ %d for unknown device.\n", irq);
-    }
-    
-    spin_lock (&SK_lock);
-
-    csr0 = SK_read_reg(CSR0);      /* store register for checking */
-
-    /* 
-     * Acknowledge all of the current interrupt sources, disable      
-     * Interrupts (INEA = 0) 
-     */
-
-    SK_write_reg(CSR0, csr0 & CSR0_CLRALL); 
-
-    if (csr0 & CSR0_ERR) /* LANCE Error */
-    {
-	printk("%s: error: %04x\n", dev->name, csr0);
-      
-        if (csr0 & CSR0_MISS)      /* No place to store packet ? */
-        { 
-            p->stats.rx_dropped++;
-        }
-    }
-
-    if (csr0 & CSR0_RINT)          /* Receive Interrupt (packet arrived) */ 
-    {
-	SK_rxintr(dev); 
-    }
-
-    if (csr0 & CSR0_TINT)          /* Transmit interrupt (packet sent) */
-    {
-	SK_txintr(dev);
-    }
-
-    SK_write_reg(CSR0, CSR0_INEA); /* Enable Interrupts */
-
-    spin_unlock (&SK_lock);
-    return IRQ_HANDLED;
-} /* End of SK_interrupt() */ 
-
-
-/*-
- * Function       : SK_txintr
- * Author         : Patrick J.D. Weichmann
- * Date Created   : 94/05/27
- *
- * Description    : After sending a packet we check status, update
- *                  statistics and relinquish ownership of transmit 
- *                  descriptor ring.
- *
- * Parameters     : I : struct net_device *dev - SK_G16 device structure
- * Return Value   : None
- * Errors         : None
- * Globals        : None
- * Update History :
- *     YY/MM/DD  uid  Description
--*/
-
-static void SK_txintr(struct net_device *dev)
-{
-    int tmdstat;
-    struct tmd *tmdp;
-    struct priv *p = netdev_priv(dev);
-
-
-    PRINTK2(("## %s: SK_txintr() status: %#06x\n", 
-            SK_NAME, SK_read_reg(CSR0)));
-
-    tmdp = p->tmdhead + p->tmdlast;     /* Which buffer we sent at last ? */
-
-    /* Set next buffer */
-    p->tmdlast++;
-    p->tmdlast &= TMDNUM-1;
-
-    tmdstat = readb(&tmdp->u.s.status);
-
-    /* 
-     * We check status of transmitted packet.
-     * see LANCE data-sheet for error explanation
-     */
-    if (tmdstat & TX_ERR) /* Error occurred */
-    {
-	int stat2 = readw(&tmdp->status2);
-
-	printk("%s: TX error: %04x %04x\n", dev->name, tmdstat, stat2);
-
-	if (stat2 & TX_TDR)    /* TDR problems? */
-	{
-	    printk("%s: tdr-problems \n", dev->name);
-	}
-
-	if (stat2 & TX_RTRY)   /* Failed in 16 attempts to transmit ? */
-            p->stats.tx_aborted_errors++;   
-        if (stat2 & TX_LCOL)   /* Late collision ? */
-            p->stats.tx_window_errors++; 
-	if (stat2 & TX_LCAR)   /* Loss of Carrier ? */  
-            p->stats.tx_carrier_errors++;
-        if (stat2 & TX_UFLO)   /* Underflow error ? */
-        {
-            p->stats.tx_fifo_errors++;
-
-            /* 
-             * If UFLO error occurs it will turn transmitter of.
-             * So we must reinit LANCE
-             */
-
-            SK_lance_init(dev, MODE_NORMAL);
-        }
-	
-	p->stats.tx_errors++;
-
-	writew(0, &tmdp->status2);             /* Clear error flags */
-    }
-    else if (tmdstat & TX_MORE)        /* Collisions occurred ? */
-    {
-        /* 
-         * Here I have a problem.
-         * I only know that there must be one or up to 15 collisions.
-         * That's why TX_MORE is set, because after 16 attempts TX_RTRY
-         * will be set which means couldn't send packet aborted transfer.
-         *
-         * First I did not have this in but then I thought at minimum
-         * we see that something was not ok.
-         * If anyone knows something better than this to handle this
-         * please report it.
-         */ 
-
-        p->stats.collisions++; 
-    }
-    else   /* Packet sent without any problems */
-    {
-        p->stats.tx_packets++; 
-    }
-
-    /* 
-     * We mark transmitter not busy anymore, because now we have a free
-     * transmit descriptor which can be filled by SK_send_packet and
-     * afterwards sent by the LANCE
-     * 
-     * The function which do handle slow IRQ parts is do_bottom_half()
-     * which runs at normal kernel priority, that means all interrupt are
-     * enabled. (see kernel/irq.c)
-     *  
-     * net_bh does something like this:
-     *  - check if already in net_bh
-     *  - try to transmit something from the send queue
-     *  - if something is in the receive queue send it up to higher 
-     *    levels if it is a known protocol
-     *  - try to transmit something from the send queue
-     */
-
-    netif_wake_queue(dev);
-
-} /* End of SK_txintr() */
-
-
-/*-
- * Function       : SK_rxintr
- * Author         : Patrick J.D. Weichmann
- * Date Created   : 94/05/27
- *
- * Description    : Buffer sent, check for errors, relinquish ownership
- *                  of the receive message descriptor. 
- *
- * Parameters     : I : SK_G16 device structure
- * Return Value   : None
- * Globals        : None
- * Update History :
- *     YY/MM/DD  uid  Description
--*/
-
-static void SK_rxintr(struct net_device *dev)
-{
-
-    struct rmd *rmdp;
-    int rmdstat;
-    struct priv *p = netdev_priv(dev);
-
-    PRINTK2(("## %s: SK_rxintr(). CSR0: %#06x\n", 
-            SK_NAME, SK_read_reg(CSR0)));
-
-    rmdp = p->rmdhead + p->rmdnum;
-
-    /* As long as we own the next entry, check status and send
-     * it up to higher layer 
-     */
-
-    while (!( (rmdstat = readb(&rmdp->u.s.status)) & RX_OWN))
-    {
-	/* 
-         * Start and end of packet must be set, because we use 
-	 * the ethernet maximum packet length (1518) as buffer size.
-	 * 
-	 * Because our buffers are at maximum OFLO and BUFF errors are
-	 * not to be concerned (see Data sheet)
-	 */
-
-	if ((rmdstat & (RX_STP | RX_ENP)) != (RX_STP | RX_ENP))
-	{
-	    /* Start of a frame > 1518 Bytes ? */
-
-	    if (rmdstat & RX_STP) 
-	    {
-		p->stats.rx_errors++;        /* bad packet received */
-		p->stats.rx_length_errors++; /* packet too long */
-
-		printk("%s: packet too long\n", dev->name);
-	    }
-	    
-	    /* 
-             * All other packets will be ignored until a new frame with
-	     * start (RX_STP) set follows.
-	     * 
-	     * What we do is just give descriptor free for new incoming
-	     * packets. 
-	     */
-
-	    writeb(RX_OWN, &rmdp->u.s.status); /* Relinquish ownership to LANCE */ 
-
-	}
-	else if (rmdstat & RX_ERR)          /* Receive Error ? */
-	{
-	    printk("%s: RX error: %04x\n", dev->name, (int) rmdstat);
-	    
-	    p->stats.rx_errors++;
-
-	    if (rmdstat & RX_FRAM) p->stats.rx_frame_errors++;
-	    if (rmdstat & RX_CRC)  p->stats.rx_crc_errors++;
-
-	    writeb(RX_OWN, &rmdp->u.s.status); /* Relinquish ownership to LANCE */
-
-	}
-	else /* We have a packet which can be queued for the upper layers */
-	{
-
-	    int len = readw(&rmdp->mlen) & 0x0fff;  /* extract message length from receive buffer */
-	    struct sk_buff *skb;
-
-	    skb = dev_alloc_skb(len+2); /* allocate socket buffer */ 
-
-	    if (skb == NULL)                /* Could not get mem ? */
-	    {
-    
-		/* 
-                 * Couldn't allocate sk_buffer so we give descriptor back
-		 * to Lance, update statistics and go ahead.
-		 */
-
-		writeb(RX_OWN, &rmdp->u.s.status); /* Relinquish ownership to LANCE */
-		printk("%s: Couldn't allocate sk_buff, deferring packet.\n",
-		       dev->name);
-		p->stats.rx_dropped++;
-
-		break;                      /* Jump out */
-	    }
-	    
-	    /* Prepare sk_buff to queue for upper layers */
-
-	    skb->dev = dev;
-	    skb_reserve(skb,2);		/* Align IP header on 16 byte boundary */
-	    
-	    /* 
-             * Copy data out of our receive descriptor into sk_buff.
-	     *
-	     * (rmdp->u.buffer & 0x00ffffff) -> get address of buffer and 
-	     * ignore status fields) 
-	     */
-
-	    memcpy_fromio(skb_put(skb,len), (rmdp->u.buffer & 0x00ffffff), len);
-
-
-	    /* 
-             * Notify the upper protocol layers that there is another packet
-	     * to handle
-	     *
-	     * netif_rx() always succeeds. see /net/inet/dev.c for more.
-	     */
-
-	    skb->protocol=eth_type_trans(skb,dev);
-	    netif_rx(skb);                 /* queue packet and mark it for processing */
-	   
-	    /* 
-             * Packet is queued and marked for processing so we
-	     * free our descriptor and update statistics 
-	     */
-
-	    writeb(RX_OWN, &rmdp->u.s.status);
-	    dev->last_rx = jiffies;
-	    p->stats.rx_packets++;
-	    p->stats.rx_bytes += len;
-
-
-	    p->rmdnum++;
-	    p->rmdnum %= RMDNUM;
-
-	    rmdp = p->rmdhead + p->rmdnum;
-	}
-    }
-} /* End of SK_rxintr() */
-
-
-/*-
- * Function       : SK_close
- * Author         : Patrick J.D. Weichmann
- * Date Created   : 94/05/26
- *
- * Description    : close gets called from dev_close() and should
- *                  deinstall the card (free_irq, mem etc).
- *
- * Parameters     : I : struct net_device *dev - our device structure
- * Return Value   : 0 - closed device driver
- * Errors         : None
- * Globals        : None
- * Update History :
- *     YY/MM/DD  uid  Description
--*/
-
-/* I have tried to set BOOT_ROM on and RAM off but then, after a 'ifconfig
- * down' the system stops. So I don't shut set card to init state.
- */
-
-static int SK_close(struct net_device *dev)
-{
-
-    PRINTK(("## %s: SK_close(). CSR0: %#06x\n", 
-           SK_NAME, SK_read_reg(CSR0)));
-
-    netif_stop_queue(dev);	   /* Transmitter busy */
-
-    printk("%s: Shutting %s down CSR0 %#06x\n", dev->name, SK_NAME, 
-           (int) SK_read_reg(CSR0));
-
-    SK_write_reg(CSR0, CSR0_STOP); /* STOP the LANCE */
-
-    free_irq(dev->irq, dev);      /* Free IRQ */
-
-    return 0; /* always succeed */
-    
-} /* End of SK_close() */
-
-
-/*-
- * Function       : SK_get_stats
- * Author         : Patrick J.D. Weichmann
- * Date Created   : 94/05/26
- *
- * Description    : Return current status structure to upper layers.
- *                  It is called by sprintf_stats (dev.c).
- *
- * Parameters     : I : struct net_device *dev   - our device structure
- * Return Value   : struct net_device_stats * - our current statistics
- * Errors         : None
- * Side Effects   : None
- * Update History :
- *     YY/MM/DD  uid  Description
--*/
-
-static struct net_device_stats *SK_get_stats(struct net_device *dev)
-{
-
-    struct priv *p = netdev_priv(dev);
-
-    PRINTK(("## %s: SK_get_stats(). CSR0: %#06x\n", 
-           SK_NAME, SK_read_reg(CSR0)));
-
-    return &p->stats;             /* Return Device status */
-
-} /* End of SK_get_stats() */
-
-
-/*-
- * Function       : set_multicast_list
- * Author         : Patrick J.D. Weichmann
- * Date Created   : 94/05/26
- *
- * Description    : This function gets called when a program performs
- *                  a SIOCSIFFLAGS call. Ifconfig does this if you call
- *                  'ifconfig [-]allmulti' which enables or disables the
- *                  Promiscuous mode.
- *                  Promiscuous mode is when the Network card accepts all
- *                  packets, not only the packets which match our MAC 
- *                  Address. It is useful for writing a network monitor,
- *                  but it is also a security problem. You have to remember
- *                  that all information on the net is not encrypted.
- *
- * Parameters     : I : struct net_device *dev - SK_G16 device Structure
- * Return Value   : None
- * Errors         : None
- * Globals        : None
- * Update History :
- *     YY/MM/DD  uid  Description
- *     95/10/18  ACox  New multicast calling scheme
--*/
-
-
-/* Set or clear the multicast filter for SK_G16.
- */
-
-static void set_multicast_list(struct net_device *dev)
-{
-
-    if (dev->flags&IFF_PROMISC)
-    {
-	/* Reinitialize LANCE with MODE_PROM set */
-	SK_lance_init(dev, MODE_PROM);
-    }
-    else if (dev->mc_count==0 && !(dev->flags&IFF_ALLMULTI))
-    {
-	/* Reinitialize LANCE without MODE_PROM */
-	SK_lance_init(dev, MODE_NORMAL);
-    }
-    else
-    {
-	/* Multicast with logical address filter on */
-	/* Reinitialize LANCE without MODE_PROM */
-	SK_lance_init(dev, MODE_NORMAL);
-	
-	/* Not implemented yet. */
-    }
-} /* End of set_multicast_list() */
-
-
-
-/*-
- * Function       : SK_rom_addr
- * Author         : Patrick J.D. Weichmann
- * Date Created   : 94/06/01
- *
- * Description    : Try to find a Boot_ROM at all possible locations
- *
- * Parameters     : None
- * Return Value   : Address where Boot_ROM is
- * Errors         : 0 - Did not find Boot_ROM
- * Globals        : None
- * Update History :
- *     YY/MM/DD  uid  Description
--*/
-
-unsigned int __init SK_rom_addr(void)
-{
-    int i,j;
-    int rom_found = 0;
-    unsigned int rom_location[] = SK_BOOT_ROM_LOCATIONS;
-    unsigned char rom_id[] = SK_BOOT_ROM_ID;
-    unsigned char test_byte;
-
-    /* Autodetect Boot_ROM */
-    PRINTK(("## %s: Autodetection of Boot_ROM\n", SK_NAME));
-
-    for (i = 0; (rom_location[i] != 0) && (rom_found == 0); i++)
-    {
-	
-	PRINTK(("##   Trying ROM location %#08x", rom_location[i]));
-	
-	rom_found = 1; 
-	for (j = 0; j < 6; j++)
-	{
-	    test_byte = readb(rom_location[i]+j);
-	    PRINTK((" %02x ", *test_byte));
-
-	    if(test_byte != rom_id[j])
-	    {
-		rom_found = 0;
-	    } 
-	}
-	PRINTK(("\n"));
-    }
-
-    if (rom_found == 1)
-    {
-	PRINTK(("## %s: Boot_ROM found at %#08x\n", 
-               SK_NAME, rom_location[(i-1)]));
-
-	return (rom_location[--i]);
-    }
-    else
-    {
-	PRINTK(("%s: No Boot_ROM found\n", SK_NAME));
-	return 0;
-    }
-} /* End of SK_rom_addr() */
-
-
-
-/* LANCE access functions 
- *
- * ! CSR1-3 can only be accessed when in CSR0 the STOP bit is set !
- */
-
-
-/*-
- * Function       : SK_reset_board
- *
- * Author         : Patrick J.D. Weichmann
- *
- * Date Created   : 94/05/25
- *
- * Description    : This function resets SK_G16 and all components, but
- *                  POS registers are not changed
- *
- * Parameters     : None
- * Return Value   : None
- * Errors         : None
- * Globals        : SK_RAM *board - SK_RAM structure pointer
- *
- * Update History :
- *     YY/MM/DD  uid  Description
--*/
-
-void SK_reset_board(void)
-{
-    writeb(0x00, SK_PORT);       /* Reset active */
-    mdelay(5);                /* Delay min 5ms */
-    writeb(SK_RESET, SK_PORT);   /* Set back to normal operation */
-
-} /* End of SK_reset_board() */
-
-
-/*-
- * Function       : SK_set_RAP
- * Author         : Patrick J.D. Weichmann
- * Date Created   : 94/05/25
- *
- * Description    : Set LANCE Register Address Port to register
- *                  for later data transfer.
- *
- * Parameters     : I : reg_number - which CSR to read/write from/to
- * Return Value   : None
- * Errors         : None
- * Globals        : SK_RAM *board - SK_RAM structure pointer
- * Update History :
- *     YY/MM/DD  uid  Description
--*/
-
-void SK_set_RAP(int reg_number)
-{
-    writew(reg_number, SK_IOREG);
-    writeb(SK_RESET | SK_RAP | SK_WREG, SK_PORT);
-    writeb(SK_DOIO, SK_IOCOM);
-
-    while (readb(SK_PORT) & SK_IORUN) 
-	barrier();
-} /* End of SK_set_RAP() */
-
-
-/*-
- * Function       : SK_read_reg
- * Author         : Patrick J.D. Weichmann
- * Date Created   : 94/05/25
- *
- * Description    : Set RAP and read data from a LANCE CSR register
- *
- * Parameters     : I : reg_number - which CSR to read from
- * Return Value   : Register contents
- * Errors         : None
- * Globals        : SK_RAM *board - SK_RAM structure pointer
- * Update History :
- *     YY/MM/DD  uid  Description
--*/
-
-int SK_read_reg(int reg_number)
-{
-    SK_set_RAP(reg_number);
-
-    writeb(SK_RESET | SK_RDATA | SK_RREG, SK_PORT);
-    writeb(SK_DOIO, SK_IOCOM);
-
-    while (readb(SK_PORT) & SK_IORUN)
-	barrier();
-    return (readw(SK_IOREG));
-
-} /* End of SK_read_reg() */
-
-
-/*-
- * Function       : SK_rread_reg
- * Author         : Patrick J.D. Weichmann
- * Date Created   : 94/05/28
- *
- * Description    : Read data from preseted register.
- *                  This function requires that you know which
- *                  Register is actually set. Be aware that CSR1-3
- *                  can only be accessed when in CSR0 STOP is set.
- *
- * Return Value   : Register contents
- * Errors         : None
- * Globals        : SK_RAM *board - SK_RAM structure pointer
- * Update History :
- *     YY/MM/DD  uid  Description
--*/
-
-int SK_rread_reg(void)
-{
-    writeb(SK_RESET | SK_RDATA | SK_RREG, SK_PORT);
-
-    writeb(SK_DOIO, SK_IOCOM);
-
-    while (readb(SK_PORT) & SK_IORUN)
-	barrier();
-    return (readw(SK_IOREG));
-
-} /* End of SK_rread_reg() */
-
-
-/*-
- * Function       : SK_write_reg
- * Author         : Patrick J.D. Weichmann
- * Date Created   : 94/05/25
- *
- * Description    : This function sets the RAP then fills in the
- *                  LANCE I/O Reg and starts Transfer to LANCE.
- *                  It waits until transfer has ended which is max. 7 ms
- *                  and then it returns.
- *
- * Parameters     : I : reg_number - which CSR to write to
- *                  I : value      - what value to fill into register 
- * Return Value   : None
- * Errors         : None
- * Globals        : SK_RAM *board - SK_RAM structure pointer
- * Update History :
- *     YY/MM/DD  uid  Description
--*/
-
-void SK_write_reg(int reg_number, int value)
-{
-    SK_set_RAP(reg_number);
-
-    writew(value, SK_IOREG);
-    writeb(SK_RESET | SK_RDATA | SK_WREG, SK_PORT);
-    writeb(SK_DOIO, SK_IOCOM);
-
-    while (readb(SK_PORT) & SK_IORUN)
-	barrier();
-} /* End of SK_write_reg */
-
-
-
-/* 
- * Debugging functions
- * -------------------
- */
-
-/*-
- * Function       : SK_print_pos
- * Author         : Patrick J.D. Weichmann
- * Date Created   : 94/05/25
- *
- * Description    : This function prints out the 4 POS (Programmable
- *                  Option Select) Registers. Used mainly to debug operation.
- *
- * Parameters     : I : struct net_device *dev - SK_G16 device structure
- *                  I : char * - Text which will be printed as title
- * Return Value   : None
- * Errors         : None
- * Update History :
- *     YY/MM/DD  uid  Description
--*/
-
-void SK_print_pos(struct net_device *dev, char *text)
-{
-    int ioaddr = dev->base_addr;
-
-    unsigned char pos0 = inb(SK_POS0),
-		  pos1 = inb(SK_POS1),
-		  pos2 = inb(SK_POS2),
-		  pos3 = inb(SK_POS3),
-		  pos4 = inb(SK_POS4);
-
-
-    printk("## %s: %s.\n"
-           "##   pos0=%#4x pos1=%#4x pos2=%#04x pos3=%#08x pos4=%#04x\n",
-           SK_NAME, text, pos0, pos1, pos2, (pos3<<14), pos4);
-
-} /* End of SK_print_pos() */
-
-
-
-/*-
- * Function       : SK_print_dev
- * Author         : Patrick J.D. Weichmann
- * Date Created   : 94/05/25
- *
- * Description    : This function simply prints out the important fields
- *                  of the device structure.
- *
- * Parameters     : I : struct net_device *dev  - SK_G16 device structure
- *                  I : char *text - Title for printing
- * Return Value   : None
- * Errors         : None
- * Update History :
- *     YY/MM/DD  uid  Description
--*/
-
-void SK_print_dev(struct net_device *dev, char *text)
-{
-    if (dev == NULL)
-    {
-	printk("## %s: Device Structure. %s\n", SK_NAME, text);
-	printk("## DEVICE == NULL\n");
-    }
-    else
-    {
-	printk("## %s: Device Structure. %s\n", SK_NAME, text);
-	printk("## Device Name: %s Base Address: %#06lx IRQ: %d\n", 
-               dev->name, dev->base_addr, dev->irq);
-	       
-	printk("## next device: %#08x init function: %#08x\n", 
-              (int) dev->next, (int) dev->init);
-    }
-
-} /* End of SK_print_dev() */
-
-
-
-/*-
- * Function       : SK_print_ram
- * Author         : Patrick J.D. Weichmann
- * Date Created   : 94/06/02
- *
- * Description    : This function is used to check how are things set up
- *                  in the 16KB RAM. Also the pointers to the receive and 
- *                  transmit descriptor rings and rx and tx buffers locations.
- *                  It contains a minor bug in printing, but has no effect to the values
- *                  only newlines are not correct.
- *
- * Parameters     : I : struct net_device *dev - SK_G16 device structure
- * Return Value   : None
- * Errors         : None
- * Globals        : None
- * Update History :
- *     YY/MM/DD  uid  Description
--*/
-
-void __init SK_print_ram(struct net_device *dev)
-{
-
-    int i;    
-    struct priv *p = netdev_priv(dev);
-
-    printk("## %s: RAM Details.\n"
-           "##   RAM at %#08x tmdhead: %#08x rmdhead: %#08x initblock: %#08x\n",
-           SK_NAME, 
-           (unsigned int) p->ram,
-           (unsigned int) p->tmdhead, 
-           (unsigned int) p->rmdhead, 
-           (unsigned int) &(p->ram)->ib);
-           
-    printk("##   ");
-
-    for(i = 0; i < TMDNUM; i++)
-    {
-           if (!(i % 3)) /* Every third line do a newline */
-           {
-               printk("\n##   ");
-           }
-        printk("tmdbufs%d: %#08x ", (i+1), (int) p->tmdbufs[i]);
-    }
-    printk("##   ");
-
-    for(i = 0; i < RMDNUM; i++)
-    {
-         if (!(i % 3)) /* Every third line do a newline */
-           {
-               printk("\n##   ");
-           }
-        printk("rmdbufs%d: %#08x ", (i+1), (int) p->rmdbufs[i]);
-    } 
-    printk("\n");
-
-} /* End of SK_print_ram() */
-
diff --git a/drivers/net/sk_g16.h b/drivers/net/sk_g16.h
deleted file mode 100644
index 0a5dc09..0000000
--- a/drivers/net/sk_g16.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/*-
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * Module         : sk_g16.h
- * Version        : $Revision$  
- *
- * Author         : M.Hipp (mhipp@student.uni-tuebingen.de)
- * changes by     : Patrick J.D. Weichmann
- *
- * Date Created   : 94/05/25
- *
- * Description    : In here are all necessary definitions of  
- *                  the am7990 (LANCE) chip used for writing a
- *                  network device driver which uses this chip 
- *
- * $Log$
--*/
-
-#ifndef SK_G16_H
-
-#define SK_G16_H
-
-
-/*
- * 	Control and Status Register 0 (CSR0) bit definitions
- *
- * (R=Readable) (W=Writeable) (S=Set on write) (C-Clear on write)
- *
- */
-
-#define CSR0_ERR	0x8000	/* Error summary (R) */
-#define CSR0_BABL	0x4000	/* Babble transmitter timeout error (RC) */
-#define CSR0_CERR	0x2000	/* Collision Error (RC) */
-#define CSR0_MISS	0x1000	/* Missed packet (RC) */
-#define CSR0_MERR	0x0800	/* Memory Error  (RC) */ 
-#define CSR0_RINT	0x0400	/* Receiver Interrupt (RC) */
-#define CSR0_TINT       0x0200	/* Transmit Interrupt (RC) */ 
-#define CSR0_IDON	0x0100	/* Initialization Done (RC) */
-#define CSR0_INTR	0x0080	/* Interrupt Flag (R) */
-#define CSR0_INEA	0x0040	/* Interrupt Enable (RW) */
-#define CSR0_RXON	0x0020	/* Receiver on (R) */
-#define CSR0_TXON	0x0010  /* Transmitter on (R) */
-#define CSR0_TDMD	0x0008	/* Transmit Demand (RS) */
-#define CSR0_STOP	0x0004 	/* Stop (RS) */
-#define CSR0_STRT	0x0002	/* Start (RS) */
-#define CSR0_INIT	0x0001	/* Initialize (RS) */
-
-#define CSR0_CLRALL     0x7f00  /* mask for all clearable bits */
-
-/*
- *    Control and Status Register 3 (CSR3) bit definitions
- *
- */
-
-#define CSR3_BSWAP	0x0004	/* Byte Swap (RW) */
-#define CSR3_ACON	0x0002  /* ALE Control (RW) */
-#define CSR3_BCON	0x0001	/* Byte Control (RW) */
-
-/*
- *	Initialization Block Mode operation Bit Definitions.
- */
-
-#define MODE_PROM	0x8000	/* Promiscuous Mode */
-#define MODE_INTL	0x0040  /* Internal Loopback */
-#define MODE_DRTY	0x0020  /* Disable Retry */ 
-#define MODE_COLL	0x0010	/* Force Collision */
-#define MODE_DTCR	0x0008	/* Disable Transmit CRC) */
-#define MODE_LOOP	0x0004	/* Loopback */
-#define MODE_DTX	0x0002	/* Disable the Transmitter */ 
-#define MODE_DRX	0x0001  /* Disable the Receiver */
-
-#define MODE_NORMAL 	0x0000  /* Normal operation mode */
-
-/*
- * 	Receive message descriptor status bit definitions.
- */
-
-#define RX_OWN		0x80	/* Owner bit 0 = host, 1 = lance */
-#define RX_ERR		0x40	/* Error Summary */
-#define RX_FRAM		0x20	/* Framing Error */
-#define RX_OFLO		0x10	/* Overflow Error */
-#define RX_CRC		0x08	/* CRC Error */ 
-#define RX_BUFF		0x04	/* Buffer Error */
-#define RX_STP		0x02	/* Start of Packet */
-#define RX_ENP		0x01	/* End of Packet */
-
-
-/*
- *	Transmit message descriptor status bit definitions.
- */
-
-#define TX_OWN		0x80	/* Owner bit 0 = host, 1 = lance */
-#define TX_ERR		0x40    /* Error Summary */
-#define TX_MORE		0x10	/* More the 1 retry needed to Xmit */
-#define TX_ONE		0x08	/* One retry needed to Xmit */
-#define TX_DEF		0x04	/* Deferred */
-#define TX_STP 		0x02	/* Start of Packet */
-#define TX_ENP		0x01	/* End of Packet */
-
-/*
- *      Transmit status (2) (valid if TX_ERR == 1)
- */
-
-#define TX_BUFF 	0x8000  /* Buffering error (no ENP) */
-#define TX_UFLO 	0x4000  /* Underflow (late memory) */
-#define TX_LCOL 	0x1000  /* Late collision */
-#define TX_LCAR 	0x0400  /* Loss of Carrier */
-#define TX_RTRY 	0x0200  /* Failed after 16 retransmissions  */
-#define TX_TDR          0x003f  /* Time-domain-reflectometer-value */
-
-
-/* 
- * Structures used for Communication with the LANCE 
- */
-
-/* LANCE Initialize Block */
-
-struct init_block 
-{
-  unsigned short mode;     /* Mode Register */
-  unsigned char  paddr[6]; /* Physical Address (MAC) */
-  unsigned char  laddr[8]; /* Logical Filter Address (not used) */
-  unsigned int   rdrp;     /* Receive Descriptor Ring pointer */
-  unsigned int   tdrp;     /* Transmit Descriptor Ring pointer */
-};
-
-
-/* Receive Message Descriptor Entry */
-
-struct rmd 
-{ 
-  union
-  {
-    unsigned long buffer;     /* Address of buffer */
-    struct 
-    {
-      unsigned char unused[3]; 
-      unsigned volatile char status;   /* Status Bits */
-    } s;
-  } u;
-  volatile short blen;        /* Buffer Length (two's complement) */
-  unsigned short mlen;        /* Message Byte Count */
-};
-
-
-/* Transmit Message Descriptor Entry */
-
-struct tmd   
-{
-  union 
-  {
-    unsigned long  buffer;    /* Address of buffer */
-    struct 
-    {
-      unsigned char unused[3];
-      unsigned volatile char status;   /* Status Bits */
-    } s;
-  } u;
-  unsigned short blen;             /* Buffer Length (two's complement) */
-  unsigned volatile short status2; /* Error Status Bits */
-};
-
-#endif /* End of SK_G16_H */
diff --git a/drivers/net/skfp/Makefile b/drivers/net/skfp/Makefile
index 6cfccfb..5f4bb1a 100644
--- a/drivers/net/skfp/Makefile
+++ b/drivers/net/skfp/Makefile
@@ -6,8 +6,8 @@
 
 skfp-objs :=  skfddi.o    hwmtm.o    fplustm.o  smt.o      cfm.o     \
               ecm.o       pcmplc.o   pmf.o      queue.o    rmt.o     \
-	      smtdef.o    smtinit.o  smttimer.o srf.o      lnkstat.o \
-              smtparse.o  hwt.o      drvfbi.o   ess.o
+	      smtdef.o    smtinit.o  smttimer.o srf.o      smtparse.o\
+	      hwt.o      drvfbi.o   ess.o
 
 # NOTE:
 #   Compiling this driver produces some warnings (and some more are 
diff --git a/drivers/net/skfp/h/osdef1st.h b/drivers/net/skfp/h/osdef1st.h
index 5359eb5..763ca18 100644
--- a/drivers/net/skfp/h/osdef1st.h
+++ b/drivers/net/skfp/h/osdef1st.h
@@ -20,6 +20,8 @@
 // HWM (HardWare Module) Definitions
 // -----------------------
 
+#include <asm/byteorder.h>
+
 #ifdef __LITTLE_ENDIAN
 #define LITTLE_ENDIAN
 #else
diff --git a/drivers/net/skfp/lnkstat.c b/drivers/net/skfp/lnkstat.c
deleted file mode 100644
index 00a2480..0000000
--- a/drivers/net/skfp/lnkstat.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/******************************************************************************
- *
- *	(C)Copyright 1998,1999 SysKonnect,
- *	a business unit of Schneider & Koch & Co. Datensysteme GmbH.
- *
- *	See the file "skfddi.c" for further information.
- *
- *	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.
- *
- *	The information in this file is provided "AS IS" without warranty.
- *
- ******************************************************************************/
-
-/*
-	IBM FDDI read error log function
-*/
-
-#include "h/types.h"
-#include "h/fddi.h"
-#include "h/smc.h"
-#include "h/lnkstat.h"
-
-#ifndef	lint
-static const char ID_sccs[] = "@(#)lnkstat.c	1.8 97/04/11 (C) SK " ;
-#endif
-
-#ifdef	sun
-#define _far
-#endif
-
-#define EL_IS_OK(x,l)	((((int)&(((struct s_error_log *)0)->x)) + \
-			sizeof(er->x)) <= l)
-
-/*
-	BEGIN_MANUAL_ENTRY(if,func;others;11)
-
-	u_long smt_get_error_word(smc)
-	struct s_smc *smc ;
-
-Function	DOWNCALL	(SMT, lnkstat.c)
-		This functions returns the SMT error work for AIX events.
-
-Return	smt_error_word	These bits are supported:
-
-		SMT_ERL_ALC	== 	[PS/PA].fddiPORTLerFlag
-		SMT_ERL_BLC	==	[PB].fddiPORTLerFlag
-		SMT_ERL_NCC	==	fddiMACNotCopiedFlag
-		SMT_ERL_FEC	==	fddiMACFrameErrorFlag
-
-	END_MANUAL_ENTRY()
- */
-u_long smt_get_error_word(struct s_smc *smc)
-{
-	u_long	st;
-
-	/*
-	 * smt error word low
-	 */
-	st = 0 ;
-	if (smc->s.sas == SMT_SAS) {
-		if (smc->mib.p[PS].fddiPORTLerFlag)
-			st |= SMT_ERL_ALC ;
-	}
-	else {
-		if (smc->mib.p[PA].fddiPORTLerFlag)
-			st |= SMT_ERL_ALC ;
-		if (smc->mib.p[PB].fddiPORTLerFlag)
-			st |= SMT_ERL_BLC ;
-	}
-	if (smc->mib.m[MAC0].fddiMACNotCopiedFlag)
-		st |= SMT_ERL_NCC ;		/* not copied condition */
-	if (smc->mib.m[MAC0].fddiMACFrameErrorFlag)
-		st |= SMT_ERL_FEC ;		/* frame error condition */
-
-	return st;
-}
-
-/*
-	BEGIN_MANUAL_ENTRY(if,func;others;11)
-
-	u_long smt_get_event_word(smc)
-	struct s_smc *smc ;
-
-Function	DOWNCALL	(SMT, lnkstat.c)
-		This functions returns the SMT event work for AIX events.
-
-Return	smt_event_word	always 0
-
-	END_MANUAL_ENTRY()
- */
-u_long smt_get_event_word(struct s_smc *smc)
-{
-	return (u_long) 0;
-}
-
-/*
-	BEGIN_MANUAL_ENTRY(if,func;others;11)
-
-	u_long smt_get_port_event_word(smc)
-	struct s_smc *smc ;
-
-Function	DOWNCALL	(SMT, lnkstat.c)
-		This functions returns the SMT port event work for AIX events.
-
-Return	smt_port_event_word	always 0
-
-	END_MANUAL_ENTRY()
- */
-u_long smt_get_port_event_word(struct s_smc *smc)
-{
-	return (u_long) 0;
-}
-
-/*
-	BEGIN_MANUAL_ENTRY(if,func;others;11)
-
-	u_long smt_read_errorlog(smc,p,len)
-	struct s_smc *smc ;
-	char _far *p ;
-	int len ;
-
-Function	DOWNCALL	(SMT, lnkstat.c)
-		This functions returns the SMT error log field for AIX events.
-
-Para	p	pointer to the error log field
-	len	len of the error log field
-
-Return	len	used len of the error log field
-
-	END_MANUAL_ENTRY()
- */
-int smt_read_errorlog(struct s_smc *smc, char _far *p, int len)
-{
-	int			i ;
-	int			st ;
-	struct s_error_log _far	*er ;
-
-	er = (struct s_error_log _far *) p ;
-	if (len > sizeof(struct s_error_log))
-		len = sizeof(struct s_error_log) ;
-	for (i = 0 ; i < len ; i++)
-		*p++ = 0 ;
-	/*
-	 * set count
-	 */
-	if (EL_IS_OK(set_count_high,len)) {
-		er->set_count_low = (u_short)smc->mib.fddiSMTSetCount.count ;
-		er->set_count_high =
-			(u_short)(smc->mib.fddiSMTSetCount.count >> 16L) ;
-	}
-	/*
-	 * aci
-	 */
-	if (EL_IS_OK(aci_id_code,len)) {
-		er->aci_id_code = 0 ;
-	}
-	/*
-	 * purge counter is missed frames; 16 bits only
-	 */
-	if (EL_IS_OK(purge_frame_counter,len)) {
-		if (smc->mib.m[MAC0].fddiMACCopied_Ct > 0xffff)
-			er->purge_frame_counter = 0xffff ;
-		else
-			er->purge_frame_counter =
-				(u_short)smc->mib.m[MAC0].fddiMACCopied_Ct ;
-	}
-	/*
-	 * CMT and RMT state machines
-	 */
-	if (EL_IS_OK(ecm_state,len))
-		er->ecm_state = smc->mib.fddiSMTECMState ;
-
-	if (EL_IS_OK(pcm_b_state,len)) {
-		if (smc->s.sas == SMT_SAS) {
-			er->pcm_a_state = smc->y[PS].mib->fddiPORTPCMState ;
-			er->pcm_b_state = 0 ;
-		}
-		else {
-			er->pcm_a_state = smc->y[PA].mib->fddiPORTPCMState ;
-			er->pcm_b_state = smc->y[PB].mib->fddiPORTPCMState ;
-		}
-	}
-	if (EL_IS_OK(cfm_state,len))
-		er->cfm_state = smc->mib.fddiSMTCF_State ;
-	if (EL_IS_OK(rmt_state,len))
-		er->rmt_state = smc->mib.m[MAC0].fddiMACRMTState ;
-
-	/*
-	 * smt error word low (we only need the low order 16 bits.)
-	 */
-
-	st = smt_get_error_word(smc) & 0xffff ;
-
-	if (EL_IS_OK(smt_error_low,len))
-		er->smt_error_low = st ;
-
-	if (EL_IS_OK(ucode_version_level,len))
-		er->ucode_version_level = 0x0101 ;
-	return(len) ;
-}
-
diff --git a/drivers/net/skfp/smt.c b/drivers/net/skfp/smt.c
index 71935ea..c3a0d2f 100644
--- a/drivers/net/skfp/smt.c
+++ b/drivers/net/skfp/smt.c
@@ -86,7 +86,7 @@
 static void smt_send_sif_operation(struct s_smc *smc, struct fddi_addr *dest,
 				   u_long tid, int local);
 #ifdef LITTLE_ENDIAN
-static void smt_string_swap(void);
+static void smt_string_swap(char *data, const char *format, int len);
 #endif
 static void smt_add_frame_len(SMbuf *mb, int len);
 static void smt_fill_una(struct s_smc *smc, struct smt_p_una *una);
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
new file mode 100644
index 0000000..30e8d58
--- /dev/null
+++ b/drivers/net/skge.c
@@ -0,0 +1,3386 @@
+/*
+ * New driver for Marvell Yukon chipset and SysKonnect Gigabit
+ * Ethernet adapters. Based on earlier sk98lin, e100 and
+ * FreeBSD if_sk drivers.
+ *
+ * This driver intentionally does not support all the features
+ * of the original driver such as link fail-over and link management because
+ * those should be done at higher levels.
+ *
+ * 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/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/pci.h>
+#include <linux/if_vlan.h>
+#include <linux/ip.h>
+#include <linux/delay.h>
+#include <linux/crc32.h>
+#include <linux/dma-mapping.h>
+#include <asm/irq.h>
+
+#include "skge.h"
+
+#define DRV_NAME		"skge"
+#define DRV_VERSION		"0.6"
+#define PFX			DRV_NAME " "
+
+#define DEFAULT_TX_RING_SIZE	128
+#define DEFAULT_RX_RING_SIZE	512
+#define MAX_TX_RING_SIZE	1024
+#define MAX_RX_RING_SIZE	4096
+#define PHY_RETRIES	        1000
+#define ETH_JUMBO_MTU		9000
+#define TX_WATCHDOG		(5 * HZ)
+#define NAPI_WEIGHT		64
+#define BLINK_HZ		(HZ/4)
+#define LINK_POLL_HZ		(HZ/10)
+
+MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver");
+MODULE_AUTHOR("Stephen Hemminger <shemminger@osdl.org>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+static const u32 default_msg
+	= NETIF_MSG_DRV| NETIF_MSG_PROBE| NETIF_MSG_LINK
+	  | NETIF_MSG_IFUP| NETIF_MSG_IFDOWN;
+
+static int debug = -1;	/* defaults above */
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
+static const struct pci_device_id skge_id_table[] = {
+	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940,
+	  PCI_ANY_ID, PCI_ANY_ID },
+	{ PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C940B,
+	  PCI_ANY_ID, PCI_ANY_ID },
+	{ PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE,
+	  PCI_ANY_ID, PCI_ANY_ID },
+	{ PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU,
+	  PCI_ANY_ID, PCI_ANY_ID },
+	{ PCI_VENDOR_ID_SYSKONNECT, 0x9E00, /* SK-9Exx  */
+	  PCI_ANY_ID, PCI_ANY_ID },
+	{ PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T,
+	  PCI_ANY_ID, PCI_ANY_ID },
+	{ PCI_VENDOR_ID_MARVELL, 0x4320, /* Gigabit Ethernet Controller */
+	  PCI_ANY_ID, PCI_ANY_ID },
+	{ PCI_VENDOR_ID_MARVELL, 0x5005, /* Marvell (11ab), Belkin */
+	  PCI_ANY_ID, PCI_ANY_ID },
+	{ PCI_VENDOR_ID_CNET, PCI_DEVICE_ID_CNET_GIGACARD,
+	  PCI_ANY_ID, PCI_ANY_ID },
+	{ PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1032,
+	  PCI_ANY_ID, PCI_ANY_ID },
+	{ PCI_VENDOR_ID_LINKSYS, PCI_DEVICE_ID_LINKSYS_EG1064,
+	  PCI_ANY_ID, PCI_ANY_ID },
+	{ 0 }
+};
+MODULE_DEVICE_TABLE(pci, skge_id_table);
+
+static int skge_up(struct net_device *dev);
+static int skge_down(struct net_device *dev);
+static void skge_tx_clean(struct skge_port *skge);
+static void skge_xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
+static void skge_gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val);
+static void genesis_get_stats(struct skge_port *skge, u64 *data);
+static void yukon_get_stats(struct skge_port *skge, u64 *data);
+static void yukon_init(struct skge_hw *hw, int port);
+static void yukon_reset(struct skge_hw *hw, int port);
+static void genesis_mac_init(struct skge_hw *hw, int port);
+static void genesis_reset(struct skge_hw *hw, int port);
+
+static const int txqaddr[] = { Q_XA1, Q_XA2 };
+static const int rxqaddr[] = { Q_R1, Q_R2 };
+static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F };
+static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F };
+
+/* Don't need to look at whole 16K.
+ * last interesting register is descriptor poll timer.
+ */
+#define SKGE_REGS_LEN	(29*128)
+
+static int skge_get_regs_len(struct net_device *dev)
+{
+	return SKGE_REGS_LEN;
+}
+
+/*
+ * Returns copy of control register region
+ * I/O region is divided into banks and certain regions are unreadable
+ */
+static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+			  void *p)
+{
+	const struct skge_port *skge = netdev_priv(dev);
+	unsigned long offs;
+	const void __iomem *io = skge->hw->regs;
+	static const unsigned long bankmap
+		= (1<<0) | (1<<2) | (1<<8) | (1<<9)
+		  | (1<<12) | (1<<13) | (1<<14) | (1<<15) | (1<<16)
+		  | (1<<17) | (1<<20) | (1<<21) | (1<<22) | (1<<23)
+		  | (1<<24)  | (1<<25) | (1<<26) | (1<<27) | (1<<28);
+
+	regs->version = 1;
+	for (offs = 0; offs < regs->len; offs += 128) {
+		u32 len = min_t(u32, 128, regs->len - offs);
+
+		if (bankmap & (1<<(offs/128)))
+			memcpy_fromio(p + offs, io + offs, len);
+		else
+			memset(p + offs, 0, len);
+	}
+}
+
+/* Wake on Lan only supported on Yukon chps with rev 1 or above */
+static int wol_supported(const struct skge_hw *hw)
+{
+	return !((hw->chip_id == CHIP_ID_GENESIS ||
+		  (hw->chip_id == CHIP_ID_YUKON && chip_rev(hw) == 0)));
+}
+
+static void skge_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct skge_port *skge = netdev_priv(dev);
+
+	wol->supported = wol_supported(skge->hw) ? WAKE_MAGIC : 0;
+	wol->wolopts = skge->wol ? WAKE_MAGIC : 0;
+}
+
+static int skge_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct skge_port *skge = netdev_priv(dev);
+	struct skge_hw *hw = skge->hw;
+
+	if(wol->wolopts != WAKE_MAGIC && wol->wolopts != 0)
+		return -EOPNOTSUPP;
+
+	if (wol->wolopts == WAKE_MAGIC && !wol_supported(hw))
+		return -EOPNOTSUPP;
+
+	skge->wol = wol->wolopts == WAKE_MAGIC;
+
+	if (skge->wol) {
+		memcpy_toio(hw->regs + WOL_MAC_ADDR, dev->dev_addr, ETH_ALEN);
+
+		skge_write16(hw, WOL_CTRL_STAT,
+			     WOL_CTL_ENA_PME_ON_MAGIC_PKT |
+			     WOL_CTL_ENA_MAGIC_PKT_UNIT);
+	} else
+		skge_write16(hw, WOL_CTRL_STAT, WOL_CTL_DEFAULT);
+
+	return 0;
+}
+
+
+static int skge_get_settings(struct net_device *dev,
+			     struct ethtool_cmd *ecmd)
+{
+	struct skge_port *skge = netdev_priv(dev);
+	struct skge_hw *hw = skge->hw;
+
+	ecmd->transceiver = XCVR_INTERNAL;
+
+	if (iscopper(hw)) {
+		if (hw->chip_id == CHIP_ID_GENESIS)
+			ecmd->supported = SUPPORTED_1000baseT_Full
+				| SUPPORTED_1000baseT_Half
+				| SUPPORTED_Autoneg | SUPPORTED_TP;
+		else {
+			ecmd->supported = SUPPORTED_10baseT_Half
+				| SUPPORTED_10baseT_Full
+				| SUPPORTED_100baseT_Half
+				| SUPPORTED_100baseT_Full
+				| SUPPORTED_1000baseT_Half
+				| SUPPORTED_1000baseT_Full
+				| SUPPORTED_Autoneg| SUPPORTED_TP;
+
+			if (hw->chip_id == CHIP_ID_YUKON)
+				ecmd->supported &= ~SUPPORTED_1000baseT_Half;
+
+			else if (hw->chip_id == CHIP_ID_YUKON_FE)
+				ecmd->supported &= ~(SUPPORTED_1000baseT_Half
+						     | SUPPORTED_1000baseT_Full);
+		}
+
+		ecmd->port = PORT_TP;
+		ecmd->phy_address = hw->phy_addr;
+	} else {
+		ecmd->supported = SUPPORTED_1000baseT_Full
+			| SUPPORTED_FIBRE
+			| SUPPORTED_Autoneg;
+
+		ecmd->port = PORT_FIBRE;
+	}
+
+	ecmd->advertising = skge->advertising;
+	ecmd->autoneg = skge->autoneg;
+	ecmd->speed = skge->speed;
+	ecmd->duplex = skge->duplex;
+	return 0;
+}
+
+static u32 skge_modes(const struct skge_hw *hw)
+{
+	u32 modes = ADVERTISED_Autoneg
+		| ADVERTISED_1000baseT_Full | ADVERTISED_1000baseT_Half
+		| ADVERTISED_100baseT_Full | ADVERTISED_100baseT_Half
+		| ADVERTISED_10baseT_Full | ADVERTISED_10baseT_Half;
+
+	if (iscopper(hw)) {
+		modes |= ADVERTISED_TP;
+		switch(hw->chip_id) {
+		case CHIP_ID_GENESIS:
+			modes &= ~(ADVERTISED_100baseT_Full
+				   | ADVERTISED_100baseT_Half
+				   | ADVERTISED_10baseT_Full
+				   | ADVERTISED_10baseT_Half);
+			break;
+
+		case CHIP_ID_YUKON:
+			modes &= ~ADVERTISED_1000baseT_Half;
+			break;
+
+		case CHIP_ID_YUKON_FE:
+			modes &= ~(ADVERTISED_1000baseT_Half|ADVERTISED_1000baseT_Full);
+			break;
+		}
+	} else {
+		modes |= ADVERTISED_FIBRE;
+		modes &= ~ADVERTISED_1000baseT_Half;
+	}
+	return modes;
+}
+
+static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	struct skge_port *skge = netdev_priv(dev);
+	const struct skge_hw *hw = skge->hw;
+
+	if (ecmd->autoneg == AUTONEG_ENABLE) {
+		if (ecmd->advertising & skge_modes(hw))
+			return -EINVAL;
+	} else {
+		switch(ecmd->speed) {
+		case SPEED_1000:
+			if (hw->chip_id == CHIP_ID_YUKON_FE)
+				return -EINVAL;
+			break;
+		case SPEED_100:
+		case SPEED_10:
+			if (iscopper(hw) || hw->chip_id == CHIP_ID_GENESIS)
+				return -EINVAL;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	skge->autoneg = ecmd->autoneg;
+	skge->speed = ecmd->speed;
+	skge->duplex = ecmd->duplex;
+	skge->advertising = ecmd->advertising;
+
+	if (netif_running(dev)) {
+		skge_down(dev);
+		skge_up(dev);
+	}
+	return (0);
+}
+
+static void skge_get_drvinfo(struct net_device *dev,
+			     struct ethtool_drvinfo *info)
+{
+	struct skge_port *skge = netdev_priv(dev);
+
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->fw_version, "N/A");
+	strcpy(info->bus_info, pci_name(skge->hw->pdev));
+}
+
+static const struct skge_stat {
+	char 	   name[ETH_GSTRING_LEN];
+	u16	   xmac_offset;
+	u16	   gma_offset;
+} skge_stats[] = {
+	{ "tx_bytes",		XM_TXO_OK_HI,  GM_TXO_OK_HI },
+	{ "rx_bytes",		XM_RXO_OK_HI,  GM_RXO_OK_HI },
+
+	{ "tx_broadcast",	XM_TXF_BC_OK,  GM_TXF_BC_OK },
+	{ "rx_broadcast",	XM_RXF_BC_OK,  GM_RXF_BC_OK },
+	{ "tx_multicast",	XM_TXF_MC_OK,  GM_TXF_MC_OK },
+	{ "rx_multicast",	XM_RXF_MC_OK,  GM_RXF_MC_OK },
+	{ "tx_unicast",		XM_TXF_UC_OK,  GM_TXF_UC_OK },
+	{ "rx_unicast",		XM_RXF_UC_OK,  GM_RXF_UC_OK },
+	{ "tx_mac_pause",	XM_TXF_MPAUSE, GM_TXF_MPAUSE },
+	{ "rx_mac_pause",	XM_RXF_MPAUSE, GM_RXF_MPAUSE },
+
+	{ "collisions",		XM_TXF_SNG_COL, GM_TXF_SNG_COL },
+	{ "multi_collisions",	XM_TXF_MUL_COL, GM_TXF_MUL_COL },
+	{ "aborted",		XM_TXF_ABO_COL, GM_TXF_ABO_COL },
+	{ "late_collision",	XM_TXF_LAT_COL, GM_TXF_LAT_COL },
+	{ "fifo_underrun",	XM_TXE_FIFO_UR, GM_TXE_FIFO_UR },
+	{ "fifo_overflow",	XM_RXE_FIFO_OV, GM_RXE_FIFO_OV },
+
+	{ "rx_toolong",		XM_RXF_LNG_ERR, GM_RXF_LNG_ERR },
+	{ "rx_jabber",		XM_RXF_JAB_PKT, GM_RXF_JAB_PKT },
+	{ "rx_runt",		XM_RXE_RUNT, 	GM_RXE_FRAG },
+	{ "rx_too_long",	XM_RXF_LNG_ERR, GM_RXF_LNG_ERR },
+	{ "rx_fcs_error",	XM_RXF_FCS_ERR, GM_RXF_FCS_ERR },
+};
+
+static int skge_get_stats_count(struct net_device *dev)
+{
+	return ARRAY_SIZE(skge_stats);
+}
+
+static void skge_get_ethtool_stats(struct net_device *dev,
+				   struct ethtool_stats *stats, u64 *data)
+{
+	struct skge_port *skge = netdev_priv(dev);
+
+	if (skge->hw->chip_id == CHIP_ID_GENESIS)
+		genesis_get_stats(skge, data);
+	else
+		yukon_get_stats(skge, data);
+}
+
+/* Use hardware MIB variables for critical path statistics and
+ * transmit feedback not reported at interrupt.
+ * Other errors are accounted for in interrupt handler.
+ */
+static struct net_device_stats *skge_get_stats(struct net_device *dev)
+{
+	struct skge_port *skge = netdev_priv(dev);
+	u64 data[ARRAY_SIZE(skge_stats)];
+
+	if (skge->hw->chip_id == CHIP_ID_GENESIS)
+		genesis_get_stats(skge, data);
+	else
+		yukon_get_stats(skge, data);
+
+	skge->net_stats.tx_bytes = data[0];
+	skge->net_stats.rx_bytes = data[1];
+	skge->net_stats.tx_packets = data[2] + data[4] + data[6];
+	skge->net_stats.rx_packets = data[3] + data[5] + data[7];
+	skge->net_stats.multicast = data[5] + data[7];
+	skge->net_stats.collisions = data[10];
+	skge->net_stats.tx_aborted_errors = data[12];
+
+	return &skge->net_stats;
+}
+
+static void skge_get_strings(struct net_device *dev, u32 stringset, u8 *data)
+{
+	int i;
+
+	switch(stringset) {
+	case ETH_SS_STATS:
+		for (i = 0; i < ARRAY_SIZE(skge_stats); i++)
+			memcpy(data + i * ETH_GSTRING_LEN,
+			       skge_stats[i].name, ETH_GSTRING_LEN);
+		break;
+	}
+}
+
+static void skge_get_ring_param(struct net_device *dev,
+				struct ethtool_ringparam *p)
+{
+	struct skge_port *skge = netdev_priv(dev);
+
+	p->rx_max_pending = MAX_RX_RING_SIZE;
+	p->tx_max_pending = MAX_TX_RING_SIZE;
+	p->rx_mini_max_pending = 0;
+	p->rx_jumbo_max_pending = 0;
+
+	p->rx_pending = skge->rx_ring.count;
+	p->tx_pending = skge->tx_ring.count;
+	p->rx_mini_pending = 0;
+	p->rx_jumbo_pending = 0;
+}
+
+static int skge_set_ring_param(struct net_device *dev,
+			       struct ethtool_ringparam *p)
+{
+	struct skge_port *skge = netdev_priv(dev);
+
+	if (p->rx_pending == 0 || p->rx_pending > MAX_RX_RING_SIZE ||
+	    p->tx_pending == 0 || p->tx_pending > MAX_TX_RING_SIZE)
+		return -EINVAL;
+
+	skge->rx_ring.count = p->rx_pending;
+	skge->tx_ring.count = p->tx_pending;
+
+	if (netif_running(dev)) {
+		skge_down(dev);
+		skge_up(dev);
+	}
+
+	return 0;
+}
+
+static u32 skge_get_msglevel(struct net_device *netdev)
+{
+	struct skge_port *skge = netdev_priv(netdev);
+	return skge->msg_enable;
+}
+
+static void skge_set_msglevel(struct net_device *netdev, u32 value)
+{
+	struct skge_port *skge = netdev_priv(netdev);
+	skge->msg_enable = value;
+}
+
+static int skge_nway_reset(struct net_device *dev)
+{
+	struct skge_port *skge = netdev_priv(dev);
+	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+
+	if (skge->autoneg != AUTONEG_ENABLE || !netif_running(dev))
+		return -EINVAL;
+
+	spin_lock_bh(&hw->phy_lock);
+	if (hw->chip_id == CHIP_ID_GENESIS) {
+		genesis_reset(hw, port);
+		genesis_mac_init(hw, port);
+	} else {
+		yukon_reset(hw, port);
+		yukon_init(hw, port);
+	}
+	spin_unlock_bh(&hw->phy_lock);
+	return 0;
+}
+
+static int skge_set_sg(struct net_device *dev, u32 data)
+{
+	struct skge_port *skge = netdev_priv(dev);
+	struct skge_hw *hw = skge->hw;
+
+	if (hw->chip_id == CHIP_ID_GENESIS && data)
+		return -EOPNOTSUPP;
+	return ethtool_op_set_sg(dev, data);
+}
+
+static int skge_set_tx_csum(struct net_device *dev, u32 data)
+{
+	struct skge_port *skge = netdev_priv(dev);
+	struct skge_hw *hw = skge->hw;
+
+	if (hw->chip_id == CHIP_ID_GENESIS && data)
+		return -EOPNOTSUPP;
+
+	return ethtool_op_set_tx_csum(dev, data);
+}
+
+static u32 skge_get_rx_csum(struct net_device *dev)
+{
+	struct skge_port *skge = netdev_priv(dev);
+
+	return skge->rx_csum;
+}
+
+/* Only Yukon supports checksum offload. */
+static int skge_set_rx_csum(struct net_device *dev, u32 data)
+{
+	struct skge_port *skge = netdev_priv(dev);
+
+	if (skge->hw->chip_id == CHIP_ID_GENESIS && data)
+		return -EOPNOTSUPP;
+
+	skge->rx_csum = data;
+	return 0;
+}
+
+/* Only Yukon II supports TSO (not implemented yet) */
+static int skge_set_tso(struct net_device *dev, u32 data)
+{
+	if (data)
+		return -EOPNOTSUPP;
+	return 0;
+}
+
+static void skge_get_pauseparam(struct net_device *dev,
+				struct ethtool_pauseparam *ecmd)
+{
+	struct skge_port *skge = netdev_priv(dev);
+
+	ecmd->tx_pause = (skge->flow_control == FLOW_MODE_LOC_SEND)
+		|| (skge->flow_control == FLOW_MODE_SYMMETRIC);
+	ecmd->rx_pause = (skge->flow_control == FLOW_MODE_REM_SEND)
+		|| (skge->flow_control == FLOW_MODE_SYMMETRIC);
+
+	ecmd->autoneg = skge->autoneg;
+}
+
+static int skge_set_pauseparam(struct net_device *dev,
+			       struct ethtool_pauseparam *ecmd)
+{
+	struct skge_port *skge = netdev_priv(dev);
+
+	skge->autoneg = ecmd->autoneg;
+	if (ecmd->rx_pause && ecmd->tx_pause)
+		skge->flow_control = FLOW_MODE_SYMMETRIC;
+	else if(ecmd->rx_pause && !ecmd->tx_pause)
+		skge->flow_control = FLOW_MODE_REM_SEND;
+	else if(!ecmd->rx_pause && ecmd->tx_pause)
+		skge->flow_control = FLOW_MODE_LOC_SEND;
+	else
+		skge->flow_control = FLOW_MODE_NONE;
+
+	if (netif_running(dev)) {
+		skge_down(dev);
+		skge_up(dev);
+	}
+	return 0;
+}
+
+/* Chip internal frequency for clock calculations */
+static inline u32 hwkhz(const struct skge_hw *hw)
+{
+	if (hw->chip_id == CHIP_ID_GENESIS)
+		return 53215; /* or:  53.125 MHz */
+	else if (hw->chip_id == CHIP_ID_YUKON_EC)
+		return 125000; /* or: 125.000 MHz */
+	else
+		return 78215; /* or:  78.125 MHz */
+}
+
+/* Chip hz to microseconds */
+static inline u32 skge_clk2usec(const struct skge_hw *hw, u32 ticks)
+{
+	return (ticks * 1000) / hwkhz(hw);
+}
+
+/* Microseconds to chip hz */
+static inline u32 skge_usecs2clk(const struct skge_hw *hw, u32 usec)
+{
+	return hwkhz(hw) * usec / 1000;
+}
+
+static int skge_get_coalesce(struct net_device *dev,
+			     struct ethtool_coalesce *ecmd)
+{
+	struct skge_port *skge = netdev_priv(dev);
+	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+
+	ecmd->rx_coalesce_usecs = 0;
+	ecmd->tx_coalesce_usecs = 0;
+
+	if (skge_read32(hw, B2_IRQM_CTRL) & TIM_START) {
+		u32 delay = skge_clk2usec(hw, skge_read32(hw, B2_IRQM_INI));
+		u32 msk = skge_read32(hw, B2_IRQM_MSK);
+
+		if (msk & rxirqmask[port])
+			ecmd->rx_coalesce_usecs = delay;
+		if (msk & txirqmask[port])
+			ecmd->tx_coalesce_usecs = delay;
+	}
+
+	return 0;
+}
+
+/* Note: interrupt timer is per board, but can turn on/off per port */
+static int skge_set_coalesce(struct net_device *dev,
+			     struct ethtool_coalesce *ecmd)
+{
+	struct skge_port *skge = netdev_priv(dev);
+	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+	u32 msk = skge_read32(hw, B2_IRQM_MSK);
+	u32 delay = 25;
+
+	if (ecmd->rx_coalesce_usecs == 0)
+		msk &= ~rxirqmask[port];
+	else if (ecmd->rx_coalesce_usecs < 25 ||
+		 ecmd->rx_coalesce_usecs > 33333)
+		return -EINVAL;
+	else {
+		msk |= rxirqmask[port];
+		delay = ecmd->rx_coalesce_usecs;
+	}
+
+	if (ecmd->tx_coalesce_usecs == 0)
+		msk &= ~txirqmask[port];
+	else if (ecmd->tx_coalesce_usecs < 25 ||
+		 ecmd->tx_coalesce_usecs > 33333)
+		return -EINVAL;
+	else {
+		msk |= txirqmask[port];
+		delay = min(delay, ecmd->rx_coalesce_usecs);
+	}
+
+	skge_write32(hw, B2_IRQM_MSK, msk);
+	if (msk == 0)
+		skge_write32(hw, B2_IRQM_CTRL, TIM_STOP);
+	else {
+		skge_write32(hw, B2_IRQM_INI, skge_usecs2clk(hw, delay));
+		skge_write32(hw, B2_IRQM_CTRL, TIM_START);
+	}
+	return 0;
+}
+
+static void skge_led_on(struct skge_hw *hw, int port)
+{
+	if (hw->chip_id == CHIP_ID_GENESIS) {
+		skge_write8(hw, SKGEMAC_REG(port, LNK_LED_REG), LINKLED_ON);
+		skge_write8(hw, B0_LED, LED_STAT_ON);
+
+		skge_write8(hw, SKGEMAC_REG(port, RX_LED_TST), LED_T_ON);
+		skge_write32(hw, SKGEMAC_REG(port, RX_LED_VAL), 100);
+		skge_write8(hw, SKGEMAC_REG(port, RX_LED_CTRL), LED_START);
+
+		switch (hw->phy_type) {
+		case SK_PHY_BCOM:
+			skge_xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL,
+					  PHY_B_PEC_LED_ON);
+			break;
+		case SK_PHY_LONE:
+			skge_xm_phy_write(hw, port, PHY_LONE_LED_CFG,
+					  0x0800);
+			break;
+		default:
+			skge_write8(hw, SKGEMAC_REG(port, TX_LED_TST), LED_T_ON);
+			skge_write32(hw, SKGEMAC_REG(port, TX_LED_VAL), 100);
+			skge_write8(hw, SKGEMAC_REG(port, TX_LED_CTRL), LED_START);
+		}
+	} else {
+		skge_gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
+		skge_gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+				  PHY_M_LED_MO_DUP(MO_LED_ON)  |
+				  PHY_M_LED_MO_10(MO_LED_ON)   |
+				  PHY_M_LED_MO_100(MO_LED_ON)  |
+				  PHY_M_LED_MO_1000(MO_LED_ON) |
+				  PHY_M_LED_MO_RX(MO_LED_ON));
+	}
+}
+
+static void skge_led_off(struct skge_hw *hw, int port)
+{
+	if (hw->chip_id == CHIP_ID_GENESIS) {
+		skge_write8(hw, SKGEMAC_REG(port, LNK_LED_REG), LINKLED_OFF);
+		skge_write8(hw, B0_LED, LED_STAT_OFF);
+
+		skge_write32(hw, SKGEMAC_REG(port, RX_LED_VAL), 0);
+		skge_write8(hw, SKGEMAC_REG(port, RX_LED_CTRL), LED_T_OFF);
+
+		switch (hw->phy_type) {
+		case SK_PHY_BCOM:
+			skge_xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL,
+					  PHY_B_PEC_LED_OFF);
+			break;
+		case SK_PHY_LONE:
+			skge_xm_phy_write(hw, port, PHY_LONE_LED_CFG,
+					  PHY_L_LC_LEDT);
+			break;
+		default:
+			skge_write32(hw, SKGEMAC_REG(port, TX_LED_VAL), 0);
+			skge_write8(hw, SKGEMAC_REG(port, TX_LED_CTRL), LED_T_OFF);
+		}
+	} else {
+		skge_gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0);
+		skge_gm_phy_write(hw, port, PHY_MARV_LED_OVER,
+				  PHY_M_LED_MO_DUP(MO_LED_OFF)  |
+				  PHY_M_LED_MO_10(MO_LED_OFF)   |
+				  PHY_M_LED_MO_100(MO_LED_OFF)  |
+				  PHY_M_LED_MO_1000(MO_LED_OFF) |
+				  PHY_M_LED_MO_RX(MO_LED_OFF));
+	}
+}
+
+static void skge_blink_timer(unsigned long data)
+{
+	struct skge_port *skge = (struct skge_port *) data;
+	struct skge_hw *hw = skge->hw;
+	unsigned long flags;
+
+	spin_lock_irqsave(&hw->phy_lock, flags);
+	if (skge->blink_on)
+		skge_led_on(hw, skge->port);
+	else
+		skge_led_off(hw, skge->port);
+	spin_unlock_irqrestore(&hw->phy_lock, flags);
+
+	skge->blink_on = !skge->blink_on;
+	mod_timer(&skge->led_blink, jiffies + BLINK_HZ);
+}
+
+/* blink LED's for finding board */
+static int skge_phys_id(struct net_device *dev, u32 data)
+{
+	struct skge_port *skge = netdev_priv(dev);
+
+	if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ))
+		data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ);
+
+	/* start blinking */
+	skge->blink_on = 1;
+	mod_timer(&skge->led_blink, jiffies+1);
+
+	msleep_interruptible(data * 1000);
+	del_timer_sync(&skge->led_blink);
+
+	skge_led_off(skge->hw, skge->port);
+
+	return 0;
+}
+
+static struct ethtool_ops skge_ethtool_ops = {
+	.get_settings	= skge_get_settings,
+	.set_settings	= skge_set_settings,
+	.get_drvinfo	= skge_get_drvinfo,
+	.get_regs_len	= skge_get_regs_len,
+	.get_regs	= skge_get_regs,
+	.get_wol	= skge_get_wol,
+	.set_wol	= skge_set_wol,
+	.get_msglevel	= skge_get_msglevel,
+	.set_msglevel	= skge_set_msglevel,
+	.nway_reset	= skge_nway_reset,
+	.get_link	= ethtool_op_get_link,
+	.get_ringparam	= skge_get_ring_param,
+	.set_ringparam	= skge_set_ring_param,
+	.get_pauseparam = skge_get_pauseparam,
+	.set_pauseparam = skge_set_pauseparam,
+	.get_coalesce	= skge_get_coalesce,
+	.set_coalesce	= skge_set_coalesce,
+	.get_tso	= ethtool_op_get_tso,
+	.set_tso	= skge_set_tso,
+	.get_sg		= ethtool_op_get_sg,
+	.set_sg		= skge_set_sg,
+	.get_tx_csum	= ethtool_op_get_tx_csum,
+	.set_tx_csum	= skge_set_tx_csum,
+	.get_rx_csum	= skge_get_rx_csum,
+	.set_rx_csum	= skge_set_rx_csum,
+	.get_strings	= skge_get_strings,
+	.phys_id	= skge_phys_id,
+	.get_stats_count = skge_get_stats_count,
+	.get_ethtool_stats = skge_get_ethtool_stats,
+};
+
+/*
+ * Allocate ring elements and chain them together
+ * One-to-one association of board descriptors with ring elements
+ */
+static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u64 base)
+{
+	struct skge_tx_desc *d;
+	struct skge_element *e;
+	int i;
+
+	ring->start = kmalloc(sizeof(*e)*ring->count, GFP_KERNEL);
+	if (!ring->start)
+		return -ENOMEM;
+
+	for (i = 0, e = ring->start, d = vaddr; i < ring->count; i++, e++, d++) {
+		e->desc = d;
+		if (i == ring->count - 1) {
+			e->next = ring->start;
+			d->next_offset = base;
+		} else {
+			e->next = e + 1;
+			d->next_offset = base + (i+1) * sizeof(*d);
+		}
+	}
+	ring->to_use = ring->to_clean = ring->start;
+
+	return 0;
+}
+
+/* Setup buffer for receiving */
+static inline int skge_rx_alloc(struct skge_port *skge,
+				struct skge_element *e)
+{
+	unsigned long bufsize = skge->netdev->mtu + ETH_HLEN; /* VLAN? */
+	struct skge_rx_desc *rd = e->desc;
+	struct sk_buff *skb;
+	u64 map;
+
+	skb = dev_alloc_skb(bufsize + NET_IP_ALIGN);
+	if (unlikely(!skb)) {
+		printk(KERN_DEBUG PFX "%s: out of memory for receive\n",
+		       skge->netdev->name);
+		return -ENOMEM;
+	}
+
+	skb->dev = skge->netdev;
+	skb_reserve(skb, NET_IP_ALIGN);
+
+	map = pci_map_single(skge->hw->pdev, skb->data, bufsize,
+			     PCI_DMA_FROMDEVICE);
+
+	rd->dma_lo = map;
+	rd->dma_hi = map >> 32;
+	e->skb = skb;
+	rd->csum1_start = ETH_HLEN;
+	rd->csum2_start = ETH_HLEN;
+	rd->csum1 = 0;
+	rd->csum2 = 0;
+
+	wmb();
+
+	rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | bufsize;
+	pci_unmap_addr_set(e, mapaddr, map);
+	pci_unmap_len_set(e, maplen, bufsize);
+	return 0;
+}
+
+/* Free all unused buffers in receive ring, assumes receiver stopped */
+static void skge_rx_clean(struct skge_port *skge)
+{
+	struct skge_hw *hw = skge->hw;
+	struct skge_ring *ring = &skge->rx_ring;
+	struct skge_element *e;
+
+	for (e = ring->to_clean; e != ring->to_use; e = e->next) {
+		struct skge_rx_desc *rd = e->desc;
+		rd->control = 0;
+
+		pci_unmap_single(hw->pdev,
+				 pci_unmap_addr(e, mapaddr),
+				 pci_unmap_len(e, maplen),
+				 PCI_DMA_FROMDEVICE);
+		dev_kfree_skb(e->skb);
+		e->skb = NULL;
+	}
+	ring->to_clean = e;
+}
+
+/* Allocate buffers for receive ring
+ * For receive: to_use   is refill location
+ *              to_clean is next received frame.
+ *
+ * if (to_use == to_clean)
+ *	 then ring all frames in ring need buffers
+ * if (to_use->next == to_clean)
+ *	 then ring all frames in ring have buffers
+ */
+static int skge_rx_fill(struct skge_port *skge)
+{
+	struct skge_ring *ring = &skge->rx_ring;
+	struct skge_element *e;
+	int ret = 0;
+
+	for (e = ring->to_use; e->next != ring->to_clean; e = e->next) {
+		if (skge_rx_alloc(skge, e)) {
+			ret = 1;
+			break;
+		}
+
+	}
+	ring->to_use = e;
+
+	return ret;
+}
+
+static void skge_link_up(struct skge_port *skge)
+{
+	netif_carrier_on(skge->netdev);
+	if (skge->tx_avail > MAX_SKB_FRAGS + 1)
+		netif_wake_queue(skge->netdev);
+
+	if (netif_msg_link(skge))
+		printk(KERN_INFO PFX
+		       "%s: Link is up at %d Mbps, %s duplex, flow control %s\n",
+		       skge->netdev->name, skge->speed,
+		       skge->duplex == DUPLEX_FULL ? "full" : "half",
+		       (skge->flow_control == FLOW_MODE_NONE) ? "none" :
+		       (skge->flow_control == FLOW_MODE_LOC_SEND) ? "tx only" :
+		       (skge->flow_control == FLOW_MODE_REM_SEND) ? "rx only" :
+		       (skge->flow_control == FLOW_MODE_SYMMETRIC) ? "tx and rx" :
+		       "unknown");
+}
+
+static void skge_link_down(struct skge_port *skge)
+{
+	netif_carrier_off(skge->netdev);
+	netif_stop_queue(skge->netdev);
+
+	if (netif_msg_link(skge))
+		printk(KERN_INFO PFX "%s: Link is down.\n", skge->netdev->name);
+}
+
+static u16 skge_xm_phy_read(struct skge_hw *hw, int port,  u16 reg)
+{
+	int i;
+	u16 v;
+
+	skge_xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr);
+	v = skge_xm_read16(hw, port, XM_PHY_DATA);
+	if (hw->phy_type != SK_PHY_XMAC) {
+		for (i = 0; i < PHY_RETRIES; i++) {
+			udelay(1);
+			if (skge_xm_read16(hw, port, XM_MMU_CMD)
+			    & XM_MMU_PHY_RDY)
+				goto ready;
+		}
+
+		printk(KERN_WARNING PFX "%s: phy read timed out\n",
+		       hw->dev[port]->name);
+		return 0;
+	ready:
+		v = skge_xm_read16(hw, port, XM_PHY_DATA);
+	}
+
+	return v;
+}
+
+static void skge_xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val)
+{
+	int i;
+
+	skge_xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr);
+	for (i = 0; i < PHY_RETRIES; i++) {
+		if (!(skge_xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY))
+			goto ready;
+		cpu_relax();
+	}
+	printk(KERN_WARNING PFX "%s: phy write failed to come ready\n",
+	       hw->dev[port]->name);
+
+
+ ready:
+	skge_xm_write16(hw, port, XM_PHY_DATA, val);
+	for (i = 0; i < PHY_RETRIES; i++) {
+		udelay(1);
+		if (!(skge_xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY))
+			return;
+	}
+	printk(KERN_WARNING PFX "%s: phy write timed out\n",
+		       hw->dev[port]->name);
+}
+
+static void genesis_init(struct skge_hw *hw)
+{
+	/* set blink source counter */
+	skge_write32(hw, B2_BSC_INI, (SK_BLK_DUR * SK_FACT_53) / 100);
+	skge_write8(hw, B2_BSC_CTRL, BSC_START);
+
+	/* configure mac arbiter */
+	skge_write16(hw, B3_MA_TO_CTRL, MA_RST_CLR);
+
+	/* configure mac arbiter timeout values */
+	skge_write8(hw, B3_MA_TOINI_RX1, SK_MAC_TO_53);
+	skge_write8(hw, B3_MA_TOINI_RX2, SK_MAC_TO_53);
+	skge_write8(hw, B3_MA_TOINI_TX1, SK_MAC_TO_53);
+	skge_write8(hw, B3_MA_TOINI_TX2, SK_MAC_TO_53);
+
+	skge_write8(hw, B3_MA_RCINI_RX1, 0);
+	skge_write8(hw, B3_MA_RCINI_RX2, 0);
+	skge_write8(hw, B3_MA_RCINI_TX1, 0);
+	skge_write8(hw, B3_MA_RCINI_TX2, 0);
+
+	/* configure packet arbiter timeout */
+	skge_write16(hw, B3_PA_CTRL, PA_RST_CLR);
+	skge_write16(hw, B3_PA_TOINI_RX1, SK_PKT_TO_MAX);
+	skge_write16(hw, B3_PA_TOINI_TX1, SK_PKT_TO_MAX);
+	skge_write16(hw, B3_PA_TOINI_RX2, SK_PKT_TO_MAX);
+	skge_write16(hw, B3_PA_TOINI_TX2, SK_PKT_TO_MAX);
+}
+
+static void genesis_reset(struct skge_hw *hw, int port)
+{
+	int i;
+	u64 zero = 0;
+
+	/* reset the statistics module */
+	skge_xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT);
+	skge_xm_write16(hw, port, XM_IMSK, 0xffff);	/* disable XMAC IRQs */
+	skge_xm_write32(hw, port, XM_MODE, 0);		/* clear Mode Reg */
+	skge_xm_write16(hw, port, XM_TX_CMD, 0);	/* reset TX CMD Reg */
+	skge_xm_write16(hw, port, XM_RX_CMD, 0);	/* reset RX CMD Reg */
+
+	/* disable all PHY IRQs */
+	if  (hw->phy_type == SK_PHY_BCOM)
+		skge_xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff);
+
+	skge_xm_outhash(hw, port, XM_HSM, (u8 *) &zero);
+	for (i = 0; i < 15; i++)
+		skge_xm_outaddr(hw, port, XM_EXM(i), (u8 *) &zero);
+	skge_xm_outhash(hw, port, XM_SRC_CHK, (u8 *) &zero);
+}
+
+
+static void genesis_mac_init(struct skge_hw *hw, int port)
+{
+	struct skge_port *skge = netdev_priv(hw->dev[port]);
+	int i;
+	u32 r;
+	u16 id1;
+	u16 ctrl1, ctrl2, ctrl3, ctrl4, ctrl5;
+
+	/* magic workaround patterns for Broadcom */
+	static const struct {
+		u16 reg;
+		u16 val;
+	} A1hack[] = {
+		{ 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 },
+		{ 0x17, 0x0013 }, { 0x15, 0x0404 }, { 0x17, 0x8006 },
+		{ 0x15, 0x0132 }, { 0x17, 0x8006 }, { 0x15, 0x0232 },
+		{ 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 },
+	}, C0hack[] = {
+		{ 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 },
+		{ 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 },
+	};
+
+
+	/* initialize Rx, Tx and Link LED */
+	skge_write8(hw, SKGEMAC_REG(port, LNK_LED_REG), LINKLED_ON);
+	skge_write8(hw, SKGEMAC_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON);
+
+	skge_write8(hw, SKGEMAC_REG(port, RX_LED_CTRL), LED_START);
+	skge_write8(hw, SKGEMAC_REG(port, TX_LED_CTRL), LED_START);
+
+	/* Unreset the XMAC. */
+	skge_write16(hw, SKGEMAC_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
+
+	/*
+	 * Perform additional initialization for external PHYs,
+	 * namely for the 1000baseTX cards that use the XMAC's
+	 * GMII mode.
+	 */
+	spin_lock_bh(&hw->phy_lock);
+	if (hw->phy_type != SK_PHY_XMAC) {
+		/* Take PHY out of reset. */
+		r = skge_read32(hw, B2_GP_IO);
+		if (port == 0)
+			r |= GP_DIR_0|GP_IO_0;
+		else
+			r |= GP_DIR_2|GP_IO_2;
+
+		skge_write32(hw, B2_GP_IO, r);
+		skge_read32(hw, B2_GP_IO);
+
+		/* Enable GMII mode on the XMAC. */
+		skge_xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD);
+
+		id1 = skge_xm_phy_read(hw, port, PHY_XMAC_ID1);
+
+		/* Optimize MDIO transfer by suppressing preamble. */
+		skge_xm_write16(hw, port, XM_MMU_CMD,
+				skge_xm_read16(hw, port, XM_MMU_CMD)
+				| XM_MMU_NO_PRE);
+
+		if (id1 == PHY_BCOM_ID1_C0) {
+			/*
+			 * Workaround BCOM Errata for the C0 type.
+			 * Write magic patterns to reserved registers.
+			 */
+			for (i = 0; i < ARRAY_SIZE(C0hack); i++)
+				skge_xm_phy_write(hw, port,
+					  C0hack[i].reg, C0hack[i].val);
+
+		} else if (id1 == PHY_BCOM_ID1_A1) {
+			/*
+			 * Workaround BCOM Errata for the A1 type.
+			 * Write magic patterns to reserved registers.
+			 */
+			for (i = 0; i < ARRAY_SIZE(A1hack); i++)
+				skge_xm_phy_write(hw, port,
+					  A1hack[i].reg, A1hack[i].val);
+		}
+
+		/*
+		 * Workaround BCOM Errata (#10523) for all BCom PHYs.
+		 * Disable Power Management after reset.
+		 */
+		r = skge_xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL);
+		skge_xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, r | PHY_B_AC_DIS_PM);
+	}
+
+	/* Dummy read */
+	skge_xm_read16(hw, port, XM_ISRC);
+
+	r = skge_xm_read32(hw, port, XM_MODE);
+	skge_xm_write32(hw, port, XM_MODE, r|XM_MD_CSA);
+
+	/* We don't need the FCS appended to the packet. */
+	r = skge_xm_read16(hw, port, XM_RX_CMD);
+	skge_xm_write16(hw, port, XM_RX_CMD, r | XM_RX_STRIP_FCS);
+
+	/* We want short frames padded to 60 bytes. */
+	r = skge_xm_read16(hw, port, XM_TX_CMD);
+	skge_xm_write16(hw, port, XM_TX_CMD, r | XM_TX_AUTO_PAD);
+
+	/*
+	 * Enable the reception of all error frames. This is is
+	 * a necessary evil due to the design of the XMAC. The
+	 * XMAC's receive FIFO is only 8K in size, however jumbo
+	 * frames can be up to 9000 bytes in length. When bad
+	 * frame filtering is enabled, the XMAC's RX FIFO operates
+	 * in 'store and forward' mode. For this to work, the
+	 * entire frame has to fit into the FIFO, but that means
+	 * that jumbo frames larger than 8192 bytes will be
+	 * truncated. Disabling all bad frame filtering causes
+	 * the RX FIFO to operate in streaming mode, in which
+	 * case the XMAC will start transfering frames out of the
+	 * RX FIFO as soon as the FIFO threshold is reached.
+	 */
+	r = skge_xm_read32(hw, port, XM_MODE);
+	skge_xm_write32(hw, port, XM_MODE,
+		     XM_MD_RX_CRCE|XM_MD_RX_LONG|XM_MD_RX_RUNT|
+		     XM_MD_RX_ERR|XM_MD_RX_IRLE);
+
+	skge_xm_outaddr(hw, port, XM_SA, hw->dev[port]->dev_addr);
+	skge_xm_outaddr(hw, port, XM_EXM(0), hw->dev[port]->dev_addr);
+
+	/*
+	 * Bump up the transmit threshold. This helps hold off transmit
+	 * underruns when we're blasting traffic from both ports at once.
+	 */
+	skge_xm_write16(hw, port, XM_TX_THR, 512);
+
+	/* Configure MAC arbiter */
+	skge_write16(hw, B3_MA_TO_CTRL, MA_RST_CLR);
+
+	/* configure timeout values */
+	skge_write8(hw, B3_MA_TOINI_RX1, 72);
+	skge_write8(hw, B3_MA_TOINI_RX2, 72);
+	skge_write8(hw, B3_MA_TOINI_TX1, 72);
+	skge_write8(hw, B3_MA_TOINI_TX2, 72);
+
+	skge_write8(hw, B3_MA_RCINI_RX1, 0);
+	skge_write8(hw, B3_MA_RCINI_RX2, 0);
+	skge_write8(hw, B3_MA_RCINI_TX1, 0);
+	skge_write8(hw, B3_MA_RCINI_TX2, 0);
+
+	/* Configure Rx MAC FIFO */
+	skge_write8(hw, SKGEMAC_REG(port, RX_MFF_CTRL2), MFF_RST_CLR);
+	skge_write16(hw, SKGEMAC_REG(port, RX_MFF_CTRL1), MFF_ENA_TIM_PAT);
+	skge_write8(hw, SKGEMAC_REG(port, RX_MFF_CTRL2), MFF_ENA_OP_MD);
+
+	/* Configure Tx MAC FIFO */
+	skge_write8(hw, SKGEMAC_REG(port, TX_MFF_CTRL2), MFF_RST_CLR);
+	skge_write16(hw, SKGEMAC_REG(port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF);
+	skge_write8(hw, SKGEMAC_REG(port, TX_MFF_CTRL2), MFF_ENA_OP_MD);
+
+	if (hw->dev[port]->mtu > ETH_DATA_LEN) {
+		/* Enable frame flushing if jumbo frames used */
+		skge_write16(hw, SKGEMAC_REG(port,RX_MFF_CTRL1), MFF_ENA_FLUSH);
+	} else {
+		/* enable timeout timers if normal frames */
+		skge_write16(hw, B3_PA_CTRL,
+			     port == 0 ? PA_ENA_TO_TX1 : PA_ENA_TO_TX2);
+	}
+
+
+	r = skge_xm_read16(hw, port, XM_RX_CMD);
+	if (hw->dev[port]->mtu > ETH_DATA_LEN)
+		skge_xm_write16(hw, port, XM_RX_CMD, r | XM_RX_BIG_PK_OK);
+	else
+		skge_xm_write16(hw, port, XM_RX_CMD, r & ~(XM_RX_BIG_PK_OK));
+
+	switch (hw->phy_type) {
+	case SK_PHY_XMAC:
+		if (skge->autoneg == AUTONEG_ENABLE) {
+			ctrl1 = PHY_X_AN_FD | PHY_X_AN_HD;
+
+			switch (skge->flow_control) {
+			case FLOW_MODE_NONE:
+				ctrl1 |= PHY_X_P_NO_PAUSE;
+				break;
+			case FLOW_MODE_LOC_SEND:
+				ctrl1 |= PHY_X_P_ASYM_MD;
+				break;
+			case FLOW_MODE_SYMMETRIC:
+				ctrl1 |= PHY_X_P_SYM_MD;
+				break;
+			case FLOW_MODE_REM_SEND:
+				ctrl1 |= PHY_X_P_BOTH_MD;
+				break;
+			}
+
+			skge_xm_phy_write(hw, port, PHY_XMAC_AUNE_ADV, ctrl1);
+			ctrl2 = PHY_CT_ANE | PHY_CT_RE_CFG;
+		} else {
+			ctrl2 = 0;
+			if (skge->duplex == DUPLEX_FULL)
+				ctrl2 |= PHY_CT_DUP_MD;
+		}
+
+		skge_xm_phy_write(hw, port, PHY_XMAC_CTRL, ctrl2);
+		break;
+
+	case SK_PHY_BCOM:
+		ctrl1 = PHY_CT_SP1000;
+		ctrl2 = 0;
+		ctrl3 = PHY_SEL_TYPE;
+		ctrl4 = PHY_B_PEC_EN_LTR;
+		ctrl5 = PHY_B_AC_TX_TST;
+
+		if (skge->autoneg == AUTONEG_ENABLE) {
+			/*
+			 * Workaround BCOM Errata #1 for the C5 type.
+			 * 1000Base-T Link Acquisition Failure in Slave Mode
+			 * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
+			 */
+			ctrl2 |= PHY_B_1000C_RD;
+			if (skge->advertising & ADVERTISED_1000baseT_Half)
+				ctrl2 |= PHY_B_1000C_AHD;
+			if (skge->advertising & ADVERTISED_1000baseT_Full)
+				ctrl2 |= PHY_B_1000C_AFD;
+
+			/* Set Flow-control capabilities */
+			switch (skge->flow_control) {
+			case FLOW_MODE_NONE:
+				ctrl3 |= PHY_B_P_NO_PAUSE;
+				break;
+			case FLOW_MODE_LOC_SEND:
+				ctrl3 |= PHY_B_P_ASYM_MD;
+				break;
+			case FLOW_MODE_SYMMETRIC:
+				ctrl3 |= PHY_B_P_SYM_MD;
+				break;
+			case FLOW_MODE_REM_SEND:
+				ctrl3 |= PHY_B_P_BOTH_MD;
+				break;
+			}
+
+			/* Restart Auto-negotiation */
+			ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG;
+		} else {
+			if (skge->duplex == DUPLEX_FULL)
+				ctrl1 |= PHY_CT_DUP_MD;
+
+			ctrl2 |= PHY_B_1000C_MSE;	/* set it to Slave */
+		}
+
+		skge_xm_phy_write(hw, port, PHY_BCOM_1000T_CTRL, ctrl2);
+		skge_xm_phy_write(hw, port, PHY_BCOM_AUNE_ADV, ctrl3);
+
+		if (skge->netdev->mtu > ETH_DATA_LEN) {
+			ctrl4 |= PHY_B_PEC_HIGH_LA;
+			ctrl5 |= PHY_B_AC_LONG_PACK;
+
+			skge_xm_phy_write(hw, port,PHY_BCOM_AUX_CTRL, ctrl5);
+		}
+
+		skge_xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, ctrl4);
+		skge_xm_phy_write(hw, port, PHY_BCOM_CTRL, ctrl1);
+		break;
+	}
+	spin_unlock_bh(&hw->phy_lock);
+
+	/* Clear MIB counters */
+	skge_xm_write16(hw, port, XM_STAT_CMD,
+			XM_SC_CLR_RXC | XM_SC_CLR_TXC);
+	/* Clear two times according to Errata #3 */
+	skge_xm_write16(hw, port, XM_STAT_CMD,
+			XM_SC_CLR_RXC | XM_SC_CLR_TXC);
+
+	/* Start polling for link status */
+	mod_timer(&skge->link_check, jiffies + LINK_POLL_HZ);
+}
+
+static void genesis_stop(struct skge_port *skge)
+{
+	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+
+	/* Clear Tx packet arbiter timeout IRQ */
+	skge_write16(hw, B3_PA_CTRL,
+		     port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2);
+
+	/*
+	 * If the transfer stucks at the MAC the STOP command will not
+	 * terminate if we don't flush the XMAC's transmit FIFO !
+	 */
+	skge_xm_write32(hw, port, XM_MODE,
+			skge_xm_read32(hw, port, XM_MODE)|XM_MD_FTF);
+
+
+	/* Reset the MAC */
+	skge_write16(hw, SKGEMAC_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
+
+	/* For external PHYs there must be special handling */
+	if (hw->phy_type != SK_PHY_XMAC) {
+		u32 reg = skge_read32(hw, B2_GP_IO);
+
+		if (port == 0) {
+			reg |= GP_DIR_0;
+			reg &= ~GP_IO_0;
+		} else {
+			reg |= GP_DIR_2;
+			reg &= ~GP_IO_2;
+		}
+		skge_write32(hw, B2_GP_IO, reg);
+		skge_read32(hw, B2_GP_IO);
+	}
+
+	skge_xm_write16(hw, port, XM_MMU_CMD,
+			skge_xm_read16(hw, port, XM_MMU_CMD)
+			& ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
+
+	skge_xm_read16(hw, port, XM_MMU_CMD);
+}
+
+
+static void genesis_get_stats(struct skge_port *skge, u64 *data)
+{
+	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+	int i;
+	unsigned long timeout = jiffies + HZ;
+
+	skge_xm_write16(hw, port,
+			XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC);
+
+	/* wait for update to complete */
+	while (skge_xm_read16(hw, port, XM_STAT_CMD)
+	       & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) {
+		if (time_after(jiffies, timeout))
+			break;
+		udelay(10);
+	}
+
+	/* special case for 64 bit octet counter */
+	data[0] = (u64) skge_xm_read32(hw, port, XM_TXO_OK_HI) << 32
+		| skge_xm_read32(hw, port, XM_TXO_OK_LO);
+	data[1] = (u64) skge_xm_read32(hw, port, XM_RXO_OK_HI) << 32
+		| skge_xm_read32(hw, port, XM_RXO_OK_LO);
+
+	for (i = 2; i < ARRAY_SIZE(skge_stats); i++)
+		data[i] = skge_xm_read32(hw, port, skge_stats[i].xmac_offset);
+}
+
+static void genesis_mac_intr(struct skge_hw *hw, int port)
+{
+	struct skge_port *skge = netdev_priv(hw->dev[port]);
+	u16 status = skge_xm_read16(hw, port, XM_ISRC);
+
+	pr_debug("genesis_intr status %x\n", status);
+	if (hw->phy_type == SK_PHY_XMAC) {
+		/* LInk down, start polling for state change */
+		if (status & XM_IS_INP_ASS) {
+			skge_xm_write16(hw, port, XM_IMSK,
+					skge_xm_read16(hw, port, XM_IMSK) | XM_IS_INP_ASS);
+			mod_timer(&skge->link_check, jiffies + LINK_POLL_HZ);
+		}
+		else if (status & XM_IS_AND)
+			mod_timer(&skge->link_check, jiffies + LINK_POLL_HZ);
+	}
+
+	if (status & XM_IS_TXF_UR) {
+		skge_xm_write32(hw, port, XM_MODE, XM_MD_FTF);
+		++skge->net_stats.tx_fifo_errors;
+	}
+	if (status & XM_IS_RXF_OV) {
+		skge_xm_write32(hw, port, XM_MODE, XM_MD_FRF);
+		++skge->net_stats.rx_fifo_errors;
+	}
+}
+
+static void skge_gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val)
+{
+	int i;
+
+	skge_gma_write16(hw, port, GM_SMI_DATA, val);
+	skge_gma_write16(hw, port, GM_SMI_CTRL,
+			 GM_SMI_CT_PHY_AD(hw->phy_addr) | GM_SMI_CT_REG_AD(reg));
+	for (i = 0; i < PHY_RETRIES; i++) {
+		udelay(1);
+
+		if (!(skge_gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_BUSY))
+			break;
+	}
+}
+
+static u16 skge_gm_phy_read(struct skge_hw *hw, int port, u16 reg)
+{
+	int i;
+
+	skge_gma_write16(hw, port, GM_SMI_CTRL,
+			 GM_SMI_CT_PHY_AD(hw->phy_addr)
+			 | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD);
+
+	for (i = 0; i < PHY_RETRIES; i++) {
+		udelay(1);
+		if (skge_gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_RD_VAL)
+			goto ready;
+	}
+
+	printk(KERN_WARNING PFX "%s: phy read timeout\n",
+	       hw->dev[port]->name);
+	return 0;
+ ready:
+	return skge_gma_read16(hw, port, GM_SMI_DATA);
+}
+
+static void genesis_link_down(struct skge_port *skge)
+{
+	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+
+	pr_debug("genesis_link_down\n");
+
+	skge_xm_write16(hw, port, XM_MMU_CMD,
+			skge_xm_read16(hw, port, XM_MMU_CMD)
+			& ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
+
+	/* dummy read to ensure writing */
+	(void) skge_xm_read16(hw, port, XM_MMU_CMD);
+
+	skge_link_down(skge);
+}
+
+static void genesis_link_up(struct skge_port *skge)
+{
+	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+	u16 cmd;
+	u32 mode, msk;
+
+	pr_debug("genesis_link_up\n");
+	cmd = skge_xm_read16(hw, port, XM_MMU_CMD);
+
+	/*
+	 * enabling pause frame reception is required for 1000BT
+	 * because the XMAC is not reset if the link is going down
+	 */
+	if (skge->flow_control == FLOW_MODE_NONE ||
+	    skge->flow_control == FLOW_MODE_LOC_SEND)
+		cmd |= XM_MMU_IGN_PF;
+	else
+		/* Enable Pause Frame Reception */
+		cmd &= ~XM_MMU_IGN_PF;
+
+	skge_xm_write16(hw, port, XM_MMU_CMD, cmd);
+
+	mode = skge_xm_read32(hw, port, XM_MODE);
+	if (skge->flow_control == FLOW_MODE_SYMMETRIC ||
+	    skge->flow_control == FLOW_MODE_LOC_SEND) {
+		/*
+		 * Configure Pause Frame Generation
+		 * Use internal and external Pause Frame Generation.
+		 * Sending pause frames is edge triggered.
+		 * Send a Pause frame with the maximum pause time if
+		 * internal oder external FIFO full condition occurs.
+		 * Send a zero pause time frame to re-start transmission.
+		 */
+		/* XM_PAUSE_DA = '010000C28001' (default) */
+		/* XM_MAC_PTIME = 0xffff (maximum) */
+		/* remember this value is defined in big endian (!) */
+		skge_xm_write16(hw, port, XM_MAC_PTIME, 0xffff);
+
+		mode |= XM_PAUSE_MODE;
+		skge_write16(hw, SKGEMAC_REG(port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
+	} else {
+		/*
+		 * disable pause frame generation is required for 1000BT
+		 * because the XMAC is not reset if the link is going down
+		 */
+		/* Disable Pause Mode in Mode Register */
+		mode &= ~XM_PAUSE_MODE;
+
+		skge_write16(hw, SKGEMAC_REG(port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
+	}
+
+	skge_xm_write32(hw, port, XM_MODE, mode);
+
+	msk = XM_DEF_MSK;
+	if (hw->phy_type != SK_PHY_XMAC)
+		msk |= XM_IS_INP_ASS;	/* disable GP0 interrupt bit */
+
+	skge_xm_write16(hw, port, XM_IMSK, msk);
+	skge_xm_read16(hw, port, XM_ISRC);
+
+	/* get MMU Command Reg. */
+	cmd = skge_xm_read16(hw, port, XM_MMU_CMD);
+	if (hw->phy_type != SK_PHY_XMAC && skge->duplex == DUPLEX_FULL)
+		cmd |= XM_MMU_GMII_FD;
+
+	if (hw->phy_type == SK_PHY_BCOM) {
+		/*
+		 * Workaround BCOM Errata (#10523) for all BCom Phys
+		 * Enable Power Management after link up
+		 */
+		skge_xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL,
+				  skge_xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL)
+				  & ~PHY_B_AC_DIS_PM);
+		skge_xm_phy_write(hw, port, PHY_BCOM_INT_MASK,
+				  PHY_B_DEF_MSK);
+	}
+
+	/* enable Rx/Tx */
+	skge_xm_write16(hw, port, XM_MMU_CMD,
+			cmd | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
+	skge_link_up(skge);
+}
+
+
+static void genesis_bcom_intr(struct skge_port *skge)
+{
+	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+	u16 stat = skge_xm_phy_read(hw, port, PHY_BCOM_INT_STAT);
+
+	pr_debug("genesis_bcom intr stat=%x\n", stat);
+
+	/* Workaround BCom Errata:
+	 *	enable and disable loopback mode if "NO HCD" occurs.
+	 */
+	if (stat & PHY_B_IS_NO_HDCL) {
+		u16 ctrl = skge_xm_phy_read(hw, port, PHY_BCOM_CTRL);
+		skge_xm_phy_write(hw, port, PHY_BCOM_CTRL,
+				  ctrl | PHY_CT_LOOP);
+		skge_xm_phy_write(hw, port, PHY_BCOM_CTRL,
+				  ctrl & ~PHY_CT_LOOP);
+	}
+
+	stat = skge_xm_phy_read(hw, port, PHY_BCOM_STAT);
+	if (stat & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) {
+		u16 aux = skge_xm_phy_read(hw, port, PHY_BCOM_AUX_STAT);
+		if ( !(aux & PHY_B_AS_LS) && netif_carrier_ok(skge->netdev))
+			genesis_link_down(skge);
+
+		else if (stat & PHY_B_IS_LST_CHANGE) {
+			if (aux & PHY_B_AS_AN_C) {
+				switch (aux & PHY_B_AS_AN_RES_MSK) {
+				case PHY_B_RES_1000FD:
+					skge->duplex = DUPLEX_FULL;
+					break;
+				case PHY_B_RES_1000HD:
+					skge->duplex = DUPLEX_HALF;
+					break;
+				}
+
+				switch (aux & PHY_B_AS_PAUSE_MSK) {
+				case PHY_B_AS_PAUSE_MSK:
+					skge->flow_control = FLOW_MODE_SYMMETRIC;
+					break;
+				case PHY_B_AS_PRR:
+					skge->flow_control = FLOW_MODE_REM_SEND;
+					break;
+				case PHY_B_AS_PRT:
+					skge->flow_control = FLOW_MODE_LOC_SEND;
+					break;
+				default:
+					skge->flow_control = FLOW_MODE_NONE;
+				}
+				skge->speed = SPEED_1000;
+			}
+			genesis_link_up(skge);
+		}
+		else
+			mod_timer(&skge->link_check, jiffies + LINK_POLL_HZ);
+	}
+}
+
+/* Perodic poll of phy status to check for link transistion  */
+static void skge_link_timer(unsigned long __arg)
+{
+	struct skge_port *skge = (struct skge_port *) __arg;
+	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+
+	if (hw->chip_id != CHIP_ID_GENESIS || !netif_running(skge->netdev))
+		return;
+
+	spin_lock_bh(&hw->phy_lock);
+	if (hw->phy_type == SK_PHY_BCOM)
+		genesis_bcom_intr(skge);
+	else {
+		int i;
+		for (i = 0; i < 3; i++)
+			if (skge_xm_read16(hw, port, XM_ISRC) & XM_IS_INP_ASS)
+				break;
+
+		if (i == 3)
+			mod_timer(&skge->link_check, jiffies + LINK_POLL_HZ);
+		else
+			genesis_link_up(skge);
+	}
+	spin_unlock_bh(&hw->phy_lock);
+}
+
+/* Marvell Phy Initailization */
+static void yukon_init(struct skge_hw *hw, int port)
+{
+	struct skge_port *skge = netdev_priv(hw->dev[port]);
+	u16 ctrl, ct1000, adv;
+	u16 ledctrl, ledover;
+
+	pr_debug("yukon_init\n");
+	if (skge->autoneg == AUTONEG_ENABLE) {
+		u16 ectrl = skge_gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
+
+		ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
+			  PHY_M_EC_MAC_S_MSK);
+		ectrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ);
+
+		/* on PHY 88E1111 there is a change for downshift control */
+		if (hw->chip_id == CHIP_ID_YUKON_EC)
+			ectrl |= PHY_M_EC_M_DSC_2(0) | PHY_M_EC_DOWN_S_ENA;
+		else
+			ectrl |= PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1);
+
+		skge_gm_phy_write(hw, port, PHY_MARV_EXT_CTRL, ectrl);
+	}
+
+	ctrl = skge_gm_phy_read(hw, port, PHY_MARV_CTRL);
+	if (skge->autoneg == AUTONEG_DISABLE)
+		ctrl &= ~PHY_CT_ANE;
+
+	ctrl |= PHY_CT_RESET;
+	skge_gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
+
+	ctrl = 0;
+	ct1000 = 0;
+	adv = PHY_SEL_TYPE;
+
+	if (skge->autoneg == AUTONEG_ENABLE) {
+		if (iscopper(hw)) {
+			if (skge->advertising & ADVERTISED_1000baseT_Full)
+				ct1000 |= PHY_M_1000C_AFD;
+			if (skge->advertising & ADVERTISED_1000baseT_Half)
+				ct1000 |= PHY_M_1000C_AHD;
+			if (skge->advertising & ADVERTISED_100baseT_Full)
+				adv |= PHY_M_AN_100_FD;
+			if (skge->advertising & ADVERTISED_100baseT_Half)
+				adv |= PHY_M_AN_100_HD;
+			if (skge->advertising & ADVERTISED_10baseT_Full)
+				adv |= PHY_M_AN_10_FD;
+			if (skge->advertising & ADVERTISED_10baseT_Half)
+				adv |= PHY_M_AN_10_HD;
+
+			/* Set Flow-control capabilities */
+			switch (skge->flow_control) {
+			case FLOW_MODE_NONE:
+				adv |= PHY_B_P_NO_PAUSE;
+				break;
+			case FLOW_MODE_LOC_SEND:
+				adv |= PHY_B_P_ASYM_MD;
+				break;
+			case FLOW_MODE_SYMMETRIC:
+				adv |= PHY_B_P_SYM_MD;
+				break;
+			case FLOW_MODE_REM_SEND:
+				adv |= PHY_B_P_BOTH_MD;
+				break;
+			}
+		} else {	/* special defines for FIBER (88E1011S only) */
+			adv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
+
+			/* Set Flow-control capabilities */
+			switch (skge->flow_control) {
+			case FLOW_MODE_NONE:
+				adv |= PHY_M_P_NO_PAUSE_X;
+				break;
+			case FLOW_MODE_LOC_SEND:
+				adv |= PHY_M_P_ASYM_MD_X;
+				break;
+			case FLOW_MODE_SYMMETRIC:
+				adv |= PHY_M_P_SYM_MD_X;
+				break;
+			case FLOW_MODE_REM_SEND:
+				adv |= PHY_M_P_BOTH_MD_X;
+				break;
+			}
+		}
+		/* Restart Auto-negotiation */
+		ctrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
+	} else {
+		/* forced speed/duplex settings */
+		ct1000 = PHY_M_1000C_MSE;
+
+		if (skge->duplex == DUPLEX_FULL)
+			ctrl |= PHY_CT_DUP_MD;
+
+		switch (skge->speed) {
+		case SPEED_1000:
+			ctrl |= PHY_CT_SP1000;
+			break;
+		case SPEED_100:
+			ctrl |= PHY_CT_SP100;
+			break;
+		}
+
+		ctrl |= PHY_CT_RESET;
+	}
+
+	if (hw->chip_id != CHIP_ID_YUKON_FE)
+		skge_gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000);
+
+	skge_gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv);
+	skge_gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl);
+
+	/* Setup Phy LED's */
+	ledctrl = PHY_M_LED_PULS_DUR(PULS_170MS);
+	ledover = 0;
+
+	if (hw->chip_id == CHIP_ID_YUKON_FE) {
+		/* on 88E3082 these bits are at 11..9 (shifted left) */
+		ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) << 1;
+
+		skge_gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR,
+				  ((skge_gm_phy_read(hw, port, PHY_MARV_FE_LED_PAR)
+
+				    & ~PHY_M_FELP_LED1_MSK)
+				   | PHY_M_FELP_LED1_CTRL(LED_PAR_CTRL_ACT_BL)));
+	} else {
+		/* set Tx LED (LED_TX) to blink mode on Rx OR Tx activity */
+		ledctrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL;
+
+		/* turn off the Rx LED (LED_RX) */
+		ledover |= PHY_M_LED_MO_RX(MO_LED_OFF);
+	}
+
+	/* disable blink mode (LED_DUPLEX) on collisions */
+	ctrl |= PHY_M_LEDC_DP_CTRL;
+	skge_gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
+
+	if (skge->autoneg == AUTONEG_DISABLE || skge->speed == SPEED_100) {
+		/* turn on 100 Mbps LED (LED_LINK100) */
+		ledover |= PHY_M_LED_MO_100(MO_LED_ON);
+	}
+
+	if (ledover)
+		skge_gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover);
+
+	/* Enable phy interrupt on autonegotiation complete (or link up) */
+	if (skge->autoneg == AUTONEG_ENABLE)
+		skge_gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL);
+	else
+		skge_gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
+}
+
+static void yukon_reset(struct skge_hw *hw, int port)
+{
+	skge_gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);/* disable PHY IRQs */
+	skge_gma_write16(hw, port, GM_MC_ADDR_H1, 0);	/* clear MC hash */
+	skge_gma_write16(hw, port, GM_MC_ADDR_H2, 0);
+	skge_gma_write16(hw, port, GM_MC_ADDR_H3, 0);
+	skge_gma_write16(hw, port, GM_MC_ADDR_H4, 0);
+
+	skge_gma_write16(hw, port, GM_RX_CTRL,
+			 skge_gma_read16(hw, port, GM_RX_CTRL)
+			 | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
+}
+
+static void yukon_mac_init(struct skge_hw *hw, int port)
+{
+	struct skge_port *skge = netdev_priv(hw->dev[port]);
+	int i;
+	u32 reg;
+	const u8 *addr = hw->dev[port]->dev_addr;
+
+	/* WA code for COMA mode -- set PHY reset */
+	if (hw->chip_id == CHIP_ID_YUKON_LITE &&
+	    chip_rev(hw) == CHIP_REV_YU_LITE_A3)
+		skge_write32(hw, B2_GP_IO,
+			     (skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9));
+
+	/* hard reset */
+	skge_write32(hw, SKGEMAC_REG(port, GPHY_CTRL), GPC_RST_SET);
+	skge_write32(hw, SKGEMAC_REG(port, GMAC_CTRL), GMC_RST_SET);
+
+	/* WA code for COMA mode -- clear PHY reset */
+	if (hw->chip_id == CHIP_ID_YUKON_LITE &&
+	    chip_rev(hw) == CHIP_REV_YU_LITE_A3)
+		skge_write32(hw, B2_GP_IO,
+			     (skge_read32(hw, B2_GP_IO) | GP_DIR_9)
+			     & ~GP_IO_9);
+
+	/* Set hardware config mode */
+	reg = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
+		GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE;
+	reg |= iscopper(hw) ? GPC_HWCFG_GMII_COP : GPC_HWCFG_GMII_FIB;
+
+	/* Clear GMC reset */
+	skge_write32(hw, SKGEMAC_REG(port, GPHY_CTRL), reg | GPC_RST_SET);
+	skge_write32(hw, SKGEMAC_REG(port, GPHY_CTRL), reg | GPC_RST_CLR);
+	skge_write32(hw, SKGEMAC_REG(port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
+	if (skge->autoneg == AUTONEG_DISABLE) {
+		reg = GM_GPCR_AU_ALL_DIS;
+		skge_gma_write16(hw, port, GM_GP_CTRL,
+				 skge_gma_read16(hw, port, GM_GP_CTRL) | reg);
+
+		switch (skge->speed) {
+		case SPEED_1000:
+			reg |= GM_GPCR_SPEED_1000;
+			/* fallthru */
+		case SPEED_100:
+			reg |= GM_GPCR_SPEED_100;
+		}
+
+		if (skge->duplex == DUPLEX_FULL)
+			reg |= GM_GPCR_DUP_FULL;
+	} else
+		reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL;
+	switch (skge->flow_control) {
+	case FLOW_MODE_NONE:
+		skge_write32(hw, SKGEMAC_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
+		reg |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
+		break;
+	case FLOW_MODE_LOC_SEND:
+		/* disable Rx flow-control */
+		reg |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
+	}
+
+	skge_gma_write16(hw, port, GM_GP_CTRL, reg);
+	skge_read16(hw, GMAC_IRQ_SRC);
+
+	spin_lock_bh(&hw->phy_lock);
+	yukon_init(hw, port);
+	spin_unlock_bh(&hw->phy_lock);
+
+	/* MIB clear */
+	reg = skge_gma_read16(hw, port, GM_PHY_ADDR);
+	skge_gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR);
+
+	for (i = 0; i < GM_MIB_CNT_SIZE; i++)
+		skge_gma_read16(hw, port, GM_MIB_CNT_BASE + 8*i);
+	skge_gma_write16(hw, port, GM_PHY_ADDR, reg);
+
+	/* transmit control */
+	skge_gma_write16(hw, port, GM_TX_CTRL, TX_COL_THR(TX_COL_DEF));
+
+	/* receive control reg: unicast + multicast + no FCS  */
+	skge_gma_write16(hw, port, GM_RX_CTRL,
+			 GM_RXCR_UCF_ENA | GM_RXCR_CRC_DIS | GM_RXCR_MCF_ENA);
+
+	/* transmit flow control */
+	skge_gma_write16(hw, port, GM_TX_FLOW_CTRL, 0xffff);
+
+	/* transmit parameter */
+	skge_gma_write16(hw, port, GM_TX_PARAM,
+			 TX_JAM_LEN_VAL(TX_JAM_LEN_DEF) |
+			 TX_JAM_IPG_VAL(TX_JAM_IPG_DEF) |
+			 TX_IPG_JAM_DATA(TX_IPG_JAM_DEF));
+
+	/* serial mode register */
+	reg = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(IPG_DATA_DEF);
+	if (hw->dev[port]->mtu > 1500)
+		reg |= GM_SMOD_JUMBO_ENA;
+
+	skge_gma_write16(hw, port, GM_SERIAL_MODE, reg);
+
+	/* physical address: used for pause frames */
+	skge_gm_set_addr(hw, port, GM_SRC_ADDR_1L, addr);
+	/* virtual address for data */
+	skge_gm_set_addr(hw, port, GM_SRC_ADDR_2L, addr);
+
+	/* enable interrupt mask for counter overflows */
+	skge_gma_write16(hw, port, GM_TX_IRQ_MSK, 0);
+	skge_gma_write16(hw, port, GM_RX_IRQ_MSK, 0);
+	skge_gma_write16(hw, port, GM_TR_IRQ_MSK, 0);
+
+	/* Initialize Mac Fifo */
+
+	/* Configure Rx MAC FIFO */
+	skge_write16(hw, SKGEMAC_REG(port, RX_GMF_FL_MSK), RX_FF_FL_DEF_MSK);
+	reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
+	if (hw->chip_id == CHIP_ID_YUKON_LITE &&
+	    chip_rev(hw) == CHIP_REV_YU_LITE_A3)
+		reg &= ~GMF_RX_F_FL_ON;
+	skge_write8(hw, SKGEMAC_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
+	skge_write16(hw, SKGEMAC_REG(port, RX_GMF_CTRL_T), reg);
+	skge_write16(hw, SKGEMAC_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF);
+
+	/* Configure Tx MAC FIFO */
+	skge_write8(hw, SKGEMAC_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR);
+	skge_write16(hw, SKGEMAC_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON);
+}
+
+static void yukon_stop(struct skge_port *skge)
+{
+	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+
+	if (hw->chip_id == CHIP_ID_YUKON_LITE &&
+	    chip_rev(hw) == CHIP_REV_YU_LITE_A3) {
+		skge_write32(hw, B2_GP_IO,
+			     skge_read32(hw, B2_GP_IO) | GP_DIR_9 | GP_IO_9);
+	}
+
+	skge_gma_write16(hw, port, GM_GP_CTRL,
+			 skge_gma_read16(hw, port, GM_GP_CTRL)
+			 & ~(GM_GPCR_RX_ENA|GM_GPCR_RX_ENA));
+	skge_gma_read16(hw, port, GM_GP_CTRL);
+
+	/* set GPHY Control reset */
+	skge_gma_write32(hw, port, GPHY_CTRL, GPC_RST_SET);
+	skge_gma_write32(hw, port, GMAC_CTRL, GMC_RST_SET);
+}
+
+static void yukon_get_stats(struct skge_port *skge, u64 *data)
+{
+	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+	int i;
+
+	data[0] = (u64) skge_gma_read32(hw, port, GM_TXO_OK_HI) << 32
+		| skge_gma_read32(hw, port, GM_TXO_OK_LO);
+	data[1] = (u64) skge_gma_read32(hw, port, GM_RXO_OK_HI) << 32
+		| skge_gma_read32(hw, port, GM_RXO_OK_LO);
+
+	for (i = 2; i < ARRAY_SIZE(skge_stats); i++)
+		data[i] = skge_gma_read32(hw, port,
+					  skge_stats[i].gma_offset);
+}
+
+static void yukon_mac_intr(struct skge_hw *hw, int port)
+{
+	struct skge_port *skge = netdev_priv(hw->dev[port]);
+	u8 status = skge_read8(hw, SKGEMAC_REG(port, GMAC_IRQ_SRC));
+
+	pr_debug("yukon_intr status %x\n", status);
+	if (status & GM_IS_RX_FF_OR) {
+		++skge->net_stats.rx_fifo_errors;
+		skge_gma_write8(hw, port, RX_GMF_CTRL_T, GMF_CLI_RX_FO);
+	}
+	if (status & GM_IS_TX_FF_UR) {
+		++skge->net_stats.tx_fifo_errors;
+		skge_gma_write8(hw, port, TX_GMF_CTRL_T, GMF_CLI_TX_FU);
+	}
+
+}
+
+static u16 yukon_speed(const struct skge_hw *hw, u16 aux)
+{
+	if (hw->chip_id == CHIP_ID_YUKON_FE)
+		return (aux & PHY_M_PS_SPEED_100) ? SPEED_100 : SPEED_10;
+
+	switch(aux & PHY_M_PS_SPEED_MSK) {
+	case PHY_M_PS_SPEED_1000:
+		return SPEED_1000;
+	case PHY_M_PS_SPEED_100:
+		return SPEED_100;
+	default:
+		return SPEED_10;
+	}
+}
+
+static void yukon_link_up(struct skge_port *skge)
+{
+	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+	u16 reg;
+
+	pr_debug("yukon_link_up\n");
+
+	/* Enable Transmit FIFO Underrun */
+	skge_write8(hw, GMAC_IRQ_MSK, GMAC_DEF_MSK);
+
+	reg = skge_gma_read16(hw, port, GM_GP_CTRL);
+	if (skge->duplex == DUPLEX_FULL || skge->autoneg == AUTONEG_ENABLE)
+		reg |= GM_GPCR_DUP_FULL;
+
+	/* enable Rx/Tx */
+	reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA;
+	skge_gma_write16(hw, port, GM_GP_CTRL, reg);
+
+	skge_gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
+	skge_link_up(skge);
+}
+
+static void yukon_link_down(struct skge_port *skge)
+{
+	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+
+	pr_debug("yukon_link_down\n");
+	skge_gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);
+	skge_gm_phy_write(hw, port, GM_GP_CTRL,
+			  skge_gm_phy_read(hw, port, GM_GP_CTRL)
+			  & ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA));
+
+	if (hw->chip_id != CHIP_ID_YUKON_FE &&
+	    skge->flow_control == FLOW_MODE_REM_SEND) {
+		/* restore Asymmetric Pause bit */
+		skge_gm_phy_write(hw, port, PHY_MARV_AUNE_ADV,
+				  skge_gm_phy_read(hw, port,
+						   PHY_MARV_AUNE_ADV)
+				  | PHY_M_AN_ASP);
+
+	}
+
+	yukon_reset(hw, port);
+	skge_link_down(skge);
+
+	yukon_init(hw, port);
+}
+
+static void yukon_phy_intr(struct skge_port *skge)
+{
+	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+	const char *reason = NULL;
+	u16 istatus, phystat;
+
+	istatus = skge_gm_phy_read(hw, port, PHY_MARV_INT_STAT);
+	phystat = skge_gm_phy_read(hw, port, PHY_MARV_PHY_STAT);
+	pr_debug("yukon phy intr istat=%x phy_stat=%x\n", istatus, phystat);
+
+	if (istatus & PHY_M_IS_AN_COMPL) {
+		if (skge_gm_phy_read(hw, port, PHY_MARV_AUNE_LP)
+		    & PHY_M_AN_RF) {
+			reason = "remote fault";
+			goto failed;
+		}
+
+		if (!(hw->chip_id == CHIP_ID_YUKON_FE || hw->chip_id == CHIP_ID_YUKON_EC)
+		    && (skge_gm_phy_read(hw, port, PHY_MARV_1000T_STAT)
+			& PHY_B_1000S_MSF)) {
+			reason = "master/slave fault";
+			goto failed;
+		}
+
+		if (!(phystat & PHY_M_PS_SPDUP_RES)) {
+			reason = "speed/duplex";
+			goto failed;
+		}
+
+		skge->duplex = (phystat & PHY_M_PS_FULL_DUP)
+			? DUPLEX_FULL : DUPLEX_HALF;
+		skge->speed = yukon_speed(hw, phystat);
+
+		/* Tx & Rx Pause Enabled bits are at 9..8 */
+		if (hw->chip_id == CHIP_ID_YUKON_XL)
+			phystat >>= 6;
+
+		/* We are using IEEE 802.3z/D5.0 Table 37-4 */
+		switch (phystat & PHY_M_PS_PAUSE_MSK) {
+		case PHY_M_PS_PAUSE_MSK:
+			skge->flow_control = FLOW_MODE_SYMMETRIC;
+			break;
+		case PHY_M_PS_RX_P_EN:
+			skge->flow_control = FLOW_MODE_REM_SEND;
+			break;
+		case PHY_M_PS_TX_P_EN:
+			skge->flow_control = FLOW_MODE_LOC_SEND;
+			break;
+		default:
+			skge->flow_control = FLOW_MODE_NONE;
+		}
+
+		if (skge->flow_control == FLOW_MODE_NONE ||
+		    (skge->speed < SPEED_1000 && skge->duplex == DUPLEX_HALF))
+			skge_write8(hw, SKGEMAC_REG(port, GMAC_CTRL), GMC_PAUSE_OFF);
+		else
+			skge_write8(hw, SKGEMAC_REG(port, GMAC_CTRL), GMC_PAUSE_ON);
+		yukon_link_up(skge);
+		return;
+	}
+
+	if (istatus & PHY_M_IS_LSP_CHANGE)
+		skge->speed = yukon_speed(hw, phystat);
+
+	if (istatus & PHY_M_IS_DUP_CHANGE)
+		skge->duplex = (phystat & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF;
+	if (istatus & PHY_M_IS_LST_CHANGE) {
+		if (phystat & PHY_M_PS_LINK_UP)
+			yukon_link_up(skge);
+		else
+			yukon_link_down(skge);
+	}
+	return;
+ failed:
+	printk(KERN_ERR PFX "%s: autonegotiation failed (%s)\n",
+	       skge->netdev->name, reason);
+
+	/* XXX restart autonegotiation? */
+}
+
+static void skge_ramset(struct skge_hw *hw, u16 q, u32 start, size_t len)
+{
+	u32 end;
+
+	start /= 8;
+	len /= 8;
+	end = start + len - 1;
+
+	skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR);
+	skge_write32(hw, RB_ADDR(q, RB_START), start);
+	skge_write32(hw, RB_ADDR(q, RB_WP), start);
+	skge_write32(hw, RB_ADDR(q, RB_RP), start);
+	skge_write32(hw, RB_ADDR(q, RB_END), end);
+
+	if (q == Q_R1 || q == Q_R2) {
+		/* Set thresholds on receive queue's */
+		skge_write32(hw, RB_ADDR(q, RB_RX_UTPP),
+			     start + (2*len)/3);
+		skge_write32(hw, RB_ADDR(q, RB_RX_LTPP),
+			     start + (len/3));
+	} else {
+		/* Enable store & forward on Tx queue's because
+		 * Tx FIFO is only 4K on Genesis and 1K on Yukon
+		 */
+		skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_STFWD);
+	}
+
+	skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_OP_MD);
+}
+
+/* Setup Bus Memory Interface */
+static void skge_qset(struct skge_port *skge, u16 q,
+		      const struct skge_element *e)
+{
+	struct skge_hw *hw = skge->hw;
+	u32 watermark = 0x600;
+	u64 base = skge->dma + (e->desc - skge->mem);
+
+	/* optimization to reduce window on 32bit/33mhz */
+	if ((skge_read16(hw, B0_CTST) & (CS_BUS_CLOCK | CS_BUS_SLOT_SZ)) == 0)
+		watermark /= 2;
+
+	skge_write32(hw, Q_ADDR(q, Q_CSR), CSR_CLR_RESET);
+	skge_write32(hw, Q_ADDR(q, Q_F), watermark);
+	skge_write32(hw, Q_ADDR(q, Q_DA_H), (u32)(base >> 32));
+	skge_write32(hw, Q_ADDR(q, Q_DA_L), (u32)base);
+}
+
+static int skge_up(struct net_device *dev)
+{
+	struct skge_port *skge = netdev_priv(dev);
+	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+	u32 chunk, ram_addr;
+	size_t rx_size, tx_size;
+	int err;
+
+	if (netif_msg_ifup(skge))
+		printk(KERN_INFO PFX "%s: enabling interface\n", dev->name);
+
+	rx_size = skge->rx_ring.count * sizeof(struct skge_rx_desc);
+	tx_size = skge->tx_ring.count * sizeof(struct skge_tx_desc);
+	skge->mem_size = tx_size + rx_size;
+	skge->mem = pci_alloc_consistent(hw->pdev, skge->mem_size, &skge->dma);
+	if (!skge->mem)
+		return -ENOMEM;
+
+	memset(skge->mem, 0, skge->mem_size);
+
+	if ((err = skge_ring_alloc(&skge->rx_ring, skge->mem, skge->dma)))
+		goto free_pci_mem;
+
+	if (skge_rx_fill(skge))
+		goto free_rx_ring;
+
+	if ((err = skge_ring_alloc(&skge->tx_ring, skge->mem + rx_size,
+				   skge->dma + rx_size)))
+		goto free_rx_ring;
+
+	skge->tx_avail = skge->tx_ring.count - 1;
+
+	/* Initialze MAC */
+	if (hw->chip_id == CHIP_ID_GENESIS)
+		genesis_mac_init(hw, port);
+	else
+		yukon_mac_init(hw, port);
+
+	/* Configure RAMbuffers */
+	chunk = hw->ram_size / (isdualport(hw) ? 4 : 2);
+	ram_addr = hw->ram_offset + 2 * chunk * port;
+
+	skge_ramset(hw, rxqaddr[port], ram_addr, chunk);
+	skge_qset(skge, rxqaddr[port], skge->rx_ring.to_clean);
+
+	BUG_ON(skge->tx_ring.to_use != skge->tx_ring.to_clean);
+	skge_ramset(hw, txqaddr[port], ram_addr+chunk, chunk);
+	skge_qset(skge, txqaddr[port], skge->tx_ring.to_use);
+
+	/* Start receiver BMU */
+	wmb();
+	skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F);
+
+	pr_debug("skge_up completed\n");
+	return 0;
+
+ free_rx_ring:
+	skge_rx_clean(skge);
+	kfree(skge->rx_ring.start);
+ free_pci_mem:
+	pci_free_consistent(hw->pdev, skge->mem_size, skge->mem, skge->dma);
+
+	return err;
+}
+
+static int skge_down(struct net_device *dev)
+{
+	struct skge_port *skge = netdev_priv(dev);
+	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+
+	if (netif_msg_ifdown(skge))
+		printk(KERN_INFO PFX "%s: disabling interface\n", dev->name);
+
+	netif_stop_queue(dev);
+
+	del_timer_sync(&skge->led_blink);
+	del_timer_sync(&skge->link_check);
+
+	/* Stop transmitter */
+	skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP);
+	skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL),
+		     RB_RST_SET|RB_DIS_OP_MD);
+
+	if (hw->chip_id == CHIP_ID_GENESIS)
+		genesis_stop(skge);
+	else
+		yukon_stop(skge);
+
+	/* Disable Force Sync bit and Enable Alloc bit */
+	skge_write8(hw, SKGEMAC_REG(port, TXA_CTRL),
+		    TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
+
+	/* Stop Interval Timer and Limit Counter of Tx Arbiter */
+	skge_write32(hw, SKGEMAC_REG(port, TXA_ITI_INI), 0L);
+	skge_write32(hw, SKGEMAC_REG(port, TXA_LIM_INI), 0L);
+
+	/* Reset PCI FIFO */
+	skge_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_SET_RESET);
+	skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET);
+
+	/* Reset the RAM Buffer async Tx queue */
+	skge_write8(hw, RB_ADDR(port == 0 ? Q_XA1 : Q_XA2, RB_CTRL), RB_RST_SET);
+	/* stop receiver */
+	skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_STOP);
+	skge_write32(hw, RB_ADDR(port ? Q_R2 : Q_R1, RB_CTRL),
+		     RB_RST_SET|RB_DIS_OP_MD);
+	skge_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_SET_RESET);
+
+	if (hw->chip_id == CHIP_ID_GENESIS) {
+		skge_write8(hw, SKGEMAC_REG(port, TX_MFF_CTRL2), MFF_RST_SET);
+		skge_write8(hw, SKGEMAC_REG(port, RX_MFF_CTRL2), MFF_RST_SET);
+		skge_write8(hw, SKGEMAC_REG(port, TX_LED_CTRL), LED_STOP);
+		skge_write8(hw, SKGEMAC_REG(port, RX_LED_CTRL), LED_STOP);
+	} else {
+		skge_write8(hw, SKGEMAC_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
+		skge_write8(hw, SKGEMAC_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
+	}
+
+	/* turn off led's */
+	skge_write16(hw, B0_LED, LED_STAT_OFF);
+
+	skge_tx_clean(skge);
+	skge_rx_clean(skge);
+
+	kfree(skge->rx_ring.start);
+	kfree(skge->tx_ring.start);
+	pci_free_consistent(hw->pdev, skge->mem_size, skge->mem, skge->dma);
+	return 0;
+}
+
+static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev)
+{
+	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)
+		return NETDEV_TX_OK;
+
+	local_irq_save(flags);
+	if (!spin_trylock(&skge->tx_lock)) {
+ 		/* Collision - tell upper layer to requeue */ 
+ 		local_irq_restore(flags); 
+ 		return NETDEV_TX_LOCKED; 
+ 	} 
+
+	if (unlikely(skge->tx_avail < skb_shinfo(skb)->nr_frags +1)) {
+		netif_stop_queue(dev);
+		spin_unlock_irqrestore(&skge->tx_lock, flags);
+
+		printk(KERN_WARNING PFX "%s: ring full when queue awake!\n",
+		       dev->name);
+		return NETDEV_TX_BUSY;
+	}
+
+	e = ring->to_use;
+	td = e->desc;
+	e->skb = skb;
+	len = skb_headlen(skb);
+	map = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE);
+	pci_unmap_addr_set(e, mapaddr, map);
+	pci_unmap_len_set(e, maplen, len);
+
+	td->dma_lo = map;
+	td->dma_hi = map >> 32;
+
+	if (skb->ip_summed == CHECKSUM_HW) {
+		const struct iphdr *ip
+			= (const struct iphdr *) (skb->data + ETH_HLEN);
+		int offset = skb->h.raw - skb->data;
+
+		/* This seems backwards, but it is what the sk98lin
+		 * does.  Looks like hardware is wrong?
+		 */
+		if (ip->protocol == IPPROTO_UDP
+	            && chip_rev(hw) == 0 && hw->chip_id == CHIP_ID_YUKON)
+			control = BMU_TCP_CHECK;
+		else
+			control = BMU_UDP_CHECK;
+
+		td->csum_offs = 0;
+		td->csum_start = offset;
+		td->csum_write = offset + skb->csum;
+	} else
+		control = BMU_CHECK;
+
+	if (!skb_shinfo(skb)->nr_frags) /* single buffer i.e. no fragments */
+		control |= BMU_EOF| BMU_IRQ_EOF;
+	else {
+		struct skge_tx_desc *tf = td;
+
+		control |= BMU_STFWD;
+		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+			map = pci_map_page(hw->pdev, frag->page, frag->page_offset,
+					   frag->size, PCI_DMA_TODEVICE);
+
+			e = e->next;
+			e->skb = NULL;
+			tf = e->desc;
+			tf->dma_lo = map;
+			tf->dma_hi = (u64) map >> 32;
+			pci_unmap_addr_set(e, mapaddr, map);
+			pci_unmap_len_set(e, maplen, frag->size);
+
+			tf->control = BMU_OWN | BMU_SW | control | frag->size;
+		}
+		tf->control |= BMU_EOF | BMU_IRQ_EOF;
+	}
+	/* Make sure all the descriptors written */
+	wmb();
+	td->control = BMU_OWN | BMU_SW | BMU_STF | control | len;
+	wmb();
+
+	skge_write8(hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_START);
+
+	if (netif_msg_tx_queued(skge))
+		printk(KERN_DEBUG "%s: tx queued, slot %td, len %d\n",
+		       dev->name, e - ring->start, skb->len);
+
+	ring->to_use = e->next;
+	skge->tx_avail -= skb_shinfo(skb)->nr_frags + 1;
+	if (skge->tx_avail <= MAX_SKB_FRAGS + 1) {
+		pr_debug("%s: transmit queue full\n", dev->name);
+		netif_stop_queue(dev);
+	}
+
+	dev->trans_start = jiffies;
+	spin_unlock_irqrestore(&skge->tx_lock, flags);
+
+	return NETDEV_TX_OK;
+}
+
+static inline void skge_tx_free(struct skge_hw *hw, struct skge_element *e)
+{
+	if (e->skb) {
+		pci_unmap_single(hw->pdev,
+			       pci_unmap_addr(e, mapaddr),
+			       pci_unmap_len(e, maplen),
+			       PCI_DMA_TODEVICE);
+		dev_kfree_skb_any(e->skb);
+		e->skb = NULL;
+	} else {
+		pci_unmap_page(hw->pdev,
+			       pci_unmap_addr(e, mapaddr),
+			       pci_unmap_len(e, maplen),
+			       PCI_DMA_TODEVICE);
+	}
+}
+
+static void skge_tx_clean(struct skge_port *skge)
+{
+	struct skge_ring *ring = &skge->tx_ring;
+	struct skge_element *e;
+	unsigned long flags;
+
+	spin_lock_irqsave(&skge->tx_lock, flags);
+	for (e = ring->to_clean; e != ring->to_use; e = e->next) {
+		++skge->tx_avail;
+		skge_tx_free(skge->hw, e);
+	}
+	ring->to_clean = e;
+	spin_unlock_irqrestore(&skge->tx_lock, flags);
+}
+
+static void skge_tx_timeout(struct net_device *dev)
+{
+	struct skge_port *skge = netdev_priv(dev);
+
+	if (netif_msg_timer(skge))
+		printk(KERN_DEBUG PFX "%s: tx timeout\n", dev->name);
+
+	skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_STOP);
+	skge_tx_clean(skge);
+}
+
+static int skge_change_mtu(struct net_device *dev, int new_mtu)
+{
+	int err = 0;
+
+	if(new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
+		return -EINVAL;
+
+	dev->mtu = new_mtu;
+
+	if (netif_running(dev)) {
+		skge_down(dev);
+		skge_up(dev);
+	}
+
+	return err;
+}
+
+static void genesis_set_multicast(struct net_device *dev)
+{
+	struct skge_port *skge = netdev_priv(dev);
+	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+	int i, count = dev->mc_count;
+	struct dev_mc_list *list = dev->mc_list;
+	u32 mode;
+	u8 filter[8];
+
+	mode = skge_xm_read32(hw, port, XM_MODE);
+	mode |= XM_MD_ENA_HASH;
+	if (dev->flags & IFF_PROMISC)
+		mode |= XM_MD_ENA_PROM;
+	else
+		mode &= ~XM_MD_ENA_PROM;
+
+	if (dev->flags & IFF_ALLMULTI)
+		memset(filter, 0xff, sizeof(filter));
+	else {
+		memset(filter, 0, sizeof(filter));
+		for(i = 0; list && i < count; i++, list = list->next) {
+			u32 crc = crc32_le(~0, list->dmi_addr, ETH_ALEN);
+			u8 bit = 63 - (crc & 63);
+
+			filter[bit/8] |= 1 << (bit%8);
+		}
+	}
+
+	skge_xm_outhash(hw, port, XM_HSM, filter);
+
+	skge_xm_write32(hw, port, XM_MODE, mode);
+}
+
+static void yukon_set_multicast(struct net_device *dev)
+{
+	struct skge_port *skge = netdev_priv(dev);
+	struct skge_hw *hw = skge->hw;
+	int port = skge->port;
+	struct dev_mc_list *list = dev->mc_list;
+	u16 reg;
+	u8 filter[8];
+
+	memset(filter, 0, sizeof(filter));
+
+	reg = skge_gma_read16(hw, port, GM_RX_CTRL);
+	reg |= GM_RXCR_UCF_ENA;
+
+	if (dev->flags & IFF_PROMISC) 		/* promiscious */
+		reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
+	else if (dev->flags & IFF_ALLMULTI)	/* all multicast */
+		memset(filter, 0xff, sizeof(filter));
+	else if (dev->mc_count == 0)		/* no multicast */
+		reg &= ~GM_RXCR_MCF_ENA;
+	else {
+		int i;
+		reg |= GM_RXCR_MCF_ENA;
+
+		for(i = 0; list && i < dev->mc_count; i++, list = list->next) {
+			u32 bit = ether_crc(ETH_ALEN, list->dmi_addr) & 0x3f;
+			filter[bit/8] |= 1 << (bit%8);
+		}
+	}
+
+
+	skge_gma_write16(hw, port, GM_MC_ADDR_H1,
+			 (u16)filter[0] | ((u16)filter[1] << 8));
+	skge_gma_write16(hw, port, GM_MC_ADDR_H2,
+			 (u16)filter[2] | ((u16)filter[3] << 8));
+	skge_gma_write16(hw, port, GM_MC_ADDR_H3,
+			 (u16)filter[4] | ((u16)filter[5] << 8));
+	skge_gma_write16(hw, port, GM_MC_ADDR_H4,
+			 (u16)filter[6] | ((u16)filter[7] << 8));
+
+	skge_gma_write16(hw, port, GM_RX_CTRL, reg);
+}
+
+static inline int bad_phy_status(const struct skge_hw *hw, u32 status)
+{
+	if (hw->chip_id == CHIP_ID_GENESIS)
+		return (status & (XMR_FS_ERR | XMR_FS_2L_VLAN)) != 0;
+	else
+		return (status & GMR_FS_ANY_ERR) ||
+			(status & GMR_FS_RX_OK) == 0;
+}
+
+static void skge_rx_error(struct skge_port *skge, int slot,
+			  u32 control, u32 status)
+{
+	if (netif_msg_rx_err(skge))
+		printk(KERN_DEBUG PFX "%s: rx err, slot %d control 0x%x status 0x%x\n",
+		       skge->netdev->name, slot, control, status);
+
+	if ((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF)
+	    || (control & BMU_BBC) > skge->netdev->mtu + VLAN_ETH_HLEN)
+		skge->net_stats.rx_length_errors++;
+	else {
+		if (skge->hw->chip_id == CHIP_ID_GENESIS) {
+			if (status & (XMR_FS_RUNT|XMR_FS_LNG_ERR))
+				skge->net_stats.rx_length_errors++;
+			if (status & XMR_FS_FRA_ERR)
+				skge->net_stats.rx_frame_errors++;
+			if (status & XMR_FS_FCS_ERR)
+				skge->net_stats.rx_crc_errors++;
+		} else {
+			if (status & (GMR_FS_LONG_ERR|GMR_FS_UN_SIZE))
+				skge->net_stats.rx_length_errors++;
+			if (status & GMR_FS_FRAGMENT)
+				skge->net_stats.rx_frame_errors++;
+			if (status & GMR_FS_CRC_ERR)
+				skge->net_stats.rx_crc_errors++;
+		}
+	}
+}
+
+static int skge_poll(struct net_device *dev, int *budget)
+{
+	struct skge_port *skge = netdev_priv(dev);
+	struct skge_hw *hw = skge->hw;
+	struct skge_ring *ring = &skge->rx_ring;
+	struct skge_element *e;
+	unsigned int to_do = min(dev->quota, *budget);
+	unsigned int work_done = 0;
+	int done;
+	static const u32 irqmask[] = { IS_PORT_1, IS_PORT_2 };
+
+	for (e = ring->to_clean; e != ring->to_use && work_done < to_do;
+	     e = e->next) {
+		struct skge_rx_desc *rd = e->desc;
+		struct sk_buff *skb = e->skb;
+		u32 control, len, status;
+
+		rmb();
+		control = rd->control;
+		if (control & BMU_OWN)
+			break;
+
+		len = control & BMU_BBC;
+		e->skb = NULL;
+
+		pci_unmap_single(hw->pdev,
+				 pci_unmap_addr(e, mapaddr),
+				 pci_unmap_len(e, maplen),
+				 PCI_DMA_FROMDEVICE);
+
+		status = rd->status;
+		if ((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF)
+		     || len > dev->mtu + VLAN_ETH_HLEN
+		     || bad_phy_status(hw, status)) {
+			skge_rx_error(skge, e - ring->start, control, status);
+			dev_kfree_skb(skb);
+			continue;
+		}
+
+		if (netif_msg_rx_status(skge))
+		    printk(KERN_DEBUG PFX "%s: rx slot %td status 0x%x len %d\n",
+			   dev->name, e - ring->start, rd->status, len);
+
+		skb_put(skb, len);
+		skb->protocol = eth_type_trans(skb, dev);
+
+		if (skge->rx_csum) {
+			skb->csum = le16_to_cpu(rd->csum2);
+			skb->ip_summed = CHECKSUM_HW;
+		}
+
+		dev->last_rx = jiffies;
+		netif_receive_skb(skb);
+
+		++work_done;
+	}
+	ring->to_clean = e;
+
+	*budget -= work_done;
+	dev->quota -= work_done;
+	done = work_done < to_do;
+
+	if (skge_rx_fill(skge))
+		done = 0;
+
+	/* restart receiver */
+	wmb();
+	skge_write8(hw, Q_ADDR(rxqaddr[skge->port], Q_CSR),
+		    CSR_START | CSR_IRQ_CL_F);
+
+	if (done) {
+		local_irq_disable();
+		hw->intr_mask |= irqmask[skge->port];
+		/* Order is important since data can get interrupted */
+		skge_write32(hw, B0_IMSK, hw->intr_mask);
+		__netif_rx_complete(dev);
+		local_irq_enable();
+	}
+
+	return !done;
+}
+
+static inline void skge_tx_intr(struct net_device *dev)
+{
+	struct skge_port *skge = netdev_priv(dev);
+	struct skge_hw *hw = skge->hw;
+	struct skge_ring *ring = &skge->tx_ring;
+	struct skge_element *e;
+
+	spin_lock(&skge->tx_lock);
+	for(e = ring->to_clean; e != ring->to_use; e = e->next) {
+		struct skge_tx_desc *td = e->desc;
+		u32 control;
+
+		rmb();
+		control = td->control;
+		if (control & BMU_OWN)
+			break;
+
+		if (unlikely(netif_msg_tx_done(skge)))
+			printk(KERN_DEBUG PFX "%s: tx done slot %td status 0x%x\n",
+			       dev->name, e - ring->start, td->status);
+
+		skge_tx_free(hw, e);
+		e->skb = NULL;
+		++skge->tx_avail;
+	}
+	ring->to_clean = e;
+	skge_write8(hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F);
+
+	if (skge->tx_avail > MAX_SKB_FRAGS + 1)
+		netif_wake_queue(dev);
+
+	spin_unlock(&skge->tx_lock);
+}
+
+static void skge_mac_parity(struct skge_hw *hw, int port)
+{
+	printk(KERN_ERR PFX "%s: mac data parity error\n",
+	       hw->dev[port] ? hw->dev[port]->name
+	       : (port == 0 ? "(port A)": "(port B"));
+
+	if (hw->chip_id == CHIP_ID_GENESIS)
+		skge_write16(hw, SKGEMAC_REG(port, TX_MFF_CTRL1),
+			     MFF_CLR_PERR);
+	else
+		/* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */
+		skge_write8(hw, SKGEMAC_REG(port, TX_GMF_CTRL_T),
+			    (hw->chip_id == CHIP_ID_YUKON && chip_rev(hw) == 0)
+			    ? GMF_CLI_TX_FC : GMF_CLI_TX_PE);
+}
+
+static void skge_pci_clear(struct skge_hw *hw)
+{
+	u16 status;
+
+	status = skge_read16(hw, SKGEPCI_REG(PCI_STATUS));
+	skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+	skge_write16(hw, SKGEPCI_REG(PCI_STATUS),
+		     status | PCI_STATUS_ERROR_BITS);
+	skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+}
+
+static void skge_mac_intr(struct skge_hw *hw, int port)
+{
+	if (hw->chip_id == CHIP_ID_GENESIS) 
+		genesis_mac_intr(hw, port);
+	else
+		yukon_mac_intr(hw, port);
+}
+
+/* Handle device specific framing and timeout interrupts */
+static void skge_error_irq(struct skge_hw *hw)
+{
+	u32 hwstatus = skge_read32(hw, B0_HWE_ISRC);
+
+	if (hw->chip_id == CHIP_ID_GENESIS) {
+		/* clear xmac errors */
+		if (hwstatus & (IS_NO_STAT_M1|IS_NO_TIST_M1))
+			skge_write16(hw, SKGEMAC_REG(0, RX_MFF_CTRL1), MFF_CLR_INSTAT);
+		if (hwstatus & (IS_NO_STAT_M2|IS_NO_TIST_M2))
+			skge_write16(hw, SKGEMAC_REG(0, RX_MFF_CTRL2), MFF_CLR_INSTAT);
+	} else {
+		/* Timestamp (unused) overflow */
+		if (hwstatus & IS_IRQ_TIST_OV)
+			skge_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ);
+
+		if (hwstatus & IS_IRQ_SENSOR) {
+			/* no sensors on 32-bit Yukon */
+			if (!(skge_read16(hw, B0_CTST) & CS_BUS_SLOT_SZ)) {
+				printk(KERN_ERR PFX "ignoring bogus sensor interrups\n");
+				skge_write32(hw, B0_HWE_IMSK,
+					     IS_ERR_MSK & ~IS_IRQ_SENSOR);
+			} else
+				printk(KERN_WARNING PFX "sensor interrupt\n");
+		}
+
+
+	}
+
+	if (hwstatus & IS_RAM_RD_PAR) {
+		printk(KERN_ERR PFX "Ram read data parity error\n");
+		skge_write16(hw, B3_RI_CTRL, RI_CLR_RD_PERR);
+	}
+
+	if (hwstatus & IS_RAM_WR_PAR) {
+		printk(KERN_ERR PFX "Ram write data parity error\n");
+		skge_write16(hw, B3_RI_CTRL, RI_CLR_WR_PERR);
+	}
+
+	if (hwstatus & IS_M1_PAR_ERR)
+		skge_mac_parity(hw, 0);
+
+	if (hwstatus & IS_M2_PAR_ERR)
+		skge_mac_parity(hw, 1);
+
+	if (hwstatus & IS_R1_PAR_ERR)
+		skge_write32(hw, B0_R1_CSR, CSR_IRQ_CL_P);
+
+	if (hwstatus & IS_R2_PAR_ERR)
+		skge_write32(hw, B0_R2_CSR, CSR_IRQ_CL_P);
+
+	if (hwstatus & (IS_IRQ_MST_ERR|IS_IRQ_STAT)) {
+		printk(KERN_ERR PFX "hardware error detected (status 0x%x)\n",
+		       hwstatus);
+
+		skge_pci_clear(hw);
+
+		hwstatus = skge_read32(hw, B0_HWE_ISRC);
+		if (hwstatus & IS_IRQ_STAT) {
+			printk(KERN_WARNING PFX "IRQ status %x: still set ignoring hardware errors\n",
+			       hwstatus);
+			hw->intr_mask &= ~IS_HW_ERR;
+		}
+	}
+}
+
+/*
+ * Interrrupt from PHY are handled in tasklet (soft irq)
+ * because accessing phy registers requires spin wait which might
+ * cause excess interrupt latency.
+ */
+static void skge_extirq(unsigned long data)
+{
+	struct skge_hw *hw = (struct skge_hw *) data;
+	int port;
+
+	spin_lock(&hw->phy_lock);
+	for (port = 0; port < 2; port++) {
+		struct net_device *dev = hw->dev[port];
+
+		if (dev && netif_running(dev)) {
+			struct skge_port *skge = netdev_priv(dev);
+
+			if (hw->chip_id != CHIP_ID_GENESIS)
+				yukon_phy_intr(skge);
+			else if (hw->phy_type == SK_PHY_BCOM)
+				genesis_bcom_intr(skge);
+		}
+	}
+	spin_unlock(&hw->phy_lock);
+
+	local_irq_disable();
+	hw->intr_mask |= IS_EXT_REG;
+	skge_write32(hw, B0_IMSK, hw->intr_mask);
+	local_irq_enable();
+}
+
+static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct skge_hw *hw = dev_id;
+	u32 status = skge_read32(hw, B0_SP_ISRC);
+
+	if (status == 0 || status == ~0) /* hotplug or shared irq */
+		return IRQ_NONE;
+
+	status &= hw->intr_mask;
+
+	if ((status & IS_R1_F) && netif_rx_schedule_prep(hw->dev[0])) {
+		status &= ~IS_R1_F;
+		hw->intr_mask &= ~IS_R1_F;
+		skge_write32(hw, B0_IMSK, hw->intr_mask);
+		__netif_rx_schedule(hw->dev[0]);
+	}
+
+	if ((status & IS_R2_F) && netif_rx_schedule_prep(hw->dev[1])) {
+		status &= ~IS_R2_F;
+		hw->intr_mask &= ~IS_R2_F;
+		skge_write32(hw, B0_IMSK, hw->intr_mask);
+		__netif_rx_schedule(hw->dev[1]);
+	}
+
+	if (status & IS_XA1_F)
+		skge_tx_intr(hw->dev[0]);
+
+	if (status & IS_XA2_F)
+		skge_tx_intr(hw->dev[1]);
+
+	if (status & IS_MAC1)
+		skge_mac_intr(hw, 0);
+	
+	if (status & IS_MAC2)
+		skge_mac_intr(hw, 1);
+
+	if (status & IS_HW_ERR)
+		skge_error_irq(hw);
+
+	if (status & IS_EXT_REG) {
+		hw->intr_mask &= ~IS_EXT_REG;
+		tasklet_schedule(&hw->ext_tasklet);
+	}
+
+	if (status)
+		skge_write32(hw, B0_IMSK, hw->intr_mask);
+
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void skge_netpoll(struct net_device *dev)
+{
+	struct skge_port *skge = netdev_priv(dev);
+
+	disable_irq(dev->irq);
+	skge_intr(dev->irq, skge->hw, NULL);
+	enable_irq(dev->irq);
+}
+#endif
+
+static int skge_set_mac_address(struct net_device *dev, void *p)
+{
+	struct skge_port *skge = netdev_priv(dev);
+	struct sockaddr *addr = p;
+	int err = 0;
+
+	if (!is_valid_ether_addr(addr->sa_data))
+		return -EADDRNOTAVAIL;
+
+	skge_down(dev);
+	memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
+	memcpy_toio(skge->hw->regs + B2_MAC_1 + skge->port*8,
+		    dev->dev_addr, ETH_ALEN);
+	memcpy_toio(skge->hw->regs + B2_MAC_2 + skge->port*8,
+		    dev->dev_addr, ETH_ALEN);
+	if (dev->flags & IFF_UP)
+		err = skge_up(dev);
+	return err;
+}
+
+static const struct {
+	u8 id;
+	const char *name;
+} skge_chips[] = {
+	{ CHIP_ID_GENESIS,	"Genesis" },
+	{ CHIP_ID_YUKON,	 "Yukon" },
+	{ CHIP_ID_YUKON_LITE,	 "Yukon-Lite"},
+	{ CHIP_ID_YUKON_LP,	 "Yukon-LP"},
+	{ CHIP_ID_YUKON_XL,	 "Yukon-2 XL"},
+	{ CHIP_ID_YUKON_EC,	 "YUKON-2 EC"},
+	{ CHIP_ID_YUKON_FE,	 "YUKON-2 FE"},
+};
+
+static const char *skge_board_name(const struct skge_hw *hw)
+{
+	int i;
+	static char buf[16];
+
+	for (i = 0; i < ARRAY_SIZE(skge_chips); i++)
+		if (skge_chips[i].id == hw->chip_id)
+			return skge_chips[i].name;
+
+	snprintf(buf, sizeof buf, "chipid 0x%x", hw->chip_id);
+	return buf;
+}
+
+
+/*
+ * Setup the board data structure, but don't bring up
+ * the port(s)
+ */
+static int skge_reset(struct skge_hw *hw)
+{
+	u16 ctst;
+	u8 t8;
+	int i, ports;
+
+	ctst = skge_read16(hw, B0_CTST);
+
+	/* do a SW reset */
+	skge_write8(hw, B0_CTST, CS_RST_SET);
+	skge_write8(hw, B0_CTST, CS_RST_CLR);
+
+	/* clear PCI errors, if any */
+	skge_pci_clear(hw);
+
+	skge_write8(hw, B0_CTST, CS_MRST_CLR);
+
+	/* restore CLK_RUN bits (for Yukon-Lite) */
+	skge_write16(hw, B0_CTST,
+		     ctst & (CS_CLK_RUN_HOT|CS_CLK_RUN_RST|CS_CLK_RUN_ENA));
+
+	hw->chip_id = skge_read8(hw, B2_CHIP_ID);
+	hw->phy_type = skge_read8(hw, B2_E_1) & 0xf;
+	hw->pmd_type = skge_read8(hw, B2_PMD_TYP);
+
+	switch(hw->chip_id) {
+	case CHIP_ID_GENESIS:
+		switch (hw->phy_type) {
+		case SK_PHY_XMAC:
+			hw->phy_addr = PHY_ADDR_XMAC;
+			break;
+		case SK_PHY_BCOM:
+			hw->phy_addr = PHY_ADDR_BCOM;
+			break;
+		default:
+			printk(KERN_ERR PFX "%s: unsupported phy type 0x%x\n",
+			       pci_name(hw->pdev), hw->phy_type);
+			return -EOPNOTSUPP;
+		}
+		break;
+
+	case CHIP_ID_YUKON:
+	case CHIP_ID_YUKON_LITE:
+	case CHIP_ID_YUKON_LP:
+		if (hw->phy_type < SK_PHY_MARV_COPPER && hw->pmd_type != 'S')
+			hw->phy_type = SK_PHY_MARV_COPPER;
+
+		hw->phy_addr = PHY_ADDR_MARV;
+		if (!iscopper(hw))
+			hw->phy_type = SK_PHY_MARV_FIBER;
+
+		break;
+
+	default:
+		printk(KERN_ERR PFX "%s: unsupported chip type 0x%x\n",
+		       pci_name(hw->pdev), hw->chip_id);
+		return -EOPNOTSUPP;
+	}
+
+	hw->mac_cfg = skge_read8(hw, B2_MAC_CFG);
+	ports = isdualport(hw) ? 2 : 1;
+
+	/* read the adapters RAM size */
+	t8 = skge_read8(hw, B2_E_0);
+	if (hw->chip_id == CHIP_ID_GENESIS) {
+		if (t8 == 3) {
+			/* special case: 4 x 64k x 36, offset = 0x80000 */
+			hw->ram_size = 0x100000;
+			hw->ram_offset = 0x80000;
+		} else
+			hw->ram_size = t8 * 512;
+	}
+	else if (t8 == 0)
+		hw->ram_size = 0x20000;
+	else
+		hw->ram_size = t8 * 4096;
+
+	if (hw->chip_id == CHIP_ID_GENESIS)
+		genesis_init(hw);
+	else {
+		/* switch power to VCC (WA for VAUX problem) */
+		skge_write8(hw, B0_POWER_CTRL,
+			    PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON);
+		for (i = 0; i < ports; i++) {
+			skge_write16(hw, SKGEMAC_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET);
+			skge_write16(hw, SKGEMAC_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
+		}
+	}
+
+	/* turn off hardware timer (unused) */
+	skge_write8(hw, B2_TI_CTRL, TIM_STOP);
+	skge_write8(hw, B2_TI_CTRL, TIM_CLR_IRQ);
+	skge_write8(hw, B0_LED, LED_STAT_ON);
+
+	/* enable the Tx Arbiters */
+	for (i = 0; i < ports; i++)
+		skge_write8(hw, SKGEMAC_REG(i, TXA_CTRL), TXA_ENA_ARB);
+
+	/* Initialize ram interface */
+	skge_write16(hw, B3_RI_CTRL, RI_RST_CLR);
+
+	skge_write8(hw, B3_RI_WTO_R1, SK_RI_TO_53);
+	skge_write8(hw, B3_RI_WTO_XA1, SK_RI_TO_53);
+	skge_write8(hw, B3_RI_WTO_XS1, SK_RI_TO_53);
+	skge_write8(hw, B3_RI_RTO_R1, SK_RI_TO_53);
+	skge_write8(hw, B3_RI_RTO_XA1, SK_RI_TO_53);
+	skge_write8(hw, B3_RI_RTO_XS1, SK_RI_TO_53);
+	skge_write8(hw, B3_RI_WTO_R2, SK_RI_TO_53);
+	skge_write8(hw, B3_RI_WTO_XA2, SK_RI_TO_53);
+	skge_write8(hw, B3_RI_WTO_XS2, SK_RI_TO_53);
+	skge_write8(hw, B3_RI_RTO_R2, SK_RI_TO_53);
+	skge_write8(hw, B3_RI_RTO_XA2, SK_RI_TO_53);
+	skge_write8(hw, B3_RI_RTO_XS2, SK_RI_TO_53);
+
+	skge_write32(hw, B0_HWE_IMSK, IS_ERR_MSK);
+
+	/* Set interrupt moderation for Transmit only
+	 * Receive interrupts avoided by NAPI
+	 */
+	skge_write32(hw, B2_IRQM_MSK, IS_XA1_F|IS_XA2_F);
+	skge_write32(hw, B2_IRQM_INI, skge_usecs2clk(hw, 100));
+	skge_write32(hw, B2_IRQM_CTRL, TIM_START);
+
+	hw->intr_mask = IS_HW_ERR | IS_EXT_REG | IS_PORT_1;
+	if (isdualport(hw))
+		hw->intr_mask |= IS_PORT_2;
+	skge_write32(hw, B0_IMSK, hw->intr_mask);
+
+	if (hw->chip_id != CHIP_ID_GENESIS)
+		skge_write8(hw, GMAC_IRQ_MSK, 0);
+
+	spin_lock_bh(&hw->phy_lock);
+	for (i = 0; i < ports; i++) {
+		if (hw->chip_id == CHIP_ID_GENESIS)
+			genesis_reset(hw, i);
+		else
+			yukon_reset(hw, i);
+	}
+	spin_unlock_bh(&hw->phy_lock);
+
+	return 0;
+}
+
+/* Initialize network device */
+static struct net_device *skge_devinit(struct skge_hw *hw, int port)
+{
+	struct skge_port *skge;
+	struct net_device *dev = alloc_etherdev(sizeof(*skge));
+
+	if (!dev) {
+		printk(KERN_ERR "skge etherdev alloc failed");
+		return NULL;
+	}
+
+	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &hw->pdev->dev);
+	dev->open = skge_up;
+	dev->stop = skge_down;
+	dev->hard_start_xmit = skge_xmit_frame;
+	dev->get_stats = skge_get_stats;
+	if (hw->chip_id == CHIP_ID_GENESIS)
+		dev->set_multicast_list = genesis_set_multicast;
+	else
+		dev->set_multicast_list = yukon_set_multicast;
+
+	dev->set_mac_address = skge_set_mac_address;
+	dev->change_mtu = skge_change_mtu;
+	SET_ETHTOOL_OPS(dev, &skge_ethtool_ops);
+	dev->tx_timeout = skge_tx_timeout;
+	dev->watchdog_timeo = TX_WATCHDOG;
+	dev->poll = skge_poll;
+	dev->weight = NAPI_WEIGHT;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	dev->poll_controller = skge_netpoll;
+#endif
+	dev->irq = hw->pdev->irq;
+	dev->features = NETIF_F_LLTX;
+
+	skge = netdev_priv(dev);
+	skge->netdev = dev;
+	skge->hw = hw;
+	skge->msg_enable = netif_msg_init(debug, default_msg);
+	skge->tx_ring.count = DEFAULT_TX_RING_SIZE;
+	skge->rx_ring.count = DEFAULT_RX_RING_SIZE;
+
+	/* Auto speed and flow control */
+	skge->autoneg = AUTONEG_ENABLE;
+	skge->flow_control = FLOW_MODE_SYMMETRIC;
+	skge->duplex = -1;
+	skge->speed = -1;
+	skge->advertising = skge_modes(hw);
+
+	hw->dev[port] = dev;
+
+	skge->port = port;
+
+	spin_lock_init(&skge->tx_lock);
+
+	init_timer(&skge->link_check);
+	skge->link_check.function = skge_link_timer;
+	skge->link_check.data = (unsigned long) skge;
+
+	init_timer(&skge->led_blink);
+	skge->led_blink.function = skge_blink_timer;
+	skge->led_blink.data = (unsigned long) skge;
+
+	if (hw->chip_id != CHIP_ID_GENESIS) {
+		dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+		skge->rx_csum = 1;
+	}
+
+	/* read the mac address */
+	memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port*8, ETH_ALEN);
+
+	/* device is off until link detection */
+	netif_carrier_off(dev);
+	netif_stop_queue(dev);
+
+	return dev;
+}
+
+static void __devinit skge_show_addr(struct net_device *dev)
+{
+	const struct skge_port *skge = netdev_priv(dev);
+
+	if (netif_msg_probe(skge))
+		printk(KERN_INFO PFX "%s: addr %02x:%02x:%02x:%02x:%02x:%02x\n",
+		       dev->name,
+		       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+		       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+}
+
+static int __devinit skge_probe(struct pci_dev *pdev,
+				const struct pci_device_id *ent)
+{
+	struct net_device *dev, *dev1;
+	struct skge_hw *hw;
+	int err, using_dac = 0;
+
+	if ((err = pci_enable_device(pdev))) {
+		printk(KERN_ERR PFX "%s cannot enable PCI device\n",
+		       pci_name(pdev));
+		goto err_out;
+	}
+
+	if ((err = pci_request_regions(pdev, DRV_NAME))) {
+		printk(KERN_ERR PFX "%s cannot obtain PCI resources\n",
+		       pci_name(pdev));
+		goto err_out_disable_pdev;
+	}
+
+	pci_set_master(pdev);
+
+	if (!(err = pci_set_dma_mask(pdev, DMA_64BIT_MASK)))
+		using_dac = 1;
+	else if (!(err = pci_set_dma_mask(pdev, DMA_32BIT_MASK))) {
+		printk(KERN_ERR PFX "%s no usable DMA configuration\n",
+		       pci_name(pdev));
+		goto err_out_free_regions;
+	}
+
+#ifdef __BIG_ENDIAN
+	/* byte swap decriptors in hardware */
+	{
+		u32 reg;
+
+		pci_read_config_dword(pdev, PCI_DEV_REG2, &reg);
+		reg |= PCI_REV_DESC;
+		pci_write_config_dword(pdev, PCI_DEV_REG2, reg);
+	}
+#endif
+
+	err = -ENOMEM;
+	hw = kmalloc(sizeof(*hw), GFP_KERNEL);
+	if (!hw) {
+		printk(KERN_ERR PFX "%s: cannot allocate hardware struct\n",
+		       pci_name(pdev));
+		goto err_out_free_regions;
+	}
+
+	memset(hw, 0, sizeof(*hw));
+	hw->pdev = pdev;
+	spin_lock_init(&hw->phy_lock);
+	tasklet_init(&hw->ext_tasklet, skge_extirq, (unsigned long) hw);
+
+	hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000);
+	if (!hw->regs) {
+		printk(KERN_ERR PFX "%s: cannot map device registers\n",
+		       pci_name(pdev));
+		goto err_out_free_hw;
+	}
+
+	if ((err = request_irq(pdev->irq, skge_intr, SA_SHIRQ, DRV_NAME, hw))) {
+		printk(KERN_ERR PFX "%s: cannot assign irq %d\n",
+		       pci_name(pdev), pdev->irq);
+		goto err_out_iounmap;
+	}
+	pci_set_drvdata(pdev, hw);
+
+	err = skge_reset(hw);
+	if (err)
+		goto err_out_free_irq;
+
+	printk(KERN_INFO PFX "addr 0x%lx irq %d chip %s rev %d\n",
+	       pci_resource_start(pdev, 0), pdev->irq,
+	       skge_board_name(hw), chip_rev(hw));
+
+	if ((dev = skge_devinit(hw, 0)) == NULL)
+		goto err_out_led_off;
+
+	if (using_dac)
+		dev->features |= NETIF_F_HIGHDMA;
+
+	if ((err = register_netdev(dev))) {
+		printk(KERN_ERR PFX "%s: cannot register net device\n",
+		       pci_name(pdev));
+		goto err_out_free_netdev;
+	}
+
+	skge_show_addr(dev);
+
+	if (isdualport(hw) && (dev1 = skge_devinit(hw, 1))) {
+		if (using_dac)
+			dev1->features |= NETIF_F_HIGHDMA;
+
+		if (register_netdev(dev1) == 0)
+			skge_show_addr(dev1);
+		else {
+			/* Failure to register second port need not be fatal */
+			printk(KERN_WARNING PFX "register of second port failed\n");
+			hw->dev[1] = NULL;
+			free_netdev(dev1);
+		}
+	}
+
+	return 0;
+
+err_out_free_netdev:
+	free_netdev(dev);
+err_out_led_off:
+	skge_write16(hw, B0_LED, LED_STAT_OFF);
+err_out_free_irq:
+	free_irq(pdev->irq, hw);
+err_out_iounmap:
+	iounmap(hw->regs);
+err_out_free_hw:
+	kfree(hw);
+err_out_free_regions:
+	pci_release_regions(pdev);
+err_out_disable_pdev:
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+err_out:
+	return err;
+}
+
+static void __devexit skge_remove(struct pci_dev *pdev)
+{
+	struct skge_hw *hw  = pci_get_drvdata(pdev);
+	struct net_device *dev0, *dev1;
+
+	if(!hw)
+		return;
+
+	if ((dev1 = hw->dev[1]))
+		unregister_netdev(dev1);
+	dev0 = hw->dev[0];
+	unregister_netdev(dev0);
+
+	tasklet_kill(&hw->ext_tasklet);
+
+	free_irq(pdev->irq, hw);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	if (dev1)
+		free_netdev(dev1);
+	free_netdev(dev0);
+	skge_write16(hw, B0_LED, LED_STAT_OFF);
+	iounmap(hw->regs);
+	kfree(hw);
+	pci_set_drvdata(pdev, NULL);
+}
+
+#ifdef CONFIG_PM
+static int skge_suspend(struct pci_dev *pdev, u32 state)
+{
+	struct skge_hw *hw  = pci_get_drvdata(pdev);
+	int i, wol = 0;
+
+	for(i = 0; i < 2; i++) {
+		struct net_device *dev = hw->dev[i];
+
+		if (dev) {
+			struct skge_port *skge = netdev_priv(dev);
+			if (netif_running(dev)) {
+				netif_carrier_off(dev);
+				skge_down(dev);
+			}
+			netif_device_detach(dev);
+			wol |= skge->wol;
+		}
+	}
+
+	pci_save_state(pdev);
+	pci_enable_wake(pdev, state, wol);
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+	return 0;
+}
+
+static int skge_resume(struct pci_dev *pdev)
+{
+	struct skge_hw *hw  = pci_get_drvdata(pdev);
+	int i;
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	pci_enable_wake(pdev, PCI_D0, 0);
+
+	skge_reset(hw);
+
+	for(i = 0; i < 2; i++) {
+		struct net_device *dev = hw->dev[i];
+		if (dev) {
+			netif_device_attach(dev);
+			if(netif_running(dev))
+				skge_up(dev);
+		}
+	}
+	return 0;
+}
+#endif
+
+static struct pci_driver skge_driver = {
+	.name =         DRV_NAME,
+	.id_table =     skge_id_table,
+	.probe =        skge_probe,
+	.remove =       __devexit_p(skge_remove),
+#ifdef CONFIG_PM
+	.suspend = 	skge_suspend,
+	.resume = 	skge_resume,
+#endif
+};
+
+static int __init skge_init_module(void)
+{
+	return pci_module_init(&skge_driver);
+}
+
+static void __exit skge_cleanup_module(void)
+{
+	pci_unregister_driver(&skge_driver);
+}
+
+module_init(skge_init_module);
+module_exit(skge_cleanup_module);
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
new file mode 100644
index 0000000..36c62b6
--- /dev/null
+++ b/drivers/net/skge.h
@@ -0,0 +1,3005 @@
+/*
+ * Definitions for the new Marvell Yukon / SysKonenct driver.
+ */
+#ifndef _SKGE_H
+#define _SKGE_H
+
+/* PCI config registers */
+#define PCI_DEV_REG1	0x40
+#define PCI_DEV_REG2	0x44
+#ifndef PCI_VPD
+#define PCI_VPD		0x50
+#endif
+
+/*	PCI_OUR_REG_2		32 bit	Our Register 2 */
+enum {
+	PCI_VPD_WR_THR  = 0xff<<24, /* Bit 31..24:	VPD Write Threshold */
+	PCI_DEV_SEL	= 0x7f<<17, /* Bit 23..17:	EEPROM Device Select */
+	PCI_VPD_ROM_SZ  = 7   <<14, /* Bit 16..14:	VPD ROM Size	*/
+ 				    /* Bit 13..12:	reserved	*/
+	PCI_EN_DUMMY_RD = 1<<3, /* Enable Dummy Read */
+	PCI_REV_DESC    = 1<<2, /* Reverse Desc. Bytes */
+	PCI_USEDATA64   = 1<<0, /* Use 64Bit Data bus ext */
+};
+
+/*	PCI_VPD_ADR_REG		16 bit	VPD Address Register */
+enum {
+	PCI_VPD_FLAG	= 1<<15,  /* starts VPD rd/wr cycle */
+	PCI_VPD_ADR_MSK =0x7fffL, /* Bit 14.. 0:	VPD Address Mask */
+	VPD_RES_ID	= 0x82,
+	VPD_RES_READ	= 0x90,
+	VPD_RES_WRITE	= 0x81,
+	VPD_RES_END	= 0x78,
+};
+
+
+#define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \
+			       PCI_STATUS_SIG_SYSTEM_ERROR | \
+			       PCI_STATUS_REC_MASTER_ABORT | \
+			       PCI_STATUS_REC_TARGET_ABORT | \
+			       PCI_STATUS_PARITY)
+
+
+enum csr_regs {
+	B0_RAP	= 0x0000,
+	B0_CTST	= 0x0004,
+	B0_LED	= 0x0006,
+	B0_POWER_CTRL	= 0x0007,
+	B0_ISRC	= 0x0008,
+	B0_IMSK	= 0x000c,
+	B0_HWE_ISRC	= 0x0010,
+	B0_HWE_IMSK	= 0x0014,
+	B0_SP_ISRC	= 0x0018,
+	B0_XM1_IMSK	= 0x0020,
+	B0_XM1_ISRC	= 0x0028,
+	B0_XM1_PHY_ADDR	= 0x0030,
+	B0_XM1_PHY_DATA	= 0x0034,
+	B0_XM2_IMSK	= 0x0040,
+	B0_XM2_ISRC	= 0x0048,
+	B0_XM2_PHY_ADDR	= 0x0050,
+	B0_XM2_PHY_DATA	= 0x0054,
+	B0_R1_CSR	= 0x0060,
+	B0_R2_CSR	= 0x0064,
+	B0_XS1_CSR	= 0x0068,
+	B0_XA1_CSR	= 0x006c,
+	B0_XS2_CSR	= 0x0070,
+	B0_XA2_CSR	= 0x0074,
+
+	B2_MAC_1	= 0x0100,
+	B2_MAC_2	= 0x0108,
+	B2_MAC_3	= 0x0110,
+	B2_CONN_TYP	= 0x0118,
+	B2_PMD_TYP	= 0x0119,
+	B2_MAC_CFG	= 0x011a,
+	B2_CHIP_ID	= 0x011b,
+	B2_E_0		= 0x011c,
+	B2_E_1		= 0x011d,
+	B2_E_2		= 0x011e,
+	B2_E_3		= 0x011f,
+	B2_FAR		= 0x0120,
+	B2_FDP		= 0x0124,
+	B2_LD_CTRL	= 0x0128,
+	B2_LD_TEST	= 0x0129,
+	B2_TI_INI	= 0x0130,
+	B2_TI_VAL	= 0x0134,
+	B2_TI_CTRL	= 0x0138,
+	B2_TI_TEST	= 0x0139,
+	B2_IRQM_INI	= 0x0140,
+	B2_IRQM_VAL	= 0x0144,
+	B2_IRQM_CTRL	= 0x0148,
+	B2_IRQM_TEST	= 0x0149,
+	B2_IRQM_MSK	= 0x014c,
+	B2_IRQM_HWE_MSK	= 0x0150,
+	B2_TST_CTRL1	= 0x0158,
+	B2_TST_CTRL2	= 0x0159,
+	B2_GP_IO	= 0x015c,
+	B2_I2C_CTRL	= 0x0160,
+	B2_I2C_DATA	= 0x0164,
+	B2_I2C_IRQ	= 0x0168,
+	B2_I2C_SW	= 0x016c,
+	B2_BSC_INI	= 0x0170,
+	B2_BSC_VAL	= 0x0174,
+	B2_BSC_CTRL	= 0x0178,
+	B2_BSC_STAT	= 0x0179,
+	B2_BSC_TST	= 0x017a,
+
+	B3_RAM_ADDR	= 0x0180,
+	B3_RAM_DATA_LO	= 0x0184,
+	B3_RAM_DATA_HI	= 0x0188,
+	B3_RI_WTO_R1	= 0x0190,
+	B3_RI_WTO_XA1	= 0x0191,
+	B3_RI_WTO_XS1	= 0x0192,
+	B3_RI_RTO_R1	= 0x0193,
+	B3_RI_RTO_XA1	= 0x0194,
+	B3_RI_RTO_XS1	= 0x0195,
+	B3_RI_WTO_R2	= 0x0196,
+	B3_RI_WTO_XA2	= 0x0197,
+	B3_RI_WTO_XS2	= 0x0198,
+	B3_RI_RTO_R2	= 0x0199,
+	B3_RI_RTO_XA2	= 0x019a,
+	B3_RI_RTO_XS2	= 0x019b,
+	B3_RI_TO_VAL	= 0x019c,
+	B3_RI_CTRL	= 0x01a0,
+	B3_RI_TEST	= 0x01a2,
+	B3_MA_TOINI_RX1	= 0x01b0,
+	B3_MA_TOINI_RX2	= 0x01b1,
+	B3_MA_TOINI_TX1	= 0x01b2,
+	B3_MA_TOINI_TX2	= 0x01b3,
+	B3_MA_TOVAL_RX1	= 0x01b4,
+	B3_MA_TOVAL_RX2	= 0x01b5,
+	B3_MA_TOVAL_TX1	= 0x01b6,
+	B3_MA_TOVAL_TX2	= 0x01b7,
+	B3_MA_TO_CTRL	= 0x01b8,
+	B3_MA_TO_TEST	= 0x01ba,
+	B3_MA_RCINI_RX1	= 0x01c0,
+	B3_MA_RCINI_RX2	= 0x01c1,
+	B3_MA_RCINI_TX1	= 0x01c2,
+	B3_MA_RCINI_TX2	= 0x01c3,
+	B3_MA_RCVAL_RX1	= 0x01c4,
+	B3_MA_RCVAL_RX2	= 0x01c5,
+	B3_MA_RCVAL_TX1	= 0x01c6,
+	B3_MA_RCVAL_TX2	= 0x01c7,
+	B3_MA_RC_CTRL	= 0x01c8,
+	B3_MA_RC_TEST	= 0x01ca,
+	B3_PA_TOINI_RX1	= 0x01d0,
+	B3_PA_TOINI_RX2	= 0x01d4,
+	B3_PA_TOINI_TX1	= 0x01d8,
+	B3_PA_TOINI_TX2	= 0x01dc,
+	B3_PA_TOVAL_RX1	= 0x01e0,
+	B3_PA_TOVAL_RX2	= 0x01e4,
+	B3_PA_TOVAL_TX1	= 0x01e8,
+	B3_PA_TOVAL_TX2	= 0x01ec,
+	B3_PA_CTRL	= 0x01f0,
+	B3_PA_TEST	= 0x01f2,
+};
+
+/*	B0_CTST			16 bit	Control/Status register */
+enum {
+	CS_CLK_RUN_HOT	= 1<<13,/* CLK_RUN hot m. (YUKON-Lite only) */
+	CS_CLK_RUN_RST	= 1<<12,/* CLK_RUN reset  (YUKON-Lite only) */
+	CS_CLK_RUN_ENA	= 1<<11,/* CLK_RUN enable (YUKON-Lite only) */
+	CS_VAUX_AVAIL	= 1<<10,/* VAUX available (YUKON only) */
+	CS_BUS_CLOCK	= 1<<9,	/* Bus Clock 0/1 = 33/66 MHz */
+	CS_BUS_SLOT_SZ	= 1<<8,	/* Slot Size 0/1 = 32/64 bit slot */
+	CS_ST_SW_IRQ	= 1<<7,	/* Set IRQ SW Request */
+	CS_CL_SW_IRQ	= 1<<6,	/* Clear IRQ SW Request */
+	CS_STOP_DONE	= 1<<5,	/* Stop Master is finished */
+	CS_STOP_MAST	= 1<<4,	/* Command Bit to stop the master */
+	CS_MRST_CLR	= 1<<3,	/* Clear Master reset	*/
+	CS_MRST_SET	= 1<<2,	/* Set Master reset	*/
+	CS_RST_CLR	= 1<<1,	/* Clear Software reset	*/
+	CS_RST_SET	= 1,	/* Set   Software reset	*/
+
+/*	B0_LED			 8 Bit	LED register */
+/* Bit  7.. 2:	reserved */
+	LED_STAT_ON	= 1<<1,	/* Status LED on	*/
+	LED_STAT_OFF	= 1,		/* Status LED off	*/
+
+/*	B0_POWER_CTRL	 8 Bit	Power Control reg (YUKON only) */
+	PC_VAUX_ENA	= 1<<7,	/* Switch VAUX Enable  */
+	PC_VAUX_DIS	= 1<<6,	/* Switch VAUX Disable */
+	PC_VCC_ENA	= 1<<5,	/* Switch VCC Enable  */
+	PC_VCC_DIS	= 1<<4,	/* Switch VCC Disable */
+	PC_VAUX_ON	= 1<<3,	/* Switch VAUX On  */
+	PC_VAUX_OFF	= 1<<2,	/* Switch VAUX Off */
+	PC_VCC_ON	= 1<<1,	/* Switch VCC On  */
+	PC_VCC_OFF	= 1<<0,	/* Switch VCC Off */
+};
+
+/*	B2_IRQM_MSK 	32 bit	IRQ Moderation Mask */
+enum {
+	IS_ALL_MSK	= 0xbffffffful,	/* All Interrupt bits */
+	IS_HW_ERR	= 1<<31,	/* Interrupt HW Error */
+					/* Bit 30:	reserved */
+	IS_PA_TO_RX1	= 1<<29,	/* Packet Arb Timeout Rx1 */
+	IS_PA_TO_RX2	= 1<<28,	/* Packet Arb Timeout Rx2 */
+	IS_PA_TO_TX1	= 1<<27,	/* Packet Arb Timeout Tx1 */
+	IS_PA_TO_TX2	= 1<<26,	/* Packet Arb Timeout Tx2 */
+	IS_I2C_READY	= 1<<25,	/* IRQ on end of I2C Tx */
+	IS_IRQ_SW	= 1<<24,	/* SW forced IRQ	*/
+	IS_EXT_REG	= 1<<23,	/* IRQ from LM80 or PHY (GENESIS only) */
+					/* IRQ from PHY (YUKON only) */
+	IS_TIMINT	= 1<<22,	/* IRQ from Timer	*/
+	IS_MAC1		= 1<<21,	/* IRQ from MAC 1	*/
+	IS_LNK_SYNC_M1	= 1<<20,	/* Link Sync Cnt wrap MAC 1 */
+	IS_MAC2		= 1<<19,	/* IRQ from MAC 2	*/
+	IS_LNK_SYNC_M2	= 1<<18,	/* Link Sync Cnt wrap MAC 2 */
+/* Receive Queue 1 */
+	IS_R1_B		= 1<<17,	/* Q_R1 End of Buffer */
+	IS_R1_F		= 1<<16,	/* Q_R1 End of Frame */
+	IS_R1_C		= 1<<15,	/* Q_R1 Encoding Error */
+/* Receive Queue 2 */
+	IS_R2_B		= 1<<14,	/* Q_R2 End of Buffer */
+	IS_R2_F		= 1<<13,	/* Q_R2 End of Frame */
+	IS_R2_C		= 1<<12,	/* Q_R2 Encoding Error */
+/* Synchronous Transmit Queue 1 */
+	IS_XS1_B	= 1<<11,	/* Q_XS1 End of Buffer */
+	IS_XS1_F	= 1<<10,	/* Q_XS1 End of Frame */
+	IS_XS1_C	= 1<<9,		/* Q_XS1 Encoding Error */
+/* Asynchronous Transmit Queue 1 */
+	IS_XA1_B	= 1<<8,		/* Q_XA1 End of Buffer */
+	IS_XA1_F	= 1<<7,		/* Q_XA1 End of Frame */
+	IS_XA1_C	= 1<<6,		/* Q_XA1 Encoding Error */
+/* Synchronous Transmit Queue 2 */
+	IS_XS2_B	= 1<<5,		/* Q_XS2 End of Buffer */
+	IS_XS2_F	= 1<<4,		/* Q_XS2 End of Frame */
+	IS_XS2_C	= 1<<3,		/* Q_XS2 Encoding Error */
+/* Asynchronous Transmit Queue 2 */
+	IS_XA2_B	= 1<<2,		/* Q_XA2 End of Buffer */
+	IS_XA2_F	= 1<<1,		/* Q_XA2 End of Frame */
+	IS_XA2_C	= 1<<0,		/* Q_XA2 Encoding Error */
+
+	IS_PORT_1	= IS_XA1_F| IS_R1_F| IS_MAC1,
+	IS_PORT_2	= IS_XA2_F| IS_R2_F| IS_MAC2,
+};
+
+
+/*	B2_IRQM_HWE_MSK	32 bit	IRQ Moderation HW Error Mask */
+enum {
+	IS_ERR_MSK	= 0x00003fff,/* 		All Error bits */
+
+	IS_IRQ_TIST_OV	= 1<<13, /* Time Stamp Timer Overflow (YUKON only) */
+	IS_IRQ_SENSOR	= 1<<12, /* IRQ from Sensor (YUKON only) */
+	IS_IRQ_MST_ERR	= 1<<11, /* IRQ master error detected */
+	IS_IRQ_STAT	= 1<<10, /* IRQ status exception */
+	IS_NO_STAT_M1	= 1<<9,	/* No Rx Status from MAC 1 */
+	IS_NO_STAT_M2	= 1<<8,	/* No Rx Status from MAC 2 */
+	IS_NO_TIST_M1	= 1<<7,	/* No Time Stamp from MAC 1 */
+	IS_NO_TIST_M2	= 1<<6,	/* No Time Stamp from MAC 2 */
+	IS_RAM_RD_PAR	= 1<<5,	/* RAM Read  Parity Error */
+	IS_RAM_WR_PAR	= 1<<4,	/* RAM Write Parity Error */
+	IS_M1_PAR_ERR	= 1<<3,	/* MAC 1 Parity Error */
+	IS_M2_PAR_ERR	= 1<<2,	/* MAC 2 Parity Error */
+	IS_R1_PAR_ERR	= 1<<1,	/* Queue R1 Parity Error */
+	IS_R2_PAR_ERR	= 1<<0,	/* Queue R2 Parity Error */
+};
+
+/*	B2_TST_CTRL1	 8 bit	Test Control Register 1 */
+enum {
+	TST_FRC_DPERR_MR = 1<<7, /* force DATAPERR on MST RD */
+	TST_FRC_DPERR_MW = 1<<6, /* force DATAPERR on MST WR */
+	TST_FRC_DPERR_TR = 1<<5, /* force DATAPERR on TRG RD */
+	TST_FRC_DPERR_TW = 1<<4, /* force DATAPERR on TRG WR */
+	TST_FRC_APERR_M	 = 1<<3, /* force ADDRPERR on MST */
+	TST_FRC_APERR_T	 = 1<<2, /* force ADDRPERR on TRG */
+	TST_CFG_WRITE_ON = 1<<1, /* Enable  Config Reg WR */
+	TST_CFG_WRITE_OFF= 1<<0, /* Disable Config Reg WR */
+};
+
+/*	B2_MAC_CFG		 8 bit	MAC Configuration / Chip Revision */
+enum {
+	CFG_CHIP_R_MSK	  = 0xf<<4,	/* Bit 7.. 4: Chip Revision */
+					/* Bit 3.. 2:	reserved */
+	CFG_DIS_M2_CLK	  = 1<<1,	/* Disable Clock for 2nd MAC */
+	CFG_SNG_MAC	  = 1<<0,	/* MAC Config: 0=2 MACs / 1=1 MAC*/
+};
+
+/*	B2_CHIP_ID		 8 bit 	Chip Identification Number */
+enum {
+	CHIP_ID_GENESIS	   = 0x0a, /* Chip ID for GENESIS */
+	CHIP_ID_YUKON	   = 0xb0, /* Chip ID for YUKON */
+	CHIP_ID_YUKON_LITE = 0xb1, /* Chip ID for YUKON-Lite (Rev. A1-A3) */
+	CHIP_ID_YUKON_LP   = 0xb2, /* Chip ID for YUKON-LP */
+	CHIP_ID_YUKON_XL   = 0xb3, /* Chip ID for YUKON-2 XL */
+	CHIP_ID_YUKON_EC   = 0xb6, /* Chip ID for YUKON-2 EC */
+ 	CHIP_ID_YUKON_FE   = 0xb7, /* Chip ID for YUKON-2 FE */
+
+	CHIP_REV_YU_LITE_A1  = 3,	/* Chip Rev. for YUKON-Lite A1,A2 */
+	CHIP_REV_YU_LITE_A3  = 7,	/* Chip Rev. for YUKON-Lite A3 */
+};
+
+/*	B2_LD_TEST		 8 bit	EPROM loader test register */
+enum {
+	LD_T_ON		= 1<<3,	/* Loader Test mode on */
+	LD_T_OFF	= 1<<2,	/* Loader Test mode off */
+	LD_T_STEP	= 1<<1,	/* Decrement FPROM addr. Counter */
+	LD_START	= 1<<0,	/* Start loading FPROM */
+};
+
+/*	B2_TI_CTRL		 8 bit	Timer control */
+/*	B2_IRQM_CTRL	 8 bit	IRQ Moderation Timer Control */
+enum {
+	TIM_START	= 1<<2,	/* Start Timer */
+	TIM_STOP	= 1<<1,	/* Stop  Timer */
+	TIM_CLR_IRQ	= 1<<0,	/* Clear Timer IRQ (!IRQM) */
+};
+
+/*	B2_TI_TEST		 8 Bit	Timer Test */
+/*	B2_IRQM_TEST	 8 bit	IRQ Moderation Timer Test */
+/*	B28_DPT_TST		 8 bit	Descriptor Poll Timer Test Reg */
+enum {
+	TIM_T_ON	= 1<<2,	/* Test mode on */
+	TIM_T_OFF	= 1<<1,	/* Test mode off */
+	TIM_T_STEP	= 1<<0,	/* Test step */
+};
+
+/*	B28_DPT_INI	32 bit	Descriptor Poll Timer Init Val */
+/*	B28_DPT_VAL	32 bit	Descriptor Poll Timer Curr Val */
+/*	B28_DPT_CTRL	 8 bit	Descriptor Poll Timer Ctrl Reg */
+enum {
+	DPT_MSK	= 0x00ffffffL,	/* Bit 23.. 0:	Desc Poll Timer Bits */
+
+	DPT_START	= 1<<1,	/* Start Descriptor Poll Timer */
+	DPT_STOP	= 1<<0,	/* Stop  Descriptor Poll Timer */
+};
+
+/*	B2_GP_IO		32 bit	General Purpose I/O Register */
+enum {
+	GP_DIR_9 = 1<<25, /* IO_9 direct, 0=In/1=Out */
+	GP_DIR_8 = 1<<24, /* IO_8 direct, 0=In/1=Out */
+	GP_DIR_7 = 1<<23, /* IO_7 direct, 0=In/1=Out */
+	GP_DIR_6 = 1<<22, /* IO_6 direct, 0=In/1=Out */
+	GP_DIR_5 = 1<<21, /* IO_5 direct, 0=In/1=Out */
+	GP_DIR_4 = 1<<20, /* IO_4 direct, 0=In/1=Out */
+	GP_DIR_3 = 1<<19, /* IO_3 direct, 0=In/1=Out */
+	GP_DIR_2 = 1<<18, /* IO_2 direct, 0=In/1=Out */
+	GP_DIR_1 = 1<<17, /* IO_1 direct, 0=In/1=Out */
+	GP_DIR_0 = 1<<16, /* IO_0 direct, 0=In/1=Out */
+
+	GP_IO_9	= 1<<9,	/* IO_9 pin */
+	GP_IO_8	= 1<<8,	/* IO_8 pin */
+	GP_IO_7	= 1<<7,	/* IO_7 pin */
+	GP_IO_6	= 1<<6,	/* IO_6 pin */
+	GP_IO_5	= 1<<5,	/* IO_5 pin */
+	GP_IO_4	= 1<<4,	/* IO_4 pin */
+	GP_IO_3	= 1<<3,	/* IO_3 pin */
+	GP_IO_2	= 1<<2,	/* IO_2 pin */
+	GP_IO_1	= 1<<1,	/* IO_1 pin */
+	GP_IO_0	= 1<<0,	/* IO_0 pin */
+};
+
+/* Rx/Tx Path related Arbiter Test Registers */
+/*	B3_MA_TO_TEST	16 bit	MAC Arbiter Timeout Test Reg */
+/*	B3_MA_RC_TEST	16 bit	MAC Arbiter Recovery Test Reg */
+/*	B3_PA_TEST		16 bit	Packet Arbiter Test Register */
+/*			Bit 15, 11, 7, and 3 are reserved in B3_PA_TEST */
+enum {
+	TX2_T_EV	= 1<<15,/* TX2 Timeout/Recv Event occured */
+	TX2_T_ON	= 1<<14,/* TX2 Timeout/Recv Timer Test On */
+	TX2_T_OFF	= 1<<13,/* TX2 Timeout/Recv Timer Tst Off */
+	TX2_T_STEP	= 1<<12,/* TX2 Timeout/Recv Timer Step */
+	TX1_T_EV	= 1<<11,/* TX1 Timeout/Recv Event occured */
+	TX1_T_ON	= 1<<10,/* TX1 Timeout/Recv Timer Test On */
+	TX1_T_OFF	= 1<<9,	/* TX1 Timeout/Recv Timer Tst Off */
+	TX1_T_STEP	= 1<<8,	/* TX1 Timeout/Recv Timer Step */
+	RX2_T_EV	= 1<<7,	/* RX2 Timeout/Recv Event occured */
+	RX2_T_ON	= 1<<6,	/* RX2 Timeout/Recv Timer Test On */
+	RX2_T_OFF	= 1<<5,	/* RX2 Timeout/Recv Timer Tst Off */
+	RX2_T_STEP	= 1<<4,	/* RX2 Timeout/Recv Timer Step */
+	RX1_T_EV	= 1<<3,	/* RX1 Timeout/Recv Event occured */
+	RX1_T_ON	= 1<<2,	/* RX1 Timeout/Recv Timer Test On */
+	RX1_T_OFF	= 1<<1,	/* RX1 Timeout/Recv Timer Tst Off */
+	RX1_T_STEP	= 1<<0,	/* RX1 Timeout/Recv Timer Step */
+};
+
+/* Descriptor Bit Definition */
+/*	TxCtrl		Transmit Buffer Control Field */
+/*	RxCtrl		Receive  Buffer Control Field */
+enum {
+	BMU_OWN		= 1<<31, /* OWN bit: 0=host/1=BMU */
+	BMU_STF		= 1<<30, /* Start of Frame */
+	BMU_EOF		= 1<<29, /* End of Frame */
+	BMU_IRQ_EOB	= 1<<28, /* Req "End of Buffer" IRQ */
+	BMU_IRQ_EOF	= 1<<27, /* Req "End of Frame" IRQ */
+				/* TxCtrl specific bits */
+	BMU_STFWD	= 1<<26, /* (Tx)	Store & Forward Frame */
+	BMU_NO_FCS	= 1<<25, /* (Tx) Disable MAC FCS (CRC) generation */
+	BMU_SW	= 1<<24, /* (Tx)	1 bit res. for SW use */
+				/* RxCtrl specific bits */
+	BMU_DEV_0	= 1<<26, /* (Rx)	Transfer data to Dev0 */
+	BMU_STAT_VAL	= 1<<25, /* (Rx)	Rx Status Valid */
+	BMU_TIST_VAL	= 1<<24, /* (Rx)	Rx TimeStamp Valid */
+			/* Bit 23..16:	BMU Check Opcodes */
+	BMU_CHECK	= 0x55<<16, /* Default BMU check */
+	BMU_TCP_CHECK	= 0x56<<16, /* Descr with TCP ext */
+	BMU_UDP_CHECK	= 0x57<<16, /* Descr with UDP ext (YUKON only) */
+	BMU_BBC		= 0xffffL, /* Bit 15.. 0:	Buffer Byte Counter */
+};
+
+/*	B2_BSC_CTRL		 8 bit	Blink Source Counter Control */
+enum {
+	 BSC_START	= 1<<1,	/* Start Blink Source Counter */
+	 BSC_STOP	= 1<<0,	/* Stop  Blink Source Counter */
+};
+
+/*	B2_BSC_STAT		 8 bit	Blink Source Counter Status */
+enum {
+	BSC_SRC		= 1<<0,	/* Blink Source, 0=Off / 1=On */
+};
+
+/*	B2_BSC_TST		16 bit	Blink Source Counter Test Reg */
+enum {
+	BSC_T_ON	= 1<<2,	/* Test mode on */
+	BSC_T_OFF	= 1<<1,	/* Test mode off */
+	BSC_T_STEP	= 1<<0,	/* Test step */
+};
+
+/*	B3_RAM_ADDR		32 bit	RAM Address, to read or write */
+					/* Bit 31..19:	reserved */
+#define RAM_ADR_RAN	0x0007ffffL	/* Bit 18.. 0:	RAM Address Range */
+/* RAM Interface Registers */
+
+/*	B3_RI_CTRL		16 bit	RAM Iface Control Register */
+enum {
+	RI_CLR_RD_PERR	= 1<<9,	/* Clear IRQ RAM Read Parity Err */
+	RI_CLR_WR_PERR	= 1<<8,	/* Clear IRQ RAM Write Parity Err*/
+
+	RI_RST_CLR	= 1<<1,	/* Clear RAM Interface Reset */
+	RI_RST_SET	= 1<<0,	/* Set   RAM Interface Reset */
+};
+
+/*	B3_RI_TEST		 8 bit	RAM Iface Test Register */
+enum {
+	RI_T_EV	= 1<<3,	/* Timeout Event occured */
+	RI_T_ON	= 1<<2,	/* Timeout Timer Test On */
+	RI_T_OFF	= 1<<1,	/* Timeout Timer Test Off */
+	RI_T_STEP	= 1<<0,	/* Timeout Timer Step */
+};
+
+/* MAC Arbiter Registers */
+/*	B3_MA_TO_CTRL	16 bit	MAC Arbiter Timeout Ctrl Reg */
+enum {
+	MA_FOE_ON	= 1<<3,	/* XMAC Fast Output Enable ON */
+	MA_FOE_OFF	= 1<<2,	/* XMAC Fast Output Enable OFF */
+	MA_RST_CLR	= 1<<1,	/* Clear MAC Arbiter Reset */
+	MA_RST_SET	= 1<<0,	/* Set   MAC Arbiter Reset */
+
+};
+
+/* Timeout values */
+#define SK_MAC_TO_53	72		/* MAC arbiter timeout */
+#define SK_PKT_TO_53	0x2000		/* Packet arbiter timeout */
+#define SK_PKT_TO_MAX	0xffff		/* Maximum value */
+#define SK_RI_TO_53	36		/* RAM interface timeout */
+
+
+/*	B3_MA_RC_CTRL	16 bit	MAC Arbiter Recovery Ctrl Reg */
+enum {
+	MA_ENA_REC_TX2	= 1<<7,	/* Enable  Recovery Timer TX2 */
+	MA_DIS_REC_TX2	= 1<<6,	/* Disable Recovery Timer TX2 */
+	MA_ENA_REC_TX1	= 1<<5,	/* Enable  Recovery Timer TX1 */
+	MA_DIS_REC_TX1	= 1<<4,	/* Disable Recovery Timer TX1 */
+	MA_ENA_REC_RX2	= 1<<3,	/* Enable  Recovery Timer RX2 */
+	MA_DIS_REC_RX2	= 1<<2,	/* Disable Recovery Timer RX2 */
+	MA_ENA_REC_RX1	= 1<<1,	/* Enable  Recovery Timer RX1 */
+	MA_DIS_REC_RX1	= 1<<0,	/* Disable Recovery Timer RX1 */
+};
+
+/* Packet Arbiter Registers */
+/*	B3_PA_CTRL		16 bit	Packet Arbiter Ctrl Register */
+enum {
+	PA_CLR_TO_TX2	= 1<<13,	/* Clear IRQ Packet Timeout TX2 */
+	PA_CLR_TO_TX1	= 1<<12,	/* Clear IRQ Packet Timeout TX1 */
+	PA_CLR_TO_RX2	= 1<<11,	/* Clear IRQ Packet Timeout RX2 */
+	PA_CLR_TO_RX1	= 1<<10,	/* Clear IRQ Packet Timeout RX1 */
+	PA_ENA_TO_TX2	= 1<<9,	/* Enable  Timeout Timer TX2 */
+	PA_DIS_TO_TX2	= 1<<8,	/* Disable Timeout Timer TX2 */
+	PA_ENA_TO_TX1	= 1<<7,	/* Enable  Timeout Timer TX1 */
+	PA_DIS_TO_TX1	= 1<<6,	/* Disable Timeout Timer TX1 */
+	PA_ENA_TO_RX2	= 1<<5,	/* Enable  Timeout Timer RX2 */
+	PA_DIS_TO_RX2	= 1<<4,	/* Disable Timeout Timer RX2 */
+	PA_ENA_TO_RX1	= 1<<3,	/* Enable  Timeout Timer RX1 */
+	PA_DIS_TO_RX1	= 1<<2,	/* Disable Timeout Timer RX1 */
+	PA_RST_CLR	= 1<<1,	/* Clear MAC Arbiter Reset */
+	PA_RST_SET	= 1<<0,	/* Set   MAC Arbiter Reset */
+};
+
+#define PA_ENA_TO_ALL	(PA_ENA_TO_RX1 | PA_ENA_TO_RX2 |\
+						PA_ENA_TO_TX1 | PA_ENA_TO_TX2)
+
+
+/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */
+/*	TXA_ITI_INI		32 bit	Tx Arb Interval Timer Init Val */
+/*	TXA_ITI_VAL		32 bit	Tx Arb Interval Timer Value */
+/*	TXA_LIM_INI		32 bit	Tx Arb Limit Counter Init Val */
+/*	TXA_LIM_VAL		32 bit	Tx Arb Limit Counter Value */
+
+#define TXA_MAX_VAL	0x00ffffffUL	/* Bit 23.. 0:	Max TXA Timer/Cnt Val */
+
+/*	TXA_CTRL		 8 bit	Tx Arbiter Control Register */
+enum {
+	TXA_ENA_FSYNC	= 1<<7,	/* Enable  force of sync Tx queue */
+	TXA_DIS_FSYNC	= 1<<6,	/* Disable force of sync Tx queue */
+	TXA_ENA_ALLOC	= 1<<5,	/* Enable  alloc of free bandwidth */
+	TXA_DIS_ALLOC	= 1<<4,	/* Disable alloc of free bandwidth */
+	TXA_START_RC	= 1<<3,	/* Start sync Rate Control */
+	TXA_STOP_RC	= 1<<2,	/* Stop  sync Rate Control */
+	TXA_ENA_ARB	= 1<<1,	/* Enable  Tx Arbiter */
+	TXA_DIS_ARB	= 1<<0,	/* Disable Tx Arbiter */
+};
+
+/*
+ *	Bank 4 - 5
+ */
+/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */
+enum {
+	TXA_ITI_INI	= 0x0200,/* 32 bit	Tx Arb Interval Timer Init Val*/
+	TXA_ITI_VAL	= 0x0204,/* 32 bit	Tx Arb Interval Timer Value */
+	TXA_LIM_INI	= 0x0208,/* 32 bit	Tx Arb Limit Counter Init Val */
+	TXA_LIM_VAL	= 0x020c,/* 32 bit	Tx Arb Limit Counter Value */
+	TXA_CTRL	= 0x0210,/*  8 bit	Tx Arbiter Control Register */
+	TXA_TEST	= 0x0211,/*  8 bit	Tx Arbiter Test Register */
+	TXA_STAT	= 0x0212,/*  8 bit	Tx Arbiter Status Register */
+};
+
+
+enum {
+	B6_EXT_REG	= 0x0300,/* External registers (GENESIS only) */
+	B7_CFG_SPC	= 0x0380,/* copy of the Configuration register */
+	B8_RQ1_REGS	= 0x0400,/* Receive Queue 1 */
+	B8_RQ2_REGS	= 0x0480,/* Receive Queue 2 */
+	B8_TS1_REGS	= 0x0600,/* Transmit sync queue 1 */
+	B8_TA1_REGS	= 0x0680,/* Transmit async queue 1 */
+	B8_TS2_REGS	= 0x0700,/* Transmit sync queue 2 */
+	B8_TA2_REGS	= 0x0780,/* Transmit sync queue 2 */
+	B16_RAM_REGS	= 0x0800,/* RAM Buffer Registers */
+};
+
+/* Queue Register Offsets, use Q_ADDR() to access */
+enum {
+	B8_Q_REGS = 0x0400, /* base of Queue registers */	
+	Q_D	= 0x00,	/* 8*32	bit	Current Descriptor */
+	Q_DA_L	= 0x20,	/* 32 bit	Current Descriptor Address Low dWord */
+	Q_DA_H	= 0x24,	/* 32 bit	Current Descriptor Address High dWord */
+	Q_AC_L	= 0x28,	/* 32 bit	Current Address Counter Low dWord */
+	Q_AC_H	= 0x2c,	/* 32 bit	Current Address Counter High dWord */
+	Q_BC	= 0x30,	/* 32 bit	Current Byte Counter */
+	Q_CSR	= 0x34,	/* 32 bit	BMU Control/Status Register */
+	Q_F	= 0x38,	/* 32 bit	Flag Register */
+	Q_T1	= 0x3c,	/* 32 bit	Test Register 1 */
+	Q_T1_TR	= 0x3c,	/*  8 bit	Test Register 1 Transfer SM */
+	Q_T1_WR	= 0x3d,	/*  8 bit	Test Register 1 Write Descriptor SM */
+	Q_T1_RD	= 0x3e,	/*  8 bit	Test Register 1 Read Descriptor SM */
+	Q_T1_SV	= 0x3f,	/*  8 bit	Test Register 1 Supervisor SM */
+	Q_T2	= 0x40,	/* 32 bit	Test Register 2	*/
+	Q_T3	= 0x44,	/* 32 bit	Test Register 3	*/
+
+/* Yukon-2 */
+	Q_DONE	= 0x24,	/* 16 bit	Done Index 		(Yukon-2 only) */
+	Q_WM	= 0x40,	/* 16 bit	FIFO Watermark */
+	Q_AL	= 0x42,	/*  8 bit	FIFO Alignment */
+	Q_RSP	= 0x44,	/* 16 bit	FIFO Read Shadow Pointer */
+	Q_RSL	= 0x46,	/*  8 bit	FIFO Read Shadow Level */
+	Q_RP	= 0x48,	/*  8 bit	FIFO Read Pointer */
+	Q_RL	= 0x4a,	/*  8 bit	FIFO Read Level */
+	Q_WP	= 0x4c,	/*  8 bit	FIFO Write Pointer */
+	Q_WSP	= 0x4d,	/*  8 bit	FIFO Write Shadow Pointer */
+	Q_WL	= 0x4e,	/*  8 bit	FIFO Write Level */
+	Q_WSL	= 0x4f,	/*  8 bit	FIFO Write Shadow Level */
+};
+#define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs))
+
+/* RAM Buffer Register Offsets */
+enum {
+
+	RB_START	= 0x00,/* 32 bit	RAM Buffer Start Address */
+	RB_END	= 0x04,/* 32 bit	RAM Buffer End Address */
+	RB_WP	= 0x08,/* 32 bit	RAM Buffer Write Pointer */
+	RB_RP	= 0x0c,/* 32 bit	RAM Buffer Read Pointer */
+	RB_RX_UTPP	= 0x10,/* 32 bit	Rx Upper Threshold, Pause Packet */
+	RB_RX_LTPP	= 0x14,/* 32 bit	Rx Lower Threshold, Pause Packet */
+	RB_RX_UTHP	= 0x18,/* 32 bit	Rx Upper Threshold, High Prio */
+	RB_RX_LTHP	= 0x1c,/* 32 bit	Rx Lower Threshold, High Prio */
+	/* 0x10 - 0x1f:	reserved at Tx RAM Buffer Registers */
+	RB_PC	= 0x20,/* 32 bit	RAM Buffer Packet Counter */
+	RB_LEV	= 0x24,/* 32 bit	RAM Buffer Level Register */
+	RB_CTRL	= 0x28,/* 32 bit	RAM Buffer Control Register */
+	RB_TST1	= 0x29,/*  8 bit	RAM Buffer Test Register 1 */
+	RB_TST2	= 0x2a,/*  8 bit	RAM Buffer Test Register 2 */
+};
+
+/* Receive and Transmit Queues */
+enum {
+	Q_R1	= 0x0000,	/* Receive Queue 1 */
+	Q_R2	= 0x0080,	/* Receive Queue 2 */
+	Q_XS1	= 0x0200,	/* Synchronous Transmit Queue 1 */
+	Q_XA1	= 0x0280,	/* Asynchronous Transmit Queue 1 */
+	Q_XS2	= 0x0300,	/* Synchronous Transmit Queue 2 */
+	Q_XA2	= 0x0380,	/* Asynchronous Transmit Queue 2 */
+};
+
+/* Different MAC Types */
+enum {
+	SK_MAC_XMAC =	0,	/* Xaqti XMAC II */
+	SK_MAC_GMAC =	1,	/* Marvell GMAC */
+};
+
+/* Different PHY Types */
+enum {
+	SK_PHY_XMAC	= 0,/* integrated in XMAC II */
+	SK_PHY_BCOM	= 1,/* Broadcom BCM5400 */
+	SK_PHY_LONE	= 2,/* Level One LXT1000  [not supported]*/
+	SK_PHY_NAT	= 3,/* National DP83891  [not supported] */
+	SK_PHY_MARV_COPPER= 4,/* Marvell 88E1011S */
+	SK_PHY_MARV_FIBER = 5,/* Marvell 88E1011S working on fiber */
+};
+
+/* PHY addresses (bits 12..8 of PHY address reg) */
+enum {
+	PHY_ADDR_XMAC	= 0<<8,
+	PHY_ADDR_BCOM	= 1<<8,
+	PHY_ADDR_LONE	= 3<<8,
+	PHY_ADDR_NAT	= 0<<8,
+/* GPHY address (bits 15..11 of SMI control reg) */
+	PHY_ADDR_MARV	= 0,
+};
+
+#define RB_ADDR(offs, queue) (B16_RAM_REGS + (queue) + (offs))
+
+/* Receive MAC FIFO, Receive LED, and Link_Sync regs (GENESIS only) */
+enum {
+	RX_MFF_EA	= 0x0c00,/* 32 bit	Receive MAC FIFO End Address */
+	RX_MFF_WP	= 0x0c04,/* 32 bit	Receive MAC FIFO Write Pointer */
+
+	RX_MFF_RP	= 0x0c0c,/* 32 bit	Receive MAC FIFO Read Pointer */
+	RX_MFF_PC	= 0x0c10,/* 32 bit	Receive MAC FIFO Packet Cnt */
+	RX_MFF_LEV	= 0x0c14,/* 32 bit	Receive MAC FIFO Level */
+	RX_MFF_CTRL1	= 0x0c18,/* 16 bit	Receive MAC FIFO Control Reg 1*/
+	RX_MFF_STAT_TO	= 0x0c1a,/*  8 bit	Receive MAC Status Timeout */
+	RX_MFF_TIST_TO	= 0x0c1b,/*  8 bit	Receive MAC Time Stamp Timeout */
+	RX_MFF_CTRL2	= 0x0c1c,/*  8 bit	Receive MAC FIFO Control Reg 2*/
+	RX_MFF_TST1	= 0x0c1d,/*  8 bit	Receive MAC FIFO Test Reg 1 */
+	RX_MFF_TST2	= 0x0c1e,/*  8 bit	Receive MAC FIFO Test Reg 2 */
+
+	RX_LED_INI	= 0x0c20,/* 32 bit	Receive LED Cnt Init Value */
+	RX_LED_VAL	= 0x0c24,/* 32 bit	Receive LED Cnt Current Value */
+	RX_LED_CTRL	= 0x0c28,/*  8 bit	Receive LED Cnt Control Reg */
+	RX_LED_TST	= 0x0c29,/*  8 bit	Receive LED Cnt Test Register */
+
+	LNK_SYNC_INI	= 0x0c30,/* 32 bit	Link Sync Cnt Init Value */
+	LNK_SYNC_VAL	= 0x0c34,/* 32 bit	Link Sync Cnt Current Value */
+	LNK_SYNC_CTRL	= 0x0c38,/*  8 bit	Link Sync Cnt Control Register */
+	LNK_SYNC_TST	= 0x0c39,/*  8 bit	Link Sync Cnt Test Register */
+	LNK_LED_REG	= 0x0c3c,/*  8 bit	Link LED Register */
+};
+
+/* Receive and Transmit MAC FIFO Registers (GENESIS only) */
+/*	RX_MFF_CTRL1	16 bit	Receive MAC FIFO Control Reg 1 */
+enum {
+	MFF_ENA_RDY_PAT	= 1<<13,	/* Enable  Ready Patch */
+	MFF_DIS_RDY_PAT	= 1<<12,	/* Disable Ready Patch */
+	MFF_ENA_TIM_PAT	= 1<<11,	/* Enable  Timing Patch */
+	MFF_DIS_TIM_PAT	= 1<<10,	/* Disable Timing Patch */
+	MFF_ENA_ALM_FUL	= 1<<9,	/* Enable  AlmostFull Sign */
+	MFF_DIS_ALM_FUL	= 1<<8,	/* Disable AlmostFull Sign */
+	MFF_ENA_PAUSE	= 1<<7,	/* Enable  Pause Signaling */
+	MFF_DIS_PAUSE	= 1<<6,	/* Disable Pause Signaling */
+	MFF_ENA_FLUSH	= 1<<5,	/* Enable  Frame Flushing */
+	MFF_DIS_FLUSH	= 1<<4,	/* Disable Frame Flushing */
+	MFF_ENA_TIST	= 1<<3,	/* Enable  Time Stamp Gener */
+	MFF_DIS_TIST	= 1<<2,	/* Disable Time Stamp Gener */
+	MFF_CLR_INTIST	= 1<<1,	/* Clear IRQ No Time Stamp */
+	MFF_CLR_INSTAT	= 1<<0,	/* Clear IRQ No Status */
+#define MFF_RX_CTRL_DEF MFF_ENA_TIM_PAT
+};
+
+/*	TX_MFF_CTRL1	16 bit	Transmit MAC FIFO Control Reg 1 */
+enum {
+	MFF_CLR_PERR	= 1<<15,	/* Clear Parity Error IRQ */
+								/* Bit 14:	reserved */
+	MFF_ENA_PKT_REC	= 1<<13,	/* Enable  Packet Recovery */
+	MFF_DIS_PKT_REC	= 1<<12,	/* Disable Packet Recovery */
+
+	MFF_ENA_W4E	= 1<<7,	/* Enable  Wait for Empty */
+	MFF_DIS_W4E	= 1<<6,	/* Disable Wait for Empty */
+
+	MFF_ENA_LOOPB	= 1<<3,	/* Enable  Loopback */
+	MFF_DIS_LOOPB	= 1<<2,	/* Disable Loopback */
+	MFF_CLR_MAC_RST	= 1<<1,	/* Clear XMAC Reset */
+	MFF_SET_MAC_RST	= 1<<0,	/* Set   XMAC Reset */
+};
+
+#define MFF_TX_CTRL_DEF	(MFF_ENA_PKT_REC | MFF_ENA_TIM_PAT | MFF_ENA_FLUSH)
+
+/*	RX_MFF_TST2	 	 8 bit	Receive MAC FIFO Test Register 2 */
+/*	TX_MFF_TST2	 	 8 bit	Transmit MAC FIFO Test Register 2 */
+enum {
+	MFF_WSP_T_ON	= 1<<6,	/* Tx: Write Shadow Ptr TestOn */
+	MFF_WSP_T_OFF	= 1<<5,	/* Tx: Write Shadow Ptr TstOff */
+	MFF_WSP_INC	= 1<<4,	/* Tx: Write Shadow Ptr Increment */
+	MFF_PC_DEC	= 1<<3,	/* Packet Counter Decrement */
+	MFF_PC_T_ON	= 1<<2,	/* Packet Counter Test On */
+	MFF_PC_T_OFF	= 1<<1,	/* Packet Counter Test Off */
+	MFF_PC_INC	= 1<<0,	/* Packet Counter Increment */
+};
+
+/*	RX_MFF_TST1	 	 8 bit	Receive MAC FIFO Test Register 1 */
+/*	TX_MFF_TST1	 	 8 bit	Transmit MAC FIFO Test Register 1 */
+enum {
+	MFF_WP_T_ON	= 1<<6,	/* Write Pointer Test On */
+	MFF_WP_T_OFF	= 1<<5,	/* Write Pointer Test Off */
+	MFF_WP_INC	= 1<<4,	/* Write Pointer Increm */
+
+	MFF_RP_T_ON	= 1<<2,	/* Read Pointer Test On */
+	MFF_RP_T_OFF	= 1<<1,	/* Read Pointer Test Off */
+	MFF_RP_DEC	= 1<<0,	/* Read Pointer Decrement */
+};
+
+/*	RX_MFF_CTRL2	 8 bit	Receive MAC FIFO Control Reg 2 */
+/*	TX_MFF_CTRL2	 8 bit	Transmit MAC FIFO Control Reg 2 */
+enum {
+	MFF_ENA_OP_MD	= 1<<3,	/* Enable  Operation Mode */
+	MFF_DIS_OP_MD	= 1<<2,	/* Disable Operation Mode */
+	MFF_RST_CLR	= 1<<1,	/* Clear MAC FIFO Reset */
+	MFF_RST_SET	= 1<<0,	/* Set   MAC FIFO Reset */
+};
+
+
+/*	Link LED Counter Registers (GENESIS only) */
+
+/*	RX_LED_CTRL		 8 bit	Receive LED Cnt Control Reg */
+/*	TX_LED_CTRL		 8 bit	Transmit LED Cnt Control Reg */
+/*	LNK_SYNC_CTRL	 8 bit	Link Sync Cnt Control Register */
+enum {
+	LED_START	= 1<<2,	/* Start Timer */
+	LED_STOP	= 1<<1,	/* Stop Timer */
+	LED_STATE	= 1<<0,	/* Rx/Tx: LED State, 1=LED on */
+};
+
+/*	RX_LED_TST		 8 bit	Receive LED Cnt Test Register */
+/*	TX_LED_TST		 8 bit	Transmit LED Cnt Test Register */
+/*	LNK_SYNC_TST	 8 bit	Link Sync Cnt Test Register */
+enum {
+	LED_T_ON	= 1<<2,	/* LED Counter Test mode On */
+	LED_T_OFF	= 1<<1,	/* LED Counter Test mode Off */
+	LED_T_STEP	= 1<<0,	/* LED Counter Step */
+};
+
+/*	LNK_LED_REG	 	 8 bit	Link LED Register */
+enum {
+	LED_BLK_ON	= 1<<5,	/* Link LED Blinking On */
+	LED_BLK_OFF	= 1<<4,	/* Link LED Blinking Off */
+	LED_SYNC_ON	= 1<<3,	/* Use Sync Wire to switch LED */
+	LED_SYNC_OFF	= 1<<2,	/* Disable Sync Wire Input */
+	LED_ON	= 1<<1,	/* switch LED on */
+	LED_OFF	= 1<<0,	/* switch LED off */
+};
+
+/* Receive GMAC FIFO (YUKON and Yukon-2) */
+enum {
+	RX_GMF_EA	= 0x0c40,/* 32 bit	Rx GMAC FIFO End Address */
+	RX_GMF_AF_THR	= 0x0c44,/* 32 bit	Rx GMAC FIFO Almost Full Thresh. */
+	RX_GMF_CTRL_T	= 0x0c48,/* 32 bit	Rx GMAC FIFO Control/Test */
+	RX_GMF_FL_MSK	= 0x0c4c,/* 32 bit	Rx GMAC FIFO Flush Mask */
+	RX_GMF_FL_THR	= 0x0c50,/* 32 bit	Rx GMAC FIFO Flush Threshold */
+	RX_GMF_TR_THR	= 0x0c54,/* 32 bit	Rx Truncation Threshold (Yukon-2) */
+
+	RX_GMF_VLAN	= 0x0c5c,/* 32 bit	Rx VLAN Type Register (Yukon-2) */
+	RX_GMF_WP	= 0x0c60,/* 32 bit	Rx GMAC FIFO Write Pointer */
+
+	RX_GMF_WLEV	= 0x0c68,/* 32 bit	Rx GMAC FIFO Write Level */
+
+	RX_GMF_RP	= 0x0c70,/* 32 bit	Rx GMAC FIFO Read Pointer */
+
+	RX_GMF_RLEV	= 0x0c78,/* 32 bit	Rx GMAC FIFO Read Level */
+};
+
+
+/*	TXA_TEST		 8 bit	Tx Arbiter Test Register */
+enum {
+	TXA_INT_T_ON	= 1<<5,	/* Tx Arb Interval Timer Test On */
+	TXA_INT_T_OFF	= 1<<4,	/* Tx Arb Interval Timer Test Off */
+	TXA_INT_T_STEP	= 1<<3,	/* Tx Arb Interval Timer Step */
+	TXA_LIM_T_ON	= 1<<2,	/* Tx Arb Limit Timer Test On */
+	TXA_LIM_T_OFF	= 1<<1,	/* Tx Arb Limit Timer Test Off */
+	TXA_LIM_T_STEP	= 1<<0,	/* Tx Arb Limit Timer Step */
+};
+
+/*	TXA_STAT		 8 bit	Tx Arbiter Status Register */
+enum {
+	TXA_PRIO_XS	= 1<<0,	/* sync queue has prio to send */
+};
+
+
+/*	Q_BC			32 bit	Current Byte Counter */
+
+/* BMU Control Status Registers */
+/*	B0_R1_CSR		32 bit	BMU Ctrl/Stat Rx Queue 1 */
+/*	B0_R2_CSR		32 bit	BMU Ctrl/Stat Rx Queue 2 */
+/*	B0_XA1_CSR		32 bit	BMU Ctrl/Stat Sync Tx Queue 1 */
+/*	B0_XS1_CSR		32 bit	BMU Ctrl/Stat Async Tx Queue 1 */
+/*	B0_XA2_CSR		32 bit	BMU Ctrl/Stat Sync Tx Queue 2 */
+/*	B0_XS2_CSR		32 bit	BMU Ctrl/Stat Async Tx Queue 2 */
+/*	Q_CSR			32 bit	BMU Control/Status Register */
+
+enum {
+	CSR_SV_IDLE	= 1<<24,	/* BMU SM Idle */
+
+	CSR_DESC_CLR	= 1<<21,	/* Clear Reset for Descr */
+	CSR_DESC_SET	= 1<<20,	/* Set   Reset for Descr */
+	CSR_FIFO_CLR	= 1<<19,	/* Clear Reset for FIFO */
+	CSR_FIFO_SET	= 1<<18,	/* Set   Reset for FIFO */
+	CSR_HPI_RUN	= 1<<17,	/* Release HPI SM */
+	CSR_HPI_RST	= 1<<16,	/* Reset   HPI SM to Idle */
+	CSR_SV_RUN	= 1<<15,	/* Release Supervisor SM */
+	CSR_SV_RST	= 1<<14,	/* Reset   Supervisor SM */
+	CSR_DREAD_RUN	= 1<<13,	/* Release Descr Read SM */
+	CSR_DREAD_RST	= 1<<12,	/* Reset   Descr Read SM */
+	CSR_DWRITE_RUN	= 1<<11,	/* Release Descr Write SM */
+	CSR_DWRITE_RST	= 1<<10,	/* Reset   Descr Write SM */
+	CSR_TRANS_RUN	= 1<<9,		/* Release Transfer SM */
+	CSR_TRANS_RST	= 1<<8,		/* Reset   Transfer SM */
+	CSR_ENA_POL	= 1<<7,		/* Enable  Descr Polling */
+	CSR_DIS_POL	= 1<<6,		/* Disable Descr Polling */
+	CSR_STOP	= 1<<5,		/* Stop  Rx/Tx Queue */
+	CSR_START	= 1<<4,		/* Start Rx/Tx Queue */
+	CSR_IRQ_CL_P	= 1<<3,		/* (Rx)	Clear Parity IRQ */
+	CSR_IRQ_CL_B	= 1<<2,		/* Clear EOB IRQ */
+	CSR_IRQ_CL_F	= 1<<1,		/* Clear EOF IRQ */
+	CSR_IRQ_CL_C	= 1<<0,		/* Clear ERR IRQ */
+};
+
+#define CSR_SET_RESET	(CSR_DESC_SET | CSR_FIFO_SET | CSR_HPI_RST |\
+			CSR_SV_RST | CSR_DREAD_RST | CSR_DWRITE_RST |\
+			CSR_TRANS_RST)
+#define CSR_CLR_RESET	(CSR_DESC_CLR | CSR_FIFO_CLR | CSR_HPI_RUN |\
+			CSR_SV_RUN | CSR_DREAD_RUN | CSR_DWRITE_RUN |\
+			CSR_TRANS_RUN)
+
+/*	Q_F				32 bit	Flag Register */
+enum {
+	F_ALM_FULL	= 1<<27,	/* Rx FIFO: almost full */
+	F_EMPTY		= 1<<27,	/* Tx FIFO: empty flag */
+	F_FIFO_EOF	= 1<<26,	/* Tag (EOF Flag) bit in FIFO */
+	F_WM_REACHED	= 1<<25,	/* Watermark reached */
+
+	F_FIFO_LEVEL	= 0x1fL<<16,	/* Bit 23..16:	# of Qwords in FIFO */
+	F_WATER_MARK	= 0x0007ffL,	/* Bit 10.. 0:	Watermark */
+};
+
+/* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */
+/*	RB_START		32 bit	RAM Buffer Start Address */
+/*	RB_END			32 bit	RAM Buffer End Address */
+/*	RB_WP			32 bit	RAM Buffer Write Pointer */
+/*	RB_RP			32 bit	RAM Buffer Read Pointer */
+/*	RB_RX_UTPP		32 bit	Rx Upper Threshold, Pause Pack */
+/*	RB_RX_LTPP		32 bit	Rx Lower Threshold, Pause Pack */
+/*	RB_RX_UTHP		32 bit	Rx Upper Threshold, High Prio */
+/*	RB_RX_LTHP		32 bit	Rx Lower Threshold, High Prio */
+/*	RB_PC			32 bit	RAM Buffer Packet Counter */
+/*	RB_LEV			32 bit	RAM Buffer Level Register */
+
+#define RB_MSK	0x0007ffff	/* Bit 18.. 0:	RAM Buffer Pointer Bits */
+/*	RB_TST2			 8 bit	RAM Buffer Test Register 2 */
+/*	RB_TST1			 8 bit	RAM Buffer Test Register 1 */
+
+/*	RB_CTRL			 8 bit	RAM Buffer Control Register */
+enum {
+	RB_ENA_STFWD	= 1<<5,	/* Enable  Store & Forward */
+	RB_DIS_STFWD	= 1<<4,	/* Disable Store & Forward */
+	RB_ENA_OP_MD	= 1<<3,	/* Enable  Operation Mode */
+	RB_DIS_OP_MD	= 1<<2,	/* Disable Operation Mode */
+	RB_RST_CLR	= 1<<1,	/* Clear RAM Buf STM Reset */
+	RB_RST_SET	= 1<<0,	/* Set   RAM Buf STM Reset */
+};
+
+/* Transmit MAC FIFO and Transmit LED Registers (GENESIS only), */
+enum {
+	TX_MFF_EA	= 0x0d00,/* 32 bit	Transmit MAC FIFO End Address */
+	TX_MFF_WP	= 0x0d04,/* 32 bit	Transmit MAC FIFO WR Pointer */
+	TX_MFF_WSP	= 0x0d08,/* 32 bit	Transmit MAC FIFO WR Shadow Ptr */
+	TX_MFF_RP	= 0x0d0c,/* 32 bit	Transmit MAC FIFO RD Pointer */
+	TX_MFF_PC	= 0x0d10,/* 32 bit	Transmit MAC FIFO Packet Cnt */
+	TX_MFF_LEV	= 0x0d14,/* 32 bit	Transmit MAC FIFO Level */
+	TX_MFF_CTRL1	= 0x0d18,/* 16 bit	Transmit MAC FIFO Ctrl Reg 1 */
+	TX_MFF_WAF	= 0x0d1a,/*  8 bit	Transmit MAC Wait after flush */
+
+	TX_MFF_CTRL2	= 0x0d1c,/*  8 bit	Transmit MAC FIFO Ctrl Reg 2 */
+	TX_MFF_TST1	= 0x0d1d,/*  8 bit	Transmit MAC FIFO Test Reg 1 */
+	TX_MFF_TST2	= 0x0d1e,/*  8 bit	Transmit MAC FIFO Test Reg 2 */
+
+	TX_LED_INI	= 0x0d20,/* 32 bit	Transmit LED Cnt Init Value */
+	TX_LED_VAL	= 0x0d24,/* 32 bit	Transmit LED Cnt Current Val */
+	TX_LED_CTRL	= 0x0d28,/*  8 bit	Transmit LED Cnt Control Reg */
+	TX_LED_TST	= 0x0d29,/*  8 bit	Transmit LED Cnt Test Reg */
+};
+
+/* Counter and Timer constants, for a host clock of 62.5 MHz */
+#define SK_XMIT_DUR		0x002faf08UL	/*  50 ms */
+#define SK_BLK_DUR		0x01dcd650UL	/* 500 ms */
+
+#define SK_DPOLL_DEF	0x00ee6b28UL	/* 250 ms at 62.5 MHz */
+
+#define SK_DPOLL_MAX	0x00ffffffUL	/* 268 ms at 62.5 MHz */
+					/* 215 ms at 78.12 MHz */
+
+#define SK_FACT_62		100	/* is given in percent */
+#define SK_FACT_53		 85     /* on GENESIS:	53.12 MHz */
+#define SK_FACT_78		125	/* on YUKON:	78.12 MHz */
+
+
+/* Transmit GMAC FIFO (YUKON only) */
+enum {
+	TX_GMF_EA	= 0x0d40,/* 32 bit	Tx GMAC FIFO End Address */
+	TX_GMF_AE_THR	= 0x0d44,/* 32 bit	Tx GMAC FIFO Almost Empty Thresh.*/
+	TX_GMF_CTRL_T	= 0x0d48,/* 32 bit	Tx GMAC FIFO Control/Test */
+
+	TX_GMF_WP	= 0x0d60,/* 32 bit 	Tx GMAC FIFO Write Pointer */
+	TX_GMF_WSP	= 0x0d64,/* 32 bit 	Tx GMAC FIFO Write Shadow Ptr. */
+	TX_GMF_WLEV	= 0x0d68,/* 32 bit 	Tx GMAC FIFO Write Level */
+
+	TX_GMF_RP	= 0x0d70,/* 32 bit 	Tx GMAC FIFO Read Pointer */
+	TX_GMF_RSTP	= 0x0d74,/* 32 bit 	Tx GMAC FIFO Restart Pointer */
+	TX_GMF_RLEV	= 0x0d78,/* 32 bit 	Tx GMAC FIFO Read Level */
+
+	/* Descriptor Poll Timer Registers */
+	B28_DPT_INI	= 0x0e00,/* 24 bit	Descriptor Poll Timer Init Val */
+	B28_DPT_VAL	= 0x0e04,/* 24 bit	Descriptor Poll Timer Curr Val */
+	B28_DPT_CTRL	= 0x0e08,/*  8 bit	Descriptor Poll Timer Ctrl Reg */
+
+	B28_DPT_TST	= 0x0e0a,/*  8 bit	Descriptor Poll Timer Test Reg */
+
+	/* Time Stamp Timer Registers (YUKON only) */
+	GMAC_TI_ST_VAL	= 0x0e14,/* 32 bit	Time Stamp Timer Curr Val */
+	GMAC_TI_ST_CTRL	= 0x0e18,/*  8 bit	Time Stamp Timer Ctrl Reg */
+	GMAC_TI_ST_TST	= 0x0e1a,/*  8 bit	Time Stamp Timer Test Reg */
+};
+
+/* Status BMU Registers (Yukon-2 only)*/
+enum {
+	STAT_CTRL	= 0x0e80,/* 32 bit	Status BMU Control Reg */
+	STAT_LAST_IDX	= 0x0e84,/* 16 bit	Status BMU Last Index */
+	/* 0x0e85 - 0x0e86:	reserved */
+	STAT_LIST_ADDR_LO	= 0x0e88,/* 32 bit	Status List Start Addr (low) */
+	STAT_LIST_ADDR_HI	= 0x0e8c,/* 32 bit	Status List Start Addr (high) */
+	STAT_TXA1_RIDX	= 0x0e90,/* 16 bit	Status TxA1 Report Index Reg */
+	STAT_TXS1_RIDX	= 0x0e92,/* 16 bit	Status TxS1 Report Index Reg */
+	STAT_TXA2_RIDX	= 0x0e94,/* 16 bit	Status TxA2 Report Index Reg */
+	STAT_TXS2_RIDX	= 0x0e96,/* 16 bit	Status TxS2 Report Index Reg */
+	STAT_TX_IDX_TH	= 0x0e98,/* 16 bit	Status Tx Index Threshold Reg */
+	STAT_PUT_IDX	= 0x0e9c,/* 16 bit	Status Put Index Reg */
+
+/* FIFO Control/Status Registers (Yukon-2 only)*/
+	STAT_FIFO_WP	= 0x0ea0,/*  8 bit	Status FIFO Write Pointer Reg */
+	STAT_FIFO_RP	= 0x0ea4,/*  8 bit	Status FIFO Read Pointer Reg */
+	STAT_FIFO_RSP	= 0x0ea6,/*  8 bit	Status FIFO Read Shadow Ptr */
+	STAT_FIFO_LEVEL	= 0x0ea8,/*  8 bit	Status FIFO Level Reg */
+	STAT_FIFO_SHLVL	= 0x0eaa,/*  8 bit	Status FIFO Shadow Level Reg */
+	STAT_FIFO_WM	= 0x0eac,/*  8 bit	Status FIFO Watermark Reg */
+	STAT_FIFO_ISR_WM	= 0x0ead,/*  8 bit	Status FIFO ISR Watermark Reg */
+
+/* Level and ISR Timer Registers (Yukon-2 only)*/
+	STAT_LEV_TIMER_INI	= 0x0eb0,/* 32 bit	Level Timer Init. Value Reg */
+	STAT_LEV_TIMER_CNT	= 0x0eb4,/* 32 bit	Level Timer Counter Reg */
+	STAT_LEV_TIMER_CTRL	= 0x0eb8,/*  8 bit	Level Timer Control Reg */
+	STAT_LEV_TIMER_TEST	= 0x0eb9,/*  8 bit	Level Timer Test Reg */
+	STAT_TX_TIMER_INI	= 0x0ec0,/* 32 bit	Tx Timer Init. Value Reg */
+	STAT_TX_TIMER_CNT	= 0x0ec4,/* 32 bit	Tx Timer Counter Reg */
+	STAT_TX_TIMER_CTRL	= 0x0ec8,/*  8 bit	Tx Timer Control Reg */
+	STAT_TX_TIMER_TEST	= 0x0ec9,/*  8 bit	Tx Timer Test Reg */
+	STAT_ISR_TIMER_INI	= 0x0ed0,/* 32 bit	ISR Timer Init. Value Reg */
+	STAT_ISR_TIMER_CNT	= 0x0ed4,/* 32 bit	ISR Timer Counter Reg */
+	STAT_ISR_TIMER_CTRL	= 0x0ed8,/*  8 bit	ISR Timer Control Reg */
+	STAT_ISR_TIMER_TEST	= 0x0ed9,/*  8 bit	ISR Timer Test Reg */
+
+	ST_LAST_IDX_MASK	= 0x007f,/* Last Index Mask */
+	ST_TXRP_IDX_MASK	= 0x0fff,/* Tx Report Index Mask */
+	ST_TXTH_IDX_MASK	= 0x0fff,/* Tx Threshold Index Mask */
+	ST_WM_IDX_MASK	= 0x3f,/* FIFO Watermark Index Mask */
+};
+
+enum {
+	LINKLED_OFF 	     = 0x01,
+	LINKLED_ON  	     = 0x02,
+	LINKLED_LINKSYNC_OFF = 0x04,
+	LINKLED_LINKSYNC_ON  = 0x08,
+	LINKLED_BLINK_OFF    = 0x10,
+	LINKLED_BLINK_ON     = 0x20,
+};
+	
+/* GMAC and GPHY Control Registers (YUKON only) */
+enum {
+	GMAC_CTRL	= 0x0f00,/* 32 bit	GMAC Control Reg */
+	GPHY_CTRL	= 0x0f04,/* 32 bit	GPHY Control Reg */
+	GMAC_IRQ_SRC	= 0x0f08,/*  8 bit	GMAC Interrupt Source Reg */
+	GMAC_IRQ_MSK	= 0x0f0c,/*  8 bit	GMAC Interrupt Mask Reg */
+	GMAC_LINK_CTRL	= 0x0f10,/* 16 bit	Link Control Reg */
+
+/* Wake-up Frame Pattern Match Control Registers (YUKON only) */
+
+	WOL_REG_OFFS	= 0x20,/* HW-Bug: Address is + 0x20 against spec. */
+
+	WOL_CTRL_STAT	= 0x0f20,/* 16 bit	WOL Control/Status Reg */
+	WOL_MATCH_CTL	= 0x0f22,/*  8 bit	WOL Match Control Reg */
+	WOL_MATCH_RES	= 0x0f23,/*  8 bit	WOL Match Result Reg */
+	WOL_MAC_ADDR	= 0x0f24,/* 32 bit	WOL MAC Address */
+	WOL_PATT_PME	= 0x0f2a,/*  8 bit	WOL PME Match Enable (Yukon-2) */
+	WOL_PATT_ASFM	= 0x0f2b,/*  8 bit	WOL ASF Match Enable (Yukon-2) */
+	WOL_PATT_RPTR	= 0x0f2c,/*  8 bit	WOL Pattern Read Pointer */
+
+/* WOL Pattern Length Registers (YUKON only) */
+
+	WOL_PATT_LEN_LO	= 0x0f30,/* 32 bit	WOL Pattern Length 3..0 */
+	WOL_PATT_LEN_HI	= 0x0f34,/* 24 bit	WOL Pattern Length 6..4 */
+
+/* WOL Pattern Counter Registers (YUKON only) */
+
+	WOL_PATT_CNT_0	= 0x0f38,/* 32 bit	WOL Pattern Counter 3..0 */
+	WOL_PATT_CNT_4	= 0x0f3c,/* 24 bit	WOL Pattern Counter 6..4 */
+};
+
+enum {
+	WOL_PATT_RAM_1	= 0x1000,/*  WOL Pattern RAM Link 1 */
+	WOL_PATT_RAM_2	= 0x1400,/*  WOL Pattern RAM Link 2 */
+};
+
+enum {
+	BASE_XMAC_1	= 0x2000,/* XMAC 1 registers */
+	BASE_GMAC_1	= 0x2800,/* GMAC 1 registers */
+	BASE_XMAC_2	= 0x3000,/* XMAC 2 registers */
+	BASE_GMAC_2	= 0x3800,/* GMAC 2 registers */
+};
+
+/*
+ * Receive Frame Status Encoding
+ */
+enum {
+	XMR_FS_LEN	= 0x3fff<<18,	/* Bit 31..18:	Rx Frame Length */
+	XMR_FS_2L_VLAN	= 1<<17, /* Bit 17:	tagged wh 2Lev VLAN ID*/
+	XMR_FS_1_VLAN	= 1<<16, /* Bit 16:	tagged wh 1ev VLAN ID*/
+	XMR_FS_BC	= 1<<15, /* Bit 15:	Broadcast Frame */
+	XMR_FS_MC	= 1<<14, /* Bit 14:	Multicast Frame */
+	XMR_FS_UC	= 1<<13, /* Bit 13:	Unicast Frame */
+
+	XMR_FS_BURST	= 1<<11, /* Bit 11:	Burst Mode */
+	XMR_FS_CEX_ERR	= 1<<10, /* Bit 10:	Carrier Ext. Error */
+	XMR_FS_802_3	= 1<<9, /* Bit  9:	802.3 Frame */
+	XMR_FS_COL_ERR	= 1<<8, /* Bit  8:	Collision Error */
+	XMR_FS_CAR_ERR	= 1<<7, /* Bit  7:	Carrier Event Error */
+	XMR_FS_LEN_ERR	= 1<<6, /* Bit  6:	In-Range Length Error */
+	XMR_FS_FRA_ERR	= 1<<5, /* Bit  5:	Framing Error */
+	XMR_FS_RUNT	= 1<<4, /* Bit  4:	Runt Frame */
+	XMR_FS_LNG_ERR	= 1<<3, /* Bit  3:	Giant (Jumbo) Frame */
+	XMR_FS_FCS_ERR	= 1<<2, /* Bit  2:	Frame Check Sequ Err */
+	XMR_FS_ERR	= 1<<1, /* Bit  1:	Frame Error */
+	XMR_FS_MCTRL	= 1<<0, /* Bit  0:	MAC Control Packet */
+
+/*
+ * XMR_FS_ERR will be set if
+ *	XMR_FS_FCS_ERR, XMR_FS_LNG_ERR, XMR_FS_RUNT,
+ *	XMR_FS_FRA_ERR, XMR_FS_LEN_ERR, or XMR_FS_CEX_ERR
+ * is set. XMR_FS_LNG_ERR and XMR_FS_LEN_ERR will issue
+ * XMR_FS_ERR unless the corresponding bit in the Receive Command
+ * Register is set.
+ */
+};
+
+/*
+,* XMAC-PHY Registers, indirect addressed over the XMAC
+ */
+enum {
+	PHY_XMAC_CTRL		= 0x00,/* 16 bit r/w	PHY Control Register */
+	PHY_XMAC_STAT		= 0x01,/* 16 bit r/w	PHY Status Register */
+	PHY_XMAC_ID0		= 0x02,/* 16 bit r/o	PHY ID0 Register */
+	PHY_XMAC_ID1		= 0x03,/* 16 bit r/o	PHY ID1 Register */
+	PHY_XMAC_AUNE_ADV	= 0x04,/* 16 bit r/w	Auto-Neg. Advertisement */
+	PHY_XMAC_AUNE_LP	= 0x05,/* 16 bit r/o	Link Partner Abi Reg */
+	PHY_XMAC_AUNE_EXP	= 0x06,/* 16 bit r/o	Auto-Neg. Expansion Reg */
+	PHY_XMAC_NEPG	= 0x07,/* 16 bit r/w	Next Page Register */
+	PHY_XMAC_NEPG_LP	= 0x08,/* 16 bit r/o	Next Page Link Partner */
+
+	PHY_XMAC_EXT_STAT	= 0x0f,/* 16 bit r/o	Ext Status Register */
+	PHY_XMAC_RES_ABI	= 0x10,/* 16 bit r/o	PHY Resolved Ability */
+};
+/*
+ * Broadcom-PHY Registers, indirect addressed over XMAC
+ */
+enum {
+	PHY_BCOM_CTRL		= 0x00,/* 16 bit r/w	PHY Control Register */
+	PHY_BCOM_STAT		= 0x01,/* 16 bit r/o	PHY Status Register */
+	PHY_BCOM_ID0		= 0x02,/* 16 bit r/o	PHY ID0 Register */
+	PHY_BCOM_ID1		= 0x03,/* 16 bit r/o	PHY ID1 Register */
+	PHY_BCOM_AUNE_ADV	= 0x04,/* 16 bit r/w	Auto-Neg. Advertisement */
+	PHY_BCOM_AUNE_LP	= 0x05,/* 16 bit r/o	Link Part Ability Reg */
+	PHY_BCOM_AUNE_EXP	= 0x06,/* 16 bit r/o	Auto-Neg. Expansion Reg */
+	PHY_BCOM_NEPG		= 0x07,/* 16 bit r/w	Next Page Register */
+	PHY_BCOM_NEPG_LP	= 0x08,/* 16 bit r/o	Next Page Link Partner */
+	/* Broadcom-specific registers */
+	PHY_BCOM_1000T_CTRL	= 0x09,/* 16 bit r/w	1000Base-T Control Reg */
+	PHY_BCOM_1000T_STAT	= 0x0a,/* 16 bit r/o	1000Base-T Status Reg */
+	PHY_BCOM_EXT_STAT	= 0x0f,/* 16 bit r/o	Extended Status Reg */
+	PHY_BCOM_P_EXT_CTRL	= 0x10,/* 16 bit r/w	PHY Extended Ctrl Reg */
+	PHY_BCOM_P_EXT_STAT	= 0x11,/* 16 bit r/o	PHY Extended Stat Reg */
+	PHY_BCOM_RE_CTR		= 0x12,/* 16 bit r/w	Receive Error Counter */
+	PHY_BCOM_FC_CTR		= 0x13,/* 16 bit r/w	False Carrier Sense Cnt */
+	PHY_BCOM_RNO_CTR	= 0x14,/* 16 bit r/w	Receiver NOT_OK Cnt */
+
+	PHY_BCOM_AUX_CTRL	= 0x18,/* 16 bit r/w	Auxiliary Control Reg */
+	PHY_BCOM_AUX_STAT	= 0x19,/* 16 bit r/o	Auxiliary Stat Summary */
+	PHY_BCOM_INT_STAT	= 0x1a,/* 16 bit r/o	Interrupt Status Reg */
+	PHY_BCOM_INT_MASK	= 0x1b,/* 16 bit r/w	Interrupt Mask Reg */
+};
+
+/*
+ * Marvel-PHY Registers, indirect addressed over GMAC
+ */
+enum {
+	PHY_MARV_CTRL		= 0x00,/* 16 bit r/w	PHY Control Register */
+	PHY_MARV_STAT		= 0x01,/* 16 bit r/o	PHY Status Register */
+	PHY_MARV_ID0		= 0x02,/* 16 bit r/o	PHY ID0 Register */
+	PHY_MARV_ID1		= 0x03,/* 16 bit r/o	PHY ID1 Register */
+	PHY_MARV_AUNE_ADV	= 0x04,/* 16 bit r/w	Auto-Neg. Advertisement */
+	PHY_MARV_AUNE_LP	= 0x05,/* 16 bit r/o	Link Part Ability Reg */
+	PHY_MARV_AUNE_EXP	= 0x06,/* 16 bit r/o	Auto-Neg. Expansion Reg */
+	PHY_MARV_NEPG		= 0x07,/* 16 bit r/w	Next Page Register */
+	PHY_MARV_NEPG_LP	= 0x08,/* 16 bit r/o	Next Page Link Partner */
+	/* Marvel-specific registers */
+	PHY_MARV_1000T_CTRL	= 0x09,/* 16 bit r/w	1000Base-T Control Reg */
+	PHY_MARV_1000T_STAT	= 0x0a,/* 16 bit r/o	1000Base-T Status Reg */
+	PHY_MARV_EXT_STAT	= 0x0f,/* 16 bit r/o	Extended Status Reg */
+	PHY_MARV_PHY_CTRL	= 0x10,/* 16 bit r/w	PHY Specific Ctrl Reg */
+	PHY_MARV_PHY_STAT	= 0x11,/* 16 bit r/o	PHY Specific Stat Reg */
+	PHY_MARV_INT_MASK	= 0x12,/* 16 bit r/w	Interrupt Mask Reg */
+	PHY_MARV_INT_STAT	= 0x13,/* 16 bit r/o	Interrupt Status Reg */
+	PHY_MARV_EXT_CTRL	= 0x14,/* 16 bit r/w	Ext. PHY Specific Ctrl */
+	PHY_MARV_RXE_CNT	= 0x15,/* 16 bit r/w	Receive Error Counter */
+	PHY_MARV_EXT_ADR	= 0x16,/* 16 bit r/w	Ext. Ad. for Cable Diag. */
+	PHY_MARV_PORT_IRQ	= 0x17,/* 16 bit r/o	Port 0 IRQ (88E1111 only) */
+	PHY_MARV_LED_CTRL	= 0x18,/* 16 bit r/w	LED Control Reg */
+	PHY_MARV_LED_OVER	= 0x19,/* 16 bit r/w	Manual LED Override Reg */
+	PHY_MARV_EXT_CTRL_2	= 0x1a,/* 16 bit r/w	Ext. PHY Specific Ctrl 2 */
+	PHY_MARV_EXT_P_STAT	= 0x1b,/* 16 bit r/w	Ext. PHY Spec. Stat Reg */
+	PHY_MARV_CABLE_DIAG	= 0x1c,/* 16 bit r/o	Cable Diagnostic Reg */
+	PHY_MARV_PAGE_ADDR	= 0x1d,/* 16 bit r/w	Extended Page Address Reg */
+	PHY_MARV_PAGE_DATA	= 0x1e,/* 16 bit r/w	Extended Page Data Reg */
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+	PHY_MARV_FE_LED_PAR	= 0x16,/* 16 bit r/w	LED Parallel Select Reg. */
+	PHY_MARV_FE_LED_SER	= 0x17,/* 16 bit r/w	LED Stream Select S. LED */
+	PHY_MARV_FE_VCT_TX	= 0x1a,/* 16 bit r/w	VCT Reg. for TXP/N Pins */
+	PHY_MARV_FE_VCT_RX	= 0x1b,/* 16 bit r/o	VCT Reg. for RXP/N Pins */
+	PHY_MARV_FE_SPEC_2	= 0x1c,/* 16 bit r/w	Specific Control Reg. 2 */
+};
+
+/* Level One-PHY Registers, indirect addressed over XMAC */
+enum {
+	PHY_LONE_CTRL		= 0x00,/* 16 bit r/w	PHY Control Register */
+	PHY_LONE_STAT		= 0x01,/* 16 bit r/o	PHY Status Register */
+	PHY_LONE_ID0		= 0x02,/* 16 bit r/o	PHY ID0 Register */
+	PHY_LONE_ID1		= 0x03,/* 16 bit r/o	PHY ID1 Register */
+	PHY_LONE_AUNE_ADV	= 0x04,/* 16 bit r/w	Auto-Neg. Advertisement */
+	PHY_LONE_AUNE_LP	= 0x05,/* 16 bit r/o	Link Part Ability Reg */
+	PHY_LONE_AUNE_EXP	= 0x06,/* 16 bit r/o	Auto-Neg. Expansion Reg */
+	PHY_LONE_NEPG		= 0x07,/* 16 bit r/w	Next Page Register */
+	PHY_LONE_NEPG_LP	= 0x08,/* 16 bit r/o	Next Page Link Partner */
+	/* Level One-specific registers */
+	PHY_LONE_1000T_CTRL	= 0x09,/* 16 bit r/w	1000Base-T Control Reg */
+	PHY_LONE_1000T_STAT	= 0x0a,/* 16 bit r/o	1000Base-T Status Reg */
+	PHY_LONE_EXT_STAT	= 0x0f,/* 16 bit r/o	Extended Status Reg */
+	PHY_LONE_PORT_CFG	= 0x10,/* 16 bit r/w	Port Configuration Reg*/
+	PHY_LONE_Q_STAT		= 0x11,/* 16 bit r/o	Quick Status Reg */
+	PHY_LONE_INT_ENAB	= 0x12,/* 16 bit r/w	Interrupt Enable Reg */
+	PHY_LONE_INT_STAT	= 0x13,/* 16 bit r/o	Interrupt Status Reg */
+	PHY_LONE_LED_CFG	= 0x14,/* 16 bit r/w	LED Configuration Reg */
+	PHY_LONE_PORT_CTRL	= 0x15,/* 16 bit r/w	Port Control Reg */
+	PHY_LONE_CIM		= 0x16,/* 16 bit r/o	CIM Reg */
+};
+
+/* National-PHY Registers, indirect addressed over XMAC */
+enum {
+	PHY_NAT_CTRL		= 0x00,/* 16 bit r/w	PHY Control Register */
+	PHY_NAT_STAT		= 0x01,/* 16 bit r/w	PHY Status Register */
+	PHY_NAT_ID0		= 0x02,/* 16 bit r/o	PHY ID0 Register */
+	PHY_NAT_ID1		= 0x03,/* 16 bit r/o	PHY ID1 Register */
+	PHY_NAT_AUNE_ADV	= 0x04,/* 16 bit r/w	Auto-Neg. Advertisement */
+	PHY_NAT_AUNE_LP		= 0x05,/* 16 bit r/o	Link Partner Ability Reg */
+	PHY_NAT_AUNE_EXP	= 0x06,/* 16 bit r/o	Auto-Neg. Expansion Reg */
+	PHY_NAT_NEPG		= 0x07,/* 16 bit r/w	Next Page Register */
+	PHY_NAT_NEPG_LP		= 0x08,/* 16 bit r/o	Next Page Link Partner Reg */
+	/* National-specific registers */
+	PHY_NAT_1000T_CTRL	= 0x09,/* 16 bit r/w	1000Base-T Control Reg */
+	PHY_NAT_1000T_STAT	= 0x0a,/* 16 bit r/o	1000Base-T Status Reg */
+	PHY_NAT_EXT_STAT	= 0x0f,/* 16 bit r/o	Extended Status Register */
+	PHY_NAT_EXT_CTRL1	= 0x10,/* 16 bit r/o	Extended Control Reg1 */
+	PHY_NAT_Q_STAT1		= 0x11,/* 16 bit r/o	Quick Status Reg1 */
+	PHY_NAT_10B_OP		= 0x12,/* 16 bit r/o	10Base-T Operations Reg */
+	PHY_NAT_EXT_CTRL2	= 0x13,/* 16 bit r/o	Extended Control Reg1 */
+	PHY_NAT_Q_STAT2		= 0x14,/* 16 bit r/o	Quick Status Reg2 */
+
+	PHY_NAT_PHY_ADDR	= 0x19,/* 16 bit r/o	PHY Address Register */
+};
+
+enum {
+	PHY_CT_RESET	= 1<<15, /* Bit 15: (sc)	clear all PHY related regs */
+	PHY_CT_LOOP	= 1<<14, /* Bit 14:	enable Loopback over PHY */
+	PHY_CT_SPS_LSB	= 1<<13, /* Bit 13:	Speed select, lower bit */
+	PHY_CT_ANE	= 1<<12, /* Bit 12:	Auto-Negotiation Enabled */
+	PHY_CT_PDOWN	= 1<<11, /* Bit 11:	Power Down Mode */
+	PHY_CT_ISOL	= 1<<10, /* Bit 10:	Isolate Mode */
+	PHY_CT_RE_CFG	= 1<<9, /* Bit  9:	(sc) Restart Auto-Negotiation */
+	PHY_CT_DUP_MD	= 1<<8, /* Bit  8:	Duplex Mode */
+	PHY_CT_COL_TST	= 1<<7, /* Bit  7:	Collision Test enabled */
+	PHY_CT_SPS_MSB	= 1<<6, /* Bit  6:	Speed select, upper bit */
+};
+
+enum {
+	PHY_CT_SP1000	= PHY_CT_SPS_MSB, /* enable speed of 1000 Mbps */
+	PHY_CT_SP100	= PHY_CT_SPS_LSB, /* enable speed of  100 Mbps */
+	PHY_CT_SP10	= 0,		  /* enable speed of   10 Mbps */
+};
+
+enum {
+	PHY_ST_EXT_ST	= 1<<8, /* Bit  8:	Extended Status Present */
+
+	PHY_ST_PRE_SUP	= 1<<6, /* Bit  6:	Preamble Suppression */
+	PHY_ST_AN_OVER	= 1<<5, /* Bit  5:	Auto-Negotiation Over */
+	PHY_ST_REM_FLT	= 1<<4, /* Bit  4:	Remote Fault Condition Occured */
+	PHY_ST_AN_CAP	= 1<<3, /* Bit  3:	Auto-Negotiation Capability */
+	PHY_ST_LSYNC	= 1<<2, /* Bit  2:	Link Synchronized */
+	PHY_ST_JAB_DET	= 1<<1, /* Bit  1:	Jabber Detected */
+	PHY_ST_EXT_REG	= 1<<0, /* Bit  0:	Extended Register available */
+};
+
+enum {
+	PHY_I1_OUI_MSK	= 0x3f<<10, /* Bit 15..10:	Organization Unique ID */
+	PHY_I1_MOD_NUM	= 0x3f<<4, /* Bit  9.. 4:	Model Number */
+	PHY_I1_REV_MSK	= 0xf, /* Bit  3.. 0:	Revision Number */
+};
+
+/* different Broadcom PHY Ids */
+enum {
+	PHY_BCOM_ID1_A1	= 0x6041,
+	PHY_BCOM_ID1_B2 = 0x6043,
+	PHY_BCOM_ID1_C0	= 0x6044,
+	PHY_BCOM_ID1_C5	= 0x6047,
+};
+
+/* different Marvell PHY Ids */
+enum {
+	PHY_MARV_ID0_VAL= 0x0141, /* Marvell Unique Identifier */
+	PHY_MARV_ID1_B0	= 0x0C23, /* Yukon (PHY 88E1011) */
+	PHY_MARV_ID1_B2	= 0x0C25, /* Yukon-Plus (PHY 88E1011) */
+	PHY_MARV_ID1_C2	= 0x0CC2, /* Yukon-EC (PHY 88E1111) */
+	PHY_MARV_ID1_Y2	= 0x0C91, /* Yukon-2 (PHY 88E1112) */
+};
+
+enum {
+	PHY_AN_NXT_PG	= 1<<15, /* Bit 15:	Request Next Page */
+	PHY_X_AN_ACK	= 1<<14, /* Bit 14:	(ro) Acknowledge Received */
+	PHY_X_AN_RFB	= 3<<12,/* Bit 13..12:	Remote Fault Bits */
+
+	PHY_X_AN_PAUSE	= 3<<7,/* Bit  8.. 7:	Pause Bits */
+	PHY_X_AN_HD	= 1<<6, /* Bit  6:	Half Duplex */
+	PHY_X_AN_FD	= 1<<5, /* Bit  5:	Full Duplex */
+};
+
+enum {
+	PHY_B_AN_RF	= 1<<13, /* Bit 13:	Remote Fault */
+
+	PHY_B_AN_ASP	= 1<<11, /* Bit 11:	Asymmetric Pause */
+	PHY_B_AN_PC	= 1<<10, /* Bit 10:	Pause Capable */
+	PHY_B_AN_SEL	= 0x1f, /* Bit 4..0:	Selector Field, 00001=Ethernet*/
+};
+
+enum {
+	PHY_L_AN_RF	= 1<<13, /* Bit 13:	Remote Fault */
+								/* Bit 12:	reserved */
+	PHY_L_AN_ASP	= 1<<11, /* Bit 11:	Asymmetric Pause */
+	PHY_L_AN_PC	= 1<<10, /* Bit 10:	Pause Capable */
+
+	PHY_L_AN_SEL	= 0x1f, /* Bit 4..0:	Selector Field, 00001=Ethernet*/
+};
+
+/*  PHY_NAT_AUNE_ADV	16 bit r/w	Auto-Negotiation Advertisement */
+/*  PHY_NAT_AUNE_LP	16 bit r/o	Link Partner Ability Reg *****/
+/*  PHY_AN_NXT_PG	(see XMAC) Bit 15:	Request Next Page */
+enum {
+	PHY_N_AN_RF	= 1<<13, /* Bit 13:	Remote Fault */
+
+	PHY_N_AN_100F	= 1<<11, /* Bit 11:	100Base-T2 FD Support */
+	PHY_N_AN_100H	= 1<<10, /* Bit 10:	100Base-T2 HD Support */
+
+	PHY_N_AN_SEL	= 0x1f, /* Bit 4..0:	Selector Field, 00001=Ethernet*/
+};
+
+/* field type definition for PHY_x_AN_SEL */
+enum {
+	PHY_SEL_TYPE	 = 1,	/* 00001 = Ethernet */
+};
+
+enum {
+	PHY_ANE_LP_NP	= 1<<3, /* Bit  3:	Link Partner can Next Page */
+	PHY_ANE_LOC_NP	= 1<<2, /* Bit  2:	Local PHY can Next Page */
+	PHY_ANE_RX_PG	= 1<<1, /* Bit  1:	Page Received */
+};
+
+enum {
+	PHY_ANE_PAR_DF	= 1<<4, /* Bit  4:	Parallel Detection Fault */
+
+	PHY_ANE_LP_CAP	= 1<<0, /* Bit  0:	Link Partner Auto-Neg. Cap. */ 	
+};
+
+enum {
+	PHY_NP_MORE	= 1<<15, /* Bit 15:	More, Next Pages to follow */
+	PHY_NP_ACK1	= 1<<14, /* Bit 14: (ro)	Ack1, for receiving a message */
+	PHY_NP_MSG_VAL	= 1<<13, /* Bit 13:	Message Page valid */
+	PHY_NP_ACK2	= 1<<12, /* Bit 12:	Ack2, comply with msg content */
+	PHY_NP_TOG	= 1<<11, /* Bit 11:	Toggle Bit, ensure sync */
+	PHY_NP_MSG	= 0x07ff, /* Bit 10..0:	Message from/to Link Partner */
+};
+
+enum {
+	PHY_X_EX_FD	= 1<<15, /* Bit 15:	Device Supports Full Duplex */
+	PHY_X_EX_HD	= 1<<14, /* Bit 14:	Device Supports Half Duplex */
+};
+
+enum {
+	PHY_X_RS_PAUSE	= 3<<7,/* Bit  8..7:	selected Pause Mode */
+	PHY_X_RS_HD	= 1<<6, /* Bit  6:	Half Duplex Mode selected */
+	PHY_X_RS_FD	= 1<<5, /* Bit  5:	Full Duplex Mode selected */
+	PHY_X_RS_ABLMIS	= 1<<4, /* Bit  4:	duplex or pause cap mismatch */
+	PHY_X_RS_PAUMIS	= 1<<3, /* Bit  3:	pause capability mismatch */
+};
+
+/** Remote Fault Bits (PHY_X_AN_RFB) encoding  */
+enum {
+	X_RFB_OK	= 0<<12,/* Bit 13..12	No errors, Link OK */
+	X_RFB_LF	= 1<<12, /* Bit 13..12	Link Failure */
+	X_RFB_OFF	= 2<<12,/* Bit 13..12	Offline */
+	X_RFB_AN_ERR	= 3<<12,/* Bit 13..12	Auto-Negotiation Error */
+};
+
+/* Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding */
+enum {
+	PHY_X_P_NO_PAUSE	= 0<<7,/* Bit  8..7:	no Pause Mode */
+	PHY_X_P_SYM_MD	= 1<<7, /* Bit  8..7:	symmetric Pause Mode */
+	PHY_X_P_ASYM_MD	= 2<<7,/* Bit  8..7:	asymmetric Pause Mode */
+	PHY_X_P_BOTH_MD	= 3<<7,/* Bit  8..7:	both Pause Mode */
+};
+
+
+/* Broadcom-Specific */
+/*****  PHY_BCOM_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
+enum {
+	PHY_B_1000C_TEST	= 7<<13,/* Bit 15..13:	Test Modes */
+	PHY_B_1000C_MSE	= 1<<12, /* Bit 12:	Master/Slave Enable */
+	PHY_B_1000C_MSC	= 1<<11, /* Bit 11:	M/S Configuration */
+	PHY_B_1000C_RD	= 1<<10, /* Bit 10:	Repeater/DTE */
+	PHY_B_1000C_AFD	= 1<<9, /* Bit  9:	Advertise Full Duplex */
+	PHY_B_1000C_AHD	= 1<<8, /* Bit  8:	Advertise Half Duplex */
+};
+
+/*****  PHY_BCOM_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
+/*****  PHY_MARV_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
+enum {
+	PHY_B_1000S_MSF	= 1<<15, /* Bit 15:	Master/Slave Fault */
+	PHY_B_1000S_MSR	= 1<<14, /* Bit 14:	Master/Slave Result */
+	PHY_B_1000S_LRS	= 1<<13, /* Bit 13:	Local Receiver Status */
+	PHY_B_1000S_RRS	= 1<<12, /* Bit 12:	Remote Receiver Status */
+	PHY_B_1000S_LP_FD	= 1<<11, /* Bit 11:	Link Partner can FD */
+	PHY_B_1000S_LP_HD	= 1<<10, /* Bit 10:	Link Partner can HD */
+									/* Bit  9..8:	reserved */
+	PHY_B_1000S_IEC	= 0xff, /* Bit  7..0:	Idle Error Count */
+};
+
+/*****  PHY_BCOM_EXT_STAT	16 bit r/o	Extended Status Register *****/
+enum {
+	PHY_B_ES_X_FD_CAP	= 1<<15, /* Bit 15:	1000Base-X FD capable */
+	PHY_B_ES_X_HD_CAP	= 1<<14, /* Bit 14:	1000Base-X HD capable */
+	PHY_B_ES_T_FD_CAP	= 1<<13, /* Bit 13:	1000Base-T FD capable */
+	PHY_B_ES_T_HD_CAP	= 1<<12, /* Bit 12:	1000Base-T HD capable */
+};
+
+/*****  PHY_BCOM_P_EXT_CTRL	16 bit r/w	PHY Extended Control Reg *****/
+enum {
+	PHY_B_PEC_MAC_PHY	= 1<<15, /* Bit 15:	10BIT/GMI-Interface */
+	PHY_B_PEC_DIS_CROSS	= 1<<14, /* Bit 14:	Disable MDI Crossover */
+	PHY_B_PEC_TX_DIS	= 1<<13, /* Bit 13:	Tx output Disabled */
+	PHY_B_PEC_INT_DIS	= 1<<12, /* Bit 12:	Interrupts Disabled */
+	PHY_B_PEC_F_INT	= 1<<11, /* Bit 11:	Force Interrupt */
+	PHY_B_PEC_BY_45	= 1<<10, /* Bit 10:	Bypass 4B5B-Decoder */
+	PHY_B_PEC_BY_SCR	= 1<<9, /* Bit  9:	Bypass Scrambler */
+	PHY_B_PEC_BY_MLT3	= 1<<8, /* Bit  8:	Bypass MLT3 Encoder */
+	PHY_B_PEC_BY_RXA	= 1<<7, /* Bit  7:	Bypass Rx Alignm. */
+	PHY_B_PEC_RES_SCR	= 1<<6, /* Bit  6:	Reset Scrambler */
+	PHY_B_PEC_EN_LTR	= 1<<5, /* Bit  5:	Ena LED Traffic Mode */
+	PHY_B_PEC_LED_ON	= 1<<4, /* Bit  4:	Force LED's on */
+	PHY_B_PEC_LED_OFF	= 1<<3, /* Bit  3:	Force LED's off */
+	PHY_B_PEC_EX_IPG	= 1<<2, /* Bit  2:	Extend Tx IPG Mode */
+	PHY_B_PEC_3_LED	= 1<<1, /* Bit  1:	Three Link LED mode */
+	PHY_B_PEC_HIGH_LA	= 1<<0, /* Bit  0:	GMII FIFO Elasticy */
+};
+
+/*****  PHY_BCOM_P_EXT_STAT	16 bit r/o	PHY Extended Status Reg *****/
+enum {
+	PHY_B_PES_CROSS_STAT	= 1<<13, /* Bit 13:	MDI Crossover Status */
+	PHY_B_PES_INT_STAT	= 1<<12, /* Bit 12:	Interrupt Status */
+	PHY_B_PES_RRS	= 1<<11, /* Bit 11:	Remote Receiver Stat. */
+	PHY_B_PES_LRS	= 1<<10, /* Bit 10:	Local Receiver Stat. */
+	PHY_B_PES_LOCKED	= 1<<9, /* Bit  9:	Locked */
+	PHY_B_PES_LS	= 1<<8, /* Bit  8:	Link Status */
+	PHY_B_PES_RF	= 1<<7, /* Bit  7:	Remote Fault */
+	PHY_B_PES_CE_ER	= 1<<6, /* Bit  6:	Carrier Ext Error */
+	PHY_B_PES_BAD_SSD	= 1<<5, /* Bit  5:	Bad SSD */
+	PHY_B_PES_BAD_ESD	= 1<<4, /* Bit  4:	Bad ESD */
+	PHY_B_PES_RX_ER	= 1<<3, /* Bit  3:	Receive Error */
+	PHY_B_PES_TX_ER	= 1<<2, /* Bit  2:	Transmit Error */
+	PHY_B_PES_LOCK_ER	= 1<<1, /* Bit  1:	Lock Error */
+	PHY_B_PES_MLT3_ER	= 1<<0, /* Bit  0:	MLT3 code Error */
+};
+
+/*****  PHY_BCOM_FC_CTR		16 bit r/w	False Carrier Counter *****/
+enum {
+	PHY_B_FC_CTR	= 0xff, /* Bit  7..0:	False Carrier Counter */
+
+/*****  PHY_BCOM_RNO_CTR	16 bit r/w	Receive NOT_OK Counter *****/
+	PHY_B_RC_LOC_MSK	= 0xff00, /* Bit 15..8:	Local Rx NOT_OK cnt */
+	PHY_B_RC_REM_MSK	= 0x00ff, /* Bit  7..0:	Remote Rx NOT_OK cnt */
+
+/*****  PHY_BCOM_AUX_CTRL	16 bit r/w	Auxiliary Control Reg *****/
+	PHY_B_AC_L_SQE		= 1<<15, /* Bit 15:	Low Squelch */
+	PHY_B_AC_LONG_PACK	= 1<<14, /* Bit 14:	Rx Long Packets */
+	PHY_B_AC_ER_CTRL	= 3<<12,/* Bit 13..12:	Edgerate Control */
+									/* Bit 11:	reserved */
+	PHY_B_AC_TX_TST	= 1<<10, /* Bit 10:	Tx test bit, always 1 */
+									/* Bit  9.. 8:	reserved */
+	PHY_B_AC_DIS_PRF	= 1<<7, /* Bit  7:	dis part resp filter */
+									/* Bit  6:	reserved */
+	PHY_B_AC_DIS_PM	= 1<<5, /* Bit  5:	dis power management */
+									/* Bit  4:	reserved */
+	PHY_B_AC_DIAG	= 1<<3, /* Bit  3:	Diagnostic Mode */
+};
+
+/*****  PHY_BCOM_AUX_STAT	16 bit r/o	Auxiliary Status Reg *****/
+enum {
+	PHY_B_AS_AN_C	= 1<<15, /* Bit 15:	AutoNeg complete */
+	PHY_B_AS_AN_CA	= 1<<14, /* Bit 14:	AN Complete Ack */
+	PHY_B_AS_ANACK_D	= 1<<13, /* Bit 13:	AN Ack Detect */
+	PHY_B_AS_ANAB_D	= 1<<12, /* Bit 12:	AN Ability Detect */
+	PHY_B_AS_NPW	= 1<<11, /* Bit 11:	AN Next Page Wait */
+	PHY_B_AS_AN_RES_MSK	= 7<<8,/* Bit 10..8:	AN HDC */
+	PHY_B_AS_PDF	= 1<<7, /* Bit  7:	Parallel Detect. Fault */
+	PHY_B_AS_RF	= 1<<6, /* Bit  6:	Remote Fault */
+	PHY_B_AS_ANP_R	= 1<<5, /* Bit  5:	AN Page Received */
+	PHY_B_AS_LP_ANAB	= 1<<4, /* Bit  4:	LP AN Ability */
+	PHY_B_AS_LP_NPAB	= 1<<3, /* Bit  3:	LP Next Page Ability */
+	PHY_B_AS_LS	= 1<<2, /* Bit  2:	Link Status */
+	PHY_B_AS_PRR	= 1<<1, /* Bit  1:	Pause Resolution-Rx */
+	PHY_B_AS_PRT	= 1<<0, /* Bit  0:	Pause Resolution-Tx */
+};
+#define PHY_B_AS_PAUSE_MSK	(PHY_B_AS_PRR | PHY_B_AS_PRT)
+
+/*****  PHY_BCOM_INT_STAT	16 bit r/o	Interrupt Status Reg *****/
+/*****  PHY_BCOM_INT_MASK	16 bit r/w	Interrupt Mask Reg *****/
+enum {
+	PHY_B_IS_PSE	= 1<<14, /* Bit 14:	Pair Swap Error */
+	PHY_B_IS_MDXI_SC	= 1<<13, /* Bit 13:	MDIX Status Change */
+	PHY_B_IS_HCT	= 1<<12, /* Bit 12:	counter above 32k */
+	PHY_B_IS_LCT	= 1<<11, /* Bit 11:	counter above 128 */
+	PHY_B_IS_AN_PR	= 1<<10, /* Bit 10:	Page Received */
+	PHY_B_IS_NO_HDCL	= 1<<9, /* Bit  9:	No HCD Link */
+	PHY_B_IS_NO_HDC	= 1<<8, /* Bit  8:	No HCD */
+	PHY_B_IS_NEG_USHDC	= 1<<7, /* Bit  7:	Negotiated Unsup. HCD */
+	PHY_B_IS_SCR_S_ER	= 1<<6, /* Bit  6:	Scrambler Sync Error */
+	PHY_B_IS_RRS_CHANGE	= 1<<5, /* Bit  5:	Remote Rx Stat Change */
+	PHY_B_IS_LRS_CHANGE	= 1<<4, /* Bit  4:	Local Rx Stat Change */
+	PHY_B_IS_DUP_CHANGE	= 1<<3, /* Bit  3:	Duplex Mode Change */
+	PHY_B_IS_LSP_CHANGE	= 1<<2, /* Bit  2:	Link Speed Change */
+	PHY_B_IS_LST_CHANGE	= 1<<1, /* Bit  1:	Link Status Changed */
+	PHY_B_IS_CRC_ER	= 1<<0, /* Bit  0:	CRC Error */
+};
+#define PHY_B_DEF_MSK	(~(PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE))
+
+/* Pause Bits (PHY_B_AN_ASP and PHY_B_AN_PC) encoding */
+enum {
+	PHY_B_P_NO_PAUSE	= 0<<10,/* Bit 11..10:	no Pause Mode */
+	PHY_B_P_SYM_MD	= 1<<10, /* Bit 11..10:	symmetric Pause Mode */
+	PHY_B_P_ASYM_MD	= 2<<10,/* Bit 11..10:	asymmetric Pause Mode */
+	PHY_B_P_BOTH_MD	= 3<<10,/* Bit 11..10:	both Pause Mode */
+};
+/*
+ * Resolved Duplex mode and Capabilities (Aux Status Summary Reg)
+ */
+enum {
+	PHY_B_RES_1000FD	= 7<<8,/* Bit 10..8:	1000Base-T Full Dup. */
+	PHY_B_RES_1000HD	= 6<<8,/* Bit 10..8:	1000Base-T Half Dup. */
+};
+
+/*
+ * Level One-Specific
+ */
+/*****  PHY_LONE_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
+enum {
+	PHY_L_1000C_TEST	= 7<<13,/* Bit 15..13:	Test Modes */
+	PHY_L_1000C_MSE	= 1<<12, /* Bit 12:	Master/Slave Enable */
+	PHY_L_1000C_MSC	= 1<<11, /* Bit 11:	M/S Configuration */
+	PHY_L_1000C_RD	= 1<<10, /* Bit 10:	Repeater/DTE */
+	PHY_L_1000C_AFD	= 1<<9, /* Bit  9:	Advertise Full Duplex */
+	PHY_L_1000C_AHD	= 1<<8, /* Bit  8:	Advertise Half Duplex */
+};
+
+/*****  PHY_LONE_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
+enum {
+	PHY_L_1000S_MSF	= 1<<15, /* Bit 15:	Master/Slave Fault */
+	PHY_L_1000S_MSR	= 1<<14, /* Bit 14:	Master/Slave Result */
+	PHY_L_1000S_LRS	= 1<<13, /* Bit 13:	Local Receiver Status */
+	PHY_L_1000S_RRS	= 1<<12, /* Bit 12:	Remote Receiver Status */
+	PHY_L_1000S_LP_FD = 1<<11, /* Bit 11:	Link Partner can FD */
+	PHY_L_1000S_LP_HD = 1<<10, /* Bit 10:	Link Partner can HD */
+
+	PHY_L_1000S_IEC	 = 0xff, /* Bit  7..0:	Idle Error Count */
+
+/*****  PHY_LONE_EXT_STAT	16 bit r/o	Extended Status Register *****/
+	PHY_L_ES_X_FD_CAP = 1<<15, /* Bit 15:	1000Base-X FD capable */
+	PHY_L_ES_X_HD_CAP = 1<<14, /* Bit 14:	1000Base-X HD capable */
+	PHY_L_ES_T_FD_CAP = 1<<13, /* Bit 13:	1000Base-T FD capable */
+	PHY_L_ES_T_HD_CAP = 1<<12, /* Bit 12:	1000Base-T HD capable */
+};
+
+/*****  PHY_LONE_PORT_CFG	16 bit r/w	Port Configuration Reg *****/
+enum {
+	PHY_L_PC_REP_MODE	= 1<<15, /* Bit 15:	Repeater Mode */
+
+	PHY_L_PC_TX_DIS	= 1<<13, /* Bit 13:	Tx output Disabled */
+	PHY_L_PC_BY_SCR	= 1<<12, /* Bit 12:	Bypass Scrambler */
+	PHY_L_PC_BY_45	= 1<<11, /* Bit 11:	Bypass 4B5B-Decoder */
+	PHY_L_PC_JAB_DIS	= 1<<10, /* Bit 10:	Jabber Disabled */
+	PHY_L_PC_SQE	= 1<<9, /* Bit  9:	Enable Heartbeat */
+	PHY_L_PC_TP_LOOP	= 1<<8, /* Bit  8:	TP Loopback */
+	PHY_L_PC_SSS	= 1<<7, /* Bit  7:	Smart Speed Selection */
+	PHY_L_PC_FIFO_SIZE	= 1<<6, /* Bit  6:	FIFO Size */
+	PHY_L_PC_PRE_EN	= 1<<5, /* Bit  5:	Preamble Enable */
+	PHY_L_PC_CIM	= 1<<4, /* Bit  4:	Carrier Integrity Mon */
+	PHY_L_PC_10_SER	= 1<<3, /* Bit  3:	Use Serial Output */
+	PHY_L_PC_ANISOL	= 1<<2, /* Bit  2:	Unisolate Port */
+	PHY_L_PC_TEN_BIT	= 1<<1, /* Bit  1:	10bit iface mode on */
+	PHY_L_PC_ALTCLOCK	= 1<<0, /* Bit  0: (ro)	ALTCLOCK Mode on */
+};
+
+/*****  PHY_LONE_Q_STAT		16 bit r/o	Quick Status Reg *****/
+enum {
+	PHY_L_QS_D_RATE	= 3<<14,/* Bit 15..14:	Data Rate */
+	PHY_L_QS_TX_STAT	= 1<<13, /* Bit 13:	Transmitting */
+	PHY_L_QS_RX_STAT	= 1<<12, /* Bit 12:	Receiving */
+	PHY_L_QS_COL_STAT	= 1<<11, /* Bit 11:	Collision */
+	PHY_L_QS_L_STAT	= 1<<10, /* Bit 10:	Link is up */
+	PHY_L_QS_DUP_MOD	= 1<<9, /* Bit  9:	Full/Half Duplex */
+	PHY_L_QS_AN	= 1<<8, /* Bit  8:	AutoNeg is On */
+	PHY_L_QS_AN_C	= 1<<7, /* Bit  7:	AN is Complete */
+	PHY_L_QS_LLE	= 7<<4,/* Bit  6..4:	Line Length Estim. */
+	PHY_L_QS_PAUSE	= 1<<3, /* Bit  3:	LP advertised Pause */
+	PHY_L_QS_AS_PAUSE	= 1<<2, /* Bit  2:	LP adv. asym. Pause */
+	PHY_L_QS_ISOLATE	= 1<<1, /* Bit  1:	CIM Isolated */
+	PHY_L_QS_EVENT	= 1<<0, /* Bit  0:	Event has occurred */
+};
+
+/*****  PHY_LONE_INT_ENAB	16 bit r/w	Interrupt Enable Reg *****/
+/*****  PHY_LONE_INT_STAT	16 bit r/o	Interrupt Status Reg *****/
+enum {
+	PHY_L_IS_AN_F	= 1<<13, /* Bit 13:	Auto-Negotiation fault */
+	PHY_L_IS_CROSS	= 1<<11, /* Bit 11:	Crossover used */
+	PHY_L_IS_POL	= 1<<10, /* Bit 10:	Polarity correct. used */
+	PHY_L_IS_SS	= 1<<9, /* Bit  9:	Smart Speed Downgrade */
+	PHY_L_IS_CFULL	= 1<<8, /* Bit  8:	Counter Full */
+	PHY_L_IS_AN_C	= 1<<7, /* Bit  7:	AutoNeg Complete */
+	PHY_L_IS_SPEED	= 1<<6, /* Bit  6:	Speed Changed */
+	PHY_L_IS_DUP	= 1<<5, /* Bit  5:	Duplex Changed */
+	PHY_L_IS_LS	= 1<<4, /* Bit  4:	Link Status Changed */
+	PHY_L_IS_ISOL	= 1<<3, /* Bit  3:	Isolate Occured */
+	PHY_L_IS_MDINT	= 1<<2, /* Bit  2: (ro)	STAT: MII Int Pending */
+	PHY_L_IS_INTEN	= 1<<1, /* Bit  1:	ENAB: Enable IRQs */
+	PHY_L_IS_FORCE	= 1<<0, /* Bit  0:	ENAB: Force Interrupt */
+};
+
+/* int. mask */
+#define PHY_L_DEF_MSK	(PHY_L_IS_LS | PHY_L_IS_ISOL | PHY_L_IS_INTEN)
+
+/*****  PHY_LONE_LED_CFG	16 bit r/w	LED Configuration Reg *****/
+enum {
+	PHY_L_LC_LEDC	= 3<<14,/* Bit 15..14:	Col/Blink/On/Off */
+	PHY_L_LC_LEDR	= 3<<12,/* Bit 13..12:	Rx/Blink/On/Off */
+	PHY_L_LC_LEDT	= 3<<10,/* Bit 11..10:	Tx/Blink/On/Off */
+	PHY_L_LC_LEDG	= 3<<8,/* Bit  9..8:	Giga/Blink/On/Off */
+	PHY_L_LC_LEDS	= 3<<6,/* Bit  7..6:	10-100/Blink/On/Off */
+	PHY_L_LC_LEDL	= 3<<4,/* Bit  5..4:	Link/Blink/On/Off */
+	PHY_L_LC_LEDF	= 3<<2,/* Bit  3..2:	Duplex/Blink/On/Off */
+	PHY_L_LC_PSTRECH= 1<<1, /* Bit  1:	Strech LED Pulses */
+	PHY_L_LC_FREQ	= 1<<0, /* Bit  0:	30/100 ms */
+};
+
+/*****  PHY_LONE_PORT_CTRL	16 bit r/w	Port Control Reg *****/
+enum {
+	PHY_L_PC_TX_TCLK = 1<<15, /* Bit 15:	Enable TX_TCLK */
+	PHY_L_PC_ALT_NP	 = 1<<13, /* Bit 14:	Alternate Next Page */
+	PHY_L_PC_GMII_ALT= 1<<12, /* Bit 13:	Alternate GMII driver */
+	PHY_L_PC_TEN_CRS = 1<<10, /* Bit 10:	Extend CRS*/
+};
+
+/*****  PHY_LONE_CIM		16 bit r/o	CIM Reg *****/
+enum {
+	PHY_L_CIM_ISOL	    = 0xff<<8,/* Bit 15..8:	Isolate Count */
+	PHY_L_CIM_FALSE_CAR = 0xff,   /* Bit  7..0:	False Carrier Count */
+};
+
+/*
+ * Pause Bits (PHY_L_AN_ASP and PHY_L_AN_PC) encoding
+ */
+enum {
+	PHY_L_P_NO_PAUSE= 0<<10,/* Bit 11..10:	no Pause Mode */
+	PHY_L_P_SYM_MD	= 1<<10, /* Bit 11..10:	symmetric Pause Mode */
+	PHY_L_P_ASYM_MD	= 2<<10,/* Bit 11..10:	asymmetric Pause Mode */
+	PHY_L_P_BOTH_MD	= 3<<10,/* Bit 11..10:	both Pause Mode */
+};
+
+/*
+ * National-Specific
+ */
+/*****  PHY_NAT_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
+enum {
+	PHY_N_1000C_TEST= 7<<13,/* Bit 15..13:	Test Modes */
+	PHY_N_1000C_MSE	= 1<<12, /* Bit 12:	Master/Slave Enable */
+	PHY_N_1000C_MSC	= 1<<11, /* Bit 11:	M/S Configuration */
+	PHY_N_1000C_RD	= 1<<10, /* Bit 10:	Repeater/DTE */
+	PHY_N_1000C_AFD	= 1<<9, /* Bit  9:	Advertise Full Duplex */
+	PHY_N_1000C_AHD	= 1<<8, /* Bit  8:	Advertise Half Duplex */
+	PHY_N_1000C_APC	= 1<<7, /* Bit  7:	Asymmetric Pause Cap. */};
+
+
+/*****  PHY_NAT_1000T_STAT	16 bit r/o	1000Base-T Status Reg *****/
+enum {
+	PHY_N_1000S_MSF	= 1<<15, /* Bit 15:	Master/Slave Fault */
+	PHY_N_1000S_MSR	= 1<<14, /* Bit 14:	Master/Slave Result */
+	PHY_N_1000S_LRS	= 1<<13, /* Bit 13:	Local Receiver Status */
+	PHY_N_1000S_RRS	= 1<<12, /* Bit 12:	Remote Receiver Status*/
+	PHY_N_1000S_LP_FD= 1<<11, /* Bit 11:	Link Partner can FD */
+	PHY_N_1000S_LP_HD= 1<<10, /* Bit 10:	Link Partner can HD */
+	PHY_N_1000C_LP_APC= 1<<9, /* Bit  9:	LP Asym. Pause Cap. */
+	PHY_N_1000S_IEC	= 0xff, /* Bit  7..0:	Idle Error Count */
+};
+
+/*****  PHY_NAT_EXT_STAT	16 bit r/o	Extended Status Register *****/
+enum {
+	PHY_N_ES_X_FD_CAP= 1<<15, /* Bit 15:	1000Base-X FD capable */
+	PHY_N_ES_X_HD_CAP= 1<<14, /* Bit 14:	1000Base-X HD capable */
+	PHY_N_ES_T_FD_CAP= 1<<13, /* Bit 13:	1000Base-T FD capable */
+	PHY_N_ES_T_HD_CAP= 1<<12, /* Bit 12:	1000Base-T HD capable */
+};
+
+/** Marvell-Specific */
+enum {
+	PHY_M_AN_NXT_PG	= 1<<15, /* Request Next Page */
+	PHY_M_AN_ACK	= 1<<14, /* (ro)	Acknowledge Received */
+	PHY_M_AN_RF	= 1<<13, /* Remote Fault */
+
+	PHY_M_AN_ASP	= 1<<11, /* Asymmetric Pause */
+	PHY_M_AN_PC	= 1<<10, /* MAC Pause implemented */
+	PHY_M_AN_100_T4	= 1<<9, /* Not cap. 100Base-T4 (always 0) */
+	PHY_M_AN_100_FD	= 1<<8, /* Advertise 100Base-TX Full Duplex */
+	PHY_M_AN_100_HD	= 1<<7, /* Advertise 100Base-TX Half Duplex */
+	PHY_M_AN_10_FD	= 1<<6, /* Advertise 10Base-TX Full Duplex */
+	PHY_M_AN_10_HD	= 1<<5, /* Advertise 10Base-TX Half Duplex */
+	PHY_M_AN_SEL_MSK =0x1f<<4,	/* Bit  4.. 0: Selector Field Mask */
+};
+
+/* special defines for FIBER (88E1011S only) */
+enum {
+	PHY_M_AN_ASP_X	= 1<<8, /* Asymmetric Pause */
+	PHY_M_AN_PC_X	= 1<<7, /* MAC Pause implemented */
+	PHY_M_AN_1000X_AHD	= 1<<6, /* Advertise 10000Base-X Half Duplex */
+	PHY_M_AN_1000X_AFD	= 1<<5, /* Advertise 10000Base-X Full Duplex */
+};
+
+/* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */
+enum {
+	PHY_M_P_NO_PAUSE_X	= 0<<7,/* Bit  8.. 7:	no Pause Mode */
+	PHY_M_P_SYM_MD_X	= 1<<7, /* Bit  8.. 7:	symmetric Pause Mode */
+	PHY_M_P_ASYM_MD_X	= 2<<7,/* Bit  8.. 7:	asymmetric Pause Mode */
+	PHY_M_P_BOTH_MD_X	= 3<<7,/* Bit  8.. 7:	both Pause Mode */
+};
+
+/*****  PHY_MARV_1000T_CTRL	16 bit r/w	1000Base-T Control Reg *****/
+enum {
+	PHY_M_1000C_TEST	= 7<<13,/* Bit 15..13:	Test Modes */
+	PHY_M_1000C_MSE	= 1<<12, /* Manual Master/Slave Enable */
+	PHY_M_1000C_MSC	= 1<<11, /* M/S Configuration (1=Master) */
+	PHY_M_1000C_MPD	= 1<<10, /* Multi-Port Device */
+	PHY_M_1000C_AFD	= 1<<9, /* Advertise Full Duplex */
+	PHY_M_1000C_AHD	= 1<<8, /* Advertise Half Duplex */
+};
+
+/*****  PHY_MARV_PHY_CTRL	16 bit r/w	PHY Specific Ctrl Reg *****/
+enum {
+	PHY_M_PC_TX_FFD_MSK	= 3<<14,/* Bit 15..14: Tx FIFO Depth Mask */
+	PHY_M_PC_RX_FFD_MSK	= 3<<12,/* Bit 13..12: Rx FIFO Depth Mask */
+	PHY_M_PC_ASS_CRS_TX	= 1<<11, /* Assert CRS on Transmit */
+	PHY_M_PC_FL_GOOD	= 1<<10, /* Force Link Good */
+	PHY_M_PC_EN_DET_MSK	= 3<<8,/* Bit  9.. 8: Energy Detect Mask */
+	PHY_M_PC_ENA_EXT_D	= 1<<7, /* Enable Ext. Distance (10BT) */
+	PHY_M_PC_MDIX_MSK	= 3<<5,/* Bit  6.. 5: MDI/MDIX Config. Mask */
+	PHY_M_PC_DIS_125CLK	= 1<<4, /* Disable 125 CLK */
+	PHY_M_PC_MAC_POW_UP	= 1<<3, /* MAC Power up */
+	PHY_M_PC_SQE_T_ENA	= 1<<2, /* SQE Test Enabled */
+	PHY_M_PC_POL_R_DIS	= 1<<1, /* Polarity Reversal Disabled */
+	PHY_M_PC_DIS_JABBER	= 1<<0, /* Disable Jabber */
+};
+
+enum {
+	PHY_M_PC_EN_DET		= 2<<8,	/* Energy Detect (Mode 1) */
+	PHY_M_PC_EN_DET_PLUS	= 3<<8, /* Energy Detect Plus (Mode 2) */
+};
+
+#define PHY_M_PC_MDI_XMODE(x)	(((x)<<5) & PHY_M_PC_MDIX_MSK)	
+
+enum {
+	PHY_M_PC_MAN_MDI	= 0, /* 00 = Manual MDI configuration */
+	PHY_M_PC_MAN_MDIX	= 1, /* 01 = Manual MDIX configuration */
+	PHY_M_PC_ENA_AUTO	= 3, /* 11 = Enable Automatic Crossover */
+};
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+enum {
+	PHY_M_PC_ENA_DTE_DT	= 1<<15, /* Enable Data Terminal Equ. (DTE) Detect */
+	PHY_M_PC_ENA_ENE_DT	= 1<<14, /* Enable Energy Detect (sense & pulse) */
+	PHY_M_PC_DIS_NLP_CK	= 1<<13, /* Disable Normal Link Puls (NLP) Check */
+	PHY_M_PC_ENA_LIP_NP	= 1<<12, /* Enable Link Partner Next Page Reg. */
+	PHY_M_PC_DIS_NLP_GN	= 1<<11, /* Disable Normal Link Puls Generation */
+
+	PHY_M_PC_DIS_SCRAMB	= 1<<9, /* Disable Scrambler */
+	PHY_M_PC_DIS_FEFI	= 1<<8, /* Disable Far End Fault Indic. (FEFI) */
+
+	PHY_M_PC_SH_TP_SEL	= 1<<6, /* Shielded Twisted Pair Select */
+	PHY_M_PC_RX_FD_MSK	= 3<<2,/* Bit  3.. 2: Rx FIFO Depth Mask */
+};
+
+/*****  PHY_MARV_PHY_STAT	16 bit r/o	PHY Specific Status Reg *****/
+enum {
+	PHY_M_PS_SPEED_MSK	= 3<<14, /* Bit 15..14: Speed Mask */
+	PHY_M_PS_SPEED_1000	= 1<<15, /*		10 = 1000 Mbps */
+	PHY_M_PS_SPEED_100	= 1<<14, /*		01 =  100 Mbps */
+	PHY_M_PS_SPEED_10	= 0,	 /*		00 =   10 Mbps */
+	PHY_M_PS_FULL_DUP	= 1<<13, /* Full Duplex */
+	PHY_M_PS_PAGE_REC	= 1<<12, /* Page Received */
+	PHY_M_PS_SPDUP_RES	= 1<<11, /* Speed & Duplex Resolved */
+	PHY_M_PS_LINK_UP	= 1<<10, /* Link Up */
+	PHY_M_PS_CABLE_MSK	= 7<<7,  /* Bit  9.. 7: Cable Length Mask */
+	PHY_M_PS_MDI_X_STAT	= 1<<6,  /* MDI Crossover Stat (1=MDIX) */
+	PHY_M_PS_DOWNS_STAT	= 1<<5,  /* Downshift Status (1=downsh.) */
+	PHY_M_PS_ENDET_STAT	= 1<<4,  /* Energy Detect Status (1=act) */
+	PHY_M_PS_TX_P_EN	= 1<<3,  /* Tx Pause Enabled */
+	PHY_M_PS_RX_P_EN	= 1<<2,  /* Rx Pause Enabled */
+	PHY_M_PS_POL_REV	= 1<<1,  /* Polarity Reversed */
+	PHY_M_PS_JABBER		= 1<<0,  /* Jabber */
+};
+
+#define PHY_M_PS_PAUSE_MSK	(PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN)
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+enum {
+	PHY_M_PS_DTE_DETECT	= 1<<15, /* Data Terminal Equipment (DTE) Detected */
+	PHY_M_PS_RES_SPEED	= 1<<14, /* Resolved Speed (1=100 Mbps, 0=10 Mbps */
+};
+
+enum {
+	PHY_M_IS_AN_ERROR	= 1<<15, /* Auto-Negotiation Error */
+	PHY_M_IS_LSP_CHANGE	= 1<<14, /* Link Speed Changed */
+	PHY_M_IS_DUP_CHANGE	= 1<<13, /* Duplex Mode Changed */
+	PHY_M_IS_AN_PR		= 1<<12, /* Page Received */
+	PHY_M_IS_AN_COMPL	= 1<<11, /* Auto-Negotiation Completed */
+	PHY_M_IS_LST_CHANGE	= 1<<10, /* Link Status Changed */
+	PHY_M_IS_SYMB_ERROR	= 1<<9, /* Symbol Error */
+	PHY_M_IS_FALSE_CARR	= 1<<8, /* False Carrier */
+	PHY_M_IS_FIFO_ERROR	= 1<<7, /* FIFO Overflow/Underrun Error */
+	PHY_M_IS_MDI_CHANGE	= 1<<6, /* MDI Crossover Changed */
+	PHY_M_IS_DOWNSH_DET	= 1<<5, /* Downshift Detected */
+	PHY_M_IS_END_CHANGE	= 1<<4, /* Energy Detect Changed */
+
+	PHY_M_IS_DTE_CHANGE	= 1<<2, /* DTE Power Det. Status Changed */
+	PHY_M_IS_POL_CHANGE	= 1<<1, /* Polarity Changed */
+	PHY_M_IS_JABBER		= 1<<0, /* Jabber */
+};
+
+#define PHY_M_DEF_MSK	( PHY_M_IS_AN_ERROR | PHY_M_IS_LSP_CHANGE | \
+			  PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR)
+
+/*****  PHY_MARV_EXT_CTRL	16 bit r/w	Ext. PHY Specific Ctrl *****/
+enum {
+	PHY_M_EC_ENA_BC_EXT = 1<<15, /* Enable Block Carr. Ext. (88E1111 only) */
+	PHY_M_EC_ENA_LIN_LB = 1<<14, /* Enable Line Loopback (88E1111 only) */
+
+	PHY_M_EC_DIS_LINK_P = 1<<12, /* Disable Link Pulses (88E1111 only) */
+	PHY_M_EC_M_DSC_MSK  = 3<<10, /* Bit 11..10:	Master Downshift Counter */
+					/* (88E1011 only) */
+	PHY_M_EC_S_DSC_MSK	= 3<<8,/* Bit  9.. 8:	Slave  Downshift Counter */
+				       /* (88E1011 only) */
+	PHY_M_EC_M_DSC_MSK2	= 7<<9,/* Bit 11.. 9:	Master Downshift Counter */
+					/* (88E1111 only) */
+	PHY_M_EC_DOWN_S_ENA	= 1<<8, /* Downshift Enable (88E1111 only) */
+					/* !!! Errata in spec. (1 = disable) */
+	PHY_M_EC_RX_TIM_CT	= 1<<7, /* RGMII Rx Timing Control*/
+	PHY_M_EC_MAC_S_MSK	= 7<<4,/* Bit  6.. 4:	Def. MAC interface speed */
+	PHY_M_EC_FIB_AN_ENA	= 1<<3, /* Fiber Auto-Neg. Enable (88E1011S only) */
+	PHY_M_EC_DTE_D_ENA	= 1<<2, /* DTE Detect Enable (88E1111 only) */
+	PHY_M_EC_TX_TIM_CT	= 1<<1, /* RGMII Tx Timing Control */
+	PHY_M_EC_TRANS_DIS	= 1<<0, /* Transmitter Disable (88E1111 only) */};
+
+#define PHY_M_EC_M_DSC(x)	((x)<<10) /* 00=1x; 01=2x; 10=3x; 11=4x */
+#define PHY_M_EC_S_DSC(x)	((x)<<8) /* 00=dis; 01=1x; 10=2x; 11=3x */
+#define PHY_M_EC_MAC_S(x)	((x)<<4) /* 01X=0; 110=2.5; 111=25 (MHz) */
+
+#define PHY_M_EC_M_DSC_2(x)	((x)<<9) /* 000=1x; 001=2x; 010=3x; 011=4x */
+											/* 100=5x; 101=6x; 110=7x; 111=8x */
+enum {
+	MAC_TX_CLK_0_MHZ	= 2,
+	MAC_TX_CLK_2_5_MHZ	= 6,
+	MAC_TX_CLK_25_MHZ 	= 7,
+};
+
+/*****  PHY_MARV_LED_CTRL	16 bit r/w	LED Control Reg *****/
+enum {
+	PHY_M_LEDC_DIS_LED	= 1<<15, /* Disable LED */
+	PHY_M_LEDC_PULS_MSK	= 7<<12,/* Bit 14..12: Pulse Stretch Mask */
+	PHY_M_LEDC_F_INT	= 1<<11, /* Force Interrupt */
+	PHY_M_LEDC_BL_R_MSK	= 7<<8,/* Bit 10.. 8: Blink Rate Mask */
+	PHY_M_LEDC_DP_C_LSB	= 1<<7, /* Duplex Control (LSB, 88E1111 only) */
+	PHY_M_LEDC_TX_C_LSB	= 1<<6, /* Tx Control (LSB, 88E1111 only) */
+	PHY_M_LEDC_LK_C_MSK	= 7<<3,/* Bit  5.. 3: Link Control Mask */
+					/* (88E1111 only) */
+};
+
+enum {
+	PHY_M_LEDC_LINK_MSK	= 3<<3,/* Bit  4.. 3: Link Control Mask */
+									/* (88E1011 only) */
+	PHY_M_LEDC_DP_CTRL	= 1<<2, /* Duplex Control */
+	PHY_M_LEDC_DP_C_MSB	= 1<<2, /* Duplex Control (MSB, 88E1111 only) */
+	PHY_M_LEDC_RX_CTRL	= 1<<1, /* Rx Activity / Link */
+	PHY_M_LEDC_TX_CTRL	= 1<<0, /* Tx Activity / Link */
+	PHY_M_LEDC_TX_C_MSB	= 1<<0, /* Tx Control (MSB, 88E1111 only) */
+};
+
+#define PHY_M_LED_PULS_DUR(x)	(	((x)<<12) & PHY_M_LEDC_PULS_MSK)
+
+enum {
+	PULS_NO_STR	= 0,/* no pulse stretching */
+	PULS_21MS	= 1,/* 21 ms to 42 ms */
+	PULS_42MS	= 2,/* 42 ms to 84 ms */
+	PULS_84MS	= 3,/* 84 ms to 170 ms */
+	PULS_170MS	= 4,/* 170 ms to 340 ms */
+	PULS_340MS	= 5,/* 340 ms to 670 ms */
+	PULS_670MS	= 6,/* 670 ms to 1.3 s */
+	PULS_1300MS	= 7,/* 1.3 s to 2.7 s */
+};
+
+#define PHY_M_LED_BLINK_RT(x)	(	((x)<<8) & PHY_M_LEDC_BL_R_MSK)
+
+enum {
+	BLINK_42MS	= 0,/* 42 ms */
+	BLINK_84MS	= 1,/* 84 ms */
+	BLINK_170MS	= 2,/* 170 ms */
+	BLINK_340MS	= 3,/* 340 ms */
+	BLINK_670MS	= 4,/* 670 ms */
+};
+
+/*****  PHY_MARV_LED_OVER	16 bit r/w	Manual LED Override Reg *****/
+#define PHY_M_LED_MO_SGMII(x)	((x)<<14) /* Bit 15..14:  SGMII AN Timer */
+										/* Bit 13..12:	reserved */
+#define PHY_M_LED_MO_DUP(x)	((x)<<10) /* Bit 11..10:  Duplex */
+#define PHY_M_LED_MO_10(x)	((x)<<8) /* Bit  9.. 8:  Link 10 */
+#define PHY_M_LED_MO_100(x)	((x)<<6) /* Bit  7.. 6:  Link 100 */
+#define PHY_M_LED_MO_1000(x)	((x)<<4) /* Bit  5.. 4:  Link 1000 */
+#define PHY_M_LED_MO_RX(x)	((x)<<2) /* Bit  3.. 2:  Rx */
+#define PHY_M_LED_MO_TX(x)	((x)<<0) /* Bit  1.. 0:  Tx */
+
+enum {
+	MO_LED_NORM	= 0,
+	MO_LED_BLINK	= 1,
+	MO_LED_OFF	= 2,
+	MO_LED_ON	= 3,
+};
+
+/*****  PHY_MARV_EXT_CTRL_2	16 bit r/w	Ext. PHY Specific Ctrl 2 *****/
+enum {
+	PHY_M_EC2_FI_IMPED	= 1<<6, /* Fiber Input  Impedance */
+	PHY_M_EC2_FO_IMPED	= 1<<5, /* Fiber Output Impedance */
+	PHY_M_EC2_FO_M_CLK	= 1<<4, /* Fiber Mode Clock Enable */
+	PHY_M_EC2_FO_BOOST	= 1<<3, /* Fiber Output Boost */
+	PHY_M_EC2_FO_AM_MSK	= 7,/* Bit  2.. 0:	Fiber Output Amplitude */
+};
+
+/*****  PHY_MARV_EXT_P_STAT 16 bit r/w	Ext. PHY Specific Status *****/
+enum {
+	PHY_M_FC_AUTO_SEL	= 1<<15, /* Fiber/Copper Auto Sel. Dis. */
+	PHY_M_FC_AN_REG_ACC	= 1<<14, /* Fiber/Copper AN Reg. Access */
+	PHY_M_FC_RESOLUTION	= 1<<13, /* Fiber/Copper Resolution */
+	PHY_M_SER_IF_AN_BP	= 1<<12, /* Ser. IF AN Bypass Enable */
+	PHY_M_SER_IF_BP_ST	= 1<<11, /* Ser. IF AN Bypass Status */
+	PHY_M_IRQ_POLARITY	= 1<<10, /* IRQ polarity */
+	PHY_M_DIS_AUT_MED	= 1<<9, /* Disable Aut. Medium Reg. Selection */
+									/* (88E1111 only) */
+								/* Bit  9.. 4: reserved (88E1011 only) */
+	PHY_M_UNDOC1	= 1<<7, /* undocumented bit !! */
+	PHY_M_DTE_POW_STAT	= 1<<4, /* DTE Power Status (88E1111 only) */
+	PHY_M_MODE_MASK	= 0xf, /* Bit  3.. 0: copy of HWCFG MODE[3:0] */
+};
+
+/*****  PHY_MARV_CABLE_DIAG	16 bit r/o	Cable Diagnostic Reg *****/
+enum {
+	PHY_M_CABD_ENA_TEST	= 1<<15, /* Enable Test (Page 0) */
+	PHY_M_CABD_DIS_WAIT	= 1<<15, /* Disable Waiting Period (Page 1) */
+					/* (88E1111 only) */
+	PHY_M_CABD_STAT_MSK	= 3<<13, /* Bit 14..13: Status Mask */
+	PHY_M_CABD_AMPL_MSK	= 0x1f<<8,/* Bit 12.. 8: Amplitude Mask */
+					/* (88E1111 only) */
+	PHY_M_CABD_DIST_MSK	= 0xff, /* Bit  7.. 0: Distance Mask */
+};
+
+/* values for Cable Diagnostic Status (11=fail; 00=OK; 10=open; 01=short) */
+enum {
+	CABD_STAT_NORMAL= 0,
+	CABD_STAT_SHORT	= 1,
+	CABD_STAT_OPEN	= 2,
+	CABD_STAT_FAIL	= 3,
+};
+
+/* for 10/100 Fast Ethernet PHY (88E3082 only) */
+/*****  PHY_MARV_FE_LED_PAR		16 bit r/w	LED Parallel Select Reg. *****/
+									/* Bit 15..12: reserved (used internally) */
+enum {
+	PHY_M_FELP_LED2_MSK = 0xf<<8,	/* Bit 11.. 8: LED2 Mask (LINK) */
+	PHY_M_FELP_LED1_MSK = 0xf<<4,	/* Bit  7.. 4: LED1 Mask (ACT) */
+	PHY_M_FELP_LED0_MSK = 0xf, /* Bit  3.. 0: LED0 Mask (SPEED) */
+};
+
+#define PHY_M_FELP_LED2_CTRL(x)	(	((x)<<8) & PHY_M_FELP_LED2_MSK)
+#define PHY_M_FELP_LED1_CTRL(x)	(	((x)<<4) & PHY_M_FELP_LED1_MSK)
+#define PHY_M_FELP_LED0_CTRL(x)	(	((x)<<0) & PHY_M_FELP_LED0_MSK)
+
+enum {
+	LED_PAR_CTRL_COLX	= 0x00,
+	LED_PAR_CTRL_ERROR	= 0x01,
+	LED_PAR_CTRL_DUPLEX	= 0x02,
+	LED_PAR_CTRL_DP_COL	= 0x03,
+	LED_PAR_CTRL_SPEED	= 0x04,
+	LED_PAR_CTRL_LINK	= 0x05,
+	LED_PAR_CTRL_TX		= 0x06,
+	LED_PAR_CTRL_RX		= 0x07,
+	LED_PAR_CTRL_ACT	= 0x08,
+	LED_PAR_CTRL_LNK_RX	= 0x09,
+	LED_PAR_CTRL_LNK_AC	= 0x0a,
+	LED_PAR_CTRL_ACT_BL	= 0x0b,
+	LED_PAR_CTRL_TX_BL	= 0x0c,
+	LED_PAR_CTRL_RX_BL	= 0x0d,
+	LED_PAR_CTRL_COL_BL	= 0x0e,
+	LED_PAR_CTRL_INACT	= 0x0f
+};
+
+/*****,PHY_MARV_FE_SPEC_2		16 bit r/w	Specific Control Reg. 2 *****/
+enum {
+	PHY_M_FESC_DIS_WAIT	= 1<<2, /* Disable TDR Waiting Period */
+	PHY_M_FESC_ENA_MCLK	= 1<<1, /* Enable MAC Rx Clock in sleep mode */
+	PHY_M_FESC_SEL_CL_A	= 1<<0, /* Select Class A driver (100B-TX) */
+};
+
+/* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */
+/*****  PHY_MARV_PHY_CTRL (page 2)		16 bit r/w	MAC Specific Ctrl *****/
+enum {
+	PHY_M_MAC_MD_MSK	= 7<<7, /* Bit  9.. 7: Mode Select Mask */
+	PHY_M_MAC_MD_AUTO	= 3,/* Auto Copper/1000Base-X */
+	PHY_M_MAC_MD_COPPER	= 5,/* Copper only */
+	PHY_M_MAC_MD_1000BX	= 7,/* 1000Base-X only */
+};
+#define PHY_M_MAC_MODE_SEL(x)	(	((x)<<7) & PHY_M_MAC_MD_MSK)
+
+/*****  PHY_MARV_PHY_CTRL (page 3)		16 bit r/w	LED Control Reg. *****/
+enum {
+	PHY_M_LEDC_LOS_MSK	= 0xf<<12,/* Bit 15..12: LOS LED Ctrl. Mask */
+	PHY_M_LEDC_INIT_MSK	= 0xf<<8, /* Bit 11.. 8: INIT LED Ctrl. Mask */
+	PHY_M_LEDC_STA1_MSK	= 0xf<<4,/* Bit  7.. 4: STAT1 LED Ctrl. Mask */
+	PHY_M_LEDC_STA0_MSK	= 0xf, /* Bit  3.. 0: STAT0 LED Ctrl. Mask */
+};
+
+#define PHY_M_LEDC_LOS_CTRL(x)	(	((x)<<12) & PHY_M_LEDC_LOS_MSK)
+#define PHY_M_LEDC_INIT_CTRL(x)	(	((x)<<8) & PHY_M_LEDC_INIT_MSK)
+#define PHY_M_LEDC_STA1_CTRL(x)	(	((x)<<4) & PHY_M_LEDC_STA1_MSK)
+#define PHY_M_LEDC_STA0_CTRL(x)	(	((x)<<0) & PHY_M_LEDC_STA0_MSK)
+
+/* GMAC registers  */
+/* Port Registers */
+enum {
+	GM_GP_STAT	= 0x0000,	/* 16 bit r/o	General Purpose Status */
+	GM_GP_CTRL	= 0x0004,	/* 16 bit r/w	General Purpose Control */
+	GM_TX_CTRL	= 0x0008,	/* 16 bit r/w	Transmit Control Reg. */
+	GM_RX_CTRL	= 0x000c,	/* 16 bit r/w	Receive Control Reg. */
+	GM_TX_FLOW_CTRL	= 0x0010,	/* 16 bit r/w	Transmit Flow-Control */
+	GM_TX_PARAM	= 0x0014,	/* 16 bit r/w	Transmit Parameter Reg. */
+	GM_SERIAL_MODE	= 0x0018,	/* 16 bit r/w	Serial Mode Register */
+/* Source Address Registers */
+	GM_SRC_ADDR_1L	= 0x001c,	/* 16 bit r/w	Source Address 1 (low) */
+	GM_SRC_ADDR_1M	= 0x0020,	/* 16 bit r/w	Source Address 1 (middle) */
+	GM_SRC_ADDR_1H	= 0x0024,	/* 16 bit r/w	Source Address 1 (high) */
+	GM_SRC_ADDR_2L	= 0x0028,	/* 16 bit r/w	Source Address 2 (low) */
+	GM_SRC_ADDR_2M	= 0x002c,	/* 16 bit r/w	Source Address 2 (middle) */
+	GM_SRC_ADDR_2H	= 0x0030,	/* 16 bit r/w	Source Address 2 (high) */
+
+/* Multicast Address Hash Registers */
+	GM_MC_ADDR_H1	= 0x0034,	/* 16 bit r/w	Multicast Address Hash 1 */
+	GM_MC_ADDR_H2	= 0x0038,	/* 16 bit r/w	Multicast Address Hash 2 */
+	GM_MC_ADDR_H3	= 0x003c,	/* 16 bit r/w	Multicast Address Hash 3 */
+	GM_MC_ADDR_H4	= 0x0040,	/* 16 bit r/w	Multicast Address Hash 4 */
+
+/* Interrupt Source Registers */
+	GM_TX_IRQ_SRC	= 0x0044,	/* 16 bit r/o	Tx Overflow IRQ Source */
+	GM_RX_IRQ_SRC	= 0x0048,	/* 16 bit r/o	Rx Overflow IRQ Source */
+	GM_TR_IRQ_SRC	= 0x004c,	/* 16 bit r/o	Tx/Rx Over. IRQ Source */
+
+/* Interrupt Mask Registers */
+	GM_TX_IRQ_MSK	= 0x0050,	/* 16 bit r/w	Tx Overflow IRQ Mask */
+	GM_RX_IRQ_MSK	= 0x0054,	/* 16 bit r/w	Rx Overflow IRQ Mask */
+	GM_TR_IRQ_MSK	= 0x0058,	/* 16 bit r/w	Tx/Rx Over. IRQ Mask */
+
+/* Serial Management Interface (SMI) Registers */
+	GM_SMI_CTRL	= 0x0080,	/* 16 bit r/w	SMI Control Register */
+	GM_SMI_DATA	= 0x0084,	/* 16 bit r/w	SMI Data Register */
+	GM_PHY_ADDR	= 0x0088,	/* 16 bit r/w	GPHY Address Register */
+};
+
+/* MIB Counters */
+#define GM_MIB_CNT_BASE	0x0100		/* Base Address of MIB Counters */
+#define GM_MIB_CNT_SIZE	44		/* Number of MIB Counters */
+
+/*
+ * MIB Counters base address definitions (low word) -
+ * use offset 4 for access to high word	(32 bit r/o)
+ */
+enum {
+	GM_RXF_UC_OK  = GM_MIB_CNT_BASE + 0,	/* Unicast Frames Received OK */
+	GM_RXF_BC_OK	= GM_MIB_CNT_BASE + 8,	/* Broadcast Frames Received OK */
+	GM_RXF_MPAUSE	= GM_MIB_CNT_BASE + 16,	/* Pause MAC Ctrl Frames Received */
+	GM_RXF_MC_OK	= GM_MIB_CNT_BASE + 24,	/* Multicast Frames Received OK */
+	GM_RXF_FCS_ERR	= GM_MIB_CNT_BASE + 32,	/* Rx Frame Check Seq. Error */
+	/* GM_MIB_CNT_BASE + 40:	reserved */
+	GM_RXO_OK_LO	= GM_MIB_CNT_BASE + 48,	/* Octets Received OK Low */
+	GM_RXO_OK_HI	= GM_MIB_CNT_BASE + 56,	/* Octets Received OK High */
+	GM_RXO_ERR_LO	= GM_MIB_CNT_BASE + 64,	/* Octets Received Invalid Low */
+	GM_RXO_ERR_HI	= GM_MIB_CNT_BASE + 72,	/* Octets Received Invalid High */
+	GM_RXF_SHT	= GM_MIB_CNT_BASE + 80,	/* Frames <64 Byte Received OK */
+	GM_RXE_FRAG	= GM_MIB_CNT_BASE + 88,	/* Frames <64 Byte Received with FCS Err */
+	GM_RXF_64B	= GM_MIB_CNT_BASE + 96,	/* 64 Byte Rx Frame */
+	GM_RXF_127B	= GM_MIB_CNT_BASE + 104,	/* 65-127 Byte Rx Frame */
+	GM_RXF_255B	= GM_MIB_CNT_BASE + 112,	/* 128-255 Byte Rx Frame */
+	GM_RXF_511B	= GM_MIB_CNT_BASE + 120,	/* 256-511 Byte Rx Frame */
+	GM_RXF_1023B	= GM_MIB_CNT_BASE + 128,	/* 512-1023 Byte Rx Frame */
+	GM_RXF_1518B	= GM_MIB_CNT_BASE + 136,	/* 1024-1518 Byte Rx Frame */
+	GM_RXF_MAX_SZ	= GM_MIB_CNT_BASE + 144,	/* 1519-MaxSize Byte Rx Frame */
+	GM_RXF_LNG_ERR	= GM_MIB_CNT_BASE + 152,	/* Rx Frame too Long Error */
+	GM_RXF_JAB_PKT	= GM_MIB_CNT_BASE + 160,	/* Rx Jabber Packet Frame */
+	/* GM_MIB_CNT_BASE + 168:	reserved */
+	GM_RXE_FIFO_OV	= GM_MIB_CNT_BASE + 176,	/* Rx FIFO overflow Event */
+	/* GM_MIB_CNT_BASE + 184:	reserved */
+	GM_TXF_UC_OK	= GM_MIB_CNT_BASE + 192,	/* Unicast Frames Xmitted OK */
+	GM_TXF_BC_OK	= GM_MIB_CNT_BASE + 200,	/* Broadcast Frames Xmitted OK */
+	GM_TXF_MPAUSE	= GM_MIB_CNT_BASE + 208,	/* Pause MAC Ctrl Frames Xmitted */
+	GM_TXF_MC_OK	= GM_MIB_CNT_BASE + 216,	/* Multicast Frames Xmitted OK */
+	GM_TXO_OK_LO	= GM_MIB_CNT_BASE + 224,	/* Octets Transmitted OK Low */
+	GM_TXO_OK_HI	= GM_MIB_CNT_BASE + 232,	/* Octets Transmitted OK High */
+	GM_TXF_64B	= GM_MIB_CNT_BASE + 240,	/* 64 Byte Tx Frame */
+	GM_TXF_127B	= GM_MIB_CNT_BASE + 248,	/* 65-127 Byte Tx Frame */
+	GM_TXF_255B	= GM_MIB_CNT_BASE + 256,	/* 128-255 Byte Tx Frame */
+	GM_TXF_511B	= GM_MIB_CNT_BASE + 264,	/* 256-511 Byte Tx Frame */
+	GM_TXF_1023B	= GM_MIB_CNT_BASE + 272,	/* 512-1023 Byte Tx Frame */
+	GM_TXF_1518B	= GM_MIB_CNT_BASE + 280,	/* 1024-1518 Byte Tx Frame */
+	GM_TXF_MAX_SZ	= GM_MIB_CNT_BASE + 288,	/* 1519-MaxSize Byte Tx Frame */
+
+	GM_TXF_COL	= GM_MIB_CNT_BASE + 304,	/* Tx Collision */
+	GM_TXF_LAT_COL	= GM_MIB_CNT_BASE + 312,	/* Tx Late Collision */
+	GM_TXF_ABO_COL	= GM_MIB_CNT_BASE + 320,	/* Tx aborted due to Exces. Col. */
+	GM_TXF_MUL_COL	= GM_MIB_CNT_BASE + 328,	/* Tx Multiple Collision */
+	GM_TXF_SNG_COL	= GM_MIB_CNT_BASE + 336,	/* Tx Single Collision */
+	GM_TXE_FIFO_UR	= GM_MIB_CNT_BASE + 344,	/* Tx FIFO Underrun Event */
+};
+
+/* GMAC Bit Definitions */
+/*	GM_GP_STAT	16 bit r/o	General Purpose Status Register */
+enum {
+	GM_GPSR_SPEED		= 1<<15, /* Bit 15:	Port Speed (1 = 100 Mbps) */
+	GM_GPSR_DUPLEX		= 1<<14, /* Bit 14:	Duplex Mode (1 = Full) */
+	GM_GPSR_FC_TX_DIS	= 1<<13, /* Bit 13:	Tx Flow-Control Mode Disabled */
+	GM_GPSR_LINK_UP		= 1<<12, /* Bit 12:	Link Up Status */
+	GM_GPSR_PAUSE		= 1<<11, /* Bit 11:	Pause State */
+	GM_GPSR_TX_ACTIVE	= 1<<10, /* Bit 10:	Tx in Progress */
+	GM_GPSR_EXC_COL		= 1<<9,	/* Bit  9:	Excessive Collisions Occured */
+	GM_GPSR_LAT_COL		= 1<<8,	/* Bit  8:	Late Collisions Occured */
+
+	GM_GPSR_PHY_ST_CH	= 1<<5,	/* Bit  5:	PHY Status Change */
+	GM_GPSR_GIG_SPEED	= 1<<4,	/* Bit  4:	Gigabit Speed (1 = 1000 Mbps) */
+	GM_GPSR_PART_MODE	= 1<<3,	/* Bit  3:	Partition mode */
+	GM_GPSR_FC_RX_DIS	= 1<<2,	/* Bit  2:	Rx Flow-Control Mode Disabled */
+	GM_GPSR_PROM_EN		= 1<<1,	/* Bit  1:	Promiscuous Mode Enabled */
+};
+	
+/*	GM_GP_CTRL	16 bit r/w	General Purpose Control Register */
+enum {
+	GM_GPCR_PROM_ENA	= 1<<14,	/* Bit 14:	Enable Promiscuous Mode */
+	GM_GPCR_FC_TX_DIS	= 1<<13, /* Bit 13:	Disable Tx Flow-Control Mode */
+	GM_GPCR_TX_ENA		= 1<<12, /* Bit 12:	Enable Transmit */
+	GM_GPCR_RX_ENA		= 1<<11, /* Bit 11:	Enable Receive */
+	GM_GPCR_BURST_ENA	= 1<<10, /* Bit 10:	Enable Burst Mode */
+	GM_GPCR_LOOP_ENA	= 1<<9,	/* Bit  9:	Enable MAC Loopback Mode */
+	GM_GPCR_PART_ENA	= 1<<8,	/* Bit  8:	Enable Partition Mode */
+	GM_GPCR_GIGS_ENA	= 1<<7,	/* Bit  7:	Gigabit Speed (1000 Mbps) */
+	GM_GPCR_FL_PASS		= 1<<6,	/* Bit  6:	Force Link Pass */
+	GM_GPCR_DUP_FULL	= 1<<5,	/* Bit  5:	Full Duplex Mode */
+	GM_GPCR_FC_RX_DIS	= 1<<4,	/* Bit  4:	Disable Rx Flow-Control Mode */
+	GM_GPCR_SPEED_100	= 1<<3,   /* Bit  3:	Port Speed 100 Mbps */
+	GM_GPCR_AU_DUP_DIS	= 1<<2,	/* Bit  2:	Disable Auto-Update Duplex */
+	GM_GPCR_AU_FCT_DIS	= 1<<1,	/* Bit  1:	Disable Auto-Update Flow-C. */
+	GM_GPCR_AU_SPD_DIS	= 1<<0,	/* Bit  0:	Disable Auto-Update Speed */
+};
+
+#define GM_GPCR_SPEED_1000	(GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100)
+#define GM_GPCR_AU_ALL_DIS	(GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS|GM_GPCR_AU_SPD_DIS)
+	
+/*	GM_TX_CTRL			16 bit r/w	Transmit Control Register */
+enum {
+	GM_TXCR_FORCE_JAM	= 1<<15, /* Bit 15:	Force Jam / Flow-Control */
+	GM_TXCR_CRC_DIS		= 1<<14, /* Bit 14:	Disable insertion of CRC */
+	GM_TXCR_PAD_DIS		= 1<<13, /* Bit 13:	Disable padding of packets */
+	GM_TXCR_COL_THR_MSK	= 1<<10, /* Bit 12..10:	Collision Threshold */
+};
+
+#define TX_COL_THR(x)		(((x)<<10) & GM_TXCR_COL_THR_MSK)
+#define TX_COL_DEF		0x04
+	
+/*	GM_RX_CTRL			16 bit r/w	Receive Control Register */
+enum {
+	GM_RXCR_UCF_ENA	= 1<<15, /* Bit 15:	Enable Unicast filtering */
+	GM_RXCR_MCF_ENA	= 1<<14, /* Bit 14:	Enable Multicast filtering */
+	GM_RXCR_CRC_DIS	= 1<<13, /* Bit 13:	Remove 4-byte CRC */
+	GM_RXCR_PASS_FC	= 1<<12, /* Bit 12:	Pass FC packets to FIFO */
+};
+	
+/*	GM_TX_PARAM		16 bit r/w	Transmit Parameter Register */
+enum {
+	GM_TXPA_JAMLEN_MSK	= 0x03<<14,	/* Bit 15..14:	Jam Length */
+	GM_TXPA_JAMIPG_MSK	= 0x1f<<9,	/* Bit 13..9:	Jam IPG */
+	GM_TXPA_JAMDAT_MSK	= 0x1f<<4,	/* Bit  8..4:	IPG Jam to Data */
+
+	TX_JAM_LEN_DEF		= 0x03,
+	TX_JAM_IPG_DEF		= 0x0b,
+	TX_IPG_JAM_DEF		= 0x1c,
+};
+
+#define TX_JAM_LEN_VAL(x)	(((x)<<14) & GM_TXPA_JAMLEN_MSK)
+#define TX_JAM_IPG_VAL(x)	(((x)<<9)  & GM_TXPA_JAMIPG_MSK)
+#define TX_IPG_JAM_DATA(x)	(((x)<<4)  & GM_TXPA_JAMDAT_MSK)
+
+
+/*	GM_SERIAL_MODE			16 bit r/w	Serial Mode Register */
+enum {
+	GM_SMOD_DATABL_MSK	= 0x1f<<11, /* Bit 15..11:	Data Blinder (r/o) */
+	GM_SMOD_LIMIT_4		= 1<<10, /* Bit 10:	4 consecutive Tx trials */
+	GM_SMOD_VLAN_ENA	= 1<<9,	/* Bit  9:	Enable VLAN  (Max. Frame Len) */
+	GM_SMOD_JUMBO_ENA	= 1<<8,	/* Bit  8:	Enable Jumbo (Max. Frame Len) */
+	 GM_SMOD_IPG_MSK	= 0x1f	/* Bit 4..0:	Inter-Packet Gap (IPG) */
+};
+	
+#define DATA_BLIND_VAL(x)	(((x)<<11) & GM_SMOD_DATABL_MSK)
+#define DATA_BLIND_DEF		0x04
+
+#define IPG_DATA_VAL(x)		(x & GM_SMOD_IPG_MSK)
+#define IPG_DATA_DEF		0x1e
+
+/*	GM_SMI_CTRL			16 bit r/w	SMI Control Register */
+enum {
+	GM_SMI_CT_PHY_A_MSK	= 0x1f<<11,/* Bit 15..11:	PHY Device Address */
+	GM_SMI_CT_REG_A_MSK	= 0x1f<<6,/* Bit 10.. 6:	PHY Register Address */
+	GM_SMI_CT_OP_RD		= 1<<5,	/* Bit  5:	OpCode Read (0=Write)*/
+	GM_SMI_CT_RD_VAL	= 1<<4,	/* Bit  4:	Read Valid (Read completed) */
+	GM_SMI_CT_BUSY		= 1<<3,	/* Bit  3:	Busy (Operation in progress) */
+};
+	
+#define GM_SMI_CT_PHY_AD(x)	(((x)<<11) & GM_SMI_CT_PHY_A_MSK)
+#define GM_SMI_CT_REG_AD(x)	(((x)<<6) & GM_SMI_CT_REG_A_MSK)
+
+/*	GM_PHY_ADDR				16 bit r/w	GPHY Address Register */
+enum {
+	GM_PAR_MIB_CLR	= 1<<5,	/* Bit  5:	Set MIB Clear Counter Mode */
+	GM_PAR_MIB_TST	= 1<<4,	/* Bit  4:	MIB Load Counter (Test Mode) */
+};
+	
+/* Receive Frame Status Encoding */
+enum {
+	GMR_FS_LEN	= 0xffff<<16, /* Bit 31..16:	Rx Frame Length */
+	GMR_FS_VLAN	= 1<<13, /* Bit 13:	VLAN Packet */
+	GMR_FS_JABBER	= 1<<12, /* Bit 12:	Jabber Packet */
+	GMR_FS_UN_SIZE	= 1<<11, /* Bit 11:	Undersize Packet */
+	GMR_FS_MC	= 1<<10, /* Bit 10:	Multicast Packet */
+	GMR_FS_BC	= 1<<9, /* Bit  9:	Broadcast Packet */
+	GMR_FS_RX_OK	= 1<<8, /* Bit  8:	Receive OK (Good Packet) */
+	GMR_FS_GOOD_FC	= 1<<7, /* Bit  7:	Good Flow-Control Packet */
+	GMR_FS_BAD_FC	= 1<<6, /* Bit  6:	Bad  Flow-Control Packet */
+	GMR_FS_MII_ERR	= 1<<5, /* Bit  5:	MII Error */
+	GMR_FS_LONG_ERR	= 1<<4, /* Bit  4:	Too Long Packet */
+	GMR_FS_FRAGMENT	= 1<<3, /* Bit  3:	Fragment */
+
+	GMR_FS_CRC_ERR	= 1<<1, /* Bit  1:	CRC Error */
+	GMR_FS_RX_FF_OV	= 1<<0, /* Bit  0:	Rx FIFO Overflow */
+
+/*
+ * GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR)
+ */
+	GMR_FS_ANY_ERR	= GMR_FS_CRC_ERR | GMR_FS_LONG_ERR | 
+		  	  GMR_FS_MII_ERR | GMR_FS_BAD_FC | GMR_FS_GOOD_FC | 
+			  GMR_FS_JABBER,
+/* Rx GMAC FIFO Flush Mask (default) */
+	RX_FF_FL_DEF_MSK = GMR_FS_CRC_ERR | GMR_FS_RX_FF_OV |GMR_FS_MII_ERR |
+			   GMR_FS_BAD_FC | GMR_FS_GOOD_FC | GMR_FS_UN_SIZE | 
+			   GMR_FS_JABBER,
+};
+
+/*	RX_GMF_CTRL_T	32 bit	Rx GMAC FIFO Control/Test */
+enum {
+	GMF_WP_TST_ON	= 1<<14,	/* Write Pointer Test On */
+	GMF_WP_TST_OFF	= 1<<13,	/* Write Pointer Test Off */
+	GMF_WP_STEP	= 1<<12,	/* Write Pointer Step/Increment */
+
+	GMF_RP_TST_ON	= 1<<10,	/* Read Pointer Test On */
+	GMF_RP_TST_OFF	= 1<<9,		/* Read Pointer Test Off */
+	GMF_RP_STEP	= 1<<8,		/* Read Pointer Step/Increment */
+	GMF_RX_F_FL_ON	= 1<<7,		/* Rx FIFO Flush Mode On */
+	GMF_RX_F_FL_OFF	= 1<<6,		/* Rx FIFO Flush Mode Off */
+	GMF_CLI_RX_FO	= 1<<5,		/* Clear IRQ Rx FIFO Overrun */
+	GMF_CLI_RX_FC	= 1<<4,		/* Clear IRQ Rx Frame Complete */
+	GMF_OPER_ON	= 1<<3,		/* Operational Mode On */
+	GMF_OPER_OFF	= 1<<2,		/* Operational Mode Off */
+	GMF_RST_CLR	= 1<<1,		/* Clear GMAC FIFO Reset */
+	GMF_RST_SET	= 1<<0,		/* Set   GMAC FIFO Reset */
+
+	RX_GMF_FL_THR_DEF = 0xa,	/* flush threshold (default) */
+};
+
+
+/*	TX_GMF_CTRL_T	32 bit	Tx GMAC FIFO Control/Test */
+enum {
+	GMF_WSP_TST_ON	= 1<<18,/* Write Shadow Pointer Test On */
+	GMF_WSP_TST_OFF	= 1<<17,/* Write Shadow Pointer Test Off */
+	GMF_WSP_STEP	= 1<<16,/* Write Shadow Pointer Step/Increment */
+
+	GMF_CLI_TX_FU	= 1<<6,	/* Clear IRQ Tx FIFO Underrun */
+	GMF_CLI_TX_FC	= 1<<5,	/* Clear IRQ Tx Frame Complete */
+	GMF_CLI_TX_PE	= 1<<4,	/* Clear IRQ Tx Parity Error */
+};
+
+/*	GMAC_TI_ST_CTRL	 8 bit	Time Stamp Timer Ctrl Reg (YUKON only) */
+enum {
+	GMT_ST_START	= 1<<2,	/* Start Time Stamp Timer */
+	GMT_ST_STOP	= 1<<1,	/* Stop  Time Stamp Timer */
+	GMT_ST_CLR_IRQ	= 1<<0,	/* Clear Time Stamp Timer IRQ */
+};
+
+/*	GMAC_CTRL		32 bit	GMAC Control Reg (YUKON only) */
+enum {
+	GMC_H_BURST_ON	= 1<<7,	/* Half Duplex Burst Mode On */
+	GMC_H_BURST_OFF	= 1<<6,	/* Half Duplex Burst Mode Off */
+	GMC_F_LOOPB_ON	= 1<<5,	/* FIFO Loopback On */
+	GMC_F_LOOPB_OFF	= 1<<4,	/* FIFO Loopback Off */
+	GMC_PAUSE_ON	= 1<<3,	/* Pause On */
+	GMC_PAUSE_OFF	= 1<<2,	/* Pause Off */
+	GMC_RST_CLR	= 1<<1,	/* Clear GMAC Reset */
+	GMC_RST_SET	= 1<<0,	/* Set   GMAC Reset */
+};
+
+/*	GPHY_CTRL		32 bit	GPHY Control Reg (YUKON only) */
+enum {
+	GPC_SEL_BDT	= 1<<28, /* Select Bi-Dir. Transfer for MDC/MDIO */
+	GPC_INT_POL_HI	= 1<<27, /* IRQ Polarity is Active HIGH */
+	GPC_75_OHM	= 1<<26, /* Use 75 Ohm Termination instead of 50 */
+	GPC_DIS_FC	= 1<<25, /* Disable Automatic Fiber/Copper Detection */
+	GPC_DIS_SLEEP	= 1<<24, /* Disable Energy Detect */
+	GPC_HWCFG_M_3	= 1<<23, /* HWCFG_MODE[3] */
+	GPC_HWCFG_M_2	= 1<<22, /* HWCFG_MODE[2] */
+	GPC_HWCFG_M_1	= 1<<21, /* HWCFG_MODE[1] */
+	GPC_HWCFG_M_0	= 1<<20, /* HWCFG_MODE[0] */
+	GPC_ANEG_0	= 1<<19, /* ANEG[0] */
+	GPC_ENA_XC	= 1<<18, /* Enable MDI crossover */
+	GPC_DIS_125	= 1<<17, /* Disable 125 MHz clock */
+	GPC_ANEG_3	= 1<<16, /* ANEG[3] */
+	GPC_ANEG_2	= 1<<15, /* ANEG[2] */
+	GPC_ANEG_1	= 1<<14, /* ANEG[1] */
+	GPC_ENA_PAUSE	= 1<<13, /* Enable Pause (SYM_OR_REM) */
+	GPC_PHYADDR_4	= 1<<12, /* Bit 4 of Phy Addr */
+	GPC_PHYADDR_3	= 1<<11, /* Bit 3 of Phy Addr */
+	GPC_PHYADDR_2	= 1<<10, /* Bit 2 of Phy Addr */
+	GPC_PHYADDR_1	= 1<<9,	 /* Bit 1 of Phy Addr */
+	GPC_PHYADDR_0	= 1<<8,	 /* Bit 0 of Phy Addr */
+						/* Bits  7..2:	reserved */
+	GPC_RST_CLR	= 1<<1,	/* Clear GPHY Reset */
+	GPC_RST_SET	= 1<<0,	/* Set   GPHY Reset */
+};
+
+#define GPC_HWCFG_GMII_COP (GPC_HWCFG_M_3|GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0)
+#define GPC_HWCFG_GMII_FIB (GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0)
+#define GPC_ANEG_ADV_ALL_M  (GPC_ANEG_3 | GPC_ANEG_2 | GPC_ANEG_1 | GPC_ANEG_0)
+
+/* forced speed and duplex mode (don't mix with other ANEG bits) */
+#define GPC_FRC10MBIT_HALF	0
+#define GPC_FRC10MBIT_FULL	GPC_ANEG_0
+#define GPC_FRC100MBIT_HALF	GPC_ANEG_1
+#define GPC_FRC100MBIT_FULL	(GPC_ANEG_0 | GPC_ANEG_1)
+
+/* auto-negotiation with limited advertised speeds */
+/* mix only with master/slave settings (for copper) */
+#define GPC_ADV_1000_HALF	GPC_ANEG_2
+#define GPC_ADV_1000_FULL	GPC_ANEG_3
+#define GPC_ADV_ALL		(GPC_ANEG_2 | GPC_ANEG_3)
+
+/* master/slave settings */
+/* only for copper with 1000 Mbps */
+#define GPC_FORCE_MASTER	0
+#define GPC_FORCE_SLAVE		GPC_ANEG_0
+#define GPC_PREF_MASTER		GPC_ANEG_1
+#define GPC_PREF_SLAVE		(GPC_ANEG_1 | GPC_ANEG_0)
+
+/*	GMAC_IRQ_SRC	 8 bit	GMAC Interrupt Source Reg (YUKON only) */
+/*	GMAC_IRQ_MSK	 8 bit	GMAC Interrupt Mask   Reg (YUKON only) */
+enum {
+	GM_IS_TX_CO_OV	= 1<<5,	/* Transmit Counter Overflow IRQ */
+	GM_IS_RX_CO_OV	= 1<<4,	/* Receive Counter Overflow IRQ */
+	GM_IS_TX_FF_UR	= 1<<3,	/* Transmit FIFO Underrun */
+	GM_IS_TX_COMPL	= 1<<2,	/* Frame Transmission Complete */
+	GM_IS_RX_FF_OR	= 1<<1,	/* Receive FIFO Overrun */
+	GM_IS_RX_COMPL	= 1<<0,	/* Frame Reception Complete */
+
+#define GMAC_DEF_MSK	(GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | GM_IS_TX_FF_UR)
+
+/*	GMAC_LINK_CTRL	16 bit	GMAC Link Control Reg (YUKON only) */
+						/* Bits 15.. 2:	reserved */
+	GMLC_RST_CLR	= 1<<1,	/* Clear GMAC Link Reset */
+	GMLC_RST_SET	= 1<<0,	/* Set   GMAC Link Reset */
+
+
+/*	WOL_CTRL_STAT	16 bit	WOL Control/Status Reg */
+	WOL_CTL_LINK_CHG_OCC		= 1<<15,
+	WOL_CTL_MAGIC_PKT_OCC		= 1<<14,
+	WOL_CTL_PATTERN_OCC		= 1<<13,
+	WOL_CTL_CLEAR_RESULT		= 1<<12,
+	WOL_CTL_ENA_PME_ON_LINK_CHG	= 1<<11,
+	WOL_CTL_DIS_PME_ON_LINK_CHG	= 1<<10,
+	WOL_CTL_ENA_PME_ON_MAGIC_PKT	= 1<<9,
+	WOL_CTL_DIS_PME_ON_MAGIC_PKT	= 1<<8,
+	WOL_CTL_ENA_PME_ON_PATTERN	= 1<<7,
+	WOL_CTL_DIS_PME_ON_PATTERN	= 1<<6,
+	WOL_CTL_ENA_LINK_CHG_UNIT	= 1<<5,
+	WOL_CTL_DIS_LINK_CHG_UNIT	= 1<<4,
+	WOL_CTL_ENA_MAGIC_PKT_UNIT	= 1<<3,
+	WOL_CTL_DIS_MAGIC_PKT_UNIT	= 1<<2,
+	WOL_CTL_ENA_PATTERN_UNIT	= 1<<1,
+	WOL_CTL_DIS_PATTERN_UNIT	= 1<<0,
+};
+
+#define WOL_CTL_DEFAULT				\
+	(WOL_CTL_DIS_PME_ON_LINK_CHG |	\
+	WOL_CTL_DIS_PME_ON_PATTERN |	\
+	WOL_CTL_DIS_PME_ON_MAGIC_PKT |	\
+	WOL_CTL_DIS_LINK_CHG_UNIT |		\
+	WOL_CTL_DIS_PATTERN_UNIT |		\
+	WOL_CTL_DIS_MAGIC_PKT_UNIT)
+
+/*	WOL_MATCH_CTL	 8 bit	WOL Match Control Reg */
+#define WOL_CTL_PATT_ENA(x)	(1 << (x))
+
+
+/* XMAC II registers				      */
+enum {
+	XM_MMU_CMD	= 0x0000, /* 16 bit r/w	MMU Command Register */
+	XM_POFF		= 0x0008, /* 32 bit r/w	Packet Offset Register */
+	XM_BURST	= 0x000c, /* 32 bit r/w	Burst Register for half duplex*/
+	XM_1L_VLAN_TAG	= 0x0010, /* 16 bit r/w	One Level VLAN Tag ID */
+	XM_2L_VLAN_TAG	= 0x0014, /* 16 bit r/w	Two Level VLAN Tag ID */
+	XM_TX_CMD	= 0x0020, /* 16 bit r/w	Transmit Command Register */
+	XM_TX_RT_LIM	= 0x0024, /* 16 bit r/w	Transmit Retry Limit Register */
+	XM_TX_STIME	= 0x0028, /* 16 bit r/w	Transmit Slottime Register */
+	XM_TX_IPG	= 0x002c, /* 16 bit r/w	Transmit Inter Packet Gap */
+	XM_RX_CMD	= 0x0030, /* 16 bit r/w	Receive Command Register */
+	XM_PHY_ADDR	= 0x0034, /* 16 bit r/w	PHY Address Register */
+	XM_PHY_DATA	= 0x0038, /* 16 bit r/w	PHY Data Register */
+	XM_GP_PORT	= 0x0040, /* 32 bit r/w	General Purpose Port Register */
+	XM_IMSK		= 0x0044, /* 16 bit r/w	Interrupt Mask Register */
+	XM_ISRC		= 0x0048, /* 16 bit r/o	Interrupt Status Register */
+	XM_HW_CFG	= 0x004c, /* 16 bit r/w	Hardware Config Register */
+	XM_TX_LO_WM	= 0x0060, /* 16 bit r/w	Tx FIFO Low Water Mark */
+	XM_TX_HI_WM	= 0x0062, /* 16 bit r/w	Tx FIFO High Water Mark */
+	XM_TX_THR	= 0x0064, /* 16 bit r/w	Tx Request Threshold */
+	XM_HT_THR	= 0x0066, /* 16 bit r/w	Host Request Threshold */
+	XM_PAUSE_DA	= 0x0068, /* NA reg r/w	Pause Destination Address */
+	XM_CTL_PARA	= 0x0070, /* 32 bit r/w	Control Parameter Register */
+	XM_MAC_OPCODE	= 0x0074, /* 16 bit r/w	Opcode for MAC control frames */
+	XM_MAC_PTIME	= 0x0076, /* 16 bit r/w	Pause time for MAC ctrl frames*/
+	XM_TX_STAT	= 0x0078, /* 32 bit r/o	Tx Status LIFO Register */
+
+	XM_EXM_START	= 0x0080, /* r/w	Start Address of the EXM Regs */
+#define XM_EXM(reg)	(XM_EXM_START + ((reg) << 3))
+};
+
+enum {
+	XM_SRC_CHK	= 0x0100, /* NA reg r/w	Source Check Address Register */
+	XM_SA		= 0x0108, /* NA reg r/w	Station Address Register */
+	XM_HSM		= 0x0110, /* 64 bit r/w	Hash Match Address Registers */
+	XM_RX_LO_WM	= 0x0118, /* 16 bit r/w	Receive Low Water Mark */
+	XM_RX_HI_WM	= 0x011a, /* 16 bit r/w	Receive High Water Mark */
+	XM_RX_THR	= 0x011c, /* 32 bit r/w	Receive Request Threshold */
+	XM_DEV_ID	= 0x0120, /* 32 bit r/o	Device ID Register */
+	XM_MODE		= 0x0124, /* 32 bit r/w	Mode Register */
+	XM_LSA		= 0x0128, /* NA reg r/o	Last Source Register */
+	XM_TS_READ	= 0x0130, /* 32 bit r/o	Time Stamp Read Register */
+	XM_TS_LOAD	= 0x0134, /* 32 bit r/o	Time Stamp Load Value */
+	XM_STAT_CMD	= 0x0200, /* 16 bit r/w	Statistics Command Register */
+	XM_RX_CNT_EV	= 0x0204, /* 32 bit r/o	Rx Counter Event Register */
+	XM_TX_CNT_EV	= 0x0208, /* 32 bit r/o	Tx Counter Event Register */
+	XM_RX_EV_MSK	= 0x020c, /* 32 bit r/w	Rx Counter Event Mask */
+	XM_TX_EV_MSK	= 0x0210, /* 32 bit r/w	Tx Counter Event Mask */
+	XM_TXF_OK	= 0x0280, /* 32 bit r/o	Frames Transmitted OK Conuter */
+	XM_TXO_OK_HI	= 0x0284, /* 32 bit r/o	Octets Transmitted OK High Cnt*/
+	XM_TXO_OK_LO	= 0x0288, /* 32 bit r/o	Octets Transmitted OK Low Cnt */
+	XM_TXF_BC_OK	= 0x028c, /* 32 bit r/o	Broadcast Frames Xmitted OK */
+	XM_TXF_MC_OK	= 0x0290, /* 32 bit r/o	Multicast Frames Xmitted OK */
+	XM_TXF_UC_OK	= 0x0294, /* 32 bit r/o	Unicast Frames Xmitted OK */
+	XM_TXF_LONG	= 0x0298, /* 32 bit r/o	Tx Long Frame Counter */
+	XM_TXE_BURST	= 0x029c, /* 32 bit r/o	Tx Burst Event Counter */
+	XM_TXF_MPAUSE	= 0x02a0, /* 32 bit r/o	Tx Pause MAC Ctrl Frame Cnt */
+	XM_TXF_MCTRL	= 0x02a4, /* 32 bit r/o	Tx MAC Ctrl Frame Counter */
+	XM_TXF_SNG_COL	= 0x02a8, /* 32 bit r/o	Tx Single Collision Counter */
+	XM_TXF_MUL_COL	= 0x02ac, /* 32 bit r/o	Tx Multiple Collision Counter */
+	XM_TXF_ABO_COL	= 0x02b0, /* 32 bit r/o	Tx aborted due to Exces. Col. */
+	XM_TXF_LAT_COL	= 0x02b4, /* 32 bit r/o	Tx Late Collision Counter */
+	XM_TXF_DEF	= 0x02b8, /* 32 bit r/o	Tx Deferred Frame Counter */
+	XM_TXF_EX_DEF	= 0x02bc, /* 32 bit r/o	Tx Excessive Deferall Counter */
+	XM_TXE_FIFO_UR	= 0x02c0, /* 32 bit r/o	Tx FIFO Underrun Event Cnt */
+	XM_TXE_CS_ERR	= 0x02c4, /* 32 bit r/o	Tx Carrier Sense Error Cnt */
+	XM_TXP_UTIL	= 0x02c8, /* 32 bit r/o	Tx Utilization in % */
+	XM_TXF_64B	= 0x02d0, /* 32 bit r/o	64 Byte Tx Frame Counter */
+	XM_TXF_127B	= 0x02d4, /* 32 bit r/o	65-127 Byte Tx Frame Counter */
+	XM_TXF_255B	= 0x02d8, /* 32 bit r/o	128-255 Byte Tx Frame Counter */
+	XM_TXF_511B	= 0x02dc, /* 32 bit r/o	256-511 Byte Tx Frame Counter */
+	XM_TXF_1023B	= 0x02e0, /* 32 bit r/o	512-1023 Byte Tx Frame Counter*/
+	XM_TXF_MAX_SZ	= 0x02e4, /* 32 bit r/o	1024-MaxSize Byte Tx Frame Cnt*/
+	XM_RXF_OK	= 0x0300, /* 32 bit r/o	Frames Received OK */
+	XM_RXO_OK_HI	= 0x0304, /* 32 bit r/o	Octets Received OK High Cnt */
+	XM_RXO_OK_LO	= 0x0308, /* 32 bit r/o	Octets Received OK Low Counter*/
+	XM_RXF_BC_OK	= 0x030c, /* 32 bit r/o	Broadcast Frames Received OK */
+	XM_RXF_MC_OK	= 0x0310, /* 32 bit r/o	Multicast Frames Received OK */
+	XM_RXF_UC_OK	= 0x0314, /* 32 bit r/o	Unicast Frames Received OK */
+	XM_RXF_MPAUSE	= 0x0318, /* 32 bit r/o	Rx Pause MAC Ctrl Frame Cnt */
+	XM_RXF_MCTRL	= 0x031c, /* 32 bit r/o	Rx MAC Ctrl Frame Counter */
+	XM_RXF_INV_MP	= 0x0320, /* 32 bit r/o	Rx invalid Pause Frame Cnt */
+	XM_RXF_INV_MOC	= 0x0324, /* 32 bit r/o	Rx Frames with inv. MAC Opcode*/
+	XM_RXE_BURST	= 0x0328, /* 32 bit r/o	Rx Burst Event Counter */
+	XM_RXE_FMISS	= 0x032c, /* 32 bit r/o	Rx Missed Frames Event Cnt */
+	XM_RXF_FRA_ERR	= 0x0330, /* 32 bit r/o	Rx Framing Error Counter */
+	XM_RXE_FIFO_OV	= 0x0334, /* 32 bit r/o	Rx FIFO overflow Event Cnt */
+	XM_RXF_JAB_PKT	= 0x0338, /* 32 bit r/o	Rx Jabber Packet Frame Cnt */
+	XM_RXE_CAR_ERR	= 0x033c, /* 32 bit r/o	Rx Carrier Event Error Cnt */
+	XM_RXF_LEN_ERR	= 0x0340, /* 32 bit r/o	Rx in Range Length Error */
+	XM_RXE_SYM_ERR	= 0x0344, /* 32 bit r/o	Rx Symbol Error Counter */
+	XM_RXE_SHT_ERR	= 0x0348, /* 32 bit r/o	Rx Short Event Error Cnt */
+	XM_RXE_RUNT	= 0x034c, /* 32 bit r/o	Rx Runt Event Counter */
+	XM_RXF_LNG_ERR	= 0x0350, /* 32 bit r/o	Rx Frame too Long Error Cnt */
+	XM_RXF_FCS_ERR	= 0x0354, /* 32 bit r/o	Rx Frame Check Seq. Error Cnt */
+	XM_RXF_CEX_ERR	= 0x035c, /* 32 bit r/o	Rx Carrier Ext Error Frame Cnt*/
+	XM_RXP_UTIL	= 0x0360, /* 32 bit r/o	Rx Utilization in % */
+	XM_RXF_64B	= 0x0368, /* 32 bit r/o	64 Byte Rx Frame Counter */
+	XM_RXF_127B	= 0x036c, /* 32 bit r/o	65-127 Byte Rx Frame Counter */
+	XM_RXF_255B	= 0x0370, /* 32 bit r/o	128-255 Byte Rx Frame Counter */
+	XM_RXF_511B	= 0x0374, /* 32 bit r/o	256-511 Byte Rx Frame Counter */
+	XM_RXF_1023B	= 0x0378, /* 32 bit r/o	512-1023 Byte Rx Frame Counter*/
+	XM_RXF_MAX_SZ	= 0x037c, /* 32 bit r/o	1024-MaxSize Byte Rx Frame Cnt*/
+};
+
+/*	XM_MMU_CMD	16 bit r/w	MMU Command Register */
+enum {
+	XM_MMU_PHY_RDY	= 1<<12,/* Bit 12:	PHY Read Ready */
+	XM_MMU_PHY_BUSY	= 1<<11,/* Bit 11:	PHY Busy */
+	XM_MMU_IGN_PF	= 1<<10,/* Bit 10:	Ignore Pause Frame */
+	XM_MMU_MAC_LB	= 1<<9,	/* Bit  9:	Enable MAC Loopback */
+	XM_MMU_FRC_COL	= 1<<7,	/* Bit  7:	Force Collision */
+	XM_MMU_SIM_COL	= 1<<6,	/* Bit  6:	Simulate Collision */
+	XM_MMU_NO_PRE	= 1<<5,	/* Bit  5:	No MDIO Preamble */
+	XM_MMU_GMII_FD	= 1<<4,	/* Bit  4:	GMII uses Full Duplex */
+	XM_MMU_RAT_CTRL	= 1<<3,	/* Bit  3:	Enable Rate Control */
+	XM_MMU_GMII_LOOP= 1<<2,	/* Bit  2:	PHY is in Loopback Mode */
+	XM_MMU_ENA_RX	= 1<<1,	/* Bit  1:	Enable Receiver */
+	XM_MMU_ENA_TX	= 1<<0,	/* Bit  0:	Enable Transmitter */
+};
+
+
+/*	XM_TX_CMD	16 bit r/w	Transmit Command Register */
+enum {
+	XM_TX_BK2BK	= 1<<6,	/* Bit  6:	Ignor Carrier Sense (Tx Bk2Bk)*/
+	XM_TX_ENC_BYP	= 1<<5,	/* Bit  5:	Set Encoder in Bypass Mode */
+	XM_TX_SAM_LINE	= 1<<4,	/* Bit  4: (sc)	Start utilization calculation */
+	XM_TX_NO_GIG_MD	= 1<<3,	/* Bit  3:	Disable Carrier Extension */
+	XM_TX_NO_PRE	= 1<<2,	/* Bit  2:	Disable Preamble Generation */
+	XM_TX_NO_CRC	= 1<<1,	/* Bit  1:	Disable CRC Generation */
+	XM_TX_AUTO_PAD	= 1<<0,	/* Bit  0:	Enable Automatic Padding */
+};
+
+/*	XM_TX_RT_LIM	16 bit r/w	Transmit Retry Limit Register */
+#define XM_RT_LIM_MSK	0x1f	/* Bit  4..0:	Tx Retry Limit */
+
+
+/*	XM_TX_STIME	16 bit r/w	Transmit Slottime Register */
+#define XM_STIME_MSK	0x7f	/* Bit  6..0:	Tx Slottime bits */
+
+
+/*	XM_TX_IPG	16 bit r/w	Transmit Inter Packet Gap */
+#define XM_IPG_MSK		0xff	/* Bit  7..0:	IPG value bits */
+
+
+/*	XM_RX_CMD	16 bit r/w	Receive Command Register */
+enum {
+	XM_RX_LENERR_OK	= 1<<8,	/* Bit  8	don't set Rx Err bit for */
+				/*		inrange error packets */
+	XM_RX_BIG_PK_OK	= 1<<7,	/* Bit  7	don't set Rx Err bit for */
+				/*		jumbo packets */
+	XM_RX_IPG_CAP	= 1<<6,	/* Bit  6	repl. type field with IPG */
+	XM_RX_TP_MD	= 1<<5,	/* Bit  5:	Enable transparent Mode */
+	XM_RX_STRIP_FCS	= 1<<4,	/* Bit  4:	Enable FCS Stripping */
+	XM_RX_SELF_RX	= 1<<3,	/* Bit  3: 	Enable Rx of own packets */
+	XM_RX_SAM_LINE	= 1<<2,	/* Bit  2: (sc)	Start utilization calculation */
+	XM_RX_STRIP_PAD	= 1<<1,	/* Bit  1:	Strip pad bytes of Rx frames */
+	XM_RX_DIS_CEXT	= 1<<0,	/* Bit  0:	Disable carrier ext. check */
+};
+
+
+/*	XM_PHY_ADDR	16 bit r/w	PHY Address Register */
+#define XM_PHY_ADDR_SZ	0x1f	/* Bit  4..0:	PHY Address bits */
+
+
+/*	XM_GP_PORT	32 bit r/w	General Purpose Port Register */
+enum {
+	XM_GP_ANIP	= 1<<6,	/* Bit  6: (ro)	Auto-Neg. in progress */
+	XM_GP_FRC_INT	= 1<<5,	/* Bit  5: (sc)	Force Interrupt */
+	XM_GP_RES_MAC	= 1<<3,	/* Bit  3: (sc)	Reset MAC and FIFOs */
+	XM_GP_RES_STAT	= 1<<2,	/* Bit  2: (sc)	Reset the statistics module */
+	XM_GP_INP_ASS	= 1<<0,	/* Bit  0: (ro) GP Input Pin asserted */
+};
+
+
+/*	XM_IMSK		16 bit r/w	Interrupt Mask Register */
+/*	XM_ISRC		16 bit r/o	Interrupt Status Register */
+enum {
+	XM_IS_LNK_AE	= 1<<14, /* Bit 14:	Link Asynchronous Event */
+	XM_IS_TX_ABORT	= 1<<13, /* Bit 13:	Transmit Abort, late Col. etc */
+	XM_IS_FRC_INT	= 1<<12, /* Bit 12:	Force INT bit set in GP */
+	XM_IS_INP_ASS	= 1<<11,	/* Bit 11:	Input Asserted, GP bit 0 set */
+	XM_IS_LIPA_RC	= 1<<10,	/* Bit 10:	Link Partner requests config */
+	XM_IS_RX_PAGE	= 1<<9,	/* Bit  9:	Page Received */
+	XM_IS_TX_PAGE	= 1<<8,	/* Bit  8:	Next Page Loaded for Transmit */
+	XM_IS_AND	= 1<<7,	/* Bit  7:	Auto-Negotiation Done */
+	XM_IS_TSC_OV	= 1<<6,	/* Bit  6:	Time Stamp Counter Overflow */
+	XM_IS_RXC_OV	= 1<<5,	/* Bit  5:	Rx Counter Event Overflow */
+	XM_IS_TXC_OV	= 1<<4,	/* Bit  4:	Tx Counter Event Overflow */
+	XM_IS_RXF_OV	= 1<<3,	/* Bit  3:	Receive FIFO Overflow */
+	XM_IS_TXF_UR	= 1<<2,	/* Bit  2:	Transmit FIFO Underrun */
+	XM_IS_TX_COMP	= 1<<1,	/* Bit  1:	Frame Tx Complete */
+	XM_IS_RX_COMP	= 1<<0,	/* Bit  0:	Frame Rx Complete */
+};
+
+#define XM_DEF_MSK	(~(XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE | \
+			   XM_IS_AND | XM_IS_RXC_OV | XM_IS_TXC_OV | \
+			   XM_IS_RXF_OV | XM_IS_TXF_UR))
+
+
+/*	XM_HW_CFG	16 bit r/w	Hardware Config Register */
+enum {
+	XM_HW_GEN_EOP	= 1<<3,	/* Bit  3:	generate End of Packet pulse */
+	XM_HW_COM4SIG	= 1<<2,	/* Bit  2:	use Comma Detect for Sig. Det.*/
+	XM_HW_GMII_MD	= 1<<0,	/* Bit  0:	GMII Interface selected */
+};
+
+
+/*	XM_TX_LO_WM	16 bit r/w	Tx FIFO Low Water Mark */
+/*	XM_TX_HI_WM	16 bit r/w	Tx FIFO High Water Mark */
+#define XM_TX_WM_MSK	0x01ff	/* Bit  9.. 0	Tx FIFO Watermark bits */
+
+/*	XM_TX_THR	16 bit r/w	Tx Request Threshold */
+/*	XM_HT_THR	16 bit r/w	Host Request Threshold */
+/*	XM_RX_THR	16 bit r/w	Rx Request Threshold */
+#define XM_THR_MSK		0x03ff	/* Bit 10.. 0	Rx/Tx Request Threshold bits */
+
+
+/*	XM_TX_STAT	32 bit r/o	Tx Status LIFO Register */
+enum {
+	XM_ST_VALID	= (1UL<<31),	/* Bit 31:	Status Valid */
+	XM_ST_BYTE_CNT	= (0x3fffL<<17),	/* Bit 30..17:	Tx frame Length */
+	XM_ST_RETRY_CNT	= (0x1fL<<12),	/* Bit 16..12:	Retry Count */
+	XM_ST_EX_COL	= 1<<11,	/* Bit 11:	Excessive Collisions */
+	XM_ST_EX_DEF	= 1<<10,	/* Bit 10:	Excessive Deferral */
+	XM_ST_BURST	= 1<<9,		/* Bit  9:	p. xmitted in burst md*/
+	XM_ST_DEFER	= 1<<8,		/* Bit  8:	packet was defered */
+	XM_ST_BC	= 1<<7,		/* Bit  7:	Broadcast packet */
+	XM_ST_MC	= 1<<6,		/* Bit  6:	Multicast packet */
+	XM_ST_UC	= 1<<5,		/* Bit  5:	Unicast packet */
+	XM_ST_TX_UR	= 1<<4,		/* Bit  4:	FIFO Underrun occured */
+	XM_ST_CS_ERR	= 1<<3,		/* Bit  3:	Carrier Sense Error */
+	XM_ST_LAT_COL	= 1<<2,		/* Bit  2:	Late Collision Error */
+	XM_ST_MUL_COL	= 1<<1,		/* Bit  1:	Multiple Collisions */
+	XM_ST_SGN_COL	= 1<<0,		/* Bit  0:	Single Collision */
+};
+
+/*	XM_RX_LO_WM	16 bit r/w	Receive Low Water Mark */
+/*	XM_RX_HI_WM	16 bit r/w	Receive High Water Mark */
+#define XM_RX_WM_MSK	0x03ff		/* Bit 11.. 0:	Rx FIFO Watermark bits */
+
+
+/*	XM_DEV_ID	32 bit r/o	Device ID Register */
+#define XM_DEV_OUI	(0x00ffffffUL<<8)	/* Bit 31..8:	Device OUI */
+#define XM_DEV_REV	(0x07L << 5)		/* Bit  7..5:	Chip Rev Num */
+
+
+/*	XM_MODE		32 bit r/w	Mode Register */
+enum {
+	XM_MD_ENA_REJ	= 1<<26, /* Bit 26:	Enable Frame Reject */
+	XM_MD_SPOE_E	= 1<<25, /* Bit 25:	Send Pause on Edge */
+									/* 		extern generated */
+	XM_MD_TX_REP	= 1<<24, /* Bit 24:	Transmit Repeater Mode */
+	XM_MD_SPOFF_I	= 1<<23, /* Bit 23:	Send Pause on FIFO full */
+									/*		intern generated */
+	XM_MD_LE_STW	= 1<<22, /* Bit 22:	Rx Stat Word in Little Endian */
+	XM_MD_TX_CONT	= 1<<21, /* Bit 21:	Send Continuous */
+	XM_MD_TX_PAUSE	= 1<<20, /* Bit 20: (sc)	Send Pause Frame */
+	XM_MD_ATS	= 1<<19, /* Bit 19:	Append Time Stamp */
+	XM_MD_SPOL_I	= 1<<18, /* Bit 18:	Send Pause on Low */
+									/*		intern generated */
+	XM_MD_SPOH_I	= 1<<17, /* Bit 17:	Send Pause on High */
+									/*		intern generated */
+	XM_MD_CAP	= 1<<16, /* Bit 16:	Check Address Pair */
+	XM_MD_ENA_HASH	= 1<<15, /* Bit 15:	Enable Hashing */
+	XM_MD_CSA	= 1<<14, /* Bit 14:	Check Station Address */
+	XM_MD_CAA	= 1<<13, /* Bit 13:	Check Address Array */
+	XM_MD_RX_MCTRL	= 1<<12, /* Bit 12:	Rx MAC Control Frame */
+	XM_MD_RX_RUNT	= 1<<11, /* Bit 11:	Rx Runt Frames */
+	XM_MD_RX_IRLE	= 1<<10, /* Bit 10:	Rx in Range Len Err Frame */
+	XM_MD_RX_LONG	= 1<<9,  /* Bit  9:	Rx Long Frame */
+	XM_MD_RX_CRCE	= 1<<8,  /* Bit  8:	Rx CRC Error Frame */
+	XM_MD_RX_ERR	= 1<<7,  /* Bit  7:	Rx Error Frame */
+	XM_MD_DIS_UC	= 1<<6,  /* Bit  6:	Disable Rx Unicast */
+	XM_MD_DIS_MC	= 1<<5,  /* Bit  5:	Disable Rx Multicast */
+	XM_MD_DIS_BC	= 1<<4,  /* Bit  4:	Disable Rx Broadcast */
+	XM_MD_ENA_PROM	= 1<<3,  /* Bit  3:	Enable Promiscuous */
+	XM_MD_ENA_BE	= 1<<2,  /* Bit  2:	Enable Big Endian */
+	XM_MD_FTF	= 1<<1,  /* Bit  1: (sc)	Flush Tx FIFO */
+	XM_MD_FRF	= 1<<0,  /* Bit  0: (sc)	Flush Rx FIFO */
+};
+
+#define XM_PAUSE_MODE	(XM_MD_SPOE_E | XM_MD_SPOL_I | XM_MD_SPOH_I)
+#define XM_DEF_MODE		(XM_MD_RX_RUNT | XM_MD_RX_IRLE | XM_MD_RX_LONG |\
+				XM_MD_RX_CRCE | XM_MD_RX_ERR | XM_MD_CSA | XM_MD_CAA)
+
+/*	XM_STAT_CMD	16 bit r/w	Statistics Command Register */
+enum {
+	XM_SC_SNP_RXC	= 1<<5,	/* Bit  5: (sc)	Snap Rx Counters */
+	XM_SC_SNP_TXC	= 1<<4,	/* Bit  4: (sc)	Snap Tx Counters */
+	XM_SC_CP_RXC	= 1<<3,	/* Bit  3: 	Copy Rx Counters Continuously */
+	XM_SC_CP_TXC	= 1<<2,	/* Bit  2:	Copy Tx Counters Continuously */
+	XM_SC_CLR_RXC	= 1<<1,	/* Bit  1: (sc)	Clear Rx Counters */
+	XM_SC_CLR_TXC	= 1<<0,	/* Bit  0: (sc) Clear Tx Counters */
+};
+
+
+/*	XM_RX_CNT_EV	32 bit r/o	Rx Counter Event Register */
+/*	XM_RX_EV_MSK	32 bit r/w	Rx Counter Event Mask */
+enum {
+	XMR_MAX_SZ_OV	= 1<<31, /* Bit 31:	1024-MaxSize Rx Cnt Ov*/
+	XMR_1023B_OV	= 1<<30, /* Bit 30:	512-1023Byte Rx Cnt Ov*/
+	XMR_511B_OV	= 1<<29, /* Bit 29:	256-511 Byte Rx Cnt Ov*/
+	XMR_255B_OV	= 1<<28, /* Bit 28:	128-255 Byte Rx Cnt Ov*/
+	XMR_127B_OV	= 1<<27, /* Bit 27:	65-127 Byte Rx Cnt Ov */
+	XMR_64B_OV	= 1<<26, /* Bit 26:	64 Byte Rx Cnt Ov */
+	XMR_UTIL_OV	= 1<<25, /* Bit 25:	Rx Util Cnt Overflow */
+	XMR_UTIL_UR	= 1<<24, /* Bit 24:	Rx Util Cnt Underrun */
+	XMR_CEX_ERR_OV	= 1<<23, /* Bit 23:	CEXT Err Cnt Ov */
+	XMR_FCS_ERR_OV	= 1<<21, /* Bit 21:	Rx FCS Error Cnt Ov */
+	XMR_LNG_ERR_OV	= 1<<20, /* Bit 20:	Rx too Long Err Cnt Ov*/
+	XMR_RUNT_OV	= 1<<19, /* Bit 19:	Runt Event Cnt Ov */
+	XMR_SHT_ERR_OV	= 1<<18, /* Bit 18:	Rx Short Ev Err Cnt Ov*/
+	XMR_SYM_ERR_OV	= 1<<17, /* Bit 17:	Rx Sym Err Cnt Ov */
+	XMR_CAR_ERR_OV	= 1<<15, /* Bit 15:	Rx Carr Ev Err Cnt Ov */
+	XMR_JAB_PKT_OV	= 1<<14, /* Bit 14:	Rx Jabb Packet Cnt Ov */
+	XMR_FIFO_OV	= 1<<13, /* Bit 13:	Rx FIFO Ov Ev Cnt Ov */
+	XMR_FRA_ERR_OV	= 1<<12, /* Bit 12:	Rx Framing Err Cnt Ov */
+	XMR_FMISS_OV	= 1<<11, /* Bit 11:	Rx Missed Ev Cnt Ov */
+	XMR_BURST	= 1<<10, /* Bit 10:	Rx Burst Event Cnt Ov */
+	XMR_INV_MOC	= 1<<9,  /* Bit  9:	Rx with inv. MAC OC Ov*/
+	XMR_INV_MP	= 1<<8,  /* Bit  8:	Rx inv Pause Frame Ov */
+	XMR_MCTRL_OV	= 1<<7,  /* Bit  7:	Rx MAC Ctrl-F Cnt Ov */
+	XMR_MPAUSE_OV	= 1<<6,  /* Bit  6:	Rx Pause MAC Ctrl-F Ov*/
+	XMR_UC_OK_OV	= 1<<5,  /* Bit  5:	Rx Unicast Frame CntOv*/
+	XMR_MC_OK_OV	= 1<<4,  /* Bit  4:	Rx Multicast Cnt Ov */
+	XMR_BC_OK_OV	= 1<<3,  /* Bit  3:	Rx Broadcast Cnt Ov */
+	XMR_OK_LO_OV	= 1<<2,  /* Bit  2:	Octets Rx OK Low CntOv*/
+	XMR_OK_HI_OV	= 1<<1,  /* Bit  1:	Octets Rx OK Hi Cnt Ov*/
+	XMR_OK_OV	= 1<<0,  /* Bit  0:	Frames Received Ok Ov */
+};
+
+#define XMR_DEF_MSK		(XMR_OK_LO_OV | XMR_OK_HI_OV)
+
+/*	XM_TX_CNT_EV	32 bit r/o	Tx Counter Event Register */
+/*	XM_TX_EV_MSK	32 bit r/w	Tx Counter Event Mask */
+enum {
+	XMT_MAX_SZ_OV	= 1<<25,	/* Bit 25:	1024-MaxSize Tx Cnt Ov*/
+	XMT_1023B_OV	= 1<<24,	/* Bit 24:	512-1023Byte Tx Cnt Ov*/
+	XMT_511B_OV	= 1<<23,	/* Bit 23:	256-511 Byte Tx Cnt Ov*/
+	XMT_255B_OV	= 1<<22,	/* Bit 22:	128-255 Byte Tx Cnt Ov*/
+	XMT_127B_OV	= 1<<21,	/* Bit 21:	65-127 Byte Tx Cnt Ov */
+	XMT_64B_OV	= 1<<20,	/* Bit 20:	64 Byte Tx Cnt Ov */
+	XMT_UTIL_OV	= 1<<19,	/* Bit 19:	Tx Util Cnt Overflow */
+	XMT_UTIL_UR	= 1<<18,	/* Bit 18:	Tx Util Cnt Underrun */
+	XMT_CS_ERR_OV	= 1<<17,	/* Bit 17:	Tx Carr Sen Err Cnt Ov*/
+	XMT_FIFO_UR_OV	= 1<<16,	/* Bit 16:	Tx FIFO Ur Ev Cnt Ov */
+	XMT_EX_DEF_OV	= 1<<15,	/* Bit 15:	Tx Ex Deferall Cnt Ov */
+	XMT_DEF	= 1<<14,	/* Bit 14:	Tx Deferred Cnt Ov */
+	XMT_LAT_COL_OV	= 1<<13,	/* Bit 13:	Tx Late Col Cnt Ov */
+	XMT_ABO_COL_OV	= 1<<12,	/* Bit 12:	Tx abo dueto Ex Col Ov*/
+	XMT_MUL_COL_OV	= 1<<11,	/* Bit 11:	Tx Mult Col Cnt Ov */
+	XMT_SNG_COL	= 1<<10,	/* Bit 10:	Tx Single Col Cnt Ov */
+	XMT_MCTRL_OV	= 1<<9,		/* Bit  9:	Tx MAC Ctrl Counter Ov*/
+	XMT_MPAUSE	= 1<<8,		/* Bit  8:	Tx Pause MAC Ctrl-F Ov*/
+	XMT_BURST	= 1<<7,		/* Bit  7:	Tx Burst Event Cnt Ov */
+	XMT_LONG	= 1<<6,		/* Bit  6:	Tx Long Frame Cnt Ov */
+	XMT_UC_OK_OV	= 1<<5,		/* Bit  5:	Tx Unicast Cnt Ov */
+	XMT_MC_OK_OV	= 1<<4,		/* Bit  4:	Tx Multicast Cnt Ov */
+	XMT_BC_OK_OV	= 1<<3,		/* Bit  3:	Tx Broadcast Cnt Ov */
+	XMT_OK_LO_OV	= 1<<2,		/* Bit  2:	Octets Tx OK Low CntOv*/
+	XMT_OK_HI_OV	= 1<<1,		/* Bit  1:	Octets Tx OK Hi Cnt Ov*/
+	XMT_OK_OV	= 1<<0,		/* Bit  0:	Frames Tx Ok Ov */
+};
+
+#define XMT_DEF_MSK		(XMT_OK_LO_OV | XMT_OK_HI_OV)
+
+struct skge_rx_desc {
+	u32		control;
+	u32		next_offset;
+	u32		dma_lo;
+	u32		dma_hi;
+	u32		status;
+	u32		timestamp;
+	u16		csum2;
+	u16		csum1;
+	u16		csum2_start;
+	u16		csum1_start;
+};
+
+struct skge_tx_desc {
+	u32		control;
+	u32		next_offset;
+	u32		dma_lo;
+	u32		dma_hi;
+	u32		status;
+	u32		csum_offs;
+	u16		csum_write;
+	u16		csum_start;
+	u32		rsvd;
+};
+
+struct skge_element {
+	struct skge_element	*next;
+	void			*desc;
+	struct sk_buff  	*skb;
+	DECLARE_PCI_UNMAP_ADDR(mapaddr);
+	DECLARE_PCI_UNMAP_LEN(maplen);
+};
+
+struct skge_ring {
+	struct skge_element *to_clean;
+	struct skge_element *to_use;
+	struct skge_element *start;
+	unsigned long	    count;
+};
+
+
+struct skge_hw {
+	void __iomem  	     *regs;
+	struct pci_dev	     *pdev;
+	u32		     intr_mask;
+	struct net_device    *dev[2];
+
+	u8		     mac_cfg;
+	u8	     	     chip_id;
+	u8		     phy_type;
+	u8		     pmd_type;
+	u16		     phy_addr;
+
+	u32	     	     ram_size;
+	u32	     	     ram_offset;
+	
+	struct tasklet_struct ext_tasklet;
+	spinlock_t	     phy_lock;
+};
+
+static inline int isdualport(const struct skge_hw *hw)
+{
+	return !(hw->mac_cfg & CFG_SNG_MAC);
+}
+
+static inline u8 chip_rev(const struct skge_hw *hw)
+{
+	return (hw->mac_cfg & CFG_CHIP_R_MSK) >> 4;
+}
+
+static inline int iscopper(const struct skge_hw *hw)
+{
+	return (hw->pmd_type == 'T');
+}
+
+enum {
+	FLOW_MODE_NONE 		= 0, /* No Flow-Control */
+	FLOW_MODE_LOC_SEND	= 1, /* Local station sends PAUSE */
+	FLOW_MODE_REM_SEND	= 2, /* Symmetric or just remote */
+	FLOW_MODE_SYMMETRIC	= 3, /* Both stations may send PAUSE */
+};
+	
+struct skge_port {
+	u32		     msg_enable;
+	struct skge_hw	     *hw;
+	struct net_device    *netdev;
+	int		     port;
+
+	spinlock_t	     tx_lock;
+	u32		     tx_avail;
+	struct skge_ring     tx_ring;
+	struct skge_ring     rx_ring;
+
+	struct net_device_stats net_stats;
+
+	u8		     rx_csum;
+	u8		     blink_on;
+	u8		     flow_control;
+	u8		     wol;
+	u8		     autoneg;	/* AUTONEG_ENABLE, AUTONEG_DISABLE */
+	u8		     duplex;	/* DUPLEX_HALF, DUPLEX_FULL */
+	u16		     speed;	/* SPEED_1000, SPEED_100, ... */
+	u32		     advertising;
+
+	void		     *mem;	/* PCI memory for rings */
+	dma_addr_t	     dma;
+	unsigned long	     mem_size;
+
+	struct timer_list    link_check;
+	struct timer_list    led_blink;
+};
+
+
+/* Register accessor for memory mapped device */
+static inline u32 skge_read32(const struct skge_hw *hw, int reg)
+{
+	return readl(hw->regs + reg);
+
+}
+
+static inline u16 skge_read16(const struct skge_hw *hw, int reg)
+{
+	return readw(hw->regs + reg);
+}
+
+static inline u8 skge_read8(const struct skge_hw *hw, int reg)
+{
+	return readb(hw->regs + reg);
+}
+
+static inline void skge_write32(const struct skge_hw *hw, int reg, u32 val)
+{
+	writel(val, hw->regs + reg);
+}
+
+static inline void skge_write16(const struct skge_hw *hw, int reg, u16 val)
+{
+	writew(val, hw->regs + reg);
+}
+
+static inline void skge_write8(const struct skge_hw *hw, int reg, u8 val)
+{
+	writeb(val, hw->regs + reg);
+}
+
+/* MAC Related Registers inside the device. */
+#define SKGEMAC_REG(port,reg)	(((port)<<7)+(reg))
+
+/* PCI config space can be accessed via memory mapped space */
+#define SKGEPCI_REG(reg) ((reg)+ 0x380)
+
+#define SKGEXM_REG(port, reg) \
+	((BASE_XMAC_1 + (port) * (BASE_XMAC_2 - BASE_XMAC_1)) | (reg) << 1)
+
+static inline u32 skge_xm_read32(const struct skge_hw *hw, int port, int reg)
+{
+	return skge_read32(hw, SKGEXM_REG(port,reg));
+}
+
+static inline u16 skge_xm_read16(const struct skge_hw *hw, int port, int reg)
+{
+	return skge_read16(hw, SKGEXM_REG(port,reg));
+}
+
+static inline u8 skge_xm_read8(const struct skge_hw *hw, int port, int reg)
+{
+	return skge_read8(hw, SKGEXM_REG(port,reg));
+}
+
+static inline void skge_xm_write32(const struct skge_hw *hw, int port, int r, u32 v)
+{
+	skge_write32(hw, SKGEXM_REG(port,r), v);
+}
+
+static inline void skge_xm_write16(const struct skge_hw *hw, int port, int r, u16 v)
+{
+	skge_write16(hw, SKGEXM_REG(port,r), v);
+}
+
+static inline void skge_xm_write8(const struct skge_hw *hw, int port, int r, u8 v)
+{
+	skge_write8(hw, SKGEXM_REG(port,r), v);
+}
+
+static inline void skge_xm_outhash(const struct skge_hw *hw, int port, int reg,
+				   const u8 *hash)
+{
+	skge_xm_write16(hw, port, reg, 
+			(u16)hash[0] | ((u16)hash[1] << 8));
+	skge_xm_write16(hw, port, reg+2, 
+			(u16)hash[2] | ((u16)hash[3] << 8));
+	skge_xm_write16(hw, port, reg+4, 
+			(u16)hash[4] | ((u16)hash[5] << 8));
+	skge_xm_write16(hw, port, reg+6, 
+			(u16)hash[6] | ((u16)hash[7] << 8));
+}
+
+static inline void skge_xm_outaddr(const struct skge_hw *hw, int port, int reg,
+				   const u8 *addr)
+{
+	skge_xm_write16(hw, port, reg, 
+			(u16)addr[0] | ((u16)addr[1] << 8));
+	skge_xm_write16(hw, port, reg, 
+			(u16)addr[2] | ((u16)addr[3] << 8));
+	skge_xm_write16(hw, port, reg, 
+			(u16)addr[4] | ((u16)addr[5] << 8));
+}
+
+
+#define SKGEGMA_REG(port,reg) \
+	((reg) + BASE_GMAC_1 + \
+	 (port) * (BASE_GMAC_2-BASE_GMAC_1))
+
+static inline u16 skge_gma_read16(const struct skge_hw *hw, int port, int reg)
+{
+	return skge_read16(hw, SKGEGMA_REG(port,reg));
+}
+
+static inline u32 skge_gma_read32(const struct skge_hw *hw, int port, int reg)
+{
+	return (u32) skge_read16(hw, SKGEGMA_REG(port,reg))
+		| ((u32)skge_read16(hw, SKGEGMA_REG(port,reg+4)) << 16);
+}
+
+static inline u8 skge_gma_read8(const struct skge_hw *hw, int port, int reg)
+{
+	return skge_read8(hw, SKGEGMA_REG(port,reg));
+}
+
+static inline void skge_gma_write16(const struct skge_hw *hw, int port, int r, u16 v)
+{
+	skge_write16(hw, SKGEGMA_REG(port,r), v);
+}
+
+static inline void skge_gma_write32(const struct skge_hw *hw, int port, int r, u32 v)
+{
+	skge_write16(hw, SKGEGMA_REG(port, r), (u16) v);
+	skge_write32(hw, SKGEGMA_REG(port, r+4), (u16)(v >> 16));
+}
+
+static inline void skge_gma_write8(const struct skge_hw *hw, int port, int r, u8 v)
+{
+	skge_write8(hw, SKGEGMA_REG(port,r), v);
+}
+
+static inline void skge_gm_set_addr(struct skge_hw *hw, int port, int reg,
+				    const u8 *addr)
+{
+	skge_gma_write16(hw, port, reg,
+			 (u16) addr[0] | ((u16) addr[1] << 8));
+	skge_gma_write16(hw, port, reg+4,
+			 (u16) addr[2] | ((u16) addr[3] << 8));
+	skge_gma_write16(hw, port, reg+8,
+			 (u16) addr[4] | ((u16) addr[5] << 8));
+}
+		
+#endif
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 8f7841c..16363b5 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -198,18 +198,12 @@
 static void
 sl_free_bufs(struct slip *sl)
 {
-	void * tmp;
-
 	/* Free all SLIP frame buffers. */
-	tmp = xchg(&sl->rbuff, NULL);
-	kfree(tmp);
-	tmp = xchg(&sl->xbuff, NULL);
-	kfree(tmp);
+	kfree(xchg(&sl->rbuff, NULL));
+	kfree(xchg(&sl->xbuff, NULL));
 #ifdef SL_INCLUDE_CSLIP
-	tmp = xchg(&sl->cbuff, NULL);
-	kfree(tmp);
-	if ((tmp = xchg(&sl->slcomp, NULL)) != NULL)
-		slhc_free(tmp);
+	kfree(xchg(&sl->cbuff, NULL));
+	slhc_free(xchg(&sl->slcomp, NULL));
 #endif
 }
 
@@ -1389,10 +1383,8 @@
 	/* First of all: check for active disciplines and hangup them.
 	 */
 	do {
-		if (busy) {
-			set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(HZ / 10);
-		}
+		if (busy)
+			msleep_interruptible(100);
 
 		busy = 0;
 		for (i = 0; i < slip_maxdev; i++) {
@@ -1430,7 +1422,7 @@
 	kfree(slip_devs);
 	slip_devs = NULL;
 
-	if ((i = tty_register_ldisc(N_SLIP, NULL)))
+	if ((i = tty_unregister_ldisc(N_SLIP)))
 	{
 		printk(KERN_ERR "SLIP: can't unregister line discipline (err = %d)\n", i);
 	}
diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c
index 990201f..f00c476 100644
--- a/drivers/net/smc-mca.c
+++ b/drivers/net/smc-mca.c
@@ -49,7 +49,6 @@
 #include <asm/system.h>
 
 #include "8390.h"
-#include "smc-mca.h"
 
 #define DRV_NAME "smc-mca"
 
@@ -100,6 +99,63 @@
 MODULE_PARM_DESC(ultra_io, "SMC Ultra/EtherEZ MCA I/O base address(es)");
 MODULE_PARM_DESC(ultra_irq, "SMC Ultra/EtherEZ MCA IRQ number(s)");
 
+static const struct {
+  unsigned int base_addr;
+} addr_table[] = {
+    { 0x0800 },
+    { 0x1800 },
+    { 0x2800 },
+    { 0x3800 },
+    { 0x4800 },
+    { 0x5800 },
+    { 0x6800 },
+    { 0x7800 },
+    { 0x8800 },
+    { 0x9800 },
+    { 0xa800 },
+    { 0xb800 },
+    { 0xc800 },
+    { 0xd800 },
+    { 0xe800 },
+    { 0xf800 }
+};
+
+#define MEM_MASK 64
+
+static const struct {
+  unsigned char mem_index;
+  unsigned long mem_start;
+  unsigned char num_pages;
+} mem_table[] = {
+    { 16, 0x0c0000, 40 },
+    { 18, 0x0c4000, 40 },
+    { 20, 0x0c8000, 40 },
+    { 22, 0x0cc000, 40 },
+    { 24, 0x0d0000, 40 },
+    { 26, 0x0d4000, 40 },
+    { 28, 0x0d8000, 40 },
+    { 30, 0x0dc000, 40 },
+    {144, 0xfc0000, 40 },
+    {148, 0xfc8000, 40 },
+    {154, 0xfd0000, 40 },
+    {156, 0xfd8000, 40 },
+    {  0, 0x0c0000, 20 },
+    {  1, 0x0c2000, 20 },
+    {  2, 0x0c4000, 20 },
+    {  3, 0x0c6000, 20 }
+};
+
+#define IRQ_MASK 243
+static const struct {
+   unsigned char new_irq;
+   unsigned char old_irq;
+} irq_table[] = {
+   {  3,  3 },
+   {  4,  4 },
+   { 10, 10 },
+   { 14, 15 }
+};
+
 static short smc_mca_adapter_ids[] __initdata = {
 	0x61c8,
 	0x61c9,
@@ -126,7 +182,7 @@
 
 static int ultra_found = 0;
 
-int __init ultramca_probe(struct device *gen_dev)
+static int __init ultramca_probe(struct device *gen_dev)
 {
 	unsigned short ioaddr;
 	struct net_device *dev;
diff --git a/drivers/net/smc-mca.h b/drivers/net/smc-mca.h
deleted file mode 100644
index ac50117..0000000
--- a/drivers/net/smc-mca.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * djweis weisd3458@uni.edu
- * most of this file was taken from ps2esdi.h
- */
-
-struct {
-  unsigned int base_addr;
-} addr_table[] = {
-    { 0x0800 },
-    { 0x1800 },
-    { 0x2800 },
-    { 0x3800 },
-    { 0x4800 },
-    { 0x5800 },
-    { 0x6800 },
-    { 0x7800 },
-    { 0x8800 },
-    { 0x9800 },
-    { 0xa800 },
-    { 0xb800 },
-    { 0xc800 },
-    { 0xd800 },
-    { 0xe800 },
-    { 0xf800 }
-};
-
-#define MEM_MASK 64
-
-struct {
-  unsigned char mem_index;
-  unsigned long mem_start;
-  unsigned char num_pages;
-} mem_table[] = {
-    { 16, 0x0c0000, 40 },
-    { 18, 0x0c4000, 40 },
-    { 20, 0x0c8000, 40 },
-    { 22, 0x0cc000, 40 },
-    { 24, 0x0d0000, 40 },
-    { 26, 0x0d4000, 40 },
-    { 28, 0x0d8000, 40 },
-    { 30, 0x0dc000, 40 },
-    {144, 0xfc0000, 40 },
-    {148, 0xfc8000, 40 },
-    {154, 0xfd0000, 40 },
-    {156, 0xfd8000, 40 },
-    {  0, 0x0c0000, 20 },
-    {  1, 0x0c2000, 20 },
-    {  2, 0x0c4000, 20 },
-    {  3, 0x0c6000, 20 }
-};
-
-#define IRQ_MASK 243
-struct {
-   unsigned char new_irq;
-   unsigned char old_irq;
-} irq_table[] = {
-   {  3,  3 },
-   {  4,  4 },
-   { 10, 10 },
-   { 14, 15 }
-};
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index b564c67..6d9dae6 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -194,12 +194,7 @@
 	err = do_ultra_probe(dev);
 	if (err)
 		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
 	return dev;
-out1:
-	cleanup_card(dev);
 out:
 	free_netdev(dev);
 	return ERR_PTR(err);
@@ -325,6 +320,9 @@
 #endif
 	NS8390_init(dev, 0);
 
+	retval = register_netdev(dev);
+	if (retval)
+		goto out;
 	return 0;
 out:
 	release_region(ioaddr, ULTRA_IO_EXTENT);
@@ -583,11 +581,8 @@
 		dev->irq = irq[this_dev];
 		dev->base_addr = io[this_dev];
 		if (do_ultra_probe(dev) == 0) {
-			if (register_netdev(dev) == 0) {
-				dev_ultra[found++] = dev;
-				continue;
-			}
-			cleanup_card(dev);
+			dev_ultra[found++] = dev;
+			continue;
 		}
 		free_netdev(dev);
 		printk(KERN_WARNING "smc-ultra.c: No SMC Ultra card found (i/o = 0x%x).\n", io[this_dev]);
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index 5e561ba..fd80048 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -129,7 +129,7 @@
 /*
  * Transmit timeout, default 5 seconds.
  */
-static int watchdog = 5000;
+static int watchdog = 1000;
 module_param(watchdog, int, 0400);
 MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
 
@@ -660,15 +660,14 @@
 	SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG);
 
 	/*
-	 * If THROTTLE_TX_PKTS is set, we look at the TX_EMPTY flag
-	 * before queueing this packet for TX, and if it's clear then
-	 * we stop the queue here.  This will have the effect of
-	 * having at most 2 packets queued for TX in the chip's memory
-	 * at all time. If THROTTLE_TX_PKTS is not set then the queue
-	 * is stopped only when memory allocation (MC_ALLOC) does not
-	 * succeed right away.
+	 * If THROTTLE_TX_PKTS is set, we stop the queue here. This will
+	 * have the effect of having at most one packet queued for TX
+	 * in the chip's memory at all time.
+	 *
+	 * If THROTTLE_TX_PKTS is not set then the queue is stopped only
+	 * when memory allocation (MC_ALLOC) does not succeed right away.
 	 */
-	if (THROTTLE_TX_PKTS && !(SMC_GET_INT() & IM_TX_EMPTY_INT))
+	if (THROTTLE_TX_PKTS)
 		netif_stop_queue(dev);
 
 	/* queue the packet for TX */
@@ -792,17 +791,20 @@
 	DBG(2, "%s: TX STATUS 0x%04x PNR 0x%02x\n",
 		dev->name, tx_status, packet_no);
 
-	if (!(tx_status & TS_SUCCESS))
+	if (!(tx_status & ES_TX_SUC))
 		lp->stats.tx_errors++;
-	if (tx_status & TS_LOSTCAR)
+
+	if (tx_status & ES_LOSTCARR)
 		lp->stats.tx_carrier_errors++;
 
-	if (tx_status & TS_LATCOL) {
-		PRINTK("%s: late collision occurred on last xmit\n", dev->name);
+	if (tx_status & (ES_LATCOL | ES_16COL)) {
+		PRINTK("%s: %s occurred on last xmit\n", dev->name,
+		       (tx_status & ES_LATCOL) ?
+			"late collision" : "too many collisions");
 		lp->stats.tx_window_errors++;
 		if (!(lp->stats.tx_window_errors & 63) && net_ratelimit()) {
-			printk(KERN_INFO "%s: unexpectedly large numbers of "
-			       "late collisions. Please check duplex "
+			printk(KERN_INFO "%s: unexpectedly large number of "
+			       "bad collisions. Please check duplex "
 			       "setting.\n", dev->name);
 		}
 	}
@@ -1236,7 +1238,7 @@
 	old_carrier = netif_carrier_ok(dev) ? 1 : 0;
 
 	SMC_SELECT_BANK(0);
-	new_carrier = SMC_inw(ioaddr, EPH_STATUS_REG) & ES_LINK_OK ? 1 : 0;
+	new_carrier = (SMC_GET_EPH_STATUS() & ES_LINK_OK) ? 1 : 0;
 	SMC_SELECT_BANK(2);
 
 	if (init || (old_carrier != new_carrier)) {
@@ -1308,15 +1310,16 @@
 		if (!status)
 			break;
 
-		if (status & IM_RCV_INT) {
-			DBG(3, "%s: RX irq\n", dev->name);
-			smc_rcv(dev);
-		} else if (status & IM_TX_INT) {
+		if (status & IM_TX_INT) {
+			/* do this before RX as it will free memory quickly */
 			DBG(3, "%s: TX int\n", dev->name);
 			smc_tx(dev);
 			SMC_ACK_INT(IM_TX_INT);
 			if (THROTTLE_TX_PKTS)
 				netif_wake_queue(dev);
+		} else if (status & IM_RCV_INT) {
+			DBG(3, "%s: RX irq\n", dev->name);
+			smc_rcv(dev);
 		} else if (status & IM_ALLOC_INT) {
 			DBG(3, "%s: Allocation irq\n", dev->name);
 			tasklet_hi_schedule(&lp->tx_task);
@@ -1337,7 +1340,10 @@
 			/* multiple collisions */
 			lp->stats.collisions += card_stats & 0xF;
 		} else if (status & IM_RX_OVRN_INT) {
-			DBG(1, "%s: RX overrun\n", dev->name);
+			DBG(1, "%s: RX overrun (EPH_ST 0x%04x)\n", dev->name,
+			       ({ int eph_st; SMC_SELECT_BANK(0);
+				  eph_st = SMC_GET_EPH_STATUS();
+				  SMC_SELECT_BANK(2); eph_st; }) );
 			SMC_ACK_INT(IM_RX_OVRN_INT);
 			lp->stats.rx_errors++;
 			lp->stats.rx_fifo_errors++;
@@ -1389,7 +1395,7 @@
 {
 	struct smc_local *lp = netdev_priv(dev);
 	void __iomem *ioaddr = lp->base;
-	int status, mask, meminfo, fifo;
+	int status, mask, eph_st, meminfo, fifo;
 
 	DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
 
@@ -1398,11 +1404,13 @@
 	mask = SMC_GET_INT_MASK();
 	fifo = SMC_GET_FIFO();
 	SMC_SELECT_BANK(0);
+	eph_st = SMC_GET_EPH_STATUS();
 	meminfo = SMC_GET_MIR();
 	SMC_SELECT_BANK(2);
 	spin_unlock_irq(&lp->lock);
-	PRINTK( "%s: INT 0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x\n",
-		dev->name, status, mask, meminfo, fifo );
+	PRINTK( "%s: TX timeout (INT 0x%02x INTMASK 0x%02x "
+		"MEM 0x%04x FIFO 0x%04x EPH_ST 0x%04x)\n",
+		dev->name, status, mask, meminfo, fifo, eph_st );
 
 	smc_reset(dev);
 	smc_enable(dev);
@@ -1863,7 +1871,7 @@
 	SMC_SELECT_BANK(1);
 	val = SMC_GET_BASE();
 	val = ((val & 0x1F00) >> 3) << SMC_IO_SHIFT;
-	if (((unsigned long)ioaddr & ((PAGE_SIZE-1)<<SMC_IO_SHIFT)) != val) { /*XXX: WTF? */
+	if (((unsigned int)ioaddr & (0x3e0 << SMC_IO_SHIFT)) != val) {
 		printk("%s: IOADDR %p doesn't match configuration (%x).\n",
 			CARDNAME, ioaddr, val);
 	}
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index ddd2688..946528e 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -151,7 +151,7 @@
 
 /* We actually can't write halfwords properly if not word aligned */
 static inline void
-SMC_outw(u16 val, unsigned long ioaddr, int reg)
+SMC_outw(u16 val, void __iomem *ioaddr, int reg)
 {
 	if (reg & 2) {
 		unsigned int v = val << 16;
@@ -317,7 +317,7 @@
 #define SMC_insl(a, r, p, l) \
 	smc_pxa_dma_insl(a, lp->physaddr, r, dev->dma, p, l)
 static inline void
-smc_pxa_dma_insl(u_long ioaddr, u_long physaddr, int reg, int dma,
+smc_pxa_dma_insl(void __iomem *ioaddr, u_long physaddr, int reg, int dma,
 		 u_char *buf, int len)
 {
 	dma_addr_t dmabuf;
@@ -355,7 +355,7 @@
 #define SMC_insw(a, r, p, l) \
 	smc_pxa_dma_insw(a, lp->physaddr, r, dev->dma, p, l)
 static inline void
-smc_pxa_dma_insw(u_long ioaddr, u_long physaddr, int reg, int dma,
+smc_pxa_dma_insw(void __iomem *ioaddr, u_long physaddr, int reg, int dma,
 		 u_char *buf, int len)
 {
 	dma_addr_t dmabuf;
@@ -681,14 +681,6 @@
 
 
 /*
- . Transmit status bits
-*/
-#define TS_SUCCESS 0x0001
-#define TS_LOSTCAR 0x0400
-#define TS_LATCOL  0x0200
-#define TS_16COL   0x0010
-
-/*
  . Receive status bits
 */
 #define RS_ALGNERR	0x8000
@@ -845,6 +837,7 @@
 #define SMC_GET_FIFO()		SMC_inw( ioaddr, FIFO_REG )
 #define SMC_GET_PTR()		SMC_inw( ioaddr, PTR_REG )
 #define SMC_SET_PTR(x)		SMC_outw( x, ioaddr, PTR_REG )
+#define SMC_GET_EPH_STATUS()	SMC_inw( ioaddr, EPH_STATUS_REG )
 #define SMC_GET_RCR()		SMC_inw( ioaddr, RCR_REG )
 #define SMC_SET_RCR(x)		SMC_outw( x, ioaddr, RCR_REG )
 #define SMC_GET_REV()		SMC_inw( ioaddr, REV_REG )
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 236bdd3..12e2b68 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -2,7 +2,7 @@
 /*
 	Written 1998-2000 by Donald Becker.
 
-	Current maintainer is Ion Badulescu <ionut@cs.columbia.edu>. Please
+	Current maintainer is Ion Badulescu <ionut ta badula tod org>. Please
 	send all bug reports to me, and not to Donald Becker, as this code
 	has been heavily modified from Donald's original version.
 
@@ -129,12 +129,18 @@
 	- put the chip to a D3 slumber on driver unload
 	- added config option to enable/disable NAPI
 
-TODO:	bugfixes (no bugs known as of right now)
+	LK1.4.2 (Ion Badulescu)
+	- finally added firmware (GPL'ed by Adaptec)
+	- removed compatibility code for 2.2.x
+
+TODO:	- fix forced speed/duplexing code (broken a long time ago, when
+	somebody converted the driver to use the generic MII code)
+	- fix VLAN support
 */
 
 #define DRV_NAME	"starfire"
-#define DRV_VERSION	"1.03+LK1.4.1"
-#define DRV_RELDATE	"February 10, 2002"
+#define DRV_VERSION	"1.03+LK1.4.2"
+#define DRV_RELDATE	"January 19, 2005"
 
 #include <linux/config.h>
 #include <linux/version.h>
@@ -145,25 +151,15 @@
 #include <linux/etherdevice.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/crc32.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/if_vlan.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-/*
- * Adaptec's license for their drivers (which is where I got the
- * firmware files) does not allow one to redistribute them. Thus, we can't
- * include the firmware with this driver.
- *
- * However, should a legal-to-distribute firmware become available,
- * the driver developer would need only to obtain the firmware in the
- * form of a C header file.
- * Once that's done, the #undef below must be changed into a #define
- * for this driver to really use the firmware. Note that Rx/Tx
- * hardware TCP checksumming is not possible without the firmware.
- *
- * WANTED: legal firmware to include with this GPL'd driver.
- */
-#undef HAS_FIRMWARE
+#include "starfire_firmware.h"
 /*
  * The current frame processor firmware fails to checksum a fragment
  * of length 1. If and when this is fixed, the #define below can be removed.
@@ -172,13 +168,7 @@
 /*
  * Define this if using the driver with the zero-copy patch
  */
-#if defined(HAS_FIRMWARE) && defined(MAX_SKB_FRAGS)
 #define ZEROCOPY
-#endif
-
-#ifdef HAS_FIRMWARE
-#include "starfire_firmware.h"
-#endif /* HAS_FIRMWARE */
 
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
 #define VLAN_SUPPORT
@@ -202,11 +192,7 @@
    The Starfire has a 512 element hash table based on the Ethernet CRC. */
 static int multicast_filter_limit = 512;
 /* Whether to do TCP/UDP checksums in hardware */
-#ifdef HAS_FIRMWARE
 static int enable_hw_cksum = 1;
-#else
-static int enable_hw_cksum = 0;
-#endif
 
 #define PKT_BUF_SZ	1536		/* Size of each temporary Rx buffer.*/
 /*
@@ -291,43 +277,15 @@
 #define RX_DESC_ADDR_SIZE RxDescAddr32bit
 #endif
 
-#ifdef MAX_SKB_FRAGS
 #define skb_first_frag_len(skb)	skb_headlen(skb)
 #define skb_num_frags(skb) (skb_shinfo(skb)->nr_frags + 1)
-#else  /* not MAX_SKB_FRAGS */
-#define skb_first_frag_len(skb)	(skb->len)
-#define skb_num_frags(skb) 1
-#endif /* not MAX_SKB_FRAGS */
-
-/* 2.2.x compatibility code */
-#if LINUX_VERSION_CODE < 0x20300
-
-#include "starfire-kcomp22.h"
-
-#else  /* LINUX_VERSION_CODE > 0x20300 */
-
-#include <linux/crc32.h>
-#include <linux/ethtool.h>
-#include <linux/mii.h>
-
-#include <linux/if_vlan.h>
-
-#define init_tx_timer(dev, func, timeout) \
-	dev->tx_timeout = func; \
-	dev->watchdog_timeo = timeout;
-#define kick_tx_timer(dev, func, timeout)
-
-#define netif_start_if(dev)
-#define netif_stop_if(dev)
-
-#define PCI_SLOT_NAME(pci_dev)	pci_name(pci_dev)
-
-#endif /* LINUX_VERSION_CODE > 0x20300 */
 
 #ifdef HAVE_NETDEV_POLL
 #define init_poll(dev) \
+do { \
 	dev->poll = &netdev_poll; \
-	dev->weight = max_interrupt_work;
+	dev->weight = max_interrupt_work; \
+} while (0)
 #define netdev_rx(dev, ioaddr) \
 do { \
 	u32 intr_enable; \
@@ -341,7 +299,7 @@
 		/* Paranoia check */ \
 		intr_enable = readl(ioaddr + IntrEnable); \
 		if (intr_enable & (IntrRxDone | IntrRxEmpty)) { \
-			printk("%s: interrupt while in polling mode!\n", dev->name); \
+			printk(KERN_INFO "%s: interrupt while in polling mode!\n", dev->name); \
 			intr_enable &= ~(IntrRxDone | IntrRxEmpty); \
 			writel(intr_enable, ioaddr + IntrEnable); \
 		} \
@@ -371,6 +329,7 @@
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
 
 module_param(max_interrupt_work, int, 0);
 module_param(mtu, int, 0);
@@ -425,7 +384,7 @@
 minimum-length padding.  It does not use the completion queue
 consumer index, but instead checks for non-zero status entries.
 
-For receive this driver uses type 0/1/2/3 receive descriptors.  The driver
+For receive this driver uses type 2/3 receive descriptors.  The driver
 allocates full frame size skbuffs for the Rx ring buffers, so all frames
 should fit in a single descriptor.  The driver does not use the completion
 queue consumer index, but instead checks for non-zero status entries.
@@ -476,7 +435,7 @@
 
 */
 
-
+
 
 enum chip_capability_flags {CanHaveMII=1, };
 
@@ -670,7 +629,6 @@
 	u32 timestamp;
 };
 /* XXX: this is ugly and I'm not sure it's worth the trouble -Ion */
-#ifdef HAS_FIRMWARE
 #ifdef VLAN_SUPPORT
 typedef struct full_rx_done_desc rx_done_desc;
 #define RxComplType RxComplType3
@@ -678,15 +636,6 @@
 typedef struct csum_rx_done_desc rx_done_desc;
 #define RxComplType RxComplType2
 #endif /* not VLAN_SUPPORT */
-#else  /* not HAS_FIRMWARE */
-#ifdef VLAN_SUPPORT
-typedef struct basic_rx_done_desc rx_done_desc;
-#define RxComplType RxComplType1
-#else  /* not VLAN_SUPPORT */
-typedef struct short_rx_done_desc rx_done_desc;
-#define RxComplType RxComplType0
-#endif /* not VLAN_SUPPORT */
-#endif /* not HAS_FIRMWARE */
 
 enum rx_done_bits {
 	RxOK=0x20000000, RxFIFOErr=0x10000000, RxBufQ2=0x08000000,
@@ -898,13 +847,10 @@
 	/* enable MWI -- it vastly improves Rx performance on sparc64 */
 	pci_set_mwi(pdev);
 
-#ifdef MAX_SKB_FRAGS
-	dev->features |= NETIF_F_SG;
-#endif /* MAX_SKB_FRAGS */
 #ifdef ZEROCOPY
 	/* Starfire can do TCP/UDP checksumming */
 	if (enable_hw_cksum)
-		dev->features |= NETIF_F_IP_CSUM;
+		dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
 #endif /* ZEROCOPY */
 #ifdef VLAN_SUPPORT
 	dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
@@ -1008,7 +954,8 @@
 	/* The chip-specific entries in the device structure. */
 	dev->open = &netdev_open;
 	dev->hard_start_xmit = &start_tx;
-	init_tx_timer(dev, tx_timeout, TX_TIMEOUT);
+	dev->tx_timeout = tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
 	init_poll(dev);
 	dev->stop = &netdev_close;
 	dev->get_stats = &get_stats;
@@ -1039,7 +986,7 @@
 				if ((mdio_read(dev, phy, MII_BMCR) & BMCR_RESET) == 0)
 					break;
 			if (boguscnt == 0) {
-				printk("%s: PHY reset never completed!\n", dev->name);
+				printk("%s: PHY#%d reset never completed!\n", dev->name, phy);
 				continue;
 			}
 			mii_status = mdio_read(dev, phy, MII_BMSR);
@@ -1110,6 +1057,7 @@
 	size_t tx_done_q_size, rx_done_q_size, tx_ring_size, rx_ring_size;
 
 	/* Do we ever need to reset the chip??? */
+
 	retval = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev);
 	if (retval)
 		return retval;
@@ -1211,7 +1159,6 @@
 
 	writel(np->intr_timer_ctrl, ioaddr + IntrTimerCtrl);
 
-	netif_start_if(dev);
 	netif_start_queue(dev);
 
 	if (debug > 1)
@@ -1238,13 +1185,11 @@
 	writel(ETH_P_8021Q, ioaddr + VlanType);
 #endif /* VLAN_SUPPORT */
 
-#ifdef HAS_FIRMWARE
 	/* Load Rx/Tx firmware into the frame processors */
 	for (i = 0; i < FIRMWARE_RX_SIZE * 2; i++)
 		writel(firmware_rx[i], ioaddr + RxGfpMem + i * 4);
 	for (i = 0; i < FIRMWARE_TX_SIZE * 2; i++)
 		writel(firmware_tx[i], ioaddr + TxGfpMem + i * 4);
-#endif /* HAS_FIRMWARE */
 	if (enable_hw_cksum)
 		/* Enable the Rx and Tx units, and the Rx/Tx frame processors. */
 		writel(TxEnable|TxGFPEnable|RxEnable|RxGFPEnable, ioaddr + GenCtrl);
@@ -1378,8 +1323,6 @@
 	u32 status;
 	int i;
 
-	kick_tx_timer(dev, tx_timeout, TX_TIMEOUT);
-
 	/*
 	 * be cautious here, wrapping the queue has weird semantics
 	 * and we may not have enough slots even when it seems we do.
@@ -1404,7 +1347,7 @@
 		}
 
 		if (has_bad_length)
-			skb_checksum_help(skb);
+			skb_checksum_help(skb, 0);
 	}
 #endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */
 
@@ -1433,12 +1376,10 @@
 			np->tx_info[entry].mapping =
 				pci_map_single(np->pci_dev, skb->data, skb_first_frag_len(skb), PCI_DMA_TODEVICE);
 		} else {
-#ifdef MAX_SKB_FRAGS
 			skb_frag_t *this_frag = &skb_shinfo(skb)->frags[i - 1];
 			status |= this_frag->size;
 			np->tx_info[entry].mapping =
 				pci_map_single(np->pci_dev, page_address(this_frag->page) + this_frag->page_offset, this_frag->size, PCI_DMA_TODEVICE);
-#endif /* MAX_SKB_FRAGS */
 		}
 
 		np->tx_ring[entry].addr = cpu_to_dma(np->tx_info[entry].mapping);
@@ -1531,7 +1472,6 @@
 				np->tx_info[entry].mapping = 0;
 				np->dirty_tx += np->tx_info[entry].used_slots;
 				entry = (entry + np->tx_info[entry].used_slots) % TX_RING_SIZE;
-#ifdef MAX_SKB_FRAGS
 				{
 					int i;
 					for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
@@ -1543,7 +1483,7 @@
 						entry++;
 					}
 				}
-#endif /* MAX_SKB_FRAGS */
+
 				dev_kfree_skb_irq(skb);
 			}
 			np->tx_done_q[np->tx_done].status = 0;
@@ -1603,7 +1543,7 @@
 		if (debug > 4)
 			printk(KERN_DEBUG "  netdev_rx() status of %d was %#8.8x.\n", np->rx_done, desc_status);
 		if (!(desc_status & RxOK)) {
-			/* There was a error. */
+			/* There was an error. */
 			if (debug > 2)
 				printk(KERN_DEBUG "  netdev_rx() Rx error was %#8.8x.\n", desc_status);
 			np->stats.rx_errors++;
@@ -1656,11 +1596,10 @@
 #endif
 
 		skb->protocol = eth_type_trans(skb, dev);
-#if defined(HAS_FIRMWARE) || defined(VLAN_SUPPORT)
+#ifdef VLAN_SUPPORT
 		if (debug > 4)
 			printk(KERN_DEBUG "  netdev_rx() status2 of %d was %#4.4x.\n", np->rx_done, le16_to_cpu(desc->status2));
 #endif
-#ifdef HAS_FIRMWARE
 		if (le16_to_cpu(desc->status2) & 0x0100) {
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 			np->stats.rx_compressed++;
@@ -1679,7 +1618,6 @@
 			skb->csum = le16_to_cpu(desc->csum);
 			printk(KERN_DEBUG "%s: checksum_hw, status2 = %#x\n", dev->name, le16_to_cpu(desc->status2));
 		}
-#endif /* HAS_FIRMWARE */
 #ifdef VLAN_SUPPORT
 		if (np->vlgrp && le16_to_cpu(desc->status2) & 0x0200) {
 			if (debug > 4)
@@ -1900,9 +1838,6 @@
 }
 
 
-/* Chips may use the upper or lower CRC bits, and may reverse and/or invert
-   them.  Select the endian-ness that results in minimal calculations.
-*/
 static void set_rx_mode(struct net_device *dev)
 {
 	struct netdev_private *np = netdev_priv(dev);
@@ -1969,6 +1904,8 @@
 		memset(mc_filter, 0, sizeof(mc_filter));
 		for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
 		     i++, mclist = mclist->next) {
+			/* The chip uses the upper 9 CRC bits
+			   as index into the hash table */
 			int bit_nr = ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 23;
 			__u32 *fptr = (__u32 *) &mc_filter[(bit_nr >> 4) & ~1];
 
@@ -2001,7 +1938,7 @@
 	struct netdev_private *np = netdev_priv(dev);
 	strcpy(info->driver, DRV_NAME);
 	strcpy(info->version, DRV_VERSION);
-	strcpy(info->bus_info, PCI_SLOT_NAME(np->pci_dev));
+	strcpy(info->bus_info, pci_name(np->pci_dev));
 }
 
 static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
@@ -2083,7 +2020,6 @@
 	int i;
 
 	netif_stop_queue(dev);
-	netif_stop_if(dev);
 
 	if (debug > 1) {
 		printk(KERN_DEBUG "%s: Shutting down ethercard, Intr status %#8.8x.\n",
@@ -2184,7 +2120,13 @@
 /* when a module, this is printed whether or not devices are found in probe */
 #ifdef MODULE
 	printk(version);
+#ifdef HAVE_NETDEV_POLL
+	printk(KERN_INFO DRV_NAME ": polling (NAPI) enabled\n");
+#else
+	printk(KERN_INFO DRV_NAME ": polling (NAPI) disabled\n");
 #endif
+#endif
+
 #ifndef ADDR_64BITS
 	/* we can do this test only at run-time... sigh */
 	if (sizeof(dma_addr_t) == sizeof(u64)) {
@@ -2192,10 +2134,6 @@
 		return -ENODEV;
 	}
 #endif /* not ADDR_64BITS */
-#ifndef HAS_FIRMWARE
-	/* unconditionally disable hw cksums if firmware is not present */
-	enable_hw_cksum = 0;
-#endif /* not HAS_FIRMWARE */
 	return pci_module_init (&starfire_driver);
 }
 
diff --git a/drivers/net/starfire_firmware.h b/drivers/net/starfire_firmware.h
new file mode 100644
index 0000000..0a66852
--- /dev/null
+++ b/drivers/net/starfire_firmware.h
@@ -0,0 +1,346 @@
+/*
+ * Copyright 2003 Adaptec, Inc.
+ *
+ * Please read the following license before using the Adaptec Software
+ * ("Program"). If you do not agree to the license terms, do not use the
+ * Program:
+ *
+ * You agree to be bound by version 2 of the General Public License ("GPL")
+ * dated June 1991, which can be found at http://www.fsf.org/licenses/gpl.html.
+ * If the link is broken, write to Free Software Foundation, 59 Temple Place,
+ * Boston, Massachusetts 02111-1307.
+ *
+ * BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE IT IS LICENSED "AS IS" AND
+ * THERE IS NO WARRANTY FOR THE PROGRAM, INCLUDING BUT NOT LIMITED TO THE
+ * IMPLIED WARRANTIES OF MERCHANTIBILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * (TO THE EXTENT PERMITTED BY APPLICABLE LAW). USE OF THE PROGRAM IS AT YOUR
+ * OWN RISK. IN NO EVENT WILL ADAPTEC OR ITS LICENSORS BE LIABLE TO YOU FOR
+ * DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM.
+ *
+ */
+
+static const u32 firmware_rx[] = {
+  0x010003dc, 0x00000000,
+  0x04000421, 0x00000086,
+  0x80000015, 0x0000180e,
+  0x81000015, 0x00006664,
+  0x1a0040ab, 0x00000b06,
+  0x14200011, 0x00000000,
+  0x14204022, 0x0000aaaa,
+  0x14204022, 0x00000300,
+  0x14204022, 0x00000000,
+  0x1a0040ab, 0x00000b14,
+  0x14200011, 0x00000000,
+  0x83000015, 0x00000002,
+  0x04000021, 0x00000000,
+  0x00000010, 0x00000000,
+  0x04000421, 0x00000087,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00008015, 0x00000000,
+  0x0000003e, 0x00000000,
+  0x00000010, 0x00000000,
+  0x82000015, 0x00004000,
+  0x009e8050, 0x00000000,
+  0x03008015, 0x00000000,
+  0x86008015, 0x00000000,
+  0x82000015, 0x00008000,
+  0x0100001c, 0x00000000,
+  0x000050a0, 0x0000010c,
+  0x4e20d011, 0x00006008,
+  0x1420d012, 0x00004008,
+  0x0000f090, 0x00007000,
+  0x0000c8b0, 0x00003000,
+  0x00004040, 0x00000000,
+  0x00108015, 0x00000000,
+  0x00a2c150, 0x00004000,
+  0x00a400b0, 0x00000014,
+  0x00000020, 0x00000000,
+  0x2500400d, 0x00002525,
+  0x00047220, 0x00003100,
+  0x00934070, 0x00000000,
+  0x00000020, 0x00000000,
+  0x00924460, 0x00000184,
+  0x2b20c011, 0x00000000,
+  0x0000c420, 0x00000540,
+  0x36014018, 0x0000422d,
+  0x14200011, 0x00000000,
+  0x00924460, 0x00000183,
+  0x3200001f, 0x00000034,
+  0x02ac0015, 0x00000002,
+  0x00a60110, 0x00000008,
+  0x42200011, 0x00000000,
+  0x00924060, 0x00000103,
+  0x0000001e, 0x00000000,
+  0x00000020, 0x00000100,
+  0x0000001e, 0x00000000,
+  0x00924460, 0x00000086,
+  0x00004080, 0x00000000,
+  0x0092c070, 0x00000000,
+  0x00924060, 0x00000100,
+  0x0000c890, 0x00005000,
+  0x00a6c110, 0x00000000,
+  0x00b0c090, 0x00000012,
+  0x021c0015, 0x00000000,
+  0x3200001f, 0x00000034,
+  0x00924460, 0x00000510,
+  0x44210011, 0x00000000,
+  0x42000011, 0x00000000,
+  0x83000015, 0x00000040,
+  0x00924460, 0x00000508,
+  0x45014018, 0x00004545,
+  0x00808050, 0x00000000,
+  0x62208012, 0x00000000,
+  0x82000015, 0x00000800,
+  0x15200011, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x80000015, 0x0000eea4,
+  0x81000015, 0x0000005f,
+  0x00000060, 0x00000000,
+  0x00004120, 0x00000000,
+  0x00004a00, 0x00004000,
+  0x00924460, 0x00000190,
+  0x5601401a, 0x00005956,
+  0x14000011, 0x00000000,
+  0x00934050, 0x00000018,
+  0x00930050, 0x00000018,
+  0x3601403a, 0x0000002d,
+  0x000643a9, 0x00000000,
+  0x0000c420, 0x00000140,
+  0x5601401a, 0x00005956,
+  0x14000011, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x000642a9, 0x00000000,
+  0x00024420, 0x00000183,
+  0x5601401a, 0x00005956,
+  0x82000015, 0x00002000,
+  0x15200011, 0x00000000,
+  0x82000015, 0x00000010,
+  0x15200011, 0x00000000,
+  0x82000015, 0x00000010,
+  0x15200011, 0x00000000,
+};	/* 104 Rx instructions */
+#define FIRMWARE_RX_SIZE 104
+
+static const u32 firmware_tx[] = {
+  0x010003dc, 0x00000000,
+  0x04000421, 0x00000086,
+  0x80000015, 0x0000180e,
+  0x81000015, 0x00006664,
+  0x1a0040ab, 0x00000b06,
+  0x14200011, 0x00000000,
+  0x14204022, 0x0000aaaa,
+  0x14204022, 0x00000300,
+  0x14204022, 0x00000000,
+  0x1a0040ab, 0x00000b14,
+  0x14200011, 0x00000000,
+  0x83000015, 0x00000002,
+  0x04000021, 0x00000000,
+  0x00000010, 0x00000000,
+  0x04000421, 0x00000087,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00008015, 0x00000000,
+  0x0000003e, 0x00000000,
+  0x00000010, 0x00000000,
+  0x82000015, 0x00004000,
+  0x009e8050, 0x00000000,
+  0x03008015, 0x00000000,
+  0x86008015, 0x00000000,
+  0x82000015, 0x00008000,
+  0x0100001c, 0x00000000,
+  0x000050a0, 0x0000010c,
+  0x4e20d011, 0x00006008,
+  0x1420d012, 0x00004008,
+  0x0000f090, 0x00007000,
+  0x0000c8b0, 0x00003000,
+  0x00004040, 0x00000000,
+  0x00108015, 0x00000000,
+  0x00a2c150, 0x00004000,
+  0x00a400b0, 0x00000014,
+  0x00000020, 0x00000000,
+  0x2500400d, 0x00002525,
+  0x00047220, 0x00003100,
+  0x00934070, 0x00000000,
+  0x00000020, 0x00000000,
+  0x00924460, 0x00000184,
+  0x2b20c011, 0x00000000,
+  0x0000c420, 0x00000540,
+  0x36014018, 0x0000422d,
+  0x14200011, 0x00000000,
+  0x00924460, 0x00000183,
+  0x3200001f, 0x00000034,
+  0x02ac0015, 0x00000002,
+  0x00a60110, 0x00000008,
+  0x42200011, 0x00000000,
+  0x00924060, 0x00000103,
+  0x0000001e, 0x00000000,
+  0x00000020, 0x00000100,
+  0x0000001e, 0x00000000,
+  0x00924460, 0x00000086,
+  0x00004080, 0x00000000,
+  0x0092c070, 0x00000000,
+  0x00924060, 0x00000100,
+  0x0000c890, 0x00005000,
+  0x00a6c110, 0x00000000,
+  0x00b0c090, 0x00000012,
+  0x021c0015, 0x00000000,
+  0x3200001f, 0x00000034,
+  0x00924460, 0x00000510,
+  0x44210011, 0x00000000,
+  0x42000011, 0x00000000,
+  0x83000015, 0x00000040,
+  0x00924460, 0x00000508,
+  0x45014018, 0x00004545,
+  0x00808050, 0x00000000,
+  0x62208012, 0x00000000,
+  0x82000015, 0x00000800,
+  0x15200011, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x80000015, 0x0000eea4,
+  0x81000015, 0x0000005f,
+  0x00000060, 0x00000000,
+  0x00004120, 0x00000000,
+  0x00004a00, 0x00004000,
+  0x00924460, 0x00000190,
+  0x5601401a, 0x00005956,
+  0x14000011, 0x00000000,
+  0x00934050, 0x00000018,
+  0x00930050, 0x00000018,
+  0x3601403a, 0x0000002d,
+  0x000643a9, 0x00000000,
+  0x0000c420, 0x00000140,
+  0x5601401a, 0x00005956,
+  0x14000011, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x000642a9, 0x00000000,
+  0x00024420, 0x00000183,
+  0x5601401a, 0x00005956,
+  0x82000015, 0x00002000,
+  0x15200011, 0x00000000,
+  0x82000015, 0x00000010,
+  0x15200011, 0x00000000,
+  0x82000015, 0x00000010,
+  0x15200011, 0x00000000,
+};	/* 104 Tx instructions */
+#define FIRMWARE_TX_SIZE 104
+#if 0
+static const u32 firmware_wol[] = {
+  0x010003dc, 0x00000000,
+  0x19000421, 0x00000087,
+  0x80000015, 0x00001a1a,
+  0x81000015, 0x00001a1a,
+  0x1a0040ab, 0x00000b06,
+  0x15200011, 0x00000000,
+  0x15204022, 0x0000aaaa,
+  0x15204022, 0x00000300,
+  0x15204022, 0x00000000,
+  0x1a0040ab, 0x00000b15,
+  0x15200011, 0x00000000,
+  0x83000015, 0x00000002,
+  0x04000021, 0x00000000,
+  0x00000010, 0x00000000,
+  0x04000421, 0x00000087,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00008015, 0x00000000,
+  0x0000003e, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x82000015, 0x00004000,
+  0x82000015, 0x00008000,
+  0x0000000c, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00004080, 0x00000100,
+  0x1f20c011, 0x00001122,
+  0x2720f011, 0x00003011,
+  0x19200071, 0x00000000,
+  0x1a200051, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x1d2040a4, 0x00003344,
+  0x1d2040a2, 0x00005566,
+  0x000040a0, 0x00000100,
+  0x00108050, 0x00000001,
+  0x1a208012, 0x00000006,
+  0x82000015, 0x00008080,
+  0x010003dc, 0x00000000,
+  0x1d2040a4, 0x00002233,
+  0x1d2040a4, 0x00004455,
+  0x2d208011, 0x00000005,
+  0x1d2040a4, 0x00006611,
+  0x00108050, 0x00000001,
+  0x27200011, 0x00000000,
+  0x1d2050a4, 0x00006600,
+  0x82000015, 0x00008080,
+  0x010003dc, 0x00000000,
+  0x00000050, 0x00000000,
+  0x1b200031, 0x00000000,
+  0x0000001e, 0x00000000,
+  0x0000001e, 0x00000000,
+  0x0000001e, 0x00000000,
+  0x0000001e, 0x00000000,
+  0x00924460, 0x00000086,
+  0x00004080, 0x00000000,
+  0x0092c070, 0x00000000,
+  0x00924060, 0x00000100,
+  0x0000c890, 0x00005000,
+  0x00a6c110, 0x00000000,
+  0x00b0c090, 0x00000012,
+  0x021c0015, 0x00000000,
+  0x3200001f, 0x00000034,
+  0x00924460, 0x00000510,
+  0x44210011, 0x00000000,
+  0x42000011, 0x00000000,
+  0x83000015, 0x00000040,
+  0x00924460, 0x00000508,
+  0x476a0012, 0x00000100,
+  0x83000015, 0x00000008,
+  0x16200011, 0x00000000,
+  0x001e8050, 0x00000000,
+  0x001e8050, 0x00000000,
+  0x00808050, 0x00000000,
+  0x03008015, 0x00000000,
+  0x62208012, 0x00000000,
+  0x82000015, 0x00000800,
+  0x16200011, 0x00000000,
+  0x80000015, 0x0000eea4,
+  0x81000015, 0x0000005f,
+  0x00000020, 0x00000000,
+  0x00004120, 0x00000000,
+  0x00004a00, 0x00004000,
+  0x00924460, 0x00000190,
+  0x5c01401a, 0x0000595c,
+  0x15000011, 0x00000000,
+  0x00934050, 0x00000018,
+  0x00930050, 0x00000018,
+  0x3601403a, 0x0000002d,
+  0x00064029, 0x00000000,
+  0x0000c420, 0x00000140,
+  0x5c01401a, 0x0000595c,
+  0x15000011, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00000010, 0x00000000,
+  0x00064029, 0x00000000,
+  0x00024420, 0x00000183,
+  0x5c01401a, 0x0000595c,
+  0x82000015, 0x00002000,
+  0x16200011, 0x00000000,
+  0x82000015, 0x00000010,
+  0x16200011, 0x00000000,
+  0x82000015, 0x00000010,
+  0x16200011, 0x00000000,
+};	/* 104 WoL instructions */
+#define FIRMWARE_WOL_SIZE 104
+#endif
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index 5cd50fd..1f56556 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -44,6 +44,7 @@
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
@@ -2989,10 +2990,10 @@
 	 */
 	if (pdev->vendor == PCI_VENDOR_ID_SUN &&
 	    pdev->device == PCI_DEVICE_ID_SUN_GEM &&
-	    !pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL)) {
+	    !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
 		pci_using_dac = 1;
 	} else {
-		err = pci_set_dma_mask(pdev, (u64) 0xffffffff);
+		err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
 		if (err) {
 			printk(KERN_ERR PFX "No usable DMA configuration, "
 			       "aborting.\n");
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index fc9b5cd..7e371b1 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -7,7 +7,12 @@
  * Copyright (C) 2005 Broadcom Corporation.
  *
  * Firmware is:
- * 	Copyright (C) 2000-2003 Broadcom Corporation.
+ *	Derived from proprietary unpublished source code,
+ *	Copyright (C) 2000-2003 Broadcom Corporation.
+ *
+ *	Permission is hereby granted for the distribution of this firmware
+ *	data in hexadecimal or equivalent format, provided this copyright
+ *	notice is accompanying it.
  */
 
 #include <linux/config.h>
@@ -61,8 +66,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.29"
-#define DRV_MODULE_RELDATE	"May 23, 2005"
+#define DRV_MODULE_VERSION	"3.32"
+#define DRV_MODULE_RELDATE	"June 24, 2005"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -332,12 +337,10 @@
 static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val)
 {
 	if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) {
-		unsigned long flags;
-
-		spin_lock_irqsave(&tp->indirect_lock, flags);
+		spin_lock_bh(&tp->indirect_lock);
 		pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
 		pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
-		spin_unlock_irqrestore(&tp->indirect_lock, flags);
+		spin_unlock_bh(&tp->indirect_lock);
 	} else {
 		writel(val, tp->regs + off);
 		if ((tp->tg3_flags & TG3_FLAG_5701_REG_WRITE_BUG) != 0)
@@ -348,12 +351,10 @@
 static void _tw32_flush(struct tg3 *tp, u32 off, u32 val)
 {
 	if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0) {
-		unsigned long flags;
-
-		spin_lock_irqsave(&tp->indirect_lock, flags);
+		spin_lock_bh(&tp->indirect_lock);
 		pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
 		pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
-		spin_unlock_irqrestore(&tp->indirect_lock, flags);
+		spin_unlock_bh(&tp->indirect_lock);
 	} else {
 		void __iomem *dest = tp->regs + off;
 		writel(val, dest);
@@ -393,28 +394,24 @@
 
 static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&tp->indirect_lock, flags);
+	spin_lock_bh(&tp->indirect_lock);
 	pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
 	pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
 
 	/* Always leave this as zero. */
 	pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
-	spin_unlock_irqrestore(&tp->indirect_lock, flags);
+	spin_unlock_bh(&tp->indirect_lock);
 }
 
 static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&tp->indirect_lock, flags);
+	spin_lock_bh(&tp->indirect_lock);
 	pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
 	pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
 
 	/* Always leave this as zero. */
 	pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
-	spin_unlock_irqrestore(&tp->indirect_lock, flags);
+	spin_unlock_bh(&tp->indirect_lock);
 }
 
 static void tg3_disable_ints(struct tg3 *tp)
@@ -433,12 +430,14 @@
 
 static void tg3_enable_ints(struct tg3 *tp)
 {
+	tp->irq_sync = 0;
+	wmb();
+
 	tw32(TG3PCI_MISC_HOST_CTRL,
 	     (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
 	tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
 		     (tp->last_tag << 24));
 	tr32(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW);
-
 	tg3_cond_int(tp);
 }
 
@@ -487,6 +486,7 @@
 
 static inline void tg3_netif_stop(struct tg3 *tp)
 {
+	tp->dev->trans_start = jiffies;	/* prevent tx timeout */
 	netif_poll_disable(tp->dev);
 	netif_tx_disable(tp->dev);
 }
@@ -499,7 +499,8 @@
 	 * (such as after tg3_init_hw)
 	 */
 	netif_poll_enable(tp->dev);
-	tg3_cond_int(tp);
+	tp->hw_status->status |= SD_STATUS_UPDATED;
+	tg3_enable_ints(tp);
 }
 
 static void tg3_switch_clocks(struct tg3 *tp)
@@ -2573,7 +2574,7 @@
 			sw_idx = NEXT_TX(sw_idx);
 		}
 
-		dev_kfree_skb_irq(skb);
+		dev_kfree_skb(skb);
 	}
 
 	tp->tx_cons = sw_idx;
@@ -2879,11 +2880,8 @@
 {
 	struct tg3 *tp = netdev_priv(netdev);
 	struct tg3_hw_status *sblk = tp->hw_status;
-	unsigned long flags;
 	int done;
 
-	spin_lock_irqsave(&tp->lock, flags);
-
 	/* handle link change and other phy events */
 	if (!(tp->tg3_flags &
 	      (TG3_FLAG_USE_LINKCHG_REG |
@@ -2891,7 +2889,9 @@
 		if (sblk->status & SD_STATUS_LINK_CHG) {
 			sblk->status = SD_STATUS_UPDATED |
 				(sblk->status & ~SD_STATUS_LINK_CHG);
+			spin_lock(&tp->lock);
 			tg3_setup_phy(tp, 0);
+			spin_unlock(&tp->lock);
 		}
 	}
 
@@ -2902,8 +2902,6 @@
 		spin_unlock(&tp->tx_lock);
 	}
 
-	spin_unlock_irqrestore(&tp->lock, flags);
-
 	/* run RX thread, within the bounds set by NAPI.
 	 * All RX "locking" is done by ensuring outside
 	 * code synchronizes with dev->poll()
@@ -2924,19 +2922,54 @@
 	if (tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)
 		tp->last_tag = sblk->status_tag;
 	rmb();
+	sblk->status &= ~SD_STATUS_UPDATED;
 
 	/* if no more work, tell net stack and NIC we're done */
 	done = !tg3_has_work(tp);
 	if (done) {
-		spin_lock_irqsave(&tp->lock, flags);
-		__netif_rx_complete(netdev);
+		spin_lock(&tp->lock);
+		netif_rx_complete(netdev);
 		tg3_restart_ints(tp);
-		spin_unlock_irqrestore(&tp->lock, flags);
+		spin_unlock(&tp->lock);
 	}
 
 	return (done ? 0 : 1);
 }
 
+static void tg3_irq_quiesce(struct tg3 *tp)
+{
+	BUG_ON(tp->irq_sync);
+
+	tp->irq_sync = 1;
+	smp_mb();
+
+	synchronize_irq(tp->pdev->irq);
+}
+
+static inline int tg3_irq_sync(struct tg3 *tp)
+{
+	return tp->irq_sync;
+}
+
+/* Fully shutdown all tg3 driver activity elsewhere in the system.
+ * If irq_sync is non-zero, then the IRQ handler must be synchronized
+ * with as well.  Most of the time, this is not necessary except when
+ * shutting down the device.
+ */
+static inline void tg3_full_lock(struct tg3 *tp, int irq_sync)
+{
+	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);
+}
+
 /* MSI ISR - No need to check for interrupt sharing and no need to
  * flush status block and interrupt mailbox. PCI ordering rules
  * guarantee that MSI will arrive after the status block.
@@ -2946,9 +2979,6 @@
 	struct net_device *dev = dev_id;
 	struct tg3 *tp = netdev_priv(dev);
 	struct tg3_hw_status *sblk = tp->hw_status;
-	unsigned long flags;
-
-	spin_lock_irqsave(&tp->lock, flags);
 
 	/*
 	 * Writing any value to intr-mbox-0 clears PCI INTA# and
@@ -2959,6 +2989,9 @@
 	 */
 	tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
 	tp->last_tag = sblk->status_tag;
+	rmb();
+	if (tg3_irq_sync(tp))
+		goto out;
 	sblk->status &= ~SD_STATUS_UPDATED;
 	if (likely(tg3_has_work(tp)))
 		netif_rx_schedule(dev);		/* schedule NAPI poll */
@@ -2967,9 +3000,7 @@
 		tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
 			     tp->last_tag << 24);
 	}
-
-	spin_unlock_irqrestore(&tp->lock, flags);
-
+out:
 	return IRQ_RETVAL(1);
 }
 
@@ -2978,11 +3009,8 @@
 	struct net_device *dev = dev_id;
 	struct tg3 *tp = netdev_priv(dev);
 	struct tg3_hw_status *sblk = tp->hw_status;
-	unsigned long flags;
 	unsigned int handled = 1;
 
-	spin_lock_irqsave(&tp->lock, flags);
-
 	/* In INTx mode, it is possible for the interrupt to arrive at
 	 * the CPU before the status block posted prior to the interrupt.
 	 * Reading the PCI State register will confirm whether the
@@ -2999,6 +3027,8 @@
 		 */
 		tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
 			     0x00000001);
+		if (tg3_irq_sync(tp))
+			goto out;
 		sblk->status &= ~SD_STATUS_UPDATED;
 		if (likely(tg3_has_work(tp)))
 			netif_rx_schedule(dev);		/* schedule NAPI poll */
@@ -3013,9 +3043,7 @@
 	} else {	/* shared interrupt */
 		handled = 0;
 	}
-
-	spin_unlock_irqrestore(&tp->lock, flags);
-
+out:
 	return IRQ_RETVAL(handled);
 }
 
@@ -3024,11 +3052,8 @@
 	struct net_device *dev = dev_id;
 	struct tg3 *tp = netdev_priv(dev);
 	struct tg3_hw_status *sblk = tp->hw_status;
-	unsigned long flags;
 	unsigned int handled = 1;
 
-	spin_lock_irqsave(&tp->lock, flags);
-
 	/* In INTx mode, it is possible for the interrupt to arrive at
 	 * the CPU before the status block posted prior to the interrupt.
 	 * Reading the PCI State register will confirm whether the
@@ -3046,6 +3071,9 @@
 		tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW,
 			     0x00000001);
 		tp->last_tag = sblk->status_tag;
+		rmb();
+		if (tg3_irq_sync(tp))
+			goto out;
 		sblk->status &= ~SD_STATUS_UPDATED;
 		if (likely(tg3_has_work(tp)))
 			netif_rx_schedule(dev);		/* schedule NAPI poll */
@@ -3060,9 +3088,7 @@
 	} else {	/* shared interrupt */
 		handled = 0;
 	}
-
-	spin_unlock_irqrestore(&tp->lock, flags);
-
+out:
 	return IRQ_RETVAL(handled);
 }
 
@@ -3101,8 +3127,7 @@
 
 	tg3_netif_stop(tp);
 
-	spin_lock_irq(&tp->lock);
-	spin_lock(&tp->tx_lock);
+	tg3_full_lock(tp, 1);
 
 	restart_timer = tp->tg3_flags2 & TG3_FLG2_RESTART_TIMER;
 	tp->tg3_flags2 &= ~TG3_FLG2_RESTART_TIMER;
@@ -3112,8 +3137,7 @@
 
 	tg3_netif_start(tp);
 
-	spin_unlock(&tp->tx_lock);
-	spin_unlock_irq(&tp->lock);
+	tg3_full_unlock(tp);
 
 	if (restart_timer)
 		mod_timer(&tp->timer, jiffies + 1);
@@ -3219,39 +3243,21 @@
 	unsigned int i;
 	u32 len, entry, base_flags, mss;
 	int would_hit_hwbug;
-	unsigned long flags;
 
 	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
-	 * interrupt.  Rejoice!
-	 *
-	 * Actually, things are not so simple.  If we are to take a hw
-	 * IRQ here, we can deadlock, consider:
-	 *
-	 *       CPU1		CPU2
-	 *   tg3_start_xmit
-	 *   take tp->tx_lock
-	 *			tg3_timer
-	 *			take tp->lock
-	 *   tg3_interrupt
-	 *   spin on tp->lock
-	 *			spin on tp->tx_lock
-	 *
-	 * So we really do need to disable interrupts when taking
-	 * tx_lock here.
+	 * interrupt.  Furthermore, IRQ processing runs lockless so we have
+	 * no IRQ context deadlocks to worry about either.  Rejoice!
 	 */
-	local_irq_save(flags);
-	if (!spin_trylock(&tp->tx_lock)) { 
-		local_irq_restore(flags);
+	if (!spin_trylock(&tp->tx_lock))
 		return NETDEV_TX_LOCKED; 
-	} 
 
 	/* This is a hard error, log it. */
 	if (unlikely(TX_BUFFS_AVAIL(tp) <= (skb_shinfo(skb)->nr_frags + 1))) {
 		netif_stop_queue(dev);
-		spin_unlock_irqrestore(&tp->tx_lock, flags);
+		spin_unlock(&tp->tx_lock);
 		printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
 		       dev->name);
 		return NETDEV_TX_BUSY;
@@ -3416,7 +3422,7 @@
 
 out_unlock:
     	mmiowb();
-	spin_unlock_irqrestore(&tp->tx_lock, flags);
+	spin_unlock(&tp->tx_lock);
 
 	dev->trans_start = jiffies;
 
@@ -3450,8 +3456,8 @@
 	}
 
 	tg3_netif_stop(tp);
-	spin_lock_irq(&tp->lock);
-	spin_lock(&tp->tx_lock);
+
+	tg3_full_lock(tp, 1);
 
 	tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
 
@@ -3461,8 +3467,7 @@
 
 	tg3_netif_start(tp);
 
-	spin_unlock(&tp->tx_lock);
-	spin_unlock_irq(&tp->lock);
+	tg3_full_unlock(tp);
 
 	return 0;
 }
@@ -5083,9 +5088,9 @@
 
 	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
 
-	spin_lock_irq(&tp->lock);
+	spin_lock_bh(&tp->lock);
 	__tg3_set_mac_addr(tp);
-	spin_unlock_irq(&tp->lock);
+	spin_unlock_bh(&tp->lock);
 
 	return 0;
 }
@@ -5722,9 +5727,6 @@
 
 	tg3_write_sig_post_reset(tp, RESET_KIND_INIT);
 
-	if (tp->tg3_flags & TG3_FLAG_INIT_COMPLETE)
-		tg3_enable_ints(tp);
-
 	return 0;
 }
 
@@ -5797,10 +5799,8 @@
 static void tg3_timer(unsigned long __opaque)
 {
 	struct tg3 *tp = (struct tg3 *) __opaque;
-	unsigned long flags;
 
-	spin_lock_irqsave(&tp->lock, flags);
-	spin_lock(&tp->tx_lock);
+	spin_lock(&tp->lock);
 
 	if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) {
 		/* All of this garbage is because when using non-tagged
@@ -5817,8 +5817,7 @@
 
 		if (!(tr32(WDMAC_MODE) & WDMAC_MODE_ENABLE)) {
 			tp->tg3_flags2 |= TG3_FLG2_RESTART_TIMER;
-			spin_unlock(&tp->tx_lock);
-			spin_unlock_irqrestore(&tp->lock, flags);
+			spin_unlock(&tp->lock);
 			schedule_work(&tp->reset_task);
 			return;
 		}
@@ -5886,8 +5885,7 @@
 		tp->asf_counter = tp->asf_multiplier;
 	}
 
-	spin_unlock(&tp->tx_lock);
-	spin_unlock_irqrestore(&tp->lock, flags);
+	spin_unlock(&tp->lock);
 
 	tp->timer.expires = jiffies + tp->timer_offset;
 	add_timer(&tp->timer);
@@ -6002,14 +6000,12 @@
 	/* Need to reset the chip because the MSI cycle may have terminated
 	 * with Master Abort.
 	 */
-	spin_lock_irq(&tp->lock);
-	spin_lock(&tp->tx_lock);
+	tg3_full_lock(tp, 1);
 
 	tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
 	err = tg3_init_hw(tp);
 
-	spin_unlock(&tp->tx_lock);
-	spin_unlock_irq(&tp->lock);
+	tg3_full_unlock(tp);
 
 	if (err)
 		free_irq(tp->pdev->irq, dev);
@@ -6022,14 +6018,12 @@
 	struct tg3 *tp = netdev_priv(dev);
 	int err;
 
-	spin_lock_irq(&tp->lock);
-	spin_lock(&tp->tx_lock);
+	tg3_full_lock(tp, 0);
 
 	tg3_disable_ints(tp);
 	tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
 
-	spin_unlock(&tp->tx_lock);
-	spin_unlock_irq(&tp->lock);
+	tg3_full_unlock(tp);
 
 	/* The placement of this call is tied
 	 * to the setup and use of Host TX descriptors.
@@ -6076,8 +6070,7 @@
 		return err;
 	}
 
-	spin_lock_irq(&tp->lock);
-	spin_lock(&tp->tx_lock);
+	tg3_full_lock(tp, 0);
 
 	err = tg3_init_hw(tp);
 	if (err) {
@@ -6101,8 +6094,7 @@
 		tp->timer.function = tg3_timer;
 	}
 
-	spin_unlock(&tp->tx_lock);
-	spin_unlock_irq(&tp->lock);
+	tg3_full_unlock(tp);
 
 	if (err) {
 		free_irq(tp->pdev->irq, dev);
@@ -6118,8 +6110,7 @@
 		err = tg3_test_msi(tp);
 
 		if (err) {
-			spin_lock_irq(&tp->lock);
-			spin_lock(&tp->tx_lock);
+			tg3_full_lock(tp, 0);
 
 			if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
 				pci_disable_msi(tp->pdev);
@@ -6129,22 +6120,19 @@
 			tg3_free_rings(tp);
 			tg3_free_consistent(tp);
 
-			spin_unlock(&tp->tx_lock);
-			spin_unlock_irq(&tp->lock);
+			tg3_full_unlock(tp);
 
 			return err;
 		}
 	}
 
-	spin_lock_irq(&tp->lock);
-	spin_lock(&tp->tx_lock);
+	tg3_full_lock(tp, 0);
 
 	add_timer(&tp->timer);
 	tp->tg3_flags |= TG3_FLAG_INIT_COMPLETE;
 	tg3_enable_ints(tp);
 
-	spin_unlock(&tp->tx_lock);
-	spin_unlock_irq(&tp->lock);
+	tg3_full_unlock(tp);
 
 	netif_start_queue(dev);
 
@@ -6390,8 +6378,7 @@
 
 	del_timer_sync(&tp->timer);
 
-	spin_lock_irq(&tp->lock);
-	spin_lock(&tp->tx_lock);
+	tg3_full_lock(tp, 1);
 #if 0
 	tg3_dump_state(tp);
 #endif
@@ -6405,8 +6392,7 @@
 		  TG3_FLAG_GOT_SERDES_FLOWCTL);
 	netif_carrier_off(tp->dev);
 
-	spin_unlock(&tp->tx_lock);
-	spin_unlock_irq(&tp->lock);
+	tg3_full_unlock(tp);
 
 	free_irq(tp->pdev->irq, dev);
 	if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
@@ -6443,16 +6429,15 @@
 	if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) &&
 	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
 	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) {
-		unsigned long flags;
 		u32 val;
 
-		spin_lock_irqsave(&tp->lock, flags);
+		spin_lock_bh(&tp->lock);
 		if (!tg3_readphy(tp, 0x1e, &val)) {
 			tg3_writephy(tp, 0x1e, val | 0x8000);
 			tg3_readphy(tp, 0x14, &val);
 		} else
 			val = 0;
-		spin_unlock_irqrestore(&tp->lock, flags);
+		spin_unlock_bh(&tp->lock);
 
 		tp->phy_crc_errors += val;
 
@@ -6714,11 +6699,9 @@
 {
 	struct tg3 *tp = netdev_priv(dev);
 
-	spin_lock_irq(&tp->lock);
-	spin_lock(&tp->tx_lock);
+	tg3_full_lock(tp, 0);
 	__tg3_set_rx_mode(dev);
-	spin_unlock(&tp->tx_lock);
-	spin_unlock_irq(&tp->lock);
+	tg3_full_unlock(tp);
 }
 
 #define TG3_REGDUMP_LEN		(32 * 1024)
@@ -6740,8 +6723,7 @@
 
 	memset(p, 0, TG3_REGDUMP_LEN);
 
-	spin_lock_irq(&tp->lock);
-	spin_lock(&tp->tx_lock);
+	tg3_full_lock(tp, 0);
 
 #define __GET_REG32(reg)	(*(p)++ = tr32(reg))
 #define GET_REG32_LOOP(base,len)		\
@@ -6791,8 +6773,7 @@
 #undef GET_REG32_LOOP
 #undef GET_REG32_1
 
-	spin_unlock(&tp->tx_lock);
-	spin_unlock_irq(&tp->lock);
+	tg3_full_unlock(tp);
 }
 
 static int tg3_get_eeprom_len(struct net_device *dev)
@@ -6968,8 +6949,7 @@
 			return -EINVAL;
 	}
 
-	spin_lock_irq(&tp->lock);
-	spin_lock(&tp->tx_lock);
+	tg3_full_lock(tp, 0);
 
 	tp->link_config.autoneg = cmd->autoneg;
 	if (cmd->autoneg == AUTONEG_ENABLE) {
@@ -6985,8 +6965,7 @@
 	if (netif_running(dev))
 		tg3_setup_phy(tp, 1);
 
-	spin_unlock(&tp->tx_lock);
-	spin_unlock_irq(&tp->lock);
+	tg3_full_unlock(tp);
   
 	return 0;
 }
@@ -7022,12 +7001,12 @@
 	    !(tp->tg3_flags & TG3_FLAG_SERDES_WOL_CAP))
 		return -EINVAL;
   
-	spin_lock_irq(&tp->lock);
+	spin_lock_bh(&tp->lock);
 	if (wol->wolopts & WAKE_MAGIC)
 		tp->tg3_flags |= TG3_FLAG_WOL_ENABLE;
 	else
 		tp->tg3_flags &= ~TG3_FLAG_WOL_ENABLE;
-	spin_unlock_irq(&tp->lock);
+	spin_unlock_bh(&tp->lock);
   
 	return 0;
 }
@@ -7067,7 +7046,7 @@
 	if (!netif_running(dev))
 		return -EAGAIN;
 
-	spin_lock_irq(&tp->lock);
+	spin_lock_bh(&tp->lock);
 	r = -EINVAL;
 	tg3_readphy(tp, MII_BMCR, &bmcr);
 	if (!tg3_readphy(tp, MII_BMCR, &bmcr) &&
@@ -7075,7 +7054,7 @@
 		tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART);
 		r = 0;
 	}
-	spin_unlock_irq(&tp->lock);
+	spin_unlock_bh(&tp->lock);
   
 	return r;
 }
@@ -7097,17 +7076,19 @@
 static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
 {
 	struct tg3 *tp = netdev_priv(dev);
+	int irq_sync = 0;
   
 	if ((ering->rx_pending > TG3_RX_RING_SIZE - 1) ||
 	    (ering->rx_jumbo_pending > TG3_RX_JUMBO_RING_SIZE - 1) ||
 	    (ering->tx_pending > TG3_TX_RING_SIZE - 1))
 		return -EINVAL;
   
-	if (netif_running(dev))
+	if (netif_running(dev)) {
 		tg3_netif_stop(tp);
+		irq_sync = 1;
+	}
 
-	spin_lock_irq(&tp->lock);
-	spin_lock(&tp->tx_lock);
+	tg3_full_lock(tp, irq_sync);
   
 	tp->rx_pending = ering->rx_pending;
 
@@ -7123,8 +7104,7 @@
 		tg3_netif_start(tp);
 	}
 
-	spin_unlock(&tp->tx_lock);
-	spin_unlock_irq(&tp->lock);
+	tg3_full_unlock(tp);
   
 	return 0;
 }
@@ -7141,12 +7121,15 @@
 static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
 {
 	struct tg3 *tp = netdev_priv(dev);
+	int irq_sync = 0;
   
-	if (netif_running(dev))
+	if (netif_running(dev)) {
 		tg3_netif_stop(tp);
+		irq_sync = 1;
+	}
 
-	spin_lock_irq(&tp->lock);
-	spin_lock(&tp->tx_lock);
+	tg3_full_lock(tp, irq_sync);
+
 	if (epause->autoneg)
 		tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
 	else
@@ -7165,8 +7148,8 @@
 		tg3_init_hw(tp);
 		tg3_netif_start(tp);
 	}
-	spin_unlock(&tp->tx_lock);
-	spin_unlock_irq(&tp->lock);
+
+	tg3_full_unlock(tp);
   
 	return 0;
 }
@@ -7187,12 +7170,12 @@
   		return 0;
   	}
   
-	spin_lock_irq(&tp->lock);
+	spin_lock_bh(&tp->lock);
 	if (data)
 		tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS;
 	else
 		tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS;
-	spin_unlock_irq(&tp->lock);
+	spin_unlock_bh(&tp->lock);
   
 	return 0;
 }
@@ -7601,8 +7584,6 @@
 
 	tg3_abort_hw(tp, 1);
 
-	/* Clearing this flag to keep interrupts disabled */
-	tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE;
 	tg3_reset_hw(tp);
 
 	mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
@@ -7711,11 +7692,14 @@
 		data[1] = 1;
 	}
 	if (etest->flags & ETH_TEST_FL_OFFLINE) {
-		if (netif_running(dev))
-			tg3_netif_stop(tp);
+		int irq_sync = 0;
 
-		spin_lock_irq(&tp->lock);
-		spin_lock(&tp->tx_lock);
+		if (netif_running(dev)) {
+			tg3_netif_stop(tp);
+			irq_sync = 1;
+		}
+
+		tg3_full_lock(tp, irq_sync);
 
 		tg3_halt(tp, RESET_KIND_SUSPEND, 1);
 		tg3_nvram_lock(tp);
@@ -7737,14 +7721,14 @@
 			data[4] = 1;
 		}
 
-		spin_unlock(&tp->tx_lock);
-		spin_unlock_irq(&tp->lock);
+		tg3_full_unlock(tp);
+
 		if (tg3_test_interrupt(tp) != 0) {
 			etest->flags |= ETH_TEST_FL_FAILED;
 			data[5] = 1;
 		}
-		spin_lock_irq(&tp->lock);
-		spin_lock(&tp->tx_lock);
+
+		tg3_full_lock(tp, 0);
 
 		tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
 		if (netif_running(dev)) {
@@ -7752,8 +7736,8 @@
 			tg3_init_hw(tp);
 			tg3_netif_start(tp);
 		}
-		spin_unlock(&tp->tx_lock);
-		spin_unlock_irq(&tp->lock);
+
+		tg3_full_unlock(tp);
 	}
 }
 
@@ -7774,9 +7758,9 @@
 		if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
 			break;			/* We have no PHY */
 
-		spin_lock_irq(&tp->lock);
+		spin_lock_bh(&tp->lock);
 		err = tg3_readphy(tp, data->reg_num & 0x1f, &mii_regval);
-		spin_unlock_irq(&tp->lock);
+		spin_unlock_bh(&tp->lock);
 
 		data->val_out = mii_regval;
 
@@ -7790,9 +7774,9 @@
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 
-		spin_lock_irq(&tp->lock);
+		spin_lock_bh(&tp->lock);
 		err = tg3_writephy(tp, data->reg_num & 0x1f, data->val_in);
-		spin_unlock_irq(&tp->lock);
+		spin_unlock_bh(&tp->lock);
 
 		return err;
 
@@ -7808,28 +7792,24 @@
 {
 	struct tg3 *tp = netdev_priv(dev);
 
-	spin_lock_irq(&tp->lock);
-	spin_lock(&tp->tx_lock);
+	tg3_full_lock(tp, 0);
 
 	tp->vlgrp = grp;
 
 	/* Update RX_MODE_KEEP_VLAN_TAG bit in RX_MODE register. */
 	__tg3_set_rx_mode(dev);
 
-	spin_unlock(&tp->tx_lock);
-	spin_unlock_irq(&tp->lock);
+	tg3_full_unlock(tp);
 }
 
 static void tg3_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 {
 	struct tg3 *tp = netdev_priv(dev);
 
-	spin_lock_irq(&tp->lock);
-	spin_lock(&tp->tx_lock);
+	tg3_full_lock(tp, 0);
 	if (tp->vlgrp)
 		tp->vlgrp->vlan_devices[vid] = NULL;
-	spin_unlock(&tp->tx_lock);
-	spin_unlock_irq(&tp->lock);
+	tg3_full_unlock(tp);
 }
 #endif
 
@@ -8555,6 +8535,16 @@
 
 		case NIC_SRAM_DATA_CFG_LED_MODE_MAC:
 			tp->led_ctrl = LED_CTRL_MODE_MAC;
+
+			/* Default to PHY_1_MODE if 0 (MAC_MODE) is
+			 * read on some older 5700/5701 bootcode.
+			 */
+			if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
+			    ASIC_REV_5700 ||
+			    GET_ASIC_REV(tp->pci_chip_rev_id) ==
+			    ASIC_REV_5701)
+				tp->led_ctrl = LED_CTRL_MODE_PHY_1;
+
 			break;
 
 		case SHASTA_EXT_LED_SHARED:
@@ -9680,10 +9670,24 @@
 	}
 	if ((tp->dma_rwctrl & DMA_RWCTRL_WRITE_BNDRY_MASK) !=
 	    DMA_RWCTRL_WRITE_BNDRY_16) {
+		static struct pci_device_id dma_wait_state_chipsets[] = {
+			{ PCI_DEVICE(PCI_VENDOR_ID_APPLE,
+				     PCI_DEVICE_ID_APPLE_UNI_N_PCI15) },
+			{ },
+		};
+
 		/* DMA test passed without adjusting DMA boundary,
-		 * just restore the calculated DMA boundary
+		 * now look for chipsets that are known to expose the
+		 * DMA bug without failing the test.
 		 */
-		tp->dma_rwctrl = saved_dma_rwctrl;
+		if (pci_dev_present(dma_wait_state_chipsets)) {
+			tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK;
+			tp->dma_rwctrl |= DMA_RWCTRL_WRITE_BNDRY_16;
+		}
+		else
+			/* Safe to use the calculated DMA boundary. */
+			tp->dma_rwctrl = saved_dma_rwctrl;
+
 		tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl);
 	}
 
@@ -10136,24 +10140,19 @@
 
 	del_timer_sync(&tp->timer);
 
-	spin_lock_irq(&tp->lock);
-	spin_lock(&tp->tx_lock);
+	tg3_full_lock(tp, 1);
 	tg3_disable_ints(tp);
-	spin_unlock(&tp->tx_lock);
-	spin_unlock_irq(&tp->lock);
+	tg3_full_unlock(tp);
 
 	netif_device_detach(dev);
 
-	spin_lock_irq(&tp->lock);
-	spin_lock(&tp->tx_lock);
+	tg3_full_lock(tp, 0);
 	tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
-	spin_unlock(&tp->tx_lock);
-	spin_unlock_irq(&tp->lock);
+	tg3_full_unlock(tp);
 
 	err = tg3_set_power_state(tp, pci_choose_state(pdev, state));
 	if (err) {
-		spin_lock_irq(&tp->lock);
-		spin_lock(&tp->tx_lock);
+		tg3_full_lock(tp, 0);
 
 		tg3_init_hw(tp);
 
@@ -10163,8 +10162,7 @@
 		netif_device_attach(dev);
 		tg3_netif_start(tp);
 
-		spin_unlock(&tp->tx_lock);
-		spin_unlock_irq(&tp->lock);
+		tg3_full_unlock(tp);
 	}
 
 	return err;
@@ -10187,20 +10185,16 @@
 
 	netif_device_attach(dev);
 
-	spin_lock_irq(&tp->lock);
-	spin_lock(&tp->tx_lock);
+	tg3_full_lock(tp, 0);
 
 	tg3_init_hw(tp);
 
 	tp->timer.expires = jiffies + tp->timer_offset;
 	add_timer(&tp->timer);
 
-	tg3_enable_ints(tp);
-
 	tg3_netif_start(tp);
 
-	spin_unlock(&tp->tx_lock);
-	spin_unlock_irq(&tp->lock);
+	tg3_full_unlock(tp);
 
 	return 0;
 }
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index 993f84c..99c5f96 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -2006,17 +2006,31 @@
 struct tg3 {
 	/* begin "general, frequently-used members" cacheline section */
 
+	/* If the IRQ handler (which runs lockless) needs to be
+	 * quiesced, the following bitmask state is used.  The
+	 * SYNC flag is set by non-IRQ context code to initiate
+	 * the quiescence.
+	 *
+	 * When the IRQ handler notices that SYNC is set, it
+	 * disables interrupts and returns.
+	 *
+	 * When all outstanding IRQ handlers have returned after
+	 * the SYNC flag has been set, the setter can be assured
+	 * that interrupts will no longer get run.
+	 *
+	 * In this way all SMP driver locks are never acquired
+	 * in hw IRQ context, only sw IRQ context or lower.
+	 */
+	unsigned int			irq_sync;
+
 	/* SMP locking strategy:
 	 *
 	 * lock: Held during all operations except TX packet
 	 *       processing.
 	 *
-	 * tx_lock: Held during tg3_start_xmit{,_4gbug} and tg3_tx
+	 * tx_lock: Held during tg3_start_xmit and tg3_tx
 	 *
-	 * If you want to shut up all asynchronous processing you must
-	 * acquire both locks, 'lock' taken before 'tx_lock'.  IRQs must
-	 * be disabled to take 'lock' but only softirq disabling is
-	 * necessary for acquisition of 'tx_lock'.
+	 * Both of these locks are to be held with BH safety.
 	 */
 	spinlock_t			lock;
 	spinlock_t			indirect_lock;
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index 9680a30..942fae0 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -171,6 +171,7 @@
 #include <linux/ioport.h>
 #include <linux/eisa.h>
 #include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
@@ -566,7 +567,7 @@
 
 		priv->adapter = &board_info[ent->driver_data];
 
-		rc = pci_set_dma_mask(pdev, 0xFFFFFFFF);
+		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
 		if (rc) {
 			printk(KERN_ERR "TLAN: No suitable PCI mapping available.\n");
 			goto err_out_free_dev;
@@ -2819,7 +2820,7 @@
  	       if (priv->link) {
 		      priv->link = 0;
 	              printk(KERN_DEBUG "TLAN: %s has lost link\n", dev->name);
-	              dev->flags &= ~IFF_RUNNING;
+		      netif_carrier_off(dev);
 		      TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_LINK_BEAT );
 		      return;
 		}
@@ -2829,7 +2830,7 @@
         if ((phy_status & MII_GS_LINK) && !priv->link) {
  		priv->link = 1;
         	printk(KERN_DEBUG "TLAN: %s has reestablished link\n", dev->name);
-        	dev->flags |= IFF_RUNNING;
+		netif_carrier_on(dev);
         }
 
 	/* Setup a new monitor */
diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c
index 0d1dcf4..41e0cd8 100644
--- a/drivers/net/tokenring/3c359.c
+++ b/drivers/net/tokenring/3c359.c
@@ -276,7 +276,8 @@
 	return ; 
 }
  
-int __devinit xl_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 
+static int __devinit xl_probe(struct pci_dev *pdev,
+			      const struct pci_device_id *ent) 
 {
 	struct net_device *dev ; 
 	struct xl_private *xl_priv ; 
diff --git a/drivers/net/tokenring/3c359_microcode.h b/drivers/net/tokenring/3c359_microcode.h
index 81354af..0400c02 100644
--- a/drivers/net/tokenring/3c359_microcode.h
+++ b/drivers/net/tokenring/3c359_microcode.h
@@ -22,7 +22,7 @@
 
 static int mc_size = 24880 ; 
 
-u8 microcode[] = { 
+static const u8 microcode[] = { 
  0xfe,0x3a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
 ,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
diff --git a/drivers/net/tokenring/abyss.c b/drivers/net/tokenring/abyss.c
index bd4a2bc..87103c4 100644
--- a/drivers/net/tokenring/abyss.c
+++ b/drivers/net/tokenring/abyss.c
@@ -468,14 +468,3 @@
 module_init(abyss_init);
 module_exit(abyss_rmmod);
 
-
-/*
- * Local variables:
- *  compile-command: "gcc -DMODVERSIONS  -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c abyss.c"
- *  alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c abyss.c"
- *  c-set-style "K&R"
- *  c-indent-level: 8
- *  c-basic-offset: 8
- *  tab-width: 8
- * End:
- */
diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
index c098863..e7b0010 100644
--- a/drivers/net/tokenring/ibmtr.c
+++ b/drivers/net/tokenring/ibmtr.c
@@ -151,7 +151,7 @@
 
 /* this allows displaying full adapter information */
 
-char *channel_def[] __devinitdata = { "ISA", "MCA", "ISA P&P" };
+static char *channel_def[] __devinitdata = { "ISA", "MCA", "ISA P&P" };
 
 static char pcchannelid[] __devinitdata = {
 	0x05, 0x00, 0x04, 0x09,
@@ -171,7 +171,7 @@
 	0x03, 0x08, 0x02, 0x00
 };
 
-char __devinit *adapter_def(char type)
+static char __devinit *adapter_def(char type)
 {
 	switch (type) {
 	case 0xF: return "PC Adapter | PC Adapter II | Adapter/A";
@@ -184,7 +184,7 @@
 
 #define TRC_INIT 0x01		/*  Trace initialization & PROBEs */
 #define TRC_INITV 0x02		/*  verbose init trace points     */
-unsigned char ibmtr_debug_trace = 0;
+static unsigned char ibmtr_debug_trace = 0;
 
 static int 	ibmtr_probe(struct net_device *dev);
 static int	ibmtr_probe1(struct net_device *dev, int ioaddr);
@@ -192,20 +192,20 @@
 static int 	trdev_init(struct net_device *dev);
 static int 	tok_open(struct net_device *dev);
 static int 	tok_init_card(struct net_device *dev);
-void 		tok_open_adapter(unsigned long dev_addr);
+static void	tok_open_adapter(unsigned long dev_addr);
 static void 	open_sap(unsigned char type, struct net_device *dev);
 static void 	tok_set_multicast_list(struct net_device *dev);
 static int 	tok_send_packet(struct sk_buff *skb, struct net_device *dev);
 static int 	tok_close(struct net_device *dev);
-irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static void 	initial_tok_int(struct net_device *dev);
 static void 	tr_tx(struct net_device *dev);
 static void 	tr_rx(struct net_device *dev);
-void 		ibmtr_reset_timer(struct timer_list*tmr,struct net_device *dev);
+static void	ibmtr_reset_timer(struct timer_list*tmr,struct net_device *dev);
 static void	tok_rerun(unsigned long dev_addr);
-void 		ibmtr_readlog(struct net_device *dev);
+static void	ibmtr_readlog(struct net_device *dev);
 static struct 	net_device_stats *tok_get_stats(struct net_device *dev);
-int 		ibmtr_change_mtu(struct net_device *dev, int mtu);
+static int	ibmtr_change_mtu(struct net_device *dev, int mtu);
 static void	find_turbo_adapters(int *iolist);
 
 static int ibmtr_portlist[IBMTR_MAX_ADAPTERS+1] __devinitdata = {
@@ -888,11 +888,6 @@
 	ti->sap_status   = CLOSED; /* CLOSED or OPEN      */
 	ti->open_failure =     NO; /* NO     or YES       */
 	ti->open_mode    = MANUAL; /* MANUAL or AUTOMATIC */
-	/* 12/2000 not typical Linux, but we can use RUNNING to let us know when
-	the network has crapped out or cables are disconnected. Useful because
-	the IFF_UP flag stays up the whole time, until ifconfig tr0 down.
-	*/
-	dev->flags &= ~IFF_RUNNING;
 
 	ti->sram_phys &= ~1; /* to reverse what we do in tok_close */
 	/* init the spinlock */
@@ -933,7 +928,7 @@
 #define DLC_MAX_SAP_OFST        32
 #define DLC_MAX_STA_OFST        33
 
-void tok_open_adapter(unsigned long dev_addr)
+static void tok_open_adapter(unsigned long dev_addr)
 {
 	struct net_device *dev = (struct net_device *) dev_addr;
 	struct tok_info *ti;
@@ -1104,7 +1099,7 @@
 	return ti->sram_virt + index;
 }
 
-void dir_open_adapter (struct net_device *dev)
+static void dir_open_adapter (struct net_device *dev)
 {
         struct tok_info *ti = (struct tok_info *) dev->priv;
         unsigned char ret_code;
@@ -1177,7 +1172,7 @@
 
 /******************************************************************************/
 
-irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	unsigned char status;
 	/*  unsigned char status_even ; */
@@ -1242,7 +1237,7 @@
 		ti->open_status = CLOSED;
 		ti->sap_status  = CLOSED;
 		ti->open_mode   = AUTOMATIC;
-		dev->flags &= ~IFF_RUNNING;
+		netif_carrier_off(dev);
 		netif_stop_queue(dev);
 		ti->open_action = RESTART;
 		outb(0, dev->base_addr + ADAPTRESET);
@@ -1323,7 +1318,7 @@
 				break;
 			}
 			netif_wake_queue(dev);
-			dev->flags |= IFF_RUNNING;/*BMS 12/2000*/
+			netif_carrier_on(dev);
 			break;
 		case DIR_INTERRUPT:
 		case DIR_MOD_OPEN_PARAMS:
@@ -1427,7 +1422,7 @@
 								ring_status);
 			if(ring_status& (REMOVE_RECV|AUTO_REMOVAL|LOBE_FAULT)){
 				netif_stop_queue(dev);
-				dev->flags &= ~IFF_RUNNING;/*not typical Linux*/
+				netif_carrier_off(dev);
 				DPRINTK("Remove received, or Auto-removal error"
 					", or Lobe fault\n");
 				DPRINTK("We'll try to reopen the closed adapter"
@@ -1845,7 +1840,7 @@
 
 /*****************************************************************************/
 
-void ibmtr_reset_timer(struct timer_list *tmr, struct net_device *dev)
+static void ibmtr_reset_timer(struct timer_list *tmr, struct net_device *dev)
 {
 	tmr->expires = jiffies + TR_RETRY_INTERVAL;
 	tmr->data = (unsigned long) dev;
@@ -1877,7 +1872,7 @@
 
 /*****************************************************************************/
 
-void ibmtr_readlog(struct net_device *dev)
+static void ibmtr_readlog(struct net_device *dev)
 {
 	struct tok_info *ti;
 
@@ -1910,7 +1905,7 @@
 
 /*****************************************************************************/
 
-int ibmtr_change_mtu(struct net_device *dev, int mtu)
+static int ibmtr_change_mtu(struct net_device *dev, int mtu)
 {
 	struct tok_info *ti = (struct tok_info *) dev->priv;
 
diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c
index 99e0b03..6e5ade9 100644
--- a/drivers/net/tokenring/lanstreamer.c
+++ b/drivers/net/tokenring/lanstreamer.c
@@ -118,6 +118,7 @@
 #include <linux/stddef.h>
 #include <linux/init.h>
 #include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include <linux/spinlock.h>
 #include <linux/version.h>
 #include <linux/bitops.h>
@@ -257,7 +258,7 @@
 #endif
 #endif
 
-	rc = pci_set_dma_mask(pdev, 0xFFFFFFFFULL);
+	rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
 	if (rc) {
 		printk(KERN_ERR "%s: No suitable PCI mapping available.\n",
 				dev->name);
diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c
index cfae2bb..659cbdb 100644
--- a/drivers/net/tokenring/madgemc.c
+++ b/drivers/net/tokenring/madgemc.c
@@ -625,7 +625,7 @@
 /*
  * Disable the board, and put back into power-up state.
  */
-void madgemc_chipset_close(struct net_device *dev)
+static void madgemc_chipset_close(struct net_device *dev)
 {
 	/* disable interrupts */
 	madgemc_setint(dev, 0);
@@ -786,15 +786,3 @@
 
 MODULE_LICENSE("GPL");
 
-
-/*
- * Local variables:
- *  compile-command: "gcc -DMODVERSIONS  -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c madgemc.c"
- *  alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c madgemc.c"
- *  c-set-style "K&R"
- *  c-indent-level: 8
- *  c-basic-offset: 8
- *  tab-width: 8
- * End:
- */
-
diff --git a/drivers/net/tokenring/proteon.c b/drivers/net/tokenring/proteon.c
index 675b063..40ad0fd 100644
--- a/drivers/net/tokenring/proteon.c
+++ b/drivers/net/tokenring/proteon.c
@@ -419,14 +419,3 @@
 }
 #endif /* MODULE */
 
-
-/*
- * Local variables:
- *  compile-command: "gcc -DMODVERSIONS  -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c proteon.c"
- *  alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c proteon.c"
- *  c-set-style "K&R"
- *  c-indent-level: 8
- *  c-basic-offset: 8
- *  tab-width: 8
- * End:
- */
diff --git a/drivers/net/tokenring/skisa.c b/drivers/net/tokenring/skisa.c
index 3fab54a..f26796e 100644
--- a/drivers/net/tokenring/skisa.c
+++ b/drivers/net/tokenring/skisa.c
@@ -429,14 +429,3 @@
 }
 #endif /* MODULE */
 
-
-/*
- * Local variables:
- *  compile-command: "gcc -DMODVERSIONS  -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c skisa.c"
- *  alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c skisa.c"
- *  c-set-style "K&R"
- *  c-indent-level: 8
- *  c-basic-offset: 8
- *  tab-width: 8
- * End:
- */
diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c
index 5c8aeac..67d2b59 100644
--- a/drivers/net/tokenring/smctr.c
+++ b/drivers/net/tokenring/smctr.c
@@ -77,7 +77,7 @@
 
 /* SMC Name of the Adapter. */
 static char smctr_name[] = "SMC TokenCard";
-char *smctr_model = "Unknown";
+static char *smctr_model = "Unknown";
 
 /* Use 0 for production, 1 for verification, 2 for debug, and
  * 3 for very verbose debug.
diff --git a/drivers/net/tokenring/smctr_firmware.h b/drivers/net/tokenring/smctr_firmware.h
index 53f2cbc..48994b0 100644
--- a/drivers/net/tokenring/smctr_firmware.h
+++ b/drivers/net/tokenring/smctr_firmware.h
@@ -21,7 +21,7 @@
 
 #if defined(CONFIG_SMCTR) || defined(CONFIG_SMCTR_MODULE)
 
-unsigned char smctr_code[] = {
+static const unsigned char smctr_code[] = {
 	0x0BC, 0x01D, 0x012, 0x03B, 0x063, 0x0B4, 0x0E9, 0x000,
 	0x000, 0x01F, 0x000, 0x001, 0x001, 0x000, 0x002, 0x005,
 	0x001, 0x000, 0x006, 0x003, 0x001, 0x000, 0x004, 0x009,
diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c
index df43b44..5e0b0ce 100644
--- a/drivers/net/tokenring/tms380tr.c
+++ b/drivers/net/tokenring/tms380tr.c
@@ -2379,7 +2379,7 @@
 EXPORT_SYMBOL(tmsdev_term);
 EXPORT_SYMBOL(tms380tr_wait);
 
-struct module *TMS380_module = NULL;
+static struct module *TMS380_module = NULL;
 
 int init_module(void)
 {
@@ -2397,14 +2397,3 @@
 
 MODULE_LICENSE("GPL");
 
-
-/*
- * Local variables:
- *  compile-command: "gcc -DMODVERSIONS  -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c tms380tr.c"
- *  alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c tms380tr.c"
- *  c-set-style "K&R"
- *  c-indent-level: 8
- *  c-basic-offset: 8
- *  tab-width: 8
- * End:
- */
diff --git a/drivers/net/tokenring/tmspci.c b/drivers/net/tokenring/tmspci.c
index 37ddb5c..2e18c0a 100644
--- a/drivers/net/tokenring/tmspci.c
+++ b/drivers/net/tokenring/tmspci.c
@@ -254,14 +254,3 @@
 module_init(tms_pci_init);
 module_exit(tms_pci_rmmod);
 
-
-/*
- * Local variables:
- *  compile-command: "gcc -DMODVERSIONS  -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c tmspci.c"
- *  alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c tmspci.c"
- *  c-set-style "K&R"
- *  c-indent-level: 8
- *  c-basic-offset: 8
- *  tab-width: 8
- * End:
- */
diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c
index e25f33d..7b89970 100644
--- a/drivers/net/tulip/dmfe.c
+++ b/drivers/net/tulip/dmfe.c
@@ -78,6 +78,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -354,7 +355,7 @@
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	if (pci_set_dma_mask(pdev, 0xffffffff)) {
+	if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
 		printk(KERN_WARNING DRV_NAME ": 32-bit PCI DMA not available.\n");
 		err = -ENODEV;
 		goto err_out_free;
@@ -743,11 +744,6 @@
 
 	DMFE_DBUG(0, "dmfe_interrupt()", 0);
 
-	if (!dev) {
-		DMFE_DBUG(1, "dmfe_interrupt() without DEVICE arg", 0);
-		return IRQ_NONE;
-	}
-
 	spin_lock_irqsave(&db->lock, flags);
 
 	/* Got DM910X status */
@@ -1806,7 +1802,7 @@
 	if ( ( (int) srom[18] & 0xff) == SROM_V41_CODE) {
 		/* SROM V4.01 */
 		/* Get NIC support media mode */
-		db->NIC_capability = le16_to_cpup(srom + 34);
+		db->NIC_capability = le16_to_cpup((__le16 *)srom + 34/2);
 		db->PHY_reg4 = 0;
 		for (tmp_reg = 1; tmp_reg < 0x10; tmp_reg <<= 1) {
 			switch( db->NIC_capability & tmp_reg ) {
@@ -1818,7 +1814,8 @@
 		}
 
 		/* Media Mode Force or not check */
-		dmfe_mode = le32_to_cpup(srom + 34) & le32_to_cpup(srom + 36);
+		dmfe_mode = le32_to_cpup((__le32 *)srom + 34/4) &
+				le32_to_cpup((__le32 *)srom + 36/4);
 		switch(dmfe_mode) {
 		case 0x4: dmfe_media_mode = DMFE_100MHF; break;	/* 100MHF */
 		case 0x2: dmfe_media_mode = DMFE_10MFD; break;	/* 10MFD */
diff --git a/drivers/net/tulip/eeprom.c b/drivers/net/tulip/eeprom.c
index ac5bf49..fbd9ab6 100644
--- a/drivers/net/tulip/eeprom.c
+++ b/drivers/net/tulip/eeprom.c
@@ -63,6 +63,22 @@
 	 */
 	{ 0x1e00, 0x0000, 0x000b, 0x8f01, 0x0103, 0x0300, 0x0821, 0x000, 0x0001, 0x0000, 0x01e1 }
   },
+  {"Cobalt Microserver", 0, 0x10, 0xE0, {0x1e00, /* 0 == controller #, 1e == offset	*/
+					 0x0000, /* 0 == high offset, 0 == gap		*/
+					 0x0800, /* Default Autoselect			*/
+					 0x8001, /* 1 leaf, extended type, bogus len	*/
+					 0x0003, /* Type 3 (MII), PHY #0		*/
+					 0x0400, /* 0 init instr, 4 reset instr		*/
+					 0x0801, /* Set control mode, GP0 output	*/
+					 0x0000, /* Drive GP0 Low (RST is active low)	*/
+					 0x0800, /* control mode, GP0 input (undriven)	*/
+					 0x0000, /* clear control mode			*/
+					 0x7800, /* 100TX FDX + HDX, 10bT FDX + HDX	*/
+					 0x01e0, /* Advertise all above			*/
+					 0x5000, /* FDX all above			*/
+					 0x1800, /* Set fast TTM in 100bt modes		*/
+					 0x0000, /* PHY cannot be unplugged		*/
+  }},
   {NULL}};
 
 
diff --git a/drivers/net/tulip/media.c b/drivers/net/tulip/media.c
index 919c40c..e26c31f 100644
--- a/drivers/net/tulip/media.c
+++ b/drivers/net/tulip/media.c
@@ -400,6 +400,9 @@
 	}
 
 	tp->csr6 = new_csr6 | (tp->csr6 & 0xfdff) | (tp->full_duplex ? 0x0200 : 0);
+
+	mdelay(1);
+
 	return;
 }
 
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index e0ae3ed..cfc346e 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -1514,8 +1514,8 @@
                     (PCI_SLOT(pdev->devfn) == 12))) {
                        /* Cobalt MAC address in first EEPROM locations. */
                        sa_offset = 0;
-                       /* No media table either */
-                       tp->flags &= ~HAS_MEDIA_TABLE;
+		       /* Ensure our media table fixup get's applied */
+		       memcpy(ee_data + 16, ee_data, 8);
                }
 #endif
 #ifdef CONFIG_GSC
diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
index caff2f5..db4b32c 100644
--- a/drivers/net/tulip/winbond-840.c
+++ b/drivers/net/tulip/winbond-840.c
@@ -121,6 +121,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
@@ -394,7 +395,7 @@
 
 	irq = pdev->irq;
 
-	if (pci_set_dma_mask(pdev,0xFFFFffff)) {
+	if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
 		printk(KERN_WARNING "Winbond-840: Device %s disabled due to DMA limitations.\n",
 		       pci_name(pdev));
 		return -EIO;
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index 7b57d55..6200cfc 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -186,6 +186,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
@@ -740,7 +741,7 @@
 		goto err_out;
 
 	/* this should always be supported */
-	rc = pci_set_dma_mask(pdev, 0xffffffff);
+	rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
 	if (rc) {
 		printk(KERN_ERR "32-bit PCI DMA addresses not supported by "
 		       "the card!?\n");
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index 66b9466..18c27e1 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -435,7 +435,7 @@
 	  the driver to support.
 
 	  If you have one or more of these cards, say M to this option;
-	  and read <file:Documentation/networking/wanpipe.txt>.
+	  and read <file:Documentation/networking/wan-router.txt>.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called wanpipe.
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 921a573..7ff814f 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -235,7 +235,7 @@
 static int irq[MAX_CARDS+1] = { -1, -1, -1, -1, -1, -1, 0, };
 
 /* for class stuff*/
-static struct class_simple *cosa_class;
+static struct class *cosa_class;
 
 #ifdef MODULE
 module_param_array(io, int, NULL, 0);
@@ -394,19 +394,19 @@
 		goto out;
 	}
 	devfs_mk_dir("cosa");
-	cosa_class = class_simple_create(THIS_MODULE, "cosa");
+	cosa_class = class_create(THIS_MODULE, "cosa");
 	if (IS_ERR(cosa_class)) {
 		err = PTR_ERR(cosa_class);
 		goto out_chrdev;
 	}
 	for (i=0; i<nr_cards; i++) {
-		class_simple_device_add(cosa_class, MKDEV(cosa_major, i),
+		class_device_create(cosa_class, MKDEV(cosa_major, i),
 				NULL, "cosa%d", i);
 		err = devfs_mk_cdev(MKDEV(cosa_major, i),
 				S_IFCHR|S_IRUSR|S_IWUSR,
 				"cosa/%d", i);
 		if (err) {
-			class_simple_device_remove(MKDEV(cosa_major, i));
+			class_device_destroy(cosa_class, MKDEV(cosa_major, i));
 			goto out_chrdev;		
 		}
 	}
@@ -427,10 +427,10 @@
 	printk(KERN_INFO "Unloading the cosa module\n");
 
 	for (i=0; i<nr_cards; i++) {
-		class_simple_device_remove(MKDEV(cosa_major, i));
+		class_device_destroy(cosa_class, MKDEV(cosa_major, i));
 		devfs_remove("cosa/%d", i);
 	}
-	class_simple_destroy(cosa_class);
+	class_destroy(cosa_class);
 	devfs_remove("cosa");
 	for (cosa=cosa_cards; nr_cards--; cosa++) {
 		/* Clean up the per-channel data */
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index 7f450b5..a5d6891 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -2,7 +2,7 @@
  * Generic HDLC support routines for Linux
  * Frame Relay support
  *
- * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 1999 - 2005 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * 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
@@ -27,6 +27,10 @@
  active = open and "link reliable"
  exist = new = not used
 
+ CCITT LMI: ITU-T Q.933 Annex A
+ ANSI LMI: ANSI T1.617 Annex D
+ CISCO LMI: the original, aka "Gang of Four" LMI
+
 */
 
 #include <linux/module.h>
@@ -49,45 +53,41 @@
 #undef DEBUG_ECN
 #undef DEBUG_LINK
 
-#define MAXLEN_LMISTAT  20	/* max size of status enquiry frame */
+#define FR_UI			0x03
+#define FR_PAD			0x00
 
-#define PVC_STATE_NEW	 0x01
-#define PVC_STATE_ACTIVE 0x02
-#define PVC_STATE_FECN	 0x08 /* FECN condition */
-#define PVC_STATE_BECN	 0x10 /* BECN condition */
+#define NLPID_IP		0xCC
+#define NLPID_IPV6		0x8E
+#define NLPID_SNAP		0x80
+#define NLPID_PAD		0x00
+#define NLPID_CCITT_ANSI_LMI	0x08
+#define NLPID_CISCO_LMI		0x09
 
 
-#define FR_UI		 0x03
-#define FR_PAD		 0x00
+#define LMI_CCITT_ANSI_DLCI	   0 /* LMI DLCI */
+#define LMI_CISCO_DLCI		1023
 
-#define NLPID_IP	 0xCC
-#define NLPID_IPV6	 0x8E
-#define NLPID_SNAP	 0x80
-#define NLPID_PAD	 0x00
-#define NLPID_Q933	 0x08
+#define LMI_CALLREF		0x00 /* Call Reference */
+#define LMI_ANSI_LOCKSHIFT	0x95 /* ANSI locking shift */
+#define LMI_ANSI_CISCO_REPTYPE	0x01 /* report type */
+#define LMI_CCITT_REPTYPE	0x51
+#define LMI_ANSI_CISCO_ALIVE	0x03 /* keep alive */
+#define LMI_CCITT_ALIVE		0x53
+#define LMI_ANSI_CISCO_PVCSTAT	0x07 /* PVC status */
+#define LMI_CCITT_PVCSTAT	0x57
 
+#define LMI_FULLREP		0x00 /* full report  */
+#define LMI_INTEGRITY		0x01 /* link integrity report */
+#define LMI_SINGLE		0x02 /* single PVC report */
 
-#define LMI_DLCI                   0 /* LMI DLCI */
-#define LMI_PROTO               0x08
-#define LMI_CALLREF             0x00 /* Call Reference */
-#define LMI_ANSI_LOCKSHIFT      0x95 /* ANSI lockshift */
-#define LMI_REPTYPE                1 /* report type */
-#define LMI_CCITT_REPTYPE       0x51
-#define LMI_ALIVE                  3 /* keep alive */
-#define LMI_CCITT_ALIVE         0x53
-#define LMI_PVCSTAT                7 /* pvc status */
-#define LMI_CCITT_PVCSTAT       0x57
-#define LMI_FULLREP                0 /* full report  */
-#define LMI_INTEGRITY              1 /* link integrity report */
-#define LMI_SINGLE                 2 /* single pvc report */
 #define LMI_STATUS_ENQUIRY      0x75
 #define LMI_STATUS              0x7D /* reply */
 
 #define LMI_REPT_LEN               1 /* report type element length */
 #define LMI_INTEG_LEN              2 /* link integrity element length */
 
-#define LMI_LENGTH                13 /* standard LMI frame length */
-#define LMI_ANSI_LENGTH           14
+#define LMI_CCITT_CISCO_LENGTH	  13 /* LMI frame lengths */
+#define LMI_ANSI_LENGTH		  14
 
 
 typedef struct {
@@ -223,35 +223,24 @@
 }
 
 
-static inline u16 status_to_dlci(u8 *status, int *active, int *new)
-{
-	*new = (status[2] & 0x08) ? 1 : 0;
-	*active = (status[2] & 0x02) ? 1 : 0;
-
-	return ((status[0] & 0x3F) << 4) | ((status[1] & 0x78) >> 3);
-}
-
-
-static inline void dlci_to_status(u16 dlci, u8 *status, int active, int new)
-{
-	status[0] = (dlci >> 4) & 0x3F;
-	status[1] = ((dlci << 3) & 0x78) | 0x80;
-	status[2] = 0x80;
-
-	if (new)
-		status[2] |= 0x08;
-	else if (active)
-		status[2] |= 0x02;
-}
-
-
-
 static int fr_hard_header(struct sk_buff **skb_p, u16 dlci)
 {
 	u16 head_len;
 	struct sk_buff *skb = *skb_p;
 
 	switch (skb->protocol) {
+	case __constant_ntohs(NLPID_CCITT_ANSI_LMI):
+		head_len = 4;
+		skb_push(skb, head_len);
+		skb->data[3] = NLPID_CCITT_ANSI_LMI;
+		break;
+
+	case __constant_ntohs(NLPID_CISCO_LMI):
+		head_len = 4;
+		skb_push(skb, head_len);
+		skb->data[3] = NLPID_CISCO_LMI;
+		break;
+
 	case __constant_ntohs(ETH_P_IP):
 		head_len = 4;
 		skb_push(skb, head_len);
@@ -264,12 +253,6 @@
 		skb->data[3] = NLPID_IPV6;
 		break;
 
-	case __constant_ntohs(LMI_PROTO):
-		head_len = 4;
-		skb_push(skb, head_len);
-		skb->data[3] = LMI_PROTO;
-		break;
-
 	case __constant_ntohs(ETH_P_802_3):
 		head_len = 10;
 		if (skb_headroom(skb) < head_len) {
@@ -461,13 +444,14 @@
 	hdlc_device *hdlc = dev_to_hdlc(dev);
 	struct sk_buff *skb;
 	pvc_device *pvc = hdlc->state.fr.first_pvc;
-	int len = (hdlc->state.fr.settings.lmi == LMI_ANSI) ? LMI_ANSI_LENGTH
-		: LMI_LENGTH;
-	int stat_len = 3;
+	int lmi = hdlc->state.fr.settings.lmi;
+	int dce = hdlc->state.fr.settings.dce;
+	int len = lmi == LMI_ANSI ? LMI_ANSI_LENGTH : LMI_CCITT_CISCO_LENGTH;
+	int stat_len = (lmi == LMI_CISCO) ? 6 : 3;
 	u8 *data;
 	int i = 0;
 
-	if (hdlc->state.fr.settings.dce && fullrep) {
+	if (dce && fullrep) {
 		len += hdlc->state.fr.dce_pvc_count * (2 + stat_len);
 		if (len > HDLC_MAX_MRU) {
 			printk(KERN_WARNING "%s: Too many PVCs while sending "
@@ -484,29 +468,31 @@
 	}
 	memset(skb->data, 0, len);
 	skb_reserve(skb, 4);
-	skb->protocol = __constant_htons(LMI_PROTO);
-	fr_hard_header(&skb, LMI_DLCI);
+	if (lmi == LMI_CISCO) {
+		skb->protocol = __constant_htons(NLPID_CISCO_LMI);
+		fr_hard_header(&skb, LMI_CISCO_DLCI);
+	} else {
+		skb->protocol = __constant_htons(NLPID_CCITT_ANSI_LMI);
+		fr_hard_header(&skb, LMI_CCITT_ANSI_DLCI);
+	}
 	data = skb->tail;
 	data[i++] = LMI_CALLREF;
-	data[i++] = hdlc->state.fr.settings.dce
-		? LMI_STATUS : LMI_STATUS_ENQUIRY;
-	if (hdlc->state.fr.settings.lmi == LMI_ANSI)
+	data[i++] = dce ? LMI_STATUS : LMI_STATUS_ENQUIRY;
+	if (lmi == LMI_ANSI)
 		data[i++] = LMI_ANSI_LOCKSHIFT;
-	data[i++] = (hdlc->state.fr.settings.lmi == LMI_CCITT)
-		? LMI_CCITT_REPTYPE : LMI_REPTYPE;
+	data[i++] = lmi == LMI_CCITT ? LMI_CCITT_REPTYPE :
+		LMI_ANSI_CISCO_REPTYPE;
 	data[i++] = LMI_REPT_LEN;
 	data[i++] = fullrep ? LMI_FULLREP : LMI_INTEGRITY;
-
-	data[i++] = (hdlc->state.fr.settings.lmi == LMI_CCITT)
-		? LMI_CCITT_ALIVE : LMI_ALIVE;
+	data[i++] = lmi == LMI_CCITT ? LMI_CCITT_ALIVE : LMI_ANSI_CISCO_ALIVE;
 	data[i++] = LMI_INTEG_LEN;
 	data[i++] = hdlc->state.fr.txseq =fr_lmi_nextseq(hdlc->state.fr.txseq);
 	data[i++] = hdlc->state.fr.rxseq;
 
-	if (hdlc->state.fr.settings.dce && fullrep) {
+	if (dce && fullrep) {
 		while (pvc) {
-			data[i++] = (hdlc->state.fr.settings.lmi == LMI_CCITT)
-				? LMI_CCITT_PVCSTAT : LMI_PVCSTAT;
+			data[i++] = lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT :
+				LMI_ANSI_CISCO_PVCSTAT;
 			data[i++] = stat_len;
 
 			/* LMI start/restart */
@@ -523,8 +509,20 @@
 				fr_log_dlci_active(pvc);
 			}
 
-			dlci_to_status(pvc->dlci, data + i,
-				       pvc->state.active, pvc->state.new);
+			if (lmi == LMI_CISCO) {
+				data[i] = pvc->dlci >> 8;
+				data[i + 1] = pvc->dlci & 0xFF;
+			} else {
+				data[i] = (pvc->dlci >> 4) & 0x3F;
+				data[i + 1] = ((pvc->dlci << 3) & 0x78) | 0x80;
+				data[i + 2] = 0x80;
+			}
+
+			if (pvc->state.new)
+				data[i + 2] |= 0x08;
+			else if (pvc->state.active)
+				data[i + 2] |= 0x02;
+
 			i += stat_len;
 			pvc = pvc->next;
 		}
@@ -569,6 +567,8 @@
 			pvc_carrier(0, pvc);
 			pvc->state.exist = pvc->state.active = 0;
 			pvc->state.new = 0;
+			if (!hdlc->state.fr.settings.dce)
+				pvc->state.bandwidth = 0;
 			pvc = pvc->next;
 		}
 	}
@@ -583,11 +583,12 @@
 	int i, cnt = 0, reliable;
 	u32 list;
 
-	if (hdlc->state.fr.settings.dce)
+	if (hdlc->state.fr.settings.dce) {
 		reliable = hdlc->state.fr.request &&
 			time_before(jiffies, hdlc->state.fr.last_poll +
 				    hdlc->state.fr.settings.t392 * HZ);
-	else {
+		hdlc->state.fr.request = 0;
+	} else {
 		hdlc->state.fr.last_errors <<= 1; /* Shift the list */
 		if (hdlc->state.fr.request) {
 			if (hdlc->state.fr.reliable)
@@ -634,65 +635,88 @@
 static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
 {
 	hdlc_device *hdlc = dev_to_hdlc(dev);
-	int stat_len;
 	pvc_device *pvc;
-	int reptype = -1, error, no_ram;
 	u8 rxseq, txseq;
-	int i;
+	int lmi = hdlc->state.fr.settings.lmi;
+	int dce = hdlc->state.fr.settings.dce;
+	int stat_len = (lmi == LMI_CISCO) ? 6 : 3, reptype, error, no_ram, i;
 
-	if (skb->len < ((hdlc->state.fr.settings.lmi == LMI_ANSI)
-			? LMI_ANSI_LENGTH : LMI_LENGTH)) {
+	if (skb->len < (lmi == LMI_ANSI ? LMI_ANSI_LENGTH :
+			LMI_CCITT_CISCO_LENGTH)) {
 		printk(KERN_INFO "%s: Short LMI frame\n", dev->name);
 		return 1;
 	}
 
-	if (skb->data[5] != (!hdlc->state.fr.settings.dce ?
-			     LMI_STATUS : LMI_STATUS_ENQUIRY)) {
-		printk(KERN_INFO "%s: LMI msgtype=%x, Not LMI status %s\n",
-		       dev->name, skb->data[2],
-		       hdlc->state.fr.settings.dce ? "enquiry" : "reply");
+	if (skb->data[3] != (lmi == LMI_CISCO ? NLPID_CISCO_LMI :
+			     NLPID_CCITT_ANSI_LMI)) {
+		printk(KERN_INFO "%s: Received non-LMI frame with LMI"
+		       " DLCI\n", dev->name);
 		return 1;
 	}
 
-	i = (hdlc->state.fr.settings.lmi == LMI_ANSI) ? 7 : 6;
+	if (skb->data[4] != LMI_CALLREF) {
+		printk(KERN_INFO "%s: Invalid LMI Call reference (0x%02X)\n",
+		       dev->name, skb->data[4]);
+		return 1;
+	}
 
-	if (skb->data[i] !=
-	    ((hdlc->state.fr.settings.lmi == LMI_CCITT)
-	     ? LMI_CCITT_REPTYPE : LMI_REPTYPE)) {
-		printk(KERN_INFO "%s: Not a report type=%x\n",
+	if (skb->data[5] != (dce ? LMI_STATUS_ENQUIRY : LMI_STATUS)) {
+		printk(KERN_INFO "%s: Invalid LMI Message type (0x%02X)\n",
+		       dev->name, skb->data[5]);
+		return 1;
+	}
+
+	if (lmi == LMI_ANSI) {
+		if (skb->data[6] != LMI_ANSI_LOCKSHIFT) {
+			printk(KERN_INFO "%s: Not ANSI locking shift in LMI"
+			       " message (0x%02X)\n", dev->name, skb->data[6]);
+			return 1;
+		}
+		i = 7;
+	} else
+		i = 6;
+
+	if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_REPTYPE :
+			     LMI_ANSI_CISCO_REPTYPE)) {
+		printk(KERN_INFO "%s: Not an LMI Report type IE (0x%02X)\n",
 		       dev->name, skb->data[i]);
 		return 1;
 	}
-	i++;
 
-	i++;				/* Skip length field */
+	if (skb->data[++i] != LMI_REPT_LEN) {
+		printk(KERN_INFO "%s: Invalid LMI Report type IE length"
+		       " (%u)\n", dev->name, skb->data[i]);
+		return 1;
+	}
 
-	reptype = skb->data[i++];
+	reptype = skb->data[++i];
+	if (reptype != LMI_INTEGRITY && reptype != LMI_FULLREP) {
+		printk(KERN_INFO "%s: Unsupported LMI Report type (0x%02X)\n",
+		       dev->name, reptype);
+		return 1;
+	}
 
-	if (skb->data[i]!=
-	    ((hdlc->state.fr.settings.lmi == LMI_CCITT)
-	     ? LMI_CCITT_ALIVE : LMI_ALIVE)) {
-		printk(KERN_INFO "%s: Unsupported status element=%x\n",
-		       dev->name, skb->data[i]);
+	if (skb->data[++i] != (lmi == LMI_CCITT ? LMI_CCITT_ALIVE :
+			       LMI_ANSI_CISCO_ALIVE)) {
+		printk(KERN_INFO "%s: Not an LMI Link integrity verification"
+		       " IE (0x%02X)\n", dev->name, skb->data[i]);
+		return 1;
+	}
+
+	if (skb->data[++i] != LMI_INTEG_LEN) {
+		printk(KERN_INFO "%s: Invalid LMI Link integrity verification"
+		       " IE length (%u)\n", dev->name, skb->data[i]);
 		return 1;
 	}
 	i++;
 
-	i++;			/* Skip length field */
-
 	hdlc->state.fr.rxseq = skb->data[i++]; /* TX sequence from peer */
 	rxseq = skb->data[i++];	/* Should confirm our sequence */
 
 	txseq = hdlc->state.fr.txseq;
 
-	if (hdlc->state.fr.settings.dce) {
-		if (reptype != LMI_FULLREP && reptype != LMI_INTEGRITY) {
-			printk(KERN_INFO "%s: Unsupported report type=%x\n",
-			       dev->name, reptype);
-			return 1;
-		}
+	if (dce)
 		hdlc->state.fr.last_poll = jiffies;
-	}
 
 	error = 0;
 	if (!hdlc->state.fr.reliable)
@@ -703,7 +727,7 @@
 		error = 1;
 	}
 
-	if (hdlc->state.fr.settings.dce) {
+	if (dce) {
 		if (hdlc->state.fr.fullrep_sent && !error) {
 /* Stop sending full report - the last one has been confirmed by DTE */
 			hdlc->state.fr.fullrep_sent = 0;
@@ -725,6 +749,7 @@
 			hdlc->state.fr.dce_changed = 0;
 		}
 
+		hdlc->state.fr.request = 1; /* got request */
 		fr_lmi_send(dev, reptype == LMI_FULLREP ? 1 : 0);
 		return 0;
 	}
@@ -739,7 +764,6 @@
 	if (reptype != LMI_FULLREP)
 		return 0;
 
-	stat_len = 3;
 	pvc = hdlc->state.fr.first_pvc;
 
 	while (pvc) {
@@ -750,24 +774,35 @@
 	no_ram = 0;
 	while (skb->len >= i + 2 + stat_len) {
 		u16 dlci;
+		u32 bw;
 		unsigned int active, new;
 
-		if (skb->data[i] != ((hdlc->state.fr.settings.lmi == LMI_CCITT)
-				     ? LMI_CCITT_PVCSTAT : LMI_PVCSTAT)) {
-			printk(KERN_WARNING "%s: Invalid PVCSTAT ID: %x\n",
-			       dev->name, skb->data[i]);
+		if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT :
+				       LMI_ANSI_CISCO_PVCSTAT)) {
+			printk(KERN_INFO "%s: Not an LMI PVC status IE"
+			       " (0x%02X)\n", dev->name, skb->data[i]);
+			return 1;
+		}
+
+		if (skb->data[++i] != stat_len) {
+			printk(KERN_INFO "%s: Invalid LMI PVC status IE length"
+			       " (%u)\n", dev->name, skb->data[i]);
 			return 1;
 		}
 		i++;
 
-		if (skb->data[i] != stat_len) {
-			printk(KERN_WARNING "%s: Invalid PVCSTAT length: %x\n",
-			       dev->name, skb->data[i]);
-			return 1;
+		new = !! (skb->data[i + 2] & 0x08);
+		active = !! (skb->data[i + 2] & 0x02);
+		if (lmi == LMI_CISCO) {
+			dlci = (skb->data[i] << 8) | skb->data[i + 1];
+			bw = (skb->data[i + 3] << 16) |
+				(skb->data[i + 4] << 8) |
+				(skb->data[i + 5]);
+		} else {
+			dlci = ((skb->data[i] & 0x3F) << 4) |
+				((skb->data[i + 1] & 0x78) >> 3);
+			bw = 0;
 		}
-		i++;
-
-		dlci = status_to_dlci(skb->data + i, &active, &new);
 
 		pvc = add_pvc(dev, dlci);
 
@@ -783,9 +818,11 @@
 			pvc->state.deleted = 0;
 			if (active != pvc->state.active ||
 			    new != pvc->state.new ||
+			    bw != pvc->state.bandwidth ||
 			    !pvc->state.exist) {
 				pvc->state.new = new;
 				pvc->state.active = active;
+				pvc->state.bandwidth = bw;
 				pvc_carrier(active, pvc);
 				fr_log_dlci_active(pvc);
 			}
@@ -801,6 +838,7 @@
 			pvc_carrier(0, pvc);
 			pvc->state.active = pvc->state.new = 0;
 			pvc->state.exist = 0;
+			pvc->state.bandwidth = 0;
 			fr_log_dlci_active(pvc);
 		}
 		pvc = pvc->next;
@@ -829,22 +867,15 @@
 
 	dlci = q922_to_dlci(skb->data);
 
-	if (dlci == LMI_DLCI) {
-		if (hdlc->state.fr.settings.lmi == LMI_NONE)
-			goto rx_error; /* LMI packet with no LMI? */
-
-		if (data[3] == LMI_PROTO) {
-			if (fr_lmi_recv(ndev, skb))
-				goto rx_error;
-			else {
-				dev_kfree_skb_any(skb);
-				return NET_RX_SUCCESS;
-			}
-		}
-
-		printk(KERN_INFO "%s: Received non-LMI frame with LMI DLCI\n",
-		       ndev->name);
-		goto rx_error;
+	if ((dlci == LMI_CCITT_ANSI_DLCI &&
+	     (hdlc->state.fr.settings.lmi == LMI_ANSI ||
+	      hdlc->state.fr.settings.lmi == LMI_CCITT)) ||
+	    (dlci == LMI_CISCO_DLCI &&
+	     hdlc->state.fr.settings.lmi == LMI_CISCO)) {
+		if (fr_lmi_recv(ndev, skb))
+			goto rx_error;
+		dev_kfree_skb_any(skb);
+		return NET_RX_SUCCESS;
 	}
 
 	pvc = find_pvc(hdlc, dlci);
@@ -1170,7 +1201,8 @@
 
 		if ((new_settings.lmi != LMI_NONE &&
 		     new_settings.lmi != LMI_ANSI &&
-		     new_settings.lmi != LMI_CCITT) ||
+		     new_settings.lmi != LMI_CCITT &&
+		     new_settings.lmi != LMI_CISCO) ||
 		    new_settings.t391 < 1 ||
 		    new_settings.t392 < 2 ||
 		    new_settings.n391 < 1 ||
diff --git a/drivers/net/wan/hdlc_generic.c b/drivers/net/wan/hdlc_generic.c
index 6ed064c..a63f6a2 100644
--- a/drivers/net/wan/hdlc_generic.c
+++ b/drivers/net/wan/hdlc_generic.c
@@ -1,7 +1,7 @@
 /*
  * Generic HDLC support routines for Linux
  *
- * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 1999 - 2005 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * 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
@@ -38,7 +38,7 @@
 #include <linux/hdlc.h>
 
 
-static const char* version = "HDLC support module revision 1.17";
+static const char* version = "HDLC support module revision 1.18";
 
 #undef DEBUG_LINK
 
@@ -126,10 +126,13 @@
 	if (!hdlc->open)
 		goto carrier_exit;
 
-	if (hdlc->carrier)
+	if (hdlc->carrier) {
+		printk(KERN_INFO "%s: Carrier detected\n", dev->name);
 		__hdlc_set_carrier_on(dev);
-	else
+	} else {
+		printk(KERN_INFO "%s: Carrier lost\n", dev->name);
 		__hdlc_set_carrier_off(dev);
+	}
 
 carrier_exit:
 	spin_unlock_irqrestore(&hdlc->state_lock, flags);
@@ -157,8 +160,11 @@
 
 	spin_lock_irq(&hdlc->state_lock);
 
-	if (hdlc->carrier)
+	if (hdlc->carrier) {
+		printk(KERN_INFO "%s: Carrier detected\n", dev->name);
 		__hdlc_set_carrier_on(dev);
+	} else
+		printk(KERN_INFO "%s: No carrier\n", dev->name);
 
 	hdlc->open = 1;
 
diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
index 15e545f..2b948ea 100644
--- a/drivers/net/wan/lmc/lmc_main.c
+++ b/drivers/net/wan/lmc/lmc_main.c
@@ -723,7 +723,7 @@
         /* lmc_reset (sc); Why reset??? The link can go down ok */
 
         /* Inform the world that link has been lost */
-        dev->flags &= ~IFF_RUNNING;
+	netif_carrier_off(dev);
     }
 
     /*
@@ -736,7 +736,7 @@
          /* lmc_reset (sc); Again why reset??? */
 
          /* Inform the world that link protocol is back up. */
-         dev->flags |= IFF_RUNNING;
+	 netif_carrier_on(dev);
 
          /* Now we have to tell the syncppp that we had an outage
           * and that it should deal.  Calling sppp_reopen here
@@ -1168,8 +1168,6 @@
     sc->lmc_media->set_link_status (sc, 1);
     sc->lmc_media->set_status (sc, NULL);
 
-    //dev->flags |= IFF_RUNNING;
-    
     netif_wake_queue(dev);
 
     sc->lmc_txfull = 0;
@@ -1233,8 +1231,6 @@
     csr6 &= ~LMC_DEC_SR;		/* Turn off the Receive bit */
     LMC_CSR_WRITE (sc, csr_command, csr6);
 
-    dev->flags &= ~IFF_RUNNING;
-
     sc->stats.rx_missed_errors +=
         LMC_CSR_READ (sc, csr_missed_frames) & 0xffff;
 
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index 1e7b477..9c1e106 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -26,6 +26,7 @@
 #include <linux/netdevice.h>
 #include <linux/hdlc.h>
 #include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include <asm/io.h>
 #include <asm/delay.h>
 
@@ -624,8 +625,8 @@
 	/* FIXME when PCI/DMA subsystems are fixed.
 	   We set both dma_mask and consistent_dma_mask back to 32 bits
 	   to indicate the card can do 32-bit DMA addressing */
-	if (pci_set_consistent_dma_mask(pdev, 0xFFFFFFFF) ||
-	    pci_set_dma_mask(pdev, 0xFFFFFFFF)) {
+	if (pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK) ||
+	    pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
 		printk(KERN_ERR "wanXL: No usable DMA configuration\n");
 		wanxl_pci_remove_one(pdev);
 		return -EIO;
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index 1c540d8..bdf672c 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -829,7 +829,7 @@
 	}
 
 	kfree(x25_asy_devs);
-	tty_register_ldisc(N_X25, NULL);
+	tty_unregister_ldisc(N_X25);
 }
 
 module_init(init_x25_asy);
diff --git a/drivers/net/wd.c b/drivers/net/wd.c
index 1f05d9b..b03feae 100644
--- a/drivers/net/wd.c
+++ b/drivers/net/wd.c
@@ -149,12 +149,7 @@
 	err = do_wd_probe(dev);
 	if (err)
 		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
 	return dev;
-out1:
-	cleanup_card(dev);
 out:
 	free_netdev(dev);
 	return ERR_PTR(err);
@@ -164,6 +159,7 @@
 static int __init wd_probe1(struct net_device *dev, int ioaddr)
 {
 	int i;
+	int err;
 	int checksum = 0;
 	int ancient = 0;			/* An old card without config registers. */
 	int word16 = 0;				/* 0 = 8 bit, 1 = 16 bit */
@@ -356,7 +352,10 @@
 		outb(inb(ioaddr+4)|0x80, ioaddr+4);
 #endif
 
-	return 0;
+	err = register_netdev(dev);
+	if (err)
+		free_irq(dev->irq, dev);
+	return err;
 }
 
 static int
@@ -527,11 +526,8 @@
 		dev->mem_start = mem[this_dev];
 		dev->mem_end = mem_end[this_dev];
 		if (do_wd_probe(dev) == 0) {
-			if (register_netdev(dev) == 0) {
-				dev_wd[found++] = dev;
-				continue;
-			}
-			cleanup_card(dev);
+			dev_wd[found++] = dev;
+			continue;
 		}
 		free_netdev(dev);
 		printk(KERN_WARNING "wd.c: No wd80x3 card found (i/o = 0x%x).\n", io[this_dev]);
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index fb10a2d..1809688 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -1209,7 +1209,7 @@
 	unsigned char		__iomem *pciaux;
 	unsigned char		*shared;
 	dma_addr_t		shared_dma;
-	int			power;
+	pm_message_t		power;
 	SsidRid			*SSID;
 	APListRid		*APList;
 #define	PCI_SHARED_LEN		2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE
@@ -2918,7 +2918,7 @@
 			flush_signals(current);
 
 		/* make swsusp happy with our thread */
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 
 		if (test_bit(JOB_DIE, &ai->flags))
 			break;
@@ -5499,9 +5499,9 @@
 	cmd.cmd=HOSTSLEEP;
 	issuecommand(ai, &cmd, &rsp);
 
-	pci_enable_wake(pdev, state, 1);
+	pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
 	pci_save_state(pdev);
-	return pci_set_power_state(pdev, state);
+	return pci_set_power_state(pdev, pci_choose_state(pdev, state));
 }
 
 static int airo_pci_resume(struct pci_dev *pdev)
@@ -5512,7 +5512,7 @@
 
 	pci_set_power_state(pdev, 0);
 	pci_restore_state(pdev);
-	pci_enable_wake(pdev, ai->power, 0);
+	pci_enable_wake(pdev, pci_choose_state(pdev, ai->power), 0);
 
 	if (ai->power > 1) {
 		reset_card(dev, 0);
@@ -5541,7 +5541,7 @@
 	}
 	writeConfigRid(ai, 0);
 	enable_MAC(ai, &rsp, 0);
-	ai->power = 0;
+	ai->power = PMSG_ON;
 	netif_device_attach(dev);
 	netif_wake_queue(dev);
 	enable_interrupts(ai);
diff --git a/drivers/net/wireless/arlan-main.c b/drivers/net/wireless/arlan-main.c
index 4f304c6e..0e1ac33 100644
--- a/drivers/net/wireless/arlan-main.c
+++ b/drivers/net/wireless/arlan-main.c
@@ -33,8 +33,6 @@
 
 #ifdef ARLAN_DEBUGGING
 
-static int arlan_entry_debug;
-static int arlan_exit_debug;
 static int testMemory = testMemoryUNKNOWN;
 static int irq = irqUNKNOWN;
 static int txScrambled = 1;
@@ -43,15 +41,13 @@
 module_param(irq, int, 0);
 module_param(mdebug, int, 0);
 module_param(testMemory, int, 0);
-module_param(arlan_entry_debug, int, 0);
-module_param(arlan_exit_debug, int, 0);
 module_param(txScrambled, int, 0);
 MODULE_PARM_DESC(irq, "(unused)");
 MODULE_PARM_DESC(testMemory, "(unused)");
 MODULE_PARM_DESC(mdebug, "Arlan multicast debugging (0-1)");
 #endif
 
-module_param(arlan_debug, int, 0);
+module_param_named(debug, arlan_debug, int, 0);
 module_param(spreadingCode, int, 0);
 module_param(channelNumber, int, 0);
 module_param(channelSet, int, 0);
@@ -63,17 +59,19 @@
 module_param(tx_delay_ms, int, 0);
 module_param(retries, int, 0);
 module_param(tx_queue_len, int, 0);
-module_param(arlan_EEPROM_bad, int, 0);
-MODULE_PARM_DESC(arlan_debug, "Arlan debug enable (0-1)");
+module_param_named(EEPROM_bad, arlan_EEPROM_bad, int, 0);
+MODULE_PARM_DESC(debug, "Arlan debug enable (0-1)");
 MODULE_PARM_DESC(retries, "Arlan maximum packet retransmisions");
 #ifdef ARLAN_ENTRY_EXIT_DEBUGGING
-MODULE_PARM_DESC(arlan_entry_debug, "Arlan driver function entry debugging");
-MODULE_PARM_DESC(arlan_exit_debug, "Arlan driver function exit debugging");
-MODULE_PARM_DESC(arlan_entry_and_exit_debug, "Arlan driver function entry and exit debugging");
-#else
-MODULE_PARM_DESC(arlan_entry_debug, "(ignored)");
-MODULE_PARM_DESC(arlan_exit_debug, "(ignored)");
-MODULE_PARM_DESC(arlan_entry_and_exit_debug, "(ignored)");
+static int arlan_entry_debug;
+static int arlan_exit_debug;
+static int arlan_entry_and_exit_debug;
+module_param_named(entry_debug, arlan_entry_debug, int, 0);
+module_param_named(exit_debug, arlan_exit_debug, int, 0);
+module_param_named(entry_and_exit_debug, arlan_entry_and_exit_debug, int, 0);
+MODULE_PARM_DESC(entry_debug, "Arlan driver function entry debugging");
+MODULE_PARM_DESC(exit_debug, "Arlan driver function exit debugging");
+MODULE_PARM_DESC(entry_and_exit_debug, "Arlan driver function entry and exit debugging");
 #endif
 
 struct arlan_conf_stru arlan_conf[MAX_ARLANS];
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index a3a3243..b1078ba 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -492,6 +492,9 @@
 static int suppress_linkstatus; /* = 0 */
 module_param(suppress_linkstatus, bool, 0644);
 MODULE_PARM_DESC(suppress_linkstatus, "Don't log link status changes");
+static int ignore_disconnect; /* = 0 */
+module_param(ignore_disconnect, int, 0644);
+MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer");
 
 /********************************************************************/
 /* Compile time configuration and compatibility stuff               */
@@ -604,7 +607,6 @@
 static int orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static int __orinoco_program_rids(struct net_device *dev);
 static void __orinoco_set_multicast_list(struct net_device *dev);
-static int orinoco_debug_dump_recs(struct net_device *dev);
 
 /********************************************************************/
 /* Internal helper functions                                        */
@@ -655,7 +657,7 @@
 	return err;
 }
 
-int orinoco_stop(struct net_device *dev)
+static int orinoco_stop(struct net_device *dev)
 {
 	struct orinoco_private *priv = netdev_priv(dev);
 	int err = 0;
@@ -686,7 +688,7 @@
 	struct orinoco_private *priv = netdev_priv(dev);
 	hermes_t *hw = &priv->hw;
 	struct iw_statistics *wstats = &priv->wstats;
-	int err = 0;
+	int err;
 	unsigned long flags;
 
 	if (! netif_device_present(dev)) {
@@ -695,9 +697,21 @@
 		return NULL; /* FIXME: Can we do better than this? */
 	}
 
+	/* If busy, return the old stats.  Returning NULL may cause
+	 * the interface to disappear from /proc/net/wireless */
 	if (orinoco_lock(priv, &flags) != 0)
-		return NULL;  /* FIXME: Erg, we've been signalled, how
-			       * do we propagate this back up? */
+		return wstats;
+
+	/* We can't really wait for the tallies inquiry command to
+	 * complete, so we just use the previous results and trigger
+	 * a new tallies inquiry command for next time - Jean II */
+	/* FIXME: Really we should wait for the inquiry to come back -
+	 * as it is the stats we give don't make a whole lot of sense.
+	 * Unfortunately, it's not clear how to do that within the
+	 * wireless extensions framework: I think we're in user
+	 * context, but a lock seems to be held by the time we get in
+	 * here so we're not safe to sleep here. */
+	hermes_inquire(hw, HERMES_INQ_TALLIES);
 
 	if (priv->iw_mode == IW_MODE_ADHOC) {
 		memset(&wstats->qual, 0, sizeof(wstats->qual));
@@ -716,25 +730,16 @@
 
 		err = HERMES_READ_RECORD(hw, USER_BAP,
 					 HERMES_RID_COMMSQUALITY, &cq);
-		
-		wstats->qual.qual = (int)le16_to_cpu(cq.qual);
-		wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;
-		wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;
-		wstats->qual.updated = 7;
+
+		if (!err) {
+			wstats->qual.qual = (int)le16_to_cpu(cq.qual);
+			wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;
+			wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;
+			wstats->qual.updated = 7;
+		}
 	}
 
-	/* We can't really wait for the tallies inquiry command to
-	 * complete, so we just use the previous results and trigger
-	 * a new tallies inquiry command for next time - Jean II */
-	/* FIXME: We're in user context (I think?), so we should just
-           wait for the tallies to come through */
-	err = hermes_inquire(hw, HERMES_INQ_TALLIES);
-               
 	orinoco_unlock(priv, &flags);
-
-	if (err)
-		return NULL;
-		
 	return wstats;
 }
 
@@ -1275,9 +1280,10 @@
 			len = sizeof(tallies);
 		}
 		
-		/* Read directly the data (no seek) */
-		hermes_read_words(hw, HERMES_DATA1, (void *) &tallies,
-				  len / 2); /* FIXME: blech! */
+		err = hermes_bap_pread(hw, IRQ_BAP, &tallies, len,
+				       infofid, sizeof(info));
+		if (err)
+			break;
 		
 		/* Increment our various counters */
 		/* wstats->discard.nwid - no wrong BSSID stuff */
@@ -1307,8 +1313,10 @@
 			break;
 		}
 
-		hermes_read_words(hw, HERMES_DATA1, (void *) &linkstatus,
-				  len / 2);
+		err = hermes_bap_pread(hw, IRQ_BAP, &linkstatus, len,
+				       infofid, sizeof(info));
+		if (err)
+			break;
 		newstatus = le16_to_cpu(linkstatus.linkstatus);
 
 		connected = (newstatus == HERMES_LINKSTATUS_CONNECTED)
@@ -1317,7 +1325,7 @@
 
 		if (connected)
 			netif_carrier_on(dev);
-		else
+		else if (!ignore_disconnect)
 			netif_carrier_off(dev);
 
 		if (newstatus != priv->last_linkstatus)
@@ -1350,6 +1358,8 @@
 	struct hermes *hw = &priv->hw;
 	int err;
 
+	netif_carrier_off(dev); /* just to make sure */
+
 	err = __orinoco_program_rids(dev);
 	if (err) {
 		printk(KERN_ERR "%s: Error %d configuring card\n",
@@ -1413,7 +1423,7 @@
 		return err;
 
 	err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
-	if (err == -EIO) {
+	if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) {
 		/* Try workaround for old Symbol firmware bug */
 		printk(KERN_WARNING "%s: firmware ALLOC bug detected "
 		       "(old Symbol firmware?). Trying to work around... ",
@@ -1610,17 +1620,15 @@
 		return err;
 	}
 	/* Set the channel/frequency */
-	if (priv->channel == 0) {
-		printk(KERN_DEBUG "%s: Channel is 0 in __orinoco_program_rids()\n", dev->name);
-		if (priv->createibss)
-			priv->channel = 10;
-	}
-	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFOWNCHANNEL,
-				   priv->channel);
-	if (err) {
-		printk(KERN_ERR "%s: Error %d setting channel\n",
-		       dev->name, err);
-		return err;
+	if (priv->channel != 0 && priv->iw_mode != IW_MODE_INFRA) {
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFOWNCHANNEL,
+					   priv->channel);
+		if (err) {
+			printk(KERN_ERR "%s: Error %d setting channel %d\n",
+			       dev->name, err, priv->channel);
+			return err;
+		}
 	}
 
 	if (priv->has_ibss) {
@@ -1916,7 +1924,7 @@
 {
 	struct orinoco_private *priv = netdev_priv(dev);
 	struct hermes *hw = &priv->hw;
-	int err = 0;
+	int err;
 	unsigned long flags;
 
 	if (orinoco_lock(priv, &flags) != 0)
@@ -1938,20 +1946,20 @@
 
 	orinoco_unlock(priv, &flags);
 
-	if (priv->hard_reset)
+	if (priv->hard_reset) {
 		err = (*priv->hard_reset)(priv);
-	if (err) {
-		printk(KERN_ERR "%s: orinoco_reset: Error %d "
-		       "performing  hard reset\n", dev->name, err);
-		/* FIXME: shutdown of some sort */
-		return;
+		if (err) {
+			printk(KERN_ERR "%s: orinoco_reset: Error %d "
+			       "performing hard reset\n", dev->name, err);
+			goto disable;
+		}
 	}
 
 	err = orinoco_reinit_firmware(dev);
 	if (err) {
 		printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n",
 		       dev->name, err);
-		return;
+		goto disable;
 	}
 
 	spin_lock_irq(&priv->lock); /* This has to be called from user context */
@@ -1972,6 +1980,10 @@
 	spin_unlock_irq(&priv->lock);
 
 	return;
+ disable:
+	hermes_set_irqmask(hw, 0);
+	netif_device_detach(dev);
+	printk(KERN_ERR "%s: Device has been disabled!\n", dev->name);
 }
 
 /********************************************************************/
@@ -2056,7 +2068,7 @@
 		if (events & HERMES_EV_ALLOC)
 			__orinoco_ev_alloc(dev, hw);
 		
-		hermes_write_regn(hw, EVACK, events);
+		hermes_write_regn(hw, EVACK, evstat);
 
 		evstat = hermes_read_regn(hw, EVSTAT);
 		events = evstat & hw->inten;
@@ -2215,6 +2227,8 @@
 			       firmver >= 0x31000;
 		priv->has_preamble = (firmver >= 0x20000);
 		priv->ibss_port = 4;
+ 		priv->broken_disableport = (firmver == 0x25013) ||
+ 					   (firmver >= 0x30000 && firmver <= 0x31000);
 		/* Tested with Intel firmware : 0x20015 => Jean II */
 		/* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */
 		break;
@@ -2267,7 +2281,7 @@
 	priv->nicbuf_size = IEEE802_11_FRAME_LEN + ETH_HLEN;
 
 	/* Initialize the firmware */
-	err = hermes_init(hw);
+	err = orinoco_reinit_firmware(dev);
 	if (err != 0) {
 		printk(KERN_ERR "%s: failed to initialize firmware (err = %d)\n",
 		       dev->name, err);
@@ -2400,31 +2414,12 @@
 	/* By default use IEEE/IBSS ad-hoc mode if we have it */
 	priv->prefer_port3 = priv->has_port3 && (! priv->has_ibss);
 	set_port_type(priv);
-	priv->channel = 10; /* default channel, more-or-less arbitrary */
+	priv->channel = 0; /* use firmware default */
 
 	priv->promiscuous = 0;
 	priv->wep_on = 0;
 	priv->tx_key = 0;
 
-	err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
-	if (err == -EIO) {
-		/* Try workaround for old Symbol firmware bug */
-		printk(KERN_WARNING "%s: firmware ALLOC bug detected "
-		       "(old Symbol firmware?). Trying to work around... ",
-		       dev->name);
-		
-		priv->nicbuf_size = TX_NICBUF_SIZE_BUG;
-		err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
-		if (err)
-			printk("failed!\n");
-		else
-			printk("ok.\n");
-	}
-	if (err) {
-		printk("%s: Error %d allocating Tx buffer\n", dev->name, err);
-		goto out;
-	}
-
 	/* Make the hardware available, as long as it hasn't been
 	 * removed elsewhere (e.g. by PCMCIA hot unplug) */
 	spin_lock_irq(&priv->lock);
@@ -2450,7 +2445,7 @@
 	priv = netdev_priv(dev);
 	priv->ndev = dev;
 	if (sizeof_card)
-		priv->card = (void *)((unsigned long)netdev_priv(dev)
+		priv->card = (void *)((unsigned long)priv
 				      + sizeof(struct orinoco_private));
 	else
 		priv->card = NULL;
@@ -2555,6 +2550,7 @@
 	}
 
 	len = le16_to_cpu(essidbuf.len);
+	BUG_ON(len > IW_ESSID_MAX_SIZE);
 
 	memset(buf, 0, IW_ESSID_MAX_SIZE+1);
 	memcpy(buf, p, len);
@@ -2923,13 +2919,14 @@
 	memset(&essidbuf, 0, sizeof(essidbuf));
 
 	if (erq->flags) {
-		if (erq->length > IW_ESSID_MAX_SIZE)
+		/* iwconfig includes the NUL in the specified length */
+		if (erq->length > IW_ESSID_MAX_SIZE+1)
 			return -E2BIG;
 		
 		if (copy_from_user(&essidbuf, erq->pointer, erq->length))
 			return -EFAULT;
 
-		essidbuf[erq->length] = '\0';
+		essidbuf[IW_ESSID_MAX_SIZE] = '\0';
 	}
 
 	if (orinoco_lock(priv, &flags) != 0)
@@ -3855,7 +3852,6 @@
 				{ SIOCIWFIRSTPRIV + 0x7, 0,
 				  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
 				  "get_ibssport" },
-				{ SIOCIWLASTPRIV, 0, 0, "dump_recs" },
 			};
 
 			wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]);
@@ -3943,14 +3939,6 @@
 		err = orinoco_ioctl_getibssport(dev, wrq);
 		break;
 
-	case SIOCIWLASTPRIV:
-		err = orinoco_debug_dump_recs(dev);
-		if (err)
-			printk(KERN_ERR "%s: Unable to dump records (%d)\n",
-			       dev->name, err);
-		break;
-
-
 	default:
 		err = -EOPNOTSUPP;
 	}
@@ -3964,187 +3952,6 @@
 	return err;
 }
 
-struct {
-	u16 rid;
-	char *name;
-	int displaytype;
-#define DISPLAY_WORDS	0
-#define DISPLAY_BYTES	1
-#define DISPLAY_STRING	2
-#define DISPLAY_XSTRING	3
-} record_table[] = {
-#define DEBUG_REC(name,type) { HERMES_RID_##name, #name, DISPLAY_##type }
-	DEBUG_REC(CNFPORTTYPE,WORDS),
-	DEBUG_REC(CNFOWNMACADDR,BYTES),
-	DEBUG_REC(CNFDESIREDSSID,STRING),
-	DEBUG_REC(CNFOWNCHANNEL,WORDS),
-	DEBUG_REC(CNFOWNSSID,STRING),
-	DEBUG_REC(CNFOWNATIMWINDOW,WORDS),
-	DEBUG_REC(CNFSYSTEMSCALE,WORDS),
-	DEBUG_REC(CNFMAXDATALEN,WORDS),
-	DEBUG_REC(CNFPMENABLED,WORDS),
-	DEBUG_REC(CNFPMEPS,WORDS),
-	DEBUG_REC(CNFMULTICASTRECEIVE,WORDS),
-	DEBUG_REC(CNFMAXSLEEPDURATION,WORDS),
-	DEBUG_REC(CNFPMHOLDOVERDURATION,WORDS),
-	DEBUG_REC(CNFOWNNAME,STRING),
-	DEBUG_REC(CNFOWNDTIMPERIOD,WORDS),
-	DEBUG_REC(CNFMULTICASTPMBUFFERING,WORDS),
-	DEBUG_REC(CNFWEPENABLED_AGERE,WORDS),
-	DEBUG_REC(CNFMANDATORYBSSID_SYMBOL,WORDS),
-	DEBUG_REC(CNFWEPDEFAULTKEYID,WORDS),
-	DEBUG_REC(CNFDEFAULTKEY0,BYTES),
-	DEBUG_REC(CNFDEFAULTKEY1,BYTES),
-	DEBUG_REC(CNFMWOROBUST_AGERE,WORDS),
-	DEBUG_REC(CNFDEFAULTKEY2,BYTES),
-	DEBUG_REC(CNFDEFAULTKEY3,BYTES),
-	DEBUG_REC(CNFWEPFLAGS_INTERSIL,WORDS),
-	DEBUG_REC(CNFWEPKEYMAPPINGTABLE,WORDS),
-	DEBUG_REC(CNFAUTHENTICATION,WORDS),
-	DEBUG_REC(CNFMAXASSOCSTA,WORDS),
-	DEBUG_REC(CNFKEYLENGTH_SYMBOL,WORDS),
-	DEBUG_REC(CNFTXCONTROL,WORDS),
-	DEBUG_REC(CNFROAMINGMODE,WORDS),
-	DEBUG_REC(CNFHOSTAUTHENTICATION,WORDS),
-	DEBUG_REC(CNFRCVCRCERROR,WORDS),
-	DEBUG_REC(CNFMMLIFE,WORDS),
-	DEBUG_REC(CNFALTRETRYCOUNT,WORDS),
-	DEBUG_REC(CNFBEACONINT,WORDS),
-	DEBUG_REC(CNFAPPCFINFO,WORDS),
-	DEBUG_REC(CNFSTAPCFINFO,WORDS),
-	DEBUG_REC(CNFPRIORITYQUSAGE,WORDS),
-	DEBUG_REC(CNFTIMCTRL,WORDS),
-	DEBUG_REC(CNFTHIRTY2TALLY,WORDS),
-	DEBUG_REC(CNFENHSECURITY,WORDS),
-	DEBUG_REC(CNFGROUPADDRESSES,BYTES),
-	DEBUG_REC(CNFCREATEIBSS,WORDS),
-	DEBUG_REC(CNFFRAGMENTATIONTHRESHOLD,WORDS),
-	DEBUG_REC(CNFRTSTHRESHOLD,WORDS),
-	DEBUG_REC(CNFTXRATECONTROL,WORDS),
-	DEBUG_REC(CNFPROMISCUOUSMODE,WORDS),
-	DEBUG_REC(CNFBASICRATES_SYMBOL,WORDS),
-	DEBUG_REC(CNFPREAMBLE_SYMBOL,WORDS),
-	DEBUG_REC(CNFSHORTPREAMBLE,WORDS),
-	DEBUG_REC(CNFWEPKEYS_AGERE,BYTES),
-	DEBUG_REC(CNFEXCLUDELONGPREAMBLE,WORDS),
-	DEBUG_REC(CNFTXKEY_AGERE,WORDS),
-	DEBUG_REC(CNFAUTHENTICATIONRSPTO,WORDS),
-	DEBUG_REC(CNFBASICRATES,WORDS),
-	DEBUG_REC(CNFSUPPORTEDRATES,WORDS),
-	DEBUG_REC(CNFTICKTIME,WORDS),
-	DEBUG_REC(CNFSCANREQUEST,WORDS),
-	DEBUG_REC(CNFJOINREQUEST,WORDS),
-	DEBUG_REC(CNFAUTHENTICATESTATION,WORDS),
-	DEBUG_REC(CNFCHANNELINFOREQUEST,WORDS),
-	DEBUG_REC(MAXLOADTIME,WORDS),
-	DEBUG_REC(DOWNLOADBUFFER,WORDS),
-	DEBUG_REC(PRIID,WORDS),
-	DEBUG_REC(PRISUPRANGE,WORDS),
-	DEBUG_REC(CFIACTRANGES,WORDS),
-	DEBUG_REC(NICSERNUM,XSTRING),
-	DEBUG_REC(NICID,WORDS),
-	DEBUG_REC(MFISUPRANGE,WORDS),
-	DEBUG_REC(CFISUPRANGE,WORDS),
-	DEBUG_REC(CHANNELLIST,WORDS),
-	DEBUG_REC(REGULATORYDOMAINS,WORDS),
-	DEBUG_REC(TEMPTYPE,WORDS),
-/*  	DEBUG_REC(CIS,BYTES), */
-	DEBUG_REC(STAID,WORDS),
-	DEBUG_REC(CURRENTSSID,STRING),
-	DEBUG_REC(CURRENTBSSID,BYTES),
-	DEBUG_REC(COMMSQUALITY,WORDS),
-	DEBUG_REC(CURRENTTXRATE,WORDS),
-	DEBUG_REC(CURRENTBEACONINTERVAL,WORDS),
-	DEBUG_REC(CURRENTSCALETHRESHOLDS,WORDS),
-	DEBUG_REC(PROTOCOLRSPTIME,WORDS),
-	DEBUG_REC(SHORTRETRYLIMIT,WORDS),
-	DEBUG_REC(LONGRETRYLIMIT,WORDS),
-	DEBUG_REC(MAXTRANSMITLIFETIME,WORDS),
-	DEBUG_REC(MAXRECEIVELIFETIME,WORDS),
-	DEBUG_REC(CFPOLLABLE,WORDS),
-	DEBUG_REC(AUTHENTICATIONALGORITHMS,WORDS),
-	DEBUG_REC(PRIVACYOPTIONIMPLEMENTED,WORDS),
-	DEBUG_REC(OWNMACADDR,BYTES),
-	DEBUG_REC(SCANRESULTSTABLE,WORDS),
-	DEBUG_REC(PHYTYPE,WORDS),
-	DEBUG_REC(CURRENTCHANNEL,WORDS),
-	DEBUG_REC(CURRENTPOWERSTATE,WORDS),
-	DEBUG_REC(CCAMODE,WORDS),
-	DEBUG_REC(SUPPORTEDDATARATES,WORDS),
-	DEBUG_REC(BUILDSEQ,BYTES),
-	DEBUG_REC(FWID,XSTRING)
-#undef DEBUG_REC
-};
-
-#define DEBUG_LTV_SIZE		128
-
-static int orinoco_debug_dump_recs(struct net_device *dev)
-{
-	struct orinoco_private *priv = netdev_priv(dev);
-	hermes_t *hw = &priv->hw;
-	u8 *val8;
-	u16 *val16;
-	int i,j;
-	u16 length;
-	int err;
-
-	/* I'm not sure: we might have a lock here, so we'd better go
-           atomic, just in case. */
-	val8 = kmalloc(DEBUG_LTV_SIZE + 2, GFP_ATOMIC);
-	if (! val8)
-		return -ENOMEM;
-	val16 = (u16 *)val8;
-
-	for (i = 0; i < ARRAY_SIZE(record_table); i++) {
-		u16 rid = record_table[i].rid;
-		int len;
-
-		memset(val8, 0, DEBUG_LTV_SIZE + 2);
-
-		err = hermes_read_ltv(hw, USER_BAP, rid, DEBUG_LTV_SIZE,
-				      &length, val8);
-		if (err) {
-			DEBUG(0, "Error %d reading RID 0x%04x\n", err, rid);
-			continue;
-		}
-		val16 = (u16 *)val8;
-		if (length == 0)
-			continue;
-
-		printk(KERN_DEBUG "%-15s (0x%04x): length=%d (%d bytes)\tvalue=",
-		       record_table[i].name,
-		       rid, length, (length-1)*2);
-		len = min(((int)length-1)*2, DEBUG_LTV_SIZE);
-
-		switch (record_table[i].displaytype) {
-		case DISPLAY_WORDS:
-			for (j = 0; j < len / 2; j++)
-				printk("%04X-", le16_to_cpu(val16[j]));
-			break;
-
-		case DISPLAY_BYTES:
-		default:
-			for (j = 0; j < len; j++)
-				printk("%02X:", val8[j]);
-			break;
-
-		case DISPLAY_STRING:
-			len = min(len, le16_to_cpu(val16[0])+2);
-			val8[len] = '\0';
-			printk("\"%s\"", (char *)&val16[1]);
-			break;
-
-		case DISPLAY_XSTRING:
-			printk("'%s'", (char *)val8);
-		}
-
-		printk("\n");
-	}
-
-	kfree(val8);
-
-	return 0;
-}
 
 /********************************************************************/
 /* Debugging                                                        */
@@ -4218,7 +4025,6 @@
 
 EXPORT_SYMBOL(__orinoco_up);
 EXPORT_SYMBOL(__orinoco_down);
-EXPORT_SYMBOL(orinoco_stop);
 EXPORT_SYMBOL(orinoco_reinit_firmware);
 
 EXPORT_SYMBOL(orinoco_interrupt);
diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h
index 13e42c2..f749b50 100644
--- a/drivers/net/wireless/orinoco.h
+++ b/drivers/net/wireless/orinoco.h
@@ -119,7 +119,6 @@
 extern void free_orinocodev(struct net_device *dev);
 extern int __orinoco_up(struct net_device *dev);
 extern int __orinoco_down(struct net_device *dev);
-extern int orinoco_stop(struct net_device *dev);
 extern int orinoco_reinit_firmware(struct net_device *dev);
 extern irqreturn_t orinoco_interrupt(int irq, void * dev_id, struct pt_regs *regs);
 
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index ec8cf29f..6c42b57 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -2828,7 +2828,7 @@
 	/* Unregister with the /proc/net file here. */
 	proc_net_remove("strip");
 
-	if ((i = tty_register_ldisc(N_STRIP, NULL)))
+	if ((i = tty_unregister_ldisc(N_STRIP)))
 		printk(KERN_ERR "STRIP: can't unregister line discipline (err = %d)\n", i);
 
 	printk(signoff);
diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
index 55720dc..531b073 100644
--- a/drivers/oprofile/buffer_sync.c
+++ b/drivers/oprofile/buffer_sync.c
@@ -62,7 +62,7 @@
 	/* To avoid latency problems, we only process the current CPU,
 	 * hoping that most samples for the task are on this CPU
 	 */
-	sync_buffer(_smp_processor_id());
+	sync_buffer(raw_smp_processor_id());
   	return 0;
 }
 
@@ -86,7 +86,7 @@
 		/* To avoid latency problems, we only process the current CPU,
 		 * hoping that most samples for the task are on this CPU
 		 */
-		sync_buffer(_smp_processor_id());
+		sync_buffer(raw_smp_processor_id());
 		return 0;
 	}
 
@@ -206,7 +206,7 @@
  */
 static unsigned long get_exec_dcookie(struct mm_struct * mm)
 {
-	unsigned long cookie = 0;
+	unsigned long cookie = NO_COOKIE;
 	struct vm_area_struct * vma;
  
 	if (!mm)
@@ -234,35 +234,42 @@
  */
 static unsigned long lookup_dcookie(struct mm_struct * mm, unsigned long addr, off_t * offset)
 {
-	unsigned long cookie = 0;
+	unsigned long cookie = NO_COOKIE;
 	struct vm_area_struct * vma;
 
 	for (vma = find_vma(mm, addr); vma; vma = vma->vm_next) {
  
-		if (!vma->vm_file)
-			continue;
-
 		if (addr < vma->vm_start || addr >= vma->vm_end)
 			continue;
 
-		cookie = fast_get_dcookie(vma->vm_file->f_dentry,
-			vma->vm_file->f_vfsmnt);
-		*offset = (vma->vm_pgoff << PAGE_SHIFT) + addr - vma->vm_start; 
+		if (vma->vm_file) {
+			cookie = fast_get_dcookie(vma->vm_file->f_dentry,
+				vma->vm_file->f_vfsmnt);
+			*offset = (vma->vm_pgoff << PAGE_SHIFT) + addr -
+				vma->vm_start;
+		} else {
+			/* must be an anonymous map */
+			*offset = addr;
+		}
+
 		break;
 	}
 
+	if (!vma)
+		cookie = INVALID_COOKIE;
+
 	return cookie;
 }
 
 
-static unsigned long last_cookie = ~0UL;
+static unsigned long last_cookie = INVALID_COOKIE;
  
 static void add_cpu_switch(int i)
 {
 	add_event_entry(ESCAPE_CODE);
 	add_event_entry(CPU_SWITCH_CODE);
 	add_event_entry(i);
-	last_cookie = ~0UL;
+	last_cookie = INVALID_COOKIE;
 }
 
 static void add_kernel_ctx_switch(unsigned int in_kernel)
@@ -317,7 +324,7 @@
  
  	cookie = lookup_dcookie(mm, s->eip, &offset);
  
-	if (!cookie) {
+	if (cookie == INVALID_COOKIE) {
 		atomic_inc(&oprofile_stats.sample_lost_no_mapping);
 		return 0;
 	}
diff --git a/drivers/oprofile/event_buffer.h b/drivers/oprofile/event_buffer.h
index 442aaad..0180236 100644
--- a/drivers/oprofile/event_buffer.h
+++ b/drivers/oprofile/event_buffer.h
@@ -35,6 +35,9 @@
 #define TRACE_BEGIN_CODE		8
 #define TRACE_END_CODE			9
  
+#define INVALID_COOKIE ~0UL
+#define NO_COOKIE 0UL
+
 /* add data to the event buffer */
 void add_event_entry(unsigned long data);
  
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
index e7f3bcb..80edfa3 100644
--- a/drivers/parport/parport_pc.c
+++ b/drivers/parport/parport_pc.c
@@ -2751,7 +2751,6 @@
 	netmos_9755,
 	netmos_9805,
 	netmos_9815,
-	netmos_9855,
 };
 
 
@@ -2826,7 +2825,6 @@
         /* netmos_9755 */               { 2, { { 0, 1 }, { 2, 3 },} }, /* untested */
 	/* netmos_9805 */               { 1, { { 0, -1 }, } }, /* untested */
 	/* netmos_9815 */               { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */
-	/* netmos_9855 */               { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */
 };
 
 static struct pci_device_id parport_pc_pci_tbl[] = {
@@ -2907,8 +2905,6 @@
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9805 },
 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9815,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9815 },
-	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 },
 	{ 0, } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl);
diff --git a/drivers/parport/parport_serial.c b/drivers/parport/parport_serial.c
index 6715a17..00498e2 100644
--- a/drivers/parport/parport_serial.c
+++ b/drivers/parport/parport_serial.c
@@ -34,6 +34,7 @@
 	titan_110l = 0,
 	titan_210l,
 	netmos_9xx5_combo,
+	netmos_9855,
 	avlab_1s1p,
 	avlab_1s1p_650,
 	avlab_1s1p_850,
@@ -87,6 +88,7 @@
 	/* titan_110l */		{ 1, { { 3, -1 }, } },
 	/* titan_210l */		{ 1, { { 3, -1 }, } },
 	/* netmos_9xx5_combo */		{ 1, { { 2, -1 }, }, netmos_parallel_init },
+	/* netmos_9855 */		{ 1, { { 0, -1 }, }, netmos_parallel_init },
 	/* avlab_1s1p     */		{ 1, { { 1, 2}, } },
 	/* avlab_1s1p_650 */		{ 1, { { 1, 2}, } },
 	/* avlab_1s1p_850 */		{ 1, { { 1, 2}, } },
@@ -120,7 +122,7 @@
 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9845,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
 	{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9855,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9xx5_combo },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, netmos_9855 },
 	/* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/
 	{ 0x14db, 0x2110, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p},
 	{ 0x14db, 0x2111, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1s1p_650},
@@ -207,6 +209,7 @@
 /* titan_110l */	{ SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 1, 921600 },
 /* titan_210l */	{ SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 },
 /* netmos_9xx5_combo */	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200, 0, 0, netmos_serial_init },
+/* netmos_9855 */	{ SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200, 0, 0, netmos_serial_init },
 /* avlab_1s1p (n/t) */	{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
 /* avlab_1s1p_650 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
 /* avlab_1s1p_850 (nt)*/{ SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 },
diff --git a/drivers/parport/probe.c b/drivers/parport/probe.c
index c949631..6e6f42d 100644
--- a/drivers/parport/probe.c
+++ b/drivers/parport/probe.c
@@ -48,14 +48,6 @@
 	printk("\n");
 }
 
-static char *strdup(char *str)
-{
-	int n = strlen(str)+1;
-	char *s = kmalloc(n, GFP_KERNEL);
-	if (!s) return NULL;
-	return strcpy(s, str);
-}
-
 static void parse_data(struct parport *port, int device, char *str)
 {
 	char *txt = kmalloc(strlen(str)+1, GFP_KERNEL);
@@ -88,16 +80,16 @@
 			if (!strcmp(p, "MFG") || !strcmp(p, "MANUFACTURER")) {
 				if (info->mfr)
 					kfree (info->mfr);
-				info->mfr = strdup(sep);
+				info->mfr = kstrdup(sep, GFP_KERNEL);
 			} else if (!strcmp(p, "MDL") || !strcmp(p, "MODEL")) {
 				if (info->model)
 					kfree (info->model);
-				info->model = strdup(sep);
+				info->model = kstrdup(sep, GFP_KERNEL);
 			} else if (!strcmp(p, "CLS") || !strcmp(p, "CLASS")) {
 				int i;
 				if (info->class_name)
 					kfree (info->class_name);
-				info->class_name = strdup(sep);
+				info->class_name = kstrdup(sep, GFP_KERNEL);
 				for (u = sep; *u; u++)
 					*u = toupper(*u);
 				for (i = 0; classes[i].token; i++) {
@@ -112,7 +104,7 @@
 				   !strcmp(p, "COMMAND SET")) {
 				if (info->cmdset)
 					kfree (info->cmdset);
-				info->cmdset = strdup(sep);
+				info->cmdset = kstrdup(sep, GFP_KERNEL);
 				/* if it speaks printer language, it's
 				   probably a printer */
 				if (strstr(sep, "PJL") || strstr(sep, "PCL"))
@@ -120,7 +112,7 @@
 			} else if (!strcmp(p, "DES") || !strcmp(p, "DESCRIPTION")) {
 				if (info->description)
 					kfree (info->description);
-				info->description = strdup(sep);
+				info->description = kstrdup(sep, GFP_KERNEL);
 			}
 		}
 	rock_on:
diff --git a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c
index 8132d94..30af105 100644
--- a/drivers/pci/hotplug/cpci_hotplug_core.c
+++ b/drivers/pci/hotplug/cpci_hotplug_core.c
@@ -217,6 +217,8 @@
 	kfree(slot->hotplug_slot->info);
 	kfree(slot->hotplug_slot->name);
 	kfree(slot->hotplug_slot);
+	if (slot->dev)
+		pci_dev_put(slot->dev);
 	kfree(slot);
 }
 
diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c
index c878028..225b5e5 100644
--- a/drivers/pci/hotplug/cpci_hotplug_pci.c
+++ b/drivers/pci/hotplug/cpci_hotplug_pci.c
@@ -315,9 +315,12 @@
 				    PCI_DEVFN(PCI_SLOT(slot->devfn), i));
 		if (dev) {
 			pci_remove_bus_device(dev);
-			slot->dev = NULL;
+			pci_dev_put(dev);
 		}
 	}
+	pci_dev_put(slot->dev);
+	slot->dev = NULL;
+
 	dbg("%s - exit", __FUNCTION__);
 	return 0;
 }
diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c
index 41c7971..4c11048 100644
--- a/drivers/pci/hotplug/cpqphp_sysfs.c
+++ b/drivers/pci/hotplug/cpqphp_sysfs.c
@@ -38,7 +38,7 @@
 
 /* A few routines that create sysfs entries for the hot plug controller */
 
-static ssize_t show_ctrl (struct device *dev, char *buf)
+static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct pci_dev *pci_dev;
 	struct controller *ctrl;
@@ -82,7 +82,7 @@
 }
 static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL);
 
-static ssize_t show_dev (struct device *dev, char *buf)
+static ssize_t show_dev (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct pci_dev *pci_dev;
 	struct controller *ctrl;
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
index c802f62..c428290 100644
--- a/drivers/pci/hotplug/pci_hotplug_core.c
+++ b/drivers/pci/hotplug/pci_hotplug_core.c
@@ -73,7 +73,7 @@
 {
 	struct hotplug_slot *slot = to_hotplug_slot(kobj);
 	struct hotplug_slot_attribute *attribute = to_hotplug_attr(attr);
-	return attribute->show ? attribute->show(slot, buf) : 0;
+	return attribute->show ? attribute->show(slot, buf) : -EIO;
 }
 
 static ssize_t hotplug_slot_attr_store(struct kobject *kobj,
@@ -81,7 +81,7 @@
 {
 	struct hotplug_slot *slot = to_hotplug_slot(kobj);
 	struct hotplug_slot_attribute *attribute = to_hotplug_attr(attr);
-	return attribute->store ? attribute->store(slot, buf, len) : 0;
+	return attribute->store ? attribute->store(slot, buf, len) : -EIO;
 }
 
 static struct sysfs_ops hotplug_slot_sysfs_ops = {
diff --git a/drivers/pci/hotplug/rpadlpar_sysfs.c b/drivers/pci/hotplug/rpadlpar_sysfs.c
index 3285b82..752e651 100644
--- a/drivers/pci/hotplug/rpadlpar_sysfs.c
+++ b/drivers/pci/hotplug/rpadlpar_sysfs.c
@@ -48,7 +48,7 @@
 	struct dlpar_io_attr *dlpar_attr = container_of(attr,
 						struct dlpar_io_attr, attr);
 	return dlpar_attr->store ?
-		dlpar_attr->store(dlpar_attr, buf, nbytes) : 0;
+		dlpar_attr->store(dlpar_attr, buf, nbytes) : -EIO;
 }
 
 static struct sysfs_ops dlpar_attr_sysfs_ops = {
diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c
index 9a1ee13..c9445eb 100644
--- a/drivers/pci/hotplug/shpchp_sysfs.c
+++ b/drivers/pci/hotplug/shpchp_sysfs.c
@@ -38,7 +38,7 @@
 
 /* A few routines that create sysfs entries for the hot plug controller */
 
-static ssize_t show_ctrl (struct device *dev, char *buf)
+static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct pci_dev *pci_dev;
 	struct controller *ctrl;
@@ -82,7 +82,7 @@
 }
 static DEVICE_ATTR (ctrl, S_IRUGO, show_ctrl, NULL);
 
-static ssize_t show_dev (struct device *dev, char *buf)
+static ssize_t show_dev (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct pci_dev *pci_dev;
 	struct controller *ctrl;
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index fe98553..e65bf2b 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -335,13 +335,14 @@
 {
 	struct device_driver *driver = kobj_to_pci_driver(kobj);
 	struct driver_attribute *dattr = attr_to_driver_attribute(attr);
-	ssize_t ret = 0;
+	ssize_t ret;
 
-	if (get_driver(driver)) {
-		if (dattr->show)
-			ret = dattr->show(driver, buf);
-		put_driver(driver);
-	}
+	if (!get_driver(driver))
+		return -ENODEV;
+
+	ret = dattr->show ? dattr->show(driver, buf) : -EIO;
+
+	put_driver(driver);
 	return ret;
 }
 
@@ -351,13 +352,14 @@
 {
 	struct device_driver *driver = kobj_to_pci_driver(kobj);
 	struct driver_attribute *dattr = attr_to_driver_attribute(attr);
-	ssize_t ret = 0;
+	ssize_t ret;
 
-	if (get_driver(driver)) {
-		if (dattr->store)
-			ret = dattr->store(driver, buf, count);
-		put_driver(driver);
-	}
+	if (!get_driver(driver))
+		return -ENODEV;
+
+	ret = dattr->store ? dattr->store(driver, buf, count) : -EIO;
+
+	put_driver(driver);
 	return ret;
 }
 
@@ -393,7 +395,10 @@
 	drv->driver.bus = &pci_bus_type;
 	drv->driver.probe = pci_device_probe;
 	drv->driver.remove = pci_device_remove;
-	drv->driver.shutdown = pci_device_shutdown,
+	/* FIXME, once all of the existing PCI drivers have been fixed to set
+	 * the pci shutdown function, this test can go away. */
+	if (!drv->driver.shutdown)
+		drv->driver.shutdown = pci_device_shutdown;
 	drv->driver.owner = drv->owner;
 	drv->driver.kobj.ktype = &pci_driver_kobj_type;
 	pci_init_dynids(&drv->dynids);
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 6ca0061..a15f940 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -29,7 +29,7 @@
 /* show configuration fields */
 #define pci_config_attr(field, format_string)				\
 static ssize_t								\
-field##_show(struct device *dev, char *buf)				\
+field##_show(struct device *dev, struct device_attribute *attr, char *buf)				\
 {									\
 	struct pci_dev *pdev;						\
 									\
@@ -44,7 +44,7 @@
 pci_config_attr(class, "0x%06x\n");
 pci_config_attr(irq, "%u\n");
 
-static ssize_t local_cpus_show(struct device *dev, char *buf)
+static ssize_t local_cpus_show(struct device *dev, struct device_attribute *attr, char *buf)
 {		
 	cpumask_t mask = pcibus_to_cpumask(to_pci_dev(dev)->bus);
 	int len = cpumask_scnprintf(buf, PAGE_SIZE-2, mask);
@@ -54,7 +54,7 @@
 
 /* show resources */
 static ssize_t
-resource_show(struct device * dev, char * buf)
+resource_show(struct device * dev, struct device_attribute *attr, char * buf)
 {
 	struct pci_dev * pci_dev = to_pci_dev(dev);
 	char * str = buf;
@@ -73,7 +73,7 @@
 	return (str - buf);
 }
 
-static ssize_t modalias_show(struct device *dev, char *buf)
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct pci_dev *pci_dev = to_pci_dev(dev);
 
@@ -339,16 +339,17 @@
 		if (!pci_resource_len(pdev, i))
 			continue;
 
-		res_attr = kmalloc(sizeof(*res_attr) + 10, GFP_ATOMIC);
+		/* allocate attribute structure, piggyback attribute name */
+		res_attr = kcalloc(1, sizeof(*res_attr) + 10, GFP_ATOMIC);
 		if (res_attr) {
-			memset(res_attr, 0, sizeof(*res_attr) + 10);
+			char *res_attr_name = (char *)(res_attr + 1);
+
 			pdev->res_attr[i] = res_attr;
-			/* Allocated above after the res_attr struct */
-			res_attr->attr.name = (char *)(res_attr + 1);
-			sprintf(res_attr->attr.name, "resource%d", i);
-			res_attr->size = pci_resource_len(pdev, i);
+			sprintf(res_attr_name, "resource%d", i);
+			res_attr->attr.name = res_attr_name;
 			res_attr->attr.mode = S_IRUSR | S_IWUSR;
 			res_attr->attr.owner = THIS_MODULE;
+			res_attr->size = pci_resource_len(pdev, i);
 			res_attr->mmap = pci_mmap_resource;
 			res_attr->private = &pdev->resource[i];
 			sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
diff --git a/drivers/pci/pci.ids b/drivers/pci/pci.ids
index 93481b4..1d2ef1e 100644
--- a/drivers/pci/pci.ids
+++ b/drivers/pci/pci.ids
@@ -7173,6 +7173,7 @@
 	080f  Sentry5 DDR/SDR RAM Controller
 	0811  Sentry5 External Interface Core
 	0816  BCM3302 Sentry5 MIPS32 CPU
+	1600  NetXtreme BCM5752 Gigabit Ethernet PCI Express
 	1644  NetXtreme BCM5700 Gigabit Ethernet
 		1014 0277  Broadcom Vigil B5700 1000Base-T
 		1028 00d1  Broadcom BCM5700
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c
index 5762857..f5c5f10 100644
--- a/drivers/pci/pcie/portdrv_core.c
+++ b/drivers/pci/pcie/portdrv_core.c
@@ -232,19 +232,16 @@
 	/* Initialize generic device interface */
 	device = &dev->device;
 	memset(device, 0, sizeof(struct device));
-	INIT_LIST_HEAD(&device->node);
-	INIT_LIST_HEAD(&device->children);
-	INIT_LIST_HEAD(&device->bus_list);
 	device->bus = &pcie_port_bus_type;
 	device->driver = NULL;
-	device->driver_data = NULL; 
+	device->driver_data = NULL;
 	device->release = release_pcie_device;	/* callback to free pcie dev */
-	sprintf(&device->bus_id[0], "pcie%02x", 
+	sprintf(&device->bus_id[0], "pcie%02x",
 		get_descriptor_id(port_type, service_type));
 	device->parent = &parent->dev;
 }
 
-static struct pcie_device* alloc_pcie_device(struct pci_dev *parent, 
+static struct pcie_device* alloc_pcie_device(struct pci_dev *parent,
 	int port_type, int service_type, int irq, int irq_mode)
 {
 	struct pcie_device *device;
@@ -270,9 +267,9 @@
 	pci_read_config_word(dev, pos + PCIE_CAPABILITIES_REG, &reg);
 	type = (reg >> 4) & PORT_TYPE_MASK;
 	if (	type == PCIE_RC_PORT || type == PCIE_SW_UPSTREAM_PORT ||
-		type == PCIE_SW_DOWNSTREAM_PORT )  
+		type == PCIE_SW_DOWNSTREAM_PORT )
 		return 0;
- 
+
 	return -ENODEV;
 }
 
@@ -283,8 +280,8 @@
 	u16 reg16;
 
 	/* Get port type */
-	pci_read_config_word(dev, 
-		pci_find_capability(dev, PCI_CAP_ID_EXP) + 
+	pci_read_config_word(dev,
+		pci_find_capability(dev, PCI_CAP_ID_EXP) +
 		PCIE_CAPABILITIES_REG, &reg16);
 	type = (reg16 >> 4) & PORT_TYPE_MASK;
 
@@ -299,11 +296,11 @@
 		if (capabilities & (1 << i)) {
 			child = alloc_pcie_device(
 				dev, 		/* parent */
-				type,		/* port type */ 
+				type,		/* port type */
 				i,		/* service type */
 				vectors[i],	/* irq */
 				irq_mode	/* interrupt mode */);
-			if (child) { 
+			if (child) {
 				status = device_register(&child->device);
 				if (status) {
 					kfree(child);
@@ -317,84 +314,78 @@
 }
 
 #ifdef CONFIG_PM
-int pcie_port_device_suspend(struct pci_dev *dev, pm_message_t state)
+static int suspend_iter(struct device *dev, void *data)
 {
-	struct list_head 		*head, *tmp;
-	struct device 			*parent, *child;
-	struct device_driver 		*driver;
 	struct pcie_port_service_driver *service_driver;
+	u32 state = (u32)data;
 
-	parent = &dev->dev;
-	head = &parent->children;
-	tmp = head->next;
-	while (head != tmp) {
-		child = container_of(tmp, struct device, node);
-		tmp = tmp->next;
-		if (child->bus != &pcie_port_bus_type)
-			continue;
-		driver = child->driver;
-		if (!driver)
-			continue;
-		service_driver = to_service_driver(driver);
-		if (service_driver->suspend)  
-			service_driver->suspend(to_pcie_device(child), state);
-	}
-	return 0; 
+ 	if ((dev->bus == &pcie_port_bus_type) &&
+ 	    (dev->driver)) {
+ 		service_driver = to_service_driver(dev->driver);
+ 		if (service_driver->suspend)
+ 			service_driver->suspend(to_pcie_device(dev), state);
+  	}
+	return 0;
 }
 
-int pcie_port_device_resume(struct pci_dev *dev) 
-{ 
-	struct list_head 		*head, *tmp;
-	struct device 			*parent, *child;
-	struct device_driver 		*driver;
+int pcie_port_device_suspend(struct pci_dev *dev, u32 state)
+{
+	device_for_each_child(&dev->dev, (void *)state, suspend_iter);
+	return 0;
+}
+
+static int resume_iter(struct device *dev, void *data)
+{
 	struct pcie_port_service_driver *service_driver;
 
-	parent = &dev->dev;
-	head = &parent->children;
-	tmp = head->next;
-	while (head != tmp) {
-		child = container_of(tmp, struct device, node);
-		tmp = tmp->next;
-		if (child->bus != &pcie_port_bus_type)
-			continue;
-		driver = child->driver;
-		if (!driver)
-			continue;
-		service_driver = to_service_driver(driver);
-		if (service_driver->resume)  
-			service_driver->resume(to_pcie_device(child));
+	if ((dev->bus == &pcie_port_bus_type) &&
+	    (dev->driver)) {
+		service_driver = to_service_driver(dev->driver);
+		if (service_driver->resume)
+			service_driver->resume(to_pcie_device(dev));
 	}
-	return 0; 
+	return 0;
+}
 
+int pcie_port_device_resume(struct pci_dev *dev)
+{
+	device_for_each_child(&dev->dev, NULL, resume_iter);
+	return 0;
 }
 #endif
 
+static int remove_iter(struct device *dev, void *data)
+{
+	struct pcie_port_service_driver *service_driver;
+
+	if (dev->bus == &pcie_port_bus_type) {
+		if (dev->driver) {
+			service_driver = to_service_driver(dev->driver);
+			if (service_driver->remove)
+				service_driver->remove(to_pcie_device(dev));
+		}
+		*(unsigned long*)data = (unsigned long)dev;
+		return 1;
+	}
+	return 0;
+}
+
 void pcie_port_device_remove(struct pci_dev *dev)
 {
-	struct list_head 		*head, *tmp;
-	struct device 			*parent, *child;
-	struct device_driver 		*driver;
-	struct pcie_port_service_driver *service_driver;
+	struct device *device;
+	unsigned long device_addr;
 	int interrupt_mode = PCIE_PORT_INTx_MODE;
+	int status;
 
-	parent = &dev->dev;
-	head = &parent->children;
-	tmp = head->next;
-	while (head != tmp) {
-		child = container_of(tmp, struct device, node);
-		tmp = tmp->next;
-		if (child->bus != &pcie_port_bus_type)
-			continue;
-		driver = child->driver;
-		if (driver) { 
-			service_driver = to_service_driver(driver);
-			if (service_driver->remove)  
-				service_driver->remove(to_pcie_device(child));
+	do {
+		status = device_for_each_child(&dev->dev, &device_addr, remove_iter);
+		if (status) {
+			device = (struct device*)device_addr;
+			interrupt_mode = (to_pcie_device(device))->interrupt_mode;
+			put_device(device);
+			device_unregister(device);
 		}
-		interrupt_mode = (to_pcie_device(child))->interrupt_mode;
-		put_device(child);
-		device_unregister(child);
-	}
+	} while (status);
 	/* Switch to INTx by default if MSI enabled */
 	if (interrupt_mode == PCIE_PORT_MSIX_MODE)
 		pci_disable_msix(dev);
@@ -423,7 +414,7 @@
 	new->driver.resume = pcie_port_resume_service;
 
 	return driver_register(&new->driver);
-} 
+}
 
 void pcie_port_service_unregister(struct pcie_port_service_driver *new)
 {
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index b7ae878..fd48b20 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -125,7 +125,7 @@
 /*
  * Find the extent of a PCI decode..
  */
-static u32 pci_size(u32 base, u32 maxbase, unsigned long mask)
+static u32 pci_size(u32 base, u32 maxbase, u32 mask)
 {
 	u32 size = mask & maxbase;	/* Find the significant bits */
 	if (!size)
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 637e949..968033f 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -456,21 +456,16 @@
 } 
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC,         quirk_amd_8131_ioapic ); 
 
+static void __init quirk_svw_msi(struct pci_dev *dev)
+{
+	pci_msi_quirk = 1;
+	printk(KERN_WARNING "PCI: MSI quirk detected. pci_msi_quirk set.\n");
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_GCNB_LE, quirk_svw_msi );
 #endif /* CONFIG_X86_IO_APIC */
 
 
 /*
- * Via 686A/B:  The PCI_INTERRUPT_LINE register for the on-chip
- * devices, USB0/1, AC97, MC97, and ACPI, has an unusual feature:
- * when written, it makes an internal connection to the PIC.
- * For these devices, this register is defined to be 4 bits wide.
- * Normally this is fine.  However for IO-APIC motherboards, or
- * non-x86 architectures (yes Via exists on PPC among other places),
- * we must mask the PCI_INTERRUPT_LINE value versus 0xf to get
- * interrupts delivered properly.
- */
-
-/*
  * FIXME: it is questionable that quirk_via_acpi
  * is needed.  It shows up as an ISA bridge, and does not
  * support the PCI_INTERRUPT_LINE register at all.  Therefore
@@ -492,28 +487,30 @@
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_3,	quirk_via_acpi );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_4,	quirk_via_acpi );
 
-static void quirk_via_irqpic(struct pci_dev *dev)
+/*
+ * Via 686A/B:  The PCI_INTERRUPT_LINE register for the on-chip
+ * devices, USB0/1, AC97, MC97, and ACPI, has an unusual feature:
+ * when written, it makes an internal connection to the PIC.
+ * For these devices, this register is defined to be 4 bits wide.
+ * Normally this is fine.  However for IO-APIC motherboards, or
+ * non-x86 architectures (yes Via exists on PPC among other places),
+ * we must mask the PCI_INTERRUPT_LINE value versus 0xf to get
+ * interrupts delivered properly.
+ */
+static void quirk_via_irq(struct pci_dev *dev)
 {
 	u8 irq, new_irq;
 
-#ifdef CONFIG_X86_IO_APIC
-	if (nr_ioapics && !skip_ioapic_setup)
-		return;
-#endif
-#ifdef CONFIG_ACPI
-	if (acpi_irq_model != ACPI_IRQ_MODEL_PIC)
-		return;
-#endif
 	new_irq = dev->irq & 0xf;
 	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
 	if (new_irq != irq) {
-		printk(KERN_INFO "PCI: Via PIC IRQ fixup for %s, from %d to %d\n",
+		printk(KERN_INFO "PCI: Via IRQ fixup for %s, from %d to %d\n",
 			pci_name(dev), irq, new_irq);
 		udelay(15);	/* unknown if delay really needed */
 		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);
 	}
 }
-DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irqpic);
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irq);
 
 /*
  * PIIX3 USB: We have to disable USB interrupts that are
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index 6375ebc..14e4124 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -171,19 +171,21 @@
 config M32R_PCC
 	bool "M32R PCMCIA I/F"
 	depends on M32R && CHIP_M32700 && PCMCIA
+	select PCCARD_NONSTATIC
 	help
 	  Say Y here to use the M32R PCMCIA controller.
 
 config M32R_CFC
 	bool "M32R CF I/F Controller"
-	depends on M32R && (PLAT_USRV || PLAT_M32700UT || PLAT_MAPPI2 || PLAT_OPSPUT)
+	depends on M32R && (PLAT_USRV || PLAT_M32700UT || PLAT_MAPPI2 || PLAT_MAPPI3 || PLAT_OPSPUT)
+	select PCCARD_NONSTATIC
 	help
 	  Say Y here to use the M32R CompactFlash controller.
 
 config M32R_CFC_NUM
 	int "M32R CF I/F number"
 	depends on M32R_CFC
-	default "1" if PLAT_USRV || PLAT_M32700UT || PLAT_MAPPI2 || PLAT_OPSPUT
+	default "1" if PLAT_USRV || PLAT_M32700UT || PLAT_MAPPI2 || PLAT_MAPPI3 || PLAT_OPSPUT
 	help
 	  Set the number of M32R CF slots.
 
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 03fc885..48e4f04 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -508,6 +508,10 @@
 		cs_err(skt, "unsupported voltage key.\n");
 		return CS_BAD_TYPE;
 	}
+
+	if (skt->power_hook)
+		skt->power_hook(skt, HOOK_POWER_PRE);
+
 	skt->socket.flags = 0;
 	skt->ops->set_socket(skt, &skt->socket);
 
@@ -522,7 +526,12 @@
 		return CS_BAD_TYPE;
 	}
 
-	return socket_reset(skt);
+	status = socket_reset(skt);
+
+	if (skt->power_hook)
+		skt->power_hook(skt, HOOK_POWER_POST);
+
+	return status;
 }
 
 /*
@@ -709,7 +718,7 @@
 		}
 
 		schedule();
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 
 		if (!skt->thread)
 			break;
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index c4ade28..569e55f 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -604,14 +604,14 @@
 /************************ per-device sysfs output ***************************/
 
 #define pcmcia_device_attr(field, test, format)				\
-static ssize_t field##_show (struct device *dev, char *buf)		\
+static ssize_t field##_show (struct device *dev, struct device_attribute *attr, char *buf)		\
 {									\
 	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);		\
 	return p_dev->test ? sprintf (buf, format, p_dev->field) : -ENODEV; \
 }
 
 #define pcmcia_device_stringattr(name, field)					\
-static ssize_t name##_show (struct device *dev, char *buf)		\
+static ssize_t name##_show (struct device *dev, struct device_attribute *attr, char *buf)		\
 {									\
 	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);		\
 	return p_dev->field ? sprintf (buf, "%s\n", p_dev->field) : -ENODEV; \
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index 581bfa9..b1111c6 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -24,9 +24,9 @@
 #include <linux/workqueue.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
+#include <linux/bitops.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/bitops.h>
 #include <asm/system.h>
 
 #include <pcmcia/version.h>
@@ -444,7 +444,7 @@
 		debug(3, "m32r_cfc: _pcc_get_status: "
 			 "power off (CPCR=0x%08x)\n", status);
 	}
-#elif defined(CONFIG_PLAT_MAPPI2)
+#elif defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3)
 	if ( status ) {
 		status = pcc_get(sock, (unsigned int)PLD_CPCR);
 		if (status == 0) { /* power off */
@@ -452,18 +452,23 @@
 			pcc_set(sock, (unsigned int)PLD_CFBUFCR,0); /* force buffer off for ZA-36 */
 			udelay(50);
 		}
-		status = pcc_get(sock, (unsigned int)PLD_CFBUFCR);
-		if (status != 0) { /* buffer off */
-			pcc_set(sock, (unsigned int)PLD_CFBUFCR,0);
-			udelay(50);
-			pcc_set(sock, (unsigned int)PLD_CFRSTCR, 0x0101);
-			udelay(25); /* for IDE reset */
-			pcc_set(sock, (unsigned int)PLD_CFRSTCR, 0x0100);
-			mdelay(2);  /* for IDE reset */
-		} else {
-			*value |= SS_POWERON;
-			*value |= SS_READY;
-		}
+		*value |= SS_POWERON;
+
+		pcc_set(sock, (unsigned int)PLD_CFBUFCR,0);
+		udelay(50);
+		pcc_set(sock, (unsigned int)PLD_CFRSTCR, 0x0101);
+		udelay(25); /* for IDE reset */
+		pcc_set(sock, (unsigned int)PLD_CFRSTCR, 0x0100);
+		mdelay(2);  /* for IDE reset */
+
+		*value |= SS_READY;
+		*value |= SS_3VCARD;
+	} else {
+		/* disable CF power */
+	        pcc_set(sock, (unsigned int)PLD_CPCR, 0);
+		udelay(100);
+		debug(3, "m32r_cfc: _pcc_get_status: "
+			 "power off (CPCR=0x%08x)\n", status);
 	}
 #else
 #error no platform configuration
@@ -479,14 +484,13 @@
 {
 //	pcc_socket_t *t = &socket[sock];
 
-#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT)
 	state->flags = 0;
 	state->csc_mask = SS_DETECT;
 	state->csc_mask |= SS_READY;
 	state->io_irq = 0;
 	state->Vcc = 33;	/* 3.3V fixed */
 	state->Vpp = 33;
-#endif
+
 	debug(3, "m32r_cfc: GetSocket(%d) = flags %#3.3x, Vcc %d, Vpp %d, "
 		  "io_irq %d, csc_mask %#2.2x\n", sock, state->flags,
 		  state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
@@ -497,32 +501,17 @@
 
 static int _pcc_set_socket(u_short sock, socket_state_t *state)
 {
-#if defined(CONFIG_PLAT_MAPPI2)
-	u_long reg = 0;
-#endif
 	debug(3, "m32r_cfc: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
 		  "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags,
 		  state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
 
-#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT)
+#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3)
 	if (state->Vcc) {
 		if ((state->Vcc != 50) && (state->Vcc != 33))
 			return -EINVAL;
 		/* accept 5V and 3.3V */
 	}
-#elif defined(CONFIG_PLAT_MAPPI2)
-	if (state->Vcc) {
-		/*
-		 * 5V only
-		 */
-		if (state->Vcc == 50) {
-			reg |= PCCSIGCR_VEN;
-		} else {
-			return -EINVAL;
-		}
-	}
 #endif
-
 	if (state->flags & SS_RESET) {
 		debug(3, ":RESET\n");
 		pcc_set(sock,(unsigned int)PLD_CFRSTCR,0x101);
@@ -788,7 +777,7 @@
 		return ret;
 	}
 
-#if defined(CONFIG_PLAT_MAPPI2)
+#if defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3)
 	pcc_set(0, (unsigned int)PLD_CFCR0, 0x0f0f);
 	pcc_set(0, (unsigned int)PLD_CFCR1, 0x0200);
 #endif
@@ -825,7 +814,7 @@
 	for (i = 0 ; i < pcc_sockets ; i++) {
 		socket[i].socket.dev.dev = &pcc_device.dev;
 		socket[i].socket.ops = &pcc_operations;
-		socket[i].socket.resource_ops = &pccard_static_ops;
+		socket[i].socket.resource_ops = &pccard_nonstatic_ops;
 		socket[i].socket.owner = THIS_MODULE;
 		socket[i].number = i;
 		ret = pcmcia_register_socket(&socket[i].socket);
diff --git a/drivers/pcmcia/m32r_cfc.h b/drivers/pcmcia/m32r_cfc.h
index 17c1db7..8146e3b 100644
--- a/drivers/pcmcia/m32r_cfc.h
+++ b/drivers/pcmcia/m32r_cfc.h
@@ -71,11 +71,15 @@
 
 #define CFC_IOPORT_BASE		0x1000
 
-#if !defined(CONFIG_PLAT_USRV)
+#if defined(CONFIG_PLAT_MAPPI3)
+#define CFC_ATTR_MAPBASE	0x14014000
+#define CFC_IO_MAPBASE_BYTE	0xb4012000
+#define CFC_IO_MAPBASE_WORD	0xb4002000
+#elif !defined(CONFIG_PLAT_USRV)
 #define CFC_ATTR_MAPBASE        0x0c014000
 #define CFC_IO_MAPBASE_BYTE     0xac012000
 #define CFC_IO_MAPBASE_WORD     0xac002000
-#else	/* CONFIG_PLAT_USRV */
+#else
 #define CFC_ATTR_MAPBASE	0x04014000
 #define CFC_IO_MAPBASE_BYTE	0xa4012000
 #define CFC_IO_MAPBASE_WORD	0xa4002000
diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h
index a8a1d10..c7ba998 100644
--- a/drivers/pcmcia/ti113x.h
+++ b/drivers/pcmcia/ti113x.h
@@ -611,6 +611,170 @@
 	}
 }
 
+
+/* Returns true value if the second slot of a two-slot controller is empty */
+static int ti12xx_2nd_slot_empty(struct yenta_socket *socket)
+{
+	struct pci_dev *func;
+	struct yenta_socket *slot2;
+	int devfn;
+	unsigned int state;
+	int ret = 1;
+
+	/* catch the two-slot controllers */
+	switch (socket->dev->device) {
+	case PCI_DEVICE_ID_TI_1220:
+	case PCI_DEVICE_ID_TI_1221:
+	case PCI_DEVICE_ID_TI_1225:
+	case PCI_DEVICE_ID_TI_1251A:
+	case PCI_DEVICE_ID_TI_1251B:
+	case PCI_DEVICE_ID_TI_1420:
+	case PCI_DEVICE_ID_TI_1450:
+	case PCI_DEVICE_ID_TI_1451A:
+	case PCI_DEVICE_ID_TI_1520:
+	case PCI_DEVICE_ID_TI_1620:
+	case PCI_DEVICE_ID_TI_4520:
+	case PCI_DEVICE_ID_TI_4450:
+	case PCI_DEVICE_ID_TI_4451:
+		/*
+		 * there are way more, but they need to be added in yenta_socket.c
+		 * and pci_ids.h first anyway.
+		 */
+		break;
+
+	/* single-slot controllers have the 2nd slot empty always :) */
+	default:
+		return 1;
+	}
+
+	/* get other slot */
+	devfn = socket->dev->devfn & ~0x07;
+	func = pci_get_slot(socket->dev->bus,
+	                    (socket->dev->devfn & 0x07) ? devfn : devfn | 0x01);
+	if (!func)
+		return 1;
+
+	slot2 = pci_get_drvdata(func);
+	if (!slot2)
+		goto out;
+
+	/* check state */
+	yenta_get_status(&socket->socket, &state);
+	if (state & SS_DETECT) {
+		ret = 0;
+		goto out;
+	}
+
+out:
+	pci_dev_put(func);
+	return ret;
+}
+
+/*
+ * TI specifiy parts for the power hook.
+ *
+ * some TI's with some CB's produces interrupt storm on power on. it has been
+ * seen with atheros wlan cards on TI1225 and TI1410. solution is simply to
+ * disable any CB interrupts during this time.
+ */
+static int ti12xx_power_hook(struct pcmcia_socket *sock, int operation)
+{
+	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
+	u32 mfunc, devctl, sysctl;
+	u8 gpio3;
+
+	/* only POWER_PRE and POWER_POST are interesting */
+	if ((operation != HOOK_POWER_PRE) && (operation != HOOK_POWER_POST))
+		return 0;
+
+	devctl = config_readb(socket, TI113X_DEVICE_CONTROL);
+	sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL);
+	mfunc = config_readl(socket, TI122X_MFUNC);
+
+	/*
+	 * all serial/tied: only disable when modparm set. always doing it
+	 * would mean a regression for working setups 'cos it disables the
+	 * interrupts for both both slots on 2-slot controllers
+	 * (and users of single slot controllers where it's save have to
+	 * live with setting the modparm, most don't have to anyway)
+	 */
+	if (((devctl & TI113X_DCR_IMODE_MASK) == TI12XX_DCR_IMODE_ALL_SERIAL) &&
+	    (pwr_irqs_off || ti12xx_2nd_slot_empty(socket))) {
+		switch (socket->dev->device) {
+		case PCI_DEVICE_ID_TI_1250:
+		case PCI_DEVICE_ID_TI_1251A:
+		case PCI_DEVICE_ID_TI_1251B:
+		case PCI_DEVICE_ID_TI_1450:
+		case PCI_DEVICE_ID_TI_1451A:
+		case PCI_DEVICE_ID_TI_4450:
+		case PCI_DEVICE_ID_TI_4451:
+			/* these chips have no IRQSER setting in MFUNC3  */
+			break;
+
+		default:
+			if (operation == HOOK_POWER_PRE)
+				mfunc = (mfunc & ~TI122X_MFUNC3_MASK);
+			else
+				mfunc = (mfunc & ~TI122X_MFUNC3_MASK) | TI122X_MFUNC3_IRQSER;
+		}
+
+		return 0;
+	}
+
+	/* do the job differently for func0/1 */
+	if ((PCI_FUNC(socket->dev->devfn) == 0) ||
+	    ((sysctl & TI122X_SCR_INTRTIE) &&
+	     (pwr_irqs_off || ti12xx_2nd_slot_empty(socket)))) {
+		/* some bridges are different */
+		switch (socket->dev->device) {
+		case PCI_DEVICE_ID_TI_1250:
+		case PCI_DEVICE_ID_TI_1251A:
+		case PCI_DEVICE_ID_TI_1251B:
+		case PCI_DEVICE_ID_TI_1450:
+			/* those oldies use gpio3 for INTA */
+			gpio3 = config_readb(socket, TI1250_GPIO3_CONTROL);
+			if (operation == HOOK_POWER_PRE)
+				gpio3 = (gpio3 & ~TI1250_GPIO_MODE_MASK) | 0x40;
+			else
+				gpio3 &= ~TI1250_GPIO_MODE_MASK;
+			config_writeb(socket, TI1250_GPIO3_CONTROL, gpio3);
+			break;
+
+		default:
+			/* all new bridges are the same */
+			if (operation == HOOK_POWER_PRE)
+				mfunc &= ~TI122X_MFUNC0_MASK;
+			else
+				mfunc |= TI122X_MFUNC0_INTA;
+			config_writel(socket, TI122X_MFUNC, mfunc);
+		}
+	} else {
+		switch (socket->dev->device) {
+		case PCI_DEVICE_ID_TI_1251A:
+		case PCI_DEVICE_ID_TI_1251B:
+		case PCI_DEVICE_ID_TI_1450:
+			/* those have INTA elsewhere and INTB in MFUNC0 */
+			if (operation == HOOK_POWER_PRE)
+				mfunc &= ~TI122X_MFUNC0_MASK;
+			else
+				mfunc |= TI125X_MFUNC0_INTB;
+			config_writel(socket, TI122X_MFUNC, mfunc);
+
+			break;
+
+		default:
+			/* all new bridges are the same */
+			if (operation == HOOK_POWER_PRE)
+				mfunc &= ~TI122X_MFUNC1_MASK;
+			else
+				mfunc |= TI122X_MFUNC1_INTB;
+			config_writel(socket, TI122X_MFUNC, mfunc);
+		}
+	}
+
+	return 0;
+}
+
 static int ti12xx_override(struct yenta_socket *socket)
 {
 	u32 val, val_orig;
@@ -654,6 +818,9 @@
 	else
 		ti12xx_irqroute_func1(socket);
 
+	/* install power hook */
+	socket->socket.power_hook = ti12xx_power_hook;
+
 	return ti_override(socket);
 }
 
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index 6404d97..bee0536 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -32,6 +32,14 @@
 module_param(disable_clkrun, bool, 0444);
 MODULE_PARM_DESC(disable_clkrun, "If PC card doesn't function properly, please try this option");
 
+static int isa_probe = 1;
+module_param(isa_probe, bool, 0444);
+MODULE_PARM_DESC(isa_probe, "If set ISA interrupts are probed (default). Set to N to disable probing");
+
+static int pwr_irqs_off;
+module_param(pwr_irqs_off, bool, 0644);
+MODULE_PARM_DESC(pwr_irqs_off, "Force IRQs off during power-on of slot. Use only when seeing IRQ storms!");
+
 #if 0
 #define debug(x,args...) printk(KERN_DEBUG "%s: " x, __func__ , ##args)
 #else
@@ -150,15 +158,16 @@
 
 	val  = (state & CB_3VCARD) ? SS_3VCARD : 0;
 	val |= (state & CB_XVCARD) ? SS_XVCARD : 0;
-	val |= (state & (CB_CDETECT1 | CB_CDETECT2 | CB_5VCARD | CB_3VCARD
-			 | CB_XVCARD | CB_YVCARD)) ? 0 : SS_PENDING;
+	val |= (state & (CB_5VCARD | CB_3VCARD | CB_XVCARD | CB_YVCARD)) ? 0 : SS_PENDING;
+	val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? SS_PENDING : 0;
+
 
 	if (state & CB_CBCARD) {
 		val |= SS_CARDBUS;	
 		val |= (state & CB_CARDSTS) ? SS_STSCHG : 0;
 		val |= (state & (CB_CDETECT1 | CB_CDETECT2)) ? 0 : SS_DETECT;
 		val |= (state & CB_PWRCYCLE) ? SS_POWERON | SS_READY : 0;
-	} else {
+	} else if (state & CB_16BITCARD) {
 		u8 status = exca_readb(socket, I365_STATUS);
 		val |= ((status & I365_CS_DETECT) == I365_CS_DETECT) ? SS_DETECT : 0;
 		if (exca_readb(socket, I365_INTCTL) & I365_PC_IOCARD) {
@@ -405,11 +414,13 @@
 }
 
 
-static unsigned int yenta_events(struct yenta_socket *socket)
+
+static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
+	unsigned int events;
+	struct yenta_socket *socket = (struct yenta_socket *) dev_id;
 	u8 csc;
 	u32 cb_event;
-	unsigned int events;
 
 	/* Clear interrupt status for the event */
 	cb_event = cb_readl(socket, CB_SOCKET_EVENT);
@@ -426,20 +437,13 @@
 		events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0;
 		events |= (csc & I365_CSC_READY) ? SS_READY : 0;
 	}
-	return events;
-}
 
-
-static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	unsigned int events;
-	struct yenta_socket *socket = (struct yenta_socket *) dev_id;
-
-	events = yenta_events(socket);
-	if (events) {
+	if (events)
 		pcmcia_parse_events(&socket->socket, events);
+
+	if (cb_event || csc)
 		return IRQ_HANDLED;
-	}
+
 	return IRQ_NONE;
 }
 
@@ -470,11 +474,22 @@
 	}
 }
 
+/* redoes voltage interrogation if required */
+static void yenta_interrogate(struct yenta_socket *socket)
+{
+	u32 state;
+
+	state = cb_readl(socket, CB_SOCKET_STATE);
+	if (!(state & (CB_5VCARD | CB_3VCARD | CB_XVCARD | CB_YVCARD)) ||
+	    (state & (CB_CDETECT1 | CB_CDETECT2 | CB_NOTACARD | CB_BADVCCREQ)) ||
+	    ((state & (CB_16BITCARD | CB_CBCARD)) == (CB_16BITCARD | CB_CBCARD)))
+		cb_writel(socket, CB_SOCKET_FORCE, CB_CVSTEST);
+}
+
 /* Called at resume and initialization events */
 static int yenta_sock_init(struct pcmcia_socket *sock)
 {
 	struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
-	u32 state;
 	u16 bridge;
 
 	bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~CB_BRIDGE_INTR;
@@ -486,10 +501,7 @@
 	exca_writeb(socket, I365_GENCTL, 0x00);
 
 	/* Redo card voltage interrogation */
-	state = cb_readl(socket, CB_SOCKET_STATE);
-	if (!(state & (CB_CDETECT1 | CB_CDETECT2 | CB_5VCARD |
-	               CB_3VCARD | CB_XVCARD | CB_YVCARD)))
-		cb_writel(socket, CB_SOCKET_FORCE, CB_CVSTEST);
+	yenta_interrogate(socket);
 
 	yenta_clear_maps(socket);
 
@@ -856,7 +868,10 @@
 	socket->socket.features |= SS_CAP_PAGE_REGS | SS_CAP_PCCARD | SS_CAP_CARDBUS;
 	socket->socket.map_size = 0x1000;
 	socket->socket.pci_irq = socket->cb_irq;
-	socket->socket.irq_mask = yenta_probe_irq(socket, isa_irq_mask);
+	if (isa_probe)
+		socket->socket.irq_mask = yenta_probe_irq(socket, isa_irq_mask);
+	else
+		socket->socket.irq_mask = 0;
 	socket->socket.cb_dev = socket->dev;
 
 	printk(KERN_INFO "Yenta: ISA IRQ mask 0x%04x, PCI irq %d\n",
@@ -996,6 +1011,7 @@
 	}
 
 	/* Figure out what the dang thing can do for the PCMCIA layer... */
+	yenta_interrogate(socket);
 	yenta_get_socket_capabilities(socket, isa_interrupts);
 	printk(KERN_INFO "Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));
 
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
index 97eeecf..add12f7 100644
--- a/drivers/pnp/card.c
+++ b/drivers/pnp/card.c
@@ -140,7 +140,7 @@
 }
 
 
-static ssize_t pnp_show_card_name(struct device *dmdev, char *buf)
+static ssize_t pnp_show_card_name(struct device *dmdev, struct device_attribute *attr, char *buf)
 {
 	char *str = buf;
 	struct pnp_card *card = to_pnp_card(dmdev);
@@ -150,7 +150,7 @@
 
 static DEVICE_ATTR(name,S_IRUGO,pnp_show_card_name,NULL);
 
-static ssize_t pnp_show_card_ids(struct device *dmdev, char *buf)
+static ssize_t pnp_show_card_ids(struct device *dmdev, struct device_attribute *attr, char *buf)
 {
 	char *str = buf;
 	struct pnp_card *card = to_pnp_card(dmdev);
@@ -259,7 +259,6 @@
 
 /**
  * pnp_remove_card_device- removes a device from the specified card
- * @card: pointer to the card to remove from
  * @dev: pointer to the device to remove
  */
 
@@ -274,7 +273,7 @@
 
 /**
  * pnp_request_card_device - Searches for a PnP device under the specified card
- * @lcard: pointer to the card link, cannot be NULL
+ * @clink: pointer to the card link, cannot be NULL
  * @id: pointer to a PnP ID structure that explains the rules for finding the device
  * @from: Starting place to search from. If NULL it will start from the begining.
  */
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c
index d64c1ca..1d037c2 100644
--- a/drivers/pnp/driver.c
+++ b/drivers/pnp/driver.c
@@ -160,10 +160,16 @@
 };
 
 
+static int count_devices(struct device * dev, void * c)
+{
+	int * count = c;
+	(*count)++;
+	return 0;
+}
+
 int pnp_register_driver(struct pnp_driver *drv)
 {
 	int count;
-	struct list_head *pos;
 
 	pnp_dbg("the driver '%s' has been registered", drv->name);
 
@@ -177,9 +183,7 @@
 	/* get the number of initial matches */
 	if (count >= 0){
 		count = 0;
-		list_for_each(pos,&drv->driver.devices){
-			count++;
-		}
+		driver_for_each_device(&drv->driver, NULL, &count, count_devices);
 	}
 	return count;
 }
diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c
index 53fac8b..a2d8ce7 100644
--- a/drivers/pnp/interface.c
+++ b/drivers/pnp/interface.c
@@ -205,7 +205,7 @@
 }
 
 
-static ssize_t pnp_show_options(struct device *dmdev, char *buf)
+static ssize_t pnp_show_options(struct device *dmdev, struct device_attribute *attr, char *buf)
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
 	struct pnp_option * independent = dev->independent;
@@ -236,7 +236,7 @@
 static DEVICE_ATTR(options,S_IRUGO,pnp_show_options,NULL);
 
 
-static ssize_t pnp_show_current_resources(struct device *dmdev, char *buf)
+static ssize_t pnp_show_current_resources(struct device *dmdev, struct device_attribute *attr, char *buf)
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
 	int i, ret;
@@ -308,7 +308,7 @@
 extern struct semaphore pnp_res_mutex;
 
 static ssize_t
-pnp_set_current_resources(struct device * dmdev, const char * ubuf, size_t count)
+pnp_set_current_resources(struct device * dmdev, struct device_attribute *attr, const char * ubuf, size_t count)
 {
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
 	char	*buf = (void *)ubuf;
@@ -444,7 +444,7 @@
 static DEVICE_ATTR(resources,S_IRUGO | S_IWUSR,
 		   pnp_show_current_resources,pnp_set_current_resources);
 
-static ssize_t pnp_show_current_ids(struct device *dmdev, char *buf)
+static ssize_t pnp_show_current_ids(struct device *dmdev, struct device_attribute *attr, char *buf)
 {
 	char *str = buf;
 	struct pnp_dev *dev = to_pnp_dev(dmdev);
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c
index 65ecef7..6c510c1 100644
--- a/drivers/pnp/manager.c
+++ b/drivers/pnp/manager.c
@@ -390,6 +390,7 @@
  * pnp_manual_config_dev - Disables Auto Config and Manually sets the resource table
  * @dev: pointer to the desired device
  * @res: pointer to the new resource config
+ * @mode: 0 or PNP_CONFIG_FORCE
  *
  * This function can be used by drivers that want to manually set thier resources.
  */
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index e939c93..778a324 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -182,7 +182,7 @@
 		msleep_interruptible(2000);
 
 		if(signal_pending(current)) {
-			if (try_to_freeze(PF_FREEZE))
+			if (try_to_freeze())
 				continue;
 			break;
 		}
diff --git a/drivers/s390/Kconfig b/drivers/s390/Kconfig
index 96413c2..a86a650 100644
--- a/drivers/s390/Kconfig
+++ b/drivers/s390/Kconfig
@@ -187,6 +187,13 @@
 	  *SYMPTOM.
 	  This driver depends on the IUCV support driver.
 
+config VMCP
+	tristate "Support for the z/VM CP interface (VM only)"
+	help
+	  Select this option if you want to be able to interact with the control
+	  program on z/VM
+
+
 config MONREADER
 	tristate "API for reading z/VM monitor service records"
 	depends on IUCV
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index ceeb3cf..6527ff6 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -176,7 +176,7 @@
 		return rc;
 
 	/* register 'device' debug area, used for all DBF_DEV_XXX calls */
-	device->debug_area = debug_register(device->cdev->dev.bus_id, 0, 2,
+	device->debug_area = debug_register(device->cdev->dev.bus_id, 1, 2,
 					    8 * sizeof (long));
 	debug_register_view(device->debug_area, &debug_sprintf_view);
 	debug_set_level(device->debug_area, DBF_EMERG);
@@ -1952,26 +1952,24 @@
  * Automatically online either all dasd devices (dasd_autodetect) or
  * all devices specified with dasd= parameters.
  */
+static int
+__dasd_auto_online(struct device *dev, void *data)
+{
+	struct ccw_device *cdev;
+
+	cdev = to_ccwdev(dev);
+	if (dasd_autodetect || dasd_busid_known(cdev->dev.bus_id) == 0)
+		ccw_device_set_online(cdev);
+	return 0;
+}
+
 void
 dasd_generic_auto_online (struct ccw_driver *dasd_discipline_driver)
 {
 	struct device_driver *drv;
-	struct device *d, *dev;
-	struct ccw_device *cdev;
 
 	drv = get_driver(&dasd_discipline_driver->driver);
-	down_read(&drv->bus->subsys.rwsem);
-	dev = NULL;
-	list_for_each_entry(d, &drv->devices, driver_list) {
-		dev = get_device(d);
-		if (!dev)
-			continue;
-		cdev = to_ccwdev(dev);
-		if (dasd_autodetect || dasd_busid_known(cdev->dev.bus_id) == 0)
-			ccw_device_set_online(cdev);
-		put_device(dev);
-	}
-	up_read(&drv->bus->subsys.rwsem);
+	driver_for_each_device(drv, NULL, NULL, __dasd_auto_online);
 	put_driver(drv);
 }
 
@@ -1983,7 +1981,7 @@
 	init_waitqueue_head(&dasd_init_waitq);
 
 	/* register 'common' DASD debug area, used for all DBF_XXX calls */
-	dasd_debug_area = debug_register("dasd", 0, 2, 8 * sizeof (long));
+	dasd_debug_area = debug_register("dasd", 1, 2, 8 * sizeof (long));
 	if (dasd_debug_area == NULL) {
 		rc = -ENOMEM;
 		goto failed;
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index 1aedc48..d948566 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -615,7 +615,7 @@
  * readonly controls the readonly status of a dasd
  */
 static ssize_t
-dasd_ro_show(struct device *dev, char *buf)
+dasd_ro_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct dasd_devmap *devmap;
 	int ro_flag;
@@ -629,7 +629,7 @@
 }
 
 static ssize_t
-dasd_ro_store(struct device *dev, const char *buf, size_t count)
+dasd_ro_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct dasd_devmap *devmap;
 	int ro_flag;
@@ -656,7 +656,7 @@
  * to talk to the device
  */
 static ssize_t 
-dasd_use_diag_show(struct device *dev, char *buf)
+dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct dasd_devmap *devmap;
 	int use_diag;
@@ -670,7 +670,7 @@
 }
 
 static ssize_t
-dasd_use_diag_store(struct device *dev, const char *buf, size_t count)
+dasd_use_diag_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct dasd_devmap *devmap;
 	ssize_t rc;
@@ -698,7 +698,7 @@
 DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store);
 
 static ssize_t
-dasd_discipline_show(struct device *dev, char *buf)
+dasd_discipline_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct dasd_devmap *devmap;
 	char *dname;
diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c
index d7f1974..43c34f8 100644
--- a/drivers/s390/block/dasd_proc.c
+++ b/drivers/s390/block/dasd_proc.c
@@ -9,13 +9,14 @@
  *
  * /proc interface for the dasd driver.
  *
- * $Revision: 1.31 $
+ * $Revision: 1.32 $
  */
 
 #include <linux/config.h>
 #include <linux/ctype.h>
 #include <linux/seq_file.h>
 #include <linux/vmalloc.h>
+#include <linux/proc_fs.h>
 
 #include <asm/debug.h>
 #include <asm/uaccess.h>
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index a66b17b6..4fde411 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -35,26 +35,29 @@
 static int dcssblk_open(struct inode *inode, struct file *filp);
 static int dcssblk_release(struct inode *inode, struct file *filp);
 static int dcssblk_make_request(struct request_queue *q, struct bio *bio);
+static int dcssblk_direct_access(struct block_device *bdev, sector_t secnum,
+				 unsigned long *data);
 
 static char dcssblk_segments[DCSSBLK_PARM_LEN] = "\0";
 
 static int dcssblk_major;
 static struct block_device_operations dcssblk_devops = {
-	.owner   = THIS_MODULE,
-	.open    = dcssblk_open,
-	.release = dcssblk_release,
+	.owner   	= THIS_MODULE,
+	.open    	= dcssblk_open,
+	.release 	= dcssblk_release,
+	.direct_access 	= dcssblk_direct_access,
 };
 
-static ssize_t dcssblk_add_store(struct device * dev, const char * buf,
+static ssize_t dcssblk_add_store(struct device * dev, struct device_attribute *attr, const char * buf,
 				  size_t count);
-static ssize_t dcssblk_remove_store(struct device * dev, const char * buf,
+static ssize_t dcssblk_remove_store(struct device * dev, struct device_attribute *attr, const char * buf,
 				  size_t count);
-static ssize_t dcssblk_save_store(struct device * dev, const char * buf,
+static ssize_t dcssblk_save_store(struct device * dev, struct device_attribute *attr, const char * buf,
 				  size_t count);
-static ssize_t dcssblk_save_show(struct device *dev, char *buf);
-static ssize_t dcssblk_shared_store(struct device * dev, const char * buf,
+static ssize_t dcssblk_save_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t dcssblk_shared_store(struct device * dev, struct device_attribute *attr, const char * buf,
 				  size_t count);
-static ssize_t dcssblk_shared_show(struct device *dev, char *buf);
+static ssize_t dcssblk_shared_show(struct device *dev, struct device_attribute *attr, char *buf);
 
 static DEVICE_ATTR(add, S_IWUSR, NULL, dcssblk_add_store);
 static DEVICE_ATTR(remove, S_IWUSR, NULL, dcssblk_remove_store);
@@ -195,7 +198,7 @@
  * operation (show + store)
  */
 static ssize_t
-dcssblk_shared_show(struct device *dev, char *buf)
+dcssblk_shared_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct dcssblk_dev_info *dev_info;
 
@@ -204,7 +207,7 @@
 }
 
 static ssize_t
-dcssblk_shared_store(struct device *dev, const char *inbuf, size_t count)
+dcssblk_shared_store(struct device *dev, struct device_attribute *attr, const char *inbuf, size_t count)
 {
 	struct dcssblk_dev_info *dev_info;
 	int rc;
@@ -288,7 +291,7 @@
  * (show + store)
  */
 static ssize_t
-dcssblk_save_show(struct device *dev, char *buf)
+dcssblk_save_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct dcssblk_dev_info *dev_info;
 
@@ -297,7 +300,7 @@
 }
 
 static ssize_t
-dcssblk_save_store(struct device *dev, const char *inbuf, size_t count)
+dcssblk_save_store(struct device *dev, struct device_attribute *attr, const char *inbuf, size_t count)
 {
 	struct dcssblk_dev_info *dev_info;
 
@@ -343,7 +346,7 @@
  * device attribute for adding devices
  */
 static ssize_t
-dcssblk_add_store(struct device *dev, const char *buf, size_t count)
+dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	int rc, i;
 	struct dcssblk_dev_info *dev_info;
@@ -517,7 +520,7 @@
  * device attribute for removing devices
  */
 static ssize_t
-dcssblk_remove_store(struct device *dev, const char *buf, size_t count)
+dcssblk_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct dcssblk_dev_info *dev_info;
 	int rc, i;
@@ -641,6 +644,20 @@
 		/* Request beyond end of DCSS segment. */
 		goto fail;
 	}
+	/* verify data transfer direction */
+	if (dev_info->is_shared) {
+		switch (dev_info->segment_type) {
+		case SEG_TYPE_SR:
+		case SEG_TYPE_ER:
+		case SEG_TYPE_SC:
+			/* cannot write to these segments */
+			if (bio_data_dir(bio) == WRITE) {
+				PRINT_WARN("rejecting write to ro segment %s\n", dev_info->dev.bus_id);
+				goto fail;
+			}
+		}
+	}
+
 	index = (bio->bi_sector >> 3);
 	bio_for_each_segment(bvec, bio, i) {
 		page_addr = (unsigned long)
@@ -661,7 +678,26 @@
 	bio_endio(bio, bytes_done, 0);
 	return 0;
 fail:
-	bio_io_error(bio, bytes_done);
+	bio_io_error(bio, bio->bi_size);
+	return 0;
+}
+
+static int
+dcssblk_direct_access (struct block_device *bdev, sector_t secnum,
+			unsigned long *data)
+{
+	struct dcssblk_dev_info *dev_info;
+	unsigned long pgoff;
+
+	dev_info = bdev->bd_disk->private_data;
+	if (!dev_info)
+		return -ENODEV;
+	if (secnum % (PAGE_SIZE/512))
+		return -EINVAL;
+	pgoff = secnum / (PAGE_SIZE / 512);
+	if ((pgoff+1)*PAGE_SIZE-1 > dev_info->end - dev_info->start)
+		return -ERANGE;
+	*data = (unsigned long) (dev_info->start+pgoff*PAGE_SIZE);
 	return 0;
 }
 
@@ -682,7 +718,7 @@
 			buf[j-i] = dcssblk_segments[j];
 		}
 		buf[j-i] = '\0';
-		rc = dcssblk_add_store(dcssblk_root_dev, buf, j-i);
+		rc = dcssblk_add_store(dcssblk_root_dev, NULL, buf, j-i);
 		if ((rc >= 0) && (dcssblk_segments[j] == '(')) {
 			for (k = 0; buf[k] != '\0'; k++)
 				buf[k] = toupper(buf[k]);
@@ -692,7 +728,7 @@
 				up_read(&dcssblk_devices_sem);
 				if (dev_info)
 					dcssblk_shared_store(&dev_info->dev,
-							     "0\n", 2);
+							     NULL, "0\n", 2);
 			}
 		}
 		while ((dcssblk_segments[j] != ',') &&
diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile
index 14e8cce..6377a96 100644
--- a/drivers/s390/char/Makefile
+++ b/drivers/s390/char/Makefile
@@ -19,6 +19,7 @@
 
 obj-$(CONFIG_ZVM_WATCHDOG) += vmwatchdog.o
 obj-$(CONFIG_VMLOGRDR) += vmlogrdr.o
+obj-$(CONFIG_VMCP) += vmcp.o
 
 tape-$(CONFIG_S390_TAPE_BLOCK) += tape_block.o
 tape-$(CONFIG_PROC_FS) += tape_proc.o
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 022f17b..f11a67f 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -860,8 +860,8 @@
 
 	/* Set the console mode for VM */
 	if (MACHINE_IS_VM) {
-		cpcmd("TERM CONMODE 3215", NULL, 0);
-		cpcmd("TERM AUTOCR OFF", NULL, 0);
+		cpcmd("TERM CONMODE 3215", NULL, 0, NULL);
+		cpcmd("TERM AUTOCR OFF", NULL, 0, NULL);
 	}
 
 	/* allocate 3215 request structures */
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index d52fb57..fc7a213 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -591,8 +591,8 @@
 
 	/* Set the console mode for VM */
 	if (MACHINE_IS_VM) {
-		cpcmd("TERM CONMODE 3270", 0, 0);
-		cpcmd("TERM AUTOCR OFF", 0, 0);
+		cpcmd("TERM CONMODE 3270", NULL, 0, NULL);
+		cpcmd("TERM AUTOCR OFF", NULL, 0, NULL);
 	}
 
 	cdev = ccw_device_probe_console();
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 8e16a97..d5eefea 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -1084,7 +1084,7 @@
  * Additional attributes for a 3270 device
  */
 static ssize_t
-raw3270_model_show(struct device *dev, char *buf)
+raw3270_model_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	return snprintf(buf, PAGE_SIZE, "%i\n",
 			((struct raw3270 *) dev->driver_data)->model);
@@ -1092,7 +1092,7 @@
 static DEVICE_ATTR(model, 0444, raw3270_model_show, 0);
 
 static ssize_t
-raw3270_rows_show(struct device *dev, char *buf)
+raw3270_rows_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	return snprintf(buf, PAGE_SIZE, "%i\n",
 			((struct raw3270 *) dev->driver_data)->rows);
@@ -1100,7 +1100,7 @@
 static DEVICE_ATTR(rows, 0444, raw3270_rows_show, 0);
 
 static ssize_t
-raw3270_columns_show(struct device *dev, char *buf)
+raw3270_columns_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	return snprintf(buf, PAGE_SIZE, "%i\n",
 			((struct raw3270 *) dev->driver_data)->cols);
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c
index 480ec87..20be88e 100644
--- a/drivers/s390/char/tape_34xx.c
+++ b/drivers/s390/char/tape_34xx.c
@@ -1351,13 +1351,13 @@
 {
 	int rc;
 
-	TAPE_DBF_AREA = debug_register ( "tape_34xx", 1, 2, 4*sizeof(long));
+	TAPE_DBF_AREA = debug_register ( "tape_34xx", 2, 2, 4*sizeof(long));
 	debug_register_view(TAPE_DBF_AREA, &debug_sprintf_view);
 #ifdef DBF_LIKE_HELL
 	debug_set_level(TAPE_DBF_AREA, 6);
 #endif
 
-	DBF_EVENT(3, "34xx init: $Revision: 1.21 $\n");
+	DBF_EVENT(3, "34xx init: $Revision: 1.23 $\n");
 	/* Register driver for 3480/3490 tapes. */
 	rc = ccw_driver_register(&tape_34xx_driver);
 	if (rc)
@@ -1378,7 +1378,7 @@
 MODULE_DEVICE_TABLE(ccw, tape_34xx_ids);
 MODULE_AUTHOR("(C) 2001-2002 IBM Deutschland Entwicklung GmbH");
 MODULE_DESCRIPTION("Linux on zSeries channel attached 3480 tape "
-		   "device driver ($Revision: 1.21 $)");
+		   "device driver ($Revision: 1.23 $)");
 MODULE_LICENSE("GPL");
 
 module_init(tape_34xx_init);
diff --git a/drivers/s390/char/tape_class.c b/drivers/s390/char/tape_class.c
index 0f8ffd4..ed0cb1f 100644
--- a/drivers/s390/char/tape_class.c
+++ b/drivers/s390/char/tape_class.c
@@ -16,7 +16,7 @@
 );
 MODULE_LICENSE("GPL");
 
-struct class_simple *tape_class;
+static struct class *tape_class;
 
 /*
  * Register a tape device and return a pointer to the cdev structure.
@@ -70,7 +70,7 @@
 	if (rc)
 		goto fail_with_cdev;
 
-	tcd->class_device = class_simple_device_add(
+	tcd->class_device = class_device_create(
 				tape_class,
 				tcd->char_device->dev,
 				device,
@@ -101,7 +101,7 @@
 			&tcd->class_device->dev->kobj,
 			tcd->mode_name
 		);
-		class_simple_device_remove(tcd->char_device->dev);
+		class_device_destroy(tape_class, tcd->char_device->dev);
 		cdev_del(tcd->char_device);
 		kfree(tcd);
 	}
@@ -111,14 +111,14 @@
 
 static int __init tape_init(void)
 {
-	tape_class = class_simple_create(THIS_MODULE, "tape390");
+	tape_class = class_create(THIS_MODULE, "tape390");
 
 	return 0;
 }
 
 static void __exit tape_exit(void)
 {
-	class_simple_destroy(tape_class);
+	class_destroy(tape_class);
 	tape_class = NULL;
 }
 
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c
index e51046a..0597aa0 100644
--- a/drivers/s390/char/tape_core.c
+++ b/drivers/s390/char/tape_core.c
@@ -107,7 +107,7 @@
  *        replaced by a link to the cdev tree.
  */
 static ssize_t
-tape_medium_state_show(struct device *dev, char *buf)
+tape_medium_state_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct tape_device *tdev;
 
@@ -119,7 +119,7 @@
 DEVICE_ATTR(medium_state, 0444, tape_medium_state_show, NULL);
 
 static ssize_t
-tape_first_minor_show(struct device *dev, char *buf)
+tape_first_minor_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct tape_device *tdev;
 
@@ -131,7 +131,7 @@
 DEVICE_ATTR(first_minor, 0444, tape_first_minor_show, NULL);
 
 static ssize_t
-tape_state_show(struct device *dev, char *buf)
+tape_state_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct tape_device *tdev;
 
@@ -144,7 +144,7 @@
 DEVICE_ATTR(state, 0444, tape_state_show, NULL);
 
 static ssize_t
-tape_operation_show(struct device *dev, char *buf)
+tape_operation_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct tape_device *tdev;
 	ssize_t rc;
@@ -171,7 +171,7 @@
 DEVICE_ATTR(operation, 0444, tape_operation_show, NULL);
 
 static ssize_t
-tape_blocksize_show(struct device *dev, char *buf)
+tape_blocksize_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct tape_device *tdev;
 
@@ -1186,7 +1186,7 @@
 static int
 tape_init (void)
 {
-	TAPE_DBF_AREA = debug_register ( "tape", 1, 2, 4*sizeof(long));
+	TAPE_DBF_AREA = debug_register ( "tape", 2, 2, 4*sizeof(long));
 	debug_register_view(TAPE_DBF_AREA, &debug_sprintf_view);
 #ifdef DBF_LIKE_HELL
 	debug_set_level(TAPE_DBF_AREA, 6);
diff --git a/drivers/s390/char/tape_proc.c b/drivers/s390/char/tape_proc.c
index 801d17c..5fec0a1 100644
--- a/drivers/s390/char/tape_proc.c
+++ b/drivers/s390/char/tape_proc.c
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/seq_file.h>
+#include <linux/proc_fs.h>
 
 #define TAPE_DBF_AREA	tape_core_dbf
 
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c
new file mode 100644
index 0000000..7f11a60
--- /dev/null
+++ b/drivers/s390/char/vmcp.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2004,2005 IBM Corporation
+ * Interface implementation for communication with the v/VM control program
+ * Author(s): Christian Borntraeger <cborntra@de.ibm.com>
+ *
+ *
+ * z/VMs CP offers the possibility to issue commands via the diagnose code 8
+ * this driver implements a character device that issues these commands and
+ * returns the answer of CP.
+
+ * The idea of this driver is based on cpint from Neale Ferguson and #CP in CMS
+ */
+
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <asm/cpcmd.h>
+#include <asm/debug.h>
+#include <asm/uaccess.h>
+#include "vmcp.h"
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Borntraeger <cborntra@de.ibm.com>");
+MODULE_DESCRIPTION("z/VM CP interface");
+
+static debug_info_t *vmcp_debug;
+
+static int vmcp_open(struct inode *inode, struct file *file)
+{
+	struct vmcp_session *session;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	session = kmalloc(sizeof(*session), GFP_KERNEL);
+	if (!session)
+		return -ENOMEM;
+	session->bufsize = PAGE_SIZE;
+	session->response = NULL;
+	session->resp_size = 0;
+	init_MUTEX(&session->mutex);
+	file->private_data = session;
+	return nonseekable_open(inode, file);
+}
+
+static int vmcp_release(struct inode *inode, struct file *file)
+{
+	struct vmcp_session *session;
+
+	session = (struct vmcp_session *)file->private_data;
+	file->private_data = NULL;
+	free_pages((unsigned long)session->response, get_order(session->bufsize));
+	kfree(session);
+	return 0;
+}
+
+static ssize_t
+vmcp_read(struct file *file, char __user * buff, size_t count, loff_t * ppos)
+{
+	size_t tocopy;
+	struct vmcp_session *session;
+
+	session = (struct vmcp_session *)file->private_data;
+	if (down_interruptible(&session->mutex))
+		return -ERESTARTSYS;
+	if (!session->response) {
+		up(&session->mutex);
+		return 0;
+	}
+	if (*ppos > session->resp_size) {
+		up(&session->mutex);
+		return 0;
+	}
+	tocopy = min(session->resp_size - (size_t) (*ppos), count);
+	tocopy = min(tocopy,session->bufsize - (size_t) (*ppos));
+
+	if (copy_to_user(buff, session->response + (*ppos), tocopy)) {
+		up(&session->mutex);
+		return -EFAULT;
+	}
+	up(&session->mutex);
+	*ppos += tocopy;
+	return tocopy;
+}
+
+static ssize_t
+vmcp_write(struct file *file, const char __user * buff, size_t count,
+	   loff_t * ppos)
+{
+	char *cmd;
+	struct vmcp_session *session;
+
+	if (count > 240)
+		return -EINVAL;
+	cmd = kmalloc(count + 1, GFP_KERNEL);
+	if (!cmd)
+		return -ENOMEM;
+	if (copy_from_user(cmd, buff, count)) {
+		kfree(cmd);
+		return -EFAULT;
+	}
+	cmd[count] = '\0';
+	session = (struct vmcp_session *)file->private_data;
+	if (down_interruptible(&session->mutex))
+		return -ERESTARTSYS;
+	if (!session->response)
+		session->response = (char *)__get_free_pages(GFP_KERNEL
+						| __GFP_REPEAT 	| GFP_DMA,
+						get_order(session->bufsize));
+	if (!session->response) {
+		up(&session->mutex);
+		kfree(cmd);
+		return -ENOMEM;
+	}
+	debug_text_event(vmcp_debug, 1, cmd);
+	session->resp_size = cpcmd(cmd, session->response,
+				   session->bufsize,
+				   &session->resp_code);
+	up(&session->mutex);
+	kfree(cmd);
+	*ppos = 0;		/* reset the file pointer after a command */
+	return count;
+}
+
+
+/*
+ * These ioctls are available, as the semantics of the diagnose 8 call
+ * does not fit very well into a Linux call. Diagnose X'08' is described in
+ * CP Programming Services SC24-6084-00
+ *
+ * VMCP_GETCODE: gives the CP return code back to user space
+ * VMCP_SETBUF: sets the response buffer for the next write call. diagnose 8
+ * expects adjacent pages in real storage and to make matters worse, we
+ * dont know the size of the response. Therefore we default to PAGESIZE and
+ * let userspace to change the response size, if userspace expects a bigger
+ * response
+ */
+static long vmcp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct vmcp_session *session;
+	int temp;
+
+	session = (struct vmcp_session *)file->private_data;
+	if (down_interruptible(&session->mutex))
+		return -ERESTARTSYS;
+	switch (cmd) {
+	case VMCP_GETCODE:
+		temp = session->resp_code;
+		up(&session->mutex);
+		return put_user(temp, (int __user *)arg);
+	case VMCP_SETBUF:
+		free_pages((unsigned long)session->response,
+				get_order(session->bufsize));
+		session->response=NULL;
+		temp = get_user(session->bufsize, (int __user *)arg);
+		if (get_order(session->bufsize) > 8) {
+			session->bufsize = PAGE_SIZE;
+			temp = -EINVAL;
+		}
+		up(&session->mutex);
+		return temp;
+	case VMCP_GETSIZE:
+		temp = session->resp_size;
+		up(&session->mutex);
+		return put_user(temp, (int __user *)arg);
+	default:
+		up(&session->mutex);
+		return -ENOIOCTLCMD;
+	}
+}
+
+static struct file_operations vmcp_fops = {
+	.owner		= THIS_MODULE,
+	.open		= &vmcp_open,
+	.release	= &vmcp_release,
+	.read		= &vmcp_read,
+	.llseek		= &no_llseek,
+	.write		= &vmcp_write,
+	.unlocked_ioctl	= &vmcp_ioctl,
+	.compat_ioctl	= &vmcp_ioctl
+};
+
+static struct miscdevice vmcp_dev = {
+	.name	= "vmcp",
+	.minor	= MISC_DYNAMIC_MINOR,
+	.fops	= &vmcp_fops,
+};
+
+static int __init vmcp_init(void)
+{
+	int ret;
+
+	if (!MACHINE_IS_VM) {
+		printk(KERN_WARNING
+		       "z/VM CP interface is only available under z/VM\n");
+		return -ENODEV;
+	}
+	ret = misc_register(&vmcp_dev);
+	if (!ret)
+		printk(KERN_INFO "z/VM CP interface loaded\n");
+	else
+		printk(KERN_WARNING
+		       "z/VM CP interface not loaded. Could not register misc device.\n");
+	vmcp_debug = debug_register("vmcp", 1, 1, 240);
+	debug_register_view(vmcp_debug, &debug_hex_ascii_view);
+	return ret;
+}
+
+static void __exit vmcp_exit(void)
+{
+	WARN_ON(misc_deregister(&vmcp_dev) != 0);
+	debug_unregister(vmcp_debug);
+	printk(KERN_INFO "z/VM CP interface unloaded.\n");
+}
+
+module_init(vmcp_init);
+module_exit(vmcp_exit);
diff --git a/drivers/s390/char/vmcp.h b/drivers/s390/char/vmcp.h
new file mode 100644
index 0000000..87389e7
--- /dev/null
+++ b/drivers/s390/char/vmcp.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2004, 2005 IBM Corporation
+ * Interface implementation for communication with the v/VM control program
+ * Version 1.0
+ * Author(s): Christian Borntraeger <cborntra@de.ibm.com>
+ *
+ *
+ * z/VMs CP offers the possibility to issue commands via the diagnose code 8
+ * this driver implements a character device that issues these commands and
+ * returns the answer of CP.
+ *
+ * The idea of this driver is based on cpint from Neale Ferguson
+ */
+
+#include <asm/semaphore.h>
+#include <linux/ioctl.h>
+
+#define VMCP_GETCODE _IOR(0x10, 1, int)
+#define VMCP_SETBUF _IOW(0x10, 2, int)
+#define VMCP_GETSIZE _IOR(0x10, 3, int)
+
+struct vmcp_session {
+	unsigned int bufsize;
+	char *response;
+	int resp_size;
+	int resp_code;
+	/* As we use copy_from/to_user, which might     *
+	 * sleep and cannot use a spinlock              */
+	struct semaphore mutex;
+};
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c
index edf50d2..491f00c 100644
--- a/drivers/s390/char/vmlogrdr.c
+++ b/drivers/s390/char/vmlogrdr.c
@@ -236,7 +236,7 @@
 	int len,i;
 
 	printk (KERN_DEBUG "vmlogrdr: query command: %s\n", cp_command);
-	cpcmd(cp_command, cp_response, sizeof(cp_response));
+	cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
 	printk (KERN_DEBUG "vmlogrdr: response: %s", cp_response);
 	len = strnlen(cp_response,sizeof(cp_response));
 	// now the parsing
@@ -288,7 +288,7 @@
 
 		printk (KERN_DEBUG "vmlogrdr: recording command: %s\n",
 			cp_command);
-		cpcmd(cp_command, cp_response, sizeof(cp_response));
+		cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
 		printk (KERN_DEBUG "vmlogrdr: recording response: %s",
 			cp_response);
 	}
@@ -301,7 +301,7 @@
 		qid_string);
 
 	printk (KERN_DEBUG "vmlogrdr: recording command: %s\n", cp_command);
-	cpcmd(cp_command, cp_response, sizeof(cp_response));
+	cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
 	printk (KERN_DEBUG "vmlogrdr: recording response: %s",
 		cp_response);
 	/* The recording command will usually answer with 'Command complete'
@@ -548,7 +548,7 @@
 }
 
 static ssize_t
-vmlogrdr_autopurge_store(struct device * dev, const char * buf, size_t count) {
+vmlogrdr_autopurge_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) {
 	struct vmlogrdr_priv_t *priv = dev->driver_data;
 	ssize_t ret = count;
 
@@ -567,7 +567,7 @@
 
 
 static ssize_t
-vmlogrdr_autopurge_show(struct device *dev, char *buf) {
+vmlogrdr_autopurge_show(struct device *dev, struct device_attribute *attr, char *buf) {
 	struct vmlogrdr_priv_t *priv = dev->driver_data;
 	return sprintf(buf, "%u\n", priv->autopurge);
 }
@@ -578,7 +578,7 @@
 
 
 static ssize_t
-vmlogrdr_purge_store(struct device * dev, const char * buf, size_t count) {
+vmlogrdr_purge_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) {
 
 	char cp_command[80];
 	char cp_response[80];
@@ -607,7 +607,7 @@
 			 priv->recording_name);
 
 	printk (KERN_DEBUG "vmlogrdr: recording command: %s\n", cp_command);
-	cpcmd(cp_command, cp_response, sizeof(cp_response));
+	cpcmd(cp_command, cp_response, sizeof(cp_response), NULL);
 	printk (KERN_DEBUG "vmlogrdr: recording response: %s",
 		cp_response);
 
@@ -619,7 +619,7 @@
 
 
 static ssize_t
-vmlogrdr_autorecording_store(struct device *dev, const char *buf,
+vmlogrdr_autorecording_store(struct device *dev, struct device_attribute *attr, const char *buf,
 			     size_t count) {
 	struct vmlogrdr_priv_t *priv = dev->driver_data;
 	ssize_t ret = count;
@@ -639,7 +639,7 @@
 
 
 static ssize_t
-vmlogrdr_autorecording_show(struct device *dev, char *buf) {
+vmlogrdr_autorecording_show(struct device *dev, struct device_attribute *attr, char *buf) {
 	struct vmlogrdr_priv_t *priv = dev->driver_data;
 	return sprintf(buf, "%u\n", priv->autorecording);
 }
@@ -650,7 +650,7 @@
 
 
 static ssize_t
-vmlogrdr_recording_store(struct device * dev, const char * buf, size_t count) {
+vmlogrdr_recording_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t count) {
 
 	struct vmlogrdr_priv_t *priv = dev->driver_data;
 	ssize_t ret;
@@ -682,7 +682,7 @@
 	char cp_command[] = "QUERY RECORDING ";
 	int len;
 
-	cpcmd(cp_command, buf, 4096);
+	cpcmd(cp_command, buf, 4096, NULL);
 	len = strlen(buf);
 	return len;
 }
@@ -703,7 +703,7 @@
 	.attrs = vmlogrdr_attrs,
 };
 
-static struct class_simple *vmlogrdr_class;
+static struct class *vmlogrdr_class;
 static struct device_driver vmlogrdr_driver = {
 	.name = "vmlogrdr",
 	.bus  = &iucv_bus,
@@ -727,7 +727,7 @@
 		goto unregdriver;
 	}
 
-	vmlogrdr_class = class_simple_create(THIS_MODULE, "vmlogrdr");
+	vmlogrdr_class = class_create(THIS_MODULE, "vmlogrdr");
 	if (IS_ERR(vmlogrdr_class)) {
 		printk(KERN_ERR "vmlogrdr: failed to create class.\n");
 		ret=PTR_ERR(vmlogrdr_class);
@@ -746,7 +746,7 @@
 
 static void
 vmlogrdr_unregister_driver(void) {
-	class_simple_destroy(vmlogrdr_class);
+	class_destroy(vmlogrdr_class);
 	vmlogrdr_class = NULL;
 	driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);
 	driver_unregister(&vmlogrdr_driver);
@@ -786,7 +786,7 @@
 		device_unregister(dev);
 		return ret;
 	}
-	priv->class_device = class_simple_device_add(
+	priv->class_device = class_device_create(
 				vmlogrdr_class,
 				MKDEV(vmlogrdr_major, priv->minor_num),
 				dev,
@@ -806,7 +806,7 @@
 
 static int
 vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv ) {
-	class_simple_device_remove(MKDEV(vmlogrdr_major, priv->minor_num));
+	class_device_destroy(vmlogrdr_class, MKDEV(vmlogrdr_major, priv->minor_num));
 	if (priv->device != NULL) {
 		sysfs_remove_group(&priv->device->kobj, &vmlogrdr_attr_group);
 		device_unregister(priv->device);
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c
index 4a06c7d..aac83ce 100644
--- a/drivers/s390/cio/blacklist.c
+++ b/drivers/s390/cio/blacklist.c
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/blacklist.c
  *   S/390 common I/O routines -- blacklisting of specific devices
- *   $Revision: 1.33 $
+ *   $Revision: 1.34 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *			      IBM Corporation
@@ -289,7 +289,7 @@
 	len = 0;
 	for (devno = off; /* abuse the page variable
 			   * as counter, see fs/proc/generic.c */
-	     devno <= __MAX_SUBCHANNELS && len + entry_size < count; devno++) {
+	     devno < __MAX_SUBCHANNELS && len + entry_size < count; devno++) {
 		if (!test_bit(devno, bl_dev))
 			continue;
 		len += sprintf(page + len, "0.0.%04lx", devno);
@@ -302,7 +302,7 @@
 		len += sprintf(page + len, "\n");
 	}
 
-	if (devno <= __MAX_SUBCHANNELS)
+	if (devno < __MAX_SUBCHANNELS)
 		*eof = 1;
 	*start = (char *) (devno - off); /* number of checked entries */
 	return len;
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c
index 21a75ee..91ea8e4 100644
--- a/drivers/s390/cio/ccwgroup.c
+++ b/drivers/s390/cio/ccwgroup.c
@@ -77,7 +77,7 @@
  * longer needed or accidentially created. Saves memory :)
  */
 static ssize_t
-ccwgroup_ungroup_store(struct device *dev, const char *buf, size_t count)
+ccwgroup_ungroup_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct ccwgroup_device *gdev;
 
@@ -310,7 +310,7 @@
 }
 
 static ssize_t
-ccwgroup_online_store (struct device *dev, const char *buf, size_t count)
+ccwgroup_online_store (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct ccwgroup_device *gdev;
 	struct ccwgroup_driver *gdrv;
@@ -338,7 +338,7 @@
 }
 
 static ssize_t
-ccwgroup_online_show (struct device *dev, char *buf)
+ccwgroup_online_show (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	int online;
 
@@ -403,34 +403,22 @@
 	return driver_register(&cdriver->driver);
 }
 
-static inline struct device *
-__get_next_ccwgroup_device(struct device_driver *drv)
+static int
+__ccwgroup_driver_unregister_device(struct device *dev, void *data)
 {
-	struct device *dev, *d;
-
-	down_read(&drv->bus->subsys.rwsem);
-	dev = NULL;
-	list_for_each_entry(d, &drv->devices, driver_list) {
-		dev = get_device(d);
-		if (dev)
-			break;
-	}
-	up_read(&drv->bus->subsys.rwsem);
-	return dev;
+	__ccwgroup_remove_symlinks(to_ccwgroupdev(dev));
+	device_unregister(dev);
+	put_device(dev);
+	return 0;
 }
 
 void
 ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver)
 {
-	struct device *dev;
-
 	/* We don't want ccwgroup devices to live longer than their driver. */
 	get_driver(&cdriver->driver);
-	while ((dev = __get_next_ccwgroup_device(&cdriver->driver))) {
-		__ccwgroup_remove_symlinks(to_ccwgroupdev(dev));
-		device_unregister(dev);
-		put_device(dev);
-	};
+	driver_for_each_device(&cdriver->driver, NULL, NULL,
+			       __ccwgroup_driver_unregister_device);
 	put_driver(&cdriver->driver);
 	driver_unregister(&cdriver->driver);
 }
@@ -449,7 +437,7 @@
 	if (cdev->dev.driver_data) {
 		gdev = (struct ccwgroup_device *)cdev->dev.driver_data;
 		if (get_device(&gdev->dev)) {
-			if (!list_empty(&gdev->dev.node))
+			if (klist_node_attached(&gdev->dev.knode_bus))
 				return gdev;
 			put_device(&gdev->dev);
 		}
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index b35fe12..b86f94e 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -852,7 +852,7 @@
  * Files for the channel path entries.
  */
 static ssize_t
-chp_status_show(struct device *dev, char *buf)
+chp_status_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct channel_path *chp = container_of(dev, struct channel_path, dev);
 
@@ -863,7 +863,7 @@
 }
 
 static ssize_t
-chp_status_write(struct device *dev, const char *buf, size_t count)
+chp_status_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct channel_path *cp = container_of(dev, struct channel_path, dev);
 	char cmd[10];
@@ -888,7 +888,7 @@
 static DEVICE_ATTR(status, 0644, chp_status_show, chp_status_write);
 
 static ssize_t
-chp_type_show(struct device *dev, char *buf)
+chp_type_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct channel_path *chp = container_of(dev, struct channel_path, dev);
 
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 1d9b3f1..ea813bd 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/cio.c
  *   S/390 common I/O routines -- low level i/o calls
- *   $Revision: 1.133 $
+ *   $Revision: 1.134 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *			      IBM Corporation
@@ -63,17 +63,17 @@
 static int __init
 cio_debug_init (void)
 {
-	cio_debug_msg_id = debug_register ("cio_msg", 4, 4, 16*sizeof (long));
+	cio_debug_msg_id = debug_register ("cio_msg", 16, 4, 16*sizeof (long));
 	if (!cio_debug_msg_id)
 		goto out_unregister;
 	debug_register_view (cio_debug_msg_id, &debug_sprintf_view);
 	debug_set_level (cio_debug_msg_id, 2);
-	cio_debug_trace_id = debug_register ("cio_trace", 4, 4, 8);
+	cio_debug_trace_id = debug_register ("cio_trace", 16, 4, 8);
 	if (!cio_debug_trace_id)
 		goto out_unregister;
 	debug_register_view (cio_debug_trace_id, &debug_hex_ascii_view);
 	debug_set_level (cio_debug_trace_id, 2);
-	cio_debug_crw_id = debug_register ("cio_crw", 2, 4, 16*sizeof (long));
+	cio_debug_crw_id = debug_register ("cio_crw", 4, 4, 16*sizeof (long));
 	if (!cio_debug_crw_id)
 		goto out_unregister;
 	debug_register_view (cio_debug_crw_id, &debug_sprintf_view);
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index 49def26..8cc4f1a 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -796,7 +796,7 @@
 }
 
 static ssize_t
-cmb_show_avg_sample_interval(struct device *dev, char *buf)
+cmb_show_avg_sample_interval(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct ccw_device *cdev;
 	long interval;
@@ -813,7 +813,7 @@
 }
 
 static ssize_t
-cmb_show_avg_utilization(struct device *dev, char *buf)
+cmb_show_avg_utilization(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct cmbdata data;
 	u64 utilization;
@@ -842,12 +842,12 @@
 }
 
 #define cmf_attr(name) \
-static ssize_t show_ ## name (struct device * dev, char * buf) \
+static ssize_t show_ ## name (struct device * dev, struct device_attribute *attr, char * buf) \
 { return cmb_show_attr((dev), buf, cmb_ ## name); } \
 static DEVICE_ATTR(name, 0444, show_ ## name, NULL);
 
 #define cmf_attr_avg(name) \
-static ssize_t show_avg_ ## name (struct device * dev, char * buf) \
+static ssize_t show_avg_ ## name (struct device * dev, struct device_attribute *attr, char * buf) \
 { return cmb_show_attr((dev), buf, cmb_ ## name); } \
 static DEVICE_ATTR(avg_ ## name, 0444, show_avg_ ## name, NULL);
 
@@ -902,12 +902,12 @@
 	.attrs = cmf_attributes_ext,
 };
 
-static ssize_t cmb_enable_show(struct device *dev, char *buf)
+static ssize_t cmb_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	return sprintf(buf, "%d\n", to_ccwdev(dev)->private->cmb ? 1 : 0);
 }
 
-static ssize_t cmb_enable_store(struct device *dev, const char *buf, size_t c)
+static ssize_t cmb_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t c)
 {
 	struct ccw_device *cdev;
 	int ret;
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 87bd70e..555119c 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -128,34 +128,28 @@
 	return ret;
 }
 
+static int
+check_subchannel(struct device * dev, void * data)
+{
+	struct subchannel *sch;
+	int irq = (unsigned long)data;
+
+	sch = to_subchannel(dev);
+	return (sch->irq == irq);
+}
+
 struct subchannel *
 get_subchannel_by_schid(int irq)
 {
-	struct subchannel *sch;
-	struct list_head *entry;
 	struct device *dev;
 
-	if (!get_bus(&css_bus_type))
-		return NULL;
-	down_read(&css_bus_type.subsys.rwsem);
-	sch = NULL;
-	list_for_each(entry, &css_bus_type.devices.list) {
-		dev = get_device(container_of(entry,
-					      struct device, bus_list));
-		if (!dev)
-			continue;
-		sch = to_subchannel(dev);
-		if (sch->irq == irq)
-			break;
-		put_device(dev);
-		sch = NULL;
-	}
-	up_read(&css_bus_type.subsys.rwsem);
-	put_bus(&css_bus_type);
+	dev = bus_find_device(&css_bus_type, NULL,
+			      (void *)(unsigned long)irq, check_subchannel);
 
-	return sch;
+	return dev ? to_subchannel(dev) : NULL;
 }
 
+
 static inline int
 css_get_subchannel_status(struct subchannel *sch, int schid)
 {
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index df03255..14c76f5 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -204,7 +204,7 @@
  * TODO: Split chpids and pimpampom up? Where is "in use" in the tree?
  */
 static ssize_t
-chpids_show (struct device * dev, char * buf)
+chpids_show (struct device * dev, struct device_attribute *attr, char * buf)
 {
 	struct subchannel *sch = to_subchannel(dev);
 	struct ssd_info *ssd = &sch->ssd_info;
@@ -219,7 +219,7 @@
 }
 
 static ssize_t
-pimpampom_show (struct device * dev, char * buf)
+pimpampom_show (struct device * dev, struct device_attribute *attr, char * buf)
 {
 	struct subchannel *sch = to_subchannel(dev);
 	struct pmcw *pmcw = &sch->schib.pmcw;
@@ -229,7 +229,7 @@
 }
 
 static ssize_t
-devtype_show (struct device *dev, char *buf)
+devtype_show (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct ccw_device *cdev = to_ccwdev(dev);
 	struct ccw_device_id *id = &(cdev->id);
@@ -242,7 +242,7 @@
 }
 
 static ssize_t
-cutype_show (struct device *dev, char *buf)
+cutype_show (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct ccw_device *cdev = to_ccwdev(dev);
 	struct ccw_device_id *id = &(cdev->id);
@@ -252,7 +252,7 @@
 }
 
 static ssize_t
-online_show (struct device *dev, char *buf)
+online_show (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct ccw_device *cdev = to_ccwdev(dev);
 
@@ -350,7 +350,7 @@
 }
 
 static ssize_t
-online_store (struct device *dev, const char *buf, size_t count)
+online_store (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct ccw_device *cdev = to_ccwdev(dev);
 	int i, force, ret;
@@ -422,7 +422,7 @@
 }
 
 static ssize_t
-available_show (struct device *dev, char *buf)
+available_show (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct ccw_device *cdev = to_ccwdev(dev);
 	struct subchannel *sch;
@@ -514,36 +514,39 @@
 	return ret;
 }
 
+struct match_data {
+	unsigned int  devno;
+	struct ccw_device * sibling;
+};
+
+static int
+match_devno(struct device * dev, void * data)
+{
+	struct match_data * d = (struct match_data *)data;
+	struct ccw_device * cdev;
+
+	cdev = to_ccwdev(dev);
+	if ((cdev->private->state == DEV_STATE_DISCONNECTED) &&
+	    (cdev->private->devno == d->devno) &&
+	    (cdev != d->sibling)) {
+		cdev->private->state = DEV_STATE_NOT_OPER;
+		return 1;
+	}
+	return 0;
+}
+
 static struct ccw_device *
 get_disc_ccwdev_by_devno(unsigned int devno, struct ccw_device *sibling)
 {
-	struct ccw_device *cdev;
-	struct list_head *entry;
 	struct device *dev;
+	struct match_data data = {
+		.devno  = devno,
+		.sibling = sibling,
+	};
 
-	if (!get_bus(&ccw_bus_type))
-		return NULL;
-	down_read(&ccw_bus_type.subsys.rwsem);
-	cdev = NULL;
-	list_for_each(entry, &ccw_bus_type.devices.list) {
-		dev = get_device(container_of(entry,
-					      struct device, bus_list));
-		if (!dev)
-			continue;
-		cdev = to_ccwdev(dev);
-		if ((cdev->private->state == DEV_STATE_DISCONNECTED) &&
-		    (cdev->private->devno == devno) &&
-		    (cdev != sibling)) {
-			cdev->private->state = DEV_STATE_NOT_OPER;
-			break;
-		}
-		put_device(dev);
-		cdev = NULL;
-	}
-	up_read(&ccw_bus_type.subsys.rwsem);
-	put_bus(&ccw_bus_type);
+	dev = bus_find_device(&css_bus_type, NULL, &data, match_devno);
 
-	return cdev;
+	return dev ? to_ccwdev(dev) : NULL;
 }
 
 static void
@@ -647,7 +650,7 @@
 	cdev = (struct ccw_device *) data;
 	sch = to_subchannel(cdev->dev.parent);
 
-	if (!list_empty(&sch->dev.children)) {
+	if (klist_node_attached(&cdev->dev.knode_parent)) {
 		bus_rescan_devices(&ccw_bus_type);
 		goto out;
 	}
@@ -1019,30 +1022,29 @@
 /*
  * get ccw_device matching the busid, but only if owned by cdrv
  */
+static int
+__ccwdev_check_busid(struct device *dev, void *id)
+{
+	char *bus_id;
+
+	bus_id = (char *)id;
+
+	return (strncmp(bus_id, dev->bus_id, BUS_ID_SIZE) == 0);
+}
+
+
 struct ccw_device *
 get_ccwdev_by_busid(struct ccw_driver *cdrv, const char *bus_id)
 {
-	struct device *d, *dev;
+	struct device *dev;
 	struct device_driver *drv;
 
 	drv = get_driver(&cdrv->driver);
 	if (!drv)
-		return 0;
+		return NULL;
 
-	down_read(&drv->bus->subsys.rwsem);
-
-	dev = NULL;
-	list_for_each_entry(d, &drv->devices, driver_list) {
-		dev = get_device(d);
-
-		if (dev && !strncmp(bus_id, dev->bus_id, BUS_ID_SIZE))
-			break;
-		else if (dev) {
-			put_device(dev);
-			dev = NULL;
-		}
-	}
-	up_read(&drv->bus->subsys.rwsem);
+	dev = driver_find_device(drv, NULL, (void *)bus_id,
+				 __ccwdev_check_busid);
 	put_driver(drv);
 
 	return dev ? to_ccwdev(dev) : 0;
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c
index bbe9f45..82194c4 100644
--- a/drivers/s390/cio/qdio.c
+++ b/drivers/s390/cio/qdio.c
@@ -56,7 +56,7 @@
 #include "ioasm.h"
 #include "chsc.h"
 
-#define VERSION_QDIO_C "$Revision: 1.98 $"
+#define VERSION_QDIO_C "$Revision: 1.101 $"
 
 /****************** MODULE PARAMETER VARIABLES ********************/
 MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
@@ -3342,7 +3342,7 @@
 qdio_register_dbf_views(void)
 {
 	qdio_dbf_setup=debug_register(QDIO_DBF_SETUP_NAME,
-				      QDIO_DBF_SETUP_INDEX,
+				      QDIO_DBF_SETUP_PAGES,
 				      QDIO_DBF_SETUP_NR_AREAS,
 				      QDIO_DBF_SETUP_LEN);
 	if (!qdio_dbf_setup)
@@ -3351,7 +3351,7 @@
 	debug_set_level(qdio_dbf_setup,QDIO_DBF_SETUP_LEVEL);
 
 	qdio_dbf_sbal=debug_register(QDIO_DBF_SBAL_NAME,
-				     QDIO_DBF_SBAL_INDEX,
+				     QDIO_DBF_SBAL_PAGES,
 				     QDIO_DBF_SBAL_NR_AREAS,
 				     QDIO_DBF_SBAL_LEN);
 	if (!qdio_dbf_sbal)
@@ -3361,7 +3361,7 @@
 	debug_set_level(qdio_dbf_sbal,QDIO_DBF_SBAL_LEVEL);
 
 	qdio_dbf_sense=debug_register(QDIO_DBF_SENSE_NAME,
-				      QDIO_DBF_SENSE_INDEX,
+				      QDIO_DBF_SENSE_PAGES,
 				      QDIO_DBF_SENSE_NR_AREAS,
 				      QDIO_DBF_SENSE_LEN);
 	if (!qdio_dbf_sense)
@@ -3371,7 +3371,7 @@
 	debug_set_level(qdio_dbf_sense,QDIO_DBF_SENSE_LEVEL);
 
 	qdio_dbf_trace=debug_register(QDIO_DBF_TRACE_NAME,
-				      QDIO_DBF_TRACE_INDEX,
+				      QDIO_DBF_TRACE_PAGES,
 				      QDIO_DBF_TRACE_NR_AREAS,
 				      QDIO_DBF_TRACE_LEN);
 	if (!qdio_dbf_trace)
@@ -3382,7 +3382,7 @@
 
 #ifdef CONFIG_QDIO_DEBUG
         qdio_dbf_slsb_out=debug_register(QDIO_DBF_SLSB_OUT_NAME,
-                                         QDIO_DBF_SLSB_OUT_INDEX,
+                                         QDIO_DBF_SLSB_OUT_PAGES,
                                          QDIO_DBF_SLSB_OUT_NR_AREAS,
                                          QDIO_DBF_SLSB_OUT_LEN);
         if (!qdio_dbf_slsb_out)
@@ -3391,7 +3391,7 @@
         debug_set_level(qdio_dbf_slsb_out,QDIO_DBF_SLSB_OUT_LEVEL);
 
         qdio_dbf_slsb_in=debug_register(QDIO_DBF_SLSB_IN_NAME,
-                                        QDIO_DBF_SLSB_IN_INDEX,
+                                        QDIO_DBF_SLSB_IN_PAGES,
                                         QDIO_DBF_SLSB_IN_NR_AREAS,
                                         QDIO_DBF_SLSB_IN_LEN);
         if (!qdio_dbf_slsb_in)
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h
index b6daada..6b8aa6a 100644
--- a/drivers/s390/cio/qdio.h
+++ b/drivers/s390/cio/qdio.h
@@ -3,7 +3,7 @@
 
 #include <asm/page.h>
 
-#define VERSION_CIO_QDIO_H "$Revision: 1.32 $"
+#define VERSION_CIO_QDIO_H "$Revision: 1.33 $"
 
 #ifdef CONFIG_QDIO_DEBUG
 #define QDIO_VERBOSE_LEVEL 9
@@ -132,7 +132,7 @@
 
 #define QDIO_DBF_SETUP_NAME "qdio_setup"
 #define QDIO_DBF_SETUP_LEN 8
-#define QDIO_DBF_SETUP_INDEX 2
+#define QDIO_DBF_SETUP_PAGES 4
 #define QDIO_DBF_SETUP_NR_AREAS 1
 #ifdef CONFIG_QDIO_DEBUG
 #define QDIO_DBF_SETUP_LEVEL 6
@@ -142,7 +142,7 @@
 
 #define QDIO_DBF_SBAL_NAME "qdio_labs" /* sbal */
 #define QDIO_DBF_SBAL_LEN 256
-#define QDIO_DBF_SBAL_INDEX 2
+#define QDIO_DBF_SBAL_PAGES 4
 #define QDIO_DBF_SBAL_NR_AREAS 2
 #ifdef CONFIG_QDIO_DEBUG
 #define QDIO_DBF_SBAL_LEVEL 6
@@ -154,16 +154,16 @@
 #define QDIO_DBF_TRACE_LEN 8
 #define QDIO_DBF_TRACE_NR_AREAS 2
 #ifdef CONFIG_QDIO_DEBUG
-#define QDIO_DBF_TRACE_INDEX 4
+#define QDIO_DBF_TRACE_PAGES 16
 #define QDIO_DBF_TRACE_LEVEL 4 /* -------- could be even more verbose here */
 #else /* CONFIG_QDIO_DEBUG */
-#define QDIO_DBF_TRACE_INDEX 2
+#define QDIO_DBF_TRACE_PAGES 4
 #define QDIO_DBF_TRACE_LEVEL 2
 #endif /* CONFIG_QDIO_DEBUG */
 
 #define QDIO_DBF_SENSE_NAME "qdio_sense"
 #define QDIO_DBF_SENSE_LEN 64
-#define QDIO_DBF_SENSE_INDEX 1
+#define QDIO_DBF_SENSE_PAGES 2
 #define QDIO_DBF_SENSE_NR_AREAS 1
 #ifdef CONFIG_QDIO_DEBUG
 #define QDIO_DBF_SENSE_LEVEL 6
@@ -176,13 +176,13 @@
 
 #define QDIO_DBF_SLSB_OUT_NAME "qdio_slsb_out"
 #define QDIO_DBF_SLSB_OUT_LEN QDIO_MAX_BUFFERS_PER_Q
-#define QDIO_DBF_SLSB_OUT_INDEX 8
+#define QDIO_DBF_SLSB_OUT_PAGES 256
 #define QDIO_DBF_SLSB_OUT_NR_AREAS 1
 #define QDIO_DBF_SLSB_OUT_LEVEL 6
 
 #define QDIO_DBF_SLSB_IN_NAME "qdio_slsb_in"
 #define QDIO_DBF_SLSB_IN_LEN QDIO_MAX_BUFFERS_PER_Q
-#define QDIO_DBF_SLSB_IN_INDEX 8
+#define QDIO_DBF_SLSB_IN_PAGES 256
 #define QDIO_DBF_SLSB_IN_NR_AREAS 1
 #define QDIO_DBF_SLSB_IN_LEVEL 6
 #endif /* CONFIG_QDIO_DEBUG */
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index 06804d3..60440db 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -146,8 +146,8 @@
 static int
 claw_register_debug_facility(void)
 {
-	claw_dbf_setup = debug_register("claw_setup", 1, 1, 8);
-	claw_dbf_trace = debug_register("claw_trace", 1, 2, 8);
+	claw_dbf_setup = debug_register("claw_setup", 2, 1, 8);
+	claw_dbf_trace = debug_register("claw_trace", 2, 2, 8);
 	if (claw_dbf_setup == NULL || claw_dbf_trace == NULL) {
 		printk(KERN_WARNING "Not enough memory for debug facility.\n");
 		claw_unregister_debug_facility();
@@ -241,20 +241,20 @@
 static void dumpit (char *buf, int len);
 #endif
 /* sysfs Functions */
-static ssize_t claw_hname_show(struct device *dev, char *buf);
-static ssize_t claw_hname_write(struct device *dev,
+static ssize_t claw_hname_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t claw_hname_write(struct device *dev, struct device_attribute *attr,
 	const char *buf, size_t count);
-static ssize_t claw_adname_show(struct device *dev, char *buf);
-static ssize_t claw_adname_write(struct device *dev,
+static ssize_t claw_adname_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t claw_adname_write(struct device *dev, struct device_attribute *attr,
 	const char *buf, size_t count);
-static ssize_t claw_apname_show(struct device *dev, char *buf);
-static ssize_t claw_apname_write(struct device *dev,
+static ssize_t claw_apname_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t claw_apname_write(struct device *dev, struct device_attribute *attr,
 	const char *buf, size_t count);
-static ssize_t claw_wbuff_show(struct device *dev, char *buf);
-static ssize_t claw_wbuff_write(struct device *dev,
+static ssize_t claw_wbuff_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t claw_wbuff_write(struct device *dev, struct device_attribute *attr,
 	const char *buf, size_t count);
-static ssize_t claw_rbuff_show(struct device *dev, char *buf);
-static ssize_t claw_rbuff_write(struct device *dev,
+static ssize_t claw_rbuff_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t claw_rbuff_write(struct device *dev, struct device_attribute *attr,
 	const char *buf, size_t count);
 static int claw_add_files(struct device *dev);
 static void claw_remove_files(struct device *dev);
@@ -4149,7 +4149,7 @@
  * sysfs attributes
  */
 static ssize_t
-claw_hname_show(struct device *dev, char *buf)
+claw_hname_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct claw_privbk *priv;
 	struct claw_env *  p_env;
@@ -4162,7 +4162,7 @@
 }
 
 static ssize_t
-claw_hname_write(struct device *dev, const char *buf, size_t count)
+claw_hname_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct claw_privbk *priv;
 	struct claw_env *  p_env;
@@ -4186,7 +4186,7 @@
 static DEVICE_ATTR(host_name, 0644, claw_hname_show, claw_hname_write);
 
 static ssize_t
-claw_adname_show(struct device *dev, char *buf)
+claw_adname_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct claw_privbk *priv;
 	struct claw_env *  p_env;
@@ -4199,7 +4199,7 @@
 }
 
 static ssize_t
-claw_adname_write(struct device *dev, const char *buf, size_t count)
+claw_adname_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct claw_privbk *priv;
 	struct claw_env *  p_env;
@@ -4223,7 +4223,7 @@
 static DEVICE_ATTR(adapter_name, 0644, claw_adname_show, claw_adname_write);
 
 static ssize_t
-claw_apname_show(struct device *dev, char *buf)
+claw_apname_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct claw_privbk *priv;
 	struct claw_env *  p_env;
@@ -4237,7 +4237,7 @@
 }
 
 static ssize_t
-claw_apname_write(struct device *dev, const char *buf, size_t count)
+claw_apname_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct claw_privbk *priv;
 	struct claw_env *  p_env;
@@ -4271,7 +4271,7 @@
 static DEVICE_ATTR(api_type, 0644, claw_apname_show, claw_apname_write);
 
 static ssize_t
-claw_wbuff_show(struct device *dev, char *buf)
+claw_wbuff_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct claw_privbk *priv;
 	struct claw_env * p_env;
@@ -4284,7 +4284,7 @@
 }
 
 static ssize_t
-claw_wbuff_write(struct device *dev, const char *buf, size_t count)
+claw_wbuff_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct claw_privbk *priv;
 	struct claw_env *  p_env;
@@ -4312,7 +4312,7 @@
 static DEVICE_ATTR(write_buffer, 0644, claw_wbuff_show, claw_wbuff_write);
 
 static ssize_t
-claw_rbuff_show(struct device *dev, char *buf)
+claw_rbuff_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct claw_privbk *priv;
 	struct claw_env *  p_env;
@@ -4325,7 +4325,7 @@
 }
 
 static ssize_t
-claw_rbuff_write(struct device *dev, const char *buf, size_t count)
+claw_rbuff_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct claw_privbk *priv;
 	struct claw_env *p_env;
diff --git a/drivers/s390/net/ctcdbug.c b/drivers/s390/net/ctcdbug.c
index 2c86bfa..0e2a8bb 100644
--- a/drivers/s390/net/ctcdbug.c
+++ b/drivers/s390/net/ctcdbug.c
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/ctcdbug.c ($Revision: 1.4 $)
+ * linux/drivers/s390/net/ctcdbug.c ($Revision: 1.6 $)
  *
  * CTC / ESCON network driver - s390 dbf exploit.
  *
@@ -9,7 +9,7 @@
  *    Author(s): Original Code written by
  *			  Peter Tiedemann (ptiedem@de.ibm.com)
  *
- *    $Revision: 1.4 $	 $Date: 2004/08/04 10:11:59 $
+ *    $Revision: 1.6 $	 $Date: 2005/05/11 08:10:17 $
  *
  * 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
@@ -51,15 +51,15 @@
 ctc_register_dbf_views(void)
 {
 	ctc_dbf_setup = debug_register(CTC_DBF_SETUP_NAME,
-					CTC_DBF_SETUP_INDEX,
+					CTC_DBF_SETUP_PAGES,
 					CTC_DBF_SETUP_NR_AREAS,
 					CTC_DBF_SETUP_LEN);
 	ctc_dbf_data = debug_register(CTC_DBF_DATA_NAME,
-				       CTC_DBF_DATA_INDEX,
+				       CTC_DBF_DATA_PAGES,
 				       CTC_DBF_DATA_NR_AREAS,
 				       CTC_DBF_DATA_LEN);
 	ctc_dbf_trace = debug_register(CTC_DBF_TRACE_NAME,
-					CTC_DBF_TRACE_INDEX,
+					CTC_DBF_TRACE_PAGES,
 					CTC_DBF_TRACE_NR_AREAS,
 					CTC_DBF_TRACE_LEN);
 
diff --git a/drivers/s390/net/ctcdbug.h b/drivers/s390/net/ctcdbug.h
index 7fe2ebd..7d6afa1 100644
--- a/drivers/s390/net/ctcdbug.h
+++ b/drivers/s390/net/ctcdbug.h
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/ctcdbug.h ($Revision: 1.5 $)
+ * linux/drivers/s390/net/ctcdbug.h ($Revision: 1.6 $)
  *
  * CTC / ESCON network driver - s390 dbf exploit.
  *
@@ -9,7 +9,7 @@
  *    Author(s): Original Code written by
  *			  Peter Tiedemann (ptiedem@de.ibm.com)
  *
- *    $Revision: 1.5 $	 $Date: 2005/02/27 19:46:44 $
+ *    $Revision: 1.6 $	 $Date: 2005/05/11 08:10:17 $
  *
  * 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
@@ -35,19 +35,19 @@
  */
 #define CTC_DBF_SETUP_NAME "ctc_setup"
 #define CTC_DBF_SETUP_LEN 16
-#define CTC_DBF_SETUP_INDEX 3
+#define CTC_DBF_SETUP_PAGES 8
 #define CTC_DBF_SETUP_NR_AREAS 1
 #define CTC_DBF_SETUP_LEVEL 3
 
 #define CTC_DBF_DATA_NAME "ctc_data"
 #define CTC_DBF_DATA_LEN 128
-#define CTC_DBF_DATA_INDEX 3
+#define CTC_DBF_DATA_PAGES 8
 #define CTC_DBF_DATA_NR_AREAS 1
 #define CTC_DBF_DATA_LEVEL 3
 
 #define CTC_DBF_TRACE_NAME "ctc_trace"
 #define CTC_DBF_TRACE_LEN 16
-#define CTC_DBF_TRACE_INDEX 2
+#define CTC_DBF_TRACE_PAGES 4
 #define CTC_DBF_TRACE_NR_AREAS 2
 #define CTC_DBF_TRACE_LEVEL 3
 
diff --git a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
index ff3e95e..96ca863 100644
--- a/drivers/s390/net/ctcmain.c
+++ b/drivers/s390/net/ctcmain.c
@@ -2469,7 +2469,7 @@
  */
 
 static ssize_t
-buffer_show(struct device *dev, char *buf)
+buffer_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct ctc_priv *priv;
 
@@ -2481,7 +2481,7 @@
 }
 
 static ssize_t
-buffer_write(struct device *dev, const char *buf, size_t count)
+buffer_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct ctc_priv *priv;
 	struct net_device *ndev;
@@ -2530,13 +2530,13 @@
 }
 
 static ssize_t
-loglevel_show(struct device *dev, char *buf)
+loglevel_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	return sprintf(buf, "%d\n", loglevel);
 }
 
 static ssize_t
-loglevel_write(struct device *dev, const char *buf, size_t count)
+loglevel_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	int ll1;
 
@@ -2589,7 +2589,7 @@
 }
 
 static ssize_t
-stats_show(struct device *dev, char *buf)
+stats_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct ctc_priv *priv = dev->driver_data;
 	if (!priv)
@@ -2599,7 +2599,7 @@
 }
 
 static ssize_t
-stats_write(struct device *dev, const char *buf, size_t count)
+stats_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct ctc_priv *priv = dev->driver_data;
 	if (!priv)
@@ -2654,7 +2654,7 @@
 }
 
 static ssize_t
-ctc_proto_show(struct device *dev, char *buf)
+ctc_proto_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct ctc_priv *priv;
 
@@ -2666,7 +2666,7 @@
 }
 
 static ssize_t
-ctc_proto_store(struct device *dev, const char *buf, size_t count)
+ctc_proto_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct ctc_priv *priv;
 	int value;
@@ -2687,7 +2687,7 @@
 
 
 static ssize_t
-ctc_type_show(struct device *dev, char *buf)
+ctc_type_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct ccwgroup_device *cgdev;
 
diff --git a/drivers/s390/net/iucv.h b/drivers/s390/net/iucv.h
index 1983302..0c4644d 100644
--- a/drivers/s390/net/iucv.h
+++ b/drivers/s390/net/iucv.h
@@ -37,19 +37,19 @@
  */
 #define IUCV_DBF_SETUP_NAME "iucv_setup"
 #define IUCV_DBF_SETUP_LEN 32
-#define IUCV_DBF_SETUP_INDEX 1
+#define IUCV_DBF_SETUP_PAGES 2
 #define IUCV_DBF_SETUP_NR_AREAS 1
 #define IUCV_DBF_SETUP_LEVEL 3
 
 #define IUCV_DBF_DATA_NAME "iucv_data"
 #define IUCV_DBF_DATA_LEN 128
-#define IUCV_DBF_DATA_INDEX 1
+#define IUCV_DBF_DATA_PAGES 2
 #define IUCV_DBF_DATA_NR_AREAS 1
 #define IUCV_DBF_DATA_LEVEL 2
 
 #define IUCV_DBF_TRACE_NAME "iucv_trace"
 #define IUCV_DBF_TRACE_LEN 16
-#define IUCV_DBF_TRACE_INDEX 2
+#define IUCV_DBF_TRACE_PAGES 4
 #define IUCV_DBF_TRACE_NR_AREAS 1
 #define IUCV_DBF_TRACE_LEVEL 3
 
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index cccfed2..46f34ba 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -11,7 +11,7 @@
  *			  Frank Pavlic (pavlic@de.ibm.com) and
  *		 	  Martin Schwidefsky <schwidefsky@de.ibm.com>
  *
- *    $Revision: 1.98 $	 $Date: 2005/04/18 13:41:29 $
+ *    $Revision: 1.99 $	 $Date: 2005/05/11 08:10:17 $
  *
  * 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
@@ -59,7 +59,7 @@
 /**
  * initialization string for output
  */
-#define VERSION_LCS_C  "$Revision: 1.98 $"
+#define VERSION_LCS_C  "$Revision: 1.99 $"
 
 static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")";
 static char debug_buffer[255];
@@ -93,8 +93,8 @@
 static int
 lcs_register_debug_facility(void)
 {
-	lcs_dbf_setup = debug_register("lcs_setup", 1, 1, 8);
-	lcs_dbf_trace = debug_register("lcs_trace", 1, 2, 8);
+	lcs_dbf_setup = debug_register("lcs_setup", 2, 1, 8);
+	lcs_dbf_trace = debug_register("lcs_trace", 2, 2, 8);
 	if (lcs_dbf_setup == NULL || lcs_dbf_trace == NULL) {
 		PRINT_ERR("Not enough memory for debug facility.\n");
 		lcs_unregister_debug_facility();
@@ -1984,7 +1984,7 @@
  * show function for portno called by cat or similar things
  */
 static ssize_t
-lcs_portno_show (struct device *dev, char *buf)
+lcs_portno_show (struct device *dev, struct device_attribute *attr, char *buf)
 {
         struct lcs_card *card;
 
@@ -2000,7 +2000,7 @@
  * store the value which is piped to file portno
  */
 static ssize_t
-lcs_portno_store (struct device *dev, const char *buf, size_t count)
+lcs_portno_store (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
         struct lcs_card *card;
         int value;
@@ -2021,7 +2021,7 @@
 static DEVICE_ATTR(portno, 0644, lcs_portno_show, lcs_portno_store);
 
 static ssize_t
-lcs_type_show(struct device *dev, char *buf)
+lcs_type_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct ccwgroup_device *cgdev;
 
@@ -2035,7 +2035,7 @@
 static DEVICE_ATTR(type, 0444, lcs_type_show, NULL);
 
 static ssize_t
-lcs_timeout_show(struct device *dev, char *buf)
+lcs_timeout_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lcs_card *card;
 
@@ -2045,7 +2045,7 @@
 }
 
 static ssize_t
-lcs_timeout_store (struct device *dev, const char *buf, size_t count)
+lcs_timeout_store (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
         struct lcs_card *card;
         int value;
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 16e8e69..69425a7 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -1,5 +1,5 @@
 /*
- * $Id: netiucv.c,v 1.63 2004/07/27 13:36:05 mschwide Exp $
+ * $Id: netiucv.c,v 1.66 2005/05/11 08:10:17 holzheu Exp $
  *
  * IUCV network driver
  *
@@ -30,7 +30,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * RELEASE-TAG: IUCV network driver $Revision: 1.63 $
+ * RELEASE-TAG: IUCV network driver $Revision: 1.66 $
  *
  */
 
@@ -391,15 +391,15 @@
 iucv_register_dbf_views(void)
 {
 	iucv_dbf_setup = debug_register(IUCV_DBF_SETUP_NAME,
-					IUCV_DBF_SETUP_INDEX,
+					IUCV_DBF_SETUP_PAGES,
 					IUCV_DBF_SETUP_NR_AREAS,
 					IUCV_DBF_SETUP_LEN);
 	iucv_dbf_data = debug_register(IUCV_DBF_DATA_NAME,
-				       IUCV_DBF_DATA_INDEX,
+				       IUCV_DBF_DATA_PAGES,
 				       IUCV_DBF_DATA_NR_AREAS,
 				       IUCV_DBF_DATA_LEN);
 	iucv_dbf_trace = debug_register(IUCV_DBF_TRACE_NAME,
-					IUCV_DBF_TRACE_INDEX,
+					IUCV_DBF_TRACE_PAGES,
 					IUCV_DBF_TRACE_NR_AREAS,
 					IUCV_DBF_TRACE_LEN);
 
@@ -1356,7 +1356,7 @@
  *****************************************************************************/
 
 static ssize_t
-user_show (struct device *dev, char *buf)
+user_show (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1365,7 +1365,7 @@
 }
 
 static ssize_t
-user_write (struct device *dev, const char *buf, size_t count)
+user_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 	struct net_device *ndev = priv->conn->netdev;
@@ -1422,7 +1422,7 @@
 static DEVICE_ATTR(user, 0644, user_show, user_write);
 
 static ssize_t
-buffer_show (struct device *dev, char *buf)
+buffer_show (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1431,7 +1431,7 @@
 }
 
 static ssize_t
-buffer_write (struct device *dev, const char *buf, size_t count)
+buffer_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 	struct net_device *ndev = priv->conn->netdev;
@@ -1486,7 +1486,7 @@
 static DEVICE_ATTR(buffer, 0644, buffer_show, buffer_write);
 
 static ssize_t
-dev_fsm_show (struct device *dev, char *buf)
+dev_fsm_show (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1497,7 +1497,7 @@
 static DEVICE_ATTR(device_fsm_state, 0444, dev_fsm_show, NULL);
 
 static ssize_t
-conn_fsm_show (struct device *dev, char *buf)
+conn_fsm_show (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1508,7 +1508,7 @@
 static DEVICE_ATTR(connection_fsm_state, 0444, conn_fsm_show, NULL);
 
 static ssize_t
-maxmulti_show (struct device *dev, char *buf)
+maxmulti_show (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1517,7 +1517,7 @@
 }
 
 static ssize_t
-maxmulti_write (struct device *dev, const char *buf, size_t count)
+maxmulti_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1529,7 +1529,7 @@
 static DEVICE_ATTR(max_tx_buffer_used, 0644, maxmulti_show, maxmulti_write);
 
 static ssize_t
-maxcq_show (struct device *dev, char *buf)
+maxcq_show (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1538,7 +1538,7 @@
 }
 
 static ssize_t
-maxcq_write (struct device *dev, const char *buf, size_t count)
+maxcq_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 	
@@ -1550,7 +1550,7 @@
 static DEVICE_ATTR(max_chained_skbs, 0644, maxcq_show, maxcq_write);
 
 static ssize_t
-sdoio_show (struct device *dev, char *buf)
+sdoio_show (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1559,7 +1559,7 @@
 }
 
 static ssize_t
-sdoio_write (struct device *dev, const char *buf, size_t count)
+sdoio_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 	
@@ -1571,7 +1571,7 @@
 static DEVICE_ATTR(tx_single_write_ops, 0644, sdoio_show, sdoio_write);
 
 static ssize_t
-mdoio_show (struct device *dev, char *buf)
+mdoio_show (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1580,7 +1580,7 @@
 }
 
 static ssize_t
-mdoio_write (struct device *dev, const char *buf, size_t count)
+mdoio_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 	
@@ -1592,7 +1592,7 @@
 static DEVICE_ATTR(tx_multi_write_ops, 0644, mdoio_show, mdoio_write);
 
 static ssize_t
-txlen_show (struct device *dev, char *buf)
+txlen_show (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1601,7 +1601,7 @@
 }
 
 static ssize_t
-txlen_write (struct device *dev, const char *buf, size_t count)
+txlen_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 	
@@ -1613,7 +1613,7 @@
 static DEVICE_ATTR(netto_bytes, 0644, txlen_show, txlen_write);
 
 static ssize_t
-txtime_show (struct device *dev, char *buf)
+txtime_show (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1622,7 +1622,7 @@
 }
 
 static ssize_t
-txtime_write (struct device *dev, const char *buf, size_t count)
+txtime_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 	
@@ -1634,7 +1634,7 @@
 static DEVICE_ATTR(max_tx_io_time, 0644, txtime_show, txtime_write);
 
 static ssize_t
-txpend_show (struct device *dev, char *buf)
+txpend_show (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1643,7 +1643,7 @@
 }
 
 static ssize_t
-txpend_write (struct device *dev, const char *buf, size_t count)
+txpend_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1655,7 +1655,7 @@
 static DEVICE_ATTR(tx_pending, 0644, txpend_show, txpend_write);
 
 static ssize_t
-txmpnd_show (struct device *dev, char *buf)
+txmpnd_show (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -1664,7 +1664,7 @@
 }
 
 static ssize_t
-txmpnd_write (struct device *dev, const char *buf, size_t count)
+txmpnd_write (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct netiucv_priv *priv = dev->driver_data;
 
@@ -2076,7 +2076,7 @@
 static void
 netiucv_banner(void)
 {
-	char vbuf[] = "$Revision: 1.63 $";
+	char vbuf[] = "$Revision: 1.66 $";
 	char *version = vbuf;
 
 	if ((version = strchr(version, ':'))) {
diff --git a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h
index a755b57..008e0a5 100644
--- a/drivers/s390/net/qeth.h
+++ b/drivers/s390/net/qeth.h
@@ -42,44 +42,44 @@
  */
 #define QETH_DBF_SETUP_NAME "qeth_setup"
 #define QETH_DBF_SETUP_LEN 8
-#define QETH_DBF_SETUP_INDEX 3
+#define QETH_DBF_SETUP_PAGES 8
 #define QETH_DBF_SETUP_NR_AREAS 1
 #define QETH_DBF_SETUP_LEVEL 5
 
 #define QETH_DBF_MISC_NAME "qeth_misc"
 #define QETH_DBF_MISC_LEN 128
-#define QETH_DBF_MISC_INDEX 1
+#define QETH_DBF_MISC_PAGES 2
 #define QETH_DBF_MISC_NR_AREAS 1
 #define QETH_DBF_MISC_LEVEL 2
 
 #define QETH_DBF_DATA_NAME "qeth_data"
 #define QETH_DBF_DATA_LEN 96
-#define QETH_DBF_DATA_INDEX 3
+#define QETH_DBF_DATA_PAGES 8
 #define QETH_DBF_DATA_NR_AREAS 1
 #define QETH_DBF_DATA_LEVEL 2
 
 #define QETH_DBF_CONTROL_NAME "qeth_control"
 #define QETH_DBF_CONTROL_LEN 256
-#define QETH_DBF_CONTROL_INDEX 3
+#define QETH_DBF_CONTROL_PAGES 8
 #define QETH_DBF_CONTROL_NR_AREAS 2
 #define QETH_DBF_CONTROL_LEVEL 5
 
 #define QETH_DBF_TRACE_NAME "qeth_trace"
 #define QETH_DBF_TRACE_LEN 8
-#define QETH_DBF_TRACE_INDEX 2
+#define QETH_DBF_TRACE_PAGES 4
 #define QETH_DBF_TRACE_NR_AREAS 2
 #define QETH_DBF_TRACE_LEVEL 3
 extern debug_info_t *qeth_dbf_trace;
 
 #define QETH_DBF_SENSE_NAME "qeth_sense"
 #define QETH_DBF_SENSE_LEN 64
-#define QETH_DBF_SENSE_INDEX 1
+#define QETH_DBF_SENSE_PAGES 2
 #define QETH_DBF_SENSE_NR_AREAS 1
 #define QETH_DBF_SENSE_LEVEL 2
 
 #define QETH_DBF_QERR_NAME "qeth_qerr"
 #define QETH_DBF_QERR_LEN 8
-#define QETH_DBF_QERR_INDEX 1
+#define QETH_DBF_QERR_PAGES 2
 #define QETH_DBF_QERR_NR_AREAS 2
 #define QETH_DBF_QERR_LEVEL 2
 
diff --git a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
index 208127a..3cb88c7 100644
--- a/drivers/s390/net/qeth_main.c
+++ b/drivers/s390/net/qeth_main.c
@@ -7639,31 +7639,31 @@
 qeth_register_dbf_views(void)
 {
 	qeth_dbf_setup = debug_register(QETH_DBF_SETUP_NAME,
-					QETH_DBF_SETUP_INDEX,
+					QETH_DBF_SETUP_PAGES,
 					QETH_DBF_SETUP_NR_AREAS,
 					QETH_DBF_SETUP_LEN);
 	qeth_dbf_misc = debug_register(QETH_DBF_MISC_NAME,
-				       QETH_DBF_MISC_INDEX,
+				       QETH_DBF_MISC_PAGES,
 				       QETH_DBF_MISC_NR_AREAS,
 				       QETH_DBF_MISC_LEN);
 	qeth_dbf_data = debug_register(QETH_DBF_DATA_NAME,
-				       QETH_DBF_DATA_INDEX,
+				       QETH_DBF_DATA_PAGES,
 				       QETH_DBF_DATA_NR_AREAS,
 				       QETH_DBF_DATA_LEN);
 	qeth_dbf_control = debug_register(QETH_DBF_CONTROL_NAME,
-					  QETH_DBF_CONTROL_INDEX,
+					  QETH_DBF_CONTROL_PAGES,
 					  QETH_DBF_CONTROL_NR_AREAS,
 					  QETH_DBF_CONTROL_LEN);
 	qeth_dbf_sense = debug_register(QETH_DBF_SENSE_NAME,
-					QETH_DBF_SENSE_INDEX,
+					QETH_DBF_SENSE_PAGES,
 					QETH_DBF_SENSE_NR_AREAS,
 					QETH_DBF_SENSE_LEN);
 	qeth_dbf_qerr = debug_register(QETH_DBF_QERR_NAME,
-				       QETH_DBF_QERR_INDEX,
+				       QETH_DBF_QERR_PAGES,
 				       QETH_DBF_QERR_NR_AREAS,
 				       QETH_DBF_QERR_LEN);
 	qeth_dbf_trace = debug_register(QETH_DBF_TRACE_NAME,
-					QETH_DBF_TRACE_INDEX,
+					QETH_DBF_TRACE_PAGES,
 					QETH_DBF_TRACE_NR_AREAS,
 					QETH_DBF_TRACE_LEN);
 
diff --git a/drivers/s390/net/qeth_sys.c b/drivers/s390/net/qeth_sys.c
index 2403483..98bedb0 100644
--- a/drivers/s390/net/qeth_sys.c
+++ b/drivers/s390/net/qeth_sys.c
@@ -30,7 +30,7 @@
 //low/high watermark
 
 static ssize_t
-qeth_dev_state_show(struct device *dev, char *buf)
+qeth_dev_state_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 	if (!card)
@@ -58,7 +58,7 @@
 static DEVICE_ATTR(state, 0444, qeth_dev_state_show, NULL);
 
 static ssize_t
-qeth_dev_chpid_show(struct device *dev, char *buf)
+qeth_dev_chpid_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 	if (!card)
@@ -70,7 +70,7 @@
 static DEVICE_ATTR(chpid, 0444, qeth_dev_chpid_show, NULL);
 
 static ssize_t
-qeth_dev_if_name_show(struct device *dev, char *buf)
+qeth_dev_if_name_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 	if (!card)
@@ -81,7 +81,7 @@
 static DEVICE_ATTR(if_name, 0444, qeth_dev_if_name_show, NULL);
 
 static ssize_t
-qeth_dev_card_type_show(struct device *dev, char *buf)
+qeth_dev_card_type_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 	if (!card)
@@ -93,7 +93,7 @@
 static DEVICE_ATTR(card_type, 0444, qeth_dev_card_type_show, NULL);
 
 static ssize_t
-qeth_dev_portno_show(struct device *dev, char *buf)
+qeth_dev_portno_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 	if (!card)
@@ -103,7 +103,7 @@
 }
 
 static ssize_t
-qeth_dev_portno_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_portno_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 	char *tmp;
@@ -129,7 +129,7 @@
 static DEVICE_ATTR(portno, 0644, qeth_dev_portno_show, qeth_dev_portno_store);
 
 static ssize_t
-qeth_dev_portname_show(struct device *dev, char *buf)
+qeth_dev_portname_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 	char portname[9] = {0, };
@@ -146,7 +146,7 @@
 }
 
 static ssize_t
-qeth_dev_portname_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_portname_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 	char *tmp;
@@ -177,7 +177,7 @@
 		qeth_dev_portname_store);
 
 static ssize_t
-qeth_dev_checksum_show(struct device *dev, char *buf)
+qeth_dev_checksum_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -188,7 +188,7 @@
 }
 
 static ssize_t
-qeth_dev_checksum_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_checksum_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 	char *tmp;
@@ -218,7 +218,7 @@
 		qeth_dev_checksum_store);
 
 static ssize_t
-qeth_dev_prioqing_show(struct device *dev, char *buf)
+qeth_dev_prioqing_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -237,7 +237,7 @@
 }
 
 static ssize_t
-qeth_dev_prioqing_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_prioqing_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 	char *tmp;
@@ -290,7 +290,7 @@
 		qeth_dev_prioqing_store);
 
 static ssize_t
-qeth_dev_bufcnt_show(struct device *dev, char *buf)
+qeth_dev_bufcnt_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -301,7 +301,7 @@
 }
 
 static ssize_t
-qeth_dev_bufcnt_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_bufcnt_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 	char *tmp;
@@ -360,7 +360,7 @@
 }
 
 static ssize_t
-qeth_dev_route4_show(struct device *dev, char *buf)
+qeth_dev_route4_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -410,7 +410,7 @@
 }
 
 static ssize_t
-qeth_dev_route4_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_route4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -425,7 +425,7 @@
 
 #ifdef CONFIG_QETH_IPV6
 static ssize_t
-qeth_dev_route6_show(struct device *dev, char *buf)
+qeth_dev_route6_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -439,7 +439,7 @@
 }
 
 static ssize_t
-qeth_dev_route6_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_route6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -461,7 +461,7 @@
 #endif
 
 static ssize_t
-qeth_dev_add_hhlen_show(struct device *dev, char *buf)
+qeth_dev_add_hhlen_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -472,7 +472,7 @@
 }
 
 static ssize_t
-qeth_dev_add_hhlen_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_add_hhlen_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 	char *tmp;
@@ -499,7 +499,7 @@
 		   qeth_dev_add_hhlen_store);
 
 static ssize_t
-qeth_dev_fake_ll_show(struct device *dev, char *buf)
+qeth_dev_fake_ll_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -510,7 +510,7 @@
 }
 
 static ssize_t
-qeth_dev_fake_ll_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_fake_ll_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 	char *tmp;
@@ -536,7 +536,7 @@
 		   qeth_dev_fake_ll_store);
 
 static ssize_t
-qeth_dev_fake_broadcast_show(struct device *dev, char *buf)
+qeth_dev_fake_broadcast_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -547,7 +547,7 @@
 }
 
 static ssize_t
-qeth_dev_fake_broadcast_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_fake_broadcast_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 	char *tmp;
@@ -574,7 +574,7 @@
 		   qeth_dev_fake_broadcast_store);
 
 static ssize_t
-qeth_dev_recover_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_recover_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 	char *tmp;
@@ -596,7 +596,7 @@
 static DEVICE_ATTR(recover, 0200, NULL, qeth_dev_recover_store);
 
 static ssize_t
-qeth_dev_broadcast_mode_show(struct device *dev, char *buf)
+qeth_dev_broadcast_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -613,7 +613,7 @@
 }
 
 static ssize_t
-qeth_dev_broadcast_mode_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_broadcast_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 	char *tmp;
@@ -651,7 +651,7 @@
 		   qeth_dev_broadcast_mode_store);
 
 static ssize_t
-qeth_dev_canonical_macaddr_show(struct device *dev, char *buf)
+qeth_dev_canonical_macaddr_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -667,7 +667,7 @@
 }
 
 static ssize_t
-qeth_dev_canonical_macaddr_store(struct device *dev, const char *buf,
+qeth_dev_canonical_macaddr_store(struct device *dev, struct device_attribute *attr, const char *buf,
 				  size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
@@ -703,7 +703,7 @@
 		   qeth_dev_canonical_macaddr_store);
 
 static ssize_t
-qeth_dev_layer2_show(struct device *dev, char *buf)
+qeth_dev_layer2_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -714,7 +714,7 @@
 }
 
 static ssize_t
-qeth_dev_layer2_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_layer2_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 	char *tmp;
@@ -742,7 +742,7 @@
 		   qeth_dev_layer2_store);
 
 static ssize_t
-qeth_dev_large_send_show(struct device *dev, char *buf)
+qeth_dev_large_send_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -762,7 +762,7 @@
 }
 
 static ssize_t
-qeth_dev_large_send_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_large_send_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 	enum qeth_large_send_types type;
@@ -832,7 +832,7 @@
 }
 
 static ssize_t
-qeth_dev_blkt_total_show(struct device *dev, char *buf)
+qeth_dev_blkt_total_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -841,7 +841,7 @@
 
 
 static ssize_t
-qeth_dev_blkt_total_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_blkt_total_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -855,7 +855,7 @@
 		   qeth_dev_blkt_total_store);
 
 static ssize_t
-qeth_dev_blkt_inter_show(struct device *dev, char *buf)
+qeth_dev_blkt_inter_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -864,7 +864,7 @@
 
 
 static ssize_t
-qeth_dev_blkt_inter_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_blkt_inter_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -876,7 +876,7 @@
 		   qeth_dev_blkt_inter_store);
 
 static ssize_t
-qeth_dev_blkt_inter_jumbo_show(struct device *dev, char *buf)
+qeth_dev_blkt_inter_jumbo_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -886,7 +886,7 @@
 
 
 static ssize_t
-qeth_dev_blkt_inter_jumbo_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_blkt_inter_jumbo_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -956,7 +956,7 @@
 
 
 static ssize_t
-qeth_dev_ipato_enable_show(struct device *dev, char *buf)
+qeth_dev_ipato_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -969,7 +969,7 @@
 }
 
 static ssize_t
-qeth_dev_ipato_enable_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_ipato_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 	char *tmp;
@@ -1004,7 +1004,7 @@
 			qeth_dev_ipato_enable_store);
 
 static ssize_t
-qeth_dev_ipato_invert4_show(struct device *dev, char *buf)
+qeth_dev_ipato_invert4_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -1018,7 +1018,7 @@
 }
 
 static ssize_t
-qeth_dev_ipato_invert4_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_ipato_invert4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 	char *tmp;
@@ -1084,7 +1084,7 @@
 }
 
 static ssize_t
-qeth_dev_ipato_add4_show(struct device *dev, char *buf)
+qeth_dev_ipato_add4_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -1153,7 +1153,7 @@
 }
 
 static ssize_t
-qeth_dev_ipato_add4_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_ipato_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -1186,7 +1186,7 @@
 }
 
 static ssize_t
-qeth_dev_ipato_del4_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_ipato_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -1201,7 +1201,7 @@
 
 #ifdef CONFIG_QETH_IPV6
 static ssize_t
-qeth_dev_ipato_invert6_show(struct device *dev, char *buf)
+qeth_dev_ipato_invert6_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -1215,7 +1215,7 @@
 }
 
 static ssize_t
-qeth_dev_ipato_invert6_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_ipato_invert6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 	char *tmp;
@@ -1247,7 +1247,7 @@
 
 
 static ssize_t
-qeth_dev_ipato_add6_show(struct device *dev, char *buf)
+qeth_dev_ipato_add6_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -1258,7 +1258,7 @@
 }
 
 static ssize_t
-qeth_dev_ipato_add6_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_ipato_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -1273,7 +1273,7 @@
 			qeth_dev_ipato_add6_store);
 
 static ssize_t
-qeth_dev_ipato_del6_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_ipato_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -1341,7 +1341,7 @@
 }
 
 static ssize_t
-qeth_dev_vipa_add4_show(struct device *dev, char *buf)
+qeth_dev_vipa_add4_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -1381,7 +1381,7 @@
 }
 
 static ssize_t
-qeth_dev_vipa_add4_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_vipa_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -1413,7 +1413,7 @@
 }
 
 static ssize_t
-qeth_dev_vipa_del4_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_vipa_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -1428,7 +1428,7 @@
 
 #ifdef CONFIG_QETH_IPV6
 static ssize_t
-qeth_dev_vipa_add6_show(struct device *dev, char *buf)
+qeth_dev_vipa_add6_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -1439,7 +1439,7 @@
 }
 
 static ssize_t
-qeth_dev_vipa_add6_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_vipa_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -1454,7 +1454,7 @@
 			qeth_dev_vipa_add6_store);
 
 static ssize_t
-qeth_dev_vipa_del6_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_vipa_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -1522,7 +1522,7 @@
 }
 
 static ssize_t
-qeth_dev_rxip_add4_show(struct device *dev, char *buf)
+qeth_dev_rxip_add4_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -1562,7 +1562,7 @@
 }
 
 static ssize_t
-qeth_dev_rxip_add4_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_rxip_add4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -1594,7 +1594,7 @@
 }
 
 static ssize_t
-qeth_dev_rxip_del4_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_rxip_del4_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -1609,7 +1609,7 @@
 
 #ifdef CONFIG_QETH_IPV6
 static ssize_t
-qeth_dev_rxip_add6_show(struct device *dev, char *buf)
+qeth_dev_rxip_add6_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -1620,7 +1620,7 @@
 }
 
 static ssize_t
-qeth_dev_rxip_add6_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_rxip_add6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 
@@ -1635,7 +1635,7 @@
 			qeth_dev_rxip_add6_store);
 
 static ssize_t
-qeth_dev_rxip_del6_store(struct device *dev, const char *buf, size_t count)
+qeth_dev_rxip_del6_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct qeth_card *card = dev->driver_data;
 
diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c
index 1e3f7f3..d6469ba 100644
--- a/drivers/s390/net/smsgiucv.c
+++ b/drivers/s390/net/smsgiucv.c
@@ -138,7 +138,7 @@
 smsg_exit(void)
 {
 	if (smsg_handle > 0) {
-		cpcmd("SET SMSG OFF", 0, 0);
+		cpcmd("SET SMSG OFF", NULL, 0, NULL);
 		iucv_sever(smsg_pathid, 0);
 		iucv_unregister_program(smsg_handle);
 		driver_unregister(&smsg_driver);
@@ -177,7 +177,7 @@
 		smsg_handle = 0;
 		return -EIO;
 	}
-	cpcmd("SET SMSG IUCV", 0, 0);
+	cpcmd("SET SMSG IUCV", NULL, 0, NULL);
 	return 0;
 }
 
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index ffa996c..5bb255e 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -31,14 +31,14 @@
 extern struct workqueue_struct *slow_path_wq;
 extern struct work_struct slow_path_work;
 
-static void
+static NORET_TYPE void
 s390_handle_damage(char *msg)
 {
-	printk(KERN_EMERG "%s\n", msg);
 #ifdef CONFIG_SMP
 	smp_send_stop();
 #endif
 	disabled_wait((unsigned long) __builtin_return_address(0));
+	for(;;);
 }
 
 /*
@@ -122,40 +122,39 @@
 	return 0;
 }
 
+struct mcck_struct {
+	int kill_task;
+	int channel_report;
+	int warning;
+	unsigned long long mcck_code;
+};
+
+static DEFINE_PER_CPU(struct mcck_struct, cpu_mcck);
+
 /*
- * machine check handler.
+ * Main machine check handler function. Will be called with interrupts enabled
+ * or disabled and machine checks enabled or disabled.
  */
 void
-s390_do_machine_check(void)
+s390_handle_mcck(void)
 {
-	struct mci *mci;
+	unsigned long flags;
+	struct mcck_struct mcck;
 
-	mci = (struct mci *) &S390_lowcore.mcck_interruption_code;
+	/*
+	 * Disable machine checks and get the current state of accumulated
+	 * machine checks. Afterwards delete the old state and enable machine
+	 * checks again.
+	 */
+	local_irq_save(flags);
+	local_mcck_disable();
+	mcck = __get_cpu_var(cpu_mcck);
+	memset(&__get_cpu_var(cpu_mcck), 0, sizeof(struct mcck_struct));
+	clear_thread_flag(TIF_MCCK_PENDING);
+	local_mcck_enable();
+	local_irq_restore(flags);
 
-	if (mci->sd)		/* system damage */
-		s390_handle_damage("received system damage machine check\n");
-
-	if (mci->pd)		/* instruction processing damage */
-		s390_handle_damage("received instruction processing "
-				   "damage machine check\n");
-
-	if (mci->se)		/* storage error uncorrected */
-		s390_handle_damage("received storage error uncorrected "
-				   "machine check\n");
-
-	if (mci->sc)		/* storage error corrected */
-		printk(KERN_WARNING
-		       "received storage error corrected machine check\n");
-
-	if (mci->ke)		/* storage key-error uncorrected */
-		s390_handle_damage("received storage key-error uncorrected "
-				   "machine check\n");
-
-	if (mci->ds && mci->fa)	/* storage degradation */
-		s390_handle_damage("received storage degradation machine "
-				   "check\n");
-
-	if (mci->cp)		/* channel report word pending */
+	if (mcck.channel_report)
 		up(&m_sem);
 
 #ifdef CONFIG_MACHCHK_WARNING
@@ -168,7 +167,7 @@
  * On VM we only get one interrupt per virtally presented machinecheck.
  * Though one suffices, we may get one interrupt per (virtual) processor.
  */
-	if (mci->w) {	/* WARNING pending ? */
+	if (mcck.warning) {	/* WARNING pending ? */
 		static int mchchk_wng_posted = 0;
 		/*
 		 * Use single machine clear, as we cannot handle smp right now
@@ -178,6 +177,261 @@
 			kill_proc(1, SIGPWR, 1);
 	}
 #endif
+
+	if (mcck.kill_task) {
+		local_irq_enable();
+		printk(KERN_EMERG "mcck: Terminating task because of machine "
+		       "malfunction (code 0x%016llx).\n", mcck.mcck_code);
+		printk(KERN_EMERG "mcck: task: %s, pid: %d.\n",
+		       current->comm, current->pid);
+		do_exit(SIGSEGV);
+	}
+}
+
+/*
+ * returns 0 if all registers could be validated
+ * returns 1 otherwise
+ */
+static int
+s390_revalidate_registers(struct mci *mci)
+{
+	int kill_task;
+	u64 tmpclock;
+	u64 zero;
+	void *fpt_save_area, *fpt_creg_save_area;
+
+	kill_task = 0;
+	zero = 0;
+	/* General purpose registers */
+	if (!mci->gr)
+		/*
+		 * General purpose registers couldn't be restored and have
+		 * unknown contents. Process needs to be terminated.
+		 */
+		kill_task = 1;
+
+	/* Revalidate floating point registers */
+	if (!mci->fp)
+		/*
+		 * Floating point registers can't be restored and
+		 * therefore the process needs to be terminated.
+		 */
+		kill_task = 1;
+
+#ifndef __s390x__
+	asm volatile("ld 0,0(%0)\n"
+		     "ld 2,8(%0)\n"
+		     "ld 4,16(%0)\n"
+		     "ld 6,24(%0)"
+		     : : "a" (&S390_lowcore.floating_pt_save_area));
+#endif
+
+	if (MACHINE_HAS_IEEE) {
+#ifdef __s390x__
+		fpt_save_area = &S390_lowcore.floating_pt_save_area;
+		fpt_creg_save_area = &S390_lowcore.fpt_creg_save_area;
+#else
+		fpt_save_area = (void *) S390_lowcore.extended_save_area_addr;
+		fpt_creg_save_area = fpt_save_area+128;
+#endif
+		/* Floating point control register */
+		if (!mci->fc) {
+			/*
+			 * Floating point control register can't be restored.
+			 * Task will be terminated.
+			 */
+			asm volatile ("lfpc 0(%0)" : : "a" (&zero));
+			kill_task = 1;
+
+		}
+		else
+			asm volatile (
+				"lfpc 0(%0)"
+				: : "a" (fpt_creg_save_area));
+
+		asm volatile("ld  0,0(%0)\n"
+			     "ld  1,8(%0)\n"
+			     "ld  2,16(%0)\n"
+			     "ld  3,24(%0)\n"
+			     "ld  4,32(%0)\n"
+			     "ld  5,40(%0)\n"
+			     "ld  6,48(%0)\n"
+			     "ld  7,56(%0)\n"
+			     "ld  8,64(%0)\n"
+			     "ld  9,72(%0)\n"
+			     "ld 10,80(%0)\n"
+			     "ld 11,88(%0)\n"
+			     "ld 12,96(%0)\n"
+			     "ld 13,104(%0)\n"
+			     "ld 14,112(%0)\n"
+			     "ld 15,120(%0)\n"
+			     : : "a" (fpt_save_area));
+	}
+
+	/* Revalidate access registers */
+	asm volatile("lam 0,15,0(%0)"
+		     : : "a" (&S390_lowcore.access_regs_save_area));
+	if (!mci->ar)
+		/*
+		 * Access registers have unknown contents.
+		 * Terminating task.
+		 */
+		kill_task = 1;
+
+	/* Revalidate control registers */
+	if (!mci->cr)
+		/*
+		 * Control registers have unknown contents.
+		 * Can't recover and therefore stopping machine.
+		 */
+		s390_handle_damage("invalid control registers.");
+	else
+#ifdef __s390x__
+		asm volatile("lctlg 0,15,0(%0)"
+			     : : "a" (&S390_lowcore.cregs_save_area));
+#else
+		asm volatile("lctl 0,15,0(%0)"
+			     : : "a" (&S390_lowcore.cregs_save_area));
+#endif
+
+	/*
+	 * We don't even try to revalidate the TOD register, since we simply
+	 * can't write something sensible into that register.
+	 */
+
+#ifdef __s390x__
+	/*
+	 * See if we can revalidate the TOD programmable register with its
+	 * old contents (should be zero) otherwise set it to zero.
+	 */
+	if (!mci->pr)
+		asm volatile("sr 0,0\n"
+			     "sckpf"
+			     : : : "0", "cc");
+	else
+		asm volatile(
+			"l 0,0(%0)\n"
+			"sckpf"
+			: : "a" (&S390_lowcore.tod_progreg_save_area) : "0", "cc");
+#endif
+
+	/* Revalidate clock comparator register */
+	asm volatile ("stck 0(%1)\n"
+		      "sckc 0(%1)"
+		      : "=m" (tmpclock) : "a" (&(tmpclock)) : "cc", "memory");
+
+	/* Check if old PSW is valid */
+	if (!mci->wp)
+		/*
+		 * Can't tell if we come from user or kernel mode
+		 * -> stopping machine.
+		 */
+		s390_handle_damage("old psw invalid.");
+
+	if (!mci->ms || !mci->pm || !mci->ia)
+		kill_task = 1;
+
+	return kill_task;
+}
+
+/*
+ * machine check handler.
+ */
+void
+s390_do_machine_check(struct pt_regs *regs)
+{
+	struct mci *mci;
+	struct mcck_struct *mcck;
+	int umode;
+
+	mci = (struct mci *) &S390_lowcore.mcck_interruption_code;
+	mcck = &__get_cpu_var(cpu_mcck);
+	umode = user_mode(regs);
+
+	if (mci->sd)
+		/* System damage -> stopping machine */
+		s390_handle_damage("received system damage machine check.");
+
+	if (mci->pd) {
+		if (mci->b) {
+			/* Processing backup -> verify if we can survive this */
+			u64 z_mcic, o_mcic, t_mcic;
+#ifdef __s390x__
+			z_mcic = (1ULL<<63 | 1ULL<<59 | 1ULL<<29);
+			o_mcic = (1ULL<<43 | 1ULL<<42 | 1ULL<<41 | 1ULL<<40 |
+				  1ULL<<36 | 1ULL<<35 | 1ULL<<34 | 1ULL<<32 |
+				  1ULL<<30 | 1ULL<<21 | 1ULL<<20 | 1ULL<<17 |
+				  1ULL<<16);
+#else
+			z_mcic = (1ULL<<63 | 1ULL<<59 | 1ULL<<57 | 1ULL<<50 |
+				  1ULL<<29);
+			o_mcic = (1ULL<<43 | 1ULL<<42 | 1ULL<<41 | 1ULL<<40 |
+				  1ULL<<36 | 1ULL<<35 | 1ULL<<34 | 1ULL<<32 |
+				  1ULL<<30 | 1ULL<<20 | 1ULL<<17 | 1ULL<<16);
+#endif
+			t_mcic = *(u64 *)mci;
+
+			if (((t_mcic & z_mcic) != 0) ||
+			    ((t_mcic & o_mcic) != o_mcic)) {
+				s390_handle_damage("processing backup machine "
+						   "check with damage.");
+			}
+			if (!umode)
+				s390_handle_damage("processing backup machine "
+						   "check in kernel mode.");
+			mcck->kill_task = 1;
+			mcck->mcck_code = *(unsigned long long *) mci;
+		}
+		else {
+			/* Processing damage -> stopping machine */
+			s390_handle_damage("received instruction processing "
+					   "damage machine check.");
+		}
+	}
+	if (s390_revalidate_registers(mci)) {
+		if (umode) {
+			/*
+			 * Couldn't restore all register contents while in
+			 * user mode -> mark task for termination.
+			 */
+			mcck->kill_task = 1;
+			mcck->mcck_code = *(unsigned long long *) mci;
+			set_thread_flag(TIF_MCCK_PENDING);
+		}
+		else
+			/*
+			 * Couldn't restore all register contents while in
+			 * kernel mode -> stopping machine.
+			 */
+			s390_handle_damage("unable to revalidate registers.");
+	}
+
+	if (mci->se)
+		/* Storage error uncorrected */
+		s390_handle_damage("received storage error uncorrected "
+				   "machine check.");
+
+	if (mci->ke)
+		/* Storage key-error uncorrected */
+		s390_handle_damage("received storage key-error uncorrected "
+				   "machine check.");
+
+	if (mci->ds && mci->fa)
+		/* Storage degradation */
+		s390_handle_damage("received storage degradation machine "
+				   "check.");
+
+	if (mci->cp) {
+		/* Channel report word pending */
+		mcck->channel_report = 1;
+		set_thread_flag(TIF_MCCK_PENDING);
+	}
+
+	if (mci->w) {
+		/* Warning pending */
+		mcck->warning = 1;
+		set_thread_flag(TIF_MCCK_PENDING);
+	}
 }
 
 /*
@@ -189,9 +443,8 @@
 machine_check_init(void)
 {
 	init_MUTEX_LOCKED(&m_sem);
-	ctl_clear_bit(14, 25);	/* disable damage MCH */
-	ctl_set_bit(14, 26);	/* enable degradation MCH */
-	ctl_set_bit(14, 27);	/* enable system recovery MCH */
+	ctl_clear_bit(14, 25);	/* disable external damage MCH */
+	ctl_set_bit(14, 27);    /* enable system recovery MCH */
 #ifdef CONFIG_MACHCHK_WARNING
 	ctl_set_bit(14, 24);	/* enable warning MCH */
 #endif
diff --git a/drivers/s390/s390mach.h b/drivers/s390/s390mach.h
index 7e26f0f..4eaa701 100644
--- a/drivers/s390/s390mach.h
+++ b/drivers/s390/s390mach.h
@@ -16,20 +16,45 @@
 	__u32   sd              :  1; /* 00 system damage */
 	__u32   pd              :  1; /* 01 instruction-processing damage */
 	__u32   sr              :  1; /* 02 system recovery */
-	__u32   to_be_defined_1 :  4; /* 03-06 */
+	__u32   to_be_defined_1 :  1; /* 03 */
+	__u32   cd              :  1; /* 04 timing-facility damage */
+	__u32   ed              :  1; /* 05 external damage */
+	__u32   to_be_defined_2 :  1; /* 06 */
 	__u32   dg              :  1; /* 07 degradation */
 	__u32   w               :  1; /* 08 warning pending */
 	__u32   cp              :  1; /* 09 channel-report pending */
-	__u32   to_be_defined_2 :  6; /* 10-15 */
+	__u32   sp              :  1; /* 10 service-processor damage */
+	__u32   ck              :  1; /* 11 channel-subsystem damage */
+	__u32   to_be_defined_3 :  2; /* 12-13 */
+	__u32   b               :  1; /* 14 backed up */
+	__u32   to_be_defined_4 :  1; /* 15 */
 	__u32   se              :  1; /* 16 storage error uncorrected */
 	__u32   sc              :  1; /* 17 storage error corrected */
 	__u32   ke              :  1; /* 18 storage-key error uncorrected */
 	__u32   ds              :  1; /* 19 storage degradation */
-	__u32	to_be_defined_3 :  4; /* 20-23 */
+	__u32   wp              :  1; /* 20 psw mwp validity */
+	__u32   ms              :  1; /* 21 psw mask and key validity */
+	__u32   pm              :  1; /* 22 psw program mask and cc validity */
+	__u32   ia              :  1; /* 23 psw instruction address validity */
 	__u32   fa              :  1; /* 24 failing storage address validity */
-	__u32   to_be_defined_4 :  7; /* 25-31 */
+	__u32   to_be_defined_5 :  1; /* 25 */
+	__u32   ec              :  1; /* 26 external damage code validity */
+	__u32   fp              :  1; /* 27 floating point register validity */
+	__u32   gr              :  1; /* 28 general register validity */
+	__u32   cr              :  1; /* 29 control register validity */
+	__u32   to_be_defined_6 :  1; /* 30 */
+	__u32   st              :  1; /* 31 storage logical validity */
 	__u32   ie              :  1; /* 32 indirect storage error */
-	__u32	to_be_defined_5 : 31; /* 33-63 */
+	__u32   ar              :  1; /* 33 access register validity */
+	__u32   da              :  1; /* 34 delayed access exception */
+	__u32   to_be_defined_7 :  7; /* 35-41 */
+	__u32   pr              :  1; /* 42 tod programmable register validity */
+	__u32   fc              :  1; /* 43 fp control register validity */
+	__u32   ap              :  1; /* 44 ancillary report */
+	__u32   to_be_defined_8 :  1; /* 45 */
+	__u32   ct              :  1; /* 46 cpu timer validity */
+	__u32   cc              :  1; /* 47 clock comparator validity */
+	__u32	to_be_defined_9 : 16; /* 47-63 */
 };
 
 /*
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 68d151a..e17b4d5 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -97,11 +97,6 @@
 		 "FC ERP QDIO CIO Config FSF SCSI Other, "
 		 "levels: 0=none 1=normal 2=devel 3=trace");
 
-#ifdef ZFCP_PRINT_FLAGS
-u32 flags_dump = 0;
-module_param(flags_dump, uint, 0);
-#endif
-
 /****************************************************************/
 /************** Functions without logging ***********************/
 /****************************************************************/
@@ -223,13 +218,20 @@
  * Parse "device=..." parameter string.
  */
 static int __init
-zfcp_device_setup(char *str)
+zfcp_device_setup(char *devstr)
 {
-	char *tmp;
+	char *tmp, *str;
+	size_t len;
 
-	if (!str)
+	if (!devstr)
 		return 0;
 
+	len = strlen(devstr) + 1;
+	str = (char *) kmalloc(len, GFP_KERNEL);
+	if (!str)
+		goto err_out;
+	memcpy(str, devstr, len);
+
 	tmp = strchr(str, ',');
 	if (!tmp)
 		goto err_out;
@@ -246,10 +248,12 @@
 	zfcp_data.init_fcp_lun = simple_strtoull(tmp, &tmp, 0);
 	if (*tmp != '\0')
 		goto err_out;
+	kfree(str);
 	return 1;
 
  err_out:
 	ZFCP_LOG_NORMAL("Parse error for device parameter string %s\n", str);
+	kfree(str);
 	return 0;
 }
 
@@ -525,7 +529,7 @@
 
  out:
 	if (fsf_req != NULL)
-		zfcp_fsf_req_cleanup(fsf_req);
+		zfcp_fsf_req_free(fsf_req);
 
 	if ((adapter != NULL) && (retval != -ENXIO))
 		zfcp_adapter_put(adapter);
@@ -1154,7 +1158,7 @@
 	INIT_LIST_HEAD(&adapter->port_remove_lh);
 
 	/* initialize list of fsf requests */
-	rwlock_init(&adapter->fsf_req_list_lock);
+	spin_lock_init(&adapter->fsf_req_list_lock);
 	INIT_LIST_HEAD(&adapter->fsf_req_list_head);
 
 	/* initialize abort lock */
@@ -1239,9 +1243,9 @@
 	zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);
 	dev_set_drvdata(&adapter->ccw_device->dev, NULL);
 	/* sanity check: no pending FSF requests */
-	read_lock_irqsave(&adapter->fsf_req_list_lock, flags);
+	spin_lock_irqsave(&adapter->fsf_req_list_lock, flags);
 	retval = !list_empty(&adapter->fsf_req_list_head);
-	read_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
+	spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
 	if (retval) {
 		ZFCP_LOG_NORMAL("bug: adapter %s (%p) still in use, "
 				"%i requests outstanding\n",
@@ -1483,19 +1487,15 @@
 		fcp_rscn_element++;
 		switch (fcp_rscn_element->addr_format) {
 		case ZFCP_PORT_ADDRESS:
-			ZFCP_LOG_FLAGS(1, "ZFCP_PORT_ADDRESS\n");
 			range_mask = ZFCP_PORTS_RANGE_PORT;
 			break;
 		case ZFCP_AREA_ADDRESS:
-			ZFCP_LOG_FLAGS(1, "ZFCP_AREA_ADDRESS\n");
 			range_mask = ZFCP_PORTS_RANGE_AREA;
 			break;
 		case ZFCP_DOMAIN_ADDRESS:
-			ZFCP_LOG_FLAGS(1, "ZFCP_DOMAIN_ADDRESS\n");
 			range_mask = ZFCP_PORTS_RANGE_DOMAIN;
 			break;
 		case ZFCP_FABRIC_ADDRESS:
-			ZFCP_LOG_FLAGS(1, "ZFCP_FABRIC_ADDRESS\n");
 			range_mask = ZFCP_PORTS_RANGE_FABRIC;
 			break;
 		default:
@@ -1762,7 +1762,10 @@
 	ct_iu_req = zfcp_sg_to_address(ct->req);
 	ct_iu_resp = zfcp_sg_to_address(ct->resp);
 
-	if ((ct->status != 0) || zfcp_check_ct_response(&ct_iu_resp->header)) {
+	if (ct->status != 0)
+		goto failed;
+
+	if (zfcp_check_ct_response(&ct_iu_resp->header)) {
 		/* FIXME: do we need some specific erp entry points */
 		atomic_set_mask(ZFCP_STATUS_PORT_INVALID_WWPN, &port->status);
 		goto failed;
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index c5daf37..4103b5b 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -62,9 +62,6 @@
 #include <linux/syscalls.h>
 #include <linux/ioctl.h>
 
-/************************ DEBUG FLAGS *****************************************/
-
-#define	ZFCP_PRINT_FLAGS
 
 /********************* GENERAL DEFINES *********************************/
 
@@ -152,8 +149,10 @@
 #define FSF_QTCB_UNSOLICITED_STATUS		0x6305
 #define ZFCP_STATUS_READ_FAILED_THRESHOLD	3
 #define ZFCP_STATUS_READS_RECOM		        FSF_STATUS_READS_RECOM
-#define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES	6
-#define ZFCP_EXCHANGE_CONFIG_DATA_SLEEP		50
+
+/* Do 1st retry in 1 second, then double the timeout for each following retry */
+#define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP	100
+#define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES	7
 
 /* timeout value for "default timer" for fsf requests */
 #define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ);
@@ -472,17 +471,6 @@
 	ZFCP_LOG(ZFCP_LOG_LEVEL_TRACE, fmt , ##args)
 #endif
 
-#ifndef ZFCP_PRINT_FLAGS
-# define ZFCP_LOG_FLAGS(level, fmt, args...)
-#else
-extern u32 flags_dump;
-# define ZFCP_LOG_FLAGS(level, fmt, args...) \
-do { \
-	if (level <= flags_dump) \
-		_ZFCP_LOG(fmt, ##args); \
-} while (0)
-#endif
-
 /*************** ADAPTER/PORT/UNIT AND FSF_REQ STATUS FLAGS ******************/
 
 /* 
@@ -502,6 +490,7 @@
 #define ZFCP_STATUS_COMMON_CLOSING              0x02000000
 #define ZFCP_STATUS_COMMON_ERP_INUSE		0x01000000
 #define ZFCP_STATUS_COMMON_ACCESS_DENIED	0x00800000
+#define ZFCP_STATUS_COMMON_ACCESS_BOXED		0x00400000
 
 /* adapter status */
 #define ZFCP_STATUS_ADAPTER_QDIOUP		0x00000002
@@ -763,6 +752,7 @@
 /**
  * struct zfcp_send_els - used to pass parameters to function zfcp_fsf_send_els
  * @adapter: adapter where request is sent from
+ * @port: port where ELS is destinated (port reference count has to be increased)
  * @d_id: destiniation id of port where request is sent to
  * @req: scatter-gather list for request
  * @resp: scatter-gather list for response
@@ -777,6 +767,7 @@
  */
 struct zfcp_send_els {
 	struct zfcp_adapter *adapter;
+	struct zfcp_port *port;
 	fc_id_t d_id;
 	struct scatterlist *req;
 	struct scatterlist *resp;
@@ -871,7 +862,7 @@
 	u32			ports;	           /* number of remote ports */
         struct timer_list       scsi_er_timer;     /* SCSI err recovery watch */
 	struct list_head	fsf_req_list_head; /* head of FSF req list */
-	rwlock_t		fsf_req_list_lock; /* lock for ops on list of
+	spinlock_t		fsf_req_list_lock; /* lock for ops on list of
 						      FSF requests */
         atomic_t       		fsf_reqs_active;   /* # active FSF reqs */
 	struct zfcp_qdio_queue	request_queue;	   /* request queue */
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 53ebc1cd..0cf31f7 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -35,7 +35,7 @@
 
 #include "zfcp_ext.h"
 
-static int zfcp_erp_adisc(struct zfcp_adapter *, fc_id_t);
+static int zfcp_erp_adisc(struct zfcp_port *);
 static void zfcp_erp_adisc_handler(unsigned long);
 
 static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int);
@@ -295,12 +295,12 @@
 
 /**
  * zfcp_erp_adisc - send ADISC ELS command
- * @adapter: adapter structure
- * @d_id: d_id of port where ADISC is sent to
+ * @port: port structure
  */
 int
-zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id)
+zfcp_erp_adisc(struct zfcp_port *port)
 {
+	struct zfcp_adapter *adapter = port->adapter;
 	struct zfcp_send_els *send_els;
 	struct zfcp_ls_adisc *adisc;
 	void *address = NULL;
@@ -332,7 +332,8 @@
 	send_els->req_count = send_els->resp_count = 1;
 
 	send_els->adapter = adapter;
-	send_els->d_id = d_id;
+	send_els->port = port;
+	send_els->d_id = port->d_id;
 	send_els->handler = zfcp_erp_adisc_handler;
 	send_els->handler_data = (unsigned long) send_els;
 
@@ -350,7 +351,7 @@
 	ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x "
 		      "(wwpn=0x%016Lx, wwnn=0x%016Lx, "
 		      "hard_nport_id=0x%08x, nport_id=0x%08x)\n",
-		      adapter->s_id, d_id, (wwn_t) adisc->wwpn,
+		      adapter->s_id, send_els->d_id, (wwn_t) adisc->wwpn,
 		      (wwn_t) adisc->wwnn, adisc->hard_nport_id,
 		      adisc->nport_id);
 
@@ -367,7 +368,7 @@
 	retval = zfcp_fsf_send_els(send_els);
 	if (retval != 0) {
 		ZFCP_LOG_NORMAL("error: initiation of Send ELS failed for port "
-				"0x%08x on adapter %s\n", d_id,
+				"0x%08x on adapter %s\n", send_els->d_id,
 				zfcp_get_busid_by_adapter(adapter));
 		del_timer(send_els->timer);
 		goto freemem;
@@ -411,14 +412,9 @@
 	del_timer(send_els->timer);
 
 	adapter = send_els->adapter;
+	port = send_els->port;
 	d_id = send_els->d_id;
 
-	read_lock(&zfcp_data.config_lock);
-	port = zfcp_get_port_by_did(send_els->adapter, send_els->d_id);
-	read_unlock(&zfcp_data.config_lock);
-
-	BUG_ON(port == NULL);
-
 	/* request rejected or timed out */
 	if (send_els->status != 0) {
 		ZFCP_LOG_NORMAL("ELS request rejected/timed out, "
@@ -482,7 +478,7 @@
 	int retval;
 
 	zfcp_port_get(port);
-	retval = zfcp_erp_adisc(port->adapter, port->d_id);
+	retval = zfcp_erp_adisc(port);
 	if (retval != 0) {
 		zfcp_port_put(port);
 		ZFCP_LOG_NORMAL("reopen needed for port 0x%016Lx "
@@ -895,7 +891,7 @@
 
 	if (erp_action->fsf_req) {
 		/* take lock to ensure that request is not being deleted meanwhile */
-		write_lock(&adapter->fsf_req_list_lock);
+		spin_lock(&adapter->fsf_req_list_lock);
 		/* check whether fsf req does still exist */
 		list_for_each_entry(fsf_req, &adapter->fsf_req_list_head, list)
 		    if (fsf_req == erp_action->fsf_req)
@@ -938,7 +934,7 @@
 			 */
 			erp_action->fsf_req = NULL;
 		}
-		write_unlock(&adapter->fsf_req_list_lock);
+		spin_unlock(&adapter->fsf_req_list_lock);
 	} else
 		debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq");
 
@@ -2286,12 +2282,12 @@
 {
 	int retval = ZFCP_ERP_SUCCEEDED;
 	int retries;
+	int sleep = ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP;
 	struct zfcp_adapter *adapter = erp_action->adapter;
 
 	atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status);
-	retries = ZFCP_EXCHANGE_CONFIG_DATA_RETRIES;
 
-	do {
+	for (retries = ZFCP_EXCHANGE_CONFIG_DATA_RETRIES; retries; retries--) {
 		atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
 				  &adapter->status);
 		ZFCP_LOG_DEBUG("Doing exchange config data\n");
@@ -2329,16 +2325,17 @@
 				      zfcp_get_busid_by_adapter(adapter));
 			break;
 		}
-		if (atomic_test_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
-				     &adapter->status)) {
-			ZFCP_LOG_DEBUG("host connection still initialising... "
-				       "waiting and retrying...\n");
-			/* sleep a little bit before retry */
-			msleep(jiffies_to_msecs(ZFCP_EXCHANGE_CONFIG_DATA_SLEEP));
-		}
-	} while ((retries--) &&
-		 atomic_test_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
-				  &adapter->status));
+
+		if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
+				     &adapter->status))
+			break;
+
+		ZFCP_LOG_DEBUG("host connection still initialising... "
+			       "waiting and retrying...\n");
+		/* sleep a little bit before retry */
+		msleep(jiffies_to_msecs(sleep));
+		sleep *= 2;
+	}
 
 	if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
 			      &adapter->status)) {
@@ -3485,6 +3482,45 @@
 }
 
 /*
+ * function:	zfcp_erp_port_boxed
+ *
+ * purpose:
+ */
+void
+zfcp_erp_port_boxed(struct zfcp_port *port)
+{
+	struct zfcp_adapter *adapter = port->adapter;
+	unsigned long flags;
+
+	debug_text_event(adapter->erp_dbf, 3, "p_access_boxed");
+	debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t));
+	read_lock_irqsave(&zfcp_data.config_lock, flags);
+	zfcp_erp_modify_port_status(port,
+			ZFCP_STATUS_COMMON_ACCESS_BOXED,
+			ZFCP_SET);
+	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+	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)
+{
+	struct zfcp_adapter *adapter = unit->port->adapter;
+
+	debug_text_event(adapter->erp_dbf, 3, "u_access_boxed");
+	debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t));
+	zfcp_erp_modify_unit_status(unit,
+			ZFCP_STATUS_COMMON_ACCESS_BOXED,
+			ZFCP_SET);
+	zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED);
+}
+
+/*
  * function:	zfcp_erp_port_access_denied
  *
  * purpose:
@@ -3495,11 +3531,13 @@
 	struct zfcp_adapter *adapter = port->adapter;
 	unsigned long flags;
 
-	debug_text_event(adapter->erp_dbf, 3, "p_access_block");
+	debug_text_event(adapter->erp_dbf, 3, "p_access_denied");
 	debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t));
 	read_lock_irqsave(&zfcp_data.config_lock, flags);
-	zfcp_erp_modify_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED |
-				    ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
+	zfcp_erp_modify_port_status(port,
+			ZFCP_STATUS_COMMON_ERP_FAILED |
+			ZFCP_STATUS_COMMON_ACCESS_DENIED,
+			ZFCP_SET);
 	read_unlock_irqrestore(&zfcp_data.config_lock, flags);
 }
 
@@ -3513,10 +3551,12 @@
 {
 	struct zfcp_adapter *adapter = unit->port->adapter;
 
-	debug_text_event(adapter->erp_dbf, 3, "u_access_block");
+	debug_text_event(adapter->erp_dbf, 3, "u_access_denied");
 	debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t));
-	zfcp_erp_modify_unit_status(unit, ZFCP_STATUS_COMMON_ERP_FAILED |
-				    ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
+	zfcp_erp_modify_unit_status(unit,
+			ZFCP_STATUS_COMMON_ERP_FAILED |
+			ZFCP_STATUS_COMMON_ACCESS_DENIED,
+			ZFCP_SET);
 }
 
 /*
@@ -3530,7 +3570,7 @@
 	struct zfcp_port *port;
 	unsigned long flags;
 
-	debug_text_event(adapter->erp_dbf, 3, "a_access_unblock");
+	debug_text_event(adapter->erp_dbf, 3, "a_access_recover");
 	debug_event(adapter->erp_dbf, 3, &adapter->name, 8);
 
 	read_lock_irqsave(&zfcp_data.config_lock, flags);
@@ -3553,10 +3593,12 @@
 	struct zfcp_adapter *adapter = port->adapter;
 	struct zfcp_unit *unit;
 
-	debug_text_event(adapter->erp_dbf, 3, "p_access_unblock");
+	debug_text_event(adapter->erp_dbf, 3, "p_access_recover");
 	debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t));
 
 	if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED,
+			      &port->status) &&
+	    !atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED,
 			      &port->status)) {
 		if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))
 			list_for_each_entry(unit, &port->unit_list_head, list)
@@ -3583,10 +3625,13 @@
 {
 	struct zfcp_adapter *adapter = unit->port->adapter;
 
-	debug_text_event(adapter->erp_dbf, 3, "u_access_unblock");
+	debug_text_event(adapter->erp_dbf, 3, "u_access_recover");
 	debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t));
 
-	if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, &unit->status))
+	if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED,
+			      &unit->status) &&
+	    !atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED,
+			      &unit->status))
 		return;
 
 	ZFCP_LOG_NORMAL("reopen of unit 0x%016Lx on port 0x%016Lx "
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index d5fd433..42df7e5 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -116,7 +116,7 @@
 					   struct timer_list*, int);
 extern int  zfcp_fsf_req_complete(struct zfcp_fsf_req *);
 extern void zfcp_fsf_incoming_els(struct zfcp_fsf_req *);
-extern void zfcp_fsf_req_cleanup(struct zfcp_fsf_req *);
+extern void zfcp_fsf_req_free(struct zfcp_fsf_req *);
 extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_command_task_management(
 	struct zfcp_adapter *, struct zfcp_unit *, u8, int);
 extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(
@@ -171,6 +171,8 @@
 
 extern int  zfcp_test_link(struct zfcp_port *);
 
+extern void zfcp_erp_port_boxed(struct zfcp_port *);
+extern void zfcp_erp_unit_boxed(struct zfcp_unit *);
 extern void zfcp_erp_port_access_denied(struct zfcp_port *);
 extern void zfcp_erp_unit_access_denied(struct zfcp_unit *);
 extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *);
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 148b11c..0d9f20e 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -61,7 +61,6 @@
 static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *);
 static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *);
 static void zfcp_fsf_req_dismiss(struct zfcp_fsf_req *);
-static void zfcp_fsf_req_free(struct zfcp_fsf_req *);
 
 /* association between FSF command and FSF QTCB type */
 static u32 fsf_qtcb_type[] = {
@@ -149,13 +148,13 @@
  *
  * locks:       none
  */
-static void
+void
 zfcp_fsf_req_free(struct zfcp_fsf_req *fsf_req)
 {
 	if (likely(fsf_req->pool != NULL))
 		mempool_free(fsf_req, fsf_req->pool);
-		else
-			kfree(fsf_req);
+	else
+		kfree(fsf_req);
 }
 
 /*
@@ -170,30 +169,21 @@
 int
 zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
 {
-	int retval = 0;
 	struct zfcp_fsf_req *fsf_req, *tmp;
+	unsigned long flags;
+	LIST_HEAD(remove_queue);
 
-	list_for_each_entry_safe(fsf_req, tmp, &adapter->fsf_req_list_head,
-				 list)
-	    zfcp_fsf_req_dismiss(fsf_req);
-	/* wait_event_timeout? */
-	while (!list_empty(&adapter->fsf_req_list_head)) {
-		ZFCP_LOG_DEBUG("fsf req list of adapter %s not yet empty\n",
-			       zfcp_get_busid_by_adapter(adapter));
-		/* wait for woken intiators to clean up their requests */
-		msleep(jiffies_to_msecs(ZFCP_FSFREQ_CLEANUP_TIMEOUT));
+	spin_lock_irqsave(&adapter->fsf_req_list_lock, flags);
+	list_splice_init(&adapter->fsf_req_list_head, &remove_queue);
+	atomic_set(&adapter->fsf_reqs_active, 0);
+	spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
+
+	list_for_each_entry_safe(fsf_req, tmp, &remove_queue, list) {
+		list_del(&fsf_req->list);
+		zfcp_fsf_req_dismiss(fsf_req);
 	}
 
-	/* consistency check */
-	if (atomic_read(&adapter->fsf_reqs_active)) {
-		ZFCP_LOG_NORMAL("bug: There are still %d FSF requests pending "
-				"on adapter %s after cleanup.\n",
-				atomic_read(&adapter->fsf_reqs_active),
-				zfcp_get_busid_by_adapter(adapter));
-		atomic_set(&adapter->fsf_reqs_active, 0);
-	}
-
-	return retval;
+	return 0;
 }
 
 /*
@@ -226,10 +216,6 @@
 {
 	int retval = 0;
 	int cleanup;
-	struct zfcp_adapter *adapter = fsf_req->adapter;
-
-	/* do some statistics */
-	atomic_dec(&adapter->fsf_reqs_active);
 
 	if (unlikely(fsf_req->fsf_command == FSF_QTCB_UNSOLICITED_STATUS)) {
 		ZFCP_LOG_DEBUG("Status read response received\n");
@@ -260,7 +246,7 @@
 		 * lock must not be held here since it will be
 		 * grabed by the called routine, too
 		 */
-		zfcp_fsf_req_cleanup(fsf_req);
+		zfcp_fsf_req_free(fsf_req);
 	} else {
 		/* notify initiator waiting for the requests completion */
 		ZFCP_LOG_TRACE("waking initiator of FSF request %p\n",fsf_req);
@@ -346,15 +332,10 @@
 	switch (fsf_req->qtcb->prefix.prot_status) {
 
 	case FSF_PROT_GOOD:
-		ZFCP_LOG_TRACE("FSF_PROT_GOOD\n");
-		break;
-
 	case FSF_PROT_FSF_STATUS_PRESENTED:
-		ZFCP_LOG_TRACE("FSF_PROT_FSF_STATUS_PRESENTED\n");
 		break;
 
 	case FSF_PROT_QTCB_VERSION_ERROR:
-		ZFCP_LOG_FLAGS(0, "FSF_PROT_QTCB_VERSION_ERROR\n");
 		ZFCP_LOG_NORMAL("error: The adapter %s contains "
 				"microcode of version 0x%x, the device driver "
 				"only supports 0x%x. Aborting.\n",
@@ -371,7 +352,6 @@
 		break;
 
 	case FSF_PROT_SEQ_NUMB_ERROR:
-		ZFCP_LOG_FLAGS(0, "FSF_PROT_SEQ_NUMB_ERROR\n");
 		ZFCP_LOG_NORMAL("bug: Sequence number mismatch between "
 				"driver (0x%x) and adapter %s (0x%x). "
 				"Restarting all operations on this adapter.\n",
@@ -390,7 +370,6 @@
 		break;
 
 	case FSF_PROT_UNSUPP_QTCB_TYPE:
-		ZFCP_LOG_FLAGS(0, "FSF_PROT_UNSUP_QTCB_TYPE\n");
 		ZFCP_LOG_NORMAL("error: Packet header type used by the "
 				"device driver is incompatible with "
 				"that used on adapter %s. "
@@ -405,7 +384,6 @@
 		break;
 
 	case FSF_PROT_HOST_CONNECTION_INITIALIZING:
-		ZFCP_LOG_FLAGS(1, "FSF_PROT_HOST_CONNECTION_INITIALIZING\n");
 		zfcp_cmd_dbf_event_fsf("hconinit", fsf_req,
 				       &fsf_req->qtcb->prefix.prot_status_qual,
 				       sizeof (union fsf_prot_status_qual));
@@ -416,7 +394,6 @@
 		break;
 
 	case FSF_PROT_DUPLICATE_REQUEST_ID:
-		ZFCP_LOG_FLAGS(0, "FSF_PROT_DUPLICATE_REQUEST_IDS\n");
 		if (fsf_req->qtcb) {
 			ZFCP_LOG_NORMAL("bug: The request identifier 0x%Lx "
 					"to the adapter %s is ambiguous. "
@@ -445,7 +422,6 @@
 		break;
 
 	case FSF_PROT_LINK_DOWN:
-		ZFCP_LOG_FLAGS(1, "FSF_PROT_LINK_DOWN\n");
 		/*
 		 * 'test and set' is not atomic here -
 		 * it's ok as long as calls to our response queue handler
@@ -502,13 +478,11 @@
 					ZFCP_STATUS_COMMON_ERP_FAILED,
 					&adapter->status);
 			zfcp_erp_adapter_reopen(adapter, 0);
-			debug_text_event(adapter->erp_dbf, 1, "prot_link_down");
 		}
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 
 	case FSF_PROT_REEST_QUEUE:
-		ZFCP_LOG_FLAGS(1, "FSF_PROT_REEST_QUEUE\n");
 		debug_text_event(adapter->erp_dbf, 1, "prot_reest_queue");
 		ZFCP_LOG_INFO("The local link to adapter with "
 			      "%s was re-plugged. "
@@ -528,7 +502,6 @@
 		break;
 
 	case FSF_PROT_ERROR_STATE:
-		ZFCP_LOG_FLAGS(0, "FSF_PROT_ERROR_STATE\n");
 		ZFCP_LOG_NORMAL("error: The adapter %s "
 				"has entered the error state. "
 				"Restarting all operations on this "
@@ -589,7 +562,6 @@
 	/* evaluate FSF Status */
 	switch (fsf_req->qtcb->header.fsf_status) {
 	case FSF_UNKNOWN_COMMAND:
-		ZFCP_LOG_FLAGS(0, "FSF_UNKNOWN_COMMAND\n");
 		ZFCP_LOG_NORMAL("bug: Command issued by the device driver is "
 				"not known by the adapter %s "
 				"Stopping all operations on this adapter. "
@@ -606,14 +578,12 @@
 		break;
 
 	case FSF_FCP_RSP_AVAILABLE:
-		ZFCP_LOG_FLAGS(2, "FSF_FCP_RSP_AVAILABLE\n");
 		ZFCP_LOG_DEBUG("FCP Sense data will be presented to the "
 			       "SCSI stack.\n");
 		debug_text_event(fsf_req->adapter->erp_dbf, 3, "fsf_s_rsp");
 		break;
 
 	case FSF_ADAPTER_STATUS_AVAILABLE:
-		ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
 		debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_astatus");
 		zfcp_fsf_fsfstatus_qual_eval(fsf_req);
 		break;
@@ -647,11 +617,9 @@
 
 	switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) {
 	case FSF_SQ_FCP_RSP_AVAILABLE:
-		ZFCP_LOG_FLAGS(2, "FSF_SQ_FCP_RSP_AVAILABLE\n");
 		debug_text_event(fsf_req->adapter->erp_dbf, 4, "fsf_sq_rsp");
 		break;
 	case FSF_SQ_RETRY_IF_POSSIBLE:
-		ZFCP_LOG_FLAGS(2, "FSF_SQ_RETRY_IF_POSSIBLE\n");
 		/* The SCSI-stack may now issue retries or escalate */
 		debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_sq_retry");
 		zfcp_cmd_dbf_event_fsf("sqretry", fsf_req,
@@ -660,7 +628,6 @@
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_SQ_COMMAND_ABORTED:
-		ZFCP_LOG_FLAGS(2, "FSF_SQ_COMMAND_ABORTED\n");
 		/* Carry the aborted state on to upper layer */
 		debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_sq_abort");
 		zfcp_cmd_dbf_event_fsf("sqabort", fsf_req,
@@ -670,7 +637,6 @@
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_SQ_NO_RECOM:
-		ZFCP_LOG_FLAGS(0, "FSF_SQ_NO_RECOM\n");
 		debug_text_exception(fsf_req->adapter->erp_dbf, 0,
 				     "fsf_sq_no_rec");
 		ZFCP_LOG_NORMAL("bug: No recommendation could be given for a"
@@ -684,7 +650,6 @@
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_SQ_ULP_PROGRAMMING_ERROR:
-		ZFCP_LOG_FLAGS(0, "FSF_SQ_ULP_PROGRAMMING_ERROR\n");
 		ZFCP_LOG_NORMAL("error: not enough SBALs for data transfer "
 				"(adapter %s)\n",
 				zfcp_get_busid_by_adapter(fsf_req->adapter));
@@ -740,72 +705,58 @@
 	switch (fsf_req->fsf_command) {
 
 	case FSF_QTCB_FCP_CMND:
-		ZFCP_LOG_FLAGS(3, "FSF_QTCB_FCP_CMND\n");
 		zfcp_fsf_send_fcp_command_handler(fsf_req);
 		break;
 
 	case FSF_QTCB_ABORT_FCP_CMND:
-		ZFCP_LOG_FLAGS(2, "FSF_QTCB_ABORT_FCP_CMND\n");
 		zfcp_fsf_abort_fcp_command_handler(fsf_req);
 		break;
 
 	case FSF_QTCB_SEND_GENERIC:
-		ZFCP_LOG_FLAGS(2, "FSF_QTCB_SEND_GENERIC\n");
 		zfcp_fsf_send_ct_handler(fsf_req);
 		break;
 
 	case FSF_QTCB_OPEN_PORT_WITH_DID:
-		ZFCP_LOG_FLAGS(2, "FSF_QTCB_OPEN_PORT_WITH_DID\n");
 		zfcp_fsf_open_port_handler(fsf_req);
 		break;
 
 	case FSF_QTCB_OPEN_LUN:
-		ZFCP_LOG_FLAGS(2, "FSF_QTCB_OPEN_LUN\n");
 		zfcp_fsf_open_unit_handler(fsf_req);
 		break;
 
 	case FSF_QTCB_CLOSE_LUN:
-		ZFCP_LOG_FLAGS(2, "FSF_QTCB_CLOSE_LUN\n");
 		zfcp_fsf_close_unit_handler(fsf_req);
 		break;
 
 	case FSF_QTCB_CLOSE_PORT:
-		ZFCP_LOG_FLAGS(2, "FSF_QTCB_CLOSE_PORT\n");
 		zfcp_fsf_close_port_handler(fsf_req);
 		break;
 
 	case FSF_QTCB_CLOSE_PHYSICAL_PORT:
-		ZFCP_LOG_FLAGS(2, "FSF_QTCB_CLOSE_PHYSICAL_PORT\n");
 		zfcp_fsf_close_physical_port_handler(fsf_req);
 		break;
 
 	case FSF_QTCB_EXCHANGE_CONFIG_DATA:
-		ZFCP_LOG_FLAGS(2, "FSF_QTCB_EXCHANGE_CONFIG_DATA\n");
 		zfcp_fsf_exchange_config_data_handler(fsf_req);
 		break;
 
 	case FSF_QTCB_EXCHANGE_PORT_DATA:
-		ZFCP_LOG_FLAGS(2, "FSF_QTCB_EXCHANGE_PORT_DATA\n");
 		zfcp_fsf_exchange_port_data_handler(fsf_req);
 		break;
 
 	case FSF_QTCB_SEND_ELS:
-		ZFCP_LOG_FLAGS(2, "FSF_QTCB_SEND_ELS\n");
 		zfcp_fsf_send_els_handler(fsf_req);
 		break;
 
 	case FSF_QTCB_DOWNLOAD_CONTROL_FILE:
-		ZFCP_LOG_FLAGS(2, "FSF_QTCB_DOWNLOAD_CONTROL_FILE\n");
 		zfcp_fsf_control_file_handler(fsf_req);
 		break;
 
 	case FSF_QTCB_UPLOAD_CONTROL_FILE:
-		ZFCP_LOG_FLAGS(2, "FSF_QTCB_UPLOAD_CONTROL_FILE\n");
 		zfcp_fsf_control_file_handler(fsf_req);
 		break;
 
 	default:
-		ZFCP_LOG_FLAGS(2, "FSF_QTCB_UNKNOWN\n");
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		ZFCP_LOG_NORMAL("bug: Command issued by the device driver is "
 				"not supported by the adapter %s\n",
@@ -929,13 +880,11 @@
 	switch (status_buffer->status_subtype) {
 
 	case FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT:
-		ZFCP_LOG_FLAGS(2, "FSF_STATUS_READ_SUB_CLOSE_PHYS_PORT\n");
 		debug_text_event(adapter->erp_dbf, 3, "unsol_pc_phys:");
 		zfcp_erp_port_reopen(port, 0);
 		break;
 
 	case FSF_STATUS_READ_SUB_ERROR_PORT:
-		ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_SUB_ERROR_PORT\n");
 		debug_text_event(adapter->erp_dbf, 1, "unsol_pc_err:");
 		zfcp_erp_port_shutdown(port, 0);
 		break;
@@ -973,14 +922,13 @@
 
 	if (fsf_req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
 		mempool_free(status_buffer, adapter->pool.data_status_read);
-		zfcp_fsf_req_cleanup(fsf_req);
+		zfcp_fsf_req_free(fsf_req);
 		goto out;
 	}
 
 	switch (status_buffer->status_type) {
 
 	case FSF_STATUS_READ_PORT_CLOSED:
-		ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_PORT_CLOSED\n");
 		debug_text_event(adapter->erp_dbf, 3, "unsol_pclosed:");
 		debug_event(adapter->erp_dbf, 3,
 			    &status_buffer->d_id, sizeof (u32));
@@ -988,13 +936,11 @@
 		break;
 
 	case FSF_STATUS_READ_INCOMING_ELS:
-		ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_INCOMING_ELS\n");
 		debug_text_event(adapter->erp_dbf, 3, "unsol_els:");
 		zfcp_fsf_incoming_els(fsf_req);
 		break;
 
 	case FSF_STATUS_READ_SENSE_DATA_AVAIL:
-		ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_SENSE_DATA_AVAIL\n");
 		debug_text_event(adapter->erp_dbf, 3, "unsol_sense:");
 		ZFCP_LOG_INFO("unsolicited sense data received (adapter %s)\n",
 			      zfcp_get_busid_by_adapter(adapter));
@@ -1003,7 +949,6 @@
 		break;
 
 	case FSF_STATUS_READ_BIT_ERROR_THRESHOLD:
-		ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_BIT_ERROR_THRESHOLD\n");
 		debug_text_event(adapter->erp_dbf, 3, "unsol_bit_err:");
 		ZFCP_LOG_NORMAL("Bit error threshold data received:\n");
 		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
@@ -1012,7 +957,6 @@
 		break;
 
 	case FSF_STATUS_READ_LINK_DOWN:
-		ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_LINK_DOWN\n");
 		debug_text_event(adapter->erp_dbf, 0, "unsol_link_down:");
 		ZFCP_LOG_INFO("Local link to adapter %s is down\n",
 			      zfcp_get_busid_by_adapter(adapter));
@@ -1022,7 +966,6 @@
 		break;
 
 	case FSF_STATUS_READ_LINK_UP:
-		ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_LINK_UP\n");
 		debug_text_event(adapter->erp_dbf, 2, "unsol_link_up:");
 		ZFCP_LOG_INFO("Local link to adapter %s was replugged. "
 			      "Restarting operations on this adapter\n",
@@ -1037,7 +980,6 @@
 		break;
 
 	case FSF_STATUS_READ_CFDC_UPDATED:
-		ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_CFDC_UPDATED\n");
 		debug_text_event(adapter->erp_dbf, 2, "unsol_cfdc_update:");
 		ZFCP_LOG_INFO("CFDC has been updated on the adapter %s\n",
 			      zfcp_get_busid_by_adapter(adapter));
@@ -1045,7 +987,6 @@
 		break;
 
 	case FSF_STATUS_READ_CFDC_HARDENED:
-		ZFCP_LOG_FLAGS(1, "FSF_STATUS_READ_CFDC_HARDENED\n");
 		debug_text_event(adapter->erp_dbf, 2, "unsol_cfdc_harden:");
 		switch (status_buffer->status_subtype) {
 		case FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE:
@@ -1078,7 +1019,7 @@
 		break;
 	}
 	mempool_free(status_buffer, adapter->pool.data_status_read);
-	zfcp_fsf_req_cleanup(fsf_req);
+	zfcp_fsf_req_free(fsf_req);
 	/*
 	 * recycle buffer and start new request repeat until outbound
 	 * queue is empty or adapter shutdown is requested
@@ -1214,7 +1155,6 @@
 
 	case FSF_PORT_HANDLE_NOT_VALID:
 		if (status_qual >> 4 != status_qual % 0xf) {
-			ZFCP_LOG_FLAGS(2, "FSF_PORT_HANDLE_NOT_VALID\n");
 			debug_text_event(new_fsf_req->adapter->erp_dbf, 3,
 					 "fsf_s_phand_nv0");
 			/*
@@ -1223,7 +1163,6 @@
 			 * fine.
 			 */
 		} else {
-			ZFCP_LOG_FLAGS(1, "FSF_PORT_HANDLE_NOT_VALID\n");
 			ZFCP_LOG_INFO("Temporary port identifier 0x%x for "
 				      "port 0x%016Lx on adapter %s invalid. "
 				      "This may happen occasionally.\n",
@@ -1246,7 +1185,6 @@
 	case FSF_LUN_HANDLE_NOT_VALID:
 		if (status_qual >> 4 != status_qual % 0xf) {
 			/* 2 */
-			ZFCP_LOG_FLAGS(0, "FSF_LUN_HANDLE_NOT_VALID\n");
 			debug_text_event(new_fsf_req->adapter->erp_dbf, 3,
 					 "fsf_s_lhand_nv0");
 			/*
@@ -1255,7 +1193,6 @@
 			 * This is fine.
 			 */
 		} else {
-			ZFCP_LOG_FLAGS(1, "FSF_LUN_HANDLE_NOT_VALID\n");
 			ZFCP_LOG_INFO
 			    ("Warning: Temporary LUN identifier 0x%x of LUN "
 			     "0x%016Lx on port 0x%016Lx on adapter %s is "
@@ -1279,7 +1216,6 @@
 		break;
 
 	case FSF_FCP_COMMAND_DOES_NOT_EXIST:
-		ZFCP_LOG_FLAGS(2, "FSF_FCP_COMMAND_DOES_NOT_EXIST\n");
 		retval = 0;
 		debug_text_event(new_fsf_req->adapter->erp_dbf, 3,
 				 "fsf_s_no_exist");
@@ -1287,50 +1223,37 @@
 		break;
 
 	case FSF_PORT_BOXED:
-		/* 2 */
-		ZFCP_LOG_FLAGS(0, "FSF_PORT_BOXED\n");
 		ZFCP_LOG_INFO("Remote port 0x%016Lx on adapter %s needs to "
 			      "be reopened\n", unit->port->wwpn,
 			      zfcp_get_busid_by_unit(unit));
 		debug_text_event(new_fsf_req->adapter->erp_dbf, 2,
 				 "fsf_s_pboxed");
-		zfcp_erp_port_reopen(unit->port, 0);
+		zfcp_erp_port_boxed(unit->port);
 		new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
 		    | ZFCP_STATUS_FSFREQ_RETRY;
 		break;
 
 	case FSF_LUN_BOXED:
-                ZFCP_LOG_FLAGS(0, "FSF_LUN_BOXED\n");
                 ZFCP_LOG_INFO(
                         "unit 0x%016Lx on port 0x%016Lx on adapter %s needs "
                         "to be reopened\n",
                         unit->fcp_lun, unit->port->wwpn,
                         zfcp_get_busid_by_unit(unit));
                 debug_text_event(new_fsf_req->adapter->erp_dbf, 1, "fsf_s_lboxed");
-                zfcp_erp_unit_reopen(unit, 0);
-                zfcp_cmd_dbf_event_fsf("unitbox", new_fsf_req,
-                        &new_fsf_req->qtcb->header.fsf_status_qual,
-                        sizeof(union fsf_status_qual));
+		zfcp_erp_unit_boxed(unit);
                 new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
                         | ZFCP_STATUS_FSFREQ_RETRY;
                 break;
 
 	case FSF_ADAPTER_STATUS_AVAILABLE:
-		/* 2 */
-		ZFCP_LOG_FLAGS(0, "FSF_ADAPTER_STATUS_AVAILABLE\n");
 		switch (new_fsf_req->qtcb->header.fsf_status_qual.word[0]) {
 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-			ZFCP_LOG_FLAGS(2,
-				       "FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
 			debug_text_event(new_fsf_req->adapter->erp_dbf, 1,
 					 "fsf_sq_ltest");
-			/* reopening link to port */
-			zfcp_erp_port_reopen(unit->port, 0);
+			zfcp_test_link(unit->port);
 			new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 			break;
 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
-			ZFCP_LOG_FLAGS(2,
-				       "FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n");
 			/* SCSI stack will escalate */
 			debug_text_event(new_fsf_req->adapter->erp_dbf, 1,
 					 "fsf_sq_ulp");
@@ -1350,8 +1273,6 @@
 		break;
 
 	case FSF_GOOD:
-		/* 3 */
-		ZFCP_LOG_FLAGS(0, "FSF_GOOD\n");
 		retval = 0;
 		new_fsf_req->status |= ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED;
 		break;
@@ -1553,12 +1474,10 @@
 	switch (header->fsf_status) {
 
         case FSF_GOOD:
-                ZFCP_LOG_FLAGS(2,"FSF_GOOD\n");
                 retval = 0;
 		break;
 
         case FSF_SERVICE_CLASS_NOT_SUPPORTED:
-		ZFCP_LOG_FLAGS(2, "FSF_SERVICE_CLASS_NOT_SUPPORTED\n");
 		if (adapter->fc_service_class <= 3) {
 			ZFCP_LOG_INFO("error: adapter %s does not support fc "
 				      "class %d.\n",
@@ -1578,17 +1497,14 @@
 		break;
 
         case FSF_ADAPTER_STATUS_AVAILABLE:
-                ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
                 switch (header->fsf_status_qual.word[0]){
                 case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-			ZFCP_LOG_FLAGS(2,"FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
 			/* reopening link to port */
 			debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest");
 			zfcp_test_link(port);
 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 			break;
                 case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
-			ZFCP_LOG_FLAGS(2,"FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n");
 			/* ERP strategy will escalate */
 			debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp");
 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -1602,7 +1518,6 @@
                 break;
 
 	case FSF_ACCESS_DENIED:
-		ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
 		ZFCP_LOG_NORMAL("access denied, cannot send generic service "
 				"command (adapter %s, port d_id=0x%08x)\n",
 				zfcp_get_busid_by_port(port), port->d_id);
@@ -1625,7 +1540,6 @@
 		break;
 
         case FSF_GENERIC_COMMAND_REJECTED:
-		ZFCP_LOG_FLAGS(2, "FSF_GENERIC_COMMAND_REJECTED\n");
 		ZFCP_LOG_INFO("generic service command rejected "
 			      "(adapter %s, port d_id=0x%08x)\n",
 			      zfcp_get_busid_by_port(port), port->d_id);
@@ -1638,7 +1552,6 @@
 		break;
 
         case FSF_PORT_HANDLE_NOT_VALID:
-		ZFCP_LOG_FLAGS(2, "FSF_PORT_HANDLE_NOT_VALID\n");
 		ZFCP_LOG_DEBUG("Temporary port identifier 0x%x for port "
 			       "0x%016Lx on adapter %s invalid. This may "
 			       "happen occasionally.\n", port->handle,
@@ -1653,12 +1566,11 @@
 		break;
 
         case FSF_PORT_BOXED:
-		ZFCP_LOG_FLAGS(2, "FSF_PORT_BOXED\n");
 		ZFCP_LOG_INFO("port needs to be reopened "
 			      "(adapter %s, port d_id=0x%08x)\n",
 			      zfcp_get_busid_by_port(port), port->d_id);
 		debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed");
-		zfcp_erp_port_reopen(port, 0);
+		zfcp_erp_port_boxed(port);
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
 		    | ZFCP_STATUS_FSFREQ_RETRY;
 		break;
@@ -1666,7 +1578,6 @@
 	/* following states should never occure, all cases avoided
 	   in zfcp_fsf_send_ct - but who knows ... */
 	case FSF_PAYLOAD_SIZE_MISMATCH:
-		ZFCP_LOG_FLAGS(2, "FSF_PAYLOAD_SIZE_MISMATCH\n");
 		ZFCP_LOG_INFO("payload size mismatch (adapter: %s, "
 			      "req_buf_length=%d, resp_buf_length=%d)\n",
 			      zfcp_get_busid_by_adapter(adapter),
@@ -1674,7 +1585,6 @@
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_REQUEST_SIZE_TOO_LARGE:
-		ZFCP_LOG_FLAGS(2, "FSF_REQUEST_SIZE_TOO_LARGE\n");
 		ZFCP_LOG_INFO("request size too large (adapter: %s, "
 			      "req_buf_length=%d)\n",
 			      zfcp_get_busid_by_adapter(adapter),
@@ -1682,7 +1592,6 @@
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_RESPONSE_SIZE_TOO_LARGE:
-		ZFCP_LOG_FLAGS(2, "FSF_RESPONSE_SIZE_TOO_LARGE\n");
 		ZFCP_LOG_INFO("response size too large (adapter: %s, "
 			      "resp_buf_length=%d)\n",
 			      zfcp_get_busid_by_adapter(adapter),
@@ -1690,7 +1599,6 @@
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 	case FSF_SBAL_MISMATCH:
-		ZFCP_LOG_FLAGS(2, "FSF_SBAL_MISMATCH\n");
 		ZFCP_LOG_INFO("SBAL mismatch (adapter: %s, req_buf_length=%d, "
 			      "resp_buf_length=%d)\n",
 			      zfcp_get_busid_by_adapter(adapter),
@@ -1846,8 +1754,8 @@
 static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
 {
 	struct zfcp_adapter *adapter;
-	fc_id_t d_id;
 	struct zfcp_port *port;
+	fc_id_t d_id;
 	struct fsf_qtcb_header *header;
 	struct fsf_qtcb_bottom_support *bottom;
 	struct zfcp_send_els *send_els;
@@ -1856,6 +1764,7 @@
 
 	send_els = fsf_req->data.send_els;
 	adapter = send_els->adapter;
+	port = send_els->port;
 	d_id = send_els->d_id;
 	header = &fsf_req->qtcb->header;
 	bottom = &fsf_req->qtcb->bottom.support;
@@ -1866,12 +1775,10 @@
 	switch (header->fsf_status) {
 
 	case FSF_GOOD:
-		ZFCP_LOG_FLAGS(2, "FSF_GOOD\n");
 		retval = 0;
 		break;
 
 	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
-		ZFCP_LOG_FLAGS(2, "FSF_SERVICE_CLASS_NOT_SUPPORTED\n");
 		if (adapter->fc_service_class <= 3) {
 			ZFCP_LOG_INFO("error: adapter %s does "
 				      "not support fibrechannel class %d.\n",
@@ -1891,22 +1798,14 @@
 		break;
 
 	case FSF_ADAPTER_STATUS_AVAILABLE:
-		ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
 		switch (header->fsf_status_qual.word[0]){
 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-			ZFCP_LOG_FLAGS(2,"FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
 			debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ltest");
-			if (send_els->ls_code != ZFCP_LS_ADISC) {
-				read_lock(&zfcp_data.config_lock);
-				port = zfcp_get_port_by_did(adapter, d_id);
-				if (port)
-					zfcp_test_link(port);
-				read_unlock(&zfcp_data.config_lock);
-			}
+			if (port && (send_els->ls_code != ZFCP_LS_ADISC))
+				zfcp_test_link(port);
 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 			break;
 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
-			ZFCP_LOG_FLAGS(2,"FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n");
 			debug_text_event(adapter->erp_dbf, 1, "fsf_sq_ulp");
 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 			retval =
@@ -1915,7 +1814,6 @@
 					      &header->fsf_status_qual.word[2]);
 			break;
 		case FSF_SQ_RETRY_IF_POSSIBLE:
-			ZFCP_LOG_FLAGS(2, "FSF_SQ_RETRY_IF_POSSIBLE\n");
 			debug_text_event(adapter->erp_dbf, 1, "fsf_sq_retry");
 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 			break;
@@ -1928,7 +1826,6 @@
 		break;
 
 	case FSF_ELS_COMMAND_REJECTED:
-		ZFCP_LOG_FLAGS(2, "FSF_ELS_COMMAND_REJECTED\n");
 		ZFCP_LOG_INFO("ELS has been rejected because command filter "
 			      "prohibited sending "
 			      "(adapter: %s, port d_id: 0x%08x)\n",
@@ -1937,7 +1834,6 @@
 		break;
 
 	case FSF_PAYLOAD_SIZE_MISMATCH:
-		ZFCP_LOG_FLAGS(2, "FSF_PAYLOAD_SIZE_MISMATCH\n");
 		ZFCP_LOG_INFO(
 			"ELS request size and ELS response size must be either "
 			"both 0, or both greater than 0 "
@@ -1948,7 +1844,6 @@
 		break;
 
 	case FSF_REQUEST_SIZE_TOO_LARGE:
-		ZFCP_LOG_FLAGS(2, "FSF_REQUEST_SIZE_TOO_LARGE\n");
 		ZFCP_LOG_INFO(
 			"Length of the ELS request buffer, "
 			"specified in QTCB bottom, "
@@ -1960,7 +1855,6 @@
 		break;
 
 	case FSF_RESPONSE_SIZE_TOO_LARGE:
-		ZFCP_LOG_FLAGS(2, "FSF_RESPONSE_SIZE_TOO_LARGE\n");
 		ZFCP_LOG_INFO(
 			"Length of the ELS response buffer, "
 			"specified in QTCB bottom, "
@@ -1973,7 +1867,6 @@
 
 	case FSF_SBAL_MISMATCH:
 		/* should never occure, avoided in zfcp_fsf_send_els */
-		ZFCP_LOG_FLAGS(2, "FSF_SBAL_MISMATCH\n");
 		ZFCP_LOG_INFO("SBAL mismatch (adapter: %s, req_buf_length=%d, "
 			      "resp_buf_length=%d)\n",
 			      zfcp_get_busid_by_adapter(adapter),
@@ -1982,7 +1875,6 @@
 		break;
 
 	case FSF_ACCESS_DENIED:
-		ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
 		ZFCP_LOG_NORMAL("access denied, cannot send ELS command "
 				"(adapter %s, port d_id=0x%08x)\n",
 				zfcp_get_busid_by_adapter(adapter), d_id);
@@ -2000,11 +1892,8 @@
 			}
 		}
 		debug_text_event(adapter->erp_dbf, 1, "fsf_s_access");
-		read_lock(&zfcp_data.config_lock);
-		port = zfcp_get_port_by_did(adapter, d_id);
 		if (port != NULL)
 			zfcp_erp_port_access_denied(port);
-		read_unlock(&zfcp_data.config_lock);
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 
@@ -2195,14 +2084,11 @@
 	switch (fsf_req->qtcb->header.fsf_status) {
 
 	case FSF_GOOD:
-		ZFCP_LOG_FLAGS(2, "FSF_GOOD\n");
-
 		if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1))
 			return -EIO;
 
 		switch (adapter->fc_topology) {
 		case FSF_TOPO_P2P:
-			ZFCP_LOG_FLAGS(1, "FSF_TOPO_P2P\n");
 			ZFCP_LOG_NORMAL("Point-to-Point fibrechannel "
 					"configuration detected at adapter %s\n"
 					"Peer WWNN 0x%016llx, "
@@ -2216,7 +2102,6 @@
 					 "top-p-to-p");
 			break;
 		case FSF_TOPO_AL:
-			ZFCP_LOG_FLAGS(1, "FSF_TOPO_AL\n");
 			ZFCP_LOG_NORMAL("error: Arbitrated loop fibrechannel "
 					"topology detected at adapter %s "
 					"unsupported, shutting down adapter\n",
@@ -2226,7 +2111,6 @@
 			zfcp_erp_adapter_shutdown(adapter, 0);
 			return -EIO;
 		case FSF_TOPO_FABRIC:
-			ZFCP_LOG_FLAGS(1, "FSF_TOPO_FABRIC\n");
 			ZFCP_LOG_INFO("Switched fabric fibrechannel "
 				      "network detected at adapter %s.\n",
 				      zfcp_get_busid_by_adapter(adapter));
@@ -2357,7 +2241,7 @@
 	wait_event(fsf_req->completion_wq,
 		   fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
 	del_timer_sync(timer);
-	zfcp_fsf_req_cleanup(fsf_req);
+	zfcp_fsf_req_free(fsf_req);
  out:
 	kfree(timer);
 	return retval;
@@ -2379,7 +2263,6 @@
 
 	switch (fsf_req->qtcb->header.fsf_status) {
         case FSF_GOOD:
-                ZFCP_LOG_FLAGS(2,"FSF_GOOD\n");
                 bottom = &fsf_req->qtcb->bottom.port;
                 memcpy(data, bottom, sizeof(*data));
                 break;
@@ -2481,7 +2364,6 @@
 	switch (header->fsf_status) {
 
 	case FSF_PORT_ALREADY_OPEN:
-		ZFCP_LOG_FLAGS(0, "FSF_PORT_ALREADY_OPEN\n");
 		ZFCP_LOG_NORMAL("bug: remote port 0x%016Lx on adapter %s "
 				"is already open.\n",
 				port->wwpn, zfcp_get_busid_by_port(port));
@@ -2494,7 +2376,6 @@
 		break;
 
 	case FSF_ACCESS_DENIED:
-		ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
 		ZFCP_LOG_NORMAL("Access denied, cannot open port 0x%016Lx "
 				"on adapter %s\n",
 				port->wwpn, zfcp_get_busid_by_port(port));
@@ -2517,7 +2398,6 @@
 		break;
 
 	case FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED:
-		ZFCP_LOG_FLAGS(1, "FSF_MAXIMUM_NUMBER_OF_PORTS_EXCEEDED\n");
 		ZFCP_LOG_INFO("error: The FSF adapter is out of resources. "
 			      "The remote port 0x%016Lx on adapter %s "
 			      "could not be opened. Disabling it.\n",
@@ -2529,11 +2409,8 @@
 		break;
 
 	case FSF_ADAPTER_STATUS_AVAILABLE:
-		ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
 		switch (header->fsf_status_qual.word[0]) {
 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-			ZFCP_LOG_FLAGS(2,
-				       "FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
 			debug_text_event(fsf_req->adapter->erp_dbf, 1,
 					 "fsf_sq_ltest");
 			/* ERP strategy will escalate */
@@ -2546,7 +2423,6 @@
 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 			break;
 		case FSF_SQ_NO_RETRY_POSSIBLE:
-			ZFCP_LOG_FLAGS(0, "FSF_SQ_NO_RETRY_POSSIBLE\n");
 			ZFCP_LOG_NORMAL("The remote port 0x%016Lx on "
 					"adapter %s could not be opened. "
 					"Disabling it.\n",
@@ -2572,7 +2448,6 @@
 		break;
 
 	case FSF_GOOD:
-		ZFCP_LOG_FLAGS(3, "FSF_GOOD\n");
 		/* save port handle assigned by FSF */
 		port->handle = header->port_handle;
 		ZFCP_LOG_INFO("The remote port 0x%016Lx via adapter %s "
@@ -2582,6 +2457,9 @@
 		/* mark port as open */
 		atomic_set_mask(ZFCP_STATUS_COMMON_OPEN |
 				ZFCP_STATUS_PORT_PHYS_OPEN, &port->status);
+		atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
+		                  ZFCP_STATUS_COMMON_ACCESS_BOXED,
+		                  &port->status);
 		retval = 0;
 		/* check whether D_ID has changed during open */
 		/*
@@ -2630,7 +2508,6 @@
 
 	case FSF_UNKNOWN_OP_SUBTYPE:
 		/* should never occure, subtype not set in zfcp_fsf_open_port */
-		ZFCP_LOG_FLAGS(2, "FSF_UNKNOWN_OP_SUBTYPE\n");
 		ZFCP_LOG_INFO("unknown operation subtype (adapter: %s, "
 			      "op_subtype=0x%x)\n",
 			      zfcp_get_busid_by_port(port),
@@ -2739,7 +2616,6 @@
 	switch (fsf_req->qtcb->header.fsf_status) {
 
 	case FSF_PORT_HANDLE_NOT_VALID:
-		ZFCP_LOG_FLAGS(1, "FSF_PORT_HANDLE_NOT_VALID\n");
 		ZFCP_LOG_INFO("Temporary port identifier 0x%x for port "
 			      "0x%016Lx on adapter %s invalid. This may happen "
 			      "occasionally.\n", port->handle,
@@ -2755,7 +2631,6 @@
 		break;
 
 	case FSF_ADAPTER_STATUS_AVAILABLE:
-		ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
 		/* Note: FSF has actually closed the port in this case.
 		 * The status code is just daft. Fingers crossed for a change
 		 */
@@ -2763,7 +2638,6 @@
 		break;
 
 	case FSF_GOOD:
-		ZFCP_LOG_FLAGS(3, "FSF_GOOD\n");
 		ZFCP_LOG_TRACE("remote port 0x016%Lx on adapter %s closed, "
 			       "port handle 0x%x\n", port->wwpn,
 			       zfcp_get_busid_by_port(port), port->handle);
@@ -2884,7 +2758,6 @@
 	switch (header->fsf_status) {
 
 	case FSF_PORT_HANDLE_NOT_VALID:
-		ZFCP_LOG_FLAGS(1, "FSF_PORT_HANDLE_NOT_VALID\n");
 		ZFCP_LOG_INFO("Temporary port identifier 0x%x invalid"
 			      "(adapter %s, port 0x%016Lx). "
 			      "This may happen occasionally.\n",
@@ -2902,7 +2775,6 @@
 		break;
 
 	case FSF_ACCESS_DENIED:
-		ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
 		ZFCP_LOG_NORMAL("Access denied, cannot close "
 				"physical port 0x%016Lx on adapter %s\n",
 				port->wwpn, zfcp_get_busid_by_port(port));
@@ -2925,32 +2797,26 @@
 		break;
 
 	case FSF_PORT_BOXED:
-		ZFCP_LOG_FLAGS(2, "FSF_PORT_BOXED\n");
 		ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter "
 			       "%s needs to be reopened but it was attempted "
 			       "to close it physically.\n",
 			       port->wwpn,
 			       zfcp_get_busid_by_port(port));
 		debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_pboxed");
-		zfcp_erp_port_reopen(port, 0);
+		zfcp_erp_port_boxed(port);
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
 			ZFCP_STATUS_FSFREQ_RETRY;
 		break;
 
 	case FSF_ADAPTER_STATUS_AVAILABLE:
-		ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
 		switch (header->fsf_status_qual.word[0]) {
 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-			ZFCP_LOG_FLAGS(2,
-				       "FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
 			debug_text_event(fsf_req->adapter->erp_dbf, 1,
 					 "fsf_sq_ltest");
 			/* This will now be escalated by ERP */
 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 			break;
 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
-			ZFCP_LOG_FLAGS(2,
-				       "FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n");
 			/* ERP strategy will escalate */
 			debug_text_event(fsf_req->adapter->erp_dbf, 1,
 					 "fsf_sq_ulp");
@@ -2970,7 +2836,6 @@
 		break;
 
 	case FSF_GOOD:
-		ZFCP_LOG_FLAGS(3, "FSF_GOOD\n");
 		ZFCP_LOG_DEBUG("Remote port 0x%016Lx via adapter %s "
 			       "physically closed, port handle 0x%x\n",
 			       port->wwpn,
@@ -3116,7 +2981,6 @@
 	switch (header->fsf_status) {
 
 	case FSF_PORT_HANDLE_NOT_VALID:
-		ZFCP_LOG_FLAGS(1, "FSF_PORT_HANDLE_NOT_VALID\n");
 		ZFCP_LOG_INFO("Temporary port identifier 0x%x "
 			      "for port 0x%016Lx on adapter %s invalid "
 			      "This may happen occasionally\n",
@@ -3132,7 +2996,6 @@
 		break;
 
 	case FSF_LUN_ALREADY_OPEN:
-		ZFCP_LOG_FLAGS(0, "FSF_LUN_ALREADY_OPEN\n");
 		ZFCP_LOG_NORMAL("bug: Attempted to open unit 0x%016Lx on "
 				"remote port 0x%016Lx on adapter %s twice.\n",
 				unit->fcp_lun,
@@ -3143,7 +3006,6 @@
 		break;
 
 	case FSF_ACCESS_DENIED:
-		ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
 		ZFCP_LOG_NORMAL("Access denied, cannot open unit 0x%016Lx on "
 				"remote port 0x%016Lx on adapter %s\n",
 				unit->fcp_lun, unit->port->wwpn,
@@ -3169,18 +3031,16 @@
 		break;
 
 	case FSF_PORT_BOXED:
-		ZFCP_LOG_FLAGS(2, "FSF_PORT_BOXED\n");
 		ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter %s "
 			       "needs to be reopened\n",
 			       unit->port->wwpn, zfcp_get_busid_by_unit(unit));
 		debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed");
-		zfcp_erp_port_reopen(unit->port, 0);
+		zfcp_erp_port_boxed(unit->port);
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
 			ZFCP_STATUS_FSFREQ_RETRY;
 		break;
 
 	case FSF_LUN_SHARING_VIOLATION:
-		ZFCP_LOG_FLAGS(2, "FSF_LUN_SHARING_VIOLATION\n");
 		if (header->fsf_status_qual.word[0] != 0) {
 			ZFCP_LOG_NORMAL("FCP-LUN 0x%Lx at the remote port "
 					"with WWPN 0x%Lx "
@@ -3224,7 +3084,6 @@
 		break;
 
 	case FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED:
-		ZFCP_LOG_FLAGS(1, "FSF_MAXIMUM_NUMBER_OF_LUNS_EXCEEDED\n");
 		ZFCP_LOG_INFO("error: The adapter ran out of resources. "
 			      "There is no handle (temporary port identifier) "
 			      "available for unit 0x%016Lx on port 0x%016Lx "
@@ -3239,20 +3098,15 @@
 		break;
 
 	case FSF_ADAPTER_STATUS_AVAILABLE:
-		ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
 		switch (header->fsf_status_qual.word[0]) {
 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-			ZFCP_LOG_FLAGS(2,
-				       "FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
 			/* Re-establish link to port */
 			debug_text_event(adapter->erp_dbf, 1,
 					 "fsf_sq_ltest");
-			zfcp_erp_port_reopen(unit->port, 0);
+			zfcp_test_link(unit->port);
 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 			break;
 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
-			ZFCP_LOG_FLAGS(2,
-				       "FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n");
 			/* ERP strategy will escalate */
 			debug_text_event(adapter->erp_dbf, 1,
 					 "fsf_sq_ulp");
@@ -3271,7 +3125,6 @@
 		break;
 
 	case FSF_INVALID_COMMAND_OPTION:
-		ZFCP_LOG_FLAGS(2, "FSF_INVALID_COMMAND_OPTION\n");
 		ZFCP_LOG_NORMAL(
 			"Invalid option 0x%x has been specified "
 			"in QTCB bottom sent to the adapter %s\n",
@@ -3282,7 +3135,6 @@
 		break;
 
 	case FSF_GOOD:
-		ZFCP_LOG_FLAGS(3, "FSF_GOOD\n");
 		/* save LUN handle assigned by FSF */
 		unit->handle = header->lun_handle;
 		ZFCP_LOG_TRACE("unit 0x%016Lx on remote port 0x%016Lx on "
@@ -3293,7 +3145,9 @@
 			       unit->handle);
 		/* mark unit as open */
 		atomic_set_mask(ZFCP_STATUS_COMMON_OPEN, &unit->status);
-
+		atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
+		                  ZFCP_STATUS_COMMON_ACCESS_BOXED,
+		                  &unit->status);
 		if (adapter->supported_features & FSF_FEATURE_LUN_SHARING){
 			if (!exclusive)
 		                atomic_set_mask(ZFCP_STATUS_UNIT_SHARED,
@@ -3437,7 +3291,6 @@
 	switch (fsf_req->qtcb->header.fsf_status) {
 
 	case FSF_PORT_HANDLE_NOT_VALID:
-		ZFCP_LOG_FLAGS(1, "FSF_PORT_HANDLE_NOT_VALID\n");
 		ZFCP_LOG_INFO("Temporary port identifier 0x%x for port "
 			      "0x%016Lx on adapter %s invalid. This may "
 			      "happen in rare circumstances\n",
@@ -3458,7 +3311,6 @@
 		break;
 
 	case FSF_LUN_HANDLE_NOT_VALID:
-		ZFCP_LOG_FLAGS(1, "FSF_LUN_HANDLE_NOT_VALID\n");
 		ZFCP_LOG_INFO("Temporary LUN identifier 0x%x of unit "
 			      "0x%016Lx on port 0x%016Lx on adapter %s is "
 			      "invalid. This may happen occasionally.\n",
@@ -3480,32 +3332,26 @@
 		break;
 
 	case FSF_PORT_BOXED:
-		ZFCP_LOG_FLAGS(2, "FSF_PORT_BOXED\n");
 		ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter %s "
 			       "needs to be reopened\n",
 			       unit->port->wwpn,
 			       zfcp_get_busid_by_unit(unit));
 		debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_pboxed");
-		zfcp_erp_port_reopen(unit->port, 0);
+		zfcp_erp_port_boxed(unit->port);
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
 			ZFCP_STATUS_FSFREQ_RETRY;
 		break;
 
 	case FSF_ADAPTER_STATUS_AVAILABLE:
-		ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
 		switch (fsf_req->qtcb->header.fsf_status_qual.word[0]) {
 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-			ZFCP_LOG_FLAGS(2,
-				       "FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
 			/* re-establish link to port */
 			debug_text_event(fsf_req->adapter->erp_dbf, 1,
 					 "fsf_sq_ltest");
-			zfcp_erp_port_reopen(unit->port, 0);
+			zfcp_test_link(unit->port);
 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 			break;
 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
-			ZFCP_LOG_FLAGS(2,
-				       "FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n");
 			/* ERP strategy will escalate */
 			debug_text_event(fsf_req->adapter->erp_dbf, 1,
 					 "fsf_sq_ulp");
@@ -3526,7 +3372,6 @@
 		break;
 
 	case FSF_GOOD:
-		ZFCP_LOG_FLAGS(3, "FSF_GOOD\n");
 		ZFCP_LOG_TRACE("unit 0x%016Lx on port 0x%016Lx on adapter %s "
 			       "closed, port handle 0x%x\n",
 			       unit->fcp_lun,
@@ -3622,7 +3467,6 @@
 	 */
 	switch (scsi_cmnd->sc_data_direction) {
 	case DMA_NONE:
-		ZFCP_LOG_FLAGS(3, "DMA_NONE\n");
 		fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_CMND;
 		/*
 		 * FIXME(qdio):
@@ -3632,19 +3476,16 @@
 		sbtype = SBAL_FLAGS0_TYPE_READ;
 		break;
 	case DMA_FROM_DEVICE:
-		ZFCP_LOG_FLAGS(3, "DMA_FROM_DEVICE\n");
 		fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_READ;
 		sbtype = SBAL_FLAGS0_TYPE_READ;
 		fcp_cmnd_iu->rddata = 1;
 		break;
 	case DMA_TO_DEVICE:
-		ZFCP_LOG_FLAGS(3, "DMA_TO_DEVICE\n");
 		fsf_req->qtcb->bottom.io.data_direction = FSF_DATADIR_WRITE;
 		sbtype = SBAL_FLAGS0_TYPE_WRITE;
 		fcp_cmnd_iu->wddata = 1;
 		break;
 	case DMA_BIDIRECTIONAL:
-		ZFCP_LOG_FLAGS(0, "DMA_BIDIRECTIONAL not supported\n");
 	default:
 		/*
 		 * dummy, catch this condition earlier
@@ -3877,7 +3718,6 @@
 	switch (header->fsf_status) {
 
 	case FSF_PORT_HANDLE_NOT_VALID:
-		ZFCP_LOG_FLAGS(1, "FSF_PORT_HANDLE_NOT_VALID\n");
 		ZFCP_LOG_INFO("Temporary port identifier 0x%x for port "
 			      "0x%016Lx on adapter %s invalid\n",
 			      unit->port->handle,
@@ -3892,7 +3732,6 @@
 		break;
 
 	case FSF_LUN_HANDLE_NOT_VALID:
-		ZFCP_LOG_FLAGS(1, "FSF_LUN_HANDLE_NOT_VALID\n");
 		ZFCP_LOG_INFO("Temporary LUN identifier 0x%x for unit "
 			      "0x%016Lx on port 0x%016Lx on adapter %s is "
 			      "invalid. This may happen occasionally.\n",
@@ -3911,7 +3750,6 @@
 		break;
 
 	case FSF_HANDLE_MISMATCH:
-		ZFCP_LOG_FLAGS(0, "FSF_HANDLE_MISMATCH\n");
 		ZFCP_LOG_NORMAL("bug: The port handle 0x%x has changed "
 				"unexpectedly. (adapter %s, port 0x%016Lx, "
 				"unit 0x%016Lx)\n",
@@ -3934,7 +3772,6 @@
 		break;
 
 	case FSF_SERVICE_CLASS_NOT_SUPPORTED:
-		ZFCP_LOG_FLAGS(0, "FSF_SERVICE_CLASS_NOT_SUPPORTED\n");
 		if (fsf_req->adapter->fc_service_class <= 3) {
 			ZFCP_LOG_NORMAL("error: The adapter %s does "
 					"not support fibrechannel class %d.\n",
@@ -3959,7 +3796,6 @@
 		break;
 
 	case FSF_FCPLUN_NOT_VALID:
-		ZFCP_LOG_FLAGS(0, "FSF_FCPLUN_NOT_VALID\n");
 		ZFCP_LOG_NORMAL("bug: unit 0x%016Lx on port 0x%016Lx on "
 				"adapter %s does not have correct unit "
 				"handle 0x%x\n",
@@ -3982,7 +3818,6 @@
 		break;
 
 	case FSF_ACCESS_DENIED:
-		ZFCP_LOG_FLAGS(2, "FSF_ACCESS_DENIED\n");
 		ZFCP_LOG_NORMAL("Access denied, cannot send FCP command to "
 				"unit 0x%016Lx on port 0x%016Lx on "
 				"adapter %s\n",	unit->fcp_lun, unit->port->wwpn,
@@ -4006,7 +3841,6 @@
 		break;
 
 	case FSF_DIRECTION_INDICATOR_NOT_VALID:
-		ZFCP_LOG_FLAGS(0, "FSF_DIRECTION_INDICATOR_NOT_VALID\n");
 		ZFCP_LOG_INFO("bug: Invalid data direction given for unit "
 			      "0x%016Lx on port 0x%016Lx on adapter %s "
 			      "(debug info %d)\n",
@@ -4026,7 +3860,6 @@
 		break;
 
 	case FSF_CMND_LENGTH_NOT_VALID:
-		ZFCP_LOG_FLAGS(0, "FSF_CMND_LENGTH_NOT_VALID\n");
 		ZFCP_LOG_NORMAL
 		    ("bug: An invalid control-data-block length field "
 		     "was found in a command for unit 0x%016Lx on port "
@@ -4046,69 +3879,43 @@
 		break;
 
 	case FSF_PORT_BOXED:
-		ZFCP_LOG_FLAGS(2, "FSF_PORT_BOXED\n");
 		ZFCP_LOG_DEBUG("The remote port 0x%016Lx on adapter %s "
 			       "needs to be reopened\n",
 			       unit->port->wwpn, zfcp_get_busid_by_unit(unit));
 		debug_text_event(fsf_req->adapter->erp_dbf, 2, "fsf_s_pboxed");
-		zfcp_erp_port_reopen(unit->port, 0);
-		zfcp_cmd_dbf_event_fsf("portbox", fsf_req,
-				       &header->fsf_status_qual,
-				       sizeof (union fsf_status_qual));
+		zfcp_erp_port_boxed(unit->port);
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR |
 			ZFCP_STATUS_FSFREQ_RETRY;
 		break;
 
 	case FSF_LUN_BOXED:
-		ZFCP_LOG_FLAGS(0, "FSF_LUN_BOXED\n");
 		ZFCP_LOG_NORMAL("unit needs to be reopened (adapter %s, "
 				"wwpn=0x%016Lx, fcp_lun=0x%016Lx)\n",
 				zfcp_get_busid_by_unit(unit),
 				unit->port->wwpn, unit->fcp_lun);
 		debug_text_event(fsf_req->adapter->erp_dbf, 1, "fsf_s_lboxed");
-		zfcp_erp_unit_reopen(unit, 0);
-		zfcp_cmd_dbf_event_fsf("unitbox", fsf_req,
-				       &header->fsf_status_qual,
-				       sizeof(union fsf_status_qual));
+		zfcp_erp_unit_boxed(unit);
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR
 			| ZFCP_STATUS_FSFREQ_RETRY;
 		break;
 
 	case FSF_ADAPTER_STATUS_AVAILABLE:
-		ZFCP_LOG_FLAGS(2, "FSF_ADAPTER_STATUS_AVAILABLE\n");
 		switch (header->fsf_status_qual.word[0]) {
 		case FSF_SQ_INVOKE_LINK_TEST_PROCEDURE:
-			ZFCP_LOG_FLAGS(2,
-				       "FSF_SQ_INVOKE_LINK_TEST_PROCEDURE\n");
 			/* re-establish link to port */
 			debug_text_event(fsf_req->adapter->erp_dbf, 1,
 					 "fsf_sq_ltest");
-			zfcp_erp_port_reopen(unit->port, 0);
-			zfcp_cmd_dbf_event_fsf(
-				"sqltest",
-				fsf_req,
-				&header->fsf_status_qual,
-				sizeof (union fsf_status_qual));
-			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
+ 			zfcp_test_link(unit->port);
 			break;
 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
-			ZFCP_LOG_FLAGS(3,
-				       "FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED\n");
 			/* FIXME(hw) need proper specs for proper action */
 			/* let scsi stack deal with retries and escalation */
 			debug_text_event(fsf_req->adapter->erp_dbf, 1,
 					 "fsf_sq_ulp");
-			zfcp_cmd_dbf_event_fsf(
-				"sqdeperp",
-				fsf_req,
-				&header->fsf_status_qual,
-				sizeof (union fsf_status_qual));
-			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 			break;
 		default:
-			/* FIXME: shall we consider this a successful transfer? */
 			ZFCP_LOG_NORMAL
-			    ("bug: Wrong status qualifier 0x%x arrived.\n",
+ 			    ("Unknown status qualifier 0x%x arrived.\n",
 			     header->fsf_status_qual.word[0]);
 			debug_text_event(fsf_req->adapter->erp_dbf, 0,
 					 "fsf_sq_inval:");
@@ -4117,14 +3924,13 @@
 					sizeof(u32));
 			break;
 		}
+		fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
 		break;
 
 	case FSF_GOOD:
-		ZFCP_LOG_FLAGS(3, "FSF_GOOD\n");
 		break;
 
 	case FSF_FCP_RSP_AVAILABLE:
-		ZFCP_LOG_FLAGS(2, "FSF_FCP_RSP_AVAILABLE\n");
 		break;
 
 	default:
@@ -4217,14 +4023,12 @@
 		ZFCP_LOG_DEBUG("rsp_len is valid\n");
 		switch (fcp_rsp_info[3]) {
 		case RSP_CODE_GOOD:
-			ZFCP_LOG_FLAGS(3, "RSP_CODE_GOOD\n");
 			/* ok, continue */
 			ZFCP_LOG_TRACE("no failure or Task Management "
 				       "Function complete\n");
 			set_host_byte(&scpnt->result, DID_OK);
 			break;
 		case RSP_CODE_LENGTH_MISMATCH:
-			ZFCP_LOG_FLAGS(0, "RSP_CODE_LENGTH_MISMATCH\n");
 			/* hardware bug */
 			ZFCP_LOG_NORMAL("bug: FCP response code indictates "
 					"that the fibrechannel protocol data "
@@ -4242,7 +4046,6 @@
 			set_host_byte(&scpnt->result, DID_ERROR);
 			goto skip_fsfstatus;
 		case RSP_CODE_FIELD_INVALID:
-			ZFCP_LOG_FLAGS(0, "RSP_CODE_FIELD_INVALID\n");
 			/* driver or hardware bug */
 			ZFCP_LOG_NORMAL("bug: FCP response code indictates "
 					"that the fibrechannel protocol data "
@@ -4261,7 +4064,6 @@
 			zfcp_cmd_dbf_event_fsf("codeinv", fsf_req, NULL, 0);
 			goto skip_fsfstatus;
 		case RSP_CODE_RO_MISMATCH:
-			ZFCP_LOG_FLAGS(0, "RSP_CODE_RO_MISMATCH\n");
 			/* hardware bug */
 			ZFCP_LOG_NORMAL("bug: The FCP response code indicates "
 					"that conflicting  values for the "
@@ -4407,13 +4209,11 @@
 	/* check FCP_RSP_INFO */
 	switch (fcp_rsp_info[3]) {
 	case RSP_CODE_GOOD:
-		ZFCP_LOG_FLAGS(3, "RSP_CODE_GOOD\n");
 		/* ok, continue */
 		ZFCP_LOG_DEBUG("no failure or Task Management "
 			       "Function complete\n");
 		break;
 	case RSP_CODE_TASKMAN_UNSUPP:
-		ZFCP_LOG_FLAGS(0, "RSP_CODE_TASKMAN_UNSUPP\n");
 		ZFCP_LOG_NORMAL("bug: A reuested task management function "
 				"is not supported on the target device "
 				"unit 0x%016Lx, port 0x%016Lx, adapter %s\n ",
@@ -4423,7 +4223,6 @@
 		fsf_req->status |= ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP;
 		break;
 	case RSP_CODE_TASKMAN_FAILED:
-		ZFCP_LOG_FLAGS(0, "RSP_CODE_TASKMAN_FAILED\n");
 		ZFCP_LOG_NORMAL("bug: A reuested task management function "
 				"failed to complete successfully. "
 				"unit 0x%016Lx, port 0x%016Lx, adapter %s.\n",
@@ -4610,7 +4409,6 @@
 	switch (header->fsf_status) {
 
 	case FSF_GOOD:
-		ZFCP_LOG_FLAGS(2, "FSF_GOOD\n");
 		ZFCP_LOG_NORMAL(
 			"The FSF request has been successfully completed "
 			"on the adapter %s\n",
@@ -4618,7 +4416,6 @@
 		break;
 
 	case FSF_OPERATION_PARTIALLY_SUCCESSFUL:
-		ZFCP_LOG_FLAGS(2, "FSF_OPERATION_PARTIALLY_SUCCESSFUL\n");
 		if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE) {
 			switch (header->fsf_status_qual.word[0]) {
 
@@ -4655,7 +4452,6 @@
 		break;
 
 	case FSF_AUTHORIZATION_FAILURE:
-		ZFCP_LOG_FLAGS(2, "FSF_AUTHORIZATION_FAILURE\n");
 		ZFCP_LOG_NORMAL(
 			"Adapter %s does not accept privileged commands\n",
 			zfcp_get_busid_by_adapter(adapter));
@@ -4664,7 +4460,6 @@
 		break;
 
 	case FSF_CFDC_ERROR_DETECTED:
-		ZFCP_LOG_FLAGS(2, "FSF_CFDC_ERROR_DETECTED\n");
 		ZFCP_LOG_NORMAL(
 			"Error at position %d in the CFDC, "
 			"CFDC is discarded by the adapter %s\n",
@@ -4675,7 +4470,6 @@
 		break;
 
 	case FSF_CONTROL_FILE_UPDATE_ERROR:
-		ZFCP_LOG_FLAGS(2, "FSF_CONTROL_FILE_UPDATE_ERROR\n");
 		ZFCP_LOG_NORMAL(
 			"Adapter %s cannot harden the control file, "
 			"file is discarded\n",
@@ -4685,7 +4479,6 @@
 		break;
 
 	case FSF_CONTROL_FILE_TOO_LARGE:
-		ZFCP_LOG_FLAGS(2, "FSF_CONTROL_FILE_TOO_LARGE\n");
 		ZFCP_LOG_NORMAL(
 			"Control file is too large, file is discarded "
 			"by the adapter %s\n",
@@ -4695,7 +4488,6 @@
 		break;
 
 	case FSF_ACCESS_CONFLICT_DETECTED:
-		ZFCP_LOG_FLAGS(2, "FSF_ACCESS_CONFLICT_DETECTED\n");
 		if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE)
 			ZFCP_LOG_NORMAL(
 				"CFDC has been discarded by the adapter %s, "
@@ -4708,7 +4500,6 @@
 		break;
 
 	case FSF_CONFLICTS_OVERRULED:
-		ZFCP_LOG_FLAGS(2, "FSF_CONFLICTS_OVERRULED\n");
 		if (bottom->operation_subtype == FSF_CFDC_OPERATION_SUBTYPE)
 			ZFCP_LOG_NORMAL(
 				"CFDC has been activated on the adapter %s, "
@@ -4721,7 +4512,6 @@
 		break;
 
 	case FSF_UNKNOWN_OP_SUBTYPE:
-		ZFCP_LOG_FLAGS(2, "FSF_UNKNOWN_OP_SUBTYPE\n");
 		ZFCP_LOG_NORMAL("unknown operation subtype (adapter: %s, "
 				"op_subtype=0x%x)\n",
 				zfcp_get_busid_by_adapter(adapter),
@@ -4731,7 +4521,6 @@
 		break;
 
 	case FSF_INVALID_COMMAND_OPTION:
-		ZFCP_LOG_FLAGS(2, "FSF_INVALID_COMMAND_OPTION\n");
 		ZFCP_LOG_NORMAL(
 			"Invalid option 0x%x has been specified "
 			"in QTCB bottom sent to the adapter %s\n",
@@ -4800,7 +4589,7 @@
 	*status = fsf_req->status;
 
 	/* cleanup request */
-	zfcp_fsf_req_cleanup(fsf_req);
+	zfcp_fsf_req_free(fsf_req);
  out:
 	return retval;
 }
@@ -4999,9 +4788,9 @@
 		inc_seq_no = 0;
 
 	/* put allocated FSF request at list tail */
-	write_lock_irqsave(&adapter->fsf_req_list_lock, flags);
+	spin_lock_irqsave(&adapter->fsf_req_list_lock, flags);
 	list_add_tail(&fsf_req->list, &adapter->fsf_req_list_head);
-	write_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
+	spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
 
 	/* figure out expiration time of timeout and start timeout */
 	if (unlikely(timer)) {
@@ -5045,9 +4834,9 @@
 		 */
 		if (timer)
 			del_timer(timer);
-		write_lock_irqsave(&adapter->fsf_req_list_lock, flags);
+		spin_lock_irqsave(&adapter->fsf_req_list_lock, flags);
 		list_del(&fsf_req->list);
-		write_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
+		spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
 		/*
 		 * adjust the number of free SBALs in request queue as well as
 		 * position of first one
@@ -5085,25 +4874,4 @@
 	return retval;
 }
 
-/*
- * function:    zfcp_fsf_req_cleanup
- *
- * purpose:	cleans up an FSF request and removes it from the specified list
- *
- * returns:
- *
- * assumption:	no pending SB in SBALEs other than QTCB
- */
-void
-zfcp_fsf_req_cleanup(struct zfcp_fsf_req *fsf_req)
-{
-	struct zfcp_adapter *adapter = fsf_req->adapter;
-	unsigned long flags;
-
-	write_lock_irqsave(&adapter->fsf_req_list_lock, flags);
-	list_del(&fsf_req->list);
-	write_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
-	zfcp_fsf_req_free(fsf_req);
-}
-
 #undef ZFCP_LOG_AREA
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index 06e862d..24e16ec 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -229,52 +229,14 @@
 			ZFCP_LOG_TRACE("status is"
 				       " QDIO_STATUS_OUTBOUND_INT \n");
 		}
-	}			// if (ZFCP_LOG_CHECK(ZFCP_LOG_LEVEL_TRACE))
+	}
 	if (unlikely(status & QDIO_STATUS_LOOK_FOR_ERROR)) {
 		retval = -EIO;
 
-		ZFCP_LOG_FLAGS(1, "QDIO_STATUS_LOOK_FOR_ERROR \n");
-
 		ZFCP_LOG_INFO("QDIO problem occurred (status=0x%x, "
 			      "qdio_error=0x%x, siga_error=0x%x)\n",
 			      status, qdio_error, siga_error);
 
-		if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION) {
-			ZFCP_LOG_FLAGS(2,
-				       "QDIO_STATUS_ACTIVATE_CHECK_CONDITION\n");
-		}
-		if (status & QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR) {
-			ZFCP_LOG_FLAGS(2,
-				       "QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR\n");
-		}
-		if (status & QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR) {
-			ZFCP_LOG_FLAGS(2,
-				       "QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR\n");
-		}
-
-		if (siga_error & QDIO_SIGA_ERROR_ACCESS_EXCEPTION) {
-			ZFCP_LOG_FLAGS(2, "QDIO_SIGA_ERROR_ACCESS_EXCEPTION\n");
-		}
-
-		if (siga_error & QDIO_SIGA_ERROR_B_BIT_SET) {
-			ZFCP_LOG_FLAGS(2, "QDIO_SIGA_ERROR_B_BIT_SET\n");
-		}
-
-		switch (qdio_error) {
-		case 0:
-			ZFCP_LOG_FLAGS(3, "QDIO_OK");
-			break;
-		case SLSB_P_INPUT_ERROR:
-			ZFCP_LOG_FLAGS(1, "SLSB_P_INPUT_ERROR\n");
-			break;
-		case SLSB_P_OUTPUT_ERROR:
-			ZFCP_LOG_FLAGS(1, "SLSB_P_OUTPUT_ERROR\n");
-			break;
-		default:
-			ZFCP_LOG_NORMAL("bug: unknown QDIO error 0x%x\n",
-					qdio_error);
-			break;
-		}
 		/* Restarting IO on the failed adapter from scratch */
 		debug_text_event(adapter->erp_dbf, 1, "qdio_err");
                /*
@@ -484,37 +446,37 @@
 zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr)
 {
 	struct zfcp_fsf_req *fsf_req;
-	int retval = 0;
 
 	/* invalid (per convention used in this driver) */
 	if (unlikely(!sbale_addr)) {
 		ZFCP_LOG_NORMAL("bug: invalid reqid\n");
-		retval = -EINVAL;
-		goto out;
+		return -EINVAL;
 	}
 
 	/* valid request id and thus (hopefully :) valid fsf_req address */
 	fsf_req = (struct zfcp_fsf_req *) sbale_addr;
 
+	/* serialize with zfcp_fsf_req_dismiss_all */
+	spin_lock(&adapter->fsf_req_list_lock);
+	if (list_empty(&adapter->fsf_req_list_head)) {
+		spin_unlock(&adapter->fsf_req_list_lock);
+		return 0;
+	}
+	list_del(&fsf_req->list);
+	atomic_dec(&adapter->fsf_reqs_active);
+	spin_unlock(&adapter->fsf_req_list_lock);
+	
 	if (unlikely(adapter != fsf_req->adapter)) {
 		ZFCP_LOG_NORMAL("bug: invalid reqid (fsf_req=%p, "
 				"fsf_req->adapter=%p, adapter=%p)\n",
 				fsf_req, fsf_req->adapter, adapter);
-		retval = -EINVAL;
-		goto out;
-	}
-
-	ZFCP_LOG_TRACE("fsf_req at %p, QTCB at %p\n", fsf_req, fsf_req->qtcb);
-	if (likely(fsf_req->qtcb)) {
-		ZFCP_LOG_TRACE("hex dump of QTCB:\n");
-		ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) fsf_req->qtcb,
-			      sizeof(struct fsf_qtcb));
+		return -EINVAL;
 	}
 
 	/* finish the FSF request */
 	zfcp_fsf_req_complete(fsf_req);
- out:
-	return retval;
+
+	return 0;
 }
 
 /**
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index e21b547..b61d309 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -433,7 +433,7 @@
  *		FAILED	- otherwise
  */
 int
-zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
+__zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
 {
 	int retval = SUCCESS;
 	struct zfcp_fsf_req *new_fsf_req, *old_fsf_req;
@@ -575,7 +575,7 @@
 	    *(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[0];
 	dbf_fsf_qual[1] =
 	    *(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[2];
-	zfcp_fsf_req_cleanup(new_fsf_req);
+	zfcp_fsf_req_free(new_fsf_req);
 #else
 	retval = zfcp_fsf_req_wait_and_cleanup(new_fsf_req,
 					       ZFCP_UNINTERRUPTIBLE, &status);
@@ -611,6 +611,17 @@
 	return retval;
 }
 
+int
+zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
+{
+	int rc;
+	struct Scsi_Host *scsi_host = scpnt->device->host;
+	spin_lock_irq(scsi_host->host_lock);
+	rc = __zfcp_scsi_eh_abort_handler(scpnt);
+	spin_unlock_irq(scsi_host->host_lock);
+	return rc;
+}
+
 /*
  * function:	zfcp_scsi_eh_device_reset_handler
  *
@@ -625,8 +636,6 @@
 	struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata;
 	struct Scsi_Host *scsi_host = scpnt->device->host;
 
-	spin_unlock_irq(scsi_host->host_lock);
-
 	if (!unit) {
 		ZFCP_LOG_NORMAL("bug: Tried reset for nonexistent unit\n");
 		retval = SUCCESS;
@@ -669,7 +678,6 @@
 		retval = SUCCESS;
 	}
  out:
-	spin_lock_irq(scsi_host->host_lock);
 	return retval;
 }
 
@@ -723,8 +731,6 @@
 	struct zfcp_unit *unit;
 	struct Scsi_Host *scsi_host = scpnt->device->host;
 
-	spin_unlock_irq(scsi_host->host_lock);
-
 	unit = (struct zfcp_unit *) scpnt->device->hostdata;
 	ZFCP_LOG_NORMAL("bus reset because of problems with "
 			"unit 0x%016Lx\n", unit->fcp_lun);
@@ -732,7 +738,6 @@
 	zfcp_erp_wait(unit->port->adapter);
 	retval = SUCCESS;
 
-	spin_lock_irq(scsi_host->host_lock);
 	return retval;
 }
 
@@ -750,8 +755,6 @@
 	struct zfcp_unit *unit;
 	struct Scsi_Host *scsi_host = scpnt->device->host;
 
-	spin_unlock_irq(scsi_host->host_lock);
-
 	unit = (struct zfcp_unit *) scpnt->device->hostdata;
 	ZFCP_LOG_NORMAL("host reset because of problems with "
 			"unit 0x%016Lx\n", unit->fcp_lun);
@@ -759,7 +762,6 @@
 	zfcp_erp_wait(unit->port->adapter);
 	retval = SUCCESS;
 
-	spin_lock_irq(scsi_host->host_lock);
 	return retval;
 }
 
@@ -922,7 +924,7 @@
  * Generates attribute for a unit.
  */
 #define ZFCP_DEFINE_SCSI_ATTR(_name, _format, _value)                    \
-static ssize_t zfcp_sysfs_scsi_##_name##_show(struct device *dev,        \
+static ssize_t zfcp_sysfs_scsi_##_name##_show(struct device *dev, struct device_attribute *attr,        \
                                               char *buf)                 \
 {                                                                        \
         struct scsi_device *sdev;                                        \
diff --git a/drivers/s390/scsi/zfcp_sysfs_adapter.c b/drivers/s390/scsi/zfcp_sysfs_adapter.c
index 23e2dca..e7345a7 100644
--- a/drivers/s390/scsi/zfcp_sysfs_adapter.c
+++ b/drivers/s390/scsi/zfcp_sysfs_adapter.c
@@ -50,7 +50,7 @@
  * Generates attributes for an adapter.
  */
 #define ZFCP_DEFINE_ADAPTER_ATTR(_name, _format, _value)                      \
-static ssize_t zfcp_sysfs_adapter_##_name##_show(struct device *dev,          \
+static ssize_t zfcp_sysfs_adapter_##_name##_show(struct device *dev, struct device_attribute *attr,          \
 						 char *buf)                   \
 {                                                                             \
 	struct zfcp_adapter *adapter;                                         \
@@ -90,7 +90,7 @@
  * Store function of the "port_add" attribute of an adapter.
  */
 static ssize_t
-zfcp_sysfs_port_add_store(struct device *dev, const char *buf, size_t count)
+zfcp_sysfs_port_add_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	wwn_t wwpn;
 	char *endp;
@@ -135,7 +135,7 @@
  * Store function of the "port_remove" attribute of an adapter.
  */
 static ssize_t
-zfcp_sysfs_port_remove_store(struct device *dev, const char *buf, size_t count)
+zfcp_sysfs_port_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct zfcp_adapter *adapter;
 	struct zfcp_port *port;
@@ -196,7 +196,7 @@
  * started for the belonging adapter.
  */
 static ssize_t
-zfcp_sysfs_adapter_failed_store(struct device *dev,
+zfcp_sysfs_adapter_failed_store(struct device *dev, struct device_attribute *attr,
 				const char *buf, size_t count)
 {
 	struct zfcp_adapter *adapter;
@@ -236,7 +236,7 @@
  * "0" if adapter is working, otherwise "1".
  */
 static ssize_t
-zfcp_sysfs_adapter_failed_show(struct device *dev, char *buf)
+zfcp_sysfs_adapter_failed_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct zfcp_adapter *adapter;
 
diff --git a/drivers/s390/scsi/zfcp_sysfs_port.c b/drivers/s390/scsi/zfcp_sysfs_port.c
index 6aafb2a..7a84c7d 100644
--- a/drivers/s390/scsi/zfcp_sysfs_port.c
+++ b/drivers/s390/scsi/zfcp_sysfs_port.c
@@ -53,7 +53,7 @@
  * Generates attributes for a port.
  */
 #define ZFCP_DEFINE_PORT_ATTR(_name, _format, _value)                    \
-static ssize_t zfcp_sysfs_port_##_name##_show(struct device *dev,        \
+static ssize_t zfcp_sysfs_port_##_name##_show(struct device *dev, struct device_attribute *attr,        \
                                               char *buf)                 \
 {                                                                        \
         struct zfcp_port *port;                                          \
@@ -82,7 +82,7 @@
  * Store function of the "unit_add" attribute of a port.
  */
 static ssize_t
-zfcp_sysfs_unit_add_store(struct device *dev, const char *buf, size_t count)
+zfcp_sysfs_unit_add_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	fcp_lun_t fcp_lun;
 	char *endp;
@@ -125,7 +125,7 @@
  * @count: number of bytes in buffer
  */
 static ssize_t
-zfcp_sysfs_unit_remove_store(struct device *dev, const char *buf, size_t count)
+zfcp_sysfs_unit_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct zfcp_port *port;
 	struct zfcp_unit *unit;
@@ -186,7 +186,7 @@
  * started for the belonging port.
  */
 static ssize_t
-zfcp_sysfs_port_failed_store(struct device *dev, const char *buf, size_t count)
+zfcp_sysfs_port_failed_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct zfcp_port *port;
 	unsigned int val;
@@ -224,7 +224,7 @@
  * "0" if port is working, otherwise "1".
  */
 static ssize_t
-zfcp_sysfs_port_failed_show(struct device *dev, char *buf)
+zfcp_sysfs_port_failed_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct zfcp_port *port;
 
diff --git a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c
index 87c0b46..0556642 100644
--- a/drivers/s390/scsi/zfcp_sysfs_unit.c
+++ b/drivers/s390/scsi/zfcp_sysfs_unit.c
@@ -53,7 +53,7 @@
  * Generates attribute for a unit.
  */
 #define ZFCP_DEFINE_UNIT_ATTR(_name, _format, _value)                    \
-static ssize_t zfcp_sysfs_unit_##_name##_show(struct device *dev,        \
+static ssize_t zfcp_sysfs_unit_##_name##_show(struct device *dev, struct device_attribute *attr,        \
                                               char *buf)                 \
 {                                                                        \
         struct zfcp_unit *unit;                                          \
@@ -86,7 +86,7 @@
  * started for the belonging unit.
  */
 static ssize_t
-zfcp_sysfs_unit_failed_store(struct device *dev, const char *buf, size_t count)
+zfcp_sysfs_unit_failed_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct zfcp_unit *unit;
 	unsigned int val;
@@ -123,7 +123,7 @@
  * "0" if unit is working, otherwise "1".
  */
 static ssize_t
-zfcp_sysfs_unit_failed_show(struct device *dev, char *buf)
+zfcp_sysfs_unit_failed_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct zfcp_unit *unit;
 
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index a2b18f5..34dbc37 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -1695,8 +1695,6 @@
 
 	tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
 
-	spin_unlock_irq(tw_dev->host->host_lock);
-
 	tw_dev->num_resets++;
 
 	printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Unit #%d: Command (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, TW_DRIVER, 0x2c, SCpnt->device->id, SCpnt->cmnd[0]);
@@ -1709,7 +1707,6 @@
 
 	retval = SUCCESS;
 out:
-	spin_lock_irq(tw_dev->host->host_lock);
 	return retval;
 } /* End twa_scsi_eh_reset() */
 
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 48f9ece..b6dc576 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -1430,8 +1430,6 @@
 
 	tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
 
-	spin_unlock_irq(tw_dev->host->host_lock);
-
 	tw_dev->num_resets++;
 
 	printk(KERN_WARNING "3w-xxxx: scsi%d: WARNING: Unit #%d: Command (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, SCpnt->device->id, SCpnt->cmnd[0]);
@@ -1444,7 +1442,6 @@
 
 	retval = SUCCESS;
 out:
-	spin_lock_irq(tw_dev->host->host_lock);
 	return retval;
 } /* End tw_scsi_eh_reset() */
 
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index 4b1bb52..a7620fc 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -170,7 +170,6 @@
 STATIC int NCR_700_queuecommand(struct scsi_cmnd *, void (*done)(struct scsi_cmnd *));
 STATIC int NCR_700_abort(struct scsi_cmnd * SCpnt);
 STATIC int NCR_700_bus_reset(struct scsi_cmnd * SCpnt);
-STATIC int NCR_700_dev_reset(struct scsi_cmnd * SCpnt);
 STATIC int NCR_700_host_reset(struct scsi_cmnd * SCpnt);
 STATIC void NCR_700_chip_setup(struct Scsi_Host *host);
 STATIC void NCR_700_chip_reset(struct Scsi_Host *host);
@@ -330,7 +329,6 @@
 	/* Fill in the missing routines from the host template */
 	tpnt->queuecommand = NCR_700_queuecommand;
 	tpnt->eh_abort_handler = NCR_700_abort;
-	tpnt->eh_device_reset_handler = NCR_700_dev_reset;
 	tpnt->eh_bus_reset_handler = NCR_700_bus_reset;
 	tpnt->eh_host_reset_handler = NCR_700_host_reset;
 	tpnt->can_queue = NCR_700_COMMAND_SLOTS_PER_HOST;
@@ -1959,34 +1957,31 @@
 	printk(KERN_INFO "scsi%d (%d:%d) New error handler wants BUS reset, cmd %p\n\t",
 	       SCp->device->host->host_no, SCp->device->id, SCp->device->lun, SCp);
 	scsi_print_command(SCp);
+
 	/* In theory, eh_complete should always be null because the
 	 * eh is single threaded, but just in case we're handling a
 	 * reset via sg or something */
-	while(hostdata->eh_complete != NULL) {
+	spin_lock_irq(SCp->device->host->host_lock);
+	while (hostdata->eh_complete != NULL) {
 		spin_unlock_irq(SCp->device->host->host_lock);
 		msleep_interruptible(100);
 		spin_lock_irq(SCp->device->host->host_lock);
 	}
+
 	hostdata->eh_complete = &complete;
 	NCR_700_internal_bus_reset(SCp->device->host);
+
 	spin_unlock_irq(SCp->device->host->host_lock);
 	wait_for_completion(&complete);
 	spin_lock_irq(SCp->device->host->host_lock);
+
 	hostdata->eh_complete = NULL;
 	/* Revalidate the transport parameters of the failing device */
 	if(hostdata->fast)
 		spi_schedule_dv_device(SCp->device);
-	return SUCCESS;
-}
 
-STATIC int
-NCR_700_dev_reset(struct scsi_cmnd * SCp)
-{
-	printk(KERN_INFO "scsi%d (%d:%d) New error handler wants device reset\n\t",
-	       SCp->device->host->host_no, SCp->device->id, SCp->device->lun);
-	scsi_print_command(SCp);
-	
-	return FAILED;
+	spin_unlock_irq(SCp->device->host->host_lock);
+	return SUCCESS;
 }
 
 STATIC int
@@ -1996,8 +1991,13 @@
 	       SCp->device->host->host_no, SCp->device->id, SCp->device->lun);
 	scsi_print_command(SCp);
 
+	spin_lock_irq(SCp->device->host->host_lock);
+
 	NCR_700_internal_bus_reset(SCp->device->host);
 	NCR_700_chip_reset(SCp->device->host);
+
+	spin_unlock_irq(SCp->device->host->host_lock);
+
 	return SUCCESS;
 }
 
@@ -2125,7 +2125,7 @@
 }
 
 static ssize_t
-NCR_700_show_active_tags(struct device *dev, char *buf)
+NCR_700_show_active_tags(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct scsi_device *SDp = to_scsi_device(dev);
 
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index 15e4b12..9d6040b 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -2746,9 +2746,15 @@
 
 	unsigned int id = SCpnt->device->id;
 	struct BusLogic_TargetStatistics *stats = &HostAdapter->TargetStatistics[id];
+	int rc;
+
+	spin_lock_irq(SCpnt->device->host->host_lock);
+
 	BusLogic_IncrementErrorCounter(&stats->HostAdapterResetsRequested);
 
-	return BusLogic_ResetHostAdapter(HostAdapter, false);
+	rc = BusLogic_ResetHostAdapter(HostAdapter, false);
+	spin_unlock_irq(SCpnt->device->host->host_lock);
+	return rc;
 }
 
 /*
diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c
index 56a695c..5beed4f 100644
--- a/drivers/scsi/FlashPoint.c
+++ b/drivers/scsi/FlashPoint.c
@@ -22,8 +22,6 @@
 #ifndef CONFIG_SCSI_OMIT_FLASHPOINT
 
 
-#define UNIX
-#define FW_TYPE		_SCCB_MGR_
 #define MAX_CARDS	8
 #undef BUSTYPE_PCI
 
@@ -34,8 +32,6 @@
 #define OS_OutPortByte(port, value)	outb(value, port)
 #define OS_OutPortWord(port, value)	outw(value, port)
 #define OS_OutPortLong(port, value)	outl(value, port)
-#define OS_Lock(x)
-#define OS_UnLock(x)
 
 
 /*
@@ -51,164 +47,17 @@
 #define SccbMgr_isr			FlashPoint_HandleInterrupt
 
 
-/*
-  Define name replacements to avoid kernel namespace pollution.
-*/
-
-#define BL_Card				FPT_BL_Card
-#define BusMasterInit			FPT_BusMasterInit
-#define CalcCrc16			FPT_CalcCrc16
-#define CalcLrc				FPT_CalcLrc
-#define ChkIfChipInitialized		FPT_ChkIfChipInitialized
-#define DiagBusMaster			FPT_DiagBusMaster
-#define DiagEEPROM			FPT_DiagEEPROM
-#define DiagXbow			FPT_DiagXbow
-#define GetTarLun			FPT_GetTarLun
-#define RNVRamData			FPT_RNVRamData
-#define RdStack				FPT_RdStack
-#define SccbMgrTableInitAll		FPT_SccbMgrTableInitAll
-#define SccbMgrTableInitCard		FPT_SccbMgrTableInitCard
-#define SccbMgrTableInitTarget		FPT_SccbMgrTableInitTarget
-#define SccbMgr_bad_isr			FPT_SccbMgr_bad_isr
-#define SccbMgr_scsi_reset		FPT_SccbMgr_scsi_reset
-#define SccbMgr_timer_expired		FPT_SccbMgr_timer_expired
-#define SendMsg				FPT_SendMsg
-#define Wait				FPT_Wait
-#define Wait1Second			FPT_Wait1Second
-#define WrStack				FPT_WrStack
-#define XbowInit			FPT_XbowInit
-#define autoCmdCmplt			FPT_autoCmdCmplt
-#define autoLoadDefaultMap		FPT_autoLoadDefaultMap
-#define busMstrDataXferStart		FPT_busMstrDataXferStart
-#define busMstrSGDataXferStart		FPT_busMstrSGDataXferStart
-#define busMstrTimeOut			FPT_busMstrTimeOut
-#define dataXferProcessor		FPT_dataXferProcessor
-#define default_intena			FPT_default_intena
-#define hostDataXferAbort		FPT_hostDataXferAbort
-#define hostDataXferRestart		FPT_hostDataXferRestart
-#define inisci				FPT_inisci
-#define mbCards				FPT_mbCards
-#define nvRamInfo			FPT_nvRamInfo
-#define phaseBusFree			FPT_phaseBusFree
-#define phaseChkFifo			FPT_phaseChkFifo
-#define phaseCommand			FPT_phaseCommand
-#define phaseDataIn			FPT_phaseDataIn
-#define phaseDataOut			FPT_phaseDataOut
-#define phaseDecode			FPT_phaseDecode
-#define phaseIllegal			FPT_phaseIllegal
-#define phaseMsgIn			FPT_phaseMsgIn
-#define phaseMsgOut			FPT_phaseMsgOut
-#define phaseStatus			FPT_phaseStatus
-#define queueAddSccb			FPT_queueAddSccb
-#define queueCmdComplete		FPT_queueCmdComplete
-#define queueDisconnect			FPT_queueDisconnect
-#define queueFindSccb			FPT_queueFindSccb
-#define queueFlushSccb			FPT_queueFlushSccb
-#define queueFlushTargSccb		FPT_queueFlushTargSccb
-#define queueSearchSelect		FPT_queueSearchSelect
-#define queueSelectFail			FPT_queueSelectFail
-#define s_PhaseTbl			FPT_s_PhaseTbl
-#define scamHAString			FPT_scamHAString
-#define scamInfo			FPT_scamInfo
-#define scarb				FPT_scarb
-#define scasid				FPT_scasid
-#define scbusf				FPT_scbusf
-#define sccbMgrTbl			FPT_sccbMgrTbl
-#define schkdd				FPT_schkdd
-#define scini				FPT_scini
-#define sciso				FPT_sciso
-#define scmachid			FPT_scmachid
-#define scsavdi				FPT_scsavdi
-#define scsel				FPT_scsel
-#define scsell				FPT_scsell
-#define scsendi				FPT_scsendi
-#define scvalq				FPT_scvalq
-#define scwirod				FPT_scwirod
-#define scwiros				FPT_scwiros
-#define scwtsel				FPT_scwtsel
-#define scxferc				FPT_scxferc
-#define sdecm				FPT_sdecm
-#define sfm				FPT_sfm
-#define shandem				FPT_shandem
-#define sinits				FPT_sinits
-#define sisyncn				FPT_sisyncn
-#define sisyncr				FPT_sisyncr
-#define siwidn				FPT_siwidn
-#define siwidr				FPT_siwidr
-#define sres				FPT_sres
-#define sresb				FPT_sresb
-#define ssel				FPT_ssel
-#define ssenss				FPT_ssenss
-#define sssyncv				FPT_sssyncv
-#define stsyncn				FPT_stsyncn
-#define stwidn				FPT_stwidn
-#define sxfrp				FPT_sxfrp
-#define utilEERead			FPT_utilEERead
-#define utilEEReadOrg			FPT_utilEEReadOrg
-#define utilEESendCmdAddr		FPT_utilEESendCmdAddr
-#define utilEEWrite			FPT_utilEEWrite
-#define utilEEWriteOnOff		FPT_utilEEWriteOnOff
-#define utilUpdateResidual		FPT_utilUpdateResidual
-
-
-/*----------------------------------------------------------------------
- *
- *
- *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
- *
- *   This file is available under both the GNU General Public License
- *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- *   $Workfile:   globals.h  $
- *
- *   Description:  Common shared global defines.
- *
- *   $Date: 1996/09/04 01:26:13 $
- *
- *   $Revision: 1.11 $
- *
- *----------------------------------------------------------------------*/
-#ifndef __GLOBALS_H__
-#define __GLOBALS_H__
-
-#define _UCB_MGR_  1
-#define _SCCB_MGR_ 2
-
-/*#include <osflags.h>*/
-
 #define MAX_CDBLEN  12
 
 #define SCAM_LEV_2	1
 
 #define CRCMASK	0xA001
 
-/*  In your osflags.h file, please ENSURE that only ONE OS FLAG 
-    is on at a time !!! Also, please make sure you turn set the 
- 	 variable FW_TYPE to either _UCB_MGR_ or _SCCB_MGR_  !!! */
-
-#if defined(DOS) || defined(WIN95_16) || defined(OS2) || defined(OTHER_16)
-   #define       COMPILER_16_BIT 1
-#elif defined(NETWARE) || defined(NT) || defined(WIN95_32) || defined(UNIX) || defined(OTHER_32) || defined(SOLARIS_REAL_MODE)
-   #define       COMPILER_32_BIT 1
-#endif
-
-
 #define     BL_VENDOR_ID      0x104B
 #define     FP_DEVICE_ID      0x8130
 #define     MM_DEVICE_ID      0x1040
 
 
-#ifndef FALSE
-#define FALSE           0
-#endif
-#ifndef TRUE
-#define TRUE            (!(FALSE))
-#endif
-
-#ifndef NULL
-#define NULL            0
-#endif
-
 #define FAILURE         0xFFFFFFFFL
 
 
@@ -222,27 +71,11 @@
 typedef void *          PVOID;
 
 
-#if defined(COMPILER_16_BIT)
-typedef unsigned char far       * uchar_ptr;
-typedef unsigned short far      * ushort_ptr;
-typedef unsigned long far       * ulong_ptr;
-#endif  /* 16_BIT_COMPILER */
-
-#if defined(COMPILER_32_BIT)
 typedef unsigned char           * uchar_ptr;
 typedef unsigned short          * ushort_ptr;
 typedef unsigned long           * ulong_ptr;
-#endif  /* 32_BIT_COMPILER */
 
 
-/*	 			NEW TYPE DEFINITIONS (shared with Mylex North)
-
-**  Use following type defines to avoid confusion in 16 and 32-bit
-**  environments.  Avoid using 'int' as it denotes 16 bits in 16-bit
-**  environment and 32 in 32-bit environments.
-
-*/
-
 #define s08bits	char
 #define s16bits 	short
 #define s32bits	long
@@ -251,195 +84,19 @@
 #define u16bits	unsigned s16bits
 #define u32bits	unsigned s32bits
 
-#if defined(COMPILER_16_BIT)
-
-typedef u08bits far 	* pu08bits;
-typedef u16bits far 	* pu16bits;
-typedef u32bits far	* pu32bits;
-
-#endif	/* COMPILER_16_BIT */
-
-#if defined(COMPILER_32_BIT)
-
 typedef u08bits 	* pu08bits;
 typedef u16bits 	* pu16bits;
 typedef u32bits 	* pu32bits;
 
-#endif	/* COMPILER_32_BIT */
-
 
 #define BIT(x)          ((UCHAR)(1<<(x)))    /* single-bit mask in bit position x */
 #define BITW(x)          ((USHORT)(1<<(x)))  /* single-bit mask in bit position x */
 
 
 
-#if defined(DOS)
-/*#include <dos.h>*/
-	#undef inportb          /* undefine for Borland Lib */
-	#undef inport           /* they may have define I/O function in LIB */
-	#undef outportb
-	#undef outport
 
-	#define OS_InPortByte(ioport) 		inportb(ioport)
-	#define OS_InPortWord(ioport) 		inport(ioport)
-	#define OS_InPortLong(ioport)			inportq(ioport, val)
-	#define OS_OutPortByte(ioport, val) outportb(ioport, val)
-	#define OS_OutPortWord(ioport, val)	outport(ioport, val)
-	#define OS_OutPortLong(ioport)		outportq(ioport, val)
-#endif	/* DOS */
-
-#if defined(NETWARE) || defined(OTHER_32) ||  defined(OTHER_16)
-	extern u08bits	OS_InPortByte(u32bits ioport);
-	extern u16bits	OS_InPortWord(u32bits ioport);
-	extern u32bits	OS_InPortLong(u32bits ioport);
-
-	extern OS_InPortByteBuffer(u32bits ioport, pu08bits buffer, u32bits count);
-	extern OS_InPortWordBuffer(u32bits ioport, pu16bits buffer, u32bits count);
-	extern OS_OutPortByte(u32bits ioport, u08bits val);
-	extern OS_OutPortWord(u32bits ioport, u16bits val);
-	extern OS_OutPortLong(u32bits ioport, u32bits val);
-	extern OS_OutPortByteBuffer(u32bits ioport, pu08bits buffer, u32bits count);
-	extern OS_OutPortWordBuffer(u32bits ioport, pu16bits buffer, u32bits count);
-#endif	/* NETWARE || OTHER_32 || OTHER_16 */
-
-#if defined (NT) || defined(WIN95_32) || defined(WIN95_16)
-	#if defined(NT)
-
-		extern __declspec(dllimport) u08bits ScsiPortReadPortUchar(pu08bits ioport);
-		extern __declspec(dllimport) u16bits ScsiPortReadPortUshort(pu16bits ioport);
-		extern __declspec(dllimport) u32bits ScsiPortReadPortUlong(pu32bits ioport);
-		extern __declspec(dllimport) void ScsiPortWritePortUchar(pu08bits ioport, u08bits val);
-		extern __declspec(dllimport) void ScsiPortWritePortUshort(pu16bits port, u16bits val);
-		extern __declspec(dllimport) void ScsiPortWritePortUlong(pu32bits port, u32bits val);
-
-	#else
-
-		extern u08bits ScsiPortReadPortUchar(pu08bits ioport);
-		extern u16bits ScsiPortReadPortUshort(pu16bits ioport);
-		extern u32bits ScsiPortReadPortUlong(pu32bits ioport);
-		extern void ScsiPortWritePortUchar(pu08bits ioport, u08bits val);
-		extern void ScsiPortWritePortUshort(pu16bits port, u16bits val);
-		extern void ScsiPortWritePortUlong(pu32bits port, u32bits val);
-	#endif
-
-
-	#define OS_InPortByte(ioport) ScsiPortReadPortUchar((pu08bits) ioport)
-	#define OS_InPortWord(ioport) ScsiPortReadPortUshort((pu16bits) ioport)
-	#define OS_InPortLong(ioport) ScsiPortReadPortUlong((pu32bits) ioport)
-
-	#define OS_OutPortByte(ioport, val) ScsiPortWritePortUchar((pu08bits) ioport, (u08bits) val)
-	#define OS_OutPortWord(ioport, val) ScsiPortWritePortUshort((pu16bits) ioport, (u16bits) val)
-	#define OS_OutPortLong(ioport, val) ScsiPortWritePortUlong((pu32bits) ioport, (u32bits) val)
-	#define OS_OutPortByteBuffer(ioport, buffer, count) \
-		ScsiPortWritePortBufferUchar((pu08bits)&port, (pu08bits) buffer, (u32bits) count)
-	#define OS_OutPortWordBuffer(ioport, buffer, count) \
-		ScsiPortWritePortBufferUshort((pu16bits)&port, (pu16bits) buffer, (u32bits) count)
-
-	#define OS_Lock(x)
-	#define OS_UnLock(x)
-#endif /* NT || WIN95_32 || WIN95_16 */
-
-#if defined (UNIX) && !defined(OS_InPortByte)
-	#define OS_InPortByte(ioport)    inb((u16bits)ioport)
-	#define OS_InPortWord(ioport)    inw((u16bits)ioport)
-	#define OS_InPortLong(ioport)    inl((u16bits)ioport)
-	#define OS_OutPortByte(ioport,val)  outb((u16bits)ioport, (u08bits)val)
-	#define OS_OutPortWord(ioport,val)  outw((u16bits)ioport, (u16bits)val)
-	#define OS_OutPortLong(ioport,val)  outl((u16bits)ioport, (u32bits)val)
-
-	#define OS_Lock(x)
-	#define OS_UnLock(x)
-#endif /* UNIX */
-
-
-#if defined(OS2)
-	extern u08bits	inb(u32bits ioport);
-	extern u16bits	inw(u32bits ioport);
-	extern void	outb(u32bits ioport, u08bits val);
-	extern void	outw(u32bits ioport, u16bits val);
-
-	#define OS_InPortByte(ioport)			inb(ioport)
-	#define OS_InPortWord(ioport)			inw(ioport)
-	#define OS_OutPortByte(ioport, val)	outb(ioport, val)
-	#define OS_OutPortWord(ioport, val)	outw(ioport, val)
-	extern u32bits	OS_InPortLong(u32bits ioport);
-	extern void	OS_OutPortLong(u32bits ioport, u32bits val);
-
-	#define OS_Lock(x)
-	#define OS_UnLock(x)
-#endif /* OS2 */
-
-#if defined(SOLARIS_REAL_MODE)
-
-extern unsigned char    inb(unsigned long ioport);
-extern unsigned short   inw(unsigned long ioport);
-
-#define OS_InPortByte(ioport)    inb(ioport)
-#define OS_InPortWord(ioport)    inw(ioport)
-
-extern void OS_OutPortByte(unsigned long ioport, unsigned char val);
-extern void OS_OutPortWord(unsigned long ioport, unsigned short val);
-extern unsigned long  OS_InPortLong(unsigned long ioport);
-extern void     OS_OutPortLong(unsigned long ioport, unsigned long val);
-
-#define OS_Lock(x)
-#define OS_UnLock(x)
-
-#endif  /* SOLARIS_REAL_MODE */
-
-#endif  /* __GLOBALS_H__ */
-
-/*----------------------------------------------------------------------
- *
- *
- *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
- *
- *   This file is available under both the GNU General Public License
- *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- *   $Workfile:   sccbmgr.h  $
- *
- *   Description:  Common shared SCCB Interface defines and SCCB 
- *						 Manager specifics defines.
- *
- *   $Date: 1996/10/24 23:09:33 $
- *
- *   $Revision: 1.14 $
- *
- *----------------------------------------------------------------------*/
-
-#ifndef __SCCB_H__
-#define __SCCB_H__
-
-/*#include <osflags.h>*/
-/*#include <globals.h>*/
-
-#if defined(BUGBUG)
-#define debug_size 32
-#endif
-
-#if defined(DOS)
-
-   typedef struct _SCCB near *PSCCB;
-	#if (FW_TYPE == _SCCB_MGR_)
-   	typedef void (*CALL_BK_FN)(PSCCB);
-	#endif
-
-#elif defined(OS2)
-
-   typedef struct _SCCB far *PSCCB;
-	#if (FW_TYPE == _SCCB_MGR_)
-   	typedef void (far *CALL_BK_FN)(PSCCB);
-	#endif
-
-#else
-
-   typedef struct _SCCB *PSCCB;
-	#if (FW_TYPE == _SCCB_MGR_)
-   	typedef void (*CALL_BK_FN)(PSCCB);
-	#endif
-
-#endif
+typedef struct _SCCB *PSCCB;
+typedef void (*CALL_BK_FN)(PSCCB);
 
 
 typedef struct SCCBMgr_info {
@@ -466,25 +123,13 @@
    ULONG    si_secondary_range;
 } SCCBMGR_INFO;
 
-#if defined(DOS)
-   typedef SCCBMGR_INFO *      PSCCBMGR_INFO;
-#else
-   #if defined (COMPILER_16_BIT)
-   typedef SCCBMGR_INFO far *  PSCCBMGR_INFO;
-   #else
-   typedef SCCBMGR_INFO *      PSCCBMGR_INFO;
-   #endif
-#endif // defined(DOS)
+typedef SCCBMGR_INFO *      PSCCBMGR_INFO;
 
 
-
-
-#if (FW_TYPE==_SCCB_MGR_)
-	#define SCSI_PARITY_ENA		  0x0001
-	#define LOW_BYTE_TERM		  0x0010
-	#define HIGH_BYTE_TERM		  0x0020
-	#define BUSTYPE_PCI	  0x3
-#endif
+#define SCSI_PARITY_ENA		  0x0001
+#define LOW_BYTE_TERM		  0x0010
+#define HIGH_BYTE_TERM		  0x0020
+#define BUSTYPE_PCI	  0x3
 
 #define SUPPORT_16TAR_32LUN	  0x0002
 #define SOFT_RESET		  0x0004
@@ -553,9 +198,6 @@
    UCHAR   Save_CdbLen;
    UCHAR   Sccb_XferState;
    ULONG   Sccb_SGoffset;
-#if (FW_TYPE == _UCB_MGR_)
-   PUCB    Sccb_ucb_ptr;
-#endif
    } SCCB;
 
 #define SCCB_SIZE sizeof(SCCB)
@@ -626,25 +268,9 @@
 
 
 
-#if (FW_TYPE==_UCB_MGR_)  
-   #define  HBA_AUTO_SENSE_FAIL        0x1B  
-   #define  HBA_TQ_REJECTED            0x1C  
-   #define  HBA_UNSUPPORTED_MSG         0x1D  
-   #define  HBA_HW_ERROR               0x20  
-   #define  HBA_ATN_NOT_RESPONDED      0x21  
-   #define  HBA_SCSI_RESET_BY_ADAPTER  0x22
-   #define  HBA_SCSI_RESET_BY_TARGET   0x23
-   #define  HBA_WRONG_CONNECTION       0x24
-   #define  HBA_BUS_DEVICE_RESET       0x25
-   #define  HBA_ABORT_QUEUE            0x26
-
-#else // these are not defined in BUDI/UCB
-
-   #define SCCB_INVALID_DIRECTION      0x18  /* Invalid target direction */
-   #define SCCB_DUPLICATE_SCCB         0x19  /* Duplicate SCCB */
-   #define SCCB_SCSI_RST               0x35  /* SCSI RESET detected. */
-
-#endif // (FW_TYPE==_UCB_MGR_)  
+#define SCCB_INVALID_DIRECTION      0x18  /* Invalid target direction */
+#define SCCB_DUPLICATE_SCCB         0x19  /* Duplicate SCCB */
+#define SCCB_SCSI_RST               0x35  /* SCSI RESET detected. */
 
 
 #define SCCB_IN_PROCESS            0x00
@@ -657,115 +283,20 @@
 #define SCCB_SIZE sizeof(SCCB)
 
 
-
-
-#if (FW_TYPE == _UCB_MGR_)
-	void SccbMgr_start_sccb(CARD_HANDLE pCurrCard, PUCB p_ucb);
-	s32bits SccbMgr_abort_sccb(CARD_HANDLE pCurrCard, PUCB p_ucb);
-	u08bits SccbMgr_my_int(CARD_HANDLE pCurrCard);
-	s32bits SccbMgr_isr(CARD_HANDLE pCurrCard);
-	void SccbMgr_scsi_reset(CARD_HANDLE pCurrCard);
-	void SccbMgr_timer_expired(CARD_HANDLE pCurrCard);
-	void SccbMgr_unload_card(CARD_HANDLE pCurrCard);
-	void SccbMgr_restore_foreign_state(CARD_HANDLE pCurrCard);
-	void SccbMgr_restore_native_state(CARD_HANDLE pCurrCard);
-	void SccbMgr_save_foreign_state(PADAPTER_INFO pAdapterInfo);
-
-#endif
-
-
-#if (FW_TYPE == _SCCB_MGR_)
-
- #if defined (DOS)
-	int    SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo);
-	USHORT SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo);
-	void  SccbMgr_start_sccb(USHORT pCurrCard, PSCCB p_SCCB);
-	int   SccbMgr_abort_sccb(USHORT pCurrCard, PSCCB p_SCCB);
-	UCHAR SccbMgr_my_int(USHORT pCurrCard);
-	int   SccbMgr_isr(USHORT pCurrCard);
-	void  SccbMgr_scsi_reset(USHORT pCurrCard);
-	void  SccbMgr_timer_expired(USHORT pCurrCard);
-	USHORT SccbMgr_status(USHORT pCurrCard);
-	void SccbMgr_unload_card(USHORT pCurrCard);
-
- #else    //non-DOS
-
-	int   SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo);
-	ULONG SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo);
-	void  SccbMgr_start_sccb(ULONG pCurrCard, PSCCB p_SCCB);
-	int   SccbMgr_abort_sccb(ULONG pCurrCard, PSCCB p_SCCB);
-	UCHAR SccbMgr_my_int(ULONG pCurrCard);
-	int   SccbMgr_isr(ULONG pCurrCard);
-	void  SccbMgr_scsi_reset(ULONG pCurrCard);
-	void  SccbMgr_enable_int(ULONG pCurrCard);
-	void  SccbMgr_disable_int(ULONG pCurrCard);
-	void  SccbMgr_timer_expired(ULONG pCurrCard);
-	void SccbMgr_unload_card(ULONG pCurrCard);
-
-  #endif
-#endif  // (FW_TYPE == _SCCB_MGR_)
-
-#endif  /* __SCCB_H__ */
-
-/*----------------------------------------------------------------------
- *
- *
- *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
- *
- *   This file is available under both the GNU General Public License
- *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- *   $Workfile:   blx30.h  $
- *
- *   Description: This module contains SCCB/UCB Manager implementation
- *                specific stuff.
- *
- *   $Date: 1996/11/13 18:34:22 $
- *
- *   $Revision: 1.10 $
- *
- *----------------------------------------------------------------------*/
-
-
-#ifndef __blx30_H__
-#define __blx30_H__
-
-/*#include <globals.h>*/
-
 #define  ORION_FW_REV      3110
 
-
-
-
 #define HARP_REVD    1
 
 
-#if defined(DOS)
-#define QUEUE_DEPTH     8+1            /*1 for Normal disconnect 0 for Q'ing. */
-#else
 #define QUEUE_DEPTH     254+1            /*1 for Normal disconnect 32 for Q'ing. */
-#endif   // defined(DOS)
 
 #define	MAX_MB_CARDS	4					/* Max. no of cards suppoerted on Mother Board */
 
 #define WIDE_SCSI       1
 
-#if defined(WIDE_SCSI)
-   #if defined(DOS)
-      #define MAX_SCSI_TAR    16
-      #define MAX_LUN         8
-		#define LUN_MASK			0x07
-   #else
-      #define MAX_SCSI_TAR    16
-      #define MAX_LUN         32
-		#define LUN_MASK			0x1f
-	
-   #endif
-#else
-   #define MAX_SCSI_TAR    8
-   #define MAX_LUN         8
-	#define LUN_MASK			0x07
-#endif 
+#define MAX_SCSI_TAR    16
+#define MAX_LUN         32
+#define LUN_MASK			0x1f
 
 #if defined(HARP_REVA)
 #define SG_BUF_CNT      15             /*Number of prefetched elements. */
@@ -778,116 +309,12 @@
 #define SG_ELEMENT_MASK 0xFFFFFFFFL
 
 
-#if (FW_TYPE == _UCB_MGR_)
-	#define OPC_DECODE_NORMAL       0x0f7f
-#endif   // _UCB_MGR_
-
-
-
-#if defined(DOS)
-
-/*#include <dos.h>*/
-	#define RD_HARPOON(ioport)          (OS_InPortByte(ioport))
-	#define RDW_HARPOON(ioport)         (OS_InPortWord(ioport))
-	#define WR_HARPOON(ioport,val)      (OS_OutPortByte(ioport,val))
-	#define WRW_HARPOON(ioport,val)     (OS_OutPortWord(ioport,val))
-
-	#define RD_HARP32(port,offset,data)  asm{db 66h;         \
-                                       push ax;             \
-                                       mov dx,port;         \
-                                       add dx, offset;      \
-                                       db 66h;              \
-                                       in ax,dx;            \
-                                       db 66h;              \
-                                       mov word ptr data,ax;\
-                                       db 66h;              \
-                                       pop ax}
-
-	#define WR_HARP32(port,offset,data) asm{db 66h;          \
-                                       push ax;             \
-                                       mov dx,port;         \
-                                       add dx, offset;      \
-                                       db 66h;              \
-                                       mov ax,word ptr data;\
-                                       db 66h;              \
-                                       out dx,ax;           \
-                                       db 66h;              \
-                                       pop ax}
-#endif	/* DOS */
-
-#if defined(NETWARE) || defined(OTHER_32) ||  defined(OTHER_16)
-	#define RD_HARPOON(ioport)     OS_InPortByte((unsigned long)ioport)
-	#define RDW_HARPOON(ioport)    OS_InPortWord((unsigned long)ioport)
-	#define RD_HARP32(ioport,offset,data) (data = OS_InPortLong(ioport + offset))
-	#define WR_HARPOON(ioport,val) OS_OutPortByte((ULONG)ioport,(UCHAR) val)
-	#define WRW_HARPOON(ioport,val)  OS_OutPortWord((ULONG)ioport,(USHORT)val)
-	#define WR_HARP32(ioport,offset,data)  OS_OutPortLong((ioport + offset), data)
-#endif	/* NETWARE || OTHER_32 || OTHER_16 */
-
-#if defined(NT) || defined(WIN95_32) || defined(WIN95_16)
-	#define RD_HARPOON(ioport)          OS_InPortByte((ULONG)ioport)
-	#define RDW_HARPOON(ioport)         OS_InPortWord((ULONG)ioport)
-	#define RD_HARP32(ioport,offset,data) (data = OS_InPortLong((ULONG)(ioport + offset)))
-	#define WR_HARPOON(ioport,val)      OS_OutPortByte((ULONG)ioport,(UCHAR) val)
-	#define WRW_HARPOON(ioport,val)     OS_OutPortWord((ULONG)ioport,(USHORT)val)
-	#define WR_HARP32(ioport,offset,data)  OS_OutPortLong((ULONG)(ioport + offset), data)
-#endif /* NT || WIN95_32 || WIN95_16 */
-
-#if defined (UNIX)
-	#define RD_HARPOON(ioport)          OS_InPortByte((u32bits)ioport)
-	#define RDW_HARPOON(ioport)         OS_InPortWord((u32bits)ioport)
-	#define RD_HARP32(ioport,offset,data) (data = OS_InPortLong((u32bits)(ioport + offset)))
-	#define WR_HARPOON(ioport,val)      OS_OutPortByte((u32bits)ioport,(u08bits) val)
-	#define WRW_HARPOON(ioport,val)       OS_OutPortWord((u32bits)ioport,(u16bits)val)
-	#define WR_HARP32(ioport,offset,data)  OS_OutPortLong((u32bits)(ioport + offset), data)
-#endif /* UNIX */
-
-#if defined(OS2)
-	#define RD_HARPOON(ioport)          OS_InPortByte((unsigned long)ioport)
-	#define RDW_HARPOON(ioport)         OS_InPortWord((unsigned long)ioport)
-	#define RD_HARP32(ioport,offset,data) (data = OS_InPortLong((ULONG)(ioport + offset)))
-	#define WR_HARPOON(ioport,val)      OS_OutPortByte((ULONG)ioport,(UCHAR) val)
-	#define WRW_HARPOON(ioport,val)       OS_OutPortWord((ULONG)ioport,(USHORT)val)
-	#define WR_HARP32(ioport,offset,data)  OS_OutPortLong(((ULONG)(ioport + offset)), data)
-#endif /* OS2 */
-
-#if defined(SOLARIS_REAL_MODE)
-
-	#define RD_HARPOON(ioport)          OS_InPortByte((unsigned long)ioport)
-	#define RDW_HARPOON(ioport)         OS_InPortWord((unsigned long)ioport)
-	#define RD_HARP32(ioport,offset,data) (data = OS_InPortLong((ULONG)(ioport + offset)))
-	#define WR_HARPOON(ioport,val)      OS_OutPortByte((ULONG)ioport,(UCHAR) val)
-	#define WRW_HARPOON(ioport,val)       OS_OutPortWord((ULONG)ioport,(USHORT)val)
-	#define WR_HARP32(ioport,offset,data)  OS_OutPortLong((ULONG)(ioport + offset), (ULONG)data)
-
-#endif  /* SOLARIS_REAL_MODE */
-
-#endif  /* __BLX30_H__ */
-
-
-/*----------------------------------------------------------------------
- * 
- *
- *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
- *
- *   This file is available under both the GNU General Public License
- *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- *   $Workfile:   target.h  $
- *
- *   Description:  Definitions for Target related structures
- *
- *   $Date: 1996/12/11 22:06:20 $
- *
- *   $Revision: 1.9 $
- *
- *----------------------------------------------------------------------*/
-
-#ifndef __TARGET__
-#define __TARGET__
-
-/*#include <globals.h>*/
-/*#include <blx30.h>*/
+#define RD_HARPOON(ioport)          OS_InPortByte((u32bits)ioport)
+#define RDW_HARPOON(ioport)         OS_InPortWord((u32bits)ioport)
+#define RD_HARP32(ioport,offset,data) (data = OS_InPortLong((u32bits)(ioport + offset)))
+#define WR_HARPOON(ioport,val)      OS_OutPortByte((u32bits)ioport,(u08bits) val)
+#define WRW_HARPOON(ioport,val)       OS_OutPortWord((u32bits)ioport,(u16bits)val)
+#define WR_HARP32(ioport,offset,data)  OS_OutPortLong((u32bits)(ioport + offset), data)
 
 
 #define  TAR_SYNC_MASK     (BIT(7)+BIT(6))
@@ -919,16 +346,7 @@
 #define  EE_WIDE_SCSI      BIT(7)
 
 
-#if defined(DOS)
-   typedef struct SCCBMgr_tar_info near *PSCCBMgr_tar_info;
-
-#elif defined(OS2)
-   typedef struct SCCBMgr_tar_info far *PSCCBMgr_tar_info;
-
-#else
-   typedef struct SCCBMgr_tar_info *PSCCBMgr_tar_info;
-
-#endif
+typedef struct SCCBMgr_tar_info *PSCCBMgr_tar_info;
 
 
 typedef struct SCCBMgr_tar_info {
@@ -949,11 +367,7 @@
 typedef struct NVRAMInfo {
 	UCHAR		niModel;								/* Model No. of card */
 	UCHAR		niCardNo;							/* Card no. */
-#if defined(DOS)
-	USHORT	niBaseAddr;							/* Port Address of card */
-#else
 	ULONG		niBaseAddr;							/* Port Address of card */
-#endif
 	UCHAR		niSysConf;							/* Adapter Configuration byte - Byte 16 of eeprom map */
 	UCHAR		niScsiConf;							/* SCSI Configuration byte - Byte 17 of eeprom map */
 	UCHAR		niScamConf;							/* SCAM Configuration byte - Byte 20 of eeprom map */
@@ -962,13 +376,7 @@
 	UCHAR		niScamTbl[MAX_SCSI_TAR][4];	/* Compressed Scam name string of Targets */
 }NVRAMINFO;
 
-#if defined(DOS)
-typedef NVRAMINFO near *PNVRamInfo;
-#elif defined (OS2)
-typedef NVRAMINFO far *PNVRamInfo;
-#else
 typedef NVRAMINFO *PNVRamInfo;
-#endif
 
 #define	MODEL_LT		1
 #define	MODEL_DL		2
@@ -978,17 +386,9 @@
 
 typedef struct SCCBcard {
    PSCCB currentSCCB;
-#if (FW_TYPE==_SCCB_MGR_)
    PSCCBMGR_INFO cardInfo;
-#else
-   PADAPTER_INFO cardInfo;
-#endif
 
-#if defined(DOS)
-   USHORT ioPort;
-#else
    ULONG ioPort;
-#endif
 
    USHORT cmdCounter;
    UCHAR  discQCount;
@@ -1002,13 +402,7 @@
       
 }SCCBCARD;
 
-#if defined(DOS)
-typedef struct SCCBcard near *PSCCBcard;
-#elif defined (OS2)
-typedef struct SCCBcard far *PSCCBcard;
-#else
 typedef struct SCCBcard *PSCCBcard;
-#endif
 
 
 #define F_TAG_STARTED		0x01
@@ -1063,29 +457,6 @@
     
 } SCCBSCAM_INFO, *PSCCBSCAM_INFO;
 
-#endif
-/*----------------------------------------------------------------------
- *
- *
- *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
- *
- *   This file is available under both the GNU General Public License
- *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- *   $Workfile:   scsi2.h  $
- *
- *   Description:  Register definitions for HARPOON ASIC.
- *
- *   $Date: 1996/11/13 18:32:57 $
- *
- *   $Revision: 1.4 $
- *
- *----------------------------------------------------------------------*/
-
-#ifndef __SCSI_H__
-#define __SCSI_H__
-
-
 
 #define  SCSI_TEST_UNIT_READY    0x00
 #define  SCSI_REZERO_UNIT        0x01
@@ -1195,29 +566,6 @@
 #define  SYNC5MBS                0x32
 #define  MAX_OFFSET              0x0F  /* Maxbyteoffset for Sync Xfers */
 
-#endif
-/*----------------------------------------------------------------------
- *  
- *
- *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
- *
- *   This file is available under both the GNU General Public License
- *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- *   $Workfile:   eeprom.h  $
- *
- *   Description:  Definitions for EEPROM related structures
- *
- *   $Date: 1996/11/13 18:28:39 $
- *
- *   $Revision: 1.4 $
- *
- *----------------------------------------------------------------------*/
-
-#ifndef __EEPROM__
-#define __EEPROM__
-
-/*#include <globals.h>*/
 
 #define  EEPROM_WD_CNT     256
 
@@ -1280,31 +628,6 @@
    #define  DISC_ENABLE_BIT   BIT(6)
 
 
-#endif
-/*----------------------------------------------------------------------
- *
- *
- *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
- *
- *   This file is available under both the GNU General Public License
- *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- *   $Workfile:   harpoon.h  $
- *
- *   Description:  Register definitions for HARPOON ASIC.
- *
- *   $Date: 1997/07/09 21:44:36 $
- *
- *   $Revision: 1.9 $
- *
- *----------------------------------------------------------------------*/
-
-
-/*#include <globals.h>*/
-
-#ifndef __HARPOON__
-#define __HARPOON__
-
 
    #define  hp_vendor_id_0       0x00		/* LSB */
       #define  ORION_VEND_0   0x4B
@@ -1578,8 +901,6 @@
 
 
 
-   extern USHORT default_intena;
-
    #define  hp_intena		 0x40
 
       #define  RESET		 BITW(7)
@@ -1972,15 +1293,6 @@
                                  xfercnt <<= 16,\
                                  xfercnt |= RDW_HARPOON((USHORT)(port+hp_xfercnt_0)))
  */
-#if defined(DOS)
-#define HP_SETUP_ADDR_CNT(port,addr,count) (WRW_HARPOON((USHORT)(port+hp_host_addr_lo), (USHORT)(addr & 0x0000FFFFL)),\
-         addr >>= 16,\
-         WRW_HARPOON((USHORT)(port+hp_host_addr_hmi), (USHORT)(addr & 0x0000FFFFL)),\
-         WR_HARP32(port,hp_xfercnt_0,count),\
-         WRW_HARPOON((USHORT)(port+hp_xfer_cnt_lo), (USHORT)(count & 0x0000FFFFL)),\
-         count >>= 16,\
-         WR_HARPOON(port+hp_xfer_cnt_hi, (count & 0xFF)))
-#else
 #define HP_SETUP_ADDR_CNT(port,addr,count) (WRW_HARPOON((port+hp_host_addr_lo), (USHORT)(addr & 0x0000FFFFL)),\
          addr >>= 16,\
          WRW_HARPOON((port+hp_host_addr_hmi), (USHORT)(addr & 0x0000FFFFL)),\
@@ -1988,7 +1300,6 @@
          WRW_HARPOON((port+hp_xfer_cnt_lo), (USHORT)(count & 0x0000FFFFL)),\
          count >>= 16,\
          WR_HARPOON(port+hp_xfer_cnt_hi, (count & 0xFF)))
-#endif
 
 #define ACCEPT_MSG(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
                           WR_HARPOON(port+hp_scsisig, S_ILL_PH);}
@@ -2020,383 +1331,145 @@
 
 
 
-#endif
 
-
-#if (FW_TYPE==_UCB_MGR_)
-void ReadNVRam(PSCCBcard pCurrCard,PUCB p_ucb);
-void WriteNVRam(PSCCBcard pCurrCard,PUCB p_ucb);
-void UpdateCheckSum(u32bits baseport);
-#endif // (FW_TYPE==_UCB_MGR_)
-
-#if defined(DOS)
-UCHAR sfm(USHORT port, PSCCB pcurrSCCB);
-void  scsiStartAuto(USHORT port);
-UCHAR sisyncn(USHORT port, UCHAR p_card, UCHAR syncFlag);
-void  ssel(USHORT port, UCHAR p_card);
-void  sres(USHORT port, UCHAR p_card, PSCCBcard pCurrCard);
-void  sdecm(UCHAR message, USHORT port, UCHAR p_card);
-void  shandem(USHORT port, UCHAR p_card,PSCCB pCurrSCCB);
-void  stsyncn(USHORT port, UCHAR p_card);
-void  sisyncr(USHORT port,UCHAR sync_pulse, UCHAR offset);
-void  sssyncv(USHORT p_port, UCHAR p_id, UCHAR p_sync_value, PSCCBMgr_tar_info currTar_Info);
-void  sresb(USHORT port, UCHAR p_card);
-void  sxfrp(USHORT p_port, UCHAR p_card);
-void  schkdd(USHORT port, UCHAR p_card);
-UCHAR RdStack(USHORT port, UCHAR index);
-void  WrStack(USHORT portBase, UCHAR index, UCHAR data);
-UCHAR ChkIfChipInitialized(USHORT ioPort);
-
-#if defined(V302)
-UCHAR GetTarLun(USHORT port, UCHAR p_card, UCHAR our_target, PSCCBcard pCurrCard, PUCHAR tag, PUCHAR lun);
-#endif
-
-void SendMsg(USHORT port, UCHAR message);
-void  queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg, UCHAR error_code);
-UCHAR scsellDOS(USHORT p_port, UCHAR targ_id);
-#else
-UCHAR sfm(ULONG port, PSCCB pcurrSCCB);
 void  scsiStartAuto(ULONG port);
-UCHAR sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag);
-void  ssel(ULONG port, UCHAR p_card);
-void  sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard);
-void  sdecm(UCHAR message, ULONG port, UCHAR p_card);
-void  shandem(ULONG port, UCHAR p_card,PSCCB pCurrSCCB);
-void  stsyncn(ULONG port, UCHAR p_card);
-void  sisyncr(ULONG port,UCHAR sync_pulse, UCHAR offset);
-void  sssyncv(ULONG p_port, UCHAR p_id, UCHAR p_sync_value, PSCCBMgr_tar_info currTar_Info);
-void  sresb(ULONG port, UCHAR p_card);
-void  sxfrp(ULONG p_port, UCHAR p_card);
-void  schkdd(ULONG port, UCHAR p_card);
-UCHAR RdStack(ULONG port, UCHAR index);
-void  WrStack(ULONG portBase, UCHAR index, UCHAR data);
-UCHAR ChkIfChipInitialized(ULONG ioPort);
+static UCHAR FPT_sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag);
+static void  FPT_ssel(ULONG port, UCHAR p_card);
+static void  FPT_sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard);
+static void  FPT_shandem(ULONG port, UCHAR p_card,PSCCB pCurrSCCB);
+static void  FPT_stsyncn(ULONG port, UCHAR p_card);
+static void  FPT_sisyncr(ULONG port,UCHAR sync_pulse, UCHAR offset);
+static void  FPT_sssyncv(ULONG p_port, UCHAR p_id, UCHAR p_sync_value,
+			 PSCCBMgr_tar_info currTar_Info);
+static void  FPT_sresb(ULONG port, UCHAR p_card);
+static void  FPT_sxfrp(ULONG p_port, UCHAR p_card);
+static void  FPT_schkdd(ULONG port, UCHAR p_card);
+static UCHAR FPT_RdStack(ULONG port, UCHAR index);
+static void  FPT_WrStack(ULONG portBase, UCHAR index, UCHAR data);
+static UCHAR FPT_ChkIfChipInitialized(ULONG ioPort);
 
-#if defined(V302)
-UCHAR GetTarLun(ULONG port, UCHAR p_card, UCHAR our_target, PSCCBcard pCurrCard, PUCHAR tar, PUCHAR lun);
-#endif
+static void FPT_SendMsg(ULONG port, UCHAR message);
+static void  FPT_queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg,
+				    UCHAR error_code);
 
-void SendMsg(ULONG port, UCHAR message);
-void  queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg, UCHAR error_code);
-#endif
+static void  FPT_sinits(PSCCB p_sccb, UCHAR p_card);
+static void  FPT_RNVRamData(PNVRamInfo pNvRamInfo);
 
-void  ssenss(PSCCBcard pCurrCard);
-void  sinits(PSCCB p_sccb, UCHAR p_card);
-void  RNVRamData(PNVRamInfo pNvRamInfo);
-
-#if defined(WIDE_SCSI)
-   #if defined(DOS)
-   UCHAR siwidn(USHORT port, UCHAR p_card);
-   void  stwidn(USHORT port, UCHAR p_card);
-   void  siwidr(USHORT port, UCHAR width);
-   #else
-   UCHAR siwidn(ULONG port, UCHAR p_card);
-   void  stwidn(ULONG port, UCHAR p_card);
-   void  siwidr(ULONG port, UCHAR width);
-   #endif
-#endif
+static UCHAR FPT_siwidn(ULONG port, UCHAR p_card);
+static void  FPT_stwidn(ULONG port, UCHAR p_card);
+static void  FPT_siwidr(ULONG port, UCHAR width);
 
 
-void  queueSelectFail(PSCCBcard pCurrCard, UCHAR p_card);
-void  queueDisconnect(PSCCB p_SCCB, UCHAR p_card);
-void  queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_SCCB, UCHAR p_card);
-void  queueSearchSelect(PSCCBcard pCurrCard, UCHAR p_card);
-void  queueFlushSccb(UCHAR p_card, UCHAR error_code);
-void  queueAddSccb(PSCCB p_SCCB, UCHAR card);
-UCHAR queueFindSccb(PSCCB p_SCCB, UCHAR p_card);
-void  utilUpdateResidual(PSCCB p_SCCB);
-USHORT CalcCrc16(UCHAR buffer[]);
-UCHAR  CalcLrc(UCHAR buffer[]);
+static void  FPT_queueSelectFail(PSCCBcard pCurrCard, UCHAR p_card);
+static void  FPT_queueDisconnect(PSCCB p_SCCB, UCHAR p_card);
+static void  FPT_queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_SCCB,
+				  UCHAR p_card);
+static void  FPT_queueSearchSelect(PSCCBcard pCurrCard, UCHAR p_card);
+static void  FPT_queueFlushSccb(UCHAR p_card, UCHAR error_code);
+static void  FPT_queueAddSccb(PSCCB p_SCCB, UCHAR card);
+static UCHAR FPT_queueFindSccb(PSCCB p_SCCB, UCHAR p_card);
+static void  FPT_utilUpdateResidual(PSCCB p_SCCB);
+static USHORT FPT_CalcCrc16(UCHAR buffer[]);
+static UCHAR  FPT_CalcLrc(UCHAR buffer[]);
 
 
-#if defined(DOS)
-void  Wait1Second(USHORT p_port);
-void  Wait(USHORT p_port, UCHAR p_delay);
-void  utilEEWriteOnOff(USHORT p_port,UCHAR p_mode);
-void  utilEEWrite(USHORT p_port, USHORT ee_data, USHORT ee_addr);
-USHORT utilEERead(USHORT p_port, USHORT ee_addr);
-USHORT utilEEReadOrg(USHORT p_port, USHORT ee_addr);
-void  utilEESendCmdAddr(USHORT p_port, UCHAR ee_cmd, USHORT ee_addr);
-#else
-void  Wait1Second(ULONG p_port);
-void  Wait(ULONG p_port, UCHAR p_delay);
-void  utilEEWriteOnOff(ULONG p_port,UCHAR p_mode);
-void  utilEEWrite(ULONG p_port, USHORT ee_data, USHORT ee_addr);
-USHORT utilEERead(ULONG p_port, USHORT ee_addr);
-USHORT utilEEReadOrg(ULONG p_port, USHORT ee_addr);
-void  utilEESendCmdAddr(ULONG p_port, UCHAR ee_cmd, USHORT ee_addr);
-#endif
+static void  FPT_Wait1Second(ULONG p_port);
+static void  FPT_Wait(ULONG p_port, UCHAR p_delay);
+static void  FPT_utilEEWriteOnOff(ULONG p_port,UCHAR p_mode);
+static void  FPT_utilEEWrite(ULONG p_port, USHORT ee_data, USHORT ee_addr);
+static USHORT FPT_utilEERead(ULONG p_port, USHORT ee_addr);
+static USHORT FPT_utilEEReadOrg(ULONG p_port, USHORT ee_addr);
+static void  FPT_utilEESendCmdAddr(ULONG p_port, UCHAR ee_cmd, USHORT ee_addr);
 
 
 
-#if defined(OS2)
-   void  far phaseDataOut(ULONG port, UCHAR p_card);
-   void  far phaseDataIn(ULONG port, UCHAR p_card);
-   void  far phaseCommand(ULONG port, UCHAR p_card);
-   void  far phaseStatus(ULONG port, UCHAR p_card);
-   void  far phaseMsgOut(ULONG port, UCHAR p_card);
-   void  far phaseMsgIn(ULONG port, UCHAR p_card);
-   void  far phaseIllegal(ULONG port, UCHAR p_card);
-#else
-   #if defined(DOS)
-      void  phaseDataOut(USHORT port, UCHAR p_card);
-      void  phaseDataIn(USHORT port, UCHAR p_card);
-      void  phaseCommand(USHORT port, UCHAR p_card);
-      void  phaseStatus(USHORT port, UCHAR p_card);
-      void  phaseMsgOut(USHORT port, UCHAR p_card);
-      void  phaseMsgIn(USHORT port, UCHAR p_card);
-      void  phaseIllegal(USHORT port, UCHAR p_card);
-   #else
-      void  phaseDataOut(ULONG port, UCHAR p_card);
-      void  phaseDataIn(ULONG port, UCHAR p_card);
-      void  phaseCommand(ULONG port, UCHAR p_card);
-      void  phaseStatus(ULONG port, UCHAR p_card);
-      void  phaseMsgOut(ULONG port, UCHAR p_card);
-      void  phaseMsgIn(ULONG port, UCHAR p_card);
-      void  phaseIllegal(ULONG port, UCHAR p_card);
-   #endif
-#endif
+static void  FPT_phaseDataOut(ULONG port, UCHAR p_card);
+static void  FPT_phaseDataIn(ULONG port, UCHAR p_card);
+static void  FPT_phaseCommand(ULONG port, UCHAR p_card);
+static void  FPT_phaseStatus(ULONG port, UCHAR p_card);
+static void  FPT_phaseMsgOut(ULONG port, UCHAR p_card);
+static void  FPT_phaseMsgIn(ULONG port, UCHAR p_card);
+static void  FPT_phaseIllegal(ULONG port, UCHAR p_card);
 
-#if defined(DOS)
-void  phaseDecode(USHORT port, UCHAR p_card);
-void  phaseChkFifo(USHORT port, UCHAR p_card);
-void  phaseBusFree(USHORT p_port, UCHAR p_card);
-#else
-void  phaseDecode(ULONG port, UCHAR p_card);
-void  phaseChkFifo(ULONG port, UCHAR p_card);
-void  phaseBusFree(ULONG p_port, UCHAR p_card);
-#endif
+static void  FPT_phaseDecode(ULONG port, UCHAR p_card);
+static void  FPT_phaseChkFifo(ULONG port, UCHAR p_card);
+static void  FPT_phaseBusFree(ULONG p_port, UCHAR p_card);
 
 
 
 
-#if defined(DOS)
-void  XbowInit(USHORT port, UCHAR scamFlg);
-void  BusMasterInit(USHORT p_port);
-int   DiagXbow(USHORT port);
-int   DiagBusMaster(USHORT port);
-void  DiagEEPROM(USHORT p_port);
-#else
-void  XbowInit(ULONG port, UCHAR scamFlg);
-void  BusMasterInit(ULONG p_port);
-int   DiagXbow(ULONG port);
-int   DiagBusMaster(ULONG port);
-void  DiagEEPROM(ULONG p_port);
-#endif
+static void  FPT_XbowInit(ULONG port, UCHAR scamFlg);
+static void  FPT_BusMasterInit(ULONG p_port);
+static void  FPT_DiagEEPROM(ULONG p_port);
 
 
 
 
-#if defined(DOS)
-void  busMstrAbort(USHORT port);
-UCHAR busMstrTimeOut(USHORT port);
-void  dataXferProcessor(USHORT port, PSCCBcard pCurrCard);
-void  busMstrSGDataXferStart(USHORT port, PSCCB pCurrSCCB);
-void  busMstrDataXferStart(USHORT port, PSCCB pCurrSCCB);
-void  hostDataXferAbort(USHORT port, UCHAR p_card, PSCCB pCurrSCCB);
-#else
 void  busMstrAbort(ULONG port);
-UCHAR busMstrTimeOut(ULONG port);
-void  dataXferProcessor(ULONG port, PSCCBcard pCurrCard);
-void  busMstrSGDataXferStart(ULONG port, PSCCB pCurrSCCB);
-void  busMstrDataXferStart(ULONG port, PSCCB pCurrSCCB);
-void  hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB);
-#endif
-void  hostDataXferRestart(PSCCB currSCCB);
+static void  FPT_dataXferProcessor(ULONG port, PSCCBcard pCurrCard);
+static void  FPT_busMstrSGDataXferStart(ULONG port, PSCCB pCurrSCCB);
+static void  FPT_busMstrDataXferStart(ULONG port, PSCCB pCurrSCCB);
+static void  FPT_hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB);
+static void  FPT_hostDataXferRestart(PSCCB currSCCB);
 
 
-#if defined (DOS)
-UCHAR SccbMgr_bad_isr(USHORT p_port, UCHAR p_card, PSCCBcard pCurrCard, USHORT p_int);
-#else
-UCHAR SccbMgr_bad_isr(ULONG p_port, UCHAR p_card, PSCCBcard pCurrCard, USHORT p_int);
+static UCHAR FPT_SccbMgr_bad_isr(ULONG p_port, UCHAR p_card,
+				 PSCCBcard pCurrCard, USHORT p_int);
 
-#endif
-
-void  SccbMgrTableInitAll(void);
-void  SccbMgrTableInitCard(PSCCBcard pCurrCard, UCHAR p_card);
-void  SccbMgrTableInitTarget(UCHAR p_card, UCHAR target);
+static void  FPT_SccbMgrTableInitAll(void);
+static void  FPT_SccbMgrTableInitCard(PSCCBcard pCurrCard, UCHAR p_card);
+static void  FPT_SccbMgrTableInitTarget(UCHAR p_card, UCHAR target);
 
 
 
-void  scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up);
+static void  FPT_scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up);
 
-#if defined(DOS)
-int   scarb(USHORT p_port, UCHAR p_sel_type);
-void  scbusf(USHORT p_port);
-void  scsel(USHORT p_port);
-void  scasid(UCHAR p_card, USHORT p_port);
-UCHAR scxferc(USHORT p_port, UCHAR p_data);
-UCHAR scsendi(USHORT p_port, UCHAR p_id_string[]);
-UCHAR sciso(USHORT p_port, UCHAR p_id_string[]);
-void  scwirod(USHORT p_port, UCHAR p_data_bit);
-void  scwiros(USHORT p_port, UCHAR p_data_bit);
-UCHAR scvalq(UCHAR p_quintet);
-UCHAR scsell(USHORT p_port, UCHAR targ_id);
-void  scwtsel(USHORT p_port);
-void  inisci(UCHAR p_card, USHORT p_port, UCHAR p_our_id);
-void  scsavdi(UCHAR p_card, USHORT p_port);
-#else
-int   scarb(ULONG p_port, UCHAR p_sel_type);
-void  scbusf(ULONG p_port);
-void  scsel(ULONG p_port);
-void  scasid(UCHAR p_card, ULONG p_port);
-UCHAR scxferc(ULONG p_port, UCHAR p_data);
-UCHAR scsendi(ULONG p_port, UCHAR p_id_string[]);
-UCHAR sciso(ULONG p_port, UCHAR p_id_string[]);
-void  scwirod(ULONG p_port, UCHAR p_data_bit);
-void  scwiros(ULONG p_port, UCHAR p_data_bit);
-UCHAR scvalq(UCHAR p_quintet);
-UCHAR scsell(ULONG p_port, UCHAR targ_id);
-void  scwtsel(ULONG p_port);
-void  inisci(UCHAR p_card, ULONG p_port, UCHAR p_our_id);
-void  scsavdi(UCHAR p_card, ULONG p_port);
-#endif
-UCHAR scmachid(UCHAR p_card, UCHAR p_id_string[]);
+static int   FPT_scarb(ULONG p_port, UCHAR p_sel_type);
+static void  FPT_scbusf(ULONG p_port);
+static void  FPT_scsel(ULONG p_port);
+static void  FPT_scasid(UCHAR p_card, ULONG p_port);
+static UCHAR FPT_scxferc(ULONG p_port, UCHAR p_data);
+static UCHAR FPT_scsendi(ULONG p_port, UCHAR p_id_string[]);
+static UCHAR FPT_sciso(ULONG p_port, UCHAR p_id_string[]);
+static void  FPT_scwirod(ULONG p_port, UCHAR p_data_bit);
+static void  FPT_scwiros(ULONG p_port, UCHAR p_data_bit);
+static UCHAR FPT_scvalq(UCHAR p_quintet);
+static UCHAR FPT_scsell(ULONG p_port, UCHAR targ_id);
+static void  FPT_scwtsel(ULONG p_port);
+static void  FPT_inisci(UCHAR p_card, ULONG p_port, UCHAR p_our_id);
+static void  FPT_scsavdi(UCHAR p_card, ULONG p_port);
+static UCHAR FPT_scmachid(UCHAR p_card, UCHAR p_id_string[]);
 
 
-#if defined(DOS)
-void  autoCmdCmplt(USHORT p_port, UCHAR p_card);
-void  autoLoadDefaultMap(USHORT p_port);
-#else
-void  autoCmdCmplt(ULONG p_port, UCHAR p_card);
-void  autoLoadDefaultMap(ULONG p_port);
-#endif
+static void  FPT_autoCmdCmplt(ULONG p_port, UCHAR p_card);
+static void  FPT_autoLoadDefaultMap(ULONG p_port);
 
 
 
-#if (FW_TYPE==_SCCB_MGR_)
-	void  OS_start_timer(unsigned long ioport, unsigned long timeout);
-	void  OS_stop_timer(unsigned long ioport, unsigned long timeout);
-	void  OS_disable_int(unsigned char intvec);
-	void  OS_enable_int(unsigned char intvec);
-	void  OS_delay(unsigned long count);
-	int   OS_VirtToPhys(u32bits CardHandle, u32bits *physaddr, u32bits *virtaddr);
-	#if !(defined(UNIX) || defined(OS2) || defined(SOLARIS_REAL_MODE)) 
-	void  OS_Lock(PSCCBMGR_INFO pCardInfo);
-	void  OS_UnLock(PSCCBMGR_INFO pCardInfo);
-#endif // if FW_TYPE == ...
+void  OS_start_timer(unsigned long ioport, unsigned long timeout);
+void  OS_stop_timer(unsigned long ioport, unsigned long timeout);
+void  OS_disable_int(unsigned char intvec);
+void  OS_enable_int(unsigned char intvec);
+void  OS_delay(unsigned long count);
+int   OS_VirtToPhys(u32bits CardHandle, u32bits *physaddr, u32bits *virtaddr);
 
-#endif
-
-extern SCCBCARD BL_Card[MAX_CARDS];
-extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];
+static SCCBMGR_TAR_INFO FPT_sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] = { { { 0 } } };
+static SCCBCARD FPT_BL_Card[MAX_CARDS] = { { 0 } };
+static SCCBSCAM_INFO FPT_scamInfo[MAX_SCSI_TAR] = { { { 0 } } };
+static NVRAMINFO FPT_nvRamInfo[MAX_MB_CARDS] = { { 0 } };
 
 
-#if defined(OS2)
-   extern void (far *s_PhaseTbl[8]) (ULONG, UCHAR);
-#else
-   #if defined(DOS)
-      extern void (*s_PhaseTbl[8]) (USHORT, UCHAR);
-   #else
-      extern void (*s_PhaseTbl[8]) (ULONG, UCHAR);
-   #endif
-#endif
+static UCHAR FPT_mbCards = 0;
+static UCHAR FPT_scamHAString[] = {0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I', 'C', \
+				   ' ', 'B', 'T', '-', '9', '3', '0', \
+				   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, \
+				   0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
 
-extern SCCBSCAM_INFO scamInfo[MAX_SCSI_TAR];
-extern NVRAMINFO nvRamInfo[MAX_MB_CARDS];
-#if defined(DOS) || defined(OS2)
-extern UCHAR temp_id_string[ID_STRING_LENGTH];
-#endif
-extern UCHAR scamHAString[];
+static USHORT FPT_default_intena = 0;
 
 
-extern UCHAR mbCards;
-#if defined(BUGBUG)
-extern UCHAR debug_int[MAX_CARDS][debug_size];
-extern UCHAR debug_index[MAX_CARDS];
-void Debug_Load(UCHAR p_card, UCHAR p_bug_data);
-#endif
+static void (*FPT_s_PhaseTbl[8]) (ULONG, UCHAR)= { 0 };
 
-#if (FW_TYPE==_SCCB_MGR_)
-#if defined(DOS)
-   extern UCHAR first_time;
-#endif
-#endif /* (FW_TYPE==_SCCB_MGR_) */
-
-#if (FW_TYPE==_UCB_MGR_)
-#if defined(DOS)
-   extern u08bits first_time;
-#endif
-#endif /* (FW_TYPE==_UCB_MGR_) */
-
-#if defined(BUGBUG)
-void Debug_Load(UCHAR p_card, UCHAR p_bug_data);
-#endif
-
-extern unsigned int SccbGlobalFlags;
-
-
-#ident "$Id: sccb.c 1.18 1997/06/10 16:47:04 mohan Exp $"
-/*----------------------------------------------------------------------
- *
- *
- *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
- *
- *   This file is available under both the GNU General Public License
- *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- *   $Workfile:   sccb.c  $
- *
- *   Description:  Functions relating to handling of the SCCB interface
- *                 between the device driver and the HARPOON.
- *
- *   $Date: 1997/06/10 16:47:04 $
- *
- *   $Revision: 1.18 $
- *
- *----------------------------------------------------------------------*/
-
-/*#include <globals.h>*/
-
-#if (FW_TYPE==_UCB_MGR_)
-	/*#include <budi.h>*/
-	/*#include <budioctl.h>*/
-#endif
-
-/*#include <sccbmgr.h>*/
-/*#include <blx30.h>*/
-/*#include <target.h>*/
-/*#include <eeprom.h>*/
-/*#include <scsi2.h>*/
-/*#include <harpoon.h>*/
-
-
-
-#if (FW_TYPE==_SCCB_MGR_)
-#define mOS_Lock(card)    OS_Lock((PSCCBMGR_INFO)(((PSCCBcard)card)->cardInfo))
-#define mOS_UnLock(card)  OS_UnLock((PSCCBMGR_INFO)(((PSCCBcard)card)->cardInfo))
-#else /* FW_TYPE==_UCB_MGR_ */
-#define mOS_Lock(card)    OS_Lock((u32bits)(((PSCCBcard)card)->ioPort))
-#define mOS_UnLock(card)  OS_UnLock((u32bits)(((PSCCBcard)card)->ioPort))
-#endif
-
-
-/*
-extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];
-extern SCCBCARD BL_Card[MAX_CARDS];
-
-extern NVRAMINFO nvRamInfo[MAX_MB_CARDS];
-extern UCHAR mbCards;
-
-#if defined (OS2)
-   extern void (far *s_PhaseTbl[8]) (ULONG, UCHAR);
-#else
-   #if defined(DOS)
-      extern void (*s_PhaseTbl[8]) (USHORT, UCHAR);
-   #else
-      extern void (*s_PhaseTbl[8]) (ULONG, UCHAR);
-   #endif
-#endif
-
-
-#if defined(BUGBUG)
-extern UCHAR debug_int[MAX_CARDS][debug_size];
-extern UCHAR debug_index[MAX_CARDS];
-void Debug_Load(UCHAR p_card, UCHAR p_bug_data);
-#endif
-*/
-
-#if (FW_TYPE==_SCCB_MGR_)
 
 /*---------------------------------------------------------------------
  *
@@ -2406,27 +1479,16 @@
  *
  *---------------------------------------------------------------------*/
 
-int SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo)
+static int SccbMgr_sense_adapter(PSCCBMGR_INFO pCardInfo)
 {
-#if defined(DOS)
-#else
    static UCHAR first_time = 1;
-#endif
 
    UCHAR i,j,id,ScamFlg;
    USHORT temp,temp2,temp3,temp4,temp5,temp6;
-#if defined(DOS)
-   USHORT ioport;
-#else
    ULONG ioport;
-#endif
 	PNVRamInfo pCurrNvRam;
 
-#if defined(DOS)
-   ioport = (USHORT)pCardInfo->si_baseaddr;
-#else
    ioport = pCardInfo->si_baseaddr;
-#endif
 
 
    if (RD_HARPOON(ioport+hp_vendor_id_0) != ORION_VEND_0)
@@ -2455,36 +1517,31 @@
 
    if (first_time)
       {
-      SccbMgrTableInitAll();
+      FPT_SccbMgrTableInitAll();
       first_time = 0;
-		mbCards = 0;
+		FPT_mbCards = 0;
       }
 
-	if(RdStack(ioport, 0) != 0x00) {
-		if(ChkIfChipInitialized(ioport) == FALSE)
+	if(FPT_RdStack(ioport, 0) != 0x00) {
+		if(FPT_ChkIfChipInitialized(ioport) == 0)
 		{
 			pCurrNvRam = NULL;
 		   WR_HARPOON(ioport+hp_semaphore, 0x00);
-			XbowInit(ioport, 0);             /*Must Init the SCSI before attempting */
-			DiagEEPROM(ioport);
+			FPT_XbowInit(ioport, 0);             /*Must Init the SCSI before attempting */
+			FPT_DiagEEPROM(ioport);
 		}
 		else
 		{
-			if(mbCards < MAX_MB_CARDS) {
-				pCurrNvRam = &nvRamInfo[mbCards];
-				mbCards++;
+			if(FPT_mbCards < MAX_MB_CARDS) {
+				pCurrNvRam = &FPT_nvRamInfo[FPT_mbCards];
+				FPT_mbCards++;
 				pCurrNvRam->niBaseAddr = ioport;
-				RNVRamData(pCurrNvRam);
+				FPT_RNVRamData(pCurrNvRam);
 			}else
 				return((int) FAILURE);
 		}
 	}else
 		pCurrNvRam = NULL;
-#if defined (NO_BIOS_OPTION)
-	pCurrNvRam = NULL;
-   XbowInit(ioport, 0);                /*Must Init the SCSI before attempting */
-   DiagEEPROM(ioport);
-#endif  /* No BIOS Option */
 
    WR_HARPOON(ioport+hp_clkctrl_0, CLKCTRL_DEFAULT);
    WR_HARPOON(ioport+hp_sys_ctrl, 0x00);
@@ -2492,7 +1549,7 @@
 	if(pCurrNvRam)
 		pCardInfo->si_id = pCurrNvRam->niAdapId;
 	else
-	   pCardInfo->si_id = (UCHAR)(utilEERead(ioport, (ADAPTER_SCSI_ID/2)) &
+	   pCardInfo->si_id = (UCHAR)(FPT_utilEERead(ioport, (ADAPTER_SCSI_ID/2)) &
    	   (UCHAR)0x0FF);
 
    pCardInfo->si_lun = 0x00;
@@ -2510,7 +1567,7 @@
 			temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
 					 (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
 		}else
-	      temp = utilEERead(ioport, (USHORT)((SYNC_RATE_TBL/2)+id));
+	      temp = FPT_utilEERead(ioport, (USHORT)((SYNC_RATE_TBL/2)+id));
 
       for (i = 0; i < 2; temp >>=8,i++) {
 
@@ -2549,12 +1606,12 @@
 	if(pCurrNvRam)
 		i = pCurrNvRam->niSysConf;
 	else
-	   i = (UCHAR)(utilEERead(ioport, (SYSTEM_CONFIG/2)));
+	   i = (UCHAR)(FPT_utilEERead(ioport, (SYSTEM_CONFIG/2)));
 
 	if(pCurrNvRam)
 		ScamFlg = pCurrNvRam->niScamConf;
 	else
-	   ScamFlg = (UCHAR) utilEERead(ioport, SCAM_CONFIG/2);
+	   ScamFlg = (UCHAR) FPT_utilEERead(ioport, SCAM_CONFIG/2);
 
    pCardInfo->si_flags = 0x0000;
 
@@ -2613,9 +1670,9 @@
 				break;
 		}
 	}else{
-	   temp = utilEERead(ioport, (MODEL_NUMB_0/2));
+	   temp = FPT_utilEERead(ioport, (MODEL_NUMB_0/2));
    	pCardInfo->si_card_model[0] = (UCHAR)(temp >> 8);
-	   temp = utilEERead(ioport, (MODEL_NUMB_2/2));
+	   temp = FPT_utilEERead(ioport, (MODEL_NUMB_2/2));
 
    	pCardInfo->si_card_model[1] = (UCHAR)(temp & 0x00FF);
 	   pCardInfo->si_card_model[2] = (UCHAR)(temp >> 8);
@@ -2677,29 +1734,17 @@
 
    SGRAM_ACCESS(ioport);
 
-   s_PhaseTbl[0] = phaseDataOut;
-   s_PhaseTbl[1] = phaseDataIn;
-   s_PhaseTbl[2] = phaseIllegal;
-   s_PhaseTbl[3] = phaseIllegal;
-   s_PhaseTbl[4] = phaseCommand;
-   s_PhaseTbl[5] = phaseStatus;
-   s_PhaseTbl[6] = phaseMsgOut;
-   s_PhaseTbl[7] = phaseMsgIn;
+   FPT_s_PhaseTbl[0] = FPT_phaseDataOut;
+   FPT_s_PhaseTbl[1] = FPT_phaseDataIn;
+   FPT_s_PhaseTbl[2] = FPT_phaseIllegal;
+   FPT_s_PhaseTbl[3] = FPT_phaseIllegal;
+   FPT_s_PhaseTbl[4] = FPT_phaseCommand;
+   FPT_s_PhaseTbl[5] = FPT_phaseStatus;
+   FPT_s_PhaseTbl[6] = FPT_phaseMsgOut;
+   FPT_s_PhaseTbl[7] = FPT_phaseMsgIn;
 
    pCardInfo->si_present = 0x01;
 
-#if defined(BUGBUG)
-
-
-   for (i = 0; i < MAX_CARDS; i++) {
-
-      for (id=0; id<debug_size; id++)
-         debug_int[i][id] =  (UCHAR)0x00;
-      debug_index[i] = 0;
-      }
-
-#endif
-
    return(0);
 }
 
@@ -2712,27 +1757,15 @@
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-USHORT SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo)
-#else
-ULONG SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo)
-#endif
+static ULONG SccbMgr_config_adapter(PSCCBMGR_INFO pCardInfo)
 {
    PSCCBcard CurrCard = NULL;
 	PNVRamInfo pCurrNvRam;
    UCHAR i,j,thisCard, ScamFlg;
    USHORT temp,sync_bit_map,id;
-#if defined(DOS)
-   USHORT ioport;
-#else
    ULONG ioport;
-#endif
 
-#if defined(DOS)
-   ioport = (USHORT)pCardInfo->si_baseaddr;
-#else
    ioport = pCardInfo->si_baseaddr;
-#endif
 
    for(thisCard =0; thisCard <= MAX_CARDS; thisCard++) {
 
@@ -2741,24 +1774,24 @@
 	 return(FAILURE);
          }
 
-      if (BL_Card[thisCard].ioPort == ioport) {
+      if (FPT_BL_Card[thisCard].ioPort == ioport) {
 
-         CurrCard = &BL_Card[thisCard];
-         SccbMgrTableInitCard(CurrCard,thisCard);
+         CurrCard = &FPT_BL_Card[thisCard];
+         FPT_SccbMgrTableInitCard(CurrCard,thisCard);
          break;
          }
 
-      else if (BL_Card[thisCard].ioPort == 0x00) {
+      else if (FPT_BL_Card[thisCard].ioPort == 0x00) {
 
-         BL_Card[thisCard].ioPort = ioport;
-         CurrCard = &BL_Card[thisCard];
+         FPT_BL_Card[thisCard].ioPort = ioport;
+         CurrCard = &FPT_BL_Card[thisCard];
 
-			if(mbCards)
-				for(i = 0; i < mbCards; i++){
-					if(CurrCard->ioPort == nvRamInfo[i].niBaseAddr)
-						CurrCard->pNvRamInfo = &nvRamInfo[i];
+			if(FPT_mbCards)
+				for(i = 0; i < FPT_mbCards; i++){
+					if(CurrCard->ioPort == FPT_nvRamInfo[i].niBaseAddr)
+						CurrCard->pNvRamInfo = &FPT_nvRamInfo[i];
 				}
-         SccbMgrTableInitCard(CurrCard,thisCard);
+         FPT_SccbMgrTableInitCard(CurrCard,thisCard);
          CurrCard->cardIndex = thisCard;
          CurrCard->cardInfo = pCardInfo;
 
@@ -2772,22 +1805,14 @@
 		ScamFlg = pCurrNvRam->niScamConf;
 	}
 	else{
-	   ScamFlg = (UCHAR) utilEERead(ioport, SCAM_CONFIG/2);
+	   ScamFlg = (UCHAR) FPT_utilEERead(ioport, SCAM_CONFIG/2);
 	}
 
 
-   BusMasterInit(ioport);
-   XbowInit(ioport, ScamFlg);
+   FPT_BusMasterInit(ioport);
+   FPT_XbowInit(ioport, ScamFlg);
 
-#if defined (NO_BIOS_OPTION)
-
-
-   if (DiagXbow(ioport)) return(FAILURE);
-   if (DiagBusMaster(ioport)) return(FAILURE);
-
-#endif  /* No BIOS Option */
-
-   autoLoadDefaultMap(ioport);
+   FPT_autoLoadDefaultMap(ioport);
 
 
    for (i = 0,id = 0x01; i != pCardInfo->si_id; i++,id <<= 1){}
@@ -2814,9 +1839,9 @@
 
    if (!(pCardInfo->si_flags & SOFT_RESET)) {
 
-      sresb(ioport,thisCard);
+      FPT_sresb(ioport,thisCard);
 
-         scini(thisCard, pCardInfo->si_id, 0);
+         FPT_scini(thisCard, pCardInfo->si_id, 0);
       }
 
 
@@ -2829,7 +1854,7 @@
 			CurrCard->globalFlags |= F_GREEN_PC;
 	}
 	else{
-	   if (utilEERead(ioport, (SYSTEM_CONFIG/2)) & GREEN_PC_ENA)
+	   if (FPT_utilEERead(ioport, (SYSTEM_CONFIG/2)) & GREEN_PC_ENA)
    	   CurrCard->globalFlags |= F_GREEN_PC;
 	}
 
@@ -2840,7 +1865,7 @@
 			CurrCard->globalFlags |= F_DO_RENEGO;
 	}
 	else{
-	   if (utilEERead(ioport, (SCSI_CONFIG/2)) & RENEGO_ENA)
+	   if (FPT_utilEERead(ioport, (SCSI_CONFIG/2)) & RENEGO_ENA)
    	   CurrCard->globalFlags |= F_DO_RENEGO;
 	}
 
@@ -2849,7 +1874,7 @@
 			CurrCard->globalFlags |= F_CONLUN_IO;
 	}
 	else{
-	   if (utilEERead(ioport, (SCSI_CONFIG/2)) & CONNIO_ENA)
+	   if (FPT_utilEERead(ioport, (SCSI_CONFIG/2)) & CONNIO_ENA)
    	   CurrCard->globalFlags |= F_CONLUN_IO;
 	}
 
@@ -2859,7 +1884,7 @@
    for (i = 0,id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) {
 
       if (temp & id)
-	 sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC;
+	 FPT_sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC;
       }
 
    sync_bit_map = 0x0001;
@@ -2871,39 +1896,34 @@
 			temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
 					 (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
 		}else
-	      temp = utilEERead(ioport, (USHORT)((SYNC_RATE_TBL/2)+id));
+	      temp = FPT_utilEERead(ioport, (USHORT)((SYNC_RATE_TBL/2)+id));
 
       for (i = 0; i < 2; temp >>=8,i++) {
 
          if (pCardInfo->si_per_targ_init_sync & sync_bit_map) {
 
-            sccbMgrTbl[thisCard][id*2+i].TarEEValue = (UCHAR)temp;
+            FPT_sccbMgrTbl[thisCard][id*2+i].TarEEValue = (UCHAR)temp;
             }
 
          else {
-	    sccbMgrTbl[thisCard][id*2+i].TarStatus |= SYNC_SUPPORTED;
-            sccbMgrTbl[thisCard][id*2+i].TarEEValue =
+	    FPT_sccbMgrTbl[thisCard][id*2+i].TarStatus |= SYNC_SUPPORTED;
+            FPT_sccbMgrTbl[thisCard][id*2+i].TarEEValue =
                (UCHAR)(temp & ~EE_SYNC_MASK);
             }
 
-#if defined(WIDE_SCSI)
 /*         if ((pCardInfo->si_per_targ_wide_nego & sync_bit_map) ||
             (id*2+i >= 8)){
 */
          if (pCardInfo->si_per_targ_wide_nego & sync_bit_map){
 
-            sccbMgrTbl[thisCard][id*2+i].TarEEValue |= EE_WIDE_SCSI;
+            FPT_sccbMgrTbl[thisCard][id*2+i].TarEEValue |= EE_WIDE_SCSI;
 
             }
 
          else { /* NARROW SCSI */
-            sccbMgrTbl[thisCard][id*2+i].TarStatus |= WIDE_NEGOCIATED;
+            FPT_sccbMgrTbl[thisCard][id*2+i].TarStatus |= WIDE_NEGOCIATED;
             }
 
-#else
-         sccbMgrTbl[thisCard][id*2+i].TarStatus |= WIDE_NEGOCIATED;
-#endif
-
 
 	 sync_bit_map <<= 1;
 
@@ -2915,1285 +1935,97 @@
    WR_HARPOON((ioport+hp_semaphore),
       (UCHAR)(RD_HARPOON((ioport+hp_semaphore)) | SCCB_MGR_PRESENT));
 
-#if defined(DOS)
-   return((USHORT)CurrCard);
-#else
    return((ULONG)CurrCard);
-#endif
 }
 
-#else  			/* end (FW_TYPE==_SCCB_MGR_)  */
-
-
-
-STATIC s16bits FP_PresenceCheck(PMGR_INFO pMgrInfo)
-{
-	PMGR_ENTRYPNTS	pMgr_EntryPnts = &pMgrInfo->mi_Functions;
-
-      pMgr_EntryPnts->UCBMgr_probe_adapter = probe_adapter;
-      pMgr_EntryPnts->UCBMgr_init_adapter = init_adapter;
-      pMgr_EntryPnts->UCBMgr_start_UCB = SccbMgr_start_sccb;
-      pMgr_EntryPnts->UCBMgr_build_UCB = build_UCB;
-      pMgr_EntryPnts->UCBMgr_abort_UCB = SccbMgr_abort_sccb;
-      pMgr_EntryPnts->UCBMgr_my_int = SccbMgr_my_int;
-      pMgr_EntryPnts->UCBMgr_isr = SccbMgr_isr;
-      pMgr_EntryPnts->UCBMgr_scsi_reset = SccbMgr_scsi_reset;
-      pMgr_EntryPnts->UCBMgr_timer_expired = SccbMgr_timer_expired;
-#ifndef NO_IOCTLS
-	  pMgr_EntryPnts->UCBMgr_unload_card = SccbMgr_unload_card;
-	  pMgr_EntryPnts->UCBMgr_save_foreign_state =
-	  									SccbMgr_save_foreign_state;
-	  pMgr_EntryPnts->UCBMgr_restore_foreign_state =
-	  									SccbMgr_restore_foreign_state;
-	  pMgr_EntryPnts->UCBMgr_restore_native_state =
-	  									SccbMgr_restore_native_state;
-#endif /*NO_IOCTLS*/
-
-      pMgrInfo->mi_SGListFormat=0x01;
-      pMgrInfo->mi_DataPtrFormat=0x01;
-      pMgrInfo->mi_MaxSGElements= (u16bits) 0xffffffff;
-      pMgrInfo->mi_MgrPrivateLen=sizeof(SCCB);
-      pMgrInfo->mi_PCIVendorID=BL_VENDOR_ID;
-      pMgrInfo->mi_PCIDeviceID=FP_DEVICE_ID;
-      pMgrInfo->mi_MgrAttributes= ATTR_IO_MAPPED +
-											 ATTR_PHYSICAL_ADDRESS +
-											 ATTR_VIRTUAL_ADDRESS +
-											 ATTR_OVERLAPPED_IO_IOCTLS_OK;
-      pMgrInfo->mi_IoRangeLen = 256;
-      return(0);
-}
-
-
-
-/*---------------------------------------------------------------------
- *
- * Function: probe_adapter
- *
- * Description: Setup and/or Search for cards and return info to caller.
- *
- *---------------------------------------------------------------------*/
-STATIC s32bits probe_adapter(PADAPTER_INFO pAdapterInfo)
-{
-   u16bits temp,temp2,temp3,temp4;
-   u08bits i,j,id;
-
-#if defined(DOS)
-#else
-   static u08bits first_time = 1;
-#endif
-   BASE_PORT ioport;
-	PNVRamInfo pCurrNvRam;
-
-   ioport = (BASE_PORT)pAdapterInfo->ai_baseaddr;
-
-
-
-   if (RD_HARPOON(ioport+hp_vendor_id_0) != ORION_VEND_0)
-      return(1);
-
-   if ((RD_HARPOON(ioport+hp_vendor_id_1) != ORION_VEND_1))
-      return(2);
-
-   if ((RD_HARPOON(ioport+hp_device_id_0) != ORION_DEV_0))
-      return(3);
-
-   if ((RD_HARPOON(ioport+hp_device_id_1) != ORION_DEV_1))
-      return(4);
-
-
-   if (RD_HARPOON(ioport+hp_rev_num) != 0x0f){
-
-
-/* For new Harpoon then check for sub_device ID LSB
-   the bits(0-3) must be all ZERO for compatible with
-   current version of SCCBMgr, else skip this Harpoon
-	device. */
-
-	   if (RD_HARPOON(ioport+hp_sub_device_id_0) & 0x0f)
-	      return(5);
-	}
-
-   if (first_time) {
-
-      SccbMgrTableInitAll();
-      first_time = 0;
-		mbCards = 0;
-      }
-
-	if(RdStack(ioport, 0) != 0x00) {
-		if(ChkIfChipInitialized(ioport) == FALSE)
-		{
-			pCurrNvRam = NULL;
-		   WR_HARPOON(ioport+hp_semaphore, 0x00);
-			XbowInit(ioport, 0);                /*Must Init the SCSI before attempting */
-			DiagEEPROM(ioport);
-		}
-		else
-		{
-			if(mbCards < MAX_MB_CARDS) {
-				pCurrNvRam = &nvRamInfo[mbCards];
-				mbCards++;
-				pCurrNvRam->niBaseAddr = ioport;
-				RNVRamData(pCurrNvRam);
-			}else
-				return((int) FAILURE);
-		}
-	}else
-		pCurrNvRam = NULL;
-
-#if defined (NO_BIOS_OPTION)
-	pCurrNvRam = NULL;
-   XbowInit(ioport, 0);                /*Must Init the SCSI before attempting */
-   DiagEEPROM(ioport);
-#endif  /* No BIOS Option */
-
-   WR_HARPOON(ioport+hp_clkctrl_0, CLKCTRL_DEFAULT);
-   WR_HARPOON(ioport+hp_sys_ctrl, 0x00);
-
-	if(pCurrNvRam)
-		pAdapterInfo->ai_id = pCurrNvRam->niAdapId;
-	else
-   	pAdapterInfo->ai_id = (u08bits)(utilEERead(ioport, (ADAPTER_SCSI_ID/2)) &
-      	(u08bits)0x0FF);
-
-   pAdapterInfo->ai_lun = 0x00;
-   pAdapterInfo->ai_fw_revision[0] = '3';
-   pAdapterInfo->ai_fw_revision[1] = '1';
-   pAdapterInfo->ai_fw_revision[2] = '1';
-   pAdapterInfo->ai_fw_revision[3] = ' ';
-   pAdapterInfo->ai_NumChannels = 1;
-
-   temp2 = 0x0000;
-   temp3 = 0x0000;
-   temp4 = 0x0000;
-
-   for (id = 0; id < (16/2); id++) {
-
-		if(pCurrNvRam){
-			temp = (USHORT) pCurrNvRam->niSyncTbl[id];
-			temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
-					 (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
-		}else
-	      temp = utilEERead(ioport, (u16bits)((SYNC_RATE_TBL/2)+id));
-
-      for (i = 0; i < 2; temp >>=8,i++) {
-
-         if ((temp & 0x03) != AUTO_RATE_00) {
-
-            temp2 >>= 0x01;
-            temp2 |= 0x8000;
-            }
-
-         else {
-            temp2 >>= 0x01;
-            }
-
-         if (temp & DISC_ENABLE_BIT) {
-
-            temp3 >>= 0x01;
-            temp3 |= 0x8000;
-            }
-
-         else {
-            temp3 >>= 0x01;
-            }
-
-         if (temp & WIDE_NEGO_BIT) {
-
-            temp4 >>= 0x01;
-            temp4 |= 0x8000;
-            }
-
-         else {
-            temp4 >>= 0x01;
-            }
-
-         }
-      }
-
-   pAdapterInfo->ai_per_targ_init_sync = temp2;
-   pAdapterInfo->ai_per_targ_no_disc = temp3;
-   pAdapterInfo->ai_per_targ_wide_nego = temp4;
-	if(pCurrNvRam)
-		i = pCurrNvRam->niSysConf;
-	else
-   	i = (u08bits)(utilEERead(ioport, (SYSTEM_CONFIG/2)));
-
-   /*
-   ** interrupts always level-triggered for FlashPoint
-   */
-   pAdapterInfo->ai_stateinfo |= LEVEL_TRIG;
-
-   if (i & 0x01)
-      pAdapterInfo->ai_stateinfo |= SCSI_PARITY_ENA;
-
-	if (i & 0x02)	/* SCSI Bus reset in AutoSCSI Set ? */
-	{
-		if(pCurrNvRam)
-		{
-			j = pCurrNvRam->niScamConf;
-		}
-		else
-		{
-		j = (u08bits) utilEERead(ioport, SCAM_CONFIG/2);
-		}
-		if(j & SCAM_ENABLED)
-		{
-			if(j & SCAM_LEVEL2)
-			{
-				pAdapterInfo->ai_stateinfo |= SCAM2_ENA;
-			}
-			else
-			{
-				pAdapterInfo->ai_stateinfo |= SCAM1_ENA;
-			}
-		}
-	}
-   j = (RD_HARPOON(ioport+hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
-   if (i & 0x04) {
-      j |= SCSI_TERM_ENA_L;
-      pAdapterInfo->ai_stateinfo |= LOW_BYTE_TERM_ENA;
-      }
-   WR_HARPOON(ioport+hp_bm_ctrl, j );
-
-   j = (RD_HARPOON(ioport+hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
-   if (i & 0x08) {
-      j |= SCSI_TERM_ENA_H;
-      pAdapterInfo->ai_stateinfo |= HIGH_BYTE_TERM_ENA;
-      }
-   WR_HARPOON(ioport+hp_ee_ctrl, j );
-
-	if(RD_HARPOON(ioport + hp_page_ctrl) & BIOS_SHADOW)
-	{
-		pAdapterInfo->ai_FlashRomSize = 64 * 1024;	/* 64k ROM */
-	}
-	else
-	{
-		pAdapterInfo->ai_FlashRomSize = 32 * 1024;	/* 32k ROM */
-	}
-
-   pAdapterInfo->ai_stateinfo |= (FAST20_ENA | TAG_QUEUE_ENA);
-   if (!(RD_HARPOON(ioport+hp_page_ctrl) & NARROW_SCSI_CARD))
-	{
-      pAdapterInfo->ai_attributes |= (WIDE_CAPABLE | FAST20_CAPABLE
-													| SCAM2_CAPABLE
-													| TAG_QUEUE_CAPABLE
-													| SUPRESS_UNDERRRUNS_CAPABLE
-													| SCSI_PARITY_CAPABLE);
-		pAdapterInfo->ai_MaxTarg = 16;
-		pAdapterInfo->ai_MaxLun  = 32;
-	}
-	else
-	{
-      pAdapterInfo->ai_attributes |= (FAST20_CAPABLE | SCAM2_CAPABLE
-													| TAG_QUEUE_CAPABLE
-													| SUPRESS_UNDERRRUNS_CAPABLE
-													| SCSI_PARITY_CAPABLE);
-		pAdapterInfo->ai_MaxTarg = 8;
-		pAdapterInfo->ai_MaxLun  = 8;
-	}
-
-   pAdapterInfo->ai_product_family = HARPOON_FAMILY;
-   pAdapterInfo->ai_HBAbustype = BUSTYPE_PCI;
-
-   for (i=0;i<CARD_MODEL_NAMELEN;i++)
-   {
-      pAdapterInfo->ai_card_model[i]=' '; /* initialize the ai_card_model */
-   }
-
-	if(pCurrNvRam){
-	pAdapterInfo->ai_card_model[0] = '9';
-		switch(pCurrNvRam->niModel & 0x0f){
-			case MODEL_LT:
-			pAdapterInfo->ai_card_model[1] = '3';
-			pAdapterInfo->ai_card_model[2] = '0';
-				break;
-			case MODEL_LW:
-			pAdapterInfo->ai_card_model[1] = '5';
-			pAdapterInfo->ai_card_model[2] = '0';
-				break;
-			case MODEL_DL:
-			pAdapterInfo->ai_card_model[1] = '3';
-			pAdapterInfo->ai_card_model[2] = '2';
-				break;
-			case MODEL_DW:
-			pAdapterInfo->ai_card_model[1] = '5';
-			pAdapterInfo->ai_card_model[2] = '2';
-				break;
-		}
-	}else{
-	   temp = utilEERead(ioport, (MODEL_NUMB_0/2));
-		pAdapterInfo->ai_card_model[0] = (u08bits)(temp >> 8);
-	   temp = utilEERead(ioport, (MODEL_NUMB_2/2));
-
-		pAdapterInfo->ai_card_model[1] = (u08bits)(temp & 0x00FF);
-	   pAdapterInfo->ai_card_model[2] = (u08bits)(temp >> 8);
-	}
-
-
-
-   pAdapterInfo->ai_FiberProductType = 0;
-
-   pAdapterInfo->ai_secondary_range = 0;
-
-   for (i=0;i<WORLD_WIDE_NAMELEN;i++)
-   {
-      pAdapterInfo->ai_worldwidename[i]='\0';
-   }
-
-   for (i=0;i<VENDOR_NAMELEN;i++)
-   {
-      pAdapterInfo->ai_vendorstring[i]='\0';
-   }
-   	pAdapterInfo->ai_vendorstring[0]='B';
-   	pAdapterInfo->ai_vendorstring[1]='U';
-   	pAdapterInfo->ai_vendorstring[2]='S';
-   	pAdapterInfo->ai_vendorstring[3]='L';
-   	pAdapterInfo->ai_vendorstring[4]='O';
-   	pAdapterInfo->ai_vendorstring[5]='G';
-   	pAdapterInfo->ai_vendorstring[6]='I';
-   	pAdapterInfo->ai_vendorstring[7]='C';
-
-	for (i=0;i<FAMILY_NAMELEN;i++)
-	{
-	   pAdapterInfo->ai_AdapterFamilyString[i]='\0';
-	}
-   	pAdapterInfo->ai_AdapterFamilyString[0]='F';
-   	pAdapterInfo->ai_AdapterFamilyString[1]='L';
-   	pAdapterInfo->ai_AdapterFamilyString[2]='A';
-   	pAdapterInfo->ai_AdapterFamilyString[3]='S';
-   	pAdapterInfo->ai_AdapterFamilyString[4]='H';
-   	pAdapterInfo->ai_AdapterFamilyString[5]='P';
-   	pAdapterInfo->ai_AdapterFamilyString[6]='O';
-   	pAdapterInfo->ai_AdapterFamilyString[7]='I';
-   	pAdapterInfo->ai_AdapterFamilyString[8]='N';
-   	pAdapterInfo->ai_AdapterFamilyString[9]='T';
-
-   ARAM_ACCESS(ioport);
-
-   for ( i = 0; i < 4; i++ ) {
-
-      pAdapterInfo->ai_XlatInfo[i] =
-         RD_HARPOON(ioport+hp_aramBase+BIOS_DATA_OFFSET+i);
-      }
-
-	/* return with -1 if no sort, else return with
-	   logical card number sorted by BIOS (zero-based) */
-
-
-	pAdapterInfo->ai_relative_cardnum = 
-      (u08bits)(RD_HARPOON(ioport+hp_aramBase+BIOS_RELATIVE_CARD)-1); 
-
-   SGRAM_ACCESS(ioport);
-
-   s_PhaseTbl[0] = phaseDataOut;
-   s_PhaseTbl[1] = phaseDataIn;
-   s_PhaseTbl[2] = phaseIllegal;
-   s_PhaseTbl[3] = phaseIllegal;
-   s_PhaseTbl[4] = phaseCommand;
-   s_PhaseTbl[5] = phaseStatus;
-   s_PhaseTbl[6] = phaseMsgOut;
-   s_PhaseTbl[7] = phaseMsgIn;
-
-   pAdapterInfo->ai_present = 0x01;
-
-#if defined(BUGBUG)
-
-
-   for (i = 0; i < MAX_CARDS; i++) {
-
-      for (id=0; id<debug_size; id++)
-         debug_int[i][id] =  (u08bits)0x00;
-      debug_index[i] = 0;
-      }
-
-#endif
-
-   return(0);
-}
-
-
-
-
-
-/*---------------------------------------------------------------------
- *
- * Function: init_adapter, exported to BUDI via UCBMgr_init_adapter entry
- *
- *
- * Description: Setup adapter for normal operation (hard reset).
- *
- *---------------------------------------------------------------------*/
-STATIC CARD_HANDLE init_adapter(PADAPTER_INFO pCardInfo)
-{
-   PSCCBcard CurrCard;
-	PNVRamInfo pCurrNvRam;
-   u08bits i,j,thisCard, ScamFlg;
-   u16bits temp,sync_bit_map,id;
-   BASE_PORT ioport;
-
-   ioport = (BASE_PORT)pCardInfo->ai_baseaddr;
-
-   for(thisCard =0; thisCard <= MAX_CARDS; thisCard++) {
-
-      if (thisCard == MAX_CARDS) {
-
-         return(FAILURE);
-         }
-
-      if (BL_Card[thisCard].ioPort == ioport) {
-
-         CurrCard = &BL_Card[thisCard];
-         SccbMgrTableInitCard(CurrCard,thisCard);
-         break;
-         }
-
-      else if (BL_Card[thisCard].ioPort == 0x00) {
-
-         BL_Card[thisCard].ioPort = ioport;
-         CurrCard = &BL_Card[thisCard];
-
-			if(mbCards)
-				for(i = 0; i < mbCards; i++){
-					if(CurrCard->ioPort == nvRamInfo[i].niBaseAddr)
-						CurrCard->pNvRamInfo = &nvRamInfo[i];
-				}
-         SccbMgrTableInitCard(CurrCard,thisCard);
-         CurrCard->cardIndex = thisCard;
-         CurrCard->cardInfo = pCardInfo;
-
-         break;
-         }
-      }
-
-	pCurrNvRam = CurrCard->pNvRamInfo;
-
-   
-	if(pCurrNvRam){
-		ScamFlg = pCurrNvRam->niScamConf;
-	}
-	else{
-	   ScamFlg = (UCHAR) utilEERead(ioport, SCAM_CONFIG/2);
-	}
-	
-
-   BusMasterInit(ioport);
-   XbowInit(ioport, ScamFlg);
-
-#if defined (NO_BIOS_OPTION)
-
-
-   if (DiagXbow(ioport)) return(FAILURE);
-   if (DiagBusMaster(ioport)) return(FAILURE);
-
-#endif  /* No BIOS Option */
-
-   autoLoadDefaultMap(ioport);
-
-
-   for (i = 0,id = 0x01; i != pCardInfo->ai_id; i++,id <<= 1){}
-
-   WR_HARPOON(ioport+hp_selfid_0, id);
-   WR_HARPOON(ioport+hp_selfid_1, 0x00);
-   WR_HARPOON(ioport+hp_arb_id, pCardInfo->ai_id);
-   CurrCard->ourId = (unsigned char) pCardInfo->ai_id;
-
-   i = (u08bits) pCardInfo->ai_stateinfo;
-   if (i & SCSI_PARITY_ENA)
-       WR_HARPOON(ioport+hp_portctrl_1,(HOST_MODE8 | CHK_SCSI_P));
-
-   j = (RD_HARPOON(ioport+hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
-   if (i & LOW_BYTE_TERM_ENA)
-      j |= SCSI_TERM_ENA_L;
-   WR_HARPOON(ioport+hp_bm_ctrl, j);
-
-   j = (RD_HARPOON(ioport+hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
-   if (i & HIGH_BYTE_TERM_ENA)
-      j |= SCSI_TERM_ENA_H;
-   WR_HARPOON(ioport+hp_ee_ctrl, j );
-
-
-   if (!(pCardInfo->ai_stateinfo & NO_RESET_IN_INIT)) {
-
-      sresb(ioport,thisCard);
-
-         scini(thisCard, (u08bits) pCardInfo->ai_id, 0);
-      }
-
-
-
-   if (pCardInfo->ai_stateinfo & SUPRESS_UNDERRRUNS_ENA)
-      CurrCard->globalFlags |= F_NO_FILTER;
-
-	if(pCurrNvRam){
-		if(pCurrNvRam->niSysConf & 0x10)
-			CurrCard->globalFlags |= F_GREEN_PC;
-	}
-	else{
-	   if (utilEERead(ioport, (SYSTEM_CONFIG/2)) & GREEN_PC_ENA)
-   	   CurrCard->globalFlags |= F_GREEN_PC;
-	}
-
-	/* Set global flag to indicate Re-Negotiation to be done on all
-		ckeck condition */
-	if(pCurrNvRam){
-		if(pCurrNvRam->niScsiConf & 0x04)
-			CurrCard->globalFlags |= F_DO_RENEGO;
-	}
-	else{
-	   if (utilEERead(ioport, (SCSI_CONFIG/2)) & RENEGO_ENA)
-   	   CurrCard->globalFlags |= F_DO_RENEGO;
-	}
-
-	if(pCurrNvRam){
-		if(pCurrNvRam->niScsiConf & 0x08)
-			CurrCard->globalFlags |= F_CONLUN_IO;
-	}
-	else{
-	   if (utilEERead(ioport, (SCSI_CONFIG/2)) & CONNIO_ENA)
-   	   CurrCard->globalFlags |= F_CONLUN_IO;
-	}
-
-   temp = pCardInfo->ai_per_targ_no_disc;
-
-   for (i = 0,id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) {
-
-      if (temp & id)
-         sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC;
-      }
-
-   sync_bit_map = 0x0001;
-
-   for (id = 0; id < (MAX_SCSI_TAR/2); id++){
-
-		if(pCurrNvRam){
-			temp = (USHORT) pCurrNvRam->niSyncTbl[id];
-			temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
-					 (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
-		}else
-	      temp = utilEERead(ioport, (u16bits)((SYNC_RATE_TBL/2)+id));
-
-      for (i = 0; i < 2; temp >>=8,i++){
-
-         if (pCardInfo->ai_per_targ_init_sync & sync_bit_map){
-
-            sccbMgrTbl[thisCard][id*2+i].TarEEValue = (u08bits)temp;
-            }
-
-         else {
-            sccbMgrTbl[thisCard][id*2+i].TarStatus |= SYNC_SUPPORTED;
-            sccbMgrTbl[thisCard][id*2+i].TarEEValue =
-               (u08bits)(temp & ~EE_SYNC_MASK);
-            }
-
-#if defined(WIDE_SCSI)
-/*         if ((pCardInfo->ai_per_targ_wide_nego & sync_bit_map) ||
-            (id*2+i >= 8)){
-*/
-         if (pCardInfo->ai_per_targ_wide_nego & sync_bit_map){
-
-            sccbMgrTbl[thisCard][id*2+i].TarEEValue |= EE_WIDE_SCSI;
-
-            }
-
-         else { /* NARROW SCSI */
-            sccbMgrTbl[thisCard][id*2+i].TarStatus |= WIDE_NEGOCIATED;
-            }
-
-#else
-         sccbMgrTbl[thisCard][id*2+i].TarStatus |= WIDE_NEGOCIATED;
-#endif
-
-
-         sync_bit_map <<= 1;
-         }
-      }
-
-
-   pCardInfo->ai_SGListFormat=0x01;
-   pCardInfo->ai_DataPtrFormat=0x01;
-   pCardInfo->ai_AEN_mask &= SCSI_RESET_COMPLETE;
-
-   WR_HARPOON((ioport+hp_semaphore),
-      (u08bits)(RD_HARPOON((ioport+hp_semaphore)) | SCCB_MGR_PRESENT));
-
-   return((u32bits)CurrCard);
-
-}
-
-
-/*---------------------------------------------------------------------
- *
- * Function: build_ucb, exported to BUDI via UCBMgr_build_ucb entry
- *
- * Description: prepare fw portion of ucb. do not start, resource not guaranteed
- *             so don't manipulate anything that's derived from states which
- *             may change
- *
- *---------------------------------------------------------------------*/
-void build_UCB(CARD_HANDLE pCurrCard, PUCB p_ucb)
-{
-
-   u08bits thisCard;
-   u08bits i,j;
-
-   PSCCB p_sccb;
-
-
-   thisCard = ((PSCCBcard) pCurrCard)->cardIndex;
-
-
-   p_sccb=(PSCCB)p_ucb->UCB_MgrPrivatePtr;
-
-
-   p_sccb->Sccb_ucb_ptr=p_ucb;
-
-   switch (p_ucb->UCB_opcode & (OPC_DEVICE_RESET+OPC_XFER_SG+OPC_CHK_RESIDUAL))
-   {
-      case OPC_DEVICE_RESET:
-         p_sccb->OperationCode=RESET_COMMAND;
-         break;
-      case OPC_XFER_SG:
-         p_sccb->OperationCode=SCATTER_GATHER_COMMAND;
-         break;
-      case OPC_XFER_SG+OPC_CHK_RESIDUAL:
-         p_sccb->OperationCode=RESIDUAL_SG_COMMAND;
-         break;
-      case OPC_CHK_RESIDUAL:
-
-	      p_sccb->OperationCode=RESIDUAL_COMMAND;
-	      break;
-      default:
-	      p_sccb->OperationCode=SCSI_INITIATOR_COMMAND;
-	      break;
-   }
-
-   if (p_ucb->UCB_opcode & OPC_TQ_ENABLE)
-   {
-      p_sccb->ControlByte = (u08bits)((p_ucb->UCB_opcode & OPC_TQ_MASK)>>2) | F_USE_CMD_Q;
-   }
-   else
-   {
-      p_sccb->ControlByte = 0;
-   }
-
-
-   p_sccb->CdbLength = (u08bits)p_ucb->UCB_cdblen;
-
-   if (p_ucb->UCB_opcode & OPC_NO_AUTO_SENSE)
-   {
-      p_sccb->RequestSenseLength = 0;
-   }
-   else
-   {
-      p_sccb->RequestSenseLength = (unsigned char) p_ucb->UCB_senselen;
-   }
-
-
-   if (p_ucb->UCB_opcode & OPC_XFER_SG)
-   {
-      p_sccb->DataPointer=p_ucb->UCB_virt_dataptr;
-      p_sccb->DataLength = (((u32bits)p_ucb->UCB_NumSgElements)<<3);
-   }
-   else
-   {
-      p_sccb->DataPointer=p_ucb->UCB_phys_dataptr;
-      p_sccb->DataLength=p_ucb->UCB_datalen;
-   };
-
-   p_sccb->HostStatus=0;
-   p_sccb->TargetStatus=0;
-   p_sccb->TargID=(unsigned char)p_ucb->UCB_targid;
-   p_sccb->Lun=(unsigned char) p_ucb->UCB_lun;
-   p_sccb->SccbIOPort=((PSCCBcard)pCurrCard)->ioPort;
-
-   j=p_ucb->UCB_cdblen;
-   for (i=0;i<j;i++)
-   {
-      p_sccb->Cdb[i] = p_ucb->UCB_cdb[i];
-   }
-
-   p_sccb->SensePointer=p_ucb->UCB_phys_senseptr;
-
-   sinits(p_sccb,thisCard);
-
-}
-#ifndef NO_IOCTLS
-
-/*---------------------------------------------------------------------
- *
- * Function: GetDevSyncRate
- *
- *---------------------------------------------------------------------*/
-STATIC  int GetDevSyncRate(PSCCBcard pCurrCard,PUCB p_ucb)
-{
-	struct _SYNC_RATE_INFO * pSyncStr;
-   PSCCBMgr_tar_info currTar_Info;
-	BASE_PORT ioport;
-	u08bits scsiID, j;
-
-#if (FW_TYPE != _SCCB_MGR_)
-	if( p_ucb->UCB_targid >= pCurrCard->cardInfo->ai_MaxTarg )
-	{
-		return(1);
-	}
-#endif
-
-	ioport  = pCurrCard->ioPort;
-	pSyncStr	= (struct _SYNC_RATE_INFO *) p_ucb->UCB_virt_dataptr;
-	scsiID = (u08bits) p_ucb->UCB_targid;
-   currTar_Info = &sccbMgrTbl[pCurrCard->cardIndex][scsiID];
-	j = currTar_Info->TarSyncCtrl;
-
-	switch (currTar_Info->TarEEValue & EE_SYNC_MASK)
-	{
-		case EE_SYNC_ASYNC:
-			pSyncStr->RequestMegaXferRate = 0x00;
-			break;
-		case EE_SYNC_5MB:
-			pSyncStr->RequestMegaXferRate = (j & NARROW_SCSI) ? 50 : 100;
-			break;
-		case EE_SYNC_10MB:
-			pSyncStr->RequestMegaXferRate = (j & NARROW_SCSI) ? 100 : 200;
-			break;
-		case EE_SYNC_20MB:
-			pSyncStr->RequestMegaXferRate = (j & NARROW_SCSI) ? 200 : 400;
-			break;
-	}
-
-	switch ((j >> 5) & 0x07)
-	{
-		case 0x00:
-			if((j & 0x07) == 0x00)
-			{
-				pSyncStr->ActualMegaXferRate = 0x00;	/* Async Mode */
-			}
-			else
-			{
-				pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 200 : 400;
-			}
-			break;
-		case 0x01:
-			pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 100 : 200;
-			break;
-		case 0x02:
-			pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 66 : 122;
-			break;
-		case 0x03:
-			pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 50 : 100;
-			break;
-		case 0x04:
-			pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 40 : 80;
-			break;
-		case 0x05:
-			pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 33 : 66;
-			break;
-		case 0x06:
-			pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 28 : 56;
-			break;
-		case 0x07:
-			pSyncStr->ActualMegaXferRate = (j & NARROW_SCSI) ? 25 : 50;
-			break;
-	}
-	pSyncStr->NegotiatedOffset = j & 0x0f;
-
-	return(0);
-}
-
-/*---------------------------------------------------------------------
- *
- * Function: SetDevSyncRate
- *
- *---------------------------------------------------------------------*/
-STATIC int SetDevSyncRate(PSCCBcard pCurrCard, PUCB p_ucb)
-{
-	struct _SYNC_RATE_INFO * pSyncStr;
-   PSCCBMgr_tar_info currTar_Info;
-	BASE_PORT ioPort;
-	u08bits scsiID, i, j, syncVal;
-	u16bits syncOffset, actualXferRate;
-	union {
-		u08bits tempb[2];
-		u16bits tempw;
-	}temp2;
-
-#if (FW_TYPE != _SCCB_MGR_)
-	if( p_ucb->UCB_targid >= pCurrCard->cardInfo->ai_MaxTarg )
-	{
-		return(1);
-	}
-#endif
-
-	ioPort  = pCurrCard->ioPort;
-	pSyncStr	= (struct _SYNC_RATE_INFO *) p_ucb->UCB_virt_dataptr;
-	scsiID = (u08bits) p_ucb->UCB_targid;
-   currTar_Info = &sccbMgrTbl[pCurrCard->cardIndex][scsiID];
-	i = RD_HARPOON(ioPort+hp_xfer_pad);		/* Save current value */
-	WR_HARPOON(ioPort+hp_xfer_pad, (i | ID_UNLOCK));
-	WR_HARPOON(ioPort+hp_select_id, ((scsiID << 4) | scsiID));
-	j = RD_HARPOON(ioPort+hp_synctarg_0);
-	WR_HARPOON(ioPort+hp_xfer_pad, i);		/* restore value */
-
-	actualXferRate = pSyncStr->ActualMegaXferRate;
-	if(!(j & NARROW_SCSI))
-	{
-		actualXferRate <<= 1;
-	}
-	if(actualXferRate == 0x00)
-	{
-		syncVal = EE_SYNC_ASYNC;			/* Async Mode */
-	}
-	if(actualXferRate == 0x0200)
-	{
-		syncVal = EE_SYNC_20MB;				/* 20/40 MB Mode */
-	}
-	if(actualXferRate > 0x0050 && actualXferRate < 0x0200 )
-	{
-		syncVal = EE_SYNC_10MB;				/* 10/20 MB Mode */
-	}
-	else
-	{
-		syncVal = EE_SYNC_5MB;				/* 5/10 MB Mode */
-	}
-	if(currTar_Info->TarEEValue && EE_SYNC_MASK == syncVal)
-		return(0);
-	currTar_Info->TarEEValue = (currTar_Info->TarEEValue & !EE_SYNC_MASK)
-											| syncVal;
-	syncOffset = (SYNC_RATE_TBL + scsiID) / 2;
-	temp2.tempw = utilEERead(ioPort, syncOffset);
-	if(scsiID & 0x01)
-	{
-		temp2.tempb[0] = (temp2.tempb[0] & !EE_SYNC_MASK) | syncVal;
-	}
-	else
-	{
-		temp2.tempb[1] = (temp2.tempb[1] & !EE_SYNC_MASK) | syncVal;
-	}
-	utilEEWriteOnOff(ioPort, 1);
-	utilEEWrite(ioPort, temp2.tempw, syncOffset);
-	utilEEWriteOnOff(ioPort, 0);
-	UpdateCheckSum(ioPort);
-
-	return(0);
-}
-/*---------------------------------------------------------------------
- *
- * Function: GetDevWideMode
- *
- *---------------------------------------------------------------------*/
-int GetDevWideMode(PSCCBcard pCurrCard,PUCB p_ucb)
-{
-	u08bits *pData;
-
-	pData = (u08bits *)p_ucb->UCB_virt_dataptr;
-	if(sccbMgrTbl[pCurrCard->cardIndex][p_ucb->UCB_targid].TarEEValue
-				& EE_WIDE_SCSI)
-	{
-		*pData = 1;
-	}
-	else
-	{
-		*pData = 0;
-	}
-
-	return(0);
-}
-
-/*---------------------------------------------------------------------
- *
- * Function: SetDevWideMode
- *
- *---------------------------------------------------------------------*/
-int SetDevWideMode(PSCCBcard pCurrCard,PUCB p_ucb)
-{
-	u08bits *pData;
-   PSCCBMgr_tar_info currTar_Info;
-	BASE_PORT ioPort;
-	u08bits scsiID, scsiWideMode;
-	u16bits syncOffset;
-	union {
-		u08bits tempb[2];
-		u16bits tempw;
-	}temp2;
-
-#if (FW_TYPE != _SCCB_MGR_)
-	if( !(pCurrCard->cardInfo->ai_attributes & WIDE_CAPABLE) )
-	{
-		return(1);
-	}
-
-	if( p_ucb->UCB_targid >= pCurrCard->cardInfo->ai_MaxTarg )
-	{
-		return(1);
-	}
-#endif
-
-	ioPort  = pCurrCard->ioPort;
-	pData = (u08bits *)p_ucb->UCB_virt_dataptr;
-	scsiID = (u08bits) p_ucb->UCB_targid;
-	currTar_Info = &sccbMgrTbl[pCurrCard->cardIndex][scsiID];
-
-	if(*pData)
-	{
-		if(currTar_Info->TarEEValue & EE_WIDE_SCSI)
-		{
-			return(0);
-		}
-		else
-		{
-			scsiWideMode = EE_WIDE_SCSI;
-		}
-	}
-	else
-	{
-		if(!(currTar_Info->TarEEValue & EE_WIDE_SCSI))
-		{
-			return(0);
-		}
-		else
-		{
-			scsiWideMode = 0;
-		}
-	}
-	currTar_Info->TarEEValue = (currTar_Info->TarEEValue & !EE_WIDE_SCSI)
-											| scsiWideMode;
-
-	syncOffset = (SYNC_RATE_TBL + scsiID) / 2;
-	temp2.tempw = utilEERead(ioPort, syncOffset);
-	if(scsiID & 0x01)
-	{
-		temp2.tempb[0] = (temp2.tempb[0] & !EE_WIDE_SCSI) | scsiWideMode;
-	}
-	else
-	{
-		temp2.tempb[1] = (temp2.tempb[1] & !EE_WIDE_SCSI) | scsiWideMode;
-	}
-	utilEEWriteOnOff(ioPort, 1);
-	utilEEWrite(ioPort, temp2.tempw, syncOffset);
-	utilEEWriteOnOff(ioPort, 0);
-	UpdateCheckSum(ioPort);
-
-	return(0);
-}
-
-/*---------------------------------------------------------------------
- *
- * Function: ReadNVRam
- *
- *---------------------------------------------------------------------*/
-void ReadNVRam(PSCCBcard pCurrCard,PUCB p_ucb)
-{
-	u08bits *pdata;
-	u16bits i,numwrds,numbytes,offset,temp;
-	u08bits OneMore = FALSE;
-#if defined(DOS)
-	u16bits ioport;
-#else
-	u32bits ioport;
-#endif
-
-	numbytes = (u16bits) p_ucb->UCB_datalen;
-	ioport  = pCurrCard->ioPort;
-   pdata   = (u08bits *) p_ucb->UCB_virt_dataptr;
-	offset  = (u16bits) (p_ucb->UCB_IOCTLParams[0]);
-
-
-
-   if (offset & 0x1)
-	{
-	    *((u16bits*) pdata) = utilEERead(ioport,(u16bits)((offset - 1) / 2)); /* 16 bit read */
-		 *pdata = *(pdata + 1);
-		 ++offset;
-   	 ++pdata;
-		 --numbytes;
-	}
-
-	numwrds = numbytes / 2;
-	if (numbytes & 1)
-	 	OneMore = TRUE;
-
-	for (i = 0; i < numwrds; i++)
-	{
-   	*((u16bits*) pdata) = utilEERead(ioport,(u16bits)(offset / 2));
-		pdata += 2;
-		offset += 2;
-   }
-	if (OneMore)
-	{
-		--pdata;
-		-- offset;
-   	temp = utilEERead(ioport,(u16bits)(offset / 2));
-		*pdata = (u08bits) (temp);
-	}
-
-} /* end proc ReadNVRam */
-
-
-/*---------------------------------------------------------------------
- *
- * Function: WriteNVRam
- *
- *---------------------------------------------------------------------*/
-void WriteNVRam(PSCCBcard pCurrCard,PUCB p_ucb)
-{
-	u08bits *pdata;
-	u16bits i,numwrds,numbytes,offset, eeprom_end;
-	u08bits OneMore = FALSE;
-	union {
-		u08bits  tempb[2];
-		u16bits  tempw;
-	} temp2;
-
-#if defined(DOS)
-	u16bits ioport;
-#else
-	u32bits ioport;
-#endif
-
-	numbytes = (u16bits) p_ucb->UCB_datalen;
-	ioport  = pCurrCard->ioPort;
-   pdata   = (u08bits *) p_ucb->UCB_virt_dataptr;
-	offset  = (u16bits) (p_ucb->UCB_IOCTLParams[0]);
-
-   if (RD_HARPOON(ioport+hp_page_ctrl) & NARROW_SCSI_CARD)
-      eeprom_end = 512;
-   else
-      eeprom_end = 768;
-	
-	if(offset > eeprom_end)
-		return;
-
-	if((offset + numbytes) > eeprom_end)
-		numbytes = eeprom_end - offset;
-
-    utilEEWriteOnOff(ioport,1);   /* Enable write access to the EEPROM */
-
-
-
-   if (offset & 0x1)
-	{
-	    temp2.tempw = utilEERead(ioport,(u16bits)((offset - 1) / 2)); /* 16 bit read */
-		 temp2.tempb[1] = *pdata;
-	    utilEEWrite(ioport, temp2.tempw, (u16bits)((offset -1) / 2));
-		 *pdata = *(pdata + 1);
-		 ++offset;
-   	 ++pdata;
-		 --numbytes;
-	}
-
-	numwrds = numbytes / 2;
-	if (numbytes & 1)
-	 	OneMore = TRUE;
-
-	for (i = 0; i < numwrds; i++)
-	{
-   	utilEEWrite(ioport, *((pu16bits)pdata),(u16bits)(offset / 2));
-		pdata += 2;
-		offset += 2;
-   }
-	if (OneMore)
-	{
-
-   	temp2.tempw = utilEERead(ioport,(u16bits)(offset / 2));
-		temp2.tempb[0] = *pdata;
-   	utilEEWrite(ioport, temp2.tempw, (u16bits)(offset / 2));
-	}
-   utilEEWriteOnOff(ioport,0);   /* Turn off write access */
-   UpdateCheckSum((u32bits)ioport);
-
-} /* end proc WriteNVRam */
-
-
-
-/*---------------------------------------------------------------------
- *
- * Function: UpdateCheckSum
- *
- * Description: Update Check Sum in EEPROM
- *
- *---------------------------------------------------------------------*/
-
-
-void UpdateCheckSum(u32bits baseport)
-{
-	USHORT i,sum_data, eeprom_end;
-
-	sum_data = 0x0000;
-
-
-   if (RD_HARPOON(baseport+hp_page_ctrl) & NARROW_SCSI_CARD)
-      eeprom_end = 512;
-   else
-      eeprom_end = 768;
-
-	for (i = 1; i < eeprom_end/2; i++)
-	{
-		sum_data += utilEERead(baseport, i);
-	}
-
-   utilEEWriteOnOff(baseport,1);   /* Enable write access to the EEPROM */
-
-   utilEEWrite(baseport, sum_data, EEPROM_CHECK_SUM/2);
-   utilEEWriteOnOff(baseport,0);   /* Turn off write access */
-}
-
-void SccbMgr_save_foreign_state(PADAPTER_INFO pAdapterInfo)
-{
-}
-
-
-void SccbMgr_restore_foreign_state(CARD_HANDLE pCurrCard)
-{
-}
-
-void SccbMgr_restore_native_state(CARD_HANDLE pCurrCard)
-{
-}
-
-#endif /* NO_IOCTLS */
-
-#endif /* (FW_TYPE==_UCB_MGR_)   */
-
-#ifndef NO_IOCTLS
-#if (FW_TYPE==_UCB_MGR_)
-void SccbMgr_unload_card(CARD_HANDLE pCurrCard)
-#else
-#if defined(DOS)
-void SccbMgr_unload_card(USHORT pCurrCard)
-#else
-void SccbMgr_unload_card(ULONG pCurrCard)
-#endif
-#endif
+static void SccbMgr_unload_card(ULONG pCurrCard)
 {
 	UCHAR i;
-#if defined(DOS)
-	USHORT portBase;
-	USHORT regOffset;
-#else
 	ULONG portBase;
 	ULONG regOffset;
-#endif
 	ULONG scamData;
-#if defined(OS2)
-	ULONG far *pScamTbl;
-#else
 	ULONG *pScamTbl;
-#endif
 	PNVRamInfo pCurrNvRam;
 
 	pCurrNvRam = ((PSCCBcard)pCurrCard)->pNvRamInfo;
 
 	if(pCurrNvRam){
-		WrStack(pCurrNvRam->niBaseAddr, 0, pCurrNvRam->niModel);
-		WrStack(pCurrNvRam->niBaseAddr, 1, pCurrNvRam->niSysConf);
-		WrStack(pCurrNvRam->niBaseAddr, 2, pCurrNvRam->niScsiConf);
-		WrStack(pCurrNvRam->niBaseAddr, 3, pCurrNvRam->niScamConf);
-		WrStack(pCurrNvRam->niBaseAddr, 4, pCurrNvRam->niAdapId);
+		FPT_WrStack(pCurrNvRam->niBaseAddr, 0, pCurrNvRam->niModel);
+		FPT_WrStack(pCurrNvRam->niBaseAddr, 1, pCurrNvRam->niSysConf);
+		FPT_WrStack(pCurrNvRam->niBaseAddr, 2, pCurrNvRam->niScsiConf);
+		FPT_WrStack(pCurrNvRam->niBaseAddr, 3, pCurrNvRam->niScamConf);
+		FPT_WrStack(pCurrNvRam->niBaseAddr, 4, pCurrNvRam->niAdapId);
 
 		for(i = 0; i < MAX_SCSI_TAR / 2; i++)
-			WrStack(pCurrNvRam->niBaseAddr, (UCHAR)(i+5), pCurrNvRam->niSyncTbl[i]);
+			FPT_WrStack(pCurrNvRam->niBaseAddr, (UCHAR)(i+5), pCurrNvRam->niSyncTbl[i]);
 
 		portBase = pCurrNvRam->niBaseAddr;
 
 		for(i = 0; i < MAX_SCSI_TAR; i++){
 			regOffset = hp_aramBase + 64 + i*4;
-#if defined(OS2)
-			pScamTbl = (ULONG far *) &pCurrNvRam->niScamTbl[i];
-#else
 			pScamTbl = (ULONG *) &pCurrNvRam->niScamTbl[i];
-#endif
 			scamData = *pScamTbl;
 			WR_HARP32(portBase, regOffset, scamData);
 		}
 
 	}else{
-		WrStack(((PSCCBcard)pCurrCard)->ioPort, 0, 0);
+		FPT_WrStack(((PSCCBcard)pCurrCard)->ioPort, 0, 0);
 	}
 }
-#endif /* NO_IOCTLS */
 
 
-void RNVRamData(PNVRamInfo pNvRamInfo)
+static void FPT_RNVRamData(PNVRamInfo pNvRamInfo)
 {
 	UCHAR i;
-#if defined(DOS)
-	USHORT portBase;
-	USHORT regOffset;
-#else
 	ULONG portBase;
 	ULONG regOffset;
-#endif
 	ULONG scamData;
-#if defined (OS2)
-	ULONG far *pScamTbl;
-#else
 	ULONG *pScamTbl;
-#endif
 
-	pNvRamInfo->niModel    = RdStack(pNvRamInfo->niBaseAddr, 0);
-	pNvRamInfo->niSysConf  = RdStack(pNvRamInfo->niBaseAddr, 1);
-	pNvRamInfo->niScsiConf = RdStack(pNvRamInfo->niBaseAddr, 2);
-	pNvRamInfo->niScamConf = RdStack(pNvRamInfo->niBaseAddr, 3);
-	pNvRamInfo->niAdapId   = RdStack(pNvRamInfo->niBaseAddr, 4);
+	pNvRamInfo->niModel    = FPT_RdStack(pNvRamInfo->niBaseAddr, 0);
+	pNvRamInfo->niSysConf  = FPT_RdStack(pNvRamInfo->niBaseAddr, 1);
+	pNvRamInfo->niScsiConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 2);
+	pNvRamInfo->niScamConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 3);
+	pNvRamInfo->niAdapId   = FPT_RdStack(pNvRamInfo->niBaseAddr, 4);
 
 	for(i = 0; i < MAX_SCSI_TAR / 2; i++)
-		pNvRamInfo->niSyncTbl[i] = RdStack(pNvRamInfo->niBaseAddr, (UCHAR)(i+5));
+		pNvRamInfo->niSyncTbl[i] = FPT_RdStack(pNvRamInfo->niBaseAddr, (UCHAR)(i+5));
 
 	portBase = pNvRamInfo->niBaseAddr;
 
 	for(i = 0; i < MAX_SCSI_TAR; i++){
 		regOffset = hp_aramBase + 64 + i*4;
 		RD_HARP32(portBase, regOffset, scamData);
-#if defined(OS2)
-		pScamTbl = (ULONG far *) &pNvRamInfo->niScamTbl[i];
-#else
 		pScamTbl = (ULONG *) &pNvRamInfo->niScamTbl[i];
-#endif
 		*pScamTbl = scamData;
 	}
 
 }
 
-#if defined(DOS)
-UCHAR RdStack(USHORT portBase, UCHAR index)
-#else
-UCHAR RdStack(ULONG portBase, UCHAR index)
-#endif
+static UCHAR FPT_RdStack(ULONG portBase, UCHAR index)
 {
 	WR_HARPOON(portBase + hp_stack_addr, index);
 	return(RD_HARPOON(portBase + hp_stack_data));
 }
 
-#if defined(DOS)
-void WrStack(USHORT portBase, UCHAR index, UCHAR data)
-#else
-void WrStack(ULONG portBase, UCHAR index, UCHAR data)
-#endif
+static void FPT_WrStack(ULONG portBase, UCHAR index, UCHAR data)
 {
 	WR_HARPOON(portBase + hp_stack_addr, index);
 	WR_HARPOON(portBase + hp_stack_data, data);
 }
 
 
-#if (FW_TYPE==_UCB_MGR_)
-u08bits ChkIfChipInitialized(BASE_PORT ioPort)
-#else
-#if defined(DOS)
-UCHAR ChkIfChipInitialized(USHORT ioPort)
-#else
-UCHAR ChkIfChipInitialized(ULONG ioPort)
-#endif
-#endif
+static UCHAR FPT_ChkIfChipInitialized(ULONG ioPort)
 {
-	if((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != RdStack(ioPort, 4))
-		return(FALSE);
+	if((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != FPT_RdStack(ioPort, 4))
+		return(0);
 	if((RD_HARPOON(ioPort + hp_clkctrl_0) & CLKCTRL_DEFAULT)
 								!= CLKCTRL_DEFAULT)
-		return(FALSE);
+		return(0);
 	if((RD_HARPOON(ioPort + hp_seltimeout) == TO_250ms) ||
 		(RD_HARPOON(ioPort + hp_seltimeout) == TO_290ms))
-		return(TRUE);
-	return(FALSE);
+		return(1);
+	return(0);
 
 }
 /*---------------------------------------------------------------------
@@ -4205,185 +2037,29 @@
  *              callback function.
  *
  *---------------------------------------------------------------------*/
-#if (FW_TYPE==_UCB_MGR_)
-void SccbMgr_start_sccb(CARD_HANDLE pCurrCard, PUCB p_ucb)
-#else
-#if defined(DOS)
-void SccbMgr_start_sccb(USHORT pCurrCard, PSCCB p_Sccb)
-#else
-void SccbMgr_start_sccb(ULONG pCurrCard, PSCCB p_Sccb)
-#endif
-#endif
+static void SccbMgr_start_sccb(ULONG pCurrCard, PSCCB p_Sccb)
 {
-#if defined(DOS)
-   USHORT ioport;
-#else
    ULONG ioport;
-#endif
    UCHAR thisCard, lun;
 	PSCCB pSaveSccb;
    CALL_BK_FN callback;
 
-#if (FW_TYPE==_UCB_MGR_)
-   PSCCB p_Sccb;
-#endif
-
-   mOS_Lock((PSCCBcard)pCurrCard);
    thisCard = ((PSCCBcard) pCurrCard)->cardIndex;
    ioport = ((PSCCBcard) pCurrCard)->ioPort;
 
-#if (FW_TYPE==_UCB_MGR_)
-   p_Sccb = (PSCCB)p_ucb->UCB_MgrPrivatePtr;
-#endif
-
 	if((p_Sccb->TargID > MAX_SCSI_TAR) || (p_Sccb->Lun > MAX_LUN))
 	{
 
-#if (FW_TYPE==_UCB_MGR_)
-		p_ucb->UCB_hbastat = SCCB_COMPLETE;
-		p_ucb->UCB_status=SCCB_ERROR;
-		callback = (CALL_BK_FN)p_ucb->UCB_callback;
-		if (callback)
-			callback(p_ucb);
-#endif
-
-#if (FW_TYPE==_SCCB_MGR_)
 		p_Sccb->HostStatus = SCCB_COMPLETE;
 		p_Sccb->SccbStatus = SCCB_ERROR;
 		callback = (CALL_BK_FN)p_Sccb->SccbCallback;
 		if (callback)
 			callback(p_Sccb);
-#endif
 
-		mOS_UnLock((PSCCBcard)pCurrCard);
 		return;
 	}
 
-#if (FW_TYPE==_SCCB_MGR_)
-   sinits(p_Sccb,thisCard);
-#endif
-
-
-#if (FW_TYPE==_UCB_MGR_)
-#ifndef NO_IOCTLS
-
-   if (p_ucb->UCB_opcode & OPC_IOCTL)
-	{
-
-		switch (p_ucb->UCB_IOCTLCommand) 
-		{
-			case READ_NVRAM:
-				ReadNVRam((PSCCBcard)pCurrCard,p_ucb);
-				p_ucb->UCB_status=UCB_SUCCESS;
-				callback = (CALL_BK_FN)p_ucb->UCB_callback;
-				if (callback)
-					callback(p_ucb);
-				mOS_UnLock((PSCCBcard)pCurrCard);
-				return;
-
-			case WRITE_NVRAM:
-				WriteNVRam((PSCCBcard)pCurrCard,p_ucb);
-				p_ucb->UCB_status=UCB_SUCCESS;
-				callback = (CALL_BK_FN)p_ucb->UCB_callback;
-				if (callback)
-					callback(p_ucb);
-				mOS_UnLock((PSCCBcard)pCurrCard);
-				return;
-
-			case SEND_SCSI_PASSTHRU:
-#if (FW_TYPE != _SCCB_MGR_)
-				if( p_ucb->UCB_targid >=
-				    ((PSCCBcard)pCurrCard)->cardInfo->ai_MaxTarg )
-				{
-					p_ucb->UCB_status = UCB_ERROR;
-					p_ucb->UCB_hbastat = HASTAT_HW_ERROR;
-					callback = (CALL_BK_FN)p_ucb->UCB_callback;
-					if (callback)
-						callback(p_ucb);
-					mOS_UnLock((PSCCBcard)pCurrCard);
-					return;
-				}
-#endif
-				break;
-
-			case HARD_RESET:
-				p_ucb->UCB_status = UCB_INVALID;
-				callback = (CALL_BK_FN)p_ucb->UCB_callback;
-				if (callback)
-					callback(p_ucb);
-				mOS_UnLock((PSCCBcard)pCurrCard);
-				return;
-			case GET_DEVICE_SYNCRATE:
-				if( !GetDevSyncRate((PSCCBcard)pCurrCard,p_ucb) )
-				{
-					p_ucb->UCB_status = UCB_SUCCESS;
-				}
-				else
-				{
-					p_ucb->UCB_status = UCB_ERROR;
-					p_ucb->UCB_hbastat = HASTAT_HW_ERROR;
-				}
-				callback = (CALL_BK_FN)p_ucb->UCB_callback;
-				if (callback)
-					callback(p_ucb);
-				mOS_UnLock((PSCCBcard)pCurrCard);
-				return;
-			case SET_DEVICE_SYNCRATE:
-				if( !SetDevSyncRate((PSCCBcard)pCurrCard,p_ucb) )
-				{
-					p_ucb->UCB_status = UCB_SUCCESS;
-				}
-				else
-				{
-					p_ucb->UCB_status = UCB_ERROR;
-					p_ucb->UCB_hbastat = HASTAT_HW_ERROR;
-				}
-				callback = (CALL_BK_FN)p_ucb->UCB_callback;
-				if (callback)
-					callback(p_ucb);
-				mOS_UnLock((PSCCBcard)pCurrCard);
-				return;
-			case GET_WIDE_MODE:
-				if( !GetDevWideMode((PSCCBcard)pCurrCard,p_ucb) )
-				{
-					p_ucb->UCB_status = UCB_SUCCESS;
-				}
-				else
-				{
-					p_ucb->UCB_status = UCB_ERROR;
-					p_ucb->UCB_hbastat = HASTAT_HW_ERROR;
-				}
-				callback = (CALL_BK_FN)p_ucb->UCB_callback;
-				if (callback)
-					callback(p_ucb);
-				mOS_UnLock((PSCCBcard)pCurrCard);
-				return;
-			case SET_WIDE_MODE:
-				if( !SetDevWideMode((PSCCBcard)pCurrCard,p_ucb) )
-				{
-					p_ucb->UCB_status = UCB_SUCCESS;
-				}
-				else
-				{
-					p_ucb->UCB_status = UCB_ERROR;
-					p_ucb->UCB_hbastat = HASTAT_HW_ERROR;
-				}
-				callback = (CALL_BK_FN)p_ucb->UCB_callback;
-				if (callback)
-					callback(p_ucb);
-				mOS_UnLock((PSCCBcard)pCurrCard);
-				return;
-			default:
-				p_ucb->UCB_status=UCB_INVALID;
-				callback = (CALL_BK_FN)p_ucb->UCB_callback;
-				if (callback)
-					callback(p_ucb);
-				mOS_UnLock((PSCCBcard)pCurrCard);
-				return;
-		}
-	}
-#endif /* NO_IOCTLS */
-#endif /* (FW_TYPE==_UCB_MGR_) */
+   FPT_sinits(p_Sccb,thisCard);
 
 
    if (!((PSCCBcard) pCurrCard)->cmdCounter)
@@ -4408,12 +2084,12 @@
 			{
 				pSaveSccb = ((PSCCBcard) pCurrCard)->currentSCCB;
 				((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb;
-				queueSelectFail(&BL_Card[thisCard], thisCard);
+				FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
 				((PSCCBcard) pCurrCard)->currentSCCB = pSaveSccb;
 			}
 		else
 			{
-	      queueAddSccb(p_Sccb,thisCard);
+	      FPT_queueAddSccb(p_Sccb,thisCard);
 			}
       }
 
@@ -4423,12 +2099,12 @@
 				{
 					pSaveSccb = ((PSCCBcard) pCurrCard)->currentSCCB;
 					((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb;
-					queueSelectFail(&BL_Card[thisCard], thisCard);
+					FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
 					((PSCCBcard) pCurrCard)->currentSCCB = pSaveSccb;
 				}
 			else
 				{
-		      queueAddSccb(p_Sccb,thisCard);
+		      FPT_queueAddSccb(p_Sccb,thisCard);
 				}
       }
 
@@ -4437,23 +2113,17 @@
       MDISABLE_INT(ioport);
 
 		if((((PSCCBcard) pCurrCard)->globalFlags & F_CONLUN_IO) && 
-			((sccbMgrTbl[thisCard][p_Sccb->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
+			((FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
 			lun = p_Sccb->Lun;
 		else
 			lun = 0;
       if ((((PSCCBcard) pCurrCard)->currentSCCB == NULL) &&
-         (sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0) &&
-         (sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun]
-         == FALSE)) {
+         (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0) &&
+         (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun]
+         == 0)) {
 
             ((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb;
-			   mOS_UnLock((PSCCBcard)pCurrCard);
-#if defined(DOS)
-            ssel((USHORT)p_Sccb->SccbIOPort,thisCard);
-#else
-	    ssel(p_Sccb->SccbIOPort,thisCard);
-#endif
-			   mOS_Lock((PSCCBcard)pCurrCard);
+	    FPT_ssel(p_Sccb->SccbIOPort,thisCard);
          }
 
       else {
@@ -4462,12 +2132,12 @@
 				{
 					pSaveSccb = ((PSCCBcard) pCurrCard)->currentSCCB;
 					((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb;
-					queueSelectFail(&BL_Card[thisCard], thisCard);
+					FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
 					((PSCCBcard) pCurrCard)->currentSCCB = pSaveSccb;
 				}
 			else
 				{
-	         	queueAddSccb(p_Sccb,thisCard);
+	         	FPT_queueAddSccb(p_Sccb,thisCard);
 				}
          }
 
@@ -4475,7 +2145,6 @@
       MENABLE_INT(ioport);
       }
 
-   mOS_UnLock((PSCCBcard)pCurrCard);
 }
 
 
@@ -4488,22 +2157,9 @@
  *              callback function.
  *
  *---------------------------------------------------------------------*/
-#if (FW_TYPE==_UCB_MGR_)
-s32bits SccbMgr_abort_sccb(CARD_HANDLE pCurrCard, PUCB p_ucb)
-#else
-#if defined(DOS)
-int SccbMgr_abort_sccb(USHORT pCurrCard, PSCCB p_Sccb)
-#else
-int SccbMgr_abort_sccb(ULONG pCurrCard, PSCCB p_Sccb)
-#endif
-#endif
-
+static int SccbMgr_abort_sccb(ULONG pCurrCard, PSCCB p_Sccb)
 {
-#if defined(DOS)
-	USHORT ioport;
-#else
 	ULONG ioport;
-#endif
 
 	UCHAR thisCard;
 	CALL_BK_FN callback;
@@ -4512,53 +2168,31 @@
 	PSCCBMgr_tar_info currTar_Info;
 
 
-#if (FW_TYPE==_UCB_MGR_)
-	PSCCB    p_Sccb;
-	p_Sccb=(PSCCB)p_ucb->UCB_MgrPrivatePtr;
-#endif
-
 	ioport = ((PSCCBcard) pCurrCard)->ioPort;
 
 	thisCard = ((PSCCBcard)pCurrCard)->cardIndex;
 
-	mOS_Lock((PSCCBcard)pCurrCard);
-
-	if (RD_HARPOON(ioport+hp_page_ctrl) & G_INT_DISABLE)
-	{
-		mOS_UnLock((PSCCBcard)pCurrCard);
-	}
-
-	else
+	if (!(RD_HARPOON(ioport+hp_page_ctrl) & G_INT_DISABLE))
 	{
 
-		if (queueFindSccb(p_Sccb,thisCard))
+		if (FPT_queueFindSccb(p_Sccb,thisCard))
 		{
 
-			mOS_UnLock((PSCCBcard)pCurrCard);
-
 			((PSCCBcard)pCurrCard)->cmdCounter--;
 
 			if (!((PSCCBcard)pCurrCard)->cmdCounter)
 				WR_HARPOON(ioport+hp_semaphore,(RD_HARPOON(ioport+hp_semaphore)
 					& (UCHAR)(~(SCCB_MGR_ACTIVE | TICKLE_ME)) ));
 
-#if (FW_TYPE==_SCCB_MGR_)
 			p_Sccb->SccbStatus = SCCB_ABORT;
 			callback = p_Sccb->SccbCallback;
 			callback(p_Sccb);
-#else
-			p_ucb->UCB_status=SCCB_ABORT;
-			callback = (CALL_BK_FN)p_ucb->UCB_callback;
-			callback(p_ucb);
-#endif
 
 			return(0);
 		}
 
 		else
 		{
-			mOS_UnLock((PSCCBcard)pCurrCard);
-
 			if (((PSCCBcard)pCurrCard)->currentSCCB == p_Sccb)
 			{
 				p_Sccb->SccbStatus = SCCB_ABORT;
@@ -4579,21 +2213,18 @@
 					{
 						p_Sccb->SccbStatus = SCCB_ABORT;
 						p_Sccb->Sccb_scsistat = ABORT_ST;
-#if (FW_TYPE==_UCB_MGR_)
-						p_ucb->UCB_status=SCCB_ABORT;
-#endif
 						p_Sccb->Sccb_scsimsg = SMABORT_TAG;
 
 						if(((PSCCBcard) pCurrCard)->currentSCCB == NULL)
 						{
 							((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb;
-							ssel(ioport, thisCard);
+							FPT_ssel(ioport, thisCard);
 						}
 						else
 						{
 							pSaveSCCB = ((PSCCBcard) pCurrCard)->currentSCCB;
 							((PSCCBcard) pCurrCard)->currentSCCB = p_Sccb;
-							queueSelectFail((PSCCBcard) pCurrCard, thisCard);
+							FPT_queueSelectFail((PSCCBcard) pCurrCard, thisCard);
 							((PSCCBcard) pCurrCard)->currentSCCB = pSaveSCCB;
 						}
 					}
@@ -4602,9 +2233,9 @@
 				}
 				else
 				{
-					currTar_Info = &sccbMgrTbl[thisCard][p_Sccb->TargID];
+					currTar_Info = &FPT_sccbMgrTbl[thisCard][p_Sccb->TargID];
 
-					if(BL_Card[thisCard].discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_Sccb->Lun]] 
+					if(FPT_BL_Card[thisCard].discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_Sccb->Lun]] 
 							== p_Sccb)
 					{
 						p_Sccb->SccbStatus = SCCB_ABORT;
@@ -4626,37 +2257,20 @@
  *              interrupt for this card and disable the IRQ Pin if so.
  *
  *---------------------------------------------------------------------*/
-#if (FW_TYPE==_UCB_MGR_)
-u08bits SccbMgr_my_int(CARD_HANDLE pCurrCard)
-#else
-#if defined(DOS)
-UCHAR SccbMgr_my_int(USHORT pCurrCard)
-#else
-UCHAR SccbMgr_my_int(ULONG pCurrCard)
-#endif
-#endif
+static UCHAR SccbMgr_my_int(ULONG pCurrCard)
 {
-#if defined(DOS)
-   USHORT ioport;
-#else
    ULONG ioport;
-#endif
 
    ioport = ((PSCCBcard)pCurrCard)->ioPort;
 
    if (RD_HARPOON(ioport+hp_int_status) & INT_ASSERTED)
    {
-
-#if defined(DOS)
-      MDISABLE_INT(ioport);
-#endif
-
-      return(TRUE);
+      return(1);
    }
 
    else
 
-      return(FALSE);
+      return(0);
 }
 
 
@@ -4670,37 +2284,19 @@
  *              us.
  *
  *---------------------------------------------------------------------*/
-#if (FW_TYPE==_UCB_MGR_)
-s32bits SccbMgr_isr(CARD_HANDLE pCurrCard)
-#else
-#if defined(DOS)
-int SccbMgr_isr(USHORT pCurrCard)
-#else
-int SccbMgr_isr(ULONG pCurrCard)
-#endif
-#endif
+static int SccbMgr_isr(ULONG pCurrCard)
 {
    PSCCB currSCCB;
    UCHAR thisCard,result,bm_status, bm_int_st;
    USHORT hp_int;
    UCHAR i, target;
-#if defined(DOS)
-   USHORT ioport;
-#else
    ULONG ioport;
-#endif
-
-   mOS_Lock((PSCCBcard)pCurrCard);
 
    thisCard = ((PSCCBcard)pCurrCard)->cardIndex;
    ioport = ((PSCCBcard)pCurrCard)->ioPort;
 
    MDISABLE_INT(ioport);
 
-#if defined(BUGBUG)
-   WR_HARPOON(ioport+hp_user_defined_D, RD_HARPOON(ioport+hp_int_status));
-#endif
-
    if ((bm_int_st=RD_HARPOON(ioport+hp_int_status)) & EXT_STATUS_ON)
 		bm_status = RD_HARPOON(ioport+hp_ext_status) & (UCHAR)BAD_EXT_STATUS;
    else
@@ -4708,33 +2304,20 @@
 
    WR_HARPOON(ioport+hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
 
-   mOS_UnLock((PSCCBcard)pCurrCard);
-
-   while ((hp_int = RDW_HARPOON((ioport+hp_intstat)) & default_intena) |
+   while ((hp_int = RDW_HARPOON((ioport+hp_intstat)) & FPT_default_intena) |
 	  bm_status)
      {
 
        currSCCB = ((PSCCBcard)pCurrCard)->currentSCCB;
 
-#if defined(BUGBUG)
-   Debug_Load(thisCard,(UCHAR) 0XFF);
-   Debug_Load(thisCard,bm_int_st);
-
-   Debug_Load(thisCard,hp_int_0);
-   Debug_Load(thisCard,hp_int_1);
-#endif
-
-
       if (hp_int & (FIFO | TIMEOUT | RESET | SCAM_SEL) || bm_status) {
-         result = SccbMgr_bad_isr(ioport,thisCard,((PSCCBcard)pCurrCard),hp_int);
+         result = FPT_SccbMgr_bad_isr(ioport,thisCard,((PSCCBcard)pCurrCard),hp_int);
          WRW_HARPOON((ioport+hp_intstat), (FIFO | TIMEOUT | RESET | SCAM_SEL));
          bm_status = 0;
 
          if (result) {
 
-			   mOS_Lock((PSCCBcard)pCurrCard);
             MENABLE_INT(ioport);
-			   mOS_UnLock((PSCCBcard)pCurrCard);
             return(result);
             }
          }
@@ -4753,7 +2336,7 @@
 
          if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT)
 
-            phaseChkFifo(ioport, thisCard);
+            FPT_phaseChkFifo(ioport, thisCard);
 
 /*         WRW_HARPOON((ioport+hp_intstat),
             (BUS_FREE | ICMD_COMP | ITAR_DISC | XFER_CNT_0));
@@ -4761,7 +2344,7 @@
 
 		 WRW_HARPOON((ioport+hp_intstat), CLR_ALL_INT_1);
 
-         autoCmdCmplt(ioport,thisCard);
+         FPT_autoCmdCmplt(ioport,thisCard);
 
          }
 
@@ -4771,7 +2354,7 @@
 
          if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT) {
 
-            phaseChkFifo(ioport, thisCard);
+            FPT_phaseChkFifo(ioport, thisCard);
 
             }
 
@@ -4784,7 +2367,7 @@
             }
 
          currSCCB->Sccb_scsistat = DISCONNECT_ST;
-         queueDisconnect(currSCCB,thisCard);
+         FPT_queueDisconnect(currSCCB,thisCard);
 
             /* Wait for the BusFree before starting a new command.  We
                must also check for being reselected since the BusFree
@@ -4803,9 +2386,7 @@
 	   */
 	   if (!(RDW_HARPOON((ioport+hp_intstat)) & (BUS_FREE | RSEL)))
 	     {
-	       mOS_Lock((PSCCBcard)pCurrCard);
 	       MENABLE_INT(ioport);
-	       mOS_UnLock((PSCCBcard)pCurrCard);
 	       return 0xFE;
 	     }
 
@@ -4825,7 +2406,7 @@
 		      {
             if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT)
 			      {
-               phaseChkFifo(ioport, thisCard);
+               FPT_phaseChkFifo(ioport, thisCard);
                }
 
             if (RD_HARPOON(ioport+hp_gp_reg_1) == SMSAVE_DATA_PTR)
@@ -4837,11 +2418,11 @@
 
             WRW_HARPOON((ioport+hp_intstat), (BUS_FREE | ITAR_DISC));
             currSCCB->Sccb_scsistat = DISCONNECT_ST;
-            queueDisconnect(currSCCB,thisCard);
+            FPT_queueDisconnect(currSCCB,thisCard);
             }
 
-         sres(ioport,thisCard,((PSCCBcard)pCurrCard));
-         phaseDecode(ioport,thisCard);
+         FPT_sres(ioport,thisCard,((PSCCBcard)pCurrCard));
+         FPT_phaseDecode(ioport,thisCard);
 
          }
 
@@ -4850,7 +2431,7 @@
          {
 
             WRW_HARPOON((ioport+hp_intstat), (IDO_STRT | XFER_CNT_0));
-            phaseDecode(ioport,thisCard);
+            FPT_phaseDecode(ioport,thisCard);
 
          }
 
@@ -4860,7 +2441,7 @@
 	 	   WRW_HARPOON((ioport+hp_intstat), (PHASE | IUNKWN | PROG_HLT));
 	 	   if ((RD_HARPOON(ioport+hp_prgmcnt_0) & (UCHAR)0x3f)< (UCHAR)SELCHK)
 	    		{
-	    		phaseDecode(ioport,thisCard);
+	    		FPT_phaseDecode(ioport,thisCard);
 	    		}
 	 	   else
 	    		{
@@ -4885,7 +2466,7 @@
 
          WRW_HARPOON((ioport+hp_intstat), XFER_CNT_0);
 
-         schkdd(ioport,thisCard);
+         FPT_schkdd(ioport,thisCard);
 
          }
 
@@ -4896,10 +2477,10 @@
 
         	if (((PSCCBcard)pCurrCard)->globalFlags & F_HOST_XFER_ACT) {
 
-           	hostDataXferAbort(ioport,thisCard,currSCCB);
+           	FPT_hostDataXferAbort(ioport,thisCard,currSCCB);
 				}
 
-         phaseBusFree(ioport,thisCard);
+         FPT_phaseBusFree(ioport,thisCard);
 			}
 
 
@@ -4919,12 +2500,12 @@
 
          if (((PSCCBcard)pCurrCard)->currentSCCB == NULL) {
 
-            queueSearchSelect(((PSCCBcard)pCurrCard),thisCard);
+            FPT_queueSearchSelect(((PSCCBcard)pCurrCard),thisCard);
             }
 
          if (((PSCCBcard)pCurrCard)->currentSCCB != NULL) {
             ((PSCCBcard)pCurrCard)->globalFlags &= ~F_NEW_SCCB_CMD;
-            ssel(ioport,thisCard);
+            FPT_ssel(ioport,thisCard);
             }
 
          break;
@@ -4933,9 +2514,7 @@
 
       }  /*end while */
 
-   mOS_Lock((PSCCBcard)pCurrCard);
    MENABLE_INT(ioport);
-   mOS_UnLock((PSCCBcard)pCurrCard);
 
    return(0);
 }
@@ -4950,18 +2529,12 @@
  *              processing time.
  *
  *---------------------------------------------------------------------*/
-#if defined(DOS)
-UCHAR SccbMgr_bad_isr(USHORT p_port, UCHAR p_card, PSCCBcard pCurrCard, USHORT p_int)
-#else
-UCHAR SccbMgr_bad_isr(ULONG p_port, UCHAR p_card, PSCCBcard pCurrCard, USHORT p_int)
-#endif
+static UCHAR FPT_SccbMgr_bad_isr(ULONG p_port, UCHAR p_card,
+				 PSCCBcard pCurrCard, USHORT p_int)
 {
-#if defined(HARP_REVX)
-   ULONG timer;
-#endif
-UCHAR temp, ScamFlg;
-PSCCBMgr_tar_info currTar_Info;
-PNVRamInfo pCurrNvRam;
+   UCHAR temp, ScamFlg;
+   PSCCBMgr_tar_info currTar_Info;
+   PNVRamInfo pCurrNvRam;
 
 
    if (RD_HARPOON(p_port+hp_ext_status) &
@@ -4971,7 +2544,7 @@
       if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
          {
 
-         hostDataXferAbort(p_port,p_card, pCurrCard->currentSCCB);
+         FPT_hostDataXferAbort(p_port,p_card, pCurrCard->currentSCCB);
          }
 
       if (RD_HARPOON(p_port+hp_pci_stat_cfg) & REC_MASTER_ABORT)
@@ -4990,7 +2563,7 @@
          if (!pCurrCard->currentSCCB->HostStatus)
             pCurrCard->currentSCCB->HostStatus = SCCB_BM_ERR;
 
-         sxfrp(p_port,p_card);
+         FPT_sxfrp(p_port,p_card);
 
 	     temp = (UCHAR)(RD_HARPOON(p_port+hp_ee_ctrl) &
 							(EXT_ARB_ACK | SCSI_TERM_ENA_H));
@@ -4999,7 +2572,7 @@
 
          if (!(RDW_HARPOON((p_port+hp_intstat)) & (BUS_FREE | RESET)))
             {
-            phaseDecode(p_port,p_card);
+            FPT_phaseDecode(p_port,p_card);
             }
          }
       }
@@ -5014,13 +2587,13 @@
 
                if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
 
-               hostDataXferAbort(p_port,p_card, pCurrCard->currentSCCB);
+               FPT_hostDataXferAbort(p_port,p_card, pCurrCard->currentSCCB);
                }
 
 
            DISABLE_AUTO(p_port);
 
-           sresb(p_port,p_card);
+           FPT_sresb(p_port,p_card);
 
            while(RD_HARPOON(p_port+hp_scsictrl_0) & SCSI_RST) {}
 
@@ -5029,12 +2602,12 @@
 					ScamFlg = pCurrNvRam->niScamConf;
 				}
 				else{
-				   ScamFlg = (UCHAR) utilEERead(p_port, SCAM_CONFIG/2);
+				   ScamFlg = (UCHAR) FPT_utilEERead(p_port, SCAM_CONFIG/2);
 				}
 
-           XbowInit(p_port, ScamFlg);
+           FPT_XbowInit(p_port, ScamFlg);
 
-               scini(p_card, pCurrCard->ourId, 0);
+               FPT_scini(p_card, pCurrCard->ourId, 0);
 
            return(0xFF);
          }
@@ -5044,34 +2617,8 @@
 
       WRW_HARPOON((p_port+hp_intstat), FIFO);
 
-#if defined(HARP_REVX)
-
-      for (timer=0x00FFFFFFL; timer != 0x00000000L; timer--) {
-
-         if (RD_HARPOON(p_port+hp_xferstat) & FIFO_EMPTY)
-            break;
-
-         if (RDW_HARPOON((p_port+hp_intstat)) & BUS_FREE)
-            break;
-         }
-
-
-      if ( (RD_HARPOON(p_port+hp_xferstat) & FIFO_EMPTY) &&
-           (RD_HARPOON(p_port+hp_fiforead) !=
-            RD_HARPOON(p_port+hp_fifowrite)) &&
-           (RD_HARPOON(p_port+hp_xfercnt_0))
-         )
-
-            WR_HARPOON((p_port+hp_xferstat), 0x01);
-
-/*      else
- */
-/*         sxfrp(p_port,p_card);
- */
-#else
       if (pCurrCard->currentSCCB != NULL)
-         sxfrp(p_port,p_card);
-#endif
+         FPT_sxfrp(p_port,p_card);
       }
 
    else if (p_int & TIMEOUT)
@@ -5085,12 +2632,12 @@
       pCurrCard->currentSCCB->HostStatus = SCCB_SELECTION_TIMEOUT;
 
 
-		currTar_Info = &sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
+		currTar_Info = &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
 		if((pCurrCard->globalFlags & F_CONLUN_IO) &&
 			((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
-	      currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] = FALSE;
+	      currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] = 0;
 		else
-	      currTar_Info->TarLUNBusy[0] = FALSE;
+	      currTar_Info->TarLUNBusy[0] = 0;
 
 
       if (currTar_Info->TarEEValue & EE_SYNC_MASK)
@@ -5104,26 +2651,23 @@
          currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
          }
 
-      sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI,currTar_Info);
+      FPT_sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI,currTar_Info);
 
-      queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card);
+      FPT_queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card);
 
       }
 
-#if defined(SCAM_LEV_2)
-
    else if (p_int & SCAM_SEL)
       {
 
-      scarb(p_port,LEVEL2_TAR);
-      scsel(p_port);
-      scasid(p_card, p_port);
+      FPT_scarb(p_port,LEVEL2_TAR);
+      FPT_scsel(p_port);
+      FPT_scasid(p_card, p_port);
 
-      scbusf(p_port);
+      FPT_scbusf(p_port);
 
       WRW_HARPOON((p_port+hp_intstat), SCAM_SEL);
       }
-#endif
 
    return(0x00);
 }
@@ -5131,126 +2675,25 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: SccbMgr_scsi_reset
- *
- * Description: A SCSI bus reset will be generated and all outstanding
- *              Sccbs will be returned via the callback.
- *
- *---------------------------------------------------------------------*/
-#if (FW_TYPE==_UCB_MGR_)
-void SccbMgr_scsi_reset(CARD_HANDLE pCurrCard)
-#else
-#if defined(DOS)
-void SccbMgr_scsi_reset(USHORT pCurrCard)
-#else
-void SccbMgr_scsi_reset(ULONG pCurrCard)
-#endif
-#endif
-{
-   UCHAR thisCard;
-
-   thisCard = ((PSCCBcard)pCurrCard)->cardIndex;
-
-   mOS_Lock((PSCCBcard)pCurrCard);
-
-   if (((PSCCBcard) pCurrCard)->globalFlags & F_GREEN_PC)
-      {
-      WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_clkctrl_0, CLKCTRL_DEFAULT);
-      WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_sys_ctrl, 0x00);
-      }
-
-   sresb(((PSCCBcard)pCurrCard)->ioPort,thisCard);
-
-   if (RD_HARPOON(((PSCCBcard)pCurrCard)->ioPort+hp_ext_status) & BM_CMD_BUSY)
-      {
-      WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_page_ctrl,
-         (RD_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_page_ctrl)
-         & ~SCATTER_EN));
-
-      WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_sg_addr,0x00);
-
-      ((PSCCBcard) pCurrCard)->globalFlags &= ~F_HOST_XFER_ACT;
-      busMstrTimeOut(((PSCCBcard) pCurrCard)->ioPort);
-
-      WR_HARPOON(((PSCCBcard) pCurrCard)->ioPort+hp_int_mask,
-         (INT_CMD_COMPL | SCSI_INTERRUPT));
-      }
-
-/*
-      if (utilEERead(((PSCCBcard)pCurrCard)->ioPort, (SCAM_CONFIG/2))
-            & SCAM_ENABLED)
-*/
-         scini(thisCard, ((PSCCBcard)pCurrCard)->ourId, 0);
-
-#if (FW_TYPE==_UCB_MGR_)
-   ((PSCCBcard)pCurrCard)->cardInfo->ai_AEN_routine(0x01,pCurrCard,0,0,0,0);
-#endif
-
-   mOS_UnLock((PSCCBcard)pCurrCard);
-}
-
-
-/*---------------------------------------------------------------------
- *
- * Function: SccbMgr_timer_expired
- *
- * Description: This function allow me to kill my own job that has not
- *              yet completed, and has cause a timeout to occur.  This
- *              timeout has caused the upper level driver to call this
- *              function.
- *
- *---------------------------------------------------------------------*/
-
-#if (FW_TYPE==_UCB_MGR_)
-void SccbMgr_timer_expired(CARD_HANDLE pCurrCard)
-#else
-#if defined(DOS)
-void SccbMgr_timer_expired(USHORT pCurrCard)
-#else
-void SccbMgr_timer_expired(ULONG pCurrCard)
-#endif
-#endif
-{
-}
-
-#if defined(DOS)
-/*---------------------------------------------------------------------
- *
- * Function: SccbMgr_status
- *
- * Description: This function returns the number of outstanding SCCB's.
- *              This is specific to the DOS enviroment, which needs this
- *              to help them keep protected and real mode commands staight.
- *
- *---------------------------------------------------------------------*/
-
-USHORT SccbMgr_status(USHORT pCurrCard)
-{
-   return(BL_Card[pCurrCard].cmdCounter);
-}
-#endif
-
-/*---------------------------------------------------------------------
- *
  * Function: SccbMgrTableInit
  *
  * Description: Initialize all Sccb manager data structures.
  *
  *---------------------------------------------------------------------*/
 
-void SccbMgrTableInitAll()
+static void FPT_SccbMgrTableInitAll()
 {
    UCHAR thisCard;
 
    for (thisCard = 0; thisCard < MAX_CARDS; thisCard++)
       {
-      SccbMgrTableInitCard(&BL_Card[thisCard],thisCard);
+      FPT_SccbMgrTableInitCard(&FPT_BL_Card[thisCard],thisCard);
 
-      BL_Card[thisCard].ioPort      = 0x00;
-      BL_Card[thisCard].cardInfo    = NULL;
-      BL_Card[thisCard].cardIndex   = 0xFF;
-      BL_Card[thisCard].ourId       = 0x00;
-		BL_Card[thisCard].pNvRamInfo	= NULL;
+      FPT_BL_Card[thisCard].ioPort      = 0x00;
+      FPT_BL_Card[thisCard].cardInfo    = NULL;
+      FPT_BL_Card[thisCard].cardIndex   = 0xFF;
+      FPT_BL_Card[thisCard].ourId       = 0x00;
+		FPT_BL_Card[thisCard].pNvRamInfo	= NULL;
       }
 }
 
@@ -5263,20 +2706,20 @@
  *
  *---------------------------------------------------------------------*/
 
-void SccbMgrTableInitCard(PSCCBcard pCurrCard, UCHAR p_card)
+static void FPT_SccbMgrTableInitCard(PSCCBcard pCurrCard, UCHAR p_card)
 {
    UCHAR scsiID, qtag;
 
 	for (qtag = 0; qtag < QUEUE_DEPTH; qtag++)
 	{
-		BL_Card[p_card].discQ_Tbl[qtag] = NULL;
+		FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
 	}
 
    for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++)
       {
-      sccbMgrTbl[p_card][scsiID].TarStatus = 0;
-      sccbMgrTbl[p_card][scsiID].TarEEValue = 0;
-      SccbMgrTableInitTarget(p_card, scsiID);
+      FPT_sccbMgrTbl[p_card][scsiID].TarStatus = 0;
+      FPT_sccbMgrTbl[p_card][scsiID].TarEEValue = 0;
+      FPT_SccbMgrTableInitTarget(p_card, scsiID);
       }
 
    pCurrCard->scanIndex = 0x00;
@@ -5298,13 +2741,13 @@
  *
  *---------------------------------------------------------------------*/
 
-void SccbMgrTableInitTarget(UCHAR p_card, UCHAR target)
+static void FPT_SccbMgrTableInitTarget(UCHAR p_card, UCHAR target)
 {
 
 	UCHAR lun, qtag;
 	PSCCBMgr_tar_info currTar_Info;
 
-	currTar_Info = &sccbMgrTbl[p_card][target];
+	currTar_Info = &FPT_sccbMgrTbl[p_card][target];
 
 	currTar_Info->TarSelQ_Cnt = 0;
 	currTar_Info->TarSyncCtrl = 0;
@@ -5312,160 +2755,28 @@
 	currTar_Info->TarSelQ_Head = NULL;
 	currTar_Info->TarSelQ_Tail = NULL;
 	currTar_Info->TarTagQ_Cnt = 0;
-	currTar_Info->TarLUN_CA = FALSE;
+	currTar_Info->TarLUN_CA = 0;
 
 
 	for (lun = 0; lun < MAX_LUN; lun++)
 	{
-		currTar_Info->TarLUNBusy[lun] = FALSE;
+		currTar_Info->TarLUNBusy[lun] = 0;
 		currTar_Info->LunDiscQ_Idx[lun] = 0;
 	}
 
 	for (qtag = 0; qtag < QUEUE_DEPTH; qtag++)
 	{
-		if(BL_Card[p_card].discQ_Tbl[qtag] != NULL)
+		if(FPT_BL_Card[p_card].discQ_Tbl[qtag] != NULL)
 		{
-			if(BL_Card[p_card].discQ_Tbl[qtag]->TargID == target)
+			if(FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == target)
 			{
-				BL_Card[p_card].discQ_Tbl[qtag] = NULL;
-				BL_Card[p_card].discQCount--;
+				FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
+				FPT_BL_Card[p_card].discQCount--;
 			}
 		}
 	}
 }
 
-#if defined(BUGBUG)
-
-/*****************************************************************
- * Save the current byte in the debug array
- *****************************************************************/
-
-
-void Debug_Load(UCHAR p_card, UCHAR p_bug_data)
-{
-   debug_int[p_card][debug_index[p_card]] = p_bug_data;
-   debug_index[p_card]++;
-
-   if (debug_index[p_card] == debug_size)
-
-      debug_index[p_card] = 0;
-}
-
-#endif
-#ident "$Id: sccb_dat.c 1.10 1997/02/22 03:16:02 awin Exp $"
-/*----------------------------------------------------------------------
- *
- *
- *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
- *
- *   This file is available under both the GNU General Public License
- *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- *   $Workfile:   sccb_dat.c  $
- *
- *   Description:  Functions relating to handling of the SCCB interface 
- *                 between the device driver and the HARPOON.
- *
- *   $Date: 1997/02/22 03:16:02 $
- *
- *   $Revision: 1.10 $
- *
- *----------------------------------------------------------------------*/
-
-/*#include <globals.h>*/
-
-#if (FW_TYPE==_UCB_MGR_)
-	/*#include <budi.h>*/
-#endif
-
-/*#include <sccbmgr.h>*/
-/*#include <blx30.h>*/
-/*#include <target.h>*/
-/*#include <harpoon.h>*/
-
-/*
-**  IMPORTANT NOTE!!!
-**
-**  You MUST preassign all data to a valid value or zero.  This is
-**  required due to the MS compiler bug under OS/2 and Solaris Real-Mode
-**  driver environment.
-*/
-
-
-SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] = { { { 0 } } };
-SCCBCARD BL_Card[MAX_CARDS] = { { 0 } };
-SCCBSCAM_INFO scamInfo[MAX_SCSI_TAR] = { { { 0 } } };
-NVRAMINFO nvRamInfo[MAX_MB_CARDS] = { { 0 } };
-
-
-#if defined(OS2)
-void (far *s_PhaseTbl[8]) (ULONG, UCHAR) = { 0 };
-UCHAR temp_id_string[ID_STRING_LENGTH] = { 0 };
-#elif defined(SOLARIS_REAL_MODE) || defined(__STDC__)
-void (*s_PhaseTbl[8]) (ULONG, UCHAR) = { 0 };
-#else
-void (*s_PhaseTbl[8]) ();
-#endif
-
-#if defined(DOS)
-UCHAR first_time = 0;
-#endif
-
-UCHAR mbCards = 0;
-UCHAR scamHAString[] = {0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I', 'C', \
-								' ', 'B', 'T', '-', '9', '3', '0', \
-								0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, \
-								0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
-
-USHORT default_intena = 0;
-
-#if defined(BUGBUG)
-UCHAR    debug_int[MAX_CARDS][debug_size] = { 0 };
-UCHAR    debug_index[MAX_CARDS] = { 0 };
-UCHAR    reserved_1[3] = { 0 };
-#endif
-#ident "$Id: scsi.c 1.23 1997/07/09 21:42:54 mohan Exp $"
-/*----------------------------------------------------------------------
- *
- *
- *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
- *
- *   This file is available under both the GNU General Public License
- *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- *   $Workfile:   scsi.c  $
- *
- *   Description:  Functions for handling SCSI bus functions such as
- *                 selection/reselection, sync negotiation, message-in
- *                 decoding.
- *
- *   $Date: 1997/07/09 21:42:54 $
- *
- *   $Revision: 1.23 $
- *
- *----------------------------------------------------------------------*/
-
-/*#include <globals.h>*/
-
-#if (FW_TYPE==_UCB_MGR_)
-	/*#include <budi.h>*/
-#endif
-
-/*#include <sccbmgr.h>*/
-/*#include <blx30.h>*/
-/*#include <target.h>*/
-/*#include <scsi2.h>*/
-/*#include <eeprom.h>*/
-/*#include <harpoon.h>*/
-
-
-/*
-extern SCCBCARD BL_Card[MAX_CARDS];
-extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];
-#if defined(BUGBUG)
-void Debug_Load(UCHAR p_card, UCHAR p_bug_data);
-#endif
-*/
 
 /*---------------------------------------------------------------------
  *
@@ -5476,11 +2787,7 @@
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-UCHAR sfm(USHORT port, PSCCB pCurrSCCB)
-#else
-UCHAR sfm(ULONG port, PSCCB pCurrSCCB)
-#endif
+static UCHAR FPT_sfm(ULONG port, PSCCB pCurrSCCB)
 {
 	UCHAR message;
 	USHORT TimeOutLoop;
@@ -5547,42 +2854,27 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: ssel
+ * Function: FPT_ssel
  *
  * Description: Load up automation and select target device.
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void ssel(USHORT port, UCHAR p_card)
-#else
-void ssel(ULONG port, UCHAR p_card)
-#endif
+static void FPT_ssel(ULONG port, UCHAR p_card)
 {
 
-#if defined(DOS)
    UCHAR auto_loaded, i, target, *theCCB;
-#elif defined(OS2)
-   UCHAR auto_loaded, i, target;
-   UCHAR far *theCCB;
-#else
-   UCHAR auto_loaded, i, target, *theCCB;
-#endif
 
-#if defined(DOS)
-   USHORT cdb_reg;
-#else
    ULONG cdb_reg;
-#endif
    PSCCBcard CurrCard;
    PSCCB currSCCB;
    PSCCBMgr_tar_info currTar_Info;
    UCHAR lastTag, lun;
 
-   CurrCard = &BL_Card[p_card];
+   CurrCard = &FPT_BL_Card[p_card];
    currSCCB = CurrCard->currentSCCB;
    target = currSCCB->TargID;
-   currTar_Info = &sccbMgrTbl[p_card][target];
+   currTar_Info = &FPT_sccbMgrTbl[p_card][target];
    lastTag = CurrCard->tagQ_Lst;
 
    ARAM_ACCESS(port);
@@ -5599,60 +2891,53 @@
 		lun = 0;
 
 
-#if defined(DOS)
-   currTar_Info->TarLUNBusy[lun] = TRUE;
-
-#else
-
    if (CurrCard->globalFlags & F_TAG_STARTED)
       {
       if (!(currSCCB->ControlByte & F_USE_CMD_Q))
          {
-      	if ((currTar_Info->TarLUN_CA == FALSE)
+      	if ((currTar_Info->TarLUN_CA == 0)
       	    && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
       	    == TAG_Q_TRYING))
             {
 
 	         if (currTar_Info->TarTagQ_Cnt !=0)
                   {
-         		   currTar_Info->TarLUNBusy[lun] = TRUE;
-            		queueSelectFail(CurrCard,p_card);
+         		   currTar_Info->TarLUNBusy[lun] = 1;
+            		FPT_queueSelectFail(CurrCard,p_card);
 					   SGRAM_ACCESS(port);
          		   return;
          		   }
 
             else {
-         		  currTar_Info->TarLUNBusy[lun] = TRUE;
+         		  currTar_Info->TarLUNBusy[lun] = 1;
          		  }
 
    	      }  /*End non-tagged */
 
 	      else {
-	         currTar_Info->TarLUNBusy[lun] = TRUE;
+	         currTar_Info->TarLUNBusy[lun] = 1;
 	         }
 
 	      }  /*!Use cmd Q Tagged */
 
 	   else {
-   	     if (currTar_Info->TarLUN_CA == TRUE)
+   	     if (currTar_Info->TarLUN_CA == 1)
                {
-      	      queueSelectFail(CurrCard,p_card);
+      	      FPT_queueSelectFail(CurrCard,p_card);
 				   SGRAM_ACCESS(port);
       	      return;
 	            }
 
-	        currTar_Info->TarLUNBusy[lun] = TRUE;
+	        currTar_Info->TarLUNBusy[lun] = 1;
 
    	     }  /*else use cmd Q tagged */
 
       }  /*if glob tagged started */
 
    else {
-        currTar_Info->TarLUNBusy[lun] = TRUE;
+        currTar_Info->TarLUNBusy[lun] = 1;
         }
 
-#endif /* DOS */
-
 
 
 	if((((CurrCard->globalFlags & F_CONLUN_IO) && 
@@ -5661,8 +2946,8 @@
 	{
 		if(CurrCard->discQCount >= QUEUE_DEPTH)
 		{
-			currTar_Info->TarLUNBusy[lun] = TRUE;
-			queueSelectFail(CurrCard,p_card);
+			currTar_Info->TarLUNBusy[lun] = 1;
+			FPT_queueSelectFail(CurrCard,p_card);
 			SGRAM_ACCESS(port);
 			return;
 		}
@@ -5680,8 +2965,8 @@
 		}
 		if(i == QUEUE_DEPTH)
 		{
-			currTar_Info->TarLUNBusy[lun] = TRUE;
-			queueSelectFail(CurrCard,p_card);
+			currTar_Info->TarLUNBusy[lun] = 1;
+			FPT_queueSelectFail(CurrCard,p_card);
 			SGRAM_ACCESS(port);
 			return;
 		}
@@ -5689,7 +2974,7 @@
 
 
 
-   auto_loaded = FALSE;
+   auto_loaded = 0;
 
    WR_HARPOON(port+hp_select_id, target);
    WR_HARPOON(port+hp_gp_reg_3, target);  /* Use by new automation logic */
@@ -5703,7 +2988,7 @@
       currSCCB->Sccb_scsimsg = SMDEV_RESET;
 
       WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT));
-      auto_loaded = TRUE;
+      auto_loaded = 1;
       currSCCB->Sccb_scsistat = SELECT_BDR_ST;
 
       if (currTar_Info->TarEEValue & EE_SYNC_MASK)
@@ -5712,16 +2997,13 @@
 	      currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
 	      }
 
-#if defined(WIDE_SCSI)
-
       if (currTar_Info->TarEEValue & EE_WIDE_SCSI)
          {
       	currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
       	}
-#endif
 
-      sssyncv(port, target, NARROW_SCSI,currTar_Info);
-      SccbMgrTableInitTarget(p_card, target);
+      FPT_sssyncv(port, target, NARROW_SCSI,currTar_Info);
+      FPT_SccbMgrTableInitTarget(p_card, target);
 
       }
 
@@ -5740,24 +3022,18 @@
 			WRW_HARPOON((port+SYNC_MSGS+4), (BRH_OP+ALWAYS+NP ));
 
 			WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT));
-			auto_loaded = TRUE;
+			auto_loaded = 1;
 		
 		}
 
-#if defined(WIDE_SCSI)
-
-
    else if (!(currTar_Info->TarStatus & WIDE_NEGOCIATED))  {
-      auto_loaded = siwidn(port,p_card);
+      auto_loaded = FPT_siwidn(port,p_card);
       currSCCB->Sccb_scsistat = SELECT_WN_ST;
       }
 
-#endif
-
-
    else if (!((currTar_Info->TarStatus & TAR_SYNC_MASK)
       == SYNC_SUPPORTED))  {
-      auto_loaded = sisyncn(port,p_card, FALSE);
+      auto_loaded = FPT_sisyncn(port,p_card, 0);
       currSCCB->Sccb_scsistat = SELECT_SN_ST;
       }
 
@@ -5765,7 +3041,6 @@
    if (!auto_loaded)
       {
 
-#if !defined(DOS)
       if (currSCCB->ControlByte & F_USE_CMD_Q)
          {
 
@@ -5789,7 +3064,7 @@
                the wheels fall off. */
             currSCCB->Sccb_scsistat = SELECT_ST;
 
-	         currTar_Info->TarLUNBusy[lun] = TRUE;
+	         currTar_Info->TarLUNBusy[lun] = 1;
             }
 
          else
@@ -5818,8 +3093,8 @@
 
             if ( i == QUEUE_DEPTH )
                {
-   	         currTar_Info->TarLUNBusy[lun] = TRUE;
-               queueSelectFail(CurrCard,p_card);
+   	         currTar_Info->TarLUNBusy[lun] = 1;
+               FPT_queueSelectFail(CurrCard,p_card);
 				   SGRAM_ACCESS(port);
    	         return;
    	         }
@@ -5832,7 +3107,6 @@
 
       else
          {
-#endif   /* !DOS */
 
          WRW_HARPOON((port+ID_MSG_STRT),BRH_OP+ALWAYS+NTCMD);
 
@@ -5842,16 +3116,10 @@
          currSCCB->Sccb_scsistat = SELECT_ST;
 
          WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT));
-#if !defined(DOS)
          }
-#endif
 
 
-#if defined(OS2)
-      theCCB = (UCHAR far *)&currSCCB->Cdb[0];
-#else
       theCCB = (UCHAR *)&currSCCB->Cdb[0];
-#endif
 
       cdb_reg = port + CMD_STRT;
 
@@ -5867,10 +3135,8 @@
 
       }  /* auto_loaded */
 
-#if defined(WIDE_SCSI)
    WRW_HARPOON((port+hp_fiforead), (USHORT) 0x00);
    WR_HARPOON(port+hp_xferstat, 0x00);
-#endif
 
    WRW_HARPOON((port+hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE));
 
@@ -5899,30 +3165,16 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: sres
+ * Function: FPT_sres
  *
  * Description: Hookup the correct CCB and handle the incoming messages.
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void sres(USHORT port, UCHAR p_card, PSCCBcard pCurrCard)
-#else
-void sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard)
-#endif
+static void FPT_sres(ULONG port, UCHAR p_card, PSCCBcard pCurrCard)
 {
 
-#if defined(V302)
-#ifdef DOS
-   UCHAR our_target,message, msgRetryCount;
-   extern UCHAR lun, tag;
-#else
-   UCHAR our_target,message,lun,tag, msgRetryCount;
-#endif
-
-#else  /* V302 */
    UCHAR our_target, message, lun = 0, tag, msgRetryCount;
-#endif /* V302 */
 
 
    PSCCBMgr_tar_info currTar_Info;
@@ -5933,7 +3185,7 @@
 
 	if(pCurrCard->currentSCCB != NULL)
 	{
-		currTar_Info = &sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
+		currTar_Info = &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
 		DISABLE_AUTO(port);
 
 
@@ -5954,7 +3206,7 @@
 		if(((pCurrCard->globalFlags & F_CONLUN_IO) &&
 			((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
 		{
-      	currTar_Info->TarLUNBusy[currSCCB->Lun] = FALSE;
+      	currTar_Info->TarLUNBusy[currSCCB->Lun] = 0;
 			if(currSCCB->Sccb_scsistat != ABORT_ST)
 			{
 				pCurrCard->discQCount--;
@@ -5964,7 +3216,7 @@
 		}
 		else
 		{
-	      currTar_Info->TarLUNBusy[0] = FALSE;
+	      currTar_Info->TarLUNBusy[0] = 0;
 			if(currSCCB->Sccb_tag)
 			{
 				if(currSCCB->Sccb_scsistat != ABORT_ST)
@@ -5982,29 +3234,21 @@
 			}
 		}
 
-      queueSelectFail(&BL_Card[p_card],p_card);
+      FPT_queueSelectFail(&FPT_BL_Card[p_card],p_card);
 	}
 
-#if defined(WIDE_SCSI)
 	WRW_HARPOON((port+hp_fiforead), (USHORT) 0x00);
-#endif
 
 
 	our_target = (UCHAR)(RD_HARPOON(port+hp_select_id) >> 4);
-	currTar_Info = &sccbMgrTbl[p_card][our_target];
+	currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
 
 
 	msgRetryCount = 0;
 	do
 	{
 
-#if defined(V302)
-
-		message = GetTarLun(port, p_card, our_target, pCurrCard, &tag, &lun);
-
-#else /* V302 */
-
-		currTar_Info = &sccbMgrTbl[p_card][our_target];
+		currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
 		tag = 0;
 
 
@@ -6022,7 +3266,7 @@
 		if ((RD_HARPOON(port+hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH)
 		{
 
-			message = sfm(port,pCurrCard->currentSCCB);
+			message = FPT_sfm(port,pCurrCard->currentSCCB);
 			if (message)
 			{
 
@@ -6030,7 +3274,6 @@
 				{
 					lun = message & (UCHAR)LUN_MASK;
 
-#if !defined(DOS)
 					if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_TRYING)
 					{
 						if (currTar_Info->TarTagQ_Cnt != 0)
@@ -6041,21 +3284,21 @@
 								ACCEPT_MSG(port);    /*Release the ACK for ID msg. */
 
 
-								message = sfm(port,pCurrCard->currentSCCB);
+								message = FPT_sfm(port,pCurrCard->currentSCCB);
 								if (message)
 								{
 									ACCEPT_MSG(port);
 								}
 
 								else
-   								message = FALSE;
+   								message = 0;
 
-								if(message != FALSE)
+								if(message != 0)
 								{
-									tag = sfm(port,pCurrCard->currentSCCB);
+									tag = FPT_sfm(port,pCurrCard->currentSCCB);
 
 									if (!(tag)) 
-										message = FALSE;
+										message = 0;
 								}
 
 							} /*C.A. exists! */
@@ -6063,7 +3306,6 @@
 						} /*End Q cnt != 0 */
 
 					} /*End Tag cmds supported! */
-#endif /* !DOS */
 
 				} /*End valid ID message.  */
 
@@ -6078,7 +3320,7 @@
 			else
 			{
 
-				message = FALSE;
+				message = 0;
 			}
 		}
 		else
@@ -6091,49 +3333,47 @@
 
 			return;
 		}
-	
-#endif /* V302 */
 
-		if(message == FALSE)
+		if(message == 0)
 		{
 			msgRetryCount++;
 			if(msgRetryCount == 1)
 			{
-				SendMsg(port, SMPARITY);
+				FPT_SendMsg(port, SMPARITY);
 			}
 			else
 			{
-				SendMsg(port, SMDEV_RESET);
+				FPT_SendMsg(port, SMDEV_RESET);
 
-				sssyncv(port, our_target, NARROW_SCSI,currTar_Info);
+				FPT_sssyncv(port, our_target, NARROW_SCSI,currTar_Info);
 
-				if (sccbMgrTbl[p_card][our_target].TarEEValue & EE_SYNC_MASK) 
+				if (FPT_sccbMgrTbl[p_card][our_target].TarEEValue & EE_SYNC_MASK) 
 				{
 			
-					sccbMgrTbl[p_card][our_target].TarStatus &= ~TAR_SYNC_MASK;
+					FPT_sccbMgrTbl[p_card][our_target].TarStatus &= ~TAR_SYNC_MASK;
 
 				}
 
-				if (sccbMgrTbl[p_card][our_target].TarEEValue & EE_WIDE_SCSI) 
+				if (FPT_sccbMgrTbl[p_card][our_target].TarEEValue & EE_WIDE_SCSI) 
 				{
 
-					sccbMgrTbl[p_card][our_target].TarStatus &= ~TAR_WIDE_MASK;
+					FPT_sccbMgrTbl[p_card][our_target].TarStatus &= ~TAR_WIDE_MASK;
 				}
 
 
-				queueFlushTargSccb(p_card, our_target, SCCB_COMPLETE);
-				SccbMgrTableInitTarget(p_card,our_target);
+				FPT_queueFlushTargSccb(p_card, our_target, SCCB_COMPLETE);
+				FPT_SccbMgrTableInitTarget(p_card,our_target);
 				return;
 			}
 		}
-	}while(message == FALSE);
+	}while(message == 0);
 
 
 
 	if(((pCurrCard->globalFlags & F_CONLUN_IO) &&
 		((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
 	{
-		currTar_Info->TarLUNBusy[lun] = TRUE;
+		currTar_Info->TarLUNBusy[lun] = 1;
 		pCurrCard->currentSCCB = pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[lun]];
 		if(pCurrCard->currentSCCB != NULL)
 		{
@@ -6146,7 +3386,7 @@
 	}
 	else
 	{
-		currTar_Info->TarLUNBusy[0] = TRUE;
+		currTar_Info->TarLUNBusy[0] = 1;
 
 
 		if (tag)
@@ -6182,7 +3422,7 @@
 		/* During Abort Tag command, the target could have got re-selected
 			and completed the command. Check the select Q and remove the CCB
 			if it is in the Select Q */
-			queueFindSccb(pCurrCard->currentSCCB, p_card);
+			FPT_queueFindSccb(pCurrCard->currentSCCB, p_card);
 		}
 	}
 
@@ -6192,106 +3432,7 @@
 	  (RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) ;
 }
 
-#if defined(V302)
-
-#if defined(DOS)
-UCHAR GetTarLun(USHORT port, UCHAR p_card, UCHAR our_target, PSCCBcard pCurrCard, PUCHAR tag, PUCHAR lun)
-#else
-UCHAR GetTarLun(ULONG port, UCHAR p_card, UCHAR our_target, PSCCBcard pCurrCard, PUCHAR tag, PUCHAR lun)
-#endif
-{
-   UCHAR message;
-   PSCCBMgr_tar_info currTar_Info;
-
-
-	currTar_Info = &sccbMgrTbl[p_card][our_target];
-	*tag = 0;
-
-
-	while(!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ))
-	{
-		if (! (RD_HARPOON(port+hp_scsisig) & SCSI_BSY))
-		{
-
-			WRW_HARPOON((port+hp_intstat), PHASE);
-			return(TRUE);
-		}
-	}
-
-	WRW_HARPOON((port+hp_intstat), PHASE);
-	if ((RD_HARPOON(port+hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH)
-	{
-
-		message = sfm(port,pCurrCard->currentSCCB);
-		if (message)
-		{
-
-			if (message <= (0x80 | LUN_MASK))
-			{
-				*lun = message & (UCHAR)LUN_MASK;
-
-#if !defined(DOS)
-				if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_TRYING)
-				{
-					if (currTar_Info->TarTagQ_Cnt != 0)
-					{
-
-						if (!(currTar_Info->TarLUN_CA))
-						{
-							ACCEPT_MSG(port);    /*Release the ACK for ID msg. */
-
-
-							message = sfm(port,pCurrCard->currentSCCB);
-							if (message)
-							{
-								ACCEPT_MSG(port);
-							}
-
-							else
-   							return(FALSE);
-
-							*tag = sfm(port,pCurrCard->currentSCCB);
-
-							if (!(*tag)) return(FALSE);
-
-						} /*C.A. exists! */
-
-					} /*End Q cnt != 0 */
-
-				} /*End Tag cmds supported! */
-#endif /* !DOS */
-
-			} /*End valid ID message.  */
-
-			else
-			{
-
-				ACCEPT_MSG_ATN(port);
-			}
-
-		} /* End good id message. */
-
-		else
-		{
-
-			return(FALSE);
-		}
-	}
-	else
-	{
-		ACCEPT_MSG_ATN(port);
-		return(TRUE);
-	}
-	return(TRUE);
-}
-
-#endif /* V302 */
-
-#if defined(DOS)
-void SendMsg(USHORT port, UCHAR message)
-#else
-void SendMsg(ULONG port, UCHAR message)
-#endif
+static void FPT_SendMsg(ULONG port, UCHAR message)
 {
 	while(!(RD_HARPOON(port+hp_scsisig) & SCSI_REQ))
 	{
@@ -6334,26 +3475,22 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: sdecm
+ * Function: FPT_sdecm
  *
  * Description: Determine the proper responce to the message from the
  *              target device.
  *
  *---------------------------------------------------------------------*/
-#if defined(DOS)
-void sdecm(UCHAR message, USHORT port, UCHAR p_card)
-#else
-void sdecm(UCHAR message, ULONG port, UCHAR p_card)
-#endif
+static void FPT_sdecm(UCHAR message, ULONG port, UCHAR p_card)
 {
 	PSCCB currSCCB;
 	PSCCBcard CurrCard;
 	PSCCBMgr_tar_info currTar_Info;
 
-	CurrCard = &BL_Card[p_card];
+	CurrCard = &FPT_BL_Card[p_card];
 	currSCCB = CurrCard->currentSCCB;
 
-	currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID];
+	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
 
 	if (message == SMREST_DATA_PTR)
 	{
@@ -6361,7 +3498,7 @@
 		{
 			currSCCB->Sccb_ATC = currSCCB->Sccb_savedATC;
 
-			hostDataXferRestart(currSCCB);
+			FPT_hostDataXferRestart(currSCCB);
 		}
 
 		ACCEPT_MSG(port);
@@ -6417,7 +3554,6 @@
 					currTar_Info->TarEEValue &= ~EE_SYNC_MASK;
 				}
 
-#if defined(WIDE_SCSI)
 				else if ((currSCCB->Sccb_scsistat == SELECT_WN_ST))
 				{
 
@@ -6428,7 +3564,6 @@
 					currTar_Info->TarEEValue &= ~EE_WIDE_SCSI;
 
 				}
-#endif
 
 				else if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_TRYING )
 				{
@@ -6460,9 +3595,9 @@
 
 				if((CurrCard->globalFlags & F_CONLUN_IO) &&
 					((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
-					currTar_Info->TarLUNBusy[currSCCB->Lun] = TRUE;
+					currTar_Info->TarLUNBusy[currSCCB->Lun] = 1;
 				else
-					currTar_Info->TarLUNBusy[0] = TRUE;
+					currTar_Info->TarLUNBusy[0] = 1;
 
 
 				currSCCB->ControlByte &= ~(UCHAR)F_USE_CMD_Q;
@@ -6490,7 +3625,7 @@
 	{
 
 		ACCEPT_MSG(port);
-		shandem(port,p_card,currSCCB);
+		FPT_shandem(port,p_card,currSCCB);
 	}
 
 	else if (message == SMIGNORWR)
@@ -6498,7 +3633,7 @@
 
 		ACCEPT_MSG(port);          /* ACK the RESIDUE MSG */
 
-		message = sfm(port,currSCCB);
+		message = FPT_sfm(port,currSCCB);
 
 		if(currSCCB->Sccb_scsimsg != SMPARITY)
 			ACCEPT_MSG(port);
@@ -6520,25 +3655,21 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: shandem
+ * Function: FPT_shandem
  *
  * Description: Decide what to do with the extended message.
  *
  *---------------------------------------------------------------------*/
-#if defined(DOS)
-void shandem(USHORT port, UCHAR p_card, PSCCB pCurrSCCB)
-#else
-void shandem(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
-#endif
+static void FPT_shandem(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
 {
 	UCHAR length,message;
 
-	length = sfm(port,pCurrSCCB);
+	length = FPT_sfm(port,pCurrSCCB);
 	if (length) 
 	{
 
 		ACCEPT_MSG(port);
-		message = sfm(port,pCurrSCCB);
+		message = FPT_sfm(port,pCurrSCCB);
 		if (message) 
 		{
 
@@ -6549,7 +3680,7 @@
 				{
 
 					ACCEPT_MSG(port);
-					stsyncn(port,p_card);
+					FPT_stsyncn(port,p_card);
 				}
 				else 
 				{
@@ -6558,7 +3689,6 @@
 					ACCEPT_MSG_ATN(port);
 				}
 			}
-#if defined(WIDE_SCSI)
 			else if (message == SMWDTR) 
 			{
 
@@ -6566,7 +3696,7 @@
 				{
 
 					ACCEPT_MSG(port);
-					stwidn(port,p_card);
+					FPT_stwidn(port,p_card);
 				}
 				else 
 				{
@@ -6577,7 +3707,6 @@
 					WR_HARPOON(port+hp_autostart_1, (AUTO_IMMED+DISCONNECT_START));
 				}
 			}
-#endif
 			else 
 			{
 
@@ -6603,24 +3732,20 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: sisyncn
+ * Function: FPT_sisyncn
  *
  * Description: Read in a message byte from the SCSI bus, and check
  *              for a parity error.
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-UCHAR sisyncn(USHORT port, UCHAR p_card, UCHAR syncFlag)
-#else
-UCHAR sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag)
-#endif
+static UCHAR FPT_sisyncn(ULONG port, UCHAR p_card, UCHAR syncFlag)
 {
    PSCCB currSCCB;
    PSCCBMgr_tar_info currTar_Info;
 
-   currSCCB = BL_Card[p_card].currentSCCB;
-   currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID];
+   currSCCB = FPT_BL_Card[p_card].currentSCCB;
+   currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
 
    if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)) {
 
@@ -6656,7 +3781,7 @@
       WRW_HARPOON((port+SYNC_MSGS+12),(BRH_OP+ALWAYS+NP      ));
 
 
-		if(syncFlag == FALSE)
+		if(syncFlag == 0)
 		{
 		   WR_HARPOON(port+hp_autostart_3, (SELECT+SELCHK_STRT));
 	      currTar_Info->TarStatus = ((currTar_Info->TarStatus &
@@ -6668,14 +3793,14 @@
 		}
 
 
-      return(TRUE);
+      return(1);
       }
 
    else {
 
       currTar_Info->TarStatus |=	 (UCHAR)SYNC_SUPPORTED;
       currTar_Info->TarEEValue &= ~EE_SYNC_MASK;
-      return(FALSE);
+      return(0);
       }
 }
 
@@ -6683,26 +3808,22 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: stsyncn
+ * Function: FPT_stsyncn
  *
  * Description: The has sent us a Sync Nego message so handle it as
  *              necessary.
  *
  *---------------------------------------------------------------------*/
-#if defined(DOS)
-void stsyncn(USHORT port, UCHAR p_card)
-#else
-void stsyncn(ULONG port, UCHAR p_card)
-#endif
+static void FPT_stsyncn(ULONG port, UCHAR p_card)
 {
    UCHAR sync_msg,offset,sync_reg,our_sync_msg;
    PSCCB currSCCB;
    PSCCBMgr_tar_info currTar_Info;
 
-   currSCCB = BL_Card[p_card].currentSCCB;
-   currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID];
+   currSCCB = FPT_BL_Card[p_card].currentSCCB;
+   currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
 
-   sync_msg = sfm(port,currSCCB);
+   sync_msg = FPT_sfm(port,currSCCB);
 
 	if((sync_msg == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY))
 	{
@@ -6713,7 +3834,7 @@
    ACCEPT_MSG(port);
 
 
-   offset = sfm(port,currSCCB);
+   offset = FPT_sfm(port,currSCCB);
 
 	if((offset == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY))
 	{
@@ -6783,7 +3904,6 @@
       }
 
 
-#if defined(WIDE_SCSI)
    if (currTar_Info->TarStatus & WIDE_ENABLED)
 
       sync_reg |= offset;
@@ -6792,11 +3912,7 @@
 
       sync_reg |= (offset | NARROW_SCSI);
 
-#else
-   sync_reg |= (offset | NARROW_SCSI);
-#endif
-
-   sssyncv(port,currSCCB->TargID,sync_reg,currTar_Info);
+   FPT_sssyncv(port,currSCCB->TargID,sync_reg,currTar_Info);
 
 
    if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
@@ -6815,7 +3931,7 @@
 
       ACCEPT_MSG_ATN(port);
 
-      sisyncr(port,sync_msg,offset);
+      FPT_sisyncr(port,sync_msg,offset);
 
       currTar_Info->TarStatus = ((currTar_Info->TarStatus &
          ~(UCHAR)TAR_SYNC_MASK) | (UCHAR)SYNC_SUPPORTED);
@@ -6825,16 +3941,12 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: sisyncr
+ * Function: FPT_sisyncr
  *
  * Description: Answer the targets sync message.
  *
  *---------------------------------------------------------------------*/
-#if defined(DOS)
-void sisyncr(USHORT port,UCHAR sync_pulse, UCHAR offset)
-#else
-void sisyncr(ULONG port,UCHAR sync_pulse, UCHAR offset)
-#endif
+static void FPT_sisyncr(ULONG port,UCHAR sync_pulse, UCHAR offset)
 {
    ARAM_ACCESS(port);
    WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT ));
@@ -6856,28 +3968,22 @@
 
 
 
-#if defined(WIDE_SCSI)
-
 /*---------------------------------------------------------------------
  *
- * Function: siwidn
+ * Function: FPT_siwidn
  *
  * Description: Read in a message byte from the SCSI bus, and check
  *              for a parity error.
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-UCHAR siwidn(USHORT port, UCHAR p_card)
-#else
-UCHAR siwidn(ULONG port, UCHAR p_card)
-#endif
+static UCHAR FPT_siwidn(ULONG port, UCHAR p_card)
 {
    PSCCB currSCCB;
    PSCCBMgr_tar_info currTar_Info;
 
-   currSCCB = BL_Card[p_card].currentSCCB;
-   currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID];
+   currSCCB = FPT_BL_Card[p_card].currentSCCB;
+   currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
 
    if (!((currTar_Info->TarStatus & TAR_WIDE_MASK) == WIDE_NEGOCIATED)) {
 
@@ -6900,7 +4006,7 @@
       currTar_Info->TarStatus = ((currTar_Info->TarStatus &
          ~(UCHAR)TAR_WIDE_MASK) | (UCHAR)WIDE_ENABLED);
 
-      return(TRUE);
+      return(1);
       }
 
    else {
@@ -6909,7 +4015,7 @@
                ~(UCHAR)TAR_WIDE_MASK) | WIDE_NEGOCIATED);
 
       currTar_Info->TarEEValue &= ~EE_WIDE_SCSI;
-      return(FALSE);
+      return(0);
       }
 }
 
@@ -6917,26 +4023,22 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: stwidn
+ * Function: FPT_stwidn
  *
  * Description: The has sent us a Wide Nego message so handle it as
  *              necessary.
  *
  *---------------------------------------------------------------------*/
-#if defined(DOS)
-void stwidn(USHORT port, UCHAR p_card)
-#else
-void stwidn(ULONG port, UCHAR p_card)
-#endif
+static void FPT_stwidn(ULONG port, UCHAR p_card)
 {
    UCHAR width;
    PSCCB currSCCB;
    PSCCBMgr_tar_info currTar_Info;
 
-   currSCCB = BL_Card[p_card].currentSCCB;
-   currTar_Info = &sccbMgrTbl[p_card][currSCCB->TargID];
+   currSCCB = FPT_BL_Card[p_card].currentSCCB;
+   currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
 
-   width = sfm(port,currSCCB);
+   width = FPT_sfm(port,currSCCB);
 
 	if((width == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY))
 	{
@@ -6958,7 +4060,7 @@
       }
 
 
-   sssyncv(port,currSCCB->TargID,width,currTar_Info);
+   FPT_sssyncv(port,currSCCB->TargID,width,currTar_Info);
 
 
    if (currSCCB->Sccb_scsistat == SELECT_WN_ST)
@@ -6972,7 +4074,7 @@
 		{
 	      ACCEPT_MSG_ATN(port);
 		   ARAM_ACCESS(port);
-	     	sisyncn(port,p_card, TRUE);
+	     	FPT_sisyncn(port,p_card, 1);
 	      currSCCB->Sccb_scsistat = SELECT_SN_ST;
 		   SGRAM_ACCESS(port);
 		}
@@ -6993,7 +4095,7 @@
       else
       	 width = SM8BIT;
 
-      siwidr(port,width);
+      FPT_siwidr(port,width);
 
       currTar_Info->TarStatus |= (WIDE_NEGOCIATED | WIDE_ENABLED);
       }
@@ -7002,16 +4104,12 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: siwidr
+ * Function: FPT_siwidr
  *
  * Description: Answer the targets Wide nego message.
  *
  *---------------------------------------------------------------------*/
-#if defined(DOS)
-void siwidr(USHORT port, UCHAR width)
-#else
-void siwidr(ULONG port, UCHAR width)
-#endif
+static void FPT_siwidr(ULONG port, UCHAR width)
 {
    ARAM_ACCESS(port);
    WRW_HARPOON((port+SYNC_MSGS+0), (MPM_OP+AMSG_OUT+SMEXT ));
@@ -7030,23 +4128,18 @@
    while (!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | AUTO_INT))) {}
 }
 
-#endif
-
 
 
 /*---------------------------------------------------------------------
  *
- * Function: sssyncv
+ * Function: FPT_sssyncv
  *
  * Description: Write the desired value to the Sync Register for the
  *              ID specified.
  *
  *---------------------------------------------------------------------*/
-#if defined(DOS)
-void sssyncv(USHORT p_port, UCHAR p_id, UCHAR p_sync_value,PSCCBMgr_tar_info currTar_Info)
-#else
-void sssyncv(ULONG p_port, UCHAR p_id, UCHAR p_sync_value,PSCCBMgr_tar_info currTar_Info)
-#endif
+static void FPT_sssyncv(ULONG p_port, UCHAR p_id, UCHAR p_sync_value,
+			PSCCBMgr_tar_info currTar_Info)
 {
    UCHAR index;
 
@@ -7112,16 +4205,12 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: sresb
+ * Function: FPT_sresb
  *
  * Description: Reset the desired card's SCSI bus.
  *
  *---------------------------------------------------------------------*/
-#if defined(DOS)
-void sresb(USHORT port, UCHAR p_card)
-#else
-void sresb(ULONG port, UCHAR p_card)
-#endif
+static void FPT_sresb(ULONG port, UCHAR p_card)
 {
    UCHAR scsiID, i;
 
@@ -7145,7 +4234,7 @@
 
    WR_HARPOON(port+hp_scsictrl_0, ENA_SCAM_SEL);
 
-   Wait(port, TO_5ms);
+   FPT_Wait(port, TO_5ms);
 
    WRW_HARPOON((port+hp_intstat), CLR_ALL_INT);
 
@@ -7153,7 +4242,7 @@
 
    for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++)
       {
-      currTar_Info = &sccbMgrTbl[p_card][scsiID];
+      currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
 
       if (currTar_Info->TarEEValue & EE_SYNC_MASK)
          {
@@ -7166,21 +4255,21 @@
       	currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
       	}
 
-      sssyncv(port, scsiID, NARROW_SCSI,currTar_Info);
+      FPT_sssyncv(port, scsiID, NARROW_SCSI,currTar_Info);
 
-      SccbMgrTableInitTarget(p_card, scsiID);
+      FPT_SccbMgrTableInitTarget(p_card, scsiID);
       }
 
-   BL_Card[p_card].scanIndex = 0x00;
-   BL_Card[p_card].currentSCCB = NULL;
-   BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT 
+   FPT_BL_Card[p_card].scanIndex = 0x00;
+   FPT_BL_Card[p_card].currentSCCB = NULL;
+   FPT_BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT 
 													| F_NEW_SCCB_CMD);
-   BL_Card[p_card].cmdCounter  = 0x00;
-	BL_Card[p_card].discQCount = 0x00;
-   BL_Card[p_card].tagQ_Lst = 0x01; 
+   FPT_BL_Card[p_card].cmdCounter  = 0x00;
+	FPT_BL_Card[p_card].discQCount = 0x00;
+   FPT_BL_Card[p_card].tagQ_Lst = 0x01; 
 
 	for(i = 0; i < QUEUE_DEPTH; i++)
-		BL_Card[p_card].discQ_Tbl[i] = NULL;
+		FPT_BL_Card[p_card].discQ_Tbl[i] = NULL;
 
    WR_HARPOON(port+hp_page_ctrl,
       (RD_HARPOON(port+hp_page_ctrl) & ~G_INT_DISABLE));
@@ -7189,12 +4278,12 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: ssenss
+ * Function: FPT_ssenss
  *
  * Description: Setup for the Auto Sense command.
  *
  *---------------------------------------------------------------------*/
-void ssenss(PSCCBcard pCurrCard)
+static void FPT_ssenss(PSCCBcard pCurrCard)
 {
    UCHAR i;
    PSCCB currSCCB;
@@ -7236,27 +4325,23 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: sxfrp
+ * Function: FPT_sxfrp
  *
  * Description: Transfer data into the bit bucket until the device
  *              decides to switch phase.
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void sxfrp(USHORT p_port, UCHAR p_card)
-#else
-void sxfrp(ULONG p_port, UCHAR p_card)
-#endif
+static void FPT_sxfrp(ULONG p_port, UCHAR p_card)
 {
    UCHAR curr_phz;
 
 
    DISABLE_AUTO(p_port);
 
-   if (BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
+   if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
 
-      hostDataXferAbort(p_port,p_card,BL_Card[p_card].currentSCCB);
+      FPT_hostDataXferAbort(p_port,p_card,FPT_BL_Card[p_card].currentSCCB);
 
       }
 
@@ -7322,25 +4407,21 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: schkdd
+ * Function: FPT_schkdd
  *
  * Description: Make sure data has been flushed from both FIFOs and abort
  *              the operations if necessary.
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void schkdd(USHORT port, UCHAR p_card)
-#else
-void schkdd(ULONG port, UCHAR p_card)
-#endif
+static void FPT_schkdd(ULONG port, UCHAR p_card)
 {
    USHORT TimeOutLoop;
 	UCHAR sPhase;
 
    PSCCB currSCCB;
 
-   currSCCB = BL_Card[p_card].currentSCCB;
+   currSCCB = FPT_BL_Card[p_card].currentSCCB;
 
 
    if ((currSCCB->Sccb_scsistat != DATA_OUT_ST) &&
@@ -7378,7 +4459,7 @@
       }
 
 
-   hostDataXferAbort(port,p_card,currSCCB);
+   FPT_hostDataXferAbort(port,p_card,currSCCB);
 
 
    while (RD_HARPOON(port+hp_scsisig) & SCSI_ACK) {}
@@ -7412,21 +4493,21 @@
 	   if (!(currSCCB->Sccb_XferState & F_ALL_XFERRED))
          {
 	      if (currSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
-	         phaseDataIn(port,p_card);
+	         FPT_phaseDataIn(port,p_card);
 	      	}
 
 	   	else {
-	       phaseDataOut(port,p_card);
+	       FPT_phaseDataOut(port,p_card);
 	       	}
 	   	}
 		else
       	{
-	   	sxfrp(port,p_card);
+	   	FPT_sxfrp(port,p_card);
 	   	if (!(RDW_HARPOON((port+hp_intstat)) &
 		      (BUS_FREE | ICMD_COMP | ITAR_DISC | RESET)))
          {
    		WRW_HARPOON((port+hp_intstat), AUTO_INT);
-		   phaseDecode(port,p_card);
+		   FPT_phaseDecode(port,p_card);
 		   }
 	   }
 
@@ -7440,13 +4521,13 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: sinits
+ * Function: FPT_sinits
  *
  * Description: Setup SCCB manager fields in this SCCB.
  *
  *---------------------------------------------------------------------*/
 
-void sinits(PSCCB p_sccb, UCHAR p_card)
+static void FPT_sinits(PSCCB p_sccb, UCHAR p_card)
 {
    PSCCBMgr_tar_info currTar_Info;
 
@@ -7454,7 +4535,7 @@
 	{
 		return;
 	}
-   currTar_Info = &sccbMgrTbl[p_card][p_sccb->TargID];
+   currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
 
    p_sccb->Sccb_XferState     = 0x00;
    p_sccb->Sccb_XferCnt       = p_sccb->DataLength;
@@ -7485,7 +4566,7 @@
 	else send Cmd with Disconnect Disable */
 
 /*
-   if (((!(BL_Card[p_card].globalFlags & F_SINGLE_DEVICE)) &&
+   if (((!(FPT_BL_Card[p_card].globalFlags & F_SINGLE_DEVICE)) &&
       (currTar_Info->TarStatus & TAR_ALLOW_DISC)) ||
       (currTar_Info->TarStatus & TAG_Q_TRYING)) {
 */
@@ -7518,55 +4599,6 @@
 }
 
 
-#ident "$Id: phase.c 1.11 1997/01/31 02:08:49 mohan Exp $"
-/*----------------------------------------------------------------------
- *
- *
- *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
- *
- *   This file is available under both the GNU General Public License
- *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- *   $Workfile:   phase.c  $
- *
- *   Description:  Functions to initially handle the SCSI bus phase when
- *                 the target asserts request (and the automation is not
- *                 enabled to handle the situation).
- *
- *   $Date: 1997/01/31 02:08:49 $
- *
- *   $Revision: 1.11 $
- *
- *----------------------------------------------------------------------*/
-
-/*#include <globals.h>*/
-
-#if (FW_TYPE==_UCB_MGR_)
-	/*#include <budi.h>*/
-#endif
-
-/*#include <sccbmgr.h>*/
-/*#include <blx30.h>*/
-/*#include <target.h>*/
-/*#include <scsi2.h>*/
-/*#include <harpoon.h>*/
-
-
-/*
-extern SCCBCARD BL_Card[MAX_CARDS];
-extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];
-
-#if defined(OS2)
-   extern void (far *s_PhaseTbl[8]) (ULONG, UCHAR);
-#else
-   #if defined(DOS)
-      extern void (*s_PhaseTbl[8]) (USHORT, UCHAR);
-   #else
-      extern void (*s_PhaseTbl[8]) (ULONG, UCHAR);
-   #endif
-#endif
-*/
-
 /*---------------------------------------------------------------------
  *
  * Function: Phase Decode
@@ -7575,29 +4607,17 @@
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void phaseDecode(USHORT p_port, UCHAR p_card)
-#else
-void phaseDecode(ULONG p_port, UCHAR p_card)
-#endif
+static void FPT_phaseDecode(ULONG p_port, UCHAR p_card)
 {
    unsigned char phase_ref;
-#if defined(OS2)
-   void (far *phase) (ULONG, UCHAR);
-#else
-   #if defined(DOS)
-      void (*phase) (USHORT, UCHAR);
-   #else
-      void (*phase) (ULONG, UCHAR);
-   #endif
-#endif
+   void (*phase) (ULONG, UCHAR);
 
 
    DISABLE_AUTO(p_port);
 
    phase_ref = (UCHAR) (RD_HARPOON(p_port+hp_scsisig) & S_SCSI_PHZ);
 
-   phase = s_PhaseTbl[phase_ref];
+   phase = FPT_s_PhaseTbl[phase_ref];
 
    (*phase)(p_port, p_card);           /* Call the correct phase func */
 }
@@ -7612,20 +4632,12 @@
  *
  *---------------------------------------------------------------------*/
 
-#if defined(OS2)
-void far phaseDataOut(ULONG port, UCHAR p_card)
-#else
-#if defined(DOS)
-void phaseDataOut(USHORT port, UCHAR p_card)
-#else
-void phaseDataOut(ULONG port, UCHAR p_card)
-#endif
-#endif
+static void FPT_phaseDataOut(ULONG port, UCHAR p_card)
 {
 
    PSCCB currSCCB;
 
-   currSCCB = BL_Card[p_card].currentSCCB;
+   currSCCB = FPT_BL_Card[p_card].currentSCCB;
    if (currSCCB == NULL)
       {
       return;  /* Exit if No SCCB record */
@@ -7640,14 +4652,7 @@
 
    WR_HARPOON(port+hp_autostart_0, (END_DATA+END_DATA_START));
 
-   dataXferProcessor(port, &BL_Card[p_card]);
-
-#if defined(NOBUGBUG)
-   if (RDW_HARPOON((port+hp_intstat)) & XFER_CNT_0)
-      WRW_HARPOON((port+hp_intstat), XFER_CNT_0);
-
-#endif
-
+   FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
 
    if (currSCCB->Sccb_XferCnt == 0) {
 
@@ -7656,9 +4661,9 @@
 	 (currSCCB->HostStatus == SCCB_COMPLETE))
 	 currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
 
-      sxfrp(port,p_card);
+      FPT_sxfrp(port,p_card);
       if (!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | RESET)))
-	    phaseDecode(port,p_card);
+	    FPT_phaseDecode(port,p_card);
       }
 }
 
@@ -7671,20 +4676,12 @@
  *
  *---------------------------------------------------------------------*/
 
-#if defined(OS2)
-void far phaseDataIn(ULONG port, UCHAR p_card)
-#else
-#if defined(DOS)
-void phaseDataIn(USHORT port, UCHAR p_card)
-#else
-void phaseDataIn(ULONG port, UCHAR p_card)
-#endif
-#endif
+static void FPT_phaseDataIn(ULONG port, UCHAR p_card)
 {
 
    PSCCB currSCCB;
 
-   currSCCB = BL_Card[p_card].currentSCCB;
+   currSCCB = FPT_BL_Card[p_card].currentSCCB;
 
    if (currSCCB == NULL)
       {
@@ -7702,7 +4699,7 @@
 
    WR_HARPOON(port+hp_autostart_0, (END_DATA+END_DATA_START));
 
-   dataXferProcessor(port, &BL_Card[p_card]);
+   FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
 
    if (currSCCB->Sccb_XferCnt == 0) {
 
@@ -7711,9 +4708,9 @@
 	 (currSCCB->HostStatus == SCCB_COMPLETE))
 	 currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
 
-      sxfrp(port,p_card);
+      FPT_sxfrp(port,p_card);
       if (!(RDW_HARPOON((port+hp_intstat)) & (BUS_FREE | RESET)))
-	    phaseDecode(port,p_card);
+	    FPT_phaseDecode(port,p_card);
 
       }
 }
@@ -7726,25 +4723,13 @@
  *
  *---------------------------------------------------------------------*/
 
-#if defined(OS2)
-void far phaseCommand(ULONG p_port, UCHAR p_card)
-#else
-#if defined(DOS)
-void phaseCommand(USHORT p_port, UCHAR p_card)
-#else
-void phaseCommand(ULONG p_port, UCHAR p_card)
-#endif
-#endif
+static void FPT_phaseCommand(ULONG p_port, UCHAR p_card)
 {
    PSCCB currSCCB;
-#if defined(DOS)
-   USHORT cdb_reg;
-#else
    ULONG cdb_reg;
-#endif
    UCHAR i;
 
-   currSCCB = BL_Card[p_card].currentSCCB;
+   currSCCB = FPT_BL_Card[p_card].currentSCCB;
 
    if (currSCCB->OperationCode == RESET_COMMAND) {
 
@@ -7790,15 +4775,7 @@
  *
  *---------------------------------------------------------------------*/
 
-#if defined(OS2)
-void far phaseStatus(ULONG port, UCHAR p_card)
-#else
-#if defined(DOS)
-void phaseStatus(USHORT port, UCHAR p_card)
-#else
-void phaseStatus(ULONG port, UCHAR p_card)
-#endif
-#endif
+static void FPT_phaseStatus(ULONG port, UCHAR p_card)
 {
    /* Start-up the automation to finish off this command and let the
       isr handle the interrupt for command complete when it comes in.
@@ -7820,21 +4797,13 @@
  *
  *---------------------------------------------------------------------*/
 
-#if defined(OS2)
-void far phaseMsgOut(ULONG port, UCHAR p_card)
-#else
-#if defined(DOS)
-void phaseMsgOut(USHORT port, UCHAR p_card)
-#else
-void phaseMsgOut(ULONG port, UCHAR p_card)
-#endif
-#endif
+static void FPT_phaseMsgOut(ULONG port, UCHAR p_card)
 {
 	UCHAR message,scsiID;
 	PSCCB currSCCB;
 	PSCCBMgr_tar_info currTar_Info;
 
-	currSCCB = BL_Card[p_card].currentSCCB;
+	currSCCB = FPT_BL_Card[p_card].currentSCCB;
 
 	if (currSCCB != NULL) {
 
@@ -7845,34 +4814,34 @@
 		{
 
 
-			currTar_Info = &sccbMgrTbl[p_card][scsiID];
+			currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
 			currTar_Info->TarSyncCtrl = 0;
-			sssyncv(port, scsiID, NARROW_SCSI,currTar_Info);
+			FPT_sssyncv(port, scsiID, NARROW_SCSI,currTar_Info);
 
-			if (sccbMgrTbl[p_card][scsiID].TarEEValue & EE_SYNC_MASK) 
+			if (FPT_sccbMgrTbl[p_card][scsiID].TarEEValue & EE_SYNC_MASK) 
 			{
 
-				sccbMgrTbl[p_card][scsiID].TarStatus &= ~TAR_SYNC_MASK;
+				FPT_sccbMgrTbl[p_card][scsiID].TarStatus &= ~TAR_SYNC_MASK;
 
 			}
 
-			if (sccbMgrTbl[p_card][scsiID].TarEEValue & EE_WIDE_SCSI) 
+			if (FPT_sccbMgrTbl[p_card][scsiID].TarEEValue & EE_WIDE_SCSI) 
 			{
 
-				sccbMgrTbl[p_card][scsiID].TarStatus &= ~TAR_WIDE_MASK;
+				FPT_sccbMgrTbl[p_card][scsiID].TarStatus &= ~TAR_WIDE_MASK;
 			}
 
 
-			queueFlushSccb(p_card,SCCB_COMPLETE);
-			SccbMgrTableInitTarget(p_card,scsiID);
+			FPT_queueFlushSccb(p_card,SCCB_COMPLETE);
+			FPT_SccbMgrTableInitTarget(p_card,scsiID);
 		}
 		else if (currSCCB->Sccb_scsistat == ABORT_ST)
 		{
 			currSCCB->HostStatus = SCCB_COMPLETE;
-			if(BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] != NULL)
+			if(FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] != NULL)
 			{
-				BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
-				sccbMgrTbl[p_card][scsiID].TarTagQ_Cnt--;
+				FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
+				FPT_sccbMgrTbl[p_card][scsiID].TarTagQ_Cnt--;
 			}
 					
 		}
@@ -7885,7 +4854,7 @@
 			{
 				currSCCB->Sccb_MGRFlags |= F_DEV_SELECTED;
 		
-				ssel(port,p_card);
+				FPT_ssel(port,p_card);
 				return;
 			}
 		}
@@ -7895,7 +4864,7 @@
 
 			if (message == SMABORT)
 
-				queueFlushSccb(p_card,SCCB_COMPLETE);
+				FPT_queueFlushSccb(p_card,SCCB_COMPLETE);
 		}
 
 	}
@@ -7930,25 +4899,25 @@
 			if (currSCCB != NULL) 
 			{
 
-				if((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
-					((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
-					sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = FALSE;
+				if((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
+					((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
+					FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 0;
 				else
-					sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = FALSE;
+					FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0;
 
-				queueCmdComplete(&BL_Card[p_card],currSCCB, p_card);
+				FPT_queueCmdComplete(&FPT_BL_Card[p_card],currSCCB, p_card);
 			}
 
 			else 
 			{
-				BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
+				FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
 			}
 		}
 
 		else 
 		{
 
-			sxfrp(port,p_card);
+			FPT_sxfrp(port,p_card);
 		}
 	}
 
@@ -7962,7 +4931,7 @@
 		}
 		else
 		{
-			sxfrp(port,p_card);
+			FPT_sxfrp(port,p_card);
 		}
 	}
 }
@@ -7976,25 +4945,17 @@
  *
  *---------------------------------------------------------------------*/
 
-#if defined(OS2)
-void far phaseMsgIn(ULONG port, UCHAR p_card)
-#else
-#if defined(DOS)
-void phaseMsgIn(USHORT port, UCHAR p_card)
-#else
-void phaseMsgIn(ULONG port, UCHAR p_card)
-#endif
-#endif
+static void FPT_phaseMsgIn(ULONG port, UCHAR p_card)
 {
 	UCHAR message;
 	PSCCB currSCCB;
 
-	currSCCB = BL_Card[p_card].currentSCCB;
+	currSCCB = FPT_BL_Card[p_card].currentSCCB;
 
-	if (BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) 
+	if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) 
 	{
 
-		phaseChkFifo(port, p_card);
+		FPT_phaseChkFifo(port, p_card);
 	}
 
 	message = RD_HARPOON(port+hp_scsidata_0);
@@ -8008,12 +4969,12 @@
 	else 
 	{
 
-		message = sfm(port,currSCCB);
+		message = FPT_sfm(port,currSCCB);
 		if (message) 
 		{
 
 
-			sdecm(message,port,p_card);
+			FPT_sdecm(message,port,p_card);
 
 		}
 		else
@@ -8037,19 +4998,11 @@
  *
  *---------------------------------------------------------------------*/
 
-#if defined(OS2)
-void far phaseIllegal(ULONG port, UCHAR p_card)
-#else
-#if defined(DOS)
-void phaseIllegal(USHORT port, UCHAR p_card)
-#else
-void phaseIllegal(ULONG port, UCHAR p_card)
-#endif
-#endif
+static void FPT_phaseIllegal(ULONG port, UCHAR p_card)
 {
    PSCCB currSCCB;
 
-   currSCCB = BL_Card[p_card].currentSCCB;
+   currSCCB = FPT_BL_Card[p_card].currentSCCB;
 
    WR_HARPOON(port+hp_scsisig, RD_HARPOON(port+hp_scsisig));
    if (currSCCB != NULL) {
@@ -8073,16 +5026,12 @@
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void phaseChkFifo(USHORT port, UCHAR p_card)
-#else
-void phaseChkFifo(ULONG port, UCHAR p_card)
-#endif
+static void FPT_phaseChkFifo(ULONG port, UCHAR p_card)
 {
    ULONG xfercnt;
    PSCCB currSCCB;
 
-   currSCCB = BL_Card[p_card].currentSCCB;
+   currSCCB = FPT_BL_Card[p_card].currentSCCB;
 
    if (currSCCB->Sccb_scsistat == DATA_IN_ST)
       {
@@ -8104,9 +5053,9 @@
 	         WRW_HARPOON((port+hp_intstat), PARITY);
 	         }
 
-	      hostDataXferAbort(port,p_card,currSCCB);
+	      FPT_hostDataXferAbort(port,p_card,currSCCB);
 
-	      dataXferProcessor(port, &BL_Card[p_card]);
+	      FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
 
 	      while((!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY)) &&
 	         (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY)) {}
@@ -8116,22 +5065,7 @@
 
 
 
-#if defined(DOS)
-   asm { mov dx,port;
-      add dx,hp_xfercnt_2;
-      in  al,dx;
-      dec dx;
-      xor ah,ah;
-      mov word ptr xfercnt+2,ax;
-      in  al,dx;
-      dec dx;
-      mov ah,al;
-      in  al,dx;
-      mov word ptr xfercnt,ax;
-      }
-#else
    GET_XFER_CNT(port,xfercnt);
-#endif
 
 
    WR_HARPOON(port+hp_xfercnt_0, 0x00);
@@ -8151,7 +5085,7 @@
       }
 
 
-   hostDataXferAbort(port,p_card,currSCCB);
+   FPT_hostDataXferAbort(port,p_card,currSCCB);
 
 
    WR_HARPOON(port+hp_fifowrite, 0x00);
@@ -8170,15 +5104,11 @@
  *              because of command complete or from a disconnect.
  *
  *---------------------------------------------------------------------*/
-#if defined(DOS)
-void phaseBusFree(USHORT port, UCHAR p_card)
-#else
-void phaseBusFree(ULONG port, UCHAR p_card)
-#endif
+static void FPT_phaseBusFree(ULONG port, UCHAR p_card)
 {
    PSCCB currSCCB;
 
-   currSCCB = BL_Card[p_card].currentSCCB;
+   currSCCB = FPT_BL_Card[p_card].currentSCCB;
 
    if (currSCCB != NULL)
       {
@@ -8189,35 +5119,34 @@
       if (currSCCB->OperationCode == RESET_COMMAND)
          {
 
-			if((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
-				((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
-	   		 sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = FALSE;
+			if((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
+				((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
+	   		 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 0;
 			else
-		   	 sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = FALSE;
+		   	 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0;
 
-	      queueCmdComplete(&BL_Card[p_card], currSCCB, p_card);
+	      FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card);
 
-	      queueSearchSelect(&BL_Card[p_card],p_card);
+	      FPT_queueSearchSelect(&FPT_BL_Card[p_card],p_card);
 
 	      }
 
       else if(currSCCB->Sccb_scsistat == SELECT_SN_ST)
 	      {
-	      sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
+	      FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
 			         (UCHAR)SYNC_SUPPORTED;
-	      sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_SYNC_MASK;
+	      FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_SYNC_MASK;
 	      }
 
       else if(currSCCB->Sccb_scsistat == SELECT_WN_ST)
 	      {
-	      sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
-		            (sccbMgrTbl[p_card][currSCCB->TargID].
+	      FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
+		            (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
 		   TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
 
-	      sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_WIDE_SCSI;
+	      FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_WIDE_SCSI;
 	      }
 
-#if !defined(DOS)
       else if(currSCCB->Sccb_scsistat == SELECT_Q_ST)
 	      {
 	      /* Make sure this is not a phony BUS_FREE.  If we were
@@ -8227,8 +5156,8 @@
 	      if ((!(RD_HARPOON(port+hp_scsisig) & SCSI_BSY)) ||
 	         (RDW_HARPOON((port+hp_intstat)) & RSEL))
 	         {
-	         sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_TAG_Q_MASK;
-	         sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |= TAG_Q_REJECT;
+	         FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_TAG_Q_MASK;
+	         FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |= TAG_Q_REJECT;
 	         }
 
 	      else
@@ -8236,7 +5165,6 @@
 	         return;
 	         }
          }
-#endif
 
       else
 	      {
@@ -8248,18 +5176,18 @@
 	         currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
 	         }
 
-			if((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
-				((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
-	   		 sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = FALSE;
+			if((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
+				((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
+	   		 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 0;
 			else
-		   	 sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = FALSE;
+		   	 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0;
 
-	      queueCmdComplete(&BL_Card[p_card], currSCCB, p_card);
+	      FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card);
 	      return;
 	      }
 
 
-      BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
+      FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
 
       } /*end if !=null */
 }
@@ -8267,44 +5195,6 @@
 
 
 
-#ident "$Id: automate.c 1.14 1997/01/31 02:11:46 mohan Exp $"
-/*----------------------------------------------------------------------
- *
- *
- *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
- *
- *   This file is available under both the GNU General Public License
- *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- *   $Workfile:   automate.c  $
- *
- *   Description:  Functions relating to programming the automation of
- *                 the HARPOON.
- *
- *   $Date: 1997/01/31 02:11:46 $
- *
- *   $Revision: 1.14 $
- *
- *----------------------------------------------------------------------*/
-
-/*#include <globals.h>*/
-
-#if (FW_TYPE==_UCB_MGR_)
-	/*#include <budi.h>*/
-#endif
-
-/*#include <sccbmgr.h>*/
-/*#include <blx30.h>*/
-/*#include <target.h>*/
-/*#include <scsi2.h>*/
-/*#include <harpoon.h>*/
-
-/*
-extern SCCBCARD BL_Card[MAX_CARDS];
-extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];
-extern SCCBCARD BL_Card[MAX_CARDS];
-*/
-
 /*---------------------------------------------------------------------
  *
  * Function: Auto Load Default Map
@@ -8312,17 +5202,9 @@
  * Description: Load the Automation RAM with the defualt map values.
  *
  *---------------------------------------------------------------------*/
-#if defined(DOS)
-void autoLoadDefaultMap(USHORT p_port)
-#else
-void autoLoadDefaultMap(ULONG p_port)
-#endif
+static void FPT_autoLoadDefaultMap(ULONG p_port)
 {
-#if defined(DOS)
-   USHORT map_addr;
-#else
    ULONG map_addr;
-#endif
 
    ARAM_ACCESS(p_port);
    map_addr = p_port + hp_aramBase;
@@ -8428,86 +5310,82 @@
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void autoCmdCmplt(USHORT p_port, UCHAR p_card)
-#else
-void autoCmdCmplt(ULONG p_port, UCHAR p_card)
-#endif
+static void FPT_autoCmdCmplt(ULONG p_port, UCHAR p_card)
 {
    PSCCB currSCCB;
    UCHAR status_byte;
 
-   currSCCB = BL_Card[p_card].currentSCCB;
+   currSCCB = FPT_BL_Card[p_card].currentSCCB;
 
    status_byte = RD_HARPOON(p_port+hp_gp_reg_0);
 
-   sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = FALSE;
+   FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = 0;
 
    if (status_byte != SSGOOD) {
 
       if (status_byte == SSQ_FULL) {
 
 
-			if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
-				((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
+			if(((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
+				((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
 			{
-	         sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE;
-				if(BL_Card[p_card].discQCount != 0)
-					BL_Card[p_card].discQCount--;
-				BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL;
+	         FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 1;
+				if(FPT_BL_Card[p_card].discQCount != 0)
+					FPT_BL_Card[p_card].discQCount--;
+				FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL;
 			}
 			else
 			{
-	         sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE;
+	         FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 1;
 				if(currSCCB->Sccb_tag)
 				{
-					if(BL_Card[p_card].discQCount != 0)
-						BL_Card[p_card].discQCount--;
-					BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
+					if(FPT_BL_Card[p_card].discQCount != 0)
+						FPT_BL_Card[p_card].discQCount--;
+					FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
 				}else
 				{
-					if(BL_Card[p_card].discQCount != 0)
-						BL_Card[p_card].discQCount--;
-					BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL;
+					if(FPT_BL_Card[p_card].discQCount != 0)
+						FPT_BL_Card[p_card].discQCount--;
+					FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL;
 				}
 			}
 
          currSCCB->Sccb_MGRFlags |= F_STATUSLOADED;
 
-         queueSelectFail(&BL_Card[p_card],p_card);
+         FPT_queueSelectFail(&FPT_BL_Card[p_card],p_card);
 
          return;
          }
 
       if(currSCCB->Sccb_scsistat == SELECT_SN_ST)
          {
-         sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
+         FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
             (UCHAR)SYNC_SUPPORTED;
 
-	      sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_SYNC_MASK;
-         BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
+	      FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_SYNC_MASK;
+         FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
 
-			if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
-				((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
+			if(((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
+				((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
 			{
-	         sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE;
-				if(BL_Card[p_card].discQCount != 0)
-					BL_Card[p_card].discQCount--;
-				BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL;
+	         FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 1;
+				if(FPT_BL_Card[p_card].discQCount != 0)
+					FPT_BL_Card[p_card].discQCount--;
+				FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL;
 			}
 			else
 			{
-	         sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE;
+	         FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 1;
 				if(currSCCB->Sccb_tag)
 				{
-					if(BL_Card[p_card].discQCount != 0)
-						BL_Card[p_card].discQCount--;
-					BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
+					if(FPT_BL_Card[p_card].discQCount != 0)
+						FPT_BL_Card[p_card].discQCount--;
+					FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
 				}else
 				{
-					if(BL_Card[p_card].discQCount != 0)
-						BL_Card[p_card].discQCount--;
-					BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL;
+					if(FPT_BL_Card[p_card].discQCount != 0)
+						FPT_BL_Card[p_card].discQCount--;
+					FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL;
 				}
 			}
          return;
@@ -8517,34 +5395,34 @@
       if(currSCCB->Sccb_scsistat == SELECT_WN_ST)
          {
 
-	      sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
-	         (sccbMgrTbl[p_card][currSCCB->TargID].
+	      FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
+	         (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
 	         TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
 
-	      sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_WIDE_SCSI;
-         BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
+	      FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= ~EE_WIDE_SCSI;
+         FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
 
-			if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
-				((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
+			if(((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
+				((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
 			{
-	         sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE;
-				if(BL_Card[p_card].discQCount != 0)
-					BL_Card[p_card].discQCount--;
-				BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL;
+	         FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 1;
+				if(FPT_BL_Card[p_card].discQCount != 0)
+					FPT_BL_Card[p_card].discQCount--;
+				FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL;
 			}
 			else
 			{
-	         sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE;
+	         FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 1;
 				if(currSCCB->Sccb_tag)
 				{
-					if(BL_Card[p_card].discQCount != 0)
-						BL_Card[p_card].discQCount--;
-					BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
+					if(FPT_BL_Card[p_card].discQCount != 0)
+						FPT_BL_Card[p_card].discQCount--;
+					FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
 				}else
 				{
-					if(BL_Card[p_card].discQCount != 0)
-						BL_Card[p_card].discQCount--;
-					BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL;
+					if(FPT_BL_Card[p_card].discQCount != 0)
+						FPT_BL_Card[p_card].discQCount--;
+					FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL;
 				}
 			}
          return;
@@ -8553,15 +5431,15 @@
      
 	   if (status_byte == SSCHECK) 
 		{
-			if(BL_Card[p_card].globalFlags & F_DO_RENEGO)
+			if(FPT_BL_Card[p_card].globalFlags & F_DO_RENEGO)
 			{
-				if (sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue & EE_SYNC_MASK)
+				if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue & EE_SYNC_MASK)
 				{
-					sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_SYNC_MASK;
+					FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_SYNC_MASK;
 				}
-				if (sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue & EE_WIDE_SCSI)
+				if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue & EE_WIDE_SCSI)
 				{
-					sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_WIDE_MASK;
+					FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus &= ~TAR_WIDE_MASK;
 				}
 			}
 		}
@@ -8573,135 +5451,61 @@
 
          if (status_byte == SSCHECK) {
 
-            sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA
-               = TRUE;
+            FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA
+               = 1;
      
 
-#if (FW_TYPE==_SCCB_MGR_)
             if (currSCCB->RequestSenseLength != NO_AUTO_REQUEST_SENSE) {
 
                if (currSCCB->RequestSenseLength == 0)
                   currSCCB->RequestSenseLength = 14;
 
-               ssenss(&BL_Card[p_card]);
-               BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
+               FPT_ssenss(&FPT_BL_Card[p_card]);
+               FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
 
- 					if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
-						((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
+ 					if(((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
+						((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
 					{
-			         sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE;
-						if(BL_Card[p_card].discQCount != 0)
-							BL_Card[p_card].discQCount--;
-						BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL;
+			         FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 1;
+						if(FPT_BL_Card[p_card].discQCount != 0)
+							FPT_BL_Card[p_card].discQCount--;
+						FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL;
 					}
 					else
 					{
-	   		      sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE;
+	   		      FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 1;
 						if(currSCCB->Sccb_tag)
 						{
-							if(BL_Card[p_card].discQCount != 0)
-								BL_Card[p_card].discQCount--;
-							BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
+							if(FPT_BL_Card[p_card].discQCount != 0)
+								FPT_BL_Card[p_card].discQCount--;
+							FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
 						}else
 						{
-							if(BL_Card[p_card].discQCount != 0)
-								BL_Card[p_card].discQCount--;
-							BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL;
+							if(FPT_BL_Card[p_card].discQCount != 0)
+								FPT_BL_Card[p_card].discQCount--;
+							FPT_BL_Card[p_card].discQ_Tbl[FPT_sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL;
 						}
 					}
                return;
                }
-#else
-				   if ((!(currSCCB->Sccb_ucb_ptr->UCB_opcode & OPC_NO_AUTO_SENSE)) &&
-			   		(currSCCB->RequestSenseLength))
-				   {
-				   	ssenss(&BL_Card[p_card]);
-				      BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
-
-						if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
-							((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
-						{
-	      			   sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = TRUE;
-							if(BL_Card[p_card].discQCount != 0)
-								BL_Card[p_card].discQCount--;
-							BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[currSCCB->Lun]] = NULL;
-						}
-						else
-						{
-	      			   sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = TRUE;
-							if(currSCCB->Sccb_tag)
-							{
-								if(BL_Card[p_card].discQCount != 0)
-									BL_Card[p_card].discQCount--;
-								BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] = NULL;
-							}else
-							{
-								if(BL_Card[p_card].discQCount != 0)
-									BL_Card[p_card].discQCount--;
-								BL_Card[p_card].discQ_Tbl[sccbMgrTbl[p_card][currSCCB->TargID].LunDiscQ_Idx[0]] = NULL;
-							}
-						}
-				      return;
-				   }
-
-#endif
             }
          }
       }
 
 
-	if((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
-		((sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
-	   sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = FALSE;
+	if((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
+		((FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
+	   FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->Lun] = 0;
 	else
-	   sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = FALSE;
+	   FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0;
 
 
-   queueCmdComplete(&BL_Card[p_card], currSCCB, p_card);
+   FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card);
 }
-#ident "$Id: busmstr.c 1.8 1997/01/31 02:10:27 mohan Exp $"
-/*----------------------------------------------------------------------
- *
- *
- *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
- *
- *   This file is available under both the GNU General Public License
- *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- *   $Workfile:   busmstr.c  $
- *
- *   Description:  Functions to start, stop, and abort BusMaster operations.
- *
- *   $Date: 1997/01/31 02:10:27 $
- *
- *   $Revision: 1.8 $
- *
- *----------------------------------------------------------------------*/
-
-/*#include <globals.h>*/
-
-#if (FW_TYPE==_UCB_MGR_)
-	/*#include <budi.h>*/
-#endif
-
-/*#include <sccbmgr.h>*/
-/*#include <blx30.h>*/
-/*#include <target.h>*/
-/*#include <scsi2.h>*/
-/*#include <harpoon.h>*/
-
-
-/*
-extern SCCBCARD BL_Card[MAX_CARDS];
-extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];
-*/
 
 #define SHORT_WAIT   0x0000000F
 #define LONG_WAIT    0x0000FFFFL
 
-#if defined(BUGBUG)
-void Debug_Load(UCHAR p_card, UCHAR p_bug_data);
-#endif
 
 /*---------------------------------------------------------------------
  *
@@ -8721,11 +5525,7 @@
  *              
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void dataXferProcessor(USHORT port, PSCCBcard pCurrCard)
-#else
-void dataXferProcessor(ULONG port, PSCCBcard pCurrCard)
-#endif
+static void FPT_dataXferProcessor(ULONG port, PSCCBcard pCurrCard)
 {
    PSCCB currSCCB;
 
@@ -8741,7 +5541,7 @@
  				}
 			pCurrCard->globalFlags |= F_HOST_XFER_ACT;
          
-         busMstrSGDataXferStart(port, currSCCB);
+         FPT_busMstrSGDataXferStart(port, currSCCB);
 			}
 
       else
@@ -8750,7 +5550,7 @@
 				{
 				pCurrCard->globalFlags |= F_HOST_XFER_ACT;
          
-         	busMstrDataXferStart(port, currSCCB);
+         	FPT_busMstrDataXferStart(port, currSCCB);
          	}
 			}
 }
@@ -8763,20 +5563,12 @@
  * Description:
  *
  *---------------------------------------------------------------------*/
-#if defined(DOS)
-void busMstrSGDataXferStart(USHORT p_port, PSCCB pcurrSCCB)
-#else
-void busMstrSGDataXferStart(ULONG p_port, PSCCB pcurrSCCB)
-#endif
+static void FPT_busMstrSGDataXferStart(ULONG p_port, PSCCB pcurrSCCB)
 {
    ULONG count,addr,tmpSGCnt;
    UINT sg_index;
    UCHAR sg_count, i;
-#if defined(DOS)
-   USHORT reg_offset;
-#else
    ULONG reg_offset;
-#endif
 
 
    if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
@@ -8802,17 +5594,6 @@
    while ((sg_count < (UCHAR)SG_BUF_CNT) &&
       ((ULONG)(sg_index * (UINT)SG_ELEMENT_SIZE) < pcurrSCCB->DataLength) ) {
 
-#if defined(COMPILER_16_BIT) && !defined(DOS)
-      tmpSGCnt += *(((ULONG far *)pcurrSCCB->DataPointer)+
-         (sg_index * 2));
-
-      count |= *(((ULONG far *)pcurrSCCB->DataPointer)+
-         (sg_index * 2));
-
-      addr = *(((ULONG far *)pcurrSCCB->DataPointer)+
-         ((sg_index * 2) + 1));
-
-#else
       tmpSGCnt += *(((ULONG *)pcurrSCCB->DataPointer)+
          (sg_index * 2));
 
@@ -8821,7 +5602,6 @@
 
       addr = *(((ULONG *)pcurrSCCB->DataPointer)+
          ((sg_index * 2) + 1));
-#endif
 
 
       if ((!sg_count) && (pcurrSCCB->Sccb_SGoffset)) {
@@ -8888,11 +5668,7 @@
  * Description: 
  *
  *---------------------------------------------------------------------*/
-#if defined(DOS)
-void busMstrDataXferStart(USHORT p_port, PSCCB pcurrSCCB)
-#else
-void busMstrDataXferStart(ULONG p_port, PSCCB pcurrSCCB)
-#endif
+static void FPT_busMstrDataXferStart(ULONG p_port, PSCCB pcurrSCCB)
 {
    ULONG addr,count;
 
@@ -8909,37 +5685,7 @@
 
       }
 
-#if defined(DOS)
-   asm { mov dx,p_port;
-         mov ax,word ptr count;
-         add dx,hp_xfer_cnt_lo;
-         out dx,al;
-         inc dx;
-         xchg ah,al
-         out dx,al;
-         inc dx;
-         mov ax,word ptr count+2;
-         out dx,al;
-         inc dx;
-         inc dx;
-         mov ax,word ptr addr;
-         out dx,al;
-         inc dx;
-         xchg ah,al
-         out dx,al;
-         inc dx;
-         mov ax,word ptr addr+2;
-         out dx,al;
-         inc dx;
-         xchg ah,al
-         out dx,al;
-         }
-
-   WR_HARP32(p_port,hp_xfercnt_0,count);
-
-#else
    HP_SETUP_ADDR_CNT(p_port,addr,count);
-#endif
 
 
    if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
@@ -8975,11 +5721,7 @@
  *               command busy is also time out, it'll just give up.
  *
  *---------------------------------------------------------------------*/
-#if defined(DOS)
-UCHAR busMstrTimeOut(USHORT p_port)
-#else
-UCHAR busMstrTimeOut(ULONG p_port)
-#endif
+static UCHAR FPT_busMstrTimeOut(ULONG p_port)
 {
    ULONG timeout;
 
@@ -9001,11 +5743,11 @@
    RD_HARPOON(p_port+hp_int_status);           /*Clear command complete */
 
    if (RD_HARPOON(p_port+hp_ext_status) & BM_CMD_BUSY) {
-      return(TRUE);
+      return(1);
       }
 
    else {
-      return(FALSE);
+      return(0);
       }
 }
 
@@ -9017,18 +5759,14 @@
  * Description: Abort any in progress transfer.
  *
  *---------------------------------------------------------------------*/
-#if defined(DOS)
-void hostDataXferAbort(USHORT port, UCHAR p_card, PSCCB pCurrSCCB)
-#else
-void hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
-#endif
+static void FPT_hostDataXferAbort(ULONG port, UCHAR p_card, PSCCB pCurrSCCB)
 {
 
    ULONG timeout;
    ULONG remain_cnt;
    UINT sg_ptr;
 
-   BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT;
+   FPT_BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT;
 
    if (pCurrSCCB->Sccb_XferState & F_AUTO_SENSE) {
 
@@ -9044,7 +5782,7 @@
 
          if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) {
 
-            if (busMstrTimeOut(port)) {
+            if (FPT_busMstrTimeOut(port)) {
 
                if (pCurrSCCB->HostStatus == 0x00)
 
@@ -9060,10 +5798,6 @@
 
                      {
                      pCurrSCCB->HostStatus = SCCB_BM_ERR;
-#if defined(BUGBUG)
-                     WR_HARPOON(port+hp_dual_addr_lo,
-                        RD_HARPOON(port+hp_ext_status));
-#endif
                      }
             }
          }
@@ -9092,22 +5826,12 @@
 
             sg_ptr--;
 
-#if defined(COMPILER_16_BIT) && !defined(DOS)
-            if (remain_cnt > (ULONG)(*(((ULONG far *)pCurrSCCB->
-               DataPointer) + (sg_ptr * 2)))) {
-
-               remain_cnt -= (ULONG)(*(((ULONG far *)pCurrSCCB->
-                  DataPointer) + (sg_ptr * 2)));
-               }
-
-#else
             if (remain_cnt > (ULONG)(*(((ULONG *)pCurrSCCB->
                DataPointer) + (sg_ptr * 2)))) {
 
                remain_cnt -= (ULONG)(*(((ULONG *)pCurrSCCB->
                   DataPointer) + (sg_ptr * 2)));
                }
-#endif
 
             else {
 
@@ -9147,7 +5871,7 @@
 
          if (RD_HARPOON(port+hp_ext_status) & BM_CMD_BUSY) {
 
-            busMstrTimeOut(port);
+            FPT_busMstrTimeOut(port);
             }
 
          else {
@@ -9159,10 +5883,6 @@
                   if (pCurrSCCB->HostStatus == 0x00) {
 
                      pCurrSCCB->HostStatus = SCCB_BM_ERR;
-#if defined(BUGBUG)
-                     WR_HARPOON(port+hp_dual_addr_lo,
-                        RD_HARPOON(port+hp_ext_status));
-#endif
                      }
                   }
                }
@@ -9203,7 +5923,7 @@
                   pCurrSCCB->HostStatus = SCCB_BM_ERR;
                   }
 
-               busMstrTimeOut(port);
+               FPT_busMstrTimeOut(port);
                }
             }
 
@@ -9214,10 +5934,6 @@
                if (pCurrSCCB->HostStatus == 0x00) {
 
                   pCurrSCCB->HostStatus = SCCB_BM_ERR;
-#if defined(BUGBUG)
-                  WR_HARPOON(port+hp_dual_addr_lo,
-                     RD_HARPOON(port+hp_ext_status));
-#endif
                   }
                }
             }
@@ -9241,7 +5957,7 @@
                pCurrSCCB->HostStatus = SCCB_BM_ERR;
                }
 
-            busMstrTimeOut(port);
+            FPT_busMstrTimeOut(port);
             }
          }
 
@@ -9253,10 +5969,6 @@
             if (pCurrSCCB->HostStatus == 0x00) {
 
                pCurrSCCB->HostStatus = SCCB_BM_ERR;
-#if defined(BUGBUG)
-               WR_HARPOON(port+hp_dual_addr_lo,
-                  RD_HARPOON(port+hp_ext_status));
-#endif
                }
             }
 
@@ -9305,15 +6017,11 @@
  *              pointers message.
  *
  *---------------------------------------------------------------------*/
-void hostDataXferRestart(PSCCB currSCCB)
+static void FPT_hostDataXferRestart(PSCCB currSCCB)
 {
    ULONG data_count;
    UINT  sg_index;
-#if defined(COMPILER_16_BIT) && !defined(DOS)
-   ULONG far *sg_ptr;
-#else
    ULONG *sg_ptr;
-#endif
 
    if (currSCCB->Sccb_XferState & F_SG_XFER) {
 
@@ -9322,11 +6030,7 @@
       sg_index = 0xffff;         /*Index by long words into sg list. */
       data_count = 0;            /*Running count of SG xfer counts. */
 
-#if defined(COMPILER_16_BIT) && !defined(DOS)
-      sg_ptr = (ULONG far *)currSCCB->DataPointer;
-#else
       sg_ptr = (ULONG *)currSCCB->DataPointer;
-#endif
 
       while (data_count < currSCCB->Sccb_ATC) {
 
@@ -9351,78 +6055,28 @@
       currSCCB->Sccb_XferCnt = currSCCB->DataLength - currSCCB->Sccb_ATC;
       }
 }
-#ident "$Id: scam.c 1.17 1997/03/20 23:49:37 mohan Exp $"
-/*----------------------------------------------------------------------
- *
- *
- *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
- *
- *   This file is available under both the GNU General Public License
- *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- *   $Workfile:   scam.c  $
- *
- *   Description:  Functions relating to handling of the SCAM selection
- *                 and the determination of the SCSI IDs to be assigned
- *                 to all perspective SCSI targets.
- *
- *   $Date: 1997/03/20 23:49:37 $
- *
- *   $Revision: 1.17 $
- *
- *----------------------------------------------------------------------*/
-
-/*#include <globals.h>*/
-
-#if (FW_TYPE==_UCB_MGR_)
-	/*#include <budi.h>*/
-#endif
-
-/*#include <sccbmgr.h>*/
-/*#include <blx30.h>*/
-/*#include <target.h>*/
-/*#include <scsi2.h>*/
-/*#include <eeprom.h>*/
-/*#include <harpoon.h>*/
 
 
 
-/*
-extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];
-extern SCCBCARD BL_Card[MAX_CARDS];
-extern SCCBSCAM_INFO scamInfo[MAX_SCSI_TAR];
-extern NVRAMINFO nvRamInfo[MAX_MB_CARDS];
-#if defined(DOS) || defined(OS2)
-extern UCHAR temp_id_string[ID_STRING_LENGTH];
-#endif
-extern UCHAR scamHAString[];
-*/
 /*---------------------------------------------------------------------
  *
- * Function: scini
+ * Function: FPT_scini
  *
  * Description: Setup all data structures necessary for SCAM selection.
  *
  *---------------------------------------------------------------------*/
 
-void scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up)
+static void FPT_scini(UCHAR p_card, UCHAR p_our_id, UCHAR p_power_up)
 {
 
-#if defined(SCAM_LEV_2)
    UCHAR loser,assigned_id;
-#endif
-#if defined(DOS)
-
-   USHORT p_port;
-#else
    ULONG p_port;
-#endif
 
    UCHAR i,k,ScamFlg ;
    PSCCBcard currCard;
 	PNVRamInfo pCurrNvRam;
 
-   currCard = &BL_Card[p_card];
+   currCard = &FPT_BL_Card[p_card];
    p_port = currCard->ioPort;
 	pCurrNvRam = currCard->pNvRamInfo;
 
@@ -9432,72 +6086,68 @@
 		i = pCurrNvRam->niSysConf;
 	}
 	else{
-	   ScamFlg = (UCHAR) utilEERead(p_port, SCAM_CONFIG/2);
-	   i = (UCHAR)(utilEERead(p_port, (SYSTEM_CONFIG/2)));
+	   ScamFlg = (UCHAR) FPT_utilEERead(p_port, SCAM_CONFIG/2);
+	   i = (UCHAR)(FPT_utilEERead(p_port, (SYSTEM_CONFIG/2)));
 	}
 	if(!(i & 0x02))	/* check if reset bus in AutoSCSI parameter set */
 		return;
 
-   inisci(p_card,p_port, p_our_id);
+   FPT_inisci(p_card,p_port, p_our_id);
 
    /* Force to wait 1 sec after SCSI bus reset. Some SCAM device FW
       too slow to return to SCAM selection */
 
    /* if (p_power_up)
-         Wait1Second(p_port);
+         FPT_Wait1Second(p_port);
       else
-         Wait(p_port, TO_250ms); */
+         FPT_Wait(p_port, TO_250ms); */
 
-   Wait1Second(p_port);
-
-#if defined(SCAM_LEV_2)
+   FPT_Wait1Second(p_port);
 
    if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2))
       {
-      while (!(scarb(p_port,INIT_SELTD))) {}
+      while (!(FPT_scarb(p_port,INIT_SELTD))) {}
 
-      scsel(p_port);
+      FPT_scsel(p_port);
 
       do {
-         scxferc(p_port,SYNC_PTRN);
-         scxferc(p_port,DOM_MSTR);
-         loser = scsendi(p_port,&scamInfo[p_our_id].id_string[0]);
+         FPT_scxferc(p_port,SYNC_PTRN);
+         FPT_scxferc(p_port,DOM_MSTR);
+         loser = FPT_scsendi(p_port,&FPT_scamInfo[p_our_id].id_string[0]);
          } while ( loser == 0xFF );
 
-      scbusf(p_port);
+      FPT_scbusf(p_port);
 
       if ((p_power_up) && (!loser))
          {
-         sresb(p_port,p_card);
-         Wait(p_port, TO_250ms);
+         FPT_sresb(p_port,p_card);
+         FPT_Wait(p_port, TO_250ms);
 
-         while (!(scarb(p_port,INIT_SELTD))) {}
+         while (!(FPT_scarb(p_port,INIT_SELTD))) {}
 
-         scsel(p_port);
+         FPT_scsel(p_port);
 
          do {
-            scxferc(p_port, SYNC_PTRN);
-            scxferc(p_port, DOM_MSTR);
-            loser = scsendi(p_port,&scamInfo[p_our_id].
+            FPT_scxferc(p_port, SYNC_PTRN);
+            FPT_scxferc(p_port, DOM_MSTR);
+            loser = FPT_scsendi(p_port,&FPT_scamInfo[p_our_id].
                id_string[0]);
             } while ( loser == 0xFF );
 
-         scbusf(p_port);
+         FPT_scbusf(p_port);
          }
       }
 
    else
       {
-      loser = FALSE;
+      loser = 0;
       }
 
 
    if (!loser)
       {
 
-#endif  /* SCAM_LEV_2 */
-
-      scamInfo[p_our_id].state = ID_ASSIGNED;
+      FPT_scamInfo[p_our_id].state = ID_ASSIGNED;
 
 
 		if (ScamFlg & SCAM_ENABLED)
@@ -9505,18 +6155,18 @@
 
 	      for (i=0; i < MAX_SCSI_TAR; i++)
   		   {
-      	   if ((scamInfo[i].state == ID_UNASSIGNED) ||
-  	      	   (scamInfo[i].state == ID_UNUSED))
+      	   if ((FPT_scamInfo[i].state == ID_UNASSIGNED) ||
+  	      	   (FPT_scamInfo[i].state == ID_UNUSED))
 	  	      {
-   	     	   if (scsell(p_port,i))
+   	     	   if (FPT_scsell(p_port,i))
       	  	   {
-            	   scamInfo[i].state = LEGACY;
-  	            	if ((scamInfo[i].id_string[0] != 0xFF) ||
-     	            	(scamInfo[i].id_string[1] != 0xFA))
+            	   FPT_scamInfo[i].state = LEGACY;
+  	            	if ((FPT_scamInfo[i].id_string[0] != 0xFF) ||
+     	            	(FPT_scamInfo[i].id_string[1] != 0xFA))
 	     	         {
 
-   	        	      scamInfo[i].id_string[0] = 0xFF;
-      	        	   scamInfo[i].id_string[1] = 0xFA;
+   	        	      FPT_scamInfo[i].id_string[0] = 0xFF;
+      	        	   FPT_scamInfo[i].id_string[1] = 0xFA;
 							if(pCurrNvRam == NULL)
 	         	         currCard->globalFlags |= F_UPDATE_EEPROM;
                	}
@@ -9524,45 +6174,43 @@
    	  	   }
       	}
 
-	      sresb(p_port,p_card);
-      	Wait1Second(p_port);
-         while (!(scarb(p_port,INIT_SELTD))) {}
-         scsel(p_port);
-         scasid(p_card, p_port);
+	      FPT_sresb(p_port,p_card);
+      	FPT_Wait1Second(p_port);
+         while (!(FPT_scarb(p_port,INIT_SELTD))) {}
+         FPT_scsel(p_port);
+         FPT_scasid(p_card, p_port);
          }
 
-#if defined(SCAM_LEV_2)
-
       }
 
    else if ((loser) && (ScamFlg & SCAM_ENABLED))
       {
-      scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0;
-      assigned_id = FALSE;
-      scwtsel(p_port);
+      FPT_scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0;
+      assigned_id = 0;
+      FPT_scwtsel(p_port);
 
       do {
-         while (scxferc(p_port,0x00) != SYNC_PTRN) {}
+         while (FPT_scxferc(p_port,0x00) != SYNC_PTRN) {}
 
-         i = scxferc(p_port,0x00);
+         i = FPT_scxferc(p_port,0x00);
          if (i == ASSIGN_ID)
             {
-            if (!(scsendi(p_port,&scamInfo[p_our_id].id_string[0])))
+            if (!(FPT_scsendi(p_port,&FPT_scamInfo[p_our_id].id_string[0])))
                   {
-                  i = scxferc(p_port,0x00);
-                  if (scvalq(i))
+                  i = FPT_scxferc(p_port,0x00);
+                  if (FPT_scvalq(i))
                      {
-                     k = scxferc(p_port,0x00);
+                     k = FPT_scxferc(p_port,0x00);
 
-                     if (scvalq(k))
+                     if (FPT_scvalq(k))
                         {
                         currCard->ourId =
                            ((UCHAR)(i<<3)+(k & (UCHAR)7)) & (UCHAR) 0x3F;
-                        inisci(p_card, p_port, p_our_id);
-                        scamInfo[currCard->ourId].state = ID_ASSIGNED;
-                        scamInfo[currCard->ourId].id_string[0]
+                        FPT_inisci(p_card, p_port, p_our_id);
+                        FPT_scamInfo[currCard->ourId].state = ID_ASSIGNED;
+                        FPT_scamInfo[currCard->ourId].id_string[0]
                            = SLV_TYPE_CODE0;
-                        assigned_id = TRUE;
+                        assigned_id = 1;
                         }
                      }
                   }
@@ -9570,43 +6218,31 @@
 
          else if (i == SET_P_FLAG)
             {
-               if (!(scsendi(p_port,
-                        &scamInfo[p_our_id].id_string[0])))
-                        scamInfo[p_our_id].id_string[0] |= 0x80;
+               if (!(FPT_scsendi(p_port,
+                        &FPT_scamInfo[p_our_id].id_string[0])))
+                        FPT_scamInfo[p_our_id].id_string[0] |= 0x80;
             }
          }while (!assigned_id);
 
-      while (scxferc(p_port,0x00) != CFG_CMPLT) {}
+      while (FPT_scxferc(p_port,0x00) != CFG_CMPLT) {}
       }
 
-#endif   /* SCAM_LEV_2 */
    if (ScamFlg & SCAM_ENABLED)
       {
-      scbusf(p_port);
+      FPT_scbusf(p_port);
       if (currCard->globalFlags & F_UPDATE_EEPROM)
          {
-         scsavdi(p_card, p_port);
+         FPT_scsavdi(p_card, p_port);
          currCard->globalFlags &= ~F_UPDATE_EEPROM;
          }
       }
 
 
-#if defined(DOS)
-   for (i=0; i < MAX_SCSI_TAR; i++)
-   {
-     	if (((ScamFlg & SCAM_ENABLED) && (scamInfo[i].state == LEGACY))
-			|| (i != p_our_id))
-        	{
-         scsellDOS(p_port,i);
-  	      }
-  	}
-#endif
-
 /*
    for (i=0,k=0; i < MAX_SCSI_TAR; i++)
       {
-      if ((scamInfo[i].state == ID_ASSIGNED) ||
-         (scamInfo[i].state == LEGACY))
+      if ((FPT_scamInfo[i].state == ID_ASSIGNED) ||
+         (FPT_scamInfo[i].state == LEGACY))
          k++;
       }
 
@@ -9620,17 +6256,13 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: scarb
+ * Function: FPT_scarb
  *
  * Description: Gain control of the bus and wait SCAM select time (250ms)
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-int scarb(USHORT p_port, UCHAR p_sel_type)
-#else
-int scarb(ULONG p_port, UCHAR p_sel_type)
-#endif
+static int FPT_scarb(ULONG p_port, UCHAR p_sel_type)
 {
    if (p_sel_type == INIT_SELTD)
       {
@@ -9639,10 +6271,10 @@
 
 
       if (RD_HARPOON(p_port+hp_scsisig) & SCSI_SEL)
-         return(FALSE);
+         return(0);
 
       if (RD_HARPOON(p_port+hp_scsidata_0) != 00)
-         return(FALSE);
+         return(0);
 
       WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) | SCSI_BSY));
 
@@ -9650,7 +6282,7 @@
 
          WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) &
             ~SCSI_BSY));
-         return(FALSE);
+         return(0);
          }
 
 
@@ -9660,7 +6292,7 @@
 
          WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) &
             ~(SCSI_BSY | SCSI_SEL)));
-         return(FALSE);
+         return(0);
          }
       }
 
@@ -9669,9 +6301,7 @@
       & ~ACTdeassert));
    WR_HARPOON(p_port+hp_scsireset, SCAM_EN);
    WR_HARPOON(p_port+hp_scsidata_0, 0x00);
-#if defined(WIDE_SCSI)
    WR_HARPOON(p_port+hp_scsidata_1, 0x00);
-#endif
    WR_HARPOON(p_port+hp_portctrl_0, SCSI_BUS_EN);
 
    WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig) | SCSI_MSG));
@@ -9679,25 +6309,21 @@
    WR_HARPOON(p_port+hp_scsisig, (RD_HARPOON(p_port+hp_scsisig)
       & ~SCSI_BSY));
 
-   Wait(p_port,TO_250ms);
+   FPT_Wait(p_port,TO_250ms);
 
-   return(TRUE);
+   return(1);
 }
 
 
 /*---------------------------------------------------------------------
  *
- * Function: scbusf
+ * Function: FPT_scbusf
  *
  * Description: Release the SCSI bus and disable SCAM selection.
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void scbusf(USHORT p_port)
-#else
-void scbusf(ULONG p_port)
-#endif
+static void FPT_scbusf(ULONG p_port)
 {
    WR_HARPOON(p_port+hp_page_ctrl,
       (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE));
@@ -9717,11 +6343,7 @@
    WR_HARPOON(p_port+hp_clkctrl_0, (RD_HARPOON(p_port+hp_clkctrl_0)
       | ACTdeassert));
 
-#if defined(SCAM_LEV_2)
    WRW_HARPOON((p_port+hp_intstat), (BUS_FREE | AUTO_INT | SCAM_SEL));
-#else
-   WRW_HARPOON((p_port+hp_intstat), (BUS_FREE | AUTO_INT));
-#endif
 
    WR_HARPOON(p_port+hp_page_ctrl,
       (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE));
@@ -9731,35 +6353,24 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: scasid
+ * Function: FPT_scasid
  *
  * Description: Assign an ID to all the SCAM devices.
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void scasid(UCHAR p_card, USHORT p_port)
-#else
-void scasid(UCHAR p_card, ULONG p_port)
-#endif
+static void FPT_scasid(UCHAR p_card, ULONG p_port)
 {
-#if defined(DOS) || defined(OS2)
-   /* Use external defined in global space area, instead of Stack
-      space. WIN/95 DOS doesnot work TINY mode. The OS doesnot intialize
-      SS equal to DS. Thus the array allocated on stack doesnot get
-      access correctly */
-#else
    UCHAR temp_id_string[ID_STRING_LENGTH];
-#endif
 
    UCHAR i,k,scam_id;
 	UCHAR crcBytes[3];
 	PNVRamInfo pCurrNvRam;
 	ushort_ptr pCrcBytes;
 
-	pCurrNvRam = BL_Card[p_card].pNvRamInfo;
+	pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
 
-   i=FALSE;
+   i=0;
 
    while (!i)
       {
@@ -9769,36 +6380,36 @@
          temp_id_string[k] = (UCHAR) 0x00;
          }
 
-      scxferc(p_port,SYNC_PTRN);
-      scxferc(p_port,ASSIGN_ID);
+      FPT_scxferc(p_port,SYNC_PTRN);
+      FPT_scxferc(p_port,ASSIGN_ID);
 
-      if (!(sciso(p_port,&temp_id_string[0])))
+      if (!(FPT_sciso(p_port,&temp_id_string[0])))
          {
 			if(pCurrNvRam){
 				pCrcBytes = (ushort_ptr)&crcBytes[0];
-				*pCrcBytes = CalcCrc16(&temp_id_string[0]);
-				crcBytes[2] = CalcLrc(&temp_id_string[0]);
+				*pCrcBytes = FPT_CalcCrc16(&temp_id_string[0]);
+				crcBytes[2] = FPT_CalcLrc(&temp_id_string[0]);
 				temp_id_string[1] = crcBytes[2];
 				temp_id_string[2] = crcBytes[0];
 				temp_id_string[3] = crcBytes[1];
 				for(k = 4; k < ID_STRING_LENGTH; k++)
 					temp_id_string[k] = (UCHAR) 0x00;
 			}
-         i = scmachid(p_card,temp_id_string);
+         i = FPT_scmachid(p_card,temp_id_string);
 
          if (i == CLR_PRIORITY)
             {
-            scxferc(p_port,MISC_CODE);
-            scxferc(p_port,CLR_P_FLAG);
-            i = FALSE;  /*Not the last ID yet. */
+            FPT_scxferc(p_port,MISC_CODE);
+            FPT_scxferc(p_port,CLR_P_FLAG);
+            i = 0;  /*Not the last ID yet. */
             }
 
          else if (i != NO_ID_AVAIL)
             {
             if (i < 8 )
-               scxferc(p_port,ID_0_7);
+               FPT_scxferc(p_port,ID_0_7);
             else
-               scxferc(p_port,ID_8_F);
+               FPT_scxferc(p_port,ID_8_F);
 
             scam_id = (i & (UCHAR) 0x07);
 
@@ -9807,21 +6418,21 @@
                if (!( k & i ))
                   scam_id += 0x08;        /*Count number of zeros in DB0-3. */
 
-            scxferc(p_port,scam_id);
+            FPT_scxferc(p_port,scam_id);
 
-            i = FALSE;  /*Not the last ID yet. */
+            i = 0;  /*Not the last ID yet. */
             }
          }
 
       else
          {
-         i = TRUE;
+         i = 1;
          }
 
       }  /*End while */
 
-   scxferc(p_port,SYNC_PTRN);
-   scxferc(p_port,CFG_CMPLT);
+   FPT_scxferc(p_port,SYNC_PTRN);
+   FPT_scxferc(p_port,CFG_CMPLT);
 }
 
 
@@ -9830,21 +6441,17 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: scsel
+ * Function: FPT_scsel
  *
  * Description: Select all the SCAM devices.
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void scsel(USHORT p_port)
-#else
-void scsel(ULONG p_port)
-#endif
+static void FPT_scsel(ULONG p_port)
 {
 
    WR_HARPOON(p_port+hp_scsisig, SCSI_SEL);
-   scwiros(p_port, SCSI_MSG);
+   FPT_scwiros(p_port, SCSI_MSG);
 
    WR_HARPOON(p_port+hp_scsisig, (SCSI_SEL | SCSI_BSY));
 
@@ -9855,11 +6462,11 @@
 
 
    WR_HARPOON(p_port+hp_scsisig, (SCSI_BSY | SCSI_IOBIT | SCSI_CD));
-   scwiros(p_port, SCSI_SEL);
+   FPT_scwiros(p_port, SCSI_SEL);
 
    WR_HARPOON(p_port+hp_scsidata_0, (UCHAR)(RD_HARPOON(p_port+hp_scsidata_0) &
       ~(UCHAR)BIT(6)));
-   scwirod(p_port, BIT(6));
+   FPT_scwirod(p_port, BIT(6));
 
    WR_HARPOON(p_port+hp_scsisig, (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
 }
@@ -9868,17 +6475,13 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: scxferc
+ * Function: FPT_scxferc
  *
  * Description: Handshake the p_data (DB4-0) across the bus.
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-UCHAR scxferc(USHORT p_port, UCHAR p_data)
-#else
-UCHAR scxferc(ULONG p_port, UCHAR p_data)
-#endif
+static UCHAR FPT_scxferc(ULONG p_port, UCHAR p_data)
 {
    UCHAR curr_data, ret_data;
 
@@ -9890,7 +6493,7 @@
 
    WR_HARPOON(p_port+hp_scsidata_0, curr_data);
 
-   scwirod(p_port,BIT(7));              /*Wait for DB7 to be released. */
+   FPT_scwirod(p_port,BIT(7));              /*Wait for DB7 to be released. */
 	while (!(RD_HARPOON(p_port+hp_scsidata_0) & BIT(5)));
 
    ret_data = (RD_HARPOON(p_port+hp_scsidata_0) & (UCHAR) 0x1F);
@@ -9903,7 +6506,7 @@
 
    WR_HARPOON(p_port+hp_scsidata_0, curr_data);
 
-   scwirod(p_port,BIT(5));              /*Wait for DB5 to be released. */
+   FPT_scwirod(p_port,BIT(5));              /*Wait for DB5 to be released. */
 
    curr_data &= ~(BIT(4)|BIT(3)|BIT(2)|BIT(1)|BIT(0)); /*Release data bits */
    curr_data |= BIT(7);
@@ -9914,7 +6517,7 @@
 
    WR_HARPOON(p_port+hp_scsidata_0, curr_data);
 
-   scwirod(p_port,BIT(6));              /*Wait for DB6 to be released. */
+   FPT_scwirod(p_port,BIT(6));              /*Wait for DB6 to be released. */
 
    return(ret_data);
 }
@@ -9922,39 +6525,35 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: scsendi
+ * Function: FPT_scsendi
  *
  * Description: Transfer our Identification string to determine if we
  *              will be the dominant master.
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-UCHAR scsendi(USHORT p_port, UCHAR p_id_string[])
-#else
-UCHAR scsendi(ULONG p_port, UCHAR p_id_string[])
-#endif
+static UCHAR FPT_scsendi(ULONG p_port, UCHAR p_id_string[])
 {
    UCHAR ret_data,byte_cnt,bit_cnt,defer;
 
-   defer = FALSE;
+   defer = 0;
 
    for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
 
       for (bit_cnt = 0x80; bit_cnt != 0 ; bit_cnt >>= 1) {
 
          if (defer)
-            ret_data = scxferc(p_port,00);
+            ret_data = FPT_scxferc(p_port,00);
 
          else if (p_id_string[byte_cnt] & bit_cnt)
 
-               ret_data = scxferc(p_port,02);
+               ret_data = FPT_scxferc(p_port,02);
 
             else {
 
-               ret_data = scxferc(p_port,01);
+               ret_data = FPT_scxferc(p_port,01);
                if (ret_data & 02)
-                  defer = TRUE;
+                  defer = 1;
                }
 
          if ((ret_data & 0x1C) == 0x10)
@@ -9980,17 +6579,13 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: sciso
+ * Function: FPT_sciso
  *
  * Description: Transfer the Identification string.
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-UCHAR sciso(USHORT p_port, UCHAR p_id_string[])
-#else
-UCHAR sciso(ULONG p_port, UCHAR p_id_string[])
-#endif
+static UCHAR FPT_sciso(ULONG p_port, UCHAR p_id_string[])
 {
    UCHAR ret_data,the_data,byte_cnt,bit_cnt;
 
@@ -10000,7 +6595,7 @@
 
       for (bit_cnt = 0; bit_cnt < 8; bit_cnt++) {
 
-         ret_data = scxferc(p_port,0);
+         ret_data = FPT_scxferc(p_port,0);
 
          if (ret_data & 0xFC)
             return(0xFF);
@@ -10020,8 +6615,8 @@
 				{
 					byte_cnt = 0;
 					bit_cnt = 0;
-					scxferc(p_port, SYNC_PTRN);
-					scxferc(p_port, ASSIGN_ID);
+					FPT_scxferc(p_port, SYNC_PTRN);
+					FPT_scxferc(p_port, ASSIGN_ID);
 					continue;
 				}
 */
@@ -10044,18 +6639,14 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: scwirod
+ * Function: FPT_scwirod
  *
  * Description: Sample the SCSI data bus making sure the signal has been
  *              deasserted for the correct number of consecutive samples.
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void scwirod(USHORT p_port, UCHAR p_data_bit)
-#else
-void scwirod(ULONG p_port, UCHAR p_data_bit)
-#endif
+static void FPT_scwirod(ULONG p_port, UCHAR p_data_bit)
 {
    UCHAR i;
 
@@ -10077,18 +6668,14 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: scwiros
+ * Function: FPT_scwiros
  *
  * Description: Sample the SCSI Signal lines making sure the signal has been
  *              deasserted for the correct number of consecutive samples.
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void scwiros(USHORT p_port, UCHAR p_data_bit)
-#else
-void scwiros(ULONG p_port, UCHAR p_data_bit)
-#endif
+static void FPT_scwiros(ULONG p_port, UCHAR p_data_bit)
 {
    UCHAR i;
 
@@ -10109,13 +6696,13 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: scvalq
+ * Function: FPT_scvalq
  *
  * Description: Make sure we received a valid data byte.
  *
  *---------------------------------------------------------------------*/
 
-UCHAR scvalq(UCHAR p_quintet)
+static UCHAR FPT_scvalq(UCHAR p_quintet)
 {
    UCHAR count;
 
@@ -10125,16 +6712,16 @@
       }
 
    if (p_quintet & 0x18)
-      return(FALSE);
+      return(0);
 
    else
-      return(TRUE);
+      return(1);
 }
 
 
 /*---------------------------------------------------------------------
  *
- * Function: scsell
+ * Function: FPT_scsell
  *
  * Description: Select the specified device ID using a selection timeout
  *              less than 4ms.  If somebody responds then it is a legacy
@@ -10142,17 +6729,9 @@
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-UCHAR scsell(USHORT p_port, UCHAR targ_id)
-#else
-UCHAR scsell(ULONG p_port, UCHAR targ_id)
-#endif
+static UCHAR FPT_scsell(ULONG p_port, UCHAR targ_id)
 {
-#if defined(DOS)
-   USHORT i;
-#else
    ULONG i;
-#endif
 
    WR_HARPOON(p_port+hp_page_ctrl,
       (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE));
@@ -10182,7 +6761,7 @@
 	    (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {}
 
    if (RDW_HARPOON((p_port+hp_intstat)) & RESET)
-         Wait(p_port, TO_250ms);
+         FPT_Wait(p_port, TO_250ms);
 
    DISABLE_AUTO(p_port);
 
@@ -10199,7 +6778,7 @@
       WR_HARPOON(p_port+hp_page_ctrl,
          (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE));
 
-      return(FALSE);  /*No legacy device */
+      return(0);  /*No legacy device */
       }
 
    else {
@@ -10217,108 +6796,19 @@
       WR_HARPOON(p_port+hp_page_ctrl,
          (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE));
 
-      return(TRUE);  /*Found one of them oldies! */
+      return(1);  /*Found one of them oldies! */
       }
 }
 
-#if defined(DOS)
 /*---------------------------------------------------------------------
  *
- * Function: scsell for DOS
- *
- * Description: Select the specified device ID using a selection timeout
- *              less than 2ms.  This was specially required to solve
- *              the problem with Plextor 12X CD-ROM drive. This drive
- *					 was responding the Selection at the end of 4ms and 
- *					 hanging the system.
- *
- *---------------------------------------------------------------------*/
-
-UCHAR scsellDOS(USHORT p_port, UCHAR targ_id)
-{
-   USHORT i;
-
-   WR_HARPOON(p_port+hp_page_ctrl,
-      (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE));
-
-   ARAM_ACCESS(p_port);
-
-   WR_HARPOON(p_port+hp_addstat,(RD_HARPOON(p_port+hp_addstat) | SCAM_TIMER));
-   WR_HARPOON(p_port+hp_seltimeout,TO_2ms);
-
-
-   for (i = p_port+CMD_STRT; i < p_port+CMD_STRT+12; i+=2) {
-      WRW_HARPOON(i, (MPM_OP+ACOMMAND));
-      }
-   WRW_HARPOON(i, (BRH_OP+ALWAYS+    NP));
-
-   WRW_HARPOON((p_port+hp_intstat),
-	       (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT));
-
-   WR_HARPOON(p_port+hp_select_id, targ_id);
-
-   WR_HARPOON(p_port+hp_portctrl_0, SCSI_PORT);
-   WR_HARPOON(p_port+hp_autostart_3, (SELECT | CMD_ONLY_STRT));
-   WR_HARPOON(p_port+hp_scsictrl_0, (SEL_TAR | ENA_RESEL));
-
-
-   while (!(RDW_HARPOON((p_port+hp_intstat)) &
-	    (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {}
-
-   if (RDW_HARPOON((p_port+hp_intstat)) & RESET)
-         Wait(p_port, TO_250ms);
-
-   DISABLE_AUTO(p_port);
-
-   WR_HARPOON(p_port+hp_addstat,(RD_HARPOON(p_port+hp_addstat) & ~SCAM_TIMER));
-   WR_HARPOON(p_port+hp_seltimeout,TO_290ms);
-
-   SGRAM_ACCESS(p_port);
-
-   if (RDW_HARPOON((p_port+hp_intstat)) & (RESET | TIMEOUT) ) {
-
-      WRW_HARPOON((p_port+hp_intstat),
-		  (RESET | TIMEOUT | SEL | BUS_FREE | PHASE));
-
-      WR_HARPOON(p_port+hp_page_ctrl,
-         (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE));
-
-      return(FALSE);  /*No legacy device */
-      }
-
-   else {
-
-      while(!(RDW_HARPOON((p_port+hp_intstat)) & BUS_FREE)) {
-				if (RD_HARPOON(p_port+hp_scsisig) & SCSI_REQ)
-					{
-					WR_HARPOON(p_port+hp_scsisig, (SCSI_ACK + S_ILL_PH));
-      			ACCEPT_MSG(p_port);
-					}
-		}
-
-      WRW_HARPOON((p_port+hp_intstat), CLR_ALL_INT_1);
-
-      WR_HARPOON(p_port+hp_page_ctrl,
-         (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE));
-
-      return(TRUE);  /*Found one of them oldies! */
-      }
-}
-#endif  /* DOS */
-
-/*---------------------------------------------------------------------
- *
- * Function: scwtsel
+ * Function: FPT_scwtsel
  *
  * Description: Wait to be selected by another SCAM initiator.
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void scwtsel(USHORT p_port)
-#else
-void scwtsel(ULONG p_port)
-#endif
+static void FPT_scwtsel(ULONG p_port)
 {
    while(!(RDW_HARPOON((p_port+hp_intstat)) & SCAM_SEL)) {}
 }
@@ -10326,23 +6816,19 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: inisci
+ * Function: FPT_inisci
  *
  * Description: Setup the data Structure with the info from the EEPROM.
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void inisci(UCHAR p_card, USHORT p_port, UCHAR p_our_id)
-#else
-void inisci(UCHAR p_card, ULONG p_port, UCHAR p_our_id)
-#endif
+static void FPT_inisci(UCHAR p_card, ULONG p_port, UCHAR p_our_id)
 {
    UCHAR i,k,max_id;
    USHORT ee_data;
 	PNVRamInfo pCurrNvRam;
 
-	pCurrNvRam = BL_Card[p_card].pNvRamInfo;
+	pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
 
    if (RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD)
       max_id = 0x08;
@@ -10354,14 +6840,14 @@
 		for(i = 0; i < max_id; i++){
 
 			for(k = 0; k < 4; k++)
-				scamInfo[i].id_string[k] = pCurrNvRam->niScamTbl[i][k];
+				FPT_scamInfo[i].id_string[k] = pCurrNvRam->niScamTbl[i][k];
 			for(k = 4; k < ID_STRING_LENGTH; k++)
-				scamInfo[i].id_string[k] = (UCHAR) 0x00;
+				FPT_scamInfo[i].id_string[k] = (UCHAR) 0x00;
 
-	      if(scamInfo[i].id_string[0] == 0x00)
-      	   scamInfo[i].state = ID_UNUSED;  /*Default to unused ID. */
+	      if(FPT_scamInfo[i].id_string[0] == 0x00)
+      	   FPT_scamInfo[i].state = ID_UNUSED;  /*Default to unused ID. */
 	      else
-   	      scamInfo[i].state = ID_UNASSIGNED;  /*Default to unassigned ID. */
+   	      FPT_scamInfo[i].state = ID_UNASSIGNED;  /*Default to unassigned ID. */
 
 		}
 	}else {
@@ -10369,38 +6855,38 @@
    	   {
       	for (k=0; k < ID_STRING_LENGTH; k+=2)
 	         {
-   	      ee_data = utilEERead(p_port, (USHORT)((EE_SCAMBASE/2) +
+   	      ee_data = FPT_utilEERead(p_port, (USHORT)((EE_SCAMBASE/2) +
       	     (USHORT) (i*((USHORT)ID_STRING_LENGTH/2)) + (USHORT)(k/2)));
-         	scamInfo[i].id_string[k] = (UCHAR) ee_data;
+         	FPT_scamInfo[i].id_string[k] = (UCHAR) ee_data;
 	         ee_data >>= 8;
-   	      scamInfo[i].id_string[k+1] = (UCHAR) ee_data;
+   	      FPT_scamInfo[i].id_string[k+1] = (UCHAR) ee_data;
       	   }
 
-	      if ((scamInfo[i].id_string[0] == 0x00) ||
-   	       (scamInfo[i].id_string[0] == 0xFF))
+	      if ((FPT_scamInfo[i].id_string[0] == 0x00) ||
+   	       (FPT_scamInfo[i].id_string[0] == 0xFF))
 
-      	   scamInfo[i].state = ID_UNUSED;  /*Default to unused ID. */
+      	   FPT_scamInfo[i].state = ID_UNUSED;  /*Default to unused ID. */
 
 	      else
-   	      scamInfo[i].state = ID_UNASSIGNED;  /*Default to unassigned ID. */
+   	      FPT_scamInfo[i].state = ID_UNASSIGNED;  /*Default to unassigned ID. */
 
       	}
 	}
 	for(k = 0; k < ID_STRING_LENGTH; k++)
-		scamInfo[p_our_id].id_string[k] = scamHAString[k];
+		FPT_scamInfo[p_our_id].id_string[k] = FPT_scamHAString[k];
 
 }
 
 /*---------------------------------------------------------------------
  *
- * Function: scmachid
+ * Function: FPT_scmachid
  *
  * Description: Match the Device ID string with our values stored in
  *              the EEPROM.
  *
  *---------------------------------------------------------------------*/
 
-UCHAR scmachid(UCHAR p_card, UCHAR p_id_string[])
+static UCHAR FPT_scmachid(UCHAR p_card, UCHAR p_id_string[])
 {
 
    UCHAR i,k,match;
@@ -10408,28 +6894,20 @@
 
    for (i=0; i < MAX_SCSI_TAR; i++) {
 
-#if !defined(SCAM_LEV_2)
-      if (scamInfo[i].state == ID_UNASSIGNED)
-         {
-#endif
-         match = TRUE;
+         match = 1;
 
          for (k=0; k < ID_STRING_LENGTH; k++)
             {
-            if (p_id_string[k] != scamInfo[i].id_string[k])
-               match = FALSE;
+            if (p_id_string[k] != FPT_scamInfo[i].id_string[k])
+               match = 0;
             }
 
          if (match)
             {
-            scamInfo[i].state = ID_ASSIGNED;
+            FPT_scamInfo[i].state = ID_ASSIGNED;
             return(i);
             }
 
-#if !defined(SCAM_LEV_2)
-         }
-#endif
-
       }
 
 
@@ -10448,17 +6926,17 @@
       {
       i--;
 
-      if (scamInfo[match].state == ID_UNUSED)
+      if (FPT_scamInfo[match].state == ID_UNUSED)
          {
          for (k=0; k < ID_STRING_LENGTH; k++)
             {
-            scamInfo[match].id_string[k] = p_id_string[k];
+            FPT_scamInfo[match].id_string[k] = p_id_string[k];
             }
 
-         scamInfo[match].state = ID_ASSIGNED;
+         FPT_scamInfo[match].state = ID_ASSIGNED;
 
-			if(BL_Card[p_card].pNvRamInfo == NULL)
-	         BL_Card[p_card].globalFlags |= F_UPDATE_EEPROM;
+			if(FPT_BL_Card[p_card].pNvRamInfo == NULL)
+	         FPT_BL_Card[p_card].globalFlags |= F_UPDATE_EEPROM;
          return(match);
 
          }
@@ -10498,17 +6976,17 @@
 
       i--;
 
-      if (scamInfo[match].state == ID_UNASSIGNED)
+      if (FPT_scamInfo[match].state == ID_UNASSIGNED)
          {
          for (k=0; k < ID_STRING_LENGTH; k++)
             {
-            scamInfo[match].id_string[k] = p_id_string[k];
+            FPT_scamInfo[match].id_string[k] = p_id_string[k];
             }
 
-         scamInfo[match].id_string[0] |= BIT(7);
-         scamInfo[match].state = ID_ASSIGNED;
-			if(BL_Card[p_card].pNvRamInfo == NULL)
-	         BL_Card[p_card].globalFlags |= F_UPDATE_EEPROM;
+         FPT_scamInfo[match].id_string[0] |= BIT(7);
+         FPT_scamInfo[match].state = ID_ASSIGNED;
+			if(FPT_BL_Card[p_card].pNvRamInfo == NULL)
+	         FPT_BL_Card[p_card].globalFlags |= F_UPDATE_EEPROM;
          return(match);
 
          }
@@ -10531,17 +7009,13 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: scsavdi
+ * Function: FPT_scsavdi
  *
  * Description: Save off the device SCAM ID strings.
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void scsavdi(UCHAR p_card, USHORT p_port)
-#else
-void scsavdi(UCHAR p_card, ULONG p_port)
-#endif
+static void FPT_scsavdi(UCHAR p_card, ULONG p_port)
 {
    UCHAR i,k,max_id;
    USHORT ee_data,sum_data;
@@ -10551,11 +7025,11 @@
 
    for (i = 1; i < EE_SCAMBASE/2; i++)
       {
-      sum_data += utilEERead(p_port, i);
+      sum_data += FPT_utilEERead(p_port, i);
       }
 
 
-   utilEEWriteOnOff(p_port,1);   /* Enable write access to the EEPROM */
+   FPT_utilEEWriteOnOff(p_port,1);   /* Enable write access to the EEPROM */
 
    if (RD_HARPOON(p_port+hp_page_ctrl) & NARROW_SCSI_CARD)
       max_id = 0x08;
@@ -10568,64 +7042,29 @@
 
       for (k=0; k < ID_STRING_LENGTH; k+=2)
          {
-         ee_data = scamInfo[i].id_string[k+1];
+         ee_data = FPT_scamInfo[i].id_string[k+1];
          ee_data <<= 8;
-         ee_data |= scamInfo[i].id_string[k];
+         ee_data |= FPT_scamInfo[i].id_string[k];
          sum_data += ee_data;
-         utilEEWrite(p_port, ee_data, (USHORT)((EE_SCAMBASE/2) +
+         FPT_utilEEWrite(p_port, ee_data, (USHORT)((EE_SCAMBASE/2) +
             (USHORT)(i*((USHORT)ID_STRING_LENGTH/2)) + (USHORT)(k/2)));
          }
       }
 
 
-   utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM/2);
-   utilEEWriteOnOff(p_port,0);   /* Turn off write access */
+   FPT_utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM/2);
+   FPT_utilEEWriteOnOff(p_port,0);   /* Turn off write access */
 }
-#ident "$Id: diagnose.c 1.10 1997/06/10 16:51:47 mohan Exp $"
-/*----------------------------------------------------------------------
- *
- *
- *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
- *
- *   This file is available under both the GNU General Public License
- *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- *   $Workfile:   diagnose.c  $
- *
- *   Description:  Diagnostic funtions for testing the integrity of
- *                 the HARPOON.
- *
- *   $Date: 1997/06/10 16:51:47 $
- *
- *   $Revision: 1.10 $
- *
- *----------------------------------------------------------------------*/
-
-/*#include <globals.h>*/
-
-#if (FW_TYPE==_UCB_MGR_)
-	/*#include <budi.h>*/
-#endif
-
-/*#include <sccbmgr.h>*/
-/*#include <blx30.h>*/
-/*#include <target.h>*/
-/*#include <eeprom.h>*/
-/*#include <harpoon.h>*/
 
 /*---------------------------------------------------------------------
  *
- * Function: XbowInit
+ * Function: FPT_XbowInit
  *
  * Description: Setup the Xbow for normal operation.
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void XbowInit(USHORT port, UCHAR ScamFlg)
-#else
-void XbowInit(ULONG port, UCHAR ScamFlg)
-#endif
+static void FPT_XbowInit(ULONG port, UCHAR ScamFlg)
 {
 UCHAR i;
 
@@ -10647,18 +7086,13 @@
 
    WRW_HARPOON((port+hp_intstat), CLR_ALL_INT);
 
-#if defined(SCAM_LEV_2)
-   default_intena = RESET | RSEL | PROG_HLT | TIMEOUT |
+   FPT_default_intena = RESET | RSEL | PROG_HLT | TIMEOUT |
 		    BUS_FREE | XFER_CNT_0 | AUTO_INT;
 
    if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2))
-		default_intena |= SCAM_SEL;
+		FPT_default_intena |= SCAM_SEL;
 
-#else
-   default_intena = RESET | RSEL | PROG_HLT | TIMEOUT |
-		    BUS_FREE | XFER_CNT_0 | AUTO_INT;
-#endif
-   WRW_HARPOON((port+hp_intena), default_intena);
+   WRW_HARPOON((port+hp_intena), FPT_default_intena);
 
    WR_HARPOON(port+hp_seltimeout,TO_290ms);
 
@@ -10667,26 +7101,6 @@
    if (RD_HARPOON(port+hp_page_ctrl) & NARROW_SCSI_CARD)
       WR_HARPOON(port+hp_addstat,SCSI_MODE8);
 
-#if defined(NO_BIOS_OPTION)
-
-   WR_HARPOON(port+hp_synctarg_0,NARROW_SCSI);
-   WR_HARPOON(port+hp_synctarg_1,NARROW_SCSI);
-   WR_HARPOON(port+hp_synctarg_2,NARROW_SCSI);
-   WR_HARPOON(port+hp_synctarg_3,NARROW_SCSI);
-   WR_HARPOON(port+hp_synctarg_4,NARROW_SCSI);
-   WR_HARPOON(port+hp_synctarg_5,NARROW_SCSI);
-   WR_HARPOON(port+hp_synctarg_6,NARROW_SCSI);
-   WR_HARPOON(port+hp_synctarg_7,NARROW_SCSI);
-   WR_HARPOON(port+hp_synctarg_8,NARROW_SCSI);
-   WR_HARPOON(port+hp_synctarg_9,NARROW_SCSI);
-   WR_HARPOON(port+hp_synctarg_10,NARROW_SCSI);
-   WR_HARPOON(port+hp_synctarg_11,NARROW_SCSI);
-   WR_HARPOON(port+hp_synctarg_12,NARROW_SCSI);
-   WR_HARPOON(port+hp_synctarg_13,NARROW_SCSI);
-   WR_HARPOON(port+hp_synctarg_14,NARROW_SCSI);
-   WR_HARPOON(port+hp_synctarg_15,NARROW_SCSI);
-
-#endif
 	WR_HARPOON(port+hp_page_ctrl, i);
 
 }
@@ -10694,17 +7108,13 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: BusMasterInit
+ * Function: FPT_BusMasterInit
  *
  * Description: Initialize the BusMaster for normal operations.
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void BusMasterInit(USHORT p_port)
-#else
-void BusMasterInit(ULONG p_port)
-#endif
+static void FPT_BusMasterInit(ULONG p_port)
 {
 
 
@@ -10719,13 +7129,6 @@
    WR_HARPOON(p_port+hp_ee_ctrl, (SCSI_TERM_ENA_H));
 
 
-#if defined(NT)
-
-   WR_HARPOON(p_port+hp_pci_cmd_cfg, (RD_HARPOON(p_port+hp_pci_cmd_cfg)
-      & ~MEM_SPACE_ENA));
-
-#endif
-
    RD_HARPOON(p_port+hp_int_status);        /*Clear interrupts. */
    WR_HARPOON(p_port+hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
    WR_HARPOON(p_port+hp_page_ctrl, (RD_HARPOON(p_port+hp_page_ctrl) &
@@ -10735,147 +7138,14 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: DiagXbow
- *
- * Description: Test Xbow integrity.  Non-zero return indicates an error.
- *
- *---------------------------------------------------------------------*/
-
-#if defined(DOS)
-int DiagXbow(USHORT port)
-#else
-int DiagXbow(ULONG port)
-#endif
-{
-   unsigned char fifo_cnt,loop_cnt;
-
-   unsigned char fifodata[5];
-   fifodata[0] = 0x00;
-   fifodata[1] = 0xFF;
-   fifodata[2] = 0x55;
-   fifodata[3] = 0xAA;
-   fifodata[4] = 0x00;
-
-
-   WRW_HARPOON((port+hp_intstat), CLR_ALL_INT);
-   WRW_HARPOON((port+hp_intena), 0x0000);
-
-   WR_HARPOON(port+hp_seltimeout,TO_5ms);
-
-   WR_HARPOON(port+hp_portctrl_0,START_TO);
-
-
-   for(fifodata[4] = 0x01; fifodata[4] != (UCHAR) 0; fifodata[4] = fifodata[4] << 1) {
-
-      WR_HARPOON(port+hp_selfid_0,fifodata[4]);
-      WR_HARPOON(port+hp_selfid_1,fifodata[4]);
-
-      if ((RD_HARPOON(port+hp_selfid_0) != fifodata[4]) ||
-          (RD_HARPOON(port+hp_selfid_1) != fifodata[4]))
-         return(1);
-      }
-
-
-   for(loop_cnt = 0; loop_cnt < 4; loop_cnt++) {
-
-      WR_HARPOON(port+hp_portctrl_0,(HOST_PORT | HOST_WRT | START_TO));
-
-
-      for (fifo_cnt = 0; fifo_cnt < FIFO_LEN; fifo_cnt++) {
-
-         WR_HARPOON(port+hp_fifodata_0, fifodata[loop_cnt]);
-         }
-
-
-      if (!(RD_HARPOON(port+hp_xferstat) & FIFO_FULL))
-         return(1);
-
-
-      WR_HARPOON(port+hp_portctrl_0,(HOST_PORT | START_TO));
-
-      for (fifo_cnt = 0; fifo_cnt < FIFO_LEN; fifo_cnt++) {
-
-         if (RD_HARPOON(port+hp_fifodata_0) != fifodata[loop_cnt])
-            return(1);
-         }
-
-
-      if (!(RD_HARPOON(port+hp_xferstat) & FIFO_EMPTY))
-         return(1);
-      }
-
-
-   while(!(RDW_HARPOON((port+hp_intstat)) & TIMEOUT)) {}
-
-
-   WR_HARPOON(port+hp_seltimeout,TO_290ms);
-
-   WRW_HARPOON((port+hp_intstat), CLR_ALL_INT);
-
-   WRW_HARPOON((port+hp_intena), default_intena);
-
-   return(0);
-}
-
-
-/*---------------------------------------------------------------------
- *
- * Function: DiagBusMaster
- *
- * Description: Test BusMaster integrity.  Non-zero return indicates an
- *              error.
- *
- *---------------------------------------------------------------------*/
-
-#if defined(DOS)
-int DiagBusMaster(USHORT port)
-#else
-int DiagBusMaster(ULONG port)
-#endif
-{
-   UCHAR testdata;
-
-   for(testdata = (UCHAR) 1; testdata != (UCHAR)0; testdata = testdata << 1) {
-
-      WR_HARPOON(port+hp_xfer_cnt_lo,testdata);
-      WR_HARPOON(port+hp_xfer_cnt_mi,testdata);
-      WR_HARPOON(port+hp_xfer_cnt_hi,testdata);
-      WR_HARPOON(port+hp_host_addr_lo,testdata);
-      WR_HARPOON(port+hp_host_addr_lmi,testdata);
-      WR_HARPOON(port+hp_host_addr_hmi,testdata);
-      WR_HARPOON(port+hp_host_addr_hi,testdata);
-
-      if ((RD_HARPOON(port+hp_xfer_cnt_lo) != testdata)   ||
-          (RD_HARPOON(port+hp_xfer_cnt_mi) != testdata)   ||
-          (RD_HARPOON(port+hp_xfer_cnt_hi) != testdata)   ||
-          (RD_HARPOON(port+hp_host_addr_lo) != testdata)  ||
-          (RD_HARPOON(port+hp_host_addr_lmi) != testdata) ||
-          (RD_HARPOON(port+hp_host_addr_hmi) != testdata) ||
-          (RD_HARPOON(port+hp_host_addr_hi) != testdata))
-
-         return(1);
-      }
-   RD_HARPOON(port+hp_int_status);        /*Clear interrupts. */
-   return(0);
-}
-
-
-
-/*---------------------------------------------------------------------
- *
- * Function: DiagEEPROM
+ * Function: FPT_DiagEEPROM
  *
  * Description: Verfiy checksum and 'Key' and initialize the EEPROM if
  *              necessary.
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void DiagEEPROM(USHORT p_port)
-#else
-void DiagEEPROM(ULONG p_port)
-#endif
-
+static void FPT_DiagEEPROM(ULONG p_port)
 {
    USHORT index,temp,max_wd_cnt;
 
@@ -10884,185 +7154,148 @@
    else
       max_wd_cnt = EEPROM_WD_CNT * 2;
 
-   temp = utilEERead(p_port, FW_SIGNATURE/2);
+   temp = FPT_utilEERead(p_port, FW_SIGNATURE/2);
 
    if (temp == 0x4641) {
 
       for (index = 2; index < max_wd_cnt; index++) {
 
-         temp += utilEERead(p_port, index);
+         temp += FPT_utilEERead(p_port, index);
 
          }
 
-      if (temp == utilEERead(p_port, EEPROM_CHECK_SUM/2)) {
+      if (temp == FPT_utilEERead(p_port, EEPROM_CHECK_SUM/2)) {
 
          return;          /*EEPROM is Okay so return now! */
          }
       }
 
 
-   utilEEWriteOnOff(p_port,(UCHAR)1);
+   FPT_utilEEWriteOnOff(p_port,(UCHAR)1);
 
    for (index = 0; index < max_wd_cnt; index++) {
 
-      utilEEWrite(p_port, 0x0000, index);
+      FPT_utilEEWrite(p_port, 0x0000, index);
       }
 
    temp = 0;
 
-   utilEEWrite(p_port, 0x4641, FW_SIGNATURE/2);
+   FPT_utilEEWrite(p_port, 0x4641, FW_SIGNATURE/2);
    temp += 0x4641;
-   utilEEWrite(p_port, 0x3920, MODEL_NUMB_0/2);
+   FPT_utilEEWrite(p_port, 0x3920, MODEL_NUMB_0/2);
    temp += 0x3920;
-   utilEEWrite(p_port, 0x3033, MODEL_NUMB_2/2);
+   FPT_utilEEWrite(p_port, 0x3033, MODEL_NUMB_2/2);
    temp += 0x3033;
-   utilEEWrite(p_port, 0x2020, MODEL_NUMB_4/2);
+   FPT_utilEEWrite(p_port, 0x2020, MODEL_NUMB_4/2);
    temp += 0x2020;
-   utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG/2);
+   FPT_utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG/2);
    temp += 0x70D3;
-   utilEEWrite(p_port, 0x0010, BIOS_CONFIG/2);
+   FPT_utilEEWrite(p_port, 0x0010, BIOS_CONFIG/2);
    temp += 0x0010;
-   utilEEWrite(p_port, 0x0003, SCAM_CONFIG/2);
+   FPT_utilEEWrite(p_port, 0x0003, SCAM_CONFIG/2);
    temp += 0x0003;
-   utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID/2);
+   FPT_utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID/2);
    temp += 0x0007;
 
-   utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN/2);
+   FPT_utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN/2);
    temp += 0x0000;
-   utilEEWrite(p_port, 0x0000, SEND_START_ENA/2);
+   FPT_utilEEWrite(p_port, 0x0000, SEND_START_ENA/2);
    temp += 0x0000;
-   utilEEWrite(p_port, 0x0000, DEVICE_ENABLE/2);
+   FPT_utilEEWrite(p_port, 0x0000, DEVICE_ENABLE/2);
    temp += 0x0000;
 
-   utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01/2);
+   FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01/2);
    temp += 0x4242;
-   utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23/2);
+   FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23/2);
    temp += 0x4242;
-   utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45/2);
+   FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45/2);
    temp += 0x4242;
-   utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67/2);
+   FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67/2);
    temp += 0x4242;
-   utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89/2);
+   FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89/2);
    temp += 0x4242;
-   utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab/2);
+   FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab/2);
    temp += 0x4242;
-   utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd/2);
+   FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd/2);
    temp += 0x4242;
-   utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef/2);
+   FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef/2);
    temp += 0x4242;
 
 
-   utilEEWrite(p_port, 0x6C46, 64/2);  /*PRODUCT ID */
+   FPT_utilEEWrite(p_port, 0x6C46, 64/2);  /*PRODUCT ID */
    temp += 0x6C46;
-   utilEEWrite(p_port, 0x7361, 66/2);  /* FlashPoint LT   */
+   FPT_utilEEWrite(p_port, 0x7361, 66/2);  /* FlashPoint LT   */
    temp += 0x7361;
-   utilEEWrite(p_port, 0x5068, 68/2);
+   FPT_utilEEWrite(p_port, 0x5068, 68/2);
    temp += 0x5068;
-   utilEEWrite(p_port, 0x696F, 70/2);
+   FPT_utilEEWrite(p_port, 0x696F, 70/2);
    temp += 0x696F;
-   utilEEWrite(p_port, 0x746E, 72/2);
+   FPT_utilEEWrite(p_port, 0x746E, 72/2);
    temp += 0x746E;
-   utilEEWrite(p_port, 0x4C20, 74/2);
+   FPT_utilEEWrite(p_port, 0x4C20, 74/2);
    temp += 0x4C20;
-   utilEEWrite(p_port, 0x2054, 76/2);
+   FPT_utilEEWrite(p_port, 0x2054, 76/2);
    temp += 0x2054;
-   utilEEWrite(p_port, 0x2020, 78/2);
+   FPT_utilEEWrite(p_port, 0x2020, 78/2);
    temp += 0x2020;
 
    index = ((EE_SCAMBASE/2)+(7*16));
-   utilEEWrite(p_port, (0x0700+TYPE_CODE0), index);
+   FPT_utilEEWrite(p_port, (0x0700+TYPE_CODE0), index);
    temp += (0x0700+TYPE_CODE0);
    index++;
-   utilEEWrite(p_port, 0x5542, index);            /*Vendor ID code */
+   FPT_utilEEWrite(p_port, 0x5542, index);            /*Vendor ID code */
    temp += 0x5542;                                /* BUSLOGIC      */
    index++;
-   utilEEWrite(p_port, 0x4C53, index);
+   FPT_utilEEWrite(p_port, 0x4C53, index);
    temp += 0x4C53;
    index++;
-   utilEEWrite(p_port, 0x474F, index);
+   FPT_utilEEWrite(p_port, 0x474F, index);
    temp += 0x474F;
    index++;
-   utilEEWrite(p_port, 0x4349, index);
+   FPT_utilEEWrite(p_port, 0x4349, index);
    temp += 0x4349;
    index++;
-   utilEEWrite(p_port, 0x5442, index);            /*Vendor unique code */
+   FPT_utilEEWrite(p_port, 0x5442, index);            /*Vendor unique code */
    temp += 0x5442;                         /* BT- 930           */
    index++;
-   utilEEWrite(p_port, 0x202D, index);
+   FPT_utilEEWrite(p_port, 0x202D, index);
    temp += 0x202D;
    index++;
-   utilEEWrite(p_port, 0x3339, index);
+   FPT_utilEEWrite(p_port, 0x3339, index);
    temp += 0x3339;
    index++;                                 /*Serial #          */
-   utilEEWrite(p_port, 0x2030, index);             /* 01234567         */
+   FPT_utilEEWrite(p_port, 0x2030, index);             /* 01234567         */
    temp += 0x2030;
    index++;
-   utilEEWrite(p_port, 0x5453, index);
+   FPT_utilEEWrite(p_port, 0x5453, index);
    temp += 0x5453;
    index++;
-   utilEEWrite(p_port, 0x5645, index);
+   FPT_utilEEWrite(p_port, 0x5645, index);
    temp += 0x5645;
    index++;
-   utilEEWrite(p_port, 0x2045, index);
+   FPT_utilEEWrite(p_port, 0x2045, index);
    temp += 0x2045;
    index++;
-   utilEEWrite(p_port, 0x202F, index);
+   FPT_utilEEWrite(p_port, 0x202F, index);
    temp += 0x202F;
    index++;
-   utilEEWrite(p_port, 0x4F4A, index);
+   FPT_utilEEWrite(p_port, 0x4F4A, index);
    temp += 0x4F4A;
    index++;
-   utilEEWrite(p_port, 0x204E, index);
+   FPT_utilEEWrite(p_port, 0x204E, index);
    temp += 0x204E;
    index++;
-   utilEEWrite(p_port, 0x3539, index);
+   FPT_utilEEWrite(p_port, 0x3539, index);
    temp += 0x3539;
 
 
 
-   utilEEWrite(p_port, temp, EEPROM_CHECK_SUM/2);
+   FPT_utilEEWrite(p_port, temp, EEPROM_CHECK_SUM/2);
 
-   utilEEWriteOnOff(p_port,(UCHAR)0);
+   FPT_utilEEWriteOnOff(p_port,(UCHAR)0);
 
 }
 
-#ident "$Id: utility.c 1.23 1997/06/10 16:55:06 mohan Exp $"
-/*----------------------------------------------------------------------
- *
- *
- *   Copyright 1995-1996 by Mylex Corporation.  All Rights Reserved
- *
- *   This file is available under both the GNU General Public License
- *   and a BSD-style copyright; see LICENSE.FlashPoint for details.
- *
- *   $Workfile:   utility.c  $
- *
- *   Description:  Utility functions relating to queueing and EEPROM
- *                 manipulation and any other garbage functions.
- *
- *   $Date: 1997/06/10 16:55:06 $
- *
- *   $Revision: 1.23 $
- *
- *----------------------------------------------------------------------*/
-/*#include <globals.h>*/
-
-#if (FW_TYPE==_UCB_MGR_)
-	/*#include <budi.h>*/
-#endif
-
-/*#include <sccbmgr.h>*/
-/*#include <blx30.h>*/
-/*#include <target.h>*/
-/*#include <scsi2.h>*/
-/*#include <harpoon.h>*/
-
-
-/*
-extern SCCBCARD BL_Card[MAX_CARDS];
-extern SCCBMGR_TAR_INFO sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR];
-extern unsigned int SccbGlobalFlags;
-*/
 
 /*---------------------------------------------------------------------
  *
@@ -11072,7 +7305,7 @@
  *
  *---------------------------------------------------------------------*/
 
-void queueSearchSelect(PSCCBcard pCurrCard, UCHAR p_card)
+static void FPT_queueSearchSelect(PSCCBcard pCurrCard, UCHAR p_card)
 {
    UCHAR scan_ptr, lun;
    PSCCBMgr_tar_info currTar_Info;
@@ -11081,7 +7314,7 @@
    scan_ptr = pCurrCard->scanIndex;
 	do 
 	{
-		currTar_Info = &sccbMgrTbl[p_card][scan_ptr];
+		currTar_Info = &FPT_sccbMgrTbl[p_card][scan_ptr];
 		if((pCurrCard->globalFlags & F_CONLUN_IO) && 
 			((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
 		{
@@ -11094,7 +7327,7 @@
 				
 				for(lun=0; lun < MAX_LUN; lun++)
 				{
-					if(currTar_Info->TarLUNBusy[lun] == FALSE)
+					if(currTar_Info->TarLUNBusy[lun] == 0)
 					{
 
 						pCurrCard->currentSCCB = currTar_Info->TarSelQ_Head;
@@ -11153,7 +7386,7 @@
 		else
 		{
 			if ((currTar_Info->TarSelQ_Cnt != 0) &&
-				(currTar_Info->TarLUNBusy[0] == FALSE))
+				(currTar_Info->TarLUNBusy[0] == 0))
 			{
 
 				pCurrCard->currentSCCB = currTar_Info->TarSelQ_Head;
@@ -11203,7 +7436,7 @@
  *
  *---------------------------------------------------------------------*/
 
-void queueSelectFail(PSCCBcard pCurrCard, UCHAR p_card)
+static void FPT_queueSelectFail(PSCCBcard pCurrCard, UCHAR p_card)
 {
    UCHAR thisTarg;
    PSCCBMgr_tar_info currTar_Info;
@@ -11211,7 +7444,7 @@
    if (pCurrCard->currentSCCB != NULL)
 	  {
 	  thisTarg = (UCHAR)(((PSCCB)(pCurrCard->currentSCCB))->TargID);
-      currTar_Info = &sccbMgrTbl[p_card][thisTarg];
+      currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
 
       pCurrCard->currentSCCB->Sccb_backlink = (PSCCB)NULL;
 
@@ -11242,103 +7475,10 @@
  *
  *---------------------------------------------------------------------*/
 
-void queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_sccb, UCHAR p_card)
+static void FPT_queueCmdComplete(PSCCBcard pCurrCard, PSCCB p_sccb,
+				 UCHAR p_card)
 {
 
-#if (FW_TYPE==_UCB_MGR_)
-
-   u08bits SCSIcmd;
-   CALL_BK_FN callback;
-   PSCCBMgr_tar_info currTar_Info;
-
-   PUCB p_ucb;
-   p_ucb=p_sccb->Sccb_ucb_ptr;
-
-   SCSIcmd = p_sccb->Cdb[0];
-
-
-   if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED))
-   {
-
-      if ((p_ucb->UCB_opcode & OPC_CHK_UNDER_OVER_RUN)                     &&
-         (p_sccb->HostStatus == SCCB_COMPLETE)                             &&
-         (p_sccb->TargetStatus != SSCHECK))
-
-         if ((SCSIcmd == SCSI_READ)             ||
-             (SCSIcmd == SCSI_WRITE)            ||
-             (SCSIcmd == SCSI_READ_EXTENDED)    ||
-             (SCSIcmd == SCSI_WRITE_EXTENDED)   ||
-             (SCSIcmd == SCSI_WRITE_AND_VERIFY) ||
-             (SCSIcmd == SCSI_START_STOP_UNIT)  ||
-             (pCurrCard->globalFlags & F_NO_FILTER)
-            )
-               p_sccb->HostStatus = SCCB_DATA_UNDER_RUN;
-   }
-
-   p_ucb->UCB_status=SCCB_SUCCESS;
-
-   if ((p_ucb->UCB_hbastat=p_sccb->HostStatus) || (p_ucb->UCB_scsistat=p_sccb->TargetStatus))
-   {
-      p_ucb->UCB_status=SCCB_ERROR;
-   }
-
-   if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) ||
-      (p_sccb->OperationCode == RESIDUAL_COMMAND))
-   {
-
-         utilUpdateResidual(p_sccb);
-
-         p_ucb->UCB_datalen=p_sccb->DataLength;
-   }
-
-   pCurrCard->cmdCounter--;
-   if (!pCurrCard->cmdCounter)
-   {
-
-      if (pCurrCard->globalFlags & F_GREEN_PC)
-      {
-         WR_HARPOON(pCurrCard->ioPort+hp_clkctrl_0,(PWR_DWN | CLKCTRL_DEFAULT));
-         WR_HARPOON(pCurrCard->ioPort+hp_sys_ctrl, STOP_CLK);
-      }
-
-      WR_HARPOON(pCurrCard->ioPort+hp_semaphore,
-      (RD_HARPOON(pCurrCard->ioPort+hp_semaphore) & ~SCCB_MGR_ACTIVE));
-   }
-
-	if(pCurrCard->discQCount != 0)
-	{
-      currTar_Info = &sccbMgrTbl[p_card][p_sccb->TargID];
-		if(((pCurrCard->globalFlags & F_CONLUN_IO) &&
-			((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
-		{
-			pCurrCard->discQCount--;
-			pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_sccb->Lun]] = NULL;
-		}
-		else
-		{
-			if(p_sccb->Sccb_tag)
-			{
-				pCurrCard->discQCount--;
-				pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL;
-			}else
-			{
-				pCurrCard->discQCount--;
-				pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]] = NULL;
-			}
-		}
-
-	}
-   callback = (CALL_BK_FN)p_ucb->UCB_callback;
-   callback(p_ucb);
-   pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
-   pCurrCard->currentSCCB = NULL;
-}
-
-
-
-
-#else
-
    UCHAR i, SCSIcmd;
    CALL_BK_FN callback;
    PSCCBMgr_tar_info currTar_Info;
@@ -11383,7 +7523,7 @@
    if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) ||
 	  (p_sccb->OperationCode == RESIDUAL_COMMAND)) {
 
-		 utilUpdateResidual(p_sccb);
+		 FPT_utilUpdateResidual(p_sccb);
 		 }
 
    pCurrCard->cmdCounter--;
@@ -11401,7 +7541,7 @@
 
 	if(pCurrCard->discQCount != 0)
 	{
-      currTar_Info = &sccbMgrTbl[p_card][p_sccb->TargID];
+      currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
 		if(((pCurrCard->globalFlags & F_CONLUN_IO) &&
 			((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
 		{
@@ -11428,7 +7568,6 @@
    pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
    pCurrCard->currentSCCB = NULL;
 }
-#endif /* ( if FW_TYPE==...) */
 
 
 /*---------------------------------------------------------------------
@@ -11438,30 +7577,30 @@
  * Description: Add SCCB to our disconnect array.
  *
  *---------------------------------------------------------------------*/
-void queueDisconnect(PSCCB p_sccb, UCHAR p_card)
+static void FPT_queueDisconnect(PSCCB p_sccb, UCHAR p_card)
 {
    PSCCBMgr_tar_info currTar_Info;
 
-	currTar_Info = &sccbMgrTbl[p_card][p_sccb->TargID];
+	currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
 
-	if(((BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
+	if(((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
 		((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
 	{
-		BL_Card[p_card].discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_sccb->Lun]] = p_sccb;
+		FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->LunDiscQ_Idx[p_sccb->Lun]] = p_sccb;
 	}
 	else
 	{
 		if (p_sccb->Sccb_tag)
 		{
-			BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] = p_sccb;
-			sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] = FALSE;
-			sccbMgrTbl[p_card][p_sccb->TargID].TarTagQ_Cnt++;
+			FPT_BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] = p_sccb;
+			FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] = 0;
+			FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarTagQ_Cnt++;
 		}else
 		{
-			BL_Card[p_card].discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]] = p_sccb;
+			FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]] = p_sccb;
 		}
 	}
-	BL_Card[p_card].currentSCCB = NULL;
+	FPT_BL_Card[p_card].currentSCCB = NULL;
 }
 
 
@@ -11473,29 +7612,29 @@
  *
  *---------------------------------------------------------------------*/
 
-void  queueFlushSccb(UCHAR p_card, UCHAR error_code)
+static void  FPT_queueFlushSccb(UCHAR p_card, UCHAR error_code)
 {
    UCHAR qtag,thisTarg;
    PSCCB currSCCB;
    PSCCBMgr_tar_info currTar_Info;
 
-   currSCCB = BL_Card[p_card].currentSCCB;
+   currSCCB = FPT_BL_Card[p_card].currentSCCB;
 	if(currSCCB != NULL)
 	{
 	   thisTarg = (UCHAR)currSCCB->TargID;
-   	currTar_Info = &sccbMgrTbl[p_card][thisTarg];
+   	currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
 
 	   for (qtag=0; qtag<QUEUE_DEPTH; qtag++) {
 
-		  if (BL_Card[p_card].discQ_Tbl[qtag] && 
-					(BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg))
+		  if (FPT_BL_Card[p_card].discQ_Tbl[qtag] && 
+					(FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg))
 			 {
 
-			 BL_Card[p_card].discQ_Tbl[qtag]->HostStatus = (UCHAR)error_code;
+			 FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus = (UCHAR)error_code;
 			
-			 queueCmdComplete(&BL_Card[p_card],BL_Card[p_card].discQ_Tbl[qtag], p_card);
+			 FPT_queueCmdComplete(&FPT_BL_Card[p_card],FPT_BL_Card[p_card].discQ_Tbl[qtag], p_card);
 
-			 BL_Card[p_card].discQ_Tbl[qtag] = NULL;
+			 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
 			 currTar_Info->TarTagQ_Cnt--;
 
 			 }
@@ -11512,24 +7651,25 @@
  *
  *---------------------------------------------------------------------*/
 
-void  queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg, UCHAR error_code)
+static void  FPT_queueFlushTargSccb(UCHAR p_card, UCHAR thisTarg,
+				    UCHAR error_code)
 {
    UCHAR qtag;
    PSCCBMgr_tar_info currTar_Info;
 
-   currTar_Info = &sccbMgrTbl[p_card][thisTarg];
+   currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
 
    for (qtag=0; qtag<QUEUE_DEPTH; qtag++) {
 
-	  if (BL_Card[p_card].discQ_Tbl[qtag] && 
-				(BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg))
+	  if (FPT_BL_Card[p_card].discQ_Tbl[qtag] && 
+				(FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg))
 		 {
 
-		 BL_Card[p_card].discQ_Tbl[qtag]->HostStatus = (UCHAR)error_code;
+		 FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus = (UCHAR)error_code;
 
-		 queueCmdComplete(&BL_Card[p_card],BL_Card[p_card].discQ_Tbl[qtag], p_card);
+		 FPT_queueCmdComplete(&FPT_BL_Card[p_card],FPT_BL_Card[p_card].discQ_Tbl[qtag], p_card);
 
-		 BL_Card[p_card].discQ_Tbl[qtag] = NULL;
+		 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
 		 currTar_Info->TarTagQ_Cnt--;
 
 		 }
@@ -11541,10 +7681,10 @@
 
 
 
-void queueAddSccb(PSCCB p_SCCB, UCHAR p_card)
+static void FPT_queueAddSccb(PSCCB p_SCCB, UCHAR p_card)
 {
    PSCCBMgr_tar_info currTar_Info;
-   currTar_Info = &sccbMgrTbl[p_card][p_SCCB->TargID];
+   currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
 
    p_SCCB->Sccb_forwardlink = NULL;
 
@@ -11575,12 +7715,12 @@
  *
  *---------------------------------------------------------------------*/
 
-UCHAR queueFindSccb(PSCCB p_SCCB, UCHAR p_card)
+static UCHAR FPT_queueFindSccb(PSCCB p_SCCB, UCHAR p_card)
 {
    PSCCB q_ptr;
    PSCCBMgr_tar_info currTar_Info;
 
-   currTar_Info = &sccbMgrTbl[p_card][p_SCCB->TargID];
+   currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
 
    q_ptr = currTar_Info->TarSelQ_Head;
 
@@ -11609,7 +7749,7 @@
 
 		 currTar_Info->TarSelQ_Cnt--;
 
-		 return(TRUE);
+		 return(1);
 		 }
 
 	  else {
@@ -11618,7 +7758,7 @@
 	  }
 
 
-   return(FALSE);
+   return(0);
 
 }
 
@@ -11636,15 +7776,11 @@
  *
  *---------------------------------------------------------------------*/
 
-void  utilUpdateResidual(PSCCB p_SCCB)
+static void  FPT_utilUpdateResidual(PSCCB p_SCCB)
 {
    ULONG partial_cnt;
    UINT  sg_index;
-#if defined(COMPILER_16_BIT) && !defined(DOS)
-   ULONG far *sg_ptr;
-#else
    ULONG *sg_ptr;
-#endif
 
    if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) {
 
@@ -11657,11 +7793,7 @@
 
 		 sg_index = p_SCCB->Sccb_sgseg;
 
-#if defined(COMPILER_16_BIT) && !defined(DOS)
-		 sg_ptr = (ULONG far *)p_SCCB->DataPointer;
-#else
 		 sg_ptr = (ULONG *)p_SCCB->DataPointer;
-#endif
 
 		 if (p_SCCB->Sccb_SGoffset) {
 
@@ -11694,17 +7826,13 @@
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void Wait1Second(USHORT p_port)
-#else
-void Wait1Second(ULONG p_port)
-#endif
+static void FPT_Wait1Second(ULONG p_port)
 {
    UCHAR i;
 
    for(i=0; i < 4; i++) {
 
-	  Wait(p_port, TO_250ms);
+	  FPT_Wait(p_port, TO_250ms);
 
 	  if ((RD_HARPOON(p_port+hp_scsictrl_0) & SCSI_RST))
 		 break;
@@ -11717,17 +7845,13 @@
 
 /*---------------------------------------------------------------------
  *
- * Function: Wait
+ * Function: FPT_Wait
  *
  * Description: Wait the desired delay.
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void Wait(USHORT p_port, UCHAR p_delay)
-#else
-void Wait(ULONG p_port, UCHAR p_delay)
-#endif
+static void FPT_Wait(ULONG p_port, UCHAR p_delay)
 {
    UCHAR old_timer;
    UCHAR green_flag;
@@ -11739,7 +7863,7 @@
 
    WR_HARPOON(p_port+hp_seltimeout,p_delay);
    WRW_HARPOON((p_port+hp_intstat), TIMEOUT);
-   WRW_HARPOON((p_port+hp_intena), (default_intena & ~TIMEOUT));
+   WRW_HARPOON((p_port+hp_intena), (FPT_default_intena & ~TIMEOUT));
 
 
    WR_HARPOON(p_port+hp_portctrl_0,
@@ -11758,7 +7882,7 @@
 	  (RD_HARPOON(p_port+hp_portctrl_0) & ~START_TO));
 
    WRW_HARPOON((p_port+hp_intstat), TIMEOUT);
-   WRW_HARPOON((p_port+hp_intena), default_intena);
+   WRW_HARPOON((p_port+hp_intena), FPT_default_intena);
 
    WR_HARPOON(p_port+hp_clkctrl_0,green_flag);
 
@@ -11775,11 +7899,7 @@
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void utilEEWriteOnOff(USHORT p_port,UCHAR p_mode)
-#else
-void utilEEWriteOnOff(ULONG p_port,UCHAR p_mode)
-#endif
+static void FPT_utilEEWriteOnOff(ULONG p_port,UCHAR p_mode)
 {
    UCHAR ee_value;
 
@@ -11787,12 +7907,12 @@
 
    if (p_mode)
 
-	  utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR);
+	  FPT_utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR);
 
    else
 
 
-	  utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR);
+	  FPT_utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR);
 
    WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */
    WR_HARPOON(p_port+hp_ee_ctrl, ee_value);       /*Turn off Master Select */
@@ -11808,11 +7928,7 @@
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void utilEEWrite(USHORT p_port, USHORT ee_data, USHORT ee_addr)
-#else
-void utilEEWrite(ULONG p_port, USHORT ee_data, USHORT ee_addr)
-#endif
+static void FPT_utilEEWrite(ULONG p_port, USHORT ee_data, USHORT ee_addr)
 {
 
    UCHAR ee_value;
@@ -11823,7 +7939,7 @@
 
 
 
-   utilEESendCmdAddr(p_port, EE_WRITE, ee_addr);
+   FPT_utilEESendCmdAddr(p_port, EE_WRITE, ee_addr);
 
 
    ee_value |= (SEE_MS + SEE_CS);
@@ -11847,7 +7963,7 @@
    ee_value &= (EXT_ARB_ACK | SCSI_TERM_ENA_H);
    WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS));
 
-   Wait(p_port, TO_10ms);
+   FPT_Wait(p_port, TO_10ms);
 
    WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS | SEE_CS)); /* Set CS to EEPROM */
    WR_HARPOON(p_port+hp_ee_ctrl, (ee_value | SEE_MS));       /* Turn off CS */
@@ -11863,19 +7979,15 @@
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-USHORT utilEERead(USHORT p_port, USHORT ee_addr)
-#else
-USHORT utilEERead(ULONG p_port, USHORT ee_addr)
-#endif
+static USHORT FPT_utilEERead(ULONG p_port, USHORT ee_addr)
 {
    USHORT i, ee_data1, ee_data2;
 
 	i = 0;
-	ee_data1 = utilEEReadOrg(p_port, ee_addr);
+	ee_data1 = FPT_utilEEReadOrg(p_port, ee_addr);
 	do
 	{
-		ee_data2 = utilEEReadOrg(p_port, ee_addr);
+		ee_data2 = FPT_utilEEReadOrg(p_port, ee_addr);
 
 		if(ee_data1 == ee_data2)
 			return(ee_data1);
@@ -11897,11 +8009,7 @@
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-USHORT utilEEReadOrg(USHORT p_port, USHORT ee_addr)
-#else
-USHORT utilEEReadOrg(ULONG p_port, USHORT ee_addr)
-#endif
+static USHORT FPT_utilEEReadOrg(ULONG p_port, USHORT ee_addr)
 {
 
    UCHAR ee_value;
@@ -11911,7 +8019,7 @@
 		   (SEE_MS | SEE_CS));
 
 
-   utilEESendCmdAddr(p_port, EE_READ, ee_addr);
+   FPT_utilEESendCmdAddr(p_port, EE_READ, ee_addr);
 
 
    ee_value |= (SEE_MS + SEE_CS);
@@ -11949,11 +8057,7 @@
  *
  *---------------------------------------------------------------------*/
 
-#if defined(DOS)
-void utilEESendCmdAddr(USHORT p_port, UCHAR ee_cmd, USHORT ee_addr)
-#else
-void utilEESendCmdAddr(ULONG p_port, UCHAR ee_cmd, USHORT ee_addr)
-#endif
+static void FPT_utilEESendCmdAddr(ULONG p_port, UCHAR ee_cmd, USHORT ee_addr)
 {
    UCHAR ee_value;
    UCHAR narrow_flg;
@@ -12016,7 +8120,7 @@
 	  }
 }
 
-USHORT CalcCrc16(UCHAR buffer[])
+static USHORT FPT_CalcCrc16(UCHAR buffer[])
 {
    USHORT crc=0;
 	int i,j;
@@ -12036,7 +8140,7 @@
 	return(crc);
 }
 
-UCHAR CalcLrc(UCHAR buffer[])
+static UCHAR FPT_CalcLrc(UCHAR buffer[])
 {
 	int i;
 	UCHAR lrc;
@@ -12109,33 +8213,6 @@
 #define FlashPoint_HandleInterrupt	    FlashPoint__HandleInterrupt
 
 
-/*
-  FlashPoint_InquireTargetInfo returns the Synchronous Period, Synchronous
-  Offset, and Wide Transfers Active information for TargetID on CardHandle.
-*/
-
-void FlashPoint_InquireTargetInfo(FlashPoint_CardHandle_T CardHandle,
-				  int TargetID,
-				  unsigned char *SynchronousPeriod,
-				  unsigned char *SynchronousOffset,
-				  unsigned char *WideTransfersActive)
-{
-  SCCBMGR_TAR_INFO *TargetInfo =
-    &sccbMgrTbl[((SCCBCARD *)CardHandle)->cardIndex][TargetID];
-  if ((TargetInfo->TarSyncCtrl & SYNC_OFFSET) > 0)
-    {
-      *SynchronousPeriod = 5 * ((TargetInfo->TarSyncCtrl >> 5) + 1);
-      *SynchronousOffset = TargetInfo->TarSyncCtrl & SYNC_OFFSET;
-    }
-  else
-    {
-      *SynchronousPeriod = 0;
-      *SynchronousOffset = 0;
-    }
-  *WideTransfersActive = (TargetInfo->TarSyncCtrl & NARROW_SCSI ? 0 : 1);
-}
-
-
 #else  /* CONFIG_SCSI_OMIT_FLASHPOINT */
 
 
@@ -12151,9 +8228,6 @@
 extern boolean FlashPoint_InterruptPending(FlashPoint_CardHandle_T);
 extern int FlashPoint_HandleInterrupt(FlashPoint_CardHandle_T);
 extern void FlashPoint_ReleaseHostAdapter(FlashPoint_CardHandle_T);
-extern void FlashPoint_InquireTargetInfo(FlashPoint_CardHandle_T,
-					 int, unsigned char *,
-					 unsigned char *, unsigned char *);
 
 
 #endif /* CONFIG_SCSI_OMIT_FLASHPOINT */
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 1811cb2..96df148 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -137,6 +137,24 @@
 
 	  If unsure, say N.
 
+config CHR_DEV_SCH
+	tristate "SCSI media changer support"
+	depends on SCSI
+	---help---
+	  This is a driver for SCSI media changers.  Most common devices are
+	  tape libraries and MOD/CDROM jukeboxes.  *Real* jukeboxes, you
+	  don't need this for those tiny 6-slot cdrom changers.  Media
+	  changers are listed as "Type: Medium Changer" in /proc/scsi/scsi.
+	  If you have such hardware and want to use it with linux, say Y
+	  here.  Check <file:Documentation/scsi-changer.txt> for details.
+	
+	  If you want to compile this 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> and
+	  <file:Documentation/scsi.txt>. The module will be called ch.o.
+	  If unsure, say N.
+	
+
 comment "Some SCSI devices (e.g. CD jukebox) support multiple LUNs"
 	depends on SCSI
 
@@ -1192,28 +1210,6 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called pas16.
 
-config SCSI_PCI2000
-	tristate "PCI2000 support"
-	depends on PCI && SCSI && BROKEN
-	help
-	  This is support for the PCI2000I EIDE interface card which acts as a
-	  SCSI host adapter.  Please read the SCSI-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called pci2000.
-
-config SCSI_PCI2220I
-	tristate "PCI2220i support"
-	depends on PCI && SCSI && BROKEN
-	help
-	  This is support for the PCI2220i EIDE interface card which acts as a
-	  SCSI host adapter.  Please read the SCSI-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called pci2220i.
-
 config SCSI_PSI240I
 	tristate "PSI240i support"
 	depends on ISA && SCSI
@@ -1752,7 +1748,7 @@
 
 config SUN3_SCSI
 	tristate "Sun3 NCR5380 SCSI"
-	depends on SUN3 && SCSI
+	depends on SUN3 && SCSI && BROKEN
 	help
 	  This option will enable support for the OBIO (onboard io) NCR5380
 	  SCSI controller found in the Sun 3/50 and 3/60, as well as for
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 9cb9fe7..3746fb9 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -50,8 +50,6 @@
 obj-$(CONFIG_BVME6000_SCSI)	+= bvme6000.o	53c7xx.o
 obj-$(CONFIG_SCSI_SIM710)	+= 53c700.o	sim710.o
 obj-$(CONFIG_SCSI_ADVANSYS)	+= advansys.o
-obj-$(CONFIG_SCSI_PCI2000)	+= pci2000.o
-obj-$(CONFIG_SCSI_PCI2220I)	+= pci2220i.o
 obj-$(CONFIG_SCSI_PSI240I)	+= psi240i.o
 obj-$(CONFIG_SCSI_BUSLOGIC)	+= BusLogic.o
 obj-$(CONFIG_SCSI_DPT_I2O)	+= dpt_i2o.o
@@ -142,6 +140,7 @@
 obj-$(CONFIG_BLK_DEV_SD)	+= sd_mod.o
 obj-$(CONFIG_BLK_DEV_SR)	+= sr_mod.o
 obj-$(CONFIG_CHR_DEV_SG)	+= sg.o
+obj-$(CONFIG_CHR_DEV_SCH)	+= ch.o
 
 scsi_mod-y			+= scsi.o hosts.o scsi_ioctl.o constants.o \
 				   scsicam.o scsi_error.o scsi_lib.o \
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c
index 770fa84..f8ec6fe 100644
--- a/drivers/scsi/NCR5380.c
+++ b/drivers/scsi/NCR5380.c
@@ -2825,39 +2825,17 @@
  * Locks: host lock taken by caller
  */
 
-static int NCR5380_bus_reset(Scsi_Cmnd * cmd) {
+static int NCR5380_bus_reset(Scsi_Cmnd * cmd)
+{
+	struct Scsi_Host *instance = cmd->device->host;
+
 	NCR5380_local_declare();
-	NCR5380_setup(cmd->device->host);
+	NCR5380_setup(instance);
+	NCR5380_print_status(instance);
 
-	NCR5380_print_status(cmd->device->host);
-	do_reset(cmd->device->host);
+	spin_lock_irq(instance->host_lock);
+	do_reset(instance);
+	spin_unlock_irq(instance->host_lock);
+
 	return SUCCESS;
 }
-
-/* 
- * Function : int NCR5380_device_reset (Scsi_Cmnd *cmd)
- * 
- * Purpose : reset a SCSI device
- *
- * Returns : FAILED
- *
- * Locks: io_request_lock held by caller
- */
-
-static int NCR5380_device_reset(Scsi_Cmnd * cmd) {
-	return FAILED;
-}
-
-/* 
- * Function : int NCR5380_host_reset (Scsi_Cmnd *cmd)
- * 
- * Purpose : reset a SCSI device
- *
- * Returns : FAILED
- *
- * Locks: io_request_lock held by caller
- */
-
-static int NCR5380_host_reset(Scsi_Cmnd * cmd) {
-	return FAILED;
-}
diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h
index b5103f9..c3462e3 100644
--- a/drivers/scsi/NCR5380.h
+++ b/drivers/scsi/NCR5380.h
@@ -306,8 +306,6 @@
 #endif
 static int NCR5380_abort(Scsi_Cmnd * cmd);
 static int NCR5380_bus_reset(Scsi_Cmnd * cmd);
-static int NCR5380_host_reset(Scsi_Cmnd * cmd);
-static int NCR5380_device_reset(Scsi_Cmnd * cmd);
 static int NCR5380_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *));
 static int NCR5380_proc_info(struct Scsi_Host *instance, char *buffer, char **start,
 off_t offset, int length, int inout);
diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c
index 74b9356..6ceabbd 100644
--- a/drivers/scsi/NCR53C9x.c
+++ b/drivers/scsi/NCR53C9x.c
@@ -94,7 +94,7 @@
 };
 
 /* The master ring of all esp hosts we are managing in this driver. */
-struct NCR_ESP *espchain;
+static struct NCR_ESP *espchain;
 int nesps = 0, esps_in_use = 0, esps_running = 0;
 
 irqreturn_t esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
@@ -1467,14 +1467,12 @@
 {
 	struct NCR_ESP *esp = (struct NCR_ESP *) SCptr->device->host->hostdata;
 
+	spin_lock_irq(esp->ehost->host_lock);
 	(void) esp_do_resetbus(esp, esp->eregs);
-
 	spin_unlock_irq(esp->ehost->host_lock);
 
 	wait_event(esp->reset_queue, (esp->resetting_bus == 0));
 
-	spin_lock_irq(esp->ehost->host_lock);
-
 	return SUCCESS;
 }
 
diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c
index c685d54..b2002ba 100644
--- a/drivers/scsi/NCR53c406a.c
+++ b/drivers/scsi/NCR53c406a.c
@@ -722,15 +722,12 @@
 	return 0;
 }
 
-static int NCR53c406a_abort(Scsi_Cmnd * SCpnt)
-{
-	DEB(printk("NCR53c406a_abort called\n"));
-	return FAILED;		/* Don't know how to abort */
-}
-
 static int NCR53c406a_host_reset(Scsi_Cmnd * SCpnt)
 {
 	DEB(printk("NCR53c406a_reset called\n"));
+
+	spin_lock_irq(SCpnt->device->host->host_lock);
+
 	outb(C4_IMG, CONFIG4);	/* Select reg set 0 */
 	outb(CHIP_RESET, CMD_REG);
 	outb(SCSI_NOP, CMD_REG);	/* required after reset */
@@ -738,19 +735,12 @@
 	chip_init();
 
 	rtrc(2);
+
+	spin_unlock_irq(SCpnt->device->host->host_lock);
+
 	return SUCCESS;
 }
 
-static int NCR53c406a_device_reset(Scsi_Cmnd * SCpnt)
-{
-	return FAILED;
-}
-
-static int NCR53c406a_bus_reset(Scsi_Cmnd * SCpnt)
-{
-	return FAILED;
-}
-
 static int NCR53c406a_biosparm(struct scsi_device *disk,
                                struct block_device *dev,
 			       sector_t capacity, int *info_array)
@@ -1075,9 +1065,6 @@
      .release            	= NCR53c406a_release,
      .info              	= NCR53c406a_info		/* info */,             
      .queuecommand      	= NCR53c406a_queue	/* queuecommand */,     
-     .eh_abort_handler  	= NCR53c406a_abort	/* abort */,            
-     .eh_bus_reset_handler      = NCR53c406a_bus_reset	/* reset */,            
-     .eh_device_reset_handler   = NCR53c406a_device_reset	/* reset */,            
      .eh_host_reset_handler     = NCR53c406a_host_reset	/* reset */,            
      .bios_param        	= NCR53c406a_biosparm	/* biosparm */,         
      .can_queue         	= 1			/* can_queue */,        
diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c
index 9928a2f..f7a1751 100644
--- a/drivers/scsi/a2091.c
+++ b/drivers/scsi/a2091.c
@@ -221,7 +221,14 @@
 static int a2091_bus_reset(Scsi_Cmnd *cmd)
 {
 	/* FIXME perform bus-specific reset */
+
+	/* FIXME 2: kill this function, and let midlayer fall back
+	   to the same action, calling wd33c93_host_reset() */
+
+	spin_lock_irq(cmd->device->host->host_lock);
 	wd33c93_host_reset(cmd);
+	spin_unlock_irq(cmd->device->host->host_lock);
+
 	return SUCCESS;
 }
 
diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c
index f8a89ec..306caf5 100644
--- a/drivers/scsi/a3000.c
+++ b/drivers/scsi/a3000.c
@@ -208,7 +208,14 @@
 static int a3000_bus_reset(Scsi_Cmnd *cmd)
 {
 	/* FIXME perform bus-specific reset */
+	
+	/* FIXME 2: kill this entire function, which should
+	   cause mid-layer to call wd33c93_host_reset anyway? */
+
+	spin_lock_irq(cmd->device->host->host_lock);
 	wd33c93_host_reset(cmd);
+	spin_unlock_irq(cmd->device->host->host_lock);
+
 	return SUCCESS;
 }
 
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index f3fc353..f02c996 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -53,10 +53,6 @@
 #define	INQD_PDT_DMASK	0x1F	/* Peripheral Device Type Mask */
 #define	INQD_PDT_QMASK	0xE0	/* Peripheral Device Qualifer Mask */
 
-#define MAX_FIB_DATA (sizeof(struct hw_fib) - sizeof(FIB_HEADER))
-
-#define MAX_DRIVER_SG_SEGMENT_COUNT 17
-
 /*
  *	Sense codes
  */
@@ -158,6 +154,13 @@
 module_param(commit, int, 0);
 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");
 
+int numacb = -1;
+module_param(numacb, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(numacb, "Request a limit to the number of adapter control blocks (FIB) allocated. Valid\nvalues are 512 and down. Default is to use suggestion from Firmware.");
+
+int acbsize = -1;
+module_param(acbsize, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. Valid values are 512,\n2048, 4096 and 8192. Default is to use suggestion from Firmware.");
 /**
  *	aac_get_config_status	-	check the adapter configuration
  *	@common: adapter to query
@@ -462,7 +465,7 @@
 			    1, 1,
 			    NULL, NULL);
 	if (status < 0) {
-		printk(KERN_WARNING "aacraid: probe_containers query failed.\n");
+		printk(KERN_WARNING "aacraid: probe_container query failed.\n");
 		goto error;
 	}
 
@@ -562,10 +565,10 @@
 	inqstrcpy ("V1.0", str->prl);
 }
 
-void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code,
-		    u8 a_sense_code, u8 incorrect_length,
-		    u8 bit_pointer, u16 field_pointer,
-		    u32 residue)
+static void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code,
+		      u8 a_sense_code, u8 incorrect_length,
+		      u8 bit_pointer, u16 field_pointer,
+		      u32 residue)
 {
 	sense_buf[0] = 0xF0;	/* Sense data valid, err code 70h (current error) */
 	sense_buf[1] = 0;	/* Segment number, always zero */
@@ -605,35 +608,63 @@
 int aac_get_adapter_info(struct aac_dev* dev)
 {
 	struct fib* fibptr;
-	struct aac_adapter_info* info;
 	int rcode;
 	u32 tmp;
+	struct aac_adapter_info * info;
+
 	if (!(fibptr = fib_alloc(dev)))
 		return -ENOMEM;
 
 	fib_init(fibptr);
-	info = (struct aac_adapter_info*) fib_data(fibptr);
-
-	memset(info,0,sizeof(struct aac_adapter_info));
+	info = (struct aac_adapter_info *) fib_data(fibptr);
+	memset(info,0,sizeof(*info));
 
 	rcode = fib_send(RequestAdapterInfo,
-			fibptr, 
-			sizeof(struct aac_adapter_info),
-			FsaNormal, 
-			1, 1, 
-			NULL, 
-			NULL);
+			 fibptr, 
+			 sizeof(*info),
+			 FsaNormal, 
+			 1, 1, 
+			 NULL, 
+			 NULL);
 
-	memcpy(&dev->adapter_info, info, sizeof(struct aac_adapter_info));
+	if (rcode < 0) {
+		fib_complete(fibptr);
+		fib_free(fibptr);
+		return rcode;
+	}
+	memcpy(&dev->adapter_info, info, sizeof(*info));
+
+	if (dev->adapter_info.options & AAC_OPT_SUPPLEMENT_ADAPTER_INFO) {
+		struct aac_supplement_adapter_info * info;
+
+		fib_init(fibptr);
+
+		info = (struct aac_supplement_adapter_info *) fib_data(fibptr);
+
+		memset(info,0,sizeof(*info));
+
+		rcode = fib_send(RequestSupplementAdapterInfo,
+				 fibptr,
+				 sizeof(*info),
+				 FsaNormal,
+				 1, 1,
+				 NULL,
+				 NULL);
+
+		if (rcode >= 0)
+			memcpy(&dev->supplement_adapter_info, info, sizeof(*info));
+	}
 
 	tmp = le32_to_cpu(dev->adapter_info.kernelrev);
-	printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d]\n", 
+	printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d] %.*s\n", 
 			dev->name, 
 			dev->id,
 			tmp>>24,
 			(tmp>>16)&0xff,
 			tmp&0xff,
-			le32_to_cpu(dev->adapter_info.kernelbuild));
+			le32_to_cpu(dev->adapter_info.kernelbuild),
+			(int)sizeof(dev->supplement_adapter_info.BuildDate),
+			dev->supplement_adapter_info.BuildDate);
 	tmp = le32_to_cpu(dev->adapter_info.monitorrev);
 	printk(KERN_INFO "%s%d: monitor %d.%d-%d[%d]\n", 
 			dev->name, dev->id,
@@ -707,6 +738,38 @@
 			rcode = -ENOMEM;
 		}
 	}
+	/* 
+	 * 57 scatter gather elements 
+	 */
+	dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size -
+		sizeof(struct aac_fibhdr) -
+		sizeof(struct aac_write) + sizeof(struct sgmap)) /
+			sizeof(struct sgmap);
+	if (dev->dac_support) {
+		/* 
+		 * 38 scatter gather elements 
+		 */
+		dev->scsi_host_ptr->sg_tablesize =
+			(dev->max_fib_size -
+			sizeof(struct aac_fibhdr) -
+			sizeof(struct aac_write64) +
+			sizeof(struct sgmap64)) /
+				sizeof(struct sgmap64);
+	}
+	dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
+	if(!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) {
+		/*
+		 * Worst case size that could cause sg overflow when
+		 * we break up SG elements that are larger than 64KB.
+		 * Would be nice if we could tell the SCSI layer what
+		 * the maximum SG element size can be. Worst case is
+		 * (sg_tablesize-1) 4KB elements with one 64KB
+		 * element.
+		 *	32bit -> 468 or 238KB	64bit -> 424 or 212KB
+		 */
+		dev->scsi_host_ptr->max_sectors =
+		  (dev->scsi_host_ptr->sg_tablesize * 8) + 112;
+	}
 
 	fib_complete(fibptr);
 	fib_free(fibptr);
@@ -747,8 +810,10 @@
 	if (le32_to_cpu(readreply->status) == ST_OK)
 		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
 	else {
-		printk(KERN_WARNING "read_callback: read failed, status = %d\n",
-				le32_to_cpu(readreply->status));
+#ifdef AAC_DETAILED_STATUS_INFO
+		printk(KERN_WARNING "read_callback: io failed, status = %d\n",
+		  le32_to_cpu(readreply->status));
+#endif
 		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
 		set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
 				    HARDWARE_ERROR,
@@ -813,7 +878,7 @@
 	aac_io_done(scsicmd);
 }
 
-int aac_read(struct scsi_cmnd * scsicmd, int cid)
+static int aac_read(struct scsi_cmnd * scsicmd, int cid)
 {
 	u32 lba;
 	u32 count;
@@ -842,7 +907,8 @@
 		lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
 		count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
 	}
-	dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies));
+	dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %u, t = %ld.\n",
+	  smp_processor_id(), (unsigned long long)lba, jiffies));
 	/*
 	 *	Alocate and initialize a Fib
 	 */
@@ -852,7 +918,7 @@
 
 	fib_init(cmd_fibcontext);
 
-	if(dev->dac_support == 1) {
+	if (dev->dac_support == 1) {
 		struct aac_read64 *readcmd;
 		readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext);
 		readcmd->command = cpu_to_le32(VM_CtHostRead64);
@@ -886,14 +952,11 @@
 		readcmd->block = cpu_to_le32(lba);
 		readcmd->count = cpu_to_le32(count * 512);
 
-		if (count * 512 > (64 * 1024))
-			BUG();
-
 		aac_build_sg(scsicmd, &readcmd->sg);
 		fibsize = sizeof(struct aac_read) + 
 			((le32_to_cpu(readcmd->sg.count) - 1) * 
 			 sizeof (struct sgentry));
-		BUG_ON (fibsize > (sizeof(struct hw_fib) - 
+		BUG_ON (fibsize > (dev->max_fib_size -
 					sizeof(struct aac_fibhdr)));
 		/*
 		 *	Now send the Fib to the adapter
@@ -976,7 +1039,7 @@
 		fibsize = sizeof(struct aac_write64) + 
 			((le32_to_cpu(writecmd->sg.count) - 1) * 
 			 sizeof (struct sgentry64));
-		BUG_ON (fibsize > (sizeof(struct hw_fib) - 
+		BUG_ON (fibsize > (dev->max_fib_size -
 					sizeof(struct aac_fibhdr)));
 		/*
 		 *	Now send the Fib to the adapter
@@ -998,15 +1061,11 @@
 		writecmd->sg.count = cpu_to_le32(1);
 		/* ->stable is not used - it did mean which type of write */
 
-		if (count * 512 > (64 * 1024)) {
-			BUG();
-		}
-
 		aac_build_sg(scsicmd, &writecmd->sg);
 		fibsize = sizeof(struct aac_write) + 
 			((le32_to_cpu(writecmd->sg.count) - 1) * 
 			 sizeof (struct sgentry));
-		BUG_ON (fibsize > (sizeof(struct hw_fib) - 
+		BUG_ON (fibsize > (dev->max_fib_size -
 					sizeof(struct aac_fibhdr)));
 		/*
 		 *	Now send the Fib to the adapter
@@ -1025,7 +1084,6 @@
 	 */
 	if (status == -EINPROGRESS)
 	{
-		dprintk("write queued.\n");
 		return 0;
 	}
 
@@ -1111,7 +1169,7 @@
 		return SCSI_MLQUEUE_DEVICE_BUSY;
 
 	/*
-	 *	Alocate and initialize a Fib
+	 *	Allocate and initialize a Fib
 	 */
 	if (!(cmd_fibcontext = 
 	    fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata))) 
@@ -1403,7 +1461,7 @@
 			/*
 			 *	Unhandled commands
 			 */
-			printk(KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", scsicmd->cmnd[0]);
+			dprintk((KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", scsicmd->cmnd[0]));
 			scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
 			set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
 				ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND,
@@ -1818,7 +1876,7 @@
 		fibsize = sizeof (struct aac_srb) - sizeof (struct sgentry) +
 			((le32_to_cpu(srbcmd->sg.count) & 0xff) * 
 			 sizeof (struct sgentry64));
-		BUG_ON (fibsize > (sizeof(struct hw_fib) - 
+		BUG_ON (fibsize > (dev->max_fib_size -
 					sizeof(struct aac_fibhdr)));
 
 		/*
@@ -1840,7 +1898,7 @@
 		fibsize = sizeof (struct aac_srb) + 
 			(((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) * 
 			 sizeof (struct sgentry));
-		BUG_ON (fibsize > (sizeof(struct hw_fib) - 
+		BUG_ON (fibsize > (dev->max_fib_size -
 					sizeof(struct aac_fibhdr)));
 
 		/*
@@ -1893,7 +1951,9 @@
 		}
 		/* hba wants the size to be exact */
 		if(byte_count > scsicmd->request_bufflen){
-			psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen);
+			u32 temp = le32_to_cpu(psg->sg[i-1].count) - 
+				(byte_count - scsicmd->request_bufflen);
+			psg->sg[i-1].count = cpu_to_le32(temp);
 			byte_count = scsicmd->request_bufflen;
 		}
 		/* Check for command underflow */
@@ -1922,7 +1982,7 @@
 {
 	struct aac_dev *dev;
 	unsigned long byte_count = 0;
-	u64 le_addr;
+	u64 addr;
 
 	dev = (struct aac_dev *)scsicmd->device->host->hostdata;
 	// Get rid of old data
@@ -1943,16 +2003,18 @@
 		byte_count = 0;
 
 		for (i = 0; i < sg_count; i++) {
-			le_addr = cpu_to_le64(sg_dma_address(sg));
-			psg->sg[i].addr[1] = (u32)(le_addr>>32);
-			psg->sg[i].addr[0] = (u32)(le_addr & 0xffffffff);
+			addr = sg_dma_address(sg);
+			psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
+			psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
 			psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));
 			byte_count += sg_dma_len(sg);
 			sg++;
 		}
 		/* hba wants the size to be exact */
 		if(byte_count > scsicmd->request_bufflen){
-			psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen);
+			u32 temp = le32_to_cpu(psg->sg[i-1].count) - 
+				(byte_count - scsicmd->request_bufflen);
+			psg->sg[i-1].count = cpu_to_le32(temp);
 			byte_count = scsicmd->request_bufflen;
 		}
 		/* Check for command underflow */
@@ -1962,15 +2024,14 @@
 		}
 	}
 	else if(scsicmd->request_bufflen) {
-		dma_addr_t addr; 
+		u64 addr; 
 		addr = pci_map_single(dev->pdev,
 				scsicmd->request_buffer,
 				scsicmd->request_bufflen,
 				scsicmd->sc_data_direction);
 		psg->count = cpu_to_le32(1);
-		le_addr = cpu_to_le64(addr);
-		psg->sg[0].addr[1] = (u32)(le_addr>>32);
-		psg->sg[0].addr[0] = (u32)(le_addr & 0xffffffff);
+		psg->sg[0].addr[0] = cpu_to_le32(addr & 0xffffffff);
+		psg->sg[0].addr[1] = cpu_to_le32(addr >> 32);
 		psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);  
 		scsicmd->SCp.dma_handle = addr;
 		byte_count = scsicmd->request_bufflen;
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 700d903..4248441 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -8,12 +8,18 @@
 
 #define MAXIMUM_NUM_CONTAINERS	32
 
-#define AAC_NUM_FIB		(256 + 64)
-#define AAC_NUM_IO_FIB		100
+#define AAC_NUM_MGT_FIB         8
+#define AAC_NUM_IO_FIB		(512 - AAC_NUM_MGT_FIB)
+#define AAC_NUM_FIB		(AAC_NUM_IO_FIB + AAC_NUM_MGT_FIB)
 
 #define AAC_MAX_LUN		(8)
 
 #define AAC_MAX_HOSTPHYSMEMPAGES (0xfffff)
+/*
+ *  max_sectors is an unsigned short, otherwise limit is 0x100000000 / 512
+ * Linux has starvation problems if we permit larger than 4MB I/O ...
+ */
+#define AAC_MAX_32BIT_SGBCOUNT	((unsigned short)8192)
 
 /*
  * These macros convert from physical channels to virtual channels
@@ -89,11 +95,21 @@
  *	on 64 bit systems not all cards support the 64 bit version
  */
 struct sgentry {
+	__le32	addr;	/* 32-bit address. */
+	__le32	count;	/* Length. */
+};
+
+struct user_sgentry {
 	u32	addr;	/* 32-bit address. */
 	u32	count;	/* Length. */
 };
 
 struct sgentry64 {
+	__le32	addr[2];	/* 64-bit addr. 2 pieces for data alignment */
+	__le32	count;	/* Length. */
+};
+
+struct user_sgentry64 {
 	u32	addr[2];	/* 64-bit addr. 2 pieces for data alignment */
 	u32	count;	/* Length. */
 };
@@ -106,15 +122,25 @@
  */
 
 struct sgmap {
-	u32		count;
+	__le32		count;
 	struct sgentry	sg[1]; 
 };
 
-struct sgmap64 {
+struct user_sgmap {
 	u32		count;
+	struct user_sgentry	sg[1]; 
+};
+
+struct sgmap64 {
+	__le32		count;
 	struct sgentry64 sg[1];
 };
 
+struct user_sgmap64 {
+	u32		count;
+	struct user_sgentry64 sg[1];
+};
+
 struct creation_info
 {
 	u8 		buildnum;		/* e.g., 588 */
@@ -123,14 +149,14 @@
 						 * 	 2 = API
 						 */
 	u8	 	year;		 	/* e.g., 1997 = 97 */
-	u32		date;			/*
+	__le32		date;			/*
 						 * unsigned 	Month		:4;	// 1 - 12
 						 * unsigned 	Day		:6;	// 1 - 32
 						 * unsigned 	Hour		:6;	// 0 - 23
 						 * unsigned 	Minute		:6;	// 0 - 60
 						 * unsigned 	Second		:6;	// 0 - 60
 						 */
-	u32		serial[2];			/* e.g., 0x1DEADB0BFAFAF001 */
+	__le32		serial[2];			/* e.g., 0x1DEADB0BFAFAF001 */
 };
 
 
@@ -175,8 +201,8 @@
  */
 
 struct aac_entry {
-	u32 size;          /* Size in bytes of Fib which this QE points to */
-	u32 addr; /* Receiver address of the FIB */
+	__le32 size; /* Size in bytes of Fib which this QE points to */
+	__le32 addr; /* Receiver address of the FIB */
 };
 
 /*
@@ -185,9 +211,10 @@
  */
  
 struct aac_qhdr {
-	u64 header_addr;		/* Address to hand the adapter to access to this queue head */
-	u32 *producer;			/* The producer index for this queue (host address) */
-	u32 *consumer;			/* The consumer index for this queue (host address) */
+	__le64 header_addr;/* Address to hand the adapter to access 
+			      to this queue head */
+	__le32 *producer; /* The producer index for this queue (host address) */
+	__le32 *consumer; /* The consumer index for this queue (host address) */
 };
 
 /*
@@ -261,29 +288,30 @@
  */
 
 struct aac_fibhdr {
-	u32 XferState;			// Current transfer state for this CCB
-	u16 Command;			// Routing information for the destination
-	u8 StructType;			// Type FIB
-	u8 Flags;			// Flags for FIB
-	u16 Size;			// Size of this FIB in bytes
-	u16 SenderSize;			// Size of the FIB in the sender (for response sizing)
-	u32 SenderFibAddress;		// Host defined data in the FIB
-	u32 ReceiverFibAddress;		// Logical address of this FIB for the adapter
-	u32 SenderData;			// Place holder for the sender to store data
+	__le32 XferState;	/* Current transfer state for this CCB */
+	__le16 Command;		/* Routing information for the destination */
+	u8 StructType;		/* Type FIB */
+	u8 Flags;		/* Flags for FIB */
+	__le16 Size;		/* Size of this FIB in bytes */
+	__le16 SenderSize;	/* Size of the FIB in the sender 
+				   (for response sizing) */
+	__le32 SenderFibAddress;  /* Host defined data in the FIB */
+	__le32 ReceiverFibAddress;/* Logical address of this FIB for 
+				     the adapter */
+	u32 SenderData;		/* Place holder for the sender to store data */
 	union {
 		struct {
-		    u32 _ReceiverTimeStart; 	// Timestamp for receipt of fib
-		    u32 _ReceiverTimeDone;	// Timestamp for completion of fib
+		    __le32 _ReceiverTimeStart; 	/* Timestamp for 
+						   receipt of fib */
+		    __le32 _ReceiverTimeDone;	/* Timestamp for 
+						   completion of fib */
 		} _s;
 	} _u;
 };
 
-#define FIB_DATA_SIZE_IN_BYTES (512 - sizeof(struct aac_fibhdr))
-
-
 struct hw_fib {
 	struct aac_fibhdr header;
-	u8 data[FIB_DATA_SIZE_IN_BYTES];		// Command specific data
+	u8 data[512-sizeof(struct aac_fibhdr)];	// Command specific data
 };
 
 /*
@@ -345,11 +373,12 @@
 #define		RequestAdapterInfo		703
 #define		IsAdapterPaused			704
 #define		SendHostTime			705
-#define		LastMiscCommand			706
+#define		RequestSupplementAdapterInfo	706
+#define		LastMiscCommand			707
 
-//
-// Commands that will target the failover level on the FSA adapter
-//
+/*
+ * Commands that will target the failover level on the FSA adapter
+ */
 
 enum fib_xfer_state {
 	HostOwned 			= (1<<0),
@@ -382,22 +411,32 @@
  */
 
 #define ADAPTER_INIT_STRUCT_REVISION		3
+#define ADAPTER_INIT_STRUCT_REVISION_4		4 // rocket science
 
 struct aac_init
 {
-	u32	InitStructRevision;
-	u32	MiniPortRevision;
-	u32	fsrev;
-	u32	CommHeaderAddress;
-	u32	FastIoCommAreaAddress;
-	u32	AdapterFibsPhysicalAddress;
-	u32	AdapterFibsVirtualAddress;
-	u32	AdapterFibsSize;
-	u32	AdapterFibAlign;
-	u32	printfbuf;
-	u32	printfbufsiz;
-	u32	HostPhysMemPages;		// number of 4k pages of host physical memory
-	u32	HostElapsedSeconds;		// number of seconds since 1970.
+	__le32	InitStructRevision;
+	__le32	MiniPortRevision;
+	__le32	fsrev;
+	__le32	CommHeaderAddress;
+	__le32	FastIoCommAreaAddress;
+	__le32	AdapterFibsPhysicalAddress;
+	__le32	AdapterFibsVirtualAddress;
+	__le32	AdapterFibsSize;
+	__le32	AdapterFibAlign;
+	__le32	printfbuf;
+	__le32	printfbufsiz;
+	__le32	HostPhysMemPages;   /* number of 4k pages of host 
+				       physical memory */
+	__le32	HostElapsedSeconds; /* number of seconds since 1970. */
+	/*
+	 * ADAPTER_INIT_STRUCT_REVISION_4 begins here
+	 */
+	__le32	InitFlags;	/* flags for supported features */
+#define INITFLAGS_NEW_COMM_SUPPORTED	0x00000001
+	__le32	MaxIoCommands;	/* max outstanding commands */
+	__le32	MaxIoSize;	/* largest I/O command */
+	__le32	MaxFibSize;	/* largest FIB to adapter */
 };
 
 enum aac_log_level {
@@ -421,7 +460,7 @@
 {
 	void (*adapter_interrupt)(struct aac_dev *dev);
 	void (*adapter_notify)(struct aac_dev *dev, u32 event);
-	int  (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 *status);
+	int  (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4);
 	int  (*adapter_check_health)(struct aac_dev *dev);
 };
 
@@ -541,6 +580,7 @@
 #define Mailbox3	SaDbCSR.MAILBOX3
 #define Mailbox4	SaDbCSR.MAILBOX4
 #define Mailbox5	SaDbCSR.MAILBOX5
+#define Mailbox6	SaDbCSR.MAILBOX6
 #define Mailbox7	SaDbCSR.MAILBOX7
 	
 #define DoorbellReg_p SaDbCSR.PRISETIRQ
@@ -763,29 +803,48 @@
  
 struct aac_adapter_info
 {
-	u32	platform;
-	u32	cpu;
-	u32	subcpu;
-	u32	clock;
-	u32	execmem;
-	u32	buffermem;
-	u32	totalmem;
-	u32	kernelrev;
-	u32	kernelbuild;
-	u32	monitorrev;
-	u32	monitorbuild;
-	u32	hwrev;
-	u32	hwbuild;
-	u32	biosrev;
-	u32	biosbuild;
-	u32	cluster;
-	u32	clusterchannelmask; 
-	u32	serial[2];
-	u32	battery;
-	u32	options;
-	u32	OEM;
+	__le32	platform;
+	__le32	cpu;
+	__le32	subcpu;
+	__le32	clock;
+	__le32	execmem;
+	__le32	buffermem;
+	__le32	totalmem;
+	__le32	kernelrev;
+	__le32	kernelbuild;
+	__le32	monitorrev;
+	__le32	monitorbuild;
+	__le32	hwrev;
+	__le32	hwbuild;
+	__le32	biosrev;
+	__le32	biosbuild;
+	__le32	cluster;
+	__le32	clusterchannelmask; 
+	__le32	serial[2];
+	__le32	battery;
+	__le32	options;
+	__le32	OEM;
 };
 
+struct aac_supplement_adapter_info
+{
+	u8	AdapterTypeText[17+1];
+	u8	Pad[2];
+	__le32	FlashMemoryByteSize;
+	__le32	FlashImageId;
+	__le32	MaxNumberPorts;
+	__le32	Version;
+	__le32	FeatureBits;
+	u8	SlotNumber;
+	u8	ReservedPad0[0];
+	u8	BuildDate[12];
+	__le32	CurrentNumberPorts;
+	__le32	ReservedGrowth[24];
+};
+#define AAC_FEATURE_FALCON	0x00000010
+#define AAC_SIS_VERSION_V3	3
+#define AAC_SIS_SLOT_UNKNOWN	0xFF
+
 /*
  * Battery platforms
  */
@@ -831,6 +890,12 @@
 
 	u16			irq_mask;
 	/*
+	 *	negotiated FIB settings
+	 */
+	unsigned		max_fib_size;
+	unsigned		sg_tablesize;
+
+	/*
 	 *	Map for 128 fib objects (64k)
 	 */	
 	dma_addr_t		hw_fib_pa;
@@ -889,12 +954,14 @@
 	u32			aif_thread;
 	struct completion	aif_completion;
 	struct aac_adapter_info adapter_info;
+	struct aac_supplement_adapter_info supplement_adapter_info;
 	/* These are in adapter info but they are in the io flow so
 	 * lets break them out so we don't have to do an AND to check them
 	 */
 	u8			nondasd_support; 
 	u8			dac_support;
 	u8			raid_scsi_mode;
+	u8			printf_enabled;
 };
 
 #define aac_adapter_interrupt(dev) \
@@ -903,6 +970,8 @@
 #define aac_adapter_notify(dev, event) \
 	(dev)->a_ops.adapter_notify(dev, event)
 
+#define aac_adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) \
+	(dev)->a_ops.adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4)
 
 #define aac_adapter_check_health(dev) \
 	(dev)->a_ops.adapter_check_health(dev)
@@ -1016,83 +1085,102 @@
 
 struct aac_read
 {
-	u32	 	command;
-	u32 		cid;
-	u32 		block;
-	u32 		count;
+	__le32	 	command;
+	__le32 		cid;
+	__le32 		block;
+	__le32 		count;
 	struct sgmap	sg;	// Must be last in struct because it is variable
 };
 
 struct aac_read64
 {
-	u32	 	command;
-	u16 		cid;
-	u16 		sector_count;
-	u32 		block;
-	u16		pad;
-	u16		flags;
+	__le32	 	command;
+	__le16 		cid;
+	__le16 		sector_count;
+	__le32 		block;
+	__le16		pad;
+	__le16		flags;
 	struct sgmap64	sg;	// Must be last in struct because it is variable
 };
 
 struct aac_read_reply
 {
-	u32	 	status;
-	u32 		count;
+	__le32	 	status;
+	__le32 		count;
 };
 
 struct aac_write
 {
-	u32		command;
-	u32 		cid;
-	u32 		block;
-	u32 		count;
-	u32	 	stable;	// Not used
+	__le32		command;
+	__le32 		cid;
+	__le32 		block;
+	__le32 		count;
+	__le32	 	stable;	// Not used
 	struct sgmap	sg;	// Must be last in struct because it is variable
 };
 
 struct aac_write64
 {
-	u32	 	command;
-	u16 		cid;
-	u16 		sector_count;
-	u32 		block;
-	u16		pad;
-	u16		flags;
+	__le32	 	command;
+	__le16 		cid;
+	__le16 		sector_count;
+	__le32 		block;
+	__le16		pad;
+	__le16		flags;
 	struct sgmap64	sg;	// Must be last in struct because it is variable
 };
 struct aac_write_reply
 {
-	u32		status;
-	u32 		count;
-	u32		committed;
+	__le32		status;
+	__le32 		count;
+	__le32		committed;
 };
 
 #define CT_FLUSH_CACHE 129
 struct aac_synchronize {
-	u32		command;	/* VM_ContainerConfig */
-	u32		type;		/* CT_FLUSH_CACHE */
-	u32		cid;
-	u32		parm1;
-	u32		parm2;
-	u32		parm3;
-	u32		parm4;
-	u32		count;	/* sizeof(((struct aac_synchronize_reply *)NULL)->data) */
+	__le32		command;	/* VM_ContainerConfig */
+	__le32		type;		/* CT_FLUSH_CACHE */
+	__le32		cid;
+	__le32		parm1;
+	__le32		parm2;
+	__le32		parm3;
+	__le32		parm4;
+	__le32		count;	/* sizeof(((struct aac_synchronize_reply *)NULL)->data) */
 };
 
 struct aac_synchronize_reply {
-	u32		dummy0;
-	u32		dummy1;
-	u32		status;	/* CT_OK */
-	u32		parm1;
-	u32		parm2;
-	u32		parm3;
-	u32		parm4;
-	u32		parm5;
+	__le32		dummy0;
+	__le32		dummy1;
+	__le32		status;	/* CT_OK */
+	__le32		parm1;
+	__le32		parm2;
+	__le32		parm3;
+	__le32		parm4;
+	__le32		parm5;
 	u8		data[16];
 };
 
 struct aac_srb
 {
+	__le32		function;
+	__le32		channel;
+	__le32		id;
+	__le32		lun;
+	__le32		timeout;
+	__le32		flags;
+	__le32		count;		// Data xfer size
+	__le32		retry_limit;
+	__le32		cdb_size;
+	u8		cdb[16];
+	struct	sgmap	sg;
+};
+
+/*
+ * This and assocated data structs are used by the 
+ * ioctl caller and are in cpu order.
+ */
+struct user_aac_srb
+{
 	u32		function;
 	u32		channel;
 	u32		id;
@@ -1103,20 +1191,18 @@
 	u32		retry_limit;
 	u32		cdb_size;
 	u8		cdb[16];
-	struct	sgmap	sg;
+	struct	user_sgmap	sg;
 };
 
-
-
 #define		AAC_SENSE_BUFFERSIZE	 30
 
 struct aac_srb_reply
 {
-	u32		status;
-	u32		srb_status;
-	u32		scsi_status;
-	u32		data_xfer_length;
-	u32		sense_data_size;
+	__le32		status;
+	__le32		srb_status;
+	__le32		scsi_status;
+	__le32		data_xfer_length;
+	__le32		sense_data_size;
 	u8		sense_data[AAC_SENSE_BUFFERSIZE]; // Can this be SCSI_SENSE_BUFFERSIZE
 };
 /*
@@ -1223,14 +1309,14 @@
  */
 
 struct aac_fsinfo {
-	u32  fsTotalSize;	/* Consumed by fs, incl. metadata */
-	u32  fsBlockSize;
-	u32  fsFragSize;
-	u32  fsMaxExtendSize;
-	u32  fsSpaceUnits;
-	u32  fsMaxNumFiles;
-	u32  fsNumFreeFiles;
-	u32  fsInodeDensity;
+	__le32  fsTotalSize;	/* Consumed by fs, incl. metadata */
+	__le32  fsBlockSize;
+	__le32  fsFragSize;
+	__le32  fsMaxExtendSize;
+	__le32  fsSpaceUnits;
+	__le32  fsMaxNumFiles;
+	__le32  fsNumFreeFiles;
+	__le32  fsInodeDensity;
 };	/* valid iff ObjType == FT_FILESYS && !(ContentState & FSCS_NOTCLEAN) */
 
 union aac_contentinfo {
@@ -1243,32 +1329,32 @@
 
 #define CT_GET_CONFIG_STATUS 147
 struct aac_get_config_status {
-	u32		command;	/* VM_ContainerConfig */
-	u32		type;		/* CT_GET_CONFIG_STATUS */
-	u32		parm1;
-	u32		parm2;
-	u32		parm3;
-	u32		parm4;
-	u32		parm5;
-	u32		count;	/* sizeof(((struct aac_get_config_status_resp *)NULL)->data) */
+	__le32		command;	/* VM_ContainerConfig */
+	__le32		type;		/* CT_GET_CONFIG_STATUS */
+	__le32		parm1;
+	__le32		parm2;
+	__le32		parm3;
+	__le32		parm4;
+	__le32		parm5;
+	__le32		count;	/* sizeof(((struct aac_get_config_status_resp *)NULL)->data) */
 };
 
 #define CFACT_CONTINUE 0
 #define CFACT_PAUSE    1
 #define CFACT_ABORT    2
 struct aac_get_config_status_resp {
-	u32		response; /* ST_OK */
-	u32		dummy0;
-	u32		status;	/* CT_OK */
-	u32		parm1;
-	u32		parm2;
-	u32		parm3;
-	u32		parm4;
-	u32		parm5;
+	__le32		response; /* ST_OK */
+	__le32		dummy0;
+	__le32		status;	/* CT_OK */
+	__le32		parm1;
+	__le32		parm2;
+	__le32		parm3;
+	__le32		parm4;
+	__le32		parm5;
 	struct {
-		u32	action; /* CFACT_CONTINUE, CFACT_PAUSE or CFACT_ABORT */
-		u16	flags;
-		s16	count;
+		__le32	action; /* CFACT_CONTINUE, CFACT_PAUSE or CFACT_ABORT */
+		__le16	flags;
+		__le16	count;
 	}		data;
 };
 
@@ -1279,26 +1365,26 @@
 #define CT_COMMIT_CONFIG 152
 
 struct aac_commit_config {
-	u32		command;	/* VM_ContainerConfig */
-	u32		type;		/* CT_COMMIT_CONFIG */
+	__le32		command;	/* VM_ContainerConfig */
+	__le32		type;		/* CT_COMMIT_CONFIG */
 };
 
 /*
- *	Query for Container Configuration Count
+ *	Query for Container Configuration Status
  */
 
 #define CT_GET_CONTAINER_COUNT 4
 struct aac_get_container_count {
-	u32		command;	/* VM_ContainerConfig */
-	u32		type;		/* CT_GET_CONTAINER_COUNT */
+	__le32		command;	/* VM_ContainerConfig */
+	__le32		type;		/* CT_GET_CONTAINER_COUNT */
 };
 
 struct aac_get_container_count_resp {
-	u32		response; /* ST_OK */
-	u32		dummy0;
-	u32		MaxContainers;
-	u32		ContainerSwitchEntries;
-	u32		MaxPartitions;
+	__le32		response; /* ST_OK */
+	__le32		dummy0;
+	__le32		MaxContainers;
+	__le32		ContainerSwitchEntries;
+	__le32		MaxPartitions;
 };
 
 
@@ -1308,15 +1394,19 @@
  */
 
 struct aac_mntent {
-	u32    			oid;
-	u8			name[16];	// if applicable
-	struct creation_info	create_info;	// if applicable
-	u32			capacity;
-	u32			vol;    	// substrate structure
-	u32			obj;	        // FT_FILESYS, FT_DATABASE, etc.
-	u32			state;		// unready for mounting, readonly, etc.
-	union aac_contentinfo	fileinfo;	// Info specific to content manager (eg, filesystem)
-	u32			altoid;		// != oid <==> snapshot or broken mirror exists
+	__le32    		oid;
+	u8			name[16];	/* if applicable */
+	struct creation_info	create_info;	/* if applicable */
+	__le32			capacity;
+	__le32			vol;    	/* substrate structure */
+	__le32			obj;	        /* FT_FILESYS, 
+						   FT_DATABASE, etc. */
+	__le32			state;		/* unready for mounting, 
+						   readonly, etc. */
+	union aac_contentinfo	fileinfo;	/* Info specific to content 
+						   manager (eg, filesystem) */
+	__le32			altoid;		/* != oid <==> snapshot or 
+						   broken mirror exists */
 };
 
 #define FSCS_NOTCLEAN	0x0001  /* fsck is neccessary before mounting */
@@ -1324,40 +1414,40 @@
 #define FSCS_HIDDEN	0x0004	/* should be ignored - set during a clear */
 
 struct aac_query_mount {
-	u32		command;
-	u32		type;
-	u32		count;
+	__le32		command;
+	__le32		type;
+	__le32		count;
 };
 
 struct aac_mount {
-	u32		status;
-	u32	   	type;           /* should be same as that requested */
-	u32		count;
+	__le32		status;
+	__le32	   	type;           /* should be same as that requested */
+	__le32		count;
 	struct aac_mntent mnt[1];
 };
 
 #define CT_READ_NAME 130
 struct aac_get_name {
-	u32		command;	/* VM_ContainerConfig */
-	u32		type;		/* CT_READ_NAME */
-	u32		cid;
-	u32		parm1;
-	u32		parm2;
-	u32		parm3;
-	u32		parm4;
-	u32		count;	/* sizeof(((struct aac_get_name_resp *)NULL)->data) */
+	__le32		command;	/* VM_ContainerConfig */
+	__le32		type;		/* CT_READ_NAME */
+	__le32		cid;
+	__le32		parm1;
+	__le32		parm2;
+	__le32		parm3;
+	__le32		parm4;
+	__le32		count;	/* sizeof(((struct aac_get_name_resp *)NULL)->data) */
 };
 
 #define CT_OK        218
 struct aac_get_name_resp {
-	u32		dummy0;
-	u32		dummy1;
-	u32		status;	/* CT_OK */
-	u32		parm1;
-	u32		parm2;
-	u32		parm3;
-	u32		parm4;
-	u32		parm5;
+	__le32		dummy0;
+	__le32		dummy1;
+	__le32		status;	/* CT_OK */
+	__le32		parm1;
+	__le32		parm2;
+	__le32		parm3;
+	__le32		parm4;
+	__le32		parm5;
 	u8		data[16];
 };
 
@@ -1366,8 +1456,8 @@
  */
 
 struct aac_close {
-	u32	command;
-	u32	cid;
+	__le32	command;
+	__le32	cid;
 };
 
 struct aac_query_disk
@@ -1434,6 +1524,7 @@
 #define FSACTL_GET_PCI_INFO               	CTL_CODE(2119, METHOD_BUFFERED)
 #define FSACTL_FORCE_DELETE_DISK		CTL_CODE(2120, METHOD_NEITHER)
 #define FSACTL_GET_CONTAINERS			2131
+#define FSACTL_SEND_LARGE_FIB			CTL_CODE(2138, METHOD_BUFFERED)
 
 
 struct aac_common
@@ -1573,8 +1664,8 @@
  */
 
 struct aac_aifcmd {
-	u32 command;		/* Tell host what type of notify this is */
-	u32 seqnum;		/* To allow ordering of reports (if necessary) */
+	__le32 command;		/* Tell host what type of notify this is */
+	__le32 seqnum;		/* To allow ordering of reports (if necessary) */
 	u8 data[1];		/* Undefined length (from kernel viewpoint) */
 };
 
@@ -1597,7 +1688,6 @@
 void fib_map_free(struct aac_dev *dev);
 void fib_free(struct fib * context);
 void fib_init(struct fib * context);
-void fib_dealloc(struct fib * context);
 void aac_printf(struct aac_dev *dev, u32 val);
 int fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt);
 int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry);
@@ -1621,3 +1711,5 @@
 struct aac_driver_ident* aac_get_driver_ident(int devtype);
 int aac_get_adapter_info(struct aac_dev* dev);
 int aac_send_shutdown(struct aac_dev *dev);
+extern int numacb;
+extern int acbsize;
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 30dd1f7..1fef92d 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -51,15 +51,22 @@
  *	This routine sends a fib to the adapter on behalf of a user level
  *	program.
  */
+# define AAC_DEBUG_PREAMBLE	KERN_INFO
+# define AAC_DEBUG_POSTAMBLE
  
 static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
 {
 	struct hw_fib * kfib;
 	struct fib *fibptr;
+	struct hw_fib * hw_fib = (struct hw_fib *)0;
+	dma_addr_t hw_fib_pa = (dma_addr_t)0LL;
+	unsigned size;
+	int retval;
 
 	fibptr = fib_alloc(dev);
-	if(fibptr == NULL)
+	if(fibptr == NULL) {
 		return -ENOMEM;
+	}
 		
 	kfib = fibptr->hw_fib;
 	/*
@@ -74,19 +81,24 @@
 	 *	will not overrun the buffer when we copy the memory. Return
 	 *	an error if we would.
 	 */
-	if (le16_to_cpu(kfib->header.Size) > 
-			sizeof(struct hw_fib) - sizeof(struct aac_fibhdr)) {
-		fib_free(fibptr);
-		return -EINVAL;
+	size = le16_to_cpu(kfib->header.Size) + sizeof(struct aac_fibhdr);
+	if (size < le16_to_cpu(kfib->header.SenderSize))
+		size = le16_to_cpu(kfib->header.SenderSize);
+	if (size > dev->max_fib_size) {
+		/* Highjack the hw_fib */
+		hw_fib = fibptr->hw_fib;
+		hw_fib_pa = fibptr->hw_fib_pa;
+		fibptr->hw_fib = kfib = pci_alloc_consistent(dev->pdev, size, &fibptr->hw_fib_pa);
+		memset(((char *)kfib) + dev->max_fib_size, 0, size - dev->max_fib_size);
+		memcpy(kfib, hw_fib, dev->max_fib_size);
 	}
 
-	if (copy_from_user(kfib, arg, le16_to_cpu(kfib->header.Size) +
-				sizeof(struct aac_fibhdr))) {
-		fib_free(fibptr);
-		return -EFAULT;
+	if (copy_from_user(kfib, arg, size)) {
+		retval = -EFAULT;
+		goto cleanup;
 	}
 
-	if (kfib->header.Command == cpu_to_le32(TakeABreakPt)) {
+	if (kfib->header.Command == cpu_to_le16(TakeABreakPt)) {
 		aac_adapter_interrupt(dev);
 		/*
 		 * Since we didn't really send a fib, zero out the state to allow 
@@ -94,16 +106,15 @@
 		 */
 		kfib->header.XferState = 0;
 	} else {
-		int retval = fib_send(kfib->header.Command, fibptr,
+		retval = fib_send(le16_to_cpu(kfib->header.Command), fibptr,
 				le16_to_cpu(kfib->header.Size) , FsaNormal,
 				1, 1, NULL, NULL);
 		if (retval) {
-			fib_free(fibptr);
-			return retval;
+			goto cleanup;
 		}
 		if (fib_complete(fibptr) != 0) {
-			fib_free(fibptr);
-			return -EINVAL;
+			retval = -EINVAL;
+			goto cleanup;
 		}
 	}
 	/*
@@ -114,12 +125,17 @@
 	 *	was already included by the adapter.)
 	 */
 
-	if (copy_to_user(arg, (void *)kfib, kfib->header.Size)) {
-		fib_free(fibptr);
-		return -EFAULT;
+	retval = 0;
+	if (copy_to_user(arg, (void *)kfib, size))
+		retval = -EFAULT;
+cleanup:
+	if (hw_fib) {
+		pci_free_consistent(dev->pdev, size, kfib, fibptr->hw_fib_pa);
+		fibptr->hw_fib_pa = hw_fib_pa;
+		fibptr->hw_fib = hw_fib;
 	}
 	fib_free(fibptr);
-	return 0;
+	return retval;
 }
 
 /**
@@ -391,26 +407,28 @@
 	struct revision response;
 
 	response.compat = 1;
-	response.version = dev->adapter_info.kernelrev;
-	response.build = dev->adapter_info.kernelbuild;
+	response.version = le32_to_cpu(dev->adapter_info.kernelrev);
+	response.build = le32_to_cpu(dev->adapter_info.kernelbuild);
 
 	if (copy_to_user(arg, &response, sizeof(response)))
 		return -EFAULT;
 	return 0;
 }
 
+
 /**
  *
  * aac_send_raw_scb
  *
  */
 
-int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
+static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
 {
 	struct fib* srbfib;
 	int status;
-	struct aac_srb *srbcmd;
-	struct aac_srb __user *user_srb = arg;
+	struct aac_srb *srbcmd = NULL;
+	struct user_aac_srb *user_srbcmd = NULL;
+	struct user_aac_srb __user *user_srb = arg;
 	struct aac_srb_reply __user *user_reply;
 	struct aac_srb_reply* reply;
 	u32 fibsize = 0;
@@ -426,50 +444,59 @@
 
 
 	if (!capable(CAP_SYS_ADMIN)){
-		printk(KERN_DEBUG"aacraid: No permission to send raw srb\n"); 
+		dprintk((KERN_DEBUG"aacraid: No permission to send raw srb\n")); 
 		return -EPERM;
 	}
 	/*
 	 *	Allocate and initialize a Fib then setup a BlockWrite command
 	 */
 	if (!(srbfib = fib_alloc(dev))) {
-		return -1;
+		return -ENOMEM;
 	}
 	fib_init(srbfib);
 
 	srbcmd = (struct aac_srb*) fib_data(srbfib);
 
+	memset(sg_list, 0, sizeof(sg_list)); /* cleanup may take issue */
 	if(copy_from_user(&fibsize, &user_srb->count,sizeof(u32))){
-		printk(KERN_DEBUG"aacraid: Could not copy data size from user\n"); 
+		dprintk((KERN_DEBUG"aacraid: Could not copy data size from user\n")); 
 		rcode = -EFAULT;
 		goto cleanup;
 	}
 
-	if (fibsize > FIB_DATA_SIZE_IN_BYTES) {
+	if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))) {
 		rcode = -EINVAL;
 		goto cleanup;
 	}
 
-	if(copy_from_user(srbcmd, user_srb,fibsize)){
-		printk(KERN_DEBUG"aacraid: Could not copy srb from user\n"); 
+	user_srbcmd = kmalloc(GFP_KERNEL, fibsize);
+	if (!user_srbcmd) {
+		dprintk((KERN_DEBUG"aacraid: Could not make a copy of the srb\n"));
+		rcode = -ENOMEM;
+		goto cleanup;
+	}
+	if(copy_from_user(user_srbcmd, user_srb,fibsize)){
+		dprintk((KERN_DEBUG"aacraid: Could not copy srb from user\n")); 
 		rcode = -EFAULT;
 		goto cleanup;
 	}
 
 	user_reply = arg+fibsize;
 
-	flags = srbcmd->flags;
+	flags = user_srbcmd->flags; /* from user in cpu order */
 	// Fix up srb for endian and force some values
+
 	srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);	// Force this
-	srbcmd->channel  = cpu_to_le32(srbcmd->channel);
-	srbcmd->id	 = cpu_to_le32(srbcmd->id);
-	srbcmd->lun      = cpu_to_le32(srbcmd->lun);
-	srbcmd->flags    = cpu_to_le32(srbcmd->flags);
-	srbcmd->timeout  = cpu_to_le32(srbcmd->timeout);
-	srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter
-	srbcmd->cdb_size = cpu_to_le32(srbcmd->cdb_size);
+	srbcmd->channel  = cpu_to_le32(user_srbcmd->channel);
+	srbcmd->id	 = cpu_to_le32(user_srbcmd->id);
+	srbcmd->lun      = cpu_to_le32(user_srbcmd->lun);
+	srbcmd->timeout  = cpu_to_le32(user_srbcmd->timeout);
+	srbcmd->flags    = cpu_to_le32(flags);
+	srbcmd->retry_limit = 0; // Obsolete parameter
+	srbcmd->cdb_size = cpu_to_le32(user_srbcmd->cdb_size);
+	memcpy(srbcmd->cdb, user_srbcmd->cdb, sizeof(srbcmd->cdb));
 	
-	switch (srbcmd->flags & (SRB_DataIn | SRB_DataOut)) {
+	switch (flags & (SRB_DataIn | SRB_DataOut)) {
 	case SRB_DataOut:
 		data_dir = DMA_TO_DEVICE;
 		break;
@@ -482,118 +509,148 @@
 	default:
 		data_dir = DMA_NONE;
 	}
+	if (user_srbcmd->sg.count > (sizeof(sg_list)/sizeof(sg_list[0]))) {
+		dprintk((KERN_DEBUG"aacraid: too many sg entries %d\n",
+		  le32_to_cpu(srbcmd->sg.count)));
+		rcode = -EINVAL;
+		goto cleanup;
+	}
 	if (dev->dac_support == 1) {
-		struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg;
+		struct user_sgmap64* upsg = (struct user_sgmap64*)&user_srbcmd->sg;
+		struct sgmap64* psg = (struct sgmap64*)&user_srbcmd->sg;
+		struct user_sgmap* usg;
 		byte_count = 0;
 
 		/*
 		 * This should also catch if user used the 32 bit sgmap
 		 */
 		actual_fibsize = sizeof(struct aac_srb) - 
-			sizeof(struct sgentry) + ((srbcmd->sg.count & 0xff) * 
-			 	sizeof(struct sgentry64));
+			sizeof(struct sgentry) +
+			((upsg->count & 0xff) * 
+		 	sizeof(struct sgentry));
 		if(actual_fibsize != fibsize){ // User made a mistake - should not continue
-			printk(KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n");
+			dprintk((KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n"));
 			rcode = -EINVAL;
 			goto cleanup;
 		}
-		if ((data_dir == DMA_NONE) && psg->count) { 
-			printk(KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n");
+		usg = kmalloc(actual_fibsize - sizeof(struct aac_srb)
+		  + sizeof(struct sgmap), GFP_KERNEL);
+		if (!usg) {
+			dprintk((KERN_DEBUG"aacraid: Allocation error in Raw SRB command\n"));
+			rcode = -ENOMEM;
+			goto cleanup;
+		}
+		memcpy (usg, upsg, actual_fibsize - sizeof(struct aac_srb)
+		  + sizeof(struct sgmap));
+		actual_fibsize = sizeof(struct aac_srb) - 
+			sizeof(struct sgentry) + ((usg->count & 0xff) * 
+			 	sizeof(struct sgentry64));
+		if ((data_dir == DMA_NONE) && upsg->count) {
+			kfree (usg);
+			dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
 			rcode = -EINVAL;
 			goto cleanup;
 		}
 
-		for (i = 0; i < psg->count; i++) {
-			dma_addr_t addr; 
-			u64 le_addr;
+		for (i = 0; i < usg->count; i++) {
+			u64 addr;
 			void* p;
-			p = kmalloc(psg->sg[i].count,GFP_KERNEL|__GFP_DMA);
+			/* Does this really need to be GFP_DMA? */
+			p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);
 			if(p == 0) {
-				printk(KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
-				psg->sg[i].count,i,psg->count);
+				kfree (usg);
+				dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
+				  usg->sg[i].count,i,usg->count));
 				rcode = -ENOMEM;
 				goto cleanup;
 			}
-			sg_user[i] = (void __user *)psg->sg[i].addr;
+			sg_user[i] = (void __user *)usg->sg[i].addr;
 			sg_list[i] = p; // save so we can clean up later
 			sg_indx = i;
 
 			if( flags & SRB_DataOut ){
-				if(copy_from_user(p,sg_user[i],psg->sg[i].count)){
-					printk(KERN_DEBUG"aacraid: Could not copy sg data from user\n"); 
+				if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){
+					kfree (usg);
+					dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); 
 					rcode = -EFAULT;
 					goto cleanup;
 				}
 			}
-			addr = pci_map_single(dev->pdev, p, psg->sg[i].count, data_dir);
+			addr = pci_map_single(dev->pdev, p, usg->sg[i].count, data_dir);
 
-			le_addr = cpu_to_le64(addr);
-			psg->sg[i].addr[1] = (u32)(le_addr>>32);
-			psg->sg[i].addr[0] = (u32)(le_addr & 0xffffffff);
-			psg->sg[i].count = cpu_to_le32(psg->sg[i].count);  
-			byte_count += psg->sg[i].count;
+			psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
+			psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
+			psg->sg[i].count = cpu_to_le32(usg->sg[i].count);  
+			byte_count += usg->sg[i].count;
 		}
+		kfree (usg);
 
 		srbcmd->count = cpu_to_le32(byte_count);
+		psg->count = cpu_to_le32(sg_indx+1);
 		status = fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL);
 	} else {
+		struct user_sgmap* upsg = &user_srbcmd->sg;
 		struct sgmap* psg = &srbcmd->sg;
 		byte_count = 0;
 
-		actual_fibsize = sizeof (struct aac_srb) + 
-			(((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) * 
-			 sizeof (struct sgentry));
+		actual_fibsize = sizeof (struct aac_srb) + (((user_srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry));
 		if(actual_fibsize != fibsize){ // User made a mistake - should not continue
-			printk(KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n");
+			dprintk((KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n"));
 			rcode = -EINVAL;
 			goto cleanup;
 		}
-		if ((data_dir == DMA_NONE) && psg->count) {
-			printk(KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n");
+		if ((data_dir == DMA_NONE) && upsg->count) {
+			dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
 			rcode = -EINVAL;
 			goto cleanup;
 		}
-		for (i = 0; i < psg->count; i++) {
+		for (i = 0; i < upsg->count; i++) {
 			dma_addr_t addr; 
 			void* p;
-			p = kmalloc(psg->sg[i].count,GFP_KERNEL);
+			p = kmalloc(upsg->sg[i].count, GFP_KERNEL);
 			if(p == 0) {
-				printk(KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
-				psg->sg[i].count,i,psg->count);
+				dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
+				  upsg->sg[i].count, i, upsg->count));
 				rcode = -ENOMEM;
 				goto cleanup;
 			}
-			sg_user[i] = (void __user *)(psg->sg[i].addr);
+			sg_user[i] = (void __user *)upsg->sg[i].addr;
 			sg_list[i] = p; // save so we can clean up later
 			sg_indx = i;
 
 			if( flags & SRB_DataOut ){
-				if(copy_from_user(p,sg_user[i],psg->sg[i].count)){
-					printk(KERN_DEBUG"aacraid: Could not copy sg data from user\n"); 
+				if(copy_from_user(p, sg_user[i],
+						upsg->sg[i].count)) {
+					dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); 
 					rcode = -EFAULT;
 					goto cleanup;
 				}
 			}
-			addr = pci_map_single(dev->pdev, p, psg->sg[i].count, data_dir);
+			addr = pci_map_single(dev->pdev, p,
+				upsg->sg[i].count, data_dir);
 
 			psg->sg[i].addr = cpu_to_le32(addr);
-			psg->sg[i].count = cpu_to_le32(psg->sg[i].count);  
-			byte_count += psg->sg[i].count;
+			psg->sg[i].count = cpu_to_le32(upsg->sg[i].count);  
+			byte_count += upsg->sg[i].count;
 		}
 		srbcmd->count = cpu_to_le32(byte_count);
+		psg->count = cpu_to_le32(sg_indx+1);
 		status = fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL);
 	}
 
 	if (status != 0){
-		printk(KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n"); 
-		rcode = -1;
+		dprintk((KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n")); 
+		rcode = -ENXIO;
 		goto cleanup;
 	}
 
 	if( flags & SRB_DataIn ) {
 		for(i = 0 ; i <= sg_indx; i++){
-			if(copy_to_user(sg_user[i],sg_list[i],le32_to_cpu(srbcmd->sg.sg[i].count))){
-				printk(KERN_DEBUG"aacraid: Could not copy sg data to user\n"); 
+			byte_count = le32_to_cpu((dev->dac_support == 1)
+			      ? ((struct sgmap64*)&srbcmd->sg)->sg[i].count
+			      : srbcmd->sg.sg[i].count);
+			if(copy_to_user(sg_user[i], sg_list[i], byte_count)){
+				dprintk((KERN_DEBUG"aacraid: Could not copy sg data to user\n")); 
 				rcode = -EFAULT;
 				goto cleanup;
 
@@ -603,12 +660,13 @@
 
 	reply = (struct aac_srb_reply *) fib_data(srbfib);
 	if(copy_to_user(user_reply,reply,sizeof(struct aac_srb_reply))){
-		printk(KERN_DEBUG"aacraid: Could not copy reply to user\n"); 
+		dprintk((KERN_DEBUG"aacraid: Could not copy reply to user\n")); 
 		rcode = -EFAULT;
 		goto cleanup;
 	}
 
 cleanup:
+	kfree(user_srbcmd);
 	for(i=0; i <= sg_indx; i++){
 		kfree(sg_list[i]);
 	}
@@ -618,14 +676,13 @@
 	return rcode;
 }
 
-
 struct aac_pci_info {
         u32 bus;
         u32 slot;
 };
 
 
-int aac_get_pci_info(struct aac_dev* dev, void __user *arg)
+static int aac_get_pci_info(struct aac_dev* dev, void __user *arg)
 {
         struct aac_pci_info pci_info;
 
@@ -633,11 +690,11 @@
 	pci_info.slot = PCI_SLOT(dev->pdev->devfn);
 
        if (copy_to_user(arg, &pci_info, sizeof(struct aac_pci_info))) {
-		printk(KERN_DEBUG "aacraid: Could not copy pci info\n");
+               dprintk((KERN_DEBUG "aacraid: Could not copy pci info\n"));
                return -EFAULT;
 	}
         return 0;
- }
+}
  
 
 int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg)
@@ -656,6 +713,7 @@
 	case FSACTL_MINIPORT_REV_CHECK:
 		status = check_revision(dev, arg);
 		break;
+	case FSACTL_SEND_LARGE_FIB:
 	case FSACTL_SENDFIB:
 		status = ioctl_send_fib(dev, arg);
 		break;
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 6832a55..43557bf 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -39,6 +39,7 @@
 #include <linux/blkdev.h>
 #include <linux/completion.h>
 #include <linux/mm.h>
+#include <scsi/scsi_host.h>
 #include <asm/semaphore.h>
 
 #include "aacraid.h"
@@ -49,8 +50,8 @@
 {
 	unsigned char *base;
 	unsigned long size, align;
-	unsigned long fibsize = 4096;
-	unsigned long printfbufsiz = 256;
+	const unsigned long fibsize = 4096;
+	const unsigned long printfbufsiz = 256;
 	struct aac_init *init;
 	dma_addr_t phys;
 
@@ -74,6 +75,8 @@
 	init = dev->init;
 
 	init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION);
+	if (dev->max_fib_size != sizeof(struct hw_fib))
+		init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4);
 	init->MiniPortRevision = cpu_to_le32(Sa_MINIPORT_REVISION);
 	init->fsrev = cpu_to_le32(dev->fsrev);
 
@@ -110,6 +113,10 @@
 		init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES);
 	}
 
+	init->InitFlags = 0;
+	init->MaxIoCommands = cpu_to_le32(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB);
+	init->MaxIoSize = cpu_to_le32(dev->scsi_host_ptr->max_sectors << 9);
+	init->MaxFibSize = cpu_to_le32(dev->max_fib_size);
 
 	/*
 	 * Increment the base address by the amount already used
@@ -152,8 +159,8 @@
 	init_waitqueue_head(&q->qfull);
 	spin_lock_init(&q->lockdata);
 	q->lock = &q->lockdata;
-	q->headers.producer = mem;
-	q->headers.consumer = mem+1;
+	q->headers.producer = (__le32 *)mem;
+	q->headers.consumer = (__le32 *)(mem+1);
 	*(q->headers.producer) = cpu_to_le32(qsize);
 	*(q->headers.consumer) = cpu_to_le32(qsize);
 	q->entries = qsize;
@@ -173,6 +180,8 @@
 	int status;
 
 	fibctx = fib_alloc(dev);
+	if (!fibctx)
+		return -ENOMEM;
 	fib_init(fibctx);
 
 	cmd = (struct aac_close *) fib_data(fibctx);
@@ -204,7 +213,7 @@
  *		0 - If there were errors initing. This is a fatal error.
  */
  
-int aac_comm_init(struct aac_dev * dev)
+static int aac_comm_init(struct aac_dev * dev)
 {
 	unsigned long hdrsize = (sizeof(u32) * NUMBER_OF_COMM_QUEUES) * 2;
 	unsigned long queuesize = sizeof(struct aac_entry) * TOTAL_QUEUE_ENTRIES;
@@ -293,6 +302,79 @@
 
 struct aac_dev *aac_init_adapter(struct aac_dev *dev)
 {
+	u32 status[5];
+	struct Scsi_Host * host = dev->scsi_host_ptr;
+
+	/*
+	 *	Check the preferred comm settings, defaults from template.
+	 */
+	dev->max_fib_size = sizeof(struct hw_fib);
+	dev->sg_tablesize = host->sg_tablesize = (dev->max_fib_size
+		- sizeof(struct aac_fibhdr)
+		- sizeof(struct aac_write) + sizeof(struct sgmap))
+			/ sizeof(struct sgmap);
+	if ((!aac_adapter_sync_cmd(dev, GET_COMM_PREFERRED_SETTINGS,
+	  0, 0, 0, 0, 0, 0,
+	  status+0, status+1, status+2, status+3, status+4))
+	 && (status[0] == 0x00000001)) {
+		/*
+		 *	status[1] >> 16		maximum command size in KB
+		 *	status[1] & 0xFFFF	maximum FIB size
+		 *	status[2] >> 16		maximum SG elements to driver
+		 *	status[2] & 0xFFFF	maximum SG elements from driver
+		 *	status[3] & 0xFFFF	maximum number FIBs outstanding
+		 */
+		host->max_sectors = (status[1] >> 16) << 1;
+		dev->max_fib_size = status[1] & 0xFFFF;
+		host->sg_tablesize = status[2] >> 16;
+		dev->sg_tablesize = status[2] & 0xFFFF;
+		host->can_queue = (status[3] & 0xFFFF) - AAC_NUM_MGT_FIB;
+		/*
+		 *	NOTE:
+		 *	All these overrides are based on a fixed internal
+		 *	knowledge and understanding of existing adapters,
+		 *	acbsize should be set with caution.
+		 */
+		if (acbsize == 512) {
+			host->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
+			dev->max_fib_size = 512;
+			dev->sg_tablesize = host->sg_tablesize
+			  = (512 - sizeof(struct aac_fibhdr)
+			    - sizeof(struct aac_write) + sizeof(struct sgmap))
+			     / sizeof(struct sgmap);
+			host->can_queue = AAC_NUM_IO_FIB;
+		} else if (acbsize == 2048) {
+			host->max_sectors = 512;
+			dev->max_fib_size = 2048;
+			host->sg_tablesize = 65;
+			dev->sg_tablesize = 81;
+			host->can_queue = 512 - AAC_NUM_MGT_FIB;
+		} else if (acbsize == 4096) {
+			host->max_sectors = 1024;
+			dev->max_fib_size = 4096;
+			host->sg_tablesize = 129;
+			dev->sg_tablesize = 166;
+			host->can_queue = 256 - AAC_NUM_MGT_FIB;
+		} else if (acbsize == 8192) {
+			host->max_sectors = 2048;
+			dev->max_fib_size = 8192;
+			host->sg_tablesize = 257;
+			dev->sg_tablesize = 337;
+			host->can_queue = 128 - AAC_NUM_MGT_FIB;
+		} else if (acbsize > 0) {
+			printk("Illegal acbsize=%d ignored\n", acbsize);
+		}
+	}
+	{
+
+		if (numacb > 0) {
+			if (numacb < host->can_queue)
+				host->can_queue = numacb;
+			else
+				printk("numacb=%d ignored\n", numacb);
+		}
+	}
+
 	/*
 	 *	Ok now init the communication subsystem
 	 */
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 3f36dba..5322865 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -25,7 +25,7 @@
  *  commsup.c
  *
  * Abstract: Contain all routines that are required for FSA host/adapter
- *    commuication.
+ *    communication.
  *
  */
 
@@ -38,6 +38,7 @@
 #include <linux/slab.h>
 #include <linux/completion.h>
 #include <linux/blkdev.h>
+#include <scsi/scsi_host.h>
 #include <asm/semaphore.h>
 
 #include "aacraid.h"
@@ -52,7 +53,13 @@
  
 static int fib_map_alloc(struct aac_dev *dev)
 {
-	if((dev->hw_fib_va = pci_alloc_consistent(dev->pdev, sizeof(struct hw_fib) * AAC_NUM_FIB, &dev->hw_fib_pa))==NULL)
+	dprintk((KERN_INFO
+	  "allocate hardware fibs pci_alloc_consistent(%p, %d * (%d + %d), %p)\n",
+	  dev->pdev, dev->max_fib_size, dev->scsi_host_ptr->can_queue,
+	  AAC_NUM_MGT_FIB, &dev->hw_fib_pa));
+	if((dev->hw_fib_va = pci_alloc_consistent(dev->pdev, dev->max_fib_size
+	  * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB),
+	  &dev->hw_fib_pa))==NULL)
 		return -ENOMEM;
 	return 0;
 }
@@ -67,7 +74,7 @@
 
 void fib_map_free(struct aac_dev *dev)
 {
-	pci_free_consistent(dev->pdev, sizeof(struct hw_fib) * AAC_NUM_FIB, dev->hw_fib_va, dev->hw_fib_pa);
+	pci_free_consistent(dev->pdev, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB), dev->hw_fib_va, dev->hw_fib_pa);
 }
 
 /**
@@ -84,17 +91,22 @@
 	struct hw_fib *hw_fib_va;
 	dma_addr_t hw_fib_pa;
 	int i;
-	
-	if(fib_map_alloc(dev)<0)
+
+	while (((i = fib_map_alloc(dev)) == -ENOMEM)
+	 && (dev->scsi_host_ptr->can_queue > (64 - AAC_NUM_MGT_FIB))) {
+		dev->init->MaxIoCommands = cpu_to_le32((dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) >> 1);
+		dev->scsi_host_ptr->can_queue = le32_to_cpu(dev->init->MaxIoCommands) - AAC_NUM_MGT_FIB;
+	}
+	if (i<0)
 		return -ENOMEM;
 		
 	hw_fib_va = dev->hw_fib_va;
 	hw_fib_pa = dev->hw_fib_pa;
-	memset(hw_fib_va, 0, sizeof(struct hw_fib) * AAC_NUM_FIB);
+	memset(hw_fib_va, 0, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB));
 	/*
 	 *	Initialise the fibs
 	 */
-	for (i = 0, fibptr = &dev->fibs[i]; i < AAC_NUM_FIB; i++, fibptr++) 
+	for (i = 0, fibptr = &dev->fibs[i]; i < (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); i++, fibptr++) 
 	{
 		fibptr->dev = dev;
 		fibptr->hw_fib = hw_fib_va;
@@ -102,16 +114,16 @@
 		fibptr->next = fibptr+1;	/* Forward chain the fibs */
 		init_MUTEX_LOCKED(&fibptr->event_wait);
 		spin_lock_init(&fibptr->event_lock);
-		hw_fib_va->header.XferState = 0xffffffff;
-		hw_fib_va->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib));
+		hw_fib_va->header.XferState = cpu_to_le32(0xffffffff);
+		hw_fib_va->header.SenderSize = cpu_to_le16(dev->max_fib_size);
 		fibptr->hw_fib_pa = hw_fib_pa;
-		hw_fib_va = (struct hw_fib *)((unsigned char *)hw_fib_va + sizeof(struct hw_fib));
-		hw_fib_pa = hw_fib_pa + sizeof(struct hw_fib); 
+		hw_fib_va = (struct hw_fib *)((unsigned char *)hw_fib_va + dev->max_fib_size);
+		hw_fib_pa = hw_fib_pa + dev->max_fib_size;
 	}
 	/*
 	 *	Add the fib chain to the free list
 	 */
-	dev->fibs[AAC_NUM_FIB-1].next = NULL;
+	dev->fibs[dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB - 1].next = NULL;
 	/*
 	 *	Enable this to debug out of queue space
 	 */
@@ -124,7 +136,7 @@
  *	@dev: Adapter to allocate the fib for
  *
  *	Allocate a fib from the adapter fib pool. If the pool is empty we
- *	wait for fibs to become free.
+ *	return NULL.
  */
  
 struct fib * fib_alloc(struct aac_dev *dev)
@@ -133,10 +145,10 @@
 	unsigned long flags;
 	spin_lock_irqsave(&dev->fib_lock, flags);
 	fibptr = dev->free_fib;	
-	/* Cannot sleep here or you get hangs. Instead we did the
-	   maths at compile time. */
-	if(!fibptr)
-		BUG();
+	if(!fibptr){
+		spin_unlock_irqrestore(&dev->fib_lock, flags);
+		return fibptr;
+	}
 	dev->free_fib = fibptr->next;
 	spin_unlock_irqrestore(&dev->fib_lock, flags);
 	/*
@@ -196,11 +208,11 @@
 	struct hw_fib *hw_fib = fibptr->hw_fib;
 
 	hw_fib->header.StructType = FIB_MAGIC;
-	hw_fib->header.Size = cpu_to_le16(sizeof(struct hw_fib));
-        hw_fib->header.XferState = cpu_to_le32(HostOwned | FibInitialized | FibEmpty | FastResponseCapable);
+	hw_fib->header.Size = cpu_to_le16(fibptr->dev->max_fib_size);
+	hw_fib->header.XferState = cpu_to_le32(HostOwned | FibInitialized | FibEmpty | FastResponseCapable);
 	hw_fib->header.SenderFibAddress = cpu_to_le32(fibptr->hw_fib_pa);
 	hw_fib->header.ReceiverFibAddress = cpu_to_le32(fibptr->hw_fib_pa);
-	hw_fib->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib));
+	hw_fib->header.SenderSize = cpu_to_le16(fibptr->dev->max_fib_size);
 }
 
 /**
@@ -211,7 +223,7 @@
  *	caller.
  */
  
-void fib_dealloc(struct fib * fibptr)
+static void fib_dealloc(struct fib * fibptr)
 {
 	struct hw_fib *hw_fib = fibptr->hw_fib;
 	if(hw_fib->header.StructType != FIB_MAGIC) 
@@ -279,7 +291,7 @@
 	}
 
         if ((*index + 1) == le32_to_cpu(*(q->headers.consumer))) { /* Queue is full */
-		printk(KERN_WARNING "Queue %d full, %d outstanding.\n",
+		printk(KERN_WARNING "Queue %d full, %u outstanding.\n",
 				qid, q->numpending);
 		return 0;
 	} else {
@@ -658,9 +670,8 @@
 			}
 			if (aac_insert_entry(dev, index, AdapHighRespQueue,  (nointr & (int)aac_config.irq_mod)) != 0) {
 			}
-		}
-		else if (hw_fib->header.XferState & NormalPriority) 
-		{
+		} else if (hw_fib->header.XferState & 
+				cpu_to_le32(NormalPriority)) {
 			u32 index;
 
 			if (size) {
@@ -744,22 +755,25 @@
 
 void aac_printf(struct aac_dev *dev, u32 val)
 {
-	int length = val & 0xffff;
-	int level = (val >> 16) & 0xffff;
 	char *cp = dev->printfbuf;
-	
-	/*
-	 *	The size of the printfbuf is set in port.c
-	 *	There is no variable or define for it
-	 */
-	if (length > 255)
-		length = 255;
-	if (cp[length] != 0)
-		cp[length] = 0;
-	if (level == LOG_AAC_HIGH_ERROR)
-		printk(KERN_WARNING "aacraid:%s", cp);
-	else
-		printk(KERN_INFO "aacraid:%s", cp);
+	if (dev->printf_enabled)
+	{
+		int length = val & 0xffff;
+		int level = (val >> 16) & 0xffff;
+		
+		/*
+		 *	The size of the printfbuf is set in port.c
+		 *	There is no variable or define for it
+		 */
+		if (length > 255)
+			length = 255;
+		if (cp[length] != 0)
+			cp[length] = 0;
+		if (level == LOG_AAC_HIGH_ERROR)
+			printk(KERN_WARNING "aacraid:%s", cp);
+		else
+			printk(KERN_INFO "aacraid:%s", cp);
+	}
 	memset(cp, 0,  256);
 }
 
@@ -832,8 +846,8 @@
 			aifcmd = (struct aac_aifcmd *) hw_fib->data;
 			if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) {
 				/* Handle Driver Notify Events */
-				*(u32 *)hw_fib->data = cpu_to_le32(ST_OK);
-				fib_adapter_complete(fib, sizeof(u32));
+				*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
+				fib_adapter_complete(fib, (u16)sizeof(u32));
 			} else {
 				struct list_head *entry;
 				/* The u32 here is important and intended. We are using
@@ -916,7 +930,7 @@
 				/*
 				 *	Set the status of this FIB
 				 */
-				*(u32 *)hw_fib->data = cpu_to_le32(ST_OK);
+				*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
 				fib_adapter_complete(fib, sizeof(u32));
 				spin_unlock_irqrestore(&dev->fib_lock, flagv);
 			}
diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c
index 8480b42..be2e98d 100644
--- a/drivers/scsi/aacraid/dpcsup.c
+++ b/drivers/scsi/aacraid/dpcsup.c
@@ -99,7 +99,7 @@
 			/*
 			 *	Doctor the fib
 			 */
-			*(u32 *)hwfib->data = cpu_to_le32(ST_OK);
+			*(__le32 *)hwfib->data = cpu_to_le32(ST_OK);
 			hwfib->header.XferState |= cpu_to_le32(AdapterProcessed);
 		}
 
@@ -107,7 +107,7 @@
 
 		if (hwfib->header.Command == cpu_to_le16(NuFileSystem))
 		{
-			u32 *pstatus = (u32 *)hwfib->data;
+			__le32 *pstatus = (__le32 *)hwfib->data;
 			if (*pstatus & cpu_to_le32(0xffff0000))
 				*pstatus = cpu_to_le32(ST_OK);
 		}
@@ -205,7 +205,7 @@
 			/*
 			 *	Set the status of this FIB
 			 */
-			*(u32 *)hw_fib->data = cpu_to_le32(ST_OK);
+			*(__le32 *)hw_fib->data = cpu_to_le32(ST_OK);
 			fib_adapter_complete(fib, sizeof(u32));
 			spin_lock_irqsave(q->lock, flags);
 		}		
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 242fa77..f7e9c89 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -215,7 +215,7 @@
  *	Returns a static string describing the device in question
  */
 
-const char *aac_info(struct Scsi_Host *shost)
+static const char *aac_info(struct Scsi_Host *shost)
 {
 	struct aac_dev *dev = (struct aac_dev *)shost->hostdata;
 	return aac_drivers[dev->cardtype].name;
@@ -288,7 +288,7 @@
 	 *	translations ( 64/32, 128/32, 255/63 ).
 	 */
 	buf = scsi_bios_ptable(bdev);
-	if(*(unsigned short *)(buf + 0x40) == cpu_to_le16(0xaa55)) {
+	if(*(__le16 *)(buf + 0x40) == cpu_to_le16(0xaa55)) {
 		struct partition *first = (struct partition * )buf;
 		struct partition *entry = first;
 		int saved_cylinders = param->cylinders;
@@ -347,10 +347,16 @@
 
 static int aac_slave_configure(struct scsi_device *sdev)
 {
+	struct Scsi_Host *host = sdev->host;
+
 	if (sdev->tagged_supported)
 		scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, 128);
 	else
 		scsi_adjust_queue_depth(sdev, 0, 1);
+
+	if (host->max_sectors < AAC_MAX_32BIT_SGBCOUNT)
+		blk_queue_max_segment_size(sdev->request_queue, 65536);
+
 	return 0;
 }
 
@@ -361,14 +367,6 @@
 }
 
 /*
- * XXX: does aac really need no error handling??
- */
-static int aac_eh_abort(struct scsi_cmnd *cmd)
-{
-	return FAILED;
-}
-
-/*
  *	aac_eh_reset	- Reset command handling
  *	@scsi_cmd:	SCSI command block causing the reset
  *
@@ -386,10 +384,13 @@
 					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;
 	}
 	/*
@@ -420,6 +421,7 @@
 		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;
 }
@@ -439,11 +441,11 @@
 static int aac_cfg_open(struct inode *inode, struct file *file)
 {
 	struct aac_dev *aac;
-	unsigned minor = iminor(inode);
+	unsigned minor_number = iminor(inode);
 	int err = -ENODEV;
 
 	list_for_each_entry(aac, &aac_devices, entry) {
-		if (aac->id == minor) {
+		if (aac->id == minor_number) {
 			file->private_data = aac;
 			err = 0;
 			break;
@@ -489,6 +491,7 @@
 	case FSACTL_DELETE_DISK:
 	case FSACTL_FORCE_DELETE_DISK:
 	case FSACTL_GET_CONTAINERS: 
+	case FSACTL_SEND_LARGE_FIB:
 		ret = aac_do_ioctl(dev, cmd, (void __user *)arg);
 		break;
 
@@ -526,6 +529,134 @@
 }
 #endif
 
+static ssize_t aac_show_model(struct class_device *class_dev,
+		char *buf)
+{
+	struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
+	int len;
+
+	len = snprintf(buf, PAGE_SIZE, "%s\n",
+		  aac_drivers[dev->cardtype].model);
+	return len;
+}
+
+static ssize_t aac_show_vendor(struct class_device *class_dev,
+		char *buf)
+{
+	struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
+	int len;
+
+	len = snprintf(buf, PAGE_SIZE, "%s\n",
+		  aac_drivers[dev->cardtype].vname);
+	return len;
+}
+
+static ssize_t aac_show_kernel_version(struct class_device *class_dev,
+		char *buf)
+{
+	struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
+	int len, tmp;
+
+	tmp = le32_to_cpu(dev->adapter_info.kernelrev);
+	len = snprintf(buf, PAGE_SIZE, "%d.%d-%d[%d]\n", 
+	  tmp >> 24, (tmp >> 16) & 0xff, tmp & 0xff,
+	  le32_to_cpu(dev->adapter_info.kernelbuild));
+	return len;
+}
+
+static ssize_t aac_show_monitor_version(struct class_device *class_dev,
+		char *buf)
+{
+	struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
+	int len, tmp;
+
+	tmp = le32_to_cpu(dev->adapter_info.monitorrev);
+	len = snprintf(buf, PAGE_SIZE, "%d.%d-%d[%d]\n", 
+	  tmp >> 24, (tmp >> 16) & 0xff, tmp & 0xff,
+	  le32_to_cpu(dev->adapter_info.monitorbuild));
+	return len;
+}
+
+static ssize_t aac_show_bios_version(struct class_device *class_dev,
+		char *buf)
+{
+	struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
+	int len, tmp;
+
+	tmp = le32_to_cpu(dev->adapter_info.biosrev);
+	len = snprintf(buf, PAGE_SIZE, "%d.%d-%d[%d]\n", 
+	  tmp >> 24, (tmp >> 16) & 0xff, tmp & 0xff,
+	  le32_to_cpu(dev->adapter_info.biosbuild));
+	return len;
+}
+
+static ssize_t aac_show_serial_number(struct class_device *class_dev,
+		char *buf)
+{
+	struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
+	int len = 0;
+
+	if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0)
+		len = snprintf(buf, PAGE_SIZE, "%x\n",
+		  le32_to_cpu(dev->adapter_info.serial[0]));
+	return len;
+}
+
+
+static struct class_device_attribute aac_model = {
+	.attr = {
+		.name = "model",
+		.mode = S_IRUGO,
+	},
+	.show = aac_show_model,
+};
+static struct class_device_attribute aac_vendor = {
+	.attr = {
+		.name = "vendor",
+		.mode = S_IRUGO,
+	},
+	.show = aac_show_vendor,
+};
+static struct class_device_attribute aac_kernel_version = {
+	.attr = {
+		.name = "hba_kernel_version",
+		.mode = S_IRUGO,
+	},
+	.show = aac_show_kernel_version,
+};
+static struct class_device_attribute aac_monitor_version = {
+	.attr = {
+		.name = "hba_monitor_version",
+		.mode = S_IRUGO,
+	},
+	.show = aac_show_monitor_version,
+};
+static struct class_device_attribute aac_bios_version = {
+	.attr = {
+		.name = "hba_bios_version",
+		.mode = S_IRUGO,
+	},
+	.show = aac_show_bios_version,
+};
+static struct class_device_attribute aac_serial_number = {
+	.attr = {
+		.name = "serial_number",
+		.mode = S_IRUGO,
+	},
+	.show = aac_show_serial_number,
+};
+
+static struct class_device_attribute *aac_attrs[] = {
+	&aac_model,
+	&aac_vendor,
+	&aac_kernel_version,
+	&aac_monitor_version,
+	&aac_bios_version,
+	&aac_serial_number,
+	NULL
+};
+
+
 static struct file_operations aac_cfg_fops = {
 	.owner		= THIS_MODULE,
 	.ioctl		= aac_cfg_ioctl,
@@ -538,7 +669,7 @@
 static struct scsi_host_template aac_driver_template = {
 	.module				= THIS_MODULE,
 	.name           		= "AAC",
-	.proc_name			= "aacraid",
+	.proc_name			= AAC_DRIVERNAME,
 	.info           		= aac_info,
 	.ioctl          		= aac_ioctl,
 #ifdef CONFIG_COMPAT
@@ -546,8 +677,8 @@
 #endif
 	.queuecommand   		= aac_queuecommand,
 	.bios_param     		= aac_biosparm,	
+	.shost_attrs			= aac_attrs,
 	.slave_configure		= aac_slave_configure,
-	.eh_abort_handler		= aac_eh_abort,
 	.eh_host_reset_handler		= aac_eh_reset,
 	.can_queue      		= AAC_NUM_IO_FIB,	
 	.this_id        		= 16,
@@ -612,7 +743,7 @@
 	aac->cardtype =  index;
 	INIT_LIST_HEAD(&aac->entry);
 
-	aac->fibs = kmalloc(sizeof(struct fib) * AAC_NUM_FIB, GFP_KERNEL);
+	aac->fibs = kmalloc(sizeof(struct fib) * (shost->can_queue + AAC_NUM_MGT_FIB), GFP_KERNEL);
 	if (!aac->fibs)
 		goto out_free_host;
 	spin_lock_init(&aac->fib_lock);
@@ -632,6 +763,24 @@
 	aac_get_adapter_info(aac);
 
 	/*
+ 	 * Lets override negotiations and drop the maximum SG limit to 34
+ 	 */
+ 	if ((aac_drivers[index].quirks & AAC_QUIRK_34SG) && 
+			(aac->scsi_host_ptr->sg_tablesize > 34)) {
+ 		aac->scsi_host_ptr->sg_tablesize = 34;
+ 		aac->scsi_host_ptr->max_sectors
+ 		  = (aac->scsi_host_ptr->sg_tablesize * 8) + 112;
+ 	}
+
+	/*
+	 * Firware printf works only with older firmware.
+	 */
+	if (aac_drivers[index].quirks & AAC_QUIRK_34SG) 
+		aac->printf_enabled = 1;
+	else
+		aac->printf_enabled = 0;
+ 
+ 	/*
 	 * max channel will be the physical channels plus 1 virtual channel
 	 * all containers are on the virtual channel 0
 	 * physical channels are address by their actual physical number+1
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c
index 1b8ed47..7d68b78 100644
--- a/drivers/scsi/aacraid/rkt.c
+++ b/drivers/scsi/aacraid/rkt.c
@@ -98,7 +98,9 @@
  *	for its	completion.
  */
 
-static int rkt_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
+static int rkt_sync_cmd(struct aac_dev *dev, u32 command,
+	u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
+	u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4)
 {
 	unsigned long start;
 	int ok;
@@ -107,12 +109,12 @@
 	 */
 	rkt_writel(dev, InboundMailbox0, command);
 	/*
-	 *	Write the parameters into Mailboxes 1 - 4
+	 *	Write the parameters into Mailboxes 1 - 6
 	 */
 	rkt_writel(dev, InboundMailbox1, p1);
-	rkt_writel(dev, InboundMailbox2, 0);
-	rkt_writel(dev, InboundMailbox3, 0);
-	rkt_writel(dev, InboundMailbox4, 0);
+	rkt_writel(dev, InboundMailbox2, p2);
+	rkt_writel(dev, InboundMailbox3, p3);
+	rkt_writel(dev, InboundMailbox4, p4);
 	/*
 	 *	Clear the synch command doorbell to start on a clean slate.
 	 */
@@ -169,6 +171,14 @@
 	 */
 	if (status)
 		*status = rkt_readl(dev, IndexRegs.Mailbox[0]);
+	if (r1)
+		*r1 = rkt_readl(dev, IndexRegs.Mailbox[1]);
+	if (r2)
+		*r2 = rkt_readl(dev, IndexRegs.Mailbox[2]);
+	if (r3)
+		*r3 = rkt_readl(dev, IndexRegs.Mailbox[3]);
+	if (r4)
+		*r4 = rkt_readl(dev, IndexRegs.Mailbox[4]);
 	/*
 	 *	Clear the synch command doorbell.
 	 */
@@ -190,8 +200,8 @@
 
 static void aac_rkt_interrupt_adapter(struct aac_dev *dev)
 {
-	u32 ret;
-	rkt_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret);
+	rkt_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0,
+	  NULL, NULL, NULL, NULL, NULL);
 }
 
 /**
@@ -220,7 +230,8 @@
 		rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3);
 		break;
 	case HostShutdown:
-//		rkt_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, &ret);
+//		rkt_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, 0, 0,
+//		  NULL, NULL, NULL, NULL, NULL);
 		break;
 	case FastIo:
 		rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6);
@@ -243,17 +254,11 @@
 
 static void aac_rkt_start_adapter(struct aac_dev *dev)
 {
-	u32 status;
 	struct aac_init *init;
 
 	init = dev->init;
 	init->HostElapsedSeconds = cpu_to_le32(get_seconds());
 	/*
-	 *	Tell the adapter we are back and up and running so it will scan
-	 *	its command queues and enable our interrupts
-	 */
-	dev->irq_mask = (DoorBellPrintfReady | OUTBOUNDDOORBELL_1 | OUTBOUNDDOORBELL_2 | OUTBOUNDDOORBELL_3 | OUTBOUNDDOORBELL_4);
-	/*
 	 *	First clear out all interrupts.  Then enable the one's that we
 	 *	can handle.
 	 */
@@ -263,7 +268,8 @@
 	rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
 
 	// We can only use a 32 bit address here
-	rkt_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &status);
+	rkt_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
+	  0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
 }
 
 /**
@@ -288,8 +294,8 @@
 	if (status & KERNEL_PANIC) {
 		char * buffer;
 		struct POSTSTATUS {
-			u32 Post_Command;
-			u32 Post_Address;
+			__le32 Post_Command;
+			__le32 Post_Address;
 		} * post;
 		dma_addr_t paddr, baddr;
 		int ret;
@@ -310,7 +316,8 @@
 		post->Post_Command = cpu_to_le32(COMMAND_POST_RESULTS);
                 post->Post_Address = cpu_to_le32(baddr);
                 rkt_writel(dev, MUnit.IMRx[0], paddr);
-                rkt_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, &status);
+                rkt_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, 0, 0, 0, 0, 0,
+		  NULL, NULL, NULL, NULL, NULL);
 		pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
 		  post, paddr);
                 if ((buffer[0] == '0') && (buffer[1] == 'x')) {
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index 630b99e..1ff25f4 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -63,7 +63,7 @@
 	{
 		bellbits = rx_readl(dev, OutboundDoorbellReg);
 		if (bellbits & DoorBellPrintfReady) {
-			aac_printf(dev, le32_to_cpu(rx_readl (dev, IndexRegs.Mailbox[5])));
+			aac_printf(dev, rx_readl(dev, IndexRegs.Mailbox[5]));
 			rx_writel(dev, MUnit.ODR,DoorBellPrintfReady);
 			rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
 		}
@@ -98,7 +98,9 @@
  *	for its	completion.
  */
 
-static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
+static int rx_sync_cmd(struct aac_dev *dev, u32 command,
+	u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
+	u32 *status, u32 * r1, u32 * r2, u32 * r3, u32 * r4)
 {
 	unsigned long start;
 	int ok;
@@ -107,12 +109,12 @@
 	 */
 	rx_writel(dev, InboundMailbox0, command);
 	/*
-	 *	Write the parameters into Mailboxes 1 - 4
+	 *	Write the parameters into Mailboxes 1 - 6
 	 */
 	rx_writel(dev, InboundMailbox1, p1);
-	rx_writel(dev, InboundMailbox2, 0);
-	rx_writel(dev, InboundMailbox3, 0);
-	rx_writel(dev, InboundMailbox4, 0);
+	rx_writel(dev, InboundMailbox2, p2);
+	rx_writel(dev, InboundMailbox3, p3);
+	rx_writel(dev, InboundMailbox4, p4);
 	/*
 	 *	Clear the synch command doorbell to start on a clean slate.
 	 */
@@ -120,7 +122,7 @@
 	/*
 	 *	Disable doorbell interrupts
 	 */
-	rx_writeb(dev, MUnit.OIMR, dev->OIMR |= 0x04);
+	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
 	/*
 	 *	Force the completion of the mask register write before issuing
 	 *	the interrupt.
@@ -169,6 +171,14 @@
 	 */
 	if (status)
 		*status = rx_readl(dev, IndexRegs.Mailbox[0]);
+	if (r1)
+		*r1 = rx_readl(dev, IndexRegs.Mailbox[1]);
+	if (r2)
+		*r2 = rx_readl(dev, IndexRegs.Mailbox[2]);
+	if (r3)
+		*r3 = rx_readl(dev, IndexRegs.Mailbox[3]);
+	if (r4)
+		*r4 = rx_readl(dev, IndexRegs.Mailbox[4]);
 	/*
 	 *	Clear the synch command doorbell.
 	 */
@@ -190,8 +200,7 @@
 
 static void aac_rx_interrupt_adapter(struct aac_dev *dev)
 {
-	u32 ret;
-	rx_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret);
+	rx_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
 }
 
 /**
@@ -220,7 +229,8 @@
 		rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3);
 		break;
 	case HostShutdown:
-//		rx_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, &ret);
+//		rx_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, 0, 0,
+//		  NULL, NULL, NULL, NULL, NULL);
 		break;
 	case FastIo:
 		rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6);
@@ -243,17 +253,11 @@
 
 static void aac_rx_start_adapter(struct aac_dev *dev)
 {
-	u32 status;
 	struct aac_init *init;
 
 	init = dev->init;
 	init->HostElapsedSeconds = cpu_to_le32(get_seconds());
 	/*
-	 *	Tell the adapter we are back and up and running so it will scan
-	 *	its command queues and enable our interrupts
-	 */
-	dev->irq_mask = (DoorBellPrintfReady | OUTBOUNDDOORBELL_1 | OUTBOUNDDOORBELL_2 | OUTBOUNDDOORBELL_3 | OUTBOUNDDOORBELL_4);
-	/*
 	 *	First clear out all interrupts.  Then enable the one's that we
 	 *	can handle.
 	 */
@@ -263,7 +267,8 @@
 	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
 
 	// We can only use a 32 bit address here
-	rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &status);
+	rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
+	  0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
 }
 
 /**
@@ -288,8 +293,8 @@
 	if (status & KERNEL_PANIC) {
 		char * buffer;
 		struct POSTSTATUS {
-			u32 Post_Command;
-			u32 Post_Address;
+			__le32 Post_Command;
+			__le32 Post_Address;
 		} * post;
 		dma_addr_t paddr, baddr;
 		int ret;
@@ -310,7 +315,8 @@
 		post->Post_Command = cpu_to_le32(COMMAND_POST_RESULTS);
 		post->Post_Address = cpu_to_le32(baddr);
 		rx_writel(dev, MUnit.IMRx[0], paddr);
-		rx_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, &status);
+		rx_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, 0, 0, 0, 0, 0,
+		  NULL, NULL, NULL, NULL, NULL);
 		pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
 		  post, paddr);
 		if ((buffer[0] == '0') && (buffer[1] == 'x')) {
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index bd6c307..0680249 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -89,7 +89,7 @@
  *	Notify the adapter of an event
  */
  
-void aac_sa_notify_adapter(struct aac_dev *dev, u32 event)
+static void aac_sa_notify_adapter(struct aac_dev *dev, u32 event)
 {
 	switch (event) {
 
@@ -106,7 +106,10 @@
 		sa_writew(dev, DoorbellReg_s,DOORBELL_3);
 		break;
 	case HostShutdown:
-		//sa_sync_cmd(dev, HOST_CRASHING, 0, &ret);
+		/*
+		sa_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, 0, 0,
+		NULL, NULL, NULL, NULL, NULL);
+		*/
 		break;
 	case FastIo:
 		sa_writew(dev, DoorbellReg_s,DOORBELL_6);
@@ -132,7 +135,9 @@
  *	for its	completion.
  */
 
-static int sa_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *ret)
+static int sa_sync_cmd(struct aac_dev *dev, u32 command, 
+		u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
+		u32 *ret, u32 *r1, u32 *r2, u32 *r3, u32 *r4)
 {
 	unsigned long start;
  	int ok;
@@ -144,9 +149,10 @@
 	 *	Write the parameters into Mailboxes 1 - 4
 	 */
 	sa_writel(dev, Mailbox1, p1);
-	sa_writel(dev, Mailbox2, 0);
-	sa_writel(dev, Mailbox3, 0);
-	sa_writel(dev, Mailbox4, 0);
+	sa_writel(dev, Mailbox2, p2);
+	sa_writel(dev, Mailbox3, p3);
+	sa_writel(dev, Mailbox4, p4);
+
 	/*
 	 *	Clear the synch command doorbell to start on a clean slate.
 	 */
@@ -188,6 +194,14 @@
 	 */
 	if (ret)
 		*ret = sa_readl(dev, Mailbox0);
+	if (r1)
+		*r1 = sa_readl(dev, Mailbox1);
+	if (r2)
+		*r2 = sa_readl(dev, Mailbox2);
+	if (r3)
+		*r3 = sa_readl(dev, Mailbox3);
+	if (r4)
+		*r4 = sa_readl(dev, Mailbox4);
 	return 0;
 }
 
@@ -201,7 +215,8 @@
 static void aac_sa_interrupt_adapter (struct aac_dev *dev)
 {
 	u32 ret;
-	sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret);
+	sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0,
+			&ret, NULL, NULL, NULL, NULL);
 }
 
 /**
@@ -230,10 +245,12 @@
 	 *	First clear out all interrupts.  Then enable the one's that 
 	 *	we can handle.
 	 */
-	sa_writew(dev, SaDbCSR.PRISETIRQMASK, cpu_to_le16(0xffff));
+	sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
 	sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4));
 	/* We can only use a 32 bit address here */
-	sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &ret);
+	sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, 
+			(u32)(ulong)dev->init_pa, 0, 0, 0, 0, 0,
+			&ret, NULL, NULL, NULL, NULL);
 }
 
 /**
diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c
index 88d119f..630b115 100644
--- a/drivers/scsi/aha152x.c
+++ b/drivers/scsi/aha152x.c
@@ -1225,8 +1225,6 @@
 	}
 
 	DO_UNLOCK(flags);
-
-	spin_lock_irq(shpnt->host_lock);
 	return ret;
 }
 
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index e9920a0..9ec4641 100644
--- a/drivers/scsi/aha1542.c
+++ b/drivers/scsi/aha1542.c
@@ -1348,20 +1348,6 @@
 	return 0;
 }
 
-static int aha1542_abort(Scsi_Cmnd * SCpnt)
-{
-
-	/*
-	 * The abort command does not leave the device in a clean state where
-	 *  it is available to be used again.  Until this gets worked out, we
-	 * will leave it commented out.  
-	 */
-
-	printk(KERN_ERR "aha1542.c: Unable to abort command for target %d\n",
-	       SCpnt->device->id);
-	return FAILED;
-}
-
 /*
  * This is a device reset.  This is handled by sending a special command
  * to the device.
@@ -1478,8 +1464,8 @@
 	 * check for timeout, and if we are doing something like this
 	 * we are pretty desperate anyways.
 	 */
-	spin_unlock_irq(SCpnt->device->host->host_lock);
 	ssleep(4);
+
 	spin_lock_irq(SCpnt->device->host->host_lock);
 
 	WAIT(STATUS(SCpnt->device->host->io_port),
@@ -1517,9 +1503,11 @@
 		}
 	}
 
+	spin_unlock_irq(SCpnt->device->host->host_lock);
 	return SUCCESS;
 
 fail:
+	spin_unlock_irq(SCpnt->device->host->host_lock);
 	return FAILED;
 }
 
@@ -1542,7 +1530,6 @@
 	 * check for timeout, and if we are doing something like this
 	 * we are pretty desperate anyways.
 	 */
-	spin_unlock_irq(SCpnt->device->host->host_lock);
 	ssleep(4);
 	spin_lock_irq(SCpnt->device->host->host_lock);
 
@@ -1586,9 +1573,11 @@
 		}
 	}
 
+	spin_unlock_irq(SCpnt->device->host->host_lock);
 	return SUCCESS;
 
 fail:
+	spin_unlock_irq(SCpnt->device->host->host_lock);
 	return FAILED;
 }
 
@@ -1817,7 +1806,6 @@
 	.detect			= aha1542_detect,
 	.release		= aha1542_release,
 	.queuecommand		= aha1542_queuecommand,
-	.eh_abort_handler	= aha1542_abort,
 	.eh_device_reset_handler= aha1542_dev_reset,
 	.eh_bus_reset_handler	= aha1542_bus_reset,
 	.eh_host_reset_handler	= aha1542_host_reset,
diff --git a/drivers/scsi/aha1542.h b/drivers/scsi/aha1542.h
index c402351..3821ee1 100644
--- a/drivers/scsi/aha1542.h
+++ b/drivers/scsi/aha1542.h
@@ -133,7 +133,6 @@
 
 static int aha1542_detect(Scsi_Host_Template *);
 static int aha1542_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-static int aha1542_abort(Scsi_Cmnd * SCpnt);
 static int aha1542_bus_reset(Scsi_Cmnd * SCpnt);
 static int aha1542_dev_reset(Scsi_Cmnd * SCpnt);
 static int aha1542_host_reset(Scsi_Cmnd * SCpnt);
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index fc5263c..9a547ca 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -39,7 +39,7 @@
 #include <asm/io.h>
 
 #define DRV_NAME	"ahci"
-#define DRV_VERSION	"1.00"
+#define DRV_VERSION	"1.01"
 
 
 enum {
@@ -50,6 +50,7 @@
 	AHCI_CMD_SLOT_SZ	= 32 * 32,
 	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_RX_FIS_SZ,
@@ -134,6 +135,9 @@
 	PORT_CMD_ICC_ACTIVE	= (0x1 << 28), /* Put i/f in active state */
 	PORT_CMD_ICC_PARTIAL	= (0x2 << 28), /* Put i/f in partial state */
 	PORT_CMD_ICC_SLUMBER	= (0x6 << 28), /* Put i/f in slumber state */
+
+	/* hpriv->flags bits */
+	AHCI_FLAG_MSI		= (1 << 0),
 };
 
 struct ahci_cmd_hdr {
@@ -183,6 +187,7 @@
 static u8 ahci_check_status(struct ata_port *ap);
 static u8 ahci_check_err(struct ata_port *ap);
 static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
+static void ahci_remove_one (struct pci_dev *pdev);
 
 static Scsi_Host_Template ahci_sht = {
 	.module			= THIS_MODULE,
@@ -272,7 +277,7 @@
 	.name			= DRV_NAME,
 	.id_table		= ahci_pci_tbl,
 	.probe			= ahci_init_one,
-	.remove			= ata_pci_remove_one,
+	.remove			= ahci_remove_one,
 };
 
 
@@ -506,7 +511,8 @@
 
 static void ahci_qc_prep(struct ata_queued_cmd *qc)
 {
-	struct ahci_port_priv *pp = qc->ap->private_data;
+	struct ata_port *ap = qc->ap;
+	struct ahci_port_priv *pp = ap->private_data;
 	u32 opts;
 	const u32 cmd_fis_len = 5; /* five dwords */
 
@@ -518,18 +524,8 @@
 	opts = (qc->n_elem << 16) | cmd_fis_len;
 	if (qc->tf.flags & ATA_TFLAG_WRITE)
 		opts |= AHCI_CMD_WRITE;
-
-	switch (qc->tf.protocol) {
-	case ATA_PROT_ATAPI:
-	case ATA_PROT_ATAPI_NODATA:
-	case ATA_PROT_ATAPI_DMA:
+	if (is_atapi_taskfile(&qc->tf))
 		opts |= AHCI_CMD_ATAPI;
-		break;
-
-	default:
-		/* do nothing */
-		break;
-	}
 
 	pp->cmd_slot[0].opts = cpu_to_le32(opts);
 	pp->cmd_slot[0].status = 0;
@@ -541,6 +537,10 @@
 	 * a SATA Register - Host to Device command FIS.
 	 */
 	ata_tf_to_fis(&qc->tf, pp->cmd_tbl, 0);
+	if (opts & AHCI_CMD_ATAPI) {
+		memset(pp->cmd_tbl + AHCI_CMD_TBL_CDB, 0, 32);
+		memcpy(pp->cmd_tbl + AHCI_CMD_TBL_CDB, qc->cdb, ap->cdb_len);
+	}
 
 	if (!(qc->flags & ATA_QCFLAG_DMAMAP))
 		return;
@@ -795,8 +795,6 @@
 				return rc;
 			}
 		}
-
-		hpriv->flags |= HOST_CAP_64;
 	} else {
 		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
 		if (rc) {
@@ -879,15 +877,19 @@
 }
 
 /* move to PCI layer, integrate w/ MSI stuff */
-static void pci_enable_intx(struct pci_dev *pdev)
+static void pci_intx(struct pci_dev *pdev, int enable)
 {
-	u16 pci_command;
+	u16 pci_command, new;
 
 	pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
-	if (pci_command & PCI_COMMAND_INTX_DISABLE) {
-		pci_command &= ~PCI_COMMAND_INTX_DISABLE;
+
+	if (enable)
+		new = pci_command & ~PCI_COMMAND_INTX_DISABLE;
+	else
+		new = pci_command | PCI_COMMAND_INTX_DISABLE;
+
+	if (new != pci_command)
 		pci_write_config_word(pdev, PCI_COMMAND, pci_command);
-	}
 }
 
 static void ahci_print_info(struct ata_probe_ent *probe_ent)
@@ -969,7 +971,7 @@
 	unsigned long base;
 	void *mmio_base;
 	unsigned int board_idx = (unsigned int) ent->driver_data;
-	int pci_dev_busy = 0;
+	int have_msi, pci_dev_busy = 0;
 	int rc;
 
 	VPRINTK("ENTER\n");
@@ -987,12 +989,17 @@
 		goto err_out;
 	}
 
-	pci_enable_intx(pdev);
+	if (pci_enable_msi(pdev) == 0)
+		have_msi = 1;
+	else {
+		pci_intx(pdev, 1);
+		have_msi = 0;
+	}
 
 	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
 	if (probe_ent == NULL) {
 		rc = -ENOMEM;
-		goto err_out_regions;
+		goto err_out_msi;
 	}
 
 	memset(probe_ent, 0, sizeof(*probe_ent));
@@ -1025,6 +1032,9 @@
 	probe_ent->mmio_base = mmio_base;
 	probe_ent->private_data = hpriv;
 
+	if (have_msi)
+		hpriv->flags |= AHCI_FLAG_MSI;
+
 	/* initialize adapter */
 	rc = ahci_host_init(probe_ent);
 	if (rc)
@@ -1044,7 +1054,11 @@
 	iounmap(mmio_base);
 err_out_free_ent:
 	kfree(probe_ent);
-err_out_regions:
+err_out_msi:
+	if (have_msi)
+		pci_disable_msi(pdev);
+	else
+		pci_intx(pdev, 0);
 	pci_release_regions(pdev);
 err_out:
 	if (!pci_dev_busy)
@@ -1052,6 +1066,42 @@
 	return rc;
 }
 
+static void ahci_remove_one (struct pci_dev *pdev)
+{
+	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);
+	}
+
+	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];
+
+		ata_scsi_release(ap->host);
+		scsi_host_put(ap->host);
+	}
+
+	host_set->ops->host_stop(host_set);
+	kfree(host_set);
+
+	if (have_msi)
+		pci_disable_msi(pdev);
+	else
+		pci_intx(pdev, 0);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	dev_set_drvdata(dev, NULL);
+}
 
 static int __init ahci_init(void)
 {
diff --git a/drivers/scsi/aic7xxx/aic7770_osm.c b/drivers/scsi/aic7xxx/aic7770_osm.c
index 682ca0b..d4ed5e9 100644
--- a/drivers/scsi/aic7xxx/aic7770_osm.c
+++ b/drivers/scsi/aic7xxx/aic7770_osm.c
@@ -44,109 +44,6 @@
 #include <linux/device.h>
 #include <linux/eisa.h>
 
-#define EISA_MFCTR_CHAR0(ID) (char)(((ID>>26) & 0x1F) | '@')  /* Bits 26-30 */
-#define EISA_MFCTR_CHAR1(ID) (char)(((ID>>21) & 0x1F) | '@')  /* Bits 21-25 */
-#define EISA_MFCTR_CHAR2(ID) (char)(((ID>>16) & 0x1F) | '@')  /* Bits 16-20 */
-#define EISA_PRODUCT_ID(ID)  (short)((ID>>4)  & 0xFFF)        /* Bits  4-15 */
-#define EISA_REVISION_ID(ID) (uint8_t)(ID & 0x0F)             /* Bits  0-3  */
-
-static int aic7770_eisa_dev_probe(struct device *dev);
-static int aic7770_eisa_dev_remove(struct device *dev);
-static struct eisa_driver aic7770_driver = {
-	.driver = {
-		.name   = "aic7xxx",
-		.probe  = aic7770_eisa_dev_probe,
-		.remove = aic7770_eisa_dev_remove,
-	}
-};
-
-typedef  struct device *aic7770_dev_t;
-
-static int aic7770_linux_config(struct aic7770_identity *entry,
-				aic7770_dev_t dev, u_int eisaBase);
-
-int
-ahc_linux_eisa_init(void)
-{
-	struct eisa_device_id *eid;
-	struct aic7770_identity *id;
-	int i;
-
-	if (aic7xxx_probe_eisa_vl == 0)
-		return -ENODEV;
-
-	/*
-	 * Linux requires the EISA IDs to be specified in
-	 * the EISA ID string format.  Perform the conversion
-	 * and setup a table with a NUL terminal entry.
-	 */
-	aic7770_driver.id_table = malloc(sizeof(struct eisa_device_id) *
-					 (ahc_num_aic7770_devs + 1),
-					 M_DEVBUF, M_NOWAIT);
-	if (aic7770_driver.id_table == NULL)
-		return -ENOMEM;
-
-	for (eid = (struct eisa_device_id *)aic7770_driver.id_table,
-	     id = aic7770_ident_table, i = 0;
-	     i < ahc_num_aic7770_devs; eid++, id++, i++) {
-
-		sprintf(eid->sig, "%c%c%c%03X%01X",
-			EISA_MFCTR_CHAR0(id->full_id),
-			EISA_MFCTR_CHAR1(id->full_id),
-			EISA_MFCTR_CHAR2(id->full_id),
-			EISA_PRODUCT_ID(id->full_id),
-			EISA_REVISION_ID(id->full_id));
-		eid->driver_data = i;
-	}
-	eid->sig[0] = 0;
-
-	return eisa_driver_register(&aic7770_driver);
-}
-
-void
-ahc_linux_eisa_exit(void)
-{
-	if(aic7xxx_probe_eisa_vl != 0 && aic7770_driver.id_table != NULL) {
-		eisa_driver_unregister(&aic7770_driver);
-		free(aic7770_driver.id_table, M_DEVBUF);
-	}
-}
-
-static int
-aic7770_linux_config(struct aic7770_identity *entry, aic7770_dev_t dev,
-		     u_int eisaBase)
-{
-	struct	ahc_softc *ahc;
-	char	buf[80];
-	char   *name;
-	int	error;
-
-	/*
-	 * Allocate a softc for this card and
-	 * set it up for attachment by our
-	 * common detect routine.
-	 */
-	sprintf(buf, "ahc_eisa:%d", eisaBase >> 12);
-	name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
-	if (name == NULL)
-		return (ENOMEM);
-	strcpy(name, buf);
-	ahc = ahc_alloc(&aic7xxx_driver_template, name);
-	if (ahc == NULL)
-		return (ENOMEM);
-	error = aic7770_config(ahc, entry, eisaBase);
-	if (error != 0) {
-		ahc->bsh.ioport = 0;
-		ahc_free(ahc);
-		return (error);
-	}
-
-	dev->driver_data = (void *)ahc;
-	if (aic7xxx_detect_complete)
-		error = ahc_linux_register_host(ahc, &aic7xxx_driver_template);
-	return (error);
-}
-
 int
 aic7770_map_registers(struct ahc_softc *ahc, u_int port)
 {
@@ -178,37 +75,79 @@
 }
 
 static int
-aic7770_eisa_dev_probe(struct device *dev)
+aic7770_probe(struct device *dev)
 {
-	struct eisa_device *edev;
+	struct eisa_device *edev = to_eisa_device(dev);
+	u_int eisaBase = edev->base_addr+AHC_EISA_SLOT_OFFSET;
+	struct	ahc_softc *ahc;
+	char	buf[80];
+	char   *name;
+	int	error;
 
-	edev = to_eisa_device(dev);
-	return (aic7770_linux_config(aic7770_ident_table + edev->id.driver_data,
-				    dev, edev->base_addr+AHC_EISA_SLOT_OFFSET));
+	sprintf(buf, "ahc_eisa:%d", eisaBase >> 12);
+	name = malloc(strlen(buf) + 1, M_DEVBUF, M_NOWAIT);
+	if (name == NULL)
+		return (ENOMEM);
+	strcpy(name, buf);
+	ahc = ahc_alloc(&aic7xxx_driver_template, name);
+	if (ahc == NULL)
+		return (ENOMEM);
+	error = aic7770_config(ahc, aic7770_ident_table + edev->id.driver_data,
+			       eisaBase);
+	if (error != 0) {
+		ahc->bsh.ioport = 0;
+		ahc_free(ahc);
+		return (error);
+	}
+
+ 	dev_set_drvdata(dev, ahc);
+
+	if (aic7xxx_detect_complete)
+		error = ahc_linux_register_host(ahc, &aic7xxx_driver_template);
+	return (error);
 }
 
 static int
-aic7770_eisa_dev_remove(struct device *dev)
+aic7770_remove(struct device *dev)
 {
-	struct ahc_softc *ahc;
-	u_long l;
+	struct ahc_softc *ahc = dev_get_drvdata(dev);
+	u_long s;
 
-	/*
-	 * We should be able to just perform
-	 * the free directly, but check our
-	 * list for extra sanity.
-	 */
-	ahc_list_lock(&l);
-	ahc = ahc_find_softc((struct ahc_softc *)dev->driver_data);
-	if (ahc != NULL) {
-		u_long s;
+	ahc_lock(ahc, &s);
+	ahc_intr_enable(ahc, FALSE);
+	ahc_unlock(ahc, &s);
 
-		ahc_lock(ahc, &s);
-		ahc_intr_enable(ahc, FALSE);
-		ahc_unlock(ahc, &s);
-		ahc_free(ahc);
+	ahc_free(ahc);
+	return 0;
+}
+ 
+static struct eisa_device_id aic7770_ids[] = {
+	{ "ADP7771", 0 }, /* AHA 274x */
+	{ "ADP7756", 1 }, /* AHA 284x BIOS enabled */
+	{ "ADP7757", 2 }, /* AHA 284x BIOS disabled */
+	{ "ADP7782", 3 }, /* AHA 274x Olivetti OEM */
+	{ "ADP7783", 4 }, /* AHA 274x Olivetti OEM (Differential) */
+	{ "ADP7770", 5 }, /* AIC7770 generic */
+	{ "" }
+};
+  
+static struct eisa_driver aic7770_driver = {
+	.id_table	= aic7770_ids,
+	.driver = {
+		.name   = "aic7xxx",
+		.probe  = aic7770_probe,
+		.remove = aic7770_remove,
 	}
-	ahc_list_unlock(&l);
-
-	return (0);
+};
+  
+int
+ahc_linux_eisa_init(void)
+{
+	return eisa_driver_register(&aic7770_driver);
+}
+  
+void
+ahc_linux_eisa_exit(void)
+{
+	eisa_driver_unregister(&aic7770_driver);
 }
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
index 7c02b7d..5f526dd 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c
@@ -1511,17 +1511,17 @@
 		       ahd_name(ahd), cmd->device->channel, cmd->device->id,
 		       cmd->device->lun, cmd);
 #endif
-	ahd_midlayer_entrypoint_lock(ahd, &s);
+	ahd_lock(ahd, &s);
 
 	dev = ahd_linux_get_device(ahd, cmd->device->channel, cmd->device->id,
 				   cmd->device->lun, /*alloc*/FALSE);
 	if (dev == NULL) {
-		ahd_midlayer_entrypoint_unlock(ahd, &s);
+		ahd_unlock(ahd, &s);
 		kfree(recovery_cmd);
 		return (FAILED);
 	}
 	if ((scb = ahd_get_scb(ahd, AHD_NEVER_COL_IDX)) == NULL) {
-		ahd_midlayer_entrypoint_unlock(ahd, &s);
+		ahd_unlock(ahd, &s);
 		kfree(recovery_cmd);
 		return (FAILED);
 	}
@@ -1570,7 +1570,7 @@
 	spin_lock_irq(&ahd->platform_data->spin_lock);
 	ahd_schedule_runq(ahd);
 	ahd_linux_run_complete_queue(ahd);
-	ahd_midlayer_entrypoint_unlock(ahd, &s);
+	ahd_unlock(ahd, &s);
 	printf("%s: Device reset returning 0x%x\n", ahd_name(ahd), retval);
 	return (retval);
 }
@@ -1591,11 +1591,11 @@
 		printf("%s: Bus reset called for cmd %p\n",
 		       ahd_name(ahd), cmd);
 #endif
-	ahd_midlayer_entrypoint_lock(ahd, &s);
+	ahd_lock(ahd, &s);
 	found = ahd_reset_channel(ahd, cmd->device->channel + 'A',
 				  /*initiate reset*/TRUE);
 	ahd_linux_run_complete_queue(ahd);
-	ahd_midlayer_entrypoint_unlock(ahd, &s);
+	ahd_unlock(ahd, &s);
 
 	if (bootverbose)
 		printf("%s: SCSI bus reset delivered. "
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index 605f92b..7823e52 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -112,23 +112,6 @@
 #define ahd_le32toh(x)	le32_to_cpu(x)
 #define ahd_le64toh(x)	le64_to_cpu(x)
 
-#ifndef LITTLE_ENDIAN
-#define LITTLE_ENDIAN 1234
-#endif
-
-#ifndef BIG_ENDIAN
-#define BIG_ENDIAN 4321
-#endif
-
-#ifndef BYTE_ORDER
-#if defined(__BIG_ENDIAN)
-#define BYTE_ORDER BIG_ENDIAN
-#endif
-#if defined(__LITTLE_ENDIAN)
-#define BYTE_ORDER LITTLE_ENDIAN
-#endif
-#endif /* BYTE_ORDER */
-
 /************************* Configuration Data *********************************/
 extern uint32_t aic79xx_allow_memio;
 extern int aic79xx_detect_complete;
diff --git a/drivers/scsi/aic7xxx/aic7xxx.h b/drivers/scsi/aic7xxx/aic7xxx.h
index 8ff16fd..0948d50 100644
--- a/drivers/scsi/aic7xxx/aic7xxx.h
+++ b/drivers/scsi/aic7xxx/aic7xxx.h
@@ -346,7 +346,6 @@
 					  * controller.
 					  */
 	AHC_NEWEEPROM_FMT     = 0x4000,
-	AHC_RESOURCE_SHORTAGE = 0x8000,
 	AHC_TQINFIFO_BLOCKED  = 0x10000,  /* Blocked waiting for ATIOs */
 	AHC_INT50_SPEEDFLEX   = 0x20000,  /*
 					   * Internal 50pin connector
@@ -1200,7 +1199,6 @@
 int			 ahc_suspend(struct ahc_softc *ahc); 
 int			 ahc_resume(struct ahc_softc *ahc);
 void			 ahc_softc_insert(struct ahc_softc *);
-struct ahc_softc	*ahc_find_softc(struct ahc_softc *ahc);
 void			 ahc_set_unit(struct ahc_softc *, int);
 void			 ahc_set_name(struct ahc_softc *, char *);
 void			 ahc_alloc_scbs(struct ahc_softc *ahc);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c
index 9a6b4a5..8a2bb6f 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_core.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_core.c
@@ -3934,22 +3934,6 @@
 	ahc->init_level++;
 }
 
-/*
- * Verify that the passed in softc pointer is for a
- * controller that is still configured.
- */
-struct ahc_softc *
-ahc_find_softc(struct ahc_softc *ahc)
-{
-	struct ahc_softc *list_ahc;
-
-	TAILQ_FOREACH(list_ahc, &ahc_tailq, links) {
-		if (list_ahc == ahc)
-			return (ahc);
-	}
-	return (NULL);
-}
-
 void
 ahc_set_unit(struct ahc_softc *ahc, int unit)
 {
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
index c13e563..b89094d 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c
@@ -122,8 +122,6 @@
 #include "aic7xxx_osm.h"
 #include "aic7xxx_inline.h"
 #include <scsi/scsicam.h>
-#include <scsi/scsi_transport.h>
-#include <scsi/scsi_transport_spi.h>
 
 static struct scsi_transport_template *ahc_linux_transport_template = NULL;
 
@@ -332,22 +330,6 @@
 static uint32_t aic7xxx_pci_parity = ~0;
 
 /*
- * Certain newer motherboards have put new PCI based devices into the
- * IO spaces that used to typically be occupied by VLB or EISA cards.
- * This overlap can cause these newer motherboards to lock up when scanned
- * for older EISA and VLB devices.  Setting this option to non-0 will
- * cause the driver to skip scanning for any VLB or EISA controllers and
- * only support the PCI controllers.  NOTE: this means that if the kernel
- * os compiled with PCI support disabled, then setting this to non-0
- * would result in never finding any devices :)
- */
-#ifndef CONFIG_AIC7XXX_PROBE_EISA_VL
-uint32_t aic7xxx_probe_eisa_vl;
-#else
-uint32_t aic7xxx_probe_eisa_vl = ~0;
-#endif
-
-/*
  * There are lots of broken chipsets in the world.  Some of them will
  * violate the PCI spec when we issue byte sized memory writes to our
  * controller.  I/O mapped register access, if allowed by the given
@@ -423,7 +405,7 @@
 );
 
 static void ahc_linux_handle_scsi_status(struct ahc_softc *,
-					 struct ahc_linux_device *,
+					 struct scsi_device *,
 					 struct scb *);
 static void ahc_linux_queue_cmd_complete(struct ahc_softc *ahc,
 					 struct scsi_cmnd *cmd);
@@ -434,17 +416,7 @@
 static void ahc_linux_initialize_scsi_bus(struct ahc_softc *ahc);
 static u_int ahc_linux_user_tagdepth(struct ahc_softc *ahc,
 				     struct ahc_devinfo *devinfo);
-static void ahc_linux_device_queue_depth(struct ahc_softc *ahc,
-					 struct ahc_linux_device *dev);
-static struct ahc_linux_target*	ahc_linux_alloc_target(struct ahc_softc*,
-						       u_int, u_int);
-static void			ahc_linux_free_target(struct ahc_softc*,
-						      struct ahc_linux_target*);
-static struct ahc_linux_device*	ahc_linux_alloc_device(struct ahc_softc*,
-						       struct ahc_linux_target*,
-						       u_int);
-static void			ahc_linux_free_device(struct ahc_softc*,
-						      struct ahc_linux_device*);
+static void ahc_linux_device_queue_depth(struct scsi_device *);
 static int ahc_linux_run_command(struct ahc_softc*,
 				 struct ahc_linux_device *,
 				 struct scsi_cmnd *);
@@ -454,32 +426,12 @@
 static int  ahc_linux_next_unit(void);
 
 /********************************* Inlines ************************************/
-static __inline struct ahc_linux_device*
-		     ahc_linux_get_device(struct ahc_softc *ahc, u_int channel,
-					  u_int target, u_int lun);
 static __inline void ahc_linux_unmap_scb(struct ahc_softc*, struct scb*);
 
 static __inline int ahc_linux_map_seg(struct ahc_softc *ahc, struct scb *scb,
 		 		      struct ahc_dma_seg *sg,
 				      dma_addr_t addr, bus_size_t len);
 
-static __inline struct ahc_linux_device*
-ahc_linux_get_device(struct ahc_softc *ahc, u_int channel, u_int target,
-		     u_int lun)
-{
-	struct ahc_linux_target *targ;
-	struct ahc_linux_device *dev;
-	u_int target_offset;
-
-	target_offset = target;
-	if (channel != 0)
-		target_offset += 8;
-	targ = ahc->platform_data->targets[target_offset];
-	BUG_ON(targ == NULL);
-	dev = targ->devices[lun];
-	return dev;
-}
-
 static __inline void
 ahc_linux_unmap_scb(struct ahc_softc *ahc, struct scb *scb)
 {
@@ -533,17 +485,6 @@
 	int     found = 0;
 
 	/*
-	 * Sanity checking of Linux SCSI data structures so
-	 * that some of our hacks^H^H^H^H^Hassumptions aren't
-	 * violated.
-	 */
-	if (offsetof(struct ahc_cmd_internal, end)
-	  > offsetof(struct scsi_cmnd, host_scribble)) {
-		printf("ahc_linux_detect: SCSI data structures changed.\n");
-		printf("ahc_linux_detect: Unable to attach\n");
-		return (0);
-	}
-	/*
 	 * If we've been passed any parameters, process them now.
 	 */
 	if (aic7xxx)
@@ -611,7 +552,7 @@
 ahc_linux_queue(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
 {
 	struct	 ahc_softc *ahc;
-	struct	 ahc_linux_device *dev;
+	struct	 ahc_linux_device *dev = scsi_transport_device_data(cmd->device);
 
 	ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
 
@@ -629,132 +570,177 @@
 	if (ahc->platform_data->qfrozen != 0)
 		return SCSI_MLQUEUE_HOST_BUSY;
 
-	dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id,
-				   cmd->device->lun);
-	BUG_ON(dev == NULL);
-
 	cmd->result = CAM_REQ_INPROG << 16;
 
 	return ahc_linux_run_command(ahc, dev, cmd);
 }
 
-static int
-ahc_linux_slave_alloc(struct scsi_device *device)
+static inline struct scsi_target **
+ahc_linux_target_in_softc(struct scsi_target *starget)
 {
-	struct	ahc_softc *ahc;
-	struct ahc_linux_target *targ;
-	struct scsi_target *starget = device->sdev_target;
-	struct ahc_linux_device *dev;
+	struct	ahc_softc *ahc =
+		*((struct ahc_softc **)dev_to_shost(&starget->dev)->hostdata);
 	unsigned int target_offset;
-	unsigned long flags;
-	int retval = -ENOMEM;
 
 	target_offset = starget->id;
 	if (starget->channel != 0)
 		target_offset += 8;
 
-	ahc = *((struct ahc_softc **)device->host->hostdata);
-	if (bootverbose)
-		printf("%s: Slave Alloc %d\n", ahc_name(ahc), device->id);
-	ahc_lock(ahc, &flags);
-	targ = ahc->platform_data->targets[target_offset];
-	if (targ == NULL) {
-		struct seeprom_config *sc;
-
-		targ = ahc_linux_alloc_target(ahc, starget->channel,
-						starget->id);
-		sc = ahc->seep_config;
-		if (targ == NULL)
-			goto out;
-
-		if (sc) {
-			unsigned short scsirate;
-			struct ahc_devinfo devinfo;
-			struct ahc_initiator_tinfo *tinfo;
-			struct ahc_tmode_tstate *tstate;
-			char channel = starget->channel + 'A';
-			unsigned int our_id = ahc->our_id;
-
-			if (starget->channel)
-				our_id = ahc->our_id_b;
-
-			if ((ahc->features & AHC_ULTRA2) != 0) {
-				scsirate = sc->device_flags[target_offset] & CFXFER;
-			} else {
-				scsirate = (sc->device_flags[target_offset] & CFXFER) << 4;
-				if (sc->device_flags[target_offset] & CFSYNCH)
-					scsirate |= SOFS;
-			}
-			if (sc->device_flags[target_offset] & CFWIDEB) {
-				scsirate |= WIDEXFER;
-				spi_max_width(starget) = 1;
-			} else
-				spi_max_width(starget) = 0;
-			spi_min_period(starget) = 
-				ahc_find_period(ahc, scsirate, AHC_SYNCRATE_DT);
-			tinfo = ahc_fetch_transinfo(ahc, channel, ahc->our_id,
-						    targ->target, &tstate);
-			ahc_compile_devinfo(&devinfo, our_id, targ->target,
-					    CAM_LUN_WILDCARD, channel,
-					    ROLE_INITIATOR);
-			ahc_set_syncrate(ahc, &devinfo, NULL, 0, 0, 0,
-					 AHC_TRANS_GOAL, /*paused*/FALSE);
-			ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
-				      AHC_TRANS_GOAL, /*paused*/FALSE);
-		}
-			
-	}
-	dev = targ->devices[device->lun];
-	if (dev == NULL) {
-		dev = ahc_linux_alloc_device(ahc, targ, device->lun);
-		if (dev == NULL)
-			goto out;
-	}
-	retval = 0;
-
- out:
-	ahc_unlock(ahc, &flags);
-	return retval;
+	return &ahc->platform_data->starget[target_offset];
 }
 
 static int
-ahc_linux_slave_configure(struct scsi_device *device)
+ahc_linux_target_alloc(struct scsi_target *starget)
 {
-	struct	ahc_softc *ahc;
-	struct	ahc_linux_device *dev;
+	struct	ahc_softc *ahc =
+		*((struct ahc_softc **)dev_to_shost(&starget->dev)->hostdata);
+	struct seeprom_config *sc = ahc->seep_config;
+	unsigned long flags;
+	struct scsi_target **ahc_targp = ahc_linux_target_in_softc(starget);
+	struct ahc_linux_target *targ = scsi_transport_target_data(starget);
+	unsigned short scsirate;
+	struct ahc_devinfo devinfo;
+	struct ahc_initiator_tinfo *tinfo;
+	struct ahc_tmode_tstate *tstate;
+	char channel = starget->channel + 'A';
+	unsigned int our_id = ahc->our_id;
+	unsigned int target_offset;
 
-	ahc = *((struct ahc_softc **)device->host->hostdata);
+	target_offset = starget->id;
+	if (starget->channel != 0)
+		target_offset += 8;
+	  
+	if (starget->channel)
+		our_id = ahc->our_id_b;
 
-	if (bootverbose)
-		printf("%s: Slave Configure %d\n", ahc_name(ahc), device->id);
+	ahc_lock(ahc, &flags);
 
-	dev = ahc_linux_get_device(ahc, device->channel, device->id,
-				   device->lun);
-	dev->scsi_device = device;
-	ahc_linux_device_queue_depth(ahc, dev);
+	BUG_ON(*ahc_targp != NULL);
 
-	/* Initial Domain Validation */
-	if (!spi_initial_dv(device->sdev_target))
-		spi_dv_device(device);
+	*ahc_targp = starget;
+	memset(targ, 0, sizeof(*targ));
+
+	if (sc) {
+		int maxsync = AHC_SYNCRATE_DT;
+		int ultra = 0;
+		int flags = sc->device_flags[target_offset];
+
+		if (ahc->flags & AHC_NEWEEPROM_FMT) {
+		    if (flags & CFSYNCHISULTRA)
+			ultra = 1;
+		} else if (flags & CFULTRAEN)
+			ultra = 1;
+		/* AIC nutcase; 10MHz appears as ultra = 1, CFXFER = 0x04
+		 * change it to ultra=0, CFXFER = 0 */
+		if(ultra && (flags & CFXFER) == 0x04) {
+			ultra = 0;
+			flags &= ~CFXFER;
+		}
+	    
+		if ((ahc->features & AHC_ULTRA2) != 0) {
+			scsirate = (flags & CFXFER) | (ultra ? 0x8 : 0);
+		} else {
+			scsirate = (flags & CFXFER) << 4;
+			maxsync = ultra ? AHC_SYNCRATE_ULTRA : 
+				AHC_SYNCRATE_FAST;
+		}
+		spi_max_width(starget) = (flags & CFWIDEB) ? 1 : 0;
+		if (!(flags & CFSYNCH))
+			spi_max_offset(starget) = 0;
+		spi_min_period(starget) = 
+			ahc_find_period(ahc, scsirate, maxsync);
+
+		tinfo = ahc_fetch_transinfo(ahc, channel, ahc->our_id,
+					    starget->id, &tstate);
+	}
+	ahc_compile_devinfo(&devinfo, our_id, starget->id,
+			    CAM_LUN_WILDCARD, channel,
+			    ROLE_INITIATOR);
+	ahc_set_syncrate(ahc, &devinfo, NULL, 0, 0, 0,
+			 AHC_TRANS_GOAL, /*paused*/FALSE);
+	ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
+		      AHC_TRANS_GOAL, /*paused*/FALSE);
+	ahc_unlock(ahc, &flags);
 
 	return 0;
 }
 
 static void
-ahc_linux_slave_destroy(struct scsi_device *device)
+ahc_linux_target_destroy(struct scsi_target *starget)
+{
+	struct scsi_target **ahc_targp = ahc_linux_target_in_softc(starget);
+
+	*ahc_targp = NULL;
+}
+
+static int
+ahc_linux_slave_alloc(struct scsi_device *sdev)
+{
+	struct	ahc_softc *ahc =
+		*((struct ahc_softc **)sdev->host->hostdata);
+	struct scsi_target *starget = sdev->sdev_target;
+	struct ahc_linux_target *targ = scsi_transport_target_data(starget);
+	struct ahc_linux_device *dev;
+
+	if (bootverbose)
+		printf("%s: Slave Alloc %d\n", ahc_name(ahc), sdev->id);
+
+	BUG_ON(targ->sdev[sdev->lun] != NULL);
+
+	dev = scsi_transport_device_data(sdev);
+	memset(dev, 0, sizeof(*dev));
+
+	/*
+	 * We start out life using untagged
+	 * transactions of which we allow one.
+	 */
+	dev->openings = 1;
+
+	/*
+	 * Set maxtags to 0.  This will be changed if we
+	 * later determine that we are dealing with
+	 * a tagged queuing capable device.
+	 */
+	dev->maxtags = 0;
+	
+	targ->sdev[sdev->lun] = sdev;
+
+	return 0;
+}
+
+static int
+ahc_linux_slave_configure(struct scsi_device *sdev)
 {
 	struct	ahc_softc *ahc;
-	struct	ahc_linux_device *dev;
 
-	ahc = *((struct ahc_softc **)device->host->hostdata);
+	ahc = *((struct ahc_softc **)sdev->host->hostdata);
+
 	if (bootverbose)
-		printf("%s: Slave Destroy %d\n", ahc_name(ahc), device->id);
-	dev = ahc_linux_get_device(ahc, device->channel,
-				   device->id, device->lun);
+		printf("%s: Slave Configure %d\n", ahc_name(ahc), sdev->id);
+
+	ahc_linux_device_queue_depth(sdev);
+
+	/* Initial Domain Validation */
+	if (!spi_initial_dv(sdev->sdev_target))
+		spi_dv_device(sdev);
+
+	return 0;
+}
+
+static void
+ahc_linux_slave_destroy(struct scsi_device *sdev)
+{
+	struct	ahc_softc *ahc;
+	struct	ahc_linux_device *dev = scsi_transport_device_data(sdev);
+	struct	ahc_linux_target *targ = scsi_transport_target_data(sdev->sdev_target);
+
+	ahc = *((struct ahc_softc **)sdev->host->hostdata);
+	if (bootverbose)
+		printf("%s: Slave Destroy %d\n", ahc_name(ahc), sdev->id);
 
 	BUG_ON(dev->active);
 
-	ahc_linux_free_device(ahc, dev);
+	targ->sdev[sdev->lun] = NULL;
 }
 
 #if defined(__i386__)
@@ -843,10 +829,14 @@
 {
 	struct ahc_softc *ahc;
 	int    found;
+	unsigned long flags;
 
 	ahc = *(struct ahc_softc **)cmd->device->host->hostdata;
+
+	ahc_lock(ahc, &flags);
 	found = ahc_reset_channel(ahc, cmd->device->channel + 'A',
 				  /*initiate reset*/TRUE);
+	ahc_unlock(ahc, &flags);
 
 	if (bootverbose)
 		printf("%s: SCSI bus reset delivered. "
@@ -874,6 +864,8 @@
 	.slave_alloc		= ahc_linux_slave_alloc,
 	.slave_configure	= ahc_linux_slave_configure,
 	.slave_destroy		= ahc_linux_slave_destroy,
+	.target_alloc		= ahc_linux_target_alloc,
+	.target_destroy		= ahc_linux_target_destroy,
 };
 
 /**************************** Tasklet Handler *********************************/
@@ -1112,8 +1104,6 @@
 		{ "debug", &ahc_debug },
 #endif
 		{ "reverse_scan", &aic7xxx_reverse_scan },
-		{ "no_probe", &aic7xxx_probe_eisa_vl },
-		{ "probe_eisa_vl", &aic7xxx_probe_eisa_vl },
 		{ "periodic_otag", &aic7xxx_periodic_otag },
 		{ "pci_parity", &aic7xxx_pci_parity },
 		{ "seltime", &aic7xxx_seltime },
@@ -1335,8 +1325,7 @@
 void
 ahc_platform_free(struct ahc_softc *ahc)
 {
-	struct ahc_linux_target *targ;
-	struct ahc_linux_device *dev;
+	struct scsi_target *starget;
 	int i, j;
 
 	if (ahc->platform_data != NULL) {
@@ -1347,22 +1336,17 @@
 
 		/* destroy all of the device and target objects */
 		for (i = 0; i < AHC_NUM_TARGETS; i++) {
-			targ = ahc->platform_data->targets[i];
-			if (targ != NULL) {
-				/* Keep target around through the loop. */
-				targ->refcount++;
+			starget = ahc->platform_data->starget[i];
+			if (starget != NULL) {
 				for (j = 0; j < AHC_NUM_LUNS; j++) {
+					struct ahc_linux_target *targ =
+						scsi_transport_target_data(starget);
 
-					if (targ->devices[j] == NULL)
+					if (targ->sdev[j] == NULL)
 						continue;
-					dev = targ->devices[j];
-					ahc_linux_free_device(ahc, dev);
+					targ->sdev[j] = NULL;
 				}
-				/*
-				 * Forcibly free the target now that
-				 * all devices are gone.
-				 */
-				ahc_linux_free_target(ahc, targ);
+				ahc->platform_data->starget[i] = NULL;
  			}
  		}
 
@@ -1395,15 +1379,25 @@
 ahc_platform_set_tags(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
 		      ahc_queue_alg alg)
 {
+	struct scsi_target *starget;
+	struct ahc_linux_target *targ;
 	struct ahc_linux_device *dev;
+	struct scsi_device *sdev;
+	u_int target_offset;
 	int was_queuing;
 	int now_queuing;
 
-	dev = ahc_linux_get_device(ahc, devinfo->channel - 'A',
-				   devinfo->target,
-				   devinfo->lun);
-	if (dev == NULL)
+	target_offset = devinfo->target;
+	if (devinfo->channel != 'A')
+		target_offset += 8;
+	starget = ahc->platform_data->starget[target_offset];
+	targ = scsi_transport_target_data(starget);
+	BUG_ON(targ == NULL);
+	sdev = targ->sdev[devinfo->lun];
+	if (sdev == NULL)
 		return;
+	dev = scsi_transport_device_data(sdev);
+
 	was_queuing = dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED);
 	switch (alg) {
 	default:
@@ -1454,30 +1448,28 @@
 		dev->maxtags = 0;
 		dev->openings =  1 - dev->active;
 	}
-	if (dev->scsi_device != NULL) {
-		switch ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED))) {
-		case AHC_DEV_Q_BASIC:
-			scsi_adjust_queue_depth(dev->scsi_device,
-						MSG_SIMPLE_TASK,
-						dev->openings + dev->active);
-			break;
-		case AHC_DEV_Q_TAGGED:
-			scsi_adjust_queue_depth(dev->scsi_device,
-						MSG_ORDERED_TASK,
-						dev->openings + dev->active);
-			break;
-		default:
-			/*
-			 * We allow the OS to queue 2 untagged transactions to
-			 * us at any time even though we can only execute them
-			 * serially on the controller/device.  This should
-			 * remove some latency.
-			 */
-			scsi_adjust_queue_depth(dev->scsi_device,
-						/*NON-TAGGED*/0,
-						/*queue depth*/2);
-			break;
-		}
+	switch ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED))) {
+	case AHC_DEV_Q_BASIC:
+		scsi_adjust_queue_depth(sdev,
+					MSG_SIMPLE_TASK,
+					dev->openings + dev->active);
+		break;
+	case AHC_DEV_Q_TAGGED:
+		scsi_adjust_queue_depth(sdev,
+					MSG_ORDERED_TASK,
+					dev->openings + dev->active);
+		break;
+	default:
+		/*
+		 * We allow the OS to queue 2 untagged transactions to
+		 * us at any time even though we can only execute them
+		 * serially on the controller/device.  This should
+		 * remove some latency.
+		 */
+		scsi_adjust_queue_depth(sdev,
+					/*NON-TAGGED*/0,
+					/*queue depth*/2);
+		break;
 	}
 }
 
@@ -1523,22 +1515,20 @@
  * Determines the queue depth for a given device.
  */
 static void
-ahc_linux_device_queue_depth(struct ahc_softc *ahc,
-			     struct ahc_linux_device *dev)
+ahc_linux_device_queue_depth(struct scsi_device *sdev)
 {
 	struct	ahc_devinfo devinfo;
 	u_int	tags;
+	struct ahc_softc *ahc = *((struct ahc_softc **)sdev->host->hostdata);
 
 	ahc_compile_devinfo(&devinfo,
-			    dev->target->channel == 0
+			    sdev->sdev_target->channel == 0
 			  ? ahc->our_id : ahc->our_id_b,
-			    dev->target->target, dev->lun,
-			    dev->target->channel == 0 ? 'A' : 'B',
+			    sdev->sdev_target->id, sdev->lun,
+			    sdev->sdev_target->channel == 0 ? 'A' : 'B',
 			    ROLE_INITIATOR);
 	tags = ahc_linux_user_tagdepth(ahc, &devinfo);
-	if (tags != 0
-	 && dev->scsi_device != NULL
-	 && dev->scsi_device->tagged_supported != 0) {
+	if (tags != 0 && sdev->tagged_supported != 0) {
 
 		ahc_set_tags(ahc, &devinfo, AHC_QUEUE_TAGGED);
 		ahc_print_devinfo(ahc, &devinfo);
@@ -1587,10 +1577,9 @@
 	/*
 	 * Get an scb to use.
 	 */
-	if ((scb = ahc_get_scb(ahc)) == NULL) {
-			ahc->flags |= AHC_RESOURCE_SHORTAGE;
-			return SCSI_MLQUEUE_HOST_BUSY;
-	}
+	scb = ahc_get_scb(ahc);
+	if (!scb)
+		return SCSI_MLQUEUE_HOST_BUSY;
 
 	scb->io_ctx = cmd;
 	scb->platform_data->dev = dev;
@@ -1767,106 +1756,6 @@
 
 }
 
-static struct ahc_linux_target*
-ahc_linux_alloc_target(struct ahc_softc *ahc, u_int channel, u_int target)
-{
-	struct ahc_linux_target *targ;
-	u_int target_offset;
-
-	target_offset = target;
-	if (channel != 0)
-		target_offset += 8;
-
-	targ = malloc(sizeof(*targ), M_DEVBUG, M_NOWAIT);
-	if (targ == NULL)
-		return (NULL);
-	memset(targ, 0, sizeof(*targ));
-	targ->channel = channel;
-	targ->target = target;
-	targ->ahc = ahc;
-	ahc->platform_data->targets[target_offset] = targ;
-	return (targ);
-}
-
-static void
-ahc_linux_free_target(struct ahc_softc *ahc, struct ahc_linux_target *targ)
-{
-	struct ahc_devinfo devinfo;
-	struct ahc_initiator_tinfo *tinfo;
-	struct ahc_tmode_tstate *tstate;
-	u_int our_id;
-	u_int target_offset;
-	char channel;
-
-	/*
-	 * Force a negotiation to async/narrow on any
-	 * future command to this device unless a bus
-	 * reset occurs between now and that command.
-	 */
-	channel = 'A' + targ->channel;
-	our_id = ahc->our_id;
-	target_offset = targ->target;
-	if (targ->channel != 0) {
-		target_offset += 8;
-		our_id = ahc->our_id_b;
-	}
-	tinfo = ahc_fetch_transinfo(ahc, channel, our_id,
-				    targ->target, &tstate);
-	ahc_compile_devinfo(&devinfo, our_id, targ->target, CAM_LUN_WILDCARD,
-			    channel, ROLE_INITIATOR);
-	ahc_set_syncrate(ahc, &devinfo, NULL, 0, 0, 0,
-			 AHC_TRANS_GOAL, /*paused*/FALSE);
-	ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
-		      AHC_TRANS_GOAL, /*paused*/FALSE);
-	ahc_update_neg_request(ahc, &devinfo, tstate, tinfo, AHC_NEG_ALWAYS);
-	ahc->platform_data->targets[target_offset] = NULL;
-	free(targ, M_DEVBUF);
-}
-
-static struct ahc_linux_device*
-ahc_linux_alloc_device(struct ahc_softc *ahc,
-		 struct ahc_linux_target *targ, u_int lun)
-{
-	struct ahc_linux_device *dev;
-
-	dev = malloc(sizeof(*dev), M_DEVBUG, M_NOWAIT);
-	if (dev == NULL)
-		return (NULL);
-	memset(dev, 0, sizeof(*dev));
-	dev->lun = lun;
-	dev->target = targ;
-
-	/*
-	 * We start out life using untagged
-	 * transactions of which we allow one.
-	 */
-	dev->openings = 1;
-
-	/*
-	 * Set maxtags to 0.  This will be changed if we
-	 * later determine that we are dealing with
-	 * a tagged queuing capable device.
-	 */
-	dev->maxtags = 0;
-	
-	targ->refcount++;
-	targ->devices[lun] = dev;
-	return (dev);
-}
-
-static void
-ahc_linux_free_device(struct ahc_softc *ahc, struct ahc_linux_device *dev)
-{
-	struct ahc_linux_target *targ;
-
-	targ = dev->target;
-	targ->devices[dev->lun] = NULL;
-	free(dev, M_DEVBUF);
-	targ->refcount--;
-	if (targ->refcount == 0)
-		ahc_linux_free_target(ahc, targ);
-}
-
 void
 ahc_send_async(struct ahc_softc *ahc, char channel,
 	       u_int target, u_int lun, ac_code code, void *arg)
@@ -1875,11 +1764,15 @@
 	case AC_TRANSFER_NEG:
 	{
 		char	buf[80];
+		struct	scsi_target *starget;
 		struct	ahc_linux_target *targ;
 		struct	info_str info;
 		struct	ahc_initiator_tinfo *tinfo;
 		struct	ahc_tmode_tstate *tstate;
 		int	target_offset;
+		unsigned int target_ppr_options;
+
+		BUG_ON(target == CAM_TARGET_WILDCARD);
 
 		info.buffer = buf;
 		info.length = sizeof(buf);
@@ -1908,32 +1801,30 @@
 		target_offset = target;
 		if (channel == 'B')
 			target_offset += 8;
-		targ = ahc->platform_data->targets[target_offset];
+		starget = ahc->platform_data->starget[target_offset];
+		targ = scsi_transport_target_data(starget);
 		if (targ == NULL)
 			break;
-		if (tinfo->curr.period == targ->last_tinfo.period
-		 && tinfo->curr.width == targ->last_tinfo.width
-		 && tinfo->curr.offset == targ->last_tinfo.offset
-		 && tinfo->curr.ppr_options == targ->last_tinfo.ppr_options)
+
+		target_ppr_options =
+			(spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0)
+			+ (spi_qas(starget) ? MSG_EXT_PPR_QAS_REQ : 0)
+			+ (spi_iu(starget) ?  MSG_EXT_PPR_IU_REQ : 0);
+
+		if (tinfo->curr.period == spi_period(starget)
+		    && tinfo->curr.width == spi_width(starget)
+		    && tinfo->curr.offset == spi_offset(starget)
+		 && tinfo->curr.ppr_options == target_ppr_options)
 			if (bootverbose == 0)
 				break;
 
-		targ->last_tinfo.period = tinfo->curr.period;
-		targ->last_tinfo.width = tinfo->curr.width;
-		targ->last_tinfo.offset = tinfo->curr.offset;
-		targ->last_tinfo.ppr_options = tinfo->curr.ppr_options;
-
-		printf("(%s:%c:", ahc_name(ahc), channel);
-		if (target == CAM_TARGET_WILDCARD)
-			printf("*): ");
-		else
-			printf("%d): ", target);
-		ahc_format_transinfo(&info, &tinfo->curr);
-		if (info.pos < info.length)
-			*info.buffer = '\0';
-		else
-			buf[info.length - 1] = '\0';
-		printf("%s", buf);
+		spi_period(starget) = tinfo->curr.period;
+		spi_width(starget) = tinfo->curr.width;
+		spi_offset(starget) = tinfo->curr.offset;
+		spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ;
+		spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ;
+		spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ;
+		spi_display_xfer_agreement(starget);
 		break;
 	}
         case AC_SENT_BDR:
@@ -2038,7 +1929,7 @@
 			ahc_set_transaction_status(scb, CAM_REQ_CMP);
 		}
 	} else if (ahc_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) {
-		ahc_linux_handle_scsi_status(ahc, dev, scb);
+		ahc_linux_handle_scsi_status(ahc, cmd->device, scb);
 	}
 
 	if (dev->openings == 1
@@ -2077,14 +1968,15 @@
 
 static void
 ahc_linux_handle_scsi_status(struct ahc_softc *ahc,
-			     struct ahc_linux_device *dev, struct scb *scb)
+			     struct scsi_device *sdev, struct scb *scb)
 {
 	struct	ahc_devinfo devinfo;
+	struct ahc_linux_device *dev = scsi_transport_device_data(sdev);
 
 	ahc_compile_devinfo(&devinfo,
 			    ahc->our_id,
-			    dev->target->target, dev->lun,
-			    dev->target->channel == 0 ? 'A' : 'B',
+			    sdev->sdev_target->id, sdev->lun,
+			    sdev->sdev_target->channel == 0 ? 'A' : 'B',
 			    ROLE_INITIATOR);
 	
 	/*
@@ -2361,6 +2253,8 @@
 		printf(" 0x%x", cmd->cmnd[cdb_byte]);
 	printf("\n");
 
+	spin_lock_irq(&ahc->platform_data->spin_lock);
+
 	/*
 	 * First determine if we currently own this command.
 	 * Start by searching the device queue.  If not found
@@ -2368,8 +2262,7 @@
 	 * at all, and the system wanted us to just abort the
 	 * command, return success.
 	 */
-	dev = ahc_linux_get_device(ahc, cmd->device->channel, cmd->device->id,
-				   cmd->device->lun);
+	dev = scsi_transport_device_data(cmd->device);
 
 	if (dev == NULL) {
 		/*
@@ -2616,6 +2509,8 @@
 		}
 		spin_lock_irq(&ahc->platform_data->spin_lock);
 	}
+
+	spin_unlock_irq(&ahc->platform_data->spin_lock);
 	return (retval);
 }
 
@@ -2626,18 +2521,6 @@
 
 static void ahc_linux_exit(void);
 
-static void ahc_linux_get_width(struct scsi_target *starget)
-{
-	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
-	struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
-	struct ahc_tmode_tstate *tstate;
-	struct ahc_initiator_tinfo *tinfo 
-		= ahc_fetch_transinfo(ahc,
-				      starget->channel + 'A',
-				      shost->this_id, starget->id, &tstate);
-	spi_width(starget) = tinfo->curr.width;
-}
-
 static void ahc_linux_set_width(struct scsi_target *starget, int width)
 {
 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
@@ -2652,18 +2535,6 @@
 	ahc_unlock(ahc, &flags);
 }
 
-static void ahc_linux_get_period(struct scsi_target *starget)
-{
-	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
-	struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
-	struct ahc_tmode_tstate *tstate;
-	struct ahc_initiator_tinfo *tinfo 
-		= ahc_fetch_transinfo(ahc,
-				      starget->channel + 'A',
-				      shost->this_id, starget->id, &tstate);
-	spi_period(starget) = tinfo->curr.period;
-}
-
 static void ahc_linux_set_period(struct scsi_target *starget, int period)
 {
 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
@@ -2674,9 +2545,9 @@
 				      starget->channel + 'A',
 				      shost->this_id, starget->id, &tstate);
 	struct ahc_devinfo devinfo;
-	unsigned int ppr_options = tinfo->curr.ppr_options;
+	unsigned int ppr_options = tinfo->goal.ppr_options;
 	unsigned long flags;
-	unsigned long offset = tinfo->curr.offset;
+	unsigned long offset = tinfo->goal.offset;
 	struct ahc_syncrate *syncrate;
 
 	if (offset == 0)
@@ -2692,7 +2563,6 @@
 
 	/* all PPR requests apart from QAS require wide transfers */
 	if (ppr_options & ~MSG_EXT_PPR_QAS_REQ) {
-		ahc_linux_get_width(starget);
 		if (spi_width(starget) == 0)
 			ppr_options &= MSG_EXT_PPR_QAS_REQ;
 	}
@@ -2704,18 +2574,6 @@
 	ahc_unlock(ahc, &flags);
 }
 
-static void ahc_linux_get_offset(struct scsi_target *starget)
-{
-	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
-	struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
-	struct ahc_tmode_tstate *tstate;
-	struct ahc_initiator_tinfo *tinfo 
-		= ahc_fetch_transinfo(ahc,
-				      starget->channel + 'A',
-				      shost->this_id, starget->id, &tstate);
-	spi_offset(starget) = tinfo->curr.offset;
-}
-
 static void ahc_linux_set_offset(struct scsi_target *starget, int offset)
 {
 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
@@ -2735,8 +2593,8 @@
 			    starget->channel + 'A', ROLE_INITIATOR);
 	if (offset != 0) {
 		syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, AHC_SYNCRATE_DT);
-		period = tinfo->curr.period;
-		ppr_options = tinfo->curr.ppr_options;
+		period = tinfo->goal.period;
+		ppr_options = tinfo->goal.ppr_options;
 	}
 	ahc_lock(ahc, &flags);
 	ahc_set_syncrate(ahc, &devinfo, syncrate, period, offset,
@@ -2744,18 +2602,6 @@
 	ahc_unlock(ahc, &flags);
 }
 
-static void ahc_linux_get_dt(struct scsi_target *starget)
-{
-	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
-	struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
-	struct ahc_tmode_tstate *tstate;
-	struct ahc_initiator_tinfo *tinfo 
-		= ahc_fetch_transinfo(ahc,
-				      starget->channel + 'A',
-				      shost->this_id, starget->id, &tstate);
-	spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ;
-}
-
 static void ahc_linux_set_dt(struct scsi_target *starget, int dt)
 {
 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
@@ -2766,9 +2612,9 @@
 				      starget->channel + 'A',
 				      shost->this_id, starget->id, &tstate);
 	struct ahc_devinfo devinfo;
-	unsigned int ppr_options = tinfo->curr.ppr_options
+	unsigned int ppr_options = tinfo->goal.ppr_options
 		& ~MSG_EXT_PPR_DT_REQ;
-	unsigned int period = tinfo->curr.period;
+	unsigned int period = tinfo->goal.period;
 	unsigned long flags;
 	struct ahc_syncrate *syncrate;
 
@@ -2782,23 +2628,11 @@
 			    starget->channel + 'A', ROLE_INITIATOR);
 	syncrate = ahc_find_syncrate(ahc, &period, &ppr_options,AHC_SYNCRATE_DT);
 	ahc_lock(ahc, &flags);
-	ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->curr.offset,
+	ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->goal.offset,
 			 ppr_options, AHC_TRANS_GOAL, FALSE);
 	ahc_unlock(ahc, &flags);
 }
 
-static void ahc_linux_get_qas(struct scsi_target *starget)
-{
-	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
-	struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
-	struct ahc_tmode_tstate *tstate;
-	struct ahc_initiator_tinfo *tinfo 
-		= ahc_fetch_transinfo(ahc,
-				      starget->channel + 'A',
-				      shost->this_id, starget->id, &tstate);
-	spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ;
-}
-
 static void ahc_linux_set_qas(struct scsi_target *starget, int qas)
 {
 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
@@ -2809,9 +2643,9 @@
 				      starget->channel + 'A',
 				      shost->this_id, starget->id, &tstate);
 	struct ahc_devinfo devinfo;
-	unsigned int ppr_options = tinfo->curr.ppr_options
+	unsigned int ppr_options = tinfo->goal.ppr_options
 		& ~MSG_EXT_PPR_QAS_REQ;
-	unsigned int period = tinfo->curr.period;
+	unsigned int period = tinfo->goal.period;
 	unsigned long flags;
 	struct ahc_syncrate *syncrate;
 
@@ -2822,23 +2656,11 @@
 			    starget->channel + 'A', ROLE_INITIATOR);
 	syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, AHC_SYNCRATE_DT);
 	ahc_lock(ahc, &flags);
-	ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->curr.offset,
+	ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->goal.offset,
 			 ppr_options, AHC_TRANS_GOAL, FALSE);
 	ahc_unlock(ahc, &flags);
 }
 
-static void ahc_linux_get_iu(struct scsi_target *starget)
-{
-	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
-	struct ahc_softc *ahc = *((struct ahc_softc **)shost->hostdata);
-	struct ahc_tmode_tstate *tstate;
-	struct ahc_initiator_tinfo *tinfo 
-		= ahc_fetch_transinfo(ahc,
-				      starget->channel + 'A',
-				      shost->this_id, starget->id, &tstate);
-	spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ;
-}
-
 static void ahc_linux_set_iu(struct scsi_target *starget, int iu)
 {
 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
@@ -2849,9 +2671,9 @@
 				      starget->channel + 'A',
 				      shost->this_id, starget->id, &tstate);
 	struct ahc_devinfo devinfo;
-	unsigned int ppr_options = tinfo->curr.ppr_options
+	unsigned int ppr_options = tinfo->goal.ppr_options
 		& ~MSG_EXT_PPR_IU_REQ;
-	unsigned int period = tinfo->curr.period;
+	unsigned int period = tinfo->goal.period;
 	unsigned long flags;
 	struct ahc_syncrate *syncrate;
 
@@ -2862,28 +2684,22 @@
 			    starget->channel + 'A', ROLE_INITIATOR);
 	syncrate = ahc_find_syncrate(ahc, &period, &ppr_options, AHC_SYNCRATE_DT);
 	ahc_lock(ahc, &flags);
-	ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->curr.offset,
+	ahc_set_syncrate(ahc, &devinfo, syncrate, period, tinfo->goal.offset,
 			 ppr_options, AHC_TRANS_GOAL, FALSE);
 	ahc_unlock(ahc, &flags);
 }
 
 static struct spi_function_template ahc_linux_transport_functions = {
-	.get_offset	= ahc_linux_get_offset,
 	.set_offset	= ahc_linux_set_offset,
 	.show_offset	= 1,
-	.get_period	= ahc_linux_get_period,
 	.set_period	= ahc_linux_set_period,
 	.show_period	= 1,
-	.get_width	= ahc_linux_get_width,
 	.set_width	= ahc_linux_set_width,
 	.show_width	= 1,
-	.get_dt		= ahc_linux_get_dt,
 	.set_dt		= ahc_linux_set_dt,
 	.show_dt	= 1,
-	.get_iu		= ahc_linux_get_iu,
 	.set_iu		= ahc_linux_set_iu,
 	.show_iu	= 1,
-	.get_qas	= ahc_linux_get_qas,
 	.set_qas	= ahc_linux_set_qas,
 	.show_qas	= 1,
 };
@@ -2896,6 +2712,10 @@
 	ahc_linux_transport_template = spi_attach_transport(&ahc_linux_transport_functions);
 	if (!ahc_linux_transport_template)
 		return -ENODEV;
+	scsi_transport_reserve_target(ahc_linux_transport_template,
+				      sizeof(struct ahc_linux_target));
+	scsi_transport_reserve_device(ahc_linux_transport_template,
+				      sizeof(struct ahc_linux_device));
 	if (ahc_linux_detect(&aic7xxx_driver_template))
 		return 0;
 	spi_release_transport(ahc_linux_transport_template);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index 30c200d..8ffe2d3 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -79,6 +79,8 @@
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_spi.h>
 
 /* Core SCSI definitions */
 #define AIC_LIB_PREFIX ahc
@@ -127,23 +129,6 @@
 #define ahc_le32toh(x)	le32_to_cpu(x)
 #define ahc_le64toh(x)	le64_to_cpu(x)
 
-#ifndef LITTLE_ENDIAN
-#define LITTLE_ENDIAN 1234
-#endif
-
-#ifndef BIG_ENDIAN
-#define BIG_ENDIAN 4321
-#endif
-
-#ifndef BYTE_ORDER
-#if defined(__BIG_ENDIAN)
-#define BYTE_ORDER BIG_ENDIAN
-#endif
-#if defined(__LITTLE_ENDIAN)
-#define BYTE_ORDER LITTLE_ENDIAN
-#endif
-#endif /* BYTE_ORDER */
-
 /************************* Configuration Data *********************************/
 extern u_int aic7xxx_no_probe;
 extern u_int aic7xxx_allow_memio;
@@ -283,35 +268,6 @@
 
 #define AIC7XXX_DRIVER_VERSION "6.2.36"
 
-/**************************** Front End Queues ********************************/
-/*
- * Data structure used to cast the Linux struct scsi_cmnd to something
- * that allows us to use the queue macros.  The linux structure has
- * plenty of space to hold the links fields as required by the queue
- * macros, but the queue macors require them to have the correct type.
- */
-struct ahc_cmd_internal {
-	/* Area owned by the Linux scsi layer. */
-	uint8_t	private[offsetof(struct scsi_cmnd, SCp.Status)];
-	union {
-		STAILQ_ENTRY(ahc_cmd)	ste;
-		LIST_ENTRY(ahc_cmd)	le;
-		TAILQ_ENTRY(ahc_cmd)	tqe;
-	} links;
-	uint32_t			end;
-};
-
-struct ahc_cmd {
-	union {
-		struct ahc_cmd_internal	icmd;
-		struct scsi_cmnd	scsi_cmd;
-	} un;
-};
-
-#define acmd_icmd(cmd) ((cmd)->un.icmd)
-#define acmd_scsi_cmd(cmd) ((cmd)->un.scsi_cmd)
-#define acmd_links un.icmd.links
-
 /*************************** Device Data Structures ***************************/
 /*
  * A per probed device structure used to deal with some error recovery
@@ -320,7 +276,6 @@
  * after a successfully completed inquiry command to the target when
  * that inquiry data indicates a lun is present.
  */
-TAILQ_HEAD(ahc_busyq, ahc_cmd);
 typedef enum {
 	AHC_DEV_FREEZE_TIL_EMPTY = 0x02, /* Freeze queue until active == 0 */
 	AHC_DEV_Q_BASIC		 = 0x10, /* Allow basic device queuing */
@@ -330,8 +285,6 @@
 
 struct ahc_linux_target;
 struct ahc_linux_device {
-	TAILQ_ENTRY(ahc_linux_device) links;
-
 	/*
 	 * The number of transactions currently
 	 * queued to the device.
@@ -401,17 +354,10 @@
 	 */
 	u_int			commands_since_idle_or_otag;
 #define AHC_OTAG_THRESH	500
-
-	int			lun;
-	struct scsi_device       *scsi_device;
-	struct			ahc_linux_target *target;
 };
 
 struct ahc_linux_target {
-	struct ahc_linux_device	 *devices[AHC_NUM_LUNS];
-	int			  channel;
-	int			  target;
-	int			  refcount;
+	struct scsi_device	 *sdev[AHC_NUM_LUNS];
 	struct ahc_transinfo	  last_tinfo;
 	struct ahc_softc	 *ahc;
 };
@@ -445,7 +391,7 @@
 	/*
 	 * Fields accessed from interrupt context.
 	 */
-	struct ahc_linux_target *targets[AHC_NUM_TARGETS]; 
+	struct scsi_target *starget[AHC_NUM_TARGETS]; 
 
 	spinlock_t		 spin_lock;
 	u_int			 qfrozen;
@@ -659,7 +605,6 @@
 
 /**************************** VL/EISA Routines ********************************/
 #ifdef CONFIG_EISA
-extern uint32_t aic7xxx_probe_eisa_vl;
 int			 ahc_linux_eisa_init(void);
 void			 ahc_linux_eisa_exit(void);
 int			 aic7770_map_registers(struct ahc_softc *ahc,
@@ -924,7 +869,6 @@
 static __inline void
 ahc_platform_scb_free(struct ahc_softc *ahc, struct scb *scb)
 {
-	ahc->flags &= ~AHC_RESOURCE_SHORTAGE;
 }
 
 int	ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
index 2a0ebce..89d737e 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c
@@ -140,27 +140,17 @@
 static void
 ahc_linux_pci_dev_remove(struct pci_dev *pdev)
 {
-	struct ahc_softc *ahc;
-	u_long l;
+	struct ahc_softc *ahc = pci_get_drvdata(pdev);
+	u_long s;
 
-	/*
-	 * We should be able to just perform
-	 * the free directly, but check our
-	 * list for extra sanity.
-	 */
-	ahc_list_lock(&l);
-	ahc = ahc_find_softc((struct ahc_softc *)pci_get_drvdata(pdev));
-	if (ahc != NULL) {
-		u_long s;
+	ahc_list_lock(&s);
+	TAILQ_REMOVE(&ahc_tailq, ahc, links);
+	ahc_list_unlock(&s);
 
-		TAILQ_REMOVE(&ahc_tailq, ahc, links);
-		ahc_list_unlock(&l);
-		ahc_lock(ahc, &s);
-		ahc_intr_enable(ahc, FALSE);
-		ahc_unlock(ahc, &s);
-		ahc_free(ahc);
-	} else
-		ahc_list_unlock(&l);
+	ahc_lock(ahc, &s);
+	ahc_intr_enable(ahc, FALSE);
+	ahc_unlock(ahc, &s);
+	ahc_free(ahc);
 }
 
 static int
@@ -174,22 +164,6 @@
 	char		*name;
 	int		 error;
 
-	/*
-	 * Some BIOSen report the same device multiple times.
-	 */
-	TAILQ_FOREACH(ahc, &ahc_tailq, links) {
-		struct pci_dev *probed_pdev;
-
-		probed_pdev = ahc->dev_softc;
-		if (probed_pdev->bus->number == pdev->bus->number
-		 && probed_pdev->devfn == pdev->devfn)
-			break;
-	}
-	if (ahc != NULL) {
-		/* Skip duplicate. */
-		return (-ENODEV);
-	}
-
 	pci = pdev;
 	entry = ahc_find_pci_device(pci);
 	if (entry == NULL)
diff --git a/drivers/scsi/aic7xxx/aic7xxx_proc.c b/drivers/scsi/aic7xxx/aic7xxx_proc.c
index 5fece85..ab4469d 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_proc.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_proc.c
@@ -50,7 +50,7 @@
 				      u_int our_id, char channel,
 				      u_int target_id, u_int target_offset);
 static void	ahc_dump_device_state(struct info_str *info,
-				      struct ahc_linux_device *dev);
+				      struct scsi_device *dev);
 static int	ahc_proc_write_seeprom(struct ahc_softc *ahc,
 				       char *buffer, int length);
 
@@ -142,6 +142,7 @@
 		      u_int target_offset)
 {
 	struct	ahc_linux_target *targ;
+	struct	scsi_target *starget;
 	struct	ahc_initiator_tinfo *tinfo;
 	struct	ahc_tmode_tstate *tstate;
 	int	lun;
@@ -153,7 +154,8 @@
 	copy_info(info, "Target %d Negotiation Settings\n", target_id);
 	copy_info(info, "\tUser: ");
 	ahc_format_transinfo(info, &tinfo->user);
-	targ = ahc->platform_data->targets[target_offset];
+	starget = ahc->platform_data->starget[target_offset];
+	targ = scsi_transport_target_data(starget);
 	if (targ == NULL)
 		return;
 
@@ -163,22 +165,25 @@
 	ahc_format_transinfo(info, &tinfo->curr);
 
 	for (lun = 0; lun < AHC_NUM_LUNS; lun++) {
-		struct ahc_linux_device *dev;
+		struct scsi_device *sdev;
 
-		dev = targ->devices[lun];
+		sdev = targ->sdev[lun];
 
-		if (dev == NULL)
+		if (sdev == NULL)
 			continue;
 
-		ahc_dump_device_state(info, dev);
+		ahc_dump_device_state(info, sdev);
 	}
 }
 
 static void
-ahc_dump_device_state(struct info_str *info, struct ahc_linux_device *dev)
+ahc_dump_device_state(struct info_str *info, struct scsi_device *sdev)
 {
+	struct ahc_linux_device *dev = scsi_transport_device_data(sdev);
+
 	copy_info(info, "\tChannel %c Target %d Lun %d Settings\n",
-		  dev->target->channel + 'A', dev->target->target, dev->lun);
+		  sdev->sdev_target->channel + 'A',
+		  sdev->sdev_target->id, sdev->lun);
 
 	copy_info(info, "\t\tCommands Queued %ld\n", dev->commands_issued);
 	copy_info(info, "\t\tCommands Active %d\n", dev->active);
@@ -292,20 +297,13 @@
 ahc_linux_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
 		    off_t offset, int length, int inout)
 {
-	struct	ahc_softc *ahc;
+	struct	ahc_softc *ahc = *(struct ahc_softc **)shost->hostdata;
 	struct	info_str info;
 	char	ahc_info[256];
-	u_long	s;
 	u_int	max_targ;
 	u_int	i;
 	int	retval;
 
-	retval = -EINVAL;
-	ahc_list_lock(&s);
-	ahc = ahc_find_softc(*(struct ahc_softc **)shost->hostdata);
-	if (ahc == NULL)
-		goto done;
-
 	 /* Has data been written to the file? */ 
 	if (inout == TRUE) {
 		retval = ahc_proc_write_seeprom(ahc, buffer, length);
@@ -367,6 +365,5 @@
 	}
 	retval = info.pos > info.offset ? info.pos - info.offset : 0;
 done:
-	ahc_list_unlock(&s);
 	return (retval);
 }
diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
index 9e9d0c4..fac091e 100644
--- a/drivers/scsi/aic7xxx_old.c
+++ b/drivers/scsi/aic7xxx_old.c
@@ -10358,7 +10358,7 @@
  *   Returns an enumerated type that indicates the status of the operation.
  *-F*************************************************************************/
 static int
-aic7xxx_bus_device_reset(Scsi_Cmnd *cmd)
+__aic7xxx_bus_device_reset(Scsi_Cmnd *cmd)
 {
   struct aic7xxx_host  *p;
   struct aic7xxx_scb   *scb;
@@ -10551,6 +10551,18 @@
     return SUCCESS;
 }
 
+static int
+aic7xxx_bus_device_reset(Scsi_Cmnd *cmd)
+{
+      int rc;
+
+      spin_lock_irq(cmd->device->host->host_lock);
+      rc = __aic7xxx_bus_device_reset(cmd);
+      spin_unlock_irq(cmd->device->host->host_lock);
+
+      return rc;
+}
+
 
 /*+F*************************************************************************
  * Function:
@@ -10585,7 +10597,7 @@
  *   Abort the current SCSI command(s).
  *-F*************************************************************************/
 static int
-aic7xxx_abort(Scsi_Cmnd *cmd)
+__aic7xxx_abort(Scsi_Cmnd *cmd)
 {
   struct aic7xxx_scb  *scb = NULL;
   struct aic7xxx_host *p;
@@ -10802,6 +10814,19 @@
   return SUCCESS;
 }
 
+static int
+aic7xxx_abort(Scsi_Cmnd *cmd)
+{
+	int rc;
+
+	spin_lock_irq(cmd->device->host->host_lock);
+	rc = __aic7xxx_abort(cmd);
+	spin_unlock_irq(cmd->device->host->host_lock);
+
+	return rc;
+}
+
+
 /*+F*************************************************************************
  * Function:
  *   aic7xxx_reset
@@ -10820,6 +10845,8 @@
   struct aic_dev_data *aic_dev;
 
   p = (struct aic7xxx_host *) cmd->device->host->hostdata;
+  spin_lock_irq(p->host->host_lock);
+
   aic_dev = AIC_DEV(cmd);
   if(aic7xxx_position(cmd) < p->scb_data->numscbs)
   {
@@ -10859,6 +10886,7 @@
      * longer have it.
      */
     unpause_sequencer(p, FALSE);
+    spin_unlock_irq(p->host->host_lock);
     return SUCCESS;
   }
     
@@ -10882,7 +10910,6 @@
   unpause_sequencer(p, FALSE);
   spin_unlock_irq(p->host->host_lock);
   ssleep(2);
-  spin_lock_irq(p->host->host_lock);
   return SUCCESS;
 }
 
diff --git a/drivers/scsi/arm/cumana_1.c b/drivers/scsi/arm/cumana_1.c
index 27271bf..26498553 100644
--- a/drivers/scsi/arm/cumana_1.c
+++ b/drivers/scsi/arm/cumana_1.c
@@ -244,9 +244,7 @@
 	.info			= cumanascsi_info,
 	.queuecommand		= cumanascsi_queue_command,
 	.eh_abort_handler	= NCR5380_abort,
-	.eh_device_reset_handler= NCR5380_device_reset,
 	.eh_bus_reset_handler	= NCR5380_bus_reset,
-	.eh_host_reset_handler	= NCR5380_host_reset,
 	.can_queue		= 16,
 	.this_id		= 7,
 	.sg_tablesize		= SG_ALL,
diff --git a/drivers/scsi/arm/ecoscsi.c b/drivers/scsi/arm/ecoscsi.c
index 303648a..f8a7fdd 100644
--- a/drivers/scsi/arm/ecoscsi.c
+++ b/drivers/scsi/arm/ecoscsi.c
@@ -162,9 +162,7 @@
 	.info		= ecoscsi_info,
 	.queuecommand	= ecoscsi_queue_command,
 	.eh_abort_handler	= NCR5380_abort,
-	.eh_device_reset_handler= NCR5380_device_reset,
 	.eh_bus_reset_handler	= NCR5380_bus_reset,
-	.eh_host_reset_handler	= NCR5380_host_reset,
 	.can_queue	= 16,
 	.this_id	= 7,
 	.sg_tablesize	= SG_ALL,
diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c
index 78b7e54..ce711f1 100644
--- a/drivers/scsi/arm/eesox.c
+++ b/drivers/scsi/arm/eesox.c
@@ -466,7 +466,7 @@
 	return pos;
 }
 
-static ssize_t eesoxscsi_show_term(struct device *dev, char *buf)
+static ssize_t eesoxscsi_show_term(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct expansion_card *ec = ECARD_DEV(dev);
 	struct Scsi_Host *host = ecard_get_drvdata(ec);
@@ -475,7 +475,7 @@
 	return sprintf(buf, "%d\n", info->control & EESOX_TERM_ENABLE ? 1 : 0);
 }
 
-static ssize_t eesoxscsi_store_term(struct device *dev, const char *buf, size_t len)
+static ssize_t eesoxscsi_store_term(struct device *dev, struct device_attribute *attr, const char *buf, size_t len)
 {
 	struct expansion_card *ec = ECARD_DEV(dev);
 	struct Scsi_Host *host = ecard_get_drvdata(ec);
diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
index 3838f88..4772fb3 100644
--- a/drivers/scsi/arm/fas216.c
+++ b/drivers/scsi/arm/fas216.c
@@ -2659,6 +2659,8 @@
 {
 	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;
 
+	spin_lock_irq(info->host->host_lock);
+
 	fas216_checkmagic(info);
 
 	printk("scsi%d.%c: %s: resetting host\n",
@@ -2686,6 +2688,7 @@
 
 	fas216_init_chip(info);
 
+	spin_unlock_irq(info->host->host_lock);
 	return SUCCESS;
 }
 
diff --git a/drivers/scsi/arm/oak.c b/drivers/scsi/arm/oak.c
index ff2554f..de24bb9 100644
--- a/drivers/scsi/arm/oak.c
+++ b/drivers/scsi/arm/oak.c
@@ -118,9 +118,7 @@
 	.info			= oakscsi_info,
 	.queuecommand		= oakscsi_queue_command,
 	.eh_abort_handler	= NCR5380_abort,
-	.eh_device_reset_handler= NCR5380_device_reset,
 	.eh_bus_reset_handler	= NCR5380_bus_reset,
-	.eh_host_reset_handler	= NCR5380_host_reset,
 	.can_queue		= 16,
 	.this_id		= 7,
 	.sg_tablesize		= SG_ALL,
diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c
index 54f23be..abda216 100644
--- a/drivers/scsi/arm/powertec.c
+++ b/drivers/scsi/arm/powertec.c
@@ -269,7 +269,7 @@
 	return pos;
 }
 
-static ssize_t powertecscsi_show_term(struct device *dev, char *buf)
+static ssize_t powertecscsi_show_term(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct expansion_card *ec = ECARD_DEV(dev);
 	struct Scsi_Host *host = ecard_get_drvdata(ec);
@@ -279,7 +279,7 @@
 }
 
 static ssize_t
-powertecscsi_store_term(struct device *dev, const char *buf, size_t len)
+powertecscsi_store_term(struct device *dev, struct device_attribute *attr, const char *buf, size_t len)
 {
 	struct expansion_card *ec = ECARD_DEV(dev);
 	struct Scsi_Host *host = ecard_get_drvdata(ec);
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 45b75dd..e6153fe 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -3146,8 +3146,8 @@
 }
 
 #define BLS buffer + len + size
-int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer, 
-		      char **start, off_t offset, int length, int inout)
+static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer, 
+			     char **start, off_t offset, int length, int inout)
 {
 	static u8 buff[512];
 	int size = 0;
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
new file mode 100644
index 0000000..3900e28
--- /dev/null
+++ b/drivers/scsi/ch.c
@@ -0,0 +1,1026 @@
+/*
+ * SCSI Media Changer device driver for Linux 2.6
+ *
+ *     (c) 1996-2003 Gerd Knorr <kraxel@bytesex.org>
+ *
+ */
+
+#define VERSION "0.25"
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/completion.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/ioctl32.h>
+#include <linux/compat.h>
+#include <linux/chio.h>			/* here are all the ioctls */
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_ioctl.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_request.h>
+#include <scsi/scsi_dbg.h>
+
+#define CH_DT_MAX       16
+#define CH_TYPES        8
+
+MODULE_DESCRIPTION("device driver for scsi media changer devices");
+MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org>");
+MODULE_LICENSE("GPL");
+
+static int init = 1;
+module_param(init, int, 0444);
+MODULE_PARM_DESC(init, \
+    "initialize element status on driver load (default: on)");
+
+static int timeout_move = 300;
+module_param(timeout_move, int, 0644);
+MODULE_PARM_DESC(timeout_move,"timeout for move commands "
+		 "(default: 300 seconds)");
+
+static int timeout_init = 3600;
+module_param(timeout_init, int, 0644);
+MODULE_PARM_DESC(timeout_init,"timeout for INITIALIZE ELEMENT STATUS "
+		 "(default: 3600 seconds)");
+
+static int verbose = 1;
+module_param(verbose, int, 0644);
+MODULE_PARM_DESC(verbose,"be verbose (default: on)");
+
+static int debug = 0;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug,"enable/disable debug messages, also prints more "
+		 "detailed sense codes on scsi errors (default: off)");
+
+static int dt_id[CH_DT_MAX] = { [ 0 ... (CH_DT_MAX-1) ] = -1 };
+static int dt_lun[CH_DT_MAX];
+module_param_array(dt_id,  int, NULL, 0444);
+module_param_array(dt_lun, int, NULL, 0444);
+
+/* tell the driver about vendor-specific slots */
+static int vendor_firsts[CH_TYPES-4];
+static int vendor_counts[CH_TYPES-4];
+module_param_array(vendor_firsts, int, NULL, 0444);
+module_param_array(vendor_counts, int, NULL, 0444);
+
+static char *vendor_labels[CH_TYPES-4] = {
+	"v0", "v1", "v2", "v3"
+};
+// module_param_string_array(vendor_labels, NULL, 0444);
+
+#define dprintk(fmt, arg...)    if (debug) \
+        printk(KERN_DEBUG "%s: " fmt, ch->name , ## arg)
+#define vprintk(fmt, arg...)    if (verbose) \
+        printk(KERN_INFO "%s: " fmt, ch->name , ## arg)
+
+/* ------------------------------------------------------------------- */
+
+#define MAX_RETRIES   1
+
+static int  ch_probe(struct device *);
+static int  ch_remove(struct device *);
+static int  ch_open(struct inode * inode, struct file * filp);
+static int  ch_release(struct inode * inode, struct file * filp);
+static int  ch_ioctl(struct inode * inode, struct file * filp,
+		     unsigned int cmd, unsigned long arg);
+#ifdef CONFIG_COMPAT
+static long ch_ioctl_compat(struct file * filp,
+			    unsigned int cmd, unsigned long arg);
+#endif
+
+static struct class * ch_sysfs_class;
+
+typedef struct {
+	struct list_head    list;
+	int                 minor;
+	char                name[8];
+	struct scsi_device  *device;
+	struct scsi_device  **dt;        /* ptrs to data transfer elements */
+	u_int               firsts[CH_TYPES];
+	u_int               counts[CH_TYPES];
+	u_int               unit_attention;
+	u_int		    voltags;
+	struct semaphore    lock;
+} scsi_changer;
+
+static LIST_HEAD(ch_devlist);
+static spinlock_t ch_devlist_lock = SPIN_LOCK_UNLOCKED;
+static int ch_devcount;
+
+static struct scsi_driver ch_template =
+{
+	.owner     	= THIS_MODULE,
+	.gendrv     	= {
+		.name	= "ch",
+		.probe  = ch_probe,
+		.remove = ch_remove,
+	},
+};
+
+static struct file_operations changer_fops =
+{
+	.owner        = THIS_MODULE,
+	.open         = ch_open,
+	.release      = ch_release,
+	.ioctl        = ch_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = ch_ioctl_compat,
+#endif
+};
+
+static struct {
+	unsigned char  sense;
+	unsigned char  asc;
+	unsigned char  ascq;
+	int	       errno;
+} err[] = {
+/* Just filled in what looks right. Hav'nt checked any standard paper for
+   these errno assignments, so they may be wrong... */
+	{
+		.sense  = ILLEGAL_REQUEST,
+		.asc    = 0x21,
+		.ascq   = 0x01,
+		.errno  = EBADSLT, /* Invalid element address */
+	},{
+		.sense  = ILLEGAL_REQUEST,
+		.asc    = 0x28,
+		.ascq   = 0x01,
+		.errno  = EBADE,   /* Import or export element accessed */
+	},{
+		.sense  = ILLEGAL_REQUEST,
+		.asc    = 0x3B,
+		.ascq   = 0x0D,
+		.errno  = EXFULL,  /* Medium destination element full */
+	},{
+		.sense  = ILLEGAL_REQUEST,
+		.asc    = 0x3B,
+		.ascq   = 0x0E,
+		.errno  = EBADE,   /* Medium source element empty */
+	},{
+		.sense  = ILLEGAL_REQUEST,
+		.asc    = 0x20,
+		.ascq   = 0x00,
+		.errno  = EBADRQC, /* Invalid command operation code */
+	},{
+	        /* end of list */
+	}
+};
+
+/* ------------------------------------------------------------------- */
+
+static int ch_find_errno(unsigned char *sense_buffer)
+{
+	int i,errno = 0;
+
+	/* Check to see if additional sense information is available */
+	if (sense_buffer[7]  > 5 &&
+	    sense_buffer[12] != 0) {
+		for (i = 0; err[i].errno != 0; i++) {
+			if (err[i].sense == sense_buffer[ 2] &&
+			    err[i].asc   == sense_buffer[12] &&
+			    err[i].ascq  == sense_buffer[13]) {
+				errno = -err[i].errno;
+				break;
+			}
+		}
+	}
+	if (errno == 0)
+		errno = -EIO;
+	return errno;
+}
+
+static int
+ch_do_scsi(scsi_changer *ch, unsigned char *cmd,
+	   void *buffer, unsigned buflength,
+	   enum dma_data_direction direction)
+{
+	int errno, retries = 0, timeout;
+	struct scsi_request *sr;
+	
+	sr = scsi_allocate_request(ch->device, GFP_KERNEL);
+	if (NULL == sr)
+		return -ENOMEM;
+
+	timeout = (cmd[0] == INITIALIZE_ELEMENT_STATUS)
+		? timeout_init : timeout_move;
+
+ retry:
+	errno = 0;
+	if (debug) {
+		dprintk("command: ");
+		__scsi_print_command(cmd);
+	}
+
+        scsi_wait_req(sr, cmd, buffer, buflength,
+		      timeout * HZ, MAX_RETRIES);
+
+	dprintk("result: 0x%x\n",sr->sr_result);
+	if (driver_byte(sr->sr_result) & DRIVER_SENSE) {
+		if (debug)
+			scsi_print_req_sense(ch->name, sr);
+		errno = ch_find_errno(sr->sr_sense_buffer);
+
+		switch(sr->sr_sense_buffer[2] & 0xf) {
+		case UNIT_ATTENTION:
+			ch->unit_attention = 1;
+			if (retries++ < 3)
+				goto retry;
+			break;
+		}
+	}
+	scsi_release_request(sr);
+	return errno;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int
+ch_elem_to_typecode(scsi_changer *ch, u_int elem)
+{
+	int i;
+	
+	for (i = 0; i < CH_TYPES; i++) {
+		if (elem >= ch->firsts[i]  &&
+		    elem <  ch->firsts[i] +
+	            ch->counts[i])
+			return i+1;
+	}
+	return 0;
+}
+
+static int
+ch_read_element_status(scsi_changer *ch, u_int elem, char *data)
+{
+	u_char  cmd[12];
+	u_char  *buffer;
+	int     result;
+	
+	buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
+	if(!buffer)
+		return -ENOMEM;
+	
+ retry:
+	memset(cmd,0,sizeof(cmd));
+	cmd[0] = READ_ELEMENT_STATUS;
+	cmd[1] = (ch->device->lun << 5) | 
+		(ch->voltags ? 0x10 : 0) |
+		ch_elem_to_typecode(ch,elem);
+	cmd[2] = (elem >> 8) & 0xff;
+	cmd[3] = elem        & 0xff;
+	cmd[5] = 1;
+	cmd[9] = 255;
+	if (0 == (result = ch_do_scsi(ch, cmd, buffer, 256, DMA_FROM_DEVICE))) {
+		if (((buffer[16] << 8) | buffer[17]) != elem) {
+			dprintk("asked for element 0x%02x, got 0x%02x\n",
+				elem,(buffer[16] << 8) | buffer[17]);
+			kfree(buffer);
+			return -EIO;
+		}
+		memcpy(data,buffer+16,16);
+	} else {
+		if (ch->voltags) {
+			ch->voltags = 0;
+			vprintk("device has no volume tag support\n");
+			goto retry;
+		}
+		dprintk("READ ELEMENT STATUS for element 0x%x failed\n",elem);
+	}
+	kfree(buffer);
+	return result;
+}
+
+static int 
+ch_init_elem(scsi_changer *ch)
+{
+	int err;
+	u_char cmd[6];
+
+	vprintk("INITIALIZE ELEMENT STATUS, may take some time ...\n");
+	memset(cmd,0,sizeof(cmd));
+	cmd[0] = INITIALIZE_ELEMENT_STATUS;
+	cmd[1] = ch->device->lun << 5;
+	err = ch_do_scsi(ch, cmd, NULL, 0, DMA_NONE);
+	vprintk("... finished\n");
+	return err;
+}
+
+static int
+ch_readconfig(scsi_changer *ch)
+{
+	u_char  cmd[10], data[16];
+	u_char  *buffer;
+	int     result,id,lun,i;
+	u_int   elem;
+
+	buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
+	if (!buffer)
+		return -ENOMEM;
+	memset(buffer,0,512);
+	
+	memset(cmd,0,sizeof(cmd));
+	cmd[0] = MODE_SENSE;
+	cmd[1] = ch->device->lun << 5;
+	cmd[2] = 0x1d;
+	cmd[4] = 255;
+	result = ch_do_scsi(ch, cmd, buffer, 255, DMA_FROM_DEVICE);
+	if (0 != result) {
+		cmd[1] |= (1<<3);
+		result  = ch_do_scsi(ch, cmd, buffer, 255, DMA_FROM_DEVICE);
+	}
+	if (0 == result) {
+		ch->firsts[CHET_MT] =
+			(buffer[buffer[3]+ 6] << 8) | buffer[buffer[3]+ 7];
+		ch->counts[CHET_MT] =
+			(buffer[buffer[3]+ 8] << 8) | buffer[buffer[3]+ 9];
+		ch->firsts[CHET_ST] =
+			(buffer[buffer[3]+10] << 8) | buffer[buffer[3]+11];
+		ch->counts[CHET_ST] =
+			(buffer[buffer[3]+12] << 8) | buffer[buffer[3]+13];
+		ch->firsts[CHET_IE] =
+			(buffer[buffer[3]+14] << 8) | buffer[buffer[3]+15];
+		ch->counts[CHET_IE] =
+			(buffer[buffer[3]+16] << 8) | buffer[buffer[3]+17];
+		ch->firsts[CHET_DT] =
+			(buffer[buffer[3]+18] << 8) | buffer[buffer[3]+19];
+		ch->counts[CHET_DT] =
+			(buffer[buffer[3]+20] << 8) | buffer[buffer[3]+21];
+		vprintk("type #1 (mt): 0x%x+%d [medium transport]\n",
+			ch->firsts[CHET_MT],
+			ch->counts[CHET_MT]);
+		vprintk("type #2 (st): 0x%x+%d [storage]\n",
+			ch->firsts[CHET_ST],
+			ch->counts[CHET_ST]);
+		vprintk("type #3 (ie): 0x%x+%d [import/export]\n",
+			ch->firsts[CHET_IE],
+			ch->counts[CHET_IE]);
+		vprintk("type #4 (dt): 0x%x+%d [data transfer]\n",
+			ch->firsts[CHET_DT],
+			ch->counts[CHET_DT]);
+	} else {
+		vprintk("reading element address assigment page failed!\n");
+	}
+	
+	/* vendor specific element types */
+	for (i = 0; i < 4; i++) {
+		if (0 == vendor_counts[i])
+			continue;
+		if (NULL == vendor_labels[i])
+			continue;
+		ch->firsts[CHET_V1+i] = vendor_firsts[i];
+		ch->counts[CHET_V1+i] = vendor_counts[i];
+		vprintk("type #%d (v%d): 0x%x+%d [%s, vendor specific]\n",
+			i+5,i+1,vendor_firsts[i],vendor_counts[i],
+			vendor_labels[i]);
+	}
+
+	/* look up the devices of the data transfer elements */
+	ch->dt = kmalloc(ch->counts[CHET_DT]*sizeof(struct scsi_device),
+			 GFP_KERNEL);
+	for (elem = 0; elem < ch->counts[CHET_DT]; elem++) {
+		id  = -1;
+		lun = 0;
+		if (elem < CH_DT_MAX  &&  -1 != dt_id[elem]) {
+			id  = dt_id[elem];
+			lun = dt_lun[elem];
+			vprintk("dt 0x%x: [insmod option] ",
+				elem+ch->firsts[CHET_DT]);
+		} else if (0 != ch_read_element_status
+			   (ch,elem+ch->firsts[CHET_DT],data)) {
+			vprintk("dt 0x%x: READ ELEMENT STATUS failed\n",
+				elem+ch->firsts[CHET_DT]);
+		} else {
+			vprintk("dt 0x%x: ",elem+ch->firsts[CHET_DT]);
+			if (data[6] & 0x80) {
+				if (verbose)
+					printk("not this SCSI bus\n");
+				ch->dt[elem] = NULL;
+			} else if (0 == (data[6] & 0x30)) {
+				if (verbose)
+					printk("ID/LUN unknown\n");
+				ch->dt[elem] = NULL;
+			} else {
+				id  = ch->device->id;
+				lun = 0;
+				if (data[6] & 0x20) id  = data[7];
+				if (data[6] & 0x10) lun = data[6] & 7;
+			}
+		}
+		if (-1 != id) {
+			if (verbose)
+				printk("ID %i, LUN %i, ",id,lun);
+			ch->dt[elem] =
+				scsi_device_lookup(ch->device->host,
+						   ch->device->channel,
+						   id,lun);
+			if (!ch->dt[elem]) {
+				/* should not happen */
+				if (verbose)
+					printk("Huh? device not found!\n");
+			} else {
+				if (verbose)
+					printk("name: %8.8s %16.16s %4.4s\n",
+					       ch->dt[elem]->vendor,
+					       ch->dt[elem]->model,
+					       ch->dt[elem]->rev);
+			}
+		}
+	}
+	ch->voltags = 1;
+	kfree(buffer);
+
+	return 0;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int
+ch_position(scsi_changer *ch, u_int trans, u_int elem, int rotate)
+{
+	u_char  cmd[10];
+	
+	dprintk("position: 0x%x\n",elem);
+	if (0 == trans)
+		trans = ch->firsts[CHET_MT];
+	memset(cmd,0,sizeof(cmd));
+	cmd[0]  = POSITION_TO_ELEMENT;
+	cmd[1]  = ch->device->lun << 5;
+	cmd[2]  = (trans >> 8) & 0xff;
+	cmd[3]  =  trans       & 0xff;
+	cmd[4]  = (elem  >> 8) & 0xff;
+	cmd[5]  =  elem        & 0xff;
+	cmd[8]  = rotate ? 1 : 0;
+	return ch_do_scsi(ch, cmd, NULL, 0, DMA_NONE);
+}
+
+static int
+ch_move(scsi_changer *ch, u_int trans, u_int src, u_int dest, int rotate)
+{
+	u_char  cmd[12];
+	
+	dprintk("move: 0x%x => 0x%x\n",src,dest);
+	if (0 == trans)
+		trans = ch->firsts[CHET_MT];
+	memset(cmd,0,sizeof(cmd));
+	cmd[0]  = MOVE_MEDIUM;
+	cmd[1]  = ch->device->lun << 5;
+	cmd[2]  = (trans >> 8) & 0xff;
+	cmd[3]  =  trans       & 0xff;
+	cmd[4]  = (src   >> 8) & 0xff;
+	cmd[5]  =  src         & 0xff;
+	cmd[6]  = (dest  >> 8) & 0xff;
+	cmd[7]  =  dest        & 0xff;
+	cmd[10] = rotate ? 1 : 0;
+	return ch_do_scsi(ch, cmd, NULL,0, DMA_NONE);
+}
+
+static int
+ch_exchange(scsi_changer *ch, u_int trans, u_int src,
+	    u_int dest1, u_int dest2, int rotate1, int rotate2)
+{
+	u_char  cmd[12];
+	
+	dprintk("exchange: 0x%x => 0x%x => 0x%x\n",
+		src,dest1,dest2);
+	if (0 == trans)
+		trans = ch->firsts[CHET_MT];
+	memset(cmd,0,sizeof(cmd));
+	cmd[0]  = EXCHANGE_MEDIUM;
+	cmd[1]  = ch->device->lun << 5;
+	cmd[2]  = (trans >> 8) & 0xff;
+	cmd[3]  =  trans       & 0xff;
+	cmd[4]  = (src   >> 8) & 0xff;
+	cmd[5]  =  src         & 0xff;
+	cmd[6]  = (dest1 >> 8) & 0xff;
+	cmd[7]  =  dest1       & 0xff;
+	cmd[8]  = (dest2 >> 8) & 0xff;
+	cmd[9]  =  dest2       & 0xff;
+	cmd[10] = (rotate1 ? 1 : 0) | (rotate2 ? 2 : 0);
+	
+	return ch_do_scsi(ch, cmd, NULL,0, DMA_NONE);
+}
+
+static void
+ch_check_voltag(char *tag)
+{
+	int i;
+
+	for (i = 0; i < 32; i++) {
+		/* restrict to ascii */
+		if (tag[i] >= 0x7f || tag[i] < 0x20)
+			tag[i] = ' ';
+		/* don't allow search wildcards */
+		if (tag[i] == '?' ||
+		    tag[i] == '*')
+			tag[i] = ' ';
+	}
+}
+
+static int
+ch_set_voltag(scsi_changer *ch, u_int elem,
+	      int alternate, int clear, u_char *tag)
+{
+	u_char  cmd[12];
+	u_char  *buffer;
+	int result;
+
+	buffer = kmalloc(512, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+	memset(buffer,0,512);
+
+	dprintk("%s %s voltag: 0x%x => \"%s\"\n",
+		clear     ? "clear"     : "set",
+		alternate ? "alternate" : "primary",
+		elem, tag);
+	memset(cmd,0,sizeof(cmd));
+	cmd[0]  = SEND_VOLUME_TAG;
+	cmd[1] = (ch->device->lun << 5) | 
+		ch_elem_to_typecode(ch,elem);
+	cmd[2] = (elem >> 8) & 0xff;
+	cmd[3] = elem        & 0xff;
+	cmd[5] = clear
+		? (alternate ? 0x0d : 0x0c)
+		: (alternate ? 0x0b : 0x0a);
+	
+	cmd[9] = 255;
+
+	memcpy(buffer,tag,32);
+	ch_check_voltag(buffer);
+
+	result = ch_do_scsi(ch, cmd, buffer, 256, DMA_TO_DEVICE);
+	kfree(buffer);
+	return result;
+}
+
+static int ch_gstatus(scsi_changer *ch, int type, unsigned char *dest)
+{
+	int retval = 0;
+	u_char data[16];
+	unsigned int i;
+	
+	down(&ch->lock);
+	for (i = 0; i < ch->counts[type]; i++) {
+		if (0 != ch_read_element_status
+		    (ch, ch->firsts[type]+i,data)) {
+			retval = -EIO;
+			break;
+		}
+		put_user(data[2], dest+i);
+		if (data[2] & CESTATUS_EXCEPT)
+			vprintk("element 0x%x: asc=0x%x, ascq=0x%x\n",
+				ch->firsts[type]+i,
+				(int)data[4],(int)data[5]);
+		retval = ch_read_element_status
+			(ch, ch->firsts[type]+i,data);
+		if (0 != retval)
+			break;
+	}
+	up(&ch->lock);
+	return retval;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int
+ch_release(struct inode *inode, struct file *file)
+{
+	scsi_changer *ch = file->private_data;
+
+	scsi_device_put(ch->device);
+	file->private_data = NULL;
+	return 0;
+}
+
+static int
+ch_open(struct inode *inode, struct file *file)
+{
+	scsi_changer *tmp, *ch;
+	int minor = iminor(inode);
+
+	spin_lock(&ch_devlist_lock);
+	ch = NULL;
+	list_for_each_entry(tmp,&ch_devlist,list) {
+		if (tmp->minor == minor)
+			ch = tmp;
+	}
+	if (NULL == ch || scsi_device_get(ch->device)) {
+		spin_unlock(&ch_devlist_lock);
+		return -ENXIO;
+	}
+	spin_unlock(&ch_devlist_lock);
+
+	file->private_data = ch;
+	return 0;
+}
+
+static int
+ch_checkrange(scsi_changer *ch, unsigned int type, unsigned int unit)
+{
+	if (type >= CH_TYPES  ||  unit >= ch->counts[type])
+		return -1;
+	return 0;
+}
+
+static int ch_ioctl(struct inode * inode, struct file * file,
+		    unsigned int cmd, unsigned long arg)
+{
+	scsi_changer *ch = file->private_data;
+	int retval;
+	
+	switch (cmd) {
+	case CHIOGPARAMS:
+	{
+		struct changer_params params;
+		
+		params.cp_curpicker = 0;
+		params.cp_npickers  = ch->counts[CHET_MT];
+		params.cp_nslots    = ch->counts[CHET_ST];
+		params.cp_nportals  = ch->counts[CHET_IE];
+		params.cp_ndrives   = ch->counts[CHET_DT];
+		
+		if (copy_to_user((void *) arg, &params, sizeof(params)))
+			return -EFAULT;
+		return 0;
+	}
+	case CHIOGVPARAMS:
+	{
+		struct changer_vendor_params vparams;
+
+		memset(&vparams,0,sizeof(vparams));
+		if (ch->counts[CHET_V1]) {
+			vparams.cvp_n1  = ch->counts[CHET_V1];
+			strncpy(vparams.cvp_label1,vendor_labels[0],16);
+		}
+		if (ch->counts[CHET_V2]) {
+			vparams.cvp_n2  = ch->counts[CHET_V2];
+			strncpy(vparams.cvp_label2,vendor_labels[1],16);
+		}
+		if (ch->counts[CHET_V3]) {
+			vparams.cvp_n3  = ch->counts[CHET_V3];
+			strncpy(vparams.cvp_label3,vendor_labels[2],16);
+		}
+		if (ch->counts[CHET_V4]) {
+			vparams.cvp_n4  = ch->counts[CHET_V4];
+			strncpy(vparams.cvp_label4,vendor_labels[3],16);
+		}
+		if (copy_to_user((void *) arg, &vparams, sizeof(vparams)))
+			return -EFAULT;
+		return 0;
+	}
+	
+	case CHIOPOSITION:
+	{
+		struct changer_position pos;
+		
+		if (copy_from_user(&pos, (void*)arg, sizeof (pos)))
+			return -EFAULT;
+
+		if (0 != ch_checkrange(ch, pos.cp_type, pos.cp_unit)) {
+			dprintk("CHIOPOSITION: invalid parameter\n");
+			return -EBADSLT;
+		}
+		down(&ch->lock);
+		retval = ch_position(ch,0,
+				     ch->firsts[pos.cp_type] + pos.cp_unit,
+				     pos.cp_flags & CP_INVERT);
+		up(&ch->lock);
+		return retval;
+	}
+	
+	case CHIOMOVE:
+	{
+		struct changer_move mv;
+
+		if (copy_from_user(&mv, (void*)arg, sizeof (mv)))
+			return -EFAULT;
+
+		if (0 != ch_checkrange(ch, mv.cm_fromtype, mv.cm_fromunit) ||
+		    0 != ch_checkrange(ch, mv.cm_totype,   mv.cm_tounit  )) {
+			dprintk("CHIOMOVE: invalid parameter\n");
+			return -EBADSLT;
+		}
+		
+		down(&ch->lock);
+		retval = ch_move(ch,0,
+				 ch->firsts[mv.cm_fromtype] + mv.cm_fromunit,
+				 ch->firsts[mv.cm_totype]   + mv.cm_tounit,
+				 mv.cm_flags & CM_INVERT);
+		up(&ch->lock);
+		return retval;
+	}
+
+	case CHIOEXCHANGE:
+	{
+		struct changer_exchange mv;
+		
+		if (copy_from_user(&mv, (void*)arg, sizeof (mv)))
+			return -EFAULT;
+
+		if (0 != ch_checkrange(ch, mv.ce_srctype,  mv.ce_srcunit ) ||
+		    0 != ch_checkrange(ch, mv.ce_fdsttype, mv.ce_fdstunit) ||
+		    0 != ch_checkrange(ch, mv.ce_sdsttype, mv.ce_sdstunit)) {
+			dprintk("CHIOEXCHANGE: invalid parameter\n");
+			return -EBADSLT;
+		}
+		
+		down(&ch->lock);
+		retval = ch_exchange
+			(ch,0,
+			 ch->firsts[mv.ce_srctype]  + mv.ce_srcunit,
+			 ch->firsts[mv.ce_fdsttype] + mv.ce_fdstunit,
+			 ch->firsts[mv.ce_sdsttype] + mv.ce_sdstunit,
+			 mv.ce_flags & CE_INVERT1, mv.ce_flags & CE_INVERT2);
+		up(&ch->lock);
+		return retval;
+	}
+
+	case CHIOGSTATUS:
+	{
+		struct changer_element_status ces;
+		
+		if (copy_from_user(&ces, (void*)arg, sizeof (ces)))
+			return -EFAULT;
+		if (ces.ces_type < 0 || ces.ces_type >= CH_TYPES)
+			return -EINVAL;
+
+		return ch_gstatus(ch, ces.ces_type, ces.ces_data);
+	}
+
+	case CHIOGELEM:
+	{
+		struct changer_get_element cge;
+		u_char  cmd[12];
+		u_char  *buffer;
+		unsigned int elem;
+		int     result,i;
+		
+		if (copy_from_user(&cge, (void*)arg, sizeof (cge)))
+			return -EFAULT;
+
+		if (0 != ch_checkrange(ch, cge.cge_type, cge.cge_unit))
+			return -EINVAL;
+		elem = ch->firsts[cge.cge_type] + cge.cge_unit;
+		
+		buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
+		if (!buffer)
+			return -ENOMEM;
+		down(&ch->lock);
+		
+	voltag_retry:
+		memset(cmd,0,sizeof(cmd));
+		cmd[0] = READ_ELEMENT_STATUS;
+		cmd[1] = (ch->device->lun << 5) |
+			(ch->voltags ? 0x10 : 0) |
+			ch_elem_to_typecode(ch,elem);
+		cmd[2] = (elem >> 8) & 0xff;
+		cmd[3] = elem        & 0xff;
+		cmd[5] = 1;
+		cmd[9] = 255;
+		
+		if (0 == (result = ch_do_scsi(ch, cmd, buffer, 256, DMA_FROM_DEVICE))) {
+			cge.cge_status = buffer[18];
+			cge.cge_flags = 0;
+			if (buffer[18] & CESTATUS_EXCEPT) {
+				cge.cge_errno = EIO;
+			}
+			if (buffer[25] & 0x80) {
+				cge.cge_flags |= CGE_SRC;
+				if (buffer[25] & 0x40)
+					cge.cge_flags |= CGE_INVERT;
+				elem = (buffer[26]<<8) | buffer[27];
+				for (i = 0; i < 4; i++) {
+					if (elem >= ch->firsts[i] &&
+					    elem <  ch->firsts[i] + ch->counts[i]) {
+						cge.cge_srctype = i;
+						cge.cge_srcunit = elem-ch->firsts[i];
+					}
+				}
+			}
+			if ((buffer[22] & 0x30) == 0x30) {
+				cge.cge_flags |= CGE_IDLUN;
+				cge.cge_id  = buffer[23];
+				cge.cge_lun = buffer[22] & 7;
+			}
+			if (buffer[9] & 0x80) {
+				cge.cge_flags |= CGE_PVOLTAG;
+				memcpy(cge.cge_pvoltag,buffer+28,36);
+			}
+			if (buffer[9] & 0x40) {
+				cge.cge_flags |= CGE_AVOLTAG;
+				memcpy(cge.cge_avoltag,buffer+64,36);
+			}
+		} else if (ch->voltags) {
+			ch->voltags = 0;
+			vprintk("device has no volume tag support\n");
+			goto voltag_retry;
+		}
+		kfree(buffer);
+		up(&ch->lock);
+		
+		if (copy_to_user((void*)arg, &cge, sizeof (cge)))
+			return -EFAULT;
+		return result;
+	}
+
+	case CHIOINITELEM:
+	{
+		down(&ch->lock);
+		retval = ch_init_elem(ch);
+		up(&ch->lock);
+		return retval;
+	}
+		
+	case CHIOSVOLTAG:
+	{
+		struct changer_set_voltag csv;
+		int elem;
+
+		if (copy_from_user(&csv, (void*)arg, sizeof(csv)))
+			return -EFAULT;
+
+		if (0 != ch_checkrange(ch, csv.csv_type, csv.csv_unit)) {
+			dprintk("CHIOSVOLTAG: invalid parameter\n");
+			return -EBADSLT;
+		}
+		elem = ch->firsts[csv.csv_type] + csv.csv_unit;
+		down(&ch->lock);
+		retval = ch_set_voltag(ch, elem,
+				       csv.csv_flags & CSV_AVOLTAG,
+				       csv.csv_flags & CSV_CLEARTAG,
+				       csv.csv_voltag);
+		up(&ch->lock);
+		return retval;
+	}
+
+	default:
+		return scsi_ioctl(ch->device, cmd, (void*)arg);
+
+	}
+}
+
+#ifdef CONFIG_COMPAT
+
+struct changer_element_status32 {
+	int		ces_type;
+	compat_uptr_t	ces_data;
+};
+#define CHIOGSTATUS32  _IOW('c', 8,struct changer_element_status32)
+
+static long ch_ioctl_compat(struct file * file,
+			    unsigned int cmd, unsigned long arg)
+{
+	scsi_changer *ch = file->private_data;
+	
+	switch (cmd) {
+	case CHIOGPARAMS:
+	case CHIOGVPARAMS:
+	case CHIOPOSITION:
+	case CHIOMOVE:
+	case CHIOEXCHANGE:
+	case CHIOGELEM:
+	case CHIOINITELEM:
+	case CHIOSVOLTAG:
+		/* compatible */
+		return ch_ioctl(NULL /* inode, unused */,
+				file, cmd, arg);
+	case CHIOGSTATUS32:
+	{
+		struct changer_element_status32 ces32;
+		unsigned char *data;
+		
+		if (copy_from_user(&ces32, (void*)arg, sizeof (ces32)))
+			return -EFAULT;
+		if (ces32.ces_type < 0 || ces32.ces_type >= CH_TYPES)
+			return -EINVAL;
+
+		data = compat_ptr(ces32.ces_data);
+		return ch_gstatus(ch, ces32.ces_type, data);
+	}
+	default:
+		// return scsi_ioctl_compat(ch->device, cmd, (void*)arg);
+		return -ENOIOCTLCMD;
+
+	}
+}
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+static int ch_probe(struct device *dev)
+{
+	struct scsi_device *sd = to_scsi_device(dev);
+	scsi_changer *ch;
+	
+	if (sd->type != TYPE_MEDIUM_CHANGER)
+		return -ENODEV;
+    
+	ch = kmalloc(sizeof(*ch), GFP_KERNEL);
+	if (NULL == ch)
+		return -ENOMEM;
+
+	memset(ch,0,sizeof(*ch));
+	ch->minor = ch_devcount;
+	sprintf(ch->name,"ch%d",ch->minor);
+	init_MUTEX(&ch->lock);
+	ch->device = sd;
+	ch_readconfig(ch);
+	if (init)
+		ch_init_elem(ch);
+
+	devfs_mk_cdev(MKDEV(SCSI_CHANGER_MAJOR,ch->minor),
+		      S_IFCHR | S_IRUGO | S_IWUGO, ch->name);
+	class_device_create(ch_sysfs_class,
+			    MKDEV(SCSI_CHANGER_MAJOR,ch->minor),
+			    dev, "s%s", ch->name);
+
+	printk(KERN_INFO "Attached scsi changer %s "
+	       "at scsi%d, channel %d, id %d, lun %d\n", 
+	       ch->name, sd->host->host_no, sd->channel, sd->id, sd->lun);
+	
+	spin_lock(&ch_devlist_lock);
+	list_add_tail(&ch->list,&ch_devlist);
+	ch_devcount++;
+	spin_unlock(&ch_devlist_lock);
+	return 0;
+}
+
+static int ch_remove(struct device *dev)
+{
+	struct scsi_device *sd = to_scsi_device(dev);
+	scsi_changer *tmp, *ch;
+
+	spin_lock(&ch_devlist_lock);
+	ch = NULL;
+	list_for_each_entry(tmp,&ch_devlist,list) {
+		if (tmp->device == sd)
+			ch = tmp;
+	}
+	BUG_ON(NULL == ch);
+	list_del(&ch->list);
+	spin_unlock(&ch_devlist_lock);
+
+	class_device_destroy(ch_sysfs_class,
+			     MKDEV(SCSI_CHANGER_MAJOR,ch->minor));
+	devfs_remove(ch->name);
+	kfree(ch->dt);
+	kfree(ch);
+	ch_devcount--;
+	return 0;
+}
+
+static int __init init_ch_module(void)
+{
+	int rc;
+	
+	printk(KERN_INFO "SCSI Media Changer driver v" VERSION " \n");
+        ch_sysfs_class = class_create(THIS_MODULE, "scsi_changer");
+        if (IS_ERR(ch_sysfs_class)) {
+		rc = PTR_ERR(ch_sysfs_class);
+		return rc;
+        }
+	rc = register_chrdev(SCSI_CHANGER_MAJOR,"ch",&changer_fops);
+	if (rc < 0) {
+		printk("Unable to get major %d for SCSI-Changer\n",
+		       SCSI_CHANGER_MAJOR);
+		goto fail1;
+	}
+	rc = scsi_register_driver(&ch_template.gendrv);
+	if (rc < 0)
+		goto fail2;
+	return 0;
+
+ fail2:
+	unregister_chrdev(SCSI_CHANGER_MAJOR, "ch");
+ fail1:
+	class_destroy(ch_sysfs_class);
+	return rc;
+}
+
+static void __exit exit_ch_module(void) 
+{
+	scsi_unregister_driver(&ch_template.gendrv);
+	unregister_chrdev(SCSI_CHANGER_MAJOR, "ch");
+	class_destroy(ch_sysfs_class);
+}
+
+module_init(init_ch_module);
+module_exit(exit_ch_module);
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index cca41cf..ae13c00 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -1310,7 +1310,7 @@
  * @cmd - some command for this host (for fetching hooks)
  * Returns: SUCCESS (0x2002) on success, else FAILED (0x2003).
  */
-static int dc395x_eh_bus_reset(struct scsi_cmnd *cmd)
+static int __dc395x_eh_bus_reset(struct scsi_cmnd *cmd)
 {
 	struct AdapterCtlBlk *acb =
 		(struct AdapterCtlBlk *)cmd->device->host->hostdata;
@@ -1356,6 +1356,16 @@
 	return SUCCESS;
 }
 
+static int dc395x_eh_bus_reset(struct scsi_cmnd *cmd)
+{
+	int rc;
+
+	spin_lock_irq(cmd->device->host->host_lock);
+	rc = __dc395x_eh_bus_reset(cmd);
+	spin_unlock_irq(cmd->device->host->host_lock);
+
+	return rc;
+}
 
 /*
  * abort an errant SCSI command
diff --git a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c
index 1d22424..7905b90 100644
--- a/drivers/scsi/dmx3191d.c
+++ b/drivers/scsi/dmx3191d.c
@@ -61,8 +61,6 @@
 	.queuecommand		= NCR5380_queue_command,
 	.eh_abort_handler	= NCR5380_abort,
 	.eh_bus_reset_handler	= NCR5380_bus_reset,
-	.eh_device_reset_handler= NCR5380_device_reset,
-	.eh_host_reset_handler	= NCR5380_host_reset,
 	.can_queue		= 32,
 	.this_id		= 7,
 	.sg_tablesize		= SG_ALL,
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 53c9b93..bbe346b 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -34,7 +34,6 @@
 
 #define ADDR32 (0)
 
-#include <linux/version.h>
 #include <linux/module.h>
 
 MODULE_AUTHOR("Deanna Bonds, with _lots_ of help from Mark Salyzyn");
@@ -113,7 +112,6 @@
 static int sys_tbl_ind = 0;
 static int sys_tbl_len = 0;
 
-static adpt_hba* hbas[DPTI_MAX_HBA];
 static adpt_hba* hba_chain = NULL;
 static int hba_count = 0;
 
@@ -691,7 +689,7 @@
 	u32 msg[4];
 	u32 rcode;
 	int old_state;
-	struct adpt_device* d = (void*) cmd->device->hostdata;
+	struct adpt_device* d = cmd->device->hostdata;
 
 	pHba = (void*) cmd->device->host->hostdata[0];
 	printk(KERN_INFO"%s: Trying to reset device\n",pHba->name);
@@ -707,7 +705,7 @@
 
 	old_state = d->state;
 	d->state |= DPTI_DEV_RESET;
-	if( (rcode = adpt_i2o_post_wait(pHba, (void*)msg,sizeof(msg), FOREVER)) ){
+	if( (rcode = adpt_i2o_post_wait(pHba, msg,sizeof(msg), FOREVER)) ){
 		d->state = old_state;
 		if(rcode == -EOPNOTSUPP ){
 			printk(KERN_INFO"%s: Device reset not supported\n",pHba->name);
@@ -737,7 +735,7 @@
 	msg[1] = (I2O_HBA_BUS_RESET<<24|HOST_TID<<12|pHba->channel[cmd->device->channel].tid);
 	msg[2] = 0;
 	msg[3] = 0;
-	if(adpt_i2o_post_wait(pHba, (void*)msg,sizeof(msg), FOREVER) ){
+	if(adpt_i2o_post_wait(pHba, msg,sizeof(msg), FOREVER) ){
 		printk(KERN_WARNING"%s: Bus reset failed.\n",pHba->name);
 		return FAILED;
 	} else {
@@ -747,7 +745,7 @@
 }
 
 // This version of reset is called by the eh_error_handler
-static int adpt_reset(struct scsi_cmnd* cmd)
+static int __adpt_reset(struct scsi_cmnd* cmd)
 {
 	adpt_hba* pHba;
 	int rcode;
@@ -763,6 +761,17 @@
 	}
 }
 
+static int adpt_reset(struct scsi_cmnd* cmd)
+{
+	int rc;
+
+	spin_lock_irq(cmd->device->host->host_lock);
+	rc = __adpt_reset(cmd);
+	spin_unlock_irq(cmd->device->host->host_lock);
+
+	return rc;
+}
+
 // This version of reset is called by the ioctls and indirectly from eh_error_handler via adpt_reset
 static int adpt_hba_reset(adpt_hba* pHba)
 {
@@ -875,7 +884,6 @@
 	void __iomem *msg_addr_virt = NULL;
 
 	int raptorFlag = FALSE;
-	int i;
 
 	if(pci_enable_device(pDev)) {
 		return -EINVAL;
@@ -935,12 +943,6 @@
 	memset(pHba, 0, sizeof(adpt_hba));
 
 	down(&adpt_configuration_lock);
-	for(i=0;i<DPTI_MAX_HBA;i++) {
-		if(hbas[i]==NULL) {
-			hbas[i]=pHba;
-			break;
-		}
-	}
 
 	if(hba_chain != NULL){
 		for(p = hba_chain; p->next; p = p->next);
@@ -950,7 +952,7 @@
 	}
 	pHba->next = NULL;
 	pHba->unit = hba_count;
-	sprintf(pHba->name, "dpti%d", i);
+	sprintf(pHba->name, "dpti%d", hba_count);
 	hba_count++;
 	
 	up(&adpt_configuration_lock);
@@ -1015,11 +1017,6 @@
 	if(pHba->host){
 		free_irq(pHba->host->irq, pHba);
 	}
-	for(i=0;i<DPTI_MAX_HBA;i++) {
-		if(hbas[i]==pHba) {
-			hbas[i] = NULL;
-		}
-	}
 	p2 = NULL;
 	for( p1 = hba_chain; p1; p2 = p1,p1=p1->next){
 		if(p1 == pHba) {
@@ -1076,12 +1073,7 @@
 
 static int adpt_init(void)
 {
-	int i;
-
 	printk("Loading Adaptec I2O RAID: Version " DPT_I2O_VERSION "\n");
-	for (i = 0; i < DPTI_MAX_HBA; i++) {
-		hbas[i] = NULL;
-	}
 #ifdef REBOOT_NOTIFIER
 	register_reboot_notifier(&adpt_reboot_notifier);
 #endif
@@ -1133,11 +1125,11 @@
 	struct adpt_i2o_post_wait_data *p1, *p2;
 	struct adpt_i2o_post_wait_data *wait_data =
 		kmalloc(sizeof(struct adpt_i2o_post_wait_data),GFP_KERNEL);
-	adpt_wait_queue_t wait;
+	DECLARE_WAITQUEUE(wait, current);
 
-	if(!wait_data){
+	if (!wait_data)
 		return -ENOMEM;
-	}
+
 	/*
 	 * The spin locking is needed to keep anyone from playing
 	 * with the queue pointers and id while we do the same
@@ -1155,12 +1147,7 @@
 	wait_data->wq = &adpt_wq_i2o_post;
 	wait_data->status = -ETIMEDOUT;
 
-	// this code is taken from kernel/sched.c:interruptible_sleep_on_timeout
-	wait.task = current;
-	init_waitqueue_entry(&wait, current);
-	spin_lock_irqsave(&adpt_wq_i2o_post.lock, flags);
-	__add_wait_queue(&adpt_wq_i2o_post, &wait);
-	spin_unlock(&adpt_wq_i2o_post.lock);
+	add_wait_queue(&adpt_wq_i2o_post, &wait);
 
 	msg[2] |= 0x80000000 | ((u32)wait_data->id);
 	timeout *= HZ;
@@ -1182,9 +1169,7 @@
 		if(pHba->host)
 			spin_lock_irq(pHba->host->host_lock);
 	}
-	spin_lock_irq(&adpt_wq_i2o_post.lock);
-	__remove_wait_queue(&adpt_wq_i2o_post, &wait);
-	spin_unlock_irqrestore(&adpt_wq_i2o_post.lock, flags);
+	remove_wait_queue(&adpt_wq_i2o_post, &wait);
 
 	if(status == -ETIMEDOUT){
 		printk(KERN_INFO"dpti%d: POST WAIT TIMEOUT\n",pHba->unit);
@@ -1454,7 +1439,7 @@
 			return -ENOMEM;
 		}
 		
-		d->controller = (void*)pHba;
+		d->controller = pHba;
 		d->next = NULL;
 
 		memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry));
@@ -1825,9 +1810,9 @@
 	memset(&si, 0, sizeof(si));
 
 	si.osType = OS_LINUX;
-	si.osMajorVersion = (u8) (LINUX_VERSION_CODE >> 16);
-	si.osMinorVersion = (u8) (LINUX_VERSION_CODE >> 8 & 0x0ff);
-	si.osRevision =     (u8) (LINUX_VERSION_CODE & 0x0ff);
+	si.osMajorVersion = 0;
+	si.osMinorVersion = 0;
+	si.osRevision = 0;
 	si.busType = SI_PCI_BUS;
 	si.processorFamily = DPTI_sig.dsProcessorFamily;
 
@@ -2000,7 +1985,7 @@
 	struct scsi_cmnd* cmd;
 	adpt_hba* pHba = dev_id;
 	u32 m;
-	ulong reply;
+	void __iomem *reply;
 	u32 status=0;
 	u32 context;
 	ulong flags = 0;
@@ -2025,11 +2010,11 @@
 				goto out;
 			}
 		}
-		reply = (ulong)bus_to_virt(m);
+		reply = bus_to_virt(m);
 
 		if (readl(reply) & MSG_FAIL) {
 			u32 old_m = readl(reply+28); 
-			ulong msg;
+			void __iomem *msg;
 			u32 old_context;
 			PDEBUG("%s: Failed message\n",pHba->name);
 			if(old_m >= 0x100000){
@@ -2038,16 +2023,16 @@
 				continue;
 			}
 			// Transaction context is 0 in failed reply frame
-			msg = (ulong)(pHba->msg_addr_virt + old_m);
+			msg = pHba->msg_addr_virt + old_m;
 			old_context = readl(msg+12);
 			writel(old_context, reply+12);
 			adpt_send_nop(pHba, old_m);
 		} 
 		context = readl(reply+8);
 		if(context & 0x40000000){ // IOCTL
-			ulong p = (ulong)(readl(reply+12));
-			if( p != 0) {
-				memcpy((void*)p, (void*)reply, REPLY_FRAME_SIZE * 4);
+			void *p = (void *)readl(reply+12);
+			if( p != NULL) {
+				memcpy_fromio(p, reply, REPLY_FRAME_SIZE * 4);
 			}
 			// All IOCTLs will also be post wait
 		}
@@ -2231,7 +2216,7 @@
 }
 
 
-static s32 adpt_i2o_to_scsi(ulong reply, struct scsi_cmnd* cmd)
+static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd)
 {
 	adpt_hba* pHba;
 	u32 hba_status;
@@ -2323,7 +2308,7 @@
 			u32 len = sizeof(cmd->sense_buffer);
 			len = (len > 40) ?  40 : len;
 			// Copy over the sense data
-			memcpy(cmd->sense_buffer, (void*)(reply+28) , len);
+			memcpy_fromio(cmd->sense_buffer, (reply+28) , len);
 			if(cmd->sense_buffer[0] == 0x70 /* class 7 */ && 
 			   cmd->sense_buffer[2] == DATA_PROTECT ){
 				/* This is to handle an array failed */
@@ -2438,7 +2423,7 @@
 					return -ENOMEM;
 				}
 				
-				d->controller = (void*)pHba;
+				d->controller = pHba;
 				d->next = NULL;
 
 				memcpy(&d->lct_data, &lct->lct_entry[i], sizeof(i2o_lct_entry));
@@ -2985,8 +2970,8 @@
 		sys_tbl->iops[count].frame_size = pHba->status_block->inbound_frame_size;
 		sys_tbl->iops[count].last_changed = sys_tbl_ind - 1; // ??
 		sys_tbl->iops[count].iop_capabilities = pHba->status_block->iop_capabilities;
-		sys_tbl->iops[count].inbound_low = (u32)virt_to_bus((void*)pHba->post_port);
-		sys_tbl->iops[count].inbound_high = (u32)((u64)virt_to_bus((void*)pHba->post_port)>>32);
+		sys_tbl->iops[count].inbound_low = (u32)virt_to_bus(pHba->post_port);
+		sys_tbl->iops[count].inbound_high = (u32)((u64)virt_to_bus(pHba->post_port)>>32);
 
 		count++;
 	}
diff --git a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h
index 426e15d..489194a 100644
--- a/drivers/scsi/dpti.h
+++ b/drivers/scsi/dpti.h
@@ -20,15 +20,7 @@
 #ifndef _DPT_H
 #define _DPT_H
 
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,00)
-#define MAX_TO_IOP_MESSAGES   (210)
-#else
 #define MAX_TO_IOP_MESSAGES   (255)
-#endif
 #define MAX_FROM_IOP_MESSAGES (255)
 
 
@@ -296,7 +288,7 @@
 static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba);
 static s32 adpt_i2o_hrt_get(adpt_hba* pHba);
 static s32 adpt_scsi_to_i2o(adpt_hba* pHba, struct scsi_cmnd* cmd, struct adpt_device* dptdevice);
-static s32 adpt_i2o_to_scsi(ulong reply, struct scsi_cmnd* cmd);
+static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd);
 static s32 adpt_scsi_register(adpt_hba* pHba,struct scsi_host_template * sht);
 static s32 adpt_hba_reset(adpt_hba* pHba);
 static s32 adpt_i2o_reset_hba(adpt_hba* pHba);
@@ -321,10 +313,6 @@
 static void adpt_delay(int millisec);
 #endif
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-static struct pci_dev* adpt_pci_find_device(uint vendor, struct pci_dev* from);
-#endif
-
 #if defined __ia64__ 
 static void adpt_ia64_info(sysInfo_S* si);
 #endif
diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c
index da1aaa4..ab9de39 100644
--- a/drivers/scsi/dtc.c
+++ b/drivers/scsi/dtc.c
@@ -482,8 +482,6 @@
 	.queuecommand			= dtc_queue_command,
 	.eh_abort_handler		= dtc_abort,
 	.eh_bus_reset_handler		= dtc_bus_reset,
-	.eh_device_reset_handler	= dtc_device_reset,
-	.eh_host_reset_handler          = dtc_host_reset,
 	.bios_param     		= dtc_biosparam,
 	.can_queue      		= CAN_QUEUE,
 	.this_id        		= 7,
diff --git a/drivers/scsi/dtc.h b/drivers/scsi/dtc.h
index c4bcdbf..ed73629 100644
--- a/drivers/scsi/dtc.h
+++ b/drivers/scsi/dtc.h
@@ -34,8 +34,6 @@
 static int dtc_detect(Scsi_Host_Template *);
 static int dtc_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 static int dtc_bus_reset(Scsi_Cmnd *);
-static int dtc_device_reset(Scsi_Cmnd *);
-static int dtc_host_reset(Scsi_Cmnd *);
 
 #ifndef CMD_PER_LUN
 #define CMD_PER_LUN 2
@@ -86,8 +84,6 @@
 #define NCR5380_queue_command		dtc_queue_command
 #define NCR5380_abort			dtc_abort
 #define NCR5380_bus_reset		dtc_bus_reset
-#define NCR5380_device_reset		dtc_device_reset
-#define NCR5380_host_reset		dtc_host_reset
 #define NCR5380_proc_info		dtc_proc_info 
 
 /* 15 12 11 10
diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c
index 81d16cf..1bb8727 100644
--- a/drivers/scsi/eata.c
+++ b/drivers/scsi/eata.c
@@ -518,8 +518,6 @@
 	.release = eata2x_release,
 	.queuecommand = eata2x_queuecommand,
 	.eh_abort_handler = eata2x_eh_abort,
-	.eh_device_reset_handler = NULL,
-	.eh_bus_reset_handler = NULL,
 	.eh_host_reset_handler = eata2x_eh_host_reset,
 	.bios_param = eata2x_bios_param,
 	.slave_configure = eata2x_slave_configure,
@@ -1950,16 +1948,20 @@
 	       ha->board_name, SCarg->device->channel, SCarg->device->id,
 	       SCarg->device->lun, SCarg->pid);
 
+	spin_lock_irq(shost->host_lock);
+
 	if (SCarg->host_scribble == NULL)
 		printk("%s: reset, pid %ld inactive.\n", ha->board_name, SCarg->pid);
 
 	if (ha->in_reset) {
 		printk("%s: reset, exit, already in reset.\n", ha->board_name);
+		spin_unlock_irq(shost->host_lock);
 		return FAILED;
 	}
 
 	if (wait_on_busy(shost->io_port, MAXLOOP)) {
 		printk("%s: reset, exit, timeout error.\n", ha->board_name);
+		spin_unlock_irq(shost->host_lock);
 		return FAILED;
 	}
 
@@ -2014,6 +2016,7 @@
 
 	if (do_dma(shost->io_port, 0, RESET_PIO)) {
 		printk("%s: reset, cannot reset, timeout error.\n", ha->board_name);
+		spin_unlock_irq(shost->host_lock);
 		return FAILED;
 	}
 
@@ -2026,9 +2029,12 @@
 	ha->in_reset = 1;
 
 	spin_unlock_irq(shost->host_lock);
+
+	/* FIXME: use a sleep instead */
 	time = jiffies;
 	while ((jiffies - time) < (10 * HZ) && limit++ < 200000)
 		udelay(100L);
+
 	spin_lock_irq(shost->host_lock);
 
 	printk("%s: reset, interrupts disabled, loops %d.\n", ha->board_name, limit);
@@ -2078,6 +2084,7 @@
 	else
 		printk("%s: reset, exit.\n", ha->board_name);
 
+	spin_unlock_irq(shost->host_lock);
 	return SUCCESS;
 }
 
diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c
index 0ee49dc..04a06b7 100644
--- a/drivers/scsi/eata_pio.c
+++ b/drivers/scsi/eata_pio.c
@@ -486,8 +486,11 @@
 
 	DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset called pid:%ld target:" " %x lun: %x reason %x\n", cmd->pid, cmd->device->id, cmd->device->lun, cmd->abort_reason));
 
+	spin_lock_irq(host->host_lock);
+
 	if (HD(cmd)->state == RESET) {
 		printk(KERN_WARNING "eata_pio_reset: exit, already in reset.\n");
+		spin_unlock_irq(host->host_lock);
 		return FAILED;
 	}
 
@@ -536,6 +539,8 @@
 
 	HD(cmd)->state = 0;
 
+	spin_unlock_irq(host->host_lock);
+
 	if (success) {		/* hmmm... */
 		DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: exit, success.\n"));
 		return SUCCESS;
diff --git a/drivers/scsi/fcal.c b/drivers/scsi/fcal.c
index 0dad89d..a6f120d 100644
--- a/drivers/scsi/fcal.c
+++ b/drivers/scsi/fcal.c
@@ -311,7 +311,6 @@
 	.use_clustering		= ENABLE_CLUSTERING,
 	.eh_abort_handler	= fcp_scsi_abort,
 	.eh_device_reset_handler = fcp_scsi_dev_reset,
-	.eh_bus_reset_handler	= fcp_scsi_bus_reset,
 	.eh_host_reset_handler	= fcp_scsi_host_reset,
 };
 #include "scsi_module.c"
diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c
index 770930e..fa652f8a 100644
--- a/drivers/scsi/fd_mcs.c
+++ b/drivers/scsi/fd_mcs.c
@@ -1241,18 +1241,9 @@
 	return SUCCESS;
 }
 
-static int fd_mcs_host_reset(Scsi_Cmnd * SCpnt)
-{
-	return FAILED;
-}
-
-static int fd_mcs_device_reset(Scsi_Cmnd * SCpnt) 
-{
-	return FAILED;
-}
-
 static int fd_mcs_bus_reset(Scsi_Cmnd * SCpnt) {
 	struct Scsi_Host *shpnt = SCpnt->device->host;
+	unsigned long flags;
 
 #if DEBUG_RESET
 	static int called_once = 0;
@@ -1269,6 +1260,8 @@
 	called_once = 1;
 #endif
 
+	spin_lock_irqsave(shpnt->host_lock, flags);
+
 	outb(1, SCSI_Cntl_port);
 	do_pause(2);
 	outb(0, SCSI_Cntl_port);
@@ -1276,6 +1269,8 @@
 	outb(0, SCSI_Mode_Cntl_port);
 	outb(PARITY_MASK, TMC_Cntl_port);
 
+	spin_unlock_irqrestore(shpnt->host_lock, flags);
+
 	/* Unless this is the very first call (i.e., SCPnt == NULL), everything
 	   is probably hosed at this point.  We will, however, try to keep
 	   things going by informing the high-level code that we need help. */
@@ -1357,8 +1352,6 @@
 	.queuecommand   		= fd_mcs_queue, 
 	.eh_abort_handler		= fd_mcs_abort,
 	.eh_bus_reset_handler		= fd_mcs_bus_reset,
-	.eh_host_reset_handler		= fd_mcs_host_reset,
-	.eh_device_reset_handler	= fd_mcs_device_reset,
 	.bios_param     		= fd_mcs_biosparam,
 	.can_queue      		= 1,
 	.this_id        		= 7,
diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c
index a843c08..4ba6a15 100644
--- a/drivers/scsi/fdomain.c
+++ b/drivers/scsi/fdomain.c
@@ -1543,12 +1543,18 @@
 
 int fdomain_16x0_bus_reset(struct scsi_cmnd *SCpnt)
 {
+   unsigned long flags;
+
+   local_irq_save(flags);
+
    outb(1, port_base + SCSI_Cntl);
    do_pause( 2 );
    outb(0, port_base + SCSI_Cntl);
    do_pause( 115 );
    outb(0, port_base + SCSI_Mode_Cntl);
    outb(PARITY_MASK, port_base + TMC_Cntl);
+
+   local_irq_restore(flags);
    return SUCCESS;
 }
 
diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c
index ca9d5bd..a3aa729 100644
--- a/drivers/scsi/g_NCR5380.c
+++ b/drivers/scsi/g_NCR5380.c
@@ -908,8 +908,6 @@
 	.queuecommand   	= generic_NCR5380_queue_command,
 	.eh_abort_handler	= generic_NCR5380_abort,
 	.eh_bus_reset_handler	= generic_NCR5380_bus_reset,
-	.eh_device_reset_handler = generic_NCR5380_device_reset,
-	.eh_host_reset_handler	= generic_NCR5380_host_reset,
 	.bios_param     	= NCR5380_BIOSPARAM,
 	.can_queue      	= CAN_QUEUE,
         .this_id        	= 7,
diff --git a/drivers/scsi/g_NCR5380.h b/drivers/scsi/g_NCR5380.h
index 0c04cefb..c8adc5a 100644
--- a/drivers/scsi/g_NCR5380.h
+++ b/drivers/scsi/g_NCR5380.h
@@ -49,8 +49,6 @@
 static int generic_NCR5380_release_resources(struct Scsi_Host *);
 static int generic_NCR5380_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 static int generic_NCR5380_bus_reset(Scsi_Cmnd *);
-static int generic_NCR5380_host_reset(Scsi_Cmnd *);
-static int generic_NCR5380_device_reset(Scsi_Cmnd *);
 static const char* generic_NCR5380_info(struct Scsi_Host *);
 
 #ifndef CMD_PER_LUN
@@ -114,8 +112,6 @@
 #define NCR5380_queue_command generic_NCR5380_queue_command
 #define NCR5380_abort generic_NCR5380_abort
 #define NCR5380_bus_reset generic_NCR5380_bus_reset
-#define NCR5380_device_reset generic_NCR5380_device_reset
-#define NCR5380_host_reset generic_NCR5380_host_reset
 #define NCR5380_pread generic_NCR5380_pread
 #define NCR5380_pwrite generic_NCR5380_pwrite
 #define NCR5380_proc_info notyet_generic_proc_info
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
index a9eaab9..4552ccc 100644
--- a/drivers/scsi/gdth.c
+++ b/drivers/scsi/gdth.c
@@ -4703,19 +4703,6 @@
     return ((const char *)ha->binfo.type_string);
 }
 
-/* new error handling */
-static int gdth_eh_abort(Scsi_Cmnd *scp)
-{
-    TRACE2(("gdth_eh_abort()\n"));
-    return FAILED;
-}
-
-static int gdth_eh_device_reset(Scsi_Cmnd *scp)
-{
-    TRACE2(("gdth_eh_device_reset()\n"));
-    return FAILED;
-}
-
 static int gdth_eh_bus_reset(Scsi_Cmnd *scp)
 {
     int i, hanum;
@@ -4770,13 +4757,6 @@
     return SUCCESS;
 }
 
-static int gdth_eh_host_reset(Scsi_Cmnd *scp)
-{
-    TRACE2(("gdth_eh_host_reset()\n"));
-    return FAILED;
-}
-
-
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 static int gdth_bios_param(struct scsi_device *sdev,struct block_device *bdev,sector_t cap,int *ip)
 #else
@@ -5713,10 +5693,7 @@
         .release                = gdth_release,
         .info                   = gdth_info, 
         .queuecommand           = gdth_queuecommand,
-        .eh_abort_handler       = gdth_eh_abort, 
-        .eh_device_reset_handler = gdth_eh_device_reset,
         .eh_bus_reset_handler   = gdth_eh_bus_reset,
-        .eh_host_reset_handler  = gdth_eh_host_reset,
         .bios_param             = gdth_bios_param,
         .can_queue              = GDTH_MAXCMDS,
         .this_id                = -1,
diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c
index 30cbf73..d12342f 100644
--- a/drivers/scsi/gvp11.c
+++ b/drivers/scsi/gvp11.c
@@ -345,7 +345,15 @@
 static int gvp11_bus_reset(Scsi_Cmnd *cmd)
 {
 	/* FIXME perform bus-specific reset */
+
+	/* FIXME 2: shouldn't we no-op this function (return
+	   FAILED), and fall back to host reset function,
+	   wd33c93_host_reset ? */
+
+	spin_lock_irq(cmd->device->host->host_lock);
 	wd33c93_host_reset(cmd);
+	spin_unlock_irq(cmd->device->host->host_lock);
+
 	return SUCCESS;
 }
 
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index ba34757..d7a38b6 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -56,7 +56,7 @@
  * @shost:	pointer to struct Scsi_Host
  * recovery:	recovery requested to run.
  **/
-void scsi_host_cancel(struct Scsi_Host *shost, int recovery)
+static void scsi_host_cancel(struct Scsi_Host *shost, int recovery)
 {
 	struct scsi_device *sdev;
 
diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c
index a3fdead..b5dc353 100644
--- a/drivers/scsi/ibmmca.c
+++ b/drivers/scsi/ibmmca.c
@@ -2118,7 +2118,7 @@
 	return 0;
 }
 
-static int ibmmca_abort(Scsi_Cmnd * cmd)
+static int __ibmmca_abort(Scsi_Cmnd * cmd)
 {
 	/* Abort does not work, as the adapter never generates an interrupt on
 	 * whatever situation is simulated, even when really pending commands
@@ -2225,7 +2225,19 @@
 	}
 }
 
-static int ibmmca_host_reset(Scsi_Cmnd * cmd)
+static int ibmmca_abort(Scsi_Cmnd * cmd)
+{
+	struct Scsi_Host *shpnt = cmd->device->host;
+	int rc;
+
+	spin_lock_irq(shpnt->host_lock);
+	rc = __ibmmca_abort(cmd);
+	spin_unlock_irq(shpnt->host_lock);
+
+	return rc;
+}
+
+static int __ibmmca_host_reset(Scsi_Cmnd * cmd)
 {
 	struct Scsi_Host *shpnt;
 	Scsi_Cmnd *cmd_aid;
@@ -2312,6 +2324,18 @@
 	return SUCCESS;
 }
 
+static int ibmmca_host_reset(Scsi_Cmnd * cmd)
+{
+	struct Scsi_Host *shpnt = cmd->device->host;
+	int rc;
+
+	spin_lock_irq(shpnt->host_lock);
+	rc = __ibmmca_host_reset(cmd);
+	spin_unlock_irq(shpnt->host_lock);
+
+	return rc;
+}
+
 static int ibmmca_biosparam(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int *info)
 {
 	int size = capacity;
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index e89f76e..d89b8eb 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -874,9 +874,7 @@
 		return FAILED;
 	}
 
-	spin_unlock_irq(hostdata->host->host_lock);
 	wait_for_completion(&evt->comp);
-	spin_lock_irq(hostdata->host->host_lock);
 
 	/* make sure we got a good response */
 	if (unlikely(srp_rsp.srp.generic.type != SRP_RSP_TYPE)) {
@@ -978,9 +976,7 @@
 		return FAILED;
 	}
 
-	spin_unlock_irq(hostdata->host->host_lock);
 	wait_for_completion(&evt->comp);
-	spin_lock_irq(hostdata->host->host_lock);
 
 	/* make sure we got a good response */
 	if (unlikely(srp_rsp.srp.generic.type != SRP_RSP_TYPE)) {
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index 83f062e..3d62c9b 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -46,6 +46,7 @@
 #include <linux/slab.h>
 #include <linux/ide.h>
 #include <linux/scatterlist.h>
+#include <linux/delay.h>
 
 #include <asm/io.h>
 #include <asm/bitops.h>
@@ -1026,11 +1027,13 @@
 		return FAILED;
 	}
 
-	spin_lock_irq(&ide_lock);
+	spin_lock_irq(cmd->device->host->host_lock);
+	spin_lock(&ide_lock);
 
 	if (!scsi->pc || (req = scsi->pc->rq) != HWGROUP(drive)->rq || !HWGROUP(drive)->handler) {
 		printk (KERN_WARNING "ide-scsi: No active request in idescsi_eh_reset\n");
 		spin_unlock(&ide_lock);
+		spin_unlock_irq(cmd->device->host->host_lock);
 		return FAILED;
 	}
 
@@ -1052,16 +1055,15 @@
 	HWGROUP(drive)->rq = NULL;
 	HWGROUP(drive)->handler = NULL;
 	HWGROUP(drive)->busy = 1;		/* will set this to zero when ide reset finished */
-	spin_unlock_irq(&ide_lock);
+	spin_unlock(&ide_lock);
 
 	ide_do_reset(drive);
 
 	/* ide_do_reset starts a polling handler which restarts itself every 50ms until the reset finishes */
 
 	do {
-		set_current_state(TASK_UNINTERRUPTIBLE);
 		spin_unlock_irq(cmd->device->host->host_lock);
-		schedule_timeout(HZ/20);
+		msleep(50);
 		spin_lock_irq(cmd->device->host->host_lock);
 	} while ( HWGROUP(drive)->handler );
 
@@ -1072,6 +1074,7 @@
 		ret = FAILED;
 	}
 
+	spin_unlock_irq(cmd->device->host->host_lock);
 	return ret;
 }
 
diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c
index be7f2ca..65e8456 100644
--- a/drivers/scsi/imm.c
+++ b/drivers/scsi/imm.c
@@ -18,6 +18,7 @@
 #include <linux/blkdev.h>
 #include <linux/parport.h>
 #include <linux/workqueue.h>
+#include <linux/delay.h>
 #include <asm/io.h>
 
 #include <scsi/scsi.h>
@@ -610,9 +611,9 @@
 	if (imm_connect(dev, 0) != 1)
 		return -EIO;
 	imm_reset_pulse(dev->base);
-	udelay(1000);	/* Delay to allow devices to settle */
+	mdelay(1);	/* Delay to allow devices to settle */
 	imm_disconnect(dev);
-	udelay(1000);	/* Another delay to allow devices to settle */
+	mdelay(1);	/* Another delay to allow devices to settle */
 	return device_check(dev);
 }
 
@@ -1026,9 +1027,9 @@
 
 	imm_connect(dev, CONNECT_NORMAL);
 	imm_reset_pulse(dev->base);
-	udelay(1000);		/* device settle delay */
+	mdelay(1);		/* device settle delay */
 	imm_disconnect(dev);
-	udelay(1000);		/* device settle delay */
+	mdelay(1);		/* device settle delay */
 	return SUCCESS;
 }
 
diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c
index 0bb0369..aed7e64 100644
--- a/drivers/scsi/in2000.c
+++ b/drivers/scsi/in2000.c
@@ -1644,14 +1644,16 @@
 	struct Scsi_Host *instance;
 	struct IN2000_hostdata *hostdata;
 	int x;
+	unsigned long flags;
 
 	instance = cmd->device->host;
 	hostdata = (struct IN2000_hostdata *) instance->hostdata;
 
 	printk(KERN_WARNING "scsi%d: Reset. ", instance->host_no);
 
-	/* do scsi-reset here */
+	spin_lock_irqsave(instance->host_lock, flags);
 
+	/* do scsi-reset here */
 	reset_hardware(instance, RESET_CARD_AND_BUS);
 	for (x = 0; x < 8; x++) {
 		hostdata->busy[x] = 0;
@@ -1668,21 +1670,12 @@
 	hostdata->outgoing_len = 0;
 
 	cmd->result = DID_RESET << 16;
+
+	spin_unlock_irqrestore(instance->host_lock, flags);
 	return SUCCESS;
 }
 
-static int in2000_host_reset(Scsi_Cmnd * cmd)
-{
-	return FAILED;
-}
-
-static int in2000_device_reset(Scsi_Cmnd * cmd)
-{
-	return FAILED;
-}
-
-
-static int in2000_abort(Scsi_Cmnd * cmd)
+static int __in2000_abort(Scsi_Cmnd * cmd)
 {
 	struct Scsi_Host *instance;
 	struct IN2000_hostdata *hostdata;
@@ -1803,6 +1796,16 @@
 	return SUCCESS;
 }
 
+static int in2000_abort(Scsi_Cmnd * cmd)
+{
+	int rc;
+
+	spin_lock_irq(cmd->device->host->host_lock);
+	rc = __in2000_abort(cmd);
+	spin_unlock_irq(cmd->device->host->host_lock);
+
+	return rc;
+}
 
 
 #define MAX_IN2000_HOSTS 3
@@ -2311,8 +2314,6 @@
 	.queuecommand    		= in2000_queuecommand,
 	.eh_abort_handler		= in2000_abort,
 	.eh_bus_reset_handler		= in2000_bus_reset,
-	.eh_device_reset_handler	= in2000_device_reset,
-	.eh_host_reset_handler	= in2000_host_reset, 
 	.bios_param      		= in2000_biosparam, 
 	.can_queue       		= IN2000_CAN_Q,
 	.this_id         		= IN2000_HOST_ID,
diff --git a/drivers/scsi/in2000.h b/drivers/scsi/in2000.h
index 019e45d..a240b52 100644
--- a/drivers/scsi/in2000.h
+++ b/drivers/scsi/in2000.h
@@ -401,9 +401,7 @@
 static void in2000_setup(char *, int *) in2000__INIT;
 static int in2000_biosparam(struct scsi_device *, struct block_device *,
 		sector_t, int *);
-static int in2000_host_reset(Scsi_Cmnd *);
 static int in2000_bus_reset(Scsi_Cmnd *);
-static int in2000_device_reset(Scsi_Cmnd *);
 
 
 #define IN2000_CAN_Q    16
diff --git a/drivers/scsi/initio.c b/drivers/scsi/initio.c
index a7b74d8..2094d48 100644
--- a/drivers/scsi/initio.c
+++ b/drivers/scsi/initio.c
@@ -223,7 +223,7 @@
 static void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb);
 static void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb);
 static int int_tul_busfree(HCS * pCurHcb);
-int int_tul_scsi_rst(HCS * pCurHcb);
+static int int_tul_scsi_rst(HCS * pCurHcb);
 static int int_tul_bad_seq(HCS * pCurHcb);
 static int int_tul_resel(HCS * pCurHcb);
 static int tul_sync_done(HCS * pCurHcb);
@@ -240,9 +240,8 @@
 static void tul_se2_update_all(WORD CurBase);	/* setup default pattern */
 static void tul_read_eeprom(WORD CurBase);
 
-				/* ---- EXTERNAL VARIABLES ---- */
-HCS tul_hcs[MAX_SUPPORTED_ADAPTERS];
 				/* ---- INTERNAL VARIABLES ---- */
+static HCS tul_hcs[MAX_SUPPORTED_ADAPTERS];
 static INI_ADPT_STRUCT i91u_adpt[MAX_SUPPORTED_ADAPTERS];
 
 /*NVRAM nvram, *nvramp = &nvram; */
@@ -381,7 +380,7 @@
 
 
 ******************************************************************/
-void tul_se2_instr(WORD CurBase, UCHAR instr)
+static void tul_se2_instr(WORD CurBase, UCHAR instr)
 {
 	int i;
 	UCHAR b;
@@ -437,7 +436,7 @@
 	Input  :address of Serial E2PROM
 	Output :value stored in  Serial E2PROM
 *******************************************************************/
-USHORT tul_se2_rd(WORD CurBase, ULONG adr)
+static USHORT tul_se2_rd(WORD CurBase, ULONG adr)
 {
 	UCHAR instr, readByte;
 	USHORT readWord;
@@ -468,7 +467,7 @@
 /******************************************************************
  Input: new value in  Serial E2PROM, address of Serial E2PROM
 *******************************************************************/
-void tul_se2_wr(WORD CurBase, UCHAR adr, USHORT writeWord)
+static void tul_se2_wr(WORD CurBase, UCHAR adr, USHORT writeWord)
 {
 	UCHAR readByte;
 	UCHAR instr;
@@ -584,8 +583,8 @@
 	TUL_WR(CurBase + TUL_GCTRL, gctrl & ~TUL_GCTRL_EEPROM_BIT);
 }				/* read_eeprom */
 
-int Addi91u_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt,
-			       BYTE bBus, BYTE bDevice)
+static int Addi91u_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt,
+				      BYTE bBus, BYTE bDevice)
 {
 	int i, j;
 
@@ -616,7 +615,7 @@
 	return 1;
 }
 
-void init_i91uAdapter_table(void)
+static void init_i91uAdapter_table(void)
 {
 	int i;
 
@@ -630,7 +629,7 @@
 	return;
 }
 
-void tul_stop_bm(HCS * pCurHcb)
+static void tul_stop_bm(HCS * pCurHcb)
 {
 
 	if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) {	/* if DMA xfer is pending, abort DMA xfer */
@@ -642,7 +641,7 @@
 }
 
 /***************************************************************************/
-void get_tulipPCIConfig(HCS * pCurHcb, int ch_idx)
+static void get_tulipPCIConfig(HCS * pCurHcb, int ch_idx)
 {
 	pCurHcb->HCS_Base = i91u_adpt[ch_idx].ADPT_BASE;	/* Supply base address  */
 	pCurHcb->HCS_BIOS = i91u_adpt[ch_idx].ADPT_BIOS;	/* Supply BIOS address  */
@@ -651,7 +650,7 @@
 }
 
 /***************************************************************************/
-int tul_reset_scsi(HCS * pCurHcb, int seconds)
+static int tul_reset_scsi(HCS * pCurHcb, int seconds)
 {
 	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_BUS);
 
@@ -670,7 +669,8 @@
 }
 
 /***************************************************************************/
-int init_tulip(HCS * pCurHcb, SCB * scbp, int tul_num_scb, BYTE * pbBiosAdr, int seconds)
+static int init_tulip(HCS * pCurHcb, SCB * scbp, int tul_num_scb,
+		      BYTE * pbBiosAdr, int seconds)
 {
 	int i;
 	BYTE *pwFlags;
@@ -788,7 +788,7 @@
 }
 
 /***************************************************************************/
-SCB *tul_alloc_scb(HCS * hcsp)
+static SCB *tul_alloc_scb(HCS * hcsp)
 {
 	SCB *pTmpScb;
 	ULONG flags;
@@ -807,7 +807,7 @@
 }
 
 /***************************************************************************/
-void tul_release_scb(HCS * hcsp, SCB * scbp)
+static void tul_release_scb(HCS * hcsp, SCB * scbp)
 {
 	ULONG flags;
 
@@ -829,7 +829,7 @@
 }
 
 /***************************************************************************/
-void tul_append_pend_scb(HCS * pCurHcb, SCB * scbp)
+static void tul_append_pend_scb(HCS * pCurHcb, SCB * scbp)
 {
 
 #if DEBUG_QUEUE
@@ -847,7 +847,7 @@
 }
 
 /***************************************************************************/
-void tul_push_pend_scb(HCS * pCurHcb, SCB * scbp)
+static void tul_push_pend_scb(HCS * pCurHcb, SCB * scbp)
 {
 
 #if DEBUG_QUEUE
@@ -863,7 +863,7 @@
 }
 
 /***************************************************************************/
-SCB *tul_find_first_pend_scb(HCS * pCurHcb)
+static SCB *tul_find_first_pend_scb(HCS * pCurHcb)
 {
 	SCB *pFirstPend;
 
@@ -894,24 +894,7 @@
 	return (pFirstPend);
 }
 /***************************************************************************/
-SCB *tul_pop_pend_scb(HCS * pCurHcb)
-{
-	SCB *pTmpScb;
-
-	if ((pTmpScb = pCurHcb->HCS_FirstPend) != NULL) {
-		if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL)
-			pCurHcb->HCS_LastPend = NULL;
-		pTmpScb->SCB_NxtScb = NULL;
-	}
-#if DEBUG_QUEUE
-	printk("Pop pend SCB %lx; ", (ULONG) pTmpScb);
-#endif
-	return (pTmpScb);
-}
-
-
-/***************************************************************************/
-void tul_unlink_pend_scb(HCS * pCurHcb, SCB * pCurScb)
+static void tul_unlink_pend_scb(HCS * pCurHcb, SCB * pCurScb)
 {
 	SCB *pTmpScb, *pPrevScb;
 
@@ -939,7 +922,7 @@
 	return;
 }
 /***************************************************************************/
-void tul_append_busy_scb(HCS * pCurHcb, SCB * scbp)
+static void tul_append_busy_scb(HCS * pCurHcb, SCB * scbp)
 {
 
 #if DEBUG_QUEUE
@@ -961,7 +944,7 @@
 }
 
 /***************************************************************************/
-SCB *tul_pop_busy_scb(HCS * pCurHcb)
+static SCB *tul_pop_busy_scb(HCS * pCurHcb)
 {
 	SCB *pTmpScb;
 
@@ -982,7 +965,7 @@
 }
 
 /***************************************************************************/
-void tul_unlink_busy_scb(HCS * pCurHcb, SCB * pCurScb)
+static void tul_unlink_busy_scb(HCS * pCurHcb, SCB * pCurScb)
 {
 	SCB *pTmpScb, *pPrevScb;
 
@@ -1037,7 +1020,7 @@
 }
 
 /***************************************************************************/
-void tul_append_done_scb(HCS * pCurHcb, SCB * scbp)
+static void tul_append_done_scb(HCS * pCurHcb, SCB * scbp)
 {
 
 #if DEBUG_QUEUE
@@ -1073,7 +1056,7 @@
 }
 
 /***************************************************************************/
-int tul_abort_srb(HCS * pCurHcb, struct scsi_cmnd *srbp)
+static int tul_abort_srb(HCS * pCurHcb, struct scsi_cmnd *srbp)
 {
 	ULONG flags;
 	SCB *pTmpScb, *pPrevScb;
@@ -1163,7 +1146,7 @@
 }
 
 /***************************************************************************/
-int tul_bad_seq(HCS * pCurHcb)
+static int tul_bad_seq(HCS * pCurHcb)
 {
 	SCB *pCurScb;
 
@@ -1182,9 +1165,11 @@
 	return (tul_post_scsi_rst(pCurHcb));
 }
 
+#if 0
+
 /************************************************************************/
-int tul_device_reset(HCS * pCurHcb, struct scsi_cmnd *pSrb,
-		unsigned int target, unsigned int ResetFlags)
+static int tul_device_reset(HCS * pCurHcb, struct scsi_cmnd *pSrb,
+			    unsigned int target, unsigned int ResetFlags)
 {
 	ULONG flags;
 	SCB *pScb;
@@ -1255,7 +1240,7 @@
 	return SCSI_RESET_PENDING;
 }
 
-int tul_reset_scsi_bus(HCS * pCurHcb)
+static int tul_reset_scsi_bus(HCS * pCurHcb)
 {
 	ULONG flags;
 
@@ -1284,8 +1269,10 @@
 	return (SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET);
 }
 
+#endif  /*  0  */
+
 /************************************************************************/
-void tul_exec_scb(HCS * pCurHcb, SCB * pCurScb)
+static void tul_exec_scb(HCS * pCurHcb, SCB * pCurScb)
 {
 	ULONG flags;
 
@@ -1318,7 +1305,7 @@
 }
 
 /***************************************************************************/
-int tul_isr(HCS * pCurHcb)
+static int tul_isr(HCS * pCurHcb)
 {
 	/* Enter critical section       */
 
@@ -2108,7 +2095,7 @@
 
 /***************************************************************************/
 /* scsi bus reset */
-int int_tul_scsi_rst(HCS * pCurHcb)
+static int int_tul_scsi_rst(HCS * pCurHcb)
 {
 	SCB *pCurScb;
 	int i;
@@ -2214,7 +2201,7 @@
 
 
 /***************************************************************************/
-int int_tul_bad_seq(HCS * pCurHcb)
+static int int_tul_bad_seq(HCS * pCurHcb)
 {				/* target wrong phase           */
 	SCB *pCurScb;
 	int i;
@@ -3014,7 +3001,11 @@
 	HCS *pHCB;
 
 	pHCB = (HCS *) SCpnt->device->host->base;
+
+	spin_lock_irq(SCpnt->device->host->host_lock);
 	tul_reset_scsi(pHCB, 0);
+	spin_unlock_irq(SCpnt->device->host->host_lock);
+
 	return SUCCESS;
 }
 
diff --git a/drivers/scsi/initio.h b/drivers/scsi/initio.h
index df3ed7c..3efb118 100644
--- a/drivers/scsi/initio.h
+++ b/drivers/scsi/initio.h
@@ -719,21 +719,3 @@
 #define SCSI_RESET_HOST_RESET 0x200
 #define SCSI_RESET_ACTION   0xff
 
-extern void init_i91uAdapter_table(void);
-extern int Addi91u_into_Adapter_table(WORD, WORD, BYTE, BYTE, BYTE);
-extern int tul_ReturnNumberOfAdapters(void);
-extern void get_tulipPCIConfig(HCS * pHCB, int iChannel_index);
-extern int init_tulip(HCS * pHCB, SCB * pSCB, int tul_num_scb, BYTE * pbBiosAdr, int reset_time);
-extern SCB *tul_alloc_scb(HCS * pHCB);
-extern int tul_abort_srb(HCS * pHCB, struct scsi_cmnd * pSRB);
-extern void tul_exec_scb(HCS * pHCB, SCB * pSCB);
-extern void tul_release_scb(HCS * pHCB, SCB * pSCB);
-extern void tul_stop_bm(HCS * pHCB);
-extern int tul_reset_scsi(HCS * pCurHcb, int seconds);
-extern int tul_isr(HCS * pHCB);
-extern int tul_reset(HCS * pHCB, struct scsi_cmnd * pSRB, unsigned char target);
-extern int tul_reset_scsi_bus(HCS * pCurHcb);
-extern int tul_device_reset(HCS * pCurHcb, struct scsi_cmnd *pSrb,
-		unsigned int target, unsigned int ResetFlags);
-				/* ---- EXTERNAL VARIABLES ---- */
-extern HCS tul_hcs[];
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 5441531..80d0226 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -1053,7 +1053,7 @@
 				array_entry->dev_res_addr.lun);
 		}
 
-		if (array_entry->dev_res_addr.bus >= IPR_MAX_NUM_BUSES) {
+		if (array_entry->expected_dev_res_addr.bus >= IPR_MAX_NUM_BUSES) {
 			ipr_err("Expected Location: unknown\n");
 		} else {
 			ipr_err("Expected Location: %d:%d:%d:%d\n",
@@ -2716,7 +2716,7 @@
  * Return value:
  * 	number of bytes printed to buffer
  **/
-static ssize_t ipr_show_adapter_handle(struct device *dev, char *buf)
+static ssize_t ipr_show_adapter_handle(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct scsi_device *sdev = to_scsi_device(dev);
 	struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata;
@@ -2885,7 +2885,7 @@
  * Return value:
  * 	SUCCESS / FAILED
  **/
-static int ipr_eh_host_reset(struct scsi_cmnd * scsi_cmd)
+static int __ipr_eh_host_reset(struct scsi_cmnd * scsi_cmd)
 {
 	struct ipr_ioa_cfg *ioa_cfg;
 	int rc;
@@ -2905,6 +2905,17 @@
 	return rc;
 }
 
+static int ipr_eh_host_reset(struct scsi_cmnd * cmd)
+{
+	int rc;
+
+	spin_lock_irq(cmd->device->host->host_lock);
+	rc = __ipr_eh_host_reset(cmd);
+	spin_unlock_irq(cmd->device->host->host_lock);
+
+	return rc;
+}
+
 /**
  * ipr_eh_dev_reset - Reset the device
  * @scsi_cmd:	scsi command struct
@@ -2916,7 +2927,7 @@
  * Return value:
  *	SUCCESS / FAILED
  **/
-static int ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd)
+static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd)
 {
 	struct ipr_cmnd *ipr_cmd;
 	struct ipr_ioa_cfg *ioa_cfg;
@@ -2970,6 +2981,17 @@
 	return (IPR_IOASC_SENSE_KEY(ioasc) ? FAILED : SUCCESS);
 }
 
+static int ipr_eh_dev_reset(struct scsi_cmnd * cmd)
+{
+	int rc;
+
+	spin_lock_irq(cmd->device->host->host_lock);
+	rc = __ipr_eh_dev_reset(cmd);
+	spin_unlock_irq(cmd->device->host->host_lock);
+
+	return rc;
+}
+
 /**
  * ipr_bus_reset_done - Op done function for bus reset.
  * @ipr_cmd:	ipr command struct
@@ -3068,6 +3090,12 @@
 	ioa_cfg = (struct ipr_ioa_cfg *)scsi_cmd->device->host->hostdata;
 	res = scsi_cmd->device->hostdata;
 
+	/* If we are currently going through reset/reload, return failed.
+	 * This will force the mid-layer to call ipr_eh_host_reset,
+	 * which will then go to sleep and wait for the reset to complete
+	 */
+	if (ioa_cfg->in_reset_reload || ioa_cfg->ioa_is_dead)
+		return FAILED;
 	if (!res || (!ipr_is_gscsi(res) && !ipr_is_vset_device(res)))
 		return FAILED;
 
@@ -3118,23 +3146,17 @@
  **/
 static int ipr_eh_abort(struct scsi_cmnd * scsi_cmd)
 {
-	struct ipr_ioa_cfg *ioa_cfg;
+	unsigned long flags;
+	int rc;
 
 	ENTER;
-	ioa_cfg = (struct ipr_ioa_cfg *) scsi_cmd->device->host->hostdata;
 
-	/* If we are currently going through reset/reload, return failed. This will force the
-	   mid-layer to call ipr_eh_host_reset, which will then go to sleep and wait for the
-	   reset to complete */
-	if (ioa_cfg->in_reset_reload)
-		return FAILED;
-	if (ioa_cfg->ioa_is_dead)
-		return FAILED;
-	if (!scsi_cmd->device->hostdata)
-		return FAILED;
+	spin_lock_irqsave(scsi_cmd->device->host->host_lock, flags);
+	rc = ipr_cancel_op(scsi_cmd);
+	spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, flags);
 
 	LEAVE;
-	return ipr_cancel_op(scsi_cmd);
+	return rc;
 }
 
 /**
@@ -5886,6 +5908,7 @@
 
 	spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags);
 	wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
+	flush_scheduled_work();
 	spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags);
 
 	spin_lock(&ipr_driver_lock);
@@ -5916,8 +5939,6 @@
 
 	ENTER;
 
-	ioa_cfg->allow_cmds = 0;
-	flush_scheduled_work();
 	ipr_remove_trace_file(&ioa_cfg->host->shost_classdev.kobj,
 			      &ipr_trace_attr);
 	ipr_remove_dump_file(&ioa_cfg->host->shost_classdev.kobj,
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 446f425..cbff3ea 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -36,8 +36,8 @@
 /*
  * Literals
  */
-#define IPR_DRIVER_VERSION "2.0.13"
-#define IPR_DRIVER_DATE "(February 21, 2005)"
+#define IPR_DRIVER_VERSION "2.0.14"
+#define IPR_DRIVER_DATE "(May 2, 2005)"
 
 /*
  * IPR_DBG_TRACE: Setting this to 1 will turn on some general function tracing
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index fbc2cb6..6dfcb4f 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -819,12 +819,15 @@
 	ips_ha_t *ha;
 	ips_copp_wait_item_t *item;
 	int ret;
+	unsigned long cpu_flags;
+	struct Scsi_Host *host;
 
 	METHOD_TRACE("ips_eh_abort", 1);
 
 	if (!SC)
 		return (FAILED);
 
+	host = SC->device->host;
 	ha = (ips_ha_t *) SC->device->host->hostdata;
 
 	if (!ha)
@@ -833,6 +836,8 @@
 	if (!ha->active)
 		return (FAILED);
 
+	IPS_LOCK_SAVE(host->host_lock, cpu_flags);
+
 	/* See if the command is on the copp queue */
 	item = ha->copp_waitlist.head;
 	while ((item) && (item->scsi_cmd != SC))
@@ -851,6 +856,8 @@
 		/* command must have already been sent */
 		ret = (FAILED);
 	}
+
+	IPS_UNLOCK_RESTORE(host->host_lock, cpu_flags);
 	return ret;
 }
 
@@ -866,7 +873,7 @@
 /*                                                                          */
 /****************************************************************************/
 static int
-ips_eh_reset(Scsi_Cmnd * SC)
+__ips_eh_reset(Scsi_Cmnd * SC)
 {
 	int ret;
 	int i;
@@ -1053,6 +1060,18 @@
 
 }
 
+static int
+ips_eh_reset(Scsi_Cmnd * SC)
+{
+	int rc;
+
+	spin_lock_irq(SC->device->host->host_lock);
+	rc = __ips_eh_reset(SC);
+	spin_unlock_irq(SC->device->host->host_lock);
+
+	return rc;
+}
+
 /****************************************************************************/
 /*                                                                          */
 /* Routine Name: ips_queue                                                  */
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 21d194c..36b401f 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1295,6 +1295,37 @@
 	DPRINTK("EXIT, err\n");
 }
 
+
+static inline u8 ata_dev_knobble(struct ata_port *ap)
+{
+	return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(ap->device->id)));
+}
+
+/**
+ * 	ata_dev_config - Run device specific handlers and check for
+ * 			 SATA->PATA bridges
+ * 	@ap: Bus 
+ * 	@i:  Device
+ *
+ * 	LOCKING:
+ */
+ 
+void ata_dev_config(struct ata_port *ap, unsigned int i)
+{
+	/* limit bridge transfers to udma5, 200 sectors */
+	if (ata_dev_knobble(ap)) {
+		printk(KERN_INFO "ata%u(%u): applying bridge limits\n",
+			ap->id, ap->device->devno);
+		ap->udma_mask &= ATA_UDMA5;
+		ap->host->max_sectors = ATA_MAX_SECTORS;
+		ap->host->hostt->max_sectors = ATA_MAX_SECTORS;
+		ap->device->flags |= ATA_DFLAG_LOCK_SECTORS;
+	}
+
+	if (ap->ops->dev_config)
+		ap->ops->dev_config(ap, &ap->device[i]);
+}
+
 /**
  *	ata_bus_probe - Reset and probe ATA bus
  *	@ap: Bus to probe
@@ -1322,8 +1353,7 @@
 		ata_dev_identify(ap, i);
 		if (ata_dev_present(&ap->device[i])) {
 			found = 1;
-			if (ap->ops->dev_config)
-				ap->ops->dev_config(ap, &ap->device[i]);
+			ata_dev_config(ap,i);
 		}
 	}
 
@@ -2577,7 +2607,6 @@
 next_sg:
 	sg = &qc->sg[qc->cursg];
 
-next_page:
 	page = sg->page;
 	offset = sg->offset + qc->cursg_ofs;
 
@@ -2585,6 +2614,7 @@
 	page = nth_page(page, (offset >> PAGE_SHIFT));
 	offset %= PAGE_SIZE;
 
+	/* don't overrun current sg */
 	count = min(sg->length - qc->cursg_ofs, bytes);
 
 	/* don't cross page boundaries */
@@ -2609,8 +2639,6 @@
 	kunmap(page);
 
 	if (bytes) {
-		if (qc->cursg_ofs < sg->length)
-			goto next_page;
 		goto next_sg;
 	}
 }
@@ -4408,6 +4436,7 @@
 EXPORT_SYMBOL_GPL(ata_host_intr);
 EXPORT_SYMBOL_GPL(ata_dev_classify);
 EXPORT_SYMBOL_GPL(ata_dev_id_string);
+EXPORT_SYMBOL_GPL(ata_dev_config);
 EXPORT_SYMBOL_GPL(ata_scsi_simulate);
 
 #ifdef CONFIG_PCI
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 42fab03..f2aff3f 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -798,7 +798,7 @@
 }
 
 static int
-lpfc_abort_handler(struct scsi_cmnd *cmnd)
+__lpfc_abort_handler(struct scsi_cmnd *cmnd)
 {
 	struct lpfc_hba *phba =
 			(struct lpfc_hba *)cmnd->device->host->hostdata[0];
@@ -918,7 +918,17 @@
 }
 
 static int
-lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
+lpfc_abort_handler(struct scsi_cmnd *cmnd)
+{
+	int rc;
+	spin_lock_irq(cmnd->device->host->host_lock);
+	rc = __lpfc_abort_handler(cmnd);
+	spin_unlock_irq(cmnd->device->host->host_lock);
+	return rc;
+}
+
+static int
+__lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
 {
 	struct Scsi_Host *shost = cmnd->device->host;
 	struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0];
@@ -1030,11 +1040,21 @@
 	return ret;
 }
 
+static int
+lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
+{
+	int rc;
+	spin_lock_irq(cmnd->device->host->host_lock);
+	rc = __lpfc_reset_lun_handler(cmnd);
+	spin_unlock_irq(cmnd->device->host->host_lock);
+	return rc;
+}
+
 /*
  * Note: midlayer calls this function with the host_lock held
  */
 static int
-lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
+__lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
 {
 	struct Scsi_Host *shost = cmnd->device->host;
 	struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata[0];
@@ -1124,6 +1144,16 @@
 }
 
 static int
+lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
+{
+	int rc;
+	spin_lock_irq(cmnd->device->host->host_lock);
+	rc = __lpfc_reset_bus_handler(cmnd);
+	spin_unlock_irq(cmnd->device->host->host_lock);
+	return rc;
+}
+
+static int
 lpfc_slave_alloc(struct scsi_device *sdev)
 {
 	struct lpfc_hba *phba = (struct lpfc_hba *)sdev->host->hostdata[0];
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c
index 3ef2a14..edd47d1 100644
--- a/drivers/scsi/mac53c94.c
+++ b/drivers/scsi/mac53c94.c
@@ -98,16 +98,14 @@
 	return 0;
 }
 
-static int mac53c94_abort(struct scsi_cmnd *cmd)
-{
-	return FAILED;
-}
-
 static int mac53c94_host_reset(struct scsi_cmnd *cmd)
 {
 	struct fsc_state *state = (struct fsc_state *) cmd->device->host->hostdata;
 	struct mac53c94_regs __iomem *regs = state->regs;
 	struct dbdma_regs __iomem *dma = state->dma;
+	unsigned long flags;
+
+	spin_lock_irqsave(cmd->device->host->host_lock, flags);
 
 	writel((RUN|PAUSE|FLUSH|WAKE) << 16, &dma->control);
 	writeb(CMD_SCSI_RESET, &regs->command);	/* assert RST */
@@ -116,6 +114,8 @@
 	udelay(20);
 	mac53c94_init(state);
 	writeb(CMD_NOP, &regs->command);
+
+	spin_unlock_irqrestore(cmd->device->host->host_lock, flags);
 	return SUCCESS;
 }
 
@@ -416,7 +416,6 @@
 	.proc_name	= "53c94",
 	.name		= "53C94",
 	.queuecommand	= mac53c94_queue,
-	.eh_abort_handler = mac53c94_abort,
 	.eh_host_reset_handler = mac53c94_host_reset,
 	.can_queue	= 1,
 	.this_id	= 7,
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c
index d5fd17e..92d2c83 100644
--- a/drivers/scsi/mac_scsi.c
+++ b/drivers/scsi/mac_scsi.c
@@ -591,8 +591,6 @@
 	.queuecommand			= macscsi_queue_command,
 	.eh_abort_handler		= macscsi_abort,
 	.eh_bus_reset_handler		= macscsi_bus_reset,
-	.eh_device_reset_handler	= macscsi_device_reset,
-	.eh_host_reset_handler		= macscsi_host_reset,
 	.can_queue			= CAN_QUEUE,
 	.this_id			= 7,
 	.sg_tablesize			= SG_ALL,
diff --git a/drivers/scsi/mac_scsi.h b/drivers/scsi/mac_scsi.h
index 23ab2c1..d26e331 100644
--- a/drivers/scsi/mac_scsi.h
+++ b/drivers/scsi/mac_scsi.h
@@ -72,8 +72,6 @@
 #define NCR5380_queue_command macscsi_queue_command
 #define NCR5380_abort macscsi_abort
 #define NCR5380_bus_reset macscsi_bus_reset
-#define NCR5380_device_reset macscsi_device_reset
-#define NCR5380_host_reset macscsi_host_reset
 #define NCR5380_proc_info macscsi_proc_info
 
 #define BOARD_NORMAL	0
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 8d707b2..ec81532 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -1938,7 +1938,7 @@
 
 
 static int
-megaraid_reset(Scsi_Cmnd *cmd)
+__megaraid_reset(Scsi_Cmnd *cmd)
 {
 	adapter_t	*adapter;
 	megacmd_t	mc;
@@ -1972,6 +1972,18 @@
 	return rval;
 }
 
+static int
+megaraid_reset(Scsi_Cmnd *cmd)
+{
+	adapter_t *adapter = (adapter_t *)cmd->device->host->hostdata;
+	int rc;
+
+	spin_lock_irq(&adapter->lock);
+	rc = __megaraid_reset(cmd);
+	spin_unlock_irq(&adapter->lock);
+
+	return rc;
+}
 
 
 /**
diff --git a/drivers/scsi/megaraid/mega_common.h b/drivers/scsi/megaraid/mega_common.h
index 18969a4..69df1a9 100644
--- a/drivers/scsi/megaraid/mega_common.h
+++ b/drivers/scsi/megaraid/mega_common.h
@@ -27,6 +27,7 @@
 #include <linux/list.h>
 #include <linux/version.h>
 #include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
 #include <asm/semaphore.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
index 138fa48..cbe4302 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.c
+++ b/drivers/scsi/megaraid/megaraid_mbox.c
@@ -10,7 +10,7 @@
  *	   2 of the License, or (at your option) any later version.
  *
  * FILE		: megaraid_mbox.c
- * Version	: v2.20.4.5 (Feb 03 2005)
+ * Version	: v2.20.4.6 (Mar 07 2005)
  *
  * Authors:
  * 	Atul Mukker		<Atul.Mukker@lsil.com>
@@ -124,7 +124,7 @@
 static void megaraid_mbox_dpc(unsigned long);
 
 static ssize_t megaraid_sysfs_show_app_hndl(struct class_device *, char *);
-static ssize_t megaraid_sysfs_show_ldnum(struct device *, char *);
+static ssize_t megaraid_sysfs_show_ldnum(struct device *, struct device_attribute *attr, char *);
 
 static int megaraid_cmm_register(adapter_t *);
 static int megaraid_cmm_unregister(adapter_t *);
@@ -202,7 +202,7 @@
  * ### global data ###
  */
 static uint8_t megaraid_mbox_version[8] =
-	{ 0x02, 0x20, 0x04, 0x05, 2, 3, 20, 5 };
+	{ 0x02, 0x20, 0x04, 0x06, 3, 7, 20, 5 };
 
 
 /*
@@ -229,9 +229,9 @@
 	},
 	{
 		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_PERC4_QC,
-		PCI_VENDOR_ID_DELL,
-		PCI_SUBSYS_ID_PERC4_QC,
+		PCI_DEVICE_ID_VERDE,
+		PCI_ANY_ID,
+		PCI_ANY_ID,
 	},
 	{
 		PCI_VENDOR_ID_DELL,
@@ -271,15 +271,9 @@
 	},
 	{
 		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_PERC4E_DC_320_2E,
-		PCI_VENDOR_ID_DELL,
-		PCI_SUBSYS_ID_PERC4E_DC_320_2E,
-	},
-	{
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_PERC4E_SC_320_1E,
-		PCI_VENDOR_ID_DELL,
-		PCI_SUBSYS_ID_PERC4E_SC_320_1E,
+		PCI_DEVICE_ID_DOBSON,
+		PCI_ANY_ID,
+		PCI_ANY_ID,
 	},
 	{
 		PCI_VENDOR_ID_AMI,
@@ -331,36 +325,6 @@
 	},
 	{
 		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_MEGARAID_SCSI_320_0x,
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_SUBSYS_ID_MEGARAID_SCSI_320_0x,
-	},
-	{
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_MEGARAID_SCSI_320_2x,
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_SUBSYS_ID_MEGARAID_SCSI_320_2x,
-	},
-	{
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_MEGARAID_SCSI_320_4x,
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_SUBSYS_ID_MEGARAID_SCSI_320_4x,
-	},
-	{
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_MEGARAID_SCSI_320_1E,
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_SUBSYS_ID_MEGARAID_SCSI_320_1E,
-	},
-	{
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_MEGARAID_SCSI_320_2E,
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_SUBSYS_ID_MEGARAID_SCSI_320_2E,
-	},
-	{
-		PCI_VENDOR_ID_LSI_LOGIC,
 		PCI_DEVICE_ID_MEGARAID_I4_133_RAID,
 		PCI_VENDOR_ID_LSI_LOGIC,
 		PCI_SUBSYS_ID_MEGARAID_I4_133_RAID,
@@ -379,21 +343,9 @@
 	},
 	{
 		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_MEGARAID_SATA_300_4x,
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_SUBSYS_ID_MEGARAID_SATA_300_4x,
-	},
-	{
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_MEGARAID_SATA_300_8x,
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_SUBSYS_ID_MEGARAID_SATA_300_8x,
-	},
-	{
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_INTEL_RAID_SRCU42X,
-		PCI_VENDOR_ID_INTEL,
-		PCI_SUBSYS_ID_INTEL_RAID_SRCU42X,
+		PCI_DEVICE_ID_LINDSAY,
+		PCI_ANY_ID,
+		PCI_ANY_ID,
 	},
 	{
 		PCI_VENDOR_ID_LSI_LOGIC,
@@ -403,58 +355,10 @@
 	},
 	{
 		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_INTEL_RAID_SRCU42E,
-		PCI_VENDOR_ID_INTEL,
-		PCI_SUBSYS_ID_INTEL_RAID_SRCU42E,
-	},
-	{
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_INTEL_RAID_SRCZCRX,
-		PCI_VENDOR_ID_INTEL,
-		PCI_SUBSYS_ID_INTEL_RAID_SRCZCRX,
-	},
-	{
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_INTEL_RAID_SRCS28X,
-		PCI_VENDOR_ID_INTEL,
-		PCI_SUBSYS_ID_INTEL_RAID_SRCS28X,
-	},
-	{
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_INTEL_RAID_SROMBU42E_ALIEF,
-		PCI_VENDOR_ID_INTEL,
-		PCI_SUBSYS_ID_INTEL_RAID_SROMBU42E_ALIEF,
-	},
-	{
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_INTEL_RAID_SROMBU42E_HARWICH,
-		PCI_VENDOR_ID_INTEL,
-		PCI_SUBSYS_ID_INTEL_RAID_SROMBU42E_HARWICH,
-	},
-	{
-		PCI_VENDOR_ID_LSI_LOGIC,
 		PCI_DEVICE_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK,
 		PCI_VENDOR_ID_INTEL,
 		PCI_SUBSYS_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK,
 	},
-	{
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_FSC_MEGARAID_PCI_EXPRESS_ROMB,
-		PCI_SUBSYS_ID_FSC,
-		PCI_SUBSYS_ID_FSC_MEGARAID_PCI_EXPRESS_ROMB,
-	},
-	{
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_MEGARAID_ACER_ROMB_2E,
-		PCI_VENDOR_ID_AI,
-		PCI_SUBSYS_ID_MEGARAID_ACER_ROMB_2E,
-	},
-	{
-		PCI_VENDOR_ID_LSI_LOGIC,
-		PCI_DEVICE_ID_MEGARAID_NEC_ROMB_2E,
-		PCI_VENDOR_ID_NEC,
-		PCI_SUBSYS_ID_MEGARAID_NEC_ROMB_2E,
-	},
 	{0}	/* Terminating entry */
 };
 MODULE_DEVICE_TABLE(pci, pci_id_table_g);
@@ -539,7 +443,8 @@
 
 
 	// register as a PCI hot-plug driver module
-	if ((rval = pci_module_init(&megaraid_pci_driver_g))) {
+	rval = pci_register_driver(&megaraid_pci_driver_g);
+	if (rval < 0) {
 		con_log(CL_ANN, (KERN_WARNING
 			"megaraid: could not register hotplug support.\n"));
 	}
@@ -619,7 +524,7 @@
 
 	// Setup the default DMA mask. This would be changed later on
 	// depending on hardware capabilities
-	if (pci_set_dma_mask(adapter->pdev, 0xFFFFFFFF) != 0) {
+	if (pci_set_dma_mask(adapter->pdev, DMA_32BIT_MASK) != 0) {
 
 		con_log(CL_ANN, (KERN_WARNING
 			"megaraid: pci_set_dma_mask failed:%d\n", __LINE__));
@@ -1031,7 +936,7 @@
 
 	// Set the DMA mask to 64-bit. All supported controllers as capable of
 	// DMA in this range
-	if (pci_set_dma_mask(adapter->pdev, 0xFFFFFFFFFFFFFFFFULL) != 0) {
+	if (pci_set_dma_mask(adapter->pdev, DMA_64BIT_MASK) != 0) {
 
 		con_log(CL_ANN, (KERN_WARNING
 			"megaraid: could not set DMA mask for 64-bit.\n"));
@@ -2661,7 +2566,7 @@
  * aborted. All the commands issued to the F/W must complete.
  **/
 static int
-megaraid_abort_handler(struct scsi_cmnd *scp)
+__megaraid_abort_handler(struct scsi_cmnd *scp)
 {
 	adapter_t		*adapter;
 	mraid_device_t		*raid_dev;
@@ -2794,6 +2699,21 @@
 	return FAILED;
 }
 
+static int
+megaraid_abort_handler(struct scsi_cmnd *scp)
+{
+	adapter_t	*adapter;
+	int rc;
+
+	adapter		= SCP2ADAPTER(scp);
+
+	spin_lock_irq(adapter->host_lock);
+	rc = __megaraid_abort_handler(scp);
+	spin_unlock_irq(adapter->host_lock);
+
+	return rc;
+}
+
 
 /**
  * megaraid_reset_handler - device reset hadler for mailbox based driver
@@ -2806,7 +2726,7 @@
  * host
  **/
 static int
-megaraid_reset_handler(struct scsi_cmnd *scp)
+__megaraid_reset_handler(struct scsi_cmnd *scp)
 {
 	adapter_t	*adapter;
 	scb_t		*scb;
@@ -2927,6 +2847,18 @@
 	return rval;
 }
 
+static int
+megaraid_reset_handler(struct scsi_cmnd *cmd)
+{
+	int rc;
+
+	spin_lock_irq(cmd->device->host->host_lock);
+	rc = __megaraid_reset_handler(cmd);
+	spin_unlock_irq(cmd->device->host->host_lock);
+
+	return rc;
+}
+
 
 /*
  * START: internal commands library
@@ -4213,7 +4145,7 @@
  * @param buf	: buffer to send data to
  */
 static ssize_t
-megaraid_sysfs_show_ldnum(struct device *dev, char *buf)
+megaraid_sysfs_show_ldnum(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct scsi_device *sdev = to_scsi_device(dev);
 	adapter_t	*adapter = (adapter_t *)SCSIHOST2ADAP(sdev->host);
diff --git a/drivers/scsi/megaraid/megaraid_mbox.h b/drivers/scsi/megaraid/megaraid_mbox.h
index 0751000..644b91b 100644
--- a/drivers/scsi/megaraid/megaraid_mbox.h
+++ b/drivers/scsi/megaraid/megaraid_mbox.h
@@ -21,8 +21,8 @@
 #include "megaraid_ioctl.h"
 
 
-#define MEGARAID_VERSION	"2.20.4.5"
-#define MEGARAID_EXT_VERSION	"(Release Date: Thu Feb 03 12:27:22 EST 2005)"
+#define MEGARAID_VERSION	"2.20.4.6"
+#define MEGARAID_EXT_VERSION	"(Release Date: Mon Mar 07 12:27:22 EST 2005)"
 
 
 /*
@@ -37,8 +37,7 @@
 #define PCI_DEVICE_ID_PERC4_DC				0x1960
 #define PCI_SUBSYS_ID_PERC4_DC				0x0518
 
-#define PCI_DEVICE_ID_PERC4_QC				0x0407
-#define PCI_SUBSYS_ID_PERC4_QC				0x0531
+#define PCI_DEVICE_ID_VERDE				0x0407
 
 #define PCI_DEVICE_ID_PERC4_DI_EVERGLADES		0x000F
 #define PCI_SUBSYS_ID_PERC4_DI_EVERGLADES		0x014A
@@ -58,11 +57,7 @@
 #define PCI_DEVICE_ID_PERC4E_DI_GUADALUPE		0x0013
 #define PCI_SUBSYS_ID_PERC4E_DI_GUADALUPE		0x0170
 
-#define PCI_DEVICE_ID_PERC4E_DC_320_2E			0x0408
-#define PCI_SUBSYS_ID_PERC4E_DC_320_2E			0x0002
-
-#define PCI_DEVICE_ID_PERC4E_SC_320_1E			0x0408
-#define PCI_SUBSYS_ID_PERC4E_SC_320_1E			0x0001
+#define PCI_DEVICE_ID_DOBSON				0x0408
 
 #define PCI_DEVICE_ID_MEGARAID_SCSI_320_0		0x1960
 #define PCI_SUBSYS_ID_MEGARAID_SCSI_320_0		0xA520
@@ -73,21 +68,6 @@
 #define PCI_DEVICE_ID_MEGARAID_SCSI_320_2		0x1960
 #define PCI_SUBSYS_ID_MEGARAID_SCSI_320_2		0x0518
 
-#define PCI_DEVICE_ID_MEGARAID_SCSI_320_0x		0x0407
-#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_0x		0x0530
-
-#define PCI_DEVICE_ID_MEGARAID_SCSI_320_2x		0x0407
-#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_2x		0x0532
-
-#define PCI_DEVICE_ID_MEGARAID_SCSI_320_4x		0x0407
-#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_4x		0x0531
-
-#define PCI_DEVICE_ID_MEGARAID_SCSI_320_1E		0x0408
-#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_1E		0x0001
-
-#define PCI_DEVICE_ID_MEGARAID_SCSI_320_2E		0x0408
-#define PCI_SUBSYS_ID_MEGARAID_SCSI_320_2E		0x0002
-
 #define PCI_DEVICE_ID_MEGARAID_I4_133_RAID		0x1960
 #define PCI_SUBSYS_ID_MEGARAID_I4_133_RAID		0x0522
 
@@ -97,52 +77,18 @@
 #define PCI_DEVICE_ID_MEGARAID_SATA_150_6		0x1960
 #define PCI_SUBSYS_ID_MEGARAID_SATA_150_6		0x0523
 
-#define PCI_DEVICE_ID_MEGARAID_SATA_300_4x		0x0409
-#define PCI_SUBSYS_ID_MEGARAID_SATA_300_4x		0x3004
-
-#define PCI_DEVICE_ID_MEGARAID_SATA_300_8x		0x0409
-#define PCI_SUBSYS_ID_MEGARAID_SATA_300_8x		0x3008
-
-#define PCI_DEVICE_ID_INTEL_RAID_SRCU42X		0x0407
-#define PCI_SUBSYS_ID_INTEL_RAID_SRCU42X		0x0532
+#define PCI_DEVICE_ID_LINDSAY				0x0409
 
 #define PCI_DEVICE_ID_INTEL_RAID_SRCS16			0x1960
 #define PCI_SUBSYS_ID_INTEL_RAID_SRCS16			0x0523
 
-#define PCI_DEVICE_ID_INTEL_RAID_SRCU42E		0x0408
-#define PCI_SUBSYS_ID_INTEL_RAID_SRCU42E		0x0002
-
-#define PCI_DEVICE_ID_INTEL_RAID_SRCZCRX		0x0407
-#define PCI_SUBSYS_ID_INTEL_RAID_SRCZCRX		0x0530
-
-#define PCI_DEVICE_ID_INTEL_RAID_SRCS28X		0x0409
-#define PCI_SUBSYS_ID_INTEL_RAID_SRCS28X		0x3008
-
-#define PCI_DEVICE_ID_INTEL_RAID_SROMBU42E_ALIEF	0x0408
-#define PCI_SUBSYS_ID_INTEL_RAID_SROMBU42E_ALIEF	0x3431
-
-#define PCI_DEVICE_ID_INTEL_RAID_SROMBU42E_HARWICH	0x0408
-#define PCI_SUBSYS_ID_INTEL_RAID_SROMBU42E_HARWICH	0x3499
-
 #define PCI_DEVICE_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK	0x1960
 #define PCI_SUBSYS_ID_INTEL_RAID_SRCU41L_LAKE_SHETEK	0x0520
 
-#define PCI_DEVICE_ID_FSC_MEGARAID_PCI_EXPRESS_ROMB	0x0408
-#define PCI_SUBSYS_ID_FSC_MEGARAID_PCI_EXPRESS_ROMB	0x1065
-
-#define PCI_DEVICE_ID_MEGARAID_ACER_ROMB_2E		0x0408
-#define PCI_SUBSYS_ID_MEGARAID_ACER_ROMB_2E		0x004D
-
 #define PCI_SUBSYS_ID_PERC3_QC				0x0471
 #define PCI_SUBSYS_ID_PERC3_DC				0x0493
 #define PCI_SUBSYS_ID_PERC3_SC				0x0475
 
-#define PCI_DEVICE_ID_MEGARAID_NEC_ROMB_2E		0x0408
-#define PCI_SUBSYS_ID_MEGARAID_NEC_ROMB_2E		0x8287
-
-#ifndef PCI_SUBSYS_ID_FSC
-#define PCI_SUBSYS_ID_FSC				0x1734
-#endif
 
 #define MBOX_MAX_SCSI_CMDS	128	// number of cmds reserved for kernel
 #define MBOX_MAX_USER_CMDS	32	// number of cmds for applications
diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c
index 9f1b550..37d110e 100644
--- a/drivers/scsi/megaraid/megaraid_mm.c
+++ b/drivers/scsi/megaraid/megaraid_mm.c
@@ -10,13 +10,12 @@
  *	   2 of the License, or (at your option) any later version.
  *
  * FILE		: megaraid_mm.c
- * Version	: v2.20.2.5 (Jan 21 2005)
+ * Version	: v2.20.2.6 (Mar 7 2005)
  *
  * Common management module
  */
 
 #include "megaraid_mm.h"
-#include <linux/smp_lock.h>
 
 
 // Entry points for char node driver
@@ -61,7 +60,7 @@
 EXPORT_SYMBOL(mraid_mm_adapter_app_handle);
 
 static int majorno;
-static uint32_t drvr_ver	= 0x02200201;
+static uint32_t drvr_ver	= 0x02200206;
 
 static int adapters_count_g;
 static struct list_head adapters_list_g;
@@ -1231,9 +1230,9 @@
 		      unsigned long arg)
 {
 	int err;
-	lock_kernel();
+
 	err = mraid_mm_ioctl(NULL, filep, cmd, arg);
-	unlock_kernel();
+
 	return err;
 }
 #endif
diff --git a/drivers/scsi/megaraid/megaraid_mm.h b/drivers/scsi/megaraid/megaraid_mm.h
index 948a001..7e36c46 100644
--- a/drivers/scsi/megaraid/megaraid_mm.h
+++ b/drivers/scsi/megaraid/megaraid_mm.h
@@ -29,9 +29,9 @@
 #include "megaraid_ioctl.h"
 
 
-#define LSI_COMMON_MOD_VERSION	"2.20.2.5"
+#define LSI_COMMON_MOD_VERSION	"2.20.2.6"
 #define LSI_COMMON_MOD_EXT_VERSION	\
-		"(Release Date: Fri Jan 21 00:01:03 EST 2005)"
+		"(Release Date: Mon Mar 7 00:01:03 EST 2005)"
 
 
 #define LSI_DBGLVL			dbglevel
diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c
index f6da46d..b05737a 100644
--- a/drivers/scsi/mesh.c
+++ b/drivers/scsi/mesh.c
@@ -1715,9 +1715,12 @@
 	struct mesh_state *ms = (struct mesh_state *) cmd->device->host->hostdata;
 	volatile struct mesh_regs __iomem *mr = ms->mesh;
 	volatile struct dbdma_regs __iomem *md = ms->dma;
+	unsigned long flags;
 
 	printk(KERN_DEBUG "mesh_host_reset\n");
 
+	spin_lock_irqsave(ms->host->host_lock, flags);
+
 	/* Reset the controller & dbdma channel */
 	out_le32(&md->control, (RUN|PAUSE|FLUSH|WAKE) << 16);	/* stop dma */
 	out_8(&mr->exception, 0xff);	/* clear all exception bits */
@@ -1739,6 +1742,7 @@
 	/* Complete pending commands */
 	handle_reset(ms);
 	
+	spin_unlock_irqrestore(ms->host->host_lock, flags);
 	return SUCCESS;
 }
 
diff --git a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c
index e73b33f..2fb31ee 100644
--- a/drivers/scsi/mvme147.c
+++ b/drivers/scsi/mvme147.c
@@ -116,7 +116,14 @@
 static int mvme147_bus_reset(Scsi_Cmnd *cmd)
 {
 	/* FIXME perform bus-specific reset */
+
+	/* FIXME 2: kill this function, and let midlayer fallback to 
+	   the same result, calling wd33c93_host_reset() */
+
+	spin_lock_irq(cmd->device->host->host_lock);
 	wd33c93_host_reset(cmd);
+	spin_unlock_irq(cmd->device->host->host_lock);
+
 	return SUCCESS;
 }
 
diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
index d28c0d9..5159cee 100644
--- a/drivers/scsi/nsp32.c
+++ b/drivers/scsi/nsp32.c
@@ -294,7 +294,6 @@
 	.this_id			= NSP32_HOST_SCSIID,
 	.use_clustering			= DISABLE_CLUSTERING,
 	.eh_abort_handler       	= nsp32_eh_abort,
-/*	.eh_device_reset_handler	= NULL, */
 	.eh_bus_reset_handler		= nsp32_eh_bus_reset,
 	.eh_host_reset_handler		= nsp32_eh_host_reset,
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,74))
@@ -2988,6 +2987,8 @@
 	nsp32_hw_data *data = (nsp32_hw_data *)SCpnt->device->host->hostdata;
 	unsigned int   base = SCpnt->device->host->io_port;
 
+	spin_lock_irq(SCpnt->device->host->host_lock);
+
 	nsp32_msg(KERN_INFO, "Bus Reset");	
 	nsp32_dbg(NSP32_DEBUG_BUSRESET, "SCpnt=0x%x", SCpnt);
 
@@ -2995,6 +2996,7 @@
 	nsp32_do_bus_reset(data);
 	nsp32_write2(base, IRQ_CONTROL, 0);
 
+	spin_unlock_irq(SCpnt->device->host->host_lock);
 	return SUCCESS;	/* SCSI bus reset is succeeded at any time. */
 }
 
@@ -3049,11 +3051,14 @@
 	nsp32_msg(KERN_INFO, "Host Reset");	
 	nsp32_dbg(NSP32_DEBUG_BUSRESET, "SCpnt=0x%x", SCpnt);
 
+	spin_lock_irq(SCpnt->device->host->host_lock);
+
 	nsp32hw_init(data);
 	nsp32_write2(base, IRQ_CONTROL, IRQ_CONTROL_ALL_IRQ_MASK);
 	nsp32_do_bus_reset(data);
 	nsp32_write2(base, IRQ_CONTROL, 0);
 
+	spin_unlock_irq(SCpnt->device->host->host_lock);
 	return SUCCESS;	/* Host reset is succeeded at any time. */
 }
 
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index c585c7b..89a4a06 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -5608,13 +5608,13 @@
 
 CLASS_DEVICE_ATTR(file_count, S_IRUGO, osst_filemark_cnt_show, NULL);
 
-static struct class_simple * osst_sysfs_class;
+static struct class *osst_sysfs_class;
 
 static int osst_sysfs_valid = 0;
 
 static void osst_sysfs_init(void)
 {
-	osst_sysfs_class = class_simple_create(THIS_MODULE, "onstream_tape");
+	osst_sysfs_class = class_create(THIS_MODULE, "onstream_tape");
 	if ( IS_ERR(osst_sysfs_class) )
 		printk(KERN_WARNING "osst :W: Unable to register sysfs class\n");
 	else
@@ -5627,7 +5627,7 @@
 
 	if (!osst_sysfs_valid) return;
 
-	osst_class_member = class_simple_device_add(osst_sysfs_class, dev, device, "%s", name);
+	osst_class_member = class_device_create(osst_sysfs_class, dev, device, "%s", name);
 	if (IS_ERR(osst_class_member)) {
 		printk(KERN_WARNING "osst :W: Unable to add sysfs class member %s\n", name);
 		return;
@@ -5645,13 +5645,13 @@
 {
 	if (!osst_sysfs_valid) return; 
 
-	class_simple_device_remove(dev);
+	class_device_destroy(osst_sysfs_class, dev);
 }
 
 static void osst_sysfs_cleanup(void)
 {
 	if (osst_sysfs_valid) {
-		class_simple_destroy(osst_sysfs_class);
+		class_destroy(osst_sysfs_class);
 		osst_sysfs_valid = 0;
 	}
 }
diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c
index 7976947..363e0eb 100644
--- a/drivers/scsi/pas16.c
+++ b/drivers/scsi/pas16.c
@@ -621,8 +621,6 @@
 	.queuecommand   = pas16_queue_command,
 	.eh_abort_handler = pas16_abort,
 	.eh_bus_reset_handler = pas16_bus_reset,
-	.eh_device_reset_handler = pas16_device_reset,
-	.eh_host_reset_handler = pas16_host_reset,
 	.bios_param     = pas16_biosparam, 
 	.can_queue      = CAN_QUEUE,
 	.this_id        = 7,
diff --git a/drivers/scsi/pas16.h b/drivers/scsi/pas16.h
index 58d4d67..65ce1cc 100644
--- a/drivers/scsi/pas16.h
+++ b/drivers/scsi/pas16.h
@@ -120,8 +120,6 @@
 static int pas16_detect(Scsi_Host_Template *);
 static int pas16_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 static int pas16_bus_reset(Scsi_Cmnd *);
-static int pas16_host_reset(Scsi_Cmnd *);
-static int pas16_device_reset(Scsi_Cmnd *);
 
 #ifndef CMD_PER_LUN
 #define CMD_PER_LUN 2
@@ -164,9 +162,7 @@
 #define do_NCR5380_intr do_pas16_intr
 #define NCR5380_queue_command pas16_queue_command
 #define NCR5380_abort pas16_abort
-#define NCR5380_device_reset pas16_device_reset
 #define NCR5380_bus_reset pas16_bus_reset
-#define NCR5380_host_reset pas16_host_reset
 #define NCR5380_proc_info pas16_proc_info
 
 /* 15 14 12 10 7 5 3 
diff --git a/drivers/scsi/pci2000.c b/drivers/scsi/pci2000.c
deleted file mode 100644
index 377a466..0000000
--- a/drivers/scsi/pci2000.c
+++ /dev/null
@@ -1,836 +0,0 @@
-/****************************************************************************
- * Perceptive Solutions, Inc. PCI-2000 device driver for Linux.
- *
- * pci2000.c - Linux Host Driver for PCI-2000 IntelliCache SCSI Adapters
- *
- * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
- * All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that redistributions of source
- * code retain the above copyright notice and this comment without
- * modification.
- *
- * Technical updates and product information at:
- *  http://www.psidisk.com
- *
- * Please send questions, comments, bug reports to:
- *  tech@psidisk.com Technical Support
- *
- *
- *	Revisions	1.10	Jan-21-1999
- *		- Fixed sign on message to reflect proper controller name.
- *		- Added support for RAID status monitoring and control.
- *
- *  Revisions	1.11	Mar-22-1999
- *		- Fixed control timeout to not lock up the entire system if
- *		  controller goes offline completely.
- *
- *	Revisions 1.12		Mar-26-1999
- *		- Fixed spinlock and PCI configuration.
- *
- *	Revisions 1.20		Mar-27-2000
- *		- Added support for dynamic DMA
- *
- ****************************************************************************/
-#define PCI2000_VERSION		"1.20"
-
-#include <linux/blkdev.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/spinlock.h>
-
-#include <asm/dma.h>
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "pci2000.h"
-#include "psi_roy.h"
-
-
-//#define DEBUG 1
-
-#ifdef DEBUG
-#define DEB(x) x
-#define STOP_HERE	{int st;for(st=0;st<100;st++){st=1;}}
-#else
-#define DEB(x)
-#define STOP_HERE
-#endif
-
-typedef struct
-	{
-	unsigned int	address;
-	unsigned int	length;
-	}	SCATGATH, *PSCATGATH;
-
-typedef struct
-	{
-	Scsi_Cmnd		*SCpnt;
-	PSCATGATH		 scatGath;
-	dma_addr_t		 scatGathDma;
-	UCHAR			*cdb;
-	dma_addr_t		 cdbDma; 
-	UCHAR			 tag;
-	}	DEV2000, *PDEV2000;
-
-typedef struct
-	{
-	ULONG			 basePort;
-	ULONG			 mb0;
-	ULONG			 mb1;
-	ULONG			 mb2;
-	ULONG			 mb3;
-	ULONG			 mb4;
-	ULONG			 cmd;
-	ULONG			 tag;
-	ULONG			 irqOwned;
-	struct pci_dev	*pdev;
-	DEV2000	 		 dev[MAX_BUS][MAX_UNITS];
-	}	ADAPTER2000, *PADAPTER2000;
-
-#define HOSTDATA(host) ((PADAPTER2000)&host->hostdata)
-#define consistentLen (MAX_BUS * MAX_UNITS * (16 * sizeof (SCATGATH) + MAX_COMMAND_SIZE))
-
-
-static struct	Scsi_Host 	   *PsiHost[MAXADAPTER] = {NULL,};  // One for each adapter
-static			int				NumAdapters = 0;
-/****************************************************************
- *	Name:			WaitReady	:LOCAL
- *
- *	Description:	Wait for controller ready.
- *
- *	Parameters:		padapter - Pointer adapter data structure.
- *
- *	Returns:		TRUE on not ready.
- *
- ****************************************************************/
-static int WaitReady (PADAPTER2000 padapter)
-	{
-	ULONG	z;
-
-	for ( z = 0;  z < (TIMEOUT_COMMAND * 4);  z++ )
-		{
-		if ( !inb_p (padapter->cmd) )
-			return FALSE;
-		udelay (250);
-		};								
-	return TRUE;
-	}
-/****************************************************************
- *	Name:			WaitReadyLong	:LOCAL
- *
- *	Description:	Wait for controller ready.
- *
- *	Parameters:		padapter - Pointer adapter data structure.
- *
- *	Returns:		TRUE on not ready.
- *
- ****************************************************************/
-static int WaitReadyLong (PADAPTER2000 padapter)
-	{
-	ULONG	z;
-
-	for ( z = 0;  z < (5000 * 4);  z++ )
-		{
-		if ( !inb_p (padapter->cmd) )
-			return FALSE;
-		udelay (250);
-		};								
-	return TRUE;
-	}
-/****************************************************************
- *	Name:	OpDone	:LOCAL
- *
- *	Description:	Clean up operation and issue done to caller.
- *
- *	Parameters:		SCpnt	- Pointer to SCSI command structure.
- *					status	- Caller status.
- *
- *	Returns:		Nothing.
- *
- ****************************************************************/
-static void OpDone (Scsi_Cmnd *SCpnt, ULONG status)
-	{
-	SCpnt->result = status;
-	SCpnt->scsi_done (SCpnt);
-	}
-/****************************************************************
- *	Name:	Command		:LOCAL
- *
- *	Description:	Issue queued command to the PCI-2000.
- *
- *	Parameters:		padapter - Pointer to adapter information structure.
- *					cmd		 - PCI-2000 command byte.
- *
- *	Returns:		Non-zero command tag if operation is accepted.
- *
- ****************************************************************/
-static UCHAR Command (PADAPTER2000 padapter, UCHAR cmd)
-	{
-	outb_p (cmd, padapter->cmd);
-	if ( WaitReady (padapter) )
-		return 0;
-
-	if ( inw_p (padapter->mb0) )
-		return 0;
-
-	return inb_p (padapter->mb1);
-	}
-/****************************************************************
- *	Name:	BuildSgList		:LOCAL
- *
- *	Description:	Build the scatter gather list for controller.
- *
- *	Parameters:		SCpnt	 - Pointer to SCSI command structure.
- *					padapter - Pointer to adapter information structure.
- *					pdev	 - Pointer to adapter device structure.
- *
- *	Returns:		Non-zero in not scatter gather.
- *
- ****************************************************************/
-static int BuildSgList (Scsi_Cmnd *SCpnt, PADAPTER2000 padapter, PDEV2000 pdev)
-	{
-	int					 z;
-	int					 zc;
-	struct scatterlist	*sg;
-
-	if ( SCpnt->use_sg )
-		{
-		sg = (struct scatterlist *)SCpnt->request_buffer;
-		zc = pci_map_sg (padapter->pdev, sg, SCpnt->use_sg, SCpnt->sc_data_direction);
-		for ( z = 0;  z < zc;  z++ )
-			{
-			pdev->scatGath[z].address = cpu_to_le32 (sg_dma_address (sg));
-			pdev->scatGath[z].length = cpu_to_le32 (sg_dma_len (sg++));
-			}
-		outl (pdev->scatGathDma, padapter->mb2);
-		outl ((zc << 24) | SCpnt->request_bufflen, padapter->mb3);
-		return FALSE;
-		}
-	if ( !SCpnt->request_bufflen)
-		{
-		outl (0, padapter->mb2);
-		outl (0, padapter->mb3);
-		return TRUE;
-		}
-	SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev,
-			SCpnt->request_buffer, SCpnt->request_bufflen,
-			SCpnt->sc_data_direction);
-	outl (SCpnt->SCp.have_data_in, padapter->mb2);
-	outl (SCpnt->request_bufflen, padapter->mb3);
-	return TRUE;
-	}
-/*********************************************************************
- *	Name:	PsiRaidCmd
- *
- *	Description:	Execute a simple command.
- *
- *	Parameters:		padapter - Pointer to adapter control structure.
- *					cmd		 - Roy command byte.
- *
- *	Returns:		Return error status.
- *
- ********************************************************************/
-static int PsiRaidCmd (PADAPTER2000 padapter, char cmd)
-	{
-	if ( WaitReady (padapter) )						// test for command register ready
-		return DID_TIME_OUT;
-	outb_p (cmd, padapter->cmd);					// issue command
-	if ( WaitReadyLong (padapter) )					// wait for adapter ready
-		return DID_TIME_OUT;
-	return DID_OK;
-	}
-/****************************************************************
- *	Name:	Irq_Handler	:LOCAL
- *
- *	Description:	Interrupt handler.
- *
- *	Parameters:		irq		- Hardware IRQ number.
- *					dev_id	-
- *					regs	-
- *
- *	Returns:		TRUE if drive is not ready in time.
- *
- ****************************************************************/
-static irqreturn_t Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
-	{
-	struct Scsi_Host   *shost = NULL;	// Pointer to host data block
-	PADAPTER2000		padapter;		// Pointer to adapter control structure
-	PDEV2000			pdev;
-	Scsi_Cmnd		   *SCpnt;
-	UCHAR				tag = 0;
-	UCHAR				tag0;
-	ULONG				error;
-	int					pun;
-	int					bus;
-	int					z;
-    unsigned long		flags;
-    int handled = 0;
-
-	DEB(printk ("\npci2000 received interrupt "));
-	for ( z = 0; z < NumAdapters;  z++ )										// scan for interrupt to process
-		{
-		if ( PsiHost[z]->irq == (UCHAR)(irq & 0xFF) )
-			{
-			tag = inb_p (HOSTDATA(PsiHost[z])->tag);
-			if (  tag )
-				{
-				shost = PsiHost[z];
-				break;
-				}
-			}
-		}
-
-	if ( !shost )
-		{
-		DEB (printk ("\npci2000: not my interrupt"));
-		goto out;
-		}
-
-    handled = 1;
-	spin_lock_irqsave(shost->host_lock, flags);
-	padapter = HOSTDATA(shost);
-
-	tag0 = tag & 0x7F;															// mask off the error bit
-	for ( bus = 0;  bus < MAX_BUS;  bus++ )										// scan the busses
-    	{
-		for ( pun = 0;  pun < MAX_UNITS;  pun++ )								// scan the targets
-    		{
-			pdev = &padapter->dev[bus][pun];
-			if ( !pdev->tag )
-    			continue;
-			if ( pdev->tag == tag0 )											// is this it?
-				{
-				pdev->tag = 0;
-				SCpnt = pdev->SCpnt;
-				goto unmapProceed;
-    			}
-			}
-    	}
-
-	outb_p (0xFF, padapter->tag);												// clear the op interrupt
-	outb_p (CMD_DONE, padapter->cmd);											// complete the op
-	goto irq_return;															// done, but, with what?
-
-unmapProceed:;
-	if ( !bus )
-		{
-		switch ( SCpnt->cmnd[0] )
-			{
-			case SCSIOP_TEST_UNIT_READY:
-				pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, sizeof (SCpnt->sense_buffer), PCI_DMA_FROMDEVICE);
-				goto irqProceed;
-			case SCSIOP_READ_CAPACITY:
-				pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, 8, PCI_DMA_FROMDEVICE);
-				goto irqProceed;
-			case SCSIOP_VERIFY:
-			case SCSIOP_START_STOP_UNIT:
-			case SCSIOP_MEDIUM_REMOVAL:
-				goto irqProceed;
-			}
-		}
-	if ( SCpnt->SCp.have_data_in )
-		pci_unmap_single (padapter->pdev, SCpnt->SCp.have_data_in, SCpnt->request_bufflen, SCpnt->sc_data_direction);
-	else 
-		{
-		if ( SCpnt->use_sg )
-			pci_unmap_sg (padapter->pdev, (struct scatterlist *)SCpnt->request_buffer, SCpnt->use_sg, SCpnt->sc_data_direction);
-		}
-
-irqProceed:;
-	if ( tag & ERR08_TAGGED )												// is there an error here?
-		{
-		if ( WaitReady (padapter) )
-			{
-			OpDone (SCpnt, DID_TIME_OUT << 16);
-			goto irq_return;
-			}
-
-		outb_p (tag0, padapter->mb0);										// get real error code
-		outb_p (CMD_ERROR, padapter->cmd);
-		if ( WaitReady (padapter) )											// wait for controller to suck up the op
-			{
-			OpDone (SCpnt, DID_TIME_OUT << 16);
-			goto irq_return;
-			}
-
-		error = inl (padapter->mb0);										// get error data
-		outb_p (0xFF, padapter->tag);										// clear the op interrupt
-		outb_p (CMD_DONE, padapter->cmd);									// complete the op
-
-		DEB (printk ("status: %lX ", error));
-		if ( error == 0x00020002 )											// is this error a check condition?
-			{
-			if ( bus )														// are we doint SCSI commands?
-				{
-				OpDone (SCpnt, (DID_OK << 16) | 2);
-				goto irq_return;
-				}
-			if ( *SCpnt->cmnd == SCSIOP_TEST_UNIT_READY )
-				OpDone (SCpnt, (DRIVER_SENSE << 24) | (DID_OK << 16) | 2);	// test caller we have sense data too
-			else
-				OpDone (SCpnt, DID_ERROR << 16);
-			goto irq_return;
-			}
-		OpDone (SCpnt, DID_ERROR << 16);
-		goto irq_return;
-		}
-
-	outb_p (0xFF, padapter->tag);											// clear the op interrupt
-	outb_p (CMD_DONE, padapter->cmd);										// complete the op
-	OpDone (SCpnt, DID_OK << 16);
-
-irq_return:
-    spin_unlock_irqrestore(shost->host_lock, flags);
-out:
-    return IRQ_RETVAL(handled);
-}
-/****************************************************************
- *	Name:	Pci2000_QueueCommand
- *
- *	Description:	Process a queued command from the SCSI manager.
- *
- *	Parameters:		SCpnt - Pointer to SCSI command structure.
- *					done  - Pointer to done function to call.
- *
- *	Returns:		Status code.
- *
- ****************************************************************/
-int Pci2000_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
-	{
-	UCHAR		   *cdb = (UCHAR *)SCpnt->cmnd;					// Pointer to SCSI CDB
-	PADAPTER2000	padapter = HOSTDATA(SCpnt->device->host);			// Pointer to adapter control structure
-	int				rc		 = -1;								// command return code
-	UCHAR			bus		 = SCpnt->device->channel;
-	UCHAR			pun		 = SCpnt->device->id;
-	UCHAR			lun		 = SCpnt->device->lun;
-	UCHAR			cmd;
-	PDEV2000		pdev	 = &padapter->dev[bus][pun];
-
-	if ( !done )
-		{
-		printk("pci2000_queuecommand: %02X: done can't be NULL\n", *cdb);
-		return 0;
-		}
-
-	SCpnt->scsi_done = done;
-	SCpnt->SCp.have_data_in = 0;
-	pdev->SCpnt = SCpnt;  									// Save this command data
-
-	if ( WaitReady (padapter) )
-		{
-		rc = DID_ERROR;
-		goto finished;
-		}
-
-	outw_p (pun | (lun << 8), padapter->mb0);
-
-	if ( bus )
-		{
-		DEB (if(*cdb) printk ("\nCDB: %X-  %X %X %X %X %X %X %X %X %X %X ", SCpnt->cmd_len, cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9]));
-		DEB (if(*cdb) printk ("\ntimeout_per_command: %d, timeout_total: %d, timeout: %d", SCpnt->timeout_per_command,
-							  SCpnt->timeout_total, SCpnt->timeout));
-		outl (SCpnt->timeout_per_command, padapter->mb1);
-		outb_p (CMD_SCSI_TIMEOUT, padapter->cmd);
-		if ( WaitReady (padapter) )
-			{
-			rc = DID_ERROR;
-			goto finished;
-			}
-
-		outw_p (pun | (lun << 8), padapter->mb0);
-		outw_p (SCpnt->cmd_len << 8, padapter->mb0 + 2);
-		memcpy (pdev->cdb, cdb, MAX_COMMAND_SIZE);
-
-		outl (pdev->cdbDma, padapter->mb1);
-		if ( BuildSgList (SCpnt, padapter, pdev) )
-			cmd = CMD_SCSI_THRU;
-		else
-			cmd = CMD_SCSI_THRU_SG;
-		if ( (pdev->tag = Command (padapter, cmd)) == 0 )
-			rc = DID_TIME_OUT;
-		goto finished;
-		}
-	else
-		{
-		if ( lun )
-			{
-			rc = DID_BAD_TARGET;
-			goto finished;
-			}
-		}
-
-	switch ( *cdb )
-		{
-		case SCSIOP_INQUIRY:   					// inquiry CDB
-			if ( cdb[2] == SC_MY_RAID )
-				{
-				switch ( cdb[3] ) 
-					{
-					case MY_SCSI_REBUILD:
-						OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_REBUILD) << 16);
-						return 0;
-					case MY_SCSI_ALARMMUTE:
-						OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_MUTE) << 16);
-						return 0;
-					case MY_SCSI_DEMOFAIL:
-						OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_FAIL) << 16);
-						return 0;
-					default:
-						if ( SCpnt->use_sg )
-							{
-							rc = DID_ERROR;
-							goto finished;
-							}
-						else
-							{
-							SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, SCpnt->request_bufflen,
-													  SCpnt->sc_data_direction);
-							outl (SCpnt->SCp.have_data_in, padapter->mb2);
-							}
-						outl (cdb[5], padapter->mb0);
-						outl (cdb[3], padapter->mb3);
-						cmd = CMD_DASD_RAID_RQ;
-						break;
-					}
-				break;
-				}
-			
-			if ( SCpnt->use_sg )
-				{
-				SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev,
-									  ((struct scatterlist *)SCpnt->request_buffer)->address,
-									  SCpnt->request_bufflen,
-									  SCpnt->sc_data_direction);
-				}
-			else
-				{
-				SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer,
-									  SCpnt->request_bufflen,
-									  SCpnt->sc_data_direction);
-				}
-			outl (SCpnt->SCp.have_data_in, padapter->mb2);
-			outl (SCpnt->request_bufflen, padapter->mb3);
-			cmd = CMD_DASD_SCSI_INQ;
-			break;
-
-		case SCSIOP_TEST_UNIT_READY:			// test unit ready CDB
-			SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->sense_buffer, sizeof (SCpnt->sense_buffer), PCI_DMA_FROMDEVICE);
-			outl (SCpnt->SCp.have_data_in, padapter->mb2);
-			outl (sizeof (SCpnt->sense_buffer), padapter->mb3);
-			cmd = CMD_TEST_READY;
-			break;
-
-		case SCSIOP_READ_CAPACITY:			  	// read capacity CDB
-			if ( SCpnt->use_sg )
-				{
-				SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, ((struct scatterlist *)(SCpnt->request_buffer))->address,
-										  8, PCI_DMA_FROMDEVICE);
-				}
-			else
-				SCpnt->SCp.have_data_in = pci_map_single (padapter->pdev, SCpnt->request_buffer, 8, PCI_DMA_FROMDEVICE);
-			outl (SCpnt->SCp.have_data_in, padapter->mb2);
-			outl (8, padapter->mb3);
-			cmd = CMD_DASD_CAP;
-			break;
-		case SCSIOP_VERIFY:						// verify CDB
-			outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
-			outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
-			cmd = CMD_READ_SG;
-			break;
-		case SCSIOP_READ:						// read10 CDB
-			outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
-			outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
-			if ( BuildSgList (SCpnt, padapter, pdev) )
-				cmd = CMD_READ;
-			else
-				cmd = CMD_READ_SG;
-			break;
-		case SCSIOP_READ6:						// read6  CDB
-			outw_p (cdb[4], padapter->mb0 + 2);
-			outl ((SCSI2LONG (&cdb[1])) & 0x001FFFFF, padapter->mb1);
-			if ( BuildSgList (SCpnt, padapter, pdev) )
-				cmd = CMD_READ;
-			else
-				cmd = CMD_READ_SG;
-			break;
-		case SCSIOP_WRITE:						// write10 CDB
-			outw_p ((USHORT)cdb[8] | ((USHORT)cdb[7] << 8), padapter->mb0 + 2);
-			outl (XSCSI2LONG (&cdb[2]), padapter->mb1);
-			if ( BuildSgList (SCpnt, padapter, pdev) )
-				cmd = CMD_WRITE;
-			else
-				cmd = CMD_WRITE_SG;
-			break;
-		case SCSIOP_WRITE6:						// write6  CDB
-			outw_p (cdb[4], padapter->mb0 + 2);
-			outl ((SCSI2LONG (&cdb[1])) & 0x001FFFFF, padapter->mb1);
-			if ( BuildSgList (SCpnt, padapter, pdev) )
-				cmd = CMD_WRITE;
-			else
-				cmd = CMD_WRITE_SG;
-			break;
-		case SCSIOP_START_STOP_UNIT:
-			cmd = CMD_EJECT_MEDIA;
-			break;
-		case SCSIOP_MEDIUM_REMOVAL:
-			switch ( cdb[4] )
-				{
-				case 0:
-					cmd = CMD_UNLOCK_DOOR;
-					break;
-				case 1:
-					cmd = CMD_LOCK_DOOR;
-					break;
-				default:
-					cmd = 0;
-					break;
-				}
-			if ( cmd )
-				break;
-		default:
-			DEB (printk ("pci2000_queuecommand: Unsupported command %02X\n", *cdb));
-			OpDone (SCpnt, DID_ERROR << 16);
-			return 0;
-		}
-
-	if ( (pdev->tag = Command (padapter, cmd)) == 0 )
-		rc = DID_TIME_OUT;
-finished:;
-	if ( rc != -1 )
-		OpDone (SCpnt, rc << 16);
-	return 0;
-	}
-/****************************************************************
- *	Name:	Pci2000_Detect
- *
- *	Description:	Detect and initialize our boards.
- *
- *	Parameters:		tpnt - Pointer to SCSI host template structure.
- *
- *	Returns:		Number of adapters installed.
- *
- ****************************************************************/
-int Pci2000_Detect (Scsi_Host_Template *tpnt)
-	{
-	int					found = 0;
-	int					installed = 0;
-	struct Scsi_Host   *pshost;
-	PADAPTER2000	    padapter;
-	int					z, zz;
-	int					setirq;
-	struct pci_dev	   *pdev = NULL;
-	UCHAR			   *consistent;
-	dma_addr_t			consistentDma;
-
-	while ( (pdev = pci_find_device (VENDOR_PSI, DEVICE_ROY_1, pdev)) != NULL )
-		{
-		if (pci_enable_device(pdev))
-			continue;
-		pshost = scsi_register (tpnt, sizeof(ADAPTER2000));
-		if(pshost == NULL)
-			continue;
-		padapter = HOSTDATA(pshost);
-
-		padapter->basePort = pci_resource_start (pdev, 1);
-		DEB (printk ("\nBase Regs = %#04X", padapter->basePort));			// get the base I/O port address
-		padapter->mb0	= padapter->basePort + RTR_MAILBOX;		   			// get the 32 bit mail boxes
-		padapter->mb1	= padapter->basePort + RTR_MAILBOX + 4;
-		padapter->mb2	= padapter->basePort + RTR_MAILBOX + 8;
-		padapter->mb3	= padapter->basePort + RTR_MAILBOX + 12;
-		padapter->mb4	= padapter->basePort + RTR_MAILBOX + 16;
-		padapter->cmd	= padapter->basePort + RTR_LOCAL_DOORBELL;			// command register
-		padapter->tag	= padapter->basePort + RTR_PCI_DOORBELL;			// tag/response register
-		padapter->pdev = pdev;
-
-		if ( WaitReady (padapter) )
-			goto unregister;
-		outb_p (0x84, padapter->mb0);
-		outb_p (CMD_SPECIFY, padapter->cmd);
-		if ( WaitReady (padapter) )
-			goto unregister;
-
-		consistent = pci_alloc_consistent (pdev, consistentLen, &consistentDma);
-		if ( !consistent )
-			{
-			printk ("Unable to allocate DMA memory for PCI-2000 controller.\n");
-			goto unregister;
-			}
-		
-		scsi_set_device(pshost, &pdev->dev);
-		pshost->irq = pdev->irq;
-		setirq = 1;
-		padapter->irqOwned = 0;
-		for ( z = 0;  z < installed;  z++ )									// scan for shared interrupts
-			{
-			if ( PsiHost[z]->irq == pshost->irq )							// if shared then, don't posses
-				setirq = 0;
-			}
-		if ( setirq )												// if not shared, posses
-			{
-			if ( request_irq (pshost->irq, Irq_Handler, SA_SHIRQ, "pci2000", padapter) < 0 )
-				{
-				if ( request_irq (pshost->irq, Irq_Handler, SA_INTERRUPT | SA_SHIRQ, "pci2000", padapter) < 0 )
-					{
-					printk ("Unable to allocate IRQ for PCI-2000 controller.\n");
-					pci_free_consistent (pdev, consistentLen, consistent, consistentDma);
-					goto unregister;
-					}
-				}
-			padapter->irqOwned = pshost->irq;						// set IRQ as owned
-			}
-		PsiHost[installed]	= pshost;										// save SCSI_HOST pointer
-
-		pshost->io_port		= padapter->basePort;
-		pshost->n_io_port	= 0xFF;
-		pshost->unique_id	= padapter->basePort;
-		pshost->max_id		= 16;
-		pshost->max_channel	= 1;
-
-		for ( zz = 0;  zz < MAX_BUS;  zz++ )
-			for ( z = 0; z < MAX_UNITS;  z++ )
-				{
-				padapter->dev[zz][z].tag = 0;
-				padapter->dev[zz][z].scatGath = (PSCATGATH)consistent;
-				padapter->dev[zz][z].scatGathDma = consistentDma;
-				consistent += 16 * sizeof (SCATGATH);
-				consistentDma += 16 * sizeof (SCATGATH);
-				padapter->dev[zz][z].cdb = (UCHAR *)consistent;
-				padapter->dev[zz][z].cdbDma = consistentDma;
-				consistent += MAX_COMMAND_SIZE;
-				consistentDma += MAX_COMMAND_SIZE;
-				}
-			
-		printk("\nPSI-2000 Intelligent Storage SCSI CONTROLLER: at I/O = %lX  IRQ = %d\n", padapter->basePort, pshost->irq);
-		printk("Version %s, Compiled %s %s\n\n", PCI2000_VERSION,  __DATE__, __TIME__);
-		found++;
-		if ( ++installed < MAXADAPTER )
-			continue;
-		break;
-unregister:;
-		scsi_unregister (pshost);
-		found++;
-		}
-	NumAdapters = installed;
-	return installed;
-	}
-/****************************************************************
- *	Name:	Pci2000_Abort
- *
- *	Description:	Process the Abort command from the SCSI manager.
- *
- *	Parameters:		SCpnt - Pointer to SCSI command structure.
- *
- *	Returns:		Allways snooze.
- *
- ****************************************************************/
-int Pci2000_Abort (Scsi_Cmnd *SCpnt)
-	{
-	DEB (printk ("pci2000_abort\n"));
-	return SCSI_ABORT_SNOOZE;
-	}
-/****************************************************************
- *	Name:	Pci2000_Reset
- *
- *	Description:	Process the Reset command from the SCSI manager.
- *
- *	Parameters:		SCpnt - Pointer to SCSI command structure.
- *					flags - Flags about the reset command
- *
- *	Returns:		No active command at this time, so this means
- *					that each time we got some kind of response the
- *					last time through.  Tell the mid-level code to
- *					request sense information in order to decide what
- *					to do next.
- *
- ****************************************************************/
-int Pci2000_Reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
-	{
-	return SCSI_RESET_PUNT;
-	}
-/****************************************************************
- *	Name:	Pci2000_Release
- *
- *	Description:	Release resources allocated for a single each adapter.
- *
- *	Parameters:		pshost - Pointer to SCSI command structure.
- *
- *	Returns:		zero.
- *
- ****************************************************************/
-int Pci2000_Release (struct Scsi_Host *pshost)
-	{
-    PADAPTER2000	padapter = HOSTDATA (pshost);
-
-	if ( padapter->irqOwned )
-		free_irq (pshost->irq, padapter);
-	pci_free_consistent (padapter->pdev, consistentLen, padapter->dev[0][0].scatGath, padapter->dev[0][0].scatGathDma);
-	release_region (pshost->io_port, pshost->n_io_port);
-    scsi_unregister(pshost);
-    return 0;
-	}
-
-/****************************************************************
- *	Name:	Pci2000_BiosParam
- *
- *	Description:	Process the biosparam request from the SCSI manager to
- *					return C/H/S data.
- *
- *	Parameters:		disk - Pointer to SCSI disk structure.
- *					dev	 - Major/minor number from kernel.
- *					geom - Pointer to integer array to place geometry data.
- *
- *	Returns:		zero.
- *
- ****************************************************************/
-int Pci2000_BiosParam (struct scsi_device *sdev, struct block_device *dev,
-		sector_t capacity, int geom[])
-	{
-	PADAPTER2000	    padapter;
-
-	padapter = HOSTDATA(sdev->host);
-
-	if ( WaitReady (padapter) )
-		return 0;
-	outb_p (sdev->id, padapter->mb0);
-	outb_p (CMD_GET_PARMS, padapter->cmd);
-	if ( WaitReady (padapter) )
-		return 0;
-
-	geom[0] = inb_p (padapter->mb2 + 3);
-	geom[1] = inb_p (padapter->mb2 + 2);
-	geom[2] = inw_p (padapter->mb2);
-	return 0;
-	}
-
-
-MODULE_LICENSE("Dual BSD/GPL");
-
-static Scsi_Host_Template driver_template = {
-	.proc_name	= "pci2000",
-	.name		= "PCI-2000 SCSI Intelligent Disk Controller",
-	.detect		= Pci2000_Detect,
-	.release	= Pci2000_Release,
-	.queuecommand	= Pci2000_QueueCommand,
-	.abort		= Pci2000_Abort,
-	.reset		= Pci2000_Reset,
-	.bios_param	= Pci2000_BiosParam,
-	.can_queue	= 16,
-	.this_id	= -1,
-	.sg_tablesize	= 16,
-	.cmd_per_lun	= 1,
-	.use_clustering	= DISABLE_CLUSTERING,
-};
-#include "scsi_module.c"
diff --git a/drivers/scsi/pci2220i.c b/drivers/scsi/pci2220i.c
deleted file mode 100644
index e395e42..0000000
--- a/drivers/scsi/pci2220i.c
+++ /dev/null
@@ -1,2915 +0,0 @@
-/****************************************************************************
- * Perceptive Solutions, Inc. PCI-2220I device driver for Linux.
- *
- * pci2220i.c - Linux Host Driver for PCI-2220I EIDE RAID Adapters
- *
- * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
- * All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that redistributions of source
- * code retain the above copyright notice and this comment without
- * modification.
- *
- * Technical updates and product information at:
- *  http://www.psidisk.com
- *
- * Please send questions, comments, bug reports to:
- *  tech@psidisk.com Technical Support
- *
- *
- *	Revisions 1.10		Mar-26-1999
- *		- Updated driver for RAID and hot reconstruct support.
- *
- *	Revisions 1.11		Mar-26-1999
- *		- Fixed spinlock and PCI configuration.
- *
- *	Revision 2.00		December-1-1999
- *		- Added code for the PCI-2240I controller
- *		- Added code for ATAPI devices.
- *		- Double buffer for scatter/gather support
- *
- *	Revision 2.10		March-27-2000
- *		- Added support for dynamic DMA
- *
- ****************************************************************************/
-
-#error Convert me to understand page+offset based scatterlists
-
-//#define DEBUG 1
-
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/blkdev.h>
-#include <linux/timer.h>
-#include <linux/spinlock.h>
-
-#include <asm/dma.h>
-#include <asm/system.h>
-#include <asm/io.h>
-
-#include "scsi.h"
-#include <scsi/scsi_host.h>
-#include "pci2220i.h"
-#include "psi_dale.h"
-
-
-#define	PCI2220I_VERSION		"2.10"
-#define	READ_CMD				IDE_CMD_READ_MULTIPLE
-#define	WRITE_CMD				IDE_CMD_WRITE_MULTIPLE
-#define	MAX_BUS_MASTER_BLOCKS	SECTORSXFER		// This is the maximum we can bus master
-
-#ifdef DEBUG
-#define DEB(x) x
-#define STOP_HERE()	{int st;for(st=0;st<100;st++){st=1;}}
-#else
-#define DEB(x)
-#define STOP_HERE()
-#endif
-
-#define MAXADAPTER 4					// Increase this and the sizes of the arrays below, if you need more.
-
-
-typedef struct
-	{
-	UCHAR			byte6;				// device select register image
-	UCHAR			spigot;				// spigot number
-	UCHAR			spigots[2];			// RAID spigots
-	UCHAR			deviceID[2];		// device ID codes
-	USHORT			sectors;			// number of sectors per track
-	USHORT			heads;				// number of heads
-	USHORT			cylinders;			// number of cylinders for this device
-	USHORT			spareword;			// placeholder
-	ULONG			blocks;				// number of blocks on device
-	DISK_MIRROR		DiskMirror[2];		// RAID status and control
-	ULONG			lastsectorlba[2];	// last addressable sector on the drive
-	USHORT			raid;				// RAID active flag
-	USHORT			mirrorRecon;
-	UCHAR			reconOn;
-	USHORT			reconCount;
-	USHORT			reconIsStarting;	// indicate hot reconstruct is starting
-	UCHAR			cmdDrqInt;			// flag for command interrupt
-	UCHAR			packet;				// command packet size in bytes
-	}	OUR_DEVICE, *POUR_DEVICE;	
-
-typedef struct
-	{
-	USHORT		 bigD;					// identity is a PCI-2240I if true, otherwise a PCI-2220I
-	USHORT		 atapi;					// this interface is for ATAPI devices only
-	ULONG		 regDmaDesc;			// address of the DMA discriptor register for direction of transfer
-	ULONG		 regDmaCmdStat;			// Byte #1 of DMA command status register
-	ULONG		 regDmaAddrPci;			// 32 bit register for PCI address of DMA
-	ULONG		 regDmaAddrLoc;			// 32 bit register for local bus address of DMA
-	ULONG		 regDmaCount;			// 32 bit register for DMA transfer count
-	ULONG		 regDmaMode;			// 32 bit register for DMA mode control
-	ULONG		 regRemap;				// 32 bit local space remap
-	ULONG		 regDesc;				// 32 bit local region descriptor
-	ULONG		 regRange;				// 32 bit local range
-	ULONG		 regIrqControl;			// 16 bit Interrupt enable/disable and status
-	ULONG		 regScratchPad;			// scratch pad I/O base address
-	ULONG		 regBase;				// Base I/O register for data space
-	ULONG		 regData;				// data register I/O address
-	ULONG		 regError;				// error register I/O address
-	ULONG		 regSectCount;			// sector count register I/O address
-	ULONG		 regLba0;				// least significant byte of LBA
-	ULONG		 regLba8;				// next least significant byte of LBA
-	ULONG		 regLba16;				// next most significan byte of LBA
-	ULONG		 regLba24;				// head and most 4 significant bits of LBA
-	ULONG		 regStatCmd;			// status on read and command on write register
-	ULONG		 regStatSel;			// board status on read and spigot select on write register
-	ULONG		 regFail;				// fail bits control register
-	ULONG		 regAltStat;			// alternate status and drive control register
-	ULONG		 basePort;				// PLX base I/O port
-	USHORT		 timingMode;			// timing mode currently set for adapter
-	USHORT		 timingPIO;				// TRUE if PIO timing is active
-	struct pci_dev	*pcidev;
-	ULONG		 timingAddress;			// address to use on adapter for current timing mode
-	ULONG		 irqOwned;				// owned IRQ or zero if shared
-	UCHAR		 numberOfDrives;		// saved number of drives on this controller
-	UCHAR		 failRegister;			// current inverted data in fail register
-	OUR_DEVICE	 device[BIGD_MAXDRIVES];
-	DISK_MIRROR	*raidData[BIGD_MAXDRIVES];
-	ULONG		 startSector;
-	USHORT		 sectorCount;
-	ULONG		 readCount;
-	UCHAR		*currentSgBuffer;
-	ULONG		 currentSgCount;
-	USHORT		 nextSg;
-	UCHAR		 cmd;
-	Scsi_Cmnd	*SCpnt;
-	POUR_DEVICE	 pdev;					// current device opearating on
-	USHORT		 devInReconIndex;
-	USHORT		 expectingIRQ;
-	USHORT		 reconOn;				// Hot reconstruct is to be done.
-	USHORT		 reconPhase;			// Hot reconstruct operation is in progress.
-	ULONG		 reconSize;
-	USHORT		 demoFail;				// flag for RAID failure demonstration
-	USHORT		 survivor;
-	USHORT		 failinprog;
-	struct timer_list	reconTimer;	
-	struct timer_list	timer;
-	UCHAR		*kBuffer;
-	dma_addr_t	 kBufferDma;
-	UCHAR		 reqSense;
-	UCHAR		 atapiCdb[16];
-	UCHAR		 atapiSpecial;
-	}	ADAPTER2220I, *PADAPTER2220I;
-
-#define HOSTDATA(host) ((PADAPTER2220I)&host->hostdata)
-
-#define	RECON_PHASE_READY		0x01
-#define	RECON_PHASE_COPY		0x02
-#define	RECON_PHASE_UPDATE		0x03
-#define	RECON_PHASE_LAST		0x04
-#define	RECON_PHASE_END			0x07	
-#define	RECON_PHASE_MARKING		0x80
-#define	RECON_PHASE_FAILOVER	0xFF
-
-static struct	Scsi_Host 	   *PsiHost[MAXADAPTER] = {NULL,};  // One for each adapter
-static			int				NumAdapters = 0;
-static			int				Installed = 0;
-static			SETUP			DaleSetup;
-static			DISK_MIRROR		DiskMirror[BIGD_MAXDRIVES];
-static			ULONG			ModeArray[] = {DALE_DATA_MODE2, DALE_DATA_MODE3, DALE_DATA_MODE4, DALE_DATA_MODE5};
-static			ULONG			ModeArray2[] = {BIGD_DATA_MODE2, BIGD_DATA_MODE3, BIGD_DATA_MODE4, BIGD_DATA_MODE5};
-
-static void ReconTimerExpiry (unsigned long data);
-
-/*******************************************************************************************************
- *	Name:			Alarm
- *
- *	Description:	Sound the for the given device
- *
- *	Parameters:		padapter - Pointer adapter data structure.
- *					device	 - Device number.
- *	
- *	Returns:		Nothing.
- *
- ******************************************************************************************************/
-static void Alarm (PADAPTER2220I padapter, UCHAR device)
-	{
-	UCHAR	zc;
-
-	if ( padapter->bigD )
-		{
-		zc = device | (FAIL_ANY | FAIL_AUDIBLE);
-		if ( padapter->failRegister & FAIL_ANY ) 
-			zc |= FAIL_MULTIPLE;
-		
-		padapter->failRegister = zc;
-		outb_p (~zc, padapter->regFail);
-		}
-	else
-		outb_p (0x3C | (1 << device), padapter->regFail);			// sound alarm and set fail light		
-	}
-/****************************************************************
- *	Name:	MuteAlarm	:LOCAL
- *
- *	Description:	Mute the audible alarm.
- *
- *	Parameters:		padapter - Pointer adapter data structure.
- *
- *	Returns:		TRUE if drive does not assert DRQ in time.
- *
- ****************************************************************/
-static void MuteAlarm (PADAPTER2220I padapter)
-	{
-	UCHAR	old;
-
-	if ( padapter->bigD )
-		{
-		padapter->failRegister &= ~FAIL_AUDIBLE;
-		outb_p (~padapter->failRegister, padapter->regFail);
-		}
-	else
-		{
-		old = (inb_p (padapter->regStatSel) >> 3) | (inb_p (padapter->regStatSel) & 0x83);
-		outb_p (old | 0x40, padapter->regFail);
-		}
-	}
-/****************************************************************
- *	Name:	WaitReady	:LOCAL
- *
- *	Description:	Wait for device ready.
- *
- *	Parameters:		padapter - Pointer adapter data structure.
- *
- *	Returns:		TRUE if drive does not assert DRQ in time.
- *
- ****************************************************************/
-static int WaitReady (PADAPTER2220I padapter)
-	{
-	ULONG	z;
-	UCHAR	status;
-
-	for ( z = 0;  z < (TIMEOUT_READY * 4);  z++ )
-		{
-		status = inb_p (padapter->regStatCmd);
-		if ( (status & (IDE_STATUS_DRDY | IDE_STATUS_BUSY)) == IDE_STATUS_DRDY )
-			return 0;
-		udelay (250);
-		}
-	return status;
-	}
-/****************************************************************
- *	Name:	WaitReadyReset	:LOCAL
- *
- *	Description:	Wait for device ready.
- *
- *	Parameters:		padapter - Pointer adapter data structure.
- *
- *	Returns:		TRUE if drive does not assert DRQ in time.
- *
- ****************************************************************/
-static int WaitReadyReset (PADAPTER2220I padapter)
-	{
-	ULONG	z;
-	UCHAR	status;
-
-	for ( z = 0;  z < (125 * 16);  z++ )				// wait up to 1/4 second
-		{
-		status = inb_p (padapter->regStatCmd);
-		if ( (status & (IDE_STATUS_DRDY | IDE_STATUS_BUSY)) == IDE_STATUS_DRDY )
-			{
-			DEB (printk ("\nPCI2220I:  Reset took %ld mSec to be ready", z / 8));
-			return 0;
-			}
-		udelay (125);
-		}
-	DEB (printk ("\nPCI2220I:  Reset took more than 2 Seconds to come ready, Disk Failure"));
-	return status;
-	}
-/****************************************************************
- *	Name:	WaitDrq	:LOCAL
- *
- *	Description:	Wait for device ready for data transfer.
- *
- *	Parameters:		padapter - Pointer adapter data structure.
- *
- *	Returns:		TRUE if drive does not assert DRQ in time.
- *
- ****************************************************************/
-static int WaitDrq (PADAPTER2220I padapter)
-	{
-	ULONG	z;
-	UCHAR	status;
-
-	for ( z = 0;  z < (TIMEOUT_DRQ * 4);  z++ )
-		{
-		status = inb_p (padapter->regStatCmd);
-		if ( status & IDE_STATUS_DRQ )
-			return 0;
-		udelay (250);
-		}
-	return status;
-	}
-/****************************************************************
- *	Name:	AtapiWaitReady	:LOCAL
- *
- *	Description:	Wait for device busy and DRQ to be cleared.
- *
- *	Parameters:		padapter - Pointer adapter data structure.
- *					msec	 - Number of milliseconds to wait.
- *
- *	Returns:		TRUE if drive does not clear busy in time.
- *
- ****************************************************************/
-static int AtapiWaitReady (PADAPTER2220I padapter, int msec)
-	{
-	int z;
-
-	for ( z = 0;  z < (msec * 16);  z++ )
-		{
-		if ( !(inb_p (padapter->regStatCmd) & (IDE_STATUS_BUSY | IDE_STATUS_DRQ)) )
-			return FALSE;
-		udelay (125);
-		}
-	return TRUE;
-	}
-/****************************************************************
- *	Name:	AtapiWaitDrq	:LOCAL
- *
- *	Description:	Wait for device ready for data transfer.
- *
- *	Parameters:		padapter - Pointer adapter data structure.
- *					msec	 - Number of milliseconds to wait.
- *
- *	Returns:		TRUE if drive does not assert DRQ in time.
- *
- ****************************************************************/
-static int AtapiWaitDrq (PADAPTER2220I padapter, int msec)
-	{
-	ULONG	z;
-
-	for ( z = 0;  z < (msec * 16);  z++ )
-		{
-		if ( inb_p (padapter->regStatCmd) & IDE_STATUS_DRQ )
-			return 0;
-		udelay (128);
-		}
-	return TRUE;
-	}
-/****************************************************************
- *	Name:	HardReset	:LOCAL
- *
- *	Description:	Wait for device ready for data transfer.
- *
- *	Parameters:		padapter - Pointer adapter data structure.
- *					pdev	 - Pointer to device.
- *					spigot	 - Spigot number.
- *
- *	Returns:		TRUE if drive does not assert DRQ in time.
- *
- ****************************************************************/
-static int HardReset (PADAPTER2220I padapter, POUR_DEVICE pdev, UCHAR spigot)
-	{
-	DEB (printk ("\npci2220i:RESET  spigot = %X  devices = %d, %d", spigot, pdev->deviceID[0], pdev->deviceID[1]));
-	mdelay (100);										// just wait 100 mSec to let drives flush	
-	SelectSpigot (padapter, spigot | SEL_IRQ_OFF);
-	
-	outb_p (0x0E, padapter->regAltStat);					// reset the suvivor
-	udelay (100);											// wait a little	
-	outb_p (0x08, padapter->regAltStat);					// clear the reset
-	udelay (100);
-
-	outb_p (0xA0, padapter->regLba24);						// select the master drive
-	if ( WaitReadyReset (padapter) )
-		{
-		DEB (printk ("\npci2220i: master not ready after reset"));
-		return TRUE;
-		}
-	outb_p (0xB0, padapter->regLba24);						// try the slave drive
-	if ( (inb_p (padapter->regStatCmd) & (IDE_STATUS_DRDY | IDE_STATUS_BUSY)) == IDE_STATUS_DRDY ) 
-		{
-		DEB (printk ("\nPCI2220I: initializing slave drive on spigot %X", spigot));
-		outb_p (SECTORSXFER, padapter->regSectCount);
-		WriteCommand (padapter, IDE_CMD_SET_MULTIPLE);	
-		if ( WaitReady (padapter) )
-			{
-			DEB (printk ("\npci2220i: slave not ready after set multiple"));
-			return TRUE;
-			}
-		}
-	
-	outb_p (0xA0, padapter->regLba24);				// select the drive
-	outb_p (SECTORSXFER, padapter->regSectCount);
-	WriteCommand (padapter, IDE_CMD_SET_MULTIPLE);	
-	if ( WaitReady (padapter) )
-		{
-		DEB (printk ("\npci2220i: master not ready after set multiple"));
-		return TRUE;
-		}
-	return FALSE;
-	}
-/****************************************************************
- *	Name:	AtapiReset	:LOCAL
- *
- *	Description:	Wait for device ready for data transfer.
- *
- *	Parameters:		padapter - Pointer adapter data structure.
- *					pdev	 - Pointer to device.
- *
- *	Returns:		TRUE if drive does not come ready.
- *
- ****************************************************************/
-static int AtapiReset (PADAPTER2220I padapter, POUR_DEVICE pdev)
-	{
-	SelectSpigot (padapter, pdev->spigot);
-	AtapiDevice (padapter, pdev->byte6);
-	AtapiCountLo (padapter, 0);
-	AtapiCountHi (padapter, 0);
-	WriteCommand (padapter, IDE_COMMAND_ATAPI_RESET);
-	udelay (125);
-	if ( AtapiWaitReady (padapter, 1000) )
-		return TRUE;
-	if ( inb_p (padapter->regStatCmd) || (inb_p (padapter->regLba8) != 0x14) || (inb_p (padapter->regLba16) != 0xEB) )
-		return TRUE;
-	return FALSE;
-	}
-/****************************************************************
- *	Name:	WalkScatGath	:LOCAL
- *
- *	Description:	Transfer data to/from scatter/gather buffers.
- *
- *	Parameters:		padapter - Pointer adapter data structure.
- *					datain   - TRUE if data read.
- *					length   - Number of bytes to transfer.
- *
- *	Returns:		Nothing.
- *
- ****************************************************************/
-static void WalkScatGath (PADAPTER2220I padapter, UCHAR datain, ULONG length)
-	{
-	ULONG	 count;
-	UCHAR	*buffer = padapter->kBuffer;
-
-	while ( length )
-		{
-		count = ( length > padapter->currentSgCount ) ? padapter->currentSgCount : length; 
-		
-		if ( datain )
-			memcpy (padapter->currentSgBuffer, buffer, count);
-		else
-			memcpy (buffer, padapter->currentSgBuffer, count);
-
-		padapter->currentSgCount -= count;
-		if ( !padapter->currentSgCount )
-			{
-			if ( padapter->nextSg < padapter->SCpnt->use_sg )
-				{
-				padapter->currentSgBuffer = ((struct scatterlist *)padapter->SCpnt->request_buffer)[padapter->nextSg].address;
-				padapter->currentSgCount = ((struct scatterlist *)padapter->SCpnt->request_buffer)[padapter->nextSg].length;
-				padapter->nextSg++;
-				}
-			}
-		else
-			padapter->currentSgBuffer += count;
-
-		length -= count;
-		buffer += count;
-		}
-	}
-/****************************************************************
- *	Name:	BusMaster	:LOCAL
- *
- *	Description:	Do a bus master I/O.
- *
- *	Parameters:		padapter - Pointer adapter data structure.
- *					datain	 - TRUE if data read.
- *					irq		 - TRUE if bus master interrupt expected.
- *
- *	Returns:		Nothing.
- *
- ****************************************************************/
-static void BusMaster (PADAPTER2220I padapter, UCHAR datain, UCHAR irq)
-	{
-	ULONG zl;
-	
-	zl = ( padapter->sectorCount > MAX_BUS_MASTER_BLOCKS ) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
-	padapter->sectorCount -= zl;
-	zl *= (ULONG)BYTES_PER_SECTOR;
-
-	if ( datain )
-		{
-		padapter->readCount = zl;
-		outb_p (8, padapter->regDmaDesc);							// read operation
-		if ( padapter->bigD )
-			{
-			if ( irq && !padapter->sectorCount )
-				outb_p (0x0C, padapter->regDmaMode);				// interrupt on
-			else
-				outb_p (0x08, padapter->regDmaMode);				// no interrupt
-			}
-		else 
-			{
-			if ( irq && !padapter->sectorCount )
-				outb_p (0x05, padapter->regDmaMode);				// interrupt on
-			else
-				outb_p (0x01, padapter->regDmaMode);				// no interrupt
-			}
-		}
-	else
-		{
-		outb_p (0x00, padapter->regDmaDesc);						// write operation
-		if ( padapter->bigD )
-			outb_p (0x08, padapter->regDmaMode);					// no interrupt						
-		else
-			outb_p (0x01, padapter->regDmaMode);					// no interrupt
-		WalkScatGath (padapter, FALSE, zl);	
-		}
-	
-	outl (padapter->timingAddress, padapter->regDmaAddrLoc);
-	outl (padapter->kBufferDma, padapter->regDmaAddrPci);
-	outl (zl, padapter->regDmaCount);
-	outb_p (0x03, padapter->regDmaCmdStat);							// kick the DMA engine in gear
-	}
-/****************************************************************
- *	Name:	AtapiBusMaster	:LOCAL
- *
- *	Description:	Do a bus master I/O.
- *
- *	Parameters:		padapter - Pointer adapter data structure.
- *					datain	 - TRUE if data read.
- *					length	 - Number of bytes to transfer.
- *
- *	Returns:		Nothing.
- *
- ****************************************************************/
-static void AtapiBusMaster (PADAPTER2220I padapter, UCHAR datain, ULONG length)
-	{
-	outl (padapter->timingAddress, padapter->regDmaAddrLoc);
-	outl (padapter->kBufferDma, padapter->regDmaAddrPci);
-	outl (length, padapter->regDmaCount);
-	if ( datain )
-		{
-		if ( padapter->readCount )
-				WalkScatGath (padapter, TRUE, padapter->readCount);
-		outb_p (0x08, padapter->regDmaDesc);						// read operation
-		outb_p (0x08, padapter->regDmaMode);						// no interrupt
-		padapter->readCount = length;
-		}
-	else
-		{
-		outb_p (0x00, padapter->regDmaDesc);						// write operation
-		outb_p (0x08, padapter->regDmaMode);						// no interrupt						
-		if ( !padapter->atapiSpecial )
-			WalkScatGath (padapter, FALSE, length);	
-		}
-	outb_p (0x03, padapter->regDmaCmdStat);							// kick the DMA engine in gear
-	}
-/****************************************************************
- *	Name:	WriteData	:LOCAL
- *
- *	Description:	Write data to device.
- *
- *	Parameters:		padapter - Pointer adapter data structure.
- *
- *	Returns:		TRUE if drive does not assert DRQ in time.
- *
- ****************************************************************/
-static int WriteData (PADAPTER2220I padapter)
-	{
-	ULONG	zl;
-	
-	if ( !WaitDrq (padapter) )
-		{
-		if ( padapter->timingPIO )
-			{
-			zl = (padapter->sectorCount > MAX_BUS_MASTER_BLOCKS) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
-			WalkScatGath (padapter, FALSE, zl * BYTES_PER_SECTOR);
-			outsw (padapter->regData, padapter->kBuffer, zl * (BYTES_PER_SECTOR / 2));
-			padapter->sectorCount -= zl;
-			}
-		else
-			BusMaster (padapter, 0, 0);
-		return 0;
-		}
-	padapter->cmd = 0;												// null out the command byte
-	return 1;
-	}
-/****************************************************************
- *	Name:	WriteDataBoth	:LOCAL
- *
- *	Description:	Write data to device.
- *
- *	Parameters:		padapter - Pointer to adapter structure.
- *					pdev	 - Pointer to device structure
- *
- *	Returns:		Index + 1 of drive not failed or zero for OK.
- *
- ****************************************************************/
-static int WriteDataBoth (PADAPTER2220I padapter, POUR_DEVICE pdev)
-	{
-	ULONG	zl;
-	UCHAR	status0, status1;
-
-	SelectSpigot (padapter, pdev->spigots[0]);
-	status0 = WaitDrq (padapter);
-	if ( !status0 )
-		{
-		SelectSpigot (padapter, pdev->spigots[1]);
-		status1 = WaitDrq (padapter);
-		if ( !status1 )
-			{
-			SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1] | padapter->bigD);
-			if ( padapter->timingPIO )
-				{
-				zl = (padapter->sectorCount > MAX_BUS_MASTER_BLOCKS) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
-				WalkScatGath (padapter, FALSE, zl * BYTES_PER_SECTOR);
-				outsw (padapter->regData, padapter->kBuffer, zl * (BYTES_PER_SECTOR / 2));
-				padapter->sectorCount -= zl;
-				}
-			else
-				BusMaster (padapter, 0, 0);
-			return 0;
-			}
-		}
-	padapter->cmd = 0;												// null out the command byte
-	if ( status0 )
-		return 2;
-	return 1;
-	}
-/****************************************************************
- *	Name:	IdeCmd	:LOCAL
- *
- *	Description:	Process an IDE command.
- *
- *	Parameters:		padapter - Pointer adapter data structure.
- *					pdev	 - Pointer to device.
- *
- *	Returns:		Zero if no error or status register contents on error.
- *
- ****************************************************************/
-static UCHAR IdeCmd (PADAPTER2220I padapter, POUR_DEVICE pdev)
-	{
-	UCHAR	status;
-
-	SelectSpigot (padapter, pdev->spigot | padapter->bigD);							// select the spigot
-	outb_p (pdev->byte6 | ((UCHAR *)(&padapter->startSector))[3], padapter->regLba24);			// select the drive
-	status = WaitReady (padapter);
-	if ( !status )
-		{
-		outb_p (padapter->sectorCount, padapter->regSectCount);
-		outb_p (((UCHAR *)(&padapter->startSector))[0], padapter->regLba0);
-		outb_p (((UCHAR *)(&padapter->startSector))[1], padapter->regLba8);
-		outb_p (((UCHAR *)(&padapter->startSector))[2], padapter->regLba16);
-		padapter->expectingIRQ = TRUE;
-		WriteCommand (padapter, padapter->cmd);
-		return 0;
-		}
-
-	padapter->cmd = 0;									// null out the command byte
-	return status;
-	}
-/****************************************************************
- *	Name:	IdeCmdBoth	:LOCAL
- *
- *	Description:	Process an IDE command to both drivers.
- *
- *	Parameters:		padapter - Pointer adapter data structure.
- *					pdev	 - Pointer to device structure
- *
- *	Returns:		Index + 1 of drive not failed or zero for OK.
- *
- ****************************************************************/
-static UCHAR IdeCmdBoth (PADAPTER2220I padapter, POUR_DEVICE pdev)
-	{
-	UCHAR	status0;
-	UCHAR	status1;
-
-	SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1]);								// select the spigots
-	outb_p (padapter->pdev->byte6 | ((UCHAR *)(&padapter->startSector))[3], padapter->regLba24);// select the drive
-	SelectSpigot (padapter, pdev->spigots[0]);
-	status0 = WaitReady (padapter);
-	if ( !status0 )
-		{
-		SelectSpigot (padapter, pdev->spigots[1]);
-		status1 = WaitReady (padapter);
-		if ( !status1 )
-			{
-			SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1] | padapter->bigD);
-			outb_p (padapter->sectorCount, padapter->regSectCount);
-			outb_p (((UCHAR *)(&padapter->startSector))[0], padapter->regLba0);
-			outb_p (((UCHAR *)(&padapter->startSector))[1], padapter->regLba8);
-			outb_p (((UCHAR *)(&padapter->startSector))[2], padapter->regLba16);
-			padapter->expectingIRQ = TRUE;
-			WriteCommand (padapter, padapter->cmd);
-			return 0;
-			}
-		}
-	padapter->cmd = 0;									// null out the command byte
-	if ( status0 )
-		return 2;
-	return 1;
-	}
-/****************************************************************
- *	Name:	OpDone	:LOCAL
- *
- *	Description:	Complete an operatoin done sequence.
- *
- *	Parameters:		padapter - Pointer to host data block.
- *					spigot	 - Spigot select code.
- *					device	 - Device byte code.
- *
- *	Returns:		Nothing.
- *
- ****************************************************************/
-static void OpDone (PADAPTER2220I padapter, ULONG result)
-	{
-	Scsi_Cmnd	   *SCpnt = padapter->SCpnt;
-	
-	if ( padapter->reconPhase )
-		{
-		padapter->reconPhase = 0;
-		if ( padapter->SCpnt )
-			{
-			Pci2220i_QueueCommand (SCpnt, SCpnt->scsi_done);
-			}
-		else
-			{
-			if ( padapter->reconOn )
-				{
-				ReconTimerExpiry ((unsigned long)padapter);
-				}
-			}
-		}
-	else
-		{
-		padapter->cmd = 0;
-		padapter->SCpnt = NULL;	
-		padapter->pdev = NULL;
-		SCpnt->result = result;
-		SCpnt->scsi_done (SCpnt);
-		if ( padapter->reconOn && !padapter->reconTimer.data )
-			{
-			padapter->reconTimer.expires = jiffies + (HZ / 4);	// start in 1/4 second
-			padapter->reconTimer.data = (unsigned long)padapter;
-			add_timer (&padapter->reconTimer);
-			}
-		}
-	}
-/****************************************************************
- *	Name:	InlineIdentify	:LOCAL
- *
- *	Description:	Do an intline inquiry on a drive.
- *
- *	Parameters:		padapter - Pointer to host data block.
- *					spigot	 - Spigot select code.
- *					device	 - Device byte code.
- *
- *	Returns:		Last addressable sector or zero if none.
- *
- ****************************************************************/
-static ULONG InlineIdentify (PADAPTER2220I padapter, UCHAR spigot, UCHAR device)
-	{
-	PIDENTIFY_DATA	pid = (PIDENTIFY_DATA)padapter->kBuffer;
-
-	SelectSpigot (padapter, spigot | SEL_IRQ_OFF);					// select the spigot
-	outb_p ((device << 4) | 0xA0, padapter->regLba24);				// select the drive
-	if ( WaitReady (padapter) )
-		return 0;
-	WriteCommand (padapter, IDE_COMMAND_IDENTIFY);	
-	if ( WaitDrq (padapter) )
-		return 0;
-	insw (padapter->regData, padapter->kBuffer, sizeof (IDENTIFY_DATA) >> 1);
-	return (pid->LBATotalSectors - 1);
-	}
-/****************************************************************
- *	Name:	AtapiIdentify	:LOCAL
- *
- *	Description:	Do an intline inquiry on a drive.
- *
- *	Parameters:		padapter - Pointer to host data block.
- *					pdev	 - Pointer to device table.
- *
- *	Returns:		TRUE on error.
- *
- ****************************************************************/
-static ULONG AtapiIdentify (PADAPTER2220I padapter, POUR_DEVICE pdev)
-	{
-	ATAPI_GENERAL_0		ag0;
-	USHORT				zs;
-	int					z;
-
-	AtapiDevice (padapter, pdev->byte6);	
-	WriteCommand (padapter, IDE_COMMAND_ATAPI_IDENTIFY);	
-	if ( AtapiWaitDrq (padapter, 3000) )
-		return TRUE;
-
-	*(USHORT *)&ag0 = inw_p (padapter->regData);
-	for ( z = 0;  z < 255;  z++ )
-		zs = inw_p (padapter->regData);
-
-	if ( ag0.ProtocolType == 2 )
-		{
-		if ( ag0.CmdDrqType == 1 )
-			pdev->cmdDrqInt = TRUE;
-		switch ( ag0.CmdPacketSize )
-			{
-			case 0:
-				pdev->packet = 6;
-				break;
-			case 1:
-				pdev->packet = 8;
-				break;
-			default:
-				pdev->packet = 6;
-				break;
-			}
-		return FALSE;
-		}
-	return TRUE;
-	}
-/****************************************************************
- *	Name:	Atapi2Scsi
- *
- *	Description:	Convert ATAPI data to SCSI data.
- *
- *	Parameters:		padapter - Pointer adapter data structure.
- *					SCpnt	 - Pointer to SCSI command structure.
- *
- *	Returns:		Nothing.
- *
- ****************************************************************/
-void Atapi2Scsi (PADAPTER2220I padapter, Scsi_Cmnd *SCpnt)
-	{
-	UCHAR	*buff = padapter->currentSgBuffer;
- 
-	switch ( SCpnt->cmnd[0] )
-		{
-		case SCSIOP_MODE_SENSE:
-			buff[0] = padapter->kBuffer[1];
-			buff[1] = padapter->kBuffer[2];
-			buff[2] = padapter->kBuffer[3];
-			buff[3] = padapter->kBuffer[7];
-			memcpy (&buff[4], &padapter->kBuffer[8], padapter->atapiCdb[8] - 8);
-			break;
-		case SCSIOP_INQUIRY:
-			padapter->kBuffer[2] = 2;
-			memcpy (buff, padapter->kBuffer, padapter->currentSgCount);
-			break;		
-		default:
-			if ( padapter->readCount )
-				WalkScatGath (padapter, TRUE, padapter->readCount);
-			break;
-		}
-	}
-/****************************************************************
- *	Name:	Scsi2Atapi
- *
- *	Description:	Convert SCSI packet command to Atapi packet command.
- *
- *	Parameters:		padapter - Pointer adapter data structure.
- *					SCpnt	 - Pointer to SCSI command structure.
- *
- *	Returns:		Nothing.
- *
- ****************************************************************/
-static void Scsi2Atapi (PADAPTER2220I padapter, Scsi_Cmnd *SCpnt)
-	{
-	UCHAR	*cdb = SCpnt->cmnd;
-	UCHAR	*buff = padapter->currentSgBuffer;
-
-	switch (cdb[0]) 
-		{
-		case SCSIOP_READ6:
-            padapter->atapiCdb[0] = SCSIOP_READ;
-			padapter->atapiCdb[1] = cdb[1] & 0xE0;
-            padapter->atapiCdb[3] = cdb[1] & 0x1F;
-			padapter->atapiCdb[4] = cdb[2];
-			padapter->atapiCdb[5] = cdb[3];
-			padapter->atapiCdb[8] = cdb[4];
-			padapter->atapiCdb[9] = cdb[5];
-			break;
-		case SCSIOP_WRITE6:
-            padapter->atapiCdb[0] = SCSIOP_WRITE;
-			padapter->atapiCdb[1] = cdb[1] & 0xE0;
-            padapter->atapiCdb[3] = cdb[1] & 0x1F;
-			padapter->atapiCdb[4] = cdb[2];
-			padapter->atapiCdb[5] = cdb[3];
-			padapter->atapiCdb[8] = cdb[4];
-			padapter->atapiCdb[9] = cdb[5];
-			break;
-        case SCSIOP_MODE_SENSE: 
-            padapter->atapiCdb[0] = SCSIOP_MODE_SENSE10;
-			padapter->atapiCdb[2] = cdb[2];
-			padapter->atapiCdb[8] = cdb[4] + 4;
-            break;
-
-        case SCSIOP_MODE_SELECT: 
-			padapter->atapiSpecial = TRUE;
-			padapter->atapiCdb[0] = SCSIOP_MODE_SELECT10;
-			padapter->atapiCdb[1] = cdb[1] | 0x10;
-			memcpy (padapter->kBuffer, buff, 4);
-			padapter->kBuffer[4] = padapter->kBuffer[5] = 0;
-			padapter->kBuffer[6] = padapter->kBuffer[7] = 0;
-			memcpy (&padapter->kBuffer[8], &buff[4], cdb[4] - 4);
-			padapter->atapiCdb[8] = cdb[4] + 4;
-			break;
-	    }
-	}
-/****************************************************************
- *	Name:	AtapiSendCdb
- *
- *	Description:	Send the CDB packet to the device.
- *
- *	Parameters:		padapter - Pointer adapter data structure.
- *					pdev	 - Pointer to device.
- *					cdb		 - Pointer to 16 byte SCSI cdb.
- *
- *	Returns:		Nothing.
- *
- ****************************************************************/
-static void AtapiSendCdb (PADAPTER2220I padapter, POUR_DEVICE pdev, CHAR *cdb)
-	{
-	DEB (printk ("\nPCI2242I: CDB: %X %X %X %X %X %X %X %X %X %X %X %X", cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]));
-	outsw (padapter->regData, cdb, pdev->packet);
-	}
-/****************************************************************
- *	Name:	AtapiRequestSense
- *
- *	Description:	Send the CDB packet to the device.
- *
- *	Parameters:		padapter - Pointer adapter data structure.
- *					pdev	 - Pointer to device.
- *					SCpnt	 - Pointer to SCSI command structure.
- *					pass	 - If true then this is the second pass to send cdb.
- *
- *	Returns:		TRUE on error.
- *
- ****************************************************************/
-static int AtapiRequestSense (PADAPTER2220I padapter, POUR_DEVICE pdev, Scsi_Cmnd *SCpnt, UCHAR pass)
-	{
-	UCHAR	cdb[16] = {SCSIOP_REQUEST_SENSE,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0};		
-	
-	DEB (printk ("\nPCI2242I: AUTO REQUEST SENSE"));
-	cdb[4] = (UCHAR)(sizeof (SCpnt->sense_buffer));
-	if ( !pass )
-		{
-		padapter->reqSense = TRUE;
-	 	AtapiCountLo (padapter, cdb[4]);						
-		AtapiCountHi (padapter, 0);						
-		outb_p (0, padapter->regError);						
-		WriteCommand (padapter, IDE_COMMAND_ATAPI_PACKET);
-		if ( pdev->cmdDrqInt )
-			return FALSE;
-
-		if ( AtapiWaitDrq (padapter, 500) )
-			return TRUE;
-		}
-	AtapiSendCdb (padapter, pdev, cdb);	
-	return FALSE;
-	}
-/****************************************************************
- *	Name:	InlineReadSignature	:LOCAL
- *
- *	Description:	Do an inline read RAID sigature.
- *
- *	Parameters:		padapter - Pointer adapter data structure.
- *					pdev	 - Pointer to device.
- *					index	 - index of data to read.
- *
- *	Returns:		Zero if no error or status register contents on error.
- *
- ****************************************************************/
-static UCHAR InlineReadSignature (PADAPTER2220I padapter, POUR_DEVICE pdev, int index)
-	{
-	UCHAR	status;
-	ULONG	zl = pdev->lastsectorlba[index];
-
-	SelectSpigot (padapter, pdev->spigots[index] | SEL_IRQ_OFF);	// select the spigot without interrupts
-	outb_p (pdev->byte6 | ((UCHAR *)&zl)[3], padapter->regLba24);		
-	status = WaitReady (padapter);
-	if ( !status )
-		{
-		outb_p (((UCHAR *)&zl)[2], padapter->regLba16);
-		outb_p (((UCHAR *)&zl)[1], padapter->regLba8); 
-		outb_p (((UCHAR *)&zl)[0], padapter->regLba0);
-		outb_p (1, padapter->regSectCount);
-		WriteCommand (padapter, IDE_COMMAND_READ);
-		status = WaitDrq (padapter);
-		if ( !status )
-			{
-			insw (padapter->regData, padapter->kBuffer, BYTES_PER_SECTOR / 2);
-			((ULONG *)(&pdev->DiskMirror[index]))[0] = ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[0];
-			((ULONG *)(&pdev->DiskMirror[index]))[1] = ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[1];
-			// some drives assert DRQ before IRQ so let's make sure we clear the IRQ
-			WaitReady (padapter);
-			return 0;			
-			}
-		}
-	return status;
-	}
-/****************************************************************
- *	Name:	DecodeError	:LOCAL
- *
- *	Description:	Decode and process device errors.
- *
- *	Parameters:		padapter - Pointer to adapter data.
- *					status - Status register code.
- *
- *	Returns:		The driver status code.
- *
- ****************************************************************/
-static ULONG DecodeError (PADAPTER2220I	padapter, UCHAR status)
-	{
-	UCHAR			error;
-
-	padapter->expectingIRQ = 0;
-	if ( status & IDE_STATUS_WRITE_FAULT )
-		{
-		return DID_PARITY << 16;
-		}
-	if ( status & IDE_STATUS_BUSY )
-		return DID_BUS_BUSY << 16;
-
-	error = inb_p (padapter->regError);
-	DEB(printk ("\npci2220i error register: %x", error));
-	switch ( error )
-		{
-		case IDE_ERROR_AMNF:
-		case IDE_ERROR_TKONF:
-		case IDE_ERROR_ABRT:
-		case IDE_ERROR_IDFN:
-		case IDE_ERROR_UNC:
-		case IDE_ERROR_BBK:
-		default:
-			return DID_ERROR << 16;
-		}
-	return DID_ERROR << 16;
-	}
-/****************************************************************
- *	Name:	StartTimer	:LOCAL
- *
- *	Description:	Start the timer.
- *
- *	Parameters:		ipadapter - Pointer adapter data structure.
- *
- *	Returns:		Nothing.
- *
- ****************************************************************/
-static void StartTimer (PADAPTER2220I padapter)
-	{
-	padapter->timer.expires = jiffies + TIMEOUT_DATA;
-	add_timer (&padapter->timer);
-	}
-/****************************************************************
- *	Name:	WriteSignature	:LOCAL
- *
- *	Description:	Start the timer.
- *
- *	Parameters:		padapter - Pointer adapter data structure.
- *					pdev	 - Pointer to our device.
- *					spigot	 - Selected spigot.
- *					index	 - index of mirror signature on device.
- *
- *	Returns:		TRUE on any error.
- *
- ****************************************************************/
-static int WriteSignature (PADAPTER2220I padapter, POUR_DEVICE pdev, UCHAR spigot, int index)
-	{
-	ULONG	zl;
-
-	SelectSpigot (padapter, spigot);
-	zl = pdev->lastsectorlba[index];
-	outb_p (pdev->byte6 | ((UCHAR *)&zl)[3], padapter->regLba24);		
-	outb_p (((UCHAR *)&zl)[2], padapter->regLba16);
-	outb_p (((UCHAR *)&zl)[1], padapter->regLba8);
-	outb_p (((UCHAR *)&zl)[0], padapter->regLba0);
-	outb_p (1, padapter->regSectCount);
-
-	WriteCommand (padapter, IDE_COMMAND_WRITE);	
-	if ( WaitDrq (padapter) )
-		return TRUE;
-	StartTimer (padapter);	
-	padapter->expectingIRQ = TRUE;
-	
-	((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[0] = ((ULONG *)(&pdev->DiskMirror[index]))[0];
-	((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[1] = ((ULONG *)(&pdev->DiskMirror[index]))[1];
-	outsw (padapter->regData, padapter->kBuffer, BYTES_PER_SECTOR / 2);
-	return FALSE;
-	}
-/*******************************************************************************************************
- *	Name:			InitFailover
- *
- *	Description:	This is the beginning of the failover routine
- *
- *	Parameters:		SCpnt	 - Pointer to SCSI command structure.
- *					padapter - Pointer adapter data structure.
- *					pdev	 - Pointer to our device.
- *	
- *	Returns:		TRUE on error.
- *
- ******************************************************************************************************/
-static int InitFailover (PADAPTER2220I padapter, POUR_DEVICE pdev)
-	{
-	UCHAR	spigot;
-	
-	DEB (printk ("\npci2220i:  Initialize failover process - survivor = %d", pdev->deviceID[padapter->survivor]));
-	pdev->raid = FALSE;									//initializes system for non raid mode
-	pdev->reconOn = FALSE;
-	spigot = pdev->spigots[padapter->survivor];	
-
-	if ( pdev->DiskMirror[padapter->survivor].status & UCBF_REBUILD )
-		{
-		DEB (printk ("\n         failed, is survivor"));
-		return (TRUE); 
-		}
-
-	if ( HardReset (padapter, pdev, spigot) )
-		{
-		DEB (printk ("\n         failed, reset"));
-		return TRUE;
-		}
-
-	Alarm (padapter, pdev->deviceID[padapter->survivor ^ 1]);
-	pdev->DiskMirror[padapter->survivor].status = UCBF_MIRRORED | UCBF_SURVIVOR;	//clear present status
-	
-	if ( WriteSignature (padapter, pdev, spigot, padapter->survivor) )
-		{
-		DEB (printk ("\n         failed, write signature"));
-		return TRUE;
-		}
-	padapter->failinprog = TRUE;
-	return FALSE;
-	}
-/****************************************************************
- *	Name:	TimerExpiry	:LOCAL
- *
- *	Description:	Timer expiry routine.
- *
- *	Parameters:		data - Pointer adapter data structure.
- *
- *	Returns:		Nothing.
- *
- ****************************************************************/
-static void TimerExpiry (unsigned long data)
-	{
-	PADAPTER2220I	padapter = (PADAPTER2220I)data;
-	struct Scsi_Host *host = padapter->SCpnt->device->host;
-	POUR_DEVICE		pdev = padapter->pdev;
-	UCHAR			status = IDE_STATUS_BUSY;
-	UCHAR			temp, temp1;
-    unsigned long		flags;
-
-    /*
-     * Disable interrupts, if they aren't already disabled and acquire
-     * the I/O spinlock.
-     */
-    spin_lock_irqsave (host->host_lock, flags);
-	DEB (printk ("\nPCI2220I: Timeout expired "));
-
-	if ( padapter->failinprog )
-		{
-		DEB (printk ("in failover process"));
-		OpDone (padapter, DecodeError (padapter, inb_p (padapter->regStatCmd)));
-		goto timerExpiryDone;
-		}
-	
-	while ( padapter->reconPhase )
-		{
-		DEB (printk ("in recon phase %X", padapter->reconPhase));
-		switch ( padapter->reconPhase )
-			{
-			case RECON_PHASE_MARKING:
-			case RECON_PHASE_LAST:
-				padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 1 : 0;
-				DEB (printk ("\npci2220i: FAILURE 1"));
-				if ( InitFailover (padapter, pdev) )
-					OpDone (padapter, DID_ERROR << 16);
-				goto timerExpiryDone;
-			
-			case RECON_PHASE_READY:
-				OpDone (padapter, DID_ERROR << 16);
-				goto timerExpiryDone;
-
-			case RECON_PHASE_COPY:
-				padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
-				DEB (printk ("\npci2220i: FAILURE 2"));
-				DEB (printk ("\n       spig/stat = %X", inb_p (padapter->regStatSel));
-				if ( InitFailover (padapter, pdev) )
-					OpDone (padapter, DID_ERROR << 16);
-				goto timerExpiryDone;
-
-			case RECON_PHASE_UPDATE:
-				padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
-				DEB (printk ("\npci2220i: FAILURE 3")));
-				if ( InitFailover (padapter, pdev) )
-					OpDone (padapter, DID_ERROR << 16);
-				goto timerExpiryDone;
-
-			case RECON_PHASE_END:
-				padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
-				DEB (printk ("\npci2220i: FAILURE 4"));
-				if ( InitFailover (padapter, pdev) )
-					OpDone (padapter, DID_ERROR << 16);
-				goto timerExpiryDone;
-			
-			default:
-				goto timerExpiryDone;
-			}
-		}
-	
-	while ( padapter->cmd )
-		{
-		outb_p (0x08, padapter->regDmaCmdStat);					// cancel interrupt from DMA engine
-		if ( pdev->raid )
-			{
-			if ( padapter->cmd == WRITE_CMD )
-				{
-				DEB (printk ("in RAID write operation"));
-				temp = ( pdev->spigot & (SEL_1 | SEL_2) ) ? SEL_1 : SEL_3;
-				if ( inb_p (padapter->regStatSel) & temp )
-					{
-					DEB (printk ("\npci2220i: Determined A OK"));
-					SelectSpigot (padapter, temp | SEL_IRQ_OFF); // Masking the interrupt during spigot select
-					temp = inb_p (padapter->regStatCmd);
-					}
-				else
-					temp = IDE_STATUS_BUSY;
-
-				temp1 = ( pdev->spigot & (SEL_1 | SEL_2) ) ? SEL_2 : SEL_4;
-				if ( inb (padapter->regStatSel) & temp1 )
-					{
-					DEB (printk ("\npci2220i: Determined B OK"));
-					SelectSpigot (padapter, temp1 | SEL_IRQ_OFF); // Masking the interrupt during spigot select
-					temp1 = inb_p (padapter->regStatCmd);
-					}
-				else
-					temp1 = IDE_STATUS_BUSY;
-			
-				if ( (temp & IDE_STATUS_BUSY) || (temp1 & IDE_STATUS_BUSY) )
-					{
-					DEB (printk ("\npci2220i: Status A: %X   B: %X", temp & 0xFF, temp1 & 0xFF));
-	 				if ( (temp & IDE_STATUS_BUSY) && (temp1 & IDE_STATUS_BUSY) ) 
-						{
-						status = temp;
-						break;
-						}		
-					else	
-						{
-						if ( temp & IDE_STATUS_BUSY )
-							padapter->survivor = 1;
-						else
-							padapter->survivor = 0;
-						if ( InitFailover (padapter, pdev) )
-							{
-							status = inb_p (padapter->regStatCmd);
-							break;
-							}
-						goto timerExpiryDone;
-						}
-					}
-				}
-			else
-				{
-				DEB (printk ("in RAID read operation"));
-				padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
-				DEB (printk ("\npci2220i: FAILURE 6"));
-				if ( InitFailover (padapter, pdev) )
-					{
-					status = inb_p (padapter->regStatCmd);
-					break;
-					}
-				goto timerExpiryDone;
-				}
-			}
-		else
-			{
-			DEB (printk ("in I/O operation"));
-			status = inb_p (padapter->regStatCmd);
-			}
-		break;
-		}
-	
-	OpDone (padapter, DecodeError (padapter, status));
-
-timerExpiryDone:;
-    /*
-     * Release the I/O spinlock and restore the original flags
-     * which will enable interrupts if and only if they were
-     * enabled on entry.
-     */
-    spin_unlock_irqrestore (host->host_lock, flags);
-	}
-/****************************************************************
- *	Name:			SetReconstruct	:LOCAL
- *
- *	Description:	Set the reconstruct up.
- *
- *	Parameters:		pdev	- Pointer to device structure.
- *					index	- Mirror index number.
- *
- *	Returns:		Number of sectors on new disk required.
- *
- ****************************************************************/
-static LONG SetReconstruct (POUR_DEVICE pdev, int index)
-	{
-	pdev->DiskMirror[index].status = UCBF_MIRRORED;							// setup the flags
-	pdev->DiskMirror[index ^ 1].status = UCBF_MIRRORED | UCBF_REBUILD;
-	pdev->DiskMirror[index ^ 1].reconstructPoint = 0;						// start the reconstruct
-	pdev->reconCount = 1990;												// mark target drive early
-	return pdev->DiskMirror[index].reconstructPoint;
-	}
-/****************************************************************
- *	Name:	ReconTimerExpiry	:LOCAL
- *
- *	Description:	Reconstruct timer expiry routine.
- *
- *	Parameters:		data - Pointer adapter data structure.
- *
- *	Returns:		Nothing.
- *
- ****************************************************************/
-static void ReconTimerExpiry (unsigned long data)
-	{
-	PADAPTER2220I	padapter = (PADAPTER2220I)data;
-	struct Scsi_Host *host = padapter->SCpnt->device->host;
-	POUR_DEVICE		pdev;
-	ULONG			testsize = 0;
-	PIDENTIFY_DATA	pid;
-	USHORT			minmode;
-	ULONG			zl;
-	UCHAR			zc;
-	USHORT			z;
-    unsigned long	flags;
-
-    /*
-     * Disable interrupts, if they aren't already disabled and acquire
-     * the I/O spinlock.
-     */
-    spin_lock_irqsave(host->host_lock, flags);
-
-	if ( padapter->SCpnt )
-		goto reconTimerExpiry;
-
-	padapter->reconTimer.data = 0;
-	for ( z = padapter->devInReconIndex + 1;  z < BIGD_MAXDRIVES;  z++ )
-		{
-		if ( padapter->device[z].reconOn )
-			break;
-		}
-	if ( z < BIGD_MAXDRIVES )
-		pdev = &padapter->device[z];
-	else
-		{
-		for ( z = 0;  z < BIGD_MAXDRIVES;  z++ )
-			{
-			if ( padapter->device[z].reconOn )
-				break;
-			}
-		if ( z < BIGD_MAXDRIVES )
-			pdev = &padapter->device[z];
-		else
-			{
-			padapter->reconOn = FALSE;
-			goto reconTimerExpiry;
-			}
-		}
-
-	padapter->devInReconIndex = z;
-	pid = (PIDENTIFY_DATA)padapter->kBuffer;
-	padapter->pdev = pdev;
-	if ( pdev->reconIsStarting )
-		{
-		pdev->reconIsStarting = FALSE;
-		pdev->reconOn = FALSE;
-
-		while ( (pdev->DiskMirror[0].signature == SIGNATURE) && (pdev->DiskMirror[1].signature == SIGNATURE) &&
-			 (pdev->DiskMirror[0].pairIdentifier == (pdev->DiskMirror[1].pairIdentifier ^ 1)) )
-			{
-			if ( (pdev->DiskMirror[0].status & UCBF_MATCHED) && (pdev->DiskMirror[1].status & UCBF_MATCHED) )
-				break;
-
-			if ( pdev->DiskMirror[0].status & UCBF_SURVIVOR )				// is first drive survivor?
-				testsize = SetReconstruct (pdev, 0);
-			else
-				if ( pdev->DiskMirror[1].status & UCBF_SURVIVOR )			// is second drive survivor?
-					testsize = SetReconstruct (pdev, 1);
-
-			if ( (pdev->DiskMirror[0].status & UCBF_REBUILD) || (pdev->DiskMirror[1].status & UCBF_REBUILD) )
-				{
-				if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
-					pdev->mirrorRecon = 0;
-				else
-					pdev->mirrorRecon = 1;
-				pdev->reconOn = TRUE;
-				}
-			break;
-			}
-
-		if ( !pdev->reconOn )
-			goto reconTimerExpiry;
-
-		if ( padapter->bigD )
-			{
-			padapter->failRegister = 0;
-			outb_p (~padapter->failRegister, padapter->regFail);
-			}
-		else
-			{
-			zc = ((inb_p (padapter->regStatSel) >> 3) | inb_p (padapter->regStatSel)) & 0x83;		// mute the alarm
-			outb_p (0xFF, padapter->regFail);
-			}
-
-		while ( 1 )
-			{
-			DEB (printk ("\npci2220i: hard reset issue"));
-			if ( HardReset (padapter, pdev, pdev->spigots[pdev->mirrorRecon]) )
-				{
-				DEB (printk ("\npci2220i: sub 1"));
-				break;
-				}
-
-			pdev->lastsectorlba[pdev->mirrorRecon] = InlineIdentify (padapter, pdev->spigots[pdev->mirrorRecon], pdev->deviceID[pdev->mirrorRecon] & 1);
-
-			if ( pdev->lastsectorlba[pdev->mirrorRecon] < testsize )
-				{
-				DEB (printk ("\npci2220i: sub 2 %ld %ld", pdev->lastsectorlba[pdev->mirrorRecon], testsize));
-				break;
-				}
-
-	        // test LBA and multiper sector transfer compatibility
-			if (!pid->SupportLBA || (pid->NumSectorsPerInt < SECTORSXFER) || !pid->Valid_64_70 )
-				{
-				DEB (printk ("\npci2220i: sub 3"));
-				break;
-				}
-
-	        // test PIO/bus matering mode compatibility
-			if ( (pid->MinPIOCycleWithoutFlow > 240) && !pid->SupportIORDYDisable && !padapter->timingPIO )
-				{
-				DEB (printk ("\npci2220i: sub 4"));
-				break;
-				}
-
-			if ( pid->MinPIOCycleWithoutFlow <= 120 )	// setup timing mode of drive
-				minmode = 5;
-			else
-				{
-				if ( pid->MinPIOCylceWithFlow <= 150 )
-					minmode = 4;
-				else
-					{
-					if ( pid->MinPIOCylceWithFlow <= 180 )
-						minmode = 3;
-					else
-						{
-						if ( pid->MinPIOCylceWithFlow <= 240 )
-							minmode = 2;
-						else
-							{
-							DEB (printk ("\npci2220i: sub 5"));
-							break;
-							}
-						}
-					}
-				}
-
-			if ( padapter->timingMode > minmode )									// set minimum timing mode
-				padapter->timingMode = minmode;
-			if ( padapter->timingMode >= 2 )
-				padapter->timingAddress	= ModeArray[padapter->timingMode - 2];
-			else
-				padapter->timingPIO = TRUE;
-
-			padapter->reconOn = TRUE;
-			break;
-			}
-
-		if ( !pdev->reconOn )
-			{		
-			padapter->survivor = pdev->mirrorRecon ^ 1;
-			padapter->reconPhase = RECON_PHASE_FAILOVER;
-			DEB (printk ("\npci2220i: FAILURE 7"));
-			InitFailover (padapter, pdev);
-			goto reconTimerExpiry;
-			}
-
-		pdev->raid = TRUE;
-	
-		if ( WriteSignature (padapter, pdev, pdev->spigot, pdev->mirrorRecon ^ 1) )
-			goto reconTimerExpiry;
-		padapter->reconPhase = RECON_PHASE_MARKING;
-		goto reconTimerExpiry;
-		}
-
-	//**********************************
-	// reconstruct copy starts here	
-	//**********************************
-	if ( pdev->reconCount++ > 2000 )
-		{
-		pdev->reconCount = 0;
-		if ( WriteSignature (padapter, pdev, pdev->spigots[pdev->mirrorRecon], pdev->mirrorRecon) )
-			{
-			padapter->survivor = pdev->mirrorRecon ^ 1;
-			padapter->reconPhase = RECON_PHASE_FAILOVER;
-			DEB (printk ("\npci2220i: FAILURE 8"));
-			InitFailover (padapter, pdev);
-			goto reconTimerExpiry;
-			}
-		padapter->reconPhase = RECON_PHASE_UPDATE;
-		goto reconTimerExpiry;
-		}
-
-	zl = pdev->DiskMirror[pdev->mirrorRecon].reconstructPoint;	
-	padapter->reconSize = pdev->DiskMirror[pdev->mirrorRecon ^ 1].reconstructPoint - zl;
-	if ( padapter->reconSize > MAX_BUS_MASTER_BLOCKS )
-		padapter->reconSize = MAX_BUS_MASTER_BLOCKS;
-
-	if ( padapter->reconSize )
-		{
-		SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1]);	// select the spigots
-		outb_p (pdev->byte6 | ((UCHAR *)(&zl))[3], padapter->regLba24);	// select the drive
-		SelectSpigot (padapter, pdev->spigot);
-		if ( WaitReady (padapter) )
-			goto reconTimerExpiry;
-
-		SelectSpigot (padapter, pdev->spigots[pdev->mirrorRecon]);
-		if ( WaitReady (padapter) )
-			{
-			padapter->survivor = pdev->mirrorRecon ^ 1;
-			padapter->reconPhase = RECON_PHASE_FAILOVER;
-			DEB (printk ("\npci2220i: FAILURE 9"));
-			InitFailover (padapter, pdev);
-			goto reconTimerExpiry;
-			}
-	
-		SelectSpigot (padapter, pdev->spigots[0] | pdev->spigots[1]);
-		outb_p (padapter->reconSize & 0xFF, padapter->regSectCount);
-		outb_p (((UCHAR *)(&zl))[0], padapter->regLba0);
-		outb_p (((UCHAR *)(&zl))[1], padapter->regLba8);
-		outb_p (((UCHAR *)(&zl))[2], padapter->regLba16);
-		padapter->expectingIRQ = TRUE;
-		padapter->reconPhase = RECON_PHASE_READY;
-		SelectSpigot (padapter, pdev->spigots[pdev->mirrorRecon]);
-		WriteCommand (padapter, WRITE_CMD);
-		StartTimer (padapter);
-		SelectSpigot (padapter, pdev->spigot);
-		WriteCommand (padapter, READ_CMD);
-		goto reconTimerExpiry;
-		}
-
-	pdev->DiskMirror[pdev->mirrorRecon].status = UCBF_MIRRORED | UCBF_MATCHED;
-	pdev->DiskMirror[pdev->mirrorRecon ^ 1].status = UCBF_MIRRORED | UCBF_MATCHED;
-	if ( WriteSignature (padapter, pdev, pdev->spigot, pdev->mirrorRecon ^ 1) )
-		goto reconTimerExpiry;
-	padapter->reconPhase = RECON_PHASE_LAST;
-
-reconTimerExpiry:;
-    /*
-     * Release the I/O spinlock and restore the original flags
-     * which will enable interrupts if and only if they were
-     * enabled on entry.
-     */
-    spin_unlock_irqrestore(host->host_lock, flags);
-	}
-/****************************************************************
- *	Name:	Irq_Handler	:LOCAL
- *
- *	Description:	Interrupt handler.
- *
- *	Parameters:		irq		- Hardware IRQ number.
- *					dev_id	-
- *					regs	-
- *
- *	Returns:		TRUE if drive is not ready in time.
- *
- ****************************************************************/
-static irqreturn_t Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
-	{
-	struct Scsi_Host   *shost = NULL;	// Pointer to host data block
-	PADAPTER2220I		padapter;		// Pointer to adapter control structure
-	POUR_DEVICE			pdev;
-	Scsi_Cmnd		   *SCpnt;
-	UCHAR				status;
-	UCHAR				status1;
-	ATAPI_STATUS		statusa;
-	ATAPI_REASON		reasona;
-	ATAPI_ERROR			errora;
-	int					z;
-	ULONG				zl;
-    unsigned long		flags;
-    int handled = 0;
-
-//	DEB (printk ("\npci2220i received interrupt\n"));
-
-	for ( z = 0; z < NumAdapters;  z++ )								// scan for interrupt to process
-		{
-		if ( PsiHost[z]->irq == (UCHAR)(irq & 0xFF) )
-			{
-			if ( inw_p (HOSTDATA(PsiHost[z])->regIrqControl) & 0x8000 )
-				{
-				shost = PsiHost[z];
-				break;
-				}
-			}
-		}
-
-	if ( !shost )
-		{
-		DEB (printk ("\npci2220i: not my interrupt"));
-		goto out;
-		}
-
-	handled = 1;
-	spin_lock_irqsave(shost->host_lock, flags);
-	padapter = HOSTDATA(shost);
-	pdev = padapter->pdev;
-	SCpnt = padapter->SCpnt;
-	outb_p (0x08, padapter->regDmaCmdStat);									// cancel interrupt from DMA engine
-
-	if ( padapter->atapi && SCpnt )
-		{
-		*(char *)&statusa = inb_p (padapter->regStatCmd);						// read the device status
-		*(char *)&reasona = inb_p (padapter->regSectCount);						// read the device interrupt reason
-	
-		if ( !statusa.bsy )
-			{
-			if ( statusa.drq )													// test for transfer phase
-				{
-				if ( !reasona.cod )												// test for data phase
-					{
-					z = (ULONG)inb_p (padapter->regLba8) | (ULONG)(inb_p (padapter->regLba16) << 8);
-					if ( padapter->reqSense )
-						insw (padapter->regData, SCpnt->sense_buffer, z / 2);
-					else
-						AtapiBusMaster (padapter, reasona.io, z);
-					goto irq_return;
-					}
-				if ( reasona.cod && !reasona.io )								// test for command packet phase
-					{
-					if ( padapter->reqSense )
-						AtapiRequestSense (padapter, pdev, SCpnt, TRUE);
-					else
-						AtapiSendCdb (padapter, pdev, padapter->atapiCdb);
-					goto irq_return;
-					}
-				}
-			else
-				{
-				if ( reasona.io && statusa.drdy )								// test for status phase
-					{
-					Atapi2Scsi (padapter, SCpnt);
-					if ( statusa.check )
-						{
-						*(UCHAR *)&errora = inb_p (padapter->regError);			// read the device error
-						if ( errora.senseKey )
-							{
-							if ( padapter->reqSense || AtapiRequestSense (padapter, pdev, SCpnt, FALSE) )
-								OpDone (padapter, DID_ERROR << 16);
-							}
-						else
-							{
-							if ( errora.ili || errora.abort )
-								OpDone (padapter, DID_ERROR << 16);
-							else
-								OpDone (padapter, DID_OK << 16);	
-							}
-						}
-					else
-						if ( padapter->reqSense )
-							{
-							DEB (printk ("PCI2242I: Sense codes - %X %X %X ", ((UCHAR *)SCpnt->sense_buffer)[0], ((UCHAR *)SCpnt->sense_buffer)[12], ((UCHAR *)SCpnt->sense_buffer)[13]));
-							OpDone (padapter, (DRIVER_SENSE << 24) | (DID_OK << 16) | 2);
-							}
-						else
-							OpDone (padapter, DID_OK << 16);	
-					}
-				}
-			}		
-		goto irq_return;
-		}
-	
-	if ( !padapter->expectingIRQ || !(SCpnt || padapter->reconPhase) )
-		{
-		DEB(printk ("\npci2220i Unsolicited interrupt\n"));
-		STOP_HERE ();
-		goto irq_return;
-		}
-	padapter->expectingIRQ = 0;
-
-	if ( padapter->failinprog )
-		{
-		DEB (printk ("\npci2220i interrupt failover complete"));
-		padapter->failinprog = FALSE;
-		status = inb_p (padapter->regStatCmd);								// read the device status
-		if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
-			{
-			DEB (printk ("\npci2220i: interrupt failover error from drive %X", status));
-			padapter->cmd = 0;
-			}
-		else
-			{
-			DEB (printk ("\npci2220i: restarting failed opertation."));
-			pdev->spigot = (padapter->survivor) ? pdev->spigots[1] : pdev->spigots[0];
-			del_timer (&padapter->timer);
-			if ( padapter->reconPhase )
-				OpDone (padapter, DID_OK << 16);
-			else
-				Pci2220i_QueueCommand (SCpnt, SCpnt->scsi_done);
-			goto irq_return;		
-			}
-		}
-
-	if ( padapter->reconPhase )
-		{
-		switch ( padapter->reconPhase )
-			{
-			case RECON_PHASE_MARKING:
-			case RECON_PHASE_LAST:
-				status = inb_p (padapter->regStatCmd);						// read the device status
-				del_timer (&padapter->timer);
-				if ( padapter->reconPhase == RECON_PHASE_LAST )
-					{
-					if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
-						{
-						padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 1 : 0;
-						DEB (printk ("\npci2220i: FAILURE 10"));
-						if ( InitFailover (padapter, pdev) )
-							OpDone (padapter, DecodeError (padapter, status));
-						goto irq_return;
-						}
-					if ( WriteSignature (padapter, pdev, pdev->spigots[pdev->mirrorRecon], pdev->mirrorRecon) )
-						{
-						padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
-						DEB (printk ("\npci2220i: FAILURE 11"));
-						if ( InitFailover (padapter, pdev) )
-							OpDone (padapter, DecodeError (padapter, status));
-						goto irq_return;
-						}
-					padapter->reconPhase = RECON_PHASE_END;	
-					goto irq_return;
-					}
-				OpDone (padapter, DID_OK << 16);
-				goto irq_return;
-
-			case RECON_PHASE_READY:
-				status = inb_p (padapter->regStatCmd);						// read the device status
-				if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
-					{
-					del_timer (&padapter->timer);
-					OpDone (padapter, DecodeError (padapter, status));
-					goto irq_return;
-					}
-				SelectSpigot (padapter, pdev->spigots[pdev->mirrorRecon]);
-				if ( WaitDrq (padapter) )
-					{
-					del_timer (&padapter->timer);
-					padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
-					DEB (printk ("\npci2220i: FAILURE 12"));
-					if ( InitFailover (padapter, pdev) )
-						OpDone (padapter, DecodeError (padapter, status));
-					goto irq_return;
-					}
-				SelectSpigot (padapter, pdev->spigot | SEL_COPY | padapter->bigD);
-				padapter->reconPhase = RECON_PHASE_COPY;
-				padapter->expectingIRQ = TRUE;
-				if ( padapter->timingPIO )
-					{
-					insw (padapter->regData, padapter->kBuffer, padapter->reconSize * (BYTES_PER_SECTOR / 2));
-					}
-				else
-					{
-					if ( (padapter->timingMode > 3) )
-						{
-						if ( padapter->bigD )
-							outl (BIGD_DATA_MODE3, padapter->regDmaAddrLoc);
-						else
-							outl (DALE_DATA_MODE3, padapter->regDmaAddrLoc);
-						}
-					else
-						outl (padapter->timingAddress, padapter->regDmaAddrLoc);
-					outl (padapter->kBufferDma, padapter->regDmaAddrPci);
-					outl (padapter->reconSize * BYTES_PER_SECTOR, padapter->regDmaCount);
-					outb_p (8, padapter->regDmaDesc);						// read operation
-					if ( padapter->bigD )
-						outb_p (8, padapter->regDmaMode);					// no interrupt
-					else
-						outb_p (1, padapter->regDmaMode);					// no interrupt
-					outb_p (0x03, padapter->regDmaCmdStat);					// kick the DMA engine in gear
-					}
-				goto irq_return;
-
-			case RECON_PHASE_COPY:
-				pdev->DiskMirror[pdev->mirrorRecon].reconstructPoint += padapter->reconSize;
-
-			case RECON_PHASE_UPDATE:
-				SelectSpigot (padapter, pdev->spigots[pdev->mirrorRecon] | SEL_IRQ_OFF);
-				status = inb_p (padapter->regStatCmd);						// read the device status
-				del_timer (&padapter->timer);
-				if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
-					{
-					padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
-					DEB (printk ("\npci2220i: FAILURE 13"));
-					DEB (printk ("\n  status register = %X   error = %X", status, inb_p (padapter->regError)));
-					if ( InitFailover (padapter, pdev) )
-						OpDone (padapter, DecodeError (padapter, status));
-					goto irq_return;
-					}
-				OpDone (padapter, DID_OK << 16);
-				goto irq_return;
-
-			case RECON_PHASE_END:
-				status = inb_p (padapter->regStatCmd);						// read the device status
-				del_timer (&padapter->timer);
-				if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
-					{
-					padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 0 : 1;
-					DEB (printk ("\npci2220i: FAILURE 14"));
-					if ( InitFailover (padapter, pdev) )
-						OpDone (padapter, DecodeError (padapter, status));
-					goto irq_return;
-					}
-				pdev->reconOn = 0;
-				if ( padapter->bigD )
-					{
-					for ( z = 0;  z < padapter->numberOfDrives;  z++ )
-						{
-						if ( padapter->device[z].DiskMirror[0].status & UCBF_SURVIVOR )
-							{
-							Alarm (padapter, padapter->device[z].deviceID[0] ^ 2);
-							MuteAlarm (padapter);
-							}
-						if ( padapter->device[z].DiskMirror[1].status & UCBF_SURVIVOR )
-							{
-							Alarm (padapter, padapter->device[z].deviceID[1] ^ 2);
-							MuteAlarm (padapter);
-							}
-						}
-					}
-				OpDone (padapter, DID_OK << 16);
-				goto irq_return;
-
-			default:
-				goto irq_return;
-			}
-		}
-		
-	switch ( padapter->cmd )												// decide how to handle the interrupt
-		{
-		case READ_CMD:
-			if ( padapter->sectorCount )
-				{
-				status = inb_p (padapter->regStatCmd);						// read the device status
-				if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
-					{
-					if ( pdev->raid )
-						{
-						padapter->survivor = ( pdev->spigot == pdev->spigots[0] ) ? 1 : 0;
-						del_timer (&padapter->timer);
-						DEB (printk ("\npci2220i: FAILURE 15"));
-						if ( !InitFailover (padapter, pdev) )
-							goto irq_return;
-						}
-					break;	
-					}
-				if ( padapter->timingPIO )
-					{
-					insw (padapter->regData, padapter->kBuffer, padapter->readCount / 2);
-					padapter->sectorCount -= padapter->readCount / BYTES_PER_SECTOR;
-					WalkScatGath (padapter, TRUE, padapter->readCount);
-					if ( !padapter->sectorCount )
-						{
-						status = 0;
-						break;
-						}
-					}
-				else
-					{
-					if ( padapter->readCount )
-						WalkScatGath (padapter, TRUE, padapter->readCount);
-					BusMaster (padapter, 1, 1);
-					}
-				padapter->expectingIRQ = TRUE;
-				goto irq_return;
-				}
-			if ( padapter->readCount && !padapter->timingPIO )
-				WalkScatGath (padapter, TRUE, padapter->readCount);
-			status = 0;
-			break;
-
-		case WRITE_CMD:
-			if ( pdev->raid )
-				{
-				SelectSpigot (padapter, pdev->spigots[0] | SEL_IRQ_OFF);				
-				status = inb_p (padapter->regStatCmd);								// read the device status
-				SelectSpigot (padapter, pdev->spigots[1] | SEL_IRQ_OFF);				
-				status1 = inb_p (padapter->regStatCmd);								// read the device status
-				}
-			else
-				SelectSpigot (padapter, pdev->spigot | SEL_IRQ_OFF);				
-				status = inb_p (padapter->regStatCmd);								// read the device status
-				status1 = 0;
-		
-			if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
-				{	
-				if ( pdev->raid && !(status1 & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT)) )
-					{
-					padapter->survivor = 1;
-					del_timer (&padapter->timer);
-					SelectSpigot (padapter, pdev->spigot | SEL_IRQ_OFF);
-					DEB (printk ("\npci2220i: FAILURE 16  status = %X  error = %X", status, inb_p (padapter->regError)));
-					if ( !InitFailover (padapter, pdev) )
-						goto irq_return;
-					}
-				break;
-				}
-			if ( pdev->raid )
-				{
-				if ( status1 & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
-					{	
-					padapter->survivor = 0;
-					del_timer (&padapter->timer);
-					DEB (printk ("\npci2220i: FAILURE 17  status = %X  error = %X", status1, inb_p (padapter->regError)));
-					if ( !InitFailover (padapter, pdev) )
-						goto irq_return;
-					status = status1;
-					break;
-					}
-				if ( padapter->sectorCount )
-					{
-					status = WriteDataBoth (padapter, pdev);
-					if ( status )
-						{
-						padapter->survivor = status >> 1;
-						del_timer (&padapter->timer);
-						DEB (printk ("\npci2220i: FAILURE 18"));
-						if ( !InitFailover (padapter, pdev) )
-							goto irq_return;
-						SelectSpigot (padapter, pdev->spigots[status] | SEL_IRQ_OFF);				
-						status = inb_p (padapter->regStatCmd);								// read the device status
-						break;
-						}
-					padapter->expectingIRQ = TRUE;
-					goto irq_return;
-					}
-				status = 0;
-				break;
-				}
-			if ( padapter->sectorCount )	
-				{	
-				SelectSpigot (padapter, pdev->spigot | padapter->bigD);
-				status = WriteData (padapter);
-				if ( status )
-					break;
-				padapter->expectingIRQ = TRUE;
-				goto irq_return;
-				}
-			status = 0;
-			break;
-
-		case IDE_COMMAND_IDENTIFY:
-			{
-			PINQUIRYDATA	pinquiryData  = SCpnt->request_buffer;
-			PIDENTIFY_DATA	pid = (PIDENTIFY_DATA)padapter->kBuffer;
-
-			status = inb_p (padapter->regStatCmd);
-			if ( status & IDE_STATUS_DRQ )
-				{
-				insw (padapter->regData, pid, sizeof (IDENTIFY_DATA) >> 1);
-
-				memset (pinquiryData, 0, SCpnt->request_bufflen);		// Zero INQUIRY data structure.
-				pinquiryData->DeviceType = 0;
-				pinquiryData->Versions = 2;
-				pinquiryData->AdditionalLength = 35 - 4;
-
-				// Fill in vendor identification fields.
-				for ( z = 0;  z < 20;  z += 2 )
-					{
-					pinquiryData->VendorId[z]	  = ((UCHAR *)pid->ModelNumber)[z + 1];
-					pinquiryData->VendorId[z + 1] = ((UCHAR *)pid->ModelNumber)[z];
-					}
-
-				// Initialize unused portion of product id.
-				for ( z = 0;  z < 4;  z++ )
-					pinquiryData->ProductId[12 + z] = ' ';
-
-				// Move firmware revision from IDENTIFY data to
-				// product revision in INQUIRY data.
-				for ( z = 0;  z < 4;  z += 2 )
-					{
-					pinquiryData->ProductRevisionLevel[z]	 = ((UCHAR *)pid->FirmwareRevision)[z + 1];
-					pinquiryData->ProductRevisionLevel[z + 1] = ((UCHAR *)pid->FirmwareRevision)[z];
-					}
-				if ( pdev == padapter->device )
-					*((USHORT *)(&pinquiryData->VendorSpecific)) = DEVICE_DALE_1;
-				
-				status = 0;
-				}
-			break;
-			}
-
-		default:
-			status = 0;
-			break;
-		}
-
-	del_timer (&padapter->timer);
-	if ( status )
-		{
-		DEB (printk ("\npci2220i Interrupt handler return error"));
-		zl = DecodeError (padapter, status);
-		}
-	else
-		zl = DID_OK << 16;
-
-	OpDone (padapter, zl);
-irq_return:
-    spin_unlock_irqrestore(shost->host_lock, flags);
-out:
-	return IRQ_RETVAL(handled);
-}
-
-/****************************************************************
- *	Name:	Pci2220i_QueueCommand
- *
- *	Description:	Process a queued command from the SCSI manager.
- *
- *	Parameters:		SCpnt - Pointer to SCSI command structure.
- *					done  - Pointer to done function to call.
- *
- *	Returns:		Status code.
- *
- ****************************************************************/
-int Pci2220i_QueueCommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
-	{
-	UCHAR		   *cdb = (UCHAR *)SCpnt->cmnd;					// Pointer to SCSI CDB
-	PADAPTER2220I	padapter = HOSTDATA(SCpnt->device->host);			// Pointer to adapter control structure
-	POUR_DEVICE		pdev	 = &padapter->device[SCpnt->device->id];// Pointer to device information
-	UCHAR			rc;											// command return code
-	int				z; 
-	PDEVICE_RAID1	pdr;
-
-	SCpnt->scsi_done = done;
-	padapter->SCpnt = SCpnt;  									// Save this command data
-	padapter->readCount = 0;
-
-	if ( SCpnt->use_sg )
-		{
-		padapter->currentSgBuffer = ((struct scatterlist *)SCpnt->request_buffer)[0].address;
-		padapter->currentSgCount = ((struct scatterlist *)SCpnt->request_buffer)[0].length;
-		}
-	else
-		{
-		padapter->currentSgBuffer = SCpnt->request_buffer;
-		padapter->currentSgCount = SCpnt->request_bufflen;
-		}
-	padapter->nextSg = 1;
-
-	if ( !done )
-		{
-		printk("pci2220i_queuecommand: %02X: done can't be NULL\n", *cdb);
-		return 0;
-		}
-	
-	if ( padapter->atapi )
-		{
-		UCHAR			zlo, zhi;
-
-		DEB (printk ("\nPCI2242I: ID %d, LUN %d opcode %X ", SCpnt->device->id, SCpnt->device->lun, *cdb));
-		padapter->pdev = pdev;
-		if ( !pdev->byte6 || SCpnt->device->lun )
-			{
-			OpDone (padapter, DID_BAD_TARGET << 16);
-			return 0;
-			}
-	
-		padapter->atapiSpecial = FALSE;
-		padapter->reqSense = FALSE;
-		memset (padapter->atapiCdb, 0, 16);
-		SelectSpigot (padapter, pdev->spigot);									// select the spigot
-		AtapiDevice (padapter, pdev->byte6);									// select the drive
-		if ( AtapiWaitReady (padapter, 100) )
-			{
-			OpDone (padapter, DID_NO_CONNECT << 16);
-			return 0;
-			}
-
-		switch ( cdb[0] ) 
-			{
-			case SCSIOP_MODE_SENSE:
-			case SCSIOP_MODE_SELECT:
-				Scsi2Atapi (padapter, SCpnt);
-				z = SCpnt->request_bufflen + 4;
-				break;
-			case SCSIOP_READ6:
-			case SCSIOP_WRITE6:
-				Scsi2Atapi (padapter, SCpnt);
-				z = SCpnt->request_bufflen;
-				break;
-			default:
-				memcpy (padapter->atapiCdb, cdb, SCpnt->cmd_len);
-				z = SCpnt->request_bufflen;
-				break;
-			}
-		if ( z > ATAPI_TRANSFER )
-			z = ATAPI_TRANSFER;
-	    zlo = (UCHAR)(z & 0xFF);
-	    zhi = (UCHAR)(z >> 8);
-
-	 	AtapiCountLo (padapter, zlo);						
-	   	AtapiCountHi (padapter, zhi);						
-	   	outb_p (0, padapter->regError);						
-		WriteCommand (padapter, IDE_COMMAND_ATAPI_PACKET);
-		if ( pdev->cmdDrqInt )
-			return 0;
-
-		if ( AtapiWaitDrq (padapter, 500) )
-			{
-			OpDone (padapter, DID_ERROR << 16);
-			return 0;
-			}
-		AtapiSendCdb (padapter, pdev, padapter->atapiCdb);	
-		return 0;
-		}
-	
-	if ( padapter->reconPhase )
-		return 0;
-	if ( padapter->reconTimer.data )
-		{
-		del_timer (&padapter->reconTimer);
-		padapter->reconTimer.data = 0;
-		}
-		
-	if ( (SCpnt->device->id >= padapter->numberOfDrives) || SCpnt->device->lun )
-		{
-		OpDone (padapter, DID_BAD_TARGET << 16);
-		return 0;
-		}
-	
-	switch ( *cdb )
-		{
-		case SCSIOP_INQUIRY:   					// inquiry CDB
-			{
-			if ( cdb[2] == SC_MY_RAID )
-				{
-				switch ( cdb[3] ) 
-					{
-					case MY_SCSI_REBUILD:
-						for ( z = 0;  z < padapter->numberOfDrives;  z++ )
-							{
-							pdev = &padapter->device[z];
-							if ( ((pdev->DiskMirror[0].status & UCBF_SURVIVOR) && (pdev->DiskMirror[1].status & UCBF_MIRRORED)) ||
-								 ((pdev->DiskMirror[1].status & UCBF_SURVIVOR) && (pdev->DiskMirror[0].status & UCBF_MIRRORED)) )
-								{
-								padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
-								}
-							}
-						OpDone (padapter, DID_OK << 16);
-						break;
-					case MY_SCSI_ALARMMUTE:
-						MuteAlarm (padapter);
-						OpDone (padapter, DID_OK << 16);
-						break;
-					case MY_SCSI_DEMOFAIL:
-						padapter->demoFail = TRUE;				
-						OpDone (padapter, DID_OK << 16);
-						break;
-					default:
-						z = cdb[5];				// get index
-						pdr = (PDEVICE_RAID1)SCpnt->request_buffer;
-						if ( padapter->raidData[z] )
-							{
-							memcpy (&pdr->DiskRaid1, padapter->raidData[z], sizeof (DISK_MIRROR));
-							if ( padapter->raidData[z]->reconstructPoint > padapter->raidData[z ^ 2]->reconstructPoint )
-								pdr->TotalSectors = padapter->raidData[z]->reconstructPoint;
-							else
-								pdr->TotalSectors = padapter->raidData[z ^ 2]->reconstructPoint;
-							}
-						else
-							memset (pdr, 0, sizeof (DEVICE_RAID1));
-						OpDone (padapter, DID_OK << 16);
-						break;
-					}	
-				return 0;
-				}
-			padapter->cmd = IDE_COMMAND_IDENTIFY;
-			break;
-			}
-
-		case SCSIOP_TEST_UNIT_READY:			// test unit ready CDB
-			OpDone (padapter, DID_OK << 16);
-			return 0;
-		case SCSIOP_READ_CAPACITY:			  	// read capctiy CDB
-			{
-			PREAD_CAPACITY_DATA	pdata = (PREAD_CAPACITY_DATA)SCpnt->request_buffer;
-
-			pdata->blksiz = 0x20000;
-			XANY2SCSI ((UCHAR *)&pdata->blks, pdev->blocks);
-			OpDone (padapter, DID_OK << 16);
-			return 0;
-			}
-		case SCSIOP_VERIFY:						// verify CDB
-			padapter->startSector = XSCSI2LONG (&cdb[2]);
-			padapter->sectorCount = (UCHAR)((USHORT)cdb[8] | ((USHORT)cdb[7] << 8));
-			padapter->cmd = IDE_COMMAND_VERIFY;
-			break;
-		case SCSIOP_READ:						// read10 CDB
-			padapter->startSector = XSCSI2LONG (&cdb[2]);
-			padapter->sectorCount = (USHORT)cdb[8] | ((USHORT)cdb[7] << 8);
-			padapter->cmd = READ_CMD;
-			break;
-		case SCSIOP_READ6:						// read6  CDB
-			padapter->startSector = SCSI2LONG (&cdb[1]);
-			padapter->sectorCount = cdb[4];
-			padapter->cmd = READ_CMD;
-			break;
-		case SCSIOP_WRITE:						// write10 CDB
-			padapter->startSector = XSCSI2LONG (&cdb[2]);
-			padapter->sectorCount = (USHORT)cdb[8] | ((USHORT)cdb[7] << 8);
-			padapter->cmd = WRITE_CMD;
-			break;
-		case SCSIOP_WRITE6:						// write6  CDB
-			padapter->startSector = SCSI2LONG (&cdb[1]);
-			padapter->sectorCount = cdb[4];
-			padapter->cmd = WRITE_CMD;
-			break;
-		default:
-			DEB (printk ("pci2220i_queuecommand: Unsupported command %02X\n", *cdb));
-			OpDone (padapter, DID_ERROR << 16);
-			return 0;
-		}
-
-	if ( padapter->reconPhase )
-		return 0;
-	
-	padapter->pdev = pdev;
-
-	while ( padapter->demoFail )
-		{
-		pdev = padapter->pdev = &padapter->device[0];
-		padapter->demoFail = FALSE;
-		if ( !pdev->raid || 
-			 (pdev->DiskMirror[0].status & UCBF_SURVIVOR) || 
-			 (pdev->DiskMirror[1].status & UCBF_SURVIVOR) )
-			{
-			break;
-			}
-		if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
-			padapter->survivor = 1;
-		else
-			padapter->survivor = 0;
-				DEB (printk ("\npci2220i: FAILURE 19"));
-		if ( InitFailover (padapter, pdev) )
-			break;
-		return 0;
-		}
-
-	StartTimer (padapter);
-	if ( pdev->raid && (padapter->cmd == WRITE_CMD) )
-		{
-		rc = IdeCmdBoth (padapter, pdev);
-		if ( !rc )
-			rc = WriteDataBoth (padapter, pdev);
-		if ( rc )
-			{
-			del_timer (&padapter->timer);
-			padapter->expectingIRQ = 0;
-			padapter->survivor = rc >> 1;
-				DEB (printk ("\npci2220i: FAILURE 20"));
-			if ( InitFailover (padapter, pdev) )
-				{
-				OpDone (padapter, DID_ERROR << 16);
-				return 0;
-				}
-			}
-		}
-	else
-		{
-		rc = IdeCmd (padapter, pdev);
-		if ( (padapter->cmd == WRITE_CMD) && !rc )
-			rc = WriteData (padapter);
-		if ( rc )
-			{
-			del_timer (&padapter->timer);
-			padapter->expectingIRQ = 0;
-			if ( pdev->raid )
-				{
-				padapter->survivor = (pdev->spigot ^ 3) >> 1;
-				DEB (printk ("\npci2220i: FAILURE 21"));
-				if ( !InitFailover (padapter, pdev) )
-					return 0;
-				}
-			OpDone (padapter, DID_ERROR << 16);
-			return 0;
-			}
-		}
-	return 0;
-	}
-/****************************************************************
- *	Name:			ReadFlash
- *
- *	Description:	Read information from controller Flash memory.
- *
- *	Parameters:		padapter - Pointer to host interface data structure.
- *					pdata	 - Pointer to data structures.
- *					base	 - base address in Flash.
- *					length	 - lenght of data space in bytes.
- *
- *	Returns:		Nothing.
- *
- ****************************************************************/
-static VOID ReadFlash (PADAPTER2220I padapter, VOID *pdata, ULONG base, ULONG length)
-	{
-	ULONG	 oldremap;
-	UCHAR	 olddesc;
-	ULONG	 z;
-	UCHAR	*pd = (UCHAR *)pdata;
-
-	oldremap = inl (padapter->regRemap);							// save values to restore later
-	olddesc  = inb_p (padapter->regDesc);
-
-	outl (base | 1, padapter->regRemap);							// remap to Flash space as specified
-	outb_p (0x40, padapter->regDesc);								// describe remap region as 8 bit
-	for ( z = 0;  z < length;  z++)									// get "length" data count
-		*pd++ = inb_p (padapter->regBase + z);						// read in the data
-
-	outl (oldremap, padapter->regRemap);							// restore remap register values
-	outb_p (olddesc, padapter->regDesc);
-	}
-/****************************************************************
- *	Name:			GetRegs
- *
- *	Description:	Initialize the regester information.
- *
- *	Parameters:		pshost		  - Pointer to SCSI host data structure.
- *					bigd		  - PCI-2240I identifier
- *					pcidev		  - Pointer to device data structure.
- *
- *	Returns:		TRUE if failure to install.
- *
- ****************************************************************/
-static USHORT GetRegs (struct Scsi_Host *pshost, BOOL bigd, struct pci_dev *pcidev)
-	{
-	PADAPTER2220I	padapter;
-	int				setirq;
-	int				z;
-	USHORT			zr, zl;
-	UCHAR		   *consistent;
-	dma_addr_t		consistentDma;
-
-	padapter = HOSTDATA(pshost);
-	memset (padapter, 0, sizeof (ADAPTER2220I));
-	memset (&DaleSetup, 0, sizeof (DaleSetup));
-	memset (DiskMirror, 0, sizeof (DiskMirror));
-
-	zr = pci_resource_start (pcidev, 1);
-	zl = pci_resource_start (pcidev, 2);
-
-	padapter->basePort = zr;
-	padapter->regRemap		= zr + RTR_LOCAL_REMAP;					// 32 bit local space remap
-	padapter->regDesc		= zr + RTR_REGIONS;	  					// 32 bit local region descriptor
-	padapter->regRange		= zr + RTR_LOCAL_RANGE;					// 32 bit local range
-	padapter->regIrqControl	= zr + RTR_INT_CONTROL_STATUS;			// 16 bit interrupt control and status
-	padapter->regScratchPad	= zr + RTR_MAILBOX;	  					// 16 byte scratchpad I/O base address
-
-	padapter->regBase		= zl;
-	padapter->regData		= zl + REG_DATA;						// data register I/O address
-	padapter->regError		= zl + REG_ERROR;						// error register I/O address
-	padapter->regSectCount	= zl + REG_SECTOR_COUNT;				// sector count register I/O address
-	padapter->regLba0		= zl + REG_LBA_0;						// least significant byte of LBA
-	padapter->regLba8		= zl + REG_LBA_8;						// next least significant byte of LBA
-	padapter->regLba16		= zl + REG_LBA_16;						// next most significan byte of LBA
-	padapter->regLba24		= zl + REG_LBA_24;						// head and most 4 significant bits of LBA
-	padapter->regStatCmd	= zl + REG_STAT_CMD;					// status on read and command on write register
-	padapter->regStatSel	= zl + REG_STAT_SEL;					// board status on read and spigot select on write register
-	padapter->regFail		= zl + REG_FAIL;
-	padapter->regAltStat	= zl + REG_ALT_STAT;
-	padapter->pcidev		= pcidev;
-
-	if ( bigd )
-		{
-		padapter->regDmaDesc	= zr + RTR_DMA0_DESC_PTR;			// address of the DMA discriptor register for direction of transfer
-		padapter->regDmaCmdStat	= zr + RTR_DMA_COMMAND_STATUS;		// Byte #0 of DMA command status register
-		padapter->regDmaAddrPci	= zr + RTR_DMA0_PCI_ADDR;			// 32 bit register for PCI address of DMA
-		padapter->regDmaAddrLoc	= zr + RTR_DMA0_LOCAL_ADDR;			// 32 bit register for local bus address of DMA
-		padapter->regDmaCount	= zr + RTR_DMA0_COUNT;				// 32 bit register for DMA transfer count
-		padapter->regDmaMode	= zr + RTR_DMA0_MODE + 1;			// 32 bit register for DMA mode control
-		padapter->bigD			= SEL_NEW_SPEED_1;					// set spigot speed control bit
-		}
-	else
-		{
-		padapter->regDmaDesc	= zl + RTL_DMA1_DESC_PTR;			// address of the DMA discriptor register for direction of transfer
-		padapter->regDmaCmdStat	= zl + RTL_DMA_COMMAND_STATUS + 1;	// Byte #1 of DMA command status register
-		padapter->regDmaAddrPci	= zl + RTL_DMA1_PCI_ADDR;			// 32 bit register for PCI address of DMA
-		padapter->regDmaAddrLoc	= zl + RTL_DMA1_LOCAL_ADDR;			// 32 bit register for local bus address of DMA
-		padapter->regDmaCount	= zl + RTL_DMA1_COUNT;				// 32 bit register for DMA transfer count
-		padapter->regDmaMode	= zl + RTL_DMA1_MODE + 1;			// 32 bit register for DMA mode control
-		}
-
-	padapter->numberOfDrives = inb_p (padapter->regScratchPad + BIGD_NUM_DRIVES);
-	if ( !bigd && !padapter->numberOfDrives )						// if no devices on this board
-		return TRUE;
-
-	pshost->irq = pcidev->irq;
-	setirq = 1;
-	for ( z = 0;  z < Installed;  z++ )								// scan for shared interrupts
-		{
-		if ( PsiHost[z]->irq == pshost->irq )						// if shared then, don't posses
-			setirq = 0;
-		}
-	if ( setirq )													// if not shared, posses
-		{
-		if ( request_irq (pshost->irq, Irq_Handler, SA_SHIRQ, "pci2220i", padapter) < 0 )
-			{
-			if ( request_irq (pshost->irq, Irq_Handler, SA_INTERRUPT | SA_SHIRQ, "pci2220i", padapter) < 0 )
-				{
-				printk ("Unable to allocate IRQ for PCI-2220I controller.\n");
-				return TRUE;
-				}
-			}
-		padapter->irqOwned = pshost->irq;							// set IRQ as owned
-		}
-
-	if ( padapter->numberOfDrives )
-		consistent = pci_alloc_consistent (pcidev, SECTORSXFER * BYTES_PER_SECTOR, &consistentDma);
-	else
-		consistent = pci_alloc_consistent (pcidev, ATAPI_TRANSFER, &consistentDma);
-	if ( !consistent )
-		{
-		printk ("Unable to allocate DMA buffer for PCI-2220I controller.\n");
-		free_irq (pshost->irq, padapter);
-		return TRUE;
-		}
-	padapter->kBuffer = consistent;
-	padapter->kBufferDma = consistentDma;
-
-	PsiHost[Installed]	= pshost;									// save SCSI_HOST pointer
-	pshost->io_port		= padapter->basePort;
-	pshost->n_io_port	= 0xFF;
-	pshost->unique_id	= padapter->regBase;
-
-	outb_p (0x01, padapter->regRange);								// fix our range register because other drivers want to tromp on it
-
-	padapter->timingMode = inb_p (padapter->regScratchPad + DALE_TIMING_MODE);
-	if ( padapter->timingMode >= 2 )
-		{
-		if ( bigd )
-			padapter->timingAddress	= ModeArray2[padapter->timingMode - 2];
-		else
-			padapter->timingAddress	= ModeArray[padapter->timingMode - 2];
-		}
-	else
-		padapter->timingPIO = TRUE;
-
-	ReadFlash (padapter, &DaleSetup, DALE_FLASH_SETUP, sizeof (SETUP));
-	ReadFlash (padapter, &DiskMirror, DALE_FLASH_RAID, sizeof (DiskMirror));
-
-	return FALSE;
-	}
-/****************************************************************
- *	Name:			SetupFinish
- *
- *	Description:	Complete the driver initialization process for a card
- *
- *	Parameters:		padapter  - Pointer to SCSI host data structure.
- *					str		  - Pointer to board type string.
- *
- *	Returns:		Nothing.
- *
- ****************************************************************/
-VOID SetupFinish (PADAPTER2220I padapter, char *str, int irq)
-	{
-	init_timer (&padapter->timer);
-	padapter->timer.function = TimerExpiry;
-	padapter->timer.data = (unsigned long)padapter;
-	init_timer (&padapter->reconTimer);
-	padapter->reconTimer.function = ReconTimerExpiry;
-	padapter->reconTimer.data = (unsigned long)padapter;
-	printk("\nPCI-%sI EIDE CONTROLLER: at I/O = %lX/%lX  IRQ = %d\n", str, padapter->basePort, padapter->regBase, irq);
-	printk("Version %s, Compiled %s %s\n\n", PCI2220I_VERSION, __DATE__, __TIME__);
-	}	
-/****************************************************************
- *	Name:	Pci2220i_Detect
- *
- *	Description:	Detect and initialize our boards.
- *
- *	Parameters:		tpnt - Pointer to SCSI host template structure.
- *
- *	Returns:		Number of adapters installed.
- *
- ****************************************************************/
-int Pci2220i_Detect (Scsi_Host_Template *tpnt)
-	{
-	struct Scsi_Host   *pshost;
-	PADAPTER2220I	    padapter;
-	POUR_DEVICE			pdev;
-	int					unit;
-	int					z;
-	USHORT				raidon;
-	UCHAR				spigot1, spigot2;
-	UCHAR				device;
-	struct pci_dev	   *pcidev = NULL;
-
-	while ( (pcidev = pci_find_device (VENDOR_PSI, DEVICE_DALE_1, pcidev)) != NULL )
-		{
-		if (pci_enable_device(pcidev))
-			continue;
-		pshost = scsi_register (tpnt, sizeof(ADAPTER2220I));
-		if(pshost==NULL)
-			continue;
-			
-		padapter = HOSTDATA(pshost);
-
-		if ( GetRegs (pshost, FALSE, pcidev) )
-			goto unregister;
-
-		scsi_set_device(pshost, &pcidev->dev);
-		pshost->max_id = padapter->numberOfDrives;
-		for ( z = 0;  z < padapter->numberOfDrives;  z++ )
-			{
-			unit = inb_p (padapter->regScratchPad + DALE_CHANNEL_DEVICE_0 + z) & 0x0F;
-			pdev = &padapter->device[z];
-			pdev->byte6		= (UCHAR)(((unit & 1) << 4) | 0xE0);
-			pdev->spigot	= (UCHAR)(1 << (unit >> 1));
-			pdev->sectors	= DaleSetup.setupDevice[unit].sectors;
-			pdev->heads		= DaleSetup.setupDevice[unit].heads;
-			pdev->cylinders = DaleSetup.setupDevice[unit].cylinders;
-			pdev->blocks	= DaleSetup.setupDevice[unit].blocks;
-
-			if ( !z )
-				{
-				DiskMirror[0].status = inb_p (padapter->regScratchPad + DALE_RAID_0_STATUS);		
-				DiskMirror[1].status = inb_p (padapter->regScratchPad + DALE_RAID_1_STATUS);		
-				if ( (DiskMirror[0].signature == SIGNATURE) && (DiskMirror[1].signature == SIGNATURE) &&
-				     (DiskMirror[0].pairIdentifier == (DiskMirror[1].pairIdentifier ^ 1)) )
-					{			 
-					raidon = TRUE;
-					if ( unit > (unit ^ 2) )
-						unit = unit ^ 2;
-					}	
-				else
-					raidon = FALSE;
-
-				memcpy (pdev->DiskMirror, DiskMirror, sizeof (DiskMirror));
-				padapter->raidData[0] = &pdev->DiskMirror[0];
-				padapter->raidData[2] = &pdev->DiskMirror[1];
-				
-				spigot1 = spigot2 = FALSE;
-				pdev->spigots[0] = 1;
-				pdev->spigots[1] = 2;
-				pdev->lastsectorlba[0] = InlineIdentify (padapter, 1, 0);
-				pdev->lastsectorlba[1] = InlineIdentify (padapter, 2, 0);
-						
-				if ( !(pdev->DiskMirror[1].status & UCBF_SURVIVOR) && pdev->lastsectorlba[0] )
-					spigot1 = TRUE;
-				if ( !(pdev->DiskMirror[0].status & UCBF_SURVIVOR) && pdev->lastsectorlba[1] )
-					spigot2 = TRUE;
-				if ( pdev->DiskMirror[0].status & DiskMirror[1].status & UCBF_SURVIVOR )
-					spigot1 = TRUE;
-
-				if ( spigot1 && (pdev->DiskMirror[0].status & UCBF_REBUILD) )
-					InlineReadSignature (padapter, pdev, 0);
-				if ( spigot2 && (pdev->DiskMirror[1].status & UCBF_REBUILD) )
-					InlineReadSignature (padapter, pdev, 1);
-
-				if ( spigot1 && spigot2 && raidon )
-					{
-					pdev->raid = 1;
-					if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
-						pdev->spigot = 2;
-					else
-						pdev->spigot = 1;
-					if ( (pdev->DiskMirror[0].status & UCBF_REBUILD) || (pdev->DiskMirror[1].status & UCBF_REBUILD) )
-						padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
-					}
-				else
-					{
-					if ( spigot1 )
-						{
-						if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
-							goto unregister;
-						pdev->DiskMirror[0].status = UCBF_MIRRORED | UCBF_SURVIVOR;
-						pdev->spigot = 1;
-						}
-					else
-						{
-						if ( pdev->DiskMirror[1].status & UCBF_REBUILD )
-							goto unregister;
-						pdev->DiskMirror[1].status = UCBF_MIRRORED | UCBF_SURVIVOR;
-						pdev->spigot = 2;
-						}
-					if ( DaleSetup.rebootRebuild && raidon )
-						padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
-					}
-			
-				if ( raidon )
-					break;
-				}
-			}
-
-		SetupFinish (padapter, "2220", pshost->irq);
-	
-		if ( ++Installed < MAXADAPTER )
-			continue;
-		break;
-unregister:;
-		scsi_unregister (pshost);
-		}
-
-	while ( (pcidev = pci_find_device (VENDOR_PSI, DEVICE_BIGD_1, pcidev)) != NULL )
-		{
-		pshost = scsi_register (tpnt, sizeof(ADAPTER2220I));
-		padapter = HOSTDATA(pshost);
-
-		if ( GetRegs (pshost, TRUE, pcidev) )
-			goto unregister1;
-
-		for ( z = 0;  z < BIGD_MAXDRIVES;  z++ )
-			DiskMirror[z].status = inb_p (padapter->regScratchPad + BIGD_RAID_0_STATUS + z);		
-
-		scsi_set_pci_device(pshost, pcidev);
-		pshost->max_id = padapter->numberOfDrives;
-		padapter->failRegister = inb_p (padapter->regScratchPad + BIGD_ALARM_IMAGE);
-		for ( z = 0;  z < padapter->numberOfDrives;  z++ )
-			{
-			unit = inb_p (padapter->regScratchPad + BIGD_DEVICE_0 + z);
-			pdev = &padapter->device[z];
-			pdev->byte6		= (UCHAR)(((unit & 1) << 4) | 0xE0);
-			pdev->spigot	= (UCHAR)(1 << (unit >> 1));
-			pdev->sectors	= DaleSetup.setupDevice[unit].sectors;
-			pdev->heads		= DaleSetup.setupDevice[unit].heads;
-			pdev->cylinders = DaleSetup.setupDevice[unit].cylinders;
-			pdev->blocks	= DaleSetup.setupDevice[unit].blocks;
-			
-			if ( (DiskMirror[unit].signature == SIGNATURE) && (DiskMirror[unit ^ 2].signature == SIGNATURE) &&
-			     (DiskMirror[unit].pairIdentifier == (DiskMirror[unit ^ 2].pairIdentifier ^ 1)) )
-				{			 
-				raidon = TRUE;
-				if ( unit > (unit ^ 2) )
-					unit = unit ^ 2;
-				}	
-			else
-				raidon = FALSE;
-				
-			spigot1 = spigot2 = FALSE;
-			memcpy (&pdev->DiskMirror[0], &DiskMirror[unit], sizeof (DISK_MIRROR));
-			memcpy (&pdev->DiskMirror[1], &DiskMirror[unit ^ 2], sizeof (DISK_MIRROR));
-			padapter->raidData[unit]	 = &pdev->DiskMirror[0];
-			padapter->raidData[unit ^ 2] = &pdev->DiskMirror[1];
-			pdev->spigots[0] = 1 << (unit >> 1);
-			pdev->spigots[1] = 1 << ((unit ^ 2) >> 1);
-			pdev->deviceID[0] = unit;
-			pdev->deviceID[1] = unit ^ 2;
-			pdev->lastsectorlba[0] = InlineIdentify (padapter, pdev->spigots[0], unit & 1);
-			pdev->lastsectorlba[1] = InlineIdentify (padapter, pdev->spigots[1], unit & 1);
-
-			if ( !(pdev->DiskMirror[1].status & UCBF_SURVIVOR) && pdev->lastsectorlba[0] )
-				spigot1 = TRUE;
-			if ( !(pdev->DiskMirror[0].status & UCBF_SURVIVOR) && pdev->lastsectorlba[1] )
-				spigot2 = TRUE;
-			if ( pdev->DiskMirror[0].status & pdev->DiskMirror[1].status & UCBF_SURVIVOR )
-				spigot1 = TRUE;
-
-			if ( spigot1 && (pdev->DiskMirror[0].status & UCBF_REBUILD) )
-				InlineReadSignature (padapter, pdev, 0);
-			if ( spigot2 && (pdev->DiskMirror[1].status & UCBF_REBUILD) )
-				InlineReadSignature (padapter, pdev, 1);
-
-			if ( spigot1 && spigot2 && raidon )
-				{
-				pdev->raid = 1;
-				if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
-					pdev->spigot = pdev->spigots[1];
-				else
-					pdev->spigot = pdev->spigots[0];
-				if ( (pdev->DiskMirror[0].status & UCBF_REBUILD) || (pdev->DiskMirror[1].status & UCBF_REBUILD) )
-					padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
-				}
-			else
-				{
-				if ( spigot1 )
-					{
-					if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
-						goto unregister1;
-					pdev->DiskMirror[0].status = UCBF_MIRRORED | UCBF_SURVIVOR;
-					pdev->spigot = pdev->spigots[0];
-					}
-				else
-					{
-					if ( pdev->DiskMirror[1].status & UCBF_REBUILD )
-						goto unregister;
-					pdev->DiskMirror[1].status = UCBF_MIRRORED | UCBF_SURVIVOR;
-					pdev->spigot = pdev->spigots[1];
-					}
-				if ( DaleSetup.rebootRebuild && raidon )
-					padapter->reconOn = pdev->reconOn = pdev->reconIsStarting = TRUE;
-				}
-			}
-		
-		if ( !padapter->numberOfDrives )									// If no ATA devices then scan ATAPI
-			{
-			unit = 0;
-			for ( spigot1 = 0;  spigot1 < 4;  spigot1++ )
-				{
-				for ( device = 0;  device < 2;  device++ )
-					{
-					DEB (printk ("\nPCI2242I: scanning for ID %d ", (spigot1 * 2) + device));
-					pdev = &(padapter->device[(spigot1 * 2) + device]);
-					pdev->byte6 = 0x0A | (device << 4);
-					pdev->spigot = 1 << spigot1;
-					if ( !AtapiReset (padapter, pdev) )
-						{
-						DEB (printk (" Device found "));
-						if ( !AtapiIdentify (padapter, pdev) )
-							{
-							DEB (printk (" Device verified"));
-							unit++;
-							continue;
-							}
-						}
-					pdev->spigot = pdev->byte6 = 0;
-					}
-				}
-
-			if ( unit )
-				{
-				padapter->atapi = TRUE;
-				padapter->timingAddress = DALE_DATA_MODE3;
-				outw_p (0x0900, padapter->regIrqControl);					// Turn our interrupts on
-				outw_p (0x0C41, padapter->regDmaMode - 1);					// setup for 16 bits, ready enabled, done IRQ enabled, no incriment
-				outb_p (0xFF, padapter->regFail);							// all fail lights and alarm off
-				pshost->max_id = 8;
-				}
-			}
-		SetupFinish (padapter, "2240", pshost->irq);
-		
-		if ( ++Installed < MAXADAPTER )
-			continue;
-		break;
-unregister1:;
-		scsi_unregister (pshost);
-		}
-
-	NumAdapters = Installed;
-	return Installed;
-	}
-/****************************************************************
- *	Name:	Pci2220i_Abort
- *
- *	Description:	Process the Abort command from the SCSI manager.
- *
- *	Parameters:		SCpnt - Pointer to SCSI command structure.
- *
- *	Returns:		Allways snooze.
- *
- ****************************************************************/
-int Pci2220i_Abort (Scsi_Cmnd *SCpnt)
-	{
-	PADAPTER2220I	padapter = HOSTDATA(SCpnt->device->host);			// Pointer to adapter control structure
-	POUR_DEVICE		pdev	 = &padapter->device[SCpnt->device->id];// Pointer to device information
-
-	if ( !padapter->SCpnt )
-		return SCSI_ABORT_NOT_RUNNING;
-	
-	if ( padapter->atapi )
-		{
-		if ( AtapiReset (padapter, pdev) )
-			return SCSI_ABORT_ERROR;
-		OpDone (padapter, DID_ABORT << 16);
-		return SCSI_ABORT_SUCCESS;
-		}
-	return SCSI_ABORT_SNOOZE;
-	}
-/****************************************************************
- *	Name:	Pci2220i_Reset
- *
- *	Description:	Process the Reset command from the SCSI manager.
- *
- *	Parameters:		SCpnt - Pointer to SCSI command structure.
- *					flags - Flags about the reset command
- *
- *	Returns:		No active command at this time, so this means
- *					that each time we got some kind of response the
- *					last time through.  Tell the mid-level code to
- *					request sense information in order to decide what
- *					to do next.
- *
- ****************************************************************/
-int Pci2220i_Reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
-	{
-	PADAPTER2220I	padapter = HOSTDATA(SCpnt->device->host);			// Pointer to adapter control structure
-	POUR_DEVICE		pdev	 = &padapter->device[SCpnt->device->id];// Pointer to device information
-
-	if ( padapter->atapi )
-		{
-		if ( AtapiReset (padapter, pdev) )
-			return SCSI_RESET_ERROR;
-		return SCSI_RESET_SUCCESS;
-		}
-	return SCSI_RESET_PUNT;
-	}
-/****************************************************************
- *	Name:	Pci2220i_Release
- *
- *	Description:	Release resources allocated for a single each adapter.
- *
- *	Parameters:		pshost - Pointer to SCSI command structure.
- *
- *	Returns:		zero.
- *
- ****************************************************************/
-int Pci2220i_Release (struct Scsi_Host *pshost)
-	{
-    PADAPTER2220I	padapter = HOSTDATA (pshost);
-	USHORT			z;
-
-	if ( padapter->reconOn )
-		{
-		padapter->reconOn = FALSE;						// shut down the hot reconstruct
-		if ( padapter->reconPhase )
-			mdelay (300);
-		if ( padapter->reconTimer.data )				// is the timer running?
-			{
-			del_timer (&padapter->reconTimer);
-			padapter->reconTimer.data = 0;
-			}
-		}
-
-	// save RAID status on the board
-	if ( padapter->bigD )
-		{
-		outb_p (padapter->failRegister, padapter->regScratchPad + BIGD_ALARM_IMAGE);
-		for ( z = 0;  z < BIGD_MAXDRIVES;  z++ )
-			{
-			if ( padapter->raidData )
-				outb_p (padapter->raidData[z]->status, padapter->regScratchPad + BIGD_RAID_0_STATUS + z);	
-			else
-				outb_p (0, padapter->regScratchPad + BIGD_RAID_0_STATUS);	
-			}
-		}
-	else
-		{
-		outb_p (padapter->device[0].DiskMirror[0].status, padapter->regScratchPad + DALE_RAID_0_STATUS);		
-		outb_p (padapter->device[0].DiskMirror[1].status, padapter->regScratchPad + DALE_RAID_1_STATUS);		
-		}
-
-	if ( padapter->irqOwned )
-		free_irq (pshost->irq, padapter);
-    release_region (pshost->io_port, pshost->n_io_port);
-	if ( padapter->numberOfDrives )
-		pci_free_consistent (padapter->pcidev, SECTORSXFER * BYTES_PER_SECTOR, padapter->kBuffer, padapter->kBufferDma);
-	else	
-		pci_free_consistent (padapter->pcidev, ATAPI_TRANSFER, padapter->kBuffer, padapter->kBufferDma);
-    scsi_unregister(pshost);
-    return 0;
-	}
-
-/****************************************************************
- *	Name:	Pci2220i_BiosParam
- *
- *	Description:	Process the biosparam request from the SCSI manager to
- *					return C/H/S data.
- *
- *	Parameters:		disk - Pointer to SCSI disk structure.
- *					dev	 - Major/minor number from kernel.
- *					geom - Pointer to integer array to place geometry data.
- *
- *	Returns:		zero.
- *
- ****************************************************************/
-int Pci2220i_BiosParam (struct scsi_device *sdev, struct block_device *dev,
-		sector_t capacity, int geom[])
-	{
-	POUR_DEVICE	pdev;
-
-	if ( !(HOSTDATA(sdev->host))->atapi )
-		{
-		pdev = &(HOSTDATA(sdev->host)->device[sdev->id]);
-
-		geom[0] = pdev->heads;
-		geom[1] = pdev->sectors;
-		geom[2] = pdev->cylinders;
-		}
-	return 0;
-	}
-
-MODULE_LICENSE("Dual BSD/GPL");
-
-static Scsi_Host_Template driver_template = {
-	.proc_name		= "pci2220i",
-	.name			= "PCI-2220I/PCI-2240I",
-	.detect			= Pci2220i_Detect,
-	.release		= Pci2220i_Release,
-	.queuecommand		= Pci2220i_QueueCommand,
-	.abort			= Pci2220i_Abort,
-	.reset			= Pci2220i_Reset,
-	.bios_param		= Pci2220i_BiosParam,
-	.can_queue		= 1,
-	.this_id		= -1,
-	.sg_tablesize		= SG_ALL,
-	.cmd_per_lun		= 1,
-	.use_clustering		= DISABLE_CLUSTERING,
-};
-#include "scsi_module.c"
diff --git a/drivers/scsi/pci2220i.h b/drivers/scsi/pci2220i.h
deleted file mode 100644
index 6926056..0000000
--- a/drivers/scsi/pci2220i.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/****************************************************************************
- * Perceptive Solutions, Inc. PCI-2220I device driver for Linux.
- *
- * pci2220i.h - Linux Host Driver for PCI-2220i EIDE Adapters
- *
- * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
- * All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that redistributions of source
- * code retain the above copyright notice and this comment without
- * modification.
- *
- * Technical updates and product information at:
- *  http://www.psidisk.com
- *
- * Please send questions, comments, bug reports to:
- *  tech@psidisk.com Technical Support
- *
- ****************************************************************************/
-#ifndef _PCI2220I_H
-#define _PCI2220I_H
-
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif 
-#define	LINUXVERSION(v,p,s)    (((v)<<16) + ((p)<<8) + (s))
-
-// function prototypes
-int Pci2220i_Detect			(Scsi_Host_Template *tpnt);
-int Pci2220i_Command		(Scsi_Cmnd *SCpnt);
-int Pci2220i_QueueCommand	(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
-int Pci2220i_Abort			(Scsi_Cmnd *SCpnt);
-int Pci2220i_Reset			(Scsi_Cmnd *SCpnt, unsigned int flags);
-int Pci2220i_Release		(struct Scsi_Host *pshost);
-int Pci2220i_BiosParam		(struct scsi_device *sdev,
-					struct block_device *dev,
-					sector_t capacity, int geom[]);
-#endif
diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c
index 496c412..3dddb32 100644
--- a/drivers/scsi/pcmcia/nsp_cs.c
+++ b/drivers/scsi/pcmcia/nsp_cs.c
@@ -92,9 +92,7 @@
 #endif
 	.info			 = nsp_info,
 	.queuecommand		 = nsp_queuecommand,
-/*	.eh_strategy_handler	 = nsp_eh_strategy,*/
 /*	.eh_abort_handler	 = nsp_eh_abort,*/
-/*	.eh_device_reset_handler = nsp_eh_device_reset,*/
 	.eh_bus_reset_handler	 = nsp_eh_bus_reset,
 	.eh_host_reset_handler	 = nsp_eh_host_reset,
 	.can_queue		 = 1,
@@ -1536,11 +1534,6 @@
 /* error handler                                                 */
 /*---------------------------------------------------------------*/
 
-/*static int nsp_eh_strategy(struct Scsi_Host *Shost)
-{
-	return FAILED;
-}*/
-
 /*
 static int nsp_eh_abort(Scsi_Cmnd *SCpnt)
 {
@@ -1549,14 +1542,6 @@
 	return nsp_eh_bus_reset(SCpnt);
 }*/
 
-/*
-static int nsp_eh_device_reset(Scsi_Cmnd *SCpnt)
-{
-	nsp_dbg(NSP_DEBUG_BUSRESET, "%s: SCpnt=0x%p", SCpnt);
-
-	return FAILED;
-}*/
-
 static int nsp_bus_reset(nsp_hw_data *data)
 {
 	unsigned int base = data->BaseAddress;
diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c
index 4766bcd..a0175f5 100644
--- a/drivers/scsi/pcmcia/qlogic_stub.c
+++ b/drivers/scsi/pcmcia/qlogic_stub.c
@@ -81,8 +81,6 @@
 	.queuecommand		= qlogicfas408_queuecommand,
 	.eh_abort_handler	= qlogicfas408_abort,
 	.eh_bus_reset_handler	= qlogicfas408_bus_reset,
-	.eh_device_reset_handler= qlogicfas408_device_reset,
-	.eh_host_reset_handler	= qlogicfas408_host_reset,
 	.bios_param		= qlogicfas408_biosparam,
 	.can_queue		= 1,
 	.this_id		= -1,
diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c
index 8457d0d..1667da9 100644
--- a/drivers/scsi/pcmcia/sym53c500_cs.c
+++ b/drivers/scsi/pcmcia/sym53c500_cs.c
@@ -627,7 +627,9 @@
 	int port_base = SCpnt->device->host->io_port;
 
 	DEB(printk("SYM53C500_host_reset called\n"));
+	spin_lock_irq(SCpnt->device->host->host_lock);
 	SYM53C500_int_host_reset(port_base);
+	spin_unlock_irq(SCpnt->device->host->host_lock);
 
 	return SUCCESS;
 }
diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c
index c01b719..623082d 100644
--- a/drivers/scsi/pluto.c
+++ b/drivers/scsi/pluto.c
@@ -354,7 +354,6 @@
 	.use_clustering		= ENABLE_CLUSTERING,
 	.eh_abort_handler	= fcp_scsi_abort,
 	.eh_device_reset_handler = fcp_scsi_dev_reset,
-	.eh_bus_reset_handler	= fcp_scsi_bus_reset,
 	.eh_host_reset_handler	= fcp_scsi_host_reset,
 };
 
diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c
index 96b4522..fafcf5d 100644
--- a/drivers/scsi/ppa.c
+++ b/drivers/scsi/ppa.c
@@ -17,6 +17,7 @@
 #include <linux/blkdev.h>
 #include <linux/parport.h>
 #include <linux/workqueue.h>
+#include <linux/delay.h>
 #include <asm/io.h>
 
 #include <scsi/scsi.h>
@@ -891,9 +892,9 @@
 
 	ppa_connect(dev, CONNECT_NORMAL);
 	ppa_reset_pulse(dev->base);
-	udelay(1000);		/* device settle delay */
+	mdelay(1);		/* device settle delay */
 	ppa_disconnect(dev);
-	udelay(1000);		/* device settle delay */
+	mdelay(1);		/* device settle delay */
 	return SUCCESS;
 }
 
diff --git a/drivers/scsi/psi_dale.h b/drivers/scsi/psi_dale.h
deleted file mode 100644
index d672e3b..0000000
--- a/drivers/scsi/psi_dale.h
+++ /dev/null
@@ -1,564 +0,0 @@
-/****************************************************************************
- * Perceptive Solutions, Inc. PCI-2220I device driver for Linux.
- *
- * psi_dalei.h - Linux Host Driver for PCI-2220i EIDE Adapters
- *
- * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
- * All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that redistributions of source
- * code retain the above copyright notice and this comment without
- * modification.
- *
- * Technical updates and product information at:
- *  http://www.psidisk.com
- *
- * Please send questions, comments, bug reports to:
- *  tech@psidisk.com Technical Support
- *
- ****************************************************************************/
-
-/************************************************/
-/*		Some defines that we like 				*/
-/************************************************/
-#define	CHAR		char
-#define	UCHAR		unsigned char
-#define	SHORT		short
-#define	USHORT		unsigned short
-#define	BOOL		unsigned short
-#define	LONG		long
-#define	ULONG		unsigned long
-#define	VOID		void
-
-/************************************************/
-/*		Dale PCI setup							*/
-/************************************************/
-#define	VENDOR_PSI			0x1256
-#define	DEVICE_DALE_1		0x4401		/* 'D1' */
-#define	DEVICE_BIGD_1		0x4201		/* 'B1' */
-#define	DEVICE_BIGD_2		0x4202		/* 'B2' */
-
-/************************************************/
-/*		Misc konstants							*/
-/************************************************/
-#define	DALE_MAXDRIVES			4
-#define	BIGD_MAXDRIVES			8
-#define	SECTORSXFER				8
-#define	ATAPI_TRANSFER			8192
-#define	BYTES_PER_SECTOR		512
-#define	DEFAULT_TIMING_MODE		5
-
-/************************************************/
-/*		EEPROM locations						*/
-/************************************************/
-#define	DALE_FLASH_PAGE_SIZE	128				// number of bytes per page
-#define	DALE_FLASH_SIZE			65536L
-
-#define	DALE_FLASH_BIOS			0x00080000L		// BIOS base address
-#define	DALE_FLASH_SETUP		0x00088000L		// SETUP PROGRAM base address offset from BIOS
-#define	DALE_FLASH_RAID			0x00088400L		// RAID signature storage
-#define	DALE_FLASH_FACTORY		0x00089000L		// FACTORY data base address offset from BIOS
-
-#define	DALE_FLASH_BIOS_SIZE	32768U			// size of FLASH BIOS REGION
-
-/************************************************/
-/*		DALE Register address offsets			*/
-/************************************************/
-#define	REG_DATA					0x80
-#define	REG_ERROR					0x84
-#define	REG_SECTOR_COUNT			0x88
-#define	REG_LBA_0					0x8C
-#define	REG_LBA_8					0x90
-#define	REG_LBA_16					0x94
-#define	REG_LBA_24					0x98
-#define	REG_STAT_CMD				0x9C
-#define	REG_STAT_SEL				0xA0
-#define	REG_FAIL					0xB0
-#define	REG_ALT_STAT				0xB8
-#define	REG_DRIVE_ADRS				0xBC
-
-#define	DALE_DATA_SLOW				0x00040000L
-#define	DALE_DATA_MODE2				0x00040000L
-#define	DALE_DATA_MODE3				0x00050000L
-#define	DALE_DATA_MODE4				0x00060000L
-#define	DALE_DATA_MODE5				0x00070000L
-
-#define	BIGD_DATA_SLOW				0x00000000L
-#define	BIGD_DATA_MODE0				0x00000000L
-#define	BIGD_DATA_MODE2				0x00000000L
-#define	BIGD_DATA_MODE3				0x00000008L
-#define	BIGD_DATA_MODE4				0x00000010L
-#define	BIGD_DATA_MODE5				0x00000020L
-
-#define RTR_LOCAL_RANGE				0x000
-#define RTR_LOCAL_REMAP				0x004
-#define RTR_EXP_RANGE				0x010
-#define RTR_EXP_REMAP				0x014
-#define RTR_REGIONS					0x018
-#define RTR_DM_MASK					0x01C
-#define RTR_DM_LOCAL_BASE			0x020
-#define RTR_DM_IO_BASE				0x024
-#define RTR_DM_PCI_REMAP			0x028
-#define RTR_DM_IO_CONFIG			0x02C
-#define RTR_MAILBOX					0x040
-#define RTR_LOCAL_DOORBELL			0x060
-#define RTR_PCI_DOORBELL			0x064
-#define RTR_INT_CONTROL_STATUS 		0x068
-#define RTR_EEPROM_CONTROL_STATUS	0x06C
-
-#define RTR_DMA0_MODE				0x0080
-#define RTR_DMA0_PCI_ADDR			0x0084
-#define RTR_DMA0_LOCAL_ADDR			0x0088
-#define RTR_DMA0_COUNT				0x008C
-#define RTR_DMA0_DESC_PTR			0x0090
-#define RTR_DMA1_MODE				0x0094
-#define RTR_DMA1_PCI_ADDR			0x0098
-#define RTR_DMA1_LOCAL_ADDR			0x009C
-#define RTR_DMA1_COUNT				0x00A0
-#define RTR_DMA1_DESC_PTR			0x00A4
-#define RTR_DMA_COMMAND_STATUS		0x00A8
-#define RTR_DMA_ARB0				0x00AC
-#define RTR_DMA_ARB1				0x00B0
-
-#define RTL_DMA0_MODE				0x00
-#define RTL_DMA0_PCI_ADDR			0x04
-#define RTL_DMA0_LOCAL_ADDR			0x08
-#define RTL_DMA0_COUNT				0x0C
-#define RTL_DMA0_DESC_PTR			0x10
-#define RTL_DMA1_MODE				0x14
-#define RTL_DMA1_PCI_ADDR			0x18
-#define RTL_DMA1_LOCAL_ADDR			0x1C
-#define RTL_DMA1_COUNT				0x20
-#define RTL_DMA1_DESC_PTR			0x24
-#define RTL_DMA_COMMAND_STATUS		0x28
-#define RTL_DMA_ARB0				0x2C
-#define RTL_DMA_ARB1				0x30
-
-/************************************************/
-/*		Dale Scratchpad locations				*/
-/************************************************/
-#define	DALE_CHANNEL_DEVICE_0		0		// device channel locations
-#define	DALE_CHANNEL_DEVICE_1		1
-#define	DALE_CHANNEL_DEVICE_2		2
-#define	DALE_CHANNEL_DEVICE_3		3
-
-#define	DALE_SCRATCH_DEVICE_0		4		// device type codes
-#define	DALE_SCRATCH_DEVICE_1		5
-#define DALE_SCRATCH_DEVICE_2		6
-#define	DALE_SCRATCH_DEVICE_3		7
-
-#define	DALE_RAID_0_STATUS			8
-#define DALE_RAID_1_STATUS			9
-
-#define	DALE_TIMING_MODE			12		// bus master timing mode (2, 3, 4, 5)
-#define	DALE_NUM_DRIVES				13		// number of addressable drives on this board
-#define	DALE_RAID_ON				14 		// RAID status On
-#define	DALE_LAST_ERROR				15		// Last error code from BIOS
-
-/************************************************/
-/*		BigD Scratchpad locations				*/
-/************************************************/
-#define	BIGD_DEVICE_0			0		// device channel locations
-#define	BIGD_DEVICE_1			1
-#define	BIGD_DEVICE_2			2
-#define	BIGD_DEVICE_3			3
-
-#define	BIGD_DEVICE_4			4		// device type codes
-#define	BIGD_DEVICE_5			5
-#define BIGD_DEVICE_6			6
-#define	BIGD_DEVICE_7			7
-
-#define	BIGD_ALARM_IMAGE		11		// ~image of alarm fail register		
-#define	BIGD_TIMING_MODE		12		// bus master timing mode (2, 3, 4, 5)
-#define	BIGD_NUM_DRIVES			13		// number of addressable drives on this board
-#define	BIGD_RAID_ON			14 		// RAID status is on for the whole board
-#define	BIGD_LAST_ERROR			15		// Last error code from BIOS
-
-#define	BIGD_RAID_0_STATUS		16
-#define BIGD_RAID_1_STATUS		17
-#define	BIGD_RAID_2_STATUS		18
-#define	BIGD_RAID_3_STATUS		19
-#define	BIGD_RAID_4_STATUS		20
-#define BIGD_RAID_5_STATUS		21
-#define	BIGD_RAID_6_STATUS		22
-#define	BIGD_RAID_7_STATUS		23
-
-/************************************************/
-/*		Dale cable select bits					*/
-/************************************************/
-#define	SEL_NONE					0x00
-#define	SEL_1						0x01
-#define	SEL_2						0x02
-#define	SEL_3						0x04
-#define	SEL_4						0x08
-#define	SEL_NEW_SPEED_1				0x20
-#define	SEL_COPY					0x40
-#define	SEL_IRQ_OFF					0x80
-
-/************************************************/
-/*		Device/Geometry controls				*/
-/************************************************/
-#define GEOMETRY_NONE	 			0x0				// No device
-#define GEOMETRY_SET				0x1				// Geometry set
-#define	GEOMETRY_LBA				0x2				// Geometry set in default LBA mode
-#define	GEOMETRY_PHOENIX			0x3				// Geometry set in Pheonix BIOS compatibility mode
-
-#define	DEVICE_NONE					0x0				// No device present
-#define	DEVICE_INACTIVE				0x1				// device present but not registered active
-#define	DEVICE_ATAPI				0x2				// ATAPI device (CD_ROM, Tape, Etc...)
-#define	DEVICE_DASD_NONLBA			0x3				// Non LBA incompatible device
-#define	DEVICE_DASD_LBA				0x4				// LBA compatible device
-
-/************************************************/
-/*		BigD fail register bits					*/
-/************************************************/
-#define	FAIL_NONE				0x00
-#define	FAIL_0					0x01
-#define	FAIL_1					0x02
-#define	FAIL_2					0x04
-#define	FAIL_MULTIPLE			0x08
-#define	FAIL_GOOD				0x20
-#define	FAIL_AUDIBLE			0x40
-#define	FAIL_ANY				0x80
-
-/************************************************/
-/*		Setup Structure Definitions				*/
-/************************************************/
-typedef struct		// device setup parameters
-	{
-	UCHAR	geometryControl;	// geometry control flags
-	UCHAR	device;				// device code
-	USHORT	sectors;			// number of sectors per track
-	USHORT	heads;				// number of heads
-	USHORT	cylinders;			// number of cylinders for this device
-	ULONG	blocks;				// number of blocks on device
-	ULONG	realCapacity;		// number of real blocks on this device for drive changed testing
-	} SETUP_DEVICE, *PSETUP_DEVICE;
-
-typedef struct		// master setup structure
-	{
-	USHORT			startupDelay;
-	BOOL			promptBIOS;
-	BOOL			fastFormat;
-	BOOL			shareInterrupt;
-	BOOL			rebootRebuild;
-	USHORT			timingMode;
-	USHORT			spare5;
-	USHORT			spare6;
-	SETUP_DEVICE	setupDevice[BIGD_MAXDRIVES];
-	}	SETUP, *PSETUP;
-
-/************************************************/
-/*		RAID Structure Definitions				*/
-/************************************************/
-typedef	struct
-	{
-	UCHAR	signature;			// 0x55 our mirror signature
-	UCHAR	status;				// current status bits
-	UCHAR	pairIdentifier;		// unique identifier for pair
-	ULONG	reconstructPoint;	// recontruction point for hot reconstruct
-	}	DISK_MIRROR;
-
-typedef struct	DEVICE_RAID1
-	{
-	long		TotalSectors;
-	DISK_MIRROR DiskRaid1;
-	}	DEVICE_RAID1, *PDEVICE_RAID1;
-
-#define	DISK_MIRROR_POSITION	0x01A8
-#define	SIGNATURE				0x55
-
-#define	MASK_SERIAL_NUMBER	0x0FFE			// mask for serial number matching
-#define	MASK_SERIAL_UNIT	0x0001			// mask for unit portion of serial number
-
-// Status bits
-#define	UCBF_MIRRORED		0x0010								// drive has a pair
-#define	UCBF_MATCHED		0x0020								// drive pair is matched
-#define	UCBF_SURVIVOR		0x0040								// this unit is a survivor of a pair
-#define	UCBF_REBUILD		0x0080								// rebuild in progress on this device
-
-// SCSI controls for RAID
-#define	SC_MY_RAID			0xBF			// our special CDB command byte for Win95... interface
-#define	MY_SCSI_QUERY1		0x32			// byte 1 subcommand to query driver for RAID 1 informatation
-#define	MY_SCSI_REBUILD		0x40			// byte 1 subcommand to reconstruct a mirrored pair
-#define MY_SCSI_DEMOFAIL	0x54			// byte 1 subcommand for RAID failure demonstration
-#define	MY_SCSI_ALARMMUTE	0x60			// byte 1 subcommand to mute any alarm currently on
-
-/************************************************/
-/*		Timeout konstants		 				*/
-/************************************************/
-#define	TIMEOUT_READY				100			// 100 mSec
-#define	TIMEOUT_DRQ					300			// 300 mSec
-#define	TIMEOUT_DATA				(3 * HZ)	// 3 seconds
-
-/************************************************/
-/*		Misc. macros			 				*/
-/************************************************/
-#define ANY2SCSI(up, p)					\
-((UCHAR *)up)[0] = (((ULONG)(p)) >> 8);	\
-((UCHAR *)up)[1] = ((ULONG)(p));
-
-#define SCSI2LONG(up)					\
-( (((long)*(((UCHAR *)up))) << 16)		\
-+ (((long)(((UCHAR *)up)[1])) << 8)		\
-+ ((long)(((UCHAR *)up)[2])) )
-
-#define XANY2SCSI(up, p)				\
-((UCHAR *)up)[0] = ((long)(p)) >> 24;	\
-((UCHAR *)up)[1] = ((long)(p)) >> 16;	\
-((UCHAR *)up)[2] = ((long)(p)) >> 8;	\
-((UCHAR *)up)[3] = ((long)(p));
-
-#define XSCSI2LONG(up)					\
-( (((long)(((UCHAR *)up)[0])) << 24)	\
-+ (((long)(((UCHAR *)up)[1])) << 16)	\
-+ (((long)(((UCHAR *)up)[2])) <<  8)	\
-+ ((long)(((UCHAR *)up)[3])) )
-
-#define	SelectSpigot(padapter,spigot)	outb_p (spigot, padapter->regStatSel)
-#define WriteCommand(padapter,cmd)		outb_p (cmd, padapter->regStatCmd)
-#define	AtapiDevice(padapter,b)			outb_p (b, padapter->regLba24);
-#define	AtapiCountLo(padapter,b)		outb_p (b, padapter->regLba8)
-#define	AtapiCountHi(padapter,b)		outb_p (b, padapter->regLba16)
-
-/************************************************/
-/*		SCSI CDB operation codes 				*/
-/************************************************/
-#define SCSIOP_TEST_UNIT_READY		0x00
-#define SCSIOP_REZERO_UNIT			0x01
-#define SCSIOP_REWIND				0x01
-#define SCSIOP_REQUEST_BLOCK_ADDR	0x02
-#define SCSIOP_REQUEST_SENSE		0x03
-#define SCSIOP_FORMAT_UNIT			0x04
-#define SCSIOP_READ_BLOCK_LIMITS	0x05
-#define SCSIOP_REASSIGN_BLOCKS		0x07
-#define SCSIOP_READ6				0x08
-#define SCSIOP_RECEIVE				0x08
-#define SCSIOP_WRITE6				0x0A
-#define SCSIOP_PRINT				0x0A
-#define SCSIOP_SEND					0x0A
-#define SCSIOP_SEEK6				0x0B
-#define SCSIOP_TRACK_SELECT			0x0B
-#define SCSIOP_SLEW_PRINT			0x0B
-#define SCSIOP_SEEK_BLOCK			0x0C
-#define SCSIOP_PARTITION			0x0D
-#define SCSIOP_READ_REVERSE			0x0F
-#define SCSIOP_WRITE_FILEMARKS		0x10
-#define SCSIOP_FLUSH_BUFFER			0x10
-#define SCSIOP_SPACE				0x11
-#define SCSIOP_INQUIRY				0x12
-#define SCSIOP_VERIFY6				0x13
-#define SCSIOP_RECOVER_BUF_DATA		0x14
-#define SCSIOP_MODE_SELECT			0x15
-#define SCSIOP_RESERVE_UNIT			0x16
-#define SCSIOP_RELEASE_UNIT			0x17
-#define SCSIOP_COPY					0x18
-#define SCSIOP_ERASE				0x19
-#define SCSIOP_MODE_SENSE			0x1A
-#define SCSIOP_START_STOP_UNIT		0x1B
-#define SCSIOP_STOP_PRINT			0x1B
-#define SCSIOP_LOAD_UNLOAD			0x1B
-#define SCSIOP_RECEIVE_DIAGNOSTIC	0x1C
-#define SCSIOP_SEND_DIAGNOSTIC		0x1D
-#define SCSIOP_MEDIUM_REMOVAL		0x1E
-#define SCSIOP_READ_CAPACITY		0x25
-#define SCSIOP_READ					0x28
-#define SCSIOP_WRITE				0x2A
-#define SCSIOP_SEEK					0x2B
-#define SCSIOP_LOCATE				0x2B
-#define SCSIOP_WRITE_VERIFY			0x2E
-#define SCSIOP_VERIFY				0x2F
-#define SCSIOP_SEARCH_DATA_HIGH		0x30
-#define SCSIOP_SEARCH_DATA_EQUAL	0x31
-#define SCSIOP_SEARCH_DATA_LOW		0x32
-#define SCSIOP_SET_LIMITS			0x33
-#define SCSIOP_READ_POSITION		0x34
-#define SCSIOP_SYNCHRONIZE_CACHE	0x35
-#define SCSIOP_COMPARE				0x39
-#define SCSIOP_COPY_COMPARE			0x3A
-#define SCSIOP_WRITE_DATA_BUFF		0x3B
-#define SCSIOP_READ_DATA_BUFF		0x3C
-#define SCSIOP_CHANGE_DEFINITION	0x40
-#define SCSIOP_READ_SUB_CHANNEL		0x42
-#define SCSIOP_READ_TOC				0x43
-#define SCSIOP_READ_HEADER			0x44
-#define SCSIOP_PLAY_AUDIO			0x45
-#define SCSIOP_PLAY_AUDIO_MSF		0x47
-#define SCSIOP_PLAY_TRACK_INDEX		0x48
-#define SCSIOP_PLAY_TRACK_RELATIVE	0x49
-#define SCSIOP_PAUSE_RESUME			0x4B
-#define SCSIOP_LOG_SELECT			0x4C
-#define SCSIOP_LOG_SENSE			0x4D
-#define SCSIOP_MODE_SELECT10		0x55
-#define SCSIOP_MODE_SENSE10			0x5A
-#define SCSIOP_LOAD_UNLOAD_SLOT		0xA6
-#define SCSIOP_MECHANISM_STATUS		0xBD
-#define SCSIOP_READ_CD				0xBE
-
-// IDE command definitions
-#define IDE_COMMAND_ATAPI_RESET		0x08
-#define IDE_COMMAND_READ			0x20
-#define IDE_COMMAND_WRITE			0x30
-#define IDE_COMMAND_RECALIBRATE		0x10
-#define IDE_COMMAND_SEEK			0x70
-#define IDE_COMMAND_SET_PARAMETERS	0x91
-#define IDE_COMMAND_VERIFY			0x40
-#define IDE_COMMAND_ATAPI_PACKET	0xA0
-#define IDE_COMMAND_ATAPI_IDENTIFY	0xA1
-#define	IDE_CMD_READ_MULTIPLE		0xC4
-#define	IDE_CMD_WRITE_MULTIPLE		0xC5
-#define	IDE_CMD_SET_MULTIPLE		0xC6
-#define IDE_COMMAND_IDENTIFY		0xEC
-
-// IDE status definitions
-#define IDE_STATUS_ERROR			0x01
-#define IDE_STATUS_INDEX			0x02
-#define IDE_STATUS_CORRECTED_ERROR	0x04
-#define IDE_STATUS_DRQ				0x08
-#define IDE_STATUS_DSC				0x10
-#define	IDE_STATUS_WRITE_FAULT		0x20
-#define IDE_STATUS_DRDY				0x40
-#define IDE_STATUS_BUSY				0x80
-
-typedef struct _ATAPI_STATUS
-	{
-	CHAR	check		:1;
-	CHAR	reserved1	:1;
-	CHAR	corr		:1;
-	CHAR	drq			:1;
-	CHAR	dsc			:1;
-	CHAR	reserved2	:1;
-	CHAR	drdy		:1;
-	CHAR	bsy			:1;
-	}	ATAPI_STATUS;
-
-typedef struct _ATAPI_REASON
-	{
-	CHAR	cod			:1;
-	CHAR	io			:1;
-	CHAR	reserved1	:6;
-	}	ATAPI_REASON;
-
-typedef struct _ATAPI_ERROR
-	{
-	CHAR	ili			:1;
-	CHAR	eom			:1;
-	CHAR	abort		:1;
-	CHAR	mcr			:1;
-	CHAR	senseKey	:4;
-	}	ATAPI_ERROR;
-
-// IDE error definitions
-#define	IDE_ERROR_AMNF				0x01
-#define	IDE_ERROR_TKONF				0x02
-#define	IDE_ERROR_ABRT				0x04
-#define	IDE_ERROR_MCR				0x08
-#define	IDE_ERROR_IDFN				0x10
-#define	IDE_ERROR_MC				0x20
-#define	IDE_ERROR_UNC				0x40
-#define	IDE_ERROR_BBK				0x80
-
-// SCSI read capacity structure
-typedef	struct _READ_CAPACITY_DATA
-	{
-	ULONG blks;				/* total blocks (converted to little endian) */
-	ULONG blksiz;			/* size of each (converted to little endian) */
-	}	READ_CAPACITY_DATA, *PREAD_CAPACITY_DATA;
-
-// SCSI inquiry data
-typedef struct _INQUIRYDATA
-	{
-	UCHAR DeviceType			:5;
-	UCHAR DeviceTypeQualifier	:3;
-	UCHAR DeviceTypeModifier	:7;
-	UCHAR RemovableMedia		:1;
-    UCHAR Versions;
-    UCHAR ResponseDataFormat;
-    UCHAR AdditionalLength;
-    UCHAR Reserved[2];
-	UCHAR SoftReset				:1;
-	UCHAR CommandQueue			:1;
-	UCHAR Reserved2				:1;
-	UCHAR LinkedCommands		:1;
-	UCHAR Synchronous			:1;
-	UCHAR Wide16Bit				:1;
-	UCHAR Wide32Bit				:1;
-	UCHAR RelativeAddressing	:1;
-    UCHAR VendorId[8];
-    UCHAR ProductId[16];
-    UCHAR ProductRevisionLevel[4];
-    UCHAR VendorSpecific[20];
-    UCHAR Reserved3[40];
-	}	INQUIRYDATA, *PINQUIRYDATA;
-
-// IDE IDENTIFY data
-#pragma pack (1)
-typedef struct _IDENTIFY_DATA
-	{
-    USHORT	GeneralConfiguration;		//  0
-    USHORT	NumberOfCylinders;			//  1
-    USHORT	Reserved1;					//  2
-    USHORT	NumberOfHeads;				//  3
-    USHORT	UnformattedBytesPerTrack;	//  4
-    USHORT	UnformattedBytesPerSector;	//  5
-    USHORT	SectorsPerTrack;			//  6
-	USHORT	NumBytesISG;				//  7 Byte Len - inter-sector gap
-	USHORT	NumBytesSync;				//  8          - sync field
-	USHORT	NumWordsVUS;				//  9 Len - Vendor Unique Info
-    USHORT	SerialNumber[10];			// 10
-    USHORT	BufferType;					// 20
-    USHORT	BufferSectorSize;			// 21
-    USHORT	NumberOfEccBytes;			// 22
-    USHORT	FirmwareRevision[4];		// 23
-    USHORT	ModelNumber[20];			// 27
-	USHORT	NumSectorsPerInt	:8;		// 47 Multiple Mode - Sec/Blk
-	USHORT	Reserved2			:8;		// 47
-	USHORT	DoubleWordMode;				// 48 flag for double word mode capable
-	USHORT	VendorUnique1		:8;		// 49
-	USHORT	SupportDMA			:1;		// 49 DMA supported
-	USHORT	SupportLBA			:1;		// 49 LBA supported
-	USHORT	SupportIORDYDisable	:1;		// 49 IORDY can be disabled
-	USHORT	SupportIORDY		:1;		// 49 IORDY supported
-	USHORT	ReservedPsuedoDMA	:1;		// 49 reserved for pseudo DMA mode support
-	USHORT	Reserved3			:3;		// 49
-	USHORT	Reserved4;					// 50
-	USHORT	Reserved5			:8;		// 51 Transfer Cycle Timing - PIO
-	USHORT	PIOCycleTime		:8;		// 51 Transfer Cycle Timing - PIO
-	USHORT	Reserved6			:8;		// 52                       - DMA
-	USHORT	DMACycleTime		:8;		// 52                       - DMA
-	USHORT	Valid_54_58			:1;		// 53 words 54 - 58 are valid
-	USHORT	Valid_64_70			:1;		// 53 words 64 - 70 are valid
-	USHORT	Reserved7			:14;	// 53
-	USHORT	LogNumCyl;					// 54 Current Translation - Num Cyl
-	USHORT	LogNumHeads;				// 55                       Num Heads
-	USHORT	LogSectorsPerTrack;			// 56                       Sec/Trk
-	ULONG	LogTotalSectors;			// 57                       Total Sec
-	USHORT	CurrentNumSecPerInt	:8;		// 59 current setting for number of sectors per interrupt
-	USHORT	ValidNumSecPerInt	:1;		// 59 Current setting is valid for number of sectors per interrupt
-	USHORT	Reserved8			:7;		// 59
-	ULONG	LBATotalSectors;			// 60 LBA Mode - Sectors
-	USHORT	DMASWordFlags;				// 62
-	USHORT	DMAMWordFlags;				// 63
-	USHORT	AdvancedPIOSupport  :8;		// 64 Flow control PIO transfer modes supported
-	USHORT	Reserved9			:8;		// 64
-	USHORT	MinMultiDMACycle;			// 65 minimum multiword DMA transfer cycle time per word
-	USHORT	RecomendDMACycle;			// 66 Manufacturer's recommende multiword DMA transfer cycle time
-	USHORT	MinPIOCycleWithoutFlow;		// 67 Minimum PIO transfer cycle time without flow control
-	USHORT	MinPIOCylceWithFlow;		// 68 Minimum PIO transfer cycle time with IORDY flow control
-	USHORT	ReservedSpace[256-69];		// 69
-	}	IDENTIFY_DATA, *PIDENTIFY_DATA;
-
-// ATAPI configuration bits
-typedef struct _ATAPI_GENERAL_0
-	{
-	USHORT	CmdPacketSize		:2;		// Command packet size
-	USHORT	Reserved1			:3;
-	USHORT	CmdDrqType			:2;
-	USHORT	Removable			:1;
-	USHORT	DeviceType			:5;
-	USHORT	Reserved2			:1;
-	USHORT	ProtocolType		:2;
-	}	ATAPI_GENERAL_0;
-
-#pragma pack ()
diff --git a/drivers/scsi/psi_roy.h b/drivers/scsi/psi_roy.h
deleted file mode 100644
index c55b9c0..0000000
--- a/drivers/scsi/psi_roy.h
+++ /dev/null
@@ -1,331 +0,0 @@
-/****************************************************************************
- * Perceptive Solutions, Inc. PCI-2000 device driver for Linux.
- *
- * psi_roy.h - Linux Host Driver for PCI-2000 IntelliCache SCSI Adapters
- *
- * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
- * All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that redistributions of source
- * code retain the above copyright notice and this comment without
- * modification.
- *
- * Technical updates and product information at:
- *  http://www.psidisk.com
- *
- * Please send questions, comments, bug reports to:
- *  tech@psidisk.com Technical Support
- *
- ****************************************************************************/
-
-#ifndef	ROY_HOST
-#define	ROY_HOST
-
-/************************************************/
-/*		PCI setup								*/
-/************************************************/
-#define	VENDOR_PSI			0x1256
-#define	DEVICE_ROY_1		0x5201		/* 'R1' */
-
-/************************************************/
-/*		controller constants					*/
-/************************************************/
-#define MAXADAPTER			4			// Increase this and the sizes of the arrays below, if you need more.
-#define	MAX_BUS				2
-#define	MAX_UNITS			16
-#define	TIMEOUT_COMMAND		400			// number of milliSecondos for command busy timeout
-
-/************************************************/
-/*		I/O address offsets						*/
-/************************************************/
-#define RTR_MAILBOX						0x040
-#define RTR_LOCAL_DOORBELL				0x060
-#define RTR_PCI_DOORBELL				0x064
-
-/************************************************/
-/*												*/
-/*			Host command codes					*/
-/*												*/
-/************************************************/
-#define	CMD_READ_CHS		0x01		/* read sectors as specified (CHS mode) */
-#define	CMD_READ			0x02		/* read sectors as specified (RBA mode) */
-#define	CMD_READ_SG			0x03		/* read sectors using scatter/gather list */
-#define	CMD_WRITE_CHS		0x04		/* write sectors as specified (CHS mode) */
-#define	CMD_WRITE			0x05		/* write sectors as specified (RBA mode) */
-#define	CMD_WRITE_SG		0x06		/* write sectors using scatter/gather list (LBA mode) */
-#define	CMD_READ_CHS_SG		0x07		/* read sectors using scatter/gather list (CHS mode) */
-#define	CMD_WRITE_CHS_SG	0x08		/* write sectors using scatter/gather list (CHS mode) */
-#define	CMD_VERIFY_CHS		0x09		/* verify data on sectors as specified (CHS mode) */
-#define	CMD_VERIFY			0x0A		/* verify data on sectors as specified (RBA mode) */
-#define	CMD_DASD_CDB		0x0B		/* process CDB for a DASD device */
-#define	CMD_DASD_CDB_SG		0x0C		/* process CDB for a DASD device with scatter/gather */
-
-#define	CMD_READ_ABS		0x10		/* read absolute disk */
-#define	CMD_WRITE_ABS		0x11		/* write absolute disk */
-#define	CMD_VERIFY_ABS		0x12		/* verify absolute disk */
-#define	CMD_TEST_READY		0x13		/* test unit ready and return status code */
-#define	CMD_LOCK_DOOR		0x14		/* lock device door */
-#define	CMD_UNLOCK_DOOR		0x15		/* unlock device door */
-#define	CMD_EJECT_MEDIA		0x16		/* eject the media */
-#define	CMD_UPDATE_CAP		0x17		/* update capacity information */
-#define	CMD_TEST_PRIV		0x18		/* test and setup private format media */
-
-
-#define	CMD_SCSI_THRU		0x30		/* SCSI pass through CDB */
-#define	CMD_SCSI_THRU_SG	0x31		/* SCSI pass through CDB with scatter/gather */
-#define	CMD_SCSI_REQ_SENSE	0x32		/* SCSI pass through request sense after check condition */
-
-#define	CMD_DASD_RAID_RQ	0x35		/* request DASD RAID drive data */
-#define	CMD_DASD_RAID_RQ0	0x31			/* byte 1 subcommand to query for RAID 0 informatation */
-#define	CMD_DASD_RAID_RQ1	0x32			/* byte 1 subcommand to query for RAID 1 informatation */
-#define	CMD_DASD_RAID_RQ5	0x33			/* byte 1 subcommand to query for RAID 5 informatation */
-
-#define	CMD_DASD_SCSI_INQ	0x36		/* do DASD inquire and return in SCSI format */
-#define	CMD_DASD_CAP		0x37		/* read DASD capacity */
-#define	CMD_DASD_INQ		0x38		/* do DASD inquire for type data and return SCSI/EIDE inquiry */
-#define	CMD_SCSI_INQ		0x39		/* do SCSI inquire */
-#define	CMD_READ_SETUP		0x3A		/* Get setup structures from controller */
-#define	CMD_WRITE_SETUP		0x3B		/* Put setup structures in controller and burn in flash */
-#define	CMD_READ_CONFIG		0x3C		/* Get the entire configuration and setup structures */
-#define	CMD_WRITE_CONFIG	0x3D		/* Put the entire configuration and setup structures in flash */
-
-#define	CMD_TEXT_DEVICE		0x3E		/* obtain device text */
-#define	CMD_TEXT_SIGNON		0x3F		/* get sign on banner */
-
-#define	CMD_QUEUE			0x40		/* any command below this generates a queue tag interrupt to host*/
-
-#define	CMD_PREFETCH		0x40		/* prefetch sectors as specified */
-#define	CMD_TEST_WRITE		0x41		/* Test a device for write protect */
-#define	CMD_LAST_STATUS		0x42		/* get last command status and error data*/
-#define	CMD_ABORT			0x43		/* abort command as specified */
-#define	CMD_ERROR			0x44		/* fetch error code from a tagged op */
-#define	CMD_DONE			0x45		/* done with operation */
-#define	CMD_DIAGNOSTICS		0x46		/* execute controller diagnostics and wait for results */
-#define	CMD_FEATURE_MODE	0x47		/* feature mode control word */
-#define	CMD_DASD_INQUIRE	0x48		/* inquire as to DASD SCSI device (32 possible) */
-#define	CMD_FEATURE_QUERY	0x49		/* query the feature control word */
-#define	CMD_DASD_EJECT		0x4A		/* Eject removable media for DASD type */
-#define	CMD_DASD_LOCK		0x4B		/* Lock removable media for DASD type */
-#define	CMD_DASD_TYPE		0x4C		/* obtain DASD device type */
-#define	CMD_NUM_DEV			0x4D		/* obtain the number of devices connected to the controller */
-#define	CMD_GET_PARMS		0x4E		/* obtain device parameters */
-#define	CMD_SPECIFY			0x4F		/* specify operating system for scatter/gather operations */
-
-#define	CMD_RAID_GET_DEV	0x50		/* read RAID device geometry */
-#define CMD_RAID_READ		0x51		/* read RAID 1 parameter block */
-#define	CMD_RAID_WRITE		0x52		/* write RAID 1 parameter block */
-#define	CMD_RAID_LITEUP		0x53		/* Light up the drive light for identification */
-#define	CMD_RAID_REBUILD	0x54		/* issue a RAID 1 pair rebuild */
-#define	CMD_RAID_MUTE		0x55		/* mute RAID failure alarm */
-#define	CMD_RAID_FAIL		0x56		/* induce a RAID failure */
-#define	CMD_RAID_STATUS		0x57		/* get status of RAID pair */
-#define	CMD_RAID_STOP		0x58		/* stop any reconstruct in progress */
-#define CMD_RAID_START		0x59		/* start reconstruct */
-#define	CMD_RAID0_READ		0x5A		/* read RAID 0 parameter block */
-#define	CMD_RAID0_WRITE		0x5B		/* write RAID 0 parameter block */
-#define	CMD_RAID5_READ		0x5C		/* read RAID 5 parameter block */
-#define	CMD_RAID5_WRITE		0x5D		/* write RAID 5 parameter block */
-
-#define	CMD_ERASE_TABLES	0x5F		/* erase partition table and RAID signatutures */
-
-#define	CMD_SCSI_GET		0x60		/* get SCSI pass through devices */
-#define	CMD_SCSI_TIMEOUT	0x61		/* set SCSI pass through timeout */
-#define	CMD_SCSI_ERROR		0x62		/* get SCSI pass through request sense length and residual data count */
-#define	CMD_GET_SPARMS		0x63		/* get SCSI bus and user parms */
-#define	CMD_SCSI_ABORT		0x64		/* abort by setting time-out to zero */
-
-#define	CMD_CHIRP_CHIRP		0x77		/* make a chirp chirp sound */
-#define	CMD_GET_LAST_DONE	0x78		/* get tag of last done in progress */
-#define	CMD_GET_FEATURES	0x79		/* get feature code and ESN */
-#define CMD_CLEAR_CACHE		0x7A		/* Clear cache on specified device */
-#define	CMD_BIOS_TEST		0x7B		/* Test whether or not to load BIOS */
-#define	CMD_WAIT_FLUSH		0x7C		/* wait for cache flushed and invalidate read cache */
-#define	CMD_RESET_BUS		0x7D		/* reset the SCSI bus */
-#define	CMD_STARTUP_QRY		0x7E		/* startup in progress query */
-#define	CMD_RESET			0x7F		/* reset the controller */
-
-#define	CMD_RESTART_RESET	0x80		/* reload and restart the controller at any reset issued */
-#define	CMD_SOFT_RESET		0x81		/* do a soft reset NOW! */
-
-/************************************************/
-/*												*/
-/*				Host return errors				*/
-/*												*/
-/************************************************/
-#define	ERR08_TAGGED		0x80		/* doorbell error ored with tag */
-
-#define	ERR16_NONE			0x0000		/* no errors */
-#define	ERR16_SC_COND_MET	0x0004		/* SCSI status - Condition Met */
-#define	ERR16_CMD			0x0101		/* command error */
-#define	ERR16_SC_CHECK_COND	0x0002		/* SCSI status - Check Condition */
-#define	ERR16_CMD_NOT		0x0201		/* command not supported */
-#define ERR16_NO_DEVICE     0x0301		/* invalid device selection */
-#define	ERR16_SECTOR		0x0202		/* bad sector */
-#define	ERR16_PROTECT		0x0303		/* write protected */
-#define	ERR16_NOSECTOR		0x0404		/* sector not found */
-#define	ERR16_MEDIA			0x0C0C		/* invalid media */
-#define	ERR16_CONTROL		0x2020		/* controller error */
-#define	ERR16_CONTROL_DMA	0x2120		/* controller DMA engine error */
-#define	ERR16_NO_ALARM		0x2220		/* alarm is not active */
-#define	ERR16_OP_BUSY		0x2320		/* operation busy */
-#define	ERR16_SEEK			0x4040		/* seek failure */
-#define	ERR16_DEVICE_FAIL	0x4140		/* device has failed */
-#define ERR16_TIMEOUT		0x8080		/* timeout error */
-#define	ERR16_DEV_NOT_READY	0xAAAA		/* drive not ready */
-#define	ERR16_UNDEFINED		0xBBBB		/* undefined error */
-#define	ERR16_WRITE_FAULT	0xCCCC		/* write fault */
-#define ERR16_INVALID_DEV	0x4001		/* invalid device access */
-#define	ERR16_DEVICE_BUSY	0x4002		/* device is busy */
-#define	ERR16_MEMORY		0x4003		/* device pass thru requires too much memory */
-#define	ERR16_NO_FEATURE	0x40FA		/* feature no implemented */
-#define	ERR16_NOTAG			0x40FD		/* no tag space available */
-#define	ERR16_NOT_READY		0x40FE		/* controller not ready error */
-#define	ERR16_SETUP_FLASH	0x5050		/* error when writing setup to flash memory */
-#define	ERR16_SETUP_SIZE	0x5051		/* setup block size error */
-#define	ERR16_SENSE			0xFFFF		/* sense opereration failed */
-#define	ERR16_SC_BUSY		0x0008		/* SCSI status - Busy */
-#define	ERR16_SC_RES_CONFL	0x0018		/* SCSI status - Reservation Conflict */
-#define	ERR16_SC_CMD_TERM	0x0022		/* SCSI status - Command Terminated */
-#define	ERR16_SC_OTHER		0x00FF		/* SCSI status - not recognized (any value masked) */
-#define	ERR16_MEDIA_CHANGED	0x8001		/* devices media has been changed */
-
-#define	ERR32_NONE			0x00000000	/* no errors */
-#define	ERR32_SC_COND_MET	0x00000004	/* SCSI status - Condition Met */
-#define	ERR32_CMD			0x00010101	/* command error */
-#define	ERR32_SC_CHECK_COND	0x00020002	/* SCSI status - Check Condition */
-#define	ERR32_CMD_NOT		0x00030201	/* command not supported */
-#define ERR32_NO_DEVICE     0x00040301	/* invalid device selection */
-#define	ERR32_SECTOR		0x00050202	/* bad sector */
-#define	ERR32_PROTECT		0x00060303	/* write protected */
-#define	ERR32_NOSECTOR		0x00070404	/* sector not found */
-#define	ERR32_MEDIA			0x00080C0C	/* invalid media */
-#define	ERR32_CONTROL		0x00092020	/* controller error */
-#define	ERR32_CONTROL_DMA	0x000A2120	/* Controller DMA error */
-#define	ERR32_NO_ALARM		0x000B2220 	/* alarm is not active */
-#define	ERR32_OP_BUSY		0x000C2320	/* operation busy */
-#define	ERR32_SEEK			0x000D4040	/* seek failure */
-#define	ERR32_DEVICE_FAIL	0x000E4140	/* device has failed */
-#define ERR32_TIMEOUT		0x000F8080	/* timeout error */
-#define	ERR32_DEV_NOT_READY	0x0010AAAA	/* drive not ready */
-#define	ERR32_UNDEFINED		0x0011BBBB	/* undefined error */
-#define	ERR32_WRITE_FAULT	0x0012CCCC	/* write fault */
-#define ERR32_INVALID_DEV	0x00134001	/* invalid device access */
-#define	ERR32_DEVICE_BUSY	0x00144002	/* device is busy */
-#define	ERR32_MEMORY		0x00154003	/* device pass thru requires too much memory */
-#define	ERR32_NO_FEATURE	0x001640FA	/* feature no implemented */
-#define	ERR32_NOTAG			0x001740FD	/* no tag space available */
-#define	ERR32_NOT_READY		0x001840FE	/* controller not ready error */
-#define	ERR32_SETUP_FLASH	0x00195050	/* error when writing setup to flash memory */
-#define	ERR32_SETUP_SIZE	0x001A5051	/* setup block size error */
-#define	ERR32_SENSE			0x001BFFFF	/* sense opereration failed */
-#define	ERR32_SC_BUSY		0x001C0008	/* SCSI status - Busy */
-#define	ERR32_SC_RES_CONFL	0x001D0018	/* SCSI status - Reservation Conflict */
-#define	ERR32_SC_CMD_TERM	0x001E0022	/* SCSI status - Command Terminated */
-#define	ERR32_SC_OTHER		0x001F00FF	/* SCSI status - not recognized (any value masked) */
-#define	ERR32_MEDIA_CHANGED	0x00208001	/* devices media has been changed */
-
-/************************************************/
-/*												*/
-/*	Host Operating System specification codes	*/
-/*												*/
-/************************************************/
-#define	SPEC_INTERRUPT		0x80		/* specification requires host interrupt */
-#define	SPEC_BACKWARD_SG	0x40		/* specification requires scatter/gather items reversed */
-#define	SPEC_DOS_BLOCK		0x01		/* DOS DASD blocking on pass through */
-#define	SPEC_OS2_V3			0x02		/* OS/2 Warp */
-#define	SPCE_SCO_3242		0x04		/* SCO 3.4.2.2 */
-#define	SPEC_QNX_4X			0x05		/* QNX 4.XX */
-#define	SPEC_NOVELL_NWPA	0x08		/* Novell NWPA scatter/gather support */
-
-/************************************************/
-/*												*/
-/*	Inquire structures							*/
-/*												*/
-/************************************************/
-typedef	struct	_CNT_SCSI_INQ
-	{
-	UCHAR	devt;						/* 00: device type */
-	UCHAR	devtm;						/* 01: device type modifier */
-	UCHAR	svers;						/* 02: SCSI version */
-	UCHAR	rfmt;						/* 03: response data format */
-	UCHAR	adlen;						/* 04: additional length of data */
-	UCHAR	res1;						/* 05: */
-	UCHAR	res2;						/* 06: */
-	UCHAR	fncs;						/* 07: functional capabilities */
-	UCHAR	vid[8];						/* 08: vendor ID */
-	UCHAR	pid[16];					/* 10: product ID */
-	UCHAR	rev[4];						/* 20: product revision */
-	}	CNT_SCSI_INQ;
-
-typedef	struct	_CNT_IDE_INQ
-	{
-	USHORT	GeneralConfiguration;		/* 00 */
-	USHORT	NumberOfCylinders;			/* 02 */
-	USHORT	Reserved1;					/* 04 */
-	USHORT	NumberOfHeads;				/* 06 */
-	USHORT	UnformattedBytesPerTrack;	/* 08 */
-	USHORT	UnformattedBytesPerSector;	/* 0A */
-	USHORT	SectorsPerTrack;			/* 0C */
-	USHORT	VendorUnique1[3];			/* 0E */
-	USHORT	SerialNumber[10];			/* 14 */
-	USHORT	BufferType;					/* 28 */
-	USHORT	BufferSectorSize;			/* 2A */
-	USHORT	NumberOfEccBytes;			/* 2C */
-	USHORT	FirmwareRevision[4];		/* 2E */
-	USHORT	ModelNumber[20];			/* 36 */
-	UCHAR	MaximumBlockTransfer;		/* 5E */
-	UCHAR	VendorUnique2;				/* 5F */
-	USHORT	DoubleWordIo;				/* 60 */
-	USHORT	Capabilities;				/* 62 */
-	USHORT	Reserved2;					/* 64 */
-	UCHAR	VendorUnique3;				/* 66 */
-	UCHAR	PioCycleTimingMode;			/* 67 */
-	UCHAR	VendorUnique4;				/* 68 */
-	UCHAR	DmaCycleTimingMode;			/* 69 */
-	USHORT	TranslationFieldsValid;		/* 6A */
-	USHORT	NumberOfCurrentCylinders;	/* 6C */
-	USHORT	NumberOfCurrentHeads;		/* 6E */
-	USHORT	CurrentSectorsPerTrack;		/* 70 */
-	ULONG	CurrentSectorCapacity;		/* 72 */
-	}	CNT_IDE_INQ;
-
-typedef struct	_DASD_INQUIRE
-	{
-	ULONG	type;						/* 0 = SCSI, 1 = IDE */
-	union
-		{
-		CNT_SCSI_INQ	scsi;			/* SCSI inquire data */
-		CNT_IDE_INQ		ide;			/* IDE inquire data */
-		}	inq;
-	}	DASD_INQUIRE;
-
-/************************************************/
-/*												*/
-/*	Device Codes								*/
-/*												*/
-/************************************************/
-#define DEVC_DASD			0x00		/* Direct-access Storage Device */
-#define DEVC_SEQACESS		0x01		/* Sequential-access device */
-#define DEVC_PRINTER		0x02		/* Printer device */
-#define DEVC_PROCESSOR		0x03		/* Processor device */
-#define DEVC_WRITEONCE		0x04		/* Write-once device */
-#define DEVC_CDROM			0x05		/* CD-ROM device */
-#define DEVC_SCANNER		0x06		/* Scanner device */
-#define DEVC_OPTICAL		0x07		/* Optical memory device */
-#define DEVC_MEDCHGR		0x08		/* Medium changer device */
-#define	DEVC_DASD_REMOVABLE	0x80		/* Direct-access storage device, Removable */
-#define	DEVC_NONE			0xFF		/* no device */
-
-// SCSI controls for RAID
-#define	SC_MY_RAID			0xBF			// our special CDB command byte for Win95... interface
-#define	MY_SCSI_QUERY0		0x31			// byte 1 subcommand to query driver for RAID 0 informatation
-#define	MY_SCSI_QUERY1		0x32			// byte 1 subcommand to query driver for RAID 1 informatation
-#define	MY_SCSI_QUERY5		0x33			// byte 1 subcommand to query driver for RAID 5 informatation
-#define	MY_SCSI_REBUILD		0x40			// byte 1 subcommand to reconstruct a mirrored pair
-#define MY_SCSI_DEMOFAIL	0x54			// byte 1 subcommand for RAID failure demonstration
-#define	MY_SCSI_ALARMMUTE	0x60			// byte 1 subcommand to mute any alarm currently on
-
-
-#endif
-
diff --git a/drivers/scsi/ql1040_fw.h b/drivers/scsi/ql1040_fw.h
index 89d8e09..aaf9284 100644
--- a/drivers/scsi/ql1040_fw.h
+++ b/drivers/scsi/ql1040_fw.h
@@ -25,17 +25,17 @@
  */
 
 /*
- *	Firmware Version 7.65.00 (14:17 Jul 20, 1999)
+ *	Firmware Version 7.65.06 (14:38 Jan 07, 2002)
  */
 
-static unsigned char firmware_version[] = {7,65,0};
+static unsigned char firmware_version[] = {7,65,6};
 
-#define FW_VERSION_STRING "7.65.0"
+#define FW_VERSION_STRING "7.65.06"
 
 static unsigned short risc_code_addr01 = 0x1000 ;
 
 static unsigned short risc_code01[] = { 
-	0x0078, 0x103a, 0x0000, 0x4057, 0x0000, 0x2043, 0x4f50, 0x5952,
+	0x0078, 0x103a, 0x0000, 0x4158, 0x0000, 0x2043, 0x4f50, 0x5952,
 	0x4947, 0x4854, 0x2031, 0x3939, 0x3520, 0x514c, 0x4f47, 0x4943,
 	0x2043, 0x4f52, 0x504f, 0x5241, 0x5449, 0x4f4e, 0x2049, 0x5350,
 	0x3130, 0x3230, 0x2049, 0x2f54, 0x2046, 0x6972, 0x6d77, 0x6172,
@@ -45,7 +45,7 @@
 	0x3031, 0x2024, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x0048,
 	0x1045, 0x0038, 0x104b, 0x0078, 0x1047, 0x0028, 0x104b, 0x20b9,
 	0x1212, 0x0078, 0x104d, 0x20b9, 0x2222, 0x20c1, 0x0008, 0x2071,
-	0x0010, 0x70c3, 0x0004, 0x20c9, 0x77ff, 0x2089, 0x1186, 0x70c7,
+	0x0010, 0x70c3, 0x0004, 0x20c9, 0x78ff, 0x2089, 0x1186, 0x70c7,
 	0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, 0x0007, 0x3f00,
 	0x70d6, 0x20c1, 0x0008, 0x2019, 0x0000, 0x2009, 0xfeff, 0x2100,
 	0x200b, 0xa5a5, 0xa1ec, 0x7fff, 0x2d64, 0x206b, 0x0a0a, 0xaddc,
@@ -59,62 +59,62 @@
 	0x118e, 0x284a, 0x263a, 0x98c0, 0xa188, 0x1000, 0x212c, 0x200b,
 	0xa5a5, 0x2114, 0xa286, 0xa5a5, 0x0040, 0x10bc, 0x250a, 0xa18a,
 	0x1000, 0x98c1, 0x0078, 0x10c1, 0x250a, 0x0078, 0x10c1, 0x2c6a,
-	0x2a5a, 0x2130, 0xa18a, 0x0040, 0x2128, 0xa1a2, 0x5100, 0x8424,
-	0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0xa192, 0x7800, 0x2009,
-	0x0000, 0x2001, 0x0031, 0x1078, 0x1cba, 0x2218, 0x2079, 0x5100,
+	0x2a5a, 0x2130, 0xa18a, 0x0040, 0x2128, 0xa1a2, 0x5200, 0x8424,
+	0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0xa192, 0x7900, 0x2009,
+	0x0000, 0x2001, 0x0031, 0x1078, 0x1d26, 0x2218, 0x2079, 0x5200,
 	0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9, 0x0040, 0x42a4, 0x8109,
 	0x00c0, 0x10dc, 0x7ef2, 0x8528, 0x7de6, 0x7cea, 0x7bee, 0x7883,
 	0x0000, 0x2031, 0x0030, 0x78cf, 0x0101, 0x780b, 0x0002, 0x780f,
-	0x0002, 0x784f, 0x0003, 0x2069, 0x5140, 0x2001, 0x04fd, 0x2004,
+	0x0002, 0x784f, 0x0003, 0x2069, 0x5240, 0x2001, 0x04fd, 0x2004,
 	0xa082, 0x0005, 0x0048, 0x1104, 0x0038, 0x1100, 0x0078, 0x1108,
 	0x681b, 0x003c, 0x0078, 0x110a, 0x00a8, 0x1108, 0x681b, 0x003c,
 	0x681b, 0x0028, 0x6807, 0x0007, 0x680b, 0x00fa, 0x680f, 0x0008,
 	0x6813, 0x0005, 0x6823, 0x0000, 0x6827, 0x0006, 0x6817, 0x0008,
-	0x682b, 0x0000, 0x681f, 0x0019, 0x2069, 0x5380, 0x2011, 0x0020,
+	0x682b, 0x0000, 0x681f, 0x0019, 0x2069, 0x5480, 0x2011, 0x0020,
 	0x2009, 0x0010, 0x680b, 0x080c, 0x680f, 0x0019, 0x6803, 0xfd00,
 	0x6807, 0x0018, 0x6a1a, 0x2d00, 0xa0e8, 0x0008, 0xa290, 0x0004,
-	0x8109, 0x00c0, 0x1122, 0x2069, 0x5400, 0x2009, 0x0002, 0x20a9,
+	0x8109, 0x00c0, 0x1122, 0x2069, 0x5500, 0x2009, 0x0002, 0x20a9,
 	0x0100, 0x6837, 0x0000, 0x680b, 0x0040, 0x7bf0, 0xa386, 0xfeff,
 	0x00c0, 0x1148, 0x6817, 0x0100, 0x681f, 0x0064, 0x0078, 0x114c,
 	0x6817, 0x0064, 0x681f, 0x0002, 0xade8, 0x0010, 0x0070, 0x1152,
-	0x0078, 0x1139, 0x8109, 0x00c0, 0x1137, 0x1078, 0x220a, 0x1078,
-	0x482c, 0x1078, 0x1963, 0x1078, 0x4d22, 0x3200, 0xa085, 0x000d,
+	0x0078, 0x1139, 0x8109, 0x00c0, 0x1137, 0x1078, 0x22a7, 0x1078,
+	0x493d, 0x1078, 0x19b5, 0x1078, 0x4e33, 0x3200, 0xa085, 0x000d,
 	0x2090, 0x70c3, 0x0000, 0x0090, 0x116c, 0x70c0, 0xa086, 0x0002,
 	0x00c0, 0x116c, 0x1078, 0x1284, 0x1078, 0x1196, 0x78cc, 0xa005,
-	0x00c0, 0x117a, 0x1078, 0x1ce3, 0x0010, 0x1180, 0x0068, 0x1180,
-	0x1078, 0x20e9, 0x0010, 0x1180, 0x0068, 0x1180, 0x1078, 0x1a48,
-	0x00e0, 0x116c, 0x1078, 0x4ba9, 0x0078, 0x116c, 0x118e, 0x1190,
-	0x240b, 0x240b, 0x48ad, 0x48ad, 0x240b, 0x240b, 0x0078, 0x118e,
+	0x00c0, 0x117a, 0x1078, 0x1d4f, 0x0010, 0x1180, 0x0068, 0x1180,
+	0x1078, 0x2186, 0x0010, 0x1180, 0x0068, 0x1180, 0x1078, 0x1ab9,
+	0x00e0, 0x116c, 0x1078, 0x4cba, 0x0078, 0x116c, 0x118e, 0x1190,
+	0x24ac, 0x24ac, 0x49be, 0x49be, 0x24ac, 0x24ac, 0x0078, 0x118e,
 	0x0078, 0x1190, 0x0078, 0x1192, 0x0078, 0x1194, 0x0068, 0x1201,
 	0x2061, 0x0000, 0x6018, 0xa084, 0x0001, 0x00c0, 0x1201, 0x7814,
 	0xa005, 0x00c0, 0x11a7, 0x0010, 0x1202, 0x0078, 0x1201, 0x2009,
-	0x515b, 0x2104, 0xa005, 0x00c0, 0x1201, 0x2009, 0x5164, 0x200b,
+	0x525b, 0x2104, 0xa005, 0x00c0, 0x1201, 0x2009, 0x5264, 0x200b,
 	0x0000, 0x7914, 0xa186, 0x0042, 0x00c0, 0x11cc, 0x7816, 0x2009,
-	0x5162, 0x2164, 0x200b, 0x0000, 0x6018, 0x70c6, 0x6014, 0x70ca,
+	0x5262, 0x2164, 0x200b, 0x0000, 0x6018, 0x70c6, 0x6014, 0x70ca,
 	0x611c, 0xa18c, 0xff00, 0x6020, 0xa084, 0x00ff, 0xa105, 0x70ce,
-	0x1078, 0x1948, 0x0078, 0x11ff, 0x7814, 0xa086, 0x0018, 0x00c0,
-	0x11d3, 0x1078, 0x165a, 0x7817, 0x0000, 0x2009, 0x5162, 0x2104,
-	0xa065, 0x0040, 0x11ef, 0x0c7e, 0x609c, 0x2060, 0x1078, 0x19b3,
-	0x0c7f, 0x609f, 0x0000, 0x1078, 0x1730, 0x2009, 0x000c, 0x6007,
-	0x0103, 0x1078, 0x1924, 0x00c0, 0x11fb, 0x1078, 0x1948, 0x2009,
-	0x5162, 0x200b, 0x0000, 0x2009, 0x515c, 0x2104, 0x200b, 0x0000,
+	0x1078, 0x199a, 0x0078, 0x11ff, 0x7814, 0xa086, 0x0018, 0x00c0,
+	0x11d3, 0x1078, 0x1678, 0x7817, 0x0000, 0x2009, 0x5262, 0x2104,
+	0xa065, 0x0040, 0x11ef, 0x0c7e, 0x609c, 0x2060, 0x1078, 0x1a17,
+	0x0c7f, 0x609f, 0x0000, 0x1078, 0x174e, 0x2009, 0x000c, 0x6007,
+	0x0103, 0x1078, 0x1976, 0x00c0, 0x11fb, 0x1078, 0x199a, 0x2009,
+	0x5262, 0x200b, 0x0000, 0x2009, 0x525c, 0x2104, 0x200b, 0x0000,
 	0xa005, 0x0040, 0x11ff, 0x2001, 0x4005, 0x0078, 0x1286, 0x0078,
 	0x1284, 0x007c, 0x70c3, 0x0000, 0x70c7, 0x0000, 0x70cb, 0x0000,
 	0x70cf, 0x0000, 0x70c0, 0xa0bc, 0xffc0, 0x00c0, 0x1252, 0x2038,
 	0x0079, 0x1212, 0x1284, 0x12e5, 0x12a9, 0x12fe, 0x130d, 0x1313,
-	0x12a0, 0x1748, 0x1317, 0x1298, 0x12ad, 0x12af, 0x12b1, 0x12b3,
-	0x174d, 0x1298, 0x1329, 0x1360, 0x1672, 0x1742, 0x12b5, 0x1591,
-	0x15ad, 0x15c9, 0x15f4, 0x154a, 0x1558, 0x156c, 0x1580, 0x13df,
-	0x1298, 0x138d, 0x1393, 0x1398, 0x139d, 0x13a3, 0x13a8, 0x13ad,
-	0x13b2, 0x13b7, 0x13bb, 0x13d0, 0x13dc, 0x1298, 0x1298, 0x1298,
-	0x1298, 0x13eb, 0x13f4, 0x1403, 0x1429, 0x1433, 0x143a, 0x1480,
-	0x148f, 0x149e, 0x14b0, 0x152a, 0x153a, 0x1298, 0x1298, 0x1298,
-	0x1298, 0x153f, 0xa0bc, 0xffa0, 0x00c0, 0x1298, 0x2038, 0xa084,
-	0x001f, 0x0079, 0x125b, 0x1786, 0x1789, 0x1799, 0x1298, 0x1298,
-	0x18df, 0x18fc, 0x1298, 0x1298, 0x1298, 0x1900, 0x1908, 0x1298,
-	0x1298, 0x1298, 0x1298, 0x12db, 0x12f4, 0x131f, 0x1356, 0x1668,
-	0x1764, 0x1778, 0x1298, 0x1829, 0x190e, 0x18bb, 0x18c5, 0x18c9,
-	0x18d7, 0x1298, 0x1298, 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0078,
+	0x12a0, 0x1766, 0x1317, 0x1298, 0x12ad, 0x12af, 0x12b1, 0x12b3,
+	0x176b, 0x1298, 0x1329, 0x1365, 0x1690, 0x1760, 0x12b5, 0x15af,
+	0x15cb, 0x15e7, 0x1612, 0x1568, 0x1576, 0x158a, 0x159e, 0x13e9,
+	0x1298, 0x1397, 0x139d, 0x13a2, 0x13a7, 0x13ad, 0x13b2, 0x13b7,
+	0x13bc, 0x13c1, 0x13c5, 0x13da, 0x13e6, 0x1298, 0x1298, 0x1298,
+	0x1298, 0x13f5, 0x13fe, 0x140d, 0x1451, 0x145b, 0x1462, 0x14a8,
+	0x14b7, 0x14c6, 0x14d8, 0x1548, 0x1558, 0x1298, 0x1298, 0x1298,
+	0x1298, 0x155d, 0xa0bc, 0xffa0, 0x00c0, 0x1298, 0x2038, 0xa084,
+	0x001f, 0x0079, 0x125b, 0x17a4, 0x17a7, 0x17b7, 0x1298, 0x1298,
+	0x1931, 0x194e, 0x1298, 0x1298, 0x1298, 0x1952, 0x195a, 0x1298,
+	0x1298, 0x1298, 0x1298, 0x12db, 0x12f4, 0x131f, 0x135b, 0x1686,
+	0x1782, 0x1796, 0x1298, 0x1847, 0x1960, 0x190d, 0x1917, 0x191b,
+	0x1929, 0x1298, 0x1298, 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0078,
 	0x1286, 0x73ce, 0x72ca, 0x71c6, 0x2001, 0x4000, 0x70c2, 0x0068,
 	0x1287, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x5000, 0x00e0,
 	0x128f, 0x00e0, 0x1291, 0x0068, 0x1291, 0x2091, 0x4080, 0x007c,
@@ -126,1974 +126,2005 @@
 	0x0007, 0x3f00, 0x70d6, 0x2079, 0x0000, 0x781b, 0x0001, 0x2031,
 	0x0030, 0x2059, 0x1000, 0x2029, 0x0457, 0x2051, 0x0470, 0x2061,
 	0x0472, 0x20b9, 0xffff, 0x20c1, 0x0000, 0x2091, 0x5000, 0x2091,
-	0x4080, 0x0078, 0x0455, 0x1078, 0x1b53, 0x00c0, 0x129c, 0x75d8,
+	0x4080, 0x0078, 0x0455, 0x1078, 0x1bc4, 0x00c0, 0x129c, 0x75d8,
 	0x74dc, 0x75da, 0x74de, 0x0078, 0x12e8, 0x2029, 0x0000, 0x2520,
-	0x71d0, 0x73c8, 0x72cc, 0x70c4, 0x1078, 0x1a8d, 0x0040, 0x1284,
-	0x70c3, 0x4002, 0x0078, 0x1284, 0x1078, 0x1b53, 0x00c0, 0x129c,
+	0x71d0, 0x73c8, 0x72cc, 0x70c4, 0x1078, 0x1afe, 0x0040, 0x1284,
+	0x70c3, 0x4002, 0x0078, 0x1284, 0x1078, 0x1bc4, 0x00c0, 0x129c,
 	0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x1301, 0x2029, 0x0000,
-	0x2520, 0x71d0, 0x73c8, 0x72cc, 0x70c4, 0x1078, 0x1aed, 0x0040,
+	0x2520, 0x71d0, 0x73c8, 0x72cc, 0x70c4, 0x1078, 0x1b5e, 0x0040,
 	0x1284, 0x70c3, 0x4002, 0x0078, 0x1284, 0x71c4, 0x70c8, 0x2114,
 	0x200a, 0x0078, 0x1282, 0x71c4, 0x2114, 0x0078, 0x1282, 0x70c7,
-	0x0007, 0x70cb, 0x0041, 0x70cf, 0x0000, 0x0078, 0x1284, 0x1078,
-	0x1b53, 0x00c0, 0x129c, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078,
+	0x0007, 0x70cb, 0x0041, 0x70cf, 0x0006, 0x0078, 0x1284, 0x1078,
+	0x1bc4, 0x00c0, 0x129c, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078,
 	0x132c, 0x2029, 0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d0,
-	0x70c6, 0x72ca, 0x73ce, 0x74d2, 0xa005, 0x0040, 0x1350, 0x8001,
-	0x7892, 0xa084, 0xfc00, 0x0040, 0x1345, 0x78cc, 0xa085, 0x0001,
-	0x78ce, 0x2001, 0x4005, 0x0078, 0x1286, 0x7a9a, 0x7b9e, 0x7da2,
-	0x7ea6, 0x7c96, 0x78cc, 0xa084, 0xfffc, 0x78ce, 0x0078, 0x1354,
-	0x78cc, 0xa085, 0x0001, 0x78ce, 0x0078, 0x1284, 0x1078, 0x1b53,
-	0x00c0, 0x129c, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078, 0x1363,
-	0x2029, 0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d4, 0x70c6,
-	0x72ca, 0x73ce, 0x74d6, 0xa005, 0x0040, 0x1387, 0x8001, 0x78ae,
-	0xa084, 0xfc00, 0x0040, 0x137c, 0x78cc, 0xa085, 0x0100, 0x78ce,
-	0x2001, 0x4005, 0x0078, 0x1286, 0x7ab6, 0x7bba, 0x7dbe, 0x7ec2,
-	0x7cb2, 0x78cc, 0xa084, 0xfcff, 0x78ce, 0x0078, 0x138b, 0x78cc,
-	0xa085, 0x0100, 0x78ce, 0x0078, 0x1284, 0x2009, 0x5161, 0x210c,
-	0x7aec, 0x0078, 0x1282, 0x2009, 0x5141, 0x210c, 0x0078, 0x1283,
-	0x2009, 0x5142, 0x210c, 0x0078, 0x1283, 0x2061, 0x5140, 0x610c,
-	0x6210, 0x0078, 0x1282, 0x2009, 0x5145, 0x210c, 0x0078, 0x1283,
-	0x2009, 0x5146, 0x210c, 0x0078, 0x1283, 0x2009, 0x5148, 0x210c,
-	0x0078, 0x1283, 0x2009, 0x5149, 0x210c, 0x0078, 0x1283, 0x7908,
-	0x7a0c, 0x0078, 0x1282, 0x71c4, 0x8107, 0xa084, 0x000f, 0x8003,
-	0x8003, 0x8003, 0xa0e8, 0x5380, 0x6a00, 0x6804, 0xa084, 0x0008,
-	0x0040, 0x13cd, 0x6b08, 0x0078, 0x13ce, 0x6b0c, 0x0078, 0x1281,
-	0x77c4, 0x1078, 0x1973, 0x2091, 0x8000, 0x6b1c, 0x6a14, 0x2091,
-	0x8001, 0x2708, 0x0078, 0x1281, 0x794c, 0x0078, 0x1283, 0x77c4,
-	0x1078, 0x1973, 0x2091, 0x8000, 0x6908, 0x6a18, 0x6b10, 0x2091,
-	0x8001, 0x0078, 0x1281, 0x71c4, 0xa182, 0x0010, 0x00c8, 0x127c,
-	0x1078, 0x22e2, 0x0078, 0x1281, 0x71c4, 0xa182, 0x0010, 0x00c8,
-	0x127c, 0x2011, 0x5141, 0x2204, 0x007e, 0x2112, 0x1078, 0x229b,
-	0x017f, 0x0078, 0x1283, 0x71c4, 0x2011, 0x1421, 0x20a9, 0x0008,
-	0x2204, 0xa106, 0x0040, 0x1413, 0x8210, 0x0070, 0x1411, 0x0078,
-	0x1408, 0x0078, 0x127c, 0xa292, 0x1421, 0x027e, 0x2011, 0x5142,
-	0x2204, 0x2112, 0x017f, 0x007e, 0x1078, 0x22a7, 0x017f, 0x0078,
+	0x70c6, 0x72ca, 0x73ce, 0x74d2, 0xa005, 0x0040, 0x1355, 0xa40a,
+	0x0040, 0x133c, 0x00c8, 0x1346, 0x8001, 0x7892, 0xa084, 0xfc00,
+	0x0040, 0x134a, 0x78cc, 0xa085, 0x0001, 0x78ce, 0x2001, 0x4005,
+	0x0078, 0x1286, 0x7a9a, 0x7b9e, 0x7da2, 0x7ea6, 0x7c96, 0x78cc,
+	0xa084, 0xfffc, 0x78ce, 0x0078, 0x1359, 0x78cc, 0xa085, 0x0001,
+	0x78ce, 0x0078, 0x1284, 0x1078, 0x1bc4, 0x00c0, 0x129c, 0x75d8,
+	0x76dc, 0x75da, 0x76de, 0x0078, 0x1368, 0x2029, 0x0000, 0x2530,
+	0x70c4, 0x72c8, 0x73cc, 0x74d4, 0x70c6, 0x72ca, 0x73ce, 0x74d6,
+	0xa005, 0x0040, 0x1391, 0xa40a, 0x0040, 0x1378, 0x00c8, 0x1382,
+	0x8001, 0x78ae, 0xa084, 0xfc00, 0x0040, 0x1386, 0x78cc, 0xa085,
+	0x0100, 0x78ce, 0x2001, 0x4005, 0x0078, 0x1286, 0x7ab6, 0x7bba,
+	0x7dbe, 0x7ec2, 0x7cb2, 0x78cc, 0xa084, 0xfcff, 0x78ce, 0x0078,
+	0x1395, 0x78cc, 0xa085, 0x0100, 0x78ce, 0x0078, 0x1284, 0x2009,
+	0x5261, 0x210c, 0x7aec, 0x0078, 0x1282, 0x2009, 0x5241, 0x210c,
+	0x0078, 0x1283, 0x2009, 0x5242, 0x210c, 0x0078, 0x1283, 0x2061,
+	0x5240, 0x610c, 0x6210, 0x0078, 0x1282, 0x2009, 0x5245, 0x210c,
+	0x0078, 0x1283, 0x2009, 0x5246, 0x210c, 0x0078, 0x1283, 0x2009,
+	0x5248, 0x210c, 0x0078, 0x1283, 0x2009, 0x5249, 0x210c, 0x0078,
+	0x1283, 0x7908, 0x7a0c, 0x0078, 0x1282, 0x71c4, 0x8107, 0xa084,
+	0x000f, 0x8003, 0x8003, 0x8003, 0xa0e8, 0x5480, 0x6a00, 0x6804,
+	0xa084, 0x0008, 0x0040, 0x13d7, 0x6b08, 0x0078, 0x13d8, 0x6b0c,
+	0x0078, 0x1281, 0x77c4, 0x1078, 0x19c5, 0x2091, 0x8000, 0x6b1c,
+	0x6a14, 0x2091, 0x8001, 0x2708, 0x0078, 0x1281, 0x794c, 0x0078,
+	0x1283, 0x77c4, 0x1078, 0x19c5, 0x2091, 0x8000, 0x6908, 0x6a18,
+	0x6b10, 0x2091, 0x8001, 0x0078, 0x1281, 0x71c4, 0xa182, 0x0010,
+	0x00c8, 0x127c, 0x1078, 0x237f, 0x0078, 0x1281, 0x71c4, 0xa182,
+	0x0010, 0x00c8, 0x127c, 0x2011, 0x5241, 0x2204, 0x007e, 0x2112,
+	0x1078, 0x2338, 0x017f, 0x0078, 0x1283, 0x71c4, 0x2019, 0x0100,
+	0x2304, 0xa082, 0x0006, 0x0048, 0x141b, 0x2011, 0x1449, 0x20a9,
+	0x0008, 0x0078, 0x141f, 0x2011, 0x1441, 0x20a9, 0x0008, 0x2204,
+	0xa106, 0x0040, 0x142a, 0x8210, 0x0070, 0x1428, 0x0078, 0x141f,
+	0x0078, 0x127c, 0x2304, 0xa082, 0x0006, 0x0048, 0x1433, 0xa292,
+	0x1449, 0x0078, 0x1435, 0xa292, 0x1441, 0x027e, 0x2011, 0x5242,
+	0x2204, 0x2112, 0x017f, 0x007e, 0x1078, 0x2344, 0x017f, 0x0078,
 	0x1283, 0x03e8, 0x00fa, 0x01f4, 0x02ee, 0x0064, 0x0019, 0x0032,
-	0x004b, 0x2061, 0x5140, 0x610c, 0x6210, 0x70c4, 0x600e, 0x70c8,
-	0x6012, 0x0078, 0x1282, 0x2061, 0x5140, 0x6114, 0x70c4, 0x6016,
-	0x0078, 0x1283, 0x2061, 0x5140, 0x71c4, 0x2011, 0x0004, 0x601f,
-	0x0019, 0x2019, 0x1212, 0xa186, 0x0028, 0x0040, 0x145b, 0x2011,
+	0x004b, 0x03e8, 0x00fa, 0x01f4, 0x02ee, 0x0004, 0x0001, 0x0002,
+	0x0003, 0x2061, 0x5240, 0x610c, 0x6210, 0x70c4, 0x600e, 0x70c8,
+	0x6012, 0x0078, 0x1282, 0x2061, 0x5240, 0x6114, 0x70c4, 0x6016,
+	0x0078, 0x1283, 0x2061, 0x5240, 0x71c4, 0x2011, 0x0004, 0x601f,
+	0x0019, 0x2019, 0x1212, 0xa186, 0x0028, 0x0040, 0x1483, 0x2011,
 	0x0005, 0x601f, 0x0019, 0x2019, 0x1212, 0xa186, 0x0032, 0x0040,
-	0x145b, 0x2011, 0x0006, 0x601f, 0x000c, 0x2019, 0x2222, 0xa186,
+	0x1483, 0x2011, 0x0006, 0x601f, 0x000c, 0x2019, 0x2222, 0xa186,
 	0x003c, 0x00c0, 0x127c, 0x6018, 0x007e, 0x611a, 0x7800, 0xa084,
-	0x0001, 0x00c0, 0x1476, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005,
-	0x0048, 0x146e, 0x0038, 0x1472, 0x0078, 0x1476, 0x0028, 0x1472,
-	0x0078, 0x1476, 0x2019, 0x2222, 0x0078, 0x1478, 0x2019, 0x1212,
-	0x23b8, 0x1078, 0x22b8, 0x1078, 0x4d22, 0x017f, 0x0078, 0x1283,
-	0x71c4, 0xa184, 0xffcf, 0x00c0, 0x127c, 0x2011, 0x5148, 0x2204,
-	0x2112, 0x007e, 0x1078, 0x22da, 0x017f, 0x0078, 0x1283, 0x71c4,
-	0xa182, 0x0010, 0x00c8, 0x127c, 0x2011, 0x5149, 0x2204, 0x007e,
-	0x2112, 0x1078, 0x22c9, 0x017f, 0x0078, 0x1283, 0x71c4, 0x72c8,
+	0x0001, 0x00c0, 0x149e, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005,
+	0x0048, 0x1496, 0x0038, 0x149a, 0x0078, 0x149e, 0x0028, 0x149a,
+	0x0078, 0x149e, 0x2019, 0x2222, 0x0078, 0x14a0, 0x2019, 0x1212,
+	0x23b8, 0x1078, 0x2355, 0x1078, 0x4e33, 0x017f, 0x0078, 0x1283,
+	0x71c4, 0xa184, 0xffcf, 0x00c0, 0x127c, 0x2011, 0x5248, 0x2204,
+	0x2112, 0x007e, 0x1078, 0x2377, 0x017f, 0x0078, 0x1283, 0x71c4,
+	0xa182, 0x0010, 0x00c8, 0x127c, 0x2011, 0x5249, 0x2204, 0x007e,
+	0x2112, 0x1078, 0x2366, 0x017f, 0x0078, 0x1283, 0x71c4, 0x72c8,
 	0xa184, 0xfffd, 0x00c0, 0x127b, 0xa284, 0xfffd, 0x00c0, 0x127b,
 	0x2100, 0x7908, 0x780a, 0x2200, 0x7a0c, 0x780e, 0x0078, 0x1282,
 	0x71c4, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e8,
-	0x5380, 0x2019, 0x0000, 0x72c8, 0xa284, 0x0080, 0x0040, 0x14c6,
-	0x6c14, 0x84ff, 0x00c0, 0x14c6, 0x6817, 0x0040, 0xa284, 0x0040,
-	0x0040, 0x14d0, 0x6c10, 0x84ff, 0x00c0, 0x14d0, 0x6813, 0x0001,
-	0x6800, 0x007e, 0xa226, 0x0040, 0x14f3, 0x6a02, 0xa484, 0x2000,
-	0x0040, 0x14dc, 0xa39d, 0x0010, 0xa484, 0x1000, 0x0040, 0x14e2,
-	0xa39d, 0x0008, 0xa484, 0x4000, 0x0040, 0x14f3, 0x810f, 0xa284,
-	0x4000, 0x0040, 0x14ef, 0x1078, 0x22fc, 0x0078, 0x14f3, 0x1078,
-	0x22ee, 0x0078, 0x14f3, 0x72cc, 0x6808, 0xa206, 0x0040, 0x1522,
-	0xa2a4, 0x00ff, 0x2061, 0x5140, 0x6118, 0xa186, 0x0028, 0x0040,
-	0x1509, 0xa186, 0x0032, 0x0040, 0x150f, 0xa186, 0x003c, 0x0040,
-	0x1515, 0xa482, 0x0064, 0x0048, 0x151f, 0x0078, 0x1519, 0xa482,
-	0x0050, 0x0048, 0x151f, 0x0078, 0x1519, 0xa482, 0x0043, 0x0048,
-	0x151f, 0x71c4, 0x71c6, 0x027f, 0x72ca, 0x0078, 0x127d, 0x6a0a,
-	0xa39d, 0x000a, 0x6804, 0xa305, 0x6806, 0x027f, 0x6b0c, 0x71c4,
-	0x0078, 0x1281, 0x77c4, 0x1078, 0x1973, 0x2091, 0x8000, 0x6a14,
-	0x6b1c, 0x2091, 0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e, 0x2708,
-	0x0078, 0x1281, 0x70c4, 0x794c, 0x784e, 0x0078, 0x1283, 0x71c4,
-	0x72c8, 0x73cc, 0xa182, 0x0010, 0x00c8, 0x127c, 0x1078, 0x230a,
-	0x0078, 0x1281, 0x77c4, 0x1078, 0x1973, 0x2091, 0x8000, 0x6a08,
-	0xa295, 0x0002, 0x6a0a, 0x2091, 0x8001, 0x2708, 0x0078, 0x1282,
-	0x77c4, 0x1078, 0x1973, 0x2091, 0x8000, 0x6a08, 0xa294, 0xfff9,
-	0x6a0a, 0x6804, 0xa005, 0x0040, 0x1567, 0x1078, 0x21d2, 0x2091,
-	0x8001, 0x2708, 0x0078, 0x1282, 0x77c4, 0x1078, 0x1973, 0x2091,
-	0x8000, 0x6a08, 0xa295, 0x0004, 0x6a0a, 0x6804, 0xa005, 0x0040,
-	0x157b, 0x1078, 0x21d2, 0x2091, 0x8001, 0x2708, 0x0078, 0x1282,
-	0x77c4, 0x2041, 0x0001, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091,
-	0x8000, 0x1078, 0x1980, 0x2091, 0x8001, 0x2708, 0x6a08, 0x0078,
-	0x1282, 0x77c4, 0x72c8, 0x73cc, 0x77c6, 0x72ca, 0x73ce, 0x1078,
-	0x19e1, 0x00c0, 0x15a9, 0x6818, 0xa005, 0x0040, 0x15a9, 0x2708,
-	0x1078, 0x231a, 0x00c0, 0x15a9, 0x7817, 0x0015, 0x2091, 0x8001,
-	0x007c, 0x2091, 0x8001, 0x0078, 0x1284, 0x77c4, 0x77c6, 0x2041,
-	0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078,
-	0x1980, 0x2061, 0x5140, 0x606f, 0x0003, 0x6782, 0x6093, 0x000f,
-	0x6073, 0x0000, 0x7817, 0x0016, 0x1078, 0x21d2, 0x2091, 0x8001,
-	0x007c, 0x77c8, 0x77ca, 0x77c4, 0x77c6, 0xa7bc, 0xff00, 0x2091,
-	0x8000, 0x2061, 0x5140, 0x606f, 0x0002, 0x6073, 0x0000, 0x6782,
-	0x6093, 0x000f, 0x7817, 0x0017, 0x1078, 0x21d2, 0x2091, 0x8001,
-	0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0010, 0x2091, 0x8000,
-	0x1078, 0x1980, 0x70c8, 0x6836, 0x8738, 0xa784, 0x001f, 0x00c0,
-	0x15e8, 0x2091, 0x8001, 0x007c, 0x78cc, 0xa084, 0x0003, 0x00c0,
-	0x1618, 0x2039, 0x0000, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051,
-	0x0008, 0x1078, 0x1973, 0x2091, 0x8000, 0x6808, 0xa80d, 0x690a,
-	0x2091, 0x8001, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1601, 0xa7bc,
-	0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, 0x1601,
-	0x2091, 0x8000, 0x2069, 0x0100, 0x6830, 0xa084, 0x0040, 0x0040,
-	0x1641, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0004,
-	0x0040, 0x162e, 0x0070, 0x162e, 0x0078, 0x1625, 0x684b, 0x0009,
-	0x20a9, 0x0014, 0x6848, 0xa084, 0x0001, 0x0040, 0x163b, 0x0070,
-	0x163b, 0x0078, 0x1632, 0x20a9, 0x00fa, 0x0070, 0x1641, 0x0078,
-	0x163d, 0x2079, 0x5100, 0x7817, 0x0018, 0x2061, 0x5140, 0x606f,
-	0x0001, 0x6073, 0x0000, 0x6093, 0x000f, 0x78cc, 0xa085, 0x0002,
-	0x78ce, 0x6808, 0xa084, 0xfffd, 0x680a, 0x681b, 0x0048, 0x2091,
-	0x8001, 0x007c, 0x78cc, 0xa084, 0xfffd, 0x78ce, 0xa084, 0x0001,
-	0x00c0, 0x1664, 0x1078, 0x1a2b, 0x71c4, 0x71c6, 0x794a, 0x007c,
-	0x1078, 0x1b53, 0x00c0, 0x129c, 0x75d8, 0x74dc, 0x75da, 0x74de,
-	0x0078, 0x1675, 0x2029, 0x0000, 0x2520, 0x71c4, 0x73c8, 0x72cc,
-	0x71c6, 0x73ca, 0x72ce, 0x2079, 0x5100, 0x2091, 0x8000, 0x1078,
-	0x192e, 0x2091, 0x8001, 0x0040, 0x172c, 0x20a9, 0x0005, 0x20a1,
-	0x5118, 0x2091, 0x8000, 0x41a1, 0x2091, 0x8001, 0x2009, 0x0020,
-	0x1078, 0x1929, 0x0040, 0x1698, 0x1078, 0x1948, 0x0078, 0x172c,
-	0x6004, 0xa084, 0xff00, 0x8007, 0x8009, 0x0040, 0x16fb, 0x0c7e,
-	0x2c68, 0x2091, 0x8000, 0x1078, 0x192e, 0x2091, 0x8001, 0x0040,
-	0x16cc, 0x2c00, 0x689e, 0x8109, 0x00c0, 0x16a0, 0x609f, 0x0000,
-	0x0c7f, 0x0c7e, 0x7218, 0x731c, 0x7420, 0x7524, 0x2c68, 0x689c,
-	0xa065, 0x0040, 0x16fa, 0x2009, 0x0020, 0x1078, 0x1929, 0x00c0,
-	0x16e3, 0x6004, 0xa084, 0x00ff, 0xa086, 0x0002, 0x00c0, 0x16cc,
-	0x2d00, 0x6002, 0x0078, 0x16b2, 0x0c7f, 0x0c7e, 0x609c, 0x2060,
-	0x1078, 0x19b3, 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1730, 0x2009,
-	0x000c, 0x6008, 0xa085, 0x0200, 0x600a, 0x1078, 0x1924, 0x1078,
-	0x1948, 0x0078, 0x172c, 0x0c7f, 0x0c7e, 0x609c, 0x2060, 0x1078,
-	0x19b3, 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1730, 0x2009, 0x000c,
-	0x6007, 0x0103, 0x601b, 0x0003, 0x1078, 0x1924, 0x1078, 0x1948,
-	0x0078, 0x172c, 0x0c7f, 0x74c4, 0x73c8, 0x72cc, 0x6014, 0x2091,
-	0x8000, 0x7817, 0x0012, 0x0e7e, 0x2071, 0x5140, 0x706f, 0x0005,
-	0x7073, 0x0000, 0x7376, 0x727a, 0x747e, 0x7082, 0x7087, 0x0000,
-	0x2c00, 0x708a, 0x708f, 0x0000, 0xa02e, 0x2530, 0x611c, 0x61a2,
-	0xa184, 0x0060, 0x0040, 0x171e, 0x1078, 0x47c2, 0x0e7f, 0x6596,
-	0x65a6, 0x669a, 0x66aa, 0x60af, 0x0000, 0x60b3, 0x0000, 0x1078,
-	0x21d2, 0x2091, 0x8001, 0x007c, 0x70c3, 0x4005, 0x0078, 0x1287,
-	0x20a9, 0x0005, 0x2099, 0x5118, 0x2091, 0x8000, 0x530a, 0x2091,
-	0x8001, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9,
-	0x0000, 0x007c, 0x71c4, 0x70c7, 0x0000, 0x7906, 0x0078, 0x1284,
-	0x71c4, 0x71c6, 0x2168, 0x0078, 0x174f, 0x2069, 0x1000, 0x690c,
-	0xa016, 0x2d04, 0xa210, 0x8d68, 0x8109, 0x00c0, 0x1751, 0xa285,
-	0x0000, 0x00c0, 0x175f, 0x70c3, 0x4000, 0x0078, 0x1761, 0x70c3,
-	0x4003, 0x70ca, 0x0078, 0x1287, 0x2011, 0x5167, 0x220c, 0x70c4,
-	0x8003, 0x0048, 0x1771, 0x1078, 0x3b7f, 0xa184, 0x7fff, 0x0078,
-	0x1775, 0x1078, 0x3b72, 0xa185, 0x8000, 0x2012, 0x0078, 0x1283,
-	0x71c4, 0x1078, 0x3b69, 0x6100, 0x2001, 0x5167, 0x2004, 0xa084,
-	0x8000, 0xa10d, 0x6204, 0x6308, 0x0078, 0x1281, 0x79e4, 0x0078,
-	0x1283, 0x71c4, 0x71c6, 0x2198, 0x20a1, 0x0042, 0x20a9, 0x0004,
-	0x53a3, 0x21a0, 0x2099, 0x0042, 0x20a9, 0x0004, 0x53a3, 0x0078,
-	0x1284, 0x70c4, 0x2068, 0x2079, 0x5100, 0x2091, 0x8000, 0x1078,
-	0x192e, 0x2091, 0x8001, 0x0040, 0x1825, 0x6007, 0x0001, 0x600b,
-	0x0000, 0x602b, 0x0000, 0x601b, 0x0006, 0x6a10, 0xa28c, 0x000f,
-	0xa284, 0x00f0, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0x6016,
-	0xa284, 0x0800, 0x0040, 0x17c0, 0x601b, 0x000a, 0x0078, 0x17c6,
-	0xa284, 0x1000, 0x0040, 0x17c6, 0x601b, 0x000c, 0xa284, 0x0300,
-	0x0040, 0x17cf, 0x602b, 0x0001, 0x8004, 0x8004, 0x8004, 0xa085,
-	0x0001, 0x601e, 0x6023, 0x0000, 0x6027, 0x0000, 0xa284, 0x0400,
-	0x0040, 0x17dc, 0x602b, 0x0000, 0x20a9, 0x0006, 0xac80, 0x000b,
-	0x20a0, 0xad80, 0x0005, 0x2098, 0x53a3, 0xa284, 0x0300, 0x00c0,
-	0x17f1, 0x6046, 0x604a, 0x604e, 0x6052, 0x6096, 0x609a, 0x0078,
-	0x17fb, 0x6800, 0x6046, 0x6804, 0x604a, 0x6e08, 0x664e, 0x6d0c,
-	0x6552, 0x6596, 0x669a, 0x6014, 0x2091, 0x8000, 0x7817, 0x0042,
-	0x2c08, 0x2061, 0x5140, 0x606f, 0x0005, 0x6073, 0x0000, 0x6077,
-	0x0000, 0x607b, 0x0000, 0x607f, 0x0000, 0x6082, 0x618a, 0xa284,
-	0x0400, 0x608e, 0x2091, 0x8001, 0x0e7e, 0x2071, 0x0020, 0x7007,
-	0x000a, 0x7007, 0x0002, 0x7003, 0x0000, 0x0e7f, 0x2091, 0x8000,
-	0x1078, 0x21d2, 0x2091, 0x8001, 0x007c, 0x70c3, 0x4005, 0x0078,
-	0x1287, 0x0c7e, 0x0d7e, 0x0e7e, 0x0f7e, 0x2091, 0x8000, 0x2071,
-	0x5140, 0x2079, 0x0100, 0x2061, 0x0010, 0x70a0, 0xa06d, 0x0040,
-	0x18b1, 0x6a04, 0xa294, 0x00ff, 0xa286, 0x0007, 0x0040, 0x1844,
-	0xa286, 0x000f, 0x00c0, 0x18b1, 0x691c, 0xa184, 0x0080, 0x00c0,
-	0x18b1, 0x6824, 0xa18c, 0xff00, 0xa085, 0x0019, 0x6826, 0x71b0,
-	0x81ff, 0x0040, 0x1867, 0x0d7e, 0x2069, 0x0020, 0x6807, 0x0010,
-	0x6908, 0x6808, 0xa106, 0x00c0, 0x1858, 0x690c, 0x680c, 0xa106,
-	0x00c0, 0x185d, 0xa184, 0x00ff, 0x00c0, 0x185d, 0x0d7f, 0x78b8,
-	0xa084, 0x801f, 0x00c0, 0x1867, 0x7848, 0xa085, 0x000c, 0x784a,
-	0x71b0, 0x81ff, 0x0040, 0x188a, 0x70b3, 0x0000, 0x0d7e, 0x2069,
-	0x0020, 0x6807, 0x0018, 0x6804, 0xa084, 0x0008, 0x00c0, 0x187b,
-	0x6807, 0x0008, 0x6804, 0xa084, 0x0008, 0x00c0, 0x1882, 0x6807,
-	0x0002, 0x0d7f, 0x61c4, 0x62c8, 0x63cc, 0x61c6, 0x62ca, 0x63ce,
-	0x0e7e, 0x2071, 0x5100, 0x7266, 0x736a, 0xae80, 0x0019, 0x0e7f,
-	0x7848, 0xa084, 0x000c, 0x00c0, 0x1898, 0x1078, 0x46db, 0x78a3,
-	0x0000, 0x7858, 0xa084, 0xedff, 0x785a, 0x70b4, 0xa080, 0x00df,
-	0x781a, 0x0f7f, 0x0e7f, 0x0d7f, 0x0c7f, 0x2091, 0x8001, 0x0078,
-	0x1284, 0x0f7f, 0x0e7f, 0x0d7f, 0x0c7f, 0x2091, 0x8001, 0x2001,
-	0x4005, 0x0078, 0x1286, 0x7980, 0x71c6, 0x71c4, 0xa182, 0x0003,
-	0x00c8, 0x127c, 0x7982, 0x0078, 0x1284, 0x7980, 0x71c6, 0x0078,
-	0x1284, 0x7974, 0x71c6, 0x71c4, 0x7976, 0x7978, 0x71ca, 0x71c8,
-	0x797a, 0x797c, 0x71ce, 0x71cc, 0x797e, 0x0078, 0x1284, 0x7974,
-	0x71c6, 0x7978, 0x71ca, 0x797c, 0x71ce, 0x0078, 0x1284, 0x7900,
-	0x71c6, 0x71c4, 0x7902, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005,
-	0x0048, 0x18ee, 0x0038, 0x18f0, 0x0078, 0x18fa, 0x00a8, 0x18fa,
-	0xa18c, 0x0001, 0x00c0, 0x18f8, 0x20b9, 0x2222, 0x0078, 0x18fa,
-	0x20b9, 0x1212, 0x0078, 0x1284, 0x7900, 0x71c6, 0x0078, 0x1284,
-	0x2009, 0x5174, 0x2104, 0x70c6, 0x70c4, 0x200a, 0x0078, 0x1284,
-	0x2009, 0x5174, 0x2104, 0x70c6, 0x0078, 0x1284, 0x71c4, 0x8107,
-	0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e8, 0x5380, 0x6a14,
-	0xd2b4, 0x0040, 0x191f, 0x2011, 0x0001, 0x0078, 0x1921, 0x2011,
-	0x0000, 0x6b0c, 0x0078, 0x1281, 0xac80, 0x0001, 0x1078, 0x1b0f,
-	0x007c, 0xac80, 0x0001, 0x1078, 0x1aaf, 0x007c, 0x7850, 0xa065,
-	0x0040, 0x1936, 0x2c04, 0x7852, 0x2063, 0x0000, 0x007c, 0x0f7e,
-	0x2079, 0x5100, 0x7850, 0xa06d, 0x0040, 0x1946, 0x2d04, 0x7852,
-	0x6803, 0x0000, 0x6807, 0x0000, 0x680b, 0x0000, 0x0f7f, 0x007c,
-	0x2091, 0x8000, 0x0f7e, 0x2079, 0x5100, 0x7850, 0x2062, 0x2c00,
-	0xa005, 0x00c0, 0x1955, 0x1078, 0x23eb, 0x7852, 0x0f7f, 0x2091,
-	0x8001, 0x007c, 0x0f7e, 0x2079, 0x5100, 0x7850, 0x206a, 0x2d00,
-	0x7852, 0x0f7f, 0x007c, 0x2011, 0x7800, 0x7a52, 0x7bec, 0x8319,
-	0x0040, 0x1970, 0xa280, 0x0031, 0x2012, 0x2010, 0x0078, 0x1967,
-	0x2013, 0x0000, 0x007c, 0xa784, 0x0f00, 0x800b, 0xa784, 0x001f,
-	0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa0e8, 0x5400, 0x007c,
-	0x1078, 0x1973, 0x2900, 0x682a, 0x2a00, 0x682e, 0x6808, 0xa084,
-	0xffef, 0xa80d, 0x690a, 0x2009, 0x5152, 0x210c, 0x6804, 0xa005,
-	0x0040, 0x19b2, 0xa116, 0x00c0, 0x199d, 0x2060, 0x6000, 0x6806,
-	0x017e, 0x200b, 0x0000, 0x0078, 0x19a0, 0x2009, 0x0000, 0x017e,
-	0x6804, 0xa065, 0x0040, 0x19af, 0x6000, 0x6806, 0x1078, 0x19c0,
-	0x1078, 0x1c5f, 0x6810, 0x8001, 0x6812, 0x00c0, 0x19a0, 0x017f,
-	0x6902, 0x6906, 0x007c, 0xa065, 0x0040, 0x19bf, 0x609c, 0x609f,
-	0x0000, 0x2008, 0x1078, 0x1948, 0x2100, 0x0078, 0x19b3, 0x007c,
-	0x6007, 0x0103, 0x608f, 0x0000, 0x20a9, 0x001c, 0xac80, 0x0005,
-	0x20a0, 0x2001, 0x0000, 0x40a4, 0x6828, 0x601a, 0x682c, 0x6022,
-	0x007c, 0x0e7e, 0x2071, 0x5140, 0x704c, 0xa08c, 0x0200, 0x00c0,
-	0x19df, 0xa088, 0x5180, 0x2d0a, 0x8000, 0x704e, 0xa006, 0x0e7f,
-	0x007c, 0x1078, 0x1973, 0x2091, 0x8000, 0x6804, 0x781e, 0xa065,
-	0x0040, 0x1a2a, 0x0078, 0x19f2, 0x2c00, 0x781e, 0x6000, 0xa065,
-	0x0040, 0x1a2a, 0x600c, 0xa306, 0x00c0, 0x19ec, 0x6010, 0xa206,
-	0x00c0, 0x19ec, 0x2c28, 0x2001, 0x5152, 0x2004, 0xac06, 0x00c0,
-	0x1a03, 0x0078, 0x1a28, 0x6804, 0xac06, 0x00c0, 0x1a10, 0x6000,
-	0xa065, 0x6806, 0x00c0, 0x1a1a, 0x6803, 0x0000, 0x0078, 0x1a1a,
-	0x6400, 0x781c, 0x2060, 0x6402, 0xa486, 0x0000, 0x00c0, 0x1a1a,
-	0x2c00, 0x6802, 0x2560, 0x1078, 0x19c0, 0x601b, 0x0005, 0x6023,
-	0x0020, 0x1078, 0x1c5f, 0x6810, 0x8001, 0x1050, 0x23eb, 0x6812,
-	0xa085, 0xffff, 0x007c, 0x2039, 0x0000, 0x2041, 0x0021, 0x2049,
-	0x0004, 0x2051, 0x0008, 0x2091, 0x8000, 0x1078, 0x1980, 0x8738,
-	0xa784, 0x001f, 0x00c0, 0x1a35, 0xa7bc, 0xff00, 0x873f, 0x8738,
-	0x873f, 0xa784, 0x0f00, 0x00c0, 0x1a35, 0x2091, 0x8001, 0x007c,
-	0x2061, 0x0000, 0x6018, 0xa084, 0x0001, 0x00c0, 0x1a59, 0x2091,
-	0x8000, 0x78e0, 0x78e3, 0x0000, 0x2091, 0x8001, 0xa005, 0x00c0,
-	0x1a5a, 0x007c, 0xa08c, 0xfff0, 0x0040, 0x1a60, 0x1078, 0x23eb,
-	0x0079, 0x1a62, 0x1a72, 0x1a75, 0x1a7b, 0x1a7f, 0x1a73, 0x1a83,
-	0x1a89, 0x1a73, 0x1a73, 0x1c29, 0x1c4d, 0x1c51, 0x1a73, 0x1a73,
-	0x1a73, 0x1a73, 0x007c, 0x1078, 0x23eb, 0x1078, 0x1a2b, 0x2001,
-	0x8001, 0x0078, 0x1c57, 0x2001, 0x8003, 0x0078, 0x1c57, 0x2001,
-	0x8004, 0x0078, 0x1c57, 0x1078, 0x1a2b, 0x2001, 0x8006, 0x0078,
-	0x1c57, 0x2001, 0x8007, 0x0078, 0x1c57, 0x2030, 0x2138, 0xa782,
-	0x0021, 0x0048, 0x1a95, 0x2009, 0x0020, 0x2600, 0x1078, 0x1aaf,
-	0x00c0, 0x1aae, 0xa7ba, 0x0020, 0x0048, 0x1aad, 0x0040, 0x1aad,
-	0x2708, 0xa6b0, 0x0020, 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1,
-	0x0000, 0xa5a9, 0x0000, 0x0078, 0x1a8f, 0xa006, 0x007c, 0x81ff,
-	0x0040, 0x1aea, 0x2099, 0x0030, 0x20a0, 0x700c, 0xa084, 0x00ff,
-	0x0040, 0x1ac1, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0,
-	0x1abc, 0x21a8, 0x7017, 0x0000, 0x810b, 0x7112, 0x721a, 0x731e,
-	0x7422, 0x7526, 0x780c, 0xa085, 0x0001, 0x7002, 0x7007, 0x0001,
-	0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x00c8, 0x1ade, 0x2009,
-	0x0022, 0x2104, 0xa084, 0x4000, 0x00c0, 0x1ad0, 0x7008, 0x800b,
-	0x00c8, 0x1ad0, 0x7007, 0x0002, 0xa08c, 0x01e0, 0x00c0, 0x1aea,
-	0x53a5, 0xa006, 0x7003, 0x0000, 0x007c, 0x2030, 0x2138, 0xa782,
-	0x0021, 0x0048, 0x1af5, 0x2009, 0x0020, 0x2600, 0x1078, 0x1b0f,
-	0x00c0, 0x1b0e, 0xa7ba, 0x0020, 0x0048, 0x1b0d, 0x0040, 0x1b0d,
-	0x2708, 0xa6b0, 0x0020, 0xa290, 0x0040, 0xa399, 0x0000, 0xa4a1,
-	0x0000, 0xa5a9, 0x0000, 0x0078, 0x1aef, 0xa006, 0x007c, 0x81ff,
-	0x0040, 0x1b50, 0x2098, 0x20a1, 0x0030, 0x700c, 0xa084, 0x00ff,
-	0x0040, 0x1b21, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0,
-	0x1b1c, 0x21a8, 0x7017, 0x0000, 0x810b, 0x7112, 0x721a, 0x731e,
-	0x7422, 0x7526, 0x780c, 0xa085, 0x0000, 0x7002, 0x53a6, 0x7007,
-	0x0001, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x00c8, 0x1b3f,
-	0x2009, 0x0022, 0x2104, 0xa084, 0x4000, 0x00c0, 0x1b31, 0x7010,
-	0xa084, 0xf000, 0x0040, 0x1b48, 0x7007, 0x0008, 0x0078, 0x1b4c,
-	0x7108, 0x8103, 0x00c8, 0x1b31, 0x7007, 0x0002, 0xa184, 0x01e0,
-	0x7003, 0x0000, 0x007c, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0004,
-	0x00c8, 0x1b5c, 0x0078, 0x1b5f, 0xa006, 0x0078, 0x1b61, 0xa085,
-	0x0001, 0x007c, 0x0e7e, 0x2071, 0x5100, 0x2d08, 0x7058, 0x6802,
-	0xa005, 0x00c0, 0x1b6c, 0x715e, 0x715a, 0x0e7f, 0x007c, 0x2c08,
-	0x7858, 0x6002, 0xa005, 0x00c0, 0x1b76, 0x795e, 0x795a, 0x007c,
-	0x2091, 0x8000, 0x6003, 0x0000, 0x2c08, 0x785c, 0xa065, 0x00c0,
-	0x1b84, 0x795a, 0x0078, 0x1b85, 0x6102, 0x795e, 0x2091, 0x8001,
-	0x1078, 0x21ef, 0x007c, 0x0e7e, 0x2071, 0x5100, 0x7058, 0xa06d,
-	0x0040, 0x1b99, 0x6800, 0x705a, 0xa005, 0x00c0, 0x1b98, 0x705e,
-	0x8dff, 0x0e7f, 0x007c, 0x0d7e, 0x0c7e, 0x0f7e, 0x2079, 0x5100,
-	0xaf80, 0x0016, 0x2060, 0x6000, 0xa005, 0x0040, 0x1bc9, 0x2068,
-	0x6814, 0xa306, 0x00c0, 0x1bb2, 0x6828, 0xa084, 0x00ff, 0xa406,
-	0x0040, 0x1bb5, 0x2d60, 0x0078, 0x1ba3, 0x6800, 0xa005, 0x6002,
-	0x00c0, 0x1bc1, 0xaf80, 0x0016, 0xac06, 0x0040, 0x1bc0, 0x2c00,
-	0x785e, 0x0d7e, 0x689c, 0xa005, 0x0040, 0x1bc8, 0x1078, 0x19b3,
-	0x007f, 0x0f7f, 0x0c7f, 0x0d7f, 0xa005, 0x007c, 0x0d7e, 0x0c7e,
-	0x0f7e, 0x2079, 0x5100, 0xaf80, 0x0016, 0x2060, 0x6000, 0xa005,
-	0x0040, 0x1bf8, 0x2068, 0x6814, 0xa084, 0x00ff, 0xa306, 0x0040,
-	0x1be4, 0x2d60, 0x0078, 0x1bd6, 0x6800, 0xa005, 0x6002, 0x00c0,
-	0x1bf0, 0xaf80, 0x0016, 0xac06, 0x0040, 0x1bef, 0x2c00, 0x785e,
-	0x0d7e, 0x689c, 0xa005, 0x0040, 0x1bf7, 0x1078, 0x19b3, 0x007f,
-	0x0f7f, 0x0c7f, 0x0d7f, 0xa005, 0x007c, 0x0d7e, 0x0c7e, 0x0f7e,
-	0x2079, 0x5100, 0xaf80, 0x0016, 0x2060, 0x6000, 0xa06d, 0x0040,
-	0x1c24, 0x6814, 0xa306, 0x0040, 0x1c10, 0x2d60, 0x0078, 0x1c05,
-	0x6800, 0xa005, 0x6002, 0x00c0, 0x1c1c, 0xaf80, 0x0016, 0xac06,
-	0x0040, 0x1c1b, 0x2c00, 0x785e, 0x0d7e, 0x689c, 0xa005, 0x0040,
-	0x1c23, 0x1078, 0x19b3, 0x007f, 0x0f7f, 0x0c7f, 0x0d7f, 0xa005,
-	0x007c, 0x2091, 0x8000, 0x2069, 0x5140, 0x6800, 0xa086, 0x0000,
-	0x0040, 0x1c37, 0x2091, 0x8001, 0x78e3, 0x0009, 0x007c, 0x6880,
-	0xa0bc, 0xff00, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0010,
-	0x1078, 0x1980, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1c40, 0x2091,
-	0x8001, 0x2001, 0x800a, 0x0078, 0x1c57, 0x2001, 0x800c, 0x0078,
-	0x1c57, 0x1078, 0x1a2b, 0x2001, 0x800d, 0x0078, 0x1c57, 0x70c2,
-	0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x4080, 0x007c, 0x6004,
-	0x2c08, 0x2063, 0x0000, 0x7884, 0x8000, 0x7886, 0x7888, 0xa005,
-	0x798a, 0x0040, 0x1c6e, 0x2c02, 0x0078, 0x1c6f, 0x798e, 0x007c,
-	0x6807, 0x0103, 0x0c7e, 0x2061, 0x5100, 0x2d08, 0x206b, 0x0000,
-	0x6084, 0x8000, 0x6086, 0x6088, 0xa005, 0x618a, 0x0040, 0x1c83,
-	0x2d02, 0x0078, 0x1c84, 0x618e, 0x0c7f, 0x007c, 0x1078, 0x1c97,
-	0x0040, 0x1c96, 0x0c7e, 0x609c, 0xa065, 0x0040, 0x1c91, 0x1078,
-	0x19b3, 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1948, 0x007c, 0x788c,
-	0xa065, 0x0040, 0x1ca9, 0x2091, 0x8000, 0x7884, 0x8001, 0x7886,
-	0x2c04, 0x788e, 0xa005, 0x00c0, 0x1ca7, 0x788a, 0x8000, 0x2091,
-	0x8001, 0x007c, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e,
-	0x00c8, 0x1cb3, 0xa200, 0x0070, 0x1cb7, 0x0078, 0x1cae, 0x8086,
-	0x818e, 0x007c, 0x157e, 0x20a9, 0x0010, 0xa005, 0x0040, 0x1cdd,
-	0xa11a, 0x00c8, 0x1cdd, 0x8213, 0x818d, 0x0048, 0x1cce, 0xa11a,
-	0x00c8, 0x1ccf, 0x0070, 0x1cd5, 0x0078, 0x1cc3, 0xa11a, 0x2308,
-	0x8210, 0x0070, 0x1cd5, 0x0078, 0x1cc3, 0x007e, 0x3200, 0xa084,
-	0xf7ff, 0x2080, 0x007f, 0x157f, 0x007c, 0x007e, 0x3200, 0xa085,
-	0x0800, 0x0078, 0x1cd9, 0x7994, 0x70d0, 0xa106, 0x0040, 0x1d51,
-	0x2091, 0x8000, 0x2071, 0x0020, 0x7004, 0xa005, 0x00c0, 0x1d51,
-	0x7008, 0x7208, 0xa206, 0x00c0, 0x1d51, 0xa286, 0x0008, 0x00c0,
-	0x1d51, 0x2071, 0x0010, 0x1078, 0x192e, 0x0040, 0x1d51, 0x7a9c,
-	0x7b98, 0x7ca4, 0x7da0, 0xa184, 0xff00, 0x0040, 0x1d1f, 0x2031,
-	0x0000, 0x810b, 0x86b5, 0x810b, 0x86b5, 0x810b, 0x86b5, 0x810b,
-	0x86b5, 0x810b, 0x86b5, 0x810b, 0x86b5, 0x2100, 0xa210, 0x2600,
-	0xa319, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x0078, 0x1d29, 0x8107,
-	0x8004, 0x8004, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9,
-	0x0000, 0x2009, 0x0020, 0x1078, 0x1929, 0x2091, 0x8001, 0x0040,
-	0x1d48, 0x1078, 0x1948, 0x78a8, 0x8000, 0x78aa, 0xa086, 0x0002,
-	0x00c0, 0x1d51, 0x2091, 0x8000, 0x78e3, 0x0002, 0x78ab, 0x0000,
-	0x78cc, 0xa085, 0x0003, 0x78ce, 0x2091, 0x8001, 0x0078, 0x1d51,
-	0x78ab, 0x0000, 0x1078, 0x20ac, 0x6004, 0xa084, 0x000f, 0x0079,
-	0x1d56, 0x2071, 0x0010, 0x2091, 0x8001, 0x007c, 0x1d66, 0x1d88,
-	0x1dae, 0x1d66, 0x1dcb, 0x1d75, 0x1f2c, 0x1f47, 0x1d66, 0x1d82,
-	0x1da8, 0x1e13, 0x1e82, 0x1ed2, 0x1ee4, 0x1f43, 0x2039, 0x0400,
-	0x78dc, 0xa705, 0x78de, 0x6008, 0xa705, 0x600a, 0x1078, 0x1fc7,
-	0x609c, 0x78da, 0x1078, 0x2094, 0x007c, 0x78dc, 0xa084, 0x0100,
-	0x0040, 0x1d7c, 0x0078, 0x1d66, 0x601c, 0xa085, 0x0080, 0x601e,
-	0x0078, 0x1d8f, 0x1078, 0x1b53, 0x00c0, 0x1d66, 0x1078, 0x20c6,
-	0x78dc, 0xa084, 0x0100, 0x0040, 0x1d8f, 0x0078, 0x1d66, 0x78df,
-	0x0000, 0x6004, 0x8007, 0xa084, 0x00ff, 0x78d2, 0x8001, 0x609f,
-	0x0000, 0x0040, 0x1da5, 0x1078, 0x1fc7, 0x0040, 0x1da5, 0x78dc,
-	0xa085, 0x0100, 0x78de, 0x0078, 0x1da7, 0x1078, 0x1feb, 0x007c,
-	0x1078, 0x1b53, 0x00c0, 0x1d66, 0x1078, 0x20c2, 0x78dc, 0xa08c,
-	0x0e00, 0x00c0, 0x1db7, 0xa084, 0x0100, 0x00c0, 0x1db9, 0x0078,
-	0x1d66, 0x1078, 0x1fc7, 0x00c0, 0x1dca, 0x6104, 0xa18c, 0x00ff,
-	0xa186, 0x0007, 0x0040, 0x1f84, 0xa186, 0x000f, 0x0040, 0x1f84,
-	0x1078, 0x1feb, 0x007c, 0x78dc, 0xa084, 0x0100, 0x0040, 0x1dd2,
-	0x0078, 0x1d66, 0x78df, 0x0000, 0x6714, 0x2011, 0x0001, 0x20a9,
-	0x0001, 0x6018, 0xa084, 0x00ff, 0xa005, 0x0040, 0x1df5, 0x2011,
-	0x0001, 0xa7bc, 0xff00, 0x20a9, 0x0020, 0xa08e, 0x0001, 0x0040,
-	0x1df5, 0x2039, 0x0000, 0x2011, 0x0002, 0x20a9, 0x0100, 0xa08e,
-	0x0002, 0x0040, 0x1df5, 0x0078, 0x1e10, 0x1078, 0x1973, 0x2091,
-	0x8000, 0x682b, 0x0000, 0x682f, 0x0000, 0x6808, 0xa084, 0xffde,
-	0x680a, 0xade8, 0x0010, 0x2091, 0x8001, 0x0070, 0x1e09, 0x0078,
-	0x1df7, 0x8211, 0x0040, 0x1e10, 0x20a9, 0x0100, 0x0078, 0x1df7,
-	0x1078, 0x1948, 0x007c, 0x2001, 0x5167, 0x2004, 0xa084, 0x8000,
-	0x0040, 0x1fac, 0x6114, 0x1078, 0x20e3, 0x6900, 0xa184, 0x0001,
-	0x0040, 0x1e34, 0x6028, 0xa084, 0x00ff, 0x00c0, 0x1fa4, 0x6800,
-	0xa084, 0x0001, 0x0040, 0x1fac, 0x6803, 0x0000, 0x680b, 0x0000,
-	0x6807, 0x0000, 0x0078, 0x1fb4, 0x2011, 0x0001, 0x6020, 0xd0f4,
-	0x0040, 0x1e3c, 0xa295, 0x0002, 0xd0c4, 0x0040, 0x1e41, 0xa295,
-	0x0008, 0xd0cc, 0x0040, 0x1e46, 0xa295, 0x0400, 0x601c, 0xa084,
-	0x0002, 0x0040, 0x1e4d, 0xa295, 0x0004, 0x602c, 0xa08c, 0x00ff,
-	0xa182, 0x0002, 0x0048, 0x1fb0, 0xa182, 0x001b, 0x00c8, 0x1fb0,
-	0x0040, 0x1fb0, 0x690e, 0x602c, 0x8007, 0xa08c, 0x00ff, 0xa182,
-	0x0002, 0x0048, 0x1fb0, 0xa182, 0x001b, 0x00c8, 0x1fb0, 0x0040,
-	0x1fb0, 0x6912, 0x6030, 0xa005, 0x00c0, 0x1e70, 0x2001, 0x001e,
-	0x8000, 0x6816, 0x6028, 0xa084, 0x00ff, 0x0040, 0x1fac, 0x6806,
-	0x6028, 0x8007, 0xa084, 0x00ff, 0x0040, 0x1fac, 0x680a, 0x6a02,
-	0x0078, 0x1fb4, 0x2001, 0x5167, 0x2004, 0xa084, 0x8000, 0x0040,
-	0x1fac, 0x6114, 0x1078, 0x20e3, 0x2091, 0x8000, 0x6a04, 0x6b08,
-	0x6418, 0xa484, 0x0003, 0x0040, 0x1ea8, 0x6128, 0xa18c, 0x00ff,
-	0x8001, 0x00c0, 0x1ea1, 0x2100, 0xa210, 0x0048, 0x1ece, 0x0078,
-	0x1ea8, 0x8001, 0x00c0, 0x1ece, 0x2100, 0xa212, 0x0048, 0x1ece,
-	0xa484, 0x000c, 0x0040, 0x1ec2, 0x6128, 0x810f, 0xa18c, 0x00ff,
-	0xa082, 0x0004, 0x00c0, 0x1eba, 0x2100, 0xa318, 0x0048, 0x1ece,
-	0x0078, 0x1ec2, 0xa082, 0x0004, 0x00c0, 0x1ece, 0x2100, 0xa31a,
-	0x0048, 0x1ece, 0x6030, 0xa005, 0x0040, 0x1ec8, 0x8000, 0x6816,
-	0x6a06, 0x6b0a, 0x2091, 0x8001, 0x0078, 0x1fb4, 0x2091, 0x8001,
-	0x0078, 0x1fb0, 0x6114, 0x1078, 0x20e3, 0x2091, 0x8000, 0x6b08,
-	0x8318, 0x0048, 0x1ee0, 0x6b0a, 0x2091, 0x8001, 0x0078, 0x1fc3,
-	0x2091, 0x8001, 0x0078, 0x1fb0, 0x6024, 0x8007, 0xa084, 0x00ff,
-	0x0040, 0x1f02, 0xa086, 0x0080, 0x00c0, 0x1f2a, 0x20a9, 0x0008,
-	0x2069, 0x7510, 0x2091, 0x8000, 0x6800, 0xa084, 0xfcff, 0x6802,
-	0xade8, 0x0008, 0x0070, 0x1efe, 0x0078, 0x1ef4, 0x2091, 0x8001,
-	0x0078, 0x1fb4, 0x6028, 0xa015, 0x0040, 0x1f2a, 0x6114, 0x1078,
-	0x20e3, 0x0d7e, 0xade8, 0x0007, 0x2091, 0x8000, 0x6800, 0xa00d,
-	0x0040, 0x1f27, 0xa206, 0x0040, 0x1f18, 0x2168, 0x0078, 0x1f0e,
-	0x0c7e, 0x2160, 0x6000, 0x6802, 0x1078, 0x1948, 0x0c7f, 0x0d7f,
-	0x6808, 0x8000, 0x680a, 0x2091, 0x8001, 0x0078, 0x1fc3, 0x2091,
-	0x8001, 0x0d7f, 0x0078, 0x1fac, 0x6114, 0x1078, 0x20e3, 0x6800,
-	0xa084, 0x0001, 0x0040, 0x1f9c, 0x2091, 0x8000, 0x6a04, 0x8210,
-	0x0048, 0x1f3f, 0x6a06, 0x2091, 0x8001, 0x0078, 0x1fc3, 0x2091,
-	0x8001, 0x0078, 0x1fb0, 0x1078, 0x1b53, 0x00c0, 0x1d66, 0x6114,
-	0x1078, 0x20e3, 0x60be, 0x60bb, 0x0000, 0x6900, 0xa184, 0x0008,
-	0x0040, 0x1f56, 0x6020, 0xa085, 0x0100, 0x6022, 0xa184, 0x0001,
-	0x0040, 0x1fac, 0xa184, 0x0100, 0x00c0, 0x1f98, 0xa184, 0x0200,
-	0x00c0, 0x1f94, 0x681c, 0xa005, 0x00c0, 0x1fa0, 0x6004, 0xa084,
-	0x00ff, 0xa086, 0x000f, 0x00c0, 0x1f6f, 0x1078, 0x20c6, 0x78df,
-	0x0000, 0x6004, 0x8007, 0xa084, 0x00ff, 0x78d2, 0x8001, 0x609f,
-	0x0000, 0x0040, 0x1f84, 0x1078, 0x1fc7, 0x0040, 0x1f84, 0x78dc,
-	0xa085, 0x0100, 0x78de, 0x007c, 0x78d7, 0x0000, 0x78db, 0x0000,
-	0x6024, 0xa084, 0xff00, 0x6026, 0x1078, 0x39de, 0x0040, 0x1ce3,
-	0x1078, 0x1b78, 0x0078, 0x1ce3, 0x2009, 0x0017, 0x0078, 0x1fb6,
-	0x2009, 0x000e, 0x0078, 0x1fb6, 0x2009, 0x0007, 0x0078, 0x1fb6,
-	0x2009, 0x0035, 0x0078, 0x1fb6, 0x2009, 0x003e, 0x0078, 0x1fb6,
-	0x2009, 0x0004, 0x0078, 0x1fb6, 0x2009, 0x0006, 0x0078, 0x1fb6,
-	0x2009, 0x0016, 0x0078, 0x1fb6, 0x2009, 0x0001, 0x6024, 0xa084,
-	0xff00, 0xa105, 0x6026, 0x2091, 0x8000, 0x1078, 0x1c5f, 0x2091,
-	0x8001, 0x0078, 0x1ce3, 0x1078, 0x1948, 0x0078, 0x1ce3, 0x78d4,
-	0xa06d, 0x00c0, 0x1fd2, 0x2c00, 0x78d6, 0x78da, 0x609f, 0x0000,
-	0x0078, 0x1fde, 0x2c00, 0x689e, 0x609f, 0x0000, 0x78d6, 0x2d00,
-	0x6002, 0x78d8, 0xad06, 0x00c0, 0x1fde, 0x6002, 0x78d0, 0x8001,
-	0x78d2, 0x00c0, 0x1fea, 0x78dc, 0xa084, 0xfeff, 0x78de, 0x78d8,
-	0x2060, 0xa006, 0x007c, 0xa02e, 0x2530, 0x611c, 0x61a2, 0xa184,
-	0xe1ff, 0x601e, 0xa184, 0x0060, 0x0040, 0x1ffa, 0x0e7e, 0x1078,
-	0x47c2, 0x0e7f, 0x6596, 0x65a6, 0x669a, 0x66aa, 0x60af, 0x0000,
-	0x60b3, 0x0000, 0x6714, 0x1078, 0x1973, 0x2091, 0x8000, 0x60a0,
-	0xa084, 0x8000, 0x00c0, 0x2021, 0x6808, 0xa084, 0x0001, 0x0040,
-	0x2021, 0x2091, 0x8001, 0x1078, 0x19c0, 0x2091, 0x8000, 0x1078,
-	0x1c5f, 0x2091, 0x8001, 0x78d7, 0x0000, 0x78db, 0x0000, 0x0078,
-	0x2093, 0x6024, 0xa096, 0x0001, 0x00c0, 0x2028, 0x8000, 0x6026,
-	0x6a10, 0x6814, 0x2091, 0x8001, 0xa202, 0x0048, 0x2037, 0x0040,
-	0x2037, 0x2039, 0x0200, 0x1078, 0x2094, 0x0078, 0x2093, 0x2c08,
-	0x2091, 0x8000, 0x60a0, 0xa084, 0x8000, 0x0040, 0x2064, 0x6800,
-	0xa065, 0x0040, 0x2069, 0x6a04, 0x0e7e, 0x2071, 0x5140, 0x7000,
-	0xa084, 0x0001, 0x0040, 0x205e, 0x7048, 0xa206, 0x00c0, 0x205e,
-	0x6b04, 0x231c, 0x2160, 0x6302, 0x2300, 0xa005, 0x00c0, 0x2059,
-	0x6902, 0x2260, 0x6102, 0x0e7f, 0x0078, 0x2070, 0x2160, 0x6202,
-	0x6906, 0x0e7f, 0x0078, 0x2070, 0x6800, 0xa065, 0x0040, 0x2069,
-	0x6102, 0x6902, 0x00c0, 0x206d, 0x6906, 0x2160, 0x6003, 0x0000,
-	0x2160, 0x60a0, 0xa084, 0x8000, 0x0040, 0x207a, 0x6808, 0xa084,
-	0xfffc, 0x680a, 0x6810, 0x8000, 0x6812, 0x2091, 0x8001, 0x6808,
-	0xa08c, 0x0040, 0x0040, 0x2089, 0xa086, 0x0040, 0x680a, 0x1078,
-	0x19d1, 0x2091, 0x8000, 0x1078, 0x21d2, 0x2091, 0x8001, 0x78db,
-	0x0000, 0x78d7, 0x0000, 0x007c, 0x6008, 0xa705, 0x600a, 0x2091,
-	0x8000, 0x1078, 0x1c5f, 0x2091, 0x8001, 0x78d8, 0xa065, 0x0040,
-	0x20a7, 0x609c, 0x78da, 0x609f, 0x0000, 0x0078, 0x2097, 0x78d7,
-	0x0000, 0x78db, 0x0000, 0x007c, 0x7990, 0x7894, 0x8000, 0xa10a,
-	0x00c8, 0x20b3, 0xa006, 0x7896, 0x70d2, 0x7804, 0xa005, 0x0040,
-	0x20c1, 0x8001, 0x7806, 0x00c0, 0x20c1, 0x0068, 0x20c1, 0x2091,
-	0x4080, 0x007c, 0x2039, 0x20da, 0x0078, 0x20c8, 0x2039, 0x20e0,
-	0x2704, 0xa005, 0x0040, 0x20d9, 0xac00, 0x2068, 0x6b08, 0x6c0c,
-	0x6910, 0x6a14, 0x690a, 0x6a0e, 0x6b12, 0x6c16, 0x8738, 0x0078,
-	0x20c8, 0x007c, 0x0003, 0x0009, 0x000f, 0x0015, 0x001b, 0x0000,
-	0x0015, 0x001b, 0x0000, 0x0c7e, 0x1078, 0x3b69, 0x2c68, 0x0c7f,
-	0x007c, 0x0010, 0x215a, 0x0068, 0x215a, 0x2029, 0x0000, 0x78cb,
-	0x0000, 0x788c, 0xa065, 0x0040, 0x2153, 0x2009, 0x5174, 0x2104,
-	0xa084, 0x0001, 0x0040, 0x2121, 0x6004, 0xa086, 0x0103, 0x00c0,
-	0x2121, 0x6018, 0xa005, 0x00c0, 0x2121, 0x6014, 0xa005, 0x00c0,
-	0x2121, 0x0d7e, 0x2069, 0x0000, 0x6818, 0xa084, 0x0001, 0x00c0,
-	0x2120, 0x600c, 0x70c6, 0x6010, 0x70ca, 0x70c3, 0x8020, 0x681b,
-	0x0001, 0x2091, 0x4080, 0x0d7f, 0x1078, 0x1c86, 0x0078, 0x2158,
-	0x0d7f, 0x1078, 0x215b, 0x0040, 0x2153, 0x6204, 0xa294, 0x00ff,
-	0xa296, 0x0003, 0x0040, 0x2133, 0x6204, 0xa296, 0x0110, 0x00c0,
-	0x2141, 0x78cb, 0x0001, 0x6204, 0xa294, 0xff00, 0x8217, 0x8211,
-	0x0040, 0x2141, 0x85ff, 0x00c0, 0x2153, 0x8210, 0xa202, 0x00c8,
-	0x2153, 0x057e, 0x1078, 0x216a, 0x057f, 0x0040, 0x214e, 0x78e0,
-	0xa086, 0x0003, 0x0040, 0x2153, 0x0078, 0x2141, 0x8528, 0x78c8,
-	0xa005, 0x0040, 0x20f1, 0x85ff, 0x0040, 0x215a, 0x2091, 0x4080,
-	0x78b0, 0x70d6, 0x007c, 0x7bac, 0x79b0, 0x70d4, 0xa102, 0x00c0,
-	0x2164, 0x2300, 0xa005, 0x007c, 0x0048, 0x2168, 0xa302, 0x007c,
-	0x8002, 0x007c, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x00c8,
-	0x2184, 0x2091, 0x8000, 0x2071, 0x0020, 0x7004, 0xa005, 0x00c0,
-	0x21b9, 0x7008, 0x7208, 0xa206, 0x00c0, 0x21b9, 0xa286, 0x0008,
-	0x00c0, 0x21b9, 0x2071, 0x0010, 0x1078, 0x21be, 0x2009, 0x0020,
-	0x6004, 0xa086, 0x0103, 0x00c0, 0x2193, 0x6028, 0xa005, 0x00c0,
-	0x2193, 0x2009, 0x000c, 0x1078, 0x1924, 0x0040, 0x21ac, 0x78c4,
-	0x8000, 0x78c6, 0xa086, 0x0002, 0x00c0, 0x21b9, 0x2091, 0x8000,
-	0x78e3, 0x0003, 0x78c7, 0x0000, 0x78cc, 0xa085, 0x0300, 0x78ce,
-	0x2091, 0x8001, 0x0078, 0x21b9, 0x78c7, 0x0000, 0x1078, 0x1c86,
-	0x79ac, 0x78b0, 0x8000, 0xa10a, 0x00c8, 0x21b7, 0xa006, 0x78b2,
-	0xa006, 0x2071, 0x0010, 0x2091, 0x8001, 0x007c, 0x8107, 0x8004,
-	0x8004, 0x7ab8, 0x7bb4, 0x7cc0, 0x7dbc, 0xa210, 0xa399, 0x0000,
-	0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x007c, 0x2009, 0x515b, 0x2091,
-	0x8000, 0x200a, 0x0f7e, 0x0e7e, 0x2071, 0x5140, 0x7000, 0xa086,
-	0x0000, 0x00c0, 0x21ec, 0x2009, 0x5112, 0x2104, 0xa005, 0x00c0,
-	0x21ec, 0x2079, 0x0100, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x21ec,
-	0x0018, 0x21ec, 0x781b, 0x004b, 0x0e7f, 0x0f7f, 0x007c, 0x0f7e,
-	0x0e7e, 0x2071, 0x5140, 0x2091, 0x8000, 0x7000, 0xa086, 0x0000,
-	0x00c0, 0x2205, 0x2079, 0x0100, 0x7830, 0xa084, 0x00c0, 0x00c0,
-	0x2205, 0x0018, 0x2205, 0x781b, 0x004d, 0x2091, 0x8001, 0x0e7f,
-	0x0f7f, 0x007c, 0x127e, 0x2091, 0x2300, 0x2071, 0x5140, 0x2079,
-	0x0100, 0x784b, 0x000f, 0x0098, 0x2218, 0x7838, 0x0078, 0x2211,
-	0x20a9, 0x0040, 0x7800, 0xa082, 0x0004, 0x0048, 0x2221, 0x20a9,
-	0x0060, 0x789b, 0x0000, 0x78af, 0x0000, 0x78af, 0x0000, 0x0070,
-	0x222b, 0x0078, 0x2223, 0x7800, 0xa082, 0x0004, 0x0048, 0x223a,
-	0x70b7, 0x0096, 0x2019, 0x4ee7, 0x1078, 0x2276, 0x702f, 0x8001,
-	0x0078, 0x2246, 0x70b7, 0x0000, 0x2019, 0x4d5f, 0x1078, 0x2276,
-	0x2019, 0x4d9e, 0x1078, 0x2276, 0x702f, 0x8000, 0x7003, 0x0000,
-	0x1078, 0x237f, 0x7004, 0xa084, 0x000f, 0x017e, 0x2009, 0x04fd,
-	0x210c, 0xa18a, 0x0005, 0x0048, 0x225b, 0x0038, 0x2261, 0xa085,
-	0x6280, 0x0078, 0x2263, 0x0028, 0x2261, 0xa085, 0x6280, 0x0078,
-	0x2263, 0xa085, 0x62c0, 0x017f, 0x7806, 0x780f, 0xb204, 0x7843,
-	0x00d8, 0x7853, 0x0080, 0x780b, 0x0008, 0x7047, 0x0008, 0x7053,
-	0x517f, 0x704f, 0x0000, 0x127f, 0x2000, 0x007c, 0x137e, 0x147e,
-	0x157e, 0x047e, 0x20a1, 0x012b, 0x2304, 0xa005, 0x789a, 0x0040,
-	0x2296, 0x8318, 0x2324, 0x8318, 0x2398, 0x24a8, 0xa484, 0xff00,
-	0x0040, 0x228e, 0xa482, 0x0100, 0x20a9, 0x0100, 0x2020, 0x53a6,
-	0xa005, 0x00c0, 0x2285, 0x3318, 0x0078, 0x227c, 0x047f, 0x157f,
-	0x147f, 0x137f, 0x007c, 0xa18c, 0x000f, 0x2011, 0x0101, 0x2204,
-	0xa084, 0xfff0, 0xa105, 0x2012, 0x1078, 0x237f, 0x007c, 0x2011,
-	0x0101, 0x20a9, 0x0009, 0x810b, 0x0070, 0x22b0, 0x0078, 0x22ab,
-	0xa18c, 0x0e00, 0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012, 0x007c,
-	0x2009, 0x0101, 0x20a9, 0x0005, 0x8213, 0x0070, 0x22c1, 0x0078,
-	0x22bc, 0xa294, 0x00e0, 0x2104, 0xa084, 0xff1f, 0xa205, 0x200a,
-	0x007c, 0x2011, 0x0101, 0x20a9, 0x000c, 0x810b, 0x0070, 0x22d2,
-	0x0078, 0x22cd, 0xa18c, 0xf000, 0x2204, 0xa084, 0x0fff, 0xa105,
-	0x2012, 0x007c, 0x2011, 0x0102, 0x2204, 0xa084, 0xffcf, 0xa105,
-	0x2012, 0x007c, 0x8103, 0x8003, 0xa080, 0x0020, 0x0c7e, 0x2061,
-	0x0100, 0x609a, 0x62ac, 0x63ac, 0x0c7f, 0x007c, 0x8103, 0x8003,
-	0xa080, 0x0022, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4, 0xa084,
-	0xffdf, 0x60ae, 0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080, 0x0022,
-	0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4, 0xa085, 0x0020, 0x60ae,
-	0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080, 0x0020, 0x0c7e, 0x2061,
-	0x0100, 0x609a, 0x60a4, 0x62ae, 0x2010, 0x60a4, 0x63ae, 0x2018,
-	0x0c7f, 0x007c, 0x2091, 0x8000, 0x0c7e, 0x0e7e, 0x6818, 0xa005,
-	0x0040, 0x235d, 0x2061, 0x7500, 0x1078, 0x2365, 0x0040, 0x2349,
-	0x20a9, 0x0000, 0x2061, 0x7400, 0x0c7e, 0x1078, 0x2365, 0x0040,
-	0x2339, 0x0c7f, 0x8c60, 0x0070, 0x2337, 0x0078, 0x232c, 0x0078,
-	0x235d, 0x007f, 0xa082, 0x7400, 0x2071, 0x5140, 0x7086, 0x7182,
-	0x2001, 0x0004, 0x706e, 0x7093, 0x000f, 0x1078, 0x21cd, 0x0078,
-	0x2359, 0x60c0, 0xa005, 0x00c0, 0x235d, 0x2071, 0x5140, 0x7182,
-	0x2c00, 0x708a, 0x2001, 0x0006, 0x706e, 0x7093, 0x000f, 0x1078,
-	0x21cd, 0x2001, 0x0000, 0x0078, 0x235f, 0x2001, 0x0001, 0x2091,
-	0x8001, 0xa005, 0x0e7f, 0x0c7f, 0x007c, 0x2c04, 0xa005, 0x0040,
-	0x237c, 0x2060, 0x600c, 0xa306, 0x00c0, 0x2379, 0x6010, 0xa206,
-	0x00c0, 0x2379, 0x6014, 0xa106, 0x00c0, 0x2379, 0xa006, 0x0078,
-	0x237e, 0x6000, 0x0078, 0x2366, 0xa085, 0x0001, 0x007c, 0x2011,
-	0x5141, 0x220c, 0xa18c, 0x000f, 0x2011, 0x013b, 0x2204, 0xa084,
-	0x0100, 0x0040, 0x2395, 0x2021, 0xff04, 0x2122, 0x810b, 0x810b,
-	0x810b, 0x810b, 0xa18d, 0x0f00, 0x2104, 0x007c, 0x0e7e, 0x68e4,
-	0xa08c, 0x0020, 0x0040, 0x23e9, 0xa084, 0x0006, 0x00c0, 0x23e9,
-	0x6014, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0f0,
-	0x5380, 0x7004, 0xa084, 0x000a, 0x00c0, 0x23e9, 0x7108, 0xa194,
-	0xff00, 0x0040, 0x23e9, 0xa18c, 0x00ff, 0x2001, 0x000c, 0xa106,
-	0x0040, 0x23d0, 0x2001, 0x0012, 0xa106, 0x0040, 0x23d4, 0x2001,
-	0x0014, 0xa106, 0x0040, 0x23d8, 0x2001, 0x0019, 0xa106, 0x0040,
-	0x23dc, 0x2001, 0x0032, 0xa106, 0x0040, 0x23e0, 0x0078, 0x23e4,
-	0x2009, 0x0012, 0x0078, 0x23e6, 0x2009, 0x0014, 0x0078, 0x23e6,
-	0x2009, 0x0019, 0x0078, 0x23e6, 0x2009, 0x0020, 0x0078, 0x23e6,
-	0x2009, 0x003f, 0x0078, 0x23e6, 0x2011, 0x0000, 0x2100, 0xa205,
-	0x700a, 0x0e7f, 0x007c, 0x0068, 0x23eb, 0x2091, 0x8000, 0x2071,
-	0x0000, 0x007e, 0x7018, 0xa084, 0x0001, 0x00c0, 0x23f2, 0x007f,
-	0x2071, 0x0010, 0x70ca, 0x007f, 0x70c6, 0x70c3, 0x8002, 0x70db,
-	0x0741, 0x70df, 0x0000, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091,
-	0x4080, 0x0078, 0x2409, 0x107e, 0x007e, 0x127e, 0x2091, 0x2300,
-	0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x77c2, 0x74c6, 0x76ca, 0x75ce,
-	0xa594, 0x003f, 0xa49c, 0x0003, 0xa484, 0x000f, 0x0079, 0x2420,
-	0x2432, 0x2432, 0x2432, 0x276c, 0x393b, 0x2430, 0x2461, 0x246b,
-	0x2430, 0x2430, 0x2430, 0x2430, 0x2430, 0x2430, 0x2430, 0x2430,
-	0x1078, 0x23eb, 0x8507, 0xa084, 0x001f, 0x0079, 0x2437, 0x2475,
-	0x276c, 0x2926, 0x2a23, 0x2a4b, 0x2ced, 0x2f98, 0x2fdb, 0x3026,
-	0x30ab, 0x3163, 0x320c, 0x2461, 0x2848, 0x2f6d, 0x2457, 0x3cc8,
-	0x3ce8, 0x3eae, 0x3eba, 0x3f8f, 0x2457, 0x2457, 0x4062, 0x4066,
-	0x3cc6, 0x2457, 0x3e19, 0x2457, 0x3b8c, 0x246b, 0x2457, 0x1078,
-	0x23eb, 0x0018, 0x2410, 0x127f, 0x2091, 0x8001, 0x007f, 0x107f,
-	0x007c, 0x2019, 0x4e3b, 0x1078, 0x2276, 0x702f, 0x0001, 0x781b,
-	0x004f, 0x0078, 0x2459, 0x2019, 0x4d9e, 0x1078, 0x2276, 0x702f,
-	0x8000, 0x781b, 0x00d0, 0x0078, 0x2459, 0x7242, 0x2009, 0x510f,
-	0x200b, 0x0000, 0xa584, 0x0001, 0x00c0, 0x3ba0, 0x0040, 0x2492,
-	0x1078, 0x23eb, 0x7003, 0x0000, 0x704b, 0x0000, 0x7043, 0x0000,
-	0x7037, 0x0000, 0x1078, 0x3912, 0x0018, 0x2410, 0x2009, 0x510f,
-	0x200b, 0x0000, 0x7068, 0xa005, 0x00c0, 0x255d, 0x706c, 0xa084,
-	0x0007, 0x0079, 0x249b, 0x2594, 0x24a3, 0x24af, 0x24cc, 0x24ee,
-	0x253b, 0x2514, 0x24a3, 0x1078, 0x38fa, 0x2009, 0x0048, 0x1078,
-	0x2e39, 0x00c0, 0x24ad, 0x7003, 0x0004, 0x0078, 0x2459, 0x1078,
-	0x38fa, 0x00c0, 0x24ca, 0x7080, 0x8007, 0x7882, 0x789b, 0x0010,
-	0x78ab, 0x000c, 0x789b, 0x0060, 0x78ab, 0x0001, 0x785b, 0x0004,
-	0x2009, 0x00e0, 0x1078, 0x2e2d, 0x00c0, 0x24ca, 0x7003, 0x0004,
-	0x7093, 0x000f, 0x0078, 0x2459, 0x1078, 0x38fa, 0x00c0, 0x24ec,
-	0x7180, 0x8107, 0x7882, 0x789b, 0x0010, 0xa18c, 0x001f, 0xa18d,
-	0x00c0, 0x79aa, 0x78ab, 0x0006, 0x789b, 0x0060, 0x78ab, 0x0002,
-	0x785b, 0x0004, 0x2009, 0x00e0, 0x1078, 0x2e2d, 0x00c0, 0x24ec,
-	0x7003, 0x0004, 0x7093, 0x000f, 0x0078, 0x2459, 0x1078, 0x38fa,
-	0x00c0, 0x2512, 0x7180, 0x8107, 0x7882, 0x789b, 0x0010, 0xa18c,
-	0x001f, 0xa18d, 0x00c0, 0x79aa, 0x78ab, 0x0020, 0x7184, 0x79aa,
-	0x78ab, 0x000d, 0x789b, 0x0060, 0x78ab, 0x0004, 0x785b, 0x0004,
-	0x2009, 0x00e0, 0x1078, 0x2e2d, 0x00c0, 0x2512, 0x7003, 0x0004,
-	0x7093, 0x000f, 0x0078, 0x2459, 0x1078, 0x38fa, 0x00c0, 0x2539,
-	0x7180, 0x8107, 0x7882, 0x789b, 0x0010, 0xa18c, 0x001f, 0xa18d,
-	0x00c0, 0x79aa, 0x78ab, 0x0006, 0x789b, 0x0060, 0x78ab, 0x0002,
-	0x785b, 0x0004, 0x2009, 0x00e0, 0x1078, 0x2e2d, 0x00c0, 0x2539,
-	0x7088, 0x708b, 0x0000, 0x2068, 0x704a, 0x7003, 0x0002, 0x7093,
-	0x000f, 0x0078, 0x2459, 0x1078, 0x38fa, 0x00c0, 0x2459, 0x7088,
-	0x2068, 0x6f14, 0x1078, 0x37ef, 0x2c50, 0x1078, 0x39ac, 0x789b,
-	0x0010, 0x6814, 0xa084, 0x001f, 0xa085, 0x0080, 0x78aa, 0x6e1c,
-	0x2041, 0x0001, 0x708c, 0xa084, 0x0400, 0x2001, 0x0004, 0x0040,
-	0x255b, 0x2001, 0x0006, 0x0078, 0x267c, 0x1078, 0x38fa, 0x00c0,
-	0x2459, 0x789b, 0x0010, 0x7068, 0x2068, 0x6f14, 0x1078, 0x37ef,
-	0x2c50, 0x1078, 0x39ac, 0x6008, 0xa085, 0x0010, 0x600a, 0x6824,
-	0xa005, 0x0040, 0x257b, 0xa082, 0x0006, 0x0048, 0x2579, 0x0078,
-	0x257b, 0x6827, 0x0005, 0x6b14, 0xa39c, 0x001f, 0xa39d, 0x00c0,
-	0x7058, 0xa084, 0x8000, 0x0040, 0x2589, 0xa684, 0x0001, 0x0040,
-	0x258b, 0xa39c, 0xffbf, 0x7baa, 0x2031, 0x0020, 0x2041, 0x0001,
-	0x2001, 0x0003, 0x0078, 0x267c, 0x0018, 0x2410, 0x744c, 0xa485,
-	0x0000, 0x0040, 0x25ae, 0xa080, 0x5180, 0x2030, 0x7150, 0x8108,
-	0xa12a, 0x0048, 0x25a5, 0x2009, 0x5180, 0x2164, 0x6504, 0x85ff,
-	0x00c0, 0x25bf, 0x8421, 0x00c0, 0x259f, 0x7152, 0x7003, 0x0000,
-	0x704b, 0x0000, 0x7040, 0xa005, 0x0040, 0x3ba0, 0x0078, 0x2459,
-	0x764c, 0xa6b0, 0x5180, 0x7150, 0x2600, 0x0078, 0x25aa, 0x7152,
-	0x2568, 0x2558, 0x754a, 0x2c50, 0x6034, 0xa085, 0x0000, 0x00c0,
-	0x25bc, 0x6708, 0x773a, 0xa784, 0x033f, 0x0040, 0x25f5, 0xa784,
-	0x0021, 0x00c0, 0x25bc, 0xa784, 0x0002, 0x0040, 0x25de, 0xa784,
-	0x0004, 0x0040, 0x25bc, 0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0008,
-	0x00c0, 0x25bc, 0xa784, 0x0010, 0x00c0, 0x25bc, 0xa784, 0x0200,
-	0x00c0, 0x25bc, 0xa784, 0x0100, 0x0040, 0x25f5, 0x6018, 0xa005,
-	0x00c0, 0x25bc, 0xa7bc, 0xfeff, 0x670a, 0x6823, 0x0000, 0x6e1c,
-	0xa684, 0x000e, 0x6118, 0x0040, 0x2605, 0x601c, 0xa102, 0x0048,
-	0x2608, 0x0040, 0x2608, 0x0078, 0x25b8, 0x81ff, 0x00c0, 0x25b8,
-	0x68c3, 0x0000, 0xa784, 0x0080, 0x00c0, 0x2610, 0x700c, 0x6022,
-	0xa7bc, 0xff7f, 0x670a, 0x1078, 0x39ac, 0x0018, 0x2410, 0x789b,
-	0x0010, 0xa046, 0x1078, 0x38fa, 0x00c0, 0x2459, 0x6b14, 0xa39c,
-	0x001f, 0xa39d, 0x00c0, 0x7058, 0xa084, 0x8000, 0x0040, 0x262c,
-	0xa684, 0x0001, 0x0040, 0x262e, 0xa39c, 0xffbf, 0xa684, 0x0010,
-	0x0040, 0x2634, 0xa39d, 0x0020, 0x7baa, 0x8840, 0xa684, 0x000e,
-	0x00c0, 0x263f, 0xa7bd, 0x0010, 0x670a, 0x0078, 0x267a, 0x7158,
-	0xa18c, 0x0800, 0x0040, 0x3401, 0x2011, 0x0020, 0xa684, 0x0008,
-	0x00c0, 0x2650, 0x8210, 0xa684, 0x0002, 0x00c0, 0x2650, 0x8210,
-	0x7aaa, 0x8840, 0x1078, 0x3912, 0x6a14, 0x610c, 0x8108, 0xa18c,
-	0x00ff, 0xa1e0, 0x7400, 0x2c64, 0x8cff, 0x0040, 0x2671, 0x6014,
-	0xa206, 0x00c0, 0x265b, 0x60b8, 0x8001, 0x60ba, 0x00c0, 0x2656,
-	0x0c7e, 0x2a60, 0x6008, 0xa085, 0x0100, 0x600a, 0x0c7f, 0x0078,
-	0x2594, 0x1078, 0x38fa, 0x00c0, 0x2459, 0x2a60, 0x610e, 0x79aa,
-	0x8840, 0x7132, 0x2001, 0x0001, 0x007e, 0x715c, 0xa184, 0x0018,
-	0x0040, 0x2697, 0xa184, 0x0010, 0x0040, 0x268a, 0x1078, 0x3604,
-	0x00c0, 0x26ba, 0xa184, 0x0008, 0x0040, 0x2697, 0x69a0, 0xa184,
-	0x0600, 0x00c0, 0x2697, 0x1078, 0x34f1, 0x0078, 0x26ba, 0x69a0,
-	0xa184, 0x0800, 0x0040, 0x26ae, 0x0c7e, 0x027e, 0x2960, 0x6000,
-	0xa085, 0x2000, 0x6002, 0x6104, 0xa18d, 0x0010, 0x6106, 0x027f,
-	0x0c7f, 0x1078, 0x3604, 0x00c0, 0x26ba, 0x69a0, 0xa184, 0x0200,
-	0x0040, 0x26b6, 0x1078, 0x3540, 0x0078, 0x26ba, 0xa184, 0x0400,
-	0x00c0, 0x2693, 0x69a0, 0xa184, 0x1000, 0x0040, 0x26c5, 0x6914,
-	0xa18c, 0xff00, 0x810f, 0x1078, 0x22ee, 0x007f, 0x7002, 0xa68c,
-	0x00e0, 0xa684, 0x0060, 0x0040, 0x26d3, 0xa086, 0x0060, 0x00c0,
-	0x26d3, 0xa18d, 0x4000, 0x88ff, 0x0040, 0x26d8, 0xa18d, 0x0004,
-	0x795a, 0x69b6, 0x789b, 0x0060, 0x2800, 0x78aa, 0x789b, 0x0061,
-	0x6818, 0xa08d, 0x8000, 0xa084, 0x7fff, 0x691a, 0xa68c, 0x0080,
-	0x0040, 0x26f7, 0x7097, 0x0000, 0xa08a, 0x000d, 0x0050, 0x26f5,
-	0xa08a, 0x000c, 0x7196, 0x2001, 0x000c, 0x800c, 0x719a, 0x78aa,
-	0x8008, 0x810c, 0x0040, 0x3407, 0xa18c, 0x00f8, 0x00c0, 0x3407,
+	0x5480, 0x2019, 0x0000, 0x72c8, 0xd2bc, 0x0040, 0x14e9, 0xa39d,
+	0x0010, 0xd2b4, 0x0040, 0x14ee, 0xa39d, 0x0008, 0x6800, 0x007e,
+	0xa226, 0x0040, 0x1511, 0x6a02, 0xa484, 0x2000, 0x0040, 0x14fa,
+	0xa39d, 0x0010, 0xa484, 0x1000, 0x0040, 0x1500, 0xa39d, 0x0008,
+	0xa484, 0x4000, 0x0040, 0x1511, 0x810f, 0xa284, 0x4000, 0x0040,
+	0x150d, 0x1078, 0x2399, 0x0078, 0x1511, 0x1078, 0x238b, 0x0078,
+	0x1511, 0x72cc, 0x6808, 0xa206, 0x0040, 0x1540, 0xa2a4, 0x00ff,
+	0x2061, 0x5240, 0x6118, 0xa186, 0x0028, 0x0040, 0x1527, 0xa186,
+	0x0032, 0x0040, 0x152d, 0xa186, 0x003c, 0x0040, 0x1533, 0xa482,
+	0x0064, 0x0048, 0x153d, 0x0078, 0x1537, 0xa482, 0x0050, 0x0048,
+	0x153d, 0x0078, 0x1537, 0xa482, 0x0043, 0x0048, 0x153d, 0x71c4,
+	0x71c6, 0x027f, 0x72ca, 0x0078, 0x127d, 0x6a0a, 0xa39d, 0x000a,
+	0x6804, 0xa305, 0x6806, 0x027f, 0x6b0c, 0x71c4, 0x0078, 0x1281,
+	0x77c4, 0x1078, 0x19c5, 0x2091, 0x8000, 0x6a14, 0x6b1c, 0x2091,
+	0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e, 0x2708, 0x0078, 0x1281,
+	0x70c4, 0x794c, 0x784e, 0x0078, 0x1283, 0x71c4, 0x72c8, 0x73cc,
+	0xa182, 0x0010, 0x00c8, 0x127c, 0x1078, 0x23a7, 0x0078, 0x1281,
+	0x77c4, 0x1078, 0x19c5, 0x2091, 0x8000, 0x6a08, 0xa295, 0x0002,
+	0x6a0a, 0x2091, 0x8001, 0x2708, 0x0078, 0x1282, 0x77c4, 0x1078,
+	0x19c5, 0x2091, 0x8000, 0x6a08, 0xa294, 0xfff9, 0x6a0a, 0x6804,
+	0xa005, 0x0040, 0x1585, 0x1078, 0x226f, 0x2091, 0x8001, 0x2708,
+	0x0078, 0x1282, 0x77c4, 0x1078, 0x19c5, 0x2091, 0x8000, 0x6a08,
+	0xa295, 0x0004, 0x6a0a, 0x6804, 0xa005, 0x0040, 0x1599, 0x1078,
+	0x226f, 0x2091, 0x8001, 0x2708, 0x0078, 0x1282, 0x77c4, 0x2041,
+	0x0001, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078,
+	0x19d2, 0x2091, 0x8001, 0x2708, 0x6a08, 0x0078, 0x1282, 0x77c4,
+	0x72c8, 0x73cc, 0x77c6, 0x72ca, 0x73ce, 0x1078, 0x1a52, 0x00c0,
+	0x15c7, 0x6818, 0xa005, 0x0040, 0x15c7, 0x2708, 0x1078, 0x23b7,
+	0x00c0, 0x15c7, 0x7817, 0x0015, 0x2091, 0x8001, 0x007c, 0x2091,
+	0x8001, 0x0078, 0x1284, 0x77c4, 0x77c6, 0x2041, 0x0021, 0x2049,
+	0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078, 0x19d2, 0x2061,
+	0x5240, 0x606f, 0x0003, 0x6782, 0x6093, 0x000f, 0x6073, 0x0000,
+	0x7817, 0x0016, 0x1078, 0x226f, 0x2091, 0x8001, 0x007c, 0x77c8,
+	0x77ca, 0x77c4, 0x77c6, 0xa7bc, 0xff00, 0x2091, 0x8000, 0x2061,
+	0x5240, 0x606f, 0x0002, 0x6073, 0x0000, 0x6782, 0x6093, 0x000f,
+	0x7817, 0x0017, 0x1078, 0x226f, 0x2091, 0x8001, 0x2041, 0x0021,
+	0x2049, 0x0004, 0x2051, 0x0010, 0x2091, 0x8000, 0x1078, 0x19d2,
+	0x70c8, 0x6836, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1606, 0x2091,
+	0x8001, 0x007c, 0x78cc, 0xa084, 0x0003, 0x00c0, 0x1636, 0x2039,
+	0x0000, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x1078,
+	0x19c5, 0x2091, 0x8000, 0x6808, 0xa80d, 0x690a, 0x2091, 0x8001,
+	0x8738, 0xa784, 0x001f, 0x00c0, 0x161f, 0xa7bc, 0xff00, 0x873f,
+	0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, 0x161f, 0x2091, 0x8000,
+	0x2069, 0x0100, 0x6830, 0xa084, 0x0040, 0x0040, 0x165f, 0x684b,
+	0x0004, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0004, 0x0040, 0x164c,
+	0x0070, 0x164c, 0x0078, 0x1643, 0x684b, 0x0009, 0x20a9, 0x0014,
+	0x6848, 0xa084, 0x0001, 0x0040, 0x1659, 0x0070, 0x1659, 0x0078,
+	0x1650, 0x20a9, 0x00fa, 0x0070, 0x165f, 0x0078, 0x165b, 0x2079,
+	0x5200, 0x7817, 0x0018, 0x2061, 0x5240, 0x606f, 0x0001, 0x6073,
+	0x0000, 0x6093, 0x000f, 0x78cc, 0xa085, 0x0002, 0x78ce, 0x6808,
+	0xa084, 0xfffd, 0x680a, 0x681b, 0x0048, 0x2091, 0x8001, 0x007c,
+	0x78cc, 0xa084, 0xfffd, 0x78ce, 0xa084, 0x0001, 0x00c0, 0x1682,
+	0x1078, 0x1a9c, 0x71c4, 0x71c6, 0x794a, 0x007c, 0x1078, 0x1bc4,
+	0x00c0, 0x129c, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x1693,
+	0x2029, 0x0000, 0x2520, 0x71c4, 0x73c8, 0x72cc, 0x71c6, 0x73ca,
+	0x72ce, 0x2079, 0x5200, 0x2091, 0x8000, 0x1078, 0x1980, 0x2091,
+	0x8001, 0x0040, 0x174a, 0x20a9, 0x0005, 0x20a1, 0x5218, 0x2091,
+	0x8000, 0x41a1, 0x2091, 0x8001, 0x2009, 0x0020, 0x1078, 0x197b,
+	0x0040, 0x16b6, 0x1078, 0x199a, 0x0078, 0x174a, 0x6004, 0xa084,
+	0xff00, 0x8007, 0x8009, 0x0040, 0x1719, 0x0c7e, 0x2c68, 0x2091,
+	0x8000, 0x1078, 0x1980, 0x2091, 0x8001, 0x0040, 0x16ea, 0x2c00,
+	0x689e, 0x8109, 0x00c0, 0x16be, 0x609f, 0x0000, 0x0c7f, 0x0c7e,
+	0x7218, 0x731c, 0x7420, 0x7524, 0x2c68, 0x689c, 0xa065, 0x0040,
+	0x1718, 0x2009, 0x0020, 0x1078, 0x197b, 0x00c0, 0x1701, 0x6004,
+	0xa084, 0x00ff, 0xa086, 0x0002, 0x00c0, 0x16ea, 0x2d00, 0x6002,
+	0x0078, 0x16d0, 0x0c7f, 0x0c7e, 0x609c, 0x2060, 0x1078, 0x1a17,
+	0x0c7f, 0x609f, 0x0000, 0x1078, 0x174e, 0x2009, 0x000c, 0x6008,
+	0xa085, 0x0200, 0x600a, 0x1078, 0x1976, 0x1078, 0x199a, 0x0078,
+	0x174a, 0x0c7f, 0x0c7e, 0x609c, 0x2060, 0x1078, 0x1a17, 0x0c7f,
+	0x609f, 0x0000, 0x1078, 0x174e, 0x2009, 0x000c, 0x6007, 0x0103,
+	0x601b, 0x0003, 0x1078, 0x1976, 0x1078, 0x199a, 0x0078, 0x174a,
+	0x0c7f, 0x74c4, 0x73c8, 0x72cc, 0x6014, 0x2091, 0x8000, 0x7817,
+	0x0012, 0x0e7e, 0x2071, 0x5240, 0x706f, 0x0005, 0x7073, 0x0000,
+	0x7376, 0x727a, 0x747e, 0x7082, 0x7087, 0x0000, 0x2c00, 0x708a,
+	0x708f, 0x0000, 0xa02e, 0x2530, 0x611c, 0x61a2, 0xa184, 0x0060,
+	0x0040, 0x173c, 0x1078, 0x48d3, 0x0e7f, 0x6596, 0x65a6, 0x669a,
+	0x66aa, 0x60af, 0x0000, 0x60b3, 0x0000, 0x1078, 0x226f, 0x2091,
+	0x8001, 0x007c, 0x70c3, 0x4005, 0x0078, 0x1287, 0x20a9, 0x0005,
+	0x2099, 0x5218, 0x2091, 0x8000, 0x530a, 0x2091, 0x8001, 0x2100,
+	0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x007c,
+	0x71c4, 0x70c7, 0x0000, 0x7906, 0x0078, 0x1284, 0x71c4, 0x71c6,
+	0x2168, 0x0078, 0x176d, 0x2069, 0x1000, 0x690c, 0xa016, 0x2d04,
+	0xa210, 0x8d68, 0x8109, 0x00c0, 0x176f, 0xa285, 0x0000, 0x00c0,
+	0x177d, 0x70c3, 0x4000, 0x0078, 0x177f, 0x70c3, 0x4003, 0x70ca,
+	0x0078, 0x1287, 0x2011, 0x5267, 0x220c, 0x70c4, 0x8003, 0x0048,
+	0x178f, 0x1078, 0x3c51, 0xa184, 0x7fff, 0x0078, 0x1793, 0x1078,
+	0x3c44, 0xa185, 0x8000, 0x2012, 0x0078, 0x1283, 0x71c4, 0x1078,
+	0x3c3b, 0x6100, 0x2001, 0x5267, 0x2004, 0xa084, 0x8000, 0xa10d,
+	0x6204, 0x6308, 0x0078, 0x1281, 0x79e4, 0x0078, 0x1283, 0x71c4,
+	0x71c6, 0x2198, 0x20a1, 0x0042, 0x20a9, 0x0004, 0x53a3, 0x21a0,
+	0x2099, 0x0042, 0x20a9, 0x0004, 0x53a3, 0x0078, 0x1284, 0x70c4,
+	0x2068, 0x2079, 0x5200, 0x2091, 0x8000, 0x1078, 0x1980, 0x2091,
+	0x8001, 0x0040, 0x1843, 0x6007, 0x0001, 0x600b, 0x0000, 0x602b,
+	0x0000, 0x601b, 0x0006, 0x6a10, 0xa28c, 0x000f, 0xa284, 0x00f0,
+	0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0x6016, 0xa284, 0x0800,
+	0x0040, 0x17de, 0x601b, 0x000a, 0x0078, 0x17e4, 0xa284, 0x1000,
+	0x0040, 0x17e4, 0x601b, 0x000c, 0xa284, 0x0300, 0x0040, 0x17ed,
+	0x602b, 0x0001, 0x8004, 0x8004, 0x8004, 0xa085, 0x0001, 0x601e,
+	0x6023, 0x0000, 0x6027, 0x0000, 0xa284, 0x0400, 0x0040, 0x17fa,
+	0x602b, 0x0000, 0x20a9, 0x0006, 0xac80, 0x000b, 0x20a0, 0xad80,
+	0x0005, 0x2098, 0x53a3, 0xa284, 0x0300, 0x00c0, 0x180f, 0x6046,
+	0x604a, 0x604e, 0x6052, 0x6096, 0x609a, 0x0078, 0x1819, 0x6800,
+	0x6046, 0x6804, 0x604a, 0x6e08, 0x664e, 0x6d0c, 0x6552, 0x6596,
+	0x669a, 0x6014, 0x2091, 0x8000, 0x7817, 0x0042, 0x2c08, 0x2061,
+	0x5240, 0x606f, 0x0005, 0x6073, 0x0000, 0x6077, 0x0000, 0x607b,
+	0x0000, 0x607f, 0x0000, 0x6082, 0x618a, 0xa284, 0x0400, 0x608e,
+	0x2091, 0x8001, 0x0e7e, 0x2071, 0x0020, 0x7007, 0x000a, 0x7007,
+	0x0002, 0x7003, 0x0000, 0x0e7f, 0x2091, 0x8000, 0x1078, 0x226f,
+	0x2091, 0x8001, 0x007c, 0x70c3, 0x4005, 0x0078, 0x1287, 0x0c7e,
+	0x0d7e, 0x0e7e, 0x0f7e, 0x2091, 0x8000, 0x2071, 0x5240, 0x2079,
+	0x0100, 0x2061, 0x0010, 0x70a0, 0xa06d, 0x0040, 0x1903, 0x6a04,
+	0xa294, 0x00ff, 0xa286, 0x0007, 0x0040, 0x1862, 0xa286, 0x000f,
+	0x00c0, 0x1903, 0x691c, 0xa184, 0x00c0, 0x0040, 0x1903, 0xa184,
+	0x0080, 0x00c0, 0x18d3, 0x6824, 0xa084, 0xff00, 0xa085, 0x0019,
+	0x6826, 0x71b0, 0x81ff, 0x0040, 0x1889, 0x0d7e, 0x2069, 0x0020,
+	0x6807, 0x0010, 0x6908, 0x6808, 0xa106, 0x00c0, 0x187a, 0x690c,
+	0x680c, 0xa106, 0x00c0, 0x187f, 0xa184, 0x00ff, 0x00c0, 0x187f,
+	0x0d7f, 0x78b8, 0xa084, 0x801f, 0x00c0, 0x1889, 0x7848, 0xa085,
+	0x000c, 0x784a, 0x71b0, 0x81ff, 0x0040, 0x18ac, 0x70b3, 0x0000,
+	0x0d7e, 0x2069, 0x0020, 0x6807, 0x0018, 0x6804, 0xa084, 0x0008,
+	0x00c0, 0x189d, 0x6807, 0x0008, 0x6804, 0xa084, 0x0008, 0x00c0,
+	0x18a4, 0x6807, 0x0002, 0x0d7f, 0x61c4, 0x62c8, 0x63cc, 0x61c6,
+	0x62ca, 0x63ce, 0x0e7e, 0x2071, 0x5200, 0x7266, 0x736a, 0xae80,
+	0x0019, 0x0e7f, 0x7848, 0xa084, 0x000c, 0x00c0, 0x18ba, 0x1078,
+	0x47e1, 0x78a3, 0x0000, 0x7858, 0xa084, 0xedff, 0x785a, 0x70b4,
+	0xa080, 0x00da, 0x781a, 0x0f7f, 0x0e7f, 0x0d7f, 0x0c7f, 0x2091,
+	0x8001, 0x0078, 0x1284, 0x6824, 0xa084, 0xff00, 0xa085, 0x0019,
+	0x6826, 0x78b8, 0xa084, 0x801f, 0x00c0, 0x18d9, 0x7848, 0xa085,
+	0x000c, 0x784a, 0x7848, 0xa084, 0x000c, 0x00c0, 0x18e2, 0x71b0,
+	0x81ff, 0x0040, 0x1901, 0x70b3, 0x0000, 0x0d7e, 0x2069, 0x0020,
+	0x6807, 0x0018, 0x6804, 0xa084, 0x0008, 0x00c0, 0x18f2, 0x6807,
+	0x0008, 0x6804, 0xa084, 0x0008, 0x00c0, 0x18f9, 0x6807, 0x0002,
+	0x0d7f, 0x0078, 0x18cb, 0x0f7f, 0x0e7f, 0x0d7f, 0x0c7f, 0x2091,
+	0x8001, 0x2001, 0x4005, 0x0078, 0x1286, 0x7980, 0x71c6, 0x71c4,
+	0xa182, 0x0003, 0x00c8, 0x127c, 0x7982, 0x0078, 0x1284, 0x7980,
+	0x71c6, 0x0078, 0x1284, 0x7974, 0x71c6, 0x71c4, 0x7976, 0x7978,
+	0x71ca, 0x71c8, 0x797a, 0x797c, 0x71ce, 0x71cc, 0x797e, 0x0078,
+	0x1284, 0x7974, 0x71c6, 0x7978, 0x71ca, 0x797c, 0x71ce, 0x0078,
+	0x1284, 0x7900, 0x71c6, 0x71c4, 0x7902, 0x2001, 0x04fd, 0x2004,
+	0xa082, 0x0005, 0x0048, 0x1940, 0x0038, 0x1942, 0x0078, 0x194c,
+	0x00a8, 0x194c, 0xa18c, 0x0001, 0x00c0, 0x194a, 0x20b9, 0x2222,
+	0x0078, 0x194c, 0x20b9, 0x1212, 0x0078, 0x1284, 0x7900, 0x71c6,
+	0x0078, 0x1284, 0x2009, 0x5274, 0x2104, 0x70c6, 0x70c4, 0x200a,
+	0x0078, 0x1284, 0x2009, 0x5274, 0x2104, 0x70c6, 0x0078, 0x1284,
+	0x71c4, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e8,
+	0x5480, 0x6a14, 0xd2b4, 0x0040, 0x1971, 0x2011, 0x0001, 0x0078,
+	0x1973, 0x2011, 0x0000, 0x6b0c, 0x0078, 0x1281, 0xac80, 0x0001,
+	0x1078, 0x1b80, 0x007c, 0xac80, 0x0001, 0x1078, 0x1b20, 0x007c,
+	0x7850, 0xa065, 0x0040, 0x1988, 0x2c04, 0x7852, 0x2063, 0x0000,
+	0x007c, 0x0f7e, 0x2079, 0x5200, 0x7850, 0xa06d, 0x0040, 0x1998,
+	0x2d04, 0x7852, 0x6803, 0x0000, 0x6807, 0x0000, 0x680b, 0x0000,
+	0x0f7f, 0x007c, 0x2091, 0x8000, 0x0f7e, 0x2079, 0x5200, 0x7850,
+	0x2062, 0x2c00, 0xa005, 0x00c0, 0x19a7, 0x1078, 0x248c, 0x7852,
+	0x0f7f, 0x2091, 0x8001, 0x007c, 0x0f7e, 0x2079, 0x5200, 0x7850,
+	0x206a, 0x2d00, 0x7852, 0x0f7f, 0x007c, 0x2011, 0x7900, 0x7a52,
+	0x7bec, 0x8319, 0x0040, 0x19c2, 0xa280, 0x0031, 0x2012, 0x2010,
+	0x0078, 0x19b9, 0x2013, 0x0000, 0x007c, 0xa784, 0x0f00, 0x800b,
+	0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa0e8,
+	0x5500, 0x007c, 0x1078, 0x19c5, 0x2900, 0x682a, 0x2a00, 0x682e,
+	0x6808, 0xa084, 0xffef, 0xa80d, 0x690a, 0x2009, 0x5252, 0x210c,
+	0x6804, 0xa005, 0x0040, 0x1a04, 0xa116, 0x00c0, 0x19ef, 0x2060,
+	0x6000, 0x6806, 0x017e, 0x200b, 0x0000, 0x0078, 0x19f2, 0x2009,
+	0x0000, 0x017e, 0x6804, 0xa065, 0x0040, 0x1a01, 0x6000, 0x6806,
+	0x1078, 0x1a31, 0x1078, 0x1ccb, 0x6810, 0x8001, 0x6812, 0x00c0,
+	0x19f2, 0x017f, 0x6902, 0x6906, 0x007c, 0xa065, 0x0040, 0x1a16,
+	0x2008, 0x609c, 0xa005, 0x0040, 0x1a13, 0x2062, 0x609f, 0x0000,
+	0xa065, 0x0078, 0x1a09, 0x7850, 0x7952, 0x2062, 0x007c, 0xa065,
+	0x0040, 0x1a30, 0x2008, 0x609c, 0xa005, 0x0040, 0x1a25, 0x2062,
+	0x609f, 0x0000, 0xa065, 0x0078, 0x1a1b, 0x0f7e, 0x2079, 0x5200,
+	0x2091, 0x8000, 0x7850, 0x7952, 0x0f7f, 0x2062, 0x2091, 0x8001,
+	0x007c, 0x6007, 0x0103, 0x608f, 0x0000, 0x20a9, 0x001c, 0xac80,
+	0x0005, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x6828, 0x601a, 0x682c,
+	0x6022, 0x007c, 0x0e7e, 0x2071, 0x5240, 0x704c, 0xa08c, 0x0200,
+	0x00c0, 0x1a50, 0xa088, 0x5280, 0x2d0a, 0x8000, 0x704e, 0xa006,
+	0x0e7f, 0x007c, 0x1078, 0x19c5, 0x2091, 0x8000, 0x6804, 0x781e,
+	0xa065, 0x0040, 0x1a9b, 0x0078, 0x1a63, 0x2c00, 0x781e, 0x6000,
+	0xa065, 0x0040, 0x1a9b, 0x600c, 0xa306, 0x00c0, 0x1a5d, 0x6010,
+	0xa206, 0x00c0, 0x1a5d, 0x2c28, 0x2001, 0x5252, 0x2004, 0xac06,
+	0x00c0, 0x1a74, 0x0078, 0x1a99, 0x6804, 0xac06, 0x00c0, 0x1a81,
+	0x6000, 0xa065, 0x6806, 0x00c0, 0x1a8b, 0x6803, 0x0000, 0x0078,
+	0x1a8b, 0x6400, 0x781c, 0x2060, 0x6402, 0xa486, 0x0000, 0x00c0,
+	0x1a8b, 0x2c00, 0x6802, 0x2560, 0x1078, 0x1a31, 0x601b, 0x0005,
+	0x6023, 0x0020, 0x1078, 0x1ccb, 0x6810, 0x8001, 0x1050, 0x248c,
+	0x6812, 0xa085, 0xffff, 0x007c, 0x2039, 0x0000, 0x2041, 0x0021,
+	0x2049, 0x0004, 0x2051, 0x0008, 0x2091, 0x8000, 0x1078, 0x19d2,
+	0x8738, 0xa784, 0x001f, 0x00c0, 0x1aa6, 0xa7bc, 0xff00, 0x873f,
+	0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, 0x1aa6, 0x2091, 0x8001,
+	0x007c, 0x2061, 0x0000, 0x6018, 0xa084, 0x0001, 0x00c0, 0x1aca,
+	0x2091, 0x8000, 0x78e0, 0x78e3, 0x0000, 0x2091, 0x8001, 0xa005,
+	0x00c0, 0x1acb, 0x007c, 0xa08c, 0xfff0, 0x0040, 0x1ad1, 0x1078,
+	0x248c, 0x0079, 0x1ad3, 0x1ae3, 0x1ae6, 0x1aec, 0x1af0, 0x1ae4,
+	0x1af4, 0x1afa, 0x1ae4, 0x1ae4, 0x1c95, 0x1cb9, 0x1cbd, 0x1ae4,
+	0x1ae4, 0x1ae4, 0x1ae4, 0x007c, 0x1078, 0x248c, 0x1078, 0x1a9c,
+	0x2001, 0x8001, 0x0078, 0x1cc3, 0x2001, 0x8003, 0x0078, 0x1cc3,
+	0x2001, 0x8004, 0x0078, 0x1cc3, 0x1078, 0x1a9c, 0x2001, 0x8006,
+	0x0078, 0x1cc3, 0x2001, 0x8007, 0x0078, 0x1cc3, 0x2030, 0x2138,
+	0xa782, 0x0021, 0x0048, 0x1b06, 0x2009, 0x0020, 0x2600, 0x1078,
+	0x1b20, 0x00c0, 0x1b1f, 0xa7ba, 0x0020, 0x0048, 0x1b1e, 0x0040,
+	0x1b1e, 0x2708, 0xa6b0, 0x0020, 0xa290, 0x0040, 0xa399, 0x0000,
+	0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x0078, 0x1b00, 0xa006, 0x007c,
+	0x81ff, 0x0040, 0x1b5b, 0x2099, 0x0030, 0x20a0, 0x700c, 0xa084,
+	0x00ff, 0x0040, 0x1b32, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004,
+	0x00c0, 0x1b2d, 0x21a8, 0x7017, 0x0000, 0x810b, 0x7112, 0x721a,
+	0x731e, 0x7422, 0x7526, 0x780c, 0xa085, 0x0001, 0x7002, 0x7007,
+	0x0001, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x00c8, 0x1b4f,
+	0x2009, 0x0022, 0x2104, 0xa084, 0x4000, 0x00c0, 0x1b41, 0x7008,
+	0x800b, 0x00c8, 0x1b41, 0x7007, 0x0002, 0xa08c, 0x01e0, 0x00c0,
+	0x1b5b, 0x53a5, 0xa006, 0x7003, 0x0000, 0x007c, 0x2030, 0x2138,
+	0xa782, 0x0021, 0x0048, 0x1b66, 0x2009, 0x0020, 0x2600, 0x1078,
+	0x1b80, 0x00c0, 0x1b7f, 0xa7ba, 0x0020, 0x0048, 0x1b7e, 0x0040,
+	0x1b7e, 0x2708, 0xa6b0, 0x0020, 0xa290, 0x0040, 0xa399, 0x0000,
+	0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x0078, 0x1b60, 0xa006, 0x007c,
+	0x81ff, 0x0040, 0x1bc1, 0x2098, 0x20a1, 0x0030, 0x700c, 0xa084,
+	0x00ff, 0x0040, 0x1b92, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004,
+	0x00c0, 0x1b8d, 0x21a8, 0x7017, 0x0000, 0x810b, 0x7112, 0x721a,
+	0x731e, 0x7422, 0x7526, 0x780c, 0xa085, 0x0000, 0x7002, 0x53a6,
+	0x7007, 0x0001, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x00c8,
+	0x1bb0, 0x2009, 0x0022, 0x2104, 0xa084, 0x4000, 0x00c0, 0x1ba2,
+	0x7010, 0xa084, 0xf000, 0x0040, 0x1bb9, 0x7007, 0x0008, 0x0078,
+	0x1bbd, 0x7108, 0x8103, 0x00c8, 0x1ba2, 0x7007, 0x0002, 0xa184,
+	0x01e0, 0x7003, 0x0000, 0x007c, 0x2001, 0x04fd, 0x2004, 0xa082,
+	0x0004, 0x00c8, 0x1bcd, 0x0078, 0x1bd0, 0xa006, 0x0078, 0x1bd2,
+	0xa085, 0x0001, 0x007c, 0x0e7e, 0x2071, 0x5200, 0x2d08, 0x7058,
+	0x6802, 0xa005, 0x00c0, 0x1bdd, 0x715e, 0x715a, 0x0e7f, 0x007c,
+	0x2c08, 0x7858, 0x6002, 0xa005, 0x00c0, 0x1be7, 0x795e, 0x795a,
+	0x007c, 0x2091, 0x8000, 0x6114, 0x1078, 0x2180, 0x6900, 0xa184,
+	0x0100, 0x00c0, 0x2035, 0xa184, 0x0200, 0x00c0, 0x2031, 0x681c,
+	0xa005, 0x00c0, 0x203d, 0x6003, 0x0000, 0x2c08, 0x785c, 0xa065,
+	0x00c0, 0x1c05, 0x795a, 0x0078, 0x1c06, 0x6102, 0x795e, 0x2091,
+	0x8001, 0x1078, 0x228c, 0x007c, 0x0e7e, 0x2071, 0x5200, 0x7058,
+	0xa06d, 0x0040, 0x1c1a, 0x6800, 0x705a, 0xa005, 0x00c0, 0x1c19,
+	0x705e, 0x8dff, 0x0e7f, 0x007c, 0x0d7e, 0x0c7e, 0x0f7e, 0x2079,
+	0x5200, 0xaf80, 0x0016, 0x2060, 0x6000, 0xa005, 0x0040, 0x1c43,
+	0x2068, 0x6814, 0xa306, 0x00c0, 0x1c33, 0x6828, 0xa084, 0x00ff,
+	0xa406, 0x0040, 0x1c36, 0x2d60, 0x0078, 0x1c24, 0x6800, 0xa005,
+	0x6002, 0x00c0, 0x1c42, 0xaf80, 0x0016, 0xac06, 0x0040, 0x1c41,
+	0x2c00, 0x785e, 0x2d00, 0x0f7f, 0x0c7f, 0x0d7f, 0xa005, 0x007c,
+	0x0d7e, 0x0c7e, 0x0f7e, 0x2079, 0x5200, 0xaf80, 0x0016, 0x2060,
+	0x6000, 0xa005, 0x0040, 0x1c6b, 0x2068, 0x6814, 0xa084, 0x00ff,
+	0xa306, 0x0040, 0x1c5e, 0x2d60, 0x0078, 0x1c50, 0x6800, 0xa005,
+	0x6002, 0x00c0, 0x1c6a, 0xaf80, 0x0016, 0xac06, 0x0040, 0x1c69,
+	0x2c00, 0x785e, 0x2d00, 0x0f7f, 0x0c7f, 0x0d7f, 0xa005, 0x007c,
+	0x0d7e, 0x0c7e, 0x0f7e, 0x2079, 0x5200, 0xaf80, 0x0016, 0x2060,
+	0x6000, 0xa06d, 0x0040, 0x1c90, 0x6814, 0xa306, 0x0040, 0x1c83,
+	0x2d60, 0x0078, 0x1c78, 0x6800, 0xa005, 0x6002, 0x00c0, 0x1c8f,
+	0xaf80, 0x0016, 0xac06, 0x0040, 0x1c8e, 0x2c00, 0x785e, 0x2d00,
+	0x0f7f, 0x0c7f, 0x0d7f, 0xa005, 0x007c, 0x2091, 0x8000, 0x2069,
+	0x5240, 0x6800, 0xa086, 0x0000, 0x0040, 0x1ca3, 0x2091, 0x8001,
+	0x78e3, 0x0009, 0x007c, 0x6880, 0xa0bc, 0xff00, 0x2041, 0x0021,
+	0x2049, 0x0004, 0x2051, 0x0010, 0x1078, 0x19d2, 0x8738, 0xa784,
+	0x001f, 0x00c0, 0x1cac, 0x2091, 0x8001, 0x2001, 0x800a, 0x0078,
+	0x1cc3, 0x2001, 0x800c, 0x0078, 0x1cc3, 0x1078, 0x1a9c, 0x2001,
+	0x800d, 0x0078, 0x1cc3, 0x70c2, 0x2061, 0x0000, 0x601b, 0x0001,
+	0x2091, 0x4080, 0x007c, 0x6004, 0x2c08, 0x2063, 0x0000, 0x7884,
+	0x8000, 0x7886, 0x7888, 0xa005, 0x798a, 0x0040, 0x1cda, 0x2c02,
+	0x0078, 0x1cdb, 0x798e, 0x007c, 0x6807, 0x0103, 0x0c7e, 0x2061,
+	0x5200, 0x2d08, 0x206b, 0x0000, 0x6084, 0x8000, 0x6086, 0x6088,
+	0xa005, 0x618a, 0x0040, 0x1cef, 0x2d02, 0x0078, 0x1cf0, 0x618e,
+	0x0c7f, 0x007c, 0x1078, 0x1d03, 0x0040, 0x1d02, 0x0c7e, 0x609c,
+	0xa065, 0x0040, 0x1cfd, 0x1078, 0x1a17, 0x0c7f, 0x609f, 0x0000,
+	0x1078, 0x199a, 0x007c, 0x788c, 0xa065, 0x0040, 0x1d15, 0x2091,
+	0x8000, 0x7884, 0x8001, 0x7886, 0x2c04, 0x788e, 0xa005, 0x00c0,
+	0x1d13, 0x788a, 0x8000, 0x2091, 0x8001, 0x007c, 0x20a9, 0x0010,
+	0xa006, 0x8004, 0x8086, 0x818e, 0x00c8, 0x1d1f, 0xa200, 0x0070,
+	0x1d23, 0x0078, 0x1d1a, 0x8086, 0x818e, 0x007c, 0x157e, 0x20a9,
+	0x0010, 0xa005, 0x0040, 0x1d49, 0xa11a, 0x00c8, 0x1d49, 0x8213,
+	0x818d, 0x0048, 0x1d3a, 0xa11a, 0x00c8, 0x1d3b, 0x0070, 0x1d41,
+	0x0078, 0x1d2f, 0xa11a, 0x2308, 0x8210, 0x0070, 0x1d41, 0x0078,
+	0x1d2f, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f, 0x157f,
+	0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078, 0x1d45, 0x7994,
+	0x70d0, 0xa106, 0x0040, 0x1dbd, 0x2091, 0x8000, 0x2071, 0x0020,
+	0x7004, 0xa005, 0x00c0, 0x1dbd, 0x7008, 0x7208, 0xa206, 0x00c0,
+	0x1dbd, 0xa286, 0x0008, 0x00c0, 0x1dbd, 0x2071, 0x0010, 0x1078,
+	0x1980, 0x0040, 0x1dbd, 0x7a9c, 0x7b98, 0x7ca4, 0x7da0, 0xa184,
+	0xff00, 0x0040, 0x1d8b, 0x2031, 0x0000, 0x810b, 0x86b5, 0x810b,
+	0x86b5, 0x810b, 0x86b5, 0x810b, 0x86b5, 0x810b, 0x86b5, 0x810b,
+	0x86b5, 0x2100, 0xa210, 0x2600, 0xa319, 0xa4a1, 0x0000, 0xa5a9,
+	0x0000, 0x0078, 0x1d95, 0x8107, 0x8004, 0x8004, 0xa210, 0xa399,
+	0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x2009, 0x0020, 0x1078,
+	0x197b, 0x2091, 0x8001, 0x0040, 0x1db4, 0x1078, 0x199a, 0x78a8,
+	0x8000, 0x78aa, 0xa086, 0x0002, 0x00c0, 0x1dbd, 0x2091, 0x8000,
+	0x78e3, 0x0002, 0x78ab, 0x0000, 0x78cc, 0xa085, 0x0003, 0x78ce,
+	0x2091, 0x8001, 0x0078, 0x1dbd, 0x78ab, 0x0000, 0x1078, 0x2149,
+	0x6004, 0xa084, 0x000f, 0x0079, 0x1dc2, 0x2071, 0x0010, 0x2091,
+	0x8001, 0x007c, 0x1dd2, 0x1df4, 0x1e1a, 0x1dd2, 0x1e37, 0x1de1,
+	0x1fc9, 0x1fe4, 0x1dd2, 0x1dee, 0x1e14, 0x1e7f, 0x1eee, 0x1f57,
+	0x1f69, 0x1fe0, 0x2039, 0x0400, 0x78dc, 0xa705, 0x78de, 0x6008,
+	0xa705, 0x600a, 0x1078, 0x2064, 0x609c, 0x78da, 0x1078, 0x2131,
+	0x007c, 0x78dc, 0xa084, 0x0100, 0x0040, 0x1de8, 0x0078, 0x1dd2,
+	0x601c, 0xa085, 0x0080, 0x601e, 0x0078, 0x1dfb, 0x1078, 0x1bc4,
+	0x00c0, 0x1dd2, 0x1078, 0x2163, 0x78dc, 0xa084, 0x0100, 0x0040,
+	0x1dfb, 0x0078, 0x1dd2, 0x78df, 0x0000, 0x6004, 0x8007, 0xa084,
+	0x00ff, 0x78d2, 0x8001, 0x609f, 0x0000, 0x0040, 0x1e11, 0x1078,
+	0x2064, 0x0040, 0x1e11, 0x78dc, 0xa085, 0x0100, 0x78de, 0x0078,
+	0x1e13, 0x1078, 0x2088, 0x007c, 0x1078, 0x1bc4, 0x00c0, 0x1dd2,
+	0x1078, 0x215f, 0x78dc, 0xa08c, 0x0e00, 0x00c0, 0x1e23, 0xa084,
+	0x0100, 0x00c0, 0x1e25, 0x0078, 0x1dd2, 0x1078, 0x2064, 0x00c0,
+	0x1e36, 0x6104, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x2021,
+	0xa186, 0x000f, 0x0040, 0x2021, 0x1078, 0x2088, 0x007c, 0x78dc,
+	0xa084, 0x0100, 0x0040, 0x1e3e, 0x0078, 0x1dd2, 0x78df, 0x0000,
+	0x6714, 0x2011, 0x0001, 0x20a9, 0x0001, 0x6018, 0xa084, 0x00ff,
+	0xa005, 0x0040, 0x1e61, 0x2011, 0x0001, 0xa7bc, 0xff00, 0x20a9,
+	0x0020, 0xa08e, 0x0001, 0x0040, 0x1e61, 0x2039, 0x0000, 0x2011,
+	0x0002, 0x20a9, 0x0100, 0xa08e, 0x0002, 0x0040, 0x1e61, 0x0078,
+	0x1e7c, 0x1078, 0x19c5, 0x2091, 0x8000, 0x682b, 0x0000, 0x682f,
+	0x0000, 0x6808, 0xa084, 0xffde, 0x680a, 0xade8, 0x0010, 0x2091,
+	0x8001, 0x0070, 0x1e75, 0x0078, 0x1e63, 0x8211, 0x0040, 0x1e7c,
+	0x20a9, 0x0100, 0x0078, 0x1e63, 0x1078, 0x199a, 0x007c, 0x2001,
+	0x5267, 0x2004, 0xa084, 0x8000, 0x0040, 0x2049, 0x6114, 0x1078,
+	0x2180, 0x6900, 0xa184, 0x0001, 0x0040, 0x1ea0, 0x6028, 0xa084,
+	0x00ff, 0x00c0, 0x2041, 0x6800, 0xa084, 0x0001, 0x0040, 0x2049,
+	0x6803, 0x0000, 0x680b, 0x0000, 0x6807, 0x0000, 0x0078, 0x2051,
+	0x2011, 0x0001, 0x6020, 0xd0f4, 0x0040, 0x1ea8, 0xa295, 0x0002,
+	0xd0c4, 0x0040, 0x1ead, 0xa295, 0x0008, 0xd0cc, 0x0040, 0x1eb2,
+	0xa295, 0x0400, 0x601c, 0xa084, 0x0002, 0x0040, 0x1eb9, 0xa295,
+	0x0004, 0x602c, 0xa08c, 0x00ff, 0xa182, 0x0002, 0x0048, 0x204d,
+	0xa182, 0x001b, 0x00c8, 0x204d, 0x0040, 0x204d, 0x690e, 0x602c,
+	0x8007, 0xa08c, 0x00ff, 0xa182, 0x0002, 0x0048, 0x204d, 0xa182,
+	0x001b, 0x00c8, 0x204d, 0x0040, 0x204d, 0x6912, 0x6030, 0xa005,
+	0x00c0, 0x1edc, 0x2001, 0x001e, 0x8000, 0x6816, 0x6028, 0xa084,
+	0x00ff, 0x0040, 0x2049, 0x6806, 0x6028, 0x8007, 0xa084, 0x00ff,
+	0x0040, 0x2049, 0x680a, 0x6a02, 0x0078, 0x2051, 0x2001, 0x5240,
+	0x2004, 0xa086, 0x0007, 0x00c0, 0x1f53, 0x2001, 0x5267, 0x2004,
+	0xa084, 0x8000, 0x0040, 0x2049, 0x6114, 0x1078, 0x2180, 0x2001,
+	0x5252, 0x2004, 0x2010, 0x82ff, 0x0040, 0x1f0e, 0xa080, 0x0005,
+	0x2004, 0xa084, 0x00ff, 0xa106, 0x00c0, 0x1f53, 0x2091, 0x8000,
+	0x6a04, 0x6b08, 0x6418, 0xa484, 0x0003, 0x0040, 0x1f2d, 0x6128,
+	0xa18c, 0x00ff, 0x8001, 0x00c0, 0x1f23, 0x2100, 0xa210, 0x0048,
+	0x1f53, 0x0078, 0x1f2d, 0x8001, 0x00c0, 0x1f53, 0x2100, 0xa212,
+	0x0048, 0x1f53, 0x82ff, 0x0040, 0x1f53, 0xa484, 0x000c, 0x0040,
+	0x1f47, 0x6128, 0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004, 0x00c0,
+	0x1f3f, 0x2100, 0xa318, 0x0048, 0x1f53, 0x0078, 0x1f47, 0xa082,
+	0x0004, 0x00c0, 0x1f53, 0x2100, 0xa31a, 0x0048, 0x1f53, 0x6030,
+	0xa005, 0x0040, 0x1f4d, 0x8000, 0x6816, 0x6a06, 0x6b0a, 0x2091,
+	0x8001, 0x0078, 0x2051, 0x2091, 0x8001, 0x0078, 0x204d, 0x6114,
+	0x1078, 0x2180, 0x2091, 0x8000, 0x6b08, 0x8318, 0x0048, 0x1f65,
+	0x6b0a, 0x2091, 0x8001, 0x0078, 0x2060, 0x2091, 0x8001, 0x0078,
+	0x204d, 0x6024, 0x8007, 0xa084, 0x00ff, 0x0040, 0x1f87, 0xa086,
+	0x0080, 0x00c0, 0x1fc7, 0x20a9, 0x0008, 0x2069, 0x7610, 0x2091,
+	0x8000, 0x6800, 0xa084, 0xfcff, 0x6802, 0xade8, 0x0008, 0x0070,
+	0x1f83, 0x0078, 0x1f79, 0x2091, 0x8001, 0x0078, 0x2051, 0x6028,
+	0xa015, 0x0040, 0x1fc7, 0x6114, 0x1078, 0x2180, 0x0c7e, 0x0d7e,
+	0xade8, 0x0007, 0x2091, 0x8000, 0x6800, 0xa00d, 0x0040, 0x1fc3,
+	0xa206, 0x0040, 0x1f9e, 0x2168, 0x0078, 0x1f94, 0x2160, 0x6000,
+	0x6802, 0x2c68, 0x1078, 0x19ac, 0x0d7f, 0x6818, 0xa00d, 0x0040,
+	0x1fbb, 0x2060, 0x6200, 0x6a1a, 0x6a1c, 0x6202, 0x681e, 0x1078,
+	0x1989, 0x2da0, 0x2198, 0x20a9, 0x0031, 0x53a3, 0x2d60, 0x1078,
+	0x1ccb, 0x0078, 0x1fbe, 0x6808, 0x8000, 0x680a, 0x2091, 0x8001,
+	0x0c7f, 0x0078, 0x2060, 0x2091, 0x8001, 0x0d7f, 0x0c7f, 0x0078,
+	0x2049, 0x6114, 0x1078, 0x2180, 0x6800, 0xa084, 0x0001, 0x0040,
+	0x2039, 0x2091, 0x8000, 0x6a04, 0x8210, 0x0048, 0x1fdc, 0x6a06,
+	0x2091, 0x8001, 0x0078, 0x2060, 0x2091, 0x8001, 0x0078, 0x204d,
+	0x1078, 0x1bc4, 0x00c0, 0x1dd2, 0x6114, 0x1078, 0x2180, 0x60be,
+	0x60bb, 0x0000, 0x6900, 0xa184, 0x0008, 0x0040, 0x1ff3, 0x6020,
+	0xa085, 0x0100, 0x6022, 0xa184, 0x0001, 0x0040, 0x2049, 0xa184,
+	0x0100, 0x00c0, 0x2035, 0xa184, 0x0200, 0x00c0, 0x2031, 0x681c,
+	0xa005, 0x00c0, 0x203d, 0x6004, 0xa084, 0x00ff, 0xa086, 0x000f,
+	0x00c0, 0x200c, 0x1078, 0x2163, 0x78df, 0x0000, 0x6004, 0x8007,
+	0xa084, 0x00ff, 0x78d2, 0x8001, 0x609f, 0x0000, 0x0040, 0x2021,
+	0x1078, 0x2064, 0x0040, 0x2021, 0x78dc, 0xa085, 0x0100, 0x78de,
+	0x007c, 0x78d7, 0x0000, 0x78db, 0x0000, 0x6024, 0xa084, 0xff00,
+	0x6026, 0x1078, 0x3aac, 0x0040, 0x1d4f, 0x1078, 0x1be9, 0x0078,
+	0x1d4f, 0x2009, 0x0017, 0x0078, 0x2053, 0x2009, 0x000e, 0x0078,
+	0x2053, 0x2009, 0x0007, 0x0078, 0x2053, 0x2009, 0x0035, 0x0078,
+	0x2053, 0x2009, 0x003e, 0x0078, 0x2053, 0x2009, 0x0004, 0x0078,
+	0x2053, 0x2009, 0x0006, 0x0078, 0x2053, 0x2009, 0x0016, 0x0078,
+	0x2053, 0x2009, 0x0001, 0x6024, 0xa084, 0xff00, 0xa105, 0x6026,
+	0x2091, 0x8000, 0x1078, 0x1ccb, 0x2091, 0x8001, 0x0078, 0x1d4f,
+	0x1078, 0x199a, 0x0078, 0x1d4f, 0x78d4, 0xa06d, 0x00c0, 0x206f,
+	0x2c00, 0x78d6, 0x78da, 0x609f, 0x0000, 0x0078, 0x207b, 0x2c00,
+	0x689e, 0x609f, 0x0000, 0x78d6, 0x2d00, 0x6002, 0x78d8, 0xad06,
+	0x00c0, 0x207b, 0x6002, 0x78d0, 0x8001, 0x78d2, 0x00c0, 0x2087,
+	0x78dc, 0xa084, 0xfeff, 0x78de, 0x78d8, 0x2060, 0xa006, 0x007c,
+	0xa02e, 0x2530, 0x611c, 0x61a2, 0xa184, 0xe1ff, 0x601e, 0xa184,
+	0x0060, 0x0040, 0x2097, 0x0e7e, 0x1078, 0x48d3, 0x0e7f, 0x6596,
+	0x65a6, 0x669a, 0x66aa, 0x60af, 0x0000, 0x60b3, 0x0000, 0x6714,
+	0x1078, 0x19c5, 0x2091, 0x8000, 0x60a0, 0xa084, 0x8000, 0x00c0,
+	0x20be, 0x6808, 0xa084, 0x0001, 0x0040, 0x20be, 0x2091, 0x8001,
+	0x1078, 0x1a31, 0x2091, 0x8000, 0x1078, 0x1ccb, 0x2091, 0x8001,
+	0x78d7, 0x0000, 0x78db, 0x0000, 0x0078, 0x2130, 0x6024, 0xa096,
+	0x0001, 0x00c0, 0x20c5, 0x8000, 0x6026, 0x6a10, 0x6814, 0x2091,
+	0x8001, 0xa202, 0x0048, 0x20d4, 0x0040, 0x20d4, 0x2039, 0x0200,
+	0x1078, 0x2131, 0x0078, 0x2130, 0x2c08, 0x2091, 0x8000, 0x60a0,
+	0xa084, 0x8000, 0x0040, 0x2101, 0x6800, 0xa065, 0x0040, 0x2106,
+	0x6a04, 0x0e7e, 0x2071, 0x5240, 0x7000, 0xa084, 0x0001, 0x0040,
+	0x20fb, 0x7048, 0xa206, 0x00c0, 0x20fb, 0x6b04, 0x231c, 0x2160,
+	0x6302, 0x2300, 0xa005, 0x00c0, 0x20f6, 0x6902, 0x2260, 0x6102,
+	0x0e7f, 0x0078, 0x210d, 0x2160, 0x6202, 0x6906, 0x0e7f, 0x0078,
+	0x210d, 0x6800, 0xa065, 0x0040, 0x2106, 0x6102, 0x6902, 0x00c0,
+	0x210a, 0x6906, 0x2160, 0x6003, 0x0000, 0x2160, 0x60a0, 0xa084,
+	0x8000, 0x0040, 0x2117, 0x6808, 0xa084, 0xfffc, 0x680a, 0x6810,
+	0x8000, 0x6812, 0x2091, 0x8001, 0x6808, 0xa08c, 0x0040, 0x0040,
+	0x2126, 0xa086, 0x0040, 0x680a, 0x1078, 0x1a42, 0x2091, 0x8000,
+	0x1078, 0x226f, 0x2091, 0x8001, 0x78db, 0x0000, 0x78d7, 0x0000,
+	0x007c, 0x6008, 0xa705, 0x600a, 0x2091, 0x8000, 0x1078, 0x1ccb,
+	0x2091, 0x8001, 0x78d8, 0xa065, 0x0040, 0x2144, 0x609c, 0x78da,
+	0x609f, 0x0000, 0x0078, 0x2134, 0x78d7, 0x0000, 0x78db, 0x0000,
+	0x007c, 0x7990, 0x7894, 0x8000, 0xa10a, 0x00c8, 0x2150, 0xa006,
+	0x7896, 0x70d2, 0x7804, 0xa005, 0x0040, 0x215e, 0x8001, 0x7806,
+	0x00c0, 0x215e, 0x0068, 0x215e, 0x2091, 0x4080, 0x007c, 0x2039,
+	0x2177, 0x0078, 0x2165, 0x2039, 0x217d, 0x2704, 0xa005, 0x0040,
+	0x2176, 0xac00, 0x2068, 0x6b08, 0x6c0c, 0x6910, 0x6a14, 0x690a,
+	0x6a0e, 0x6b12, 0x6c16, 0x8738, 0x0078, 0x2165, 0x007c, 0x0003,
+	0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0015, 0x001b, 0x0000,
+	0x0c7e, 0x1078, 0x3c3b, 0x2c68, 0x0c7f, 0x007c, 0x0010, 0x21f7,
+	0x0068, 0x21f7, 0x2029, 0x0000, 0x78cb, 0x0000, 0x788c, 0xa065,
+	0x0040, 0x21f0, 0x2009, 0x5274, 0x2104, 0xa084, 0x0001, 0x0040,
+	0x21be, 0x6004, 0xa086, 0x0103, 0x00c0, 0x21be, 0x6018, 0xa005,
+	0x00c0, 0x21be, 0x6014, 0xa005, 0x00c0, 0x21be, 0x0d7e, 0x2069,
+	0x0000, 0x6818, 0xa084, 0x0001, 0x00c0, 0x21bd, 0x600c, 0x70c6,
+	0x6010, 0x70ca, 0x70c3, 0x8020, 0x681b, 0x0001, 0x2091, 0x4080,
+	0x0d7f, 0x1078, 0x1cf2, 0x0078, 0x21f5, 0x0d7f, 0x1078, 0x21f8,
+	0x0040, 0x21f0, 0x6204, 0xa294, 0x00ff, 0xa296, 0x0003, 0x0040,
+	0x21d0, 0x6204, 0xa296, 0x0110, 0x00c0, 0x21de, 0x78cb, 0x0001,
+	0x6204, 0xa294, 0xff00, 0x8217, 0x8211, 0x0040, 0x21de, 0x85ff,
+	0x00c0, 0x21f0, 0x8210, 0xa202, 0x00c8, 0x21f0, 0x057e, 0x1078,
+	0x2207, 0x057f, 0x0040, 0x21eb, 0x78e0, 0xa086, 0x0003, 0x0040,
+	0x21f0, 0x0078, 0x21de, 0x8528, 0x78c8, 0xa005, 0x0040, 0x218e,
+	0x85ff, 0x0040, 0x21f7, 0x2091, 0x4080, 0x78b0, 0x70d6, 0x007c,
+	0x7bac, 0x79b0, 0x70d4, 0xa102, 0x00c0, 0x2201, 0x2300, 0xa005,
+	0x007c, 0x0048, 0x2205, 0xa302, 0x007c, 0x8002, 0x007c, 0x2001,
+	0x04fd, 0x2004, 0xa082, 0x0005, 0x00c8, 0x2221, 0x2091, 0x8000,
+	0x2071, 0x0020, 0x7004, 0xa005, 0x00c0, 0x2256, 0x7008, 0x7208,
+	0xa206, 0x00c0, 0x2256, 0xa286, 0x0008, 0x00c0, 0x2256, 0x2071,
+	0x0010, 0x1078, 0x225b, 0x2009, 0x0020, 0x6004, 0xa086, 0x0103,
+	0x00c0, 0x2230, 0x6028, 0xa005, 0x00c0, 0x2230, 0x2009, 0x000c,
+	0x1078, 0x1976, 0x0040, 0x2249, 0x78c4, 0x8000, 0x78c6, 0xa086,
+	0x0002, 0x00c0, 0x2256, 0x2091, 0x8000, 0x78e3, 0x0003, 0x78c7,
+	0x0000, 0x78cc, 0xa085, 0x0300, 0x78ce, 0x2091, 0x8001, 0x0078,
+	0x2256, 0x78c7, 0x0000, 0x1078, 0x1cf2, 0x79ac, 0x78b0, 0x8000,
+	0xa10a, 0x00c8, 0x2254, 0xa006, 0x78b2, 0xa006, 0x2071, 0x0010,
+	0x2091, 0x8001, 0x007c, 0x8107, 0x8004, 0x8004, 0x7ab8, 0x7bb4,
+	0x7cc0, 0x7dbc, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9,
+	0x0000, 0x007c, 0x2009, 0x525b, 0x2091, 0x8000, 0x200a, 0x0f7e,
+	0x0e7e, 0x2071, 0x5240, 0x7000, 0xa086, 0x0000, 0x00c0, 0x2289,
+	0x2009, 0x5212, 0x2104, 0xa005, 0x00c0, 0x2289, 0x2079, 0x0100,
+	0x7830, 0xa084, 0x00c0, 0x00c0, 0x2289, 0x0018, 0x2289, 0x781b,
+	0x004b, 0x0e7f, 0x0f7f, 0x007c, 0x0f7e, 0x0e7e, 0x2071, 0x5240,
+	0x2091, 0x8000, 0x7000, 0xa086, 0x0000, 0x00c0, 0x22a2, 0x2079,
+	0x0100, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x22a2, 0x0018, 0x22a2,
+	0x781b, 0x004d, 0x2091, 0x8001, 0x0e7f, 0x0f7f, 0x007c, 0x127e,
+	0x2091, 0x2300, 0x2071, 0x5240, 0x2079, 0x0100, 0x784b, 0x000f,
+	0x0098, 0x22b5, 0x7838, 0x0078, 0x22ae, 0x20a9, 0x0040, 0x7800,
+	0xa082, 0x0004, 0x0048, 0x22be, 0x20a9, 0x0060, 0x789b, 0x0000,
+	0x78af, 0x0000, 0x78af, 0x0000, 0x0070, 0x22c8, 0x0078, 0x22c0,
+	0x7800, 0xa082, 0x0004, 0x0048, 0x22d7, 0x70b7, 0x0093, 0x2019,
+	0x4ff0, 0x1078, 0x2313, 0x702f, 0x8001, 0x0078, 0x22e3, 0x70b7,
+	0x0000, 0x2019, 0x4e70, 0x1078, 0x2313, 0x2019, 0x4eaf, 0x1078,
+	0x2313, 0x702f, 0x8000, 0x7003, 0x0000, 0x1078, 0x2420, 0x7004,
+	0xa084, 0x000f, 0x017e, 0x2009, 0x04fd, 0x210c, 0xa18a, 0x0005,
+	0x0048, 0x22f8, 0x0038, 0x22fe, 0xa085, 0x6280, 0x0078, 0x2300,
+	0x0028, 0x22fe, 0xa085, 0x6280, 0x0078, 0x2300, 0xa085, 0x62c0,
+	0x017f, 0x7806, 0x780f, 0xb204, 0x7843, 0x00d8, 0x7853, 0x0080,
+	0x780b, 0x0008, 0x7047, 0x0008, 0x7053, 0x527f, 0x704f, 0x0000,
+	0x127f, 0x2000, 0x007c, 0x137e, 0x147e, 0x157e, 0x047e, 0x20a1,
+	0x012b, 0x2304, 0xa005, 0x789a, 0x0040, 0x2333, 0x8318, 0x2324,
+	0x8318, 0x2398, 0x24a8, 0xa484, 0xff00, 0x0040, 0x232b, 0xa482,
+	0x0100, 0x20a9, 0x0100, 0x2020, 0x53a6, 0xa005, 0x00c0, 0x2322,
+	0x3318, 0x0078, 0x2319, 0x047f, 0x157f, 0x147f, 0x137f, 0x007c,
+	0xa18c, 0x000f, 0x2011, 0x0101, 0x2204, 0xa084, 0xfff0, 0xa105,
+	0x2012, 0x1078, 0x2420, 0x007c, 0x2011, 0x0101, 0x20a9, 0x0009,
+	0x810b, 0x0070, 0x234d, 0x0078, 0x2348, 0xa18c, 0x0e00, 0x2204,
+	0xa084, 0xf1ff, 0xa105, 0x2012, 0x007c, 0x2009, 0x0101, 0x20a9,
+	0x0005, 0x8213, 0x0070, 0x235e, 0x0078, 0x2359, 0xa294, 0x00e0,
+	0x2104, 0xa084, 0xff1f, 0xa205, 0x200a, 0x007c, 0x2011, 0x0101,
+	0x20a9, 0x000c, 0x810b, 0x0070, 0x236f, 0x0078, 0x236a, 0xa18c,
+	0xf000, 0x2204, 0xa084, 0x0fff, 0xa105, 0x2012, 0x007c, 0x2011,
+	0x0102, 0x2204, 0xa084, 0xffcf, 0xa105, 0x2012, 0x007c, 0x8103,
+	0x8003, 0xa080, 0x0020, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x62ac,
+	0x63ac, 0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080, 0x0022, 0x0c7e,
+	0x2061, 0x0100, 0x609a, 0x60a4, 0xa084, 0xffdf, 0x60ae, 0x0c7f,
+	0x007c, 0x8103, 0x8003, 0xa080, 0x0022, 0x0c7e, 0x2061, 0x0100,
+	0x609a, 0x60a4, 0xa085, 0x0020, 0x60ae, 0x0c7f, 0x007c, 0x8103,
+	0x8003, 0xa080, 0x0020, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4,
+	0x62ae, 0x2010, 0x60a4, 0x63ae, 0x2018, 0x0c7f, 0x007c, 0x2091,
+	0x8000, 0x0c7e, 0x0e7e, 0x6818, 0xa005, 0x0040, 0x23fe, 0x2061,
+	0x7600, 0x1078, 0x2406, 0x0040, 0x23e8, 0x20a9, 0x0000, 0x2061,
+	0x7500, 0x0c7e, 0x1078, 0x2406, 0x0040, 0x23d6, 0x0c7f, 0x8c60,
+	0x0070, 0x23d4, 0x0078, 0x23c9, 0x0078, 0x23fe, 0x007f, 0xa082,
+	0x7500, 0x2071, 0x5240, 0x7086, 0x7182, 0x2001, 0x0004, 0x706e,
+	0x7093, 0x000f, 0x7073, 0x0000, 0x1078, 0x226a, 0x0078, 0x23fa,
+	0x60c0, 0xa005, 0x00c0, 0x23fe, 0x2071, 0x5240, 0x7182, 0x2c00,
+	0x708a, 0x2001, 0x0006, 0x706e, 0x7093, 0x000f, 0x7073, 0x0000,
+	0x1078, 0x226a, 0x2001, 0x0000, 0x0078, 0x2400, 0x2001, 0x0001,
+	0x2091, 0x8001, 0xa005, 0x0e7f, 0x0c7f, 0x007c, 0x2c04, 0xa005,
+	0x0040, 0x241d, 0x2060, 0x600c, 0xa306, 0x00c0, 0x241a, 0x6010,
+	0xa206, 0x00c0, 0x241a, 0x6014, 0xa106, 0x00c0, 0x241a, 0xa006,
+	0x0078, 0x241f, 0x6000, 0x0078, 0x2407, 0xa085, 0x0001, 0x007c,
+	0x2011, 0x5241, 0x220c, 0xa18c, 0x000f, 0x2011, 0x013b, 0x2204,
+	0xa084, 0x0100, 0x0040, 0x2436, 0x2021, 0xff04, 0x2122, 0x810b,
+	0x810b, 0x810b, 0x810b, 0xa18d, 0x0f00, 0x2104, 0x007c, 0x0e7e,
+	0x68e4, 0xa08c, 0x0020, 0x0040, 0x248a, 0xa084, 0x0006, 0x00c0,
+	0x248a, 0x6014, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
+	0xa0f0, 0x5480, 0x7004, 0xa084, 0x000a, 0x00c0, 0x248a, 0x7108,
+	0xa194, 0xff00, 0x0040, 0x248a, 0xa18c, 0x00ff, 0x2001, 0x000c,
+	0xa106, 0x0040, 0x2471, 0x2001, 0x0012, 0xa106, 0x0040, 0x2475,
+	0x2001, 0x0014, 0xa106, 0x0040, 0x2479, 0x2001, 0x0019, 0xa106,
+	0x0040, 0x247d, 0x2001, 0x0032, 0xa106, 0x0040, 0x2481, 0x0078,
+	0x2485, 0x2009, 0x0012, 0x0078, 0x2487, 0x2009, 0x0014, 0x0078,
+	0x2487, 0x2009, 0x0019, 0x0078, 0x2487, 0x2009, 0x0020, 0x0078,
+	0x2487, 0x2009, 0x003f, 0x0078, 0x2487, 0x2011, 0x0000, 0x2100,
+	0xa205, 0x700a, 0x0e7f, 0x007c, 0x0068, 0x248c, 0x2091, 0x8000,
+	0x2071, 0x0000, 0x007e, 0x7018, 0xa084, 0x0001, 0x00c0, 0x2493,
+	0x007f, 0x2071, 0x0010, 0x70ca, 0x007f, 0x70c6, 0x70c3, 0x8002,
+	0x70db, 0x0741, 0x70df, 0x0006, 0x2071, 0x0000, 0x701b, 0x0001,
+	0x2091, 0x4080, 0x0078, 0x24aa, 0x107e, 0x007e, 0x127e, 0x2091,
+	0x2300, 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x77c2, 0x74c6, 0x76ca,
+	0x75ce, 0xa594, 0x003f, 0xa49c, 0x0003, 0xa484, 0x000f, 0x0079,
+	0x24c1, 0x24d3, 0x24d3, 0x24d3, 0x280d, 0x3a09, 0x24d1, 0x2502,
+	0x250c, 0x24d1, 0x24d1, 0x24d1, 0x24d1, 0x24d1, 0x24d1, 0x24d1,
+	0x24d1, 0x1078, 0x248c, 0x8507, 0xa084, 0x001f, 0x0079, 0x24d8,
+	0x2516, 0x280d, 0x29c7, 0x2ac4, 0x2aec, 0x2d8c, 0x3037, 0x309a,
+	0x30fb, 0x3180, 0x3238, 0x32d6, 0x2502, 0x28e9, 0x300c, 0x24f8,
+	0x3dac, 0x3dcc, 0x3f8f, 0x3f9b, 0x4074, 0x24f8, 0x24f8, 0x4149,
+	0x414d, 0x3daa, 0x24f8, 0x3efa, 0x24f8, 0x3c5e, 0x250c, 0x24f8,
+	0x1078, 0x248c, 0x0018, 0x24b1, 0x127f, 0x2091, 0x8001, 0x007f,
+	0x107f, 0x007c, 0x2019, 0x4f49, 0x1078, 0x2313, 0x702f, 0x0001,
+	0x781b, 0x004f, 0x0078, 0x24fa, 0x2019, 0x4eaf, 0x1078, 0x2313,
+	0x702f, 0x8000, 0x781b, 0x00cd, 0x0078, 0x24fa, 0x7242, 0x2009,
+	0x520f, 0x200b, 0x0000, 0xa584, 0x0001, 0x00c0, 0x3c72, 0x0040,
+	0x2533, 0x1078, 0x248c, 0x7003, 0x0000, 0x704b, 0x0000, 0x7043,
+	0x0000, 0x7037, 0x0000, 0x1078, 0x39e0, 0x0018, 0x24b1, 0x2009,
+	0x520f, 0x200b, 0x0000, 0x7068, 0xa005, 0x00c0, 0x25fe, 0x706c,
+	0xa084, 0x0007, 0x0079, 0x253c, 0x2635, 0x2544, 0x2550, 0x256d,
+	0x258f, 0x25dc, 0x25b5, 0x2544, 0x1078, 0x39c8, 0x2009, 0x0048,
+	0x1078, 0x2ed8, 0x00c0, 0x254e, 0x7003, 0x0004, 0x0078, 0x24fa,
+	0x1078, 0x39c8, 0x00c0, 0x256b, 0x7080, 0x8007, 0x7882, 0x789b,
+	0x0010, 0x78ab, 0x000c, 0x789b, 0x0060, 0x78ab, 0x0001, 0x785b,
+	0x0004, 0x2009, 0x00dd, 0x1078, 0x2ecc, 0x00c0, 0x256b, 0x7003,
+	0x0004, 0x7093, 0x000f, 0x0078, 0x24fa, 0x1078, 0x39c8, 0x00c0,
+	0x258d, 0x7180, 0x8107, 0x7882, 0x789b, 0x0010, 0xa18c, 0x001f,
+	0xa18d, 0x00c0, 0x79aa, 0x78ab, 0x0006, 0x789b, 0x0060, 0x78ab,
+	0x0002, 0x785b, 0x0004, 0x2009, 0x00dd, 0x1078, 0x2ecc, 0x00c0,
+	0x258d, 0x7003, 0x0004, 0x7093, 0x000f, 0x0078, 0x24fa, 0x1078,
+	0x39c8, 0x00c0, 0x25b3, 0x7180, 0x8107, 0x7882, 0x789b, 0x0010,
+	0xa18c, 0x001f, 0xa18d, 0x00c0, 0x79aa, 0x78ab, 0x0020, 0x7184,
+	0x79aa, 0x78ab, 0x000d, 0x789b, 0x0060, 0x78ab, 0x0004, 0x785b,
+	0x0004, 0x2009, 0x00dd, 0x1078, 0x2ecc, 0x00c0, 0x25b3, 0x7003,
+	0x0004, 0x7093, 0x000f, 0x0078, 0x24fa, 0x1078, 0x39c8, 0x00c0,
+	0x25da, 0x7180, 0x8107, 0x7882, 0x789b, 0x0010, 0xa18c, 0x001f,
+	0xa18d, 0x00c0, 0x79aa, 0x78ab, 0x0006, 0x789b, 0x0060, 0x78ab,
+	0x0002, 0x785b, 0x0004, 0x2009, 0x00dd, 0x1078, 0x2ecc, 0x00c0,
+	0x25da, 0x7088, 0x708b, 0x0000, 0x2068, 0x704a, 0x7003, 0x0002,
+	0x7093, 0x000f, 0x0078, 0x24fa, 0x1078, 0x39c8, 0x00c0, 0x24fa,
+	0x7088, 0x2068, 0x6f14, 0x1078, 0x38bd, 0x2c50, 0x1078, 0x3a7a,
+	0x789b, 0x0010, 0x6814, 0xa084, 0x001f, 0xa085, 0x0080, 0x78aa,
+	0x6e1c, 0x2041, 0x0001, 0x708c, 0xa084, 0x0400, 0x2001, 0x0004,
+	0x0040, 0x25fc, 0x2001, 0x0006, 0x0078, 0x271d, 0x1078, 0x39c8,
+	0x00c0, 0x24fa, 0x789b, 0x0010, 0x7068, 0x2068, 0x6f14, 0x1078,
+	0x38bd, 0x2c50, 0x1078, 0x3a7a, 0x6008, 0xa085, 0x0010, 0x600a,
+	0x6824, 0xa005, 0x0040, 0x261c, 0xa082, 0x0006, 0x0048, 0x261a,
+	0x0078, 0x261c, 0x6827, 0x0005, 0x6b14, 0xa39c, 0x001f, 0xa39d,
+	0x00c0, 0x7058, 0xa084, 0x8000, 0x0040, 0x262a, 0xa684, 0x0001,
+	0x0040, 0x262c, 0xa39c, 0xffbf, 0x7baa, 0x2031, 0x0020, 0x2041,
+	0x0001, 0x2001, 0x0003, 0x0078, 0x271d, 0x0018, 0x24b1, 0x744c,
+	0xa485, 0x0000, 0x0040, 0x264f, 0xa080, 0x5280, 0x2030, 0x7150,
+	0x8108, 0xa12a, 0x0048, 0x2646, 0x2009, 0x5280, 0x2164, 0x6504,
+	0x85ff, 0x00c0, 0x2660, 0x8421, 0x00c0, 0x2640, 0x7152, 0x7003,
+	0x0000, 0x704b, 0x0000, 0x7040, 0xa005, 0x0040, 0x3c72, 0x0078,
+	0x24fa, 0x764c, 0xa6b0, 0x5280, 0x7150, 0x2600, 0x0078, 0x264b,
+	0x7152, 0x2568, 0x2558, 0x754a, 0x2c50, 0x6034, 0xa085, 0x0000,
+	0x00c0, 0x265d, 0x6708, 0x773a, 0xa784, 0x033f, 0x0040, 0x2696,
+	0xa784, 0x0021, 0x00c0, 0x265d, 0xa784, 0x0002, 0x0040, 0x267f,
+	0xa784, 0x0004, 0x0040, 0x265d, 0xa7bc, 0xfffb, 0x670a, 0xa784,
+	0x0008, 0x00c0, 0x265d, 0xa784, 0x0010, 0x00c0, 0x265d, 0xa784,
+	0x0200, 0x00c0, 0x265d, 0xa784, 0x0100, 0x0040, 0x2696, 0x6018,
+	0xa005, 0x00c0, 0x265d, 0xa7bc, 0xfeff, 0x670a, 0x6823, 0x0000,
+	0x6e1c, 0xa684, 0x000e, 0x6118, 0x0040, 0x26a6, 0x601c, 0xa102,
+	0x0048, 0x26a9, 0x0040, 0x26a9, 0x0078, 0x2659, 0x81ff, 0x00c0,
+	0x2659, 0x68c3, 0x0000, 0xa784, 0x0080, 0x00c0, 0x26b1, 0x700c,
+	0x6022, 0xa7bc, 0xff7f, 0x670a, 0x1078, 0x3a7a, 0x0018, 0x24b1,
+	0x789b, 0x0010, 0xa046, 0x1078, 0x39c8, 0x00c0, 0x24fa, 0x6b14,
+	0xa39c, 0x001f, 0xa39d, 0x00c0, 0x7058, 0xa084, 0x8000, 0x0040,
+	0x26cd, 0xa684, 0x0001, 0x0040, 0x26cf, 0xa39c, 0xffbf, 0xa684,
+	0x0010, 0x0040, 0x26d5, 0xa39d, 0x0020, 0x7baa, 0x8840, 0xa684,
+	0x000e, 0x00c0, 0x26e0, 0xa7bd, 0x0010, 0x670a, 0x0078, 0x271b,
+	0x7158, 0xa18c, 0x0800, 0x0040, 0x34cb, 0x2011, 0x0020, 0xa684,
+	0x0008, 0x00c0, 0x26f1, 0x8210, 0xa684, 0x0002, 0x00c0, 0x26f1,
+	0x8210, 0x7aaa, 0x8840, 0x1078, 0x39e0, 0x6a14, 0x610c, 0x8108,
+	0xa18c, 0x00ff, 0xa1e0, 0x7500, 0x2c64, 0x8cff, 0x0040, 0x2712,
+	0x6014, 0xa206, 0x00c0, 0x26fc, 0x60b8, 0x8001, 0x60ba, 0x00c0,
+	0x26f7, 0x0c7e, 0x2a60, 0x6008, 0xa085, 0x0100, 0x600a, 0x0c7f,
+	0x0078, 0x2635, 0x1078, 0x39c8, 0x00c0, 0x24fa, 0x2a60, 0x610e,
+	0x79aa, 0x8840, 0x7132, 0x2001, 0x0001, 0x007e, 0x715c, 0xa184,
+	0x0018, 0x0040, 0x2738, 0xa184, 0x0010, 0x0040, 0x272b, 0x1078,
+	0x36d0, 0x00c0, 0x275b, 0xa184, 0x0008, 0x0040, 0x2738, 0x69a0,
+	0xa184, 0x0600, 0x00c0, 0x2738, 0x1078, 0x35bb, 0x0078, 0x275b,
+	0x69a0, 0xa184, 0x0800, 0x0040, 0x274f, 0x0c7e, 0x027e, 0x2960,
+	0x6000, 0xa085, 0x2000, 0x6002, 0x6104, 0xa18d, 0x0010, 0x6106,
+	0x027f, 0x0c7f, 0x1078, 0x36d0, 0x00c0, 0x275b, 0x69a0, 0xa184,
+	0x0200, 0x0040, 0x2757, 0x1078, 0x360c, 0x0078, 0x275b, 0xa184,
+	0x0400, 0x00c0, 0x2734, 0x69a0, 0xa184, 0x1000, 0x0040, 0x2766,
+	0x6914, 0xa18c, 0xff00, 0x810f, 0x1078, 0x238b, 0x007f, 0x7002,
+	0xa68c, 0x00e0, 0xa684, 0x0060, 0x0040, 0x2774, 0xa086, 0x0060,
+	0x00c0, 0x2774, 0xa18d, 0x4000, 0x88ff, 0x0040, 0x2779, 0xa18d,
+	0x0004, 0x795a, 0x69b6, 0x789b, 0x0060, 0x2800, 0x78aa, 0x789b,
+	0x0061, 0x6818, 0xa08d, 0x8000, 0xa084, 0x7fff, 0x691a, 0xa68c,
+	0x0080, 0x0040, 0x2798, 0x7097, 0x0000, 0xa08a, 0x000d, 0x0050,
+	0x2796, 0xa08a, 0x000c, 0x7196, 0x2001, 0x000c, 0x800c, 0x719a,
+	0x78aa, 0x8008, 0x810c, 0x0040, 0x34d1, 0xa18c, 0x00f8, 0x00c0,
+	0x34d1, 0x157e, 0x137e, 0x147e, 0x20a1, 0x012b, 0x789b, 0x0000,
+	0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f,
+	0x157f, 0x6814, 0x8007, 0x7882, 0x6d94, 0x7dd6, 0x7dde, 0x6e98,
+	0x7ed2, 0x7eda, 0x1078, 0x39c8, 0x00c0, 0x27cf, 0x702c, 0x8003,
+	0x0048, 0x27c8, 0x2019, 0x4eaf, 0x1078, 0x2313, 0x702f, 0x8000,
+	0x7830, 0xa084, 0x00c0, 0x00c0, 0x27cf, 0x0098, 0x27d7, 0x6008,
+	0xa084, 0xffef, 0x600a, 0x1078, 0x39e0, 0x0078, 0x2523, 0x7200,
+	0xa284, 0x0007, 0xa086, 0x0001, 0x00c0, 0x27e4, 0x781b, 0x004f,
+	0x1078, 0x39e0, 0x0078, 0x27f5, 0x6ab4, 0xa295, 0x2000, 0x7a5a,
+	0x781b, 0x004f, 0x1078, 0x39e0, 0x7200, 0x2500, 0xa605, 0x0040,
+	0x27f5, 0xa284, 0x0007, 0x1079, 0x2803, 0xad80, 0x0009, 0x7036,
+	0xa284, 0x0007, 0xa086, 0x0001, 0x00c0, 0x24fa, 0x6018, 0x8000,
+	0x601a, 0x0078, 0x24fa, 0x280b, 0x4b4b, 0x4b4b, 0x4b3a, 0x4b4b,
+	0x280b, 0x4b3a, 0x280b, 0x1078, 0x248c, 0x1078, 0x39c8, 0x0f7e,
+	0x2079, 0x5200, 0x78cc, 0x0f7f, 0xa084, 0x0001, 0x0040, 0x2831,
+	0x706c, 0xa086, 0x0001, 0x00c0, 0x2820, 0x706e, 0x0078, 0x28c4,
+	0x706c, 0xa086, 0x0005, 0x00c0, 0x282f, 0x7088, 0x2068, 0x681b,
+	0x0004, 0x6817, 0x0000, 0x6820, 0xa085, 0x0008, 0x6822, 0x706f,
+	0x0000, 0x2011, 0x0004, 0x716c, 0xa186, 0x0001, 0x0040, 0x2852,
+	0xa186, 0x0007, 0x00c0, 0x2842, 0x2009, 0x5238, 0x200b, 0x0005,
+	0x0078, 0x2852, 0x2009, 0x5213, 0x2104, 0x2009, 0x5212, 0x200a,
+	0x2009, 0x5238, 0x200b, 0x0001, 0x706f, 0x0000, 0x7073, 0x0001,
+	0x0078, 0x2854, 0x706f, 0x0000, 0x1078, 0x4887, 0x157e, 0x20a9,
+	0x0010, 0x2039, 0x0000, 0x1078, 0x37b0, 0xa7b8, 0x0100, 0x0070,
+	0x2863, 0x0078, 0x285b, 0x157f, 0x7000, 0x0079, 0x2867, 0x2895,
+	0x287c, 0x287c, 0x286f, 0x2895, 0x2895, 0x2895, 0x2895, 0x2021,
+	0x525a, 0x2404, 0xa005, 0x0040, 0x2895, 0xad06, 0x00c0, 0x287c,
+	0x6800, 0x2022, 0x0078, 0x288c, 0x6820, 0xa084, 0x0001, 0x00c0,
+	0x2888, 0x6f14, 0x1078, 0x38bd, 0x1078, 0x34a2, 0x0078, 0x288c,
+	0x7060, 0x2060, 0x6800, 0x6002, 0x6a1a, 0x6817, 0x0000, 0x6820,
+	0xa085, 0x0008, 0x6822, 0x1078, 0x1cdc, 0x2021, 0x7600, 0x1078,
+	0x28d1, 0x2021, 0x525a, 0x1078, 0x28d1, 0x157e, 0x20a9, 0x0000,
+	0x2021, 0x7500, 0x1078, 0x28d1, 0x8420, 0x0070, 0x28a9, 0x0078,
+	0x28a2, 0x2061, 0x5500, 0x2021, 0x0002, 0x20a9, 0x0100, 0x6018,
+	0x6110, 0x81ff, 0x0040, 0x28b8, 0xa102, 0x0050, 0x28b8, 0x6012,
+	0x601b, 0x0000, 0xace0, 0x0010, 0x0070, 0x28c0, 0x0078, 0x28af,
+	0x8421, 0x00c0, 0x28ad, 0x157f, 0x709c, 0xa084, 0x8000, 0x0040,
+	0x28cb, 0x1078, 0x3ace, 0x7003, 0x0000, 0x704b, 0x0000, 0x0078,
+	0x24fa, 0x047e, 0x2404, 0xa005, 0x0040, 0x28e5, 0x2068, 0x6800,
+	0x007e, 0x6a1a, 0x6817, 0x0000, 0x6820, 0xa085, 0x0008, 0x6822,
+	0x1078, 0x1cdc, 0x007f, 0x0078, 0x28d3, 0x047f, 0x2023, 0x0000,
+	0x007c, 0xa282, 0x0003, 0x0050, 0x28ef, 0x1078, 0x248c, 0x2300,
+	0x0079, 0x28f2, 0x28f5, 0x2968, 0x2985, 0xa282, 0x0002, 0x0040,
+	0x28fb, 0x1078, 0x248c, 0x706c, 0x706f, 0x0000, 0x7093, 0x0000,
+	0x0079, 0x2902, 0x290a, 0x290a, 0x290c, 0x2940, 0x34d7, 0x290a,
+	0x2940, 0x290a, 0x1078, 0x248c, 0x7780, 0x1078, 0x37b0, 0x7780,
+	0xa7bc, 0x0f00, 0x1078, 0x38bd, 0x6018, 0xa005, 0x0040, 0x2937,
+	0x2021, 0x7600, 0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x29a0,
+	0x0040, 0x2937, 0x157e, 0x20a9, 0x0000, 0x2021, 0x7500, 0x047e,
+	0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x29a0, 0x047f, 0x0040,
+	0x2936, 0x8420, 0x0070, 0x2936, 0x0078, 0x2927, 0x157f, 0x8738,
+	0xa784, 0x001f, 0x00c0, 0x2912, 0x0078, 0x2523, 0x0078, 0x2523,
+	0x7780, 0x1078, 0x38bd, 0x6018, 0xa005, 0x0040, 0x2966, 0x2021,
+	0x7600, 0x2009, 0x0005, 0x2011, 0x0020, 0x1078, 0x29a0, 0x0040,
+	0x2966, 0x157e, 0x20a9, 0x0000, 0x2021, 0x7500, 0x047e, 0x2009,
+	0x0005, 0x2011, 0x0020, 0x1078, 0x29a0, 0x047f, 0x0040, 0x2965,
+	0x8420, 0x0070, 0x2965, 0x0078, 0x2956, 0x157f, 0x0078, 0x2523,
+	0x2200, 0x0079, 0x296b, 0x296e, 0x2970, 0x2970, 0x1078, 0x248c,
+	0x2009, 0x0012, 0x706c, 0xa086, 0x0002, 0x0040, 0x2979, 0x2009,
+	0x000e, 0x6818, 0xa084, 0x8000, 0x0040, 0x297f, 0x691a, 0x706f,
+	0x0000, 0x7073, 0x0001, 0x0078, 0x3956, 0x2200, 0x0079, 0x2988,
+	0x298d, 0x2970, 0x298b, 0x1078, 0x248c, 0x1078, 0x4887, 0x7000,
+	0xa086, 0x0001, 0x00c0, 0x3467, 0x1078, 0x34b8, 0x6008, 0xa084,
+	0xffef, 0x600a, 0x1078, 0x345a, 0x0040, 0x3467, 0x0078, 0x2635,
+	0x2404, 0xa005, 0x0040, 0x29c3, 0x2068, 0x2d04, 0x007e, 0x6814,
+	0xa706, 0x0040, 0x29af, 0x2d20, 0x007f, 0x0078, 0x29a1, 0x007f,
+	0x2022, 0x691a, 0x6817, 0x0000, 0x6820, 0xa205, 0x6822, 0x1078,
+	0x1cdc, 0x6010, 0x8001, 0x6012, 0x6008, 0xa084, 0xffef, 0x600a,
+	0x1078, 0x34b8, 0x007c, 0xa085, 0x0001, 0x0078, 0x29c2, 0x2300,
+	0x0079, 0x29ca, 0x29cf, 0x29cd, 0x2a68, 0x1078, 0x248c, 0x78ec,
+	0xa084, 0x0001, 0x00c0, 0x29e3, 0x7000, 0xa086, 0x0004, 0x00c0,
+	0x29db, 0x0078, 0x2a06, 0x1078, 0x34b8, 0x6008, 0xa084, 0xffef,
+	0x600a, 0x0078, 0x3467, 0x78e4, 0xa005, 0x00d0, 0x2a06, 0x0018,
+	0x24fa, 0x2008, 0xa084, 0x0030, 0x00c0, 0x29f2, 0x781b, 0x004f,
+	0x0078, 0x24fa, 0x78ec, 0xa084, 0x0003, 0x0040, 0x29ee, 0x2100,
+	0xa084, 0x0007, 0x0079, 0x29fc, 0x2a3f, 0x2a4a, 0x2a30, 0x2a04,
+	0x39bb, 0x39bb, 0x2a04, 0x2a59, 0x1078, 0x248c, 0x7000, 0xa086,
+	0x0004, 0x00c0, 0x2a20, 0x706c, 0xa086, 0x0002, 0x00c0, 0x2a16,
+	0x2011, 0x0002, 0x2019, 0x0000, 0x0078, 0x28e9, 0x706c, 0xa086,
+	0x0006, 0x0040, 0x2a10, 0x706c, 0xa086, 0x0004, 0x0040, 0x2a10,
+	0x79e4, 0xa184, 0x0030, 0x0040, 0x2a2a, 0x78ec, 0xa084, 0x0003,
+	0x00c0, 0x2a2c, 0x0078, 0x300c, 0x2001, 0x0003, 0x0078, 0x2da0,
+	0x6818, 0xa084, 0x8000, 0x0040, 0x2a37, 0x681b, 0x001d, 0x1078,
+	0x378f, 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x24fa, 0x6818,
+	0xa084, 0x8000, 0x0040, 0x2a46, 0x681b, 0x001d, 0x1078, 0x378f,
+	0x0078, 0x3986, 0x6818, 0xa084, 0x8000, 0x0040, 0x2a51, 0x681b,
+	0x001d, 0x1078, 0x378f, 0x782b, 0x3008, 0x781b, 0x00ca, 0x0078,
+	0x24fa, 0x6818, 0xa084, 0x8000, 0x0040, 0x2a60, 0x681b, 0x001d,
+	0x1078, 0x378f, 0x782b, 0x3008, 0x781b, 0x008f, 0x0078, 0x24fa,
+	0xa584, 0x000f, 0x00c0, 0x2a85, 0x7000, 0x0079, 0x2a6f, 0x2523,
+	0x2a79, 0x2a77, 0x3467, 0x3467, 0x3467, 0x3467, 0x2a77, 0x1078,
+	0x248c, 0x1078, 0x34b8, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078,
+	0x345a, 0x0040, 0x3467, 0x0078, 0x2635, 0x78e4, 0xa005, 0x00d0,
+	0x2a06, 0x0018, 0x2a06, 0x2008, 0xa084, 0x0030, 0x00c0, 0x2a94,
+	0x781b, 0x004f, 0x0078, 0x24fa, 0x78ec, 0xa084, 0x0003, 0x0040,
+	0x2a90, 0x2100, 0xa184, 0x0007, 0x0079, 0x2a9e, 0x2ab0, 0x2ab4,
+	0x2aa8, 0x2aa6, 0x39bb, 0x39bb, 0x2aa6, 0x39b1, 0x1078, 0x248c,
+	0x1078, 0x3797, 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x24fa,
+	0x1078, 0x3797, 0x0078, 0x3986, 0x1078, 0x3797, 0x782b, 0x3008,
+	0x781b, 0x00ca, 0x0078, 0x24fa, 0x1078, 0x3797, 0x782b, 0x3008,
+	0x781b, 0x008f, 0x0078, 0x24fa, 0x2300, 0x0079, 0x2ac7, 0x2acc,
+	0x2aca, 0x2ace, 0x1078, 0x248c, 0x0078, 0x3180, 0x681b, 0x0008,
+	0x78a3, 0x0000, 0x79e4, 0xa184, 0x0030, 0x0040, 0x3180, 0x78ec,
+	0xa084, 0x0003, 0x0040, 0x3180, 0xa184, 0x0007, 0x0079, 0x2ae0,
+	0x2ae8, 0x2ab4, 0x2a30, 0x3956, 0x39bb, 0x39bb, 0x2ae8, 0x39b1,
+	0x1078, 0x396a, 0x0078, 0x24fa, 0xa282, 0x0005, 0x0050, 0x2af2,
+	0x1078, 0x248c, 0x2300, 0x0079, 0x2af5, 0x2af8, 0x2d4d, 0x2d5b,
+	0x2200, 0x0079, 0x2afb, 0x2b15, 0x2b02, 0x2b15, 0x2b00, 0x2d32,
+	0x1078, 0x248c, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa082,
+	0x0020, 0x0048, 0x376b, 0xa08a, 0x0004, 0x00c8, 0x376b, 0x0079,
+	0x2b11, 0x376b, 0x376b, 0x376b, 0x3719, 0x789b, 0x0018, 0x79a8,
+	0xa184, 0x0080, 0x0040, 0x2b26, 0x0078, 0x376b, 0x7000, 0xa005,
+	0x00c0, 0x2b1c, 0x2011, 0x0004, 0x0078, 0x32e9, 0xa184, 0x00ff,
+	0xa08a, 0x0010, 0x00c8, 0x376b, 0x0079, 0x2b2e, 0x2b40, 0x2b3e,
+	0x2b58, 0x2b5c, 0x2c17, 0x376b, 0x376b, 0x2c19, 0x376b, 0x376b,
+	0x2d2e, 0x2d2e, 0x376b, 0x376b, 0x376b, 0x2d30, 0x1078, 0x248c,
+	0xa684, 0x1000, 0x0040, 0x2b4d, 0x2001, 0x0500, 0x8000, 0x8000,
+	0x783a, 0x781b, 0x008d, 0x0078, 0x24fa, 0x6818, 0xa084, 0x8000,
+	0x0040, 0x2b56, 0x681b, 0x001d, 0x0078, 0x2b44, 0x0078, 0x3956,
+	0x681b, 0x001d, 0x0078, 0x377b, 0x6920, 0x6922, 0xa684, 0x1800,
+	0x00c0, 0x2b9d, 0x6820, 0xa084, 0x0001, 0x00c0, 0x2ba5, 0x6818,
+	0xa086, 0x0008, 0x00c0, 0x2b6e, 0x681b, 0x0000, 0xa684, 0x0400,
+	0x0040, 0x2c13, 0xa684, 0x0080, 0x0040, 0x2b99, 0x7097, 0x0000,
+	0x6818, 0xa084, 0x003f, 0xa08a, 0x000d, 0x0050, 0x2b99, 0xa08a,
+	0x000c, 0x7196, 0x2001, 0x000c, 0x800c, 0x719a, 0x789b, 0x0061,
+	0x78aa, 0x157e, 0x137e, 0x147e, 0x20a1, 0x012b, 0x789b, 0x0000,
+	0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f,
+	0x157f, 0x781b, 0x0058, 0x0078, 0x24fa, 0xa684, 0x1000, 0x0040,
+	0x2ba5, 0x781b, 0x0065, 0x0078, 0x24fa, 0xa684, 0x0060, 0x0040,
+	0x2c0f, 0xa684, 0x0800, 0x0040, 0x2c0f, 0xa684, 0x8000, 0x00c0,
+	0x2bb3, 0x0078, 0x2bcb, 0xa6b4, 0x7fff, 0x7e5a, 0x6eb6, 0x7adc,
+	0x79d8, 0x78d0, 0x801b, 0x00c8, 0x2bbe, 0x8000, 0xa084, 0x003f,
+	0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94,
+	0x2200, 0xa303, 0x68ae, 0xa684, 0x4000, 0x0040, 0x2bd3, 0xa6b4,
+	0xbfff, 0x7e5a, 0x6eb6, 0x7000, 0xa086, 0x0003, 0x00c0, 0x2be0,
+	0x1078, 0x493d, 0x1078, 0x4b3a, 0x781b, 0x0064, 0x0078, 0x24fa,
+	0xa006, 0x1078, 0x4c41, 0x6ab0, 0x69ac, 0x6c98, 0x6b94, 0x2200,
+	0xa105, 0x0040, 0x2bef, 0x2200, 0xa422, 0x2100, 0xa31b, 0x6caa,
+	0x7cd2, 0x7cda, 0x6ba6, 0x7bd6, 0x7bde, 0x2300, 0xa405, 0x00c0,
+	0x2c01, 0xa6b5, 0x4000, 0x7e5a, 0x6eb6, 0x781b, 0x0064, 0x0078,
+	0x24fa, 0x781b, 0x0064, 0x2200, 0xa115, 0x00c0, 0x2c0b, 0x1078,
+	0x4b4b, 0x0078, 0x24fa, 0x1078, 0x4b96, 0x0078, 0x24fa, 0x781b,
+	0x0065, 0x0078, 0x24fa, 0x781b, 0x0058, 0x0078, 0x24fa, 0x1078,
+	0x248c, 0x0078, 0x2c7a, 0x6920, 0xa184, 0x0100, 0x0040, 0x2c31,
+	0xa18c, 0xfeff, 0x6922, 0x0c7e, 0x7054, 0x2060, 0x6000, 0xa084,
+	0xefff, 0x6002, 0x6004, 0xa084, 0xfff5, 0x6006, 0x0c7f, 0x0078,
+	0x2c69, 0xa184, 0x0200, 0x0040, 0x2c69, 0xa18c, 0xfdff, 0x6922,
+	0x0c7e, 0x7054, 0x2060, 0x6000, 0xa084, 0xdfff, 0x6002, 0x6004,
+	0xa084, 0xffef, 0x6006, 0x2008, 0x2c48, 0x0c7f, 0xa184, 0x0008,
+	0x0040, 0x2c69, 0x1078, 0x38b9, 0x1078, 0x35bb, 0x88ff, 0x0040,
+	0x2c69, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xa6b5, 0x0004,
+	0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2c63, 0x782b, 0x3008, 0x781b,
+	0x0056, 0x0078, 0x24fa, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078,
+	0x24fa, 0x7e58, 0xa684, 0x0400, 0x00c0, 0x2c72, 0x781b, 0x0058,
+	0x0078, 0x24fa, 0x781b, 0x0065, 0x0078, 0x24fa, 0x0078, 0x3773,
+	0x0078, 0x3773, 0x2019, 0x0000, 0x7990, 0xa18c, 0x0007, 0x00c0,
+	0x2c88, 0x6820, 0xa084, 0x0100, 0x0040, 0x2c78, 0x2009, 0x0008,
+	0x789b, 0x0010, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001, 0x00c0,
+	0x2cbf, 0x2300, 0x7ca8, 0xa400, 0x2018, 0xa102, 0x0040, 0x2cb7,
+	0x0048, 0x2c9c, 0x0078, 0x2cb9, 0xa380, 0x0002, 0xa102, 0x00c8,
+	0x2cb7, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0c7e, 0x7054, 0x2060,
+	0x6000, 0xa084, 0xefef, 0x6002, 0x6004, 0xa084, 0xffe5, 0x6006,
+	0x0c7f, 0x7e58, 0xa6b4, 0xfffb, 0x7e5a, 0x0078, 0x2c6a, 0x0078,
+	0x2c1b, 0x24a8, 0x7aa8, 0x00f0, 0x2cb9, 0x0078, 0x2c8a, 0xa284,
+	0x00f0, 0xa086, 0x0020, 0x00c0, 0x2d1f, 0x8318, 0x8318, 0x2300,
+	0xa102, 0x0040, 0x2ccf, 0x0048, 0x2ccf, 0x0078, 0x2d1c, 0xa286,
+	0x0023, 0x0040, 0x2c78, 0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58,
+	0xa684, 0xfff1, 0xa085, 0x0010, 0x2030, 0x7e5a, 0x6008, 0xa085,
+	0x0010, 0x600a, 0x0c7e, 0x7054, 0x2060, 0x6004, 0x2008, 0x2c48,
+	0x0c7f, 0xa184, 0x0010, 0x0040, 0x2cf3, 0x1078, 0x38b9, 0x1078,
+	0x36d0, 0x0078, 0x2d02, 0x0c7e, 0x7054, 0x2060, 0x6004, 0x2008,
+	0x2c48, 0x0c7f, 0xa184, 0x0008, 0x0040, 0x2c69, 0x1078, 0x38b9,
+	0x1078, 0x35bb, 0x88ff, 0x0040, 0x2c69, 0x789b, 0x0060, 0x2800,
+	0x78aa, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2d16,
+	0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x24fa, 0x782b, 0x3008,
+	0x781b, 0x0065, 0x0078, 0x24fa, 0x7aa8, 0x0078, 0x2c8a, 0x8318,
+	0x2300, 0xa102, 0x0040, 0x2d28, 0x0048, 0x2d28, 0x0078, 0x2c8a,
+	0xa284, 0x0080, 0x00c0, 0x377b, 0x0078, 0x3773, 0x0078, 0x377b,
+	0x0078, 0x376b, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa08e,
+	0x0001, 0x0040, 0x2d3d, 0x1078, 0x248c, 0x7aa8, 0xa294, 0x00ff,
+	0x78a8, 0xa084, 0x00ff, 0xa08a, 0x0004, 0x00c8, 0x376b, 0x0079,
+	0x2d49, 0x376b, 0x3508, 0x376b, 0x3665, 0xa282, 0x0000, 0x00c0,
+	0x2d53, 0x1078, 0x248c, 0x1078, 0x378f, 0x782b, 0x3008, 0x781b,
+	0x0065, 0x0078, 0x24fa, 0xa282, 0x0003, 0x00c0, 0x2d61, 0x1078,
+	0x248c, 0xa484, 0x8000, 0x00c0, 0x2d84, 0x706c, 0xa005, 0x0040,
+	0x2d6b, 0x1078, 0x248c, 0x6f14, 0x7782, 0xa7bc, 0x0f00, 0x1078,
+	0x38bd, 0x6008, 0xa085, 0x0021, 0x600a, 0x8738, 0xa784, 0x001f,
+	0x00c0, 0x2d6f, 0x1078, 0x3793, 0x706f, 0x0002, 0x2009, 0x5238,
+	0x200b, 0x0009, 0x0078, 0x2d86, 0x1078, 0x379f, 0x782b, 0x3008,
+	0x781b, 0x0065, 0x0078, 0x24fa, 0xa282, 0x0004, 0x0050, 0x2d92,
+	0x1078, 0x248c, 0x2300, 0x0079, 0x2d95, 0x2d98, 0x2e81, 0x2eb4,
+	0xa286, 0x0003, 0x0040, 0x2d9e, 0x1078, 0x248c, 0x2001, 0x0000,
+	0x007e, 0x68c0, 0xa005, 0x0040, 0x2da7, 0x7003, 0x0003, 0x68a0,
+	0xa084, 0x2000, 0x0040, 0x2db0, 0x6008, 0xa085, 0x0002, 0x600a,
+	0x007f, 0x703e, 0x7000, 0xa084, 0x0007, 0x0079, 0x2db7, 0x2523,
+	0x2dc1, 0x2dc1, 0x2fb6, 0x2ff2, 0x2523, 0x2ff2, 0x2dbf, 0x1078,
+	0x248c, 0xa684, 0x1000, 0x00c0, 0x2dc9, 0x1078, 0x4887, 0x0040,
+	0x2e5b, 0x7868, 0xa08c, 0x00ff, 0x0040, 0x2e11, 0xa186, 0x0008,
+	0x00c0, 0x2de0, 0x1078, 0x34b8, 0x6008, 0xa084, 0xffef, 0x600a,
+	0x1078, 0x345a, 0x0040, 0x2e11, 0x1078, 0x4887, 0x0078, 0x2df8,
+	0xa186, 0x0028, 0x00c0, 0x2e11, 0x1078, 0x4887, 0x6008, 0xa084,
+	0xffef, 0x600a, 0x6018, 0xa005, 0x0040, 0x2df8, 0x8001, 0x601a,
+	0xa005, 0x0040, 0x2df8, 0x8001, 0xa005, 0x0040, 0x2df8, 0x601e,
+	0x6820, 0xa084, 0x0001, 0x0040, 0x2523, 0x6820, 0xa084, 0xfffe,
+	0x6822, 0x7060, 0x0c7e, 0x2060, 0x6800, 0x6002, 0x0c7f, 0x6004,
+	0x6802, 0xa005, 0x2d00, 0x00c0, 0x2e0e, 0x6002, 0x6006, 0x0078,
+	0x2523, 0x017e, 0x1078, 0x2ee5, 0x017f, 0xa684, 0xdf00, 0x681e,
+	0x682b, 0x0000, 0x6f14, 0x81ff, 0x0040, 0x2e5b, 0xa186, 0x0002,
+	0x00c0, 0x2e5b, 0xa684, 0x0800, 0x00c0, 0x2e2e, 0xa684, 0x0060,
+	0x0040, 0x2e2e, 0x78d8, 0x7adc, 0x682e, 0x6a32, 0x6820, 0xa084,
+	0x0800, 0x00c0, 0x2e5b, 0x8717, 0xa294, 0x000f, 0x8213, 0x8213,
+	0x8213, 0xa290, 0x5480, 0xa290, 0x0000, 0x221c, 0xa384, 0x0100,
+	0x00c0, 0x2e44, 0x0078, 0x2e4a, 0x8210, 0x2204, 0xa085, 0x0018,
+	0x2012, 0x8211, 0xa384, 0x0400, 0x0040, 0x2e57, 0x68a0, 0xa084,
+	0x0100, 0x00c0, 0x2e57, 0x1078, 0x2f69, 0x0078, 0x2523, 0x6008,
+	0xa085, 0x0002, 0x600a, 0x6916, 0x6818, 0xa084, 0x8000, 0x0040,
+	0x2e63, 0x703c, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x1078, 0x34a9,
+	0x1078, 0x34b8, 0x00c0, 0x2e70, 0x6008, 0xa084, 0xffef, 0x600a,
+	0x6820, 0xa084, 0x0001, 0x00c0, 0x2e79, 0x1078, 0x34a2, 0x0078,
+	0x2e7d, 0x7060, 0x2060, 0x6800, 0x6002, 0x1078, 0x1cdc, 0x0078,
+	0x2523, 0xa282, 0x0004, 0x0048, 0x2e87, 0x1078, 0x248c, 0x2200,
+	0x0079, 0x2e8a, 0x2e85, 0x2e8e, 0x2e9b, 0x2e8e, 0x7000, 0xa086,
+	0x0005, 0x0040, 0x2e97, 0x1078, 0x378f, 0x782b, 0x3008, 0x781b,
+	0x0065, 0x0078, 0x24fa, 0x7890, 0x8007, 0x8001, 0xa084, 0x0007,
+	0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c, 0x00ff, 0xa186, 0x0003,
+	0x0040, 0x2eb0, 0xa186, 0x0000, 0x0040, 0x2eb0, 0x0078, 0x376b,
+	0x781b, 0x0065, 0x0078, 0x24fa, 0x6820, 0xa085, 0x0004, 0x6822,
+	0x82ff, 0x00c0, 0x2ebf, 0x1078, 0x378f, 0x0078, 0x2ec6, 0x8211,
+	0x0040, 0x2ec4, 0x1078, 0x248c, 0x1078, 0x379f, 0x782b, 0x3008,
+	0x781b, 0x0065, 0x0078, 0x24fa, 0x702c, 0x8003, 0x0048, 0x2ed6,
+	0x2019, 0x4eaf, 0x1078, 0x2313, 0x702f, 0x8000, 0x1078, 0x39e0,
+	0x7830, 0xa084, 0x00c0, 0x00c0, 0x2ee2, 0x0018, 0x2ee2, 0x791a,
+	0xa006, 0x007c, 0xa085, 0x0001, 0x007c, 0xa684, 0x0060, 0x00c0,
+	0x2eef, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x2f68, 0xa684,
+	0x0800, 0x00c0, 0x2f11, 0x68b4, 0xa084, 0x4800, 0xa635, 0xa684,
+	0x0800, 0x00c0, 0x2f11, 0x6998, 0x6a94, 0x692e, 0x6a32, 0x703c,
+	0xa005, 0x00c0, 0x2f09, 0x2200, 0xa105, 0x0040, 0x2f10, 0x703f,
+	0x0015, 0x7000, 0xa086, 0x0006, 0x0040, 0x2f10, 0x1078, 0x4887,
+	0x007c, 0xa684, 0x0020, 0x0040, 0x2f33, 0xa684, 0x4000, 0x0040,
+	0x2f1f, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x2f09, 0x68b4,
+	0xa084, 0x4800, 0xa635, 0xa684, 0x4000, 0x00c0, 0x2f19, 0x703c,
+	0xa005, 0x00c0, 0x2f2d, 0x703f, 0x0015, 0x79d8, 0x7adc, 0x692e,
+	0x6a32, 0x0078, 0x2f09, 0xa684, 0x4000, 0x0040, 0x2f3d, 0x682f,
+	0x0000, 0x6833, 0x0000, 0x0078, 0x2f09, 0x68b4, 0xa084, 0x4800,
+	0xa635, 0xa684, 0x4000, 0x00c0, 0x2f37, 0x703c, 0xa005, 0x00c0,
+	0x2f4b, 0x703f, 0x0015, 0x79d8, 0x7adc, 0x78d0, 0x80fb, 0x00c8,
+	0x2f52, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x692e,
+	0x6a32, 0x2100, 0xa205, 0x00c0, 0x2f5f, 0x0078, 0x2f09, 0x7000,
+	0xa086, 0x0006, 0x0040, 0x2f68, 0x1078, 0x4c41, 0x0078, 0x2f09,
+	0x007c, 0x6008, 0xa085, 0x0200, 0x600a, 0xa384, 0x0200, 0x0040,
+	0x2f75, 0x6008, 0xa085, 0x0002, 0x600a, 0x681b, 0x0006, 0x688f,
+	0x0000, 0x6893, 0x0000, 0x6a30, 0x692c, 0x6a3e, 0x6942, 0x682f,
+	0x0003, 0x6833, 0x0000, 0x6837, 0x0020, 0x6897, 0x0000, 0x689b,
+	0x0020, 0x68b3, 0x0000, 0x68af, 0x0000, 0x7000, 0x0079, 0x2f90,
+	0x2523, 0x2f9a, 0x2fa3, 0x2f98, 0x2f98, 0x2f98, 0x2f98, 0x2f98,
+	0x1078, 0x248c, 0x6820, 0xa084, 0x0001, 0x00c0, 0x2fa3, 0x1078,
+	0x34a2, 0x0078, 0x2fa9, 0x7060, 0x2c50, 0x2060, 0x6800, 0x6002,
+	0x2a60, 0x2021, 0x525a, 0x2404, 0xa005, 0x0040, 0x2fb2, 0x2020,
+	0x0078, 0x2fab, 0x2d22, 0x206b, 0x0000, 0x007c, 0x1078, 0x34a9,
+	0x1078, 0x34b8, 0x6008, 0xa084, 0xfdff, 0x600a, 0x682b, 0x0000,
+	0x789b, 0x000e, 0x6f14, 0x6817, 0x0002, 0x1078, 0x4c89, 0xa684,
+	0x0800, 0x0040, 0x2fcf, 0x691c, 0xa18d, 0x2000, 0x691e, 0x6818,
+	0xa084, 0x8000, 0x0040, 0x2fdf, 0x7868, 0xa08c, 0x00ff, 0x0040,
+	0x2fdd, 0x681b, 0x001e, 0x0078, 0x2fdf, 0x681b, 0x0000, 0x2021,
+	0x525a, 0x2404, 0xad06, 0x0040, 0x2fe6, 0x7460, 0x6800, 0x2022,
+	0x68c3, 0x0000, 0x6a3c, 0x6940, 0x6a32, 0x692e, 0x1078, 0x1cdc,
+	0x0078, 0x2523, 0x1078, 0x2ee5, 0x682b, 0x0000, 0x2001, 0x000e,
+	0x6f14, 0x1078, 0x39e6, 0xa08c, 0x00ff, 0x6916, 0x6818, 0xa084,
+	0x8000, 0x0040, 0x3005, 0x703c, 0x681a, 0xa68c, 0xdf00, 0x691e,
+	0x706f, 0x0000, 0x0078, 0x2523, 0x7000, 0xa005, 0x00c0, 0x3012,
+	0x0078, 0x2523, 0xa006, 0x1078, 0x4887, 0x6817, 0x0000, 0x681b,
+	0x0014, 0xa68c, 0xdf00, 0x691e, 0x682b, 0x0000, 0x6820, 0xa085,
+	0x00ff, 0x6822, 0x7000, 0x0079, 0x3025, 0x2523, 0x302f, 0x302f,
+	0x3031, 0x3031, 0x3031, 0x3031, 0x302d, 0x1078, 0x248c, 0x1078,
+	0x34b8, 0x6008, 0xa084, 0xffef, 0x600a, 0x0078, 0x3472, 0x2300,
+	0x0079, 0x303a, 0x303d, 0x303f, 0x3098, 0x1078, 0x248c, 0xa684,
+	0x8000, 0x00c0, 0x307d, 0x7000, 0x0079, 0x3046, 0x2523, 0x3050,
+	0x3050, 0x306c, 0x3050, 0x3079, 0x306c, 0x304e, 0x1078, 0x248c,
+	0xa684, 0x0060, 0xa086, 0x0060, 0x00c0, 0x3068, 0xa6b4, 0xffdf,
+	0xa6b4, 0xbfff, 0xa6b5, 0x2000, 0x7e5a, 0x6eb6, 0x681c, 0xa084,
+	0xffdf, 0x681e, 0x1078, 0x4887, 0x1078, 0x4b4b, 0x0078, 0x3956,
+	0xa684, 0x2000, 0x0040, 0x305a, 0x6818, 0xa084, 0x8000, 0x0040,
+	0x3079, 0x681b, 0x0015, 0xa684, 0x4000, 0x0040, 0x3079, 0x681b,
+	0x0007, 0x1078, 0x396a, 0x0078, 0x24fa, 0xa6b4, 0x7fff, 0x7e5a,
+	0x7adc, 0x79d8, 0x78d0, 0x79d2, 0x801b, 0x00c8, 0x3088, 0x8000,
+	0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302,
+	0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x781b, 0x0065, 0x007c,
+	0x1078, 0x248c, 0x2300, 0x0079, 0x309d, 0x30a0, 0x30a2, 0x30eb,
+	0x1078, 0x248c, 0xa684, 0x8000, 0x00c0, 0x30da, 0x7000, 0x0079,
+	0x30a9, 0x2523, 0x30b3, 0x30b3, 0x30cf, 0x30b3, 0x30d6, 0x30cf,
+	0x30b1, 0x1078, 0x248c, 0xa684, 0x0060, 0xa086, 0x0060, 0x00c0,
+	0x30cb, 0xa6b4, 0xffbf, 0xa6b4, 0xbfff, 0xa6b5, 0x2000, 0x7e5a,
+	0x6eb6, 0x681c, 0xa084, 0xffbf, 0x681e, 0x1078, 0x4887, 0x1078,
+	0x4b4b, 0x0078, 0x3956, 0xa684, 0x2000, 0x0040, 0x30bd, 0x6818,
+	0xa084, 0x8000, 0x0040, 0x30d6, 0x681b, 0x0007, 0x781b, 0x00ca,
+	0x0078, 0x24fa, 0xa6b4, 0x7fff, 0x7e5a, 0x7adc, 0x79d8, 0x6b98,
+	0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x79d2,
+	0x781b, 0x0065, 0x007c, 0x6820, 0xa085, 0x0004, 0x6822, 0x1078,
+	0x3921, 0xa6b5, 0x0800, 0x1078, 0x378f, 0x782b, 0x3008, 0x781b,
+	0x0065, 0x0078, 0x24fa, 0x2300, 0x0079, 0x30fe, 0x3101, 0x3103,
+	0x3105, 0x1078, 0x248c, 0x0078, 0x377b, 0xa684, 0x0400, 0x00c0,
+	0x312e, 0x79e4, 0xa184, 0x0020, 0x0040, 0x3115, 0x78ec, 0xa084,
+	0x0003, 0x0040, 0x3115, 0x782b, 0x3009, 0x789b, 0x0060, 0x78ab,
+	0x0000, 0xa684, 0xfffb, 0x785a, 0x79e4, 0xa184, 0x0020, 0x0040,
+	0x3126, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x312a, 0x2001, 0x0014,
+	0x0078, 0x2da0, 0xa184, 0x0007, 0x0079, 0x3166, 0x7a90, 0xa294,
+	0x0007, 0x789b, 0x0060, 0x79a8, 0x81ff, 0x0040, 0x3164, 0x789b,
+	0x0010, 0x7ba8, 0xa384, 0x0001, 0x00c0, 0x3155, 0x7ba8, 0x7ba8,
+	0xa386, 0x0001, 0x00c0, 0x3148, 0x2009, 0xfff7, 0x0078, 0x314e,
+	0xa386, 0x0003, 0x00c0, 0x3155, 0x2009, 0xffef, 0x0c7e, 0x7054,
+	0x2060, 0x6004, 0xa104, 0x6006, 0x0c7f, 0x789b, 0x0060, 0x78ab,
+	0x0000, 0xa684, 0xfffb, 0x785a, 0x782b, 0x3009, 0x6920, 0xa18c,
+	0xfdff, 0xa18c, 0xfeff, 0x6922, 0x0078, 0x3956, 0x2a3f, 0x2a4a,
+	0x3170, 0x3178, 0x316e, 0x316e, 0x3956, 0x3956, 0x1078, 0x248c,
+	0x6920, 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x6922, 0x0078, 0x3960,
+	0x6920, 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x6922, 0x0078, 0x3956,
+	0x79e4, 0xa184, 0x0030, 0x0040, 0x318a, 0x78ec, 0xa084, 0x0003,
+	0x00c0, 0x31b1, 0x7000, 0xa086, 0x0004, 0x00c0, 0x31a4, 0x706c,
+	0xa086, 0x0002, 0x00c0, 0x319a, 0x2011, 0x0002, 0x2019, 0x0000,
+	0x0078, 0x28e9, 0x706c, 0xa086, 0x0006, 0x0040, 0x3194, 0x706c,
+	0xa086, 0x0004, 0x0040, 0x3194, 0x7000, 0xa086, 0x0000, 0x0040,
+	0x24fa, 0x6818, 0xa085, 0x8000, 0x681a, 0x2001, 0x0014, 0x0078,
+	0x2da0, 0xa184, 0x0007, 0x0079, 0x31b5, 0x3956, 0x3956, 0x31bd,
+	0x3956, 0x39bb, 0x39bb, 0x3956, 0x3956, 0xa684, 0x0080, 0x0040,
+	0x31ec, 0x7194, 0x81ff, 0x0040, 0x31ec, 0xa182, 0x000d, 0x00d0,
+	0x31cd, 0x7097, 0x0000, 0x0078, 0x31d2, 0xa182, 0x000c, 0x7096,
+	0x2009, 0x000c, 0x789b, 0x0061, 0x79aa, 0x157e, 0x137e, 0x147e,
+	0x7098, 0x8114, 0xa210, 0x729a, 0xa080, 0x000b, 0xad00, 0x2098,
+	0x20a1, 0x012b, 0x789b, 0x0000, 0x8108, 0x81ac, 0x53a6, 0x147f,
+	0x137f, 0x157f, 0x0078, 0x3960, 0xa684, 0x0400, 0x00c0, 0x322d,
+	0x6820, 0xa084, 0x0001, 0x0040, 0x3960, 0xa68c, 0x0060, 0xa684,
+	0x0060, 0x0040, 0x3201, 0xa086, 0x0060, 0x00c0, 0x3201, 0xa18d,
+	0x4000, 0xa18c, 0xfffb, 0x795a, 0x69b6, 0x789b, 0x0060, 0x78ab,
+	0x0000, 0x789b, 0x0061, 0x6818, 0xa085, 0x8000, 0x681a, 0x78aa,
+	0x8008, 0x810c, 0x0040, 0x34d1, 0xa18c, 0x00f8, 0x00c0, 0x34d1,
 	0x157e, 0x137e, 0x147e, 0x20a1, 0x012b, 0x789b, 0x0000, 0x8000,
 	0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f,
-	0x6814, 0x8007, 0x7882, 0x6d94, 0x7dd6, 0x7dde, 0x6e98, 0x7ed2,
-	0x7eda, 0x1078, 0x38fa, 0x00c0, 0x272e, 0x702c, 0x8003, 0x0048,
-	0x2727, 0x2019, 0x4d9e, 0x1078, 0x2276, 0x702f, 0x8000, 0x7830,
-	0xa084, 0x00c0, 0x00c0, 0x272e, 0x0098, 0x2736, 0x6008, 0xa084,
-	0xffef, 0x600a, 0x1078, 0x3912, 0x0078, 0x2482, 0x7200, 0xa284,
-	0x0007, 0xa086, 0x0001, 0x00c0, 0x2743, 0x781b, 0x004f, 0x1078,
-	0x3912, 0x0078, 0x2754, 0x6ab4, 0xa295, 0x2000, 0x7a5a, 0x781b,
-	0x004f, 0x1078, 0x3912, 0x7200, 0x2500, 0xa605, 0x0040, 0x2754,
-	0xa284, 0x0007, 0x1079, 0x2762, 0xad80, 0x0009, 0x7036, 0xa284,
-	0x0007, 0xa086, 0x0001, 0x00c0, 0x2459, 0x6018, 0x8000, 0x601a,
-	0x0078, 0x2459, 0x276a, 0x4a3a, 0x4a3a, 0x4a29, 0x4a3a, 0x276a,
-	0x4a29, 0x276a, 0x1078, 0x23eb, 0x1078, 0x38fa, 0x0f7e, 0x2079,
-	0x5100, 0x78cc, 0x0f7f, 0xa084, 0x0001, 0x0040, 0x2790, 0x706c,
-	0xa086, 0x0001, 0x00c0, 0x277f, 0x706e, 0x0078, 0x2823, 0x706c,
-	0xa086, 0x0005, 0x00c0, 0x278e, 0x7088, 0x2068, 0x681b, 0x0004,
-	0x6817, 0x0000, 0x6820, 0xa085, 0x0008, 0x6822, 0x706f, 0x0000,
-	0x2011, 0x0004, 0x716c, 0xa186, 0x0001, 0x0040, 0x27b1, 0xa186,
-	0x0007, 0x00c0, 0x27a1, 0x2009, 0x5138, 0x200b, 0x0005, 0x0078,
-	0x27b1, 0x2009, 0x5113, 0x2104, 0x2009, 0x5112, 0x200a, 0x2009,
-	0x5138, 0x200b, 0x0001, 0x706f, 0x0000, 0x7073, 0x0001, 0x0078,
-	0x27b3, 0x706f, 0x0000, 0x1078, 0x4776, 0x157e, 0x20a9, 0x0010,
-	0x2039, 0x0000, 0x1078, 0x36e2, 0xa7b8, 0x0100, 0x0070, 0x27c2,
-	0x0078, 0x27ba, 0x157f, 0x7000, 0x0079, 0x27c6, 0x27f4, 0x27db,
-	0x27db, 0x27ce, 0x27f4, 0x27f4, 0x27f4, 0x27f4, 0x2021, 0x515a,
-	0x2404, 0xa005, 0x0040, 0x27f4, 0xad06, 0x00c0, 0x27db, 0x6800,
-	0x2022, 0x0078, 0x27eb, 0x6820, 0xa084, 0x0001, 0x00c0, 0x27e7,
-	0x6f14, 0x1078, 0x37ef, 0x1078, 0x33d8, 0x0078, 0x27eb, 0x7060,
-	0x2060, 0x6800, 0x6002, 0x6a1a, 0x6817, 0x0000, 0x6820, 0xa085,
-	0x0008, 0x6822, 0x1078, 0x1c70, 0x2021, 0x7500, 0x1078, 0x2830,
-	0x2021, 0x515a, 0x1078, 0x2830, 0x157e, 0x20a9, 0x0000, 0x2021,
-	0x7400, 0x1078, 0x2830, 0x8420, 0x0070, 0x2808, 0x0078, 0x2801,
-	0x2061, 0x5400, 0x2021, 0x0002, 0x20a9, 0x0100, 0x6018, 0x6110,
-	0x81ff, 0x0040, 0x2817, 0xa102, 0x0050, 0x2817, 0x6012, 0x601b,
-	0x0000, 0xace0, 0x0010, 0x0070, 0x281f, 0x0078, 0x280e, 0x8421,
-	0x00c0, 0x280c, 0x157f, 0x709c, 0xa084, 0x8000, 0x0040, 0x282a,
-	0x1078, 0x3a00, 0x7003, 0x0000, 0x704b, 0x0000, 0x0078, 0x2459,
-	0x047e, 0x2404, 0xa005, 0x0040, 0x2844, 0x2068, 0x6800, 0x007e,
-	0x6a1a, 0x6817, 0x0000, 0x6820, 0xa085, 0x0008, 0x6822, 0x1078,
-	0x1c70, 0x007f, 0x0078, 0x2832, 0x047f, 0x2023, 0x0000, 0x007c,
-	0xa282, 0x0003, 0x0050, 0x284e, 0x1078, 0x23eb, 0x2300, 0x0079,
-	0x2851, 0x2854, 0x28c7, 0x28e4, 0xa282, 0x0002, 0x0040, 0x285a,
-	0x1078, 0x23eb, 0x706c, 0x706f, 0x0000, 0x7093, 0x0000, 0x0079,
-	0x2861, 0x2869, 0x2869, 0x286b, 0x289f, 0x340d, 0x2869, 0x289f,
-	0x2869, 0x1078, 0x23eb, 0x7780, 0x1078, 0x36e2, 0x7780, 0xa7bc,
-	0x0f00, 0x1078, 0x37ef, 0x6018, 0xa005, 0x0040, 0x2896, 0x2021,
-	0x7500, 0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x28ff, 0x0040,
-	0x2896, 0x157e, 0x20a9, 0x0000, 0x2021, 0x7400, 0x047e, 0x2009,
-	0x0004, 0x2011, 0x0010, 0x1078, 0x28ff, 0x047f, 0x0040, 0x2895,
-	0x8420, 0x0070, 0x2895, 0x0078, 0x2886, 0x157f, 0x8738, 0xa784,
-	0x001f, 0x00c0, 0x2871, 0x0078, 0x2482, 0x0078, 0x2482, 0x7780,
-	0x1078, 0x37ef, 0x6018, 0xa005, 0x0040, 0x28c5, 0x2021, 0x7500,
-	0x2009, 0x0005, 0x2011, 0x0020, 0x1078, 0x28ff, 0x0040, 0x28c5,
-	0x157e, 0x20a9, 0x0000, 0x2021, 0x7400, 0x047e, 0x2009, 0x0005,
-	0x2011, 0x0020, 0x1078, 0x28ff, 0x047f, 0x0040, 0x28c4, 0x8420,
-	0x0070, 0x28c4, 0x0078, 0x28b5, 0x157f, 0x0078, 0x2482, 0x2200,
-	0x0079, 0x28ca, 0x28cd, 0x28cf, 0x28cf, 0x1078, 0x23eb, 0x2009,
-	0x0012, 0x706c, 0xa086, 0x0002, 0x0040, 0x28d8, 0x2009, 0x000e,
-	0x6818, 0xa084, 0x8000, 0x0040, 0x28de, 0x691a, 0x706f, 0x0000,
-	0x7073, 0x0001, 0x0078, 0x3888, 0x2200, 0x0079, 0x28e7, 0x28ec,
-	0x28cf, 0x28ea, 0x1078, 0x23eb, 0x1078, 0x4776, 0x7000, 0xa086,
-	0x0001, 0x00c0, 0x339d, 0x1078, 0x33ee, 0x6008, 0xa084, 0xffef,
-	0x600a, 0x1078, 0x3390, 0x0040, 0x339d, 0x0078, 0x2594, 0x2404,
-	0xa005, 0x0040, 0x2922, 0x2068, 0x2d04, 0x007e, 0x6814, 0xa706,
-	0x0040, 0x290e, 0x2d20, 0x007f, 0x0078, 0x2900, 0x007f, 0x2022,
-	0x691a, 0x6817, 0x0000, 0x6820, 0xa205, 0x6822, 0x1078, 0x1c70,
-	0x6010, 0x8001, 0x6012, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078,
-	0x33ee, 0x007c, 0xa085, 0x0001, 0x0078, 0x2921, 0x2300, 0x0079,
-	0x2929, 0x292e, 0x292c, 0x29c7, 0x1078, 0x23eb, 0x78ec, 0xa084,
-	0x0001, 0x00c0, 0x2942, 0x7000, 0xa086, 0x0004, 0x00c0, 0x293a,
-	0x0078, 0x2965, 0x1078, 0x33ee, 0x6008, 0xa084, 0xffef, 0x600a,
-	0x0078, 0x339d, 0x78e4, 0xa005, 0x00d0, 0x2965, 0x0018, 0x2459,
-	0x2008, 0xa084, 0x0030, 0x00c0, 0x2951, 0x781b, 0x004f, 0x0078,
-	0x2459, 0x78ec, 0xa084, 0x0003, 0x0040, 0x294d, 0x2100, 0xa084,
-	0x0007, 0x0079, 0x295b, 0x299e, 0x29a9, 0x298f, 0x2963, 0x38ed,
-	0x38ed, 0x2963, 0x29b8, 0x1078, 0x23eb, 0x7000, 0xa086, 0x0004,
-	0x00c0, 0x297f, 0x706c, 0xa086, 0x0002, 0x00c0, 0x2975, 0x2011,
-	0x0002, 0x2019, 0x0000, 0x0078, 0x2848, 0x706c, 0xa086, 0x0006,
-	0x0040, 0x296f, 0x706c, 0xa086, 0x0004, 0x0040, 0x296f, 0x79e4,
-	0xa184, 0x0030, 0x0040, 0x2989, 0x78ec, 0xa084, 0x0003, 0x00c0,
-	0x298b, 0x0078, 0x2f6d, 0x2001, 0x0003, 0x0078, 0x2d01, 0x6818,
-	0xa084, 0x8000, 0x0040, 0x2996, 0x681b, 0x001d, 0x1078, 0x36c1,
-	0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x2459, 0x6818, 0xa084,
-	0x8000, 0x0040, 0x29a5, 0x681b, 0x001d, 0x1078, 0x36c1, 0x0078,
-	0x38b8, 0x6818, 0xa084, 0x8000, 0x0040, 0x29b0, 0x681b, 0x001d,
-	0x1078, 0x36c1, 0x782b, 0x3008, 0x781b, 0x00cd, 0x0078, 0x2459,
-	0x6818, 0xa084, 0x8000, 0x0040, 0x29bf, 0x681b, 0x001d, 0x1078,
-	0x36c1, 0x782b, 0x3008, 0x781b, 0x008e, 0x0078, 0x2459, 0xa584,
-	0x000f, 0x00c0, 0x29e4, 0x7000, 0x0079, 0x29ce, 0x2482, 0x29d8,
-	0x29d6, 0x339d, 0x339d, 0x339d, 0x339d, 0x29d6, 0x1078, 0x23eb,
-	0x1078, 0x33ee, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078, 0x3390,
-	0x0040, 0x339d, 0x0078, 0x2594, 0x78e4, 0xa005, 0x00d0, 0x2965,
-	0x0018, 0x2965, 0x2008, 0xa084, 0x0030, 0x00c0, 0x29f3, 0x781b,
-	0x004f, 0x0078, 0x2459, 0x78ec, 0xa084, 0x0003, 0x0040, 0x29ef,
-	0x2100, 0xa184, 0x0007, 0x0079, 0x29fd, 0x2a0f, 0x2a13, 0x2a07,
-	0x2a05, 0x38ed, 0x38ed, 0x2a05, 0x38e3, 0x1078, 0x23eb, 0x1078,
-	0x36c9, 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x2459, 0x1078,
-	0x36c9, 0x0078, 0x38b8, 0x1078, 0x36c9, 0x782b, 0x3008, 0x781b,
-	0x00cd, 0x0078, 0x2459, 0x1078, 0x36c9, 0x782b, 0x3008, 0x781b,
-	0x008e, 0x0078, 0x2459, 0x2300, 0x0079, 0x2a26, 0x2a2b, 0x2a29,
-	0x2a2d, 0x1078, 0x23eb, 0x0078, 0x30ab, 0x681b, 0x0008, 0x78a3,
-	0x0000, 0x79e4, 0xa184, 0x0030, 0x0040, 0x30ab, 0x78ec, 0xa084,
-	0x0003, 0x0040, 0x30ab, 0xa184, 0x0007, 0x0079, 0x2a3f, 0x2a47,
-	0x2a13, 0x298f, 0x3888, 0x38ed, 0x38ed, 0x2a47, 0x38e3, 0x1078,
-	0x389c, 0x0078, 0x2459, 0xa282, 0x0005, 0x0050, 0x2a51, 0x1078,
-	0x23eb, 0x2300, 0x0079, 0x2a54, 0x2a57, 0x2cae, 0x2cbc, 0x2200,
-	0x0079, 0x2a5a, 0x2a74, 0x2a61, 0x2a74, 0x2a5f, 0x2c93, 0x1078,
-	0x23eb, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa082, 0x0020,
-	0x0048, 0x369d, 0xa08a, 0x0004, 0x00c8, 0x369d, 0x0079, 0x2a70,
-	0x369d, 0x369d, 0x369d, 0x364b, 0x789b, 0x0018, 0x79a8, 0xa184,
-	0x0080, 0x0040, 0x2a85, 0x0078, 0x369d, 0x7000, 0xa005, 0x00c0,
-	0x2a7b, 0x2011, 0x0004, 0x0078, 0x321f, 0xa184, 0x00ff, 0xa08a,
-	0x0010, 0x00c8, 0x369d, 0x0079, 0x2a8d, 0x2a9f, 0x2a9d, 0x2ab7,
-	0x2abb, 0x2b78, 0x369d, 0x369d, 0x2b7a, 0x369d, 0x369d, 0x2c8f,
-	0x2c8f, 0x369d, 0x369d, 0x369d, 0x2c91, 0x1078, 0x23eb, 0xa684,
-	0x1000, 0x0040, 0x2aac, 0x2001, 0x0500, 0x8000, 0x8000, 0x783a,
-	0x781b, 0x008c, 0x0078, 0x2459, 0x6818, 0xa084, 0x8000, 0x0040,
-	0x2ab5, 0x681b, 0x001d, 0x0078, 0x2aa3, 0x0078, 0x3888, 0x681b,
-	0x001d, 0x0078, 0x36ad, 0x6920, 0x6922, 0xa684, 0x1800, 0x00c0,
-	0x2afc, 0x6820, 0xa084, 0x0001, 0x00c0, 0x2b04, 0x6818, 0xa086,
-	0x0008, 0x00c0, 0x2acd, 0x681b, 0x0000, 0xa684, 0x0400, 0x0040,
-	0x2b74, 0xa684, 0x0080, 0x0040, 0x2af8, 0x7097, 0x0000, 0x6818,
-	0xa084, 0x003f, 0xa08a, 0x000d, 0x0050, 0x2af8, 0xa08a, 0x000c,
-	0x7196, 0x2001, 0x000c, 0x800c, 0x719a, 0x789b, 0x0061, 0x78aa,
-	0x157e, 0x137e, 0x147e, 0x20a1, 0x012b, 0x789b, 0x0000, 0x8000,
-	0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f,
-	0x781b, 0x0058, 0x0078, 0x2459, 0xa684, 0x1000, 0x0040, 0x2b04,
-	0x781b, 0x0065, 0x0078, 0x2459, 0xa684, 0x0060, 0x0040, 0x2b70,
-	0xa684, 0x0800, 0x0040, 0x2b70, 0xa684, 0x8000, 0x00c0, 0x2b12,
-	0x0078, 0x2b2c, 0xa6b4, 0x7fff, 0x7e5a, 0x6eb6, 0x789b, 0x0076,
-	0x7aac, 0x79ac, 0x78ac, 0x801b, 0x00c8, 0x2b1f, 0x8000, 0xa084,
-	0x003f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2,
-	0x6b94, 0x2200, 0xa303, 0x68ae, 0xa684, 0x4000, 0x0040, 0x2b34,
-	0xa6b4, 0xbfff, 0x7e5a, 0x6eb6, 0x7000, 0xa086, 0x0003, 0x00c0,
-	0x2b41, 0x1078, 0x482c, 0x1078, 0x4a29, 0x781b, 0x0064, 0x0078,
-	0x2459, 0xa006, 0x1078, 0x4b30, 0x6ab0, 0x69ac, 0x6c98, 0x6b94,
-	0x2200, 0xa105, 0x0040, 0x2b50, 0x2200, 0xa422, 0x2100, 0xa31b,
-	0x6caa, 0x7cd2, 0x7cda, 0x6ba6, 0x7bd6, 0x7bde, 0x2300, 0xa405,
-	0x00c0, 0x2b62, 0xa6b5, 0x4000, 0x7e5a, 0x6eb6, 0x781b, 0x0064,
-	0x0078, 0x2459, 0x781b, 0x0064, 0x2200, 0xa115, 0x00c0, 0x2b6c,
-	0x1078, 0x4a3a, 0x0078, 0x2459, 0x1078, 0x4a85, 0x0078, 0x2459,
-	0x781b, 0x0065, 0x0078, 0x2459, 0x781b, 0x0058, 0x0078, 0x2459,
-	0x1078, 0x23eb, 0x0078, 0x2bdb, 0x6920, 0xa184, 0x0100, 0x0040,
-	0x2b92, 0xa18c, 0xfeff, 0x6922, 0x0c7e, 0x7054, 0x2060, 0x6000,
-	0xa084, 0xefff, 0x6002, 0x6004, 0xa084, 0xfff5, 0x6006, 0x0c7f,
-	0x0078, 0x2bca, 0xa184, 0x0200, 0x0040, 0x2bca, 0xa18c, 0xfdff,
-	0x6922, 0x0c7e, 0x7054, 0x2060, 0x6000, 0xa084, 0xdfff, 0x6002,
-	0x6004, 0xa084, 0xffef, 0x6006, 0x2008, 0x2c48, 0x0c7f, 0xa184,
-	0x0008, 0x0040, 0x2bca, 0x1078, 0x37eb, 0x1078, 0x34f1, 0x88ff,
-	0x0040, 0x2bca, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xa6b5,
-	0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2bc4, 0x782b, 0x3008,
-	0x781b, 0x0056, 0x0078, 0x2459, 0x782b, 0x3008, 0x781b, 0x0065,
-	0x0078, 0x2459, 0x7e58, 0xa684, 0x0400, 0x00c0, 0x2bd3, 0x781b,
-	0x0058, 0x0078, 0x2459, 0x781b, 0x0065, 0x0078, 0x2459, 0x0078,
-	0x36a5, 0x0078, 0x36a5, 0x2019, 0x0000, 0x7990, 0xa18c, 0x0007,
-	0x00c0, 0x2be9, 0x6820, 0xa084, 0x0100, 0x0040, 0x2bd9, 0x2009,
-	0x0008, 0x789b, 0x0010, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001,
-	0x00c0, 0x2c20, 0x2300, 0x7ca8, 0xa400, 0x2018, 0xa102, 0x0040,
-	0x2c18, 0x0048, 0x2bfd, 0x0078, 0x2c1a, 0xa380, 0x0002, 0xa102,
-	0x00c8, 0x2c18, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0c7e, 0x7054,
-	0x2060, 0x6000, 0xa084, 0xefef, 0x6002, 0x6004, 0xa084, 0xffe5,
-	0x6006, 0x0c7f, 0x7e58, 0xa6b4, 0xfffb, 0x7e5a, 0x0078, 0x2bcb,
-	0x0078, 0x2b7c, 0x24a8, 0x7aa8, 0x00f0, 0x2c1a, 0x0078, 0x2beb,
-	0xa284, 0x00f0, 0xa086, 0x0020, 0x00c0, 0x2c80, 0x8318, 0x8318,
-	0x2300, 0xa102, 0x0040, 0x2c30, 0x0048, 0x2c30, 0x0078, 0x2c7d,
-	0xa286, 0x0023, 0x0040, 0x2bd9, 0x681c, 0xa084, 0xfff1, 0x681e,
-	0x7e58, 0xa684, 0xfff1, 0xa085, 0x0010, 0x2030, 0x7e5a, 0x6008,
-	0xa085, 0x0010, 0x600a, 0x0c7e, 0x7054, 0x2060, 0x6004, 0x2008,
-	0x2c48, 0x0c7f, 0xa184, 0x0010, 0x0040, 0x2c54, 0x1078, 0x37eb,
-	0x1078, 0x3604, 0x0078, 0x2c63, 0x0c7e, 0x7054, 0x2060, 0x6004,
-	0x2008, 0x2c48, 0x0c7f, 0xa184, 0x0008, 0x0040, 0x2bca, 0x1078,
-	0x37eb, 0x1078, 0x34f1, 0x88ff, 0x0040, 0x2bca, 0x789b, 0x0060,
-	0x2800, 0x78aa, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0,
-	0x2c77, 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x2459, 0x782b,
-	0x3008, 0x781b, 0x0065, 0x0078, 0x2459, 0x7aa8, 0x0078, 0x2beb,
-	0x8318, 0x2300, 0xa102, 0x0040, 0x2c89, 0x0048, 0x2c89, 0x0078,
-	0x2beb, 0xa284, 0x0080, 0x00c0, 0x36ad, 0x0078, 0x36a5, 0x0078,
-	0x36ad, 0x0078, 0x369d, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff,
-	0xa08e, 0x0001, 0x0040, 0x2c9e, 0x1078, 0x23eb, 0x7aa8, 0xa294,
-	0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a, 0x0004, 0x00c8, 0x369d,
-	0x0079, 0x2caa, 0x369d, 0x343e, 0x369d, 0x3599, 0xa282, 0x0000,
-	0x00c0, 0x2cb4, 0x1078, 0x23eb, 0x1078, 0x36c1, 0x782b, 0x3008,
-	0x781b, 0x0065, 0x0078, 0x2459, 0xa282, 0x0003, 0x00c0, 0x2cc2,
-	0x1078, 0x23eb, 0xa484, 0x8000, 0x00c0, 0x2ce5, 0x706c, 0xa005,
-	0x0040, 0x2ccc, 0x1078, 0x23eb, 0x6f14, 0x7782, 0xa7bc, 0x0f00,
-	0x1078, 0x37ef, 0x6008, 0xa085, 0x0021, 0x600a, 0x8738, 0xa784,
-	0x001f, 0x00c0, 0x2cd0, 0x1078, 0x36c5, 0x706f, 0x0002, 0x2009,
-	0x5138, 0x200b, 0x0009, 0x0078, 0x2ce7, 0x1078, 0x36d1, 0x782b,
-	0x3008, 0x781b, 0x0065, 0x0078, 0x2459, 0xa282, 0x0004, 0x0050,
-	0x2cf3, 0x1078, 0x23eb, 0x2300, 0x0079, 0x2cf6, 0x2cf9, 0x2de2,
-	0x2e15, 0xa286, 0x0003, 0x0040, 0x2cff, 0x1078, 0x23eb, 0x2001,
-	0x0000, 0x007e, 0x68c0, 0xa005, 0x0040, 0x2d08, 0x7003, 0x0003,
-	0x68a0, 0xa084, 0x2000, 0x0040, 0x2d11, 0x6008, 0xa085, 0x0002,
-	0x600a, 0x007f, 0x703e, 0x7000, 0xa084, 0x0007, 0x0079, 0x2d18,
-	0x2482, 0x2d22, 0x2d22, 0x2f17, 0x2f53, 0x2482, 0x2f53, 0x2d20,
-	0x1078, 0x23eb, 0xa684, 0x1000, 0x00c0, 0x2d2a, 0x1078, 0x4776,
-	0x0040, 0x2dbc, 0x7868, 0xa08c, 0x00ff, 0x0040, 0x2d72, 0xa186,
-	0x0008, 0x00c0, 0x2d41, 0x1078, 0x33ee, 0x6008, 0xa084, 0xffef,
-	0x600a, 0x1078, 0x3390, 0x0040, 0x2d72, 0x1078, 0x4776, 0x0078,
-	0x2d59, 0xa186, 0x0028, 0x00c0, 0x2d72, 0x1078, 0x4776, 0x6008,
-	0xa084, 0xffef, 0x600a, 0x6018, 0xa005, 0x0040, 0x2d59, 0x8001,
-	0x601a, 0xa005, 0x0040, 0x2d59, 0x8001, 0xa005, 0x0040, 0x2d59,
-	0x601e, 0x6820, 0xa084, 0x0001, 0x0040, 0x2482, 0x6820, 0xa084,
-	0xfffe, 0x6822, 0x7060, 0x0c7e, 0x2060, 0x6800, 0x6002, 0x0c7f,
-	0x6004, 0x6802, 0xa005, 0x2d00, 0x00c0, 0x2d6f, 0x6002, 0x6006,
-	0x0078, 0x2482, 0x017e, 0x1078, 0x2e46, 0x017f, 0xa684, 0xdf00,
-	0x681e, 0x682b, 0x0000, 0x6f14, 0x81ff, 0x0040, 0x2dbc, 0xa186,
-	0x0002, 0x00c0, 0x2dbc, 0xa684, 0x0800, 0x00c0, 0x2d8f, 0xa684,
-	0x0060, 0x0040, 0x2d8f, 0x78d8, 0x7adc, 0x682e, 0x6a32, 0x6820,
-	0xa084, 0x0800, 0x00c0, 0x2dbc, 0x8717, 0xa294, 0x000f, 0x8213,
-	0x8213, 0x8213, 0xa290, 0x5380, 0xa290, 0x0000, 0x221c, 0xa384,
-	0x0100, 0x00c0, 0x2da5, 0x0078, 0x2dab, 0x8210, 0x2204, 0xa085,
-	0x0018, 0x2012, 0x8211, 0xa384, 0x0400, 0x0040, 0x2db8, 0x68a0,
-	0xa084, 0x0100, 0x00c0, 0x2db8, 0x1078, 0x2eca, 0x0078, 0x2482,
-	0x6008, 0xa085, 0x0002, 0x600a, 0x6916, 0x6818, 0xa084, 0x8000,
-	0x0040, 0x2dc4, 0x703c, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x1078,
-	0x33df, 0x1078, 0x33ee, 0x00c0, 0x2dd1, 0x6008, 0xa084, 0xffef,
-	0x600a, 0x6820, 0xa084, 0x0001, 0x00c0, 0x2dda, 0x1078, 0x33d8,
-	0x0078, 0x2dde, 0x7060, 0x2060, 0x6800, 0x6002, 0x1078, 0x1c70,
-	0x0078, 0x2482, 0xa282, 0x0004, 0x0048, 0x2de8, 0x1078, 0x23eb,
-	0x2200, 0x0079, 0x2deb, 0x2de6, 0x2def, 0x2dfc, 0x2def, 0x7000,
-	0xa086, 0x0005, 0x0040, 0x2df8, 0x1078, 0x36c1, 0x782b, 0x3008,
-	0x781b, 0x0065, 0x0078, 0x2459, 0x7890, 0x8007, 0x8001, 0xa084,
-	0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c, 0x00ff, 0xa186,
-	0x0003, 0x0040, 0x2e11, 0xa186, 0x0000, 0x0040, 0x2e11, 0x0078,
-	0x369d, 0x781b, 0x0065, 0x0078, 0x2459, 0x6820, 0xa085, 0x0004,
-	0x6822, 0x82ff, 0x00c0, 0x2e20, 0x1078, 0x36c1, 0x0078, 0x2e27,
-	0x8211, 0x0040, 0x2e25, 0x1078, 0x23eb, 0x1078, 0x36d1, 0x782b,
-	0x3008, 0x781b, 0x0065, 0x0078, 0x2459, 0x702c, 0x8003, 0x0048,
-	0x2e37, 0x2019, 0x4d9e, 0x1078, 0x2276, 0x702f, 0x8000, 0x1078,
-	0x3912, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x2e43, 0x0018, 0x2e43,
-	0x791a, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c, 0xa684, 0x0060,
-	0x00c0, 0x2e50, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x2ec9,
-	0xa684, 0x0800, 0x00c0, 0x2e72, 0x68b4, 0xa084, 0x4800, 0xa635,
-	0xa684, 0x0800, 0x00c0, 0x2e72, 0x6998, 0x6a94, 0x692e, 0x6a32,
-	0x703c, 0xa005, 0x00c0, 0x2e6a, 0x2200, 0xa105, 0x0040, 0x2e71,
-	0x703f, 0x0015, 0x7000, 0xa086, 0x0006, 0x0040, 0x2e71, 0x1078,
-	0x4776, 0x007c, 0xa684, 0x0020, 0x0040, 0x2e94, 0xa684, 0x4000,
-	0x0040, 0x2e80, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x2e6a,
-	0x68b4, 0xa084, 0x4800, 0xa635, 0xa684, 0x4000, 0x00c0, 0x2e7a,
-	0x703c, 0xa005, 0x00c0, 0x2e8e, 0x703f, 0x0015, 0x79d8, 0x7adc,
-	0x692e, 0x6a32, 0x0078, 0x2e6a, 0xa684, 0x4000, 0x0040, 0x2e9e,
-	0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x2e6a, 0x68b4, 0xa084,
-	0x4800, 0xa635, 0xa684, 0x4000, 0x00c0, 0x2e98, 0x703c, 0xa005,
-	0x00c0, 0x2eac, 0x703f, 0x0015, 0x79d8, 0x7adc, 0x78d0, 0x80fb,
-	0x00c8, 0x2eb3, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000,
-	0x692e, 0x6a32, 0x2100, 0xa205, 0x00c0, 0x2ec0, 0x0078, 0x2e6a,
-	0x7000, 0xa086, 0x0006, 0x0040, 0x2ec9, 0x1078, 0x4b30, 0x0078,
-	0x2e6a, 0x007c, 0x6008, 0xa085, 0x0200, 0x600a, 0xa384, 0x0200,
-	0x0040, 0x2ed6, 0x6008, 0xa085, 0x0002, 0x600a, 0x681b, 0x0006,
-	0x688f, 0x0000, 0x6893, 0x0000, 0x6a30, 0x692c, 0x6a3e, 0x6942,
-	0x682f, 0x0003, 0x6833, 0x0000, 0x6837, 0x0020, 0x6897, 0x0000,
-	0x689b, 0x0020, 0x68b3, 0x0000, 0x68af, 0x0000, 0x7000, 0x0079,
-	0x2ef1, 0x2482, 0x2efb, 0x2f04, 0x2ef9, 0x2ef9, 0x2ef9, 0x2ef9,
-	0x2ef9, 0x1078, 0x23eb, 0x6820, 0xa084, 0x0001, 0x00c0, 0x2f04,
-	0x1078, 0x33d8, 0x0078, 0x2f0a, 0x7060, 0x2c50, 0x2060, 0x6800,
-	0x6002, 0x2a60, 0x2021, 0x515a, 0x2404, 0xa005, 0x0040, 0x2f13,
-	0x2020, 0x0078, 0x2f0c, 0x2d22, 0x206b, 0x0000, 0x007c, 0x1078,
-	0x33df, 0x1078, 0x33ee, 0x6008, 0xa084, 0xfdff, 0x600a, 0x682b,
-	0x0000, 0x789b, 0x000e, 0x6f14, 0x6817, 0x0002, 0x1078, 0x4b78,
-	0xa684, 0x0800, 0x0040, 0x2f30, 0x691c, 0xa18d, 0x2000, 0x691e,
-	0x6818, 0xa084, 0x8000, 0x0040, 0x2f40, 0x7868, 0xa08c, 0x00ff,
-	0x0040, 0x2f3e, 0x681b, 0x001e, 0x0078, 0x2f40, 0x681b, 0x0000,
-	0x2021, 0x515a, 0x2404, 0xad06, 0x0040, 0x2f47, 0x7460, 0x6800,
-	0x2022, 0x68c3, 0x0000, 0x6a3c, 0x6940, 0x6a32, 0x692e, 0x1078,
-	0x1c70, 0x0078, 0x2482, 0x1078, 0x2e46, 0x682b, 0x0000, 0x2001,
-	0x000e, 0x6f14, 0x1078, 0x3918, 0xa08c, 0x00ff, 0x6916, 0x6818,
-	0xa084, 0x8000, 0x0040, 0x2f66, 0x703c, 0x681a, 0xa68c, 0xdf00,
-	0x691e, 0x706f, 0x0000, 0x0078, 0x2482, 0x7000, 0xa005, 0x00c0,
-	0x2f73, 0x0078, 0x2482, 0xa006, 0x1078, 0x4776, 0x6817, 0x0000,
-	0x681b, 0x0014, 0xa68c, 0xdf00, 0x691e, 0x682b, 0x0000, 0x6820,
-	0xa085, 0x00ff, 0x6822, 0x7000, 0x0079, 0x2f86, 0x2482, 0x2f90,
-	0x2f90, 0x2f92, 0x2f92, 0x2f92, 0x2f92, 0x2f8e, 0x1078, 0x23eb,
-	0x1078, 0x33ee, 0x6008, 0xa084, 0xffef, 0x600a, 0x0078, 0x33a8,
-	0x2300, 0x0079, 0x2f9b, 0x2f9e, 0x2fa0, 0x2fd9, 0x1078, 0x23eb,
-	0x7000, 0x0079, 0x2fa3, 0x2482, 0x2fad, 0x2fad, 0x2fc8, 0x2fad,
-	0x2fd5, 0x2fc8, 0x2fab, 0x1078, 0x23eb, 0xa684, 0x0060, 0xa086,
-	0x0060, 0x00c0, 0x2fc4, 0xa6b4, 0xffdf, 0xa6b4, 0xbfff, 0xa6b5,
-	0x2000, 0x7e5a, 0x681c, 0xa084, 0xffdf, 0x681e, 0x1078, 0x4776,
-	0x1078, 0x4a3a, 0x0078, 0x3888, 0xa684, 0x2000, 0x0040, 0x2fb7,
-	0x6818, 0xa084, 0x8000, 0x0040, 0x2fd5, 0x681b, 0x0015, 0xa684,
-	0x4000, 0x0040, 0x2fd5, 0x681b, 0x0007, 0x1078, 0x389c, 0x0078,
-	0x2459, 0x1078, 0x23eb, 0x2300, 0x0079, 0x2fde, 0x2fe1, 0x2fe3,
-	0x3016, 0x1078, 0x23eb, 0x7000, 0x0079, 0x2fe6, 0x2482, 0x2ff0,
-	0x2ff0, 0x300b, 0x2ff0, 0x3012, 0x300b, 0x2fee, 0x1078, 0x23eb,
-	0xa684, 0x0060, 0xa086, 0x0060, 0x00c0, 0x3007, 0xa6b4, 0xffbf,
-	0xa6b4, 0xbfff, 0xa6b5, 0x2000, 0x7e5a, 0x681c, 0xa084, 0xffbf,
-	0x681e, 0x1078, 0x4776, 0x1078, 0x4a3a, 0x0078, 0x3888, 0xa684,
-	0x2000, 0x0040, 0x2ffa, 0x6818, 0xa084, 0x8000, 0x0040, 0x3012,
-	0x681b, 0x0007, 0x781b, 0x00cd, 0x0078, 0x2459, 0x6820, 0xa085,
-	0x0004, 0x6822, 0x1078, 0x3853, 0xa6b5, 0x0800, 0x1078, 0x36c1,
-	0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x2459, 0x2300, 0x0079,
-	0x3029, 0x302c, 0x302e, 0x3030, 0x1078, 0x23eb, 0x0078, 0x36ad,
-	0xa684, 0x0400, 0x00c0, 0x3059, 0x79e4, 0xa184, 0x0020, 0x0040,
-	0x3040, 0x78ec, 0xa084, 0x0003, 0x0040, 0x3040, 0x782b, 0x3009,
-	0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, 0x79e4,
-	0xa184, 0x0020, 0x0040, 0x3051, 0x78ec, 0xa084, 0x0003, 0x00c0,
-	0x3055, 0x2001, 0x0014, 0x0078, 0x2d01, 0xa184, 0x0007, 0x0079,
-	0x3091, 0x7a90, 0xa294, 0x0007, 0x789b, 0x0060, 0x79a8, 0x81ff,
-	0x0040, 0x308f, 0x789b, 0x0010, 0x7ba8, 0xa384, 0x0001, 0x00c0,
-	0x3080, 0x7ba8, 0x7ba8, 0xa386, 0x0001, 0x00c0, 0x3073, 0x2009,
-	0xfff7, 0x0078, 0x3079, 0xa386, 0x0003, 0x00c0, 0x3080, 0x2009,
-	0xffef, 0x0c7e, 0x7054, 0x2060, 0x6004, 0xa104, 0x6006, 0x0c7f,
-	0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, 0x782b,
-	0x3009, 0x6920, 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x6922, 0x0078,
-	0x3888, 0x299e, 0x29a9, 0x309b, 0x30a3, 0x3099, 0x3099, 0x3888,
-	0x3888, 0x1078, 0x23eb, 0x6920, 0xa18c, 0xfdff, 0xa18c, 0xfeff,
-	0x6922, 0x0078, 0x3892, 0x6920, 0xa18c, 0xfdff, 0xa18c, 0xfeff,
-	0x6922, 0x0078, 0x3888, 0x79e4, 0xa184, 0x0030, 0x0040, 0x30b5,
-	0x78ec, 0xa084, 0x0003, 0x00c0, 0x30dc, 0x7000, 0xa086, 0x0004,
-	0x00c0, 0x30cf, 0x706c, 0xa086, 0x0002, 0x00c0, 0x30c5, 0x2011,
-	0x0002, 0x2019, 0x0000, 0x0078, 0x2848, 0x706c, 0xa086, 0x0006,
-	0x0040, 0x30bf, 0x706c, 0xa086, 0x0004, 0x0040, 0x30bf, 0x7000,
-	0xa086, 0x0000, 0x0040, 0x2459, 0x6818, 0xa085, 0x8000, 0x681a,
-	0x2001, 0x0014, 0x0078, 0x2d01, 0xa184, 0x0007, 0x0079, 0x30e0,
-	0x3888, 0x3888, 0x30e8, 0x3888, 0x38ed, 0x38ed, 0x3888, 0x3888,
-	0xa684, 0x0080, 0x0040, 0x3117, 0x7194, 0x81ff, 0x0040, 0x3117,
-	0xa182, 0x000d, 0x00d0, 0x30f8, 0x7097, 0x0000, 0x0078, 0x30fd,
-	0xa182, 0x000c, 0x7096, 0x2009, 0x000c, 0x789b, 0x0061, 0x79aa,
-	0x157e, 0x137e, 0x147e, 0x7098, 0x8114, 0xa210, 0x729a, 0xa080,
-	0x000b, 0xad00, 0x2098, 0x20a1, 0x012b, 0x789b, 0x0000, 0x8108,
-	0x81ac, 0x53a6, 0x147f, 0x137f, 0x157f, 0x0078, 0x3892, 0xa684,
-	0x0400, 0x00c0, 0x3158, 0x6820, 0xa084, 0x0001, 0x0040, 0x3892,
-	0xa68c, 0x0060, 0xa684, 0x0060, 0x0040, 0x312c, 0xa086, 0x0060,
-	0x00c0, 0x312c, 0xa18d, 0x4000, 0xa18c, 0xfffb, 0x795a, 0x69b6,
-	0x789b, 0x0060, 0x78ab, 0x0000, 0x789b, 0x0061, 0x6818, 0xa085,
-	0x8000, 0x681a, 0x78aa, 0x8008, 0x810c, 0x0040, 0x3407, 0xa18c,
-	0x00f8, 0x00c0, 0x3407, 0x157e, 0x137e, 0x147e, 0x20a1, 0x012b,
-	0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6,
-	0x147f, 0x137f, 0x157f, 0x6814, 0x8007, 0x7882, 0x0078, 0x3892,
-	0x6818, 0xa084, 0x8000, 0x0040, 0x315f, 0x681b, 0x0008, 0x781b,
-	0x00c3, 0x0078, 0x2459, 0x2300, 0x0079, 0x3166, 0x316b, 0x320a,
-	0x3169, 0x1078, 0x23eb, 0x7000, 0xa084, 0x0007, 0x0079, 0x3170,
-	0x2482, 0x317a, 0x31af, 0x3185, 0x3178, 0x2482, 0x3178, 0x3178,
-	0x1078, 0x23eb, 0x681c, 0xa084, 0x2000, 0x0040, 0x3193, 0x6008,
-	0xa085, 0x0002, 0x600a, 0x0078, 0x3193, 0x68c0, 0xa005, 0x00c0,
-	0x31af, 0x6920, 0xa18d, 0x0001, 0x6922, 0x68c3, 0x0001, 0x6800,
-	0x706a, 0x0078, 0x31a9, 0x6920, 0xa18d, 0x0001, 0x6922, 0x6800,
-	0x6006, 0xa005, 0x00c0, 0x319d, 0x6002, 0x681c, 0xa084, 0x000e,
-	0x0040, 0x31a9, 0x7014, 0x68ba, 0x7130, 0xa188, 0x7400, 0x0078,
-	0x31ab, 0x2009, 0x7500, 0x2104, 0x6802, 0x2d0a, 0x7162, 0x6eb6,
-	0xa684, 0x0060, 0x0040, 0x3208, 0xa684, 0x0800, 0x00c0, 0x31c3,
-	0xa684, 0x7fff, 0x68b6, 0x6894, 0x68a6, 0x6898, 0x68aa, 0x1078,
-	0x4776, 0x0078, 0x3208, 0xa684, 0x0020, 0x0040, 0x31d8, 0x68c0,
-	0xa005, 0x0040, 0x31cf, 0x1078, 0x4b78, 0x0078, 0x31d2, 0xa006,
-	0x1078, 0x4b30, 0x79d8, 0x7adc, 0x69aa, 0x6aa6, 0x0078, 0x31de,
-	0x1078, 0x37fc, 0x69aa, 0x6aa6, 0x1078, 0x4b30, 0xa684, 0x8000,
-	0x0040, 0x3208, 0xa684, 0x7fff, 0x68b6, 0x2001, 0x0076, 0x1078,
-	0x3918, 0x2010, 0x2001, 0x0078, 0x1078, 0x3918, 0x2008, 0xa684,
-	0x0020, 0x00c0, 0x3200, 0x2001, 0x007a, 0x1078, 0x3918, 0x801b,
-	0x00c8, 0x31fb, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000,
-	0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae,
-	0x0078, 0x2482, 0x0078, 0x36ad, 0x7037, 0x0000, 0xa282, 0x0006,
-	0x0050, 0x3214, 0x1078, 0x23eb, 0x7000, 0xa084, 0x0007, 0x10c0,
-	0x39be, 0x2300, 0x0079, 0x321c, 0x321f, 0x3248, 0x325c, 0x2200,
-	0x0079, 0x3222, 0x3246, 0x36ad, 0x3228, 0x3246, 0x3278, 0x32ba,
-	0x7003, 0x0005, 0x2001, 0x7610, 0x2068, 0x704a, 0x157e, 0x20a9,
-	0x0031, 0x2003, 0x0000, 0x8000, 0x0070, 0x3238, 0x0078, 0x3231,
-	0x157f, 0xad80, 0x0009, 0x7036, 0x6817, 0x0000, 0x68b7, 0x0700,
-	0x6823, 0x0800, 0x6827, 0x0003, 0x0078, 0x369d, 0x1078, 0x23eb,
-	0x7003, 0x0005, 0x2001, 0x7610, 0x2068, 0x704a, 0xad80, 0x0009,
-	0x7036, 0x2200, 0x0079, 0x3254, 0x36ad, 0x325a, 0x325a, 0x3278,
-	0x325a, 0x36ad, 0x1078, 0x23eb, 0x7003, 0x0005, 0x2001, 0x7610,
-	0x2068, 0x704a, 0xad80, 0x0009, 0x7036, 0x2200, 0x0079, 0x3268,
-	0x3270, 0x326e, 0x326e, 0x3270, 0x326e, 0x3270, 0x1078, 0x23eb,
-	0x1078, 0x36d1, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x2459,
-	0x7003, 0x0002, 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8,
-	0xa484, 0x001f, 0xa215, 0x2069, 0x7500, 0x2d04, 0x2d08, 0x7162,
-	0x2068, 0xa005, 0x0040, 0x3293, 0x6814, 0xa206, 0x0040, 0x32af,
-	0x6800, 0x0078, 0x3286, 0x7003, 0x0005, 0x2001, 0x7610, 0x2068,
-	0x704a, 0x7036, 0x157e, 0x20a9, 0x0031, 0x2003, 0x0000, 0x8000,
-	0x0070, 0x32a4, 0x0078, 0x329d, 0x157f, 0xad80, 0x0009, 0x7036,
-	0x6a16, 0x68b7, 0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x6eb4,
-	0x7e5a, 0x6820, 0xa084, 0x0c00, 0x0040, 0x3309, 0x1078, 0x36c9,
-	0x0078, 0x3309, 0x7003, 0x0002, 0x7a80, 0xa294, 0x0f00, 0x789b,
-	0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215, 0x79a8, 0x79a8, 0xa18c,
-	0x00ff, 0xa1e8, 0x7400, 0x2d04, 0x2d08, 0x7162, 0x2068, 0xa005,
-	0x0040, 0x32d9, 0x6814, 0xa206, 0x0040, 0x32f4, 0x6800, 0x0078,
-	0x32cc, 0x7003, 0x0005, 0x2001, 0x7610, 0x2068, 0x704a, 0x157e,
-	0x20a9, 0x0031, 0x2003, 0x0000, 0x8000, 0x0070, 0x32e9, 0x0078,
-	0x32e2, 0x157f, 0xad80, 0x0009, 0x7036, 0x6a16, 0x68b7, 0x0700,
-	0x6823, 0x0800, 0x6827, 0x0003, 0x6eb4, 0x7e5a, 0x6820, 0xa084,
-	0x0c00, 0x0040, 0x3309, 0xa084, 0x0800, 0x0040, 0x3303, 0x1078,
-	0x36cd, 0x0078, 0x3309, 0x1078, 0x36c9, 0x708b, 0x0000, 0x0078,
-	0x3309, 0x027e, 0x8207, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
-	0xa080, 0x5380, 0x2060, 0x7056, 0x6000, 0x705a, 0x6004, 0x705e,
-	0xa684, 0x0060, 0x0040, 0x3361, 0x6b98, 0x6c94, 0x69ac, 0x68b0,
-	0xa105, 0x00c0, 0x3343, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0xa6b4,
-	0xb7ff, 0x7e5a, 0xa684, 0x0060, 0xa086, 0x0060, 0x0040, 0x3361,
-	0x68c0, 0xa005, 0x0040, 0x333c, 0x7003, 0x0003, 0x682b, 0x0000,
-	0x1078, 0x4a29, 0x0078, 0x333e, 0x1078, 0x4a3a, 0xa6b5, 0x2000,
-	0x7e5a, 0x0078, 0x3361, 0x68b0, 0xa31a, 0x2100, 0xa423, 0x2400,
-	0xa305, 0x0040, 0x3361, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0x68b0,
-	0xa6b4, 0xbfff, 0x7e5a, 0x007e, 0x68c0, 0xa005, 0x007f, 0x0040,
-	0x335f, 0x7003, 0x0003, 0x1078, 0x4a29, 0x0078, 0x3361, 0x1078,
-	0x4a85, 0x077f, 0x1078, 0x37ef, 0x2009, 0x0065, 0xa684, 0x0004,
-	0x0040, 0x3382, 0x78e4, 0xa084, 0x0030, 0x0040, 0x337a, 0x78ec,
-	0xa084, 0x0003, 0x0040, 0x337a, 0x782b, 0x3008, 0x2009, 0x0065,
-	0x0078, 0x3382, 0x0f7e, 0x2079, 0x5100, 0x1078, 0x4776, 0x0f7f,
-	0x0040, 0x2482, 0x791a, 0x2d00, 0x704a, 0x8207, 0xa084, 0x000f,
-	0x8003, 0x8003, 0x8003, 0xa080, 0x5380, 0x2048, 0x0078, 0x2459,
-	0x6020, 0xa005, 0x0040, 0x339c, 0x8001, 0x6022, 0x6008, 0xa085,
-	0x0008, 0x600a, 0x7010, 0x6026, 0x007c, 0xa006, 0x1078, 0x4776,
-	0x6817, 0x0000, 0x681b, 0x0001, 0x6823, 0x0040, 0x681f, 0x0100,
-	0x7000, 0xa084, 0x0007, 0x0079, 0x33ad, 0x2482, 0x33b7, 0x33b7,
-	0x33d4, 0x33bf, 0x33bd, 0x33bf, 0x33b5, 0x1078, 0x23eb, 0x1078,
-	0x33df, 0x1078, 0x33d8, 0x1078, 0x1c70, 0x0078, 0x2482, 0x706c,
-	0x706f, 0x0000, 0x7093, 0x0000, 0x0079, 0x33c6, 0x33d0, 0x33d0,
-	0x33ce, 0x33ce, 0x33ce, 0x33d0, 0x33ce, 0x33d0, 0x0079, 0x2861,
-	0x706f, 0x0000, 0x0078, 0x2482, 0x681b, 0x0000, 0x0078, 0x2f17,
-	0x6800, 0xa005, 0x00c0, 0x33dd, 0x6002, 0x6006, 0x007c, 0x6010,
-	0xa005, 0x0040, 0x33e8, 0x8001, 0x00d0, 0x33e8, 0x1078, 0x23eb,
-	0x6012, 0x6008, 0xa084, 0xffef, 0x600a, 0x007c, 0x6018, 0xa005,
-	0x0040, 0x33f4, 0x8001, 0x601a, 0x007c, 0x1078, 0x3912, 0x681b,
-	0x0018, 0x0078, 0x342b, 0x1078, 0x3912, 0x681b, 0x0019, 0x0078,
-	0x342b, 0x1078, 0x3912, 0x681b, 0x001a, 0x0078, 0x342b, 0x1078,
-	0x3912, 0x681b, 0x0003, 0x0078, 0x342b, 0x7780, 0x1078, 0x37ef,
-	0x7184, 0xa18c, 0x00ff, 0xa1e8, 0x7400, 0x2d04, 0x2d08, 0x2068,
-	0xa005, 0x00c0, 0x341d, 0x0078, 0x2482, 0x6814, 0x7280, 0xa206,
-	0x0040, 0x3425, 0x6800, 0x0078, 0x3416, 0x6800, 0x200a, 0x681b,
-	0x0005, 0x708b, 0x0000, 0x1078, 0x33df, 0x6820, 0xa084, 0x0001,
-	0x00c0, 0x3434, 0x1078, 0x33d8, 0x1078, 0x33ee, 0x681f, 0x0000,
-	0x6823, 0x0020, 0x1078, 0x1c70, 0x0078, 0x2482, 0xa282, 0x0003,
-	0x00c0, 0x369d, 0x7da8, 0xa5ac, 0x00ff, 0x7ca8, 0xa4a4, 0x00ff,
-	0x6920, 0xa18d, 0x0080, 0x6922, 0xa184, 0x0100, 0x0040, 0x34a2,
-	0xa18c, 0xfeff, 0x6922, 0xa4a4, 0x00ff, 0x0040, 0x348c, 0xa482,
-	0x000c, 0x0048, 0x345f, 0x0040, 0x345f, 0x2021, 0x000c, 0x852b,
-	0x852b, 0x1078, 0x3760, 0x0040, 0x3469, 0x1078, 0x355b, 0x0078,
-	0x3495, 0x1078, 0x371b, 0x0c7e, 0x2960, 0x6004, 0xa084, 0xfff5,
-	0x6006, 0x1078, 0x3586, 0x0c7f, 0x6920, 0xa18d, 0x0100, 0x6922,
-	0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x3486,
-	0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x2459, 0x782b, 0x3008,
-	0x781b, 0x0065, 0x0078, 0x2459, 0x0c7e, 0x2960, 0x6004, 0xa084,
-	0xfff5, 0x6006, 0x1078, 0x3586, 0x0c7f, 0x7e58, 0xa684, 0x0400,
-	0x00c0, 0x349e, 0x781b, 0x0058, 0x0078, 0x2459, 0x781b, 0x0065,
-	0x0078, 0x2459, 0x0c7e, 0x7054, 0x2060, 0x6100, 0xa18c, 0x1000,
-	0x0040, 0x34e2, 0x6208, 0x8217, 0xa294, 0x00ff, 0xa282, 0x000c,
-	0x0048, 0x34b6, 0x0040, 0x34b6, 0x2011, 0x000c, 0x2400, 0xa202,
-	0x00c8, 0x34bb, 0x2220, 0x6208, 0xa294, 0x00ff, 0x7018, 0xa086,
-	0x0028, 0x00c0, 0x34cb, 0xa282, 0x0019, 0x00c8, 0x34d1, 0x2011,
-	0x0019, 0x0078, 0x34d1, 0xa282, 0x000c, 0x00c8, 0x34d1, 0x2011,
-	0x000c, 0x2200, 0xa502, 0x00c8, 0x34d6, 0x2228, 0x1078, 0x371f,
-	0x852b, 0x852b, 0x1078, 0x3760, 0x0040, 0x34e2, 0x1078, 0x355b,
-	0x0078, 0x34e6, 0x1078, 0x371b, 0x1078, 0x3586, 0x7858, 0xa085,
-	0x0004, 0x785a, 0x0c7f, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078,
-	0x2459, 0x0c7e, 0x2960, 0x6000, 0xa084, 0x1000, 0x00c0, 0x3509,
-	0x6010, 0xa084, 0x000f, 0x00c0, 0x3503, 0x6104, 0xa18c, 0xfff5,
-	0x6106, 0x0c7f, 0x007c, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078,
-	0x3530, 0x68a0, 0xa084, 0x0200, 0x00c0, 0x3503, 0x6208, 0xa294,
-	0x00ff, 0x7018, 0xa086, 0x0028, 0x00c0, 0x351e, 0xa282, 0x0019,
-	0x00c8, 0x3524, 0x2011, 0x0019, 0x0078, 0x3524, 0xa282, 0x000c,
-	0x00c8, 0x3524, 0x2011, 0x000c, 0x6308, 0x831f, 0xa39c, 0x00ff,
-	0xa382, 0x000c, 0x0048, 0x3530, 0x0040, 0x3530, 0x2019, 0x000c,
-	0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa,
-	0xa8c0, 0x0005, 0x6820, 0xa085, 0x0100, 0x6822, 0x0c7f, 0x007c,
-	0x0c7e, 0x2960, 0xa18c, 0xfff5, 0x6106, 0x2011, 0x0032, 0x2019,
-	0x0000, 0x0078, 0x354b, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab,
-	0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xa085, 0x0100,
-	0x6822, 0x0c7f, 0x007c, 0x0c7e, 0x7154, 0x2160, 0x1078, 0x3562,
-	0x0c7f, 0x007c, 0x2008, 0xa084, 0xfff0, 0xa425, 0x7c86, 0x6018,
-	0x789a, 0x7cae, 0x6412, 0x78a4, 0xa084, 0xfff8, 0xa18c, 0x0007,
-	0xa105, 0x78a6, 0x6016, 0x788a, 0xa4a4, 0x000f, 0x8427, 0x8204,
-	0x8004, 0xa084, 0x00ff, 0xa405, 0x600e, 0x78ec, 0xd08c, 0x00c0,
-	0x3585, 0x6004, 0xa084, 0xfff5, 0x6006, 0x007c, 0x0c7e, 0x7054,
-	0x2060, 0x1078, 0x358d, 0x0c7f, 0x007c, 0x6018, 0x789a, 0x78a4,
-	0xa084, 0xfff0, 0x78a6, 0x6012, 0x7884, 0xa084, 0xfff0, 0x7886,
-	0x007c, 0xa282, 0x0002, 0x00c0, 0x369d, 0x7aa8, 0x6920, 0xa18d,
-	0x0080, 0x6922, 0xa184, 0x0200, 0x0040, 0x35e2, 0xa18c, 0xfdff,
-	0x6922, 0xa294, 0x00ff, 0xa282, 0x0002, 0x00c8, 0x369d, 0x1078,
-	0x362b, 0x1078, 0x3586, 0xa980, 0x0001, 0x200c, 0x1078, 0x37eb,
-	0x1078, 0x34f1, 0x88ff, 0x0040, 0x35d5, 0x789b, 0x0060, 0x2800,
-	0x78aa, 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0,
-	0x35cf, 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x2459, 0x782b,
-	0x3008, 0x781b, 0x0065, 0x0078, 0x2459, 0x7e58, 0xa684, 0x0400,
-	0x00c0, 0x35de, 0x781b, 0x0058, 0x0078, 0x2459, 0x781b, 0x0065,
-	0x0078, 0x2459, 0xa282, 0x0002, 0x00c8, 0x35ea, 0xa284, 0x0001,
-	0x0040, 0x35f4, 0x7154, 0xa188, 0x0000, 0x210c, 0xa18c, 0x2000,
-	0x00c0, 0x35f4, 0x2011, 0x0000, 0x1078, 0x370d, 0x1078, 0x362b,
-	0x1078, 0x3586, 0x7858, 0xa085, 0x0004, 0x785a, 0x782b, 0x3008,
-	0x781b, 0x0065, 0x0078, 0x2459, 0x0c7e, 0x027e, 0x2960, 0x6000,
-	0x2011, 0x0001, 0xa084, 0x2000, 0x00c0, 0x361b, 0x6014, 0xa084,
-	0x0040, 0x00c0, 0x3619, 0xa18c, 0xffef, 0x6106, 0xa006, 0x0078,
-	0x3628, 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab,
-	0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x6820, 0xa085, 0x0200, 0x6822,
-	0x027f, 0x0c7f, 0x007c, 0x0c7e, 0x7054, 0x2060, 0x1078, 0x3632,
-	0x0c7f, 0x007c, 0x82ff, 0x0040, 0x3637, 0x2011, 0x0040, 0x6018,
-	0xa080, 0x0002, 0x789a, 0x78a4, 0xa084, 0xffbf, 0xa205, 0x78a6,
-	0x788a, 0x6016, 0x78ec, 0xd08c, 0x00c0, 0x364a, 0x6004, 0xa084,
-	0xffef, 0x6006, 0x007c, 0x007e, 0x7000, 0xa086, 0x0003, 0x0040,
-	0x3654, 0x007f, 0x0078, 0x3657, 0x007f, 0x0078, 0x3699, 0xa684,
-	0x0020, 0x0040, 0x3699, 0x7888, 0xa084, 0x0040, 0x0040, 0x3699,
-	0x7bb8, 0xa384, 0x003f, 0x831b, 0x00c8, 0x3667, 0x8000, 0xa005,
-	0x0040, 0x367d, 0x831b, 0x00c8, 0x3670, 0x8001, 0x0040, 0x3695,
-	0xa684, 0x4000, 0x0040, 0x367d, 0x78b8, 0x801b, 0x00c8, 0x3679,
-	0x8000, 0xa084, 0x003f, 0x00c0, 0x3695, 0xa6b4, 0xbfff, 0x7e5a,
-	0x79d8, 0x7adc, 0x2001, 0x0001, 0xa108, 0x00c8, 0x3689, 0xa291,
-	0x0000, 0x79d2, 0x79da, 0x7ad6, 0x7ade, 0x1078, 0x4b30, 0x781b,
-	0x0064, 0x1078, 0x49b5, 0x0078, 0x2459, 0x781b, 0x0064, 0x0078,
-	0x2459, 0x781b, 0x0065, 0x0078, 0x2459, 0x1078, 0x36d5, 0x782b,
-	0x3008, 0x781b, 0x0065, 0x0078, 0x2459, 0x1078, 0x36c1, 0x782b,
-	0x3008, 0x781b, 0x0065, 0x0078, 0x2459, 0x6827, 0x0002, 0x1078,
-	0x36c9, 0x78e4, 0xa084, 0x0030, 0x0040, 0x2482, 0x78ec, 0xa084,
-	0x0003, 0x0040, 0x2482, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078,
-	0x2459, 0x2001, 0x0005, 0x0078, 0x36d7, 0x2001, 0x000c, 0x0078,
-	0x36d7, 0x2001, 0x0006, 0x0078, 0x36d7, 0x2001, 0x000d, 0x0078,
-	0x36d7, 0x2001, 0x0009, 0x0078, 0x36d7, 0x2001, 0x0007, 0x789b,
-	0x0010, 0x78aa, 0x789b, 0x0060, 0x78ab, 0x0001, 0xa6b5, 0x0004,
-	0x7e5a, 0x007c, 0x077e, 0x873f, 0xa7bc, 0x000f, 0x873b, 0x873b,
-	0x8703, 0xa0e0, 0x5380, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184,
-	0x000f, 0x0040, 0x36fb, 0xa184, 0xfff0, 0x78a6, 0x6012, 0x6004,
-	0xa085, 0x0008, 0x6006, 0x8738, 0x8738, 0x7f9a, 0x79a4, 0xa184,
-	0x0040, 0x0040, 0x370b, 0xa184, 0xffbf, 0x78a6, 0x6016, 0x6004,
-	0xa085, 0x0010, 0x6006, 0x077f, 0x007c, 0x789b, 0x0010, 0x78ab,
-	0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060,
-	0x78ab, 0x0004, 0x007c, 0x2021, 0x0000, 0x2029, 0x0032, 0x789b,
-	0x0010, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa,
-	0x7caa, 0x789b, 0x0060, 0x78ab, 0x0005, 0x007c, 0x157e, 0x8007,
-	0xa084, 0x00ff, 0x8003, 0x8003, 0xa080, 0x0020, 0x789a, 0x79a4,
-	0xa18c, 0xfff0, 0x2001, 0x5146, 0x2004, 0xa082, 0x0028, 0x0040,
-	0x3749, 0x2021, 0x37d2, 0x2019, 0x0014, 0x20a9, 0x000c, 0x0078,
-	0x374f, 0x2021, 0x37de, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011,
-	0x0064, 0x2404, 0xa084, 0xfff0, 0xa106, 0x0040, 0x375e, 0x8420,
-	0x2300, 0xa210, 0x0070, 0x375e, 0x0078, 0x3751, 0x157f, 0x007c,
-	0x157e, 0x2009, 0x5146, 0x210c, 0xa182, 0x0032, 0x0048, 0x3774,
-	0x0040, 0x3778, 0x2009, 0x37c4, 0x2019, 0x0011, 0x20a9, 0x000e,
-	0x2011, 0x0032, 0x0078, 0x378a, 0xa182, 0x0028, 0x0040, 0x3782,
-	0x2009, 0x37d2, 0x2019, 0x0014, 0x20a9, 0x000c, 0x2011, 0x0064,
-	0x0078, 0x378a, 0x2009, 0x37de, 0x2019, 0x0019, 0x20a9, 0x000d,
-	0x2011, 0x0064, 0x2200, 0xa502, 0x0040, 0x379a, 0x0048, 0x379a,
-	0x8108, 0x2300, 0xa210, 0x0070, 0x3797, 0x0078, 0x378a, 0x157f,
-	0xa006, 0x007c, 0x157f, 0xa582, 0x0064, 0x00c8, 0x37a9, 0x7808,
-	0xa085, 0x0070, 0x780a, 0x7044, 0xa085, 0x0070, 0x7046, 0x0078,
-	0x37a9, 0x78ec, 0xa084, 0x0300, 0x0040, 0x37b1, 0x2104, 0x0078,
-	0x37c2, 0x2104, 0xa09e, 0x1102, 0x00c0, 0x37c2, 0x2001, 0x04fd,
-	0x2004, 0xa082, 0x0005, 0x0048, 0x37c1, 0x2001, 0x1201, 0x0078,
-	0x37c2, 0x2104, 0xa005, 0x007c, 0x1102, 0x3002, 0x3202, 0x4203,
-	0x4403, 0x5404, 0x5604, 0x6605, 0x6805, 0x7806, 0x7a06, 0x0c07,
-	0x0c07, 0x0e07, 0x3202, 0x4202, 0x5202, 0x6202, 0x7202, 0x6605,
-	0x7605, 0x7805, 0x7a05, 0x7c05, 0x7e05, 0x7f05, 0x2202, 0x3202,
-	0x4202, 0x5202, 0x5404, 0x6404, 0x7404, 0x7604, 0x7804, 0x7a04,
-	0x7c04, 0x7e04, 0x7f04, 0x789b, 0x0010, 0xa046, 0x007c, 0xa784,
-	0x0f00, 0x800b, 0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003,
-	0xa105, 0xa0e0, 0x5400, 0x007c, 0x79d8, 0x7adc, 0x78d0, 0x801b,
-	0x00c8, 0x3803, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000,
-	0x007c, 0x0f7e, 0x2079, 0x0100, 0x2009, 0x5140, 0x2091, 0x8000,
-	0x2104, 0x0079, 0x3813, 0x3849, 0x381d, 0x381d, 0x381d, 0x381d,
-	0x381d, 0x381d, 0x384d, 0x1078, 0x23eb, 0x784b, 0x0004, 0x7848,
-	0xa084, 0x0004, 0x00c0, 0x381f, 0x784b, 0x0008, 0x7848, 0xa084,
-	0x0008, 0x00c0, 0x3826, 0x68b4, 0xa085, 0x4000, 0x68b6, 0x7858,
-	0xa085, 0x4000, 0x785a, 0x7830, 0xa084, 0x0080, 0x00c0, 0x3849,
-	0x0018, 0x3849, 0x681c, 0xa084, 0x0020, 0x00c0, 0x3847, 0x0e7e,
-	0x2071, 0x5140, 0x1078, 0x389c, 0x0e7f, 0x0078, 0x3849, 0x781b,
-	0x00cd, 0x2091, 0x8001, 0x0f7f, 0x007c, 0x70b3, 0x0000, 0x1078,
-	0x3a76, 0x0078, 0x3849, 0x0c7e, 0x6814, 0x8007, 0xa084, 0x000f,
-	0x8003, 0x8003, 0x8003, 0xa0e0, 0x5380, 0x6004, 0xa084, 0x000a,
-	0x00c0, 0x3886, 0x6108, 0xa194, 0xff00, 0x0040, 0x3886, 0xa18c,
-	0x00ff, 0x2001, 0x0019, 0xa106, 0x0040, 0x3875, 0x2001, 0x0032,
-	0xa106, 0x0040, 0x3879, 0x0078, 0x387d, 0x2009, 0x0020, 0x0078,
-	0x387f, 0x2009, 0x003f, 0x0078, 0x387f, 0x2011, 0x0000, 0x2100,
-	0xa205, 0x600a, 0x6004, 0xa085, 0x0002, 0x6006, 0x0c7f, 0x007c,
-	0x781b, 0x0065, 0x0078, 0x2459, 0x782b, 0x3008, 0x781b, 0x0065,
-	0x0078, 0x2459, 0x781b, 0x0058, 0x0078, 0x2459, 0x782b, 0x3008,
-	0x781b, 0x0056, 0x0078, 0x2459, 0x2009, 0x5120, 0x210c, 0xa186,
-	0x0000, 0x0040, 0x38b0, 0xa186, 0x0001, 0x0040, 0x38b3, 0x2009,
-	0x5138, 0x200b, 0x000b, 0x706f, 0x0001, 0x781b, 0x0048, 0x007c,
-	0x781b, 0x00c7, 0x007c, 0x2009, 0x5138, 0x200b, 0x000a, 0x007c,
-	0x2009, 0x5120, 0x210c, 0xa186, 0x0000, 0x0040, 0x38d3, 0xa186,
-	0x0001, 0x0040, 0x38cd, 0x2009, 0x5138, 0x200b, 0x000b, 0x706f,
-	0x0001, 0x781b, 0x0048, 0x0078, 0x2459, 0x2009, 0x5138, 0x200b,
-	0x000a, 0x0078, 0x2459, 0x782b, 0x3008, 0x781b, 0x00c7, 0x0078,
-	0x2459, 0x781b, 0x00cd, 0x0078, 0x2459, 0x782b, 0x3008, 0x781b,
-	0x00cd, 0x0078, 0x2459, 0x781b, 0x008e, 0x0078, 0x2459, 0x782b,
-	0x3008, 0x781b, 0x008e, 0x0078, 0x2459, 0x6818, 0xa084, 0x8000,
-	0x0040, 0x38f4, 0x681b, 0x001d, 0x706f, 0x0001, 0x781b, 0x0048,
-	0x0078, 0x2459, 0x007e, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x3910,
-	0x7808, 0xa084, 0xfffc, 0x780a, 0x0005, 0x0005, 0x0005, 0x0005,
-	0x78ec, 0xa084, 0x0021, 0x0040, 0x3910, 0x7044, 0x780a, 0xa005,
-	0x007f, 0x007c, 0x7044, 0xa085, 0x0002, 0x7046, 0x780a, 0x007c,
-	0x007e, 0x7830, 0xa084, 0x0040, 0x00c0, 0x3919, 0x0098, 0x3924,
-	0x007f, 0x789a, 0x78ac, 0x007c, 0x7808, 0xa084, 0xfffd, 0x780a,
-	0x0005, 0x0005, 0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, 0x0040,
-	0x3933, 0x0098, 0x3931, 0x007f, 0x789a, 0x78ac, 0x007e, 0x7044,
-	0x780a, 0x007f, 0x007c, 0x78ec, 0xa084, 0x0002, 0x00c0, 0x4760,
-	0xa784, 0x007d, 0x00c0, 0x3947, 0x2700, 0x1078, 0x23eb, 0xa784,
-	0x0001, 0x00c0, 0x2f6d, 0xa784, 0x0070, 0x0040, 0x3957, 0x0c7e,
-	0x2d60, 0x2f68, 0x1078, 0x2396, 0x2d78, 0x2c68, 0x0c7f, 0xa784,
-	0x0008, 0x0040, 0x3964, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003,
-	0x0040, 0x2482, 0x0078, 0x3888, 0xa784, 0x0004, 0x0040, 0x3997,
-	0x78b8, 0xa084, 0x4001, 0x0040, 0x3997, 0x784b, 0x0008, 0x78ec,
-	0xa084, 0x0003, 0x0040, 0x2482, 0x78e4, 0xa084, 0x0007, 0xa086,
-	0x0001, 0x00c0, 0x3997, 0x78c0, 0xa085, 0x4800, 0x2030, 0x7e5a,
-	0x781b, 0x00cd, 0x0078, 0x2459, 0x784b, 0x0008, 0x6818, 0xa084,
-	0x8000, 0x0040, 0x3993, 0x681b, 0x0015, 0xa684, 0x4000, 0x0040,
-	0x3993, 0x681b, 0x0007, 0x1078, 0x389c, 0x0078, 0x2459, 0x681b,
-	0x0003, 0x7858, 0xa084, 0x3f00, 0x681e, 0x682f, 0x0000, 0x6833,
-	0x0000, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x2965,
-	0x0018, 0x2459, 0x0078, 0x36a5, 0x6b14, 0x8307, 0xa084, 0x000f,
-	0x8003, 0x8003, 0x8003, 0xa080, 0x5380, 0x2060, 0x2048, 0x7056,
-	0x6000, 0x705a, 0x6004, 0x705e, 0x2a60, 0x007c, 0x0079, 0x39c0,
-	0x39c8, 0x39c9, 0x39c8, 0x39cb, 0x39c8, 0x39c8, 0x39c8, 0x39d0,
-	0x007c, 0x1078, 0x33ee, 0x1078, 0x4776, 0x7038, 0x600a, 0x007c,
-	0x70a0, 0xa005, 0x0040, 0x39dd, 0x2068, 0x1078, 0x1b62, 0x1078,
-	0x46f8, 0x1078, 0x46ff, 0x70a3, 0x0000, 0x007c, 0x0e7e, 0x2091,
-	0x8000, 0x2071, 0x5140, 0x7000, 0xa086, 0x0007, 0x00c0, 0x39f4,
-	0x6110, 0x70bc, 0xa106, 0x00c0, 0x39f4, 0x0e7f, 0x1078, 0x1b6f,
-	0x1078, 0x39fa, 0xa006, 0x007c, 0x2091, 0x8001, 0x0e7f, 0xa085,
-	0x0001, 0x007c, 0x0f7e, 0x0e7e, 0x2071, 0x5140, 0x0078, 0x21fa,
-	0x785b, 0x0000, 0x70af, 0x000e, 0x2009, 0x0100, 0x017e, 0x70a0,
-	0xa06d, 0x0040, 0x3a0f, 0x70a3, 0x0000, 0x0078, 0x3a15, 0x70b3,
-	0x0000, 0x1078, 0x1b8b, 0x0040, 0x3a1b, 0x70ac, 0x6826, 0x1078,
-	0x3af8, 0x0078, 0x3a0f, 0x017f, 0x157e, 0x0c7e, 0x0d7e, 0x20a9,
-	0x0008, 0x2061, 0x7510, 0x6000, 0xa105, 0x6002, 0x601c, 0xa06d,
-	0x0040, 0x3a33, 0x6800, 0x601e, 0x1078, 0x195a, 0x6008, 0x8000,
-	0x600a, 0x0078, 0x3a26, 0x6018, 0xa06d, 0x0040, 0x3a3d, 0x6800,
-	0x601a, 0x1078, 0x195a, 0x0078, 0x3a33, 0xace0, 0x0008, 0x0070,
-	0x3a43, 0x0078, 0x3a23, 0x709c, 0xa084, 0x8000, 0x0040, 0x3a4a,
-	0x1078, 0x3b72, 0x0d7f, 0x0c7f, 0x157f, 0x007c, 0x127e, 0x2091,
-	0x2300, 0x6804, 0xa084, 0x000f, 0x0079, 0x3a56, 0x3a66, 0x3a66,
-	0x3a66, 0x3a66, 0x3a66, 0x3a66, 0x3a68, 0x3a6e, 0x3a66, 0x3a66,
-	0x3a66, 0x3a66, 0x3a66, 0x3a70, 0x3a66, 0x3a68, 0x1078, 0x23eb,
-	0x1078, 0x44d0, 0x1078, 0x195a, 0x0078, 0x3a74, 0x6827, 0x000b,
-	0x1078, 0x44d0, 0x1078, 0x3af8, 0x127f, 0x007c, 0x127e, 0x2091,
-	0x2300, 0x0098, 0x3a92, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x3a92,
-	0x0d7e, 0x1078, 0x4708, 0x2d00, 0x682e, 0x2009, 0x0004, 0x2001,
-	0x0000, 0x6827, 0x0084, 0x1078, 0x46c1, 0x1078, 0x3af8, 0x0d7f,
-	0x0078, 0x3ac6, 0x7948, 0xa185, 0x4000, 0x784a, 0x0098, 0x3a9b,
-	0x794a, 0x0078, 0x3a80, 0x7828, 0xa086, 0x1834, 0x00c0, 0x3aa4,
-	0xa185, 0x0004, 0x0078, 0x3aab, 0x7828, 0xa086, 0x1814, 0x00c0,
-	0x3a98, 0xa185, 0x000c, 0x784a, 0x789b, 0x000e, 0x78ab, 0x0002,
-	0x7858, 0xa084, 0x00ff, 0xa085, 0x0400, 0x785a, 0x70b4, 0xa080,
-	0x0091, 0x781a, 0x6827, 0x0284, 0x682c, 0x6836, 0x6830, 0x683a,
-	0x2009, 0x0004, 0x2001, 0x0000, 0x1078, 0x46c1, 0x127f, 0x007c,
-	0x0d7e, 0x6b14, 0x1078, 0x1bfd, 0x0040, 0x3ad5, 0x2068, 0x6827,
-	0x0002, 0x1078, 0x3af8, 0x0078, 0x3aca, 0x0d7f, 0x007c, 0x0d7e,
-	0x6b14, 0x6c28, 0xa4a4, 0x00ff, 0x1078, 0x1b9b, 0x0040, 0x3ae5,
-	0x2068, 0x6827, 0x0002, 0x1078, 0x3af8, 0x0d7f, 0x007c, 0x0d7e,
-	0x6b14, 0xa39c, 0x00ff, 0x1078, 0x1bce, 0x0040, 0x3af6, 0x2068,
-	0x6827, 0x0002, 0x1078, 0x3af8, 0x0078, 0x3aeb, 0x0d7f, 0x007c,
-	0x0c7e, 0x6914, 0x1078, 0x3b69, 0x6904, 0xa18c, 0x00ff, 0xa186,
-	0x0006, 0x0040, 0x3b13, 0xa186, 0x000d, 0x0040, 0x3b32, 0xa186,
-	0x0017, 0x00c0, 0x3b0f, 0x1078, 0x195a, 0x0078, 0x3b11, 0x1078,
-	0x1c72, 0x0c7f, 0x007c, 0x6004, 0x8001, 0x0048, 0x3b30, 0x6006,
-	0x2009, 0x0000, 0xa684, 0x0001, 0x00c0, 0x3b20, 0xa18d, 0x8000,
-	0xa684, 0x0004, 0x0040, 0x3b26, 0xa18d, 0x0002, 0x691e, 0x6823,
-	0x0000, 0x7104, 0x810f, 0x6818, 0xa105, 0x681a, 0x0078, 0x3b0f,
-	0x1078, 0x23eb, 0x6018, 0xa005, 0x00c0, 0x3b41, 0x6008, 0x8001,
-	0x0048, 0x3b41, 0x600a, 0x601c, 0x6802, 0x2d00, 0x601e, 0x0078,
-	0x3b57, 0xac88, 0x0006, 0x2104, 0xa005, 0x0040, 0x3b4a, 0x2008,
-	0x0078, 0x3b43, 0x6802, 0x2d0a, 0x6008, 0x8001, 0x0048, 0x3b11,
-	0x600a, 0x6018, 0x2068, 0x6800, 0x601a, 0x0078, 0x3b3b, 0x157e,
-	0x137e, 0x147e, 0x0c7e, 0x0d7e, 0x1078, 0x1937, 0x2da0, 0x137f,
-	0x20a9, 0x0031, 0x53a3, 0x0c7f, 0x147f, 0x137f, 0x157f, 0x0078,
-	0x3b0f, 0xa184, 0x001f, 0x8003, 0x8003, 0x8003, 0xa080, 0x7510,
-	0x2060, 0x007c, 0x2019, 0x5151, 0x2304, 0xa085, 0x0001, 0x201a,
-	0x2019, 0x0102, 0x2304, 0xa085, 0x0001, 0x201a, 0x007c, 0x2019,
-	0x5151, 0x2304, 0xa084, 0xfffe, 0x201a, 0x2019, 0x0102, 0x2304,
-	0xa084, 0xfffe, 0x201a, 0x007c, 0x7990, 0xa18c, 0xfff8, 0x7992,
-	0x70b4, 0xa080, 0x00dd, 0x781a, 0x0078, 0x2459, 0x70a3, 0x0000,
-	0x7003, 0x0000, 0x7043, 0x0001, 0x7037, 0x0000, 0x0018, 0x2410,
-	0x1078, 0x1b8b, 0x0040, 0x3bc7, 0x2009, 0x510f, 0x200b, 0x0000,
-	0x68bc, 0x2060, 0x6100, 0xa184, 0x0300, 0x0040, 0x3bbb, 0x6827,
-	0x000e, 0xa084, 0x0200, 0x0040, 0x3bb7, 0x6827, 0x0017, 0x1078,
-	0x3af8, 0x0078, 0x3b96, 0x7000, 0xa086, 0x0007, 0x00c0, 0x3c29,
-	0x2d00, 0x70a2, 0xad80, 0x000f, 0x7036, 0x0078, 0x3bce, 0x7040,
-	0xa086, 0x0001, 0x0040, 0x2492, 0x0078, 0x2459, 0x2031, 0x0000,
-	0x691c, 0xa184, 0x0002, 0x0040, 0x3bd7, 0xa6b5, 0x0004, 0xa184,
-	0x00c0, 0x8003, 0x8003, 0x8007, 0xa080, 0x3cc2, 0x2004, 0xa635,
-	0x6820, 0xa084, 0x0400, 0x0040, 0x3bef, 0x789b, 0x0018, 0x78ab,
-	0x0003, 0x789b, 0x0081, 0x78ab, 0x0001, 0xa6b5, 0x1000, 0x6820,
-	0xa084, 0x8000, 0x00c0, 0x3bfd, 0x681c, 0xa084, 0x8000, 0x00c0,
-	0x3c04, 0xa6b5, 0x0800, 0x0078, 0x3c04, 0xa6b5, 0x0400, 0x789b,
-	0x000e, 0x6824, 0x8007, 0x78aa, 0x6820, 0xa084, 0x0100, 0x0040,
-	0x3c0b, 0xa6b5, 0x4000, 0xa684, 0x0200, 0x0040, 0x3c25, 0x682c,
-	0x78d2, 0x6830, 0x78d6, 0xa684, 0x0100, 0x0040, 0x3c23, 0x682c,
-	0xa084, 0x0001, 0x0040, 0x3c23, 0x7888, 0xa084, 0x0040, 0x0040,
-	0x3c23, 0xa6b5, 0x8000, 0x1078, 0x46f0, 0x7e5a, 0x6eb6, 0x0078,
-	0x4727, 0x1078, 0x38fa, 0x00c0, 0x3cbc, 0x702c, 0x8004, 0x0048,
-	0x3c37, 0x2019, 0x4e3b, 0x1078, 0x2276, 0x702f, 0x0001, 0x2041,
-	0x0001, 0x2031, 0x1000, 0x789b, 0x0018, 0x6814, 0xa084, 0x001f,
-	0xa085, 0x0080, 0x78aa, 0x691c, 0xa184, 0x0002, 0x0040, 0x3c50,
-	0xa6b5, 0x0004, 0x78ab, 0x0020, 0x6828, 0x78aa, 0xa8c0, 0x0002,
-	0x681c, 0xd0f4, 0x0040, 0x3c59, 0x2c50, 0x1078, 0x39ac, 0x1078,
-	0x45ff, 0x6820, 0xa084, 0x8000, 0x0040, 0x3c67, 0xa6b5, 0x0400,
-	0x789b, 0x000e, 0x6824, 0x8007, 0x78aa, 0x0078, 0x3c6e, 0x681c,
-	0xa084, 0x8000, 0x00c0, 0x3c6e, 0xa6b5, 0x0800, 0x6820, 0xa084,
-	0x0100, 0x0040, 0x3c75, 0xa6b5, 0x4000, 0x681c, 0xa084, 0x00c0,
-	0x8003, 0x8003, 0x8007, 0xa080, 0x3cc2, 0x2004, 0xa635, 0xa684,
-	0x0100, 0x0040, 0x3c8f, 0x682c, 0xa084, 0x0001, 0x0040, 0x3c8f,
-	0x7888, 0xa084, 0x0040, 0x0040, 0x3c8f, 0xa6b5, 0x8000, 0x789b,
-	0x007e, 0x7eae, 0x6eb6, 0x6814, 0x8007, 0x78aa, 0x7882, 0x2810,
-	0x7aaa, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x3cbc, 0x0018, 0x3cbc,
-	0x70b4, 0xa080, 0x00e2, 0x781a, 0x1078, 0x3912, 0xa684, 0x0200,
-	0x0040, 0x3cb0, 0x682c, 0x78d2, 0x6830, 0x78d6, 0x1078, 0x46f0,
-	0x2d00, 0x70a2, 0x704a, 0x6810, 0x70be, 0x7003, 0x0007, 0xad80,
-	0x000f, 0x7036, 0x0078, 0x2459, 0x1078, 0x1b62, 0x1078, 0x3912,
-	0x0078, 0x2459, 0x0000, 0x0300, 0x0200, 0x0000, 0x1078, 0x23eb,
-	0x2300, 0x0079, 0x3ccb, 0x3cce, 0x3cce, 0x3cd0, 0x1078, 0x23eb,
-	0x1078, 0x46ff, 0x6924, 0xa184, 0x00ff, 0xa086, 0x000a, 0x0040,
-	0x3ce2, 0xa184, 0xff00, 0xa085, 0x000a, 0x6826, 0x1078, 0x1b62,
-	0x0078, 0x3b96, 0x2001, 0x000a, 0x1078, 0x4691, 0x0078, 0x3b96,
-	0xa282, 0x0005, 0x0050, 0x3cee, 0x1078, 0x23eb, 0x7000, 0xa084,
-	0x0007, 0x10c0, 0x39be, 0x1078, 0x1937, 0x00c0, 0x3d0d, 0xa684,
-	0x0004, 0x0040, 0x3cff, 0x2001, 0x2800, 0x0078, 0x3d01, 0x2001,
-	0x0800, 0x71b4, 0xa188, 0x0091, 0x789b, 0x000e, 0x78aa, 0x2031,
-	0x0400, 0x7e5a, 0x791a, 0x0078, 0x2459, 0x6807, 0x0106, 0x680b,
-	0x0000, 0x689f, 0x0000, 0x6827, 0x0000, 0xa386, 0x0002, 0x00c0,
-	0x3d2e, 0xa286, 0x0002, 0x00c0, 0x3d2e, 0x78a0, 0xa005, 0x00c0,
-	0x3d2e, 0xa484, 0x8000, 0x00c0, 0x3d2e, 0x78e4, 0xa084, 0x0008,
-	0x0040, 0x3d2e, 0xa6b5, 0x0008, 0x2019, 0x0000, 0x1078, 0x411e,
-	0x2d00, 0x70a2, 0x704a, 0x7003, 0x0007, 0x7037, 0x0000, 0x6824,
-	0xa084, 0x0080, 0x0040, 0x3d40, 0x1078, 0x41d0, 0x0078, 0x2459,
-	0x2300, 0x0079, 0x3d43, 0x3d46, 0x3dc7, 0x3de6, 0x2200, 0x0079,
-	0x3d49, 0x3d4e, 0x3d5e, 0x3d84, 0x3d90, 0x3db3, 0x2029, 0x0001,
-	0xa026, 0x2011, 0x0000, 0x1078, 0x42f1, 0x0079, 0x3d57, 0x3d5c,
-	0x2459, 0x3b96, 0x3d5c, 0x3d5c, 0x1078, 0x23eb, 0x7990, 0xa18c,
-	0x0007, 0x00c0, 0x3d65, 0x2009, 0x0008, 0x2011, 0x0001, 0xa684,
-	0x0004, 0x0040, 0x3d6d, 0x2011, 0x0003, 0x2220, 0xa12a, 0x2011,
-	0x0001, 0x1078, 0x42f1, 0x0079, 0x3d75, 0x3d7a, 0x2459, 0x3b96,
-	0x3d82, 0x3d7c, 0x0078, 0x472d, 0x70ab, 0x3d80, 0x0078, 0x2459,
-	0x0078, 0x3d7a, 0x1078, 0x23eb, 0xa684, 0x0010, 0x0040, 0x3d8e,
-	0x1078, 0x419f, 0x0040, 0x3d8e, 0x0078, 0x2459, 0x0078, 0x420c,
-	0x6000, 0xa084, 0x0002, 0x0040, 0x3dad, 0x70b4, 0xa080, 0x00d2,
-	0x781a, 0x0d7e, 0x1078, 0x4708, 0x2d00, 0x682e, 0x6827, 0x0000,
-	0x1078, 0x3af8, 0x0d7f, 0x1078, 0x195a, 0x7003, 0x0000, 0x7037,
-	0x0000, 0x704b, 0x0000, 0x0078, 0x3b96, 0xa684, 0x0004, 0x00c0,
-	0x3db3, 0x0078, 0x472d, 0x6000, 0xa084, 0x0004, 0x00c0, 0x3dc5,
-	0x6000, 0xa084, 0x0001, 0x0040, 0x3dc5, 0x70ab, 0x3dc5, 0x2001,
-	0x0007, 0x1078, 0x4689, 0x0078, 0x4733, 0x0078, 0x472d, 0x2200,
-	0x0079, 0x3dca, 0x3dcf, 0x3dcf, 0x3dcf, 0x3dd1, 0x3dcf, 0x1078,
-	0x23eb, 0x70a7, 0x3dd5, 0x0078, 0x4739, 0x2011, 0x0018, 0x1078,
-	0x42eb, 0x0079, 0x3ddb, 0x3de0, 0x2459, 0x3b96, 0x3de2, 0x3de4,
-	0x1078, 0x23eb, 0x1078, 0x23eb, 0x1078, 0x23eb, 0x2200, 0x0079,
-	0x3de9, 0x3dee, 0x3df0, 0x3df0, 0x3dee, 0x3dee, 0x1078, 0x23eb,
-	0x78e4, 0xa084, 0x0008, 0x0040, 0x3e05, 0x70a7, 0x3df9, 0x0078,
-	0x4739, 0x2011, 0x0004, 0x1078, 0x42eb, 0x0079, 0x3dff, 0x3e05,
-	0x2459, 0x3b96, 0x3e05, 0x3e0f, 0x3e13, 0x70ab, 0x3e0d, 0x2001,
-	0x0003, 0x1078, 0x4689, 0x0078, 0x4733, 0x0078, 0x472d, 0x70ab,
-	0x3e05, 0x0078, 0x2459, 0x70ab, 0x3e17, 0x0078, 0x2459, 0x0078,
-	0x3e0d, 0xa282, 0x0003, 0x0050, 0x3e1f, 0x1078, 0x23eb, 0xa386,
-	0x0002, 0x00c0, 0x3e38, 0xa286, 0x0002, 0x00c0, 0x3e3e, 0x78a0,
-	0xa005, 0x00c0, 0x3e3e, 0xa484, 0x8000, 0x00c0, 0x3e3e, 0x78e4,
-	0xa084, 0x0008, 0x0040, 0x3e38, 0xa6b5, 0x0008, 0x2019, 0x0000,
-	0xa684, 0x0008, 0x0040, 0x3e3e, 0x1078, 0x417c, 0x6810, 0x70be,
-	0x7003, 0x0007, 0x2300, 0x0079, 0x3e45, 0x3e48, 0x3e75, 0x3e7d,
-	0x2200, 0x0079, 0x3e4b, 0x3e50, 0x3e4e, 0x3e69, 0x1078, 0x23eb,
-	0x7990, 0xa1ac, 0x0007, 0xa026, 0x2011, 0x0001, 0x1078, 0x42f1,
-	0x0079, 0x3e5a, 0x3e5f, 0x2459, 0x3b96, 0x3e67, 0x3e61, 0x0078,
-	0x472d, 0x70ab, 0x3e65, 0x0078, 0x2459, 0x0078, 0x3e5f, 0x1078,
-	0x23eb, 0xa684, 0x0010, 0x0040, 0x3e73, 0x1078, 0x419f, 0x0040,
-	0x3e73, 0x0078, 0x2459, 0x0078, 0x420c, 0x2200, 0x0079, 0x3e78,
-	0x3e7b, 0x3e7b, 0x3e7b, 0x1078, 0x23eb, 0x2200, 0x0079, 0x3e80,
-	0x3e83, 0x3e85, 0x3e85, 0x1078, 0x23eb, 0x78e4, 0xa084, 0x0008,
-	0x0040, 0x3e9a, 0x70a7, 0x3e8e, 0x0078, 0x4739, 0x2011, 0x0004,
-	0x1078, 0x42eb, 0x0079, 0x3e94, 0x3e9a, 0x2459, 0x3b96, 0x3e9a,
-	0x3ea4, 0x3ea8, 0x70ab, 0x3ea2, 0x2001, 0x0003, 0x1078, 0x4689,
-	0x0078, 0x4733, 0x0078, 0x472d, 0x70ab, 0x3e9a, 0x0078, 0x2459,
-	0x70ab, 0x3eac, 0x0078, 0x2459, 0x0078, 0x3ea2, 0x2300, 0x0079,
-	0x3eb1, 0x3eb6, 0x3eb8, 0x3eb4, 0x1078, 0x23eb, 0x70a4, 0x007a,
-	0x70a4, 0x007a, 0xa282, 0x0002, 0x0050, 0x3ec0, 0x1078, 0x23eb,
-	0xa684, 0x0200, 0x0040, 0x3eca, 0x1078, 0x46f8, 0x1078, 0x42d3,
-	0x1078, 0x46ff, 0x2300, 0x0079, 0x3ecd, 0x3ed0, 0x3ef4, 0x3f5a,
-	0xa286, 0x0001, 0x0040, 0x3ed6, 0x1078, 0x23eb, 0xa684, 0x0200,
-	0x0040, 0x3ede, 0x1078, 0x46f8, 0x1078, 0x46ff, 0x2001, 0x0001,
-	0x1078, 0x4691, 0x78b8, 0xa084, 0xc001, 0x0040, 0x3ef0, 0x7848,
-	0xa085, 0x0008, 0x784a, 0x7848, 0xa084, 0x0008, 0x00c0, 0x3eeb,
-	0x7003, 0x0000, 0x0078, 0x3b96, 0x2200, 0x0079, 0x3ef7, 0x3ef9,
-	0x3f2a, 0x70a7, 0x3efd, 0x0078, 0x4739, 0x2011, 0x000d, 0x1078,
-	0x42eb, 0x0079, 0x3f03, 0x3f0a, 0x2459, 0x3b96, 0x3f12, 0x3f1a,
-	0x3f20, 0x3f22, 0xa6b4, 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a,
-	0x0078, 0x4727, 0xa6b4, 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a,
-	0x0078, 0x4727, 0x70ab, 0x3f1e, 0x0078, 0x2459, 0x0078, 0x3f0a,
-	0x1078, 0x23eb, 0x70ab, 0x3f26, 0x0078, 0x2459, 0x1078, 0x473f,
-	0x0078, 0x2459, 0x70a7, 0x3f2e, 0x0078, 0x4739, 0x2011, 0x0012,
-	0x1078, 0x42eb, 0x0079, 0x3f34, 0x3f3a, 0x2459, 0x3b96, 0x3f46,
-	0x3f4e, 0x3f54, 0xa6b4, 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a,
-	0x70b4, 0xa080, 0x00a6, 0x781a, 0x0078, 0x2459, 0xa6b4, 0x00ff,
-	0xa6b5, 0x0400, 0x6eb6, 0x7e5a, 0x0078, 0x4727, 0x70ab, 0x3f52,
-	0x0078, 0x2459, 0x0078, 0x3f3a, 0x70ab, 0x3f58, 0x0078, 0x2459,
-	0x0078, 0x3f46, 0xa286, 0x0001, 0x0040, 0x3f60, 0x1078, 0x23eb,
-	0x70a7, 0x3f64, 0x0078, 0x4739, 0x2011, 0x0015, 0x1078, 0x42eb,
-	0x0079, 0x3f6a, 0x3f6f, 0x2459, 0x3b96, 0x3f7d, 0x3f89, 0xa6b4,
-	0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a, 0x783b, 0x1301, 0x70b4,
-	0xa080, 0x00b4, 0x781a, 0x0078, 0x2459, 0xa6b4, 0x00ff, 0xa6b5,
-	0x0400, 0x6eb6, 0x7e5a, 0x70b4, 0xa080, 0x00a6, 0x781a, 0x0078,
-	0x2459, 0x70ab, 0x3f8d, 0x0078, 0x2459, 0x0078, 0x3f6f, 0xa282,
-	0x0003, 0x0050, 0x3f95, 0x1078, 0x23eb, 0x2300, 0x0079, 0x3f98,
-	0x3f9b, 0x3fd2, 0x402d, 0xa286, 0x0001, 0x0040, 0x3fa1, 0x1078,
-	0x23eb, 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x3fae,
-	0x1078, 0x3af8, 0x7003, 0x0000, 0x0078, 0x3b96, 0x683b, 0x0000,
-	0x6837, 0x0000, 0xa684, 0x0200, 0x0040, 0x3fbc, 0x1078, 0x46f8,
-	0x1078, 0x42d3, 0x1078, 0x46ff, 0x2001, 0x0001, 0x1078, 0x4691,
-	0x78b8, 0xa084, 0xc001, 0x0040, 0x3fce, 0x7848, 0xa085, 0x0008,
-	0x784a, 0x7848, 0xa084, 0x0008, 0x00c0, 0x3fc9, 0x7003, 0x0000,
-	0x0078, 0x3b96, 0x2200, 0x0079, 0x3fd5, 0x3fd7, 0x4008, 0x70a7,
-	0x3fdb, 0x0078, 0x4739, 0x2011, 0x000d, 0x1078, 0x42eb, 0x0079,
-	0x3fe1, 0x3fe8, 0x2459, 0x3b96, 0x3ff0, 0x3ff8, 0x3ffe, 0x4000,
-	0xa6b4, 0x00ff, 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4727,
-	0xa6b4, 0x00ff, 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4727,
-	0x70ab, 0x3ffc, 0x0078, 0x2459, 0x0078, 0x3fe8, 0x1078, 0x23eb,
-	0x70ab, 0x4004, 0x0078, 0x2459, 0x1078, 0x473f, 0x0078, 0x2459,
-	0x70a7, 0x400c, 0x0078, 0x4739, 0x2011, 0x0005, 0x1078, 0x42eb,
-	0x0079, 0x4012, 0x4017, 0x2459, 0x3b96, 0x401f, 0x4027, 0xa6b4,
-	0x00ff, 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4727, 0xa6b4,
-	0x00ff, 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4727, 0x70ab,
-	0x402b, 0x0078, 0x2459, 0x0078, 0x4017, 0xa286, 0x0001, 0x0040,
-	0x4033, 0x1078, 0x23eb, 0x70a7, 0x4037, 0x0078, 0x4739, 0x2011,
-	0x0006, 0x1078, 0x42eb, 0x0079, 0x403d, 0x4042, 0x2459, 0x3b96,
-	0x4048, 0x4052, 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4727,
-	0xa6b4, 0x00ff, 0xa6b5, 0x0800, 0x6eb6, 0xa6b5, 0x4000, 0x7e5a,
-	0x0078, 0x4727, 0x70ab, 0x4056, 0x0078, 0x2459, 0x0078, 0x4042,
-	0x2300, 0x0079, 0x405b, 0x4060, 0x405e, 0x405e, 0x1078, 0x23eb,
-	0x1078, 0x23eb, 0x2300, 0x71a8, 0xa005, 0x017a, 0x6810, 0x70be,
-	0xa282, 0x0003, 0x0050, 0x406e, 0x1078, 0x23eb, 0x2300, 0x0079,
-	0x4071, 0x4074, 0x4082, 0x40a4, 0xa684, 0x0200, 0x0040, 0x407c,
-	0x1078, 0x46f8, 0x1078, 0x46ff, 0x2001, 0x0001, 0x1078, 0x4691,
-	0x0078, 0x2459, 0xa296, 0x0002, 0x0040, 0x408b, 0x82ff, 0x0040,
-	0x408b, 0x1078, 0x23eb, 0x70a7, 0x408f, 0x0078, 0x4739, 0x2011,
-	0x0018, 0x1078, 0x42eb, 0x0079, 0x4095, 0x409a, 0x2459, 0x3b96,
-	0x409c, 0x409e, 0x0078, 0x4727, 0x0078, 0x4727, 0x70ab, 0x40a2,
-	0x0078, 0x2459, 0x0078, 0x409a, 0x2200, 0x0079, 0x40a7, 0x40a9,
-	0x40c2, 0x70a7, 0x40ad, 0x0078, 0x4739, 0x2011, 0x0017, 0x1078,
-	0x42eb, 0x0079, 0x40b3, 0x40b8, 0x2459, 0x3b96, 0x40ba, 0x40bc,
-	0x0078, 0x4727, 0x0078, 0x4727, 0x70ab, 0x40c0, 0x0078, 0x2459,
-	0x0078, 0x40b8, 0xa484, 0x8000, 0x00c0, 0x410c, 0xa684, 0x0100,
-	0x0040, 0x40d6, 0x1078, 0x46f8, 0x1078, 0x42d3, 0x1078, 0x46ff,
-	0x7848, 0xa085, 0x000c, 0x784a, 0x0078, 0x40da, 0x78d8, 0x78d2,
-	0x78dc, 0x78d6, 0xa6b4, 0xefff, 0x7e5a, 0x70a7, 0x40e1, 0x0078,
-	0x4739, 0x2011, 0x000d, 0x1078, 0x42eb, 0x0079, 0x40e7, 0x40ee,
-	0x2459, 0x3b96, 0x40ee, 0x40fc, 0x4102, 0x4104, 0xa684, 0x0100,
-	0x0040, 0x40fa, 0x1078, 0x46b6, 0x682c, 0x78d2, 0x6830, 0x78d6,
-	0x1078, 0x46f0, 0x0078, 0x4727, 0x70ab, 0x4100, 0x0078, 0x2459,
-	0x0078, 0x40ee, 0x1078, 0x23eb, 0x70ab, 0x4108, 0x0078, 0x2459,
-	0x1078, 0x473f, 0x0078, 0x2459, 0x1078, 0x46ff, 0x70ab, 0x4116,
-	0x2001, 0x0003, 0x1078, 0x4689, 0x0078, 0x4733, 0x1078, 0x46f0,
-	0x682c, 0x78d2, 0x6830, 0x78d6, 0x0078, 0x4727, 0x70b8, 0x6812,
-	0x70be, 0x8000, 0x70ba, 0x681b, 0x0000, 0xa684, 0x0008, 0x0040,
-	0x4141, 0x157e, 0x137e, 0x147e, 0x7890, 0x8004, 0x8004, 0x8004,
-	0x8004, 0xa084, 0x000f, 0x681a, 0x80ac, 0x789b, 0x0000, 0xaf80,
-	0x002b, 0x2098, 0xad80, 0x000b, 0x20a0, 0x53a5, 0x147f, 0x137f,
-	0x157f, 0xa6c4, 0x0f00, 0xa684, 0x0002, 0x00c0, 0x4150, 0x692c,
-	0x810d, 0x810d, 0x810d, 0xa184, 0x0007, 0x2008, 0x0078, 0x415f,
-	0x789b, 0x0010, 0x79ac, 0xa184, 0x0020, 0x0040, 0x415f, 0x017e,
-	0x2009, 0x0005, 0x2001, 0x3d00, 0x1078, 0x46c1, 0x017f, 0xa184,
-	0x001f, 0xa805, 0x6816, 0x1078, 0x3b69, 0x68be, 0xa684, 0x0004,
-	0x0040, 0x4170, 0xa18c, 0xff00, 0x78a8, 0xa084, 0x00ff, 0xa105,
-	0x682a, 0xa6b4, 0x00ff, 0x6000, 0xa084, 0x0008, 0x0040, 0x417a,
-	0xa6b5, 0x4000, 0x6eb6, 0x007c, 0x157e, 0x137e, 0x147e, 0x6918,
-	0x7890, 0x8004, 0x8004, 0x8004, 0x8004, 0xa084, 0x000f, 0x007e,
-	0xa100, 0x681a, 0x007f, 0x8000, 0x8004, 0x0040, 0x419b, 0x20a8,
-	0x8104, 0xa080, 0x000b, 0xad00, 0x20a0, 0x789b, 0x0000, 0xaf80,
-	0x002b, 0x2098, 0x53a5, 0x147f, 0x137f, 0x157f, 0x007c, 0x682c,
-	0xa084, 0x0020, 0x00c0, 0x41a7, 0x620c, 0x0078, 0x41a8, 0x6210,
-	0x6b18, 0x2300, 0xa202, 0x0040, 0x41c8, 0x2018, 0xa382, 0x000e,
-	0x0048, 0x41b8, 0x0040, 0x41b8, 0x2019, 0x000e, 0x0078, 0x41bc,
-	0x7858, 0xa084, 0xffef, 0x785a, 0x783b, 0x1b01, 0x7893, 0x0000,
-	0x7ba2, 0x70b4, 0xa080, 0x008e, 0x781a, 0xa085, 0x0001, 0x007c,
-	0x7858, 0xa084, 0xffef, 0x785a, 0x7893, 0x0000, 0xa006, 0x007c,
-	0x6904, 0xa18c, 0x00ff, 0xa196, 0x0007, 0x0040, 0x41dd, 0xa196,
-	0x000f, 0x0040, 0x41dd, 0x6807, 0x0117, 0x6914, 0x1078, 0x3b69,
-	0x6100, 0x8104, 0x00c8, 0x41f8, 0x601c, 0xa005, 0x0040, 0x41ec,
-	0x2001, 0x0800, 0x0078, 0x41fa, 0x0d7e, 0x6824, 0x007e, 0x1078,
-	0x4708, 0x007f, 0x6826, 0x2d00, 0x682e, 0x1078, 0x3af8, 0x0d7f,
-	0x2001, 0x0200, 0x6826, 0x8007, 0x789b, 0x000e, 0x78aa, 0x6820,
-	0xa085, 0x8000, 0x6822, 0x2031, 0x0400, 0x6eb6, 0x7e5a, 0x71b4,
-	0xa188, 0x0091, 0x791a, 0x007c, 0xa6c4, 0x0f00, 0xa684, 0x0002,
-	0x00c0, 0x4220, 0x692c, 0x810d, 0x810d, 0x810d, 0xa184, 0x0007,
-	0x2008, 0xa805, 0x6816, 0x1078, 0x3b69, 0x68be, 0x0078, 0x4223,
-	0x6914, 0x1078, 0x3b69, 0x6100, 0x8104, 0x00c8, 0x4280, 0xa184,
-	0x0300, 0x0040, 0x422f, 0x6807, 0x0117, 0x0078, 0x424d, 0x6004,
-	0xa005, 0x00c0, 0x4256, 0x6807, 0x0117, 0x601c, 0xa005, 0x00c0,
-	0x4243, 0x0d7e, 0x1078, 0x4708, 0x6827, 0x0034, 0x2d00, 0x682e,
-	0x1078, 0x3af8, 0x0d7f, 0xa684, 0x0004, 0x0040, 0x424d, 0x2031,
-	0x0400, 0x2001, 0x2800, 0x0078, 0x4251, 0x2031, 0x0400, 0x2001,
-	0x0800, 0x71b4, 0xa188, 0x0091, 0x0078, 0x42ae, 0x6018, 0xa005,
-	0x00c0, 0x4243, 0x601c, 0xa005, 0x00c0, 0x4243, 0x689f, 0x0000,
-	0x6827, 0x003d, 0xa684, 0x0001, 0x0040, 0x42bc, 0xd694, 0x00c0,
-	0x4279, 0x6100, 0xd1d4, 0x0040, 0x4279, 0x692c, 0x81ff, 0x0040,
-	0x42bc, 0xa186, 0x0003, 0x0040, 0x42bc, 0xa186, 0x0012, 0x0040,
-	0x42bc, 0xa6b5, 0x0800, 0x71b4, 0xa188, 0x00af, 0x0078, 0x42b7,
-	0x6807, 0x0117, 0x2031, 0x0400, 0x692c, 0xa18c, 0x00ff, 0xa186,
-	0x0012, 0x00c0, 0x4291, 0x2001, 0x42c9, 0x2009, 0x0001, 0x0078,
-	0x42a2, 0xa186, 0x0003, 0x00c0, 0x429b, 0x2001, 0x42ca, 0x2009,
-	0x0012, 0x0078, 0x42a2, 0x2001, 0x0200, 0x71b4, 0xa188, 0x0091,
-	0x0078, 0x42ae, 0x1078, 0x46db, 0x78a3, 0x0000, 0x681c, 0xa085,
-	0x0040, 0x681e, 0x71b4, 0xa188, 0x00df, 0xa006, 0x6826, 0x8007,
-	0x789b, 0x000e, 0x78aa, 0x6820, 0xa085, 0x8000, 0x6822, 0x6eb6,
-	0x7e5a, 0x791a, 0x0078, 0x2459, 0x6eb6, 0x1078, 0x3af8, 0x6810,
-	0x70be, 0x7003, 0x0007, 0x70a3, 0x0000, 0x704b, 0x0000, 0x0078,
-	0x2459, 0x0023, 0x0070, 0x0005, 0x0000, 0x0a00, 0x0000, 0x0000,
-	0x0025, 0x0000, 0x0000, 0x683b, 0x0000, 0x6837, 0x0000, 0xa684,
-	0x0200, 0x0040, 0x42ea, 0x78b8, 0xa08c, 0x001f, 0xa084, 0x8000,
-	0x0040, 0x42e3, 0x8108, 0x78d8, 0xa100, 0x6836, 0x78dc, 0xa081,
-	0x0000, 0x683a, 0x007c, 0x7990, 0x810f, 0xa5ac, 0x0007, 0x2021,
-	0x0000, 0xa480, 0x0010, 0x789a, 0x79a8, 0xa18c, 0x00ff, 0xa184,
-	0x0080, 0x00c0, 0x4319, 0xa182, 0x0020, 0x00c8, 0x4337, 0xa182,
-	0x0012, 0x00c8, 0x467b, 0x2100, 0x1079, 0x4307, 0x007c, 0x467b,
-	0x44e8, 0x467b, 0x467b, 0x4344, 0x4347, 0x4381, 0x43b7, 0x43eb,
-	0x43ee, 0x467b, 0x467b, 0x43a2, 0x4412, 0x444c, 0x467b, 0x467b,
-	0x4473, 0xa184, 0x0020, 0x00c0, 0x44a7, 0xa18c, 0x001f, 0x6814,
-	0xa084, 0x001f, 0xa106, 0x0040, 0x4334, 0x70b4, 0xa080, 0x00d2,
-	0x781a, 0x2001, 0x0014, 0x1078, 0x4691, 0x1078, 0x46ff, 0x7003,
-	0x0000, 0x2001, 0x0002, 0x007c, 0x2001, 0x0000, 0x007c, 0xa182,
-	0x0024, 0x00c8, 0x467b, 0xa184, 0x0003, 0x1079, 0x4307, 0x007c,
-	0x467b, 0x467b, 0x467b, 0x467b, 0x1078, 0x467b, 0x007c, 0x2200,
-	0x0079, 0x434a, 0x4476, 0x4476, 0x436e, 0x436e, 0x436e, 0x436e,
-	0x436e, 0x436e, 0x436e, 0x436e, 0x436c, 0x436e, 0x4363, 0x436e,
-	0x436e, 0x436e, 0x436e, 0x436e, 0x4376, 0x4379, 0x4476, 0x4379,
-	0x436e, 0x436e, 0x436e, 0x0c7e, 0x077e, 0x6f14, 0x1078, 0x36e2,
-	0x077f, 0x0c7f, 0x0078, 0x436e, 0x1078, 0x458b, 0x6827, 0x02b3,
-	0x2009, 0x000b, 0x2001, 0x4800, 0x0078, 0x44aa, 0x1078, 0x4670,
-	0x007c, 0x6827, 0x0093, 0x2009, 0x000b, 0x2001, 0x4800, 0x0078,
-	0x4492, 0x2d58, 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0,
-	0x438b, 0x6807, 0x0117, 0x6827, 0x0002, 0x1078, 0x4708, 0x6827,
-	0x0036, 0x6932, 0x2d00, 0x682e, 0x0d7e, 0x1078, 0x3ac8, 0x1078,
-	0x44d0, 0x2b68, 0x1078, 0x3af8, 0x0d7f, 0x1078, 0x3af8, 0x2001,
-	0x0002, 0x007c, 0x1078, 0x44d0, 0x2001, 0x0017, 0x1078, 0x4691,
-	0x70a3, 0x0000, 0x2009, 0x5138, 0x200b, 0x0006, 0x70af, 0x0017,
-	0x2009, 0x0200, 0x1078, 0x3a06, 0x2001, 0x0001, 0x007c, 0x2200,
-	0x0079, 0x43ba, 0x4476, 0x44a7, 0x44a7, 0x44a7, 0x43db, 0x44b7,
-	0x43e3, 0x44b7, 0x44b7, 0x44ba, 0x44ba, 0x44bf, 0x44bf, 0x43d3,
-	0x43d3, 0x44a7, 0x44a7, 0x44b7, 0x44a7, 0x43e3, 0x4476, 0x43e3,
-	0x43e3, 0x43e3, 0x43e3, 0x6827, 0x0084, 0x2009, 0x000b, 0x2001,
-	0x4300, 0x0078, 0x44c9, 0x6827, 0x000d, 0x2009, 0x000b, 0x2001,
-	0x4300, 0x0078, 0x44aa, 0x6827, 0x0093, 0x2009, 0x000b, 0x2001,
-	0x4300, 0x0078, 0x4492, 0x2001, 0x0000, 0x007c, 0x2200, 0x0079,
-	0x43f1, 0x4476, 0x440a, 0x440a, 0x440a, 0x440a, 0x44b7, 0x44b7,
-	0x44b7, 0x44b7, 0x44b7, 0x44b7, 0x44b7, 0x44b7, 0x440a, 0x440a,
-	0x440a, 0x440a, 0x44b7, 0x440a, 0x440a, 0x44b7, 0x44b7, 0x44b7,
-	0x44b7, 0x4476, 0x6827, 0x0093, 0x2009, 0x000b, 0x2001, 0x4300,
-	0x0078, 0x4492, 0xa684, 0x0004, 0x00c0, 0x4426, 0x6804, 0xa084,
-	0x00ff, 0xa086, 0x0006, 0x00c0, 0x467b, 0x1078, 0x44d0, 0x6807,
-	0x0117, 0x1078, 0x3af8, 0x2001, 0x0002, 0x007c, 0x6000, 0xa084,
-	0x0004, 0x0040, 0x467b, 0x2d58, 0x6804, 0xa084, 0x00ff, 0xa086,
-	0x0006, 0x00c0, 0x4435, 0x6807, 0x0117, 0x6827, 0x0002, 0x1078,
-	0x4708, 0x6827, 0x0036, 0x6932, 0x2d00, 0x682e, 0x0d7e, 0x1078,
-	0x3ad7, 0x1078, 0x44d0, 0x2b68, 0x1078, 0x3af8, 0x0d7f, 0x1078,
-	0x3af8, 0x2001, 0x0002, 0x007c, 0x6000, 0xa084, 0x0004, 0x0040,
-	0x467b, 0x2d58, 0x6a04, 0xa294, 0x00ff, 0xa286, 0x0006, 0x00c0,
-	0x445b, 0x6807, 0x0117, 0x6827, 0x0002, 0x2d58, 0x1078, 0x4708,
-	0x6827, 0x0036, 0x6932, 0x2d00, 0x682e, 0x0d7e, 0x1078, 0x3ae7,
-	0x1078, 0x44d0, 0x2b68, 0x1078, 0x3af8, 0x0d7f, 0x1078, 0x3af8,
-	0x2001, 0x0002, 0x007c, 0x1078, 0x467b, 0x007c, 0x70b4, 0xa080,
-	0x00d2, 0x781a, 0x2001, 0x0001, 0x1078, 0x4691, 0x1078, 0x46ff,
-	0x7003, 0x0000, 0x2001, 0x0002, 0x007c, 0x1078, 0x46c1, 0x1078,
-	0x46f8, 0x1078, 0x42d3, 0x1078, 0x41d0, 0x1078, 0x46ff, 0x2001,
-	0x0001, 0x007c, 0x1078, 0x46c1, 0x1078, 0x46f8, 0x1078, 0x42d3,
-	0x70b4, 0xa080, 0x00d2, 0x781a, 0x2001, 0x0013, 0x1078, 0x4691,
-	0x1078, 0x46ff, 0x7003, 0x0000, 0x2001, 0x0002, 0x007c, 0x1078,
-	0x467b, 0x007c, 0x1078, 0x46c1, 0x1078, 0x46f8, 0x1078, 0x42d3,
-	0x1078, 0x41d0, 0x1078, 0x46ff, 0x2001, 0x0001, 0x007c, 0x2001,
-	0x0003, 0x007c, 0x1078, 0x458b, 0x2001, 0x0000, 0x007c, 0x0c7e,
-	0x077e, 0x6f14, 0x1078, 0x36e2, 0x077f, 0x0c7f, 0x2001, 0x0000,
-	0x007c, 0x1078, 0x46c1, 0x1078, 0x467b, 0x2001, 0x0006, 0x007c,
-	0x6904, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x44db, 0xa186,
-	0x000f, 0x00c0, 0x44df, 0x1078, 0x46f8, 0x1078, 0x42d3, 0x70b4,
-	0xa080, 0x00d2, 0x781a, 0x1078, 0x46ff, 0x7003, 0x0000, 0x007c,
-	0x7aa8, 0xa294, 0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a, 0x0004,
-	0x00c8, 0x467b, 0x1079, 0x44f5, 0x007c, 0x467b, 0x44f9, 0x467b,
-	0x4592, 0xa282, 0x0003, 0x0040, 0x4500, 0x1078, 0x467b, 0x007c,
-	0x7da8, 0xa5ac, 0x00ff, 0x7ca8, 0xa4a4, 0x00ff, 0x69b8, 0xa184,
-	0x0100, 0x0040, 0x453f, 0xa18c, 0xfeff, 0x69ba, 0x78a0, 0xa005,
-	0x00c0, 0x453f, 0xa4a4, 0x00ff, 0x0040, 0x4533, 0xa482, 0x000c,
-	0x0040, 0x451c, 0x00c8, 0x4526, 0x852b, 0x852b, 0x1078, 0x3760,
-	0x0040, 0x4526, 0x1078, 0x355b, 0x0078, 0x4535, 0x1078, 0x465d,
-	0x1078, 0x3586, 0x69b8, 0xa18d, 0x0100, 0x69ba, 0xa6b5, 0x1000,
-	0x7e5a, 0x0078, 0x4538, 0x1078, 0x3586, 0xa6b4, 0xefff, 0x7e5a,
-	0x70b4, 0xa080, 0x0091, 0x781a, 0x2001, 0x0001, 0x007c, 0x0c7e,
-	0x1078, 0x457f, 0x6200, 0xd2e4, 0x0040, 0x4570, 0x6208, 0x8217,
-	0xa294, 0x00ff, 0xa282, 0x000c, 0x0048, 0x4552, 0x0040, 0x4552,
-	0x2011, 0x000c, 0x2400, 0xa202, 0x00c8, 0x4557, 0x2220, 0x6208,
-	0xa294, 0x00ff, 0x701c, 0xa202, 0x00c8, 0x455f, 0x721c, 0x2200,
-	0xa502, 0x00c8, 0x4564, 0x2228, 0x1078, 0x4661, 0x852b, 0x852b,
-	0x1078, 0x3760, 0x0040, 0x4570, 0x1078, 0x3562, 0x0078, 0x4574,
-	0x1078, 0x465d, 0x1078, 0x358d, 0xa6b5, 0x1000, 0x7e5a, 0x70b4,
-	0xa080, 0x00be, 0x781a, 0x2001, 0x0004, 0x0c7f, 0x007c, 0x007e,
-	0x6814, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e0,
-	0x5380, 0x007f, 0x007c, 0x0c7e, 0x1078, 0x457f, 0x1078, 0x358d,
-	0x0c7f, 0x007c, 0xa282, 0x0002, 0x00c0, 0x467b, 0x7aa8, 0xa294,
-	0x00ff, 0x69b8, 0xa184, 0x0200, 0x0040, 0x45c9, 0xa18c, 0xfdff,
-	0x69ba, 0x78a0, 0xa005, 0x00c0, 0x45c9, 0xa282, 0x0002, 0x00c8,
-	0x369d, 0x1078, 0x4627, 0x1078, 0x362b, 0x1078, 0x3586, 0xa684,
-	0x0100, 0x0040, 0x45bf, 0x682c, 0xa084, 0x0001, 0x0040, 0x45bf,
-	0xc6fc, 0x7888, 0xa084, 0x0040, 0x0040, 0x45bf, 0xc6fd, 0xa6b5,
-	0x1000, 0x7e5a, 0x70b4, 0xa080, 0x0091, 0x781a, 0x2001, 0x0001,
-	0x007c, 0x0c7e, 0x1078, 0x457f, 0xa284, 0xfffe, 0x0040, 0x45d4,
-	0x2011, 0x0001, 0x0078, 0x45d8, 0xa284, 0x0001, 0x0040, 0x45de,
-	0x6100, 0xd1ec, 0x00c0, 0x45de, 0x2011, 0x0000, 0x1078, 0x4619,
-	0x1078, 0x3632, 0x1078, 0x358d, 0xa684, 0x0100, 0x0040, 0x45f4,
-	0x682c, 0xa084, 0x0001, 0x0040, 0x45f4, 0xc6fc, 0x7888, 0xa084,
-	0x0040, 0x0040, 0x45f4, 0xc6fd, 0xa6b5, 0x1000, 0x7e5a, 0x70b4,
-	0xa080, 0x00be, 0x781a, 0x2001, 0x0004, 0x0c7f, 0x007c, 0x0c7e,
-	0x2960, 0x6000, 0x2011, 0x0001, 0xa084, 0x2000, 0x00c0, 0x460a,
-	0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003,
-	0x7aaa, 0xa8c0, 0x0004, 0x68b8, 0xa085, 0x0200, 0x68ba, 0x0c7f,
-	0x007c, 0x789b, 0x0018, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab,
-	0x0003, 0x7aaa, 0x789b, 0x0081, 0x78ab, 0x0004, 0x007c, 0x0c7e,
-	0x7054, 0x2060, 0x6000, 0xa084, 0x1000, 0x00c0, 0x4635, 0x2029,
-	0x0032, 0x2021, 0x0000, 0x0078, 0x4655, 0x6508, 0xa5ac, 0x00ff,
-	0x7018, 0xa086, 0x0028, 0x00c0, 0x4645, 0xa582, 0x0019, 0x00c8,
-	0x464b, 0x2029, 0x0019, 0x0078, 0x464b, 0xa582, 0x000c, 0x00c8,
-	0x464b, 0x2029, 0x000c, 0x6408, 0x8427, 0xa4a4, 0x00ff, 0xa482,
-	0x000c, 0x0048, 0x4655, 0x2021, 0x000c, 0x1078, 0x4661, 0x68b8,
-	0xa085, 0x0100, 0x68ba, 0x0c7f, 0x007c, 0x2021, 0x0000, 0x2029,
-	0x0032, 0x789b, 0x0018, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab,
-	0x0001, 0x7daa, 0x7caa, 0x789b, 0x0081, 0x78ab, 0x0005, 0x007c,
-	0x2001, 0x0003, 0x1078, 0x4689, 0x70b4, 0xa080, 0x00be, 0x781a,
-	0x2001, 0x0005, 0x007c, 0x2001, 0x0007, 0x1078, 0x4689, 0xa6b5,
-	0x1000, 0x7e5a, 0x70b4, 0xa080, 0x00be, 0x781a, 0x2001, 0x0004,
-	0x007c, 0x789b, 0x0018, 0x78aa, 0x789b, 0x0081, 0x78ab, 0x0001,
-	0x007c, 0x6904, 0xa18c, 0x00ff, 0xa196, 0x0007, 0x0040, 0x469f,
-	0xa196, 0x000f, 0x0040, 0x469f, 0x1078, 0x195a, 0x007c, 0x6924,
-	0xa194, 0x003f, 0x00c0, 0x46a8, 0xa18c, 0xffc0, 0xa105, 0x6826,
-	0x1078, 0x3af8, 0x691c, 0xa184, 0x0100, 0x0040, 0x46b5, 0x6914,
-	0x1078, 0x3b69, 0x6204, 0x8210, 0x6206, 0x007c, 0x692c, 0x6834,
-	0x682e, 0xa112, 0x6930, 0x6838, 0x6832, 0xa11b, 0xa200, 0xa301,
-	0x007c, 0x0c7e, 0xade0, 0x0018, 0x6003, 0x0070, 0x6106, 0x600b,
-	0x0000, 0x600f, 0x0a00, 0x6013, 0x0000, 0x6017, 0x0000, 0x8007,
-	0x601a, 0x601f, 0x0000, 0x6023, 0x0000, 0x0c7f, 0x6824, 0xa085,
-	0x0080, 0x6826, 0x007c, 0x157e, 0x137e, 0x147e, 0x2098, 0xaf80,
-	0x002d, 0x20a0, 0x81ac, 0x0040, 0x46e6, 0x53a6, 0xa184, 0x0001,
-	0x0040, 0x46ec, 0x3304, 0x78be, 0x147f, 0x137f, 0x157f, 0x007c,
-	0x70b0, 0xa005, 0x10c0, 0x23eb, 0x70b3, 0x8000, 0x0078, 0x4a3a,
-	0x71b0, 0x81ff, 0x0040, 0x46fe, 0x1078, 0x4b30, 0x007c, 0x71b0,
-	0x81ff, 0x0040, 0x4707, 0x70b3, 0x0000, 0x1078, 0x4776, 0x007c,
-	0x0c7e, 0x0d7e, 0x1078, 0x1937, 0x0c7f, 0x157e, 0x137e, 0x147e,
-	0x2da0, 0x2c98, 0x20a9, 0x0031, 0x53a3, 0x147f, 0x137f, 0x157f,
-	0x6807, 0x010d, 0x680b, 0x0000, 0x7004, 0x8007, 0x681a, 0x6823,
-	0x0000, 0x681f, 0x0000, 0x689f, 0x0000, 0x0c7f, 0x007c, 0x70b4,
-	0xa080, 0x0091, 0x781a, 0x0078, 0x2459, 0x70b4, 0xa080, 0x0081,
-	0x781a, 0x0078, 0x2459, 0x70b4, 0xa080, 0x00be, 0x781a, 0x0078,
-	0x2459, 0x70b4, 0xa080, 0x00c8, 0x781a, 0x0078, 0x2459, 0x6904,
-	0xa18c, 0x00ff, 0xa196, 0x0007, 0x0040, 0x474c, 0xa196, 0x000f,
-	0x0040, 0x474c, 0x6807, 0x0117, 0x2001, 0x0200, 0x6826, 0x8007,
-	0x789b, 0x000e, 0x78aa, 0x6820, 0xa085, 0x8000, 0x6822, 0x2031,
-	0x0400, 0x6eb6, 0x7e5a, 0x71b4, 0xa188, 0x0091, 0x791a, 0x007c,
-	0x1078, 0x46ff, 0x7848, 0xa085, 0x000c, 0x784a, 0x70b4, 0xa080,
-	0x00d2, 0x781a, 0x2009, 0x000b, 0x2001, 0x4400, 0x1078, 0x46c1,
-	0x2001, 0x0013, 0x1078, 0x4691, 0x0078, 0x3b96, 0x127e, 0x2091,
-	0x2200, 0x2049, 0x4776, 0x7000, 0x7204, 0xa205, 0x720c, 0xa215,
-	0x7008, 0xa084, 0xfff7, 0xa205, 0x0040, 0x4788, 0x0078, 0x478d,
-	0x7003, 0x0000, 0x127f, 0x2000, 0x007c, 0x7000, 0xa084, 0x0001,
-	0x00c0, 0x47bb, 0x7108, 0x8103, 0x00c8, 0x479a, 0x1078, 0x48bd,
-	0x0078, 0x4792, 0x700c, 0xa08c, 0x00ff, 0x0040, 0x47bb, 0x7004,
-	0x8004, 0x00c8, 0x47b2, 0x7014, 0xa005, 0x00c0, 0x47ae, 0x7010,
-	0xa005, 0x0040, 0x47b2, 0xa102, 0x00c8, 0x4792, 0x7007, 0x0010,
-	0x0078, 0x47bb, 0x8aff, 0x0040, 0x47bb, 0x1078, 0x4b07, 0x00c0,
-	0x47b5, 0x0040, 0x4792, 0x1078, 0x4846, 0x7003, 0x0000, 0x127f,
-	0x2000, 0x007c, 0x017e, 0x6104, 0xa18c, 0x00ff, 0xa186, 0x0007,
-	0x0040, 0x47ce, 0xa18e, 0x000f, 0x00c0, 0x47d1, 0x6040, 0x0078,
-	0x47d2, 0x6428, 0x017f, 0x84ff, 0x0040, 0x47fc, 0x2c70, 0x7004,
-	0xa0bc, 0x000f, 0xa7b8, 0x480c, 0x273c, 0x87fb, 0x00c0, 0x47ea,
-	0x0048, 0x47e4, 0x1078, 0x23eb, 0x609c, 0xa075, 0x0040, 0x47fc,
-	0x0078, 0x47d7, 0x2704, 0xae68, 0x6808, 0xa630, 0x680c, 0xa529,
-	0x8421, 0x0040, 0x47fc, 0x8738, 0x2704, 0xa005, 0x00c0, 0x47eb,
-	0x709c, 0xa075, 0x00c0, 0x47d7, 0x007c, 0x0000, 0x0005, 0x0009,
-	0x000d, 0x0011, 0x0015, 0x0019, 0x001d, 0x0000, 0x0003, 0x0009,
-	0x000f, 0x0015, 0x001b, 0x0000, 0x0000, 0x4801, 0x47fe, 0x0000,
-	0x0000, 0x8000, 0x0000, 0x4801, 0x0000, 0x4809, 0x4806, 0x0000,
-	0x0000, 0x0000, 0x0000, 0x4809, 0x0000, 0x4804, 0x4804, 0x0000,
-	0x0000, 0x8000, 0x0000, 0x4804, 0x0000, 0x480a, 0x480a, 0x0000,
-	0x0000, 0x0000, 0x0000, 0x480a, 0x127e, 0x2091, 0x2200, 0x2079,
-	0x5100, 0x2071, 0x0010, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003,
-	0x0000, 0x2071, 0x0020, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003,
-	0x0000, 0x2049, 0x0000, 0x127f, 0x2000, 0x007c, 0x2049, 0x4846,
-	0x2019, 0x0000, 0x7004, 0x8004, 0x00c8, 0x4899, 0x7007, 0x0012,
-	0x7108, 0x7008, 0xa106, 0x00c0, 0x4850, 0xa184, 0x01e0, 0x0040,
-	0x485b, 0x1078, 0x23eb, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005,
-	0x00c8, 0x4866, 0xa184, 0x4000, 0x00c0, 0x4850, 0xa19c, 0x300c,
-	0xa386, 0x2004, 0x0040, 0x4874, 0xa386, 0x0008, 0x0040, 0x487f,
-	0xa386, 0x200c, 0x00c0, 0x4850, 0x7200, 0x8204, 0x0048, 0x487f,
-	0x730c, 0xa384, 0x00ff, 0x0040, 0x487f, 0x1078, 0x23eb, 0x7007,
-	0x0012, 0x7000, 0xa084, 0x0001, 0x00c0, 0x4899, 0x7008, 0xa084,
-	0x01e0, 0x00c0, 0x4899, 0x7310, 0x7014, 0xa305, 0x0040, 0x4899,
-	0x710c, 0xa184, 0x0300, 0x00c0, 0x4899, 0xa184, 0x00ff, 0x00c0,
-	0x4846, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xa084, 0x0008,
-	0x00c0, 0x489d, 0x7007, 0x0012, 0x7108, 0x8103, 0x0048, 0x48a2,
-	0x7003, 0x0000, 0x2049, 0x0000, 0x007c, 0x107e, 0x007e, 0x127e,
-	0x157e, 0x2091, 0x2200, 0x7108, 0x1078, 0x48bd, 0x157f, 0x127f,
-	0x2091, 0x8001, 0x007f, 0x107f, 0x007c, 0x7204, 0x7500, 0x730c,
-	0xa384, 0x0300, 0x00c0, 0x48e4, 0xa184, 0x01e0, 0x00c0, 0x4908,
-	0x7108, 0xa184, 0x01e0, 0x00c0, 0x4908, 0x2001, 0x04fd, 0x2004,
-	0xa082, 0x0005, 0x00c8, 0x48d8, 0xa184, 0x4000, 0x00c0, 0x48c8,
-	0xa184, 0x0007, 0x0079, 0x48dc, 0x48e6, 0x48f8, 0x48e4, 0x48f8,
-	0x48e4, 0x4944, 0x48e4, 0x4942, 0x1078, 0x23eb, 0x7004, 0xa084,
-	0x0010, 0xa085, 0x0002, 0x7006, 0x8aff, 0x00c0, 0x48f3, 0x2049,
-	0x0000, 0x0078, 0x48f7, 0x1078, 0x4b07, 0x00c0, 0x48f3, 0x007c,
-	0x7004, 0xa084, 0x0010, 0xa085, 0x0002, 0x7006, 0x8aff, 0x00c0,
-	0x4903, 0x0078, 0x4907, 0x1078, 0x4b07, 0x00c0, 0x4903, 0x007c,
-	0x7007, 0x0012, 0x7108, 0x00e0, 0x490b, 0x2091, 0x6000, 0x00e0,
-	0x490f, 0x2091, 0x6000, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004,
-	0xa084, 0x0008, 0x00c0, 0x4917, 0x7007, 0x0012, 0x7108, 0x8103,
-	0x0048, 0x491c, 0x7003, 0x0000, 0x7000, 0xa005, 0x00c0, 0x4930,
-	0x7004, 0xa005, 0x00c0, 0x4930, 0x700c, 0xa005, 0x0040, 0x4932,
-	0x0078, 0x4913, 0x2049, 0x0000, 0x1078, 0x3809, 0x6818, 0xa084,
-	0x8000, 0x0040, 0x493d, 0x681b, 0x0002, 0x007c, 0x1078, 0x23eb,
-	0x1078, 0x23eb, 0x1078, 0x49a0, 0x7210, 0x7114, 0x700c, 0xa09c,
-	0x00ff, 0x2800, 0xa300, 0xa211, 0xa189, 0x0000, 0x1078, 0x49a0,
-	0x2704, 0x2c58, 0xac60, 0x6308, 0x2200, 0xa322, 0x630c, 0x2100,
-	0xa31b, 0x2400, 0xa305, 0x0040, 0x4967, 0x00c8, 0x4967, 0x8412,
-	0x8210, 0x830a, 0xa189, 0x0000, 0x2b60, 0x0078, 0x494e, 0x2b60,
-	0x8a07, 0x007e, 0x6004, 0xa084, 0x0008, 0x0040, 0x4973, 0xa7ba,
-	0x4806, 0x0078, 0x4975, 0xa7ba, 0x47fe, 0x007f, 0xa73d, 0x2c00,
-	0x6886, 0x6f8a, 0x6c92, 0x6b8e, 0x7007, 0x0012, 0x1078, 0x4846,
-	0x007c, 0x8738, 0x2704, 0xa005, 0x00c0, 0x4994, 0x609c, 0xa005,
-	0x0040, 0x499d, 0x2060, 0x6004, 0xa084, 0x000f, 0xa080, 0x480c,
-	0x203c, 0x87fb, 0x1040, 0x23eb, 0x8a51, 0x0040, 0x499c, 0x7008,
-	0xa084, 0x0003, 0xa086, 0x0003, 0x007c, 0x2051, 0x0000, 0x007c,
-	0x8a50, 0x8739, 0x2704, 0xa004, 0x00c0, 0x49b4, 0x6000, 0xa064,
-	0x00c0, 0x49ab, 0x2d60, 0x6004, 0xa084, 0x000f, 0xa080, 0x481c,
-	0x203c, 0x87fb, 0x1040, 0x23eb, 0x007c, 0x127e, 0x0d7e, 0x2091,
-	0x2200, 0x0d7f, 0x6884, 0x2060, 0x6888, 0x6b8c, 0x6c90, 0x8057,
-	0xaad4, 0x00ff, 0xa084, 0x00ff, 0x007e, 0x6804, 0xa084, 0x0008,
-	0x007f, 0x0040, 0x49cf, 0xa0b8, 0x4806, 0x0078, 0x49d1, 0xa0b8,
-	0x47fe, 0x7e08, 0xa6b5, 0x000c, 0x6904, 0xa18c, 0x00ff, 0xa186,
-	0x0007, 0x0040, 0x49df, 0xa18e, 0x000f, 0x00c0, 0x49e8, 0x681c,
-	0xa084, 0x0040, 0x0040, 0x49ef, 0xa6b5, 0x0001, 0x0078, 0x49ef,
-	0x681c, 0xa084, 0x0040, 0x0040, 0x49ef, 0xa6b5, 0x0001, 0x7007,
-	0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x49f1, 0x2400, 0xa305,
-	0x00c0, 0x49fc, 0x0078, 0x4a22, 0x2c58, 0x2704, 0x6104, 0xac60,
-	0x6000, 0xa400, 0x701a, 0x6004, 0xa301, 0x701e, 0xa184, 0x0008,
-	0x0040, 0x4a12, 0x6010, 0xa081, 0x0000, 0x7022, 0x6014, 0xa081,
-	0x0000, 0x7026, 0x6208, 0x2400, 0xa202, 0x7012, 0x620c, 0x2300,
-	0xa203, 0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x1078, 0x4981,
-	0x0078, 0x4a24, 0x1078, 0x4b07, 0x00c0, 0x4a22, 0x127f, 0x2000,
-	0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x7007, 0x0004,
-	0x7004, 0xa084, 0x0004, 0x00c0, 0x4a30, 0x7003, 0x0008, 0x127f,
-	0x2000, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x2049,
-	0x4a3a, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x4a43,
-	0x7e08, 0xa6b5, 0x000c, 0x6904, 0xa18c, 0x00ff, 0xa186, 0x0007,
-	0x0040, 0x4a56, 0xa18e, 0x000f, 0x00c0, 0x4a61, 0x681c, 0xa084,
-	0x0040, 0x0040, 0x4a5d, 0xa6b5, 0x0001, 0x6840, 0x2050, 0x0078,
-	0x4a6a, 0x681c, 0xa084, 0x0020, 0x00c0, 0x4a68, 0xa6b5, 0x0001,
-	0x6828, 0x2050, 0x2d60, 0x6004, 0xa0bc, 0x000f, 0xa7b8, 0x480c,
-	0x273c, 0x87fb, 0x00c0, 0x4a7e, 0x0048, 0x4a78, 0x1078, 0x23eb,
-	0x689c, 0xa065, 0x0040, 0x4a82, 0x0078, 0x4a6b, 0x1078, 0x4b07,
-	0x00c0, 0x4a7e, 0x127f, 0x2000, 0x007c, 0x127e, 0x007e, 0x017e,
-	0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x037f, 0x047f, 0x7e08, 0xa6b5,
-	0x000c, 0x6904, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x4a9c,
-	0xa18e, 0x000f, 0x00c0, 0x4aa5, 0x681c, 0xa084, 0x0040, 0x0040,
-	0x4aac, 0xa6b5, 0x0001, 0x0078, 0x4aac, 0x681c, 0xa084, 0x0040,
-	0x0040, 0x4aac, 0xa6b5, 0x0001, 0x2049, 0x4a85, 0x017e, 0x6904,
-	0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x4aba, 0xa18e, 0x000f,
-	0x00c0, 0x4abd, 0x6840, 0x0078, 0x4abe, 0x6828, 0x017f, 0xa055,
-	0x0040, 0x4b04, 0x2d70, 0x2e60, 0x7004, 0xa0bc, 0x000f, 0xa7b8,
-	0x480c, 0x273c, 0x87fb, 0x00c0, 0x4ad8, 0x0048, 0x4ad1, 0x1078,
-	0x23eb, 0x709c, 0xa075, 0x2060, 0x0040, 0x4b04, 0x0078, 0x4ac4,
-	0x2704, 0xae68, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0048, 0x4af1,
-	0x8a51, 0x00c0, 0x4ae5, 0x1078, 0x23eb, 0x8738, 0x2704, 0xa005,
-	0x00c0, 0x4ad9, 0x709c, 0xa075, 0x2060, 0x0040, 0x4b04, 0x0078,
-	0x4ac4, 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x6908, 0x2400,
-	0xa122, 0x690c, 0x2300, 0xa11b, 0x00c8, 0x4b00, 0x1078, 0x23eb,
-	0x2071, 0x0020, 0x0078, 0x49ef, 0x127f, 0x2000, 0x007c, 0x7008,
-	0xa084, 0x0003, 0xa086, 0x0003, 0x0040, 0x4b2f, 0x2704, 0xac08,
-	0x2104, 0x701a, 0x8108, 0x2104, 0x701e, 0x8108, 0x2104, 0x7012,
-	0x8108, 0x2104, 0x7016, 0x6004, 0xa084, 0x0008, 0x0040, 0x4b26,
-	0x8108, 0x2104, 0x7022, 0x8108, 0x2104, 0x7026, 0x7602, 0x7004,
-	0xa084, 0x0010, 0xa085, 0x0001, 0x7006, 0x1078, 0x4981, 0x007c,
-	0x127e, 0x007e, 0x0d7e, 0x2091, 0x2200, 0x2049, 0x4b30, 0x0d7f,
-	0x087f, 0x7108, 0xa184, 0x0003, 0x00c0, 0x4b5a, 0x017e, 0x6904,
-	0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x4b4a, 0xa18e, 0x000f,
-	0x00c0, 0x4b4d, 0x6840, 0x0078, 0x4b4e, 0x6828, 0x017f, 0xa005,
-	0x0040, 0x4b68, 0x0078, 0x478d, 0x0020, 0x4b5a, 0x1078, 0x4944,
-	0x0078, 0x4b68, 0x00a0, 0x4b61, 0x7108, 0x1078, 0x48bd, 0x0078,
-	0x4b39, 0x7007, 0x0010, 0x00a0, 0x4b63, 0x7108, 0x1078, 0x48bd,
-	0x7008, 0xa086, 0x0008, 0x00c0, 0x4b39, 0x7000, 0xa005, 0x00c0,
-	0x4b39, 0x7003, 0x0000, 0x2049, 0x0000, 0x127f, 0x2000, 0x007c,
-	0x127e, 0x147e, 0x137e, 0x157e, 0x0c7e, 0x0d7e, 0x2091, 0x2200,
-	0x0d7f, 0x2049, 0x4b78, 0xad80, 0x0011, 0x20a0, 0x2099, 0x0031,
-	0x700c, 0xa084, 0x00ff, 0x682a, 0x7007, 0x0008, 0x7007, 0x0002,
-	0x7003, 0x0001, 0x0040, 0x4b97, 0x8000, 0x80ac, 0x53a5, 0x7007,
-	0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x4b99, 0x0c7f, 0x2049,
-	0x0000, 0x7003, 0x0000, 0x157f, 0x137f, 0x147f, 0x127f, 0x2000,
-	0x007c, 0x2091, 0x6000, 0x2091, 0x8000, 0x78cc, 0xa005, 0x0040,
-	0x4bc0, 0x7994, 0x70d0, 0xa106, 0x00c0, 0x4bc0, 0x7804, 0xa005,
-	0x0040, 0x4bc0, 0x7807, 0x0000, 0x0068, 0x4bc0, 0x2091, 0x4080,
-	0x7820, 0x8001, 0x7822, 0x00c0, 0x4c1b, 0x7824, 0x7822, 0x2069,
-	0x5140, 0x6800, 0xa084, 0x0007, 0x0040, 0x4bde, 0xa086, 0x0002,
-	0x0040, 0x4bde, 0x6834, 0xa00d, 0x0040, 0x4bde, 0x2104, 0xa005,
-	0x0040, 0x4bde, 0x8001, 0x200a, 0x0040, 0x4cc3, 0x7848, 0xa005,
-	0x0040, 0x4bec, 0x8001, 0x784a, 0x00c0, 0x4bec, 0x2009, 0x0102,
-	0x6844, 0x200a, 0x1078, 0x21d2, 0x6890, 0xa005, 0x0040, 0x4bf8,
-	0x8001, 0x6892, 0x00c0, 0x4bf8, 0x686f, 0x0000, 0x6873, 0x0001,
-	0x2061, 0x5400, 0x20a9, 0x0100, 0x2009, 0x0002, 0x6034, 0xa005,
-	0x0040, 0x4c0e, 0x8001, 0x6036, 0x00c0, 0x4c0e, 0x6010, 0xa005,
-	0x0040, 0x4c0e, 0x017e, 0x1078, 0x21d2, 0x017f, 0xace0, 0x0010,
-	0x0070, 0x4c14, 0x0078, 0x4bfe, 0x8109, 0x0040, 0x4c1b, 0x20a9,
-	0x0100, 0x0078, 0x4bfe, 0x1078, 0x4c28, 0x1078, 0x4c4d, 0x2009,
-	0x5151, 0x2104, 0x2009, 0x0102, 0x200a, 0x2091, 0x8001, 0x007c,
-	0x7834, 0x8001, 0x7836, 0x00c0, 0x4c4c, 0x7838, 0x7836, 0x2091,
-	0x8000, 0x7844, 0xa005, 0x00c0, 0x4c37, 0x2001, 0x0101, 0x8001,
-	0x7846, 0xa080, 0x7400, 0x2040, 0x2004, 0xa065, 0x0040, 0x4c4c,
-	0x6024, 0xa005, 0x0040, 0x4c48, 0x8001, 0x6026, 0x0040, 0x4c7c,
-	0x6000, 0x2c40, 0x0078, 0x4c3d, 0x007c, 0x7828, 0x8001, 0x782a,
-	0x00c0, 0x4c7b, 0x782c, 0x782a, 0x7830, 0xa005, 0x00c0, 0x4c5a,
-	0x2001, 0x0200, 0x8001, 0x7832, 0x8003, 0x8003, 0x8003, 0x8003,
-	0xa090, 0x5400, 0xa298, 0x0002, 0x2304, 0xa084, 0x0008, 0x0040,
-	0x4c7b, 0xa290, 0x0009, 0x2204, 0xa005, 0x0040, 0x4c73, 0x8001,
-	0x2012, 0x00c0, 0x4c7b, 0x2304, 0xa084, 0xfff7, 0xa085, 0x0080,
-	0x201a, 0x1078, 0x21d2, 0x007c, 0x2069, 0x5140, 0x6800, 0xa005,
-	0x0040, 0x4c86, 0x6848, 0xac06, 0x0040, 0x4cc3, 0x601b, 0x0006,
-	0x60b4, 0xa084, 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085,
-	0x0060, 0x6022, 0x6000, 0x2042, 0x6714, 0x6f82, 0x1078, 0x1973,
-	0x6818, 0xa005, 0x0040, 0x4c9e, 0x8001, 0x681a, 0x6808, 0xa084,
-	0xffef, 0x680a, 0x6810, 0x8001, 0x00d0, 0x4ca8, 0x1078, 0x23eb,
-	0x6812, 0x602f, 0x0000, 0x6033, 0x0000, 0x2c68, 0x1078, 0x1c70,
-	0x2069, 0x5140, 0x7944, 0xa184, 0x0100, 0x2001, 0x0006, 0x686e,
-	0x00c0, 0x4cbe, 0x6986, 0x2001, 0x0004, 0x686e, 0x1078, 0x21cd,
-	0x2091, 0x8001, 0x007c, 0x2069, 0x0100, 0x2009, 0x5140, 0x2104,
-	0xa084, 0x0007, 0x0040, 0x4d1f, 0xa086, 0x0007, 0x00c0, 0x4cd9,
-	0x0d7e, 0x2009, 0x5152, 0x216c, 0x1078, 0x3a4e, 0x0d7f, 0x0078,
-	0x4d1f, 0x2009, 0x5152, 0x2164, 0x1078, 0x2396, 0x601b, 0x0006,
-	0x6858, 0xa084, 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085,
-	0x0048, 0x6022, 0x602f, 0x0000, 0x6033, 0x0000, 0x6830, 0xa084,
-	0x0040, 0x0040, 0x4d13, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848,
-	0xa084, 0x0004, 0x0040, 0x4d00, 0x0070, 0x4d00, 0x0078, 0x4cf7,
-	0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0001, 0x0040,
-	0x4d0d, 0x0070, 0x4d0d, 0x0078, 0x4d04, 0x20a9, 0x00fa, 0x0070,
-	0x4d13, 0x0078, 0x4d0f, 0x6808, 0xa084, 0xfffd, 0x680a, 0x681b,
-	0x0048, 0x2009, 0x515b, 0x200b, 0x0007, 0x784c, 0x784a, 0x2091,
-	0x8001, 0x007c, 0x2079, 0x5100, 0x1078, 0x4d4d, 0x1078, 0x4d31,
-	0x1078, 0x4d3f, 0x7833, 0x0000, 0x7847, 0x0000, 0x784b, 0x0000,
-	0x007c, 0x2019, 0x0003, 0x2011, 0x5146, 0x2204, 0xa086, 0x003c,
-	0x0040, 0x4d3c, 0x2019, 0x0002, 0x7b2a, 0x7b2e, 0x007c, 0x2019,
-	0x0039, 0x2011, 0x5146, 0x2204, 0xa086, 0x003c, 0x0040, 0x4d4a,
-	0x2019, 0x0027, 0x7b36, 0x7b3a, 0x007c, 0x2019, 0x3971, 0x2011,
-	0x5146, 0x2204, 0xa086, 0x003c, 0x0040, 0x4d58, 0x2019, 0x2626,
-	0x7b22, 0x7b26, 0x783f, 0x0000, 0x7843, 0x000a, 0x007c, 0x0020,
-	0x002b, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
-	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
-	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
-	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
-	0x0020, 0x0000, 0x0014, 0x0014, 0x9849, 0x0014, 0x0014, 0x0014,
-	0x0014, 0x0014, 0x0014, 0x0014, 0x0080, 0x000f, 0x0000, 0x0201,
-	0x0604, 0x0c08, 0x2120, 0x4022, 0xf880, 0x0018, 0x300b, 0xa201,
-	0x0014, 0xa200, 0x0014, 0xa200, 0x0214, 0x0000, 0x006c, 0x0002,
-	0x0014, 0x98d0, 0x009e, 0x0096, 0xa202, 0x8838, 0x3806, 0x8839,
-	0x20c3, 0x0864, 0x9884, 0x28c1, 0x9cb1, 0xa203, 0x300c, 0x2846,
-	0x8161, 0x846a, 0x8300, 0x1856, 0x883a, 0x9865, 0x28f2, 0x9c90,
-	0x9858, 0x300c, 0x28e1, 0x9c90, 0x2802, 0xa206, 0x64c3, 0x282d,
-	0xa207, 0x64a0, 0x67a0, 0x6fc0, 0x1814, 0x883b, 0x7824, 0x68c1,
-	0x7864, 0x883e, 0x9878, 0x8576, 0x8677, 0x206b, 0x28c1, 0x9cb1,
-	0x2044, 0x2103, 0x20a2, 0x2081, 0x9865, 0xa209, 0x2901, 0x988c,
-	0x0014, 0xa205, 0xa300, 0x1872, 0x879a, 0x883c, 0x1fe2, 0xc601,
-	0xa20a, 0x856e, 0x0704, 0x9c90, 0x0014, 0xa204, 0xa300, 0x3009,
-	0x19e2, 0xf868, 0x8176, 0x86eb, 0x85eb, 0x872e, 0x87a9, 0x883f,
-	0x08e6, 0x9890, 0xf881, 0x988b, 0xc801, 0x0014, 0xf8c1, 0x0016,
-	0x85b2, 0x80f0, 0x9532, 0xfb02, 0x1de2, 0x0014, 0x8532, 0xf241,
-	0x0014, 0x1de2, 0x84a8, 0xd7a0, 0x1fe6, 0x0014, 0xa208, 0x6043,
-	0x8008, 0x1dc1, 0x0016, 0x8300, 0x8160, 0x842a, 0xf041, 0x3008,
-	0x84a8, 0x11d6, 0x7042, 0x20dd, 0x0011, 0x20d5, 0x8822, 0x0016,
-	0x8000, 0x2847, 0x1011, 0x98c3, 0x8000, 0xa000, 0x2802, 0x1011,
-	0x98c9, 0x9865, 0x283e, 0x1011, 0x98cd, 0xa20b, 0x0017, 0x300c,
-	0xa300, 0x1de2, 0xdb81, 0x0014, 0x0210, 0x98da, 0x0014, 0x26e0,
-	0x873a, 0xfb02, 0x19f2, 0x1fe2, 0x0014, 0xa20d, 0x3806, 0x0210,
-	0x9cb6, 0x0704, 0x0000, 0x006c, 0x0002, 0x984f, 0x0014, 0x009e,
-	0x00a5, 0x0017, 0x60ff, 0x300c, 0x8720, 0xa211, 0x9cd5, 0x8772,
-	0x8837, 0x2101, 0x987a, 0x10d2, 0x78e2, 0x9cd8, 0x9859, 0xd984,
-	0xf0e2, 0xf0a1, 0x98d2, 0x0014, 0x8831, 0xd166, 0x8830, 0x800f,
-	0x9401, 0xb520, 0xc802, 0x8820, 0x987a, 0x2301, 0x987a, 0x10d2,
-	0x78e4, 0x9cd8, 0x8821, 0x8820, 0x9859, 0xf123, 0xf142, 0xf101,
-	0x98cb, 0x10d2, 0x70f6, 0x8832, 0x8203, 0x870c, 0xd99e, 0x6001,
-	0x0014, 0x6845, 0x0214, 0xa21b, 0x9cd5, 0x2001, 0x98ca, 0x8201,
-	0x1852, 0xd184, 0xd163, 0x8834, 0x8001, 0x988d, 0x3027, 0x84a8,
-	0x1a56, 0x8833, 0x0014, 0xa218, 0x6981, 0x9cc1, 0x692a, 0x6902,
-	0x1834, 0x989d, 0x1a14, 0x8010, 0x8592, 0x8026, 0x84b9, 0x7021,
-	0x0014, 0xa300, 0x69e1, 0x9caa, 0x694c, 0xa213, 0x9cba, 0x1462,
-	0xa213, 0x8000, 0x16e1, 0x98b4, 0x8023, 0x16e1, 0x8001, 0x10f1,
-	0x0016, 0x6968, 0xa214, 0x9cba, 0x8004, 0x16e1, 0x0101, 0x300a,
-	0x8827, 0x0014, 0x9cba, 0x0014, 0x61c2, 0x8002, 0x14e1, 0x0016,
-	0xa217, 0x9cc1, 0x0014, 0xa300, 0x8181, 0x842a, 0x84a8, 0x1ce6,
-	0x882c, 0x0016, 0xa212, 0x9cd5, 0x10d2, 0x70e4, 0x0004, 0x8007,
-	0x9424, 0xcc1a, 0x9cd8, 0x98ca, 0x8827, 0x300a, 0x0013, 0x8000,
-	0x84a4, 0x0016, 0x11c2, 0x211e, 0x870e, 0xa21d, 0x0014, 0x878e,
-	0x0016, 0xa21c, 0x1035, 0x9891, 0xa210, 0xa000, 0x8010, 0x8592,
-	0x853b, 0xd044, 0x8022, 0x3807, 0x84bb, 0x98ef, 0x8021, 0x3807,
-	0x84b9, 0x300c, 0x817e, 0x872b, 0x8772, 0x9891, 0x0000, 0x0020,
-	0x002b, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
-	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
-	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
-	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
-	0x0020, 0x0000, 0x0014, 0x0014, 0x9849, 0x0014, 0x0014, 0x98e5,
-	0x98d0, 0x0014, 0x0014, 0x0014, 0x0080, 0x013f, 0x0000, 0x0201,
-	0x0604, 0x0c08, 0x2120, 0x4022, 0xf880, 0x0018, 0x300b, 0xa201,
-	0x0014, 0xa200, 0x0014, 0xa200, 0x0214, 0xa202, 0x8838, 0x3806,
-	0x8839, 0x20c3, 0x0864, 0xa82e, 0x28c1, 0x9cb1, 0xa203, 0x300c,
-	0x2846, 0x8161, 0x846a, 0x8300, 0x1856, 0x883a, 0xa804, 0x28f2,
-	0x9c90, 0xa8f4, 0x300c, 0x28e1, 0x9c90, 0x2802, 0xa206, 0x64c3,
-	0x282d, 0xa207, 0x64a0, 0x67a0, 0x6fc0, 0x1814, 0x883b, 0x7824,
-	0x68c1, 0x7864, 0x883e, 0xa802, 0x8576, 0x8677, 0x206b, 0x28c1,
-	0x9cb1, 0x2044, 0x2103, 0x20a2, 0x2081, 0xa8e5, 0xa209, 0x2901,
-	0xa809, 0x0014, 0xa205, 0xa300, 0x1872, 0x879a, 0x883c, 0x1fe2,
-	0xc601, 0xa20a, 0x856e, 0x0704, 0x9c90, 0x0014, 0xa204, 0xa300,
-	0x3009, 0x19e2, 0xf868, 0x8176, 0x86eb, 0x85eb, 0x872e, 0x87a9,
-	0x883f, 0x08e6, 0xa8f3, 0xf881, 0xa8ec, 0xc801, 0x0014, 0xf8c1,
-	0x0016, 0x85b2, 0x80f0, 0x9532, 0xfb02, 0x1de2, 0x0014, 0x8532,
-	0xf241, 0x0014, 0x1de2, 0x84a8, 0xd7a0, 0x1fe6, 0x0014, 0xa208,
-	0x6043, 0x8008, 0x1dc1, 0x0016, 0x8300, 0x8160, 0x842a, 0xf041,
-	0x3008, 0x84a8, 0x11d6, 0x7042, 0x20dd, 0x0011, 0x20d5, 0x8822,
-	0x0016, 0x8000, 0x2847, 0x1011, 0xa8fc, 0x8000, 0xa000, 0x2802,
-	0x1011, 0xa8fd, 0xa898, 0x283e, 0x1011, 0xa8fd, 0xa20b, 0x0017,
-	0x300c, 0xa300, 0x1de2, 0xdb81, 0x0014, 0x0210, 0xa801, 0x0014,
-	0x26e0, 0x873a, 0xfb02, 0x19f2, 0x1fe2, 0x0014, 0xa20d, 0x3806,
-	0x0210, 0x9cb6, 0x0704, 0x0017, 0x60ff, 0x300c, 0x8720, 0xa211,
-	0x9d6b, 0x8772, 0x8837, 0x2101, 0xa821, 0x10d2, 0x78e2, 0x9d6e,
-	0xa8fc, 0xd984, 0xf0e2, 0xf0a1, 0xa871, 0x0014, 0x8831, 0xd166,
-	0x8830, 0x800f, 0x9401, 0xb520, 0xc802, 0x8820, 0xa80f, 0x2301,
-	0xa80d, 0x10d2, 0x78e4, 0x9d6e, 0x8821, 0x8820, 0xa8e6, 0xf123,
-	0xf142, 0xf101, 0xa854, 0x10d2, 0x70f6, 0x8832, 0x8203, 0x870c,
-	0xd99e, 0x6001, 0x0014, 0x6845, 0x0214, 0xa21b, 0x9d6b, 0x2001,
-	0xa845, 0x8201, 0x1852, 0xd184, 0xd163, 0x8834, 0x8001, 0xa801,
-	0x3027, 0x84a8, 0x1a56, 0x8833, 0x0014, 0xa218, 0x6981, 0x9d57,
-	0x692a, 0x6902, 0x1834, 0xa805, 0x1a14, 0x8010, 0x8592, 0x8026,
-	0x84b9, 0x7021, 0x0014, 0xa300, 0x69e1, 0x9d40, 0x694c, 0xa213,
-	0x9d50, 0x1462, 0xa213, 0x8000, 0x16e1, 0xa80a, 0x8023, 0x16e1,
-	0x8001, 0x10f1, 0x0016, 0x6968, 0xa214, 0x9d50, 0x8004, 0x16e1,
-	0x0101, 0x300a, 0x8827, 0x0014, 0x9d50, 0x0014, 0x61c2, 0x8002,
-	0x14e1, 0x0016, 0xa217, 0x9d57, 0x0014, 0xa300, 0x8181, 0x842a,
-	0x84a8, 0x1ce6, 0x882c, 0x0016, 0xa212, 0x9d6b, 0x10d2, 0x70e4,
-	0x0004, 0x8007, 0x9424, 0xcc1a, 0x9d6e, 0xa8f8, 0x8827, 0x300a,
-	0x0013, 0x8000, 0x84a4, 0x0016, 0x11c2, 0x211e, 0x870e, 0xa21d,
-	0x0014, 0x878e, 0x0016, 0xa21c, 0x1035, 0xa8af, 0xa210, 0x3807,
-	0x300c, 0x817e, 0x872b, 0x8772, 0xa8a8, 0x0000, 0xdf21
+	0x6814, 0x8007, 0x7882, 0x0078, 0x3960, 0x6818, 0xa084, 0x8000,
+	0x0040, 0x3234, 0x681b, 0x0008, 0x781b, 0x00c0, 0x0078, 0x24fa,
+	0x2300, 0x0079, 0x323b, 0x3240, 0x32d4, 0x323e, 0x1078, 0x248c,
+	0x7000, 0xa084, 0x0007, 0x0079, 0x3245, 0x2523, 0x324f, 0x3284,
+	0x325a, 0x324d, 0x2523, 0x324d, 0x324d, 0x1078, 0x248c, 0x681c,
+	0xa084, 0x2000, 0x0040, 0x3268, 0x6008, 0xa085, 0x0002, 0x600a,
+	0x0078, 0x3268, 0x68c0, 0xa005, 0x00c0, 0x3284, 0x6920, 0xa18d,
+	0x0001, 0x6922, 0x68c3, 0x0001, 0x6800, 0x706a, 0x0078, 0x327e,
+	0x6920, 0xa18d, 0x0001, 0x6922, 0x6800, 0x6006, 0xa005, 0x00c0,
+	0x3272, 0x6002, 0x681c, 0xa084, 0x000e, 0x0040, 0x327e, 0x7014,
+	0x68ba, 0x7130, 0xa188, 0x7500, 0x0078, 0x3280, 0x2009, 0x7600,
+	0x2104, 0x6802, 0x2d0a, 0x7162, 0x6eb6, 0xa684, 0x0060, 0x0040,
+	0x32d2, 0xa684, 0x0800, 0x00c0, 0x3298, 0xa684, 0x7fff, 0x68b6,
+	0x6894, 0x68a6, 0x6898, 0x68aa, 0x1078, 0x4887, 0x0078, 0x32d2,
+	0xa684, 0x0020, 0x0040, 0x32ad, 0x68c0, 0xa005, 0x0040, 0x32a4,
+	0x1078, 0x4c89, 0x0078, 0x32a7, 0xa006, 0x1078, 0x4c41, 0x79d8,
+	0x7adc, 0x69aa, 0x6aa6, 0x0078, 0x32b3, 0x1078, 0x38ca, 0x69aa,
+	0x6aa6, 0x1078, 0x4c41, 0xa684, 0x8000, 0x0040, 0x32d2, 0xa684,
+	0x7fff, 0x68b6, 0x7adc, 0x79d8, 0xa684, 0x0020, 0x00c0, 0x32ca,
+	0x78d0, 0x801b, 0x00c8, 0x32c5, 0x8000, 0xa084, 0x003f, 0xa108,
+	0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200,
+	0xa303, 0x68ae, 0x0078, 0x2523, 0x0078, 0x377b, 0x7037, 0x0000,
+	0xa282, 0x0006, 0x0050, 0x32de, 0x1078, 0x248c, 0x7000, 0xa084,
+	0x0007, 0x10c0, 0x3a8c, 0x2300, 0x0079, 0x32e6, 0x32e9, 0x3312,
+	0x3326, 0x2200, 0x0079, 0x32ec, 0x3310, 0x377b, 0x32f2, 0x3310,
+	0x3342, 0x3384, 0x7003, 0x0005, 0x2001, 0x7710, 0x2068, 0x704a,
+	0x157e, 0x20a9, 0x0031, 0x2003, 0x0000, 0x8000, 0x0070, 0x3302,
+	0x0078, 0x32fb, 0x157f, 0xad80, 0x0009, 0x7036, 0x6817, 0x0000,
+	0x68b7, 0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x0078, 0x376b,
+	0x1078, 0x248c, 0x7003, 0x0005, 0x2001, 0x7710, 0x2068, 0x704a,
+	0xad80, 0x0009, 0x7036, 0x2200, 0x0079, 0x331e, 0x377b, 0x3324,
+	0x3324, 0x3342, 0x3324, 0x377b, 0x1078, 0x248c, 0x7003, 0x0005,
+	0x2001, 0x7710, 0x2068, 0x704a, 0xad80, 0x0009, 0x7036, 0x2200,
+	0x0079, 0x3332, 0x333a, 0x3338, 0x3338, 0x333a, 0x3338, 0x333a,
+	0x1078, 0x248c, 0x1078, 0x379f, 0x782b, 0x3008, 0x781b, 0x0065,
+	0x0078, 0x24fa, 0x7003, 0x0002, 0x7a80, 0xa294, 0x0f00, 0x789b,
+	0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215, 0x2069, 0x7600, 0x2d04,
+	0x2d08, 0x7162, 0x2068, 0xa005, 0x0040, 0x335d, 0x6814, 0xa206,
+	0x0040, 0x3379, 0x6800, 0x0078, 0x3350, 0x7003, 0x0005, 0x2001,
+	0x7710, 0x2068, 0x704a, 0x7036, 0x157e, 0x20a9, 0x0031, 0x2003,
+	0x0000, 0x8000, 0x0070, 0x336e, 0x0078, 0x3367, 0x157f, 0xad80,
+	0x0009, 0x7036, 0x6a16, 0x68b7, 0x0700, 0x6823, 0x0800, 0x6827,
+	0x0003, 0x6eb4, 0x7e5a, 0x6820, 0xa084, 0x0c00, 0x0040, 0x33d3,
+	0x1078, 0x3797, 0x0078, 0x33d3, 0x7003, 0x0002, 0x7a80, 0xa294,
+	0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215, 0x79a8,
+	0x79a8, 0xa18c, 0x00ff, 0xa1e8, 0x7500, 0x2d04, 0x2d08, 0x7162,
+	0x2068, 0xa005, 0x0040, 0x33a3, 0x6814, 0xa206, 0x0040, 0x33be,
+	0x6800, 0x0078, 0x3396, 0x7003, 0x0005, 0x2001, 0x7710, 0x2068,
+	0x704a, 0x157e, 0x20a9, 0x0031, 0x2003, 0x0000, 0x8000, 0x0070,
+	0x33b3, 0x0078, 0x33ac, 0x157f, 0xad80, 0x0009, 0x7036, 0x6a16,
+	0x68b7, 0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x6eb4, 0x7e5a,
+	0x6820, 0xa084, 0x0c00, 0x0040, 0x33d3, 0xa084, 0x0800, 0x0040,
+	0x33cd, 0x1078, 0x379b, 0x0078, 0x33d3, 0x1078, 0x3797, 0x708b,
+	0x0000, 0x0078, 0x33d3, 0x027e, 0x8207, 0xa084, 0x000f, 0x8003,
+	0x8003, 0x8003, 0xa080, 0x5480, 0x2060, 0x7056, 0x6000, 0x705a,
+	0x6004, 0x705e, 0xa684, 0x0060, 0x0040, 0x342b, 0x6b98, 0x6c94,
+	0x69ac, 0x68b0, 0xa105, 0x00c0, 0x340d, 0x7bd2, 0x7bda, 0x7cd6,
+	0x7cde, 0xa6b4, 0xb7ff, 0x7e5a, 0xa684, 0x0060, 0xa086, 0x0060,
+	0x0040, 0x342b, 0x68c0, 0xa005, 0x0040, 0x3406, 0x7003, 0x0003,
+	0x682b, 0x0000, 0x1078, 0x4b3a, 0x0078, 0x3408, 0x1078, 0x4b4b,
+	0xa6b5, 0x2000, 0x7e5a, 0x0078, 0x342b, 0x68b0, 0xa31a, 0x2100,
+	0xa423, 0x2400, 0xa305, 0x0040, 0x342b, 0x7bd2, 0x7bda, 0x7cd6,
+	0x7cde, 0x68b0, 0xa6b4, 0xbfff, 0x7e5a, 0x007e, 0x68c0, 0xa005,
+	0x007f, 0x0040, 0x3429, 0x7003, 0x0003, 0x1078, 0x4b3a, 0x0078,
+	0x342b, 0x1078, 0x4b96, 0x077f, 0x1078, 0x38bd, 0x2009, 0x0065,
+	0xa684, 0x0004, 0x0040, 0x344c, 0x78e4, 0xa084, 0x0030, 0x0040,
+	0x3444, 0x78ec, 0xa084, 0x0003, 0x0040, 0x3444, 0x782b, 0x3008,
+	0x2009, 0x0065, 0x0078, 0x344c, 0x0f7e, 0x2079, 0x5200, 0x1078,
+	0x4887, 0x0f7f, 0x0040, 0x2523, 0x791a, 0x2d00, 0x704a, 0x8207,
+	0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x5480, 0x2048,
+	0x0078, 0x24fa, 0x6020, 0xa005, 0x0040, 0x3466, 0x8001, 0x6022,
+	0x6008, 0xa085, 0x0008, 0x600a, 0x7010, 0x6026, 0x007c, 0xa006,
+	0x1078, 0x4887, 0x6817, 0x0000, 0x681b, 0x0001, 0x6823, 0x0040,
+	0x681f, 0x0100, 0x7000, 0xa084, 0x0007, 0x0079, 0x3477, 0x2523,
+	0x3481, 0x3481, 0x349e, 0x3489, 0x3487, 0x3489, 0x347f, 0x1078,
+	0x248c, 0x1078, 0x34a9, 0x1078, 0x34a2, 0x1078, 0x1cdc, 0x0078,
+	0x2523, 0x706c, 0x706f, 0x0000, 0x7093, 0x0000, 0x0079, 0x3490,
+	0x349a, 0x349a, 0x3498, 0x3498, 0x3498, 0x349a, 0x3498, 0x349a,
+	0x0079, 0x2902, 0x706f, 0x0000, 0x0078, 0x2523, 0x681b, 0x0000,
+	0x0078, 0x2fb6, 0x6800, 0xa005, 0x00c0, 0x34a7, 0x6002, 0x6006,
+	0x007c, 0x6010, 0xa005, 0x0040, 0x34b2, 0x8001, 0x00d0, 0x34b2,
+	0x1078, 0x248c, 0x6012, 0x6008, 0xa084, 0xffef, 0x600a, 0x007c,
+	0x6018, 0xa005, 0x0040, 0x34be, 0x8001, 0x601a, 0x007c, 0x1078,
+	0x39e0, 0x681b, 0x0018, 0x0078, 0x34f5, 0x1078, 0x39e0, 0x681b,
+	0x0019, 0x0078, 0x34f5, 0x1078, 0x39e0, 0x681b, 0x001a, 0x0078,
+	0x34f5, 0x1078, 0x39e0, 0x681b, 0x0003, 0x0078, 0x34f5, 0x7780,
+	0x1078, 0x38bd, 0x7184, 0xa18c, 0x00ff, 0xa1e8, 0x7500, 0x2d04,
+	0x2d08, 0x2068, 0xa005, 0x00c0, 0x34e7, 0x0078, 0x2523, 0x6814,
+	0x7280, 0xa206, 0x0040, 0x34ef, 0x6800, 0x0078, 0x34e0, 0x6800,
+	0x200a, 0x681b, 0x0005, 0x708b, 0x0000, 0x1078, 0x34a9, 0x6820,
+	0xa084, 0x0001, 0x00c0, 0x34fe, 0x1078, 0x34a2, 0x1078, 0x34b8,
+	0x681f, 0x0000, 0x6823, 0x0020, 0x1078, 0x1cdc, 0x0078, 0x2523,
+	0xa282, 0x0003, 0x00c0, 0x376b, 0x7da8, 0xa5ac, 0x00ff, 0x7ca8,
+	0xa4a4, 0x00ff, 0x6920, 0xa18d, 0x0080, 0x6922, 0xa184, 0x0100,
+	0x0040, 0x356c, 0xa18c, 0xfeff, 0x6922, 0xa4a4, 0x00ff, 0x0040,
+	0x3556, 0xa482, 0x000c, 0x0048, 0x3529, 0x0040, 0x3529, 0x2021,
+	0x000c, 0x852b, 0x852b, 0x1078, 0x382e, 0x0040, 0x3533, 0x1078,
+	0x3627, 0x0078, 0x355f, 0x1078, 0x37e9, 0x0c7e, 0x2960, 0x6004,
+	0xa084, 0xfff5, 0x6006, 0x1078, 0x3652, 0x0c7f, 0x6920, 0xa18d,
+	0x0100, 0x6922, 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400,
+	0x00c0, 0x3550, 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x24fa,
+	0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x24fa, 0x0c7e, 0x2960,
+	0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, 0x3652, 0x0c7f, 0x7e58,
+	0xa684, 0x0400, 0x00c0, 0x3568, 0x781b, 0x0058, 0x0078, 0x24fa,
+	0x781b, 0x0065, 0x0078, 0x24fa, 0x0c7e, 0x7054, 0x2060, 0x6100,
+	0xa18c, 0x1000, 0x0040, 0x35ac, 0x6208, 0x8217, 0xa294, 0x00ff,
+	0xa282, 0x000c, 0x0048, 0x3580, 0x0040, 0x3580, 0x2011, 0x000c,
+	0x2400, 0xa202, 0x00c8, 0x3585, 0x2220, 0x6208, 0xa294, 0x00ff,
+	0x7018, 0xa086, 0x0028, 0x00c0, 0x3595, 0xa282, 0x0019, 0x00c8,
+	0x359b, 0x2011, 0x0019, 0x0078, 0x359b, 0xa282, 0x000c, 0x00c8,
+	0x359b, 0x2011, 0x000c, 0x2200, 0xa502, 0x00c8, 0x35a0, 0x2228,
+	0x1078, 0x37ed, 0x852b, 0x852b, 0x1078, 0x382e, 0x0040, 0x35ac,
+	0x1078, 0x3627, 0x0078, 0x35b0, 0x1078, 0x37e9, 0x1078, 0x3652,
+	0x7858, 0xa085, 0x0004, 0x785a, 0x0c7f, 0x782b, 0x3008, 0x781b,
+	0x0065, 0x0078, 0x24fa, 0x0c7e, 0x2960, 0x6000, 0xd0e4, 0x00c0,
+	0x35d5, 0xd0b4, 0x00c0, 0x35cf, 0x6010, 0xa084, 0x000f, 0x00c0,
+	0x35cf, 0x6104, 0xa18c, 0xfff5, 0x6106, 0x0c7f, 0x007c, 0x2011,
+	0x0032, 0x2019, 0x0000, 0x0078, 0x35fc, 0x68a0, 0xa084, 0x0200,
+	0x00c0, 0x35cf, 0x6208, 0xa294, 0x00ff, 0x7018, 0xa086, 0x0028,
+	0x00c0, 0x35ea, 0xa282, 0x0019, 0x00c8, 0x35f0, 0x2011, 0x0019,
+	0x0078, 0x35f0, 0xa282, 0x000c, 0x00c8, 0x35f0, 0x2011, 0x000c,
+	0x6308, 0x831f, 0xa39c, 0x00ff, 0xa382, 0x000c, 0x0048, 0x35fc,
+	0x0040, 0x35fc, 0x2019, 0x000c, 0x78ab, 0x0001, 0x78ab, 0x0003,
+	0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xa085,
+	0x0100, 0x6822, 0x0c7f, 0x007c, 0x0c7e, 0x2960, 0xa18c, 0xfff5,
+	0x6106, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078, 0x3617, 0x78ab,
+	0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0,
+	0x0005, 0x6820, 0xa085, 0x0100, 0x6822, 0x0c7f, 0x007c, 0x0c7e,
+	0x7154, 0x2160, 0x1078, 0x362e, 0x0c7f, 0x007c, 0x2008, 0xa084,
+	0xfff0, 0xa425, 0x7c86, 0x6018, 0x789a, 0x7cae, 0x6412, 0x78a4,
+	0xa084, 0xfff8, 0xa18c, 0x0007, 0xa105, 0x78a6, 0x6016, 0x788a,
+	0xa4a4, 0x000f, 0x8427, 0x8204, 0x8004, 0xa084, 0x00ff, 0xa405,
+	0x600e, 0x78ec, 0xd08c, 0x00c0, 0x3651, 0x6004, 0xa084, 0xfff5,
+	0x6006, 0x007c, 0x0c7e, 0x7054, 0x2060, 0x1078, 0x3659, 0x0c7f,
+	0x007c, 0x6018, 0x789a, 0x78a4, 0xa084, 0xfff0, 0x78a6, 0x6012,
+	0x7884, 0xa084, 0xfff0, 0x7886, 0x007c, 0xa282, 0x0002, 0x00c0,
+	0x376b, 0x7aa8, 0x6920, 0xa18d, 0x0080, 0x6922, 0xa184, 0x0200,
+	0x0040, 0x36ae, 0xa18c, 0xfdff, 0x6922, 0xa294, 0x00ff, 0xa282,
+	0x0002, 0x00c8, 0x376b, 0x1078, 0x36f9, 0x1078, 0x3652, 0xa980,
+	0x0001, 0x200c, 0x1078, 0x38b9, 0x1078, 0x35bb, 0x88ff, 0x0040,
+	0x36a1, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xa6b5, 0x0004,
+	0x7e5a, 0xa684, 0x0400, 0x00c0, 0x369b, 0x782b, 0x3008, 0x781b,
+	0x0056, 0x0078, 0x24fa, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078,
+	0x24fa, 0x7e58, 0xa684, 0x0400, 0x00c0, 0x36aa, 0x781b, 0x0058,
+	0x0078, 0x24fa, 0x781b, 0x0065, 0x0078, 0x24fa, 0xa282, 0x0002,
+	0x00c8, 0x36b6, 0xa284, 0x0001, 0x0040, 0x36c0, 0x7154, 0xa188,
+	0x0000, 0x210c, 0xa18c, 0x2000, 0x00c0, 0x36c0, 0x2011, 0x0000,
+	0x1078, 0x37db, 0x1078, 0x36f9, 0x1078, 0x3652, 0x7858, 0xa085,
+	0x0004, 0x785a, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x24fa,
+	0x0c7e, 0x027e, 0x2960, 0x6000, 0x2011, 0x0001, 0xd0ec, 0x00c0,
+	0x36e9, 0xd0bc, 0x00c0, 0x36e7, 0x6014, 0xa084, 0x0040, 0x00c0,
+	0x36e7, 0xa18c, 0xffef, 0x6106, 0xa006, 0x0078, 0x36f6, 0x2011,
+	0x0000, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa,
+	0xa8c0, 0x0004, 0x6820, 0xa085, 0x0200, 0x6822, 0x027f, 0x0c7f,
+	0x007c, 0x0c7e, 0x7054, 0x2060, 0x1078, 0x3700, 0x0c7f, 0x007c,
+	0x82ff, 0x0040, 0x3705, 0x2011, 0x0040, 0x6018, 0xa080, 0x0002,
+	0x789a, 0x78a4, 0xa084, 0xffbf, 0xa205, 0x78a6, 0x788a, 0x6016,
+	0x78ec, 0xd08c, 0x00c0, 0x3718, 0x6004, 0xa084, 0xffef, 0x6006,
+	0x007c, 0x007e, 0x7000, 0xa086, 0x0003, 0x0040, 0x3722, 0x007f,
+	0x0078, 0x3725, 0x007f, 0x0078, 0x3767, 0xa684, 0x0020, 0x0040,
+	0x3767, 0x7888, 0xa084, 0x0040, 0x0040, 0x3767, 0x7bb8, 0xa384,
+	0x003f, 0x831b, 0x00c8, 0x3735, 0x8000, 0xa005, 0x0040, 0x374b,
+	0x831b, 0x00c8, 0x373e, 0x8001, 0x0040, 0x3763, 0xa684, 0x4000,
+	0x0040, 0x374b, 0x78b8, 0x801b, 0x00c8, 0x3747, 0x8000, 0xa084,
+	0x003f, 0x00c0, 0x3763, 0xa6b4, 0xbfff, 0x7e5a, 0x79d8, 0x7adc,
+	0x2001, 0x0001, 0xa108, 0x00c8, 0x3757, 0xa291, 0x0000, 0x79d2,
+	0x79da, 0x7ad6, 0x7ade, 0x1078, 0x4c41, 0x781b, 0x0064, 0x1078,
+	0x4ac6, 0x0078, 0x24fa, 0x781b, 0x0064, 0x0078, 0x24fa, 0x781b,
+	0x0065, 0x0078, 0x24fa, 0x1078, 0x37a3, 0x782b, 0x3008, 0x781b,
+	0x0065, 0x0078, 0x24fa, 0x1078, 0x378f, 0x782b, 0x3008, 0x781b,
+	0x0065, 0x0078, 0x24fa, 0x6827, 0x0002, 0x1078, 0x3797, 0x78e4,
+	0xa084, 0x0030, 0x0040, 0x2523, 0x78ec, 0xa084, 0x0003, 0x0040,
+	0x2523, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x24fa, 0x2001,
+	0x0005, 0x0078, 0x37a5, 0x2001, 0x000c, 0x0078, 0x37a5, 0x2001,
+	0x0006, 0x0078, 0x37a5, 0x2001, 0x000d, 0x0078, 0x37a5, 0x2001,
+	0x0009, 0x0078, 0x37a5, 0x2001, 0x0007, 0x789b, 0x0010, 0x78aa,
+	0x789b, 0x0060, 0x78ab, 0x0001, 0xa6b5, 0x0004, 0x7e5a, 0x007c,
+	0x077e, 0x873f, 0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703, 0xa0e0,
+	0x5480, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184, 0x000f, 0x0040,
+	0x37c9, 0xa184, 0xfff0, 0x78a6, 0x6012, 0x6004, 0xa085, 0x0008,
+	0x6006, 0x8738, 0x8738, 0x7f9a, 0x79a4, 0xa184, 0x0040, 0x0040,
+	0x37d9, 0xa184, 0xffbf, 0x78a6, 0x6016, 0x6004, 0xa085, 0x0010,
+	0x6006, 0x077f, 0x007c, 0x789b, 0x0010, 0x78ab, 0x0001, 0x78ab,
+	0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060, 0x78ab, 0x0004,
+	0x007c, 0x2021, 0x0000, 0x2029, 0x0032, 0x789b, 0x0010, 0x78ab,
+	0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa, 0x7caa, 0x789b,
+	0x0060, 0x78ab, 0x0005, 0x007c, 0x157e, 0x8007, 0xa084, 0x00ff,
+	0x8003, 0x8003, 0xa080, 0x0020, 0x789a, 0x79a4, 0xa18c, 0xfff0,
+	0x2001, 0x5246, 0x2004, 0xa082, 0x0028, 0x0040, 0x3817, 0x2021,
+	0x38a0, 0x2019, 0x0014, 0x20a9, 0x000c, 0x0078, 0x381d, 0x2021,
+	0x38ac, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011, 0x0064, 0x2404,
+	0xa084, 0xfff0, 0xa106, 0x0040, 0x382c, 0x8420, 0x2300, 0xa210,
+	0x0070, 0x382c, 0x0078, 0x381f, 0x157f, 0x007c, 0x157e, 0x2009,
+	0x5246, 0x210c, 0xa182, 0x0032, 0x0048, 0x3842, 0x0040, 0x3846,
+	0x2009, 0x3892, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011, 0x0032,
+	0x0078, 0x3858, 0xa182, 0x0028, 0x0040, 0x3850, 0x2009, 0x38a0,
+	0x2019, 0x0014, 0x20a9, 0x000c, 0x2011, 0x0064, 0x0078, 0x3858,
+	0x2009, 0x38ac, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011, 0x0064,
+	0x2200, 0xa502, 0x0040, 0x3868, 0x0048, 0x3868, 0x8108, 0x2300,
+	0xa210, 0x0070, 0x3865, 0x0078, 0x3858, 0x157f, 0xa006, 0x007c,
+	0x157f, 0xa582, 0x0064, 0x00c8, 0x3877, 0x7808, 0xa085, 0x0070,
+	0x780a, 0x7044, 0xa085, 0x0070, 0x7046, 0x0078, 0x3877, 0x78ec,
+	0xa084, 0x0300, 0x0040, 0x387f, 0x2104, 0x0078, 0x3890, 0x2104,
+	0xa09e, 0x1102, 0x00c0, 0x3890, 0x2001, 0x04fd, 0x2004, 0xa082,
+	0x0005, 0x0048, 0x388f, 0x2001, 0x1201, 0x0078, 0x3890, 0x2104,
+	0xa005, 0x007c, 0x1102, 0x3002, 0x3202, 0x4203, 0x4403, 0x5404,
+	0x5604, 0x6605, 0x6805, 0x7806, 0x7a06, 0x0c07, 0x0c07, 0x0e07,
+	0x3202, 0x4202, 0x5202, 0x6202, 0x7202, 0x6605, 0x7605, 0x7805,
+	0x7a05, 0x7c05, 0x7e05, 0x7f05, 0x2202, 0x3202, 0x4202, 0x5202,
+	0x5404, 0x6404, 0x7404, 0x7604, 0x7804, 0x7a04, 0x7c04, 0x7e04,
+	0x7f04, 0x789b, 0x0010, 0xa046, 0x007c, 0xa784, 0x0f00, 0x800b,
+	0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa0e0,
+	0x5500, 0x007c, 0x79d8, 0x7adc, 0x78d0, 0x801b, 0x00c8, 0x38d1,
+	0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x007c, 0x0f7e,
+	0x2079, 0x0100, 0x2009, 0x5240, 0x2091, 0x8000, 0x2104, 0x0079,
+	0x38e1, 0x3917, 0x38eb, 0x38eb, 0x38eb, 0x38eb, 0x38eb, 0x38eb,
+	0x391b, 0x1078, 0x248c, 0x784b, 0x0004, 0x7848, 0xa084, 0x0004,
+	0x00c0, 0x38ed, 0x784b, 0x0008, 0x7848, 0xa084, 0x0008, 0x00c0,
+	0x38f4, 0x68b4, 0xa085, 0x4000, 0x68b6, 0x7858, 0xa085, 0x4000,
+	0x785a, 0x7830, 0xa084, 0x0080, 0x00c0, 0x3917, 0x0018, 0x3917,
+	0x681c, 0xa084, 0x0020, 0x00c0, 0x3915, 0x0e7e, 0x2071, 0x5240,
+	0x1078, 0x396a, 0x0e7f, 0x0078, 0x3917, 0x781b, 0x00ca, 0x2091,
+	0x8001, 0x0f7f, 0x007c, 0x70b3, 0x0000, 0x1078, 0x3b44, 0x0078,
+	0x3917, 0x0c7e, 0x6814, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003,
+	0x8003, 0xa0e0, 0x5480, 0x6004, 0xa084, 0x000a, 0x00c0, 0x3954,
+	0x6108, 0xa194, 0xff00, 0x0040, 0x3954, 0xa18c, 0x00ff, 0x2001,
+	0x0019, 0xa106, 0x0040, 0x3943, 0x2001, 0x0032, 0xa106, 0x0040,
+	0x3947, 0x0078, 0x394b, 0x2009, 0x0020, 0x0078, 0x394d, 0x2009,
+	0x003f, 0x0078, 0x394d, 0x2011, 0x0000, 0x2100, 0xa205, 0x600a,
+	0x6004, 0xa085, 0x0002, 0x6006, 0x0c7f, 0x007c, 0x781b, 0x0065,
+	0x0078, 0x24fa, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x24fa,
+	0x781b, 0x0058, 0x0078, 0x24fa, 0x782b, 0x3008, 0x781b, 0x0056,
+	0x0078, 0x24fa, 0x2009, 0x5220, 0x210c, 0xa186, 0x0000, 0x0040,
+	0x397e, 0xa186, 0x0001, 0x0040, 0x3981, 0x2009, 0x5238, 0x200b,
+	0x000b, 0x706f, 0x0001, 0x781b, 0x0048, 0x007c, 0x781b, 0x00c4,
+	0x007c, 0x2009, 0x5238, 0x200b, 0x000a, 0x007c, 0x2009, 0x5220,
+	0x210c, 0xa186, 0x0000, 0x0040, 0x39a1, 0xa186, 0x0001, 0x0040,
+	0x399b, 0x2009, 0x5238, 0x200b, 0x000b, 0x706f, 0x0001, 0x781b,
+	0x0048, 0x0078, 0x24fa, 0x2009, 0x5238, 0x200b, 0x000a, 0x0078,
+	0x24fa, 0x782b, 0x3008, 0x781b, 0x00c4, 0x0078, 0x24fa, 0x781b,
+	0x00ca, 0x0078, 0x24fa, 0x782b, 0x3008, 0x781b, 0x00ca, 0x0078,
+	0x24fa, 0x781b, 0x008f, 0x0078, 0x24fa, 0x782b, 0x3008, 0x781b,
+	0x008f, 0x0078, 0x24fa, 0x6818, 0xa084, 0x8000, 0x0040, 0x39c2,
+	0x681b, 0x001d, 0x706f, 0x0001, 0x781b, 0x0048, 0x0078, 0x24fa,
+	0x007e, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x39de, 0x7808, 0xa084,
+	0xfffc, 0x780a, 0x0005, 0x0005, 0x0005, 0x0005, 0x78ec, 0xa084,
+	0x0021, 0x0040, 0x39de, 0x7044, 0x780a, 0xa005, 0x007f, 0x007c,
+	0x7044, 0xa085, 0x0002, 0x7046, 0x780a, 0x007c, 0x007e, 0x7830,
+	0xa084, 0x0040, 0x00c0, 0x39e7, 0x0098, 0x39f2, 0x007f, 0x789a,
+	0x78ac, 0x007c, 0x7808, 0xa084, 0xfffd, 0x780a, 0x0005, 0x0005,
+	0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, 0x0040, 0x3a01, 0x0098,
+	0x39ff, 0x007f, 0x789a, 0x78ac, 0x007e, 0x7044, 0x780a, 0x007f,
+	0x007c, 0x78ec, 0xa084, 0x0002, 0x00c0, 0x4871, 0xa784, 0x007d,
+	0x00c0, 0x3a15, 0x2700, 0x1078, 0x248c, 0xa784, 0x0001, 0x00c0,
+	0x300c, 0xa784, 0x0070, 0x0040, 0x3a25, 0x0c7e, 0x2d60, 0x2f68,
+	0x1078, 0x2437, 0x2d78, 0x2c68, 0x0c7f, 0xa784, 0x0008, 0x0040,
+	0x3a32, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x2523,
+	0x0078, 0x3956, 0xa784, 0x0004, 0x0040, 0x3a65, 0x78b8, 0xa084,
+	0x4001, 0x0040, 0x3a65, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003,
+	0x0040, 0x2523, 0x78e4, 0xa084, 0x0007, 0xa086, 0x0001, 0x00c0,
+	0x3a65, 0x78c0, 0xa085, 0x4800, 0x2030, 0x7e5a, 0x781b, 0x00ca,
+	0x0078, 0x24fa, 0x784b, 0x0008, 0x6818, 0xa084, 0x8000, 0x0040,
+	0x3a61, 0x681b, 0x0015, 0xa684, 0x4000, 0x0040, 0x3a61, 0x681b,
+	0x0007, 0x1078, 0x396a, 0x0078, 0x24fa, 0x681b, 0x0003, 0x7858,
+	0xa084, 0x3f00, 0x681e, 0x682f, 0x0000, 0x6833, 0x0000, 0x784b,
+	0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x2a06, 0x0018, 0x24fa,
+	0x0078, 0x3773, 0x6b14, 0x8307, 0xa084, 0x000f, 0x8003, 0x8003,
+	0x8003, 0xa080, 0x5480, 0x2060, 0x2048, 0x7056, 0x6000, 0x705a,
+	0x6004, 0x705e, 0x2a60, 0x007c, 0x0079, 0x3a8e, 0x3a96, 0x3a97,
+	0x3a96, 0x3a99, 0x3a96, 0x3a96, 0x3a96, 0x3a9e, 0x007c, 0x1078,
+	0x34b8, 0x1078, 0x4887, 0x7038, 0x600a, 0x007c, 0x70a0, 0xa005,
+	0x0040, 0x3aab, 0x2068, 0x1078, 0x1bd3, 0x1078, 0x47fe, 0x1078,
+	0x4805, 0x70a3, 0x0000, 0x007c, 0x0e7e, 0x2091, 0x8000, 0x2071,
+	0x5240, 0x7000, 0xa086, 0x0007, 0x00c0, 0x3ac2, 0x6110, 0x70bc,
+	0xa106, 0x00c0, 0x3ac2, 0x0e7f, 0x1078, 0x1be0, 0x1078, 0x3ac8,
+	0xa006, 0x007c, 0x2091, 0x8001, 0x0e7f, 0xa085, 0x0001, 0x007c,
+	0x0f7e, 0x0e7e, 0x2071, 0x5240, 0x0078, 0x2297, 0x785b, 0x0000,
+	0x70af, 0x000e, 0x2009, 0x0100, 0x017e, 0x70a0, 0xa06d, 0x0040,
+	0x3add, 0x70a3, 0x0000, 0x0078, 0x3ae3, 0x70b3, 0x0000, 0x1078,
+	0x1c0c, 0x0040, 0x3ae9, 0x70ac, 0x6826, 0x1078, 0x3bc6, 0x0078,
+	0x3add, 0x017f, 0x157e, 0x0c7e, 0x0d7e, 0x20a9, 0x0008, 0x2061,
+	0x7610, 0x6000, 0xa105, 0x6002, 0x601c, 0xa06d, 0x0040, 0x3b01,
+	0x6800, 0x601e, 0x1078, 0x19ac, 0x6008, 0x8000, 0x600a, 0x0078,
+	0x3af4, 0x6018, 0xa06d, 0x0040, 0x3b0b, 0x6800, 0x601a, 0x1078,
+	0x19ac, 0x0078, 0x3b01, 0xace0, 0x0008, 0x0070, 0x3b11, 0x0078,
+	0x3af1, 0x709c, 0xa084, 0x8000, 0x0040, 0x3b18, 0x1078, 0x3c44,
+	0x0d7f, 0x0c7f, 0x157f, 0x007c, 0x127e, 0x2091, 0x2300, 0x6804,
+	0xa084, 0x000f, 0x0079, 0x3b24, 0x3b34, 0x3b34, 0x3b34, 0x3b34,
+	0x3b34, 0x3b34, 0x3b36, 0x3b3c, 0x3b34, 0x3b34, 0x3b34, 0x3b34,
+	0x3b34, 0x3b3e, 0x3b34, 0x3b36, 0x1078, 0x248c, 0x1078, 0x45d3,
+	0x1078, 0x19ac, 0x0078, 0x3b42, 0x6827, 0x000b, 0x1078, 0x45d3,
+	0x1078, 0x3bc6, 0x127f, 0x007c, 0x127e, 0x2091, 0x2300, 0x0098,
+	0x3b60, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x3b60, 0x0d7e, 0x1078,
+	0x4812, 0x2d00, 0x682e, 0x2009, 0x0004, 0x2001, 0x0000, 0x6827,
+	0x0084, 0x1078, 0x47c7, 0x1078, 0x3bc6, 0x0d7f, 0x0078, 0x3b94,
+	0x7948, 0xa185, 0x4000, 0x784a, 0x0098, 0x3b69, 0x794a, 0x0078,
+	0x3b4e, 0x7828, 0xa086, 0x1834, 0x00c0, 0x3b72, 0xa185, 0x0004,
+	0x0078, 0x3b79, 0x7828, 0xa086, 0x1814, 0x00c0, 0x3b66, 0xa185,
+	0x000c, 0x784a, 0x789b, 0x000e, 0x78ab, 0x0002, 0x7858, 0xa084,
+	0x00ff, 0xa085, 0x0400, 0x785a, 0x70b4, 0xa080, 0x0091, 0x781a,
+	0x6827, 0x0284, 0x682c, 0x6836, 0x6830, 0x683a, 0x2009, 0x0004,
+	0x2001, 0x0000, 0x1078, 0x47c7, 0x127f, 0x007c, 0x0d7e, 0x6b14,
+	0x1078, 0x1c70, 0x0040, 0x3ba3, 0x2068, 0x6827, 0x0002, 0x1078,
+	0x3bc6, 0x0078, 0x3b98, 0x0d7f, 0x007c, 0x0d7e, 0x6b14, 0x6c28,
+	0xa4a4, 0x00ff, 0x1078, 0x1c1c, 0x0040, 0x3bb3, 0x2068, 0x6827,
+	0x0002, 0x1078, 0x3bc6, 0x0d7f, 0x007c, 0x0d7e, 0x6b14, 0xa39c,
+	0x00ff, 0x1078, 0x1c48, 0x0040, 0x3bc4, 0x2068, 0x6827, 0x0002,
+	0x1078, 0x3bc6, 0x0078, 0x3bb9, 0x0d7f, 0x007c, 0x0c7e, 0x6914,
+	0x1078, 0x3c3b, 0x6904, 0xa18c, 0x00ff, 0xa186, 0x0006, 0x0040,
+	0x3be1, 0xa186, 0x000d, 0x0040, 0x3c00, 0xa186, 0x0017, 0x00c0,
+	0x3bdd, 0x1078, 0x19ac, 0x0078, 0x3bdf, 0x1078, 0x1cde, 0x0c7f,
+	0x007c, 0x6004, 0x8001, 0x0048, 0x3bfe, 0x6006, 0x2009, 0x0000,
+	0xa684, 0x0001, 0x00c0, 0x3bee, 0xa18d, 0x8000, 0xa684, 0x0004,
+	0x0040, 0x3bf4, 0xa18d, 0x0002, 0x691e, 0x6823, 0x0000, 0x7104,
+	0x810f, 0x6818, 0xa105, 0x681a, 0x0078, 0x3bdd, 0x1078, 0x248c,
+	0x6018, 0xa005, 0x00c0, 0x3c0f, 0x6008, 0x8001, 0x0048, 0x3c0f,
+	0x600a, 0x601c, 0x6802, 0x2d00, 0x601e, 0x0078, 0x3c25, 0xac88,
+	0x0006, 0x2104, 0xa005, 0x0040, 0x3c18, 0x2008, 0x0078, 0x3c11,
+	0x6802, 0x2d0a, 0x6008, 0x8001, 0x0048, 0x3bdf, 0x600a, 0x6018,
+	0x2068, 0x6800, 0x601a, 0x0078, 0x3c09, 0x157e, 0x137e, 0x147e,
+	0x0c7e, 0x0d7e, 0x1078, 0x1989, 0x00c0, 0x3c30, 0x1078, 0x248c,
+	0x2da0, 0x137f, 0x20a9, 0x0031, 0x53a3, 0x0c7f, 0x147f, 0x137f,
+	0x157f, 0x0078, 0x3bdd, 0xa184, 0x001f, 0x8003, 0x8003, 0x8003,
+	0xa080, 0x7610, 0x2060, 0x007c, 0x2019, 0x5251, 0x2304, 0xa085,
+	0x0001, 0x201a, 0x2019, 0x0102, 0x2304, 0xa085, 0x0001, 0x201a,
+	0x007c, 0x2019, 0x5251, 0x2304, 0xa084, 0xfffe, 0x201a, 0x2019,
+	0x0102, 0x2304, 0xa084, 0xfffe, 0x201a, 0x007c, 0x7990, 0xa18c,
+	0xfff8, 0x7992, 0x70b4, 0xa080, 0x00d8, 0x781a, 0x0078, 0x24fa,
+	0x70a3, 0x0000, 0x7003, 0x0000, 0x7043, 0x0001, 0x7037, 0x0000,
+	0x0018, 0x24b1, 0x1078, 0x1c0c, 0x0040, 0x3c99, 0x2009, 0x520f,
+	0x200b, 0x0000, 0x68bc, 0x2060, 0x6100, 0xa184, 0x0300, 0x0040,
+	0x3c8d, 0x6827, 0x000e, 0xa084, 0x0200, 0x0040, 0x3c89, 0x6827,
+	0x0017, 0x1078, 0x3bc6, 0x0078, 0x3c68, 0x7000, 0xa086, 0x0007,
+	0x00c0, 0x3d0d, 0x2d00, 0x70a2, 0xad80, 0x000f, 0x7036, 0x0078,
+	0x3ca0, 0x7040, 0xa086, 0x0001, 0x0040, 0x2533, 0x0078, 0x24fa,
+	0x2031, 0x0000, 0x691c, 0xa184, 0x0002, 0x0040, 0x3ca9, 0xa6b5,
+	0x0004, 0xa184, 0x00c0, 0x8003, 0x8003, 0x8007, 0xa080, 0x3da6,
+	0x2004, 0xa635, 0x6820, 0xa084, 0x0400, 0x0040, 0x3cc1, 0x789b,
+	0x0018, 0x78ab, 0x0003, 0x789b, 0x0081, 0x78ab, 0x0001, 0xa6b5,
+	0x5000, 0x6820, 0xa084, 0x8000, 0x0040, 0x3ccf, 0xa6b5, 0x0400,
+	0x789b, 0x000e, 0x6824, 0x8007, 0x78aa, 0x0078, 0x3cef, 0x681c,
+	0xd0fc, 0x00c0, 0x3cdd, 0xa6b5, 0x0800, 0x6820, 0xd0c4, 0x0040,
+	0x3cef, 0xa6b5, 0x4000, 0x0078, 0x3cef, 0x6820, 0xd0c4, 0x0040,
+	0x3ce5, 0xa6b5, 0x4000, 0x0078, 0x3cef, 0x789b, 0x0018, 0x78ab,
+	0x0002, 0x789b, 0x0081, 0x78ab, 0x0001, 0xa6b5, 0x1000, 0xa684,
+	0x0200, 0x0040, 0x3d09, 0x682c, 0x78d2, 0x6830, 0x78d6, 0xa684,
+	0x0100, 0x0040, 0x3d07, 0x682c, 0xa084, 0x0001, 0x0040, 0x3d07,
+	0x7888, 0xa084, 0x0040, 0x0040, 0x3d07, 0xa6b5, 0x8000, 0x1078,
+	0x47f6, 0x7e5a, 0x6eb6, 0x0078, 0x4835, 0x1078, 0x39c8, 0x00c0,
+	0x3da0, 0x702c, 0x8004, 0x0048, 0x3d1b, 0x2019, 0x4f49, 0x1078,
+	0x2313, 0x702f, 0x0001, 0x2041, 0x0001, 0x2031, 0x1000, 0x789b,
+	0x0018, 0x6814, 0xa084, 0x001f, 0xa085, 0x0080, 0x78aa, 0x691c,
+	0xa184, 0x0002, 0x0040, 0x3d34, 0xa6b5, 0x0004, 0x78ab, 0x0020,
+	0x6828, 0x78aa, 0xa8c0, 0x0002, 0x681c, 0xd0f4, 0x0040, 0x3d3d,
+	0x2c50, 0x1078, 0x3a7a, 0x1078, 0x4702, 0x6820, 0xa084, 0x8000,
+	0x0040, 0x3d4b, 0xa6b5, 0x0400, 0x789b, 0x000e, 0x6824, 0x8007,
+	0x78aa, 0x0078, 0x3d52, 0x681c, 0xa084, 0x8000, 0x00c0, 0x3d52,
+	0xa6b5, 0x0800, 0x6820, 0xa084, 0x0100, 0x0040, 0x3d59, 0xa6b5,
+	0x4000, 0x681c, 0xa084, 0x00c0, 0x8003, 0x8003, 0x8007, 0xa080,
+	0x3da6, 0x2004, 0xa635, 0xa684, 0x0100, 0x0040, 0x3d73, 0x682c,
+	0xa084, 0x0001, 0x0040, 0x3d73, 0x7888, 0xa084, 0x0040, 0x0040,
+	0x3d73, 0xa6b5, 0x8000, 0x789b, 0x007e, 0x7eae, 0x6eb6, 0x6814,
+	0x8007, 0x78aa, 0x7882, 0x2810, 0x7aaa, 0x7830, 0xa084, 0x00c0,
+	0x00c0, 0x3da0, 0x0018, 0x3da0, 0x70b4, 0xa080, 0x00dd, 0x781a,
+	0x1078, 0x39e0, 0xa684, 0x0200, 0x0040, 0x3d94, 0x682c, 0x78d2,
+	0x6830, 0x78d6, 0x1078, 0x47f6, 0x2d00, 0x70a2, 0x704a, 0x6810,
+	0x70be, 0x7003, 0x0007, 0xad80, 0x000f, 0x7036, 0x0078, 0x24fa,
+	0x1078, 0x1bd3, 0x1078, 0x39e0, 0x0078, 0x24fa, 0x0000, 0x0300,
+	0x0200, 0x0000, 0x1078, 0x248c, 0x2300, 0x0079, 0x3daf, 0x3db2,
+	0x3db2, 0x3db4, 0x1078, 0x248c, 0x1078, 0x4805, 0x6924, 0xa184,
+	0x00ff, 0xa086, 0x000a, 0x0040, 0x3dc6, 0xa184, 0xff00, 0xa085,
+	0x000a, 0x6826, 0x1078, 0x1bd3, 0x0078, 0x3c68, 0x2001, 0x000a,
+	0x1078, 0x4797, 0x0078, 0x3c68, 0xa282, 0x0005, 0x0050, 0x3dd2,
+	0x1078, 0x248c, 0x7000, 0xa084, 0x0007, 0x10c0, 0x3a8c, 0x1078,
+	0x1989, 0x00c0, 0x3df4, 0x2069, 0xffff, 0xa684, 0x0004, 0x0040,
+	0x3de5, 0x2001, 0x2800, 0x0078, 0x3de7, 0x2001, 0x0800, 0x71b4,
+	0xa188, 0x0091, 0x789b, 0x000e, 0x8007, 0x78aa, 0x2031, 0x0400,
+	0x7e5a, 0x791a, 0x0078, 0x24fa, 0x6807, 0x0106, 0x680b, 0x0000,
+	0x689f, 0x0000, 0x6827, 0x0000, 0xa386, 0x0002, 0x00c0, 0x3e15,
+	0xa286, 0x0002, 0x00c0, 0x3e15, 0x78a0, 0xa005, 0x00c0, 0x3e15,
+	0xa484, 0x8000, 0x00c0, 0x3e15, 0x78e4, 0xa084, 0x0008, 0x0040,
+	0x3e15, 0xa6b5, 0x0008, 0x2019, 0x0000, 0x1078, 0x4217, 0x2d00,
+	0x70a2, 0x704a, 0x7003, 0x0007, 0x7037, 0x0000, 0x6824, 0xa084,
+	0x0080, 0x0040, 0x3e27, 0x1078, 0x42cd, 0x0078, 0x24fa, 0x2300,
+	0x0079, 0x3e2a, 0x3e2d, 0x3eae, 0x3ec7, 0x2200, 0x0079, 0x3e30,
+	0x3e35, 0x3e45, 0x3e6b, 0x3e77, 0x3e9a, 0x2029, 0x0001, 0xa026,
+	0x2011, 0x0000, 0x1078, 0x43f3, 0x0079, 0x3e3e, 0x3e43, 0x24fa,
+	0x3c68, 0x3e43, 0x3e43, 0x1078, 0x248c, 0x7990, 0xa18c, 0x0007,
+	0x00c0, 0x3e4c, 0x2009, 0x0008, 0x2011, 0x0001, 0xa684, 0x0004,
+	0x0040, 0x3e54, 0x2011, 0x0003, 0x2220, 0xa12a, 0x2011, 0x0001,
+	0x1078, 0x43f3, 0x0079, 0x3e5c, 0x3e61, 0x24fa, 0x3c68, 0x3e69,
+	0x3e63, 0x0078, 0x483b, 0x70ab, 0x3e67, 0x0078, 0x24fa, 0x0078,
+	0x3e61, 0x1078, 0x248c, 0xa684, 0x0010, 0x0040, 0x3e75, 0x1078,
+	0x429c, 0x0040, 0x3e75, 0x0078, 0x24fa, 0x0078, 0x430d, 0x6000,
+	0xa084, 0x0002, 0x0040, 0x3e94, 0x70b4, 0xa080, 0x00cd, 0x781a,
+	0x0d7e, 0x1078, 0x4812, 0x2d00, 0x682e, 0x6827, 0x0000, 0x1078,
+	0x3bc6, 0x0d7f, 0x1078, 0x19ac, 0x7003, 0x0000, 0x7037, 0x0000,
+	0x704b, 0x0000, 0x0078, 0x3c68, 0xa684, 0x0004, 0x00c0, 0x3e9a,
+	0x0078, 0x483b, 0x6000, 0xa084, 0x0004, 0x00c0, 0x3eac, 0x6000,
+	0xa084, 0x0001, 0x0040, 0x3eac, 0x70ab, 0x3eac, 0x2001, 0x0007,
+	0x1078, 0x478f, 0x0078, 0x4841, 0x0078, 0x483b, 0x2200, 0x0079,
+	0x3eb1, 0x3eb6, 0x3eb8, 0x3eb6, 0x3eb6, 0x3eb6, 0x1078, 0x248c,
+	0x70a7, 0x3ebc, 0x0078, 0x4847, 0x78e4, 0xa084, 0x0008, 0x00c0,
+	0x3eb8, 0x1078, 0x4781, 0x70ab, 0x3ec5, 0x0078, 0x483b, 0x2200,
+	0x0079, 0x3eca, 0x3ecf, 0x3ed1, 0x3ed1, 0x3ecf, 0x3ecf, 0x1078,
+	0x248c, 0x78e4, 0xa084, 0x0008, 0x0040, 0x3ee6, 0x70a7, 0x3eda,
+	0x0078, 0x4847, 0x2011, 0x0004, 0x1078, 0x43ed, 0x0079, 0x3ee0,
+	0x3ee6, 0x24fa, 0x3c68, 0x3ee6, 0x3ef0, 0x3ef4, 0x70ab, 0x3eee,
+	0x2001, 0x0003, 0x1078, 0x478f, 0x0078, 0x4841, 0x0078, 0x483b,
+	0x70ab, 0x3ee6, 0x0078, 0x24fa, 0x70ab, 0x3ef8, 0x0078, 0x24fa,
+	0x0078, 0x3eee, 0xa282, 0x0003, 0x0050, 0x3f00, 0x1078, 0x248c,
+	0xa386, 0x0002, 0x00c0, 0x3f19, 0xa286, 0x0002, 0x00c0, 0x3f1f,
+	0x78a0, 0xa005, 0x00c0, 0x3f1f, 0xa484, 0x8000, 0x00c0, 0x3f1f,
+	0x78e4, 0xa084, 0x0008, 0x0040, 0x3f19, 0xa6b5, 0x0008, 0x2019,
+	0x0000, 0xa684, 0x0008, 0x0040, 0x3f1f, 0x1078, 0x4279, 0x6810,
+	0x70be, 0x7003, 0x0007, 0x2300, 0x0079, 0x3f26, 0x3f29, 0x3f56,
+	0x3f5e, 0x2200, 0x0079, 0x3f2c, 0x3f31, 0x3f2f, 0x3f4a, 0x1078,
+	0x248c, 0x7990, 0xa1ac, 0x0007, 0xa026, 0x2011, 0x0001, 0x1078,
+	0x43f3, 0x0079, 0x3f3b, 0x3f40, 0x24fa, 0x3c68, 0x3f48, 0x3f42,
+	0x0078, 0x483b, 0x70ab, 0x3f46, 0x0078, 0x24fa, 0x0078, 0x3f40,
+	0x1078, 0x248c, 0xa684, 0x0010, 0x0040, 0x3f54, 0x1078, 0x429c,
+	0x0040, 0x3f54, 0x0078, 0x24fa, 0x0078, 0x430d, 0x2200, 0x0079,
+	0x3f59, 0x3f5c, 0x3f5c, 0x3f5c, 0x1078, 0x248c, 0x2200, 0x0079,
+	0x3f61, 0x3f64, 0x3f66, 0x3f66, 0x1078, 0x248c, 0x78e4, 0xa084,
+	0x0008, 0x0040, 0x3f7b, 0x70a7, 0x3f6f, 0x0078, 0x4847, 0x2011,
+	0x0004, 0x1078, 0x43ed, 0x0079, 0x3f75, 0x3f7b, 0x24fa, 0x3c68,
+	0x3f7b, 0x3f85, 0x3f89, 0x70ab, 0x3f83, 0x2001, 0x0003, 0x1078,
+	0x478f, 0x0078, 0x4841, 0x0078, 0x483b, 0x70ab, 0x3f7b, 0x0078,
+	0x24fa, 0x70ab, 0x3f8d, 0x0078, 0x24fa, 0x0078, 0x3f83, 0x2300,
+	0x0079, 0x3f92, 0x3f97, 0x3f99, 0x3f95, 0x1078, 0x248c, 0x70a4,
+	0x007a, 0x70a4, 0x007a, 0xa282, 0x0002, 0x0050, 0x3fa1, 0x1078,
+	0x248c, 0xa684, 0x0200, 0x0040, 0x3fab, 0x1078, 0x47fe, 0x1078,
+	0x43d5, 0x1078, 0x4805, 0x2300, 0x0079, 0x3fae, 0x3fb1, 0x3fd9,
+	0x403f, 0xad86, 0xffff, 0x0040, 0x3c68, 0xa286, 0x0001, 0x0040,
+	0x3fbb, 0x1078, 0x248c, 0xa684, 0x0200, 0x0040, 0x3fc3, 0x1078,
+	0x47fe, 0x1078, 0x4805, 0x2001, 0x0001, 0x1078, 0x4797, 0x78b8,
+	0xa084, 0xc001, 0x0040, 0x3fd5, 0x7848, 0xa085, 0x0008, 0x784a,
+	0x7848, 0xa084, 0x0008, 0x00c0, 0x3fd0, 0x7003, 0x0000, 0x0078,
+	0x3c68, 0x2200, 0x0079, 0x3fdc, 0x3fde, 0x400f, 0x70a7, 0x3fe2,
+	0x0078, 0x4847, 0x2011, 0x000d, 0x1078, 0x43ed, 0x0079, 0x3fe8,
+	0x3fef, 0x24fa, 0x3c68, 0x3ff7, 0x3fff, 0x4005, 0x4007, 0xa6b4,
+	0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a, 0x0078, 0x4835, 0xa6b4,
+	0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a, 0x0078, 0x4835, 0x70ab,
+	0x4003, 0x0078, 0x24fa, 0x0078, 0x3fef, 0x1078, 0x248c, 0x70ab,
+	0x400b, 0x0078, 0x24fa, 0x1078, 0x484d, 0x0078, 0x24fa, 0x70a7,
+	0x4013, 0x0078, 0x4847, 0x2011, 0x0012, 0x1078, 0x43ed, 0x0079,
+	0x4019, 0x401f, 0x24fa, 0x3c68, 0x402b, 0x4033, 0x4039, 0xa6b4,
+	0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a, 0x70b4, 0xa080, 0x00aa,
+	0x781a, 0x0078, 0x24fa, 0xa6b4, 0x00ff, 0xa6b5, 0x0400, 0x6eb6,
+	0x7e5a, 0x0078, 0x4835, 0x70ab, 0x4037, 0x0078, 0x24fa, 0x0078,
+	0x401f, 0x70ab, 0x403d, 0x0078, 0x24fa, 0x0078, 0x402b, 0xa286,
+	0x0001, 0x0040, 0x4045, 0x1078, 0x248c, 0x70a7, 0x4049, 0x0078,
+	0x4847, 0x2011, 0x0015, 0x1078, 0x43ed, 0x0079, 0x404f, 0x4054,
+	0x24fa, 0x3c68, 0x4062, 0x406e, 0xa6b4, 0x00ff, 0xa6b5, 0x0400,
+	0x6eb6, 0x7e5a, 0x783b, 0x1301, 0x70b4, 0xa080, 0x00b5, 0x781a,
+	0x0078, 0x24fa, 0xa6b4, 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a,
+	0x70b4, 0xa080, 0x00aa, 0x781a, 0x0078, 0x24fa, 0x70ab, 0x4072,
+	0x0078, 0x24fa, 0x0078, 0x4054, 0xa282, 0x0003, 0x0050, 0x407a,
+	0x1078, 0x248c, 0x2300, 0x0079, 0x407d, 0x4080, 0x40b7, 0x4114,
+	0xa286, 0x0001, 0x0040, 0x4086, 0x1078, 0x248c, 0x6804, 0xa084,
+	0x00ff, 0xa086, 0x0006, 0x00c0, 0x4093, 0x1078, 0x3bc6, 0x7003,
+	0x0000, 0x0078, 0x3c68, 0x683b, 0x0000, 0x6837, 0x0000, 0xa684,
+	0x0200, 0x0040, 0x40a1, 0x1078, 0x47fe, 0x1078, 0x43d5, 0x1078,
+	0x4805, 0x2001, 0x0001, 0x1078, 0x4797, 0x78b8, 0xa084, 0xc001,
+	0x0040, 0x40b3, 0x7848, 0xa085, 0x0008, 0x784a, 0x7848, 0xa084,
+	0x0008, 0x00c0, 0x40ae, 0x7003, 0x0000, 0x0078, 0x3c68, 0x2200,
+	0x0079, 0x40ba, 0x40bc, 0x40ef, 0x70a7, 0x40c0, 0x0078, 0x4847,
+	0x2011, 0x000d, 0x1078, 0x43ed, 0x0079, 0x40c6, 0x40cd, 0x24fa,
+	0x3c68, 0x40d5, 0x40dd, 0x40e3, 0x40e5, 0xa6b4, 0x00ff, 0xa6b5,
+	0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4835, 0xa6b4, 0x00ff, 0xa6b5,
+	0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4835, 0x70ab, 0x40e1, 0x0078,
+	0x24fa, 0x0078, 0x40cd, 0x1078, 0x248c, 0x70ab, 0x40eb, 0x1078,
+	0x4805, 0x0078, 0x24fa, 0x1078, 0x484d, 0x0078, 0x24fa, 0x70a7,
+	0x40f3, 0x0078, 0x4847, 0x2011, 0x0005, 0x1078, 0x43ed, 0x0079,
+	0x40f9, 0x40fe, 0x24fa, 0x3c68, 0x4106, 0x410e, 0xa6b4, 0x00ff,
+	0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4835, 0xa6b4, 0x00ff,
+	0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4835, 0x70ab, 0x4112,
+	0x0078, 0x24fa, 0x0078, 0x40fe, 0xa286, 0x0001, 0x0040, 0x411a,
+	0x1078, 0x248c, 0x70a7, 0x411e, 0x0078, 0x4847, 0x2011, 0x0006,
+	0x1078, 0x43ed, 0x0079, 0x4124, 0x4129, 0x24fa, 0x3c68, 0x412f,
+	0x4139, 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4835, 0xa6b4,
+	0x00ff, 0xa6b5, 0x0800, 0x6eb6, 0xa6b5, 0x4000, 0x7e5a, 0x0078,
+	0x4835, 0x70ab, 0x413d, 0x0078, 0x24fa, 0x0078, 0x4129, 0x2300,
+	0x0079, 0x4142, 0x4147, 0x4145, 0x4145, 0x1078, 0x248c, 0x1078,
+	0x248c, 0x2300, 0x71a8, 0xa005, 0x017a, 0x6810, 0x70be, 0xa282,
+	0x0003, 0x0050, 0x4155, 0x1078, 0x248c, 0x2300, 0x0079, 0x4158,
+	0x415b, 0x4169, 0x418b, 0xa684, 0x0200, 0x0040, 0x4163, 0x1078,
+	0x47fe, 0x1078, 0x4805, 0x2001, 0x0001, 0x1078, 0x4797, 0x0078,
+	0x24fa, 0xa296, 0x0002, 0x0040, 0x4172, 0x82ff, 0x0040, 0x4172,
+	0x1078, 0x248c, 0x70a7, 0x4176, 0x0078, 0x4847, 0x2011, 0x0018,
+	0x1078, 0x43ed, 0x0079, 0x417c, 0x4181, 0x24fa, 0x3c68, 0x4183,
+	0x4185, 0x0078, 0x4835, 0x0078, 0x4835, 0x70ab, 0x4189, 0x0078,
+	0x24fa, 0x0078, 0x4181, 0x2200, 0x0079, 0x418e, 0x4190, 0x41a9,
+	0x70a7, 0x4194, 0x0078, 0x4847, 0x2011, 0x0017, 0x1078, 0x43ed,
+	0x0079, 0x419a, 0x419f, 0x24fa, 0x3c68, 0x41a1, 0x41a3, 0x0078,
+	0x4835, 0x0078, 0x4835, 0x70ab, 0x41a7, 0x0078, 0x24fa, 0x0078,
+	0x419f, 0xa484, 0x8000, 0x00c0, 0x4205, 0xa684, 0x0100, 0x0040,
+	0x41b5, 0x1078, 0x47fe, 0x1078, 0x43d5, 0x78d8, 0x78d2, 0x78dc,
+	0x78d6, 0xa6b4, 0xefff, 0x7e5a, 0x70a7, 0x41c0, 0x0078, 0x4847,
+	0x2011, 0x000d, 0x1078, 0x43ed, 0x0079, 0x41c6, 0x41cd, 0x24fa,
+	0x3c68, 0x41cd, 0x41f3, 0x41f9, 0x41fb, 0x78d8, 0x79dc, 0xa105,
+	0x00c0, 0x41df, 0x78b8, 0xa084, 0x001f, 0x00c0, 0x41df, 0x70b3,
+	0x0000, 0x7858, 0xa084, 0xfdff, 0x785a, 0x0078, 0x4835, 0xa684,
+	0x0100, 0x0040, 0x41f1, 0x7848, 0xa085, 0x0008, 0x784a, 0x1078,
+	0x47bc, 0x682c, 0x78d2, 0x6830, 0x78d6, 0x70b3, 0x0000, 0x1078,
+	0x47f6, 0x0078, 0x4835, 0x70ab, 0x41f7, 0x0078, 0x24fa, 0x0078,
+	0x41cd, 0x1078, 0x248c, 0x70ab, 0x4201, 0x1078, 0x4805, 0x0078,
+	0x24fa, 0x1078, 0x484d, 0x0078, 0x24fa, 0x1078, 0x4805, 0x70ab,
+	0x420f, 0x2001, 0x0003, 0x1078, 0x478f, 0x0078, 0x4841, 0x1078,
+	0x47f6, 0x682c, 0x78d2, 0x6830, 0x78d6, 0x0078, 0x4835, 0x70b8,
+	0x6812, 0x70be, 0x8000, 0x70ba, 0x681b, 0x0000, 0xa684, 0x0008,
+	0x0040, 0x423a, 0x157e, 0x137e, 0x147e, 0x7890, 0x8004, 0x8004,
+	0x8004, 0x8004, 0xa084, 0x000f, 0x681a, 0x80ac, 0x789b, 0x0000,
+	0xaf80, 0x002b, 0x2098, 0xad80, 0x000b, 0x20a0, 0x53a5, 0x147f,
+	0x137f, 0x157f, 0xa6c4, 0x0f00, 0xa684, 0x0002, 0x00c0, 0x4249,
+	0x692c, 0x810d, 0x810d, 0x810d, 0xa184, 0x0007, 0x2008, 0x0078,
+	0x425c, 0x789b, 0x0010, 0x79ac, 0xa184, 0x0020, 0x0040, 0x425c,
+	0x017e, 0x2009, 0x0005, 0x2001, 0x3d00, 0x1078, 0x47c7, 0x6824,
+	0xa085, 0x003b, 0x6826, 0x017f, 0xa184, 0x001f, 0xa805, 0x6816,
+	0x1078, 0x3c3b, 0x68be, 0xa684, 0x0004, 0x0040, 0x426d, 0xa18c,
+	0xff00, 0x78a8, 0xa084, 0x00ff, 0xa105, 0x682a, 0xa6b4, 0x00ff,
+	0x6000, 0xa084, 0x0008, 0x0040, 0x4277, 0xa6b5, 0x4000, 0x6eb6,
+	0x007c, 0x157e, 0x137e, 0x147e, 0x6918, 0x7890, 0x8004, 0x8004,
+	0x8004, 0x8004, 0xa084, 0x000f, 0x007e, 0xa100, 0x681a, 0x007f,
+	0x8000, 0x8004, 0x0040, 0x4298, 0x20a8, 0x8104, 0xa080, 0x000b,
+	0xad00, 0x20a0, 0x789b, 0x0000, 0xaf80, 0x002b, 0x2098, 0x53a5,
+	0x147f, 0x137f, 0x157f, 0x007c, 0x682c, 0xa084, 0x0020, 0x00c0,
+	0x42a4, 0x620c, 0x0078, 0x42a5, 0x6210, 0x6b18, 0x2300, 0xa202,
+	0x0040, 0x42c5, 0x2018, 0xa382, 0x000e, 0x0048, 0x42b5, 0x0040,
+	0x42b5, 0x2019, 0x000e, 0x0078, 0x42b9, 0x7858, 0xa084, 0xffef,
+	0x785a, 0x783b, 0x1b01, 0x7893, 0x0000, 0x7ba2, 0x70b4, 0xa080,
+	0x008e, 0x781a, 0xa085, 0x0001, 0x007c, 0x7858, 0xa084, 0xffef,
+	0x785a, 0x7893, 0x0000, 0xa006, 0x007c, 0x6904, 0xa18c, 0x00ff,
+	0xa196, 0x0007, 0x0040, 0x42da, 0xa196, 0x000f, 0x0040, 0x42da,
+	0x6807, 0x0117, 0x6914, 0x1078, 0x3c3b, 0x6100, 0x8104, 0x00c8,
+	0x42f5, 0x601c, 0xa005, 0x0040, 0x42e9, 0x2001, 0x0800, 0x0078,
+	0x42f7, 0x0d7e, 0x6824, 0x007e, 0x1078, 0x4812, 0x007f, 0x6826,
+	0x2d00, 0x682e, 0x1078, 0x3bc6, 0x0d7f, 0x2001, 0x0200, 0x6924,
+	0xa18c, 0x00ff, 0xa10d, 0x6926, 0x8007, 0x789b, 0x000e, 0x78aa,
+	0x6820, 0xa085, 0x8000, 0x6822, 0x2031, 0x0400, 0x6eb6, 0x7e5a,
+	0x71b4, 0xa188, 0x0091, 0x791a, 0x007c, 0xa6c4, 0x0f00, 0xa684,
+	0x0002, 0x00c0, 0x4321, 0x692c, 0x810d, 0x810d, 0x810d, 0xa184,
+	0x0007, 0x2008, 0xa805, 0x6816, 0x1078, 0x3c3b, 0x68be, 0x0078,
+	0x4324, 0x6914, 0x1078, 0x3c3b, 0x6100, 0x8104, 0x00c8, 0x4382,
+	0xa184, 0x0300, 0x0040, 0x4330, 0x6807, 0x0117, 0x0078, 0x434e,
+	0x6004, 0xa005, 0x00c0, 0x4357, 0x6807, 0x0117, 0x601c, 0xa005,
+	0x00c0, 0x4344, 0x0d7e, 0x1078, 0x4812, 0x6827, 0x0034, 0x2d00,
+	0x682e, 0x1078, 0x3bc6, 0x0d7f, 0xa684, 0x0004, 0x0040, 0x434e,
+	0x2031, 0x0400, 0x2001, 0x2800, 0x0078, 0x4352, 0x2031, 0x0400,
+	0x2001, 0x0800, 0x71b4, 0xa188, 0x0091, 0x0078, 0x43b0, 0x6018,
+	0xa005, 0x00c0, 0x4344, 0x601c, 0xa005, 0x00c0, 0x4344, 0x689f,
+	0x0000, 0x6827, 0x003d, 0xa684, 0x0001, 0x0040, 0x43be, 0xd694,
+	0x00c0, 0x437b, 0x6100, 0xd1d4, 0x0040, 0x437b, 0x692c, 0xa18c,
+	0x00ff, 0x0040, 0x43be, 0xa186, 0x0003, 0x0040, 0x43be, 0xa186,
+	0x0012, 0x0040, 0x43be, 0xa6b5, 0x0800, 0x71b4, 0xa188, 0x00ae,
+	0x0078, 0x43b9, 0x6807, 0x0117, 0x2031, 0x0400, 0x692c, 0xa18c,
+	0x00ff, 0xa186, 0x0012, 0x00c0, 0x4393, 0x2001, 0x43cb, 0x2009,
+	0x0001, 0x0078, 0x43a4, 0xa186, 0x0003, 0x00c0, 0x439d, 0x2001,
+	0x43cc, 0x2009, 0x0012, 0x0078, 0x43a4, 0x2001, 0x0200, 0x71b4,
+	0xa188, 0x0091, 0x0078, 0x43b0, 0x1078, 0x47e1, 0x78a3, 0x0000,
+	0x681c, 0xa085, 0x0040, 0x681e, 0x71b4, 0xa188, 0x00da, 0xa006,
+	0x6826, 0x8007, 0x789b, 0x000e, 0x78aa, 0x6820, 0xa085, 0x8000,
+	0x6822, 0x6eb6, 0x7e5a, 0x791a, 0x0078, 0x24fa, 0x6eb6, 0x1078,
+	0x3bc6, 0x6810, 0x70be, 0x7003, 0x0007, 0x70a3, 0x0000, 0x704b,
+	0x0000, 0x0078, 0x24fa, 0x0023, 0x0070, 0x0005, 0x0000, 0x0a00,
+	0x0000, 0x0000, 0x0025, 0x0000, 0x0000, 0x683b, 0x0000, 0x6837,
+	0x0000, 0xa684, 0x0200, 0x0040, 0x43ec, 0x78b8, 0xa08c, 0x001f,
+	0xa084, 0x8000, 0x0040, 0x43e5, 0x8108, 0x78d8, 0xa100, 0x6836,
+	0x78dc, 0xa081, 0x0000, 0x683a, 0x007c, 0x7990, 0x810f, 0xa5ac,
+	0x0007, 0x2021, 0x0000, 0xa480, 0x0010, 0x789a, 0x79a8, 0xa18c,
+	0x00ff, 0xa184, 0x0080, 0x00c0, 0x441b, 0xa182, 0x0020, 0x00c8,
+	0x4439, 0xa182, 0x0012, 0x00c8, 0x4781, 0x2100, 0x1079, 0x4409,
+	0x007c, 0x4781, 0x45eb, 0x4781, 0x4781, 0x4446, 0x4449, 0x4483,
+	0x44b9, 0x44ed, 0x44f0, 0x4781, 0x4781, 0x44a4, 0x4514, 0x454e,
+	0x4781, 0x4781, 0x4574, 0xa184, 0x0020, 0x00c0, 0x45a8, 0xa18c,
+	0x001f, 0x6814, 0xa084, 0x001f, 0xa106, 0x0040, 0x4436, 0x70b4,
+	0xa080, 0x00cd, 0x781a, 0x2001, 0x0014, 0x1078, 0x4797, 0x1078,
+	0x4805, 0x7003, 0x0000, 0x2001, 0x0002, 0x007c, 0x2001, 0x0000,
+	0x007c, 0xa182, 0x0024, 0x00c8, 0x4781, 0xa184, 0x0003, 0x1079,
+	0x4409, 0x007c, 0x4781, 0x4781, 0x4781, 0x4781, 0x1078, 0x4781,
+	0x007c, 0x2200, 0x0079, 0x444c, 0x4577, 0x4577, 0x4470, 0x4470,
+	0x4470, 0x4470, 0x4470, 0x4470, 0x4470, 0x4470, 0x446e, 0x4470,
+	0x4465, 0x4470, 0x4470, 0x4470, 0x4470, 0x4470, 0x4478, 0x447b,
+	0x4577, 0x447b, 0x4470, 0x4470, 0x4470, 0x0c7e, 0x077e, 0x6f14,
+	0x1078, 0x37b0, 0x077f, 0x0c7f, 0x0078, 0x4470, 0x1078, 0x468e,
+	0x6827, 0x02b3, 0x2009, 0x000b, 0x2001, 0x4800, 0x0078, 0x45ab,
+	0x1078, 0x4773, 0x007c, 0x6827, 0x0093, 0x2009, 0x000b, 0x2001,
+	0x4800, 0x0078, 0x4593, 0x2d58, 0x6804, 0xa084, 0x00ff, 0xa086,
+	0x0006, 0x00c0, 0x448d, 0x6807, 0x0117, 0x6827, 0x0002, 0x1078,
+	0x4812, 0x6827, 0x0036, 0x6932, 0x2d00, 0x682e, 0x0d7e, 0x1078,
+	0x3b96, 0x1078, 0x45d3, 0x2b68, 0x1078, 0x3bc6, 0x0d7f, 0x1078,
+	0x3bc6, 0x2001, 0x0002, 0x007c, 0x1078, 0x45d3, 0x2001, 0x0017,
+	0x1078, 0x4797, 0x70a3, 0x0000, 0x2009, 0x5238, 0x200b, 0x0006,
+	0x70af, 0x0017, 0x2009, 0x0200, 0x1078, 0x3ad4, 0x2001, 0x0001,
+	0x007c, 0x2200, 0x0079, 0x44bc, 0x4577, 0x45a8, 0x45a8, 0x45a8,
+	0x44dd, 0x45ba, 0x44e5, 0x45ba, 0x45ba, 0x45bd, 0x45bd, 0x45c2,
+	0x45c2, 0x44d5, 0x44d5, 0x45a8, 0x45a8, 0x45ba, 0x45a8, 0x44e5,
+	0x4577, 0x44e5, 0x44e5, 0x44e5, 0x44e5, 0x6827, 0x0084, 0x2009,
+	0x000b, 0x2001, 0x4300, 0x0078, 0x45cc, 0x6827, 0x000d, 0x2009,
+	0x000b, 0x2001, 0x4300, 0x0078, 0x45ab, 0x6827, 0x0093, 0x2009,
+	0x000b, 0x2001, 0x4300, 0x0078, 0x4593, 0x2001, 0x0000, 0x007c,
+	0x2200, 0x0079, 0x44f3, 0x4577, 0x450c, 0x450c, 0x450c, 0x450c,
+	0x45ba, 0x45ba, 0x45ba, 0x45ba, 0x45ba, 0x45ba, 0x45ba, 0x45ba,
+	0x450c, 0x450c, 0x450c, 0x450c, 0x45ba, 0x450c, 0x450c, 0x45ba,
+	0x45ba, 0x45ba, 0x45ba, 0x4577, 0x6827, 0x0093, 0x2009, 0x000b,
+	0x2001, 0x4300, 0x0078, 0x4593, 0xa684, 0x0004, 0x00c0, 0x4528,
+	0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x4781, 0x1078,
+	0x45d3, 0x6807, 0x0117, 0x1078, 0x3bc6, 0x2001, 0x0002, 0x007c,
+	0x6000, 0xa084, 0x0004, 0x0040, 0x4781, 0x2d58, 0x6804, 0xa084,
+	0x00ff, 0xa086, 0x0006, 0x00c0, 0x4537, 0x6807, 0x0117, 0x6827,
+	0x0002, 0x1078, 0x4812, 0x6827, 0x0036, 0x6932, 0x2d00, 0x682e,
+	0x0d7e, 0x1078, 0x3ba5, 0x1078, 0x45d3, 0x2b68, 0x1078, 0x3bc6,
+	0x0d7f, 0x1078, 0x3bc6, 0x2001, 0x0002, 0x007c, 0x6000, 0xa084,
+	0x0004, 0x0040, 0x4781, 0x6a04, 0xa294, 0x00ff, 0xa286, 0x0006,
+	0x00c0, 0x455c, 0x6807, 0x0117, 0x6827, 0x0002, 0x2d58, 0x1078,
+	0x4812, 0x6827, 0x0036, 0x6932, 0x2d00, 0x682e, 0x0d7e, 0x1078,
+	0x3bb5, 0x1078, 0x45d3, 0x2b68, 0x1078, 0x3bc6, 0x0d7f, 0x1078,
+	0x3bc6, 0x2001, 0x0002, 0x007c, 0x1078, 0x4781, 0x007c, 0x70b4,
+	0xa080, 0x00cd, 0x781a, 0x2001, 0x0001, 0x1078, 0x4797, 0x1078,
+	0x4805, 0x7003, 0x0000, 0x2001, 0x0002, 0x007c, 0x1078, 0x47c7,
+	0x1078, 0x47fe, 0x1078, 0x43d5, 0x1078, 0x42cd, 0x1078, 0x4805,
+	0x2001, 0x0001, 0x007c, 0x1078, 0x47c7, 0x1078, 0x47fe, 0x1078,
+	0x43d5, 0x70b4, 0xa080, 0x00cd, 0x781a, 0x2001, 0x0013, 0x1078,
+	0x4797, 0x1078, 0x4805, 0x7003, 0x0000, 0x2001, 0x0002, 0x007c,
+	0x1078, 0x4781, 0x007c, 0x1078, 0x47c7, 0x1078, 0x47fe, 0x1078,
+	0x43d5, 0x1078, 0x42cd, 0x1078, 0x4805, 0x1078, 0x484d, 0x2001,
+	0x0001, 0x007c, 0x2001, 0x0003, 0x007c, 0x1078, 0x468e, 0x2001,
+	0x0000, 0x007c, 0x0c7e, 0x077e, 0x6f14, 0x1078, 0x37b0, 0x077f,
+	0x0c7f, 0x2001, 0x0000, 0x007c, 0x1078, 0x47c7, 0x1078, 0x4781,
+	0x2001, 0x0006, 0x007c, 0x6904, 0xa18c, 0x00ff, 0xa186, 0x0007,
+	0x0040, 0x45de, 0xa186, 0x000f, 0x00c0, 0x45e2, 0x1078, 0x47fe,
+	0x1078, 0x43d5, 0x70b4, 0xa080, 0x00cd, 0x781a, 0x1078, 0x4805,
+	0x7003, 0x0000, 0x007c, 0x7aa8, 0xa294, 0x00ff, 0x78a8, 0xa084,
+	0x00ff, 0xa08a, 0x0004, 0x00c8, 0x4781, 0x1079, 0x45f8, 0x007c,
+	0x4781, 0x45fc, 0x4781, 0x4695, 0xa282, 0x0003, 0x0040, 0x4603,
+	0x1078, 0x4781, 0x007c, 0x7da8, 0xa5ac, 0x00ff, 0x7ca8, 0xa4a4,
+	0x00ff, 0x69b8, 0xa184, 0x0100, 0x0040, 0x4642, 0xa18c, 0xfeff,
+	0x69ba, 0x78a0, 0xa005, 0x00c0, 0x4642, 0xa4a4, 0x00ff, 0x0040,
+	0x4636, 0xa482, 0x000c, 0x0040, 0x461f, 0x00c8, 0x4629, 0x852b,
+	0x852b, 0x1078, 0x382e, 0x0040, 0x4629, 0x1078, 0x3627, 0x0078,
+	0x4638, 0x1078, 0x4760, 0x1078, 0x3652, 0x69b8, 0xa18d, 0x0100,
+	0x69ba, 0xa6b5, 0x1000, 0x7e5a, 0x0078, 0x463b, 0x1078, 0x3652,
+	0xa6b4, 0xefff, 0x7e5a, 0x70b4, 0xa080, 0x0091, 0x781a, 0x2001,
+	0x0001, 0x007c, 0x0c7e, 0x1078, 0x4682, 0x6200, 0xd2e4, 0x0040,
+	0x4673, 0x6208, 0x8217, 0xa294, 0x00ff, 0xa282, 0x000c, 0x0048,
+	0x4655, 0x0040, 0x4655, 0x2011, 0x000c, 0x2400, 0xa202, 0x00c8,
+	0x465a, 0x2220, 0x6208, 0xa294, 0x00ff, 0x701c, 0xa202, 0x00c8,
+	0x4662, 0x721c, 0x2200, 0xa502, 0x00c8, 0x4667, 0x2228, 0x1078,
+	0x4764, 0x852b, 0x852b, 0x1078, 0x382e, 0x0040, 0x4673, 0x1078,
+	0x362e, 0x0078, 0x4677, 0x1078, 0x4760, 0x1078, 0x3659, 0xa6b5,
+	0x1000, 0x7e5a, 0x70b4, 0xa080, 0x00b9, 0x781a, 0x2001, 0x0004,
+	0x0c7f, 0x007c, 0x007e, 0x6814, 0x8007, 0xa084, 0x000f, 0x8003,
+	0x8003, 0x8003, 0xa0e0, 0x5480, 0x007f, 0x007c, 0x0c7e, 0x1078,
+	0x4682, 0x1078, 0x3659, 0x0c7f, 0x007c, 0xa282, 0x0002, 0x00c0,
+	0x4781, 0x7aa8, 0xa294, 0x00ff, 0x69b8, 0xa184, 0x0200, 0x0040,
+	0x46cc, 0xa18c, 0xfdff, 0x69ba, 0x78a0, 0xa005, 0x00c0, 0x46cc,
+	0xa282, 0x0002, 0x00c8, 0x376b, 0x1078, 0x472a, 0x1078, 0x36f9,
+	0x1078, 0x3652, 0xa684, 0x0100, 0x0040, 0x46c2, 0x682c, 0xa084,
+	0x0001, 0x0040, 0x46c2, 0xc6fc, 0x7888, 0xa084, 0x0040, 0x0040,
+	0x46c2, 0xc6fd, 0xa6b5, 0x1000, 0x7e5a, 0x70b4, 0xa080, 0x0091,
+	0x781a, 0x2001, 0x0001, 0x007c, 0x0c7e, 0x1078, 0x4682, 0xa284,
+	0xfffe, 0x0040, 0x46d7, 0x2011, 0x0001, 0x0078, 0x46db, 0xa284,
+	0x0001, 0x0040, 0x46e1, 0x6100, 0xd1ec, 0x00c0, 0x46e1, 0x2011,
+	0x0000, 0x1078, 0x471c, 0x1078, 0x3700, 0x1078, 0x3659, 0xa684,
+	0x0100, 0x0040, 0x46f7, 0x682c, 0xa084, 0x0001, 0x0040, 0x46f7,
+	0xc6fc, 0x7888, 0xa084, 0x0040, 0x0040, 0x46f7, 0xc6fd, 0xa6b5,
+	0x1000, 0x7e5a, 0x70b4, 0xa080, 0x00b9, 0x781a, 0x2001, 0x0004,
+	0x0c7f, 0x007c, 0x0c7e, 0x2960, 0x6000, 0x2011, 0x0001, 0xa084,
+	0x2000, 0x00c0, 0x470d, 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab,
+	0x0002, 0x78ab, 0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x68b8, 0xa085,
+	0x0200, 0x68ba, 0x0c7f, 0x007c, 0x789b, 0x0018, 0x78ab, 0x0001,
+	0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0081, 0x78ab,
+	0x0004, 0x007c, 0x0c7e, 0x7054, 0x2060, 0x6000, 0xa084, 0x1000,
+	0x00c0, 0x4738, 0x2029, 0x0032, 0x2021, 0x0000, 0x0078, 0x4758,
+	0x6508, 0xa5ac, 0x00ff, 0x7018, 0xa086, 0x0028, 0x00c0, 0x4748,
+	0xa582, 0x0019, 0x00c8, 0x474e, 0x2029, 0x0019, 0x0078, 0x474e,
+	0xa582, 0x000c, 0x00c8, 0x474e, 0x2029, 0x000c, 0x6408, 0x8427,
+	0xa4a4, 0x00ff, 0xa482, 0x000c, 0x0048, 0x4758, 0x2021, 0x000c,
+	0x1078, 0x4764, 0x68b8, 0xa085, 0x0100, 0x68ba, 0x0c7f, 0x007c,
+	0x2021, 0x0000, 0x2029, 0x0032, 0x789b, 0x0018, 0x78ab, 0x0001,
+	0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa, 0x7caa, 0x789b, 0x0081,
+	0x78ab, 0x0005, 0x007c, 0x2001, 0x0003, 0x1078, 0x478f, 0xa6b5,
+	0x1000, 0x7e5a, 0x70b4, 0xa080, 0x00b9, 0x781a, 0x2001, 0x0005,
+	0x007c, 0x2001, 0x0007, 0x1078, 0x478f, 0xa6b5, 0x1000, 0x7e5a,
+	0x70b4, 0xa080, 0x00b9, 0x781a, 0x2001, 0x0004, 0x007c, 0x789b,
+	0x0018, 0x78aa, 0x789b, 0x0081, 0x78ab, 0x0001, 0x007c, 0x6904,
+	0xa18c, 0x00ff, 0xa196, 0x0007, 0x0040, 0x47a5, 0xa196, 0x000f,
+	0x0040, 0x47a5, 0x1078, 0x19ac, 0x007c, 0x6924, 0xa194, 0x003f,
+	0x00c0, 0x47ae, 0xa18c, 0xffc0, 0xa105, 0x6826, 0x1078, 0x3bc6,
+	0x691c, 0xa184, 0x0100, 0x0040, 0x47bb, 0x6914, 0x1078, 0x3c3b,
+	0x6204, 0x8210, 0x6206, 0x007c, 0x692c, 0x6834, 0x682e, 0xa112,
+	0x6930, 0x6838, 0x6832, 0xa11b, 0xa200, 0xa301, 0x007c, 0x0c7e,
+	0xade0, 0x0018, 0x6003, 0x0070, 0x6106, 0x600b, 0x0000, 0x600f,
+	0x0a00, 0x6013, 0x0000, 0x6017, 0x0000, 0x8007, 0x601a, 0x601f,
+	0x0000, 0x6023, 0x0000, 0x0c7f, 0x6824, 0xa085, 0x0080, 0x6826,
+	0x007c, 0x157e, 0x137e, 0x147e, 0x2098, 0xaf80, 0x002d, 0x20a0,
+	0x81ac, 0x0040, 0x47ec, 0x53a6, 0xa184, 0x0001, 0x0040, 0x47f2,
+	0x3304, 0x78be, 0x147f, 0x137f, 0x157f, 0x007c, 0x70b0, 0xa005,
+	0x10c0, 0x248c, 0x70b3, 0x8000, 0x0078, 0x4b4b, 0x71b0, 0x81ff,
+	0x0040, 0x4804, 0x1078, 0x4c41, 0x007c, 0x71b0, 0x81ff, 0x0040,
+	0x4811, 0x7848, 0xa085, 0x0008, 0x784a, 0x70b3, 0x0000, 0x1078,
+	0x4887, 0x007c, 0x0c7e, 0x0d7e, 0x1078, 0x1989, 0x00c0, 0x481a,
+	0x1078, 0x248c, 0x0c7f, 0x157e, 0x137e, 0x147e, 0x2da0, 0x2c98,
+	0x20a9, 0x0031, 0x53a3, 0x147f, 0x137f, 0x157f, 0x6807, 0x010d,
+	0x680b, 0x0000, 0x7004, 0x8007, 0x681a, 0x6823, 0x0000, 0x681f,
+	0x0000, 0x689f, 0x0000, 0x0c7f, 0x007c, 0x70b4, 0xa080, 0x0091,
+	0x781a, 0x0078, 0x24fa, 0x70b4, 0xa080, 0x0081, 0x781a, 0x0078,
+	0x24fa, 0x70b4, 0xa080, 0x00b9, 0x781a, 0x0078, 0x24fa, 0x70b4,
+	0xa080, 0x00c3, 0x781a, 0x0078, 0x24fa, 0x6904, 0xa18c, 0x00ff,
+	0xa196, 0x0007, 0x0040, 0x485a, 0xa196, 0x000f, 0x0040, 0x485a,
+	0x6807, 0x0117, 0x6824, 0xa084, 0x00ff, 0xa085, 0x0200, 0x6826,
+	0x8007, 0x789b, 0x000e, 0x78aa, 0x6820, 0xa085, 0x8000, 0x6822,
+	0x2031, 0x0400, 0x6eb6, 0x7e5a, 0x71b4, 0xa188, 0x0091, 0x791a,
+	0x007c, 0x1078, 0x4805, 0x7848, 0xa085, 0x000c, 0x784a, 0x70b4,
+	0xa080, 0x00cd, 0x781a, 0x2009, 0x000b, 0x2001, 0x4400, 0x1078,
+	0x47c7, 0x2001, 0x0013, 0x1078, 0x4797, 0x0078, 0x3c68, 0x127e,
+	0x2091, 0x2200, 0x2049, 0x4887, 0x7000, 0x7204, 0xa205, 0x720c,
+	0xa215, 0x7008, 0xa084, 0xfff7, 0xa205, 0x0040, 0x4899, 0x0078,
+	0x489e, 0x7003, 0x0000, 0x127f, 0x2000, 0x007c, 0x7000, 0xa084,
+	0x0001, 0x00c0, 0x48cc, 0x7108, 0x8103, 0x00c8, 0x48ab, 0x1078,
+	0x49ce, 0x0078, 0x48a3, 0x700c, 0xa08c, 0x00ff, 0x0040, 0x48cc,
+	0x7004, 0x8004, 0x00c8, 0x48c3, 0x7014, 0xa005, 0x00c0, 0x48bf,
+	0x7010, 0xa005, 0x0040, 0x48c3, 0xa102, 0x00c8, 0x48a3, 0x7007,
+	0x0010, 0x0078, 0x48cc, 0x8aff, 0x0040, 0x48cc, 0x1078, 0x4c18,
+	0x00c0, 0x48c6, 0x0040, 0x48a3, 0x1078, 0x4957, 0x7003, 0x0000,
+	0x127f, 0x2000, 0x007c, 0x017e, 0x6104, 0xa18c, 0x00ff, 0xa186,
+	0x0007, 0x0040, 0x48df, 0xa18e, 0x000f, 0x00c0, 0x48e2, 0x6040,
+	0x0078, 0x48e3, 0x6428, 0x017f, 0x84ff, 0x0040, 0x490d, 0x2c70,
+	0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x491d, 0x273c, 0x87fb, 0x00c0,
+	0x48fb, 0x0048, 0x48f5, 0x1078, 0x248c, 0x609c, 0xa075, 0x0040,
+	0x490d, 0x0078, 0x48e8, 0x2704, 0xae68, 0x6808, 0xa630, 0x680c,
+	0xa529, 0x8421, 0x0040, 0x490d, 0x8738, 0x2704, 0xa005, 0x00c0,
+	0x48fc, 0x709c, 0xa075, 0x00c0, 0x48e8, 0x007c, 0x0000, 0x0005,
+	0x0009, 0x000d, 0x0011, 0x0015, 0x0019, 0x001d, 0x0000, 0x0003,
+	0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0000, 0x4912, 0x490f,
+	0x0000, 0x0000, 0x8000, 0x0000, 0x4912, 0x0000, 0x491a, 0x4917,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x491a, 0x0000, 0x4915, 0x4915,
+	0x0000, 0x0000, 0x8000, 0x0000, 0x4915, 0x0000, 0x491b, 0x491b,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x491b, 0x127e, 0x2091, 0x2200,
+	0x2079, 0x5200, 0x2071, 0x0010, 0x7007, 0x000a, 0x7007, 0x0002,
+	0x7003, 0x0000, 0x2071, 0x0020, 0x7007, 0x000a, 0x7007, 0x0002,
+	0x7003, 0x0000, 0x2049, 0x0000, 0x127f, 0x2000, 0x007c, 0x2049,
+	0x4957, 0x2019, 0x0000, 0x7004, 0x8004, 0x00c8, 0x49aa, 0x7007,
+	0x0012, 0x7108, 0x7008, 0xa106, 0x00c0, 0x4961, 0xa184, 0x01e0,
+	0x0040, 0x496c, 0x1078, 0x248c, 0x2001, 0x04fd, 0x2004, 0xa082,
+	0x0005, 0x00c8, 0x4977, 0xa184, 0x4000, 0x00c0, 0x4961, 0xa19c,
+	0x300c, 0xa386, 0x2004, 0x0040, 0x4985, 0xa386, 0x0008, 0x0040,
+	0x4990, 0xa386, 0x200c, 0x00c0, 0x4961, 0x7200, 0x8204, 0x0048,
+	0x4990, 0x730c, 0xa384, 0x00ff, 0x0040, 0x4990, 0x1078, 0x248c,
+	0x7007, 0x0012, 0x7000, 0xa084, 0x0001, 0x00c0, 0x49aa, 0x7008,
+	0xa084, 0x01e0, 0x00c0, 0x49aa, 0x7310, 0x7014, 0xa305, 0x0040,
+	0x49aa, 0x710c, 0xa184, 0x0300, 0x00c0, 0x49aa, 0xa184, 0x00ff,
+	0x00c0, 0x4957, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xa084,
+	0x0008, 0x00c0, 0x49ae, 0x7007, 0x0012, 0x7108, 0x8103, 0x0048,
+	0x49b3, 0x7003, 0x0000, 0x2049, 0x0000, 0x007c, 0x107e, 0x007e,
+	0x127e, 0x157e, 0x2091, 0x2200, 0x7108, 0x1078, 0x49ce, 0x157f,
+	0x127f, 0x2091, 0x8001, 0x007f, 0x107f, 0x007c, 0x7204, 0x7500,
+	0x730c, 0xa384, 0x0300, 0x00c0, 0x49f5, 0xa184, 0x01e0, 0x00c0,
+	0x4a19, 0x7108, 0xa184, 0x01e0, 0x00c0, 0x4a19, 0x2001, 0x04fd,
+	0x2004, 0xa082, 0x0005, 0x00c8, 0x49e9, 0xa184, 0x4000, 0x00c0,
+	0x49d9, 0xa184, 0x0007, 0x0079, 0x49ed, 0x49f7, 0x4a09, 0x49f5,
+	0x4a09, 0x49f5, 0x4a55, 0x49f5, 0x4a53, 0x1078, 0x248c, 0x7004,
+	0xa084, 0x0010, 0xa085, 0x0002, 0x7006, 0x8aff, 0x00c0, 0x4a04,
+	0x2049, 0x0000, 0x0078, 0x4a08, 0x1078, 0x4c18, 0x00c0, 0x4a04,
+	0x007c, 0x7004, 0xa084, 0x0010, 0xa085, 0x0002, 0x7006, 0x8aff,
+	0x00c0, 0x4a14, 0x0078, 0x4a18, 0x1078, 0x4c18, 0x00c0, 0x4a14,
+	0x007c, 0x7007, 0x0012, 0x7108, 0x00e0, 0x4a1c, 0x2091, 0x6000,
+	0x00e0, 0x4a20, 0x2091, 0x6000, 0x7007, 0x0012, 0x7007, 0x0008,
+	0x7004, 0xa084, 0x0008, 0x00c0, 0x4a28, 0x7007, 0x0012, 0x7108,
+	0x8103, 0x0048, 0x4a2d, 0x7003, 0x0000, 0x7000, 0xa005, 0x00c0,
+	0x4a41, 0x7004, 0xa005, 0x00c0, 0x4a41, 0x700c, 0xa005, 0x0040,
+	0x4a43, 0x0078, 0x4a24, 0x2049, 0x0000, 0x1078, 0x38d7, 0x6818,
+	0xa084, 0x8000, 0x0040, 0x4a4e, 0x681b, 0x0002, 0x007c, 0x1078,
+	0x248c, 0x1078, 0x248c, 0x1078, 0x4ab1, 0x7210, 0x7114, 0x700c,
+	0xa09c, 0x00ff, 0x2800, 0xa300, 0xa211, 0xa189, 0x0000, 0x1078,
+	0x4ab1, 0x2704, 0x2c58, 0xac60, 0x6308, 0x2200, 0xa322, 0x630c,
+	0x2100, 0xa31b, 0x2400, 0xa305, 0x0040, 0x4a78, 0x00c8, 0x4a78,
+	0x8412, 0x8210, 0x830a, 0xa189, 0x0000, 0x2b60, 0x0078, 0x4a5f,
+	0x2b60, 0x8a07, 0x007e, 0x6004, 0xa084, 0x0008, 0x0040, 0x4a84,
+	0xa7ba, 0x4917, 0x0078, 0x4a86, 0xa7ba, 0x490f, 0x007f, 0xa73d,
+	0x2c00, 0x6886, 0x6f8a, 0x6c92, 0x6b8e, 0x7007, 0x0012, 0x1078,
+	0x4957, 0x007c, 0x8738, 0x2704, 0xa005, 0x00c0, 0x4aa5, 0x609c,
+	0xa005, 0x0040, 0x4aae, 0x2060, 0x6004, 0xa084, 0x000f, 0xa080,
+	0x491d, 0x203c, 0x87fb, 0x1040, 0x248c, 0x8a51, 0x0040, 0x4aad,
+	0x7008, 0xa084, 0x0003, 0xa086, 0x0003, 0x007c, 0x2051, 0x0000,
+	0x007c, 0x8a50, 0x8739, 0x2704, 0xa004, 0x00c0, 0x4ac5, 0x6000,
+	0xa064, 0x00c0, 0x4abc, 0x2d60, 0x6004, 0xa084, 0x000f, 0xa080,
+	0x492d, 0x203c, 0x87fb, 0x1040, 0x248c, 0x007c, 0x127e, 0x0d7e,
+	0x2091, 0x2200, 0x0d7f, 0x6884, 0x2060, 0x6888, 0x6b8c, 0x6c90,
+	0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff, 0x007e, 0x6804, 0xa084,
+	0x0008, 0x007f, 0x0040, 0x4ae0, 0xa0b8, 0x4917, 0x0078, 0x4ae2,
+	0xa0b8, 0x490f, 0x7e08, 0xa6b5, 0x000c, 0x6904, 0xa18c, 0x00ff,
+	0xa186, 0x0007, 0x0040, 0x4af0, 0xa18e, 0x000f, 0x00c0, 0x4af9,
+	0x681c, 0xa084, 0x0040, 0x0040, 0x4b00, 0xa6b5, 0x0001, 0x0078,
+	0x4b00, 0x681c, 0xa084, 0x0040, 0x0040, 0x4b00, 0xa6b5, 0x0001,
+	0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x4b02, 0x2400,
+	0xa305, 0x00c0, 0x4b0d, 0x0078, 0x4b33, 0x2c58, 0x2704, 0x6104,
+	0xac60, 0x6000, 0xa400, 0x701a, 0x6004, 0xa301, 0x701e, 0xa184,
+	0x0008, 0x0040, 0x4b23, 0x6010, 0xa081, 0x0000, 0x7022, 0x6014,
+	0xa081, 0x0000, 0x7026, 0x6208, 0x2400, 0xa202, 0x7012, 0x620c,
+	0x2300, 0xa203, 0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x1078,
+	0x4a92, 0x0078, 0x4b35, 0x1078, 0x4c18, 0x00c0, 0x4b33, 0x127f,
+	0x2000, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x7007,
+	0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x4b41, 0x7003, 0x0008,
+	0x127f, 0x2000, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f,
+	0x2049, 0x4b4b, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0,
+	0x4b54, 0x7e08, 0xa6b5, 0x000c, 0x6904, 0xa18c, 0x00ff, 0xa186,
+	0x0007, 0x0040, 0x4b67, 0xa18e, 0x000f, 0x00c0, 0x4b72, 0x681c,
+	0xa084, 0x0040, 0x0040, 0x4b6e, 0xa6b5, 0x0001, 0x6840, 0x2050,
+	0x0078, 0x4b7b, 0x681c, 0xa084, 0x0020, 0x00c0, 0x4b79, 0xa6b5,
+	0x0001, 0x6828, 0x2050, 0x2d60, 0x6004, 0xa0bc, 0x000f, 0xa7b8,
+	0x491d, 0x273c, 0x87fb, 0x00c0, 0x4b8f, 0x0048, 0x4b89, 0x1078,
+	0x248c, 0x689c, 0xa065, 0x0040, 0x4b93, 0x0078, 0x4b7c, 0x1078,
+	0x4c18, 0x00c0, 0x4b8f, 0x127f, 0x2000, 0x007c, 0x127e, 0x007e,
+	0x017e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x037f, 0x047f, 0x7e08,
+	0xa6b5, 0x000c, 0x6904, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040,
+	0x4bad, 0xa18e, 0x000f, 0x00c0, 0x4bb6, 0x681c, 0xa084, 0x0040,
+	0x0040, 0x4bbd, 0xa6b5, 0x0001, 0x0078, 0x4bbd, 0x681c, 0xa084,
+	0x0040, 0x0040, 0x4bbd, 0xa6b5, 0x0001, 0x2049, 0x4b96, 0x017e,
+	0x6904, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x4bcb, 0xa18e,
+	0x000f, 0x00c0, 0x4bce, 0x6840, 0x0078, 0x4bcf, 0x6828, 0x017f,
+	0xa055, 0x0040, 0x4c15, 0x2d70, 0x2e60, 0x7004, 0xa0bc, 0x000f,
+	0xa7b8, 0x491d, 0x273c, 0x87fb, 0x00c0, 0x4be9, 0x0048, 0x4be2,
+	0x1078, 0x248c, 0x709c, 0xa075, 0x2060, 0x0040, 0x4c15, 0x0078,
+	0x4bd5, 0x2704, 0xae68, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0048,
+	0x4c02, 0x8a51, 0x00c0, 0x4bf6, 0x1078, 0x248c, 0x8738, 0x2704,
+	0xa005, 0x00c0, 0x4bea, 0x709c, 0xa075, 0x2060, 0x0040, 0x4c15,
+	0x0078, 0x4bd5, 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x6908,
+	0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, 0x00c8, 0x4c11, 0x1078,
+	0x248c, 0x2071, 0x0020, 0x0078, 0x4b00, 0x127f, 0x2000, 0x007c,
+	0x7008, 0xa084, 0x0003, 0xa086, 0x0003, 0x0040, 0x4c40, 0x2704,
+	0xac08, 0x2104, 0x701a, 0x8108, 0x2104, 0x701e, 0x8108, 0x2104,
+	0x7012, 0x8108, 0x2104, 0x7016, 0x6004, 0xa084, 0x0008, 0x0040,
+	0x4c37, 0x8108, 0x2104, 0x7022, 0x8108, 0x2104, 0x7026, 0x7602,
+	0x7004, 0xa084, 0x0010, 0xa085, 0x0001, 0x7006, 0x1078, 0x4a92,
+	0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091, 0x2200, 0x2049, 0x4c41,
+	0x0d7f, 0x087f, 0x7108, 0xa184, 0x0003, 0x00c0, 0x4c6b, 0x017e,
+	0x6904, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x4c5b, 0xa18e,
+	0x000f, 0x00c0, 0x4c5e, 0x6840, 0x0078, 0x4c5f, 0x6828, 0x017f,
+	0xa005, 0x0040, 0x4c79, 0x0078, 0x489e, 0x0020, 0x4c6b, 0x1078,
+	0x4a55, 0x0078, 0x4c79, 0x00a0, 0x4c72, 0x7108, 0x1078, 0x49ce,
+	0x0078, 0x4c4a, 0x7007, 0x0010, 0x00a0, 0x4c74, 0x7108, 0x1078,
+	0x49ce, 0x7008, 0xa086, 0x0008, 0x00c0, 0x4c4a, 0x7000, 0xa005,
+	0x00c0, 0x4c4a, 0x7003, 0x0000, 0x2049, 0x0000, 0x127f, 0x2000,
+	0x007c, 0x127e, 0x147e, 0x137e, 0x157e, 0x0c7e, 0x0d7e, 0x2091,
+	0x2200, 0x0d7f, 0x2049, 0x4c89, 0xad80, 0x0011, 0x20a0, 0x2099,
+	0x0031, 0x700c, 0xa084, 0x00ff, 0x682a, 0x7007, 0x0008, 0x7007,
+	0x0002, 0x7003, 0x0001, 0x0040, 0x4ca8, 0x8000, 0x80ac, 0x53a5,
+	0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x4caa, 0x0c7f,
+	0x2049, 0x0000, 0x7003, 0x0000, 0x157f, 0x137f, 0x147f, 0x127f,
+	0x2000, 0x007c, 0x2091, 0x6000, 0x2091, 0x8000, 0x78cc, 0xa005,
+	0x0040, 0x4cd1, 0x7994, 0x70d0, 0xa106, 0x00c0, 0x4cd1, 0x7804,
+	0xa005, 0x0040, 0x4cd1, 0x7807, 0x0000, 0x0068, 0x4cd1, 0x2091,
+	0x4080, 0x7820, 0x8001, 0x7822, 0x00c0, 0x4d2c, 0x7824, 0x7822,
+	0x2069, 0x5240, 0x6800, 0xa084, 0x0007, 0x0040, 0x4cef, 0xa086,
+	0x0002, 0x0040, 0x4cef, 0x6834, 0xa00d, 0x0040, 0x4cef, 0x2104,
+	0xa005, 0x0040, 0x4cef, 0x8001, 0x200a, 0x0040, 0x4dd4, 0x7848,
+	0xa005, 0x0040, 0x4cfd, 0x8001, 0x784a, 0x00c0, 0x4cfd, 0x2009,
+	0x0102, 0x6844, 0x200a, 0x1078, 0x226f, 0x6890, 0xa005, 0x0040,
+	0x4d09, 0x8001, 0x6892, 0x00c0, 0x4d09, 0x686f, 0x0000, 0x6873,
+	0x0001, 0x2061, 0x5500, 0x20a9, 0x0100, 0x2009, 0x0002, 0x6034,
+	0xa005, 0x0040, 0x4d1f, 0x8001, 0x6036, 0x00c0, 0x4d1f, 0x6010,
+	0xa005, 0x0040, 0x4d1f, 0x017e, 0x1078, 0x226f, 0x017f, 0xace0,
+	0x0010, 0x0070, 0x4d25, 0x0078, 0x4d0f, 0x8109, 0x0040, 0x4d2c,
+	0x20a9, 0x0100, 0x0078, 0x4d0f, 0x1078, 0x4d39, 0x1078, 0x4d5e,
+	0x2009, 0x5251, 0x2104, 0x2009, 0x0102, 0x200a, 0x2091, 0x8001,
+	0x007c, 0x7834, 0x8001, 0x7836, 0x00c0, 0x4d5d, 0x7838, 0x7836,
+	0x2091, 0x8000, 0x7844, 0xa005, 0x00c0, 0x4d48, 0x2001, 0x0101,
+	0x8001, 0x7846, 0xa080, 0x7500, 0x2040, 0x2004, 0xa065, 0x0040,
+	0x4d5d, 0x6024, 0xa005, 0x0040, 0x4d59, 0x8001, 0x6026, 0x0040,
+	0x4d8d, 0x6000, 0x2c40, 0x0078, 0x4d4e, 0x007c, 0x7828, 0x8001,
+	0x782a, 0x00c0, 0x4d8c, 0x782c, 0x782a, 0x7830, 0xa005, 0x00c0,
+	0x4d6b, 0x2001, 0x0200, 0x8001, 0x7832, 0x8003, 0x8003, 0x8003,
+	0x8003, 0xa090, 0x5500, 0xa298, 0x0002, 0x2304, 0xa084, 0x0008,
+	0x0040, 0x4d8c, 0xa290, 0x0009, 0x2204, 0xa005, 0x0040, 0x4d84,
+	0x8001, 0x2012, 0x00c0, 0x4d8c, 0x2304, 0xa084, 0xfff7, 0xa085,
+	0x0080, 0x201a, 0x1078, 0x226f, 0x007c, 0x2069, 0x5240, 0x6800,
+	0xa005, 0x0040, 0x4d97, 0x6848, 0xac06, 0x0040, 0x4dd4, 0x601b,
+	0x0006, 0x60b4, 0xa084, 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff,
+	0xa085, 0x0060, 0x6022, 0x6000, 0x2042, 0x6714, 0x6f82, 0x1078,
+	0x19c5, 0x6818, 0xa005, 0x0040, 0x4daf, 0x8001, 0x681a, 0x6808,
+	0xa084, 0xffef, 0x680a, 0x6810, 0x8001, 0x00d0, 0x4db9, 0x1078,
+	0x248c, 0x6812, 0x602f, 0x0000, 0x6033, 0x0000, 0x2c68, 0x1078,
+	0x1cdc, 0x2069, 0x5240, 0x7944, 0xa184, 0x0100, 0x2001, 0x0006,
+	0x686e, 0x00c0, 0x4dcf, 0x6986, 0x2001, 0x0004, 0x686e, 0x1078,
+	0x226a, 0x2091, 0x8001, 0x007c, 0x2069, 0x0100, 0x2009, 0x5240,
+	0x2104, 0xa084, 0x0007, 0x0040, 0x4e30, 0xa086, 0x0007, 0x00c0,
+	0x4dea, 0x0d7e, 0x2009, 0x5252, 0x216c, 0x1078, 0x3b1c, 0x0d7f,
+	0x0078, 0x4e30, 0x2009, 0x5252, 0x2164, 0x1078, 0x2437, 0x601b,
+	0x0006, 0x6858, 0xa084, 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff,
+	0xa085, 0x0048, 0x6022, 0x602f, 0x0000, 0x6033, 0x0000, 0x6830,
+	0xa084, 0x0040, 0x0040, 0x4e24, 0x684b, 0x0004, 0x20a9, 0x0014,
+	0x6848, 0xa084, 0x0004, 0x0040, 0x4e11, 0x0070, 0x4e11, 0x0078,
+	0x4e08, 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0001,
+	0x0040, 0x4e1e, 0x0070, 0x4e1e, 0x0078, 0x4e15, 0x20a9, 0x00fa,
+	0x0070, 0x4e24, 0x0078, 0x4e20, 0x6808, 0xa084, 0xfffd, 0x680a,
+	0x681b, 0x0048, 0x2009, 0x525b, 0x200b, 0x0007, 0x784c, 0x784a,
+	0x2091, 0x8001, 0x007c, 0x2079, 0x5200, 0x1078, 0x4e5e, 0x1078,
+	0x4e42, 0x1078, 0x4e50, 0x7833, 0x0000, 0x7847, 0x0000, 0x784b,
+	0x0000, 0x007c, 0x2019, 0x0003, 0x2011, 0x5246, 0x2204, 0xa086,
+	0x003c, 0x0040, 0x4e4d, 0x2019, 0x0002, 0x7b2a, 0x7b2e, 0x007c,
+	0x2019, 0x0039, 0x2011, 0x5246, 0x2204, 0xa086, 0x003c, 0x0040,
+	0x4e5b, 0x2019, 0x0027, 0x7b36, 0x7b3a, 0x007c, 0x2019, 0x3971,
+	0x2011, 0x5246, 0x2204, 0xa086, 0x003c, 0x0040, 0x4e69, 0x2019,
+	0x2626, 0x7b22, 0x7b26, 0x783f, 0x0000, 0x7843, 0x000a, 0x007c,
+	0x0020, 0x002b, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+	0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+	0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+	0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+	0x0000, 0x0020, 0x0000, 0x0014, 0x0014, 0x9849, 0x0014, 0x0014,
+	0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0080, 0x000f, 0x0000,
+	0x0201, 0x0604, 0x0c08, 0x2120, 0x4022, 0xf880, 0x0018, 0x300b,
+	0xa201, 0x0014, 0xa200, 0x0014, 0xa200, 0x0214, 0x0000, 0x006c,
+	0x0002, 0x0014, 0x98cd, 0x009e, 0x0093, 0xa202, 0x8838, 0x3806,
+	0x8839, 0x20c3, 0x0864, 0x9885, 0x28c1, 0x9cae, 0xa203, 0x300c,
+	0x2846, 0x8161, 0x846a, 0x8300, 0x1856, 0x883a, 0x9865, 0x28f2,
+	0x9c91, 0x9858, 0x300c, 0x28e1, 0x9c91, 0x2802, 0xa206, 0x64c3,
+	0x282e, 0xa207, 0x64a0, 0x6de0, 0x67a0, 0x6fc0, 0x1814, 0x883b,
+	0x7824, 0x68c1, 0x7864, 0x883e, 0x9879, 0x8576, 0x8677, 0x206b,
+	0x28c1, 0x9cae, 0x2044, 0x2103, 0x20a2, 0x2081, 0x9865, 0xa209,
+	0x2901, 0x988d, 0x0014, 0xa205, 0xa300, 0x1872, 0x879a, 0x883c,
+	0x1fe2, 0xc601, 0xa20a, 0x856e, 0x0704, 0x9c91, 0x0014, 0xa204,
+	0xa300, 0x3009, 0x19e2, 0xf864, 0x856e, 0x883f, 0x08e6, 0x9891,
+	0xf881, 0x988c, 0xc801, 0x0014, 0xf8c1, 0x0016, 0x85b2, 0x80f0,
+	0x9532, 0xfb02, 0x1de2, 0x0014, 0x8532, 0xf241, 0x0014, 0x1de2,
+	0x84a8, 0xd7a0, 0x1fe6, 0x0014, 0xa208, 0x6043, 0x8008, 0x1dc1,
+	0x0016, 0x8300, 0x8160, 0x842a, 0xf041, 0x3008, 0x84a8, 0x11d6,
+	0x7042, 0x20dd, 0x0011, 0x20d5, 0x8822, 0x0016, 0x8000, 0x2847,
+	0x1011, 0x98c0, 0x8000, 0xa000, 0x2802, 0x1011, 0x98c6, 0x9865,
+	0x283e, 0x1011, 0x98ca, 0xa20b, 0x0017, 0x300c, 0xa300, 0x1de2,
+	0xdb81, 0x0014, 0x0210, 0x98d7, 0x0014, 0x26e0, 0x873a, 0xfb02,
+	0x19f2, 0x1fe2, 0x0014, 0xa20d, 0x3806, 0x0210, 0x9cb3, 0x0704,
+	0x0000, 0x006c, 0x0002, 0x984f, 0x0014, 0x009e, 0x00a0, 0x0017,
+	0x60ff, 0x300c, 0x8720, 0xa211, 0x9cd0, 0x8772, 0x8837, 0x2101,
+	0x987a, 0x10d2, 0x78e2, 0x9cd3, 0x9859, 0xd984, 0xf0e2, 0xf0a1,
+	0x98cd, 0x0014, 0x8831, 0xd166, 0x8830, 0x800f, 0x9401, 0xb520,
+	0xc802, 0x8820, 0x987a, 0x2301, 0x987a, 0x10d2, 0x78e4, 0x9cd3,
+	0x8821, 0x8820, 0x9859, 0xf123, 0xf142, 0xf101, 0x98c6, 0x10d2,
+	0x70f6, 0x8832, 0x8203, 0x870c, 0xd99e, 0x6001, 0x0014, 0x6845,
+	0x0214, 0xa21b, 0x9cd0, 0x2001, 0x98c5, 0x8201, 0x1852, 0xd184,
+	0xd163, 0x8834, 0x8001, 0x988d, 0x3027, 0x84a8, 0x1a56, 0x8833,
+	0x0014, 0xa218, 0x6981, 0x9cbc, 0x6926, 0x6902, 0x1a34, 0x9899,
+	0x1a14, 0x7021, 0x0014, 0xa300, 0x6141, 0x6964, 0x8010, 0x8592,
+	0x8026, 0x84b9, 0x69e4, 0x8023, 0x16e1, 0x8001, 0x10f1, 0x6946,
+	0xa213, 0x1462, 0xa213, 0x8000, 0x16e1, 0x98b5, 0x6969, 0xa214,
+	0x61c2, 0x8002, 0x14e1, 0x8004, 0x16e1, 0x0101, 0x300a, 0x8827,
+	0x0014, 0xa217, 0x9cbc, 0x0014, 0xa300, 0x8181, 0x842a, 0x84a8,
+	0x1ce6, 0x882c, 0x0016, 0xa212, 0x9cd0, 0x10d2, 0x70e4, 0x0004,
+	0x8007, 0x9424, 0xcc1a, 0x9cd3, 0x98c5, 0x8827, 0x300a, 0x0013,
+	0x8000, 0x84a4, 0x0016, 0x11c2, 0x211e, 0x870e, 0xa21d, 0x0014,
+	0x878e, 0x0016, 0xa21c, 0x1035, 0x9891, 0xa210, 0xa000, 0x8010,
+	0x8592, 0x853b, 0xd044, 0x8022, 0x3807, 0x84bb, 0x98ea, 0x8021,
+	0x3807, 0x84b9, 0x300c, 0x817e, 0x872b, 0x8772, 0x9891, 0x0000,
+	0x0020, 0x002b, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+	0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+	0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+	0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
+	0x0000, 0x0020, 0x0000, 0x0014, 0x0014, 0x9849, 0x0014, 0x0014,
+	0x98e2, 0x98cd, 0x0014, 0x0014, 0x0014, 0x0080, 0x0137, 0x0000,
+	0x0201, 0x0604, 0x0c08, 0x2120, 0x4022, 0xf880, 0x0018, 0x300b,
+	0xa201, 0x0014, 0xa200, 0x0014, 0xa200, 0x0214, 0xa202, 0x8838,
+	0x3806, 0x8839, 0x20c3, 0x0864, 0xa82f, 0x28c1, 0x9cae, 0xa203,
+	0x300c, 0x2846, 0x8161, 0x846a, 0x8300, 0x1856, 0x883a, 0xa804,
+	0x28f2, 0x9c91, 0xa8f4, 0x300c, 0x28e1, 0x9c91, 0x2802, 0xa206,
+	0x64c3, 0x282e, 0xa207, 0x64a0, 0x6de0, 0x67a0, 0x6fc0, 0x1814,
+	0x883b, 0x7824, 0x68c1, 0x7864, 0x883e, 0xa802, 0x8576, 0x8677,
+	0x206b, 0x28c1, 0x9cae, 0x2044, 0x2103, 0x20a2, 0x2081, 0xa8e4,
+	0xa209, 0x2901, 0xa809, 0x0014, 0xa205, 0xa300, 0x1872, 0x879a,
+	0x883c, 0x1fe2, 0xc601, 0xa20a, 0x856e, 0x0704, 0x9c91, 0x0014,
+	0xa204, 0xa300, 0x3009, 0x19e2, 0xf864, 0x856e, 0x883f, 0x08e6,
+	0xa8f7, 0xf881, 0xa8f0, 0xc801, 0x0014, 0xf8c1, 0x0016, 0x85b2,
+	0x80f0, 0x9532, 0xfb02, 0x1de2, 0x0014, 0x8532, 0xf241, 0x0014,
+	0x1de2, 0x84a8, 0xd7a0, 0x1fe6, 0x0014, 0xa208, 0x6043, 0x8008,
+	0x1dc1, 0x0016, 0x8300, 0x8160, 0x842a, 0xf041, 0x3008, 0x84a8,
+	0x11d6, 0x7042, 0x20dd, 0x0011, 0x20d5, 0x8822, 0x0016, 0x8000,
+	0x2847, 0x1011, 0xa8fc, 0x8000, 0xa000, 0x2802, 0x1011, 0xa8fd,
+	0xa89b, 0x283e, 0x1011, 0xa8fd, 0xa20b, 0x0017, 0x300c, 0xa300,
+	0x1de2, 0xdb81, 0x0014, 0x0210, 0xa801, 0x0014, 0x26e0, 0x873a,
+	0xfb02, 0x19f2, 0x1fe2, 0x0014, 0xa20d, 0x3806, 0x0210, 0x9cb3,
+	0x0704, 0x0017, 0x60ff, 0x300c, 0x8720, 0xa211, 0x9d63, 0x8772,
+	0x8837, 0x2101, 0xa821, 0x10d2, 0x78e2, 0x9d66, 0xa8fc, 0xd984,
+	0xf0e2, 0xf0a1, 0xa86c, 0x0014, 0x8831, 0xd166, 0x8830, 0x800f,
+	0x9401, 0xb520, 0xc802, 0x8820, 0xa80f, 0x2301, 0xa80d, 0x10d2,
+	0x78e4, 0x9d66, 0x8821, 0x8820, 0xa8e6, 0xf123, 0xf142, 0xf101,
+	0xa84f, 0x10d2, 0x70f6, 0x8832, 0x8203, 0x870c, 0xd99e, 0x6001,
+	0x0014, 0x6845, 0x0214, 0xa21b, 0x9d63, 0x2001, 0xa840, 0x8201,
+	0x1852, 0xd184, 0xd163, 0x8834, 0x8001, 0xa801, 0x3027, 0x84a8,
+	0x1a56, 0x8833, 0x0014, 0xa218, 0x6981, 0x9d4f, 0x6926, 0x6902,
+	0x1a34, 0xa801, 0x1a14, 0x7021, 0x0014, 0xa300, 0x6141, 0x6964,
+	0x8010, 0x8592, 0x8026, 0x84b9, 0x69e4, 0x8023, 0x16e1, 0x8001,
+	0x10f1, 0x6946, 0xa213, 0x1462, 0xa213, 0x8000, 0x16e1, 0xa807,
+	0x6969, 0xa214, 0x61c2, 0x8002, 0x14e1, 0x8004, 0x16e1, 0x0101,
+	0x300a, 0x8827, 0x0014, 0xa217, 0x9d4f, 0x0014, 0xa300, 0x8181,
+	0x842a, 0x84a8, 0x1ce6, 0x882c, 0x0016, 0xa212, 0x9d63, 0x10d2,
+	0x70e4, 0x0004, 0x8007, 0x9424, 0xcc1a, 0x9d66, 0xa8f8, 0x8827,
+	0x300a, 0x0013, 0x8000, 0x84a4, 0x0016, 0x11c2, 0x211e, 0x870e,
+	0xa21d, 0x0014, 0x878e, 0x0016, 0xa21c, 0x1035, 0xa8b4, 0xa210,
+	0x3807, 0x300c, 0x817e, 0x872b, 0x8772, 0xa8ad, 0x0000, 0x0d0c
 };
-static unsigned short   risc_code_length01 = 0x4057;
-
+static unsigned short risc_code_length01 = 0x4158;
diff --git a/drivers/scsi/ql12160_fw.h b/drivers/scsi/ql12160_fw.h
index 9db6a20..d89dac0 100644
--- a/drivers/scsi/ql12160_fw.h
+++ b/drivers/scsi/ql12160_fw.h
@@ -22,19 +22,19 @@
  ************************************************************************/
 
 /*
- *	Firmware Version 10.04.32 (12:03 May 09, 2001)
+ *	Firmware Version 10.04.42 (15:44 Apr 18, 2003)
  */
 
 #ifdef UNIQUE_FW_NAME
-static unsigned char fw12160i_version_str[] = {10,4,32};
+static unsigned char fw12160i_version_str[] = {10,4,42};
 #else
-static unsigned char firmware_version[] = {10,4,32};
+static unsigned char firmware_version[] = {10,4,42};
 #endif
 
 #ifdef UNIQUE_FW_NAME
-#define fw12160i_VERSION_STRING "10.04.32"
+#define fw12160i_VERSION_STRING "10.04.42"
 #else
-#define FW_VERSION_STRING "10.04.32"
+#define FW_VERSION_STRING "10.04.42"
 #endif
 
 #ifdef UNIQUE_FW_NAME
@@ -48,7 +48,7 @@
 #else
 static unsigned short risc_code01[] = {
 #endif
-	0x0804, 0x1041, 0x0000, 0x35e6, 0x0000, 0x2043, 0x4f50, 0x5952,
+	0x0804, 0x1041, 0x0000, 0x36c9, 0x0000, 0x2043, 0x4f50, 0x5952,
 	0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932, 0x2c31,
 	0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749, 0x4320,
 	0x434f, 0x5250, 0x4f52, 0x4154, 0x494f, 0x4e00, 0x2049, 0x5350,
@@ -56,112 +56,112 @@
 	0x6572, 0x7369, 0x6f6e, 0x2031, 0x302e, 0x3034, 0x2020, 0x2043,
 	0x7573, 0x746f, 0x6d65, 0x7220, 0x4e6f, 0x2e20, 0x3030, 0x2050,
 	0x726f, 0x6475, 0x6374, 0x204e, 0x6f2e, 0x2020, 0x3030, 0x2020,
-	0x2400, 0x20c9, 0x8fff, 0x2071, 0x0200, 0x70a0, 0x70a2, 0x2001,
+	0x2400, 0x20c9, 0x90ff, 0x2071, 0x0200, 0x70a0, 0x70a2, 0x2001,
 	0x01ff, 0x2004, 0xd0fc, 0x1120, 0x2071, 0x0100, 0x70a0, 0x70a2,
 	0x20c1, 0x0020, 0x2089, 0x1221, 0x2071, 0x0010, 0x70c3, 0x0004,
 	0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, 0x000a,
 	0x2001, 0x04fd, 0x2004, 0x70d6, 0x2009, 0xfeff, 0x2130, 0x2128,
-	0xa1a2, 0x4600, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424,
-	0xa192, 0x9000, 0x2009, 0x0000, 0x2001, 0x0032, 0x080c, 0x1de8,
-	0x2218, 0x2079, 0x4600, 0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9,
+	0xa1a2, 0x4700, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424,
+	0xa192, 0x9100, 0x2009, 0x0000, 0x2001, 0x0032, 0x080c, 0x1e05,
+	0x2218, 0x2079, 0x4700, 0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9,
 	0x0040, 0x42a4, 0x8109, 0x1dd8, 0x2009, 0xff00, 0x3400, 0xa102,
 	0x0218, 0x0110, 0x20a8, 0x42a4, 0x781b, 0x0064, 0x7814, 0xc0cd,
-	0xc0d5, 0x7816, 0x2071, 0x0200, 0x00d6, 0x2069, 0x4640, 0x080c,
-	0x459a, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1130, 0x2069, 0x4680,
-	0x2071, 0x0100, 0x080c, 0x459a, 0x7814, 0xc0d4, 0x7816, 0x00de,
+	0xc0d5, 0x7816, 0x2071, 0x0200, 0x00d6, 0x2069, 0x4740, 0x080c,
+	0x465c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1130, 0x2069, 0x4780,
+	0x2071, 0x0100, 0x080c, 0x465c, 0x7814, 0xc0d4, 0x7816, 0x00de,
 	0x7eca, 0x7cc2, 0x7bc6, 0x7867, 0x0000, 0x7800, 0xc08d, 0x7802,
 	0x2031, 0x0030, 0x78af, 0x0101, 0x7823, 0x0002, 0x7827, 0x0002,
-	0x2009, 0x0002, 0x2069, 0x4640, 0x681b, 0x0003, 0x6823, 0x0007,
+	0x2009, 0x0002, 0x2069, 0x4740, 0x681b, 0x0003, 0x6823, 0x0007,
 	0x6827, 0x00fa, 0x682b, 0x0008, 0x682f, 0x0028, 0x6837, 0x0006,
 	0x6833, 0x0008, 0x683b, 0x0000, 0x8109, 0x0500, 0x68cf, 0x000a,
-	0x68bf, 0x46c0, 0x2079, 0x4600, 0x68d3, 0x762d, 0x68c3, 0x4bc0,
-	0x68c7, 0x4ac0, 0x68cb, 0x8bc0, 0x68a7, 0x8e44, 0x68ab, 0x8e49,
-	0x68af, 0x8e44, 0x68b3, 0x8e44, 0x68a3, 0x0001, 0x2001, 0x01ff,
-	0x2004, 0xd0fc, 0x11c8, 0x2069, 0x4680, 0x0870, 0x68cf, 0x000a,
-	0x68bf, 0x48c0, 0x68d3, 0x7839, 0x68c3, 0x6bc0, 0x68c7, 0x4b40,
-	0x68cb, 0x8cd0, 0x68a7, 0x8e49, 0x68ab, 0x8e4e, 0x68af, 0x8e49,
-	0x68b3, 0x8e49, 0x68a3, 0x0001, 0x00e6, 0x2069, 0x4ac0, 0x2071,
+	0x68bf, 0x47c0, 0x2079, 0x4700, 0x68d3, 0x762d, 0x68c3, 0x4cc0,
+	0x68c7, 0x4bc0, 0x68cb, 0x8cc0, 0x68a7, 0x8f44, 0x68ab, 0x8f49,
+	0x68af, 0x8f44, 0x68b3, 0x8f44, 0x68a3, 0x0001, 0x2001, 0x01ff,
+	0x2004, 0xd0fc, 0x11c8, 0x2069, 0x4780, 0x0870, 0x68cf, 0x000a,
+	0x68bf, 0x49c0, 0x68d3, 0x7839, 0x68c3, 0x6cc0, 0x68c7, 0x4c40,
+	0x68cb, 0x8dd0, 0x68a7, 0x8f49, 0x68ab, 0x8f4e, 0x68af, 0x8f49,
+	0x68b3, 0x8f49, 0x68a3, 0x0001, 0x00e6, 0x2069, 0x4bc0, 0x2071,
 	0x0200, 0x70ec, 0xd0e4, 0x2019, 0x1809, 0x2021, 0x0009, 0x1120,
-	0x2019, 0x180c, 0x2021, 0x000c, 0x080c, 0x1d58, 0x2001, 0x01ff,
-	0x2004, 0xd0fc, 0x1188, 0x2069, 0x4b40, 0x2071, 0x0100, 0x70ec,
+	0x2019, 0x180c, 0x2021, 0x000c, 0x080c, 0x1d75, 0x2001, 0x01ff,
+	0x2004, 0xd0fc, 0x1188, 0x2069, 0x4c40, 0x2071, 0x0100, 0x70ec,
 	0xd0e4, 0x2019, 0x1809, 0x2021, 0x0009, 0x1120, 0x2019, 0x180c,
-	0x2021, 0x000c, 0x080c, 0x1d58, 0x00ee, 0x2011, 0x0002, 0x2069,
-	0x4bc0, 0x2009, 0x0002, 0x20a9, 0x0100, 0x6837, 0x0000, 0x680b,
+	0x2021, 0x000c, 0x080c, 0x1d75, 0x00ee, 0x2011, 0x0002, 0x2069,
+	0x4cc0, 0x2009, 0x0002, 0x20a9, 0x0100, 0x6837, 0x0000, 0x680b,
 	0x0040, 0x7bc8, 0xa386, 0xfeff, 0x1128, 0x6817, 0x0100, 0x681f,
 	0x0064, 0x0020, 0x6817, 0x0064, 0x681f, 0x0002, 0xade8, 0x0010,
 	0x1f04, 0x1135, 0x8109, 0x1d38, 0x2001, 0x01ff, 0x2004, 0xd0fc,
-	0x1128, 0x8211, 0x0118, 0x2069, 0x6bc0, 0x08d8, 0x080c, 0x22cf,
-	0x080c, 0x4015, 0x080c, 0x1b6d, 0x080c, 0x4553, 0x2091, 0x2200,
-	0x2079, 0x4600, 0x2071, 0x0050, 0x2091, 0x2400, 0x2079, 0x4600,
-	0x2071, 0x0020, 0x2091, 0x2600, 0x2079, 0x0200, 0x2071, 0x4640,
-	0x2091, 0x2800, 0x2079, 0x0100, 0x2071, 0x4680, 0x2091, 0x2000,
-	0x2079, 0x4600, 0x2071, 0x0010, 0x3200, 0xa085, 0x303d, 0x2090,
+	0x1128, 0x8211, 0x0118, 0x2069, 0x6cc0, 0x08d8, 0x080c, 0x22f6,
+	0x080c, 0x403d, 0x080c, 0x1b8c, 0x080c, 0x4615, 0x2091, 0x2200,
+	0x2079, 0x4700, 0x2071, 0x0050, 0x2091, 0x2400, 0x2079, 0x4700,
+	0x2071, 0x0020, 0x2091, 0x2600, 0x2079, 0x0200, 0x2071, 0x4740,
+	0x2091, 0x2800, 0x2079, 0x0100, 0x2071, 0x4780, 0x2091, 0x2000,
+	0x2079, 0x4700, 0x2071, 0x0010, 0x3200, 0xa085, 0x303d, 0x2090,
 	0x2071, 0x0010, 0x70c3, 0x0000, 0x1004, 0x118c, 0x70c0, 0xa086,
 	0x0002, 0x1110, 0x080c, 0x13ba, 0x2039, 0x0000, 0x080c, 0x12ab,
 	0x78ac, 0xa005, 0x1180, 0x0e04, 0x119a, 0x786c, 0xa065, 0x0110,
-	0x080c, 0x207a, 0x080c, 0x1e09, 0x0e04, 0x11af, 0x786c, 0xa065,
-	0x0110, 0x080c, 0x207a, 0x0e04, 0x11af, 0x2009, 0x4647, 0x2011,
-	0x4687, 0x2104, 0x220c, 0xa105, 0x0110, 0x080c, 0x1c7c, 0x2071,
-	0x4640, 0x70a0, 0xa005, 0x01e8, 0x744c, 0xa485, 0x0000, 0x01c8,
+	0x080c, 0x20a1, 0x080c, 0x1e26, 0x0e04, 0x11af, 0x786c, 0xa065,
+	0x0110, 0x080c, 0x20a1, 0x0e04, 0x11af, 0x2009, 0x4747, 0x2011,
+	0x4787, 0x2104, 0x220c, 0xa105, 0x0110, 0x080c, 0x1c9b, 0x2071,
+	0x4740, 0x70a0, 0xa005, 0x01e8, 0x744c, 0xa485, 0x0000, 0x01c8,
 	0x2079, 0x0200, 0x2091, 0x8000, 0x72d0, 0xa28c, 0x303d, 0x2190,
-	0x080c, 0x2720, 0x2091, 0x8000, 0x2091, 0x303d, 0x0e04, 0x11d1,
-	0x2079, 0x4600, 0x786c, 0xa065, 0x0120, 0x2071, 0x0010, 0x080c,
-	0x207a, 0x1d04, 0x11d9, 0x2079, 0x4600, 0x2071, 0x0010, 0x080c,
-	0x4370, 0x2071, 0x4680, 0x70a0, 0xa005, 0x0188, 0x704c, 0xa025,
+	0x080c, 0x274c, 0x2091, 0x8000, 0x2091, 0x303d, 0x0e04, 0x11d1,
+	0x2079, 0x4700, 0x786c, 0xa065, 0x0120, 0x2071, 0x0010, 0x080c,
+	0x20a1, 0x1d04, 0x11d9, 0x2079, 0x4700, 0x2071, 0x0010, 0x080c,
+	0x4429, 0x2071, 0x4780, 0x70a0, 0xa005, 0x0188, 0x704c, 0xa025,
 	0x0170, 0x2079, 0x0100, 0x2091, 0x8000, 0x72d0, 0xa28c, 0x303d,
-	0x2190, 0x080c, 0x2720, 0x2091, 0x8000, 0x2091, 0x303d, 0x2079,
-	0x4600, 0x2071, 0x0010, 0x0e04, 0x11fa, 0x786c, 0xa065, 0x0110,
-	0x080c, 0x207a, 0x1d04, 0x118e, 0x080c, 0x4370, 0x0804, 0x118e,
+	0x2190, 0x080c, 0x274c, 0x2091, 0x8000, 0x2091, 0x303d, 0x2079,
+	0x4700, 0x2071, 0x0010, 0x0e04, 0x11fa, 0x786c, 0xa065, 0x0110,
+	0x080c, 0x20a1, 0x1d04, 0x118e, 0x080c, 0x4429, 0x0804, 0x118e,
 	0x3c00, 0xa084, 0x0007, 0x0002, 0x120c, 0x120c, 0x120e, 0x120e,
-	0x1213, 0x1213, 0x1218, 0x1218, 0x080c, 0x254c, 0x2091, 0x2400,
-	0x080c, 0x40ad, 0x0005, 0x2091, 0x2200, 0x080c, 0x40ad, 0x0005,
-	0x2091, 0x2200, 0x080c, 0x40ad, 0x2091, 0x2400, 0x080c, 0x40ad,
+	0x1213, 0x1213, 0x1218, 0x1218, 0x080c, 0x2575, 0x2091, 0x2400,
+	0x080c, 0x40d5, 0x0005, 0x2091, 0x2200, 0x080c, 0x40d5, 0x0005,
+	0x2091, 0x2200, 0x080c, 0x40d5, 0x2091, 0x2400, 0x080c, 0x40d5,
 	0x0005, 0x1241, 0x1241, 0x1242, 0x1242, 0x124d, 0x124d, 0x124d,
 	0x124d, 0x1256, 0x1256, 0x1261, 0x1261, 0x124d, 0x124d, 0x124d,
 	0x124d, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270,
 	0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270,
 	0x1270, 0x0cf8, 0x0006, 0x0106, 0x0126, 0x2091, 0x2800, 0x080c,
-	0x2569, 0x012e, 0x010e, 0x000e, 0x000d, 0x0006, 0x0106, 0x0126,
+	0x2592, 0x012e, 0x010e, 0x000e, 0x000d, 0x0006, 0x0106, 0x0126,
 	0x080c, 0x1200, 0x012e, 0x010e, 0x000e, 0x000d, 0x0006, 0x0106,
-	0x0126, 0x2091, 0x2600, 0x080c, 0x2569, 0x012e, 0x010e, 0x000e,
-	0x000d, 0x0006, 0x0106, 0x0126, 0x2091, 0x2600, 0x080c, 0x2569,
-	0x2091, 0x2800, 0x080c, 0x2569, 0x012e, 0x010e, 0x000e, 0x000d,
-	0x0006, 0x0106, 0x0126, 0x00d6, 0x00e6, 0x00f6, 0x2079, 0x4600,
-	0x2071, 0x0200, 0x2069, 0x4640, 0x3d00, 0xd08c, 0x0130, 0x70ec,
-	0xa084, 0x1c00, 0x78e2, 0x080c, 0x459a, 0x3d00, 0xd084, 0x0150,
-	0x2069, 0x4680, 0x2071, 0x0100, 0x70ec, 0xa084, 0x1c00, 0x78e6,
-	0x080c, 0x459a, 0x080c, 0x24fd, 0x00fe, 0x00ee, 0x00de, 0x012e,
+	0x0126, 0x2091, 0x2600, 0x080c, 0x2592, 0x012e, 0x010e, 0x000e,
+	0x000d, 0x0006, 0x0106, 0x0126, 0x2091, 0x2600, 0x080c, 0x2592,
+	0x2091, 0x2800, 0x080c, 0x2592, 0x012e, 0x010e, 0x000e, 0x000d,
+	0x0006, 0x0106, 0x0126, 0x00d6, 0x00e6, 0x00f6, 0x2079, 0x4700,
+	0x2071, 0x0200, 0x2069, 0x4740, 0x3d00, 0xd08c, 0x0130, 0x70ec,
+	0xa084, 0x1c00, 0x78e2, 0x080c, 0x465c, 0x3d00, 0xd084, 0x0150,
+	0x2069, 0x4780, 0x2071, 0x0100, 0x70ec, 0xa084, 0x1c00, 0x78e6,
+	0x080c, 0x465c, 0x080c, 0x2526, 0x00fe, 0x00ee, 0x00de, 0x012e,
 	0x010e, 0x000e, 0x000d, 0x7008, 0x800b, 0x1240, 0x7007, 0x0002,
 	0xa08c, 0x01e0, 0x1120, 0xd09c, 0x0108, 0x0887, 0x0897, 0x70c3,
 	0x4002, 0x0804, 0x13bd, 0x0e04, 0x131e, 0x2061, 0x0000, 0x6018,
 	0xd084, 0x1904, 0x131e, 0x7828, 0xa005, 0x1120, 0x0004, 0x131f,
-	0x0804, 0x131e, 0xd0fc, 0x0130, 0x0006, 0x080c, 0x1b0a, 0x000e,
-	0x0150, 0x0028, 0x0006, 0x080c, 0x1aff, 0x000e, 0x0120, 0x2001,
-	0x4007, 0x0804, 0x13bc, 0x7910, 0xd0fc, 0x1128, 0x2061, 0x4640,
-	0xc19c, 0xc7fc, 0x0020, 0x2061, 0x4680, 0xc19d, 0xc7fd, 0x6060,
+	0x0804, 0x131e, 0xd0fc, 0x0130, 0x0006, 0x080c, 0x1b29, 0x000e,
+	0x0150, 0x0028, 0x0006, 0x080c, 0x1b1e, 0x000e, 0x0120, 0x2001,
+	0x4007, 0x0804, 0x13bc, 0x7910, 0xd0fc, 0x1128, 0x2061, 0x4740,
+	0xc19c, 0xc7fc, 0x0020, 0x2061, 0x4780, 0xc19d, 0xc7fd, 0x6060,
 	0xa005, 0x1904, 0x131e, 0x7912, 0x607e, 0x7828, 0xc0fc, 0xa086,
-	0x0018, 0x1120, 0x00c6, 0x080c, 0x1916, 0x00ce, 0x782b, 0x0000,
-	0x6078, 0xa065, 0x01e0, 0x00c6, 0x609c, 0x080c, 0x1bd4, 0x00ce,
-	0x609f, 0x0000, 0x080c, 0x1a41, 0x2009, 0x0018, 0x6087, 0x0103,
+	0x0018, 0x1120, 0x00c6, 0x080c, 0x1926, 0x00ce, 0x782b, 0x0000,
+	0x6078, 0xa065, 0x01e0, 0x00c6, 0x609c, 0x080c, 0x1bf3, 0x00ce,
+	0x609f, 0x0000, 0x080c, 0x1a60, 0x2009, 0x0018, 0x6087, 0x0103,
 	0x7810, 0x0006, 0x84ff, 0x1110, 0x85ff, 0x0110, 0xc0c5, 0x7812,
-	0x080c, 0x1b15, 0x000e, 0x7812, 0x1198, 0x080c, 0x1b60, 0x7810,
-	0xd09c, 0x1118, 0x2061, 0x4640, 0x0020, 0x2061, 0x4680, 0xc09c,
+	0x080c, 0x1b34, 0x000e, 0x7812, 0x1198, 0x080c, 0x1b7f, 0x7810,
+	0xd09c, 0x1118, 0x2061, 0x4740, 0x0020, 0x2061, 0x4780, 0xc09c,
 	0x7812, 0x607b, 0x0000, 0x60d0, 0xd0c4, 0x0130, 0xc0c4, 0x60d2,
 	0x2001, 0x4005, 0x0804, 0x13bc, 0x0804, 0x13ba, 0x0005, 0xa006,
 	0x70c2, 0x70c6, 0x70ca, 0x70ce, 0x70da, 0x70c0, 0xa03d, 0xa08a,
 	0x0040, 0x1a04, 0x136c, 0x0002, 0x13ba, 0x1408, 0x13d6, 0x143c,
-	0x1470, 0x1470, 0x13ce, 0x1a59, 0x147a, 0x13c8, 0x13da, 0x13db,
-	0x13dc, 0x13dd, 0x1a5d, 0x13c8, 0x1487, 0x14db, 0x1931, 0x1a53,
-	0x13de, 0x17ba, 0x17f0, 0x1822, 0x1868, 0x1777, 0x1784, 0x1797,
-	0x17a9, 0x15b0, 0x13c8, 0x150d, 0x1518, 0x1526, 0x1534, 0x154b,
-	0x1559, 0x155c, 0x156a, 0x1578, 0x1582, 0x1596, 0x15a2, 0x13c8,
-	0x13c8, 0x13c8, 0x13c8, 0x15bd, 0x15ce, 0x15e8, 0x161c, 0x1645,
-	0x1657, 0x165a, 0x1685, 0x16be, 0x16d0, 0x1745, 0x1755, 0x13c8,
-	0x13c8, 0x13c8, 0x13c8, 0x1767, 0x2100, 0xa08a, 0x0040, 0x1a04,
-	0x13c8, 0x0002, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x1a7f,
-	0x1a85, 0x13c8, 0x13c8, 0x13c8, 0x1a89, 0x1ac9, 0x13c8, 0x13c8,
-	0x13c8, 0x13c8, 0x1403, 0x146b, 0x1482, 0x14d6, 0x192c, 0x13c8,
-	0x13c8, 0x18fb, 0x13c8, 0x1acd, 0x1a71, 0x1a7b, 0x13c8, 0x13c8,
+	0x1470, 0x1470, 0x13ce, 0x1a78, 0x147a, 0x13c8, 0x13da, 0x13db,
+	0x13dc, 0x13dd, 0x1a7c, 0x13c8, 0x1487, 0x14db, 0x1941, 0x1a72,
+	0x13de, 0x17c8, 0x17fe, 0x1830, 0x1876, 0x1785, 0x1792, 0x17a5,
+	0x17b7, 0x15bf, 0x13c8, 0x150d, 0x1518, 0x1526, 0x1534, 0x154b,
+	0x1559, 0x155c, 0x156e, 0x157c, 0x1586, 0x15a5, 0x15b1, 0x13c8,
+	0x13c8, 0x13c8, 0x13c8, 0x15cc, 0x15dd, 0x15f7, 0x162b, 0x1654,
+	0x1666, 0x1669, 0x1693, 0x16cc, 0x16de, 0x1753, 0x1763, 0x13c8,
+	0x13c8, 0x13c8, 0x13c8, 0x1775, 0x2100, 0xa08a, 0x0040, 0x1a04,
+	0x13c8, 0x0002, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x1a9e,
+	0x1aa4, 0x13c8, 0x13c8, 0x13c8, 0x1aa8, 0x1ae8, 0x13c8, 0x13c8,
+	0x13c8, 0x13c8, 0x1403, 0x146b, 0x1482, 0x14d6, 0x193c, 0x13c8,
+	0x13c8, 0x190b, 0x13c8, 0x1aec, 0x1a90, 0x1a9a, 0x13c8, 0x13c8,
 	0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8,
 	0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8,
 	0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8,
@@ -191,7 +191,7 @@
 	0x0001, 0x7008, 0xd0fc, 0x0de8, 0xa084, 0x01e0, 0x0d48, 0x70c3,
 	0x4002, 0x0804, 0x13bd, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0878,
 	0x71c4, 0x70c8, 0x2114, 0xa79e, 0x0004, 0x1108, 0x200a, 0x72ca,
-	0x0804, 0x13b9, 0x70c7, 0x000a, 0x70cb, 0x0004, 0x70cf, 0x0020,
+	0x0804, 0x13b9, 0x70c7, 0x000a, 0x70cb, 0x0004, 0x70cf, 0x002a,
 	0x0804, 0x13ba, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0018, 0x2029,
 	0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d0, 0x70c6, 0x72ca,
 	0x73ce, 0x74d2, 0xa005, 0x05e8, 0xa40a, 0x0108, 0x1240, 0x8001,
@@ -211,1281 +211,1286 @@
 	0xc2c5, 0x7a12, 0x7c96, 0x78ac, 0xa084, 0xfcff, 0x78ae, 0x0018,
 	0x78ac, 0xc0c5, 0x78ae, 0x0804, 0x13ba, 0x2009, 0x0000, 0x786c,
 	0xa065, 0x0118, 0x8108, 0x6000, 0x0cd8, 0x7ac4, 0x0804, 0x13b8,
-	0x2009, 0x4648, 0x210c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904,
-	0x13b9, 0x2011, 0x4688, 0x2214, 0x0804, 0x13b8, 0x2009, 0x4649,
+	0x2009, 0x4748, 0x210c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904,
+	0x13b9, 0x2011, 0x4788, 0x2214, 0x0804, 0x13b8, 0x2009, 0x4749,
 	0x210c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x2011,
-	0x4689, 0x2214, 0x0804, 0x13b8, 0x2061, 0x4640, 0x6128, 0x622c,
+	0x4789, 0x2214, 0x0804, 0x13b8, 0x2061, 0x4740, 0x6128, 0x622c,
 	0x8214, 0x8214, 0x8214, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1148,
-	0x2061, 0x4680, 0x6328, 0x73da, 0x632c, 0x831c, 0x831c, 0x831c,
-	0x73de, 0x0804, 0x13b8, 0x2009, 0x464c, 0x210c, 0x2001, 0x01ff,
-	0x2004, 0xd0fc, 0x1904, 0x13b9, 0x2011, 0x468c, 0x2214, 0x0804,
-	0x13b8, 0x7918, 0x0804, 0x13b9, 0x2009, 0x0202, 0x210c, 0x2001,
-	0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x2011, 0x0102, 0x2214,
-	0x0804, 0x13b8, 0x2009, 0x464d, 0x210c, 0x2001, 0x01ff, 0x2004,
-	0xd0fc, 0x1904, 0x13b9, 0x2011, 0x468d, 0x2214, 0x0804, 0x13b8,
-	0x7920, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x7a24,
-	0x0804, 0x13b8, 0x2011, 0x4b40, 0x71c4, 0xd1fc, 0x1110, 0x2011,
-	0x4ac0, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa268,
-	0x6a00, 0x6b08, 0x6c1c, 0x74da, 0x0804, 0x13b7, 0x77c4, 0x080c,
-	0x1b7b, 0x2091, 0x8000, 0x6b1c, 0x6a14, 0x2091, 0x8001, 0x2708,
-	0x0804, 0x13b7, 0x2061, 0x4640, 0x6118, 0x2001, 0x01ff, 0x2004,
-	0xd0fc, 0x1904, 0x13b9, 0x2061, 0x4680, 0x6218, 0x0804, 0x13b8,
-	0x77c4, 0x080c, 0x1b7b, 0x2091, 0x8000, 0x6908, 0x6a18, 0x6b10,
-	0x77da, 0x2091, 0x8001, 0x0804, 0x13b7, 0x71c4, 0x2110, 0xa294,
-	0x000f, 0xa282, 0x0010, 0x1a04, 0x13b3, 0x080c, 0x238b, 0xa384,
-	0x4000, 0x0110, 0xa295, 0x0020, 0x0804, 0x13b7, 0x71c4, 0x2100,
-	0xc0bc, 0xa082, 0x0010, 0x1a04, 0x13b3, 0xd1bc, 0x1120, 0x2011,
-	0x4648, 0x2204, 0x0020, 0x2011, 0x4688, 0x2204, 0xc0bd, 0x0006,
-	0x2100, 0xc0bc, 0x2012, 0x080c, 0x2331, 0x001e, 0x0804, 0x13b9,
-	0x71c4, 0x2021, 0x4649, 0x2404, 0x70c6, 0x2019, 0x0000, 0x0030,
-	0x71c8, 0x2021, 0x4689, 0x2404, 0x70ca, 0xc3fd, 0x2011, 0x1614,
-	0x20a9, 0x0008, 0x2204, 0xa106, 0x0138, 0x8210, 0x1f04, 0x15fa,
-	0x71c4, 0x72c8, 0x0804, 0x13b2, 0xa292, 0x1614, 0x0026, 0x2122,
-	0x001e, 0x080c, 0x2343, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1110,
-	0xd3fc, 0x09f0, 0x0804, 0x13ba, 0x03e8, 0x00fa, 0x01f4, 0x02ee,
-	0x0004, 0x0001, 0x0002, 0x0003, 0x2061, 0x4640, 0x6128, 0x622c,
-	0x8214, 0x8214, 0x8214, 0x70c4, 0x602a, 0x70c8, 0x8003, 0x8003,
-	0x8003, 0x602e, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x11a0, 0x0026,
-	0x0016, 0x2061, 0x4680, 0x6128, 0x622c, 0x8214, 0x8214, 0x8214,
-	0x70d8, 0x602a, 0x70dc, 0x8003, 0x8003, 0x8003, 0x602e, 0x71da,
-	0x72de, 0x001e, 0x002e, 0x0804, 0x13b8, 0x2061, 0x4640, 0x6130,
-	0x70c4, 0x6032, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9,
-	0x2061, 0x4680, 0x6230, 0x70c8, 0x6032, 0x0804, 0x13b8, 0x7918,
-	0x0804, 0x13b9, 0x71c4, 0xa184, 0xf0cf, 0x0148, 0x2001, 0x01ff,
-	0x2004, 0xd0fc, 0x1904, 0x13b3, 0x72c8, 0x0804, 0x13b2, 0x0006,
-	0x2019, 0x0000, 0x080c, 0x237f, 0x2001, 0x01ff, 0x2004, 0xd0fc,
-	0x0118, 0x001e, 0x0804, 0x13b9, 0x71c8, 0xa184, 0xf0cf, 0x0128,
-	0x0006, 0x2110, 0x71c4, 0x0804, 0x13b2, 0x0006, 0xc3fd, 0x080c,
-	0x237f, 0x002e, 0x001e, 0x0804, 0x13b8, 0x71c4, 0xa182, 0x0010,
-	0x0248, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b3, 0x72c8,
-	0x0804, 0x13b2, 0x2011, 0x464d, 0x2204, 0x0006, 0x8104, 0x1208,
-	0x8108, 0x2112, 0x2019, 0x0000, 0x080c, 0x236c, 0x2001, 0x01ff,
-	0x2004, 0xd0fc, 0x0118, 0x001e, 0x0804, 0x13b9, 0x71c8, 0xa182,
-	0x0010, 0x0228, 0x0006, 0x2110, 0x71c4, 0x0804, 0x13b2, 0x2011,
-	0x468d, 0x2204, 0x0006, 0x8104, 0x1208, 0x8108, 0x2112, 0xc3fd,
-	0x080c, 0x236c, 0x002e, 0x001e, 0x0804, 0x13b8, 0x71c4, 0x72c8,
-	0xa184, 0xfffd, 0x1904, 0x13b2, 0xa284, 0xfffd, 0x1904, 0x13b2,
-	0x2100, 0x7920, 0x7822, 0x2200, 0x7a24, 0x7826, 0x0804, 0x13b8,
-	0x2011, 0x4b40, 0x71c4, 0xd1fc, 0x1110, 0x2011, 0x4ac0, 0x8107,
-	0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa268, 0x72c8, 0x73cc,
-	0x74d8, 0x71c6, 0x6800, 0x70ca, 0x73ce, 0x74da, 0x2091, 0x8000,
-	0x6a02, 0xd2ac, 0x1118, 0x2021, 0x0000, 0x0090, 0xa484, 0x00ff,
-	0xa082, 0x0002, 0x1a04, 0x1741, 0x843f, 0xa7bc, 0x00ff, 0x0140,
-	0xa786, 0x0002, 0x1904, 0x1741, 0xa484, 0x00ff, 0x0904, 0x1741,
-	0x2061, 0x0200, 0xd1fc, 0x0110, 0x2061, 0x0100, 0x2029, 0x0009,
-	0x2031, 0x0062, 0x843f, 0xa7bc, 0x00ff, 0x0130, 0x8307, 0xa084,
-	0x00ff, 0x1110, 0xa73d, 0x1138, 0x2041, 0x0019, 0xa384, 0x00ff,
-	0xa082, 0x001a, 0x0210, 0xa4a4, 0x00ff, 0x8307, 0xa084, 0x00ff,
-	0x0188, 0xa842, 0x02f0, 0xa086, 0x0010, 0x1120, 0xa39c, 0x00ff,
-	0xa39d, 0x0f00, 0xa3bc, 0x00ff, 0x2500, 0xa702, 0x0290, 0x2600,
-	0xa702, 0x1278, 0x2039, 0x003a, 0x6804, 0xa705, 0x6806, 0x6b0a,
-	0x6b0c, 0x73ce, 0x681c, 0x70da, 0x6c1e, 0x2091, 0x8001, 0x0804,
-	0x13ba, 0x2091, 0x8001, 0x0804, 0x13b4, 0x77c4, 0x080c, 0x1b7b,
-	0x2091, 0x8000, 0x6a14, 0x6b1c, 0x2091, 0x8001, 0x70c8, 0x6816,
-	0x70cc, 0x681e, 0x2708, 0x0804, 0x13b7, 0x70c4, 0x2061, 0x4640,
-	0x6118, 0x601a, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9,
-	0x70c8, 0x2061, 0x4680, 0x6218, 0x601a, 0x0804, 0x13b8, 0x71c4,
-	0x72c8, 0x73cc, 0xa182, 0x0010, 0x1a04, 0x13b3, 0x080c, 0x23af,
-	0xa384, 0x4000, 0x0110, 0xa295, 0x0020, 0x0804, 0x13b7, 0x77c4,
-	0x080c, 0x1b7b, 0x2091, 0x8000, 0x6a08, 0xc28d, 0x6a0a, 0x2091,
-	0x8001, 0x2708, 0x0804, 0x13b8, 0x77c4, 0x080c, 0x1b7b, 0x2091,
-	0x8000, 0x6a08, 0xa294, 0xfff9, 0x6a0a, 0x6804, 0xa005, 0x0110,
-	0x080c, 0x22ae, 0x2091, 0x8001, 0x2708, 0x0804, 0x13b8, 0x77c4,
-	0x080c, 0x1b7b, 0x2091, 0x8000, 0x6a08, 0xc295, 0x6a0a, 0x6804,
-	0xa005, 0x0110, 0x080c, 0x22ae, 0x2091, 0x8001, 0x2708, 0x0804,
-	0x13b8, 0x77c4, 0x2041, 0x0001, 0x2049, 0x0005, 0x2051, 0x0020,
-	0x2091, 0x8000, 0x080c, 0x1b93, 0x2091, 0x8001, 0x2708, 0x6a08,
-	0x0804, 0x13b8, 0x77c4, 0xd7fc, 0x0128, 0x080c, 0x1b0a, 0x0138,
-	0x0804, 0x13bc, 0x080c, 0x1aff, 0x0110, 0x0804, 0x13bc, 0x73c8,
-	0x72cc, 0x77c6, 0x73ca, 0x72ce, 0x080c, 0x1c0b, 0x11e8, 0x6818,
-	0xa005, 0x01a0, 0x2708, 0x0076, 0x080c, 0x23ce, 0x007e, 0x1170,
-	0x2001, 0x0015, 0xd7fc, 0x1118, 0x2061, 0x4640, 0x0018, 0xc0fd,
-	0x2061, 0x4680, 0x782a, 0x2091, 0x8001, 0x0005, 0x2091, 0x8001,
-	0x2001, 0x4005, 0x0804, 0x13bc, 0x2091, 0x8001, 0x0804, 0x13ba,
-	0x77c4, 0xd7fc, 0x0128, 0x080c, 0x1b0a, 0x0138, 0x0804, 0x13bc,
-	0x080c, 0x1aff, 0x0110, 0x0804, 0x13bc, 0x77c6, 0x2041, 0x0021,
-	0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x080c, 0x1b93,
-	0x2009, 0x0016, 0xd7fc, 0x1118, 0x2061, 0x4640, 0x0018, 0x2061,
-	0x4680, 0xc1fd, 0x6063, 0x0003, 0x607b, 0x0000, 0x6772, 0x607f,
-	0x000f, 0x792a, 0x61d0, 0xc1c4, 0x61d2, 0x080c, 0x22ae, 0x2091,
-	0x8001, 0x0005, 0x77c8, 0x77ca, 0x77c4, 0x77c6, 0xd7fc, 0x0128,
-	0x080c, 0x1b0a, 0x0138, 0x0804, 0x13bc, 0x080c, 0x1aff, 0x0110,
-	0x0804, 0x13bc, 0xa7bc, 0xff00, 0x2091, 0x8000, 0x2009, 0x0017,
-	0xd7fc, 0x1118, 0x2061, 0x4640, 0x0018, 0x2061, 0x4680, 0xc1fd,
-	0x607b, 0x0000, 0x6063, 0x0002, 0x6772, 0x607f, 0x000f, 0x792a,
-	0x61d0, 0xc1c4, 0x61d2, 0x080c, 0x22ae, 0x2091, 0x8001, 0x2041,
-	0x0021, 0x2049, 0x0005, 0x2051, 0x0030, 0x2091, 0x8000, 0x70c8,
-	0xa005, 0x0118, 0x60d0, 0xc0fd, 0x60d2, 0x080c, 0x1b93, 0x70c8,
-	0x6836, 0x8738, 0xa784, 0x001f, 0x1dc0, 0x2091, 0x8001, 0x0005,
-	0x2019, 0x0000, 0x72c8, 0xd284, 0x0128, 0x080c, 0x1b0a, 0x0138,
-	0x0804, 0x13bc, 0x080c, 0x1aff, 0x0110, 0x0804, 0x13bc, 0x72c8,
-	0x72ca, 0x78ac, 0xa084, 0x0003, 0x1508, 0x2039, 0x0000, 0xd284,
-	0x0108, 0xc7fd, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008,
-	0x080c, 0x1b7b, 0x2091, 0x8000, 0x6808, 0xc0d4, 0xa80d, 0x690a,
-	0x2091, 0x8001, 0x8738, 0xa784, 0x001f, 0x1d90, 0xa7bc, 0xff00,
-	0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x1d50, 0x2091, 0x8000,
+	0x2061, 0x4780, 0x6328, 0x73da, 0x632c, 0x831c, 0x831c, 0x831c,
+	0x73de, 0x0804, 0x13b8, 0x2009, 0x474c, 0x210c, 0x2001, 0x01ff,
+	0x2004, 0xd0fc, 0x1904, 0x13b9, 0x2011, 0x478c, 0x2214, 0x0804,
+	0x13b8, 0x7918, 0x0804, 0x13b9, 0x2009, 0x0202, 0x210c, 0xa18c,
+	0x0f30, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x2011,
+	0x0102, 0x2214, 0xa294, 0x0f30, 0x0804, 0x13b8, 0x2009, 0x474d,
+	0x210c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x2011,
+	0x478d, 0x2214, 0x0804, 0x13b8, 0x7920, 0x2001, 0x01ff, 0x2004,
+	0xd0fc, 0x1904, 0x13b9, 0x7a24, 0x0804, 0x13b8, 0x2011, 0x4c40,
+	0x71c4, 0xd1fc, 0x1110, 0x2011, 0x4bc0, 0x8107, 0xa084, 0x000f,
+	0x8003, 0x8003, 0x8003, 0xa268, 0x6a00, 0x6b08, 0x6c1c, 0x74da,
+	0xd1fc, 0x1118, 0x2021, 0x023b, 0x0010, 0x2021, 0x013b, 0x2424,
+	0xa4a4, 0x1c00, 0x74de, 0x0804, 0x13b7, 0x77c4, 0x080c, 0x1b9a,
+	0x2091, 0x8000, 0x6b1c, 0x6a14, 0x2091, 0x8001, 0x2708, 0x0804,
+	0x13b7, 0x2061, 0x4740, 0x6118, 0x2001, 0x01ff, 0x2004, 0xd0fc,
+	0x1904, 0x13b9, 0x2061, 0x4780, 0x6218, 0x0804, 0x13b8, 0x77c4,
+	0x080c, 0x1b9a, 0x2091, 0x8000, 0x6908, 0x6a18, 0x6b10, 0x77da,
+	0x2091, 0x8001, 0x0804, 0x13b7, 0x71c4, 0x2110, 0xa294, 0x000f,
+	0xa282, 0x0010, 0x1a04, 0x13b3, 0x080c, 0x23b4, 0xa384, 0x4000,
+	0x0110, 0xa295, 0x0020, 0x0804, 0x13b7, 0x71c4, 0x2100, 0xc0bc,
+	0xa082, 0x0010, 0x1a04, 0x13b3, 0xd1bc, 0x1120, 0x2011, 0x4748,
+	0x2204, 0x0020, 0x2011, 0x4788, 0x2204, 0xc0bd, 0x0006, 0x2100,
+	0xc0bc, 0x2012, 0x080c, 0x2358, 0x001e, 0x0804, 0x13b9, 0x71c4,
+	0x2021, 0x4749, 0x2404, 0x70c6, 0x2019, 0x0000, 0x0030, 0x71c8,
+	0x2021, 0x4789, 0x2404, 0x70ca, 0xc3fd, 0x2011, 0x1623, 0x20a9,
+	0x0008, 0x2204, 0xa106, 0x0138, 0x8210, 0x1f04, 0x1609, 0x71c4,
+	0x72c8, 0x0804, 0x13b2, 0xa292, 0x1623, 0x0026, 0x2122, 0x001e,
+	0x080c, 0x236a, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1110, 0xd3fc,
+	0x09f0, 0x0804, 0x13ba, 0x03e8, 0x00fa, 0x01f4, 0x02ee, 0x0004,
+	0x0001, 0x0002, 0x0003, 0x2061, 0x4740, 0x6128, 0x622c, 0x8214,
+	0x8214, 0x8214, 0x70c4, 0x602a, 0x70c8, 0x8003, 0x8003, 0x8003,
+	0x602e, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x11a0, 0x0026, 0x0016,
+	0x2061, 0x4780, 0x6128, 0x622c, 0x8214, 0x8214, 0x8214, 0x70d8,
+	0x602a, 0x70dc, 0x8003, 0x8003, 0x8003, 0x602e, 0x71da, 0x72de,
+	0x001e, 0x002e, 0x0804, 0x13b8, 0x2061, 0x4740, 0x6130, 0x70c4,
+	0x6032, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x2061,
+	0x4780, 0x6230, 0x70c8, 0x6032, 0x0804, 0x13b8, 0x7918, 0x0804,
+	0x13b9, 0x71c4, 0xa184, 0xf0cf, 0x0148, 0x2001, 0x01ff, 0x2004,
+	0xd0fc, 0x1904, 0x13b3, 0x72c8, 0x0804, 0x13b2, 0x2019, 0x0000,
+	0x080c, 0x23a6, 0x0036, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x0118,
+	0x001e, 0x0804, 0x13b9, 0x71c8, 0xa184, 0xf0cf, 0x0128, 0x000e,
+	0x2110, 0x71c4, 0x0804, 0x13b2, 0xc3fd, 0x080c, 0x23a6, 0x2310,
+	0x001e, 0x0804, 0x13b8, 0x71c4, 0xa182, 0x0010, 0x0248, 0x2001,
+	0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b3, 0x72c8, 0x0804, 0x13b2,
+	0x2011, 0x474d, 0x2204, 0x0006, 0x8104, 0x1208, 0x8108, 0x2112,
+	0x2019, 0x0000, 0x080c, 0x2393, 0x2001, 0x01ff, 0x2004, 0xd0fc,
+	0x0118, 0x001e, 0x0804, 0x13b9, 0x71c8, 0xa182, 0x0010, 0x0228,
+	0x0006, 0x2110, 0x71c4, 0x0804, 0x13b2, 0x2011, 0x478d, 0x2204,
+	0x0006, 0x8104, 0x1208, 0x8108, 0x2112, 0xc3fd, 0x080c, 0x2393,
+	0x002e, 0x001e, 0x0804, 0x13b8, 0x71c4, 0x72c8, 0xa184, 0xfffd,
+	0x1904, 0x13b2, 0xa284, 0xfffd, 0x1904, 0x13b2, 0x2100, 0x7920,
+	0x7822, 0x2200, 0x7a24, 0x7826, 0x0804, 0x13b8, 0x2011, 0x4c40,
+	0x71c4, 0xd1fc, 0x1110, 0x2011, 0x4bc0, 0x8107, 0xa084, 0x000f,
+	0x8003, 0x8003, 0x8003, 0xa268, 0x72c8, 0x73cc, 0x74d8, 0x71c6,
+	0x6800, 0x70ca, 0x73ce, 0x74da, 0x2091, 0x8000, 0x6a02, 0xd2ac,
+	0x1118, 0x2021, 0x0000, 0x0090, 0xa484, 0x00ff, 0xa082, 0x0002,
+	0x1a04, 0x174f, 0x843f, 0xa7bc, 0x00ff, 0x0140, 0xa786, 0x0002,
+	0x1904, 0x174f, 0xa484, 0x00ff, 0x0904, 0x174f, 0x2061, 0x0200,
+	0xd1fc, 0x0110, 0x2061, 0x0100, 0x2029, 0x0009, 0x2031, 0x0062,
+	0x843f, 0xa7bc, 0x00ff, 0x0130, 0x8307, 0xa084, 0x00ff, 0x1110,
+	0xa73d, 0x1138, 0x2041, 0x0019, 0xa384, 0x00ff, 0xa082, 0x001a,
+	0x0210, 0xa4a4, 0x00ff, 0x8307, 0xa084, 0x00ff, 0x0188, 0xa842,
+	0x02f0, 0xa086, 0x0010, 0x1120, 0xa39c, 0x00ff, 0xa39d, 0x0f00,
+	0xa3bc, 0x00ff, 0x2500, 0xa702, 0x0290, 0x2600, 0xa702, 0x1278,
+	0x2039, 0x003a, 0x6804, 0xa705, 0x6806, 0x6b0a, 0x6b0c, 0x73ce,
+	0x681c, 0x70da, 0x6c1e, 0x2091, 0x8001, 0x0804, 0x13ba, 0x2091,
+	0x8001, 0x0804, 0x13b4, 0x77c4, 0x080c, 0x1b9a, 0x2091, 0x8000,
+	0x6a14, 0x6b1c, 0x2091, 0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e,
+	0x2708, 0x0804, 0x13b7, 0x70c4, 0x2061, 0x4740, 0x6118, 0x601a,
+	0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x70c8, 0x2061,
+	0x4780, 0x6218, 0x601a, 0x0804, 0x13b8, 0x71c4, 0x72c8, 0x73cc,
+	0xa182, 0x0010, 0x1a04, 0x13b3, 0x080c, 0x23d8, 0xa384, 0x4000,
+	0x0110, 0xa295, 0x0020, 0x0804, 0x13b7, 0x77c4, 0x080c, 0x1b9a,
+	0x2091, 0x8000, 0x6a08, 0xc28d, 0x6a0a, 0x2091, 0x8001, 0x2708,
+	0x0804, 0x13b8, 0x77c4, 0x080c, 0x1b9a, 0x2091, 0x8000, 0x6a08,
+	0xa294, 0xfff9, 0x6a0a, 0x6804, 0xa005, 0x0110, 0x080c, 0x22d5,
+	0x2091, 0x8001, 0x2708, 0x0804, 0x13b8, 0x77c4, 0x080c, 0x1b9a,
+	0x2091, 0x8000, 0x6a08, 0xc295, 0x6a0a, 0x6804, 0xa005, 0x0110,
+	0x080c, 0x22d5, 0x2091, 0x8001, 0x2708, 0x0804, 0x13b8, 0x77c4,
+	0x2041, 0x0001, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000,
+	0x080c, 0x1bb2, 0x2091, 0x8001, 0x2708, 0x6a08, 0x0804, 0x13b8,
+	0x77c4, 0xd7fc, 0x0128, 0x080c, 0x1b29, 0x0138, 0x0804, 0x13bc,
+	0x080c, 0x1b1e, 0x0110, 0x0804, 0x13bc, 0x73c8, 0x72cc, 0x77c6,
+	0x73ca, 0x72ce, 0x080c, 0x1c2a, 0x11e8, 0x6818, 0xa005, 0x01a0,
+	0x2708, 0x0076, 0x080c, 0x23f7, 0x007e, 0x1170, 0x2001, 0x0015,
+	0xd7fc, 0x1118, 0x2061, 0x4740, 0x0018, 0xc0fd, 0x2061, 0x4780,
+	0x782a, 0x2091, 0x8001, 0x0005, 0x2091, 0x8001, 0x2001, 0x4005,
+	0x0804, 0x13bc, 0x2091, 0x8001, 0x0804, 0x13ba, 0x77c4, 0xd7fc,
+	0x0128, 0x080c, 0x1b29, 0x0138, 0x0804, 0x13bc, 0x080c, 0x1b1e,
+	0x0110, 0x0804, 0x13bc, 0x77c6, 0x2041, 0x0021, 0x2049, 0x0005,
+	0x2051, 0x0020, 0x2091, 0x8000, 0x080c, 0x1bb2, 0x2009, 0x0016,
+	0xd7fc, 0x1118, 0x2061, 0x4740, 0x0018, 0x2061, 0x4780, 0xc1fd,
+	0x6063, 0x0003, 0x607b, 0x0000, 0x6772, 0x607f, 0x000f, 0x792a,
+	0x61d0, 0xc1c4, 0x61d2, 0x080c, 0x22d5, 0x2091, 0x8001, 0x0005,
+	0x77c8, 0x77ca, 0x77c4, 0x77c6, 0xd7fc, 0x0128, 0x080c, 0x1b29,
+	0x0138, 0x0804, 0x13bc, 0x080c, 0x1b1e, 0x0110, 0x0804, 0x13bc,
+	0xa7bc, 0xff00, 0x2091, 0x8000, 0x2009, 0x0017, 0xd7fc, 0x1118,
+	0x2061, 0x4740, 0x0018, 0x2061, 0x4780, 0xc1fd, 0x607b, 0x0000,
+	0x6063, 0x0002, 0x6772, 0x607f, 0x000f, 0x792a, 0x61d0, 0xc1c4,
+	0x61d2, 0x080c, 0x22d5, 0x2091, 0x8001, 0x2041, 0x0021, 0x2049,
+	0x0005, 0x2051, 0x0010, 0x2091, 0x8000, 0x70c8, 0xa005, 0x0118,
+	0x60d0, 0xc0fd, 0x60d2, 0x080c, 0x1bb2, 0x70c8, 0x6836, 0x8738,
+	0xa784, 0x001f, 0x1dc0, 0x2091, 0x8001, 0x0005, 0x2019, 0x0000,
+	0x72c8, 0xd284, 0x0128, 0x080c, 0x1b29, 0x0138, 0x0804, 0x13bc,
+	0x080c, 0x1b1e, 0x0110, 0x0804, 0x13bc, 0x72c8, 0x72ca, 0x78ac,
+	0xa084, 0x0003, 0x1518, 0x2039, 0x0000, 0xd284, 0x0108, 0xc7fd,
+	0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x080c, 0x1b9a,
+	0x2091, 0x8000, 0x6808, 0xc0d4, 0xa80d, 0x690a, 0x6837, 0x0000,
+	0x2091, 0x8001, 0x8738, 0xa784, 0x001f, 0x1d80, 0xa7bc, 0xff00,
+	0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x1d40, 0x2091, 0x8000,
 	0x72c8, 0x2069, 0x0100, 0xd284, 0x1110, 0x2069, 0x0200, 0x6808,
 	0xa084, 0xfffd, 0x680a, 0x6830, 0xd0b4, 0x01b0, 0x684b, 0x0004,
-	0x20a9, 0x0014, 0x6848, 0xd094, 0x0110, 0x1f04, 0x18b2, 0x684b,
-	0x0009, 0x20a9, 0x0014, 0x6848, 0xd084, 0x0110, 0x1f04, 0x18bb,
-	0x20a9, 0x00fa, 0x1f04, 0x18c2, 0x2079, 0x4600, 0x2009, 0x0018,
-	0x72c8, 0xd284, 0x1118, 0x2061, 0x4640, 0x0018, 0x2061, 0x4680,
+	0x20a9, 0x0014, 0x6848, 0xd094, 0x0110, 0x1f04, 0x18c2, 0x684b,
+	0x0009, 0x20a9, 0x0014, 0x6848, 0xd084, 0x0110, 0x1f04, 0x18cb,
+	0x20a9, 0x00fa, 0x1f04, 0x18d2, 0x2079, 0x4700, 0x2009, 0x0018,
+	0x72c8, 0xd284, 0x1118, 0x2061, 0x4740, 0x0018, 0x2061, 0x4780,
 	0xc1fd, 0x607b, 0x0000, 0x792a, 0x6063, 0x0001, 0x607f, 0x000f,
 	0x60a3, 0x0000, 0x60a4, 0x60ae, 0x60b2, 0x60d0, 0xd0b4, 0x0160,
 	0xc0b4, 0x60d2, 0x00c6, 0x60b4, 0xa065, 0x6008, 0xc0d4, 0x600a,
 	0x6018, 0x8001, 0x601a, 0x00ce, 0x60d0, 0xa084, 0x7eff, 0x60d2,
 	0x78ac, 0xc08d, 0x78ae, 0x83ff, 0x0108, 0x0005, 0x681b, 0x0054,
-	0x2091, 0x8001, 0x0005, 0x73cc, 0x080c, 0x186a, 0x69ec, 0x6a48,
+	0x2091, 0x8001, 0x0005, 0x73cc, 0x080c, 0x1878, 0x69ec, 0x6a48,
 	0xa185, 0x1800, 0x684a, 0xa185, 0x0040, 0x68ee, 0x73cc, 0x2021,
-	0x0004, 0x20a9, 0x09ff, 0x1f04, 0x190b, 0x8421, 0x1dd0, 0x8319,
+	0x0004, 0x20a9, 0x09ff, 0x1f04, 0x191b, 0x8421, 0x1dd0, 0x8319,
 	0x1db0, 0x69ee, 0x6a4a, 0x2091, 0x8001, 0x0005, 0xd7fc, 0x1118,
-	0x2069, 0x4640, 0x0010, 0x2069, 0x4680, 0x71c4, 0x71c6, 0x6916,
+	0x2069, 0x4740, 0x0010, 0x2069, 0x4780, 0x71c4, 0x71c6, 0x6916,
 	0x81ff, 0x1110, 0x68a3, 0x0001, 0x78ac, 0xc08c, 0x78ae, 0xd084,
-	0x1110, 0x080c, 0x1c5b, 0x0005, 0x75d8, 0x74dc, 0x75da, 0x74de,
+	0x1110, 0x080c, 0x1c7a, 0x0005, 0x75d8, 0x74dc, 0x75da, 0x74de,
 	0x0010, 0xa02e, 0x2520, 0x71c4, 0x73c8, 0x72cc, 0x71c6, 0x73ca,
-	0x72ce, 0x2079, 0x4600, 0x7dde, 0x7cda, 0x7bd6, 0x7ad2, 0x080c,
-	0x1b58, 0x0904, 0x1a3d, 0x20a9, 0x0005, 0x20a1, 0x4614, 0x2091,
-	0x8000, 0x41a1, 0x2091, 0x8001, 0x2009, 0x0040, 0x080c, 0x1d24,
-	0x0120, 0x080c, 0x1b60, 0x0804, 0x1a3d, 0x6004, 0xa08c, 0x00ff,
-	0xa18e, 0x0009, 0x1120, 0x0006, 0x080c, 0x205f, 0x000e, 0xa084,
-	0xff00, 0x8007, 0x8009, 0x0904, 0x19e1, 0x00c6, 0x2c68, 0x080c,
-	0x1b58, 0x05a8, 0x2c00, 0x689e, 0x8109, 0x1dc0, 0x609f, 0x0000,
+	0x72ce, 0x2079, 0x4700, 0x7dde, 0x7cda, 0x7bd6, 0x7ad2, 0x080c,
+	0x1b77, 0x0904, 0x1a5c, 0x20a9, 0x0005, 0x20a1, 0x4714, 0x2091,
+	0x8000, 0x41a1, 0x2091, 0x8001, 0x2009, 0x0040, 0x080c, 0x1d41,
+	0x0120, 0x080c, 0x1b7f, 0x0804, 0x1a5c, 0x6004, 0xa08c, 0x00ff,
+	0xa18e, 0x0009, 0x1120, 0x0006, 0x080c, 0x2086, 0x000e, 0xa084,
+	0xff00, 0x8007, 0x8009, 0x0904, 0x19f1, 0x00c6, 0x2c68, 0x080c,
+	0x1b77, 0x05a8, 0x2c00, 0x689e, 0x8109, 0x1dc0, 0x609f, 0x0000,
 	0x00ce, 0x00c6, 0x7ddc, 0x7cd8, 0x7bd4, 0x7ad0, 0xa290, 0x0040,
 	0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x7dde, 0x7cda,
-	0x7bd6, 0x7ad2, 0x2c68, 0x689c, 0xa065, 0x0904, 0x19e0, 0x2009,
-	0x0040, 0x080c, 0x1d24, 0x15a0, 0x6004, 0xa084, 0x00ff, 0xa086,
-	0x0002, 0x1168, 0x6004, 0xa084, 0x00ff, 0xa086, 0x000a, 0x1120,
-	0x0016, 0x080c, 0x205c, 0x001e, 0x2d00, 0x6002, 0x0898, 0x00ce,
-	0x00c6, 0x609c, 0x080c, 0x1bd4, 0x00ce, 0x609f, 0x0000, 0x080c,
-	0x1a41, 0x2009, 0x0018, 0x6008, 0xc0cd, 0x600a, 0x6004, 0x6086,
+	0x7bd6, 0x7ad2, 0x2c68, 0x689c, 0xa065, 0x0904, 0x19f0, 0x2009,
+	0x0040, 0x080c, 0x1d41, 0x15a0, 0x6004, 0xa084, 0x00ff, 0xa086,
+	0x0002, 0x0150, 0x6004, 0xa084, 0x00ff, 0xa086, 0x000a, 0x1138,
+	0x0016, 0x080c, 0x2083, 0x001e, 0x2d00, 0x6002, 0x0898, 0x00ce,
+	0x00c6, 0x609c, 0x080c, 0x1bf3, 0x00ce, 0x609f, 0x0000, 0x080c,
+	0x1a60, 0x2009, 0x0018, 0x6008, 0xc0cd, 0x600a, 0x6004, 0x6086,
 	0x7810, 0x0006, 0x84ff, 0x1110, 0x85ff, 0x0110, 0xc0c5, 0x7812,
-	0x080c, 0x1b15, 0x000e, 0x7812, 0x080c, 0x1b60, 0x0804, 0x1a3d,
-	0x00ce, 0x00c6, 0x609c, 0x080c, 0x1bd4, 0x00ce, 0x609f, 0x0000,
-	0x080c, 0x1a41, 0x2009, 0x0018, 0x6087, 0x0103, 0x601b, 0x0003,
+	0x080c, 0x1b34, 0x000e, 0x7812, 0x080c, 0x1b7f, 0x0804, 0x1a5c,
+	0x00ce, 0x00c6, 0x609c, 0x080c, 0x1bf3, 0x00ce, 0x609f, 0x0000,
+	0x080c, 0x1a60, 0x2009, 0x0018, 0x6087, 0x0103, 0x601b, 0x0003,
 	0x7810, 0x0006, 0x84ff, 0x1110, 0x85ff, 0x0110, 0xc0c5, 0x7812,
-	0x080c, 0x1b15, 0x000e, 0x7812, 0x080c, 0x1b60, 0x0804, 0x1a3d,
-	0x00ce, 0x6114, 0xd1fc, 0x0120, 0x080c, 0x1b0a, 0x01f0, 0x0018,
-	0x080c, 0x1aff, 0x01d0, 0x080c, 0x1a41, 0x2009, 0x0018, 0x6087,
+	0x080c, 0x1b34, 0x000e, 0x7812, 0x080c, 0x1b7f, 0x0804, 0x1a5c,
+	0x00ce, 0x6114, 0xd1fc, 0x0120, 0x080c, 0x1b29, 0x01f0, 0x0018,
+	0x080c, 0x1b1e, 0x01d0, 0x080c, 0x1a60, 0x2009, 0x0018, 0x6087,
 	0x0103, 0x601b, 0x0021, 0x7810, 0x0006, 0x84ff, 0x1110, 0x85ff,
-	0x0110, 0xc0c5, 0x7812, 0x080c, 0x1b15, 0x000e, 0x7812, 0x080c,
-	0x1b60, 0x2001, 0x4007, 0x0804, 0x13bc, 0x74c4, 0x73c8, 0x72cc,
-	0x6014, 0x2091, 0x8000, 0x00e6, 0x2009, 0x0012, 0xd0fc, 0x1118,
-	0x2071, 0x4640, 0x0018, 0x2071, 0x4680, 0xc1fd, 0x792a, 0x7063,
-	0x0005, 0x71d0, 0xc1c4, 0x71d2, 0x7366, 0x726a, 0x746e, 0x7072,
-	0x7077, 0x0000, 0x2c00, 0x707a, 0xa02e, 0x2530, 0x611c, 0xa184,
-	0x0060, 0x0110, 0x080c, 0x3fc1, 0x00ee, 0x6596, 0x65a6, 0x669a,
-	0x66aa, 0x60af, 0x0000, 0x60b3, 0x0000, 0x6714, 0x6023, 0x0000,
-	0x080c, 0x22ae, 0x2091, 0x8001, 0x0005, 0x70c3, 0x4005, 0x0804,
-	0x13bd, 0x20a9, 0x0005, 0x2099, 0x4614, 0x2091, 0x8000, 0x530a,
-	0x2091, 0x8001, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000,
-	0xa5a9, 0x0000, 0x0005, 0x71c4, 0x70c7, 0x0000, 0x791e, 0x0804,
-	0x13ba, 0x71c4, 0x71c6, 0x2168, 0x0010, 0x2069, 0x1000, 0x690c,
-	0xa016, 0x2d04, 0xa210, 0x8d68, 0x8109, 0x1dd8, 0xa285, 0x0000,
-	0x1118, 0x70c3, 0x4000, 0x0010, 0x70c3, 0x4003, 0x70ca, 0x0804,
-	0x13bd, 0x7964, 0x71c6, 0x71c4, 0xa182, 0x0003, 0x1a04, 0x13b3,
-	0x7966, 0x0804, 0x13ba, 0x7964, 0x71c6, 0x0804, 0x13ba, 0x7900,
-	0x71c6, 0x71c4, 0x7902, 0x0804, 0x13ba, 0x7900, 0x71c6, 0x0804,
-	0x13ba, 0x70c4, 0x2011, 0x0000, 0xa08c, 0x000d, 0x0160, 0x810c,
-	0x0230, 0x8210, 0x810c, 0x810c, 0x0210, 0x8210, 0x810c, 0x81ff,
-	0x1904, 0x13b4, 0x8210, 0x7a0e, 0xd28c, 0x0538, 0x7910, 0xc1cd,
-	0x7912, 0x2009, 0x0021, 0x2019, 0x0003, 0xd284, 0x01c0, 0x8108,
-	0x2019, 0x0041, 0x2011, 0x8e4e, 0x2312, 0x2019, 0x0042, 0x8210,
-	0x2312, 0x2019, 0x0043, 0x8210, 0x2312, 0x2019, 0x0046, 0x8210,
-	0x2312, 0x2019, 0x0047, 0x8210, 0x2312, 0x2019, 0x0006, 0x2011,
-	0x8e53, 0x2112, 0x2011, 0x8e73, 0x2312, 0x7904, 0x7806, 0x0804,
-	0x13b9, 0x7804, 0x70c6, 0x0804, 0x13ba, 0x71c4, 0xd1fc, 0x1118,
-	0x2011, 0x4ac0, 0x0010, 0x2011, 0x4b40, 0x8107, 0xa084, 0x000f,
-	0x8003, 0x8003, 0x8003, 0xa268, 0x2011, 0x0000, 0x6814, 0xd0fc,
-	0x0110, 0xa295, 0x0200, 0xd0b4, 0x0110, 0xa295, 0x0001, 0x6b0c,
-	0x6800, 0x70da, 0x0804, 0x13b7, 0x7814, 0xd0f4, 0x0130, 0x2001,
-	0x4007, 0x70db, 0x0000, 0xa005, 0x0048, 0xd0fc, 0x0130, 0x2001,
-	0x4007, 0x70db, 0x0001, 0xa005, 0x0008, 0xa006, 0x0005, 0x7814,
-	0xd0f4, 0x0130, 0x2001, 0x4007, 0x70db, 0x0000, 0xa005, 0x0008,
-	0xa006, 0x0005, 0x7814, 0xd0fc, 0x0130, 0x2001, 0x4007, 0x70db,
-	0x0001, 0xa005, 0x0008, 0xa006, 0x0005, 0x7112, 0x721a, 0x731e,
-	0x7810, 0xd0c4, 0x0110, 0x7422, 0x7526, 0xac80, 0x0001, 0x8108,
-	0x810c, 0x81a9, 0x8098, 0x20a1, 0x0030, 0x7003, 0x0000, 0x6084,
-	0x20a2, 0x53a6, 0x7007, 0x0001, 0x7974, 0xa184, 0xff00, 0x0140,
-	0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0018,
-	0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, 0xa006, 0xa211,
-	0x7d10, 0xd5c4, 0x0120, 0x7b84, 0xa319, 0x7c80, 0xa421, 0x7008,
-	0xd0fc, 0x0de8, 0x7003, 0x0001, 0x7007, 0x0006, 0x711a, 0x721e,
-	0x7d10, 0xd5c4, 0x0110, 0x7322, 0x7426, 0xa084, 0x01e0, 0x0005,
-	0x7848, 0xa065, 0x0120, 0x2c04, 0x784a, 0x2063, 0x0000, 0x0005,
-	0x00f6, 0x2079, 0x4600, 0x7848, 0x2062, 0x2c00, 0xa005, 0x1110,
-	0x080c, 0x254c, 0x784a, 0x00fe, 0x0005, 0x2011, 0x9000, 0x7a4a,
-	0x7bc4, 0x8319, 0x0128, 0xa280, 0x0032, 0x2012, 0x2010, 0x0cc8,
-	0x2013, 0x0000, 0x0005, 0x0016, 0x0026, 0xd7fc, 0x1118, 0x2011,
-	0x4bc0, 0x0010, 0x2011, 0x6bc0, 0xa784, 0x0f00, 0x800b, 0xa784,
-	0x001f, 0x0120, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa268,
-	0x002e, 0x001e, 0x0005, 0x0c39, 0x2900, 0x682a, 0x2a00, 0x682e,
-	0x6808, 0xa084, 0xf9ef, 0xa80d, 0x690a, 0x00e6, 0xd7fc, 0x1128,
-	0x2009, 0x4652, 0x2071, 0x4640, 0x0020, 0x2009, 0x4692, 0x2071,
-	0x4680, 0x210c, 0x6804, 0xa005, 0x0148, 0xa116, 0x1138, 0x2060,
-	0x6000, 0x6806, 0x0016, 0x200b, 0x0000, 0x0018, 0x2009, 0x0000,
-	0x0016, 0x6804, 0xa065, 0x0178, 0x6000, 0x6806, 0x0421, 0x080c,
-	0x1d95, 0x6810, 0x7908, 0x8109, 0x790a, 0x8001, 0x6812, 0x1d88,
-	0x7910, 0xc1a5, 0x7912, 0x001e, 0x6902, 0x6906, 0x2d00, 0x2060,
-	0x080c, 0x2693, 0x00ee, 0x0005, 0xa065, 0x0160, 0x2008, 0x609c,
-	0xa005, 0x0128, 0x2062, 0x609f, 0x0000, 0xa065, 0x0cc0, 0x7848,
-	0x794a, 0x2062, 0x0005, 0x6007, 0x0103, 0x608f, 0x0000, 0x20a9,
-	0x001c, 0xac80, 0x0005, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x6828,
-	0x601a, 0x682c, 0x6022, 0x0005, 0x00e6, 0xd7fc, 0x1128, 0x2071,
-	0x4640, 0x2031, 0x46c0, 0x0020, 0x2071, 0x4680, 0x2031, 0x48c0,
-	0x704c, 0xa08c, 0x0200, 0x1128, 0xa608, 0x2d0a, 0x8000, 0x704e,
-	0xa006, 0x00ee, 0x0005, 0x00f6, 0xd7fc, 0x1118, 0x2079, 0x4640,
-	0x0010, 0x2079, 0x4680, 0x080c, 0x1b7b, 0x2091, 0x8000, 0x6804,
-	0x780a, 0xa065, 0x05f0, 0x0030, 0x2c00, 0x780a, 0x2060, 0x6000,
-	0xa065, 0x05b8, 0x6010, 0xa306, 0x1db8, 0x600c, 0xa206, 0x1da0,
-	0x2c28, 0x7848, 0xac06, 0x1108, 0x0448, 0x6804, 0xac06, 0x1140,
-	0x6000, 0x2060, 0x6806, 0xa005, 0x1118, 0x6803, 0x0000, 0x0048,
-	0x6400, 0x7808, 0x2060, 0x6402, 0xa486, 0x0000, 0x1110, 0x2c00,
-	0x6802, 0x2560, 0x080c, 0x1be3, 0x601b, 0x0005, 0x6023, 0x0020,
-	0x00fe, 0x080c, 0x1d95, 0x00f6, 0x7908, 0x8109, 0x790a, 0x6810,
-	0x8001, 0x6812, 0x1118, 0x7810, 0xc0a5, 0x7812, 0x2001, 0xffff,
-	0xa005, 0x00fe, 0x0005, 0x0076, 0x2700, 0x2039, 0x0000, 0xd0fc,
-	0x0108, 0xc7fd, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008,
-	0x2091, 0x8000, 0x080c, 0x1b93, 0x8738, 0xa784, 0x001f, 0x1dd0,
-	0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x1d90,
-	0x2091, 0x8001, 0x007e, 0x0005, 0x786c, 0x2009, 0x8e74, 0x210c,
-	0xa10d, 0x0118, 0xa065, 0x0804, 0x207a, 0x2061, 0x0000, 0x6018,
-	0xd084, 0x11b8, 0x7810, 0xd08c, 0x0130, 0xc08c, 0x7812, 0xc7fc,
-	0x2069, 0x4640, 0x0028, 0xc08d, 0x7812, 0x2069, 0x4680, 0xc7fd,
-	0x2091, 0x8000, 0x681c, 0x681f, 0x0000, 0x2091, 0x8001, 0xa005,
-	0x1108, 0x0005, 0xa08c, 0xfff0, 0x0110, 0x080c, 0x254c, 0x0002,
-	0x1cb8, 0x1cbb, 0x1cc1, 0x1cc5, 0x1cb9, 0x1cc9, 0x1cb9, 0x1cb9,
-	0x1cb9, 0x1ccf, 0x1cfb, 0x1cfe, 0x1d03, 0x1d0c, 0x1cb9, 0x1cb9,
-	0x0005, 0x080c, 0x254c, 0x080c, 0x1c5b, 0x2001, 0x8001, 0x0804,
-	0x1d15, 0x2001, 0x8003, 0x0804, 0x1d15, 0x2001, 0x8004, 0x0804,
-	0x1d15, 0x080c, 0x1c5b, 0x2001, 0x8006, 0x0804, 0x1d15, 0x2091,
-	0x8000, 0x0076, 0xd7fc, 0x1128, 0x2069, 0x4640, 0x2039, 0x0009,
-	0x0020, 0x2069, 0x4680, 0x2039, 0x0009, 0x6800, 0xa086, 0x0000,
-	0x0128, 0x000e, 0x6f1e, 0x2091, 0x8001, 0x0005, 0x6870, 0x007e,
-	0xa0bc, 0xff00, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0010,
-	0x080c, 0x1b93, 0x8738, 0xa784, 0x001f, 0x1dd0, 0x2091, 0x8001,
-	0x2001, 0x800a, 0x00d0, 0x2001, 0x800c, 0x00b8, 0x080c, 0x1c5b,
-	0x2001, 0x800d, 0x0090, 0xd7fc, 0x0110, 0x78e4, 0x0008, 0x78e0,
-	0x70c6, 0x2001, 0x800e, 0x0048, 0xd7fc, 0x0110, 0x78ec, 0x0008,
-	0x78e8, 0x70c6, 0x2001, 0x800f, 0x0000, 0x70c2, 0xd7fc, 0x1118,
-	0x70db, 0x0000, 0x0010, 0x70db, 0x0001, 0x2061, 0x0000, 0x601b,
-	0x0001, 0x2091, 0x4080, 0x0005, 0xac80, 0x0001, 0x81ff, 0x0518,
-	0x2099, 0x0030, 0x20a0, 0x700c, 0xa084, 0x07ff, 0x0100, 0x7018,
-	0x0006, 0x701c, 0x0006, 0x7020, 0x0006, 0x7024, 0x0006, 0x7112,
-	0x81ac, 0x721a, 0x731e, 0x7422, 0x7526, 0x7003, 0x0001, 0x7007,
-	0x0001, 0x7008, 0x800b, 0x1ee8, 0x7007, 0x0002, 0xa08c, 0x01e0,
-	0x1110, 0x53a5, 0xa006, 0x7003, 0x0000, 0x7007, 0x0004, 0x000e,
-	0x7026, 0x000e, 0x7022, 0x000e, 0x701e, 0x000e, 0x701a, 0x0005,
-	0x2011, 0x0020, 0x2009, 0x0010, 0x6b0a, 0x6c0e, 0x681f, 0x0201,
-	0x6803, 0xfd20, 0x6807, 0x0038, 0x6a1a, 0x2d00, 0xa0e8, 0x0008,
-	0xa290, 0x0004, 0x8109, 0x1d80, 0x0005, 0x70ec, 0xd0dc, 0x1520,
-	0x2029, 0x0001, 0x7814, 0xd0cc, 0x1160, 0x70ec, 0xd0e4, 0x2019,
-	0x0c0a, 0x2021, 0x000a, 0x1120, 0x2019, 0x0c0c, 0x2021, 0x000c,
-	0x0070, 0x70ec, 0xd0e4, 0x1128, 0x2019, 0x180c, 0x2021, 0x000c,
-	0x0030, 0x2019, 0x1809, 0x2021, 0x0009, 0xa5ad, 0x0200, 0x6b0a,
-	0x6c0e, 0x6d1e, 0x6807, 0x0038, 0x0005, 0x6004, 0x6086, 0x2c08,
-	0x2063, 0x0000, 0x7868, 0xa005, 0x796a, 0x0110, 0x2c02, 0x0008,
-	0x796e, 0x0005, 0x00c6, 0x2061, 0x4600, 0x6887, 0x0103, 0x2d08,
-	0x206b, 0x0000, 0x6068, 0xa005, 0x616a, 0x0110, 0x2d02, 0x0008,
-	0x616e, 0x00ce, 0x0005, 0x2091, 0x8000, 0x2c04, 0x786e, 0xa005,
-	0x1108, 0x786a, 0x2091, 0x8001, 0x609c, 0xa005, 0x0188, 0x00c6,
-	0x2060, 0x2008, 0x609c, 0xa005, 0x0138, 0x2062, 0x609f, 0x0000,
-	0xa065, 0x609c, 0xa005, 0x1dc8, 0x7848, 0x794a, 0x2062, 0x00ce,
-	0x7848, 0x2062, 0x609f, 0x0000, 0xac85, 0x0000, 0x1110, 0x080c,
-	0x254c, 0x784a, 0x0005, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086,
-	0x818e, 0x1208, 0xa200, 0x1f04, 0x1ddf, 0x8086, 0x818e, 0x0005,
-	0x0156, 0x20a9, 0x0010, 0xa005, 0x01b8, 0xa11a, 0x12a8, 0x8213,
-	0x818d, 0x0228, 0xa11a, 0x1220, 0x1f04, 0x1def, 0x0028, 0xa11a,
-	0x2308, 0x8210, 0x1f04, 0x1def, 0x0006, 0x3200, 0xa084, 0xefff,
-	0x2080, 0x000e, 0x015e, 0x0005, 0x0006, 0x3200, 0xa085, 0x1000,
-	0x0cb8, 0x7d74, 0x70d0, 0xa506, 0x0904, 0x1ebd, 0x7810, 0x2050,
-	0x080c, 0x1b58, 0x0904, 0x1ebd, 0xa046, 0x7970, 0x2500, 0x8000,
-	0xa112, 0x2009, 0x0040, 0x1208, 0x0030, 0x72d0, 0xa206, 0x0118,
-	0x8840, 0x2009, 0x0080, 0x00c6, 0x7112, 0x7007, 0x0001, 0x2099,
-	0x0030, 0x20a9, 0x0020, 0xac80, 0x0001, 0x20a0, 0x2061, 0x0000,
-	0x88ff, 0x0110, 0x080c, 0x1b58, 0x7008, 0xd0fc, 0x0de8, 0x7007,
-	0x0002, 0x2091, 0x8001, 0xa08c, 0x01e0, 0x1538, 0x53a5, 0x8cff,
-	0x1120, 0x88ff, 0x0904, 0x1eaa, 0x0050, 0x2c00, 0x788e, 0x20a9,
-	0x0020, 0xac80, 0x0001, 0x20a0, 0x53a5, 0x0804, 0x1eaa, 0xa046,
-	0x7218, 0x731c, 0xdac4, 0x0110, 0x7420, 0x7524, 0xa292, 0x0040,
-	0xa39b, 0x0000, 0xa4a3, 0x0000, 0xa5ab, 0x0000, 0x721a, 0x731e,
-	0xdac4, 0x0118, 0x7422, 0x7526, 0xa006, 0x7007, 0x0004, 0x0904,
-	0x1eaa, 0x8cff, 0x0110, 0x080c, 0x1b60, 0x00ce, 0x080c, 0x1b60,
-	0xa046, 0x7888, 0x8000, 0x788a, 0xa086, 0x0002, 0x01c0, 0x7a7c,
-	0x7b78, 0xdac4, 0x0110, 0x7c84, 0x7d80, 0x7974, 0x8107, 0x8004,
-	0x8004, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000,
-	0x721a, 0x731e, 0xdac4, 0x0588, 0x7422, 0x7526, 0x0470, 0x6014,
-	0xd0fc, 0x1118, 0x2069, 0x4640, 0x0010, 0x2069, 0x4680, 0x2091,
-	0x8000, 0x681f, 0x0002, 0x88ff, 0x0120, 0xa046, 0x788c, 0x2060,
-	0x0c70, 0x788b, 0x0000, 0x78ac, 0xa085, 0x0003, 0x78ae, 0x2091,
-	0x8001, 0x0098, 0x00ce, 0x788b, 0x0000, 0x080c, 0x2035, 0x6004,
-	0xa084, 0x000f, 0x0059, 0x88ff, 0x0130, 0x788c, 0x2060, 0x6004,
-	0xa084, 0x000f, 0x0019, 0x0804, 0x1e09, 0x0005, 0x0002, 0x1ecf,
-	0x1eea, 0x1f03, 0x1ecf, 0x1f10, 0x1ee0, 0x1ecf, 0x1ecf, 0x1ecf,
-	0x1ee8, 0x1f01, 0x1ecf, 0x1ecf, 0x1ecf, 0x1ecf, 0x1ecf, 0x2039,
-	0x0400, 0x78bc, 0xa705, 0x78be, 0x6008, 0xa705, 0x600a, 0x080c,
-	0x1f4c, 0x609c, 0x78ba, 0x609f, 0x0000, 0x080c, 0x2021, 0x0005,
-	0x78bc, 0xd0c4, 0x0108, 0x0c58, 0x601c, 0xc0bd, 0x601e, 0x0030,
-	0x080c, 0x205f, 0x78bc, 0xd0c4, 0x0108, 0x0c08, 0x78bf, 0x0000,
-	0x6004, 0x8007, 0xa084, 0x00ff, 0x78b2, 0x8001, 0x0138, 0x080c,
-	0x1f4c, 0x0120, 0x78bc, 0xc0c5, 0x78be, 0x0010, 0x0804, 0x1f67,
-	0x0005, 0x080c, 0x205c, 0x78bc, 0xa08c, 0x0e00, 0x1110, 0xd0c4,
-	0x1108, 0x0828, 0x080c, 0x1f4c, 0x1110, 0x0804, 0x1f67, 0x0005,
-	0x78bc, 0xd0c4, 0x0110, 0x0804, 0x1ecf, 0x78bf, 0x0000, 0x6714,
-	0x2011, 0x0001, 0x22a8, 0x6018, 0xa084, 0x00ff, 0xa005, 0x0188,
-	0xa7bc, 0xff00, 0x20a9, 0x0020, 0xa08e, 0x0001, 0x0150, 0xa7bc,
-	0x8000, 0x2011, 0x0002, 0x20a9, 0x0100, 0xa08e, 0x0002, 0x0108,
-	0x00c0, 0x080c, 0x1b7b, 0x2d00, 0x2091, 0x8000, 0x682b, 0x0000,
-	0x682f, 0x0000, 0x6808, 0xa084, 0xffde, 0x680a, 0xade8, 0x0010,
-	0x2091, 0x8001, 0x1f04, 0x1f34, 0x8211, 0x0118, 0x20a9, 0x0100,
-	0x0c58, 0x080c, 0x1b60, 0x0005, 0x609f, 0x0000, 0x78b4, 0xa06d,
-	0x2c00, 0x78b6, 0x1110, 0x78ba, 0x0038, 0x689e, 0x2d00, 0x6002,
-	0x78b8, 0xad06, 0x1108, 0x6002, 0x78b0, 0x8001, 0x78b2, 0x1130,
-	0x78bc, 0xc0c4, 0x78be, 0x78b8, 0x2060, 0xa006, 0x0005, 0x00e6,
-	0xa02e, 0x2530, 0x7dba, 0x7db6, 0x65ae, 0x65b2, 0x601c, 0x60a2,
-	0x2048, 0xa984, 0xe1ff, 0x601e, 0xa984, 0x0060, 0x0110, 0x080c,
-	0x3fc1, 0x6596, 0x65a6, 0x669a, 0x66aa, 0x6714, 0x2071, 0x4680,
-	0xd7fc, 0x1110, 0x2071, 0x4640, 0xa784, 0x0f00, 0x800b, 0xa784,
-	0x001f, 0x0120, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0x71c0,
-	0xa168, 0x2700, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
-	0x71c4, 0xa100, 0x60c2, 0x2091, 0x8000, 0x7814, 0xd0c4, 0x0138,
-	0xd7fc, 0x1118, 0xd0f4, 0x1140, 0x0010, 0xd0fc, 0x1128, 0x6e08,
-	0xd684, 0x01f0, 0xd9fc, 0x11e0, 0x2091, 0x8001, 0x080c, 0x1be3,
-	0x2091, 0x8000, 0x080c, 0x1d95, 0x2091, 0x8001, 0x7814, 0xd0c4,
-	0x0904, 0x201f, 0xd7fc, 0x1120, 0xd0f4, 0x1130, 0x0804, 0x201f,
-	0xd0fc, 0x1110, 0x0804, 0x201f, 0x601b, 0x0021, 0x0804, 0x201f,
-	0x6024, 0xa096, 0x0001, 0x1110, 0x8000, 0x6026, 0x6a10, 0x6814,
-	0xa202, 0x0268, 0x0160, 0x2091, 0x8001, 0x2039, 0x0200, 0x609c,
-	0x78ba, 0x609f, 0x0000, 0x080c, 0x2021, 0x0804, 0x201f, 0x2c08,
-	0xd9fc, 0x01f0, 0x6800, 0xa065, 0x01d8, 0x6a04, 0x7000, 0xa084,
-	0x0002, 0x0168, 0x7048, 0xa206, 0x1150, 0x6b04, 0x2160, 0x2304,
-	0x6002, 0xa005, 0x1108, 0x6902, 0x2260, 0x6102, 0x0098, 0x2d00,
-	0x2060, 0x080c, 0x2693, 0x6e08, 0x2160, 0x6202, 0x6906, 0x0050,
-	0x6800, 0x6902, 0xa065, 0x0110, 0x6102, 0x0008, 0x6906, 0x2160,
-	0x6003, 0x0000, 0x2160, 0xd9fc, 0x0118, 0xa6b4, 0xfffc, 0x6e0a,
-	0x6810, 0x7d08, 0x8528, 0x7d0a, 0x8000, 0x6812, 0x2091, 0x8001,
-	0xd6b4, 0x0128, 0xa6b6, 0x0040, 0x6e0a, 0x080c, 0x1bf4, 0x00ee,
-	0x0005, 0x6008, 0xa705, 0x600a, 0x2091, 0x8000, 0x080c, 0x1d95,
-	0x2091, 0x8001, 0x78b8, 0xa065, 0x0128, 0x609c, 0x78ba, 0x609f,
-	0x0000, 0x0c78, 0x78b6, 0x78ba, 0x0005, 0x7970, 0x7874, 0x2818,
-	0xd384, 0x0118, 0x8000, 0xa112, 0x0220, 0x8000, 0xa112, 0x1278,
-	0xc384, 0x7a7c, 0x721a, 0x7a78, 0x721e, 0xdac4, 0x0120, 0x7a84,
-	0x7222, 0x7a80, 0x7226, 0xa006, 0xd384, 0x0108, 0x8000, 0x7876,
-	0x70d2, 0x781c, 0xa005, 0x0138, 0x8001, 0x781e, 0x1120, 0x0e04,
-	0x205b, 0x2091, 0x4080, 0x0005, 0x2039, 0x2071, 0x0010, 0x2039,
-	0x2077, 0x2704, 0xa005, 0x0160, 0xac00, 0x2068, 0x6908, 0x6810,
-	0x6912, 0x680a, 0x690c, 0x6814, 0x6916, 0x680e, 0x8738, 0x0c88,
-	0x0005, 0x0003, 0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0015,
-	0x001b, 0x0000, 0x2041, 0x0000, 0x780c, 0x0002, 0x2223, 0x21fe,
-	0x2082, 0x20f2, 0x2039, 0x8e74, 0x2734, 0x7d10, 0x00c0, 0x6084,
-	0xa086, 0x0103, 0x1904, 0x20dc, 0x6114, 0x6018, 0xa105, 0x0120,
-	0x86ff, 0x11d8, 0x0804, 0x20dc, 0x8603, 0xa080, 0x8e55, 0x620c,
-	0x2202, 0x8000, 0x6210, 0x2202, 0x080c, 0x1db3, 0x8630, 0xa68e,
-	0x000f, 0x0904, 0x215d, 0x786c, 0xa065, 0x1d08, 0x7808, 0xa602,
-	0x1220, 0xd5ac, 0x1110, 0x263a, 0x0005, 0xa682, 0x0003, 0x1a04,
-	0x215d, 0x2091, 0x8000, 0x2069, 0x0000, 0x6818, 0xd084, 0x11f8,
-	0x2011, 0x8e55, 0x2204, 0x70c6, 0x8210, 0x2204, 0x70ca, 0xd684,
-	0x1130, 0x8210, 0x2204, 0x70da, 0x8210, 0x2204, 0x70de, 0xa685,
-	0x8020, 0x70c2, 0x681b, 0x0001, 0x2091, 0x4080, 0x7810, 0xa084,
-	0xffcf, 0x7812, 0x2091, 0x8001, 0x203b, 0x0000, 0x0005, 0x7810,
-	0xc0ad, 0x7812, 0x0804, 0x215d, 0x263a, 0x080c, 0x2229, 0x1904,
-	0x2245, 0x786c, 0xa065, 0x1904, 0x2087, 0x2091, 0x8000, 0x7810,
-	0xa084, 0xffcf, 0x86ff, 0x0108, 0xc0ad, 0x7812, 0x2091, 0x8001,
-	0x0804, 0x2245, 0x2039, 0x8e74, 0x2734, 0x7d10, 0x00a0, 0x6084,
-	0xa086, 0x0103, 0x1904, 0x2147, 0x6114, 0x6018, 0xa105, 0x0120,
-	0x86ff, 0x11b8, 0x0804, 0x2147, 0xa680, 0x8e55, 0x620c, 0x2202,
-	0x080c, 0x1db3, 0x8630, 0xa68e, 0x001e, 0x0904, 0x215d, 0x786c,
-	0xa065, 0x1d28, 0x7808, 0xa602, 0x1220, 0xd5ac, 0x1110, 0x263a,
-	0x0005, 0xa682, 0x0006, 0x1a04, 0x215d, 0x2091, 0x8000, 0x2069,
-	0x0000, 0x6818, 0xd084, 0x11f8, 0x2011, 0x8e55, 0x2009, 0x8e4e,
-	0x26a8, 0x211c, 0x2204, 0x201a, 0x8108, 0x8210, 0x1f04, 0x2129,
-	0xa685, 0x8030, 0x70c2, 0x681b, 0x0001, 0x2091, 0x4080, 0x7810,
-	0xa084, 0xffcf, 0x7812, 0x2091, 0x8001, 0xa006, 0x2009, 0x8e75,
-	0x200a, 0x203a, 0x0005, 0x7810, 0xc0ad, 0x7812, 0x00b0, 0x263a,
-	0x080c, 0x2229, 0x1904, 0x2245, 0x786c, 0xa065, 0x1904, 0x20f7,
-	0x2091, 0x8000, 0x7810, 0xa084, 0xffcf, 0x86ff, 0x0108, 0xc0ad,
-	0x7812, 0x2091, 0x8001, 0x0804, 0x2245, 0x2091, 0x8000, 0x7007,
-	0x0004, 0x7994, 0x70d4, 0xa102, 0x0228, 0x0168, 0x7b90, 0xa302,
-	0x1150, 0x0010, 0x8002, 0x1138, 0x263a, 0x7810, 0xc0ad, 0x7812,
-	0x2091, 0x8001, 0x0005, 0xa184, 0xff00, 0x0140, 0x810f, 0x810c,
-	0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0018, 0x8107, 0x8004,
-	0x8004, 0x7a9c, 0xa210, 0x721a, 0x7a98, 0xa006, 0xa211, 0x721e,
-	0xd4c4, 0x0130, 0x7aa4, 0xa211, 0x7222, 0x7aa0, 0xa211, 0x7226,
-	0x20a1, 0x0030, 0x7003, 0x0000, 0x2009, 0x8e54, 0x260a, 0x8109,
-	0x2198, 0x2104, 0xd084, 0x0108, 0x8633, 0xa6b0, 0x0002, 0x26a8,
-	0x53a6, 0x8603, 0x7012, 0x7007, 0x0001, 0x7990, 0x7894, 0x8000,
-	0xa10a, 0x1208, 0xa006, 0x2028, 0x7974, 0xa184, 0xff00, 0x0140,
-	0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0018,
-	0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, 0xa006, 0xa211,
-	0xd4c4, 0x0120, 0x7b84, 0xa319, 0x7c80, 0xa421, 0x7008, 0xd0fc,
-	0x0de8, 0xa084, 0x01e0, 0x01d0, 0x7d10, 0x2031, 0x8e54, 0x2634,
-	0x78a8, 0x8000, 0x78aa, 0xd08c, 0x1138, 0x7007, 0x0006, 0x7004,
-	0xd094, 0x1de8, 0x0804, 0x215f, 0x2069, 0x4647, 0x206b, 0x0003,
-	0x78ac, 0xa085, 0x0300, 0x78ae, 0xa006, 0x0048, 0x2030, 0x75d6,
-	0x2091, 0x4080, 0x7d96, 0x7d10, 0xa5ac, 0xffcf, 0x7d12, 0x2091,
-	0x8001, 0x78aa, 0x7007, 0x0006, 0x263a, 0x7003, 0x0001, 0x711a,
-	0x721e, 0xd5c4, 0x0110, 0x7322, 0x7426, 0x0005, 0x6084, 0xa086,
-	0x0103, 0x11d8, 0x6114, 0x6018, 0xa105, 0x11b8, 0x2069, 0x0000,
-	0x6818, 0xd084, 0x1190, 0x600c, 0x70c6, 0x6010, 0x70ca, 0x70c3,
-	0x8020, 0x681b, 0x0001, 0x2091, 0x4080, 0x080c, 0x1db3, 0x0e04,
-	0x221c, 0x786c, 0xa065, 0x1d10, 0x0005, 0x0059, 0x1530, 0x786c,
-	0xa065, 0x19e0, 0x0410, 0x0029, 0x1500, 0x786c, 0xa065, 0x1dd8,
-	0x00e0, 0x6084, 0xa086, 0x0103, 0x1168, 0x6018, 0xc0fc, 0x601a,
-	0xa086, 0x0004, 0x1138, 0x7804, 0xd0a4, 0x0120, 0x080c, 0x1db3,
-	0xa006, 0x0005, 0x0079, 0x1118, 0xa085, 0x0001, 0x0005, 0x00b9,
-	0x1110, 0x2041, 0x0001, 0x7d10, 0x0005, 0x88ff, 0x0110, 0x2091,
-	0x4080, 0x0005, 0x7b90, 0x7994, 0x70d4, 0xa102, 0x1118, 0xa385,
-	0x0000, 0x0005, 0x0210, 0xa302, 0x0005, 0x8002, 0x0005, 0xa184,
-	0xff00, 0x0140, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007,
-	0xa100, 0x0018, 0x8107, 0x8004, 0x8004, 0x7a9c, 0x7b98, 0x7ca4,
-	0x7da0, 0xa210, 0xa006, 0xa319, 0xa421, 0xa529, 0x2009, 0x0018,
-	0x6028, 0xa005, 0x0110, 0x2009, 0x0040, 0x080c, 0x1b15, 0x01d0,
-	0x78a8, 0x8000, 0x78aa, 0xd08c, 0x1510, 0x6014, 0xd0fc, 0x1118,
-	0x2069, 0x4640, 0x0010, 0x2069, 0x4680, 0x2091, 0x8000, 0x681f,
-	0x0003, 0x78ab, 0x0000, 0x78ac, 0xa085, 0x0300, 0x78ae, 0x2091,
-	0x8001, 0x0068, 0x78ab, 0x0000, 0x080c, 0x1db3, 0x7990, 0x7894,
-	0x8000, 0xa10a, 0x1208, 0xa006, 0x7896, 0x70d6, 0xa006, 0x2071,
-	0x0010, 0x2091, 0x8001, 0x0005, 0xd7fc, 0x1118, 0x2009, 0x4658,
-	0x0010, 0x2009, 0x4698, 0x2091, 0x8000, 0x200a, 0x00f6, 0x2009,
-	0x4680, 0x2079, 0x0100, 0xd7fc, 0x1120, 0x2009, 0x4640, 0x2079,
-	0x0200, 0x2104, 0xa086, 0x0000, 0x1180, 0xd7fc, 0x1118, 0x2009,
-	0x4645, 0x0010, 0x2009, 0x4685, 0x2104, 0xa005, 0x1130, 0x7830,
-	0xa084, 0x00c0, 0x1110, 0x781b, 0x0052, 0x00fe, 0x0005, 0x2009,
-	0x0002, 0x2069, 0x4600, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904,
-	0x2324, 0x2071, 0x4680, 0x2079, 0x0100, 0x2021, 0x48bf, 0x784b,
-	0x000f, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x0118, 0x2019, 0x3e0f,
-	0x0030, 0x20a1, 0x012b, 0x2019, 0x3e0f, 0xd184, 0x0110, 0x20a1,
-	0x022b, 0x2304, 0xa005, 0x0140, 0x789a, 0x8318, 0x23ac, 0x8318,
-	0x2398, 0x53a6, 0x3318, 0x0ca8, 0x789b, 0x0000, 0x789b, 0x0020,
-	0x20a9, 0x0010, 0x78af, 0x0000, 0x78af, 0x2020, 0x1f04, 0x2302,
-	0x7003, 0x0000, 0x0016, 0xd18c, 0x2009, 0x0000, 0x0108, 0xc1bd,
-	0x080c, 0x2443, 0x001e, 0x7020, 0xa084, 0x000f, 0xa085, 0x6300,
-	0x7806, 0x780f, 0x9000, 0x7843, 0x00d8, 0x7853, 0x0090, 0x780b,
-	0x2f08, 0x7452, 0x704f, 0x0000, 0x8109, 0x0140, 0x2071, 0x4640,
-	0x2079, 0x0200, 0x2021, 0x46bf, 0x0804, 0x22df, 0x080c, 0x24fd,
-	0x0005, 0x0016, 0x2011, 0x0101, 0xd1bc, 0x1110, 0x2011, 0x0201,
-	0xa18c, 0x000f, 0x2204, 0xa084, 0xfff0, 0xa105, 0x2012, 0x001e,
-	0x080c, 0x2443, 0x0005, 0x2011, 0x0101, 0xd3fc, 0x1110, 0x2011,
-	0x0201, 0x20a9, 0x0009, 0x810b, 0x1f04, 0x234b, 0xa18c, 0x0e00,
-	0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012, 0x0005, 0x2019, 0x0002,
-	0x2009, 0x0101, 0x20a9, 0x0005, 0x8213, 0x1f04, 0x235c, 0xa294,
-	0x00e0, 0x2104, 0xa084, 0xff1f, 0xa205, 0x200a, 0x8319, 0x0118,
-	0x2009, 0x0201, 0x0c78, 0x0005, 0x2011, 0x0101, 0xd3fc, 0x1110,
-	0x2011, 0x0201, 0x20a9, 0x000c, 0x810b, 0x1f04, 0x2374, 0xa18c,
-	0xf000, 0x2204, 0xa084, 0x0fff, 0xa105, 0x2012, 0x0005, 0x2011,
-	0x0102, 0xd3fc, 0x1110, 0x2011, 0x0202, 0x2204, 0xa084, 0xf0cf,
-	0xa105, 0x2012, 0x0005, 0x00c6, 0x2061, 0x0100, 0xd1bc, 0x1110,
-	0x2061, 0x0200, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0020, 0x609a,
-	0x62ac, 0x63ac, 0x00ce, 0x0005, 0x00c6, 0x2061, 0x0100, 0xd1bc,
-	0x1110, 0x2061, 0x0200, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0022,
-	0x609a, 0x60a4, 0xa084, 0xffdf, 0x60ae, 0x00ce, 0x0005, 0x00c6,
-	0x2061, 0x0100, 0xd1bc, 0x1110, 0x2061, 0x0200, 0xc1bc, 0x8103,
-	0x8003, 0xa080, 0x0020, 0x609a, 0x60a4, 0xa28c, 0x0020, 0x0118,
-	0xc2ac, 0xa39d, 0x4000, 0xc3ec, 0xd3b4, 0x1108, 0xc3ed, 0x62ae,
-	0x2010, 0x60a4, 0x63ae, 0x2018, 0x00ce, 0x0005, 0x2091, 0x8000,
-	0x00c6, 0x00e6, 0x6818, 0xa005, 0x0904, 0x2427, 0xd1fc, 0x0118,
-	0x2061, 0x8dd0, 0x0010, 0x2061, 0x8cc0, 0x080c, 0x242f, 0x0560,
-	0x20a9, 0x0101, 0xd1fc, 0x0118, 0x2061, 0x8cd0, 0x0010, 0x2061,
-	0x8bc0, 0x00c6, 0x080c, 0x242f, 0x0128, 0x00ce, 0x8c60, 0x1f04,
-	0x23e9, 0x04a8, 0x000e, 0xd1fc, 0x0128, 0xa082, 0x8cd0, 0x2071,
-	0x4680, 0x0020, 0xa082, 0x8bc0, 0x2071, 0x4640, 0x7076, 0x7172,
-	0x2138, 0x2001, 0x0004, 0x7062, 0x707f, 0x000f, 0x71d0, 0xc1c4,
-	0x71d2, 0x080c, 0x22a4, 0x00c0, 0xd1fc, 0x1118, 0x2071, 0x4640,
-	0x0010, 0x2071, 0x4680, 0x6020, 0xc0dd, 0x6022, 0x7172, 0x2138,
-	0x2c00, 0x707a, 0x2001, 0x0006, 0x7062, 0x707f, 0x000f, 0x71d0,
-	0xc1c4, 0x71d2, 0x080c, 0x22a4, 0x2001, 0x0000, 0x0010, 0x2001,
-	0x0001, 0x2091, 0x8001, 0xa005, 0x00ee, 0x00ce, 0x0005, 0x2c04,
-	0xa005, 0x0170, 0x2060, 0x6010, 0xa306, 0x1140, 0x600c, 0xa206,
-	0x1128, 0x6014, 0xa106, 0x1110, 0xa006, 0x0020, 0x6000, 0x0c80,
-	0xa085, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x0016, 0x2079, 0x4680,
-	0x2071, 0x0100, 0xd1bc, 0x1120, 0x2079, 0x4640, 0x2071, 0x0200,
-	0x7920, 0xa18c, 0x000f, 0x70ec, 0xd0c4, 0x1110, 0x001e, 0x0060,
-	0x810b, 0x810b, 0x810b, 0x810b, 0x000e, 0xa18d, 0x0800, 0xd0bc,
-	0x1110, 0xa18d, 0x0f00, 0x2104, 0x00ee, 0x00fe, 0x0005, 0x2001,
-	0x4601, 0x2004, 0xd0ac, 0x1138, 0x68e4, 0xd0ac, 0x0120, 0xa084,
-	0x0006, 0x1108, 0x0009, 0x0005, 0x6014, 0x00e6, 0x0036, 0x2018,
-	0x2071, 0x4b40, 0xd0fc, 0x1110, 0x2071, 0x4ac0, 0x8007, 0xa084,
-	0x000f, 0x8003, 0x8003, 0x8003, 0xae70, 0x7004, 0xa084, 0x000a,
-	0x1904, 0x24fa, 0x7108, 0xa194, 0xff00, 0x0904, 0x24fa, 0xa18c,
-	0x00ff, 0x701c, 0xa084, 0xff00, 0x01c0, 0x7004, 0xa085, 0x003a,
-	0x7006, 0x2001, 0x0009, 0xa102, 0x16d8, 0x2001, 0x000a, 0xa102,
-	0x16d0, 0x2001, 0x000c, 0xa102, 0x16c8, 0x701c, 0xa084, 0x00ff,
-	0x701e, 0x7004, 0xa084, 0xffdf, 0x7006, 0x2001, 0x000a, 0xa106,
-	0x01a8, 0x2001, 0x000c, 0xa106, 0x01a0, 0x2001, 0x0012, 0xa106,
-	0x0198, 0x2001, 0x0014, 0xa106, 0x0190, 0x2001, 0x0019, 0xa106,
-	0x0188, 0x2001, 0x0032, 0xa106, 0x0180, 0x00d8, 0x2009, 0x000c,
-	0x00d0, 0x2009, 0x0012, 0x00b8, 0x2009, 0x0014, 0x00a0, 0x2009,
-	0x0019, 0x0088, 0x2009, 0x0020, 0x0070, 0x2009, 0x003f, 0x0058,
-	0x2009, 0x000a, 0x0040, 0x2009, 0x000c, 0x0028, 0x2009, 0x0019,
-	0x0010, 0x2011, 0x0000, 0x2100, 0xa205, 0x700a, 0x7004, 0xa085,
-	0x000a, 0x7006, 0x2071, 0x4600, 0x7004, 0xd0bc, 0x0158, 0xd3fc,
-	0x1120, 0x73ea, 0x2071, 0x4640, 0x0018, 0x73ee, 0x2071, 0x4680,
-	0x701f, 0x000d, 0x003e, 0x00ee, 0x0005, 0x2001, 0x01ff, 0x2004,
-	0xd0fc, 0x11d0, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x12a0,
-	0x2071, 0x0200, 0x71ec, 0xa18c, 0x1c00, 0x810f, 0x810c, 0x810c,
-	0x2079, 0x0100, 0x78ec, 0xa084, 0x1c00, 0x8007, 0x8004, 0x8004,
-	0xa105, 0xa08a, 0x0007, 0x0208, 0x0005, 0x0002, 0x254b, 0x2532,
-	0x254b, 0x2532, 0x2525, 0x253f, 0x2525, 0x7008, 0xa084, 0xc3ff,
-	0xa085, 0x3000, 0x700a, 0x7808, 0xa084, 0xc3ff, 0xa085, 0x3000,
-	0x780a, 0x0005, 0x7008, 0xa084, 0xc3ff, 0xa085, 0x2000, 0x700a,
-	0x7808, 0xa084, 0xc3ff, 0xa085, 0x2000, 0x780a, 0x0005, 0x7008,
-	0xa084, 0xc3ff, 0xa085, 0x0c00, 0x700a, 0x7808, 0xa084, 0xc3ff,
-	0xa085, 0x0c00, 0x780a, 0x0005, 0x0e04, 0x254c, 0x2091, 0x8000,
-	0x2071, 0x0000, 0x0006, 0x7018, 0xd084, 0x1de8, 0x000e, 0x2071,
-	0x0010, 0x70ca, 0x000e, 0x70c6, 0x70c3, 0x8002, 0x70db, 0x0a04,
-	0x70df, 0x0020, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080,
-	0x0cf8, 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x78a0, 0x708a, 0x758e,
-	0x7492, 0x7696, 0x779a, 0xa594, 0x003f, 0xd4f4, 0x0138, 0xd7bc,
-	0x1128, 0xa784, 0x007d, 0x1904, 0x3c74, 0x0871, 0xa49c, 0x000f,
-	0xa382, 0x0004, 0x0320, 0xa3a6, 0x0007, 0x1930, 0x2418, 0x8507,
-	0xa084, 0x000f, 0x0002, 0x2b49, 0x2c34, 0x2c72, 0x2ed8, 0x3256,
-	0x32ad, 0x3353, 0x33e2, 0x34b6, 0x3588, 0x259e, 0x259b, 0x2970,
-	0x2a56, 0x322a, 0x259b, 0x080c, 0x254c, 0x0005, 0xa006, 0x0038,
-	0x7808, 0xc08d, 0x780a, 0xa006, 0x7002, 0x704a, 0x7042, 0x70ce,
-	0x705c, 0xa005, 0x1904, 0x26ec, 0x7060, 0xa084, 0x0007, 0x0002,
-	0x25b8, 0x2626, 0x262e, 0x2637, 0x2640, 0x26d2, 0x2649, 0x2626,
-	0x7830, 0xd0bc, 0x1d10, 0x71d0, 0xd1bc, 0x19f8, 0xd1b4, 0x1904,
-	0x2603, 0x70a0, 0xa086, 0x0001, 0x09c0, 0x70b0, 0xa06d, 0x6800,
-	0xa065, 0xa055, 0x789b, 0x0080, 0x6b0c, 0x7baa, 0x6808, 0xa045,
-	0x6d10, 0x6804, 0xa06d, 0xa05d, 0xa886, 0x0001, 0x0118, 0x69bc,
-	0x7daa, 0x79aa, 0x68c0, 0xa04d, 0x6e1c, 0x2001, 0x0010, 0x0804,
-	0x281f, 0x705c, 0xa005, 0x1904, 0x259d, 0x00c6, 0x00d6, 0x70b0,
-	0xa06d, 0x6800, 0xa065, 0xa055, 0x789b, 0x0080, 0x6b0c, 0x7baa,
-	0x6808, 0xa045, 0x6d10, 0x6804, 0xa06d, 0xa05d, 0xa886, 0x0001,
-	0x0118, 0x69bc, 0x7daa, 0x79aa, 0x68c0, 0xa04d, 0x6e1c, 0x2001,
-	0x0020, 0x0804, 0x281f, 0x080c, 0x3c33, 0x1904, 0x259d, 0x781b,
-	0x0068, 0x70b8, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de,
-	0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d, 0x780a, 0x68bc, 0x703e,
-	0xc1b4, 0x71d2, 0x70b4, 0xa065, 0x68c0, 0x7056, 0x7003, 0x0002,
-	0x2d00, 0x704a, 0xad80, 0x0009, 0x7042, 0x0005, 0x080c, 0x3c33,
-	0x1120, 0x781b, 0x0054, 0x7003, 0x0004, 0x0005, 0x080c, 0x3c33,
-	0x1128, 0x2011, 0x000c, 0x0419, 0x7003, 0x0004, 0x0005, 0x080c,
-	0x3c33, 0x1128, 0x2011, 0x0006, 0x00d1, 0x7003, 0x0004, 0x0005,
-	0x080c, 0x3c33, 0x1128, 0x2011, 0x000d, 0x0089, 0x7003, 0x0004,
-	0x0005, 0x080c, 0x3c33, 0x1150, 0x2011, 0x0006, 0x0041, 0x7078,
-	0x707b, 0x0000, 0x2068, 0x704a, 0x7003, 0x0004, 0x0005, 0x7170,
-	0xc1fc, 0x8107, 0x7882, 0x789b, 0x0080, 0xa286, 0x000c, 0x1120,
-	0x7aaa, 0x2001, 0x0001, 0x0098, 0xa18c, 0x001f, 0xa18d, 0x00c0,
-	0x79aa, 0xa286, 0x000d, 0x0120, 0x7aaa, 0x2001, 0x0002, 0x0038,
-	0x78ab, 0x0020, 0x7174, 0x79aa, 0x7aaa, 0x2001, 0x0004, 0x789b,
-	0x0060, 0x78aa, 0x785b, 0x0004, 0x781b, 0x0113, 0x080c, 0x3c46,
-	0x707f, 0x000f, 0x70d0, 0xd0b4, 0x0168, 0xc0b4, 0x70d2, 0x00c6,
-	0x70b4, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001,
-	0x601a, 0x00ce, 0x0005, 0x7014, 0xa005, 0x1138, 0x70d0, 0xd0b4,
-	0x0128, 0x70b4, 0xac06, 0x1110, 0x0c29, 0x0005, 0x0016, 0x71a0,
-	0xa186, 0x0001, 0x0528, 0x00d6, 0x0026, 0x2100, 0x2011, 0x0001,
-	0xa212, 0x70b0, 0x2068, 0x6800, 0xac06, 0x0120, 0x8211, 0x01b0,
-	0x00c9, 0x0cc8, 0x00c6, 0x2100, 0x2011, 0x0001, 0xa212, 0x70b0,
-	0x2068, 0x6800, 0x2060, 0x6008, 0xa084, 0xfbef, 0x600a, 0x8211,
-	0x0110, 0x0041, 0x0cb0, 0x70a3, 0x0001, 0x00ce, 0x002e, 0x00de,
-	0x001e, 0x0005, 0xade8, 0x0005, 0x70a8, 0xad06, 0x1110, 0x70a4,
-	0x2068, 0x0005, 0x080c, 0x3c33, 0x1904, 0x259d, 0x7078, 0x2068,
-	0x7770, 0x080c, 0x3b6f, 0x2c50, 0x080c, 0x3cce, 0x789b, 0x0080,
-	0x6814, 0xa084, 0x001f, 0xc0bd, 0x78aa, 0x6e1c, 0x2041, 0x0001,
-	0x2001, 0x0004, 0x0804, 0x2824, 0x080c, 0x3c33, 0x1904, 0x259d,
-	0x789b, 0x0080, 0x705c, 0x2068, 0x6f14, 0x70d0, 0xd0b4, 0x0168,
-	0xc0b4, 0x70d2, 0x00c6, 0x70b4, 0xa065, 0x6008, 0xa084, 0xfbef,
-	0x600a, 0x6018, 0x8001, 0x601a, 0x00ce, 0x080c, 0x3b6f, 0x2c50,
-	0x080c, 0x3cce, 0x6824, 0xa005, 0x0130, 0xa082, 0x0006, 0x0208,
-	0x0010, 0x6827, 0x0005, 0x6814, 0xa084, 0x001f, 0xc0bd, 0x78aa,
-	0x2031, 0x0020, 0x2041, 0x0001, 0x2001, 0x0003, 0x0804, 0x2824,
-	0xc28d, 0x72d2, 0x72bc, 0xa200, 0xa015, 0x7150, 0x8108, 0xa12a,
-	0x0208, 0x71bc, 0x2164, 0x6504, 0x85ff, 0x1170, 0x7152, 0x8421,
-	0x1da8, 0x70d0, 0xd08c, 0x0128, 0x70cc, 0xa005, 0x1110, 0x70cf,
-	0x000a, 0x0005, 0x2200, 0x0c90, 0x70d0, 0xc08c, 0x70d2, 0x70cf,
-	0x0000, 0x6034, 0xa005, 0x1db0, 0x6708, 0xa784, 0x073f, 0x01d0,
-	0xd7d4, 0x1d80, 0xa784, 0x0021, 0x1d68, 0xa784, 0x0002, 0x0130,
-	0xa784, 0x0004, 0x0d38, 0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0218,
-	0x1d08, 0xa784, 0x0100, 0x0130, 0x6018, 0xa005, 0x19d8, 0xa7bc,
-	0xfeff, 0x670a, 0x2568, 0x6823, 0x0000, 0x6e1c, 0xa684, 0x000e,
-	0x6318, 0x0128, 0x601c, 0xa302, 0x0220, 0x0118, 0x0858, 0x83ff,
-	0x1948, 0x2d58, 0x2c50, 0x7152, 0xd7bc, 0x1120, 0x7028, 0x6022,
-	0x603a, 0x0010, 0xc7bc, 0x670a, 0x68c0, 0xa065, 0xa04d, 0x6100,
-	0x2a60, 0x2041, 0x0001, 0x6b14, 0xa39c, 0x001f, 0xa39d, 0x00c0,
-	0xd1fc, 0x0110, 0xd684, 0x0110, 0xa39c, 0xffbf, 0xd6a4, 0x0110,
-	0xa39d, 0x0020, 0xa684, 0x000e, 0x1904, 0x27d6, 0xc7a5, 0x670a,
-	0x2c00, 0x68c6, 0x77a0, 0xa786, 0x0001, 0x1178, 0x70d0, 0xd0b4,
-	0x1160, 0x7000, 0xa082, 0x0002, 0x1240, 0x7830, 0xd0bc, 0x1128,
-	0x789b, 0x0080, 0x7baa, 0x0804, 0x281d, 0x8739, 0x77a2, 0x2750,
-	0x77ac, 0xa7b0, 0x0005, 0x70a8, 0xa606, 0x1108, 0x76a4, 0x76ae,
-	0x2c3a, 0x8738, 0x2d3a, 0x8738, 0x283a, 0x8738, 0x233a, 0x8738,
-	0x253a, 0x7830, 0xd0bc, 0x0150, 0x2091, 0x8000, 0x2091, 0x303d,
-	0x70d0, 0xa084, 0x303d, 0x2091, 0x8000, 0x2090, 0xaad5, 0x0000,
-	0x0120, 0x8421, 0x2200, 0x1904, 0x2725, 0x0005, 0xd1dc, 0x0904,
-	0x37ce, 0x2029, 0x0020, 0xd69c, 0x1120, 0x8528, 0xd68c, 0x1108,
-	0x8528, 0x8840, 0x6f14, 0x610c, 0x8108, 0xa18c, 0x00ff, 0x70c8,
-	0xa160, 0x2c64, 0x8cff, 0x0188, 0x6014, 0xa706, 0x1dd0, 0x60b8,
-	0x8001, 0x60ba, 0x1d88, 0x2a60, 0x6008, 0xa085, 0x0100, 0x600a,
-	0x2200, 0x8421, 0x1904, 0x2725, 0x0005, 0x2a60, 0x610e, 0x69be,
-	0x2c00, 0x68c6, 0x8840, 0x6008, 0xc0d5, 0x600a, 0x77a0, 0xa786,
-	0x0001, 0x1904, 0x27ad, 0x70d0, 0xd0b4, 0x1904, 0x27ad, 0x7000,
-	0xa082, 0x0002, 0x1a04, 0x27ad, 0x7830, 0xd0bc, 0x1904, 0x27ad,
-	0x789b, 0x0080, 0x7baa, 0x7daa, 0x79aa, 0x2001, 0x0002, 0x0006,
-	0x6018, 0x8000, 0x601a, 0x0008, 0x0006, 0x2960, 0x6104, 0x2a60,
-	0x080c, 0x3ce1, 0x1590, 0xa184, 0x0018, 0x0180, 0xa184, 0x0010,
-	0x0118, 0x080c, 0x3977, 0x1548, 0xa184, 0x0008, 0x0138, 0x69a0,
-	0xa184, 0x0600, 0x1118, 0x080c, 0x3895, 0x00f8, 0x69a0, 0xa184,
-	0x1e00, 0x0528, 0xa184, 0x0800, 0x0178, 0x00c6, 0x2960, 0x6000,
-	0xa085, 0x2000, 0x6002, 0x6104, 0xa18d, 0x0010, 0x6106, 0x00ce,
-	0x080c, 0x3977, 0x1150, 0x69a0, 0xa184, 0x0200, 0x0118, 0x080c,
-	0x38da, 0x0018, 0xa184, 0x0400, 0x19f0, 0x69a0, 0xa184, 0x1000,
-	0x0130, 0x6914, 0xa18c, 0xff00, 0x810f, 0x080c, 0x239c, 0x002e,
-	0xa68c, 0x00e0, 0xa684, 0x0060, 0x0128, 0xa086, 0x0060, 0x1110,
-	0xa18d, 0x4000, 0xa18d, 0x0104, 0x69b6, 0x789b, 0x0060, 0x2800,
-	0x78aa, 0x6818, 0xc0fd, 0x681a, 0xd6bc, 0x0168, 0xc0fc, 0x7083,
-	0x0000, 0xa08a, 0x000d, 0x0328, 0xa08a, 0x000c, 0x7182, 0x2001,
-	0x000c, 0x800c, 0x7186, 0x78aa, 0x3518, 0x3340, 0x3428, 0x8000,
-	0x80ac, 0xaf80, 0x002b, 0x20a0, 0x789b, 0x0000, 0xad80, 0x000b,
-	0x2098, 0x53a6, 0x23a8, 0x2898, 0x25a0, 0xa286, 0x0020, 0x1508,
-	0x70d0, 0xc0b5, 0x70d2, 0x2c00, 0x70b6, 0x2d00, 0x70ba, 0x6814,
-	0xc0fc, 0x8007, 0x7882, 0xa286, 0x0002, 0x0904, 0x28f5, 0x70a0,
-	0x8000, 0x70a2, 0x74b0, 0xa498, 0x0005, 0x70a8, 0xa306, 0x1108,
-	0x73a4, 0x73b2, 0xa286, 0x0010, 0x0904, 0x259d, 0x00de, 0x00ce,
-	0x0005, 0x7000, 0xa005, 0x19e0, 0xa286, 0x0002, 0x1904, 0x290c,
-	0x080c, 0x3c33, 0x19a8, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x2091,
-	0x8000, 0x781b, 0x0068, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de,
-	0x6898, 0x78d2, 0x78da, 0x2091, 0x8001, 0x7808, 0xc08d, 0x780a,
-	0x0126, 0x00d6, 0x00c6, 0x70d0, 0xa084, 0x2e00, 0x2090, 0x00ce,
-	0x00de, 0x012e, 0x2900, 0x7056, 0x68bc, 0x703e, 0x7003, 0x0002,
-	0x2d00, 0x704a, 0xad80, 0x0009, 0x7042, 0x7830, 0xd0bc, 0x0140,
-	0x2091, 0x303d, 0x70d0, 0xa084, 0x303d, 0x2091, 0x8000, 0x2090,
-	0x70a0, 0xa005, 0x1108, 0x0005, 0x8421, 0x0de8, 0x724c, 0x70bc,
-	0xa200, 0xa015, 0x0804, 0x2725, 0xa286, 0x0010, 0x1560, 0x080c,
-	0x3c33, 0x1904, 0x28a0, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x781b,
-	0x0068, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2,
-	0x78da, 0x7808, 0xc08d, 0x780a, 0x70a0, 0x8000, 0x70a2, 0x74b0,
-	0xa490, 0x0005, 0x70a8, 0xa206, 0x1108, 0x72a4, 0x72b2, 0x2900,
-	0x7056, 0x68bc, 0x703e, 0x7003, 0x0002, 0x2d00, 0x704a, 0xad80,
-	0x0009, 0x7042, 0x0005, 0x6bb4, 0xa39d, 0x2000, 0x7b5a, 0x6814,
-	0xc0fc, 0x8007, 0x7882, 0x6b94, 0x7bd6, 0x7bde, 0x6e98, 0x7ed2,
-	0x7eda, 0x781b, 0x0068, 0x2900, 0x7056, 0x7202, 0x7808, 0xc08d,
-	0x780a, 0x2300, 0xa605, 0x0170, 0x70d0, 0xa084, 0x2e00, 0xa086,
-	0x2600, 0x1118, 0x2009, 0x0000, 0x0010, 0x2009, 0x0001, 0xa284,
-	0x000f, 0x0023, 0xad80, 0x0009, 0x7042, 0x0005, 0x296e, 0x41d9,
-	0x41d9, 0x41c7, 0x41d9, 0x296e, 0x296e, 0x296e, 0x080c, 0x254c,
-	0x7808, 0xa084, 0xfffd, 0x780a, 0x00f6, 0x2079, 0x4600, 0x78ac,
-	0x00fe, 0xd084, 0x01b0, 0x7060, 0xa086, 0x0001, 0x0904, 0x2a32,
-	0x7060, 0xa086, 0x0005, 0x1158, 0x7078, 0x2068, 0x681b, 0x0004,
+	0x0110, 0xc0c5, 0x7812, 0x080c, 0x1b34, 0x000e, 0x7812, 0x080c,
+	0x1b7f, 0x2001, 0x4007, 0x0804, 0x13bc, 0x6104, 0xa18c, 0x00ff,
+	0xa186, 0x0005, 0x1118, 0x601c, 0xc0bd, 0x601e, 0x74c4, 0x73c8,
+	0x72cc, 0x6014, 0x2091, 0x8000, 0x00e6, 0x2009, 0x0012, 0xd0fc,
+	0x1118, 0x2071, 0x4740, 0x0018, 0x2071, 0x4780, 0xc1fd, 0x792a,
+	0x7063, 0x0005, 0x71d0, 0xc1c4, 0x71d2, 0x7366, 0x726a, 0x746e,
+	0x7072, 0x7077, 0x0000, 0x2c00, 0x707a, 0xa02e, 0x2530, 0x611c,
+	0xa184, 0x0060, 0x0110, 0x080c, 0x3fe9, 0x00ee, 0x6596, 0x65a6,
+	0x669a, 0x66aa, 0x60af, 0x0000, 0x60b3, 0x0000, 0x6714, 0x6023,
+	0x0000, 0x6024, 0xa096, 0x0001, 0x1110, 0x8000, 0x6026, 0x080c,
+	0x22d5, 0x2091, 0x8001, 0x0005, 0x70c3, 0x4005, 0x0804, 0x13bd,
+	0x20a9, 0x0005, 0x2099, 0x4714, 0x2091, 0x8000, 0x530a, 0x2091,
+	0x8001, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9,
+	0x0000, 0x0005, 0x71c4, 0x70c7, 0x0000, 0x791e, 0x0804, 0x13ba,
+	0x71c4, 0x71c6, 0x2168, 0x0010, 0x2069, 0x1000, 0x690c, 0xa016,
+	0x2d04, 0xa210, 0x8d68, 0x8109, 0x1dd8, 0xa285, 0x0000, 0x1118,
+	0x70c3, 0x4000, 0x0010, 0x70c3, 0x4003, 0x70ca, 0x0804, 0x13bd,
+	0x7964, 0x71c6, 0x71c4, 0xa182, 0x0003, 0x1a04, 0x13b3, 0x7966,
+	0x0804, 0x13ba, 0x7964, 0x71c6, 0x0804, 0x13ba, 0x7900, 0x71c6,
+	0x71c4, 0x7902, 0x0804, 0x13ba, 0x7900, 0x71c6, 0x0804, 0x13ba,
+	0x70c4, 0x2011, 0x0000, 0xa08c, 0x000d, 0x0160, 0x810c, 0x0230,
+	0x8210, 0x810c, 0x810c, 0x0210, 0x8210, 0x810c, 0x81ff, 0x1904,
+	0x13b4, 0x8210, 0x7a0e, 0xd28c, 0x0538, 0x7910, 0xc1cd, 0x7912,
+	0x2009, 0x0021, 0x2019, 0x0003, 0xd284, 0x01c0, 0x8108, 0x2019,
+	0x0041, 0x2011, 0x8f4e, 0x2312, 0x2019, 0x0042, 0x8210, 0x2312,
+	0x2019, 0x0043, 0x8210, 0x2312, 0x2019, 0x0046, 0x8210, 0x2312,
+	0x2019, 0x0047, 0x8210, 0x2312, 0x2019, 0x0006, 0x2011, 0x8f53,
+	0x2112, 0x2011, 0x8f73, 0x2312, 0x7904, 0x7806, 0x0804, 0x13b9,
+	0x7804, 0x70c6, 0x0804, 0x13ba, 0x71c4, 0xd1fc, 0x1118, 0x2011,
+	0x4bc0, 0x0010, 0x2011, 0x4c40, 0x8107, 0xa084, 0x000f, 0x8003,
+	0x8003, 0x8003, 0xa268, 0x2011, 0x0000, 0x6814, 0xd0fc, 0x0110,
+	0xa295, 0x0200, 0xd0b4, 0x0110, 0xa295, 0x0001, 0x6b0c, 0x6800,
+	0x70da, 0x0804, 0x13b7, 0x7814, 0xd0f4, 0x0130, 0x2001, 0x4007,
+	0x70db, 0x0000, 0xa005, 0x0048, 0xd0fc, 0x0130, 0x2001, 0x4007,
+	0x70db, 0x0001, 0xa005, 0x0008, 0xa006, 0x0005, 0x7814, 0xd0f4,
+	0x0130, 0x2001, 0x4007, 0x70db, 0x0000, 0xa005, 0x0008, 0xa006,
+	0x0005, 0x7814, 0xd0fc, 0x0130, 0x2001, 0x4007, 0x70db, 0x0001,
+	0xa005, 0x0008, 0xa006, 0x0005, 0x7112, 0x721a, 0x731e, 0x7810,
+	0xd0c4, 0x0110, 0x7422, 0x7526, 0xac80, 0x0001, 0x8108, 0x810c,
+	0x81a9, 0x8098, 0x20a1, 0x0030, 0x7003, 0x0000, 0x6084, 0x20a2,
+	0x53a6, 0x7007, 0x0001, 0x7974, 0xa184, 0xff00, 0x0140, 0x810f,
+	0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0018, 0x8107,
+	0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, 0xa006, 0xa211, 0x7d10,
+	0xd5c4, 0x0120, 0x7b84, 0xa319, 0x7c80, 0xa421, 0x7008, 0xd0fc,
+	0x0de8, 0x7003, 0x0001, 0x7007, 0x0006, 0x711a, 0x721e, 0x7d10,
+	0xd5c4, 0x0110, 0x7322, 0x7426, 0xa084, 0x01e0, 0x0005, 0x7848,
+	0xa065, 0x0120, 0x2c04, 0x784a, 0x2063, 0x0000, 0x0005, 0x00f6,
+	0x2079, 0x4700, 0x7848, 0x2062, 0x2c00, 0xa005, 0x1110, 0x080c,
+	0x2575, 0x784a, 0x00fe, 0x0005, 0x2011, 0x9100, 0x7a4a, 0x7bc4,
+	0x8319, 0x0128, 0xa280, 0x0032, 0x2012, 0x2010, 0x0cc8, 0x2013,
+	0x0000, 0x0005, 0x0016, 0x0026, 0xd7fc, 0x1118, 0x2011, 0x4cc0,
+	0x0010, 0x2011, 0x6cc0, 0xa784, 0x0f00, 0x800b, 0xa784, 0x001f,
+	0x0120, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa268, 0x002e,
+	0x001e, 0x0005, 0x0c39, 0x2900, 0x682a, 0x2a00, 0x682e, 0x6808,
+	0xa084, 0xf9ef, 0xa80d, 0x690a, 0x00e6, 0xd7fc, 0x1128, 0x2009,
+	0x4752, 0x2071, 0x4740, 0x0020, 0x2009, 0x4792, 0x2071, 0x4780,
+	0x210c, 0x6804, 0xa005, 0x0148, 0xa116, 0x1138, 0x2060, 0x6000,
+	0x6806, 0x0016, 0x200b, 0x0000, 0x0018, 0x2009, 0x0000, 0x0016,
+	0x6804, 0xa065, 0x0178, 0x6000, 0x6806, 0x0421, 0x080c, 0x1db2,
+	0x6810, 0x7908, 0x8109, 0x790a, 0x8001, 0x6812, 0x1d88, 0x7910,
+	0xc1a5, 0x7912, 0x001e, 0x6902, 0x6906, 0x2d00, 0x2060, 0x080c,
+	0x26bf, 0x00ee, 0x0005, 0xa065, 0x0160, 0x2008, 0x609c, 0xa005,
+	0x0128, 0x2062, 0x609f, 0x0000, 0xa065, 0x0cc0, 0x7848, 0x794a,
+	0x2062, 0x0005, 0x6007, 0x0103, 0x608f, 0x0000, 0x20a9, 0x001c,
+	0xac80, 0x0005, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x6828, 0x601a,
+	0x682c, 0x6022, 0x0005, 0x00e6, 0xd7fc, 0x1128, 0x2071, 0x4740,
+	0x2031, 0x47c0, 0x0020, 0x2071, 0x4780, 0x2031, 0x49c0, 0x704c,
+	0xa08c, 0x0200, 0x1128, 0xa608, 0x2d0a, 0x8000, 0x704e, 0xa006,
+	0x00ee, 0x0005, 0x00f6, 0xd7fc, 0x1118, 0x2079, 0x4740, 0x0010,
+	0x2079, 0x4780, 0x080c, 0x1b9a, 0x2091, 0x8000, 0x6804, 0x780a,
+	0xa065, 0x05f0, 0x0030, 0x2c00, 0x780a, 0x2060, 0x6000, 0xa065,
+	0x05b8, 0x6010, 0xa306, 0x1db8, 0x600c, 0xa206, 0x1da0, 0x2c28,
+	0x7848, 0xac06, 0x1108, 0x0448, 0x6804, 0xac06, 0x1140, 0x6000,
+	0x2060, 0x6806, 0xa005, 0x1118, 0x6803, 0x0000, 0x0048, 0x6400,
+	0x7808, 0x2060, 0x6402, 0xa486, 0x0000, 0x1110, 0x2c00, 0x6802,
+	0x2560, 0x080c, 0x1c02, 0x601b, 0x0005, 0x6023, 0x0020, 0x00fe,
+	0x080c, 0x1db2, 0x00f6, 0x7908, 0x8109, 0x790a, 0x6810, 0x8001,
+	0x6812, 0x1118, 0x7810, 0xc0a5, 0x7812, 0x2001, 0xffff, 0xa005,
+	0x00fe, 0x0005, 0x0076, 0x2700, 0x2039, 0x0000, 0xd0fc, 0x0108,
+	0xc7fd, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x2091,
+	0x8000, 0x080c, 0x1bb2, 0x8738, 0xa784, 0x001f, 0x1dd0, 0xa7bc,
+	0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x1d90, 0x2091,
+	0x8001, 0x007e, 0x0005, 0x786c, 0x2009, 0x8f74, 0x210c, 0xa10d,
+	0x0118, 0xa065, 0x0804, 0x20a1, 0x2061, 0x0000, 0x6018, 0xd084,
+	0x11b8, 0x7810, 0xd08c, 0x0130, 0xc08c, 0x7812, 0xc7fc, 0x2069,
+	0x4740, 0x0028, 0xc08d, 0x7812, 0x2069, 0x4780, 0xc7fd, 0x2091,
+	0x8000, 0x681c, 0x681f, 0x0000, 0x2091, 0x8001, 0xa005, 0x1108,
+	0x0005, 0xa08c, 0xfff0, 0x0110, 0x080c, 0x2575, 0x0002, 0x1cd7,
+	0x1cda, 0x1ce0, 0x1ce4, 0x1cd8, 0x1ce8, 0x1cd8, 0x1cd8, 0x1cd8,
+	0x1cee, 0x1d18, 0x1d1b, 0x1d20, 0x1d29, 0x1cd8, 0x1cd8, 0x0005,
+	0x080c, 0x2575, 0x080c, 0x1c7a, 0x2001, 0x8001, 0x0804, 0x1d32,
+	0x2001, 0x8003, 0x0804, 0x1d32, 0x2001, 0x8004, 0x0804, 0x1d32,
+	0x080c, 0x1c7a, 0x2001, 0x8006, 0x0804, 0x1d32, 0x2011, 0x800a,
+	0x2091, 0x8000, 0xd7fc, 0x1118, 0x2069, 0x4740, 0x0010, 0x2069,
+	0x4780, 0x2038, 0x6800, 0xa086, 0x0000, 0x0120, 0x6f1e, 0x2091,
+	0x8001, 0x0005, 0x0026, 0x6870, 0xa0bc, 0xff00, 0x2041, 0x0021,
+	0x2049, 0x0004, 0x2051, 0x0010, 0x080c, 0x1bb2, 0x8738, 0xa784,
+	0x001f, 0x1dd0, 0x2091, 0x8001, 0x000e, 0x6970, 0x71c6, 0x00d0,
+	0x2001, 0x800c, 0x00b8, 0x080c, 0x1c7a, 0x2001, 0x800d, 0x0090,
+	0xd7fc, 0x0110, 0x78e4, 0x0008, 0x78e0, 0x70c6, 0x2001, 0x800e,
+	0x0048, 0xd7fc, 0x0110, 0x78ec, 0x0008, 0x78e8, 0x70c6, 0x2001,
+	0x800f, 0x0000, 0x70c2, 0xd7fc, 0x1118, 0x70db, 0x0000, 0x0010,
+	0x70db, 0x0001, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x4080,
+	0x0005, 0xac80, 0x0001, 0x81ff, 0x0518, 0x2099, 0x0030, 0x20a0,
+	0x700c, 0xa084, 0x07ff, 0x0100, 0x7018, 0x0006, 0x701c, 0x0006,
+	0x7020, 0x0006, 0x7024, 0x0006, 0x7112, 0x81ac, 0x721a, 0x731e,
+	0x7422, 0x7526, 0x7003, 0x0001, 0x7007, 0x0001, 0x7008, 0x800b,
+	0x1ee8, 0x7007, 0x0002, 0xa08c, 0x01e0, 0x1110, 0x53a5, 0xa006,
+	0x7003, 0x0000, 0x7007, 0x0004, 0x000e, 0x7026, 0x000e, 0x7022,
+	0x000e, 0x701e, 0x000e, 0x701a, 0x0005, 0x2011, 0x0020, 0x2009,
+	0x0010, 0x6b0a, 0x6c0e, 0x681f, 0x0201, 0x6803, 0xfd20, 0x6807,
+	0x0038, 0x6a1a, 0x2d00, 0xa0e8, 0x0008, 0xa290, 0x0004, 0x8109,
+	0x1d80, 0x0005, 0x70ec, 0xd0dc, 0x1520, 0x2029, 0x0001, 0x7814,
+	0xd0cc, 0x1160, 0x70ec, 0xd0e4, 0x2019, 0x0c0a, 0x2021, 0x000a,
+	0x1120, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x0070, 0x70ec, 0xd0e4,
+	0x1128, 0x2019, 0x180c, 0x2021, 0x000c, 0x0030, 0x2019, 0x1809,
+	0x2021, 0x0009, 0xa5ad, 0x0200, 0x6b0a, 0x6c0e, 0x6d1e, 0x6807,
+	0x0038, 0x0005, 0x6004, 0x6086, 0x2c08, 0x2063, 0x0000, 0x7868,
+	0xa005, 0x796a, 0x0110, 0x2c02, 0x0008, 0x796e, 0x0005, 0x00c6,
+	0x2061, 0x4700, 0x6887, 0x0103, 0x2d08, 0x206b, 0x0000, 0x6068,
+	0xa005, 0x616a, 0x0110, 0x2d02, 0x0008, 0x616e, 0x00ce, 0x0005,
+	0x2091, 0x8000, 0x2c04, 0x786e, 0xa005, 0x1108, 0x786a, 0x2091,
+	0x8001, 0x609c, 0xa005, 0x0188, 0x00c6, 0x2060, 0x2008, 0x609c,
+	0xa005, 0x0138, 0x2062, 0x609f, 0x0000, 0xa065, 0x609c, 0xa005,
+	0x1dc8, 0x7848, 0x794a, 0x2062, 0x00ce, 0x7848, 0x2062, 0x609f,
+	0x0000, 0xac85, 0x0000, 0x1110, 0x080c, 0x2575, 0x784a, 0x0005,
+	0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e, 0x1208, 0xa200,
+	0x1f04, 0x1dfc, 0x8086, 0x818e, 0x0005, 0x0156, 0x20a9, 0x0010,
+	0xa005, 0x01b8, 0xa11a, 0x12a8, 0x8213, 0x818d, 0x0228, 0xa11a,
+	0x1220, 0x1f04, 0x1e0c, 0x0028, 0xa11a, 0x2308, 0x8210, 0x1f04,
+	0x1e0c, 0x0006, 0x3200, 0xa084, 0xefff, 0x2080, 0x000e, 0x015e,
+	0x0005, 0x0006, 0x3200, 0xa085, 0x1000, 0x0cb8, 0x7d74, 0x70d0,
+	0xa506, 0x0904, 0x1eda, 0x7810, 0x2050, 0x080c, 0x1b77, 0x0904,
+	0x1eda, 0xa046, 0x7970, 0x2500, 0x8000, 0xa112, 0x2009, 0x0040,
+	0x1208, 0x0030, 0x72d0, 0xa206, 0x0118, 0x8840, 0x2009, 0x0080,
+	0x00c6, 0x7112, 0x7007, 0x0001, 0x2099, 0x0030, 0x20a9, 0x0020,
+	0xac80, 0x0001, 0x20a0, 0x2061, 0x0000, 0x88ff, 0x0110, 0x080c,
+	0x1b77, 0x7008, 0xd0fc, 0x0de8, 0x7007, 0x0002, 0x2091, 0x8001,
+	0xa08c, 0x01e0, 0x1538, 0x53a5, 0x8cff, 0x1120, 0x88ff, 0x0904,
+	0x1ec7, 0x0050, 0x2c00, 0x788e, 0x20a9, 0x0020, 0xac80, 0x0001,
+	0x20a0, 0x53a5, 0x0804, 0x1ec7, 0xa046, 0x7218, 0x731c, 0xdac4,
+	0x0110, 0x7420, 0x7524, 0xa292, 0x0040, 0xa39b, 0x0000, 0xa4a3,
+	0x0000, 0xa5ab, 0x0000, 0x721a, 0x731e, 0xdac4, 0x0118, 0x7422,
+	0x7526, 0xa006, 0x7007, 0x0004, 0x0904, 0x1ec7, 0x8cff, 0x0110,
+	0x080c, 0x1b7f, 0x00ce, 0x080c, 0x1b7f, 0xa046, 0x7888, 0x8000,
+	0x788a, 0xa086, 0x0002, 0x01c0, 0x7a7c, 0x7b78, 0xdac4, 0x0110,
+	0x7c84, 0x7d80, 0x7974, 0x8107, 0x8004, 0x8004, 0xa210, 0xa399,
+	0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x721a, 0x731e, 0xdac4,
+	0x0588, 0x7422, 0x7526, 0x0470, 0x6014, 0xd0fc, 0x1118, 0x2069,
+	0x4740, 0x0010, 0x2069, 0x4780, 0x2091, 0x8000, 0x681f, 0x0002,
+	0x88ff, 0x0120, 0xa046, 0x788c, 0x2060, 0x0c70, 0x788b, 0x0000,
+	0x78ac, 0xa085, 0x0003, 0x78ae, 0x2091, 0x8001, 0x0098, 0x00ce,
+	0x788b, 0x0000, 0x080c, 0x205c, 0x6004, 0xa084, 0x000f, 0x0059,
+	0x88ff, 0x0130, 0x788c, 0x2060, 0x6004, 0xa084, 0x000f, 0x0019,
+	0x0804, 0x1e26, 0x0005, 0x0002, 0x1eec, 0x1f07, 0x1f20, 0x1eec,
+	0x1f2d, 0x1efd, 0x1eec, 0x1eec, 0x1eec, 0x1f05, 0x1f1e, 0x1eec,
+	0x1eec, 0x1eec, 0x1eec, 0x1eec, 0x2039, 0x0400, 0x78bc, 0xa705,
+	0x78be, 0x6008, 0xa705, 0x600a, 0x080c, 0x1f69, 0x609c, 0x78ba,
+	0x609f, 0x0000, 0x080c, 0x2048, 0x0005, 0x78bc, 0xd0c4, 0x0108,
+	0x0c58, 0x601c, 0xc0bd, 0x601e, 0x0030, 0x080c, 0x2086, 0x78bc,
+	0xd0c4, 0x0108, 0x0c08, 0x78bf, 0x0000, 0x6004, 0x8007, 0xa084,
+	0x00ff, 0x78b2, 0x8001, 0x0138, 0x080c, 0x1f69, 0x0120, 0x78bc,
+	0xc0c5, 0x78be, 0x0010, 0x0804, 0x1f84, 0x0005, 0x080c, 0x2083,
+	0x78bc, 0xa08c, 0x0e00, 0x1110, 0xd0c4, 0x1108, 0x0828, 0x080c,
+	0x1f69, 0x1110, 0x0804, 0x1f84, 0x0005, 0x78bc, 0xd0c4, 0x0110,
+	0x0804, 0x1eec, 0x78bf, 0x0000, 0x6714, 0x2011, 0x0001, 0x22a8,
+	0x6018, 0xa084, 0x00ff, 0xa005, 0x0188, 0xa7bc, 0xff00, 0x20a9,
+	0x0020, 0xa08e, 0x0001, 0x0150, 0xa7bc, 0x8000, 0x2011, 0x0002,
+	0x20a9, 0x0100, 0xa08e, 0x0002, 0x0108, 0x00c0, 0x080c, 0x1b9a,
+	0x2d00, 0x2091, 0x8000, 0x682b, 0x0000, 0x682f, 0x0000, 0x6808,
+	0xa084, 0xffde, 0x680a, 0xade8, 0x0010, 0x2091, 0x8001, 0x1f04,
+	0x1f51, 0x8211, 0x0118, 0x20a9, 0x0100, 0x0c58, 0x080c, 0x1b7f,
+	0x0005, 0x609f, 0x0000, 0x78b4, 0xa06d, 0x2c00, 0x78b6, 0x1110,
+	0x78ba, 0x0038, 0x689e, 0x2d00, 0x6002, 0x78b8, 0xad06, 0x1108,
+	0x6002, 0x78b0, 0x8001, 0x78b2, 0x1130, 0x78bc, 0xc0c4, 0x78be,
+	0x78b8, 0x2060, 0xa006, 0x0005, 0x00e6, 0xa02e, 0x2530, 0x7dba,
+	0x7db6, 0x65ae, 0x65b2, 0x601c, 0x60a2, 0x2048, 0xa984, 0xe1ff,
+	0x601e, 0xa984, 0x0060, 0x0160, 0x080c, 0x3fe9, 0x86ff, 0x1140,
+	0x85ff, 0x1130, 0x2039, 0x0800, 0x080c, 0x2048, 0x0804, 0x2046,
+	0x6596, 0x65a6, 0x669a, 0x66aa, 0x6714, 0x2071, 0x4780, 0xd7fc,
+	0x1110, 0x2071, 0x4740, 0xa784, 0x0f00, 0x800b, 0xa784, 0x001f,
+	0x0120, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0x71c0, 0xa168,
+	0x2700, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0x71c4,
+	0xa100, 0x60c2, 0x2091, 0x8000, 0x7814, 0xd0c4, 0x0138, 0xd7fc,
+	0x1118, 0xd0f4, 0x1140, 0x0010, 0xd0fc, 0x1128, 0x6e08, 0xd684,
+	0x01f0, 0xd9fc, 0x11e0, 0x2091, 0x8001, 0x080c, 0x1c02, 0x2091,
+	0x8000, 0x080c, 0x1db2, 0x2091, 0x8001, 0x7814, 0xd0c4, 0x0904,
+	0x2046, 0xd7fc, 0x1120, 0xd0f4, 0x1130, 0x0804, 0x2046, 0xd0fc,
+	0x1110, 0x0804, 0x2046, 0x601b, 0x0021, 0x0804, 0x2046, 0x6024,
+	0xa096, 0x0001, 0x1110, 0x8000, 0x6026, 0x6a10, 0x6814, 0xa202,
+	0x0268, 0x0160, 0x2091, 0x8001, 0x2039, 0x0200, 0x609c, 0x78ba,
+	0x609f, 0x0000, 0x080c, 0x2048, 0x0804, 0x2046, 0x2c08, 0xd9fc,
+	0x01f0, 0x6800, 0xa065, 0x01d8, 0x6a04, 0x7000, 0xa084, 0x0002,
+	0x0168, 0x7048, 0xa206, 0x1150, 0x6b04, 0x2160, 0x2304, 0x6002,
+	0xa005, 0x1108, 0x6902, 0x2260, 0x6102, 0x0098, 0x2d00, 0x2060,
+	0x080c, 0x26bf, 0x6e08, 0x2160, 0x6202, 0x6906, 0x0050, 0x6800,
+	0x6902, 0xa065, 0x0110, 0x6102, 0x0008, 0x6906, 0x2160, 0x6003,
+	0x0000, 0x2160, 0xd9fc, 0x0118, 0xa6b4, 0xfffc, 0x6e0a, 0x6810,
+	0x7d08, 0x8528, 0x7d0a, 0x8000, 0x6812, 0x2091, 0x8001, 0xd6b4,
+	0x0128, 0xa6b6, 0x0040, 0x6e0a, 0x080c, 0x1c13, 0x00ee, 0x0005,
+	0x6008, 0xa705, 0x600a, 0x2091, 0x8000, 0x080c, 0x1db2, 0x2091,
+	0x8001, 0x78b8, 0xa065, 0x0128, 0x609c, 0x78ba, 0x609f, 0x0000,
+	0x0c78, 0x78b6, 0x78ba, 0x0005, 0x7970, 0x7874, 0x2818, 0xd384,
+	0x0118, 0x8000, 0xa112, 0x0220, 0x8000, 0xa112, 0x1278, 0xc384,
+	0x7a7c, 0x721a, 0x7a78, 0x721e, 0xdac4, 0x0120, 0x7a84, 0x7222,
+	0x7a80, 0x7226, 0xa006, 0xd384, 0x0108, 0x8000, 0x7876, 0x70d2,
+	0x781c, 0xa005, 0x0138, 0x8001, 0x781e, 0x1120, 0x0e04, 0x2082,
+	0x2091, 0x4080, 0x0005, 0x2039, 0x2098, 0x0010, 0x2039, 0x209e,
+	0x2704, 0xa005, 0x0160, 0xac00, 0x2068, 0x6908, 0x6810, 0x6912,
+	0x680a, 0x690c, 0x6814, 0x6916, 0x680e, 0x8738, 0x0c88, 0x0005,
+	0x0003, 0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0015, 0x001b,
+	0x0000, 0x2041, 0x0000, 0x780c, 0x0002, 0x224a, 0x2225, 0x20a9,
+	0x2119, 0x2039, 0x8f74, 0x2734, 0x7d10, 0x00c0, 0x6084, 0xa086,
+	0x0103, 0x1904, 0x2103, 0x6114, 0x6018, 0xa105, 0x0120, 0x86ff,
+	0x11d8, 0x0804, 0x2103, 0x8603, 0xa080, 0x8f55, 0x620c, 0x2202,
+	0x8000, 0x6210, 0x2202, 0x080c, 0x1dd0, 0x8630, 0xa68e, 0x000f,
+	0x0904, 0x2184, 0x786c, 0xa065, 0x1d08, 0x7808, 0xa602, 0x1220,
+	0xd5ac, 0x1110, 0x263a, 0x0005, 0xa682, 0x0003, 0x1a04, 0x2184,
+	0x2091, 0x8000, 0x2069, 0x0000, 0x6818, 0xd084, 0x11f8, 0x2011,
+	0x8f55, 0x2204, 0x70c6, 0x8210, 0x2204, 0x70ca, 0xd684, 0x1130,
+	0x8210, 0x2204, 0x70da, 0x8210, 0x2204, 0x70de, 0xa685, 0x8020,
+	0x70c2, 0x681b, 0x0001, 0x2091, 0x4080, 0x7810, 0xa084, 0xffcf,
+	0x7812, 0x2091, 0x8001, 0x203b, 0x0000, 0x0005, 0x7810, 0xc0ad,
+	0x7812, 0x0804, 0x2184, 0x263a, 0x080c, 0x2250, 0x1904, 0x226c,
+	0x786c, 0xa065, 0x1904, 0x20ae, 0x2091, 0x8000, 0x7810, 0xa084,
+	0xffcf, 0x86ff, 0x0108, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0804,
+	0x226c, 0x2039, 0x8f74, 0x2734, 0x7d10, 0x00a0, 0x6084, 0xa086,
+	0x0103, 0x1904, 0x216e, 0x6114, 0x6018, 0xa105, 0x0120, 0x86ff,
+	0x11b8, 0x0804, 0x216e, 0xa680, 0x8f55, 0x620c, 0x2202, 0x080c,
+	0x1dd0, 0x8630, 0xa68e, 0x001e, 0x0904, 0x2184, 0x786c, 0xa065,
+	0x1d28, 0x7808, 0xa602, 0x1220, 0xd5ac, 0x1110, 0x263a, 0x0005,
+	0xa682, 0x0006, 0x1a04, 0x2184, 0x2091, 0x8000, 0x2069, 0x0000,
+	0x6818, 0xd084, 0x11f8, 0x2011, 0x8f55, 0x2009, 0x8f4e, 0x26a8,
+	0x211c, 0x2204, 0x201a, 0x8108, 0x8210, 0x1f04, 0x2150, 0xa685,
+	0x8030, 0x70c2, 0x681b, 0x0001, 0x2091, 0x4080, 0x7810, 0xa084,
+	0xffcf, 0x7812, 0x2091, 0x8001, 0xa006, 0x2009, 0x8f75, 0x200a,
+	0x203a, 0x0005, 0x7810, 0xc0ad, 0x7812, 0x00b0, 0x263a, 0x080c,
+	0x2250, 0x1904, 0x226c, 0x786c, 0xa065, 0x1904, 0x211e, 0x2091,
+	0x8000, 0x7810, 0xa084, 0xffcf, 0x86ff, 0x0108, 0xc0ad, 0x7812,
+	0x2091, 0x8001, 0x0804, 0x226c, 0x2091, 0x8000, 0x7007, 0x0004,
+	0x7994, 0x70d4, 0xa102, 0x0228, 0x0168, 0x7b90, 0xa302, 0x1150,
+	0x0010, 0x8002, 0x1138, 0x263a, 0x7810, 0xc0ad, 0x7812, 0x2091,
+	0x8001, 0x0005, 0xa184, 0xff00, 0x0140, 0x810f, 0x810c, 0x810c,
+	0x8004, 0x8004, 0x8007, 0xa100, 0x0018, 0x8107, 0x8004, 0x8004,
+	0x7a9c, 0xa210, 0x721a, 0x7a98, 0xa006, 0xa211, 0x721e, 0xd4c4,
+	0x0130, 0x7aa4, 0xa211, 0x7222, 0x7aa0, 0xa211, 0x7226, 0x20a1,
+	0x0030, 0x7003, 0x0000, 0x2009, 0x8f54, 0x260a, 0x8109, 0x2198,
+	0x2104, 0xd084, 0x0108, 0x8633, 0xa6b0, 0x0002, 0x26a8, 0x53a6,
+	0x8603, 0x7012, 0x7007, 0x0001, 0x7990, 0x7894, 0x8000, 0xa10a,
+	0x1208, 0xa006, 0x2028, 0x7974, 0xa184, 0xff00, 0x0140, 0x810f,
+	0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0018, 0x8107,
+	0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, 0xa006, 0xa211, 0xd4c4,
+	0x0120, 0x7b84, 0xa319, 0x7c80, 0xa421, 0x7008, 0xd0fc, 0x0de8,
+	0xa084, 0x01e0, 0x01d0, 0x7d10, 0x2031, 0x8f54, 0x2634, 0x78a8,
+	0x8000, 0x78aa, 0xd08c, 0x1138, 0x7007, 0x0006, 0x7004, 0xd094,
+	0x1de8, 0x0804, 0x2186, 0x2069, 0x4747, 0x206b, 0x0003, 0x78ac,
+	0xa085, 0x0300, 0x78ae, 0xa006, 0x0048, 0x2030, 0x75d6, 0x2091,
+	0x4080, 0x7d96, 0x7d10, 0xa5ac, 0xffcf, 0x7d12, 0x2091, 0x8001,
+	0x78aa, 0x7007, 0x0006, 0x263a, 0x7003, 0x0001, 0x711a, 0x721e,
+	0xd5c4, 0x0110, 0x7322, 0x7426, 0x0005, 0x6084, 0xa086, 0x0103,
+	0x11d8, 0x6114, 0x6018, 0xa105, 0x11b8, 0x2069, 0x0000, 0x6818,
+	0xd084, 0x1190, 0x600c, 0x70c6, 0x6010, 0x70ca, 0x70c3, 0x8020,
+	0x681b, 0x0001, 0x2091, 0x4080, 0x080c, 0x1dd0, 0x0e04, 0x2243,
+	0x786c, 0xa065, 0x1d10, 0x0005, 0x0059, 0x1530, 0x786c, 0xa065,
+	0x19e0, 0x0410, 0x0029, 0x1500, 0x786c, 0xa065, 0x1dd8, 0x00e0,
+	0x6084, 0xa086, 0x0103, 0x1168, 0x6018, 0xc0fc, 0x601a, 0xa086,
+	0x0004, 0x1138, 0x7804, 0xd0a4, 0x0120, 0x080c, 0x1dd0, 0xa006,
+	0x0005, 0x0079, 0x1118, 0xa085, 0x0001, 0x0005, 0x00b9, 0x1110,
+	0x2041, 0x0001, 0x7d10, 0x0005, 0x88ff, 0x0110, 0x2091, 0x4080,
+	0x0005, 0x7b90, 0x7994, 0x70d4, 0xa102, 0x1118, 0xa385, 0x0000,
+	0x0005, 0x0210, 0xa302, 0x0005, 0x8002, 0x0005, 0xa184, 0xff00,
+	0x0140, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100,
+	0x0018, 0x8107, 0x8004, 0x8004, 0x7a9c, 0x7b98, 0x7ca4, 0x7da0,
+	0xa210, 0xa006, 0xa319, 0xa421, 0xa529, 0x2009, 0x0018, 0x6028,
+	0xa005, 0x0110, 0x2009, 0x0040, 0x080c, 0x1b34, 0x01d0, 0x78a8,
+	0x8000, 0x78aa, 0xd08c, 0x1510, 0x6014, 0xd0fc, 0x1118, 0x2069,
+	0x4740, 0x0010, 0x2069, 0x4780, 0x2091, 0x8000, 0x681f, 0x0003,
+	0x78ab, 0x0000, 0x78ac, 0xa085, 0x0300, 0x78ae, 0x2091, 0x8001,
+	0x0068, 0x78ab, 0x0000, 0x080c, 0x1dd0, 0x7990, 0x7894, 0x8000,
+	0xa10a, 0x1208, 0xa006, 0x7896, 0x70d6, 0xa006, 0x2071, 0x0010,
+	0x2091, 0x8001, 0x0005, 0xd7fc, 0x1118, 0x2009, 0x4758, 0x0010,
+	0x2009, 0x4798, 0x2091, 0x8000, 0x200a, 0x00f6, 0x2009, 0x4780,
+	0x2079, 0x0100, 0xd7fc, 0x1120, 0x2009, 0x4740, 0x2079, 0x0200,
+	0x2104, 0xa086, 0x0000, 0x1180, 0xd7fc, 0x1118, 0x2009, 0x4745,
+	0x0010, 0x2009, 0x4785, 0x2104, 0xa005, 0x1130, 0x7830, 0xa084,
+	0x00c0, 0x1110, 0x781b, 0x0052, 0x00fe, 0x0005, 0x2009, 0x0002,
+	0x2069, 0x4700, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x234b,
+	0x2071, 0x4780, 0x2079, 0x0100, 0x2021, 0x49bf, 0x784b, 0x000f,
+	0x2001, 0x01ff, 0x2004, 0xd0fc, 0x0118, 0x2019, 0x3e37, 0x0030,
+	0x20a1, 0x012b, 0x2019, 0x3e37, 0xd184, 0x0110, 0x20a1, 0x022b,
+	0x2304, 0xa005, 0x0140, 0x789a, 0x8318, 0x23ac, 0x8318, 0x2398,
+	0x53a6, 0x3318, 0x0ca8, 0x789b, 0x0000, 0x789b, 0x0020, 0x20a9,
+	0x0010, 0x78af, 0x0000, 0x78af, 0x2020, 0x1f04, 0x2329, 0x7003,
+	0x0000, 0x0016, 0xd18c, 0x2009, 0x0000, 0x0108, 0xc1bd, 0x080c,
+	0x246c, 0x001e, 0x7020, 0xa084, 0x000f, 0xa085, 0x6300, 0x7806,
+	0x780f, 0x9000, 0x7843, 0x00d8, 0x7853, 0x0090, 0x780b, 0x2f08,
+	0x7452, 0x704f, 0x0000, 0x8109, 0x0140, 0x2071, 0x4740, 0x2079,
+	0x0200, 0x2021, 0x47bf, 0x0804, 0x2306, 0x080c, 0x2526, 0x0005,
+	0x0016, 0x2011, 0x0101, 0xd1bc, 0x1110, 0x2011, 0x0201, 0xa18c,
+	0x000f, 0x2204, 0xa084, 0xfff0, 0xa105, 0x2012, 0x001e, 0x080c,
+	0x246c, 0x0005, 0x2011, 0x0101, 0xd3fc, 0x1110, 0x2011, 0x0201,
+	0x20a9, 0x0009, 0x810b, 0x1f04, 0x2372, 0xa18c, 0x0e00, 0x2204,
+	0xa084, 0xf1ff, 0xa105, 0x2012, 0x0005, 0x2019, 0x0002, 0x2009,
+	0x0101, 0x20a9, 0x0005, 0x8213, 0x1f04, 0x2383, 0xa294, 0x00e0,
+	0x2104, 0xa084, 0xff1f, 0xa205, 0x200a, 0x8319, 0x0118, 0x2009,
+	0x0201, 0x0c78, 0x0005, 0x2011, 0x0101, 0xd3fc, 0x1110, 0x2011,
+	0x0201, 0x20a9, 0x000c, 0x810b, 0x1f04, 0x239b, 0xa18c, 0xf000,
+	0x2204, 0xa084, 0x0fff, 0xa105, 0x2012, 0x0005, 0x2011, 0x0102,
+	0xd3fc, 0x1110, 0x2011, 0x0202, 0x2204, 0xa09c, 0x0f30, 0xa084,
+	0xf0cf, 0xa105, 0x2012, 0x0005, 0x00c6, 0x2061, 0x0100, 0xd1bc,
+	0x1110, 0x2061, 0x0200, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0020,
+	0x609a, 0x62ac, 0x63ac, 0x00ce, 0x0005, 0x00c6, 0x2061, 0x0100,
+	0xd1bc, 0x1110, 0x2061, 0x0200, 0xc1bc, 0x8103, 0x8003, 0xa080,
+	0x0022, 0x609a, 0x60a4, 0xa084, 0xffdf, 0x60ae, 0x00ce, 0x0005,
+	0x00c6, 0x2061, 0x0100, 0xd1bc, 0x1110, 0x2061, 0x0200, 0xc1bc,
+	0x8103, 0x8003, 0xa080, 0x0020, 0x609a, 0x60a4, 0xa28c, 0x0020,
+	0x0118, 0xc2ac, 0xa39d, 0x4000, 0xc3ec, 0xd3b4, 0x1108, 0xc3ed,
+	0x62ae, 0x2010, 0x60a4, 0x63ae, 0x2018, 0x00ce, 0x0005, 0x2091,
+	0x8000, 0x00c6, 0x00e6, 0x6818, 0xa005, 0x0904, 0x2450, 0xd1fc,
+	0x0118, 0x2061, 0x8ed0, 0x0010, 0x2061, 0x8dc0, 0x080c, 0x2458,
+	0x0560, 0x20a9, 0x0101, 0xd1fc, 0x0118, 0x2061, 0x8dd0, 0x0010,
+	0x2061, 0x8cc0, 0x00c6, 0x080c, 0x2458, 0x0128, 0x00ce, 0x8c60,
+	0x1f04, 0x2412, 0x04a8, 0x000e, 0xd1fc, 0x0128, 0xa082, 0x8dd0,
+	0x2071, 0x4780, 0x0020, 0xa082, 0x8cc0, 0x2071, 0x4740, 0x7076,
+	0x7172, 0x2138, 0x2001, 0x0004, 0x7062, 0x707f, 0x000f, 0x71d0,
+	0xc1c4, 0x71d2, 0x080c, 0x22cb, 0x00c0, 0xd1fc, 0x1118, 0x2071,
+	0x4740, 0x0010, 0x2071, 0x4780, 0x6020, 0xc0dd, 0x6022, 0x7172,
+	0x2138, 0x2c00, 0x707a, 0x2001, 0x0006, 0x7062, 0x707f, 0x000f,
+	0x71d0, 0xc1c4, 0x71d2, 0x080c, 0x22cb, 0x2001, 0x0000, 0x0010,
+	0x2001, 0x0001, 0x2091, 0x8001, 0xa005, 0x00ee, 0x00ce, 0x0005,
+	0x2c04, 0xa005, 0x0170, 0x2060, 0x6010, 0xa306, 0x1140, 0x600c,
+	0xa206, 0x1128, 0x6014, 0xa106, 0x1110, 0xa006, 0x0020, 0x6000,
+	0x0c80, 0xa085, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x0016, 0x2079,
+	0x4780, 0x2071, 0x0100, 0xd1bc, 0x1120, 0x2079, 0x4740, 0x2071,
+	0x0200, 0x7920, 0xa18c, 0x000f, 0x70ec, 0xd0c4, 0x1110, 0x001e,
+	0x0060, 0x810b, 0x810b, 0x810b, 0x810b, 0x000e, 0xa18d, 0x0800,
+	0xd0bc, 0x1110, 0xa18d, 0x0f00, 0x2104, 0x00ee, 0x00fe, 0x0005,
+	0x2001, 0x4701, 0x2004, 0xd0ac, 0x1138, 0x68e4, 0xd0ac, 0x0120,
+	0xa084, 0x0006, 0x1108, 0x0009, 0x0005, 0x6014, 0x00e6, 0x0036,
+	0x2018, 0x2071, 0x4c40, 0xd0fc, 0x1110, 0x2071, 0x4bc0, 0x8007,
+	0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xae70, 0x7004, 0xa084,
+	0x000a, 0x1904, 0x2523, 0x7108, 0xa194, 0xff00, 0x0904, 0x2523,
+	0xa18c, 0x00ff, 0x701c, 0xa084, 0xff00, 0x01c0, 0x7004, 0xa085,
+	0x003a, 0x7006, 0x2001, 0x0009, 0xa102, 0x16d8, 0x2001, 0x000a,
+	0xa102, 0x16d0, 0x2001, 0x000c, 0xa102, 0x16c8, 0x701c, 0xa084,
+	0x00ff, 0x701e, 0x7004, 0xa084, 0xffdf, 0x7006, 0x2001, 0x000a,
+	0xa106, 0x01a8, 0x2001, 0x000c, 0xa106, 0x01a0, 0x2001, 0x0012,
+	0xa106, 0x0198, 0x2001, 0x0014, 0xa106, 0x0190, 0x2001, 0x0019,
+	0xa106, 0x0188, 0x2001, 0x0032, 0xa106, 0x0180, 0x00d8, 0x2009,
+	0x000c, 0x00d0, 0x2009, 0x0012, 0x00b8, 0x2009, 0x0014, 0x00a0,
+	0x2009, 0x0019, 0x0088, 0x2009, 0x0020, 0x0070, 0x2009, 0x003f,
+	0x0058, 0x2009, 0x000a, 0x0040, 0x2009, 0x000c, 0x0028, 0x2009,
+	0x0019, 0x0010, 0x2011, 0x0000, 0x2100, 0xa205, 0x700a, 0x7004,
+	0xa085, 0x000a, 0x7006, 0x2071, 0x4700, 0x7004, 0xd0bc, 0x0158,
+	0xd3fc, 0x1120, 0x73ea, 0x2071, 0x4740, 0x0018, 0x73ee, 0x2071,
+	0x4780, 0x701f, 0x000d, 0x003e, 0x00ee, 0x0005, 0x2001, 0x01ff,
+	0x2004, 0xd0fc, 0x11d0, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005,
+	0x12a0, 0x2071, 0x0200, 0x71ec, 0xa18c, 0x1c00, 0x810f, 0x810c,
+	0x810c, 0x2079, 0x0100, 0x78ec, 0xa084, 0x1c00, 0x8007, 0x8004,
+	0x8004, 0xa105, 0xa08a, 0x0007, 0x0208, 0x0005, 0x0002, 0x2574,
+	0x255b, 0x2574, 0x255b, 0x254e, 0x2568, 0x254e, 0x7008, 0xa084,
+	0xc3ff, 0xa085, 0x3000, 0x700a, 0x7808, 0xa084, 0xc3ff, 0xa085,
+	0x3000, 0x780a, 0x0005, 0x7008, 0xa084, 0xc3ff, 0xa085, 0x2000,
+	0x700a, 0x7808, 0xa084, 0xc3ff, 0xa085, 0x2000, 0x780a, 0x0005,
+	0x7008, 0xa084, 0xc3ff, 0xa085, 0x0c00, 0x700a, 0x7808, 0xa084,
+	0xc3ff, 0xa085, 0x0c00, 0x780a, 0x0005, 0x0e04, 0x2575, 0x2091,
+	0x8000, 0x2071, 0x0000, 0x0006, 0x7018, 0xd084, 0x1de8, 0x000e,
+	0x2071, 0x0010, 0x70ca, 0x000e, 0x70c6, 0x70c3, 0x8002, 0x70db,
+	0x0a04, 0x70df, 0x002a, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091,
+	0x4080, 0x0cf8, 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x78a0, 0x708a,
+	0x758e, 0x7492, 0x7696, 0x779a, 0xa594, 0x003f, 0xd4f4, 0x0138,
+	0xd7bc, 0x1128, 0xa784, 0x007d, 0x1904, 0x3c9c, 0x0871, 0xa49c,
+	0x000f, 0xa382, 0x0004, 0x0320, 0xa3a6, 0x0007, 0x1930, 0x2418,
+	0x8507, 0xa084, 0x000f, 0x0002, 0x2b6c, 0x2c57, 0x2c95, 0x2efb,
+	0x3279, 0x32d0, 0x3376, 0x3405, 0x34d9, 0x35ab, 0x25c7, 0x25c4,
+	0x299e, 0x2a85, 0x324d, 0x25c4, 0x080c, 0x2575, 0x0005, 0xa006,
+	0x0038, 0x7808, 0xc08d, 0x780a, 0xa006, 0x7002, 0x704a, 0x7042,
+	0x70ce, 0x705c, 0xa005, 0x1904, 0x2718, 0x7060, 0xa084, 0x0007,
+	0x0002, 0x25e1, 0x2652, 0x265a, 0x2663, 0x266c, 0x26fe, 0x2675,
+	0x2652, 0x7830, 0xd0bc, 0x1d10, 0x71d0, 0xd1bc, 0x19f8, 0xd1b4,
+	0x1904, 0x262f, 0x70a0, 0xa086, 0x0001, 0x09c0, 0x7014, 0xa005,
+	0x19a8, 0x70b0, 0xa06d, 0x6800, 0xa065, 0xa055, 0x789b, 0x0080,
+	0x6b0c, 0x7baa, 0x6808, 0xa045, 0x6d10, 0x6804, 0xa06d, 0xa05d,
+	0xa886, 0x0001, 0x0118, 0x69bc, 0x7daa, 0x79aa, 0x68c0, 0xa04d,
+	0x6e1c, 0x2001, 0x0010, 0x0804, 0x284b, 0x705c, 0xa005, 0x1904,
+	0x25c6, 0x00c6, 0x00d6, 0x70b0, 0xa06d, 0x6800, 0xa065, 0xa055,
+	0x789b, 0x0080, 0x6b0c, 0x7baa, 0x6808, 0xa045, 0x6d10, 0x6804,
+	0xa06d, 0xa05d, 0xa886, 0x0001, 0x0118, 0x69bc, 0x7daa, 0x79aa,
+	0x68c0, 0xa04d, 0x6e1c, 0x2001, 0x0020, 0x0804, 0x284b, 0x080c,
+	0x3c5b, 0x1904, 0x25c6, 0x781b, 0x0068, 0x70b8, 0xa06d, 0x68b4,
+	0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x7808,
+	0xc08d, 0x780a, 0x68bc, 0x703e, 0xc1b4, 0x71d2, 0x70b4, 0xa065,
+	0x68c0, 0x7056, 0x7003, 0x0002, 0x2d00, 0x704a, 0xad80, 0x0009,
+	0x7042, 0x0005, 0x080c, 0x3c5b, 0x1120, 0x781b, 0x0054, 0x7003,
+	0x0004, 0x0005, 0x080c, 0x3c5b, 0x1128, 0x2011, 0x000c, 0x0419,
+	0x7003, 0x0004, 0x0005, 0x080c, 0x3c5b, 0x1128, 0x2011, 0x0006,
+	0x00d1, 0x7003, 0x0004, 0x0005, 0x080c, 0x3c5b, 0x1128, 0x2011,
+	0x000d, 0x0089, 0x7003, 0x0004, 0x0005, 0x080c, 0x3c5b, 0x1150,
+	0x2011, 0x0006, 0x0041, 0x7078, 0x707b, 0x0000, 0x2068, 0x704a,
+	0x7003, 0x0004, 0x0005, 0x7170, 0xc1fc, 0x8107, 0x7882, 0x789b,
+	0x0080, 0xa286, 0x000c, 0x1120, 0x7aaa, 0x2001, 0x0001, 0x0098,
+	0xa18c, 0x001f, 0xa18d, 0x00c0, 0x79aa, 0xa286, 0x000d, 0x0120,
+	0x7aaa, 0x2001, 0x0002, 0x0038, 0x78ab, 0x0020, 0x7174, 0x79aa,
+	0x7aaa, 0x2001, 0x0004, 0x789b, 0x0060, 0x78aa, 0x785b, 0x0004,
+	0x781b, 0x0113, 0x080c, 0x3c6e, 0x707f, 0x000f, 0x70d0, 0xd0b4,
+	0x0168, 0xc0b4, 0x70d2, 0x00c6, 0x70b4, 0xa065, 0x6008, 0xa084,
+	0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x00ce, 0x0005, 0x7014,
+	0xa005, 0x1138, 0x70d0, 0xd0b4, 0x0128, 0x70b4, 0xac06, 0x1110,
+	0x0c29, 0x0005, 0x0016, 0x71a0, 0xa186, 0x0001, 0x0528, 0x00d6,
+	0x0026, 0x2100, 0x2011, 0x0001, 0xa212, 0x70b0, 0x2068, 0x6800,
+	0xac06, 0x0120, 0x8211, 0x01b0, 0x00c9, 0x0cc8, 0x00c6, 0x2100,
+	0x2011, 0x0001, 0xa212, 0x70b0, 0x2068, 0x6800, 0x2060, 0x6008,
+	0xa084, 0xfbef, 0x600a, 0x8211, 0x0110, 0x0041, 0x0cb0, 0x70a3,
+	0x0001, 0x00ce, 0x002e, 0x00de, 0x001e, 0x0005, 0xade8, 0x0005,
+	0x70a8, 0xad06, 0x1110, 0x70a4, 0x2068, 0x0005, 0x080c, 0x3c5b,
+	0x1904, 0x25c6, 0x7078, 0x2068, 0x7770, 0x080c, 0x3b95, 0x2c50,
+	0x080c, 0x3cf6, 0x789b, 0x0080, 0x6814, 0xa084, 0x001f, 0xc0bd,
+	0x78aa, 0x6e1c, 0x2041, 0x0001, 0x2001, 0x0004, 0x0804, 0x2850,
+	0x080c, 0x3c5b, 0x1904, 0x25c6, 0x789b, 0x0080, 0x705c, 0x2068,
+	0x6f14, 0x70d0, 0xd0b4, 0x0168, 0xc0b4, 0x70d2, 0x00c6, 0x70b4,
+	0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a,
+	0x00ce, 0x080c, 0x3b95, 0x2c50, 0x080c, 0x3cf6, 0x6824, 0xa005,
+	0x0130, 0xa082, 0x0006, 0x0208, 0x0010, 0x6827, 0x0005, 0x6814,
+	0xa084, 0x001f, 0xc0bd, 0x78aa, 0x2031, 0x0020, 0x2041, 0x0001,
+	0x2001, 0x0003, 0x0804, 0x2850, 0xc28d, 0x72d2, 0x72bc, 0xa200,
+	0xa015, 0x7150, 0x8108, 0xa12a, 0x0208, 0x71bc, 0x2164, 0x6504,
+	0x85ff, 0x1170, 0x7152, 0x8421, 0x1da8, 0x70d0, 0xd08c, 0x0128,
+	0x70cc, 0xa005, 0x1110, 0x70cf, 0x000a, 0x0005, 0x2200, 0x0c90,
+	0x70d0, 0xc08c, 0x70d2, 0x70cf, 0x0000, 0x6034, 0xa005, 0x1db0,
+	0x6708, 0xa784, 0x073f, 0x01d0, 0xd7d4, 0x1d80, 0xa784, 0x0021,
+	0x1d68, 0xa784, 0x0002, 0x0130, 0xa784, 0x0004, 0x0d38, 0xa7bc,
+	0xfffb, 0x670a, 0xa784, 0x0218, 0x1d08, 0xa784, 0x0100, 0x0130,
+	0x6018, 0xa005, 0x19d8, 0xa7bc, 0xfeff, 0x670a, 0x2568, 0x6823,
+	0x0000, 0x6e1c, 0xa684, 0x000e, 0x6318, 0x0128, 0x601c, 0xa302,
+	0x0220, 0x0118, 0x0858, 0x83ff, 0x1948, 0x2d58, 0x2c50, 0x7152,
+	0xd7bc, 0x1120, 0x7028, 0x6022, 0x603a, 0x0010, 0xc7bc, 0x670a,
+	0x68c0, 0xa065, 0xa04d, 0x6100, 0x2a60, 0x2041, 0x0001, 0x6b14,
+	0xa39c, 0x001f, 0xa39d, 0x00c0, 0xd1fc, 0x0110, 0xd684, 0x0110,
+	0xa39c, 0xffbf, 0xd6a4, 0x0110, 0xa39d, 0x0020, 0xa684, 0x000e,
+	0x1904, 0x2802, 0xc7a5, 0x670a, 0x2c00, 0x68c6, 0x77a0, 0xa786,
+	0x0001, 0x1178, 0x70d0, 0xd0b4, 0x1160, 0x7000, 0xa082, 0x0002,
+	0x1240, 0x7830, 0xd0bc, 0x1128, 0x789b, 0x0080, 0x7baa, 0x0804,
+	0x2849, 0x8739, 0x77a2, 0x2750, 0x77ac, 0xa7b0, 0x0005, 0x70a8,
+	0xa606, 0x1108, 0x76a4, 0x76ae, 0x2c3a, 0x8738, 0x2d3a, 0x8738,
+	0x283a, 0x8738, 0x233a, 0x8738, 0x253a, 0x7830, 0xd0bc, 0x0150,
+	0x2091, 0x8000, 0x2091, 0x303d, 0x70d0, 0xa084, 0x303d, 0x2091,
+	0x8000, 0x2090, 0xaad5, 0x0000, 0x0120, 0x8421, 0x2200, 0x1904,
+	0x2751, 0x0005, 0xd1dc, 0x0904, 0x37f1, 0x2029, 0x0020, 0xd69c,
+	0x1120, 0x8528, 0xd68c, 0x1108, 0x8528, 0x8840, 0x6f14, 0x610c,
+	0x8108, 0xa18c, 0x00ff, 0x70c8, 0xa160, 0x2c64, 0x8cff, 0x0188,
+	0x6014, 0xa706, 0x1dd0, 0x60b8, 0x8001, 0x60ba, 0x1d88, 0x2a60,
+	0x6008, 0xa085, 0x0100, 0x600a, 0x2200, 0x8421, 0x1904, 0x2751,
+	0x0005, 0x2a60, 0x610e, 0x69be, 0x2c00, 0x68c6, 0x8840, 0x6008,
+	0xc0d5, 0x600a, 0x77a0, 0xa786, 0x0001, 0x1904, 0x27d9, 0x70d0,
+	0xd0b4, 0x1904, 0x27d9, 0x7000, 0xa082, 0x0002, 0x1a04, 0x27d9,
+	0x7830, 0xd0bc, 0x1904, 0x27d9, 0x789b, 0x0080, 0x7baa, 0x7daa,
+	0x79aa, 0x2001, 0x0002, 0x0006, 0x6018, 0x8000, 0x601a, 0x0008,
+	0x0006, 0x2960, 0x6104, 0x2a60, 0x080c, 0x3d09, 0x1590, 0xa184,
+	0x0018, 0x0180, 0xa184, 0x0010, 0x0118, 0x080c, 0x399a, 0x1548,
+	0xa184, 0x0008, 0x0138, 0x69a0, 0xa184, 0x0600, 0x1118, 0x080c,
+	0x38b8, 0x00f8, 0x69a0, 0xa184, 0x1e00, 0x0528, 0xa184, 0x0800,
+	0x0178, 0x00c6, 0x2960, 0x6000, 0xa085, 0x2000, 0x6002, 0x6104,
+	0xa18d, 0x0010, 0x6106, 0x00ce, 0x080c, 0x399a, 0x1150, 0x69a0,
+	0xa184, 0x0200, 0x0118, 0x080c, 0x38fd, 0x0018, 0xa184, 0x0400,
+	0x19f0, 0x69a0, 0xa184, 0x1000, 0x0130, 0x6914, 0xa18c, 0xff00,
+	0x810f, 0x080c, 0x23c5, 0x002e, 0xa68c, 0x00e0, 0xa684, 0x0060,
+	0x0128, 0xa086, 0x0060, 0x1110, 0xa18d, 0x4000, 0xa18d, 0x0104,
+	0x69b6, 0x789b, 0x0060, 0x2800, 0x78aa, 0x6818, 0xc0fd, 0x681a,
+	0xd6bc, 0x0168, 0xc0fc, 0x7083, 0x0000, 0xa08a, 0x000d, 0x0328,
+	0xa08a, 0x000c, 0x7182, 0x2001, 0x000c, 0x800c, 0x7186, 0x78aa,
+	0x3518, 0x3340, 0x3428, 0x8000, 0x80ac, 0xaf80, 0x002b, 0x20a0,
+	0x789b, 0x0000, 0xad80, 0x000b, 0x2098, 0x53a6, 0x23a8, 0x2898,
+	0x25a0, 0xa286, 0x0020, 0x1508, 0x70d0, 0xc0b5, 0x70d2, 0x2c00,
+	0x70b6, 0x2d00, 0x70ba, 0x6814, 0xc0fc, 0x8007, 0x7882, 0xa286,
+	0x0002, 0x0904, 0x2921, 0x70a0, 0x8000, 0x70a2, 0x74b0, 0xa498,
+	0x0005, 0x70a8, 0xa306, 0x1108, 0x73a4, 0x73b2, 0xa286, 0x0010,
+	0x0904, 0x25c6, 0x00de, 0x00ce, 0x0005, 0x7000, 0xa005, 0x19e0,
+	0xa286, 0x0002, 0x1904, 0x2938, 0x080c, 0x3c5b, 0x19a8, 0x6814,
+	0xc0fc, 0x8007, 0x7882, 0x2091, 0x8000, 0x781b, 0x0068, 0x68b4,
+	0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x2091,
+	0x8001, 0x7808, 0xc08d, 0x780a, 0x0126, 0x00d6, 0x00c6, 0x70d0,
+	0xa084, 0x2e00, 0x2090, 0x00ce, 0x00de, 0x012e, 0x2900, 0x7056,
+	0x68bc, 0x703e, 0x7003, 0x0002, 0x2d00, 0x704a, 0xad80, 0x0009,
+	0x7042, 0x7830, 0xd0bc, 0x0140, 0x2091, 0x303d, 0x70d0, 0xa084,
+	0x303d, 0x2091, 0x8000, 0x2090, 0x70a0, 0xa005, 0x1108, 0x0005,
+	0x8421, 0x0de8, 0x724c, 0x70bc, 0xa200, 0xa015, 0x0804, 0x2751,
+	0xa286, 0x0010, 0x1560, 0x080c, 0x3c5b, 0x1904, 0x28cc, 0x6814,
+	0xc0fc, 0x8007, 0x7882, 0x781b, 0x0068, 0x68b4, 0x785a, 0x6894,
+	0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d, 0x780a,
+	0x70a0, 0x8000, 0x70a2, 0x74b0, 0xa490, 0x0005, 0x70a8, 0xa206,
+	0x1108, 0x72a4, 0x72b2, 0x2900, 0x7056, 0x68bc, 0x703e, 0x7003,
+	0x0002, 0x2d00, 0x704a, 0xad80, 0x0009, 0x7042, 0x0005, 0x6bb4,
+	0xa39d, 0x2000, 0x7b5a, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x6b94,
+	0x7bd6, 0x7bde, 0x6e98, 0x7ed2, 0x7eda, 0x781b, 0x0068, 0x2900,
+	0x7056, 0x7202, 0x7808, 0xc08d, 0x780a, 0x2300, 0xa605, 0x0170,
+	0x70d0, 0xa084, 0x2e00, 0xa086, 0x2600, 0x1118, 0x2009, 0x0000,
+	0x0010, 0x2009, 0x0001, 0xa284, 0x000f, 0x0033, 0xad80, 0x0009,
+	0x7042, 0x2d00, 0x704a, 0x0005, 0x299c, 0x4208, 0x4208, 0x41f6,
+	0x4208, 0x299c, 0x299c, 0x299c, 0x080c, 0x2575, 0x7808, 0xa084,
+	0xfffd, 0x780a, 0x00f6, 0x2079, 0x4700, 0x78ac, 0x00fe, 0xd084,
+	0x01c0, 0x7160, 0xa186, 0x0001, 0x0904, 0x2a61, 0xa186, 0x0007,
+	0x0170, 0xa186, 0x0005, 0x1158, 0x7078, 0x2068, 0x681b, 0x0004,
 	0x6817, 0x0000, 0x6820, 0xa084, 0x00ff, 0xc09d, 0x6822, 0x7063,
-	0x0000, 0x70a3, 0x0000, 0x70a4, 0x70ae, 0x70b2, 0x080c, 0x2682,
-	0x0156, 0x2011, 0x0004, 0x7160, 0xa186, 0x0001, 0x0160, 0xa186,
-	0x0007, 0x1118, 0x701f, 0x0005, 0x0030, 0x701f, 0x0001, 0x70d0,
-	0xc0c5, 0x70d2, 0x0000, 0x2001, 0x460a, 0x2004, 0xa084, 0x00ff,
-	0xa086, 0x0018, 0x0130, 0x7018, 0x7016, 0xa005, 0x1110, 0x70a3,
-	0x0001, 0x0066, 0x080c, 0x3f26, 0x20a9, 0x0010, 0x2039, 0x0000,
-	0x080c, 0x3a66, 0xa7b8, 0x0100, 0x1f04, 0x29c0, 0x006e, 0x7000,
-	0x0002, 0x29fd, 0x29db, 0x29db, 0x29d3, 0x29fd, 0x29fd, 0x29fd,
-	0x29d1, 0x080c, 0x254c, 0x705c, 0xa005, 0x0538, 0xad06, 0x1118,
-	0x6800, 0x705e, 0x0080, 0x6820, 0xd084, 0x1148, 0x6f14, 0x080c,
-	0x3b6f, 0x6008, 0xc0d4, 0x600a, 0x080c, 0x37a4, 0x0020, 0x7058,
-	0x2060, 0x6800, 0x6002, 0xa684, 0x5f00, 0x681e, 0x6818, 0xd0fc,
-	0x0108, 0x6a1a, 0x6817, 0x0000, 0x682b, 0x0000, 0x6820, 0xa084,
-	0x00ff, 0xc09d, 0x6822, 0x080c, 0x1da2, 0x2011, 0x0004, 0x74c8,
-	0xa4a0, 0x0100, 0x04b1, 0xaea0, 0x0017, 0x0499, 0x20a9, 0x0101,
-	0x74c8, 0x0479, 0x8420, 0x1f04, 0x2a09, 0x70c0, 0x2060, 0x2021,
-	0x0002, 0x20a9, 0x0100, 0x6110, 0x81ff, 0x0198, 0x6018, 0x0016,
-	0x0006, 0x2011, 0x4602, 0x220c, 0xa102, 0x2012, 0x000e, 0x001e,
-	0xa102, 0x0338, 0x6012, 0x1128, 0x2011, 0x4604, 0x2204, 0xc0a5,
-	0x2012, 0x601b, 0x0000, 0xace0, 0x0010, 0x1f04, 0x2a13, 0x8421,
-	0x1d00, 0x015e, 0x7063, 0x0000, 0x7003, 0x0000, 0x704b, 0x0000,
-	0x0005, 0x0046, 0x2404, 0xa005, 0x01a8, 0x2068, 0x6800, 0x0006,
-	0x6a1a, 0x6817, 0x0000, 0x682b, 0x0000, 0x68b4, 0xa084, 0x5f00,
-	0x681e, 0x6820, 0xa084, 0x00ff, 0xc09d, 0x6822, 0x080c, 0x1da2,
-	0x000e, 0x0c48, 0x004e, 0x2023, 0x0000, 0x0005, 0xa282, 0x0003,
-	0x0310, 0x080c, 0x254c, 0x2300, 0x0002, 0x2a60, 0x2add, 0x2af7,
-	0xa282, 0x0002, 0x0110, 0x080c, 0x254c, 0x7060, 0x7063, 0x0000,
-	0x707f, 0x0000, 0x0022, 0x77d0, 0xc7c5, 0x77d2, 0x0002, 0x2a77,
-	0x2a77, 0x2a79, 0x2ab1, 0x37d8, 0x2a77, 0x2ab1, 0x2a77, 0x080c,
-	0x254c, 0x7770, 0x080c, 0x3a66, 0x7770, 0xa7bc, 0x8f00, 0x080c,
-	0x3b6f, 0x6018, 0xa005, 0x0528, 0xd7fc, 0x1118, 0x2021, 0x8cc0,
-	0x0010, 0x2021, 0x8dd0, 0x2009, 0x0005, 0x2011, 0x0010, 0x080c,
-	0x2b11, 0x01b8, 0x0156, 0x20a9, 0x0101, 0xd7fc, 0x1118, 0x2021,
-	0x8bc0, 0x0010, 0x2021, 0x8cd0, 0x0046, 0x2009, 0x0005, 0x2011,
-	0x0010, 0x080c, 0x2b11, 0x004e, 0x0118, 0x8420, 0x1f04, 0x2a9c,
-	0x015e, 0x8738, 0xa784, 0x001f, 0x1990, 0x0804, 0x25a0, 0x0804,
-	0x25a0, 0x7770, 0x080c, 0x3b6f, 0x6018, 0xa005, 0x0520, 0xd7fc,
-	0x1118, 0x2021, 0x8cc0, 0x0010, 0x2021, 0x8dd0, 0x2009, 0x0005,
-	0x2011, 0x0020, 0x080c, 0x2b11, 0x01b0, 0x0156, 0x20a9, 0x0101,
-	0xd7fc, 0x1118, 0x2021, 0x8bc0, 0x0010, 0x2021, 0x8cd0, 0x0046,
-	0x2009, 0x0005, 0x2011, 0x0020, 0x04e1, 0x004e, 0x0118, 0x8420,
-	0x1f04, 0x2acf, 0x015e, 0x0804, 0x25a0, 0x2200, 0x0002, 0x2ae2,
-	0x2ae4, 0x2ae4, 0x080c, 0x254c, 0x2009, 0x0012, 0x7060, 0xa086,
-	0x0002, 0x0110, 0x2009, 0x000e, 0x6818, 0xd0fc, 0x0108, 0x691a,
-	0x7063, 0x0000, 0x70d0, 0xc0c5, 0x70d2, 0x0804, 0x3be5, 0x2200,
-	0x0002, 0x2afe, 0x2ae4, 0x2afc, 0x080c, 0x254c, 0x080c, 0x3f26,
-	0x7000, 0xa086, 0x0002, 0x1904, 0x375d, 0x080c, 0x37be, 0x6008,
-	0xa084, 0xfbef, 0x600a, 0x080c, 0x374f, 0x0904, 0x375d, 0x0804,
-	0x25a0, 0x2404, 0xa005, 0x0590, 0x2068, 0x2d04, 0x0006, 0x6814,
-	0xa706, 0x0118, 0x2d20, 0x000e, 0x0ca8, 0x000e, 0x2022, 0x691a,
+	0x0000, 0x70a3, 0x0000, 0x70a4, 0x70ae, 0x70b2, 0x080c, 0x26ae,
+	0x0156, 0x2011, 0x0004, 0x7160, 0xa186, 0x0001, 0x0158, 0xa186,
+	0x0007, 0x1118, 0x701f, 0x0005, 0x0010, 0x701f, 0x0001, 0x70d0,
+	0xc0c5, 0x70d2, 0x2001, 0x470a, 0x2004, 0xa084, 0x00ff, 0xa086,
+	0x0018, 0x0130, 0x7018, 0x7016, 0xa005, 0x1110, 0x70a3, 0x0001,
+	0x0066, 0x080c, 0x3f4e, 0x20a9, 0x0010, 0x2039, 0x0000, 0x080c,
+	0x3a8b, 0xa7b8, 0x0100, 0x1f04, 0x29ef, 0x006e, 0x7000, 0x0002,
+	0x2a2c, 0x2a0a, 0x2a0a, 0x2a02, 0x2a2c, 0x2a2c, 0x2a2c, 0x2a00,
+	0x080c, 0x2575, 0x705c, 0xa005, 0x0538, 0xad06, 0x1118, 0x6800,
+	0x705e, 0x0080, 0x6820, 0xd084, 0x1148, 0x6f14, 0x080c, 0x3b95,
+	0x6008, 0xc0d4, 0x600a, 0x080c, 0x37c7, 0x0020, 0x7058, 0x2060,
+	0x6800, 0x6002, 0xa684, 0x5f00, 0x681e, 0x6818, 0xd0fc, 0x0108,
+	0x6a1a, 0x6817, 0x0000, 0x682b, 0x0000, 0x6820, 0xa084, 0x00ff,
+	0xc09d, 0x6822, 0x080c, 0x1dbf, 0x2011, 0x0004, 0x74c8, 0xa4a0,
+	0x0100, 0x04b1, 0xaea0, 0x0017, 0x0499, 0x20a9, 0x0101, 0x74c8,
+	0x0479, 0x8420, 0x1f04, 0x2a38, 0x70c0, 0x2060, 0x2021, 0x0002,
+	0x20a9, 0x0100, 0x6110, 0x81ff, 0x0198, 0x6018, 0x0016, 0x0006,
+	0x2011, 0x4702, 0x220c, 0xa102, 0x2012, 0x000e, 0x001e, 0xa102,
+	0x0338, 0x6012, 0x1128, 0x2011, 0x4704, 0x2204, 0xc0a5, 0x2012,
+	0x601b, 0x0000, 0xace0, 0x0010, 0x1f04, 0x2a42, 0x8421, 0x1d00,
+	0x015e, 0x7063, 0x0000, 0x7003, 0x0000, 0x704b, 0x0000, 0x0005,
+	0x0046, 0x2404, 0xa005, 0x01a8, 0x2068, 0x6800, 0x0006, 0x6a1a,
 	0x6817, 0x0000, 0x682b, 0x0000, 0x68b4, 0xa084, 0x5f00, 0x681e,
-	0x6820, 0xa084, 0x00ff, 0xa205, 0x6822, 0x080c, 0x1da2, 0x2021,
-	0x4602, 0x241c, 0x8319, 0x2322, 0x6010, 0x8001, 0x6012, 0x1128,
-	0x2021, 0x4604, 0x2404, 0xc0a5, 0x2022, 0x6008, 0xa084, 0xf9ef,
-	0x600a, 0x080c, 0x269e, 0x080c, 0x37be, 0x0005, 0xa085, 0x0001,
-	0x0ce0, 0x2300, 0x0002, 0x2b50, 0x2b4e, 0x2bcb, 0x080c, 0x254c,
-	0x78e4, 0xa005, 0x17b0, 0x3208, 0xa18c, 0x0800, 0x0118, 0x0104,
-	0x259d, 0x0010, 0x0304, 0x259d, 0x2008, 0xa084, 0x0030, 0x1110,
-	0x0804, 0x322a, 0x78ec, 0xa084, 0x0003, 0x0dd0, 0x7884, 0xd0fc,
-	0x1118, 0xa184, 0x0007, 0x0090, 0xa184, 0x0007, 0xa086, 0x0004,
-	0x1118, 0x2001, 0x0000, 0x0050, 0xa184, 0x0007, 0xa086, 0x0005,
-	0x0118, 0xa184, 0x0007, 0x0010, 0x2001, 0x0001, 0x0002, 0x2bae,
-	0x2bb7, 0x2ba4, 0x2b87, 0x3c29, 0x3c29, 0x2b87, 0x2bc1, 0x080c,
-	0x254c, 0x7000, 0xa086, 0x0004, 0x1190, 0x7060, 0xa086, 0x0002,
-	0x1130, 0x2011, 0x0002, 0x2019, 0x0000, 0x0804, 0x2a56, 0x7060,
-	0xa086, 0x0006, 0x0db0, 0x7060, 0xa086, 0x0004, 0x0d90, 0x79e4,
-	0x2001, 0x0003, 0x0804, 0x2f18, 0x6818, 0xd0fc, 0x0110, 0x681b,
-	0x001d, 0x080c, 0x3a3c, 0x781b, 0x006e, 0x0005, 0x6818, 0xd0fc,
-	0x0110, 0x681b, 0x001d, 0x080c, 0x3a3c, 0x0804, 0x3c07, 0x6818,
-	0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c, 0x3a3c, 0x781b, 0x00fa,
-	0x0005, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c, 0x3a3c,
-	0x781b, 0x00cb, 0x0005, 0xa584, 0x000f, 0x11c0, 0x7000, 0x0002,
-	0x25a0, 0x2bd8, 0x2bda, 0x375d, 0x375d, 0x375d, 0x2bd8, 0x2bd8,
-	0x080c, 0x254c, 0x080c, 0x37be, 0x6008, 0xa084, 0xfbef, 0x600a,
-	0x080c, 0x374f, 0x0904, 0x375d, 0x0804, 0x25a0, 0x78e4, 0xa005,
-	0x1b04, 0x2b89, 0x3208, 0xa18c, 0x0800, 0x0118, 0x0104, 0x2b89,
-	0x0010, 0x0304, 0x2b89, 0x2008, 0xa084, 0x0030, 0x1118, 0x781b,
-	0x0068, 0x0005, 0x78ec, 0xa084, 0x0003, 0x0dc8, 0x7884, 0xd0fc,
-	0x1118, 0xa184, 0x0007, 0x0090, 0xa184, 0x0007, 0xa086, 0x0004,
-	0x1118, 0x2001, 0x0000, 0x0050, 0xa184, 0x0007, 0xa086, 0x0005,
-	0x0118, 0xa184, 0x0007, 0x0010, 0x2001, 0x0001, 0x0002, 0x2c26,
-	0x2c2a, 0x2c21, 0x2c1f, 0x3c29, 0x3c29, 0x2c1f, 0x3c23, 0x080c,
-	0x254c, 0x080c, 0x3a42, 0x781b, 0x006e, 0x0005, 0x080c, 0x3a42,
-	0x0804, 0x3c07, 0x080c, 0x3a42, 0x781b, 0x00fa, 0x0005, 0x080c,
-	0x3a42, 0x781b, 0x00cb, 0x0005, 0x2300, 0x0002, 0x2c3b, 0x2c39,
-	0x2c3d, 0x080c, 0x254c, 0x0804, 0x33e2, 0x681b, 0x0016, 0x78a3,
-	0x0000, 0x79e4, 0xa184, 0x0030, 0x0904, 0x33e2, 0x78ec, 0xa084,
-	0x0003, 0x0904, 0x33e2, 0xa184, 0x0100, 0x0d98, 0x7884, 0xd0fc,
-	0x1118, 0xa184, 0x0007, 0x0090, 0xa184, 0x0007, 0xa086, 0x0004,
-	0x1118, 0x2001, 0x0000, 0x0050, 0xa184, 0x0007, 0xa086, 0x0005,
-	0x0118, 0xa184, 0x0007, 0x0010, 0x2001, 0x0001, 0x0002, 0x2c6f,
-	0x2c2a, 0x2ba4, 0x3be5, 0x3c29, 0x3c29, 0x3be5, 0x3c23, 0x080c,
-	0x3bf1, 0x0005, 0xa282, 0x0005, 0x0310, 0x080c, 0x254c, 0x7898,
-	0x2040, 0x2300, 0x0002, 0x2c7e, 0x2ea8, 0x2eb2, 0x2200, 0x0002,
-	0x2c9a, 0x2c87, 0x2c9a, 0x2c85, 0x2e8a, 0x080c, 0x254c, 0x789b,
-	0x0018, 0x78a8, 0x2010, 0xa084, 0x00ff, 0xa082, 0x0020, 0x0a04,
-	0x3a0b, 0xa08a, 0x0004, 0x1a04, 0x3a0b, 0x0002, 0x3a0b, 0x3a0b,
-	0x3a0b, 0x39c1, 0x789b, 0x0018, 0x79a8, 0xa184, 0x0080, 0x0148,
-	0x0804, 0x3a0b, 0x7000, 0xa005, 0x1dd8, 0x2011, 0x0004, 0x0804,
-	0x3594, 0xa184, 0x00ff, 0xa08a, 0x0010, 0x1a04, 0x3a0b, 0x0002,
-	0x2cc2, 0x2cc0, 0x2cd4, 0x2cd8, 0x2d86, 0x3a0b, 0x3a0b, 0x2d88,
-	0x3a0b, 0x3a0b, 0x2e86, 0x2e86, 0x3a0b, 0x3a0b, 0x3a0b, 0x2e88,
-	0x080c, 0x254c, 0xd6e4, 0x0140, 0x2001, 0x0300, 0x8000, 0x8000,
-	0x783a, 0x781b, 0x00c7, 0x0005, 0x6818, 0xd0fc, 0x0118, 0x681b,
-	0x001d, 0x0c90, 0x0804, 0x3be5, 0x681b, 0x001d, 0x0804, 0x3a36,
-	0x6920, 0x6922, 0xa684, 0x1800, 0x1904, 0x2d29, 0x6820, 0xd084,
-	0x1904, 0x2d31, 0x6818, 0xa086, 0x0008, 0x1110, 0x681b, 0x0000,
-	0xd6d4, 0x0568, 0xd6bc, 0x0558, 0x7083, 0x0000, 0x6818, 0xa084,
-	0x003f, 0xa08a, 0x000d, 0x0718, 0xa08a, 0x000c, 0x7182, 0x2001,
-	0x000c, 0x800c, 0x7186, 0x789b, 0x0061, 0x78aa, 0x0156, 0x0136,
-	0x0146, 0x0016, 0x3208, 0xa18c, 0x0600, 0x0118, 0x20a1, 0x022b,
-	0x0010, 0x20a1, 0x012b, 0x001e, 0x789b, 0x0000, 0x8000, 0x80ac,
-	0xad80, 0x000b, 0x2098, 0x53a6, 0x014e, 0x013e, 0x015e, 0x6038,
-	0xa005, 0x1150, 0x681c, 0xa084, 0x000e, 0x0904, 0x3a36, 0x080c,
-	0x3a48, 0x782b, 0x3008, 0x0010, 0x8001, 0x603a, 0x781b, 0x0071,
-	0x0005, 0xd6e4, 0x0130, 0x781b, 0x0083, 0x0005, 0x781b, 0x0083,
-	0x0005, 0xa684, 0x0060, 0x0dd0, 0xd6dc, 0x0dc0, 0xd6fc, 0x01a0,
-	0xc6fc, 0x7e5a, 0x6eb6, 0x7adc, 0x79d8, 0x78d0, 0x8007, 0xa084,
-	0x007f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2,
-	0x6b94, 0x2200, 0xa303, 0x68ae, 0xd6f4, 0x0118, 0xc6f4, 0x7e5a,
-	0x6eb6, 0x7000, 0xa086, 0x0003, 0x1148, 0x0006, 0x080c, 0x3f26,
-	0x080c, 0x41d9, 0x000e, 0x781b, 0x0080, 0x0005, 0xa006, 0x080c,
-	0x42b5, 0x6ab0, 0x69ac, 0x6c98, 0x6b94, 0x2200, 0xa105, 0x0120,
-	0x2200, 0xa422, 0x2100, 0xa31b, 0x6caa, 0x7cd2, 0x7cda, 0x6ba6,
-	0x7bd6, 0x7bde, 0x2300, 0xa405, 0x1130, 0xc6f5, 0x7e5a, 0x6eb6,
-	0x781b, 0x0080, 0x0005, 0x781b, 0x0080, 0x2200, 0xa115, 0x1118,
-	0x080c, 0x41d9, 0x0005, 0x080c, 0x4206, 0x0005, 0x080c, 0x254c,
-	0x0804, 0x2e1c, 0x00c6, 0x7054, 0x2060, 0x6920, 0xa18c, 0xecff,
-	0x6922, 0x6000, 0xa084, 0xcfdf, 0x6002, 0x080c, 0x38f4, 0xa006,
-	0x2040, 0x2038, 0x080c, 0x399c, 0x0804, 0x2e10, 0x00c6, 0x7054,
-	0x2060, 0x2c48, 0x7aa8, 0xa294, 0x00ff, 0xa286, 0x0004, 0x11d8,
-	0x6920, 0xd1e4, 0x1170, 0x2039, 0x0000, 0x2041, 0x0000, 0x2031,
-	0x0000, 0xa006, 0x2010, 0x080c, 0x38f7, 0x080c, 0x399c, 0x0804,
-	0x2e10, 0xa18c, 0xecff, 0x6922, 0x6104, 0xa18c, 0xffdd, 0x6106,
-	0x6000, 0xc0ac, 0x6002, 0xa286, 0x0003, 0x01d0, 0x6104, 0xa184,
-	0x0010, 0x0548, 0x080c, 0x3b6b, 0x080c, 0x3977, 0x88ff, 0x0518,
-	0x00ce, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a,
-	0xd6d4, 0x1118, 0x781b, 0x006e, 0x0005, 0x781b, 0x0082, 0x0005,
-	0x6920, 0xd1cc, 0x0130, 0xa18c, 0xfdff, 0x6922, 0x6000, 0xc0ec,
-	0x6002, 0x2039, 0x0000, 0x2041, 0x0000, 0x2031, 0x0000, 0xa006,
-	0x2010, 0x080c, 0x399c, 0xa286, 0x0001, 0x0158, 0x6104, 0xa184,
-	0x0008, 0x01b0, 0x080c, 0x3b6b, 0x080c, 0x3895, 0x88ff, 0x1980,
-	0x0078, 0x6920, 0xd1c4, 0x0130, 0xa18c, 0xfeff, 0x6922, 0x6000,
-	0xc0e4, 0x6002, 0x2031, 0x0000, 0xa006, 0x2010, 0x080c, 0x38f7,
-	0x00ce, 0x7e58, 0xd6d4, 0x1118, 0x781b, 0x0071, 0x0005, 0x781b,
-	0x0083, 0x0005, 0x0804, 0x3a32, 0x2808, 0x789b, 0x0080, 0x2019,
-	0x0080, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001, 0x11b8, 0x2300,
-	0xa102, 0xa086, 0x0001, 0x0904, 0x2d8a, 0x7ca8, 0xa4a4, 0x00ff,
-	0xa480, 0x0002, 0xa300, 0x2018, 0xa102, 0x0a04, 0x2d9e, 0x0904,
-	0x2d9e, 0x24a8, 0x7aa8, 0x1f04, 0x2e3a, 0x0c18, 0xa284, 0x00f0,
-	0xa082, 0x0020, 0x06b8, 0x2200, 0xa082, 0x0021, 0x1698, 0x7aa8,
-	0x8318, 0x8318, 0x2100, 0xa302, 0x0aa0, 0xa286, 0x0023, 0x0950,
-	0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58, 0xa684, 0xfff1, 0xc0a5,
-	0x2030, 0x7e5a, 0x6008, 0xc0a5, 0x600a, 0x78a0, 0x8001, 0x0904,
-	0x2e10, 0x20a8, 0x7998, 0x789b, 0x0060, 0x78aa, 0x2011, 0x0080,
-	0x799a, 0x78a8, 0x7998, 0x7a9a, 0x78aa, 0x7a98, 0x1f04, 0x2e68,
-	0xc695, 0x7e5a, 0xd6d4, 0x1118, 0x781b, 0x006e, 0x0005, 0x781b,
-	0x0082, 0x0005, 0x8318, 0x2100, 0xa302, 0x0a04, 0x2e21, 0xa284,
-	0x0080, 0x1904, 0x3a36, 0x78a0, 0xa005, 0x08c8, 0x0804, 0x3a36,
-	0x0804, 0x3a0b, 0x7054, 0xa04d, 0x789b, 0x0018, 0x78a8, 0xa084,
-	0x00ff, 0xa08e, 0x0001, 0x0110, 0x080c, 0x254c, 0x7aa8, 0xa294,
-	0x00ff, 0x784b, 0x0008, 0x78a8, 0xa084, 0x00ff, 0xa08a, 0x0005,
-	0x1a04, 0x3a0b, 0x0002, 0x3a0b, 0x380c, 0x3a0b, 0x3927, 0x3d31,
-	0xa282, 0x0000, 0x1110, 0x080c, 0x254c, 0x080c, 0x3a3c, 0x781b,
-	0x0082, 0x0005, 0xa282, 0x0003, 0x1110, 0x080c, 0x254c, 0xd4fc,
-	0x11d0, 0x7060, 0xa005, 0x0110, 0x080c, 0x254c, 0x6f14, 0x7772,
-	0xa7bc, 0x8f00, 0x080c, 0x3b6f, 0x6008, 0xa085, 0x0021, 0x600a,
-	0x8738, 0xa784, 0x001f, 0x1db0, 0x080c, 0x3a3f, 0x7063, 0x0002,
-	0x701f, 0x0009, 0x0010, 0x080c, 0x3a4b, 0x781b, 0x0082, 0x0005,
-	0xa282, 0x0004, 0x0310, 0x080c, 0x254c, 0x2300, 0x0002, 0x2ee2,
-	0x3078, 0x30b4, 0xa286, 0x0003, 0x0598, 0x7200, 0x7cd8, 0x7ddc,
-	0x7fd0, 0x71d0, 0xd1b4, 0x0528, 0xd1bc, 0x1518, 0x2001, 0x4601,
-	0x2004, 0xd0c4, 0x11f0, 0x7868, 0xa084, 0x00ff, 0x11d0, 0xa282,
-	0x0002, 0x12b8, 0x00d6, 0x783b, 0x8300, 0x781b, 0x0059, 0x70b8,
-	0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2,
-	0x78da, 0xc1b4, 0x71d2, 0x7003, 0x0030, 0x00de, 0x2001, 0x0000,
-	0x0058, 0x783b, 0x1300, 0x781b, 0x0057, 0x2001, 0x0000, 0x0020,
-	0x7200, 0x7cd8, 0x7ddc, 0x7fd0, 0x7046, 0x68a0, 0xd0ec, 0x0118,
-	0x6008, 0xc08d, 0x600a, 0xa284, 0x000f, 0x0002, 0x3059, 0x2f33,
-	0x2f30, 0x3184, 0x320f, 0x25a0, 0x2f2e, 0x2f2e, 0x080c, 0x254c,
-	0x6008, 0xc0d4, 0x600a, 0xd6e4, 0x0120, 0x7044, 0xa086, 0x0014,
-	0x11e8, 0x080c, 0x3f26, 0x2009, 0x0000, 0x6818, 0xd0fc, 0x0108,
-	0x7044, 0xa086, 0x0014, 0x0168, 0x6818, 0xa086, 0x0008, 0x1904,
-	0x301b, 0x7858, 0xd09c, 0x0904, 0x301b, 0x6820, 0xd0ac, 0x0904,
-	0x301b, 0x681b, 0x0014, 0x2009, 0x0002, 0x04a8, 0x7868, 0xa08c,
-	0x00ff, 0x0588, 0xa186, 0x0008, 0x1158, 0x6008, 0xc0a4, 0x600a,
-	0x080c, 0x374f, 0x0540, 0x080c, 0x37be, 0x080c, 0x3f26, 0x0060,
-	0xa186, 0x0028, 0x1500, 0x6018, 0xa005, 0x0d78, 0x8001, 0x0d68,
-	0x8001, 0x0d58, 0x601e, 0x0c48, 0x6820, 0xd084, 0x0904, 0x25a0,
-	0xc084, 0x6822, 0x080c, 0x2693, 0x7058, 0x00c6, 0x2060, 0x6800,
-	0x6002, 0x00ce, 0x6004, 0x6802, 0xa005, 0x2d00, 0x1108, 0x6002,
-	0x6006, 0x0804, 0x25a0, 0x0016, 0x81ff, 0x15f0, 0x7000, 0xa086,
-	0x0030, 0x05d0, 0x71d0, 0xd1bc, 0x15b8, 0xd1b4, 0x11e8, 0x705c,
-	0xa005, 0x1590, 0x70a0, 0xa086, 0x0001, 0x0570, 0x7003, 0x0000,
-	0x0046, 0x0056, 0x0076, 0x0066, 0x00c6, 0x00d6, 0x080c, 0x25c5,
-	0x00de, 0x00ce, 0x006e, 0x007e, 0x005e, 0x004e, 0x71d0, 0xd1b4,
-	0x11d8, 0x7003, 0x0040, 0x00c0, 0x080c, 0x3c33, 0x11a8, 0x781b,
-	0x0068, 0x00d6, 0x70b8, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6,
+	0x6820, 0xa084, 0x00ff, 0xc09d, 0x6822, 0x080c, 0x1dbf, 0x000e,
+	0x0c48, 0x004e, 0x2023, 0x0000, 0x0005, 0xa282, 0x0003, 0x0310,
+	0x080c, 0x2575, 0x2300, 0x0002, 0x2a8f, 0x2b0c, 0x2b1a, 0xa282,
+	0x0002, 0x0110, 0x080c, 0x2575, 0x7060, 0x7063, 0x0000, 0x707f,
+	0x0000, 0x0022, 0x77d0, 0xc7c5, 0x77d2, 0x0002, 0x2aa6, 0x2aa6,
+	0x2aa8, 0x2ae0, 0x37fb, 0x2aa6, 0x2ae0, 0x2aa6, 0x080c, 0x2575,
+	0x7770, 0x080c, 0x3a8b, 0x7770, 0xa7bc, 0x8f00, 0x080c, 0x3b95,
+	0x6018, 0xa005, 0x0528, 0xd7fc, 0x1118, 0x2021, 0x8dc0, 0x0010,
+	0x2021, 0x8ed0, 0x2009, 0x0005, 0x2011, 0x0010, 0x080c, 0x2b34,
+	0x01b8, 0x0156, 0x20a9, 0x0101, 0xd7fc, 0x1118, 0x2021, 0x8cc0,
+	0x0010, 0x2021, 0x8dd0, 0x0046, 0x2009, 0x0005, 0x2011, 0x0010,
+	0x080c, 0x2b34, 0x004e, 0x0118, 0x8420, 0x1f04, 0x2acb, 0x015e,
+	0x8738, 0xa784, 0x001f, 0x1990, 0x0804, 0x25c9, 0x0804, 0x25c9,
+	0x7770, 0x080c, 0x3b95, 0x6018, 0xa005, 0x0520, 0xd7fc, 0x1118,
+	0x2021, 0x8dc0, 0x0010, 0x2021, 0x8ed0, 0x2009, 0x0005, 0x2011,
+	0x0020, 0x080c, 0x2b34, 0x01b0, 0x0156, 0x20a9, 0x0101, 0xd7fc,
+	0x1118, 0x2021, 0x8cc0, 0x0010, 0x2021, 0x8dd0, 0x0046, 0x2009,
+	0x0005, 0x2011, 0x0020, 0x0481, 0x004e, 0x0118, 0x8420, 0x1f04,
+	0x2afe, 0x015e, 0x0804, 0x25c9, 0x2200, 0x0002, 0x2b11, 0x2b13,
+	0x2b13, 0x080c, 0x2575, 0x7063, 0x0000, 0x70d0, 0xc0c5, 0x70d2,
+	0x0804, 0x25c9, 0x2200, 0x0002, 0x2b21, 0x2b13, 0x2b1f, 0x080c,
+	0x2575, 0x080c, 0x3f4e, 0x7000, 0xa086, 0x0002, 0x1904, 0x3780,
+	0x080c, 0x37e1, 0x6008, 0xa084, 0xfbef, 0x600a, 0x080c, 0x3772,
+	0x0904, 0x3780, 0x0804, 0x25c9, 0x2404, 0xa005, 0x0590, 0x2068,
+	0x2d04, 0x0006, 0x6814, 0xa706, 0x0118, 0x2d20, 0x000e, 0x0ca8,
+	0x000e, 0x2022, 0x691a, 0x6817, 0x0000, 0x682b, 0x0000, 0x68b4,
+	0xa084, 0x5f00, 0x681e, 0x6820, 0xa084, 0x00ff, 0xa205, 0x6822,
+	0x080c, 0x1dbf, 0x2021, 0x4702, 0x241c, 0x8319, 0x2322, 0x6010,
+	0x8001, 0x6012, 0x1128, 0x2021, 0x4704, 0x2404, 0xc0a5, 0x2022,
+	0x6008, 0xa084, 0xf9ef, 0x600a, 0x080c, 0x26ca, 0x080c, 0x37e1,
+	0x0005, 0xa085, 0x0001, 0x0ce0, 0x2300, 0x0002, 0x2b73, 0x2b71,
+	0x2bee, 0x080c, 0x2575, 0x78e4, 0xa005, 0x17b0, 0x3208, 0xa18c,
+	0x0800, 0x0118, 0x0104, 0x25c6, 0x0010, 0x0304, 0x25c6, 0x2008,
+	0xa084, 0x0030, 0x1110, 0x0804, 0x324d, 0x78ec, 0xa084, 0x0003,
+	0x0dd0, 0x7884, 0xd0fc, 0x1118, 0xa184, 0x0007, 0x0090, 0xa184,
+	0x0007, 0xa086, 0x0004, 0x1118, 0x2001, 0x0000, 0x0050, 0xa184,
+	0x0007, 0xa086, 0x0005, 0x0118, 0xa184, 0x0007, 0x0010, 0x2001,
+	0x0001, 0x0002, 0x2bd1, 0x2bda, 0x2bc7, 0x2baa, 0x3c4f, 0x3c4f,
+	0x2baa, 0x2be4, 0x080c, 0x2575, 0x7000, 0xa086, 0x0004, 0x1190,
+	0x7060, 0xa086, 0x0002, 0x1130, 0x2011, 0x0002, 0x2019, 0x0000,
+	0x0804, 0x2a85, 0x7060, 0xa086, 0x0006, 0x0db0, 0x7060, 0xa086,
+	0x0004, 0x0d90, 0x79e4, 0x2001, 0x0003, 0x0804, 0x2f3b, 0x6818,
+	0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c, 0x3a61, 0x781b, 0x006e,
+	0x0005, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c, 0x3a61,
+	0x0804, 0x3c2d, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c,
+	0x3a61, 0x781b, 0x00fa, 0x0005, 0x6818, 0xd0fc, 0x0110, 0x681b,
+	0x001d, 0x080c, 0x3a61, 0x781b, 0x00cb, 0x0005, 0xa584, 0x000f,
+	0x11c0, 0x7000, 0x0002, 0x25c9, 0x2bfb, 0x2bfd, 0x3780, 0x3780,
+	0x3780, 0x2bfb, 0x2bfb, 0x080c, 0x2575, 0x080c, 0x37e1, 0x6008,
+	0xa084, 0xfbef, 0x600a, 0x080c, 0x3772, 0x0904, 0x3780, 0x0804,
+	0x25c9, 0x78e4, 0xa005, 0x1b04, 0x2bac, 0x3208, 0xa18c, 0x0800,
+	0x0118, 0x0104, 0x2bac, 0x0010, 0x0304, 0x2bac, 0x2008, 0xa084,
+	0x0030, 0x1118, 0x781b, 0x0068, 0x0005, 0x78ec, 0xa084, 0x0003,
+	0x0dc8, 0x7884, 0xd0fc, 0x1118, 0xa184, 0x0007, 0x0090, 0xa184,
+	0x0007, 0xa086, 0x0004, 0x1118, 0x2001, 0x0000, 0x0050, 0xa184,
+	0x0007, 0xa086, 0x0005, 0x0118, 0xa184, 0x0007, 0x0010, 0x2001,
+	0x0001, 0x0002, 0x2c49, 0x2c4d, 0x2c44, 0x2c42, 0x3c4f, 0x3c4f,
+	0x2c42, 0x3c49, 0x080c, 0x2575, 0x080c, 0x3a67, 0x781b, 0x006e,
+	0x0005, 0x080c, 0x3a67, 0x0804, 0x3c2d, 0x080c, 0x3a67, 0x781b,
+	0x00fa, 0x0005, 0x080c, 0x3a67, 0x781b, 0x00cb, 0x0005, 0x2300,
+	0x0002, 0x2c5e, 0x2c5c, 0x2c60, 0x080c, 0x2575, 0x0804, 0x3405,
+	0x681b, 0x0016, 0x78a3, 0x0000, 0x79e4, 0xa184, 0x0030, 0x0904,
+	0x3405, 0x78ec, 0xa084, 0x0003, 0x0904, 0x3405, 0xa184, 0x0100,
+	0x0d98, 0x7884, 0xd0fc, 0x1118, 0xa184, 0x0007, 0x0090, 0xa184,
+	0x0007, 0xa086, 0x0004, 0x1118, 0x2001, 0x0000, 0x0050, 0xa184,
+	0x0007, 0xa086, 0x0005, 0x0118, 0xa184, 0x0007, 0x0010, 0x2001,
+	0x0001, 0x0002, 0x2c92, 0x2c4d, 0x2bc7, 0x3c0b, 0x3c4f, 0x3c4f,
+	0x3c0b, 0x3c49, 0x080c, 0x3c17, 0x0005, 0xa282, 0x0005, 0x0310,
+	0x080c, 0x2575, 0x7898, 0x2040, 0x2300, 0x0002, 0x2ca1, 0x2ecb,
+	0x2ed5, 0x2200, 0x0002, 0x2cbd, 0x2caa, 0x2cbd, 0x2ca8, 0x2ead,
+	0x080c, 0x2575, 0x789b, 0x0018, 0x78a8, 0x2010, 0xa084, 0x00ff,
+	0xa082, 0x0020, 0x0a04, 0x3a30, 0xa08a, 0x0004, 0x1a04, 0x3a30,
+	0x0002, 0x3a30, 0x3a30, 0x3a30, 0x39e4, 0x789b, 0x0018, 0x79a8,
+	0xa184, 0x0080, 0x0148, 0x0804, 0x3a30, 0x7000, 0xa005, 0x1dd8,
+	0x2011, 0x0004, 0x0804, 0x35b7, 0xa184, 0x00ff, 0xa08a, 0x0010,
+	0x1a04, 0x3a30, 0x0002, 0x2ce5, 0x2ce3, 0x2cf7, 0x2cfb, 0x2da9,
+	0x3a30, 0x3a30, 0x2dab, 0x3a30, 0x3a30, 0x2ea9, 0x2ea9, 0x3a30,
+	0x3a30, 0x3a30, 0x2eab, 0x080c, 0x2575, 0xd6e4, 0x0140, 0x2001,
+	0x0300, 0x8000, 0x8000, 0x783a, 0x781b, 0x00c7, 0x0005, 0x6818,
+	0xd0fc, 0x0118, 0x681b, 0x001d, 0x0c90, 0x0804, 0x3c0b, 0x681b,
+	0x001d, 0x0804, 0x3a5b, 0x6920, 0x6922, 0xa684, 0x1800, 0x1904,
+	0x2d4c, 0x6820, 0xd084, 0x1904, 0x2d54, 0x6818, 0xa086, 0x0008,
+	0x1110, 0x681b, 0x0000, 0xd6d4, 0x0568, 0xd6bc, 0x0558, 0x7083,
+	0x0000, 0x6818, 0xa084, 0x003f, 0xa08a, 0x000d, 0x0718, 0xa08a,
+	0x000c, 0x7182, 0x2001, 0x000c, 0x800c, 0x7186, 0x789b, 0x0061,
+	0x78aa, 0x0156, 0x0136, 0x0146, 0x0016, 0x3208, 0xa18c, 0x0600,
+	0x0118, 0x20a1, 0x022b, 0x0010, 0x20a1, 0x012b, 0x001e, 0x789b,
+	0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x014e,
+	0x013e, 0x015e, 0x6038, 0xa005, 0x1150, 0x681c, 0xa084, 0x000e,
+	0x0904, 0x3a5b, 0x080c, 0x3a6d, 0x782b, 0x3008, 0x0010, 0x8001,
+	0x603a, 0x781b, 0x0071, 0x0005, 0xd6e4, 0x0130, 0x781b, 0x0083,
+	0x0005, 0x781b, 0x0083, 0x0005, 0xa684, 0x0060, 0x0dd0, 0xd6dc,
+	0x0dc0, 0xd6fc, 0x01a0, 0xc6fc, 0x7e5a, 0x6eb6, 0x7adc, 0x79d8,
+	0x78d0, 0x8007, 0xa084, 0x007f, 0xa108, 0xa291, 0x0000, 0x6b98,
+	0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0xd6f4,
+	0x0118, 0xc6f4, 0x7e5a, 0x6eb6, 0x7000, 0xa086, 0x0003, 0x1148,
+	0x0006, 0x080c, 0x3f4e, 0x080c, 0x4208, 0x000e, 0x781b, 0x0080,
+	0x0005, 0xa006, 0x080c, 0x42e8, 0x6ab0, 0x69ac, 0x6c98, 0x6b94,
+	0x2200, 0xa105, 0x0120, 0x2200, 0xa422, 0x2100, 0xa31b, 0x6caa,
+	0x7cd2, 0x7cda, 0x6ba6, 0x7bd6, 0x7bde, 0x2300, 0xa405, 0x1130,
+	0xc6f5, 0x7e5a, 0x6eb6, 0x781b, 0x0080, 0x0005, 0x781b, 0x0080,
+	0x2200, 0xa115, 0x1118, 0x080c, 0x4208, 0x0005, 0x080c, 0x4235,
+	0x0005, 0x080c, 0x2575, 0x0804, 0x2e3f, 0x00c6, 0x7054, 0x2060,
+	0x6920, 0xa18c, 0xecff, 0x6922, 0x6000, 0xa084, 0xcfdf, 0x6002,
+	0x080c, 0x3917, 0xa006, 0x2040, 0x2038, 0x080c, 0x39bf, 0x0804,
+	0x2e33, 0x00c6, 0x7054, 0x2060, 0x2c48, 0x7aa8, 0xa294, 0x00ff,
+	0xa286, 0x0004, 0x11d8, 0x6920, 0xd1e4, 0x1170, 0x2039, 0x0000,
+	0x2041, 0x0000, 0x2031, 0x0000, 0xa006, 0x2010, 0x080c, 0x391a,
+	0x080c, 0x39bf, 0x0804, 0x2e33, 0xa18c, 0xecff, 0x6922, 0x6104,
+	0xa18c, 0xffdd, 0x6106, 0x6000, 0xc0ac, 0x6002, 0xa286, 0x0003,
+	0x01d0, 0x6104, 0xa184, 0x0010, 0x0548, 0x080c, 0x3b91, 0x080c,
+	0x399a, 0x88ff, 0x0518, 0x00ce, 0x789b, 0x0060, 0x2800, 0x78aa,
+	0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x1118, 0x781b, 0x006e, 0x0005,
+	0x781b, 0x0082, 0x0005, 0x6920, 0xd1cc, 0x0130, 0xa18c, 0xfdff,
+	0x6922, 0x6000, 0xc0ec, 0x6002, 0x2039, 0x0000, 0x2041, 0x0000,
+	0x2031, 0x0000, 0xa006, 0x2010, 0x080c, 0x39bf, 0xa286, 0x0001,
+	0x0158, 0x6104, 0xa184, 0x0008, 0x01b0, 0x080c, 0x3b91, 0x080c,
+	0x38b8, 0x88ff, 0x1980, 0x0078, 0x6920, 0xd1c4, 0x0130, 0xa18c,
+	0xfeff, 0x6922, 0x6000, 0xc0e4, 0x6002, 0x2031, 0x0000, 0xa006,
+	0x2010, 0x080c, 0x391a, 0x00ce, 0x7e58, 0xd6d4, 0x1118, 0x781b,
+	0x0071, 0x0005, 0x781b, 0x0083, 0x0005, 0x0804, 0x3a57, 0x2808,
+	0x789b, 0x0080, 0x2019, 0x0080, 0x78a8, 0xa094, 0x00ff, 0xa286,
+	0x0001, 0x11b8, 0x2300, 0xa102, 0xa086, 0x0001, 0x0904, 0x2dad,
+	0x7ca8, 0xa4a4, 0x00ff, 0xa480, 0x0002, 0xa300, 0x2018, 0xa102,
+	0x0a04, 0x2dc1, 0x0904, 0x2dc1, 0x24a8, 0x7aa8, 0x1f04, 0x2e5d,
+	0x0c18, 0xa284, 0x00f0, 0xa082, 0x0020, 0x06b8, 0x2200, 0xa082,
+	0x0021, 0x1698, 0x7aa8, 0x8318, 0x8318, 0x2100, 0xa302, 0x0aa0,
+	0xa286, 0x0023, 0x0950, 0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58,
+	0xa684, 0xfff1, 0xc0a5, 0x2030, 0x7e5a, 0x6008, 0xc0a5, 0x600a,
+	0x78a0, 0xa005, 0x0904, 0x2e34, 0x20a8, 0x7998, 0x789b, 0x0060,
+	0x78aa, 0x2011, 0x0080, 0x799a, 0x78a8, 0x7998, 0x7a9a, 0x78aa,
+	0x7a98, 0x1f04, 0x2e8b, 0xc695, 0x7e5a, 0xd6d4, 0x1118, 0x781b,
+	0x006e, 0x0005, 0x781b, 0x0082, 0x0005, 0x8318, 0x2100, 0xa302,
+	0x0a04, 0x2e44, 0xa284, 0x0080, 0x1904, 0x3a5b, 0x78a0, 0xa005,
+	0x08c8, 0x0804, 0x3a5b, 0x0804, 0x3a30, 0x7054, 0xa04d, 0x789b,
+	0x0018, 0x78a8, 0xa084, 0x00ff, 0xa08e, 0x0001, 0x0110, 0x080c,
+	0x2575, 0x7aa8, 0xa294, 0x00ff, 0x784b, 0x0008, 0x78a8, 0xa084,
+	0x00ff, 0xa08a, 0x0005, 0x1a04, 0x3a30, 0x0002, 0x3a30, 0x382f,
+	0x3a30, 0x394a, 0x3d59, 0xa282, 0x0000, 0x1110, 0x080c, 0x2575,
+	0x080c, 0x3a61, 0x781b, 0x0082, 0x0005, 0xa282, 0x0003, 0x1110,
+	0x080c, 0x2575, 0xd4fc, 0x11d0, 0x7060, 0xa005, 0x0110, 0x080c,
+	0x2575, 0x6f14, 0x7772, 0xa7bc, 0x8f00, 0x080c, 0x3b95, 0x6008,
+	0xa085, 0x0021, 0x600a, 0x8738, 0xa784, 0x001f, 0x1db0, 0x080c,
+	0x3a64, 0x7063, 0x0002, 0x701f, 0x0009, 0x0010, 0x080c, 0x3a70,
+	0x781b, 0x0082, 0x0005, 0xa282, 0x0004, 0x0310, 0x080c, 0x2575,
+	0x2300, 0x0002, 0x2f05, 0x309b, 0x30d7, 0xa286, 0x0003, 0x0598,
+	0x7200, 0x7cd8, 0x7ddc, 0x7fd0, 0x71d0, 0xd1b4, 0x0528, 0xd1bc,
+	0x1518, 0x2001, 0x4701, 0x2004, 0xd0c4, 0x11f0, 0x7868, 0xa084,
+	0x00ff, 0x11d0, 0xa282, 0x0002, 0x12b8, 0x00d6, 0x783b, 0x8300,
+	0x781b, 0x0059, 0x70b8, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6,
 	0x78de, 0x6898, 0x78d2, 0x78da, 0xc1b4, 0x71d2, 0x7003, 0x0030,
-	0x7808, 0xc08d, 0x780a, 0x00de, 0x080c, 0x30dc, 0x001e, 0x81ff,
-	0x0904, 0x301b, 0xa684, 0xdf00, 0x681e, 0x682b, 0x0000, 0x6f14,
-	0xa186, 0x0002, 0x1904, 0x301c, 0x6818, 0xa086, 0x0014, 0x1130,
-	0x2008, 0xd6e4, 0x0118, 0x7868, 0xa08c, 0x00ff, 0x080c, 0x3a55,
-	0x080c, 0x269e, 0x6820, 0xd0dc, 0x1578, 0x8717, 0xa294, 0x000f,
-	0x8213, 0x8213, 0x8213, 0xb284, 0x0600, 0x0118, 0xa290, 0x4ac0,
-	0x0010, 0xa290, 0x4b40, 0xa290, 0x0000, 0x221c, 0xd3c4, 0x0170,
-	0x6820, 0xd0e4, 0x0128, 0xa084, 0xefff, 0x6822, 0xc3ac, 0x2312,
-	0x8210, 0x2204, 0xa085, 0x0038, 0x2012, 0x8211, 0xd3d4, 0x0138,
-	0x68a0, 0xd0c4, 0x1120, 0x080c, 0x3144, 0x0804, 0x25a0, 0x6008,
-	0xc08d, 0x600a, 0x0008, 0x692a, 0x6916, 0x6818, 0xd0fc, 0x0110,
-	0x7044, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x6410, 0x84ff, 0x0168,
-	0x2009, 0x4602, 0x2104, 0x8001, 0x200a, 0x8421, 0x6412, 0x1128,
-	0x2021, 0x4604, 0x2404, 0xc0a5, 0x2022, 0x6018, 0xa005, 0x0118,
-	0x8001, 0x601a, 0x1118, 0x6008, 0xc0a4, 0x600a, 0x6820, 0xd084,
-	0x1130, 0x6800, 0xa005, 0x1108, 0x6002, 0x6006, 0x0020, 0x7058,
-	0x2060, 0x6800, 0x6002, 0x2061, 0x4600, 0x6887, 0x0103, 0x2d08,
-	0x206b, 0x0000, 0x6068, 0xa005, 0x616a, 0x0110, 0x2d02, 0x0008,
-	0x616e, 0x7200, 0xa286, 0x0030, 0x0158, 0xa286, 0x0040, 0x1904,
-	0x25a0, 0x7003, 0x0002, 0x7048, 0x2068, 0x68c4, 0x2060, 0x0005,
-	0x7003, 0x0002, 0x70b8, 0xa06d, 0x68bc, 0x703e, 0x70b4, 0xa065,
-	0x68c0, 0x7056, 0x2d00, 0x704a, 0xad80, 0x0009, 0x7042, 0x0005,
-	0xa282, 0x0004, 0x0210, 0x080c, 0x254c, 0x2200, 0x0002, 0x3083,
-	0x3092, 0x309e, 0x3092, 0xa586, 0x1300, 0x0160, 0xa586, 0x8300,
-	0x1d90, 0x7003, 0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084,
-	0xfbef, 0x600a, 0x7000, 0xa086, 0x0005, 0x0128, 0x080c, 0x3a3c,
-	0x781b, 0x0082, 0x0005, 0x781b, 0x0083, 0x0005, 0x7890, 0x8007,
-	0x8001, 0xa084, 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c,
-	0x00ff, 0xa186, 0x0003, 0x0128, 0xa186, 0x0000, 0x0110, 0x0804,
-	0x3a0b, 0x781b, 0x0083, 0x0005, 0x6820, 0xc095, 0x6822, 0x82ff,
-	0x1118, 0x080c, 0x3a3c, 0x0030, 0x8211, 0x0110, 0x080c, 0x254c,
-	0x080c, 0x3a4b, 0x781b, 0x0082, 0x0005, 0x080c, 0x3c46, 0x7830,
-	0xa084, 0x00c0, 0x1170, 0x0016, 0x3208, 0xa18c, 0x0800, 0x001e,
-	0x0118, 0x0104, 0x30d9, 0x0010, 0x0304, 0x30d9, 0x791a, 0xa006,
-	0x0005, 0xa085, 0x0001, 0x0005, 0xa684, 0x0060, 0x1130, 0x682f,
-	0x0000, 0x6833, 0x0000, 0x0804, 0x3143, 0xd6dc, 0x1198, 0x68b4,
-	0xd0dc, 0x1180, 0x6998, 0x6a94, 0x692e, 0x6a32, 0x7044, 0xa005,
-	0x1130, 0x2200, 0xa105, 0x0904, 0x3f26, 0x7047, 0x0015, 0x0804,
-	0x3f26, 0x0005, 0xd6ac, 0x01f0, 0xd6f4, 0x0130, 0x682f, 0x0000,
-	0x6833, 0x0000, 0x0804, 0x3f26, 0x68b4, 0xa084, 0x4000, 0xa635,
-	0xd6f4, 0x1da0, 0x7044, 0xa005, 0x1110, 0x7047, 0x0015, 0xd6dc,
-	0x1128, 0x68b4, 0xd0dc, 0x0110, 0x6ca8, 0x6da4, 0x6c2e, 0x6d32,
-	0x0804, 0x3f26, 0xd6f4, 0x0130, 0x682f, 0x0000, 0x6833, 0x0000,
-	0x0804, 0x3f26, 0x68b4, 0xa084, 0x4800, 0xa635, 0xd6f4, 0x1da0,
-	0x7044, 0xa005, 0x1110, 0x7047, 0x0015, 0x2408, 0x2510, 0x2700,
-	0x8007, 0xa084, 0x007f, 0xa108, 0xa291, 0x0000, 0x692e, 0x6a32,
-	0x2100, 0xa205, 0x1110, 0x0804, 0x3f26, 0x7000, 0xa086, 0x0006,
-	0x0110, 0x0804, 0x3f26, 0x0005, 0x6946, 0x6008, 0xc0cd, 0xd3cc,
-	0x0108, 0xc08d, 0x600a, 0x6818, 0x683a, 0x681b, 0x0006, 0x688f,
-	0x0000, 0x6893, 0x0000, 0x6a30, 0x692c, 0x6a3e, 0x6942, 0x682f,
-	0x0003, 0x6833, 0x0000, 0x6837, 0x0020, 0x6897, 0x0000, 0x689b,
-	0x0020, 0x7000, 0x0002, 0x25a0, 0x3173, 0x316d, 0x316b, 0x316b,
-	0x316b, 0x316b, 0x316b, 0x080c, 0x254c, 0x6820, 0xd084, 0x1118,
-	0x080c, 0x37a4, 0x0030, 0x7058, 0x2c50, 0x2060, 0x6800, 0x6002,
-	0x2a60, 0xaea0, 0x0017, 0x2404, 0xa005, 0x0110, 0x2020, 0x0cd8,
-	0x2d22, 0x206b, 0x0000, 0x0005, 0x080c, 0x37aa, 0x080c, 0x37be,
-	0x6008, 0xc0cc, 0x600a, 0x682b, 0x0000, 0x789b, 0x000e, 0x6f14,
-	0x6938, 0x691a, 0x6944, 0x6916, 0x2009, 0x0000, 0xae86, 0x4640,
-	0x0110, 0x2009, 0x0001, 0x080c, 0x42ec, 0xd6dc, 0x01c8, 0x691c,
-	0xc1ed, 0x691e, 0x6828, 0xa082, 0x000e, 0x0290, 0x6848, 0xa084,
-	0x000f, 0xa086, 0x000b, 0x1160, 0x685c, 0xa086, 0x0047, 0x1140,
-	0x2001, 0x4601, 0x2004, 0xd0ac, 0x1118, 0x2700, 0x080c, 0x2475,
-	0x6818, 0xd0fc, 0x0140, 0x681b, 0x0000, 0x7868, 0xa08c, 0x00ff,
-	0x0110, 0x681b, 0x001e, 0xaea0, 0x0017, 0x6800, 0x2022, 0x6a3c,
-	0x6940, 0x6a32, 0x692e, 0x68c0, 0x2060, 0x6000, 0xd0a4, 0x0580,
-	0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x00d6, 0x00f6,
-	0x0156, 0x0146, 0x2079, 0x4600, 0x080c, 0x1b93, 0x014e, 0x015e,
-	0x00fe, 0x70c8, 0x2010, 0x2009, 0x0101, 0x0026, 0x2204, 0xa06d,
-	0x0140, 0x6814, 0xa706, 0x0110, 0x6800, 0x0cc8, 0x6820, 0xc0d5,
-	0x6822, 0x002e, 0x8210, 0x8109, 0x1d80, 0x00de, 0x7063, 0x0003,
-	0x707b, 0x0000, 0x7772, 0x707f, 0x000f, 0x71d0, 0xc1c4, 0x71d2,
-	0x6818, 0xa086, 0x0002, 0x1138, 0x6817, 0x0000, 0x682b, 0x0000,
-	0x681c, 0xc0ec, 0x681e, 0x080c, 0x1da2, 0x0804, 0x25a0, 0x7cd8,
-	0x7ddc, 0x7fd0, 0x080c, 0x30dc, 0x682b, 0x0000, 0x789b, 0x000e,
-	0x6f14, 0x080c, 0x3c4a, 0xa08c, 0x00ff, 0x6916, 0x6818, 0xd0fc,
-	0x0110, 0x7044, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x7063, 0x0000,
-	0x0804, 0x25a0, 0x7000, 0xa005, 0x1110, 0x0804, 0x25a0, 0xa006,
-	0x080c, 0x3f26, 0x6920, 0xd1ac, 0x1110, 0x681b, 0x0014, 0xa68c,
-	0xdf00, 0x691e, 0x682b, 0x0000, 0x6820, 0xa084, 0x00ff, 0x6822,
-	0x7000, 0x0002, 0x25a0, 0x324c, 0x324c, 0x324f, 0x324f, 0x324f,
-	0x324a, 0x324a, 0x080c, 0x254c, 0x6818, 0x0804, 0x2f18, 0x6008,
-	0xc0a4, 0x600a, 0x6817, 0x0000, 0x0804, 0x3772, 0x2300, 0x0002,
-	0x325b, 0x325d, 0x32ab, 0x080c, 0x254c, 0xd6fc, 0x1904, 0x2d38,
-	0x7000, 0xa00d, 0x0002, 0x25a0, 0x326d, 0x326d, 0x3297, 0x326d,
-	0x32a8, 0x326b, 0x326b, 0x080c, 0x254c, 0xa684, 0x0060, 0x0538,
-	0xa086, 0x0060, 0x1510, 0xc6ac, 0xc6f4, 0xc6ed, 0x7e5a, 0x6eb6,
-	0x681c, 0xc0ac, 0x681e, 0xa186, 0x0002, 0x0148, 0x080c, 0x3f26,
-	0x69ac, 0x68b0, 0xa115, 0x0118, 0x080c, 0x4206, 0x0010, 0x080c,
-	0x41d9, 0x781b, 0x0083, 0x71d0, 0xd1b4, 0x1904, 0x259d, 0x70a0,
-	0xa086, 0x0001, 0x1904, 0x25e1, 0x0005, 0xd6ec, 0x09f0, 0x6818,
-	0xd0fc, 0x0170, 0xd6f4, 0x1130, 0x681b, 0x0015, 0x781b, 0x0083,
-	0x0804, 0x259d, 0x681b, 0x0007, 0x682f, 0x0000, 0x6833, 0x0000,
-	0x080c, 0x3bf1, 0x0005, 0x080c, 0x254c, 0x2300, 0x0002, 0x32b4,
-	0x32d6, 0x332e, 0x080c, 0x254c, 0x7000, 0x0002, 0x32be, 0x32c0,
-	0x32c7, 0x32be, 0x32be, 0x32be, 0x32be, 0x32be, 0x080c, 0x254c,
-	0x69ac, 0x68b0, 0xa115, 0x0118, 0x080c, 0x4206, 0x0010, 0x080c,
-	0x41d9, 0x681c, 0xc0b4, 0x681e, 0x70d0, 0xd0b4, 0x1904, 0x259d,
-	0x70a0, 0xa086, 0x0001, 0x1904, 0x25e1, 0x0005, 0xd6fc, 0x1904,
-	0x331e, 0x7000, 0xa00d, 0x0002, 0x25a0, 0x32ec, 0x32e6, 0x3316,
-	0x32ec, 0x331b, 0x32e4, 0x32e4, 0x080c, 0x254c, 0x6894, 0x78d6,
-	0x78de, 0x6898, 0x78d2, 0x78da, 0xa684, 0x0060, 0x0538, 0xa086,
-	0x0060, 0x1510, 0xa6b4, 0xbfbf, 0xc6ed, 0x7e5a, 0x6eb6, 0xa186,
-	0x0002, 0x0148, 0x080c, 0x3f26, 0x69ac, 0x68b0, 0xa115, 0x0118,
-	0x080c, 0x4206, 0x0010, 0x080c, 0x41d9, 0x781b, 0x0083, 0x681c,
-	0xc0b4, 0x681e, 0x71d0, 0xd1b4, 0x1904, 0x259d, 0x70a0, 0xa086,
-	0x0001, 0x1904, 0x25e1, 0x0005, 0xd6ec, 0x09f0, 0x6818, 0xd0fc,
-	0x0110, 0x681b, 0x0007, 0x781b, 0x00fb, 0x0005, 0xc6fc, 0x7e5a,
-	0x7adc, 0x79d8, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200,
-	0xa303, 0x68ae, 0x79d2, 0x781b, 0x0083, 0x0005, 0xd6dc, 0x0130,
-	0x782b, 0x3009, 0x781b, 0x0083, 0x0804, 0x259d, 0x7884, 0xc0ac,
-	0x7886, 0x78e4, 0xa084, 0x0008, 0x1150, 0xa484, 0x0200, 0x0108,
-	0xc6f5, 0xc6dd, 0x7e5a, 0x781b, 0x0083, 0x0804, 0x259d, 0x6820,
-	0xc095, 0x6822, 0x080c, 0x3bdc, 0xc6dd, 0x080c, 0x3a3c, 0x781b,
-	0x0082, 0x0804, 0x259d, 0x2300, 0x0002, 0x3358, 0x335a, 0x335c,
-	0x080c, 0x254c, 0x0804, 0x3a36, 0x7d98, 0xd6d4, 0x15a8, 0x79e4,
-	0xd1ac, 0x0130, 0x78ec, 0xa084, 0x0003, 0x0110, 0x782b, 0x3009,
-	0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, 0x7d9a,
-	0x79e4, 0xd1ac, 0x0120, 0x78ec, 0xa084, 0x0003, 0x1120, 0x2001,
-	0x0014, 0x0804, 0x2f18, 0x7884, 0xd0fc, 0x1118, 0xa184, 0x0007,
+	0x00de, 0x2001, 0x0000, 0x0058, 0x783b, 0x1300, 0x781b, 0x0057,
+	0x2001, 0x0000, 0x0020, 0x7200, 0x7cd8, 0x7ddc, 0x7fd0, 0x7046,
+	0x68a0, 0xd0ec, 0x0118, 0x6008, 0xc08d, 0x600a, 0xa284, 0x000f,
+	0x0002, 0x307c, 0x2f56, 0x2f53, 0x31a7, 0x3232, 0x25c9, 0x2f51,
+	0x2f51, 0x080c, 0x2575, 0x6008, 0xc0d4, 0x600a, 0xd6e4, 0x0120,
+	0x7044, 0xa086, 0x0014, 0x11e8, 0x080c, 0x3f4e, 0x2009, 0x0000,
+	0x6818, 0xd0fc, 0x0108, 0x7044, 0xa086, 0x0014, 0x0168, 0x6818,
+	0xa086, 0x0008, 0x1904, 0x303e, 0x7858, 0xd09c, 0x0904, 0x303e,
+	0x6820, 0xd0ac, 0x0904, 0x303e, 0x681b, 0x0014, 0x2009, 0x0002,
+	0x04a8, 0x7868, 0xa08c, 0x00ff, 0x0588, 0xa186, 0x0008, 0x1158,
+	0x6008, 0xc0a4, 0x600a, 0x080c, 0x3772, 0x0540, 0x080c, 0x37e1,
+	0x080c, 0x3f4e, 0x0060, 0xa186, 0x0028, 0x1500, 0x6018, 0xa005,
+	0x0d78, 0x8001, 0x0d68, 0x8001, 0x0d58, 0x601e, 0x0c48, 0x6820,
+	0xd084, 0x0904, 0x25c9, 0xc084, 0x6822, 0x080c, 0x26bf, 0x7058,
+	0x00c6, 0x2060, 0x6800, 0x6002, 0x00ce, 0x6004, 0x6802, 0xa005,
+	0x2d00, 0x1108, 0x6002, 0x6006, 0x0804, 0x25c9, 0x0016, 0x81ff,
+	0x15f0, 0x7000, 0xa086, 0x0030, 0x05d0, 0x71d0, 0xd1bc, 0x15b8,
+	0xd1b4, 0x11e8, 0x705c, 0xa005, 0x1590, 0x70a0, 0xa086, 0x0001,
+	0x0570, 0x7003, 0x0000, 0x0046, 0x0056, 0x0076, 0x0066, 0x00c6,
+	0x00d6, 0x080c, 0x25f1, 0x00de, 0x00ce, 0x006e, 0x007e, 0x005e,
+	0x004e, 0x71d0, 0xd1b4, 0x11d8, 0x7003, 0x0040, 0x00c0, 0x080c,
+	0x3c5b, 0x11a8, 0x781b, 0x0068, 0x00d6, 0x70b8, 0xa06d, 0x68b4,
+	0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0xc1b4,
+	0x71d2, 0x7003, 0x0030, 0x7808, 0xc08d, 0x780a, 0x00de, 0x080c,
+	0x30ff, 0x001e, 0x81ff, 0x0904, 0x303e, 0xa684, 0xdf00, 0x681e,
+	0x682b, 0x0000, 0x6f14, 0xa186, 0x0002, 0x1904, 0x303f, 0x6818,
+	0xa086, 0x0014, 0x1130, 0x2008, 0xd6e4, 0x0118, 0x7868, 0xa08c,
+	0x00ff, 0x080c, 0x3a7a, 0x080c, 0x26ca, 0x6820, 0xd0dc, 0x1578,
+	0x8717, 0xa294, 0x000f, 0x8213, 0x8213, 0x8213, 0xb284, 0x0600,
+	0x0118, 0xa290, 0x4bc0, 0x0010, 0xa290, 0x4c40, 0xa290, 0x0000,
+	0x221c, 0xd3c4, 0x0170, 0x6820, 0xd0e4, 0x0128, 0xa084, 0xefff,
+	0x6822, 0xc3ac, 0x2312, 0x8210, 0x2204, 0xa085, 0x0038, 0x2012,
+	0x8211, 0xd3d4, 0x0138, 0x68a0, 0xd0c4, 0x1120, 0x080c, 0x3167,
+	0x0804, 0x25c9, 0x6008, 0xc08d, 0x600a, 0x0008, 0x692a, 0x6916,
+	0x6818, 0xd0fc, 0x0110, 0x7044, 0x681a, 0xa68c, 0xdf00, 0x691e,
+	0x6410, 0x84ff, 0x0168, 0x2009, 0x4702, 0x2104, 0x8001, 0x200a,
+	0x8421, 0x6412, 0x1128, 0x2021, 0x4704, 0x2404, 0xc0a5, 0x2022,
+	0x6018, 0xa005, 0x0118, 0x8001, 0x601a, 0x1118, 0x6008, 0xc0a4,
+	0x600a, 0x6820, 0xd084, 0x1130, 0x6800, 0xa005, 0x1108, 0x6002,
+	0x6006, 0x0020, 0x7058, 0x2060, 0x6800, 0x6002, 0x2061, 0x4700,
+	0x6887, 0x0103, 0x2d08, 0x206b, 0x0000, 0x6068, 0xa005, 0x616a,
+	0x0110, 0x2d02, 0x0008, 0x616e, 0x7200, 0xa286, 0x0030, 0x0158,
+	0xa286, 0x0040, 0x1904, 0x25c9, 0x7003, 0x0002, 0x7048, 0x2068,
+	0x68c4, 0x2060, 0x0005, 0x7003, 0x0002, 0x70b8, 0xa06d, 0x68bc,
+	0x703e, 0x70b4, 0xa065, 0x68c0, 0x7056, 0x2d00, 0x704a, 0xad80,
+	0x0009, 0x7042, 0x0005, 0xa282, 0x0004, 0x0210, 0x080c, 0x2575,
+	0x2200, 0x0002, 0x30a6, 0x30b5, 0x30c1, 0x30b5, 0xa586, 0x1300,
+	0x0160, 0xa586, 0x8300, 0x1d90, 0x7003, 0x0000, 0x6018, 0x8001,
+	0x601a, 0x6008, 0xa084, 0xfbef, 0x600a, 0x7000, 0xa086, 0x0005,
+	0x0128, 0x080c, 0x3a61, 0x781b, 0x0082, 0x0005, 0x781b, 0x0083,
+	0x0005, 0x7890, 0x8007, 0x8001, 0xa084, 0x0007, 0xa080, 0x0018,
+	0x789a, 0x79a8, 0xa18c, 0x00ff, 0xa186, 0x0003, 0x0128, 0xa186,
+	0x0000, 0x0110, 0x0804, 0x3a30, 0x781b, 0x0083, 0x0005, 0x6820,
+	0xc095, 0x6822, 0x82ff, 0x1118, 0x080c, 0x3a61, 0x0030, 0x8211,
+	0x0110, 0x080c, 0x2575, 0x080c, 0x3a70, 0x781b, 0x0082, 0x0005,
+	0x080c, 0x3c6e, 0x7830, 0xa084, 0x00c0, 0x1170, 0x0016, 0x3208,
+	0xa18c, 0x0800, 0x001e, 0x0118, 0x0104, 0x30fc, 0x0010, 0x0304,
+	0x30fc, 0x791a, 0xa006, 0x0005, 0xa085, 0x0001, 0x0005, 0xa684,
+	0x0060, 0x1130, 0x682f, 0x0000, 0x6833, 0x0000, 0x0804, 0x3166,
+	0xd6dc, 0x1198, 0x68b4, 0xd0dc, 0x1180, 0x6998, 0x6a94, 0x692e,
+	0x6a32, 0x7044, 0xa005, 0x1130, 0x2200, 0xa105, 0x0904, 0x3f4e,
+	0x7047, 0x0015, 0x0804, 0x3f4e, 0x0005, 0xd6ac, 0x01f0, 0xd6f4,
+	0x0130, 0x682f, 0x0000, 0x6833, 0x0000, 0x0804, 0x3f4e, 0x68b4,
+	0xa084, 0x4000, 0xa635, 0xd6f4, 0x1da0, 0x7044, 0xa005, 0x1110,
+	0x7047, 0x0015, 0xd6dc, 0x1128, 0x68b4, 0xd0dc, 0x0110, 0x6ca8,
+	0x6da4, 0x6c2e, 0x6d32, 0x0804, 0x3f4e, 0xd6f4, 0x0130, 0x682f,
+	0x0000, 0x6833, 0x0000, 0x0804, 0x3f4e, 0x68b4, 0xa084, 0x4800,
+	0xa635, 0xd6f4, 0x1da0, 0x7044, 0xa005, 0x1110, 0x7047, 0x0015,
+	0x2408, 0x2510, 0x2700, 0x8007, 0xa084, 0x007f, 0xa108, 0xa291,
+	0x0000, 0x692e, 0x6a32, 0x2100, 0xa205, 0x1110, 0x0804, 0x3f4e,
+	0x7000, 0xa086, 0x0006, 0x0110, 0x0804, 0x3f4e, 0x0005, 0x6946,
+	0x6008, 0xc0cd, 0xd3cc, 0x0108, 0xc08d, 0x600a, 0x6818, 0x683a,
+	0x681b, 0x0006, 0x688f, 0x0000, 0x6893, 0x0000, 0x6a30, 0x692c,
+	0x6a3e, 0x6942, 0x682f, 0x0003, 0x6833, 0x0000, 0x6837, 0x0020,
+	0x6897, 0x0000, 0x689b, 0x0020, 0x7000, 0x0002, 0x25c9, 0x3196,
+	0x3190, 0x318e, 0x318e, 0x318e, 0x318e, 0x318e, 0x080c, 0x2575,
+	0x6820, 0xd084, 0x1118, 0x080c, 0x37c7, 0x0030, 0x7058, 0x2c50,
+	0x2060, 0x6800, 0x6002, 0x2a60, 0xaea0, 0x0017, 0x2404, 0xa005,
+	0x0110, 0x2020, 0x0cd8, 0x2d22, 0x206b, 0x0000, 0x0005, 0x080c,
+	0x37cd, 0x080c, 0x37e1, 0x6008, 0xc0cc, 0x600a, 0x682b, 0x0000,
+	0x789b, 0x000e, 0x6f14, 0x6938, 0x691a, 0x6944, 0x6916, 0x2009,
+	0x0000, 0xae86, 0x4740, 0x0110, 0x2009, 0x0001, 0x080c, 0x431f,
+	0xd6dc, 0x01c8, 0x691c, 0xc1ed, 0x691e, 0x6828, 0xa082, 0x000e,
+	0x0290, 0x6848, 0xa084, 0x000f, 0xa086, 0x000b, 0x1160, 0x685c,
+	0xa086, 0x0047, 0x1140, 0x2001, 0x4701, 0x2004, 0xd0ac, 0x1118,
+	0x2700, 0x080c, 0x249e, 0x6818, 0xd0fc, 0x0140, 0x681b, 0x0000,
+	0x7868, 0xa08c, 0x00ff, 0x0110, 0x681b, 0x001e, 0xaea0, 0x0017,
+	0x6800, 0x2022, 0x6a3c, 0x6940, 0x6a32, 0x692e, 0x68c0, 0x2060,
+	0x6000, 0xd0a4, 0x0580, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051,
+	0x0020, 0x00d6, 0x00f6, 0x0156, 0x0146, 0x2079, 0x4700, 0x080c,
+	0x1bb2, 0x014e, 0x015e, 0x00fe, 0x70c8, 0x2010, 0x2009, 0x0101,
+	0x0026, 0x2204, 0xa06d, 0x0140, 0x6814, 0xa706, 0x0110, 0x6800,
+	0x0cc8, 0x6820, 0xc0d5, 0x6822, 0x002e, 0x8210, 0x8109, 0x1d80,
+	0x00de, 0x7063, 0x0003, 0x707b, 0x0000, 0x7772, 0x707f, 0x000f,
+	0x71d0, 0xc1c4, 0x71d2, 0x6818, 0xa086, 0x0002, 0x1138, 0x6817,
+	0x0000, 0x682b, 0x0000, 0x681c, 0xc0ec, 0x681e, 0x080c, 0x1dbf,
+	0x0804, 0x25c9, 0x7cd8, 0x7ddc, 0x7fd0, 0x080c, 0x30ff, 0x682b,
+	0x0000, 0x789b, 0x000e, 0x6f14, 0x080c, 0x3c72, 0xa08c, 0x00ff,
+	0x6916, 0x6818, 0xd0fc, 0x0110, 0x7044, 0x681a, 0xa68c, 0xdf00,
+	0x691e, 0x7063, 0x0000, 0x0804, 0x25c9, 0x7000, 0xa005, 0x1110,
+	0x0804, 0x25c9, 0xa006, 0x080c, 0x3f4e, 0x6920, 0xd1ac, 0x1110,
+	0x681b, 0x0014, 0xa68c, 0xdf00, 0x691e, 0x682b, 0x0000, 0x6820,
+	0xa084, 0x00ff, 0x6822, 0x7000, 0x0002, 0x25c9, 0x326f, 0x326f,
+	0x3272, 0x3272, 0x3272, 0x326d, 0x326d, 0x080c, 0x2575, 0x6818,
+	0x0804, 0x2f3b, 0x6008, 0xc0a4, 0x600a, 0x6817, 0x0000, 0x0804,
+	0x3795, 0x2300, 0x0002, 0x327e, 0x3280, 0x32ce, 0x080c, 0x2575,
+	0xd6fc, 0x1904, 0x2d5b, 0x7000, 0xa00d, 0x0002, 0x25c9, 0x3290,
+	0x3290, 0x32ba, 0x3290, 0x32cb, 0x328e, 0x328e, 0x080c, 0x2575,
+	0xa684, 0x0060, 0x0538, 0xa086, 0x0060, 0x1510, 0xc6ac, 0xc6f4,
+	0xc6ed, 0x7e5a, 0x6eb6, 0x681c, 0xc0ac, 0x681e, 0xa186, 0x0002,
+	0x0148, 0x080c, 0x3f4e, 0x69ac, 0x68b0, 0xa115, 0x0118, 0x080c,
+	0x4235, 0x0010, 0x080c, 0x4208, 0x781b, 0x0083, 0x71d0, 0xd1b4,
+	0x1904, 0x25c6, 0x70a0, 0xa086, 0x0001, 0x1904, 0x260d, 0x0005,
+	0xd6ec, 0x09f0, 0x6818, 0xd0fc, 0x0170, 0xd6f4, 0x1130, 0x681b,
+	0x0015, 0x781b, 0x0083, 0x0804, 0x25c6, 0x681b, 0x0007, 0x682f,
+	0x0000, 0x6833, 0x0000, 0x080c, 0x3c17, 0x0005, 0x080c, 0x2575,
+	0x2300, 0x0002, 0x32d7, 0x32f9, 0x3351, 0x080c, 0x2575, 0x7000,
+	0x0002, 0x32e1, 0x32e3, 0x32ea, 0x32e1, 0x32e1, 0x32e1, 0x32e1,
+	0x32e1, 0x080c, 0x2575, 0x69ac, 0x68b0, 0xa115, 0x0118, 0x080c,
+	0x4235, 0x0010, 0x080c, 0x4208, 0x681c, 0xc0b4, 0x681e, 0x70d0,
+	0xd0b4, 0x1904, 0x25c6, 0x70a0, 0xa086, 0x0001, 0x1904, 0x260d,
+	0x0005, 0xd6fc, 0x1904, 0x3341, 0x7000, 0xa00d, 0x0002, 0x25c9,
+	0x330f, 0x3309, 0x3339, 0x330f, 0x333e, 0x3307, 0x3307, 0x080c,
+	0x2575, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0xa684,
+	0x0060, 0x0538, 0xa086, 0x0060, 0x1510, 0xa6b4, 0xbfbf, 0xc6ed,
+	0x7e5a, 0x6eb6, 0xa186, 0x0002, 0x0148, 0x080c, 0x3f4e, 0x69ac,
+	0x68b0, 0xa115, 0x0118, 0x080c, 0x4235, 0x0010, 0x080c, 0x4208,
+	0x781b, 0x0083, 0x681c, 0xc0b4, 0x681e, 0x71d0, 0xd1b4, 0x1904,
+	0x25c6, 0x70a0, 0xa086, 0x0001, 0x1904, 0x260d, 0x0005, 0xd6ec,
+	0x09f0, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x0007, 0x781b, 0x00fb,
+	0x0005, 0xc6fc, 0x7e5a, 0x7adc, 0x79d8, 0x6b98, 0x2100, 0xa302,
+	0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x79d2, 0x781b, 0x0083,
+	0x0005, 0xd6dc, 0x0130, 0x782b, 0x3009, 0x781b, 0x0083, 0x0804,
+	0x25c6, 0x7884, 0xc0ac, 0x7886, 0x78e4, 0xa084, 0x0008, 0x1150,
+	0xa484, 0x0200, 0x0108, 0xc6f5, 0xc6dd, 0x7e5a, 0x781b, 0x0083,
+	0x0804, 0x25c6, 0x6820, 0xc095, 0x6822, 0x080c, 0x3c02, 0xc6dd,
+	0x080c, 0x3a61, 0x781b, 0x0082, 0x0804, 0x25c6, 0x2300, 0x0002,
+	0x337b, 0x337d, 0x337f, 0x080c, 0x2575, 0x0804, 0x3a5b, 0x7d98,
+	0xd6d4, 0x15a8, 0x79e4, 0xd1ac, 0x0130, 0x78ec, 0xa084, 0x0003,
+	0x0110, 0x782b, 0x3009, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684,
+	0xfffb, 0x785a, 0x7d9a, 0x79e4, 0xd1ac, 0x0120, 0x78ec, 0xa084,
+	0x0003, 0x1120, 0x2001, 0x0014, 0x0804, 0x2f3b, 0x7884, 0xd0fc,
+	0x1118, 0xa184, 0x0007, 0x0090, 0xa184, 0x0007, 0xa086, 0x0004,
+	0x1118, 0x2001, 0x0000, 0x0050, 0xa184, 0x0007, 0xa086, 0x0005,
+	0x0118, 0xa184, 0x0007, 0x0010, 0x2001, 0x0001, 0x04c2, 0x7a90,
+	0xa294, 0x0007, 0x789b, 0x0060, 0x79a8, 0x81ff, 0x0568, 0x789b,
+	0x0080, 0x7ba8, 0xa384, 0x0001, 0x11d0, 0x7ba8, 0x7ba8, 0xa386,
+	0x0004, 0x1118, 0x2009, 0xffdf, 0x0058, 0xa386, 0x0001, 0x1118,
+	0x2009, 0xfff7, 0x0028, 0xa386, 0x0003, 0x1148, 0x2009, 0xffef,
+	0x00c6, 0x7054, 0x2060, 0x6004, 0xa104, 0x6006, 0x00ce, 0x789b,
+	0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, 0x782b, 0x3009,
+	0x6920, 0xa18c, 0xecff, 0x6922, 0x7d9a, 0x0804, 0x3c0b, 0x2bd1,
+	0x2bda, 0x33f9, 0x33ff, 0x33f7, 0x33f7, 0x3c0b, 0x3c0b, 0x080c,
+	0x2575, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0804, 0x3c11, 0x6920,
+	0xa18c, 0xfcff, 0x6922, 0x0804, 0x3c0b, 0x79e4, 0xa184, 0x0030,
+	0x0120, 0x78ec, 0xa084, 0x0003, 0x1570, 0x7000, 0xa086, 0x0004,
+	0x1190, 0x7060, 0xa086, 0x0002, 0x1130, 0x2011, 0x0002, 0x2019,
+	0x0000, 0x0804, 0x2a85, 0x7060, 0xa086, 0x0006, 0x0db0, 0x7060,
+	0xa086, 0x0004, 0x0d90, 0x7000, 0xa086, 0x0000, 0x0904, 0x25c6,
+	0x6920, 0xa184, 0x0420, 0x0128, 0xc1d4, 0x6922, 0x6818, 0x0804,
+	0x2f3b, 0x6818, 0xa08e, 0x0002, 0x0120, 0xc0fd, 0x681a, 0x2001,
+	0x0014, 0x0804, 0x2f3b, 0x7884, 0xd0fc, 0x1118, 0xa184, 0x0007,
 	0x0090, 0xa184, 0x0007, 0xa086, 0x0004, 0x1118, 0x2001, 0x0000,
 	0x0050, 0xa184, 0x0007, 0xa086, 0x0005, 0x0118, 0xa184, 0x0007,
-	0x0010, 0x2001, 0x0001, 0x04c2, 0x7a90, 0xa294, 0x0007, 0x789b,
-	0x0060, 0x79a8, 0x81ff, 0x0568, 0x789b, 0x0080, 0x7ba8, 0xa384,
-	0x0001, 0x11d0, 0x7ba8, 0x7ba8, 0xa386, 0x0004, 0x1118, 0x2009,
-	0xffdf, 0x0058, 0xa386, 0x0001, 0x1118, 0x2009, 0xfff7, 0x0028,
-	0xa386, 0x0003, 0x1148, 0x2009, 0xffef, 0x00c6, 0x7054, 0x2060,
-	0x6004, 0xa104, 0x6006, 0x00ce, 0x789b, 0x0060, 0x78ab, 0x0000,
-	0xa684, 0xfffb, 0x785a, 0x782b, 0x3009, 0x6920, 0xa18c, 0xecff,
-	0x6922, 0x7d9a, 0x0804, 0x3be5, 0x2bae, 0x2bb7, 0x33d6, 0x33dc,
-	0x33d4, 0x33d4, 0x3be5, 0x3be5, 0x080c, 0x254c, 0x6920, 0xa18c,
-	0xfcff, 0x6922, 0x0804, 0x3beb, 0x6920, 0xa18c, 0xfcff, 0x6922,
-	0x0804, 0x3be5, 0x79e4, 0xa184, 0x0030, 0x0120, 0x78ec, 0xa084,
-	0x0003, 0x1570, 0x7000, 0xa086, 0x0004, 0x1190, 0x7060, 0xa086,
-	0x0002, 0x1130, 0x2011, 0x0002, 0x2019, 0x0000, 0x0804, 0x2a56,
-	0x7060, 0xa086, 0x0006, 0x0db0, 0x7060, 0xa086, 0x0004, 0x0d90,
-	0x7000, 0xa086, 0x0000, 0x0904, 0x259d, 0x6920, 0xa184, 0x0420,
-	0x0128, 0xc1d4, 0x6922, 0x6818, 0x0804, 0x2f18, 0x6818, 0xa08e,
-	0x0002, 0x0120, 0xc0fd, 0x681a, 0x2001, 0x0014, 0x0804, 0x2f18,
-	0x7884, 0xd0fc, 0x1118, 0xa184, 0x0007, 0x0090, 0xa184, 0x0007,
-	0xa086, 0x0004, 0x1118, 0x2001, 0x0000, 0x0050, 0xa184, 0x0007,
-	0xa086, 0x0005, 0x0118, 0xa184, 0x0007, 0x0010, 0x2001, 0x0001,
-	0x0002, 0x3be5, 0x3be5, 0x3439, 0x3be5, 0x3c29, 0x3c29, 0x3be5,
-	0x3be5, 0xd6bc, 0x0570, 0x7180, 0x81ff, 0x0558, 0xa182, 0x000d,
-	0x1318, 0x7083, 0x0000, 0x0028, 0xa182, 0x000c, 0x7082, 0x2009,
-	0x000c, 0x789b, 0x0061, 0x79aa, 0x0156, 0x0136, 0x0146, 0x7084,
-	0x8114, 0xa210, 0x7286, 0xa080, 0x000b, 0xad00, 0x2098, 0xb284,
-	0x0600, 0x0118, 0x20a1, 0x022b, 0x0010, 0x20a1, 0x012b, 0x789b,
-	0x0000, 0x8108, 0x81ac, 0x53a6, 0x014e, 0x013e, 0x015e, 0x0804,
-	0x3beb, 0xd6d4, 0x1904, 0x34ac, 0x6820, 0xd084, 0x0904, 0x3beb,
-	0xa68c, 0x0060, 0xa684, 0x0060, 0x0120, 0xa086, 0x0060, 0x1108,
-	0xc1f5, 0xc194, 0x795a, 0x69b6, 0x789b, 0x0060, 0x78ab, 0x0000,
-	0x789b, 0x0061, 0x6818, 0xc0fd, 0x681a, 0x78aa, 0x8008, 0x810c,
-	0x0904, 0x37d3, 0xa18c, 0x00f8, 0x1904, 0x37d3, 0x0156, 0x0136,
-	0x0146, 0x0016, 0x20a1, 0x012b, 0x3208, 0xa18c, 0x0600, 0x0110,
-	0x20a1, 0x022b, 0x001e, 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80,
-	0x000b, 0x2098, 0x53a6, 0x014e, 0x013e, 0x015e, 0x6814, 0xc0fc,
-	0x8007, 0x7882, 0x0804, 0x3beb, 0x6818, 0xd0fc, 0x0110, 0x681b,
-	0x0008, 0x080c, 0x3a3c, 0x781b, 0x00ed, 0x0005, 0x2300, 0x0002,
-	0x34bd, 0x357a, 0x34bb, 0x080c, 0x254c, 0x7cd8, 0x7ddc, 0x7fd0,
-	0x82ff, 0x1528, 0x7200, 0xa286, 0x0003, 0x0904, 0x2ee6, 0x71d0,
-	0xd1bc, 0x11f8, 0xd1b4, 0x01e8, 0x2001, 0x4601, 0x2004, 0xd0c4,
-	0x11c0, 0x00d6, 0x783b, 0x8800, 0x781b, 0x0059, 0x70b8, 0xa06d,
-	0x68b4, 0xc0a5, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2,
-	0x78da, 0xc1b4, 0x71d2, 0x7003, 0x0030, 0x00de, 0x0030, 0x7200,
-	0x0020, 0x783b, 0x1800, 0x781b, 0x0057, 0xa284, 0x000f, 0x0002,
-	0x3565, 0x3522, 0x34fa, 0x2f15, 0x34f8, 0x3565, 0x34f8, 0x34f8,
-	0x080c, 0x254c, 0x681c, 0xd0ec, 0x0118, 0x6008, 0xc08d, 0x600a,
-	0x6920, 0xc185, 0x6922, 0x6800, 0x6006, 0xa005, 0x1108, 0x6002,
-	0x6008, 0xc0d4, 0x600a, 0x681c, 0xa084, 0x000e, 0x1120, 0x71c8,
-	0xa188, 0x0100, 0x0028, 0x7030, 0x68ba, 0x713c, 0x70c8, 0xa108,
-	0x2104, 0x6802, 0x2d0a, 0x715a, 0xd6dc, 0x1120, 0xc6fc, 0x6eb6,
-	0x0804, 0x3565, 0x6eb6, 0xa684, 0x0060, 0x1120, 0xa684, 0x7fff,
-	0x68b6, 0x04d8, 0xd6dc, 0x1150, 0xa684, 0x7fff, 0x68b6, 0x6894,
-	0x68a6, 0x6898, 0x68aa, 0x080c, 0x3f26, 0x0478, 0xd6ac, 0x0140,
-	0xa006, 0x080c, 0x3f26, 0x2408, 0x2510, 0x69aa, 0x6aa6, 0x0068,
-	0x2408, 0x2510, 0x2700, 0x8007, 0xa084, 0x007f, 0xa108, 0xa291,
-	0x0000, 0x69aa, 0x6aa6, 0x080c, 0x3f26, 0xd6fc, 0x01b0, 0xa684,
-	0x7fff, 0x68b6, 0x2510, 0x2408, 0xd6ac, 0x1138, 0x2700, 0x8007,
-	0xa084, 0x007f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302,
-	0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x7000, 0xa086, 0x0030,
-	0x1904, 0x25a0, 0x7003, 0x0002, 0x70b8, 0xa06d, 0x68bc, 0x703e,
-	0x70b4, 0xa065, 0x68c0, 0x7056, 0x2d00, 0x704a, 0xad80, 0x0009,
-	0x7042, 0x0005, 0xa586, 0x8800, 0x1148, 0x7003, 0x0000, 0x6018,
-	0x8001, 0x601a, 0x6008, 0xa084, 0xfbef, 0x600a, 0x0804, 0x3a36,
-	0x7043, 0x0000, 0xa282, 0x0006, 0x0310, 0x080c, 0x254c, 0x2300,
-	0x0002, 0x3594, 0x35a5, 0x35af, 0x2200, 0x0002, 0x359c, 0x3a36,
-	0x359e, 0x359c, 0x35e0, 0x362e, 0x080c, 0x254c, 0x7a80, 0xa294,
-	0x0f00, 0x080c, 0x3682, 0x0804, 0x3a0b, 0x00c1, 0x0002, 0x3a36,
-	0x35ad, 0x35ad, 0x35e0, 0x35ad, 0x3a36, 0x080c, 0x254c, 0x0071,
-	0x0002, 0x35b9, 0x35b7, 0x35b7, 0x35b9, 0x35b7, 0x35b9, 0x080c,
-	0x254c, 0x080c, 0x3a4b, 0x781b, 0x0082, 0x0005, 0x7000, 0xa086,
-	0x0002, 0x1150, 0x080c, 0x37be, 0x0010, 0x080c, 0x3f26, 0x6008,
-	0xa084, 0xfbef, 0x600a, 0x0020, 0x7000, 0xa086, 0x0003, 0x0da8,
-	0x7003, 0x0005, 0x2001, 0x8de0, 0xae8e, 0x4640, 0x0110, 0x2001,
-	0x8e12, 0x2068, 0x704a, 0xad80, 0x0009, 0x7042, 0x2200, 0x0005,
-	0x7000, 0xa086, 0x0002, 0x1158, 0x70d0, 0xc0b5, 0x70d2, 0x2c00,
-	0x70b6, 0x2d00, 0x70ba, 0x0038, 0x080c, 0x3f26, 0x0020, 0x7000,
-	0xa086, 0x0003, 0x0dc8, 0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00,
-	0x789b, 0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215, 0x2069, 0x8cc0,
-	0xb284, 0x0600, 0x1118, 0xc2fd, 0x2069, 0x8dd0, 0x2d04, 0x2d08,
-	0x715a, 0xa06d, 0x0128, 0x6814, 0xa206, 0x0120, 0x6800, 0x0cb8,
-	0x080c, 0x3682, 0x6eb4, 0x7e5a, 0x6920, 0xa184, 0x0c00, 0x0904,
-	0x36a8, 0x7060, 0xa086, 0x0006, 0x1128, 0x7070, 0xa206, 0x1110,
-	0x7062, 0x707a, 0x681b, 0x0005, 0xc1ad, 0x681b, 0x0005, 0xc1ad,
-	0xc1d4, 0x6922, 0x080c, 0x3a42, 0x0804, 0x36a8, 0x7200, 0xa286,
-	0x0002, 0x1158, 0x70d0, 0xc0b5, 0x70d2, 0x2c00, 0x70b6, 0x2d00,
-	0x70ba, 0x0030, 0x080c, 0x3f26, 0x0018, 0xa286, 0x0003, 0x0dd0,
-	0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8,
-	0xa484, 0x001f, 0xa215, 0xae86, 0x4640, 0x0108, 0xc2fd, 0x79a8,
-	0x79a8, 0xa18c, 0x00ff, 0x2118, 0x70c8, 0xa168, 0x2d04, 0x2d08,
-	0x715a, 0xa06d, 0x0128, 0x6814, 0xa206, 0x0118, 0x6800, 0x0cb8,
-	0x0409, 0x6eb4, 0x6920, 0xa184, 0x0c00, 0x0904, 0x36a8, 0xd0dc,
-	0x0178, 0x7060, 0xa086, 0x0004, 0x1140, 0x7070, 0xa206, 0x1128,
-	0x7074, 0xa306, 0x1110, 0x7062, 0x707a, 0x080c, 0x3a48, 0x0480,
-	0x681b, 0x0005, 0xc1ad, 0xc1d4, 0x6922, 0x080c, 0x3a42, 0x707b,
-	0x0000, 0x0430, 0x7003, 0x0005, 0xb284, 0x0600, 0x0118, 0x2001,
-	0x8de0, 0x0010, 0x2001, 0x8e12, 0x2068, 0x704a, 0x0156, 0x20a9,
-	0x0032, 0x2003, 0x0000, 0x8000, 0x1f04, 0x3691, 0x015e, 0xb284,
-	0x0600, 0x0110, 0xc2fc, 0x0008, 0xc2fd, 0x6a16, 0xad80, 0x0009,
-	0x7042, 0x68b7, 0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x0005,
-	0xc6ec, 0xa6ac, 0x0060, 0x0904, 0x36ef, 0x6b98, 0x6c94, 0x69ac,
-	0x68b0, 0xa105, 0x11e0, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0xa586,
-	0x0060, 0x05c8, 0xd6f4, 0x1108, 0xc6ed, 0xa6b4, 0xb7ff, 0x7e5a,
-	0x2009, 0x0083, 0xd69c, 0x0128, 0x2009, 0x0082, 0x2019, 0x0000,
-	0x2320, 0x791a, 0xd6ec, 0x0588, 0x080c, 0x41d9, 0x0470, 0x68b0,
-	0xa31a, 0x2100, 0xa423, 0x2400, 0xa305, 0x01f8, 0x7bd2, 0x7bda,
-	0x7cd6, 0x7cde, 0x68b0, 0xd6f4, 0x1108, 0xc6ed, 0xc6f4, 0x7e5a,
-	0x2011, 0x0083, 0xd69c, 0x0128, 0x2011, 0x0082, 0x2019, 0x0000,
-	0x2320, 0x7a1a, 0xd6ec, 0x0188, 0x080c, 0x4206, 0x0070, 0x2019,
-	0x0000, 0x2320, 0x0010, 0xa6b4, 0xb7ff, 0x7e5a, 0x2009, 0x0083,
-	0xd69c, 0x0110, 0x2009, 0x0082, 0x791a, 0x68c0, 0x7056, 0x2d00,
-	0x704a, 0x68c4, 0x2060, 0x71d0, 0x2001, 0x4601, 0x2004, 0xd0c4,
-	0x15c8, 0x70d4, 0xa02d, 0x01b8, 0xd1bc, 0x0548, 0x7a80, 0xa294,
-	0x0f00, 0x70d8, 0xa206, 0x0118, 0x78e0, 0xa504, 0x1558, 0x70d6,
-	0xc1bc, 0x71d2, 0x0438, 0x2031, 0x0001, 0x852c, 0x0218, 0x8633,
-	0x8210, 0x0cd8, 0x0005, 0x7de0, 0xa594, 0xff00, 0x0130, 0x2011,
-	0x0008, 0x852f, 0x0c81, 0x8637, 0x0008, 0x0c69, 0x8217, 0x7880,
-	0xa084, 0x0f00, 0xa206, 0x0170, 0x72da, 0x76d6, 0x0058, 0x7a80,
-	0xa294, 0x0f00, 0x70d8, 0xa236, 0x0dc0, 0x78e0, 0xa534, 0x0da8,
-	0xc1bd, 0x71d2, 0xd1b4, 0x1904, 0x259d, 0x2300, 0xa405, 0x0904,
-	0x259d, 0x70a0, 0xa086, 0x0001, 0x1904, 0x25e1, 0x0005, 0x6020,
-	0xa005, 0x0150, 0x8001, 0x6022, 0x6008, 0xa085, 0x0008, 0x600a,
-	0x700f, 0x0100, 0x702c, 0x6026, 0x0005, 0xa006, 0x080c, 0x3f26,
-	0x7000, 0xa086, 0x0002, 0x0120, 0x7060, 0xa086, 0x0005, 0x1150,
-	0x682b, 0x0000, 0x6817, 0x0000, 0x681b, 0x0001, 0x6823, 0x0040,
-	0x681f, 0x0100, 0x7000, 0xa084, 0x000f, 0x0002, 0x25a0, 0x3783,
-	0x3780, 0x37a0, 0x378c, 0x25a0, 0x377e, 0x377e, 0x080c, 0x254c,
-	0x0449, 0x0411, 0x0028, 0x0431, 0x7058, 0x2060, 0x6800, 0x6002,
-	0x080c, 0x1da2, 0x0804, 0x25a0, 0x7060, 0x7063, 0x0000, 0x707f,
-	0x0000, 0x0002, 0x379c, 0x379c, 0x379a, 0x379a, 0x379a, 0x379c,
-	0x379a, 0x379c, 0x0804, 0x2a6b, 0x7063, 0x0000, 0x0804, 0x25a0,
-	0x681b, 0x0000, 0x0804, 0x3184, 0x6800, 0xa005, 0x1108, 0x6002,
-	0x6006, 0x0005, 0x6410, 0x84ff, 0x0168, 0x2009, 0x4602, 0x2104,
-	0x8001, 0x200a, 0x8421, 0x6412, 0x1128, 0x2021, 0x4604, 0x2404,
-	0xc0a5, 0x2022, 0x6008, 0xc0a4, 0x600a, 0x0005, 0x6018, 0xa005,
-	0x0110, 0x8001, 0x601a, 0x0005, 0x080c, 0x3c46, 0x681b, 0x0018,
-	0x0490, 0x080c, 0x3c46, 0x681b, 0x0019, 0x0468, 0x080c, 0x3c46,
-	0x681b, 0x001a, 0x0440, 0x080c, 0x3c46, 0x681b, 0x0003, 0x0418,
-	0x7770, 0x080c, 0x3b6f, 0x7174, 0xa18c, 0x00ff, 0x3210, 0xa294,
-	0x0600, 0x0118, 0xa1e8, 0x8bc0, 0x0010, 0xa1e8, 0x8cd0, 0x2d04,
-	0x2d08, 0x2068, 0xa005, 0x1118, 0x707a, 0x0804, 0x25a0, 0x6814,
-	0x7270, 0xa206, 0x0110, 0x6800, 0x0c98, 0x6800, 0x200a, 0x681b,
-	0x0005, 0x707b, 0x0000, 0x080c, 0x37aa, 0x6820, 0xd084, 0x1110,
-	0x080c, 0x37a4, 0x080c, 0x37be, 0x681f, 0x0000, 0x6823, 0x0020,
-	0x080c, 0x1da2, 0x0804, 0x25a0, 0xa282, 0x0003, 0x1904, 0x3a10,
-	0x7da8, 0xa5ac, 0x00ff, 0x7ea8, 0xa6b4, 0x00ff, 0x6920, 0xc1bd,
-	0x6922, 0xd1c4, 0x05b0, 0xc1c4, 0x6922, 0xa6b4, 0x00ff, 0x0530,
-	0xa682, 0x0018, 0x0218, 0x0110, 0x2031, 0x0018, 0xa686, 0x0010,
-	0x1108, 0x8630, 0x852b, 0x852b, 0x2041, 0x0000, 0x080c, 0x3ac9,
-	0x0118, 0x080c, 0x38f7, 0x00a0, 0x080c, 0x3a95, 0x080c, 0x38f4,
-	0x6920, 0xc1c5, 0x6922, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x1118,
-	0x781b, 0x006e, 0x0005, 0x781b, 0x0082, 0x0005, 0x080c, 0x38f4,
+	0x0010, 0x2001, 0x0001, 0x0002, 0x3c0b, 0x3c0b, 0x345c, 0x3c0b,
+	0x3c4f, 0x3c4f, 0x3c0b, 0x3c0b, 0xd6bc, 0x0570, 0x7180, 0x81ff,
+	0x0558, 0xa182, 0x000d, 0x1318, 0x7083, 0x0000, 0x0028, 0xa182,
+	0x000c, 0x7082, 0x2009, 0x000c, 0x789b, 0x0061, 0x79aa, 0x0156,
+	0x0136, 0x0146, 0x7084, 0x8114, 0xa210, 0x7286, 0xa080, 0x000b,
+	0xad00, 0x2098, 0xb284, 0x0600, 0x0118, 0x20a1, 0x022b, 0x0010,
+	0x20a1, 0x012b, 0x789b, 0x0000, 0x8108, 0x81ac, 0x53a6, 0x014e,
+	0x013e, 0x015e, 0x0804, 0x3c11, 0xd6d4, 0x1904, 0x34cf, 0x6820,
+	0xd084, 0x0904, 0x3c11, 0xa68c, 0x0060, 0xa684, 0x0060, 0x0120,
+	0xa086, 0x0060, 0x1108, 0xc1f5, 0xc194, 0x795a, 0x69b6, 0x789b,
+	0x0060, 0x78ab, 0x0000, 0x789b, 0x0061, 0x6818, 0xc0fd, 0x681a,
+	0x78aa, 0x8008, 0x810c, 0x0904, 0x37f6, 0xa18c, 0x00f8, 0x1904,
+	0x37f6, 0x0156, 0x0136, 0x0146, 0x0016, 0x20a1, 0x012b, 0x3208,
+	0xa18c, 0x0600, 0x0110, 0x20a1, 0x022b, 0x001e, 0x789b, 0x0000,
+	0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x014e, 0x013e,
+	0x015e, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x0804, 0x3c11, 0x6818,
+	0xd0fc, 0x0110, 0x681b, 0x0008, 0x080c, 0x3a61, 0x781b, 0x00ed,
+	0x0005, 0x2300, 0x0002, 0x34e0, 0x359d, 0x34de, 0x080c, 0x2575,
+	0x7cd8, 0x7ddc, 0x7fd0, 0x82ff, 0x1528, 0x7200, 0xa286, 0x0003,
+	0x0904, 0x2f09, 0x71d0, 0xd1bc, 0x11f8, 0xd1b4, 0x01e8, 0x2001,
+	0x4701, 0x2004, 0xd0c4, 0x11c0, 0x00d6, 0x783b, 0x8800, 0x781b,
+	0x0059, 0x70b8, 0xa06d, 0x68b4, 0xc0a5, 0x785a, 0x6894, 0x78d6,
+	0x78de, 0x6898, 0x78d2, 0x78da, 0xc1b4, 0x71d2, 0x7003, 0x0030,
+	0x00de, 0x0030, 0x7200, 0x0020, 0x783b, 0x1800, 0x781b, 0x0057,
+	0xa284, 0x000f, 0x0002, 0x3588, 0x3545, 0x351d, 0x2f38, 0x351b,
+	0x3588, 0x351b, 0x351b, 0x080c, 0x2575, 0x681c, 0xd0ec, 0x0118,
+	0x6008, 0xc08d, 0x600a, 0x6920, 0xc185, 0x6922, 0x6800, 0x6006,
+	0xa005, 0x1108, 0x6002, 0x6008, 0xc0d4, 0x600a, 0x681c, 0xa084,
+	0x000e, 0x1120, 0x71c8, 0xa188, 0x0100, 0x0028, 0x7030, 0x68ba,
+	0x713c, 0x70c8, 0xa108, 0x2104, 0x6802, 0x2d0a, 0x715a, 0xd6dc,
+	0x1120, 0xc6fc, 0x6eb6, 0x0804, 0x3588, 0x6eb6, 0xa684, 0x0060,
+	0x1120, 0xa684, 0x7fff, 0x68b6, 0x04d8, 0xd6dc, 0x1150, 0xa684,
+	0x7fff, 0x68b6, 0x6894, 0x68a6, 0x6898, 0x68aa, 0x080c, 0x3f4e,
+	0x0478, 0xd6ac, 0x0140, 0xa006, 0x080c, 0x3f4e, 0x2408, 0x2510,
+	0x69aa, 0x6aa6, 0x0068, 0x2408, 0x2510, 0x2700, 0x8007, 0xa084,
+	0x007f, 0xa108, 0xa291, 0x0000, 0x69aa, 0x6aa6, 0x080c, 0x3f4e,
+	0xd6fc, 0x01b0, 0xa684, 0x7fff, 0x68b6, 0x2510, 0x2408, 0xd6ac,
+	0x1138, 0x2700, 0x8007, 0xa084, 0x007f, 0xa108, 0xa291, 0x0000,
+	0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae,
+	0x7000, 0xa086, 0x0030, 0x1904, 0x25c9, 0x7003, 0x0002, 0x70b8,
+	0xa06d, 0x68bc, 0x703e, 0x70b4, 0xa065, 0x68c0, 0x7056, 0x2d00,
+	0x704a, 0xad80, 0x0009, 0x7042, 0x0005, 0xa586, 0x8800, 0x1148,
+	0x7003, 0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084, 0xfbef,
+	0x600a, 0x0804, 0x3a5b, 0x7043, 0x0000, 0xa282, 0x0006, 0x0310,
+	0x080c, 0x2575, 0x2300, 0x0002, 0x35b7, 0x35c8, 0x35d2, 0x2200,
+	0x0002, 0x35bf, 0x3a5b, 0x35c1, 0x35bf, 0x3603, 0x3651, 0x080c,
+	0x2575, 0x7a80, 0xa294, 0x0f00, 0x080c, 0x36a5, 0x0804, 0x3a30,
+	0x00c1, 0x0002, 0x3a5b, 0x35d0, 0x35d0, 0x3603, 0x35d0, 0x3a5b,
+	0x080c, 0x2575, 0x0071, 0x0002, 0x35dc, 0x35da, 0x35da, 0x35dc,
+	0x35da, 0x35dc, 0x080c, 0x2575, 0x080c, 0x3a70, 0x781b, 0x0082,
+	0x0005, 0x7000, 0xa086, 0x0002, 0x1150, 0x080c, 0x37e1, 0x0010,
+	0x080c, 0x3f4e, 0x6008, 0xa084, 0xfbef, 0x600a, 0x0020, 0x7000,
+	0xa086, 0x0003, 0x0da8, 0x7003, 0x0005, 0x2001, 0x8ee0, 0xae8e,
+	0x4740, 0x0110, 0x2001, 0x8f12, 0x2068, 0x704a, 0xad80, 0x0009,
+	0x7042, 0x2200, 0x0005, 0x7000, 0xa086, 0x0002, 0x1158, 0x70d0,
+	0xc0b5, 0x70d2, 0x2c00, 0x70b6, 0x2d00, 0x70ba, 0x0038, 0x080c,
+	0x3f4e, 0x0020, 0x7000, 0xa086, 0x0003, 0x0dc8, 0x7003, 0x0001,
+	0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x001f,
+	0xa215, 0x2069, 0x8dc0, 0xb284, 0x0600, 0x1118, 0xc2fd, 0x2069,
+	0x8ed0, 0x2d04, 0x2d08, 0x715a, 0xa06d, 0x0128, 0x6814, 0xa206,
+	0x0120, 0x6800, 0x0cb8, 0x080c, 0x36a5, 0x6eb4, 0x7e5a, 0x6920,
+	0xa184, 0x0c00, 0x0904, 0x36cb, 0x7060, 0xa086, 0x0006, 0x1128,
+	0x7070, 0xa206, 0x1110, 0x7062, 0x707a, 0x681b, 0x0005, 0xc1ad,
+	0x681b, 0x0005, 0xc1ad, 0xc1d4, 0x6922, 0x080c, 0x3a67, 0x0804,
+	0x36cb, 0x7200, 0xa286, 0x0002, 0x1158, 0x70d0, 0xc0b5, 0x70d2,
+	0x2c00, 0x70b6, 0x2d00, 0x70ba, 0x0030, 0x080c, 0x3f4e, 0x0018,
+	0xa286, 0x0003, 0x0dd0, 0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00,
+	0x789b, 0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215, 0xae86, 0x4740,
+	0x0108, 0xc2fd, 0x79a8, 0x79a8, 0xa18c, 0x00ff, 0x2118, 0x70c8,
+	0xa168, 0x2d04, 0x2d08, 0x715a, 0xa06d, 0x0128, 0x6814, 0xa206,
+	0x0118, 0x6800, 0x0cb8, 0x0409, 0x6eb4, 0x6920, 0xa184, 0x0c00,
+	0x0904, 0x36cb, 0xd0dc, 0x0178, 0x7060, 0xa086, 0x0004, 0x1140,
+	0x7070, 0xa206, 0x1128, 0x7074, 0xa306, 0x1110, 0x7062, 0x707a,
+	0x080c, 0x3a6d, 0x0480, 0x681b, 0x0005, 0xc1ad, 0xc1d4, 0x6922,
+	0x080c, 0x3a67, 0x707b, 0x0000, 0x0430, 0x7003, 0x0005, 0xb284,
+	0x0600, 0x0118, 0x2001, 0x8ee0, 0x0010, 0x2001, 0x8f12, 0x2068,
+	0x704a, 0x0156, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x1f04,
+	0x36b4, 0x015e, 0xb284, 0x0600, 0x0110, 0xc2fc, 0x0008, 0xc2fd,
+	0x6a16, 0xad80, 0x0009, 0x7042, 0x68b7, 0x0700, 0x6823, 0x0800,
+	0x6827, 0x0003, 0x0005, 0xc6ec, 0xa6ac, 0x0060, 0x0904, 0x3712,
+	0x6b98, 0x6c94, 0x69ac, 0x68b0, 0xa105, 0x11e0, 0x7bd2, 0x7bda,
+	0x7cd6, 0x7cde, 0xa586, 0x0060, 0x05c8, 0xd6f4, 0x1108, 0xc6ed,
+	0xa6b4, 0xb7ff, 0x7e5a, 0x2009, 0x0083, 0xd69c, 0x0128, 0x2009,
+	0x0082, 0x2019, 0x0000, 0x2320, 0x791a, 0xd6ec, 0x0588, 0x080c,
+	0x4208, 0x0470, 0x68b0, 0xa31a, 0x2100, 0xa423, 0x2400, 0xa305,
+	0x01f8, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0x68b0, 0xd6f4, 0x1108,
+	0xc6ed, 0xc6f4, 0x7e5a, 0x2011, 0x0083, 0xd69c, 0x0128, 0x2011,
+	0x0082, 0x2019, 0x0000, 0x2320, 0x7a1a, 0xd6ec, 0x0188, 0x080c,
+	0x4235, 0x0070, 0x2019, 0x0000, 0x2320, 0x0010, 0xa6b4, 0xb7ff,
+	0x7e5a, 0x2009, 0x0083, 0xd69c, 0x0110, 0x2009, 0x0082, 0x791a,
+	0x68c0, 0x7056, 0x2d00, 0x704a, 0x68c4, 0x2060, 0x71d0, 0x2001,
+	0x4701, 0x2004, 0xd0c4, 0x15c8, 0x70d4, 0xa02d, 0x01b8, 0xd1bc,
+	0x0548, 0x7a80, 0xa294, 0x0f00, 0x70d8, 0xa206, 0x0118, 0x78e0,
+	0xa504, 0x1558, 0x70d6, 0xc1bc, 0x71d2, 0x0438, 0x2031, 0x0001,
+	0x852c, 0x0218, 0x8633, 0x8210, 0x0cd8, 0x0005, 0x7de0, 0xa594,
+	0xff00, 0x0130, 0x2011, 0x0008, 0x852f, 0x0c81, 0x8637, 0x0008,
+	0x0c69, 0x8217, 0x7880, 0xa084, 0x0f00, 0xa206, 0x0170, 0x72da,
+	0x76d6, 0x0058, 0x7a80, 0xa294, 0x0f00, 0x70d8, 0xa236, 0x0dc0,
+	0x78e0, 0xa534, 0x0da8, 0xc1bd, 0x71d2, 0xd1b4, 0x1904, 0x25c6,
+	0x2300, 0xa405, 0x0904, 0x25c6, 0x70a0, 0xa086, 0x0001, 0x1904,
+	0x260d, 0x0005, 0x6020, 0xa005, 0x0150, 0x8001, 0x6022, 0x6008,
+	0xa085, 0x0008, 0x600a, 0x700f, 0x0100, 0x702c, 0x6026, 0x0005,
+	0xa006, 0x080c, 0x3f4e, 0x7000, 0xa086, 0x0002, 0x0120, 0x7060,
+	0xa086, 0x0005, 0x1150, 0x682b, 0x0000, 0x6817, 0x0000, 0x681b,
+	0x0001, 0x6823, 0x0040, 0x681f, 0x0100, 0x7000, 0xa084, 0x000f,
+	0x0002, 0x25c9, 0x37a6, 0x37a3, 0x37c3, 0x37af, 0x25c9, 0x37a1,
+	0x37a1, 0x080c, 0x2575, 0x0449, 0x0411, 0x0028, 0x0431, 0x7058,
+	0x2060, 0x6800, 0x6002, 0x080c, 0x1dbf, 0x0804, 0x25c9, 0x7060,
+	0x7063, 0x0000, 0x707f, 0x0000, 0x0002, 0x37bf, 0x37bf, 0x37bd,
+	0x37bd, 0x37bd, 0x37bf, 0x37bd, 0x37bf, 0x0804, 0x2a9a, 0x7063,
+	0x0000, 0x0804, 0x25c9, 0x681b, 0x0000, 0x0804, 0x31a7, 0x6800,
+	0xa005, 0x1108, 0x6002, 0x6006, 0x0005, 0x6410, 0x84ff, 0x0168,
+	0x2009, 0x4702, 0x2104, 0x8001, 0x200a, 0x8421, 0x6412, 0x1128,
+	0x2021, 0x4704, 0x2404, 0xc0a5, 0x2022, 0x6008, 0xc0a4, 0x600a,
+	0x0005, 0x6018, 0xa005, 0x0110, 0x8001, 0x601a, 0x0005, 0x080c,
+	0x3c6e, 0x681b, 0x0018, 0x0490, 0x080c, 0x3c6e, 0x681b, 0x0019,
+	0x0468, 0x080c, 0x3c6e, 0x681b, 0x001a, 0x0440, 0x080c, 0x3c6e,
+	0x681b, 0x0003, 0x0418, 0x7770, 0x080c, 0x3b95, 0x7174, 0xa18c,
+	0x00ff, 0x3210, 0xa294, 0x0600, 0x0118, 0xa1e8, 0x8cc0, 0x0010,
+	0xa1e8, 0x8dd0, 0x2d04, 0x2d08, 0x2068, 0xa005, 0x1118, 0x707a,
+	0x0804, 0x25c9, 0x6814, 0x7270, 0xa206, 0x0110, 0x6800, 0x0c98,
+	0x6800, 0x200a, 0x681b, 0x0005, 0x707b, 0x0000, 0x080c, 0x37cd,
+	0x6820, 0xd084, 0x1110, 0x080c, 0x37c7, 0x080c, 0x37e1, 0x681f,
+	0x0000, 0x6823, 0x0020, 0x080c, 0x1dbf, 0x0804, 0x25c9, 0xa282,
+	0x0003, 0x1904, 0x3a35, 0x7da8, 0xa5ac, 0x00ff, 0x7ea8, 0xa6b4,
+	0x00ff, 0x6920, 0xc1bd, 0x6922, 0xd1c4, 0x05b0, 0xc1c4, 0x6922,
+	0xa6b4, 0x00ff, 0x0530, 0xa682, 0x0018, 0x0218, 0x0110, 0x2031,
+	0x0018, 0xa686, 0x0010, 0x1108, 0x8630, 0x852b, 0x852b, 0x2041,
+	0x0000, 0x080c, 0x3aee, 0x0118, 0x080c, 0x391a, 0x00a0, 0x080c,
+	0x3aba, 0x080c, 0x3917, 0x6920, 0xc1c5, 0x6922, 0x7e58, 0xc695,
+	0x7e5a, 0xd6d4, 0x1118, 0x781b, 0x006e, 0x0005, 0x781b, 0x0082,
+	0x0005, 0x080c, 0x3917, 0x7e58, 0xd6d4, 0x1118, 0x781b, 0x0071,
+	0x0005, 0x781b, 0x0083, 0x0005, 0x00c6, 0x7054, 0x2060, 0x6100,
+	0xd1e4, 0x0598, 0x6208, 0x8217, 0xa294, 0x00ff, 0xa282, 0x0018,
+	0x0218, 0x0110, 0x2011, 0x0018, 0x2600, 0xa202, 0x1208, 0x2230,
+	0xa686, 0x0010, 0x1108, 0x8630, 0x6208, 0xa294, 0x00ff, 0x78ec,
+	0xd0e4, 0x0130, 0xa282, 0x000a, 0x1240, 0x2011, 0x000a, 0x0028,
+	0xa282, 0x000c, 0x1210, 0x2011, 0x000c, 0x2200, 0xa502, 0x1208,
+	0x2228, 0x080c, 0x3abe, 0x852b, 0x852b, 0x2041, 0x0000, 0x080c,
+	0x3aee, 0x0118, 0x080c, 0x391a, 0x0020, 0x080c, 0x3aba, 0x080c,
+	0x3917, 0x7858, 0xc095, 0x785a, 0x00ce, 0x781b, 0x0082, 0x0005,
+	0x00c6, 0x2960, 0x6000, 0xd0e4, 0x1188, 0xd0b4, 0x1150, 0x6010,
+	0xa084, 0x000f, 0x1130, 0x6104, 0xa18c, 0xfff5, 0x6106, 0x00ce,
+	0x0005, 0x2011, 0x0032, 0x2019, 0x0000, 0x00f0, 0x68a0, 0xd0cc,
+	0x1dc0, 0x6208, 0xa294, 0x00ff, 0x78ec, 0xd0e4, 0x0130, 0xa282,
+	0x000b, 0x1218, 0x2011, 0x000a, 0x0028, 0xa282, 0x000c, 0x1210,
+	0x2011, 0x000c, 0x6308, 0x831f, 0xa39c, 0x00ff, 0xa382, 0x0018,
+	0x0218, 0x0110, 0x2019, 0x0018, 0x78ab, 0x0001, 0x78ab, 0x0003,
+	0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xc0c5,
+	0x6822, 0x080c, 0x3a7a, 0x00ce, 0x0005, 0x00c6, 0x2960, 0x6104,
+	0xa18c, 0xfff5, 0x6106, 0x2011, 0x0032, 0x2019, 0x0000, 0x0000,
+	0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa,
+	0xa8c0, 0x0005, 0x6820, 0xc0c5, 0x6822, 0x00ce, 0x0005, 0xa006,
+	0x2030, 0x2010, 0x00c6, 0x7154, 0x2160, 0x2018, 0x2008, 0xa084,
+	0xffe0, 0xa635, 0x7e86, 0x6018, 0x789a, 0x7eae, 0x6612, 0x78a4,
+	0xa084, 0x7770, 0xa18c, 0x000f, 0xa105, 0x2029, 0x4705, 0x252c,
+	0xd5cc, 0x0140, 0xd3a4, 0x0110, 0xa085, 0x0800, 0xd3fc, 0x0110,
+	0xa085, 0x8080, 0x78a6, 0x6016, 0x788a, 0xa6b4, 0x001f, 0x8637,
+	0x8204, 0x8004, 0xa605, 0x600e, 0x6004, 0xa084, 0xffd5, 0x6006,
+	0x00ce, 0x0005, 0xa282, 0x0002, 0x1904, 0x3a3f, 0x7aa8, 0x6920,
+	0xc1bd, 0x6922, 0xd1cc, 0x0568, 0xc1cc, 0x6922, 0xa294, 0x00ff,
+	0xa282, 0x0002, 0x1a04, 0x3a30, 0x080c, 0x39c1, 0x080c, 0x3917,
+	0xa980, 0x0001, 0x200c, 0x080c, 0x3b91, 0x080c, 0x38b8, 0x88ff,
+	0x0178, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a,
+	0xd6d4, 0x1118, 0x781b, 0x006e, 0x0005, 0x781b, 0x0082, 0x0005,
 	0x7e58, 0xd6d4, 0x1118, 0x781b, 0x0071, 0x0005, 0x781b, 0x0083,
-	0x0005, 0x00c6, 0x7054, 0x2060, 0x6100, 0xd1e4, 0x0598, 0x6208,
-	0x8217, 0xa294, 0x00ff, 0xa282, 0x0018, 0x0218, 0x0110, 0x2011,
-	0x0018, 0x2600, 0xa202, 0x1208, 0x2230, 0xa686, 0x0010, 0x1108,
-	0x8630, 0x6208, 0xa294, 0x00ff, 0x78ec, 0xd0e4, 0x0130, 0xa282,
-	0x000a, 0x1240, 0x2011, 0x000a, 0x0028, 0xa282, 0x000c, 0x1210,
-	0x2011, 0x000c, 0x2200, 0xa502, 0x1208, 0x2228, 0x080c, 0x3a99,
-	0x852b, 0x852b, 0x2041, 0x0000, 0x080c, 0x3ac9, 0x0118, 0x080c,
-	0x38f7, 0x0020, 0x080c, 0x3a95, 0x080c, 0x38f4, 0x7858, 0xc095,
-	0x785a, 0x00ce, 0x781b, 0x0082, 0x0005, 0x00c6, 0x2960, 0x6000,
-	0xd0e4, 0x1188, 0xd0b4, 0x1150, 0x6010, 0xa084, 0x000f, 0x1130,
-	0x6104, 0xa18c, 0xfff5, 0x6106, 0x00ce, 0x0005, 0x2011, 0x0032,
-	0x2019, 0x0000, 0x00f0, 0x68a0, 0xd0cc, 0x1dc0, 0x6208, 0xa294,
-	0x00ff, 0x78ec, 0xd0e4, 0x0130, 0xa282, 0x000b, 0x1218, 0x2011,
-	0x000a, 0x0028, 0xa282, 0x000c, 0x1210, 0x2011, 0x000c, 0x6308,
-	0x831f, 0xa39c, 0x00ff, 0xa382, 0x0018, 0x0218, 0x0110, 0x2019,
-	0x0018, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa,
-	0x7baa, 0xa8c0, 0x0005, 0x6820, 0xc0c5, 0x6822, 0x080c, 0x3a55,
-	0x00ce, 0x0005, 0x00c6, 0x2960, 0x6104, 0xa18c, 0xfff5, 0x6106,
-	0x2011, 0x0032, 0x2019, 0x0000, 0x0000, 0x78ab, 0x0001, 0x78ab,
-	0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820,
-	0xc0c5, 0x6822, 0x00ce, 0x0005, 0xa006, 0x2030, 0x2010, 0x00c6,
-	0x7154, 0x2160, 0x2018, 0x2008, 0xa084, 0xffe0, 0xa635, 0x7e86,
-	0x6018, 0x789a, 0x7eae, 0x6612, 0x78a4, 0xa084, 0x7770, 0xa18c,
-	0x000f, 0xa105, 0x2029, 0x4605, 0x252c, 0xd5cc, 0x0140, 0xd3a4,
-	0x0110, 0xa085, 0x0800, 0xd3fc, 0x0110, 0xa085, 0x8080, 0x78a6,
-	0x6016, 0x788a, 0xa6b4, 0x001f, 0x8637, 0x8204, 0x8004, 0xa605,
-	0x600e, 0x6004, 0xa084, 0xffd5, 0x6006, 0x00ce, 0x0005, 0xa282,
-	0x0002, 0x1904, 0x3a1a, 0x7aa8, 0x6920, 0xc1bd, 0x6922, 0xd1cc,
-	0x0568, 0xc1cc, 0x6922, 0xa294, 0x00ff, 0xa282, 0x0002, 0x1a04,
-	0x3a0b, 0x080c, 0x399e, 0x080c, 0x38f4, 0xa980, 0x0001, 0x200c,
-	0x080c, 0x3b6b, 0x080c, 0x3895, 0x88ff, 0x0178, 0x789b, 0x0060,
-	0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x1118, 0x781b,
-	0x006e, 0x0005, 0x781b, 0x0082, 0x0005, 0x7e58, 0xd6d4, 0x1118,
-	0x781b, 0x0071, 0x0005, 0x781b, 0x0083, 0x0005, 0xa282, 0x0002,
-	0x1218, 0xa284, 0x0001, 0x0140, 0x7154, 0xa188, 0x0000, 0x210c,
-	0xd1ec, 0x1110, 0x2011, 0x0000, 0x080c, 0x3a87, 0x0479, 0x080c,
-	0x38f4, 0x7858, 0xc095, 0x785a, 0x781b, 0x0082, 0x0005, 0x00c6,
-	0x0026, 0x2960, 0x6000, 0x2011, 0x0001, 0xd0ec, 0x1158, 0xd0bc,
-	0x1138, 0x6014, 0xd0b4, 0x1120, 0xc1a4, 0x6106, 0xa006, 0x0088,
-	0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003,
-	0x7aaa, 0xa8c0, 0x0004, 0x080c, 0x3a55, 0x6820, 0xa085, 0x0200,
-	0x6822, 0x002e, 0x00ce, 0x0005, 0x8807, 0xa715, 0x00c6, 0x2009,
-	0x0000, 0x7054, 0x2060, 0x82ff, 0x0110, 0x2009, 0x0040, 0x6018,
-	0xa080, 0x0002, 0x789a, 0x78a4, 0xa084, 0xff9f, 0xa105, 0xc0ec,
-	0xd0b4, 0x1108, 0xc0ed, 0x6100, 0xd1f4, 0x0110, 0xa085, 0x0020,
-	0x78a6, 0x6016, 0x788a, 0x6004, 0xa084, 0xffef, 0x6006, 0x00ce,
-	0x0005, 0x0006, 0x7000, 0xa086, 0x0003, 0x0110, 0x000e, 0x0010,
-	0x000e, 0x0488, 0xd6ac, 0x0578, 0x7888, 0xa084, 0x0040, 0x0558,
-	0x7bb8, 0x8307, 0xa084, 0x007f, 0x1508, 0x8207, 0xa084, 0x00ff,
-	0xa09e, 0x0001, 0x1904, 0x3a32, 0xd6f4, 0x11d0, 0x79d8, 0x7adc,
-	0xa108, 0xa291, 0x0000, 0x79d2, 0x79da, 0x7ad6, 0x7ade, 0x080c,
-	0x42b5, 0x781b, 0x0080, 0xb284, 0x0600, 0x0118, 0x2001, 0x0000,
-	0x0010, 0x2001, 0x0001, 0x080c, 0x4172, 0x0005, 0x080c, 0x254c,
-	0x781b, 0x0080, 0x0005, 0x781b, 0x0083, 0x0005, 0x2039, 0x0000,
-	0x2041, 0x0000, 0x2031, 0x0000, 0xa006, 0x2010, 0x080c, 0x38f7,
-	0x080c, 0x399c, 0x7e58, 0x080c, 0x3a4e, 0x781b, 0x0082, 0x0005,
-	0x0cd1, 0x6820, 0xc0c4, 0x6822, 0x00c6, 0x7054, 0x2060, 0x080c,
-	0x3921, 0x00b0, 0x0c81, 0x6820, 0xc0cc, 0x6822, 0x00c6, 0x7054,
-	0x2060, 0x080c, 0x39bb, 0x0060, 0x0c31, 0x6820, 0xa084, 0xecff,
-	0x6822, 0x00c6, 0x7054, 0x2060, 0x6004, 0xa084, 0xffc5, 0x6006,
-	0x00ce, 0x0005, 0x0049, 0x781b, 0x0082, 0x0005, 0x6827, 0x0002,
-	0x0049, 0x781b, 0x0082, 0x0005, 0x2001, 0x0005, 0x0088, 0x2001,
-	0x000c, 0x0070, 0x6820, 0xc0d5, 0x6822, 0x2001, 0x0006, 0x0040,
-	0x2001, 0x000d, 0x0028, 0x2001, 0x0009, 0x0010, 0x2001, 0x0007,
-	0x789b, 0x007e, 0x78aa, 0xc69d, 0x7e5a, 0x70d0, 0xd0b4, 0x0168,
-	0xc0b4, 0x70d2, 0x00c6, 0x70b4, 0xa065, 0x6008, 0xa084, 0xfbef,
-	0x600a, 0x6018, 0x8001, 0x601a, 0x00ce, 0x0005, 0x0076, 0x873f,
-	0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703, 0xa0e0, 0x4ac0, 0xae8e,
-	0x4640, 0x0110, 0xa0e0, 0x4b40, 0xa7b8, 0x0020, 0x7f9a, 0x79a4,
-	0xa184, 0x7fe0, 0x78ae, 0x6012, 0x79a4, 0xa184, 0x773f, 0x78a6,
-	0x6016, 0x6004, 0xa085, 0x0038, 0x6006, 0x007e, 0x0005, 0x789b,
-	0x0080, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa,
-	0x789b, 0x0060, 0x78ab, 0x0004, 0x0800, 0x2031, 0x0000, 0x2029,
-	0x0032, 0x789b, 0x0080, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab,
-	0x0001, 0x7daa, 0x7eaa, 0x789b, 0x0060, 0x78ab, 0x0005, 0x0804,
-	0x3a55, 0x0156, 0x8007, 0xa084, 0x00ff, 0x8003, 0x8003, 0xa080,
-	0x0020, 0x789a, 0x79a4, 0xa18c, 0xffe0, 0x2021, 0x3b54, 0x2019,
-	0x0011, 0x20a9, 0x000e, 0x2011, 0x0032, 0x2404, 0xa084, 0xffe0,
-	0xa106, 0x0128, 0x8420, 0x2300, 0xa210, 0x1f04, 0x3abd, 0x015e,
-	0x0005, 0x0156, 0x04f8, 0x2021, 0x3b62, 0x20a9, 0x0009, 0x2011,
-	0x0029, 0xa582, 0x0028, 0x0550, 0x8420, 0x95a9, 0x2011, 0x0033,
-	0xa582, 0x0033, 0x0618, 0x8420, 0x95a9, 0x2019, 0x000a, 0x2011,
-	0x0065, 0x2200, 0xa502, 0x02d0, 0x8420, 0x2300, 0xa210, 0x1f04,
-	0x3ae1, 0x015e, 0x0088, 0x2021, 0x3b54, 0x2019, 0x0011, 0x20a9,
-	0x000e, 0x2011, 0x0033, 0x2200, 0xa502, 0x0240, 0x8420, 0x2300,
-	0xa210, 0x1f04, 0x3af3, 0x015e, 0xa006, 0x0005, 0x8211, 0x015e,
-	0xa582, 0x0064, 0x1220, 0x7808, 0xa085, 0x0070, 0x780a, 0x2404,
-	0xa005, 0x0005, 0xa886, 0x0002, 0x01e8, 0x2021, 0x3b40, 0x20a9,
-	0x000d, 0x2011, 0x0028, 0xa582, 0x0028, 0x0d48, 0x8420, 0x2019,
-	0x0019, 0x2011, 0x0033, 0x2200, 0xa502, 0x0e00, 0x8420, 0x2300,
-	0xa210, 0x1f04, 0x3b1b, 0x015e, 0x2011, 0x0184, 0xa582, 0x0185,
-	0x0ab0, 0x0890, 0x2021, 0x3b4f, 0x20a9, 0x0003, 0x2011, 0x0024,
-	0xa586, 0x0024, 0x0960, 0x8420, 0x2011, 0x0028, 0xa586, 0x0028,
-	0x0930, 0x8420, 0x2019, 0x0019, 0x2011, 0x0033, 0x0804, 0x3af3,
-	0x1021, 0x2202, 0x3403, 0x4604, 0x5805, 0x6a06, 0x7c07, 0x4610,
-	0x4612, 0x5812, 0x5a12, 0x6a14, 0x6c14, 0x6e14, 0x7e17, 0x9021,
-	0xb002, 0xe204, 0xe210, 0xe210, 0x1209, 0x3002, 0x3202, 0x4203,
-	0x4403, 0x5404, 0x5604, 0x6605, 0x6805, 0x7806, 0x7a06, 0x0c07,
-	0x0c07, 0x0e07, 0x10e1, 0x330a, 0x5805, 0x5a05, 0x6a06, 0x6c06,
-	0x7c07, 0x7e07, 0x0e00, 0x789b, 0x0080, 0xa046, 0x0005, 0xa784,
-	0x0f00, 0x800b, 0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003,
-	0xa105, 0xd7fc, 0x0118, 0xa0e0, 0x6bc0, 0x0010, 0xa0e0, 0x4bc0,
-	0x0005, 0x00e6, 0x00f6, 0xd084, 0x0138, 0x2079, 0x0100, 0x2009,
-	0x4680, 0x2071, 0x4680, 0x0030, 0x2009, 0x4640, 0x2079, 0x0200,
-	0x2071, 0x4640, 0x2091, 0x8000, 0x2104, 0xa084, 0x000f, 0x0002,
-	0x3ba2, 0x3ba2, 0x3ba2, 0x3ba2, 0x3ba2, 0x3ba2, 0x3ba0, 0x3ba0,
-	0x080c, 0x254c, 0x69b4, 0xc1f5, 0xa18c, 0xff9f, 0x69b6, 0xa005,
-	0x0580, 0x7858, 0xa084, 0xff9f, 0xa085, 0x6000, 0x785a, 0x7828,
-	0xa086, 0x1814, 0x1530, 0x784b, 0x0004, 0x7848, 0xa084, 0x0004,
-	0x1de0, 0x784b, 0x0008, 0x7848, 0xa084, 0x0008, 0x1de0, 0x7830,
-	0xd0bc, 0x11b8, 0xb284, 0x0800, 0x0118, 0x0104, 0x3bd9, 0x0010,
-	0x0304, 0x3bd9, 0x79e4, 0xa184, 0x0030, 0x0158, 0x78ec, 0xa084,
-	0x0003, 0x0138, 0x681c, 0xd0ac, 0x1110, 0x00d9, 0x0010, 0x781b,
-	0x00fb, 0x00fe, 0x00ee, 0x0005, 0x2001, 0x4601, 0x2004, 0xd0ac,
-	0x1118, 0x6814, 0x080c, 0x2475, 0x0005, 0x781b, 0x0083, 0x0005,
-	0x781b, 0x0082, 0x0005, 0x781b, 0x0071, 0x0005, 0x781b, 0x006e,
-	0x0005, 0x2009, 0x4619, 0x210c, 0xa186, 0x0000, 0x0150, 0xa186,
-	0x0001, 0x0150, 0x701f, 0x000b, 0x7063, 0x0001, 0x781b, 0x0054,
-	0x0005, 0x781b, 0x00f3, 0x0005, 0x701f, 0x000a, 0x0005, 0x2009,
-	0x4619, 0x210c, 0xa186, 0x0000, 0x0168, 0xa186, 0x0001, 0x0138,
-	0x701f, 0x000b, 0x7063, 0x0001, 0x781b, 0x0054, 0x0005, 0x701f,
-	0x000a, 0x0005, 0x781b, 0x00f2, 0x0005, 0x781b, 0x00fb, 0x0005,
-	0x781b, 0x00fa, 0x0005, 0x781b, 0x00cc, 0x0005, 0x781b, 0x00cb,
-	0x0005, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d, 0x7063, 0x0001,
+	0x0005, 0xa282, 0x0002, 0x1218, 0xa284, 0x0001, 0x0140, 0x7154,
+	0xa188, 0x0000, 0x210c, 0xd1ec, 0x1110, 0x2011, 0x0000, 0x080c,
+	0x3aac, 0x0479, 0x080c, 0x3917, 0x7858, 0xc095, 0x785a, 0x781b,
+	0x0082, 0x0005, 0x00c6, 0x0026, 0x2960, 0x6000, 0x2011, 0x0001,
+	0xd0ec, 0x1158, 0xd0bc, 0x1138, 0x6014, 0xd0b4, 0x1120, 0xc1a4,
+	0x6106, 0xa006, 0x0088, 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab,
+	0x0002, 0x78ab, 0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x080c, 0x3a7a,
+	0x6820, 0xa085, 0x0200, 0x6822, 0x002e, 0x00ce, 0x0005, 0x8807,
+	0xa715, 0x00c6, 0x2009, 0x0000, 0x7054, 0x2060, 0x82ff, 0x0110,
+	0x2009, 0x0040, 0x6018, 0xa080, 0x0002, 0x789a, 0x78a4, 0xa084,
+	0xff9f, 0xa105, 0xc0ec, 0xd0b4, 0x1108, 0xc0ed, 0x6100, 0xd1f4,
+	0x0110, 0xa085, 0x0020, 0x78a6, 0x6016, 0x788a, 0x6004, 0xa084,
+	0xffef, 0x6006, 0x00ce, 0x0005, 0x0006, 0x7000, 0xa086, 0x0003,
+	0x0110, 0x000e, 0x0010, 0x000e, 0x0498, 0xd6ac, 0x0588, 0x7888,
+	0xa084, 0x0040, 0x0568, 0x7bb8, 0x8307, 0xa084, 0x007f, 0x1518,
+	0x8207, 0xa084, 0x00ff, 0x0904, 0x3a57, 0xa09a, 0x0004, 0x1a04,
+	0x3a57, 0xd6f4, 0x11d0, 0x79d8, 0x7adc, 0xa108, 0xa291, 0x0000,
+	0x79d2, 0x79da, 0x7ad6, 0x7ade, 0x080c, 0x42e8, 0x781b, 0x0080,
+	0xb284, 0x0600, 0x0118, 0x2001, 0x0000, 0x0010, 0x2001, 0x0001,
+	0x080c, 0x419a, 0x0005, 0x080c, 0x2575, 0x781b, 0x0080, 0x0005,
+	0x781b, 0x0083, 0x0005, 0x2039, 0x0000, 0x2041, 0x0000, 0x2031,
+	0x0000, 0xa006, 0x2010, 0x080c, 0x391a, 0x080c, 0x39bf, 0x7e58,
+	0x080c, 0x3a73, 0x781b, 0x0082, 0x0005, 0x0cd1, 0x6820, 0xc0c4,
+	0x6822, 0x00c6, 0x7054, 0x2060, 0x080c, 0x3944, 0x00b0, 0x0c81,
+	0x6820, 0xc0cc, 0x6822, 0x00c6, 0x7054, 0x2060, 0x080c, 0x39de,
+	0x0060, 0x0c31, 0x6820, 0xa084, 0xecff, 0x6822, 0x00c6, 0x7054,
+	0x2060, 0x6004, 0xa084, 0xffc5, 0x6006, 0x00ce, 0x0005, 0x0049,
+	0x781b, 0x0082, 0x0005, 0x6827, 0x0002, 0x0049, 0x781b, 0x0082,
+	0x0005, 0x2001, 0x0005, 0x0088, 0x2001, 0x000c, 0x0070, 0x6820,
+	0xc0d5, 0x6822, 0x2001, 0x0006, 0x0040, 0x2001, 0x000d, 0x0028,
+	0x2001, 0x0009, 0x0010, 0x2001, 0x0007, 0x789b, 0x007e, 0x78aa,
+	0xc69d, 0x7e5a, 0x70d0, 0xd0b4, 0x0168, 0xc0b4, 0x70d2, 0x00c6,
+	0x70b4, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001,
+	0x601a, 0x00ce, 0x0005, 0x0076, 0x873f, 0xa7bc, 0x000f, 0x873b,
+	0x873b, 0x8703, 0xa0e0, 0x4bc0, 0xae8e, 0x4740, 0x0110, 0xa0e0,
+	0x4c40, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184, 0x7fe0, 0x78ae,
+	0x6012, 0x79a4, 0xa184, 0x773f, 0x78a6, 0x6016, 0x6004, 0xa085,
+	0x0038, 0x6006, 0x007e, 0x0005, 0x789b, 0x0080, 0x78ab, 0x0001,
+	0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060, 0x78ab,
+	0x0004, 0x0800, 0x2031, 0x0000, 0x2029, 0x0032, 0x789b, 0x0080,
+	0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa, 0x7eaa,
+	0x789b, 0x0060, 0x78ab, 0x0005, 0x0804, 0x3a7a, 0x0156, 0x8007,
+	0xa084, 0x00ff, 0x8003, 0x8003, 0xa080, 0x0020, 0x789a, 0x79a4,
+	0xa18c, 0xffe0, 0x2021, 0x3b7a, 0x2019, 0x0011, 0x20a9, 0x000e,
+	0x2011, 0x0032, 0x2404, 0xa084, 0xffe0, 0xa106, 0x0128, 0x8420,
+	0x2300, 0xa210, 0x1f04, 0x3ae2, 0x015e, 0x0005, 0x0156, 0x0804,
+	0x3b30, 0x2021, 0x3b88, 0x20a9, 0x0009, 0x2011, 0x0029, 0xa582,
+	0x0028, 0x0550, 0x8420, 0x95a9, 0x2011, 0x0033, 0xa582, 0x0033,
+	0x0618, 0x8420, 0x95a9, 0x2019, 0x000a, 0x2011, 0x0065, 0x2200,
+	0xa502, 0x02d0, 0x8420, 0x2300, 0xa210, 0x1f04, 0x3b07, 0x015e,
+	0x0088, 0x2021, 0x3b7a, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011,
+	0x0033, 0x2200, 0xa502, 0x0240, 0x8420, 0x2300, 0xa210, 0x1f04,
+	0x3b19, 0x015e, 0xa006, 0x0005, 0x8211, 0x015e, 0xa582, 0x0064,
+	0x1220, 0x7808, 0xa085, 0x0070, 0x780a, 0x2404, 0xa005, 0x0005,
+	0xa886, 0x0002, 0x01e8, 0x2021, 0x3b66, 0x20a9, 0x000d, 0x2011,
+	0x0028, 0xa582, 0x0028, 0x0d48, 0x8420, 0x2019, 0x0019, 0x2011,
+	0x0033, 0x2200, 0xa502, 0x0e00, 0x8420, 0x2300, 0xa210, 0x1f04,
+	0x3b41, 0x015e, 0x2011, 0x0184, 0xa582, 0x0185, 0x0ab0, 0x0890,
+	0x2021, 0x3b75, 0x20a9, 0x0003, 0x2011, 0x0024, 0xa586, 0x0024,
+	0x0960, 0x8420, 0x2011, 0x0028, 0xa586, 0x0028, 0x0930, 0x8420,
+	0x2019, 0x0019, 0x2011, 0x0033, 0x0804, 0x3b19, 0x1021, 0x2202,
+	0x3403, 0x4604, 0x5805, 0x6a06, 0x7c07, 0x4610, 0x4612, 0x5812,
+	0x5a12, 0x6a14, 0x6c14, 0x6e14, 0x7e17, 0x9021, 0xb002, 0xe204,
+	0xe210, 0xe210, 0x1209, 0x3002, 0x3202, 0x4203, 0x4403, 0x5404,
+	0x5604, 0x6605, 0x6805, 0x7806, 0x7a06, 0x0c07, 0x0c07, 0x0e07,
+	0x10e1, 0x330a, 0x5805, 0x5a05, 0x6a06, 0x6c06, 0x7c07, 0x7e07,
+	0x0e00, 0x789b, 0x0080, 0xa046, 0x0005, 0xa784, 0x0f00, 0x800b,
+	0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xd7fc,
+	0x0118, 0xa0e0, 0x6cc0, 0x0010, 0xa0e0, 0x4cc0, 0x0005, 0x00e6,
+	0x00f6, 0xd084, 0x0138, 0x2079, 0x0100, 0x2009, 0x4780, 0x2071,
+	0x4780, 0x0030, 0x2009, 0x4740, 0x2079, 0x0200, 0x2071, 0x4740,
+	0x2091, 0x8000, 0x2104, 0xa084, 0x000f, 0x0002, 0x3bc8, 0x3bc8,
+	0x3bc8, 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc6, 0x3bc6, 0x080c, 0x2575,
+	0x69b4, 0xc1f5, 0xa18c, 0xff9f, 0x69b6, 0xa005, 0x0580, 0x7858,
+	0xa084, 0xff9f, 0xa085, 0x6000, 0x785a, 0x7828, 0xa086, 0x1814,
+	0x1530, 0x784b, 0x0004, 0x7848, 0xa084, 0x0004, 0x1de0, 0x784b,
+	0x0008, 0x7848, 0xa084, 0x0008, 0x1de0, 0x7830, 0xd0bc, 0x11b8,
+	0xb284, 0x0800, 0x0118, 0x0104, 0x3bff, 0x0010, 0x0304, 0x3bff,
+	0x79e4, 0xa184, 0x0030, 0x0158, 0x78ec, 0xa084, 0x0003, 0x0138,
+	0x681c, 0xd0ac, 0x1110, 0x00d9, 0x0010, 0x781b, 0x00fb, 0x00fe,
+	0x00ee, 0x0005, 0x2001, 0x4701, 0x2004, 0xd0ac, 0x1118, 0x6814,
+	0x080c, 0x249e, 0x0005, 0x781b, 0x0083, 0x0005, 0x781b, 0x0082,
+	0x0005, 0x781b, 0x0071, 0x0005, 0x781b, 0x006e, 0x0005, 0x2009,
+	0x4719, 0x210c, 0xa186, 0x0000, 0x0150, 0xa186, 0x0001, 0x0150,
+	0x701f, 0x000b, 0x7063, 0x0001, 0x781b, 0x0054, 0x0005, 0x781b,
+	0x00f3, 0x0005, 0x701f, 0x000a, 0x0005, 0x2009, 0x4719, 0x210c,
+	0xa186, 0x0000, 0x0168, 0xa186, 0x0001, 0x0138, 0x701f, 0x000b,
+	0x7063, 0x0001, 0x781b, 0x0054, 0x0005, 0x701f, 0x000a, 0x0005,
+	0x781b, 0x00f2, 0x0005, 0x781b, 0x00fb, 0x0005, 0x781b, 0x00fa,
+	0x0005, 0x781b, 0x00cc, 0x0005, 0x781b, 0x00cb, 0x0005, 0x6818,
+	0xd0fc, 0x0110, 0x681b, 0x001d, 0x701f, 0x000b, 0x7063, 0x0001,
 	0x781b, 0x0054, 0x0005, 0x7830, 0xa084, 0x00c0, 0x1170, 0x7808,
 	0xc08c, 0x780a, 0xe000, 0xe000, 0xe000, 0xe000, 0x78ec, 0xa084,
 	0x0021, 0x0118, 0x7808, 0xc08d, 0x780a, 0x0005, 0x7808, 0xc08d,
 	0x780a, 0x0005, 0x7830, 0xa084, 0x0040, 0x1de0, 0xb284, 0x0800,
-	0x0118, 0x1104, 0x3c58, 0x0010, 0x1304, 0x3c58, 0x78ac, 0x0005,
+	0x0118, 0x1104, 0x3c80, 0x0010, 0x1304, 0x3c80, 0x78ac, 0x0005,
 	0x7808, 0xa084, 0xfffd, 0x780a, 0xe000, 0xe000, 0xe000, 0xe000,
 	0x78ec, 0xa084, 0x0021, 0x0140, 0xb284, 0x0800, 0x0118, 0x1104,
-	0x3c67, 0x0010, 0x1304, 0x3c6a, 0x78ac, 0x0006, 0x7808, 0xa085,
-	0x0002, 0x780a, 0x000e, 0x0005, 0xa784, 0x0001, 0x1904, 0x322a,
-	0xa784, 0x0070, 0x0140, 0x00c6, 0x2d60, 0x2f68, 0x080c, 0x2467,
+	0x3c8f, 0x0010, 0x1304, 0x3c92, 0x78ac, 0x0006, 0x7808, 0xa085,
+	0x0002, 0x780a, 0x000e, 0x0005, 0xa784, 0x0001, 0x1904, 0x324d,
+	0xa784, 0x0070, 0x0140, 0x00c6, 0x2d60, 0x2f68, 0x080c, 0x2490,
 	0x2d78, 0x2c68, 0x00ce, 0xa784, 0x0008, 0x0148, 0x784b, 0x0008,
-	0x78ec, 0xa084, 0x0003, 0x0904, 0x322a, 0x0804, 0x3be5, 0xa784,
+	0x78ec, 0xa084, 0x0003, 0x0904, 0x324d, 0x0804, 0x3c0b, 0xa784,
 	0x0004, 0x01c8, 0x78b8, 0xa084, 0x8000, 0x01a8, 0x784b, 0x0008,
-	0x78ec, 0xa084, 0x0003, 0x0904, 0x322a, 0x78e4, 0xa084, 0x0007,
+	0x78ec, 0xa084, 0x0003, 0x0904, 0x324d, 0x78e4, 0xa084, 0x0007,
 	0xa086, 0x0001, 0x1140, 0x78c0, 0xa685, 0x4800, 0x2030, 0x7e5a,
 	0x781b, 0x00fb, 0x0005, 0xa784, 0x0080, 0x0140, 0x7884, 0xd0fc,
-	0x0128, 0x080c, 0x3a32, 0x681b, 0x0022, 0x0005, 0x681b, 0x0003,
+	0x0128, 0x080c, 0x3a57, 0x681b, 0x0022, 0x0005, 0x681b, 0x0003,
 	0x7858, 0xa084, 0x5f00, 0x681e, 0x682f, 0x0000, 0x6833, 0x0000,
-	0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0904, 0x2b89, 0xb284,
-	0x0800, 0x0110, 0x0104, 0x259d, 0x0304, 0x259d, 0x6b14, 0x8307,
+	0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0904, 0x2bac, 0xb284,
+	0x0800, 0x0110, 0x0104, 0x25c6, 0x0304, 0x25c6, 0x6b14, 0x8307,
 	0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xd3fc, 0x0118, 0xa080,
-	0x4b40, 0x0010, 0xa080, 0x4ac0, 0x2060, 0x2048, 0x7056, 0x2a60,
-	0x0005, 0x00c6, 0x2960, 0x6000, 0xd0ac, 0x0904, 0x3d2f, 0x68a0,
-	0xd1ac, 0x1120, 0xa084, 0x0e00, 0x0904, 0x3d2d, 0x6108, 0x8117,
+	0x4c40, 0x0010, 0xa080, 0x4bc0, 0x2060, 0x2048, 0x7056, 0x2a60,
+	0x0005, 0x00c6, 0x2960, 0x6000, 0xd0ac, 0x0904, 0x3d57, 0x68a0,
+	0xd1ac, 0x1120, 0xa084, 0x0e00, 0x0904, 0x3d55, 0x6108, 0x8117,
 	0xa18c, 0x00ff, 0x631c, 0x832f, 0xd0dc, 0x0110, 0xa39d, 0x0001,
 	0xd0cc, 0x11c8, 0xa584, 0x00ff, 0x0138, 0x78ec, 0xd0e4, 0x0110,
 	0x8213, 0x00b8, 0x2029, 0x0000, 0xa182, 0x000c, 0x1290, 0x78ec,
@@ -1493,23 +1498,23 @@
 	0x2009, 0x000a, 0x0030, 0x2009, 0x0032, 0x2011, 0x0000, 0x2029,
 	0x0000, 0x78ab, 0x0001, 0x78ab, 0x0006, 0x78ab, 0x0004, 0x79aa,
 	0x78ab, 0x0000, 0x7aaa, 0x7baa, 0x7daa, 0xa8c0, 0x0008, 0x6820,
-	0xa085, 0x1000, 0x6822, 0x080c, 0x3a55, 0xa085, 0x0001, 0x00ce,
-	0x0005, 0xa282, 0x0006, 0x1904, 0x3a24, 0x7da8, 0x7eac, 0x8637,
+	0xa085, 0x1000, 0x6822, 0x080c, 0x3a7a, 0xa085, 0x0001, 0x00ce,
+	0x0005, 0xa282, 0x0006, 0x1904, 0x3a49, 0x7da8, 0x7eac, 0x8637,
 	0xa5ac, 0x00ff, 0xa6b4, 0x00ff, 0x7fac, 0x8747, 0xa7bc, 0x00ff,
-	0xa8c4, 0x00ff, 0x6920, 0xc1bd, 0x6922, 0xd1e4, 0x0904, 0x3da3,
-	0xa18c, 0xecff, 0x6922, 0xa782, 0x0002, 0x1a04, 0x39fe, 0xa6b4,
-	0x00ff, 0x0904, 0x3da0, 0xa682, 0x0031, 0x1a04, 0x39fe, 0xa582,
-	0x0009, 0x0a04, 0x39fe, 0xa882, 0x0003, 0x1a04, 0x39fe, 0xa886,
-	0x0002, 0x01d0, 0xa886, 0x0000, 0x1904, 0x39fe, 0x2001, 0x000c,
+	0xa8c4, 0x00ff, 0x6920, 0xc1bd, 0x6922, 0xd1e4, 0x0904, 0x3dcb,
+	0xa18c, 0xecff, 0x6922, 0xa782, 0x0002, 0x1a04, 0x3a23, 0xa6b4,
+	0x00ff, 0x0904, 0x3dc8, 0xa682, 0x0031, 0x1a04, 0x3a23, 0xa582,
+	0x0009, 0x0a04, 0x3a23, 0xa882, 0x0003, 0x1a04, 0x3a23, 0xa886,
+	0x0002, 0x01d0, 0xa886, 0x0000, 0x1904, 0x3a23, 0x2001, 0x000c,
 	0x79ec, 0xd1e4, 0x0110, 0x2001, 0x000a, 0xa502, 0x1290, 0x080c,
-	0x39fe, 0x00c6, 0x2960, 0x6004, 0xa085, 0x001a, 0x6006, 0x6000,
-	0xc0ac, 0x6002, 0x00ce, 0x0005, 0xa786, 0x0000, 0x0904, 0x39fe,
+	0x3a23, 0x00c6, 0x2960, 0x6004, 0xa085, 0x001a, 0x6006, 0x6000,
+	0xc0ac, 0x6002, 0x00ce, 0x0005, 0xa786, 0x0000, 0x0904, 0x3a23,
 	0x8634, 0xa682, 0x0018, 0x0228, 0x0120, 0x2031, 0x0018, 0x0804,
-	0x3df1, 0xa686, 0x0010, 0x1108, 0x8630, 0x852b, 0x852b, 0x080c,
-	0x3ac9, 0x0904, 0x39fe, 0x080c, 0x38f7, 0x080c, 0x399c, 0x7e58,
+	0x3e19, 0xa686, 0x0010, 0x1108, 0x8630, 0x852b, 0x852b, 0x080c,
+	0x3aee, 0x0904, 0x3a23, 0x080c, 0x391a, 0x080c, 0x39bf, 0x7e58,
 	0xd6d4, 0x1118, 0x781b, 0x0071, 0x0005, 0x781b, 0x0083, 0x0005,
-	0x080c, 0x38f4, 0x0c90, 0xa886, 0x0002, 0x1108, 0x8634, 0x7154,
-	0xa188, 0x0000, 0x210c, 0xd1ac, 0x0904, 0x39fe, 0xd1ec, 0x1120,
+	0x080c, 0x3917, 0x0c90, 0xa886, 0x0002, 0x1108, 0x8634, 0x7154,
+	0xa188, 0x0000, 0x210c, 0xd1ac, 0x0904, 0x3a23, 0xd1ec, 0x1120,
 	0x2039, 0x0000, 0x2041, 0x0000, 0xd1e4, 0x1120, 0x2031, 0x0000,
 	0x2041, 0x0000, 0xa782, 0x0002, 0x12c8, 0x621c, 0xa284, 0x00ff,
 	0xa706, 0x0110, 0x2039, 0x0000, 0xa605, 0x0190, 0x6108, 0x811f,
@@ -1517,11 +1522,11 @@
 	0xa086, 0x0201, 0x0160, 0xa886, 0x0000, 0x0168, 0x2039, 0x0000,
 	0x2041, 0x0000, 0x2031, 0x0000, 0xa006, 0x2010, 0x0070, 0xa284,
 	0xff00, 0x1108, 0x2040, 0xa184, 0x00ff, 0xa502, 0x0108, 0x2128,
-	0x852b, 0x852b, 0x080c, 0x3ac9, 0x0d58, 0x080c, 0x38f7, 0x080c,
-	0x399c, 0x789b, 0x0080, 0x78ab, 0x0001, 0x78ab, 0x0006, 0x78ab,
+	0x852b, 0x852b, 0x080c, 0x3aee, 0x0d58, 0x080c, 0x391a, 0x080c,
+	0x39bf, 0x789b, 0x0080, 0x78ab, 0x0001, 0x78ab, 0x0006, 0x78ab,
 	0x0004, 0x7daa, 0x78ab, 0x0000, 0x7eaa, 0x7faa, 0x2800, 0x78aa,
 	0x789b, 0x0060, 0x78ab, 0x0008, 0x6820, 0xc0e5, 0x6822, 0x080c,
-	0x3a55, 0x7858, 0xc095, 0x785a, 0x781b, 0x0082, 0x0005, 0x0020,
+	0x3a7a, 0x7858, 0xc095, 0x785a, 0x781b, 0x0082, 0x0005, 0x0020,
 	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
 	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
 	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
@@ -1559,223 +1564,248 @@
 	0x20dd, 0x0011, 0x20d5, 0x8822, 0x0016, 0x0000, 0x0126, 0x70d0,
 	0xa084, 0x4c00, 0x8004, 0x2090, 0x7204, 0x7008, 0xc09c, 0xa205,
 	0x11a0, 0x720c, 0x82ff, 0x0128, 0x8aff, 0x1178, 0x7200, 0xd284,
-	0x1160, 0x7804, 0xd0cc, 0x0110, 0x080c, 0x4328, 0x7007, 0x0008,
+	0x1160, 0x7804, 0xd0cc, 0x0110, 0x080c, 0x435b, 0x7007, 0x0008,
 	0x7003, 0x0008, 0x012e, 0x2000, 0x0005, 0x7000, 0xa084, 0x0003,
 	0x7002, 0xc69c, 0xd084, 0x0588, 0x7108, 0xe000, 0x7008, 0xa106,
-	0x1dd8, 0xa184, 0x0003, 0x0904, 0x3fa2, 0xa184, 0x01e0, 0x1904,
-	0x3fa2, 0xd1f4, 0x1d88, 0xa184, 0x3000, 0xa086, 0x1000, 0x0d60,
+	0x1dd8, 0xa184, 0x0003, 0x0904, 0x3fca, 0xa184, 0x01e0, 0x1904,
+	0x3fca, 0xd1f4, 0x1d88, 0xa184, 0x3000, 0xa086, 0x1000, 0x0d60,
 	0x2011, 0x0180, 0x710c, 0x8211, 0x0130, 0x7008, 0xd0f4, 0x1d20,
 	0x700c, 0xa106, 0x0dc0, 0x7007, 0x0012, 0x7108, 0xe000, 0x7008,
 	0xa106, 0x1dd8, 0xa184, 0x0003, 0x0568, 0xd194, 0x0db0, 0xd1f4,
 	0x0548, 0x7007, 0x0002, 0x0880, 0x0428, 0x7108, 0xd1fc, 0x0130,
-	0x080c, 0x40ae, 0x8aff, 0x0904, 0x3f2c, 0x0cb8, 0x700c, 0xa08c,
+	0x080c, 0x40d6, 0x8aff, 0x0904, 0x3f54, 0x0cb8, 0x700c, 0xa08c,
 	0x07ff, 0x01e8, 0x7004, 0xd084, 0x0178, 0x7014, 0xa005, 0x1148,
 	0x7010, 0x7310, 0xa306, 0x1de0, 0x2300, 0xa005, 0x0128, 0xa102,
-	0x1e20, 0x7007, 0x0010, 0x0030, 0x8aff, 0x0148, 0x080c, 0x426b,
-	0x1de8, 0x09d8, 0x080c, 0x4034, 0x012e, 0x2000, 0x0005, 0x7204,
+	0x1e20, 0x7007, 0x0010, 0x0030, 0x8aff, 0x0148, 0x080c, 0x429a,
+	0x1de8, 0x09d8, 0x080c, 0x405c, 0x012e, 0x2000, 0x0005, 0x7204,
 	0x7108, 0xc19c, 0x8103, 0x1218, 0x7007, 0x0002, 0x0cc0, 0xa205,
-	0x1d88, 0x7007, 0x0008, 0x7003, 0x0008, 0x0006, 0x2001, 0x4601,
-	0x2004, 0xd0cc, 0x0110, 0x080c, 0x4328, 0x000e, 0x012e, 0x2000,
+	0x1d88, 0x7007, 0x0008, 0x7003, 0x0008, 0x0006, 0x2001, 0x4701,
+	0x2004, 0xd0cc, 0x0110, 0x080c, 0x435b, 0x000e, 0x012e, 0x2000,
 	0x0005, 0x6428, 0x84ff, 0x0508, 0x2c70, 0x7004, 0xa0bc, 0x000f,
-	0xa7b8, 0x3ff5, 0x273c, 0x87fb, 0x1148, 0x0210, 0x080c, 0x254c,
-	0x609c, 0xa075, 0x0190, 0x0c88, 0x2039, 0x3fea, 0x2704, 0xae68,
+	0xa7b8, 0x401d, 0x273c, 0x87fb, 0x1148, 0x0210, 0x080c, 0x2575,
+	0x609c, 0xa075, 0x0190, 0x0c88, 0x2039, 0x4012, 0x2704, 0xae68,
 	0x6808, 0xa630, 0x680c, 0xa529, 0x8421, 0x0138, 0x8738, 0x2704,
 	0xa005, 0x1da8, 0x709c, 0xa075, 0x1d00, 0x0005, 0x0000, 0x0005,
 	0x0009, 0x000d, 0x0011, 0x0015, 0x0019, 0x001d, 0x0000, 0x0003,
-	0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0000, 0x3fea, 0x3fe7,
-	0x0000, 0x0000, 0x8000, 0x0000, 0x3fea, 0x0000, 0x3ff2, 0x3fef,
-	0x0000, 0x0000, 0x0000, 0x0000, 0x3ff2, 0x0000, 0x3fed, 0x3fed,
-	0x0000, 0x0000, 0x8000, 0x0000, 0x3fed, 0x0000, 0x3ff3, 0x3ff3,
-	0x0000, 0x0000, 0x0000, 0x0000, 0x3ff3, 0x2079, 0x4600, 0x2071,
+	0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0000, 0x4012, 0x400f,
+	0x0000, 0x0000, 0x8000, 0x0000, 0x4012, 0x0000, 0x401a, 0x4017,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x401a, 0x0000, 0x4015, 0x4015,
+	0x0000, 0x0000, 0x8000, 0x0000, 0x4015, 0x0000, 0x401b, 0x401b,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x401b, 0x2079, 0x4700, 0x2071,
 	0x0010, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0001, 0x2009,
 	0x0002, 0x2071, 0x0050, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003,
 	0x0000, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1128, 0x8109, 0x0118,
-	0x2071, 0x0020, 0x0c80, 0x0005, 0x7004, 0x8004, 0x1a04, 0x408a,
+	0x2071, 0x0020, 0x0c80, 0x0005, 0x7004, 0x8004, 0x1a04, 0x40b2,
 	0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0, 0x0120, 0x080c,
-	0x40e6, 0x0804, 0x40aa, 0x7007, 0x0012, 0x2019, 0x0000, 0x7108,
-	0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0, 0x0120, 0x080c, 0x40e6,
-	0x0804, 0x40aa, 0xa19c, 0x300c, 0xa386, 0x2004, 0x0190, 0xa386,
+	0x410e, 0x0804, 0x40d2, 0x7007, 0x0012, 0x2019, 0x0000, 0x7108,
+	0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0, 0x0120, 0x080c, 0x410e,
+	0x0804, 0x40d2, 0xa19c, 0x300c, 0xa386, 0x2004, 0x0190, 0xa386,
 	0x0008, 0x01c0, 0x7004, 0xd084, 0x1148, 0x7108, 0x7008, 0xa106,
-	0x1de0, 0xa184, 0x0003, 0x0110, 0x0804, 0x40e6, 0xa386, 0x200c,
+	0x1de0, 0xa184, 0x0003, 0x0110, 0x0804, 0x410e, 0xa386, 0x200c,
 	0x19f0, 0x7200, 0x8204, 0x0230, 0x730c, 0xa384, 0x07ff, 0x0110,
-	0x080c, 0x254c, 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0,
-	0x0118, 0x080c, 0x40e6, 0x0470, 0x7007, 0x0012, 0x7000, 0xd084,
+	0x080c, 0x2575, 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0,
+	0x0118, 0x080c, 0x410e, 0x0470, 0x7007, 0x0012, 0x7000, 0xd084,
 	0x1148, 0x7310, 0x7014, 0xa305, 0x0128, 0x710c, 0xa184, 0x07ff,
-	0x1904, 0x4034, 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0,
-	0x0118, 0x080c, 0x40e6, 0x00b0, 0x7007, 0x0012, 0x7007, 0x0008,
+	0x1904, 0x405c, 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0,
+	0x0118, 0x080c, 0x410e, 0x00b0, 0x7007, 0x0012, 0x7007, 0x0008,
 	0x7004, 0xd09c, 0x1de8, 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184,
-	0x01e0, 0x0118, 0x080c, 0x40e6, 0x0028, 0x7007, 0x0012, 0x7108,
+	0x01e0, 0x0118, 0x080c, 0x410e, 0x0028, 0x7007, 0x0012, 0x7108,
 	0x8103, 0x0e88, 0x7003, 0x0008, 0x0005, 0x7108, 0xa184, 0x01e0,
 	0x15a8, 0x7108, 0xa184, 0x01e0, 0x1588, 0xa184, 0x0007, 0x0002,
-	0x40c2, 0x40d0, 0x40c0, 0x40d0, 0x40c0, 0x4120, 0x40c0, 0x411e,
-	0x080c, 0x254c, 0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x8aff,
-	0x1118, 0x2049, 0x0000, 0x0005, 0x080c, 0x426b, 0x1de8, 0x0005,
+	0x40ea, 0x40f8, 0x40e8, 0x40f8, 0x40e8, 0x4148, 0x40e8, 0x4146,
+	0x080c, 0x2575, 0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x8aff,
+	0x1118, 0x2049, 0x0000, 0x0005, 0x080c, 0x429a, 0x1de8, 0x0005,
 	0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x7004, 0xd084, 0x1140,
 	0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x0003, 0x0108, 0x0030,
-	0x8aff, 0x0118, 0x080c, 0x426b, 0x1de8, 0x0005, 0x7007, 0x0012,
-	0x7108, 0x1d04, 0x40e9, 0x2091, 0x6000, 0x1d04, 0x40ed, 0x2091,
+	0x8aff, 0x0118, 0x080c, 0x429a, 0x1de8, 0x0005, 0x7007, 0x0012,
+	0x7108, 0x1d04, 0x4111, 0x2091, 0x6000, 0x1d04, 0x4115, 0x2091,
 	0x6000, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xd09c, 0x1de8,
 	0x7007, 0x0012, 0x7108, 0xd1fc, 0x1dd8, 0x7003, 0x0000, 0x7000,
 	0xa005, 0x1130, 0x7004, 0xa005, 0x1118, 0x700c, 0xa005, 0x0108,
 	0x0c40, 0x2049, 0x0000, 0xb284, 0x0200, 0x0118, 0x2001, 0x0000,
-	0x0010, 0x2001, 0x0001, 0x080c, 0x3b81, 0x681b, 0x0002, 0x2051,
-	0x0000, 0x0005, 0x080c, 0x254c, 0x080c, 0x254c, 0x080c, 0x415f,
+	0x0010, 0x2001, 0x0001, 0x080c, 0x3ba7, 0x681b, 0x0002, 0x2051,
+	0x0000, 0x0005, 0x080c, 0x2575, 0x080c, 0x2575, 0x080c, 0x4187,
 	0x7210, 0x7114, 0x700c, 0xa09c, 0x07ff, 0x2800, 0xa300, 0xa211,
 	0xa189, 0x0000, 0x04a1, 0x2704, 0x2c58, 0xac60, 0x6308, 0x2200,
 	0xa322, 0x630c, 0x2100, 0xa31b, 0x2400, 0xa305, 0x0140, 0x1238,
 	0x8412, 0x8210, 0x830a, 0xa189, 0x0000, 0x2b60, 0x0c58, 0x2b60,
-	0x8a07, 0x0006, 0x6004, 0xd09c, 0x0118, 0xa7ba, 0x3fef, 0x0010,
-	0xa7ba, 0x3fe7, 0x000e, 0xa73d, 0x2c00, 0x6886, 0x6f8a, 0x6c92,
+	0x8a07, 0x0006, 0x6004, 0xd09c, 0x0118, 0xa7ba, 0x4017, 0x0010,
+	0xa7ba, 0x400f, 0x000e, 0xa73d, 0x2c00, 0x6886, 0x6f8a, 0x6c92,
 	0x6b8e, 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0, 0x0110,
-	0x080c, 0x40e6, 0x7007, 0x0012, 0x080c, 0x4034, 0x0005, 0x8a50,
+	0x080c, 0x410e, 0x7007, 0x0012, 0x080c, 0x405c, 0x0005, 0x8a50,
 	0x8739, 0x2704, 0xa004, 0x1168, 0x6000, 0xa064, 0x1108, 0x2d60,
-	0x6004, 0xa084, 0x000f, 0xa080, 0x4005, 0x203c, 0x87fb, 0x090c,
-	0x254c, 0x0005, 0x0126, 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004,
+	0x6004, 0xa084, 0x000f, 0xa080, 0x402d, 0x203c, 0x87fb, 0x090c,
+	0x2575, 0x0005, 0x0126, 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004,
 	0x2090, 0x00de, 0x6884, 0x2060, 0x6888, 0x6b8c, 0x6c90, 0x8057,
 	0xaad4, 0x00ff, 0xa084, 0x00ff, 0x0006, 0x6804, 0xa084, 0x0008,
-	0x000e, 0x0118, 0xa0b8, 0x3fef, 0x0010, 0xa0b8, 0x3fe7, 0xb284,
+	0x000e, 0x0118, 0xa0b8, 0x4017, 0x0010, 0xa0b8, 0x400f, 0xb284,
 	0x0200, 0x0110, 0x7e20, 0x0008, 0x7e24, 0xa6b5, 0x000c, 0x681c,
-	0xd0b4, 0x0108, 0xc685, 0x2400, 0xa305, 0x0518, 0x2c58, 0x2704,
-	0x6104, 0xac60, 0x6000, 0xa400, 0x701a, 0x6004, 0xa301, 0x701e,
-	0xd19c, 0x0140, 0x6010, 0xa081, 0x0000, 0x7022, 0x6014, 0xa081,
-	0x0000, 0x7026, 0x6208, 0x2400, 0xa202, 0x7012, 0x620c, 0x2300,
-	0xa203, 0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x080c, 0x4292,
-	0x0010, 0x080c, 0x426b, 0x1de8, 0x012e, 0x2000, 0x0005, 0x0126,
-	0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de, 0x7007,
-	0x0004, 0x7004, 0xd094, 0x1de8, 0x7003, 0x0008, 0x012e, 0x2000,
-	0x0005, 0x0126, 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090,
-	0x00de, 0x7e20, 0xb284, 0x0200, 0x1108, 0x7e24, 0xa6b5, 0x000c,
-	0x681c, 0xd0ac, 0x1118, 0xc685, 0x7003, 0x0000, 0x6828, 0x2050,
-	0x2d60, 0x6004, 0xa0bc, 0x000f, 0xa7b8, 0x3ff5, 0x273c, 0x87fb,
-	0x1138, 0x0210, 0x080c, 0x254c, 0x689c, 0xa065, 0x0120, 0x0c88,
-	0x080c, 0x426b, 0x1de8, 0x012e, 0x2000, 0x0005, 0x0126, 0x0006,
-	0x0016, 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x7e20,
-	0xb284, 0x0200, 0x1108, 0x7e24, 0x00de, 0x003e, 0x004e, 0xa6b5,
-	0x000c, 0x681c, 0xd0b4, 0x0128, 0xc685, 0x7003, 0x0000, 0x7007,
-	0x0004, 0x2049, 0x4206, 0x6828, 0xa055, 0x00d6, 0x0904, 0x4267,
-	0x2d70, 0x2e60, 0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x3ff5, 0x273c,
-	0x87fb, 0x1140, 0x0210, 0x080c, 0x254c, 0x709c, 0xa075, 0x2060,
-	0x0570, 0x0c80, 0x2704, 0xae68, 0x6808, 0xa422, 0x680c, 0xa31b,
-	0x0268, 0x8a51, 0x1110, 0x080c, 0x254c, 0x8738, 0x2704, 0xa005,
-	0x1d90, 0x709c, 0xa075, 0x2060, 0x01d0, 0x08e0, 0x8422, 0x8420,
-	0x831a, 0xa399, 0x0000, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300,
-	0xa11b, 0x1210, 0x080c, 0x254c, 0xb284, 0x0200, 0x0118, 0x2071,
-	0x0050, 0x0010, 0x2071, 0x0020, 0x00de, 0x0804, 0x419b, 0x00de,
-	0x012e, 0x2000, 0x0005, 0x7008, 0x0006, 0xa084, 0x01e0, 0x000e,
-	0x0110, 0xa006, 0x0005, 0xa084, 0x0003, 0xa086, 0x0003, 0x1108,
-	0x0005, 0x2704, 0xac78, 0x7800, 0x701a, 0x7804, 0x701e, 0x7808,
-	0x7012, 0x780c, 0x7016, 0x6004, 0xd09c, 0x0120, 0x7810, 0x7022,
-	0x7814, 0x7026, 0x7602, 0x7004, 0xa084, 0x0010, 0xc085, 0x7006,
-	0x2079, 0x4600, 0x8a51, 0x01e8, 0x8738, 0x2704, 0xa005, 0x1168,
-	0x609c, 0xa005, 0x01b8, 0x2060, 0x6004, 0xa084, 0x000f, 0xa080,
-	0x3ff5, 0x203c, 0x87fb, 0x090c, 0x254c, 0x7008, 0x0006, 0xa084,
-	0x01e0, 0x000e, 0x0110, 0xa006, 0x0028, 0xa084, 0x0003, 0xa086,
-	0x0003, 0x0005, 0x2051, 0x0000, 0x0005, 0x0126, 0x0006, 0x00d6,
-	0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de, 0x008e, 0x7108,
-	0xa184, 0x0003, 0x1128, 0x6828, 0xa005, 0x0178, 0x0804, 0x3f45,
-	0x7108, 0xd1fc, 0x0118, 0x080c, 0x40ae, 0x0c88, 0x7007, 0x0010,
-	0x7108, 0xd1fc, 0x0de8, 0x080c, 0x40ae, 0x7008, 0xa086, 0x0008,
-	0x1d30, 0x7000, 0xa005, 0x1d18, 0x7003, 0x0000, 0x2049, 0x0000,
-	0x0006, 0x2001, 0x4601, 0x2004, 0xd0cc, 0x0110, 0x080c, 0x4328,
-	0x000e, 0x012e, 0x2000, 0x0005, 0x0126, 0x0146, 0x0136, 0x0156,
-	0x00c6, 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de,
-	0x2049, 0x42ec, 0xad80, 0x0011, 0x20a0, 0xb284, 0x0200, 0x0118,
-	0x2099, 0x0032, 0x0010, 0x2099, 0x0031, 0x700c, 0xa084, 0x07ff,
-	0x682a, 0x7007, 0x0008, 0x7007, 0x0002, 0x7003, 0x0001, 0x0118,
-	0x8000, 0x80ac, 0x53a5, 0x700c, 0xa084, 0x07ff, 0x0130, 0x7007,
-	0x0004, 0x7004, 0xa084, 0x0004, 0x1de0, 0x00ce, 0x2049, 0x0000,
-	0x7003, 0x0000, 0x015e, 0x013e, 0x014e, 0x012e, 0x2000, 0x0005,
-	0x6814, 0xd0fc, 0x0904, 0x436b, 0x7000, 0xd084, 0x05e0, 0x7e24,
-	0xa6b5, 0x0004, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x1de0,
-	0x7118, 0x0016, 0x711c, 0x0016, 0x7120, 0x0016, 0x7124, 0x0016,
-	0x701b, 0x0000, 0x701f, 0x3fff, 0x7023, 0x0000, 0x7027, 0x0000,
-	0x7013, 0x0004, 0x7017, 0x0000, 0x7602, 0x7007, 0x0001, 0x2001,
-	0xffff, 0x2009, 0x0031, 0x200a, 0x200a, 0x7108, 0x7008, 0xa106,
-	0x1de0, 0xd1fc, 0x0dd0, 0x002e, 0x7226, 0x002e, 0x7222, 0x002e,
-	0x721e, 0x002e, 0x721a, 0x7007, 0x0002, 0x7008, 0xa086, 0x0008,
-	0x0110, 0x0804, 0x40e6, 0x7007, 0x0004, 0x7003, 0x0000, 0x0005,
-	0x2091, 0x8000, 0x2091, 0x6000, 0x78ac, 0xa005, 0x1168, 0x7974,
-	0x70d0, 0xa106, 0x1148, 0x781c, 0xa005, 0x0130, 0x781f, 0x0000,
-	0x0e04, 0x4384, 0x2091, 0x4080, 0x2069, 0x4680, 0xd7fc, 0x1110,
-	0x2069, 0x4640, 0x6800, 0xa084, 0x000f, 0x1198, 0x68d0, 0xd0b4,
-	0x0180, 0xd0bc, 0x1170, 0x00f6, 0x2079, 0x0100, 0xd7fc, 0x1110,
-	0x2079, 0x0200, 0x7830, 0xa084, 0x00c0, 0x1110, 0x080c, 0x22ae,
-	0x00fe, 0x7830, 0x8001, 0x7832, 0x1904, 0x440b, 0x7834, 0x7832,
-	0x2061, 0x6bc0, 0x2069, 0x4680, 0xc7fd, 0x68cc, 0xa005, 0x0128,
-	0x8001, 0x68ce, 0x1110, 0x080c, 0x4577, 0x6800, 0xa084, 0x000f,
-	0x0168, 0xa086, 0x0001, 0x0150, 0x6840, 0xa00d, 0x0138, 0x2104,
-	0xa005, 0x0120, 0x8001, 0x200a, 0x0904, 0x4514, 0x6814, 0xa005,
-	0x01a8, 0x8001, 0x6816, 0x1190, 0x68a3, 0x0001, 0x00f6, 0xd7fc,
-	0x1118, 0x2079, 0x0200, 0x0010, 0x2079, 0x0100, 0x080c, 0x3c46,
-	0x00fe, 0x6860, 0xa005, 0x0110, 0x080c, 0x22ae, 0x687c, 0xa005,
-	0x0140, 0x8001, 0x687e, 0x1128, 0x6863, 0x0000, 0x68d0, 0xc0c5,
-	0x68d2, 0x68d0, 0xd0fc, 0x01b0, 0xc0fc, 0x68d2, 0x20a9, 0x0200,
-	0x6034, 0xa005, 0x0158, 0x8001, 0x6036, 0x68d0, 0xc0fd, 0x68d2,
-	0x1128, 0x6010, 0xa005, 0x0110, 0x080c, 0x22ae, 0xace0, 0x0010,
-	0x1f04, 0x43f0, 0xd7fc, 0x0138, 0x2061, 0x4bc0, 0x2069, 0x4640,
-	0xc7fc, 0x0804, 0x43ad, 0x0459, 0x7838, 0x8001, 0x783a, 0x11a0,
-	0x783c, 0x783a, 0x2061, 0x4bc0, 0x2069, 0x4640, 0xc7fc, 0x680c,
-	0xa005, 0x0110, 0x080c, 0x4487, 0xd7fc, 0x1130, 0x2061, 0x6bc0,
-	0x2069, 0x4680, 0xc7fd, 0x0c98, 0x7810, 0xd0cc, 0x0168, 0xd0ac,
-	0x1120, 0xd0a4, 0x0148, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0e04,
-	0x4433, 0x080c, 0x207a, 0x0005, 0x2091, 0x8001, 0x0005, 0x7840,
-	0x8001, 0x7842, 0x1904, 0x4486, 0x7844, 0x7842, 0x2069, 0x4640,
-	0xc7fc, 0x2079, 0x0200, 0x68d4, 0xa005, 0x0138, 0x7de0, 0xa504,
-	0x1120, 0x68d6, 0x68d0, 0xc0bc, 0x68d2, 0x2079, 0x4600, 0x6810,
-	0xa005, 0x1110, 0x2001, 0x0101, 0x8001, 0x6812, 0xd7fc, 0x0118,
-	0xa080, 0x8cd0, 0x0010, 0xa080, 0x8bc0, 0x2040, 0x2004, 0xa065,
-	0x01e0, 0x6024, 0xa005, 0x01b0, 0x8001, 0x6026, 0x1198, 0x6800,
-	0xa005, 0x0130, 0x6848, 0xac06, 0x1118, 0x080c, 0x4514, 0x0068,
-	0x6860, 0xa005, 0x0118, 0x6027, 0x0001, 0x0020, 0x080c, 0x44c8,
-	0x2804, 0x0c28, 0x6000, 0x2c40, 0x0c10, 0xd7fc, 0x1138, 0x2069,
-	0x4680, 0xc7fd, 0x2079, 0x0100, 0x0804, 0x4443, 0x0005, 0x2009,
-	0x0000, 0x20a9, 0x0200, 0x6008, 0xd09c, 0x0558, 0x6024, 0xa005,
-	0x0118, 0x8001, 0x6026, 0x0418, 0x6008, 0xc09c, 0xd084, 0x1110,
-	0xd0ac, 0x01c0, 0x600a, 0x6004, 0xa005, 0x01d8, 0x00d6, 0x00c6,
-	0x0016, 0x2068, 0x6010, 0x8001, 0x6012, 0x080c, 0x37a4, 0x2d00,
-	0x2c68, 0x2060, 0x080c, 0x1be3, 0x080c, 0x1d95, 0x001e, 0x00ce,
-	0x00de, 0x0038, 0xc0bd, 0x600a, 0xa18d, 0x0001, 0x0010, 0xa18d,
-	0x0100, 0xace0, 0x0010, 0x1f04, 0x448b, 0xa184, 0x0001, 0x0130,
-	0xa18c, 0xfffe, 0x690e, 0x080c, 0x22ae, 0x0008, 0x690e, 0x0005,
-	0x2c00, 0x687a, 0x6714, 0x6f72, 0x6017, 0x0000, 0x602b, 0x0000,
-	0x601b, 0x0006, 0x60b4, 0xa084, 0x5f00, 0x601e, 0x6020, 0xa084,
-	0x00ff, 0xa085, 0x0060, 0x6022, 0x6000, 0x2042, 0x6858, 0xac06,
-	0x1110, 0x2800, 0x685a, 0x080c, 0x1b7b, 0x6818, 0xa005, 0x0110,
-	0x8001, 0x681a, 0x6808, 0xc0a4, 0x680a, 0x6810, 0x7908, 0x8109,
-	0x790a, 0x8001, 0x1310, 0x080c, 0x254c, 0x6812, 0x1118, 0x7910,
-	0xc1a5, 0x7912, 0x602f, 0x0000, 0x6033, 0x0000, 0x2c68, 0x080c,
-	0x1da2, 0xd7fc, 0x1118, 0x2069, 0x4640, 0x0010, 0x2069, 0x4680,
-	0x6910, 0xa184, 0x0100, 0x2001, 0x0006, 0x1118, 0x6976, 0x2001,
-	0x0004, 0x080c, 0x22a4, 0x0005, 0x00d6, 0x6948, 0x2160, 0xd7fc,
-	0x1118, 0x2069, 0x0200, 0x0010, 0x2069, 0x0100, 0x080c, 0x2467,
-	0x601b, 0x0006, 0x6858, 0xa084, 0x5f00, 0x601e, 0x6020, 0xa084,
-	0x00ff, 0xa085, 0x0048, 0x6022, 0x602f, 0x0000, 0x6033, 0x0000,
-	0x6808, 0xa084, 0xfffd, 0x680a, 0x6830, 0xd0b4, 0x01b0, 0x684b,
-	0x0004, 0x20a9, 0x0014, 0x6848, 0xd094, 0x0110, 0x1f04, 0x453b,
-	0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xd084, 0x0110, 0x1f04,
-	0x4544, 0x20a9, 0x00fa, 0x1f04, 0x454b, 0x681b, 0x0054, 0x00de,
-	0x6863, 0x0007, 0x0005, 0x2079, 0x4600, 0x00e1, 0x0089, 0x00a9,
-	0x2009, 0x0002, 0x2069, 0x4680, 0x680f, 0x0000, 0x6813, 0x0000,
-	0x6817, 0x0000, 0x8109, 0x0118, 0x2069, 0x4640, 0x0ca8, 0x0005,
-	0x2019, 0x00a3, 0x7b3a, 0x7b3e, 0x0005, 0x2019, 0x0033, 0x7b42,
-	0x7b46, 0x0005, 0x2019, 0x32dd, 0x7b32, 0x7b36, 0x0005, 0x6a4c,
-	0xa285, 0x0000, 0x01f0, 0x6950, 0x6bbc, 0xa300, 0x00c6, 0x2164,
-	0x6304, 0x83ff, 0x1138, 0x8211, 0x0148, 0x8108, 0xa11a, 0x0eb8,
-	0x69bc, 0x0ca8, 0x68cf, 0x000a, 0x00ce, 0x0005, 0x694c, 0x6abc,
-	0x2264, 0x6008, 0xc0b5, 0x600a, 0x8210, 0x8109, 0x1dc8, 0x694e,
-	0x00ce, 0x0005, 0x1d04, 0x459a, 0x2091, 0x6000, 0x1d04, 0x459e,
-	0x2091, 0x6000, 0x70ec, 0xd0dc, 0x1118, 0xd0d4, 0x0190, 0x0098,
-	0xae8e, 0x0100, 0x0138, 0x7814, 0xc0f5, 0xc0c5, 0x7816, 0xd0d4,
-	0x1578, 0x0458, 0x7814, 0xc0fd, 0xc0c5, 0x7816, 0xd0d4, 0x1540,
-	0x0420, 0xd0e4, 0x0538, 0x1d04, 0x45bb, 0x2091, 0x6000, 0x2009,
-	0x000c, 0x1d04, 0x45c1, 0x2091, 0x6000, 0x8109, 0x1dd0, 0x70e4,
-	0xa084, 0x01ff, 0xa086, 0x01ff, 0x1110, 0x70ec, 0x08c8, 0xae8e,
-	0x0100, 0x0128, 0x7814, 0xc0f4, 0xd0fc, 0x1130, 0x0020, 0x7814,
-	0xc0fc, 0xd0f4, 0x1108, 0xc0c4, 0x7816, 0x7804, 0xd08c, 0x0110,
-	0x681f, 0x000c, 0x70a0, 0x70a2, 0x0005, 0x7c12
+	0xd0b4, 0x0108, 0xc685, 0x2400, 0xa305, 0x0550, 0x2c58, 0x2704,
+	0x6104, 0xac60, 0x6000, 0xa400, 0x2048, 0xa9cc, 0x0004, 0x0118,
+	0x080c, 0x43a3, 0x0400, 0x701a, 0x6004, 0xa301, 0x701e, 0xd19c,
+	0x0140, 0x6010, 0xa081, 0x0000, 0x7022, 0x6014, 0xa081, 0x0000,
+	0x7026, 0x6208, 0x2400, 0xa202, 0x7012, 0x620c, 0x2300, 0xa203,
+	0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x080c, 0x42c5, 0x0010,
+	0x080c, 0x429a, 0x1de8, 0x012e, 0x2000, 0x0005, 0x0126, 0x00d6,
+	0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de, 0x7007, 0x0004,
+	0x7004, 0xd094, 0x1de8, 0x7003, 0x0008, 0x012e, 0x2000, 0x0005,
+	0x0126, 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de,
+	0x7e20, 0xb284, 0x0200, 0x1108, 0x7e24, 0xa6b5, 0x000c, 0x681c,
+	0xd0ac, 0x1118, 0xc685, 0x7003, 0x0000, 0x6828, 0x2050, 0x2d60,
+	0x6004, 0xa0bc, 0x000f, 0xa7b8, 0x401d, 0x273c, 0x87fb, 0x1138,
+	0x0210, 0x080c, 0x2575, 0x689c, 0xa065, 0x0120, 0x0c88, 0x080c,
+	0x429a, 0x1de8, 0x012e, 0x2000, 0x0005, 0x0126, 0x0006, 0x0016,
+	0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x7e20, 0xb284,
+	0x0200, 0x1108, 0x7e24, 0x00de, 0x003e, 0x004e, 0xa6b5, 0x000c,
+	0x681c, 0xd0b4, 0x0128, 0xc685, 0x7003, 0x0000, 0x7007, 0x0004,
+	0x2049, 0x4235, 0x6828, 0xa055, 0x00d6, 0x0904, 0x4296, 0x2d70,
+	0x2e60, 0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x401d, 0x273c, 0x87fb,
+	0x1140, 0x0210, 0x080c, 0x2575, 0x709c, 0xa075, 0x2060, 0x0570,
+	0x0c80, 0x2704, 0xae68, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0268,
+	0x8a51, 0x1110, 0x080c, 0x2575, 0x8738, 0x2704, 0xa005, 0x1d90,
+	0x709c, 0xa075, 0x2060, 0x01d0, 0x08e0, 0x8422, 0x8420, 0x831a,
+	0xa399, 0x0000, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b,
+	0x1210, 0x080c, 0x2575, 0xb284, 0x0200, 0x0118, 0x2071, 0x0050,
+	0x0010, 0x2071, 0x0020, 0x00de, 0x0804, 0x41c3, 0x00de, 0x012e,
+	0x2000, 0x0005, 0x7008, 0x0006, 0xa084, 0x01e0, 0x000e, 0x0110,
+	0xa006, 0x0005, 0xa084, 0x0003, 0xa086, 0x0003, 0x1108, 0x0005,
+	0x2704, 0xac78, 0x7800, 0x2f08, 0xd094, 0x1904, 0x43a6, 0x701a,
+	0x7804, 0x701e, 0x7808, 0x7012, 0x780c, 0x7016, 0x6004, 0xd09c,
+	0x0120, 0x7810, 0x7022, 0x7814, 0x7026, 0x7602, 0x7004, 0xa084,
+	0x0010, 0xc085, 0x7006, 0x2079, 0x4700, 0x8a51, 0x01e8, 0x8738,
+	0x2704, 0xa005, 0x1168, 0x609c, 0xa005, 0x01b8, 0x2060, 0x6004,
+	0xa084, 0x000f, 0xa080, 0x401d, 0x203c, 0x87fb, 0x090c, 0x2575,
+	0x7008, 0x0006, 0xa084, 0x01e0, 0x000e, 0x0110, 0xa006, 0x0028,
+	0xa084, 0x0003, 0xa086, 0x0003, 0x0005, 0x2051, 0x0000, 0x0005,
+	0x0126, 0x0006, 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090,
+	0x00de, 0x008e, 0x7108, 0xa184, 0x0003, 0x1128, 0x6828, 0xa005,
+	0x0178, 0x0804, 0x3f6d, 0x7108, 0xd1fc, 0x0118, 0x080c, 0x40d6,
+	0x0c88, 0x7007, 0x0010, 0x7108, 0xd1fc, 0x0de8, 0x080c, 0x40d6,
+	0x7008, 0xa086, 0x0008, 0x1d30, 0x7000, 0xa005, 0x1d18, 0x7003,
+	0x0000, 0x2049, 0x0000, 0x0006, 0x2001, 0x4701, 0x2004, 0xd0cc,
+	0x0110, 0x080c, 0x435b, 0x000e, 0x012e, 0x2000, 0x0005, 0x0126,
+	0x0146, 0x0136, 0x0156, 0x00c6, 0x00d6, 0x70d0, 0xa084, 0x4c00,
+	0x8004, 0x2090, 0x00de, 0x2049, 0x431f, 0xad80, 0x0011, 0x20a0,
+	0xb284, 0x0200, 0x0118, 0x2099, 0x0032, 0x0010, 0x2099, 0x0031,
+	0x700c, 0xa084, 0x07ff, 0x682a, 0x7007, 0x0008, 0x7007, 0x0002,
+	0x7003, 0x0001, 0x0118, 0x8000, 0x80ac, 0x53a5, 0x700c, 0xa084,
+	0x07ff, 0x0130, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x1de0,
+	0x00ce, 0x2049, 0x0000, 0x7003, 0x0000, 0x015e, 0x013e, 0x014e,
+	0x012e, 0x2000, 0x0005, 0x6814, 0xd0fc, 0x0904, 0x439e, 0x7000,
+	0xd084, 0x05e0, 0x7e24, 0xa6b5, 0x0004, 0x7007, 0x0004, 0x7004,
+	0xa084, 0x0004, 0x1de0, 0x7118, 0x0016, 0x711c, 0x0016, 0x7120,
+	0x0016, 0x7124, 0x0016, 0x701b, 0x0000, 0x701f, 0x3fff, 0x7023,
+	0x0000, 0x7027, 0x0000, 0x7013, 0x0004, 0x7017, 0x0000, 0x7602,
+	0x7007, 0x0001, 0x2001, 0xffff, 0x2009, 0x0031, 0x200a, 0x200a,
+	0x7108, 0x7008, 0xa106, 0x1de0, 0xd1fc, 0x0dd0, 0x002e, 0x7226,
+	0x002e, 0x7222, 0x002e, 0x721e, 0x002e, 0x721a, 0x7007, 0x0002,
+	0x7008, 0xa086, 0x0008, 0x0110, 0x0804, 0x410e, 0x7007, 0x0004,
+	0x7003, 0x0000, 0x0005, 0x2049, 0x41c3, 0x0068, 0x7008, 0xa084,
+	0x0003, 0x0110, 0xa006, 0x0005, 0xa006, 0x2020, 0x2018, 0x2c58,
+	0x2160, 0x2049, 0x0000, 0x8b58, 0x6100, 0x2100, 0xa408, 0x711a,
+	0x6004, 0xa301, 0x701e, 0x0006, 0x2b04, 0xa084, 0x0008, 0x0150,
+	0x6010, 0xa081, 0x0000, 0x7022, 0x0006, 0x6014, 0xa081, 0x0000,
+	0x7026, 0x0006, 0xa184, 0x0007, 0x2011, 0x0008, 0xa22a, 0x6208,
+	0x2400, 0xa212, 0x0026, 0x620c, 0x2240, 0x2300, 0xa843, 0x002e,
+	0x88ff, 0x1170, 0x2500, 0xa202, 0x0108, 0x1250, 0x2220, 0x2041,
+	0x0000, 0x2b04, 0xd09c, 0x0110, 0x000e, 0x000e, 0x000e, 0x0450,
+	0x7512, 0x7017, 0x0000, 0x7602, 0xa986, 0x41c3, 0x1118, 0x7007,
+	0x0001, 0x0028, 0x7004, 0xa084, 0x0010, 0xc085, 0x7006, 0x2500,
+	0xa100, 0x701a, 0x2b04, 0xa084, 0x0008, 0x0110, 0x000e, 0x004e,
+	0x001e, 0xa189, 0x0000, 0x711e, 0x2b0c, 0xa18c, 0x0008, 0x0130,
+	0xa4a1, 0x0000, 0x7422, 0xa081, 0x0000, 0x7026, 0x2500, 0xa222,
+	0xa8c3, 0x0000, 0x7412, 0x2820, 0x7416, 0x7602, 0xa986, 0x41c3,
+	0x1118, 0x7007, 0x0001, 0x0028, 0x7004, 0xa084, 0x0010, 0xc085,
+	0x7006, 0x8b59, 0x2b60, 0x2079, 0x4700, 0x080c, 0x42c5, 0xa006,
+	0x0005, 0x2091, 0x8000, 0x2091, 0x6000, 0x78ac, 0xa005, 0x1168,
+	0x7974, 0x70d0, 0xa106, 0x1148, 0x781c, 0xa005, 0x0130, 0x781f,
+	0x0000, 0x0e04, 0x443d, 0x2091, 0x4080, 0x2069, 0x4780, 0xc7fd,
+	0x6800, 0xa084, 0x000f, 0x1198, 0x68d0, 0xd0b4, 0x0180, 0xd0bc,
+	0x1170, 0x00f6, 0x2079, 0x0100, 0xd7fc, 0x1110, 0x2079, 0x0200,
+	0x7830, 0xa084, 0x00c0, 0x1110, 0x080c, 0x22d5, 0x00fe, 0xd7fc,
+	0x0120, 0x2069, 0x4740, 0xc7fc, 0x0c18, 0x7830, 0x8001, 0x7832,
+	0x1904, 0x44c7, 0x7834, 0x7832, 0x2061, 0x6cc0, 0x2069, 0x4780,
+	0xc7fd, 0x68cc, 0xa005, 0x0128, 0x8001, 0x68ce, 0x1110, 0x080c,
+	0x4639, 0x6800, 0xa084, 0x000f, 0x0168, 0xa086, 0x0001, 0x0150,
+	0x6840, 0xa00d, 0x0138, 0x2104, 0xa005, 0x0120, 0x8001, 0x200a,
+	0x0904, 0x45d6, 0x6814, 0xa005, 0x01a8, 0x8001, 0x6816, 0x1190,
+	0x68a3, 0x0001, 0x00f6, 0xd7fc, 0x1118, 0x2079, 0x0200, 0x0010,
+	0x2079, 0x0100, 0x080c, 0x3c6e, 0x00fe, 0x6860, 0xa005, 0x0110,
+	0x080c, 0x22d5, 0x687c, 0xa005, 0x0140, 0x8001, 0x687e, 0x1128,
+	0x6863, 0x0000, 0x68d0, 0xc0c5, 0x68d2, 0x68d0, 0xd0fc, 0x01b0,
+	0xc0fc, 0x68d2, 0x20a9, 0x0200, 0x6034, 0xa005, 0x0158, 0x8001,
+	0x6036, 0x68d0, 0xc0fd, 0x68d2, 0x1128, 0x6010, 0xa005, 0x0110,
+	0x080c, 0x22d5, 0xace0, 0x0010, 0x1f04, 0x44ac, 0xd7fc, 0x0138,
+	0x2061, 0x4cc0, 0x2069, 0x4740, 0xc7fc, 0x0804, 0x4469, 0x0459,
+	0x7838, 0x8001, 0x783a, 0x11a0, 0x783c, 0x783a, 0x2061, 0x4cc0,
+	0x2069, 0x4740, 0xc7fc, 0x680c, 0xa005, 0x0110, 0x080c, 0x4543,
+	0xd7fc, 0x1130, 0x2061, 0x6cc0, 0x2069, 0x4780, 0xc7fd, 0x0c98,
+	0x7810, 0xd0cc, 0x0168, 0xd0ac, 0x1120, 0xd0a4, 0x0148, 0xc0ad,
+	0x7812, 0x2091, 0x8001, 0x0e04, 0x44ef, 0x080c, 0x20a1, 0x0005,
+	0x2091, 0x8001, 0x0005, 0x7840, 0x8001, 0x7842, 0x1904, 0x4542,
+	0x7844, 0x7842, 0x2069, 0x4740, 0xc7fc, 0x2079, 0x0200, 0x68d4,
+	0xa005, 0x0138, 0x7de0, 0xa504, 0x1120, 0x68d6, 0x68d0, 0xc0bc,
+	0x68d2, 0x2079, 0x4700, 0x6810, 0xa005, 0x1110, 0x2001, 0x0101,
+	0x8001, 0x6812, 0xd7fc, 0x0118, 0xa080, 0x8dd0, 0x0010, 0xa080,
+	0x8cc0, 0x2040, 0x2004, 0xa065, 0x01e0, 0x6024, 0xa005, 0x01b0,
+	0x8001, 0x6026, 0x1198, 0x6800, 0xa005, 0x0130, 0x6848, 0xac06,
+	0x1118, 0x080c, 0x45d6, 0x0068, 0x6860, 0xa005, 0x0118, 0x6027,
+	0x0001, 0x0020, 0x080c, 0x4584, 0x2804, 0x0c28, 0x6000, 0x2c40,
+	0x0c10, 0xd7fc, 0x1138, 0x2069, 0x4780, 0xc7fd, 0x2079, 0x0100,
+	0x0804, 0x44ff, 0x0005, 0x2009, 0x0000, 0x20a9, 0x0200, 0x6008,
+	0xd09c, 0x0558, 0x6024, 0xa005, 0x0118, 0x8001, 0x6026, 0x0418,
+	0x6008, 0xc09c, 0xd084, 0x1110, 0xd0ac, 0x01c0, 0x600a, 0x6004,
+	0xa005, 0x01d8, 0x00d6, 0x00c6, 0x0016, 0x2068, 0x6010, 0x8001,
+	0x6012, 0x080c, 0x37c7, 0x2d00, 0x2c68, 0x2060, 0x080c, 0x1c02,
+	0x080c, 0x1db2, 0x001e, 0x00ce, 0x00de, 0x0038, 0xc0bd, 0x600a,
+	0xa18d, 0x0001, 0x0010, 0xa18d, 0x0100, 0xace0, 0x0010, 0x1f04,
+	0x4547, 0xa184, 0x0001, 0x0130, 0xa18c, 0xfffe, 0x690e, 0x080c,
+	0x22d5, 0x0008, 0x690e, 0x0005, 0x2c00, 0x687a, 0x6714, 0x6f72,
+	0x6017, 0x0000, 0x602b, 0x0000, 0x601b, 0x0006, 0x60b4, 0xa084,
+	0x5f00, 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085, 0x0060, 0x6022,
+	0x6000, 0x2042, 0x2069, 0x4780, 0xd7fc, 0x1110, 0x2069, 0x4740,
+	0x6858, 0xac06, 0x1110, 0x2800, 0x685a, 0x080c, 0x1b9a, 0x6818,
+	0xa005, 0x0110, 0x8001, 0x681a, 0x6808, 0xc0a4, 0x680a, 0x6810,
+	0x7908, 0x8109, 0x790a, 0x8001, 0x1310, 0x080c, 0x2575, 0x6812,
+	0x1118, 0x7910, 0xc1a5, 0x7912, 0x602f, 0x0000, 0x6033, 0x0000,
+	0x2c68, 0x080c, 0x1dbf, 0xd7fc, 0x1118, 0x2069, 0x4740, 0x0010,
+	0x2069, 0x4780, 0x6910, 0xa184, 0x0100, 0x2001, 0x0006, 0x1118,
+	0x6976, 0x2001, 0x0004, 0x080c, 0x22cb, 0x0005, 0x00d6, 0x6948,
+	0x2160, 0xd7fc, 0x1118, 0x2069, 0x0200, 0x0010, 0x2069, 0x0100,
+	0x080c, 0x2490, 0x601b, 0x0006, 0x6858, 0xa084, 0x5f00, 0x601e,
+	0x6020, 0xa084, 0x00ff, 0xa085, 0x0048, 0x6022, 0x602f, 0x0000,
+	0x6033, 0x0000, 0x6808, 0xa084, 0xfffd, 0x680a, 0x6830, 0xd0b4,
+	0x01b0, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, 0xd094, 0x0110,
+	0x1f04, 0x45fd, 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xd084,
+	0x0110, 0x1f04, 0x4606, 0x20a9, 0x00fa, 0x1f04, 0x460d, 0x681b,
+	0x0054, 0x00de, 0x6863, 0x0007, 0x0005, 0x2079, 0x4700, 0x00e1,
+	0x0089, 0x00a9, 0x2009, 0x0002, 0x2069, 0x4780, 0x680f, 0x0000,
+	0x6813, 0x0000, 0x6817, 0x0000, 0x8109, 0x0118, 0x2069, 0x4740,
+	0x0ca8, 0x0005, 0x2019, 0x00a3, 0x7b3a, 0x7b3e, 0x0005, 0x2019,
+	0x0033, 0x7b42, 0x7b46, 0x0005, 0x2019, 0x32dd, 0x7b32, 0x7b36,
+	0x0005, 0x6a4c, 0xa285, 0x0000, 0x01f0, 0x6950, 0x6bbc, 0xa300,
+	0x00c6, 0x2164, 0x6304, 0x83ff, 0x1138, 0x8211, 0x0148, 0x8108,
+	0xa11a, 0x0eb8, 0x69bc, 0x0ca8, 0x68cf, 0x000a, 0x00ce, 0x0005,
+	0x694c, 0x6abc, 0x2264, 0x6008, 0xc0b5, 0x600a, 0x8210, 0x8109,
+	0x1dc8, 0x694e, 0x00ce, 0x0005, 0x0016, 0x1d04, 0x465d, 0x2091,
+	0x6000, 0x1d04, 0x4661, 0x2091, 0x6000, 0x70ec, 0xd0dc, 0x1118,
+	0xd0d4, 0x0190, 0x00a0, 0xae8e, 0x0100, 0x0138, 0x7814, 0xc0f5,
+	0xc0c5, 0x7816, 0xd0d4, 0x1580, 0x0460, 0x7814, 0xc0fd, 0xc0c5,
+	0x7816, 0xd0d4, 0x1548, 0x0428, 0xd0e4, 0x0904, 0x46c4, 0x1d04,
+	0x467f, 0x2091, 0x6000, 0x2009, 0x000c, 0x1d04, 0x4685, 0x2091,
+	0x6000, 0x8109, 0x1dd0, 0x70e4, 0xa084, 0x01ff, 0xa086, 0x01ff,
+	0x1110, 0x70ec, 0x08c0, 0xae8e, 0x0100, 0x0128, 0x7814, 0xc0f4,
+	0xd0fc, 0x1130, 0x0020, 0x7814, 0xc0fc, 0xd0f4, 0x1108, 0xc0c4,
+	0x7816, 0x7804, 0xd08c, 0x0500, 0x00c6, 0x2061, 0x0000, 0x6018,
+	0xd084, 0x11b8, 0xae86, 0x0200, 0x00e6, 0x2071, 0x0010, 0x0120,
+	0x70db, 0x0001, 0x78e4, 0x0018, 0x70db, 0x0000, 0x78e0, 0x70c6,
+	0x70c3, 0x800e, 0x601b, 0x0001, 0x2091, 0x4080, 0x00ee, 0x00ce,
+	0x0018, 0x00ce, 0x681f, 0x000c, 0x001e, 0x70a0, 0x70a2, 0x0005,
+	0x0c26
 };
 #ifdef UNIQUE_FW_NAME
-static unsigned short   fw12160i_length01 = 0x35e6;
+static unsigned short fw12160i_length01 = 0x36c9;
 #else
-static unsigned short   risc_code_length01 = 0x35e6;
+static unsigned short risc_code_length01 = 0x36c9;
 #endif
+
diff --git a/drivers/scsi/ql1280_fw.h b/drivers/scsi/ql1280_fw.h
index 2621e99..784f2a0 100644
--- a/drivers/scsi/ql1280_fw.h
+++ b/drivers/scsi/ql1280_fw.h
@@ -23,25 +23,25 @@
 
 
 /*
- *	Firmware Version 8.15.00 (14:35 Aug 22, 2000)
+ *	Firmware Version 8.15.11 (10:20 Jan 02, 2002)
  */
 
 #ifdef UNIQUE_FW_NAME
-static unsigned char fw1280ei_version_str[] = {8,15,0};
+static unsigned char fw1280ei_version_str[] = {8,15,11};
 #else
-static unsigned char firmware_version[] = {8,15,0};
+static unsigned char firmware_version[] = {8,15,11};
 #endif
 
 #ifdef UNIQUE_FW_NAME
-#define fw1280ei_VERSION_STRING "8.15.00"
+#define fw1280ei_VERSION_STRING "8.15.11"
 #else
-#define FW_VERSION_STRING "8.15.00"
+#define FW_VERSION_STRING "8.15.11"
 #endif
 
 #ifdef UNIQUE_FW_NAME
-static unsigned short fw1280ei_addr01 = 0x1000;
+static unsigned short fw1280ei_addr01 = 0x1000 ;
 #else
-static unsigned short risc_code_addr01 = 0x1000;
+static unsigned short risc_code_addr01 = 0x1000 ;
 #endif
 
 #ifdef UNIQUE_FW_NAME
@@ -49,7 +49,7 @@
 #else
 static unsigned short risc_code01[] = {
 #endif
-	0x0078, 0x1041, 0x0000, 0x3d3b, 0x0000, 0x2043, 0x4f50, 0x5952,
+	0x0078, 0x1041, 0x0000, 0x3e2e, 0x0000, 0x2043, 0x4f50, 0x5952,
 	0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932, 0x2c31,
 	0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749, 0x4320,
 	0x434f, 0x5250, 0x4f52, 0x4154, 0x494f, 0x4e00, 0x2049, 0x5350,
@@ -57,7 +57,7 @@
 	0x6572, 0x7369, 0x6f6e, 0x2030, 0x382e, 0x3135, 0x2020, 0x2043,
 	0x7573, 0x746f, 0x6d65, 0x7220, 0x4e6f, 0x2e20, 0x3030, 0x2050,
 	0x726f, 0x6475, 0x6374, 0x204e, 0x6f2e, 0x2020, 0x3030, 0x2020,
-	0x2400, 0x20c9, 0x97ff, 0x2001, 0x04fc, 0x2004, 0xa086, 0x1080,
+	0x2400, 0x20c9, 0x98ff, 0x2001, 0x04fc, 0x2004, 0xa086, 0x1080,
 	0x00c0, 0x1054, 0x2071, 0x0100, 0x70a0, 0x70a2, 0x20c1, 0x0010,
 	0x2089, 0x1374, 0x0078, 0x106d, 0x2001, 0x04fc, 0x2004, 0xa086,
 	0x1280, 0x00c0, 0x1069, 0x2071, 0x0200, 0x70a0, 0x70a2, 0x2071,
@@ -70,1660 +70,1670 @@
 	0xa286, 0xa5a5, 0x0040, 0x10a4, 0xa386, 0x000f, 0x0040, 0x10a0,
 	0x2c6a, 0x2a5a, 0x20c1, 0x0020, 0x2019, 0x000f, 0x0078, 0x1080,
 	0x2c6a, 0x2a5a, 0x0078, 0x10a2, 0x2c6a, 0x2a5a, 0x2130, 0x2128,
-	0xa1a2, 0x4e00, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424,
-	0xa192, 0x9800, 0x2009, 0x0000, 0x2001, 0x0032, 0x1078, 0x207a,
-	0x2218, 0x2079, 0x4e00, 0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9,
+	0xa1a2, 0x4f00, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424,
+	0xa192, 0x9900, 0x2009, 0x0000, 0x2001, 0x0032, 0x1078, 0x20c1,
+	0x2218, 0x2079, 0x4f00, 0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9,
 	0x0040, 0x42a4, 0x8109, 0x00c0, 0x10bf, 0x2009, 0xff00, 0x3400,
 	0xa102, 0x0048, 0x10cf, 0x0040, 0x10cf, 0x20a8, 0x42a4, 0x2001,
 	0x04fc, 0x2004, 0xa086, 0x1080, 0x00c0, 0x10e5, 0x2071, 0x0100,
-	0x0d7e, 0x2069, 0x4e40, 0x1078, 0x4cdd, 0x0d7f, 0x7810, 0xc0ed,
+	0x0d7e, 0x2069, 0x4f40, 0x1078, 0x4db0, 0x0d7f, 0x7810, 0xc0ed,
 	0x7812, 0x781b, 0x0064, 0x0078, 0x110a, 0x2001, 0x04fc, 0x2004,
 	0xa086, 0x1280, 0x00c0, 0x1105, 0x7814, 0xc0ed, 0xc0d5, 0x7816,
-	0x781b, 0x0064, 0x2071, 0x0200, 0x0d7e, 0x2069, 0x4e40, 0x1078,
-	0x4cdd, 0x2069, 0x4e80, 0x2071, 0x0100, 0x1078, 0x4cdd, 0x7814,
+	0x781b, 0x0064, 0x2071, 0x0200, 0x0d7e, 0x2069, 0x4f40, 0x1078,
+	0x4db0, 0x2069, 0x4f80, 0x2071, 0x0100, 0x1078, 0x4db0, 0x7814,
 	0xc0d4, 0x7816, 0x0d7f, 0x0078, 0x110a, 0x7814, 0xc0e5, 0x7816,
 	0x781b, 0x003c, 0x7eca, 0x7cc2, 0x7bc6, 0x7867, 0x0000, 0x7800,
 	0xc08d, 0x7802, 0x2031, 0x0030, 0x78af, 0x0101, 0x7823, 0x0002,
-	0x7827, 0x0002, 0x2009, 0x0002, 0x2069, 0x4e40, 0x681b, 0x0003,
+	0x7827, 0x0002, 0x2009, 0x0002, 0x2069, 0x4f40, 0x681b, 0x0003,
 	0x6823, 0x0007, 0x6827, 0x00fa, 0x682b, 0x0008, 0x682f, 0x0028,
 	0x6837, 0x0000, 0x683b, 0x0006, 0x6833, 0x0008, 0x683f, 0x0000,
-	0x8109, 0x0040, 0x115e, 0x68d3, 0x000a, 0x68c3, 0x4ec0, 0x2079,
-	0x4e00, 0x7814, 0xd0e4, 0x00c0, 0x1144, 0xd0ec, 0x00c0, 0x1148,
+	0x8109, 0x0040, 0x115e, 0x68d3, 0x000a, 0x68c3, 0x4fc0, 0x2079,
+	0x4f00, 0x7814, 0xd0e4, 0x00c0, 0x1144, 0xd0ec, 0x00c0, 0x1148,
 	0x68d7, 0x7329, 0x0078, 0x114a, 0x68d7, 0x730d, 0x0078, 0x114a,
-	0x68d7, 0x732d, 0x68c7, 0x53c0, 0x68cb, 0x52c0, 0x68cf, 0x93c0,
-	0x68ab, 0x9644, 0x68af, 0x9649, 0x68b3, 0x9644, 0x68b7, 0x9644,
-	0x68a7, 0x0001, 0x2069, 0x4e80, 0x0078, 0x111e, 0x68d3, 0x000a,
-	0x68c3, 0x50c0, 0x7814, 0xd0e4, 0x00c0, 0x116a, 0x68d7, 0x7439,
-	0x0078, 0x116c, 0x68d7, 0x7419, 0x68c7, 0x73c0, 0x68cb, 0x5340,
-	0x68cf, 0x94d0, 0x68ab, 0x9649, 0x68af, 0x964e, 0x68b3, 0x9649,
-	0x68b7, 0x9649, 0x68a7, 0x0001, 0x7810, 0xd0ec, 0x00c0, 0x11c2,
-	0x7814, 0xd0e4, 0x00c0, 0x11b4, 0x0e7e, 0x2069, 0x52c0, 0x2071,
+	0x68d7, 0x732d, 0x68c7, 0x54c0, 0x68cb, 0x53c0, 0x68cf, 0x94c0,
+	0x68ab, 0x9744, 0x68af, 0x9749, 0x68b3, 0x9744, 0x68b7, 0x9744,
+	0x68a7, 0x0001, 0x2069, 0x4f80, 0x0078, 0x111e, 0x68d3, 0x000a,
+	0x68c3, 0x51c0, 0x7814, 0xd0e4, 0x00c0, 0x116a, 0x68d7, 0x7439,
+	0x0078, 0x116c, 0x68d7, 0x7419, 0x68c7, 0x74c0, 0x68cb, 0x5440,
+	0x68cf, 0x95d0, 0x68ab, 0x9749, 0x68af, 0x974e, 0x68b3, 0x9749,
+	0x68b7, 0x9749, 0x68a7, 0x0001, 0x7810, 0xd0ec, 0x00c0, 0x11c2,
+	0x7814, 0xd0e4, 0x00c0, 0x11b4, 0x0e7e, 0x2069, 0x53c0, 0x2071,
 	0x0200, 0x70ec, 0xd0e4, 0x00c0, 0x1195, 0x2019, 0x0c0c, 0x2021,
-	0x000c, 0x1078, 0x2009, 0x0078, 0x119b, 0x2019, 0x0c0a, 0x2021,
-	0x000a, 0x1078, 0x2009, 0x2069, 0x5340, 0x2071, 0x0100, 0x70ec,
+	0x000c, 0x1078, 0x2050, 0x0078, 0x119b, 0x2019, 0x0c0a, 0x2021,
+	0x000a, 0x1078, 0x2050, 0x2069, 0x5440, 0x2071, 0x0100, 0x70ec,
 	0xd0e4, 0x00c0, 0x11ab, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x1078,
-	0x2009, 0x0078, 0x11b1, 0x2019, 0x0c0a, 0x2021, 0x000a, 0x1078,
-	0x2009, 0x0e7f, 0x0078, 0x11db, 0x2019, 0x0c0c, 0x2021, 0x000c,
-	0x2069, 0x52c0, 0x1078, 0x2009, 0x2069, 0x5340, 0x1078, 0x2009,
-	0x0078, 0x11db, 0x2069, 0x52c0, 0x0e7e, 0x2071, 0x0100, 0x70ec,
+	0x2050, 0x0078, 0x11b1, 0x2019, 0x0c0a, 0x2021, 0x000a, 0x1078,
+	0x2050, 0x0e7f, 0x0078, 0x11db, 0x2019, 0x0c0c, 0x2021, 0x000c,
+	0x2069, 0x53c0, 0x1078, 0x2050, 0x2069, 0x5440, 0x1078, 0x2050,
+	0x0078, 0x11db, 0x2069, 0x53c0, 0x0e7e, 0x2071, 0x0100, 0x70ec,
 	0xd0e4, 0x00c0, 0x11d4, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x1078,
-	0x2009, 0x0e7f, 0x0078, 0x11db, 0x2019, 0x0c0a, 0x2021, 0x000a,
-	0x1078, 0x2009, 0x0e7f, 0x2011, 0x0002, 0x2069, 0x53c0, 0x2009,
+	0x2050, 0x0e7f, 0x0078, 0x11db, 0x2019, 0x0c0a, 0x2021, 0x000a,
+	0x1078, 0x2050, 0x0e7f, 0x2011, 0x0002, 0x2069, 0x54c0, 0x2009,
 	0x0002, 0x20a9, 0x0100, 0x6837, 0x0000, 0x680b, 0x0040, 0x7bc8,
 	0xa386, 0xfeff, 0x00c0, 0x11f2, 0x6817, 0x0100, 0x681f, 0x0064,
 	0x0078, 0x11f6, 0x6817, 0x0064, 0x681f, 0x0002, 0xade8, 0x0010,
 	0x00f0, 0x11e3, 0x8109, 0x00c0, 0x11e1, 0x8211, 0x0040, 0x1204,
-	0x2069, 0x73c0, 0x0078, 0x11df, 0x1078, 0x265b, 0x1078, 0x468e,
-	0x1078, 0x1dd4, 0x1078, 0x4c6f, 0x2091, 0x2100, 0x2079, 0x4e00,
+	0x2069, 0x74c0, 0x0078, 0x11df, 0x1078, 0x26a2, 0x1078, 0x4712,
+	0x1078, 0x1e1b, 0x1078, 0x4d42, 0x2091, 0x2100, 0x2079, 0x4f00,
 	0x7810, 0xd0ec, 0x0040, 0x1218, 0x2071, 0x0020, 0x0078, 0x121a,
-	0x2071, 0x0050, 0x2091, 0x2200, 0x2079, 0x4e00, 0x2071, 0x0020,
-	0x2091, 0x2300, 0x2079, 0x4e00, 0x7810, 0xd0ec, 0x0040, 0x122c,
-	0x2079, 0x0100, 0x0078, 0x122e, 0x2079, 0x0200, 0x2071, 0x4e40,
-	0x2091, 0x2400, 0x2079, 0x0100, 0x2071, 0x4e80, 0x2091, 0x2000,
-	0x2079, 0x4e00, 0x2071, 0x0010, 0x3200, 0xa085, 0x303d, 0x2090,
+	0x2071, 0x0050, 0x2091, 0x2200, 0x2079, 0x4f00, 0x2071, 0x0020,
+	0x2091, 0x2300, 0x2079, 0x4f00, 0x7810, 0xd0ec, 0x0040, 0x122c,
+	0x2079, 0x0100, 0x0078, 0x122e, 0x2079, 0x0200, 0x2071, 0x4f40,
+	0x2091, 0x2400, 0x2079, 0x0100, 0x2071, 0x4f80, 0x2091, 0x2000,
+	0x2079, 0x4f00, 0x2071, 0x0010, 0x3200, 0xa085, 0x303d, 0x2090,
 	0x2071, 0x0010, 0x70c3, 0x0000, 0x0090, 0x124d, 0x70c0, 0xa086,
-	0x0002, 0x00c0, 0x124d, 0x1078, 0x15ba, 0x2039, 0x0000, 0x7810,
+	0x0002, 0x00c0, 0x124d, 0x1078, 0x15c1, 0x2039, 0x0000, 0x7810,
 	0xd0ec, 0x00c0, 0x12cf, 0x1078, 0x148e, 0x78ac, 0xa005, 0x00c0,
 	0x126b, 0x0068, 0x1261, 0x786c, 0xa065, 0x0040, 0x1261, 0x1078,
-	0x2395, 0x1078, 0x20a1, 0x0068, 0x1278, 0x786c, 0xa065, 0x0040,
-	0x126b, 0x1078, 0x2395, 0x0068, 0x1278, 0x2009, 0x4e47, 0x2011,
-	0x4e87, 0x2104, 0x220c, 0xa105, 0x0040, 0x1278, 0x1078, 0x1f0a,
-	0x2071, 0x4e40, 0x70a4, 0xa005, 0x0040, 0x129d, 0x7450, 0xa485,
+	0x23dc, 0x1078, 0x20e8, 0x0068, 0x1278, 0x786c, 0xa065, 0x0040,
+	0x126b, 0x1078, 0x23dc, 0x0068, 0x1278, 0x2009, 0x4f47, 0x2011,
+	0x4f87, 0x2104, 0x220c, 0xa105, 0x0040, 0x1278, 0x1078, 0x1f51,
+	0x2071, 0x4f40, 0x70a4, 0xa005, 0x0040, 0x129d, 0x7450, 0xa485,
 	0x0000, 0x0040, 0x129d, 0x2079, 0x0200, 0x2091, 0x8000, 0x72d4,
-	0xa28c, 0x303d, 0x2190, 0x1078, 0x2b6a, 0x2091, 0x8000, 0x2091,
-	0x303d, 0x0068, 0x129d, 0x2079, 0x4e00, 0x786c, 0xa065, 0x0040,
-	0x129d, 0x2071, 0x0010, 0x1078, 0x2395, 0x00e0, 0x12a5, 0x2079,
-	0x4e00, 0x2071, 0x0010, 0x1078, 0x4a43, 0x2071, 0x4e80, 0x70a4,
+	0xa28c, 0x303d, 0x2190, 0x1078, 0x2bb1, 0x2091, 0x8000, 0x2091,
+	0x303d, 0x0068, 0x129d, 0x2079, 0x4f00, 0x786c, 0xa065, 0x0040,
+	0x129d, 0x2071, 0x0010, 0x1078, 0x23dc, 0x00e0, 0x12a5, 0x2079,
+	0x4f00, 0x2071, 0x0010, 0x1078, 0x4b16, 0x2071, 0x4f80, 0x70a4,
 	0xa005, 0x0040, 0x12bd, 0x7050, 0xa025, 0x0040, 0x12bd, 0x2079,
 	0x0100, 0x2091, 0x8000, 0x72d4, 0xa28c, 0x303d, 0x2190, 0x1078,
-	0x2b6a, 0x2091, 0x8000, 0x2091, 0x303d, 0x2079, 0x4e00, 0x2071,
+	0x2bb1, 0x2091, 0x8000, 0x2091, 0x303d, 0x2079, 0x4f00, 0x2071,
 	0x0010, 0x0068, 0x12c9, 0x786c, 0xa065, 0x0040, 0x12c9, 0x1078,
-	0x2395, 0x00e0, 0x1253, 0x1078, 0x4a43, 0x0078, 0x1253, 0x1078,
+	0x23dc, 0x00e0, 0x1253, 0x1078, 0x4b16, 0x0078, 0x1253, 0x1078,
 	0x148e, 0x78ac, 0xa005, 0x00c0, 0x12e7, 0x0068, 0x12dd, 0x786c,
-	0xa065, 0x0040, 0x12dd, 0x1078, 0x2395, 0x1078, 0x20a1, 0x0068,
-	0x12f1, 0x786c, 0xa065, 0x0040, 0x12e7, 0x1078, 0x2395, 0x0068,
-	0x12f1, 0x2009, 0x4e47, 0x2104, 0xa005, 0x0040, 0x12f1, 0x1078,
-	0x1f0a, 0x2071, 0x4e40, 0x70a4, 0xa005, 0x0040, 0x130c, 0x7450,
+	0xa065, 0x0040, 0x12dd, 0x1078, 0x23dc, 0x1078, 0x20e8, 0x0068,
+	0x12f1, 0x786c, 0xa065, 0x0040, 0x12e7, 0x1078, 0x23dc, 0x0068,
+	0x12f1, 0x2009, 0x4f47, 0x2104, 0xa005, 0x0040, 0x12f1, 0x1078,
+	0x1f51, 0x2071, 0x4f40, 0x70a4, 0xa005, 0x0040, 0x130c, 0x7450,
 	0xa485, 0x0000, 0x0040, 0x130c, 0x2079, 0x0100, 0x2091, 0x8000,
-	0x72d4, 0xa28c, 0x303d, 0x2190, 0x1078, 0x2b6a, 0x2091, 0x8000,
-	0x2091, 0x303d, 0x2079, 0x4e00, 0x2071, 0x0010, 0x0068, 0x1316,
-	0x786c, 0xa065, 0x0040, 0x1316, 0x1078, 0x2395, 0x00e0, 0x12cf,
-	0x1078, 0x4a43, 0x0078, 0x12cf, 0x133c, 0x133c, 0x133e, 0x133e,
+	0x72d4, 0xa28c, 0x303d, 0x2190, 0x1078, 0x2bb1, 0x2091, 0x8000,
+	0x2091, 0x303d, 0x2079, 0x4f00, 0x2071, 0x0010, 0x0068, 0x1316,
+	0x786c, 0xa065, 0x0040, 0x1316, 0x1078, 0x23dc, 0x00e0, 0x12cf,
+	0x1078, 0x4b16, 0x0078, 0x12cf, 0x133c, 0x133c, 0x133e, 0x133e,
 	0x134b, 0x134b, 0x134b, 0x134b, 0x1356, 0x1356, 0x1363, 0x1363,
 	0x134b, 0x134b, 0x134b, 0x134b, 0x133c, 0x133c, 0x133e, 0x133e,
 	0x134b, 0x134b, 0x134b, 0x134b, 0x1356, 0x1356, 0x1363, 0x1363,
 	0x134b, 0x134b, 0x134b, 0x134b, 0x0078, 0x133c, 0x007e, 0x107e,
-	0x127e, 0x2091, 0x2400, 0x1078, 0x298a, 0x127f, 0x107f, 0x007f,
+	0x127e, 0x2091, 0x2400, 0x1078, 0x29d1, 0x127f, 0x107f, 0x007f,
 	0x2091, 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x1078, 0x13c8,
 	0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007e, 0x107e,
-	0x127e, 0x2091, 0x2300, 0x1078, 0x298a, 0x127f, 0x107f, 0x007f,
+	0x127e, 0x2091, 0x2300, 0x1078, 0x29d1, 0x127f, 0x107f, 0x007f,
 	0x2091, 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x2091, 0x2300,
-	0x1078, 0x298a, 0x2091, 0x2400, 0x1078, 0x298a, 0x127f, 0x107f,
+	0x1078, 0x29d1, 0x2091, 0x2400, 0x1078, 0x29d1, 0x127f, 0x107f,
 	0x007f, 0x2091, 0x8001, 0x007c, 0x1394, 0x1394, 0x1396, 0x1396,
 	0x13a3, 0x13a3, 0x13a3, 0x13a3, 0x13ae, 0x13ae, 0x1396, 0x1396,
 	0x13a3, 0x13a3, 0x13a3, 0x13a3, 0x13af, 0x13af, 0x13af, 0x13af,
 	0x13af, 0x13af, 0x13af, 0x13af, 0x13af, 0x13af, 0x13af, 0x13af,
 	0x13af, 0x13af, 0x13af, 0x13af, 0x0078, 0x1394, 0x007e, 0x107e,
-	0x127e, 0x2091, 0x2300, 0x1078, 0x298a, 0x127f, 0x107f, 0x007f,
+	0x127e, 0x2091, 0x2300, 0x1078, 0x29d1, 0x127f, 0x107f, 0x007f,
 	0x2091, 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x1078, 0x13d5,
 	0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007c, 0x107e,
 	0x127e, 0x0d7e, 0x0e7e, 0x0f7e, 0x007e, 0x2071, 0x0100, 0x2069,
-	0x4e40, 0x2079, 0x4e00, 0x70ec, 0xa084, 0x1c00, 0x78e2, 0x1078,
-	0x4cdd, 0x007f, 0x0f7f, 0x0e7f, 0x0d7f, 0x127f, 0x107f, 0x007c,
+	0x4f40, 0x2079, 0x4f00, 0x70ec, 0xa084, 0x1c00, 0x78e2, 0x1078,
+	0x4db0, 0x007f, 0x0f7f, 0x0e7f, 0x0d7f, 0x127f, 0x107f, 0x007c,
 	0x3c00, 0xa084, 0x0007, 0x0079, 0x13cd, 0x13de, 0x13de, 0x13e0,
 	0x13e0, 0x13e5, 0x13e5, 0x13ea, 0x13ea, 0x3c00, 0xa084, 0x0003,
-	0x0079, 0x13da, 0x13de, 0x13de, 0x13f3, 0x13f3, 0x1078, 0x296b,
-	0x2091, 0x2200, 0x1078, 0x4768, 0x007c, 0x2091, 0x2100, 0x1078,
-	0x4768, 0x007c, 0x2091, 0x2100, 0x1078, 0x4768, 0x2091, 0x2200,
-	0x1078, 0x4768, 0x007c, 0x2091, 0x2100, 0x1078, 0x4768, 0x007c,
+	0x0079, 0x13da, 0x13de, 0x13de, 0x13f3, 0x13f3, 0x1078, 0x29b2,
+	0x2091, 0x2200, 0x1078, 0x47ec, 0x007c, 0x2091, 0x2100, 0x1078,
+	0x47ec, 0x007c, 0x2091, 0x2100, 0x1078, 0x47ec, 0x2091, 0x2200,
+	0x1078, 0x47ec, 0x007c, 0x2091, 0x2100, 0x1078, 0x47ec, 0x007c,
 	0x1418, 0x1418, 0x141a, 0x141a, 0x1427, 0x1427, 0x1427, 0x1427,
 	0x1432, 0x1432, 0x143f, 0x143f, 0x1427, 0x1427, 0x1427, 0x1427,
 	0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450,
 	0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450,
 	0x0078, 0x1418, 0x007e, 0x107e, 0x127e, 0x2091, 0x2400, 0x1078,
-	0x298a, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007e,
+	0x29d1, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007e,
 	0x107e, 0x127e, 0x1078, 0x13c8, 0x127f, 0x107f, 0x007f, 0x2091,
 	0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x2091, 0x2300, 0x1078,
-	0x298a, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007e,
-	0x107e, 0x127e, 0x2091, 0x2300, 0x1078, 0x298a, 0x2091, 0x2400,
-	0x1078, 0x298a, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c,
-	0x007e, 0x107e, 0x127e, 0x0d7e, 0x0e7e, 0x0f7e, 0x2079, 0x4e00,
-	0x2071, 0x0200, 0x2069, 0x4e40, 0x3d00, 0xd08c, 0x0040, 0x1466,
-	0x70ec, 0xa084, 0x1c00, 0x78e2, 0x1078, 0x4cdd, 0x3d00, 0xd084,
-	0x0040, 0x1474, 0x2069, 0x4e80, 0x2071, 0x0100, 0x70ec, 0xa084,
-	0x1c00, 0x78e6, 0x1078, 0x4cdd, 0x0f7f, 0x0e7f, 0x0d7f, 0x127f,
+	0x29d1, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007e,
+	0x107e, 0x127e, 0x2091, 0x2300, 0x1078, 0x29d1, 0x2091, 0x2400,
+	0x1078, 0x29d1, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c,
+	0x007e, 0x107e, 0x127e, 0x0d7e, 0x0e7e, 0x0f7e, 0x2079, 0x4f00,
+	0x2071, 0x0200, 0x2069, 0x4f40, 0x3d00, 0xd08c, 0x0040, 0x1466,
+	0x70ec, 0xa084, 0x1c00, 0x78e2, 0x1078, 0x4db0, 0x3d00, 0xd084,
+	0x0040, 0x1474, 0x2069, 0x4f80, 0x2071, 0x0100, 0x70ec, 0xa084,
+	0x1c00, 0x78e6, 0x1078, 0x4db0, 0x0f7f, 0x0e7f, 0x0d7f, 0x127f,
 	0x107f, 0x007f, 0x007c, 0x7008, 0x800b, 0x00c8, 0x1489, 0x7007,
 	0x0002, 0xa08c, 0x01e0, 0x00c0, 0x148a, 0xd09c, 0x0040, 0x1489,
-	0x087a, 0x097a, 0x70c3, 0x4002, 0x0078, 0x15bd, 0x0068, 0x1513,
-	0x2061, 0x0000, 0x6018, 0xd084, 0x00c0, 0x1513, 0x7828, 0xa005,
-	0x00c0, 0x149e, 0x0010, 0x1514, 0x0078, 0x1513, 0x7910, 0xd1f4,
-	0x0040, 0x14a6, 0x2001, 0x4007, 0x0078, 0x15bc, 0x7914, 0xd1ec,
-	0x0040, 0x14c1, 0xd0fc, 0x0040, 0x14b7, 0x007e, 0x1078, 0x1d64,
-	0x007f, 0x0040, 0x14c1, 0x2001, 0x4007, 0x0078, 0x15bc, 0x007e,
-	0x1078, 0x1d54, 0x007f, 0x0040, 0x14c1, 0x2001, 0x4007, 0x0078,
-	0x15bc, 0x7910, 0xd0fc, 0x00c0, 0x14cb, 0x2061, 0x4e40, 0xc19c,
-	0xc7fc, 0x0078, 0x14cf, 0x2061, 0x4e80, 0xc19d, 0xc7fd, 0x6064,
-	0xa005, 0x00c0, 0x1513, 0x7912, 0x6083, 0x0000, 0x7828, 0xc0fc,
-	0xa086, 0x0018, 0x00c0, 0x14e0, 0x0c7e, 0x1078, 0x1b5b, 0x0c7f,
-	0x782b, 0x0000, 0x607c, 0xa065, 0x0040, 0x14f9, 0x0c7e, 0x609c,
-	0x1078, 0x1e49, 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1c84, 0x2009,
-	0x0018, 0x6087, 0x0103, 0x1078, 0x1d74, 0x00c0, 0x150d, 0x1078,
-	0x1dc6, 0x7810, 0xd09c, 0x00c0, 0x1501, 0x2061, 0x4e40, 0x0078,
-	0x1505, 0x2061, 0x4e80, 0xc09c, 0x7812, 0x607f, 0x0000, 0x60d4,
-	0xd0dc, 0x0040, 0x1511, 0xc0dc, 0x60d6, 0x2001, 0x4005, 0x0078,
-	0x15bc, 0x0078, 0x15ba, 0x007c, 0x7810, 0xd0f4, 0x0040, 0x151c,
-	0x2001, 0x4007, 0x0078, 0x15bc, 0xa006, 0x70c2, 0x70c6, 0x70ca,
-	0x70ce, 0x70da, 0x70c0, 0xa03d, 0xa08a, 0x0040, 0x00c8, 0x152a,
-	0x0079, 0x1531, 0x2100, 0xa08a, 0x0040, 0x00c8, 0x15c8, 0x0079,
-	0x1571, 0x15ba, 0x1610, 0x15d9, 0x1648, 0x1680, 0x1680, 0x15d0,
-	0x1c9c, 0x168b, 0x15c8, 0x15dd, 0x15df, 0x15e1, 0x15e3, 0x1ca1,
-	0x15c8, 0x1699, 0x16f6, 0x1b7b, 0x1c96, 0x15e5, 0x19c0, 0x1a02,
-	0x1a3d, 0x1a8e, 0x197b, 0x1988, 0x199c, 0x19af, 0x17cb, 0x15c8,
-	0x172d, 0x173a, 0x1746, 0x1752, 0x1768, 0x1774, 0x1777, 0x1783,
-	0x178f, 0x1797, 0x17b3, 0x17bf, 0x15c8, 0x15c8, 0x15c8, 0x15c8,
-	0x17d8, 0x17ea, 0x1806, 0x183c, 0x1864, 0x1874, 0x1877, 0x18a8,
-	0x18d9, 0x18eb, 0x194a, 0x195a, 0x15c8, 0x15c8, 0x15c8, 0x15c8,
-	0x196a, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x1cc6, 0x1ccc,
-	0x15c8, 0x15c8, 0x15c8, 0x1cd0, 0x1d15, 0x15c8, 0x15c8, 0x15c8,
-	0x15c8, 0x160a, 0x167a, 0x1693, 0x16f0, 0x1b75, 0x15c8, 0x15c8,
-	0x1b3e, 0x15c8, 0x1d19, 0x1cb8, 0x1cc2, 0x15c8, 0x15c8, 0x15c8,
-	0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8,
-	0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8,
-	0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8,
-	0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8, 0x15c8,
-	0x15c8, 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0078, 0x15bc, 0x73ce,
-	0x72ca, 0x71c6, 0x2001, 0x4000, 0x70c2, 0x0068, 0x15bd, 0x2061,
-	0x0000, 0x601b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x007c,
-	0x70c3, 0x4001, 0x0078, 0x15bd, 0x70c3, 0x4006, 0x0078, 0x15bd,
-	0x2099, 0x0041, 0x20a1, 0x0041, 0x20a9, 0x0005, 0x53a3, 0x0078,
-	0x15ba, 0x70c4, 0x70c3, 0x0004, 0x007a, 0x0078, 0x15ba, 0x0078,
-	0x15ba, 0x0078, 0x15ba, 0x0078, 0x15ba, 0x2091, 0x8000, 0x70c3,
-	0x0004, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3,
-	0x0008, 0x2001, 0x000f, 0x70d6, 0x2079, 0x0000, 0x781b, 0x0001,
-	0x2031, 0x0030, 0x2059, 0x1000, 0x2029, 0x041a, 0x2051, 0x0445,
-	0x2061, 0x0447, 0x20c1, 0x0020, 0x2091, 0x5000, 0x2091, 0x4080,
-	0x0078, 0x0418, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x1613,
-	0x2029, 0x0000, 0x2520, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x20a0,
-	0x2099, 0x0030, 0x7003, 0x0001, 0x7007, 0x0006, 0x731a, 0x721e,
-	0x7422, 0x7526, 0x2021, 0x0040, 0x81ff, 0x0040, 0x15ba, 0xa182,
-	0x0040, 0x00c8, 0x162d, 0x2120, 0xa006, 0x2008, 0x8403, 0x7012,
-	0x7007, 0x0004, 0x7007, 0x0001, 0x7008, 0xd0fc, 0x0040, 0x1634,
-	0x7007, 0x0002, 0xa084, 0x01e0, 0x0040, 0x1642, 0x70c3, 0x4002,
-	0x0078, 0x15bd, 0x24a8, 0x53a5, 0x0078, 0x1624, 0x0078, 0x15ba,
-	0x2029, 0x0000, 0x2520, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x2098,
-	0x20a1, 0x0030, 0x7003, 0x0000, 0x7007, 0x0006, 0x731a, 0x721e,
-	0x7422, 0x7526, 0x2021, 0x0040, 0x7007, 0x0006, 0x81ff, 0x0040,
-	0x15ba, 0xa182, 0x0040, 0x00c8, 0x1667, 0x2120, 0xa006, 0x2008,
-	0x8403, 0x7012, 0x24a8, 0x53a6, 0x7007, 0x0001, 0x7008, 0xd0fc,
-	0x0040, 0x166e, 0xa084, 0x01e0, 0x0040, 0x165c, 0x70c3, 0x4002,
-	0x0078, 0x15bd, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x164b,
-	0x71c4, 0x70c8, 0x2114, 0xa79e, 0x0004, 0x00c0, 0x1688, 0x200a,
-	0x72ca, 0x0078, 0x15b9, 0x70c7, 0x0008, 0x70cb, 0x000f, 0x70cf,
-	0x0000, 0x0078, 0x15ba, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078,
-	0x169c, 0x2029, 0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d0,
-	0x70c6, 0x72ca, 0x73ce, 0x74d2, 0xa005, 0x0040, 0x16eb, 0xa40a,
-	0x0040, 0x16ac, 0x00c8, 0x16b5, 0x8001, 0x7872, 0xa084, 0xfc00,
-	0x0040, 0x16b9, 0x78ac, 0xc085, 0x78ae, 0x2001, 0x4005, 0x0078,
-	0x15bc, 0x7b7e, 0x7a7a, 0x7e86, 0x7d82, 0x7c76, 0xa48c, 0xff00,
-	0x0040, 0x16d1, 0x8407, 0x8004, 0x8004, 0x810c, 0x810c, 0x810f,
-	0xa118, 0xa291, 0x0000, 0xa6b1, 0x0000, 0xa581, 0x0000, 0x0078,
-	0x16db, 0x8407, 0x8004, 0x8004, 0xa318, 0xa291, 0x0000, 0xa6b1,
-	0x0000, 0xa581, 0x0000, 0x731a, 0x721e, 0x7622, 0x7026, 0xa605,
-	0x0040, 0x16e5, 0x7a10, 0xc2c5, 0x7a12, 0x78ac, 0xa084, 0xfffc,
-	0x78ae, 0x0078, 0x16ee, 0x78ac, 0xc085, 0x78ae, 0x0078, 0x15ba,
-	0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078, 0x16f9, 0x2029, 0x0000,
-	0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d4, 0x70c6, 0x72ca, 0x73ce,
-	0x74d6, 0xa005, 0x0040, 0x1728, 0xa40a, 0x0040, 0x1709, 0x00c8,
-	0x15bc, 0x8001, 0x7892, 0xa084, 0xfc00, 0x0040, 0x1716, 0x78ac,
-	0xc0c5, 0x78ae, 0x2001, 0x4005, 0x0078, 0x15bc, 0x7a9a, 0x7b9e,
-	0x7da2, 0x7ea6, 0x2600, 0xa505, 0x0040, 0x1721, 0x7a10, 0xc2c5,
-	0x7a12, 0x7c96, 0x78ac, 0xa084, 0xfcff, 0x78ae, 0x0078, 0x172b,
-	0x78ac, 0xc0c5, 0x78ae, 0x0078, 0x15ba, 0x2009, 0x0000, 0x786c,
-	0xa065, 0x0040, 0x1737, 0x8108, 0x6000, 0x0078, 0x1730, 0x7ac4,
-	0x0078, 0x15b8, 0x2009, 0x4e48, 0x210c, 0x7810, 0xd0ec, 0x00c0,
-	0x15b9, 0x2011, 0x4e88, 0x2214, 0x0078, 0x15b8, 0x2009, 0x4e49,
-	0x210c, 0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x2011, 0x4e89, 0x2214,
-	0x0078, 0x15b8, 0x2061, 0x4e40, 0x6128, 0x622c, 0x8214, 0x8214,
-	0x8214, 0x7810, 0xd0ec, 0x00c0, 0x1766, 0x2061, 0x4e80, 0x6328,
-	0x73da, 0x632c, 0x831c, 0x831c, 0x831c, 0x73de, 0x0078, 0x15b8,
-	0x2009, 0x4e4c, 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x2011,
-	0x4e8c, 0x2214, 0x0078, 0x15b8, 0x7918, 0x0078, 0x15b9, 0x2009,
-	0x4e4d, 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x2011, 0x4e8d,
-	0x2214, 0x0078, 0x15b8, 0x2009, 0x4e4e, 0x210c, 0x7810, 0xd0ec,
-	0x00c0, 0x15b9, 0x2011, 0x4e8e, 0x2214, 0x0078, 0x15b8, 0x7920,
-	0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x7a24, 0x0078, 0x15b8, 0x71c4,
-	0xd1fc, 0x00c0, 0x179f, 0x2011, 0x52c0, 0x0078, 0x17a1, 0x2011,
-	0x5340, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa268,
-	0x6a00, 0x6804, 0xd09c, 0x0040, 0x17b0, 0x6b08, 0x0078, 0x17b1,
-	0x6b0c, 0x0078, 0x15b7, 0x77c4, 0x1078, 0x1de4, 0x2091, 0x8000,
-	0x6b1c, 0x6a14, 0x2091, 0x8001, 0x2708, 0x0078, 0x15b7, 0x2061,
-	0x4e40, 0x6118, 0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x2061, 0x4e80,
-	0x6218, 0x0078, 0x15b8, 0x77c4, 0x1078, 0x1de4, 0x2091, 0x8000,
-	0x6908, 0x6a18, 0x6b10, 0x77da, 0x2091, 0x8001, 0x0078, 0x15b7,
-	0x71c4, 0x2110, 0xa294, 0x000f, 0xa282, 0x0010, 0x00c8, 0x15b2,
-	0x1078, 0x277f, 0xa384, 0x4000, 0x0040, 0x17e8, 0xa295, 0x0020,
-	0x0078, 0x15b7, 0x71c4, 0x2100, 0xc0bc, 0xa082, 0x0010, 0x00c8,
-	0x15b2, 0xd1bc, 0x00c0, 0x17f9, 0x2011, 0x4e48, 0x2204, 0x0078,
-	0x17fd, 0x2011, 0x4e88, 0x2204, 0xc0bd, 0x007e, 0x2100, 0xc0bc,
-	0x2012, 0x1078, 0x26dc, 0x017f, 0x0078, 0x15b9, 0x71c4, 0x2021,
-	0x4e49, 0x2404, 0x70c6, 0x2019, 0x0000, 0x0078, 0x1815, 0x71c8,
-	0x2021, 0x4e89, 0x2404, 0x70ca, 0xc3fd, 0x2011, 0x1834, 0x20a9,
-	0x0008, 0x2204, 0xa106, 0x0040, 0x1824, 0x8210, 0x00f0, 0x1819,
-	0x71c4, 0x72c8, 0x0078, 0x15b1, 0xa292, 0x1834, 0x027e, 0x2122,
-	0x017f, 0x1078, 0x26fd, 0x7810, 0xd0ec, 0x00c0, 0x1832, 0xd3fc,
-	0x0040, 0x180f, 0x0078, 0x15ba, 0x03e8, 0x00fa, 0x01f4, 0x02ee,
-	0x0004, 0x0001, 0x0002, 0x0003, 0x2061, 0x4e40, 0x6128, 0x622c,
+	0x087a, 0x097a, 0x70c3, 0x4002, 0x0078, 0x15c4, 0x0068, 0x151a,
+	0x2061, 0x0000, 0x6018, 0xd084, 0x00c0, 0x151a, 0x7828, 0xa005,
+	0x00c0, 0x149e, 0x0010, 0x151b, 0x0078, 0x151a, 0x7910, 0xd1f4,
+	0x0040, 0x14a4, 0x0078, 0x14b9, 0x7914, 0xd1ec, 0x0040, 0x14bd,
+	0xd0fc, 0x0040, 0x14b3, 0x007e, 0x1078, 0x1dae, 0x007f, 0x0040,
+	0x14bd, 0x0078, 0x14b9, 0x007e, 0x1078, 0x1da1, 0x007f, 0x0040,
+	0x14bd, 0x2001, 0x4007, 0x0078, 0x15c3, 0x7910, 0xd0fc, 0x00c0,
+	0x14c7, 0x2061, 0x4f40, 0xc19c, 0xc7fc, 0x0078, 0x14cb, 0x2061,
+	0x4f80, 0xc19d, 0xc7fd, 0x6064, 0xa005, 0x00c0, 0x151a, 0x7912,
+	0x6082, 0x7828, 0xc0fc, 0xa086, 0x0018, 0x00c0, 0x14db, 0x0c7e,
+	0x1078, 0x1b85, 0x0c7f, 0x782b, 0x0000, 0x607c, 0xa065, 0x0040,
+	0x1500, 0x0c7e, 0x609c, 0x1078, 0x1e90, 0x0c7f, 0x609f, 0x0000,
+	0x1078, 0x1cd5, 0x2009, 0x0018, 0x6087, 0x0103, 0x7810, 0x007e,
+	0x84ff, 0x00c0, 0x14f6, 0x85ff, 0x0040, 0x14f8, 0xc0c5, 0x7812,
+	0x1078, 0x1dbb, 0x007f, 0x7812, 0x00c0, 0x1514, 0x1078, 0x1e0d,
+	0x7810, 0xd09c, 0x00c0, 0x1508, 0x2061, 0x4f40, 0x0078, 0x150c,
+	0x2061, 0x4f80, 0xc09c, 0x7812, 0x607f, 0x0000, 0x60d4, 0xd0dc,
+	0x0040, 0x1518, 0xc0dc, 0x60d6, 0x2001, 0x4005, 0x0078, 0x15c3,
+	0x0078, 0x15c1, 0x007c, 0x7810, 0xd0f4, 0x0040, 0x1523, 0x2001,
+	0x4007, 0x0078, 0x15c3, 0xa006, 0x70c2, 0x70c6, 0x70ca, 0x70ce,
+	0x70da, 0x70c0, 0xa03d, 0xa08a, 0x0040, 0x00c8, 0x1531, 0x0079,
+	0x1538, 0x2100, 0xa08a, 0x0040, 0x00c8, 0x15cf, 0x0079, 0x1578,
+	0x15c1, 0x1617, 0x15e0, 0x164f, 0x1687, 0x1687, 0x15d7, 0x1ced,
+	0x1692, 0x15cf, 0x15e4, 0x15e6, 0x15e8, 0x15ea, 0x1cf2, 0x15cf,
+	0x16a0, 0x16fd, 0x1ba5, 0x1ce7, 0x15ec, 0x19ea, 0x1a2c, 0x1a67,
+	0x1ab8, 0x19a5, 0x19b2, 0x19c6, 0x19d9, 0x17eb, 0x15cf, 0x1734,
+	0x1741, 0x174d, 0x1759, 0x176f, 0x177b, 0x177e, 0x178a, 0x1796,
+	0x179e, 0x17d3, 0x17df, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x17f8,
+	0x180a, 0x1826, 0x185c, 0x1884, 0x1894, 0x1897, 0x18c8, 0x18f9,
+	0x190b, 0x1974, 0x1984, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x1994,
+	0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x1d17, 0x1d1d, 0x15cf,
+	0x15cf, 0x15cf, 0x1d21, 0x1d66, 0x15cf, 0x15cf, 0x15cf, 0x15cf,
+	0x1611, 0x1681, 0x169a, 0x16f7, 0x1b9f, 0x15cf, 0x15cf, 0x1b68,
+	0x15cf, 0x1d6a, 0x1d09, 0x1d13, 0x15cf, 0x15cf, 0x15cf, 0x15cf,
+	0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf,
+	0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf,
+	0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf,
+	0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf,
+	0x72ca, 0x71c6, 0x2001, 0x4006, 0x0078, 0x15c3, 0x73ce, 0x72ca,
+	0x71c6, 0x2001, 0x4000, 0x70c2, 0x0068, 0x15c4, 0x2061, 0x0000,
+	0x601b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x007c, 0x70c3,
+	0x4001, 0x0078, 0x15c4, 0x70c3, 0x4006, 0x0078, 0x15c4, 0x2099,
+	0x0041, 0x20a1, 0x0041, 0x20a9, 0x0005, 0x53a3, 0x0078, 0x15c1,
+	0x70c4, 0x70c3, 0x0004, 0x007a, 0x0078, 0x15c1, 0x0078, 0x15c1,
+	0x0078, 0x15c1, 0x0078, 0x15c1, 0x2091, 0x8000, 0x70c3, 0x0004,
+	0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, 0x0008,
+	0x2001, 0x000f, 0x70d6, 0x2079, 0x0000, 0x781b, 0x0001, 0x2031,
+	0x0030, 0x2059, 0x1000, 0x2029, 0x041a, 0x2051, 0x0445, 0x2061,
+	0x0447, 0x20c1, 0x0020, 0x2091, 0x5000, 0x2091, 0x4080, 0x0078,
+	0x0418, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x161a, 0x2029,
+	0x0000, 0x2520, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x20a0, 0x2099,
+	0x0030, 0x7003, 0x0001, 0x7007, 0x0006, 0x731a, 0x721e, 0x7422,
+	0x7526, 0x2021, 0x0040, 0x81ff, 0x0040, 0x15c1, 0xa182, 0x0040,
+	0x00c8, 0x1634, 0x2120, 0xa006, 0x2008, 0x8403, 0x7012, 0x7007,
+	0x0004, 0x7007, 0x0001, 0x7008, 0xd0fc, 0x0040, 0x163b, 0x7007,
+	0x0002, 0xa084, 0x01e0, 0x0040, 0x1649, 0x70c3, 0x4002, 0x0078,
+	0x15c4, 0x24a8, 0x53a5, 0x0078, 0x162b, 0x0078, 0x15c1, 0x2029,
+	0x0000, 0x2520, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x2098, 0x20a1,
+	0x0030, 0x7003, 0x0000, 0x7007, 0x0006, 0x731a, 0x721e, 0x7422,
+	0x7526, 0x2021, 0x0040, 0x7007, 0x0006, 0x81ff, 0x0040, 0x15c1,
+	0xa182, 0x0040, 0x00c8, 0x166e, 0x2120, 0xa006, 0x2008, 0x8403,
+	0x7012, 0x24a8, 0x53a6, 0x7007, 0x0001, 0x7008, 0xd0fc, 0x0040,
+	0x1675, 0xa084, 0x01e0, 0x0040, 0x1663, 0x70c3, 0x4002, 0x0078,
+	0x15c4, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x1652, 0x71c4,
+	0x70c8, 0x2114, 0xa79e, 0x0004, 0x00c0, 0x168f, 0x200a, 0x72ca,
+	0x0078, 0x15c0, 0x70c7, 0x0008, 0x70cb, 0x000f, 0x70cf, 0x000b,
+	0x0078, 0x15c1, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078, 0x16a3,
+	0x2029, 0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d0, 0x70c6,
+	0x72ca, 0x73ce, 0x74d2, 0xa005, 0x0040, 0x16f2, 0xa40a, 0x0040,
+	0x16b3, 0x00c8, 0x16bc, 0x8001, 0x7872, 0xa084, 0xfc00, 0x0040,
+	0x16c0, 0x78ac, 0xc085, 0x78ae, 0x2001, 0x4005, 0x0078, 0x15c3,
+	0x7b7e, 0x7a7a, 0x7e86, 0x7d82, 0x7c76, 0xa48c, 0xff00, 0x0040,
+	0x16d8, 0x8407, 0x8004, 0x8004, 0x810c, 0x810c, 0x810f, 0xa118,
+	0xa291, 0x0000, 0xa6b1, 0x0000, 0xa581, 0x0000, 0x0078, 0x16e2,
+	0x8407, 0x8004, 0x8004, 0xa318, 0xa291, 0x0000, 0xa6b1, 0x0000,
+	0xa581, 0x0000, 0x731a, 0x721e, 0x7622, 0x7026, 0xa605, 0x0040,
+	0x16ec, 0x7a10, 0xc2c5, 0x7a12, 0x78ac, 0xa084, 0xfffc, 0x78ae,
+	0x0078, 0x16f5, 0x78ac, 0xc085, 0x78ae, 0x0078, 0x15c1, 0x75d8,
+	0x76dc, 0x75da, 0x76de, 0x0078, 0x1700, 0x2029, 0x0000, 0x2530,
+	0x70c4, 0x72c8, 0x73cc, 0x74d4, 0x70c6, 0x72ca, 0x73ce, 0x74d6,
+	0xa005, 0x0040, 0x172f, 0xa40a, 0x0040, 0x1710, 0x00c8, 0x1719,
+	0x8001, 0x7892, 0xa084, 0xfc00, 0x0040, 0x171d, 0x78ac, 0xc0c5,
+	0x78ae, 0x2001, 0x4005, 0x0078, 0x15c3, 0x7a9a, 0x7b9e, 0x7da2,
+	0x7ea6, 0x2600, 0xa505, 0x0040, 0x1728, 0x7a10, 0xc2c5, 0x7a12,
+	0x7c96, 0x78ac, 0xa084, 0xfcff, 0x78ae, 0x0078, 0x1732, 0x78ac,
+	0xc0c5, 0x78ae, 0x0078, 0x15c1, 0x2009, 0x0000, 0x786c, 0xa065,
+	0x0040, 0x173e, 0x8108, 0x6000, 0x0078, 0x1737, 0x7ac4, 0x0078,
+	0x15bf, 0x2009, 0x4f48, 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x15c0,
+	0x2011, 0x4f88, 0x2214, 0x0078, 0x15bf, 0x2009, 0x4f49, 0x210c,
+	0x7810, 0xd0ec, 0x00c0, 0x15c0, 0x2011, 0x4f89, 0x2214, 0x0078,
+	0x15bf, 0x2061, 0x4f40, 0x6128, 0x622c, 0x8214, 0x8214, 0x8214,
+	0x7810, 0xd0ec, 0x00c0, 0x176d, 0x2061, 0x4f80, 0x6328, 0x73da,
+	0x632c, 0x831c, 0x831c, 0x831c, 0x73de, 0x0078, 0x15bf, 0x2009,
+	0x4f4c, 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x15c0, 0x2011, 0x4f8c,
+	0x2214, 0x0078, 0x15bf, 0x7918, 0x0078, 0x15c0, 0x2009, 0x4f4d,
+	0x210c, 0x7810, 0xd0ec, 0x00c0, 0x15c0, 0x2011, 0x4f8d, 0x2214,
+	0x0078, 0x15bf, 0x2009, 0x4f4e, 0x210c, 0x7810, 0xd0ec, 0x00c0,
+	0x15c0, 0x2011, 0x4f8e, 0x2214, 0x0078, 0x15bf, 0x7920, 0x7810,
+	0xd0ec, 0x00c0, 0x15c0, 0x7a24, 0x0078, 0x15bf, 0x71c4, 0xd1fc,
+	0x00c0, 0x17a6, 0x2011, 0x53c0, 0x0078, 0x17a8, 0x2011, 0x5440,
+	0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa268, 0x6a00,
+	0x6804, 0xd09c, 0x0040, 0x17b7, 0x6b08, 0x0078, 0x17b8, 0x6b0c,
+	0xd1fc, 0x00c0, 0x17bf, 0x2021, 0x023b, 0x0078, 0x17c1, 0x2021,
+	0x013b, 0x2424, 0x7914, 0xd1e4, 0x0040, 0x17cd, 0xd4c4, 0x00c0,
+	0x17cc, 0xc4d5, 0x0078, 0x17cd, 0xc4dd, 0xa4a4, 0x1c00, 0x74de,
+	0x71c4, 0x0078, 0x15be, 0x77c4, 0x1078, 0x1e2b, 0x2091, 0x8000,
+	0x6b1c, 0x6a14, 0x2091, 0x8001, 0x2708, 0x0078, 0x15be, 0x2061,
+	0x4f40, 0x6118, 0x7810, 0xd0ec, 0x00c0, 0x15c0, 0x2061, 0x4f80,
+	0x6218, 0x0078, 0x15bf, 0x77c4, 0x1078, 0x1e2b, 0x2091, 0x8000,
+	0x6908, 0x6a18, 0x6b10, 0x77da, 0x2091, 0x8001, 0x0078, 0x15be,
+	0x71c4, 0x2110, 0xa294, 0x000f, 0xa282, 0x0010, 0x00c8, 0x15b9,
+	0x1078, 0x27c6, 0xa384, 0x4000, 0x0040, 0x1808, 0xa295, 0x0020,
+	0x0078, 0x15be, 0x71c4, 0x2100, 0xc0bc, 0xa082, 0x0010, 0x00c8,
+	0x15b9, 0xd1bc, 0x00c0, 0x1819, 0x2011, 0x4f48, 0x2204, 0x0078,
+	0x181d, 0x2011, 0x4f88, 0x2204, 0xc0bd, 0x007e, 0x2100, 0xc0bc,
+	0x2012, 0x1078, 0x2723, 0x017f, 0x0078, 0x15c0, 0x71c4, 0x2021,
+	0x4f49, 0x2404, 0x70c6, 0x2019, 0x0000, 0x0078, 0x1835, 0x71c8,
+	0x2021, 0x4f89, 0x2404, 0x70ca, 0xc3fd, 0x2011, 0x1854, 0x20a9,
+	0x0008, 0x2204, 0xa106, 0x0040, 0x1844, 0x8210, 0x00f0, 0x1839,
+	0x71c4, 0x72c8, 0x0078, 0x15b8, 0xa292, 0x1854, 0x027e, 0x2122,
+	0x017f, 0x1078, 0x2744, 0x7810, 0xd0ec, 0x00c0, 0x1852, 0xd3fc,
+	0x0040, 0x182f, 0x0078, 0x15c1, 0x03e8, 0x00fa, 0x01f4, 0x02ee,
+	0x0004, 0x0001, 0x0002, 0x0003, 0x2061, 0x4f40, 0x6128, 0x622c,
 	0x8214, 0x8214, 0x8214, 0x70c4, 0x602a, 0x70c8, 0x8003, 0x8003,
-	0x8003, 0x602e, 0x7810, 0xd0ec, 0x00c0, 0x1862, 0x027e, 0x017e,
-	0x2061, 0x4e80, 0x6128, 0x622c, 0x8214, 0x8214, 0x8214, 0x70d8,
+	0x8003, 0x602e, 0x7810, 0xd0ec, 0x00c0, 0x1882, 0x027e, 0x017e,
+	0x2061, 0x4f80, 0x6128, 0x622c, 0x8214, 0x8214, 0x8214, 0x70d8,
 	0x602a, 0x70dc, 0x8003, 0x8003, 0x8003, 0x602e, 0x71da, 0x72de,
-	0x017f, 0x027f, 0x0078, 0x15b8, 0x2061, 0x4e40, 0x6130, 0x70c4,
-	0x6032, 0x7810, 0xd0ec, 0x00c0, 0x15b9, 0x2061, 0x4e80, 0x6230,
-	0x70c8, 0x6032, 0x0078, 0x15b8, 0x7918, 0x0078, 0x15b9, 0x71c4,
-	0xa184, 0xffcf, 0x0040, 0x1883, 0x7810, 0xd0ec, 0x00c0, 0x15b2,
-	0x72c8, 0x0078, 0x15b1, 0x2011, 0x4e4d, 0x2204, 0x2112, 0x007e,
-	0x2019, 0x0000, 0x1078, 0x2764, 0x7810, 0xd0ec, 0x0040, 0x1893,
-	0x017f, 0x0078, 0x15b9, 0x71c8, 0xa184, 0xffcf, 0x0040, 0x189c,
-	0x2110, 0x71c4, 0x0078, 0x15b1, 0x2011, 0x4e8d, 0x2204, 0x2112,
-	0x007e, 0xc3fd, 0x1078, 0x2764, 0x027f, 0x017f, 0x0078, 0x15b8,
-	0x71c4, 0xa182, 0x0010, 0x0048, 0x18b4, 0x7810, 0xd0ec, 0x00c0,
-	0x15b2, 0x72c8, 0x0078, 0x15b1, 0x2011, 0x4e4e, 0x2204, 0x007e,
-	0x2112, 0x2019, 0x0000, 0x1078, 0x2742, 0x7810, 0xd0ec, 0x0040,
-	0x18c4, 0x017f, 0x0078, 0x15b9, 0x71c8, 0xa182, 0x0010, 0x0048,
-	0x18cd, 0x2110, 0x71c4, 0x0078, 0x15b1, 0x2011, 0x4e8e, 0x2204,
-	0x007e, 0x2112, 0xc3fd, 0x1078, 0x2742, 0x027f, 0x017f, 0x0078,
-	0x15b8, 0x71c4, 0x72c8, 0xa184, 0xfffd, 0x00c0, 0x15b1, 0xa284,
-	0xfffd, 0x00c0, 0x15b1, 0x2100, 0x7920, 0x7822, 0x2200, 0x7a24,
-	0x7826, 0x0078, 0x15b8, 0x71c4, 0xd1fc, 0x00c0, 0x18f3, 0x2011,
-	0x52c0, 0x0078, 0x18f5, 0x2011, 0x5340, 0x8107, 0xa084, 0x000f,
-	0x8003, 0x8003, 0x8003, 0xa268, 0x2019, 0x0000, 0x72c8, 0x2091,
-	0x8000, 0x6800, 0x007e, 0xa226, 0x0040, 0x191e, 0x6a02, 0xd4ec,
-	0x0040, 0x190b, 0xc3a5, 0xd4e4, 0x0040, 0x190f, 0xc39d, 0xd4f4,
-	0x0040, 0x191e, 0x810f, 0xd2f4, 0x0040, 0x191a, 0x1078, 0x27c1,
-	0x0078, 0x191e, 0x1078, 0x279f, 0x0078, 0x191e, 0x72cc, 0x6808,
-	0xa206, 0x0040, 0x1940, 0xa2a4, 0x00ff, 0x7814, 0xd0e4, 0x00c0,
-	0x1931, 0xa482, 0x0028, 0x0048, 0x193d, 0x0040, 0x193d, 0x0078,
-	0x1935, 0xa482, 0x0043, 0x0048, 0x193d, 0x71c4, 0x71c6, 0x027f,
-	0x72ca, 0x2091, 0x8001, 0x0078, 0x15b3, 0x6a0a, 0xa39d, 0x000a,
-	0x6804, 0xa305, 0x6806, 0x027f, 0x6b0c, 0x71c4, 0x2091, 0x8001,
-	0x0078, 0x15b7, 0x77c4, 0x1078, 0x1de4, 0x2091, 0x8000, 0x6a14,
-	0x6b1c, 0x2091, 0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e, 0x2708,
-	0x0078, 0x15b7, 0x70c4, 0x2061, 0x4e40, 0x6118, 0x601a, 0x7810,
-	0xd0ec, 0x00c0, 0x15b9, 0x70c8, 0x2061, 0x4e80, 0x6218, 0x601a,
-	0x0078, 0x15b8, 0x71c4, 0x72c8, 0x73cc, 0xa182, 0x0010, 0x00c8,
-	0x15b2, 0x1078, 0x27e3, 0xa384, 0x4000, 0x0040, 0x1979, 0xa295,
-	0x0020, 0x0078, 0x15b7, 0x77c4, 0x1078, 0x1de4, 0x2091, 0x8000,
-	0x6a08, 0xc28d, 0x6a0a, 0x2091, 0x8001, 0x2708, 0x0078, 0x15b8,
-	0x77c4, 0x1078, 0x1de4, 0x2091, 0x8000, 0x6a08, 0xa294, 0xfff9,
-	0x6a0a, 0x6804, 0xa005, 0x0040, 0x1997, 0x1078, 0x2628, 0x2091,
-	0x8001, 0x2708, 0x0078, 0x15b8, 0x77c4, 0x1078, 0x1de4, 0x2091,
-	0x8000, 0x6a08, 0xc295, 0x6a0a, 0x6804, 0xa005, 0x0040, 0x19aa,
-	0x1078, 0x2628, 0x2091, 0x8001, 0x2708, 0x0078, 0x15b8, 0x77c4,
-	0x2041, 0x0001, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000,
-	0x1078, 0x1dff, 0x2091, 0x8001, 0x2708, 0x6a08, 0x0078, 0x15b8,
-	0x77c4, 0x7814, 0xd0e4, 0x00c0, 0x19d4, 0xd7fc, 0x0040, 0x19ce,
-	0x1078, 0x1d64, 0x0040, 0x19d4, 0x0078, 0x15bc, 0x1078, 0x1d54,
-	0x0040, 0x19d4, 0x0078, 0x15bc, 0x73c8, 0x72cc, 0x77c6, 0x73ca,
-	0x72ce, 0x1078, 0x1e86, 0x00c0, 0x19fe, 0x6818, 0xa005, 0x0040,
-	0x19f8, 0x2708, 0x077e, 0x1078, 0x2813, 0x077f, 0x00c0, 0x19f8,
-	0x2001, 0x0015, 0xd7fc, 0x00c0, 0x19f1, 0x2061, 0x4e40, 0x0078,
-	0x19f4, 0xc0fd, 0x2061, 0x4e80, 0x782a, 0x2091, 0x8001, 0x007c,
-	0x2091, 0x8001, 0x2001, 0x4005, 0x0078, 0x15bc, 0x2091, 0x8001,
-	0x0078, 0x15ba, 0x77c4, 0x7814, 0xd0e4, 0x00c0, 0x1a16, 0xd7fc,
-	0x0040, 0x1a10, 0x1078, 0x1d64, 0x0040, 0x1a16, 0x0078, 0x15bc,
-	0x1078, 0x1d54, 0x0040, 0x1a16, 0x0078, 0x15bc, 0x77c6, 0x2041,
-	0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078,
-	0x1dff, 0x2009, 0x0016, 0xd7fc, 0x00c0, 0x1a2a, 0x2061, 0x4e40,
-	0x0078, 0x1a2d, 0x2061, 0x4e80, 0xc1fd, 0x6067, 0x0003, 0x607f,
-	0x0000, 0x6776, 0x6083, 0x000f, 0x792a, 0x61d4, 0xc1dc, 0x61d6,
-	0x1078, 0x2628, 0x2091, 0x8001, 0x007c, 0x77c8, 0x77ca, 0x77c4,
-	0x77c6, 0x7814, 0xd0e4, 0x00c0, 0x1a54, 0xd7fc, 0x0040, 0x1a4e,
-	0x1078, 0x1d64, 0x0040, 0x1a54, 0x0078, 0x15bc, 0x1078, 0x1d54,
-	0x0040, 0x1a54, 0x0078, 0x15bc, 0xa7bc, 0xff00, 0x2091, 0x8000,
-	0x2009, 0x0017, 0xd7fc, 0x00c0, 0x1a61, 0x2061, 0x4e40, 0x0078,
-	0x1a64, 0x2061, 0x4e80, 0xc1fd, 0x607f, 0x0000, 0x6067, 0x0002,
-	0x6776, 0x6083, 0x000f, 0x792a, 0x61d4, 0xc1dc, 0x61d6, 0x1078,
-	0x2628, 0x2091, 0x8001, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051,
-	0x0010, 0x2091, 0x8000, 0x70c8, 0xa005, 0x0040, 0x1a82, 0x60d4,
-	0xc0fd, 0x60d6, 0x1078, 0x1dff, 0x70c8, 0x6836, 0x8738, 0xa784,
-	0x001f, 0x00c0, 0x1a82, 0x2091, 0x8001, 0x007c, 0x2019, 0x0000,
-	0x7814, 0xd0e4, 0x00c0, 0x1aa4, 0x72c8, 0xd284, 0x0040, 0x1a9e,
-	0x1078, 0x1d64, 0x0040, 0x1aa4, 0x0078, 0x15bc, 0x1078, 0x1d54,
-	0x0040, 0x1aa4, 0x0078, 0x15bc, 0x72c8, 0x72ca, 0x78ac, 0xa084,
-	0x0003, 0x00c0, 0x1acf, 0x2039, 0x0000, 0xd284, 0x0040, 0x1ab1,
-	0xc7fd, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x1078,
-	0x1de4, 0x2091, 0x8000, 0x6808, 0xc0d4, 0xa80d, 0x690a, 0x2091,
-	0x8001, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1ab7, 0xa7bc, 0xff00,
-	0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, 0x1ab7, 0x2091,
-	0x8000, 0x72c8, 0xd284, 0x00c0, 0x1ae1, 0x7810, 0xd0ec, 0x0040,
-	0x1add, 0x2069, 0x0100, 0x0078, 0x1ae3, 0x2069, 0x0200, 0x0078,
-	0x1ae3, 0x2069, 0x0100, 0x6808, 0xa084, 0xfffd, 0x680a, 0x6830,
-	0xd0b4, 0x0040, 0x1b03, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848,
-	0xd094, 0x0040, 0x1af5, 0x00f0, 0x1aef, 0x684b, 0x0009, 0x20a9,
-	0x0014, 0x6848, 0xd084, 0x0040, 0x1aff, 0x00f0, 0x1af9, 0x20a9,
-	0x00fa, 0x00f0, 0x1b01, 0x2079, 0x4e00, 0x2009, 0x0018, 0x72c8,
-	0xd284, 0x00c0, 0x1b0f, 0x2061, 0x4e40, 0x0078, 0x1b12, 0x2061,
-	0x4e80, 0xc1fd, 0x607f, 0x0000, 0x792a, 0x6067, 0x0001, 0x6083,
-	0x000f, 0x60a7, 0x0000, 0x60a8, 0x60b2, 0x60b6, 0x60d4, 0xd0b4,
-	0x0040, 0x1b2e, 0xc0b4, 0x60d6, 0x0c7e, 0x60b8, 0xa065, 0x6008,
-	0xc0d4, 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f, 0x60d4, 0xa084,
-	0x77ff, 0x60d6, 0x78ac, 0xc08d, 0x78ae, 0x83ff, 0x0040, 0x1b39,
-	0x007c, 0x681b, 0x0047, 0x2091, 0x8001, 0x007c, 0x73cc, 0x1078,
-	0x1a90, 0x69ec, 0x6a48, 0xa185, 0x1800, 0x684a, 0xa185, 0x0040,
-	0x68ee, 0x73cc, 0x2021, 0x0004, 0x20a9, 0x09ff, 0x00f0, 0x1b4e,
-	0x8421, 0x00c0, 0x1b4c, 0x8319, 0x00c0, 0x1b4a, 0x69ee, 0x6a4a,
-	0x2091, 0x8001, 0x007c, 0xd7fc, 0x00c0, 0x1b62, 0x2069, 0x4e40,
-	0x0078, 0x1b64, 0x2069, 0x4e80, 0x71c4, 0x71c6, 0x6916, 0x81ff,
-	0x00c0, 0x1b6c, 0x68a7, 0x0001, 0x78ac, 0xc08c, 0x78ae, 0xd084,
-	0x00c0, 0x1b74, 0x1078, 0x1ee6, 0x007c, 0x75d8, 0x74dc, 0x75da,
-	0x74de, 0x0078, 0x1b7e, 0x2029, 0x0000, 0x2520, 0x71c4, 0x73c8,
-	0x72cc, 0x71c6, 0x73ca, 0x72ce, 0x2079, 0x4e00, 0x7dde, 0x7cda,
-	0x7bd6, 0x7ad2, 0x1078, 0x1dbd, 0x0040, 0x1c80, 0x20a9, 0x0005,
-	0x20a1, 0x4e14, 0x2091, 0x8000, 0x41a1, 0x2091, 0x8001, 0x2009,
-	0x0040, 0x1078, 0x1fd1, 0x0040, 0x1ba1, 0x1078, 0x1dc6, 0x0078,
-	0x1c80, 0x6004, 0xa08c, 0x00ff, 0xa18e, 0x0009, 0x00c0, 0x1bac,
-	0x007e, 0x1078, 0x2378, 0x007f, 0xa084, 0xff00, 0x8007, 0x8009,
-	0x0040, 0x1c20, 0x0c7e, 0x2c68, 0x1078, 0x1dbd, 0x0040, 0x1bf2,
-	0x2c00, 0x689e, 0x8109, 0x00c0, 0x1bb3, 0x609f, 0x0000, 0x0c7f,
-	0x0c7e, 0x7ddc, 0x7cd8, 0x7bd4, 0x7ad0, 0xa290, 0x0040, 0xa399,
-	0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x7dde, 0x7cda, 0x7bd6,
-	0x7ad2, 0x2c68, 0x689c, 0xa065, 0x0040, 0x1c1f, 0x2009, 0x0040,
-	0x1078, 0x1fd1, 0x00c0, 0x1c09, 0x6004, 0xa084, 0x00ff, 0xa086,
-	0x0002, 0x00c0, 0x1bf2, 0x6004, 0xa084, 0x00ff, 0xa086, 0x000a,
-	0x00c0, 0x1bee, 0x017e, 0x1078, 0x2374, 0x017f, 0x2d00, 0x6002,
-	0x0078, 0x1bc1, 0x0c7f, 0x0c7e, 0x609c, 0x1078, 0x1e49, 0x0c7f,
-	0x609f, 0x0000, 0x1078, 0x1c84, 0x2009, 0x0018, 0x6008, 0xc0cd,
-	0x600a, 0x6004, 0x6086, 0x1078, 0x1d74, 0x1078, 0x1dc6, 0x0078,
-	0x1c80, 0x0c7f, 0x0c7e, 0x609c, 0x1078, 0x1e49, 0x0c7f, 0x609f,
-	0x0000, 0x1078, 0x1c84, 0x2009, 0x0018, 0x6087, 0x0103, 0x601b,
-	0x0003, 0x1078, 0x1d74, 0x1078, 0x1dc6, 0x0078, 0x1c80, 0x0c7f,
-	0x7814, 0xd0e4, 0x00c0, 0x1c45, 0x6114, 0xd1fc, 0x0040, 0x1c2e,
-	0x1078, 0x1d64, 0x0040, 0x1c45, 0x0078, 0x1c32, 0x1078, 0x1d54,
-	0x0040, 0x1c45, 0x2029, 0x0000, 0x2520, 0x2009, 0x0018, 0x73c8,
-	0x72cc, 0x6087, 0x0103, 0x601b, 0x0021, 0x1078, 0x1d74, 0x1078,
-	0x1dc6, 0x2001, 0x4007, 0x0078, 0x15bc, 0x74c4, 0x73c8, 0x72cc,
-	0x6014, 0x2091, 0x8000, 0x0e7e, 0x2009, 0x0012, 0xd0fc, 0x00c0,
-	0x1c55, 0x2071, 0x4e40, 0x0078, 0x1c58, 0x2071, 0x4e80, 0xc1fd,
-	0x792a, 0x7067, 0x0005, 0x71d4, 0xc1dc, 0x71d6, 0x736a, 0x726e,
-	0x7472, 0x7076, 0x707b, 0x0000, 0x2c00, 0x707e, 0xa02e, 0x2530,
-	0x611c, 0xa184, 0x0060, 0x0040, 0x1c6f, 0x1078, 0x4632, 0x0e7f,
-	0x6596, 0x65a6, 0x669a, 0x66aa, 0x60af, 0x0000, 0x60b3, 0x0000,
-	0x6714, 0x6023, 0x0000, 0x1078, 0x2628, 0x2091, 0x8001, 0x007c,
-	0x70c3, 0x4005, 0x0078, 0x15bd, 0x20a9, 0x0005, 0x2099, 0x4e14,
-	0x2091, 0x8000, 0x530a, 0x2091, 0x8001, 0x2100, 0xa210, 0xa399,
-	0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x007c, 0x71c4, 0x70c7,
-	0x0000, 0x791e, 0x0078, 0x15ba, 0x71c4, 0x71c6, 0x2168, 0x0078,
-	0x1ca3, 0x2069, 0x1000, 0x690c, 0xa016, 0x2d04, 0xa210, 0x8d68,
-	0x8109, 0x00c0, 0x1ca5, 0xa285, 0x0000, 0x00c0, 0x1cb3, 0x70c3,
-	0x4000, 0x0078, 0x1cb5, 0x70c3, 0x4003, 0x70ca, 0x0078, 0x15bd,
-	0x7964, 0x71c6, 0x71c4, 0xa182, 0x0003, 0x00c8, 0x15b2, 0x7966,
-	0x0078, 0x15ba, 0x7964, 0x71c6, 0x0078, 0x15ba, 0x7900, 0x71c6,
-	0x71c4, 0x7902, 0x0078, 0x15ba, 0x7900, 0x71c6, 0x0078, 0x15ba,
-	0x70c4, 0x2011, 0x0000, 0xa08c, 0x000d, 0x0040, 0x1ce5, 0x810c,
-	0x0048, 0x1ce1, 0x8210, 0x810c, 0x810c, 0x0048, 0x1ce1, 0x8210,
-	0x810c, 0x81ff, 0x00c0, 0x15b3, 0x8210, 0x7a0e, 0xd28c, 0x0040,
-	0x1d11, 0x7910, 0xc1cd, 0x7912, 0x2009, 0x0021, 0x2019, 0x0003,
-	0xd284, 0x0040, 0x1d0b, 0x8108, 0x2019, 0x0041, 0x2011, 0x964e,
-	0x2312, 0x2019, 0x0042, 0x8210, 0x2312, 0x2019, 0x0043, 0x8210,
-	0x2312, 0x2019, 0x0046, 0x8210, 0x2312, 0x2019, 0x0047, 0x8210,
-	0x2312, 0x2019, 0x0006, 0x2011, 0x9653, 0x2112, 0x2011, 0x9673,
-	0x2312, 0x7904, 0x7806, 0x0078, 0x15b9, 0x7804, 0x70c6, 0x0078,
-	0x15ba, 0x71c4, 0xd1fc, 0x00c0, 0x1d21, 0x2011, 0x52c0, 0x0078,
-	0x1d23, 0x2011, 0x5340, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003,
-	0x8003, 0xa268, 0x6a14, 0xd2b4, 0x0040, 0x1d32, 0x2011, 0x0001,
-	0x0078, 0x1d34, 0x2011, 0x0000, 0x6b0c, 0x6800, 0x70da, 0x0078,
-	0x15b7, 0x017e, 0x7814, 0xd0f4, 0x0040, 0x1d46, 0x2001, 0x4007,
-	0x70db, 0x0000, 0xa18d, 0x0001, 0x0078, 0x1d52, 0xd0fc, 0x0040,
-	0x1d51, 0x2001, 0x4007, 0x70db, 0x0001, 0xa18d, 0x0001, 0x0078,
-	0x1d52, 0xa006, 0x017f, 0x007c, 0x017e, 0x7814, 0xd0f4, 0x0040,
-	0x1d61, 0x2001, 0x4007, 0x70db, 0x0000, 0xa18d, 0x0001, 0x0078,
-	0x1d62, 0xa006, 0x017f, 0x007c, 0x017e, 0x7814, 0xd0fc, 0x0040,
-	0x1d71, 0x2001, 0x4007, 0x70db, 0x0001, 0xa18d, 0x0001, 0x0078,
-	0x1d72, 0xa006, 0x017f, 0x007c, 0x7112, 0x721a, 0x731e, 0x7810,
-	0xd0c4, 0x0040, 0x1d7d, 0x7422, 0x7526, 0xac80, 0x0001, 0x8108,
-	0x810c, 0x81a9, 0x8098, 0x20a1, 0x0030, 0x7003, 0x0000, 0x6084,
-	0x20a2, 0x53a6, 0x7007, 0x0001, 0x7974, 0xa184, 0xff00, 0x0040,
-	0x1d9a, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100,
-	0x0078, 0x1d9d, 0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78,
-	0xa006, 0xa211, 0x7d10, 0xd5c4, 0x0040, 0x1daa, 0x7b84, 0xa319,
-	0x7c80, 0xa421, 0x7008, 0xd0fc, 0x0040, 0x1daa, 0x7003, 0x0001,
-	0x7007, 0x0006, 0x711a, 0x721e, 0x7d10, 0xd5c4, 0x0040, 0x1dba,
-	0x7322, 0x7426, 0xa084, 0x01e0, 0x007c, 0x7848, 0xa065, 0x0040,
-	0x1dc5, 0x2c04, 0x784a, 0x2063, 0x0000, 0x007c, 0x0f7e, 0x2079,
-	0x4e00, 0x7848, 0x2062, 0x2c00, 0xa005, 0x00c0, 0x1dd1, 0x1078,
-	0x296b, 0x784a, 0x0f7f, 0x007c, 0x2011, 0x9800, 0x7a4a, 0x7bc4,
-	0x8319, 0x0040, 0x1de1, 0xa280, 0x0032, 0x2012, 0x2010, 0x0078,
-	0x1dd8, 0x2013, 0x0000, 0x007c, 0x017e, 0x027e, 0xd7fc, 0x00c0,
-	0x1ded, 0x2011, 0x53c0, 0x0078, 0x1def, 0x2011, 0x73c0, 0xa784,
-	0x0f00, 0x800b, 0xa784, 0x001f, 0x0040, 0x1dfa, 0x8003, 0x8003,
-	0x8003, 0x8003, 0xa105, 0xa268, 0x027f, 0x017f, 0x007c, 0x1078,
-	0x1de4, 0x2900, 0x682a, 0x2a00, 0x682e, 0x6808, 0xa084, 0xf9ef,
-	0xa80d, 0x690a, 0x0e7e, 0xd7fc, 0x00c0, 0x1e14, 0x2009, 0x4e53,
-	0x2071, 0x4e40, 0x0078, 0x1e18, 0x2009, 0x4e93, 0x2071, 0x4e80,
-	0x210c, 0x6804, 0xa005, 0x0040, 0x1e28, 0xa116, 0x00c0, 0x1e28,
-	0x2060, 0x6000, 0x6806, 0x017e, 0x200b, 0x0000, 0x0078, 0x1e2b,
-	0x2009, 0x0000, 0x017e, 0x6804, 0xa065, 0x0040, 0x1e40, 0x6000,
-	0x6806, 0x1078, 0x1e5b, 0x1078, 0x201d, 0x6810, 0x7908, 0x8109,
-	0x790a, 0x8001, 0x6812, 0x00c0, 0x1e2b, 0x7910, 0xc1a5, 0x7912,
-	0x017f, 0x6902, 0x6906, 0x2d00, 0x2060, 0x1078, 0x2acc, 0x0e7f,
-	0x007c, 0xa065, 0x0040, 0x1e5a, 0x2008, 0x609c, 0xa005, 0x0040,
-	0x1e57, 0x2062, 0x609f, 0x0000, 0xa065, 0x0078, 0x1e4d, 0x7848,
-	0x794a, 0x2062, 0x007c, 0x6007, 0x0103, 0x608f, 0x0000, 0x20a9,
-	0x001c, 0xac80, 0x0005, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x6828,
-	0x601a, 0x682c, 0x6022, 0x007c, 0x0e7e, 0xd7fc, 0x00c0, 0x1e76,
-	0x2071, 0x4e40, 0x2031, 0x4ec0, 0x0078, 0x1e7a, 0x2071, 0x4e80,
-	0x2031, 0x50c0, 0x7050, 0xa08c, 0x0200, 0x00c0, 0x1e84, 0xa608,
-	0x2d0a, 0x8000, 0x7052, 0xa006, 0x0e7f, 0x007c, 0x0f7e, 0xd7fc,
-	0x00c0, 0x1e8e, 0x2079, 0x4e40, 0x0078, 0x1e90, 0x2079, 0x4e80,
-	0x1078, 0x1de4, 0x2091, 0x8000, 0x6804, 0x780a, 0xa065, 0x0040,
-	0x1ee4, 0x0078, 0x1ea2, 0x2c00, 0x780a, 0x2060, 0x6000, 0xa065,
-	0x0040, 0x1ee4, 0x6010, 0xa306, 0x00c0, 0x1e9b, 0x600c, 0xa206,
-	0x00c0, 0x1e9b, 0x2c28, 0x784c, 0xac06, 0x00c0, 0x1eb1, 0x0078,
-	0x1ee1, 0x6804, 0xac06, 0x00c0, 0x1ebf, 0x6000, 0x2060, 0x6806,
-	0xa005, 0x00c0, 0x1ebf, 0x6803, 0x0000, 0x0078, 0x1ec9, 0x6400,
-	0x7808, 0x2060, 0x6402, 0xa486, 0x0000, 0x00c0, 0x1ec9, 0x2c00,
-	0x6802, 0x2560, 0x0f7f, 0x1078, 0x1e5b, 0x0f7e, 0x601b, 0x0005,
-	0x6023, 0x0020, 0x0f7f, 0x1078, 0x201d, 0x0f7e, 0x7908, 0x8109,
-	0x790a, 0x6810, 0x8001, 0x6812, 0x00c0, 0x1ee1, 0x7810, 0xc0a5,
-	0x7812, 0x2001, 0xffff, 0xa005, 0x0f7f, 0x007c, 0x077e, 0x2700,
-	0x2039, 0x0000, 0xd0fc, 0x0040, 0x1eee, 0xc7fd, 0x2041, 0x0021,
-	0x2049, 0x0004, 0x2051, 0x0008, 0x2091, 0x8000, 0x1078, 0x1dff,
-	0x8738, 0xa784, 0x001f, 0x00c0, 0x1ef6, 0xa7bc, 0xff00, 0x873f,
-	0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, 0x1ef6, 0x2091, 0x8001,
-	0x077f, 0x007c, 0x786c, 0x2009, 0x9674, 0x210c, 0xa10d, 0x0040,
-	0x1f14, 0xa065, 0x0078, 0x2395, 0x2061, 0x0000, 0x6018, 0xd084,
-	0x00c0, 0x1f34, 0x7810, 0xd08c, 0x0040, 0x1f25, 0xc08c, 0x7812,
-	0xc7fc, 0x2069, 0x4e40, 0x0078, 0x1f2a, 0xc08d, 0x7812, 0x2069,
-	0x4e80, 0xc7fd, 0x2091, 0x8000, 0x681c, 0x681f, 0x0000, 0x2091,
-	0x8001, 0xa005, 0x00c0, 0x1f35, 0x007c, 0xa08c, 0xfff0, 0x0040,
-	0x1f3b, 0x1078, 0x296b, 0x0079, 0x1f3d, 0x1f4d, 0x1f50, 0x1f56,
-	0x1f5a, 0x1f4e, 0x1f5e, 0x1f4e, 0x1f4e, 0x1f4e, 0x1f64, 0x1f95,
-	0x1f99, 0x1f9f, 0x1fb4, 0x1f4e, 0x1f4e, 0x007c, 0x1078, 0x296b,
-	0x1078, 0x1ee6, 0x2001, 0x8001, 0x0078, 0x1fc0, 0x2001, 0x8003,
-	0x0078, 0x1fc0, 0x2001, 0x8004, 0x0078, 0x1fc0, 0x1078, 0x1ee6,
-	0x2001, 0x8006, 0x0078, 0x1fc0, 0x2091, 0x8000, 0x077e, 0xd7fc,
-	0x00c0, 0x1f70, 0x2069, 0x4e40, 0x2039, 0x0009, 0x0078, 0x1f74,
-	0x2069, 0x4e80, 0x2039, 0x0009, 0x6800, 0xa086, 0x0000, 0x0040,
-	0x1f7e, 0x007f, 0x6f1e, 0x2091, 0x8001, 0x007c, 0x6874, 0x077f,
-	0xa0bc, 0xff00, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0010,
-	0x1078, 0x1dff, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1f88, 0x2091,
-	0x8001, 0x2001, 0x800a, 0x0078, 0x1fc0, 0x2001, 0x800c, 0x0078,
-	0x1fc0, 0x1078, 0x1ee6, 0x2001, 0x800d, 0x0078, 0x1fc0, 0x7814,
-	0xd0e4, 0x00c0, 0x1fb2, 0xd0ec, 0x0040, 0x1fac, 0xd7fc, 0x0040,
-	0x1fac, 0x78e4, 0x0078, 0x1fad, 0x78e0, 0x70c6, 0x2001, 0x800e,
-	0x0078, 0x1fc0, 0x0078, 0x1f4e, 0xd7fc, 0x0040, 0x1fba, 0x78ec,
-	0x0078, 0x1fbb, 0x78e8, 0x70c6, 0x2001, 0x800f, 0x0078, 0x1fc0,
-	0x70c2, 0xd7fc, 0x00c0, 0x1fc8, 0x70db, 0x0000, 0x0078, 0x1fca,
-	0x70db, 0x0001, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x4080,
-	0x007c, 0xac80, 0x0001, 0x81ff, 0x0040, 0x1ffc, 0x2099, 0x0030,
-	0x20a0, 0x700c, 0xa084, 0x03ff, 0x0040, 0x1fde, 0x7018, 0x007e,
-	0x701c, 0x007e, 0x7020, 0x007e, 0x7024, 0x007e, 0x7112, 0x81ac,
-	0x721a, 0x731e, 0x7422, 0x7526, 0x7003, 0x0001, 0x7007, 0x0001,
-	0x7008, 0x800b, 0x00c8, 0x1ff0, 0x7007, 0x0002, 0xa08c, 0x01e0,
-	0x00c0, 0x1ffc, 0x53a5, 0xa006, 0x7003, 0x0000, 0x7007, 0x0004,
-	0x007f, 0x7026, 0x007f, 0x7022, 0x007f, 0x701e, 0x007f, 0x701a,
-	0x007c, 0x2011, 0x0020, 0x2009, 0x0010, 0x6b0a, 0x6c0e, 0x6803,
-	0xfd00, 0x6807, 0x0018, 0x6a1a, 0x2d00, 0xa0e8, 0x0008, 0xa290,
-	0x0004, 0x8109, 0x00c0, 0x200d, 0x007c, 0x6004, 0x6086, 0x2c08,
-	0x2063, 0x0000, 0x7868, 0xa005, 0x796a, 0x0040, 0x202a, 0x2c02,
-	0x0078, 0x202b, 0x796e, 0x007c, 0x0c7e, 0x2061, 0x4e00, 0x6887,
-	0x0103, 0x2d08, 0x206b, 0x0000, 0x6068, 0xa005, 0x616a, 0x0040,
-	0x203c, 0x2d02, 0x0078, 0x203d, 0x616e, 0x0c7f, 0x007c, 0x2091,
-	0x8000, 0x2c04, 0x786e, 0xa005, 0x00c0, 0x2047, 0x786a, 0x2091,
-	0x8001, 0x609c, 0xa005, 0x0040, 0x2060, 0x0c7e, 0x2060, 0x2008,
-	0x609c, 0xa005, 0x0040, 0x205c, 0x2062, 0x609f, 0x0000, 0xa065,
-	0x609c, 0xa005, 0x00c0, 0x2054, 0x7848, 0x794a, 0x2062, 0x0c7f,
-	0x7848, 0x2062, 0x609f, 0x0000, 0xac85, 0x0000, 0x00c0, 0x206a,
-	0x1078, 0x296b, 0x784a, 0x007c, 0x20a9, 0x0010, 0xa006, 0x8004,
-	0x8086, 0x818e, 0x00c8, 0x2075, 0xa200, 0x00f0, 0x2070, 0x8086,
-	0x818e, 0x007c, 0x157e, 0x20a9, 0x0010, 0xa005, 0x0040, 0x209b,
-	0xa11a, 0x00c8, 0x209b, 0x8213, 0x818d, 0x0048, 0x208e, 0xa11a,
-	0x00c8, 0x208f, 0x00f0, 0x2083, 0x0078, 0x2093, 0xa11a, 0x2308,
-	0x8210, 0x00f0, 0x2083, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080,
-	0x007f, 0x157f, 0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078,
-	0x2097, 0x7d74, 0x70d0, 0xa506, 0x0040, 0x2187, 0x7810, 0x2050,
-	0x7800, 0xd08c, 0x0040, 0x20c3, 0xdaec, 0x0040, 0x20c3, 0x0e7e,
-	0x2091, 0x8000, 0x2071, 0x0020, 0x7004, 0xa005, 0x00c0, 0x20c0,
-	0x7008, 0x0e7f, 0xa086, 0x0008, 0x0040, 0x20c3, 0x0078, 0x2187,
-	0x0e7f, 0x0078, 0x2187, 0x1078, 0x1dbd, 0x0040, 0x2187, 0xa046,
-	0x7970, 0x2500, 0x8000, 0xa112, 0x2009, 0x0040, 0x00c8, 0x20d2,
-	0x0078, 0x20d9, 0x72d0, 0xa206, 0x0040, 0x20d9, 0x8840, 0x2009,
-	0x0080, 0x0c7e, 0x7112, 0x7007, 0x0001, 0x2099, 0x0030, 0x20a9,
-	0x0020, 0xac80, 0x0001, 0x20a0, 0x2061, 0x0000, 0x88ff, 0x0040,
-	0x20eb, 0x1078, 0x1dbd, 0x7008, 0xd0fc, 0x0040, 0x20eb, 0x7007,
-	0x0002, 0x2091, 0x8001, 0xa08c, 0x01e0, 0x00c0, 0x2122, 0x53a5,
-	0x8cff, 0x00c0, 0x2100, 0x88ff, 0x0040, 0x2171, 0x0078, 0x210a,
-	0x2c00, 0x788e, 0x20a9, 0x0020, 0xac80, 0x0001, 0x20a0, 0x53a5,
-	0x0078, 0x2171, 0xa046, 0x7218, 0x731c, 0xdac4, 0x0040, 0x2112,
-	0x7420, 0x7524, 0xa292, 0x0040, 0xa39b, 0x0000, 0xa4a3, 0x0000,
-	0xa5ab, 0x0000, 0x721a, 0x731e, 0xdac4, 0x0040, 0x2122, 0x7422,
-	0x7526, 0xa006, 0x7007, 0x0004, 0x0040, 0x2171, 0x8cff, 0x0040,
-	0x212b, 0x1078, 0x1dc6, 0x0c7f, 0x1078, 0x1dc6, 0xa046, 0x7888,
-	0x8000, 0x788a, 0xa086, 0x0002, 0x0040, 0x2151, 0x7a7c, 0x7b78,
-	0xdac4, 0x0040, 0x213d, 0x7c84, 0x7d80, 0x7974, 0x8107, 0x8004,
-	0x8004, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000,
-	0x721a, 0x731e, 0xdac4, 0x0040, 0x2187, 0x7422, 0x7526, 0x0078,
-	0x2187, 0x6014, 0xd0fc, 0x00c0, 0x2159, 0x2069, 0x4e40, 0x0078,
-	0x215b, 0x2069, 0x4e80, 0x2091, 0x8000, 0x681f, 0x0002, 0x88ff,
-	0x0040, 0x2167, 0xa046, 0x788c, 0x2060, 0x0078, 0x2151, 0x788b,
-	0x0000, 0x78ac, 0xa085, 0x0003, 0x78ae, 0x2091, 0x8001, 0x0078,
-	0x2187, 0x0c7f, 0x788b, 0x0000, 0x1078, 0x2346, 0x6004, 0xa084,
-	0x000f, 0x1078, 0x2188, 0x88ff, 0x0040, 0x2185, 0x788c, 0x2060,
-	0x6004, 0xa084, 0x000f, 0x1078, 0x2188, 0x0078, 0x20a1, 0x007c,
-	0x0079, 0x218a, 0x219a, 0x21b8, 0x21d6, 0x219a, 0x21e7, 0x21ab,
-	0x219a, 0x219a, 0x219a, 0x21b6, 0x21d4, 0x219a, 0x219a, 0x219a,
-	0x219a, 0x219a, 0x2039, 0x0400, 0x78bc, 0xa705, 0x78be, 0x6008,
-	0xa705, 0x600a, 0x1078, 0x222a, 0x609c, 0x78ba, 0x609f, 0x0000,
-	0x1078, 0x2330, 0x007c, 0x78bc, 0xd0c4, 0x0040, 0x21b1, 0x0078,
-	0x219a, 0x601c, 0xc0bd, 0x601e, 0x0078, 0x21be, 0x1078, 0x2378,
-	0x78bc, 0xd0c4, 0x0040, 0x21be, 0x0078, 0x219a, 0x78bf, 0x0000,
-	0x6004, 0x8007, 0xa084, 0x00ff, 0x78b2, 0x8001, 0x0040, 0x21d1,
-	0x1078, 0x222a, 0x0040, 0x21d1, 0x78bc, 0xc0c5, 0x78be, 0x0078,
-	0x21d3, 0x0078, 0x2249, 0x007c, 0x1078, 0x2374, 0x78bc, 0xa08c,
-	0x0e00, 0x00c0, 0x21de, 0xd0c4, 0x00c0, 0x21e0, 0x0078, 0x219a,
-	0x1078, 0x222a, 0x00c0, 0x21e6, 0x0078, 0x2249, 0x007c, 0x78bc,
-	0xd0c4, 0x0040, 0x21ed, 0x0078, 0x219a, 0x78bf, 0x0000, 0x6714,
-	0x2011, 0x0001, 0x22a8, 0x6018, 0xa084, 0x00ff, 0xa005, 0x0040,
-	0x220d, 0xa7bc, 0xff00, 0x20a9, 0x0020, 0xa08e, 0x0001, 0x0040,
-	0x220d, 0xa7bc, 0x8000, 0x2011, 0x0002, 0x20a9, 0x0100, 0xa08e,
-	0x0002, 0x0040, 0x220d, 0x0078, 0x2227, 0x1078, 0x1de4, 0x2d00,
-	0x2091, 0x8000, 0x682b, 0x0000, 0x682f, 0x0000, 0x6808, 0xa084,
-	0xffde, 0x680a, 0xade8, 0x0010, 0x2091, 0x8001, 0x00f0, 0x2210,
-	0x8211, 0x0040, 0x2227, 0x20a9, 0x0100, 0x0078, 0x2210, 0x1078,
-	0x1dc6, 0x007c, 0x609f, 0x0000, 0x78b4, 0xa06d, 0x2c00, 0x78b6,
-	0x00c0, 0x2235, 0x78ba, 0x0078, 0x223d, 0x689e, 0x2d00, 0x6002,
-	0x78b8, 0xad06, 0x00c0, 0x223d, 0x6002, 0x78b0, 0x8001, 0x78b2,
-	0x00c0, 0x2248, 0x78bc, 0xc0c4, 0x78be, 0x78b8, 0x2060, 0xa006,
-	0x007c, 0x0e7e, 0xa02e, 0x2530, 0x7dba, 0x7db6, 0x65ae, 0x65b2,
-	0x601c, 0x60a2, 0x2048, 0xa984, 0xe1ff, 0x601e, 0xa984, 0x0060,
-	0x0040, 0x225c, 0x1078, 0x4632, 0x6596, 0x65a6, 0x669a, 0x66aa,
-	0x6714, 0x2071, 0x4e80, 0xd7fc, 0x00c0, 0x2268, 0x2071, 0x4e40,
-	0xa784, 0x0f00, 0x800b, 0xa784, 0x001f, 0x0040, 0x2273, 0x8003,
-	0x8003, 0x8003, 0x8003, 0xa105, 0x71c4, 0xa168, 0x2700, 0x8007,
-	0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0x71c8, 0xa100, 0x60c2,
-	0x2091, 0x8000, 0x7814, 0xd0c4, 0x0040, 0x2298, 0xd0ec, 0x0040,
-	0x2294, 0xd7fc, 0x00c0, 0x2291, 0xd0f4, 0x00c0, 0x229f, 0x0078,
-	0x2298, 0xd0fc, 0x00c0, 0x229f, 0x7810, 0xd0f4, 0x00c0, 0x229f,
-	0x6e08, 0xd684, 0x0040, 0x22c9, 0xd9fc, 0x00c0, 0x22c9, 0x2091,
-	0x8001, 0x1078, 0x1e5b, 0x2091, 0x8000, 0x1078, 0x201d, 0x2091,
-	0x8001, 0x7814, 0xd0e4, 0x00c0, 0x232e, 0x7814, 0xd0c4, 0x0040,
-	0x232e, 0xd0ec, 0x0040, 0x22c1, 0xd7fc, 0x00c0, 0x22bc, 0xd0f4,
-	0x00c0, 0x22c5, 0x0078, 0x232e, 0xd0fc, 0x00c0, 0x22c5, 0x0078,
-	0x232e, 0x7810, 0xd0f4, 0x0040, 0x232e, 0x601b, 0x0021, 0x0078,
-	0x232e, 0x6024, 0xa096, 0x0001, 0x00c0, 0x22d0, 0x8000, 0x6026,
-	0x6a10, 0x6814, 0xa202, 0x0048, 0x22e3, 0x0040, 0x22e3, 0x2091,
-	0x8001, 0x2039, 0x0200, 0x609c, 0x78ba, 0x609f, 0x0000, 0x1078,
-	0x2330, 0x0078, 0x232e, 0x2c08, 0xd9fc, 0x0040, 0x230b, 0x6800,
-	0xa065, 0x0040, 0x230b, 0x6a04, 0x7000, 0xa084, 0x0002, 0x0040,
-	0x2301, 0x704c, 0xa206, 0x00c0, 0x2301, 0x6b04, 0x2160, 0x2304,
-	0x6002, 0xa005, 0x00c0, 0x22fd, 0x6902, 0x2260, 0x6102, 0x0078,
-	0x2317, 0x2d00, 0x2060, 0x1078, 0x2acc, 0x6e08, 0x2160, 0x6202,
-	0x6906, 0x0078, 0x2317, 0x6800, 0x6902, 0xa065, 0x0040, 0x2313,
-	0x6102, 0x0078, 0x2314, 0x6906, 0x2160, 0x6003, 0x0000, 0x2160,
-	0xd9fc, 0x0040, 0x231e, 0xa6b4, 0xfffc, 0x6e0a, 0x6810, 0x7d08,
-	0x8528, 0x7d0a, 0x8000, 0x6812, 0x2091, 0x8001, 0xd6b4, 0x0040,
-	0x232e, 0xa6b6, 0x0040, 0x6e0a, 0x1078, 0x1e6c, 0x0e7f, 0x007c,
-	0x6008, 0xa705, 0x600a, 0x2091, 0x8000, 0x1078, 0x201d, 0x2091,
-	0x8001, 0x78b8, 0xa065, 0x0040, 0x2343, 0x609c, 0x78ba, 0x609f,
-	0x0000, 0x0078, 0x2330, 0x78b6, 0x78ba, 0x007c, 0x7970, 0x7874,
-	0x2818, 0xd384, 0x0040, 0x2350, 0x8000, 0xa112, 0x0048, 0x2355,
-	0x8000, 0xa112, 0x00c8, 0x2365, 0xc384, 0x7a7c, 0x721a, 0x7a78,
-	0x721e, 0xdac4, 0x0040, 0x2360, 0x7a84, 0x7222, 0x7a80, 0x7226,
-	0xa006, 0xd384, 0x0040, 0x2365, 0x8000, 0x7876, 0x70d2, 0x781c,
-	0xa005, 0x0040, 0x2373, 0x8001, 0x781e, 0x00c0, 0x2373, 0x0068,
-	0x2373, 0x2091, 0x4080, 0x007c, 0x2039, 0x238c, 0x0078, 0x237a,
-	0x2039, 0x2392, 0x2704, 0xa005, 0x0040, 0x238b, 0xac00, 0x2068,
-	0x6908, 0x6810, 0x6912, 0x680a, 0x690c, 0x6814, 0x6916, 0x680e,
-	0x8738, 0x0078, 0x237a, 0x007c, 0x0003, 0x0009, 0x000f, 0x0015,
-	0x001b, 0x0000, 0x0015, 0x001b, 0x0000, 0x2041, 0x0000, 0x780c,
-	0x0079, 0x239a, 0x256c, 0x253f, 0x239e, 0x2417, 0x2039, 0x9674,
-	0x2734, 0x7d10, 0x0078, 0x23be, 0x6084, 0xa086, 0x0103, 0x00c0,
-	0x2400, 0x6114, 0x6018, 0xa105, 0x0040, 0x23b3, 0x86ff, 0x00c0,
-	0x23cf, 0x0078, 0x2400, 0x8603, 0xa080, 0x9655, 0x620c, 0x2202,
-	0x8000, 0x6210, 0x2202, 0x1078, 0x203f, 0x8630, 0xa68e, 0x000f,
-	0x0040, 0x248b, 0x786c, 0xa065, 0x00c0, 0x23a4, 0x7808, 0xa602,
-	0x00c8, 0x23cf, 0xd5ac, 0x00c0, 0x23cf, 0x263a, 0x007c, 0xa682,
-	0x0003, 0x00c8, 0x248b, 0x2091, 0x8000, 0x2069, 0x0000, 0x6818,
-	0xd084, 0x00c0, 0x23fb, 0x2011, 0x9655, 0x2204, 0x70c6, 0x8210,
-	0x2204, 0x70ca, 0xd684, 0x00c0, 0x23eb, 0x8210, 0x2204, 0x70da,
-	0x8210, 0x2204, 0x70de, 0xa685, 0x8020, 0x70c2, 0x681b, 0x0001,
+	0x017f, 0x027f, 0x0078, 0x15bf, 0x2061, 0x4f40, 0x6130, 0x70c4,
+	0x6032, 0x7810, 0xd0ec, 0x00c0, 0x15c0, 0x2061, 0x4f80, 0x6230,
+	0x70c8, 0x6032, 0x0078, 0x15bf, 0x7918, 0x0078, 0x15c0, 0x71c4,
+	0xa184, 0xffcf, 0x0040, 0x18a3, 0x7810, 0xd0ec, 0x00c0, 0x15b9,
+	0x72c8, 0x0078, 0x15b8, 0x2011, 0x4f4d, 0x2204, 0x2112, 0x007e,
+	0x2019, 0x0000, 0x1078, 0x27ab, 0x7810, 0xd0ec, 0x0040, 0x18b3,
+	0x017f, 0x0078, 0x15c0, 0x71c8, 0xa184, 0xffcf, 0x0040, 0x18bc,
+	0x2110, 0x71c4, 0x0078, 0x15b8, 0x2011, 0x4f8d, 0x2204, 0x2112,
+	0x007e, 0xc3fd, 0x1078, 0x27ab, 0x027f, 0x017f, 0x0078, 0x15bf,
+	0x71c4, 0xa182, 0x0010, 0x0048, 0x18d4, 0x7810, 0xd0ec, 0x00c0,
+	0x15b9, 0x72c8, 0x0078, 0x15b8, 0x2011, 0x4f4e, 0x2204, 0x007e,
+	0x2112, 0x2019, 0x0000, 0x1078, 0x2789, 0x7810, 0xd0ec, 0x0040,
+	0x18e4, 0x017f, 0x0078, 0x15c0, 0x71c8, 0xa182, 0x0010, 0x0048,
+	0x18ed, 0x2110, 0x71c4, 0x0078, 0x15b8, 0x2011, 0x4f8e, 0x2204,
+	0x007e, 0x2112, 0xc3fd, 0x1078, 0x2789, 0x027f, 0x017f, 0x0078,
+	0x15bf, 0x71c4, 0x72c8, 0xa184, 0xfffd, 0x00c0, 0x15b8, 0xa284,
+	0xfffd, 0x00c0, 0x15b8, 0x2100, 0x7920, 0x7822, 0x2200, 0x7a24,
+	0x7826, 0x0078, 0x15bf, 0x71c4, 0xd1fc, 0x00c0, 0x1913, 0x2011,
+	0x53c0, 0x0078, 0x1915, 0x2011, 0x5440, 0x8107, 0xa084, 0x000f,
+	0x8003, 0x8003, 0x8003, 0xa268, 0x2019, 0x0000, 0x72c8, 0xd2bc,
+	0x0040, 0x1924, 0xa39d, 0x0010, 0xd2b4, 0x0040, 0x1929, 0xa39d,
+	0x0008, 0x2091, 0x8000, 0x6800, 0x007e, 0xa226, 0x0040, 0x1948,
+	0x6a02, 0xd4ec, 0x0040, 0x1935, 0xc3a5, 0xd4e4, 0x0040, 0x1939,
+	0xc39d, 0xd4f4, 0x0040, 0x1948, 0x810f, 0xd2f4, 0x0040, 0x1944,
+	0x1078, 0x2808, 0x0078, 0x1948, 0x1078, 0x27e6, 0x0078, 0x1948,
+	0x72cc, 0x6808, 0xa206, 0x0040, 0x196a, 0xa2a4, 0x00ff, 0x7814,
+	0xd0e4, 0x00c0, 0x195b, 0xa482, 0x0028, 0x0048, 0x1967, 0x0040,
+	0x1967, 0x0078, 0x195f, 0xa482, 0x0043, 0x0048, 0x1967, 0x71c4,
+	0x71c6, 0x027f, 0x72ca, 0x2091, 0x8001, 0x0078, 0x15ba, 0x6a0a,
+	0xa39d, 0x000a, 0x6804, 0xa305, 0x6806, 0x027f, 0x6b0c, 0x71c4,
+	0x2091, 0x8001, 0x0078, 0x15be, 0x77c4, 0x1078, 0x1e2b, 0x2091,
+	0x8000, 0x6a14, 0x6b1c, 0x2091, 0x8001, 0x70c8, 0x6816, 0x70cc,
+	0x681e, 0x2708, 0x0078, 0x15be, 0x70c4, 0x2061, 0x4f40, 0x6118,
+	0x601a, 0x7810, 0xd0ec, 0x00c0, 0x15c0, 0x70c8, 0x2061, 0x4f80,
+	0x6218, 0x601a, 0x0078, 0x15bf, 0x71c4, 0x72c8, 0x73cc, 0xa182,
+	0x0010, 0x00c8, 0x15b9, 0x1078, 0x282a, 0xa384, 0x4000, 0x0040,
+	0x19a3, 0xa295, 0x0020, 0x0078, 0x15be, 0x77c4, 0x1078, 0x1e2b,
+	0x2091, 0x8000, 0x6a08, 0xc28d, 0x6a0a, 0x2091, 0x8001, 0x2708,
+	0x0078, 0x15bf, 0x77c4, 0x1078, 0x1e2b, 0x2091, 0x8000, 0x6a08,
+	0xa294, 0xfff9, 0x6a0a, 0x6804, 0xa005, 0x0040, 0x19c1, 0x1078,
+	0x266f, 0x2091, 0x8001, 0x2708, 0x0078, 0x15bf, 0x77c4, 0x1078,
+	0x1e2b, 0x2091, 0x8000, 0x6a08, 0xc295, 0x6a0a, 0x6804, 0xa005,
+	0x0040, 0x19d4, 0x1078, 0x266f, 0x2091, 0x8001, 0x2708, 0x0078,
+	0x15bf, 0x77c4, 0x2041, 0x0001, 0x2049, 0x0005, 0x2051, 0x0020,
+	0x2091, 0x8000, 0x1078, 0x1e46, 0x2091, 0x8001, 0x2708, 0x6a08,
+	0x0078, 0x15bf, 0x77c4, 0x7814, 0xd0e4, 0x00c0, 0x19fe, 0xd7fc,
+	0x0040, 0x19f8, 0x1078, 0x1dae, 0x0040, 0x19fe, 0x0078, 0x15c3,
+	0x1078, 0x1da1, 0x0040, 0x19fe, 0x0078, 0x15c3, 0x73c8, 0x72cc,
+	0x77c6, 0x73ca, 0x72ce, 0x1078, 0x1ecd, 0x00c0, 0x1a28, 0x6818,
+	0xa005, 0x0040, 0x1a22, 0x2708, 0x077e, 0x1078, 0x285a, 0x077f,
+	0x00c0, 0x1a22, 0x2001, 0x0015, 0xd7fc, 0x00c0, 0x1a1b, 0x2061,
+	0x4f40, 0x0078, 0x1a1e, 0xc0fd, 0x2061, 0x4f80, 0x782a, 0x2091,
+	0x8001, 0x007c, 0x2091, 0x8001, 0x2001, 0x4005, 0x0078, 0x15c3,
+	0x2091, 0x8001, 0x0078, 0x15c1, 0x77c4, 0x7814, 0xd0e4, 0x00c0,
+	0x1a40, 0xd7fc, 0x0040, 0x1a3a, 0x1078, 0x1dae, 0x0040, 0x1a40,
+	0x0078, 0x15c3, 0x1078, 0x1da1, 0x0040, 0x1a40, 0x0078, 0x15c3,
+	0x77c6, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091,
+	0x8000, 0x1078, 0x1e46, 0x2009, 0x0016, 0xd7fc, 0x00c0, 0x1a54,
+	0x2061, 0x4f40, 0x0078, 0x1a57, 0x2061, 0x4f80, 0xc1fd, 0x6067,
+	0x0003, 0x607f, 0x0000, 0x6776, 0x6083, 0x000f, 0x792a, 0x61d4,
+	0xc1dc, 0x61d6, 0x1078, 0x266f, 0x2091, 0x8001, 0x007c, 0x77c8,
+	0x77ca, 0x77c4, 0x77c6, 0x7814, 0xd0e4, 0x00c0, 0x1a7e, 0xd7fc,
+	0x0040, 0x1a78, 0x1078, 0x1dae, 0x0040, 0x1a7e, 0x0078, 0x15c3,
+	0x1078, 0x1da1, 0x0040, 0x1a7e, 0x0078, 0x15c3, 0xa7bc, 0xff00,
+	0x2091, 0x8000, 0x2009, 0x0017, 0xd7fc, 0x00c0, 0x1a8b, 0x2061,
+	0x4f40, 0x0078, 0x1a8e, 0x2061, 0x4f80, 0xc1fd, 0x607f, 0x0000,
+	0x6067, 0x0002, 0x6776, 0x6083, 0x000f, 0x792a, 0x61d4, 0xc1dc,
+	0x61d6, 0x1078, 0x266f, 0x2091, 0x8001, 0x2041, 0x0021, 0x2049,
+	0x0005, 0x2051, 0x0010, 0x2091, 0x8000, 0x70c8, 0xa005, 0x0040,
+	0x1aac, 0x60d4, 0xc0fd, 0x60d6, 0x1078, 0x1e46, 0x70c8, 0x6836,
+	0x8738, 0xa784, 0x001f, 0x00c0, 0x1aac, 0x2091, 0x8001, 0x007c,
+	0x2019, 0x0000, 0x7814, 0xd0e4, 0x00c0, 0x1ace, 0x72c8, 0xd284,
+	0x0040, 0x1ac8, 0x1078, 0x1dae, 0x0040, 0x1ace, 0x0078, 0x15c3,
+	0x1078, 0x1da1, 0x0040, 0x1ace, 0x0078, 0x15c3, 0x72c8, 0x72ca,
+	0x78ac, 0xa084, 0x0003, 0x00c0, 0x1af9, 0x2039, 0x0000, 0xd284,
+	0x0040, 0x1adb, 0xc7fd, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051,
+	0x0008, 0x1078, 0x1e2b, 0x2091, 0x8000, 0x6808, 0xc0d4, 0xa80d,
+	0x690a, 0x2091, 0x8001, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1ae1,
+	0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0,
+	0x1ae1, 0x2091, 0x8000, 0x72c8, 0xd284, 0x00c0, 0x1b0b, 0x7810,
+	0xd0ec, 0x0040, 0x1b07, 0x2069, 0x0100, 0x0078, 0x1b0d, 0x2069,
+	0x0200, 0x0078, 0x1b0d, 0x2069, 0x0100, 0x6808, 0xa084, 0xfffd,
+	0x680a, 0x6830, 0xd0b4, 0x0040, 0x1b2d, 0x684b, 0x0004, 0x20a9,
+	0x0014, 0x6848, 0xd094, 0x0040, 0x1b1f, 0x00f0, 0x1b19, 0x684b,
+	0x0009, 0x20a9, 0x0014, 0x6848, 0xd084, 0x0040, 0x1b29, 0x00f0,
+	0x1b23, 0x20a9, 0x00fa, 0x00f0, 0x1b2b, 0x2079, 0x4f00, 0x2009,
+	0x0018, 0x72c8, 0xd284, 0x00c0, 0x1b39, 0x2061, 0x4f40, 0x0078,
+	0x1b3c, 0x2061, 0x4f80, 0xc1fd, 0x607f, 0x0000, 0x792a, 0x6067,
+	0x0001, 0x6083, 0x000f, 0x60a7, 0x0000, 0x60a8, 0x60b2, 0x60b6,
+	0x60d4, 0xd0b4, 0x0040, 0x1b58, 0xc0b4, 0x60d6, 0x0c7e, 0x60b8,
+	0xa065, 0x6008, 0xc0d4, 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f,
+	0x60d4, 0xa084, 0x77ff, 0x60d6, 0x78ac, 0xc08d, 0x78ae, 0x83ff,
+	0x0040, 0x1b63, 0x007c, 0x681b, 0x0047, 0x2091, 0x8001, 0x007c,
+	0x73cc, 0x1078, 0x1aba, 0x69ec, 0x6a48, 0xa185, 0x1800, 0x684a,
+	0xa185, 0x0040, 0x68ee, 0x73cc, 0x2021, 0x0004, 0x20a9, 0x09ff,
+	0x00f0, 0x1b78, 0x8421, 0x00c0, 0x1b76, 0x8319, 0x00c0, 0x1b74,
+	0x69ee, 0x6a4a, 0x2091, 0x8001, 0x007c, 0xd7fc, 0x00c0, 0x1b8c,
+	0x2069, 0x4f40, 0x0078, 0x1b8e, 0x2069, 0x4f80, 0x71c4, 0x71c6,
+	0x6916, 0x81ff, 0x00c0, 0x1b96, 0x68a7, 0x0001, 0x78ac, 0xc08c,
+	0x78ae, 0xd084, 0x00c0, 0x1b9e, 0x1078, 0x1f2d, 0x007c, 0x75d8,
+	0x74dc, 0x75da, 0x74de, 0x0078, 0x1ba7, 0xa02e, 0x2520, 0x71c4,
+	0x73c8, 0x72cc, 0x71c6, 0x73ca, 0x72ce, 0x2079, 0x4f00, 0x7dde,
+	0x7cda, 0x7bd6, 0x7ad2, 0x1078, 0x1e04, 0x0040, 0x1cd1, 0x20a9,
+	0x0005, 0x20a1, 0x4f14, 0x2091, 0x8000, 0x41a1, 0x2091, 0x8001,
+	0x2009, 0x0040, 0x1078, 0x2018, 0x0040, 0x1bca, 0x1078, 0x1e0d,
+	0x0078, 0x1cd1, 0x6004, 0xa08c, 0x00ff, 0xa18e, 0x0009, 0x00c0,
+	0x1bd5, 0x007e, 0x1078, 0x23bf, 0x007f, 0xa084, 0xff00, 0x8007,
+	0x8009, 0x0040, 0x1c61, 0x0c7e, 0x2c68, 0x1078, 0x1e04, 0x0040,
+	0x1c1b, 0x2c00, 0x689e, 0x8109, 0x00c0, 0x1bdc, 0x609f, 0x0000,
+	0x0c7f, 0x0c7e, 0x7ddc, 0x7cd8, 0x7bd4, 0x7ad0, 0xa290, 0x0040,
+	0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x7dde, 0x7cda,
+	0x7bd6, 0x7ad2, 0x2c68, 0x689c, 0xa065, 0x0040, 0x1c60, 0x2009,
+	0x0040, 0x1078, 0x2018, 0x00c0, 0x1c3e, 0x6004, 0xa084, 0x00ff,
+	0xa086, 0x0002, 0x00c0, 0x1c1b, 0x6004, 0xa084, 0x00ff, 0xa086,
+	0x000a, 0x00c0, 0x1c17, 0x017e, 0x1078, 0x23bb, 0x017f, 0x2d00,
+	0x6002, 0x0078, 0x1bea, 0x0c7f, 0x0c7e, 0x609c, 0x1078, 0x1e90,
+	0x0c7f, 0x609f, 0x0000, 0x1078, 0x1cd5, 0x2009, 0x0018, 0x6008,
+	0xc0cd, 0x600a, 0x6004, 0x6086, 0x7810, 0x007e, 0x84ff, 0x00c0,
+	0x1c34, 0x85ff, 0x0040, 0x1c36, 0xc0c5, 0x7812, 0x1078, 0x1dbb,
+	0x007f, 0x7812, 0x1078, 0x1e0d, 0x0078, 0x1cd1, 0x0c7f, 0x0c7e,
+	0x609c, 0x1078, 0x1e90, 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1cd5,
+	0x2009, 0x0018, 0x6087, 0x0103, 0x601b, 0x0003, 0x7810, 0x007e,
+	0x84ff, 0x00c0, 0x1c56, 0x85ff, 0x0040, 0x1c58, 0xc0c5, 0x7812,
+	0x1078, 0x1dbb, 0x007f, 0x7812, 0x1078, 0x1e0d, 0x0078, 0x1cd1,
+	0x0c7f, 0x7814, 0xd0e4, 0x00c0, 0x1c8f, 0x6114, 0xd1fc, 0x0040,
+	0x1c6f, 0x1078, 0x1dae, 0x0040, 0x1c8f, 0x0078, 0x1c73, 0x1078,
+	0x1da1, 0x0040, 0x1c8f, 0x1078, 0x1cd5, 0x2009, 0x0018, 0x6087,
+	0x0103, 0x601b, 0x0021, 0x7810, 0x007e, 0x84ff, 0x00c0, 0x1c83,
+	0x85ff, 0x0040, 0x1c85, 0xc0c5, 0x7812, 0x1078, 0x1dbb, 0x007f,
+	0x7812, 0x1078, 0x1e0d, 0x2001, 0x4007, 0x0078, 0x15c3, 0x74c4,
+	0x73c8, 0x72cc, 0x6014, 0x2091, 0x8000, 0x0e7e, 0x2009, 0x0012,
+	0xd0fc, 0x00c0, 0x1c9f, 0x2071, 0x4f40, 0x0078, 0x1ca2, 0x2071,
+	0x4f80, 0xc1fd, 0x792a, 0x7067, 0x0005, 0x71d4, 0xc1dc, 0x71d6,
+	0x736a, 0x726e, 0x7472, 0x7076, 0x707b, 0x0000, 0x2c00, 0x707e,
+	0xa02e, 0x2530, 0x611c, 0xa184, 0x0060, 0x0040, 0x1cb9, 0x1078,
+	0x46b6, 0x0e7f, 0x6596, 0x65a6, 0x669a, 0x66aa, 0x60af, 0x0000,
+	0x60b3, 0x0000, 0x6714, 0x6023, 0x0000, 0x6024, 0xa096, 0x0001,
+	0x00c0, 0x1ccc, 0x8000, 0x6026, 0x1078, 0x266f, 0x2091, 0x8001,
+	0x007c, 0x70c3, 0x4005, 0x0078, 0x15c4, 0x20a9, 0x0005, 0x2099,
+	0x4f14, 0x2091, 0x8000, 0x530a, 0x2091, 0x8001, 0x2100, 0xa210,
+	0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x007c, 0x71c4,
+	0x70c7, 0x0000, 0x791e, 0x0078, 0x15c1, 0x71c4, 0x71c6, 0x2168,
+	0x0078, 0x1cf4, 0x2069, 0x1000, 0x690c, 0xa016, 0x2d04, 0xa210,
+	0x8d68, 0x8109, 0x00c0, 0x1cf6, 0xa285, 0x0000, 0x00c0, 0x1d04,
+	0x70c3, 0x4000, 0x0078, 0x1d06, 0x70c3, 0x4003, 0x70ca, 0x0078,
+	0x15c4, 0x7964, 0x71c6, 0x71c4, 0xa182, 0x0003, 0x00c8, 0x15b9,
+	0x7966, 0x0078, 0x15c1, 0x7964, 0x71c6, 0x0078, 0x15c1, 0x7900,
+	0x71c6, 0x71c4, 0x7902, 0x0078, 0x15c1, 0x7900, 0x71c6, 0x0078,
+	0x15c1, 0x70c4, 0x2011, 0x0000, 0xa08c, 0x000d, 0x0040, 0x1d36,
+	0x810c, 0x0048, 0x1d32, 0x8210, 0x810c, 0x810c, 0x0048, 0x1d32,
+	0x8210, 0x810c, 0x81ff, 0x00c0, 0x15ba, 0x8210, 0x7a0e, 0xd28c,
+	0x0040, 0x1d62, 0x7910, 0xc1cd, 0x7912, 0x2009, 0x0021, 0x2019,
+	0x0003, 0xd284, 0x0040, 0x1d5c, 0x8108, 0x2019, 0x0041, 0x2011,
+	0x974e, 0x2312, 0x2019, 0x0042, 0x8210, 0x2312, 0x2019, 0x0043,
+	0x8210, 0x2312, 0x2019, 0x0046, 0x8210, 0x2312, 0x2019, 0x0047,
+	0x8210, 0x2312, 0x2019, 0x0006, 0x2011, 0x9753, 0x2112, 0x2011,
+	0x9773, 0x2312, 0x7904, 0x7806, 0x0078, 0x15c0, 0x7804, 0x70c6,
+	0x0078, 0x15c1, 0x71c4, 0xd1fc, 0x00c0, 0x1d72, 0x2011, 0x53c0,
+	0x0078, 0x1d74, 0x2011, 0x5440, 0x8107, 0xa084, 0x000f, 0x8003,
+	0x8003, 0x8003, 0xa268, 0x6a14, 0xd2b4, 0x0040, 0x1d83, 0x2011,
+	0x0001, 0x0078, 0x1d85, 0x2011, 0x0000, 0x6b0c, 0x6800, 0x70da,
+	0x0078, 0x15be, 0x7814, 0xd0f4, 0x0040, 0x1d95, 0x2001, 0x4007,
+	0x70db, 0x0000, 0xa005, 0x0078, 0x1da0, 0xd0fc, 0x0040, 0x1d9f,
+	0x2001, 0x4007, 0x70db, 0x0001, 0xa005, 0x0078, 0x1da0, 0xa006,
+	0x007c, 0x7814, 0xd0f4, 0x0040, 0x1dac, 0x2001, 0x4007, 0x70db,
+	0x0000, 0xa005, 0x0078, 0x1dad, 0xa006, 0x007c, 0x7814, 0xd0fc,
+	0x0040, 0x1db9, 0x2001, 0x4007, 0x70db, 0x0001, 0xa005, 0x0078,
+	0x1dba, 0xa006, 0x007c, 0x7112, 0x721a, 0x731e, 0x7810, 0xd0c4,
+	0x0040, 0x1dc4, 0x7422, 0x7526, 0xac80, 0x0001, 0x8108, 0x810c,
+	0x81a9, 0x8098, 0x20a1, 0x0030, 0x7003, 0x0000, 0x6084, 0x20a2,
+	0x53a6, 0x7007, 0x0001, 0x7974, 0xa184, 0xff00, 0x0040, 0x1de1,
+	0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0078,
+	0x1de4, 0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, 0xa006,
+	0xa211, 0x7d10, 0xd5c4, 0x0040, 0x1df1, 0x7b84, 0xa319, 0x7c80,
+	0xa421, 0x7008, 0xd0fc, 0x0040, 0x1df1, 0x7003, 0x0001, 0x7007,
+	0x0006, 0x711a, 0x721e, 0x7d10, 0xd5c4, 0x0040, 0x1e01, 0x7322,
+	0x7426, 0xa084, 0x01e0, 0x007c, 0x7848, 0xa065, 0x0040, 0x1e0c,
+	0x2c04, 0x784a, 0x2063, 0x0000, 0x007c, 0x0f7e, 0x2079, 0x4f00,
+	0x7848, 0x2062, 0x2c00, 0xa005, 0x00c0, 0x1e18, 0x1078, 0x29b2,
+	0x784a, 0x0f7f, 0x007c, 0x2011, 0x9900, 0x7a4a, 0x7bc4, 0x8319,
+	0x0040, 0x1e28, 0xa280, 0x0032, 0x2012, 0x2010, 0x0078, 0x1e1f,
+	0x2013, 0x0000, 0x007c, 0x017e, 0x027e, 0xd7fc, 0x00c0, 0x1e34,
+	0x2011, 0x54c0, 0x0078, 0x1e36, 0x2011, 0x74c0, 0xa784, 0x0f00,
+	0x800b, 0xa784, 0x001f, 0x0040, 0x1e41, 0x8003, 0x8003, 0x8003,
+	0x8003, 0xa105, 0xa268, 0x027f, 0x017f, 0x007c, 0x1078, 0x1e2b,
+	0x2900, 0x682a, 0x2a00, 0x682e, 0x6808, 0xa084, 0xf9ef, 0xa80d,
+	0x690a, 0x0e7e, 0xd7fc, 0x00c0, 0x1e5b, 0x2009, 0x4f53, 0x2071,
+	0x4f40, 0x0078, 0x1e5f, 0x2009, 0x4f93, 0x2071, 0x4f80, 0x210c,
+	0x6804, 0xa005, 0x0040, 0x1e6f, 0xa116, 0x00c0, 0x1e6f, 0x2060,
+	0x6000, 0x6806, 0x017e, 0x200b, 0x0000, 0x0078, 0x1e72, 0x2009,
+	0x0000, 0x017e, 0x6804, 0xa065, 0x0040, 0x1e87, 0x6000, 0x6806,
+	0x1078, 0x1ea2, 0x1078, 0x2064, 0x6810, 0x7908, 0x8109, 0x790a,
+	0x8001, 0x6812, 0x00c0, 0x1e72, 0x7910, 0xc1a5, 0x7912, 0x017f,
+	0x6902, 0x6906, 0x2d00, 0x2060, 0x1078, 0x2b13, 0x0e7f, 0x007c,
+	0xa065, 0x0040, 0x1ea1, 0x2008, 0x609c, 0xa005, 0x0040, 0x1e9e,
+	0x2062, 0x609f, 0x0000, 0xa065, 0x0078, 0x1e94, 0x7848, 0x794a,
+	0x2062, 0x007c, 0x6007, 0x0103, 0x608f, 0x0000, 0x20a9, 0x001c,
+	0xac80, 0x0005, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x6828, 0x601a,
+	0x682c, 0x6022, 0x007c, 0x0e7e, 0xd7fc, 0x00c0, 0x1ebd, 0x2071,
+	0x4f40, 0x2031, 0x4fc0, 0x0078, 0x1ec1, 0x2071, 0x4f80, 0x2031,
+	0x51c0, 0x7050, 0xa08c, 0x0200, 0x00c0, 0x1ecb, 0xa608, 0x2d0a,
+	0x8000, 0x7052, 0xa006, 0x0e7f, 0x007c, 0x0f7e, 0xd7fc, 0x00c0,
+	0x1ed5, 0x2079, 0x4f40, 0x0078, 0x1ed7, 0x2079, 0x4f80, 0x1078,
+	0x1e2b, 0x2091, 0x8000, 0x6804, 0x780a, 0xa065, 0x0040, 0x1f2b,
+	0x0078, 0x1ee9, 0x2c00, 0x780a, 0x2060, 0x6000, 0xa065, 0x0040,
+	0x1f2b, 0x6010, 0xa306, 0x00c0, 0x1ee2, 0x600c, 0xa206, 0x00c0,
+	0x1ee2, 0x2c28, 0x784c, 0xac06, 0x00c0, 0x1ef8, 0x0078, 0x1f28,
+	0x6804, 0xac06, 0x00c0, 0x1f06, 0x6000, 0x2060, 0x6806, 0xa005,
+	0x00c0, 0x1f06, 0x6803, 0x0000, 0x0078, 0x1f10, 0x6400, 0x7808,
+	0x2060, 0x6402, 0xa486, 0x0000, 0x00c0, 0x1f10, 0x2c00, 0x6802,
+	0x2560, 0x0f7f, 0x1078, 0x1ea2, 0x0f7e, 0x601b, 0x0005, 0x6023,
+	0x0020, 0x0f7f, 0x1078, 0x2064, 0x0f7e, 0x7908, 0x8109, 0x790a,
+	0x6810, 0x8001, 0x6812, 0x00c0, 0x1f28, 0x7810, 0xc0a5, 0x7812,
+	0x2001, 0xffff, 0xa005, 0x0f7f, 0x007c, 0x077e, 0x2700, 0x2039,
+	0x0000, 0xd0fc, 0x0040, 0x1f35, 0xc7fd, 0x2041, 0x0021, 0x2049,
+	0x0004, 0x2051, 0x0008, 0x2091, 0x8000, 0x1078, 0x1e46, 0x8738,
+	0xa784, 0x001f, 0x00c0, 0x1f3d, 0xa7bc, 0xff00, 0x873f, 0x8738,
+	0x873f, 0xa784, 0x0f00, 0x00c0, 0x1f3d, 0x2091, 0x8001, 0x077f,
+	0x007c, 0x786c, 0x2009, 0x9774, 0x210c, 0xa10d, 0x0040, 0x1f5b,
+	0xa065, 0x0078, 0x23dc, 0x2061, 0x0000, 0x6018, 0xd084, 0x00c0,
+	0x1f7b, 0x7810, 0xd08c, 0x0040, 0x1f6c, 0xc08c, 0x7812, 0xc7fc,
+	0x2069, 0x4f40, 0x0078, 0x1f71, 0xc08d, 0x7812, 0x2069, 0x4f80,
+	0xc7fd, 0x2091, 0x8000, 0x681c, 0x681f, 0x0000, 0x2091, 0x8001,
+	0xa005, 0x00c0, 0x1f7c, 0x007c, 0xa08c, 0xfff0, 0x0040, 0x1f82,
+	0x1078, 0x29b2, 0x0079, 0x1f84, 0x1f94, 0x1f97, 0x1f9d, 0x1fa1,
+	0x1f95, 0x1fa5, 0x1f95, 0x1f95, 0x1f95, 0x1fab, 0x1fdc, 0x1fe0,
+	0x1fe6, 0x1ffb, 0x1f95, 0x1f95, 0x007c, 0x1078, 0x29b2, 0x1078,
+	0x1f2d, 0x2001, 0x8001, 0x0078, 0x2007, 0x2001, 0x8003, 0x0078,
+	0x2007, 0x2001, 0x8004, 0x0078, 0x2007, 0x1078, 0x1f2d, 0x2001,
+	0x8006, 0x0078, 0x2007, 0x2091, 0x8000, 0x077e, 0xd7fc, 0x00c0,
+	0x1fb7, 0x2069, 0x4f40, 0x2039, 0x0009, 0x0078, 0x1fbb, 0x2069,
+	0x4f80, 0x2039, 0x0009, 0x6800, 0xa086, 0x0000, 0x0040, 0x1fc5,
+	0x007f, 0x6f1e, 0x2091, 0x8001, 0x007c, 0x6874, 0x077f, 0xa0bc,
+	0xff00, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0010, 0x1078,
+	0x1e46, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1fcf, 0x2091, 0x8001,
+	0x2001, 0x800a, 0x0078, 0x2007, 0x2001, 0x800c, 0x0078, 0x2007,
+	0x1078, 0x1f2d, 0x2001, 0x800d, 0x0078, 0x2007, 0x7814, 0xd0e4,
+	0x00c0, 0x1ff9, 0xd0ec, 0x0040, 0x1ff3, 0xd7fc, 0x0040, 0x1ff3,
+	0x78e4, 0x0078, 0x1ff4, 0x78e0, 0x70c6, 0x2001, 0x800e, 0x0078,
+	0x2007, 0x0078, 0x1f95, 0xd7fc, 0x0040, 0x2001, 0x78ec, 0x0078,
+	0x2002, 0x78e8, 0x70c6, 0x2001, 0x800f, 0x0078, 0x2007, 0x70c2,
+	0xd7fc, 0x00c0, 0x200f, 0x70db, 0x0000, 0x0078, 0x2011, 0x70db,
+	0x0001, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x4080, 0x007c,
+	0xac80, 0x0001, 0x81ff, 0x0040, 0x2043, 0x2099, 0x0030, 0x20a0,
+	0x700c, 0xa084, 0x03ff, 0x0040, 0x2025, 0x7018, 0x007e, 0x701c,
+	0x007e, 0x7020, 0x007e, 0x7024, 0x007e, 0x7112, 0x81ac, 0x721a,
+	0x731e, 0x7422, 0x7526, 0x7003, 0x0001, 0x7007, 0x0001, 0x7008,
+	0x800b, 0x00c8, 0x2037, 0x7007, 0x0002, 0xa08c, 0x01e0, 0x00c0,
+	0x2043, 0x53a5, 0xa006, 0x7003, 0x0000, 0x7007, 0x0004, 0x007f,
+	0x7026, 0x007f, 0x7022, 0x007f, 0x701e, 0x007f, 0x701a, 0x007c,
+	0x2011, 0x0020, 0x2009, 0x0010, 0x6b0a, 0x6c0e, 0x6803, 0xfd00,
+	0x6807, 0x0018, 0x6a1a, 0x2d00, 0xa0e8, 0x0008, 0xa290, 0x0004,
+	0x8109, 0x00c0, 0x2054, 0x007c, 0x6004, 0x6086, 0x2c08, 0x2063,
+	0x0000, 0x7868, 0xa005, 0x796a, 0x0040, 0x2071, 0x2c02, 0x0078,
+	0x2072, 0x796e, 0x007c, 0x0c7e, 0x2061, 0x4f00, 0x6887, 0x0103,
+	0x2d08, 0x206b, 0x0000, 0x6068, 0xa005, 0x616a, 0x0040, 0x2083,
+	0x2d02, 0x0078, 0x2084, 0x616e, 0x0c7f, 0x007c, 0x2091, 0x8000,
+	0x2c04, 0x786e, 0xa005, 0x00c0, 0x208e, 0x786a, 0x2091, 0x8001,
+	0x609c, 0xa005, 0x0040, 0x20a7, 0x0c7e, 0x2060, 0x2008, 0x609c,
+	0xa005, 0x0040, 0x20a3, 0x2062, 0x609f, 0x0000, 0xa065, 0x609c,
+	0xa005, 0x00c0, 0x209b, 0x7848, 0x794a, 0x2062, 0x0c7f, 0x7848,
+	0x2062, 0x609f, 0x0000, 0xac85, 0x0000, 0x00c0, 0x20b1, 0x1078,
+	0x29b2, 0x784a, 0x007c, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086,
+	0x818e, 0x00c8, 0x20bc, 0xa200, 0x00f0, 0x20b7, 0x8086, 0x818e,
+	0x007c, 0x157e, 0x20a9, 0x0010, 0xa005, 0x0040, 0x20e2, 0xa11a,
+	0x00c8, 0x20e2, 0x8213, 0x818d, 0x0048, 0x20d5, 0xa11a, 0x00c8,
+	0x20d6, 0x00f0, 0x20ca, 0x0078, 0x20da, 0xa11a, 0x2308, 0x8210,
+	0x00f0, 0x20ca, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f,
+	0x157f, 0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078, 0x20de,
+	0x7d74, 0x70d0, 0xa506, 0x0040, 0x21ce, 0x7810, 0x2050, 0x7800,
+	0xd08c, 0x0040, 0x210a, 0xdaec, 0x0040, 0x210a, 0x0e7e, 0x2091,
+	0x8000, 0x2071, 0x0020, 0x7004, 0xa005, 0x00c0, 0x2107, 0x7008,
+	0x0e7f, 0xa086, 0x0008, 0x0040, 0x210a, 0x0078, 0x21ce, 0x0e7f,
+	0x0078, 0x21ce, 0x1078, 0x1e04, 0x0040, 0x21ce, 0xa046, 0x7970,
+	0x2500, 0x8000, 0xa112, 0x2009, 0x0040, 0x00c8, 0x2119, 0x0078,
+	0x2120, 0x72d0, 0xa206, 0x0040, 0x2120, 0x8840, 0x2009, 0x0080,
+	0x0c7e, 0x7112, 0x7007, 0x0001, 0x2099, 0x0030, 0x20a9, 0x0020,
+	0xac80, 0x0001, 0x20a0, 0x2061, 0x0000, 0x88ff, 0x0040, 0x2132,
+	0x1078, 0x1e04, 0x7008, 0xd0fc, 0x0040, 0x2132, 0x7007, 0x0002,
+	0x2091, 0x8001, 0xa08c, 0x01e0, 0x00c0, 0x2169, 0x53a5, 0x8cff,
+	0x00c0, 0x2147, 0x88ff, 0x0040, 0x21b8, 0x0078, 0x2151, 0x2c00,
+	0x788e, 0x20a9, 0x0020, 0xac80, 0x0001, 0x20a0, 0x53a5, 0x0078,
+	0x21b8, 0xa046, 0x7218, 0x731c, 0xdac4, 0x0040, 0x2159, 0x7420,
+	0x7524, 0xa292, 0x0040, 0xa39b, 0x0000, 0xa4a3, 0x0000, 0xa5ab,
+	0x0000, 0x721a, 0x731e, 0xdac4, 0x0040, 0x2169, 0x7422, 0x7526,
+	0xa006, 0x7007, 0x0004, 0x0040, 0x21b8, 0x8cff, 0x0040, 0x2172,
+	0x1078, 0x1e0d, 0x0c7f, 0x1078, 0x1e0d, 0xa046, 0x7888, 0x8000,
+	0x788a, 0xa086, 0x0002, 0x0040, 0x2198, 0x7a7c, 0x7b78, 0xdac4,
+	0x0040, 0x2184, 0x7c84, 0x7d80, 0x7974, 0x8107, 0x8004, 0x8004,
+	0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x721a,
+	0x731e, 0xdac4, 0x0040, 0x21ce, 0x7422, 0x7526, 0x0078, 0x21ce,
+	0x6014, 0xd0fc, 0x00c0, 0x21a0, 0x2069, 0x4f40, 0x0078, 0x21a2,
+	0x2069, 0x4f80, 0x2091, 0x8000, 0x681f, 0x0002, 0x88ff, 0x0040,
+	0x21ae, 0xa046, 0x788c, 0x2060, 0x0078, 0x2198, 0x788b, 0x0000,
+	0x78ac, 0xa085, 0x0003, 0x78ae, 0x2091, 0x8001, 0x0078, 0x21ce,
+	0x0c7f, 0x788b, 0x0000, 0x1078, 0x238d, 0x6004, 0xa084, 0x000f,
+	0x1078, 0x21cf, 0x88ff, 0x0040, 0x21cc, 0x788c, 0x2060, 0x6004,
+	0xa084, 0x000f, 0x1078, 0x21cf, 0x0078, 0x20e8, 0x007c, 0x0079,
+	0x21d1, 0x21e1, 0x21ff, 0x221d, 0x21e1, 0x222e, 0x21f2, 0x21e1,
+	0x21e1, 0x21e1, 0x21fd, 0x221b, 0x21e1, 0x21e1, 0x21e1, 0x21e1,
+	0x21e1, 0x2039, 0x0400, 0x78bc, 0xa705, 0x78be, 0x6008, 0xa705,
+	0x600a, 0x1078, 0x2271, 0x609c, 0x78ba, 0x609f, 0x0000, 0x1078,
+	0x2377, 0x007c, 0x78bc, 0xd0c4, 0x0040, 0x21f8, 0x0078, 0x21e1,
+	0x601c, 0xc0bd, 0x601e, 0x0078, 0x2205, 0x1078, 0x23bf, 0x78bc,
+	0xd0c4, 0x0040, 0x2205, 0x0078, 0x21e1, 0x78bf, 0x0000, 0x6004,
+	0x8007, 0xa084, 0x00ff, 0x78b2, 0x8001, 0x0040, 0x2218, 0x1078,
+	0x2271, 0x0040, 0x2218, 0x78bc, 0xc0c5, 0x78be, 0x0078, 0x221a,
+	0x0078, 0x2290, 0x007c, 0x1078, 0x23bb, 0x78bc, 0xa08c, 0x0e00,
+	0x00c0, 0x2225, 0xd0c4, 0x00c0, 0x2227, 0x0078, 0x21e1, 0x1078,
+	0x2271, 0x00c0, 0x222d, 0x0078, 0x2290, 0x007c, 0x78bc, 0xd0c4,
+	0x0040, 0x2234, 0x0078, 0x21e1, 0x78bf, 0x0000, 0x6714, 0x2011,
+	0x0001, 0x22a8, 0x6018, 0xa084, 0x00ff, 0xa005, 0x0040, 0x2254,
+	0xa7bc, 0xff00, 0x20a9, 0x0020, 0xa08e, 0x0001, 0x0040, 0x2254,
+	0xa7bc, 0x8000, 0x2011, 0x0002, 0x20a9, 0x0100, 0xa08e, 0x0002,
+	0x0040, 0x2254, 0x0078, 0x226e, 0x1078, 0x1e2b, 0x2d00, 0x2091,
+	0x8000, 0x682b, 0x0000, 0x682f, 0x0000, 0x6808, 0xa084, 0xffde,
+	0x680a, 0xade8, 0x0010, 0x2091, 0x8001, 0x00f0, 0x2257, 0x8211,
+	0x0040, 0x226e, 0x20a9, 0x0100, 0x0078, 0x2257, 0x1078, 0x1e0d,
+	0x007c, 0x609f, 0x0000, 0x78b4, 0xa06d, 0x2c00, 0x78b6, 0x00c0,
+	0x227c, 0x78ba, 0x0078, 0x2284, 0x689e, 0x2d00, 0x6002, 0x78b8,
+	0xad06, 0x00c0, 0x2284, 0x6002, 0x78b0, 0x8001, 0x78b2, 0x00c0,
+	0x228f, 0x78bc, 0xc0c4, 0x78be, 0x78b8, 0x2060, 0xa006, 0x007c,
+	0x0e7e, 0xa02e, 0x2530, 0x7dba, 0x7db6, 0x65ae, 0x65b2, 0x601c,
+	0x60a2, 0x2048, 0xa984, 0xe1ff, 0x601e, 0xa984, 0x0060, 0x0040,
+	0x22a3, 0x1078, 0x46b6, 0x6596, 0x65a6, 0x669a, 0x66aa, 0x6714,
+	0x2071, 0x4f80, 0xd7fc, 0x00c0, 0x22af, 0x2071, 0x4f40, 0xa784,
+	0x0f00, 0x800b, 0xa784, 0x001f, 0x0040, 0x22ba, 0x8003, 0x8003,
+	0x8003, 0x8003, 0xa105, 0x71c4, 0xa168, 0x2700, 0x8007, 0xa084,
+	0x000f, 0x8003, 0x8003, 0x8003, 0x71c8, 0xa100, 0x60c2, 0x2091,
+	0x8000, 0x7814, 0xd0c4, 0x0040, 0x22df, 0xd0ec, 0x0040, 0x22db,
+	0xd7fc, 0x00c0, 0x22d8, 0xd0f4, 0x00c0, 0x22e6, 0x0078, 0x22df,
+	0xd0fc, 0x00c0, 0x22e6, 0x7810, 0xd0f4, 0x00c0, 0x22e6, 0x6e08,
+	0xd684, 0x0040, 0x2310, 0xd9fc, 0x00c0, 0x2310, 0x2091, 0x8001,
+	0x1078, 0x1ea2, 0x2091, 0x8000, 0x1078, 0x2064, 0x2091, 0x8001,
+	0x7814, 0xd0e4, 0x00c0, 0x2375, 0x7814, 0xd0c4, 0x0040, 0x2375,
+	0xd0ec, 0x0040, 0x2308, 0xd7fc, 0x00c0, 0x2303, 0xd0f4, 0x00c0,
+	0x230c, 0x0078, 0x2375, 0xd0fc, 0x00c0, 0x230c, 0x0078, 0x2375,
+	0x7810, 0xd0f4, 0x0040, 0x2375, 0x601b, 0x0021, 0x0078, 0x2375,
+	0x6024, 0xa096, 0x0001, 0x00c0, 0x2317, 0x8000, 0x6026, 0x6a10,
+	0x6814, 0xa202, 0x0048, 0x232a, 0x0040, 0x232a, 0x2091, 0x8001,
+	0x2039, 0x0200, 0x609c, 0x78ba, 0x609f, 0x0000, 0x1078, 0x2377,
+	0x0078, 0x2375, 0x2c08, 0xd9fc, 0x0040, 0x2352, 0x6800, 0xa065,
+	0x0040, 0x2352, 0x6a04, 0x7000, 0xa084, 0x0002, 0x0040, 0x2348,
+	0x704c, 0xa206, 0x00c0, 0x2348, 0x6b04, 0x2160, 0x2304, 0x6002,
+	0xa005, 0x00c0, 0x2344, 0x6902, 0x2260, 0x6102, 0x0078, 0x235e,
+	0x2d00, 0x2060, 0x1078, 0x2b13, 0x6e08, 0x2160, 0x6202, 0x6906,
+	0x0078, 0x235e, 0x6800, 0x6902, 0xa065, 0x0040, 0x235a, 0x6102,
+	0x0078, 0x235b, 0x6906, 0x2160, 0x6003, 0x0000, 0x2160, 0xd9fc,
+	0x0040, 0x2365, 0xa6b4, 0xfffc, 0x6e0a, 0x6810, 0x7d08, 0x8528,
+	0x7d0a, 0x8000, 0x6812, 0x2091, 0x8001, 0xd6b4, 0x0040, 0x2375,
+	0xa6b6, 0x0040, 0x6e0a, 0x1078, 0x1eb3, 0x0e7f, 0x007c, 0x6008,
+	0xa705, 0x600a, 0x2091, 0x8000, 0x1078, 0x2064, 0x2091, 0x8001,
+	0x78b8, 0xa065, 0x0040, 0x238a, 0x609c, 0x78ba, 0x609f, 0x0000,
+	0x0078, 0x2377, 0x78b6, 0x78ba, 0x007c, 0x7970, 0x7874, 0x2818,
+	0xd384, 0x0040, 0x2397, 0x8000, 0xa112, 0x0048, 0x239c, 0x8000,
+	0xa112, 0x00c8, 0x23ac, 0xc384, 0x7a7c, 0x721a, 0x7a78, 0x721e,
+	0xdac4, 0x0040, 0x23a7, 0x7a84, 0x7222, 0x7a80, 0x7226, 0xa006,
+	0xd384, 0x0040, 0x23ac, 0x8000, 0x7876, 0x70d2, 0x781c, 0xa005,
+	0x0040, 0x23ba, 0x8001, 0x781e, 0x00c0, 0x23ba, 0x0068, 0x23ba,
+	0x2091, 0x4080, 0x007c, 0x2039, 0x23d3, 0x0078, 0x23c1, 0x2039,
+	0x23d9, 0x2704, 0xa005, 0x0040, 0x23d2, 0xac00, 0x2068, 0x6908,
+	0x6810, 0x6912, 0x680a, 0x690c, 0x6814, 0x6916, 0x680e, 0x8738,
+	0x0078, 0x23c1, 0x007c, 0x0003, 0x0009, 0x000f, 0x0015, 0x001b,
+	0x0000, 0x0015, 0x001b, 0x0000, 0x2041, 0x0000, 0x780c, 0x0079,
+	0x23e1, 0x25b3, 0x2586, 0x23e5, 0x245e, 0x2039, 0x9774, 0x2734,
+	0x7d10, 0x0078, 0x2405, 0x6084, 0xa086, 0x0103, 0x00c0, 0x2447,
+	0x6114, 0x6018, 0xa105, 0x0040, 0x23fa, 0x86ff, 0x00c0, 0x2416,
+	0x0078, 0x2447, 0x8603, 0xa080, 0x9755, 0x620c, 0x2202, 0x8000,
+	0x6210, 0x2202, 0x1078, 0x2086, 0x8630, 0xa68e, 0x000f, 0x0040,
+	0x24d2, 0x786c, 0xa065, 0x00c0, 0x23eb, 0x7808, 0xa602, 0x00c8,
+	0x2416, 0xd5ac, 0x00c0, 0x2416, 0x263a, 0x007c, 0xa682, 0x0003,
+	0x00c8, 0x24d2, 0x2091, 0x8000, 0x2069, 0x0000, 0x6818, 0xd084,
+	0x00c0, 0x2442, 0x2011, 0x9755, 0x2204, 0x70c6, 0x8210, 0x2204,
+	0x70ca, 0xd684, 0x00c0, 0x2432, 0x8210, 0x2204, 0x70da, 0x8210,
+	0x2204, 0x70de, 0xa685, 0x8020, 0x70c2, 0x681b, 0x0001, 0x2091,
+	0x4080, 0x7810, 0xa084, 0xffcf, 0x7812, 0x2091, 0x8001, 0x203b,
+	0x0000, 0x007c, 0x7810, 0xc0ad, 0x7812, 0x0078, 0x24d2, 0x263a,
+	0x1078, 0x25bd, 0x00c0, 0x25e0, 0x786c, 0xa065, 0x00c0, 0x23eb,
+	0x2091, 0x8000, 0x7810, 0xa084, 0xffcf, 0x86ff, 0x0040, 0x2459,
+	0xc0ad, 0x7812, 0x2091, 0x8001, 0x0078, 0x25e0, 0x2039, 0x9774,
+	0x2734, 0x7d10, 0x0078, 0x247a, 0x6084, 0xa086, 0x0103, 0x00c0,
+	0x24bb, 0x6114, 0x6018, 0xa105, 0x0040, 0x2473, 0x86ff, 0x00c0,
+	0x248b, 0x0078, 0x24bb, 0xa680, 0x9755, 0x620c, 0x2202, 0x1078,
+	0x2086, 0x8630, 0xa68e, 0x001e, 0x0040, 0x24d2, 0x786c, 0xa065,
+	0x00c0, 0x2464, 0x7808, 0xa602, 0x00c8, 0x248b, 0xd5ac, 0x00c0,
+	0x248b, 0x263a, 0x007c, 0xa682, 0x0006, 0x00c8, 0x24d2, 0x2091,
+	0x8000, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0, 0x24b6, 0x2011,
+	0x9755, 0x2009, 0x974e, 0x26a8, 0x211c, 0x2204, 0x201a, 0x8108,
+	0x8210, 0x00f0, 0x249c, 0xa685, 0x8030, 0x70c2, 0x681b, 0x0001,
 	0x2091, 0x4080, 0x7810, 0xa084, 0xffcf, 0x7812, 0x2091, 0x8001,
-	0x203b, 0x0000, 0x007c, 0x7810, 0xc0ad, 0x7812, 0x0078, 0x248b,
-	0x263a, 0x1078, 0x2576, 0x00c0, 0x2599, 0x786c, 0xa065, 0x00c0,
-	0x23a4, 0x2091, 0x8000, 0x7810, 0xa084, 0xffcf, 0x86ff, 0x0040,
-	0x2412, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0078, 0x2599, 0x2039,
-	0x9674, 0x2734, 0x7d10, 0x0078, 0x2433, 0x6084, 0xa086, 0x0103,
-	0x00c0, 0x2474, 0x6114, 0x6018, 0xa105, 0x0040, 0x242c, 0x86ff,
-	0x00c0, 0x2444, 0x0078, 0x2474, 0xa680, 0x9655, 0x620c, 0x2202,
-	0x1078, 0x203f, 0x8630, 0xa68e, 0x001e, 0x0040, 0x248b, 0x786c,
-	0xa065, 0x00c0, 0x241d, 0x7808, 0xa602, 0x00c8, 0x2444, 0xd5ac,
-	0x00c0, 0x2444, 0x263a, 0x007c, 0xa682, 0x0006, 0x00c8, 0x248b,
-	0x2091, 0x8000, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0, 0x246f,
-	0x2011, 0x9655, 0x2009, 0x964e, 0x26a8, 0x211c, 0x2204, 0x201a,
-	0x8108, 0x8210, 0x00f0, 0x2455, 0xa685, 0x8030, 0x70c2, 0x681b,
-	0x0001, 0x2091, 0x4080, 0x7810, 0xa084, 0xffcf, 0x7812, 0x2091,
-	0x8001, 0xa006, 0x2009, 0x9675, 0x200a, 0x203a, 0x007c, 0x7810,
-	0xc0ad, 0x7812, 0x0078, 0x248b, 0x263a, 0x1078, 0x2576, 0x00c0,
-	0x2599, 0x786c, 0xa065, 0x00c0, 0x241d, 0x2091, 0x8000, 0x7810,
-	0xa084, 0xffcf, 0x86ff, 0x0040, 0x2486, 0xc0ad, 0x7812, 0x2091,
-	0x8001, 0x0078, 0x2599, 0x2091, 0x8000, 0x7007, 0x0004, 0x7994,
-	0x70d4, 0xa102, 0x0048, 0x249c, 0x0040, 0x24a6, 0x7b90, 0xa302,
-	0x00c0, 0x24a6, 0x0078, 0x249f, 0x8002, 0x00c0, 0x24a6, 0x263a,
-	0x7810, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x007c, 0xa184, 0xff00,
-	0x0040, 0x24b3, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007,
-	0xa100, 0x0078, 0x24b6, 0x8107, 0x8004, 0x8004, 0x7a9c, 0xa210,
-	0x721a, 0x7a98, 0xa006, 0xa211, 0x721e, 0xd4c4, 0x0040, 0x24c6,
-	0x7aa4, 0xa211, 0x7222, 0x7aa0, 0xa211, 0x7226, 0x20a1, 0x0030,
-	0x7003, 0x0000, 0x2009, 0x9654, 0x260a, 0x8109, 0x2198, 0x2104,
-	0xd084, 0x0040, 0x24d4, 0x8633, 0xa6b0, 0x0002, 0x26a8, 0x53a6,
-	0x8603, 0x7012, 0x7007, 0x0001, 0x7990, 0x7894, 0x8000, 0xa10a,
-	0x00c8, 0x24e3, 0xa006, 0x2028, 0x7974, 0xa184, 0xff00, 0x0040,
-	0x24f2, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100,
-	0x0078, 0x24f5, 0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78,
-	0xa006, 0xa211, 0xd4c4, 0x0040, 0x2501, 0x7b84, 0xa319, 0x7c80,
-	0xa421, 0x7008, 0xd0fc, 0x0040, 0x2501, 0xa084, 0x01e0, 0x0040,
-	0x2526, 0x7d10, 0x2031, 0x9654, 0x2634, 0x78a8, 0x8000, 0x78aa,
-	0xd08c, 0x00c0, 0x251b, 0x7007, 0x0006, 0x7004, 0xd094, 0x00c0,
-	0x2515, 0x0078, 0x248d, 0x2069, 0x4e47, 0x206b, 0x0003, 0x78ac,
-	0xa085, 0x0300, 0x78ae, 0xa006, 0x0078, 0x252f, 0x2030, 0x75d6,
-	0x2091, 0x4080, 0x7d96, 0x7d10, 0xa5ac, 0xffcf, 0x7d12, 0x2091,
-	0x8001, 0x78aa, 0x7007, 0x0006, 0x263a, 0x7003, 0x0001, 0x711a,
-	0x721e, 0xd5c4, 0x0040, 0x253e, 0x7322, 0x7426, 0x007c, 0x6084,
-	0xa086, 0x0103, 0x00c0, 0x2562, 0x6114, 0x6018, 0xa105, 0x00c0,
-	0x2562, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0, 0x2562, 0x600c,
-	0x70c6, 0x6010, 0x70ca, 0x70c3, 0x8020, 0x681b, 0x0001, 0x2091,
-	0x4080, 0x1078, 0x203f, 0x0068, 0x2561, 0x786c, 0xa065, 0x00c0,
-	0x253f, 0x007c, 0x1078, 0x2576, 0x00c0, 0x2599, 0x786c, 0xa065,
-	0x00c0, 0x253f, 0x0078, 0x2599, 0x1078, 0x2576, 0x00c0, 0x2599,
-	0x786c, 0xa065, 0x00c0, 0x256c, 0x0078, 0x2599, 0x6084, 0xa086,
-	0x0103, 0x00c0, 0x258a, 0x6018, 0xc0fc, 0x601a, 0xa086, 0x0004,
-	0x00c0, 0x258a, 0x7804, 0xd0a4, 0x0040, 0x258a, 0x1078, 0x203f,
-	0xa006, 0x007c, 0x1078, 0x259f, 0x00c0, 0x2591, 0xa085, 0x0001,
-	0x007c, 0x1078, 0x25ae, 0x00c0, 0x2597, 0x2041, 0x0001, 0x7d10,
-	0x007c, 0x88ff, 0x0040, 0x259e, 0x2091, 0x4080, 0x007c, 0x7b90,
-	0x7994, 0x70d4, 0xa102, 0x00c0, 0x25a8, 0xa385, 0x0000, 0x007c,
-	0x0048, 0x25ac, 0xa302, 0x007c, 0x8002, 0x007c, 0x7810, 0xd0ec,
-	0x0040, 0x25c6, 0x0e7e, 0x2091, 0x8000, 0x2071, 0x0020, 0x7004,
-	0xa005, 0x00c0, 0x25c3, 0x7008, 0x0e7f, 0xa086, 0x0008, 0x0040,
-	0x25c6, 0x0078, 0x2617, 0x0e7f, 0x0078, 0x2617, 0xa184, 0xff00,
-	0x0040, 0x25d3, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007,
-	0xa100, 0x0078, 0x25d6, 0x8107, 0x8004, 0x8004, 0x7a9c, 0x7b98,
-	0x7ca4, 0x7da0, 0xa210, 0xa006, 0xa319, 0xa421, 0xa529, 0x2009,
-	0x0018, 0x6028, 0xa005, 0x0040, 0x25e7, 0x2009, 0x0040, 0x1078,
-	0x1d74, 0x0040, 0x2609, 0x78a8, 0x8000, 0x78aa, 0xd08c, 0x00c0,
-	0x2617, 0x6014, 0xd0fc, 0x00c0, 0x25f9, 0x2069, 0x4e40, 0x0078,
-	0x25fb, 0x2069, 0x4e80, 0x2091, 0x8000, 0x681f, 0x0003, 0x78ab,
-	0x0000, 0x78ac, 0xa085, 0x0300, 0x78ae, 0x2091, 0x8001, 0x0078,
-	0x2617, 0x78ab, 0x0000, 0x1078, 0x203f, 0x7990, 0x7894, 0x8000,
-	0xa10a, 0x00c8, 0x2614, 0xa006, 0x7896, 0x70d6, 0xa006, 0x2071,
-	0x0010, 0x2091, 0x8001, 0x007c, 0xd7fc, 0x00c0, 0x2623, 0x2009,
-	0x4e59, 0x0078, 0x2625, 0x2009, 0x4e99, 0x2091, 0x8000, 0x200a,
-	0x0f7e, 0xd7fc, 0x00c0, 0x263c, 0x2009, 0x4e40, 0x2001, 0x4e04,
-	0x2004, 0xd0ec, 0x0040, 0x2638, 0x2079, 0x0100, 0x0078, 0x2640,
-	0x2079, 0x0200, 0x0078, 0x2640, 0x2009, 0x4e80, 0x2079, 0x0100,
-	0x2104, 0xa086, 0x0000, 0x00c0, 0x2659, 0xd7fc, 0x00c0, 0x264c,
-	0x2009, 0x4e45, 0x0078, 0x264e, 0x2009, 0x4e85, 0x2104, 0xa005,
-	0x00c0, 0x2659, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x2659, 0x781b,
-	0x0045, 0x0f7f, 0x007c, 0x2009, 0x0002, 0x2069, 0x4e00, 0x6810,
-	0xd0ec, 0x00c0, 0x26c8, 0x2071, 0x4e80, 0x2079, 0x0100, 0x2021,
-	0x50bf, 0x784b, 0x000f, 0x2019, 0x4457, 0xd184, 0x0040, 0x267c,
-	0x6810, 0xd0ec, 0x0040, 0x2678, 0x20a1, 0x012b, 0x0078, 0x267e,
-	0x20a1, 0x022b, 0x0078, 0x267e, 0x20a1, 0x012b, 0x2304, 0xa005,
-	0x0040, 0x268b, 0x789a, 0x8318, 0x23ac, 0x8318, 0x2398, 0x53a6,
-	0x3318, 0x0078, 0x267e, 0x789b, 0x0020, 0x20a9, 0x0010, 0x6814,
-	0xd0e4, 0x0040, 0x269b, 0x78af, 0x0000, 0x78af, 0x9020, 0x00f0,
-	0x2693, 0x0078, 0x26a1, 0x78af, 0x0000, 0x78af, 0x8020, 0x00f0,
-	0x269b, 0x7003, 0x0000, 0x017e, 0xd18c, 0x2009, 0x0000, 0x0040,
-	0x26aa, 0xc1bd, 0x1078, 0x289b, 0x017f, 0x7020, 0xa084, 0x000f,
-	0x007e, 0x6814, 0xd0e4, 0x007f, 0x00c0, 0x26ba, 0xa085, 0x6340,
-	0x0078, 0x26bc, 0xa085, 0x62c0, 0x7806, 0x780f, 0x9200, 0x7843,
-	0x00d8, 0x7853, 0x0080, 0x780b, 0x0008, 0x7456, 0x7053, 0x0000,
-	0x8109, 0x0040, 0x26db, 0x2071, 0x4e40, 0x6810, 0xd0ec, 0x0040,
-	0x26d5, 0x2079, 0x0100, 0x0078, 0x26d7, 0x2079, 0x0200, 0x2021,
-	0x4ebf, 0x0078, 0x2669, 0x007c, 0x017e, 0xd1bc, 0x00c0, 0x26f0,
-	0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x26ec,
-	0x2011, 0x0101, 0x0078, 0x26f2, 0x2011, 0x0201, 0x0078, 0x26f2,
-	0x2011, 0x0101, 0xa18c, 0x000f, 0x2204, 0xa084, 0xfff0, 0xa105,
-	0x2012, 0x017f, 0x1078, 0x289b, 0x007c, 0xd3fc, 0x00c0, 0x2710,
-	0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x270c,
-	0x2011, 0x0101, 0x0078, 0x2712, 0x2011, 0x0201, 0x0078, 0x2712,
-	0x2011, 0x0101, 0x20a9, 0x0009, 0x810b, 0x00f0, 0x2714, 0xa18c,
-	0x0e00, 0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012, 0x007c, 0x2019,
-	0x0002, 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x0040, 0x272c, 0x8319,
-	0x2009, 0x0101, 0x0078, 0x272e, 0x2009, 0x0101, 0x20a9, 0x0005,
-	0x8213, 0x00f0, 0x2730, 0xa294, 0x00e0, 0x2104, 0xa084, 0xff1f,
-	0xa205, 0x200a, 0x8319, 0x0040, 0x2741, 0x2009, 0x0201, 0x0078,
-	0x272e, 0x007c, 0xd3fc, 0x00c0, 0x2755, 0x007e, 0x2001, 0x4e04,
-	0x2004, 0xd0ec, 0x007f, 0x0040, 0x2751, 0x2011, 0x0101, 0x0078,
-	0x2757, 0x2011, 0x0201, 0x0078, 0x2757, 0x2011, 0x0101, 0x20a9,
-	0x000c, 0x810b, 0x00f0, 0x2759, 0xa18c, 0xf000, 0x2204, 0xa084,
-	0x0fff, 0xa105, 0x2012, 0x007c, 0xd3fc, 0x00c0, 0x2777, 0x007e,
-	0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x2773, 0x2011,
-	0x0102, 0x0078, 0x2779, 0x2011, 0x0202, 0x0078, 0x2779, 0x2011,
-	0x0102, 0x2204, 0xa084, 0xffcf, 0xa105, 0x2012, 0x007c, 0x0c7e,
-	0xd1bc, 0x00c0, 0x2793, 0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec,
-	0x007f, 0x0040, 0x278f, 0x2061, 0x0100, 0x0078, 0x2795, 0x2061,
-	0x0200, 0x0078, 0x2795, 0x2061, 0x0100, 0xc1bc, 0x8103, 0x8003,
-	0xa080, 0x0020, 0x609a, 0x62ac, 0x63ac, 0x0c7f, 0x007c, 0x0c7e,
-	0xd1bc, 0x00c0, 0x27b3, 0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec,
-	0x007f, 0x0040, 0x27af, 0x2061, 0x0100, 0x0078, 0x27b5, 0x2061,
-	0x0200, 0x0078, 0x27b5, 0x2061, 0x0100, 0xc1bc, 0x8103, 0x8003,
-	0xa080, 0x0022, 0x609a, 0x60a4, 0xa084, 0xffdf, 0x60ae, 0x0c7f,
-	0x007c, 0x0c7e, 0xd1bc, 0x00c0, 0x27d5, 0x007e, 0x2001, 0x4e04,
-	0x2004, 0xd0ec, 0x007f, 0x0040, 0x27d1, 0x2061, 0x0100, 0x0078,
-	0x27d7, 0x2061, 0x0200, 0x0078, 0x27d7, 0x2061, 0x0100, 0xc1bc,
-	0x8103, 0x8003, 0xa080, 0x0022, 0x609a, 0x60a4, 0xa085, 0x0020,
-	0x60ae, 0x0c7f, 0x007c, 0x0c7e, 0xd1bc, 0x00c0, 0x27f7, 0x007e,
-	0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x27f3, 0x2061,
-	0x0100, 0x0078, 0x27f9, 0x2061, 0x0200, 0x0078, 0x27f9, 0x2061,
-	0x0100, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0020, 0x609a, 0x60a4,
-	0xa28c, 0x0020, 0x0040, 0x2807, 0xc2ac, 0xa39d, 0x4000, 0xc3fc,
-	0xd3b4, 0x00c0, 0x280c, 0xc3fd, 0x62ae, 0x2010, 0x60a4, 0x63ae,
-	0x2018, 0x0c7f, 0x007c, 0x2091, 0x8000, 0x0c7e, 0x0e7e, 0x6818,
-	0xa005, 0x0040, 0x2879, 0xd1fc, 0x0040, 0x2822, 0x2061, 0x95d0,
-	0x0078, 0x2824, 0x2061, 0x94c0, 0x1078, 0x2881, 0x0040, 0x285b,
-	0x20a9, 0x0101, 0xd1fc, 0x0040, 0x2831, 0x2061, 0x94d0, 0x0078,
-	0x2833, 0x2061, 0x93c0, 0x0c7e, 0x1078, 0x2881, 0x0040, 0x283e,
-	0x0c7f, 0x8c60, 0x00f0, 0x2833, 0x0078, 0x2879, 0x007f, 0xd1fc,
-	0x0040, 0x2848, 0xa082, 0x94d0, 0x2071, 0x4e80, 0x0078, 0x284c,
-	0xa082, 0x93c0, 0x2071, 0x4e40, 0x707a, 0x7176, 0x2138, 0x2001,
-	0x0004, 0x7066, 0x7083, 0x000f, 0x71d4, 0xc1dc, 0x71d6, 0x1078,
-	0x261c, 0x0078, 0x2875, 0xd1fc, 0x00c0, 0x2862, 0x2071, 0x4e40,
-	0x0078, 0x2864, 0x2071, 0x4e80, 0x6020, 0xc0dd, 0x6022, 0x7176,
-	0x2138, 0x2c00, 0x707e, 0x2001, 0x0006, 0x7066, 0x7083, 0x000f,
-	0x71d4, 0xc1dc, 0x71d6, 0x1078, 0x261c, 0x2001, 0x0000, 0x0078,
-	0x287b, 0x2001, 0x0001, 0x2091, 0x8001, 0xa005, 0x0e7f, 0x0c7f,
-	0x007c, 0x2c04, 0xa005, 0x0040, 0x2898, 0x2060, 0x6010, 0xa306,
-	0x00c0, 0x2895, 0x600c, 0xa206, 0x00c0, 0x2895, 0x6014, 0xa106,
-	0x00c0, 0x2895, 0xa006, 0x0078, 0x289a, 0x6000, 0x0078, 0x2882,
-	0xa085, 0x0001, 0x007c, 0x0f7e, 0x0e7e, 0x017e, 0xd1bc, 0x00c0,
-	0x28b3, 0x2079, 0x4e40, 0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec,
-	0x007f, 0x0040, 0x28af, 0x2071, 0x0100, 0x0078, 0x28b7, 0x2071,
-	0x0200, 0x0078, 0x28b7, 0x2079, 0x4e80, 0x2071, 0x0100, 0x7920,
-	0xa18c, 0x000f, 0x70ec, 0xd0c4, 0x00c0, 0x28c1, 0x017f, 0x0078,
-	0x28dc, 0x810b, 0x810b, 0x810b, 0x810b, 0x007f, 0xd0bc, 0x00c0,
-	0x28d9, 0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f, 0x0040,
-	0x28d5, 0xa18d, 0x0f00, 0x0078, 0x28db, 0xa18d, 0x0f00, 0x0078,
-	0x28db, 0xa18d, 0x0800, 0x2104, 0x0e7f, 0x0f7f, 0x007c, 0x0e7e,
-	0x2001, 0x4e01, 0x2004, 0xd0ac, 0x00c0, 0x295c, 0x68e4, 0xd0ac,
-	0x0040, 0x295c, 0xa084, 0x0006, 0x00c0, 0x295c, 0x6014, 0xd0fc,
-	0x00c0, 0x28f6, 0x2071, 0x52c0, 0x0078, 0x28f8, 0x2071, 0x5340,
-	0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xae70, 0x7004,
-	0xa084, 0x000a, 0x00c0, 0x295c, 0x7108, 0xa194, 0xff00, 0x0040,
-	0x295c, 0xa18c, 0x00ff, 0x2001, 0x000a, 0xa106, 0x0040, 0x292b,
-	0x2001, 0x000c, 0xa106, 0x0040, 0x292f, 0x2001, 0x0012, 0xa106,
-	0x0040, 0x2933, 0x2001, 0x0014, 0xa106, 0x0040, 0x2937, 0x2001,
-	0x0019, 0xa106, 0x0040, 0x293b, 0x2001, 0x0032, 0xa106, 0x0040,
-	0x293f, 0x0078, 0x2943, 0x2009, 0x000c, 0x0078, 0x2945, 0x2009,
-	0x0012, 0x0078, 0x2945, 0x2009, 0x0014, 0x0078, 0x2945, 0x2009,
-	0x0019, 0x0078, 0x2945, 0x2009, 0x0020, 0x0078, 0x2945, 0x2009,
-	0x003f, 0x0078, 0x2945, 0x2011, 0x0000, 0x2100, 0xa205, 0x700a,
-	0x2071, 0x4e00, 0x7004, 0xd0bc, 0x0040, 0x295c, 0x6014, 0xd0fc,
-	0x00c0, 0x2957, 0x70ea, 0x2071, 0x4e40, 0x0078, 0x295a, 0x70ee,
-	0x2071, 0x4e80, 0x701f, 0x000d, 0x0e7f, 0x007c, 0x2001, 0x4e05,
-	0x2004, 0xd0e4, 0x00c0, 0x296a, 0x7804, 0xa084, 0xff1f, 0xa085,
-	0x6340, 0x7806, 0x007c, 0x0068, 0x296b, 0x2091, 0x8000, 0x2071,
-	0x0000, 0x007e, 0x7018, 0xd084, 0x00c0, 0x2972, 0x007f, 0x2071,
-	0x0010, 0x70ca, 0x007f, 0x70c6, 0x70c3, 0x8002, 0x70db, 0x080f,
-	0x70df, 0x0000, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080,
-	0x0078, 0x2988, 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x78a0, 0x708e,
-	0x7592, 0x7496, 0x769a, 0x779e, 0xa594, 0x003f, 0xd4f4, 0x0040,
-	0x299f, 0xa784, 0x007d, 0x00c0, 0x43cd, 0x1078, 0x296b, 0xa49c,
-	0x000f, 0xa382, 0x0004, 0x0050, 0x29aa, 0xa3a6, 0x0007, 0x00c0,
-	0x296b, 0x2418, 0x8507, 0xa084, 0x000f, 0x0079, 0x29af, 0x3028,
-	0x3119, 0x3144, 0x33b6, 0x379f, 0x3819, 0x38ce, 0x395f, 0x3a4d,
-	0x3b3c, 0x29c2, 0x29bf, 0x2df9, 0x2f1c, 0x3770, 0x29bf, 0x1078,
-	0x296b, 0x007c, 0xa006, 0x0078, 0x29cc, 0x7808, 0xc08d, 0x780a,
-	0xa006, 0x7002, 0x704e, 0x7046, 0x70d2, 0x7060, 0xa005, 0x00c0,
-	0x2b32, 0x7064, 0xa084, 0x0007, 0x0079, 0x29d6, 0x29de, 0x2a51,
-	0x2a5a, 0x2a65, 0x2a70, 0x2b18, 0x2a7b, 0x2a51, 0x7830, 0xd0bc,
-	0x00c0, 0x29c1, 0x71d4, 0xd1bc, 0x00c0, 0x29c1, 0xd1b4, 0x00c0,
-	0x2a2e, 0x70a4, 0xa086, 0x0001, 0x0040, 0x29c1, 0x70b4, 0xa06d,
-	0x6800, 0xa065, 0xa055, 0x789b, 0x0010, 0x6b0c, 0x7baa, 0x6808,
-	0xa045, 0x6d10, 0x6804, 0xa06d, 0xa05d, 0xa886, 0x0001, 0x0040,
-	0x2a04, 0x69bc, 0x7daa, 0x79aa, 0x68c0, 0xa04d, 0x6e1c, 0x2001,
-	0x0010, 0x0078, 0x2c8c, 0x7060, 0xa005, 0x00c0, 0x29c1, 0x0c7e,
-	0x0d7e, 0x70b4, 0xa06d, 0x6800, 0xa065, 0xa055, 0x789b, 0x0010,
-	0x6b0c, 0x7baa, 0x6808, 0xa045, 0x6d10, 0x6804, 0xa06d, 0xa05d,
-	0xa886, 0x0001, 0x0040, 0x2a27, 0x69bc, 0x7daa, 0x79aa, 0x68c0,
-	0xa04d, 0x6e1c, 0x2001, 0x0020, 0x0078, 0x2c8c, 0x1078, 0x4360,
-	0x00c0, 0x29c1, 0x781b, 0x005b, 0x70bc, 0xa06d, 0x68b4, 0x785a,
-	0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d,
-	0x780a, 0x68bc, 0x7042, 0xc1b4, 0x71d6, 0x70b8, 0xa065, 0x68c0,
-	0x705a, 0x7003, 0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046,
-	0x007c, 0x1078, 0x4360, 0x00c0, 0x2a59, 0x781b, 0x0047, 0x7003,
-	0x0004, 0x007c, 0x1078, 0x4360, 0x00c0, 0x2a64, 0x2011, 0x000c,
-	0x1078, 0x2a8b, 0x7003, 0x0004, 0x007c, 0x1078, 0x4360, 0x00c0,
-	0x2a6f, 0x2011, 0x0006, 0x1078, 0x2a8b, 0x7003, 0x0004, 0x007c,
-	0x1078, 0x4360, 0x00c0, 0x2a7a, 0x2011, 0x000d, 0x1078, 0x2a8b,
-	0x7003, 0x0004, 0x007c, 0x1078, 0x4360, 0x00c0, 0x2a8a, 0x2011,
-	0x0006, 0x1078, 0x2a8b, 0x707c, 0x707f, 0x0000, 0x2068, 0x704e,
-	0x7003, 0x0001, 0x007c, 0x7174, 0xc1fc, 0x8107, 0x7882, 0x789b,
-	0x0010, 0xa286, 0x000c, 0x00c0, 0x2a9a, 0x7aaa, 0x2001, 0x0001,
-	0x0078, 0x2aaf, 0xa18c, 0x001f, 0xa18d, 0x00c0, 0x79aa, 0xa286,
-	0x000d, 0x0040, 0x2aa8, 0x7aaa, 0x2001, 0x0002, 0x0078, 0x2aaf,
-	0x78ab, 0x0020, 0x7178, 0x79aa, 0x7aaa, 0x2001, 0x0004, 0x789b,
-	0x0060, 0x78aa, 0x785b, 0x0004, 0x781b, 0x0116, 0x1078, 0x4383,
-	0x7083, 0x000f, 0x70d4, 0xd0b4, 0x0040, 0x2acb, 0xc0b4, 0x70d6,
-	0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018,
-	0x8001, 0x601a, 0x0c7f, 0x007c, 0x7014, 0xa005, 0x00c0, 0x2ada,
-	0x70d4, 0xd0b4, 0x0040, 0x2adb, 0x70b8, 0xac06, 0x00c0, 0x2adb,
-	0x1078, 0x2aba, 0x007c, 0x017e, 0x71a4, 0xa186, 0x0001, 0x0040,
-	0x2b0d, 0x0d7e, 0x027e, 0x2100, 0x2011, 0x0001, 0xa212, 0x70b4,
-	0x2068, 0x6800, 0xac06, 0x0040, 0x2af4, 0x8211, 0x0040, 0x2b0b,
-	0x1078, 0x2b0f, 0x0078, 0x2ae9, 0x0c7e, 0x2100, 0x2011, 0x0001,
-	0xa212, 0x70b4, 0x2068, 0x6800, 0x2060, 0x6008, 0xa084, 0xfbef,
-	0x600a, 0x8211, 0x0040, 0x2b08, 0x1078, 0x2b0f, 0x0078, 0x2afb,
-	0x70a7, 0x0001, 0x0c7f, 0x027f, 0x0d7f, 0x017f, 0x007c, 0xade8,
-	0x0005, 0x70ac, 0xad06, 0x00c0, 0x2b17, 0x70a8, 0x2068, 0x007c,
-	0x1078, 0x4360, 0x00c0, 0x29c1, 0x707c, 0x2068, 0x7774, 0x1078,
-	0x41fe, 0x2c50, 0x1078, 0x4442, 0x789b, 0x0010, 0x6814, 0xa084,
-	0x001f, 0xc0bd, 0x78aa, 0x6e1c, 0x2041, 0x0001, 0x2001, 0x0004,
-	0x0078, 0x2c92, 0x1078, 0x4360, 0x00c0, 0x29c1, 0x789b, 0x0010,
-	0x7060, 0x2068, 0x6f14, 0x70d4, 0xd0b4, 0x0040, 0x2b4c, 0xc0b4,
-	0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a,
-	0x6018, 0x8001, 0x601a, 0x0c7f, 0x1078, 0x41fe, 0x2c50, 0x1078,
-	0x4442, 0x6824, 0xa005, 0x0040, 0x2b5d, 0xa082, 0x0006, 0x0048,
-	0x2b5b, 0x0078, 0x2b5d, 0x6827, 0x0005, 0x6814, 0xa084, 0x001f,
-	0xc0bd, 0x78aa, 0x2031, 0x0020, 0x2041, 0x0001, 0x2001, 0x0003,
-	0x0078, 0x2c92, 0xc28d, 0x72d6, 0x72c0, 0xa200, 0xa015, 0x7154,
-	0x8108, 0xa12a, 0x0048, 0x2b75, 0x71c0, 0x2164, 0x6504, 0x85ff,
-	0x00c0, 0x2b8c, 0x7156, 0x8421, 0x00c0, 0x2b70, 0x70d4, 0xd08c,
-	0x0040, 0x2b88, 0x70d0, 0xa005, 0x00c0, 0x2b88, 0x70d3, 0x000a,
-	0x007c, 0x2200, 0x0078, 0x2b7a, 0x70d4, 0xc08c, 0x70d6, 0x70d3,
-	0x0000, 0x6034, 0xa005, 0x00c0, 0x2b89, 0x6708, 0xa784, 0x073f,
-	0x0040, 0x2bbb, 0xd7d4, 0x00c0, 0x2b89, 0xa784, 0x0021, 0x00c0,
-	0x2b89, 0xa784, 0x0002, 0x0040, 0x2bac, 0xa784, 0x0004, 0x0040,
-	0x2b89, 0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0218, 0x00c0, 0x2b89,
-	0xa784, 0x0100, 0x0040, 0x2bbb, 0x6018, 0xa005, 0x00c0, 0x2b89,
-	0xa7bc, 0xfeff, 0x670a, 0x2568, 0x6823, 0x0000, 0x6e1c, 0xa684,
-	0x000e, 0x6318, 0x0040, 0x2bcc, 0x601c, 0xa302, 0x0048, 0x2bcf,
-	0x0040, 0x2bcf, 0x0078, 0x2b89, 0x83ff, 0x00c0, 0x2b89, 0x2d58,
-	0x2c50, 0x7156, 0xd7bc, 0x00c0, 0x2bd8, 0x7028, 0x6022, 0x603a,
-	0xc7bc, 0x670a, 0x68c0, 0xa065, 0xa04d, 0x6100, 0x2a60, 0x2041,
-	0x0001, 0x6b14, 0xa39c, 0x001f, 0xa39d, 0x00c0, 0xd1fc, 0x0040,
-	0x2bec, 0xd684, 0x0040, 0x2bee, 0xa39c, 0xffbf, 0xd6a4, 0x0040,
-	0x2bf3, 0xa39d, 0x0020, 0xa684, 0x000e, 0x00c0, 0x2c3e, 0xc7a5,
-	0x670a, 0x2c00, 0x68c6, 0x77a4, 0xa786, 0x0001, 0x00c0, 0x2c12,
-	0x70d4, 0xd0b4, 0x00c0, 0x2c12, 0x7000, 0xa082, 0x0002, 0x00c8,
-	0x2c12, 0x7830, 0xd0bc, 0x00c0, 0x2c12, 0x789b, 0x0010, 0x7baa,
-	0x0078, 0x2c8a, 0x8739, 0x77a6, 0x2750, 0x77b0, 0xa7b0, 0x0005,
-	0x70ac, 0xa606, 0x00c0, 0x2c1d, 0x76a8, 0x76b2, 0x2c3a, 0x8738,
-	0x2d3a, 0x8738, 0x283a, 0x8738, 0x233a, 0x8738, 0x253a, 0x7830,
-	0xd0bc, 0x0040, 0x2c35, 0x2091, 0x8000, 0x2091, 0x303d, 0x70d4,
-	0xa084, 0x303d, 0x2091, 0x8000, 0x2090, 0xaad5, 0x0000, 0x0040,
-	0x2c3d, 0x8421, 0x2200, 0x00c0, 0x2b6f, 0x007c, 0xd1dc, 0x0040,
-	0x3e00, 0x2029, 0x0020, 0xd69c, 0x00c0, 0x2c4b, 0x8528, 0xd68c,
-	0x00c0, 0x2c4b, 0x8528, 0x8840, 0x6f14, 0x610c, 0x8108, 0xa18c,
-	0x00ff, 0x70cc, 0xa160, 0x2c64, 0x8cff, 0x0040, 0x2c6a, 0x6014,
-	0xa706, 0x00c0, 0x2c53, 0x60b8, 0x8001, 0x60ba, 0x00c0, 0x2c4e,
-	0x2a60, 0x6008, 0xa085, 0x0100, 0x600a, 0x2200, 0x8421, 0x00c0,
-	0x2b6f, 0x007c, 0x2a60, 0x610e, 0x69be, 0x2c00, 0x68c6, 0x8840,
-	0x6008, 0xc0d5, 0x600a, 0x77a4, 0xa786, 0x0001, 0x00c0, 0x2c12,
-	0x70d4, 0xd0b4, 0x00c0, 0x2c12, 0x7000, 0xa082, 0x0002, 0x00c8,
-	0x2c12, 0x7830, 0xd0bc, 0x00c0, 0x2c12, 0x789b, 0x0010, 0x7baa,
-	0x7daa, 0x79aa, 0x2001, 0x0002, 0x007e, 0x6018, 0x8000, 0x601a,
-	0x0078, 0x2c93, 0x007e, 0x2960, 0x6104, 0x2a60, 0xa184, 0x0018,
-	0x0040, 0x2caf, 0xa184, 0x0010, 0x0040, 0x2ca2, 0x1078, 0x4011,
-	0x00c0, 0x2cd4, 0xa184, 0x0008, 0x0040, 0x2caf, 0x69a0, 0xa184,
-	0x0600, 0x00c0, 0x2caf, 0x1078, 0x3ef5, 0x0078, 0x2cd4, 0x69a0,
-	0xa184, 0x1e00, 0x0040, 0x2cdf, 0xa184, 0x0800, 0x0040, 0x2cc8,
-	0x0c7e, 0x2960, 0x6000, 0xa085, 0x2000, 0x6002, 0x6104, 0xa18d,
-	0x0010, 0x6106, 0x0c7f, 0x1078, 0x4011, 0x00c0, 0x2cd4, 0x69a0,
-	0xa184, 0x0200, 0x0040, 0x2cd0, 0x1078, 0x3f54, 0x0078, 0x2cd4,
-	0xa184, 0x0400, 0x00c0, 0x2cab, 0x69a0, 0xa184, 0x1000, 0x0040,
-	0x2cdf, 0x6914, 0xa18c, 0xff00, 0x810f, 0x1078, 0x279f, 0x027f,
-	0xa68c, 0x00e0, 0xa684, 0x0060, 0x0040, 0x2cec, 0xa086, 0x0060,
-	0x00c0, 0x2cec, 0xa18d, 0x4000, 0xa18d, 0x0104, 0x69b6, 0x789b,
-	0x0060, 0x2800, 0x78aa, 0x6818, 0xc0fd, 0x681a, 0xd6bc, 0x0040,
-	0x2d07, 0xc0fc, 0x7087, 0x0000, 0xa08a, 0x000d, 0x0050, 0x2d05,
-	0xa08a, 0x000c, 0x7186, 0x2001, 0x000c, 0x800c, 0x718a, 0x78aa,
-	0x3518, 0x3340, 0x3428, 0x8000, 0x80ac, 0xaf80, 0x002b, 0x20a0,
-	0x789b, 0x0000, 0xad80, 0x000b, 0x2098, 0x53a6, 0x23a8, 0x2898,
-	0x25a0, 0xa286, 0x0020, 0x00c0, 0x2d3f, 0x70d4, 0xc0b5, 0x70d6,
-	0x2c00, 0x70ba, 0x2d00, 0x70be, 0x6814, 0xc0fc, 0x8007, 0x7882,
-	0xa286, 0x0002, 0x0040, 0x2d75, 0x70a4, 0x8000, 0x70a6, 0x74b4,
-	0xa498, 0x0005, 0x70ac, 0xa306, 0x00c0, 0x2d37, 0x73a8, 0x73b6,
-	0xa286, 0x0010, 0x0040, 0x29c1, 0x0d7f, 0x0c7f, 0x007c, 0x7000,
-	0xa005, 0x00c0, 0x2d1d, 0xa286, 0x0002, 0x00c0, 0x2d8f, 0x1078,
-	0x4360, 0x00c0, 0x2d1d, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x2091,
-	0x8000, 0x781b, 0x005b, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de,
-	0x6898, 0x78d2, 0x78da, 0x2091, 0x8001, 0x7808, 0xc08d, 0x780a,
-	0x127e, 0x0d7e, 0x0c7e, 0x70d4, 0xa084, 0x2700, 0x2090, 0x0c7f,
-	0x0d7f, 0x127f, 0x2900, 0x705a, 0x68bc, 0x7042, 0x7003, 0x0002,
-	0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x7830, 0xd0bc, 0x0040,
-	0x2d81, 0x2091, 0x303d, 0x70d4, 0xa084, 0x303d, 0x2091, 0x8000,
-	0x2090, 0x70a4, 0xa005, 0x00c0, 0x2d86, 0x007c, 0x8421, 0x0040,
-	0x2d85, 0x7250, 0x70c0, 0xa200, 0xa015, 0x0078, 0x2b6f, 0xa286,
-	0x0010, 0x00c0, 0x2dc0, 0x1078, 0x4360, 0x00c0, 0x2d1d, 0x6814,
-	0xc0fc, 0x8007, 0x7882, 0x781b, 0x005b, 0x68b4, 0x785a, 0x6894,
+	0xa006, 0x2009, 0x9775, 0x200a, 0x203a, 0x007c, 0x7810, 0xc0ad,
+	0x7812, 0x0078, 0x24d2, 0x263a, 0x1078, 0x25bd, 0x00c0, 0x25e0,
+	0x786c, 0xa065, 0x00c0, 0x2464, 0x2091, 0x8000, 0x7810, 0xa084,
+	0xffcf, 0x86ff, 0x0040, 0x24cd, 0xc0ad, 0x7812, 0x2091, 0x8001,
+	0x0078, 0x25e0, 0x2091, 0x8000, 0x7007, 0x0004, 0x7994, 0x70d4,
+	0xa102, 0x0048, 0x24e3, 0x0040, 0x24ed, 0x7b90, 0xa302, 0x00c0,
+	0x24ed, 0x0078, 0x24e6, 0x8002, 0x00c0, 0x24ed, 0x263a, 0x7810,
+	0xc0ad, 0x7812, 0x2091, 0x8001, 0x007c, 0xa184, 0xff00, 0x0040,
+	0x24fa, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100,
+	0x0078, 0x24fd, 0x8107, 0x8004, 0x8004, 0x7a9c, 0xa210, 0x721a,
+	0x7a98, 0xa006, 0xa211, 0x721e, 0xd4c4, 0x0040, 0x250d, 0x7aa4,
+	0xa211, 0x7222, 0x7aa0, 0xa211, 0x7226, 0x20a1, 0x0030, 0x7003,
+	0x0000, 0x2009, 0x9754, 0x260a, 0x8109, 0x2198, 0x2104, 0xd084,
+	0x0040, 0x251b, 0x8633, 0xa6b0, 0x0002, 0x26a8, 0x53a6, 0x8603,
+	0x7012, 0x7007, 0x0001, 0x7990, 0x7894, 0x8000, 0xa10a, 0x00c8,
+	0x252a, 0xa006, 0x2028, 0x7974, 0xa184, 0xff00, 0x0040, 0x2539,
+	0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0078,
+	0x253c, 0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, 0xa006,
+	0xa211, 0xd4c4, 0x0040, 0x2548, 0x7b84, 0xa319, 0x7c80, 0xa421,
+	0x7008, 0xd0fc, 0x0040, 0x2548, 0xa084, 0x01e0, 0x0040, 0x256d,
+	0x7d10, 0x2031, 0x9754, 0x2634, 0x78a8, 0x8000, 0x78aa, 0xd08c,
+	0x00c0, 0x2562, 0x7007, 0x0006, 0x7004, 0xd094, 0x00c0, 0x255c,
+	0x0078, 0x24d4, 0x2069, 0x4f47, 0x206b, 0x0003, 0x78ac, 0xa085,
+	0x0300, 0x78ae, 0xa006, 0x0078, 0x2576, 0x2030, 0x75d6, 0x2091,
+	0x4080, 0x7d96, 0x7d10, 0xa5ac, 0xffcf, 0x7d12, 0x2091, 0x8001,
+	0x78aa, 0x7007, 0x0006, 0x263a, 0x7003, 0x0001, 0x711a, 0x721e,
+	0xd5c4, 0x0040, 0x2585, 0x7322, 0x7426, 0x007c, 0x6084, 0xa086,
+	0x0103, 0x00c0, 0x25a9, 0x6114, 0x6018, 0xa105, 0x00c0, 0x25a9,
+	0x2069, 0x0000, 0x6818, 0xd084, 0x00c0, 0x25a9, 0x600c, 0x70c6,
+	0x6010, 0x70ca, 0x70c3, 0x8020, 0x681b, 0x0001, 0x2091, 0x4080,
+	0x1078, 0x2086, 0x0068, 0x25a8, 0x786c, 0xa065, 0x00c0, 0x2586,
+	0x007c, 0x1078, 0x25bd, 0x00c0, 0x25e0, 0x786c, 0xa065, 0x00c0,
+	0x2586, 0x0078, 0x25e0, 0x1078, 0x25bd, 0x00c0, 0x25e0, 0x786c,
+	0xa065, 0x00c0, 0x25b3, 0x0078, 0x25e0, 0x6084, 0xa086, 0x0103,
+	0x00c0, 0x25d1, 0x6018, 0xc0fc, 0x601a, 0xa086, 0x0004, 0x00c0,
+	0x25d1, 0x7804, 0xd0a4, 0x0040, 0x25d1, 0x1078, 0x2086, 0xa006,
+	0x007c, 0x1078, 0x25e6, 0x00c0, 0x25d8, 0xa085, 0x0001, 0x007c,
+	0x1078, 0x25f5, 0x00c0, 0x25de, 0x2041, 0x0001, 0x7d10, 0x007c,
+	0x88ff, 0x0040, 0x25e5, 0x2091, 0x4080, 0x007c, 0x7b90, 0x7994,
+	0x70d4, 0xa102, 0x00c0, 0x25ef, 0xa385, 0x0000, 0x007c, 0x0048,
+	0x25f3, 0xa302, 0x007c, 0x8002, 0x007c, 0x7810, 0xd0ec, 0x0040,
+	0x260d, 0x0e7e, 0x2091, 0x8000, 0x2071, 0x0020, 0x7004, 0xa005,
+	0x00c0, 0x260a, 0x7008, 0x0e7f, 0xa086, 0x0008, 0x0040, 0x260d,
+	0x0078, 0x265e, 0x0e7f, 0x0078, 0x265e, 0xa184, 0xff00, 0x0040,
+	0x261a, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100,
+	0x0078, 0x261d, 0x8107, 0x8004, 0x8004, 0x7a9c, 0x7b98, 0x7ca4,
+	0x7da0, 0xa210, 0xa006, 0xa319, 0xa421, 0xa529, 0x2009, 0x0018,
+	0x6028, 0xa005, 0x0040, 0x262e, 0x2009, 0x0040, 0x1078, 0x1dbb,
+	0x0040, 0x2650, 0x78a8, 0x8000, 0x78aa, 0xd08c, 0x00c0, 0x265e,
+	0x6014, 0xd0fc, 0x00c0, 0x2640, 0x2069, 0x4f40, 0x0078, 0x2642,
+	0x2069, 0x4f80, 0x2091, 0x8000, 0x681f, 0x0003, 0x78ab, 0x0000,
+	0x78ac, 0xa085, 0x0300, 0x78ae, 0x2091, 0x8001, 0x0078, 0x265e,
+	0x78ab, 0x0000, 0x1078, 0x2086, 0x7990, 0x7894, 0x8000, 0xa10a,
+	0x00c8, 0x265b, 0xa006, 0x7896, 0x70d6, 0xa006, 0x2071, 0x0010,
+	0x2091, 0x8001, 0x007c, 0xd7fc, 0x00c0, 0x266a, 0x2009, 0x4f59,
+	0x0078, 0x266c, 0x2009, 0x4f99, 0x2091, 0x8000, 0x200a, 0x0f7e,
+	0xd7fc, 0x00c0, 0x2683, 0x2009, 0x4f40, 0x2001, 0x4f04, 0x2004,
+	0xd0ec, 0x0040, 0x267f, 0x2079, 0x0100, 0x0078, 0x2687, 0x2079,
+	0x0200, 0x0078, 0x2687, 0x2009, 0x4f80, 0x2079, 0x0100, 0x2104,
+	0xa086, 0x0000, 0x00c0, 0x26a0, 0xd7fc, 0x00c0, 0x2693, 0x2009,
+	0x4f45, 0x0078, 0x2695, 0x2009, 0x4f85, 0x2104, 0xa005, 0x00c0,
+	0x26a0, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x26a0, 0x781b, 0x0045,
+	0x0f7f, 0x007c, 0x2009, 0x0002, 0x2069, 0x4f00, 0x6810, 0xd0ec,
+	0x00c0, 0x270f, 0x2071, 0x4f80, 0x2079, 0x0100, 0x2021, 0x51bf,
+	0x784b, 0x000f, 0x2019, 0x44a7, 0xd184, 0x0040, 0x26c3, 0x6810,
+	0xd0ec, 0x0040, 0x26bf, 0x20a1, 0x012b, 0x0078, 0x26c5, 0x20a1,
+	0x022b, 0x0078, 0x26c5, 0x20a1, 0x012b, 0x2304, 0xa005, 0x0040,
+	0x26d2, 0x789a, 0x8318, 0x23ac, 0x8318, 0x2398, 0x53a6, 0x3318,
+	0x0078, 0x26c5, 0x789b, 0x0020, 0x20a9, 0x0010, 0x6814, 0xd0e4,
+	0x0040, 0x26e2, 0x78af, 0x0000, 0x78af, 0x9020, 0x00f0, 0x26da,
+	0x0078, 0x26e8, 0x78af, 0x0000, 0x78af, 0x8020, 0x00f0, 0x26e2,
+	0x7003, 0x0000, 0x017e, 0xd18c, 0x2009, 0x0000, 0x0040, 0x26f1,
+	0xc1bd, 0x1078, 0x28e2, 0x017f, 0x7020, 0xa084, 0x000f, 0x007e,
+	0x6814, 0xd0e4, 0x007f, 0x00c0, 0x2701, 0xa085, 0x6340, 0x0078,
+	0x2703, 0xa085, 0x62c0, 0x7806, 0x780f, 0x9200, 0x7843, 0x00d8,
+	0x7853, 0x0080, 0x780b, 0x0008, 0x7456, 0x7053, 0x0000, 0x8109,
+	0x0040, 0x2722, 0x2071, 0x4f40, 0x6810, 0xd0ec, 0x0040, 0x271c,
+	0x2079, 0x0100, 0x0078, 0x271e, 0x2079, 0x0200, 0x2021, 0x4fbf,
+	0x0078, 0x26b0, 0x007c, 0x017e, 0xd1bc, 0x00c0, 0x2737, 0x007e,
+	0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x2733, 0x2011,
+	0x0101, 0x0078, 0x2739, 0x2011, 0x0201, 0x0078, 0x2739, 0x2011,
+	0x0101, 0xa18c, 0x000f, 0x2204, 0xa084, 0xfff0, 0xa105, 0x2012,
+	0x017f, 0x1078, 0x28e2, 0x007c, 0xd3fc, 0x00c0, 0x2757, 0x007e,
+	0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x2753, 0x2011,
+	0x0101, 0x0078, 0x2759, 0x2011, 0x0201, 0x0078, 0x2759, 0x2011,
+	0x0101, 0x20a9, 0x0009, 0x810b, 0x00f0, 0x275b, 0xa18c, 0x0e00,
+	0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012, 0x007c, 0x2019, 0x0002,
+	0x2001, 0x4f04, 0x2004, 0xd0ec, 0x0040, 0x2773, 0x8319, 0x2009,
+	0x0101, 0x0078, 0x2775, 0x2009, 0x0101, 0x20a9, 0x0005, 0x8213,
+	0x00f0, 0x2777, 0xa294, 0x00e0, 0x2104, 0xa084, 0xff1f, 0xa205,
+	0x200a, 0x8319, 0x0040, 0x2788, 0x2009, 0x0201, 0x0078, 0x2775,
+	0x007c, 0xd3fc, 0x00c0, 0x279c, 0x007e, 0x2001, 0x4f04, 0x2004,
+	0xd0ec, 0x007f, 0x0040, 0x2798, 0x2011, 0x0101, 0x0078, 0x279e,
+	0x2011, 0x0201, 0x0078, 0x279e, 0x2011, 0x0101, 0x20a9, 0x000c,
+	0x810b, 0x00f0, 0x27a0, 0xa18c, 0xf000, 0x2204, 0xa084, 0x0fff,
+	0xa105, 0x2012, 0x007c, 0xd3fc, 0x00c0, 0x27be, 0x007e, 0x2001,
+	0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x27ba, 0x2011, 0x0102,
+	0x0078, 0x27c0, 0x2011, 0x0202, 0x0078, 0x27c0, 0x2011, 0x0102,
+	0x2204, 0xa084, 0xffcf, 0xa105, 0x2012, 0x007c, 0x0c7e, 0xd1bc,
+	0x00c0, 0x27da, 0x007e, 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f,
+	0x0040, 0x27d6, 0x2061, 0x0100, 0x0078, 0x27dc, 0x2061, 0x0200,
+	0x0078, 0x27dc, 0x2061, 0x0100, 0xc1bc, 0x8103, 0x8003, 0xa080,
+	0x0020, 0x609a, 0x62ac, 0x63ac, 0x0c7f, 0x007c, 0x0c7e, 0xd1bc,
+	0x00c0, 0x27fa, 0x007e, 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f,
+	0x0040, 0x27f6, 0x2061, 0x0100, 0x0078, 0x27fc, 0x2061, 0x0200,
+	0x0078, 0x27fc, 0x2061, 0x0100, 0xc1bc, 0x8103, 0x8003, 0xa080,
+	0x0022, 0x609a, 0x60a4, 0xa084, 0xffdf, 0x60ae, 0x0c7f, 0x007c,
+	0x0c7e, 0xd1bc, 0x00c0, 0x281c, 0x007e, 0x2001, 0x4f04, 0x2004,
+	0xd0ec, 0x007f, 0x0040, 0x2818, 0x2061, 0x0100, 0x0078, 0x281e,
+	0x2061, 0x0200, 0x0078, 0x281e, 0x2061, 0x0100, 0xc1bc, 0x8103,
+	0x8003, 0xa080, 0x0022, 0x609a, 0x60a4, 0xa085, 0x0020, 0x60ae,
+	0x0c7f, 0x007c, 0x0c7e, 0xd1bc, 0x00c0, 0x283e, 0x007e, 0x2001,
+	0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x283a, 0x2061, 0x0100,
+	0x0078, 0x2840, 0x2061, 0x0200, 0x0078, 0x2840, 0x2061, 0x0100,
+	0xc1bc, 0x8103, 0x8003, 0xa080, 0x0020, 0x609a, 0x60a4, 0xa28c,
+	0x0020, 0x0040, 0x284e, 0xc2ac, 0xa39d, 0x4000, 0xc3fc, 0xd3b4,
+	0x00c0, 0x2853, 0xc3fd, 0x62ae, 0x2010, 0x60a4, 0x63ae, 0x2018,
+	0x0c7f, 0x007c, 0x2091, 0x8000, 0x0c7e, 0x0e7e, 0x6818, 0xa005,
+	0x0040, 0x28c0, 0xd1fc, 0x0040, 0x2869, 0x2061, 0x96d0, 0x0078,
+	0x286b, 0x2061, 0x95c0, 0x1078, 0x28c8, 0x0040, 0x28a2, 0x20a9,
+	0x0101, 0xd1fc, 0x0040, 0x2878, 0x2061, 0x95d0, 0x0078, 0x287a,
+	0x2061, 0x94c0, 0x0c7e, 0x1078, 0x28c8, 0x0040, 0x2885, 0x0c7f,
+	0x8c60, 0x00f0, 0x287a, 0x0078, 0x28c0, 0x007f, 0xd1fc, 0x0040,
+	0x288f, 0xa082, 0x95d0, 0x2071, 0x4f80, 0x0078, 0x2893, 0xa082,
+	0x94c0, 0x2071, 0x4f40, 0x707a, 0x7176, 0x2138, 0x2001, 0x0004,
+	0x7066, 0x7083, 0x000f, 0x71d4, 0xc1dc, 0x71d6, 0x1078, 0x2663,
+	0x0078, 0x28bc, 0xd1fc, 0x00c0, 0x28a9, 0x2071, 0x4f40, 0x0078,
+	0x28ab, 0x2071, 0x4f80, 0x6020, 0xc0dd, 0x6022, 0x7176, 0x2138,
+	0x2c00, 0x707e, 0x2001, 0x0006, 0x7066, 0x7083, 0x000f, 0x71d4,
+	0xc1dc, 0x71d6, 0x1078, 0x2663, 0x2001, 0x0000, 0x0078, 0x28c2,
+	0x2001, 0x0001, 0x2091, 0x8001, 0xa005, 0x0e7f, 0x0c7f, 0x007c,
+	0x2c04, 0xa005, 0x0040, 0x28df, 0x2060, 0x6010, 0xa306, 0x00c0,
+	0x28dc, 0x600c, 0xa206, 0x00c0, 0x28dc, 0x6014, 0xa106, 0x00c0,
+	0x28dc, 0xa006, 0x0078, 0x28e1, 0x6000, 0x0078, 0x28c9, 0xa085,
+	0x0001, 0x007c, 0x0f7e, 0x0e7e, 0x017e, 0xd1bc, 0x00c0, 0x28fa,
+	0x2079, 0x4f40, 0x007e, 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f,
+	0x0040, 0x28f6, 0x2071, 0x0100, 0x0078, 0x28fe, 0x2071, 0x0200,
+	0x0078, 0x28fe, 0x2079, 0x4f80, 0x2071, 0x0100, 0x7920, 0xa18c,
+	0x000f, 0x70ec, 0xd0c4, 0x00c0, 0x2908, 0x017f, 0x0078, 0x2923,
+	0x810b, 0x810b, 0x810b, 0x810b, 0x007f, 0xd0bc, 0x00c0, 0x2920,
+	0x007e, 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x291c,
+	0xa18d, 0x0f00, 0x0078, 0x2922, 0xa18d, 0x0f00, 0x0078, 0x2922,
+	0xa18d, 0x0800, 0x2104, 0x0e7f, 0x0f7f, 0x007c, 0x0e7e, 0x2001,
+	0x4f01, 0x2004, 0xd0ac, 0x00c0, 0x29a3, 0x68e4, 0xd0ac, 0x0040,
+	0x29a3, 0xa084, 0x0006, 0x00c0, 0x29a3, 0x6014, 0xd0fc, 0x00c0,
+	0x293d, 0x2071, 0x53c0, 0x0078, 0x293f, 0x2071, 0x5440, 0x8007,
+	0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xae70, 0x7004, 0xa084,
+	0x000a, 0x00c0, 0x29a3, 0x7108, 0xa194, 0xff00, 0x0040, 0x29a3,
+	0xa18c, 0x00ff, 0x2001, 0x000a, 0xa106, 0x0040, 0x2972, 0x2001,
+	0x000c, 0xa106, 0x0040, 0x2976, 0x2001, 0x0012, 0xa106, 0x0040,
+	0x297a, 0x2001, 0x0014, 0xa106, 0x0040, 0x297e, 0x2001, 0x0019,
+	0xa106, 0x0040, 0x2982, 0x2001, 0x0032, 0xa106, 0x0040, 0x2986,
+	0x0078, 0x298a, 0x2009, 0x000c, 0x0078, 0x298c, 0x2009, 0x0012,
+	0x0078, 0x298c, 0x2009, 0x0014, 0x0078, 0x298c, 0x2009, 0x0019,
+	0x0078, 0x298c, 0x2009, 0x0020, 0x0078, 0x298c, 0x2009, 0x003f,
+	0x0078, 0x298c, 0x2011, 0x0000, 0x2100, 0xa205, 0x700a, 0x2071,
+	0x4f00, 0x7004, 0xd0bc, 0x0040, 0x29a3, 0x6014, 0xd0fc, 0x00c0,
+	0x299e, 0x70ea, 0x2071, 0x4f40, 0x0078, 0x29a1, 0x70ee, 0x2071,
+	0x4f80, 0x701f, 0x000d, 0x0e7f, 0x007c, 0x2001, 0x4f05, 0x2004,
+	0xd0e4, 0x00c0, 0x29b1, 0x7804, 0xa084, 0xff1f, 0xa085, 0x6340,
+	0x7806, 0x007c, 0x0068, 0x29b2, 0x2091, 0x8000, 0x2071, 0x0000,
+	0x007e, 0x7018, 0xd084, 0x00c0, 0x29b9, 0x007f, 0x2071, 0x0010,
+	0x70ca, 0x007f, 0x70c6, 0x70c3, 0x8002, 0x70db, 0x080f, 0x70df,
+	0x000b, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078,
+	0x29cf, 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x78a0, 0x708e, 0x7592,
+	0x7496, 0x769a, 0x779e, 0xa594, 0x003f, 0xd4f4, 0x0040, 0x29e6,
+	0xa784, 0x007d, 0x00c0, 0x441d, 0x1078, 0x29b2, 0xa49c, 0x000f,
+	0xa382, 0x0004, 0x0050, 0x29f1, 0xa3a6, 0x0007, 0x00c0, 0x29b2,
+	0x2418, 0x8507, 0xa084, 0x000f, 0x0079, 0x29f6, 0x3071, 0x3162,
+	0x318d, 0x33ff, 0x37e8, 0x3862, 0x3917, 0x39a8, 0x3a96, 0x3b85,
+	0x2a09, 0x2a06, 0x2e42, 0x2f65, 0x37b9, 0x2a06, 0x1078, 0x29b2,
+	0x007c, 0xa006, 0x0078, 0x2a13, 0x7808, 0xc08d, 0x780a, 0xa006,
+	0x7002, 0x704e, 0x7046, 0x70d2, 0x7060, 0xa005, 0x00c0, 0x2b79,
+	0x7064, 0xa084, 0x0007, 0x0079, 0x2a1d, 0x2a25, 0x2a98, 0x2aa1,
+	0x2aac, 0x2ab7, 0x2b5f, 0x2ac2, 0x2a98, 0x7830, 0xd0bc, 0x00c0,
+	0x2a08, 0x71d4, 0xd1bc, 0x00c0, 0x2a08, 0xd1b4, 0x00c0, 0x2a75,
+	0x70a4, 0xa086, 0x0001, 0x0040, 0x2a08, 0x70b4, 0xa06d, 0x6800,
+	0xa065, 0xa055, 0x789b, 0x0010, 0x6b0c, 0x7baa, 0x6808, 0xa045,
+	0x6d10, 0x6804, 0xa06d, 0xa05d, 0xa886, 0x0001, 0x0040, 0x2a4b,
+	0x69bc, 0x7daa, 0x79aa, 0x68c0, 0xa04d, 0x6e1c, 0x2001, 0x0010,
+	0x0078, 0x2cd3, 0x7060, 0xa005, 0x00c0, 0x2a08, 0x0c7e, 0x0d7e,
+	0x70b4, 0xa06d, 0x6800, 0xa065, 0xa055, 0x789b, 0x0010, 0x6b0c,
+	0x7baa, 0x6808, 0xa045, 0x6d10, 0x6804, 0xa06d, 0xa05d, 0xa886,
+	0x0001, 0x0040, 0x2a6e, 0x69bc, 0x7daa, 0x79aa, 0x68c0, 0xa04d,
+	0x6e1c, 0x2001, 0x0020, 0x0078, 0x2cd3, 0x1078, 0x43b0, 0x00c0,
+	0x2a08, 0x781b, 0x005b, 0x70bc, 0xa06d, 0x68b4, 0x785a, 0x6894,
 	0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d, 0x780a,
-	0x70a4, 0x8000, 0x70a6, 0x74b4, 0xa490, 0x0005, 0x70ac, 0xa206,
-	0x00c0, 0x2db3, 0x72a8, 0x72b6, 0x2900, 0x705a, 0x68bc, 0x7042,
+	0x68bc, 0x7042, 0xc1b4, 0x71d6, 0x70b8, 0xa065, 0x68c0, 0x705a,
 	0x7003, 0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x007c,
-	0x6bb4, 0xa39d, 0x2000, 0x7b5a, 0x6814, 0xc0fc, 0x8007, 0x7882,
-	0x6b94, 0x7bd6, 0x7bde, 0x6e98, 0x7ed2, 0x7eda, 0x781b, 0x005b,
-	0x2900, 0x705a, 0x7202, 0x7808, 0xc08d, 0x780a, 0x2300, 0xa605,
-	0x0040, 0x2deb, 0x70d4, 0xa084, 0x2700, 0xa086, 0x2300, 0x00c0,
-	0x2de5, 0x2009, 0x0000, 0x0078, 0x2de7, 0x2009, 0x0001, 0xa284,
-	0x000f, 0x1079, 0x2def, 0xad80, 0x0009, 0x7046, 0x007c, 0x2df7,
-	0x48bd, 0x48bd, 0x48aa, 0x48bd, 0x2df7, 0x2df7, 0x2df7, 0x1078,
-	0x296b, 0x7808, 0xa084, 0xfffd, 0x780a, 0x1078, 0x295e, 0x0f7e,
-	0x2079, 0x4e00, 0x78ac, 0x0f7f, 0xd084, 0x0040, 0x2e21, 0x7064,
-	0xa086, 0x0001, 0x00c0, 0x2e0f, 0x7066, 0x0078, 0x2ef8, 0x7064,
-	0xa086, 0x0005, 0x00c0, 0x2e1f, 0x707c, 0x2068, 0x681b, 0x0004,
-	0x6817, 0x0000, 0x6820, 0xa084, 0x00ff, 0xc09d, 0x6822, 0x7067,
-	0x0000, 0x70a7, 0x0000, 0x70a8, 0x70b2, 0x70b6, 0x1078, 0x2aba,
-	0x157e, 0x2011, 0x0004, 0x7164, 0xa186, 0x0001, 0x0040, 0x2e41,
-	0xa186, 0x0007, 0x00c0, 0x2e38, 0x701f, 0x0005, 0x0078, 0x2e41,
-	0x701f, 0x0001, 0x7067, 0x0000, 0x70d4, 0xc0dd, 0x70d6, 0x0078,
-	0x2e43, 0x7067, 0x0000, 0x2001, 0x4e0a, 0x2004, 0xa084, 0x00ff,
-	0xa086, 0x0018, 0x0040, 0x2e53, 0x7018, 0x7016, 0xa005, 0x00c0,
-	0x2e53, 0x70a7, 0x0001, 0x067e, 0x1078, 0x4586, 0x20a9, 0x0010,
-	0x2039, 0x0000, 0x1078, 0x40f8, 0xa7b8, 0x0100, 0x00f0, 0x2e5a,
-	0x067f, 0x7000, 0x0079, 0x2e64, 0x2e9e, 0x2e79, 0x2e79, 0x2e6e,
-	0x2e9e, 0x2e9e, 0x2e9e, 0x2e6c, 0x1078, 0x296b, 0x7060, 0xa005,
-	0x0040, 0x2e9e, 0xad06, 0x00c0, 0x2e79, 0x6800, 0x7062, 0x0078,
-	0x2e8b, 0x6820, 0xd084, 0x00c0, 0x2e87, 0x6f14, 0x1078, 0x41fe,
-	0x6008, 0xc0d4, 0x600a, 0x1078, 0x3dd0, 0x0078, 0x2e8b, 0x705c,
-	0x2060, 0x6800, 0x6002, 0xa684, 0x5f00, 0x681e, 0x6818, 0xd0fc,
-	0x0040, 0x2e93, 0x6a1a, 0x6817, 0x0000, 0x682b, 0x0000, 0x6820,
-	0xa084, 0x00ff, 0xc09d, 0x6822, 0x1078, 0x202c, 0xb284, 0x0400,
-	0x0040, 0x2ea6, 0x2021, 0x95d0, 0x0078, 0x2ea8, 0x2021, 0x94c0,
-	0x1078, 0x2efd, 0xb284, 0x0400, 0x0040, 0x2eb2, 0x2021, 0x4e98,
-	0x0078, 0x2eb4, 0x2021, 0x4e58, 0x1078, 0x2efd, 0x20a9, 0x0101,
-	0xb284, 0x0400, 0x0040, 0x2ec0, 0x2021, 0x94d0, 0x0078, 0x2ec2,
-	0x2021, 0x93c0, 0x1078, 0x2efd, 0x8420, 0x00f0, 0x2ec2, 0xb284,
-	0x0300, 0x0040, 0x2ecf, 0x2061, 0x53c0, 0x0078, 0x2ed1, 0x2061,
-	0x73c0, 0x2021, 0x0002, 0x20a9, 0x0100, 0x6110, 0x81ff, 0x0040,
-	0x2eee, 0x6018, 0x017e, 0x007e, 0x2011, 0x4e02, 0x220c, 0xa102,
-	0x2012, 0x007f, 0x017f, 0xa102, 0x0050, 0x2eee, 0x6012, 0x00c0,
-	0x2eee, 0x2011, 0x4e04, 0x2204, 0xc0a5, 0x2012, 0x601b, 0x0000,
-	0xace0, 0x0010, 0x00f0, 0x2ed5, 0x8421, 0x00c0, 0x2ed3, 0x157f,
-	0x7003, 0x0000, 0x704f, 0x0000, 0x007c, 0x047e, 0x2404, 0xa005,
-	0x0040, 0x2f18, 0x2068, 0x6800, 0x007e, 0x6a1a, 0x6817, 0x0000,
+	0x1078, 0x43b0, 0x00c0, 0x2aa0, 0x781b, 0x0047, 0x7003, 0x0004,
+	0x007c, 0x1078, 0x43b0, 0x00c0, 0x2aab, 0x2011, 0x000c, 0x1078,
+	0x2ad2, 0x7003, 0x0004, 0x007c, 0x1078, 0x43b0, 0x00c0, 0x2ab6,
+	0x2011, 0x0006, 0x1078, 0x2ad2, 0x7003, 0x0004, 0x007c, 0x1078,
+	0x43b0, 0x00c0, 0x2ac1, 0x2011, 0x000d, 0x1078, 0x2ad2, 0x7003,
+	0x0004, 0x007c, 0x1078, 0x43b0, 0x00c0, 0x2ad1, 0x2011, 0x0006,
+	0x1078, 0x2ad2, 0x707c, 0x707f, 0x0000, 0x2068, 0x704e, 0x7003,
+	0x0001, 0x007c, 0x7174, 0xc1fc, 0x8107, 0x7882, 0x789b, 0x0010,
+	0xa286, 0x000c, 0x00c0, 0x2ae1, 0x7aaa, 0x2001, 0x0001, 0x0078,
+	0x2af6, 0xa18c, 0x001f, 0xa18d, 0x00c0, 0x79aa, 0xa286, 0x000d,
+	0x0040, 0x2aef, 0x7aaa, 0x2001, 0x0002, 0x0078, 0x2af6, 0x78ab,
+	0x0020, 0x7178, 0x79aa, 0x7aaa, 0x2001, 0x0004, 0x789b, 0x0060,
+	0x78aa, 0x785b, 0x0004, 0x781b, 0x0116, 0x1078, 0x43d3, 0x7083,
+	0x000f, 0x70d4, 0xd0b4, 0x0040, 0x2b12, 0xc0b4, 0x70d6, 0x0c7e,
+	0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001,
+	0x601a, 0x0c7f, 0x007c, 0x7014, 0xa005, 0x00c0, 0x2b21, 0x70d4,
+	0xd0b4, 0x0040, 0x2b22, 0x70b8, 0xac06, 0x00c0, 0x2b22, 0x1078,
+	0x2b01, 0x007c, 0x017e, 0x71a4, 0xa186, 0x0001, 0x0040, 0x2b54,
+	0x0d7e, 0x027e, 0x2100, 0x2011, 0x0001, 0xa212, 0x70b4, 0x2068,
+	0x6800, 0xac06, 0x0040, 0x2b3b, 0x8211, 0x0040, 0x2b52, 0x1078,
+	0x2b56, 0x0078, 0x2b30, 0x0c7e, 0x2100, 0x2011, 0x0001, 0xa212,
+	0x70b4, 0x2068, 0x6800, 0x2060, 0x6008, 0xa084, 0xfbef, 0x600a,
+	0x8211, 0x0040, 0x2b4f, 0x1078, 0x2b56, 0x0078, 0x2b42, 0x70a7,
+	0x0001, 0x0c7f, 0x027f, 0x0d7f, 0x017f, 0x007c, 0xade8, 0x0005,
+	0x70ac, 0xad06, 0x00c0, 0x2b5e, 0x70a8, 0x2068, 0x007c, 0x1078,
+	0x43b0, 0x00c0, 0x2a08, 0x707c, 0x2068, 0x7774, 0x1078, 0x424e,
+	0x2c50, 0x1078, 0x4492, 0x789b, 0x0010, 0x6814, 0xa084, 0x001f,
+	0xc0bd, 0x78aa, 0x6e1c, 0x2041, 0x0001, 0x2001, 0x0004, 0x0078,
+	0x2cd9, 0x1078, 0x43b0, 0x00c0, 0x2a08, 0x789b, 0x0010, 0x7060,
+	0x2068, 0x6f14, 0x70d4, 0xd0b4, 0x0040, 0x2b93, 0xc0b4, 0x70d6,
+	0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018,
+	0x8001, 0x601a, 0x0c7f, 0x1078, 0x424e, 0x2c50, 0x1078, 0x4492,
+	0x6824, 0xa005, 0x0040, 0x2ba4, 0xa082, 0x0006, 0x0048, 0x2ba2,
+	0x0078, 0x2ba4, 0x6827, 0x0005, 0x6814, 0xa084, 0x001f, 0xc0bd,
+	0x78aa, 0x2031, 0x0020, 0x2041, 0x0001, 0x2001, 0x0003, 0x0078,
+	0x2cd9, 0xc28d, 0x72d6, 0x72c0, 0xa200, 0xa015, 0x7154, 0x8108,
+	0xa12a, 0x0048, 0x2bbc, 0x71c0, 0x2164, 0x6504, 0x85ff, 0x00c0,
+	0x2bd3, 0x7156, 0x8421, 0x00c0, 0x2bb7, 0x70d4, 0xd08c, 0x0040,
+	0x2bcf, 0x70d0, 0xa005, 0x00c0, 0x2bcf, 0x70d3, 0x000a, 0x007c,
+	0x2200, 0x0078, 0x2bc1, 0x70d4, 0xc08c, 0x70d6, 0x70d3, 0x0000,
+	0x6034, 0xa005, 0x00c0, 0x2bd0, 0x6708, 0xa784, 0x073f, 0x0040,
+	0x2c02, 0xd7d4, 0x00c0, 0x2bd0, 0xa784, 0x0021, 0x00c0, 0x2bd0,
+	0xa784, 0x0002, 0x0040, 0x2bf3, 0xa784, 0x0004, 0x0040, 0x2bd0,
+	0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0218, 0x00c0, 0x2bd0, 0xa784,
+	0x0100, 0x0040, 0x2c02, 0x6018, 0xa005, 0x00c0, 0x2bd0, 0xa7bc,
+	0xfeff, 0x670a, 0x2568, 0x6823, 0x0000, 0x6e1c, 0xa684, 0x000e,
+	0x6318, 0x0040, 0x2c13, 0x601c, 0xa302, 0x0048, 0x2c16, 0x0040,
+	0x2c16, 0x0078, 0x2bd0, 0x83ff, 0x00c0, 0x2bd0, 0x2d58, 0x2c50,
+	0x7156, 0xd7bc, 0x00c0, 0x2c1f, 0x7028, 0x6022, 0x603a, 0xc7bc,
+	0x670a, 0x68c0, 0xa065, 0xa04d, 0x6100, 0x2a60, 0x2041, 0x0001,
+	0x6b14, 0xa39c, 0x001f, 0xa39d, 0x00c0, 0xd1fc, 0x0040, 0x2c33,
+	0xd684, 0x0040, 0x2c35, 0xa39c, 0xffbf, 0xd6a4, 0x0040, 0x2c3a,
+	0xa39d, 0x0020, 0xa684, 0x000e, 0x00c0, 0x2c85, 0xc7a5, 0x670a,
+	0x2c00, 0x68c6, 0x77a4, 0xa786, 0x0001, 0x00c0, 0x2c59, 0x70d4,
+	0xd0b4, 0x00c0, 0x2c59, 0x7000, 0xa082, 0x0002, 0x00c8, 0x2c59,
+	0x7830, 0xd0bc, 0x00c0, 0x2c59, 0x789b, 0x0010, 0x7baa, 0x0078,
+	0x2cd1, 0x8739, 0x77a6, 0x2750, 0x77b0, 0xa7b0, 0x0005, 0x70ac,
+	0xa606, 0x00c0, 0x2c64, 0x76a8, 0x76b2, 0x2c3a, 0x8738, 0x2d3a,
+	0x8738, 0x283a, 0x8738, 0x233a, 0x8738, 0x253a, 0x7830, 0xd0bc,
+	0x0040, 0x2c7c, 0x2091, 0x8000, 0x2091, 0x303d, 0x70d4, 0xa084,
+	0x303d, 0x2091, 0x8000, 0x2090, 0xaad5, 0x0000, 0x0040, 0x2c84,
+	0x8421, 0x2200, 0x00c0, 0x2bb6, 0x007c, 0xd1dc, 0x0040, 0x3e49,
+	0x2029, 0x0020, 0xd69c, 0x00c0, 0x2c92, 0x8528, 0xd68c, 0x00c0,
+	0x2c92, 0x8528, 0x8840, 0x6f14, 0x610c, 0x8108, 0xa18c, 0x00ff,
+	0x70cc, 0xa160, 0x2c64, 0x8cff, 0x0040, 0x2cb1, 0x6014, 0xa706,
+	0x00c0, 0x2c9a, 0x60b8, 0x8001, 0x60ba, 0x00c0, 0x2c95, 0x2a60,
+	0x6008, 0xa085, 0x0100, 0x600a, 0x2200, 0x8421, 0x00c0, 0x2bb6,
+	0x007c, 0x2a60, 0x610e, 0x69be, 0x2c00, 0x68c6, 0x8840, 0x6008,
+	0xc0d5, 0x600a, 0x77a4, 0xa786, 0x0001, 0x00c0, 0x2c59, 0x70d4,
+	0xd0b4, 0x00c0, 0x2c59, 0x7000, 0xa082, 0x0002, 0x00c8, 0x2c59,
+	0x7830, 0xd0bc, 0x00c0, 0x2c59, 0x789b, 0x0010, 0x7baa, 0x7daa,
+	0x79aa, 0x2001, 0x0002, 0x007e, 0x6018, 0x8000, 0x601a, 0x0078,
+	0x2cda, 0x007e, 0x2960, 0x6104, 0x2a60, 0xa184, 0x0018, 0x0040,
+	0x2cf6, 0xa184, 0x0010, 0x0040, 0x2ce9, 0x1078, 0x405e, 0x00c0,
+	0x2d1b, 0xa184, 0x0008, 0x0040, 0x2cf6, 0x69a0, 0xa184, 0x0600,
+	0x00c0, 0x2cf6, 0x1078, 0x3f3e, 0x0078, 0x2d1b, 0x69a0, 0xa184,
+	0x1e00, 0x0040, 0x2d26, 0xa184, 0x0800, 0x0040, 0x2d0f, 0x0c7e,
+	0x2960, 0x6000, 0xa085, 0x2000, 0x6002, 0x6104, 0xa18d, 0x0010,
+	0x6106, 0x0c7f, 0x1078, 0x405e, 0x00c0, 0x2d1b, 0x69a0, 0xa184,
+	0x0200, 0x0040, 0x2d17, 0x1078, 0x3fa1, 0x0078, 0x2d1b, 0xa184,
+	0x0400, 0x00c0, 0x2cf2, 0x69a0, 0xa184, 0x1000, 0x0040, 0x2d26,
+	0x6914, 0xa18c, 0xff00, 0x810f, 0x1078, 0x27e6, 0x027f, 0xa68c,
+	0x00e0, 0xa684, 0x0060, 0x0040, 0x2d33, 0xa086, 0x0060, 0x00c0,
+	0x2d33, 0xa18d, 0x4000, 0xa18d, 0x0104, 0x69b6, 0x789b, 0x0060,
+	0x2800, 0x78aa, 0x6818, 0xc0fd, 0x681a, 0xd6bc, 0x0040, 0x2d4e,
+	0xc0fc, 0x7087, 0x0000, 0xa08a, 0x000d, 0x0050, 0x2d4c, 0xa08a,
+	0x000c, 0x7186, 0x2001, 0x000c, 0x800c, 0x718a, 0x78aa, 0x3518,
+	0x3340, 0x3428, 0x8000, 0x80ac, 0xaf80, 0x002b, 0x20a0, 0x789b,
+	0x0000, 0xad80, 0x000b, 0x2098, 0x53a6, 0x23a8, 0x2898, 0x25a0,
+	0xa286, 0x0020, 0x00c0, 0x2d86, 0x70d4, 0xc0b5, 0x70d6, 0x2c00,
+	0x70ba, 0x2d00, 0x70be, 0x6814, 0xc0fc, 0x8007, 0x7882, 0xa286,
+	0x0002, 0x0040, 0x2dbc, 0x70a4, 0x8000, 0x70a6, 0x74b4, 0xa498,
+	0x0005, 0x70ac, 0xa306, 0x00c0, 0x2d7e, 0x73a8, 0x73b6, 0xa286,
+	0x0010, 0x0040, 0x2a08, 0x0d7f, 0x0c7f, 0x007c, 0x7000, 0xa005,
+	0x00c0, 0x2d64, 0xa286, 0x0002, 0x00c0, 0x2dd6, 0x1078, 0x43b0,
+	0x00c0, 0x2d64, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x2091, 0x8000,
+	0x781b, 0x005b, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898,
+	0x78d2, 0x78da, 0x2091, 0x8001, 0x7808, 0xc08d, 0x780a, 0x127e,
+	0x0d7e, 0x0c7e, 0x70d4, 0xa084, 0x2700, 0x2090, 0x0c7f, 0x0d7f,
+	0x127f, 0x2900, 0x705a, 0x68bc, 0x7042, 0x7003, 0x0002, 0x2d00,
+	0x704e, 0xad80, 0x0009, 0x7046, 0x7830, 0xd0bc, 0x0040, 0x2dc8,
+	0x2091, 0x303d, 0x70d4, 0xa084, 0x303d, 0x2091, 0x8000, 0x2090,
+	0x70a4, 0xa005, 0x00c0, 0x2dcd, 0x007c, 0x8421, 0x0040, 0x2dcc,
+	0x7250, 0x70c0, 0xa200, 0xa015, 0x0078, 0x2bb6, 0xa286, 0x0010,
+	0x00c0, 0x2e07, 0x1078, 0x43b0, 0x00c0, 0x2d64, 0x6814, 0xc0fc,
+	0x8007, 0x7882, 0x781b, 0x005b, 0x68b4, 0x785a, 0x6894, 0x78d6,
+	0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d, 0x780a, 0x70a4,
+	0x8000, 0x70a6, 0x74b4, 0xa490, 0x0005, 0x70ac, 0xa206, 0x00c0,
+	0x2dfa, 0x72a8, 0x72b6, 0x2900, 0x705a, 0x68bc, 0x7042, 0x7003,
+	0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x007c, 0x6bb4,
+	0xa39d, 0x2000, 0x7b5a, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x6b94,
+	0x7bd6, 0x7bde, 0x6e98, 0x7ed2, 0x7eda, 0x781b, 0x005b, 0x2900,
+	0x705a, 0x7202, 0x7808, 0xc08d, 0x780a, 0x2300, 0xa605, 0x0040,
+	0x2e32, 0x70d4, 0xa084, 0x2700, 0xa086, 0x2300, 0x00c0, 0x2e2c,
+	0x2009, 0x0000, 0x0078, 0x2e2e, 0x2009, 0x0001, 0xa284, 0x000f,
+	0x1079, 0x2e38, 0xad80, 0x0009, 0x7046, 0x2d00, 0x704e, 0x007c,
+	0x2e40, 0x493f, 0x493f, 0x492c, 0x493f, 0x2e40, 0x2e40, 0x2e40,
+	0x1078, 0x29b2, 0x7808, 0xa084, 0xfffd, 0x780a, 0x1078, 0x29a5,
+	0x0f7e, 0x2079, 0x4f00, 0x78ac, 0x0f7f, 0xd084, 0x0040, 0x2e6a,
+	0x7064, 0xa086, 0x0001, 0x00c0, 0x2e58, 0x7066, 0x0078, 0x2f41,
+	0x7064, 0xa086, 0x0005, 0x00c0, 0x2e68, 0x707c, 0x2068, 0x681b,
+	0x0004, 0x6817, 0x0000, 0x6820, 0xa084, 0x00ff, 0xc09d, 0x6822,
+	0x7067, 0x0000, 0x70a7, 0x0000, 0x70a8, 0x70b2, 0x70b6, 0x1078,
+	0x2b01, 0x157e, 0x2011, 0x0004, 0x7164, 0xa186, 0x0001, 0x0040,
+	0x2e8a, 0xa186, 0x0007, 0x00c0, 0x2e81, 0x701f, 0x0005, 0x0078,
+	0x2e8a, 0x701f, 0x0001, 0x7067, 0x0000, 0x70d4, 0xc0dd, 0x70d6,
+	0x0078, 0x2e8c, 0x7067, 0x0000, 0x2001, 0x4f0a, 0x2004, 0xa084,
+	0x00ff, 0xa086, 0x0018, 0x0040, 0x2e9c, 0x7018, 0x7016, 0xa005,
+	0x00c0, 0x2e9c, 0x70a7, 0x0001, 0x067e, 0x1078, 0x45d6, 0x20a9,
+	0x0010, 0x2039, 0x0000, 0x1078, 0x4148, 0xa7b8, 0x0100, 0x00f0,
+	0x2ea3, 0x067f, 0x7000, 0x0079, 0x2ead, 0x2ee7, 0x2ec2, 0x2ec2,
+	0x2eb7, 0x2ee7, 0x2ee7, 0x2ee7, 0x2eb5, 0x1078, 0x29b2, 0x7060,
+	0xa005, 0x0040, 0x2ee7, 0xad06, 0x00c0, 0x2ec2, 0x6800, 0x7062,
+	0x0078, 0x2ed4, 0x6820, 0xd084, 0x00c0, 0x2ed0, 0x6f14, 0x1078,
+	0x424e, 0x6008, 0xc0d4, 0x600a, 0x1078, 0x3e19, 0x0078, 0x2ed4,
+	0x705c, 0x2060, 0x6800, 0x6002, 0xa684, 0x5f00, 0x681e, 0x6818,
+	0xd0fc, 0x0040, 0x2edc, 0x6a1a, 0x6817, 0x0000, 0x682b, 0x0000,
+	0x6820, 0xa084, 0x00ff, 0xc09d, 0x6822, 0x1078, 0x2073, 0xb284,
+	0x0400, 0x0040, 0x2eef, 0x2021, 0x96d0, 0x0078, 0x2ef1, 0x2021,
+	0x95c0, 0x1078, 0x2f46, 0xb284, 0x0400, 0x0040, 0x2efb, 0x2021,
+	0x4f98, 0x0078, 0x2efd, 0x2021, 0x4f58, 0x1078, 0x2f46, 0x20a9,
+	0x0101, 0xb284, 0x0400, 0x0040, 0x2f09, 0x2021, 0x95d0, 0x0078,
+	0x2f0b, 0x2021, 0x94c0, 0x1078, 0x2f46, 0x8420, 0x00f0, 0x2f0b,
+	0xb284, 0x0300, 0x0040, 0x2f18, 0x2061, 0x54c0, 0x0078, 0x2f1a,
+	0x2061, 0x74c0, 0x2021, 0x0002, 0x20a9, 0x0100, 0x6110, 0x81ff,
+	0x0040, 0x2f37, 0x6018, 0x017e, 0x007e, 0x2011, 0x4f02, 0x220c,
+	0xa102, 0x2012, 0x007f, 0x017f, 0xa102, 0x0050, 0x2f37, 0x6012,
+	0x00c0, 0x2f37, 0x2011, 0x4f04, 0x2204, 0xc0a5, 0x2012, 0x601b,
+	0x0000, 0xace0, 0x0010, 0x00f0, 0x2f1e, 0x8421, 0x00c0, 0x2f1c,
+	0x157f, 0x7003, 0x0000, 0x704f, 0x0000, 0x007c, 0x047e, 0x2404,
+	0xa005, 0x0040, 0x2f61, 0x2068, 0x6800, 0x007e, 0x6a1a, 0x6817,
+	0x0000, 0x682b, 0x0000, 0x68b4, 0xa084, 0x5f00, 0x681e, 0x6820,
+	0xa084, 0x00ff, 0xc09d, 0x6822, 0x1078, 0x2073, 0x007f, 0x0078,
+	0x2f48, 0x047f, 0x2023, 0x0000, 0x007c, 0xa282, 0x0003, 0x0050,
+	0x2f6b, 0x1078, 0x29b2, 0x2300, 0x0079, 0x2f6e, 0x2f71, 0x2ffc,
+	0x3019, 0xa282, 0x0002, 0x0040, 0x2f77, 0x1078, 0x29b2, 0x7064,
+	0x7067, 0x0000, 0x7083, 0x0000, 0x0079, 0x2f7e, 0x2f86, 0x2f86,
+	0x2f88, 0x2fc8, 0x3e55, 0x2f86, 0x2fc8, 0x2f86, 0x1078, 0x29b2,
+	0x7774, 0x1078, 0x4148, 0x7774, 0xa7bc, 0x8f00, 0x1078, 0x424e,
+	0x6018, 0xa005, 0x0040, 0x2fbf, 0xd7fc, 0x00c0, 0x2f9b, 0x2021,
+	0x95c0, 0x0078, 0x2f9d, 0x2021, 0x96d0, 0x2009, 0x0005, 0x2011,
+	0x0010, 0x1078, 0x3034, 0x0040, 0x2fbf, 0x157e, 0x20a9, 0x0101,
+	0xd7fc, 0x00c0, 0x2faf, 0x2021, 0x94c0, 0x0078, 0x2fb1, 0x2021,
+	0x95d0, 0x047e, 0x2009, 0x0005, 0x2011, 0x0010, 0x1078, 0x3034,
+	0x047f, 0x0040, 0x2fbe, 0x8420, 0x00f0, 0x2fb1, 0x157f, 0x8738,
+	0xa784, 0x001f, 0x00c0, 0x2f8e, 0x0078, 0x2a0c, 0x0078, 0x2a0c,
+	0x7774, 0x1078, 0x424e, 0x6018, 0xa005, 0x0040, 0x2ffa, 0xd7fc,
+	0x00c0, 0x2fd6, 0x2021, 0x95c0, 0x0078, 0x2fd8, 0x2021, 0x96d0,
+	0x2009, 0x0005, 0x2011, 0x0020, 0x1078, 0x3034, 0x0040, 0x2ffa,
+	0x157e, 0x20a9, 0x0101, 0xd7fc, 0x00c0, 0x2fea, 0x2021, 0x94c0,
+	0x0078, 0x2fec, 0x2021, 0x95d0, 0x047e, 0x2009, 0x0005, 0x2011,
+	0x0020, 0x1078, 0x3034, 0x047f, 0x0040, 0x2ff9, 0x8420, 0x00f0,
+	0x2fec, 0x157f, 0x0078, 0x2a0c, 0x2200, 0x0079, 0x2fff, 0x3002,
+	0x3004, 0x3004, 0x1078, 0x29b2, 0x2009, 0x0012, 0x7064, 0xa086,
+	0x0002, 0x0040, 0x300d, 0x2009, 0x000e, 0x6818, 0xd0fc, 0x0040,
+	0x3012, 0x691a, 0x7067, 0x0000, 0x70d4, 0xc0dd, 0x70d6, 0x0078,
+	0x435d, 0x2200, 0x0079, 0x301c, 0x3021, 0x3004, 0x301f, 0x1078,
+	0x29b2, 0x1078, 0x45d6, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3dc7,
+	0x1078, 0x3e36, 0x6008, 0xa084, 0xfbef, 0x600a, 0x1078, 0x3db8,
+	0x0040, 0x3dc7, 0x0078, 0x2a0c, 0x2404, 0xa005, 0x0040, 0x306d,
+	0x2068, 0x2d04, 0x007e, 0x6814, 0xa706, 0x0040, 0x3043, 0x2d20,
+	0x007f, 0x0078, 0x3035, 0x007f, 0x2022, 0x691a, 0x6817, 0x0000,
 	0x682b, 0x0000, 0x68b4, 0xa084, 0x5f00, 0x681e, 0x6820, 0xa084,
-	0x00ff, 0xc09d, 0x6822, 0x1078, 0x202c, 0x007f, 0x0078, 0x2eff,
-	0x047f, 0x2023, 0x0000, 0x007c, 0xa282, 0x0003, 0x0050, 0x2f22,
-	0x1078, 0x296b, 0x2300, 0x0079, 0x2f25, 0x2f28, 0x2fb3, 0x2fd0,
-	0xa282, 0x0002, 0x0040, 0x2f2e, 0x1078, 0x296b, 0x7064, 0x7067,
-	0x0000, 0x7083, 0x0000, 0x0079, 0x2f35, 0x2f3d, 0x2f3d, 0x2f3f,
-	0x2f7f, 0x3e0c, 0x2f3d, 0x2f7f, 0x2f3d, 0x1078, 0x296b, 0x7774,
-	0x1078, 0x40f8, 0x7774, 0xa7bc, 0x8f00, 0x1078, 0x41fe, 0x6018,
-	0xa005, 0x0040, 0x2f76, 0xd7fc, 0x00c0, 0x2f52, 0x2021, 0x94c0,
-	0x0078, 0x2f54, 0x2021, 0x95d0, 0x2009, 0x0005, 0x2011, 0x0010,
-	0x1078, 0x2feb, 0x0040, 0x2f76, 0x157e, 0x20a9, 0x0101, 0xd7fc,
-	0x00c0, 0x2f66, 0x2021, 0x93c0, 0x0078, 0x2f68, 0x2021, 0x94d0,
-	0x047e, 0x2009, 0x0005, 0x2011, 0x0010, 0x1078, 0x2feb, 0x047f,
-	0x0040, 0x2f75, 0x8420, 0x00f0, 0x2f68, 0x157f, 0x8738, 0xa784,
-	0x001f, 0x00c0, 0x2f45, 0x0078, 0x29c5, 0x0078, 0x29c5, 0x7774,
-	0x1078, 0x41fe, 0x6018, 0xa005, 0x0040, 0x2fb1, 0xd7fc, 0x00c0,
-	0x2f8d, 0x2021, 0x94c0, 0x0078, 0x2f8f, 0x2021, 0x95d0, 0x2009,
-	0x0005, 0x2011, 0x0020, 0x1078, 0x2feb, 0x0040, 0x2fb1, 0x157e,
-	0x20a9, 0x0101, 0xd7fc, 0x00c0, 0x2fa1, 0x2021, 0x93c0, 0x0078,
-	0x2fa3, 0x2021, 0x94d0, 0x047e, 0x2009, 0x0005, 0x2011, 0x0020,
-	0x1078, 0x2feb, 0x047f, 0x0040, 0x2fb0, 0x8420, 0x00f0, 0x2fa3,
-	0x157f, 0x0078, 0x29c5, 0x2200, 0x0079, 0x2fb6, 0x2fb9, 0x2fbb,
-	0x2fbb, 0x1078, 0x296b, 0x2009, 0x0012, 0x7064, 0xa086, 0x0002,
-	0x0040, 0x2fc4, 0x2009, 0x000e, 0x6818, 0xd0fc, 0x0040, 0x2fc9,
-	0x691a, 0x7067, 0x0000, 0x70d4, 0xc0dd, 0x70d6, 0x0078, 0x430d,
-	0x2200, 0x0079, 0x2fd3, 0x2fd8, 0x2fbb, 0x2fd6, 0x1078, 0x296b,
-	0x1078, 0x4586, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3d7e, 0x1078,
-	0x3ded, 0x6008, 0xa084, 0xfbef, 0x600a, 0x1078, 0x3d6f, 0x0040,
-	0x3d7e, 0x0078, 0x29c5, 0x2404, 0xa005, 0x0040, 0x3024, 0x2068,
-	0x2d04, 0x007e, 0x6814, 0xa706, 0x0040, 0x2ffa, 0x2d20, 0x007f,
-	0x0078, 0x2fec, 0x007f, 0x2022, 0x691a, 0x6817, 0x0000, 0x682b,
-	0x0000, 0x68b4, 0xa084, 0x5f00, 0x681e, 0x6820, 0xa084, 0x00ff,
-	0xa205, 0x6822, 0x1078, 0x202c, 0x2021, 0x4e02, 0x241c, 0x8319,
-	0x2322, 0x6010, 0x8001, 0x6012, 0x00c0, 0x301b, 0x2021, 0x4e04,
-	0x2404, 0xc0a5, 0x2022, 0x6008, 0xa084, 0xf9ef, 0x600a, 0x1078,
-	0x2adb, 0x1078, 0x3ded, 0x007c, 0xa085, 0x0001, 0x0078, 0x3023,
-	0x2300, 0x0079, 0x302b, 0x3030, 0x302e, 0x30b0, 0x1078, 0x296b,
-	0x78e4, 0xa005, 0x00d0, 0x3066, 0x3208, 0x007e, 0x2001, 0x4e04,
-	0x2004, 0xd0ec, 0x007f, 0x0040, 0x3041, 0xa18c, 0x0300, 0x0078,
-	0x3043, 0xa18c, 0x0400, 0x0040, 0x3049, 0x0018, 0x29c1, 0x0078,
-	0x304b, 0x0028, 0x29c1, 0x2008, 0xa084, 0x0030, 0x00c0, 0x3052,
-	0x0078, 0x3770, 0x78ec, 0xa084, 0x0003, 0x0040, 0x3050, 0x2100,
-	0xa084, 0x0007, 0x0079, 0x305c, 0x3090, 0x309a, 0x3085, 0x3064,
-	0x4355, 0x4355, 0x3064, 0x30a5, 0x1078, 0x296b, 0x7000, 0xa086,
-	0x0004, 0x00c0, 0x3080, 0x7064, 0xa086, 0x0002, 0x00c0, 0x3076,
-	0x2011, 0x0002, 0x2019, 0x0000, 0x0078, 0x2f1c, 0x7064, 0xa086,
-	0x0006, 0x0040, 0x3070, 0x7064, 0xa086, 0x0004, 0x0040, 0x3070,
-	0x79e4, 0x2001, 0x0003, 0x0078, 0x33fa, 0x6818, 0xd0fc, 0x0040,
-	0x308b, 0x681b, 0x001d, 0x1078, 0x40c8, 0x781b, 0x0064, 0x007c,
-	0x6818, 0xd0fc, 0x0040, 0x3096, 0x681b, 0x001d, 0x1078, 0x40c8,
-	0x0078, 0x4331, 0x6818, 0xd0fc, 0x0040, 0x30a0, 0x681b, 0x001d,
-	0x1078, 0x40c8, 0x781b, 0x00f8, 0x007c, 0x6818, 0xd0fc, 0x0040,
-	0x30ab, 0x681b, 0x001d, 0x1078, 0x40c8, 0x781b, 0x00c8, 0x007c,
-	0xa584, 0x000f, 0x00c0, 0x30cf, 0x1078, 0x295e, 0x7000, 0x0079,
-	0x30b9, 0x29c5, 0x30c1, 0x30c3, 0x3d7e, 0x3d7e, 0x3d7e, 0x30c1,
-	0x30c1, 0x1078, 0x296b, 0x1078, 0x3ded, 0x6008, 0xa084, 0xfbef,
-	0x600a, 0x1078, 0x3d6f, 0x0040, 0x3d7e, 0x0078, 0x29c5, 0x78e4,
-	0xa005, 0x00d0, 0x3066, 0x3208, 0x007e, 0x2001, 0x4e04, 0x2004,
-	0xd0ec, 0x007f, 0x0040, 0x30e0, 0xa18c, 0x0300, 0x0078, 0x30e2,
-	0xa18c, 0x0400, 0x0040, 0x30e8, 0x0018, 0x3066, 0x0078, 0x30ea,
-	0x0028, 0x3066, 0x2008, 0xa084, 0x0030, 0x00c0, 0x30f2, 0x781b,
-	0x005b, 0x007c, 0x78ec, 0xa084, 0x0003, 0x0040, 0x30ef, 0x2100,
-	0xa184, 0x0007, 0x0079, 0x30fc, 0x310b, 0x310f, 0x3106, 0x3104,
-	0x4355, 0x4355, 0x3104, 0x434f, 0x1078, 0x296b, 0x1078, 0x40d0,
-	0x781b, 0x0064, 0x007c, 0x1078, 0x40d0, 0x0078, 0x4331, 0x1078,
-	0x40d0, 0x781b, 0x00f8, 0x007c, 0x1078, 0x40d0, 0x781b, 0x00c8,
-	0x007c, 0x2300, 0x0079, 0x311c, 0x3121, 0x311f, 0x3123, 0x1078,
-	0x296b, 0x0078, 0x395f, 0x681b, 0x0016, 0x78a3, 0x0000, 0x79e4,
-	0xa184, 0x0030, 0x0040, 0x395f, 0x78ec, 0xa084, 0x0003, 0x0040,
-	0x395f, 0xa184, 0x0100, 0x0040, 0x3127, 0xa184, 0x0007, 0x0079,
-	0x3139, 0x3141, 0x310f, 0x3085, 0x430d, 0x4355, 0x4355, 0x430d,
-	0x434f, 0x1078, 0x4319, 0x007c, 0xa282, 0x0005, 0x0050, 0x314a,
-	0x1078, 0x296b, 0x2300, 0x0079, 0x314d, 0x3150, 0x3380, 0x338b,
-	0x2200, 0x0079, 0x3153, 0x316d, 0x315a, 0x316d, 0x3158, 0x3363,
-	0x1078, 0x296b, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa082,
-	0x0020, 0x0048, 0x40b7, 0xa08a, 0x0004, 0x00c8, 0x40b7, 0x0079,
-	0x3169, 0x40b7, 0x40b7, 0x40b7, 0x4061, 0x789b, 0x0018, 0x79a8,
-	0xa184, 0x0080, 0x0040, 0x317e, 0x0078, 0x40b7, 0x7000, 0xa005,
-	0x00c0, 0x3174, 0x2011, 0x0004, 0x0078, 0x3b4a, 0xa184, 0x00ff,
-	0xa08a, 0x0010, 0x00c8, 0x40b7, 0x0079, 0x3186, 0x3198, 0x3196,
-	0x31ad, 0x31b1, 0x3284, 0x40b7, 0x40b7, 0x3286, 0x40b7, 0x40b7,
-	0x335f, 0x335f, 0x40b7, 0x40b7, 0x40b7, 0x3361, 0x1078, 0x296b,
-	0xd6e4, 0x0040, 0x31a3, 0x2001, 0x0300, 0x8000, 0x8000, 0x783a,
-	0x781b, 0x00c3, 0x007c, 0x6818, 0xd0fc, 0x0040, 0x31ab, 0x681b,
-	0x001d, 0x0078, 0x319b, 0x0078, 0x430d, 0x681b, 0x001d, 0x0078,
-	0x40c1, 0x6920, 0x6922, 0xa684, 0x1800, 0x00c0, 0x3216, 0x6820,
-	0xd084, 0x00c0, 0x321c, 0x6818, 0xa086, 0x0008, 0x00c0, 0x31c2,
-	0x681b, 0x0000, 0xd6d4, 0x0040, 0x3281, 0xd6bc, 0x0040, 0x3202,
-	0x7087, 0x0000, 0x6818, 0xa084, 0x003f, 0xa08a, 0x000d, 0x0050,
-	0x3202, 0xa08a, 0x000c, 0x7186, 0x2001, 0x000c, 0x800c, 0x718a,
-	0x789b, 0x0061, 0x78aa, 0x157e, 0x137e, 0x147e, 0x017e, 0x3208,
-	0xa18c, 0x0300, 0x0040, 0x31f4, 0x007e, 0x2001, 0x4e04, 0x2004,
-	0xd0ec, 0x007f, 0x0040, 0x31f0, 0x20a1, 0x012b, 0x0078, 0x31f6,
-	0x20a1, 0x022b, 0x0078, 0x31f6, 0x20a1, 0x012b, 0x017f, 0x789b,
-	0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f,
-	0x137f, 0x157f, 0x6038, 0xa005, 0x00c0, 0x3211, 0x681c, 0xa084,
-	0x000e, 0x0040, 0x40c1, 0x1078, 0x40d7, 0x782b, 0x3008, 0x0078,
-	0x3213, 0x8001, 0x603a, 0x781b, 0x0067, 0x007c, 0xd6e4, 0x0040,
-	0x321c, 0x781b, 0x0079, 0x007c, 0xa684, 0x0060, 0x0040, 0x327e,
-	0xd6dc, 0x0040, 0x327e, 0xd6fc, 0x00c0, 0x3228, 0x0078, 0x323f,
-	0xc6fc, 0x7e5a, 0x6eb6, 0x7adc, 0x79d8, 0x78d0, 0x801b, 0x00c8,
-	0x3232, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x6b98,
-	0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0xd6f4,
-	0x0040, 0x3245, 0xc6f4, 0x7e5a, 0x6eb6, 0x7000, 0xa086, 0x0003,
-	0x00c0, 0x3253, 0x007e, 0x1078, 0x4586, 0x1078, 0x48bd, 0x007f,
-	0x781b, 0x0076, 0x007c, 0xa006, 0x1078, 0x49c3, 0x6ab0, 0x69ac,
-	0x6c98, 0x6b94, 0x2200, 0xa105, 0x0040, 0x3262, 0x2200, 0xa422,
-	0x2100, 0xa31b, 0x6caa, 0x7cd2, 0x7cda, 0x6ba6, 0x7bd6, 0x7bde,
-	0x2300, 0xa405, 0x00c0, 0x3272, 0xc6f5, 0x7e5a, 0x6eb6, 0x781b,
-	0x0076, 0x007c, 0x781b, 0x0076, 0x2200, 0xa115, 0x00c0, 0x327b,
-	0x1078, 0x48bd, 0x007c, 0x1078, 0x48f5, 0x007c, 0x781b, 0x0079,
-	0x007c, 0x781b, 0x0067, 0x007c, 0x1078, 0x296b, 0x0078, 0x32d2,
-	0x6920, 0xd1c4, 0x0040, 0x329b, 0xc1c4, 0x6922, 0x0c7e, 0x7058,
-	0x2060, 0x6000, 0xc0e4, 0x6002, 0x6004, 0xa084, 0xfff5, 0x6006,
-	0x0c7f, 0x0078, 0x32c6, 0xd1cc, 0x0040, 0x32c6, 0xc1cc, 0x6922,
-	0x0c7e, 0x7058, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x6004, 0xc0a4,
-	0x6006, 0x2008, 0x2c48, 0x0c7f, 0xd19c, 0x0040, 0x32c6, 0x1078,
-	0x41fa, 0x1078, 0x3ef5, 0x88ff, 0x0040, 0x32c6, 0x789b, 0x0060,
-	0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x00c0, 0x32c3,
-	0x781b, 0x0064, 0x007c, 0x781b, 0x0078, 0x007c, 0x7e58, 0xd6d4,
-	0x00c0, 0x32cd, 0x781b, 0x0067, 0x007c, 0x781b, 0x0079, 0x007c,
-	0x0078, 0x40bc, 0x2019, 0x0000, 0x7990, 0xa18c, 0x0007, 0x00c0,
-	0x32e0, 0x6820, 0xa084, 0x0100, 0x0040, 0x32d0, 0x2009, 0x0008,
-	0x789b, 0x0010, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001, 0x00c0,
-	0x32fc, 0x2300, 0x7ca8, 0xa400, 0x2018, 0xa102, 0x0040, 0x32f4,
-	0x0048, 0x32f4, 0x0078, 0x32f6, 0x0078, 0x3288, 0x24a8, 0x7aa8,
-	0x00f0, 0x32f6, 0x0078, 0x32e2, 0xa284, 0x00f0, 0xa086, 0x0020,
-	0x00c0, 0x3350, 0x8318, 0x8318, 0x2300, 0xa102, 0x0040, 0x330c,
-	0x0048, 0x330c, 0x0078, 0x334d, 0xa286, 0x0023, 0x0040, 0x32d0,
-	0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58, 0xa684, 0xfff1, 0xc0a5,
-	0x2030, 0x7e5a, 0x6008, 0xc0a5, 0x600a, 0x0c7e, 0x7058, 0x2060,
-	0x6004, 0x2008, 0x2c48, 0x0c7f, 0xd1a4, 0x0040, 0x332d, 0x1078,
-	0x41fa, 0x1078, 0x4011, 0x0078, 0x333b, 0x0c7e, 0x7058, 0x2060,
-	0x6004, 0x2008, 0x2c48, 0x0c7f, 0xd19c, 0x0040, 0x32c6, 0x1078,
-	0x41fa, 0x1078, 0x3ef5, 0x88ff, 0x0040, 0x32c6, 0x789b, 0x0060,
-	0x2800, 0x78aa, 0xc695, 0x7e5a, 0xd6d4, 0x00c0, 0x334a, 0x781b,
-	0x0064, 0x007c, 0x781b, 0x0078, 0x007c, 0x7aa8, 0x0078, 0x32e2,
-	0x8318, 0x2300, 0xa102, 0x0040, 0x3359, 0x0048, 0x3359, 0x0078,
-	0x32e2, 0xa284, 0x0080, 0x00c0, 0x40c1, 0x0078, 0x40bc, 0x0078,
-	0x40c1, 0x0078, 0x40b7, 0x7058, 0xa04d, 0x789b, 0x0018, 0x78a8,
-	0xa084, 0x00ff, 0xa08e, 0x0001, 0x0040, 0x3370, 0x1078, 0x296b,
-	0x7aa8, 0xa294, 0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a, 0x0004,
-	0x00c8, 0x40b7, 0x0079, 0x337c, 0x40b7, 0x3e46, 0x40b7, 0x3fb9,
-	0xa282, 0x0000, 0x00c0, 0x3386, 0x1078, 0x296b, 0x1078, 0x40c8,
-	0x781b, 0x0078, 0x007c, 0xa282, 0x0003, 0x00c0, 0x3391, 0x1078,
-	0x296b, 0xd4fc, 0x00c0, 0x33b1, 0x7064, 0xa005, 0x0040, 0x339a,
-	0x1078, 0x296b, 0x6f14, 0x7776, 0xa7bc, 0x8f00, 0x1078, 0x41fe,
-	0x6008, 0xa085, 0x0021, 0x600a, 0x8738, 0xa784, 0x001f, 0x00c0,
-	0x339e, 0x1078, 0x40cc, 0x7067, 0x0002, 0x701f, 0x0009, 0x0078,
-	0x33b3, 0x1078, 0x40db, 0x781b, 0x0078, 0x007c, 0xa282, 0x0004,
-	0x0050, 0x33bc, 0x1078, 0x296b, 0x2300, 0x0079, 0x33bf, 0x33c2,
-	0x3582, 0x35c5, 0xa286, 0x0003, 0x0040, 0x33fa, 0x7200, 0x7cd8,
-	0x7ddc, 0x7fd0, 0x71d4, 0xd1bc, 0x00c0, 0x33f2, 0xd1b4, 0x0040,
-	0x33f2, 0x7868, 0xa084, 0x00ff, 0x00c0, 0x33f2, 0xa282, 0x0002,
-	0x00c8, 0x33f2, 0x0d7e, 0x783b, 0x8300, 0x781b, 0x004c, 0x70bc,
-	0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2,
-	0x78da, 0xc1b4, 0x71d6, 0x7003, 0x0030, 0x0d7f, 0x2001, 0x0000,
-	0x0078, 0x33fe, 0x783b, 0x1300, 0x781b, 0x004a, 0x2001, 0x0000,
-	0x0078, 0x33fe, 0x7200, 0x7cd8, 0x7ddc, 0x7fd0, 0x704a, 0x68a0,
-	0xd0ec, 0x0040, 0x3406, 0x6008, 0xc08d, 0x600a, 0xa284, 0x000f,
-	0x0079, 0x340a, 0x3562, 0x3417, 0x3414, 0x36c8, 0x3754, 0x29c5,
-	0x3412, 0x3412, 0x1078, 0x296b, 0x6008, 0xc0d4, 0x600a, 0xd6e4,
-	0x0040, 0x341f, 0x7048, 0xa086, 0x0014, 0x00c0, 0x343f, 0x1078,
-	0x4586, 0x2009, 0x0000, 0x6818, 0xd0fc, 0x0040, 0x3428, 0x7048,
-	0xa086, 0x0014, 0x0040, 0x3439, 0x6818, 0xa086, 0x0008, 0x00c0,
-	0x351a, 0x7858, 0xd09c, 0x0040, 0x351a, 0x6820, 0xd0ac, 0x0040,
-	0x351a, 0x681b, 0x0014, 0x2009, 0x0002, 0x0078, 0x347e, 0x7868,
-	0xa08c, 0x00ff, 0x0040, 0x347e, 0xa186, 0x0008, 0x00c0, 0x3455,
-	0x6008, 0xc0a4, 0x600a, 0x1078, 0x3d6f, 0x0040, 0x347e, 0x1078,
-	0x3ded, 0x1078, 0x4586, 0x0078, 0x3466, 0xa186, 0x0028, 0x00c0,
-	0x347e, 0x6018, 0xa005, 0x0040, 0x3448, 0x8001, 0x0040, 0x3448,
-	0x8001, 0x0040, 0x3448, 0x601e, 0x0078, 0x3448, 0x6820, 0xd084,
-	0x0040, 0x29c5, 0xc084, 0x6822, 0x1078, 0x2acc, 0x705c, 0x0c7e,
-	0x2060, 0x6800, 0x6002, 0x0c7f, 0x6004, 0x6802, 0xa005, 0x2d00,
-	0x00c0, 0x347b, 0x6002, 0x6006, 0x0078, 0x29c5, 0x017e, 0x81ff,
-	0x00c0, 0x34c8, 0x7000, 0xa086, 0x0030, 0x0040, 0x34c8, 0x71d4,
-	0xd1bc, 0x00c0, 0x34c8, 0xd1b4, 0x00c0, 0x34af, 0x7060, 0xa005,
-	0x00c0, 0x34c8, 0x70a4, 0xa086, 0x0001, 0x0040, 0x34c8, 0x7003,
-	0x0000, 0x047e, 0x057e, 0x077e, 0x067e, 0x0c7e, 0x0d7e, 0x1078,
-	0x29ee, 0x0d7f, 0x0c7f, 0x067f, 0x077f, 0x057f, 0x047f, 0x71d4,
-	0xd1b4, 0x00c0, 0x34c8, 0x7003, 0x0040, 0x0078, 0x34c8, 0x1078,
-	0x4360, 0x00c0, 0x34c8, 0x781b, 0x005b, 0x0d7e, 0x70bc, 0xa06d,
-	0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da,
-	0xc1b4, 0x71d6, 0x7003, 0x0030, 0x7808, 0xc08d, 0x780a, 0x0d7f,
-	0x1078, 0x35ff, 0x017f, 0x81ff, 0x0040, 0x351a, 0xa684, 0xdf00,
-	0x681e, 0x682b, 0x0000, 0x6f14, 0xa186, 0x0002, 0x00c0, 0x351b,
-	0x6818, 0xa086, 0x0014, 0x00c0, 0x34e4, 0x2008, 0xd6e4, 0x0040,
-	0x34e4, 0x7868, 0xa08c, 0x00ff, 0x1078, 0x2aba, 0x1078, 0x2adb,
-	0x6820, 0xd0dc, 0x00c0, 0x351b, 0x8717, 0xa294, 0x000f, 0x8213,
-	0x8213, 0x8213, 0xb284, 0x0300, 0x0040, 0x34fa, 0xa290, 0x52c0,
-	0x0078, 0x34fc, 0xa290, 0x5340, 0xa290, 0x0000, 0x221c, 0xd3c4,
-	0x00c0, 0x3504, 0x0078, 0x350a, 0x8210, 0x2204, 0xa085, 0x0018,
-	0x2012, 0x8211, 0xd3d4, 0x0040, 0x3515, 0x68a0, 0xd0c4, 0x00c0,
-	0x3515, 0x1078, 0x3679, 0x0078, 0x29c5, 0x6008, 0xc08d, 0x600a,
-	0x0078, 0x351b, 0x692a, 0x6916, 0x6818, 0xd0fc, 0x0040, 0x3522,
-	0x7048, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x6410, 0x84ff, 0x0040,
-	0x3537, 0x2009, 0x4e02, 0x2104, 0x8001, 0x200a, 0x8421, 0x6412,
-	0x00c0, 0x3537, 0x2021, 0x4e04, 0x2404, 0xc0a5, 0x2022, 0x6018,
-	0xa005, 0x0040, 0x353f, 0x8001, 0x601a, 0x00c0, 0x3542, 0x6008,
-	0xc0a4, 0x600a, 0x6820, 0xd084, 0x00c0, 0x354e, 0x6800, 0xa005,
-	0x00c0, 0x354b, 0x6002, 0x6006, 0x0078, 0x3552, 0x705c, 0x2060,
-	0x6800, 0x6002, 0x2061, 0x4e00, 0x6887, 0x0103, 0x2d08, 0x206b,
-	0x0000, 0x6068, 0xa005, 0x616a, 0x0040, 0x3561, 0x2d02, 0x0078,
-	0x3562, 0x616e, 0x7200, 0xa286, 0x0030, 0x0040, 0x3572, 0xa286,
-	0x0040, 0x00c0, 0x29c5, 0x7003, 0x0002, 0x704c, 0x2068, 0x68c4,
-	0x2060, 0x007c, 0x7003, 0x0002, 0x70bc, 0xa06d, 0x68bc, 0x7042,
-	0x70b8, 0xa065, 0x68c0, 0x705a, 0x2d00, 0x704e, 0xad80, 0x0009,
-	0x7046, 0x007c, 0xa282, 0x0004, 0x0048, 0x3588, 0x1078, 0x296b,
-	0x2200, 0x0079, 0x358b, 0x358f, 0x35a0, 0x35ad, 0x35a0, 0xa586,
-	0x1300, 0x0040, 0x35a0, 0xa586, 0x8300, 0x00c0, 0x3586, 0x7003,
-	0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084, 0xfbef, 0x600a,
-	0x7000, 0xa086, 0x0005, 0x0040, 0x35aa, 0x1078, 0x40c8, 0x781b,
-	0x0078, 0x007c, 0x781b, 0x0079, 0x007c, 0x7890, 0x8007, 0x8001,
-	0xa084, 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c, 0x00ff,
-	0xa186, 0x0003, 0x0040, 0x35c2, 0xa186, 0x0000, 0x0040, 0x35c2,
-	0x0078, 0x40b7, 0x781b, 0x0079, 0x007c, 0x6820, 0xc095, 0x6822,
-	0x82ff, 0x00c0, 0x35cf, 0x1078, 0x40c8, 0x0078, 0x35d6, 0x8211,
-	0x0040, 0x35d4, 0x1078, 0x296b, 0x1078, 0x40db, 0x781b, 0x0078,
-	0x007c, 0x1078, 0x4383, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x35fc,
-	0x017e, 0x3208, 0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f,
-	0x0040, 0x35ee, 0xa18c, 0x0300, 0x0078, 0x35f0, 0xa18c, 0x0400,
-	0x017f, 0x0040, 0x35f7, 0x0018, 0x35fc, 0x0078, 0x35f9, 0x0028,
-	0x35fc, 0x791a, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c, 0xa684,
-	0x0060, 0x00c0, 0x3609, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078,
-	0x3678, 0xd6dc, 0x00c0, 0x3621, 0x68b4, 0xd0dc, 0x00c0, 0x3621,
-	0x6998, 0x6a94, 0x692e, 0x6a32, 0x7048, 0xa005, 0x00c0, 0x361e,
-	0x2200, 0xa105, 0x0040, 0x4586, 0x704b, 0x0015, 0x0078, 0x4586,
-	0x007c, 0xd6ac, 0x0040, 0x3647, 0xd6f4, 0x0040, 0x362d, 0x682f,
-	0x0000, 0x6833, 0x0000, 0x0078, 0x4586, 0x68b4, 0xa084, 0x4000,
-	0xa635, 0xd6f4, 0x00c0, 0x3627, 0x7048, 0xa005, 0x00c0, 0x363a,
-	0x704b, 0x0015, 0xd6dc, 0x00c0, 0x3643, 0x68b4, 0xd0dc, 0x0040,
-	0x3643, 0x6ca8, 0x6da4, 0x6c2e, 0x6d32, 0x0078, 0x4586, 0xd6f4,
-	0x0040, 0x3650, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x4586,
-	0x68b4, 0xa084, 0x4800, 0xa635, 0xd6f4, 0x00c0, 0x364a, 0x7048,
-	0xa005, 0x00c0, 0x365d, 0x704b, 0x0015, 0x2408, 0x2510, 0x2700,
-	0x80fb, 0x00c8, 0x3664, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291,
-	0x0000, 0x692e, 0x6a32, 0x2100, 0xa205, 0x00c0, 0x3671, 0x0078,
-	0x4586, 0x7000, 0xa086, 0x0006, 0x0040, 0x3678, 0x0078, 0x4586,
-	0x007c, 0x6946, 0x6008, 0xc0cd, 0xd3cc, 0x0040, 0x3680, 0xc08d,
-	0x600a, 0x6818, 0x683a, 0x681b, 0x0006, 0x688f, 0x0000, 0x6893,
-	0x0000, 0x6a30, 0x692c, 0x6a3e, 0x6942, 0x682f, 0x0003, 0x6833,
-	0x0000, 0x6837, 0x0020, 0x6897, 0x0000, 0x689b, 0x0020, 0x7000,
-	0x0079, 0x369a, 0x29c5, 0x36ac, 0x36a4, 0x36a2, 0x36a2, 0x36a2,
-	0x36a2, 0x36a2, 0x1078, 0x296b, 0x6820, 0xd084, 0x00c0, 0x36ac,
-	0x1078, 0x3dd0, 0x0078, 0x36b2, 0x705c, 0x2c50, 0x2060, 0x6800,
-	0x6002, 0x2a60, 0x3208, 0xa18c, 0x0300, 0x0040, 0x36bb, 0x2021,
-	0x4e58, 0x0078, 0x36bd, 0x2021, 0x4e98, 0x2404, 0xa005, 0x0040,
-	0x36c4, 0x2020, 0x0078, 0x36bd, 0x2d22, 0x206b, 0x0000, 0x007c,
-	0x1078, 0x3dd7, 0x1078, 0x3ded, 0x6008, 0xc0cc, 0x600a, 0x682b,
-	0x0000, 0x789b, 0x000e, 0x6f14, 0x6938, 0x691a, 0x6944, 0x6916,
-	0x3208, 0xa18c, 0x0300, 0x0040, 0x36e1, 0x2009, 0x0000, 0x0078,
-	0x36e3, 0x2009, 0x0001, 0x1078, 0x49f8, 0xd6dc, 0x0040, 0x36eb,
-	0x691c, 0xc1ed, 0x691e, 0x6818, 0xd0fc, 0x0040, 0x36fa, 0x7868,
-	0xa08c, 0x00ff, 0x0040, 0x36f8, 0x681b, 0x001e, 0x0078, 0x36fa,
-	0x681b, 0x0000, 0xb284, 0x0300, 0x00c0, 0x3702, 0x2021, 0x4e98,
-	0x0078, 0x3704, 0x2021, 0x4e58, 0x6800, 0x2022, 0x6a3c, 0x6940,
-	0x6a32, 0x692e, 0x68c0, 0x2060, 0x6000, 0xd0a4, 0x0040, 0x3744,
-	0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x0d7e, 0x0f7e,
-	0x157e, 0x147e, 0x2079, 0x4e00, 0x1078, 0x1dff, 0x147f, 0x157f,
-	0x0f7f, 0x70cc, 0x2010, 0x2009, 0x0101, 0x027e, 0x2204, 0xa06d,
-	0x0040, 0x3734, 0x6814, 0xa706, 0x0040, 0x3731, 0x6800, 0x0078,
-	0x3727, 0x6820, 0xc0d5, 0x6822, 0x027f, 0x8210, 0x8109, 0x00c0,
-	0x3725, 0x0d7f, 0x7067, 0x0003, 0x707f, 0x0000, 0x7776, 0x7083,
-	0x000f, 0x71d4, 0xc1dc, 0x71d6, 0x6818, 0xa086, 0x0002, 0x00c0,
-	0x3750, 0x6817, 0x0000, 0x682b, 0x0000, 0x681c, 0xc0ec, 0x681e,
-	0x1078, 0x202c, 0x0078, 0x29c5, 0x7cd8, 0x7ddc, 0x7fd0, 0x1078,
-	0x35ff, 0x682b, 0x0000, 0x789b, 0x000e, 0x6f14, 0x1078, 0x4387,
-	0xa08c, 0x00ff, 0x6916, 0x6818, 0xd0fc, 0x0040, 0x3769, 0x7048,
-	0x681a, 0xa68c, 0xdf00, 0x691e, 0x7067, 0x0000, 0x0078, 0x29c5,
-	0x7000, 0xa005, 0x00c0, 0x3776, 0x0078, 0x29c5, 0xa006, 0x1078,
-	0x4586, 0x6920, 0xd1ac, 0x00c0, 0x377f, 0x681b, 0x0014, 0xa68c,
-	0xdf00, 0x691e, 0x682b, 0x0000, 0x6820, 0xa084, 0x00ff, 0x6822,
-	0x7000, 0x0079, 0x378b, 0x29c5, 0x3795, 0x3795, 0x3798, 0x3798,
-	0x3798, 0x3793, 0x3793, 0x1078, 0x296b, 0x6818, 0x0078, 0x33fa,
-	0x6008, 0xc0a4, 0x600a, 0x6817, 0x0000, 0x0078, 0x3d95, 0x2300,
-	0x0079, 0x37a2, 0x37a5, 0x37a7, 0x3817, 0x1078, 0x296b, 0xd6fc,
-	0x00c0, 0x37fe, 0x7000, 0xa00d, 0x0079, 0x37ae, 0x29c5, 0x37b8,
-	0x37b8, 0x37e8, 0x37b8, 0x37fb, 0x37b6, 0x37b6, 0x1078, 0x296b,
-	0xa684, 0x0060, 0x0040, 0x37e8, 0xa086, 0x0060, 0x00c0, 0x37e5,
-	0xc6ac, 0xc6f4, 0xc6ed, 0x7e5a, 0x6eb6, 0x681c, 0xc0ac, 0x681e,
-	0xa186, 0x0002, 0x0040, 0x37d7, 0x1078, 0x4586, 0x69ac, 0x68b0,
-	0xa115, 0x0040, 0x37d7, 0x1078, 0x48f5, 0x0078, 0x37d9, 0x1078,
-	0x48bd, 0x781b, 0x0079, 0x71d4, 0xd1b4, 0x00c0, 0x29c1, 0x70a4,
-	0xa086, 0x0001, 0x00c0, 0x2a0b, 0x007c, 0xd6ec, 0x0040, 0x37c2,
-	0x6818, 0xd0fc, 0x0040, 0x37fb, 0xd6f4, 0x00c0, 0x37f5, 0x681b,
-	0x0015, 0x781b, 0x0079, 0x0078, 0x29c1, 0x681b, 0x0007, 0x682f,
-	0x0000, 0x6833, 0x0000, 0x1078, 0x4319, 0x007c, 0xc6fc, 0x7e5a,
-	0x7adc, 0x79d8, 0x78d0, 0x801b, 0x00c8, 0x3807, 0x8000, 0xa084,
-	0x003f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2,
-	0x6b94, 0x2200, 0xa303, 0x68ae, 0x781b, 0x0079, 0x007c, 0x1078,
-	0x296b, 0x2300, 0x0079, 0x381c, 0x3821, 0x3846, 0x38a6, 0x1078,
-	0x296b, 0x7000, 0x0079, 0x3824, 0x382c, 0x382e, 0x3837, 0x382c,
-	0x382c, 0x382c, 0x382c, 0x382c, 0x1078, 0x296b, 0x69ac, 0x68b0,
-	0xa115, 0x0040, 0x3837, 0x1078, 0x48f5, 0x0078, 0x3839, 0x1078,
-	0x48bd, 0x681c, 0xc0b4, 0x681e, 0x70d4, 0xd0b4, 0x00c0, 0x29c1,
-	0x70a4, 0xa086, 0x0001, 0x00c0, 0x2a0b, 0x007c, 0xd6fc, 0x00c0,
-	0x3896, 0x7000, 0xa00d, 0x0079, 0x384d, 0x29c5, 0x385d, 0x3857,
-	0x388d, 0x385d, 0x3893, 0x3855, 0x3855, 0x1078, 0x296b, 0x6894,
-	0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0xa684, 0x0060, 0x0040,
-	0x388d, 0xa086, 0x0060, 0x00c0, 0x388a, 0xa6b4, 0xbfbf, 0xc6ed,
-	0x7e5a, 0x6eb6, 0xa186, 0x0002, 0x0040, 0x3879, 0x1078, 0x4586,
-	0x69ac, 0x68b0, 0xa115, 0x0040, 0x3879, 0x1078, 0x48f5, 0x0078,
-	0x387b, 0x1078, 0x48bd, 0x781b, 0x0079, 0x681c, 0xc0b4, 0x681e,
-	0x71d4, 0xd1b4, 0x00c0, 0x29c1, 0x70a4, 0xa086, 0x0001, 0x00c0,
-	0x2a0b, 0x007c, 0xd6ec, 0x0040, 0x3867, 0x6818, 0xd0fc, 0x0040,
-	0x3893, 0x681b, 0x0007, 0x781b, 0x00f9, 0x007c, 0xc6fc, 0x7e5a,
-	0x7adc, 0x79d8, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200,
-	0xa303, 0x68ae, 0x79d2, 0x781b, 0x0079, 0x007c, 0xd6dc, 0x0040,
-	0x38af, 0x782b, 0x3009, 0x781b, 0x0079, 0x0078, 0x29c1, 0x7884,
-	0xc0ac, 0x7886, 0x78e4, 0xa084, 0x0008, 0x00c0, 0x38c2, 0xa484,
-	0x0200, 0x0040, 0x38bc, 0xc6f5, 0xc6dd, 0x7e5a, 0x781b, 0x0079,
-	0x0078, 0x29c1, 0x6820, 0xc095, 0x6822, 0x1078, 0x4292, 0xc6dd,
-	0x1078, 0x40c8, 0x781b, 0x0078, 0x0078, 0x29c1, 0x2300, 0x0079,
-	0x38d1, 0x38d4, 0x38d6, 0x38d8, 0x1078, 0x296b, 0x0078, 0x40c1,
-	0xd6d4, 0x00c0, 0x3913, 0x79e4, 0xd1ac, 0x0040, 0x38e6, 0x78ec,
-	0xa084, 0x0003, 0x0040, 0x38e6, 0x782b, 0x3009, 0x789b, 0x0060,
-	0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, 0x79e4, 0xd1ac, 0x0040,
-	0x38f6, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x390f, 0x2001, 0x4e04,
-	0x2004, 0xd0e4, 0x00c0, 0x390b, 0x6820, 0xd0c4, 0x0040, 0x390b,
-	0x0c7e, 0x7058, 0x2060, 0x6004, 0xc09d, 0x6006, 0x6008, 0xa084,
-	0x00ff, 0x600a, 0x0c7f, 0x2001, 0x0014, 0x0078, 0x33fa, 0xa184,
-	0x0007, 0x0079, 0x3949, 0x7a90, 0xa294, 0x0007, 0x789b, 0x0060,
-	0x79a8, 0x81ff, 0x0040, 0x3947, 0x789b, 0x0010, 0x7ba8, 0xa384,
-	0x0001, 0x00c0, 0x393a, 0x7ba8, 0x7ba8, 0xa386, 0x0001, 0x00c0,
-	0x392d, 0x2009, 0xfff7, 0x0078, 0x3933, 0xa386, 0x0003, 0x00c0,
-	0x393a, 0x2009, 0xffef, 0x0c7e, 0x7058, 0x2060, 0x6004, 0xa104,
-	0x6006, 0x0c7f, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb,
-	0x785a, 0x782b, 0x3009, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0078,
-	0x430d, 0x3090, 0x309a, 0x3953, 0x3959, 0x3951, 0x3951, 0x430d,
-	0x430d, 0x1078, 0x296b, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0078,
-	0x4313, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0078, 0x430d, 0x79e4,
-	0xa184, 0x0030, 0x0040, 0x3969, 0x78ec, 0xa084, 0x0003, 0x00c0,
-	0x399d, 0x7000, 0xa086, 0x0004, 0x00c0, 0x3983, 0x7064, 0xa086,
-	0x0002, 0x00c0, 0x3979, 0x2011, 0x0002, 0x2019, 0x0000, 0x0078,
-	0x2f1c, 0x7064, 0xa086, 0x0006, 0x0040, 0x3973, 0x7064, 0xa086,
-	0x0004, 0x0040, 0x3973, 0x7000, 0xa086, 0x0000, 0x0040, 0x29c1,
-	0x6920, 0xa184, 0x0420, 0x0040, 0x3992, 0xc1d4, 0x6922, 0x6818,
-	0x0078, 0x33fa, 0x6818, 0xa08e, 0x0002, 0x0040, 0x399b, 0xc0fd,
-	0x681a, 0x2001, 0x0014, 0x0078, 0x33fa, 0xa184, 0x0007, 0x0079,
-	0x39a1, 0x430d, 0x430d, 0x39a9, 0x430d, 0x4355, 0x4355, 0x430d,
-	0x430d, 0xd6bc, 0x0040, 0x39eb, 0x7184, 0x81ff, 0x0040, 0x39eb,
-	0xa182, 0x000d, 0x00d0, 0x39b8, 0x7087, 0x0000, 0x0078, 0x39bd,
-	0xa182, 0x000c, 0x7086, 0x2009, 0x000c, 0x789b, 0x0061, 0x79aa,
-	0x157e, 0x137e, 0x147e, 0x7088, 0x8114, 0xa210, 0x728a, 0xa080,
-	0x000b, 0xad00, 0x2098, 0xb284, 0x0300, 0x0040, 0x39df, 0x007e,
-	0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x39db, 0x20a1,
-	0x012b, 0x0078, 0x39e1, 0x20a1, 0x022b, 0x0078, 0x39e1, 0x20a1,
-	0x012b, 0x789b, 0x0000, 0x8108, 0x81ac, 0x53a6, 0x147f, 0x137f,
-	0x157f, 0x0078, 0x4313, 0xd6d4, 0x00c0, 0x3a3f, 0x6820, 0xd084,
-	0x0040, 0x4313, 0xa68c, 0x0060, 0xa684, 0x0060, 0x0040, 0x39fd,
-	0xa086, 0x0060, 0x00c0, 0x39fd, 0xc1f5, 0xc194, 0x795a, 0x69b6,
-	0x789b, 0x0060, 0x78ab, 0x0000, 0x789b, 0x0061, 0x6818, 0xc0fd,
-	0x681a, 0x78aa, 0x8008, 0x810c, 0x0040, 0x3e06, 0xa18c, 0x00f8,
-	0x00c0, 0x3e06, 0x157e, 0x137e, 0x147e, 0x017e, 0x3208, 0xa18c,
-	0x0300, 0x0040, 0x3a2b, 0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec,
-	0x007f, 0x0040, 0x3a27, 0x20a1, 0x012b, 0x0078, 0x3a2d, 0x20a1,
-	0x022b, 0x0078, 0x3a2d, 0x20a1, 0x012b, 0x017f, 0x789b, 0x0000,
-	0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f,
-	0x157f, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x0078, 0x4313, 0x6818,
-	0xd0fc, 0x0040, 0x3a45, 0x681b, 0x0008, 0x6820, 0xc0ad, 0x6822,
-	0x1078, 0x40d0, 0x781b, 0x00ea, 0x007c, 0x2300, 0x0079, 0x3a50,
-	0x3a55, 0x3b2d, 0x3a53, 0x1078, 0x296b, 0x7cd8, 0x7ddc, 0x7fd0,
-	0x82ff, 0x00c0, 0x3a7e, 0x7200, 0xa286, 0x0003, 0x0040, 0x33c7,
-	0x71d4, 0xd1bc, 0x00c0, 0x3a81, 0xd1b4, 0x0040, 0x3a81, 0x0d7e,
-	0x783b, 0x8800, 0x781b, 0x004c, 0x70bc, 0xa06d, 0x68b4, 0xc0a5,
-	0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0xc1b4,
-	0x71d6, 0x7003, 0x0030, 0x0d7f, 0x0078, 0x3a85, 0x7200, 0x0078,
-	0x3a85, 0x783b, 0x1800, 0x781b, 0x004a, 0xa284, 0x000f, 0x0079,
-	0x3a89, 0x3b18, 0x3ac7, 0x3a93, 0x33f6, 0x3a91, 0x3b18, 0x3a91,
-	0x3a91, 0x1078, 0x296b, 0x681c, 0xd0ec, 0x0040, 0x3a9a, 0x6008,
-	0xc08d, 0x600a, 0x6920, 0xc185, 0x6922, 0x6800, 0x6006, 0xa005,
-	0x00c0, 0x3aa3, 0x6002, 0x6008, 0xc0d4, 0x600a, 0x681c, 0xa084,
-	0x000e, 0x00c0, 0x3ab7, 0xb284, 0x0300, 0x0040, 0x3ab3, 0x2009,
-	0x94c0, 0x0078, 0x3abc, 0x2009, 0x95d0, 0x0078, 0x3abc, 0x7030,
-	0x68ba, 0x7140, 0x70cc, 0xa108, 0x2104, 0x6802, 0x2d0a, 0x715e,
-	0xd6dc, 0x00c0, 0x3ac7, 0xc6fc, 0x6eb6, 0x0078, 0x3b18, 0x6eb6,
-	0xa684, 0x0060, 0x00c0, 0x3ad1, 0xa684, 0x7fff, 0x68b6, 0x0078,
-	0x3b18, 0xd6dc, 0x00c0, 0x3adf, 0xa684, 0x7fff, 0x68b6, 0x6894,
-	0x68a6, 0x6898, 0x68aa, 0x1078, 0x4586, 0x0078, 0x3b18, 0xd6ac,
-	0x0040, 0x3aeb, 0xa006, 0x1078, 0x4586, 0x2408, 0x2510, 0x69aa,
-	0x6aa6, 0x0078, 0x3afb, 0x2408, 0x2510, 0x2700, 0x801b, 0x00c8,
-	0x3af2, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x69aa,
-	0x6aa6, 0x1078, 0x4586, 0xd6fc, 0x0040, 0x3b18, 0xa684, 0x7fff,
-	0x68b6, 0x2510, 0x2408, 0xd6ac, 0x00c0, 0x3b10, 0x2700, 0x801b,
-	0x00c8, 0x3b0b, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000,
+	0x00ff, 0xa205, 0x6822, 0x1078, 0x2073, 0x2021, 0x4f02, 0x241c,
+	0x8319, 0x2322, 0x6010, 0x8001, 0x6012, 0x00c0, 0x3064, 0x2021,
+	0x4f04, 0x2404, 0xc0a5, 0x2022, 0x6008, 0xa084, 0xf9ef, 0x600a,
+	0x1078, 0x2b22, 0x1078, 0x3e36, 0x007c, 0xa085, 0x0001, 0x0078,
+	0x306c, 0x2300, 0x0079, 0x3074, 0x3079, 0x3077, 0x30f9, 0x1078,
+	0x29b2, 0x78e4, 0xa005, 0x00d0, 0x30af, 0x3208, 0x007e, 0x2001,
+	0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x308a, 0xa18c, 0x0300,
+	0x0078, 0x308c, 0xa18c, 0x0400, 0x0040, 0x3092, 0x0018, 0x2a08,
+	0x0078, 0x3094, 0x0028, 0x2a08, 0x2008, 0xa084, 0x0030, 0x00c0,
+	0x309b, 0x0078, 0x37b9, 0x78ec, 0xa084, 0x0003, 0x0040, 0x3099,
+	0x2100, 0xa084, 0x0007, 0x0079, 0x30a5, 0x30d9, 0x30e3, 0x30ce,
+	0x30ad, 0x43a5, 0x43a5, 0x30ad, 0x30ee, 0x1078, 0x29b2, 0x7000,
+	0xa086, 0x0004, 0x00c0, 0x30c9, 0x7064, 0xa086, 0x0002, 0x00c0,
+	0x30bf, 0x2011, 0x0002, 0x2019, 0x0000, 0x0078, 0x2f65, 0x7064,
+	0xa086, 0x0006, 0x0040, 0x30b9, 0x7064, 0xa086, 0x0004, 0x0040,
+	0x30b9, 0x79e4, 0x2001, 0x0003, 0x0078, 0x3443, 0x6818, 0xd0fc,
+	0x0040, 0x30d4, 0x681b, 0x001d, 0x1078, 0x4118, 0x781b, 0x0064,
+	0x007c, 0x6818, 0xd0fc, 0x0040, 0x30df, 0x681b, 0x001d, 0x1078,
+	0x4118, 0x0078, 0x4381, 0x6818, 0xd0fc, 0x0040, 0x30e9, 0x681b,
+	0x001d, 0x1078, 0x4118, 0x781b, 0x00f8, 0x007c, 0x6818, 0xd0fc,
+	0x0040, 0x30f4, 0x681b, 0x001d, 0x1078, 0x4118, 0x781b, 0x00c8,
+	0x007c, 0xa584, 0x000f, 0x00c0, 0x3118, 0x1078, 0x29a5, 0x7000,
+	0x0079, 0x3102, 0x2a0c, 0x310a, 0x310c, 0x3dc7, 0x3dc7, 0x3dc7,
+	0x310a, 0x310a, 0x1078, 0x29b2, 0x1078, 0x3e36, 0x6008, 0xa084,
+	0xfbef, 0x600a, 0x1078, 0x3db8, 0x0040, 0x3dc7, 0x0078, 0x2a0c,
+	0x78e4, 0xa005, 0x00d0, 0x30af, 0x3208, 0x007e, 0x2001, 0x4f04,
+	0x2004, 0xd0ec, 0x007f, 0x0040, 0x3129, 0xa18c, 0x0300, 0x0078,
+	0x312b, 0xa18c, 0x0400, 0x0040, 0x3131, 0x0018, 0x30af, 0x0078,
+	0x3133, 0x0028, 0x30af, 0x2008, 0xa084, 0x0030, 0x00c0, 0x313b,
+	0x781b, 0x005b, 0x007c, 0x78ec, 0xa084, 0x0003, 0x0040, 0x3138,
+	0x2100, 0xa184, 0x0007, 0x0079, 0x3145, 0x3154, 0x3158, 0x314f,
+	0x314d, 0x43a5, 0x43a5, 0x314d, 0x439f, 0x1078, 0x29b2, 0x1078,
+	0x4120, 0x781b, 0x0064, 0x007c, 0x1078, 0x4120, 0x0078, 0x4381,
+	0x1078, 0x4120, 0x781b, 0x00f8, 0x007c, 0x1078, 0x4120, 0x781b,
+	0x00c8, 0x007c, 0x2300, 0x0079, 0x3165, 0x316a, 0x3168, 0x316c,
+	0x1078, 0x29b2, 0x0078, 0x39a8, 0x681b, 0x0016, 0x78a3, 0x0000,
+	0x79e4, 0xa184, 0x0030, 0x0040, 0x39a8, 0x78ec, 0xa084, 0x0003,
+	0x0040, 0x39a8, 0xa184, 0x0100, 0x0040, 0x3170, 0xa184, 0x0007,
+	0x0079, 0x3182, 0x318a, 0x3158, 0x30ce, 0x435d, 0x43a5, 0x43a5,
+	0x435d, 0x439f, 0x1078, 0x4369, 0x007c, 0xa282, 0x0005, 0x0050,
+	0x3193, 0x1078, 0x29b2, 0x2300, 0x0079, 0x3196, 0x3199, 0x33c9,
+	0x33d4, 0x2200, 0x0079, 0x319c, 0x31b6, 0x31a3, 0x31b6, 0x31a1,
+	0x33ac, 0x1078, 0x29b2, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff,
+	0xa082, 0x0020, 0x0048, 0x4107, 0xa08a, 0x0004, 0x00c8, 0x4107,
+	0x0079, 0x31b2, 0x4107, 0x4107, 0x4107, 0x40b1, 0x789b, 0x0018,
+	0x79a8, 0xa184, 0x0080, 0x0040, 0x31c7, 0x0078, 0x4107, 0x7000,
+	0xa005, 0x00c0, 0x31bd, 0x2011, 0x0004, 0x0078, 0x3b93, 0xa184,
+	0x00ff, 0xa08a, 0x0010, 0x00c8, 0x4107, 0x0079, 0x31cf, 0x31e1,
+	0x31df, 0x31f6, 0x31fa, 0x32cd, 0x4107, 0x4107, 0x32cf, 0x4107,
+	0x4107, 0x33a8, 0x33a8, 0x4107, 0x4107, 0x4107, 0x33aa, 0x1078,
+	0x29b2, 0xd6e4, 0x0040, 0x31ec, 0x2001, 0x0300, 0x8000, 0x8000,
+	0x783a, 0x781b, 0x00c3, 0x007c, 0x6818, 0xd0fc, 0x0040, 0x31f4,
+	0x681b, 0x001d, 0x0078, 0x31e4, 0x0078, 0x435d, 0x681b, 0x001d,
+	0x0078, 0x4111, 0x6920, 0x6922, 0xa684, 0x1800, 0x00c0, 0x325f,
+	0x6820, 0xd084, 0x00c0, 0x3265, 0x6818, 0xa086, 0x0008, 0x00c0,
+	0x320b, 0x681b, 0x0000, 0xd6d4, 0x0040, 0x32ca, 0xd6bc, 0x0040,
+	0x324b, 0x7087, 0x0000, 0x6818, 0xa084, 0x003f, 0xa08a, 0x000d,
+	0x0050, 0x324b, 0xa08a, 0x000c, 0x7186, 0x2001, 0x000c, 0x800c,
+	0x718a, 0x789b, 0x0061, 0x78aa, 0x157e, 0x137e, 0x147e, 0x017e,
+	0x3208, 0xa18c, 0x0300, 0x0040, 0x323d, 0x007e, 0x2001, 0x4f04,
+	0x2004, 0xd0ec, 0x007f, 0x0040, 0x3239, 0x20a1, 0x012b, 0x0078,
+	0x323f, 0x20a1, 0x022b, 0x0078, 0x323f, 0x20a1, 0x012b, 0x017f,
+	0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6,
+	0x147f, 0x137f, 0x157f, 0x6038, 0xa005, 0x00c0, 0x325a, 0x681c,
+	0xa084, 0x000e, 0x0040, 0x4111, 0x1078, 0x4127, 0x782b, 0x3008,
+	0x0078, 0x325c, 0x8001, 0x603a, 0x781b, 0x0067, 0x007c, 0xd6e4,
+	0x0040, 0x3265, 0x781b, 0x0079, 0x007c, 0xa684, 0x0060, 0x0040,
+	0x32c7, 0xd6dc, 0x0040, 0x32c7, 0xd6fc, 0x00c0, 0x3271, 0x0078,
+	0x3288, 0xc6fc, 0x7e5a, 0x6eb6, 0x7adc, 0x79d8, 0x78d0, 0x801b,
+	0x00c8, 0x327b, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000,
 	0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae,
-	0x7000, 0xa086, 0x0030, 0x00c0, 0x29c5, 0x7003, 0x0002, 0x70bc,
-	0xa06d, 0x68bc, 0x7042, 0x70b8, 0xa065, 0x68c0, 0x705a, 0x2d00,
-	0x704e, 0xad80, 0x0009, 0x7046, 0x007c, 0xa586, 0x8800, 0x00c0,
-	0x3b3a, 0x7003, 0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084,
-	0xfbef, 0x600a, 0x0078, 0x40c1, 0x7047, 0x0000, 0xa282, 0x0006,
-	0x0050, 0x3b44, 0x1078, 0x296b, 0x2300, 0x0079, 0x3b47, 0x3b4a,
-	0x3b5c, 0x3b68, 0x2200, 0x0079, 0x3b4d, 0x3b53, 0x40c1, 0x3b55,
-	0x3b53, 0x3ba2, 0x3bf7, 0x1078, 0x296b, 0x7a80, 0xa294, 0x0f00,
-	0x1078, 0x3c81, 0x0078, 0x40b7, 0x1078, 0x3b79, 0x0079, 0x3b60,
-	0x40c1, 0x3b66, 0x3b66, 0x3ba2, 0x3b66, 0x40c1, 0x1078, 0x296b,
-	0x1078, 0x3b79, 0x0079, 0x3b6c, 0x3b74, 0x3b72, 0x3b72, 0x3b74,
-	0x3b72, 0x3b74, 0x1078, 0x296b, 0x1078, 0x40db, 0x781b, 0x0078,
-	0x007c, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3b8a, 0x1078, 0x3ded,
-	0x0078, 0x3b84, 0x1078, 0x4586, 0x6008, 0xa084, 0xfbef, 0x600a,
-	0x0078, 0x3b8f, 0x7000, 0xa086, 0x0003, 0x0040, 0x3b82, 0x7003,
-	0x0005, 0xb284, 0x0300, 0x0040, 0x3b99, 0x2001, 0x95e0, 0x0078,
-	0x3b9b, 0x2001, 0x9612, 0x2068, 0x704e, 0xad80, 0x0009, 0x7046,
-	0x2200, 0x007c, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3bb4, 0x70d4,
-	0xc0b5, 0x70d6, 0x2c00, 0x70ba, 0x2d00, 0x70be, 0x0078, 0x3bb9,
-	0x1078, 0x4586, 0x0078, 0x3bb9, 0x7000, 0xa086, 0x0003, 0x0040,
-	0x3bb0, 0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018,
-	0x7ca8, 0xa484, 0x001f, 0xa215, 0x2069, 0x94c0, 0xb284, 0x0300,
-	0x00c0, 0x3bcd, 0xc2fd, 0x2069, 0x95d0, 0x2d04, 0x2d08, 0x715e,
-	0xa06d, 0x0040, 0x3bda, 0x6814, 0xa206, 0x0040, 0x3bdc, 0x6800,
-	0x0078, 0x3bce, 0x1078, 0x3c81, 0x6eb4, 0x7e5a, 0x6920, 0xa184,
-	0x0c00, 0x0040, 0x3cab, 0x7064, 0xa086, 0x0006, 0x00c0, 0x3bee,
-	0x7074, 0xa206, 0x00c0, 0x3bee, 0x7066, 0x707e, 0x681b, 0x0005,
-	0xc1ad, 0xc1d4, 0x6922, 0x1078, 0x40d0, 0x0078, 0x3cab, 0x7200,
-	0xa286, 0x0002, 0x00c0, 0x3c09, 0x70d4, 0xc0b5, 0x70d6, 0x2c00,
-	0x70ba, 0x2d00, 0x70be, 0x0078, 0x3c0d, 0x1078, 0x4586, 0x0078,
-	0x3c0d, 0xa286, 0x0003, 0x0040, 0x3c05, 0x7003, 0x0001, 0x7a80,
-	0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215,
-	0xb284, 0x0300, 0x00c0, 0x3c1d, 0xc2fd, 0x79a8, 0x79a8, 0xa18c,
-	0x00ff, 0x2118, 0x70cc, 0xa168, 0x2d04, 0x2d08, 0x715e, 0xa06d,
-	0x0040, 0x3c31, 0x6814, 0xa206, 0x0040, 0x3c5a, 0x6800, 0x0078,
-	0x3c25, 0x7003, 0x0005, 0xb284, 0x0300, 0x0040, 0x3c3b, 0x2001,
-	0x95e0, 0x0078, 0x3c3d, 0x2001, 0x9612, 0x2068, 0x704e, 0x157e,
-	0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x00f0, 0x3c42, 0x157f,
-	0xb284, 0x0300, 0x0040, 0x3c4f, 0xc2fc, 0x0078, 0x3c50, 0xc2fd,
-	0x6a16, 0xad80, 0x0009, 0x7046, 0x68b7, 0x0700, 0x6823, 0x0800,
-	0x6827, 0x0003, 0x6eb4, 0x6920, 0xa184, 0x0c00, 0x0040, 0x3cab,
-	0xd0dc, 0x0040, 0x3c76, 0x7064, 0xa086, 0x0004, 0x00c0, 0x3c72,
-	0x7074, 0xa206, 0x00c0, 0x3c72, 0x7078, 0xa306, 0x00c0, 0x3c72,
-	0x7066, 0x707e, 0x1078, 0x40d7, 0x0078, 0x3cab, 0x681b, 0x0005,
-	0xc1ad, 0xc1d4, 0x6922, 0x1078, 0x40d0, 0x707f, 0x0000, 0x0078,
-	0x3cab, 0x7003, 0x0005, 0xb284, 0x0300, 0x0040, 0x3c8b, 0x2001,
-	0x95e0, 0x0078, 0x3c8d, 0x2001, 0x9612, 0x2068, 0x704e, 0x157e,
-	0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x00f0, 0x3c92, 0x157f,
-	0xb284, 0x0300, 0x0040, 0x3c9f, 0xc2fc, 0x0078, 0x3ca0, 0xc2fd,
-	0x6a16, 0xad80, 0x0009, 0x7046, 0x68b7, 0x0700, 0x6823, 0x0800,
-	0x6827, 0x0003, 0x007c, 0xc6ec, 0xa6ac, 0x0060, 0x0040, 0x3cfd,
-	0x6b98, 0x6c94, 0x69ac, 0x68b0, 0xa105, 0x00c0, 0x3cd8, 0x7bd2,
-	0x7bda, 0x7cd6, 0x7cde, 0xa586, 0x0060, 0x0040, 0x3d02, 0xd6f4,
-	0x00c0, 0x3cc3, 0xc6ed, 0xa6b4, 0xb7ff, 0x7e5a, 0x2009, 0x0079,
-	0xd69c, 0x0040, 0x3cd0, 0x2009, 0x0078, 0x2019, 0x0000, 0x2320,
-	0x791a, 0xd6ec, 0x0040, 0x3d0d, 0x1078, 0x48bd, 0x0078, 0x3d0d,
-	0x68b0, 0xa31a, 0x2100, 0xa423, 0x2400, 0xa305, 0x0040, 0x3d04,
-	0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0x68b0, 0xd6f4, 0x00c0, 0x3ce9,
-	0xc6ed, 0xc6f4, 0x7e5a, 0x2011, 0x0079, 0xd69c, 0x0040, 0x3cf5,
-	0x2011, 0x0078, 0x2019, 0x0000, 0x2320, 0x7a1a, 0xd6ec, 0x0040,
-	0x3d0d, 0x1078, 0x48f5, 0x0078, 0x3d0d, 0x2019, 0x0000, 0x2320,
-	0x0078, 0x3d04, 0xa6b4, 0xb7ff, 0x7e5a, 0x2009, 0x0079, 0xd69c,
-	0x0040, 0x3d0c, 0x2009, 0x0078, 0x791a, 0x68c0, 0x705a, 0x2d00,
-	0x704e, 0x68c4, 0x2060, 0x71d4, 0x2001, 0x4e01, 0x2004, 0xd0c4,
-	0x00c0, 0x3d62, 0x70d8, 0xa02d, 0x0040, 0x3d3b, 0xd1bc, 0x0040,
-	0x3d55, 0x7a80, 0xa294, 0x0f00, 0x70dc, 0xa206, 0x0040, 0x3d2c,
-	0x78e0, 0xa504, 0x00c0, 0x3d62, 0x70da, 0xc1bc, 0x71d6, 0x0078,
-	0x3d62, 0x2031, 0x0001, 0x852c, 0x0048, 0x3d3a, 0x8633, 0x8210,
-	0x0078, 0x3d33, 0x007c, 0x7de0, 0xa594, 0xff00, 0x0040, 0x3d48,
-	0x2011, 0x0008, 0x852f, 0x1078, 0x3d31, 0x8637, 0x0078, 0x3d4a,
-	0x1078, 0x3d31, 0x8217, 0x7880, 0xa084, 0x0f00, 0xa206, 0x0040,
-	0x3d62, 0x72de, 0x76da, 0x0078, 0x3d62, 0x7a80, 0xa294, 0x0f00,
-	0x70dc, 0xa236, 0x0040, 0x3d52, 0x78e0, 0xa534, 0x0040, 0x3d52,
-	0xc1bd, 0x71d6, 0xd1b4, 0x00c0, 0x29c1, 0x2300, 0xa405, 0x0040,
-	0x29c1, 0x70a4, 0xa086, 0x0001, 0x00c0, 0x2a0b, 0x007c, 0x6020,
-	0xa005, 0x0040, 0x3d7d, 0x8001, 0x6022, 0x6008, 0xa085, 0x0008,
-	0x600a, 0x700f, 0x0100, 0x702c, 0x6026, 0x007c, 0xa006, 0x1078,
-	0x4586, 0x7000, 0xa086, 0x0002, 0x0040, 0x3d8b, 0x7064, 0xa086,
-	0x0005, 0x00c0, 0x3d95, 0x682b, 0x0000, 0x6817, 0x0000, 0x681b,
-	0x0001, 0x6823, 0x0040, 0x681f, 0x0100, 0x7000, 0xa084, 0x000f,
-	0x0079, 0x3d9a, 0x29c5, 0x3daa, 0x3da4, 0x3dcc, 0x3db4, 0x29c5,
-	0x3da2, 0x3da2, 0x1078, 0x296b, 0x1078, 0x3dd7, 0x1078, 0x3dd0,
-	0x0078, 0x3db0, 0x1078, 0x3dd7, 0x705c, 0x2060, 0x6800, 0x6002,
-	0x1078, 0x202c, 0x0078, 0x29c5, 0x7064, 0x7067, 0x0000, 0x7083,
-	0x0000, 0x0079, 0x3dbb, 0x3dc8, 0x3dc8, 0x3dc3, 0x3dc3, 0x3dc3,
-	0x3dc8, 0x3dc3, 0x3dc8, 0x77d4, 0xc7dd, 0x77d6, 0x0079, 0x2f35,
-	0x7067, 0x0000, 0x0078, 0x29c5, 0x681b, 0x0000, 0x0078, 0x36c8,
-	0x6800, 0xa005, 0x00c0, 0x3dd5, 0x6002, 0x6006, 0x007c, 0x6410,
-	0x84ff, 0x0040, 0x3de9, 0x2009, 0x4e02, 0x2104, 0x8001, 0x200a,
-	0x8421, 0x6412, 0x00c0, 0x3de9, 0x2021, 0x4e04, 0x2404, 0xc0a5,
-	0x2022, 0x6008, 0xc0a4, 0x600a, 0x007c, 0x6018, 0xa005, 0x0040,
-	0x3df3, 0x8001, 0x601a, 0x007c, 0x1078, 0x4383, 0x681b, 0x0018,
-	0x0078, 0x3e34, 0x1078, 0x4383, 0x681b, 0x0019, 0x0078, 0x3e34,
-	0x1078, 0x4383, 0x681b, 0x001a, 0x0078, 0x3e34, 0x1078, 0x4383,
-	0x681b, 0x0003, 0x0078, 0x3e34, 0x7774, 0x1078, 0x41fe, 0x7178,
-	0xa18c, 0x00ff, 0x3210, 0xa294, 0x0300, 0x0040, 0x3e1b, 0xa1e8,
-	0x93c0, 0x0078, 0x3e1d, 0xa1e8, 0x94d0, 0x2d04, 0x2d08, 0x2068,
-	0xa005, 0x00c0, 0x3e26, 0x707e, 0x0078, 0x29c5, 0x6814, 0x7274,
-	0xa206, 0x0040, 0x3e2e, 0x6800, 0x0078, 0x3e1e, 0x6800, 0x200a,
-	0x681b, 0x0005, 0x707f, 0x0000, 0x1078, 0x3dd7, 0x6820, 0xd084,
-	0x00c0, 0x3e3c, 0x1078, 0x3dd0, 0x1078, 0x3ded, 0x681f, 0x0000,
-	0x6823, 0x0020, 0x1078, 0x202c, 0x0078, 0x29c5, 0xa282, 0x0003,
-	0x00c0, 0x40b7, 0x7da8, 0xa5ac, 0x00ff, 0x7e5a, 0x7ea8, 0xa6b4,
-	0x00ff, 0x6920, 0xc1bd, 0x6922, 0xd1c4, 0x0040, 0x3ea1, 0xc1c4,
-	0x6922, 0xa6b4, 0x00ff, 0x0040, 0x3e8e, 0xa682, 0x000c, 0x0048,
-	0x3e65, 0x0040, 0x3e65, 0x2031, 0x000c, 0x2500, 0xa086, 0x000a,
-	0x0040, 0x3e6c, 0x852b, 0x852b, 0x1078, 0x4190, 0x0040, 0x3e74,
-	0x1078, 0x3f6f, 0x0078, 0x3e97, 0x1078, 0x414b, 0x0c7e, 0x2960,
-	0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, 0x3fa5, 0x0c7f, 0x6920,
-	0xc1c5, 0x6922, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x00c0, 0x3e8b,
-	0x781b, 0x0064, 0x007c, 0x781b, 0x0078, 0x007c, 0x0c7e, 0x2960,
-	0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, 0x3fa5, 0x0c7f, 0x7e58,
-	0xd6d4, 0x00c0, 0x3e9e, 0x781b, 0x0067, 0x007c, 0x781b, 0x0079,
-	0x007c, 0x0c7e, 0x7058, 0x2060, 0x6100, 0xd1e4, 0x0040, 0x3eea,
-	0x6208, 0x8217, 0xa294, 0x00ff, 0xa282, 0x000c, 0x0048, 0x3eb4,
-	0x0040, 0x3eb4, 0x2011, 0x000c, 0x2600, 0xa202, 0x00c8, 0x3eb9,
-	0x2230, 0x6208, 0xa294, 0x00ff, 0x2001, 0x4e05, 0x2004, 0xd0e4,
-	0x00c0, 0x3ece, 0x78ec, 0xd0e4, 0x0040, 0x3ece, 0xa282, 0x000a,
-	0x00c8, 0x3ed4, 0x2011, 0x000a, 0x0078, 0x3ed4, 0xa282, 0x000c,
-	0x00c8, 0x3ed4, 0x2011, 0x000c, 0x2200, 0xa502, 0x00c8, 0x3ed9,
-	0x2228, 0x1078, 0x414f, 0x2500, 0xa086, 0x000a, 0x0040, 0x3ee2,
-	0x852b, 0x852b, 0x1078, 0x4190, 0x0040, 0x3eea, 0x1078, 0x3f6f,
-	0x0078, 0x3eee, 0x1078, 0x414b, 0x1078, 0x3fa5, 0x7858, 0xc095,
-	0x785a, 0x0c7f, 0x781b, 0x0078, 0x007c, 0x0c7e, 0x2960, 0x6000,
-	0xd0e4, 0x00c0, 0x3f0b, 0xa084, 0x0040, 0x00c0, 0x3f05, 0x6104,
-	0xa18c, 0xfff5, 0x6106, 0x0c7f, 0x007c, 0x2011, 0x0032, 0x2019,
-	0x0000, 0x0078, 0x3f36, 0x68a0, 0xd0cc, 0x00c0, 0x3f05, 0x6208,
-	0xa294, 0x00ff, 0x2001, 0x4e05, 0x2004, 0xd0e4, 0x00c0, 0x3f24,
-	0x78ec, 0xd0e4, 0x0040, 0x3f24, 0xa282, 0x000b, 0x00c8, 0x3f24,
-	0x2011, 0x000a, 0x0078, 0x3f2a, 0xa282, 0x000c, 0x00c8, 0x3f2a,
-	0x2011, 0x000c, 0x6308, 0x831f, 0xa39c, 0x00ff, 0xa382, 0x000c,
-	0x0048, 0x3f36, 0x0040, 0x3f36, 0x2019, 0x000c, 0x78ab, 0x0001,
-	0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005,
-	0x6820, 0xc0c5, 0x6822, 0x70d4, 0xd0b4, 0x0040, 0x3f52, 0xc0b4,
-	0x70d6, 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018,
-	0x8001, 0x601a, 0x0c7f, 0x007c, 0x0c7e, 0x2960, 0x6104, 0xa18c,
-	0xfff5, 0x6106, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078, 0x3f60,
-	0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa,
-	0xa8c0, 0x0005, 0x6820, 0xc0c5, 0x6822, 0x0c7f, 0x007c, 0x0c7e,
-	0x7158, 0x2160, 0x2018, 0xa08c, 0x0020, 0x0040, 0x3f78, 0xc0ac,
-	0x2008, 0xa084, 0xfff0, 0xa635, 0x7e86, 0x6018, 0x789a, 0x7eae,
-	0x6612, 0x78a4, 0xa084, 0xfff0, 0xa18c, 0x000f, 0xa105, 0xc0f4,
-	0xa39c, 0x0020, 0x0040, 0x3f8e, 0xa085, 0x4000, 0xc0fc, 0xd0b4,
-	0x00c0, 0x3f93, 0xc0fd, 0x78a6, 0x6016, 0x788a, 0xa6b4, 0x000f,
-	0x8637, 0x8204, 0x8004, 0xa084, 0x00ff, 0xa605, 0x600e, 0x6004,
-	0xa084, 0xfff5, 0x6006, 0x0c7f, 0x007c, 0x0c7e, 0x7058, 0x2060,
-	0x6018, 0x789a, 0x78a4, 0xa084, 0xfff0, 0x78a6, 0x6012, 0x7884,
-	0xa084, 0xfff0, 0x7886, 0x600c, 0xa084, 0x00ff, 0x600e, 0x0c7f,
-	0x007c, 0xa282, 0x0002, 0x00c0, 0x40b7, 0x7aa8, 0x6920, 0xc1bd,
-	0x6922, 0xd1cc, 0x0040, 0x3ff4, 0xc1cc, 0x6922, 0xa294, 0x00ff,
-	0xa282, 0x0002, 0x00c8, 0x40b7, 0x1078, 0x4044, 0x1078, 0x3fa5,
-	0xa980, 0x0001, 0x200c, 0x1078, 0x41fa, 0x1078, 0x3ef5, 0x88ff,
-	0x0040, 0x3fea, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695,
-	0x7e5a, 0xd6d4, 0x00c0, 0x3fe7, 0x781b, 0x0064, 0x007c, 0x781b,
-	0x0078, 0x007c, 0x7e58, 0xd6d4, 0x00c0, 0x3ff1, 0x781b, 0x0067,
-	0x007c, 0x781b, 0x0079, 0x007c, 0xa282, 0x0002, 0x00c8, 0x3ffc,
-	0xa284, 0x0001, 0x0040, 0x4005, 0x7158, 0xa188, 0x0000, 0x210c,
-	0xd1ec, 0x00c0, 0x4005, 0x2011, 0x0000, 0x1078, 0x412c, 0x1078,
-	0x4044, 0x1078, 0x3fa5, 0x7858, 0xc095, 0x785a, 0x781b, 0x0078,
-	0x007c, 0x0c7e, 0x027e, 0x2960, 0x6000, 0x2011, 0x0001, 0xd0ec,
-	0x00c0, 0x4025, 0xa084, 0x0080, 0x00c0, 0x4023, 0xc1a4, 0x6106,
-	0xa006, 0x0078, 0x4041, 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab,
+	0xd6f4, 0x0040, 0x328e, 0xc6f4, 0x7e5a, 0x6eb6, 0x7000, 0xa086,
+	0x0003, 0x00c0, 0x329c, 0x007e, 0x1078, 0x45d6, 0x1078, 0x493f,
+	0x007f, 0x781b, 0x0076, 0x007c, 0xa006, 0x1078, 0x4a44, 0x6ab0,
+	0x69ac, 0x6c98, 0x6b94, 0x2200, 0xa105, 0x0040, 0x32ab, 0x2200,
+	0xa422, 0x2100, 0xa31b, 0x6caa, 0x7cd2, 0x7cda, 0x6ba6, 0x7bd6,
+	0x7bde, 0x2300, 0xa405, 0x00c0, 0x32bb, 0xc6f5, 0x7e5a, 0x6eb6,
+	0x781b, 0x0076, 0x007c, 0x781b, 0x0076, 0x2200, 0xa115, 0x00c0,
+	0x32c4, 0x1078, 0x493f, 0x007c, 0x1078, 0x4977, 0x007c, 0x781b,
+	0x0079, 0x007c, 0x781b, 0x0067, 0x007c, 0x1078, 0x29b2, 0x0078,
+	0x331b, 0x6920, 0xd1c4, 0x0040, 0x32e4, 0xc1c4, 0x6922, 0x0c7e,
+	0x7058, 0x2060, 0x6000, 0xc0e4, 0x6002, 0x6004, 0xa084, 0xfff5,
+	0x6006, 0x0c7f, 0x0078, 0x330f, 0xd1cc, 0x0040, 0x330f, 0xc1cc,
+	0x6922, 0x0c7e, 0x7058, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x6004,
+	0xc0a4, 0x6006, 0x2008, 0x2c48, 0x0c7f, 0xd19c, 0x0040, 0x330f,
+	0x1078, 0x424a, 0x1078, 0x3f3e, 0x88ff, 0x0040, 0x330f, 0x789b,
+	0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x00c0,
+	0x330c, 0x781b, 0x0064, 0x007c, 0x781b, 0x0078, 0x007c, 0x7e58,
+	0xd6d4, 0x00c0, 0x3316, 0x781b, 0x0067, 0x007c, 0x781b, 0x0079,
+	0x007c, 0x0078, 0x410c, 0x2019, 0x0000, 0x7990, 0xa18c, 0x0007,
+	0x00c0, 0x3329, 0x6820, 0xa084, 0x0100, 0x0040, 0x3319, 0x2009,
+	0x0008, 0x789b, 0x0010, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001,
+	0x00c0, 0x3345, 0x2300, 0x7ca8, 0xa400, 0x2018, 0xa102, 0x0040,
+	0x333d, 0x0048, 0x333d, 0x0078, 0x333f, 0x0078, 0x32d1, 0x24a8,
+	0x7aa8, 0x00f0, 0x333f, 0x0078, 0x332b, 0xa284, 0x00f0, 0xa086,
+	0x0020, 0x00c0, 0x3399, 0x8318, 0x8318, 0x2300, 0xa102, 0x0040,
+	0x3355, 0x0048, 0x3355, 0x0078, 0x3396, 0xa286, 0x0023, 0x0040,
+	0x3319, 0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58, 0xa684, 0xfff1,
+	0xc0a5, 0x2030, 0x7e5a, 0x6008, 0xc0a5, 0x600a, 0x0c7e, 0x7058,
+	0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xd1a4, 0x0040, 0x3376,
+	0x1078, 0x424a, 0x1078, 0x405e, 0x0078, 0x3384, 0x0c7e, 0x7058,
+	0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xd19c, 0x0040, 0x330f,
+	0x1078, 0x424a, 0x1078, 0x3f3e, 0x88ff, 0x0040, 0x330f, 0x789b,
+	0x0060, 0x2800, 0x78aa, 0xc695, 0x7e5a, 0xd6d4, 0x00c0, 0x3393,
+	0x781b, 0x0064, 0x007c, 0x781b, 0x0078, 0x007c, 0x7aa8, 0x0078,
+	0x332b, 0x8318, 0x2300, 0xa102, 0x0040, 0x33a2, 0x0048, 0x33a2,
+	0x0078, 0x332b, 0xa284, 0x0080, 0x00c0, 0x4111, 0x0078, 0x410c,
+	0x0078, 0x4111, 0x0078, 0x4107, 0x7058, 0xa04d, 0x789b, 0x0018,
+	0x78a8, 0xa084, 0x00ff, 0xa08e, 0x0001, 0x0040, 0x33b9, 0x1078,
+	0x29b2, 0x7aa8, 0xa294, 0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a,
+	0x0004, 0x00c8, 0x4107, 0x0079, 0x33c5, 0x4107, 0x3e8f, 0x4107,
+	0x4006, 0xa282, 0x0000, 0x00c0, 0x33cf, 0x1078, 0x29b2, 0x1078,
+	0x4118, 0x781b, 0x0078, 0x007c, 0xa282, 0x0003, 0x00c0, 0x33da,
+	0x1078, 0x29b2, 0xd4fc, 0x00c0, 0x33fa, 0x7064, 0xa005, 0x0040,
+	0x33e3, 0x1078, 0x29b2, 0x6f14, 0x7776, 0xa7bc, 0x8f00, 0x1078,
+	0x424e, 0x6008, 0xa085, 0x0021, 0x600a, 0x8738, 0xa784, 0x001f,
+	0x00c0, 0x33e7, 0x1078, 0x411c, 0x7067, 0x0002, 0x701f, 0x0009,
+	0x0078, 0x33fc, 0x1078, 0x412b, 0x781b, 0x0078, 0x007c, 0xa282,
+	0x0004, 0x0050, 0x3405, 0x1078, 0x29b2, 0x2300, 0x0079, 0x3408,
+	0x340b, 0x35cb, 0x360e, 0xa286, 0x0003, 0x0040, 0x3443, 0x7200,
+	0x7cd8, 0x7ddc, 0x7fd0, 0x71d4, 0xd1bc, 0x00c0, 0x343b, 0xd1b4,
+	0x0040, 0x343b, 0x7868, 0xa084, 0x00ff, 0x00c0, 0x343b, 0xa282,
+	0x0002, 0x00c8, 0x343b, 0x0d7e, 0x783b, 0x8300, 0x781b, 0x004c,
+	0x70bc, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898,
+	0x78d2, 0x78da, 0xc1b4, 0x71d6, 0x7003, 0x0030, 0x0d7f, 0x2001,
+	0x0000, 0x0078, 0x3447, 0x783b, 0x1300, 0x781b, 0x004a, 0x2001,
+	0x0000, 0x0078, 0x3447, 0x7200, 0x7cd8, 0x7ddc, 0x7fd0, 0x704a,
+	0x68a0, 0xd0ec, 0x0040, 0x344f, 0x6008, 0xc08d, 0x600a, 0xa284,
+	0x000f, 0x0079, 0x3453, 0x35ab, 0x3460, 0x345d, 0x3711, 0x379d,
+	0x2a0c, 0x345b, 0x345b, 0x1078, 0x29b2, 0x6008, 0xc0d4, 0x600a,
+	0xd6e4, 0x0040, 0x3468, 0x7048, 0xa086, 0x0014, 0x00c0, 0x3488,
+	0x1078, 0x45d6, 0x2009, 0x0000, 0x6818, 0xd0fc, 0x0040, 0x3471,
+	0x7048, 0xa086, 0x0014, 0x0040, 0x3482, 0x6818, 0xa086, 0x0008,
+	0x00c0, 0x3563, 0x7858, 0xd09c, 0x0040, 0x3563, 0x6820, 0xd0ac,
+	0x0040, 0x3563, 0x681b, 0x0014, 0x2009, 0x0002, 0x0078, 0x34c7,
+	0x7868, 0xa08c, 0x00ff, 0x0040, 0x34c7, 0xa186, 0x0008, 0x00c0,
+	0x349e, 0x6008, 0xc0a4, 0x600a, 0x1078, 0x3db8, 0x0040, 0x34c7,
+	0x1078, 0x3e36, 0x1078, 0x45d6, 0x0078, 0x34af, 0xa186, 0x0028,
+	0x00c0, 0x34c7, 0x6018, 0xa005, 0x0040, 0x3491, 0x8001, 0x0040,
+	0x3491, 0x8001, 0x0040, 0x3491, 0x601e, 0x0078, 0x3491, 0x6820,
+	0xd084, 0x0040, 0x2a0c, 0xc084, 0x6822, 0x1078, 0x2b13, 0x705c,
+	0x0c7e, 0x2060, 0x6800, 0x6002, 0x0c7f, 0x6004, 0x6802, 0xa005,
+	0x2d00, 0x00c0, 0x34c4, 0x6002, 0x6006, 0x0078, 0x2a0c, 0x017e,
+	0x81ff, 0x00c0, 0x3511, 0x7000, 0xa086, 0x0030, 0x0040, 0x3511,
+	0x71d4, 0xd1bc, 0x00c0, 0x3511, 0xd1b4, 0x00c0, 0x34f8, 0x7060,
+	0xa005, 0x00c0, 0x3511, 0x70a4, 0xa086, 0x0001, 0x0040, 0x3511,
+	0x7003, 0x0000, 0x047e, 0x057e, 0x077e, 0x067e, 0x0c7e, 0x0d7e,
+	0x1078, 0x2a35, 0x0d7f, 0x0c7f, 0x067f, 0x077f, 0x057f, 0x047f,
+	0x71d4, 0xd1b4, 0x00c0, 0x3511, 0x7003, 0x0040, 0x0078, 0x3511,
+	0x1078, 0x43b0, 0x00c0, 0x3511, 0x781b, 0x005b, 0x0d7e, 0x70bc,
+	0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2,
+	0x78da, 0xc1b4, 0x71d6, 0x7003, 0x0030, 0x7808, 0xc08d, 0x780a,
+	0x0d7f, 0x1078, 0x3648, 0x017f, 0x81ff, 0x0040, 0x3563, 0xa684,
+	0xdf00, 0x681e, 0x682b, 0x0000, 0x6f14, 0xa186, 0x0002, 0x00c0,
+	0x3564, 0x6818, 0xa086, 0x0014, 0x00c0, 0x352d, 0x2008, 0xd6e4,
+	0x0040, 0x352d, 0x7868, 0xa08c, 0x00ff, 0x1078, 0x2b01, 0x1078,
+	0x2b22, 0x6820, 0xd0dc, 0x00c0, 0x3564, 0x8717, 0xa294, 0x000f,
+	0x8213, 0x8213, 0x8213, 0xb284, 0x0300, 0x0040, 0x3543, 0xa290,
+	0x53c0, 0x0078, 0x3545, 0xa290, 0x5440, 0xa290, 0x0000, 0x221c,
+	0xd3c4, 0x00c0, 0x354d, 0x0078, 0x3553, 0x8210, 0x2204, 0xa085,
+	0x0018, 0x2012, 0x8211, 0xd3d4, 0x0040, 0x355e, 0x68a0, 0xd0c4,
+	0x00c0, 0x355e, 0x1078, 0x36c2, 0x0078, 0x2a0c, 0x6008, 0xc08d,
+	0x600a, 0x0078, 0x3564, 0x692a, 0x6916, 0x6818, 0xd0fc, 0x0040,
+	0x356b, 0x7048, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x6410, 0x84ff,
+	0x0040, 0x3580, 0x2009, 0x4f02, 0x2104, 0x8001, 0x200a, 0x8421,
+	0x6412, 0x00c0, 0x3580, 0x2021, 0x4f04, 0x2404, 0xc0a5, 0x2022,
+	0x6018, 0xa005, 0x0040, 0x3588, 0x8001, 0x601a, 0x00c0, 0x358b,
+	0x6008, 0xc0a4, 0x600a, 0x6820, 0xd084, 0x00c0, 0x3597, 0x6800,
+	0xa005, 0x00c0, 0x3594, 0x6002, 0x6006, 0x0078, 0x359b, 0x705c,
+	0x2060, 0x6800, 0x6002, 0x2061, 0x4f00, 0x6887, 0x0103, 0x2d08,
+	0x206b, 0x0000, 0x6068, 0xa005, 0x616a, 0x0040, 0x35aa, 0x2d02,
+	0x0078, 0x35ab, 0x616e, 0x7200, 0xa286, 0x0030, 0x0040, 0x35bb,
+	0xa286, 0x0040, 0x00c0, 0x2a0c, 0x7003, 0x0002, 0x704c, 0x2068,
+	0x68c4, 0x2060, 0x007c, 0x7003, 0x0002, 0x70bc, 0xa06d, 0x68bc,
+	0x7042, 0x70b8, 0xa065, 0x68c0, 0x705a, 0x2d00, 0x704e, 0xad80,
+	0x0009, 0x7046, 0x007c, 0xa282, 0x0004, 0x0048, 0x35d1, 0x1078,
+	0x29b2, 0x2200, 0x0079, 0x35d4, 0x35d8, 0x35e9, 0x35f6, 0x35e9,
+	0xa586, 0x1300, 0x0040, 0x35e9, 0xa586, 0x8300, 0x00c0, 0x35cf,
+	0x7003, 0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084, 0xfbef,
+	0x600a, 0x7000, 0xa086, 0x0005, 0x0040, 0x35f3, 0x1078, 0x4118,
+	0x781b, 0x0078, 0x007c, 0x781b, 0x0079, 0x007c, 0x7890, 0x8007,
+	0x8001, 0xa084, 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c,
+	0x00ff, 0xa186, 0x0003, 0x0040, 0x360b, 0xa186, 0x0000, 0x0040,
+	0x360b, 0x0078, 0x4107, 0x781b, 0x0079, 0x007c, 0x6820, 0xc095,
+	0x6822, 0x82ff, 0x00c0, 0x3618, 0x1078, 0x4118, 0x0078, 0x361f,
+	0x8211, 0x0040, 0x361d, 0x1078, 0x29b2, 0x1078, 0x412b, 0x781b,
+	0x0078, 0x007c, 0x1078, 0x43d3, 0x7830, 0xa084, 0x00c0, 0x00c0,
+	0x3645, 0x017e, 0x3208, 0x007e, 0x2001, 0x4f04, 0x2004, 0xd0ec,
+	0x007f, 0x0040, 0x3637, 0xa18c, 0x0300, 0x0078, 0x3639, 0xa18c,
+	0x0400, 0x017f, 0x0040, 0x3640, 0x0018, 0x3645, 0x0078, 0x3642,
+	0x0028, 0x3645, 0x791a, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c,
+	0xa684, 0x0060, 0x00c0, 0x3652, 0x682f, 0x0000, 0x6833, 0x0000,
+	0x0078, 0x36c1, 0xd6dc, 0x00c0, 0x366a, 0x68b4, 0xd0dc, 0x00c0,
+	0x366a, 0x6998, 0x6a94, 0x692e, 0x6a32, 0x7048, 0xa005, 0x00c0,
+	0x3667, 0x2200, 0xa105, 0x0040, 0x45d6, 0x704b, 0x0015, 0x0078,
+	0x45d6, 0x007c, 0xd6ac, 0x0040, 0x3690, 0xd6f4, 0x0040, 0x3676,
+	0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x45d6, 0x68b4, 0xa084,
+	0x4000, 0xa635, 0xd6f4, 0x00c0, 0x3670, 0x7048, 0xa005, 0x00c0,
+	0x3683, 0x704b, 0x0015, 0xd6dc, 0x00c0, 0x368c, 0x68b4, 0xd0dc,
+	0x0040, 0x368c, 0x6ca8, 0x6da4, 0x6c2e, 0x6d32, 0x0078, 0x45d6,
+	0xd6f4, 0x0040, 0x3699, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078,
+	0x45d6, 0x68b4, 0xa084, 0x4800, 0xa635, 0xd6f4, 0x00c0, 0x3693,
+	0x7048, 0xa005, 0x00c0, 0x36a6, 0x704b, 0x0015, 0x2408, 0x2510,
+	0x2700, 0x80fb, 0x00c8, 0x36ad, 0x8000, 0xa084, 0x003f, 0xa108,
+	0xa291, 0x0000, 0x692e, 0x6a32, 0x2100, 0xa205, 0x00c0, 0x36ba,
+	0x0078, 0x45d6, 0x7000, 0xa086, 0x0006, 0x0040, 0x36c1, 0x0078,
+	0x45d6, 0x007c, 0x6946, 0x6008, 0xc0cd, 0xd3cc, 0x0040, 0x36c9,
+	0xc08d, 0x600a, 0x6818, 0x683a, 0x681b, 0x0006, 0x688f, 0x0000,
+	0x6893, 0x0000, 0x6a30, 0x692c, 0x6a3e, 0x6942, 0x682f, 0x0003,
+	0x6833, 0x0000, 0x6837, 0x0020, 0x6897, 0x0000, 0x689b, 0x0020,
+	0x7000, 0x0079, 0x36e3, 0x2a0c, 0x36f5, 0x36ed, 0x36eb, 0x36eb,
+	0x36eb, 0x36eb, 0x36eb, 0x1078, 0x29b2, 0x6820, 0xd084, 0x00c0,
+	0x36f5, 0x1078, 0x3e19, 0x0078, 0x36fb, 0x705c, 0x2c50, 0x2060,
+	0x6800, 0x6002, 0x2a60, 0x3208, 0xa18c, 0x0300, 0x0040, 0x3704,
+	0x2021, 0x4f58, 0x0078, 0x3706, 0x2021, 0x4f98, 0x2404, 0xa005,
+	0x0040, 0x370d, 0x2020, 0x0078, 0x3706, 0x2d22, 0x206b, 0x0000,
+	0x007c, 0x1078, 0x3e20, 0x1078, 0x3e36, 0x6008, 0xc0cc, 0x600a,
+	0x682b, 0x0000, 0x789b, 0x000e, 0x6f14, 0x6938, 0x691a, 0x6944,
+	0x6916, 0x3208, 0xa18c, 0x0300, 0x0040, 0x372a, 0x2009, 0x0000,
+	0x0078, 0x372c, 0x2009, 0x0001, 0x1078, 0x4a81, 0xd6dc, 0x0040,
+	0x3734, 0x691c, 0xc1ed, 0x691e, 0x6818, 0xd0fc, 0x0040, 0x3743,
+	0x7868, 0xa08c, 0x00ff, 0x0040, 0x3741, 0x681b, 0x001e, 0x0078,
+	0x3743, 0x681b, 0x0000, 0xb284, 0x0300, 0x00c0, 0x374b, 0x2021,
+	0x4f98, 0x0078, 0x374d, 0x2021, 0x4f58, 0x6800, 0x2022, 0x6a3c,
+	0x6940, 0x6a32, 0x692e, 0x68c0, 0x2060, 0x6000, 0xd0a4, 0x0040,
+	0x378d, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x0d7e,
+	0x0f7e, 0x157e, 0x147e, 0x2079, 0x4f00, 0x1078, 0x1e46, 0x147f,
+	0x157f, 0x0f7f, 0x70cc, 0x2010, 0x2009, 0x0101, 0x027e, 0x2204,
+	0xa06d, 0x0040, 0x377d, 0x6814, 0xa706, 0x0040, 0x377a, 0x6800,
+	0x0078, 0x3770, 0x6820, 0xc0d5, 0x6822, 0x027f, 0x8210, 0x8109,
+	0x00c0, 0x376e, 0x0d7f, 0x7067, 0x0003, 0x707f, 0x0000, 0x7776,
+	0x7083, 0x000f, 0x71d4, 0xc1dc, 0x71d6, 0x6818, 0xa086, 0x0002,
+	0x00c0, 0x3799, 0x6817, 0x0000, 0x682b, 0x0000, 0x681c, 0xc0ec,
+	0x681e, 0x1078, 0x2073, 0x0078, 0x2a0c, 0x7cd8, 0x7ddc, 0x7fd0,
+	0x1078, 0x3648, 0x682b, 0x0000, 0x789b, 0x000e, 0x6f14, 0x1078,
+	0x43d7, 0xa08c, 0x00ff, 0x6916, 0x6818, 0xd0fc, 0x0040, 0x37b2,
+	0x7048, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x7067, 0x0000, 0x0078,
+	0x2a0c, 0x7000, 0xa005, 0x00c0, 0x37bf, 0x0078, 0x2a0c, 0xa006,
+	0x1078, 0x45d6, 0x6920, 0xd1ac, 0x00c0, 0x37c8, 0x681b, 0x0014,
+	0xa68c, 0xdf00, 0x691e, 0x682b, 0x0000, 0x6820, 0xa084, 0x00ff,
+	0x6822, 0x7000, 0x0079, 0x37d4, 0x2a0c, 0x37de, 0x37de, 0x37e1,
+	0x37e1, 0x37e1, 0x37dc, 0x37dc, 0x1078, 0x29b2, 0x6818, 0x0078,
+	0x3443, 0x6008, 0xc0a4, 0x600a, 0x6817, 0x0000, 0x0078, 0x3dde,
+	0x2300, 0x0079, 0x37eb, 0x37ee, 0x37f0, 0x3860, 0x1078, 0x29b2,
+	0xd6fc, 0x00c0, 0x3847, 0x7000, 0xa00d, 0x0079, 0x37f7, 0x2a0c,
+	0x3801, 0x3801, 0x3831, 0x3801, 0x3844, 0x37ff, 0x37ff, 0x1078,
+	0x29b2, 0xa684, 0x0060, 0x0040, 0x3831, 0xa086, 0x0060, 0x00c0,
+	0x382e, 0xc6ac, 0xc6f4, 0xc6ed, 0x7e5a, 0x6eb6, 0x681c, 0xc0ac,
+	0x681e, 0xa186, 0x0002, 0x0040, 0x3820, 0x1078, 0x45d6, 0x69ac,
+	0x68b0, 0xa115, 0x0040, 0x3820, 0x1078, 0x4977, 0x0078, 0x3822,
+	0x1078, 0x493f, 0x781b, 0x0079, 0x71d4, 0xd1b4, 0x00c0, 0x2a08,
+	0x70a4, 0xa086, 0x0001, 0x00c0, 0x2a52, 0x007c, 0xd6ec, 0x0040,
+	0x380b, 0x6818, 0xd0fc, 0x0040, 0x3844, 0xd6f4, 0x00c0, 0x383e,
+	0x681b, 0x0015, 0x781b, 0x0079, 0x0078, 0x2a08, 0x681b, 0x0007,
+	0x682f, 0x0000, 0x6833, 0x0000, 0x1078, 0x4369, 0x007c, 0xc6fc,
+	0x7e5a, 0x7adc, 0x79d8, 0x78d0, 0x801b, 0x00c8, 0x3850, 0x8000,
+	0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302,
+	0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x781b, 0x0079, 0x007c,
+	0x1078, 0x29b2, 0x2300, 0x0079, 0x3865, 0x386a, 0x388f, 0x38ef,
+	0x1078, 0x29b2, 0x7000, 0x0079, 0x386d, 0x3875, 0x3877, 0x3880,
+	0x3875, 0x3875, 0x3875, 0x3875, 0x3875, 0x1078, 0x29b2, 0x69ac,
+	0x68b0, 0xa115, 0x0040, 0x3880, 0x1078, 0x4977, 0x0078, 0x3882,
+	0x1078, 0x493f, 0x681c, 0xc0b4, 0x681e, 0x70d4, 0xd0b4, 0x00c0,
+	0x2a08, 0x70a4, 0xa086, 0x0001, 0x00c0, 0x2a52, 0x007c, 0xd6fc,
+	0x00c0, 0x38df, 0x7000, 0xa00d, 0x0079, 0x3896, 0x2a0c, 0x38a6,
+	0x38a0, 0x38d6, 0x38a6, 0x38dc, 0x389e, 0x389e, 0x1078, 0x29b2,
+	0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0xa684, 0x0060,
+	0x0040, 0x38d6, 0xa086, 0x0060, 0x00c0, 0x38d3, 0xa6b4, 0xbfbf,
+	0xc6ed, 0x7e5a, 0x6eb6, 0xa186, 0x0002, 0x0040, 0x38c2, 0x1078,
+	0x45d6, 0x69ac, 0x68b0, 0xa115, 0x0040, 0x38c2, 0x1078, 0x4977,
+	0x0078, 0x38c4, 0x1078, 0x493f, 0x781b, 0x0079, 0x681c, 0xc0b4,
+	0x681e, 0x71d4, 0xd1b4, 0x00c0, 0x2a08, 0x70a4, 0xa086, 0x0001,
+	0x00c0, 0x2a52, 0x007c, 0xd6ec, 0x0040, 0x38b0, 0x6818, 0xd0fc,
+	0x0040, 0x38dc, 0x681b, 0x0007, 0x781b, 0x00f9, 0x007c, 0xc6fc,
+	0x7e5a, 0x7adc, 0x79d8, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94,
+	0x2200, 0xa303, 0x68ae, 0x79d2, 0x781b, 0x0079, 0x007c, 0xd6dc,
+	0x0040, 0x38f8, 0x782b, 0x3009, 0x781b, 0x0079, 0x0078, 0x2a08,
+	0x7884, 0xc0ac, 0x7886, 0x78e4, 0xa084, 0x0008, 0x00c0, 0x390b,
+	0xa484, 0x0200, 0x0040, 0x3905, 0xc6f5, 0xc6dd, 0x7e5a, 0x781b,
+	0x0079, 0x0078, 0x2a08, 0x6820, 0xc095, 0x6822, 0x1078, 0x42e2,
+	0xc6dd, 0x1078, 0x4118, 0x781b, 0x0078, 0x0078, 0x2a08, 0x2300,
+	0x0079, 0x391a, 0x391d, 0x391f, 0x3921, 0x1078, 0x29b2, 0x0078,
+	0x4111, 0xd6d4, 0x00c0, 0x395c, 0x79e4, 0xd1ac, 0x0040, 0x392f,
+	0x78ec, 0xa084, 0x0003, 0x0040, 0x392f, 0x782b, 0x3009, 0x789b,
+	0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, 0x79e4, 0xd1ac,
+	0x0040, 0x393f, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x3958, 0x2001,
+	0x4f04, 0x2004, 0xd0e4, 0x00c0, 0x3954, 0x6820, 0xd0c4, 0x0040,
+	0x3954, 0x0c7e, 0x7058, 0x2060, 0x6004, 0xc09d, 0x6006, 0x6008,
+	0xa084, 0x00ff, 0x600a, 0x0c7f, 0x2001, 0x0014, 0x0078, 0x3443,
+	0xa184, 0x0007, 0x0079, 0x3992, 0x7a90, 0xa294, 0x0007, 0x789b,
+	0x0060, 0x79a8, 0x81ff, 0x0040, 0x3990, 0x789b, 0x0010, 0x7ba8,
+	0xa384, 0x0001, 0x00c0, 0x3983, 0x7ba8, 0x7ba8, 0xa386, 0x0001,
+	0x00c0, 0x3976, 0x2009, 0xfff7, 0x0078, 0x397c, 0xa386, 0x0003,
+	0x00c0, 0x3983, 0x2009, 0xffef, 0x0c7e, 0x7058, 0x2060, 0x6004,
+	0xa104, 0x6006, 0x0c7f, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684,
+	0xfffb, 0x785a, 0x782b, 0x3009, 0x6920, 0xa18c, 0xfcff, 0x6922,
+	0x0078, 0x435d, 0x30d9, 0x30e3, 0x399c, 0x39a2, 0x399a, 0x399a,
+	0x435d, 0x435d, 0x1078, 0x29b2, 0x6920, 0xa18c, 0xfcff, 0x6922,
+	0x0078, 0x4363, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0078, 0x435d,
+	0x79e4, 0xa184, 0x0030, 0x0040, 0x39b2, 0x78ec, 0xa084, 0x0003,
+	0x00c0, 0x39e6, 0x7000, 0xa086, 0x0004, 0x00c0, 0x39cc, 0x7064,
+	0xa086, 0x0002, 0x00c0, 0x39c2, 0x2011, 0x0002, 0x2019, 0x0000,
+	0x0078, 0x2f65, 0x7064, 0xa086, 0x0006, 0x0040, 0x39bc, 0x7064,
+	0xa086, 0x0004, 0x0040, 0x39bc, 0x7000, 0xa086, 0x0000, 0x0040,
+	0x2a08, 0x6920, 0xa184, 0x0420, 0x0040, 0x39db, 0xc1d4, 0x6922,
+	0x6818, 0x0078, 0x3443, 0x6818, 0xa08e, 0x0002, 0x0040, 0x39e4,
+	0xc0fd, 0x681a, 0x2001, 0x0014, 0x0078, 0x3443, 0xa184, 0x0007,
+	0x0079, 0x39ea, 0x435d, 0x435d, 0x39f2, 0x435d, 0x43a5, 0x43a5,
+	0x435d, 0x435d, 0xd6bc, 0x0040, 0x3a34, 0x7184, 0x81ff, 0x0040,
+	0x3a34, 0xa182, 0x000d, 0x00d0, 0x3a01, 0x7087, 0x0000, 0x0078,
+	0x3a06, 0xa182, 0x000c, 0x7086, 0x2009, 0x000c, 0x789b, 0x0061,
+	0x79aa, 0x157e, 0x137e, 0x147e, 0x7088, 0x8114, 0xa210, 0x728a,
+	0xa080, 0x000b, 0xad00, 0x2098, 0xb284, 0x0300, 0x0040, 0x3a28,
+	0x007e, 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x3a24,
+	0x20a1, 0x012b, 0x0078, 0x3a2a, 0x20a1, 0x022b, 0x0078, 0x3a2a,
+	0x20a1, 0x012b, 0x789b, 0x0000, 0x8108, 0x81ac, 0x53a6, 0x147f,
+	0x137f, 0x157f, 0x0078, 0x4363, 0xd6d4, 0x00c0, 0x3a88, 0x6820,
+	0xd084, 0x0040, 0x4363, 0xa68c, 0x0060, 0xa684, 0x0060, 0x0040,
+	0x3a46, 0xa086, 0x0060, 0x00c0, 0x3a46, 0xc1f5, 0xc194, 0x795a,
+	0x69b6, 0x789b, 0x0060, 0x78ab, 0x0000, 0x789b, 0x0061, 0x6818,
+	0xc0fd, 0x681a, 0x78aa, 0x8008, 0x810c, 0x0040, 0x3e4f, 0xa18c,
+	0x00f8, 0x00c0, 0x3e4f, 0x157e, 0x137e, 0x147e, 0x017e, 0x3208,
+	0xa18c, 0x0300, 0x0040, 0x3a74, 0x007e, 0x2001, 0x4f04, 0x2004,
+	0xd0ec, 0x007f, 0x0040, 0x3a70, 0x20a1, 0x012b, 0x0078, 0x3a76,
+	0x20a1, 0x022b, 0x0078, 0x3a76, 0x20a1, 0x012b, 0x017f, 0x789b,
+	0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f,
+	0x137f, 0x157f, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x0078, 0x4363,
+	0x6818, 0xd0fc, 0x0040, 0x3a8e, 0x681b, 0x0008, 0x6820, 0xc0ad,
+	0x6822, 0x1078, 0x4120, 0x781b, 0x00ea, 0x007c, 0x2300, 0x0079,
+	0x3a99, 0x3a9e, 0x3b76, 0x3a9c, 0x1078, 0x29b2, 0x7cd8, 0x7ddc,
+	0x7fd0, 0x82ff, 0x00c0, 0x3ac7, 0x7200, 0xa286, 0x0003, 0x0040,
+	0x3410, 0x71d4, 0xd1bc, 0x00c0, 0x3aca, 0xd1b4, 0x0040, 0x3aca,
+	0x0d7e, 0x783b, 0x8800, 0x781b, 0x004c, 0x70bc, 0xa06d, 0x68b4,
+	0xc0a5, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da,
+	0xc1b4, 0x71d6, 0x7003, 0x0030, 0x0d7f, 0x0078, 0x3ace, 0x7200,
+	0x0078, 0x3ace, 0x783b, 0x1800, 0x781b, 0x004a, 0xa284, 0x000f,
+	0x0079, 0x3ad2, 0x3b61, 0x3b10, 0x3adc, 0x343f, 0x3ada, 0x3b61,
+	0x3ada, 0x3ada, 0x1078, 0x29b2, 0x681c, 0xd0ec, 0x0040, 0x3ae3,
+	0x6008, 0xc08d, 0x600a, 0x6920, 0xc185, 0x6922, 0x6800, 0x6006,
+	0xa005, 0x00c0, 0x3aec, 0x6002, 0x6008, 0xc0d4, 0x600a, 0x681c,
+	0xa084, 0x000e, 0x00c0, 0x3b00, 0xb284, 0x0300, 0x0040, 0x3afc,
+	0x2009, 0x95c0, 0x0078, 0x3b05, 0x2009, 0x96d0, 0x0078, 0x3b05,
+	0x7030, 0x68ba, 0x7140, 0x70cc, 0xa108, 0x2104, 0x6802, 0x2d0a,
+	0x715e, 0xd6dc, 0x00c0, 0x3b10, 0xc6fc, 0x6eb6, 0x0078, 0x3b61,
+	0x6eb6, 0xa684, 0x0060, 0x00c0, 0x3b1a, 0xa684, 0x7fff, 0x68b6,
+	0x0078, 0x3b61, 0xd6dc, 0x00c0, 0x3b28, 0xa684, 0x7fff, 0x68b6,
+	0x6894, 0x68a6, 0x6898, 0x68aa, 0x1078, 0x45d6, 0x0078, 0x3b61,
+	0xd6ac, 0x0040, 0x3b34, 0xa006, 0x1078, 0x45d6, 0x2408, 0x2510,
+	0x69aa, 0x6aa6, 0x0078, 0x3b44, 0x2408, 0x2510, 0x2700, 0x801b,
+	0x00c8, 0x3b3b, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000,
+	0x69aa, 0x6aa6, 0x1078, 0x45d6, 0xd6fc, 0x0040, 0x3b61, 0xa684,
+	0x7fff, 0x68b6, 0x2510, 0x2408, 0xd6ac, 0x00c0, 0x3b59, 0x2700,
+	0x801b, 0x00c8, 0x3b54, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291,
+	0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303,
+	0x68ae, 0x7000, 0xa086, 0x0030, 0x00c0, 0x2a0c, 0x7003, 0x0002,
+	0x70bc, 0xa06d, 0x68bc, 0x7042, 0x70b8, 0xa065, 0x68c0, 0x705a,
+	0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x007c, 0xa586, 0x8800,
+	0x00c0, 0x3b83, 0x7003, 0x0000, 0x6018, 0x8001, 0x601a, 0x6008,
+	0xa084, 0xfbef, 0x600a, 0x0078, 0x4111, 0x7047, 0x0000, 0xa282,
+	0x0006, 0x0050, 0x3b8d, 0x1078, 0x29b2, 0x2300, 0x0079, 0x3b90,
+	0x3b93, 0x3ba5, 0x3bb1, 0x2200, 0x0079, 0x3b96, 0x3b9c, 0x4111,
+	0x3b9e, 0x3b9c, 0x3beb, 0x3c40, 0x1078, 0x29b2, 0x7a80, 0xa294,
+	0x0f00, 0x1078, 0x3cca, 0x0078, 0x4107, 0x1078, 0x3bc2, 0x0079,
+	0x3ba9, 0x4111, 0x3baf, 0x3baf, 0x3beb, 0x3baf, 0x4111, 0x1078,
+	0x29b2, 0x1078, 0x3bc2, 0x0079, 0x3bb5, 0x3bbd, 0x3bbb, 0x3bbb,
+	0x3bbd, 0x3bbb, 0x3bbd, 0x1078, 0x29b2, 0x1078, 0x412b, 0x781b,
+	0x0078, 0x007c, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3bd3, 0x1078,
+	0x3e36, 0x0078, 0x3bcd, 0x1078, 0x45d6, 0x6008, 0xa084, 0xfbef,
+	0x600a, 0x0078, 0x3bd8, 0x7000, 0xa086, 0x0003, 0x0040, 0x3bcb,
+	0x7003, 0x0005, 0xb284, 0x0300, 0x0040, 0x3be2, 0x2001, 0x96e0,
+	0x0078, 0x3be4, 0x2001, 0x9712, 0x2068, 0x704e, 0xad80, 0x0009,
+	0x7046, 0x2200, 0x007c, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3bfd,
+	0x70d4, 0xc0b5, 0x70d6, 0x2c00, 0x70ba, 0x2d00, 0x70be, 0x0078,
+	0x3c02, 0x1078, 0x45d6, 0x0078, 0x3c02, 0x7000, 0xa086, 0x0003,
+	0x0040, 0x3bf9, 0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00, 0x789b,
+	0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215, 0x2069, 0x95c0, 0xb284,
+	0x0300, 0x00c0, 0x3c16, 0xc2fd, 0x2069, 0x96d0, 0x2d04, 0x2d08,
+	0x715e, 0xa06d, 0x0040, 0x3c23, 0x6814, 0xa206, 0x0040, 0x3c25,
+	0x6800, 0x0078, 0x3c17, 0x1078, 0x3cca, 0x6eb4, 0x7e5a, 0x6920,
+	0xa184, 0x0c00, 0x0040, 0x3cf4, 0x7064, 0xa086, 0x0006, 0x00c0,
+	0x3c37, 0x7074, 0xa206, 0x00c0, 0x3c37, 0x7066, 0x707e, 0x681b,
+	0x0005, 0xc1ad, 0xc1d4, 0x6922, 0x1078, 0x4120, 0x0078, 0x3cf4,
+	0x7200, 0xa286, 0x0002, 0x00c0, 0x3c52, 0x70d4, 0xc0b5, 0x70d6,
+	0x2c00, 0x70ba, 0x2d00, 0x70be, 0x0078, 0x3c56, 0x1078, 0x45d6,
+	0x0078, 0x3c56, 0xa286, 0x0003, 0x0040, 0x3c4e, 0x7003, 0x0001,
+	0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x001f,
+	0xa215, 0xb284, 0x0300, 0x00c0, 0x3c66, 0xc2fd, 0x79a8, 0x79a8,
+	0xa18c, 0x00ff, 0x2118, 0x70cc, 0xa168, 0x2d04, 0x2d08, 0x715e,
+	0xa06d, 0x0040, 0x3c7a, 0x6814, 0xa206, 0x0040, 0x3ca3, 0x6800,
+	0x0078, 0x3c6e, 0x7003, 0x0005, 0xb284, 0x0300, 0x0040, 0x3c84,
+	0x2001, 0x96e0, 0x0078, 0x3c86, 0x2001, 0x9712, 0x2068, 0x704e,
+	0x157e, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x00f0, 0x3c8b,
+	0x157f, 0xb284, 0x0300, 0x0040, 0x3c98, 0xc2fc, 0x0078, 0x3c99,
+	0xc2fd, 0x6a16, 0xad80, 0x0009, 0x7046, 0x68b7, 0x0700, 0x6823,
+	0x0800, 0x6827, 0x0003, 0x6eb4, 0x6920, 0xa184, 0x0c00, 0x0040,
+	0x3cf4, 0xd0dc, 0x0040, 0x3cbf, 0x7064, 0xa086, 0x0004, 0x00c0,
+	0x3cbb, 0x7074, 0xa206, 0x00c0, 0x3cbb, 0x7078, 0xa306, 0x00c0,
+	0x3cbb, 0x7066, 0x707e, 0x1078, 0x4127, 0x0078, 0x3cf4, 0x681b,
+	0x0005, 0xc1ad, 0xc1d4, 0x6922, 0x1078, 0x4120, 0x707f, 0x0000,
+	0x0078, 0x3cf4, 0x7003, 0x0005, 0xb284, 0x0300, 0x0040, 0x3cd4,
+	0x2001, 0x96e0, 0x0078, 0x3cd6, 0x2001, 0x9712, 0x2068, 0x704e,
+	0x157e, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x00f0, 0x3cdb,
+	0x157f, 0xb284, 0x0300, 0x0040, 0x3ce8, 0xc2fc, 0x0078, 0x3ce9,
+	0xc2fd, 0x6a16, 0xad80, 0x0009, 0x7046, 0x68b7, 0x0700, 0x6823,
+	0x0800, 0x6827, 0x0003, 0x007c, 0xc6ec, 0xa6ac, 0x0060, 0x0040,
+	0x3d46, 0x6b98, 0x6c94, 0x69ac, 0x68b0, 0xa105, 0x00c0, 0x3d21,
+	0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0xa586, 0x0060, 0x0040, 0x3d4b,
+	0xd6f4, 0x00c0, 0x3d0c, 0xc6ed, 0xa6b4, 0xb7ff, 0x7e5a, 0x2009,
+	0x0079, 0xd69c, 0x0040, 0x3d19, 0x2009, 0x0078, 0x2019, 0x0000,
+	0x2320, 0x791a, 0xd6ec, 0x0040, 0x3d56, 0x1078, 0x493f, 0x0078,
+	0x3d56, 0x68b0, 0xa31a, 0x2100, 0xa423, 0x2400, 0xa305, 0x0040,
+	0x3d4d, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0x68b0, 0xd6f4, 0x00c0,
+	0x3d32, 0xc6ed, 0xc6f4, 0x7e5a, 0x2011, 0x0079, 0xd69c, 0x0040,
+	0x3d3e, 0x2011, 0x0078, 0x2019, 0x0000, 0x2320, 0x7a1a, 0xd6ec,
+	0x0040, 0x3d56, 0x1078, 0x4977, 0x0078, 0x3d56, 0x2019, 0x0000,
+	0x2320, 0x0078, 0x3d4d, 0xa6b4, 0xb7ff, 0x7e5a, 0x2009, 0x0079,
+	0xd69c, 0x0040, 0x3d55, 0x2009, 0x0078, 0x791a, 0x68c0, 0x705a,
+	0x2d00, 0x704e, 0x68c4, 0x2060, 0x71d4, 0x2001, 0x4f01, 0x2004,
+	0xd0c4, 0x00c0, 0x3dab, 0x70d8, 0xa02d, 0x0040, 0x3d84, 0xd1bc,
+	0x0040, 0x3d9e, 0x7a80, 0xa294, 0x0f00, 0x70dc, 0xa206, 0x0040,
+	0x3d75, 0x78e0, 0xa504, 0x00c0, 0x3dab, 0x70da, 0xc1bc, 0x71d6,
+	0x0078, 0x3dab, 0x2031, 0x0001, 0x852c, 0x0048, 0x3d83, 0x8633,
+	0x8210, 0x0078, 0x3d7c, 0x007c, 0x7de0, 0xa594, 0xff00, 0x0040,
+	0x3d91, 0x2011, 0x0008, 0x852f, 0x1078, 0x3d7a, 0x8637, 0x0078,
+	0x3d93, 0x1078, 0x3d7a, 0x8217, 0x7880, 0xa084, 0x0f00, 0xa206,
+	0x0040, 0x3dab, 0x72de, 0x76da, 0x0078, 0x3dab, 0x7a80, 0xa294,
+	0x0f00, 0x70dc, 0xa236, 0x0040, 0x3d9b, 0x78e0, 0xa534, 0x0040,
+	0x3d9b, 0xc1bd, 0x71d6, 0xd1b4, 0x00c0, 0x2a08, 0x2300, 0xa405,
+	0x0040, 0x2a08, 0x70a4, 0xa086, 0x0001, 0x00c0, 0x2a52, 0x007c,
+	0x6020, 0xa005, 0x0040, 0x3dc6, 0x8001, 0x6022, 0x6008, 0xa085,
+	0x0008, 0x600a, 0x700f, 0x0100, 0x702c, 0x6026, 0x007c, 0xa006,
+	0x1078, 0x45d6, 0x7000, 0xa086, 0x0002, 0x0040, 0x3dd4, 0x7064,
+	0xa086, 0x0005, 0x00c0, 0x3dde, 0x682b, 0x0000, 0x6817, 0x0000,
+	0x681b, 0x0001, 0x6823, 0x0040, 0x681f, 0x0100, 0x7000, 0xa084,
+	0x000f, 0x0079, 0x3de3, 0x2a0c, 0x3df3, 0x3ded, 0x3e15, 0x3dfd,
+	0x2a0c, 0x3deb, 0x3deb, 0x1078, 0x29b2, 0x1078, 0x3e20, 0x1078,
+	0x3e19, 0x0078, 0x3df9, 0x1078, 0x3e20, 0x705c, 0x2060, 0x6800,
+	0x6002, 0x1078, 0x2073, 0x0078, 0x2a0c, 0x7064, 0x7067, 0x0000,
+	0x7083, 0x0000, 0x0079, 0x3e04, 0x3e11, 0x3e11, 0x3e0c, 0x3e0c,
+	0x3e0c, 0x3e11, 0x3e0c, 0x3e11, 0x77d4, 0xc7dd, 0x77d6, 0x0079,
+	0x2f7e, 0x7067, 0x0000, 0x0078, 0x2a0c, 0x681b, 0x0000, 0x0078,
+	0x3711, 0x6800, 0xa005, 0x00c0, 0x3e1e, 0x6002, 0x6006, 0x007c,
+	0x6410, 0x84ff, 0x0040, 0x3e32, 0x2009, 0x4f02, 0x2104, 0x8001,
+	0x200a, 0x8421, 0x6412, 0x00c0, 0x3e32, 0x2021, 0x4f04, 0x2404,
+	0xc0a5, 0x2022, 0x6008, 0xc0a4, 0x600a, 0x007c, 0x6018, 0xa005,
+	0x0040, 0x3e3c, 0x8001, 0x601a, 0x007c, 0x1078, 0x43d3, 0x681b,
+	0x0018, 0x0078, 0x3e7d, 0x1078, 0x43d3, 0x681b, 0x0019, 0x0078,
+	0x3e7d, 0x1078, 0x43d3, 0x681b, 0x001a, 0x0078, 0x3e7d, 0x1078,
+	0x43d3, 0x681b, 0x0003, 0x0078, 0x3e7d, 0x7774, 0x1078, 0x424e,
+	0x7178, 0xa18c, 0x00ff, 0x3210, 0xa294, 0x0300, 0x0040, 0x3e64,
+	0xa1e8, 0x94c0, 0x0078, 0x3e66, 0xa1e8, 0x95d0, 0x2d04, 0x2d08,
+	0x2068, 0xa005, 0x00c0, 0x3e6f, 0x707e, 0x0078, 0x2a0c, 0x6814,
+	0x7274, 0xa206, 0x0040, 0x3e77, 0x6800, 0x0078, 0x3e67, 0x6800,
+	0x200a, 0x681b, 0x0005, 0x707f, 0x0000, 0x1078, 0x3e20, 0x6820,
+	0xd084, 0x00c0, 0x3e85, 0x1078, 0x3e19, 0x1078, 0x3e36, 0x681f,
+	0x0000, 0x6823, 0x0020, 0x1078, 0x2073, 0x0078, 0x2a0c, 0xa282,
+	0x0003, 0x00c0, 0x4107, 0x7da8, 0xa5ac, 0x00ff, 0x7e5a, 0x7ea8,
+	0xa6b4, 0x00ff, 0x6920, 0xc1bd, 0x6922, 0xd1c4, 0x0040, 0x3eea,
+	0xc1c4, 0x6922, 0xa6b4, 0x00ff, 0x0040, 0x3ed7, 0xa682, 0x000c,
+	0x0048, 0x3eae, 0x0040, 0x3eae, 0x2031, 0x000c, 0x2500, 0xa086,
+	0x000a, 0x0040, 0x3eb5, 0x852b, 0x852b, 0x1078, 0x41e0, 0x0040,
+	0x3ebd, 0x1078, 0x3fbc, 0x0078, 0x3ee0, 0x1078, 0x419b, 0x0c7e,
+	0x2960, 0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, 0x3ff2, 0x0c7f,
+	0x6920, 0xc1c5, 0x6922, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x00c0,
+	0x3ed4, 0x781b, 0x0064, 0x007c, 0x781b, 0x0078, 0x007c, 0x0c7e,
+	0x2960, 0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, 0x3ff2, 0x0c7f,
+	0x7e58, 0xd6d4, 0x00c0, 0x3ee7, 0x781b, 0x0067, 0x007c, 0x781b,
+	0x0079, 0x007c, 0x0c7e, 0x7058, 0x2060, 0x6100, 0xd1e4, 0x0040,
+	0x3f33, 0x6208, 0x8217, 0xa294, 0x00ff, 0xa282, 0x000c, 0x0048,
+	0x3efd, 0x0040, 0x3efd, 0x2011, 0x000c, 0x2600, 0xa202, 0x00c8,
+	0x3f02, 0x2230, 0x6208, 0xa294, 0x00ff, 0x2001, 0x4f05, 0x2004,
+	0xd0e4, 0x00c0, 0x3f17, 0x78ec, 0xd0e4, 0x0040, 0x3f17, 0xa282,
+	0x000a, 0x00c8, 0x3f1d, 0x2011, 0x000a, 0x0078, 0x3f1d, 0xa282,
+	0x000c, 0x00c8, 0x3f1d, 0x2011, 0x000c, 0x2200, 0xa502, 0x00c8,
+	0x3f22, 0x2228, 0x1078, 0x419f, 0x2500, 0xa086, 0x000a, 0x0040,
+	0x3f2b, 0x852b, 0x852b, 0x1078, 0x41e0, 0x0040, 0x3f33, 0x1078,
+	0x3fbc, 0x0078, 0x3f37, 0x1078, 0x419b, 0x1078, 0x3ff2, 0x7858,
+	0xc095, 0x785a, 0x0c7f, 0x781b, 0x0078, 0x007c, 0x0c7e, 0x2960,
+	0x6000, 0xd0e4, 0x00c0, 0x3f58, 0xd0b4, 0x00c0, 0x3f52, 0x6010,
+	0xa084, 0x000f, 0x00c0, 0x3f52, 0x6104, 0xa18c, 0xfff5, 0x6106,
+	0x0c7f, 0x007c, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078, 0x3f83,
+	0x68a0, 0xd0cc, 0x00c0, 0x3f52, 0x6208, 0xa294, 0x00ff, 0x2001,
+	0x4f05, 0x2004, 0xd0e4, 0x00c0, 0x3f71, 0x78ec, 0xd0e4, 0x0040,
+	0x3f71, 0xa282, 0x000b, 0x00c8, 0x3f71, 0x2011, 0x000a, 0x0078,
+	0x3f77, 0xa282, 0x000c, 0x00c8, 0x3f77, 0x2011, 0x000c, 0x6308,
+	0x831f, 0xa39c, 0x00ff, 0xa382, 0x000c, 0x0048, 0x3f83, 0x0040,
+	0x3f83, 0x2019, 0x000c, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab,
+	0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xc0c5, 0x6822,
+	0x70d4, 0xd0b4, 0x0040, 0x3f9f, 0xc0b4, 0x70d6, 0x70b8, 0xa065,
+	0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f,
+	0x007c, 0x0c7e, 0x2960, 0x6104, 0xa18c, 0xfff5, 0x6106, 0x2011,
+	0x0032, 0x2019, 0x0000, 0x0078, 0x3fad, 0x78ab, 0x0001, 0x78ab,
+	0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820,
+	0xc0c5, 0x6822, 0x0c7f, 0x007c, 0x0c7e, 0x7158, 0x2160, 0x2018,
+	0xa08c, 0x0020, 0x0040, 0x3fc5, 0xc0ac, 0x2008, 0xa084, 0xfff0,
+	0xa635, 0x7e86, 0x6018, 0x789a, 0x7eae, 0x6612, 0x78a4, 0xa084,
+	0xfff0, 0xa18c, 0x000f, 0xa105, 0xc0f4, 0xa39c, 0x0020, 0x0040,
+	0x3fdb, 0xa085, 0x4000, 0xc0fc, 0xd0b4, 0x00c0, 0x3fe0, 0xc0fd,
+	0x78a6, 0x6016, 0x788a, 0xa6b4, 0x000f, 0x8637, 0x8204, 0x8004,
+	0xa084, 0x00ff, 0xa605, 0x600e, 0x6004, 0xa084, 0xfff5, 0x6006,
+	0x0c7f, 0x007c, 0x0c7e, 0x7058, 0x2060, 0x6018, 0x789a, 0x78a4,
+	0xa084, 0xfff0, 0x78a6, 0x6012, 0x7884, 0xa084, 0xfff0, 0x7886,
+	0x600c, 0xa084, 0x00ff, 0x600e, 0x0c7f, 0x007c, 0xa282, 0x0002,
+	0x00c0, 0x4107, 0x7aa8, 0x6920, 0xc1bd, 0x6922, 0xd1cc, 0x0040,
+	0x4041, 0xc1cc, 0x6922, 0xa294, 0x00ff, 0xa282, 0x0002, 0x00c8,
+	0x4107, 0x1078, 0x4094, 0x1078, 0x3ff2, 0xa980, 0x0001, 0x200c,
+	0x1078, 0x424a, 0x1078, 0x3f3e, 0x88ff, 0x0040, 0x4037, 0x789b,
+	0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x00c0,
+	0x4034, 0x781b, 0x0064, 0x007c, 0x781b, 0x0078, 0x007c, 0x7e58,
+	0xd6d4, 0x00c0, 0x403e, 0x781b, 0x0067, 0x007c, 0x781b, 0x0079,
+	0x007c, 0xa282, 0x0002, 0x00c8, 0x4049, 0xa284, 0x0001, 0x0040,
+	0x4052, 0x7158, 0xa188, 0x0000, 0x210c, 0xd1ec, 0x00c0, 0x4052,
+	0x2011, 0x0000, 0x1078, 0x417c, 0x1078, 0x4094, 0x1078, 0x3ff2,
+	0x7858, 0xc095, 0x785a, 0x781b, 0x0078, 0x007c, 0x0c7e, 0x027e,
+	0x2960, 0x6000, 0x2011, 0x0001, 0xd0ec, 0x00c0, 0x4075, 0xd0bc,
+	0x00c0, 0x4073, 0x6014, 0xd0b4, 0x00c0, 0x4073, 0xc1a4, 0x6106,
+	0xa006, 0x0078, 0x4091, 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab,
 	0x0002, 0x78ab, 0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x70d4, 0xd0b4,
-	0x0040, 0x403d, 0xc0b4, 0x70d6, 0x70b8, 0xa065, 0x6008, 0xa084,
+	0x0040, 0x408d, 0xc0b4, 0x70d6, 0x70b8, 0xa065, 0x6008, 0xa084,
 	0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x6820, 0xa085, 0x0200,
 	0x6822, 0x027f, 0x0c7f, 0x007c, 0x0c7e, 0x7058, 0x2060, 0x82ff,
-	0x0040, 0x404c, 0x2011, 0x0040, 0x6018, 0xa080, 0x0002, 0x789a,
-	0x78a4, 0xa084, 0xffbf, 0xa205, 0xc0fc, 0xd0b4, 0x00c0, 0x4059,
+	0x0040, 0x409c, 0x2011, 0x0040, 0x6018, 0xa080, 0x0002, 0x789a,
+	0x78a4, 0xa084, 0xffbf, 0xa205, 0xc0fc, 0xd0b4, 0x00c0, 0x40a9,
 	0xc0fd, 0x78a6, 0x6016, 0x788a, 0x6004, 0xc0a4, 0x6006, 0x0c7f,
-	0x007c, 0x007e, 0x7000, 0xa086, 0x0003, 0x0040, 0x406a, 0x007f,
-	0x0078, 0x406d, 0x007f, 0x0078, 0x40b4, 0xd6ac, 0x0040, 0x40b4,
-	0x7888, 0xa084, 0x0040, 0x0040, 0x40b4, 0x7bb8, 0xa384, 0x003f,
-	0x831b, 0x00c8, 0x407c, 0x8000, 0xa005, 0x0040, 0x4091, 0x831b,
-	0x00c8, 0x4085, 0x8001, 0x0040, 0x40b1, 0xd6f4, 0x0040, 0x4091,
-	0x78b8, 0x801b, 0x00c8, 0x408d, 0x8000, 0xa084, 0x003f, 0x00c0,
-	0x40b1, 0xc6f4, 0x7e5a, 0x79d8, 0x7adc, 0x2001, 0x0001, 0xa108,
-	0x00c8, 0x409c, 0xa291, 0x0000, 0x79d2, 0x79da, 0x7ad6, 0x7ade,
-	0x1078, 0x49c3, 0x781b, 0x0076, 0xb284, 0x0300, 0x0040, 0x40ac,
-	0x2001, 0x0000, 0x0078, 0x40ae, 0x2001, 0x0001, 0x1078, 0x484b,
+	0x007c, 0x007e, 0x7000, 0xa086, 0x0003, 0x0040, 0x40ba, 0x007f,
+	0x0078, 0x40bd, 0x007f, 0x0078, 0x4104, 0xd6ac, 0x0040, 0x4104,
+	0x7888, 0xa084, 0x0040, 0x0040, 0x4104, 0x7bb8, 0xa384, 0x003f,
+	0x831b, 0x00c8, 0x40cc, 0x8000, 0xa005, 0x0040, 0x40e1, 0x831b,
+	0x00c8, 0x40d5, 0x8001, 0x0040, 0x4101, 0xd6f4, 0x0040, 0x40e1,
+	0x78b8, 0x801b, 0x00c8, 0x40dd, 0x8000, 0xa084, 0x003f, 0x00c0,
+	0x4101, 0xc6f4, 0x7e5a, 0x79d8, 0x7adc, 0x2001, 0x0001, 0xa108,
+	0x00c8, 0x40ec, 0xa291, 0x0000, 0x79d2, 0x79da, 0x7ad6, 0x7ade,
+	0x1078, 0x4a44, 0x781b, 0x0076, 0xb284, 0x0300, 0x0040, 0x40fc,
+	0x2001, 0x0000, 0x0078, 0x40fe, 0x2001, 0x0001, 0x1078, 0x48ce,
 	0x007c, 0x781b, 0x0076, 0x007c, 0x781b, 0x0079, 0x007c, 0x1078,
-	0x40df, 0x781b, 0x0078, 0x007c, 0x1078, 0x40c8, 0x781b, 0x0078,
-	0x007c, 0x6827, 0x0002, 0x1078, 0x40d0, 0x781b, 0x0078, 0x007c,
-	0x2001, 0x0005, 0x0078, 0x40e1, 0x2001, 0x000c, 0x0078, 0x40e1,
-	0x6820, 0xc0d5, 0x6822, 0x2001, 0x0006, 0x0078, 0x40e1, 0x2001,
-	0x000d, 0x0078, 0x40e1, 0x2001, 0x0009, 0x0078, 0x40e1, 0x2001,
+	0x412f, 0x781b, 0x0078, 0x007c, 0x1078, 0x4118, 0x781b, 0x0078,
+	0x007c, 0x6827, 0x0002, 0x1078, 0x4120, 0x781b, 0x0078, 0x007c,
+	0x2001, 0x0005, 0x0078, 0x4131, 0x2001, 0x000c, 0x0078, 0x4131,
+	0x6820, 0xc0d5, 0x6822, 0x2001, 0x0006, 0x0078, 0x4131, 0x2001,
+	0x000d, 0x0078, 0x4131, 0x2001, 0x0009, 0x0078, 0x4131, 0x2001,
 	0x0007, 0x789b, 0x007e, 0x78aa, 0xc69d, 0x7e5a, 0x70d4, 0xd0b4,
-	0x0040, 0x40f7, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008,
+	0x0040, 0x4147, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008,
 	0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f, 0x007c,
 	0x077e, 0x873f, 0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703, 0x017e,
-	0xb28c, 0x0300, 0x0040, 0x4108, 0xa0e0, 0x52c0, 0x0078, 0x410a,
-	0xa0e0, 0x5340, 0x017f, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184,
-	0x000f, 0x0040, 0x411a, 0xa184, 0xfff0, 0x78a6, 0x6012, 0x6004,
+	0xb28c, 0x0300, 0x0040, 0x4158, 0xa0e0, 0x53c0, 0x0078, 0x415a,
+	0xa0e0, 0x5440, 0x017f, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184,
+	0x000f, 0x0040, 0x416a, 0xa184, 0xfff0, 0x78a6, 0x6012, 0x6004,
 	0xc09d, 0x6006, 0x8738, 0x8738, 0x7f9a, 0x79a4, 0xa184, 0x0040,
-	0x0040, 0x412a, 0xa184, 0xffbf, 0xc0fd, 0x78a6, 0x6016, 0x6004,
+	0x0040, 0x417a, 0xa184, 0xffbf, 0xc0fd, 0x78a6, 0x6016, 0x6004,
 	0xc0a5, 0x6006, 0x077f, 0x007c, 0x789b, 0x0010, 0x78ab, 0x0001,
 	0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060, 0x78ab,
-	0x0004, 0x70d4, 0xd0b4, 0x0040, 0x414a, 0xc0b4, 0x70d6, 0x0c7e,
+	0x0004, 0x70d4, 0xd0b4, 0x0040, 0x419a, 0xc0b4, 0x70d6, 0x0c7e,
 	0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001,
 	0x601a, 0x0c7f, 0x007c, 0x2031, 0x0000, 0x2029, 0x0032, 0x789b,
 	0x0010, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa,
 	0x7eaa, 0x789b, 0x0060, 0x78ab, 0x0005, 0x70d4, 0xd0b4, 0x0040,
-	0x416e, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084,
+	0x41be, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084,
 	0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f, 0x007c, 0x157e,
 	0x8007, 0xa084, 0x00ff, 0x8003, 0x8003, 0xa080, 0x0020, 0x789a,
-	0x79a4, 0xa18c, 0xfff0, 0x2021, 0x41e3, 0x2019, 0x0011, 0x20a9,
+	0x79a4, 0xa18c, 0xfff0, 0x2021, 0x4233, 0x2019, 0x0011, 0x20a9,
 	0x000e, 0x2011, 0x0032, 0x2404, 0xa084, 0xfff0, 0xa106, 0x0040,
-	0x418e, 0x8420, 0x2300, 0xa210, 0x00f0, 0x4183, 0x157f, 0x007c,
-	0x157e, 0x2001, 0x4e05, 0x2004, 0xd0e4, 0x00c0, 0x41c1, 0x2021,
-	0x41f1, 0x20a9, 0x0009, 0x2011, 0x0028, 0xa582, 0x0019, 0x0040,
-	0x41d7, 0x0048, 0x41d7, 0x8420, 0x95a9, 0x2011, 0x0032, 0xa582,
-	0x0032, 0x0040, 0x41d7, 0x0048, 0x41d7, 0x8420, 0x95a9, 0x2019,
-	0x000a, 0x2011, 0x0064, 0x2200, 0xa502, 0x0040, 0x41d7, 0x0048,
-	0x41d7, 0x8420, 0x2300, 0xa210, 0x00f0, 0x41b3, 0x157f, 0x0078,
-	0x41d5, 0x2021, 0x41e3, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011,
-	0x0032, 0x2200, 0xa502, 0x0040, 0x41d7, 0x0048, 0x41d7, 0x8420,
-	0x2300, 0xa210, 0x00f0, 0x41c9, 0x157f, 0xa006, 0x007c, 0x157f,
-	0xa582, 0x0064, 0x00c8, 0x41e0, 0x7808, 0xa085, 0x0070, 0x780a,
+	0x41de, 0x8420, 0x2300, 0xa210, 0x00f0, 0x41d3, 0x157f, 0x007c,
+	0x157e, 0x2001, 0x4f05, 0x2004, 0xd0e4, 0x00c0, 0x4211, 0x2021,
+	0x4241, 0x20a9, 0x0009, 0x2011, 0x0028, 0xa582, 0x0019, 0x0040,
+	0x4227, 0x0048, 0x4227, 0x8420, 0x95a9, 0x2011, 0x0032, 0xa582,
+	0x0032, 0x0040, 0x4227, 0x0048, 0x4227, 0x8420, 0x95a9, 0x2019,
+	0x000a, 0x2011, 0x0064, 0x2200, 0xa502, 0x0040, 0x4227, 0x0048,
+	0x4227, 0x8420, 0x2300, 0xa210, 0x00f0, 0x4203, 0x157f, 0x0078,
+	0x4225, 0x2021, 0x4233, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011,
+	0x0032, 0x2200, 0xa502, 0x0040, 0x4227, 0x0048, 0x4227, 0x8420,
+	0x2300, 0xa210, 0x00f0, 0x4219, 0x157f, 0xa006, 0x007c, 0x157f,
+	0xa582, 0x0064, 0x00c8, 0x4230, 0x7808, 0xa085, 0x0070, 0x780a,
 	0x2404, 0xa005, 0x007c, 0x1209, 0x3002, 0x3202, 0x4203, 0x4403,
 	0x5404, 0x5604, 0x6605, 0x6805, 0x7806, 0x7a06, 0x0c07, 0x0c07,
 	0x0e07, 0x10e1, 0x330a, 0x5805, 0x5a05, 0x6a06, 0x6c06, 0x7c07,
 	0x7e07, 0x0e00, 0x789b, 0x0010, 0xa046, 0x007c, 0xa784, 0x0f00,
 	0x800b, 0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105,
-	0xd7fc, 0x0040, 0x420f, 0xa0e0, 0x73c0, 0x0078, 0x4211, 0xa0e0,
-	0x53c0, 0x007c, 0x0e7e, 0x0f7e, 0xd084, 0x0040, 0x421f, 0x2079,
-	0x0100, 0x2009, 0x4e80, 0x2071, 0x4e80, 0x0078, 0x422f, 0x2009,
-	0x4e40, 0x2071, 0x4e40, 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x0040,
-	0x422d, 0x2079, 0x0100, 0x0078, 0x422f, 0x2079, 0x0200, 0x2091,
-	0x8000, 0x2104, 0xa084, 0x000f, 0x0079, 0x4236, 0x4240, 0x4240,
-	0x4240, 0x4240, 0x4240, 0x4240, 0x423e, 0x423e, 0x1078, 0x296b,
-	0x69b4, 0xc1f5, 0xa18c, 0xff9f, 0x69b6, 0xa005, 0x0040, 0x428f,
+	0xd7fc, 0x0040, 0x425f, 0xa0e0, 0x74c0, 0x0078, 0x4261, 0xa0e0,
+	0x54c0, 0x007c, 0x0e7e, 0x0f7e, 0xd084, 0x0040, 0x426f, 0x2079,
+	0x0100, 0x2009, 0x4f80, 0x2071, 0x4f80, 0x0078, 0x427f, 0x2009,
+	0x4f40, 0x2071, 0x4f40, 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x0040,
+	0x427d, 0x2079, 0x0100, 0x0078, 0x427f, 0x2079, 0x0200, 0x2091,
+	0x8000, 0x2104, 0xa084, 0x000f, 0x0079, 0x4286, 0x4290, 0x4290,
+	0x4290, 0x4290, 0x4290, 0x4290, 0x428e, 0x428e, 0x1078, 0x29b2,
+	0x69b4, 0xc1f5, 0xa18c, 0xff9f, 0x69b6, 0xa005, 0x0040, 0x42df,
 	0x7858, 0xa084, 0xff9f, 0xa085, 0x6000, 0x785a, 0x7828, 0xa086,
-	0x1814, 0x00c0, 0x428f, 0x784b, 0x0004, 0x7848, 0xa084, 0x0004,
-	0x00c0, 0x4255, 0x784b, 0x0008, 0x7848, 0xa084, 0x0008, 0x00c0,
-	0x425c, 0x7830, 0xd0bc, 0x00c0, 0x428f, 0x007e, 0x2001, 0x4e04,
-	0x2004, 0xd0ec, 0x007f, 0x0040, 0x4271, 0xb284, 0x0300, 0x0078,
-	0x4273, 0xb284, 0x0400, 0x0040, 0x4279, 0x0018, 0x428f, 0x0078,
-	0x427b, 0x0028, 0x428f, 0x79e4, 0xa184, 0x0030, 0x0040, 0x428f,
-	0x78ec, 0xa084, 0x0003, 0x0040, 0x428f, 0x681c, 0xd0ac, 0x00c0,
-	0x428d, 0x1078, 0x4319, 0x0078, 0x428f, 0x781b, 0x00f9, 0x0f7f,
-	0x0e7f, 0x007c, 0x0c7e, 0x2001, 0x4e01, 0x2004, 0xd0ac, 0x00c0,
-	0x430b, 0x6814, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
-	0xb28c, 0x0300, 0x0040, 0x42a8, 0xa0e0, 0x52c0, 0x0078, 0x42aa,
-	0xa0e0, 0x5340, 0x6004, 0xa084, 0x000a, 0x00c0, 0x430b, 0x6108,
-	0xa194, 0xff00, 0x0040, 0x430b, 0xa18c, 0x00ff, 0x2001, 0x000a,
-	0xa106, 0x0040, 0x42d6, 0x2001, 0x000c, 0xa106, 0x0040, 0x42da,
-	0x2001, 0x0012, 0xa106, 0x0040, 0x42de, 0x2001, 0x0014, 0xa106,
-	0x0040, 0x42e2, 0x2001, 0x0019, 0xa106, 0x0040, 0x42e6, 0x2001,
-	0x0032, 0xa106, 0x0040, 0x42ea, 0x0078, 0x42ee, 0x2009, 0x000c,
-	0x0078, 0x42f0, 0x2009, 0x0012, 0x0078, 0x42f0, 0x2009, 0x0014,
-	0x0078, 0x42f0, 0x2009, 0x0019, 0x0078, 0x42f0, 0x2009, 0x0020,
-	0x0078, 0x42f0, 0x2009, 0x003f, 0x0078, 0x42f0, 0x2011, 0x0000,
+	0x1814, 0x00c0, 0x42df, 0x784b, 0x0004, 0x7848, 0xa084, 0x0004,
+	0x00c0, 0x42a5, 0x784b, 0x0008, 0x7848, 0xa084, 0x0008, 0x00c0,
+	0x42ac, 0x7830, 0xd0bc, 0x00c0, 0x42df, 0x007e, 0x2001, 0x4f04,
+	0x2004, 0xd0ec, 0x007f, 0x0040, 0x42c1, 0xb284, 0x0300, 0x0078,
+	0x42c3, 0xb284, 0x0400, 0x0040, 0x42c9, 0x0018, 0x42df, 0x0078,
+	0x42cb, 0x0028, 0x42df, 0x79e4, 0xa184, 0x0030, 0x0040, 0x42df,
+	0x78ec, 0xa084, 0x0003, 0x0040, 0x42df, 0x681c, 0xd0ac, 0x00c0,
+	0x42dd, 0x1078, 0x4369, 0x0078, 0x42df, 0x781b, 0x00f9, 0x0f7f,
+	0x0e7f, 0x007c, 0x0c7e, 0x2001, 0x4f01, 0x2004, 0xd0ac, 0x00c0,
+	0x435b, 0x6814, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
+	0xb28c, 0x0300, 0x0040, 0x42f8, 0xa0e0, 0x53c0, 0x0078, 0x42fa,
+	0xa0e0, 0x5440, 0x6004, 0xa084, 0x000a, 0x00c0, 0x435b, 0x6108,
+	0xa194, 0xff00, 0x0040, 0x435b, 0xa18c, 0x00ff, 0x2001, 0x000a,
+	0xa106, 0x0040, 0x4326, 0x2001, 0x000c, 0xa106, 0x0040, 0x432a,
+	0x2001, 0x0012, 0xa106, 0x0040, 0x432e, 0x2001, 0x0014, 0xa106,
+	0x0040, 0x4332, 0x2001, 0x0019, 0xa106, 0x0040, 0x4336, 0x2001,
+	0x0032, 0xa106, 0x0040, 0x433a, 0x0078, 0x433e, 0x2009, 0x000c,
+	0x0078, 0x4340, 0x2009, 0x0012, 0x0078, 0x4340, 0x2009, 0x0014,
+	0x0078, 0x4340, 0x2009, 0x0019, 0x0078, 0x4340, 0x2009, 0x0020,
+	0x0078, 0x4340, 0x2009, 0x003f, 0x0078, 0x4340, 0x2011, 0x0000,
 	0x2100, 0xa205, 0x600a, 0x6004, 0xa085, 0x0002, 0x6006, 0x2061,
-	0x4e00, 0x6004, 0xd0bc, 0x0040, 0x430b, 0x6814, 0xd0fc, 0x00c0,
-	0x4306, 0x60ea, 0x2061, 0x4e40, 0x0078, 0x4309, 0x60ee, 0x2061,
-	0x4e80, 0x601f, 0x800f, 0x0c7f, 0x007c, 0x781b, 0x0079, 0x007c,
+	0x4f00, 0x6004, 0xd0bc, 0x0040, 0x435b, 0x6814, 0xd0fc, 0x00c0,
+	0x4356, 0x60ea, 0x2061, 0x4f40, 0x0078, 0x4359, 0x60ee, 0x2061,
+	0x4f80, 0x601f, 0x800f, 0x0c7f, 0x007c, 0x781b, 0x0079, 0x007c,
 	0x781b, 0x0078, 0x007c, 0x781b, 0x0067, 0x007c, 0x781b, 0x0064,
-	0x007c, 0x2009, 0x4e19, 0x210c, 0xa186, 0x0000, 0x0040, 0x432b,
-	0xa186, 0x0001, 0x0040, 0x432e, 0x701f, 0x000b, 0x7067, 0x0001,
+	0x007c, 0x2009, 0x4f19, 0x210c, 0xa186, 0x0000, 0x0040, 0x437b,
+	0xa186, 0x0001, 0x0040, 0x437e, 0x701f, 0x000b, 0x7067, 0x0001,
 	0x781b, 0x0047, 0x007c, 0x781b, 0x00f0, 0x007c, 0x701f, 0x000a,
-	0x007c, 0x2009, 0x4e19, 0x210c, 0xa186, 0x0000, 0x0040, 0x4346,
-	0xa186, 0x0001, 0x0040, 0x4343, 0x701f, 0x000b, 0x7067, 0x0001,
+	0x007c, 0x2009, 0x4f19, 0x210c, 0xa186, 0x0000, 0x0040, 0x4396,
+	0xa186, 0x0001, 0x0040, 0x4393, 0x701f, 0x000b, 0x7067, 0x0001,
 	0x781b, 0x0047, 0x007c, 0x701f, 0x000a, 0x007c, 0x781b, 0x00ef,
 	0x007c, 0x781b, 0x00f9, 0x007c, 0x781b, 0x00f8, 0x007c, 0x781b,
 	0x00c9, 0x007c, 0x781b, 0x00c8, 0x007c, 0x6818, 0xd0fc, 0x0040,
-	0x435b, 0x681b, 0x001d, 0x7067, 0x0001, 0x781b, 0x0047, 0x007c,
-	0x7830, 0xa084, 0x00c0, 0x00c0, 0x4382, 0x7808, 0xc08c, 0x780a,
+	0x43ab, 0x681b, 0x001d, 0x7067, 0x0001, 0x781b, 0x0047, 0x007c,
+	0x7830, 0xa084, 0x00c0, 0x00c0, 0x43d2, 0x7808, 0xc08c, 0x780a,
 	0x0005, 0x0005, 0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, 0x00c0,
-	0x437f, 0x2001, 0x4e05, 0x2004, 0xd0e4, 0x00c0, 0x437d, 0x7804,
+	0x43cf, 0x2001, 0x4f05, 0x2004, 0xd0e4, 0x00c0, 0x43cd, 0x7804,
 	0xa084, 0xff1f, 0xa085, 0x00e0, 0x7806, 0xa006, 0x007c, 0x7808,
 	0xc08d, 0x780a, 0x007c, 0x7808, 0xc08d, 0x780a, 0x007c, 0x7830,
-	0xa084, 0x0040, 0x00c0, 0x4387, 0x2001, 0x4e04, 0x2004, 0xd0ec,
-	0x0040, 0x4396, 0xb284, 0x0300, 0x0078, 0x4398, 0xb284, 0x0400,
-	0x0040, 0x439e, 0x0098, 0x43a2, 0x0078, 0x43a0, 0x00a8, 0x43a2,
+	0xa084, 0x0040, 0x00c0, 0x43d7, 0x2001, 0x4f04, 0x2004, 0xd0ec,
+	0x0040, 0x43e6, 0xb284, 0x0300, 0x0078, 0x43e8, 0xb284, 0x0400,
+	0x0040, 0x43ee, 0x0098, 0x43f2, 0x0078, 0x43f0, 0x00a8, 0x43f2,
 	0x78ac, 0x007c, 0x7808, 0xa084, 0xfffd, 0x780a, 0x0005, 0x0005,
-	0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, 0x0040, 0x43c5, 0x007e,
-	0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x43bb, 0xb284,
-	0x0300, 0x0078, 0x43bd, 0xb284, 0x0400, 0x0040, 0x43c3, 0x0098,
-	0x43bf, 0x0078, 0x43c5, 0x00a8, 0x43c3, 0x78ac, 0x007e, 0x7808,
+	0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, 0x0040, 0x4415, 0x007e,
+	0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x440b, 0xb284,
+	0x0300, 0x0078, 0x440d, 0xb284, 0x0400, 0x0040, 0x4413, 0x0098,
+	0x440f, 0x0078, 0x4415, 0x00a8, 0x4413, 0x78ac, 0x007e, 0x7808,
 	0xa085, 0x0002, 0x780a, 0x007f, 0x007c, 0xa784, 0x0001, 0x00c0,
-	0x3770, 0xa784, 0x0070, 0x0040, 0x43dd, 0x0c7e, 0x2d60, 0x2f68,
-	0x1078, 0x28df, 0x2d78, 0x2c68, 0x0c7f, 0xa784, 0x0008, 0x0040,
-	0x43ea, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x3770,
-	0x0078, 0x430d, 0xa784, 0x0004, 0x0040, 0x4419, 0x78b8, 0xa084,
-	0x4001, 0x0040, 0x4419, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003,
-	0x0040, 0x3770, 0x78e4, 0xa084, 0x0007, 0xa086, 0x0001, 0x00c0,
-	0x4419, 0x78c0, 0xa685, 0x4800, 0x2030, 0x7e5a, 0x781b, 0x00f9,
-	0x007c, 0x784b, 0x0008, 0x6818, 0xd0fc, 0x0040, 0x4416, 0x681b,
-	0x0015, 0xd6f4, 0x0040, 0x4416, 0x681b, 0x0007, 0x1078, 0x4319,
+	0x37b9, 0xa784, 0x0070, 0x0040, 0x442d, 0x0c7e, 0x2d60, 0x2f68,
+	0x1078, 0x2926, 0x2d78, 0x2c68, 0x0c7f, 0xa784, 0x0008, 0x0040,
+	0x443a, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x37b9,
+	0x0078, 0x435d, 0xa784, 0x0004, 0x0040, 0x4469, 0x78b8, 0xa084,
+	0x4001, 0x0040, 0x4469, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003,
+	0x0040, 0x37b9, 0x78e4, 0xa084, 0x0007, 0xa086, 0x0001, 0x00c0,
+	0x4469, 0x78c0, 0xa685, 0x4800, 0x2030, 0x7e5a, 0x781b, 0x00f9,
+	0x007c, 0x784b, 0x0008, 0x6818, 0xd0fc, 0x0040, 0x4466, 0x681b,
+	0x0015, 0xd6f4, 0x0040, 0x4466, 0x681b, 0x0007, 0x1078, 0x4369,
 	0x007c, 0x681b, 0x0003, 0x7858, 0xa084, 0x3f00, 0x681e, 0x682f,
 	0x0000, 0x6833, 0x0000, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003,
-	0x0040, 0x3066, 0x007e, 0x2001, 0x4e04, 0x2004, 0xd0ec, 0x007f,
-	0x0040, 0x4436, 0xb284, 0x0300, 0x0078, 0x4438, 0xb284, 0x0400,
-	0x0040, 0x443e, 0x0018, 0x29c1, 0x0078, 0x4440, 0x0028, 0x29c1,
-	0x0078, 0x40bc, 0x6b14, 0x8307, 0xa084, 0x000f, 0x8003, 0x8003,
-	0x8003, 0xd3fc, 0x0040, 0x4450, 0xa080, 0x5340, 0x0078, 0x4452,
-	0xa080, 0x52c0, 0x2060, 0x2048, 0x705a, 0x2a60, 0x007c, 0x0020,
+	0x0040, 0x30af, 0x007e, 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f,
+	0x0040, 0x4486, 0xb284, 0x0300, 0x0078, 0x4488, 0xb284, 0x0400,
+	0x0040, 0x448e, 0x0018, 0x2a08, 0x0078, 0x4490, 0x0028, 0x2a08,
+	0x0078, 0x410c, 0x6b14, 0x8307, 0xa084, 0x000f, 0x8003, 0x8003,
+	0x8003, 0xd3fc, 0x0040, 0x44a0, 0xa080, 0x5440, 0x0078, 0x44a2,
+	0xa080, 0x53c0, 0x2060, 0x2048, 0x705a, 0x2a60, 0x007c, 0x0020,
 	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
 	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
 	0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
@@ -1763,255 +1773,276 @@
 	0x0016, 0x7944, 0x8421, 0xa020, 0xa532, 0x84a1, 0x0016, 0x7944,
 	0x8421, 0xa0df, 0x9532, 0x84a1, 0x0016, 0x0000, 0x127e, 0x70d4,
 	0xa084, 0x4600, 0x8004, 0x2090, 0x7204, 0x7008, 0xc09c, 0xa205,
-	0x00c0, 0x45a2, 0x720c, 0x82ff, 0x0040, 0x459d, 0x8aff, 0x00c0,
-	0x45a2, 0x7200, 0xd284, 0x00c0, 0x45a2, 0x7003, 0x0008, 0x127f,
+	0x00c0, 0x4602, 0x720c, 0x82ff, 0x0040, 0x45ed, 0x8aff, 0x00c0,
+	0x4602, 0x7200, 0xd284, 0x00c0, 0x4602, 0x7804, 0xd0cc, 0x0040,
+	0x45f3, 0x1078, 0x4acc, 0x7023, 0x0000, 0x7027, 0x0000, 0x7000,
+	0xd084, 0x0040, 0x45fd, 0x7007, 0x0004, 0x7003, 0x0008, 0x127f,
 	0x2000, 0x007c, 0x7000, 0xa084, 0x0003, 0x7002, 0xc69c, 0xd084,
-	0x0040, 0x45e5, 0x7108, 0x0005, 0x7008, 0xa106, 0x00c0, 0x45aa,
-	0xa184, 0x0003, 0x0040, 0x4616, 0xa184, 0x01e0, 0x00c0, 0x4616,
-	0xd1f4, 0x00c0, 0x45aa, 0xa184, 0x3000, 0xa086, 0x1000, 0x0040,
-	0x45aa, 0x2011, 0x0180, 0x710c, 0x8211, 0x0040, 0x45cf, 0x7008,
-	0xd0f4, 0x00c0, 0x45aa, 0x700c, 0xa106, 0x0040, 0x45c4, 0x7007,
-	0x0012, 0x7108, 0x0005, 0x7008, 0xa106, 0x00c0, 0x45d1, 0xa184,
-	0x0003, 0x0040, 0x4616, 0xd194, 0x0040, 0x45d1, 0xd1f4, 0x0040,
-	0x4616, 0x7007, 0x0002, 0x0078, 0x45aa, 0x7108, 0xd1fc, 0x0040,
-	0x45f0, 0x1078, 0x4769, 0x8aff, 0x0040, 0x458c, 0x0078, 0x45e5,
-	0x700c, 0xa08c, 0x03ff, 0x0040, 0x461b, 0x7004, 0xd084, 0x0040,
-	0x460d, 0x7014, 0xa005, 0x00c0, 0x4609, 0x7010, 0x7310, 0xa306,
-	0x00c0, 0x45fd, 0x2300, 0xa005, 0x0040, 0x460d, 0xa102, 0x00c8,
-	0x45e5, 0x7007, 0x0010, 0x0078, 0x4616, 0x8aff, 0x0040, 0x461b,
-	0x1078, 0x4970, 0x00c0, 0x4610, 0x0040, 0x45e5, 0x1078, 0x46b4,
-	0x127f, 0x2000, 0x007c, 0x7204, 0x7108, 0xc19c, 0x8103, 0x00c8,
-	0x462a, 0x7007, 0x0002, 0x0078, 0x461b, 0x7003, 0x0008, 0x127f,
-	0x2000, 0x007c, 0xa205, 0x00c0, 0x4616, 0x7003, 0x0008, 0x127f,
-	0x2000, 0x007c, 0x6428, 0x84ff, 0x0040, 0x465e, 0x2c70, 0x7004,
-	0xa0bc, 0x000f, 0xa7b8, 0x466e, 0x273c, 0x87fb, 0x00c0, 0x464c,
-	0x0048, 0x4644, 0x1078, 0x296b, 0x609c, 0xa075, 0x0040, 0x465e,
-	0x0078, 0x4637, 0x2039, 0x4663, 0x2704, 0xae68, 0x6808, 0xa630,
-	0x680c, 0xa529, 0x8421, 0x0040, 0x465e, 0x8738, 0x2704, 0xa005,
-	0x00c0, 0x464d, 0x709c, 0xa075, 0x00c0, 0x4637, 0x007c, 0x0000,
-	0x0005, 0x0009, 0x000d, 0x0011, 0x0015, 0x0019, 0x001d, 0x0000,
-	0x0003, 0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0000, 0x4663,
-	0x4660, 0x0000, 0x0000, 0x8000, 0x0000, 0x4663, 0x0000, 0x466b,
-	0x4668, 0x0000, 0x0000, 0x0000, 0x0000, 0x466b, 0x0000, 0x4666,
-	0x4666, 0x0000, 0x0000, 0x8000, 0x0000, 0x4666, 0x0000, 0x466c,
-	0x466c, 0x0000, 0x0000, 0x0000, 0x0000, 0x466c, 0x2079, 0x4e00,
-	0x2071, 0x0010, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0001,
-	0x7810, 0xd0ec, 0x0040, 0x46a2, 0x2009, 0x0001, 0x2071, 0x0020,
-	0x0078, 0x46a6, 0x2009, 0x0002, 0x2071, 0x0050, 0x7007, 0x000a,
-	0x7007, 0x0002, 0x7003, 0x0000, 0x8109, 0x0040, 0x46b3, 0x2071,
-	0x0020, 0x0078, 0x46a6, 0x007c, 0x7004, 0x8004, 0x00c8, 0x473d,
-	0x7108, 0x7008, 0xa106, 0x00c0, 0x46b8, 0xa184, 0x01e0, 0x0040,
-	0x46c5, 0x1078, 0x47ac, 0x0078, 0x4765, 0x7007, 0x0012, 0x2019,
-	0x0000, 0x7108, 0x7008, 0xa106, 0x00c0, 0x46c9, 0xa184, 0x01e0,
-	0x0040, 0x46d6, 0x1078, 0x47ac, 0x0078, 0x4765, 0x7810, 0xd0ec,
-	0x0040, 0x46f0, 0x2001, 0x04fd, 0x2004, 0xa086, 0x0003, 0x00c0,
-	0x46f4, 0xa184, 0x4000, 0x0040, 0x46f8, 0xa382, 0x0003, 0x00c8,
-	0x46f8, 0xa184, 0x0004, 0x0040, 0x46c9, 0x8318, 0x0078, 0x46c9,
-	0x7814, 0xd0ec, 0x00c0, 0x46f8, 0xa184, 0x4000, 0x00c0, 0x46c9,
-	0xa19c, 0x300c, 0xa386, 0x2004, 0x0040, 0x4715, 0xa386, 0x0008,
-	0x0040, 0x4720, 0x7004, 0xd084, 0x00c0, 0x4711, 0x7108, 0x7008,
-	0xa106, 0x00c0, 0x4706, 0xa184, 0x0003, 0x0040, 0x4711, 0x0078,
-	0x47ac, 0xa386, 0x200c, 0x00c0, 0x46c9, 0x7200, 0x8204, 0x0048,
-	0x4720, 0x730c, 0xa384, 0x03ff, 0x0040, 0x4720, 0x1078, 0x296b,
-	0x7108, 0x7008, 0xa106, 0x00c0, 0x4720, 0xa184, 0x01e0, 0x0040,
-	0x472d, 0x1078, 0x47ac, 0x0078, 0x4765, 0x7007, 0x0012, 0x7000,
-	0xd084, 0x00c0, 0x473d, 0x7310, 0x7014, 0xa305, 0x0040, 0x473d,
-	0x710c, 0xa184, 0x03ff, 0x00c0, 0x46b4, 0x7108, 0x7008, 0xa106,
-	0x00c0, 0x473d, 0xa184, 0x01e0, 0x0040, 0x474a, 0x1078, 0x47ac,
-	0x0078, 0x4765, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xd09c,
-	0x00c0, 0x474e, 0x7108, 0x7008, 0xa106, 0x00c0, 0x4752, 0xa184,
-	0x01e0, 0x0040, 0x475f, 0x1078, 0x47ac, 0x0078, 0x4765, 0x7007,
-	0x0012, 0x7108, 0x8103, 0x0048, 0x4752, 0x7003, 0x0008, 0x007c,
-	0x7108, 0xa184, 0x01e0, 0x00c0, 0x47ac, 0x7108, 0xa184, 0x01e0,
-	0x00c0, 0x47ac, 0xa184, 0x0007, 0x0079, 0x4776, 0x4780, 0x4790,
-	0x477e, 0x4790, 0x477e, 0x47ee, 0x477e, 0x47ec, 0x1078, 0x296b,
-	0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x8aff, 0x00c0, 0x478b,
-	0x2049, 0x0000, 0x007c, 0x1078, 0x4970, 0x00c0, 0x478b, 0x007c,
-	0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x7004, 0xd084, 0x00c0,
-	0x47a4, 0x7108, 0x7008, 0xa106, 0x00c0, 0x4799, 0xa184, 0x0003,
-	0x0040, 0x47a4, 0x0078, 0x47ac, 0x8aff, 0x0040, 0x47ab, 0x1078,
-	0x4970, 0x00c0, 0x47a7, 0x007c, 0x7007, 0x0012, 0x7108, 0x00e0,
-	0x47af, 0x2091, 0x6000, 0x00e0, 0x47b3, 0x2091, 0x6000, 0x7007,
-	0x0012, 0x7007, 0x0008, 0x7004, 0xd09c, 0x00c0, 0x47bb, 0x7007,
-	0x0012, 0x7108, 0xd1fc, 0x00c0, 0x47bf, 0x7003, 0x0000, 0x7000,
-	0xa005, 0x00c0, 0x47d3, 0x7004, 0xa005, 0x00c0, 0x47d3, 0x700c,
-	0xa005, 0x0040, 0x47d5, 0x0078, 0x47b7, 0x2049, 0x0000, 0xb284,
-	0x0100, 0x0040, 0x47df, 0x2001, 0x0000, 0x0078, 0x47e1, 0x2001,
-	0x0001, 0x1078, 0x4212, 0x681b, 0x0002, 0x2051, 0x0000, 0x007c,
-	0x1078, 0x296b, 0x1078, 0x296b, 0x1078, 0x4836, 0x7210, 0x7114,
-	0x700c, 0xa09c, 0x03ff, 0x2800, 0xa300, 0xa211, 0xa189, 0x0000,
-	0x1078, 0x4836, 0x2704, 0x2c58, 0xac60, 0x6308, 0x2200, 0xa322,
-	0x630c, 0x2100, 0xa31b, 0x2400, 0xa305, 0x0040, 0x4811, 0x00c8,
-	0x4811, 0x8412, 0x8210, 0x830a, 0xa189, 0x0000, 0x2b60, 0x0078,
-	0x47f8, 0x2b60, 0x8a07, 0x007e, 0x6004, 0xa084, 0x0008, 0x0040,
-	0x481d, 0xa7ba, 0x4668, 0x0078, 0x481f, 0xa7ba, 0x4660, 0x007f,
-	0xa73d, 0x2c00, 0x6886, 0x6f8a, 0x6c92, 0x6b8e, 0x7108, 0x7008,
-	0xa106, 0x00c0, 0x4826, 0xa184, 0x01e0, 0x0040, 0x4831, 0x1078,
-	0x47ac, 0x7007, 0x0012, 0x1078, 0x46b4, 0x007c, 0x8a50, 0x8739,
-	0x2704, 0xa004, 0x00c0, 0x484a, 0x6000, 0xa064, 0x00c0, 0x4841,
-	0x2d60, 0x6004, 0xa084, 0x000f, 0xa080, 0x467e, 0x203c, 0x87fb,
-	0x1040, 0x296b, 0x007c, 0x127e, 0x0d7e, 0x70d4, 0xa084, 0x4600,
-	0x8004, 0x2090, 0x0d7f, 0x6884, 0x2060, 0x6888, 0x6b8c, 0x6c90,
-	0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff, 0x007e, 0x6804, 0xa084,
-	0x0008, 0x007f, 0x0040, 0x4868, 0xa0b8, 0x4668, 0x0078, 0x486a,
-	0xa0b8, 0x4660, 0xb284, 0x0100, 0x0040, 0x4871, 0x7e20, 0x0078,
-	0x4872, 0x7e24, 0xa6b5, 0x000c, 0x681c, 0xd0b4, 0x0040, 0x4879,
-	0xc685, 0x2400, 0xa305, 0x0040, 0x48a3, 0x2c58, 0x2704, 0x6104,
-	0xac60, 0x6000, 0xa400, 0x701a, 0x6004, 0xa301, 0x701e, 0xa184,
-	0x0008, 0x0040, 0x4893, 0x6010, 0xa081, 0x0000, 0x7022, 0x6014,
-	0xa081, 0x0000, 0x7026, 0x6208, 0x2400, 0xa202, 0x7012, 0x620c,
-	0x2300, 0xa203, 0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x1078,
-	0x499b, 0x0078, 0x48a5, 0x1078, 0x4970, 0x00c0, 0x48a3, 0x127f,
-	0x2000, 0x007c, 0x127e, 0x0d7e, 0x70d4, 0xa084, 0x4600, 0x8004,
-	0x2090, 0x0d7f, 0x7007, 0x0004, 0x7004, 0xd094, 0x00c0, 0x48b4,
-	0x7003, 0x0008, 0x127f, 0x2000, 0x007c, 0x127e, 0x0d7e, 0x70d4,
-	0xa084, 0x4600, 0x8004, 0x007e, 0x2090, 0x007f, 0x0d7f, 0x7e20,
-	0xb284, 0x0100, 0x00c0, 0x48cd, 0x7e24, 0xa6b5, 0x000c, 0x681c,
-	0xd0ac, 0x00c0, 0x48d8, 0xc685, 0x7003, 0x0000, 0x7007, 0x0004,
-	0x6828, 0x2050, 0x2d60, 0x6004, 0xa0bc, 0x000f, 0xa7b8, 0x466e,
-	0x273c, 0x87fb, 0x00c0, 0x48ee, 0x0048, 0x48e8, 0x1078, 0x296b,
-	0x689c, 0xa065, 0x0040, 0x48f2, 0x0078, 0x48db, 0x1078, 0x4970,
-	0x00c0, 0x48ee, 0x127f, 0x2000, 0x007c, 0x127e, 0x007e, 0x017e,
+	0x0040, 0x465b, 0x7108, 0x0005, 0x7008, 0xa106, 0x00c0, 0x460a,
+	0xa184, 0x0003, 0x0040, 0x468c, 0xa184, 0x01e0, 0x00c0, 0x468c,
+	0xd1f4, 0x00c0, 0x460a, 0xa184, 0x3000, 0xa086, 0x1000, 0x0040,
+	0x460a, 0x2001, 0x4f05, 0x2004, 0xd0e4, 0x0040, 0x4637, 0x2011,
+	0x0180, 0x710c, 0x8211, 0x0040, 0x4645, 0x7008, 0xd0f4, 0x00c0,
+	0x460a, 0x700c, 0xa106, 0x0040, 0x462a, 0x0078, 0x4627, 0x2011,
+	0x0180, 0x710c, 0x8211, 0x0040, 0x4645, 0x7008, 0xd0f4, 0x00c0,
+	0x460a, 0x700c, 0xa106, 0x0040, 0x463a, 0x7007, 0x0012, 0x7108,
+	0x0005, 0x7008, 0xa106, 0x00c0, 0x4647, 0xa184, 0x0003, 0x0040,
+	0x468c, 0xd194, 0x0040, 0x4647, 0xd1f4, 0x0040, 0x468c, 0x7007,
+	0x0002, 0x0078, 0x460a, 0x7108, 0xd1fc, 0x0040, 0x4666, 0x1078,
+	0x47ed, 0x8aff, 0x0040, 0x45dc, 0x0078, 0x465b, 0x700c, 0xa08c,
+	0x03ff, 0x0040, 0x4691, 0x7004, 0xd084, 0x0040, 0x4683, 0x7014,
+	0xa005, 0x00c0, 0x467f, 0x7010, 0x7310, 0xa306, 0x00c0, 0x4673,
+	0x2300, 0xa005, 0x0040, 0x4683, 0xa102, 0x00c8, 0x465b, 0x7007,
+	0x0010, 0x0078, 0x468c, 0x8aff, 0x0040, 0x4691, 0x1078, 0x49f2,
+	0x00c0, 0x4686, 0x0040, 0x465b, 0x1078, 0x4738, 0x127f, 0x2000,
+	0x007c, 0x7204, 0x7108, 0xc19c, 0x8103, 0x00c8, 0x46a0, 0x7007,
+	0x0002, 0x0078, 0x4691, 0x7003, 0x0008, 0x127f, 0x2000, 0x007c,
+	0xa205, 0x00c0, 0x468c, 0x7023, 0x0000, 0x7027, 0x0000, 0x7003,
+	0x0008, 0x007e, 0x2001, 0x4f01, 0x2004, 0xd0cc, 0x0040, 0x46b2,
+	0x1078, 0x4acc, 0x007f, 0x127f, 0x2000, 0x007c, 0x6428, 0x84ff,
+	0x0040, 0x46e2, 0x2c70, 0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x46f2,
+	0x273c, 0x87fb, 0x00c0, 0x46d0, 0x0048, 0x46c8, 0x1078, 0x29b2,
+	0x609c, 0xa075, 0x0040, 0x46e2, 0x0078, 0x46bb, 0x2039, 0x46e7,
+	0x2704, 0xae68, 0x6808, 0xa630, 0x680c, 0xa529, 0x8421, 0x0040,
+	0x46e2, 0x8738, 0x2704, 0xa005, 0x00c0, 0x46d1, 0x709c, 0xa075,
+	0x00c0, 0x46bb, 0x007c, 0x0000, 0x0005, 0x0009, 0x000d, 0x0011,
+	0x0015, 0x0019, 0x001d, 0x0000, 0x0003, 0x0009, 0x000f, 0x0015,
+	0x001b, 0x0000, 0x0000, 0x46e7, 0x46e4, 0x0000, 0x0000, 0x8000,
+	0x0000, 0x46e7, 0x0000, 0x46ef, 0x46ec, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x46ef, 0x0000, 0x46ea, 0x46ea, 0x0000, 0x0000, 0x8000,
+	0x0000, 0x46ea, 0x0000, 0x46f0, 0x46f0, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x46f0, 0x2079, 0x4f00, 0x2071, 0x0010, 0x7007, 0x000a,
+	0x7007, 0x0002, 0x7003, 0x0001, 0x7810, 0xd0ec, 0x0040, 0x4726,
+	0x2009, 0x0001, 0x2071, 0x0020, 0x0078, 0x472a, 0x2009, 0x0002,
+	0x2071, 0x0050, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0000,
+	0x8109, 0x0040, 0x4737, 0x2071, 0x0020, 0x0078, 0x472a, 0x007c,
+	0x7004, 0x8004, 0x00c8, 0x47c1, 0x7108, 0x7008, 0xa106, 0x00c0,
+	0x473c, 0xa184, 0x01e0, 0x0040, 0x4749, 0x1078, 0x4830, 0x0078,
+	0x47e9, 0x7007, 0x0012, 0x2019, 0x0000, 0x7108, 0x7008, 0xa106,
+	0x00c0, 0x474d, 0xa184, 0x01e0, 0x0040, 0x475a, 0x1078, 0x4830,
+	0x0078, 0x47e9, 0x7810, 0xd0ec, 0x0040, 0x4774, 0x2001, 0x04fd,
+	0x2004, 0xa086, 0x0003, 0x00c0, 0x4778, 0xa184, 0x4000, 0x0040,
+	0x477c, 0xa382, 0x0003, 0x00c8, 0x477c, 0xa184, 0x0004, 0x0040,
+	0x474d, 0x8318, 0x0078, 0x474d, 0x7814, 0xd0ec, 0x00c0, 0x477c,
+	0xa184, 0x4000, 0x00c0, 0x474d, 0xa19c, 0x300c, 0xa386, 0x2004,
+	0x0040, 0x4799, 0xa386, 0x0008, 0x0040, 0x47a4, 0x7004, 0xd084,
+	0x00c0, 0x4795, 0x7108, 0x7008, 0xa106, 0x00c0, 0x478a, 0xa184,
+	0x0003, 0x0040, 0x4795, 0x0078, 0x4830, 0xa386, 0x200c, 0x00c0,
+	0x474d, 0x7200, 0x8204, 0x0048, 0x47a4, 0x730c, 0xa384, 0x03ff,
+	0x0040, 0x47a4, 0x1078, 0x29b2, 0x7108, 0x7008, 0xa106, 0x00c0,
+	0x47a4, 0xa184, 0x01e0, 0x0040, 0x47b1, 0x1078, 0x4830, 0x0078,
+	0x47e9, 0x7007, 0x0012, 0x7000, 0xd084, 0x00c0, 0x47c1, 0x7310,
+	0x7014, 0xa305, 0x0040, 0x47c1, 0x710c, 0xa184, 0x03ff, 0x00c0,
+	0x4738, 0x7108, 0x7008, 0xa106, 0x00c0, 0x47c1, 0xa184, 0x01e0,
+	0x0040, 0x47ce, 0x1078, 0x4830, 0x0078, 0x47e9, 0x7007, 0x0012,
+	0x7007, 0x0008, 0x7004, 0xd09c, 0x00c0, 0x47d2, 0x7108, 0x7008,
+	0xa106, 0x00c0, 0x47d6, 0xa184, 0x01e0, 0x0040, 0x47e3, 0x1078,
+	0x4830, 0x0078, 0x47e9, 0x7007, 0x0012, 0x7108, 0x8103, 0x0048,
+	0x47d6, 0x7003, 0x0008, 0x007c, 0x7108, 0xa184, 0x01e0, 0x00c0,
+	0x4830, 0x7108, 0xa184, 0x01e0, 0x00c0, 0x4830, 0xa184, 0x0007,
+	0x0079, 0x47fa, 0x4804, 0x4814, 0x4802, 0x4814, 0x4802, 0x4872,
+	0x4802, 0x4870, 0x1078, 0x29b2, 0x7004, 0xa084, 0x0010, 0xc08d,
+	0x7006, 0x8aff, 0x00c0, 0x480f, 0x2049, 0x0000, 0x007c, 0x1078,
+	0x49f2, 0x00c0, 0x480f, 0x007c, 0x7004, 0xa084, 0x0010, 0xc08d,
+	0x7006, 0x7004, 0xd084, 0x00c0, 0x4828, 0x7108, 0x7008, 0xa106,
+	0x00c0, 0x481d, 0xa184, 0x0003, 0x0040, 0x4828, 0x0078, 0x4830,
+	0x8aff, 0x0040, 0x482f, 0x1078, 0x49f2, 0x00c0, 0x482b, 0x007c,
+	0x7007, 0x0012, 0x7108, 0x00e0, 0x4833, 0x2091, 0x6000, 0x00e0,
+	0x4837, 0x2091, 0x6000, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004,
+	0xd09c, 0x00c0, 0x483f, 0x7007, 0x0012, 0x7108, 0xd1fc, 0x00c0,
+	0x4843, 0x7003, 0x0000, 0x7000, 0xa005, 0x00c0, 0x4857, 0x7004,
+	0xa005, 0x00c0, 0x4857, 0x700c, 0xa005, 0x0040, 0x4859, 0x0078,
+	0x483b, 0x2049, 0x0000, 0xb284, 0x0100, 0x0040, 0x4863, 0x2001,
+	0x0000, 0x0078, 0x4865, 0x2001, 0x0001, 0x1078, 0x4262, 0x681b,
+	0x0002, 0x2051, 0x0000, 0x007c, 0x1078, 0x29b2, 0x1078, 0x29b2,
+	0x1078, 0x48b9, 0x7210, 0x7114, 0x700c, 0xa09c, 0x03ff, 0x2800,
+	0xa300, 0xa211, 0xa189, 0x0000, 0x1078, 0x48b9, 0x2704, 0x2c58,
+	0xac60, 0x6308, 0x2200, 0xa322, 0x630c, 0x2100, 0xa31b, 0x2400,
+	0xa305, 0x0040, 0x4895, 0x00c8, 0x4895, 0x8412, 0x8210, 0x830a,
+	0xa189, 0x0000, 0x2b60, 0x0078, 0x487c, 0x2b60, 0x8a07, 0x007e,
+	0x6004, 0xd09c, 0x0040, 0x48a0, 0xa7ba, 0x46ec, 0x0078, 0x48a2,
+	0xa7ba, 0x46e4, 0x007f, 0xa73d, 0x2c00, 0x6886, 0x6f8a, 0x6c92,
+	0x6b8e, 0x7108, 0x7008, 0xa106, 0x00c0, 0x48a9, 0xa184, 0x01e0,
+	0x0040, 0x48b4, 0x1078, 0x4830, 0x7007, 0x0012, 0x1078, 0x4738,
+	0x007c, 0x8a50, 0x8739, 0x2704, 0xa004, 0x00c0, 0x48cd, 0x6000,
+	0xa064, 0x00c0, 0x48c4, 0x2d60, 0x6004, 0xa084, 0x000f, 0xa080,
+	0x4702, 0x203c, 0x87fb, 0x1040, 0x29b2, 0x007c, 0x127e, 0x0d7e,
+	0x70d4, 0xa084, 0x4600, 0x8004, 0x2090, 0x0d7f, 0x6884, 0x2060,
+	0x6888, 0x6b8c, 0x6c90, 0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff,
+	0x007e, 0x6804, 0xa084, 0x0008, 0x007f, 0x0040, 0x48eb, 0xa0b8,
+	0x46ec, 0x0078, 0x48ed, 0xa0b8, 0x46e4, 0xb284, 0x0100, 0x0040,
+	0x48f4, 0x7e20, 0x0078, 0x48f5, 0x7e24, 0xa6b5, 0x000c, 0x681c,
+	0xd0b4, 0x0040, 0x48fc, 0xc685, 0x2400, 0xa305, 0x0040, 0x4925,
+	0x2c58, 0x2704, 0x6104, 0xac60, 0x6000, 0xa400, 0x701a, 0x6004,
+	0xa301, 0x701e, 0xd19c, 0x0040, 0x4915, 0x6010, 0xa081, 0x0000,
+	0x7022, 0x6014, 0xa081, 0x0000, 0x7026, 0x6208, 0x2400, 0xa202,
+	0x7012, 0x620c, 0x2300, 0xa203, 0x7016, 0x7602, 0x7007, 0x0001,
+	0x2b60, 0x1078, 0x4a1c, 0x0078, 0x4927, 0x1078, 0x49f2, 0x00c0,
+	0x4925, 0x127f, 0x2000, 0x007c, 0x127e, 0x0d7e, 0x70d4, 0xa084,
+	0x4600, 0x8004, 0x2090, 0x0d7f, 0x7007, 0x0004, 0x7004, 0xd094,
+	0x00c0, 0x4936, 0x7003, 0x0008, 0x127f, 0x2000, 0x007c, 0x127e,
 	0x0d7e, 0x70d4, 0xa084, 0x4600, 0x8004, 0x007e, 0x2090, 0x007f,
-	0x7e20, 0xb284, 0x0100, 0x00c0, 0x4906, 0x7e24, 0x0d7f, 0x037f,
-	0x047f, 0xa6b5, 0x000c, 0x681c, 0xd0b4, 0x0040, 0x4914, 0xc685,
-	0x7003, 0x0000, 0x7007, 0x0004, 0x2049, 0x48f5, 0x6828, 0xa055,
-	0x0d7e, 0x0040, 0x496c, 0x2d70, 0x2e60, 0x7004, 0xa0bc, 0x000f,
-	0xa7b8, 0x466e, 0x273c, 0x87fb, 0x00c0, 0x4931, 0x0048, 0x492a,
-	0x1078, 0x296b, 0x709c, 0xa075, 0x2060, 0x0040, 0x496c, 0x0078,
-	0x491d, 0x2704, 0xae68, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0048,
-	0x494a, 0x8a51, 0x00c0, 0x493e, 0x1078, 0x296b, 0x8738, 0x2704,
-	0xa005, 0x00c0, 0x4932, 0x709c, 0xa075, 0x2060, 0x0040, 0x496c,
-	0x0078, 0x491d, 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x6908,
-	0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, 0x00c8, 0x4959, 0x1078,
-	0x296b, 0xb284, 0x0100, 0x0040, 0x4967, 0x2001, 0x4e04, 0x2004,
-	0xd0ec, 0x00c0, 0x4967, 0x2071, 0x0050, 0x0078, 0x4969, 0x2071,
-	0x0020, 0x0d7f, 0x0078, 0x4879, 0x0d7f, 0x127f, 0x2000, 0x007c,
-	0x7008, 0x007e, 0xa084, 0x01e0, 0x007f, 0x0040, 0x4979, 0xa006,
-	0x007c, 0xa084, 0x0003, 0xa086, 0x0003, 0x00c0, 0x4980, 0x007c,
-	0x2704, 0xac78, 0x7800, 0x701a, 0x7804, 0x701e, 0x7808, 0x7012,
-	0x780c, 0x7016, 0x6004, 0xa084, 0x0008, 0x0040, 0x4993, 0x7810,
-	0x7022, 0x7814, 0x7026, 0x7602, 0x7004, 0xa084, 0x0010, 0xc085,
-	0x7006, 0x2079, 0x4e00, 0x8a51, 0x0040, 0x49bf, 0x8738, 0x2704,
-	0xa005, 0x00c0, 0x49b1, 0x609c, 0xa005, 0x0040, 0x49c0, 0x2060,
-	0x6004, 0xa084, 0x000f, 0xa080, 0x466e, 0x203c, 0x87fb, 0x1040,
-	0x296b, 0x7008, 0x007e, 0xa084, 0x01e0, 0x007f, 0x0040, 0x49bb,
-	0xa006, 0x0078, 0x49c0, 0xa084, 0x0003, 0xa086, 0x0003, 0x007c,
-	0x2051, 0x0000, 0x007c, 0x127e, 0x007e, 0x0d7e, 0x70d4, 0xa084,
-	0x4600, 0x8004, 0x2090, 0x0d7f, 0x087f, 0x7108, 0xa184, 0x0003,
-	0x00c0, 0x49d8, 0x6828, 0xa005, 0x0040, 0x49e8, 0x0078, 0x45a2,
-	0x7108, 0xd1fc, 0x0040, 0x49e0, 0x1078, 0x4769, 0x0078, 0x49cd,
-	0x7007, 0x0010, 0x7108, 0xd1fc, 0x0040, 0x49e2, 0x1078, 0x4769,
-	0x7008, 0xa086, 0x0008, 0x00c0, 0x49cd, 0x7000, 0xa005, 0x00c0,
-	0x49cd, 0x7003, 0x0000, 0x2049, 0x0000, 0x127f, 0x2000, 0x007c,
-	0x127e, 0x147e, 0x137e, 0x157e, 0x0c7e, 0x0d7e, 0x70d4, 0xa084,
-	0x4600, 0x8004, 0x2090, 0x0d7f, 0x2049, 0x49f8, 0xad80, 0x0011,
-	0x20a0, 0xb284, 0x0100, 0x0040, 0x4a1b, 0x2001, 0x4e04, 0x2004,
-	0xd0ec, 0x0040, 0x4a17, 0x2099, 0x0031, 0x0078, 0x4a1d, 0x2099,
-	0x0032, 0x0078, 0x4a1d, 0x2099, 0x0031, 0x700c, 0xa084, 0x03ff,
-	0x682a, 0x7007, 0x0008, 0x7007, 0x0002, 0x7003, 0x0001, 0x0040,
-	0x4a2c, 0x8000, 0x80ac, 0x53a5, 0x700c, 0xa084, 0x03ff, 0x0040,
-	0x4a38, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x4a33,
-	0x0c7f, 0x2049, 0x0000, 0x7003, 0x0000, 0x157f, 0x137f, 0x147f,
-	0x127f, 0x2000, 0x007c, 0x2091, 0x8000, 0x2091, 0x6000, 0x78ac,
-	0xa005, 0x00c0, 0x4a5a, 0x7974, 0x70d0, 0xa106, 0x00c0, 0x4a5a,
-	0x781c, 0xa005, 0x0040, 0x4a5a, 0x781f, 0x0000, 0x0068, 0x4a5a,
-	0x2091, 0x4080, 0x7830, 0x8001, 0x7832, 0x00c0, 0x4ae2, 0x7834,
-	0x7832, 0x7810, 0xd0ec, 0x00c0, 0x4adb, 0x2061, 0x73c0, 0x2069,
-	0x4e80, 0xc7fd, 0x68d0, 0xa005, 0x0040, 0x4a74, 0x8001, 0x68d2,
-	0x00c0, 0x4a74, 0x1078, 0x4cb0, 0x6800, 0xa084, 0x000f, 0x0040,
-	0x4a89, 0xa086, 0x0001, 0x0040, 0x4a89, 0x6844, 0xa00d, 0x0040,
-	0x4a89, 0x2104, 0xa005, 0x0040, 0x4a89, 0x8001, 0x200a, 0x0040,
-	0x4c23, 0x6814, 0xa005, 0x0040, 0x4aae, 0x8001, 0x6816, 0x00c0,
-	0x4aae, 0x68a7, 0x0001, 0x0f7e, 0xd7fc, 0x00c0, 0x4aa3, 0x7810,
-	0xd0ec, 0x0040, 0x4a9f, 0x2079, 0x0100, 0x0078, 0x4aa5, 0x2079,
-	0x0200, 0x0078, 0x4aa5, 0x2079, 0x0100, 0x1078, 0x4383, 0x0f7f,
-	0x6864, 0xa005, 0x0040, 0x4aae, 0x1078, 0x2628, 0x6880, 0xa005,
-	0x0040, 0x4abb, 0x8001, 0x6882, 0x00c0, 0x4abb, 0x6867, 0x0000,
-	0x68d4, 0xc0dd, 0x68d6, 0x68d4, 0xd0fc, 0x0040, 0x4ad8, 0xc0fc,
-	0x68d6, 0x20a9, 0x0200, 0x6034, 0xa005, 0x0040, 0x4ad4, 0x8001,
-	0x6036, 0x68d4, 0xc0fd, 0x68d6, 0x00c0, 0x4ad4, 0x6010, 0xa005,
-	0x0040, 0x4ad4, 0x1078, 0x2628, 0xace0, 0x0010, 0x00f0, 0x4ac3,
-	0xd7fc, 0x0040, 0x4ae2, 0x2061, 0x53c0, 0x2069, 0x4e40, 0xc7fc,
-	0x0078, 0x4a6a, 0x1078, 0x4b1e, 0x7838, 0x8001, 0x783a, 0x00c0,
-	0x4b04, 0x783c, 0x783a, 0x2061, 0x53c0, 0x2069, 0x4e40, 0xc7fc,
-	0x680c, 0xa005, 0x0040, 0x4af6, 0x1078, 0x4b88, 0xd7fc, 0x00c0,
-	0x4b04, 0x7810, 0xd0ec, 0x00c0, 0x4b04, 0x2061, 0x73c0, 0x2069,
-	0x4e80, 0xc7fd, 0x0078, 0x4af0, 0x7814, 0xd0e4, 0x00c0, 0x4b08,
-	0x7810, 0xd0cc, 0x0040, 0x4b1b, 0xd0ac, 0x00c0, 0x4b14, 0xd0a4,
-	0x0040, 0x4b1b, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0068, 0x4b1a,
-	0x1078, 0x2395, 0x007c, 0x2091, 0x8001, 0x007c, 0x7840, 0x8001,
-	0x7842, 0x00c0, 0x4b87, 0x7844, 0x7842, 0x2069, 0x4e40, 0xc7fc,
-	0x7810, 0x2079, 0x0200, 0xd0ec, 0x0040, 0x4b30, 0x2079, 0x0100,
-	0x68d8, 0xa005, 0x0040, 0x4b3c, 0x7de0, 0xa504, 0x00c0, 0x4b3c,
-	0x68da, 0x68d4, 0xc0bc, 0x68d6, 0x2079, 0x4e00, 0x6810, 0xa005,
-	0x00c0, 0x4b44, 0x2001, 0x0101, 0x8001, 0x6812, 0xd7fc, 0x0040,
-	0x4b4d, 0xa080, 0x94d0, 0x0078, 0x4b4f, 0xa080, 0x93c0, 0x2040,
-	0x2004, 0xa065, 0x0040, 0x4b79, 0x6024, 0xa005, 0x0040, 0x4b75,
-	0x8001, 0x6026, 0x00c0, 0x4b75, 0x6800, 0xa005, 0x0040, 0x4b68,
-	0x684c, 0xac06, 0x00c0, 0x4b68, 0x1078, 0x4c23, 0x0078, 0x4b79,
-	0x6864, 0xa005, 0x0040, 0x4b70, 0x6027, 0x0001, 0x0078, 0x4b75,
-	0x1078, 0x4bd6, 0x2804, 0x0078, 0x4b51, 0x6000, 0x2c40, 0x0078,
-	0x4b51, 0xd7fc, 0x00c0, 0x4b87, 0x7810, 0xd0ec, 0x00c0, 0x4b87,
-	0x2069, 0x4e80, 0xc7fd, 0x2079, 0x0100, 0x0078, 0x4b30, 0x007c,
-	0x2009, 0x0000, 0x20a9, 0x0200, 0x6008, 0xd09c, 0x0040, 0x4bc2,
-	0x6024, 0xa005, 0x0040, 0x4b98, 0x8001, 0x6026, 0x0078, 0x4bc0,
-	0x6008, 0xc09c, 0xd084, 0x00c0, 0x4ba0, 0xd0ac, 0x0040, 0x4bba,
-	0x600a, 0x6004, 0xa005, 0x0040, 0x4bc2, 0x0d7e, 0x0c7e, 0x017e,
-	0x2068, 0x6010, 0x8001, 0x6012, 0x1078, 0x3dd0, 0x2d00, 0x2c68,
-	0x2060, 0x1078, 0x1e5b, 0x1078, 0x201d, 0x017f, 0x0c7f, 0x0d7f,
-	0x0078, 0x4bc2, 0xc0bd, 0x600a, 0xa18d, 0x0001, 0x0078, 0x4bc2,
-	0xa18d, 0x0100, 0xace0, 0x0010, 0x00f0, 0x4b8c, 0xa184, 0x0001,
-	0x0040, 0x4bd1, 0xa18c, 0xfffe, 0x690e, 0x1078, 0x2628, 0x0078,
-	0x4bd2, 0x690e, 0x007c, 0x00c0, 0x4bd2, 0x786c, 0x2c00, 0x687e,
-	0x6714, 0x6f76, 0x6017, 0x0000, 0x602b, 0x0000, 0x601b, 0x0006,
-	0x60b4, 0xa084, 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085,
-	0x0060, 0x6022, 0x6000, 0x2042, 0x1078, 0x1de4, 0x6818, 0xa005,
-	0x0040, 0x4bf4, 0x8001, 0x681a, 0x6808, 0xc0a4, 0x680a, 0x6810,
-	0x7908, 0x8109, 0x790a, 0x8001, 0x00d0, 0x4c00, 0x1078, 0x296b,
-	0x6812, 0x00c0, 0x4c06, 0x7910, 0xc1a5, 0x7912, 0x602f, 0x0000,
-	0x6033, 0x0000, 0x2c68, 0x1078, 0x202c, 0xd7fc, 0x00c0, 0x4c14,
-	0x2069, 0x4e40, 0x0078, 0x4c16, 0x2069, 0x4e80, 0x6910, 0xa184,
-	0x0100, 0x2001, 0x0006, 0x00c0, 0x4c20, 0x697a, 0x2001, 0x0004,
-	0x1078, 0x261c, 0x007c, 0x0d7e, 0x694c, 0x2160, 0xd7fc, 0x00c0,
-	0x4c35, 0x7810, 0xd0ec, 0x0040, 0x4c31, 0x2069, 0x0100, 0x0078,
-	0x4c37, 0x2069, 0x0200, 0x0078, 0x4c37, 0x2069, 0x0100, 0x1078,
-	0x28df, 0x601b, 0x0006, 0x6858, 0xa084, 0x3f00, 0x601e, 0x6020,
-	0xa084, 0x00ff, 0xa085, 0x0048, 0x6022, 0x602f, 0x0000, 0x6033,
-	0x0000, 0x6808, 0xa084, 0xfffd, 0x680a, 0x6830, 0xd0b4, 0x0040,
-	0x4c69, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, 0xd094, 0x0040,
-	0x4c5b, 0x00f0, 0x4c55, 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848,
-	0xd084, 0x0040, 0x4c65, 0x00f0, 0x4c5f, 0x20a9, 0x00fa, 0x00f0,
-	0x4c67, 0x681b, 0x0047, 0x0d7f, 0x6867, 0x0007, 0x007c, 0x2079,
-	0x4e00, 0x1078, 0x4ca3, 0x1078, 0x4c89, 0x1078, 0x4c96, 0x2009,
-	0x0002, 0x2069, 0x4e80, 0x680f, 0x0000, 0x6813, 0x0000, 0x6817,
-	0x0000, 0x8109, 0x0040, 0x4c88, 0x2069, 0x4e40, 0x0078, 0x4c7b,
-	0x007c, 0x7810, 0xd0ec, 0x0040, 0x4c91, 0x2019, 0x00cc, 0x0078,
-	0x4c93, 0x2019, 0x007b, 0x7b3a, 0x7b3e, 0x007c, 0x7814, 0xd0e4,
-	0x00c0, 0x4c9e, 0x2019, 0x0040, 0x0078, 0x4ca0, 0x2019, 0x0026,
-	0x7b42, 0x7b46, 0x007c, 0x7814, 0xd0e4, 0x00c0, 0x4cab, 0x2019,
-	0x3f94, 0x0078, 0x4cad, 0x2019, 0x2624, 0x7b32, 0x7b36, 0x007c,
-	0x6a50, 0xa285, 0x0000, 0x0040, 0x4cdc, 0x6954, 0x6bc0, 0xa300,
-	0x0c7e, 0x2164, 0x6304, 0x83ff, 0x00c0, 0x4cc8, 0x8211, 0x0040,
-	0x4ccc, 0x8108, 0xa11a, 0x0048, 0x4cb9, 0x69c0, 0x0078, 0x4cb9,
-	0x68d3, 0x000a, 0x0c7f, 0x007c, 0x6950, 0x6ac0, 0x2264, 0x602b,
-	0x0000, 0x602f, 0x0000, 0x6008, 0xc0b5, 0x600a, 0x8210, 0x8109,
-	0x00c0, 0x4cce, 0x6952, 0x0c7f, 0x007c, 0x00e0, 0x4cdd, 0x2091,
-	0x6000, 0x00e0, 0x4ce1, 0x2091, 0x6000, 0x70ec, 0xd0dc, 0x00c0,
-	0x4cee, 0xd0d4, 0x0040, 0x4d17, 0x0078, 0x4d1a, 0x2008, 0x7810,
-	0xd0ec, 0x0040, 0x4d01, 0xd1c4, 0x00c0, 0x4d39, 0x7814, 0xc0c5,
-	0x7816, 0x7810, 0xc0f5, 0x7812, 0xd0ec, 0x0040, 0x4d35, 0x0078,
-	0x4d31, 0xae8e, 0x0100, 0x0040, 0x4d0e, 0x7814, 0xc0f5, 0xc0c5,
-	0x7816, 0xd0d4, 0x00c0, 0x4d35, 0x0078, 0x4d31, 0x7814, 0xc0fd,
-	0xc0c5, 0x7816, 0xd0d4, 0x00c0, 0x4d35, 0x0078, 0x4d31, 0xd0e4,
-	0x0040, 0x4d37, 0x00e0, 0x4d1a, 0x2091, 0x6000, 0x2009, 0x000c,
-	0x00e0, 0x4d20, 0x2091, 0x6000, 0x8109, 0x00c0, 0x4d20, 0x70e4,
-	0xa084, 0x01ff, 0xa086, 0x01ff, 0x00c0, 0x4d31, 0x70ec, 0x0078,
-	0x4cee, 0x7804, 0xd08c, 0x0040, 0x4d37, 0x681f, 0x000c, 0x70a0,
-	0x70a2, 0x007c, 0x205b
+	0x0d7f, 0x7e20, 0xb284, 0x0100, 0x00c0, 0x494f, 0x7e24, 0xa6b5,
+	0x000c, 0x681c, 0xd0ac, 0x00c0, 0x495a, 0xc685, 0x7003, 0x0000,
+	0x7007, 0x0004, 0x6828, 0x2050, 0x2d60, 0x6004, 0xa0bc, 0x000f,
+	0xa7b8, 0x46f2, 0x273c, 0x87fb, 0x00c0, 0x4970, 0x0048, 0x496a,
+	0x1078, 0x29b2, 0x689c, 0xa065, 0x0040, 0x4974, 0x0078, 0x495d,
+	0x1078, 0x49f2, 0x00c0, 0x4970, 0x127f, 0x2000, 0x007c, 0x127e,
+	0x007e, 0x017e, 0x0d7e, 0x70d4, 0xa084, 0x4600, 0x8004, 0x007e,
+	0x2090, 0x007f, 0x7e20, 0xb284, 0x0100, 0x00c0, 0x4988, 0x7e24,
+	0x0d7f, 0x037f, 0x047f, 0xa6b5, 0x000c, 0x681c, 0xd0b4, 0x0040,
+	0x4996, 0xc685, 0x7003, 0x0000, 0x7007, 0x0004, 0x2049, 0x4977,
+	0x6828, 0xa055, 0x0d7e, 0x0040, 0x49ee, 0x2d70, 0x2e60, 0x7004,
+	0xa0bc, 0x000f, 0xa7b8, 0x46f2, 0x273c, 0x87fb, 0x00c0, 0x49b3,
+	0x0048, 0x49ac, 0x1078, 0x29b2, 0x709c, 0xa075, 0x2060, 0x0040,
+	0x49ee, 0x0078, 0x499f, 0x2704, 0xae68, 0x6808, 0xa422, 0x680c,
+	0xa31b, 0x0048, 0x49cc, 0x8a51, 0x00c0, 0x49c0, 0x1078, 0x29b2,
+	0x8738, 0x2704, 0xa005, 0x00c0, 0x49b4, 0x709c, 0xa075, 0x2060,
+	0x0040, 0x49ee, 0x0078, 0x499f, 0x8422, 0x8420, 0x831a, 0xa399,
+	0x0000, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, 0x00c8,
+	0x49db, 0x1078, 0x29b2, 0xb284, 0x0100, 0x0040, 0x49e9, 0x2001,
+	0x4f04, 0x2004, 0xd0ec, 0x00c0, 0x49e9, 0x2071, 0x0050, 0x0078,
+	0x49eb, 0x2071, 0x0020, 0x0d7f, 0x0078, 0x48fc, 0x0d7f, 0x127f,
+	0x2000, 0x007c, 0x7008, 0x007e, 0xa084, 0x01e0, 0x007f, 0x0040,
+	0x49fb, 0xa006, 0x007c, 0xa084, 0x0003, 0xa086, 0x0003, 0x00c0,
+	0x4a02, 0x007c, 0x2704, 0xac78, 0x7800, 0x701a, 0x7804, 0x701e,
+	0x7808, 0x7012, 0x780c, 0x7016, 0x6004, 0xd09c, 0x0040, 0x4a14,
+	0x7810, 0x7022, 0x7814, 0x7026, 0x7602, 0x7004, 0xa084, 0x0010,
+	0xc085, 0x7006, 0x2079, 0x4f00, 0x8738, 0x8a51, 0x0040, 0x4a40,
+	0x2704, 0xa005, 0x00c0, 0x4a32, 0x609c, 0xa005, 0x0040, 0x4a41,
+	0x2060, 0x6004, 0xa084, 0x000f, 0xa080, 0x46f2, 0x203c, 0x87fb,
+	0x1040, 0x29b2, 0x7008, 0x007e, 0xa084, 0x01e0, 0x007f, 0x0040,
+	0x4a3c, 0xa006, 0x0078, 0x4a41, 0xa084, 0x0003, 0xa086, 0x0003,
+	0x007c, 0x2051, 0x0000, 0x007c, 0x127e, 0x007e, 0x0d7e, 0x70d4,
+	0xa084, 0x4600, 0x8004, 0x2090, 0x0d7f, 0x087f, 0x7108, 0xa184,
+	0x0003, 0x00c0, 0x4a59, 0x6828, 0xa005, 0x0040, 0x4a69, 0x0078,
+	0x4602, 0x7108, 0xd1fc, 0x0040, 0x4a61, 0x1078, 0x47ed, 0x0078,
+	0x4a4e, 0x7007, 0x0010, 0x7108, 0xd1fc, 0x0040, 0x4a63, 0x1078,
+	0x47ed, 0x7008, 0xa086, 0x0008, 0x00c0, 0x4a4e, 0x7000, 0xa005,
+	0x00c0, 0x4a4e, 0x7003, 0x0000, 0x2049, 0x0000, 0x007e, 0x7804,
+	0xd0cc, 0x0040, 0x4a7d, 0x1078, 0x4acc, 0x007f, 0x127f, 0x2000,
+	0x007c, 0x127e, 0x147e, 0x137e, 0x157e, 0x0c7e, 0x0d7e, 0x70d4,
+	0xa084, 0x4600, 0x8004, 0x2090, 0x0d7f, 0x2049, 0x4a81, 0xad80,
+	0x0011, 0x20a0, 0xb284, 0x0100, 0x0040, 0x4aa4, 0x2001, 0x4f04,
+	0x2004, 0xd0ec, 0x0040, 0x4aa0, 0x2099, 0x0031, 0x0078, 0x4aa6,
+	0x2099, 0x0032, 0x0078, 0x4aa6, 0x2099, 0x0031, 0x700c, 0xa084,
+	0x03ff, 0x682a, 0x7007, 0x0008, 0x7007, 0x0002, 0x7003, 0x0001,
+	0x0040, 0x4ab5, 0x8000, 0x80ac, 0x53a5, 0x700c, 0xa084, 0x03ff,
+	0x0040, 0x4ac1, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0,
+	0x4abc, 0x0c7f, 0x2049, 0x0000, 0x7003, 0x0000, 0x157f, 0x137f,
+	0x147f, 0x127f, 0x2000, 0x007c, 0x6814, 0xd0fc, 0x0040, 0x4b11,
+	0x7000, 0xd084, 0x0040, 0x4b11, 0x7e24, 0xa6b5, 0x0004, 0x7007,
+	0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x4ad9, 0x7118, 0x017e,
+	0x711c, 0x017e, 0x7120, 0x017e, 0x7124, 0x017e, 0xa00e, 0x711a,
+	0x701f, 0x3fff, 0x7122, 0x7126, 0x7013, 0x0004, 0x7116, 0x7602,
+	0x7007, 0x0001, 0x2001, 0xffff, 0x2009, 0x0031, 0x200a, 0x200a,
+	0x7108, 0x7008, 0xa106, 0x00c0, 0x4af8, 0xd1fc, 0x0040, 0x4af8,
+	0x027f, 0x7226, 0x027f, 0x7222, 0x027f, 0x721e, 0x027f, 0x721a,
+	0x7007, 0x0002, 0x7008, 0xa086, 0x0008, 0x0040, 0x4b11, 0x0078,
+	0x4830, 0x7007, 0x0004, 0x7003, 0x0000, 0x007c, 0x2091, 0x8000,
+	0x2091, 0x6000, 0x78ac, 0xa005, 0x00c0, 0x4b2d, 0x7974, 0x70d0,
+	0xa106, 0x00c0, 0x4b2d, 0x781c, 0xa005, 0x0040, 0x4b2d, 0x781f,
+	0x0000, 0x0068, 0x4b2d, 0x2091, 0x4080, 0x7830, 0x8001, 0x7832,
+	0x00c0, 0x4bb5, 0x7834, 0x7832, 0x7810, 0xd0ec, 0x00c0, 0x4bae,
+	0x2061, 0x74c0, 0x2069, 0x4f80, 0xc7fd, 0x68d0, 0xa005, 0x0040,
+	0x4b47, 0x8001, 0x68d2, 0x00c0, 0x4b47, 0x1078, 0x4d83, 0x6800,
+	0xa084, 0x000f, 0x0040, 0x4b5c, 0xa086, 0x0001, 0x0040, 0x4b5c,
+	0x6844, 0xa00d, 0x0040, 0x4b5c, 0x2104, 0xa005, 0x0040, 0x4b5c,
+	0x8001, 0x200a, 0x0040, 0x4cf6, 0x6814, 0xa005, 0x0040, 0x4b81,
+	0x8001, 0x6816, 0x00c0, 0x4b81, 0x68a7, 0x0001, 0x0f7e, 0xd7fc,
+	0x00c0, 0x4b76, 0x7810, 0xd0ec, 0x0040, 0x4b72, 0x2079, 0x0100,
+	0x0078, 0x4b78, 0x2079, 0x0200, 0x0078, 0x4b78, 0x2079, 0x0100,
+	0x1078, 0x43d3, 0x0f7f, 0x6864, 0xa005, 0x0040, 0x4b81, 0x1078,
+	0x266f, 0x6880, 0xa005, 0x0040, 0x4b8e, 0x8001, 0x6882, 0x00c0,
+	0x4b8e, 0x6867, 0x0000, 0x68d4, 0xc0dd, 0x68d6, 0x68d4, 0xd0fc,
+	0x0040, 0x4bab, 0xc0fc, 0x68d6, 0x20a9, 0x0200, 0x6034, 0xa005,
+	0x0040, 0x4ba7, 0x8001, 0x6036, 0x68d4, 0xc0fd, 0x68d6, 0x00c0,
+	0x4ba7, 0x6010, 0xa005, 0x0040, 0x4ba7, 0x1078, 0x266f, 0xace0,
+	0x0010, 0x00f0, 0x4b96, 0xd7fc, 0x0040, 0x4bb5, 0x2061, 0x54c0,
+	0x2069, 0x4f40, 0xc7fc, 0x0078, 0x4b3d, 0x1078, 0x4bf1, 0x7838,
+	0x8001, 0x783a, 0x00c0, 0x4bd7, 0x783c, 0x783a, 0x2061, 0x54c0,
+	0x2069, 0x4f40, 0xc7fc, 0x680c, 0xa005, 0x0040, 0x4bc9, 0x1078,
+	0x4c5b, 0xd7fc, 0x00c0, 0x4bd7, 0x7810, 0xd0ec, 0x00c0, 0x4bd7,
+	0x2061, 0x74c0, 0x2069, 0x4f80, 0xc7fd, 0x0078, 0x4bc3, 0x7814,
+	0xd0e4, 0x00c0, 0x4bdb, 0x7810, 0xd0cc, 0x0040, 0x4bee, 0xd0ac,
+	0x00c0, 0x4be7, 0xd0a4, 0x0040, 0x4bee, 0xc0ad, 0x7812, 0x2091,
+	0x8001, 0x0068, 0x4bed, 0x1078, 0x23dc, 0x007c, 0x2091, 0x8001,
+	0x007c, 0x7840, 0x8001, 0x7842, 0x00c0, 0x4c5a, 0x7844, 0x7842,
+	0x2069, 0x4f40, 0xc7fc, 0x7810, 0x2079, 0x0200, 0xd0ec, 0x0040,
+	0x4c03, 0x2079, 0x0100, 0x68d8, 0xa005, 0x0040, 0x4c0f, 0x7de0,
+	0xa504, 0x00c0, 0x4c0f, 0x68da, 0x68d4, 0xc0bc, 0x68d6, 0x2079,
+	0x4f00, 0x6810, 0xa005, 0x00c0, 0x4c17, 0x2001, 0x0101, 0x8001,
+	0x6812, 0xd7fc, 0x0040, 0x4c20, 0xa080, 0x95d0, 0x0078, 0x4c22,
+	0xa080, 0x94c0, 0x2040, 0x2004, 0xa065, 0x0040, 0x4c4c, 0x6024,
+	0xa005, 0x0040, 0x4c48, 0x8001, 0x6026, 0x00c0, 0x4c48, 0x6800,
+	0xa005, 0x0040, 0x4c3b, 0x684c, 0xac06, 0x00c0, 0x4c3b, 0x1078,
+	0x4cf6, 0x0078, 0x4c4c, 0x6864, 0xa005, 0x0040, 0x4c43, 0x6027,
+	0x0001, 0x0078, 0x4c48, 0x1078, 0x4ca9, 0x2804, 0x0078, 0x4c24,
+	0x6000, 0x2c40, 0x0078, 0x4c24, 0xd7fc, 0x00c0, 0x4c5a, 0x7810,
+	0xd0ec, 0x00c0, 0x4c5a, 0x2069, 0x4f80, 0xc7fd, 0x2079, 0x0100,
+	0x0078, 0x4c03, 0x007c, 0x2009, 0x0000, 0x20a9, 0x0200, 0x6008,
+	0xd09c, 0x0040, 0x4c95, 0x6024, 0xa005, 0x0040, 0x4c6b, 0x8001,
+	0x6026, 0x0078, 0x4c93, 0x6008, 0xc09c, 0xd084, 0x00c0, 0x4c73,
+	0xd0ac, 0x0040, 0x4c8d, 0x600a, 0x6004, 0xa005, 0x0040, 0x4c95,
+	0x0d7e, 0x0c7e, 0x017e, 0x2068, 0x6010, 0x8001, 0x6012, 0x1078,
+	0x3e19, 0x2d00, 0x2c68, 0x2060, 0x1078, 0x1ea2, 0x1078, 0x2064,
+	0x017f, 0x0c7f, 0x0d7f, 0x0078, 0x4c95, 0xc0bd, 0x600a, 0xa18d,
+	0x0001, 0x0078, 0x4c95, 0xa18d, 0x0100, 0xace0, 0x0010, 0x00f0,
+	0x4c5f, 0xa184, 0x0001, 0x0040, 0x4ca4, 0xa18c, 0xfffe, 0x690e,
+	0x1078, 0x266f, 0x0078, 0x4ca5, 0x690e, 0x007c, 0x00c0, 0x4ca5,
+	0x786c, 0x2c00, 0x687e, 0x6714, 0x6f76, 0x6017, 0x0000, 0x602b,
+	0x0000, 0x601b, 0x0006, 0x60b4, 0xa084, 0x3f00, 0x601e, 0x6020,
+	0xa084, 0x00ff, 0xa085, 0x0060, 0x6022, 0x6000, 0x2042, 0x1078,
+	0x1e2b, 0x6818, 0xa005, 0x0040, 0x4cc7, 0x8001, 0x681a, 0x6808,
+	0xc0a4, 0x680a, 0x6810, 0x7908, 0x8109, 0x790a, 0x8001, 0x00d0,
+	0x4cd3, 0x1078, 0x29b2, 0x6812, 0x00c0, 0x4cd9, 0x7910, 0xc1a5,
+	0x7912, 0x602f, 0x0000, 0x6033, 0x0000, 0x2c68, 0x1078, 0x2073,
+	0xd7fc, 0x00c0, 0x4ce7, 0x2069, 0x4f40, 0x0078, 0x4ce9, 0x2069,
+	0x4f80, 0x6910, 0xa184, 0x0100, 0x2001, 0x0006, 0x00c0, 0x4cf3,
+	0x697a, 0x2001, 0x0004, 0x1078, 0x2663, 0x007c, 0x0d7e, 0x694c,
+	0x2160, 0xd7fc, 0x00c0, 0x4d08, 0x7810, 0xd0ec, 0x0040, 0x4d04,
+	0x2069, 0x0100, 0x0078, 0x4d0a, 0x2069, 0x0200, 0x0078, 0x4d0a,
+	0x2069, 0x0100, 0x1078, 0x2926, 0x601b, 0x0006, 0x6858, 0xa084,
+	0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085, 0x0048, 0x6022,
+	0x602f, 0x0000, 0x6033, 0x0000, 0x6808, 0xa084, 0xfffd, 0x680a,
+	0x6830, 0xd0b4, 0x0040, 0x4d3c, 0x684b, 0x0004, 0x20a9, 0x0014,
+	0x6848, 0xd094, 0x0040, 0x4d2e, 0x00f0, 0x4d28, 0x684b, 0x0009,
+	0x20a9, 0x0014, 0x6848, 0xd084, 0x0040, 0x4d38, 0x00f0, 0x4d32,
+	0x20a9, 0x00fa, 0x00f0, 0x4d3a, 0x681b, 0x0047, 0x0d7f, 0x6867,
+	0x0007, 0x007c, 0x2079, 0x4f00, 0x1078, 0x4d76, 0x1078, 0x4d5c,
+	0x1078, 0x4d69, 0x2009, 0x0002, 0x2069, 0x4f80, 0x680f, 0x0000,
+	0x6813, 0x0000, 0x6817, 0x0000, 0x8109, 0x0040, 0x4d5b, 0x2069,
+	0x4f40, 0x0078, 0x4d4e, 0x007c, 0x7810, 0xd0ec, 0x0040, 0x4d64,
+	0x2019, 0x00cc, 0x0078, 0x4d66, 0x2019, 0x007b, 0x7b3a, 0x7b3e,
+	0x007c, 0x7814, 0xd0e4, 0x00c0, 0x4d71, 0x2019, 0x0040, 0x0078,
+	0x4d73, 0x2019, 0x0026, 0x7b42, 0x7b46, 0x007c, 0x7814, 0xd0e4,
+	0x00c0, 0x4d7e, 0x2019, 0x3f94, 0x0078, 0x4d80, 0x2019, 0x2624,
+	0x7b32, 0x7b36, 0x007c, 0x6a50, 0xa285, 0x0000, 0x0040, 0x4daf,
+	0x6954, 0x6bc0, 0xa300, 0x0c7e, 0x2164, 0x6304, 0x83ff, 0x00c0,
+	0x4d9b, 0x8211, 0x0040, 0x4d9f, 0x8108, 0xa11a, 0x0048, 0x4d8c,
+	0x69c0, 0x0078, 0x4d8c, 0x68d3, 0x000a, 0x0c7f, 0x007c, 0x6950,
+	0x6ac0, 0x2264, 0x602b, 0x0000, 0x602f, 0x0000, 0x6008, 0xc0b5,
+	0x600a, 0x8210, 0x8109, 0x00c0, 0x4da1, 0x6952, 0x0c7f, 0x007c,
+	0x00e0, 0x4db0, 0x2091, 0x6000, 0x00e0, 0x4db4, 0x2091, 0x6000,
+	0x70ec, 0xd0dc, 0x00c0, 0x4dc1, 0xd0d4, 0x0040, 0x4dea, 0x0078,
+	0x4ded, 0x2008, 0x7810, 0xd0ec, 0x0040, 0x4dd4, 0xd1c4, 0x00c0,
+	0x4e0e, 0x7814, 0xc0c5, 0x7816, 0x7810, 0xc0f5, 0x7812, 0xd0ec,
+	0x0040, 0x4e0a, 0x0078, 0x4e06, 0xae8e, 0x0100, 0x0040, 0x4de1,
+	0x7814, 0xc0f5, 0xc0c5, 0x7816, 0xd0d4, 0x00c0, 0x4e0a, 0x0078,
+	0x4e06, 0x7814, 0xc0fd, 0xc0c5, 0x7816, 0xd0d4, 0x00c0, 0x4e0a,
+	0x0078, 0x4e06, 0xd0e4, 0x0040, 0x4e0c, 0x00e0, 0x4ded, 0x2091,
+	0x6000, 0x2009, 0x000c, 0x00e0, 0x4df3, 0x2091, 0x6000, 0x8109,
+	0x00c0, 0x4df3, 0x70e4, 0xa084, 0x01ff, 0xa086, 0x01ff, 0x00c0,
+	0x4e04, 0x70ec, 0x0078, 0x4dc1, 0x1078, 0x4e0f, 0x7804, 0xd08c,
+	0x0040, 0x4e0c, 0x681f, 0x000c, 0x70a0, 0x70a2, 0x007c, 0x7910,
+	0xd1ec, 0x0040, 0x4e19, 0x7814, 0xc0c4, 0xc1f4, 0x7912, 0x0078,
+	0x4e2b, 0xae8e, 0x0100, 0x0040, 0x4e25, 0x7814, 0xc0f4, 0xd0fc,
+	0x00c0, 0x4e2b, 0xc0c4, 0x0078, 0x4e2b, 0x7814, 0xc0fc, 0xd0f4,
+	0x00c0, 0x4e2b, 0xc0c4, 0x7816, 0x007c, 0x14e3
 };
 #ifdef UNIQUE_FW_NAME
-static unsigned short   fw1280ei_length01 = 0x3d3b;
+static unsigned short fw1280ei_length01 = 0x3e2e;
 #else
-static unsigned short   risc_code_length01 = 0x3d3b;
+static unsigned short risc_code_length01 = 0x3e2e;
 #endif
+
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index 4ad2808..1a4ce1c 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -1098,7 +1098,13 @@
 static int
 qla1280_eh_abort(struct scsi_cmnd * cmd)
 {
-	return qla1280_error_action(cmd, ABORT_COMMAND);
+	int rc;
+
+	spin_lock_irq(cmd->device->host->host_lock);
+	rc = qla1280_error_action(cmd, ABORT_COMMAND);
+	spin_unlock_irq(cmd->device->host->host_lock);
+
+	return rc;
 }
 
 /**************************************************************************
@@ -1108,7 +1114,13 @@
 static int
 qla1280_eh_device_reset(struct scsi_cmnd *cmd)
 {
-	return qla1280_error_action(cmd, DEVICE_RESET);
+	int rc;
+
+	spin_lock_irq(cmd->device->host->host_lock);
+	rc = qla1280_error_action(cmd, DEVICE_RESET);
+	spin_unlock_irq(cmd->device->host->host_lock);
+
+	return rc;
 }
 
 /**************************************************************************
@@ -1118,7 +1130,13 @@
 static int
 qla1280_eh_bus_reset(struct scsi_cmnd *cmd)
 {
-	return qla1280_error_action(cmd, BUS_RESET);
+	int rc;
+
+	spin_lock_irq(cmd->device->host->host_lock);
+	rc = qla1280_error_action(cmd, BUS_RESET);
+	spin_unlock_irq(cmd->device->host->host_lock);
+
+	return rc;
 }
 
 /**************************************************************************
@@ -1128,7 +1146,13 @@
 static int
 qla1280_eh_adapter_reset(struct scsi_cmnd *cmd)
 {
-	return qla1280_error_action(cmd, ADAPTER_RESET);
+	int rc;
+
+	spin_lock_irq(cmd->device->host->host_lock);
+	rc = qla1280_error_action(cmd, ADAPTER_RESET);
+	spin_unlock_irq(cmd->device->host->host_lock);
+
+	return rc;
 }
 
 static int
@@ -4038,11 +4062,10 @@
 			scsi_status, handle);
 	}
 
-	/* Target busy */
-	if (scsi_status & SS_BUSY_CONDITION &&
-	    scsi_status != SS_RESERVE_CONFLICT) {
-		CMD_RESULT(cmd) =
-			DID_BUS_BUSY << 16 | (scsi_status & 0xff);
+	/* Target busy or queue full */
+	if ((scsi_status & 0xFF) == SAM_STAT_TASK_SET_FULL ||
+	    (scsi_status & 0xFF) == SAM_STAT_BUSY) {
+		CMD_RESULT(cmd) = scsi_status & 0xff;
 	} else {
 
 		/* Save ISP completion status */
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index c4cd4ac..329d1a1 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -1063,8 +1063,7 @@
 		return;
 
 	printk("  sp flags=0x%x\n", sp->flags);
-	printk("  r_start=0x%lx, u_start=0x%lx, f_start=0x%lx, state=%d\n",
-	    sp->r_start, sp->u_start, sp->f_start, sp->state);
+	printk("  state=%d\n", sp->state);
 }
 
 #if defined(QL_DEBUG_ROUTINES)
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 7d47b8d..83a32e4 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -252,31 +252,12 @@
 	/* Request state */
 	uint16_t state;
 
-	/* Timing counts. */
-	unsigned long e_start;		/* Start of extend timeout */
-	unsigned long r_start;		/* Start of request */
-	unsigned long u_start;		/* When sent to RISC */
-	unsigned long f_start;		/* When placed in FO queue*/
-
 	/* Single transfer DMA context */
 	dma_addr_t dma_handle;
 
 	uint32_t request_sense_length;
 	uint8_t *request_sense_ptr;
 
-	int ext_history;
-
-	/* Suspend delay */
-	int delay;
-
-	/* Raw completion info for use by failover ? */
-	uint8_t	fo_retry_cnt;		/* Retry count this request */
-	uint8_t	err_id;			/* error id */
-#define SRB_ERR_PORT	1		/* Request failed -- "port down" */
-#define SRB_ERR_LOOP	2		/* Request failed -- "loop down" */
-#define SRB_ERR_DEVICE	3		/* Request failed -- "device error" */
-#define SRB_ERR_OTHER	4
-
 	/* SRB magic number */
 	uint16_t magic;
 #define SRB_MAGIC       0x10CB
@@ -2082,23 +2063,8 @@
 	uint32_t	current_outstanding_cmd; 
 	srb_t		*status_srb;	/* Status continuation entry. */
 
-	unsigned long	last_irq_cpu;	/* cpu where we got our last irq */
-
 	uint16_t           revision;
 	uint8_t           ports;
-	u_long            actthreads;
-	u_long            ipreq_cnt;
-	u_long            qthreads;
-
-	uint32_t        total_isr_cnt;		/* Interrupt count */
-	uint32_t        total_isp_aborts;	/* controller err cnt */
-	uint32_t        total_lip_cnt;		/* LIP cnt */
-	uint32_t	total_dev_errs;		/* device error cnt */
-	uint32_t	total_ios;		/* IO cnt */
-	uint64_t	total_bytes;		/* xfr byte cnt */
-	uint32_t	total_mbx_timeout;	/* mailbox timeout cnt */
-	uint32_t 	total_loop_resync; 	/* loop resyn cnt */
-	uint32_t	dropped_frame_error_cnt;
 
 	/* ISP configuration data. */
 	uint16_t	loop_id;		/* Host adapter loop id */
@@ -2124,8 +2090,6 @@
 #define P2P_LOOP  3
 
         uint8_t		marker_needed; 
-	uint8_t		sns_retry_cnt;
-	uint8_t		mem_err;
 
 	uint8_t		interrupts_on;
 
@@ -2138,16 +2102,11 @@
 	uint16_t	nvram_base;
 
 	uint16_t	loop_reset_delay;
-	uint16_t	minimum_timeout;
 	uint8_t		retry_count;
 	uint8_t		login_timeout;
 	uint16_t	r_a_tov;
 	int		port_down_retry_count;
-	uint8_t		loop_down_timeout;
 	uint8_t		mbx_count;
-	uint16_t	max_probe_luns;
-	uint16_t	max_luns;
-	uint16_t	max_targets;
 	uint16_t	last_loop_id;
 
         uint32_t	login_retry_count; 
@@ -2181,7 +2140,6 @@
 	uint8_t dpc_active;                  /* DPC routine is active */
 
 	/* Timeout timers. */
-	uint8_t         queue_restart_timer;   
 	uint8_t         loop_down_abort_time;    /* port down timer */
 	atomic_t        loop_down_timer;         /* loop down timer */
 	uint8_t         link_down_timeout;       /* link down timeout */
@@ -2230,18 +2188,6 @@
 
 	mbx_cmd_t 	mc;
 
-	uint8_t	*cmdline;
-
-	uint32_t failover_type;
-	uint32_t failback_delay;
-	unsigned long   cfg_flags;
-#define	CFG_ACTIVE	0	/* CFG during a failover, event update, or ioctl */
-#define	CFG_FAILOVER	1	/* CFG during path change */
-
-	uint32_t	binding_type;
-#define BIND_BY_PORT_NAME	0
-#define BIND_BY_PORT_ID		1
-
 	/* Basic firmware related information. */
 	struct qla_board_info	*brd_info;
 	uint16_t	fw_major_version;
@@ -2274,12 +2220,6 @@
 	uint8_t     nvram_version; 
 	uint32_t    isp_abort_cnt;
 
-	/* Adapter I/O statistics for failover */
-	uint64_t	IosRequested;
-	uint64_t	BytesRequested;
-	uint64_t	IosExecuted;
-	uint64_t	BytesExecuted;
-
 	/* Needed for BEACON */
 	uint16_t	beacon_blink_led;
 	uint16_t	beacon_green_on;
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 2efec6c..164866b 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -53,27 +53,13 @@
  */
 extern char qla2x00_version_str[];
 
-extern int num_hosts;
-extern int apiHBAInstance;
-
-extern struct _qla2x00stats qla2x00_stats;
-extern int ql2xretrycount;
 extern int ql2xlogintimeout;
 extern int qlport_down_retry;
-extern int ql2xmaxqdepth;
-extern int displayConfig;
 extern int ql2xplogiabsentdevice;
 extern int ql2xenablezio;
 extern int ql2xintrdelaytimer;
 extern int ql2xloginretrycount;
 
-extern int ConfigRequired;
-
-extern int Bind;
-extern int ql2xsuspendcount;
-#if defined(MODULE)
-extern char *ql2xopts;
-#endif
 extern void qla2x00_sp_compl(scsi_qla_host_t *, srb_t *);
 
 extern char *qla2x00_get_fw_version_str(struct scsi_qla_host *, char *);
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 0387005..7629558 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -85,9 +85,7 @@
 	atomic_set(&ha->loop_down_timer, LOOP_DOWN_TIME);
 	atomic_set(&ha->loop_state, LOOP_DOWN);
 	ha->device_flags = 0;
-	ha->sns_retry_cnt = 0;
 	ha->dpc_flags = 0;
-	ha->failback_delay = 0;
 	ha->flags.management_server_logged_in = 0;
 	ha->marker_needed = 0;
 	ha->mbx_flags = 0;
@@ -171,8 +169,6 @@
 
 				if (wait_time == 0)
 					rval = QLA_FUNCTION_FAILED;
-				if (ha->mem_err)
-					restart_risc = 1;
 			} else if (ha->device_flags & DFLG_NO_CABLE)
 				/* If no cable, then all is good. */
 				rval = QLA_SUCCESS;
@@ -1410,13 +1406,8 @@
 	/* Set minimum RATOV to 200 tenths of a second. */
 	ha->r_a_tov = 200;
 
-	ha->minimum_timeout =
-	    (ha->login_timeout * ha->retry_count) + nv->port_down_retry_count;
 	ha->loop_reset_delay = nv->reset_delay;
 
-	/* Will get the value from NVRAM. */
-	ha->loop_down_timeout = LOOP_DOWN_TIMEOUT;
-
 	/* Link Down Timeout = 0:
 	 *
 	 * 	When Port Down timer expires we will start returning
@@ -1429,18 +1420,13 @@
 	 */						
 	if (nv->link_down_timeout == 0) {
 		ha->loop_down_abort_time =
-		    (LOOP_DOWN_TIME - ha->loop_down_timeout);
+		    (LOOP_DOWN_TIME - LOOP_DOWN_TIMEOUT);
 	} else {
 		ha->link_down_timeout =	 nv->link_down_timeout;
 		ha->loop_down_abort_time =
 		    (LOOP_DOWN_TIME - ha->link_down_timeout);
 	} 
 
-	ha->max_luns = MAX_LUNS;
-	ha->max_probe_luns = le16_to_cpu(nv->max_luns_per_target);
-	if (ha->max_probe_luns == 0)
-		ha->max_probe_luns = MIN_LUNS;
-
 	/*
 	 * Need enough time to try and get the port back.
 	 */
@@ -1457,16 +1443,6 @@
 	if (ql2xloginretrycount)
 		ha->login_retry_count = ql2xloginretrycount;
 
-	ha->binding_type = Bind;
-	if (ha->binding_type != BIND_BY_PORT_NAME &&
-	    ha->binding_type != BIND_BY_PORT_ID) {
-		qla_printk(KERN_WARNING, ha,
-		    "Invalid binding type specified (%d), "
-		    "defaulting to BIND_BY_PORT_NAME!!!\n", ha->binding_type);
-
-		ha->binding_type = BIND_BY_PORT_NAME;
-	}
-
 	icb->lun_enables = __constant_cpu_to_le16(0);
 	icb->command_resource_count = 0;
 	icb->immediate_notify_resource_count = 0;
@@ -1578,7 +1554,6 @@
 	 */
 	clear_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
 	clear_bit(RSCN_UPDATE, &ha->dpc_flags);
-	ha->mem_err = 0 ;
 
 	/* Determine what we need to do */
 	if (ha->current_topology == ISP_CFG_FL &&
@@ -2707,7 +2682,6 @@
 	rval = QLA_SUCCESS;
 
 	atomic_set(&ha->loop_state, LOOP_UPDATE);
-	qla2x00_stats.loop_resync++;
 	clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags);
 	if (ha->flags.online) {
 		if (!(rval = qla2x00_fw_ready(ha))) {
@@ -2786,9 +2760,6 @@
 	if (ha->flags.online) {
 		ha->flags.online = 0;
 		clear_bit(ISP_ABORT_NEEDED, &ha->dpc_flags);
-		qla2x00_stats.ispAbort++;
-		ha->total_isp_aborts++;  /* used by ioctl */
-		ha->sns_retry_cnt = 0;
 
 		qla_printk(KERN_INFO, ha,
 		    "Performing ISP error recovery - ha= %p.\n", ha);
@@ -2810,8 +2781,6 @@
 			sp = ha->outstanding_cmds[cnt];
 			if (sp) {
 				ha->outstanding_cmds[cnt] = NULL;
-				if (ha->actthreads)
-					ha->actthreads--;
 				sp->flags = 0;
 				sp->cmd->result = DID_RESET << 16;
 				sp->cmd->host_scribble = (unsigned char *)NULL;
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index af964bb..ecaf9f8 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -433,11 +433,8 @@
 	} else
 		ha->request_ring_ptr++;
 
-	ha->actthreads++;
-	ha->total_ios++;
 	sp->flags |= SRB_DMA_VALID;
 	sp->state = SRB_ACTIVE_STATE;
-	sp->u_start = jiffies;
 
 	/* Set chip new ring index. */
 	WRT_REG_WORD(ISP_REQ_Q_IN(ha, reg), ha->req_ring_index);
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 6792cfa..e7a8b74 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -91,9 +91,6 @@
 	}
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
-	ha->last_irq_cpu = _smp_processor_id();
-	ha->total_isr_cnt++;
-
 	if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
 	    (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
 		spin_lock_irqsave(&ha->mbx_reg_lock, flags);
@@ -200,9 +197,6 @@
 	}
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
-	ha->last_irq_cpu = _smp_processor_id();
-	ha->total_isr_cnt++;
-
 	if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
 	    (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
 		spin_lock_irqsave(&ha->mbx_reg_lock, flags);
@@ -417,7 +411,6 @@
 		/* Update AEN queue. */
 		qla2x00_enqueue_aen(ha, MBA_LIP_OCCURRED, NULL);
 
-		ha->total_lip_cnt++;
 		break;
 
 	case MBA_LOOP_UP:		/* Loop Up Event */
@@ -485,7 +478,6 @@
 		/* Update AEN queue. */
 		qla2x00_enqueue_aen(ha, MBA_LIP_RESET, NULL);
 
-		ha->total_lip_cnt++;
 		break;
 
 	case MBA_POINT_TO_POINT:	/* Point-to-Point */
@@ -695,14 +687,11 @@
 		/* Free outstanding command slot. */
 		ha->outstanding_cmds[index] = NULL;
 
-		if (ha->actthreads)
-			ha->actthreads--;
 		CMD_COMPL_STATUS(sp->cmd) = 0L;
 		CMD_SCSI_STATUS(sp->cmd) = 0L;
 
 		/* Save ISP completion status */
 		sp->cmd->result = DID_OK << 16;
-		sp->fo_retry_cnt = 0;
 		qla2x00_sp_compl(ha, sp);
 	} else {
 		DEBUG2(printk("scsi(%ld): Invalid ISP SCSI completion handle\n",
@@ -865,9 +854,6 @@
 		return;
 	}
 
-	if (ha->actthreads)
-		ha->actthreads--;
-
 	comp_status = le16_to_cpu(pkt->comp_status);
 	/* Mask of reserved bits 12-15, before we examine the scsi status */
 	scsi_status = le16_to_cpu(pkt->scsi_status) & SS_MASK;
@@ -1026,7 +1012,6 @@
 				    cp->request_bufflen));
 
 				cp->result = DID_BUS_BUSY << 16;
-				ha->dropped_frame_error_cnt++;
 				break;
 			}
 
@@ -1233,8 +1218,7 @@
 	if (sp) {
 		/* Free outstanding command slot. */
 		ha->outstanding_cmds[pkt->handle] = NULL;
-		if (ha->actthreads)
-			ha->actthreads--;
+
 		/* Bad payload or header */
 		if (pkt->entry_status &
 		    (RF_INV_E_ORDER | RF_INV_E_COUNT |
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 15f6aca..eeaec7c 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -219,10 +219,8 @@
 		ha->flags.mbox_int = 0;
 		clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
 
-		if (ha->mailbox_out[0] != MBS_COMMAND_COMPLETE) {
-			qla2x00_stats.mboxerr++;
+		if (ha->mailbox_out[0] != MBS_COMMAND_COMPLETE)
 			rval = QLA_FUNCTION_FAILED;
-		}
 
 		/* Load return mailbox registers. */
 		iptr2 = mcp->mb;
@@ -249,8 +247,6 @@
 		qla2x00_dump_regs(ha);
 #endif
 
-		qla2x00_stats.mboxtout++;
-		ha->total_mbx_timeout++;
 		rval = QLA_FUNCTION_TIMEOUT;
 	}
 
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 3c97aa4..0b12498 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -36,27 +36,12 @@
 /*
  * SRB allocation cache
  */
-char srb_cachep_name[16];
-kmem_cache_t *srb_cachep;
-
-/*
- * Stats for all adpaters.
- */
-struct _qla2x00stats qla2x00_stats;
+static kmem_cache_t *srb_cachep;
 
 /*
  * Ioctl related information.
  */
-int num_hosts;
-int apiHBAInstance;
-
-/*
- * Module parameter information and variables
- */
-int ql2xmaxqdepth;
-module_param(ql2xmaxqdepth, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(ql2xmaxqdepth,
-		"Maximum queue depth to report for target devices.");
+static int num_hosts;
 
 int ql2xlogintimeout = 20;
 module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR);
@@ -69,12 +54,6 @@
 		"Maximum number of command retries to a port that returns"
 		"a PORT-DOWN status.");
 
-int ql2xretrycount = 20;
-module_param(ql2xretrycount, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(ql2xretrycount,
-		"Maximum number of mid-layer retries allowed for a command.  "
-		"Default value is 20, ");
-
 int ql2xplogiabsentdevice;
 module_param(ql2xplogiabsentdevice, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(ql2xplogiabsentdevice,
@@ -95,25 +74,6 @@
 		"ZIO: Waiting time for Firmware before it generates an "
 		"interrupt to the host to notify completion of request.");
 
-int ConfigRequired;
-module_param(ConfigRequired, int, S_IRUGO|S_IRUSR);
-MODULE_PARM_DESC(ConfigRequired,
-		"If 1, then only configured devices passed in through the"
-		"ql2xopts parameter will be presented to the OS");
-
-int Bind = BIND_BY_PORT_NAME;
-module_param(Bind, int, S_IRUGO|S_IRUSR);
-MODULE_PARM_DESC(Bind,
-		"Target persistent binding method: "
-		"0 by Portname (default); 1 by PortID; 2 by Nodename. ");
-
-int ql2xsuspendcount = SUSPEND_COUNT;
-module_param(ql2xsuspendcount, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(ql2xsuspendcount,
-		"Number of 6-second suspend iterations to perform while a "
-		"target returns a <NOT READY> status.  Default is 10 "
-		"iterations.");
-
 int ql2xloginretrycount = 0;
 module_param(ql2xloginretrycount, int, S_IRUGO|S_IRUSR);
 MODULE_PARM_DESC(ql2xloginretrycount,
@@ -330,7 +290,6 @@
 	sp->fcport = fcport;
 	sp->cmd = cmd;
 	sp->flags = 0;
-	sp->err_id = 0;
 
 	CMD_SP(cmd) = (void *)sp;
 	cmd->scsi_done = done;
@@ -474,7 +433,6 @@
 
 	while ((!atomic_read(&ha->loop_down_timer) &&
 	    atomic_read(&ha->loop_state) == LOOP_DOWN) ||
-	    test_bit(CFG_ACTIVE, &ha->cfg_flags) ||
 	    atomic_read(&ha->loop_state) != LOOP_READY) {
 		msleep(1000);
 		if (time_after_eq(jiffies, loop_timeout)) {
@@ -519,7 +477,6 @@
 	serial = cmd->serial_number;
 
 	/* Check active list for command command. */
-	spin_unlock_irq(ha->host->host_lock);
 	spin_lock_irqsave(&ha->hardware_lock, flags);
 	for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) {
 		sp = ha->outstanding_cmds[i];
@@ -558,7 +515,6 @@
 			    "%x.\n", ha->host_no, id, lun, serial, ret);
 		}
 	}
-	spin_lock_irq(ha->host->host_lock);
 
 	qla_printk(KERN_INFO, ha, 
 	    "scsi(%ld:%d:%d): Abort command issued -- %lx %x.\n", ha->host_no,
@@ -658,12 +614,8 @@
 	qla_printk(KERN_INFO, ha,
 	    "scsi(%ld:%d:%d): DEVICE RESET ISSUED.\n", ha->host_no, id, lun);
 
-	spin_unlock_irq(ha->host->host_lock);
-
-	if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS) {
-		spin_lock_irq(ha->host->host_lock);
+	if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS)
 		goto eh_dev_reset_done;
-	}
 
 	if (qla2x00_wait_for_loop_ready(ha) == QLA_SUCCESS) {
 		if (qla2x00_device_reset(ha, fcport) == 0)
@@ -714,8 +666,6 @@
 	    "scsi(%ld:%d:%d): DEVICE RESET SUCCEEDED.\n", ha->host_no, id, lun);
 
 eh_dev_reset_done:
-	spin_lock_irq(ha->host->host_lock);
-
 	return ret;
 }
 
@@ -805,8 +755,6 @@
 	qla_printk(KERN_INFO, ha,
 	    "scsi(%ld:%d:%d): LOOP RESET ISSUED.\n", ha->host_no, id, lun);
 
-	spin_unlock_irq(ha->host->host_lock);
-
 	if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS) {
 		DEBUG2(printk("%s failed:board disabled\n",__func__));
 		goto eh_bus_reset_done;
@@ -828,8 +776,6 @@
 	qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__,
 	    (ret == FAILED) ? "failed" : "succeded");
 
-	spin_lock_irq(ha->host->host_lock);
-
 	return ret;
 }
 
@@ -871,8 +817,6 @@
 	qla_printk(KERN_INFO, ha,
 	    "scsi(%ld:%d:%d): ADAPTER RESET ISSUED.\n", ha->host_no, id, lun);
 
-	spin_unlock_irq(ha->host->host_lock);
-
 	if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS)
 		goto eh_host_reset_lock;
 
@@ -901,8 +845,6 @@
 		ret = SUCCESS;
 
 eh_host_reset_lock:
-	spin_lock_irq(ha->host->host_lock);
-
 	qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__,
 	    (ret == FAILED) ? "failed" : "succeded");
 
@@ -1150,7 +1092,7 @@
  */
 int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
 {
-	int	ret;
+	int	ret = -ENODEV;
 	device_reg_t __iomem *reg;
 	struct Scsi_Host *host;
 	scsi_qla_host_t *ha;
@@ -1161,7 +1103,7 @@
 	fc_port_t *fcport;
 
 	if (pci_enable_device(pdev))
-		return -1;
+		goto probe_out;
 
 	host = scsi_host_alloc(&qla2x00_driver_template,
 	    sizeof(scsi_qla_host_t));
@@ -1183,9 +1125,8 @@
 
 	/* Configure PCI I/O space */
 	ret = qla2x00_iospace_config(ha);
-	if (ret != 0) {
-		goto probe_alloc_failed;
-	}
+	if (ret)
+		goto probe_failed;
 
 	/* Sanitize the information from PCI BIOS. */
 	host->irq = pdev->irq;
@@ -1196,34 +1137,24 @@
 
 	spin_lock_init(&ha->hardware_lock);
 
-	/* 4.23 Initialize /proc/scsi/qla2x00 counters */
-	ha->actthreads = 0;
-	ha->qthreads   = 0;
-	ha->total_isr_cnt = 0;
-	ha->total_isp_aborts = 0;
-	ha->total_lip_cnt = 0;
-	ha->total_dev_errs = 0;
-	ha->total_ios = 0;
-	ha->total_bytes = 0;
-
 	ha->prev_topology = 0;
 	ha->ports = MAX_BUSES;
 
 	if (IS_QLA2100(ha)) {
-		ha->max_targets = MAX_TARGETS_2100;
+		host->max_id = MAX_TARGETS_2100;
 		ha->mbx_count = MAILBOX_REGISTER_COUNT_2100;
 		ha->request_q_length = REQUEST_ENTRY_CNT_2100;
 		ha->response_q_length = RESPONSE_ENTRY_CNT_2100;
 		ha->last_loop_id = SNS_LAST_LOOP_ID_2100;
 		host->sg_tablesize = 32;
 	} else if (IS_QLA2200(ha)) {
-		ha->max_targets = MAX_TARGETS_2200;
+		host->max_id = MAX_TARGETS_2200;
 		ha->mbx_count = MAILBOX_REGISTER_COUNT;
 		ha->request_q_length = REQUEST_ENTRY_CNT_2200;
 		ha->response_q_length = RESPONSE_ENTRY_CNT_2100;
 		ha->last_loop_id = SNS_LAST_LOOP_ID_2100;
 	} else /*if (IS_QLA2300(ha))*/ {
-		ha->max_targets = MAX_TARGETS_2200;
+		host->max_id = MAX_TARGETS_2200;
 		ha->mbx_count = MAILBOX_REGISTER_COUNT;
 		ha->request_q_length = REQUEST_ENTRY_CNT_2200;
 		ha->response_q_length = RESPONSE_ENTRY_CNT_2300;
@@ -1258,23 +1189,10 @@
 		qla_printk(KERN_WARNING, ha,
 		    "[ERROR] Failed to allocate memory for adapter\n");
 
-		goto probe_alloc_failed;
+		ret = -ENOMEM;
+		goto probe_failed;
 	}
 
-	pci_set_drvdata(pdev, ha);
-	host->this_id = 255;
-	host->cmd_per_lun = 3;
-	host->unique_id = ha->instance;
-	host->max_cmd_len = MAX_CMDSZ;
-	host->max_channel = ha->ports - 1;
-	host->max_id = ha->max_targets;
-	host->max_lun = ha->max_luns;
-	host->transportt = qla2xxx_transport_template;
-	if (scsi_add_host(host, &pdev->dev))
-		goto probe_alloc_failed;
-
-	qla2x00_alloc_sysfs_attr(ha);
-
 	if (qla2x00_initialize_adapter(ha) &&
 	    !(ha->device_flags & DFLG_NO_CABLE)) {
 
@@ -1285,11 +1203,10 @@
 		    "Adapter flags %x.\n",
 		    ha->host_no, ha->device_flags));
 
+		ret = -ENODEV;
 		goto probe_failed;
 	}
 
-	qla2x00_init_host_attr(ha);
-
 	/*
 	 * Startup the kernel thread for this host adapter
 	 */
@@ -1299,17 +1216,26 @@
 		qla_printk(KERN_WARNING, ha,
 		    "Unable to start DPC thread!\n");
 
+		ret = -ENODEV;
 		goto probe_failed;
 	}
 	wait_for_completion(&ha->dpc_inited);
 
+	host->this_id = 255;
+	host->cmd_per_lun = 3;
+	host->unique_id = ha->instance;
+	host->max_cmd_len = MAX_CMDSZ;
+	host->max_channel = ha->ports - 1;
+	host->max_lun = MAX_LUNS;
+	host->transportt = qla2xxx_transport_template;
+
 	if (IS_QLA2100(ha) || IS_QLA2200(ha))
 		ret = request_irq(host->irq, qla2100_intr_handler,
 		    SA_INTERRUPT|SA_SHIRQ, ha->brd_info->drv_name, ha);
 	else
 		ret = request_irq(host->irq, qla2300_intr_handler,
 		    SA_INTERRUPT|SA_SHIRQ, ha->brd_info->drv_name, ha);
-	if (ret != 0) {
+	if (ret) {
 		qla_printk(KERN_WARNING, ha,
 		    "Failed to reserve interrupt %d already in use.\n",
 		    host->irq);
@@ -1363,9 +1289,18 @@
 		msleep(10);
 	}
 
+	pci_set_drvdata(pdev, ha);
 	ha->flags.init_done = 1;
 	num_hosts++;
 
+	ret = scsi_add_host(host, &pdev->dev);
+	if (ret)
+		goto probe_failed;
+
+	qla2x00_alloc_sysfs_attr(ha);
+
+	qla2x00_init_host_attr(ha);
+
 	qla_printk(KERN_INFO, ha, "\n"
 	    " QLogic Fibre Channel HBA Driver: %s\n"
 	    "  QLogic %s - %s\n"
@@ -1384,9 +1319,6 @@
 probe_failed:
 	fc_remove_host(ha->host);
 
-	scsi_remove_host(host);
-
-probe_alloc_failed:
 	qla2x00_free_device(ha);
 
 	scsi_host_put(host);
@@ -1394,7 +1326,8 @@
 probe_disable_device:
 	pci_disable_device(pdev);
 
-	return -1;
+probe_out:
+	return ret;
 }
 EXPORT_SYMBOL_GPL(qla2x00_probe_one);
 
@@ -2338,8 +2271,7 @@
 qla2x00_module_init(void)
 {
 	/* Allocate cache for SRBs. */
-	sprintf(srb_cachep_name, "qla2xxx_srbs");
-	srb_cachep = kmem_cache_create(srb_cachep_name, sizeof(srb_t), 0,
+	srb_cachep = kmem_cache_create("qla2xxx_srbs", sizeof(srb_t), 0,
 	    SLAB_HWCACHE_ALIGN, NULL, NULL);
 	if (srb_cachep == NULL) {
 		printk(KERN_ERR
@@ -2367,16 +2299,7 @@
 static void __exit
 qla2x00_module_exit(void)
 {
-	/* Free SRBs cache. */
-	if (srb_cachep != NULL) {
-		if (kmem_cache_destroy(srb_cachep) != 0) {
-			printk(KERN_ERR
-			    "qla2xxx: Unable to free SRB cache...Memory pools "
-			    "still active?\n");
-		}
-		srb_cachep = NULL;
-	}
-
+	kmem_cache_destroy(srb_cachep);
 	fc_release_transport(qla2xxx_transport_template);
 }
 
diff --git a/drivers/scsi/qlogicfas.c b/drivers/scsi/qlogicfas.c
index a1adb38..55e698b 100644
--- a/drivers/scsi/qlogicfas.c
+++ b/drivers/scsi/qlogicfas.c
@@ -191,8 +191,6 @@
 	.queuecommand		= qlogicfas408_queuecommand,
 	.eh_abort_handler	= qlogicfas408_abort,
 	.eh_bus_reset_handler	= qlogicfas408_bus_reset,
-	.eh_device_reset_handler= qlogicfas408_device_reset,
-	.eh_host_reset_handler	= qlogicfas408_host_reset,
 	.bios_param		= qlogicfas408_biosparam,
 	.can_queue		= 1,
 	.this_id		= -1,
diff --git a/drivers/scsi/qlogicfas408.c b/drivers/scsi/qlogicfas408.c
index 5b6ce0a..cb75e0b 100644
--- a/drivers/scsi/qlogicfas408.c
+++ b/drivers/scsi/qlogicfas408.c
@@ -511,29 +511,17 @@
 int qlogicfas408_bus_reset(Scsi_Cmnd * cmd)
 {
 	struct qlogicfas408_priv *priv = get_priv_by_cmd(cmd);
+	unsigned long flags;
+
 	priv->qabort = 2;
+
+	spin_lock_irqsave(cmd->device->host->host_lock, flags);
 	ql_zap(priv);
+	spin_unlock_irqrestore(cmd->device->host->host_lock, flags);
+
 	return SUCCESS;
 }
 
-/* 
- *	Reset SCSI host controller
- */
-
-int qlogicfas408_host_reset(Scsi_Cmnd * cmd)
-{
-	return FAILED;
-}
-
-/* 
- *	Reset SCSI device
- */
-
-int qlogicfas408_device_reset(Scsi_Cmnd * cmd)
-{
-	return FAILED;
-}
-
 /*
  *	Return info string
  */
@@ -626,8 +614,6 @@
 EXPORT_SYMBOL(qlogicfas408_queuecommand);
 EXPORT_SYMBOL(qlogicfas408_abort);
 EXPORT_SYMBOL(qlogicfas408_bus_reset);
-EXPORT_SYMBOL(qlogicfas408_device_reset);
-EXPORT_SYMBOL(qlogicfas408_host_reset);
 EXPORT_SYMBOL(qlogicfas408_biosparam);
 EXPORT_SYMBOL(qlogicfas408_ihandl);
 EXPORT_SYMBOL(qlogicfas408_get_chip_type);
diff --git a/drivers/scsi/qlogicfas408.h b/drivers/scsi/qlogicfas408.h
index f01cbd6..4b3df20 100644
--- a/drivers/scsi/qlogicfas408.h
+++ b/drivers/scsi/qlogicfas408.h
@@ -109,8 +109,6 @@
 			sector_t capacity, int ip[]);
 int qlogicfas408_abort(Scsi_Cmnd * cmd);
 int qlogicfas408_bus_reset(Scsi_Cmnd * cmd);
-int qlogicfas408_host_reset(Scsi_Cmnd * cmd);
-int qlogicfas408_device_reset(Scsi_Cmnd * cmd);
 const char *qlogicfas408_info(struct Scsi_Host *host);
 int qlogicfas408_get_chip_type(int qbase, int int_type);
 void qlogicfas408_setup(int qbase, int id, int int_type);
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
index b18c905..5c1d441 100644
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -59,6 +59,7 @@
 
 	board_2037x		= 0,	/* FastTrak S150 TX2plus */
 	board_20319		= 1,	/* FastTrak S150 TX4 */
+	board_20619		= 2,	/* FastTrak TX4000 */
 
 	PDC_HAS_PATA		= (1 << 1), /* PDC20375 has PATA */
 
@@ -147,6 +148,17 @@
 		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
 		.port_ops	= &pdc_ata_ops,
 	},
+
+	/* board_20619 */
+	{
+		.sht		= &pdc_ata_sht,
+		.host_flags	= ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST |
+				  ATA_FLAG_MMIO | ATA_FLAG_SLAVE_POSS,
+		.pio_mask	= 0x1f, /* pio0-4 */
+		.mwdma_mask	= 0x07, /* mwdma0-2 */
+		.udma_mask	= 0x7f, /* udma0-6 ; FIXME */
+		.port_ops	= &pdc_ata_ops,
+	},
 };
 
 static struct pci_device_id pdc_ata_pci_tbl[] = {
@@ -172,6 +184,9 @@
 	{ PCI_VENDOR_ID_PROMISE, 0x3d18, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
 	  board_20319 },
 
+	{ PCI_VENDOR_ID_PROMISE, 0x6629, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+	  board_20619 },
+
 	{ }	/* terminate list */
 };
 
@@ -636,6 +651,15 @@
 	case board_2037x:
        		probe_ent->n_ports = 2;
 		break;
+	case board_20619:
+		probe_ent->n_ports = 4;
+
+		pdc_ata_setup_port(&probe_ent->port[2], base + 0x300);
+		pdc_ata_setup_port(&probe_ent->port[3], base + 0x380);
+
+		probe_ent->port[2].scr_addr = base + 0x600;
+		probe_ent->port[3].scr_addr = base + 0x700;
+                break;
 	default:
 		BUG();
 		break;
@@ -676,7 +700,7 @@
 
 
 MODULE_AUTHOR("Jeff Garzik");
-MODULE_DESCRIPTION("Promise SATA TX2/TX4 low-level driver");
+MODULE_DESCRIPTION("Promise ATA TX2/TX4/TX4000 low-level driver");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, pdc_ata_pci_tbl);
 MODULE_VERSION(DRV_VERSION);
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index 238580d..49ed557 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -432,7 +432,13 @@
 		writeb(cls, mmio_base + SIL_FIFO_R0);
 		writeb(cls, mmio_base + SIL_FIFO_W0);
 		writeb(cls, mmio_base + SIL_FIFO_R1);
-		writeb(cls, mmio_base + SIL_FIFO_W2);
+		writeb(cls, mmio_base + SIL_FIFO_W1);
+		if (ent->driver_data == sil_3114) {
+			writeb(cls, mmio_base + SIL_FIFO_R2);
+			writeb(cls, mmio_base + SIL_FIFO_W2);
+			writeb(cls, mmio_base + SIL_FIFO_R3);
+			writeb(cls, mmio_base + SIL_FIFO_W3);
+		}
 	} else
 		printk(KERN_WARNING DRV_NAME "(%s): cache line size not set.  Driver may not function\n",
 			pci_name(pdev));
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index edef1fa..858e071 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -49,7 +49,7 @@
 #endif /* CONFIG_PPC_OF */
 
 #define DRV_NAME	"sata_svw"
-#define DRV_VERSION	"1.05"
+#define DRV_VERSION	"1.06"
 
 /* Taskfile registers offsets */
 #define K2_SATA_TF_CMD_OFFSET		0x00
@@ -344,6 +344,7 @@
 	void *mmio_base;
 	int pci_dev_busy = 0;
 	int rc;
+	int i;
 
 	if (!printed_version++)
 		printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
@@ -421,11 +422,11 @@
 	probe_ent->mwdma_mask = 0x7;
 	probe_ent->udma_mask = 0x7f;
 
-	/* We have 4 ports per PCI function */
-	k2_sata_setup_port(&probe_ent->port[0], base + 0 * K2_SATA_PORT_OFFSET);
-	k2_sata_setup_port(&probe_ent->port[1], base + 1 * K2_SATA_PORT_OFFSET);
-	k2_sata_setup_port(&probe_ent->port[2], base + 2 * K2_SATA_PORT_OFFSET);
-	k2_sata_setup_port(&probe_ent->port[3], base + 3 * K2_SATA_PORT_OFFSET);
+	/* different controllers have different number of ports - currently 4 or 8 */
+	/* All ports are on the same function. Multi-function device is no
+	 * longer available. This should not be seen in any system. */
+	for (i = 0; i < ent->driver_data; i++)
+		k2_sata_setup_port(&probe_ent->port[i], base + i * K2_SATA_PORT_OFFSET);
 
 	pci_set_master(pdev);
 
@@ -445,11 +446,17 @@
 	return rc;
 }
 
-
+/* 0x240 is device ID for Apple K2 device
+ * 0x241 is device ID for Serverworks Frodo4
+ * 0x242 is device ID for Serverworks Frodo8
+ * 0x24a is device ID for BCM5785 (aka HT1000) HT southbridge integrated SATA
+ * controller
+ * */
 static struct pci_device_id k2_sata_pci_tbl[] = {
-	{ 0x1166, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ 0x1166, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+	{ 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+	{ 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
+	{ 0x1166, 0x024a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
 	{ }
 };
 
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 184bcae..1cb5f7d 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -68,6 +68,8 @@
 #include "scsi_priv.h"
 #include "scsi_logging.h"
 
+static void scsi_done(struct scsi_cmnd *cmd);
+static int scsi_retry_command(struct scsi_cmnd *cmd);
 
 /*
  * Definitions and constants.
@@ -638,10 +640,12 @@
 	}
 	spin_unlock_irqrestore(host->host_lock, flags);
 	if (rtn) {
-		atomic_inc(&cmd->device->iodone_cnt);
-		scsi_queue_insert(cmd,
-				(rtn == SCSI_MLQUEUE_DEVICE_BUSY) ?
-				 rtn : SCSI_MLQUEUE_HOST_BUSY);
+		if (scsi_delete_timer(cmd)) {
+			atomic_inc(&cmd->device->iodone_cnt);
+			scsi_queue_insert(cmd,
+					  (rtn == SCSI_MLQUEUE_DEVICE_BUSY) ?
+					  rtn : SCSI_MLQUEUE_HOST_BUSY);
+		}
 		SCSI_LOG_MLQUEUE(3,
 		    printk("queuecommand : request rejected\n"));
 	}
@@ -739,7 +743,7 @@
  *
  * This function is interrupt context safe.
  */
-void scsi_done(struct scsi_cmnd *cmd)
+static void scsi_done(struct scsi_cmnd *cmd)
 {
 	/*
 	 * We don't have to worry about this one timing out any more.
@@ -834,7 +838,7 @@
  *              level drivers should not become re-entrant as a result of
  *              this.
  */
-int scsi_retry_command(struct scsi_cmnd *cmd)
+static int scsi_retry_command(struct scsi_cmnd *cmd)
 {
 	/*
 	 * Restore the SCSI command state.
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index e020888..322b5a4 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -1783,7 +1783,7 @@
 device_initcall(scsi_debug_init);
 module_exit(scsi_debug_exit);
 
-void pseudo_0_release(struct device * dev)
+static void pseudo_0_release(struct device * dev)
 {
 	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
 		printk(KERN_INFO "scsi_debug: pseudo_0_release() called\n");
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 2bf1ee2..ceb4e0c 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -434,8 +434,7 @@
 	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd:%p\n", __FUNCTION__,
 					  scmd));
 
-	if (scmd->device->host->eh_action)
-		up(scmd->device->host->eh_action);
+	up(scmd->device->host->eh_action);
 }
 
 /**
@@ -457,8 +456,7 @@
 		SCSI_LOG_ERROR_RECOVERY(3, printk("%s scmd: %p result: %x\n",
 					   __FUNCTION__, scmd, scmd->result));
 
-		if (scmd->device->host->eh_action)
-			up(scmd->device->host->eh_action);
+		up(scmd->device->host->eh_action);
 	}
 }
 
@@ -528,10 +526,8 @@
 		 * abort a timed out command or not.  not sure how
 		 * we should treat them differently anyways.
 		 */
-		spin_lock_irqsave(shost->host_lock, flags);
 		if (shost->hostt->eh_abort_handler)
 			shost->hostt->eh_abort_handler(scmd);
-		spin_unlock_irqrestore(shost->host_lock, flags);
 			
 		scmd->request->rq_status = RQ_SCSI_DONE;
 		scmd->owner = SCSI_OWNER_ERROR_HANDLER;
@@ -737,11 +733,8 @@
  **/
 static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
 {
-	unsigned long flags;
-	int rtn = FAILED;
-
 	if (!scmd->device->host->hostt->eh_abort_handler)
-		return rtn;
+		return FAILED;
 
 	/*
 	 * scsi_done was called just after the command timed out and before
@@ -752,11 +745,7 @@
 
 	scmd->owner = SCSI_OWNER_LOWLEVEL;
 
-	spin_lock_irqsave(scmd->device->host->host_lock, flags);
-	rtn = scmd->device->host->hostt->eh_abort_handler(scmd);
-	spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
-
-	return rtn;
+	return scmd->device->host->hostt->eh_abort_handler(scmd);
 }
 
 /**
@@ -770,6 +759,7 @@
 {
 	static unsigned char tur_command[6] = {TEST_UNIT_READY, 0, 0, 0, 0, 0};
 	int retry_cnt = 1, rtn;
+	int saved_result;
 
 retry_tur:
 	memcpy(scmd->cmnd, tur_command, sizeof(tur_command));
@@ -780,6 +770,7 @@
 	 */
 	memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));
 
+	saved_result = scmd->result;
 	scmd->request_buffer = NULL;
 	scmd->request_bufflen = 0;
 	scmd->use_sg = 0;
@@ -794,6 +785,7 @@
 	 * the original request, so let's restore the original data. (db)
 	 */
 	scsi_setup_cmd_retry(scmd);
+	scmd->result = saved_result;
 
 	/*
 	 * hey, we are done.  let's look to see what happened.
@@ -865,17 +857,14 @@
  **/
 static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
 {
-	unsigned long flags;
-	int rtn = FAILED;
+	int rtn;
 
 	if (!scmd->device->host->hostt->eh_device_reset_handler)
-		return rtn;
+		return FAILED;
 
 	scmd->owner = SCSI_OWNER_LOWLEVEL;
 
-	spin_lock_irqsave(scmd->device->host->host_lock, flags);
 	rtn = scmd->device->host->hostt->eh_device_reset_handler(scmd);
-	spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
 
 	if (rtn == SUCCESS) {
 		scmd->device->was_reset = 1;
@@ -896,6 +885,7 @@
 {
 	static unsigned char stu_command[6] = {START_STOP, 0, 0, 0, 1, 0};
 	int rtn;
+	int saved_result;
 
 	if (!scmd->device->allow_restart)
 		return 1;
@@ -908,6 +898,7 @@
 	 */
 	memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer));
 
+	saved_result = scmd->result;
 	scmd->request_buffer = NULL;
 	scmd->request_bufflen = 0;
 	scmd->use_sg = 0;
@@ -922,6 +913,7 @@
 	 * the original request, so let's restore the original data. (db)
 	 */
 	scsi_setup_cmd_retry(scmd);
+	scmd->result = saved_result;
 
 	/*
 	 * hey, we are done.  let's look to see what happened.
@@ -1061,9 +1053,7 @@
 	if (!scmd->device->host->hostt->eh_bus_reset_handler)
 		return FAILED;
 
-	spin_lock_irqsave(scmd->device->host->host_lock, flags);
 	rtn = scmd->device->host->hostt->eh_bus_reset_handler(scmd);
-	spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
 
 	if (rtn == SUCCESS) {
 		if (!scmd->device->host->hostt->skip_settle_delay)
@@ -1092,9 +1082,7 @@
 	if (!scmd->device->host->hostt->eh_host_reset_handler)
 		return FAILED;
 
-	spin_lock_irqsave(scmd->device->host->host_lock, flags);
 	rtn = scmd->device->host->hostt->eh_host_reset_handler(scmd);
-	spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
 
 	if (rtn == SUCCESS) {
 		if (!scmd->device->host->hostt->skip_settle_delay)
@@ -1561,6 +1549,11 @@
 							  scmd));
 				scsi_queue_insert(scmd, SCSI_MLQUEUE_EH_RETRY);
 		} else {
+			/*
+			 * If just we got sense for the device (called
+			 * scsi_eh_get_sense), scmd->result is already
+			 * set, do not set DRIVER_TIMEOUT.
+			 */
 			if (!scmd->result)
 				scmd->result |= (DRIVER_TIMEOUT << 24);
 			SCSI_LOG_ERROR_RECOVERY(3, printk("%s: flush finish"
@@ -1870,7 +1863,6 @@
 		rtn = FAILED;
 	}
 
-	scsi_delete_timer(scmd);
 	scsi_next_command(scmd);
 	return rtn;
 }
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index d18da21..621dee8 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -44,7 +44,7 @@
 #endif
 
 #define SP(x) { x, "sgpool-" #x } 
-struct scsi_host_sg_pool scsi_sg_pools[] = { 
+static struct scsi_host_sg_pool scsi_sg_pools[] = {
 	SP(8),
 	SP(16),
 	SP(32),
@@ -92,10 +92,12 @@
 	 */
 	sreq->sr_request->flags &= ~REQ_DONTPREP;
 	blk_insert_request(sreq->sr_device->request_queue, sreq->sr_request,
-		       	   at_head, sreq, 0);
+		       	   at_head, sreq);
 	return 0;
 }
 
+static void scsi_run_queue(struct request_queue *q);
+
 /*
  * Function:    scsi_queue_insert()
  *
@@ -119,18 +121,14 @@
 {
 	struct Scsi_Host *host = cmd->device->host;
 	struct scsi_device *device = cmd->device;
+	struct request_queue *q = device->request_queue;
+	unsigned long flags;
 
 	SCSI_LOG_MLQUEUE(1,
 		 printk("Inserting command %p into mlqueue\n", cmd));
 
 	/*
-	 * We are inserting the command into the ml queue.  First, we
-	 * cancel the timer, so it doesn't time out.
-	 */
-	scsi_delete_timer(cmd);
-
-	/*
-	 * Next, set the appropriate busy bit for the device/host.
+	 * Set the appropriate busy bit for the device/host.
 	 *
 	 * If the host/device isn't busy, assume that something actually
 	 * completed, and that we should be able to queue a command now.
@@ -160,17 +158,22 @@
 	scsi_device_unbusy(device);
 
 	/*
-	 * Insert this command at the head of the queue for it's device.
-	 * It will go before all other commands that are already in the queue.
+	 * Requeue this command.  It will go before all other commands
+	 * that are already in the queue.
 	 *
 	 * NOTE: there is magic here about the way the queue is plugged if
 	 * we have no outstanding commands.
 	 * 
-	 * Although this *doesn't* plug the queue, it does call the request
+	 * Although we *don't* plug the queue, we call the request
 	 * function.  The SCSI request function detects the blocked condition
 	 * and plugs the queue appropriately.
-	 */
-	blk_insert_request(device->request_queue, cmd->request, 1, cmd, 1);
+         */
+	spin_lock_irqsave(q->queue_lock, flags);
+	blk_requeue_request(q, cmd->request);
+	spin_unlock_irqrestore(q->queue_lock, flags);
+
+	scsi_run_queue(q);
+
 	return 0;
 }
 
@@ -485,8 +488,13 @@
  */
 static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd)
 {
+	unsigned long flags;
+
 	cmd->request->flags &= ~REQ_DONTPREP;
-	blk_insert_request(q, cmd->request, 1, cmd, 1);
+
+	spin_lock_irqsave(q->queue_lock, flags);
+	blk_requeue_request(q, cmd->request);
+	spin_unlock_irqrestore(q->queue_lock, flags);
 
 	scsi_run_queue(q);
 }
@@ -941,10 +949,8 @@
 	 * if sg table allocation fails, requeue request later.
 	 */
 	sgpnt = scsi_alloc_sgtable(cmd, GFP_ATOMIC);
-	if (unlikely(!sgpnt)) {
-		req->flags |= REQ_SPECIAL;
+	if (unlikely(!sgpnt))
 		return BLKPREP_DEFER;
-	}
 
 	cmd->request_buffer = (char *) sgpnt;
 	cmd->request_bufflen = req->nr_sectors << 9;
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index c01580df..96d4f74 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -61,8 +61,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_done(struct scsi_cmnd *cmd);
-extern int scsi_retry_command(struct scsi_cmnd *cmd);
 extern int scsi_insert_special_req(struct scsi_request *sreq, int);
 extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd,
 		struct scsi_request *sreq);
@@ -136,7 +134,6 @@
 #endif /* CONFIG_SYSCTL */
 
 /* scsi_sysfs.c */
-extern void scsi_device_dev_release(struct device *);
 extern int scsi_sysfs_add_sdev(struct scsi_device *);
 extern int scsi_sysfs_add_host(struct Scsi_Host *);
 extern int scsi_sysfs_register(void);
@@ -145,7 +142,6 @@
 extern int scsi_sysfs_target_initialize(struct scsi_device *);
 extern struct scsi_transport_template blank_transport_template;
 
-extern struct class sdev_class;
 extern struct bus_type scsi_bus_type;
 
 /* 
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 8d0d302..9fa2090 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -293,6 +293,10 @@
 {
 	struct device *parent = dev->parent;
 	struct scsi_target *starget = to_scsi_target(dev);
+	struct Scsi_Host *shost = dev_to_shost(parent);
+
+	if (shost->hostt->target_destroy)
+		shost->hostt->target_destroy(starget);
 	kfree(starget);
 	put_device(parent);
 }
@@ -360,9 +364,23 @@
 	list_add_tail(&starget->siblings, &shost->__targets);
 	spin_unlock_irqrestore(shost->host_lock, flags);
 	/* allocate and add */
-	transport_setup_device(&starget->dev);
-	device_add(&starget->dev);
-	transport_add_device(&starget->dev);
+	transport_setup_device(dev);
+	device_add(dev);
+	transport_add_device(dev);
+	if (shost->hostt->target_alloc) {
+		int error = shost->hostt->target_alloc(starget);
+
+		if(error) {
+			dev_printk(KERN_ERR, dev, "target allocation failed, error %d\n", error);
+			/* don't want scsi_target_reap to do the final
+			 * put because it will be under the host lock */
+			get_device(dev);
+			scsi_target_reap(starget);
+			put_device(dev);
+			return NULL;
+		}
+	}
+
 	return starget;
 
  found:
@@ -625,6 +643,7 @@
 	case TYPE_MEDIUM_CHANGER:
 	case TYPE_ENCLOSURE:
 	case TYPE_COMM:
+	case TYPE_RBC:
 		sdev->writeable = 1;
 		break;
 	case TYPE_WORM:
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index e75ee46..beed7fb 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -150,7 +150,7 @@
 	put_device(&sdev->sdev_gendev);
 }
 
-void scsi_device_dev_release(struct device *dev)
+static void scsi_device_dev_release(struct device *dev)
 {
 	struct scsi_device *sdev;
 	struct device *parent;
@@ -185,7 +185,7 @@
 		put_device(parent);
 }
 
-struct class sdev_class = {
+static struct class sdev_class = {
 	.name		= "scsi_device",
 	.release	= scsi_device_cls_release,
 };
@@ -230,7 +230,7 @@
  */
 #define sdev_show_function(field, format_string)				\
 static ssize_t								\
-sdev_show_##field (struct device *dev, char *buf)				\
+sdev_show_##field (struct device *dev, struct device_attribute *attr, char *buf)				\
 {									\
 	struct scsi_device *sdev;					\
 	sdev = to_scsi_device(dev);					\
@@ -254,7 +254,7 @@
 	sdev_show_function(field, format_string)				\
 									\
 static ssize_t								\
-sdev_store_##field (struct device *dev, const char *buf, size_t count)	\
+sdev_store_##field (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)	\
 {									\
 	struct scsi_device *sdev;					\
 	sdev = to_scsi_device(dev);					\
@@ -274,7 +274,7 @@
 	sdev_show_function(field, "%d\n")					\
 									\
 static ssize_t								\
-sdev_store_##field (struct device *dev, const char *buf, size_t count)	\
+sdev_store_##field (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)	\
 {									\
 	int ret;							\
 	struct scsi_device *sdev;					\
@@ -317,7 +317,7 @@
 sdev_rd_attr (rev, "%.4s\n");
 
 static ssize_t
-sdev_show_timeout (struct device *dev, char *buf)
+sdev_show_timeout (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct scsi_device *sdev;
 	sdev = to_scsi_device(dev);
@@ -325,7 +325,7 @@
 }
 
 static ssize_t
-sdev_store_timeout (struct device *dev, const char *buf, size_t count)
+sdev_store_timeout (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct scsi_device *sdev;
 	int timeout;
@@ -337,14 +337,14 @@
 static DEVICE_ATTR(timeout, S_IRUGO | S_IWUSR, sdev_show_timeout, sdev_store_timeout);
 
 static ssize_t
-store_rescan_field (struct device *dev, const char *buf, size_t count) 
+store_rescan_field (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	scsi_rescan_device(dev);
 	return count;
 }
 static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field);
 
-static ssize_t sdev_store_delete(struct device *dev, const char *buf,
+static ssize_t sdev_store_delete(struct device *dev, struct device_attribute *attr, const char *buf,
 				 size_t count)
 {
 	scsi_remove_device(to_scsi_device(dev));
@@ -353,7 +353,7 @@
 static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete);
 
 static ssize_t
-store_state_field(struct device *dev, const char *buf, size_t count)
+store_state_field(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	int i;
 	struct scsi_device *sdev = to_scsi_device(dev);
@@ -376,7 +376,7 @@
 }
 
 static ssize_t
-show_state_field(struct device *dev, char *buf)
+show_state_field(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct scsi_device *sdev = to_scsi_device(dev);
 	const char *name = scsi_device_state_name(sdev->sdev_state);
@@ -390,7 +390,7 @@
 static DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_state_field, store_state_field);
 
 static ssize_t
-show_queue_type_field(struct device *dev, char *buf)
+show_queue_type_field(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct scsi_device *sdev = to_scsi_device(dev);
 	const char *name = "none";
@@ -406,7 +406,7 @@
 static DEVICE_ATTR(queue_type, S_IRUGO, show_queue_type_field, NULL);
 
 static ssize_t
-show_iostat_counterbits(struct device *dev, char *buf)
+show_iostat_counterbits(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	return snprintf(buf, 20, "%d\n", (int)sizeof(atomic_t) * 8);
 }
@@ -415,7 +415,7 @@
 
 #define show_sdev_iostat(field)						\
 static ssize_t								\
-show_iostat_##field(struct device *dev, char *buf)			\
+show_iostat_##field(struct device *dev, struct device_attribute *attr, char *buf)			\
 {									\
 	struct scsi_device *sdev = to_scsi_device(dev);			\
 	unsigned long long count = atomic_read(&sdev->field);		\
@@ -449,7 +449,7 @@
 	NULL
 };
 
-static ssize_t sdev_store_queue_depth_rw(struct device *dev, const char *buf,
+static ssize_t sdev_store_queue_depth_rw(struct device *dev, struct device_attribute *attr, const char *buf,
 					 size_t count)
 {
 	int depth, retval;
@@ -475,7 +475,7 @@
 	__ATTR(queue_depth, S_IRUGO | S_IWUSR, sdev_show_queue_depth,
 	       sdev_store_queue_depth_rw);
 
-static ssize_t sdev_store_queue_type_rw(struct device *dev, const char *buf,
+static ssize_t sdev_store_queue_type_rw(struct device *dev, struct device_attribute *attr, const char *buf,
 					size_t count)
 {
 	struct scsi_device *sdev = to_scsi_device(dev);
@@ -669,6 +669,13 @@
 	scsi_target_reap(starget);
 }
 
+static int __remove_child (struct device * dev, void * data)
+{
+	if (scsi_is_target_device(dev))
+		__scsi_remove_target(to_scsi_target(dev));
+	return 0;
+}
+
 /**
  * scsi_remove_target - try to remove a target and all its devices
  * @dev: generic starget or parent of generic stargets to be removed
@@ -679,7 +686,7 @@
  */
 void scsi_remove_target(struct device *dev)
 {
-	struct device *rdev, *idev, *next;
+	struct device *rdev;
 
 	if (scsi_is_target_device(dev)) {
 		__scsi_remove_target(to_scsi_target(dev));
@@ -687,10 +694,7 @@
 	}
 
 	rdev = get_device(dev);
-	list_for_each_entry_safe(idev, next, &dev->children, node) {
-		if (scsi_is_target_device(idev))
-			__scsi_remove_target(to_scsi_target(idev));
-	}
+	device_for_each_child(dev, NULL, __remove_child);
 	put_device(rdev);
 }
 EXPORT_SYMBOL(scsi_remove_target);
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c
index 67c6cc4..2918b96 100644
--- a/drivers/scsi/scsi_transport_spi.c
+++ b/drivers/scsi/scsi_transport_spi.c
@@ -348,17 +348,21 @@
 spi_transport_rd_attr(rti, "%d\n");
 spi_transport_rd_attr(pcomp_en, "%d\n");
 
+/* we only care about the first child device so we return 1 */
+static int child_iter(struct device *dev, void *data)
+{
+	struct scsi_device *sdev = to_scsi_device(dev);
+
+	spi_dv_device(sdev);
+	return 1;
+}
+
 static ssize_t
 store_spi_revalidate(struct class_device *cdev, const char *buf, size_t count)
 {
 	struct scsi_target *starget = transport_class_to_starget(cdev);
 
-	/* FIXME: we're relying on an awful lot of device internals
-	 * here.  We really need a function to get the first available
-	 * child */
-	struct device *dev = container_of(starget->dev.children.next, struct device, node);
-	struct scsi_device *sdev = to_scsi_device(dev);
-	spi_dv_device(sdev);
+	device_for_each_child(&starget->dev, NULL, child_iter);
 	return count;
 }
 static CLASS_DEVICE_ATTR(revalidate, S_IWUSR, NULL, store_spi_revalidate);
@@ -669,6 +673,7 @@
 {
 	struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt);
 	struct scsi_device *sdev = sreq->sr_device;
+	struct scsi_target *starget = sdev->sdev_target;
 	int period = 0, prevperiod = 0; 
 	enum spi_compare_returns retval;
 
@@ -682,24 +687,40 @@
 			break;
 
 		/* OK, retrain, fallback */
+		if (i->f->get_iu)
+			i->f->get_iu(starget);
+		if (i->f->get_qas)
+			i->f->get_qas(starget);
 		if (i->f->get_period)
 			i->f->get_period(sdev->sdev_target);
-		newperiod = spi_period(sdev->sdev_target);
-		period = newperiod > period ? newperiod : period;
-		if (period < 0x0d)
-			period++;
-		else
-			period += period >> 1;
 
-		if (unlikely(period > 0xff || period == prevperiod)) {
-			/* Total failure; set to async and return */
-			SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation Failure, dropping back to Asynchronous\n");
-			DV_SET(offset, 0);
-			return SPI_COMPARE_FAILURE;
+		/* Here's the fallback sequence; first try turning off
+		 * IU, then QAS (if we can control them), then finally
+		 * fall down the periods */
+		if (i->f->set_iu && spi_iu(starget)) {
+			SPI_PRINTK(starget, KERN_ERR, "Domain Validation Disabing Information Units\n");
+			DV_SET(iu, 0);
+		} else if (i->f->set_qas && spi_qas(starget)) {
+			SPI_PRINTK(starget, KERN_ERR, "Domain Validation Disabing Quick Arbitration and Selection\n");
+			DV_SET(qas, 0);
+		} else {
+			newperiod = spi_period(starget);
+			period = newperiod > period ? newperiod : period;
+			if (period < 0x0d)
+				period++;
+			else
+				period += period >> 1;
+
+			if (unlikely(period > 0xff || period == prevperiod)) {
+				/* Total failure; set to async and return */
+				SPI_PRINTK(starget, KERN_ERR, "Domain Validation Failure, dropping back to Asynchronous\n");
+				DV_SET(offset, 0);
+				return SPI_COMPARE_FAILURE;
+			}
+			SPI_PRINTK(starget, KERN_ERR, "Domain Validation detected failure, dropping back\n");
+			DV_SET(period, period);
+			prevperiod = period;
 		}
-		SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation detected failure, dropping back\n");
-		DV_SET(period, period);
-		prevperiod = period;
 	}
 	return retval;
 }
@@ -768,23 +789,21 @@
 	
 	if (spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS)
 	    != SPI_COMPARE_SUCCESS) {
-		SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation Initial Inquiry Failed\n");
+		SPI_PRINTK(starget, KERN_ERR, "Domain Validation Initial Inquiry Failed\n");
 		/* FIXME: should probably offline the device here? */
 		return;
 	}
 
 	/* test width */
 	if (i->f->set_width && spi_max_width(starget) && sdev->wdtr) {
-		i->f->set_width(sdev->sdev_target, 1);
-
-		printk("WIDTH IS %d\n", spi_max_width(starget));
+		i->f->set_width(starget, 1);
 
 		if (spi_dv_device_compare_inquiry(sreq, buffer,
 						   buffer + len,
 						   DV_LOOPS)
 		    != SPI_COMPARE_SUCCESS) {
-			SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Wide Transfers Fail\n");
-			i->f->set_width(sdev->sdev_target, 0);
+			SPI_PRINTK(starget, KERN_ERR, "Wide Transfers Fail\n");
+			i->f->set_width(starget, 0);
 		}
 	}
 
@@ -792,7 +811,7 @@
 		return;
 
 	/* device can't handle synchronous */
-	if(!sdev->ppr && !sdev->sdtr)
+	if (!sdev->ppr && !sdev->sdtr)
 		return;
 
 	/* see if the device has an echo buffer.  If it does we can
@@ -807,16 +826,30 @@
 	/* now set up to the maximum */
 	DV_SET(offset, spi_max_offset(starget));
 	DV_SET(period, spi_min_period(starget));
+	/* try QAS requests; this should be harmless to set if the
+	 * target supports it */
+	DV_SET(qas, 1);
+	/* Also try IU transfers */
+	DV_SET(iu, 1);
+	if (spi_min_period(starget) < 9) {
+		/* This u320 (or u640). Ignore the coupled parameters
+		 * like DT and IU, but set the optional ones */
+		DV_SET(rd_strm, 1);
+		DV_SET(wr_flow, 1);
+		DV_SET(rti, 1);
+		if (spi_min_period(starget) == 8)
+			DV_SET(pcomp_en, 1);
+	}
 
 	if (len == 0) {
-		SPI_PRINTK(sdev->sdev_target, KERN_INFO, "Domain Validation skipping write tests\n");
+		SPI_PRINTK(starget, KERN_INFO, "Domain Validation skipping write tests\n");
 		spi_dv_retrain(sreq, buffer, buffer + len,
 			       spi_dv_device_compare_inquiry);
 		return;
 	}
 
 	if (len > SPI_MAX_ECHO_BUFFER_SIZE) {
-		SPI_PRINTK(sdev->sdev_target, KERN_WARNING, "Echo buffer size %d is too big, trimming to %d\n", len, SPI_MAX_ECHO_BUFFER_SIZE);
+		SPI_PRINTK(starget, KERN_WARNING, "Echo buffer size %d is too big, trimming to %d\n", len, SPI_MAX_ECHO_BUFFER_SIZE);
 		len = SPI_MAX_ECHO_BUFFER_SIZE;
 	}
 
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 19afb25..bb823559 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1368,17 +1368,26 @@
  */
 static void
 sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
-		   struct scsi_request *SRpnt, unsigned char *buffer) {
+		   struct scsi_request *SRpnt, unsigned char *buffer)
+{
 	int len = 0, res;
 
-	const int dbd = 0;	   /* DBD */
-	const int modepage = 0x08; /* current values, cache page */
+	int dbd;
+	int modepage;
 	struct scsi_mode_data data;
 	struct scsi_sense_hdr sshdr;
 
 	if (sdkp->device->skip_ms_page_8)
 		goto defaults;
 
+	if (sdkp->device->type == TYPE_RBC) {
+		modepage = 6;
+		dbd = 8;
+	} else {
+		modepage = 8;
+		dbd = 0;
+	}
+
 	/* cautiously ask */
 	res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, 4, &data);
 
@@ -1409,11 +1418,20 @@
 			"write back, no read (daft)"
 		};
 		int ct = 0;
-		int offset = data.header_length +
-			data.block_descriptor_length + 2;
+		int offset = data.header_length + data.block_descriptor_length;
 
-		sdkp->WCE = ((buffer[offset] & 0x04) != 0);
-		sdkp->RCD = ((buffer[offset] & 0x01) != 0);
+		if ((buffer[offset] & 0x3f) != modepage) {
+			printk(KERN_ERR "%s: got wrong page\n", diskname);
+			goto defaults;
+		}
+
+		if (modepage == 8) {
+			sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0);
+			sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0);
+		} else {
+			sdkp->WCE = ((buffer[offset + 2] & 0x01) == 0);
+			sdkp->RCD = 0;
+		}
 
 		ct =  sdkp->RCD + 2*sdkp->WCE;
 
@@ -1533,7 +1551,7 @@
 	int error;
 
 	error = -ENODEV;
-	if ((sdp->type != TYPE_DISK) && (sdp->type != TYPE_MOD))
+	if (sdp->type != TYPE_DISK && sdp->type != TYPE_MOD && sdp->type != TYPE_RBC)
 		goto out;
 
 	SCSI_LOG_HLQUEUE(3, printk("sd_attach: scsi device: <%d,%d,%d,%d>\n", 
@@ -1570,7 +1588,7 @@
 	sdkp->openers = 0;
 
 	if (!sdp->timeout) {
-		if (sdp->type == TYPE_DISK)
+		if (sdp->type != TYPE_MOD)
 			sdp->timeout = SD_TIMEOUT;
 		else
 			sdp->timeout = SD_MOD_TIMEOUT;
diff --git a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c
index 4c95abb..a0cace9 100644
--- a/drivers/scsi/seagate.c
+++ b/drivers/scsi/seagate.c
@@ -97,6 +97,7 @@
 #include <linux/delay.h>
 #include <linux/blkdev.h>
 #include <linux/stat.h>
+#include <linux/delay.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
@@ -1631,7 +1632,7 @@
 	/* assert  RESET signal on SCSI bus.  */
 	WRITE_CONTROL (BASE_CMD | CMD_RST);
 
-	udelay (20 * 1000);
+	mdelay (20);
 
 	WRITE_CONTROL (BASE_CMD);
 	st0x_aborted = DID_RESET;
@@ -1640,16 +1641,6 @@
 	return SUCCESS;
 }
 
-static int seagate_st0x_host_reset(Scsi_Cmnd *SCpnt)
-{
-	return FAILED;
-}
-
-static int seagate_st0x_device_reset(Scsi_Cmnd *SCpnt)
-{
-	return FAILED;
-}
-
 static int seagate_st0x_release(struct Scsi_Host *shost)
 {
 	if (shost->irq)
@@ -1665,8 +1656,6 @@
 	.queuecommand   	= seagate_st0x_queue_command,
 	.eh_abort_handler	= seagate_st0x_abort,
 	.eh_bus_reset_handler	= seagate_st0x_bus_reset,
-	.eh_host_reset_handler	= seagate_st0x_host_reset,
-	.eh_device_reset_handler = seagate_st0x_device_reset,
 	.can_queue      	= 1,
 	.this_id        	= 7,
 	.sg_tablesize   	= SG_ALL,
diff --git a/drivers/scsi/seagate.h b/drivers/scsi/seagate.h
index e49e8ec..8889ff1 100644
--- a/drivers/scsi/seagate.h
+++ b/drivers/scsi/seagate.h
@@ -15,7 +15,5 @@
 static int seagate_st0x_abort(Scsi_Cmnd *);
 static const char *seagate_st0x_info(struct Scsi_Host *);
 static int seagate_st0x_bus_reset(Scsi_Cmnd *);
-static int seagate_st0x_device_reset(Scsi_Cmnd *);
-static int seagate_st0x_host_reset(Scsi_Cmnd *);
 
 #endif /* _SEAGATE_H */
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 7936aaf..51292f2 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1430,7 +1430,7 @@
 	.fasync = sg_fasync,
 };
 
-static struct class_simple * sg_sysfs_class;
+static struct class *sg_sysfs_class;
 
 static int sg_sysfs_valid = 0;
 
@@ -1551,13 +1551,13 @@
 	if (sg_sysfs_valid) {
 		struct class_device * sg_class_member;
 
-		sg_class_member = class_simple_device_add(sg_sysfs_class, 
+		sg_class_member = class_device_create(sg_sysfs_class,
 				MKDEV(SCSI_GENERIC_MAJOR, k), 
 				cl_dev->dev, "%s", 
 				disk->disk_name);
 		if (IS_ERR(sg_class_member))
 			printk(KERN_WARNING "sg_add: "
-				"class_simple_device_add failed\n");
+				"class_device_create failed\n");
 		class_set_devdata(sg_class_member, sdp);
 		error = sysfs_create_link(&scsidp->sdev_gendev.kobj, 
 					  &sg_class_member->kobj, "generic");
@@ -1636,7 +1636,7 @@
 
 	if (sdp) {
 		sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic");
-		class_simple_device_remove(MKDEV(SCSI_GENERIC_MAJOR, k));
+		class_device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, k));
 		cdev_del(sdp->cdev);
 		sdp->cdev = NULL;
 		devfs_remove("%s/generic", scsidp->devfs_name);
@@ -1677,7 +1677,7 @@
 				    SG_MAX_DEVS, "sg");
 	if (rc)
 		return rc;
-        sg_sysfs_class = class_simple_create(THIS_MODULE, "scsi_generic");
+        sg_sysfs_class = class_create(THIS_MODULE, "scsi_generic");
         if ( IS_ERR(sg_sysfs_class) ) {
 		rc = PTR_ERR(sg_sysfs_class);
 		goto err_out;
@@ -1690,7 +1690,7 @@
 #endif				/* CONFIG_SCSI_PROC_FS */
 		return 0;
 	}
-	class_simple_destroy(sg_sysfs_class);
+	class_destroy(sg_sysfs_class);
 err_out:
 	unregister_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0), SG_MAX_DEVS);
 	return rc;
@@ -1703,7 +1703,7 @@
 	sg_proc_cleanup();
 #endif				/* CONFIG_SCSI_PROC_FS */
 	scsi_unregister_interface(&sg_interface);
-	class_simple_destroy(sg_sysfs_class);
+	class_destroy(sg_sysfs_class);
 	sg_sysfs_valid = 0;
 	unregister_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0),
 				 SG_MAX_DEVS);
@@ -2472,6 +2472,8 @@
 	if ((!sfp) || (!srp) || (!sfp->headrp))
 		return res;
 	write_lock_irqsave(&sfp->rq_list_lock, iflags);
+	if (srp->my_cmdp)
+		srp->my_cmdp->upper_private_data = NULL;
 	prev_rp = sfp->headrp;
 	if (srp == prev_rp) {
 		sfp->headrp = prev_rp->nextrp;
diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c
index 270f2aa..a5ba2c6 100644
--- a/drivers/scsi/sgiwd93.c
+++ b/drivers/scsi/sgiwd93.c
@@ -310,7 +310,14 @@
 static int sgiwd93_bus_reset(Scsi_Cmnd *cmd)
 {
 	/* FIXME perform bus-specific reset */
+
+	/* FIXME 2: kill this function, and let midlayer fallback
+	   to the same result, calling wd33c93_host_reset() */
+
+	spin_lock_irq(cmd->device->host->host_lock);
 	wd33c93_host_reset(cmd);
+	spin_unlock_irq(cmd->device->host->host_lock);
+
 	return SUCCESS;
 }
 
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 265d1ee..0291a8f 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -17,7 +17,7 @@
    Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
  */
 
-static char *verstr = "20050312";
+static char *verstr = "20050501";
 
 #include <linux/module.h>
 
@@ -29,6 +29,7 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/mtio.h>
+#include <linux/cdrom.h>
 #include <linux/ioctl.h>
 #include <linux/fcntl.h>
 #include <linux/spinlock.h>
@@ -50,6 +51,7 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_ioctl.h>
 #include <scsi/scsi_request.h>
+#include <scsi/sg.h>
 
 
 /* The driver prints some debugging information on the console if DEBUG
@@ -82,7 +84,7 @@
 static int st_dev_max;
 static int st_nr_dev;
 
-static struct class_simple *st_sysfs_class;
+static struct class *st_sysfs_class;
 
 MODULE_AUTHOR("Kai Makisara");
 MODULE_DESCRIPTION("SCSI Tape Driver");
@@ -3463,7 +3465,10 @@
 		case SCSI_IOCTL_GET_BUS_NUMBER:
 			break;
 		default:
-			if (!capable(CAP_SYS_ADMIN))
+			if ((cmd_in == SG_IO ||
+			     cmd_in == SCSI_IOCTL_SEND_COMMAND ||
+			     cmd_in == CDROM_SEND_PACKET) &&
+			    !capable(CAP_SYS_RAWIO))
 				i = -EPERM;
 			else
 				i = scsi_cmd_ioctl(file, STp->disk, cmd_in, p);
@@ -3471,10 +3476,12 @@
 				return i;
 			break;
 	}
-	if (!capable(CAP_SYS_ADMIN) &&
-	    (cmd_in == SCSI_IOCTL_START_UNIT || cmd_in == SCSI_IOCTL_STOP_UNIT))
-		return -EPERM;
-	return scsi_ioctl(STp->device, cmd_in, p);
+	retval = scsi_ioctl(STp->device, cmd_in, p);
+	if (!retval && cmd_in == SCSI_IOCTL_STOP_UNIT) { /* unload */
+		STp->rew_at_close = 0;
+		STp->ready = ST_NO_TAPE;
+	}
+	return retval;
 
  out:
 	up(&STp->lock);
@@ -4017,8 +4024,9 @@
 			if (STm->cdevs[j]) {
 				if (cdev == STm->cdevs[j])
 					cdev = NULL;
-				class_simple_device_remove(MKDEV(SCSI_TAPE_MAJOR,
-								 TAPE_MINOR(i, mode, j)));
+				class_device_destroy(st_sysfs_class,
+						     MKDEV(SCSI_TAPE_MAJOR,
+							   TAPE_MINOR(i, mode, j)));
 				cdev_del(STm->cdevs[j]);
 			}
 		}
@@ -4061,8 +4069,9 @@
 				devfs_remove("%s/mt%s", SDp->devfs_name, st_formats[j]);
 				devfs_remove("%s/mt%sn", SDp->devfs_name, st_formats[j]);
 				for (j=0; j < 2; j++) {
-					class_simple_device_remove(MKDEV(SCSI_TAPE_MAJOR,
-									 TAPE_MINOR(i, mode, j)));
+					class_device_destroy(st_sysfs_class,
+							     MKDEV(SCSI_TAPE_MAJOR,
+								   TAPE_MINOR(i, mode, j)));
 					cdev_del(tpnt->modes[mode].cdevs[j]);
 					tpnt->modes[mode].cdevs[j] = NULL;
 				}
@@ -4127,7 +4136,7 @@
 		"st: Version %s, fixed bufsize %d, s/g segs %d\n",
 		verstr, st_fixed_buffer_size, st_max_sg_segs);
 
-	st_sysfs_class = class_simple_create(THIS_MODULE, "scsi_tape");
+	st_sysfs_class = class_create(THIS_MODULE, "scsi_tape");
 	if (IS_ERR(st_sysfs_class)) {
 		st_sysfs_class = NULL;
 		printk(KERN_ERR "Unable create sysfs class for SCSI tapes\n");
@@ -4141,7 +4150,7 @@
 			return 0;
 		}
 		if (st_sysfs_class)
-			class_simple_destroy(st_sysfs_class);		
+			class_destroy(st_sysfs_class);
 		unregister_chrdev_region(MKDEV(SCSI_TAPE_MAJOR, 0),
 
 					 ST_MAX_TAPE_ENTRIES);
@@ -4154,7 +4163,7 @@
 static void __exit exit_st(void)
 {
 	if (st_sysfs_class)
-		class_simple_destroy(st_sysfs_class);
+		class_destroy(st_sysfs_class);
 	st_sysfs_class = NULL;
 	do_remove_driverfs_files();
 	scsi_unregister_driver(&st_template.gendrv);
@@ -4277,12 +4286,12 @@
 		snprintf(name, 10, "%s%s%s", rew ? "n" : "",
 			 STp->disk->disk_name, st_formats[i]);
 		st_class_member =
-			class_simple_device_add(st_sysfs_class,
-						MKDEV(SCSI_TAPE_MAJOR,
-						      TAPE_MINOR(dev_num, mode, rew)),
-						&STp->device->sdev_gendev, "%s", name);
+			class_device_create(st_sysfs_class,
+					    MKDEV(SCSI_TAPE_MAJOR,
+						  TAPE_MINOR(dev_num, mode, rew)),
+					    &STp->device->sdev_gendev, "%s", name);
 		if (IS_ERR(st_class_member)) {
-			printk(KERN_WARNING "st%d: class_simple_device_add failed\n",
+			printk(KERN_WARNING "st%d: class_device_create failed\n",
 			       dev_num);
 			goto out;
 		}
diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c
index 5d1dc0e..09d7639 100644
--- a/drivers/scsi/sun3x_esp.c
+++ b/drivers/scsi/sun3x_esp.c
@@ -23,8 +23,6 @@
 #include <asm/dvma.h>
 #include <asm/irq.h>
 
-extern struct NCR_ESP *espchain;
-
 static void dma_barrier(struct NCR_ESP *esp);
 static int  dma_bytes_sent(struct NCR_ESP *esp, int fifo_count);
 static int  dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp);
diff --git a/drivers/scsi/sym53c416.c b/drivers/scsi/sym53c416.c
index ebfddd4..ef19adc 100644
--- a/drivers/scsi/sym53c416.c
+++ b/drivers/scsi/sym53c416.c
@@ -785,26 +785,14 @@
 	return 0;
 }
 
-static int sym53c416_abort(Scsi_Cmnd *SCpnt)
-{
-	return FAILED;
-}
-
-static int sym53c416_bus_reset(Scsi_Cmnd *SCpnt)
-{
-	return FAILED;
-}
-
-static int sym53c416_device_reset(Scsi_Cmnd *SCpnt)
-{
-	return FAILED;
-}
-
 static int sym53c416_host_reset(Scsi_Cmnd *SCpnt)
 {
 	int base;
 	int scsi_id = -1;	
 	int i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&sym53c416_lock, flags);
 
 	/* printk("sym53c416_reset\n"); */
 	base = SCpnt->device->host->io_port;
@@ -816,6 +804,8 @@
 	outb(NOOP | PIO_MODE, base + COMMAND_REG);
 	outb(RESET_SCSI_BUS, base + COMMAND_REG);
 	sym53c416_init(base, scsi_id);
+
+	spin_unlock_irqrestore(&sym53c416_lock, flags);
 	return SUCCESS;
 }
 
@@ -865,10 +855,7 @@
 	.detect =		sym53c416_detect,
 	.info =			sym53c416_info,	
 	.queuecommand =		sym53c416_queuecommand,
-	.eh_abort_handler =	sym53c416_abort,
 	.eh_host_reset_handler =sym53c416_host_reset,
-	.eh_bus_reset_handler = sym53c416_bus_reset,
-	.eh_device_reset_handler =sym53c416_device_reset,
 	.release = 		sym53c416_release,
 	.bios_param =		sym53c416_bios_param,
 	.can_queue =		1,
diff --git a/drivers/scsi/sym53c416.h b/drivers/scsi/sym53c416.h
index 3c0e3f8..fd6b120 100644
--- a/drivers/scsi/sym53c416.h
+++ b/drivers/scsi/sym53c416.h
@@ -26,10 +26,7 @@
 static const char *sym53c416_info(struct Scsi_Host *);
 static int sym53c416_release(struct Scsi_Host *);
 static int sym53c416_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-static int sym53c416_abort(Scsi_Cmnd *);
 static int sym53c416_host_reset(Scsi_Cmnd *);
-static int sym53c416_bus_reset(Scsi_Cmnd *);
-static int sym53c416_device_reset(Scsi_Cmnd *);
 static int sym53c416_bios_param(struct scsi_device *, struct block_device *,
 		sector_t, int *);
 static void sym53c416_setup(char *str, int *ints);
diff --git a/drivers/scsi/sym53c8xx_2/sym_defs.h b/drivers/scsi/sym53c8xx_2/sym_defs.h
index 15bb891..2d9437d 100644
--- a/drivers/scsi/sym53c8xx_2/sym_defs.h
+++ b/drivers/scsi/sym53c8xx_2/sym_defs.h
@@ -40,7 +40,7 @@
 #ifndef SYM_DEFS_H
 #define SYM_DEFS_H
 
-#define SYM_VERSION "2.2.0"
+#define SYM_VERSION "2.2.1"
 #define SYM_DRIVER_NAME	"sym-" SYM_VERSION
 
 /*
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index 5b07c6e..d76766c 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -155,10 +155,11 @@
 	base = tmp;
 	if ((tmp & 0x7) == PCI_BASE_ADDRESS_MEM_TYPE_64) {
 		pci_read_config_dword(pdev, PCI_BAR_OFFSET(index++), &tmp);
-		if (tmp > 0)
+		if (tmp > 0) {
 			dev_err(&pdev->dev,
 				"BAR %d is 64-bit, disabling\n", index - 1);
-		base = 0;
+			base = 0;
+		}
 	}
 
 	if ((base & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
@@ -389,13 +390,20 @@
 {
 	struct sym_tblmove *data = &cp->phys.data[SYM_CONF_MAX_SG-1];
 	int segment;
+	unsigned int len = cmd->request_bufflen;
 
-	cp->data_len = cmd->request_bufflen;
-
-	if (cmd->request_bufflen) {
+	if (len) {
 		dma_addr_t baddr = map_scsi_single_data(np, cmd);
 		if (baddr) {
-			sym_build_sge(np, data, baddr, cmd->request_bufflen);
+			if (len & 1) {
+				struct sym_tcb *tp = &np->target[cp->target];
+				if (tp->head.wval & EWS) {
+					len++;
+					cp->odd_byte_adjustment++;
+				}
+			}
+			cp->data_len = len;
+			sym_build_sge(np, data, baddr, len);
 			segment = 1;
 		} else {
 			segment = -2;
@@ -418,6 +426,7 @@
 		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 sym_tcb *tp = &np->target[cp->target];
 		struct sym_tblmove *data;
 
 		if (use_sg > SYM_CONF_MAX_SG) {
@@ -431,6 +440,11 @@
 			dma_addr_t baddr = sg_dma_address(&scatter[segment]);
 			unsigned int len = sg_dma_len(&scatter[segment]);
 
+			if ((len & 1) && (tp->head.wval & EWS)) {
+				len++;
+				cp->odd_byte_adjustment++;
+			}
+
 			sym_build_sge(np, &data[segment], baddr, len);
 			cp->data_len += len;
 		}
@@ -456,10 +470,8 @@
 	 *  Minimal checkings, so that we will not 
 	 *  go outside our tables.
 	 */
-	if (sdev->id == np->myaddr ||
-	    sdev->id >= SYM_CONF_MAX_TARGET ||
-	    sdev->lun >= SYM_CONF_MAX_LUN) {
-		sym_xpt_done2(np, cmd, CAM_DEV_NOT_THERE);
+	if (sdev->id == np->myaddr) {
+		sym_xpt_done2(np, cmd, DID_NO_CONNECT);
 		return 0;
 	}
 
@@ -469,28 +481,6 @@
 	tp = &np->target[sdev->id];
 
 	/*
-	 *  Complete the 1st INQUIRY command with error 
-	 *  condition if the device is flagged NOSCAN 
-	 *  at BOOT in the NVRAM. This may speed up 
-	 *  the boot and maintain coherency with BIOS 
-	 *  device numbering. Clearing the flag allows 
-	 *  user to rescan skipped devices later.
-	 *  We also return error for devices not flagged 
-	 *  for SCAN LUNS in the NVRAM since some mono-lun 
-	 *  devices behave badly when asked for some non 
-	 *  zero LUN. Btw, this is an absolute hack.:-)
-	 */
-	if (cmd->cmnd[0] == 0x12 || cmd->cmnd[0] == 0x0) {
-		if ((tp->usrflags & SYM_SCAN_BOOT_DISABLED) ||
-		    ((tp->usrflags & SYM_SCAN_LUNS_DISABLED) && 
-		     sdev->lun != 0)) {
-			tp->usrflags &= ~SYM_SCAN_BOOT_DISABLED;
-			sym_xpt_done2(np, cmd, CAM_DEV_NOT_THERE);
-			return 0;
-		}
-	}
-
-	/*
 	 *  Select tagged/untagged.
 	 */
 	lp = sym_lp(tp, sdev->lun);
@@ -511,23 +501,10 @@
  */
 static inline int sym_setup_cdb(struct sym_hcb *np, struct scsi_cmnd *cmd, struct sym_ccb *cp)
 {
-	u32	cmd_ba;
-	int	cmd_len;
-
-	/*
-	 *  CDB is 16 bytes max.
-	 */
-	if (cmd->cmd_len > sizeof(cp->cdb_buf)) {
-		sym_set_cam_status(cp->cmd, CAM_REQ_INVALID);
-		return -1;
-	}
-
 	memcpy(cp->cdb_buf, cmd->cmnd, cmd->cmd_len);
-	cmd_ba  = CCB_BA (cp, cdb_buf[0]);
-	cmd_len = cmd->cmd_len;
 
-	cp->phys.cmd.addr	= cpu_to_scr(cmd_ba);
-	cp->phys.cmd.size	= cpu_to_scr(cmd_len);
+	cp->phys.cmd.addr = CCB_BA(cp, cdb_buf[0]);
+	cp->phys.cmd.size = cpu_to_scr(cmd->cmd_len);
 
 	return 0;
 }
@@ -554,10 +531,7 @@
 	if (dir != DMA_NONE) {
 		cp->segments = sym_scatter(np, cp, cmd);
 		if (cp->segments < 0) {
-			if (cp->segments == -2)
-				sym_set_cam_status(cmd, CAM_RESRC_UNAVAIL);
-			else
-				sym_set_cam_status(cmd, CAM_REQ_TOO_BIG);
+			sym_set_cam_status(cmd, DID_ERROR);
 			goto out_abort;
 		}
 	} else {
@@ -855,7 +829,7 @@
 	ep->to_do = to_do;
 	/* Complete the command with locks held as required by the driver */
 	if (to_do == SYM_EH_DO_COMPLETE)
-		sym_xpt_done2(np, cmd, CAM_REQ_ABORTED);
+		sym_xpt_done2(np, cmd, DID_ABORT);
 
 	/* Wait for completion with locks released, as required by kernel */
 	if (to_do == SYM_EH_DO_WAIT) {
@@ -882,22 +856,46 @@
  */
 static int sym53c8xx_eh_abort_handler(struct scsi_cmnd *cmd)
 {
-	return sym_eh_handler(SYM_EH_ABORT, "ABORT", cmd);
+	int rc;
+
+	spin_lock_irq(cmd->device->host->host_lock);
+	rc = sym_eh_handler(SYM_EH_ABORT, "ABORT", cmd);
+	spin_unlock_irq(cmd->device->host->host_lock);
+
+	return rc;
 }
 
 static int sym53c8xx_eh_device_reset_handler(struct scsi_cmnd *cmd)
 {
-	return sym_eh_handler(SYM_EH_DEVICE_RESET, "DEVICE RESET", cmd);
+	int rc;
+
+	spin_lock_irq(cmd->device->host->host_lock);
+	rc = sym_eh_handler(SYM_EH_DEVICE_RESET, "DEVICE RESET", cmd);
+	spin_unlock_irq(cmd->device->host->host_lock);
+
+	return rc;
 }
 
 static int sym53c8xx_eh_bus_reset_handler(struct scsi_cmnd *cmd)
 {
-	return sym_eh_handler(SYM_EH_BUS_RESET, "BUS RESET", cmd);
+	int rc;
+
+	spin_lock_irq(cmd->device->host->host_lock);
+	rc = sym_eh_handler(SYM_EH_BUS_RESET, "BUS RESET", cmd);
+	spin_unlock_irq(cmd->device->host->host_lock);
+
+	return rc;
 }
 
 static int sym53c8xx_eh_host_reset_handler(struct scsi_cmnd *cmd)
 {
-	return sym_eh_handler(SYM_EH_HOST_RESET, "HOST RESET", cmd);
+	int rc;
+
+	spin_lock_irq(cmd->device->host->host_lock);
+	rc = sym_eh_handler(SYM_EH_HOST_RESET, "HOST RESET", cmd);
+	spin_unlock_irq(cmd->device->host->host_lock);
+
+	return rc;
 }
 
 /*
@@ -921,7 +919,7 @@
 	lp->s.reqtags     = reqtags;
 
 	if (reqtags != oldtags) {
-		dev_info(&tp->sdev->sdev_target->dev,
+		dev_info(&tp->starget->dev,
 		         "tagged command queuing %s, command queue depth %d.\n",
 		          lp->s.reqtags ? "enabled" : "disabled",
  		          lp->started_limit);
@@ -981,24 +979,36 @@
 	return DEF_DEPTH;
 }
 
-static int sym53c8xx_slave_alloc(struct scsi_device *device)
+static int sym53c8xx_slave_alloc(struct scsi_device *sdev)
 {
-	struct sym_hcb *np = sym_get_hcb(device->host);
-	struct sym_tcb *tp = &np->target[device->id];
-	if (!tp->sdev)
-		tp->sdev = device;
+	struct sym_hcb *np;
+	struct sym_tcb *tp;
 
+	if (sdev->id >= SYM_CONF_MAX_TARGET || sdev->lun >= SYM_CONF_MAX_LUN)
+		return -ENXIO;
+
+	np = sym_get_hcb(sdev->host);
+	tp = &np->target[sdev->id];
+
+	/*
+	 * Fail the device init if the device is flagged NOSCAN at BOOT in
+	 * the NVRAM.  This may speed up boot and maintain coherency with
+	 * BIOS device numbering.  Clearing the flag allows the user to
+	 * rescan skipped devices later.  We also return an error for
+	 * devices not flagged for SCAN LUNS in the NVRAM since some single
+	 * lun devices behave badly when asked for a non zero LUN.
+	 */
+
+	if ((tp->usrflags & SYM_SCAN_BOOT_DISABLED) ||
+	    ((tp->usrflags & SYM_SCAN_LUNS_DISABLED) && sdev->lun != 0)) {
+		tp->usrflags &= ~SYM_SCAN_BOOT_DISABLED;
+		return -ENXIO;
+	}
+
+	tp->starget = sdev->sdev_target;
 	return 0;
 }
 
-static void sym53c8xx_slave_destroy(struct scsi_device *device)
-{
-	struct sym_hcb *np = sym_get_hcb(device->host);
-	struct sym_tcb *tp = &np->target[device->id];
-	if (tp->sdev == device)
-		tp->sdev = NULL;
-}
-
 /*
  * Linux entry point for device queue sizing.
  */
@@ -1897,6 +1907,7 @@
 	 */
 	printk("%s: resetting chip\n", sym_name(np));
 	OUTB(np, nc_istat, SRST);
+	INB(np, nc_mbox1);
 	udelay(10);
 	OUTB(np, nc_istat, 0);
 
@@ -1915,7 +1926,6 @@
 	.queuecommand		= sym53c8xx_queue_command,
 	.slave_alloc		= sym53c8xx_slave_alloc,
 	.slave_configure	= sym53c8xx_slave_configure,
-	.slave_destroy		= sym53c8xx_slave_destroy,
 	.eh_abort_handler	= sym53c8xx_eh_abort_handler,
 	.eh_device_reset_handler = sym53c8xx_eh_device_reset_handler,
 	.eh_bus_reset_handler	= sym53c8xx_eh_bus_reset_handler,
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h
index e943f16..d3d52f1 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.h
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.h
@@ -142,33 +142,6 @@
 #define scr_to_cpu(dw)	le32_to_cpu(dw)
 
 /*
- *  Remap some status field values.
- */
-#define CAM_REQ_CMP		DID_OK
-#define CAM_SEL_TIMEOUT		DID_NO_CONNECT
-#define CAM_CMD_TIMEOUT		DID_TIME_OUT
-#define CAM_REQ_ABORTED		DID_ABORT
-#define CAM_UNCOR_PARITY	DID_PARITY
-#define CAM_SCSI_BUS_RESET	DID_RESET	
-#define CAM_REQUEUE_REQ		DID_SOFT_ERROR
-#define	CAM_UNEXP_BUSFREE	DID_ERROR
-#define	CAM_SCSI_BUSY		DID_BUS_BUSY
-
-#define	CAM_DEV_NOT_THERE	DID_NO_CONNECT
-#define	CAM_REQ_INVALID		DID_ERROR
-#define	CAM_REQ_TOO_BIG		DID_ERROR
-
-#define	CAM_RESRC_UNAVAIL	DID_ERROR
-
-/*
- *  Remap data direction values.
- */
-#define CAM_DIR_NONE		DMA_NONE
-#define CAM_DIR_IN		DMA_FROM_DEVICE
-#define CAM_DIR_OUT		DMA_TO_DEVICE
-#define CAM_DIR_UNKNOWN		DMA_BIDIRECTIONAL
-
-/*
  *  These ones are used as return code from 
  *  error recovery handlers under Linux.
  */
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index 50a176b..e753ba2 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -97,7 +97,7 @@
 static void sym_print_nego_msg(struct sym_hcb *np, int target, char *label, u_char *msg)
 {
 	struct sym_tcb *tp = &np->target[target];
-	dev_info(&tp->sdev->sdev_target->dev, "%s: ", label);
+	dev_info(&tp->starget->dev, "%s: ", label);
 
 	sym_show_msg(msg);
 	printf(".\n");
@@ -149,8 +149,10 @@
 static void sym_chip_reset (struct sym_hcb *np)
 {
 	OUTB(np, nc_istat, SRST);
+	INB(np, nc_mbox1);
 	udelay(10);
 	OUTB(np, nc_istat, 0);
+	INB(np, nc_mbox1);
 	udelay(2000);	/* For BUS MODE to settle */
 }
 
@@ -216,6 +218,7 @@
 	OUTB(np, nc_stest3, TE);
 	OUTB(np, nc_dcntl, (np->rv_dcntl & IRQM));
 	OUTB(np, nc_scntl1, CRST);
+	INB(np, nc_mbox1);
 	udelay(200);
 
 	if (!SYM_SETUP_SCSI_BUS_CHECK)
@@ -280,8 +283,10 @@
 		if (!i)
 			printf("%s: the chip cannot lock the frequency\n",
 				sym_name(np));
-	} else
-		udelay((50+10));
+	} else {
+		INB(np, nc_mbox1);
+		udelay(50+10);
+	}
 	OUTB(np, nc_stest3, HSC);		/* Halt the scsi clock	*/
 	OUTB(np, nc_scntl3, scntl3);
 	OUTB(np, nc_stest1, (DBLEN|DBLSEL));/* Select clock multiplier	*/
@@ -1445,7 +1450,7 @@
 static int sym_prepare_nego(struct sym_hcb *np, struct sym_ccb *cp, u_char *msgptr)
 {
 	struct sym_tcb *tp = &np->target[cp->target];
-	struct scsi_target *starget = tp->sdev->sdev_target;
+	struct scsi_target *starget = tp->starget;
 	struct sym_trans *goal = &tp->tgoal;
 	int msglen = 0;
 	int nego;
@@ -1690,7 +1695,7 @@
 		if (cam_status)
 			sym_set_cam_status(cmd, cam_status);
 #ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
-		if (sym_get_cam_status(cmd) == CAM_REQUEUE_REQ) {
+		if (sym_get_cam_status(cmd) == DID_SOFT_ERROR) {
 			struct sym_tcb *tp = &np->target[cp->target];
 			struct sym_lcb *lp = sym_lp(tp, cp->lun);
 			if (lp) {
@@ -1791,12 +1796,13 @@
 	/*
 	 *  Wakeup all pending jobs.
 	 */
-	sym_flush_busy_queue(np, CAM_SCSI_BUS_RESET);
+	sym_flush_busy_queue(np, DID_RESET);
 
 	/*
 	 *  Init chip.
 	 */
 	OUTB(np, nc_istat,  0x00);			/*  Remove Reset, abort */
+	INB(np, nc_mbox1);
 	udelay(2000); /* The 895 needs time for the bus mode to settle */
 
 	OUTB(np, nc_scntl0, np->rv_scntl0 | 0xc0);
@@ -1905,6 +1911,7 @@
 	if (np->features & (FE_ULTRA2|FE_ULTRA3)) {
 		OUTONW(np, nc_sien, SBMC);
 		if (reason == 0) {
+			INB(np, nc_mbox1);
 			mdelay(100);
 			INW(np, nc_sist);
 		}
@@ -2074,7 +2081,7 @@
 static void sym_setwide(struct sym_hcb *np, int target, u_char wide)
 {
 	struct sym_tcb *tp = &np->target[target];
-	struct scsi_target *starget = tp->sdev->sdev_target;
+	struct scsi_target *starget = tp->starget;
 
 	if (spi_width(starget) == wide)
 		return;
@@ -2102,7 +2109,7 @@
             u_char ofs, u_char per, u_char div, u_char fak)
 {
 	struct sym_tcb *tp = &np->target[target];
-	struct scsi_target *starget = tp->sdev->sdev_target;
+	struct scsi_target *starget = tp->starget;
 	u_char wide = (tp->head.wval & EWS) ? BUS_16_BIT : BUS_8_BIT;
 
 	sym_settrans(np, target, 0, ofs, per, wide, div, fak);
@@ -2129,7 +2136,7 @@
              u_char per, u_char wide, u_char div, u_char fak)
 {
 	struct sym_tcb *tp = &np->target[target];
-	struct scsi_target *starget = tp->sdev->sdev_target;
+	struct scsi_target *starget = tp->starget;
 
 	sym_settrans(np, target, opts, ofs, per, wide, div, fak);
 
@@ -2944,7 +2951,7 @@
  *  Dequeue from the START queue all CCBs that match 
  *  a given target/lun/task condition (-1 means all),
  *  and move them from the BUSY queue to the COMP queue 
- *  with CAM_REQUEUE_REQ status condition.
+ *  with DID_SOFT_ERROR status condition.
  *  This function is used during error handling/recovery.
  *  It is called with SCRIPTS not running.
  */
@@ -2974,7 +2981,7 @@
 		if ((target == -1 || cp->target == target) &&
 		    (lun    == -1 || cp->lun    == lun)    &&
 		    (task   == -1 || cp->tag    == task)) {
-			sym_set_cam_status(cp->cmd, CAM_REQUEUE_REQ);
+			sym_set_cam_status(cp->cmd, DID_SOFT_ERROR);
 			sym_remque(&cp->link_ccbq);
 			sym_insque_tail(&cp->link_ccbq, &np->comp_ccbq);
 		}
@@ -3093,13 +3100,13 @@
 		/*
 		 *  Message table indirect structure.
 		 */
-		cp->phys.smsg.addr	= cpu_to_scr(CCB_BA(cp, scsi_smsg2));
+		cp->phys.smsg.addr	= CCB_BA(cp, scsi_smsg2);
 		cp->phys.smsg.size	= cpu_to_scr(msglen);
 
 		/*
 		 *  sense command
 		 */
-		cp->phys.cmd.addr	= cpu_to_scr(CCB_BA(cp, sensecmd));
+		cp->phys.cmd.addr	= CCB_BA(cp, sensecmd);
 		cp->phys.cmd.size	= cpu_to_scr(6);
 
 		/*
@@ -3116,7 +3123,7 @@
 		 *  sense data
 		 */
 		memset(cp->sns_bbuf, 0, SYM_SNS_BBUF_LEN);
-		cp->phys.sense.addr	= cpu_to_scr(CCB_BA(cp, sns_bbuf));
+		cp->phys.sense.addr	= CCB_BA(cp, sns_bbuf);
 		cp->phys.sense.size	= cpu_to_scr(SYM_SNS_BBUF_LEN);
 
 		/*
@@ -3198,7 +3205,7 @@
 		sym_insque_tail(&cp->link_ccbq, &np->comp_ccbq);
 
 		/* Preserve the software timeout condition */
-		if (sym_get_cam_status(cmd) != CAM_CMD_TIMEOUT)
+		if (sym_get_cam_status(cmd) != DID_TIME_OUT)
 			sym_set_cam_status(cmd, cam_status);
 		++i;
 #if 0
@@ -3366,7 +3373,7 @@
 		 *  Make sure at least our IO to abort has been dequeued.
 		 */
 #ifndef SYM_OPT_HANDLE_DEVICE_QUEUEING
-		assert(i && sym_get_cam_status(cp->cmd) == CAM_REQUEUE_REQ);
+		assert(i && sym_get_cam_status(cp->cmd) == DID_SOFT_ERROR);
 #else
 		sym_remque(&cp->link_ccbq);
 		sym_insque_tail(&cp->link_ccbq, &np->comp_ccbq);
@@ -3375,9 +3382,9 @@
 		 *  Keep track in cam status of the reason of the abort.
 		 */
 		if (cp->to_abort == 2)
-			sym_set_cam_status(cp->cmd, CAM_CMD_TIMEOUT);
+			sym_set_cam_status(cp->cmd, DID_TIME_OUT);
 		else
-			sym_set_cam_status(cp->cmd, CAM_REQ_ABORTED);
+			sym_set_cam_status(cp->cmd, DID_ABORT);
 
 		/*
 		 *  Complete with error everything that we have dequeued.
@@ -3491,7 +3498,7 @@
 		 *  conditions not due to timeout.
 		 */
 		if (cp->to_abort == 2)
-			sym_set_cam_status(cp->cmd, CAM_CMD_TIMEOUT);
+			sym_set_cam_status(cp->cmd, DID_TIME_OUT);
 		cp->to_abort = 0; /* We donnot expect to fail here */
 		break;
 
@@ -3502,7 +3509,7 @@
 	case SIR_ABORT_SENT:
 		target = INB(np, nc_sdid) & 0xf;
 		tp = &np->target[target];
-		starget = tp->sdev->sdev_target;
+		starget = tp->starget;
 		
 		/*
 		**  If we didn't abort anything, leave here.
@@ -3551,7 +3558,7 @@
 		 */
 		i = (INL(np, nc_scratcha) - np->squeue_ba) / 4;
 		sym_dequeue_from_squeue(np, i, target, lun, -1);
-		sym_clear_tasks(np, CAM_REQ_ABORTED, target, lun, task);
+		sym_clear_tasks(np, DID_ABORT, target, lun, task);
 		sym_flush_comp_queue(np, 0);
 
  		/*
@@ -3566,7 +3573,7 @@
 	 *  Print to the log the message we intend to send.
 	 */
 	if (num == SIR_TARGET_SELECTED) {
-		dev_info(&tp->sdev->sdev_target->dev, "control msgout:");
+		dev_info(&tp->starget->dev, "control msgout:");
 		sym_printl_hex(np->abrt_msg, np->abrt_tbl.size);
 		np->abrt_tbl.size = cpu_to_scr(np->abrt_tbl.size);
 	}
@@ -3877,6 +3884,8 @@
 		resid += (tmp & 0xffffff);
 	}
 
+	resid -= cp->odd_byte_adjustment;
+
 	/*
 	 *  Hopefully, the result is not too wrong.
 	 */
@@ -4758,10 +4767,8 @@
 	}
 
 #endif
-	/*
-	 *  Remember all informations needed to free this CCB.
-	 */
 	cp->to_abort = 0;
+	cp->odd_byte_adjustment = 0;
 	cp->tag	   = tag;
 	cp->order  = tag_order;
 	cp->target = tn;
@@ -5104,7 +5111,7 @@
 	lp->itlq_tbl = sym_calloc_dma(SYM_CONF_MAX_TASK*4, "ITLQ_TBL");
 	if (!lp->itlq_tbl)
 		goto fail;
-	lp->cb_tags = kcalloc(SYM_CONF_MAX_TASK, 1, GFP_KERNEL);
+	lp->cb_tags = kcalloc(SYM_CONF_MAX_TASK, 1, GFP_ATOMIC);
 	if (!lp->cb_tags) {
 		sym_mfree_dma(lp->itlq_tbl, SYM_CONF_MAX_TASK*4, "ITLQ_TBL");
 		lp->itlq_tbl = NULL;
@@ -5243,7 +5250,7 @@
 	/*
 	 *  message
 	 */
-	cp->phys.smsg.addr	= cpu_to_scr(CCB_BA(cp, scsi_smsg));
+	cp->phys.smsg.addr	= CCB_BA(cp, scsi_smsg);
 	cp->phys.smsg.size	= cpu_to_scr(msglen);
 
 	/*
@@ -5343,7 +5350,7 @@
 }
 
 /*
- *  Complete execution of a SCSI command with extented 
+ *  Complete execution of a SCSI command with extended 
  *  error, SCSI status error, or having been auto-sensed.
  *
  *  The SCRIPTS processor is not running there, so we 
@@ -5441,7 +5448,7 @@
 		/*
 		 *  Let's requeue it to device.
 		 */
-		sym_set_cam_status(cmd, CAM_REQUEUE_REQ);
+		sym_set_cam_status(cmd, DID_SOFT_ERROR);
 		goto finish;
 	}
 weirdness:
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h
index a95cbe4..c55c7a5 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.h
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h
@@ -444,7 +444,7 @@
 	 */
 	u_char	usrflags;
 	u_short	usrtags;
-	struct scsi_device *sdev;
+	struct scsi_target *starget;
 };
 
 /*
@@ -754,10 +754,8 @@
 	int	segments;	/* Number of SG segments	*/
 
 	u8	order;		/* Tag type (if tagged command)	*/
+	unsigned char odd_byte_adjustment;	/* odd-sized req on wide bus */
 
-	/*
-	 *  Miscellaneous status'.
-	 */
 	u_char	nego_status;	/* Negotiation status		*/
 	u_char	xerr_status;	/* Extended error flags		*/
 	u32	extra_bytes;	/* Extraneous bytes transferred	*/
@@ -809,7 +807,7 @@
 #endif
 };
 
-#define CCB_BA(cp,lbl)	(cp->ccb_ba + offsetof(struct sym_ccb, lbl))
+#define CCB_BA(cp,lbl)	cpu_to_scr(cp->ccb_ba + offsetof(struct sym_ccb, lbl))
 
 #ifdef	SYM_OPT_HANDLE_DIR_UNKNOWN
 #define	sym_goalp(cp) ((cp->host_flags & HF_DATA_IN) ? cp->goalp : cp->wgoalp)
@@ -1138,33 +1136,33 @@
 	 *  No segments means no data.
 	 */
 	if (!cp->segments)
-		dir = CAM_DIR_NONE;
+		dir = DMA_NONE;
 
 	/*
 	 *  Set the data pointer.
 	 */
 	switch(dir) {
 #ifdef	SYM_OPT_HANDLE_DIR_UNKNOWN
-	case CAM_DIR_UNKNOWN:
+	case DMA_BIDIRECTIONAL:
 #endif
-	case CAM_DIR_OUT:
+	case DMA_TO_DEVICE:
 		goalp = SCRIPTA_BA(np, data_out2) + 8;
 		lastp = goalp - 8 - (cp->segments * (2*4));
 #ifdef	SYM_OPT_HANDLE_DIR_UNKNOWN
 		cp->wgoalp = cpu_to_scr(goalp);
-		if (dir != CAM_DIR_UNKNOWN)
+		if (dir != DMA_BIDIRECTIONAL)
 			break;
 		cp->phys.head.wlastp = cpu_to_scr(lastp);
 		/* fall through */
 #else
 		break;
 #endif
-	case CAM_DIR_IN:
+	case DMA_FROM_DEVICE:
 		cp->host_flags |= HF_DATA_IN;
 		goalp = SCRIPTA_BA(np, data_in2) + 8;
 		lastp = goalp - 8 - (cp->segments * (2*4));
 		break;
-	case CAM_DIR_NONE:
+	case DMA_NONE:
 	default:
 #ifdef	SYM_OPT_HANDLE_DIR_UNKNOWN
 		cp->host_flags |= HF_DATA_IN;
@@ -1185,7 +1183,7 @@
 	/*
 	 *  If direction is unknown, start at data_io.
 	 */
-	if (dir == CAM_DIR_UNKNOWN)
+	if (dir == DMA_BIDIRECTIONAL)
 		cp->phys.head.savep = cpu_to_scr(SCRIPTB_BA(np, data_io));
 #endif
 }
diff --git a/drivers/scsi/sym53c8xx_2/sym_nvram.c b/drivers/scsi/sym53c8xx_2/sym_nvram.c
index 1b721e3..cd9140e15 100644
--- a/drivers/scsi/sym53c8xx_2/sym_nvram.c
+++ b/drivers/scsi/sym53c8xx_2/sym_nvram.c
@@ -270,6 +270,7 @@
 
 	}
 	OUTB(np, nc_gpreg, *gpreg);
+	INB(np, nc_mbox1);
 	udelay(5);
 }
 
@@ -547,6 +548,7 @@
 static void T93C46_Clk(struct sym_device *np, u_char *gpreg)
 {
 	OUTB(np, nc_gpreg, *gpreg | 0x04);
+	INB(np, nc_mbox1);
 	udelay(2);
 	OUTB(np, nc_gpreg, *gpreg);
 }
@@ -574,6 +576,7 @@
 	*gpreg |= 0x10;
 		
 	OUTB(np, nc_gpreg, *gpreg);
+	INB(np, nc_mbox1);
 	udelay(2);
 
 	T93C46_Clk(np, gpreg);
@@ -586,6 +589,7 @@
 {
 	*gpreg &= 0xef;
 	OUTB(np, nc_gpreg, *gpreg);
+	INB(np, nc_mbox1);
 	udelay(2);
 
 	T93C46_Clk(np, gpreg);
@@ -733,7 +737,8 @@
 	return SYM_PARISC_PDC;
 }
 #else
-static int sym_read_parisc_pdc(struct sym_device *np, struct pdc_initiator *x)
+static inline int sym_read_parisc_pdc(struct sym_device *np,
+					struct pdc_initiator *x)
 {
 	return 0;
 }
diff --git a/drivers/scsi/t128.c b/drivers/scsi/t128.c
index 6dc2897..f4b780e 100644
--- a/drivers/scsi/t128.c
+++ b/drivers/scsi/t128.c
@@ -437,8 +437,6 @@
 	.queuecommand   = t128_queue_command,
 	.eh_abort_handler = t128_abort,
 	.eh_bus_reset_handler    = t128_bus_reset,
-	.eh_host_reset_handler   = t128_host_reset,
-	.eh_device_reset_handler = t128_device_reset,
 	.bios_param     = t128_biosparam,
 	.can_queue      = CAN_QUEUE,
         .this_id        = 7,
diff --git a/drivers/scsi/t128.h b/drivers/scsi/t128.h
index 161ba53..9ad1d68 100644
--- a/drivers/scsi/t128.h
+++ b/drivers/scsi/t128.h
@@ -96,9 +96,7 @@
 			  sector_t, int*);
 static int t128_detect(Scsi_Host_Template *);
 static int t128_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-static int t128_host_reset(Scsi_Cmnd *);
 static int t128_bus_reset(Scsi_Cmnd *);
-static int t128_device_reset(Scsi_Cmnd *);
 
 #ifndef CMD_PER_LUN
 #define CMD_PER_LUN 2
@@ -140,8 +138,6 @@
 #define do_NCR5380_intr do_t128_intr
 #define NCR5380_queue_command t128_queue_command
 #define NCR5380_abort t128_abort
-#define NCR5380_host_reset t128_host_reset
-#define NCR5380_device_reset t128_device_reset
 #define NCR5380_bus_reset t128_bus_reset
 #define NCR5380_proc_info t128_proc_info
 
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
index ee9df02..9589c67 100644
--- a/drivers/scsi/tmscsim.c
+++ b/drivers/scsi/tmscsim.c
@@ -2120,6 +2120,8 @@
 	struct dc390_acb*    pACB = (struct dc390_acb*) cmd->device->host->hostdata;
 	u8   bval;
 
+	spin_lock_irq(cmd->device->host->host_lock);
+
 	bval = DC390_read8(CtrlReg1) | DIS_INT_ON_SCSI_RST;
 	DC390_write8(CtrlReg1, bval);	/* disable IRQ on bus reset */
 
@@ -2127,7 +2129,7 @@
 	dc390_ResetSCSIBus(pACB);
 
 	dc390_ResetDevParam(pACB);
-	udelay(1000);
+	mdelay(1);
 	pACB->pScsiHost->last_reset = jiffies + 3*HZ/2 
 		+ HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
     
@@ -2142,6 +2144,8 @@
 	bval = DC390_read8(CtrlReg1) & ~DIS_INT_ON_SCSI_RST;
 	DC390_write8(CtrlReg1, bval);	/* re-enable interrupt */
 
+	spin_unlock_irq(cmd->device->host->host_lock);
+
 	return SUCCESS;
 }
 
diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c
index dca2154..98369ce 100644
--- a/drivers/scsi/u14-34f.c
+++ b/drivers/scsi/u14-34f.c
@@ -446,8 +446,6 @@
                 .release                 = u14_34f_release,
                 .queuecommand            = u14_34f_queuecommand,
                 .eh_abort_handler        = u14_34f_eh_abort,
-                .eh_device_reset_handler = NULL,
-                .eh_bus_reset_handler    = NULL,
                 .eh_host_reset_handler   = u14_34f_eh_host_reset,
                 .bios_param              = u14_34f_bios_param,
                 .slave_configure         = u14_34f_slave_configure,
@@ -1419,16 +1417,20 @@
    printk("%s: reset, enter, target %d.%d:%d, pid %ld.\n",
           BN(j), SCarg->device->channel, SCarg->device->id, SCarg->device->lun, SCarg->pid);
 
+   spin_lock_irq(sh[j]->host_lock);
+
    if (SCarg->host_scribble == NULL)
       printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid);
 
    if (HD(j)->in_reset) {
       printk("%s: reset, exit, already in reset.\n", BN(j));
+      spin_unlock_irq(sh[j]->host_lock);
       return FAILED;
       }
 
    if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
       printk("%s: reset, exit, timeout error.\n", BN(j));
+      spin_unlock_irq(sh[j]->host_lock);
       return FAILED;
       }
 
@@ -1479,6 +1481,7 @@
 
    if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
       printk("%s: reset, cannot reset, timeout error.\n", BN(j));
+      spin_unlock_irq(sh[j]->host_lock);
       return FAILED;
       }
 
@@ -1540,6 +1543,7 @@
    if (arg_done) printk("%s: reset, exit, pid %ld done.\n", BN(j), SCarg->pid);
    else          printk("%s: reset, exit.\n", BN(j));
 
+   spin_unlock_irq(sh[j]->host_lock);
    return SUCCESS;
 }
 
diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c
index 97f4d91..486551b 100644
--- a/drivers/scsi/ultrastor.c
+++ b/drivers/scsi/ultrastor.c
@@ -879,7 +879,7 @@
 	ogm_addr = (unsigned int)isa_bus_to_virt(inl(port0 + 23));
 	icm_status = inb(port0 + 27);
 	icm_addr = (unsigned int)isa_bus_to_virt(inl(port0 + 28));
-	spin_lock_irqsave(host->host_lock, flags);
+	spin_unlock_irqrestore(host->host_lock, flags);
       }
 
     /* First check to see if an interrupt is pending.  I suspect the SiS
@@ -954,9 +954,7 @@
     SCpnt->result = DID_ABORT << 16;
     
     /* Take the host lock to guard against scsi layer re-entry */
-    spin_lock_irqsave(host->host_lock, flags);
     done(SCpnt);
-    spin_unlock_irqrestore(host->host_lock, flags);
 
     /* Need to set a timeout here in case command never completes.  */
     return SUCCESS;
diff --git a/drivers/scsi/wd7000.c b/drivers/scsi/wd7000.c
index bf4a758..fb54a87 100644
--- a/drivers/scsi/wd7000.c
+++ b/drivers/scsi/wd7000.c
@@ -1586,9 +1586,16 @@
 {
 	Adapter *host = (Adapter *) SCpnt->device->host->hostdata;
 
-	if (wd7000_adapter_reset(host) < 0)
+	spin_unlock_irq(SCpnt->device->host->host_lock);
+
+	if (wd7000_adapter_reset(host) < 0) {
+		spin_unlock_irq(SCpnt->device->host->host_lock);
 		return FAILED;
+	}
+
 	wd7000_enable_intr(host);
+
+	spin_unlock_irq(SCpnt->device->host->host_lock);
 	return SUCCESS;
 }
 
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c
index db92a0c..feb8e73 100644
--- a/drivers/serial/68328serial.c
+++ b/drivers/serial/68328serial.c
@@ -992,18 +992,17 @@
 /*
  * This routine sends a break character out the serial port.
  */
-static void send_break(	struct m68k_serial * info, int duration)
+static void send_break(struct m68k_serial * info, unsigned int duration)
 {
 	m68328_uart *uart = &uart_addr[info->line];
         unsigned long flags;
         if (!info->port)
                 return;
-        set_current_state(TASK_INTERRUPTIBLE);
         save_flags(flags);
         cli();
 #ifdef USE_INTS	
 	uart->utx.w |= UTX_SEND_BREAK;
-        schedule_timeout(duration);
+	msleep_interruptible(duration);
 	uart->utx.w &= ~UTX_SEND_BREAK;
 #endif		
         restore_flags(flags);
@@ -1033,14 +1032,14 @@
 				return retval;
 			tty_wait_until_sent(tty, 0);
 			if (!arg)
-				send_break(info, HZ/4);	/* 1/4 second */
+				send_break(info, 250);	/* 1/4 second */
 			return 0;
 		case TCSBRKP:	/* support for POSIX tcsendbreak() */
 			retval = tty_check_change(tty);
 			if (retval)
 				return retval;
 			tty_wait_until_sent(tty, 0);
-			send_break(info, arg ? arg*(HZ/10) : HZ/4);
+			send_break(info, arg ? arg*(100) : 250);
 			return 0;
 		case TIOCGSOFTCAR:
 			error = put_user(C_CLOCAL(tty) ? 1 : 0,
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index f148022..b116122 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -1394,14 +1394,13 @@
 /*
  * This routine sends a break character out the serial port.
  */
-static void send_break(ser_info_t *info, int duration)
+static void send_break(ser_info_t *info, unsigned int duration)
 {
-	set_current_state(TASK_INTERRUPTIBLE);
 #ifdef SERIAL_DEBUG_SEND_BREAK
 	printk("rs_send_break(%d) jiff=%lu...", duration, jiffies);
 #endif
 	begin_break(info);
-	schedule_timeout(duration);
+	msleep_interruptible(duration);
 	end_break(info);
 #ifdef SERIAL_DEBUG_SEND_BREAK
 	printk("done jiffies=%lu\n", jiffies);
@@ -1436,7 +1435,7 @@
 			if (signal_pending(current))
 				return -EINTR;
 			if (!arg) {
-				send_break(info, HZ/4);	/* 1/4 second */
+				send_break(info, 250);	/* 1/4 second */
 				if (signal_pending(current))
 					return -EINTR;
 			}
@@ -1448,7 +1447,7 @@
 			tty_wait_until_sent(tty, 0);
 			if (signal_pending(current))
 				return -EINTR;
-			send_break(info, arg ? arg*(HZ/10) : HZ/4);
+			send_break(info, arg ? arg*100 : 250);
 			if (signal_pending(current))
 				return -EINTR;
 			return 0;
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 30e8beb..d8b9d2b 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -132,9 +132,9 @@
 	struct uart_port	port;
 	struct timer_list	timer;		/* "no irq" timer */
 	struct list_head	list;		/* ports on this IRQ */
-	unsigned int		capabilities;	/* port capabilities */
+	unsigned short		capabilities;	/* port capabilities */
+	unsigned short		bugs;		/* port bugs */
 	unsigned int		tx_loadsz;	/* transmit fifo load size */
-	unsigned short		rev;
 	unsigned char		acr;
 	unsigned char		ier;
 	unsigned char		lcr;
@@ -560,7 +560,14 @@
 	if (id1 == 0x16 && id2 == 0xC9 &&
 	    (id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) {
 		up->port.type = PORT_16C950;
-		up->rev = rev | (id3 << 8);
+
+		/*
+		 * Enable work around for the Oxford Semiconductor 952 rev B
+		 * chip which causes it to seriously miscalculate baud rates
+		 * when DLL is 0.
+		 */
+		if (id3 == 0x52 && rev == 0x01)
+			up->bugs |= UART_BUG_QUOT;
 		return;
 	}
 	
@@ -577,8 +584,6 @@
 
 	id2 = id1 >> 8;
 	if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) {
-		if (id2 == 0x10)
-			up->rev = id1 & 255;
 		up->port.type = PORT_16850;
 		return;
 	}
@@ -809,6 +814,7 @@
 //	save_flags(flags); cli();
 
 	up->capabilities = 0;
+	up->bugs = 0;
 
 	if (!(up->port.flags & UPF_BUGGY_UART)) {
 		/*
@@ -1021,6 +1027,8 @@
 	}
 }
 
+static void transmit_chars(struct uart_8250_port *up);
+
 static void serial8250_start_tx(struct uart_port *port, unsigned int tty_start)
 {
 	struct uart_8250_port *up = (struct uart_8250_port *)port;
@@ -1028,6 +1036,14 @@
 	if (!(up->ier & UART_IER_THRI)) {
 		up->ier |= UART_IER_THRI;
 		serial_out(up, UART_IER, up->ier);
+
+		if (up->bugs & UART_BUG_TXEN) {
+			unsigned char lsr, iir;
+			lsr = serial_in(up, UART_LSR);
+			iir = serial_in(up, UART_IIR);
+			if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT)
+				transmit_chars(up);
+		}
 	}
 	/*
 	 * We only do this from uart_start
@@ -1433,6 +1449,7 @@
 {
 	struct uart_8250_port *up = (struct uart_8250_port *)port;
 	unsigned long flags;
+	unsigned char lsr, iir;
 	int retval;
 
 	up->capabilities = uart_config[up->port.type].flags;
@@ -1536,6 +1553,26 @@
 			up->port.mctrl |= TIOCM_OUT2;
 
 	serial8250_set_mctrl(&up->port, up->port.mctrl);
+
+	/*
+	 * Do a quick test to see if we receive an
+	 * interrupt when we enable the TX irq.
+	 */
+	serial_outp(up, UART_IER, UART_IER_THRI);
+	lsr = serial_in(up, UART_LSR);
+	iir = serial_in(up, UART_IIR);
+	serial_outp(up, UART_IER, 0);
+
+	if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
+		if (!(up->bugs & UART_BUG_TXEN)) {
+			up->bugs |= UART_BUG_TXEN;
+			pr_debug("ttyS%d - enabling bad tx status workarounds\n",
+				 port->line);
+		}
+	} else {
+		up->bugs &= ~UART_BUG_TXEN;
+	}
+
 	spin_unlock_irqrestore(&up->port.lock, flags);
 
 	/*
@@ -1645,22 +1682,22 @@
 
 	switch (termios->c_cflag & CSIZE) {
 	case CS5:
-		cval = 0x00;
+		cval = UART_LCR_WLEN5;
 		break;
 	case CS6:
-		cval = 0x01;
+		cval = UART_LCR_WLEN6;
 		break;
 	case CS7:
-		cval = 0x02;
+		cval = UART_LCR_WLEN7;
 		break;
 	default:
 	case CS8:
-		cval = 0x03;
+		cval = UART_LCR_WLEN8;
 		break;
 	}
 
 	if (termios->c_cflag & CSTOPB)
-		cval |= 0x04;
+		cval |= UART_LCR_STOP;
 	if (termios->c_cflag & PARENB)
 		cval |= UART_LCR_PARITY;
 	if (!(termios->c_cflag & PARODD))
@@ -1677,12 +1714,9 @@
 	quot = serial8250_get_divisor(port, baud);
 
 	/*
-	 * Work around a bug in the Oxford Semiconductor 952 rev B
-	 * chip which causes it to seriously miscalculate baud rates
-	 * when DLL is 0.
+	 * Oxford Semi 952 rev B workaround
 	 */
-	if ((quot & 0xff) == 0 && up->port.type == PORT_16C950 &&
-	    up->rev == 0x5201)
+	if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0)
 		quot ++;
 
 	if (up->capabilities & UART_CAP_FIFO && up->port.fifosize > 1) {
diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h
index 4f3d62f..9225c82 100644
--- a/drivers/serial/8250.h
+++ b/drivers/serial/8250.h
@@ -51,6 +51,9 @@
 #define UART_CAP_AFE	(1 << 11)	/* MCR-based hw flow control */
 #define UART_CAP_UUE	(1 << 12)	/* UART needs IER bit 6 set (Xscale) */
 
+#define UART_BUG_QUOT	(1 << 0)	/* UART has buggy quot LSB */
+#define UART_BUG_TXEN	(1 << 1)	/* UART has buggy TX IIR status */
+
 #if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486))
 #define _INLINE_ inline
 #else
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 6e44b46..25fcef2 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -753,7 +753,7 @@
 
 config SERIAL_ICOM
 	tristate "IBM Multiport Serial Adapter"
-	depends on PPC_ISERIES || PPC_PSERIES
+	depends on PCI && (PPC_ISERIES || PPC_PSERIES)
 	select SERIAL_CORE
 	help
 	  This driver is for a family of multiport serial adapters
@@ -843,4 +843,13 @@
           To compile this driver as a module, choose M here: the
           module will be called jsm.
 
+config SERIAL_SGI_IOC4
+	tristate "SGI IOC4 controller serial support"
+	depends on (IA64_GENERIC || IA64_SGI_SN2) && SGI_IOC4
+	select SERIAL_CORE
+	help
+		If you have an SGI Altix with an IOC4 based Base IO card
+		and wish to use the serial ports on this card, say Y.
+		Otherwise, say N.
+
 endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 81b77d7..8f1cdde 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -51,4 +51,4 @@
 obj-$(CONFIG_SERIAL_JSM) += jsm/
 obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
 obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o
-obj-$(CONFIG_BLK_DEV_SGIIOC4) += ioc4_serial.o
+obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o
diff --git a/drivers/serial/au1x00_uart.c b/drivers/serial/au1x00_uart.c
index b6d3d50..5400dc2 100644
--- a/drivers/serial/au1x00_uart.c
+++ b/drivers/serial/au1x00_uart.c
@@ -773,22 +773,22 @@
 
 	switch (termios->c_cflag & CSIZE) {
 	case CS5:
-		cval = 0x00;
+		cval = UART_LCR_WLEN5;
 		break;
 	case CS6:
-		cval = 0x01;
+		cval = UART_LCR_WLEN6;
 		break;
 	case CS7:
-		cval = 0x02;
+		cval = UART_LCR_WLEN7;
 		break;
 	default:
 	case CS8:
-		cval = 0x03;
+		cval = UART_LCR_WLEN8;
 		break;
 	}
 
 	if (termios->c_cflag & CSTOPB)
-		cval |= 0x04;
+		cval |= UART_LCR_STOP;
 	if (termios->c_cflag & PARENB)
 		cval |= UART_LCR_PARITY;
 	if (!(termios->c_cflag & PARODD))
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
index b422c3a..c4c8f4b 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
@@ -134,12 +134,21 @@
 
 void scc2_lineif(struct uart_cpm_port *pinfo)
 {
+	/*
+	 * STx GP3 uses the SCC2 secondary option pin assignment
+	 * which this driver doesn't account for in the static
+	 * pin assignments. This kind of board specific info
+	 * really has to get out of the driver so boards can
+	 * be supported in a sane fashion.
+	 */
+#ifndef CONFIG_STX_GP3
 	volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
 	io->iop_pparb |= 0x008b0000;
 	io->iop_pdirb |= 0x00880000;
 	io->iop_psorb |= 0x00880000;
 	io->iop_pdirb &= ~0x00030000;
 	io->iop_psorb &= ~0x00030000;
+#endif
 	cpm2_immr->im_cpmux.cmx_scr &= 0xff00ffff;
 	cpm2_immr->im_cpmux.cmx_scr |= 0x00090000;
 	pinfo->brg = 2;
diff --git a/drivers/serial/icom.h b/drivers/serial/icom.h
index 23dc0f7..798f1ef 100644
--- a/drivers/serial/icom.h
+++ b/drivers/serial/icom.h
@@ -286,5 +286,3 @@
 	u32	__iomem *global_int_mask;
 	unsigned long	processor_id;
 };
-
-#define MSECS_TO_JIFFIES(ms) (((ms)*HZ+999)/1000)
diff --git a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
index ba4e13a..793c3a7 100644
--- a/drivers/serial/ioc4_serial.c
+++ b/drivers/serial/ioc4_serial.c
@@ -20,7 +20,7 @@
 #include <linux/serial_reg.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/ioc4_common.h>
+#include <linux/ioc4.h>
 #include <linux/serial_core.h>
 
 /*
@@ -130,12 +130,19 @@
 				 IOC4_SIO_IR_S3_TX_EXPLICIT)
 
 /* Bitmasks for IOC4_OTHER_IR, IOC4_OTHER_IEC, and IOC4_OTHER_IES  */
-#define IOC4_OTHER_IR_ATA_INT           0x00000001  /* ATAPI intr pass-thru */
-#define IOC4_OTHER_IR_ATA_MEMERR        0x00000002  /* ATAPI DMA PCI error */
-#define IOC4_OTHER_IR_S0_MEMERR         0x00000004  /* Port 0 PCI error */
-#define IOC4_OTHER_IR_S1_MEMERR         0x00000008  /* Port 1 PCI error */
-#define IOC4_OTHER_IR_S2_MEMERR         0x00000010  /* Port 2 PCI error */
-#define IOC4_OTHER_IR_S3_MEMERR         0x00000020  /* Port 3 PCI error */
+#define IOC4_OTHER_IR_ATA_INT		0x00000001  /* ATAPI intr pass-thru */
+#define IOC4_OTHER_IR_ATA_MEMERR	0x00000002  /* ATAPI DMA PCI error */
+#define IOC4_OTHER_IR_S0_MEMERR		0x00000004  /* Port 0 PCI error */
+#define IOC4_OTHER_IR_S1_MEMERR		0x00000008  /* Port 1 PCI error */
+#define IOC4_OTHER_IR_S2_MEMERR		0x00000010  /* Port 2 PCI error */
+#define IOC4_OTHER_IR_S3_MEMERR		0x00000020  /* Port 3 PCI error */
+#define IOC4_OTHER_IR_KBD_INT		0x00000040  /* Keyboard/mouse */
+#define IOC4_OTHER_IR_RESERVED		0x007fff80  /* Reserved */
+#define IOC4_OTHER_IR_RT_INT		0x00800000  /* INT_OUT section output */
+#define IOC4_OTHER_IR_GEN_INT		0xff000000  /* Generic pins */
+
+#define IOC4_OTHER_IR_SER_MEMERR (IOC4_OTHER_IR_S0_MEMERR | IOC4_OTHER_IR_S1_MEMERR | \
+				  IOC4_OTHER_IR_S2_MEMERR | IOC4_OTHER_IR_S3_MEMERR)
 
 /* Bitmasks for IOC4_SIO_CR */
 #define IOC4_SIO_CR_CMD_PULSE_SHIFT              0  /* byte bus strobe shift */
@@ -274,70 +281,24 @@
 #define i4u_dlm u2.dlm
 #define i4u_fcr u3.fcr
 
-/* PCI memory space register map addressed using pci_bar0 */
-struct ioc4_memregs {
-	struct ioc4_mem {
-		/* Miscellaneous IOC4  registers */
-		uint32_t pci_err_addr_l;
-		uint32_t pci_err_addr_h;
-		uint32_t sio_ir;
-		uint32_t other_ir;
+/* Serial port registers used for DMA serial I/O */
+struct ioc4_serial {
+	uint32_t sbbr01_l;
+	uint32_t sbbr01_h;
+	uint32_t sbbr23_l;
+	uint32_t sbbr23_h;
 
-		/* These registers are read-only for general kernel code.  */
-		uint32_t sio_ies_ro;
-		uint32_t other_ies_ro;
-		uint32_t sio_iec_ro;
-		uint32_t other_iec_ro;
-		uint32_t sio_cr;
-		uint32_t misc_fill1;
-		uint32_t int_out;
-		uint32_t misc_fill2;
-		uint32_t gpcr_s;
-		uint32_t gpcr_c;
-		uint32_t gpdr;
-		uint32_t misc_fill3;
-		uint32_t gppr_0;
-		uint32_t gppr_1;
-		uint32_t gppr_2;
-		uint32_t gppr_3;
-		uint32_t gppr_4;
-		uint32_t gppr_5;
-		uint32_t gppr_6;
-		uint32_t gppr_7;
-	} ioc4_mem;
-
-	char misc_fill4[0x100 - 0x5C - 4];
-
-	/* ATA/ATAP registers */
-	uint32_t ata_notused[9];
-	char ata_fill1[0x140 - 0x120 - 4];
-	uint32_t ata_notused1[8];
-	char ata_fill2[0x200 - 0x15C - 4];
-
-	/* Keyboard and mouse registers */
-	uint32_t km_notused[5];;
-	char km_fill1[0x300 - 0x210 - 4];
-
-	/* Serial port registers used for DMA serial I/O */
-	struct ioc4_serial {
-		uint32_t sbbr01_l;
-		uint32_t sbbr01_h;
-		uint32_t sbbr23_l;
-		uint32_t sbbr23_h;
-
-		struct ioc4_serialregs port_0;
-		struct ioc4_serialregs port_1;
-		struct ioc4_serialregs port_2;
-		struct ioc4_serialregs port_3;
-		struct ioc4_uartregs uart_0;
-		struct ioc4_uartregs uart_1;
-		struct ioc4_uartregs uart_2;
-		struct ioc4_uartregs uart_3;
-	} ioc4_serial;
-};
+	struct ioc4_serialregs port_0;
+	struct ioc4_serialregs port_1;
+	struct ioc4_serialregs port_2;
+	struct ioc4_serialregs port_3;
+	struct ioc4_uartregs uart_0;
+	struct ioc4_uartregs uart_1;
+	struct ioc4_uartregs uart_2;
+	struct ioc4_uartregs uart_3;
+} ioc4_serial;
 
 /* UART clock speed */
-#define IOC4_SER_XIN_CLK        IOC4_SER_XIN_CLK_66
 #define IOC4_SER_XIN_CLK_66     66666667
 #define IOC4_SER_XIN_CLK_33     33333333
 
@@ -412,8 +373,8 @@
 					| UART_LCR_WLEN7 | UART_LCR_WLEN8)
 #define LCR_MASK_STOP_BITS	(UART_LCR_STOP)
 
-#define PENDING(_p)	(readl(&(_p)->ip_mem->sio_ir) & _p->ip_ienb)
-#define READ_SIO_IR(_p) readl(&(_p)->ip_mem->sio_ir)
+#define PENDING(_p)	(readl(&(_p)->ip_mem->sio_ir.raw) & _p->ip_ienb)
+#define READ_SIO_IR(_p) readl(&(_p)->ip_mem->sio_ir.raw)
 
 /* Default to 4k buffers */
 #ifdef IOC4_1K_BUFFERS
@@ -447,7 +408,7 @@
  */
 #define MAX_IOC4_INTR_ENTS	(8 * sizeof(uint32_t))
 struct ioc4_soft {
-	struct ioc4_mem __iomem *is_ioc4_mem_addr;
+	struct ioc4_misc_regs __iomem *is_ioc4_misc_addr;
 	struct ioc4_serial __iomem *is_ioc4_serial_addr;
 
 	/* Each interrupt type has an entry in the array */
@@ -486,7 +447,7 @@
 	struct ioc4_soft *ip_ioc4_soft;
 
 	/* pci mem addresses */
-	struct ioc4_mem __iomem *ip_mem;
+	struct ioc4_misc_regs __iomem *ip_mem;
 	struct ioc4_serial __iomem *ip_serial;
 	struct ioc4_serialregs __iomem *ip_serial_regs;
 	struct ioc4_uartregs __iomem *ip_uart_regs;
@@ -553,7 +514,7 @@
 	uint32_t intr_dma_error;
 	uint32_t intr_clear;
 	uint32_t intr_all;
-	char rs422_select_pin;
+	int rs422_select_pin;
 };
 
 static struct hooks hooks_array[IOC4_NUM_SERIAL_PORTS] = {
@@ -669,7 +630,7 @@
 static inline void
 write_ireg(struct ioc4_soft *ioc4_soft, uint32_t val, int which, int type)
 {
-	struct ioc4_mem __iomem *mem = ioc4_soft->is_ioc4_mem_addr;
+	struct ioc4_misc_regs __iomem *mem = ioc4_soft->is_ioc4_misc_addr;
 	unsigned long flags;
 
 	spin_lock_irqsave(&ioc4_soft->is_ir_lock, flags);
@@ -678,11 +639,11 @@
 	case IOC4_SIO_INTR_TYPE:
 		switch (which) {
 		case IOC4_W_IES:
-			writel(val, &mem->sio_ies_ro);
+			writel(val, &mem->sio_ies.raw);
 			break;
 
 		case IOC4_W_IEC:
-			writel(val, &mem->sio_iec_ro);
+			writel(val, &mem->sio_iec.raw);
 			break;
 		}
 		break;
@@ -690,11 +651,11 @@
 	case IOC4_OTHER_INTR_TYPE:
 		switch (which) {
 		case IOC4_W_IES:
-			writel(val, &mem->other_ies_ro);
+			writel(val, &mem->other_ies.raw);
 			break;
 
 		case IOC4_W_IEC:
-			writel(val, &mem->other_iec_ro);
+			writel(val, &mem->other_iec.raw);
 			break;
 		}
 		break;
@@ -747,7 +708,8 @@
  */
 static struct ioc4_port *get_ioc4_port(struct uart_port *the_port)
 {
-	struct ioc4_control *control = dev_get_drvdata(the_port->dev);
+	struct ioc4_driver_data *idd = dev_get_drvdata(the_port->dev);
+	struct ioc4_control *control = idd->idd_serial_data;
 	int ii;
 
 	if (control) {
@@ -782,7 +744,7 @@
 static inline uint32_t
 pending_intrs(struct ioc4_soft *soft, int type)
 {
-	struct ioc4_mem __iomem *mem = soft->is_ioc4_mem_addr;
+	struct ioc4_misc_regs __iomem *mem = soft->is_ioc4_misc_addr;
 	unsigned long flag;
 	uint32_t intrs = 0;
 
@@ -793,11 +755,11 @@
 
 	switch (type) {
 	case IOC4_SIO_INTR_TYPE:
-		intrs = readl(&mem->sio_ir) & readl(&mem->sio_ies_ro);
+		intrs = readl(&mem->sio_ir.raw) & readl(&mem->sio_ies.raw);
 		break;
 
 	case IOC4_OTHER_INTR_TYPE:
-		intrs = readl(&mem->other_ir) & readl(&mem->other_ies_ro);
+		intrs = readl(&mem->other_ir.raw) & readl(&mem->other_ies.raw);
 
 		/* Don't process any ATA interrupte */
 		intrs &= ~(IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR);
@@ -826,7 +788,7 @@
 
 	/* Wait until any pending bus activity for this port has ceased */
 	do
-		sio_cr = readl(&port->ip_mem->sio_cr);
+		sio_cr = readl(&port->ip_mem->sio_cr.raw);
 	while (!(sio_cr & IOC4_SIO_CR_SIO_DIAG_IDLE));
 
 	/* Finish reset sequence */
@@ -899,7 +861,7 @@
 	write_ireg(port->ip_ioc4_soft, hooks->intr_clear,
 		       IOC4_W_IEC, IOC4_SIO_INTR_TYPE);
 	port->ip_ienb &= ~hooks->intr_clear;
-	writel(hooks->intr_clear, &port->ip_mem->sio_ir);
+	writel(hooks->intr_clear, &port->ip_mem->sio_ir.raw);
 	return 0;
 }
 
@@ -918,23 +880,23 @@
 	spin_lock_irqsave(&port->ip_lock, flags);
 
 	/* ACK the interrupt */
-	writel(hooks->intr_dma_error, &port->ip_mem->other_ir);
+	writel(hooks->intr_dma_error, &port->ip_mem->other_ir.raw);
 
-	if (readl(&port->ip_mem->pci_err_addr_l) & IOC4_PCI_ERR_ADDR_VLD) {
+	if (readl(&port->ip_mem->pci_err_addr_l.raw) & IOC4_PCI_ERR_ADDR_VLD) {
 		printk(KERN_ERR
 			"PCI error address is 0x%lx, "
 				"master is serial port %c %s\n",
 		     (((uint64_t)readl(&port->ip_mem->pci_err_addr_h)
 							 << 32)
-				| readl(&port->ip_mem->pci_err_addr_l))
+				| readl(&port->ip_mem->pci_err_addr_l.raw))
 					& IOC4_PCI_ERR_ADDR_ADDR_MSK, '1' +
-		     ((char)(readl(&port->ip_mem-> pci_err_addr_l) &
+		     ((char)(readl(&port->ip_mem->pci_err_addr_l.raw) &
 			     IOC4_PCI_ERR_ADDR_MST_NUM_MSK) >> 1),
-		     (readl(&port->ip_mem->pci_err_addr_l)
+		     (readl(&port->ip_mem->pci_err_addr_l.raw)
 				& IOC4_PCI_ERR_ADDR_MST_TYP_MSK)
 				? "RX" : "TX");
 
-		if (readl(&port->ip_mem->pci_err_addr_l)
+		if (readl(&port->ip_mem->pci_err_addr_l.raw)
 						& IOC4_PCI_ERR_ADDR_MUL_ERR) {
 			printk(KERN_ERR
 				"Multiple errors occurred\n");
@@ -1018,26 +980,26 @@
 				"other_ies = 0x%x\n",
 			       (intr_type == IOC4_SIO_INTR_TYPE) ? "sio" :
 			       "other", this_ir,
-			       readl(&soft->is_ioc4_mem_addr->sio_ir),
-			       readl(&soft->is_ioc4_mem_addr->sio_ies_ro),
-			       readl(&soft->is_ioc4_mem_addr->other_ir),
-			       readl(&soft->is_ioc4_mem_addr->other_ies_ro));
+			       readl(&soft->is_ioc4_misc_addr->sio_ir.raw),
+			       readl(&soft->is_ioc4_misc_addr->sio_ies.raw),
+			       readl(&soft->is_ioc4_misc_addr->other_ir.raw),
+			       readl(&soft->is_ioc4_misc_addr->other_ies.raw));
 		}
 	}
 #ifdef DEBUG_INTERRUPTS
 	{
-		struct ioc4_mem __iomem *mem = soft->is_ioc4_mem_addr;
+		struct ioc4_misc_regs __iomem *mem = soft->is_ioc4_misc_addr;
 		spinlock_t *lp = &soft->is_ir_lock;
 		unsigned long flag;
 
 		spin_lock_irqsave(&soft->is_ir_lock, flag);
-		printk ("%s : %d : mem 0x%p sio_ir 0x%x sio_ies_ro 0x%x "
-				"other_ir 0x%x other_ies_ro 0x%x mask 0x%x\n",
+		printk ("%s : %d : mem 0x%p sio_ir 0x%x sio_ies 0x%x "
+				"other_ir 0x%x other_ies 0x%x mask 0x%x\n",
 		     __FUNCTION__, __LINE__,
-		     (void *)mem, readl(&mem->sio_ir),
-		     readl(&mem->sio_ies_ro),
-		     readl(&mem->other_ir),
-		     readl(&mem->other_ies_ro),
+		     (void *)mem, readl(&mem->sio_ir.raw),
+		     readl(&mem->sio_ies.raw),
+		     readl(&mem->other_ir.raw),
+		     readl(&mem->other_ies.raw),
 		     IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR);
 		spin_unlock_irqrestore(&soft->is_ir_lock, flag);
 	}
@@ -1049,21 +1011,20 @@
  * ioc4_attach_local - Device initialization.
  *			Called at *_attach() time for each
  *			IOC4 with serial ports in the system.
- * @control: ioc4_control ptr
- * @pdev: PCI handle for this device
- * @soft: soft struct for this device
- * @ioc4: ioc4 mem space
+ * @idd: Master module data for this IOC4
  */
-static int inline ioc4_attach_local(struct pci_dev *pdev,
-			struct ioc4_control *control,
-			struct ioc4_soft *soft, void __iomem *ioc4_mem,
-			void __iomem *ioc4_serial)
+static int inline ioc4_attach_local(struct ioc4_driver_data *idd)
 {
 	struct ioc4_port *port;
 	struct ioc4_port *ports[IOC4_NUM_SERIAL_PORTS];
 	int port_number;
 	uint16_t ioc4_revid_min = 62;
 	uint16_t ioc4_revid;
+	struct pci_dev *pdev = idd->idd_pdev;
+	struct ioc4_control* control = idd->idd_serial_data;
+	struct ioc4_soft *soft = control->ic_soft;
+	void __iomem *ioc4_misc = idd->idd_misc_regs;
+	void __iomem *ioc4_serial = soft->is_ioc4_serial_addr;
 
 	/* IOC4 firmware must be at least rev 62 */
 	pci_read_config_word(pdev, PCI_COMMAND_SPECIAL, &ioc4_revid);
@@ -1076,7 +1037,7 @@
 				ioc4_revid, ioc4_revid_min);
 		return -EPERM;
 	}
-	BUG_ON(ioc4_mem == NULL);
+	BUG_ON(ioc4_misc == NULL);
 	BUG_ON(ioc4_serial == NULL);
 
 	/* Create port structures for each port */
@@ -1100,10 +1061,18 @@
 		port->ip_ioc4_soft = soft;
 		port->ip_pdev = pdev;
 		port->ip_ienb = 0;
-		port->ip_pci_bus_speed = IOC4_SER_XIN_CLK;
+		/* Use baud rate calculations based on detected PCI
+		 * bus speed.  Simply test whether the PCI clock is
+		 * running closer to 66MHz or 33MHz.
+		 */
+		if (idd->count_period/IOC4_EXTINT_COUNT_DIVISOR < 20) {
+			port->ip_pci_bus_speed = IOC4_SER_XIN_CLK_66;
+		} else {
+			port->ip_pci_bus_speed = IOC4_SER_XIN_CLK_33;
+		}
 		port->ip_baud = 9600;
 		port->ip_control = control;
-		port->ip_mem = ioc4_mem;
+		port->ip_mem = ioc4_misc;
 		port->ip_serial = ioc4_serial;
 
 		/* point to the right hook */
@@ -1604,14 +1573,12 @@
 	switch (proto) {
 	case PROTO_RS232:
 		/* Clear the appropriate GIO pin */
-		writel(0, (&port->ip_mem->gppr_0 +
-				  hooks->rs422_select_pin));
+		writel(0, (&port->ip_mem->gppr[hooks->rs422_select_pin].raw));
 		break;
 
 	case PROTO_RS422:
 		/* Set the appropriate GIO pin */
-		writel(1, (&port->ip_mem->gppr_0 +
-				  hooks->rs422_select_pin));
+		writel(1, (&port->ip_mem->gppr[hooks->rs422_select_pin].raw));
 		break;
 
 	default:
@@ -1885,7 +1852,7 @@
 		if (sio_ir & hooks->intr_delta_dcd) {
 			/* ACK the interrupt */
 			writel(hooks->intr_delta_dcd,
-				&port->ip_mem->sio_ir);
+				&port->ip_mem->sio_ir.raw);
 
 			shadow = readl(&port->ip_serial_regs->shadow);
 
@@ -1907,7 +1874,7 @@
 		if (sio_ir & hooks->intr_delta_cts) {
 			/* ACK the interrupt */
 			writel(hooks->intr_delta_cts,
-					&port->ip_mem->sio_ir);
+					&port->ip_mem->sio_ir.raw);
 
 			shadow = readl(&port->ip_serial_regs->shadow);
 
@@ -1928,7 +1895,7 @@
 		if (sio_ir & hooks->intr_rx_timer) {
 			/* ACK the interrupt */
 			writel(hooks->intr_rx_timer,
-				&port->ip_mem->sio_ir);
+				&port->ip_mem->sio_ir.raw);
 
 			if ((port->ip_notify & N_DATA_READY)
 					&& (port->ip_port)) {
@@ -1974,7 +1941,7 @@
 
 			/* ACK the interrupt */
 			writel(hooks->intr_tx_explicit,
-					&port->ip_mem->sio_ir);
+					&port->ip_mem->sio_ir.raw);
 
 			if (port->ip_notify & N_OUTPUT_LOWAT)
 				ioc4_cb_output_lowat(port);
@@ -2634,7 +2601,8 @@
 {
 	struct ioc4_port *port;
 	struct uart_port *the_port;
-	struct ioc4_control *control = pci_get_drvdata(pdev);
+	struct ioc4_driver_data *idd = pci_get_drvdata(pdev);
+	struct ioc4_control *control = idd->idd_serial_data;
 	int ii;
 
 	DPRINT_CONFIG(("%s: attach pdev 0x%p - control 0x%p\n",
@@ -2680,55 +2648,29 @@
 
 /**
  * ioc4_serial_attach_one - register attach function
- *		called per card found from ioc4_serial_detect as part
- *		of module_init().
- * @pdev: handle for this card
- * @pci_id: pci id for this card
+ *		called per card found from IOC4 master module.
+ * @idd: Master module data for this IOC4
  */
 int
-ioc4_serial_attach_one(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+ioc4_serial_attach_one(struct ioc4_driver_data *idd)
 {
-	struct ioc4_mem __iomem *mem;
-	unsigned long tmp_addr, tmp_addr1;
+	unsigned long tmp_addr1;
 	struct ioc4_serial __iomem *serial;
 	struct ioc4_soft *soft;
 	struct ioc4_control *control;
-	int tmp, ret = 0;
+	int ret = 0;
 
 
-	DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, pdev, pci_id));
-
-	/* Map in the ioc4 memory */
-	tmp_addr = pci_resource_start(pdev, 0);
-	if (!tmp_addr) {
-		printk(KERN_WARNING
-			 "ioc4 (%p) : unable to get PIO mapping for "
-				"MEM space\n", (void *)pdev);
-		return -ENODEV;
-	}
-	if (!request_region(tmp_addr, sizeof(struct ioc4_mem), "sioc4_mem")) {
-		printk(KERN_ALERT
-			"ioc4 (%p): unable to get request region for "
-			"MEM space\n", (void *)pdev);
-		return -ENODEV;
-	}
-	mem = ioremap(tmp_addr, sizeof(struct ioc4_mem));
-	if (!mem) {
-		printk(KERN_WARNING
-			 "ioc4 (%p) : unable to remap ioc4 memory\n",
-				(void *)pdev);
-		ret = -ENODEV;
-		goto out1;
-	}
+	DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, idd->idd_pdev, idd->idd_pci_id));
 
 	/* request serial registers */
-	tmp_addr1 = pci_resource_start(pdev, 0) + IOC4_SERIAL_OFFSET;
+	tmp_addr1 = idd->idd_bar0 + IOC4_SERIAL_OFFSET;
 
 	if (!request_region(tmp_addr1, sizeof(struct ioc4_serial),
 					"sioc4_uart")) {
 		printk(KERN_WARNING
 			"ioc4 (%p): unable to get request region for "
-				"uart space\n", (void *)pdev);
+				"uart space\n", (void *)idd->idd_pdev);
 		ret = -ENODEV;
 		goto out1;
 	}
@@ -2736,12 +2678,12 @@
 	if (!serial) {
 		printk(KERN_WARNING
 			 "ioc4 (%p) : unable to remap ioc4 serial register\n",
-				(void *)pdev);
+				(void *)idd->idd_pdev);
 		ret = -ENODEV;
 		goto out2;
 	}
 	DPRINT_CONFIG(("%s : mem 0x%p, serial 0x%p\n",
-				__FUNCTION__, (void *)mem, (void *)serial));
+				__FUNCTION__, (void *)idd->idd_misc_regs, (void *)serial));
 
 	/* Get memory for the new card */
 	control = kmalloc(sizeof(struct ioc4_control) * IOC4_NUM_SERIAL_PORTS,
@@ -2754,59 +2696,56 @@
 		goto out2;
 	}
 	memset(control, 0, sizeof(struct ioc4_control));
-	pci_set_drvdata(pdev, control);
+	idd->idd_serial_data = control;
 
 	/* Allocate the soft structure */
 	soft = kmalloc(sizeof(struct ioc4_soft), GFP_KERNEL);
 	if (!soft) {
 		printk(KERN_WARNING
 		       "ioc4 (%p): unable to get memory for the soft struct\n",
-		       (void *)pdev);
+		       (void *)idd->idd_pdev);
 		ret = -ENOMEM;
 		goto out3;
 	}
 	memset(soft, 0, sizeof(struct ioc4_soft));
 
 	spin_lock_init(&soft->is_ir_lock);
-	soft->is_ioc4_mem_addr = mem;
+	soft->is_ioc4_misc_addr = idd->idd_misc_regs;
 	soft->is_ioc4_serial_addr = serial;
 
 	/* Init the IOC4 */
-	pci_read_config_dword(pdev, PCI_COMMAND, &tmp);
-	pci_write_config_dword(pdev, PCI_COMMAND,
-			       tmp | PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
-
-	writel(0xf << IOC4_SIO_CR_CMD_PULSE_SHIFT, &mem->sio_cr);
+	writel(0xf << IOC4_SIO_CR_CMD_PULSE_SHIFT,
+	       &idd->idd_misc_regs->sio_cr.raw);
 
 	/* Enable serial port mode select generic PIO pins as outputs */
 	writel(IOC4_GPCR_UART0_MODESEL | IOC4_GPCR_UART1_MODESEL
 		| IOC4_GPCR_UART2_MODESEL | IOC4_GPCR_UART3_MODESEL,
-		&mem->gpcr_s);
+		&idd->idd_misc_regs->gpcr_s.raw);
 
-	/* Clear and disable all interrupts */
+	/* Clear and disable all serial interrupts */
 	write_ireg(soft, ~0, IOC4_W_IEC, IOC4_SIO_INTR_TYPE);
-	writel(~0, &mem->sio_ir);
-	write_ireg(soft, ~(IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR),
-			IOC4_W_IEC, IOC4_OTHER_INTR_TYPE);
-	writel(~(IOC4_OTHER_IR_ATA_MEMERR | IOC4_OTHER_IR_ATA_MEMERR),
-					&mem->other_ir);
+	writel(~0, &idd->idd_misc_regs->sio_ir.raw);
+	write_ireg(soft, IOC4_OTHER_IR_SER_MEMERR, IOC4_W_IEC,
+		   IOC4_OTHER_INTR_TYPE);
+	writel(IOC4_OTHER_IR_SER_MEMERR, &idd->idd_misc_regs->other_ir.raw);
 	control->ic_soft = soft;
-	if (!request_irq(pdev->irq, ioc4_intr, SA_SHIRQ,
+
+	/* Hook up interrupt handler */
+	if (!request_irq(idd->idd_pdev->irq, ioc4_intr, SA_SHIRQ,
 				"sgi-ioc4serial", (void *)soft)) {
-		control->ic_irq = pdev->irq;
+		control->ic_irq = idd->idd_pdev->irq;
 	} else {
 		printk(KERN_WARNING
 		    "%s : request_irq fails for IRQ 0x%x\n ",
-			__FUNCTION__, pdev->irq);
+			__FUNCTION__, idd->idd_pdev->irq);
 	}
-	if ((ret = ioc4_attach_local(pdev, control, soft,
-				soft->is_ioc4_mem_addr,
-				soft->is_ioc4_serial_addr)))
+	ret = ioc4_attach_local(idd);
+	if (ret)
 		goto out4;
 
 	/* register port with the serial core */
 
-	if ((ret = ioc4_serial_core_attach(pdev)))
+	if ((ret = ioc4_serial_core_attach(idd->idd_pdev)))
 		goto out4;
 
 	return ret;
@@ -2819,7 +2758,6 @@
 out2:
 	release_region(tmp_addr1, sizeof(struct ioc4_serial));
 out1:
-	release_region(tmp_addr, sizeof(struct ioc4_mem));
 
 	return ret;
 }
@@ -2828,11 +2766,10 @@
 /**
  * ioc4_serial_remove_one - detach function
  *
- * @pdev: handle for this card
+ * @idd: IOC4 master module data for this IOC4
  */
 
-#if 0
-void ioc4_serial_remove_one(struct pci_dev *pdev)
+int ioc4_serial_remove_one(struct ioc4_driver_data *idd)
 {
 	int ii;
 	struct ioc4_control *control;
@@ -2840,7 +2777,7 @@
 	struct ioc4_port *port;
 	struct ioc4_soft *soft;
 
-	control = pci_get_drvdata(pdev);
+	control = idd->idd_serial_data;
 
 	for (ii = 0; ii < IOC4_NUM_SERIAL_PORTS; ii++) {
 		the_port = &control->ic_port[ii].icp_uart_port;
@@ -2867,10 +2804,17 @@
 		kfree(soft);
 	}
 	kfree(control);
-	pci_set_drvdata(pdev, NULL);
-	uart_unregister_driver(&ioc4_uart);
+	idd->idd_serial_data = NULL;
+
+	return 0;
 }
-#endif
+
+static struct ioc4_submodule ioc4_serial_submodule = {
+	.is_name = "IOC4_serial",
+	.is_owner = THIS_MODULE,
+	.is_probe = ioc4_serial_attach_one,
+	.is_remove = ioc4_serial_remove_one,
+};
 
 /**
  * ioc4_serial_init - module init
@@ -2886,12 +2830,20 @@
 			__FUNCTION__);
 		return ret;
 	}
-	return 0;
+
+	/* register with IOC4 main module */
+	return ioc4_register_submodule(&ioc4_serial_submodule);
 }
 
+static void __devexit ioc4_serial_exit(void)
+{
+	ioc4_unregister_submodule(&ioc4_serial_submodule);
+	uart_unregister_driver(&ioc4_uart);
+}
+
+module_init(ioc4_serial_init);
+module_exit(ioc4_serial_exit);
+
 MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>");
 MODULE_DESCRIPTION("Serial PCI driver module for SGI IOC4 Base-IO Card");
 MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(ioc4_serial_init);
-EXPORT_SYMBOL(ioc4_serial_attach_one);
diff --git a/drivers/serial/m32r_sio.c b/drivers/serial/m32r_sio.c
index 08d61f1..0301fea 100644
--- a/drivers/serial/m32r_sio.c
+++ b/drivers/serial/m32r_sio.c
@@ -724,22 +724,22 @@
 
 	switch (termios->c_cflag & CSIZE) {
 	case CS5:
-		cval = 0x00;
+		cval = UART_LCR_WLEN5;
 		break;
 	case CS6:
-		cval = 0x01;
+		cval = UART_LCR_WLEN6;
 		break;
 	case CS7:
-		cval = 0x02;
+		cval = UART_LCR_WLEN7;
 		break;
 	default:
 	case CS8:
-		cval = 0x03;
+		cval = UART_LCR_WLEN8;
 		break;
 	}
 
 	if (termios->c_cflag & CSTOPB)
-		cval |= 0x04;
+		cval |= UART_LCR_STOP;
 	if (termios->c_cflag & PARENB)
 		cval |= UART_LCR_PARITY;
 	if (!(termios->c_cflag & PARODD))
diff --git a/drivers/serial/mpsc.c b/drivers/serial/mpsc.c
index a8314ae..a2a6433 100644
--- a/drivers/serial/mpsc.c
+++ b/drivers/serial/mpsc.c
@@ -67,7 +67,11 @@
 
 static struct mpsc_port_info mpsc_ports[MPSC_NUM_CTLRS];
 static struct mpsc_shared_regs mpsc_shared_regs;
+static struct uart_driver mpsc_reg;
 
+static void mpsc_start_rx(struct mpsc_port_info *pi);
+static void mpsc_free_ring_mem(struct mpsc_port_info *pi);
+static void mpsc_release_port(struct uart_port *port);
 /*
  ******************************************************************************
  *
@@ -546,7 +550,6 @@
 mpsc_alloc_ring_mem(struct mpsc_port_info *pi)
 {
 	int rc = 0;
-	static void mpsc_free_ring_mem(struct mpsc_port_info *pi);
 
 	pr_debug("mpsc_alloc_ring_mem[%d]: Allocating ring mem\n",
 		pi->port.line);
@@ -745,7 +748,6 @@
 	int	rc = 0;
 	u8	*bp;
 	char	flag = TTY_NORMAL;
-	static void mpsc_start_rx(struct mpsc_port_info *pi);
 
 	pr_debug("mpsc_rx_intr[%d]: Handling Rx intr\n", pi->port.line);
 
@@ -1178,7 +1180,6 @@
 mpsc_shutdown(struct uart_port *port)
 {
 	struct mpsc_port_info *pi = (struct mpsc_port_info *)port;
-	static void mpsc_release_port(struct uart_port *port);
 
 	pr_debug("mpsc_shutdown[%d]: Shutting down MPSC\n", port->line);
 
@@ -1448,7 +1449,6 @@
 	return uart_set_options(&pi->port, co, baud, parity, bits, flow);
 }
 
-extern struct uart_driver mpsc_reg;
 static struct console mpsc_console = {
 	.name   = MPSC_DEV_NAME,
 	.write  = mpsc_console_write,
diff --git a/drivers/serial/pxa.c b/drivers/serial/pxa.c
index 9dc151d..08b08d6 100644
--- a/drivers/serial/pxa.c
+++ b/drivers/serial/pxa.c
@@ -455,22 +455,22 @@
 
 	switch (termios->c_cflag & CSIZE) {
 	case CS5:
-		cval = 0x00;
+		cval = UART_LCR_WLEN5;
 		break;
 	case CS6:
-		cval = 0x01;
+		cval = UART_LCR_WLEN6;
 		break;
 	case CS7:
-		cval = 0x02;
+		cval = UART_LCR_WLEN7;
 		break;
 	default:
 	case CS8:
-		cval = 0x03;
+		cval = UART_LCR_WLEN8;
 		break;
 	}
 
 	if (termios->c_cflag & CSTOPB)
-		cval |= 0x04;
+		cval |= UART_LCR_STOP;
 	if (termios->c_cflag & PARENB)
 		cval |= UART_LCR_PARITY;
 	if (!(termios->c_cflag & PARODD))
diff --git a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
index 2a9f7ad..5c46784 100644
--- a/drivers/serial/s3c2410.c
+++ b/drivers/serial/s3c2410.c
@@ -198,7 +198,7 @@
 
 /* translate a port to the device name */
 
-static inline char *s3c24xx_serial_portname(struct uart_port *port)
+static inline const char *s3c24xx_serial_portname(struct uart_port *port)
 {
 	return to_platform_device(port->dev)->name;
 }
@@ -903,7 +903,7 @@
 
 static int s3c24xx_serial_request_port(struct uart_port *port)
 {
-	char *name = s3c24xx_serial_portname(port);
+	const char *name = s3c24xx_serial_portname(port);
 	return request_mem_region(port->mapbase, MAP_SIZE, name) ? 0 : -EBUSY;
 }
 
diff --git a/drivers/serial/sa1100.c b/drivers/serial/sa1100.c
index 22565a6..98641c3 100644
--- a/drivers/serial/sa1100.c
+++ b/drivers/serial/sa1100.c
@@ -197,7 +197,7 @@
 sa1100_rx_chars(struct sa1100_port *sport, struct pt_regs *regs)
 {
 	struct tty_struct *tty = sport->port.info->tty;
-	unsigned int status, ch, flg, ignored = 0;
+	unsigned int status, ch, flg;
 
 	status = UTSR1_TO_SM(UART_GET_UTSR1(sport)) |
 		 UTSR0_TO_SM(UART_GET_UTSR0(sport));
diff --git a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
index fee6418..840815f 100644
--- a/drivers/serial/sn_console.c
+++ b/drivers/serial/sn_console.c
@@ -572,6 +572,7 @@
 
 	if (uart_circ_empty(xmit) || uart_tx_stopped(&port->sc_port)) {
 		/* Nothing to do. */
+		ia64_sn_console_intr_disable(SAL_CONSOLE_INTR_XMIT);
 		return;
 	}
 
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
index 5c4231a..8e65206 100644
--- a/drivers/serial/sunzilog.c
+++ b/drivers/serial/sunzilog.c
@@ -1071,7 +1071,7 @@
  */
 static struct zilog_layout __iomem * __init get_zs_sun4u(int chip, int zsnode)
 {
-	unsigned long mapped_addr;
+	void __iomem *mapped_addr;
 	unsigned int sun4u_ino;
 	struct sbus_bus *sbus = NULL;
 	struct sbus_dev *sdev = NULL;
@@ -1111,9 +1111,9 @@
 		apply_fhc_ranges(central_bus->child,
 				 &zsregs[0], 1);
 		apply_central_ranges(central_bus, &zsregs[0], 1);
-		mapped_addr =
-			(((u64)zsregs[0].which_io)<<32UL) |
-			((u64)zsregs[0].phys_addr);
+		mapped_addr = (void __iomem *)
+			((((u64)zsregs[0].which_io)<<32UL) |
+			((u64)zsregs[0].phys_addr));
 	}
 
 	if (zilog_irq == -1) {
diff --git a/drivers/sh/superhyway/superhyway-sysfs.c b/drivers/sh/superhyway/superhyway-sysfs.c
index 39ab6a1..dc119ce 100644
--- a/drivers/sh/superhyway/superhyway-sysfs.c
+++ b/drivers/sh/superhyway/superhyway-sysfs.c
@@ -15,7 +15,7 @@
 #include <linux/superhyway.h>
 
 #define superhyway_ro_attr(name, fmt, field)				\
-static ssize_t name##_show(struct device *dev, char *buf)		\
+static ssize_t name##_show(struct device *dev, struct device_attribute *attr, char *buf)		\
 {									\
 	struct superhyway_device *s = to_superhyway_device(dev);	\
 	return sprintf(buf, fmt, s->field);				\
diff --git a/drivers/sn/Kconfig b/drivers/sn/Kconfig
new file mode 100644
index 0000000..13b8d24
--- /dev/null
+++ b/drivers/sn/Kconfig
@@ -0,0 +1,20 @@
+#
+# Miscellaneous SN-specific devices
+#
+
+menu "SN Devices"
+
+config SGI_IOC4
+	tristate "SGI IOC4 Base IO support"
+	depends on (IA64_GENERIC || IA64_SGI_SN2) && MMTIMER
+	default m
+	---help---
+	This option enables basic support for the SGI IOC4-based Base IO
+	controller card.  This option does not enable any specific
+	functions on such a card, but provides necessary infrastructure
+	for other drivers to utilize.
+
+	If you have an SGI Altix with an IOC4-based
+	I/O controller say Y.  Otherwise say N.
+
+endmenu
diff --git a/drivers/sn/Makefile b/drivers/sn/Makefile
index 631e549..c2a2841 100644
--- a/drivers/sn/Makefile
+++ b/drivers/sn/Makefile
@@ -3,4 +3,4 @@
 #
 #
 
-obj-$(CONFIG_BLK_DEV_SGIIOC4) += ioc4.o
+obj-$(CONFIG_SGI_IOC4) += ioc4.o
diff --git a/drivers/sn/ioc4.c b/drivers/sn/ioc4.c
index d9e4ee2..ea75b3d 100644
--- a/drivers/sn/ioc4.c
+++ b/drivers/sn/ioc4.c
@@ -6,60 +6,422 @@
  * Copyright (C) 2005 Silicon Graphics, Inc.  All Rights Reserved.
  */
 
-/*
- * This file contains a shim driver for the IOC4 IDE and serial drivers.
+/* This file contains the master driver module for use by SGI IOC4 subdrivers.
+ *
+ * It allocates any resources shared between multiple subdevices, and
+ * provides accessor functions (where needed) and the like for those
+ * resources.  It also provides a mechanism for the subdevice modules
+ * to support loading and unloading.
+ *
+ * Non-shared resources (e.g. external interrupt A_INT_OUT register page
+ * alias, serial port and UART registers) are handled by the subdevice
+ * modules themselves.
+ *
+ * This is all necessary because IOC4 is not implemented as a multi-function
+ * PCI device, but an amalgamation of disparate registers for several
+ * types of device (ATA, serial, external interrupts).  The normal
+ * resource management in the kernel doesn't have quite the right interfaces
+ * to handle this situation (e.g. multiple modules can't claim the same
+ * PCI ID), thus this IOC4 master module.
  */
 
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/pci.h>
-#include <linux/ioc4_common.h>
-#include <linux/ide.h>
+#include <linux/ioc4.h>
+#include <linux/mmtimer.h>
+#include <linux/rtc.h>
+#include <linux/rwsem.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/clksupport.h>
+#include <asm/sn/shub_mmr.h>
 
+/***************
+ * Definitions *
+ ***************/
 
-static int __devinit
-ioc4_probe_one(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+/* Tweakable values */
+
+/* PCI bus speed detection/calibration */
+#define IOC4_CALIBRATE_COUNT 63	/* Calibration cycle period */
+#define IOC4_CALIBRATE_CYCLES 256	/* Average over this many cycles */
+#define IOC4_CALIBRATE_DISCARD 2	/* Discard first few cycles */
+#define IOC4_CALIBRATE_LOW_MHZ 25	/* Lower bound on bus speed sanity */
+#define IOC4_CALIBRATE_HIGH_MHZ 75	/* Upper bound on bus speed sanity */
+#define IOC4_CALIBRATE_DEFAULT_MHZ 66	/* Assumed if sanity check fails */
+
+/************************
+ * Submodule management *
+ ************************/
+
+static LIST_HEAD(ioc4_devices);
+static DECLARE_RWSEM(ioc4_devices_rwsem);
+
+static LIST_HEAD(ioc4_submodules);
+static DECLARE_RWSEM(ioc4_submodules_rwsem);
+
+/* Register an IOC4 submodule */
+int
+ioc4_register_submodule(struct ioc4_submodule *is)
 {
+	struct ioc4_driver_data *idd;
+
+	down_write(&ioc4_submodules_rwsem);
+	list_add(&is->is_list, &ioc4_submodules);
+	up_write(&ioc4_submodules_rwsem);
+
+	/* Initialize submodule for each IOC4 */
+	if (!is->is_probe)
+		return 0;
+
+	down_read(&ioc4_devices_rwsem);
+	list_for_each_entry(idd, &ioc4_devices, idd_list) {
+		if (is->is_probe(idd)) {
+			printk(KERN_WARNING
+			       "%s: IOC4 submodule %s probe failed "
+			       "for pci_dev %s",
+			       __FUNCTION__, module_name(is->is_owner),
+			       pci_name(idd->idd_pdev));
+		}
+	}
+	up_read(&ioc4_devices_rwsem);
+
+	return 0;
+}
+
+/* Unregister an IOC4 submodule */
+void
+ioc4_unregister_submodule(struct ioc4_submodule *is)
+{
+	struct ioc4_driver_data *idd;
+
+	down_write(&ioc4_submodules_rwsem);
+	list_del(&is->is_list);
+	up_write(&ioc4_submodules_rwsem);
+
+	/* Remove submodule for each IOC4 */
+	if (!is->is_remove)
+		return;
+
+	down_read(&ioc4_devices_rwsem);
+	list_for_each_entry(idd, &ioc4_devices, idd_list) {
+		if (is->is_remove(idd)) {
+			printk(KERN_WARNING
+			       "%s: IOC4 submodule %s remove failed "
+			       "for pci_dev %s.\n",
+			       __FUNCTION__, module_name(is->is_owner),
+			       pci_name(idd->idd_pdev));
+		}
+	}
+	up_read(&ioc4_devices_rwsem);
+}
+
+/*********************
+ * Device management *
+ *********************/
+
+#define IOC4_CALIBRATE_LOW_LIMIT \
+	(1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_LOW_MHZ)
+#define IOC4_CALIBRATE_HIGH_LIMIT \
+	(1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_HIGH_MHZ)
+#define IOC4_CALIBRATE_DEFAULT \
+	(1000*IOC4_EXTINT_COUNT_DIVISOR/IOC4_CALIBRATE_DEFAULT_MHZ)
+
+#define IOC4_CALIBRATE_END \
+	(IOC4_CALIBRATE_CYCLES + IOC4_CALIBRATE_DISCARD)
+
+#define IOC4_INT_OUT_MODE_TOGGLE 0x7	/* Toggle INT_OUT every COUNT+1 ticks */
+
+/* Determines external interrupt output clock period of the PCI bus an
+ * IOC4 is attached to.  This value can be used to determine the PCI
+ * bus speed.
+ *
+ * IOC4 has a design feature that various internal timers are derived from
+ * the PCI bus clock.  This causes IOC4 device drivers to need to take the
+ * bus speed into account when setting various register values (e.g. INT_OUT
+ * register COUNT field, UART divisors, etc).  Since this information is
+ * needed by several subdrivers, it is determined by the main IOC4 driver,
+ * even though the following code utilizes external interrupt registers
+ * to perform the speed calculation.
+ */
+static void
+ioc4_clock_calibrate(struct ioc4_driver_data *idd)
+{
+	extern unsigned long sn_rtc_cycles_per_second;
+	union ioc4_int_out int_out;
+	union ioc4_gpcr gpcr;
+	unsigned int state, last_state = 1;
+	uint64_t start = 0, end, period;
+	unsigned int count = 0;
+
+	/* Enable output */
+	gpcr.raw = 0;
+	gpcr.fields.dir = IOC4_GPCR_DIR_0;
+	gpcr.fields.int_out_en = 1;
+	writel(gpcr.raw, &idd->idd_misc_regs->gpcr_s.raw);
+
+	/* Reset to power-on state */
+	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;
+	int_out.fields.mode = IOC4_INT_OUT_MODE_TOGGLE;
+	int_out.fields.diag = 0;
+	writel(int_out.raw, &idd->idd_misc_regs->int_out.raw);
+	mmiowb();
+
+	/* Check square wave period averaged over some number of cycles */
+	do {
+		int_out.raw = readl(&idd->idd_misc_regs->int_out.raw);
+		state = int_out.fields.int_out;
+		if (!last_state && state) {
+			count++;
+			if (count == IOC4_CALIBRATE_END) {
+				end = rtc_time();
+				break;
+			} else if (count == IOC4_CALIBRATE_DISCARD)
+				start = rtc_time();
+		}
+		last_state = state;
+	} while (1);
+
+	/* Calculation rearranged to preserve intermediate precision.
+	 * Logically:
+	 * 1. "end - start" gives us number of RTC cycles over all the
+	 *    square wave cycles measured.
+	 * 2. Divide by number of square wave cycles to get number of
+	 *    RTC cycles per square wave cycle.
+	 * 3. Divide by 2*(int_out.fields.count+1), which is the formula
+	 *    by which the IOC4 generates the square wave, to get the
+	 *    number of RTC cycles per IOC4 INT_OUT count.
+	 * 4. Divide by sn_rtc_cycles_per_second to get seconds per
+	 *    count.
+	 * 5. Multiply by 1E9 to get nanoseconds per count.
+	 */
+	period = ((end - start) * 1000000000) /
+	    (IOC4_CALIBRATE_CYCLES * 2 * (IOC4_CALIBRATE_COUNT + 1)
+	     * sn_rtc_cycles_per_second);
+
+	/* 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",
+		       IOC4_CALIBRATE_DEFAULT / IOC4_EXTINT_COUNT_DIVISOR);
+		period = IOC4_CALIBRATE_DEFAULT;
+	} else {
+		printk("succeeded. PCI clock ticks are %ld ns.\n",
+		       period / IOC4_EXTINT_COUNT_DIVISOR);
+	}
+
+	/* Remember results.  We store the extint clock period rather
+	 * than the PCI clock period so that greater precision is
+	 * retained.  Divide by IOC4_EXTINT_COUNT_DIVISOR to get
+	 * PCI clock period.
+	 */
+	idd->count_period = period;
+}
+
+/* Adds a new instance of an IOC4 card */
+static int
+ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+{
+	struct ioc4_driver_data *idd;
+	struct ioc4_submodule *is;
+	uint32_t pcmd;
 	int ret;
 
+	/* Enable IOC4 and take ownership of it */
 	if ((ret = pci_enable_device(pdev))) {
 		printk(KERN_WARNING
-			 "%s: Failed to enable device with "
-				"pci_dev 0x%p... returning\n",
-				__FUNCTION__, (void *)pdev);
-		return ret;
+		       "%s: Failed to enable IOC4 device for pci_dev %s.\n",
+		       __FUNCTION__, pci_name(pdev));
+		goto out;
 	}
 	pci_set_master(pdev);
 
-	/* attach each sub-device */
-	ret = ioc4_ide_attach_one(pdev, pci_id);
-	if (ret)
-		return ret;
-	return ioc4_serial_attach_one(pdev, pci_id);
+	/* Set up per-IOC4 data */
+	idd = kmalloc(sizeof(struct ioc4_driver_data), GFP_KERNEL);
+	if (!idd) {
+		printk(KERN_WARNING
+		       "%s: Failed to allocate IOC4 data for pci_dev %s.\n",
+		       __FUNCTION__, pci_name(pdev));
+		ret = -ENODEV;
+		goto out_idd;
+	}
+	idd->idd_pdev = pdev;
+	idd->idd_pci_id = pci_id;
+
+	/* Map IOC4 misc registers.  These are shared between subdevices
+	 * so the main IOC4 module manages them.
+	 */
+	idd->idd_bar0 = pci_resource_start(idd->idd_pdev, 0);
+	if (!idd->idd_bar0) {
+		printk(KERN_WARNING
+		       "%s: Unable to find IOC4 misc resource "
+		       "for pci_dev %s.\n",
+		       __FUNCTION__, pci_name(idd->idd_pdev));
+		ret = -ENODEV;
+		goto out_pci;
+	}
+	if (!request_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs),
+			    "ioc4_misc")) {
+		printk(KERN_WARNING
+		       "%s: Unable to request IOC4 misc region "
+		       "for pci_dev %s.\n",
+		       __FUNCTION__, pci_name(idd->idd_pdev));
+		ret = -ENODEV;
+		goto out_pci;
+	}
+	idd->idd_misc_regs = ioremap(idd->idd_bar0,
+				     sizeof(struct ioc4_misc_regs));
+	if (!idd->idd_misc_regs) {
+		printk(KERN_WARNING
+		       "%s: Unable to remap IOC4 misc region "
+		       "for pci_dev %s.\n",
+		       __FUNCTION__, pci_name(idd->idd_pdev));
+		ret = -ENODEV;
+		goto out_misc_region;
+	}
+
+	/* Failsafe portion of per-IOC4 initialization */
+
+	/* Initialize IOC4 */
+	pci_read_config_dword(idd->idd_pdev, PCI_COMMAND, &pcmd);
+	pci_write_config_dword(idd->idd_pdev, PCI_COMMAND,
+			       pcmd | PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
+
+	/* Determine PCI clock */
+	ioc4_clock_calibrate(idd);
+
+	/* Disable/clear all interrupts.  Need to do this here lest
+	 * one submodule request the shared IOC4 IRQ, but interrupt
+	 * is generated by a different subdevice.
+	 */
+	/* Disable */
+	writel(~0, &idd->idd_misc_regs->other_iec.raw);
+	writel(~0, &idd->idd_misc_regs->sio_iec);
+	/* Clear (i.e. acknowledge) */
+	writel(~0, &idd->idd_misc_regs->other_ir.raw);
+	writel(~0, &idd->idd_misc_regs->sio_ir);
+
+	/* Track PCI-device specific data */
+	idd->idd_serial_data = NULL;
+	pci_set_drvdata(idd->idd_pdev, idd);
+	down_write(&ioc4_devices_rwsem);
+	list_add(&idd->idd_list, &ioc4_devices);
+	up_write(&ioc4_devices_rwsem);
+
+	/* Add this IOC4 to all submodules */
+	down_read(&ioc4_submodules_rwsem);
+	list_for_each_entry(is, &ioc4_submodules, is_list) {
+		if (is->is_probe && is->is_probe(idd)) {
+			printk(KERN_WARNING
+			       "%s: IOC4 submodule 0x%s probe failed "
+			       "for pci_dev %s.\n",
+			       __FUNCTION__, module_name(is->is_owner),
+			       pci_name(idd->idd_pdev));
+		}
+	}
+	up_read(&ioc4_submodules_rwsem);
+
+	return 0;
+
+out_misc_region:
+	release_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
+out_pci:
+	kfree(idd);
+out_idd:
+	pci_disable_device(pdev);
+out:
+	return ret;
 }
 
-/* pci device struct */
-static struct pci_device_id ioc4_s_id_table[] = {
+/* Removes a particular instance of an IOC4 card. */
+static void
+ioc4_remove(struct pci_dev *pdev)
+{
+	struct ioc4_submodule *is;
+	struct ioc4_driver_data *idd;
+
+	idd = pci_get_drvdata(pdev);
+
+	/* Remove this IOC4 from all submodules */
+	down_read(&ioc4_submodules_rwsem);
+	list_for_each_entry(is, &ioc4_submodules, is_list) {
+		if (is->is_remove && is->is_remove(idd)) {
+			printk(KERN_WARNING
+			       "%s: IOC4 submodule 0x%s remove failed "
+			       "for pci_dev %s.\n",
+			       __FUNCTION__, module_name(is->is_owner),
+			       pci_name(idd->idd_pdev));
+		}
+	}
+	up_read(&ioc4_submodules_rwsem);
+
+	/* Release resources */
+	iounmap(idd->idd_misc_regs);
+	if (!idd->idd_bar0) {
+		printk(KERN_WARNING
+		       "%s: Unable to get IOC4 misc mapping for pci_dev %s. "
+		       "Device removal may be incomplete.\n",
+		       __FUNCTION__, pci_name(idd->idd_pdev));
+	}
+	release_region(idd->idd_bar0, sizeof(struct ioc4_misc_regs));
+
+	/* Disable IOC4 and relinquish */
+	pci_disable_device(pdev);
+
+	/* Remove and free driver data */
+	down_write(&ioc4_devices_rwsem);
+	list_del(&idd->idd_list);
+	up_write(&ioc4_devices_rwsem);
+	kfree(idd);
+}
+
+static struct pci_device_id ioc4_id_table[] = {
 	{PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC4, PCI_ANY_ID,
 	 PCI_ANY_ID, 0x0b4000, 0xFFFFFF},
 	{0}
 };
-MODULE_DEVICE_TABLE(pci, ioc4_s_id_table);
 
-static struct pci_driver __devinitdata ioc4_s_driver = {
-	.name	= "IOC4",
-	.id_table = ioc4_s_id_table,
-	.probe	= ioc4_probe_one,
+static struct pci_driver __devinitdata ioc4_driver = {
+	.name = "IOC4",
+	.id_table = ioc4_id_table,
+	.probe = ioc4_probe,
+	.remove = ioc4_remove,
 };
 
-static int __devinit ioc4_detect(void)
+MODULE_DEVICE_TABLE(pci, ioc4_id_table);
+
+/*********************
+ * Module management *
+ *********************/
+
+/* Module load */
+static int __devinit
+ioc4_init(void)
 {
-	ioc4_serial_init();
-
-	return pci_register_driver(&ioc4_s_driver);
+	return pci_register_driver(&ioc4_driver);
 }
-module_init(ioc4_detect);
 
-MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>");
-MODULE_DESCRIPTION("PCI driver module for SGI IOC4 Base-IO Card");
+/* Module unload */
+static void __devexit
+ioc4_exit(void)
+{
+	pci_unregister_driver(&ioc4_driver);
+}
+
+module_init(ioc4_init);
+module_exit(ioc4_exit);
+
+MODULE_AUTHOR("Brent Casavant - Silicon Graphics, Inc. <bcasavan@sgi.com>");
+MODULE_DESCRIPTION("PCI driver master module for SGI IOC4 Base-IO Card");
 MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(ioc4_register_submodule);
+EXPORT_SYMBOL(ioc4_unregister_submodule);
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c
index d5863b8..f2c9fa4 100644
--- a/drivers/telephony/ixj.c
+++ b/drivers/telephony/ixj.c
@@ -329,10 +329,8 @@
 
 static void ixj_fsk_free(IXJ *j)
 {
-	if(j->fskdata != NULL) {
-		kfree(j->fskdata);
-		j->fskdata = NULL;
-	}
+	kfree(j->fskdata);
+	j->fskdata = NULL;
 }
 
 static void ixj_fsk_alloc(IXJ *j)
@@ -3867,13 +3865,11 @@
 		j->rec_mode = 7;
 		break;
 	default:
+		kfree(j->read_buffer);
 		j->rec_frame_size = 0;
 		j->rec_mode = -1;
-		if (j->read_buffer) {
-			kfree(j->read_buffer);
-			j->read_buffer = NULL;
-			j->read_buffer_size = 0;
-		}
+		j->read_buffer = NULL;
+		j->read_buffer_size = 0;
 		retval = 1;
 		break;
 	}
@@ -3991,14 +3987,12 @@
 
 static void ixj_record_stop(IXJ *j)
 {
-	if(ixjdebug & 0x0002)
+	if (ixjdebug & 0x0002)
 		printk("IXJ %d Stopping Record Codec %d at %ld\n", j->board, j->rec_codec, jiffies);
 
-	if (j->read_buffer) {
-		kfree(j->read_buffer);
-		j->read_buffer = NULL;
-		j->read_buffer_size = 0;
-	}
+	kfree(j->read_buffer);
+	j->read_buffer = NULL;
+	j->read_buffer_size = 0;
 	if (j->rec_mode > -1) {
 		ixj_WriteDSPCommand(0x5120, j);
 		j->rec_mode = -1;
@@ -4449,13 +4443,11 @@
 		j->play_mode = 5;
 		break;
 	default:
+		kfree(j->write_buffer);
 		j->play_frame_size = 0;
 		j->play_mode = -1;
-		if (j->write_buffer) {
-			kfree(j->write_buffer);
-			j->write_buffer = NULL;
-			j->write_buffer_size = 0;
-		}
+		j->write_buffer = NULL;
+		j->write_buffer_size = 0;
 		retval = 1;
 		break;
 	}
@@ -4578,14 +4570,12 @@
 
 static void ixj_play_stop(IXJ *j)
 {
-	if(ixjdebug & 0x0002)
+	if (ixjdebug & 0x0002)
 		printk("IXJ %d Stopping Play Codec %d at %ld\n", j->board, j->play_codec, jiffies);
 
-	if (j->write_buffer) {
-		kfree(j->write_buffer);
-		j->write_buffer = NULL;
-		j->write_buffer_size = 0;
-	}
+	kfree(j->write_buffer);
+	j->write_buffer = NULL;
+	j->write_buffer_size = 0;
 	if (j->play_mode > -1) {
 		ixj_WriteDSPCommand(0x5221, j);	/* Stop playback and flush buffers.  8022 reference page 9-40 */
 
@@ -5810,9 +5800,7 @@
 		ixj_play_tone(j, 0);
 		j->tone_state = j->tone_cadence_state = 0;
 		if (j->cadence_t) {
-			if (j->cadence_t->ce) {
-				kfree(j->cadence_t->ce);
-			}
+			kfree(j->cadence_t->ce);
 			kfree(j->cadence_t);
 			j->cadence_t = NULL;
 		}
@@ -7497,10 +7485,8 @@
 					printk(KERN_INFO "IXJ: Releasing XILINX address for /dev/phone%d\n", cnt);
 				release_region(j->XILINXbase, 4);
 			}
-			if (j->read_buffer)
-				kfree(j->read_buffer);
-			if (j->write_buffer)
-				kfree(j->write_buffer);
+			kfree(j->read_buffer);
+			kfree(j->write_buffer);
 			if (j->dev)
 				pnp_device_detach(j->dev);
 			if (ixjdebug & 0x0002)
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index ef0b357..83e815d 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -239,7 +239,7 @@
 	int setno)
 {
 	const struct usb_interface_descriptor *desc = &intfc->altsetting[setno].desc;
-	char *driver_name = "";
+	const char *driver_name = "";
 
 	if (start > end)
 		return start;
diff --git a/drivers/usb/core/file.c b/drivers/usb/core/file.c
index 38ed222..65ca131 100644
--- a/drivers/usb/core/file.c
+++ b/drivers/usb/core/file.c
@@ -68,7 +68,7 @@
 	.open =		usb_open,
 };
 
-static struct class_simple *usb_class;
+static struct class *usb_class;
 
 int usb_major_init(void)
 {
@@ -80,9 +80,10 @@
 		goto out;
 	}
 
-	usb_class = class_simple_create(THIS_MODULE, "usb");
+	usb_class = class_create(THIS_MODULE, "usb");
 	if (IS_ERR(usb_class)) {
-		err("class_simple_create failed for usb devices");
+		error = PTR_ERR(usb_class);
+		err("class_create failed for usb devices");
 		unregister_chrdev(USB_MAJOR, "usb");
 		goto out;
 	}
@@ -95,7 +96,7 @@
 
 void usb_major_cleanup(void)
 {
-	class_simple_destroy(usb_class);
+	class_destroy(usb_class);
 	devfs_remove("usb");
 	unregister_chrdev(USB_MAJOR, "usb");
 }
@@ -171,7 +172,7 @@
 		++temp;
 	else
 		temp = name;
-	intf->class_dev = class_simple_device_add(usb_class, MKDEV(USB_MAJOR, minor), &intf->dev, "%s", temp);
+	intf->class_dev = class_device_create(usb_class, MKDEV(USB_MAJOR, minor), &intf->dev, "%s", temp);
 	if (IS_ERR(intf->class_dev)) {
 		spin_lock (&minor_lock);
 		usb_minors[intf->minor] = NULL;
@@ -220,7 +221,7 @@
 
 	snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base);
 	devfs_remove (name);
-	class_simple_device_remove(MKDEV(USB_MAJOR, intf->minor));
+	class_device_destroy(usb_class, MKDEV(USB_MAJOR, intf->minor));
 	intf->class_dev = NULL;
 	intf->minor = -1;
 }
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 266e9e0..0da2373 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -651,50 +651,45 @@
 /*-------------------------------------------------------------------------*/
 
 /* exported only within usbcore */
-struct usb_bus *usb_bus_get (struct usb_bus *bus)
-{
-	struct class_device *tmp;
-
-	if (!bus)
-		return NULL;
-
-	tmp = class_device_get(&bus->class_dev);
-	if (tmp)        
-		return to_usb_bus(tmp);
-	else
-		return NULL;
-}
-
-/* exported only within usbcore */
-void usb_bus_put (struct usb_bus *bus)
+struct usb_bus *usb_bus_get(struct usb_bus *bus)
 {
 	if (bus)
-		class_device_put(&bus->class_dev);
+		kref_get(&bus->kref);
+	return bus;
 }
 
-/*-------------------------------------------------------------------------*/
-
-static void usb_host_release(struct class_device *class_dev)
+static void usb_host_release(struct kref *kref)
 {
-	struct usb_bus *bus = to_usb_bus(class_dev);
+	struct usb_bus *bus = container_of(kref, struct usb_bus, kref);
 
 	if (bus->release)
 		bus->release(bus);
 }
 
-static struct class usb_host_class = {
-	.name		= "usb_host",
-	.release	= &usb_host_release,
-};
+/* exported only within usbcore */
+void usb_bus_put(struct usb_bus *bus)
+{
+	if (bus)
+		kref_put(&bus->kref, usb_host_release);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct class *usb_host_class;
 
 int usb_host_init(void)
 {
-	return class_register(&usb_host_class);
+	int retval = 0;
+
+	usb_host_class = class_create(THIS_MODULE, "usb_host");
+	if (IS_ERR(usb_host_class))
+		retval = PTR_ERR(usb_host_class);
+	return retval;
 }
 
 void usb_host_cleanup(void)
 {
-	class_unregister(&usb_host_class);
+	class_destroy(usb_host_class);
 }
 
 /**
@@ -719,8 +714,7 @@
 
 	INIT_LIST_HEAD (&bus->bus_list);
 
-	class_device_initialize(&bus->class_dev);
-	bus->class_dev.class = &usb_host_class;
+	kref_init(&bus->kref);
 }
 
 /**
@@ -761,7 +755,6 @@
 static int usb_register_bus(struct usb_bus *bus)
 {
 	int busnum;
-	int retval;
 
 	down (&usb_bus_list_lock);
 	busnum = find_next_zero_bit (busmap.busmap, USB_MAXBUS, 1);
@@ -774,15 +767,15 @@
 		return -E2BIG;
 	}
 
-	snprintf(bus->class_dev.class_id, BUS_ID_SIZE, "usb%d", busnum);
-	bus->class_dev.dev = bus->controller;
-	retval = class_device_add(&bus->class_dev);
-	if (retval) {
+	bus->class_dev = class_device_create(usb_host_class, MKDEV(0,0), bus->controller, "usb%d", busnum);
+	if (IS_ERR(bus->class_dev)) {
 		clear_bit(busnum, busmap.busmap);
 		up(&usb_bus_list_lock);
-		return retval;
+		return PTR_ERR(bus->class_dev);
 	}
 
+	class_set_devdata(bus->class_dev, bus);
+
 	/* Add it to the local list of buses */
 	list_add (&bus->bus_list, &usb_bus_list);
 	up (&usb_bus_list_lock);
@@ -820,7 +813,7 @@
 
 	clear_bit (bus->busnum, busmap.busmap);
 
-	class_device_del(&bus->class_dev);
+	class_device_unregister(bus->class_dev);
 }
 
 /**
@@ -1801,7 +1794,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
+#if defined(CONFIG_USB_MON)
 
 struct usb_mon_operations *mon_ops;
 
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index f67cf1e..325a516 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -399,7 +399,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
+#if defined(CONFIG_USB_MON)
 
 struct usb_mon_operations {
 	void (*urb_submit)(struct usb_bus *bus, struct urb *urb);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index d2d648e..a8d879a 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -2808,7 +2808,7 @@
 	do {
 		hub_events();
 		wait_event_interruptible(khubd_wait, !list_empty(&hub_event_list)); 
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 	} while (!signal_pending(current));
 
 	pr_debug ("%s: khubd exiting\n", usbcore_name);
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c
index f9f9561..c3e3a95 100644
--- a/drivers/usb/core/inode.c
+++ b/drivers/usb/core/inode.c
@@ -453,17 +453,6 @@
 	return 0;
 }
 
-static struct dentry * get_dentry(struct dentry *parent, const char *name)
-{               
-	struct qstr qstr;
-
-	qstr.name = name;
-	qstr.len = strlen(name);
-	qstr.hash = full_name_hash(name,qstr.len);
-	return lookup_hash(&qstr,parent);
-}               
-
-
 /*
  * fs_create_by_name - create a file, given a name
  * @name:	name of file
@@ -496,7 +485,7 @@
 
 	*dentry = NULL;
 	down(&parent->d_inode->i_sem);
-	*dentry = get_dentry (parent, name);
+	*dentry = lookup_one_len(name, parent, strlen(name));
 	if (!IS_ERR(dentry)) {
 		if ((mode & S_IFMT) == S_IFDIR)
 			error = usbfs_mkdir (parent->d_inode, *dentry, mode);
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 4d0c9e6..740cb4c 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -24,7 +24,7 @@
 
 /* Active configuration fields */
 #define usb_actconfig_show(field, multiplier, format_string)		\
-static ssize_t  show_##field (struct device *dev, char *buf)		\
+static ssize_t  show_##field (struct device *dev, struct device_attribute *attr, char *buf)		\
 {									\
 	struct usb_device *udev;					\
 	struct usb_host_config *actconfig;				\
@@ -46,7 +46,7 @@
 usb_actconfig_attr (bmAttributes, 1, "%2x\n")
 usb_actconfig_attr (bMaxPower, 2, "%3dmA\n")
 
-static ssize_t show_configuration_string(struct device *dev, char *buf)
+static ssize_t show_configuration_string(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct usb_device *udev;
 	struct usb_host_config *actconfig;
@@ -69,7 +69,7 @@
 usb_actconfig_show(bConfigurationValue, 1, "%u\n");
 
 static ssize_t
-set_bConfigurationValue (struct device *dev, const char *buf, size_t count)
+set_bConfigurationValue (struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct usb_device	*udev = udev = to_usb_device (dev);
 	int			config, value;
@@ -87,7 +87,7 @@
 
 /* String fields */
 #define usb_string_attr(name)						\
-static ssize_t  show_##name(struct device *dev, char *buf)		\
+static ssize_t  show_##name(struct device *dev, struct device_attribute *attr, char *buf)		\
 {									\
 	struct usb_device *udev;					\
 	int len;							\
@@ -107,7 +107,7 @@
 usb_string_attr(serial);
 
 static ssize_t
-show_speed (struct device *dev, char *buf)
+show_speed (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct usb_device *udev;
 	char *speed;
@@ -133,7 +133,7 @@
 static DEVICE_ATTR(speed, S_IRUGO, show_speed, NULL);
 
 static ssize_t
-show_devnum (struct device *dev, char *buf)
+show_devnum (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct usb_device *udev;
 
@@ -143,7 +143,7 @@
 static DEVICE_ATTR(devnum, S_IRUGO, show_devnum, NULL);
 
 static ssize_t
-show_version (struct device *dev, char *buf)
+show_version (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct usb_device *udev;
 	u16 bcdUSB;
@@ -155,7 +155,7 @@
 static DEVICE_ATTR(version, S_IRUGO, show_version, NULL);
 
 static ssize_t
-show_maxchild (struct device *dev, char *buf)
+show_maxchild (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct usb_device *udev;
 
@@ -167,7 +167,7 @@
 /* Descriptor fields */
 #define usb_descriptor_attr_le16(field, format_string)			\
 static ssize_t								\
-show_##field (struct device *dev, char *buf)				\
+show_##field (struct device *dev, struct device_attribute *attr, char *buf)				\
 {									\
 	struct usb_device *udev;					\
 									\
@@ -183,7 +183,7 @@
 
 #define usb_descriptor_attr(field, format_string)			\
 static ssize_t								\
-show_##field (struct device *dev, char *buf)				\
+show_##field (struct device *dev, struct device_attribute *attr, char *buf)				\
 {									\
 	struct usb_device *udev;					\
 									\
@@ -254,7 +254,7 @@
 /* Interface fields */
 #define usb_intf_attr(field, format_string)				\
 static ssize_t								\
-show_##field (struct device *dev, char *buf)				\
+show_##field (struct device *dev, struct device_attribute *attr, char *buf)				\
 {									\
 	struct usb_interface *intf = to_usb_interface (dev);		\
 									\
@@ -269,7 +269,7 @@
 usb_intf_attr (bInterfaceSubClass, "%02x\n")
 usb_intf_attr (bInterfaceProtocol, "%02x\n")
 
-static ssize_t show_interface_string(struct device *dev, char *buf)
+static ssize_t show_interface_string(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct usb_interface *intf;
 	struct usb_device *udev;
@@ -286,7 +286,7 @@
 }
 static DEVICE_ATTR(interface, S_IRUGO, show_interface_string, NULL);
 
-static ssize_t show_modalias(struct device *dev, char *buf)
+static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct usb_interface *intf;
 	struct usb_device *udev;
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 25cf7e9..a3c4220 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -293,7 +293,7 @@
 	/* if interface was already added, bind now; else let
 	 * the future device_add() bind it, bypassing probe()
 	 */
-	if (!list_empty (&dev->bus_list))
+	if (klist_node_attached(&dev->knode_bus))
 		device_bind_driver(dev);
 
 	return 0;
@@ -322,9 +322,15 @@
 	if (!dev->driver || dev->driver != &driver->driver)
 		return;
 
-	/* don't disconnect from disconnect(), or before dev_add() */
-	if (!list_empty (&dev->driver_list) && !list_empty (&dev->bus_list))
+	/* don't release from within disconnect() */
+	if (iface->condition != USB_INTERFACE_BOUND)
+		return;
+
+	/* release only after device_add() */
+	if (klist_node_attached(&dev->knode_bus)) {
+		iface->condition = USB_INTERFACE_UNBINDING;
 		device_release_driver(dev);
+	}
 
 	dev->driver = NULL;
 	usb_set_intfdata(iface, NULL);
@@ -462,6 +468,25 @@
 	return NULL;
 }
 
+
+static int __find_interface(struct device * dev, void * data)
+{
+	struct usb_interface ** ret = (struct usb_interface **)data;
+	struct usb_interface * intf = *ret;
+	int *minor = (int *)data;
+
+	/* can't look at usb devices, only interfaces */
+	if (dev->driver == &usb_generic_driver)
+		return 0;
+
+	intf = to_usb_interface(dev);
+	if (intf->minor != -1 && intf->minor == *minor) {
+		*ret = intf;
+		return 1;
+	}
+	return 0;
+}
+
 /**
  * usb_find_interface - find usb_interface pointer for driver and device
  * @drv: the driver whose current configuration is considered
@@ -473,26 +498,12 @@
  */
 struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor)
 {
-	struct list_head *entry;
-	struct device *dev;
-	struct usb_interface *intf;
+	struct usb_interface *intf = (struct usb_interface *)(long)minor;
+	int ret;
 
-	list_for_each(entry, &drv->driver.devices) {
-		dev = container_of(entry, struct device, driver_list);
+	ret = driver_for_each_device(&drv->driver, NULL, &intf, __find_interface);
 
-		/* can't look at usb devices, only interfaces */
-		if (dev->driver == &usb_generic_driver)
-			continue;
-
-		intf = to_usb_interface(dev);
-		if (intf->minor == -1)
-			continue;
-		if (intf->minor == minor)
-			return intf;
-	}
-
-	/* no device found that matches */
-	return NULL;	
+	return ret ? intf : NULL;
 }
 
 static int usb_device_match (struct device *dev, struct device_driver *drv)
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 8ef8a9c..c039d2f 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -633,7 +633,7 @@
 
 /* "function" sysfs attribute */
 static ssize_t
-show_function (struct device *dev, char *buf)
+show_function (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct dummy	*dum = gadget_dev_to_dummy (dev);
 
@@ -1600,7 +1600,7 @@
 }
 
 static ssize_t
-show_urbs (struct device *dev, char *buf)
+show_urbs (struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct usb_hcd		*hcd = dev_get_drvdata (dev);
 	struct dummy		*dum = hcd_to_dummy (hcd);
diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c
index 4857f0e..a9be851 100644
--- a/drivers/usb/gadget/file_storage.c
+++ b/drivers/usb/gadget/file_storage.c
@@ -1554,8 +1554,7 @@
 	rc = wait_event_interruptible(fsg->thread_wqh,
 			fsg->thread_wakeup_needed);
 	fsg->thread_wakeup_needed = 0;
-	if (current->flags & PF_FREEZE)
-		refrigerator(PF_FREEZE);
+	try_to_freeze();
 	return (rc ? -EINTR : 0);
 }
 
@@ -3554,14 +3553,14 @@
 }
 
 
-static ssize_t show_ro(struct device *dev, char *buf)
+static ssize_t show_ro(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lun	*curlun = dev_to_lun(dev);
 
 	return sprintf(buf, "%d\n", curlun->ro);
 }
 
-static ssize_t show_file(struct device *dev, char *buf)
+static ssize_t show_file(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct lun	*curlun = dev_to_lun(dev);
 	struct fsg_dev	*fsg = (struct fsg_dev *) dev_get_drvdata(dev);
@@ -3589,7 +3588,7 @@
 }
 
 
-static ssize_t store_ro(struct device *dev, const char *buf, size_t count)
+static ssize_t store_ro(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	ssize_t		rc = count;
 	struct lun	*curlun = dev_to_lun(dev);
@@ -3613,7 +3612,7 @@
 	return rc;
 }
 
-static ssize_t store_file(struct device *dev, const char *buf, size_t count)
+static ssize_t store_file(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct lun	*curlun = dev_to_lun(dev);
 	struct fsg_dev	*fsg = (struct fsg_dev *) dev_get_drvdata(dev);
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index e5457f2..e47e398 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -1469,7 +1469,7 @@
 
 /* "function" sysfs attribute */
 static ssize_t
-show_function (struct device *_dev, char *buf)
+show_function (struct device *_dev, struct device_attribute *attr, char *buf)
 {
 	struct net2280	*dev = dev_get_drvdata (_dev);
 
@@ -1482,7 +1482,7 @@
 static DEVICE_ATTR (function, S_IRUGO, show_function, NULL);
 
 static ssize_t
-show_registers (struct device *_dev, char *buf)
+show_registers (struct device *_dev, struct device_attribute *attr, char *buf)
 {
 	struct net2280		*dev;
 	char			*next;
@@ -1637,7 +1637,7 @@
 static DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
 
 static ssize_t
-show_queues (struct device *_dev, char *buf)
+show_queues (struct device *_dev, struct device_attribute *attr, char *buf)
 {
 	struct net2280		*dev;
 	char			*next;
diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
index 6390c57..b8b4524 100644
--- a/drivers/usb/gadget/pxa2xx_udc.c
+++ b/drivers/usb/gadget/pxa2xx_udc.c
@@ -1429,7 +1429,7 @@
 
 /* "function" sysfs attribute */
 static ssize_t
-show_function (struct device *_dev, char *buf)
+show_function (struct device *_dev, struct device_attribute *attr, char *buf)
 {
 	struct pxa2xx_udc	*dev = dev_get_drvdata (_dev);
 
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 9b347d7..2ff11d5 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -450,7 +450,7 @@
 
 	*buf = 0;
 
-	bus = to_usb_bus(class_dev);
+	bus = class_get_devdata(class_dev);
 	hcd = bus->hcpriv;
 	ehci = hcd_to_ehci (hcd);
 	next = buf;
@@ -496,7 +496,7 @@
 		return 0;
 	seen_count = 0;
 
-	bus = to_usb_bus(class_dev);
+	bus = class_get_devdata(class_dev);
 	hcd = bus->hcpriv;
 	ehci = hcd_to_ehci (hcd);
 	next = buf;
@@ -633,7 +633,7 @@
 	static char		fmt [] = "%*s\n";
 	static char		label [] = "";
 
-	bus = to_usb_bus(class_dev);
+	bus = class_get_devdata(class_dev);
 	hcd = bus->hcpriv;
 	ehci = hcd_to_ehci (hcd);
 	next = buf;
@@ -735,7 +735,7 @@
 
 static inline void create_debug_files (struct ehci_hcd *ehci)
 {
-	struct class_device *cldev = &ehci_to_hcd(ehci)->self.class_dev;
+	struct class_device *cldev = ehci_to_hcd(ehci)->self.class_dev;
 
 	class_device_create_file(cldev, &class_device_attr_async);
 	class_device_create_file(cldev, &class_device_attr_periodic);
@@ -744,7 +744,7 @@
 
 static inline void remove_debug_files (struct ehci_hcd *ehci)
 {
-	struct class_device *cldev = &ehci_to_hcd(ehci)->self.class_dev;
+	struct class_device *cldev = ehci_to_hcd(ehci)->self.class_dev;
 
 	class_device_remove_file(cldev, &class_device_attr_async);
 	class_device_remove_file(cldev, &class_device_attr_periodic);
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 429330b..d7b4f79 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -439,9 +439,12 @@
 			/* force reset to complete */
 			writel (temp & ~PORT_RESET,
 					&ehci->regs->port_status [wIndex]);
+			/* REVISIT:  some hardware needs 550+ usec to clear
+			 * this bit; seems too long to spin routinely...
+			 */
 			retval = handshake (
 					&ehci->regs->port_status [wIndex],
-					PORT_RESET, 0, 500);
+					PORT_RESET, 0, 750);
 			if (retval != 0) {
 				ehci_err (ehci, "port %d reset error %d\n",
 					wIndex + 1, retval);
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index 62f53a2..c58408c 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -481,7 +481,7 @@
 	size_t			temp;
 	unsigned long		flags;
 
-	bus = to_usb_bus(class_dev);
+	bus = class_get_devdata(class_dev);
 	hcd = bus->hcpriv;
 	ohci = hcd_to_ohci(hcd);
 
@@ -514,7 +514,7 @@
 		return 0;
 	seen_count = 0;
 
-	bus = to_usb_bus(class_dev);
+	bus = class_get_devdata(class_dev);
 	hcd = bus->hcpriv;
 	ohci = hcd_to_ohci(hcd);
 	next = buf;
@@ -611,7 +611,7 @@
 	char			*next;
 	u32			rdata;
 
-	bus = to_usb_bus(class_dev);
+	bus = class_get_devdata(class_dev);
 	hcd = bus->hcpriv;
 	ohci = hcd_to_ohci(hcd);
 	regs = ohci->regs;
@@ -684,7 +684,7 @@
 
 static inline void create_debug_files (struct ohci_hcd *ohci)
 {
-	struct class_device *cldev = &ohci_to_hcd(ohci)->self.class_dev;
+	struct class_device *cldev = ohci_to_hcd(ohci)->self.class_dev;
 
 	class_device_create_file(cldev, &class_device_attr_async);
 	class_device_create_file(cldev, &class_device_attr_periodic);
@@ -694,7 +694,7 @@
 
 static inline void remove_debug_files (struct ohci_hcd *ohci)
 {
-	struct class_device *cldev = &ohci_to_hcd(ohci)->self.class_dev;
+	struct class_device *cldev = ohci_to_hcd(ohci)->self.class_dev;
 
 	class_device_remove_file(cldev, &class_device_attr_async);
 	class_device_remove_file(cldev, &class_device_attr_periodic);
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
index a692185..6bb0f25 100644
--- a/drivers/usb/input/aiptek.c
+++ b/drivers/usb/input/aiptek.c
@@ -1016,7 +1016,7 @@
 /***********************************************************************
  * support the 'size' file -- display support
  */
-static ssize_t show_tabletSize(struct device *dev, char *buf)
+static ssize_t show_tabletSize(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
@@ -1039,7 +1039,7 @@
 /***********************************************************************
  * support routines for the 'product_id' file
  */
-static ssize_t show_tabletProductId(struct device *dev, char *buf)
+static ssize_t show_tabletProductId(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
@@ -1055,7 +1055,7 @@
 /***********************************************************************
  * support routines for the 'vendor_id' file
  */
-static ssize_t show_tabletVendorId(struct device *dev, char *buf)
+static ssize_t show_tabletVendorId(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
@@ -1070,7 +1070,7 @@
 /***********************************************************************
  * support routines for the 'vendor' file
  */
-static ssize_t show_tabletManufacturer(struct device *dev, char *buf)
+static ssize_t show_tabletManufacturer(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	int retval;
@@ -1087,7 +1087,7 @@
 /***********************************************************************
  * support routines for the 'product' file
  */
-static ssize_t show_tabletProduct(struct device *dev, char *buf)
+static ssize_t show_tabletProduct(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	int retval;
@@ -1105,7 +1105,7 @@
  * support routines for the 'pointer_mode' file. Note that this file
  * both displays current setting and allows reprogramming.
  */
-static ssize_t show_tabletPointerMode(struct device *dev, char *buf)
+static ssize_t show_tabletPointerMode(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	char *s;
@@ -1134,7 +1134,7 @@
 }
 
 static ssize_t
-store_tabletPointerMode(struct device *dev, const char *buf, size_t count)
+store_tabletPointerMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	if (aiptek == NULL)
@@ -1159,7 +1159,7 @@
  * support routines for the 'coordinate_mode' file. Note that this file
  * both displays current setting and allows reprogramming.
  */
-static ssize_t show_tabletCoordinateMode(struct device *dev, char *buf)
+static ssize_t show_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	char *s;
@@ -1184,7 +1184,7 @@
 }
 
 static ssize_t
-store_tabletCoordinateMode(struct device *dev, const char *buf, size_t count)
+store_tabletCoordinateMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	if (aiptek == NULL)
@@ -1208,7 +1208,7 @@
  * support routines for the 'tool_mode' file. Note that this file
  * both displays current setting and allows reprogramming.
  */
-static ssize_t show_tabletToolMode(struct device *dev, char *buf)
+static ssize_t show_tabletToolMode(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	char *s;
@@ -1253,7 +1253,7 @@
 }
 
 static ssize_t
-store_tabletToolMode(struct device *dev, const char *buf, size_t count)
+store_tabletToolMode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	if (aiptek == NULL)
@@ -1286,7 +1286,7 @@
  * support routines for the 'xtilt' file. Note that this file
  * both displays current setting and allows reprogramming.
  */
-static ssize_t show_tabletXtilt(struct device *dev, char *buf)
+static ssize_t show_tabletXtilt(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
@@ -1302,7 +1302,7 @@
 }
 
 static ssize_t
-store_tabletXtilt(struct device *dev, const char *buf, size_t count)
+store_tabletXtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	int x;
@@ -1328,7 +1328,7 @@
  * support routines for the 'ytilt' file. Note that this file
  * both displays current setting and allows reprogramming.
  */
-static ssize_t show_tabletYtilt(struct device *dev, char *buf)
+static ssize_t show_tabletYtilt(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
@@ -1344,7 +1344,7 @@
 }
 
 static ssize_t
-store_tabletYtilt(struct device *dev, const char *buf, size_t count)
+store_tabletYtilt(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	int y;
@@ -1370,7 +1370,7 @@
  * support routines for the 'jitter' file. Note that this file
  * both displays current setting and allows reprogramming.
  */
-static ssize_t show_tabletJitterDelay(struct device *dev, char *buf)
+static ssize_t show_tabletJitterDelay(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
@@ -1381,7 +1381,7 @@
 }
 
 static ssize_t
-store_tabletJitterDelay(struct device *dev, const char *buf, size_t count)
+store_tabletJitterDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
@@ -1400,7 +1400,7 @@
  * support routines for the 'delay' file. Note that this file
  * both displays current setting and allows reprogramming.
  */
-static ssize_t show_tabletProgrammableDelay(struct device *dev, char *buf)
+static ssize_t show_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
@@ -1412,7 +1412,7 @@
 }
 
 static ssize_t
-store_tabletProgrammableDelay(struct device *dev, const char *buf, size_t count)
+store_tabletProgrammableDelay(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
@@ -1431,7 +1431,7 @@
  * support routines for the 'input_path' file. Note that this file
  * only displays current setting.
  */
-static ssize_t show_tabletInputDevice(struct device *dev, char *buf)
+static ssize_t show_tabletInputDevice(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
@@ -1448,7 +1448,7 @@
  * support routines for the 'event_count' file. Note that this file
  * only displays current setting.
  */
-static ssize_t show_tabletEventsReceived(struct device *dev, char *buf)
+static ssize_t show_tabletEventsReceived(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
@@ -1464,7 +1464,7 @@
  * support routines for the 'diagnostic' file. Note that this file
  * only displays current setting.
  */
-static ssize_t show_tabletDiagnosticMessage(struct device *dev, char *buf)
+static ssize_t show_tabletDiagnosticMessage(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	char *retMsg;
@@ -1506,7 +1506,7 @@
  * support routines for the 'stylus_upper' file. Note that this file
  * both displays current setting and allows for setting changing.
  */
-static ssize_t show_tabletStylusUpper(struct device *dev, char *buf)
+static ssize_t show_tabletStylusUpper(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	char *s;
@@ -1531,7 +1531,7 @@
 }
 
 static ssize_t
-store_tabletStylusUpper(struct device *dev, const char *buf, size_t count)
+store_tabletStylusUpper(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
@@ -1556,7 +1556,7 @@
  * support routines for the 'stylus_lower' file. Note that this file
  * both displays current setting and allows for setting changing.
  */
-static ssize_t show_tabletStylusLower(struct device *dev, char *buf)
+static ssize_t show_tabletStylusLower(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	char *s;
@@ -1581,7 +1581,7 @@
 }
 
 static ssize_t
-store_tabletStylusLower(struct device *dev, const char *buf, size_t count)
+store_tabletStylusLower(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
@@ -1606,7 +1606,7 @@
  * support routines for the 'mouse_left' file. Note that this file
  * both displays current setting and allows for setting changing.
  */
-static ssize_t show_tabletMouseLeft(struct device *dev, char *buf)
+static ssize_t show_tabletMouseLeft(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	char *s;
@@ -1635,7 +1635,7 @@
 }
 
 static ssize_t
-store_tabletMouseLeft(struct device *dev, const char *buf, size_t count)
+store_tabletMouseLeft(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
@@ -1660,7 +1660,7 @@
  * support routines for the 'mouse_middle' file. Note that this file
  * both displays current setting and allows for setting changing.
  */
-static ssize_t show_tabletMouseMiddle(struct device *dev, char *buf)
+static ssize_t show_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	char *s;
@@ -1689,7 +1689,7 @@
 }
 
 static ssize_t
-store_tabletMouseMiddle(struct device *dev, const char *buf, size_t count)
+store_tabletMouseMiddle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
@@ -1716,7 +1716,7 @@
  * support routines for the 'mouse_right' file. Note that this file
  * both displays current setting and allows for setting changing.
  */
-static ssize_t show_tabletMouseRight(struct device *dev, char *buf)
+static ssize_t show_tabletMouseRight(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 	char *s;
@@ -1745,7 +1745,7 @@
 }
 
 static ssize_t
-store_tabletMouseRight(struct device *dev, const char *buf, size_t count)
+store_tabletMouseRight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
@@ -1771,7 +1771,7 @@
  * support routines for the 'wheel' file. Note that this file
  * both displays current setting and allows for setting changing.
  */
-static ssize_t show_tabletWheel(struct device *dev, char *buf)
+static ssize_t show_tabletWheel(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
@@ -1787,7 +1787,7 @@
 }
 
 static ssize_t
-store_tabletWheel(struct device *dev, const char *buf, size_t count)
+store_tabletWheel(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
@@ -1805,7 +1805,7 @@
  * support routines for the 'execute' file. Note that this file
  * both displays current setting and allows for setting changing.
  */
-static ssize_t show_tabletExecute(struct device *dev, char *buf)
+static ssize_t show_tabletExecute(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
@@ -1820,7 +1820,7 @@
 }
 
 static ssize_t
-store_tabletExecute(struct device *dev, const char *buf, size_t count)
+store_tabletExecute(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
@@ -1846,7 +1846,7 @@
  * support routines for the 'odm_code' file. Note that this file
  * only displays current setting.
  */
-static ssize_t show_tabletODMCode(struct device *dev, char *buf)
+static ssize_t show_tabletODMCode(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
@@ -1862,7 +1862,7 @@
  * support routines for the 'model_code' file. Note that this file
  * only displays current setting.
  */
-static ssize_t show_tabletModelCode(struct device *dev, char *buf)
+static ssize_t show_tabletModelCode(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
@@ -1878,7 +1878,7 @@
  * support routines for the 'firmware_code' file. Note that this file
  * only displays current setting.
  */
-static ssize_t show_firmwareCode(struct device *dev, char *buf)
+static ssize_t show_firmwareCode(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct aiptek *aiptek = dev_get_drvdata(dev);
 
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
index d88e588..100b49bd 100644
--- a/drivers/usb/input/hid-core.c
+++ b/drivers/usb/input/hid-core.c
@@ -1774,7 +1774,7 @@
 			intf->altsetting->desc.bInterfaceNumber);
 
 	if (!(hid = usb_hid_configure(intf)))
-		return -EIO;
+		return -ENODEV;
 
 	hid_init_reports(hid);
 	hid_dump_device(hid);
@@ -1789,7 +1789,7 @@
 	if (!hid->claimed) {
 		printk ("HID device not claimed by input or hiddev\n");
 		hid_disconnect(intf);
-		return -EIO;
+		return -ENODEV;
 	}
 
 	printk(KERN_INFO);
diff --git a/drivers/usb/media/pwc/pwc-if.c b/drivers/usb/media/pwc/pwc-if.c
index 5429ff3..b77e65c 100644
--- a/drivers/usb/media/pwc/pwc-if.c
+++ b/drivers/usb/media/pwc/pwc-if.c
@@ -332,10 +332,6 @@
 #endif	 
 	;
 	 }
-	if (kbuf == NULL) {
-	   Err("Failed to allocate decompress table.\n");
-	   return -ENOMEM;
-	}
 	pdev->decompress_data = kbuf;
 	
 	/* Allocate image buffer; double buffer for mmap() */
diff --git a/drivers/usb/media/pwc/pwc-uncompress.c b/drivers/usb/media/pwc/pwc-uncompress.c
index bc3b163..ef4204e 100644
--- a/drivers/usb/media/pwc/pwc-uncompress.c
+++ b/drivers/usb/media/pwc/pwc-uncompress.c
@@ -118,9 +118,9 @@
 		   return -ENXIO; /* No such device or address: missing decompressor */
 		 }
 
+#if 0
 		switch (pdev->type)
 		 {
-#if 0		 
 		  case 675:
 		  case 680:
 		  case 690:
@@ -128,18 +128,17 @@
 		  case 730:
 		  case 740:
 		  case 750:
-		    pwc_dec23_decompress(&pdev->image, &pdev->view, &pdev->offset,
-				yuv, image,
-				flags,
+		    pwc_dec23_decompress(&pdev->image, &pdev->view,
+				&pdev->offset, yuv, image, flags,
 				pdev->decompress_data, pdev->vbandlength);
 		    break;
 		  case 645:
 		  case 646:
 		    /* TODO & FIXME */
-#endif		    
-		    return -ENXIO; /* No such device or address: missing decompressor */
+		    return -ENXIO; /* Missing decompressor */
 		    break;
 		 }
+#endif
 	}
 	return 0;
 }
diff --git a/drivers/usb/misc/cytherm.c b/drivers/usb/misc/cytherm.c
index 626e2b0..b33044d 100644
--- a/drivers/usb/misc/cytherm.c
+++ b/drivers/usb/misc/cytherm.c
@@ -85,7 +85,7 @@
 #define BRIGHTNESS 0x2c     /* RAM location for brightness value */
 #define BRIGHTNESS_SEM 0x2b /* RAM location for brightness semaphore */
 
-static ssize_t show_brightness(struct device *dev, char *buf)
+static ssize_t show_brightness(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct usb_interface *intf = to_usb_interface(dev);    
 	struct usb_cytherm *cytherm = usb_get_intfdata(intf);     
@@ -93,7 +93,7 @@
 	return sprintf(buf, "%i", cytherm->brightness);
 }
 
-static ssize_t set_brightness(struct device *dev, const char *buf, 
+static ssize_t set_brightness(struct device *dev, struct device_attribute *attr, const char *buf,
 			      size_t count)
 {
 	struct usb_interface *intf = to_usb_interface(dev);
@@ -138,7 +138,7 @@
 #define TEMP 0x33 /* RAM location for temperature */
 #define SIGN 0x34 /* RAM location for temperature sign */
 
-static ssize_t show_temp(struct device *dev, char *buf)
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf)
 {
 
 	struct usb_interface *intf = to_usb_interface(dev);
@@ -174,7 +174,7 @@
 }
 
 
-static ssize_t set_temp(struct device *dev, const char *buf, size_t count)
+static ssize_t set_temp(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	return count;
 }
@@ -184,7 +184,7 @@
 
 #define BUTTON 0x7a
 
-static ssize_t show_button(struct device *dev, char *buf)
+static ssize_t show_button(struct device *dev, struct device_attribute *attr, char *buf)
 {
 
 	struct usb_interface *intf = to_usb_interface(dev);
@@ -215,7 +215,7 @@
 }
 
 
-static ssize_t set_button(struct device *dev, const char *buf, size_t count)
+static ssize_t set_button(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	return count;
 }
@@ -223,7 +223,7 @@
 static DEVICE_ATTR(button, S_IRUGO, show_button, set_button);
 
 
-static ssize_t show_port0(struct device *dev, char *buf)
+static ssize_t show_port0(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct usb_interface *intf = to_usb_interface(dev);
 	struct usb_cytherm *cytherm = usb_get_intfdata(intf);
@@ -249,7 +249,7 @@
 }
 
 
-static ssize_t set_port0(struct device *dev, const char *buf, size_t count)
+static ssize_t set_port0(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct usb_interface *intf = to_usb_interface(dev);
 	struct usb_cytherm *cytherm = usb_get_intfdata(intf);
@@ -283,7 +283,7 @@
 
 static DEVICE_ATTR(port0, S_IRUGO | S_IWUSR | S_IWGRP, show_port0, set_port0);
 
-static ssize_t show_port1(struct device *dev, char *buf)
+static ssize_t show_port1(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct usb_interface *intf = to_usb_interface(dev);
 	struct usb_cytherm *cytherm = usb_get_intfdata(intf);
@@ -309,7 +309,7 @@
 }
 
 
-static ssize_t set_port1(struct device *dev, const char *buf, size_t count)
+static ssize_t set_port1(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	struct usb_interface *intf = to_usb_interface(dev);
 	struct usb_cytherm *cytherm = usb_get_intfdata(intf);
diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c
index ddbf8e9..067a814 100644
--- a/drivers/usb/misc/phidgetkit.c
+++ b/drivers/usb/misc/phidgetkit.c
@@ -173,7 +173,7 @@
 }
 
 #define set_lcd_line(number)	\
-static ssize_t lcd_line_##number(struct device *dev, const char *buf, size_t count)	\
+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);			\
@@ -184,7 +184,7 @@
 set_lcd_line(1);
 set_lcd_line(2);
 
-static ssize_t set_backlight(struct device *dev, const char *buf, size_t count)
+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);
@@ -232,7 +232,7 @@
 	}
 }
 
-static ssize_t enable_lcd_files(struct device *dev, const char *buf, size_t count)
+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);
@@ -307,7 +307,7 @@
 }
 
 #define show_set_output(value)		\
-static ssize_t set_output##value(struct device *dev, 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);		\
@@ -324,7 +324,7 @@
 	return retval ? retval : count;					\
 }									\
 									\
-static ssize_t show_output##value(struct device *dev, char *buf)	\
+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);	\
@@ -343,7 +343,7 @@
 show_set_output(8);	/* should be MAX_INTERFACES - 1 */
 
 #define show_input(value)	\
-static ssize_t show_input##value(struct device *dev, char *buf)	\
+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);	\
@@ -362,7 +362,7 @@
 show_input(8);		/* should be MAX_INTERFACES - 1 */
 
 #define show_sensor(value)	\
-static ssize_t show_sensor##value(struct device *dev, char *buf)	\
+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);	\
diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c
index 4bd2915..b84eda6 100644
--- a/drivers/usb/misc/phidgetservo.c
+++ b/drivers/usb/misc/phidgetservo.c
@@ -207,7 +207,7 @@
 }
 
 #define show_set(value)	\
-static ssize_t set_servo##value (struct device *dev,			\
+static ssize_t set_servo##value (struct device *dev, struct device_attribute *attr,			\
 					const char *buf, size_t count)	\
 {									\
 	int degrees, minutes, retval;					\
@@ -233,7 +233,7 @@
 	return retval < 0 ? retval : count;				\
 }									\
 									\
-static ssize_t show_servo##value (struct device *dev, char *buf) 	\
+static ssize_t show_servo##value (struct device *dev, struct device_attribute *attr, char *buf) 	\
 {									\
 	struct usb_interface *intf = to_usb_interface (dev);		\
 	struct phidget_servo *servo = usb_get_intfdata (intf);		\
diff --git a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c
index ee329d5..f6ba4c7 100644
--- a/drivers/usb/misc/usbled.c
+++ b/drivers/usb/misc/usbled.c
@@ -81,14 +81,14 @@
 }
 
 #define show_set(value)	\
-static ssize_t show_##value(struct device *dev, char *buf)		\
+static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf)		\
 {									\
 	struct usb_interface *intf = to_usb_interface(dev);		\
 	struct usb_led *led = usb_get_intfdata(intf);			\
 									\
 	return sprintf(buf, "%d\n", led->value);			\
 }									\
-static ssize_t set_##value(struct device *dev, const char *buf, size_t count)	\
+static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)	\
 {									\
 	struct usb_interface *intf = to_usb_interface(dev);		\
 	struct usb_led *led = usb_get_intfdata(intf);			\
diff --git a/drivers/usb/mon/Kconfig b/drivers/usb/mon/Kconfig
index 4e6152a..777642e 100644
--- a/drivers/usb/mon/Kconfig
+++ b/drivers/usb/mon/Kconfig
@@ -2,13 +2,9 @@
 # USB Monitor configuration
 #
 
-# In normal life, it makes little sense to have usbmon as a module, and in fact
-# it is harmful, because there is no way to autoload the module.
-# The 'm' option is allowed for hackers who debug the usbmon itself,
-# and for those who have usbcore as a module.
 config USB_MON
-	tristate "USB Monitor"
-	depends on USB
+	bool "USB Monitor"
+	depends on USB!=n
 	default y
 	help
 	  If you say Y here, a component which captures the USB traffic
@@ -17,6 +13,5 @@
 	  Harding's USBMon.
 
 	  This is somewhat experimental at this time, but it should be safe,
-	  as long as you aren't building this as a module and then removing it.
-
-	  If unsure, say Y. Do not say M.
+	  as long as you aren't using modular USB and try to remove this
+	  module.
diff --git a/drivers/usb/mon/Makefile b/drivers/usb/mon/Makefile
index 3cff8d4..f18d10c 100644
--- a/drivers/usb/mon/Makefile
+++ b/drivers/usb/mon/Makefile
@@ -4,4 +4,4 @@
 
 usbmon-objs	:= mon_main.o mon_stat.o mon_text.o
 
-obj-$(CONFIG_USB_MON)	+= usbmon.o
+obj-$(CONFIG_USB)	+= usbmon.o
diff --git a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
index a9a7cf4..fd6ff4c 100644
--- a/drivers/usb/net/kaweth.c
+++ b/drivers/usb/net/kaweth.c
@@ -520,7 +520,7 @@
 
 	/* we check the link state to report changes */
 	if (kaweth->linkstate != (act_state = ( kaweth->intbuffer[STATE_OFFSET] | STATE_MASK) >> STATE_SHIFT)) {
-		if (!act_state)
+		if (act_state)
 			netif_carrier_on(kaweth->net);
 		else
 			netif_carrier_off(kaweth->net);
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 051c3a7..d882fa3 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -264,7 +264,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.4.1"
+#define DRIVER_VERSION "v1.4.2"
 #define DRIVER_AUTHOR "Greg Kroah-Hartman <greg@kroah.com>, Bill Ryder <bryder@sgi.com>, Kuba Ober <kuba@mareimbrium.org>"
 #define DRIVER_DESC "USB FTDI Serial Converters Driver"
 
@@ -687,6 +687,8 @@
  	char prev_status, diff_status;        /* Used for TIOCMIWAIT */
 	__u8 rx_flags;		/* receive state flags (throttling) */
 	spinlock_t rx_lock;	/* spinlock for receive state */
+	struct work_struct rx_work;
+	int rx_processed;
 
 	__u16 interface;	/* FT2232C port interface (0 for FT232/245) */
 
@@ -717,7 +719,7 @@
 static int  ftdi_chars_in_buffer	(struct usb_serial_port *port);
 static void ftdi_write_bulk_callback	(struct urb *urb, struct pt_regs *regs);
 static void ftdi_read_bulk_callback	(struct urb *urb, struct pt_regs *regs);
-static void ftdi_process_read		(struct usb_serial_port *port);
+static void ftdi_process_read		(void *param);
 static void ftdi_set_termios		(struct usb_serial_port *port, struct termios * old);
 static int  ftdi_tiocmget               (struct usb_serial_port *port, struct file *file);
 static int  ftdi_tiocmset		(struct usb_serial_port *port, struct file * file, unsigned int set, unsigned int clear);
@@ -1216,7 +1218,7 @@
  * ***************************************************************************
  */
 
-static ssize_t show_latency_timer(struct device *dev, char *buf)
+static ssize_t show_latency_timer(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct usb_serial_port *port = to_usb_serial_port(dev);
 	struct ftdi_private *priv = usb_get_serial_port_data(port);
@@ -1243,7 +1245,7 @@
 }
 
 /* Write a new value of the latency timer, in units of milliseconds. */
-static ssize_t store_latency_timer(struct device *dev, const char *valbuf,
+static ssize_t store_latency_timer(struct device *dev, struct device_attribute *attr, const char *valbuf,
 				   size_t count)
 {
 	struct usb_serial_port *port = to_usb_serial_port(dev);
@@ -1274,7 +1276,7 @@
 
 /* Write an event character directly to the FTDI register.  The ASCII
    value is in the low 8 bits, with the enable bit in the 9th bit. */
-static ssize_t store_event_char(struct device *dev, const char *valbuf,
+static ssize_t store_event_char(struct device *dev, struct device_attribute *attr, const char *valbuf,
 				size_t count)
 {
 	struct usb_serial_port *port = to_usb_serial_port(dev);
@@ -1387,6 +1389,8 @@
 		port->read_urb->transfer_buffer_length = BUFSZ;
 	}
 
+	INIT_WORK(&priv->rx_work, ftdi_process_read, port);
+
 	/* Free port's existing write urb and transfer buffer. */
 	if (port->write_urb) {
 		usb_free_urb (port->write_urb);
@@ -1617,6 +1621,7 @@
 	spin_unlock_irqrestore(&priv->rx_lock, flags);
 
 	/* Start reading from the device */
+	priv->rx_processed = 0;
 	usb_fill_bulk_urb(port->read_urb, dev,
 		      usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress),
 		      port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length,
@@ -1667,6 +1672,10 @@
 			err("Error from RTS LOW urb");
 		}
 	} /* Note change no line if hupcl is off */
+
+	/* cancel any scheduled reading */
+	cancel_delayed_work(&priv->rx_work);
+	flush_scheduled_work();
 	
 	/* shutdown our bulk read */
 	if (port->read_urb)
@@ -1862,23 +1871,14 @@
 		return;
 	}
 
-	/* If throttled, delay receive processing until unthrottled. */
-	spin_lock(&priv->rx_lock);
-	if (priv->rx_flags & THROTTLED) {
-		dbg("Deferring read urb processing until unthrottled");
-		priv->rx_flags |= ACTUALLY_THROTTLED;
-		spin_unlock(&priv->rx_lock);
-		return;
-	}
-	spin_unlock(&priv->rx_lock);
-
 	ftdi_process_read(port);
 
 } /* ftdi_read_bulk_callback */
 
 
-static void ftdi_process_read (struct usb_serial_port *port)
+static void ftdi_process_read (void *param)
 { /* ftdi_process_read */
+	struct usb_serial_port *port = (struct usb_serial_port*)param;
 	struct urb *urb;
 	struct tty_struct *tty;
 	struct ftdi_private *priv;
@@ -1889,6 +1889,7 @@
 	int result;
 	int need_flip;
 	int packet_offset;
+	unsigned long flags;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -1915,12 +1916,18 @@
 
 	data = urb->transfer_buffer;
 
-        /* The first two bytes of every read packet are status */
-	if (urb->actual_length > 2) {
-		usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+	if (priv->rx_processed) {
+		dbg("%s - already processed: %d bytes, %d remain", __FUNCTION__,
+				priv->rx_processed,
+				urb->actual_length - priv->rx_processed);
 	} else {
-                dbg("Status only: %03oo %03oo",data[0],data[1]);
-        }
+		/* The first two bytes of every read packet are status */
+		if (urb->actual_length > 2) {
+			usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
+		} else {
+			dbg("Status only: %03oo %03oo",data[0],data[1]);
+		}
+	}
 
 
 	/* TO DO -- check for hung up line and handle appropriately: */
@@ -1929,8 +1936,12 @@
 	/* if CD is dropped and the line is not CLOCAL then we should hangup */
 
 	need_flip = 0;
-	for (packet_offset=0; packet_offset < urb->actual_length; packet_offset += PKTSZ) {
+	for (packet_offset = priv->rx_processed; packet_offset < urb->actual_length; packet_offset += PKTSZ) {
+		int length;
+
 		/* Compare new line status to the old one, signal if different */
+		/* N.B. packet may be processed more than once, but differences
+		 * are only processed once.  */
 		if (priv != NULL) {
 			char new_status = data[packet_offset+0] & FTDI_STATUS_B0_MASK;
 			if (new_status != priv->prev_status) {
@@ -1940,6 +1951,35 @@
 			}
 		}
 
+		length = min(PKTSZ, urb->actual_length-packet_offset)-2;
+		if (length < 0) {
+			err("%s - bad packet length: %d", __FUNCTION__, length+2);
+			length = 0;
+		}
+
+		/* have to make sure we don't overflow the buffer
+		   with tty_insert_flip_char's */
+		if (tty->flip.count+length > TTY_FLIPBUF_SIZE) {
+			tty_flip_buffer_push(tty);
+			need_flip = 0;
+
+			if (tty->flip.count != 0) {
+				/* flip didn't work, this happens when ftdi_process_read() is
+				 * called from ftdi_unthrottle, because TTY_DONT_FLIP is set */
+				dbg("%s - flip buffer push failed", __FUNCTION__);
+				break;
+			}
+		}
+		if (priv->rx_flags & THROTTLED) {
+			dbg("%s - throttled", __FUNCTION__);
+			break;
+		}
+		if (tty->ldisc.receive_room(tty)-tty->flip.count < length) {
+			/* break out & wait for throttling/unthrottling to happen */
+			dbg("%s - receive room low", __FUNCTION__);
+			break;
+		}
+
 		/* Handle errors and break */
 		error_flag = TTY_NORMAL;
 		/* Although the device uses a bitmask and hence can have multiple */
@@ -1962,13 +2002,8 @@
 			error_flag = TTY_FRAME;
 			dbg("FRAMING error");
 		}
-		if (urb->actual_length > packet_offset + 2) {
-			for (i = 2; (i < PKTSZ) && ((i+packet_offset) < urb->actual_length); ++i) {
-				/* have to make sure we don't overflow the buffer
-				  with tty_insert_flip_char's */
-				if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
-					tty_flip_buffer_push(tty);
-				}
+		if (length > 0) {
+			for (i = 2; i < length+2; i++) {
 				/* Note that the error flag is duplicated for 
 				   every character received since we don't know
 				   which character it applied to */
@@ -2005,6 +2040,35 @@
 		tty_flip_buffer_push(tty);
 	}
 
+	if (packet_offset < urb->actual_length) {
+		/* not completely processed - record progress */
+		priv->rx_processed = packet_offset;
+		dbg("%s - incomplete, %d bytes processed, %d remain",
+				__FUNCTION__, packet_offset,
+				urb->actual_length - packet_offset);
+		/* check if we were throttled while processing */
+		spin_lock_irqsave(&priv->rx_lock, flags);
+		if (priv->rx_flags & THROTTLED) {
+			priv->rx_flags |= ACTUALLY_THROTTLED;
+			spin_unlock_irqrestore(&priv->rx_lock, flags);
+			dbg("%s - deferring remainder until unthrottled",
+					__FUNCTION__);
+			return;
+		}
+		spin_unlock_irqrestore(&priv->rx_lock, flags);
+		/* if the port is closed stop trying to read */
+		if (port->open_count > 0){
+			/* delay processing of remainder */
+			schedule_delayed_work(&priv->rx_work, 1);
+		} else {
+			dbg("%s - port is closed", __FUNCTION__);
+		}
+		return;
+	}
+
+	/* urb is completely processed */
+	priv->rx_processed = 0;
+
 	/* if the port is closed stop trying to read */
 	if (port->open_count > 0){
 		/* Continue trying to always read  */
@@ -2444,7 +2508,7 @@
 	spin_unlock_irqrestore(&priv->rx_lock, flags);
 
 	if (actually_throttled)
-		ftdi_process_read(port);
+		schedule_work(&priv->rx_work);
 }
 
 static int __init ftdi_init (void)
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index 22e48a2..e43eddc 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -233,13 +233,11 @@
 		set_bit(US_FLIDX_ABORTING, &us->flags);
 		usb_stor_stop_transport(us);
 	}
-	scsi_unlock(us_to_host(us));
 
 	/* Wait for the aborted command to finish */
 	wait_for_completion(&us->notify);
 
 	/* Reacquire the lock and allow USB transfers to resume */
-	scsi_lock(us_to_host(us));
 	clear_bit(US_FLIDX_ABORTING, &us->flags);
 	clear_bit(US_FLIDX_TIMED_OUT, &us->flags);
 	return SUCCESS;
@@ -255,8 +253,6 @@
 
 	US_DEBUGP("%s called\n", __FUNCTION__);
 
-	scsi_unlock(us_to_host(us));
-
 	/* lock the device pointers and do the reset */
 	down(&(us->dev_semaphore));
 	if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) {
@@ -266,8 +262,6 @@
 		result = us->transport_reset(us);
 	up(&(us->dev_semaphore));
 
-	/* lock the host for the return */
-	scsi_lock(us_to_host(us));
 	return result;
 }
 
@@ -282,8 +276,6 @@
 
 	US_DEBUGP("%s called\n", __FUNCTION__);
 
-	scsi_unlock(us_to_host(us));
-
 	/* The USB subsystem doesn't handle synchronisation between
 	 * a device's several drivers. Therefore we reset only devices
 	 * with just one interface, which we of course own. */
@@ -310,7 +302,6 @@
 	up(&(us->dev_semaphore));
 
 	/* lock the host for the return */
-	scsi_lock(us_to_host(us));
 	return result < 0 ? FAILED : SUCCESS;
 }
 
@@ -407,7 +398,7 @@
  ***********************************************************************/
 
 /* Output routine for the sysfs max_sectors file */
-static ssize_t show_max_sectors(struct device *dev, char *buf)
+static ssize_t show_max_sectors(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct scsi_device *sdev = to_scsi_device(dev);
 
@@ -415,7 +406,7 @@
 }
 
 /* Input routine for the sysfs max_sectors file */
-static ssize_t store_max_sectors(struct device *dev, const char *buf,
+static ssize_t store_max_sectors(struct device *dev, struct device_attribute *attr, const char *buf,
 		size_t count)
 {
 	struct scsi_device *sdev = to_scsi_device(dev);
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 35c1ca6..77e7fc2 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -847,10 +847,8 @@
 		wait_event_interruptible_timeout(us->delay_wait,
 				test_bit(US_FLIDX_DISCONNECTING, &us->flags),
 				delay_use * HZ);
-		if (current->flags & PF_FREEZE) {
-			refrigerator(PF_FREEZE);
+		if (try_to_freeze())
 			goto retry;
-		}
 	}
 
 	/* If the device is still connected, perform the scanning */
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 6be8fbe..04d3120 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -322,6 +322,22 @@
 	  This is the frame buffer device driver for the Amiga FrameMaster
 	  card from BSC (exhibited 1992 but not shipped as a CBM product).
 
+config FB_ARC
+	tristate "Arc Monochrome LCD board support"
+	depends on FB && X86
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
+	help
+	  This enables support for the Arc Monochrome LCD board. The board
+	  is based on the KS-108 lcd controller and is typically a matrix
+	  of 2*n chips. This driver was tested with a 128x64 panel. This
+	  driver supports it for use with x86 SBCs through a 16 bit GPIO
+	  interface (8 bit data, 8 bit control). If you anticpate using
+	  this driver, say Y or M; otherwise say N. You must specify the
+	  GPIO IO address to be used for setting control and data.
+
 config FB_ATARI
 	bool "Atari native chipset support"
 	depends on (FB = y) && ATARI && BROKEN
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index bd8dc0f..b018df4 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -21,6 +21,7 @@
 # Hardware specific drivers go first
 obj-$(CONFIG_FB_RETINAZ3)         += retz3fb.o
 obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p.o
+obj-$(CONFIG_FB_ARC)              += arcfb.o
 obj-$(CONFIG_FB_CLPS711X)         += clps711xfb.o
 obj-$(CONFIG_FB_CYBER)            += cyberfb.o
 obj-$(CONFIG_FB_CYBER2000)        += cyber2000fb.o
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
new file mode 100644
index 0000000..d28457e
--- /dev/null
+++ b/drivers/video/arcfb.c
@@ -0,0 +1,684 @@
+/*
+ * linux/drivers/video/arcfb.c -- FB driver for Arc monochrome LCD board
+ *
+ * Copyright (C) 2005, Jaya Kumar <jayalk@intworks.biz>
+ * http://www.intworks.biz/arclcd
+ *
+ * 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.
+ *
+ * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
+ *
+ * This driver was written to be used with the Arc LCD board. Arc uses a
+ * set of KS108 chips that control individual 64x64 LCD matrices. The board
+ * can be paneled in a variety of setups such as 2x1=128x64, 4x4=256x256 and
+ * so on. The interface between the board and the host is TTL based GPIO. The
+ * GPIO requirements are 8 writable data lines and 4+n lines for control. On a
+ * GPIO-less system, the board can be tested by connecting the respective sigs
+ * up to a parallel port connector. The driver requires the IO addresses for
+ * data and control GPIO at load time. It is unable to probe for the
+ * existence of the LCD so it must be told at load time whether it should
+ * be enabled or not.
+ *
+ * Todo:
+ * - testing with 4x4
+ * - testing with interrupt hw
+ *
+ * General notes:
+ * - User must set tuhold. It's in microseconds. According to the 108 spec,
+ *   the hold time is supposed to be at least 1 microsecond.
+ * - User must set num_cols=x num_rows=y, eg: x=2 means 128
+ * - User must set arcfb_enable=1 to enable it
+ * - User must set dio_addr=0xIOADDR cio_addr=0xIOADDR
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/arcfb.h>
+
+#include <asm/uaccess.h>
+
+#define floor8(a) (a&(~0x07))
+#define floorXres(a,xres) (a&(~(xres - 1)))
+#define iceil8(a) (((int)((a+7)/8))*8)
+#define ceil64(a) (a|0x3F)
+#define ceilXres(a,xres) (a|(xres - 1))
+
+/* ks108 chipset specific defines and code */
+
+#define KS_SET_DPY_START_LINE 	0xC0
+#define KS_SET_PAGE_NUM 	0xB8
+#define KS_SET_X 		0x40
+#define KS_CEHI 		0x01
+#define KS_CELO 		0x00
+#define KS_SEL_CMD 		0x08
+#define KS_SEL_DATA 		0x00
+#define KS_DPY_ON 		0x3F
+#define KS_DPY_OFF 		0x3E
+#define KS_INTACK 		0x40
+#define KS_CLRINT		0x02
+
+struct arcfb_par {
+	unsigned long dio_addr;
+	unsigned long cio_addr;
+	unsigned long c2io_addr;
+	atomic_t ref_count;
+	unsigned char cslut[9];
+	struct fb_info *info;
+	unsigned int irq;
+	spinlock_t lock;
+};
+
+static struct fb_fix_screeninfo arcfb_fix __initdata = {
+	.id =		"arcfb",
+	.type =		FB_TYPE_PACKED_PIXELS,
+	.visual =	FB_VISUAL_MONO01,
+	.xpanstep =	0,
+	.ypanstep =	1,
+	.ywrapstep =	0,
+	.accel =	FB_ACCEL_NONE,
+};
+
+static struct fb_var_screeninfo arcfb_var __initdata = {
+	.xres		= 128,
+	.yres		= 64,
+	.xres_virtual	= 128,
+	.yres_virtual	= 64,
+	.bits_per_pixel	= 1,
+	.nonstd		= 1,
+};
+
+static unsigned long num_cols;
+static unsigned long num_rows;
+static unsigned long dio_addr;
+static unsigned long cio_addr;
+static unsigned long c2io_addr;
+static unsigned long splashval;
+static unsigned long tuhold;
+static unsigned int nosplash;
+static unsigned int arcfb_enable;
+static unsigned int irq;
+
+static DECLARE_WAIT_QUEUE_HEAD(arcfb_waitq);
+
+static void ks108_writeb_ctl(struct arcfb_par *par,
+				unsigned int chipindex, unsigned char value)
+{
+	unsigned char chipselval = par->cslut[chipindex];
+
+	outb(chipselval|KS_CEHI|KS_SEL_CMD, par->cio_addr);
+	outb(value, par->dio_addr);
+	udelay(tuhold);
+	outb(chipselval|KS_CELO|KS_SEL_CMD, par->cio_addr);
+}
+
+static void ks108_writeb_mainctl(struct arcfb_par *par, unsigned char value)
+{
+
+	outb(value, par->cio_addr);
+	udelay(tuhold);
+}
+
+static unsigned char ks108_readb_ctl2(struct arcfb_par *par)
+{
+	return inb(par->c2io_addr);
+}
+
+static void ks108_writeb_data(struct arcfb_par *par,
+				unsigned int chipindex, unsigned char value)
+{
+	unsigned char chipselval = par->cslut[chipindex];
+
+	outb(chipselval|KS_CEHI|KS_SEL_DATA, par->cio_addr);
+	outb(value, par->dio_addr);
+	udelay(tuhold);
+	outb(chipselval|KS_CELO|KS_SEL_DATA, par->cio_addr);
+}
+
+static void ks108_set_start_line(struct arcfb_par *par,
+				unsigned int chipindex, unsigned char y)
+{
+	ks108_writeb_ctl(par, chipindex, KS_SET_DPY_START_LINE|y);
+}
+
+static void ks108_set_yaddr(struct arcfb_par *par,
+				unsigned int chipindex, unsigned char y)
+{
+	ks108_writeb_ctl(par, chipindex, KS_SET_PAGE_NUM|y);
+}
+
+static void ks108_set_xaddr(struct arcfb_par *par,
+				unsigned int chipindex, unsigned char x)
+{
+	ks108_writeb_ctl(par, chipindex, KS_SET_X|x);
+}
+
+static void ks108_clear_lcd(struct arcfb_par *par, unsigned int chipindex)
+{
+	int i,j;
+
+	for (i = 0; i <= 8; i++) {
+		ks108_set_yaddr(par, chipindex, i);
+		ks108_set_xaddr(par, chipindex, 0);
+		for (j = 0; j < 64; j++) {
+			ks108_writeb_data(par, chipindex,
+				(unsigned char) splashval);
+		}
+	}
+}
+
+/* main arcfb functions */
+
+static int arcfb_open(struct fb_info *info, int user)
+{
+	struct arcfb_par *par = info->par;
+
+	atomic_inc(&par->ref_count);
+	return 0;
+}
+
+static int arcfb_release(struct fb_info *info, int user)
+{
+	struct arcfb_par *par = info->par;
+	int count = atomic_read(&par->ref_count);
+
+	if (!count)
+		return -EINVAL;
+	atomic_dec(&par->ref_count);
+	return 0;
+}
+
+static int arcfb_pan_display(struct fb_var_screeninfo *var,
+				struct fb_info *info)
+{
+	int i;
+	struct arcfb_par *par = info->par;
+
+	if ((var->vmode & FB_VMODE_YWRAP) && (var->yoffset < 64)
+		&& (info->var.yres <= 64)) {
+		for (i = 0; i < num_cols; i++) {
+			ks108_set_start_line(par, i, var->yoffset);
+		}
+		info->var.yoffset = var->yoffset;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static irqreturn_t arcfb_interrupt(int vec, void *dev_instance,
+		struct pt_regs *regs)
+{
+	struct fb_info *info = dev_instance;
+	unsigned char ctl2status;
+	struct arcfb_par *par = info->par;
+
+	ctl2status = ks108_readb_ctl2(par);
+
+	if (!(ctl2status & KS_INTACK)) /* not arc generated interrupt */
+		return IRQ_NONE;
+
+	ks108_writeb_mainctl(par, KS_CLRINT);
+
+	spin_lock(&par->lock);
+        if (waitqueue_active(&arcfb_waitq)) {
+                wake_up(&arcfb_waitq);
+        }
+	spin_unlock(&par->lock);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * here we handle a specific page on the lcd. the complexity comes from
+ * the fact that the fb is laidout in 8xX vertical columns. we extract
+ * each write of 8 vertical pixels. then we shift out as we move along
+ * X. That's what rightshift does. bitmask selects the desired input bit.
+ */
+static void arcfb_lcd_update_page(struct arcfb_par *par, unsigned int upper,
+		unsigned int left, unsigned int right, unsigned int distance)
+{
+	unsigned char *src;
+	unsigned int xindex, yindex, chipindex, linesize;
+	int i, count;
+	unsigned char val;
+	unsigned char bitmask, rightshift;
+
+	xindex = left >> 6;
+	yindex = upper >> 6;
+	chipindex = (xindex + (yindex*num_cols));
+
+	ks108_set_yaddr(par, chipindex, upper/8);
+
+	linesize = par->info->var.xres/8;
+	src = par->info->screen_base + (left/8) + (upper * linesize);
+	ks108_set_xaddr(par, chipindex, left);
+
+	bitmask=1;
+	rightshift=0;
+	while (left <= right) {
+		val = 0;
+		for (i = 0; i < 8; i++) {
+			if ( i > rightshift) {
+				val |= (*(src + (i*linesize)) & bitmask)
+						<< (i - rightshift);
+			} else {
+				val |= (*(src + (i*linesize)) & bitmask)
+						 >> (rightshift - i);
+			}
+		}
+		ks108_writeb_data(par, chipindex, val);
+		left++;
+		count++;
+		if (bitmask == 0x80) {
+			bitmask = 1;
+			src++;
+			rightshift=0;
+		} else {
+			bitmask <<= 1;
+			rightshift++;
+		}
+	}
+}
+
+/*
+ * here we handle the entire vertical page of the update. we write across
+ * lcd chips. update_page uses the upper/left values to decide which
+ * chip to select for the right. upper is needed for setting the page
+ * desired for the write.
+ */
+static void arcfb_lcd_update_vert(struct arcfb_par *par, unsigned int top,
+		unsigned int bottom, unsigned int left, unsigned int right)
+{
+	unsigned int distance, upper, lower;
+
+	distance = (bottom - top) + 1;
+	upper = top;
+	lower = top + 7;
+
+	while (distance > 0) {
+		distance -= 8;
+		arcfb_lcd_update_page(par, upper, left, right, 8);
+		upper = lower + 1;
+		lower = upper + 7;
+	}
+}
+
+/*
+ * here we handle horizontal blocks for the update. update_vert will
+ * handle spaning multiple pages. we break out each horizontal
+ * block in to individual blocks no taller than 64 pixels.
+ */
+static void arcfb_lcd_update_horiz(struct arcfb_par *par, unsigned int left,
+			unsigned int right, unsigned int top, unsigned int h)
+{
+	unsigned int distance, upper, lower;
+
+	distance = h;
+	upper = floor8(top);
+	lower = min(upper + distance - 1, ceil64(upper));
+
+	while (distance > 0) {
+		distance -= ((lower - upper) + 1 );
+		arcfb_lcd_update_vert(par, upper, lower, left, right);
+		upper = lower + 1;
+		lower = min(upper + distance - 1, ceil64(upper));
+	}
+}
+
+/*
+ * here we start the process of spliting out the fb update into
+ * individual blocks of pixels. we end up spliting into 64x64 blocks
+ * and finally down to 64x8 pages.
+ */
+static void arcfb_lcd_update(struct arcfb_par *par, unsigned int dx,
+			unsigned int dy, unsigned int w, unsigned int h)
+{
+	unsigned int left, right, distance, y;
+
+	/* align the request first */
+	y = floor8(dy);
+	h += dy - y;
+	h = iceil8(h);
+
+	distance = w;
+	left = dx;
+	right = min(left + w - 1, ceil64(left));
+
+	while (distance > 0) {
+		arcfb_lcd_update_horiz(par, left, right, y, h);
+		distance -= ((right - left) + 1);
+		left = right + 1;
+		right = min(left + distance - 1, ceil64(left));
+	}
+}
+
+void arcfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct arcfb_par *par = info->par;
+
+	cfb_fillrect(info, rect);
+
+	/* update the physical lcd */
+	arcfb_lcd_update(par, rect->dx, rect->dy, rect->width, rect->height);
+}
+
+void arcfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+	struct arcfb_par *par = info->par;
+
+	cfb_copyarea(info, area);
+
+	/* update the physical lcd */
+	arcfb_lcd_update(par, area->dx, area->dy, area->width, area->height);
+}
+
+void arcfb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct arcfb_par *par = info->par;
+
+	cfb_imageblit(info, image);
+
+	/* update the physical lcd */
+	arcfb_lcd_update(par, image->dx, image->dy, image->width,
+				image->height);
+}
+
+static int arcfb_ioctl(struct inode *inode, struct file *file,
+			  unsigned int cmd, unsigned long arg,
+			  struct fb_info *info)
+{
+	void __user *argp = (void __user *)arg;
+	struct arcfb_par *par = info->par;
+	unsigned long flags;
+
+	switch (cmd) {
+		case FBIO_WAITEVENT:
+		{
+			DEFINE_WAIT(wait);
+			/* illegal to wait on arc if no irq will occur */
+			if (!par->irq)
+				return -EINVAL;
+
+			/* wait until the Arc has generated an interrupt
+			 * which will wake us up */
+			spin_lock_irqsave(&par->lock, flags);
+			prepare_to_wait(&arcfb_waitq, &wait,
+					TASK_INTERRUPTIBLE);
+			spin_unlock_irqrestore(&par->lock, flags);
+			schedule();
+			finish_wait(&arcfb_waitq, &wait);
+		}
+		case FBIO_GETCONTROL2:
+		{
+			unsigned char ctl2;
+
+			ctl2 = ks108_readb_ctl2(info->par);
+			if (copy_to_user(argp, &ctl2, sizeof(ctl2)))
+				return -EFAULT;
+			return 0;
+		}
+		default:
+			return -EINVAL;
+	}
+}
+
+/*
+ * this is the access path from userspace. they can seek and write to
+ * the fb. it's inefficient for them to do anything less than 64*8
+ * writes since we update the lcd in each write() anyway.
+ */
+static ssize_t arcfb_write(struct file *file, const char *buf, size_t count,
+				loff_t *ppos)
+{
+	/* modded from epson 1355 */
+
+	struct inode *inode;
+	int fbidx;
+	struct fb_info *info;
+	unsigned long p;
+	int err=-EINVAL;
+	unsigned int fbmemlength,x,y,w,h, bitppos, startpos, endpos, bitcount;
+	struct arcfb_par *par;
+	unsigned int xres;
+
+	p = *ppos;
+	inode = file->f_dentry->d_inode;
+	fbidx = iminor(inode);
+	info = registered_fb[fbidx];
+	par = info->par;
+
+	if (!info || !info->screen_base)
+		return -ENODEV;
+
+	xres = info->var.xres;
+	fbmemlength = (xres * info->var.yres)/8;
+
+	if (p > fbmemlength)
+		return -ENOSPC;
+
+	err = 0;
+	if ((count + p) > fbmemlength) {
+		count = fbmemlength - p;
+		err = -ENOSPC;
+	}
+
+	if (count) {
+		char *base_addr;
+
+		base_addr = info->screen_base;
+		count -= copy_from_user(base_addr + p, buf, count);
+		*ppos += count;
+		err = -EFAULT;
+	}
+
+
+	bitppos = p*8;
+	startpos = floorXres(bitppos, xres);
+	endpos = ceilXres((bitppos + (count*8)), xres);
+	bitcount = endpos - startpos;
+
+	x = startpos % xres;
+	y = startpos / xres;
+	w = xres;
+	h = bitcount / xres;
+	arcfb_lcd_update(par, x, y, w, h);
+
+	if (count)
+		return count;
+	return err;
+}
+
+static void arcfb_platform_release(struct device *device)
+{
+}
+
+static struct fb_ops arcfb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_open	= arcfb_open,
+	.fb_write	= arcfb_write,
+	.fb_release	= arcfb_release,
+	.fb_pan_display	= arcfb_pan_display,
+	.fb_fillrect	= arcfb_fillrect,
+	.fb_copyarea	= arcfb_copyarea,
+	.fb_imageblit	= arcfb_imageblit,
+	.fb_cursor	= soft_cursor,
+	.fb_ioctl 	= arcfb_ioctl,
+};
+
+static int __init arcfb_probe(struct device *device)
+{
+	struct platform_device *dev = to_platform_device(device);
+	struct fb_info *info;
+	int retval = -ENOMEM;
+	int videomemorysize;
+	unsigned char *videomemory;
+	struct arcfb_par *par;
+	int i;
+
+	videomemorysize = (((64*64)*num_cols)*num_rows)/8;
+
+	/* We need a flat backing store for the Arc's
+	   less-flat actual paged framebuffer */
+	if (!(videomemory = vmalloc(videomemorysize)))
+		return retval;
+
+	memset(videomemory, 0, videomemorysize);
+
+	info = framebuffer_alloc(sizeof(struct arcfb_par), &dev->dev);
+	if (!info)
+		goto err;
+
+	info->screen_base = (char __iomem *)videomemory;
+	info->fbops = &arcfb_ops;
+
+	info->var = arcfb_var;
+	info->fix = arcfb_fix;
+	par = info->par;
+	par->info = info;
+
+	if (!dio_addr || !cio_addr || !c2io_addr) {
+		printk(KERN_WARNING "no IO addresses supplied\n");
+		goto err1;
+	}
+	par->dio_addr = dio_addr;
+	par->cio_addr = cio_addr;
+	par->c2io_addr = c2io_addr;
+	par->cslut[0] = 0x00;
+	par->cslut[1] = 0x06;
+	info->flags = FBINFO_FLAG_DEFAULT;
+	spin_lock_init(&par->lock);
+	retval = register_framebuffer(info);
+	if (retval < 0)
+		goto err1;
+	dev_set_drvdata(&dev->dev, info);
+	if (irq) {
+		par->irq = irq;
+		if (request_irq(par->irq, &arcfb_interrupt, SA_SHIRQ,
+				"arcfb", info)) {
+			printk(KERN_INFO
+				"arcfb: Failed req IRQ %d\n", par->irq);
+			goto err1;
+		}
+	}
+	printk(KERN_INFO
+	       "fb%d: Arc frame buffer device, using %dK of video memory\n",
+	       info->node, videomemorysize >> 10);
+
+	/* this inits the lcd but doesn't clear dirty pixels */
+	for (i = 0; i < num_cols * num_rows; i++) {
+		ks108_writeb_ctl(par, i, KS_DPY_OFF);
+		ks108_set_start_line(par, i, 0);
+		ks108_set_yaddr(par, i, 0);
+		ks108_set_xaddr(par, i, 0);
+		ks108_writeb_ctl(par, i, KS_DPY_ON);
+	}
+
+	/* if we were told to splash the screen, we just clear it */
+	if (!nosplash) {
+		for (i = 0; i < num_cols * num_rows; i++) {
+			printk(KERN_INFO "fb%d: splashing lcd %d\n",
+				info->node, i);
+			ks108_set_start_line(par, i, 0);
+			ks108_clear_lcd(par, i);
+		}
+	}
+
+	return 0;
+err1:
+	framebuffer_release(info);
+err:
+	vfree(videomemory);
+	return retval;
+}
+
+static int arcfb_remove(struct device *device)
+{
+	struct fb_info *info = dev_get_drvdata(device);
+
+	if (info) {
+		unregister_framebuffer(info);
+		vfree(info->screen_base);
+		framebuffer_release(info);
+	}
+	return 0;
+}
+
+static struct device_driver arcfb_driver = {
+	.name	= "arcfb",
+	.bus	= &platform_bus_type,
+	.probe	= arcfb_probe,
+	.remove = arcfb_remove,
+};
+
+static struct platform_device arcfb_device = {
+	.name	= "arcfb",
+	.id	= 0,
+	.dev	= {
+		.release = arcfb_platform_release,
+	}
+};
+
+static int __init arcfb_init(void)
+{
+	int ret;
+
+	if (!arcfb_enable)
+		return -ENXIO;
+
+	ret = driver_register(&arcfb_driver);
+	if (!ret) {
+		ret = platform_device_register(&arcfb_device);
+		if (ret)
+			driver_unregister(&arcfb_driver);
+	}
+	return ret;
+
+}
+
+static void __exit arcfb_exit(void)
+{
+	platform_device_unregister(&arcfb_device);
+	driver_unregister(&arcfb_driver);
+}
+
+module_param(num_cols, ulong, 0);
+MODULE_PARM_DESC(num_cols, "Num horiz panels, eg: 2 = 128 bit wide");
+module_param(num_rows, ulong, 0);
+MODULE_PARM_DESC(num_rows, "Num vert panels, eg: 1 = 64 bit high");
+module_param(nosplash, uint, 0);
+MODULE_PARM_DESC(nosplash, "Disable doing the splash screen");
+module_param(arcfb_enable, uint, 0);
+MODULE_PARM_DESC(arcfb_enable, "Enable communication with Arc board");
+module_param(dio_addr, ulong, 0);
+MODULE_PARM_DESC(dio_addr, "IO address for data, eg: 0x480");
+module_param(cio_addr, ulong, 0);
+MODULE_PARM_DESC(cio_addr, "IO address for control, eg: 0x400");
+module_param(c2io_addr, ulong, 0);
+MODULE_PARM_DESC(c2io_addr, "IO address for secondary control, eg: 0x408");
+module_param(splashval, ulong, 0);
+MODULE_PARM_DESC(splashval, "Splash pattern: 0xFF is black, 0x00 is green");
+module_param(tuhold, ulong, 0);
+MODULE_PARM_DESC(tuhold, "Time to hold between strobing data to Arc board");
+module_param(irq, uint, 0);
+MODULE_PARM_DESC(irq, "IRQ for the Arc board");
+
+module_init(arcfb_init);
+module_exit(arcfb_exit);
+
+MODULE_DESCRIPTION("fbdev driver for Arc monochrome LCD board");
+MODULE_AUTHOR("Jaya Kumar");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
index ee25b9e..47a6b12 100644
--- a/drivers/video/aty/radeon_base.c
+++ b/drivers/video/aty/radeon_base.c
@@ -2374,10 +2374,9 @@
 	} while (   rinfo->fb_base == 0 &&
 		  ((rinfo->mapped_vram /=2) >= MIN_MAPPED_VRAM) );
 
-	if (rinfo->fb_base)
-		memset_io(rinfo->fb_base, 0, rinfo->mapped_vram);
-	else {
-		printk (KERN_ERR "radeonfb (%s): cannot map FB\n", pci_name(rinfo->pdev));
+	if (rinfo->fb_base == NULL) {
+		printk (KERN_ERR "radeonfb (%s): cannot map FB\n",
+			pci_name(rinfo->pdev));
 		ret = -EIO;
 		goto err_unmap_rom;
 	}
diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c
index cacd88c..b6fe30c 100644
--- a/drivers/video/au1100fb.c
+++ b/drivers/video/au1100fb.c
@@ -111,15 +111,15 @@
 void au1100_nocursor(struct display *p, int mode, int xx, int yy){};
 
 static struct fb_ops au1100fb_ops = {
-	owner:		THIS_MODULE,
-	fb_get_fix:	fbgen_get_fix,
-	fb_get_var:	fbgen_get_var,
-	fb_set_var:	fbgen_set_var,
-	fb_get_cmap:	fbgen_get_cmap,
-	fb_set_cmap:	fbgen_set_cmap,
-	fb_pan_display: fbgen_pan_display,
-        fb_ioctl:       au1100fb_ioctl,
-	fb_mmap:        au1100fb_mmap,
+	.owner		= THIS_MODULE,
+	.fb_get_fix	= fbgen_get_fix,
+	.fb_get_var	= fbgen_get_var,
+	.fb_set_var	= fbgen_set_var,
+	.fb_get_cmap	= fbgen_get_cmap,
+	.fb_set_cmap	= fbgen_set_cmap,
+	.fb_pan_display	= fbgen_pan_display,
+        .fb_ioctl	= au1100fb_ioctl,
+	.fb_mmap	= au1100fb_mmap,
 };
 
 static void au1100_detect(void)
diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c
index ab98f22..95e7255 100644
--- a/drivers/video/chipsfb.c
+++ b/drivers/video/chipsfb.c
@@ -423,9 +423,6 @@
 	pmu_register_sleep_notifier(&chips_sleep_notifier);
 #endif /* CONFIG_PMAC_PBOOK */
 
-	/* Clear the entire framebuffer */
-	memset(p->screen_base, 0, 0x100000);
-
 	pci_set_drvdata(dp, p);
 	return 0;
 }
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index ccf5581..cbff983 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -153,6 +153,14 @@
 	  Small console font with Macintosh-style high-half glyphs.  Some Mac
 	  framebuffer drivers don't support this one at all.
 
+config FONT_7x14
+	bool "console 7x14 font (not supported by all drivers)" if FONTS
+	depends on FRAMEBUFFER_CONSOLE
+	help
+	  Console font with characters just a bit smaller than the default.
+	  If the standard 8x16 font is a little too big for you, say Y.
+	  Otherwise, say N.
+
 config FONT_PEARL_8x8
 	bool "Pearl (old m68k) console 8x8 font" if FONTS
 	depends on FRAMEBUFFER_CONSOLE
@@ -187,5 +195,13 @@
 	  big letters (like the letters used in the SPARC PROM). If the
 	  standard font is unreadable for you, say Y, otherwise say N.
 
+config FONT_10x18
+	bool "console 10x18 font (not supported by all drivers)" if FONTS
+	depends on FRAMEBUFFER_CONSOLE
+	help
+	  This is a high resolution console font for machines with very
+	  big letters. It fits between the sun 12x22 and the normal 8x16 font.
+	  If other fonts are too big or too small for you, say Y, otherwise say N.
+
 endmenu
 
diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile
index 3351644..b562f6b 100644
--- a/drivers/video/console/Makefile
+++ b/drivers/video/console/Makefile
@@ -10,6 +10,8 @@
 font-objs-$(CONFIG_FONT_8x8)       += font_8x8.o
 font-objs-$(CONFIG_FONT_8x16)      += font_8x16.o
 font-objs-$(CONFIG_FONT_6x11)      += font_6x11.o
+font-objs-$(CONFIG_FONT_7x14)      += font_7x14.o
+font-objs-$(CONFIG_FONT_10x18)     += font_10x18.o
 font-objs-$(CONFIG_FONT_PEARL_8x8) += font_pearl_8x8.o
 font-objs-$(CONFIG_FONT_ACORN_8x8) += font_acorn_8x8.o
 font-objs-$(CONFIG_FONT_MINI_4x6)  += font_mini_4x6.o
diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index b28a4b0..3c73157 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -107,13 +107,6 @@
 		      const unsigned short *s, int count, int yy, int xx,
 		      int fg, int bg)
 {
-	void (*move_unaligned)(struct fb_info *info, struct fb_pixmap *buf,
-			       u8 *dst, u32 d_pitch, u8 *src, u32 idx,
-			       u32 height, u32 shift_high, u32 shift_low,
-			       u32 mod);
-	void (*move_aligned)(struct fb_info *info, struct fb_pixmap *buf,
-			     u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch,
-			     u32 height);
 	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
 	unsigned int width = (vc->vc_font.width + 7) >> 3;
 	unsigned int cellsize = vc->vc_font.height * width;
@@ -141,13 +134,6 @@
 	image.height = vc->vc_font.height;
 	image.depth = 1;
 
-	if (info->pixmap.outbuf && info->pixmap.inbuf) {
-		move_aligned = fb_iomove_buf_aligned;
-		move_unaligned = fb_iomove_buf_unaligned;
-	} else {
-		move_aligned = fb_sysmove_buf_aligned;
-		move_unaligned = fb_sysmove_buf_unaligned;
-	}
 	while (count) {
 		if (count > maxcnt)
 			cnt = k = maxcnt;
@@ -171,9 +157,9 @@
 					src = buf;
 				}
 
-				move_unaligned(info, &info->pixmap, dst, pitch,
-					       src, idx, image.height,
-					       shift_high, shift_low, mod);
+				fb_pad_unaligned_buffer(dst, pitch, src, idx,
+						image.height, shift_high,
+						shift_low, mod);
 				shift_low += mod;
 				dst += (shift_low >= 8) ? width : width - 1;
 				shift_low &= 7;
@@ -189,8 +175,7 @@
 					src = buf;
 				}
 
-				move_aligned(info, &info->pixmap, dst, pitch,
-					     src, idx, image.height);
+				fb_pad_aligned_buffer(dst, pitch, src, idx, image.height);
 				dst += width;
 			}
 		}
diff --git a/drivers/video/console/font_10x18.c b/drivers/video/console/font_10x18.c
new file mode 100644
index 0000000..ff0af96
--- /dev/null
+++ b/drivers/video/console/font_10x18.c
@@ -0,0 +1,5146 @@
+/********************************
+ * adapted from font_sun12x22.c *
+ * by Jurriaan Kalkman 06-2005  *
+ ********************************/
+
+#include <linux/font.h>
+
+#define FONTDATAMAX 9216
+
+static unsigned char fontdata_10x18[FONTDATAMAX] = {
+
+	/* 0 0x00 '^@' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 1 0x01 '^A' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x3f, 0x80, /* 0011111110 */
+	0x40, 0x40, /* 0100000001 */
+	0x5b, 0x40, /* 0101101101 */
+	0x40, 0x40, /* 0100000001 */
+	0x44, 0x40, /* 0100010001 */
+	0x44, 0x40, /* 0100010001 */
+	0x51, 0x40, /* 0101000101 */
+	0x4e, 0x40, /* 0100111001 */
+	0x40, 0x40, /* 0100000001 */
+	0x3f, 0x80, /* 0011111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 2 0x02 '^B' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x3f, 0x80, /* 0011111110 */
+	0x7f, 0xc0, /* 0111111111 */
+	0x64, 0xc0, /* 0110010011 */
+	0x7f, 0xc0, /* 0111111111 */
+	0x7b, 0xc0, /* 0111101111 */
+	0x7b, 0xc0, /* 0111101111 */
+	0x6e, 0xc0, /* 0110111011 */
+	0x71, 0xc0, /* 0111000111 */
+	0x7f, 0xc0, /* 0111111111 */
+	0x3f, 0x80, /* 0011111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 3 0x03 '^C' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x11, 0x00, /* 0001000100 */
+	0x3b, 0x80, /* 0011101110 */
+	0x7f, 0xc0, /* 0111111111 */
+	0x3f, 0x80, /* 0011111110 */
+	0x3f, 0x80, /* 0011111110 */
+	0x1f, 0x00, /* 0001111100 */
+	0x1f, 0x00, /* 0001111100 */
+	0x0e, 0x00, /* 0000111000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x04, 0x00, /* 0000010000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 4 0x04 '^D' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x04, 0x00, /* 0000010000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x1f, 0x00, /* 0001111100 */
+	0x1f, 0x00, /* 0001111100 */
+	0x3f, 0x80, /* 0011111110 */
+	0x1f, 0x00, /* 0001111100 */
+	0x1f, 0x00, /* 0001111100 */
+	0x0e, 0x00, /* 0000111000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x04, 0x00, /* 0000010000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 5 0x05 '^E' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x31, 0x80, /* 0011000110 */
+	0x7b, 0xc0, /* 0111101111 */
+	0x35, 0x80, /* 0011010110 */
+	0x04, 0x00, /* 0000010000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x1f, 0x00, /* 0001111100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 6 0x06 '^F' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x04, 0x00, /* 0000010000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x1f, 0x00, /* 0001111100 */
+	0x1f, 0x00, /* 0001111100 */
+	0x3f, 0x80, /* 0011111110 */
+	0x7f, 0xc0, /* 0111111111 */
+	0x7f, 0xc0, /* 0111111111 */
+	0x35, 0x80, /* 0011010110 */
+	0x04, 0x00, /* 0000010000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x1f, 0x00, /* 0001111100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 7 0x07 '^G' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x3f, 0x00, /* 0011111100 */
+	0x3f, 0x00, /* 0011111100 */
+	0x1e, 0x00, /* 0001111000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 8 0x08 '^H' */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xf3, 0xc0, /* 1111001111 */
+	0xe1, 0xc0, /* 1110000111 */
+	0xe1, 0xc0, /* 1110000111 */
+	0xc0, 0xc0, /* 1100000011 */
+	0xc0, 0xc0, /* 1100000011 */
+	0xe1, 0xc0, /* 1110000111 */
+	0xe1, 0xc0, /* 1110000111 */
+	0xf3, 0xc0, /* 1111001111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+
+	/* 9 0x09 '^I' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x12, 0x00, /* 0001001000 */
+	0x12, 0x00, /* 0001001000 */
+	0x21, 0x00, /* 0010000100 */
+	0x21, 0x00, /* 0010000100 */
+	0x12, 0x00, /* 0001001000 */
+	0x12, 0x00, /* 0001001000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 10 0x0a '^J' */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xf3, 0xc0, /* 1111001111 */
+	0xed, 0xc0, /* 1110110111 */
+	0xed, 0xc0, /* 1110110111 */
+	0xde, 0xc0, /* 1101111011 */
+	0xde, 0xc0, /* 1101111011 */
+	0xed, 0xc0, /* 1110110111 */
+	0xed, 0xc0, /* 1110110111 */
+	0xf3, 0xc0, /* 1111001111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+
+	/* 11 0x0b '^K' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0f, 0xc0, /* 0000111111 */
+	0x0f, 0xc0, /* 0000111111 */
+	0x03, 0xc0, /* 0000001111 */
+	0x06, 0xc0, /* 0000011011 */
+	0x0c, 0xc0, /* 0000110011 */
+	0x3c, 0x00, /* 0011110000 */
+	0x66, 0x00, /* 0110011000 */
+	0xc3, 0x00, /* 1100001100 */
+	0xc3, 0x00, /* 1100001100 */
+	0xc3, 0x00, /* 1100001100 */
+	0x66, 0x00, /* 0110011000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 12 0x0c '^L' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x33, 0x00, /* 0011001100 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x33, 0x00, /* 0011001100 */
+	0x1e, 0x00, /* 0001111000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x3f, 0x00, /* 0011111100 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 13 0x0d '^M' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0f, 0x80, /* 0000111110 */
+	0x08, 0x80, /* 0000100010 */
+	0x0f, 0x80, /* 0000111110 */
+	0x08, 0x00, /* 0000100000 */
+	0x08, 0x00, /* 0000100000 */
+	0x08, 0x00, /* 0000100000 */
+	0x08, 0x00, /* 0000100000 */
+	0x08, 0x00, /* 0000100000 */
+	0x08, 0x00, /* 0000100000 */
+	0x38, 0x00, /* 0011100000 */
+	0x78, 0x00, /* 0111100000 */
+	0x30, 0x00, /* 0011000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 14 0x0e '^N' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x1f, 0x80, /* 0001111110 */
+	0x10, 0x80, /* 0001000010 */
+	0x1f, 0x80, /* 0001111110 */
+	0x10, 0x80, /* 0001000010 */
+	0x10, 0x80, /* 0001000010 */
+	0x10, 0x80, /* 0001000010 */
+	0x10, 0x80, /* 0001000010 */
+	0x13, 0x80, /* 0001001110 */
+	0x17, 0x80, /* 0001011110 */
+	0x73, 0x00, /* 0111001100 */
+	0xf0, 0x00, /* 1111000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 15 0x0f '^O' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x04, 0x00, /* 0000010000 */
+	0x24, 0x80, /* 0010010010 */
+	0x15, 0x00, /* 0001010100 */
+	0x55, 0x40, /* 0101010101 */
+	0x3f, 0x80, /* 0011111110 */
+	0x0e, 0x00, /* 0000111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x3f, 0x80, /* 0011111110 */
+	0x55, 0x40, /* 0101010101 */
+	0x15, 0x00, /* 0001010100 */
+	0x24, 0x80, /* 0010010010 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 16 0x10 '^P' */
+	0x00, 0x80, /* 0000000010 */
+	0x01, 0x80, /* 0000000110 */
+	0x03, 0x80, /* 0000001110 */
+	0x07, 0x80, /* 0000011110 */
+	0x0f, 0x80, /* 0000111110 */
+	0x1f, 0x80, /* 0001111110 */
+	0x3f, 0x80, /* 0011111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0xff, 0x80, /* 1111111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x3f, 0x80, /* 0011111110 */
+	0x1f, 0x80, /* 0001111110 */
+	0x0f, 0x80, /* 0000111110 */
+	0x07, 0x80, /* 0000011110 */
+	0x03, 0x80, /* 0000001110 */
+	0x01, 0x80, /* 0000000110 */
+	0x00, 0x80, /* 0000000010 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 17 0x11 '^Q' */
+	0x40, 0x00, /* 0100000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x70, 0x00, /* 0111000000 */
+	0x78, 0x00, /* 0111100000 */
+	0x7c, 0x00, /* 0111110000 */
+	0x7e, 0x00, /* 0111111000 */
+	0x7f, 0x00, /* 0111111100 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0xc0, /* 0111111111 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0x00, /* 0111111100 */
+	0x7e, 0x00, /* 0111111000 */
+	0x7c, 0x00, /* 0111110000 */
+	0x78, 0x00, /* 0111100000 */
+	0x70, 0x00, /* 0111000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x40, 0x00, /* 0100000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 18 0x12 '^R' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x3f, 0x00, /* 0011111100 */
+	0x7f, 0x80, /* 0111111110 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x3f, 0x00, /* 0011111100 */
+	0x1e, 0x00, /* 0001111000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 19 0x13 '^S' */
+	0x00, 0x00, /* 0000000000 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 20 0x14 '^T' */
+	0x00, 0x00, /* 0000000000 */
+	0x1f, 0xc0, /* 0001111111 */
+	0x39, 0x80, /* 0011100110 */
+	0x79, 0x80, /* 0111100110 */
+	0x79, 0x80, /* 0111100110 */
+	0x79, 0x80, /* 0111100110 */
+	0x39, 0x80, /* 0011100110 */
+	0x19, 0x80, /* 0001100110 */
+	0x19, 0x80, /* 0001100110 */
+	0x19, 0x80, /* 0001100110 */
+	0x19, 0x80, /* 0001100110 */
+	0x19, 0x80, /* 0001100110 */
+	0x19, 0x80, /* 0001100110 */
+	0x39, 0xc0, /* 0011100111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 21 0x15 '^U' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x3e, 0x00, /* 0011111000 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x3e, 0x00, /* 0011111000 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x3e, 0x00, /* 0011111000 */
+	0x03, 0x00, /* 0000001100 */
+	0x03, 0x00, /* 0000001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x3e, 0x00, /* 0011111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 22 0x16 '^V' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 23 0x17 '^W' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x3f, 0x00, /* 0011111100 */
+	0x7f, 0x80, /* 0111111110 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x3f, 0x00, /* 0011111100 */
+	0x1e, 0x00, /* 0001111000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 24 0x18 '^X' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x3f, 0x00, /* 0011111100 */
+	0x7f, 0x80, /* 0111111110 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 25 0x19 '^Y' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x3f, 0x00, /* 0011111100 */
+	0x1e, 0x00, /* 0001111000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 26 0x1a '^Z' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x04, 0x00, /* 0000010000 */
+	0x06, 0x00, /* 0000011000 */
+	0x07, 0x00, /* 0000011100 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x07, 0x00, /* 0000011100 */
+	0x06, 0x00, /* 0000011000 */
+	0x04, 0x00, /* 0000010000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 27 0x1b '^[' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x08, 0x00, /* 0000100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x38, 0x00, /* 0011100000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x38, 0x00, /* 0011100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x08, 0x00, /* 0000100000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 28 0x1c '^\' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 29 0x1d '^]' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x12, 0x00, /* 0001001000 */
+	0x33, 0x00, /* 0011001100 */
+	0x73, 0x80, /* 0111001110 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0x73, 0x80, /* 0111001110 */
+	0x33, 0x00, /* 0011001100 */
+	0x12, 0x00, /* 0001001000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 30 0x1e '^^' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x04, 0x00, /* 0000010000 */
+	0x04, 0x00, /* 0000010000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x1f, 0x00, /* 0001111100 */
+	0x1f, 0x00, /* 0001111100 */
+	0x3f, 0x80, /* 0011111110 */
+	0x3f, 0x80, /* 0011111110 */
+	0x7f, 0xc0, /* 0111111111 */
+	0x7f, 0xc0, /* 0111111111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 31 0x1f '^_' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x7f, 0xc0, /* 0111111111 */
+	0x7f, 0xc0, /* 0111111111 */
+	0x3f, 0x80, /* 0011111110 */
+	0x3f, 0x80, /* 0011111110 */
+	0x1f, 0x00, /* 0001111100 */
+	0x1f, 0x00, /* 0001111100 */
+	0x0e, 0x00, /* 0000111000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x04, 0x00, /* 0000010000 */
+	0x04, 0x00, /* 0000010000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 32 0x20 ' ' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 33 0x21 '!' */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 34 0x22 '"' */
+	0x00, 0x00, /* 0000000000 */
+	0x63, 0x00, /* 0110001100 */
+	0xf7, 0x80, /* 1111011110 */
+	0xf7, 0x80, /* 1111011110 */
+	0x31, 0x80, /* 0011000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x63, 0x00, /* 0110001100 */
+	0x42, 0x00, /* 0100001000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 35 0x23 '#' */
+	0x00, 0x00, /* 0000000000 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 36 0x24 '$' */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x3e, 0x00, /* 0011111000 */
+	0x3f, 0x00, /* 0011111100 */
+	0x6f, 0x80, /* 0110111110 */
+	0x6d, 0x80, /* 0110110110 */
+	0x6c, 0x80, /* 0110110010 */
+	0x3c, 0x00, /* 0011110000 */
+	0x0f, 0x00, /* 0000111100 */
+	0x0d, 0x80, /* 0000110110 */
+	0x4d, 0x80, /* 0100110110 */
+	0x6d, 0x80, /* 0110110110 */
+	0x7f, 0x00, /* 0111111100 */
+	0x3e, 0x00, /* 0011111000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 37 0x25 '%' */
+	0x00, 0x00, /* 0000000000 */
+	0x31, 0x80, /* 0011000110 */
+	0x7b, 0x00, /* 0111101100 */
+	0x7b, 0x00, /* 0111101100 */
+	0x36, 0x00, /* 0011011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x1b, 0x00, /* 0001101100 */
+	0x37, 0x80, /* 0011011110 */
+	0x37, 0x80, /* 0011011110 */
+	0x63, 0x00, /* 0110001100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 38 0x26 '&' */
+	0x00, 0x00, /* 0000000000 */
+	0x07, 0x00, /* 0000011100 */
+	0x0f, 0x80, /* 0000111110 */
+	0x19, 0x80, /* 0001100110 */
+	0x19, 0x80, /* 0001100110 */
+	0x0f, 0x80, /* 0000111110 */
+	0x1e, 0x00, /* 0001111000 */
+	0x3e, 0x00, /* 0011111000 */
+	0x76, 0x00, /* 0111011000 */
+	0x66, 0x40, /* 0110011001 */
+	0x63, 0xc0, /* 0110001111 */
+	0x63, 0x80, /* 0110001110 */
+	0x63, 0x00, /* 0110001100 */
+	0x3f, 0x80, /* 0011111110 */
+	0x1c, 0xc0, /* 0001110011 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 39 0x27 ''' */
+	0x00, 0x00, /* 0000000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x78, 0x00, /* 0111100000 */
+	0x78, 0x00, /* 0111100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x30, 0x00, /* 0011000000 */
+	0x20, 0x00, /* 0010000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 40 0x28 '(' */
+	0x00, 0x00, /* 0000000000 */
+	0x03, 0x00, /* 0000001100 */
+	0x06, 0x00, /* 0000011000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x06, 0x00, /* 0000011000 */
+	0x03, 0x00, /* 0000001100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 41 0x29 ')' */
+	0x00, 0x00, /* 0000000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x18, 0x00, /* 0001100000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x30, 0x00, /* 0011000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 42 0x2a '*' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x4c, 0x80, /* 0100110010 */
+	0x6d, 0x80, /* 0110110110 */
+	0x3f, 0x00, /* 0011111100 */
+	0x7f, 0x80, /* 0111111110 */
+	0x3f, 0x00, /* 0011111100 */
+	0x6d, 0x80, /* 0110110110 */
+	0x4c, 0x80, /* 0100110010 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 43 0x2b '+' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 44 0x2c ',' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x78, 0x00, /* 0111100000 */
+	0x78, 0x00, /* 0111100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x30, 0x00, /* 0011000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x40, 0x00, /* 0100000000 */
+
+	/* 45 0x2d '-' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 46 0x2e '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x18, 0x00, /* 0001100000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 47 0x2f '/' */
+	0x00, 0x00, /* 0000000000 */
+	0x01, 0x80, /* 0000000110 */
+	0x01, 0x80, /* 0000000110 */
+	0x03, 0x00, /* 0000001100 */
+	0x03, 0x00, /* 0000001100 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 48 0x30 '0' */
+	0x00, 0x00, /* 0000000000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x1f, 0x00, /* 0001111100 */
+	0x23, 0x00, /* 0010001100 */
+	0x61, 0x80, /* 0110000110 */
+	0x63, 0x80, /* 0110001110 */
+	0x65, 0x80, /* 0110010110 */
+	0x65, 0x80, /* 0110010110 */
+	0x69, 0x80, /* 0110100110 */
+	0x69, 0x80, /* 0110100110 */
+	0x71, 0x80, /* 0111000110 */
+	0x61, 0x00, /* 0110000100 */
+	0x31, 0x00, /* 0011000100 */
+	0x3e, 0x00, /* 0011111000 */
+	0x1c, 0x00, /* 0001110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 49 0x31 '1' */
+	0x00, 0x00, /* 0000000000 */
+	0x04, 0x00, /* 0000010000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x1c, 0x00, /* 0001110000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x6c, 0x00, /* 0110110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 50 0x32 '2' */
+	0x00, 0x00, /* 0000000000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x3f, 0x00, /* 0011111100 */
+	0x63, 0x80, /* 0110001110 */
+	0x41, 0x80, /* 0100000110 */
+	0x01, 0x80, /* 0000000110 */
+	0x01, 0x80, /* 0000000110 */
+	0x03, 0x00, /* 0000001100 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x30, 0x80, /* 0011000010 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 51 0x33 '3' */
+	0x00, 0x00, /* 0000000000 */
+	0x1c, 0x00, /* 0001110000 */
+	0x3e, 0x00, /* 0011111000 */
+	0x47, 0x00, /* 0100011100 */
+	0x03, 0x00, /* 0000001100 */
+	0x07, 0x00, /* 0000011100 */
+	0x06, 0x00, /* 0000011000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x07, 0x00, /* 0000011100 */
+	0x03, 0x00, /* 0000001100 */
+	0x01, 0x80, /* 0000000110 */
+	0x41, 0x80, /* 0100000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x3f, 0x00, /* 0011111100 */
+	0x1e, 0x00, /* 0001111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 52 0x34 '4' */
+	0x00, 0x00, /* 0000000000 */
+	0x06, 0x00, /* 0000011000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x36, 0x00, /* 0011011000 */
+	0x36, 0x00, /* 0011011000 */
+	0x66, 0x00, /* 0110011000 */
+	0x66, 0x00, /* 0110011000 */
+	0xc6, 0x00, /* 1100011000 */
+	0xc6, 0x00, /* 1100011000 */
+	0xff, 0x80, /* 1111111110 */
+	0xff, 0x80, /* 1111111110 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 53 0x35 '5' */
+	0x00, 0x00, /* 0000000000 */
+	0x1f, 0x00, /* 0001111100 */
+	0x1f, 0x00, /* 0001111100 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x7e, 0x00, /* 0111111000 */
+	0x67, 0x00, /* 0110011100 */
+	0x03, 0x80, /* 0000001110 */
+	0x01, 0x80, /* 0000000110 */
+	0x01, 0x80, /* 0000000110 */
+	0x01, 0x80, /* 0000000110 */
+	0x41, 0x80, /* 0100000110 */
+	0x63, 0x00, /* 0110001100 */
+	0x3e, 0x00, /* 0011111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 54 0x36 '6' */
+	0x00, 0x00, /* 0000000000 */
+	0x06, 0x00, /* 0000011000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x6e, 0x00, /* 0110111000 */
+	0x7f, 0x00, /* 0111111100 */
+	0x73, 0x80, /* 0111001110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x71, 0x00, /* 0111000100 */
+	0x3e, 0x00, /* 0011111000 */
+	0x1c, 0x00, /* 0001110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 55 0x37 '7' */
+	0x00, 0x00, /* 0000000000 */
+	0x1f, 0x80, /* 0001111110 */
+	0x3f, 0x80, /* 0011111110 */
+	0x61, 0x80, /* 0110000110 */
+	0x01, 0x80, /* 0000000110 */
+	0x03, 0x00, /* 0000001100 */
+	0x03, 0x00, /* 0000001100 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 56 0x38 '8' */
+	0x00, 0x00, /* 0000000000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x23, 0x00, /* 0010001100 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x31, 0x00, /* 0011000100 */
+	0x1a, 0x00, /* 0001101000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x16, 0x00, /* 0001011000 */
+	0x23, 0x00, /* 0010001100 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x31, 0x00, /* 0011000100 */
+	0x1e, 0x00, /* 0001111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 57 0x39 '9' */
+	0x00, 0x00, /* 0000000000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x17, 0x00, /* 0001011100 */
+	0x23, 0x80, /* 0010001110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x73, 0x80, /* 0111001110 */
+	0x3d, 0x80, /* 0011110110 */
+	0x19, 0x80, /* 0001100110 */
+	0x01, 0x80, /* 0000000110 */
+	0x03, 0x00, /* 0000001100 */
+	0x03, 0x00, /* 0000001100 */
+	0x06, 0x00, /* 0000011000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 58 0x3a ':' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x18, 0x00, /* 0001100000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x18, 0x00, /* 0001100000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 59 0x3b ';' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x18, 0x00, /* 0001100000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x00, 0x00, /* 0000000000 */
+	0x18, 0x00, /* 0001100000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x30, 0x00, /* 0011000000 */
+	0x20, 0x00, /* 0010000000 */
+
+	/* 60 0x3c '<' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x03, 0x00, /* 0000001100 */
+	0x06, 0x00, /* 0000011000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x30, 0x00, /* 0011000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x18, 0x00, /* 0001100000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x06, 0x00, /* 0000011000 */
+	0x03, 0x00, /* 0000001100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 61 0x3d '=' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 62 0x3e '>' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x18, 0x00, /* 0001100000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x06, 0x00, /* 0000011000 */
+	0x03, 0x00, /* 0000001100 */
+	0x01, 0x80, /* 0000000110 */
+	0x01, 0x80, /* 0000000110 */
+	0x03, 0x00, /* 0000001100 */
+	0x06, 0x00, /* 0000011000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x30, 0x00, /* 0011000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 63 0x3f '?' */
+	0x00, 0x00, /* 0000000000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x1f, 0x00, /* 0001111100 */
+	0x3b, 0x80, /* 0011101110 */
+	0x21, 0x80, /* 0010000110 */
+	0x01, 0x80, /* 0000000110 */
+	0x03, 0x00, /* 0000001100 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 64 0x40 '@' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x3f, 0x00, /* 0011111100 */
+	0x31, 0x80, /* 0011000110 */
+	0x65, 0x80, /* 0110010110 */
+	0x6d, 0x80, /* 0110110110 */
+	0x6d, 0x80, /* 0110110110 */
+	0x6d, 0x80, /* 0110110110 */
+	0x6d, 0x80, /* 0110110110 */
+	0x6f, 0x80, /* 0110111110 */
+	0x60, 0x00, /* 0110000000 */
+	0x31, 0x80, /* 0011000110 */
+	0x3f, 0x80, /* 0011111110 */
+	0x0f, 0x00, /* 0000111100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 65 0x41 'A' */
+	0x00, 0x00, /* 0000000000 */
+	0x04, 0x00, /* 0000010000 */
+	0x04, 0x00, /* 0000010000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x19, 0x80, /* 0001100110 */
+	0x31, 0x80, /* 0011000110 */
+	0x3f, 0x80, /* 0011111110 */
+	0x31, 0x80, /* 0011000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x60, 0xc0, /* 0110000011 */
+	0x60, 0xc0, /* 0110000011 */
+	0xf1, 0xc0, /* 1111000111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 66 0x42 'B' */
+	0x00, 0x00, /* 0000000000 */
+	0xfc, 0x00, /* 1111110000 */
+	0x62, 0x00, /* 0110001000 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x66, 0x00, /* 0110011000 */
+	0x7e, 0x00, /* 0111111000 */
+	0x63, 0x00, /* 0110001100 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x63, 0x00, /* 0110001100 */
+	0xfe, 0x00, /* 1111111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 67 0x43 'C' */
+	0x00, 0x00, /* 0000000000 */
+	0x0f, 0x00, /* 0000111100 */
+	0x11, 0x80, /* 0001000110 */
+	0x20, 0x80, /* 0010000010 */
+	0x20, 0x00, /* 0010000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x20, 0x00, /* 0010000000 */
+	0x30, 0x80, /* 0011000010 */
+	0x19, 0x00, /* 0001100100 */
+	0x0e, 0x00, /* 0000111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 68 0x44 'D' */
+	0x00, 0x00, /* 0000000000 */
+	0xfc, 0x00, /* 1111110000 */
+	0x67, 0x00, /* 0110011100 */
+	0x63, 0x00, /* 0110001100 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x00, /* 0110000100 */
+	0x66, 0x00, /* 0110011000 */
+	0xf8, 0x00, /* 1111100000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 69 0x45 'E' */
+	0x00, 0x00, /* 0000000000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x30, 0x80, /* 0011000010 */
+	0x30, 0x80, /* 0011000010 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x31, 0x00, /* 0011000100 */
+	0x3f, 0x00, /* 0011111100 */
+	0x31, 0x00, /* 0011000100 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x80, /* 0011000010 */
+	0x30, 0x80, /* 0011000010 */
+	0x7f, 0x80, /* 0111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 70 0x46 'F' */
+	0x00, 0x00, /* 0000000000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x30, 0x80, /* 0011000010 */
+	0x30, 0x80, /* 0011000010 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x31, 0x00, /* 0011000100 */
+	0x3f, 0x00, /* 0011111100 */
+	0x31, 0x00, /* 0011000100 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x78, 0x00, /* 0111100000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 71 0x47 'G' */
+	0x00, 0x00, /* 0000000000 */
+	0x0f, 0x00, /* 0000111100 */
+	0x11, 0x80, /* 0001000110 */
+	0x20, 0x80, /* 0010000010 */
+	0x20, 0x00, /* 0010000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x67, 0xc0, /* 0110011111 */
+	0x61, 0x80, /* 0110000110 */
+	0x21, 0x80, /* 0010000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x19, 0x80, /* 0001100110 */
+	0x0e, 0x00, /* 0000111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 72 0x48 'H' */
+	0x00, 0x00, /* 0000000000 */
+	0xf3, 0xc0, /* 1111001111 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0xf3, 0xc0, /* 1111001111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 73 0x49 'I' */
+	0x00, 0x00, /* 0000000000 */
+	0x3f, 0x00, /* 0011111100 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x3f, 0x00, /* 0011111100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 74 0x4a 'J' */
+	0x00, 0x00, /* 0000000000 */
+	0x3f, 0x00, /* 0011111100 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x08, 0x00, /* 0000100000 */
+	0x70, 0x00, /* 0111000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 75 0x4b 'K' */
+	0x00, 0x00, /* 0000000000 */
+	0xf1, 0x80, /* 1111000110 */
+	0x63, 0x00, /* 0110001100 */
+	0x66, 0x00, /* 0110011000 */
+	0x6c, 0x00, /* 0110110000 */
+	0x78, 0x00, /* 0111100000 */
+	0x70, 0x00, /* 0111000000 */
+	0x70, 0x00, /* 0111000000 */
+	0x78, 0x00, /* 0111100000 */
+	0x78, 0x00, /* 0111100000 */
+	0x6c, 0x00, /* 0110110000 */
+	0x66, 0x00, /* 0110011000 */
+	0x63, 0x00, /* 0110001100 */
+	0x61, 0x80, /* 0110000110 */
+	0xf0, 0xc0, /* 1111000011 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 76 0x4c 'L' */
+	0x00, 0x00, /* 0000000000 */
+	0x78, 0x00, /* 0111100000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x80, /* 0011000010 */
+	0x30, 0x80, /* 0011000010 */
+	0x7f, 0x80, /* 0111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 77 0x4d 'M' */
+	0x00, 0x00, /* 0000000000 */
+	0xe0, 0xc0, /* 1110000011 */
+	0x61, 0x80, /* 0110000110 */
+	0x73, 0x80, /* 0111001110 */
+	0x73, 0x80, /* 0111001110 */
+	0x6d, 0x80, /* 0110110110 */
+	0x6d, 0x80, /* 0110110110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0xf3, 0xc0, /* 1111001111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 78 0x4e 'N' */
+	0x00, 0x00, /* 0000000000 */
+	0xf3, 0xc0, /* 1111001111 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x71, 0x80, /* 0111000110 */
+	0x79, 0x80, /* 0111100110 */
+	0x79, 0x80, /* 0111100110 */
+	0x6d, 0x80, /* 0110110110 */
+	0x6d, 0x80, /* 0110110110 */
+	0x67, 0x80, /* 0110011110 */
+	0x67, 0x80, /* 0110011110 */
+	0x63, 0x80, /* 0110001110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0xf3, 0xc0, /* 1111001111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 79 0x4f 'O' */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x17, 0x00, /* 0001011100 */
+	0x23, 0x00, /* 0010001100 */
+	0x21, 0x80, /* 0010000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x21, 0x00, /* 0010000100 */
+	0x31, 0x00, /* 0011000100 */
+	0x1a, 0x00, /* 0001101000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 80 0x50 'P' */
+	0x00, 0x00, /* 0000000000 */
+	0xfe, 0x00, /* 1111111000 */
+	0x63, 0x00, /* 0110001100 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x63, 0x00, /* 0110001100 */
+	0x7e, 0x00, /* 0111111000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0xf0, 0x00, /* 1111000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 81 0x51 'Q' */
+	0x00, 0x00, /* 0000000000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x13, 0x00, /* 0001001100 */
+	0x23, 0x00, /* 0010001100 */
+	0x21, 0x80, /* 0010000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x3b, 0x00, /* 0011101100 */
+	0x1e, 0x00, /* 0001111000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x26, 0x00, /* 0010011000 */
+	0x03, 0x80, /* 0000001110 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 82 0x52 'R' */
+	0x00, 0x00, /* 0000000000 */
+	0xfe, 0x00, /* 1111111000 */
+	0x63, 0x00, /* 0110001100 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x00, /* 0110000100 */
+	0x7e, 0x00, /* 0111111000 */
+	0x78, 0x00, /* 0111100000 */
+	0x6c, 0x00, /* 0110110000 */
+	0x6e, 0x00, /* 0110111000 */
+	0x67, 0x00, /* 0110011100 */
+	0x63, 0x80, /* 0110001110 */
+	0x61, 0xc0, /* 0110000111 */
+	0xf0, 0xc0, /* 1111000011 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 83 0x53 'S' */
+	0x00, 0x00, /* 0000000000 */
+	0x1f, 0x00, /* 0001111100 */
+	0x31, 0x80, /* 0011000110 */
+	0x60, 0x80, /* 0110000010 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x18, 0x00, /* 0001100000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x06, 0x00, /* 0000011000 */
+	0x03, 0x00, /* 0000001100 */
+	0x01, 0x80, /* 0000000110 */
+	0x41, 0x80, /* 0100000110 */
+	0x63, 0x00, /* 0110001100 */
+	0x3e, 0x00, /* 0011111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 84 0x54 'T' */
+	0x00, 0x00, /* 0000000000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x4c, 0x80, /* 0100110010 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x3f, 0x00, /* 0011111100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 85 0x55 'U' */
+	0x00, 0x00, /* 0000000000 */
+	0xf3, 0xc0, /* 1111001111 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x73, 0x00, /* 0111001100 */
+	0x3f, 0x00, /* 0011111100 */
+	0x1e, 0x00, /* 0001111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 86 0x56 'V' */
+	0x00, 0x00, /* 0000000000 */
+	0xe1, 0xc0, /* 1110000111 */
+	0xc0, 0xc0, /* 1100000011 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x12, 0x00, /* 0001001000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 87 0x57 'W' */
+	0x00, 0x00, /* 0000000000 */
+	0xe1, 0xc0, /* 1110000111 */
+	0xc0, 0xc0, /* 1100000011 */
+	0xc0, 0xc0, /* 1100000011 */
+	0xc0, 0xc0, /* 1100000011 */
+	0xe0, 0xc0, /* 1110000011 */
+	0x61, 0x80, /* 0110000110 */
+	0x6d, 0x80, /* 0110110110 */
+	0x6d, 0x80, /* 0110110110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x77, 0x00, /* 0111011100 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 88 0x58 'X' */
+	0x00, 0x00, /* 0000000000 */
+	0xf7, 0x80, /* 1111011110 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x36, 0x00, /* 0011011000 */
+	0x36, 0x00, /* 0011011000 */
+	0x36, 0x00, /* 0011011000 */
+	0x1c, 0x00, /* 0001110000 */
+	0x1c, 0x00, /* 0001110000 */
+	0x36, 0x00, /* 0011011000 */
+	0x36, 0x00, /* 0011011000 */
+	0x36, 0x00, /* 0011011000 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0xf7, 0x80, /* 1111011110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 89 0x59 'Y' */
+	0x00, 0x00, /* 0000000000 */
+	0xf3, 0xc0, /* 1111001111 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x1e, 0x00, /* 0001111000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 90 0x5a 'Z' */
+	0x00, 0x00, /* 0000000000 */
+	0x3f, 0x80, /* 0011111110 */
+	0x21, 0x80, /* 0010000110 */
+	0x01, 0x80, /* 0000000110 */
+	0x03, 0x00, /* 0000001100 */
+	0x03, 0x00, /* 0000001100 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x80, /* 0011000010 */
+	0x3f, 0x80, /* 0011111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 91 0x5b '[' */
+	0x00, 0x00, /* 0000000000 */
+	0x1f, 0x00, /* 0001111100 */
+	0x1f, 0x00, /* 0001111100 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x1f, 0x00, /* 0001111100 */
+	0x1f, 0x00, /* 0001111100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 92 0x5c '\' */
+	0x00, 0x00, /* 0000000000 */
+	0xc0, 0x00, /* 1100000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x03, 0x00, /* 0000001100 */
+	0x03, 0x00, /* 0000001100 */
+	0x01, 0x80, /* 0000000110 */
+	0x01, 0x80, /* 0000000110 */
+	0x00, 0xc0, /* 0000000011 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 93 0x5d ']' */
+	0x00, 0x00, /* 0000000000 */
+	0x3e, 0x00, /* 0011111000 */
+	0x3e, 0x00, /* 0011111000 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x3e, 0x00, /* 0011111000 */
+	0x3e, 0x00, /* 0011111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 94 0x5e '^' */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x33, 0x00, /* 0011001100 */
+	0x61, 0x80, /* 0110000110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 95 0x5f '_' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 96 0x60 '`' */
+	0x04, 0x00, /* 0000010000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 97 0x61 'a' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x1f, 0x00, /* 0001111100 */
+	0x31, 0x80, /* 0011000110 */
+	0x21, 0x80, /* 0010000110 */
+	0x07, 0x80, /* 0000011110 */
+	0x39, 0x80, /* 0011100110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x73, 0x80, /* 0111001110 */
+	0x3d, 0xc0, /* 0011110111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 98 0x62 'b' */
+	0x20, 0x00, /* 0010000000 */
+	0x60, 0x00, /* 0110000000 */
+	0xe0, 0x00, /* 1110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x66, 0x00, /* 0110011000 */
+	0x6f, 0x00, /* 0110111100 */
+	0x73, 0x80, /* 0111001110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x71, 0x80, /* 0111000110 */
+	0x7b, 0x00, /* 0111101100 */
+	0x4e, 0x00, /* 0100111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 99 0x63 'c' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x37, 0x00, /* 0011011100 */
+	0x23, 0x00, /* 0010001100 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x71, 0x00, /* 0111000100 */
+	0x33, 0x00, /* 0011001100 */
+	0x1e, 0x00, /* 0001111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 100 0x64 'd' */
+	0x01, 0x80, /* 0000000110 */
+	0x03, 0x80, /* 0000001110 */
+	0x01, 0x80, /* 0000000110 */
+	0x01, 0x80, /* 0000000110 */
+	0x01, 0x80, /* 0000000110 */
+	0x0d, 0x80, /* 0000110110 */
+	0x37, 0x80, /* 0011011110 */
+	0x23, 0x80, /* 0010001110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x73, 0x80, /* 0111001110 */
+	0x35, 0x80, /* 0011010110 */
+	0x19, 0xc0, /* 0001100111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 101 0x65 'e' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x33, 0x00, /* 0011001100 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x19, 0x80, /* 0001100110 */
+	0x0e, 0x00, /* 0000111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 102 0x66 'f' */
+	0x07, 0x00, /* 0000011100 */
+	0x09, 0x80, /* 0000100110 */
+	0x09, 0x80, /* 0000100110 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x7f, 0x00, /* 0111111100 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 103 0x67 'g' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x1c, 0x80, /* 0001110010 */
+	0x37, 0x80, /* 0011011110 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x36, 0x00, /* 0011011000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x60, 0x00, /* 0110000000 */
+	0x7f, 0x00, /* 0111111100 */
+	0x3f, 0x80, /* 0011111110 */
+	0x21, 0x80, /* 0010000110 */
+	0x40, 0x80, /* 0100000010 */
+	0x7f, 0x00, /* 0111111100 */
+	0x3e, 0x00, /* 0011111000 */
+
+	/* 104 0x68 'h' */
+	0x10, 0x00, /* 0001000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x70, 0x00, /* 0111000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x37, 0x00, /* 0011011100 */
+	0x3b, 0x80, /* 0011101110 */
+	0x31, 0x80, /* 0011000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x7b, 0xc0, /* 0111101111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 105 0x69 'i' */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x3f, 0x00, /* 0011111100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 106 0x6a 'j' */
+	0x00, 0x00, /* 0000000000 */
+	0x01, 0x80, /* 0000000110 */
+	0x01, 0x80, /* 0000000110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x07, 0x80, /* 0000011110 */
+	0x01, 0x80, /* 0000000110 */
+	0x01, 0x80, /* 0000000110 */
+	0x01, 0x80, /* 0000000110 */
+	0x01, 0x80, /* 0000000110 */
+	0x01, 0x80, /* 0000000110 */
+	0x01, 0x80, /* 0000000110 */
+	0x01, 0x80, /* 0000000110 */
+	0x41, 0x80, /* 0100000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x71, 0x80, /* 0111000110 */
+	0x3f, 0x00, /* 0011111100 */
+	0x1c, 0x00, /* 0001110000 */
+
+	/* 107 0x6b 'k' */
+	0x60, 0x00, /* 0110000000 */
+	0xe0, 0x00, /* 1110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x63, 0x80, /* 0110001110 */
+	0x66, 0x00, /* 0110011000 */
+	0x6c, 0x00, /* 0110110000 */
+	0x78, 0x00, /* 0111100000 */
+	0x70, 0x00, /* 0111000000 */
+	0x78, 0x00, /* 0111100000 */
+	0x6c, 0x00, /* 0110110000 */
+	0x6e, 0x00, /* 0110111000 */
+	0x67, 0x00, /* 0110011100 */
+	0xf3, 0x80, /* 1111001110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 108 0x6c 'l' */
+	0x3c, 0x00, /* 0011110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x3f, 0x00, /* 0011111100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 109 0x6d 'm' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0xdb, 0x80, /* 1101101110 */
+	0x6d, 0x80, /* 0110110110 */
+	0x6d, 0x80, /* 0110110110 */
+	0x6d, 0x80, /* 0110110110 */
+	0x6d, 0x80, /* 0110110110 */
+	0x6d, 0x80, /* 0110110110 */
+	0x6d, 0x80, /* 0110110110 */
+	0x6d, 0x80, /* 0110110110 */
+	0x6d, 0x80, /* 0110110110 */
+	0xed, 0xc0, /* 1110110111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 110 0x6e 'n' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x6f, 0x00, /* 0110111100 */
+	0x7b, 0x80, /* 0111101110 */
+	0x31, 0x80, /* 0011000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x7b, 0xc0, /* 0111101111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 111 0x6f 'o' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x66, 0x00, /* 0110011000 */
+	0xc3, 0x00, /* 1100001100 */
+	0xc1, 0x80, /* 1100000110 */
+	0xc1, 0x80, /* 1100000110 */
+	0xc1, 0x80, /* 1100000110 */
+	0xc1, 0x80, /* 1100000110 */
+	0xe1, 0x80, /* 1110000110 */
+	0x73, 0x00, /* 0111001100 */
+	0x3c, 0x00, /* 0011110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 112 0x70 'p' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0xde, 0x00, /* 1101111000 */
+	0x76, 0x00, /* 0111011000 */
+	0x63, 0x00, /* 0110001100 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x71, 0x80, /* 0111000110 */
+	0x7b, 0x00, /* 0111101100 */
+	0x7e, 0x00, /* 0111111000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0xf0, 0x00, /* 1111000000 */
+
+	/* 113 0x71 'q' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0e, 0xc0, /* 0000111011 */
+	0x1b, 0x80, /* 0001101110 */
+	0x33, 0x80, /* 0011001110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x71, 0x80, /* 0111000110 */
+	0x3b, 0x80, /* 0011101110 */
+	0x1f, 0x80, /* 0001111110 */
+	0x01, 0x80, /* 0000000110 */
+	0x01, 0x80, /* 0000000110 */
+	0x03, 0xc0, /* 0000001111 */
+
+	/* 114 0x72 'r' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x73, 0x00, /* 0111001100 */
+	0x35, 0x80, /* 0011010110 */
+	0x39, 0x80, /* 0011100110 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x78, 0x00, /* 0111100000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 115 0x73 's' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x3f, 0x00, /* 0011111100 */
+	0x63, 0x00, /* 0110001100 */
+	0x61, 0x00, /* 0110000100 */
+	0x70, 0x00, /* 0111000000 */
+	0x38, 0x00, /* 0011100000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x07, 0x00, /* 0000011100 */
+	0x43, 0x00, /* 0100001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x7e, 0x00, /* 0111111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 116 0x74 't' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x08, 0x00, /* 0000100000 */
+	0x08, 0x00, /* 0000100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x1c, 0x80, /* 0001110010 */
+	0x0f, 0x00, /* 0000111100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 117 0x75 'u' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0xf7, 0x80, /* 1111011110 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x77, 0x00, /* 0111011100 */
+	0x3d, 0x80, /* 0011110110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 118 0x76 'v' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0xf1, 0xc0, /* 1111000111 */
+	0x60, 0xc0, /* 0110000011 */
+	0x31, 0x80, /* 0011000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x19, 0x80, /* 0001100110 */
+	0x1b, 0x00, /* 0001101100 */
+	0x0f, 0x00, /* 0000111100 */
+	0x0f, 0x00, /* 0000111100 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 119 0x77 'w' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0xe3, 0xc0, /* 1110001111 */
+	0xc1, 0x80, /* 1100000110 */
+	0xc1, 0x80, /* 1100000110 */
+	0xc1, 0x80, /* 1100000110 */
+	0xc1, 0x80, /* 1100000110 */
+	0x6b, 0x00, /* 0110101100 */
+	0x6b, 0x00, /* 0110101100 */
+	0x7e, 0x00, /* 0111111000 */
+	0x36, 0x00, /* 0011011000 */
+	0x36, 0x00, /* 0011011000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 120 0x78 'x' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0xf7, 0x80, /* 1111011110 */
+	0x63, 0x00, /* 0110001100 */
+	0x36, 0x00, /* 0011011000 */
+	0x36, 0x00, /* 0011011000 */
+	0x1c, 0x00, /* 0001110000 */
+	0x1c, 0x00, /* 0001110000 */
+	0x36, 0x00, /* 0011011000 */
+	0x66, 0x00, /* 0110011000 */
+	0x63, 0x00, /* 0110001100 */
+	0xf7, 0x80, /* 1111011110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 121 0x79 'y' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0xf3, 0xc0, /* 1111001111 */
+	0x61, 0x80, /* 0110000110 */
+	0x33, 0x00, /* 0011001100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1e, 0x00, /* 0001111000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x78, 0x00, /* 0111100000 */
+	0x70, 0x00, /* 0111000000 */
+
+	/* 122 0x7a 'z' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x61, 0x80, /* 0110000110 */
+	0x43, 0x00, /* 0100001100 */
+	0x06, 0x00, /* 0000011000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x30, 0x00, /* 0011000000 */
+	0x60, 0x80, /* 0110000010 */
+	0x61, 0x80, /* 0110000110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 123 0x7b '{' */
+	0x07, 0x00, /* 0000011100 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x70, 0x00, /* 0111000000 */
+	0x18, 0x00, /* 0001100000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x07, 0x00, /* 0000011100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 124 0x7c '|' */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 125 0x7d '}' */
+	0x38, 0x00, /* 0011100000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x06, 0x00, /* 0000011000 */
+	0x03, 0x80, /* 0000001110 */
+	0x06, 0x00, /* 0000011000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x38, 0x00, /* 0011100000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 126 0x7e '~' */
+	0x00, 0x00, /* 0000000000 */
+	0x18, 0x80, /* 0001100010 */
+	0x3d, 0x80, /* 0011110110 */
+	0x6f, 0x00, /* 0110111100 */
+	0x46, 0x00, /* 0100011000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 127 0x7f '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x12, 0x00, /* 0001001000 */
+	0x21, 0x00, /* 0010000100 */
+	0x40, 0x80, /* 0100000010 */
+	0x40, 0x80, /* 0100000010 */
+	0x40, 0x80, /* 0100000010 */
+	0x7f, 0x80, /* 0111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 128 0x80 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x1f, 0x00, /* 0001111100 */
+	0x21, 0x80, /* 0010000110 */
+	0x40, 0x80, /* 0100000010 */
+	0x40, 0x00, /* 0100000000 */
+	0x40, 0x00, /* 0100000000 */
+	0x40, 0x00, /* 0100000000 */
+	0x40, 0x00, /* 0100000000 */
+	0x40, 0x00, /* 0100000000 */
+	0x40, 0x00, /* 0100000000 */
+	0x60, 0x80, /* 0110000010 */
+	0x31, 0x00, /* 0011000100 */
+	0x1e, 0x00, /* 0001111000 */
+	0x08, 0x00, /* 0000100000 */
+	0x04, 0x00, /* 0000010000 */
+	0x02, 0x00, /* 0000001000 */
+	0x02, 0x00, /* 0000001000 */
+	0x1c, 0x00, /* 0001110000 */
+
+	/* 129 0x81 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x7b, 0x80, /* 0111101110 */
+	0x31, 0x00, /* 0011000100 */
+	0x31, 0x00, /* 0011000100 */
+	0x31, 0x00, /* 0011000100 */
+	0x31, 0x00, /* 0011000100 */
+	0x31, 0x00, /* 0011000100 */
+	0x31, 0x00, /* 0011000100 */
+	0x31, 0x00, /* 0011000100 */
+	0x3b, 0x00, /* 0011101100 */
+	0x1c, 0x80, /* 0001110010 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 130 0x82 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x01, 0x00, /* 0000000100 */
+	0x02, 0x00, /* 0000001000 */
+	0x04, 0x00, /* 0000010000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x33, 0x00, /* 0011001100 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x19, 0x80, /* 0001100110 */
+	0x0e, 0x00, /* 0000111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 131 0x83 '.' */
+	0x04, 0x00, /* 0000010000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x1b, 0x00, /* 0001101100 */
+	0x31, 0x80, /* 0011000110 */
+	0x00, 0x00, /* 0000000000 */
+	0x1f, 0x00, /* 0001111100 */
+	0x31, 0x80, /* 0011000110 */
+	0x21, 0x80, /* 0010000110 */
+	0x07, 0x80, /* 0000011110 */
+	0x39, 0x80, /* 0011100110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x73, 0x80, /* 0111001110 */
+	0x3d, 0xc0, /* 0011110111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 132 0x84 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x1f, 0x00, /* 0001111100 */
+	0x31, 0x80, /* 0011000110 */
+	0x21, 0x80, /* 0010000110 */
+	0x07, 0x80, /* 0000011110 */
+	0x39, 0x80, /* 0011100110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x73, 0x80, /* 0111001110 */
+	0x3d, 0xc0, /* 0011110111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 133 0x85 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x18, 0x00, /* 0001100000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x06, 0x00, /* 0000011000 */
+	0x00, 0x00, /* 0000000000 */
+	0x1f, 0x00, /* 0001111100 */
+	0x31, 0x80, /* 0011000110 */
+	0x21, 0x80, /* 0010000110 */
+	0x07, 0x80, /* 0000011110 */
+	0x39, 0x80, /* 0011100110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x73, 0x80, /* 0111001110 */
+	0x3d, 0xc0, /* 0011110111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 134 0x86 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x1b, 0x00, /* 0001101100 */
+	0x0e, 0x00, /* 0000111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x1f, 0x00, /* 0001111100 */
+	0x31, 0x80, /* 0011000110 */
+	0x21, 0x80, /* 0010000110 */
+	0x07, 0x80, /* 0000011110 */
+	0x39, 0x80, /* 0011100110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x73, 0x80, /* 0111001110 */
+	0x3d, 0xc0, /* 0011110111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 135 0x87 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x1f, 0x00, /* 0001111100 */
+	0x31, 0x80, /* 0011000110 */
+	0x20, 0x80, /* 0010000010 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x70, 0x80, /* 0111000010 */
+	0x30, 0x80, /* 0011000010 */
+	0x1f, 0x00, /* 0001111100 */
+	0x04, 0x00, /* 0000010000 */
+	0x02, 0x00, /* 0000001000 */
+	0x01, 0x00, /* 0000000100 */
+	0x0e, 0x00, /* 0000111000 */
+
+	/* 136 0x88 '.' */
+	0x04, 0x00, /* 0000010000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x1b, 0x00, /* 0001101100 */
+	0x31, 0x80, /* 0011000110 */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x33, 0x00, /* 0011001100 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x19, 0x80, /* 0001100110 */
+	0x0e, 0x00, /* 0000111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 137 0x89 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x36, 0x00, /* 0011011000 */
+	0x36, 0x00, /* 0011011000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x33, 0x00, /* 0011001100 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x19, 0x80, /* 0001100110 */
+	0x0e, 0x00, /* 0000111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 138 0x8a '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x18, 0x00, /* 0001100000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x33, 0x00, /* 0011001100 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x19, 0x80, /* 0001100110 */
+	0x0e, 0x00, /* 0000111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 139 0x8b '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x36, 0x00, /* 0011011000 */
+	0x36, 0x00, /* 0011011000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x3f, 0x00, /* 0011111100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 140 0x8c '.' */
+	0x08, 0x00, /* 0000100000 */
+	0x1c, 0x00, /* 0001110000 */
+	0x36, 0x00, /* 0011011000 */
+	0x63, 0x00, /* 0110001100 */
+	0x00, 0x00, /* 0000000000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x3f, 0x00, /* 0011111100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 141 0x8d '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x18, 0x00, /* 0001100000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x3f, 0x00, /* 0011111100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 142 0x8e '.' */
+	0x31, 0x80, /* 0011000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x04, 0x00, /* 0000010000 */
+	0x04, 0x00, /* 0000010000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x19, 0x00, /* 0001100100 */
+	0x19, 0x00, /* 0001100100 */
+	0x3f, 0x00, /* 0011111100 */
+	0x31, 0x00, /* 0011000100 */
+	0x31, 0x00, /* 0011000100 */
+	0x60, 0x80, /* 0110000010 */
+	0x60, 0x80, /* 0110000010 */
+	0xf3, 0xc0, /* 1111001111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 143 0x8f '.' */
+	0x04, 0x00, /* 0000010000 */
+	0x0a, 0x00, /* 0000101000 */
+	0x0a, 0x00, /* 0000101000 */
+	0x04, 0x00, /* 0000010000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x19, 0x00, /* 0001100100 */
+	0x19, 0x00, /* 0001100100 */
+	0x3f, 0x00, /* 0011111100 */
+	0x31, 0x00, /* 0011000100 */
+	0x31, 0x00, /* 0011000100 */
+	0x60, 0x80, /* 0110000010 */
+	0x60, 0x80, /* 0110000010 */
+	0xf3, 0xc0, /* 1111001111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 144 0x90 '.' */
+	0x03, 0x00, /* 0000001100 */
+	0x06, 0x00, /* 0000011000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x30, 0x80, /* 0011000010 */
+	0x30, 0x80, /* 0011000010 */
+	0x30, 0x00, /* 0011000000 */
+	0x31, 0x00, /* 0011000100 */
+	0x3f, 0x00, /* 0011111100 */
+	0x31, 0x00, /* 0011000100 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x80, /* 0011000010 */
+	0x30, 0x80, /* 0011000010 */
+	0x7f, 0x80, /* 0111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 145 0x91 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x3b, 0x80, /* 0011101110 */
+	0x6c, 0xc0, /* 0110110011 */
+	0x4c, 0xc0, /* 0100110011 */
+	0x0c, 0xc0, /* 0000110011 */
+	0x3f, 0xc0, /* 0011111111 */
+	0x6c, 0x00, /* 0110110000 */
+	0xcc, 0x00, /* 1100110000 */
+	0xcc, 0x00, /* 1100110000 */
+	0xee, 0xc0, /* 1110111011 */
+	0x7b, 0x80, /* 0111101110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 146 0x92 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x07, 0xc0, /* 0000011111 */
+	0x0e, 0x40, /* 0000111001 */
+	0x0e, 0x40, /* 0000111001 */
+	0x0e, 0x00, /* 0000111000 */
+	0x16, 0x00, /* 0001011000 */
+	0x16, 0x80, /* 0001011010 */
+	0x17, 0x80, /* 0001011110 */
+	0x16, 0x80, /* 0001011010 */
+	0x3e, 0x00, /* 0011111000 */
+	0x26, 0x00, /* 0010011000 */
+	0x26, 0x00, /* 0010011000 */
+	0x46, 0x40, /* 0100011001 */
+	0x46, 0x40, /* 0100011001 */
+	0xef, 0xc0, /* 1110111111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 147 0x93 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x08, 0x00, /* 0000100000 */
+	0x1c, 0x00, /* 0001110000 */
+	0x36, 0x00, /* 0011011000 */
+	0x00, 0x00, /* 0000000000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x66, 0x00, /* 0110011000 */
+	0xc3, 0x00, /* 1100001100 */
+	0xc1, 0x80, /* 1100000110 */
+	0xc1, 0x80, /* 1100000110 */
+	0xc1, 0x80, /* 1100000110 */
+	0xc1, 0x80, /* 1100000110 */
+	0xe1, 0x80, /* 1110000110 */
+	0x73, 0x00, /* 0111001100 */
+	0x3c, 0x00, /* 0011110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 148 0x94 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x00, 0x00, /* 0000000000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x66, 0x00, /* 0110011000 */
+	0xc3, 0x00, /* 1100001100 */
+	0xc1, 0x80, /* 1100000110 */
+	0xc1, 0x80, /* 1100000110 */
+	0xc1, 0x80, /* 1100000110 */
+	0xc1, 0x80, /* 1100000110 */
+	0xe1, 0x80, /* 1110000110 */
+	0x73, 0x00, /* 0111001100 */
+	0x3c, 0x00, /* 0011110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 149 0x95 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x18, 0x00, /* 0001100000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x06, 0x00, /* 0000011000 */
+	0x00, 0x00, /* 0000000000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x66, 0x00, /* 0110011000 */
+	0xc3, 0x00, /* 1100001100 */
+	0xc1, 0x80, /* 1100000110 */
+	0xc1, 0x80, /* 1100000110 */
+	0xc1, 0x80, /* 1100000110 */
+	0xc1, 0x80, /* 1100000110 */
+	0xe1, 0x80, /* 1110000110 */
+	0x73, 0x00, /* 0111001100 */
+	0x3c, 0x00, /* 0011110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 150 0x96 '.' */
+	0x08, 0x00, /* 0000100000 */
+	0x1c, 0x00, /* 0001110000 */
+	0x36, 0x00, /* 0011011000 */
+	0x63, 0x00, /* 0110001100 */
+	0x00, 0x00, /* 0000000000 */
+	0xf7, 0x80, /* 1111011110 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x77, 0x00, /* 0111011100 */
+	0x3d, 0x80, /* 0011110110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 151 0x97 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x18, 0x00, /* 0001100000 */
+	0x00, 0x00, /* 0000000000 */
+	0xf7, 0x80, /* 1111011110 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x77, 0x00, /* 0111011100 */
+	0x3d, 0x80, /* 0011110110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 152 0x98 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0xf3, 0xc0, /* 1111001111 */
+	0x61, 0x80, /* 0110000110 */
+	0x33, 0x00, /* 0011001100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1e, 0x00, /* 0001111000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x78, 0x00, /* 0111100000 */
+	0x70, 0x00, /* 0111000000 */
+
+	/* 153 0x99 '.' */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x0c, 0x00, /* 0000110000 */
+	0x17, 0x00, /* 0001011100 */
+	0x23, 0x00, /* 0010001100 */
+	0x21, 0x80, /* 0010000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x21, 0x00, /* 0010000100 */
+	0x31, 0x00, /* 0011000100 */
+	0x1a, 0x00, /* 0001101000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 154 0x9a '.' */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x00, 0x00, /* 0000000000 */
+	0xf1, 0xc0, /* 1111000111 */
+	0x60, 0x80, /* 0110000010 */
+	0x60, 0x80, /* 0110000010 */
+	0x60, 0x80, /* 0110000010 */
+	0x60, 0x80, /* 0110000010 */
+	0x60, 0x80, /* 0110000010 */
+	0x60, 0x80, /* 0110000010 */
+	0x60, 0x80, /* 0110000010 */
+	0x60, 0x80, /* 0110000010 */
+	0x71, 0x00, /* 0111000100 */
+	0x3f, 0x00, /* 0011111100 */
+	0x1e, 0x00, /* 0001111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 155 0x9b '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x1f, 0x80, /* 0001111110 */
+	0x36, 0x80, /* 0011011010 */
+	0x26, 0x00, /* 0010011000 */
+	0x66, 0x00, /* 0110011000 */
+	0x66, 0x00, /* 0110011000 */
+	0x66, 0x00, /* 0110011000 */
+	0x66, 0x00, /* 0110011000 */
+	0x76, 0x00, /* 0111011000 */
+	0x36, 0x80, /* 0011011010 */
+	0x1f, 0x80, /* 0001111110 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 156 0x9c '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x3b, 0x00, /* 0011101100 */
+	0x33, 0x00, /* 0011001100 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x7e, 0x00, /* 0111111000 */
+	0x7e, 0x00, /* 0111111000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x7c, 0x80, /* 0111110010 */
+	0x7f, 0x80, /* 0111111110 */
+	0x43, 0x00, /* 0100001100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 157 0x9d '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x40, 0x80, /* 0100000010 */
+	0x40, 0x80, /* 0100000010 */
+	0x21, 0x00, /* 0010000100 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x1e, 0x00, /* 0001111000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x3f, 0x00, /* 0011111100 */
+	0x0c, 0x00, /* 0000110000 */
+	0x3f, 0x00, /* 0011111100 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 158 0x9e '.' */
+	0x00, 0x00, /* 0000000000 */
+	0xbf, 0x00, /* 1011111100 */
+	0x40, 0x80, /* 0100000010 */
+	0x40, 0x80, /* 0100000010 */
+	0x7f, 0x00, /* 0111111100 */
+	0x40, 0x00, /* 0100000000 */
+	0x48, 0x00, /* 0100100000 */
+	0x48, 0x00, /* 0100100000 */
+	0x5e, 0x00, /* 0101111000 */
+	0x48, 0x00, /* 0100100000 */
+	0x48, 0x00, /* 0100100000 */
+	0x48, 0x00, /* 0100100000 */
+	0x48, 0x80, /* 0100100010 */
+	0x47, 0x00, /* 0100011100 */
+	0xe0, 0x00, /* 1110000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 159 0x9f '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x03, 0x00, /* 0000001100 */
+	0x04, 0x80, /* 0000010010 */
+	0x08, 0x00, /* 0000100000 */
+	0x08, 0x00, /* 0000100000 */
+	0x08, 0x00, /* 0000100000 */
+	0x08, 0x00, /* 0000100000 */
+	0x09, 0x00, /* 0000100100 */
+	0x3e, 0x00, /* 0011111000 */
+	0x48, 0x00, /* 0100100000 */
+	0x08, 0x00, /* 0000100000 */
+	0x08, 0x00, /* 0000100000 */
+	0x08, 0x00, /* 0000100000 */
+	0x08, 0x00, /* 0000100000 */
+	0x08, 0x00, /* 0000100000 */
+	0x90, 0x00, /* 1001000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 160 0xa0 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x03, 0x00, /* 0000001100 */
+	0x06, 0x00, /* 0000011000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x1f, 0x00, /* 0001111100 */
+	0x31, 0x80, /* 0011000110 */
+	0x21, 0x80, /* 0010000110 */
+	0x07, 0x80, /* 0000011110 */
+	0x39, 0x80, /* 0011100110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x73, 0x80, /* 0111001110 */
+	0x3d, 0xc0, /* 0011110111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 161 0xa1 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x03, 0x00, /* 0000001100 */
+	0x06, 0x00, /* 0000011000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x3f, 0x00, /* 0011111100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 162 0xa2 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x06, 0x00, /* 0000011000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x00, 0x00, /* 0000000000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x66, 0x00, /* 0110011000 */
+	0xc3, 0x00, /* 1100001100 */
+	0xc1, 0x80, /* 1100000110 */
+	0xc1, 0x80, /* 1100000110 */
+	0xc1, 0x80, /* 1100000110 */
+	0xc1, 0x80, /* 1100000110 */
+	0xe1, 0x80, /* 1110000110 */
+	0x73, 0x00, /* 0111001100 */
+	0x3c, 0x00, /* 0011110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 163 0xa3 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x06, 0x00, /* 0000011000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x00, 0x00, /* 0000000000 */
+	0xf7, 0x80, /* 1111011110 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x77, 0x00, /* 0111011100 */
+	0x3d, 0x80, /* 0011110110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 164 0xa4 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x38, 0x80, /* 0011100010 */
+	0x7f, 0x80, /* 0111111110 */
+	0x47, 0x00, /* 0100011100 */
+	0x00, 0x00, /* 0000000000 */
+	0x6f, 0x00, /* 0110111100 */
+	0x7b, 0x80, /* 0111101110 */
+	0x31, 0x80, /* 0011000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x7b, 0xc0, /* 0111101111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 165 0xa5 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x38, 0x80, /* 0011100010 */
+	0x7f, 0x80, /* 0111111110 */
+	0x47, 0x00, /* 0100011100 */
+	0x00, 0x00, /* 0000000000 */
+	0xe3, 0xc0, /* 1110001111 */
+	0x71, 0x80, /* 0111000110 */
+	0x79, 0x80, /* 0111100110 */
+	0x79, 0x80, /* 0111100110 */
+	0x6d, 0x80, /* 0110110110 */
+	0x6d, 0x80, /* 0110110110 */
+	0x67, 0x80, /* 0110011110 */
+	0x63, 0x80, /* 0110001110 */
+	0x61, 0x80, /* 0110000110 */
+	0xf0, 0xc0, /* 1111000011 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 166 0xa6 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x3e, 0x00, /* 0011111000 */
+	0x63, 0x00, /* 0110001100 */
+	0x03, 0x00, /* 0000001100 */
+	0x0f, 0x00, /* 0000111100 */
+	0x33, 0x00, /* 0011001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x67, 0x00, /* 0110011100 */
+	0x3b, 0x80, /* 0011101110 */
+	0x00, 0x00, /* 0000000000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 167 0xa7 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x33, 0x00, /* 0011001100 */
+	0x21, 0x80, /* 0010000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x00, /* 0110000100 */
+	0x33, 0x00, /* 0011001100 */
+	0x1c, 0x00, /* 0001110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 168 0xa8 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x00, 0x00, /* 0000000000 */
+	0x06, 0x00, /* 0000011000 */
+	0x06, 0x00, /* 0000011000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x30, 0x00, /* 0011000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x80, /* 0110000010 */
+	0x73, 0x80, /* 0111001110 */
+	0x3f, 0x00, /* 0011111100 */
+	0x1e, 0x00, /* 0001111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 169 0xa9 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 170 0xaa '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x01, 0x80, /* 0000000110 */
+	0x01, 0x80, /* 0000000110 */
+	0x01, 0x80, /* 0000000110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 171 0xab '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x20, 0x00, /* 0010000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x20, 0x00, /* 0010000000 */
+	0x20, 0x80, /* 0010000010 */
+	0x21, 0x00, /* 0010000100 */
+	0x22, 0x00, /* 0010001000 */
+	0x74, 0x00, /* 0111010000 */
+	0x08, 0x00, /* 0000100000 */
+	0x17, 0x00, /* 0001011100 */
+	0x28, 0x80, /* 0010100010 */
+	0x43, 0x00, /* 0100001100 */
+	0x04, 0x00, /* 0000010000 */
+	0x08, 0x00, /* 0000100000 */
+	0x0f, 0x80, /* 0000111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 172 0xac '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x20, 0x00, /* 0010000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x20, 0x00, /* 0010000000 */
+	0x20, 0x80, /* 0010000010 */
+	0x21, 0x00, /* 0010000100 */
+	0x22, 0x00, /* 0010001000 */
+	0x74, 0x00, /* 0111010000 */
+	0x09, 0x00, /* 0000100100 */
+	0x13, 0x00, /* 0001001100 */
+	0x25, 0x00, /* 0010010100 */
+	0x49, 0x00, /* 0100100100 */
+	0x1f, 0x80, /* 0001111110 */
+	0x01, 0x00, /* 0000000100 */
+	0x01, 0x00, /* 0000000100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 173 0xad '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 174 0xae '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0d, 0x80, /* 0000110110 */
+	0x1b, 0x00, /* 0001101100 */
+	0x36, 0x00, /* 0011011000 */
+	0x6c, 0x00, /* 0110110000 */
+	0xd8, 0x00, /* 1101100000 */
+	0x6c, 0x00, /* 0110110000 */
+	0x36, 0x00, /* 0011011000 */
+	0x1b, 0x00, /* 0001101100 */
+	0x0d, 0x80, /* 0000110110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 175 0xaf '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x6c, 0x00, /* 0110110000 */
+	0x36, 0x00, /* 0011011000 */
+	0x1b, 0x00, /* 0001101100 */
+	0x0d, 0x80, /* 0000110110 */
+	0x06, 0xc0, /* 0000011011 */
+	0x0d, 0x80, /* 0000110110 */
+	0x1b, 0x00, /* 0001101100 */
+	0x36, 0x00, /* 0011011000 */
+	0x6c, 0x00, /* 0110110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 176 0xb0 '.' */
+	0xc3, 0x00, /* 1100001100 */
+	0x41, 0x00, /* 0100000100 */
+	0x18, 0x40, /* 0001100001 */
+	0x10, 0x40, /* 0001000001 */
+	0xc3, 0x00, /* 1100001100 */
+	0x41, 0x00, /* 0100000100 */
+	0x18, 0x40, /* 0001100001 */
+	0x10, 0x40, /* 0001000001 */
+	0xc3, 0x00, /* 1100001100 */
+	0x41, 0x00, /* 0100000100 */
+	0x18, 0x40, /* 0001100001 */
+	0x10, 0x40, /* 0001000001 */
+	0xc3, 0x00, /* 1100001100 */
+	0x41, 0x00, /* 0100000100 */
+	0x18, 0x40, /* 0001100001 */
+	0x10, 0x40, /* 0001000001 */
+	0xc3, 0x00, /* 1100001100 */
+	0x41, 0x00, /* 0100000100 */
+
+	/* 177 0xb1 '.' */
+	0x11, 0x00, /* 0001000100 */
+	0xbb, 0x80, /* 1011101110 */
+	0x11, 0x00, /* 0001000100 */
+	0x44, 0x40, /* 0100010001 */
+	0xee, 0xc0, /* 1110111011 */
+	0x44, 0x40, /* 0100010001 */
+	0x11, 0x00, /* 0001000100 */
+	0xbb, 0x80, /* 1011101110 */
+	0x11, 0x00, /* 0001000100 */
+	0x44, 0x40, /* 0100010001 */
+	0xee, 0xc0, /* 1110111011 */
+	0x44, 0x40, /* 0100010001 */
+	0x11, 0x00, /* 0001000100 */
+	0xbb, 0x80, /* 1011101110 */
+	0x11, 0x00, /* 0001000100 */
+	0x44, 0x40, /* 0100010001 */
+	0xee, 0xc0, /* 1110111011 */
+	0x44, 0x40, /* 0100010001 */
+
+	/* 178 0xb2 '.' */
+	0x3c, 0xc0, /* 0011110011 */
+	0xbe, 0xc0, /* 1011111011 */
+	0xe7, 0x80, /* 1110011110 */
+	0xef, 0x80, /* 1110111110 */
+	0x3c, 0xc0, /* 0011110011 */
+	0xbe, 0xc0, /* 1011111011 */
+	0xe7, 0x80, /* 1110011110 */
+	0xef, 0x80, /* 1110111110 */
+	0x3c, 0xc0, /* 0011110011 */
+	0xbe, 0xc0, /* 1011111011 */
+	0xe7, 0x80, /* 1110011110 */
+	0xef, 0x80, /* 1110111110 */
+	0x3c, 0xc0, /* 0011110011 */
+	0xbe, 0xc0, /* 1011111011 */
+	0xe7, 0x80, /* 1110011110 */
+	0xef, 0x80, /* 1110111110 */
+	0x3c, 0xc0, /* 0011110011 */
+	0xbe, 0xc0, /* 1011111011 */
+
+	/* 179 0xb3 '.' */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+
+	/* 180 0xb4 '.' */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0xfc, 0x00, /* 1111110000 */
+	0xfc, 0x00, /* 1111110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+
+	/* 181 0xb5 '.' */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0xfc, 0x00, /* 1111110000 */
+	0xfc, 0x00, /* 1111110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0xfc, 0x00, /* 1111110000 */
+	0xfc, 0x00, /* 1111110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+
+	/* 182 0xb6 '.' */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0xfb, 0x00, /* 1111101100 */
+	0xfb, 0x00, /* 1111101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+
+	/* 183 0xb7 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0xff, 0x00, /* 1111111100 */
+	0xff, 0x00, /* 1111111100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+
+	/* 184 0xb8 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0xfc, 0x00, /* 1111110000 */
+	0xfc, 0x00, /* 1111110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0xfc, 0x00, /* 1111110000 */
+	0xfc, 0x00, /* 1111110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+
+	/* 185 0xb9 '.' */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0xfb, 0x00, /* 1111101100 */
+	0xfb, 0x00, /* 1111101100 */
+	0x03, 0x00, /* 0000001100 */
+	0xfb, 0x00, /* 1111101100 */
+	0xfb, 0x00, /* 1111101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+
+	/* 186 0xba '.' */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+
+	/* 187 0xbb '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0xff, 0x00, /* 1111111100 */
+	0xff, 0x00, /* 1111111100 */
+	0x03, 0x00, /* 0000001100 */
+	0xfb, 0x00, /* 1111101100 */
+	0xfb, 0x00, /* 1111101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+
+	/* 188 0xbc '.' */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0xfb, 0x00, /* 1111101100 */
+	0xfb, 0x00, /* 1111101100 */
+	0x03, 0x00, /* 0000001100 */
+	0xff, 0x00, /* 1111111100 */
+	0xff, 0x00, /* 1111111100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 189 0xbd '.' */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0xff, 0x00, /* 1111111100 */
+	0xff, 0x00, /* 1111111100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 190 0xbe '.' */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0xfc, 0x00, /* 1111110000 */
+	0xfc, 0x00, /* 1111110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0xfc, 0x00, /* 1111110000 */
+	0xfc, 0x00, /* 1111110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 191 0xbf '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0xfc, 0x00, /* 1111110000 */
+	0xfc, 0x00, /* 1111110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+
+	/* 192 0xc0 '.' */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0f, 0xc0, /* 0000111111 */
+	0x0f, 0xc0, /* 0000111111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 193 0xc1 '.' */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 194 0xc2 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+
+	/* 195 0xc3 '.' */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0f, 0xc0, /* 0000111111 */
+	0x0f, 0xc0, /* 0000111111 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+
+	/* 196 0xc4 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 197 0xc5 '.' */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+
+	/* 198 0xc6 '.' */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0f, 0xc0, /* 0000111111 */
+	0x0f, 0xc0, /* 0000111111 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0f, 0xc0, /* 0000111111 */
+	0x0f, 0xc0, /* 0000111111 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+
+	/* 199 0xc7 '.' */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0xc0, /* 0001101111 */
+	0x1b, 0xc0, /* 0001101111 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+
+	/* 200 0xc8 '.' */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0xc0, /* 0001101111 */
+	0x1b, 0xc0, /* 0001101111 */
+	0x18, 0x00, /* 0001100000 */
+	0x1f, 0xc0, /* 0001111111 */
+	0x1f, 0xc0, /* 0001111111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 201 0xc9 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x1f, 0xc0, /* 0001111111 */
+	0x1f, 0xc0, /* 0001111111 */
+	0x18, 0x00, /* 0001100000 */
+	0x1b, 0xc0, /* 0001101111 */
+	0x1b, 0xc0, /* 0001101111 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+
+	/* 202 0xca '.' */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0xfb, 0xc0, /* 1111101111 */
+	0xfb, 0xc0, /* 1111101111 */
+	0x00, 0x00, /* 0000000000 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 203 0xcb '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0x00, 0x00, /* 0000000000 */
+	0xfb, 0xc0, /* 1111101111 */
+	0xfb, 0xc0, /* 1111101111 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+
+	/* 204 0xcc '.' */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0xc0, /* 0001101111 */
+	0x1b, 0xc0, /* 0001101111 */
+	0x18, 0x00, /* 0001100000 */
+	0x1b, 0xc0, /* 0001101111 */
+	0x1b, 0xc0, /* 0001101111 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+
+	/* 205 0xcd '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0x00, 0x00, /* 0000000000 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 206 0xce '.' */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0xfb, 0xc0, /* 1111101111 */
+	0xfb, 0xc0, /* 1111101111 */
+	0x00, 0x00, /* 0000000000 */
+	0xfb, 0xc0, /* 1111101111 */
+	0xfb, 0xc0, /* 1111101111 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+
+	/* 207 0xcf '.' */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0x00, 0x00, /* 0000000000 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 208 0xd0 '.' */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 209 0xd1 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0x00, 0x00, /* 0000000000 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+
+	/* 210 0xd2 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+
+	/* 211 0xd3 '.' */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1f, 0xc0, /* 0001111111 */
+	0x1f, 0xc0, /* 0001111111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 212 0xd4 '.' */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0f, 0xc0, /* 0000111111 */
+	0x0f, 0xc0, /* 0000111111 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0f, 0xc0, /* 0000111111 */
+	0x0f, 0xc0, /* 0000111111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 213 0xd5 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0f, 0xc0, /* 0000111111 */
+	0x0f, 0xc0, /* 0000111111 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0f, 0xc0, /* 0000111111 */
+	0x0f, 0xc0, /* 0000111111 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+
+	/* 214 0xd6 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x1f, 0xc0, /* 0001111111 */
+	0x1f, 0xc0, /* 0001111111 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+
+	/* 215 0xd7 '.' */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+	0x1b, 0x00, /* 0001101100 */
+
+	/* 216 0xd8 '.' */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0x0c, 0x00, /* 0000110000 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+
+	/* 217 0xd9 '.' */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0xfc, 0x00, /* 1111110000 */
+	0xfc, 0x00, /* 1111110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 218 0xda '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0f, 0xc0, /* 0000111111 */
+	0x0f, 0xc0, /* 0000111111 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+
+	/* 219 0xdb '.' */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+
+	/* 220 0xdc '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+
+	/* 221 0xdd '.' */
+	0xf8, 0x00, /* 1111100000 */
+	0xf8, 0x00, /* 1111100000 */
+	0xf8, 0x00, /* 1111100000 */
+	0xf8, 0x00, /* 1111100000 */
+	0xf8, 0x00, /* 1111100000 */
+	0xf8, 0x00, /* 1111100000 */
+	0xf8, 0x00, /* 1111100000 */
+	0xf8, 0x00, /* 1111100000 */
+	0xf8, 0x00, /* 1111100000 */
+	0xf8, 0x00, /* 1111100000 */
+	0xf8, 0x00, /* 1111100000 */
+	0xf8, 0x00, /* 1111100000 */
+	0xf8, 0x00, /* 1111100000 */
+	0xf8, 0x00, /* 1111100000 */
+	0xf8, 0x00, /* 1111100000 */
+	0xf8, 0x00, /* 1111100000 */
+	0xf8, 0x00, /* 1111100000 */
+	0xf8, 0x00, /* 1111100000 */
+
+	/* 222 0xde '.' */
+	0x07, 0xc0, /* 0000011111 */
+	0x07, 0xc0, /* 0000011111 */
+	0x07, 0xc0, /* 0000011111 */
+	0x07, 0xc0, /* 0000011111 */
+	0x07, 0xc0, /* 0000011111 */
+	0x07, 0xc0, /* 0000011111 */
+	0x07, 0xc0, /* 0000011111 */
+	0x07, 0xc0, /* 0000011111 */
+	0x07, 0xc0, /* 0000011111 */
+	0x07, 0xc0, /* 0000011111 */
+	0x07, 0xc0, /* 0000011111 */
+	0x07, 0xc0, /* 0000011111 */
+	0x07, 0xc0, /* 0000011111 */
+	0x07, 0xc0, /* 0000011111 */
+	0x07, 0xc0, /* 0000011111 */
+	0x07, 0xc0, /* 0000011111 */
+	0x07, 0xc0, /* 0000011111 */
+	0x07, 0xc0, /* 0000011111 */
+
+	/* 223 0xdf '.' */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0xff, 0xc0, /* 1111111111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 224 0xe0 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x1c, 0x80, /* 0001110010 */
+	0x35, 0x80, /* 0011010110 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x63, 0x00, /* 0110001100 */
+	0x37, 0x80, /* 0011011110 */
+	0x1c, 0x80, /* 0001110010 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 225 0xe1 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x33, 0x00, /* 0011001100 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x63, 0x00, /* 0110001100 */
+	0x6f, 0x00, /* 0110111100 */
+	0x63, 0x00, /* 0110001100 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x63, 0x00, /* 0110001100 */
+	0x6e, 0x00, /* 0110111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 226 0xe2 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 227 0xe3 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 228 0xe4 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0xff, 0x80, /* 1111111110 */
+	0x60, 0x00, /* 0110000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x80, /* 0011000010 */
+	0x61, 0x80, /* 0110000110 */
+	0xff, 0x80, /* 1111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 229 0xe5 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x1f, 0xc0, /* 0001111111 */
+	0x36, 0x00, /* 0011011000 */
+	0x63, 0x00, /* 0110001100 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x33, 0x00, /* 0011001100 */
+	0x3e, 0x00, /* 0011111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 230 0xe6 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x73, 0x80, /* 0111001110 */
+	0x6d, 0x80, /* 0110110110 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0xc0, 0x00, /* 1100000000 */
+
+	/* 231 0xe7 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x01, 0x80, /* 0000000110 */
+	0x36, 0x40, /* 0011011001 */
+	0x5e, 0x00, /* 0101111000 */
+	0x8c, 0x00, /* 1000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 232 0xe8 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x33, 0x00, /* 0011001100 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x33, 0x00, /* 0011001100 */
+	0x1e, 0x00, /* 0001111000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 233 0xe9 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x1f, 0x00, /* 0001111100 */
+	0x31, 0x80, /* 0011000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x60, 0xc0, /* 0110000011 */
+	0x7f, 0xc0, /* 0111111111 */
+	0x7f, 0xc0, /* 0111111111 */
+	0x60, 0xc0, /* 0110000011 */
+	0x31, 0x80, /* 0011000110 */
+	0x31, 0x80, /* 0011000110 */
+	0x1f, 0x00, /* 0001111100 */
+	0x0e, 0x00, /* 0000111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 234 0xea '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x33, 0x00, /* 0011001100 */
+	0x61, 0x80, /* 0110000110 */
+	0xc0, 0xc0, /* 1100000011 */
+	0xc0, 0xc0, /* 1100000011 */
+	0xc0, 0xc0, /* 1100000011 */
+	0x61, 0x80, /* 0110000110 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0xf3, 0xc0, /* 1111001111 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 235 0xeb '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x07, 0x00, /* 0000011100 */
+	0x1f, 0x80, /* 0001111110 */
+	0x30, 0xc0, /* 0011000011 */
+	0x30, 0x00, /* 0011000000 */
+	0x18, 0x00, /* 0001100000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x3e, 0x00, /* 0011111000 */
+	0x66, 0x00, /* 0110011000 */
+	0xc3, 0x00, /* 1100001100 */
+	0xc3, 0x00, /* 1100001100 */
+	0xc3, 0x00, /* 1100001100 */
+	0x66, 0x00, /* 0110011000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 236 0xec '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x33, 0x00, /* 0011001100 */
+	0x6d, 0x80, /* 0110110110 */
+	0xcc, 0xc0, /* 1100110011 */
+	0xcc, 0xc0, /* 1100110011 */
+	0xcc, 0xc0, /* 1100110011 */
+	0xcc, 0xc0, /* 1100110011 */
+	0x6d, 0x80, /* 0110110110 */
+	0x33, 0x00, /* 0011001100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 237 0xed '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x01, 0x80, /* 0000000110 */
+	0x01, 0x80, /* 0000000110 */
+	0x03, 0x00, /* 0000001100 */
+	0x03, 0x00, /* 0000001100 */
+	0x37, 0x00, /* 0011011100 */
+	0x6d, 0x80, /* 0110110110 */
+	0xcc, 0xc0, /* 1100110011 */
+	0xcc, 0xc0, /* 1100110011 */
+	0xcc, 0xc0, /* 1100110011 */
+	0xcc, 0xc0, /* 1100110011 */
+	0x6d, 0x80, /* 0110110110 */
+	0x3b, 0x00, /* 0011101100 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x60, 0x00, /* 0110000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 238 0xee '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x03, 0x80, /* 0000001110 */
+	0x0e, 0x00, /* 0000111000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x3f, 0x80, /* 0011111110 */
+	0x3f, 0x80, /* 0011111110 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x18, 0x00, /* 0001100000 */
+	0x18, 0x00, /* 0001100000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x03, 0x80, /* 0000001110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 239 0xef '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x33, 0x00, /* 0011001100 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x61, 0x80, /* 0110000110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 240 0xf0 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 241 0xf1 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 242 0xf2 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0xe0, 0x00, /* 1110000000 */
+	0x38, 0x00, /* 0011100000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x03, 0x80, /* 0000001110 */
+	0x0e, 0x00, /* 0000111000 */
+	0x38, 0x00, /* 0011100000 */
+	0xe0, 0x00, /* 1110000000 */
+	0x00, 0x00, /* 0000000000 */
+	0xff, 0x00, /* 1111111100 */
+	0xff, 0x00, /* 1111111100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 243 0xf3 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x03, 0x80, /* 0000001110 */
+	0x0e, 0x00, /* 0000111000 */
+	0x38, 0x00, /* 0011100000 */
+	0xe0, 0x00, /* 1110000000 */
+	0x38, 0x00, /* 0011100000 */
+	0x0e, 0x00, /* 0000111000 */
+	0x03, 0x80, /* 0000001110 */
+	0x00, 0x00, /* 0000000000 */
+	0xff, 0x80, /* 1111111110 */
+	0xff, 0x80, /* 1111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 244 0xf4 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x30, 0x00, /* 0011000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 245 0xf5 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x03, 0x00, /* 0000001100 */
+	0x03, 0x00, /* 0000001100 */
+	0x03, 0x00, /* 0000001100 */
+	0x03, 0x00, /* 0000001100 */
+	0x03, 0x00, /* 0000001100 */
+	0x03, 0x00, /* 0000001100 */
+	0x03, 0x00, /* 0000001100 */
+	0x03, 0x00, /* 0000001100 */
+	0x03, 0x00, /* 0000001100 */
+	0x03, 0x00, /* 0000001100 */
+	0x03, 0x00, /* 0000001100 */
+	0x03, 0x00, /* 0000001100 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 246 0xf6 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 247 0xf7 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x38, 0x00, /* 0011100000 */
+	0x6c, 0x00, /* 0110110000 */
+	0x06, 0xc0, /* 0000011011 */
+	0x03, 0x80, /* 0000001110 */
+	0x38, 0x00, /* 0011100000 */
+	0x6c, 0x00, /* 0110110000 */
+	0x06, 0xc0, /* 0000011011 */
+	0x03, 0x80, /* 0000001110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 248 0xf8 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x33, 0x00, /* 0011001100 */
+	0x33, 0x00, /* 0011001100 */
+	0x1e, 0x00, /* 0001111000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 249 0xf9 '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 250 0xfa '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 251 0xfb '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x0f, 0xc0, /* 0000111111 */
+	0x0f, 0xc0, /* 0000111111 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0xcc, 0x00, /* 1100110000 */
+	0x6c, 0x00, /* 0110110000 */
+	0x3c, 0x00, /* 0011110000 */
+	0x1c, 0x00, /* 0001110000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 252 0xfc '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x27, 0x00, /* 0010011100 */
+	0x7b, 0x00, /* 0111101100 */
+	0x31, 0x00, /* 0011000100 */
+	0x31, 0x00, /* 0011000100 */
+	0x31, 0x00, /* 0011000100 */
+	0x7b, 0x80, /* 0111101110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 253 0xfd '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x1e, 0x00, /* 0001111000 */
+	0x3f, 0x00, /* 0011111100 */
+	0x63, 0x00, /* 0110001100 */
+	0x43, 0x00, /* 0100001100 */
+	0x06, 0x00, /* 0000011000 */
+	0x0c, 0x00, /* 0000110000 */
+	0x18, 0x00, /* 0001100000 */
+	0x30, 0x80, /* 0011000010 */
+	0x7f, 0x80, /* 0111111110 */
+	0x7f, 0x80, /* 0111111110 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 254 0xfe '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x3f, 0x00, /* 0011111100 */
+	0x3f, 0x00, /* 0011111100 */
+	0x3f, 0x00, /* 0011111100 */
+	0x3f, 0x00, /* 0011111100 */
+	0x3f, 0x00, /* 0011111100 */
+	0x3f, 0x00, /* 0011111100 */
+	0x3f, 0x00, /* 0011111100 */
+	0x3f, 0x00, /* 0011111100 */
+	0x3f, 0x00, /* 0011111100 */
+	0x3f, 0x00, /* 0011111100 */
+	0x3f, 0x00, /* 0011111100 */
+	0x3f, 0x00, /* 0011111100 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+	/* 255 0xff '.' */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+	0x00, 0x00, /* 0000000000 */
+
+};
+
+
+struct font_desc font_10x18 = {
+	FONT10x18_IDX,
+	"10x18",
+	10,
+	18,
+	fontdata_10x18,
+#ifdef __sparc__
+	5
+#else
+	-1
+#endif
+};
diff --git a/drivers/video/console/font_7x14.c b/drivers/video/console/font_7x14.c
new file mode 100644
index 0000000..1fa7fcf
--- /dev/null
+++ b/drivers/video/console/font_7x14.c
@@ -0,0 +1,4118 @@
+/**************************************/
+/* this file adapted from font_8x16.c */
+/* by Jurriaan Kalkman 05-2005        */
+/**************************************/
+
+#include <linux/font.h>
+
+#define FONTDATAMAX 3584
+
+static unsigned char fontdata_7x14[FONTDATAMAX] = {
+
+	/* 0 0x00 '^@' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 1 0x01 '^A' */
+	0x00, /* 0000000 */
+	0x7c, /* 0111110 */
+	0x82, /* 1000001 */
+	0xaa, /* 1010101 */
+	0x82, /* 1000001 */
+	0x82, /* 1000001 */
+	0xba, /* 1011101 */
+	0x92, /* 1001001 */
+	0x82, /* 1000001 */
+	0x7c, /* 0111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 2 0x02 '^B' */
+	0x00, /* 0000000 */
+	0x7c, /* 0111110 */
+	0xfe, /* 1111111 */
+	0xd6, /* 1101011 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xc6, /* 1100011 */
+	0xee, /* 1110111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0x7c, /* 0111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 3 0x03 '^C' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x6c, /* 0110110 */
+	0x7c, /* 0111110 */
+	0xfe, /* 1111111 */
+	0x7c, /* 0111110 */
+	0x38, /* 0011100 */
+	0x18, /* 0001100 */
+	0x10, /* 0001000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 4 0x04 '^D' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x10, /* 0001000 */
+	0x38, /* 0011100 */
+	0x7c, /* 0111110 */
+	0xfe, /* 1111111 */
+	0x7c, /* 0111110 */
+	0x38, /* 0011100 */
+	0x10, /* 0001000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 5 0x05 '^E' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x38, /* 0011100 */
+	0x38, /* 0011100 */
+	0x38, /* 0011100 */
+	0xee, /* 1110111 */
+	0xee, /* 1110111 */
+	0xee, /* 1110111 */
+	0x10, /* 0001000 */
+	0x10, /* 0001000 */
+	0x38, /* 0011100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 6 0x06 '^F' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x10, /* 0001000 */
+	0x38, /* 0011100 */
+	0x7c, /* 0111110 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0x7c, /* 0111110 */
+	0x10, /* 0001000 */
+	0x10, /* 0001000 */
+	0x38, /* 0011100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 7 0x07 '^G' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x18, /* 0001100 */
+	0x3c, /* 0011110 */
+	0x3c, /* 0011110 */
+	0x18, /* 0001100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 8 0x08 '^H' */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xe6, /* 1110011 */
+	0xc2, /* 1100001 */
+	0xc2, /* 1100001 */
+	0xe6, /* 1110011 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+
+	/* 9 0x09 '^I' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x38, /* 0011100 */
+	0x6c, /* 0110110 */
+	0x44, /* 0100010 */
+	0x6c, /* 0110110 */
+	0x38, /* 0011100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 10 0x0a '^J' */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xc6, /* 1100011 */
+	0x92, /* 1001001 */
+	0xba, /* 1011101 */
+	0x92, /* 1001001 */
+	0xc6, /* 1100011 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+
+	/* 11 0x0b '^K' */
+	0x00, /* 0000000 */
+	0x1e, /* 0001111 */
+	0x0e, /* 0000111 */
+	0x1a, /* 0001101 */
+	0x1a, /* 0001101 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 12 0x0c '^L' */
+	0x00, /* 0000000 */
+	0x3c, /* 0011110 */
+	0x66, /* 0110011 */
+	0x66, /* 0110011 */
+	0x66, /* 0110011 */
+	0x66, /* 0110011 */
+	0x3c, /* 0011110 */
+	0x18, /* 0001100 */
+	0x7e, /* 0111111 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 13 0x0d '^M' */
+	0x00, /* 0000000 */
+	0x3e, /* 0011111 */
+	0x36, /* 0011011 */
+	0x3e, /* 0011111 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x70, /* 0111000 */
+	0xf0, /* 1111000 */
+	0xe0, /* 1110000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 14 0x0e '^N' */
+	0x00, /* 0000000 */
+	0x7e, /* 0111111 */
+	0x66, /* 0110011 */
+	0x7e, /* 0111111 */
+	0x66, /* 0110011 */
+	0x66, /* 0110011 */
+	0x66, /* 0110011 */
+	0x66, /* 0110011 */
+	0x6e, /* 0110111 */
+	0xee, /* 1110111 */
+	0xec, /* 1110110 */
+	0xc0, /* 1100000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 15 0x0f '^O' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x10, /* 0001000 */
+	0x10, /* 0001000 */
+	0xd6, /* 1101011 */
+	0x38, /* 0011100 */
+	0xee, /* 1110111 */
+	0x38, /* 0011100 */
+	0xd6, /* 1101011 */
+	0x10, /* 0001000 */
+	0x10, /* 0001000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 16 0x10 '^P' */
+	0x00, /* 0000000 */
+	0x80, /* 1000000 */
+	0xc0, /* 1100000 */
+	0xe0, /* 1110000 */
+	0xf0, /* 1111000 */
+	0xfc, /* 1111110 */
+	0xf0, /* 1111000 */
+	0xe0, /* 1110000 */
+	0xc0, /* 1100000 */
+	0x80, /* 1000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 17 0x11 '^Q' */
+	0x00, /* 0000000 */
+	0x04, /* 0000010 */
+	0x0c, /* 0000110 */
+	0x1c, /* 0001110 */
+	0x3c, /* 0011110 */
+	0xfc, /* 1111110 */
+	0x3c, /* 0011110 */
+	0x1c, /* 0001110 */
+	0x0c, /* 0000110 */
+	0x04, /* 0000010 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 18 0x12 '^R' */
+	0x00, /* 0000000 */
+	0x18, /* 0001100 */
+	0x3c, /* 0011110 */
+	0x7e, /* 0111111 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x7e, /* 0111111 */
+	0x3c, /* 0011110 */
+	0x18, /* 0001100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 19 0x13 '^S' */
+	0x00, /* 0000000 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x00, /* 0000000 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 20 0x14 '^T' */
+	0x00, /* 0000000 */
+	0x7e, /* 0111111 */
+	0xd4, /* 1101010 */
+	0xd4, /* 1101010 */
+	0xd4, /* 1101010 */
+	0x74, /* 0111010 */
+	0x14, /* 0001010 */
+	0x14, /* 0001010 */
+	0x14, /* 0001010 */
+	0x14, /* 0001010 */
+	0x16, /* 0001011 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 21 0x15 '^U' */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0x60, /* 0110000 */
+	0x38, /* 0011100 */
+	0x6c, /* 0110110 */
+	0xc6, /* 1100011 */
+	0xc6, /* 1100011 */
+	0x6c, /* 0110110 */
+	0x38, /* 0011100 */
+	0x18, /* 0001100 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 22 0x16 '^V' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xfc, /* 1111110 */
+	0xfc, /* 1111110 */
+	0xfc, /* 1111110 */
+	0xfc, /* 1111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 23 0x17 '^W' */
+	0x00, /* 0000000 */
+	0x18, /* 0001100 */
+	0x3c, /* 0011110 */
+	0x7e, /* 0111111 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x7e, /* 0111111 */
+	0x3c, /* 0011110 */
+	0x18, /* 0001100 */
+	0x7e, /* 0111111 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 24 0x18 '^X' */
+	0x00, /* 0000000 */
+	0x18, /* 0001100 */
+	0x3c, /* 0011110 */
+	0x7e, /* 0111111 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 25 0x19 '^Y' */
+	0x00, /* 0000000 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x7e, /* 0111111 */
+	0x3c, /* 0011110 */
+	0x18, /* 0001100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 26 0x1a '^Z' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x30, /* 0011000 */
+	0x18, /* 0001100 */
+	0xfc, /* 1111110 */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 27 0x1b '^[' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x30, /* 0011000 */
+	0x60, /* 0110000 */
+	0xfc, /* 1111110 */
+	0x60, /* 0110000 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 28 0x1c '^\' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xfc, /* 1111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 29 0x1d '^]' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x28, /* 0010100 */
+	0x6c, /* 0110110 */
+	0xfe, /* 1111111 */
+	0x6c, /* 0110110 */
+	0x28, /* 0010100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 30 0x1e '^^' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x78, /* 0111100 */
+	0x78, /* 0111100 */
+	0xfc, /* 1111110 */
+	0xfc, /* 1111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 31 0x1f '^_' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xfc, /* 1111110 */
+	0xfc, /* 1111110 */
+	0x78, /* 0111100 */
+	0x78, /* 0111100 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 32 0x20 ' ' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 33 0x21 '!' */
+	0x00, /* 0000000 */
+	0x18, /* 0001100 */
+	0x3c, /* 0011110 */
+	0x3c, /* 0011110 */
+	0x3c, /* 0011110 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x00, /* 0000000 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 34 0x22 '"' */
+	0x00, /* 0000000 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x28, /* 0010100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 35 0x23 '#' */
+	0x00, /* 0000000 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 36 0x24 '$' */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xc4, /* 1100010 */
+	0xc0, /* 1100000 */
+	0x78, /* 0111100 */
+	0x0c, /* 0000110 */
+	0x8c, /* 1000110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+
+	/* 37 0x25 '%' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xc0, /* 1100000 */
+	0xc4, /* 1100010 */
+	0x0c, /* 0000110 */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x60, /* 0110000 */
+	0xcc, /* 1100110 */
+	0x8c, /* 1000110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 38 0x26 '&' */
+	0x00, /* 0000000 */
+	0x38, /* 0011100 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x38, /* 0011100 */
+	0x78, /* 0111100 */
+	0xde, /* 1101111 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xdc, /* 1101110 */
+	0x76, /* 0111011 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 39 0x27 ''' */
+	0x00, /* 0000000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x60, /* 0110000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 40 0x28 '(' */
+	0x00, /* 0000000 */
+	0x0c, /* 0000110 */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x18, /* 0001100 */
+	0x0c, /* 0000110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 41 0x29 ')' */
+	0x00, /* 0000000 */
+	0x30, /* 0011000 */
+	0x18, /* 0001100 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 42 0x2a '*' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x6c, /* 0110110 */
+	0x38, /* 0011100 */
+	0xfe, /* 1111111 */
+	0x38, /* 0011100 */
+	0x6c, /* 0110110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 43 0x2b '+' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x10, /* 0001000 */
+	0x10, /* 0001000 */
+	0x7c, /* 0111110 */
+	0x10, /* 0001000 */
+	0x10, /* 0001000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 44 0x2c ',' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 45 0x2d '-' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xfc, /* 1111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 46 0x2e '.' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 47 0x2f '/' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x04, /* 0000010 */
+	0x0c, /* 0000110 */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x60, /* 0110000 */
+	0xc0, /* 1100000 */
+	0x80, /* 1000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 48 0x30 '0' */
+	0x00, /* 0000000 */
+	0x30, /* 0011000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xdc, /* 1101110 */
+	0xec, /* 1110110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 49 0x31 '1' */
+	0x00, /* 0000000 */
+	0x18, /* 0001100 */
+	0x38, /* 0011100 */
+	0x78, /* 0111100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x7c, /* 0111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 50 0x32 '2' */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0x0c, /* 0000110 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x60, /* 0110000 */
+	0xc0, /* 1100000 */
+	0xcc, /* 1100110 */
+	0xfc, /* 1111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 51 0x33 '3' */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x38, /* 0011100 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 52 0x34 '4' */
+	0x00, /* 0000000 */
+	0x0c, /* 0000110 */
+	0x1c, /* 0001110 */
+	0x3c, /* 0011110 */
+	0x6c, /* 0110110 */
+	0xcc, /* 1100110 */
+	0xfe, /* 1111111 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 53 0x35 '5' */
+	0x00, /* 0000000 */
+	0xfc, /* 1111110 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xf8, /* 1111100 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 54 0x36 '6' */
+	0x00, /* 0000000 */
+	0x30, /* 0011000 */
+	0x60, /* 0110000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xf8, /* 1111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 55 0x37 '7' */
+	0x00, /* 0000000 */
+	0xfc, /* 1111110 */
+	0xcc, /* 1100110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 56 0x38 '8' */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 57 0x39 '9' */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x7c, /* 0111110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x18, /* 0001100 */
+	0x70, /* 0111000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 58 0x3a ':' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 59 0x3b ';' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 60 0x3c '<' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x04, /* 0000010 */
+	0x0c, /* 0000110 */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x60, /* 0110000 */
+	0x30, /* 0011000 */
+	0x18, /* 0001100 */
+	0x0c, /* 0000110 */
+	0x04, /* 0000010 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 61 0x3d '=' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x7c, /* 0111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x7c, /* 0111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 62 0x3e '>' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x40, /* 0100000 */
+	0x60, /* 0110000 */
+	0x30, /* 0011000 */
+	0x18, /* 0001100 */
+	0x0c, /* 0000110 */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x60, /* 0110000 */
+	0x40, /* 0100000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 63 0x3f '?' */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 64 0x40 '@' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xdc, /* 1101110 */
+	0xdc, /* 1101110 */
+	0xd8, /* 1101100 */
+	0xc0, /* 1100000 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 65 0x41 'A' */
+	0x00, /* 0000000 */
+	0x30, /* 0011000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xfc, /* 1111110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 66 0x42 'B' */
+	0x00, /* 0000000 */
+	0xf8, /* 1111100 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x78, /* 0111100 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0xf8, /* 1111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 67 0x43 'C' */
+	0x00, /* 0000000 */
+	0x38, /* 0011100 */
+	0x6c, /* 0110110 */
+	0xc4, /* 1100010 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc4, /* 1100010 */
+	0x6c, /* 0110110 */
+	0x38, /* 0011100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 68 0x44 'D' */
+	0x00, /* 0000000 */
+	0xf0, /* 1111000 */
+	0xd8, /* 1101100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xd8, /* 1101100 */
+	0xf0, /* 1111000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 69 0x45 'E' */
+	0x00, /* 0000000 */
+	0x7c, /* 0111110 */
+	0x6c, /* 0110110 */
+	0x64, /* 0110010 */
+	0x68, /* 0110100 */
+	0x78, /* 0111100 */
+	0x68, /* 0110100 */
+	0x60, /* 0110000 */
+	0x64, /* 0110010 */
+	0x6c, /* 0110110 */
+	0x7c, /* 0111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 70 0x46 'F' */
+	0x00, /* 0000000 */
+	0x7c, /* 0111110 */
+	0x64, /* 0110010 */
+	0x60, /* 0110000 */
+	0x68, /* 0110100 */
+	0x78, /* 0111100 */
+	0x68, /* 0110100 */
+	0x60, /* 0110000 */
+	0x60, /* 0110000 */
+	0x60, /* 0110000 */
+	0x70, /* 0111000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 71 0x47 'G' */
+	0x00, /* 0000000 */
+	0x38, /* 0011100 */
+	0x6c, /* 0110110 */
+	0xc4, /* 1100010 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xdc, /* 1101110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x6c, /* 0110110 */
+	0x34, /* 0011010 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 72 0x48 'H' */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xfc, /* 1111110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 73 0x49 'I' */
+	0x00, /* 0000000 */
+	0x3c, /* 0011110 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x3c, /* 0011110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 74 0x4a 'J' */
+	0x00, /* 0000000 */
+	0x1c, /* 0001110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 75 0x4b 'K' */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xd8, /* 1101100 */
+	0xf0, /* 1111000 */
+	0xf0, /* 1111000 */
+	0xd8, /* 1101100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 76 0x4c 'L' */
+	0x00, /* 0000000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc4, /* 1100010 */
+	0xcc, /* 1100110 */
+	0xfc, /* 1111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 77 0x4d 'M' */
+	0x00, /* 0000000 */
+	0xc6, /* 1100011 */
+	0xee, /* 1110111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xd6, /* 1101011 */
+	0xc6, /* 1100011 */
+	0xc6, /* 1100011 */
+	0xc6, /* 1100011 */
+	0xc6, /* 1100011 */
+	0xc6, /* 1100011 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 78 0x4e 'N' */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0xec, /* 1110110 */
+	0xec, /* 1110110 */
+	0xfc, /* 1111110 */
+	0xdc, /* 1101110 */
+	0xdc, /* 1101110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 79 0x4f 'O' */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 80 0x50 'P' */
+	0x00, /* 0000000 */
+	0xf8, /* 1111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xf8, /* 1111100 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 81 0x51 'Q' */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xdc, /* 1101110 */
+	0x78, /* 0111100 */
+	0x18, /* 0001100 */
+	0x1c, /* 0001110 */
+	0x00, /* 0000000 */
+
+	/* 82 0x52 'R' */
+	0x00, /* 0000000 */
+	0xf8, /* 1111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xf8, /* 1111100 */
+	0xd8, /* 1101100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 83 0x53 'S' */
+	0x00, /* 0000000 */
+	0x7c, /* 0111110 */
+	0xc4, /* 1100010 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0x60, /* 0110000 */
+	0x38, /* 0011100 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x8c, /* 1000110 */
+	0xf8, /* 1111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 84 0x54 'T' */
+	0x00, /* 0000000 */
+	0xfc, /* 1111110 */
+	0xfc, /* 1111110 */
+	0xb4, /* 1011010 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 85 0x55 'U' */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 86 0x56 'V' */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x78, /* 0111100 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 87 0x57 'W' */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xfc, /* 1111110 */
+	0xfc, /* 1111110 */
+	0x48, /* 0100100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 88 0x58 'X' */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x78, /* 0111100 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x78, /* 0111100 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 89 0x59 'Y' */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 90 0x5a 'Z' */
+	0x00, /* 0000000 */
+	0xfc, /* 1111110 */
+	0xcc, /* 1100110 */
+	0x8c, /* 1000110 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x60, /* 0110000 */
+	0xc4, /* 1100010 */
+	0xcc, /* 1100110 */
+	0xfc, /* 1111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 91 0x5b '[' */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0x60, /* 0110000 */
+	0x60, /* 0110000 */
+	0x60, /* 0110000 */
+	0x60, /* 0110000 */
+	0x60, /* 0110000 */
+	0x60, /* 0110000 */
+	0x60, /* 0110000 */
+	0x60, /* 0110000 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 92 0x5c '\' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x80, /* 1000000 */
+	0xc0, /* 1100000 */
+	0xe0, /* 1110000 */
+	0x70, /* 0111000 */
+	0x38, /* 0011100 */
+	0x1c, /* 0001110 */
+	0x0c, /* 0000110 */
+	0x04, /* 0000010 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 93 0x5d ']' */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 94 0x5e '^' */
+	0x10, /* 0001000 */
+	0x38, /* 0011100 */
+	0x6c, /* 0110110 */
+	0xc6, /* 1100011 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 95 0x5f '_' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xfe, /* 1111111 */
+	0x00, /* 0000000 */
+
+	/* 96 0x60 '`' */
+	0x00, /* 0000000 */
+	0x60, /* 0110000 */
+	0x30, /* 0011000 */
+	0x18, /* 0001100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 97 0x61 'a' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0x0c, /* 0000110 */
+	0x7c, /* 0111110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x76, /* 0111011 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 98 0x62 'b' */
+	0x00, /* 0000000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xf0, /* 1111000 */
+	0xd8, /* 1101100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xf8, /* 1111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 99 0x63 'c' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 100 0x64 'd' */
+	0x00, /* 0000000 */
+	0x1c, /* 0001110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x3c, /* 0011110 */
+	0x6c, /* 0110110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x76, /* 0111011 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 101 0x65 'e' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xfc, /* 1111110 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 102 0x66 'f' */
+	0x00, /* 0000000 */
+	0x38, /* 0011100 */
+	0x6c, /* 0110110 */
+	0x64, /* 0110010 */
+	0x60, /* 0110000 */
+	0xf0, /* 1111000 */
+	0x60, /* 0110000 */
+	0x60, /* 0110000 */
+	0x60, /* 0110000 */
+	0x60, /* 0110000 */
+	0xf0, /* 1111000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 103 0x67 'g' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x76, /* 0111011 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x7c, /* 0111110 */
+	0x0c, /* 0000110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+
+	/* 104 0x68 'h' */
+	0x00, /* 0000000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xd8, /* 1101100 */
+	0xec, /* 1110110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 105 0x69 'i' */
+	0x00, /* 0000000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x70, /* 0111000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 106 0x6a 'j' */
+	0x00, /* 0000000 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x00, /* 0000000 */
+	0x1c, /* 0001110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+
+	/* 107 0x6b 'k' */
+	0x00, /* 0000000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xcc, /* 1100110 */
+	0xd8, /* 1101100 */
+	0xf0, /* 1111000 */
+	0xf0, /* 1111000 */
+	0xd8, /* 1101100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 108 0x6c 'l' */
+	0x00, /* 0000000 */
+	0x70, /* 0111000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 109 0x6d 'm' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xec, /* 1110110 */
+	0xfe, /* 1111111 */
+	0xd6, /* 1101011 */
+	0xd6, /* 1101011 */
+	0xd6, /* 1101011 */
+	0xd6, /* 1101011 */
+	0xd6, /* 1101011 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 110 0x6e 'n' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xb8, /* 1011100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 111 0x6f 'o' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 112 0x70 'p' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xb8, /* 1011100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xf8, /* 1111100 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+
+	/* 113 0x71 'q' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x74, /* 0111010 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x7c, /* 0111110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+
+	/* 114 0x72 'r' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xb8, /* 1011100 */
+	0xec, /* 1110110 */
+	0xcc, /* 1100110 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 115 0x73 's' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0x60, /* 0110000 */
+	0x30, /* 0011000 */
+	0x18, /* 0001100 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 116 0x74 't' */
+	0x00, /* 0000000 */
+	0x10, /* 0001000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0xfc, /* 1111110 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x36, /* 0011011 */
+	0x1c, /* 0001110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 117 0x75 'u' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x76, /* 0111011 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 118 0x76 'v' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 119 0x77 'w' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xc6, /* 1100011 */
+	0xc6, /* 1100011 */
+	0xd6, /* 1101011 */
+	0xd6, /* 1101011 */
+	0xd6, /* 1101011 */
+	0xfe, /* 1111111 */
+	0x6c, /* 0110110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 120 0x78 'x' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x30, /* 0011000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 121 0x79 'y' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x7c, /* 0111110 */
+	0x0c, /* 0000110 */
+	0x18, /* 0001100 */
+	0xf0, /* 1111000 */
+
+	/* 122 0x7a 'z' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xfc, /* 1111110 */
+	0xcc, /* 1100110 */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x60, /* 0110000 */
+	0xcc, /* 1100110 */
+	0xfc, /* 1111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 123 0x7b '{' */
+	0x00, /* 0000000 */
+	0x1c, /* 0001110 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0xe0, /* 1110000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x1c, /* 0001110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 124 0x7c '|' */
+	0x00, /* 0000000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 125 0x7d '}' */
+	0x00, /* 0000000 */
+	0x70, /* 0111000 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x0e, /* 0000111 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x70, /* 0111000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 126 0x7e '~' */
+	0x00, /* 0000000 */
+	0xec, /* 1110110 */
+	0xb8, /* 1011100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 127 0x7f '' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x10, /* 0001000 */
+	0x38, /* 0011100 */
+	0x6c, /* 0110110 */
+	0xc6, /* 1100011 */
+	0xc6, /* 1100011 */
+	0xc6, /* 1100011 */
+	0xfe, /* 1111111 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 128 0x80 '€' */
+	0x00, /* 0000000 */
+	0x38, /* 0011100 */
+	0x6c, /* 0110110 */
+	0xc4, /* 1100010 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc4, /* 1100010 */
+	0x6c, /* 0110110 */
+	0x38, /* 0011100 */
+	0x18, /* 0001100 */
+	0x70, /* 0111000 */
+	0x00, /* 0000000 */
+
+	/* 129 0x81 '' */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x76, /* 0111011 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 130 0x82 '‚' */
+	0x0c, /* 0000110 */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xfc, /* 1111110 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 131 0x83 'ƒ' */
+	0x10, /* 0001000 */
+	0x38, /* 0011100 */
+	0x6c, /* 0110110 */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0x0c, /* 0000110 */
+	0x7c, /* 0111110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x76, /* 0111011 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 132 0x84 '„' */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0x0c, /* 0000110 */
+	0x7c, /* 0111110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x76, /* 0111011 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 133 0x85 '…' */
+	0x60, /* 0110000 */
+	0x30, /* 0011000 */
+	0x18, /* 0001100 */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0x0c, /* 0000110 */
+	0x7c, /* 0111110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x76, /* 0111011 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 134 0x86 '†' */
+	0x38, /* 0011100 */
+	0x6c, /* 0110110 */
+	0x38, /* 0011100 */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0x0c, /* 0000110 */
+	0x7c, /* 0111110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x76, /* 0111011 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 135 0x87 '‡' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0xe0, /* 1110000 */
+
+	/* 136 0x88 'ˆ' */
+	0x10, /* 0001000 */
+	0x38, /* 0011100 */
+	0x6c, /* 0110110 */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xfc, /* 1111110 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 137 0x89 '‰' */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xfc, /* 1111110 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 138 0x8a 'Š' */
+	0xc0, /* 1100000 */
+	0x60, /* 0110000 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xfc, /* 1111110 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 139 0x8b '‹' */
+	0x00, /* 0000000 */
+	0x6c, /* 0110110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x38, /* 0011100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x3c, /* 0011110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 140 0x8c 'Œ' */
+	0x30, /* 0011000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x70, /* 0111000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 141 0x8d '' */
+	0xc0, /* 1100000 */
+	0x60, /* 0110000 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x70, /* 0111000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 142 0x8e 'Ž' */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x30, /* 0011000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xfc, /* 1111110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 143 0x8f '' */
+	0x30, /* 0011000 */
+	0x48, /* 0100100 */
+	0x48, /* 0100100 */
+	0x30, /* 0011000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xfc, /* 1111110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 144 0x90 '' */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0xfc, /* 1111110 */
+	0xcc, /* 1100110 */
+	0xc4, /* 1100010 */
+	0xd0, /* 1101000 */
+	0xf0, /* 1111000 */
+	0xd0, /* 1101000 */
+	0xc4, /* 1100010 */
+	0xcc, /* 1100110 */
+	0xfc, /* 1111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 145 0x91 '‘' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xec, /* 1110110 */
+	0x36, /* 0011011 */
+	0x36, /* 0011011 */
+	0x7e, /* 0111111 */
+	0xd8, /* 1101100 */
+	0xd8, /* 1101100 */
+	0x6e, /* 0110111 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 146 0x92 '’' */
+	0x00, /* 0000000 */
+	0x3e, /* 0011111 */
+	0x6c, /* 0110110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xfe, /* 1111111 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xce, /* 1100111 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 147 0x93 '“' */
+	0x10, /* 0001000 */
+	0x38, /* 0011100 */
+	0x6c, /* 0110110 */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 148 0x94 '”' */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 149 0x95 '•' */
+	0xc0, /* 1100000 */
+	0x60, /* 0110000 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 150 0x96 '–' */
+	0x30, /* 0011000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x76, /* 0111011 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 151 0x97 '—' */
+	0x60, /* 0110000 */
+	0x30, /* 0011000 */
+	0x18, /* 0001100 */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x76, /* 0111011 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 152 0x98 '˜' */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x7c, /* 0111110 */
+	0x0c, /* 0000110 */
+	0x18, /* 0001100 */
+	0x70, /* 0111000 */
+
+	/* 153 0x99 '™' */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 154 0x9a 'š' */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 155 0x9b '›' */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x7c, /* 0111110 */
+	0xcc, /* 1100110 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xcc, /* 1100110 */
+	0x7c, /* 0111110 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 156 0x9c 'œ' */
+	0x38, /* 0011100 */
+	0x6c, /* 0110110 */
+	0x64, /* 0110010 */
+	0x60, /* 0110000 */
+	0xf0, /* 1111000 */
+	0x60, /* 0110000 */
+	0x60, /* 0110000 */
+	0x60, /* 0110000 */
+	0x60, /* 0110000 */
+	0xe6, /* 1110011 */
+	0xfc, /* 1111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 157 0x9d '' */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x30, /* 0011000 */
+	0xfc, /* 1111110 */
+	0x30, /* 0011000 */
+	0xfc, /* 1111110 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 158 0x9e 'ž' */
+	0xf8, /* 1111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xf8, /* 1111100 */
+	0xc4, /* 1100010 */
+	0xcc, /* 1100110 */
+	0xde, /* 1101111 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xc6, /* 1100011 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 159 0x9f 'Ÿ' */
+	0x1c, /* 0001110 */
+	0x36, /* 0011011 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0xfc, /* 1111110 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0xb0, /* 1011000 */
+	0xe0, /* 1110000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 160 0xa0 ' ' */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x60, /* 0110000 */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0x0c, /* 0000110 */
+	0x7c, /* 0111110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x76, /* 0111011 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 161 0xa1 '¡' */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x60, /* 0110000 */
+	0x00, /* 0000000 */
+	0x70, /* 0111000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 162 0xa2 '¢' */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x60, /* 0110000 */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 163 0xa3 '£' */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x60, /* 0110000 */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x76, /* 0111011 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 164 0xa4 '¤' */
+	0x00, /* 0000000 */
+	0x76, /* 0111011 */
+	0xdc, /* 1101110 */
+	0x00, /* 0000000 */
+	0xb8, /* 1011100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 165 0xa5 '¥' */
+	0x76, /* 0111011 */
+	0xdc, /* 1101110 */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0xec, /* 1110110 */
+	0xec, /* 1110110 */
+	0xfc, /* 1111110 */
+	0xdc, /* 1101110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 166 0xa6 '¦' */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xd8, /* 1101100 */
+	0xd8, /* 1101100 */
+	0x7c, /* 0111110 */
+	0x00, /* 0000000 */
+	0xfc, /* 1111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 167 0xa7 '§' */
+	0x00, /* 0000000 */
+	0x70, /* 0111000 */
+	0xd8, /* 1101100 */
+	0xd8, /* 1101100 */
+	0x70, /* 0111000 */
+	0x00, /* 0000000 */
+	0xf8, /* 1111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 168 0xa8 '¨' */
+	0x00, /* 0000000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x60, /* 0110000 */
+	0xc0, /* 1100000 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 169 0xa9 '©' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xfc, /* 1111110 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 170 0xaa 'ª' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xfc, /* 1111110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 171 0xab '«' */
+	0x60, /* 0110000 */
+	0xe0, /* 1110000 */
+	0x62, /* 0110001 */
+	0x66, /* 0110011 */
+	0x6c, /* 0110110 */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x60, /* 0110000 */
+	0xc0, /* 1100000 */
+	0xb8, /* 1011100 */
+	0x4c, /* 0100110 */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x7c, /* 0111110 */
+
+	/* 172 0xac '¬' */
+	0x60, /* 0110000 */
+	0xe0, /* 1110000 */
+	0x62, /* 0110001 */
+	0x66, /* 0110011 */
+	0x6c, /* 0110110 */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x6c, /* 0110110 */
+	0xdc, /* 1101110 */
+	0xb4, /* 1011010 */
+	0x7e, /* 0111111 */
+	0x0c, /* 0000110 */
+	0x0c, /* 0000110 */
+	0x00, /* 0000000 */
+
+	/* 173 0xad '­' */
+	0x00, /* 0000000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x78, /* 0111100 */
+	0x78, /* 0111100 */
+	0x78, /* 0111100 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 174 0xae '®' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x36, /* 0011011 */
+	0x6c, /* 0110110 */
+	0xd8, /* 1101100 */
+	0x6c, /* 0110110 */
+	0x36, /* 0011011 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 175 0xaf '¯' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xd8, /* 1101100 */
+	0x6c, /* 0110110 */
+	0x36, /* 0011011 */
+	0x6c, /* 0110110 */
+	0xd8, /* 1101100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 176 0xb0 '°' */
+	0x88, /* 1000100 */
+	0x22, /* 0010001 */
+	0x88, /* 1000100 */
+	0x22, /* 0010001 */
+	0x88, /* 1000100 */
+	0x22, /* 0010001 */
+	0x88, /* 1000100 */
+	0x22, /* 0010001 */
+	0x88, /* 1000100 */
+	0x22, /* 0010001 */
+	0x88, /* 1000100 */
+	0x22, /* 0010001 */
+	0x88, /* 1000100 */
+	0x22, /* 0010001 */
+
+	/* 177 0xb1 '±' */
+	0x54, /* 0101010 */
+	0xaa, /* 1010101 */
+	0x54, /* 0101010 */
+	0xaa, /* 1010101 */
+	0x54, /* 0101010 */
+	0xaa, /* 1010101 */
+	0x54, /* 0101010 */
+	0xaa, /* 1010101 */
+	0x54, /* 0101010 */
+	0xaa, /* 1010101 */
+	0x54, /* 0101010 */
+	0xaa, /* 1010101 */
+	0x54, /* 0101010 */
+	0xaa, /* 1010101 */
+
+	/* 178 0xb2 '²' */
+	0xee, /* 1110111 */
+	0xba, /* 1011101 */
+	0xee, /* 1110111 */
+	0xba, /* 1011101 */
+	0xee, /* 1110111 */
+	0xba, /* 1011101 */
+	0xee, /* 1110111 */
+	0xba, /* 1011101 */
+	0xee, /* 1110111 */
+	0xba, /* 1011101 */
+	0xee, /* 1110111 */
+	0xba, /* 1011101 */
+	0xee, /* 1110111 */
+	0xba, /* 1011101 */
+
+	/* 179 0xb3 '³' */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+
+	/* 180 0xb4 '´' */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0xf0, /* 1111000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+
+	/* 181 0xb5 'µ' */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0xf0, /* 1111000 */
+	0x30, /* 0011000 */
+	0xf0, /* 1111000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+
+	/* 182 0xb6 '¶' */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0xec, /* 1110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+
+	/* 183 0xb7 '·' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xfc, /* 1111110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+
+	/* 184 0xb8 '¸' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xf0, /* 1111000 */
+	0x30, /* 0011000 */
+	0xf0, /* 1111000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+
+	/* 185 0xb9 '¹' */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0xec, /* 1110110 */
+	0x0c, /* 0000110 */
+	0xec, /* 1110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+
+	/* 186 0xba 'º' */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+
+	/* 187 0xbb '»' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xfc, /* 1111110 */
+	0x0c, /* 0000110 */
+	0xec, /* 1110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+
+	/* 188 0xbc '¼' */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0xec, /* 1110110 */
+	0x0c, /* 0000110 */
+	0xfc, /* 1111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 189 0xbd '½' */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0xfc, /* 1111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 190 0xbe '¾' */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0xf0, /* 1111000 */
+	0x30, /* 0011000 */
+	0xf0, /* 1111000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 191 0xbf '¿' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xf0, /* 1111000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+
+	/* 192 0xc0 'À' */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x3e, /* 0011111 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 193 0xc1 'Á' */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0xfe, /* 1111111 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 194 0xc2 'Â' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xfe, /* 1111111 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+
+	/* 195 0xc3 'Ã' */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x3e, /* 0011111 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+
+	/* 196 0xc4 'Ä' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xfe, /* 1111111 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 197 0xc5 'Å' */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0xfe, /* 1111111 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+
+	/* 198 0xc6 'Æ' */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x3e, /* 0011111 */
+	0x30, /* 0011000 */
+	0x3e, /* 0011111 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+
+	/* 199 0xc7 'Ç' */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6e, /* 0110111 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+
+	/* 200 0xc8 'È' */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6e, /* 0110111 */
+	0x60, /* 0110000 */
+	0x7e, /* 0111111 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 201 0xc9 'É' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x7e, /* 0111111 */
+	0x60, /* 0110000 */
+	0x6e, /* 0110111 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+
+	/* 202 0xca 'Ê' */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0xee, /* 1110111 */
+	0x00, /* 0000000 */
+	0xfe, /* 1111111 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 203 0xcb 'Ë' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xfe, /* 1111111 */
+	0x00, /* 0000000 */
+	0xee, /* 1110111 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+
+	/* 204 0xcc 'Ì' */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6e, /* 0110111 */
+	0x60, /* 0110000 */
+	0x6e, /* 0110111 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+
+	/* 205 0xcd 'Í' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xfe, /* 1111111 */
+	0x00, /* 0000000 */
+	0xfe, /* 1111111 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 206 0xce 'Î' */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0xee, /* 1110111 */
+	0x00, /* 0000000 */
+	0xee, /* 1110111 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+
+	/* 207 0xcf 'Ï' */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0xfe, /* 1111111 */
+	0x00, /* 0000000 */
+	0xfe, /* 1111111 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 208 0xd0 'Ð' */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0xfe, /* 1111111 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 209 0xd1 'Ñ' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xfe, /* 1111111 */
+	0x00, /* 0000000 */
+	0xfe, /* 1111111 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+
+	/* 210 0xd2 'Ò' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xfe, /* 1111111 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+
+	/* 211 0xd3 'Ó' */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x7e, /* 0111111 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 212 0xd4 'Ô' */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x3e, /* 0011111 */
+	0x30, /* 0011000 */
+	0x3e, /* 0011111 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 213 0xd5 'Õ' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x3e, /* 0011111 */
+	0x30, /* 0011000 */
+	0x3e, /* 0011111 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+
+	/* 214 0xd6 'Ö' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x7e, /* 0111111 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+
+	/* 215 0xd7 '×' */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0xfe, /* 1111111 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+
+	/* 216 0xd8 'Ø' */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0xfe, /* 1111111 */
+	0x30, /* 0011000 */
+	0xfe, /* 1111111 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+
+	/* 217 0xd9 'Ù' */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0xf0, /* 1111000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 218 0xda 'Ú' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x3e, /* 0011111 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+
+	/* 219 0xdb 'Û' */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+
+	/* 220 0xdc 'Ü' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+
+	/* 221 0xdd 'Ý' */
+	0xe0, /* 1110000 */
+	0xe0, /* 1110000 */
+	0xe0, /* 1110000 */
+	0xe0, /* 1110000 */
+	0xe0, /* 1110000 */
+	0xe0, /* 1110000 */
+	0xe0, /* 1110000 */
+	0xe0, /* 1110000 */
+	0xe0, /* 1110000 */
+	0xe0, /* 1110000 */
+	0xe0, /* 1110000 */
+	0xe0, /* 1110000 */
+	0xe0, /* 1110000 */
+	0xe0, /* 1110000 */
+
+	/* 222 0xde 'Þ' */
+	0x1e, /* 0001111 */
+	0x1e, /* 0001111 */
+	0x1e, /* 0001111 */
+	0x1e, /* 0001111 */
+	0x1e, /* 0001111 */
+	0x1e, /* 0001111 */
+	0x1e, /* 0001111 */
+	0x1e, /* 0001111 */
+	0x1e, /* 0001111 */
+	0x1e, /* 0001111 */
+	0x1e, /* 0001111 */
+	0x1e, /* 0001111 */
+	0x1e, /* 0001111 */
+	0x1e, /* 0001111 */
+
+	/* 223 0xdf 'ß' */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 224 0xe0 'à' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x76, /* 0111011 */
+	0xdc, /* 1101110 */
+	0xd8, /* 1101100 */
+	0xd8, /* 1101100 */
+	0xd8, /* 1101100 */
+	0xdc, /* 1101110 */
+	0x76, /* 0111011 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 225 0xe1 'á' */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xd8, /* 1101100 */
+	0xcc, /* 1100110 */
+	0xc6, /* 1100011 */
+	0xc6, /* 1100011 */
+	0xc6, /* 1100011 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 226 0xe2 'â' */
+	0x00, /* 0000000 */
+	0xfc, /* 1111110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 227 0xe3 'ã' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xfe, /* 1111111 */
+	0xfe, /* 1111111 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 228 0xe4 'ä' */
+	0x00, /* 0000000 */
+	0xfc, /* 1111110 */
+	0xcc, /* 1100110 */
+	0x60, /* 0110000 */
+	0x30, /* 0011000 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x60, /* 0110000 */
+	0xcc, /* 1100110 */
+	0xfc, /* 1111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 229 0xe5 'å' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x7e, /* 0111111 */
+	0xd8, /* 1101100 */
+	0xd8, /* 1101100 */
+	0xd8, /* 1101100 */
+	0xd8, /* 1101100 */
+	0xd8, /* 1101100 */
+	0x70, /* 0111000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 230 0xe6 'æ' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xf8, /* 1111100 */
+	0xc0, /* 1100000 */
+	0xc0, /* 1100000 */
+	0x80, /* 1000000 */
+
+	/* 231 0xe7 'ç' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x76, /* 0111011 */
+	0xdc, /* 1101110 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 232 0xe8 'è' */
+	0x00, /* 0000000 */
+	0xfc, /* 1111110 */
+	0x30, /* 0011000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x30, /* 0011000 */
+	0xfc, /* 1111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 233 0xe9 'é' */
+	0x00, /* 0000000 */
+	0x38, /* 0011100 */
+	0x6c, /* 0110110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xfc, /* 1111110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x6c, /* 0110110 */
+	0x38, /* 0011100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 234 0xea 'ê' */
+	0x00, /* 0000000 */
+	0x38, /* 0011100 */
+	0x6c, /* 0110110 */
+	0xc6, /* 1100011 */
+	0xc6, /* 1100011 */
+	0xc6, /* 1100011 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0xee, /* 1110111 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 235 0xeb 'ë' */
+	0x00, /* 0000000 */
+	0x3c, /* 0011110 */
+	0x60, /* 0110000 */
+	0x30, /* 0011000 */
+	0x18, /* 0001100 */
+	0x7c, /* 0111110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x78, /* 0111100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 236 0xec 'ì' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x7c, /* 0111110 */
+	0xd6, /* 1101011 */
+	0xd6, /* 1101011 */
+	0xd6, /* 1101011 */
+	0x7c, /* 0111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 237 0xed 'í' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x06, /* 0000011 */
+	0x0c, /* 0000110 */
+	0x7c, /* 0111110 */
+	0xd6, /* 1101011 */
+	0xd6, /* 1101011 */
+	0xe6, /* 1110011 */
+	0x7c, /* 0111110 */
+	0x60, /* 0110000 */
+	0xc0, /* 1100000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 238 0xee 'î' */
+	0x00, /* 0000000 */
+	0x1c, /* 0001110 */
+	0x30, /* 0011000 */
+	0x60, /* 0110000 */
+	0x60, /* 0110000 */
+	0x7c, /* 0111110 */
+	0x60, /* 0110000 */
+	0x60, /* 0110000 */
+	0x60, /* 0110000 */
+	0x30, /* 0011000 */
+	0x1c, /* 0001110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 239 0xef 'ï' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0xcc, /* 1100110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 240 0xf0 'ð' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xfc, /* 1111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xfc, /* 1111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xfc, /* 1111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 241 0xf1 'ñ' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0xfc, /* 1111110 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0xfc, /* 1111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 242 0xf2 'ò' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x60, /* 0110000 */
+	0x30, /* 0011000 */
+	0x18, /* 0001100 */
+	0x0c, /* 0000110 */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x60, /* 0110000 */
+	0x00, /* 0000000 */
+	0xfc, /* 1111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 243 0xf3 'ó' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x60, /* 0110000 */
+	0xc0, /* 1100000 */
+	0x60, /* 0110000 */
+	0x30, /* 0011000 */
+	0x18, /* 0001100 */
+	0x00, /* 0000000 */
+	0xfc, /* 1111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 244 0xf4 'ô' */
+	0x00, /* 0000000 */
+	0x1c, /* 0001110 */
+	0x36, /* 0011011 */
+	0x36, /* 0011011 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+
+	/* 245 0xf5 'õ' */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0xd8, /* 1101100 */
+	0xd8, /* 1101100 */
+	0xd8, /* 1101100 */
+	0x70, /* 0111000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 246 0xf6 'ö' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0xfc, /* 1111110 */
+	0x00, /* 0000000 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 247 0xf7 '÷' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x76, /* 0111011 */
+	0xdc, /* 1101110 */
+	0x00, /* 0000000 */
+	0x76, /* 0111011 */
+	0xdc, /* 1101110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 248 0xf8 'ø' */
+	0x38, /* 0011100 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x38, /* 0011100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 249 0xf9 'ù' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x30, /* 0011000 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 250 0xfa 'ú' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x30, /* 0011000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 251 0xfb 'û' */
+	0x1e, /* 0001111 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0x18, /* 0001100 */
+	0xd8, /* 1101100 */
+	0xd8, /* 1101100 */
+	0xd8, /* 1101100 */
+	0x78, /* 0111100 */
+	0x38, /* 0011100 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 252 0xfc 'ü' */
+	0xd8, /* 1101100 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x6c, /* 0110110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 253 0xfd 'ý' */
+	0x78, /* 0111100 */
+	0xcc, /* 1100110 */
+	0x18, /* 0001100 */
+	0x30, /* 0011000 */
+	0x64, /* 0110010 */
+	0xfc, /* 1111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 254 0xfe 'þ' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x7c, /* 0111110 */
+	0x7c, /* 0111110 */
+	0x7c, /* 0111110 */
+	0x7c, /* 0111110 */
+	0x7c, /* 0111110 */
+	0x7c, /* 0111110 */
+	0x7c, /* 0111110 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+	/* 255 0xff 'ÿ' */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+	0x00, /* 0000000 */
+
+};
+
+
+struct font_desc font_7x14 = {
+	FONT7x14_IDX,
+	"7x14",
+	7,
+	14,
+	fontdata_7x14,
+	0
+};
diff --git a/drivers/video/console/font_sun12x22.c b/drivers/video/console/font_sun12x22.c
index 05215d0..c7bd967 100644
--- a/drivers/video/console/font_sun12x22.c
+++ b/drivers/video/console/font_sun12x22.c
@@ -29,24 +29,23 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 1 0x01 '^A' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
+	0x1f, 0xc0, /* 000111111100 */
+	0x30, 0x60, /* 001100000110 */
+	0x65, 0x30, /* 011001010011 */
+	0x6d, 0xb0, /* 011011011011 */
+	0x60, 0x30, /* 011000000011 */
+	0x62, 0x30, /* 011000100011 */
+	0x62, 0x30, /* 011000100011 */
+	0x60, 0x30, /* 011000000011 */
+	0x6f, 0xb0, /* 011011111011 */
+	0x67, 0x30, /* 011001110011 */
+	0x30, 0x60, /* 001100000110 */
+	0x1f, 0xc0, /* 000111111100 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -54,24 +53,23 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 2 0x02 '^B' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
+	0x1f, 0xc0, /* 000111111100 */
+	0x3f, 0xe0, /* 001111111110 */
+	0x7a, 0xf0, /* 011110101111 */
+	0x72, 0x70, /* 011100100111 */
+	0x7f, 0xf0, /* 011111111111 */
+	0x7d, 0xf0, /* 011111011111 */
+	0x7d, 0xf0, /* 011111011111 */
+	0x7f, 0xf0, /* 011111111111 */
+	0x70, 0x70, /* 011100000111 */
+	0x78, 0xf0, /* 011110001111 */
+	0x3f, 0xe0, /* 001111111110 */
+	0x1f, 0xc0, /* 000111111100 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -79,24 +77,23 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 3 0x03 '^C' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x19, 0x80, /* 000110011000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x7f, 0xe0, /* 011111111110 */
 	0x3f, 0xc0, /* 001111111100 */
 	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
+	0x1f, 0x80, /* 000111111000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -104,49 +101,47 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 4 0x04 '^D' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
+	0x02, 0x00, /* 000000100000 */
+	0x07, 0x00, /* 000001110000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x1f, 0xc0, /* 000111111100 */
+	0x1f, 0xc0, /* 000111111100 */
+	0x3f, 0xe0, /* 001111111110 */
+	0x1f, 0xc0, /* 000111111100 */
+	0x1f, 0xc0, /* 000111111100 */
+	0x0f, 0x80, /* 000011111000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x07, 0x00, /* 000001110000 */
+	0x02, 0x00, /* 000000100000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 
 	/* 5 0x05 '^E' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
+	0x02, 0x00, /* 000000100000 */
+	0x07, 0x00, /* 000001110000 */
+	0x07, 0x00, /* 000001110000 */
+	0x02, 0x00, /* 000000100000 */
+	0x18, 0xc0, /* 000110001100 */
+	0x3d, 0xe0, /* 001111011110 */
+	0x3d, 0xe0, /* 001111011110 */
+	0x1a, 0xc0, /* 000110101100 */
+	0x02, 0x00, /* 000000100000 */
+	0x07, 0x00, /* 000001110000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x1f, 0xc0, /* 000111111100 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -154,23 +149,22 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 6 0x06 '^F' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x1f, 0x80, /* 000111111000 */
 	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x36, 0xc0, /* 001101101100 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x1f, 0x80, /* 000111111000 */
 	0x3f, 0xc0, /* 001111111100 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -179,24 +173,23 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 7 0x07 '^G' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x1f, 0x80, /* 000111111000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x06, 0x00, /* 000001100000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -204,49 +197,47 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 8 0x08 '^H' */
-	/* FIXME */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xf9, 0xf0, /* 111110011111 */
+	0xf0, 0xf0, /* 111100001111 */
+	0xf0, 0xf0, /* 111100001111 */
+	0xe0, 0x70, /* 111000000111 */
+	0xe0, 0x70, /* 111000000111 */
+	0xc0, 0x30, /* 110000000011 */
+	0xc0, 0x30, /* 110000000011 */
+	0xe0, 0x70, /* 111000000111 */
+	0xe0, 0x70, /* 111000000111 */
+	0xf0, 0xf0, /* 111100001111 */
+	0xf0, 0xf0, /* 111100001111 */
+	0xf9, 0xf0, /* 111110011111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
 
 	/* 9 0x09 '^I' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x06, 0x00, /* 000001100000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -254,149 +245,143 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 10 0x0a '^J' */
-	/* FIXME */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xf9, 0xf0, /* 111110011111 */
+	0xf0, 0xf0, /* 111100001111 */
+	0xf0, 0xf0, /* 111100001111 */
+	0xe6, 0x70, /* 111001100111 */
+	0xe6, 0x70, /* 111001100111 */
+	0xcf, 0x30, /* 110011110011 */
+	0xcf, 0x30, /* 110011110011 */
+	0xe6, 0x70, /* 111001100111 */
+	0xe6, 0x70, /* 111001100111 */
+	0xf0, 0xf0, /* 111100001111 */
+	0xf0, 0xf0, /* 111100001111 */
+	0xf9, 0xf0, /* 111110011111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
 
 	/* 11 0x0b '^K' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
+	0x0f, 0xe0, /* 000011111110 */
+	0x0f, 0xe0, /* 000011111110 */
+	0x01, 0xe0, /* 000000011110 */
+	0x03, 0x60, /* 000000110110 */
+	0x06, 0x60, /* 000001100110 */
+	0x1e, 0x00, /* 000111100000 */
+	0x33, 0x00, /* 001100110000 */
+	0x33, 0x00, /* 001100110000 */
+	0x61, 0x80, /* 011000011000 */
+	0x61, 0x80, /* 011000011000 */
+	0x33, 0x00, /* 001100110000 */
+	0x33, 0x00, /* 001100110000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x0c, 0x00, /* 000011000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 
 	/* 12 0x0c '^L' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x19, 0x80, /* 000110011000 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x19, 0x80, /* 000110011000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 
 	/* 13 0x0d '^M' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
+	0x0f, 0xe0, /* 000011111110 */
+	0x0c, 0x60, /* 000011000110 */
+	0x0c, 0x60, /* 000011000110 */
+	0x0f, 0xe0, /* 000011111110 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x3c, 0x00, /* 001111000000 */
+	0x7c, 0x00, /* 011111000000 */
+	0x78, 0x00, /* 011110000000 */
+	0x30, 0x00, /* 001100000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 
 	/* 14 0x0e '^N' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
+	0x1f, 0xe0, /* 000111111110 */
+	0x18, 0x60, /* 000110000110 */
+	0x18, 0x60, /* 000110000110 */
+	0x1f, 0xe0, /* 000111111110 */
+	0x18, 0x60, /* 000110000110 */
+	0x18, 0x60, /* 000110000110 */
+	0x18, 0x60, /* 000110000110 */
+	0x18, 0x60, /* 000110000110 */
+	0x18, 0x60, /* 000110000110 */
+	0x18, 0x60, /* 000110000110 */
+	0x19, 0xe0, /* 000110011110 */
+	0x1b, 0xe0, /* 000110111110 */
+	0x1b, 0xc0, /* 000110111100 */
+	0x79, 0x80, /* 011110011000 */
+	0xf8, 0x00, /* 111110000000 */
+	0xf0, 0x00, /* 111100000000 */
+	0x60, 0x00, /* 011000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 
 	/* 15 0x0f '^O' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x18, 0xc0, /* 000110001100 */
+	0x0d, 0x80, /* 000011011000 */
+	0x6d, 0xb0, /* 011011011011 */
+	0x3d, 0xe0, /* 001111011110 */
+	0x00, 0x00, /* 000000000000 */
+	0x3d, 0xe0, /* 001111011110 */
+	0x6d, 0xb0, /* 011011011011 */
+	0x0d, 0x80, /* 000011011000 */
+	0x18, 0xc0, /* 000110001100 */
+	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -404,74 +389,71 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 16 0x10 '^P' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
+	0x00, 0x20, /* 000000000010 */
+	0x00, 0x60, /* 000000000110 */
+	0x00, 0xe0, /* 000000001110 */
+	0x01, 0xe0, /* 000000011110 */
+	0x03, 0xe0, /* 000000111110 */
+	0x07, 0xe0, /* 000001111110 */
+	0x0f, 0xe0, /* 000011111110 */
+	0x1f, 0xe0, /* 000111111110 */
+	0x3f, 0xe0, /* 001111111110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x3f, 0xe0, /* 001111111110 */
+	0x1f, 0xe0, /* 000111111110 */
+	0x0f, 0xe0, /* 000011111110 */
+	0x07, 0xe0, /* 000001111110 */
+	0x03, 0xe0, /* 000000111110 */
+	0x01, 0xe0, /* 000000011110 */
+	0x00, 0xe0, /* 000000001110 */
+	0x00, 0x60, /* 000000000110 */
+	0x00, 0x20, /* 000000000010 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 
 	/* 17 0x11 '^Q' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
+	0x40, 0x00, /* 010000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x70, 0x00, /* 011100000000 */
+	0x78, 0x00, /* 011110000000 */
+	0x7c, 0x00, /* 011111000000 */
+	0x7e, 0x00, /* 011111100000 */
+	0x7f, 0x00, /* 011111110000 */
+	0x7f, 0x80, /* 011111111000 */
+	0x7f, 0xc0, /* 011111111100 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xc0, /* 011111111100 */
+	0x7f, 0x80, /* 011111111000 */
+	0x7f, 0x00, /* 011111110000 */
+	0x7e, 0x00, /* 011111100000 */
+	0x7c, 0x00, /* 011111000000 */
+	0x78, 0x00, /* 011110000000 */
+	0x70, 0x00, /* 011100000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x40, 0x00, /* 010000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 
 	/* 18 0x12 '^R' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
+	0x04, 0x00, /* 000001000000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x3f, 0x80, /* 001111111000 */
+	0x7f, 0xc0, /* 011111111100 */
+	0x0e, 0x00, /* 000011100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x7f, 0xc0, /* 011111111100 */
+	0x3f, 0x80, /* 001111111000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x04, 0x00, /* 000001000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -551,24 +533,23 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 22 0x16 '^V' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -576,24 +557,23 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 23 0x17 '^W' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
+	0x04, 0x00, /* 000001000000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x3f, 0x80, /* 001111111000 */
+	0x7f, 0xc0, /* 011111111100 */
+	0x0e, 0x00, /* 000011100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x7f, 0xc0, /* 011111111100 */
+	0x3f, 0x80, /* 001111111000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x04, 0x00, /* 000001000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xe0, /* 011111111110 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -601,49 +581,47 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 24 0x18 '^X' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
+	0x04, 0x00, /* 000001000000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x3f, 0x80, /* 001111111000 */
+	0x7f, 0xc0, /* 011111111100 */
+	0x0e, 0x00, /* 000011100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x0e, 0x00, /* 000011100000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 
 	/* 25 0x19 '^Y' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
+	0x0e, 0x00, /* 000011100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x7f, 0xc0, /* 011111111100 */
+	0x3f, 0x80, /* 001111111000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x04, 0x00, /* 000001000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -651,24 +629,23 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 26 0x1a '^Z' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x08, 0x00, /* 000010000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x38, 0x00, /* 001110000000 */
+	0x7f, 0xe0, /* 011111111110 */
+	0xff, 0xe0, /* 111111111110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x38, 0x00, /* 001110000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x08, 0x00, /* 000010000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -676,24 +653,23 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 27 0x1b '^[' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x01, 0x00, /* 000000010000 */
+	0x01, 0x80, /* 000000011000 */
+	0x01, 0xc0, /* 000000011100 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xf0, /* 011111111111 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x01, 0xc0, /* 000000011100 */
+	0x01, 0x80, /* 000000011000 */
+	0x01, 0x00, /* 000000010000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -701,24 +677,23 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 28 0x1c '^\' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x3f, 0xe0, /* 001111111110 */
+	0x3f, 0xe0, /* 001111111110 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -726,24 +701,23 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 29 0x1d '^]' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x09, 0x00, /* 000010010000 */
+	0x19, 0x80, /* 000110011000 */
+	0x39, 0xc0, /* 001110011100 */
+	0x7f, 0xe0, /* 011111111110 */
+	0xff, 0xf0, /* 111111111111 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x39, 0xc0, /* 001110011100 */
+	0x19, 0x80, /* 000110011000 */
+	0x09, 0x00, /* 000010010000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -751,24 +725,23 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 30 0x1e '^^' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x04, 0x00, /* 000001000000 */
+	0x04, 0x00, /* 000001000000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x3f, 0x80, /* 001111111000 */
+	0x3f, 0x80, /* 001111111000 */
+	0x7f, 0xc0, /* 011111111100 */
+	0x7f, 0xc0, /* 011111111100 */
+	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -776,24 +749,23 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 31 0x1f '^_' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x7f, 0xc0, /* 011111111100 */
+	0x7f, 0xc0, /* 011111111100 */
+	0x3f, 0x80, /* 001111111000 */
+	0x3f, 0x80, /* 001111111000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x04, 0x00, /* 000001000000 */
+	0x04, 0x00, /* 000001000000 */
+	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -3081,29 +3053,28 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 127 0x7f '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 128 0x80 '.' */
 	0x00, 0x00, /* 000000000000 */
@@ -3826,53 +3797,51 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 158 0x9e '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
+	0x7f, 0x80, /* 011111111000 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0x60, /* 001100000110 */
+	0x30, 0x60, /* 001100000110 */
+	0x30, 0x60, /* 001100000110 */
+	0x30, 0xc0, /* 001100001100 */
+	0x37, 0x80, /* 001101111000 */
+	0x30, 0x00, /* 001100000000 */
+	0x33, 0x00, /* 001100110000 */
+	0x37, 0x80, /* 001101111000 */
+	0x33, 0x00, /* 001100110000 */
+	0x33, 0x00, /* 001100110000 */
+	0x33, 0x30, /* 001100110011 */
+	0x31, 0xe0, /* 001100011110 */
+	0x78, 0xc0, /* 011110001100 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 
 	/* 159 0x9f '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
+	0x00, 0xc0, /* 000000001100 */
+	0x01, 0xe0, /* 000000011110 */
+	0x03, 0x30, /* 000000110011 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x3f, 0xe0, /* 001111111110 */
+	0x7f, 0xc0, /* 011111111100 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0xcc, 0x00, /* 110011000000 */
+	0x78, 0x00, /* 011110000000 */
+	0x30, 0x00, /* 001100000000 */
 	0x00, 0x00, /* 000000000000 */
 
 	/* 160 0xa0 '.' */
@@ -4092,24 +4061,23 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 169 0xa9 '.' */
-	/* FIXME */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -5413,24 +5381,23 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 224 0xe0 '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x60, /* 000011110110 */
+	0x13, 0xe0, /* 000100111110 */
+	0x21, 0xc0, /* 001000011100 */
+	0x60, 0xc0, /* 011000001100 */
+	0x60, 0xc0, /* 011000001100 */
+	0x60, 0xc0, /* 011000001100 */
+	0x60, 0xc0, /* 011000001100 */
+	0x70, 0x80, /* 011100001000 */
+	0x39, 0xc0, /* 001110011100 */
+	0x1f, 0x60, /* 000111110110 */
+	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -5462,49 +5429,47 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 226 0xe2 '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xe0, /* 001111111110 */
+	0x3f, 0xe0, /* 001111111110 */
+	0x30, 0x60, /* 001100000110 */
+	0x30, 0x60, /* 001100000110 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 
 	/* 227 0xe3 '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -5512,49 +5477,47 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 228 0xe4 '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x60, 0x60, /* 011000000110 */
+	0x30, 0x60, /* 001100000110 */
+	0x30, 0x00, /* 001100000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x60, /* 001100000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xe0, /* 011111111110 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 
 	/* 229 0xe5 '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
+	0x07, 0xe0, /* 000001111110 */
+	0x0f, 0xe0, /* 000011111110 */
+	0x13, 0x80, /* 000100111000 */
+	0x21, 0xc0, /* 001000011100 */
+	0x60, 0xc0, /* 011000001100 */
+	0x60, 0xc0, /* 011000001100 */
+	0x60, 0xc0, /* 011000001100 */
+	0x60, 0xc0, /* 011000001100 */
+	0x70, 0x80, /* 011100001000 */
+	0x39, 0x00, /* 001110010000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -5586,74 +5549,71 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 231 0xe7 '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
+	0x19, 0x80, /* 000110011000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x66, 0x60, /* 011001100110 */
+	0x66, 0x60, /* 011001100110 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 
 	/* 232 0xe8 '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x19, 0x80, /* 000110011000 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x19, 0x80, /* 000110011000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xe0, /* 011111111110 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 
 	/* 233 0xe9 '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x30, 0xc0, /* 001100001100 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x30, 0xc0, /* 001100001100 */
+	0x1f, 0x80, /* 000111111000 */
+	0x0f, 0x00, /* 000011110000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -5661,24 +5621,23 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 234 0xea '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x31, 0x80, /* 001100011000 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0xd9, 0xb0, /* 110110011011 */
+	0x79, 0xe0, /* 011110011110 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -5686,49 +5645,47 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 235 0xeb '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
+	0x07, 0x80, /* 000001111000 */
+	0x0c, 0xc0, /* 000011001100 */
+	0x18, 0x60, /* 000110000110 */
+	0x18, 0x00, /* 000110000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x03, 0x00, /* 000000110000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x11, 0xc0, /* 000100011100 */
+	0x20, 0xe0, /* 001000001110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x70, 0x40, /* 011100000100 */
+	0x38, 0x80, /* 001110001000 */
+	0x1f, 0x00, /* 000111110000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 
 	/* 236 0xec '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x39, 0xc0, /* 001110011100 */
+	0x6f, 0x60, /* 011011110110 */
+	0x66, 0x60, /* 011001100110 */
+	0xc6, 0x30, /* 110001100011 */
+	0xc6, 0x30, /* 110001100011 */
+	0x66, 0x60, /* 011001100110 */
+	0x6f, 0x60, /* 011011110110 */
+	0x39, 0xc0, /* 001110011100 */
+	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -5736,74 +5693,71 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 237 0xed '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
+	0x00, 0xc0, /* 000000001100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x01, 0x80, /* 000000011000 */
+	0x01, 0x80, /* 000000011000 */
+	0x3b, 0xc0, /* 001110111100 */
+	0x6f, 0x60, /* 011011110110 */
+	0x66, 0x60, /* 011001100110 */
+	0xc6, 0x30, /* 110001100011 */
+	0xc6, 0x30, /* 110001100011 */
+	0x66, 0x60, /* 011001100110 */
+	0x6f, 0x60, /* 011011110110 */
+	0x3d, 0xc0, /* 001111011100 */
+	0x18, 0x00, /* 000110000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 
 	/* 238 0xee '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
+	0x01, 0xc0, /* 000000011100 */
+	0x03, 0x00, /* 000000110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x1f, 0xc0, /* 000111111100 */
+	0x18, 0x00, /* 000110000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x03, 0x00, /* 000000110000 */
+	0x01, 0xc0, /* 000000011100 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 
 	/* 239 0xef '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
+	0x0f, 0x00, /* 000011110000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x39, 0xc0, /* 001110011100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -5811,24 +5765,23 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 240 0xf0 '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xe0, /* 011111111110 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -5860,24 +5813,23 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 242 0xf2 '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x38, 0x00, /* 001110000000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x03, 0x80, /* 000000111000 */
+	0x00, 0xe0, /* 000000001110 */
+	0x00, 0xe0, /* 000000001110 */
+	0x03, 0x80, /* 000000111000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x38, 0x00, /* 001110000000 */
+	0x60, 0x00, /* 011000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xe0, /* 011111111110 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -5885,24 +5837,23 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 243 0xf3 '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
+	0x00, 0x60, /* 000000000110 */
+	0x01, 0xc0, /* 000000011100 */
+	0x07, 0x00, /* 000001110000 */
+	0x1c, 0x00, /* 000111000000 */
+	0x70, 0x00, /* 011100000000 */
+	0x70, 0x00, /* 011100000000 */
+	0x1c, 0x00, /* 000111000000 */
+	0x07, 0x00, /* 000001110000 */
+	0x01, 0xc0, /* 000000011100 */
+	0x00, 0x60, /* 000000000110 */
 	0x00, 0x00, /* 000000000000 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xe0, /* 011111111110 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -5910,54 +5861,52 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 244 0xf4 '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
+	0x03, 0x80, /* 000000111000 */
+	0x07, 0xc0, /* 000001111100 */
+	0x0c, 0x60, /* 000011000110 */
+	0x0c, 0x60, /* 000011000110 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
 
 	/* 245 0xf5 '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
+	0x1c, 0x00, /* 000111000000 */
+	0x3e, 0x00, /* 001111100000 */
+	0x63, 0x00, /* 011000110000 */
+	0x63, 0x00, /* 011000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
 
 	/* 246 0xf6 '.' */
 	0x00, 0x00, /* 000000000000 */
@@ -5984,24 +5933,23 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 247 0xf7 '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x38, 0x00, /* 001110000000 */
+	0x6c, 0x00, /* 011011000000 */
+	0x06, 0x30, /* 000001100011 */
+	0x03, 0x60, /* 000000110110 */
+	0x39, 0xc0, /* 001110011100 */
+	0x6c, 0x00, /* 011011000000 */
+	0x06, 0x30, /* 000001100011 */
+	0x03, 0x60, /* 000000110110 */
+	0x01, 0xc0, /* 000000011100 */
+	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -6033,24 +5981,23 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 249 0xf9 '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1c, 0x00, /* 000111000000 */
+	0x3e, 0x00, /* 001111100000 */
+	0x3e, 0x00, /* 001111100000 */
+	0x3e, 0x00, /* 001111100000 */
+	0x1c, 0x00, /* 000111000000 */
+	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -6067,13 +6014,13 @@
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x06, 0x00, /* 000001100000 */
-	0x0f, 0x00, /* 000011110000 */
-	0x0f, 0x00, /* 000011110000 */
-	0x06, 0x00, /* 000001100000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x3c, 0x00, /* 001111000000 */
+	0x3c, 0x00, /* 001111000000 */
+	0x18, 0x00, /* 000110000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
@@ -6082,49 +6029,47 @@
 	0x00, 0x00, /* 000000000000 */
 
 	/* 251 0xfb '.' */
-	/* FIXME */
 	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
-	0x00, 0x00, /* 000000000000 */
+	0x07, 0xe0, /* 000001111110 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0xc6, 0x00, /* 110001100000 */
+	0x66, 0x00, /* 011001100000 */
+	0x36, 0x00, /* 001101100000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x02, 0x00, /* 000000100000 */
 	0x00, 0x00, /* 000000000000 */
 
 	/* 252 0xfc '.' */
-	/* FIXME */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x13, 0x80, /* 000100111000 */
+	0x3d, 0xc0, /* 001111011100 */
+	0x18, 0xc0, /* 000110001100 */
+	0x18, 0xc0, /* 000110001100 */
+	0x18, 0xc0, /* 000110001100 */
+	0x18, 0xc0, /* 000110001100 */
+	0x3d, 0xe0, /* 001111011110 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
-	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
 	0x00, 0x00, /* 000000000000 */
diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c
index 465d678..e79b297 100644
--- a/drivers/video/console/fonts.c
+++ b/drivers/video/console/fonts.c
@@ -36,6 +36,10 @@
 #undef NO_FONTS
     &font_vga_6x11,
 #endif
+#ifdef CONFIG_FONT_7x14
+#undef NO_FONTS
+    &font_7x14,
+#endif
 #ifdef CONFIG_FONT_SUN8x16
 #undef NO_FONTS
     &font_sun_8x16,
@@ -44,6 +48,10 @@
 #undef NO_FONTS
     &font_sun_12x22,
 #endif
+#ifdef CONFIG_FONT_10x18
+#undef NO_FONTS
+    &font_10x18,
+#endif
 #ifdef CONFIG_FONT_ACORN_8x8
 #undef NO_FONTS
     &font_acorn_8x8,
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index bcf59b2..d27fa91 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -95,6 +95,7 @@
 /* Description of the hardware situation */
 static unsigned long	vga_vram_base;		/* Base of video memory */
 static unsigned long	vga_vram_end;		/* End of video memory */
+static int		vga_vram_size;		/* Size of video memory */
 static u16		vga_video_port_reg;	/* Video register select port */
 static u16		vga_video_port_val;	/* Video register value port */
 static unsigned int	vga_video_num_columns;	/* Number of text columns */
@@ -288,6 +289,7 @@
 
 	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;
 
 	/*
 	 *      Find out if there is a graphics card present.
@@ -504,9 +506,13 @@
 	 */
 	vga_video_num_columns = c->vc_cols;
 	vga_video_num_lines = c->vc_rows;
+
+	/* We can only copy out the size of the video buffer here,
+	 * otherwise we get into VGA BIOS */
+
 	if (!vga_is_gfx)
 		scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf,
-			    c->vc_screenbuf_size);
+			    c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size);
 	return 0;		/* Redrawing not needed */
 }
 
@@ -961,7 +967,6 @@
 	if (!lines)		/* Turn scrollback off */
 		c->vc_visible_origin = c->vc_origin;
 	else {
-		int vram_size = vga_vram_end - vga_vram_base;
 		int margin = c->vc_size_row * 4;
 		int ul, we, p, st;
 
@@ -971,7 +976,7 @@
 			we = vga_rolled_over + c->vc_size_row;
 		} else {
 			ul = 0;
-			we = vram_size;
+			we = vga_vram_size;
 		}
 		p = (c->vc_visible_origin - vga_vram_base - ul + we) % we +
 		    lines * c->vc_size_row;
@@ -1012,9 +1017,13 @@
 		c->vc_x = ORIG_X;
 		c->vc_y = ORIG_Y;
 	}
+
+	/* We can't copy in more then the size of the video buffer,
+	 * or we'll be copying in VGA BIOS */
+
 	if (!vga_is_gfx)
 		scr_memcpyw((u16 *) c->vc_screenbuf, (u16 *) c->vc_origin,
-			    c->vc_screenbuf_size);
+			    c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size);
 }
 
 static int vgacon_scroll(struct vc_data *c, int t, int b, int dir,
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 7705070..2222de6 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -76,70 +76,22 @@
 EXPORT_SYMBOL(fb_get_color_depth);
 
 /*
- * Drawing helpers.
+ * Data padding functions.
  */
-void fb_iomove_buf_aligned(struct fb_info *info, struct fb_pixmap *buf,
-			   u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch,
-			   u32 height)
+void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height)
 {
 	int i;
 
 	for (i = height; i--; ) {
-		buf->outbuf(info, dst, src, s_pitch);
+		memcpy(dst, src, s_pitch);
 		src += s_pitch;
 		dst += d_pitch;
 	}
 }
+EXPORT_SYMBOL(fb_pad_aligned_buffer);
 
-void fb_sysmove_buf_aligned(struct fb_info *info, struct fb_pixmap *buf,
-			    u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch,
-			    u32 height)
-{
-	int i, j;
-
-	for (i = height; i--; ) {
-		for (j = 0; j < s_pitch; j++)
-			dst[j] = src[j];
-		src += s_pitch;
-		dst += d_pitch;
-	}
-}
-
-void fb_iomove_buf_unaligned(struct fb_info *info, struct fb_pixmap *buf,
-			     u8 *dst, u32 d_pitch, u8 *src, u32 idx,
-			     u32 height, u32 shift_high, u32 shift_low,
-			     u32 mod)
-{
-	u8 mask = (u8) (0xfff << shift_high), tmp;
-	int i, j;
-
-	for (i = height; i--; ) {
-		for (j = 0; j < idx; j++) {
-			tmp = buf->inbuf(info, dst+j);
-			tmp &= mask;
-			tmp |= *src >> shift_low;
-			buf->outbuf(info, dst+j, &tmp, 1);
-			tmp = *src << shift_high;
-			buf->outbuf(info, dst+j+1, &tmp, 1);
-			src++;
-		}
-		tmp = buf->inbuf(info, dst+idx);
-		tmp &= mask;
-		tmp |= *src >> shift_low;
-		buf->outbuf(info, dst+idx, &tmp, 1);
-		if (shift_high < mod) {
-			tmp = *src << shift_high;
-			buf->outbuf(info, dst+idx+1, &tmp, 1);
-		}	
-		src++;
-		dst += d_pitch;
-	}
-}
-
-void fb_sysmove_buf_unaligned(struct fb_info *info, struct fb_pixmap *buf,
-			      u8 *dst, u32 d_pitch, u8 *src, u32 idx,
-			      u32 height, u32 shift_high, u32 shift_low,
-			      u32 mod)
+void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, u32 height,
+				u32 shift_high, u32 shift_low, u32 mod)
 {
 	u8 mask = (u8) (0xfff << shift_high), tmp;
 	int i, j;
@@ -166,6 +118,7 @@
 		dst += d_pitch;
 	}
 }
+EXPORT_SYMBOL(fb_pad_unaligned_buffer);
 
 /*
  * we need to lock this section since fb_cursor
@@ -1040,7 +993,7 @@
 #endif
 };
 
-static struct class_simple *fb_class;
+static struct class *fb_class;
 
 /**
  *	register_framebuffer - registers a frame buffer device
@@ -1066,7 +1019,7 @@
 			break;
 	fb_info->node = i;
 
-	fb_info->class_device = class_simple_device_add(fb_class, MKDEV(FB_MAJOR, i),
+	fb_info->class_device = class_device_create(fb_class, MKDEV(FB_MAJOR, i),
 				    fb_info->device, "fb%d", i);
 	if (IS_ERR(fb_info->class_device)) {
 		/* Not fatal */
@@ -1081,7 +1034,7 @@
 			fb_info->pixmap.size = FBPIXMAPSIZE;
 			fb_info->pixmap.buf_align = 1;
 			fb_info->pixmap.scan_align = 1;
-			fb_info->pixmap.access_align = 4;
+			fb_info->pixmap.access_align = 32;
 			fb_info->pixmap.flags = FB_PIXMAP_DEFAULT;
 		}
 	}	
@@ -1134,7 +1087,7 @@
 	registered_fb[i]=NULL;
 	num_registered_fb--;
 	fb_cleanup_class_device(fb_info);
-	class_simple_device_remove(MKDEV(FB_MAJOR, i));
+	class_device_destroy(fb_class, MKDEV(FB_MAJOR, i));
 	return 0;
 }
 
@@ -1197,7 +1150,7 @@
 	if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
 		printk("unable to get major %d for fb devs\n", FB_MAJOR);
 
-	fb_class = class_simple_create(THIS_MODULE, "graphics");
+	fb_class = class_create(THIS_MODULE, "graphics");
 	if (IS_ERR(fb_class)) {
 		printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));
 		fb_class = NULL;
@@ -1210,7 +1163,7 @@
 static void __exit
 fbmem_exit(void)
 {
-	class_simple_destroy(fb_class);
+	class_destroy(fb_class);
 }
 
 module_exit(fbmem_exit);
@@ -1357,10 +1310,6 @@
 EXPORT_SYMBOL(fb_blank);
 EXPORT_SYMBOL(fb_pan_display);
 EXPORT_SYMBOL(fb_get_buffer_offset);
-EXPORT_SYMBOL(fb_iomove_buf_unaligned);
-EXPORT_SYMBOL(fb_iomove_buf_aligned);
-EXPORT_SYMBOL(fb_sysmove_buf_unaligned);
-EXPORT_SYMBOL(fb_sysmove_buf_aligned);
 EXPORT_SYMBOL(fb_set_suspend);
 EXPORT_SYMBOL(fb_register_client);
 EXPORT_SYMBOL(fb_unregister_client);
diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
index c78a2c5..7dfbf39 100644
--- a/drivers/video/fbsysfs.c
+++ b/drivers/video/fbsysfs.c
@@ -228,8 +228,6 @@
 	if (last - buf >= count)
 		return -EINVAL;
 	var.yres_virtual = simple_strtoul(last, &last, 0);
-	printk(KERN_ERR "fb: xres %d yres %d\n", var.xres_virtual,
-	       var.yres_virtual);
 
 	if ((err = activate(fb_info, &var)))
 		return err;
@@ -241,7 +239,7 @@
 	struct fb_info *fb_info =
 		(struct fb_info *)class_get_devdata(class_device);
 	return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xres_virtual,
-			fb_info->var.xres_virtual);
+			fb_info->var.yres_virtual);
 }
 
 static ssize_t store_cmap(struct class_device *class_device, const char * buf,
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index 2a02328..d3c1922 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -1045,14 +1045,14 @@
  * sysfs
  */
 
-static ssize_t gbefb_show_memsize(struct device *dev, char *buf)
+static ssize_t gbefb_show_memsize(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	return snprintf(buf, PAGE_SIZE, "%d\n", gbe_mem_size);
 }
 
 static DEVICE_ATTR(size, S_IRUGO, gbefb_show_memsize, NULL);
 
-static ssize_t gbefb_show_rev(struct device *device, char *buf)
+static ssize_t gbefb_show_rev(struct device *device, struct device_attribute *attr, char *buf)
 {
 	return snprintf(buf, PAGE_SIZE, "%d\n", gbe_revision);
 }
diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
index a9a618f..7513fb9 100644
--- a/drivers/video/i810/i810_main.c
+++ b/drivers/video/i810/i810_main.c
@@ -1885,6 +1885,7 @@
 	memset(info->pixmap.addr, 0, 8*1024);
 	info->pixmap.size = 8*1024;
 	info->pixmap.buf_align = 8;
+	info->pixmap.access_align = 32;
 	info->pixmap.flags = FB_PIXMAP_SYSTEM;
 
 	if ((err = i810_allocate_pci_resource(par, entry))) {
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
index 25f9a9a..298bc9c 100644
--- a/drivers/video/intelfb/intelfbdrv.c
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -214,7 +214,7 @@
 
 /* PCI driver module table */
 static struct pci_driver intelfb_driver = {
-	.name =		"Intel(R) " SUPPORTED_CHIPSETS " Framebuffer Driver",
+	.name =		"intelfb",
 	.id_table =	intelfb_pci_table,
 	.probe =	intelfb_pci_register,
 	.remove =	__devexit_p(intelfb_pci_unregister)
@@ -238,12 +238,15 @@
 static int probeonly    = 0;
 static int idonly       = 0;
 static int bailearly    = 0;
+static int voffset	= 48;
 static char *mode       = NULL;
 
 module_param(accel, bool, S_IRUGO);
 MODULE_PARM_DESC(accel, "Enable console acceleration");
 module_param(vram, int, S_IRUGO);
 MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB");
+module_param(voffset, int, S_IRUGO);
+MODULE_PARM_DESC(voffset, "Offset of framebuffer in MiB");
 module_param(hwcursor, bool, S_IRUGO);
 MODULE_PARM_DESC(hwcursor, "Enable HW cursor");
 module_param(mtrr, bool, S_IRUGO);
@@ -503,6 +506,7 @@
 	struct agp_bridge_data *bridge;
  	int aperture_bar = 0;
  	int mmio_bar = 1;
+	int offset;
 
 	DBG_MSG("intelfb_pci_register\n");
 
@@ -659,17 +663,21 @@
 		return -ENODEV;
 	}
 
+	if (MB(voffset) < stolen_size)
+		offset = (stolen_size >> 12);
+	else
+		offset = ROUND_UP_TO_PAGE(MB(voffset))/GTT_PAGE_SIZE;
+
 	/* set the mem offsets - set them after the already used pages */
 	if (dinfo->accel) {
-		dinfo->ring.offset = (stolen_size >> 12)
-			+ gtt_info.current_memory;
+		dinfo->ring.offset = offset + gtt_info.current_memory;
 	}
 	if (dinfo->hwcursor) {
-		dinfo->cursor.offset = (stolen_size >> 12) +
+		dinfo->cursor.offset = offset +
 			+ gtt_info.current_memory + (dinfo->ring.size >> 12);
 	}
 	if (dinfo->fbmem_gart) {
-		dinfo->fb.offset = (stolen_size >> 12) +
+		dinfo->fb.offset = offset +
 			+ gtt_info.current_memory + (dinfo->ring.size >> 12)
 			+ (dinfo->cursor.size >> 12);
 	}
@@ -1083,6 +1091,7 @@
 
 	info->pixmap.size = 64*1024;
 	info->pixmap.buf_align = 8;
+	info->pixmap.access_align = 32;
 	info->pixmap.flags = FB_PIXMAP_SYSTEM;
 
 	if (intelfb_init_var(dinfo))
@@ -1293,7 +1302,7 @@
 
 	intelfb_blank(FB_BLANK_POWERDOWN, info);
 
-	if (dinfo->accel)
+	if (ACCEL(dinfo, info))
 		intelfbhw_2d_stop(dinfo);
 
  	memcpy(hw, &dinfo->save_state, sizeof(*hw));
@@ -1309,7 +1318,7 @@
 
 	update_dinfo(dinfo, &info->var);
 
-	if (dinfo->accel)
+	if (ACCEL(dinfo, info))
 		intelfbhw_2d_start(dinfo);
 
 	intelfb_pan_display(&info->var, info);
diff --git a/drivers/video/macmodes.c b/drivers/video/macmodes.c
index de5a0f3..2fc7108 100644
--- a/drivers/video/macmodes.c
+++ b/drivers/video/macmodes.c
@@ -387,3 +387,4 @@
 }
 EXPORT_SYMBOL(mac_find_mode);
 
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c
index e529841..67f8534 100644
--- a/drivers/video/matrox/matroxfb_maven.c
+++ b/drivers/video/matrox/matroxfb_maven.c
@@ -1230,7 +1230,6 @@
 }
 
 static unsigned short normal_i2c[] = { MAVEN_I2CID, I2C_CLIENT_END };
-static unsigned short normal_i2c_range[] = { MAVEN_I2CID, MAVEN_I2CID, I2C_CLIENT_END };
 I2C_CLIENT_INSMOD;
 
 static struct i2c_driver maven_driver;
diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c
index 76fd3a5..a18dd02 100644
--- a/drivers/video/matrox/matroxfb_misc.c
+++ b/drivers/video/matrox/matroxfb_misc.c
@@ -197,10 +197,7 @@
 	DBG(__FUNCTION__)
 
 	hw->SEQ[0] = 0x00;
-	if (fwidth == 9)
-		hw->SEQ[1] = 0x00;
-	else
-		hw->SEQ[1] = 0x01;	/* or 0x09 */
+	hw->SEQ[1] = 0x01;	/* or 0x09 */
 	hw->SEQ[2] = 0x0F;	/* bitplanes */
 	hw->SEQ[3] = 0x00;
 	hw->SEQ[4] = 0x0E;
diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
index 47733f5..b2e6b24 100644
--- a/drivers/video/nvidia/nvidia.c
+++ b/drivers/video/nvidia/nvidia.c
@@ -516,9 +516,9 @@
 static void nvidiafb_load_cursor_image(struct nvidia_par *par, u8 * data8,
 				       u16 bg, u16 fg, u32 w, u32 h)
 {
+	u32 *data = (u32 *) data8;
 	int i, j, k = 0;
 	u32 b, tmp;
-	u32 *data = (u32 *) data8;
 
 	w = (w + 1) & ~1;
 
@@ -890,11 +890,11 @@
 {
 	struct nvidia_par *par = info->par;
 	u8 data[MAX_CURS * MAX_CURS / 8];
-	u16 fg, bg;
 	int i, set = cursor->set;
+	u16 fg, bg;
 
 	if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
-		return soft_cursor(info, cursor);
+		return -ENXIO;
 
 	NVShowHideCursor(par, 0);
 
@@ -931,21 +931,18 @@
 		if (src) {
 			switch (cursor->rop) {
 			case ROP_XOR:
-				for (i = 0; i < s_pitch * cursor->image.height;
-				     i++)
+				for (i = 0; i < s_pitch * cursor->image.height; i++)
 					src[i] = dat[i] ^ msk[i];
 				break;
 			case ROP_COPY:
 			default:
-				for (i = 0; i < s_pitch * cursor->image.height;
-				     i++)
+				for (i = 0; i < s_pitch * cursor->image.height; i++)
 					src[i] = dat[i] & msk[i];
 				break;
 			}
 
-			fb_sysmove_buf_aligned(info, &info->pixmap, data,
-					       d_pitch, src, s_pitch,
-					       cursor->image.height);
+			fb_pad_aligned_buffer(data, d_pitch, src, s_pitch,
+						cursor->image.height);
 
 			bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
 			    ((info->cmap.green[bg_idx] & 0xf8) << 2) |
@@ -1348,6 +1345,7 @@
 
 	info->pixmap.scan_align = 4;
 	info->pixmap.buf_align = 4;
+	info->pixmap.access_align = 32;
 	info->pixmap.size = 8 * 1024;
 	info->pixmap.flags = FB_PIXMAP_SYSTEM;
 
diff --git a/drivers/video/pm3fb.c b/drivers/video/pm3fb.c
index 8e024aa..e0dad94 100644
--- a/drivers/video/pm3fb.c
+++ b/drivers/video/pm3fb.c
@@ -5,7 +5,7 @@
  *  Based on code written by:
  *           Sven Luther, <luther@dpt-info.u-strasbg.fr>
  *           Alan Hourihane, <alanh@fairlite.demon.co.uk>
- *           Russel King, <rmk@arm.linux.org.uk>
+ *           Russell King, <rmk@arm.linux.org.uk>
  *  Based on linux/drivers/video/skeletonfb.c:
  *	Copyright (C) 1997 Geert Uytterhoeven
  *  Based on linux/driver/video/pm2fb.c:
diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
index 815fbc8..16e37a5 100644
--- a/drivers/video/pxafb.c
+++ b/drivers/video/pxafb.c
@@ -43,6 +43,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
+#include <asm/div64.h>
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/bitfield.h>
 #include <asm/arch/pxafb.h>
@@ -460,7 +461,7 @@
          * speeds */
 
 	pcd = (unsigned long long)get_lcdclk_frequency_10khz() * pixclock;
-	pcd /= 100000000 * 2;
+	do_div(pcd, 100000000 * 2);
 	/* no need for this, since we should subtract 1 anyway. they cancel */
 	/* pcd += 1; */ /* make up for integer math truncations */
 	return (unsigned int)pcd;
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index b0c886d..6a9e183 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -1582,12 +1582,11 @@
 {
 	struct riva_par *par = (struct riva_par *) info->par;
 	u8 data[MAX_CURS * MAX_CURS/8];
-	u16 fg, bg;
 	int i, set = cursor->set;
+	u16 fg, bg;
 
-	if (cursor->image.width > MAX_CURS ||
-	    cursor->image.height > MAX_CURS)
-		return soft_cursor(info, cursor);
+	if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
+		return -ENXIO;
 
 	par->riva.ShowHideCursor(&par->riva, 0);
 
@@ -1625,21 +1624,18 @@
 		if (src) {
 			switch (cursor->rop) {
 			case ROP_XOR:
-				for (i = 0; i < s_pitch * cursor->image.height;
-				     i++)
+				for (i = 0; i < s_pitch * cursor->image.height; i++)
 					src[i] = dat[i] ^ msk[i];
 				break;
 			case ROP_COPY:
 			default:
-				for (i = 0; i < s_pitch * cursor->image.height;
-				     i++)
+				for (i = 0; i < s_pitch * cursor->image.height; i++)
 					src[i] = dat[i] & msk[i];
 				break;
 			}
 
-			fb_sysmove_buf_aligned(info, &info->pixmap, data,
-					       d_pitch, src, s_pitch,
-					       cursor->image.height);
+			fb_pad_aligned_buffer(data, d_pitch, src, s_pitch,
+						cursor->image.height);
 
 			bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
 				((info->cmap.green[bg_idx] & 0xf8) << 2) |
@@ -1727,6 +1723,7 @@
 
 	info->pixmap.size = 8 * 1024;
 	info->pixmap.buf_align = 4;
+	info->pixmap.access_align = 32;
 	info->pixmap.flags = FB_PIXMAP_SYSTEM;
 	info->var.yres_virtual = -1;
 	NVTRACE_LEAVE();
diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c
index b637c38..789de13 100644
--- a/drivers/video/s1d13xxxfb.c
+++ b/drivers/video/s1d13xxxfb.c
@@ -493,7 +493,7 @@
 }
 
 
-static int __devexit
+static int
 s1d13xxxfb_remove(struct device *dev)
 {
 	struct fb_info *info = dev_get_drvdata(dev);
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 03d74e8..8fadcda 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -1897,7 +1897,7 @@
 		info->pixmap.size = 8*1024;
 		info->pixmap.scan_align = 4;
 		info->pixmap.buf_align = 4;
-		info->pixmap.access_align = 4;
+		info->pixmap.access_align = 32;
 
 		fb_alloc_cmap (&info->cmap, NR_PALETTE, 0);
 		info->flags |= FBINFO_HWACCEL_COPYAREA |
diff --git a/drivers/video/softcursor.c b/drivers/video/softcursor.c
index 13a4511..229c4bc 100644
--- a/drivers/video/softcursor.c
+++ b/drivers/video/softcursor.c
@@ -58,17 +58,10 @@
 	} else 
 		memcpy(src, image->data, dsize);
 	
-	if (info->pixmap.outbuf)
-		fb_iomove_buf_aligned(info, &info->pixmap, dst, d_pitch, src,
-				  s_pitch, image->height);
-	else
-		fb_sysmove_buf_aligned(info, &info->pixmap, dst, d_pitch, src,
-				   s_pitch, image->height);
-
+	fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, image->height);
 	image->data = dst;
 	info->fbops->fb_imageblit(info, image);
 	kfree(src);
-
 	return 0;
 }
 
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index 3027841..9ed1a93 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -271,7 +271,7 @@
 
 	if (!request_mem_region(vesafb_fix.smem_start, size_total, "vesafb")) {
 		printk(KERN_WARNING
-		       "vesafb: abort, cannot reserve video memory at 0x%lx\n",
+		       "vesafb: cannot reserve video memory at 0x%lx\n",
 			vesafb_fix.smem_start);
 		/* We cannot make this fatal. Sometimes this comes from magic
 		   spaces our resource handlers simply don't know about */
@@ -279,13 +279,13 @@
 
 	info = framebuffer_alloc(sizeof(u32) * 256, &dev->dev);
 	if (!info) {
-		release_mem_region(vesafb_fix.smem_start, vesafb_fix.smem_len);
+		release_mem_region(vesafb_fix.smem_start, size_total);
 		return -ENOMEM;
 	}
 	info->pseudo_palette = info->par;
 	info->par = NULL;
 
-        info->screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len);
+	info->screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len);
 	if (!info->screen_base) {
 		printk(KERN_ERR
 		       "vesafb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n",
@@ -386,13 +386,14 @@
 	request_region(0x3c0, 32, "vesafb");
 
 	if (mtrr) {
-		int temp_size = size_total;
+		unsigned int temp_size = size_total;
 		/* Find the largest power-of-two */
 		while (temp_size & (temp_size - 1))
-                	temp_size &= (temp_size - 1);
-                        
-                /* Try and find a power of two to add */
-		while (temp_size && mtrr_add(vesafb_fix.smem_start, temp_size, MTRR_TYPE_WRCOMB, 1)==-EINVAL) {
+			temp_size &= (temp_size - 1);
+
+		/* Try and find a power of two to add */
+		while (temp_size > PAGE_SIZE &&
+			mtrr_add(vesafb_fix.smem_start, temp_size, MTRR_TYPE_WRCOMB, 1)==-EINVAL) {
 			temp_size >>= 1;
 		}
 	}
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index 58cd2ad..adcda69 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -101,7 +101,7 @@
  * Sysfs functions
  */
 
-static ssize_t rotation_show(struct device *dev, char *buf)
+static ssize_t rotation_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct fb_info *info = dev_get_drvdata(dev);
 	struct w100fb_par *par=info->par;
@@ -109,7 +109,7 @@
 	return sprintf(buf, "%d\n",par->rotation_flag);
 }
 
-static ssize_t rotation_store(struct device *dev, const char *buf, size_t count)
+static ssize_t rotation_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	unsigned int rotate;
 	struct fb_info *info = dev_get_drvdata(dev);
@@ -134,7 +134,7 @@
 
 static DEVICE_ATTR(rotation, 0644, rotation_show, rotation_store);
 
-static ssize_t w100fb_reg_read(struct device *dev, const char *buf, size_t count)
+static ssize_t w100fb_reg_read(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	unsigned long param;
 	unsigned long regs;
@@ -146,7 +146,7 @@
 
 static DEVICE_ATTR(reg_read, 0200, NULL, w100fb_reg_read);
 
-static ssize_t w100fb_reg_write(struct device *dev, const char *buf, size_t count)
+static ssize_t w100fb_reg_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	unsigned long regs;
 	unsigned long param;
@@ -163,7 +163,7 @@
 static DEVICE_ATTR(reg_write, 0200, NULL, w100fb_reg_write);
 
 
-static ssize_t fastsysclk_show(struct device *dev, char *buf)
+static ssize_t fastsysclk_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct fb_info *info = dev_get_drvdata(dev);
 	struct w100fb_par *par=info->par;
@@ -171,7 +171,7 @@
 	return sprintf(buf, "%d\n",par->fastsysclk_mode);
 }
 
-static ssize_t fastsysclk_store(struct device *dev, const char *buf, size_t count)
+static ssize_t fastsysclk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
 	int param;
 	struct fb_info *info = dev_get_drvdata(dev);
diff --git a/drivers/w1/Kconfig b/drivers/w1/Kconfig
index 2ab65c9..4f12079 100644
--- a/drivers/w1/Kconfig
+++ b/drivers/w1/Kconfig
@@ -3,9 +3,9 @@
 config W1
 	tristate "Dallas's 1-wire support"
 	---help---
-	  Dallas's 1-wire bus is usefull to connect slow 1-pin devices 
+	  Dallas's 1-wire bus is usefull to connect slow 1-pin devices
 	  such as iButtons and thermal sensors.
-	  
+
 	  If you want W1 support, you should say Y here.
 
 	  This W1 support can also be built as a module.  If so, the module
@@ -17,8 +17,8 @@
 	help
 	  Say Y here if you want to communicate with your 1-wire devices
 	  using Matrox's G400 GPIO pins.
-	  
-	  This support is also available as a module.  If so, the module 
+
+	  This support is also available as a module.  If so, the module
 	  will be called matrox_w1.ko.
 
 config W1_DS9490
@@ -27,17 +27,17 @@
 	help
 	  Say Y here if you want to have a driver for DS9490R UWB <-> W1 bridge.
 
-	  This support is also available as a module.  If so, the module 
+	  This support is also available as a module.  If so, the module
 	  will be called ds9490r.ko.
 
-config W1_DS9490_BRIDGE
+config W1_DS9490R_BRIDGE
 	tristate "DS9490R USB <-> W1 transport layer for 1-wire"
 	depends on W1_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 
+	  This support is also available as a module.  If so, the module
 	  will be called ds_w1_bridge.ko.
 
 config W1_THERM
@@ -51,7 +51,7 @@
 	tristate "Simple 64bit memory family implementation"
 	depends on W1
 	help
-	  Say Y here if you want to connect 1-wire 
+	  Say Y here if you want to connect 1-wire
 	  simple 64bit memory rom(ds2401/ds2411/ds1990*) to you wire.
 
 endmenu
diff --git a/drivers/w1/ds_w1_bridge.c b/drivers/w1/ds_w1_bridge.c
index 0baaeb5..7bddd8a 100644
--- a/drivers/w1/ds_w1_bridge.c
+++ b/drivers/w1/ds_w1_bridge.c
@@ -83,11 +83,11 @@
 	return byte;
 }
 
-static void ds9490r_write_block(unsigned long data, u8 *buf, int len)
+static void ds9490r_write_block(unsigned long data, const u8 *buf, int len)
 {
 	struct ds_device *dev = (struct ds_device *)data;
 
-	ds_write_block(dev, buf, len);
+	ds_write_block(dev, (u8 *)buf, len);
 }
 
 static u8 ds9490r_read_block(unsigned long data, u8 *buf, int len)
diff --git a/drivers/w1/matrox_w1.c b/drivers/w1/matrox_w1.c
index e565416..0b03f8f 100644
--- a/drivers/w1/matrox_w1.c
+++ b/drivers/w1/matrox_w1.c
@@ -1,8 +1,8 @@
 /*
- * 	matrox_w1.c
+ *	matrox_w1.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
@@ -59,7 +59,7 @@
 	.remove = __devexit_p(matrox_w1_remove),
 };
 
-/* 
+/*
  * Matrox G400 DDC registers.
  */
 
@@ -177,8 +177,8 @@
 
 	dev->bus_master = (struct w1_bus_master *)(dev + 1);
 
-	/* 
-	 * True for G400, for some other we need resource 0, see drivers/video/matrox/matroxfb_base.c 
+	/*
+	 * True for G400, for some other we need resource 0, see drivers/video/matrox/matroxfb_base.c
 	 */
 
 	dev->phys_addr = pci_resource_start(pdev, 1);
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 8d78218..312cf32 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -1,8 +1,8 @@
 /*
- * 	w1.c
+ *	w1.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
@@ -59,6 +59,19 @@
 static int control_needs_exit;
 static DECLARE_COMPLETION(w1_control_complete);
 
+/* stuff for the default family */
+static ssize_t w1_famdefault_read_name(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+	return(sprintf(buf, "%s\n", sl->name));
+}
+static struct w1_family_ops w1_default_fops = {
+	.rname = &w1_famdefault_read_name,
+};
+static struct w1_family w1_default_family = {
+	.fops = &w1_default_fops,
+};
+
 static int w1_master_match(struct device *dev, struct device_driver *drv)
 {
 	return 1;
@@ -88,7 +101,7 @@
 	complete(&sl->dev_released);
 }
 
-static ssize_t w1_default_read_name(struct device *dev, char *buf)
+static ssize_t w1_default_read_name(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	return sprintf(buf, "No family registered.\n");
 }
@@ -99,6 +112,20 @@
 	return sprintf(buf, "No family registered.\n");
 }
 
+static struct device_attribute w1_slave_attribute =
+	__ATTR(name, S_IRUGO, w1_default_read_name, NULL);
+
+static struct bin_attribute w1_slave_bin_attribute = {
+	.attr = {
+		.name = "w1_slave",
+		.mode = S_IRUGO,
+		.owner = THIS_MODULE,
+	},
+	.size = W1_SLAVE_DATA_SIZE,
+	.read = &w1_default_read_bin,
+};
+
+
 static struct bus_type w1_bus_type = {
 	.name = "w1",
 	.match = w1_master_match,
@@ -119,104 +146,118 @@
 	.release = &w1_master_release
 };
 
-static struct device_attribute w1_slave_attribute = {
-	.attr = {
-			.name = "name",
-			.mode = S_IRUGO,
-			.owner = THIS_MODULE
-	},
-	.show = &w1_default_read_name,
-};
-
-static struct device_attribute w1_slave_attribute_val = {
-	.attr = {
-			.name = "value",
-			.mode = S_IRUGO,
-			.owner = THIS_MODULE
-	},
-	.show = &w1_default_read_name,
-};
-
-static ssize_t w1_master_attribute_show_name(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_attribute *attr, char *buf)
 {
-	struct w1_master *md = container_of (dev, struct w1_master, dev);
+	struct w1_master *md = container_of(dev, struct w1_master, dev);
 	ssize_t count;
-	
+
 	if (down_interruptible (&md->mutex))
 		return -EBUSY;
 
 	count = sprintf(buf, "%s\n", md->name);
-	
+
 	up(&md->mutex);
 
 	return count;
 }
 
-static ssize_t w1_master_attribute_show_pointer(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_store_search(struct device * dev,
+						struct device_attribute *attr,
+						const char * buf, size_t count)
+{
+	struct w1_master *md = container_of(dev, struct w1_master, dev);
+
+	if (down_interruptible (&md->mutex))
+		return -EBUSY;
+
+	md->search_count = simple_strtol(buf, NULL, 0);
+
+	up(&md->mutex);
+
+	return count;
+}
+
+static ssize_t w1_master_attribute_show_search(struct device *dev,
+					       struct device_attribute *attr,
+					       char *buf)
 {
 	struct w1_master *md = container_of(dev, struct w1_master, dev);
 	ssize_t count;
-	
+
+	if (down_interruptible (&md->mutex))
+		return -EBUSY;
+
+	count = sprintf(buf, "%d\n", md->search_count);
+
+	up(&md->mutex);
+
+	return count;
+}
+
+static ssize_t w1_master_attribute_show_pointer(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct w1_master *md = container_of(dev, struct w1_master, dev);
+	ssize_t count;
+
 	if (down_interruptible(&md->mutex))
 		return -EBUSY;
 
 	count = sprintf(buf, "0x%p\n", md->bus_master);
-	
+
 	up(&md->mutex);
 	return count;
 }
 
-static ssize_t w1_master_attribute_show_timeout(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_timeout(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	ssize_t count;
 	count = sprintf(buf, "%d\n", w1_timeout);
 	return count;
 }
 
-static ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct w1_master *md = container_of(dev, struct w1_master, dev);
 	ssize_t count;
-	
+
 	if (down_interruptible(&md->mutex))
 		return -EBUSY;
 
 	count = sprintf(buf, "%d\n", md->max_slave_count);
-	
+
 	up(&md->mutex);
 	return count;
 }
 
-static ssize_t w1_master_attribute_show_attempts(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_attempts(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct w1_master *md = container_of(dev, struct w1_master, dev);
 	ssize_t count;
-	
+
 	if (down_interruptible(&md->mutex))
 		return -EBUSY;
 
 	count = sprintf(buf, "%lu\n", md->attempts);
-	
+
 	up(&md->mutex);
 	return count;
 }
 
-static ssize_t w1_master_attribute_show_slave_count(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_slave_count(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct w1_master *md = container_of(dev, struct w1_master, dev);
 	ssize_t count;
-	
+
 	if (down_interruptible(&md->mutex))
 		return -EBUSY;
 
 	count = sprintf(buf, "%d\n", md->slave_count);
-	
+
 	up(&md->mutex);
 	return count;
 }
 
-static ssize_t w1_master_attribute_show_slaves(struct device *dev, char *buf)
-
+static ssize_t w1_master_attribute_show_slaves(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct w1_master *md = container_of(dev, struct w1_master, dev);
 	int c = PAGE_SIZE;
@@ -233,7 +274,7 @@
 		list_for_each_safe(ent, n, &md->slist) {
 			sl = list_entry(ent, struct w1_slave, w1_slave_entry);
 
- 			c -= snprintf(buf + PAGE_SIZE - c, c, "%s\n", sl->name);
+			c -= snprintf(buf + PAGE_SIZE - c, c, "%s\n", sl->name);
 		}
 	}
 
@@ -242,73 +283,52 @@
 	return PAGE_SIZE - c;
 }
 
-static struct device_attribute w1_master_attribute_slaves = {
-	.attr = {
- 			.name = "w1_master_slaves",
-			.mode = S_IRUGO,
-			.owner = THIS_MODULE,
-	},
- 	.show = &w1_master_attribute_show_slaves,
-};
-static struct device_attribute w1_master_attribute_slave_count = {
-	.attr = {
-			.name = "w1_master_slave_count",
-			.mode = S_IRUGO,
-			.owner = THIS_MODULE
-	},
-	.show = &w1_master_attribute_show_slave_count,
-};
-static struct device_attribute w1_master_attribute_attempts = {
-	.attr = {
-			.name = "w1_master_attempts",
-			.mode = S_IRUGO,
-			.owner = THIS_MODULE
-	},
-	.show = &w1_master_attribute_show_attempts,
-};
-static struct device_attribute w1_master_attribute_max_slave_count = {
-	.attr = {
-			.name = "w1_master_max_slave_count",
-			.mode = S_IRUGO,
-			.owner = THIS_MODULE
-	},
-	.show = &w1_master_attribute_show_max_slave_count,
-};
-static struct device_attribute w1_master_attribute_timeout = {
-	.attr = {
-			.name = "w1_master_timeout",
-			.mode = S_IRUGO,
-			.owner = THIS_MODULE
-	},
-	.show = &w1_master_attribute_show_timeout,
-};
-static struct device_attribute w1_master_attribute_pointer = {
-	.attr = {
-			.name = "w1_master_pointer",
-			.mode = S_IRUGO,
-			.owner = THIS_MODULE
-	},
-	.show = &w1_master_attribute_show_pointer,
-};
-static struct device_attribute w1_master_attribute_name = {
-	.attr = {
-			.name = "w1_master_name",
-			.mode = S_IRUGO,
-			.owner = THIS_MODULE
-	},
-	.show = &w1_master_attribute_show_name,
+#define W1_MASTER_ATTR_RO(_name, _mode)				\
+	struct device_attribute w1_master_attribute_##_name =	\
+		__ATTR(w1_master_##_name, _mode,		\
+		       w1_master_attribute_show_##_name, NULL)
+
+#define W1_MASTER_ATTR_RW(_name, _mode)				\
+	struct device_attribute w1_master_attribute_##_name =	\
+		__ATTR(w1_master_##_name, _mode,		\
+		       w1_master_attribute_show_##_name,	\
+		       w1_master_attribute_store_##_name)
+
+static W1_MASTER_ATTR_RO(name, S_IRUGO);
+static W1_MASTER_ATTR_RO(slaves, S_IRUGO);
+static W1_MASTER_ATTR_RO(slave_count, S_IRUGO);
+static W1_MASTER_ATTR_RO(max_slave_count, S_IRUGO);
+static W1_MASTER_ATTR_RO(attempts, S_IRUGO);
+static W1_MASTER_ATTR_RO(timeout, S_IRUGO);
+static W1_MASTER_ATTR_RO(pointer, S_IRUGO);
+static W1_MASTER_ATTR_RW(search, S_IRUGO | S_IWUGO);
+
+static struct attribute *w1_master_default_attrs[] = {
+	&w1_master_attribute_name.attr,
+	&w1_master_attribute_slaves.attr,
+	&w1_master_attribute_slave_count.attr,
+	&w1_master_attribute_max_slave_count.attr,
+	&w1_master_attribute_attempts.attr,
+	&w1_master_attribute_timeout.attr,
+	&w1_master_attribute_pointer.attr,
+	&w1_master_attribute_search.attr,
+	NULL
 };
 
-static struct bin_attribute w1_slave_bin_attribute = {
-	.attr = {
-		 	.name = "w1_slave",
-		 	.mode = S_IRUGO,
-			.owner = THIS_MODULE,
-	},
-	.size = W1_SLAVE_DATA_SIZE,
-	.read = &w1_default_read_bin,
+static struct attribute_group w1_master_defattr_group = {
+	.attrs = w1_master_default_attrs,
 };
 
+int w1_create_master_attributes(struct w1_master *master)
+{
+	return sysfs_create_group(&master->dev.kobj, &w1_master_defattr_group);
+}
+
+void w1_destroy_master_attributes(struct w1_master *master)
+{
+	sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group);
+}
+
 static int __w1_attach_slave_device(struct w1_slave *sl)
 {
 	int err;
@@ -319,13 +339,13 @@
 	sl->dev.release = &w1_slave_release;
 
 	snprintf(&sl->dev.bus_id[0], sizeof(sl->dev.bus_id),
-		  "%02x-%012llx",
-		  (unsigned int) sl->reg_num.family,
-		  (unsigned long long) sl->reg_num.id);
-	snprintf (&sl->name[0], sizeof(sl->name),
-		  "%02x-%012llx",
-		  (unsigned int) sl->reg_num.family,
-		  (unsigned long long) sl->reg_num.id);
+		 "%02x-%012llx",
+		 (unsigned int) sl->reg_num.family,
+		 (unsigned long long) sl->reg_num.id);
+	snprintf(&sl->name[0], sizeof(sl->name),
+		 "%02x-%012llx",
+		 (unsigned int) sl->reg_num.family,
+		 (unsigned long long) sl->reg_num.id);
 
 	dev_dbg(&sl->dev, "%s: registering %s.\n", __func__,
 		&sl->dev.bus_id[0]);
@@ -333,48 +353,36 @@
 	err = device_register(&sl->dev);
 	if (err < 0) {
 		dev_err(&sl->dev,
-			 "Device registration [%s] failed. err=%d\n",
-			 sl->dev.bus_id, err);
+			"Device registration [%s] failed. err=%d\n",
+			sl->dev.bus_id, err);
 		return err;
 	}
 
 	memcpy(&sl->attr_bin, &w1_slave_bin_attribute, sizeof(sl->attr_bin));
 	memcpy(&sl->attr_name, &w1_slave_attribute, sizeof(sl->attr_name));
-	memcpy(&sl->attr_val, &w1_slave_attribute_val, sizeof(sl->attr_val));
-	
+
 	sl->attr_bin.read = sl->family->fops->rbin;
 	sl->attr_name.show = sl->family->fops->rname;
-	sl->attr_val.show = sl->family->fops->rval;
-	sl->attr_val.attr.name = sl->family->fops->rvalname;
 
 	err = device_create_file(&sl->dev, &sl->attr_name);
 	if (err < 0) {
 		dev_err(&sl->dev,
-			 "sysfs file creation for [%s] failed. err=%d\n",
-			 sl->dev.bus_id, err);
+			"sysfs file creation for [%s] failed. err=%d\n",
+			sl->dev.bus_id, err);
 		device_unregister(&sl->dev);
 		return err;
 	}
 
-	err = device_create_file(&sl->dev, &sl->attr_val);
-	if (err < 0) {
-		dev_err(&sl->dev,
-			 "sysfs file creation for [%s] failed. err=%d\n",
-			 sl->dev.bus_id, err);
-		device_remove_file(&sl->dev, &sl->attr_name);
-		device_unregister(&sl->dev);
-		return err;
-	}
-
-	err = sysfs_create_bin_file(&sl->dev.kobj, &sl->attr_bin);
-	if (err < 0) {
-		dev_err(&sl->dev,
-			 "sysfs file creation for [%s] failed. err=%d\n",
-			 sl->dev.bus_id, err);
-		device_remove_file(&sl->dev, &sl->attr_name);
-		device_remove_file(&sl->dev, &sl->attr_val);
-		device_unregister(&sl->dev);
-		return err;
+	if ( sl->attr_bin.read ) {
+		err = sysfs_create_bin_file(&sl->dev.kobj, &sl->attr_bin);
+		if (err < 0) {
+			dev_err(&sl->dev,
+				"sysfs file creation for [%s] failed. err=%d\n",
+				sl->dev.bus_id, err);
+			device_remove_file(&sl->dev, &sl->attr_name);
+			device_unregister(&sl->dev);
+			return err;
+		}
 	}
 
 	list_add_tail(&sl->w1_slave_entry, &sl->master->slist);
@@ -410,12 +418,10 @@
 	spin_lock(&w1_flock);
 	f = w1_family_registered(rn->family);
 	if (!f) {
-		spin_unlock(&w1_flock);
+		f= &w1_default_family;
 		dev_info(&dev->dev, "Family %x for %02x.%012llx.%02x is not registered.\n",
 			  rn->family, rn->family,
 			  (unsigned long long)rn->id, rn->crc);
-		kfree(sl);
-		return -ENODEV;
 	}
 	__w1_family_get(f);
 	spin_unlock(&w1_flock);
@@ -445,7 +451,7 @@
 static void w1_slave_detach(struct w1_slave *sl)
 {
 	struct w1_netlink_msg msg;
-	
+
 	dev_info(&sl->dev, "%s: detaching %s.\n", __func__, sl->name);
 
 	while (atomic_read(&sl->refcnt)) {
@@ -456,12 +462,15 @@
 			flush_signals(current);
 	}
 
-	sysfs_remove_bin_file (&sl->dev.kobj, &sl->attr_bin);
+	if ( sl->attr_bin.read ) {
+		sysfs_remove_bin_file (&sl->dev.kobj, &sl->attr_bin);
+	}
 	device_remove_file(&sl->dev, &sl->attr_name);
-	device_remove_file(&sl->dev, &sl->attr_val);
 	device_unregister(&sl->dev);
 	w1_family_put(sl->family);
 
+	sl->master->slave_count--;
+
 	memcpy(&msg.id.id, &sl->reg_num, sizeof(msg.id.id));
 	msg.type = W1_SLAVE_REMOVE;
 	w1_netlink_send(sl->master, &msg);
@@ -471,8 +480,8 @@
 {
 	struct w1_master *dev;
 	int found = 0;
-	
-	spin_lock_irq(&w1_mlock);
+
+	spin_lock_bh(&w1_mlock);
 	list_for_each_entry(dev, &w1_masters, w1_master_entry) {
 		if (dev->bus_master->data == data) {
 			found = 1;
@@ -480,12 +489,26 @@
 			break;
 		}
 	}
-	spin_unlock_irq(&w1_mlock);
+	spin_unlock_bh(&w1_mlock);
 
 	return (found)?dev:NULL;
 }
 
-void w1_slave_found(unsigned long data, u64 rn)
+void w1_reconnect_slaves(struct w1_family *f)
+{
+	struct w1_master *dev;
+
+	spin_lock_bh(&w1_mlock);
+	list_for_each_entry(dev, &w1_masters, w1_master_entry) {
+		dev_info(&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);
+}
+
+
+static void w1_slave_found(unsigned long data, u64 rn)
 {
 	int slave_count;
 	struct w1_slave *sl;
@@ -500,7 +523,7 @@
 				data);
 		return;
 	}
-	
+
 	tmp = (struct w1_reg_num *) &rn;
 
 	slave_count = 0;
@@ -513,8 +536,7 @@
 		    sl->reg_num.crc == tmp->crc) {
 			set_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
 			break;
-		}
-		else if (sl->reg_num.family == tmp->family) {
+		} else if (sl->reg_num.family == tmp->family) {
 			family_found = 1;
 			break;
 		}
@@ -528,30 +550,43 @@
 		rn && ((le64_to_cpu(rn) >> 56) & 0xff) == w1_calc_crc8((u8 *)&rn, 7)) {
 		w1_attach_slave_device(dev, tmp);
 	}
-			
+
 	atomic_dec(&dev->refcnt);
 }
 
-void w1_search(struct w1_master *dev)
+/**
+ * Performs a ROM Search & registers any devices found.
+ * The 1-wire search is a simple binary tree search.
+ * For each bit of the address, we read two bits and write one bit.
+ * The bit written will put to sleep all devies that don't match that bit.
+ * When the two reads differ, the direction choice is obvious.
+ * When both bits are 0, we must choose a path to take.
+ * When we can scan all 64 bits without having to choose a path, we are done.
+ *
+ * See "Application note 187 1-wire search algorithm" at www.maxim-ic.com
+ *
+ * @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)
 {
-	u64 last, rn, tmp;
-	int i, count = 0;
-	int last_family_desc, last_zero, last_device;
-	int search_bit, id_bit, comp_bit, desc_bit;
+	u64 last_rn, rn, tmp64;
+	int i, slave_count = 0;
+	int last_zero, last_device;
+	int search_bit, desc_bit;
+	u8  triplet_ret = 0;
 
-	search_bit = id_bit = comp_bit = 0;
-	rn = tmp = last = 0;
-	last_device = last_zero = last_family_desc = 0;
+	search_bit = 0;
+	rn = last_rn = 0;
+	last_device = 0;
+	last_zero = -1;
 
 	desc_bit = 64;
 
-	while (!(id_bit && comp_bit) && !last_device
-		&& count++ < dev->max_slave_count) {
-		last = rn;
+	while ( !last_device && (slave_count++ < dev->max_slave_count) ) {
+		last_rn = rn;
 		rn = 0;
 
-		last_family_desc = 0;
-
 		/*
 		 * Reset bus and all 1-wire device state machines
 		 * so they can respond to our requests.
@@ -563,94 +598,46 @@
 			break;
 		}
 
-#if 1
+		/* Start the search */
 		w1_write_8(dev, W1_SEARCH);
 		for (i = 0; i < 64; ++i) {
-			/*
-			 * Read 2 bits from bus.
-			 * All who don't sleep must send ID bit and COMPLEMENT ID bit.
-			 * They actually are ANDed between all senders.
-			 */
-			id_bit = w1_touch_bit(dev, 1);
-			comp_bit = w1_touch_bit(dev, 1);
+			/* Determine the direction/search bit */
+			if (i == desc_bit)
+				search_bit = 1;	  /* took the 0 path last time, so take the 1 path */
+			else if (i > desc_bit)
+				search_bit = 0;	  /* take the 0 path on the next branch */
+			else
+				search_bit = ((last_rn >> i) & 0x1);
 
-			if (id_bit && comp_bit)
+			/** Read two bits and write one bit */
+			triplet_ret = w1_triplet(dev, search_bit);
+
+			/* quit if no device responded */
+			if ( (triplet_ret & 0x03) == 0x03 )
 				break;
 
-			if (id_bit == 0 && comp_bit == 0) {
-				if (i == desc_bit)
-					search_bit = 1;
-				else if (i > desc_bit)
-					search_bit = 0;
-				else
-					search_bit = ((last >> i) & 0x1);
+			/* If both directions were valid, and we took the 0 path... */
+			if (triplet_ret == 0)
+				last_zero = i;
 
-				if (search_bit == 0) {
-					last_zero = i;
-					if (last_zero < 9)
-						last_family_desc = last_zero;
-				}
-
-			}
-			else
-				search_bit = id_bit;
-
-			tmp = search_bit;
-			rn |= (tmp << i);
-
-			/*
-			 * Write 1 bit to bus
-			 * and make all who don't have "search_bit" in "i"'th position
-			 * in it's registration number sleep.
-			 */
-			if (dev->bus_master->touch_bit)
-				w1_touch_bit(dev, search_bit);
-			else
-				w1_write_bit(dev, search_bit);
-
+			/* extract the direction taken & update the device number */
+			tmp64 = (triplet_ret >> 2);
+			rn |= (tmp64 << i);
 		}
-#endif
 
-		if (desc_bit == last_zero)
-			last_device = 1;
-
-		desc_bit = last_zero;
-	
-		w1_slave_found(dev->bus_master->data, rn);
+		if ( (triplet_ret & 0x03) != 0x03 ) {
+			if ( (desc_bit == last_zero) || (last_zero < 0))
+				last_device = 1;
+			desc_bit = last_zero;
+			cb(dev->bus_master->data, rn);
+		}
 	}
 }
 
-int w1_create_master_attributes(struct w1_master *dev)
+static int w1_control(void *data)
 {
-	if (	device_create_file(&dev->dev, &w1_master_attribute_slaves) < 0 ||
-		device_create_file(&dev->dev, &w1_master_attribute_slave_count) < 0 ||
-		device_create_file(&dev->dev, &w1_master_attribute_attempts) < 0 ||
-		device_create_file(&dev->dev, &w1_master_attribute_max_slave_count) < 0 ||
-		device_create_file(&dev->dev, &w1_master_attribute_timeout) < 0||
-		device_create_file(&dev->dev, &w1_master_attribute_pointer) < 0||
-		device_create_file(&dev->dev, &w1_master_attribute_name) < 0)
-		return -EINVAL;
-
-	return 0;
-}
-
-void w1_destroy_master_attributes(struct w1_master *dev)
-{
-	device_remove_file(&dev->dev, &w1_master_attribute_slaves);
-	device_remove_file(&dev->dev, &w1_master_attribute_slave_count);
-	device_remove_file(&dev->dev, &w1_master_attribute_attempts);
-	device_remove_file(&dev->dev, &w1_master_attribute_max_slave_count);
-	device_remove_file(&dev->dev, &w1_master_attribute_timeout);
-	device_remove_file(&dev->dev, &w1_master_attribute_pointer);
-	device_remove_file(&dev->dev, &w1_master_attribute_name);
-}
-
-
-int w1_control(void *data)
-{
-	struct w1_slave *sl;
-	struct w1_master *dev;
-	struct list_head *ent, *ment, *n, *mn;
+	struct w1_slave *sl, *sln;
+	struct w1_master *dev, *n;
 	int err, have_to_wait = 0;
 
 	daemonize("w1_control");
@@ -659,16 +646,14 @@
 	while (!control_needs_exit || have_to_wait) {
 		have_to_wait = 0;
 
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 		msleep_interruptible(w1_timeout * 1000);
 
 		if (signal_pending(current))
 			flush_signals(current);
 
-		list_for_each_safe(ment, mn, &w1_masters) {
-			dev = list_entry(ment, struct w1_master, w1_master_entry);
-
-			if (!control_needs_exit && !dev->need_exit)
+		list_for_each_entry_safe(dev, n, &w1_masters, w1_master_entry) {
+			if (!control_needs_exit && !dev->flags)
 				continue;
 			/*
 			 * Little race: we can create thread but not set the flag.
@@ -679,12 +664,8 @@
 				continue;
 			}
 
-			spin_lock(&w1_mlock);
-			list_del(&dev->w1_master_entry);
-			spin_unlock(&w1_mlock);
-
 			if (control_needs_exit) {
-				dev->need_exit = 1;
+				set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
 
 				err = kill_proc(dev->kpid, SIGTERM, 1);
 				if (err)
@@ -693,24 +674,42 @@
 						 dev->kpid);
 			}
 
-			wait_for_completion(&dev->dev_exited);
+			if (test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) {
+				wait_for_completion(&dev->dev_exited);
+				spin_lock_bh(&w1_mlock);
+				list_del(&dev->w1_master_entry);
+				spin_unlock_bh(&w1_mlock);
 
-			list_for_each_safe(ent, n, &dev->slist) {
-				sl = list_entry(ent, struct w1_slave, w1_slave_entry);
-
-				if (!sl)
-					dev_warn(&dev->dev,
-						  "%s: slave entry is NULL.\n",
-						  __func__);
-				else {
+				list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
 					list_del(&sl->w1_slave_entry);
 
 					w1_slave_detach(sl);
 					kfree(sl);
 				}
+				w1_destroy_master_attributes(dev);
+				atomic_dec(&dev->refcnt);
+				continue;
 			}
-			w1_destroy_master_attributes(dev);
-			atomic_dec(&dev->refcnt);
+
+			if (test_bit(W1_MASTER_NEED_RECONNECT, &dev->flags)) {
+				dev_info(&dev->dev, "Reconnecting slaves in device %s.\n", dev->name);
+				down(&dev->mutex);
+				list_for_each_entry(sl, &dev->slist, w1_slave_entry) {
+					if (sl->family->fid == W1_FAMILY_DEFAULT) {
+						struct w1_reg_num rn;
+						list_del(&sl->w1_slave_entry);
+						w1_slave_detach(sl);
+
+						memcpy(&rn, &sl->reg_num, sizeof(rn));
+
+						kfree(sl);
+
+						w1_attach_slave_device(dev, &rn);
+					}
+				}
+				clear_bit(W1_MASTER_NEED_RECONNECT, &dev->flags);
+				up(&dev->mutex);
+			}
 		}
 	}
 
@@ -720,51 +719,50 @@
 int w1_process(void *data)
 {
 	struct w1_master *dev = (struct w1_master *) data;
-	struct list_head *ent, *n;
-	struct w1_slave *sl;
+	struct w1_slave *sl, *sln;
 
 	daemonize("%s", dev->name);
 	allow_signal(SIGTERM);
 
-	while (!dev->need_exit) {
-		try_to_freeze(PF_FREEZE);
+	while (!test_bit(W1_MASTER_NEED_EXIT, &dev->flags)) {
+		try_to_freeze();
 		msleep_interruptible(w1_timeout * 1000);
 
 		if (signal_pending(current))
 			flush_signals(current);
 
-		if (dev->need_exit)
+		if (test_bit(W1_MASTER_NEED_EXIT, &dev->flags))
 			break;
 
 		if (!dev->initialized)
 			continue;
 
+		if (dev->search_count == 0)
+			continue;
+
 		if (down_interruptible(&dev->mutex))
 			continue;
 
-		list_for_each_safe(ent, n, &dev->slist) {
-			sl = list_entry(ent, struct w1_slave, w1_slave_entry);
+		list_for_each_entry(sl, &dev->slist, w1_slave_entry)
+			clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
 
-			if (sl)
-				clear_bit(W1_SLAVE_ACTIVE, (long *)&sl->flags);
-		}
-		
 		w1_search_devices(dev, w1_slave_found);
 
-		list_for_each_safe(ent, n, &dev->slist) {
-			sl = list_entry(ent, struct w1_slave, w1_slave_entry);
-
-			if (sl && !test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) {
+		list_for_each_entry_safe(sl, sln, &dev->slist, w1_slave_entry) {
+			if (!test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags) && !--sl->ttl) {
 				list_del (&sl->w1_slave_entry);
 
 				w1_slave_detach (sl);
 				kfree (sl);
 
 				dev->slave_count--;
-			}
-			else if (test_bit(W1_SLAVE_ACTIVE, (unsigned long *)&sl->flags))
+			} 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);
 	}
 
@@ -774,7 +772,7 @@
 	return 0;
 }
 
-int w1_init(void)
+static int w1_init(void)
 {
 	int retval;
 
@@ -814,18 +812,14 @@
 	return retval;
 }
 
-void w1_fini(void)
+static void w1_fini(void)
 {
 	struct w1_master *dev;
-	struct list_head *ent, *n;
 
-	list_for_each_safe(ent, n, &w1_masters) {
-		dev = list_entry(ent, struct w1_master, w1_master_entry);
+	list_for_each_entry(dev, &w1_masters, w1_master_entry)
 		__w1_remove_master_device(dev);
-	}
 
 	control_needs_exit = 1;
-
 	wait_for_completion(&w1_control_complete);
 
 	driver_unregister(&w1_driver);
diff --git a/drivers/w1/w1.h b/drivers/w1/w1.h
index abbddaf..4f0a986 100644
--- a/drivers/w1/w1.h
+++ b/drivers/w1/w1.h
@@ -1,8 +1,8 @@
 /*
- * 	w1.h
+ *	w1.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
@@ -74,36 +74,86 @@
 	int			ttl;
 
 	struct w1_master	*master;
-	struct w1_family 	*family;
-	struct device 		dev;
-	struct completion 	dev_released;
+	struct w1_family	*family;
+	struct device		dev;
+	struct completion	dev_released;
 
-	struct bin_attribute 	attr_bin;
-	struct device_attribute	attr_name, attr_val;
+	struct bin_attribute	attr_bin;
+	struct device_attribute	attr_name;
 };
 
 typedef void (* w1_slave_found_callback)(unsigned long, u64);
 
+
+/**
+ * Note: read_bit and write_bit are very low level functions and should only
+ * be used with hardware that doesn't really support 1-wire operations,
+ * like a parallel/serial port.
+ * Either define read_bit and write_bit OR define, at minimum, touch_bit and
+ * reset_bus.
+ */
 struct w1_bus_master
 {
-	unsigned long		data;
+	/** the first parameter in all the functions below */
+	unsigned long	data;
 
-	u8			(*read_bit)(unsigned long);
-	void			(*write_bit)(unsigned long, u8);
-  	
-	u8			(*read_byte)(unsigned long);
-  	void			(*write_byte)(unsigned long, u8);
-  	
-	u8			(*read_block)(unsigned long, u8 *, int);
-	void			(*write_block)(unsigned long, u8 *, int);
-	
-  	u8			(*touch_bit)(unsigned long, u8);
-  
-  	u8			(*reset_bus)(unsigned long);
+	/**
+	 * Sample the line level
+	 * @return the level read (0 or 1)
+	 */
+	u8		(*read_bit)(unsigned long);
 
-	void			(*search)(unsigned long, w1_slave_found_callback);
+	/** Sets the line level */
+	void		(*write_bit)(unsigned long, u8);
+
+	/**
+	 * touch_bit is the lowest-level function for devices that really
+	 * support the 1-wire protocol.
+	 * touch_bit(0) = write-0 cycle
+	 * touch_bit(1) = write-1 / read cycle
+	 * @return the bit read (0 or 1)
+	 */
+	u8		(*touch_bit)(unsigned long, u8);
+
+	/**
+	 * Reads a bytes. Same as 8 touch_bit(1) calls.
+	 * @return the byte read
+	 */
+	u8		(*read_byte)(unsigned long);
+
+	/**
+	 * Writes a byte. Same as 8 touch_bit(x) calls.
+	 */
+	void		(*write_byte)(unsigned long, u8);
+
+	/**
+	 * Same as a series of read_byte() calls
+	 * @return the number of bytes read
+	 */
+	u8		(*read_block)(unsigned long, u8 *, int);
+
+	/** Same as a series of write_byte() calls */
+	void		(*write_block)(unsigned long, const u8 *, int);
+
+	/**
+	 * Combines two reads and a smart write for ROM searches
+	 * @return bit0=Id bit1=comp_id bit2=dir_taken
+	 */
+	u8		(*triplet)(unsigned long, u8);
+
+	/**
+	 * long write-0 with a read for the presence pulse detection
+	 * @return -1=Error, 0=Device present, 1=No device present
+	 */
+	u8		(*reset_bus)(unsigned long);
+
+	/** Really nice hardware can handles the ROM searches */
+	void		(*search)(unsigned long, w1_slave_found_callback);
 };
 
+#define W1_MASTER_NEED_EXIT		0
+#define W1_MASTER_NEED_RECONNECT	1
+
 struct w1_master
 {
 	struct list_head	w1_master_entry;
@@ -115,30 +165,31 @@
 	int			slave_ttl;
 	int			initialized;
 	u32			id;
+	int			search_count;
 
 	atomic_t		refcnt;
 
 	void			*priv;
 	int			priv_size;
 
-	int			need_exit;
+	long			flags;
+
 	pid_t			kpid;
-	struct semaphore 	mutex;
+	struct semaphore	mutex;
 
 	struct device_driver	*driver;
-	struct device 		dev;
-	struct completion 	dev_released;
-	struct completion 	dev_exited;
+	struct device		dev;
+	struct completion	dev_released;
+	struct completion	dev_exited;
 
 	struct w1_bus_master	*bus_master;
 
 	u32			seq, groups;
-	struct sock 		*nls;
+	struct sock		*nls;
 };
 
 int w1_create_master_attributes(struct w1_master *);
-void w1_destroy_master_attributes(struct w1_master *);
-void w1_search(struct w1_master *dev);
+void w1_search(struct w1_master *dev, w1_slave_found_callback cb);
 
 #endif /* __KERNEL__ */
 
diff --git a/drivers/w1/w1_family.c b/drivers/w1/w1_family.c
index d1d56ec..02eee57 100644
--- a/drivers/w1/w1_family.c
+++ b/drivers/w1/w1_family.c
@@ -1,8 +1,8 @@
 /*
- * 	w1_family.c
+ *	w1_family.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
@@ -27,10 +27,11 @@
 
 DEFINE_SPINLOCK(w1_flock);
 static LIST_HEAD(w1_families);
+extern void w1_reconnect_slaves(struct w1_family *f);
 
 static int w1_check_family(struct w1_family *f)
 {
-	if (!f->fops->rname || !f->fops->rbin || !f->fops->rval || !f->fops->rvalname)
+	if (!f->fops->rname || !f->fops->rbin)
 		return -EINVAL;
 
 	return 0;
@@ -60,9 +61,10 @@
 		newf->need_exit = 0;
 		list_add_tail(&newf->family_entry, &w1_families);
 	}
-
 	spin_unlock(&w1_flock);
 
+	w1_reconnect_slaves(newf);
+
 	return ret;
 }
 
diff --git a/drivers/w1/w1_family.h b/drivers/w1/w1_family.h
index 03a2de7..b26da01 100644
--- a/drivers/w1/w1_family.h
+++ b/drivers/w1/w1_family.h
@@ -1,8 +1,8 @@
 /*
- * 	w1_family.h
+ *	w1_family.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
@@ -27,27 +27,27 @@
 #include <asm/atomic.h>
 
 #define W1_FAMILY_DEFAULT	0
-#define W1_FAMILY_THERM		0x10
-#define W1_FAMILY_SMEM		0x01
+#define W1_FAMILY_SMEM_01	0x01
+#define W1_FAMILY_SMEM_81	0x81
+#define W1_THERM_DS18S20 	0x10
+#define W1_THERM_DS1822  	0x22
+#define W1_THERM_DS18B20 	0x28
 
 #define MAXNAMELEN		32
 
 struct w1_family_ops
 {
-	ssize_t (* rname)(struct device *, char *);
+	ssize_t (* rname)(struct device *, struct device_attribute *, char *);
 	ssize_t (* rbin)(struct kobject *, char *, loff_t, size_t);
-	
-	ssize_t (* rval)(struct device *, char *);
-	unsigned char rvalname[MAXNAMELEN];
 };
 
 struct w1_family
 {
 	struct list_head	family_entry;
 	u8			fid;
-	
+
 	struct w1_family_ops	*fops;
-	
+
 	atomic_t		refcnt;
 	u8			need_exit;
 };
diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c
index 5f0bafb..35e85d9 100644
--- a/drivers/w1/w1_int.c
+++ b/drivers/w1/w1_int.c
@@ -1,8 +1,8 @@
 /*
- * 	w1_int.c
+ *	w1_int.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
@@ -39,8 +39,9 @@
 
 extern int w1_process(void *);
 
-struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
-	      struct device_driver *driver, struct device *device)
+static struct w1_master * w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
+				       struct device_driver *driver,
+				       struct device *device)
 {
 	struct w1_master *dev;
 	int err;
@@ -60,14 +61,15 @@
 
 	dev->bus_master = (struct w1_bus_master *)(dev + 1);
 
-	dev->owner 		= THIS_MODULE;
-	dev->max_slave_count 	= slave_count;
-	dev->slave_count 	= 0;
-	dev->attempts 		= 0;
-	dev->kpid 		= -1;
-	dev->initialized 	= 0;
-	dev->id 		= id;
+	dev->owner		= THIS_MODULE;
+	dev->max_slave_count	= slave_count;
+	dev->slave_count	= 0;
+	dev->attempts		= 0;
+	dev->kpid		= -1;
+	dev->initialized	= 0;
+	dev->id			= id;
 	dev->slave_ttl		= slave_ttl;
+        dev->search_count	= -1; /* continual scan */
 
 	atomic_set(&dev->refcnt, 2);
 
@@ -105,7 +107,7 @@
 	return dev;
 }
 
-void w1_free_dev(struct w1_master *dev)
+static void w1_free_dev(struct w1_master *dev)
 {
 	device_unregister(&dev->dev);
 	if (dev->nls && dev->nls->sk_socket)
@@ -120,6 +122,13 @@
 	int retval = 0;
 	struct w1_netlink_msg msg;
 
+        /* validate minimum functionality */
+        if (!(master->touch_bit && master->reset_bus) &&
+            !(master->write_bit && master->read_bit)) {
+		printk(KERN_ERR "w1_add_master_device: invalid function set\n");
+		return(-EINVAL);
+        }
+
 	dev = w1_alloc_dev(w1_ids++, w1_max_slave_count, w1_max_slave_ttl, &w1_driver, &w1_device);
 	if (!dev)
 		return -ENOMEM;
@@ -153,7 +162,7 @@
 	return 0;
 
 err_out_kill_thread:
-	dev->need_exit = 1;
+	set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
 	if (kill_proc(dev->kpid, SIGTERM, 1))
 		dev_err(&dev->dev,
 			 "Failed to send signal to w1 kernel thread %d.\n",
@@ -171,7 +180,7 @@
 	int err;
 	struct w1_netlink_msg msg;
 
-	dev->need_exit = 1;
+	set_bit(W1_MASTER_NEED_EXIT, &dev->flags);
 	err = kill_proc(dev->kpid, SIGTERM, 1);
 	if (err)
 		dev_err(&dev->dev,
@@ -197,10 +206,8 @@
 void w1_remove_master_device(struct w1_bus_master *bm)
 {
 	struct w1_master *dev = NULL;
-	struct list_head *ent, *n;
 
-	list_for_each_safe(ent, n, &w1_masters) {
-		dev = list_entry(ent, struct w1_master, w1_master_entry);
+	list_for_each_entry(dev, &w1_masters, w1_master_entry) {
 		if (!dev->initialized)
 			continue;
 
diff --git a/drivers/w1/w1_int.h b/drivers/w1/w1_int.h
index fdb531e..4274082 100644
--- a/drivers/w1/w1_int.h
+++ b/drivers/w1/w1_int.h
@@ -1,8 +1,8 @@
 /*
- * 	w1_int.h
+ *	w1_int.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
@@ -27,8 +27,6 @@
 
 #include "w1.h"
 
-struct w1_master * w1_alloc_dev(u32, int, int, struct device_driver *, struct device *);
-void w1_free_dev(struct w1_master *dev);
 int w1_add_master_device(struct w1_bus_master *);
 void w1_remove_master_device(struct w1_bus_master *);
 void __w1_remove_master_device(struct w1_master *);
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c
index 02796b5..00f0322 100644
--- a/drivers/w1/w1_io.c
+++ b/drivers/w1/w1_io.c
@@ -1,8 +1,8 @@
 /*
- * 	w1_io.c
+ *	w1_io.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
@@ -55,15 +55,29 @@
 	udelay(tm * w1_delay_parm);
 }
 
+static void w1_write_bit(struct w1_master *dev, int bit);
+static u8 w1_read_bit(struct w1_master *dev);
+
+/**
+ * Generates a write-0 or write-1 cycle and samples the level.
+ */
 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);
-	else
+	else if (bit)
 		return w1_read_bit(dev);
+	else {
+		w1_write_bit(dev, 0);
+		return(0);
+	}
 }
 
-void w1_write_bit(struct w1_master *dev, int bit)
+/**
+ * Generates a write-0 or write-1 cycle.
+ * Only call if dev->bus_master->touch_bit is NULL
+ */
+static void w1_write_bit(struct w1_master *dev, int bit)
 {
 	if (bit) {
 		dev->bus_master->write_bit(dev->bus_master->data, 0);
@@ -78,6 +92,12 @@
 	}
 }
 
+/**
+ * Writes 8 bits.
+ *
+ * @param dev     the master device
+ * @param byte    the byte to write
+ */
 void w1_write_8(struct w1_master *dev, u8 byte)
 {
 	int i;
@@ -86,10 +106,15 @@
 		dev->bus_master->write_byte(dev->bus_master->data, byte);
 	else
 		for (i = 0; i < 8; ++i)
-			w1_write_bit(dev, (byte >> i) & 0x1);
+			w1_touch_bit(dev, (byte >> i) & 0x1);
 }
 
-u8 w1_read_bit(struct w1_master *dev)
+
+/**
+ * Generates a write-1 cycle and samples the level.
+ * Only call if dev->bus_master->touch_bit is NULL
+ */
+static u8 w1_read_bit(struct w1_master *dev)
 {
 	int result;
 
@@ -104,6 +129,53 @@
 	return result & 0x1;
 }
 
+/**
+ * Does a triplet - used for searching ROM addresses.
+ * Return bits:
+ *  bit 0 = id_bit
+ *  bit 1 = comp_bit
+ *  bit 2 = dir_taken
+ * If both bits 0 & 1 are set, the search should be restarted.
+ *
+ * @param dev     the master device
+ * @param bdir    the bit to write if both id_bit and comp_bit are 0
+ * @return        bit fields - see above
+ */
+u8 w1_triplet(struct w1_master *dev, int bdir)
+{
+	if ( dev->bus_master->triplet )
+		return(dev->bus_master->triplet(dev->bus_master->data, bdir));
+	else {
+		u8 id_bit   = w1_touch_bit(dev, 1);
+		u8 comp_bit = w1_touch_bit(dev, 1);
+		u8 retval;
+
+		if ( id_bit && comp_bit )
+			return(0x03);  /* error */
+
+		if ( !id_bit && !comp_bit ) {
+			/* Both bits are valid, take the direction given */
+			retval = bdir ? 0x04 : 0;
+		} else {
+			/* Only one bit is valid, take that direction */
+			bdir = id_bit;
+			retval = id_bit ? 0x05 : 0x02;
+		}
+
+		if ( dev->bus_master->touch_bit )
+			w1_touch_bit(dev, bdir);
+		else
+			w1_write_bit(dev, bdir);
+		return(retval);
+	}
+}
+
+/**
+ * Reads 8 bits.
+ *
+ * @param dev     the master device
+ * @return        the byte read
+ */
 u8 w1_read_8(struct w1_master * dev)
 {
 	int i;
@@ -113,12 +185,20 @@
 		res = dev->bus_master->read_byte(dev->bus_master->data);
 	else
 		for (i = 0; i < 8; ++i)
-			res |= (w1_read_bit(dev) << i);
+			res |= (w1_touch_bit(dev,1) << i);
 
 	return res;
 }
 
-void w1_write_block(struct w1_master *dev, u8 *buf, int len)
+/**
+ * Writes a series of bytes.
+ *
+ * @param dev     the master device
+ * @param buf     pointer to the data to write
+ * @param len     the number of bytes to write
+ * @return        the byte read
+ */
+void w1_write_block(struct w1_master *dev, const u8 *buf, int len)
 {
 	int i;
 
@@ -129,6 +209,14 @@
 			w1_write_8(dev, buf[i]);
 }
 
+/**
+ * Reads a series of bytes.
+ *
+ * @param dev     the master device
+ * @param buf     pointer to the buffer to fill
+ * @param len     the number of bytes to read
+ * @return        the number of bytes read
+ */
 u8 w1_read_block(struct w1_master *dev, u8 *buf, int len)
 {
 	int i;
@@ -145,9 +233,15 @@
 	return ret;
 }
 
+/**
+ * Issues a reset bus sequence.
+ *
+ * @param  dev The bus master pointer
+ * @return     0=Device present, 1=No device present or error
+ */
 int w1_reset_bus(struct w1_master *dev)
 {
-	int result = 0;
+	int result;
 
 	if (dev->bus_master->reset_bus)
 		result = dev->bus_master->reset_bus(dev->bus_master->data) & 0x1;
@@ -180,12 +274,11 @@
 	if (dev->bus_master->search)
 		dev->bus_master->search(dev->bus_master->data, cb);
 	else
-		w1_search(dev);
+		w1_search(dev, cb);
 }
 
-EXPORT_SYMBOL(w1_write_bit);
+EXPORT_SYMBOL(w1_touch_bit);
 EXPORT_SYMBOL(w1_write_8);
-EXPORT_SYMBOL(w1_read_bit);
 EXPORT_SYMBOL(w1_read_8);
 EXPORT_SYMBOL(w1_reset_bus);
 EXPORT_SYMBOL(w1_calc_crc8);
diff --git a/drivers/w1/w1_io.h b/drivers/w1/w1_io.h
index 6c57300..af58297 100644
--- a/drivers/w1/w1_io.h
+++ b/drivers/w1/w1_io.h
@@ -1,8 +1,8 @@
 /*
- * 	w1_io.h
+ *	w1_io.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
@@ -26,13 +26,12 @@
 
 void w1_delay(unsigned long);
 u8 w1_touch_bit(struct w1_master *, int);
-void w1_write_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_bit(struct w1_master *);
 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 *, u8 *, int);
+void w1_write_block(struct w1_master *, const u8 *, int);
 u8 w1_read_block(struct w1_master *, u8 *, int);
 void w1_search_devices(struct w1_master *dev, w1_slave_found_callback cb);
 
diff --git a/drivers/w1/w1_log.h b/drivers/w1/w1_log.h
index a6bf6f4..fe6bdf4 100644
--- a/drivers/w1/w1_log.h
+++ b/drivers/w1/w1_log.h
@@ -1,8 +1,8 @@
 /*
- * 	w1_log.h
+ *	w1_log.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
diff --git a/drivers/w1/w1_netlink.h b/drivers/w1/w1_netlink.h
index ea1b530..8615756 100644
--- a/drivers/w1/w1_netlink.h
+++ b/drivers/w1/w1_netlink.h
@@ -33,13 +33,13 @@
 	W1_MASTER_REMOVE,
 };
 
-struct w1_netlink_msg 
+struct w1_netlink_msg
 {
 	__u8				type;
 	__u8				reserved[3];
 	union
 	{
-		struct w1_reg_num 	id;
+		struct w1_reg_num	id;
 		__u64			w1_id;
 		struct
 		{
diff --git a/drivers/w1/w1_smem.c b/drivers/w1/w1_smem.c
index a54e425..70d2d46 100644
--- a/drivers/w1/w1_smem.c
+++ b/drivers/w1/w1_smem.c
@@ -1,8 +1,8 @@
 /*
- * 	w1_smem.c
+ *	w1_smem.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 smems of the GNU General Public License as published by
@@ -36,41 +36,25 @@
 MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>");
 MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, 64bit memory family.");
 
-static ssize_t w1_smem_read_name(struct device *, char *);
-static ssize_t w1_smem_read_val(struct device *, char *);
+static ssize_t w1_smem_read_name(struct device *, struct device_attribute *attr, char *);
 static ssize_t w1_smem_read_bin(struct kobject *, char *, loff_t, size_t);
 
 static struct w1_family_ops w1_smem_fops = {
 	.rname = &w1_smem_read_name,
 	.rbin = &w1_smem_read_bin,
-	.rval = &w1_smem_read_val,
-	.rvalname = "id",
 };
 
-static ssize_t w1_smem_read_name(struct device *dev, char *buf)
+static ssize_t w1_smem_read_name(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
 
 	return sprintf(buf, "%s\n", sl->name);
 }
 
-static ssize_t w1_smem_read_val(struct device *dev, char *buf)
-{
-	struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
-	int i;
-	ssize_t count = 0;
-	
-	for (i = 0; i < 8; ++i)
-		count += sprintf(buf + count, "%02x ", ((u8 *)&sl->reg_num)[i]);
-	count += sprintf(buf + count, "\n");
-
-	return count;
-}
-
 static ssize_t w1_smem_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
 {
 	struct w1_slave *sl = container_of(container_of(kobj, struct device, kobj),
-			      			struct w1_slave, dev);
+					   struct w1_slave, dev);
 	int i;
 
 	atomic_inc(&sl->refcnt);
@@ -90,7 +74,7 @@
 	for (i = 0; i < 8; ++i)
 		count += sprintf(buf + count, "%02x ", ((u8 *)&sl->reg_num)[i]);
 	count += sprintf(buf + count, "\n");
-	
+
 out:
 	up(&sl->master->mutex);
 out_dec:
@@ -99,19 +83,37 @@
 	return count;
 }
 
-static struct w1_family w1_smem_family = {
-	.fid = W1_FAMILY_SMEM,
+static struct w1_family w1_smem_family_01 = {
+	.fid = W1_FAMILY_SMEM_01,
+	.fops = &w1_smem_fops,
+};
+
+static struct w1_family w1_smem_family_81 = {
+	.fid = W1_FAMILY_SMEM_81,
 	.fops = &w1_smem_fops,
 };
 
 static int __init w1_smem_init(void)
 {
-	return w1_register_family(&w1_smem_family);
+	int err;
+
+	err = w1_register_family(&w1_smem_family_01);
+	if (err)
+		return err;
+	
+	err = w1_register_family(&w1_smem_family_81);
+	if (err) {
+		w1_unregister_family(&w1_smem_family_01);
+		return err;
+	}
+
+	return 0;
 }
 
 static void __exit w1_smem_fini(void)
 {
-	w1_unregister_family(&w1_smem_family);
+	w1_unregister_family(&w1_smem_family_01);
+	w1_unregister_family(&w1_smem_family_81);
 }
 
 module_init(w1_smem_init);
diff --git a/drivers/w1/w1_therm.c b/drivers/w1/w1_therm.c
index 0b18178..165526c 100644
--- a/drivers/w1/w1_therm.c
+++ b/drivers/w1/w1_therm.c
@@ -1,8 +1,8 @@
 /*
- * 	w1_therm.c
+ *	w1_therm.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 therms of the GNU General Public License as published by
@@ -38,31 +38,78 @@
 MODULE_DESCRIPTION("Driver for 1-wire Dallas network protocol, temperature family.");
 
 static u8 bad_roms[][9] = {
-				{0xaa, 0x00, 0x4b, 0x46, 0xff, 0xff, 0x0c, 0x10, 0x87}, 
+				{0xaa, 0x00, 0x4b, 0x46, 0xff, 0xff, 0x0c, 0x10, 0x87},
 				{}
 			};
 
-static ssize_t w1_therm_read_name(struct device *, char *);
-static ssize_t w1_therm_read_temp(struct device *, char *);
+static ssize_t w1_therm_read_name(struct device *, struct device_attribute *attr, char *);
 static ssize_t w1_therm_read_bin(struct kobject *, char *, loff_t, size_t);
 
 static struct w1_family_ops w1_therm_fops = {
 	.rname = &w1_therm_read_name,
 	.rbin = &w1_therm_read_bin,
-	.rval = &w1_therm_read_temp,
-	.rvalname = "temp1_input",
 };
 
-static ssize_t w1_therm_read_name(struct device *dev, char *buf)
+static struct w1_family w1_therm_family_DS18S20 = {
+	.fid = W1_THERM_DS18S20,
+	.fops = &w1_therm_fops,
+};
+
+static struct w1_family w1_therm_family_DS18B20 = {
+	.fid = W1_THERM_DS18B20,
+	.fops = &w1_therm_fops,
+};
+static struct w1_family w1_therm_family_DS1822 = {
+	.fid = W1_THERM_DS1822,
+	.fops = &w1_therm_fops,
+};
+
+struct w1_therm_family_converter
+{
+	u8			broken;
+	u16			reserved;
+	struct w1_family	*f;
+	int			(*convert)(u8 rom[9]);
+};
+
+static inline int w1_DS18B20_convert_temp(u8 rom[9]);
+static inline int w1_DS18S20_convert_temp(u8 rom[9]);
+
+static struct w1_therm_family_converter w1_therm_families[] = {
+	{
+		.f		= &w1_therm_family_DS18S20,
+		.convert 	= w1_DS18S20_convert_temp
+	},
+	{
+		.f		= &w1_therm_family_DS1822,
+		.convert 	= w1_DS18B20_convert_temp
+	},
+	{
+		.f		= &w1_therm_family_DS18B20,
+		.convert 	= w1_DS18B20_convert_temp
+	},
+};
+
+static ssize_t w1_therm_read_name(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
 
 	return sprintf(buf, "%s\n", sl->name);
 }
 
-static inline int w1_convert_temp(u8 rom[9])
+static inline int w1_DS18B20_convert_temp(u8 rom[9])
+{
+	int t = (rom[1] << 8) | rom[0];
+	t /= 16;
+	return t;
+}
+
+static inline int w1_DS18S20_convert_temp(u8 rom[9])
 {
 	int t, h;
+
+	if (!rom[7])
+		return 0;
 	
 	if (rom[1] == 0)
 		t = ((s32)rom[0] >> 1)*1000;
@@ -77,11 +124,15 @@
 	return t;
 }
 
-static ssize_t w1_therm_read_temp(struct device *dev, char *buf)
+static inline int w1_convert_temp(u8 rom[9], u8 fid)
 {
-	struct w1_slave *sl = container_of(dev, struct w1_slave, dev);
+	int i;
 
-	return sprintf(buf, "%d\n", w1_convert_temp(sl->rom));
+	for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i)
+		if (w1_therm_families[i].f->fid == fid)
+			return w1_therm_families[i].convert(rom);
+
+	return 0;
 }
 
 static int w1_therm_check_rom(u8 rom[9])
@@ -98,7 +149,7 @@
 static ssize_t w1_therm_read_bin(struct kobject *kobj, char *buf, loff_t off, size_t count)
 {
 	struct w1_slave *sl = container_of(container_of(kobj, struct device, kobj),
-			      			struct w1_slave, dev);
+					   struct w1_slave, dev);
 	struct w1_master *dev = sl->master;
 	u8 rom[9], crc, verdict;
 	int i, max_trying = 10;
@@ -133,7 +184,7 @@
 			unsigned int tm = 750;
 
 			memcpy(&match[1], (u64 *) & sl->reg_num, 8);
-			
+
 			w1_write_block(dev, match, 9);
 
 			w1_write_8(dev, W1_CONVERT_TEMP);
@@ -146,7 +197,7 @@
 
 			if (!w1_reset_bus (dev)) {
 				w1_write_block(dev, match, 9);
-				
+
 				w1_write_8(dev, W1_READ_SCRATCHPAD);
 				if ((count = w1_read_block(dev, rom, 9)) != 9) {
 					dev_warn(&dev->dev, "w1_read_block() returned %d instead of 9.\n", count);
@@ -176,7 +227,7 @@
 	for (i = 0; i < 9; ++i)
 		count += sprintf(buf + count, "%02x ", sl->rom[i]);
 	
-	count += sprintf(buf + count, "t=%d\n", w1_convert_temp(rom));
+	count += sprintf(buf + count, "t=%d\n", w1_convert_temp(rom, sl->family->fid));
 out:
 	up(&dev->mutex);
 out_dec:
@@ -186,19 +237,26 @@
 	return count;
 }
 
-static struct w1_family w1_therm_family = {
-	.fid = W1_FAMILY_THERM,
-	.fops = &w1_therm_fops,
-};
-
 static int __init w1_therm_init(void)
 {
-	return w1_register_family(&w1_therm_family);
+	int err, i;
+
+	for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i) {
+		err = w1_register_family(w1_therm_families[i].f);
+		if (err)
+			w1_therm_families[i].broken = 1;
+	}
+
+	return 0;
 }
 
 static void __exit w1_therm_fini(void)
 {
-	w1_unregister_family(&w1_therm_family);
+	int i;
+
+	for (i=0; i<sizeof(w1_therm_families)/sizeof(w1_therm_families[0]); ++i)
+		if (!w1_therm_families[i].broken)
+			w1_unregister_family(w1_therm_families[i].f);
 }
 
 module_init(w1_therm_init);
diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c
index dad03fc..04ca884 100644
--- a/drivers/zorro/zorro-sysfs.c
+++ b/drivers/zorro/zorro-sysfs.c
@@ -21,7 +21,7 @@
 /* show configuration fields */
 #define zorro_config_attr(name, field, format_string)			\
 static ssize_t								\
-show_##name(struct device *dev, char *buf)				\
+show_##name(struct device *dev, struct device_attribute *attr, char *buf)				\
 {									\
 	struct zorro_dev *z;						\
 									\
@@ -36,7 +36,7 @@
 zorro_config_attr(slotaddr, slotaddr, "0x%04x\n");
 zorro_config_attr(slotsize, slotsize, "0x%04x\n");
 
-static ssize_t zorro_show_resource(struct device *dev, char *buf)
+static ssize_t zorro_show_resource(struct device *dev, struct device_attribute *attr, char *buf)
 {
 	struct zorro_dev *z = to_zorro_dev(dev);
 
diff --git a/fs/Kconfig b/fs/Kconfig
index 6a4ad4b..0621779 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -50,6 +50,23 @@
 	  If you are not using a security module that requires using
 	  extended attributes for file security labels, say N.
 
+config EXT2_FS_XIP
+	bool "Ext2 execute in place support"
+	depends on EXT2_FS
+	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
+	  capable of this feature without using the page cache.
+
+	  If you do not use a block device that is capable of using this,
+	  or if unsure, say N.
+
+config FS_XIP
+# execute in place
+	bool
+	depends on EXT2_FS_XIP
+	default y
+
 config EXT3_FS
 	tristate "Ext3 journalling file system support"
 	help
@@ -717,6 +734,12 @@
 	bool "/proc/kcore support" if !ARM
 	depends on PROC_FS && MMU
 
+config PROC_VMCORE
+        bool "/proc/vmcore support (EXPERIMENTAL)"
+        depends on PROC_FS && EMBEDDED && EXPERIMENTAL && CRASH_DUMP
+        help
+        Exports the dump image of crashed kernel in ELF format.
+
 config SYSFS
 	bool "sysfs file system support" if EMBEDDED
 	default y
@@ -741,56 +764,6 @@
 
 	Designers of embedded systems may wish to say N here to conserve space.
 
-config DEVFS_FS
-	bool "/dev file system support (OBSOLETE)"
-	depends on EXPERIMENTAL
-	help
-	  This is support for devfs, a virtual file system (like /proc) which
-	  provides the file system interface to device drivers, normally found
-	  in /dev. Devfs does not depend on major and minor number
-	  allocations. Device drivers register entries in /dev which then
-	  appear automatically, which means that the system administrator does
-	  not have to create character and block special device files in the
-	  /dev directory using the mknod command (or MAKEDEV script) anymore.
-
-	  This is work in progress. If you want to use this, you *must* read
-	  the material in <file:Documentation/filesystems/devfs/>, especially
-	  the file README there.
-
-	  Note that devfs no longer manages /dev/pts!  If you are using UNIX98
-	  ptys, you will also need to mount the /dev/pts filesystem (devpts).
-
-	  Note that devfs has been obsoleted by udev,
-	  <http://www.kernel.org/pub/linux/utils/kernel/hotplug/>.
-	  It has been stripped down to a bare minimum and is only provided for
-	  legacy installations that use its naming scheme which is
-	  unfortunately different from the names normal Linux installations
-	  use.
-
-	  If unsure, say N.
-
-config DEVFS_MOUNT
-	bool "Automatically mount at boot"
-	depends on DEVFS_FS
-	help
-	  This option appears if you have CONFIG_DEVFS_FS enabled. Setting
-	  this to 'Y' will make the kernel automatically mount devfs onto /dev
-	  when the system is booted, before the init thread is started.
-	  You can override this with the "devfs=nomount" boot option.
-
-	  If unsure, say N.
-
-config DEVFS_DEBUG
-	bool "Debug devfs"
-	depends on DEVFS_FS
-	help
-	  If you say Y here, then the /dev file system code will generate
-	  debugging messages. See the file
-	  <file:Documentation/filesystems/devfs/boot-options> for more
-	  details.
-
-	  If unsure, say N.
-
 config DEVPTS_FS_XATTR
 	bool "/dev/pts Extended Attributes"
 	depends on UNIX98_PTYS
@@ -1318,6 +1291,7 @@
 	depends on INET
 	select LOCKD
 	select SUNRPC
+	select NFS_ACL_SUPPORT if NFS_V3_ACL
 	help
 	  If you are connected to some other (usually local) Unix computer
 	  (using SLIP, PLIP, PPP or Ethernet) and want to mount files residing
@@ -1360,6 +1334,16 @@
 
 	  If unsure, say Y.
 
+config NFS_V3_ACL
+	bool "Provide client support for the NFSv3 ACL protocol extension"
+	depends on NFS_V3
+	help
+	  Implement the NFSv3 ACL protocol extension for manipulating POSIX
+	  Access Control Lists.  The server should also be compiled with
+	  the NFSv3 ACL protocol extension; see the CONFIG_NFSD_V3_ACL option.
+
+	  If unsure, say N.
+
 config NFS_V4
 	bool "Provide NFSv4 client support (EXPERIMENTAL)"
 	depends on NFS_FS && EXPERIMENTAL
@@ -1403,6 +1387,7 @@
 	select LOCKD
 	select SUNRPC
 	select EXPORTFS
+	select NFS_ACL_SUPPORT if NFSD_V3_ACL || NFSD_V2_ACL
 	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
@@ -1426,6 +1411,10 @@
 	  To compile the NFS server support as a module, choose M here: the
 	  module will be called nfsd.  If unsure, say N.
 
+config NFSD_V2_ACL
+	bool
+	depends on NFSD
+
 config NFSD_V3
 	bool "Provide NFSv3 server support"
 	depends on NFSD
@@ -1433,10 +1422,22 @@
 	  If you would like to include the NFSv3 server as well as the NFSv2
 	  server, say Y here.  If unsure, say Y.
 
+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
+	  be compiled with the NFSv3 ACL protocol extension; see the
+	  CONFIG_NFS_V3_ACL option.  If unsure, say N.
+
 config NFSD_V4
 	bool "Provide NFSv4 server support (EXPERIMENTAL)"
 	depends on NFSD_V3 && EXPERIMENTAL
 	select NFSD_TCP
+	select CRYPTO_MD5
+	select CRYPTO
 	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
@@ -1477,6 +1478,15 @@
 config EXPORTFS
 	tristate
 
+config NFS_ACL_SUPPORT
+	tristate
+	select FS_POSIX_ACL
+
+config NFS_COMMON
+	bool
+	depends on NFSD || NFS_FS
+	default y
+
 config SUNRPC
 	tristate
 
diff --git a/fs/Makefile b/fs/Makefile
index 443f2bc..20edcf28 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -10,6 +10,7 @@
 		ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \
 		attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \
 		seq_file.o xattr.o libfs.o fs-writeback.o mpage.o direct-io.o \
+		ioprio.o
 
 obj-$(CONFIG_EPOLL)		+= eventpoll.o
 obj-$(CONFIG_COMPAT)		+= compat.o
@@ -31,6 +32,7 @@
 
 obj-$(CONFIG_FS_MBCACHE)	+= mbcache.o
 obj-$(CONFIG_FS_POSIX_ACL)	+= posix_acl.o xattr_acl.o
+obj-$(CONFIG_NFS_COMMON)	+= nfs_common/
 
 obj-$(CONFIG_QUOTA)		+= dquot.o
 obj-$(CONFIG_QFMT_V1)		+= quota_v1.o
diff --git a/fs/afs/kafsasyncd.c b/fs/afs/kafsasyncd.c
index 6fc88ae..7ac07d0 100644
--- a/fs/afs/kafsasyncd.c
+++ b/fs/afs/kafsasyncd.c
@@ -116,7 +116,7 @@
 		remove_wait_queue(&kafsasyncd_sleepq, &myself);
 		set_current_state(TASK_RUNNING);
 
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 
 		/* discard pending signals */
 		afs_discard_my_signals();
diff --git a/fs/afs/kafstimod.c b/fs/afs/kafstimod.c
index 86e710d..65bc05a 100644
--- a/fs/afs/kafstimod.c
+++ b/fs/afs/kafstimod.c
@@ -91,7 +91,7 @@
 			complete_and_exit(&kafstimod_dead, 0);
 		}
 
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 
 		/* discard pending signals */
 		afs_discard_my_signals();
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index c7b2b88..9c09641 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -185,6 +185,19 @@
 int autofs4_wait_release(struct autofs_sb_info *,autofs_wqt_t,int);
 void autofs4_catatonic_mode(struct autofs_sb_info *);
 
+static inline int autofs4_follow_mount(struct vfsmount **mnt, struct dentry **dentry)
+{
+	int res = 0;
+
+	while (d_mountpoint(*dentry)) {
+		int followed = follow_down(mnt, dentry);
+		if (!followed)
+			break;
+		res = 1;
+	}
+	return res;
+}
+
 static inline int simple_positive(struct dentry *dentry)
 {
 	return dentry->d_inode && !d_unhashed(dentry);
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c
index 500425e..feb6ac4 100644
--- a/fs/autofs4/expire.c
+++ b/fs/autofs4/expire.c
@@ -56,12 +56,9 @@
 	mntget(mnt);
 	dget(dentry);
 
-	if (!follow_down(&mnt, &dentry))
+	if (!autofs4_follow_mount(&mnt, &dentry))
 		goto done;
 
-	while (d_mountpoint(dentry) && follow_down(&mnt, &dentry))
-		;
-
 	/* This is an autofs submount, we can't expire it */
 	if (is_autofs4_dentry(dentry))
 		goto done;
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c
index 3765c04..2a771ec 100644
--- a/fs/autofs4/root.c
+++ b/fs/autofs4/root.c
@@ -205,7 +205,11 @@
 		struct vfsmount *fp_mnt = mntget(mnt);
 		struct dentry *fp_dentry = dget(dentry);
 
-		while (follow_down(&fp_mnt, &fp_dentry) && d_mountpoint(fp_dentry));
+		if (!autofs4_follow_mount(&fp_mnt, &fp_dentry)) {
+			dput(fp_dentry);
+			mntput(fp_mnt);
+			return -ENOENT;
+		}
 
 		fp = dentry_open(fp_dentry, fp_mnt, file->f_flags);
 		status = PTR_ERR(fp);
@@ -302,7 +306,14 @@
 		
 		DPRINTK("expire done status=%d", status);
 		
-		return 0;
+		/*
+		 * If the directory still exists the mount request must
+		 * continue otherwise it can't be followed at the right
+		 * time during the walk.
+		 */
+		status = d_invalidate(dentry);
+		if (status != -EBUSY)
+			return 0;
 	}
 
 	DPRINTK("dentry=%p %.*s ino=%p",
diff --git a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
index 5a40d36..fa2348d 100644
--- a/fs/autofs4/waitq.c
+++ b/fs/autofs4/waitq.c
@@ -191,6 +191,13 @@
 	}
 
 	if ( !wq ) {
+		/* Can't wait for an expire if there's no mount */
+		if (notify == NFY_NONE && !d_mountpoint(dentry)) {
+			kfree(name);
+			up(&sbi->wq_sem);
+			return -ENOENT;
+		}
+
 		/* Create a new wait queue */
 		wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL);
 		if ( !wq ) {
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index 009b892..dd9baab 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -316,6 +316,7 @@
 	current->mm->brk = ex.a_bss +
 		(current->mm->start_brk = N_BSSADDR(ex));
 	current->mm->free_area_cache = current->mm->mmap_base;
+	current->mm->cached_hole_size = 0;
 
 	set_mm_counter(current->mm, rss, 0);
 	current->mm->mmap = NULL;
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index c374be5..7976a23 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -775,6 +775,7 @@
 	   change some of these later */
 	set_mm_counter(current->mm, rss, 0);
 	current->mm->free_area_cache = current->mm->mmap_base;
+	current->mm->cached_hole_size = 0;
 	retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP),
 				 executable_stack);
 	if (retval < 0) {
@@ -1125,7 +1126,7 @@
 	return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
 }
 
-static int dump_seek(struct file *file, off_t off)
+static int dump_seek(struct file *file, loff_t off)
 {
 	if (file->f_op->llseek) {
 		if (file->f_op->llseek(file, off, 0) != off)
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index f0cd67d..c8998dc 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -520,7 +520,7 @@
 		DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
 
 		down_write(&current->mm->mmap_sem);
-		textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, 0, 0);
+		textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, MAP_SHARED, 0);
 		up_write(&current->mm->mmap_sem);
 		if (!textpos  || textpos >= (unsigned long) -4096) {
 			if (!textpos)
@@ -532,7 +532,7 @@
 		down_write(&current->mm->mmap_sem);
 		realdatastart = do_mmap(0, 0, data_len + extra +
 				MAX_SHARED_LIBS * sizeof(unsigned long),
-				PROT_READ|PROT_WRITE|PROT_EXEC, 0, 0);
+				PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
 		up_write(&current->mm->mmap_sem);
 
 		if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) {
@@ -574,7 +574,7 @@
 		down_write(&current->mm->mmap_sem);
 		textpos = do_mmap(0, 0, text_len + data_len + extra +
 					MAX_SHARED_LIBS * sizeof(unsigned long),
-				PROT_READ | PROT_EXEC | PROT_WRITE, 0, 0);
+				PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
 		up_write(&current->mm->mmap_sem);
 		if (!textpos  || textpos >= (unsigned long) -4096) {
 			if (!textpos)
diff --git a/fs/block_dev.c b/fs/block_dev.c
index c0cbd1b..e0df94c 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -777,8 +777,7 @@
 	return generic_file_aio_write_nolock(iocb, &local_iov, 1, &iocb->ki_pos);
 }
 
-static int block_ioctl(struct inode *inode, struct file *file, unsigned cmd,
-			unsigned long arg)
+static long block_ioctl(struct file *file, unsigned cmd, unsigned long arg)
 {
 	return blkdev_ioctl(file->f_mapping->host, file, cmd, arg);
 }
@@ -803,7 +802,7 @@
   	.aio_write	= blkdev_file_aio_write, 
 	.mmap		= generic_file_mmap,
 	.fsync		= block_fsync,
-	.ioctl		= block_ioctl,
+	.unlocked_ioctl	= block_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= compat_blkdev_ioctl,
 #endif
diff --git a/fs/buffer.c b/fs/buffer.c
index 7e9e409..13e5938 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -331,7 +331,7 @@
 	return ret;
 }
 
-asmlinkage long sys_fsync(unsigned int fd)
+static long do_fsync(unsigned int fd, int datasync)
 {
 	struct file * file;
 	struct address_space *mapping;
@@ -342,14 +342,14 @@
 	if (!file)
 		goto out;
 
-	mapping = file->f_mapping;
-
 	ret = -EINVAL;
 	if (!file->f_op || !file->f_op->fsync) {
 		/* Why?  We can still call filemap_fdatawrite */
 		goto out_putf;
 	}
 
+	mapping = file->f_mapping;
+
 	current->flags |= PF_SYNCWRITE;
 	ret = filemap_fdatawrite(mapping);
 
@@ -358,7 +358,7 @@
 	 * which could cause livelocks in fsync_buffers_list
 	 */
 	down(&mapping->host->i_sem);
-	err = file->f_op->fsync(file, file->f_dentry, 0);
+	err = file->f_op->fsync(file, file->f_dentry, datasync);
 	if (!ret)
 		ret = err;
 	up(&mapping->host->i_sem);
@@ -373,39 +373,14 @@
 	return ret;
 }
 
+asmlinkage long sys_fsync(unsigned int fd)
+{
+	return do_fsync(fd, 0);
+}
+
 asmlinkage long sys_fdatasync(unsigned int fd)
 {
-	struct file * file;
-	struct address_space *mapping;
-	int ret, err;
-
-	ret = -EBADF;
-	file = fget(fd);
-	if (!file)
-		goto out;
-
-	ret = -EINVAL;
-	if (!file->f_op || !file->f_op->fsync)
-		goto out_putf;
-
-	mapping = file->f_mapping;
-
-	current->flags |= PF_SYNCWRITE;
-	ret = filemap_fdatawrite(mapping);
-	down(&mapping->host->i_sem);
-	err = file->f_op->fsync(file, file->f_dentry, 1);
-	if (!ret)
-		ret = err;
-	up(&mapping->host->i_sem);
-	err = filemap_fdatawait(mapping);
-	if (!ret)
-		ret = err;
-	current->flags &= ~PF_SYNCWRITE;
-
-out_putf:
-	fput(file);
-out:
-	return ret;
+	return do_fsync(fd, 1);
 }
 
 /*
@@ -528,7 +503,7 @@
 	for_each_pgdat(pgdat) {
 		zones = pgdat->node_zonelists[GFP_NOFS&GFP_ZONEMASK].zones;
 		if (*zones)
-			try_to_free_pages(zones, GFP_NOFS, 0);
+			try_to_free_pages(zones, GFP_NOFS);
 	}
 }
 
@@ -1951,7 +1926,6 @@
 			if (err)
 				break;
 			if (buffer_new(bh)) {
-				clear_buffer_new(bh);
 				unmap_underlying_metadata(bh->b_bdev,
 							bh->b_blocknr);
 				if (PageUptodate(page)) {
@@ -1993,9 +1967,14 @@
 		if (!buffer_uptodate(*wait_bh))
 			err = -EIO;
 	}
-	if (!err)
-		return err;
-
+	if (!err) {
+		bh = head;
+		do {
+			if (buffer_new(bh))
+				clear_buffer_new(bh);
+		} while ((bh = bh->b_this_page) != head);
+		return 0;
+	}
 	/* Error case: */
 	/*
 	 * Zero out any newly allocated blocks to avoid exposing stale
diff --git a/fs/char_dev.c b/fs/char_dev.c
index c1e3537..e82aac9 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -56,10 +56,21 @@
 
 	down(&chrdevs_lock);
 	for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) {
-		for (cd = chrdevs[i]; cd; cd = cd->next)
+		for (cd = chrdevs[i]; cd; cd = cd->next) {
+			/*
+			 * if the current name, plus the 5 extra characters
+			 * in the device line for this entry
+			 * would run us off the page, we're done
+			 */
+			if ((len+strlen(cd->name) + 5) >= PAGE_SIZE)
+				goto page_full;
+
+
 			len += sprintf(page+len, "%3d %s\n",
 				       cd->major, cd->name);
+		}
 	}
+page_full:
 	up(&chrdevs_lock);
 
 	return len;
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 95483ba..dab4774 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -6,7 +6,8 @@
 recommended, unmount and rmmod cifs will kill them when they are
 no longer needed).  Fix readdir to ASCII servers (ie older servers
 which do not support Unicode) and also require asterik.
-
+Fix out of memory case in which data could be written one page
+off in the page cache.
 
 Version 1.33
 ------------
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index d00b3bf..78af585 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -96,5 +96,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.34"
+#define CIFS_VERSION   "1.35"
 #endif				/* _CIFSFS_H */
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index dde2d25..30ab70c 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1352,6 +1352,8 @@
 				      GFP_KERNEL)) {
 			page_cache_release(page);
 			cFYI(1, ("Add page cache failed"));
+			data += PAGE_CACHE_SIZE;
+			bytes_read -= PAGE_CACHE_SIZE;
 			continue;
 		}
 
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index b8b78cb..8d336a9 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -82,12 +82,12 @@
 		/* get new inode */
 		if (*pinode == NULL) {
 			*pinode = new_inode(sb);
-			if(*pinode == NULL) 
+			if (*pinode == NULL) 
 				return -ENOMEM;
 			/* Is an i_ino of zero legal? */
 			/* Are there sanity checks we can use to ensure that
 			   the server is really filling in that field? */
-			if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
+			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
 				(*pinode)->i_ino =
 					(unsigned long)findData.UniqueId;
 			} /* note ino incremented to unique num in new_inode */
@@ -134,7 +134,7 @@
 		inode->i_gid = le64_to_cpu(findData.Gid);
 		inode->i_nlink = le64_to_cpu(findData.Nlinks);
 
-		if(is_size_safe_to_change(cifsInfo)) {
+		if (is_size_safe_to_change(cifsInfo)) {
 		/* can not safely change the file size here if the
 		   client is writing to it due to potential races */
 
@@ -162,7 +162,7 @@
 		if (S_ISREG(inode->i_mode)) {
 			cFYI(1, (" File inode "));
 			inode->i_op = &cifs_file_inode_ops;
-			if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
+			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
 				inode->i_fop = &cifs_file_direct_ops;
 			else
 				inode->i_fop = &cifs_file_ops;
@@ -198,17 +198,17 @@
 	pTcon = cifs_sb->tcon;
 	cFYI(1,("Getting info on %s ", search_path));
 
-	if((pfindData == NULL) && (*pinode != NULL)) {
-		if(CIFS_I(*pinode)->clientCanCacheRead) {
+	if ((pfindData == NULL) && (*pinode != NULL)) {
+		if (CIFS_I(*pinode)->clientCanCacheRead) {
 			cFYI(1,("No need to revalidate cached inode sizes"));
 			return rc;
 		}
 	}
 
 	/* if file info not passed in then get it from server */
-	if(pfindData == NULL) {
+	if (pfindData == NULL) {
 		buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
-		if(buf == NULL)
+		if (buf == NULL)
 			return -ENOMEM;
 		pfindData = (FILE_ALL_INFO *)buf;
 		/* could do find first instead but this returns more info */
@@ -268,7 +268,7 @@
 			   IndexNumber field is not guaranteed unique? */
 
 #ifdef CONFIG_CIFS_EXPERIMENTAL		
-			if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){
+			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){
 				int rc1 = 0;
 				__u64 inode_num;
 
@@ -277,7 +277,7 @@
 					cifs_sb->local_nls,
 					cifs_sb->mnt_cifs_flags &
 						CIFS_MOUNT_MAP_SPECIAL_CHR);
-				if(rc1) {
+				if (rc1) {
 					cFYI(1,("GetSrvInodeNum rc %d", rc1));
 					/* BB EOPNOSUPP disable SERVER_INUM? */
 				} else /* do we need cast or hash to ino? */
@@ -355,7 +355,7 @@
 		if (S_ISREG(inode->i_mode)) {
 			cFYI(1, (" File inode "));
 			inode->i_op = &cifs_file_inode_ops;
-			if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
+			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO)
 				inode->i_fop = &cifs_file_direct_ops;
 			else
 				inode->i_fop = &cifs_file_ops;
@@ -422,7 +422,7 @@
 			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
 
 	if (!rc) {
-		if(direntry->d_inode)
+		if (direntry->d_inode)
 			direntry->d_inode->i_nlink--;
 	} else if (rc == -ENOENT) {
 		d_drop(direntry);
@@ -441,7 +441,7 @@
 					      cifs_sb->mnt_cifs_flags & 
 						CIFS_MOUNT_MAP_SPECIAL_CHR);
 			CIFSSMBClose(xid, pTcon, netfid);
-			if(direntry->d_inode)
+			if (direntry->d_inode)
 				direntry->d_inode->i_nlink--;
 		}
 	} else if (rc == -EACCES) {
@@ -496,7 +496,7 @@
 					    cifs_sb->mnt_cifs_flags & 
 						CIFS_MOUNT_MAP_SPECIAL_CHR);
 			if (!rc) {
-				if(direntry->d_inode)
+				if (direntry->d_inode)
 					direntry->d_inode->i_nlink--;
 			} else if (rc == -ETXTBSY) {
 				int oplock = FALSE;
@@ -517,14 +517,14 @@
 						cifs_sb->mnt_cifs_flags &
 						    CIFS_MOUNT_MAP_SPECIAL_CHR);
 					CIFSSMBClose(xid, pTcon, netfid);
-					if(direntry->d_inode)
+					if (direntry->d_inode)
 			                        direntry->d_inode->i_nlink--;
 				}
 			/* BB if rc = -ETXTBUSY goto the rename logic BB */
 			}
 		}
 	}
-	if(direntry->d_inode) {
+	if (direntry->d_inode) {
 		cifsInode = CIFS_I(direntry->d_inode);
 		cifsInode->time = 0;	/* will force revalidate to get info
 					   when needed */
@@ -582,7 +582,7 @@
 		if (direntry->d_inode)
 			direntry->d_inode->i_nlink = 2;
 		if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
-			if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
 				CIFSSMBUnixSetPerms(xid, pTcon, full_path,
 						    mode,
 						    (__u64)current->euid,
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index ef001a9..3d1cce3 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -61,7 +61,7 @@
 
 
 struct venus_comm coda_comms[MAX_CODADEVS];
-static struct class_simple *coda_psdev_class;
+static struct class *coda_psdev_class;
 
 /*
  * Device operations
@@ -363,14 +363,14 @@
 		     CODA_PSDEV_MAJOR);
               return -EIO;
 	}
-	coda_psdev_class = class_simple_create(THIS_MODULE, "coda");
+	coda_psdev_class = class_create(THIS_MODULE, "coda");
 	if (IS_ERR(coda_psdev_class)) {
 		err = PTR_ERR(coda_psdev_class);
 		goto out_chrdev;
 	}		
 	devfs_mk_dir ("coda");
 	for (i = 0; i < MAX_CODADEVS; i++) {
-		class_simple_device_add(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR,i), 
+		class_device_create(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR,i),
 				NULL, "cfs%d", i);
 		err = devfs_mk_cdev(MKDEV(CODA_PSDEV_MAJOR, i),
 				S_IFCHR|S_IRUSR|S_IWUSR, "coda/%d", i);
@@ -382,8 +382,8 @@
 
 out_class:
 	for (i = 0; i < MAX_CODADEVS; i++) 
-		class_simple_device_remove(MKDEV(CODA_PSDEV_MAJOR, i));
-	class_simple_destroy(coda_psdev_class);
+		class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i));
+	class_destroy(coda_psdev_class);
 out_chrdev:
 	unregister_chrdev(CODA_PSDEV_MAJOR, "coda");
 out:
@@ -425,10 +425,10 @@
 	return 0;
 out:
 	for (i = 0; i < MAX_CODADEVS; i++) {
-		class_simple_device_remove(MKDEV(CODA_PSDEV_MAJOR, i));
+		class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i));
 		devfs_remove("coda/%d", i);
 	}
-	class_simple_destroy(coda_psdev_class);
+	class_destroy(coda_psdev_class);
 	devfs_remove("coda");
 	unregister_chrdev(CODA_PSDEV_MAJOR, "coda");
 	coda_sysctl_clean();
@@ -447,10 +447,10 @@
                 printk("coda: failed to unregister filesystem\n");
         }
 	for (i = 0; i < MAX_CODADEVS; i++) {
-		class_simple_device_remove(MKDEV(CODA_PSDEV_MAJOR, i));
+		class_device_destroy(coda_psdev_class, MKDEV(CODA_PSDEV_MAJOR, i));
 		devfs_remove("coda/%d", i);
 	}
-	class_simple_destroy(coda_psdev_class);
+	class_destroy(coda_psdev_class);
 	devfs_remove("coda");
 	unregister_chrdev(CODA_PSDEV_MAJOR, "coda");
 	coda_sysctl_clean();
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 548556f..efc97d9 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -45,44 +45,15 @@
 	.open =		default_open,
 };
 
-#define simple_type(type, format, temptype, strtolfn)				\
-static ssize_t read_file_##type(struct file *file, char __user *user_buf,	\
-				size_t count, loff_t *ppos)			\
-{										\
-	char buf[32];								\
-	type *val = file->private_data;						\
-										\
-	snprintf(buf, sizeof(buf), format "\n", *val);				\
-	return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));\
-}										\
-static ssize_t write_file_##type(struct file *file, const char __user *user_buf,\
-				 size_t count, loff_t *ppos)			\
-{										\
-	char *endp;								\
-	char buf[32];								\
-	int buf_size;								\
-	type *val = file->private_data;						\
-	temptype tmp;								\
-										\
-	memset(buf, 0x00, sizeof(buf));						\
-	buf_size = min(count, (sizeof(buf)-1));					\
-	if (copy_from_user(buf, user_buf, buf_size))				\
-		return -EFAULT;							\
-										\
-	tmp = strtolfn(buf, &endp, 0);						\
-	if ((endp == buf) || ((type)tmp != tmp))				\
-		return -EINVAL;							\
-	*val = tmp;								\
-	return count;								\
-}										\
-static struct file_operations fops_##type = {					\
-	.read =		read_file_##type,					\
-	.write =	write_file_##type,					\
-	.open =		default_open,						\
-};
-simple_type(u8, "%c", unsigned long, simple_strtoul);
-simple_type(u16, "%hi", unsigned long, simple_strtoul);
-simple_type(u32, "%i", unsigned long, simple_strtoul);
+static void debugfs_u8_set(void *data, u64 val)
+{
+	*(u8 *)data = val;
+}
+static u64 debugfs_u8_get(void *data)
+{
+	return *(u8 *)data;
+}
+DEFINE_SIMPLE_ATTRIBUTE(fops_u8, debugfs_u8_get, debugfs_u8_set, "%llu\n");
 
 /**
  * debugfs_create_u8 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value.
@@ -116,6 +87,16 @@
 }
 EXPORT_SYMBOL_GPL(debugfs_create_u8);
 
+static void debugfs_u16_set(void *data, u64 val)
+{
+	*(u16 *)data = val;
+}
+static u64 debugfs_u16_get(void *data)
+{
+	return *(u16 *)data;
+}
+DEFINE_SIMPLE_ATTRIBUTE(fops_u16, debugfs_u16_get, debugfs_u16_set, "%llu\n");
+
 /**
  * debugfs_create_u16 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value.
  *
@@ -148,6 +129,16 @@
 }
 EXPORT_SYMBOL_GPL(debugfs_create_u16);
 
+static void debugfs_u32_set(void *data, u64 val)
+{
+	*(u32 *)data = val;
+}
+static u64 debugfs_u32_get(void *data)
+{
+	return *(u32 *)data;
+}
+DEFINE_SIMPLE_ATTRIBUTE(fops_u32, debugfs_u32_get, debugfs_u32_set, "%llu\n");
+
 /**
  * debugfs_create_u32 - create a file in the debugfs filesystem that is used to read and write a unsigned 8 bit value.
  *
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index b529786..a86ac4a 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -110,16 +110,6 @@
 	return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files);
 }
 
-static struct dentry * get_dentry(struct dentry *parent, const char *name)
-{               
-	struct qstr qstr;
-
-	qstr.name = name;
-	qstr.len = strlen(name);
-	qstr.hash = full_name_hash(name,qstr.len);
-	return lookup_hash(&qstr,parent);
-}               
-
 static struct super_block *debug_get_sb(struct file_system_type *fs_type,
 				        int flags, const char *dev_name,
 					void *data)
@@ -157,7 +147,7 @@
 
 	*dentry = NULL;
 	down(&parent->d_inode->i_sem);
-	*dentry = get_dentry (parent, name);
+	*dentry = lookup_one_len(name, parent, strlen(name));
 	if (!IS_ERR(dentry)) {
 		if ((mode & S_IFMT) == S_IFDIR)
 			error = debugfs_mkdir(parent->d_inode, *dentry, mode);
diff --git a/fs/direct-io.c b/fs/direct-io.c
index 1d55e7e..0d06097 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -215,7 +215,7 @@
 static void dio_complete(struct dio *dio, loff_t offset, ssize_t bytes)
 {
 	if (dio->end_io && dio->result)
-		dio->end_io(dio->inode, offset, bytes, dio->map_bh.b_private);
+		dio->end_io(dio->iocb, offset, bytes, dio->map_bh.b_private);
 	if (dio->lock_type == DIO_LOCKING)
 		up_read(&dio->inode->i_alloc_sem);
 }
diff --git a/fs/dquot.c b/fs/dquot.c
index 3995ce7..b973233 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -409,13 +409,10 @@
  * for this sb+type at all. */
 static void invalidate_dquots(struct super_block *sb, int type)
 {
-	struct dquot *dquot;
-	struct list_head *head;
+	struct dquot *dquot, *tmp;
 
 	spin_lock(&dq_list_lock);
-	for (head = inuse_list.next; head != &inuse_list;) {
-		dquot = list_entry(head, struct dquot, dq_inuse);
-		head = head->next;
+	list_for_each_entry_safe(dquot, tmp, &inuse_list, dq_inuse) {
 		if (dquot->dq_sb != sb)
 			continue;
 		if (dquot->dq_type != type)
@@ -1519,14 +1516,22 @@
  * This function is used when filesystem needs to initialize quotas
  * during mount time.
  */
-int vfs_quota_on_mount(int type, int format_id, struct dentry *dentry)
+int vfs_quota_on_mount(struct super_block *sb, char *qf_name,
+		int format_id, int type)
 {
+	struct dentry *dentry;
 	int error;
 
+	dentry = lookup_one_len(qf_name, sb->s_root, strlen(qf_name));
+	if (IS_ERR(dentry))
+		return PTR_ERR(dentry);
+
 	error = security_quota_on(dentry);
-	if (error)
-		return error;
-	return vfs_quota_on_inode(dentry->d_inode, type, format_id);
+	if (!error)
+		error = vfs_quota_on_inode(dentry->d_inode, type, format_id);
+
+	dput(dentry);
+	return error;
 }
 
 /* Generic routine for getting common part of quota structure */
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 9900e33..6ab1dd0 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -101,57 +101,6 @@
 /* Maximum number of poll wake up nests we are allowing */
 #define EP_MAX_POLLWAKE_NESTS 4
 
-/* Macro to allocate a "struct epitem" from the slab cache */
-#define EPI_MEM_ALLOC()	(struct epitem *) kmem_cache_alloc(epi_cache, SLAB_KERNEL)
-
-/* Macro to free a "struct epitem" to the slab cache */
-#define EPI_MEM_FREE(p) kmem_cache_free(epi_cache, p)
-
-/* Macro to allocate a "struct eppoll_entry" from the slab cache */
-#define PWQ_MEM_ALLOC()	(struct eppoll_entry *) kmem_cache_alloc(pwq_cache, SLAB_KERNEL)
-
-/* Macro to free a "struct eppoll_entry" to the slab cache */
-#define PWQ_MEM_FREE(p) kmem_cache_free(pwq_cache, p)
-
-/* Fast test to see if the file is an evenpoll file */
-#define IS_FILE_EPOLL(f) ((f)->f_op == &eventpoll_fops)
-
-/* Setup the structure that is used as key for the rb-tree */
-#define EP_SET_FFD(p, f, d) do { (p)->file = (f); (p)->fd = (d); } while (0)
-
-/* Compare rb-tree keys */
-#define EP_CMP_FFD(p1, p2) ((p1)->file > (p2)->file ? +1: \
-			    ((p1)->file < (p2)->file ? -1: (p1)->fd - (p2)->fd))
-
-/* Special initialization for the rb-tree node to detect linkage */
-#define EP_RB_INITNODE(n) (n)->rb_parent = (n)
-
-/* Removes a node from the rb-tree and marks it for a fast is-linked check */
-#define EP_RB_ERASE(n, r) do { rb_erase(n, r); (n)->rb_parent = (n); } while (0)
-
-/* Fast check to verify that the item is linked to the main rb-tree */
-#define EP_RB_LINKED(n) ((n)->rb_parent != (n))
-
-/*
- * Remove the item from the list and perform its initialization.
- * This is useful for us because we can test if the item is linked
- * using "EP_IS_LINKED(p)".
- */
-#define EP_LIST_DEL(p) do { list_del(p); INIT_LIST_HEAD(p); } while (0)
-
-/* Tells us if the item is currently linked */
-#define EP_IS_LINKED(p) (!list_empty(p))
-
-/* Get the "struct epitem" from a wait queue pointer */
-#define EP_ITEM_FROM_WAIT(p) ((struct epitem *) container_of(p, struct eppoll_entry, wait)->base)
-
-/* Get the "struct epitem" from an epoll queue wrapper */
-#define EP_ITEM_FROM_EPQUEUE(p) (container_of(p, struct ep_pqueue, pt)->epi)
-
-/* Tells if the epoll_ctl(2) operation needs an event copy from userspace */
-#define EP_OP_HASH_EVENT(op) ((op) != EPOLL_CTL_DEL)
-
-
 struct epoll_filefd {
 	struct file *file;
 	int fd;
@@ -357,6 +306,82 @@
 
 
 
+/* Fast test to see if the file is an evenpoll file */
+static inline int is_file_epoll(struct file *f)
+{
+	return f->f_op == &eventpoll_fops;
+}
+
+/* Setup the structure that is used as key for the rb-tree */
+static inline void ep_set_ffd(struct epoll_filefd *ffd,
+			      struct file *file, int fd)
+{
+	ffd->file = file;
+	ffd->fd = fd;
+}
+
+/* Compare rb-tree keys */
+static inline int ep_cmp_ffd(struct epoll_filefd *p1,
+			     struct epoll_filefd *p2)
+{
+	return (p1->file > p2->file ? +1:
+	        (p1->file < p2->file ? -1 : p1->fd - p2->fd));
+}
+
+/* Special initialization for the rb-tree node to detect linkage */
+static inline void ep_rb_initnode(struct rb_node *n)
+{
+	n->rb_parent = 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;
+}
+
+/* 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;
+}
+
+/*
+ * Remove the item from the list and perform its initialization.
+ * This is useful for us because we can test if the item is linked
+ * using "ep_is_linked(p)".
+ */
+static inline void ep_list_del(struct list_head *p)
+{
+	list_del(p);
+	INIT_LIST_HEAD(p);
+}
+
+/* Tells us if the item is currently linked */
+static inline int ep_is_linked(struct list_head *p)
+{
+	return !list_empty(p);
+}
+
+/* Get the "struct epitem" from a wait queue pointer */
+static inline struct epitem * ep_item_from_wait(wait_queue_t *p)
+{
+	return container_of(p, struct eppoll_entry, wait)->base;
+}
+
+/* Get the "struct epitem" from an epoll queue wrapper */
+static inline struct epitem * ep_item_from_epqueue(poll_table *p)
+{
+	return container_of(p, struct ep_pqueue, pt)->epi;
+}
+
+/* Tells if the epoll_ctl(2) operation needs an event copy from userspace */
+static inline int ep_op_hash_event(int op)
+{
+	return op != EPOLL_CTL_DEL;
+}
+
 /* Initialize the poll safe wake up structure */
 static void ep_poll_safewake_init(struct poll_safewake *psw)
 {
@@ -456,7 +481,7 @@
 		epi = list_entry(lsthead->next, struct epitem, fllink);
 
 		ep = epi->ep;
-		EP_LIST_DEL(&epi->fllink);
+		ep_list_del(&epi->fllink);
 		down_write(&ep->sem);
 		ep_remove(ep, epi);
 		up_write(&ep->sem);
@@ -534,7 +559,7 @@
 		     current, epfd, op, fd, event));
 
 	error = -EFAULT;
-	if (EP_OP_HASH_EVENT(op) &&
+	if (ep_op_hash_event(op) &&
 	    copy_from_user(&epds, event, sizeof(struct epoll_event)))
 		goto eexit_1;
 
@@ -560,7 +585,7 @@
 	 * adding an epoll file descriptor inside itself.
 	 */
 	error = -EINVAL;
-	if (file == tfile || !IS_FILE_EPOLL(file))
+	if (file == tfile || !is_file_epoll(file))
 		goto eexit_3;
 
 	/*
@@ -656,7 +681,7 @@
 	 * the user passed to us _is_ an eventpoll file.
 	 */
 	error = -EINVAL;
-	if (!IS_FILE_EPOLL(file))
+	if (!is_file_epoll(file))
 		goto eexit_2;
 
 	/*
@@ -831,11 +856,11 @@
 	struct epitem *epi, *epir = NULL;
 	struct epoll_filefd ffd;
 
-	EP_SET_FFD(&ffd, file, fd);
+	ep_set_ffd(&ffd, file, fd);
 	read_lock_irqsave(&ep->lock, flags);
 	for (rbp = ep->rbr.rb_node; rbp; ) {
 		epi = rb_entry(rbp, struct epitem, rbn);
-		kcmp = EP_CMP_FFD(&ffd, &epi->ffd);
+		kcmp = ep_cmp_ffd(&ffd, &epi->ffd);
 		if (kcmp > 0)
 			rbp = rbp->rb_right;
 		else if (kcmp < 0)
@@ -875,7 +900,7 @@
 {
 
 	if (atomic_dec_and_test(&epi->usecnt))
-		EPI_MEM_FREE(epi);
+		kmem_cache_free(epi_cache, epi);
 }
 
 
@@ -886,10 +911,10 @@
 static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
 				 poll_table *pt)
 {
-	struct epitem *epi = EP_ITEM_FROM_EPQUEUE(pt);
+	struct epitem *epi = ep_item_from_epqueue(pt);
 	struct eppoll_entry *pwq;
 
-	if (epi->nwait >= 0 && (pwq = PWQ_MEM_ALLOC())) {
+	if (epi->nwait >= 0 && (pwq = kmem_cache_alloc(pwq_cache, SLAB_KERNEL))) {
 		init_waitqueue_func_entry(&pwq->wait, ep_poll_callback);
 		pwq->whead = whead;
 		pwq->base = epi;
@@ -912,7 +937,7 @@
 	while (*p) {
 		parent = *p;
 		epic = rb_entry(parent, struct epitem, rbn);
-		kcmp = EP_CMP_FFD(&epi->ffd, &epic->ffd);
+		kcmp = ep_cmp_ffd(&epi->ffd, &epic->ffd);
 		if (kcmp > 0)
 			p = &parent->rb_right;
 		else
@@ -932,17 +957,17 @@
 	struct ep_pqueue epq;
 
 	error = -ENOMEM;
-	if (!(epi = EPI_MEM_ALLOC()))
+	if (!(epi = kmem_cache_alloc(epi_cache, SLAB_KERNEL)))
 		goto eexit_1;
 
 	/* Item initialization follow here ... */
-	EP_RB_INITNODE(&epi->rbn);
+	ep_rb_initnode(&epi->rbn);
 	INIT_LIST_HEAD(&epi->rdllink);
 	INIT_LIST_HEAD(&epi->fllink);
 	INIT_LIST_HEAD(&epi->txlink);
 	INIT_LIST_HEAD(&epi->pwqlist);
 	epi->ep = ep;
-	EP_SET_FFD(&epi->ffd, tfile, fd);
+	ep_set_ffd(&epi->ffd, tfile, fd);
 	epi->event = *event;
 	atomic_set(&epi->usecnt, 1);
 	epi->nwait = 0;
@@ -978,7 +1003,7 @@
 	ep_rbtree_insert(ep, epi);
 
 	/* If the file is already "ready" we drop it inside the ready list */
-	if ((revents & event->events) && !EP_IS_LINKED(&epi->rdllink)) {
+	if ((revents & event->events) && !ep_is_linked(&epi->rdllink)) {
 		list_add_tail(&epi->rdllink, &ep->rdllist);
 
 		/* Notify waiting tasks that events are available */
@@ -1007,11 +1032,11 @@
 	 * allocated wait queue.
 	 */
 	write_lock_irqsave(&ep->lock, flags);
-	if (EP_IS_LINKED(&epi->rdllink))
-		EP_LIST_DEL(&epi->rdllink);
+	if (ep_is_linked(&epi->rdllink))
+		ep_list_del(&epi->rdllink);
 	write_unlock_irqrestore(&ep->lock, flags);
 
-	EPI_MEM_FREE(epi);
+	kmem_cache_free(epi_cache, epi);
 eexit_1:
 	return error;
 }
@@ -1050,14 +1075,14 @@
 	 * If the item is not linked to the hash it means that it's on its
 	 * way toward the removal. Do nothing in this case.
 	 */
-	if (EP_RB_LINKED(&epi->rbn)) {
+	if (ep_rb_linked(&epi->rbn)) {
 		/*
 		 * If the item is "hot" and it is not registered inside the ready
 		 * list, push it inside. If the item is not "hot" and it is currently
 		 * registered inside the ready list, unlink it.
 		 */
 		if (revents & event->events) {
-			if (!EP_IS_LINKED(&epi->rdllink)) {
+			if (!ep_is_linked(&epi->rdllink)) {
 				list_add_tail(&epi->rdllink, &ep->rdllist);
 
 				/* Notify waiting tasks that events are available */
@@ -1097,9 +1122,9 @@
 		while (!list_empty(lsthead)) {
 			pwq = list_entry(lsthead->next, struct eppoll_entry, llink);
 
-			EP_LIST_DEL(&pwq->llink);
+			ep_list_del(&pwq->llink);
 			remove_wait_queue(pwq->whead, &pwq->wait);
-			PWQ_MEM_FREE(pwq);
+			kmem_cache_free(pwq_cache, pwq);
 		}
 	}
 }
@@ -1118,7 +1143,7 @@
 	 * The check protect us from doing a double unlink ( crash ).
 	 */
 	error = -ENOENT;
-	if (!EP_RB_LINKED(&epi->rbn))
+	if (!ep_rb_linked(&epi->rbn))
 		goto eexit_1;
 
 	/*
@@ -1133,14 +1158,14 @@
 	 * This operation togheter with the above check closes the door to
 	 * double unlinks.
 	 */
-	EP_RB_ERASE(&epi->rbn, &ep->rbr);
+	ep_rb_erase(&epi->rbn, &ep->rbr);
 
 	/*
 	 * If the item we are going to remove is inside the ready file descriptors
 	 * we want to remove it from this list to avoid stale events.
 	 */
-	if (EP_IS_LINKED(&epi->rdllink))
-		EP_LIST_DEL(&epi->rdllink);
+	if (ep_is_linked(&epi->rdllink))
+		ep_list_del(&epi->rdllink);
 
 	error = 0;
 eexit_1:
@@ -1174,8 +1199,8 @@
 
 	/* Remove the current item from the list of epoll hooks */
 	spin_lock(&file->f_ep_lock);
-	if (EP_IS_LINKED(&epi->fllink))
-		EP_LIST_DEL(&epi->fllink);
+	if (ep_is_linked(&epi->fllink))
+		ep_list_del(&epi->fllink);
 	spin_unlock(&file->f_ep_lock);
 
 	/* We need to acquire the write IRQ lock before calling ep_unlink() */
@@ -1210,7 +1235,7 @@
 {
 	int pwake = 0;
 	unsigned long flags;
-	struct epitem *epi = EP_ITEM_FROM_WAIT(wait);
+	struct epitem *epi = ep_item_from_wait(wait);
 	struct eventpoll *ep = epi->ep;
 
 	DNPRINTK(3, (KERN_INFO "[%p] eventpoll: poll_callback(%p) epi=%p ep=%p\n",
@@ -1228,7 +1253,7 @@
 		goto is_disabled;
 
 	/* If this file is already in the ready list we exit soon */
-	if (EP_IS_LINKED(&epi->rdllink))
+	if (ep_is_linked(&epi->rdllink))
 		goto is_linked;
 
 	list_add_tail(&epi->rdllink, &ep->rdllist);
@@ -1307,7 +1332,7 @@
 		lnk = lnk->next;
 
 		/* If this file is already in the ready list we exit soon */
-		if (!EP_IS_LINKED(&epi->txlink)) {
+		if (!ep_is_linked(&epi->txlink)) {
 			/*
 			 * This is initialized in this way so that the default
 			 * behaviour of the reinjecting code will be to push back
@@ -1322,7 +1347,7 @@
 			/*
 			 * Unlink the item from the ready list.
 			 */
-			EP_LIST_DEL(&epi->rdllink);
+			ep_list_del(&epi->rdllink);
 		}
 	}
 
@@ -1401,7 +1426,7 @@
 		epi = list_entry(txlist->next, struct epitem, txlink);
 
 		/* Unlink the current item from the transfer list */
-		EP_LIST_DEL(&epi->txlink);
+		ep_list_del(&epi->txlink);
 
 		/*
 		 * If the item is no more linked to the interest set, we don't
@@ -1410,8 +1435,8 @@
 		 * item is set to have an Edge Triggered behaviour, we don't have
 		 * to push it back either.
 		 */
-		if (EP_RB_LINKED(&epi->rbn) && !(epi->event.events & EPOLLET) &&
-		    (epi->revents & epi->event.events) && !EP_IS_LINKED(&epi->rdllink)) {
+		if (ep_rb_linked(&epi->rbn) && !(epi->event.events & EPOLLET) &&
+		    (epi->revents & epi->event.events) && !ep_is_linked(&epi->rdllink)) {
 			list_add_tail(&epi->rdllink, &ep->rdllist);
 			ricnt++;
 		}
diff --git a/fs/exec.c b/fs/exec.c
index e56ee24..4887191 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -58,6 +58,9 @@
 
 int core_uses_pid;
 char core_pattern[65] = "core";
+int suid_dumpable = 0;
+
+EXPORT_SYMBOL(suid_dumpable);
 /* The maximal length of core_pattern is also specified in sysctl.c */
 
 static struct linux_binfmt *formats;
@@ -649,6 +652,7 @@
 	}
 	sig->group_exit_task = NULL;
 	sig->notify_count = 0;
+	sig->real_timer.data = (unsigned long)current;
 	spin_unlock_irq(lock);
 
 	/*
@@ -675,10 +679,8 @@
 		proc_dentry2 = proc_pid_unhash(leader);
 		write_lock_irq(&tasklist_lock);
 
-		if (leader->tgid != current->tgid)
-			BUG();
-		if (current->pid == current->tgid)
-			BUG();
+		BUG_ON(leader->tgid != current->tgid);
+		BUG_ON(current->pid == current->tgid);
 		/*
 		 * An exec() starts a new thread group with the
 		 * TGID of the previous thread group. Rehash the
@@ -726,8 +728,7 @@
 		proc_pid_flush(proc_dentry1);
 		proc_pid_flush(proc_dentry2);
 
-		if (exit_state != EXIT_ZOMBIE)
-			BUG();
+		BUG_ON(exit_state != EXIT_ZOMBIE);
 		release_task(leader);
         }
 
@@ -772,10 +773,8 @@
 			kmem_cache_free(sighand_cachep, oldsighand);
 	}
 
-	if (!thread_group_empty(current))
-		BUG();
-	if (!thread_group_leader(current))
-		BUG();
+	BUG_ON(!thread_group_empty(current));
+	BUG_ON(!thread_group_leader(current));
 	return 0;
 }
 	
@@ -868,6 +867,9 @@
 
 	if (current->euid == current->uid && current->egid == current->gid)
 		current->mm->dumpable = 1;
+	else
+		current->mm->dumpable = suid_dumpable;
+
 	name = bprm->filename;
 
 	/* Copies the binary name from after last slash */
@@ -888,7 +890,7 @@
 	    permission(bprm->file->f_dentry->d_inode,MAY_READ, NULL) ||
 	    (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) {
 		suid_keys(current);
-		current->mm->dumpable = 0;
+		current->mm->dumpable = suid_dumpable;
 	}
 
 	/* An exec changes our domain. We are no longer part of the thread
@@ -1436,6 +1438,8 @@
 	struct inode * inode;
 	struct file * file;
 	int retval = 0;
+	int fsuid = current->fsuid;
+	int flag = 0;
 
 	binfmt = current->binfmt;
 	if (!binfmt || !binfmt->core_dump)
@@ -1445,6 +1449,16 @@
 		up_write(&mm->mmap_sem);
 		goto fail;
 	}
+
+	/*
+	 *	We cannot trust fsuid as being the "true" uid of the
+	 *	process nor do we know its entire history. We only know it
+	 *	was tainted so we dump it as root in mode 2.
+	 */
+	if (mm->dumpable == 2) {	/* Setuid core dump mode */
+		flag = O_EXCL;		/* Stop rewrite attacks */
+		current->fsuid = 0;	/* Dump root private */
+	}
 	mm->dumpable = 0;
 	init_completion(&mm->core_done);
 	spin_lock_irq(&current->sighand->siglock);
@@ -1470,7 +1484,7 @@
  	lock_kernel();
 	format_corename(corename, core_pattern, signr);
 	unlock_kernel();
-	file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE, 0600);
+	file = filp_open(corename, O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag, 0600);
 	if (IS_ERR(file))
 		goto fail_unlock;
 	inode = file->f_dentry->d_inode;
@@ -1495,6 +1509,7 @@
 close_fail:
 	filp_close(file, NULL);
 fail_unlock:
+	current->fsuid = fsuid;
 	complete_all(&mm->core_done);
 fail:
 	return retval;
diff --git a/fs/ext2/Makefile b/fs/ext2/Makefile
index ee240a1..c5d02da 100644
--- a/fs/ext2/Makefile
+++ b/fs/ext2/Makefile
@@ -10,3 +10,4 @@
 ext2-$(CONFIG_EXT2_FS_XATTR)	 += xattr.o xattr_user.o xattr_trusted.o
 ext2-$(CONFIG_EXT2_FS_POSIX_ACL) += acl.o
 ext2-$(CONFIG_EXT2_FS_SECURITY)	 += xattr_security.o
+ext2-$(CONFIG_EXT2_FS_XIP)	 += xip.o
diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c
index 25f4a64..213148c 100644
--- a/fs/ext2/acl.c
+++ b/fs/ext2/acl.c
@@ -396,12 +396,12 @@
 ext2_xattr_list_acl_access(struct inode *inode, char *list, size_t list_size,
 			   const char *name, size_t name_len)
 {
-	const size_t size = sizeof(XATTR_NAME_ACL_ACCESS);
+	const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
 
 	if (!test_opt(inode->i_sb, POSIX_ACL))
 		return 0;
 	if (list && size <= list_size)
-		memcpy(list, XATTR_NAME_ACL_ACCESS, size);
+		memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
 	return size;
 }
 
@@ -409,12 +409,12 @@
 ext2_xattr_list_acl_default(struct inode *inode, char *list, size_t list_size,
 			    const char *name, size_t name_len)
 {
-	const size_t size = sizeof(XATTR_NAME_ACL_DEFAULT);
+	const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
 
 	if (!test_opt(inode->i_sb, POSIX_ACL))
 		return 0;
 	if (list && size <= list_size)
-		memcpy(list, XATTR_NAME_ACL_DEFAULT, size);
+		memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
 	return size;
 }
 
@@ -506,14 +506,14 @@
 }
 
 struct xattr_handler ext2_xattr_acl_access_handler = {
-	.prefix	= XATTR_NAME_ACL_ACCESS,
+	.prefix	= POSIX_ACL_XATTR_ACCESS,
 	.list	= ext2_xattr_list_acl_access,
 	.get	= ext2_xattr_get_acl_access,
 	.set	= ext2_xattr_set_acl_access,
 };
 
 struct xattr_handler ext2_xattr_acl_default_handler = {
-	.prefix	= XATTR_NAME_ACL_DEFAULT,
+	.prefix	= POSIX_ACL_XATTR_DEFAULT,
 	.list	= ext2_xattr_list_acl_default,
 	.get	= ext2_xattr_get_acl_default,
 	.set	= ext2_xattr_set_acl_default,
diff --git a/fs/ext2/acl.h b/fs/ext2/acl.h
index fed96ae..0bde85b 100644
--- a/fs/ext2/acl.h
+++ b/fs/ext2/acl.h
@@ -4,7 +4,7 @@
   (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
 */
 
-#include <linux/xattr_acl.h>
+#include <linux/posix_acl_xattr.h>
 
 #define EXT2_ACL_VERSION	0x0001
 
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index 8f0fd72..eed521d 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -147,9 +147,11 @@
 /* file.c */
 extern struct inode_operations ext2_file_inode_operations;
 extern struct file_operations ext2_file_operations;
+extern 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;
 
 /* namei.c */
diff --git a/fs/ext2/file.c b/fs/ext2/file.c
index f5e8614..a484412 100644
--- a/fs/ext2/file.c
+++ b/fs/ext2/file.c
@@ -55,6 +55,20 @@
 	.sendfile	= generic_file_sendfile,
 };
 
+#ifdef CONFIG_EXT2_FS_XIP
+struct file_operations ext2_xip_file_operations = {
+	.llseek		= generic_file_llseek,
+	.read		= xip_file_read,
+	.write		= xip_file_write,
+	.ioctl		= ext2_ioctl,
+	.mmap		= xip_file_mmap,
+	.open		= generic_file_open,
+	.release	= ext2_release_file,
+	.fsync		= ext2_sync_file,
+	.sendfile	= xip_file_sendfile,
+};
+#endif
+
 struct inode_operations ext2_file_inode_operations = {
 	.truncate	= ext2_truncate,
 #ifdef CONFIG_EXT2_FS_XATTR
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index a50d9db..53dceb0 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -33,6 +33,7 @@
 #include <linux/mpage.h>
 #include "ext2.h"
 #include "acl.h"
+#include "xip.h"
 
 MODULE_AUTHOR("Remy Card and others");
 MODULE_DESCRIPTION("Second Extended Filesystem");
@@ -594,6 +595,16 @@
 	if (err)
 		goto cleanup;
 
+	if (ext2_use_xip(inode->i_sb)) {
+		/*
+		 * we need to clear the block
+		 */
+		err = ext2_clear_xip_target (inode,
+			le32_to_cpu(chain[depth-1].key));
+		if (err)
+			goto cleanup;
+	}
+
 	if (ext2_splice_branch(inode, iblock, chain, partial, left) < 0)
 		goto changed;
 
@@ -691,6 +702,11 @@
 	.writepages		= ext2_writepages,
 };
 
+struct address_space_operations ext2_aops_xip = {
+	.bmap			= ext2_bmap,
+	.get_xip_page		= ext2_get_xip_page,
+};
+
 struct address_space_operations ext2_nobh_aops = {
 	.readpage		= ext2_readpage,
 	.readpages		= ext2_readpages,
@@ -910,7 +926,9 @@
 	iblock = (inode->i_size + blocksize-1)
 					>> EXT2_BLOCK_SIZE_BITS(inode->i_sb);
 
-	if (test_opt(inode->i_sb, NOBH))
+	if (mapping_is_xip(inode->i_mapping))
+		xip_truncate_page(inode->i_mapping, inode->i_size);
+	else if (test_opt(inode->i_sb, NOBH))
 		nobh_truncate_page(inode->i_mapping, inode->i_size);
 	else
 		block_truncate_page(inode->i_mapping,
@@ -1110,11 +1128,16 @@
 
 	if (S_ISREG(inode->i_mode)) {
 		inode->i_op = &ext2_file_inode_operations;
-		inode->i_fop = &ext2_file_operations;
-		if (test_opt(inode->i_sb, NOBH))
+		if (ext2_use_xip(inode->i_sb)) {
+			inode->i_mapping->a_ops = &ext2_aops_xip;
+			inode->i_fop = &ext2_xip_file_operations;
+		} else if (test_opt(inode->i_sb, NOBH)) {
 			inode->i_mapping->a_ops = &ext2_nobh_aops;
-		else
+			inode->i_fop = &ext2_file_operations;
+		} else {
 			inode->i_mapping->a_ops = &ext2_aops;
+			inode->i_fop = &ext2_file_operations;
+		}
 	} else if (S_ISDIR(inode->i_mode)) {
 		inode->i_op = &ext2_dir_inode_operations;
 		inode->i_fop = &ext2_dir_operations;
diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c
index 3176b3d..c551395 100644
--- a/fs/ext2/namei.c
+++ b/fs/ext2/namei.c
@@ -34,6 +34,7 @@
 #include "ext2.h"
 #include "xattr.h"
 #include "acl.h"
+#include "xip.h"
 
 /*
  * Couple of helper functions - make the code slightly cleaner.
@@ -127,11 +128,16 @@
 	int err = PTR_ERR(inode);
 	if (!IS_ERR(inode)) {
 		inode->i_op = &ext2_file_inode_operations;
-		inode->i_fop = &ext2_file_operations;
-		if (test_opt(inode->i_sb, NOBH))
+		if (ext2_use_xip(inode->i_sb)) {
+			inode->i_mapping->a_ops = &ext2_aops_xip;
+			inode->i_fop = &ext2_xip_file_operations;
+		} else if (test_opt(inode->i_sb, NOBH)) {
 			inode->i_mapping->a_ops = &ext2_nobh_aops;
-		else
+			inode->i_fop = &ext2_file_operations;
+		} else {
 			inode->i_mapping->a_ops = &ext2_aops;
+			inode->i_fop = &ext2_file_operations;
+		}
 		mark_inode_dirty(inode);
 		err = ext2_add_nondir(dentry, inode);
 	}
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 661c3d9..876e391 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -31,6 +31,7 @@
 #include "ext2.h"
 #include "xattr.h"
 #include "acl.h"
+#include "xip.h"
 
 static void ext2_sync_super(struct super_block *sb,
 			    struct ext2_super_block *es);
@@ -257,7 +258,7 @@
 	Opt_bsd_df, Opt_minix_df, Opt_grpid, Opt_nogrpid,
 	Opt_resgid, Opt_resuid, Opt_sb, Opt_err_cont, Opt_err_panic, Opt_err_ro,
 	Opt_nouid32, Opt_check, Opt_nocheck, Opt_debug, Opt_oldalloc, Opt_orlov, Opt_nobh,
-	Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl,
+	Opt_user_xattr, Opt_nouser_xattr, Opt_acl, Opt_noacl, Opt_xip,
 	Opt_ignore, Opt_err,
 };
 
@@ -286,6 +287,7 @@
 	{Opt_nouser_xattr, "nouser_xattr"},
 	{Opt_acl, "acl"},
 	{Opt_noacl, "noacl"},
+	{Opt_xip, "xip"},
 	{Opt_ignore, "grpquota"},
 	{Opt_ignore, "noquota"},
 	{Opt_ignore, "quota"},
@@ -397,6 +399,13 @@
 			printk("EXT2 (no)acl options not supported\n");
 			break;
 #endif
+		case Opt_xip:
+#ifdef CONFIG_EXT2_FS_XIP
+			set_opt (sbi->s_mount_opt, XIP);
+#else
+			printk("EXT2 xip option not supported\n");
+#endif
+			break;
 		case Opt_ignore:
 			break;
 		default:
@@ -640,6 +649,9 @@
 		((EXT2_SB(sb)->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ?
 		 MS_POSIXACL : 0);
 
+	ext2_xip_verify_sb(sb); /* see if bdev supports xip, unset
+				    EXT2_MOUNT_XIP if not */
+
 	if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV &&
 	    (EXT2_HAS_COMPAT_FEATURE(sb, ~0U) ||
 	     EXT2_HAS_RO_COMPAT_FEATURE(sb, ~0U) ||
@@ -668,6 +680,13 @@
 
 	blocksize = BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size);
 
+	if ((ext2_use_xip(sb)) && ((blocksize != PAGE_SIZE) ||
+				  (sb->s_blocksize != blocksize))) {
+		if (!silent)
+			printk("XIP: Unsupported blocksize\n");
+		goto failed_mount;
+	}
+
 	/* If the blocksize doesn't match, re-read the thing.. */
 	if (sb->s_blocksize != blocksize) {
 		brelse(bh);
@@ -916,6 +935,7 @@
 {
 	struct ext2_sb_info * sbi = EXT2_SB(sb);
 	struct ext2_super_block * es;
+	unsigned long old_mount_opt = sbi->s_mount_opt;
 
 	/*
 	 * Allow the "check" option to be passed as a remount option.
@@ -927,6 +947,11 @@
 		((sbi->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0);
 
 	es = sbi->s_es;
+	if (((sbi->s_mount_opt & EXT2_MOUNT_XIP) !=
+	    (old_mount_opt & EXT2_MOUNT_XIP)) &&
+	    invalidate_inodes(sb))
+		ext2_warning(sb, __FUNCTION__, "busy inodes while remounting "\
+			     "xip remain in cache (no functional problem)");
 	if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
 		return 0;
 	if (*flags & MS_RDONLY) {
diff --git a/fs/ext2/xip.c b/fs/ext2/xip.c
new file mode 100644
index 0000000..d44431d
--- /dev/null
+++ b/fs/ext2/xip.c
@@ -0,0 +1,80 @@
+/*
+ *  linux/fs/ext2/xip.c
+ *
+ * Copyright (C) 2005 IBM Corporation
+ * Author: Carsten Otte (cotte@de.ibm.com)
+ */
+
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/buffer_head.h>
+#include <linux/ext2_fs_sb.h>
+#include <linux/ext2_fs.h>
+#include "ext2.h"
+#include "xip.h"
+
+static inline int
+__inode_direct_access(struct inode *inode, sector_t sector, unsigned long *data) {
+	BUG_ON(!inode->i_sb->s_bdev->bd_disk->fops->direct_access);
+	return inode->i_sb->s_bdev->bd_disk->fops
+		->direct_access(inode->i_sb->s_bdev,sector,data);
+}
+
+int
+ext2_clear_xip_target(struct inode *inode, int block) {
+	sector_t sector = block*(PAGE_SIZE/512);
+	unsigned long data;
+	int rc;
+
+	rc = __inode_direct_access(inode, sector, &data);
+	if (rc)
+		return rc;
+	clear_page((void*)data);
+	return 0;
+}
+
+void ext2_xip_verify_sb(struct super_block *sb)
+{
+	struct ext2_sb_info *sbi = EXT2_SB(sb);
+
+	if ((sbi->s_mount_opt & EXT2_MOUNT_XIP)) {
+		if ((sb->s_bdev == NULL) ||
+			sb->s_bdev->bd_disk == NULL ||
+			sb->s_bdev->bd_disk->fops == NULL ||
+			sb->s_bdev->bd_disk->fops->direct_access == NULL) {
+			sbi->s_mount_opt &= (~EXT2_MOUNT_XIP);
+			ext2_warning(sb, __FUNCTION__,
+				"ignoring xip option - not supported by bdev");
+		}
+	}
+}
+
+struct page*
+ext2_get_xip_page(struct address_space *mapping, sector_t blockno,
+		   int create)
+{
+	int rc;
+	unsigned long data;
+	struct buffer_head tmp;
+
+	tmp.b_state = 0;
+	tmp.b_blocknr = 0;
+	rc = ext2_get_block(mapping->host, blockno/(PAGE_SIZE/512) , &tmp,
+				create);
+	if (rc)
+		return ERR_PTR(rc);
+	if (tmp.b_blocknr == 0) {
+		/* SPARSE block */
+		BUG_ON(create);
+		return ERR_PTR(-ENODATA);
+	}
+
+	rc = __inode_direct_access
+		(mapping->host,tmp.b_blocknr*(PAGE_SIZE/512) ,&data);
+	if (rc)
+		return ERR_PTR(rc);
+
+	SetPageUptodate(virt_to_page(data));
+	return virt_to_page(data);
+}
diff --git a/fs/ext2/xip.h b/fs/ext2/xip.h
new file mode 100644
index 0000000..aa85331
--- /dev/null
+++ b/fs/ext2/xip.h
@@ -0,0 +1,25 @@
+/*
+ *  linux/fs/ext2/xip.h
+ *
+ * Copyright (C) 2005 IBM Corporation
+ * Author: Carsten Otte (cotte@de.ibm.com)
+ */
+
+#ifdef CONFIG_EXT2_FS_XIP
+extern void ext2_xip_verify_sb (struct super_block *);
+extern int ext2_clear_xip_target (struct inode *, int);
+
+static inline int ext2_use_xip (struct super_block *sb)
+{
+	struct ext2_sb_info *sbi = EXT2_SB(sb);
+	return (sbi->s_mount_opt & EXT2_MOUNT_XIP);
+}
+struct page* ext2_get_xip_page (struct address_space *, sector_t, int);
+#define mapping_is_xip(map) unlikely(map->a_ops->get_xip_page)
+#else
+#define mapping_is_xip(map)			0
+#define ext2_xip_verify_sb(sb)			do { } while (0)
+#define ext2_use_xip(sb)			0
+#define ext2_clear_xip_target(inode, chain)	0
+#define ext2_get_xip_page			NULL
+#endif
diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c
index 638c13a..3ac3826 100644
--- a/fs/ext3/acl.c
+++ b/fs/ext3/acl.c
@@ -393,7 +393,8 @@
 		int retries = 0;
 
 	retry:
-		handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS);
+		handle = ext3_journal_start(inode,
+				EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
 		if (IS_ERR(handle)) {
 			error = PTR_ERR(handle);
 			ext3_std_error(inode->i_sb, error);
@@ -417,12 +418,12 @@
 ext3_xattr_list_acl_access(struct inode *inode, char *list, size_t list_len,
 			   const char *name, size_t name_len)
 {
-	const size_t size = sizeof(XATTR_NAME_ACL_ACCESS);
+	const size_t size = sizeof(POSIX_ACL_XATTR_ACCESS);
 
 	if (!test_opt(inode->i_sb, POSIX_ACL))
 		return 0;
 	if (list && size <= list_len)
-		memcpy(list, XATTR_NAME_ACL_ACCESS, size);
+		memcpy(list, POSIX_ACL_XATTR_ACCESS, size);
 	return size;
 }
 
@@ -430,12 +431,12 @@
 ext3_xattr_list_acl_default(struct inode *inode, char *list, size_t list_len,
 			    const char *name, size_t name_len)
 {
-	const size_t size = sizeof(XATTR_NAME_ACL_DEFAULT);
+	const size_t size = sizeof(POSIX_ACL_XATTR_DEFAULT);
 
 	if (!test_opt(inode->i_sb, POSIX_ACL))
 		return 0;
 	if (list && size <= list_len)
-		memcpy(list, XATTR_NAME_ACL_DEFAULT, size);
+		memcpy(list, POSIX_ACL_XATTR_DEFAULT, size);
 	return size;
 }
 
@@ -503,7 +504,7 @@
 		acl = NULL;
 
 retry:
-	handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS);
+	handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
 	error = ext3_set_acl(handle, inode, type, acl);
@@ -535,14 +536,14 @@
 }
 
 struct xattr_handler ext3_xattr_acl_access_handler = {
-	.prefix	= XATTR_NAME_ACL_ACCESS,
+	.prefix	= POSIX_ACL_XATTR_ACCESS,
 	.list	= ext3_xattr_list_acl_access,
 	.get	= ext3_xattr_get_acl_access,
 	.set	= ext3_xattr_set_acl_access,
 };
 
 struct xattr_handler ext3_xattr_acl_default_handler = {
-	.prefix	= XATTR_NAME_ACL_DEFAULT,
+	.prefix	= POSIX_ACL_XATTR_DEFAULT,
 	.list	= ext3_xattr_list_acl_default,
 	.get	= ext3_xattr_get_acl_default,
 	.set	= ext3_xattr_set_acl_default,
diff --git a/fs/ext3/acl.h b/fs/ext3/acl.h
index 98af0c0..92d50b5 100644
--- a/fs/ext3/acl.h
+++ b/fs/ext3/acl.h
@@ -4,7 +4,7 @@
   (C) 2001 Andreas Gruenbacher, <a.gruenbacher@computer.org>
 */
 
-#include <linux/xattr_acl.h>
+#include <linux/posix_acl_xattr.h>
 
 #define EXT3_ACL_VERSION	0x0001
 
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 0d5fa73..0b2db4f 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -128,7 +128,7 @@
 	if (needed > EXT3_MAX_TRANS_DATA) 
 		needed = EXT3_MAX_TRANS_DATA;
 
-	return EXT3_DATA_TRANS_BLOCKS + needed;
+	return EXT3_DATA_TRANS_BLOCKS(inode->i_sb) + needed;
 }
 
 /* 
@@ -2763,7 +2763,8 @@
 
 		/* (user+group)*(old+new) structure, inode write (sb,
 		 * inode block, ? - but truncate inode update has it) */
-		handle = ext3_journal_start(inode, 4*EXT3_QUOTA_INIT_BLOCKS+3);
+		handle = ext3_journal_start(inode, 2*(EXT3_QUOTA_INIT_BLOCKS(inode->i_sb)+
+					EXT3_QUOTA_DEL_BLOCKS(inode->i_sb))+3);
 		if (IS_ERR(handle)) {
 			error = PTR_ERR(handle);
 			goto err_out;
@@ -2861,7 +2862,7 @@
 #ifdef CONFIG_QUOTA
 	/* We know that structure was already allocated during DQUOT_INIT so
 	 * we will be updating only the data blocks + inodes */
-	ret += 2*EXT3_QUOTA_TRANS_BLOCKS;
+	ret += 2*EXT3_QUOTA_TRANS_BLOCKS(inode->i_sb);
 #endif
 
 	return ret;
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
index 79742d8..50378d8 100644
--- a/fs/ext3/namei.c
+++ b/fs/ext3/namei.c
@@ -932,8 +932,16 @@
 	struct inode *dir = dentry->d_parent->d_inode;
 
 	sb = dir->i_sb;
-	if (!(frame = dx_probe(dentry, NULL, &hinfo, frames, err)))
-		return NULL;
+	/* NFS may look up ".." - look at dx_root directory block */
+	if (namelen > 2 || name[0] != '.'||(name[1] != '.' && name[1] != '\0')){
+		if (!(frame = dx_probe(dentry, NULL, &hinfo, frames, err)))
+			return NULL;
+	} else {
+		frame = frames;
+		frame->bh = NULL;			/* for dx_release() */
+		frame->at = (struct dx_entry *)frames;	/* hack for zero entry*/
+		dx_set_block(frame->at, 0);		/* dx_root block is 0 */
+	}
 	hash = hinfo.hash;
 	do {
 		block = dx_get_block(frame->at);
@@ -1637,9 +1645,9 @@
 	int err, retries = 0;
 
 retry:
-	handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
+	handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
 					EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
-					2*EXT3_QUOTA_INIT_BLOCKS);
+					2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
 
@@ -1671,9 +1679,9 @@
 		return -EINVAL;
 
 retry:
-	handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
+	handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
 			 		EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
-					2*EXT3_QUOTA_INIT_BLOCKS);
+					2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
 
@@ -1707,9 +1715,9 @@
 		return -EMLINK;
 
 retry:
-	handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
+	handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
 					EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 +
-					2*EXT3_QUOTA_INIT_BLOCKS);
+					2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
 
@@ -1998,7 +2006,7 @@
 	/* Initialize quotas before so that eventual writes go in
 	 * separate transaction */
 	DQUOT_INIT(dentry->d_inode);
-	handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
+	handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS(dir->i_sb));
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
 
@@ -2057,7 +2065,7 @@
 	/* Initialize quotas before so that eventual writes go
 	 * in separate transaction */
 	DQUOT_INIT(dentry->d_inode);
-	handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS);
+	handle = ext3_journal_start(dir, EXT3_DELETE_TRANS_BLOCKS(dir->i_sb));
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
 
@@ -2112,9 +2120,9 @@
 		return -ENAMETOOLONG;
 
 retry:
-	handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
+	handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
 			 		EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 +
-					2*EXT3_QUOTA_INIT_BLOCKS);
+					2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb));
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
 
@@ -2166,7 +2174,7 @@
 		return -EMLINK;
 
 retry:
-	handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
+	handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) +
 					EXT3_INDEX_EXTRA_TRANS_BLOCKS);
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
@@ -2208,7 +2216,8 @@
 	 * in separate transaction */
 	if (new_dentry->d_inode)
 		DQUOT_INIT(new_dentry->d_inode);
-	handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS +
+	handle = ext3_journal_start(old_dir, 2 *
+					EXT3_DATA_TRANS_BLOCKS(old_dir->i_sb) +
 			 		EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2);
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 981ccb2..b4b3e8a 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -589,7 +589,7 @@
 	Opt_commit, Opt_journal_update, Opt_journal_inum,
 	Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
 	Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
-	Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0,
+	Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
 	Opt_ignore, Opt_barrier, Opt_err, Opt_resize,
 };
 
@@ -634,10 +634,10 @@
 	{Opt_grpjquota, "grpjquota=%s"},
 	{Opt_jqfmt_vfsold, "jqfmt=vfsold"},
 	{Opt_jqfmt_vfsv0, "jqfmt=vfsv0"},
-	{Opt_ignore, "grpquota"},
-	{Opt_ignore, "noquota"},
-	{Opt_ignore, "quota"},
-	{Opt_ignore, "usrquota"},
+	{Opt_quota, "grpquota"},
+	{Opt_noquota, "noquota"},
+	{Opt_quota, "quota"},
+	{Opt_quota, "usrquota"},
 	{Opt_barrier, "barrier=%u"},
 	{Opt_err, NULL},
 	{Opt_resize, "resize"},
@@ -876,6 +876,7 @@
 				sbi->s_qf_names[qtype] = NULL;
 				return 0;
 			}
+			set_opt(sbi->s_mount_opt, QUOTA);
 			break;
 		case Opt_offusrjquota:
 			qtype = USRQUOTA;
@@ -898,6 +899,17 @@
 		case Opt_jqfmt_vfsv0:
 			sbi->s_jquota_fmt = QFMT_VFS_V0;
 			break;
+		case Opt_quota:
+			set_opt(sbi->s_mount_opt, QUOTA);
+			break;
+		case Opt_noquota:
+			if (sb_any_quota_enabled(sb)) {
+				printk(KERN_ERR "EXT3-fs: Cannot change quota "
+					"options when quota turned on.\n");
+				return 0;
+			}
+			clear_opt(sbi->s_mount_opt, QUOTA);
+			break;
 #else
 		case Opt_usrjquota:
 		case Opt_grpjquota:
@@ -909,6 +921,9 @@
 				"EXT3-fs: journalled quota options not "
 				"supported.\n");
 			break;
+		case Opt_quota:
+		case Opt_noquota:
+			break;
 #endif
 		case Opt_abort:
 			set_opt(sbi->s_mount_opt, ABORT);
@@ -2238,7 +2253,7 @@
 	int ret, err;
 
 	/* We may create quota structure so we need to reserve enough blocks */
-	handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS);
+	handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS(inode->i_sb));
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
 	ret = dquot_initialize(inode, type);
@@ -2254,7 +2269,7 @@
 	int ret, err;
 
 	/* We may delete quota structure so we need to reserve enough blocks */
-	handle = ext3_journal_start(inode, 2*EXT3_QUOTA_INIT_BLOCKS);
+	handle = ext3_journal_start(inode, 2*EXT3_QUOTA_DEL_BLOCKS(inode->i_sb));
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
 	ret = dquot_drop(inode);
@@ -2272,7 +2287,7 @@
 
 	inode = dquot_to_inode(dquot);
 	handle = ext3_journal_start(inode,
-					EXT3_QUOTA_TRANS_BLOCKS);
+					EXT3_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
 	ret = dquot_commit(dquot);
@@ -2288,7 +2303,7 @@
 	handle_t *handle;
 
 	handle = ext3_journal_start(dquot_to_inode(dquot),
-					EXT3_QUOTA_INIT_BLOCKS);
+					EXT3_QUOTA_INIT_BLOCKS(dquot->dq_sb));
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
 	ret = dquot_acquire(dquot);
@@ -2304,7 +2319,7 @@
 	handle_t *handle;
 
 	handle = ext3_journal_start(dquot_to_inode(dquot),
-					EXT3_QUOTA_INIT_BLOCKS);
+					EXT3_QUOTA_DEL_BLOCKS(dquot->dq_sb));
 	if (IS_ERR(handle))
 		return PTR_ERR(handle);
 	ret = dquot_release(dquot);
@@ -2348,22 +2363,8 @@
  */
 static int ext3_quota_on_mount(struct super_block *sb, int type)
 {
-	int err;
-	struct dentry *dentry;
-	struct qstr name = { .name = EXT3_SB(sb)->s_qf_names[type],
-			     .hash = 0,
-			     .len = strlen(EXT3_SB(sb)->s_qf_names[type])};
-
-	dentry = lookup_hash(&name, sb->s_root);
-	if (IS_ERR(dentry))
-		return PTR_ERR(dentry);
-	err = vfs_quota_on_mount(type, EXT3_SB(sb)->s_jquota_fmt, dentry);
-	/* Now invalidate and put the dentry - quota got its own reference
-	 * to inode and dentry has at least wrong hash so we had better
-	 * throw it away */
-	d_invalidate(dentry);
-	dput(dentry);
-	return err;
+	return vfs_quota_on_mount(sb, EXT3_SB(sb)->s_qf_names[type],
+			EXT3_SB(sb)->s_jquota_fmt, type);
 }
 
 /*
@@ -2375,6 +2376,8 @@
 	int err;
 	struct nameidata nd;
 
+	if (!test_opt(sb, QUOTA))
+		return -EINVAL;
 	/* Not journalling quota? */
 	if (!EXT3_SB(sb)->s_qf_names[USRQUOTA] &&
 	    !EXT3_SB(sb)->s_qf_names[GRPQUOTA])
diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c
index 4cbc6d0..3f9dfa6 100644
--- a/fs/ext3/xattr.c
+++ b/fs/ext3/xattr.c
@@ -1044,7 +1044,7 @@
 	int error, retries = 0;
 
 retry:
-	handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS);
+	handle = ext3_journal_start(inode, EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
 	if (IS_ERR(handle)) {
 		error = PTR_ERR(handle);
 	} else {
diff --git a/fs/file_table.c b/fs/file_table.c
index 03d83cb..fa7849f 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -63,42 +63,45 @@
  */
 struct file *get_empty_filp(void)
 {
-static int old_max;
+	static int old_max;
 	struct file * f;
 
 	/*
 	 * Privileged users can go above max_files
 	 */
-	if (files_stat.nr_files < files_stat.max_files ||
-				capable(CAP_SYS_ADMIN)) {
-		f = kmem_cache_alloc(filp_cachep, GFP_KERNEL);
-		if (f) {
-			memset(f, 0, sizeof(*f));
-			if (security_file_alloc(f)) {
-				file_free(f);
-				goto fail;
-			}
-			eventpoll_init_file(f);
-			atomic_set(&f->f_count, 1);
-			f->f_uid = current->fsuid;
-			f->f_gid = current->fsgid;
-			rwlock_init(&f->f_owner.lock);
-			/* f->f_version: 0 */
-			INIT_LIST_HEAD(&f->f_list);
-			f->f_maxcount = INT_MAX;
-			return f;
-		}
-	}
+	if (files_stat.nr_files >= files_stat.max_files &&
+				!capable(CAP_SYS_ADMIN))
+		goto over;
 
+	f = kmem_cache_alloc(filp_cachep, GFP_KERNEL);
+	if (f == NULL)
+		goto fail;
+
+	memset(f, 0, sizeof(*f));
+	if (security_file_alloc(f))
+		goto fail_sec;
+
+	eventpoll_init_file(f);
+	atomic_set(&f->f_count, 1);
+	f->f_uid = current->fsuid;
+	f->f_gid = current->fsgid;
+	rwlock_init(&f->f_owner.lock);
+	/* f->f_version: 0 */
+	INIT_LIST_HEAD(&f->f_list);
+	f->f_maxcount = INT_MAX;
+	return f;
+
+over:
 	/* Ran out of filps - report that */
-	if (files_stat.max_files >= old_max) {
+	if (files_stat.nr_files > old_max) {
 		printk(KERN_INFO "VFS: file-max limit %d reached\n",
 					files_stat.max_files);
-		old_max = files_stat.max_files;
-	} else {
-		/* Big problems... */
-		printk(KERN_WARNING "VFS: filp allocation failed\n");
+		old_max = files_stat.nr_files;
 	}
+	goto fail;
+
+fail_sec:
+	file_free(f);
 fail:
 	return NULL;
 }
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index 8e050fa..e94ab39 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -485,32 +485,6 @@
 	spin_unlock(&sb_lock);
 }
 
-/*
- * Find a superblock with inodes that need to be synced
- */
-static struct super_block *get_super_to_sync(void)
-{
-	struct super_block *sb;
-restart:
-	spin_lock(&sb_lock);
-	sb = sb_entry(super_blocks.prev);
-	for (; sb != sb_entry(&super_blocks); sb = sb_entry(sb->s_list.prev)) {
-		if (sb->s_syncing)
-			continue;
-		sb->s_syncing = 1;
-		sb->s_count++;
-		spin_unlock(&sb_lock);
-		down_read(&sb->s_umount);
-		if (!sb->s_root) {
-			drop_super(sb);
-			goto restart;
-		}
-		return sb;
-	}
-	spin_unlock(&sb_lock);
-	return NULL;
-}
-
 /**
  * sync_inodes - writes all inodes to disk
  * @wait: wait for completion
@@ -530,23 +504,39 @@
  * outstanding dirty inodes, the writeback goes block-at-a-time within the
  * filesystem's write_inode().  This is extremely slow.
  */
-void sync_inodes(int wait)
+static void __sync_inodes(int wait)
 {
 	struct super_block *sb;
 
-	set_sb_syncing(0);
-	while ((sb = get_super_to_sync()) != NULL) {
-		sync_inodes_sb(sb, 0);
-		sync_blockdev(sb->s_bdev);
-		drop_super(sb);
+	spin_lock(&sb_lock);
+restart:
+	list_for_each_entry(sb, &super_blocks, s_list) {
+		if (sb->s_syncing)
+			continue;
+		sb->s_syncing = 1;
+		sb->s_count++;
+		spin_unlock(&sb_lock);
+		down_read(&sb->s_umount);
+		if (sb->s_root) {
+			sync_inodes_sb(sb, wait);
+			sync_blockdev(sb->s_bdev);
+		}
+		up_read(&sb->s_umount);
+		spin_lock(&sb_lock);
+		if (__put_super_and_need_restart(sb))
+			goto restart;
 	}
+	spin_unlock(&sb_lock);
+}
+
+void sync_inodes(int wait)
+{
+	set_sb_syncing(0);
+	__sync_inodes(0);
+
 	if (wait) {
 		set_sb_syncing(0);
-		while ((sb = get_super_to_sync()) != NULL) {
-			sync_inodes_sb(sb, 1);
-			sync_blockdev(sb->s_bdev);
-			drop_super(sb);
-		}
+		__sync_inodes(1);
 	}
 }
 
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 2af3338..3a9b6d1 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -122,6 +122,9 @@
 
 	start_addr = mm->free_area_cache;
 
+	if (len <= mm->cached_hole_size)
+		start_addr = TASK_UNMAPPED_BASE;
+
 full_search:
 	addr = ALIGN(start_addr, HPAGE_SIZE);
 
diff --git a/fs/inode.c b/fs/inode.c
index 801fe7f..1f9a3a2 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -500,7 +500,7 @@
 			continue;
 		if (!test(inode, data))
 			continue;
-		if (inode->i_state & (I_FREEING|I_CLEAR)) {
+		if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)) {
 			__wait_on_freeing_inode(inode);
 			goto repeat;
 		}
@@ -525,7 +525,7 @@
 			continue;
 		if (inode->i_sb != sb)
 			continue;
-		if (inode->i_state & (I_FREEING|I_CLEAR)) {
+		if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)) {
 			__wait_on_freeing_inode(inode);
 			goto repeat;
 		}
@@ -727,7 +727,7 @@
 struct inode *igrab(struct inode *inode)
 {
 	spin_lock(&inode_lock);
-	if (!(inode->i_state & I_FREEING))
+	if (!(inode->i_state & (I_FREEING|I_WILL_FREE)))
 		__iget(inode);
 	else
 		/*
@@ -1024,17 +1024,21 @@
 		if (!(inode->i_state & (I_DIRTY|I_LOCK)))
 			list_move(&inode->i_list, &inode_unused);
 		inodes_stat.nr_unused++;
-		spin_unlock(&inode_lock);
-		if (!sb || (sb->s_flags & MS_ACTIVE))
+		if (!sb || (sb->s_flags & MS_ACTIVE)) {
+			spin_unlock(&inode_lock);
 			return;
+		}
+		inode->i_state |= I_WILL_FREE;
+		spin_unlock(&inode_lock);
 		write_inode_now(inode, 1);
 		spin_lock(&inode_lock);
+		inode->i_state &= ~I_WILL_FREE;
 		inodes_stat.nr_unused--;
 		hlist_del_init(&inode->i_hash);
 	}
 	list_del_init(&inode->i_list);
 	list_del_init(&inode->i_sb_list);
-	inode->i_state|=I_FREEING;
+	inode->i_state |= I_FREEING;
 	inodes_stat.nr_inodes--;
 	spin_unlock(&inode_lock);
 	if (inode->i_data.nrpages)
diff --git a/fs/ioprio.c b/fs/ioprio.c
new file mode 100644
index 0000000..663e420
--- /dev/null
+++ b/fs/ioprio.c
@@ -0,0 +1,172 @@
+/*
+ * fs/ioprio.c
+ *
+ * Copyright (C) 2004 Jens Axboe <axboe@suse.de>
+ *
+ * Helper functions for setting/querying io priorities of processes. The
+ * system calls closely mimmick getpriority/setpriority, see the man page for
+ * those. The prio argument is a composite of prio class and prio data, where
+ * the data argument has meaning within that class. The standard scheduling
+ * classes have 8 distinct prio levels, with 0 being the highest prio and 7
+ * being the lowest.
+ *
+ * IOW, setting BE scheduling class with prio 2 is done ala:
+ *
+ * unsigned int prio = (IOPRIO_CLASS_BE << IOPRIO_CLASS_SHIFT) | 2;
+ *
+ * ioprio_set(PRIO_PROCESS, pid, prio);
+ *
+ * See also Documentation/block/ioprio.txt
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/ioprio.h>
+#include <linux/blkdev.h>
+
+static int set_task_ioprio(struct task_struct *task, int ioprio)
+{
+	struct io_context *ioc;
+
+	if (task->uid != current->euid &&
+	    task->uid != current->uid && !capable(CAP_SYS_NICE))
+		return -EPERM;
+
+	task_lock(task);
+
+	task->ioprio = ioprio;
+
+	ioc = task->io_context;
+	if (ioc && ioc->set_ioprio)
+		ioc->set_ioprio(ioc, ioprio);
+
+	task_unlock(task);
+	return 0;
+}
+
+asmlinkage int sys_ioprio_set(int which, int who, int ioprio)
+{
+	int class = IOPRIO_PRIO_CLASS(ioprio);
+	int data = IOPRIO_PRIO_DATA(ioprio);
+	struct task_struct *p, *g;
+	struct user_struct *user;
+	int ret;
+
+	switch (class) {
+		case IOPRIO_CLASS_RT:
+			if (!capable(CAP_SYS_ADMIN))
+				return -EPERM;
+			/* fall through, rt has prio field too */
+		case IOPRIO_CLASS_BE:
+			if (data >= IOPRIO_BE_NR || data < 0)
+				return -EINVAL;
+
+			break;
+		case IOPRIO_CLASS_IDLE:
+			break;
+		default:
+			return -EINVAL;
+	}
+
+	ret = -ESRCH;
+	read_lock_irq(&tasklist_lock);
+	switch (which) {
+		case IOPRIO_WHO_PROCESS:
+			if (!who)
+				p = current;
+			else
+				p = find_task_by_pid(who);
+			if (p)
+				ret = set_task_ioprio(p, ioprio);
+			break;
+		case IOPRIO_WHO_PGRP:
+			if (!who)
+				who = process_group(current);
+			do_each_task_pid(who, PIDTYPE_PGID, p) {
+				ret = set_task_ioprio(p, ioprio);
+				if (ret)
+					break;
+			} while_each_task_pid(who, PIDTYPE_PGID, p);
+			break;
+		case IOPRIO_WHO_USER:
+			if (!who)
+				user = current->user;
+			else
+				user = find_user(who);
+
+			if (!user)
+				break;
+
+			do_each_thread(g, p) {
+				if (p->uid != who)
+					continue;
+				ret = set_task_ioprio(p, ioprio);
+				if (ret)
+					break;
+			} while_each_thread(g, p);
+
+			if (who)
+				free_uid(user);
+			break;
+		default:
+			ret = -EINVAL;
+	}
+
+	read_unlock_irq(&tasklist_lock);
+	return ret;
+}
+
+asmlinkage int sys_ioprio_get(int which, int who)
+{
+	struct task_struct *g, *p;
+	struct user_struct *user;
+	int ret = -ESRCH;
+
+	read_lock_irq(&tasklist_lock);
+	switch (which) {
+		case IOPRIO_WHO_PROCESS:
+			if (!who)
+				p = current;
+			else
+				p = find_task_by_pid(who);
+			if (p)
+				ret = p->ioprio;
+			break;
+		case IOPRIO_WHO_PGRP:
+			if (!who)
+				who = process_group(current);
+			do_each_task_pid(who, PIDTYPE_PGID, p) {
+				if (ret == -ESRCH)
+					ret = p->ioprio;
+				else
+					ret = ioprio_best(ret, p->ioprio);
+			} while_each_task_pid(who, PIDTYPE_PGID, p);
+			break;
+		case IOPRIO_WHO_USER:
+			if (!who)
+				user = current->user;
+			else
+				user = find_user(who);
+
+			if (!user)
+				break;
+
+			do_each_thread(g, p) {
+				if (p->uid != user->uid)
+					continue;
+				if (ret == -ESRCH)
+					ret = p->ioprio;
+				else
+					ret = ioprio_best(ret, p->ioprio);
+			} while_each_thread(g, p);
+
+			if (who)
+				free_uid(user);
+			break;
+		default:
+			ret = -EINVAL;
+	}
+
+	read_unlock_irq(&tasklist_lock);
+	return ret;
+}
+
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c
index 6030956..7901ac9 100644
--- a/fs/isofs/dir.c
+++ b/fs/isofs/dir.c
@@ -193,12 +193,17 @@
 
 		/* Handle everything else.  Do name translation if there
 		   is no Rock Ridge NM field. */
-		if (sbi->s_unhide == 'n') {
-			/* Do not report hidden or associated files */
-			if (de->flags[-sbi->s_high_sierra] & 5) {
-				filp->f_pos += de_len;
-				continue;
-			}
+
+		/*
+		 * Do not report hidden files if so instructed, or associated
+		 * files unless instructed to do so
+		 */
+		if ((sbi->s_hide == 'y' &&
+				(de->flags[-sbi->s_high_sierra] & 1)) ||
+		      (sbi->s_showassoc =='n' &&
+				(de->flags[-sbi->s_high_sierra] & 4))) {
+			filp->f_pos += de_len;
+			continue;
 		}
 
 		map = 1;
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c
index abd7b12..1652de1 100644
--- a/fs/isofs/inode.c
+++ b/fs/isofs/inode.c
@@ -28,11 +28,6 @@
 
 #define BEQUIET
 
-#ifdef LEAK_CHECK
-static int check_malloc;
-static int check_bread;
-#endif
-
 static int isofs_hashi(struct dentry *parent, struct qstr *qstr);
 static int isofs_hash(struct dentry *parent, struct qstr *qstr);
 static int isofs_dentry_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
@@ -55,11 +50,6 @@
 	}
 #endif
 
-#ifdef LEAK_CHECK
-	printk("Outstanding mallocs:%d, outstanding buffers: %d\n",
-	       check_malloc, check_bread);
-#endif
-
 	kfree(sbi);
 	sb->s_fs_info = NULL;
 	return;
@@ -73,7 +63,7 @@
 static struct inode *isofs_alloc_inode(struct super_block *sb)
 {
 	struct iso_inode_info *ei;
-	ei = (struct iso_inode_info *)kmem_cache_alloc(isofs_inode_cachep, SLAB_KERNEL);
+	ei = kmem_cache_alloc(isofs_inode_cachep, SLAB_KERNEL);
 	if (!ei)
 		return NULL;
 	return &ei->vfs_inode;
@@ -84,9 +74,9 @@
 	kmem_cache_free(isofs_inode_cachep, ISOFS_I(inode));
 }
 
-static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
 {
-	struct iso_inode_info *ei = (struct iso_inode_info *) foo;
+	struct iso_inode_info *ei = foo;
 
 	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
 	    SLAB_CTOR_CONSTRUCTOR)
@@ -107,7 +97,8 @@
 static void destroy_inodecache(void)
 {
 	if (kmem_cache_destroy(isofs_inode_cachep))
-		printk(KERN_INFO "iso_inode_cache: not all structures were freed\n");
+		printk(KERN_INFO "iso_inode_cache: not all structures were "
+					"freed\n");
 }
 
 static int isofs_remount(struct super_block *sb, int *flags, char *data)
@@ -144,7 +135,7 @@
 	{
 		.d_hash		= isofs_hashi_ms,
 		.d_compare	= isofs_dentry_cmpi_ms,
-	}
+	},
 #endif
 };
 
@@ -153,7 +144,8 @@
 	char rock;
 	char joliet;
 	char cruft;
-	char unhide;
+	char hide;
+	char showassoc;
 	char nocompress;
 	unsigned char check;
 	unsigned int blocksize;
@@ -219,8 +211,8 @@
 /*
  * Case insensitive compare of two isofs names.
  */
-static int
-isofs_dentry_cmpi_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int ms)
+static int isofs_dentry_cmpi_common(struct dentry *dentry, struct qstr *a,
+				struct qstr *b, int ms)
 {
 	int alen, blen;
 
@@ -243,8 +235,8 @@
 /*
  * Case sensitive compare of two isofs names.
  */
-static int
-isofs_dentry_cmp_common(struct dentry *dentry,struct qstr *a,struct qstr *b,int ms)
+static int isofs_dentry_cmp_common(struct dentry *dentry, struct qstr *a,
+					struct qstr *b, int ms)
 {
 	int alen, blen;
 
@@ -318,13 +310,15 @@
 	Opt_block, Opt_check_r, Opt_check_s, Opt_cruft, Opt_gid, Opt_ignore,
 	Opt_iocharset, Opt_map_a, Opt_map_n, Opt_map_o, Opt_mode, Opt_nojoliet,
 	Opt_norock, Opt_sb, Opt_session, Opt_uid, Opt_unhide, Opt_utf8, Opt_err,
-	Opt_nocompress,
+	Opt_nocompress, Opt_hide, Opt_showassoc,
 };
 
 static match_table_t tokens = {
 	{Opt_norock, "norock"},
 	{Opt_nojoliet, "nojoliet"},
 	{Opt_unhide, "unhide"},
+	{Opt_hide, "hide"},
+	{Opt_showassoc, "showassoc"},
 	{Opt_cruft, "cruft"},
 	{Opt_utf8, "utf8"},
 	{Opt_iocharset, "iocharset=%s"},
@@ -356,7 +350,7 @@
 	{Opt_err, NULL}
 };
 
-static int parse_options(char *options, struct iso9660_options * popt)
+static int parse_options(char *options, struct iso9660_options *popt)
 {
 	char *p;
 	int option;
@@ -365,7 +359,8 @@
 	popt->rock = 'y';
 	popt->joliet = 'y';
 	popt->cruft = 'n';
-	popt->unhide = 'n';
+	popt->hide = 'n';
+	popt->showassoc = 'n';
 	popt->check = 'u';		/* unset */
 	popt->nocompress = 0;
 	popt->blocksize = 1024;
@@ -398,8 +393,12 @@
 		case Opt_nojoliet:
 			popt->joliet = 'n';
 			break;
+		case Opt_hide:
+			popt->hide = 'y';
+			break;
 		case Opt_unhide:
-			popt->unhide = 'y';
+		case Opt_showassoc:
+			popt->showassoc = 'y';
 			break;
 		case Opt_cruft:
 			popt->cruft = 'y';
@@ -493,7 +492,7 @@
  */
 #define WE_OBEY_THE_WRITTEN_STANDARDS 1
 
-static unsigned int isofs_get_last_session(struct super_block *sb,s32 session )
+static unsigned int isofs_get_last_session(struct super_block *sb, s32 session)
 {
 	struct cdrom_multisession ms_info;
 	unsigned int vol_desc_start;
@@ -518,7 +517,8 @@
 		printk(KERN_ERR "Invalid session number or type of track\n");
 	}
 	i = ioctl_by_bdev(bdev, CDROMMULTISESSION, (unsigned long) &ms_info);
-	if(session > 0) printk(KERN_ERR "Invalid session number\n");
+	if (session > 0)
+		printk(KERN_ERR "Invalid session number\n");
 #if 0
 	printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i);
 	if (i==0) {
@@ -557,13 +557,13 @@
 	struct iso9660_options		opt;
 	struct isofs_sb_info	      * sbi;
 
-	sbi = kmalloc(sizeof(struct isofs_sb_info), GFP_KERNEL);
+	sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
 	if (!sbi)
 		return -ENOMEM;
 	s->s_fs_info = sbi;
-	memset(sbi, 0, sizeof(struct isofs_sb_info));
+	memset(sbi, 0, sizeof(*sbi));
 
-	if (!parse_options((char *) data, &opt))
+	if (!parse_options((char *)data, &opt))
 		goto out_freesbi;
 
 	/*
@@ -792,7 +792,8 @@
 	sbi->s_rock = (opt.rock == 'y' ? 2 : 0);
 	sbi->s_rock_offset = -1; /* initial offset, will guess until SP is found*/
 	sbi->s_cruft = opt.cruft;
-	sbi->s_unhide = opt.unhide;
+	sbi->s_hide = opt.hide;
+	sbi->s_showassoc = opt.showassoc;
 	sbi->s_uid = opt.uid;
 	sbi->s_gid = opt.gid;
 	sbi->s_utf8 = opt.utf8;
@@ -1002,7 +1003,6 @@
 		rv++;
 	}
 
-
 abort:
 	unlock_kernel();
 	return rv;
@@ -1014,7 +1014,7 @@
 static int isofs_get_block(struct inode *inode, sector_t iblock,
 		    struct buffer_head *bh_result, int create)
 {
-	if ( create ) {
+	if (create) {
 		printk("isofs_get_block: Kernel tries to allocate a block\n");
 		return -EROFS;
 	}
@@ -1061,19 +1061,17 @@
 
 static inline void test_and_set_uid(uid_t *p, uid_t value)
 {
-	if(value) {
+	if (value)
 		*p = value;
-	}
 }
 
 static inline void test_and_set_gid(gid_t *p, gid_t value)
 {
-        if(value) {
+        if (value)
                 *p = value;
-        }
 }
 
-static int isofs_read_level3_size(struct inode * inode)
+static int isofs_read_level3_size(struct inode *inode)
 {
 	unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
 	int high_sierra = ISOFS_SB(inode->i_sb)->s_high_sierra;
@@ -1136,7 +1134,7 @@
 				bh = sb_bread(inode->i_sb, block);
 				if (!bh)
 					goto out_noread;
-				memcpy((void *) tmpde + slop, bh->b_data, offset);
+				memcpy((void *)tmpde+slop, bh->b_data, offset);
 			}
 			de = tmpde;
 		}
@@ -1150,12 +1148,11 @@
 		more_entries = de->flags[-high_sierra] & 0x80;
 
 		i++;
-		if(i > 100)
+		if (i > 100)
 			goto out_toomany;
-	} while(more_entries);
+	} while (more_entries);
 out:
-	if (tmpde)
-		kfree(tmpde);
+	kfree(tmpde);
 	if (bh)
 		brelse(bh);
 	return 0;
@@ -1179,7 +1176,7 @@
 	goto out;
 }
 
-static void isofs_read_inode(struct inode * inode)
+static void isofs_read_inode(struct inode *inode)
 {
 	struct super_block *sb = inode->i_sb;
 	struct isofs_sb_info *sbi = ISOFS_SB(sb);
@@ -1249,7 +1246,7 @@
 	ei->i_format_parm[2] = 0;
 
 	ei->i_section_size = isonum_733 (de->size);
-	if(de->flags[-high_sierra] & 0x80) {
+	if (de->flags[-high_sierra] & 0x80) {
 		if(isofs_read_level3_size(inode)) goto fail;
 	} else {
 		ei->i_next_section_block = 0;
@@ -1336,16 +1333,16 @@
 		/* XXX - parse_rock_ridge_inode() had already set i_rdev. */
 		init_special_inode(inode, inode->i_mode, inode->i_rdev);
 
- out:
+out:
 	if (tmpde)
 		kfree(tmpde);
 	if (bh)
 		brelse(bh);
 	return;
 
- out_badread:
+out_badread:
 	printk(KERN_WARNING "ISOFS: unable to read i-node block\n");
- fail:
+fail:
 	make_bad_inode(inode);
 	goto out;
 }
@@ -1394,11 +1391,8 @@
 
 	hashval = (block << sb->s_blocksize_bits) | offset;
 
-	inode = iget5_locked(sb,
-			     hashval,
-			     &isofs_iget5_test,
-			     &isofs_iget5_set,
-			     &data);
+	inode = iget5_locked(sb, hashval, &isofs_iget5_test,
+			     &isofs_iget5_set, &data);
 
 	if (inode && (inode->i_state & I_NEW)) {
 		sb->s_op->read_inode(inode);
@@ -1408,36 +1402,6 @@
 	return inode;
 }
 
-#ifdef LEAK_CHECK
-#undef malloc
-#undef free_s
-#undef sb_bread
-#undef brelse
-
-void * leak_check_malloc(unsigned int size){
-  void * tmp;
-  check_malloc++;
-  tmp = kmalloc(size, GFP_KERNEL);
-  return tmp;
-}
-
-void leak_check_free_s(void * obj, int size){
-  check_malloc--;
-  return kfree(obj);
-}
-
-struct buffer_head * leak_check_bread(struct super_block *sb, int block){
-  check_bread++;
-  return sb_bread(sb, block);
-}
-
-void leak_check_brelse(struct buffer_head * bh){
-  check_bread--;
-  return brelse(bh);
-}
-
-#endif
-
 static struct super_block *isofs_get_sb(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *data)
 {
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h
index 9ce7b51..38c7515 100644
--- a/fs/isofs/isofs.h
+++ b/fs/isofs/isofs.h
@@ -47,6 +47,8 @@
 	unsigned char s_nosuid;
 	unsigned char s_nodev;
 	unsigned char s_nocompress;
+	unsigned char s_hide;
+	unsigned char s_showassoc;
 
 	mode_t s_mode;
 	gid_t s_gid;
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c
index 690edf3..e37e82b 100644
--- a/fs/isofs/namei.c
+++ b/fs/isofs/namei.c
@@ -131,14 +131,16 @@
 		}
 
 		/*
-		 * Skip hidden or associated files unless unhide is set 
+		 * Skip hidden or associated files unless hide or showassoc,
+		 * respectively, is set
 		 */
 		match = 0;
 		if (dlen > 0 &&
-		    (!(de->flags[-sbi->s_high_sierra] & 5)
-		     || sbi->s_unhide == 'y'))
-		{
-			match = (isofs_cmp(dentry,dpnt,dlen) == 0);
+			(sbi->s_hide =='n' ||
+				(!(de->flags[-sbi->s_high_sierra] & 1))) &&
+			(sbi->s_showassoc =='y' ||
+				(!(de->flags[-sbi->s_high_sierra] & 4)))) {
+			match = (isofs_cmp(dentry, dpnt, dlen) == 0);
 		}
 		if (match) {
 			isofs_normalize_block_and_offset(de,
@@ -146,11 +148,11 @@
 							 &offset_saved);
                         *block_rv = block_saved;
                         *offset_rv = offset_saved;
-			if (bh) brelse(bh);
+			brelse(bh);
 			return 1;
 		}
 	}
-	if (bh) brelse(bh);
+	brelse(bh);
 	return 0;
 }
 
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c
index 089e79c..4326cb4 100644
--- a/fs/isofs/rock.c
+++ b/fs/isofs/rock.c
@@ -13,352 +13,542 @@
 #include "isofs.h"
 #include "rock.h"
 
-/* These functions are designed to read the system areas of a directory record
+/*
+ * These functions are designed to read the system areas of a directory record
  * and extract relevant information.  There are different functions provided
  * depending upon what information we need at the time.  One function fills
  * out an inode structure, a second one extracts a filename, a third one
  * returns a symbolic link name, and a fourth one returns the extent number
- * for the file. */
+ * for the file.
+ */
 
-#define SIG(A,B) ((A) | ((B) << 8)) /* isonum_721() */
+#define SIG(A,B) ((A) | ((B) << 8))	/* isonum_721() */
 
+struct rock_state {
+	void *buffer;
+	unsigned char *chr;
+	int len;
+	int cont_size;
+	int cont_extent;
+	int cont_offset;
+	struct inode *inode;
+};
 
-/* This is a way of ensuring that we have something in the system
-   use fields that is compatible with Rock Ridge */
-#define CHECK_SP(FAIL)	       			\
-      if(rr->u.SP.magic[0] != 0xbe) FAIL;	\
-      if(rr->u.SP.magic[1] != 0xef) FAIL;       \
-      ISOFS_SB(inode->i_sb)->s_rock_offset=rr->u.SP.skip;
-/* We define a series of macros because each function must do exactly the
-   same thing in certain places.  We use the macros to ensure that everything
-   is done correctly */
+/*
+ * This is a way of ensuring that we have something in the system
+ * use fields that is compatible with Rock Ridge.  Return zero on success.
+ */
 
-#define CONTINUE_DECLS \
-  int cont_extent = 0, cont_offset = 0, cont_size = 0;   \
-  void *buffer = NULL
-
-#define CHECK_CE	       			\
-      {cont_extent = isonum_733(rr->u.CE.extent); \
-      cont_offset = isonum_733(rr->u.CE.offset); \
-      cont_size = isonum_733(rr->u.CE.size);}
-
-#define SETUP_ROCK_RIDGE(DE,CHR,LEN)	      		      	\
-  {LEN= sizeof(struct iso_directory_record) + DE->name_len[0];	\
-  if(LEN & 1) LEN++;						\
-  CHR = ((unsigned char *) DE) + LEN;				\
-  LEN = *((unsigned char *) DE) - LEN;                          \
-  if (LEN<0) LEN=0;                                             \
-  if (ISOFS_SB(inode->i_sb)->s_rock_offset!=-1)                \
-  {                                                             \
-     LEN-=ISOFS_SB(inode->i_sb)->s_rock_offset;                \
-     CHR+=ISOFS_SB(inode->i_sb)->s_rock_offset;                \
-     if (LEN<0) LEN=0;                                          \
-  }                                                             \
-}                                     
-
-#define MAYBE_CONTINUE(LABEL,DEV) \
-  {if (buffer) { kfree(buffer); buffer = NULL; } \
-  if (cont_extent){ \
-    int block, offset, offset1; \
-    struct buffer_head * pbh; \
-    buffer = kmalloc(cont_size,GFP_KERNEL); \
-    if (!buffer) goto out; \
-    block = cont_extent; \
-    offset = cont_offset; \
-    offset1 = 0; \
-    pbh = sb_bread(DEV->i_sb, block); \
-    if(pbh){       \
-      if (offset > pbh->b_size || offset + cont_size > pbh->b_size){	\
-	brelse(pbh); \
-	goto out; \
-      } \
-      memcpy(buffer + offset1, pbh->b_data + offset, cont_size - offset1); \
-      brelse(pbh); \
-      chr = (unsigned char *) buffer; \
-      len = cont_size; \
-      cont_extent = 0; \
-      cont_size = 0; \
-      cont_offset = 0; \
-      goto LABEL; \
-    }    \
-    printk("Unable to read rock-ridge attributes\n");    \
-  }}
-
-/* return length of name field; 0: not found, -1: to be ignored */
-int get_rock_ridge_filename(struct iso_directory_record * de,
-			    char * retname, struct inode * inode)
+static int check_sp(struct rock_ridge *rr, struct inode *inode)
 {
-  int len;
-  unsigned char * chr;
-  CONTINUE_DECLS;
-  int retnamlen = 0, truncate=0;
- 
-  if (!ISOFS_SB(inode->i_sb)->s_rock) return 0;
-  *retname = 0;
+	if (rr->u.SP.magic[0] != 0xbe)
+		return -1;
+	if (rr->u.SP.magic[1] != 0xef)
+		return -1;
+	ISOFS_SB(inode->i_sb)->s_rock_offset = rr->u.SP.skip;
+	return 0;
+}
 
-  SETUP_ROCK_RIDGE(de, chr, len);
- repeat:
-  {
-    struct rock_ridge * rr;
-    int sig;
-    
-    while (len > 2){ /* There may be one byte for padding somewhere */
-      rr = (struct rock_ridge *) chr;
-      if (rr->len < 3) goto out; /* Something got screwed up here */
-      sig = isonum_721(chr);
-      chr += rr->len; 
-      len -= rr->len;
-      if (len < 0) goto out;	/* corrupted isofs */
+static void setup_rock_ridge(struct iso_directory_record *de,
+			struct inode *inode, struct rock_state *rs)
+{
+	rs->len = sizeof(struct iso_directory_record) + de->name_len[0];
+	if (rs->len & 1)
+		(rs->len)++;
+	rs->chr = (unsigned char *)de + rs->len;
+	rs->len = *((unsigned char *)de) - rs->len;
+	if (rs->len < 0)
+		rs->len = 0;
 
-      switch(sig){
-      case SIG('R','R'):
-	if((rr->u.RR.flags[0] & RR_NM) == 0) goto out;
-	break;
-      case SIG('S','P'):
-	CHECK_SP(goto out);
-	break;
-      case SIG('C','E'):
-	CHECK_CE;
-	break;
-      case SIG('N','M'):
-	if (truncate) break;
-	if (rr->len < 5) break;
-        /*
-	 * If the flags are 2 or 4, this indicates '.' or '..'.
-	 * We don't want to do anything with this, because it
-	 * screws up the code that calls us.  We don't really
-	 * care anyways, since we can just use the non-RR
-	 * name.
-	 */
-	if (rr->u.NM.flags & 6) {
-	  break;
+	if (ISOFS_SB(inode->i_sb)->s_rock_offset != -1) {
+		rs->len -= ISOFS_SB(inode->i_sb)->s_rock_offset;
+		rs->chr += ISOFS_SB(inode->i_sb)->s_rock_offset;
+		if (rs->len < 0)
+			rs->len = 0;
+	}
+}
+
+static void init_rock_state(struct rock_state *rs, struct inode *inode)
+{
+	memset(rs, 0, sizeof(*rs));
+	rs->inode = inode;
+}
+
+/*
+ * Returns 0 if the caller should continue scanning, 1 if the scan must end
+ * and -ve on error.
+ */
+static int rock_continue(struct rock_state *rs)
+{
+	int ret = 1;
+	int blocksize = 1 << rs->inode->i_blkbits;
+	const int min_de_size = offsetof(struct rock_ridge, u);
+
+	kfree(rs->buffer);
+	rs->buffer = NULL;
+
+	if ((unsigned)rs->cont_offset > blocksize - min_de_size ||
+	    (unsigned)rs->cont_size > blocksize ||
+	    (unsigned)(rs->cont_offset + rs->cont_size) > blocksize) {
+		printk(KERN_NOTICE "rock: corrupted directory entry. "
+			"extent=%d, offset=%d, size=%d\n",
+			rs->cont_extent, rs->cont_offset, rs->cont_size);
+		ret = -EIO;
+		goto out;
 	}
 
-	if (rr->u.NM.flags & ~1) {
-	  printk("Unsupported NM flag settings (%d)\n",rr->u.NM.flags);
-	  break;
+	if (rs->cont_extent) {
+		struct buffer_head *bh;
+
+		rs->buffer = kmalloc(rs->cont_size, GFP_KERNEL);
+		if (!rs->buffer) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		ret = -EIO;
+		bh = sb_bread(rs->inode->i_sb, rs->cont_extent);
+		if (bh) {
+			memcpy(rs->buffer, bh->b_data + rs->cont_offset,
+					rs->cont_size);
+			put_bh(bh);
+			rs->chr = rs->buffer;
+			rs->len = rs->cont_size;
+			rs->cont_extent = 0;
+			rs->cont_size = 0;
+			rs->cont_offset = 0;
+			return 0;
+		}
+		printk("Unable to read rock-ridge attributes\n");
 	}
-	if((strlen(retname) + rr->len - 5) >= 254) {
-	  truncate = 1;
-	  break;
+out:
+	kfree(rs->buffer);
+	rs->buffer = NULL;
+	return ret;
+}
+
+/*
+ * We think there's a record of type `sig' at rs->chr.  Parse the signature
+ * and make sure that there's really room for a record of that type.
+ */
+static int rock_check_overflow(struct rock_state *rs, int sig)
+{
+	int len;
+
+	switch (sig) {
+	case SIG('S', 'P'):
+		len = sizeof(struct SU_SP_s);
+		break;
+	case SIG('C', 'E'):
+		len = sizeof(struct SU_CE_s);
+		break;
+	case SIG('E', 'R'):
+		len = sizeof(struct SU_ER_s);
+		break;
+	case SIG('R', 'R'):
+		len = sizeof(struct RR_RR_s);
+		break;
+	case SIG('P', 'X'):
+		len = sizeof(struct RR_PX_s);
+		break;
+	case SIG('P', 'N'):
+		len = sizeof(struct RR_PN_s);
+		break;
+	case SIG('S', 'L'):
+		len = sizeof(struct RR_SL_s);
+		break;
+	case SIG('N', 'M'):
+		len = sizeof(struct RR_NM_s);
+		break;
+	case SIG('C', 'L'):
+		len = sizeof(struct RR_CL_s);
+		break;
+	case SIG('P', 'L'):
+		len = sizeof(struct RR_PL_s);
+		break;
+	case SIG('T', 'F'):
+		len = sizeof(struct RR_TF_s);
+		break;
+	case SIG('Z', 'F'):
+		len = sizeof(struct RR_ZF_s);
+		break;
+	default:
+		len = 0;
+		break;
 	}
-	strncat(retname, rr->u.NM.name, rr->len - 5);
-	retnamlen += rr->len - 5;
-	break;
-      case SIG('R','E'):
-	if (buffer) kfree(buffer);
-	return -1;
-      default:
-	break;
-      }
-    }
-  }
-  MAYBE_CONTINUE(repeat,inode);
-  if (buffer) kfree(buffer);
-  return retnamlen; /* If 0, this file did not have a NM field */
- out:
-  if(buffer) kfree(buffer);
-  return 0;
+	len += offsetof(struct rock_ridge, u);
+	if (len > rs->len) {
+		printk(KERN_NOTICE "rock: directory entry would overflow "
+				"storage\n");
+		printk(KERN_NOTICE "rock: sig=0x%02x, size=%d, remaining=%d\n",
+				sig, len, rs->len);
+		return -EIO;
+	}
+	return 0;
+}
+
+/*
+ * return length of name field; 0: not found, -1: to be ignored
+ */
+int get_rock_ridge_filename(struct iso_directory_record *de,
+			    char *retname, struct inode *inode)
+{
+	struct rock_state rs;
+	struct rock_ridge *rr;
+	int sig;
+	int retnamlen = 0;
+	int truncate = 0;
+	int ret = 0;
+
+	if (!ISOFS_SB(inode->i_sb)->s_rock)
+		return 0;
+	*retname = 0;
+
+	init_rock_state(&rs, inode);
+	setup_rock_ridge(de, inode, &rs);
+repeat:
+
+	while (rs.len > 2) { /* There may be one byte for padding somewhere */
+		rr = (struct rock_ridge *)rs.chr;
+		if (rr->len < 3)
+			goto out;	/* Something got screwed up here */
+		sig = isonum_721(rs.chr);
+		if (rock_check_overflow(&rs, sig))
+			goto eio;
+		rs.chr += rr->len;
+		rs.len -= rr->len;
+		if (rs.len < 0)
+			goto eio;	/* corrupted isofs */
+
+		switch (sig) {
+		case SIG('R', 'R'):
+			if ((rr->u.RR.flags[0] & RR_NM) == 0)
+				goto out;
+			break;
+		case SIG('S', 'P'):
+			if (check_sp(rr, inode))
+				goto out;
+			break;
+		case SIG('C', 'E'):
+			rs.cont_extent = isonum_733(rr->u.CE.extent);
+			rs.cont_offset = isonum_733(rr->u.CE.offset);
+			rs.cont_size = isonum_733(rr->u.CE.size);
+			break;
+		case SIG('N', 'M'):
+			if (truncate)
+				break;
+			if (rr->len < 5)
+				break;
+			/*
+			 * If the flags are 2 or 4, this indicates '.' or '..'.
+			 * We don't want to do anything with this, because it
+			 * screws up the code that calls us.  We don't really
+			 * care anyways, since we can just use the non-RR
+			 * name.
+			 */
+			if (rr->u.NM.flags & 6)
+				break;
+
+			if (rr->u.NM.flags & ~1) {
+				printk("Unsupported NM flag settings (%d)\n",
+					rr->u.NM.flags);
+				break;
+			}
+			if ((strlen(retname) + rr->len - 5) >= 254) {
+				truncate = 1;
+				break;
+			}
+			strncat(retname, rr->u.NM.name, rr->len - 5);
+			retnamlen += rr->len - 5;
+			break;
+		case SIG('R', 'E'):
+			kfree(rs.buffer);
+			return -1;
+		default:
+			break;
+		}
+	}
+	ret = rock_continue(&rs);
+	if (ret == 0)
+		goto repeat;
+	if (ret == 1)
+		return retnamlen; /* If 0, this file did not have a NM field */
+out:
+	kfree(rs.buffer);
+	return ret;
+eio:
+	ret = -EIO;
+	goto out;
 }
 
 static int
 parse_rock_ridge_inode_internal(struct iso_directory_record *de,
 				struct inode *inode, int regard_xa)
 {
-  int len;
-  unsigned char * chr;
-  int symlink_len = 0;
-  CONTINUE_DECLS;
+	int symlink_len = 0;
+	int cnt, sig;
+	struct inode *reloc;
+	struct rock_ridge *rr;
+	int rootflag;
+	struct rock_state rs;
+	int ret = 0;
 
-  if (!ISOFS_SB(inode->i_sb)->s_rock) return 0;
+	if (!ISOFS_SB(inode->i_sb)->s_rock)
+		return 0;
 
-  SETUP_ROCK_RIDGE(de, chr, len);
-  if (regard_xa)
-   {
-     chr+=14;
-     len-=14;
-     if (len<0) len=0;
-   }
-   
- repeat:
-  {
-    int cnt, sig;
-    struct inode * reloc;
-    struct rock_ridge * rr;
-    int rootflag;
-    
-    while (len > 2){ /* There may be one byte for padding somewhere */
-      rr = (struct rock_ridge *) chr;
-      if (rr->len < 3) goto out; /* Something got screwed up here */
-      sig = isonum_721(chr);
-      chr += rr->len; 
-      len -= rr->len;
-      if (len < 0) goto out;	/* corrupted isofs */
-      
-      switch(sig){
+	init_rock_state(&rs, inode);
+	setup_rock_ridge(de, inode, &rs);
+	if (regard_xa) {
+		rs.chr += 14;
+		rs.len -= 14;
+		if (rs.len < 0)
+			rs.len = 0;
+	}
+
+repeat:
+	while (rs.len > 2) { /* There may be one byte for padding somewhere */
+		rr = (struct rock_ridge *)rs.chr;
+		if (rr->len < 3)
+			goto out;	/* Something got screwed up here */
+		sig = isonum_721(rs.chr);
+		if (rock_check_overflow(&rs, sig))
+			goto eio;
+		rs.chr += rr->len;
+		rs.len -= rr->len;
+		if (rs.len < 0)
+			goto eio;	/* corrupted isofs */
+
+		switch (sig) {
 #ifndef CONFIG_ZISOFS		/* No flag for SF or ZF */
-      case SIG('R','R'):
-	if((rr->u.RR.flags[0] & 
- 	    (RR_PX | RR_TF | RR_SL | RR_CL)) == 0) goto out;
-	break;
+		case SIG('R', 'R'):
+			if ((rr->u.RR.flags[0] &
+			     (RR_PX | RR_TF | RR_SL | RR_CL)) == 0)
+				goto out;
+			break;
 #endif
-      case SIG('S','P'):
-	CHECK_SP(goto out);
-	break;
-      case SIG('C','E'):
-	CHECK_CE;
-	break;
-      case SIG('E','R'):
-	ISOFS_SB(inode->i_sb)->s_rock = 1;
-	printk(KERN_DEBUG "ISO 9660 Extensions: ");
-	{ int p;
-	  for(p=0;p<rr->u.ER.len_id;p++) printk("%c",rr->u.ER.data[p]);
-	}
-	  printk("\n");
-	break;
-      case SIG('P','X'):
-	inode->i_mode  = isonum_733(rr->u.PX.mode);
-	inode->i_nlink = isonum_733(rr->u.PX.n_links);
-	inode->i_uid   = isonum_733(rr->u.PX.uid);
-	inode->i_gid   = isonum_733(rr->u.PX.gid);
-	break;
-      case SIG('P','N'):
-	{ int high, low;
-	  high = isonum_733(rr->u.PN.dev_high);
-	  low = isonum_733(rr->u.PN.dev_low);
-	  /*
-	   * The Rock Ridge standard specifies that if sizeof(dev_t) <= 4,
-	   * then the high field is unused, and the device number is completely
-	   * stored in the low field.  Some writers may ignore this subtlety,
-	   * and as a result we test to see if the entire device number is
-	   * stored in the low field, and use that.
-	   */
-	  if((low & ~0xff) && high == 0) {
-	    inode->i_rdev = MKDEV(low >> 8, low & 0xff);
-	  } else {
-	    inode->i_rdev = MKDEV(high, low);
-	  }
-	}
-	break;
-      case SIG('T','F'):
-	/* Some RRIP writers incorrectly place ctime in the TF_CREATE field.
-	   Try to handle this correctly for either case. */
-	cnt = 0; /* Rock ridge never appears on a High Sierra disk */
-	if(rr->u.TF.flags & TF_CREATE) { 
-	  inode->i_ctime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
-	  inode->i_ctime.tv_nsec = 0;
-	}
-	if(rr->u.TF.flags & TF_MODIFY) {
-	  inode->i_mtime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
-	  inode->i_mtime.tv_nsec = 0;
-	}
-	if(rr->u.TF.flags & TF_ACCESS) {
-	  inode->i_atime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
-	  inode->i_atime.tv_nsec = 0;
-	}
-	if(rr->u.TF.flags & TF_ATTRIBUTES) { 
-	  inode->i_ctime.tv_sec = iso_date(rr->u.TF.times[cnt++].time, 0);
-	  inode->i_ctime.tv_nsec = 0;
-	} 
-	break;
-      case SIG('S','L'):
-	{int slen;
-	 struct SL_component * slp;
-	 struct SL_component * oldslp;
-	 slen = rr->len - 5;
-	 slp = &rr->u.SL.link;
-	 inode->i_size = symlink_len;
-	 while (slen > 1){
-	   rootflag = 0;
-	   switch(slp->flags &~1){
-	   case 0:
-	     inode->i_size += slp->len;
-	     break;
-	   case 2:
-	     inode->i_size += 1;
-	     break;
-	   case 4:
-	     inode->i_size += 2;
-	     break;
-	   case 8:
-	     rootflag = 1;
-	     inode->i_size += 1;
-	     break;
-	   default:
-	     printk("Symlink component flag not implemented\n");
-	   }
-	   slen -= slp->len + 2;
-	   oldslp = slp;
-	   slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
+		case SIG('S', 'P'):
+			if (check_sp(rr, inode))
+				goto out;
+			break;
+		case SIG('C', 'E'):
+			rs.cont_extent = isonum_733(rr->u.CE.extent);
+			rs.cont_offset = isonum_733(rr->u.CE.offset);
+			rs.cont_size = isonum_733(rr->u.CE.size);
+			break;
+		case SIG('E', 'R'):
+			ISOFS_SB(inode->i_sb)->s_rock = 1;
+			printk(KERN_DEBUG "ISO 9660 Extensions: ");
+			{
+				int p;
+				for (p = 0; p < rr->u.ER.len_id; p++)
+					printk("%c", rr->u.ER.data[p]);
+			}
+			printk("\n");
+			break;
+		case SIG('P', 'X'):
+			inode->i_mode = isonum_733(rr->u.PX.mode);
+			inode->i_nlink = isonum_733(rr->u.PX.n_links);
+			inode->i_uid = isonum_733(rr->u.PX.uid);
+			inode->i_gid = isonum_733(rr->u.PX.gid);
+			break;
+		case SIG('P', 'N'):
+			{
+				int high, low;
+				high = isonum_733(rr->u.PN.dev_high);
+				low = isonum_733(rr->u.PN.dev_low);
+				/*
+				 * The Rock Ridge standard specifies that if
+				 * sizeof(dev_t) <= 4, then the high field is
+				 * unused, and the device number is completely
+				 * stored in the low field.  Some writers may
+				 * ignore this subtlety,
+				 * and as a result we test to see if the entire
+				 * device number is
+				 * stored in the low field, and use that.
+				 */
+				if ((low & ~0xff) && high == 0) {
+					inode->i_rdev =
+					    MKDEV(low >> 8, low & 0xff);
+				} else {
+					inode->i_rdev =
+					    MKDEV(high, low);
+				}
+			}
+			break;
+		case SIG('T', 'F'):
+			/*
+			 * Some RRIP writers incorrectly place ctime in the
+			 * TF_CREATE field. Try to handle this correctly for
+			 * either case.
+			 */
+			/* Rock ridge never appears on a High Sierra disk */
+			cnt = 0;
+			if (rr->u.TF.flags & TF_CREATE) {
+				inode->i_ctime.tv_sec =
+				    iso_date(rr->u.TF.times[cnt++].time,
+					     0);
+				inode->i_ctime.tv_nsec = 0;
+			}
+			if (rr->u.TF.flags & TF_MODIFY) {
+				inode->i_mtime.tv_sec =
+				    iso_date(rr->u.TF.times[cnt++].time,
+					     0);
+				inode->i_mtime.tv_nsec = 0;
+			}
+			if (rr->u.TF.flags & TF_ACCESS) {
+				inode->i_atime.tv_sec =
+				    iso_date(rr->u.TF.times[cnt++].time,
+					     0);
+				inode->i_atime.tv_nsec = 0;
+			}
+			if (rr->u.TF.flags & TF_ATTRIBUTES) {
+				inode->i_ctime.tv_sec =
+				    iso_date(rr->u.TF.times[cnt++].time,
+					     0);
+				inode->i_ctime.tv_nsec = 0;
+			}
+			break;
+		case SIG('S', 'L'):
+			{
+				int slen;
+				struct SL_component *slp;
+				struct SL_component *oldslp;
+				slen = rr->len - 5;
+				slp = &rr->u.SL.link;
+				inode->i_size = symlink_len;
+				while (slen > 1) {
+					rootflag = 0;
+					switch (slp->flags & ~1) {
+					case 0:
+						inode->i_size +=
+						    slp->len;
+						break;
+					case 2:
+						inode->i_size += 1;
+						break;
+					case 4:
+						inode->i_size += 2;
+						break;
+					case 8:
+						rootflag = 1;
+						inode->i_size += 1;
+						break;
+					default:
+						printk("Symlink component flag "
+							"not implemented\n");
+					}
+					slen -= slp->len + 2;
+					oldslp = slp;
+					slp = (struct SL_component *)
+						(((char *)slp) + slp->len + 2);
 
-	   if(slen < 2) {
-	     if(    ((rr->u.SL.flags & 1) != 0) 
-		    && ((oldslp->flags & 1) == 0) ) inode->i_size += 1;
-	     break;
-	   }
+					if (slen < 2) {
+						if (((rr->u.SL.
+						      flags & 1) != 0)
+						    &&
+						    ((oldslp->
+						      flags & 1) == 0))
+							inode->i_size +=
+							    1;
+						break;
+					}
 
-	   /*
-	    * If this component record isn't continued, then append a '/'.
-	    */
-	   if (!rootflag && (oldslp->flags & 1) == 0)
-		   inode->i_size += 1;
-	 }
-	}
-	symlink_len = inode->i_size;
-	break;
-      case SIG('R','E'):
-	printk(KERN_WARNING "Attempt to read inode for relocated directory\n");
-	goto out;
-      case SIG('C','L'):
-	ISOFS_I(inode)->i_first_extent = isonum_733(rr->u.CL.location);
-	reloc = isofs_iget(inode->i_sb, ISOFS_I(inode)->i_first_extent, 0);
-	if (!reloc)
-		goto out;
-	inode->i_mode = reloc->i_mode;
-	inode->i_nlink = reloc->i_nlink;
-	inode->i_uid = reloc->i_uid;
-	inode->i_gid = reloc->i_gid;
-	inode->i_rdev = reloc->i_rdev;
-	inode->i_size = reloc->i_size;
-	inode->i_blocks = reloc->i_blocks;
-	inode->i_atime = reloc->i_atime;
-	inode->i_ctime = reloc->i_ctime;
-	inode->i_mtime = reloc->i_mtime;
-	iput(reloc);
-	break;
+					/*
+					 * If this component record isn't
+					 * continued, then append a '/'.
+					 */
+					if (!rootflag
+					    && (oldslp->flags & 1) == 0)
+						inode->i_size += 1;
+				}
+			}
+			symlink_len = inode->i_size;
+			break;
+		case SIG('R', 'E'):
+			printk(KERN_WARNING "Attempt to read inode for "
+					"relocated directory\n");
+			goto out;
+		case SIG('C', 'L'):
+			ISOFS_I(inode)->i_first_extent =
+			    isonum_733(rr->u.CL.location);
+			reloc =
+			    isofs_iget(inode->i_sb,
+				       ISOFS_I(inode)->i_first_extent,
+				       0);
+			if (!reloc)
+				goto out;
+			inode->i_mode = reloc->i_mode;
+			inode->i_nlink = reloc->i_nlink;
+			inode->i_uid = reloc->i_uid;
+			inode->i_gid = reloc->i_gid;
+			inode->i_rdev = reloc->i_rdev;
+			inode->i_size = reloc->i_size;
+			inode->i_blocks = reloc->i_blocks;
+			inode->i_atime = reloc->i_atime;
+			inode->i_ctime = reloc->i_ctime;
+			inode->i_mtime = reloc->i_mtime;
+			iput(reloc);
+			break;
 #ifdef CONFIG_ZISOFS
-      case SIG('Z','F'):
-	      if ( !ISOFS_SB(inode->i_sb)->s_nocompress ) {
-		      int algo;
-		      algo = isonum_721(rr->u.ZF.algorithm);
-		      if ( algo == SIG('p','z') ) {
-			      int block_shift = isonum_711(&rr->u.ZF.parms[1]);
-			      if ( block_shift < PAGE_CACHE_SHIFT || block_shift > 17 ) {
-				      printk(KERN_WARNING "isofs: Can't handle ZF block size of 2^%d\n", block_shift);
-			      } else {
-				/* Note: we don't change i_blocks here */
-				      ISOFS_I(inode)->i_file_format = isofs_file_compressed;
-				/* Parameters to compression algorithm (header size, block size) */
-				      ISOFS_I(inode)->i_format_parm[0] = isonum_711(&rr->u.ZF.parms[0]);
-				      ISOFS_I(inode)->i_format_parm[1] = isonum_711(&rr->u.ZF.parms[1]);
-				      inode->i_size = isonum_733(rr->u.ZF.real_size);
-			      }
-		      } else {
-			      printk(KERN_WARNING "isofs: Unknown ZF compression algorithm: %c%c\n",
-				     rr->u.ZF.algorithm[0], rr->u.ZF.algorithm[1]);
-		      }
-	      }
-	      break;
+		case SIG('Z', 'F'): {
+			int algo;
+
+			if (ISOFS_SB(inode->i_sb)->s_nocompress)
+				break;
+			algo = isonum_721(rr->u.ZF.algorithm);
+			if (algo == SIG('p', 'z')) {
+				int block_shift =
+					isonum_711(&rr->u.ZF.parms[1]);
+				if (block_shift < PAGE_CACHE_SHIFT
+						|| block_shift > 17) {
+					printk(KERN_WARNING "isofs: "
+						"Can't handle ZF block "
+						"size of 2^%d\n",
+						block_shift);
+				} else {
+					/*
+					 * Note: we don't change
+					 * i_blocks here
+					 */
+					ISOFS_I(inode)->i_file_format =
+						isofs_file_compressed;
+					/*
+					 * Parameters to compression
+					 * algorithm (header size,
+					 * block size)
+					 */
+					ISOFS_I(inode)->i_format_parm[0] =
+						isonum_711(&rr->u.ZF.parms[0]);
+					ISOFS_I(inode)->i_format_parm[1] =
+						isonum_711(&rr->u.ZF.parms[1]);
+					inode->i_size =
+					    isonum_733(rr->u.ZF.
+						       real_size);
+				}
+			} else {
+				printk(KERN_WARNING
+				       "isofs: Unknown ZF compression "
+						"algorithm: %c%c\n",
+				       rr->u.ZF.algorithm[0],
+				       rr->u.ZF.algorithm[1]);
+			}
+			break;
+		}
 #endif
-      default:
-	break;
-      }
-    }
-  }
-  MAYBE_CONTINUE(repeat,inode);
- out:
-  if(buffer) kfree(buffer);
-  return 0;
+		default:
+			break;
+		}
+	}
+	ret = rock_continue(&rs);
+	if (ret == 0)
+		goto repeat;
+	if (ret == 1)
+		ret = 0;
+out:
+	kfree(rs.buffer);
+	return ret;
+eio:
+	ret = -EIO;
+	goto out;
 }
 
 static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit)
@@ -376,32 +566,32 @@
 			if (slp->len > plimit - rpnt)
 				return NULL;
 			memcpy(rpnt, slp->text, slp->len);
-			rpnt+=slp->len;
+			rpnt += slp->len;
 			break;
 		case 2:
 			if (rpnt >= plimit)
 				return NULL;
-			*rpnt++='.';
+			*rpnt++ = '.';
 			break;
 		case 4:
 			if (2 > plimit - rpnt)
 				return NULL;
-			*rpnt++='.';
-			*rpnt++='.';
+			*rpnt++ = '.';
+			*rpnt++ = '.';
 			break;
 		case 8:
 			if (rpnt >= plimit)
 				return NULL;
 			rootflag = 1;
-			*rpnt++='/';
+			*rpnt++ = '/';
 			break;
 		default:
 			printk("Symlink component flag not implemented (%d)\n",
-			     slp->flags);
+			       slp->flags);
 		}
 		slen -= slp->len + 2;
 		oldslp = slp;
-		slp = (struct SL_component *) ((char *) slp + slp->len + 2);
+		slp = (struct SL_component *)((char *)slp + slp->len + 2);
 
 		if (slen < 2) {
 			/*
@@ -412,7 +602,7 @@
 			    !(oldslp->flags & 1)) {
 				if (rpnt >= plimit)
 					return NULL;
-				*rpnt++='/';
+				*rpnt++ = '/';
 			}
 			break;
 		}
@@ -423,59 +613,61 @@
 		if (!rootflag && !(oldslp->flags & 1)) {
 			if (rpnt >= plimit)
 				return NULL;
-			*rpnt++='/';
+			*rpnt++ = '/';
 		}
 	}
 	return rpnt;
 }
 
-int parse_rock_ridge_inode(struct iso_directory_record * de,
-			   struct inode * inode)
+int parse_rock_ridge_inode(struct iso_directory_record *de, struct inode *inode)
 {
-   int result=parse_rock_ridge_inode_internal(de,inode,0);
-   /* if rockridge flag was reset and we didn't look for attributes
-    * behind eventual XA attributes, have a look there */
-   if ((ISOFS_SB(inode->i_sb)->s_rock_offset==-1)
-       &&(ISOFS_SB(inode->i_sb)->s_rock==2))
-     {
-	result=parse_rock_ridge_inode_internal(de,inode,14);
-     }
-   return result;
+	int result = parse_rock_ridge_inode_internal(de, inode, 0);
+
+	/*
+	 * if rockridge flag was reset and we didn't look for attributes
+	 * behind eventual XA attributes, have a look there
+	 */
+	if ((ISOFS_SB(inode->i_sb)->s_rock_offset == -1)
+	    && (ISOFS_SB(inode->i_sb)->s_rock == 2)) {
+		result = parse_rock_ridge_inode_internal(de, inode, 14);
+	}
+	return result;
 }
 
-/* readpage() for symlinks: reads symlink contents into the page and either
-   makes it uptodate and returns 0 or returns error (-EIO) */
-
+/*
+ * readpage() for symlinks: reads symlink contents into the page and either
+ * makes it uptodate and returns 0 or returns error (-EIO)
+ */
 static int rock_ridge_symlink_readpage(struct file *file, struct page *page)
 {
 	struct inode *inode = page->mapping->host;
-        struct iso_inode_info *ei = ISOFS_I(inode);
+	struct iso_inode_info *ei = ISOFS_I(inode);
 	char *link = kmap(page);
 	unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
 	struct buffer_head *bh;
 	char *rpnt = link;
 	unsigned char *pnt;
-	struct iso_directory_record *raw_inode;
-	CONTINUE_DECLS;
+	struct iso_directory_record *raw_de;
 	unsigned long block, offset;
 	int sig;
-	int len;
-	unsigned char *chr;
 	struct rock_ridge *rr;
+	struct rock_state rs;
+	int ret;
 
 	if (!ISOFS_SB(inode->i_sb)->s_rock)
 		goto error;
 
+	init_rock_state(&rs, inode);
 	block = ei->i_iget5_block;
 	lock_kernel();
 	bh = sb_bread(inode->i_sb, block);
 	if (!bh)
 		goto out_noread;
 
-        offset = ei->i_iget5_offset;
-	pnt = (unsigned char *) bh->b_data + offset;
+	offset = ei->i_iget5_offset;
+	pnt = (unsigned char *)bh->b_data + offset;
 
-	raw_inode = (struct iso_directory_record *) pnt;
+	raw_de = (struct iso_directory_record *)pnt;
 
 	/*
 	 * If we go past the end of the buffer, there is some sort of error.
@@ -483,20 +675,24 @@
 	if (offset + *pnt > bufsize)
 		goto out_bad_span;
 
-	/* Now test for possible Rock Ridge extensions which will override
-	   some of these numbers in the inode structure. */
+	/*
+	 * Now test for possible Rock Ridge extensions which will override
+	 * some of these numbers in the inode structure.
+	 */
 
-	SETUP_ROCK_RIDGE(raw_inode, chr, len);
+	setup_rock_ridge(raw_de, inode, &rs);
 
-      repeat:
-	while (len > 2) { /* There may be one byte for padding somewhere */
-		rr = (struct rock_ridge *) chr;
+repeat:
+	while (rs.len > 2) { /* There may be one byte for padding somewhere */
+		rr = (struct rock_ridge *)rs.chr;
 		if (rr->len < 3)
 			goto out;	/* Something got screwed up here */
-		sig = isonum_721(chr);
-		chr += rr->len;
-		len -= rr->len;
-		if (len < 0)
+		sig = isonum_721(rs.chr);
+		if (rock_check_overflow(&rs, sig))
+			goto out;
+		rs.chr += rr->len;
+		rs.len -= rr->len;
+		if (rs.len < 0)
 			goto out;	/* corrupted isofs */
 
 		switch (sig) {
@@ -505,7 +701,8 @@
 				goto out;
 			break;
 		case SIG('S', 'P'):
-			CHECK_SP(goto out);
+			if (check_sp(rr, inode))
+				goto out;
 			break;
 		case SIG('S', 'L'):
 			rpnt = get_symlink_chunk(rpnt, rr,
@@ -515,14 +712,18 @@
 			break;
 		case SIG('C', 'E'):
 			/* This tells is if there is a continuation record */
-			CHECK_CE;
+			rs.cont_extent = isonum_733(rr->u.CE.extent);
+			rs.cont_offset = isonum_733(rr->u.CE.offset);
+			rs.cont_size = isonum_733(rr->u.CE.size);
 		default:
 			break;
 		}
 	}
-	MAYBE_CONTINUE(repeat, inode);
-	if (buffer)
-		kfree(buffer);
+	ret = rock_continue(&rs);
+	if (ret == 0)
+		goto repeat;
+	if (ret < 0)
+		goto fail;
 
 	if (rpnt == link)
 		goto fail;
@@ -535,19 +736,18 @@
 	return 0;
 
 	/* error exit from macro */
-      out:
-	if (buffer)
-		kfree(buffer);
+out:
+	kfree(rs.buffer);
 	goto fail;
-      out_noread:
+out_noread:
 	printk("unable to read i-node block");
 	goto fail;
-      out_bad_span:
+out_bad_span:
 	printk("symlink spans iso9660 blocks\n");
-      fail:
+fail:
 	brelse(bh);
 	unlock_kernel();
-      error:
+error:
 	SetPageError(page);
 	kunmap(page);
 	unlock_page(page);
@@ -555,5 +755,5 @@
 }
 
 struct address_space_operations isofs_symlink_aops = {
-	.readpage	= rock_ridge_symlink_readpage
+	.readpage = rock_ridge_symlink_readpage
 };
diff --git a/fs/isofs/rock.h b/fs/isofs/rock.h
index deaf5c8..ed09e2b 100644
--- a/fs/isofs/rock.h
+++ b/fs/isofs/rock.h
@@ -1,85 +1,88 @@
-/* These structs are used by the system-use-sharing protocol, in which the
-   Rock Ridge extensions are embedded.  It is quite possible that other
-   extensions are present on the disk, and this is fine as long as they
-   all use SUSP */
+/*
+ * These structs are used by the system-use-sharing protocol, in which the
+ * Rock Ridge extensions are embedded.  It is quite possible that other
+ * extensions are present on the disk, and this is fine as long as they
+ * all use SUSP
+ */
 
-struct SU_SP{
-  unsigned char magic[2];
-  unsigned char skip;
-} __attribute__((packed));
+struct SU_SP_s {
+	unsigned char magic[2];
+	unsigned char skip;
+} __attribute__ ((packed));
 
-struct SU_CE{
-  char extent[8];
-  char offset[8];
-  char size[8];
+struct SU_CE_s {
+	char extent[8];
+	char offset[8];
+	char size[8];
 };
 
-struct SU_ER{
-  unsigned char len_id;
-  unsigned char len_des;
-  unsigned char len_src;
-  unsigned char ext_ver;
-  char data[0];
-} __attribute__((packed));
+struct SU_ER_s {
+	unsigned char len_id;
+	unsigned char len_des;
+	unsigned char len_src;
+	unsigned char ext_ver;
+	char data[0];
+} __attribute__ ((packed));
 
-struct RR_RR{
-  char flags[1];
-} __attribute__((packed));
+struct RR_RR_s {
+	char flags[1];
+} __attribute__ ((packed));
 
-struct RR_PX{
-  char mode[8];
-  char n_links[8];
-  char uid[8];
-  char gid[8];
+struct RR_PX_s {
+	char mode[8];
+	char n_links[8];
+	char uid[8];
+	char gid[8];
 };
 
-struct RR_PN{
-  char dev_high[8];
-  char dev_low[8];
+struct RR_PN_s {
+	char dev_high[8];
+	char dev_low[8];
 };
 
+struct SL_component {
+	unsigned char flags;
+	unsigned char len;
+	char text[0];
+} __attribute__ ((packed));
 
-struct SL_component{
-  unsigned char flags;
-  unsigned char len;
-  char text[0];
-} __attribute__((packed));
+struct RR_SL_s {
+	unsigned char flags;
+	struct SL_component link;
+} __attribute__ ((packed));
 
-struct RR_SL{
-  unsigned char flags;
-  struct SL_component link;
-} __attribute__((packed));
+struct RR_NM_s {
+	unsigned char flags;
+	char name[0];
+} __attribute__ ((packed));
 
-struct RR_NM{
-  unsigned char flags;
-  char name[0];
-} __attribute__((packed));
-
-struct RR_CL{
-  char location[8];
+struct RR_CL_s {
+	char location[8];
 };
 
-struct RR_PL{
-  char location[8];
+struct RR_PL_s {
+	char location[8];
 };
 
-struct stamp{
-  char time[7];
-} __attribute__((packed));
+struct stamp {
+	char time[7];
+} __attribute__ ((packed));
 
-struct RR_TF{
-  char flags;
-  struct stamp times[0];  /* Variable number of these beasts */
-} __attribute__((packed));
+struct RR_TF_s {
+	char flags;
+	struct stamp times[0];	/* Variable number of these beasts */
+} __attribute__ ((packed));
 
 /* Linux-specific extension for transparent decompression */
-struct RR_ZF{
-  char algorithm[2];
-  char parms[2];
-  char real_size[8];
+struct RR_ZF_s {
+	char algorithm[2];
+	char parms[2];
+	char real_size[8];
 };
 
-/* These are the bits and their meanings for flags in the TF structure. */
+/*
+ * These are the bits and their meanings for flags in the TF structure.
+ */
 #define TF_CREATE 1
 #define TF_MODIFY 2
 #define TF_ACCESS 4
@@ -89,31 +92,31 @@
 #define TF_EFFECTIVE 64
 #define TF_LONG_FORM 128
 
-struct rock_ridge{
-  char signature[2];
-  unsigned char len;
-  unsigned char version;
-  union{
-    struct SU_SP SP;
-    struct SU_CE CE;
-    struct SU_ER ER;
-    struct RR_RR RR;
-    struct RR_PX PX;
-    struct RR_PN PN;
-    struct RR_SL SL;
-    struct RR_NM NM;
-    struct RR_CL CL;
-    struct RR_PL PL;
-    struct RR_TF TF;
-    struct RR_ZF ZF;
-  } u;
+struct rock_ridge {
+	char signature[2];
+	unsigned char len;
+	unsigned char version;
+	union {
+		struct SU_SP_s SP;
+		struct SU_CE_s CE;
+		struct SU_ER_s ER;
+		struct RR_RR_s RR;
+		struct RR_PX_s PX;
+		struct RR_PN_s PN;
+		struct RR_SL_s SL;
+		struct RR_NM_s NM;
+		struct RR_CL_s CL;
+		struct RR_PL_s PL;
+		struct RR_TF_s TF;
+		struct RR_ZF_s ZF;
+	} u;
 };
 
-#define RR_PX 1   /* POSIX attributes */
-#define RR_PN 2   /* POSIX devices */
-#define RR_SL 4   /* Symbolic link */
-#define RR_NM 8   /* Alternate Name */
-#define RR_CL 16  /* Child link */
-#define RR_PL 32  /* Parent link */
-#define RR_RE 64  /* Relocation directory */
-#define RR_TF 128 /* Timestamps */
+#define RR_PX 1			/* POSIX attributes */
+#define RR_PN 2			/* POSIX devices */
+#define RR_SL 4			/* Symbolic link */
+#define RR_NM 8			/* Alternate Name */
+#define RR_CL 16		/* Child link */
+#define RR_PL 32		/* Parent link */
+#define RR_RE 64		/* Relocation directory */
+#define RR_TF 128		/* Timestamps */
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index 1e6f2e2..5e7b439 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -167,7 +167,7 @@
 	}
 
 	wake_up(&journal->j_wait_done_commit);
-	if (current->flags & PF_FREEZE) {
+	if (freezing(current)) {
 		/*
 		 * The simpler the better. Flushing journal isn't a
 		 * good idea, because that depends on threads that may
@@ -175,7 +175,7 @@
 		 */
 		jbd_debug(1, "Now suspending kjournald\n");
 		spin_unlock(&journal->j_state_lock);
-		refrigerator(PF_FREEZE);
+		refrigerator();
 		spin_lock(&journal->j_state_lock);
 	} else {
 		/*
diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c
index 8cc6893..fc589dd 100644
--- a/fs/jffs/intrep.c
+++ b/fs/jffs/intrep.c
@@ -175,8 +175,64 @@
 	}
 }
 
+/* Print the contents of a node.  */
+static void
+jffs_print_node(struct jffs_node *n)
+{
+	D(printk("jffs_node: 0x%p\n", n));
+	D(printk("{\n"));
+	D(printk("        0x%08x, /* version  */\n", n->version));
+	D(printk("        0x%08x, /* data_offset  */\n", n->data_offset));
+	D(printk("        0x%08x, /* data_size  */\n", n->data_size));
+	D(printk("        0x%08x, /* removed_size  */\n", n->removed_size));
+	D(printk("        0x%08x, /* fm_offset  */\n", n->fm_offset));
+	D(printk("        0x%02x,       /* name_size  */\n", n->name_size));
+	D(printk("        0x%p, /* fm,  fm->offset: %u  */\n",
+		 n->fm, (n->fm ? n->fm->offset : 0)));
+	D(printk("        0x%p, /* version_prev  */\n", n->version_prev));
+	D(printk("        0x%p, /* version_next  */\n", n->version_next));
+	D(printk("        0x%p, /* range_prev  */\n", n->range_prev));
+	D(printk("        0x%p, /* range_next  */\n", n->range_next));
+	D(printk("}\n"));
+}
+
 #endif
 
+/* Print the contents of a raw inode.  */
+static void
+jffs_print_raw_inode(struct jffs_raw_inode *raw_inode)
+{
+	D(printk("jffs_raw_inode: inode number: %u\n", raw_inode->ino));
+	D(printk("{\n"));
+	D(printk("        0x%08x, /* magic  */\n", raw_inode->magic));
+	D(printk("        0x%08x, /* ino  */\n", raw_inode->ino));
+	D(printk("        0x%08x, /* pino  */\n", raw_inode->pino));
+	D(printk("        0x%08x, /* version  */\n", raw_inode->version));
+	D(printk("        0x%08x, /* mode  */\n", raw_inode->mode));
+	D(printk("        0x%04x,     /* uid  */\n", raw_inode->uid));
+	D(printk("        0x%04x,     /* gid  */\n", raw_inode->gid));
+	D(printk("        0x%08x, /* atime  */\n", raw_inode->atime));
+	D(printk("        0x%08x, /* mtime  */\n", raw_inode->mtime));
+	D(printk("        0x%08x, /* ctime  */\n", raw_inode->ctime));
+	D(printk("        0x%08x, /* offset  */\n", raw_inode->offset));
+	D(printk("        0x%08x, /* dsize  */\n", raw_inode->dsize));
+	D(printk("        0x%08x, /* rsize  */\n", raw_inode->rsize));
+	D(printk("        0x%02x,       /* nsize  */\n", raw_inode->nsize));
+	D(printk("        0x%02x,       /* nlink  */\n", raw_inode->nlink));
+	D(printk("        0x%02x,       /* spare  */\n",
+		 raw_inode->spare));
+	D(printk("        %u,          /* rename  */\n",
+		 raw_inode->rename));
+	D(printk("        %u,          /* deleted  */\n",
+		 raw_inode->deleted));
+	D(printk("        0x%02x,       /* accurate  */\n",
+		 raw_inode->accurate));
+	D(printk("        0x%08x, /* dchksum  */\n", raw_inode->dchksum));
+	D(printk("        0x%04x,     /* nchksum  */\n", raw_inode->nchksum));
+	D(printk("        0x%04x,     /* chksum  */\n", raw_inode->chksum));
+	D(printk("}\n"));
+}
+
 #define flash_safe_acquire(arg)
 #define flash_safe_release(arg)
 
@@ -2507,64 +2563,6 @@
 	return 0;
 }
 
-/* Print the contents of a node.  */
-void
-jffs_print_node(struct jffs_node *n)
-{
-	D(printk("jffs_node: 0x%p\n", n));
-	D(printk("{\n"));
-	D(printk("        0x%08x, /* version  */\n", n->version));
-	D(printk("        0x%08x, /* data_offset  */\n", n->data_offset));
-	D(printk("        0x%08x, /* data_size  */\n", n->data_size));
-	D(printk("        0x%08x, /* removed_size  */\n", n->removed_size));
-	D(printk("        0x%08x, /* fm_offset  */\n", n->fm_offset));
-	D(printk("        0x%02x,       /* name_size  */\n", n->name_size));
-	D(printk("        0x%p, /* fm,  fm->offset: %u  */\n",
-		 n->fm, (n->fm ? n->fm->offset : 0)));
-	D(printk("        0x%p, /* version_prev  */\n", n->version_prev));
-	D(printk("        0x%p, /* version_next  */\n", n->version_next));
-	D(printk("        0x%p, /* range_prev  */\n", n->range_prev));
-	D(printk("        0x%p, /* range_next  */\n", n->range_next));
-	D(printk("}\n"));
-}
-
-
-/* Print the contents of a raw inode.  */
-void
-jffs_print_raw_inode(struct jffs_raw_inode *raw_inode)
-{
-	D(printk("jffs_raw_inode: inode number: %u\n", raw_inode->ino));
-	D(printk("{\n"));
-	D(printk("        0x%08x, /* magic  */\n", raw_inode->magic));
-	D(printk("        0x%08x, /* ino  */\n", raw_inode->ino));
-	D(printk("        0x%08x, /* pino  */\n", raw_inode->pino));
-	D(printk("        0x%08x, /* version  */\n", raw_inode->version));
-	D(printk("        0x%08x, /* mode  */\n", raw_inode->mode));
-	D(printk("        0x%04x,     /* uid  */\n", raw_inode->uid));
-	D(printk("        0x%04x,     /* gid  */\n", raw_inode->gid));
-	D(printk("        0x%08x, /* atime  */\n", raw_inode->atime));
-	D(printk("        0x%08x, /* mtime  */\n", raw_inode->mtime));
-	D(printk("        0x%08x, /* ctime  */\n", raw_inode->ctime));
-	D(printk("        0x%08x, /* offset  */\n", raw_inode->offset));
-	D(printk("        0x%08x, /* dsize  */\n", raw_inode->dsize));
-	D(printk("        0x%08x, /* rsize  */\n", raw_inode->rsize));
-	D(printk("        0x%02x,       /* nsize  */\n", raw_inode->nsize));
-	D(printk("        0x%02x,       /* nlink  */\n", raw_inode->nlink));
-	D(printk("        0x%02x,       /* spare  */\n",
-		 raw_inode->spare));
-	D(printk("        %u,          /* rename  */\n",
-		 raw_inode->rename));
-	D(printk("        %u,          /* deleted  */\n",
-		 raw_inode->deleted));
-	D(printk("        0x%02x,       /* accurate  */\n",
-		 raw_inode->accurate));
-	D(printk("        0x%08x, /* dchksum  */\n", raw_inode->dchksum));
-	D(printk("        0x%04x,     /* nchksum  */\n", raw_inode->nchksum));
-	D(printk("        0x%04x,     /* chksum  */\n", raw_inode->chksum));
-	D(printk("}\n"));
-}
-
-
 /* Print the contents of a file.  */
 #if 0
 int
diff --git a/fs/jffs/intrep.h b/fs/jffs/intrep.h
index 4ae97b1..5c7abe0 100644
--- a/fs/jffs/intrep.h
+++ b/fs/jffs/intrep.h
@@ -49,8 +49,6 @@
 void jffs_garbage_collect_trigger(struct jffs_control *c);
 
 /* For debugging purposes.  */
-void jffs_print_node(struct jffs_node *n);
-void jffs_print_raw_inode(struct jffs_raw_inode *raw_inode);
 #if 0
 int jffs_print_file(struct jffs_file *f);
 #endif  /*  0  */
diff --git a/fs/jffs/jffs_fm.c b/fs/jffs/jffs_fm.c
index 0cab8da..053e3a9 100644
--- a/fs/jffs/jffs_fm.c
+++ b/fs/jffs/jffs_fm.c
@@ -31,6 +31,60 @@
 extern kmem_cache_t     *fm_cache;
 extern kmem_cache_t     *node_cache;
 
+#if CONFIG_JFFS_FS_VERBOSE > 0
+void
+jffs_print_fmcontrol(struct jffs_fmcontrol *fmc)
+{
+	D(printk("struct jffs_fmcontrol: 0x%p\n", fmc));
+	D(printk("{\n"));
+	D(printk("        %u, /* flash_size  */\n", fmc->flash_size));
+	D(printk("        %u, /* used_size  */\n", fmc->used_size));
+	D(printk("        %u, /* dirty_size  */\n", fmc->dirty_size));
+	D(printk("        %u, /* free_size  */\n", fmc->free_size));
+	D(printk("        %u, /* sector_size  */\n", fmc->sector_size));
+	D(printk("        %u, /* min_free_size  */\n", fmc->min_free_size));
+	D(printk("        %u, /* max_chunk_size  */\n", fmc->max_chunk_size));
+	D(printk("        0x%p, /* mtd  */\n", fmc->mtd));
+	D(printk("        0x%p, /* head  */    "
+		 "(head->offset = 0x%08x)\n",
+		 fmc->head, (fmc->head ? fmc->head->offset : 0)));
+	D(printk("        0x%p, /* tail  */    "
+		 "(tail->offset + tail->size = 0x%08x)\n",
+		 fmc->tail,
+		 (fmc->tail ? fmc->tail->offset + fmc->tail->size : 0)));
+	D(printk("        0x%p, /* head_extra  */\n", fmc->head_extra));
+	D(printk("        0x%p, /* tail_extra  */\n", fmc->tail_extra));
+	D(printk("}\n"));
+}
+#endif  /*  CONFIG_JFFS_FS_VERBOSE > 0  */
+
+#if CONFIG_JFFS_FS_VERBOSE > 2
+static void
+jffs_print_fm(struct jffs_fm *fm)
+{
+	D(printk("struct jffs_fm: 0x%p\n", fm));
+	D(printk("{\n"));
+	D(printk("       0x%08x, /* offset  */\n", fm->offset));
+	D(printk("       %u, /* size  */\n", fm->size));
+	D(printk("       0x%p, /* prev  */\n", fm->prev));
+	D(printk("       0x%p, /* next  */\n", fm->next));
+	D(printk("       0x%p, /* nodes  */\n", fm->nodes));
+	D(printk("}\n"));
+}
+#endif  /*  CONFIG_JFFS_FS_VERBOSE > 2  */
+
+#if 0
+void
+jffs_print_node_ref(struct jffs_node_ref *ref)
+{
+	D(printk("struct jffs_node_ref: 0x%p\n", ref));
+	D(printk("{\n"));
+	D(printk("       0x%p, /* node  */\n", ref->node));
+	D(printk("       0x%p, /* next  */\n", ref->next));
+	D(printk("}\n"));
+}
+#endif  /*  0  */
+
 /* This function creates a new shiny flash memory control structure.  */
 struct jffs_fmcontrol *
 jffs_build_begin(struct jffs_control *c, int unit)
@@ -742,54 +796,3 @@
 {
 	return no_jffs_node;
 }
-
-void
-jffs_print_fmcontrol(struct jffs_fmcontrol *fmc)
-{
-	D(printk("struct jffs_fmcontrol: 0x%p\n", fmc));
-	D(printk("{\n"));
-	D(printk("        %u, /* flash_size  */\n", fmc->flash_size));
-	D(printk("        %u, /* used_size  */\n", fmc->used_size));
-	D(printk("        %u, /* dirty_size  */\n", fmc->dirty_size));
-	D(printk("        %u, /* free_size  */\n", fmc->free_size));
-	D(printk("        %u, /* sector_size  */\n", fmc->sector_size));
-	D(printk("        %u, /* min_free_size  */\n", fmc->min_free_size));
-	D(printk("        %u, /* max_chunk_size  */\n", fmc->max_chunk_size));
-	D(printk("        0x%p, /* mtd  */\n", fmc->mtd));
-	D(printk("        0x%p, /* head  */    "
-		 "(head->offset = 0x%08x)\n",
-		 fmc->head, (fmc->head ? fmc->head->offset : 0)));
-	D(printk("        0x%p, /* tail  */    "
-		 "(tail->offset + tail->size = 0x%08x)\n",
-		 fmc->tail,
-		 (fmc->tail ? fmc->tail->offset + fmc->tail->size : 0)));
-	D(printk("        0x%p, /* head_extra  */\n", fmc->head_extra));
-	D(printk("        0x%p, /* tail_extra  */\n", fmc->tail_extra));
-	D(printk("}\n"));
-}
-
-void
-jffs_print_fm(struct jffs_fm *fm)
-{
-	D(printk("struct jffs_fm: 0x%p\n", fm));
-	D(printk("{\n"));
-	D(printk("       0x%08x, /* offset  */\n", fm->offset));
-	D(printk("       %u, /* size  */\n", fm->size));
-	D(printk("       0x%p, /* prev  */\n", fm->prev));
-	D(printk("       0x%p, /* next  */\n", fm->next));
-	D(printk("       0x%p, /* nodes  */\n", fm->nodes));
-	D(printk("}\n"));
-}
-
-#if 0
-void
-jffs_print_node_ref(struct jffs_node_ref *ref)
-{
-	D(printk("struct jffs_node_ref: 0x%p\n", ref));
-	D(printk("{\n"));
-	D(printk("       0x%p, /* node  */\n", ref->node));
-	D(printk("       0x%p, /* next  */\n", ref->next));
-	D(printk("}\n"));
-}
-#endif  /*  0  */
-
diff --git a/fs/jffs/jffs_fm.h b/fs/jffs/jffs_fm.h
index bc291c4..f64151e 100644
--- a/fs/jffs/jffs_fm.h
+++ b/fs/jffs/jffs_fm.h
@@ -139,8 +139,9 @@
 void jffs_fmfree_partly(struct jffs_fmcontrol *fmc, struct jffs_fm *fm,
 			__u32 size);
 
+#if CONFIG_JFFS_FS_VERBOSE > 0
 void jffs_print_fmcontrol(struct jffs_fmcontrol *fmc);
-void jffs_print_fm(struct jffs_fm *fm);
+#endif
 #if 0
 void jffs_print_node_ref(struct jffs_node_ref *ref);
 #endif  /*  0  */
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c
index 1be6de2..638836b 100644
--- a/fs/jffs2/background.c
+++ b/fs/jffs2/background.c
@@ -92,7 +92,7 @@
 			schedule();
 		}
 
-		if (try_to_freeze(0))
+		if (try_to_freeze())
 			continue;
 
 		cond_resched();
diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c
index 8d2a9ab..e892dab 100644
--- a/fs/jfs/acl.c
+++ b/fs/jfs/acl.c
@@ -21,6 +21,7 @@
 #include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/quotaops.h>
+#include <linux/posix_acl_xattr.h>
 #include "jfs_incore.h"
 #include "jfs_xattr.h"
 #include "jfs_acl.h"
@@ -36,11 +37,11 @@
 
 	switch(type) {
 		case ACL_TYPE_ACCESS:
-			ea_name = XATTR_NAME_ACL_ACCESS;
+			ea_name = POSIX_ACL_XATTR_ACCESS;
 			p_acl = &ji->i_acl;
 			break;
 		case ACL_TYPE_DEFAULT:
-			ea_name = XATTR_NAME_ACL_DEFAULT;
+			ea_name = POSIX_ACL_XATTR_DEFAULT;
 			p_acl = &ji->i_default_acl;
 			break;
 		default:
@@ -70,8 +71,7 @@
 		if (!IS_ERR(acl))
 			*p_acl = posix_acl_dup(acl);
 	}
-	if (value)
-		kfree(value);
+	kfree(value);
 	return acl;
 }
 
@@ -89,11 +89,11 @@
 
 	switch(type) {
 		case ACL_TYPE_ACCESS:
-			ea_name = XATTR_NAME_ACL_ACCESS;
+			ea_name = POSIX_ACL_XATTR_ACCESS;
 			p_acl = &ji->i_acl;
 			break;
 		case ACL_TYPE_DEFAULT:
-			ea_name = XATTR_NAME_ACL_DEFAULT;
+			ea_name = POSIX_ACL_XATTR_DEFAULT;
 			p_acl = &ji->i_default_acl;
 			if (!S_ISDIR(inode->i_mode))
 				return acl ? -EACCES : 0;
@@ -102,7 +102,7 @@
 			return -EINVAL;
 	}
 	if (acl) {
-		size = xattr_acl_size(acl->a_count);
+		size = posix_acl_xattr_size(acl->a_count);
 		value = kmalloc(size, GFP_KERNEL);
 		if (!value)
 			return -ENOMEM;
@@ -112,8 +112,7 @@
 	}
 	rc = __jfs_setxattr(inode, ea_name, value, size, 0);
 out:
-	if (value)
-		kfree(value);
+	kfree(value);
 
 	if (!rc) {
 		if (*p_acl && (*p_acl != JFS_ACL_NOT_CACHED))
diff --git a/fs/jfs/file.c b/fs/jfs/file.c
index a87b06f..c2c19c9 100644
--- a/fs/jfs/file.c
+++ b/fs/jfs/file.c
@@ -1,6 +1,6 @@
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2002
- *   Portions Copyright (c) Christoph Hellwig, 2001-2002
+ *   Copyright (C) International Business Machines Corp., 2000-2002
+ *   Portions Copyright (C) Christoph Hellwig, 2001-2002
  *
  *   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,16 +19,13 @@
 
 #include <linux/fs.h>
 #include "jfs_incore.h"
+#include "jfs_inode.h"
 #include "jfs_dmap.h"
 #include "jfs_txnmgr.h"
 #include "jfs_xattr.h"
 #include "jfs_acl.h"
 #include "jfs_debug.h"
 
-
-extern int jfs_commit_inode(struct inode *, int);
-extern void jfs_truncate(struct inode *);
-
 int jfs_fsync(struct file *file, struct dentry *dentry, int datasync)
 {
 	struct inode *inode = dentry->d_inode;
diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c
index 24a6891..2137138 100644
--- a/fs/jfs/inode.c
+++ b/fs/jfs/inode.c
@@ -23,6 +23,7 @@
 #include <linux/pagemap.h>
 #include <linux/quotaops.h>
 #include "jfs_incore.h"
+#include "jfs_inode.h"
 #include "jfs_filsys.h"
 #include "jfs_imap.h"
 #include "jfs_extent.h"
@@ -30,14 +31,6 @@
 #include "jfs_debug.h"
 
 
-extern struct inode_operations jfs_dir_inode_operations;
-extern struct inode_operations jfs_file_inode_operations;
-extern struct inode_operations jfs_symlink_inode_operations;
-extern struct file_operations jfs_dir_operations;
-extern struct file_operations jfs_file_operations;
-struct address_space_operations jfs_aops;
-extern int freeZeroLink(struct inode *);
-
 void jfs_read_inode(struct inode *inode)
 {
 	if (diRead(inode)) { 
@@ -136,7 +129,7 @@
 	jfs_info("In jfs_delete_inode, inode = 0x%p", inode);
 
 	if (test_cflag(COMMIT_Freewmap, inode))
-		freeZeroLink(inode);
+		jfs_free_zero_link(inode);
 
 	diFree(inode);
 
diff --git a/fs/jfs/jfs_acl.h b/fs/jfs/jfs_acl.h
index d2ae430..a3acd3e 100644
--- a/fs/jfs/jfs_acl.h
+++ b/fs/jfs/jfs_acl.h
@@ -20,8 +20,6 @@
 
 #ifdef CONFIG_JFS_POSIX_ACL
 
-#include <linux/xattr_acl.h>
-
 int jfs_permission(struct inode *, int, struct nameidata *);
 int jfs_init_acl(struct inode *, struct inode *);
 int jfs_setattr(struct dentry *, struct iattr *);
diff --git a/fs/jfs/jfs_debug.c b/fs/jfs/jfs_debug.c
index 91a0a88..4caea6b 100644
--- a/fs/jfs/jfs_debug.c
+++ b/fs/jfs/jfs_debug.c
@@ -58,8 +58,6 @@
 
 static struct proc_dir_entry *base;
 #ifdef CONFIG_JFS_DEBUG
-extern read_proc_t jfs_txanchor_read;
-
 static int loglevel_read(char *page, char **start, off_t off,
 			 int count, int *eof, void *data)
 {
@@ -97,14 +95,6 @@
 }
 #endif
 
-
-#ifdef CONFIG_JFS_STATISTICS
-extern read_proc_t jfs_lmstats_read;
-extern read_proc_t jfs_txstats_read;
-extern read_proc_t jfs_xtstat_read;
-extern read_proc_t jfs_mpstat_read;
-#endif
-
 static struct {
 	const char	*name;
 	read_proc_t	*read_fn;
diff --git a/fs/jfs/jfs_debug.h b/fs/jfs/jfs_debug.h
index a38079a..ddffbbd 100644
--- a/fs/jfs/jfs_debug.h
+++ b/fs/jfs/jfs_debug.h
@@ -1,6 +1,6 @@
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2002
- *   Portions Copyright (c) Christoph Hellwig, 2001-2002
+ *   Copyright (C) International Business Machines Corp., 2000-2002
+ *   Portions Copyright (C) Christoph Hellwig, 2001-2002
  *
  *   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
@@ -31,7 +31,9 @@
  * CONFIG_JFS_DEBUG or CONFIG_JFS_STATISTICS is defined
  */
 #if defined(CONFIG_PROC_FS) && (defined(CONFIG_JFS_DEBUG) || defined(CONFIG_JFS_STATISTICS))
-	#define PROC_FS_JFS
+#define PROC_FS_JFS
+extern void jfs_proc_init(void);
+extern void jfs_proc_clean(void);
 #endif
 
 /*
@@ -65,8 +67,8 @@
 
 extern int jfsloglevel;
 
-/* dump memory contents */
 extern void dump_mem(char *label, void *data, int length);
+extern int jfs_txanchor_read(char *, char **, off_t, int, int *, void *);
 
 /* information message: e.g., configuration, major event */
 #define jfs_info(fmt, arg...) do {			\
@@ -110,6 +112,11 @@
  *	----------
  */
 #ifdef	CONFIG_JFS_STATISTICS
+extern int jfs_lmstats_read(char *, char **, off_t, int, int *, void *);
+extern int jfs_txstats_read(char *, char **, off_t, int, int *, void *);
+extern int jfs_mpstat_read(char *, char **, off_t, int, int *, void *);
+extern int jfs_xtstat_read(char *, char **, off_t, int, int *, void *);
+
 #define	INCREMENT(x)		((x)++)
 #define	DECREMENT(x)		((x)--)
 #define	HIGHWATERMARK(x,y)	((x) = max((x), (y)))
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
index 69007fd..cced2fe 100644
--- a/fs/jfs/jfs_dmap.c
+++ b/fs/jfs/jfs_dmap.c
@@ -272,7 +272,6 @@
 int dbUnmount(struct inode *ipbmap, int mounterror)
 {
 	struct bmap *bmp = JFS_SBI(ipbmap->i_sb)->bmap;
-	int i;
 
 	if (!(mounterror || isReadOnly(ipbmap)))
 		dbSync(ipbmap);
@@ -282,14 +281,6 @@
 	 */
 	truncate_inode_pages(ipbmap->i_mapping, 0);
 
-	/*
-	 * Sanity Check
-	 */
-	for (i = 0; i < bmp->db_numag; i++)
-		if (atomic_read(&bmp->db_active[i]))
-			printk(KERN_ERR "dbUnmount: db_active[%d] = %d\n",
-			       i, atomic_read(&bmp->db_active[i]));
-
 	/* free the memory for the in-memory bmap. */
 	kfree(bmp);
 
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index ac41f72..8676aee 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -2931,6 +2931,9 @@
 	ASSERT(p->header.flag & BT_LEAF);
 
 	tlck = txLock(tid, inode, mp, tlckDTREE | tlckENTRY);
+	if (BT_IS_ROOT(mp))
+		tlck->type |= tlckBTROOT;
+
 	dtlck = (struct dt_lock *) &tlck->lock;
 
 	stbl = DT_GETSTBL(p);
diff --git a/fs/jfs/jfs_extent.c b/fs/jfs/jfs_extent.c
index 1953acb..4879603 100644
--- a/fs/jfs/jfs_extent.c
+++ b/fs/jfs/jfs_extent.c
@@ -19,6 +19,7 @@
 #include <linux/fs.h>
 #include <linux/quotaops.h>
 #include "jfs_incore.h"
+#include "jfs_inode.h"
 #include "jfs_superblock.h"
 #include "jfs_dmap.h"
 #include "jfs_extent.h"
@@ -33,12 +34,6 @@
 #endif
 static s64 extRoundDown(s64 nb);
 
-/*
- * external references
- */
-extern int jfs_commit_inode(struct inode *, int);
-
-
 #define DPD(a)          (printk("(a): %d\n",(a)))
 #define DPC(a)          (printk("(a): %c\n",(a)))
 #define DPL1(a)					\
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
index 7acff2c..971af29 100644
--- a/fs/jfs/jfs_imap.c
+++ b/fs/jfs/jfs_imap.c
@@ -47,6 +47,7 @@
 #include <linux/quotaops.h>
 
 #include "jfs_incore.h"
+#include "jfs_inode.h"
 #include "jfs_filsys.h"
 #include "jfs_dinode.h"
 #include "jfs_dmap.h"
@@ -69,11 +70,6 @@
 #define AG_UNLOCK(imap,agno)		up(&imap->im_aglock[agno])
 
 /*
- * external references
- */
-extern struct address_space_operations jfs_aops;
-
-/*
  * forward references
  */
 static int diAllocAG(struct inomap *, int, boolean_t, struct inode *);
diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c
index 84f2459..2af5efb 100644
--- a/fs/jfs/jfs_inode.c
+++ b/fs/jfs/jfs_inode.c
@@ -19,6 +19,7 @@
 #include <linux/fs.h>
 #include <linux/quotaops.h>
 #include "jfs_incore.h"
+#include "jfs_inode.h"
 #include "jfs_filsys.h"
 #include "jfs_imap.h"
 #include "jfs_dinode.h"
diff --git a/fs/jfs/jfs_inode.h b/fs/jfs/jfs_inode.h
index 3df91fb..b54bac5 100644
--- a/fs/jfs/jfs_inode.h
+++ b/fs/jfs/jfs_inode.h
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2001
+ *   Copyright (C) International Business Machines Corp., 2000-2001
  *
  *   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,5 +19,22 @@
 #define _H_JFS_INODE
 
 extern struct inode *ialloc(struct inode *, umode_t);
+extern int jfs_fsync(struct file *, struct dentry *, int);
+extern void jfs_read_inode(struct inode *);
+extern int jfs_commit_inode(struct inode *, int);
+extern int jfs_write_inode(struct inode*, int);
+extern void jfs_delete_inode(struct inode *);
+extern void jfs_dirty_inode(struct inode *);
+extern void jfs_truncate(struct inode *);
+extern void jfs_truncate_nolock(struct inode *, loff_t);
+extern void jfs_free_zero_link(struct inode *);
+extern struct dentry *jfs_get_parent(struct dentry *dentry);
 
+extern struct address_space_operations jfs_aops;
+extern struct inode_operations jfs_dir_inode_operations;
+extern struct file_operations jfs_dir_operations;
+extern struct inode_operations jfs_file_inode_operations;
+extern struct file_operations jfs_file_operations;
+extern struct inode_operations jfs_symlink_inode_operations;
+extern struct dentry_operations jfs_ci_dentry_operations;
 #endif				/* _H_JFS_INODE */
diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
index dfa1200..79d0762 100644
--- a/fs/jfs/jfs_logmgr.c
+++ b/fs/jfs/jfs_logmgr.c
@@ -71,6 +71,7 @@
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_metapage.h"
+#include "jfs_superblock.h"
 #include "jfs_txnmgr.h"
 #include "jfs_debug.h"
 
@@ -167,14 +168,6 @@
 static DECLARE_MUTEX(jfs_log_sem);
 
 /*
- * external references
- */
-extern void txLazyUnlock(struct tblock * tblk);
-extern int jfs_stop_threads;
-extern struct completion jfsIOwait;
-extern int jfs_tlocks_low;
-
-/*
  * forward references
  */
 static int lmWriteRecord(struct jfs_log * log, struct tblock * tblk,
@@ -1624,6 +1617,8 @@
 		}
 	}
 	assert(list_empty(&log->cqueue));
+
+#ifdef CONFIG_JFS_DEBUG
 	if (!list_empty(&log->synclist)) {
 		struct logsyncblk *lp;
 
@@ -1638,9 +1633,8 @@
 				dump_mem("orphan tblock", lp,
 					 sizeof(struct tblock));
 		}
-//		current->state = TASK_INTERRUPTIBLE;
-//		schedule();
 	}
+#endif
 	//assert(list_empty(&log->synclist));
 	clear_bit(log_FLUSH, &log->flag);
 }
@@ -2365,9 +2359,9 @@
 			lbmStartIO(bp);
 			spin_lock_irq(&log_redrive_lock);
 		}
-		if (current->flags & PF_FREEZE) {
+		if (freezing(current)) {
 			spin_unlock_irq(&log_redrive_lock);
-			refrigerator(PF_FREEZE);
+			refrigerator();
 		} else {
 			add_wait_queue(&jfs_IO_thread_wait, &wq);
 			set_current_state(TASK_INTERRUPTIBLE);
diff --git a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h
index 51291fb..747114c 100644
--- a/fs/jfs/jfs_logmgr.h
+++ b/fs/jfs/jfs_logmgr.h
@@ -507,6 +507,8 @@
 extern int lmLogShutdown(struct jfs_log * log);
 extern int lmLogInit(struct jfs_log * log);
 extern int lmLogFormat(struct jfs_log *log, s64 logAddress, int logSize);
+extern int lmGroupCommit(struct jfs_log *, struct tblock *);
+extern int jfsIOWait(void *);
 extern void jfs_flush_journal(struct jfs_log * log, int wait);
 extern void jfs_syncpt(struct jfs_log *log);
 
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
index 41bf078..6c5485d 100644
--- a/fs/jfs/jfs_metapage.c
+++ b/fs/jfs/jfs_metapage.c
@@ -198,7 +198,7 @@
 	}
 }
 
-static inline struct metapage *alloc_metapage(int gfp_mask)
+static inline struct metapage *alloc_metapage(unsigned int gfp_mask)
 {
 	return mempool_alloc(metapage_mempool, gfp_mask);
 }
@@ -726,12 +726,12 @@
 	page_cache_release(page);
 }
 
-extern void hold_metapage(struct metapage *mp)
+void hold_metapage(struct metapage *mp)
 {
 	lock_page(mp->page);
 }
 
-extern void put_metapage(struct metapage *mp)
+void put_metapage(struct metapage *mp)
 {
 	if (mp->count || mp->nohomeok) {
 		/* Someone else will release this */
diff --git a/fs/jfs/jfs_metapage.h b/fs/jfs/jfs_metapage.h
index 991e9fb..f0b7d32 100644
--- a/fs/jfs/jfs_metapage.h
+++ b/fs/jfs/jfs_metapage.h
@@ -1,6 +1,6 @@
 /*
- *   Copyright (c) International Business Machines Corp., 2000-2002
- *   Portions Copyright (c) Christoph Hellwig, 2001-2002
+ *   Copyright (C) International Business Machines Corp., 2000-2002
+ *   Portions Copyright (C) Christoph Hellwig, 2001-2002
  *
  *   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
@@ -58,6 +58,8 @@
 #define mark_metapage_dirty(mp) set_bit(META_dirty, &(mp)->flag)
 
 /* function prototypes */
+extern int metapage_init(void);
+extern void metapage_exit(void);
 extern struct metapage *__get_metapage(struct inode *inode,
 				  unsigned long lblock, unsigned int size,
 				  int absolute, unsigned long new);
diff --git a/fs/jfs/jfs_superblock.h b/fs/jfs/jfs_superblock.h
index ab0566f..fcf781b 100644
--- a/fs/jfs/jfs_superblock.h
+++ b/fs/jfs/jfs_superblock.h
@@ -109,5 +109,16 @@
 extern int readSuper(struct super_block *, struct buffer_head **);
 extern int updateSuper(struct super_block *, uint);
 extern void jfs_error(struct super_block *, const char *, ...);
+extern int jfs_mount(struct super_block *);
+extern int jfs_mount_rw(struct super_block *, int);
+extern int jfs_umount(struct super_block *);
+extern int jfs_umount_rw(struct super_block *);
+
+extern int jfs_stop_threads;
+extern struct completion jfsIOwait;
+extern wait_queue_head_t jfs_IO_thread_wait;
+extern wait_queue_head_t jfs_commit_thread_wait;
+extern wait_queue_head_t jfs_sync_thread_wait;
+extern int jfs_extendfs(struct super_block *, s64, int);
 
 #endif /*_H_JFS_SUPERBLOCK */
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index e93d01a..121c981 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -42,7 +42,6 @@
  * hold on to mp+lock thru update of maps
  */
 
-
 #include <linux/fs.h>
 #include <linux/vmalloc.h>
 #include <linux/smp_lock.h>
@@ -51,6 +50,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include "jfs_incore.h"
+#include "jfs_inode.h"
 #include "jfs_filsys.h"
 #include "jfs_metapage.h"
 #include "jfs_dinode.h"
@@ -109,7 +109,6 @@
 static int TxLockVHWM;		/* Very High water mark */
 struct tlock *TxLock;           /* transaction lock table */
 
-
 /*
  *      transaction management lock
  */
@@ -149,7 +148,6 @@
 
 #define TXN_WAKEUP(event) wake_up_all(event)
 
-
 /*
  *      statistics
  */
@@ -161,16 +159,6 @@
 	int waitlock;		/* 4: # of tlock wait */
 } stattx;
 
-
-/*
- * external references
- */
-extern int lmGroupCommit(struct jfs_log *, struct tblock *);
-extern int jfs_commit_inode(struct inode *, int);
-extern int jfs_stop_threads;
-
-extern struct completion jfsIOwait;
-
 /*
  * forward references
  */
@@ -358,7 +346,6 @@
 	TxBlock = NULL;
 }
 
-
 /*
  * NAME:        txBegin()
  *
@@ -460,7 +447,6 @@
 	return t;
 }
 
-
 /*
  * NAME:        txBeginAnon()
  *
@@ -503,7 +489,6 @@
 	TXN_UNLOCK();
 }
 
-
 /*
  *      txEnd()
  *
@@ -592,7 +577,6 @@
 	TXN_WAKEUP(&TxAnchor.freewait);
 }
 
-
 /*
  *      txLock()
  *
@@ -868,7 +852,6 @@
 	return NULL;
 }
 
-
 /*
  * NAME:        txRelease()
  *
@@ -908,7 +891,6 @@
 	TXN_UNLOCK();
 }
 
-
 /*
  * NAME:        txUnlock()
  *
@@ -996,7 +978,6 @@
 	}
 }
 
-
 /*
  *      txMaplock()
  *
@@ -1069,7 +1050,6 @@
 	return tlck;
 }
 
-
 /*
  *      txLinelock()
  *
@@ -1103,8 +1083,6 @@
 	return linelock;
 }
 
-
-
 /*
  *              transaction commit management
  *              -----------------------------
@@ -1373,7 +1351,6 @@
 	return rc;
 }
 
-
 /*
  * NAME:        txLog()
  *
@@ -1437,7 +1414,6 @@
 	return rc;
 }
 
-
 /*
  *      diLog()
  *
@@ -1465,7 +1441,6 @@
 	if (tlck->type & tlckENTRY) {
 		/* log after-image for logredo(): */
 		lrd->type = cpu_to_le16(LOG_REDOPAGE);
-//              *pxd = mp->cm_pxd;
 		PXDaddress(pxd, mp->index);
 		PXDlength(pxd,
 			  mp->logical_size >> tblk->sb->s_blocksize_bits);
@@ -1552,7 +1527,6 @@
 	return rc;
 }
 
-
 /*
  *      dataLog()
  *
@@ -1599,7 +1573,6 @@
 	return 0;
 }
 
-
 /*
  *      dtLog()
  *
@@ -1639,7 +1612,6 @@
 			lrd->log.redopage.type |= cpu_to_le16(LOG_EXTEND);
 		else
 			lrd->log.redopage.type |= cpu_to_le16(LOG_NEW);
-//              *pxd = mp->cm_pxd;
 		PXDaddress(pxd, mp->index);
 		PXDlength(pxd,
 			  mp->logical_size >> tblk->sb->s_blocksize_bits);
@@ -1704,7 +1676,6 @@
 	return;
 }
 
-
 /*
  *      xtLog()
  *
@@ -1760,7 +1731,6 @@
 		 * applying the after-image to the meta-data page.
 		 */
 		lrd->type = cpu_to_le16(LOG_REDOPAGE);
-//              *page_pxd = mp->cm_pxd;
 		PXDaddress(page_pxd, mp->index);
 		PXDlength(page_pxd,
 			  mp->logical_size >> tblk->sb->s_blocksize_bits);
@@ -2093,7 +2063,6 @@
 	return;
 }
 
-
 /*
  *      mapLog()
  *
@@ -2180,7 +2149,6 @@
 	}
 }
 
-
 /*
  *      txEA()
  *
@@ -2233,7 +2201,6 @@
 	}
 }
 
-
 /*
  *      txForce()
  *
@@ -2300,7 +2267,6 @@
 	}
 }
 
-
 /*
  *      txUpdateMap()
  *
@@ -2437,7 +2403,6 @@
 	}
 }
 
-
 /*
  *      txAllocPMap()
  *
@@ -2509,7 +2474,6 @@
 	}
 }
 
-
 /*
  *      txFreeMap()
  *
@@ -2611,7 +2575,6 @@
 	}
 }
 
-
 /*
  *      txFreelock()
  *
@@ -2652,7 +2615,6 @@
 	TXN_UNLOCK();
 }
 
-
 /*
  *      txAbort()
  *
@@ -2826,9 +2788,9 @@
 		/* In case a wakeup came while all threads were active */
 		jfs_commit_thread_waking = 0;
 
-		if (current->flags & PF_FREEZE) {
+		if (freezing(current)) {
 			LAZY_UNLOCK(flags);
-			refrigerator(PF_FREEZE);
+			refrigerator();
 		} else {
 			DECLARE_WAITQUEUE(wq, current);
 
@@ -3025,9 +2987,9 @@
 		/* Add anon_list2 back to anon_list */
 		list_splice_init(&TxAnchor.anon_list2, &TxAnchor.anon_list);
 
-		if (current->flags & PF_FREEZE) {
+		if (freezing(current)) {
 			TXN_UNLOCK();
-			refrigerator(PF_FREEZE);
+			refrigerator();
 		} else {
 			DECLARE_WAITQUEUE(wq, current);
 
diff --git a/fs/jfs/jfs_txnmgr.h b/fs/jfs/jfs_txnmgr.h
index b71b82c..59ad0f6 100644
--- a/fs/jfs/jfs_txnmgr.h
+++ b/fs/jfs/jfs_txnmgr.h
@@ -285,34 +285,26 @@
 /*
  * external declarations
  */
-extern struct tlock *txLock(tid_t tid, struct inode *ip, struct metapage *mp,
-			    int flag);
+extern int jfs_tlocks_low;
 
-extern struct tlock *txMaplock(tid_t tid, struct inode *ip, int flag);
-
-extern int txCommit(tid_t tid, int nip, struct inode **iplist, int flag);
-
-extern tid_t txBegin(struct super_block *sb, int flag);
-
-extern void txBeginAnon(struct super_block *sb);
-
-extern void txEnd(tid_t tid);
-
-extern void txAbort(tid_t tid, int dirty);
-
-extern struct linelock *txLinelock(struct linelock * tlock);
-
-extern void txFreeMap(struct inode *ip, struct maplock * maplock,
-		      struct tblock * tblk, int maptype);
-
-extern void txEA(tid_t tid, struct inode *ip, dxd_t * oldea, dxd_t * newea);
-
-extern void txFreelock(struct inode *ip);
-
-extern int lmLog(struct jfs_log * log, struct tblock * tblk, struct lrd * lrd,
-		 struct tlock * tlck);
-
-extern void txQuiesce(struct super_block *sb);
-
-extern void txResume(struct super_block *sb);
+extern int txInit(void);
+extern void txExit(void);
+extern struct tlock *txLock(tid_t, struct inode *, struct metapage *, int);
+extern struct tlock *txMaplock(tid_t, struct inode *, int);
+extern int txCommit(tid_t, int, struct inode **, int);
+extern tid_t txBegin(struct super_block *, int);
+extern void txBeginAnon(struct super_block *);
+extern void txEnd(tid_t);
+extern void txAbort(tid_t, int);
+extern struct linelock *txLinelock(struct linelock *);
+extern void txFreeMap(struct inode *, struct maplock *, struct tblock *, int);
+extern void txEA(tid_t, struct inode *, dxd_t *, dxd_t *);
+extern void txFreelock(struct inode *);
+extern int lmLog(struct jfs_log *, struct tblock *, struct lrd *,
+		 struct tlock *);
+extern void txQuiesce(struct super_block *);
+extern void txResume(struct super_block *);
+extern void txLazyUnlock(struct tblock *);
+extern int jfs_lazycommit(void *);
+extern int jfs_sync(void *);
 #endif				/* _H_JFS_TXNMGR */
diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c
index 8413a36..1cae14e 100644
--- a/fs/jfs/namei.c
+++ b/fs/jfs/namei.c
@@ -31,20 +31,9 @@
 #include "jfs_acl.h"
 #include "jfs_debug.h"
 
-extern struct inode_operations jfs_file_inode_operations;
-extern struct inode_operations jfs_symlink_inode_operations;
-extern struct file_operations jfs_file_operations;
-extern struct address_space_operations jfs_aops;
-
-extern int jfs_fsync(struct file *, struct dentry *, int);
-extern void jfs_truncate_nolock(struct inode *, loff_t);
-extern int jfs_init_acl(struct inode *, struct inode *);
-
 /*
  * forward references
  */
-struct inode_operations jfs_dir_inode_operations;
-struct file_operations jfs_dir_operations;
 struct dentry_operations jfs_ci_dentry_operations;
 
 static s64 commitZeroLink(tid_t, struct inode *);
@@ -655,7 +644,7 @@
 
 
 /*
- * NAME:	freeZeroLink()
+ * NAME:	jfs_free_zero_link()
  *
  * FUNCTION:    for non-directory, called by iClose(),
  *		free resources of a file from cache and WORKING map 
@@ -663,15 +652,12 @@
  *		while associated with a pager object,
  *
  * PARAMETER:	ip	- pointer to inode of file.
- *
- * RETURN:	0 -ok
  */
-int freeZeroLink(struct inode *ip)
+void jfs_free_zero_link(struct inode *ip)
 {
-	int rc = 0;
 	int type;
 
-	jfs_info("freeZeroLink: ip = 0x%p", ip);
+	jfs_info("jfs_free_zero_link: ip = 0x%p", ip);
 
 	/* return if not reg or symbolic link or if size is
 	 * already ok.
@@ -684,10 +670,10 @@
 	case S_IFLNK:
 		/* if its contained in inode nothing to do */
 		if (ip->i_size < IDATASIZE)
-			return 0;
+			return;
 		break;
 	default:
-		return 0;
+		return;
 	}
 
 	/*
@@ -737,9 +723,7 @@
 	 * free xtree/data blocks from working block map;
 	 */
 	if (ip->i_size)
-		rc = xtTruncate(0, ip, 0, COMMIT_WMAP);
-
-	return rc;
+		xtTruncate(0, ip, 0, COMMIT_WMAP);
 }
 
 /*
diff --git a/fs/jfs/super.c b/fs/jfs/super.c
index 5e774ed..ee32211 100644
--- a/fs/jfs/super.c
+++ b/fs/jfs/super.c
@@ -24,10 +24,12 @@
 #include <linux/completion.h>
 #include <linux/vfs.h>
 #include <linux/moduleparam.h>
+#include <linux/posix_acl.h>
 #include <asm/uaccess.h>
 
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
+#include "jfs_inode.h"
 #include "jfs_metapage.h"
 #include "jfs_superblock.h"
 #include "jfs_dmap.h"
@@ -62,37 +64,6 @@
 MODULE_PARM_DESC(jfsloglevel, "Specify JFS loglevel (0, 1 or 2)");
 #endif
 
-/*
- * External declarations
- */
-extern int jfs_mount(struct super_block *);
-extern int jfs_mount_rw(struct super_block *, int);
-extern int jfs_umount(struct super_block *);
-extern int jfs_umount_rw(struct super_block *);
-
-extern int jfsIOWait(void *);
-extern int jfs_lazycommit(void *);
-extern int jfs_sync(void *);
-
-extern void jfs_read_inode(struct inode *inode);
-extern void jfs_dirty_inode(struct inode *inode);
-extern void jfs_delete_inode(struct inode *inode);
-extern int jfs_write_inode(struct inode *inode, int wait);
-
-extern struct dentry *jfs_get_parent(struct dentry *dentry);
-extern int jfs_extendfs(struct super_block *, s64, int);
-
-extern struct dentry_operations jfs_ci_dentry_operations;
-
-#ifdef PROC_FS_JFS		/* see jfs_debug.h */
-extern void jfs_proc_init(void);
-extern void jfs_proc_clean(void);
-#endif
-
-extern wait_queue_head_t jfs_IO_thread_wait;
-extern wait_queue_head_t jfs_commit_thread_wait;
-extern wait_queue_head_t jfs_sync_thread_wait;
-
 static void jfs_handle_error(struct super_block *sb)
 {
 	struct jfs_sb_info *sbi = JFS_SBI(sb);
@@ -593,11 +564,6 @@
 	.fs_flags	= FS_REQUIRES_DEV,
 };
 
-extern int metapage_init(void);
-extern int txInit(void);
-extern void txExit(void);
-extern void metapage_exit(void);
-
 static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
 {
 	struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo;
diff --git a/fs/jfs/symlink.c b/fs/jfs/symlink.c
index ef4c07e..287d8d6 100644
--- a/fs/jfs/symlink.c
+++ b/fs/jfs/symlink.c
@@ -1,5 +1,5 @@
 /*
- *   Copyright (c) Christoph Hellwig, 2001-2002
+ *   Copyright (C) Christoph Hellwig, 2001-2002
  *
  *   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,6 +19,7 @@
 #include <linux/fs.h>
 #include <linux/namei.h>
 #include "jfs_incore.h"
+#include "jfs_inode.h"
 #include "jfs_xattr.h"
 
 static int jfs_follow_link(struct dentry *dentry, struct nameidata *nd)
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index 7a9ffd5..ee438d4 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -19,6 +19,7 @@
 
 #include <linux/fs.h>
 #include <linux/xattr.h>
+#include <linux/posix_acl_xattr.h>
 #include <linux/quotaops.h>
 #include "jfs_incore.h"
 #include "jfs_superblock.h"
@@ -718,9 +719,9 @@
 		return -EPERM;
 
 	/*
-	 * XATTR_NAME_ACL_ACCESS is tied to i_mode
+	 * POSIX_ACL_XATTR_ACCESS is tied to i_mode
 	 */
-	if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0) {
+	if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0) {
 		acl = posix_acl_from_xattr(value, value_len);
 		if (IS_ERR(acl)) {
 			rc = PTR_ERR(acl);
@@ -750,7 +751,7 @@
 		JFS_IP(inode)->i_acl = JFS_ACL_NOT_CACHED;
 
 		return 0;
-	} else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0) {
+	} else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0) {
 		acl = posix_acl_from_xattr(value, value_len);
 		if (IS_ERR(acl)) {
 			rc = PTR_ERR(acl);
@@ -946,8 +947,7 @@
       out:
 	up_write(&JFS_IP(inode)->xattr_sem);
 
-	if (os2name)
-		kfree(os2name);
+	kfree(os2name);
 
 	return rc;
 }
@@ -1042,8 +1042,7 @@
       out:
 	up_read(&JFS_IP(inode)->xattr_sem);
 
-	if (os2name)
-		kfree(os2name);
+	kfree(os2name);
 
 	return size;
 }
diff --git a/fs/libfs.c b/fs/libfs.c
index f90b295..58101df 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -183,6 +183,7 @@
 	.llseek		= dcache_dir_lseek,
 	.read		= generic_read_dir,
 	.readdir	= dcache_readdir,
+	.fsync		= simple_sync_file,
 };
 
 struct inode_operations simple_dir_inode_operations = {
@@ -519,6 +520,102 @@
 	return 0;
 }
 
+/* Simple attribute files */
+
+struct simple_attr {
+	u64 (*get)(void *);
+	void (*set)(void *, u64);
+	char get_buf[24];	/* enough to store a u64 and "\n\0" */
+	char set_buf[24];
+	void *data;
+	const char *fmt;	/* format for read operation */
+	struct semaphore sem;	/* protects access to these buffers */
+};
+
+/* simple_attr_open is called by an actual attribute open file operation
+ * to set the attribute specific access operations. */
+int simple_attr_open(struct inode *inode, struct file *file,
+		     u64 (*get)(void *), void (*set)(void *, u64),
+		     const char *fmt)
+{
+	struct simple_attr *attr;
+
+	attr = kmalloc(sizeof(*attr), GFP_KERNEL);
+	if (!attr)
+		return -ENOMEM;
+
+	attr->get = get;
+	attr->set = set;
+	attr->data = inode->u.generic_ip;
+	attr->fmt = fmt;
+	init_MUTEX(&attr->sem);
+
+	file->private_data = attr;
+
+	return nonseekable_open(inode, file);
+}
+
+int simple_attr_close(struct inode *inode, struct file *file)
+{
+	kfree(file->private_data);
+	return 0;
+}
+
+/* read from the buffer that is filled with the get function */
+ssize_t simple_attr_read(struct file *file, char __user *buf,
+			 size_t len, loff_t *ppos)
+{
+	struct simple_attr *attr;
+	size_t size;
+	ssize_t ret;
+
+	attr = file->private_data;
+
+	if (!attr->get)
+		return -EACCES;
+
+	down(&attr->sem);
+	if (*ppos) /* continued read */
+		size = strlen(attr->get_buf);
+	else	  /* first read */
+		size = scnprintf(attr->get_buf, sizeof(attr->get_buf),
+				 attr->fmt,
+				 (unsigned long long)attr->get(attr->data));
+
+	ret = simple_read_from_buffer(buf, len, ppos, attr->get_buf, size);
+	up(&attr->sem);
+	return ret;
+}
+
+/* interpret the buffer as a number to call the set function with */
+ssize_t simple_attr_write(struct file *file, const char __user *buf,
+			  size_t len, loff_t *ppos)
+{
+	struct simple_attr *attr;
+	u64 val;
+	size_t size;
+	ssize_t ret;
+
+	attr = file->private_data;
+
+	if (!attr->set)
+		return -EACCES;
+
+	down(&attr->sem);
+	ret = -EFAULT;
+	size = min(sizeof(attr->set_buf) - 1, len);
+	if (copy_from_user(attr->set_buf, buf, size))
+		goto out;
+
+	ret = len; /* claim we got the whole input */
+	attr->set_buf[size] = '\0';
+	val = simple_strtol(attr->set_buf, NULL, 0);
+	attr->set(attr->data, val);
+out:
+	up(&attr->sem);
+	return ret;
+}
+
 EXPORT_SYMBOL(dcache_dir_close);
 EXPORT_SYMBOL(dcache_dir_lseek);
 EXPORT_SYMBOL(dcache_dir_open);
@@ -547,3 +644,7 @@
 EXPORT_SYMBOL(simple_transaction_get);
 EXPORT_SYMBOL(simple_transaction_read);
 EXPORT_SYMBOL(simple_transaction_release);
+EXPORT_SYMBOL_GPL(simple_attr_open);
+EXPORT_SYMBOL_GPL(simple_attr_close);
+EXPORT_SYMBOL_GPL(simple_attr_read);
+EXPORT_SYMBOL_GPL(simple_attr_write);
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index ef7103b..006bb9e 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -31,7 +31,7 @@
  * This is the representation of a blocked client lock.
  */
 struct nlm_wait {
-	struct nlm_wait *	b_next;		/* linked list */
+	struct list_head	b_list;		/* linked list */
 	wait_queue_head_t	b_wait;		/* where to wait on */
 	struct nlm_host *	b_host;
 	struct file_lock *	b_lock;		/* local file lock */
@@ -39,27 +39,54 @@
 	u32			b_status;	/* grant callback status */
 };
 
-static struct nlm_wait *	nlm_blocked;
+static LIST_HEAD(nlm_blocked);
+
+/*
+ * Queue up a lock for blocking so that the GRANTED request can see it
+ */
+int nlmclnt_prepare_block(struct nlm_rqst *req, struct nlm_host *host, struct file_lock *fl)
+{
+	struct nlm_wait *block;
+
+	BUG_ON(req->a_block != NULL);
+	block = kmalloc(sizeof(*block), GFP_KERNEL);
+	if (block == NULL)
+		return -ENOMEM;
+	block->b_host = host;
+	block->b_lock = fl;
+	init_waitqueue_head(&block->b_wait);
+	block->b_status = NLM_LCK_BLOCKED;
+
+	list_add(&block->b_list, &nlm_blocked);
+	req->a_block = block;
+
+	return 0;
+}
+
+void nlmclnt_finish_block(struct nlm_rqst *req)
+{
+	struct nlm_wait *block = req->a_block;
+
+	if (block == NULL)
+		return;
+	req->a_block = NULL;
+	list_del(&block->b_list);
+	kfree(block);
+}
 
 /*
  * Block on a lock
  */
-int
-nlmclnt_block(struct nlm_host *host, struct file_lock *fl, u32 *statp)
+long nlmclnt_block(struct nlm_rqst *req, long timeout)
 {
-	struct nlm_wait	block, **head;
-	int		err;
-	u32		pstate;
+	struct nlm_wait	*block = req->a_block;
+	long ret;
 
-	block.b_host   = host;
-	block.b_lock   = fl;
-	init_waitqueue_head(&block.b_wait);
-	block.b_status = NLM_LCK_BLOCKED;
-	block.b_next   = nlm_blocked;
-	nlm_blocked    = &block;
-
-	/* Remember pseudo nsm state */
-	pstate = host->h_state;
+	/* A borken server might ask us to block even if we didn't
+	 * request it. Just say no!
+	 */
+	if (!req->a_args.block)
+		return -EAGAIN;
 
 	/* Go to sleep waiting for GRANT callback. Some servers seem
 	 * to lose callbacks, however, so we're going to poll from
@@ -69,28 +96,16 @@
 	 * a 1 minute timeout would do. See the comment before
 	 * nlmclnt_lock for an explanation.
 	 */
-	sleep_on_timeout(&block.b_wait, 30*HZ);
+	ret = wait_event_interruptible_timeout(block->b_wait,
+			block->b_status != NLM_LCK_BLOCKED,
+			timeout);
 
-	for (head = &nlm_blocked; *head; head = &(*head)->b_next) {
-		if (*head == &block) {
-			*head = block.b_next;
-			break;
-		}
+	if (block->b_status != NLM_LCK_BLOCKED) {
+		req->a_res.status = block->b_status;
+		block->b_status = NLM_LCK_BLOCKED;
 	}
 
-	if (!signalled()) {
-		*statp = block.b_status;
-		return 0;
-	}
-
-	/* Okay, we were interrupted. Cancel the pending request
-	 * unless the server has rebooted.
-	 */
-	if (pstate == host->h_state && (err = nlmclnt_cancel(host, fl)) < 0)
-		printk(KERN_NOTICE
-			"lockd: CANCEL call failed (errno %d)\n", -err);
-
-	return -ERESTARTSYS;
+	return ret;
 }
 
 /*
@@ -100,27 +115,23 @@
 nlmclnt_grant(struct nlm_lock *lock)
 {
 	struct nlm_wait	*block;
+	u32 res = nlm_lck_denied;
 
 	/*
 	 * Look up blocked request based on arguments. 
 	 * Warning: must not use cookie to match it!
 	 */
-	for (block = nlm_blocked; block; block = block->b_next) {
-		if (nlm_compare_locks(block->b_lock, &lock->fl))
-			break;
+	list_for_each_entry(block, &nlm_blocked, b_list) {
+		if (nlm_compare_locks(block->b_lock, &lock->fl)) {
+			/* Alright, we found a lock. Set the return status
+			 * and wake up the caller
+			 */
+			block->b_status = NLM_LCK_GRANTED;
+			wake_up(&block->b_wait);
+			res = nlm_granted;
+		}
 	}
-
-	/* Ooops, no blocked request found. */
-	if (block == NULL)
-		return nlm_lck_denied;
-
-	/* Alright, we found the lock. Set the return status and
-	 * wake up the caller.
-	 */
-	block->b_status = NLM_LCK_GRANTED;
-	wake_up(&block->b_wait);
-
-	return nlm_granted;
+	return res;
 }
 
 /*
@@ -230,7 +241,7 @@
 	host->h_reclaiming = 0;
 
 	/* Now, wake up all processes that sleep on a blocked lock */
-	for (block = nlm_blocked; block; block = block->b_next) {
+	list_for_each_entry(block, &nlm_blocked, b_list) {
 		if (block->b_host == host) {
 			block->b_status = NLM_LCK_DENIED_GRACE_PERIOD;
 			wake_up(&block->b_wait);
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index a440761..14b3ce8 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -21,6 +21,7 @@
 
 #define NLMDBG_FACILITY		NLMDBG_CLIENT
 #define NLMCLNT_GRACE_WAIT	(5*HZ)
+#define NLMCLNT_POLL_TIMEOUT	(30*HZ)
 
 static int	nlmclnt_test(struct nlm_rqst *, struct file_lock *);
 static int	nlmclnt_lock(struct nlm_rqst *, struct file_lock *);
@@ -312,7 +313,7 @@
 	prepare_to_wait(queue, &wait, TASK_INTERRUPTIBLE);
 	if (!signalled ()) {
 		schedule_timeout(NLMCLNT_GRACE_WAIT);
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 		if (!signalled ())
 			status = 0;
 	}
@@ -553,7 +554,8 @@
 {
 	struct nlm_host	*host = req->a_host;
 	struct nlm_res	*resp = &req->a_res;
-	int		status;
+	long timeout;
+	int status;
 
 	if (!host->h_monitored && nsm_monitor(host) < 0) {
 		printk(KERN_NOTICE "lockd: failed to monitor %s\n",
@@ -562,15 +564,32 @@
 		goto out;
 	}
 
-	do {
-		if ((status = nlmclnt_call(req, NLMPROC_LOCK)) >= 0) {
-			if (resp->status != NLM_LCK_BLOCKED)
-				break;
-			status = nlmclnt_block(host, fl, &resp->status);
-		}
+	if (req->a_args.block) {
+		status = nlmclnt_prepare_block(req, host, fl);
 		if (status < 0)
 			goto out;
-	} while (resp->status == NLM_LCK_BLOCKED && req->a_args.block);
+	}
+	for(;;) {
+		status = nlmclnt_call(req, NLMPROC_LOCK);
+		if (status < 0)
+			goto out_unblock;
+		if (resp->status != NLM_LCK_BLOCKED)
+			break;
+		/* Wait on an NLM blocking lock */
+		timeout = nlmclnt_block(req, NLMCLNT_POLL_TIMEOUT);
+		/* Did a reclaimer thread notify us of a server reboot? */
+		if (resp->status ==  NLM_LCK_DENIED_GRACE_PERIOD)
+			continue;
+		if (resp->status != NLM_LCK_BLOCKED)
+			break;
+		if (timeout >= 0)
+			continue;
+		/* We were interrupted. Send a CANCEL request to the server
+		 * and exit
+		 */
+		status = (int)timeout;
+		goto out_unblock;
+	}
 
 	if (resp->status == NLM_LCK_GRANTED) {
 		fl->fl_u.nfs_fl.state = host->h_state;
@@ -579,6 +598,11 @@
 		do_vfs_lock(fl);
 	}
 	status = nlm_stat_to_errno(resp->status);
+out_unblock:
+	nlmclnt_finish_block(req);
+	/* Cancel the blocked request if it is still pending */
+	if (resp->status == NLM_LCK_BLOCKED)
+		nlmclnt_cancel(host, fl);
 out:
 	nlmclnt_release_lockargs(req);
 	return status;
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 52707c5..82c77df 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -189,17 +189,15 @@
 			goto forgetit;
 
 		xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout);
+		xprt->nocong = 1;	/* No congestion control for NLM */
+		xprt->resvport = 1;	/* NLM requires a reserved port */
 
 		/* Existing NLM servers accept AUTH_UNIX only */
 		clnt = rpc_create_client(xprt, host->h_name, &nlm_program,
 					host->h_version, RPC_AUTH_UNIX);
-		if (IS_ERR(clnt)) {
-			xprt_destroy(xprt);
+		if (IS_ERR(clnt))
 			goto forgetit;
-		}
 		clnt->cl_autobind = 1;	/* turn on pmap queries */
-		xprt->nocong = 1;	/* No congestion control for NLM */
-		xprt->resvport = 1;	/* NLM requires a reserved port */
 
 		host->h_rpcclnt = clnt;
 	}
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 6fc1beb..2d144ab 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -115,20 +115,19 @@
 	xprt = xprt_create_proto(IPPROTO_UDP, &sin, NULL);
 	if (IS_ERR(xprt))
 		return (struct rpc_clnt *)xprt;
+	xprt->resvport = 1;	/* NSM requires a reserved port */
 
 	clnt = rpc_create_client(xprt, "localhost",
 				&nsm_program, SM_VERSION,
 				RPC_AUTH_NULL);
 	if (IS_ERR(clnt))
-		goto out_destroy;
+		goto out_err;
 	clnt->cl_softrtry = 1;
 	clnt->cl_chatty   = 1;
 	clnt->cl_oneshot  = 1;
-	xprt->resvport = 1;	/* NSM requires a reserved port */
 	return clnt;
 
-out_destroy:
-	xprt_destroy(xprt);
+out_err:
 	return clnt;
 }
 
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index b82e470..6e24255 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -191,7 +191,9 @@
 		printk(KERN_DEBUG
 			"lockd: new process, skipping host shutdown\n");
 	wake_up(&lockd_exit);
-		
+
+	flush_signals(current);
+
 	/* Exit the RPC thread */
 	svc_exit_thread(rqstp);
 
diff --git a/fs/locks.c b/fs/locks.c
index 3fa6a7c..a0bc034 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1548,6 +1548,8 @@
 
 	if (filp->f_op && filp->f_op->lock) {
 		error = filp->f_op->lock(filp, F_GETLK, &file_lock);
+		if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
+			file_lock.fl_ops->fl_release_private(&file_lock);
 		if (error < 0)
 			goto out;
 		else
@@ -1690,6 +1692,8 @@
 
 	if (filp->f_op && filp->f_op->lock) {
 		error = filp->f_op->lock(filp, F_GETLK, &file_lock);
+		if (file_lock.fl_ops && file_lock.fl_ops->fl_release_private)
+			file_lock.fl_ops->fl_release_private(&file_lock);
 		if (error < 0)
 			goto out;
 		else
@@ -1873,6 +1877,8 @@
 			.fl_end = OFFSET_MAX,
 		};
 		filp->f_op->flock(filp, F_SETLKW, &fl);
+		if (fl.fl_ops && fl.fl_ops->fl_release_private)
+			fl.fl_ops->fl_release_private(&fl);
 	}
 
 	lock_kernel();
diff --git a/fs/namei.c b/fs/namei.c
index dd78f01..fa8df81 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -493,12 +493,21 @@
 	return PTR_ERR(link);
 }
 
-static inline int __do_follow_link(struct dentry *dentry, struct nameidata *nd)
+struct path {
+	struct vfsmount *mnt;
+	struct dentry *dentry;
+};
+
+static inline int __do_follow_link(struct path *path, struct nameidata *nd)
 {
 	int error;
+	struct dentry *dentry = path->dentry;
 
-	touch_atime(nd->mnt, dentry);
+	touch_atime(path->mnt, dentry);
 	nd_set_link(nd, NULL);
+
+	if (path->mnt == nd->mnt)
+		mntget(path->mnt);
 	error = dentry->d_inode->i_op->follow_link(dentry, nd);
 	if (!error) {
 		char *s = nd_get_link(nd);
@@ -507,6 +516,8 @@
 		if (dentry->d_inode->i_op->put_link)
 			dentry->d_inode->i_op->put_link(dentry, nd);
 	}
+	dput(dentry);
+	mntput(path->mnt);
 
 	return error;
 }
@@ -518,7 +529,7 @@
  * Without that kind of total limit, nasty chains of consecutive
  * symlinks can cause almost arbitrarily long lookups. 
  */
-static inline int do_follow_link(struct dentry *dentry, struct nameidata *nd)
+static inline int do_follow_link(struct path *path, struct nameidata *nd)
 {
 	int err = -ELOOP;
 	if (current->link_count >= MAX_NESTED_LINKS)
@@ -527,17 +538,20 @@
 		goto loop;
 	BUG_ON(nd->depth >= MAX_NESTED_LINKS);
 	cond_resched();
-	err = security_inode_follow_link(dentry, nd);
+	err = security_inode_follow_link(path->dentry, nd);
 	if (err)
 		goto loop;
 	current->link_count++;
 	current->total_link_count++;
 	nd->depth++;
-	err = __do_follow_link(dentry, nd);
+	err = __do_follow_link(path, nd);
 	current->link_count--;
 	nd->depth--;
 	return err;
 loop:
+	dput(path->dentry);
+	if (path->mnt != nd->mnt)
+		mntput(path->mnt);
 	path_release(nd);
 	return err;
 }
@@ -565,87 +579,91 @@
 /* no need for dcache_lock, as serialization is taken care in
  * namespace.c
  */
-static int follow_mount(struct vfsmount **mnt, struct dentry **dentry)
+static int __follow_mount(struct path *path)
 {
 	int res = 0;
-	while (d_mountpoint(*dentry)) {
-		struct vfsmount *mounted = lookup_mnt(*mnt, *dentry);
+	while (d_mountpoint(path->dentry)) {
+		struct vfsmount *mounted = lookup_mnt(path->mnt, path->dentry);
 		if (!mounted)
 			break;
-		mntput(*mnt);
-		*mnt = mounted;
-		dput(*dentry);
-		*dentry = dget(mounted->mnt_root);
+		dput(path->dentry);
+		if (res)
+			mntput(path->mnt);
+		path->mnt = mounted;
+		path->dentry = dget(mounted->mnt_root);
 		res = 1;
 	}
 	return res;
 }
 
+static void follow_mount(struct vfsmount **mnt, struct dentry **dentry)
+{
+	while (d_mountpoint(*dentry)) {
+		struct vfsmount *mounted = lookup_mnt(*mnt, *dentry);
+		if (!mounted)
+			break;
+		dput(*dentry);
+		mntput(*mnt);
+		*mnt = mounted;
+		*dentry = dget(mounted->mnt_root);
+	}
+}
+
 /* no need for dcache_lock, as serialization is taken care in
  * namespace.c
  */
-static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry)
+int follow_down(struct vfsmount **mnt, struct dentry **dentry)
 {
 	struct vfsmount *mounted;
 
 	mounted = lookup_mnt(*mnt, *dentry);
 	if (mounted) {
+		dput(*dentry);
 		mntput(*mnt);
 		*mnt = mounted;
-		dput(*dentry);
 		*dentry = dget(mounted->mnt_root);
 		return 1;
 	}
 	return 0;
 }
 
-int follow_down(struct vfsmount **mnt, struct dentry **dentry)
-{
-	return __follow_down(mnt,dentry);
-}
- 
-static inline void follow_dotdot(struct vfsmount **mnt, struct dentry **dentry)
+static inline void follow_dotdot(struct nameidata *nd)
 {
 	while(1) {
 		struct vfsmount *parent;
-		struct dentry *old = *dentry;
+		struct dentry *old = nd->dentry;
 
                 read_lock(&current->fs->lock);
-		if (*dentry == current->fs->root &&
-		    *mnt == current->fs->rootmnt) {
+		if (nd->dentry == current->fs->root &&
+		    nd->mnt == current->fs->rootmnt) {
                         read_unlock(&current->fs->lock);
 			break;
 		}
                 read_unlock(&current->fs->lock);
 		spin_lock(&dcache_lock);
-		if (*dentry != (*mnt)->mnt_root) {
-			*dentry = dget((*dentry)->d_parent);
+		if (nd->dentry != nd->mnt->mnt_root) {
+			nd->dentry = dget(nd->dentry->d_parent);
 			spin_unlock(&dcache_lock);
 			dput(old);
 			break;
 		}
 		spin_unlock(&dcache_lock);
 		spin_lock(&vfsmount_lock);
-		parent = (*mnt)->mnt_parent;
-		if (parent == *mnt) {
+		parent = nd->mnt->mnt_parent;
+		if (parent == nd->mnt) {
 			spin_unlock(&vfsmount_lock);
 			break;
 		}
 		mntget(parent);
-		*dentry = dget((*mnt)->mnt_mountpoint);
+		nd->dentry = dget(nd->mnt->mnt_mountpoint);
 		spin_unlock(&vfsmount_lock);
 		dput(old);
-		mntput(*mnt);
-		*mnt = parent;
+		mntput(nd->mnt);
+		nd->mnt = parent;
 	}
-	follow_mount(mnt, dentry);
+	follow_mount(&nd->mnt, &nd->dentry);
 }
 
-struct path {
-	struct vfsmount *mnt;
-	struct dentry *dentry;
-};
-
 /*
  *  It's more convoluted than I'd like it to be, but... it's still fairly
  *  small and for now I'd prefer to have fast path as straight as possible.
@@ -664,6 +682,7 @@
 done:
 	path->mnt = mnt;
 	path->dentry = dentry;
+	__follow_mount(path);
 	return 0;
 
 need_lookup:
@@ -751,7 +770,7 @@
 			case 2:	
 				if (this.name[1] != '.')
 					break;
-				follow_dotdot(&nd->mnt, &nd->dentry);
+				follow_dotdot(nd);
 				inode = nd->dentry->d_inode;
 				/* fallthrough */
 			case 1:
@@ -771,8 +790,6 @@
 		err = do_lookup(nd, &this, &next);
 		if (err)
 			break;
-		/* Check mountpoints.. */
-		follow_mount(&next.mnt, &next.dentry);
 
 		err = -ENOENT;
 		inode = next.dentry->d_inode;
@@ -783,10 +800,7 @@
 			goto out_dput;
 
 		if (inode->i_op->follow_link) {
-			mntget(next.mnt);
-			err = do_follow_link(next.dentry, nd);
-			dput(next.dentry);
-			mntput(next.mnt);
+			err = do_follow_link(&next, nd);
 			if (err)
 				goto return_err;
 			err = -ENOENT;
@@ -798,6 +812,8 @@
 				break;
 		} else {
 			dput(nd->dentry);
+			if (nd->mnt != next.mnt)
+				mntput(nd->mnt);
 			nd->mnt = next.mnt;
 			nd->dentry = next.dentry;
 		}
@@ -819,7 +835,7 @@
 			case 2:	
 				if (this.name[1] != '.')
 					break;
-				follow_dotdot(&nd->mnt, &nd->dentry);
+				follow_dotdot(nd);
 				inode = nd->dentry->d_inode;
 				/* fallthrough */
 			case 1:
@@ -833,19 +849,17 @@
 		err = do_lookup(nd, &this, &next);
 		if (err)
 			break;
-		follow_mount(&next.mnt, &next.dentry);
 		inode = next.dentry->d_inode;
 		if ((lookup_flags & LOOKUP_FOLLOW)
 		    && inode && inode->i_op && inode->i_op->follow_link) {
-			mntget(next.mnt);
-			err = do_follow_link(next.dentry, nd);
-			dput(next.dentry);
-			mntput(next.mnt);
+			err = do_follow_link(&next, nd);
 			if (err)
 				goto return_err;
 			inode = nd->dentry->d_inode;
 		} else {
 			dput(nd->dentry);
+			if (nd->mnt != next.mnt)
+				mntput(nd->mnt);
 			nd->mnt = next.mnt;
 			nd->dentry = next.dentry;
 		}
@@ -885,6 +899,8 @@
 		return 0;
 out_dput:
 		dput(next.dentry);
+		if (nd->mnt != next.mnt)
+			mntput(next.mnt);
 		break;
 	}
 	path_release(nd);
@@ -1398,7 +1414,7 @@
 int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
 {
 	int acc_mode, error = 0;
-	struct dentry *dentry;
+	struct path path;
 	struct dentry *dir;
 	int count = 0;
 
@@ -1442,23 +1458,24 @@
 	dir = nd->dentry;
 	nd->flags &= ~LOOKUP_PARENT;
 	down(&dir->d_inode->i_sem);
-	dentry = __lookup_hash(&nd->last, nd->dentry, nd);
+	path.dentry = __lookup_hash(&nd->last, nd->dentry, nd);
+	path.mnt = nd->mnt;
 
 do_last:
-	error = PTR_ERR(dentry);
-	if (IS_ERR(dentry)) {
+	error = PTR_ERR(path.dentry);
+	if (IS_ERR(path.dentry)) {
 		up(&dir->d_inode->i_sem);
 		goto exit;
 	}
 
 	/* Negative dentry, just create the file */
-	if (!dentry->d_inode) {
+	if (!path.dentry->d_inode) {
 		if (!IS_POSIXACL(dir->d_inode))
 			mode &= ~current->fs->umask;
-		error = vfs_create(dir->d_inode, dentry, mode, nd);
+		error = vfs_create(dir->d_inode, path.dentry, mode, nd);
 		up(&dir->d_inode->i_sem);
 		dput(nd->dentry);
-		nd->dentry = dentry;
+		nd->dentry = path.dentry;
 		if (error)
 			goto exit;
 		/* Don't check for write permission, don't truncate */
@@ -1476,22 +1493,24 @@
 	if (flag & O_EXCL)
 		goto exit_dput;
 
-	if (d_mountpoint(dentry)) {
+	if (__follow_mount(&path)) {
 		error = -ELOOP;
 		if (flag & O_NOFOLLOW)
 			goto exit_dput;
-		while (__follow_down(&nd->mnt,&dentry) && d_mountpoint(dentry));
 	}
 	error = -ENOENT;
-	if (!dentry->d_inode)
+	if (!path.dentry->d_inode)
 		goto exit_dput;
-	if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link)
+	if (path.dentry->d_inode->i_op && path.dentry->d_inode->i_op->follow_link)
 		goto do_link;
 
 	dput(nd->dentry);
-	nd->dentry = dentry;
+	nd->dentry = path.dentry;
+	if (nd->mnt != path.mnt)
+		mntput(nd->mnt);
+	nd->mnt = path.mnt;
 	error = -EISDIR;
-	if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode))
+	if (path.dentry->d_inode && S_ISDIR(path.dentry->d_inode->i_mode))
 		goto exit;
 ok:
 	error = may_open(nd, acc_mode, flag);
@@ -1500,7 +1519,9 @@
 	return 0;
 
 exit_dput:
-	dput(dentry);
+	dput(path.dentry);
+	if (nd->mnt != path.mnt)
+		mntput(path.mnt);
 exit:
 	path_release(nd);
 	return error;
@@ -1520,18 +1541,15 @@
 	 * are done. Procfs-like symlinks just set LAST_BIND.
 	 */
 	nd->flags |= LOOKUP_PARENT;
-	error = security_inode_follow_link(dentry, nd);
+	error = security_inode_follow_link(path.dentry, nd);
 	if (error)
 		goto exit_dput;
-	error = __do_follow_link(dentry, nd);
-	dput(dentry);
+	error = __do_follow_link(&path, nd);
 	if (error)
 		return error;
 	nd->flags &= ~LOOKUP_PARENT;
-	if (nd->last_type == LAST_BIND) {
-		dentry = nd->dentry;
+	if (nd->last_type == LAST_BIND)
 		goto ok;
-	}
 	error = -EISDIR;
 	if (nd->last_type != LAST_NORM)
 		goto exit;
@@ -1546,7 +1564,8 @@
 	}
 	dir = nd->dentry;
 	down(&dir->d_inode->i_sem);
-	dentry = __lookup_hash(&nd->last, nd->dentry, nd);
+	path.dentry = __lookup_hash(&nd->last, nd->dentry, nd);
+	path.mnt = nd->mnt;
 	putname(nd->last.name);
 	goto do_last;
 }
@@ -1558,19 +1577,35 @@
  *
  * Simple function to lookup and return a dentry and create it
  * if it doesn't exist.  Is SMP-safe.
+ *
+ * Returns with nd->dentry->d_inode->i_sem locked.
  */
 struct dentry *lookup_create(struct nameidata *nd, int is_dir)
 {
-	struct dentry *dentry;
+	struct dentry *dentry = ERR_PTR(-EEXIST);
 
 	down(&nd->dentry->d_inode->i_sem);
-	dentry = ERR_PTR(-EEXIST);
+	/*
+	 * Yucky last component or no last component at all?
+	 * (foo/., foo/.., /////)
+	 */
 	if (nd->last_type != LAST_NORM)
 		goto fail;
 	nd->flags &= ~LOOKUP_PARENT;
+
+	/*
+	 * Do the final lookup.
+	 */
 	dentry = lookup_hash(&nd->last, nd->dentry);
 	if (IS_ERR(dentry))
 		goto fail;
+
+	/*
+	 * Special case - lookup gave negative, but... we had foo/bar/
+	 * From the vfs_mknod() POV we just have a negative dentry -
+	 * all is fine. Let's be bastards - you had / on the end, you've
+	 * been asking for (non-existent) directory. -ENOENT for you.
+	 */
 	if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)
 		goto enoent;
 	return dentry;
diff --git a/fs/namespace.c b/fs/namespace.c
index 3b93e5d..208c079 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -337,7 +337,7 @@
 
 EXPORT_SYMBOL(may_umount);
 
-void umount_tree(struct vfsmount *mnt)
+static void umount_tree(struct vfsmount *mnt)
 {
 	struct vfsmount *p;
 	LIST_HEAD(kill);
diff --git a/fs/ncpfs/dir.c b/fs/ncpfs/dir.c
index 2dc2d86..a9f7a8a 100644
--- a/fs/ncpfs/dir.c
+++ b/fs/ncpfs/dir.c
@@ -705,18 +705,6 @@
 		DPRINTK("ncp_do_readdir: init failed, err=%d\n", err);
 		return;
 	}
-#ifdef USE_OLD_SLOW_DIRECTORY_LISTING
-	for (;;) {
-		err = ncp_search_for_file_or_subdir(server, &seq, &entry.i);
-		if (err) {
-			DPRINTK("ncp_do_readdir: search failed, err=%d\n", err);
-			break;
-		}
-		entry.volume = entry.i.volNumber;
-		if (!ncp_fill_cache(filp, dirent, filldir, ctl, &entry))
-			break;
-	}
-#else
 	/* We MUST NOT use server->buffer_size handshaked with server if we are
 	   using UDP, as for UDP server uses max. buffer size determined by
 	   MTU, and for TCP server uses hardwired value 65KB (== 66560 bytes). 
@@ -754,7 +742,6 @@
 		}
 	} while (more);
 	vfree(buf);
-#endif
 	return;
 }
 
diff --git a/fs/ncpfs/ncplib_kernel.c b/fs/ncpfs/ncplib_kernel.c
index e4eb5ed..c755e18 100644
--- a/fs/ncpfs/ncplib_kernel.c
+++ b/fs/ncpfs/ncplib_kernel.c
@@ -845,46 +845,6 @@
 	return result;
 }
 
-/* Search for everything */
-int ncp_search_for_file_or_subdir(struct ncp_server *server,
-				  struct nw_search_sequence *seq,
-				  struct nw_info_struct *target)
-{
-	int result;
-
-	ncp_init_request(server);
-	ncp_add_byte(server, 3);	/* subfunction */
-	ncp_add_byte(server, server->name_space[seq->volNumber]);
-	ncp_add_byte(server, 0);	/* data stream (???) */
-	ncp_add_word(server, cpu_to_le16(0x8006));	/* Search attribs */
-	ncp_add_dword(server, RIM_ALL);		/* return info mask */
-	ncp_add_mem(server, seq, 9);
-#ifdef CONFIG_NCPFS_NFS_NS
-	if (server->name_space[seq->volNumber] == NW_NS_NFS) {
-		ncp_add_byte(server, 0);	/* 0 byte pattern */
-	} else 
-#endif
-	{
-		ncp_add_byte(server, 2);	/* 2 byte pattern */
-		ncp_add_byte(server, 0xff);	/* following is a wildcard */
-		ncp_add_byte(server, '*');
-	}
-	
-	if ((result = ncp_request(server, 87)) != 0)
-		goto out;
-	memcpy(seq, ncp_reply_data(server, 0), sizeof(*seq));
-	ncp_extract_file_info(ncp_reply_data(server, 10), target);
-
-	ncp_unlock_server(server);
-	
-	result = ncp_obtain_nfs_info(server, target);
-	return result;
-
-out:
-	ncp_unlock_server(server);
-	return result;
-}
-
 int ncp_search_for_fileset(struct ncp_server *server,
 			   struct nw_search_sequence *seq,
 			   int* more,
diff --git a/fs/ncpfs/ncplib_kernel.h b/fs/ncpfs/ncplib_kernel.h
index 05ec2e9..9e4dc30 100644
--- a/fs/ncpfs/ncplib_kernel.h
+++ b/fs/ncpfs/ncplib_kernel.h
@@ -87,9 +87,6 @@
 
 int ncp_initialize_search(struct ncp_server *, struct inode *,
 		      struct nw_search_sequence *target);
-int ncp_search_for_file_or_subdir(struct ncp_server *server,
-			      struct nw_search_sequence *seq,
-			      struct nw_info_struct *target);
 int ncp_search_for_fileset(struct ncp_server *server,
 			   struct nw_search_sequence *seq,
 			   int* more, int* cnt,
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index b4baa03..8b3bb71 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -8,6 +8,7 @@
 			   proc.o read.o symlink.o unlink.o write.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
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 560d617..f2ca782 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -14,6 +14,7 @@
 #include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/svcsock.h>
 #include <linux/nfs_fs.h>
+#include "nfs4_fs.h"
 #include "callback.h"
 
 #define NFSDBG_FACILITY NFSDBG_CALLBACK
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index ece27e4..65f1e19 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -8,6 +8,7 @@
 #include <linux/config.h>
 #include <linux/nfs4.h>
 #include <linux/nfs_fs.h>
+#include "nfs4_fs.h"
 #include "callback.h"
 #include "delegation.h"
 
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index d271df9..7c33b9a 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -10,6 +10,7 @@
 #include <linux/sunrpc/svc.h>
 #include <linux/nfs4.h>
 #include <linux/nfs_fs.h>
+#include "nfs4_fs.h"
 #include "callback.h"
 
 #define CB_OP_TAGLEN_MAXSZ	(512)
@@ -410,7 +411,6 @@
 	xdr_init_decode(&xdr_in, &rqstp->rq_arg, rqstp->rq_arg.head[0].iov_base);
 
 	p = (uint32_t*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len);
-	rqstp->rq_res.head[0].iov_len = PAGE_SIZE;
 	xdr_init_encode(&xdr_out, &rqstp->rq_res, p);
 
 	decode_compound_hdr_arg(&xdr_in, &hdr_arg);
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 5b9c60f..d7f7eb6 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -16,6 +16,7 @@
 #include <linux/nfs_fs.h>
 #include <linux/nfs_xdr.h>
 
+#include "nfs4_fs.h"
 #include "delegation.h"
 
 static struct nfs_delegation *nfs_alloc_delegation(void)
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 73f96ac..b38a57e 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -32,6 +32,7 @@
 #include <linux/smp_lock.h>
 #include <linux/namei.h>
 
+#include "nfs4_fs.h"
 #include "delegation.h"
 
 #define NFS_PARANOIA 1
@@ -50,8 +51,10 @@
 static int nfs_rename(struct inode *, struct dentry *,
 		      struct inode *, struct dentry *);
 static int nfs_fsync_dir(struct file *, struct dentry *, int);
+static loff_t nfs_llseek_dir(struct file *, loff_t, int);
 
 struct file_operations nfs_dir_operations = {
+	.llseek		= nfs_llseek_dir,
 	.read		= generic_read_dir,
 	.readdir	= nfs_readdir,
 	.open		= nfs_opendir,
@@ -74,6 +77,27 @@
 	.setattr	= nfs_setattr,
 };
 
+#ifdef CONFIG_NFS_V3
+struct inode_operations nfs3_dir_inode_operations = {
+	.create		= nfs_create,
+	.lookup		= nfs_lookup,
+	.link		= nfs_link,
+	.unlink		= nfs_unlink,
+	.symlink	= nfs_symlink,
+	.mkdir		= nfs_mkdir,
+	.rmdir		= nfs_rmdir,
+	.mknod		= nfs_mknod,
+	.rename		= nfs_rename,
+	.permission	= nfs_permission,
+	.getattr	= nfs_getattr,
+	.setattr	= nfs_setattr,
+	.listxattr	= nfs3_listxattr,
+	.getxattr	= nfs3_getxattr,
+	.setxattr	= nfs3_setxattr,
+	.removexattr	= nfs3_removexattr,
+};
+#endif  /* CONFIG_NFS_V3 */
+
 #ifdef CONFIG_NFS_V4
 
 static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *);
@@ -90,6 +114,9 @@
 	.permission	= nfs_permission,
 	.getattr	= nfs_getattr,
 	.setattr	= nfs_setattr,
+	.getxattr       = nfs4_getxattr,
+	.setxattr       = nfs4_setxattr,
+	.listxattr      = nfs4_listxattr,
 };
 
 #endif /* CONFIG_NFS_V4 */
@@ -116,7 +143,8 @@
 	struct page	*page;
 	unsigned long	page_index;
 	u32		*ptr;
-	u64		target;
+	u64		*dir_cookie;
+	loff_t		current_index;
 	struct nfs_entry *entry;
 	decode_dirent_t	decode;
 	int		plus;
@@ -164,12 +192,10 @@
 	NFS_FLAGS(inode) |= NFS_INO_INVALID_ATIME;
 	/* Ensure consistent page alignment of the data.
 	 * Note: assumes we have exclusive access to this mapping either
-	 *	 throught inode->i_sem or some other mechanism.
+	 *	 through inode->i_sem or some other mechanism.
 	 */
-	if (page->index == 0) {
-		invalidate_inode_pages(inode->i_mapping);
-		NFS_I(inode)->readdir_timestamp = timestamp;
-	}
+	if (page->index == 0)
+		invalidate_inode_pages2_range(inode->i_mapping, PAGE_CACHE_SIZE, -1);
 	unlock_page(page);
 	return 0;
  error:
@@ -202,22 +228,22 @@
 
 /*
  * Given a pointer to a buffer that has already been filled by a call
- * to readdir, find the next entry.
+ * to readdir, find the next entry with cookie '*desc->dir_cookie'.
  *
  * If the end of the buffer has been reached, return -EAGAIN, if not,
  * return the offset within the buffer of the next entry to be
  * read.
  */
 static inline
-int find_dirent(nfs_readdir_descriptor_t *desc, struct page *page)
+int find_dirent(nfs_readdir_descriptor_t *desc)
 {
 	struct nfs_entry *entry = desc->entry;
 	int		loop_count = 0,
 			status;
 
 	while((status = dir_decode(desc)) == 0) {
-		dfprintk(VFS, "NFS: found cookie %Lu\n", (long long)entry->cookie);
-		if (entry->prev_cookie == desc->target)
+		dfprintk(VFS, "NFS: found cookie %Lu\n", (unsigned long long)entry->cookie);
+		if (entry->prev_cookie == *desc->dir_cookie)
 			break;
 		if (loop_count++ > 200) {
 			loop_count = 0;
@@ -229,8 +255,44 @@
 }
 
 /*
- * Find the given page, and call find_dirent() in order to try to
- * return the next entry.
+ * Given a pointer to a buffer that has already been filled by a call
+ * to readdir, find the entry at offset 'desc->file->f_pos'.
+ *
+ * If the end of the buffer has been reached, return -EAGAIN, if not,
+ * return the offset within the buffer of the next entry to be
+ * read.
+ */
+static inline
+int find_dirent_index(nfs_readdir_descriptor_t *desc)
+{
+	struct nfs_entry *entry = desc->entry;
+	int		loop_count = 0,
+			status;
+
+	for(;;) {
+		status = dir_decode(desc);
+		if (status)
+			break;
+
+		dfprintk(VFS, "NFS: found cookie %Lu at index %Ld\n", (unsigned long long)entry->cookie, desc->current_index);
+
+		if (desc->file->f_pos == desc->current_index) {
+			*desc->dir_cookie = entry->cookie;
+			break;
+		}
+		desc->current_index++;
+		if (loop_count++ > 200) {
+			loop_count = 0;
+			schedule();
+		}
+	}
+	dfprintk(VFS, "NFS: find_dirent_index() returns %d\n", status);
+	return status;
+}
+
+/*
+ * Find the given page, and call find_dirent() or find_dirent_index in
+ * order to try to return the next entry.
  */
 static inline
 int find_dirent_page(nfs_readdir_descriptor_t *desc)
@@ -253,7 +315,10 @@
 	/* NOTE: Someone else may have changed the READDIRPLUS flag */
 	desc->page = page;
 	desc->ptr = kmap(page);		/* matching kunmap in nfs_do_filldir */
-	status = find_dirent(desc, page);
+	if (*desc->dir_cookie != 0)
+		status = find_dirent(desc);
+	else
+		status = find_dirent_index(desc);
 	if (status < 0)
 		dir_page_release(desc);
  out:
@@ -268,7 +333,8 @@
  * Recurse through the page cache pages, and return a
  * filled nfs_entry structure of the next directory entry if possible.
  *
- * The target for the search is 'desc->target'.
+ * The target for the search is '*desc->dir_cookie' if non-0,
+ * 'desc->file->f_pos' otherwise
  */
 static inline
 int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
@@ -276,7 +342,16 @@
 	int		loop_count = 0;
 	int		res;
 
-	dfprintk(VFS, "NFS: readdir_search_pagecache() searching for cookie %Lu\n", (long long)desc->target);
+	/* Always search-by-index from the beginning of the cache */
+	if (*desc->dir_cookie == 0) {
+		dfprintk(VFS, "NFS: readdir_search_pagecache() searching for offset %Ld\n", (long long)desc->file->f_pos);
+		desc->page_index = 0;
+		desc->entry->cookie = desc->entry->prev_cookie = 0;
+		desc->entry->eof = 0;
+		desc->current_index = 0;
+	} else
+		dfprintk(VFS, "NFS: readdir_search_pagecache() searching for cookie %Lu\n", (unsigned long long)*desc->dir_cookie);
+
 	for (;;) {
 		res = find_dirent_page(desc);
 		if (res != -EAGAIN)
@@ -313,7 +388,7 @@
 	int		loop_count = 0,
 			res;
 
-	dfprintk(VFS, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n", (long long)desc->target);
+	dfprintk(VFS, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n", (long long)entry->cookie);
 
 	for(;;) {
 		unsigned d_type = DT_UNKNOWN;
@@ -333,10 +408,11 @@
 		}
 
 		res = filldir(dirent, entry->name, entry->len, 
-			      entry->prev_cookie, fileid, d_type);
+			      file->f_pos, fileid, d_type);
 		if (res < 0)
 			break;
-		file->f_pos = desc->target = entry->cookie;
+		file->f_pos++;
+		*desc->dir_cookie = entry->cookie;
 		if (dir_decode(desc) != 0) {
 			desc->page_index ++;
 			break;
@@ -349,7 +425,7 @@
 	dir_page_release(desc);
 	if (dentry != NULL)
 		dput(dentry);
-	dfprintk(VFS, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", (long long)desc->target, res);
+	dfprintk(VFS, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", (unsigned long long)*desc->dir_cookie, res);
 	return res;
 }
 
@@ -375,14 +451,14 @@
 	struct page	*page = NULL;
 	int		status;
 
-	dfprintk(VFS, "NFS: uncached_readdir() searching for cookie %Lu\n", (long long)desc->target);
+	dfprintk(VFS, "NFS: uncached_readdir() searching for cookie %Lu\n", (unsigned long long)*desc->dir_cookie);
 
 	page = alloc_page(GFP_HIGHUSER);
 	if (!page) {
 		status = -ENOMEM;
 		goto out;
 	}
-	desc->error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, desc->target,
+	desc->error = NFS_PROTO(inode)->readdir(file->f_dentry, cred, *desc->dir_cookie,
 						page,
 						NFS_SERVER(inode)->dtsize,
 						desc->plus);
@@ -391,7 +467,7 @@
 	desc->ptr = kmap(page);		/* matching kunmap in nfs_do_filldir */
 	if (desc->error >= 0) {
 		if ((status = dir_decode(desc)) == 0)
-			desc->entry->prev_cookie = desc->target;
+			desc->entry->prev_cookie = *desc->dir_cookie;
 	} else
 		status = -EIO;
 	if (status < 0)
@@ -412,8 +488,9 @@
 	goto out;
 }
 
-/* The file offset position is now represented as a true offset into the
- * page cache as is the case in most of the other filesystems.
+/* The file offset position represents the dirent entry number.  A
+   last cookie cache takes care of the common case of reading the
+   whole directory.
  */
 static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
@@ -435,15 +512,15 @@
 	}
 
 	/*
-	 * filp->f_pos points to the file offset in the page cache.
-	 * but if the cache has meanwhile been zapped, we need to
-	 * read from the last dirent to revalidate f_pos
-	 * itself.
+	 * filp->f_pos points to the dirent entry number.
+	 * *desc->dir_cookie has the cookie for the next entry. We have
+	 * to either find the entry with the appropriate number or
+	 * revalidate the cookie.
 	 */
 	memset(desc, 0, sizeof(*desc));
 
 	desc->file = filp;
-	desc->target = filp->f_pos;
+	desc->dir_cookie = &((struct nfs_open_context *)filp->private_data)->dir_cookie;
 	desc->decode = NFS_PROTO(inode)->decode_dirent;
 	desc->plus = NFS_USE_READDIRPLUS(inode);
 
@@ -455,9 +532,10 @@
 
 	while(!desc->entry->eof) {
 		res = readdir_search_pagecache(desc);
+
 		if (res == -EBADCOOKIE) {
 			/* This means either end of directory */
-			if (desc->entry->cookie != desc->target) {
+			if (*desc->dir_cookie && desc->entry->cookie != *desc->dir_cookie) {
 				/* Or that the server has 'lost' a cookie */
 				res = uncached_readdir(desc, dirent, filldir);
 				if (res >= 0)
@@ -490,6 +568,28 @@
 	return 0;
 }
 
+loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int origin)
+{
+	down(&filp->f_dentry->d_inode->i_sem);
+	switch (origin) {
+		case 1:
+			offset += filp->f_pos;
+		case 0:
+			if (offset >= 0)
+				break;
+		default:
+			offset = -EINVAL;
+			goto out;
+	}
+	if (offset != filp->f_pos) {
+		filp->f_pos = offset;
+		((struct nfs_open_context *)filp->private_data)->dir_cookie = 0;
+	}
+out:
+	up(&filp->f_dentry->d_inode->i_sem);
+	return offset;
+}
+
 /*
  * All directory operations under NFS are synchronous, so fsync()
  * is a dummy operation.
@@ -528,19 +628,39 @@
 	dentry->d_time = jiffies;
 }
 
+/*
+ * Return the intent data that applies to this particular path component
+ *
+ * Note that the current set of intents only apply to the very last
+ * component of the path.
+ * We check for this using LOOKUP_CONTINUE and LOOKUP_PARENT.
+ */
+static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd, unsigned int mask)
+{
+	if (nd->flags & (LOOKUP_CONTINUE|LOOKUP_PARENT))
+		return 0;
+	return nd->flags & mask;
+}
+
+/*
+ * Inode and filehandle revalidation for lookups.
+ *
+ * We force revalidation in the cases where the VFS sets LOOKUP_REVAL,
+ * or if the intent information indicates that we're about to open this
+ * particular file and the "nocto" mount flag is not set.
+ *
+ */
 static inline
 int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd)
 {
 	struct nfs_server *server = NFS_SERVER(inode);
 
 	if (nd != NULL) {
-		int ndflags = nd->flags;
 		/* VFS wants an on-the-wire revalidation */
-		if (ndflags & LOOKUP_REVAL)
+		if (nd->flags & LOOKUP_REVAL)
 			goto out_force;
 		/* This is an open(2) */
-		if ((ndflags & LOOKUP_OPEN) &&
-				!(ndflags & LOOKUP_CONTINUE) &&
+		if (nfs_lookup_check_intent(nd, LOOKUP_OPEN) != 0 &&
 				!(server->flags & NFS_MOUNT_NOCTO))
 			goto out_force;
 	}
@@ -560,12 +680,8 @@
 int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
 		       struct nameidata *nd)
 {
-	int ndflags = 0;
-
-	if (nd)
-		ndflags = nd->flags;
 	/* Don't revalidate a negative dentry if we're creating a new file */
-	if ((ndflags & LOOKUP_CREATE) && !(ndflags & LOOKUP_CONTINUE))
+	if (nd != NULL && nfs_lookup_check_intent(nd, LOOKUP_CREATE) != 0)
 		return 0;
 	return !nfs_check_verifier(dir, dentry);
 }
@@ -700,12 +816,16 @@
 	.d_iput		= nfs_dentry_iput,
 };
 
+/*
+ * Use intent information to check whether or not we're going to do
+ * an O_EXCL create using this path component.
+ */
 static inline
 int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd)
 {
 	if (NFS_PROTO(dir)->version == 2)
 		return 0;
-	if (!nd || (nd->flags & LOOKUP_CONTINUE) || !(nd->flags & LOOKUP_CREATE))
+	if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_CREATE) == 0)
 		return 0;
 	return (nd->intent.open.flags & O_EXCL) != 0;
 }
@@ -772,12 +892,13 @@
 	.d_iput		= nfs_dentry_iput,
 };
 
+/*
+ * Use intent information to determine whether we need to substitute
+ * the NFSv4-style stateful OPEN for the LOOKUP call
+ */
 static int is_atomic_open(struct inode *dir, struct nameidata *nd)
 {
-	if (!nd)
-		return 0;
-	/* Check that we are indeed trying to open this file */
-	if ((nd->flags & LOOKUP_CONTINUE) || !(nd->flags & LOOKUP_OPEN))
+	if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_OPEN) == 0)
 		return 0;
 	/* NFS does not (yet) have a stateful open for directories */
 	if (nd->flags & LOOKUP_DIRECTORY)
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 68df803..6537f2c 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -517,7 +517,7 @@
 	result = tot_bytes;
 
 out:
-	nfs_end_data_update_defer(inode);
+	nfs_end_data_update(inode);
 	nfs_writedata_free(wdata);
 	return result;
 
@@ -751,11 +751,6 @@
 	retval = -EFAULT;
 	if (!access_ok(VERIFY_READ, iov.iov_base, iov.iov_len))
 		goto out;
-        if (file->f_error) {
-                retval = file->f_error;
-                file->f_error = 0;
-                goto out;
-        }
 	retval = -EFBIG;
 	if (limit != RLIM_INFINITY) {
 		if (pos >= limit) {
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index f06eee6..5621ba9 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -37,6 +37,7 @@
 
 static int nfs_file_open(struct inode *, struct file *);
 static int nfs_file_release(struct inode *, struct file *);
+static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin);
 static int  nfs_file_mmap(struct file *, struct vm_area_struct *);
 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);
@@ -48,7 +49,7 @@
 static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl);
 
 struct file_operations nfs_file_operations = {
-	.llseek		= remote_llseek,
+	.llseek		= nfs_file_llseek,
 	.read		= do_sync_read,
 	.write		= do_sync_write,
 	.aio_read		= nfs_file_read,
@@ -70,6 +71,18 @@
 	.setattr	= nfs_setattr,
 };
 
+#ifdef CONFIG_NFS_V3
+struct inode_operations nfs3_file_inode_operations = {
+	.permission	= nfs_permission,
+	.getattr	= nfs_getattr,
+	.setattr	= nfs_setattr,
+	.listxattr	= nfs3_listxattr,
+	.getxattr	= nfs3_getxattr,
+	.setxattr	= nfs3_setxattr,
+	.removexattr	= nfs3_removexattr,
+};
+#endif  /* CONFIG_NFS_v3 */
+
 /* Hack for future NFS swap support */
 #ifndef IS_SWAPFILE
 # define IS_SWAPFILE(inode)	(0)
@@ -114,6 +127,61 @@
 	return NFS_PROTO(inode)->file_release(inode, filp);
 }
 
+/**
+ * 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)
+{
+	int retval = 0;
+
+	if ((NFS_FLAGS(inode) & NFS_INO_REVAL_PAGECACHE) || 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
+ *
+ * Revalidates the file length. This is basically a wrapper around
+ * nfs_revalidate_inode() that takes into account the fact that we may
+ * have cached writes (in which case we don't care about the server's
+ * idea of what the file length is), or O_DIRECT (in which case we
+ * shouldn't trust the cache).
+ */
+static int nfs_revalidate_file_size(struct inode *inode, struct file *filp)
+{
+	struct nfs_server *server = NFS_SERVER(inode);
+	struct nfs_inode *nfsi = NFS_I(inode);
+
+	if (server->flags & NFS_MOUNT_NOAC)
+		goto force_reval;
+	if (filp->f_flags & O_DIRECT)
+		goto force_reval;
+	if (nfsi->npages != 0)
+		return 0;
+	if (!(NFS_FLAGS(inode) & NFS_INO_REVAL_PAGECACHE) && !nfs_attribute_timeout(inode))
+		return 0;
+force_reval:
+	return __nfs_revalidate_inode(server, inode);
+}
+
+static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin)
+{
+	/* origin == SEEK_END => we must revalidate the cached file length */
+	if (origin == 2) {
+		struct inode *inode = filp->f_mapping->host;
+		int retval = nfs_revalidate_file_size(inode, filp);
+		if (retval < 0)
+			return (loff_t)retval;
+	}
+	return remote_llseek(filp, offset, origin);
+}
+
 /*
  * Flush all dirty pages, and check for write errors.
  *
@@ -158,7 +226,7 @@
 		dentry->d_parent->d_name.name, dentry->d_name.name,
 		(unsigned long) count, (unsigned long) pos);
 
-	result = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+	result = nfs_revalidate_file(inode, iocb->ki_filp);
 	if (!result)
 		result = generic_file_aio_read(iocb, buf, count, pos);
 	return result;
@@ -176,7 +244,7 @@
 		dentry->d_parent->d_name.name, dentry->d_name.name,
 		(unsigned long) count, (unsigned long long) *ppos);
 
-	res = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+	res = nfs_revalidate_file(inode, filp);
 	if (!res)
 		res = generic_file_sendfile(filp, ppos, count, actor, target);
 	return res;
@@ -192,7 +260,7 @@
 	dfprintk(VFS, "nfs: mmap(%s/%s)\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name);
 
-	status = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+	status = nfs_revalidate_file(inode, file);
 	if (!status)
 		status = generic_file_mmap(file, vma);
 	return status;
@@ -281,9 +349,15 @@
 	result = -EBUSY;
 	if (IS_SWAPFILE(inode))
 		goto out_swapfile;
-	result = nfs_revalidate_inode(NFS_SERVER(inode), inode);
-	if (result)
-		goto out;
+	/*
+	 * O_APPEND implies that we must revalidate the file length.
+	 */
+	if (iocb->ki_filp->f_flags & O_APPEND) {
+		result = nfs_revalidate_file_size(inode, iocb->ki_filp);
+		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 87f4f9a..ffb8df9 100644
--- a/fs/nfs/idmap.c
+++ b/fs/nfs/idmap.c
@@ -50,6 +50,7 @@
 #include <linux/nfs_fs.h>
 
 #include <linux/nfs_idmap.h>
+#include "nfs4_fs.h"
 
 #define IDMAP_HASH_SZ          128
 
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index f2317f3..4845911 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -39,6 +39,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
+#include "nfs4_fs.h"
 #include "delegation.h"
 
 #define NFSDBG_FACILITY		NFSDBG_VFS
@@ -63,6 +64,7 @@
 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 void nfs_zap_acl_cache(struct inode *);
 
 static struct rpc_program	nfs_program;
 
@@ -106,6 +108,21 @@
 	.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 =		sizeof(nfsacl_version) / sizeof(nfsacl_version[0]),
+	.version =		nfsacl_version,
+	.stats =		&nfsacl_rpcstat,
+};
+#endif  /* CONFIG_NFS_V3_ACL */
+
 static inline unsigned long
 nfs_fattr_to_ino_t(struct nfs_fattr *fattr)
 {
@@ -118,7 +135,7 @@
 	int flags = sync ? FLUSH_WAIT : 0;
 	int ret;
 
-	ret = nfs_commit_inode(inode, 0, 0, flags);
+	ret = nfs_commit_inode(inode, flags);
 	if (ret < 0)
 		return ret;
 	return 0;
@@ -140,10 +157,6 @@
 	clear_inode(inode);
 }
 
-/*
- * For the moment, the only task for the NFS clear_inode method is to
- * release the mmap credential
- */
 static void
 nfs_clear_inode(struct inode *inode)
 {
@@ -152,6 +165,7 @@
 
 	nfs_wb_all(inode);
 	BUG_ON (!list_empty(&nfsi->open_files));
+	nfs_zap_acl_cache(inode);
 	cred = nfsi->cache_access.cred;
 	if (cred)
 		put_rpccred(cred);
@@ -161,11 +175,13 @@
 void
 nfs_umount_begin(struct super_block *sb)
 {
-	struct nfs_server *server = NFS_SB(sb);
-	struct rpc_clnt	*rpc;
+	struct rpc_clnt	*rpc = NFS_SB(sb)->client;
 
 	/* -EIO all pending I/O */
-	if ((rpc = server->client) != NULL)
+	if (!IS_ERR(rpc))
+		rpc_killall_tasks(rpc);
+	rpc = NFS_SB(sb)->client_acl;
+	if (!IS_ERR(rpc))
 		rpc_killall_tasks(rpc);
 }
 
@@ -366,13 +382,15 @@
 	xprt = xprt_create_proto(tcp ? IPPROTO_TCP : IPPROTO_UDP,
 				 &server->addr, &timeparms);
 	if (IS_ERR(xprt)) {
-		printk(KERN_WARNING "NFS: cannot create RPC transport.\n");
+		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)) {
-		printk(KERN_WARNING "NFS: cannot create RPC client.\n");
+		dprintk("%s: cannot create RPC client. Error = %ld\n",
+				__FUNCTION__, PTR_ERR(xprt));
 		goto out_fail;
 	}
 
@@ -383,7 +401,6 @@
 	return clnt;
 
 out_fail:
-	xprt_destroy(xprt);
 	return clnt;
 }
 
@@ -427,21 +444,16 @@
 
 	/* Check NFS protocol revision and initialize RPC op vector
 	 * and file handle pool. */
-	if (server->flags & NFS_MOUNT_VER3) {
 #ifdef CONFIG_NFS_V3
+	if (server->flags & NFS_MOUNT_VER3) {
 		server->rpc_ops = &nfs_v3_clientops;
 		server->caps |= NFS_CAP_READDIRPLUS;
-		if (data->version < 4) {
-			printk(KERN_NOTICE "NFS: NFSv3 not supported by mount program.\n");
-			return -EIO;
-		}
-#else
-		printk(KERN_NOTICE "NFS: NFSv3 not supported.\n");
-		return -EIO;
-#endif
 	} 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))
@@ -455,17 +467,34 @@
 		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);
-		if (!rpcauth_create(RPC_AUTH_UNIX, server->client_sys))
-			return -ENOMEM;
+		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;
@@ -549,6 +578,7 @@
 		{ NFS_MOUNT_NOCTO, ",nocto", "" },
 		{ NFS_MOUNT_NOAC, ",noac", "" },
 		{ NFS_MOUNT_NONLM, ",nolock", ",lock" },
+		{ NFS_MOUNT_NOACL, ",noacl", "" },
 		{ 0, NULL, NULL }
 	};
 	struct proc_nfs_info *nfs_infop;
@@ -590,9 +620,19 @@
 
 	memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
 	if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))
-		nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS;
+		nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
 	else
-		nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS;
+		nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
+}
+
+static void nfs_zap_acl_cache(struct inode *inode)
+{
+	void (*clear_acl_cache)(struct inode *);
+
+	clear_acl_cache = NFS_PROTO(inode)->clear_acl_cache;
+	if (clear_acl_cache != NULL)
+		clear_acl_cache(inode);
+	NFS_I(inode)->flags &= ~NFS_INO_INVALID_ACL;
 }
 
 /*
@@ -689,7 +729,7 @@
 		/* Why so? Because we want revalidate for devices/FIFOs, and
 		 * that's precisely what we have in nfs_file_inode_operations.
 		 */
-		inode->i_op = &nfs_file_inode_operations;
+		inode->i_op = NFS_SB(sb)->rpc_ops->file_inode_ops;
 		if (S_ISREG(inode->i_mode)) {
 			inode->i_fop = &nfs_file_operations;
 			inode->i_data.a_ops = &nfs_file_aops;
@@ -792,7 +832,7 @@
 		}
 	}
 	if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0)
-		NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS;
+		NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
 	nfs_end_data_update(inode);
 	unlock_kernel();
 	return error;
@@ -851,7 +891,7 @@
 		ctx->state = NULL;
 		ctx->lockowner = current->files;
 		ctx->error = 0;
-		init_waitqueue_head(&ctx->waitq);
+		ctx->dir_cookie = 0;
 	}
 	return ctx;
 }
@@ -1015,6 +1055,7 @@
 		goto out;
 	}
 	flags = nfsi->flags;
+	nfsi->flags &= ~NFS_INO_REVAL_PAGECACHE;
 	/*
 	 * We may need to keep the attributes marked as invalid if
 	 * we raced with nfs_end_attr_update().
@@ -1022,21 +1063,9 @@
 	if (verifier == nfsi->cache_change_attribute)
 		nfsi->flags &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME);
 	/* Do the page cache invalidation */
-	if (flags & NFS_INO_INVALID_DATA) {
-		if (S_ISREG(inode->i_mode)) {
-			if (filemap_fdatawrite(inode->i_mapping) == 0)
-				filemap_fdatawait(inode->i_mapping);
-			nfs_wb_all(inode);
-		}
-		nfsi->flags &= ~NFS_INO_INVALID_DATA;
-		invalidate_inode_pages2(inode->i_mapping);
-		memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
-		dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n",
-				inode->i_sb->s_id,
-				(long long)NFS_FILEID(inode));
-		/* This ensures we revalidate dentries */
-		nfsi->cache_change_attribute++;
-	}
+	nfs_revalidate_mapping(inode, inode->i_mapping);
+	if (flags & NFS_INO_INVALID_ACL)
+		nfs_zap_acl_cache(inode);
 	dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n",
 		inode->i_sb->s_id,
 		(long long)NFS_FILEID(inode));
@@ -1074,6 +1103,34 @@
 }
 
 /**
+ * nfs_revalidate_mapping - Revalidate the pagecache
+ * @inode - pointer to host inode
+ * @mapping - pointer to mapping
+ */
+void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping)
+{
+	struct nfs_inode *nfsi = NFS_I(inode);
+
+	if (nfsi->flags & NFS_INO_INVALID_DATA) {
+		if (S_ISREG(inode->i_mode)) {
+			if (filemap_fdatawrite(mapping) == 0)
+				filemap_fdatawait(mapping);
+			nfs_wb_all(inode);
+		}
+		invalidate_inode_pages2(mapping);
+		nfsi->flags &= ~NFS_INO_INVALID_DATA;
+		if (S_ISDIR(inode->i_mode)) {
+			memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf));
+			/* This ensures we revalidate child dentries */
+			nfsi->cache_change_attribute++;
+		}
+		dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n",
+				inode->i_sb->s_id,
+				(long long)NFS_FILEID(inode));
+	}
+}
+
+/**
  * nfs_begin_data_update
  * @inode - pointer to inode
  * Declare that a set of operations will update file data on the server
@@ -1106,27 +1163,6 @@
 }
 
 /**
- * nfs_end_data_update_defer
- * @inode - pointer to inode
- * Declare end of the operations that will update file data
- * This will defer marking the inode as needing revalidation
- * unless there are no other pending updates.
- */
-void nfs_end_data_update_defer(struct inode *inode)
-{
-	struct nfs_inode *nfsi = NFS_I(inode);
-
-	if (atomic_dec_and_test(&nfsi->data_updates)) {
-		/* Mark the attribute cache for revalidation */
-		nfsi->flags |= NFS_INO_INVALID_ATTR;
-		/* Directories and symlinks: invalidate page cache too */
-		if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
-			nfsi->flags |= NFS_INO_INVALID_DATA;
-		nfsi->cache_change_attribute ++;
-	}
-}
-
-/**
  * nfs_refresh_inode - verify consistency of the inode attribute cache
  * @inode - pointer to inode
  * @fattr - updated attributes
@@ -1152,8 +1188,11 @@
 		if ((fattr->valid & NFS_ATTR_PRE_CHANGE) != 0
 				&& nfsi->change_attr == fattr->pre_change_attr)
 			nfsi->change_attr = fattr->change_attr;
-		if (!data_unstable && nfsi->change_attr != fattr->change_attr)
+		if (nfsi->change_attr != fattr->change_attr) {
 			nfsi->flags |= NFS_INO_INVALID_ATTR;
+			if (!data_unstable)
+				nfsi->flags |= NFS_INO_REVAL_PAGECACHE;
+		}
 	}
 
 	if ((fattr->valid & NFS_ATTR_FATTR) == 0)
@@ -1176,18 +1215,22 @@
 	}
 
 	/* Verify a few of the more important attributes */
-	if (!data_unstable) {
-		if (!timespec_equal(&inode->i_mtime, &fattr->mtime)
-				|| cur_size != new_isize)
-			nfsi->flags |= NFS_INO_INVALID_ATTR;
-	} else if (S_ISREG(inode->i_mode) && new_isize > cur_size)
-			nfsi->flags |= NFS_INO_INVALID_ATTR;
+	if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) {
+		nfsi->flags |= NFS_INO_INVALID_ATTR;
+		if (!data_unstable)
+			nfsi->flags |= NFS_INO_REVAL_PAGECACHE;
+	}
+	if (cur_size != new_isize) {
+		nfsi->flags |= NFS_INO_INVALID_ATTR;
+		if (nfsi->npages == 0)
+			nfsi->flags |= NFS_INO_REVAL_PAGECACHE;
+	}
 
 	/* Have any file permissions changed? */
 	if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)
 			|| inode->i_uid != fattr->uid
 			|| inode->i_gid != fattr->gid)
-		nfsi->flags |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS;
+		nfsi->flags |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL;
 
 	/* Has the link count changed? */
 	if (inode->i_nlink != fattr->nlink)
@@ -1215,10 +1258,8 @@
 static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsigned long verifier)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
-	__u64		new_size;
-	loff_t		new_isize;
+	loff_t cur_isize, new_isize;
 	unsigned int	invalid = 0;
-	loff_t		cur_isize;
 	int data_unstable;
 
 	dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n",
@@ -1251,61 +1292,56 @@
 	/* Are we racing with known updates of the metadata on the server? */
 	data_unstable = ! nfs_verify_change_attribute(inode, verifier);
 
-	/* Check if the file size agrees */
-	new_size = fattr->size;
+	/* Check if our cached file size is stale */
  	new_isize = nfs_size_to_loff_t(fattr->size);
 	cur_isize = i_size_read(inode);
-	if (cur_isize != new_size) {
-#ifdef NFS_DEBUG_VERBOSE
-		printk(KERN_DEBUG "NFS: isize change on %s/%ld\n", inode->i_sb->s_id, inode->i_ino);
-#endif
-		/*
-		 * If we have pending writebacks, things can get
-		 * messy.
-		 */
-		if (S_ISREG(inode->i_mode) && data_unstable) {
-			if (new_isize > cur_isize) {
+	if (new_isize != cur_isize) {
+		/* Do we perhaps have any outstanding writes? */
+		if (nfsi->npages == 0) {
+			/* No, but did we race with nfs_end_data_update()? */
+			if (verifier  ==  nfsi->cache_change_attribute) {
 				inode->i_size = new_isize;
-				invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
+				invalid |= NFS_INO_INVALID_DATA;
 			}
-		} else {
+			invalid |= NFS_INO_INVALID_ATTR;
+		} else if (new_isize > cur_isize) {
 			inode->i_size = new_isize;
 			invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
 		}
+		dprintk("NFS: isize change on server for file %s/%ld\n",
+				inode->i_sb->s_id, inode->i_ino);
 	}
 
-	/*
-	 * Note: we don't check inode->i_mtime since pipes etc.
-	 *       can change this value in VFS without requiring a
-	 *	 cache revalidation.
-	 */
+	/* Check if the mtime agrees */
 	if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) {
 		memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
-#ifdef NFS_DEBUG_VERBOSE
-		printk(KERN_DEBUG "NFS: mtime change on %s/%ld\n", inode->i_sb->s_id, inode->i_ino);
-#endif
+		dprintk("NFS: mtime change on server for file %s/%ld\n",
+				inode->i_sb->s_id, inode->i_ino);
 		if (!data_unstable)
 			invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
 	}
 
 	if ((fattr->valid & NFS_ATTR_FATTR_V4)
 	    && nfsi->change_attr != fattr->change_attr) {
-#ifdef NFS_DEBUG_VERBOSE
-		printk(KERN_DEBUG "NFS: change_attr change on %s/%ld\n",
+		dprintk("NFS: change_attr change on server for file %s/%ld\n",
 		       inode->i_sb->s_id, inode->i_ino);
-#endif
 		nfsi->change_attr = fattr->change_attr;
 		if (!data_unstable)
-			invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS;
+			invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
 	}
 
-	memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
+	/* If ctime has changed we should definitely clear access+acl caches */
+	if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) {
+		if (!data_unstable)
+			invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
+		memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
+	}
 	memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime));
 
 	if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) ||
 	    inode->i_uid != fattr->uid ||
 	    inode->i_gid != fattr->gid)
-		invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS;
+		invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
 
 	inode->i_mode = fattr->mode;
 	inode->i_nlink = fattr->nlink;
@@ -1385,75 +1421,96 @@
 	int flags, const char *dev_name, void *raw_data)
 {
 	int error;
-	struct nfs_server *server;
+	struct nfs_server *server = NULL;
 	struct super_block *s;
 	struct nfs_fh *root;
 	struct nfs_mount_data *data = raw_data;
 
-	if (!data) {
-		printk("nfs_read_super: missing data argument\n");
-		return ERR_PTR(-EINVAL);
+	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 = kmalloc(sizeof(struct nfs_server), GFP_KERNEL);
 	if (!server)
-		return ERR_PTR(-ENOMEM);
+		goto out_err;
 	memset(server, 0, sizeof(struct nfs_server));
 	/* Zero out the NFS state stuff */
 	init_nfsv4_state(server);
-
-	if (data->version != NFS_MOUNT_VERSION) {
-		printk("nfs warning: mount version %s than kernel\n",
-			data->version < NFS_MOUNT_VERSION ? "older" : "newer");
-		if (data->version < 2)
-			data->namlen = 0;
-		if (data->version < 3)
-			data->bsize  = 0;
-		if (data->version < 4) {
-			data->flags &= ~NFS_MOUNT_VER3;
-			data->root.size = NFS2_FHSIZE;
-			memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE);
-		}
-		if (data->version < 5)
-			data->flags &= ~NFS_MOUNT_SECFLAVOUR;
-	}
+	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)) {
-		printk("nfs_get_sb: invalid root filehandle\n");
-		kfree(server);
-		return ERR_PTR(-EINVAL);
+		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) {
-		printk("NFS: mount program didn't pass remote address!\n");
-		kfree(server);
-		return ERR_PTR(-EINVAL);
+		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) {
-		kfree(server);
-		return s;
-	}
+	if (IS_ERR(s) || s->s_root)
+		goto out_rpciod_down;
 
 	s->s_flags = flags;
 
-	/* Fire up rpciod if not yet running */
-	if (rpciod_up() != 0) {
-		printk(KERN_WARNING "NFS: couldn't start rpciod!\n");
-		kfree(server);
-		return ERR_PTR(-EIO);
-	}
-
 	error = nfs_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
 	if (error) {
 		up_write(&s->s_umount);
@@ -1462,6 +1519,11 @@
 	}
 	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)
@@ -1470,10 +1532,12 @@
 
 	kill_anon_super(s);
 
-	if (server->client != NULL && !IS_ERR(server->client))
+	if (!IS_ERR(server->client))
 		rpc_shutdown_client(server->client);
-	if (server->client_sys != NULL && !IS_ERR(server->client_sys))
+	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 */
@@ -1594,15 +1658,19 @@
 
 	clp = nfs4_get_client(&server->addr.sin_addr);
 	if (!clp) {
-		printk(KERN_WARNING "NFS: failed to create NFS4 client.\n");
+		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)
-			printk(KERN_INFO "NFS: cannot yet deal with multiple auth flavours.\n");
+		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;
@@ -1610,21 +1678,22 @@
 	}
 
 	down_write(&clp->cl_sem);
-	if (clp->cl_rpcclient == NULL) {
+	if (IS_ERR(clp->cl_rpcclient)) {
 		xprt = xprt_create_proto(proto, &server->addr, &timeparms);
 		if (IS_ERR(xprt)) {
 			up_write(&clp->cl_sem);
-			printk(KERN_WARNING "NFS: cannot create RPC transport.\n");
 			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);
-			printk(KERN_WARNING "NFS: cannot create RPC client.\n");
-			xprt_destroy(xprt);
 			err = PTR_ERR(clnt);
+			dprintk("%s: cannot create RPC client. Error = %d\n",
+					__FUNCTION__, err);
 			goto out_fail;
 		}
 		clnt->cl_intr     = 1;
@@ -1656,21 +1725,26 @@
 	clp = NULL;
 
 	if (IS_ERR(clnt)) {
-		printk(KERN_WARNING "NFS: cannot create RPC client.\n");
-		return PTR_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) {
-		printk(KERN_WARNING "NFS: failed to create idmapper.\n");
+		dprintk("%s: failed to create idmapper.\n", __FUNCTION__);
 		return -ENOMEM;
 	}
 
 	if (clnt->cl_auth->au_flavor != authflavour) {
-		if (rpcauth_create(authflavour, clnt) == NULL) {
-			printk(KERN_WARNING "NFS: couldn't create credcache!\n");
-			return -ENOMEM;
+		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);
 		}
 	}
 
@@ -1730,8 +1804,12 @@
 	struct nfs4_mount_data *data = raw_data;
 	void *p;
 
-	if (!data) {
-		printk("nfs_read_super: missing data argument\n");
+	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);
 	}
 
@@ -1741,11 +1819,7 @@
 	memset(server, 0, sizeof(struct nfs_server));
 	/* Zero out the NFS state stuff */
 	init_nfsv4_state(server);
-
-	if (data->version != NFS4_MOUNT_VERSION) {
-		printk("nfs warning: mount version %s than kernel\n",
-			data->version < NFS4_MOUNT_VERSION ? "older" : "newer");
-	}
+	server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL);
 
 	p = nfs_copy_user_string(NULL, &data->hostname, 256);
 	if (IS_ERR(p))
@@ -1773,11 +1847,20 @@
 	}
 	if (server->addr.sin_family != AF_INET ||
 	    server->addr.sin_addr.s_addr == INADDR_ANY) {
-		printk("NFS: mount program didn't pass remote IP address!\n");
+		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)
@@ -1785,13 +1868,6 @@
 
 	s->s_flags = flags;
 
-	/* Fire up rpciod if not yet running */
-	if (rpciod_up() != 0) {
-		printk(KERN_WARNING "NFS: couldn't start rpciod!\n");
-		s = ERR_PTR(-EIO);
-		goto out_free;
-	}
-
 	error = nfs4_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
 	if (error) {
 		up_write(&s->s_umount);
@@ -1875,6 +1951,13 @@
 	if (!nfsi)
 		return NULL;
 	nfsi->flags = 0;
+#ifdef CONFIG_NFS_V3_ACL
+	nfsi->acl_access = ERR_PTR(-EAGAIN);
+	nfsi->acl_default = ERR_PTR(-EAGAIN);
+#endif
+#ifdef CONFIG_NFS_V4
+	nfsi->nfs4_acl = NULL;
+#endif /* CONFIG_NFS_V4 */
 	return &nfsi->vfs_inode;
 }
 
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index 9d3ddad..0e82617 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -80,9 +80,7 @@
 	clnt = rpc_create_client(xprt, hostname,
 				&mnt_program, version,
 				RPC_AUTH_UNIX);
-	if (IS_ERR(clnt)) {
-		xprt_destroy(xprt);
-	} else {
+	if (!IS_ERR(clnt)) {
 		clnt->cl_softrtry = 1;
 		clnt->cl_chatty   = 1;
 		clnt->cl_oneshot  = 1;
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
new file mode 100644
index 0000000..ee3536f
--- /dev/null
+++ b/fs/nfs/nfs3acl.c
@@ -0,0 +1,403 @@
+#include <linux/fs.h>
+#include <linux/nfs.h>
+#include <linux/nfs3.h>
+#include <linux/nfs_fs.h>
+#include <linux/xattr_acl.h>
+#include <linux/nfsacl.h>
+
+#define NFSDBG_FACILITY	NFSDBG_PROC
+
+ssize_t nfs3_listxattr(struct dentry *dentry, char *buffer, size_t size)
+{
+	struct inode *inode = dentry->d_inode;
+	struct posix_acl *acl;
+	int pos=0, len=0;
+
+#	define output(s) do {						\
+			if (pos + sizeof(s) <= size) {			\
+				memcpy(buffer + pos, s, sizeof(s));	\
+				pos += sizeof(s);			\
+			}						\
+			len += sizeof(s);				\
+		} while(0)
+
+	acl = nfs3_proc_getacl(inode, ACL_TYPE_ACCESS);
+	if (IS_ERR(acl))
+		return PTR_ERR(acl);
+	if (acl) {
+		output("system.posix_acl_access");
+		posix_acl_release(acl);
+	}
+
+	if (S_ISDIR(inode->i_mode)) {
+		acl = nfs3_proc_getacl(inode, ACL_TYPE_DEFAULT);
+		if (IS_ERR(acl))
+			return PTR_ERR(acl);
+		if (acl) {
+			output("system.posix_acl_default");
+			posix_acl_release(acl);
+		}
+	}
+
+#	undef output
+
+	if (!buffer || len <= size)
+		return len;
+	return -ERANGE;
+}
+
+ssize_t nfs3_getxattr(struct dentry *dentry, const char *name,
+		void *buffer, size_t size)
+{
+	struct inode *inode = dentry->d_inode;
+	struct posix_acl *acl;
+	int type, error = 0;
+
+	if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0)
+		type = ACL_TYPE_ACCESS;
+	else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0)
+		type = ACL_TYPE_DEFAULT;
+	else
+		return -EOPNOTSUPP;
+
+	acl = nfs3_proc_getacl(inode, type);
+	if (IS_ERR(acl))
+		return PTR_ERR(acl);
+	else if (acl) {
+		if (type == ACL_TYPE_ACCESS && acl->a_count == 0)
+			error = -ENODATA;
+		else
+			error = posix_acl_to_xattr(acl, buffer, size);
+		posix_acl_release(acl);
+	} else
+		error = -ENODATA;
+
+	return error;
+}
+
+int nfs3_setxattr(struct dentry *dentry, const char *name,
+	     const void *value, size_t size, int flags)
+{
+	struct inode *inode = dentry->d_inode;
+	struct posix_acl *acl;
+	int type, error;
+
+	if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0)
+		type = ACL_TYPE_ACCESS;
+	else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0)
+		type = ACL_TYPE_DEFAULT;
+	else
+		return -EOPNOTSUPP;
+
+	acl = posix_acl_from_xattr(value, size);
+	if (IS_ERR(acl))
+		return PTR_ERR(acl);
+	error = nfs3_proc_setacl(inode, type, acl);
+	posix_acl_release(acl);
+
+	return error;
+}
+
+int nfs3_removexattr(struct dentry *dentry, const char *name)
+{
+	struct inode *inode = dentry->d_inode;
+	int type;
+
+	if (strcmp(name, XATTR_NAME_ACL_ACCESS) == 0)
+		type = ACL_TYPE_ACCESS;
+	else if (strcmp(name, XATTR_NAME_ACL_DEFAULT) == 0)
+		type = ACL_TYPE_DEFAULT;
+	else
+		return -EOPNOTSUPP;
+
+	return nfs3_proc_setacl(inode, type, NULL);
+}
+
+static void __nfs3_forget_cached_acls(struct nfs_inode *nfsi)
+{
+	if (!IS_ERR(nfsi->acl_access)) {
+		posix_acl_release(nfsi->acl_access);
+		nfsi->acl_access = ERR_PTR(-EAGAIN);
+	}
+	if (!IS_ERR(nfsi->acl_default)) {
+		posix_acl_release(nfsi->acl_default);
+		nfsi->acl_default = ERR_PTR(-EAGAIN);
+	}
+}
+
+void nfs3_forget_cached_acls(struct inode *inode)
+{
+	dprintk("NFS: nfs3_forget_cached_acls(%s/%ld)\n", inode->i_sb->s_id,
+		inode->i_ino);
+	spin_lock(&inode->i_lock);
+	__nfs3_forget_cached_acls(NFS_I(inode));
+	spin_unlock(&inode->i_lock);
+}
+
+static struct posix_acl *nfs3_get_cached_acl(struct inode *inode, int type)
+{
+	struct nfs_inode *nfsi = NFS_I(inode);
+	struct posix_acl *acl = ERR_PTR(-EINVAL);
+
+	spin_lock(&inode->i_lock);
+	switch(type) {
+		case ACL_TYPE_ACCESS:
+			acl = nfsi->acl_access;
+			break;
+
+		case ACL_TYPE_DEFAULT:
+			acl = nfsi->acl_default;
+			break;
+
+		default:
+			goto out;
+	}
+	if (IS_ERR(acl))
+		acl = ERR_PTR(-EAGAIN);
+	else
+		acl = posix_acl_dup(acl);
+out:
+	spin_unlock(&inode->i_lock);
+	dprintk("NFS: nfs3_get_cached_acl(%s/%ld, %d) = %p\n", inode->i_sb->s_id,
+		inode->i_ino, type, acl);
+	return acl;
+}
+
+static void nfs3_cache_acls(struct inode *inode, struct posix_acl *acl,
+		    struct posix_acl *dfacl)
+{
+	struct nfs_inode *nfsi = NFS_I(inode);
+
+	dprintk("nfs3_cache_acls(%s/%ld, %p, %p)\n", inode->i_sb->s_id,
+		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);
+	spin_unlock(&inode->i_lock);
+}
+
+struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
+{
+	struct nfs_server *server = NFS_SERVER(inode);
+	struct nfs_fattr fattr;
+	struct page *pages[NFSACL_MAXPAGES] = { };
+	struct nfs3_getaclargs args = {
+		.fh = NFS_FH(inode),
+		/* The xdr layer may allocate pages here. */
+		.pages = pages,
+	};
+	struct nfs3_getaclres res = {
+		.fattr =	&fattr,
+	};
+	struct posix_acl *acl;
+	int status, count;
+
+	if (!nfs_server_capable(inode, NFS_CAP_ACLS))
+		return ERR_PTR(-EOPNOTSUPP);
+
+	status = nfs_revalidate_inode(server, inode);
+	if (status < 0)
+		return ERR_PTR(status);
+	acl = nfs3_get_cached_acl(inode, type);
+	if (acl != ERR_PTR(-EAGAIN))
+		return acl;
+	acl = NULL;
+
+	/*
+	 * Only get the access acl when explicitly requested: We don't
+	 * need it for access decisions, and only some applications use
+	 * it. Applications which request the access acl first are not
+	 * penalized from this optimization.
+	 */
+	if (type == ACL_TYPE_ACCESS)
+		args.mask |= NFS_ACLCNT|NFS_ACL;
+	if (S_ISDIR(inode->i_mode))
+		args.mask |= NFS_DFACLCNT|NFS_DFACL;
+	if (args.mask == 0)
+		return NULL;
+
+	dprintk("NFS call getacl\n");
+	status = rpc_call(server->client_acl, ACLPROC3_GETACL,
+			  &args, &res, 0);
+	dprintk("NFS reply getacl: %d\n", status);
+
+	/* pages may have been allocated at the xdr layer. */
+	for (count = 0; count < NFSACL_MAXPAGES && args.pages[count]; count++)
+		__free_page(args.pages[count]);
+
+	switch (status) {
+		case 0:
+			status = nfs_refresh_inode(inode, &fattr);
+			break;
+		case -EPFNOSUPPORT:
+		case -EPROTONOSUPPORT:
+			dprintk("NFS_V3_ACL extension not supported; disabling\n");
+			server->caps &= ~NFS_CAP_ACLS;
+		case -ENOTSUPP:
+			status = -EOPNOTSUPP;
+		default:
+			goto getout;
+	}
+	if ((args.mask & res.mask) != args.mask) {
+		status = -EIO;
+		goto getout;
+	}
+
+	if (res.acl_access != NULL) {
+		if (posix_acl_equiv_mode(res.acl_access, NULL) == 0) {
+			posix_acl_release(res.acl_access);
+			res.acl_access = NULL;
+		}
+	}
+	nfs3_cache_acls(inode, res.acl_access, res.acl_default);
+
+	switch(type) {
+		case ACL_TYPE_ACCESS:
+			acl = res.acl_access;
+			res.acl_access = NULL;
+			break;
+
+		case ACL_TYPE_DEFAULT:
+			acl = res.acl_default;
+			res.acl_default = NULL;
+	}
+
+getout:
+	posix_acl_release(res.acl_access);
+	posix_acl_release(res.acl_default);
+
+	if (status != 0) {
+		posix_acl_release(acl);
+		acl = ERR_PTR(status);
+	}
+	return acl;
+}
+
+static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
+		  struct posix_acl *dfacl)
+{
+	struct nfs_server *server = NFS_SERVER(inode);
+	struct nfs_fattr fattr;
+	struct page *pages[NFSACL_MAXPAGES] = { };
+	struct nfs3_setaclargs args = {
+		.inode = inode,
+		.mask = NFS_ACL,
+		.acl_access = acl,
+		.pages = pages,
+	};
+	int status, count;
+
+	status = -EOPNOTSUPP;
+	if (!nfs_server_capable(inode, NFS_CAP_ACLS))
+		goto out;
+
+	/* We are doing this here, because XDR marshalling can only
+	   return -ENOMEM. */
+	status = -ENOSPC;
+	if (acl != NULL && acl->a_count > NFS_ACL_MAX_ENTRIES)
+		goto out;
+	if (dfacl != NULL && dfacl->a_count > NFS_ACL_MAX_ENTRIES)
+		goto out;
+	if (S_ISDIR(inode->i_mode)) {
+		args.mask |= NFS_DFACL;
+		args.acl_default = dfacl;
+	}
+
+	dprintk("NFS call setacl\n");
+	nfs_begin_data_update(inode);
+	status = rpc_call(server->client_acl, ACLPROC3_SETACL,
+			  &args, &fattr, 0);
+	NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS;
+	nfs_end_data_update(inode);
+	dprintk("NFS reply setacl: %d\n", status);
+
+	/* pages may have been allocated at the xdr layer. */
+	for (count = 0; count < NFSACL_MAXPAGES && args.pages[count]; count++)
+		__free_page(args.pages[count]);
+
+	switch (status) {
+		case 0:
+			status = nfs_refresh_inode(inode, &fattr);
+			break;
+		case -EPFNOSUPPORT:
+		case -EPROTONOSUPPORT:
+			dprintk("NFS_V3_ACL SETACL RPC not supported"
+					"(will not retry)\n");
+			server->caps &= ~NFS_CAP_ACLS;
+		case -ENOTSUPP:
+			status = -EOPNOTSUPP;
+	}
+out:
+	return status;
+}
+
+int nfs3_proc_setacl(struct inode *inode, int type, struct posix_acl *acl)
+{
+	struct posix_acl *alloc = NULL, *dfacl = NULL;
+	int status;
+
+	if (S_ISDIR(inode->i_mode)) {
+		switch(type) {
+			case ACL_TYPE_ACCESS:
+				alloc = dfacl = nfs3_proc_getacl(inode,
+						ACL_TYPE_DEFAULT);
+				if (IS_ERR(alloc))
+					goto fail;
+				break;
+
+			case ACL_TYPE_DEFAULT:
+				dfacl = acl;
+				alloc = acl = nfs3_proc_getacl(inode,
+						ACL_TYPE_ACCESS);
+				if (IS_ERR(alloc))
+					goto fail;
+				break;
+
+			default:
+				return -EINVAL;
+		}
+	} else if (type != ACL_TYPE_ACCESS)
+			return -EINVAL;
+
+	if (acl == NULL) {
+		alloc = acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
+		if (IS_ERR(alloc))
+			goto fail;
+	}
+	status = nfs3_proc_setacls(inode, acl, dfacl);
+	posix_acl_release(alloc);
+	return status;
+
+fail:
+	return PTR_ERR(alloc);
+}
+
+int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode,
+		mode_t mode)
+{
+	struct posix_acl *dfacl, *acl;
+	int error = 0;
+
+	dfacl = nfs3_proc_getacl(dir, ACL_TYPE_DEFAULT);
+	if (IS_ERR(dfacl)) {
+		error = PTR_ERR(dfacl);
+		return (error == -EOPNOTSUPP) ? 0 : error;
+	}
+	if (!dfacl)
+		return 0;
+	acl = posix_acl_clone(dfacl, GFP_KERNEL);
+	error = -ENOMEM;
+	if (!acl)
+		goto out_release_dfacl;
+	error = posix_acl_create_masq(acl, &mode);
+	if (error < 0)
+		goto out_release_acl;
+	error = nfs3_proc_setacls(inode, acl, S_ISDIR(inode->i_mode) ?
+						      dfacl : NULL);
+out_release_acl:
+	posix_acl_release(acl);
+out_release_dfacl:
+	posix_acl_release(dfacl);
+	return error;
+}
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index 3878494..7851569 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -17,6 +17,7 @@
 #include <linux/nfs_page.h>
 #include <linux/lockd/bind.h>
 #include <linux/smp_lock.h>
+#include <linux/nfs_mount.h>
 
 #define NFSDBG_FACILITY		NFSDBG_PROC
 
@@ -45,7 +46,7 @@
 nfs3_rpc_call_wrapper(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
 {
 	struct rpc_message msg = {
-		.rpc_proc	= &nfs3_procedures[proc],
+		.rpc_proc	= &clnt->cl_procinfo[proc],
 		.rpc_argp	= argp,
 		.rpc_resp	= resp,
 	};
@@ -313,7 +314,8 @@
 		.fh		= &fhandle,
 		.fattr		= &fattr
 	};
-	int			status;
+	mode_t mode = sattr->ia_mode;
+	int status;
 
 	dprintk("NFS call  create %s\n", dentry->d_name.name);
 	arg.createmode = NFS3_CREATE_UNCHECKED;
@@ -323,6 +325,8 @@
 		arg.verifier[1] = current->pid;
 	}
 
+	sattr->ia_mode &= ~current->fs->umask;
+
 again:
 	dir_attr.valid = 0;
 	fattr.valid = 0;
@@ -369,6 +373,9 @@
 		nfs_refresh_inode(dentry->d_inode, &fattr);
 		dprintk("NFS reply setattr (post-create): %d\n", status);
 	}
+	if (status != 0)
+		goto out;
+	status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode);
 out:
 	dprintk("NFS reply create: %d\n", status);
 	return status;
@@ -538,15 +545,24 @@
 		.fh		= &fhandle,
 		.fattr		= &fattr
 	};
-	int			status;
+	int mode = sattr->ia_mode;
+	int status;
 
 	dprintk("NFS call  mkdir %s\n", dentry->d_name.name);
 	dir_attr.valid = 0;
 	fattr.valid = 0;
+
+	sattr->ia_mode &= ~current->fs->umask;
+
 	status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, 0);
 	nfs_refresh_inode(dir, &dir_attr);
-	if (status == 0)
-		status = nfs_instantiate(dentry, &fhandle, &fattr);
+	if (status != 0)
+		goto out;
+	status = nfs_instantiate(dentry, &fhandle, &fattr);
+	if (status != 0)
+		goto out;
+	status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode);
+out:
 	dprintk("NFS reply mkdir: %d\n", status);
 	return status;
 }
@@ -641,6 +657,7 @@
 		.fh		= &fh,
 		.fattr		= &fattr
 	};
+	mode_t mode = sattr->ia_mode;
 	int status;
 
 	switch (sattr->ia_mode & S_IFMT) {
@@ -653,12 +670,20 @@
 
 	dprintk("NFS call  mknod %s %u:%u\n", dentry->d_name.name,
 			MAJOR(rdev), MINOR(rdev));
+
+	sattr->ia_mode &= ~current->fs->umask;
+
 	dir_attr.valid = 0;
 	fattr.valid = 0;
 	status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, 0);
 	nfs_refresh_inode(dir, &dir_attr);
-	if (status == 0)
-		status = nfs_instantiate(dentry, &fh, &fattr);
+	if (status != 0)
+		goto out;
+	status = nfs_instantiate(dentry, &fh, &fattr);
+	if (status != 0)
+		goto out;
+	status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode);
+out:
 	dprintk("NFS reply mknod: %d\n", status);
 	return status;
 }
@@ -825,7 +850,8 @@
 struct nfs_rpc_ops	nfs_v3_clientops = {
 	.version	= 3,			/* protocol version */
 	.dentry_ops	= &nfs_dentry_operations,
-	.dir_inode_ops	= &nfs_dir_inode_operations,
+	.dir_inode_ops	= &nfs3_dir_inode_operations,
+	.file_inode_ops	= &nfs3_file_inode_operations,
 	.getroot	= nfs3_proc_get_root,
 	.getattr	= nfs3_proc_getattr,
 	.setattr	= nfs3_proc_setattr,
@@ -856,4 +882,5 @@
 	.file_open	= nfs_open,
 	.file_release	= nfs_release,
 	.lock		= nfs3_proc_lock,
+	.clear_acl_cache = nfs3_forget_cached_acls,
 };
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index a3593d4..db4a904 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -21,6 +21,7 @@
 #include <linux/nfs.h>
 #include <linux/nfs3.h>
 #include <linux/nfs_fs.h>
+#include <linux/nfsacl.h>
 
 #define NFSDBG_FACILITY		NFSDBG_XDR
 
@@ -79,6 +80,11 @@
 #define NFS3_pathconfres_sz	(1+NFS3_post_op_attr_sz+6)
 #define NFS3_commitres_sz	(1+NFS3_wcc_data_sz+2)
 
+#define ACL3_getaclargs_sz	(NFS3_fh_sz+1)
+#define ACL3_setaclargs_sz	(NFS3_fh_sz+1+2*(2+5*3))
+#define ACL3_getaclres_sz	(1+NFS3_post_op_attr_sz+1+2*(2+5*3))
+#define ACL3_setaclres_sz	(1+NFS3_post_op_attr_sz)
+
 /*
  * Map file type to S_IFMT bits
  */
@@ -627,6 +633,74 @@
 	return 0;
 }
 
+#ifdef CONFIG_NFS_V3_ACL
+/*
+ * Encode GETACL arguments
+ */
+static int
+nfs3_xdr_getaclargs(struct rpc_rqst *req, u32 *p,
+		    struct nfs3_getaclargs *args)
+{
+	struct rpc_auth *auth = req->rq_task->tk_auth;
+	unsigned int replen;
+
+	p = xdr_encode_fhandle(p, args->fh);
+	*p++ = htonl(args->mask);
+	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
+
+	if (args->mask & (NFS_ACL | NFS_DFACL)) {
+		/* Inline the page array */
+		replen = (RPC_REPHDRSIZE + auth->au_rslack +
+			  ACL3_getaclres_sz) << 2;
+		xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0,
+				 NFSACL_MAXPAGES << PAGE_SHIFT);
+	}
+	return 0;
+}
+
+/*
+ * Encode SETACL arguments
+ */
+static int
+nfs3_xdr_setaclargs(struct rpc_rqst *req, u32 *p,
+                   struct nfs3_setaclargs *args)
+{
+	struct xdr_buf *buf = &req->rq_snd_buf;
+	unsigned int base, len_in_head, len = nfsacl_size(
+		(args->mask & NFS_ACL)   ? args->acl_access  : NULL,
+		(args->mask & NFS_DFACL) ? args->acl_default : NULL);
+	int count, err;
+
+	p = xdr_encode_fhandle(p, NFS_FH(args->inode));
+	*p++ = htonl(args->mask);
+	base = (char *)p - (char *)buf->head->iov_base;
+	/* put as much of the acls into head as possible. */
+	len_in_head = min_t(unsigned int, buf->head->iov_len - base, len);
+	len -= len_in_head;
+	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p + (len_in_head >> 2));
+
+	for (count = 0; (count << PAGE_SHIFT) < len; count++) {
+		args->pages[count] = alloc_page(GFP_KERNEL);
+		if (!args->pages[count]) {
+			while (count)
+				__free_page(args->pages[--count]);
+			return -ENOMEM;
+		}
+	}
+	xdr_encode_pages(buf, args->pages, 0, len);
+
+	err = nfsacl_encode(buf, base, args->inode,
+			    (args->mask & NFS_ACL) ?
+			    args->acl_access : NULL, 1, 0);
+	if (err > 0)
+		err = nfsacl_encode(buf, base + err, args->inode,
+				    (args->mask & NFS_DFACL) ?
+				    args->acl_default : NULL, 1,
+				    NFS_ACL_DEFAULT);
+	return (err > 0) ? 0 : err;
+}
+#endif  /* CONFIG_NFS_V3_ACL */
+
 /*
  * NFS XDR decode functions
  */
@@ -978,6 +1052,54 @@
 	return 0;
 }
 
+#ifdef CONFIG_NFS_V3_ACL
+/*
+ * Decode GETACL reply
+ */
+static int
+nfs3_xdr_getaclres(struct rpc_rqst *req, u32 *p,
+		   struct nfs3_getaclres *res)
+{
+	struct xdr_buf *buf = &req->rq_rcv_buf;
+	int status = ntohl(*p++);
+	struct posix_acl **acl;
+	unsigned int *aclcnt;
+	int err, base;
+
+	if (status != 0)
+		return -nfs_stat_to_errno(status);
+	p = xdr_decode_post_op_attr(p, res->fattr);
+	res->mask = ntohl(*p++);
+	if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
+		return -EINVAL;
+	base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base;
+
+	acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL;
+	aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL;
+	err = nfsacl_decode(buf, base, aclcnt, acl);
+
+	acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL;
+	aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL;
+	if (err > 0)
+		err = nfsacl_decode(buf, base + err, aclcnt, acl);
+	return (err > 0) ? 0 : err;
+}
+
+/*
+ * Decode setacl reply.
+ */
+static int
+nfs3_xdr_setaclres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
+{
+	int status = ntohl(*p++);
+
+	if (status)
+		return -nfs_stat_to_errno(status);
+	xdr_decode_post_op_attr(p, fattr);
+	return 0;
+}
+#endif  /* CONFIG_NFS_V3_ACL */
+
 #ifndef MAX
 # define MAX(a, b)	(((a) > (b))? (a) : (b))
 #endif
@@ -1021,3 +1143,28 @@
 	.procs			= nfs3_procedures
 };
 
+#ifdef CONFIG_NFS_V3_ACL
+static struct rpc_procinfo	nfs3_acl_procedures[] = {
+	[ACLPROC3_GETACL] = {
+		.p_proc = ACLPROC3_GETACL,
+		.p_encode = (kxdrproc_t) nfs3_xdr_getaclargs,
+		.p_decode = (kxdrproc_t) nfs3_xdr_getaclres,
+		.p_bufsiz = MAX(ACL3_getaclargs_sz, ACL3_getaclres_sz) << 2,
+		.p_timer = 1,
+	},
+	[ACLPROC3_SETACL] = {
+		.p_proc = ACLPROC3_SETACL,
+		.p_encode = (kxdrproc_t) nfs3_xdr_setaclargs,
+		.p_decode = (kxdrproc_t) nfs3_xdr_setaclres,
+		.p_bufsiz = MAX(ACL3_setaclargs_sz, ACL3_setaclres_sz) << 2,
+		.p_timer = 0,
+	},
+};
+
+struct rpc_version		nfsacl_version3 = {
+	.number			= 3,
+	.nrprocs		= sizeof(nfs3_acl_procedures)/
+				  sizeof(nfs3_acl_procedures[0]),
+	.procs			= nfs3_acl_procedures,
+};
+#endif  /* CONFIG_NFS_V3_ACL */
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
new file mode 100644
index 0000000..ec1a22d
--- /dev/null
+++ b/fs/nfs/nfs4_fs.h
@@ -0,0 +1,253 @@
+/*
+ * linux/fs/nfs/nfs4_fs.h
+ *
+ * Copyright (C) 2005 Trond Myklebust
+ *
+ * NFSv4-specific filesystem definitions and declarations
+ */
+
+#ifndef __LINUX_FS_NFS_NFS4_FS_H
+#define __LINUX_FS_NFS_NFS4_FS_H
+
+#ifdef CONFIG_NFS_V4
+
+struct idmap;
+
+/*
+ * In a seqid-mutating op, this macro controls which error return
+ * values trigger incrementation of the seqid.
+ *
+ * from rfc 3010:
+ * The client MUST monotonically increment the sequence number for the
+ * CLOSE, LOCK, LOCKU, OPEN, OPEN_CONFIRM, and OPEN_DOWNGRADE
+ * operations.  This is true even in the event that the previous
+ * operation that used the sequence number received an error.  The only
+ * exception to this rule is if the previous operation received one of
+ * the following errors: NFSERR_STALE_CLIENTID, NFSERR_STALE_STATEID,
+ * NFSERR_BAD_STATEID, NFSERR_BAD_SEQID, NFSERR_BADXDR,
+ * NFSERR_RESOURCE, NFSERR_NOFILEHANDLE.
+ *
+ */
+#define seqid_mutating_err(err)       \
+(((err) != NFSERR_STALE_CLIENTID) &&  \
+ ((err) != NFSERR_STALE_STATEID)  &&  \
+ ((err) != NFSERR_BAD_STATEID)    &&  \
+ ((err) != NFSERR_BAD_SEQID)      &&  \
+ ((err) != NFSERR_BAD_XDR)        &&  \
+ ((err) != NFSERR_RESOURCE)       &&  \
+ ((err) != NFSERR_NOFILEHANDLE))
+
+enum nfs4_client_state {
+	NFS4CLNT_OK  = 0,
+};
+
+/*
+ * The nfs4_client identifies our client state to the server.
+ */
+struct nfs4_client {
+	struct list_head	cl_servers;	/* Global list of servers */
+	struct in_addr		cl_addr;	/* Server identifier */
+	u64			cl_clientid;	/* constant */
+	nfs4_verifier		cl_confirm;
+	unsigned long		cl_state;
+
+	u32			cl_lockowner_id;
+
+	/*
+	 * The following rwsem ensures exclusive access to the server
+	 * while we recover the state following a lease expiration.
+	 */
+	struct rw_semaphore	cl_sem;
+
+	struct list_head	cl_delegations;
+	struct list_head	cl_state_owners;
+	struct list_head	cl_unused;
+	int			cl_nunused;
+	spinlock_t		cl_lock;
+	atomic_t		cl_count;
+
+	struct rpc_clnt *	cl_rpcclient;
+	struct rpc_cred *	cl_cred;
+
+	struct list_head	cl_superblocks;	/* List of nfs_server structs */
+
+	unsigned long		cl_lease_time;
+	unsigned long		cl_last_renewal;
+	struct work_struct	cl_renewd;
+	struct work_struct	cl_recoverd;
+
+	wait_queue_head_t	cl_waitq;
+	struct rpc_wait_queue	cl_rpcwaitq;
+
+	/* used for the setclientid verifier */
+	struct timespec		cl_boot_time;
+
+	/* idmapper */
+	struct idmap *		cl_idmap;
+
+	/* Our own IP address, as a null-terminated string.
+	 * This is used to generate the clientid, and the callback address.
+	 */
+	char			cl_ipaddr[16];
+	unsigned char		cl_id_uniquifier;
+};
+
+/*
+ * NFS4 state_owners and lock_owners are simply labels for ordered
+ * sequences of RPC calls. Their sole purpose is to provide once-only
+ * semantics by allowing the server to identify replayed requests.
+ *
+ * The ->so_sema is held during all state_owner seqid-mutating operations:
+ * OPEN, OPEN_DOWNGRADE, and CLOSE. Its purpose is to properly serialize
+ * so_seqid.
+ */
+struct nfs4_state_owner {
+	struct list_head     so_list;	 /* per-clientid list of state_owners */
+	struct nfs4_client   *so_client;
+	u32                  so_id;      /* 32-bit identifier, unique */
+	struct semaphore     so_sema;
+	u32                  so_seqid;   /* protected by so_sema */
+	atomic_t	     so_count;
+
+	struct rpc_cred	     *so_cred;	 /* Associated cred */
+	struct list_head     so_states;
+	struct list_head     so_delegations;
+};
+
+/*
+ * struct nfs4_state maintains the client-side state for a given
+ * (state_owner,inode) tuple (OPEN) or state_owner (LOCK).
+ *
+ * OPEN:
+ * In order to know when to OPEN_DOWNGRADE or CLOSE the state on the server,
+ * we need to know how many files are open for reading or writing on a
+ * given inode. This information too is stored here.
+ *
+ * LOCK: one nfs4_state (LOCK) to hold the lock stateid nfs4_state(OPEN)
+ */
+
+struct nfs4_lock_state {
+	struct list_head	ls_locks;	/* Other lock stateids */
+	struct nfs4_state *	ls_state;	/* Pointer to open state */
+	fl_owner_t		ls_owner;	/* POSIX lock owner */
+#define NFS_LOCK_INITIALIZED 1
+	int			ls_flags;
+	u32			ls_seqid;
+	u32			ls_id;
+	nfs4_stateid		ls_stateid;
+	atomic_t		ls_count;
+};
+
+/* bits for nfs4_state->flags */
+enum {
+	LK_STATE_IN_USE,
+	NFS_DELEGATED_STATE,
+};
+
+struct nfs4_state {
+	struct list_head open_states;	/* List of states for the same state_owner */
+	struct list_head inode_states;	/* List of states for the same inode */
+	struct list_head lock_states;	/* List of subservient lock stateids */
+
+	struct nfs4_state_owner *owner;	/* Pointer to the open owner */
+	struct inode *inode;		/* Pointer to the inode */
+
+	unsigned long flags;		/* Do we hold any locks? */
+	struct semaphore lock_sema;	/* Serializes file locking operations */
+	spinlock_t state_lock;		/* Protects the lock_states list */
+
+	nfs4_stateid stateid;
+
+	unsigned int nreaders;
+	unsigned int nwriters;
+	int state;			/* State on the server (R,W, or RW) */
+	atomic_t count;
+};
+
+
+struct nfs4_exception {
+	long timeout;
+	int retry;
+};
+
+struct nfs4_state_recovery_ops {
+	int (*recover_open)(struct nfs4_state_owner *, struct nfs4_state *);
+	int (*recover_lock)(struct nfs4_state *, struct file_lock *);
+};
+
+extern struct dentry_operations nfs4_dentry_operations;
+extern struct inode_operations nfs4_dir_inode_operations;
+
+/* inode.c */
+extern ssize_t nfs4_getxattr(struct dentry *, const char *, void *, size_t);
+extern int nfs4_setxattr(struct dentry *, const char *, const void *, size_t, int);
+extern ssize_t nfs4_listxattr(struct dentry *, char *, size_t);
+
+
+/* nfs4proc.c */
+extern int nfs4_map_errors(int err);
+extern int nfs4_proc_setclientid(struct nfs4_client *, u32, unsigned short);
+extern int nfs4_proc_setclientid_confirm(struct nfs4_client *);
+extern int nfs4_proc_async_renew(struct nfs4_client *);
+extern int nfs4_proc_renew(struct nfs4_client *);
+extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode);
+extern struct inode *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
+extern int nfs4_open_revalidate(struct inode *, struct dentry *, int);
+
+extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
+extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;
+
+extern const u32 nfs4_fattr_bitmap[2];
+extern const u32 nfs4_statfs_bitmap[2];
+extern const u32 nfs4_pathconf_bitmap[2];
+extern const u32 nfs4_fsinfo_bitmap[2];
+
+/* nfs4renewd.c */
+extern void nfs4_schedule_state_renewal(struct nfs4_client *);
+extern void nfs4_renewd_prepare_shutdown(struct nfs_server *);
+extern void nfs4_kill_renewd(struct nfs4_client *);
+extern void nfs4_renew_state(void *);
+
+/* nfs4state.c */
+extern void init_nfsv4_state(struct nfs_server *);
+extern void destroy_nfsv4_state(struct nfs_server *);
+extern struct nfs4_client *nfs4_get_client(struct in_addr *);
+extern void nfs4_put_client(struct nfs4_client *clp);
+extern int nfs4_init_client(struct nfs4_client *clp);
+extern struct nfs4_client *nfs4_find_client(struct in_addr *);
+extern u32 nfs4_alloc_lockowner_id(struct nfs4_client *);
+
+extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
+extern void nfs4_put_state_owner(struct nfs4_state_owner *);
+extern void nfs4_drop_state_owner(struct nfs4_state_owner *);
+extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
+extern void nfs4_put_open_state(struct nfs4_state *);
+extern void nfs4_close_state(struct nfs4_state *, mode_t);
+extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode);
+extern void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp);
+extern void nfs4_schedule_state_recovery(struct nfs4_client *);
+extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl);
+extern void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *ls);
+extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t);
+
+extern const nfs4_stateid zero_stateid;
+
+/* nfs4xdr.c */
+extern uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus);
+extern struct rpc_procinfo nfs4_procedures[];
+
+struct nfs4_mount_data;
+
+/* callback_xdr.c */
+extern struct svc_version nfs4_callback_version1;
+
+#else
+
+#define init_nfsv4_state(server)  do { } while (0)
+#define destroy_nfsv4_state(server)       do { } while (0)
+#define nfs4_put_state_owner(inode, owner) do { } while (0)
+#define nfs4_put_open_state(state) do { } while (0)
+#define nfs4_close_state(a, b) do { } while (0)
+
+#endif /* CONFIG_NFS_V4 */
+#endif /* __LINUX_FS_NFS_NFS4_FS.H */
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 1d5cb3e..1b76f80 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -48,6 +48,7 @@
 #include <linux/smp_lock.h>
 #include <linux/namei.h>
 
+#include "nfs4_fs.h"
 #include "delegation.h"
 
 #define NFSDBG_FACILITY		NFSDBG_PROC
@@ -62,8 +63,6 @@
 extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus);
 extern struct rpc_procinfo nfs4_procedures[];
 
-extern nfs4_stateid zero_stateid;
-
 /* Prevent leaks of NFSv4 errors into userland */
 int nfs4_map_errors(int err)
 {
@@ -104,7 +103,7 @@
 	| FATTR4_WORD1_SPACE_TOTAL
 };
 
-u32 nfs4_pathconf_bitmap[2] = {
+const u32 nfs4_pathconf_bitmap[2] = {
 	FATTR4_WORD0_MAXLINK
 	| FATTR4_WORD0_MAXNAME,
 	0
@@ -124,7 +123,7 @@
 
 	BUG_ON(readdir->count < 80);
 	if (cookie > 2) {
-		readdir->cookie = (cookie > 2) ? cookie : 0;
+		readdir->cookie = cookie;
 		memcpy(&readdir->verifier, verifier, sizeof(readdir->verifier));
 		return;
 	}
@@ -270,14 +269,9 @@
 	int err;
 	do {
 		err = _nfs4_open_reclaim(sp, state);
-		switch (err) {
-			case 0:
-			case -NFS4ERR_STALE_CLIENTID:
-			case -NFS4ERR_STALE_STATEID:
-			case -NFS4ERR_EXPIRED:
-				return err;
-		}
-		err = nfs4_handle_exception(server, err, &exception);
+		if (err != -NFS4ERR_DELAY)
+			break;
+		nfs4_handle_exception(server, err, &exception);
 	} while (exception.retry);
 	return err;
 }
@@ -509,6 +503,20 @@
 	goto out_nodeleg;
 }
 
+static inline int nfs4_do_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
+{
+	struct nfs_server *server = NFS_SERVER(dentry->d_inode);
+	struct nfs4_exception exception = { };
+	int err;
+
+	do {
+		err = _nfs4_open_expired(sp, state, dentry);
+		if (err == -NFS4ERR_DELAY)
+			nfs4_handle_exception(server, err, &exception);
+	} while (exception.retry);
+	return err;
+}
+
 static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
 {
 	struct nfs_inode *nfsi = NFS_I(state->inode);
@@ -521,7 +529,7 @@
 			continue;
 		get_nfs_open_context(ctx);
 		spin_unlock(&state->inode->i_lock);
-		status = _nfs4_open_expired(sp, state, ctx->dentry);
+		status = nfs4_do_open_expired(sp, state, ctx->dentry);
 		put_nfs_open_context(ctx);
 		return status;
 	}
@@ -748,11 +756,10 @@
 
         fattr->valid = 0;
 
-	if (state != NULL)
+	if (state != NULL) {
 		msg.rpc_cred = state->owner->so_cred;
-	if (sattr->ia_valid & ATTR_SIZE)
-		nfs4_copy_stateid(&arg.stateid, state, NULL);
-	else
+		nfs4_copy_stateid(&arg.stateid, state, current->files);
+	} else
 		memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid));
 
 	return rpc_call_sync(server->client, &msg, 0);
@@ -1116,47 +1123,31 @@
 nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
 		  struct iattr *sattr)
 {
-	struct inode *		inode = dentry->d_inode;
-	int			size_change = sattr->ia_valid & ATTR_SIZE;
-	struct nfs4_state	*state = NULL;
-	int need_iput = 0;
+	struct rpc_cred *cred;
+	struct inode *inode = dentry->d_inode;
+	struct nfs4_state *state;
 	int status;
 
 	fattr->valid = 0;
 	
-	if (size_change) {
-		struct rpc_cred *cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
-		if (IS_ERR(cred))
-			return PTR_ERR(cred);
+	cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
+	if (IS_ERR(cred))
+		return PTR_ERR(cred);
+	/* Search for an existing WRITE delegation first */
+	state = nfs4_open_delegated(inode, FMODE_WRITE, cred);
+	if (!IS_ERR(state)) {
+		/* NB: nfs4_open_delegated() bumps the inode->i_count */
+		iput(inode);
+	} else {
+		/* Search for an existing open(O_WRITE) stateid */
 		state = nfs4_find_state(inode, cred, FMODE_WRITE);
-		if (state == NULL) {
-			state = nfs4_open_delegated(dentry->d_inode,
-					FMODE_WRITE, cred);
-			if (IS_ERR(state))
-				state = nfs4_do_open(dentry->d_parent->d_inode,
-						dentry, FMODE_WRITE,
-						NULL, cred);
-			need_iput = 1;
-		}
-		put_rpccred(cred);
-		if (IS_ERR(state))
-			return PTR_ERR(state);
-
-		if (state->inode != inode) {
-			printk(KERN_WARNING "nfs: raced in setattr (%p != %p), returning -EIO\n", inode, state->inode);
-			status = -EIO;
-			goto out;
-		}
 	}
+
 	status = nfs4_do_setattr(NFS_SERVER(inode), fattr,
 			NFS_FH(inode), sattr, state);
-out:
-	if (state) {
-		inode = state->inode;
+	if (state != NULL)
 		nfs4_close_state(state, FMODE_WRITE);
-		if (need_iput)
-			iput(inode);
-	}
+	put_rpccred(cred);
 	return status;
 }
 
@@ -1731,6 +1722,10 @@
 	};
 	int			status;
 
+	dprintk("%s: dentry = %s/%s, cookie = %Lu\n", __FUNCTION__,
+			dentry->d_parent->d_name.name,
+			dentry->d_name.name,
+			(unsigned long long)cookie);
 	lock_kernel();
 	nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args);
 	res.pgbase = args.pgbase;
@@ -1738,6 +1733,7 @@
 	if (status == 0)
 		memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE);
 	unlock_kernel();
+	dprintk("%s: returns %d\n", __FUNCTION__, status);
 	return status;
 }
 
@@ -2163,6 +2159,193 @@
 	return 0;
 }
 
+static inline int nfs4_server_supports_acls(struct nfs_server *server)
+{
+	return (server->caps & NFS_CAP_ACLS)
+		&& (server->acl_bitmask & ACL4_SUPPORT_ALLOW_ACL)
+		&& (server->acl_bitmask & ACL4_SUPPORT_DENY_ACL);
+}
+
+/* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_CACHE_SIZE, and that
+ * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_CACHE_SIZE) bytes on
+ * the stack.
+ */
+#define NFS4ACL_MAXPAGES (XATTR_SIZE_MAX >> PAGE_CACHE_SHIFT)
+
+static void buf_to_pages(const void *buf, size_t buflen,
+		struct page **pages, unsigned int *pgbase)
+{
+	const void *p = buf;
+
+	*pgbase = offset_in_page(buf);
+	p -= *pgbase;
+	while (p < buf + buflen) {
+		*(pages++) = virt_to_page(p);
+		p += PAGE_CACHE_SIZE;
+	}
+}
+
+struct nfs4_cached_acl {
+	int cached;
+	size_t len;
+	char data[0];
+};
+
+static void nfs4_set_cached_acl(struct inode *inode, struct nfs4_cached_acl *acl)
+{
+	struct nfs_inode *nfsi = NFS_I(inode);
+
+	spin_lock(&inode->i_lock);
+	kfree(nfsi->nfs4_acl);
+	nfsi->nfs4_acl = acl;
+	spin_unlock(&inode->i_lock);
+}
+
+static void nfs4_zap_acl_attr(struct inode *inode)
+{
+	nfs4_set_cached_acl(inode, NULL);
+}
+
+static inline ssize_t nfs4_read_cached_acl(struct inode *inode, char *buf, size_t buflen)
+{
+	struct nfs_inode *nfsi = NFS_I(inode);
+	struct nfs4_cached_acl *acl;
+	int ret = -ENOENT;
+
+	spin_lock(&inode->i_lock);
+	acl = nfsi->nfs4_acl;
+	if (acl == NULL)
+		goto out;
+	if (buf == NULL) /* user is just asking for length */
+		goto out_len;
+	if (acl->cached == 0)
+		goto out;
+	ret = -ERANGE; /* see getxattr(2) man page */
+	if (acl->len > buflen)
+		goto out;
+	memcpy(buf, acl->data, acl->len);
+out_len:
+	ret = acl->len;
+out:
+	spin_unlock(&inode->i_lock);
+	return ret;
+}
+
+static void nfs4_write_cached_acl(struct inode *inode, const char *buf, size_t acl_len)
+{
+	struct nfs4_cached_acl *acl;
+
+	if (buf && acl_len <= PAGE_SIZE) {
+		acl = kmalloc(sizeof(*acl) + acl_len, GFP_KERNEL);
+		if (acl == NULL)
+			goto out;
+		acl->cached = 1;
+		memcpy(acl->data, buf, acl_len);
+	} else {
+		acl = kmalloc(sizeof(*acl), GFP_KERNEL);
+		if (acl == NULL)
+			goto out;
+		acl->cached = 0;
+	}
+	acl->len = acl_len;
+out:
+	nfs4_set_cached_acl(inode, acl);
+}
+
+static inline ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen)
+{
+	struct page *pages[NFS4ACL_MAXPAGES];
+	struct nfs_getaclargs args = {
+		.fh = NFS_FH(inode),
+		.acl_pages = pages,
+		.acl_len = buflen,
+	};
+	size_t resp_len = buflen;
+	void *resp_buf;
+	struct rpc_message msg = {
+		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETACL],
+		.rpc_argp = &args,
+		.rpc_resp = &resp_len,
+	};
+	struct page *localpage = NULL;
+	int ret;
+
+	if (buflen < PAGE_SIZE) {
+		/* As long as we're doing a round trip to the server anyway,
+		 * let's be prepared for a page of acl data. */
+		localpage = alloc_page(GFP_KERNEL);
+		resp_buf = page_address(localpage);
+		if (localpage == NULL)
+			return -ENOMEM;
+		args.acl_pages[0] = localpage;
+		args.acl_pgbase = 0;
+		args.acl_len = PAGE_SIZE;
+	} else {
+		resp_buf = buf;
+		buf_to_pages(buf, buflen, args.acl_pages, &args.acl_pgbase);
+	}
+	ret = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+	if (ret)
+		goto out_free;
+	if (resp_len > args.acl_len)
+		nfs4_write_cached_acl(inode, NULL, resp_len);
+	else
+		nfs4_write_cached_acl(inode, resp_buf, resp_len);
+	if (buf) {
+		ret = -ERANGE;
+		if (resp_len > buflen)
+			goto out_free;
+		if (localpage)
+			memcpy(buf, resp_buf, resp_len);
+	}
+	ret = resp_len;
+out_free:
+	if (localpage)
+		__free_page(localpage);
+	return ret;
+}
+
+static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen)
+{
+	struct nfs_server *server = NFS_SERVER(inode);
+	int ret;
+
+	if (!nfs4_server_supports_acls(server))
+		return -EOPNOTSUPP;
+	ret = nfs_revalidate_inode(server, inode);
+	if (ret < 0)
+		return ret;
+	ret = nfs4_read_cached_acl(inode, buf, buflen);
+	if (ret != -ENOENT)
+		return ret;
+	return nfs4_get_acl_uncached(inode, buf, buflen);
+}
+
+static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen)
+{
+	struct nfs_server *server = NFS_SERVER(inode);
+	struct page *pages[NFS4ACL_MAXPAGES];
+	struct nfs_setaclargs arg = {
+		.fh		= NFS_FH(inode),
+		.acl_pages	= pages,
+		.acl_len	= buflen,
+	};
+	struct rpc_message msg = {
+		.rpc_proc	= &nfs4_procedures[NFSPROC4_CLNT_SETACL],
+		.rpc_argp	= &arg,
+		.rpc_resp	= NULL,
+	};
+	int ret;
+
+	if (!nfs4_server_supports_acls(server))
+		return -EOPNOTSUPP;
+	buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
+	ret = rpc_call_sync(NFS_SERVER(inode)->client, &msg, 0);
+	if (ret == 0)
+		nfs4_write_cached_acl(inode, buf, buflen);
+	return ret;
+}
+
 static int
 nfs4_async_handle_error(struct rpc_task *task, struct nfs_server *server)
 {
@@ -2448,14 +2631,11 @@
 	down_read(&clp->cl_sem);
 	nlo.clientid = clp->cl_clientid;
 	down(&state->lock_sema);
-	lsp = nfs4_find_lock_state(state, request->fl_owner);
-	if (lsp)
-		nlo.id = lsp->ls_id; 
-	else {
-		spin_lock(&clp->cl_lock);
-		nlo.id = nfs4_alloc_lockowner_id(clp);
-		spin_unlock(&clp->cl_lock);
-	}
+	status = nfs4_set_lock_state(state, request);
+	if (status != 0)
+		goto out;
+	lsp = request->fl_u.nfs4_fl.owner;
+	nlo.id = lsp->ls_id; 
 	arg.u.lockt = &nlo;
 	status = rpc_call_sync(server->client, &msg, 0);
 	if (!status) {
@@ -2476,8 +2656,7 @@
 		request->fl_pid = 0;
 		status = 0;
 	}
-	if (lsp)
-		nfs4_put_lock_state(lsp);
+out:
 	up(&state->lock_sema);
 	up_read(&clp->cl_sem);
 	return status;
@@ -2537,28 +2716,26 @@
 	};
 	struct nfs4_lock_state *lsp;
 	struct nfs_locku_opargs luargs;
-	int status = 0;
+	int status;
 			
 	down_read(&clp->cl_sem);
 	down(&state->lock_sema);
-	lsp = nfs4_find_lock_state(state, request->fl_owner);
-	if (!lsp)
+	status = nfs4_set_lock_state(state, request);
+	if (status != 0)
 		goto out;
+	lsp = request->fl_u.nfs4_fl.owner;
 	/* We might have lost the locks! */
-	if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) {
-		luargs.seqid = lsp->ls_seqid;
-		memcpy(&luargs.stateid, &lsp->ls_stateid, sizeof(luargs.stateid));
-		arg.u.locku = &luargs;
-		status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
-		nfs4_increment_lock_seqid(status, lsp);
-	}
+	if ((lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0)
+		goto out;
+	luargs.seqid = lsp->ls_seqid;
+	memcpy(&luargs.stateid, &lsp->ls_stateid, sizeof(luargs.stateid));
+	arg.u.locku = &luargs;
+	status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
+	nfs4_increment_lock_seqid(status, lsp);
 
-	if (status == 0) {
+	if (status == 0)
 		memcpy(&lsp->ls_stateid,  &res.u.stateid, 
 				sizeof(lsp->ls_stateid));
-		nfs4_notify_unlck(state, request, lsp);
-	}
-	nfs4_put_lock_state(lsp);
 out:
 	up(&state->lock_sema);
 	if (status == 0)
@@ -2584,7 +2761,7 @@
 {
 	struct inode *inode = state->inode;
 	struct nfs_server *server = NFS_SERVER(inode);
-	struct nfs4_lock_state *lsp;
+	struct nfs4_lock_state *lsp = request->fl_u.nfs4_fl.owner;
 	struct nfs_lockargs arg = {
 		.fh = NFS_FH(inode),
 		.type = nfs4_lck_type(cmd, request),
@@ -2606,9 +2783,6 @@
 	};
 	int status;
 
-	lsp = nfs4_get_lock_state(state, request->fl_owner);
-	if (lsp == NULL)
-		return -ENOMEM;
 	if (!(lsp->ls_flags & NFS_LOCK_INITIALIZED)) {
 		struct nfs4_state_owner *owner = state->owner;
 		struct nfs_open_to_lock otl = {
@@ -2630,38 +2804,57 @@
 		* seqid mutating errors */
 		nfs4_increment_seqid(status, owner);
 		up(&owner->so_sema);
+		if (status == 0) {
+			lsp->ls_flags |= NFS_LOCK_INITIALIZED;
+			lsp->ls_seqid++;
+		}
 	} else {
 		struct nfs_exist_lock el = {
 			.seqid = lsp->ls_seqid,
 		};
 		memcpy(&el.stateid, &lsp->ls_stateid, sizeof(el.stateid));
 		largs.u.exist_lock = &el;
-		largs.new_lock_owner = 0;
 		arg.u.lock = &largs;
 		status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
+		/* increment seqid on success, and * seqid mutating errors*/
+		nfs4_increment_lock_seqid(status, lsp);
 	}
-	/* increment seqid on success, and * seqid mutating errors*/
-	nfs4_increment_lock_seqid(status, lsp);
 	/* save the returned stateid. */
-	if (status == 0) {
+	if (status == 0)
 		memcpy(&lsp->ls_stateid, &res.u.stateid, sizeof(nfs4_stateid));
-		lsp->ls_flags |= NFS_LOCK_INITIALIZED;
-		if (!reclaim)
-			nfs4_notify_setlk(state, request, lsp);
-	} else if (status == -NFS4ERR_DENIED)
+	else if (status == -NFS4ERR_DENIED)
 		status = -EAGAIN;
-	nfs4_put_lock_state(lsp);
 	return status;
 }
 
 static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
 {
-	return _nfs4_do_setlk(state, F_SETLK, request, 1);
+	struct nfs_server *server = NFS_SERVER(state->inode);
+	struct nfs4_exception exception = { };
+	int err;
+
+	do {
+		err = _nfs4_do_setlk(state, F_SETLK, request, 1);
+		if (err != -NFS4ERR_DELAY)
+			break;
+		nfs4_handle_exception(server, err, &exception);
+	} while (exception.retry);
+	return err;
 }
 
 static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request)
 {
-	return _nfs4_do_setlk(state, F_SETLK, request, 0);
+	struct nfs_server *server = NFS_SERVER(state->inode);
+	struct nfs4_exception exception = { };
+	int err;
+
+	do {
+		err = _nfs4_do_setlk(state, F_SETLK, request, 0);
+		if (err != -NFS4ERR_DELAY)
+			break;
+		nfs4_handle_exception(server, err, &exception);
+	} while (exception.retry);
+	return err;
 }
 
 static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
@@ -2671,7 +2864,9 @@
 
 	down_read(&clp->cl_sem);
 	down(&state->lock_sema);
-	status = _nfs4_do_setlk(state, cmd, request, 0);
+	status = nfs4_set_lock_state(state, request);
+	if (status == 0)
+		status = _nfs4_do_setlk(state, cmd, request, 0);
 	up(&state->lock_sema);
 	if (status == 0) {
 		/* Note: we always want to sleep here! */
@@ -2729,10 +2924,53 @@
 		if (signalled())
 			break;
 	} while(status < 0);
-
 	return status;
 }
 
+
+#define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"
+
+int nfs4_setxattr(struct dentry *dentry, const char *key, const void *buf,
+		size_t buflen, int flags)
+{
+	struct inode *inode = dentry->d_inode;
+
+	if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0)
+		return -EOPNOTSUPP;
+
+	if (!S_ISREG(inode->i_mode) &&
+	    (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
+		return -EPERM;
+
+	return nfs4_proc_set_acl(inode, buf, buflen);
+}
+
+/* The getxattr man page suggests returning -ENODATA for unknown attributes,
+ * and that's what we'll do for e.g. user attributes that haven't been set.
+ * But we'll follow ext2/ext3's lead by returning -EOPNOTSUPP for unsupported
+ * attributes in kernel-managed attribute namespaces. */
+ssize_t nfs4_getxattr(struct dentry *dentry, const char *key, void *buf,
+		size_t buflen)
+{
+	struct inode *inode = dentry->d_inode;
+
+	if (strcmp(key, XATTR_NAME_NFSV4_ACL) != 0)
+		return -EOPNOTSUPP;
+
+	return nfs4_proc_get_acl(inode, buf, buflen);
+}
+
+ssize_t nfs4_listxattr(struct dentry *dentry, char *buf, size_t buflen)
+{
+	size_t len = strlen(XATTR_NAME_NFSV4_ACL) + 1;
+
+	if (buf && buflen < len)
+		return -ERANGE;
+	if (buf)
+		memcpy(buf, XATTR_NAME_NFSV4_ACL, len);
+	return len;
+}
+
 struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = {
 	.recover_open	= nfs4_open_reclaim,
 	.recover_lock	= nfs4_lock_reclaim,
@@ -2743,10 +2981,20 @@
 	.recover_lock	= nfs4_lock_expired,
 };
 
+static struct inode_operations nfs4_file_inode_operations = {
+	.permission	= nfs_permission,
+	.getattr	= nfs_getattr,
+	.setattr	= nfs_setattr,
+	.getxattr	= nfs4_getxattr,
+	.setxattr	= nfs4_setxattr,
+	.listxattr	= nfs4_listxattr,
+};
+
 struct nfs_rpc_ops	nfs_v4_clientops = {
 	.version	= 4,			/* protocol version */
 	.dentry_ops	= &nfs4_dentry_operations,
 	.dir_inode_ops	= &nfs4_dir_inode_operations,
+	.file_inode_ops	= &nfs4_file_inode_operations,
 	.getroot	= nfs4_proc_get_root,
 	.getattr	= nfs4_proc_getattr,
 	.setattr	= nfs4_proc_setattr,
@@ -2777,6 +3025,7 @@
 	.file_open      = nfs4_proc_file_open,
 	.file_release   = nfs4_proc_file_release,
 	.lock		= nfs4_proc_lock,
+	.clear_acl_cache = nfs4_zap_acl_attr,
 };
 
 /*
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c
index 667e06f..a300162 100644
--- a/fs/nfs/nfs4renewd.c
+++ b/fs/nfs/nfs4renewd.c
@@ -53,6 +53,7 @@
 #include <linux/nfs.h>
 #include <linux/nfs4.h>
 #include <linux/nfs_fs.h>
+#include "nfs4_fs.h"
 
 #define NFSDBG_FACILITY	NFSDBG_PROC
 
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 231cebc..afe587d 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -46,24 +46,18 @@
 #include <linux/workqueue.h>
 #include <linux/bitops.h>
 
+#include "nfs4_fs.h"
 #include "callback.h"
 #include "delegation.h"
 
 #define OPENOWNER_POOL_SIZE	8
 
+const nfs4_stateid zero_stateid;
+
 static DEFINE_SPINLOCK(state_spinlock);
-
-nfs4_stateid zero_stateid;
-
-#if 0
-nfs4_stateid one_stateid =
-	{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-#endif
-
 static LIST_HEAD(nfs4_clientid_list);
 
 static void nfs4_recover_state(void *);
-extern void nfs4_renew_state(void *);
 
 void
 init_nfsv4_state(struct nfs_server *server)
@@ -116,6 +110,7 @@
 	INIT_LIST_HEAD(&clp->cl_superblocks);
 	init_waitqueue_head(&clp->cl_waitq);
 	rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client");
+	clp->cl_rpcclient = ERR_PTR(-EINVAL);
 	clp->cl_boot_time = CURRENT_TIME;
 	clp->cl_state = 1 << NFS4CLNT_OK;
 	return clp;
@@ -137,7 +132,7 @@
 	if (clp->cl_cred)
 		put_rpccred(clp->cl_cred);
 	nfs_idmap_delete(clp);
-	if (clp->cl_rpcclient)
+	if (!IS_ERR(clp->cl_rpcclient))
 		rpc_shutdown_client(clp->cl_rpcclient);
 	kfree(clp);
 	nfs_callback_down();
@@ -365,7 +360,7 @@
 	atomic_set(&state->count, 1);
 	INIT_LIST_HEAD(&state->lock_states);
 	init_MUTEX(&state->lock_sema);
-	rwlock_init(&state->state_lock);
+	spin_lock_init(&state->state_lock);
 	return state;
 }
 
@@ -547,16 +542,6 @@
 	return NULL;
 }
 
-struct nfs4_lock_state *
-nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
-{
-	struct nfs4_lock_state *lsp;
-	read_lock(&state->state_lock);
-	lsp = __nfs4_find_lock_state(state, fl_owner);
-	read_unlock(&state->state_lock);
-	return lsp;
-}
-
 /*
  * Return a compatible lock_state. If no initialized lock_state structure
  * exists, return an uninitialized one.
@@ -573,14 +558,13 @@
 		return NULL;
 	lsp->ls_flags = 0;
 	lsp->ls_seqid = 0;	/* arbitrary */
-	lsp->ls_id = -1; 
 	memset(lsp->ls_stateid.data, 0, sizeof(lsp->ls_stateid.data));
 	atomic_set(&lsp->ls_count, 1);
 	lsp->ls_owner = fl_owner;
-	INIT_LIST_HEAD(&lsp->ls_locks);
 	spin_lock(&clp->cl_lock);
 	lsp->ls_id = nfs4_alloc_lockowner_id(clp);
 	spin_unlock(&clp->cl_lock);
+	INIT_LIST_HEAD(&lsp->ls_locks);
 	return lsp;
 }
 
@@ -590,34 +574,103 @@
  *
  * The caller must be holding state->lock_sema and clp->cl_sem
  */
-struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner)
+static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner)
 {
-	struct nfs4_lock_state * lsp;
+	struct nfs4_lock_state *lsp, *new = NULL;
 	
-	lsp = nfs4_find_lock_state(state, owner);
-	if (lsp == NULL)
-		lsp = nfs4_alloc_lock_state(state, owner);
+	for(;;) {
+		spin_lock(&state->state_lock);
+		lsp = __nfs4_find_lock_state(state, owner);
+		if (lsp != NULL)
+			break;
+		if (new != NULL) {
+			new->ls_state = state;
+			list_add(&new->ls_locks, &state->lock_states);
+			set_bit(LK_STATE_IN_USE, &state->flags);
+			lsp = new;
+			new = NULL;
+			break;
+		}
+		spin_unlock(&state->state_lock);
+		new = nfs4_alloc_lock_state(state, owner);
+		if (new == NULL)
+			return NULL;
+	}
+	spin_unlock(&state->state_lock);
+	kfree(new);
 	return lsp;
 }
 
 /*
+ * Release reference to lock_state, and free it if we see that
+ * it is no longer in use
+ */
+static void nfs4_put_lock_state(struct nfs4_lock_state *lsp)
+{
+	struct nfs4_state *state;
+
+	if (lsp == NULL)
+		return;
+	state = lsp->ls_state;
+	if (!atomic_dec_and_lock(&lsp->ls_count, &state->state_lock))
+		return;
+	list_del(&lsp->ls_locks);
+	if (list_empty(&state->lock_states))
+		clear_bit(LK_STATE_IN_USE, &state->flags);
+	spin_unlock(&state->state_lock);
+	kfree(lsp);
+}
+
+static void nfs4_fl_copy_lock(struct file_lock *dst, struct file_lock *src)
+{
+	struct nfs4_lock_state *lsp = src->fl_u.nfs4_fl.owner;
+
+	dst->fl_u.nfs4_fl.owner = lsp;
+	atomic_inc(&lsp->ls_count);
+}
+
+static void nfs4_fl_release_lock(struct file_lock *fl)
+{
+	nfs4_put_lock_state(fl->fl_u.nfs4_fl.owner);
+}
+
+static struct file_lock_operations nfs4_fl_lock_ops = {
+	.fl_copy_lock = nfs4_fl_copy_lock,
+	.fl_release_private = nfs4_fl_release_lock,
+};
+
+int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl)
+{
+	struct nfs4_lock_state *lsp;
+
+	if (fl->fl_ops != NULL)
+		return 0;
+	lsp = nfs4_get_lock_state(state, fl->fl_owner);
+	if (lsp == NULL)
+		return -ENOMEM;
+	fl->fl_u.nfs4_fl.owner = lsp;
+	fl->fl_ops = &nfs4_fl_lock_ops;
+	return 0;
+}
+
+/*
  * Byte-range lock aware utility to initialize the stateid of read/write
  * requests.
  */
-void
-nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner)
+void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner)
 {
-	if (test_bit(LK_STATE_IN_USE, &state->flags)) {
-		struct nfs4_lock_state *lsp;
+	struct nfs4_lock_state *lsp;
 
-		lsp = nfs4_find_lock_state(state, fl_owner);
-		if (lsp) {
-			memcpy(dst, &lsp->ls_stateid, sizeof(*dst));
-			nfs4_put_lock_state(lsp);
-			return;
-		}
-	}
 	memcpy(dst, &state->stateid, sizeof(*dst));
+	if (test_bit(LK_STATE_IN_USE, &state->flags) == 0)
+		return;
+
+	spin_lock(&state->state_lock);
+	lsp = __nfs4_find_lock_state(state, fl_owner);
+	if (lsp != NULL && (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0)
+		memcpy(dst, &lsp->ls_stateid, sizeof(*dst));
+	spin_unlock(&state->state_lock);
+	nfs4_put_lock_state(lsp);
 }
 
 /*
@@ -629,84 +682,6 @@
 		lsp->ls_seqid++;
 }
 
-/* 
-* Check to see if the request lock (type FL_UNLK) effects the fl lock.
-*
-* fl and request must have the same posix owner
-*
-* return: 
-* 0 -> fl not effected by request
-* 1 -> fl consumed by request
-*/
-
-static int
-nfs4_check_unlock(struct file_lock *fl, struct file_lock *request)
-{
-	if (fl->fl_start >= request->fl_start && fl->fl_end <= request->fl_end)
-		return 1;
-	return 0;
-}
-
-/*
- * Post an initialized lock_state on the state->lock_states list.
- */
-void nfs4_notify_setlk(struct nfs4_state *state, struct file_lock *request, struct nfs4_lock_state *lsp)
-{
-	if (!list_empty(&lsp->ls_locks))
-		return;
-	atomic_inc(&lsp->ls_count);
-	write_lock(&state->state_lock);
-	list_add(&lsp->ls_locks, &state->lock_states);
-	set_bit(LK_STATE_IN_USE, &state->flags);
-	write_unlock(&state->state_lock);
-}
-
-/* 
- * to decide to 'reap' lock state:
- * 1) search i_flock for file_locks with fl.lock_state = to ls.
- * 2) determine if unlock will consume found lock. 
- * 	if so, reap
- *
- * 	else, don't reap.
- *
- */
-void
-nfs4_notify_unlck(struct nfs4_state *state, struct file_lock *request, struct nfs4_lock_state *lsp)
-{
-	struct inode *inode = state->inode;
-	struct file_lock *fl;
-
-	for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
-		if (!(fl->fl_flags & FL_POSIX))
-			continue;
-		if (fl->fl_owner != lsp->ls_owner)
-			continue;
-		/* Exit if we find at least one lock which is not consumed */
-		if (nfs4_check_unlock(fl,request) == 0)
-			return;
-	}
-
-	write_lock(&state->state_lock);
-	list_del_init(&lsp->ls_locks);
-	if (list_empty(&state->lock_states))
-		clear_bit(LK_STATE_IN_USE, &state->flags);
-	write_unlock(&state->state_lock);
-	nfs4_put_lock_state(lsp);
-}
-
-/*
- * Release reference to lock_state, and free it if we see that
- * it is no longer in use
- */
-void
-nfs4_put_lock_state(struct nfs4_lock_state *lsp)
-{
-	if (!atomic_dec_and_test(&lsp->ls_count))
-		return;
-	BUG_ON (!list_empty(&lsp->ls_locks));
-	kfree(lsp);
-}
-
 /*
 * Called with sp->so_sema and clp->cl_sem held.
 *
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 5f4de05..6c564ef 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -51,6 +51,7 @@
 #include <linux/nfs4.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_idmap.h>
+#include "nfs4_fs.h"
 
 #define NFSDBG_FACILITY		NFSDBG_XDR
 
@@ -82,12 +83,16 @@
 #define encode_getfh_maxsz      (op_encode_hdr_maxsz)
 #define decode_getfh_maxsz      (op_decode_hdr_maxsz + 1 + \
 				((3+NFS4_FHSIZE) >> 2))
-#define encode_getattr_maxsz    (op_encode_hdr_maxsz + 3)
+#define nfs4_fattr_bitmap_maxsz 3
+#define encode_getattr_maxsz    (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz)
 #define nfs4_name_maxsz		(1 + ((3 + NFS4_MAXNAMLEN) >> 2))
 #define nfs4_path_maxsz		(1 + ((3 + NFS4_MAXPATHLEN) >> 2))
-#define nfs4_fattr_bitmap_maxsz (36 + 2 * nfs4_name_maxsz)
-#define decode_getattr_maxsz    (op_decode_hdr_maxsz + 3 + \
-                                nfs4_fattr_bitmap_maxsz)
+/* This is based on getfattr, which uses the most attributes: */
+#define nfs4_fattr_value_maxsz	(1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \
+				3 + 3 + 3 + 2 * nfs4_name_maxsz))
+#define nfs4_fattr_maxsz	(nfs4_fattr_bitmap_maxsz + \
+				nfs4_fattr_value_maxsz)
+#define decode_getattr_maxsz    (op_decode_hdr_maxsz + nfs4_fattr_maxsz)
 #define encode_savefh_maxsz     (op_encode_hdr_maxsz)
 #define decode_savefh_maxsz     (op_decode_hdr_maxsz)
 #define encode_fsinfo_maxsz	(op_encode_hdr_maxsz + 2)
@@ -122,11 +127,11 @@
 #define encode_symlink_maxsz	(op_encode_hdr_maxsz + \
 				1 + nfs4_name_maxsz + \
 				nfs4_path_maxsz + \
-				nfs4_fattr_bitmap_maxsz)
+				nfs4_fattr_maxsz)
 #define decode_symlink_maxsz	(op_decode_hdr_maxsz + 8)
 #define encode_create_maxsz	(op_encode_hdr_maxsz + \
 				2 + nfs4_name_maxsz + \
-				nfs4_fattr_bitmap_maxsz)
+				nfs4_fattr_maxsz)
 #define decode_create_maxsz	(op_decode_hdr_maxsz + 8)
 #define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4)
 #define decode_delegreturn_maxsz (op_decode_hdr_maxsz)
@@ -205,7 +210,7 @@
 #define NFS4_enc_setattr_sz     (compound_encode_hdr_maxsz + \
                                 encode_putfh_maxsz + \
                                 op_encode_hdr_maxsz + 4 + \
-                                nfs4_fattr_bitmap_maxsz + \
+                                nfs4_fattr_maxsz + \
                                 encode_getattr_maxsz)
 #define NFS4_dec_setattr_sz     (compound_decode_hdr_maxsz + \
                                 decode_putfh_maxsz + \
@@ -360,6 +365,20 @@
 				encode_delegreturn_maxsz)
 #define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \
 				decode_delegreturn_maxsz)
+#define NFS4_enc_getacl_sz	(compound_encode_hdr_maxsz + \
+				encode_putfh_maxsz + \
+				encode_getattr_maxsz)
+#define NFS4_dec_getacl_sz	(compound_decode_hdr_maxsz + \
+				decode_putfh_maxsz + \
+				op_decode_hdr_maxsz + \
+				nfs4_fattr_bitmap_maxsz + 1)
+#define NFS4_enc_setacl_sz	(compound_encode_hdr_maxsz + \
+				encode_putfh_maxsz + \
+				op_encode_hdr_maxsz + 4 + \
+				nfs4_fattr_bitmap_maxsz + 1)
+#define NFS4_dec_setacl_sz	(compound_decode_hdr_maxsz + \
+				decode_putfh_maxsz + \
+				op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz)
 
 static struct {
 	unsigned int	mode;
@@ -459,7 +478,7 @@
 	 * In the worst-case, this would be
 	 *   12(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime)
 	 *          = 36 bytes, plus any contribution from variable-length fields
-	 *            such as owner/group/acl's.
+	 *            such as owner/group.
 	 */
 	len = 16;
 
@@ -660,8 +679,6 @@
 
 static int encode_getfattr(struct xdr_stream *xdr, const u32* bitmask)
 {
-	extern u32 nfs4_fattr_bitmap[];
-
 	return encode_getattr_two(xdr,
 			bitmask[0] & nfs4_fattr_bitmap[0],
 			bitmask[1] & nfs4_fattr_bitmap[1]);
@@ -669,8 +686,6 @@
 
 static int encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask)
 {
-	extern u32 nfs4_fsinfo_bitmap[];
-
 	return encode_getattr_two(xdr, bitmask[0] & nfs4_fsinfo_bitmap[0],
 			bitmask[1] & nfs4_fsinfo_bitmap[1]);
 }
@@ -969,7 +984,6 @@
 
 static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx)
 {
-	extern nfs4_stateid zero_stateid;
 	nfs4_stateid stateid;
 	uint32_t *p;
 
@@ -1000,6 +1014,10 @@
 static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req)
 {
 	struct rpc_auth *auth = req->rq_task->tk_auth;
+	uint32_t attrs[2] = {
+		FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID,
+		FATTR4_WORD1_MOUNTED_ON_FILEID,
+	};
 	int replen;
 	uint32_t *p;
 
@@ -1010,13 +1028,20 @@
 	WRITE32(readdir->count >> 1);  /* We're not doing readdirplus */
 	WRITE32(readdir->count);
 	WRITE32(2);
-	if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID) {
-		WRITE32(0);
-		WRITE32(FATTR4_WORD1_MOUNTED_ON_FILEID);
-	} else {
-		WRITE32(FATTR4_WORD0_FILEID);
-		WRITE32(0);
-	}
+	/* Switch to mounted_on_fileid if the server supports it */
+	if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)
+		attrs[0] &= ~FATTR4_WORD0_FILEID;
+	else
+		attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
+	WRITE32(attrs[0] & readdir->bitmask[0]);
+	WRITE32(attrs[1] & readdir->bitmask[1]);
+	dprintk("%s: cookie = %Lu, verifier = 0x%x%x, bitmap = 0x%x%x\n",
+			__FUNCTION__,
+			(unsigned long long)readdir->cookie,
+			((u32 *)readdir->verifier.data)[0],
+			((u32 *)readdir->verifier.data)[1],
+			attrs[0] & readdir->bitmask[0],
+			attrs[1] & readdir->bitmask[1]);
 
 	/* set up reply kvec
 	 *    toplevel_status + taglen + rescount + OP_PUTFH + status
@@ -1025,6 +1050,9 @@
 	replen = (RPC_REPHDRSIZE + auth->au_rslack + 9) << 2;
 	xdr_inline_pages(&req->rq_rcv_buf, replen, readdir->pages,
 			 readdir->pgbase, readdir->count);
+	dprintk("%s: inlined page args = (%u, %p, %u, %u)\n",
+			__FUNCTION__, replen, readdir->pages,
+			readdir->pgbase, readdir->count);
 
 	return 0;
 }
@@ -1089,6 +1117,25 @@
 }
 
 static int
+encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg)
+{
+	uint32_t *p;
+
+	RESERVE_SPACE(4+sizeof(zero_stateid.data));
+	WRITE32(OP_SETATTR);
+	WRITEMEM(zero_stateid.data, sizeof(zero_stateid.data));
+	RESERVE_SPACE(2*4);
+	WRITE32(1);
+	WRITE32(FATTR4_WORD0_ACL);
+	if (arg->acl_len % 4)
+		return -EINVAL;
+	RESERVE_SPACE(4);
+	WRITE32(arg->acl_len);
+	xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len);
+	return 0;
+}
+
+static int
 encode_savefh(struct xdr_stream *xdr)
 {
 	uint32_t *p;
@@ -1632,6 +1679,34 @@
 }
 
 /*
+ * Encode a GETACL request
+ */
+static int
+nfs4_xdr_enc_getacl(struct rpc_rqst *req, uint32_t *p,
+		struct nfs_getaclargs *args)
+{
+	struct xdr_stream xdr;
+	struct rpc_auth *auth = req->rq_task->tk_auth;
+	struct compound_hdr hdr = {
+		.nops   = 2,
+	};
+	int replen, status;
+
+	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+	encode_compound_hdr(&xdr, &hdr);
+	status = encode_putfh(&xdr, args->fh);
+	if (status)
+		goto out;
+	status = encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0);
+	/* set up reply buffer: */
+	replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_getacl_sz) << 2;
+	xdr_inline_pages(&req->rq_rcv_buf, replen,
+		args->acl_pages, args->acl_pgbase, args->acl_len);
+out:
+	return status;
+}
+
+/*
  * Encode a WRITE request
  */
 static int nfs4_xdr_enc_write(struct rpc_rqst *req, uint32_t *p, struct nfs_writeargs *args)
@@ -1697,7 +1772,6 @@
  */
 static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, uint32_t *p, const struct nfs4_pathconf_arg *args)
 {
-	extern u32 nfs4_pathconf_bitmap[2];
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
 		.nops = 2,
@@ -1718,7 +1792,6 @@
  */
 static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, uint32_t *p, const struct nfs4_statfs_arg *args)
 {
-	extern u32 nfs4_statfs_bitmap[];
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
 		.nops = 2,
@@ -3003,6 +3076,11 @@
 		return status;
 	READ_BUF(8);
 	COPYMEM(readdir->verifier.data, 8);
+	dprintk("%s: verifier = 0x%x%x\n",
+			__FUNCTION__,
+			((u32 *)readdir->verifier.data)[0],
+			((u32 *)readdir->verifier.data)[1]);
+
 
 	hdrlen = (char *) p - (char *) iov->iov_base;
 	recvd = rcvbuf->len - hdrlen;
@@ -3017,12 +3095,14 @@
 	for (nr = 0; *p++; nr++) {
 		if (p + 3 > end)
 			goto short_pkt;
+		dprintk("cookie = %Lu, ", *((unsigned long long *)p));
 		p += 2;			/* cookie */
 		len = ntohl(*p++);	/* filename length */
 		if (len > NFS4_MAXNAMLEN) {
 			printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)\n", len);
 			goto err_unmap;
 		}
+		dprintk("filename = %*s\n", len, (char *)p);
 		p += XDR_QUADLEN(len);
 		if (p + 1 > end)
 			goto short_pkt;
@@ -3042,6 +3122,7 @@
 	kunmap_atomic(kaddr, KM_USER0);
 	return 0;
 short_pkt:
+	dprintk("%s: short packet at entry %d\n", __FUNCTION__, nr);
 	entry[0] = entry[1] = 0;
 	/* truncate listing ? */
 	if (!nr) {
@@ -3127,6 +3208,47 @@
 	return decode_op_hdr(xdr, OP_RENEW);
 }
 
+static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
+		size_t *acl_len)
+{
+	uint32_t *savep;
+	uint32_t attrlen,
+		 bitmap[2] = {0};
+	struct kvec *iov = req->rq_rcv_buf.head;
+	int status;
+
+	*acl_len = 0;
+	if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
+		goto out;
+	if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
+		goto out;
+	if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
+		goto out;
+
+	if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U)))
+		return -EIO;
+	if (likely(bitmap[0] & FATTR4_WORD0_ACL)) {
+		int hdrlen, recvd;
+
+		/* We ignore &savep and don't do consistency checks on
+		 * the attr length.  Let userspace figure it out.... */
+		hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base;
+		recvd = req->rq_rcv_buf.len - hdrlen;
+		if (attrlen > recvd) {
+			printk(KERN_WARNING "NFS: server cheating in getattr"
+					" acl reply: attrlen %u > recvd %u\n",
+					attrlen, recvd);
+			return -EINVAL;
+		}
+		if (attrlen <= *acl_len)
+			xdr_read_pages(xdr, attrlen);
+		*acl_len = attrlen;
+	}
+
+out:
+	return status;
+}
+
 static int
 decode_savefh(struct xdr_stream *xdr)
 {
@@ -3418,6 +3540,71 @@
 
 }
 
+/*
+ * Encode an SETACL request
+ */
+static int
+nfs4_xdr_enc_setacl(struct rpc_rqst *req, uint32_t *p, struct nfs_setaclargs *args)
+{
+        struct xdr_stream xdr;
+        struct compound_hdr hdr = {
+                .nops   = 2,
+        };
+        int status;
+
+        xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+        encode_compound_hdr(&xdr, &hdr);
+        status = encode_putfh(&xdr, args->fh);
+        if (status)
+                goto out;
+        status = encode_setacl(&xdr, args);
+out:
+        return status;
+}
+/*
+ * Decode SETACL response
+ */
+static int
+nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, uint32_t *p, void *res)
+{
+	struct xdr_stream xdr;
+	struct compound_hdr hdr;
+	int status;
+
+	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+	status = decode_compound_hdr(&xdr, &hdr);
+	if (status)
+		goto out;
+	status = decode_putfh(&xdr);
+	if (status)
+		goto out;
+	status = decode_setattr(&xdr, res);
+out:
+	return status;
+}
+
+/*
+ * Decode GETACL response
+ */
+static int
+nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, uint32_t *p, size_t *acl_len)
+{
+	struct xdr_stream xdr;
+	struct compound_hdr hdr;
+	int status;
+
+	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+	status = decode_compound_hdr(&xdr, &hdr);
+	if (status)
+		goto out;
+	status = decode_putfh(&xdr);
+	if (status)
+		goto out;
+	status = decode_getacl(&xdr, rqstp, acl_len);
+
+out:
+	return status;
+}
 
 /*
  * Decode CLOSE response
@@ -3895,6 +4082,12 @@
 	}
 	len = XDR_QUADLEN(ntohl(*p++));	/* attribute buffer length */
 	if (len > 0) {
+		if (bitmap[0] & FATTR4_WORD0_RDATTR_ERROR) {
+			bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR;
+			/* Ignore the return value of rdattr_error for now */
+			p++;
+			len--;
+		}
 		if (bitmap[0] == 0 && bitmap[1] == FATTR4_WORD1_MOUNTED_ON_FILEID)
 			xdr_decode_hyper(p, &entry->ino);
 		else if (bitmap[0] == FATTR4_WORD0_FILEID)
@@ -3934,6 +4127,8 @@
 	{ NFS4ERR_DQUOT,	EDQUOT		},
 	{ NFS4ERR_STALE,	ESTALE		},
 	{ NFS4ERR_BADHANDLE,	EBADHANDLE	},
+	{ NFS4ERR_BADOWNER,	EINVAL		},
+	{ NFS4ERR_BADNAME,	EINVAL		},
 	{ NFS4ERR_BAD_COOKIE,	EBADCOOKIE	},
 	{ NFS4ERR_NOTSUPP,	ENOTSUPP	},
 	{ NFS4ERR_TOOSMALL,	ETOOSMALL	},
@@ -4019,6 +4214,8 @@
   PROC(READDIR,		enc_readdir,	dec_readdir),
   PROC(SERVER_CAPS,	enc_server_caps, dec_server_caps),
   PROC(DELEGRETURN,	enc_delegreturn, dec_delegreturn),
+  PROC(GETACL,		enc_getacl,	dec_getacl),
+  PROC(SETACL,		enc_setacl,	dec_setacl),
 };
 
 struct rpc_version		nfs_version4 = {
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
index fd5bc59..1b272a1 100644
--- a/fs/nfs/nfsroot.c
+++ b/fs/nfs/nfsroot.c
@@ -124,6 +124,7 @@
 	Opt_soft, Opt_hard, Opt_intr,
 	Opt_nointr, Opt_posix, Opt_noposix, Opt_cto, Opt_nocto, Opt_ac, 
 	Opt_noac, Opt_lock, Opt_nolock, Opt_v2, Opt_v3, Opt_udp, Opt_tcp,
+	Opt_acl, Opt_noacl,
 	/* Error token */
 	Opt_err
 };
@@ -158,6 +159,8 @@
 	{Opt_udp, "udp"},
 	{Opt_tcp, "proto=tcp"},
 	{Opt_tcp, "tcp"},
+	{Opt_acl, "acl"},
+	{Opt_noacl, "noacl"},
 	{Opt_err, NULL}
 	
 };
@@ -266,6 +269,12 @@
 			case Opt_tcp:
 				nfs_data.flags |= NFS_MOUNT_TCP;
 				break;
+			case Opt_acl:
+				nfs_data.flags &= ~NFS_MOUNT_NOACL;
+				break;
+			case Opt_noacl:
+				nfs_data.flags |= NFS_MOUNT_NOACL;
+				break;
 			default : 
 				return 0;
 		}
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index 4f1ba72..d53857b 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -107,11 +107,38 @@
 	smp_mb__before_clear_bit();
 	clear_bit(PG_BUSY, &req->wb_flags);
 	smp_mb__after_clear_bit();
-	wake_up_all(&req->wb_context->waitq);
+	wake_up_bit(&req->wb_flags, PG_BUSY);
 	nfs_release_request(req);
 }
 
 /**
+ * nfs_set_page_writeback_locked - Lock a request for writeback
+ * @req:
+ */
+int nfs_set_page_writeback_locked(struct nfs_page *req)
+{
+	struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode);
+
+	if (!nfs_lock_request(req))
+		return 0;
+	radix_tree_tag_set(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK);
+	return 1;
+}
+
+/**
+ * nfs_clear_page_writeback - Unlock request and wake up sleepers
+ */
+void nfs_clear_page_writeback(struct nfs_page *req)
+{
+	struct nfs_inode *nfsi = NFS_I(req->wb_context->dentry->d_inode);
+
+	spin_lock(&nfsi->req_lock);
+	radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_WRITEBACK);
+	spin_unlock(&nfsi->req_lock);
+	nfs_unlock_request(req);
+}
+
+/**
  * nfs_clear_request - Free up all resources allocated to the request
  * @req:
  *
@@ -150,34 +177,15 @@
 	nfs_page_free(req);
 }
 
-/**
- * nfs_list_add_request - Insert a request into a sorted list
- * @req: request
- * @head: head of list into which to insert the request.
- *
- * Note that the wb_list is sorted by page index in order to facilitate
- * coalescing of requests.
- * We use an insertion sort that is optimized for the case of appended
- * writes.
- */
-void
-nfs_list_add_request(struct nfs_page *req, struct list_head *head)
+static int nfs_wait_bit_interruptible(void *word)
 {
-	struct list_head *pos;
+	int ret = 0;
 
-#ifdef NFS_PARANOIA
-	if (!list_empty(&req->wb_list)) {
-		printk(KERN_ERR "NFS: Add to list failed!\n");
-		BUG();
-	}
-#endif
-	list_for_each_prev(pos, head) {
-		struct nfs_page	*p = nfs_list_entry(pos);
-		if (p->wb_index < req->wb_index)
-			break;
-	}
-	list_add(&req->wb_list, pos);
-	req->wb_list_head = head;
+	if (signal_pending(current))
+		ret = -ERESTARTSYS;
+	else
+		schedule();
+	return ret;
 }
 
 /**
@@ -190,12 +198,22 @@
 int
 nfs_wait_on_request(struct nfs_page *req)
 {
-	struct inode	*inode = req->wb_context->dentry->d_inode;
-        struct rpc_clnt	*clnt = NFS_CLIENT(inode);
+        struct rpc_clnt	*clnt = NFS_CLIENT(req->wb_context->dentry->d_inode);
+	sigset_t oldmask;
+	int ret = 0;
 
-	if (!NFS_WBACK_BUSY(req))
-		return 0;
-	return nfs_wait_event(clnt, req->wb_context->waitq, !NFS_WBACK_BUSY(req));
+	if (!test_bit(PG_BUSY, &req->wb_flags))
+		goto out;
+	/*
+	 * Note: the call to rpc_clnt_sigmask() suffices to ensure that we
+	 *	 are not interrupted if intr flag is not set
+	 */
+	rpc_clnt_sigmask(clnt, &oldmask);
+	ret = out_of_line_wait_on_bit(&req->wb_flags, PG_BUSY,
+			nfs_wait_bit_interruptible, TASK_INTERRUPTIBLE);
+	rpc_clnt_sigunmask(clnt, &oldmask);
+out:
+	return ret;
 }
 
 /**
@@ -243,6 +261,62 @@
 	return npages;
 }
 
+#define NFS_SCAN_MAXENTRIES 16
+/**
+ * nfs_scan_lock_dirty - Scan the radix tree for dirty requests
+ * @nfsi: NFS inode
+ * @dst: Destination list
+ * @idx_start: lower bound of page->index to scan
+ * @npages: idx_start + npages sets the upper bound to scan.
+ *
+ * Moves elements from one of the inode request lists.
+ * If the number of requests is set to 0, the entire address_space
+ * starting at index idx_start, is scanned.
+ * 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_lock_dirty(struct nfs_inode *nfsi, struct list_head *dst,
+	      unsigned long idx_start, unsigned int npages)
+{
+	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)
+		idx_end = ~0;
+	else
+		idx_end = idx_start + npages - 1;
+
+	for (;;) {
+		found = radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree,
+				(void **)&pgvec[0], idx_start, NFS_SCAN_MAXENTRIES,
+				NFS_PAGE_TAG_DIRTY);
+		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 (nfs_set_page_writeback_locked(req)) {
+				radix_tree_tag_clear(&nfsi->nfs_page_tree,
+						req->wb_index, NFS_PAGE_TAG_DIRTY);
+				nfs_list_remove_request(req);
+				nfs_list_add_request(req, dst);
+				res++;
+			}
+		}
+	}
+out:
+	return res;
+}
+
 /**
  * nfs_scan_list - Scan a list for matching requests
  * @head: One of the NFS inode request lists
@@ -280,7 +354,7 @@
 		if (req->wb_index > idx_end)
 			break;
 
-		if (!nfs_lock_request(req))
+		if (!nfs_set_page_writeback_locked(req))
 			continue;
 		nfs_list_remove_request(req);
 		nfs_list_add_request(req, dst);
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index d31b4d6..cedf636 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -622,6 +622,7 @@
 	.version	= 2,		       /* protocol version */
 	.dentry_ops	= &nfs_dentry_operations,
 	.dir_inode_ops	= &nfs_dir_inode_operations,
+	.file_inode_ops	= &nfs_file_inode_operations,
 	.getroot	= nfs_proc_get_root,
 	.getattr	= nfs_proc_getattr,
 	.setattr	= nfs_proc_setattr,
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index a0042fb..6f866b8 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -173,7 +173,6 @@
 	if (len < PAGE_CACHE_SIZE)
 		memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len);
 
-	nfs_lock_request(new);
 	nfs_list_add_request(new, &one_request);
 	nfs_pagein_one(&one_request, inode);
 	return 0;
@@ -185,7 +184,6 @@
 
 	nfs_clear_request(req);
 	nfs_release_request(req);
-	nfs_unlock_request(req);
 
 	dprintk("NFS: read done (%s/%Ld %d@%Ld)\n",
 			req->wb_context->dentry->d_inode->i_sb->s_id,
@@ -553,7 +551,6 @@
 	}
 	if (len < PAGE_CACHE_SIZE)
 		memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len);
-	nfs_lock_request(new);
 	nfs_list_add_request(new, desc->head);
 	return 0;
 }
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 6f7a4af..5130eda 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -220,7 +220,7 @@
 		ClearPageError(page);
 
 io_error:
-	nfs_end_data_update_defer(inode);
+	nfs_end_data_update(inode);
 	nfs_writedata_free(wdata);
 	return written ? written : result;
 }
@@ -352,7 +352,7 @@
 		if (err < 0)
 			goto out;
 	}
-	err = nfs_commit_inode(inode, 0, 0, wb_priority(wbc));
+	err = nfs_commit_inode(inode, wb_priority(wbc));
 	if (err > 0) {
 		wbc->nr_to_write -= err;
 		err = 0;
@@ -401,7 +401,7 @@
 	nfsi->npages--;
 	if (!nfsi->npages) {
 		spin_unlock(&nfsi->req_lock);
-		nfs_end_data_update_defer(inode);
+		nfs_end_data_update(inode);
 		iput(inode);
 	} else
 		spin_unlock(&nfsi->req_lock);
@@ -446,6 +446,8 @@
 	struct nfs_inode *nfsi = NFS_I(inode);
 
 	spin_lock(&nfsi->req_lock);
+	radix_tree_tag_set(&nfsi->nfs_page_tree,
+			req->wb_index, NFS_PAGE_TAG_DIRTY);
 	nfs_list_add_request(req, &nfsi->dirty);
 	nfsi->ndirty++;
 	spin_unlock(&nfsi->req_lock);
@@ -503,13 +505,12 @@
 
 	spin_lock(&nfsi->req_lock);
 	next = idx_start;
-	while (radix_tree_gang_lookup(&nfsi->nfs_page_tree, (void **)&req, next, 1)) {
+	while (radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree, (void **)&req, next, 1, NFS_PAGE_TAG_WRITEBACK)) {
 		if (req->wb_index > idx_end)
 			break;
 
 		next = req->wb_index + 1;
-		if (!NFS_WBACK_BUSY(req))
-			continue;
+		BUG_ON(!NFS_WBACK_BUSY(req));
 
 		atomic_inc(&req->wb_count);
 		spin_unlock(&nfsi->req_lock);
@@ -538,12 +539,15 @@
 nfs_scan_dirty(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
-	int	res;
-	res = nfs_scan_list(&nfsi->dirty, dst, idx_start, npages);
-	nfsi->ndirty -= res;
-	sub_page_state(nr_dirty,res);
-	if ((nfsi->ndirty == 0) != list_empty(&nfsi->dirty))
-		printk(KERN_ERR "NFS: desynchronized value of nfs_i.ndirty.\n");
+	int res = 0;
+
+	if (nfsi->ndirty != 0) {
+		res = nfs_scan_lock_dirty(nfsi, dst, idx_start, npages);
+		nfsi->ndirty -= res;
+		sub_page_state(nr_dirty,res);
+		if ((nfsi->ndirty == 0) != list_empty(&nfsi->dirty))
+			printk(KERN_ERR "NFS: desynchronized value of nfs_i.ndirty.\n");
+	}
 	return res;
 }
 
@@ -562,11 +566,14 @@
 nfs_scan_commit(struct inode *inode, struct list_head *dst, unsigned long idx_start, unsigned int npages)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
-	int	res;
-	res = nfs_scan_list(&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");
+	int res = 0;
+
+	if (nfsi->ncommit != 0) {
+		res = nfs_scan_list(&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");
+	}
 	return res;
 }
 #endif
@@ -750,7 +757,7 @@
 	 * is entirely in cache, it may be more efficient to avoid
 	 * fragmenting write requests.
 	 */
-	if (PageUptodate(page) && inode->i_flock == NULL) {
+	if (PageUptodate(page) && inode->i_flock == NULL && !(file->f_mode & O_SYNC)) {
 		loff_t end_offs = i_size_read(inode) - 1;
 		unsigned long end_index = end_offs >> PAGE_CACHE_SHIFT;
 
@@ -821,7 +828,7 @@
 #else
 	nfs_inode_remove_request(req);
 #endif
-	nfs_unlock_request(req);
+	nfs_clear_page_writeback(req);
 }
 
 static inline int flush_task_priority(int how)
@@ -952,7 +959,7 @@
 		nfs_writedata_free(data);
 	}
 	nfs_mark_request_dirty(req);
-	nfs_unlock_request(req);
+	nfs_clear_page_writeback(req);
 	return -ENOMEM;
 }
 
@@ -1002,7 +1009,7 @@
 		struct nfs_page *req = nfs_list_entry(head->next);
 		nfs_list_remove_request(req);
 		nfs_mark_request_dirty(req);
-		nfs_unlock_request(req);
+		nfs_clear_page_writeback(req);
 	}
 	return -ENOMEM;
 }
@@ -1029,7 +1036,7 @@
 		req = nfs_list_entry(head->next);
 		nfs_list_remove_request(req);
 		nfs_mark_request_dirty(req);
-		nfs_unlock_request(req);
+		nfs_clear_page_writeback(req);
 	}
 	return error;
 }
@@ -1121,7 +1128,7 @@
 		nfs_inode_remove_request(req);
 #endif
 	next:
-		nfs_unlock_request(req);
+		nfs_clear_page_writeback(req);
 	}
 }
 
@@ -1210,36 +1217,24 @@
 		struct nfs_write_data *data, int how)
 {
 	struct rpc_task		*task = &data->task;
-	struct nfs_page		*first, *last;
+	struct nfs_page		*first;
 	struct inode		*inode;
-	loff_t			start, end, len;
 
 	/* Set up the RPC argument and reply structs
 	 * NB: take care not to mess about with data->commit et al. */
 
 	list_splice_init(head, &data->pages);
 	first = nfs_list_entry(data->pages.next);
-	last = nfs_list_entry(data->pages.prev);
 	inode = first->wb_context->dentry->d_inode;
 
-	/*
-	 * Determine the offset range of requests in the COMMIT call.
-	 * We rely on the fact that data->pages is an ordered list...
-	 */
-	start = req_offset(first);
-	end = req_offset(last) + last->wb_bytes;
-	len = end - start;
-	/* If 'len' is not a 32-bit quantity, pass '0' in the COMMIT call */
-	if (end >= i_size_read(inode) || len < 0 || len > (~((u32)0) >> 1))
-		len = 0;
-
 	data->inode	  = inode;
 	data->cred	  = first->wb_context->cred;
 
 	data->args.fh     = NFS_FH(data->inode);
-	data->args.offset = start;
-	data->args.count  = len;
-	data->res.count   = len;
+	/* Note: we always request a commit of the entire inode */
+	data->args.offset = 0;
+	data->args.count  = 0;
+	data->res.count   = 0;
 	data->res.fattr   = &data->fattr;
 	data->res.verf    = &data->verf;
 	
@@ -1278,7 +1273,7 @@
 		req = nfs_list_entry(head->next);
 		nfs_list_remove_request(req);
 		nfs_mark_request_commit(req);
-		nfs_unlock_request(req);
+		nfs_clear_page_writeback(req);
 	}
 	return -ENOMEM;
 }
@@ -1324,7 +1319,7 @@
 		dprintk(" mismatch\n");
 		nfs_mark_request_dirty(req);
 	next:
-		nfs_unlock_request(req);
+		nfs_clear_page_writeback(req);
 		res++;
 	}
 	sub_page_state(nr_unstable,res);
@@ -1342,16 +1337,23 @@
 	spin_lock(&nfsi->req_lock);
 	res = nfs_scan_dirty(inode, &head, idx_start, npages);
 	spin_unlock(&nfsi->req_lock);
-	if (res)
-		error = nfs_flush_list(&head, NFS_SERVER(inode)->wpages, how);
+	if (res) {
+		struct nfs_server *server = NFS_SERVER(inode);
+
+		/* For single writes, FLUSH_STABLE is more efficient */
+		if (res == nfsi->npages && nfsi->npages <= server->wpages) {
+			if (res > 1 || nfs_list_entry(head.next)->wb_bytes <= server->wsize)
+				how |= FLUSH_STABLE;
+		}
+		error = nfs_flush_list(&head, server->wpages, how);
+	}
 	if (error < 0)
 		return error;
 	return res;
 }
 
 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
-int nfs_commit_inode(struct inode *inode, unsigned long idx_start,
-		    unsigned int npages, int how)
+int nfs_commit_inode(struct inode *inode, int how)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 	LIST_HEAD(head);
@@ -1359,15 +1361,13 @@
 				error = 0;
 
 	spin_lock(&nfsi->req_lock);
-	res = nfs_scan_commit(inode, &head, idx_start, npages);
+	res = nfs_scan_commit(inode, &head, 0, 0);
+	spin_unlock(&nfsi->req_lock);
 	if (res) {
-		res += nfs_scan_commit(inode, &head, 0, 0);
-		spin_unlock(&nfsi->req_lock);
 		error = nfs_commit_list(&head, how);
-	} else
-		spin_unlock(&nfsi->req_lock);
-	if (error < 0)
-		return error;
+		if (error < 0)
+			return error;
+	}
 	return res;
 }
 #endif
@@ -1389,7 +1389,7 @@
 			error = nfs_flush_inode(inode, idx_start, npages, how);
 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
 		if (error == 0)
-			error = nfs_commit_inode(inode, idx_start, npages, how);
+			error = nfs_commit_inode(inode, how);
 #endif
 	} while (error > 0);
 	return error;
diff --git a/fs/nfs_common/Makefile b/fs/nfs_common/Makefile
new file mode 100644
index 0000000..f689ed8
--- /dev/null
+++ b/fs/nfs_common/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for Linux filesystem routines that are shared by client and server.
+#
+
+obj-$(CONFIG_NFS_ACL_SUPPORT) += nfs_acl.o
+
+nfs_acl-objs := nfsacl.o
diff --git a/fs/nfs_common/nfsacl.c b/fs/nfs_common/nfsacl.c
new file mode 100644
index 0000000..18c58c3
--- /dev/null
+++ b/fs/nfs_common/nfsacl.c
@@ -0,0 +1,257 @@
+/*
+ * fs/nfs_common/nfsacl.c
+ *
+ *  Copyright (C) 2002-2003 Andreas Gruenbacher <agruen@suse.de>
+ */
+
+/*
+ * The Solaris nfsacl protocol represents some ACLs slightly differently
+ * than POSIX 1003.1e draft 17 does (and we do):
+ *
+ *  - Minimal ACLs always have an ACL_MASK entry, so they have
+ *    four instead of three entries.
+ *  - The ACL_MASK entry in such minimal ACLs always has the same
+ *    permissions as the ACL_GROUP_OBJ entry. (In extended ACLs
+ *    the ACL_MASK and ACL_GROUP_OBJ entries may differ.)
+ *  - The identifier fields of the ACL_USER_OBJ and ACL_GROUP_OBJ
+ *    entries contain the identifiers of the owner and owning group.
+ *    (In POSIX ACLs we always set them to ACL_UNDEFINED_ID).
+ *  - ACL entries in the kernel are kept sorted in ascending order
+ *    of (e_tag, e_id). Solaris ACLs are unsorted.
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/sunrpc/xdr.h>
+#include <linux/nfsacl.h>
+#include <linux/nfs3.h>
+#include <linux/sort.h>
+
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(nfsacl_encode);
+EXPORT_SYMBOL(nfsacl_decode);
+
+struct nfsacl_encode_desc {
+	struct xdr_array2_desc desc;
+	unsigned int count;
+	struct posix_acl *acl;
+	int typeflag;
+	uid_t uid;
+	gid_t gid;
+};
+
+static int
+xdr_nfsace_encode(struct xdr_array2_desc *desc, void *elem)
+{
+	struct nfsacl_encode_desc *nfsacl_desc =
+		(struct nfsacl_encode_desc *) desc;
+	u32 *p = (u32 *) elem;
+
+	if (nfsacl_desc->count < nfsacl_desc->acl->a_count) {
+		struct posix_acl_entry *entry =
+			&nfsacl_desc->acl->a_entries[nfsacl_desc->count++];
+
+		*p++ = htonl(entry->e_tag | nfsacl_desc->typeflag);
+		switch(entry->e_tag) {
+			case ACL_USER_OBJ:
+				*p++ = htonl(nfsacl_desc->uid);
+				break;
+			case ACL_GROUP_OBJ:
+				*p++ = htonl(nfsacl_desc->gid);
+				break;
+			case ACL_USER:
+			case ACL_GROUP:
+				*p++ = htonl(entry->e_id);
+				break;
+			default:  /* Solaris depends on that! */
+				*p++ = 0;
+				break;
+		}
+		*p++ = htonl(entry->e_perm & S_IRWXO);
+	} else {
+		const struct posix_acl_entry *pa, *pe;
+		int group_obj_perm = ACL_READ|ACL_WRITE|ACL_EXECUTE;
+
+		FOREACH_ACL_ENTRY(pa, nfsacl_desc->acl, pe) {
+			if (pa->e_tag == ACL_GROUP_OBJ) {
+				group_obj_perm = pa->e_perm & S_IRWXO;
+				break;
+			}
+		}
+		/* fake up ACL_MASK entry */
+		*p++ = htonl(ACL_MASK | nfsacl_desc->typeflag);
+		*p++ = htonl(0);
+		*p++ = htonl(group_obj_perm);
+	}
+
+	return 0;
+}
+
+unsigned int
+nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode,
+	      struct posix_acl *acl, int encode_entries, int typeflag)
+{
+	int entries = (acl && acl->a_count) ? max_t(int, acl->a_count, 4) : 0;
+	struct nfsacl_encode_desc nfsacl_desc = {
+		.desc = {
+			.elem_size = 12,
+			.array_len = encode_entries ? entries : 0,
+			.xcode = xdr_nfsace_encode,
+		},
+		.acl = acl,
+		.typeflag = typeflag,
+		.uid = inode->i_uid,
+		.gid = inode->i_gid,
+	};
+	int err;
+
+	if (entries > NFS_ACL_MAX_ENTRIES ||
+	    xdr_encode_word(buf, base, entries))
+		return -EINVAL;
+	err = xdr_encode_array2(buf, base + 4, &nfsacl_desc.desc);
+	if (!err)
+		err = 8 + nfsacl_desc.desc.elem_size *
+			  nfsacl_desc.desc.array_len;
+	return err;
+}
+
+struct nfsacl_decode_desc {
+	struct xdr_array2_desc desc;
+	unsigned int count;
+	struct posix_acl *acl;
+};
+
+static int
+xdr_nfsace_decode(struct xdr_array2_desc *desc, void *elem)
+{
+	struct nfsacl_decode_desc *nfsacl_desc =
+		(struct nfsacl_decode_desc *) desc;
+	u32 *p = (u32 *) elem;
+	struct posix_acl_entry *entry;
+
+	if (!nfsacl_desc->acl) {
+		if (desc->array_len > NFS_ACL_MAX_ENTRIES)
+			return -EINVAL;
+		nfsacl_desc->acl = posix_acl_alloc(desc->array_len, GFP_KERNEL);
+		if (!nfsacl_desc->acl)
+			return -ENOMEM;
+		nfsacl_desc->count = 0;
+	}
+
+	entry = &nfsacl_desc->acl->a_entries[nfsacl_desc->count++];
+	entry->e_tag = ntohl(*p++) & ~NFS_ACL_DEFAULT;
+	entry->e_id = ntohl(*p++);
+	entry->e_perm = ntohl(*p++);
+
+	switch(entry->e_tag) {
+		case ACL_USER_OBJ:
+		case ACL_USER:
+		case ACL_GROUP_OBJ:
+		case ACL_GROUP:
+		case ACL_OTHER:
+			if (entry->e_perm & ~S_IRWXO)
+				return -EINVAL;
+			break;
+		case ACL_MASK:
+			/* Solaris sometimes sets additonal bits in the mask */
+			entry->e_perm &= S_IRWXO;
+			break;
+		default:
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+cmp_acl_entry(const void *x, const void *y)
+{
+	const struct posix_acl_entry *a = x, *b = y;
+
+	if (a->e_tag != b->e_tag)
+		return a->e_tag - b->e_tag;
+	else if (a->e_id > b->e_id)
+		return 1;
+	else if (a->e_id < b->e_id)
+		return -1;
+	else
+		return 0;
+}
+
+/*
+ * Convert from a Solaris ACL to a POSIX 1003.1e draft 17 ACL.
+ */
+static int
+posix_acl_from_nfsacl(struct posix_acl *acl)
+{
+	struct posix_acl_entry *pa, *pe,
+	       *group_obj = NULL, *mask = NULL;
+
+	if (!acl)
+		return 0;
+
+	sort(acl->a_entries, acl->a_count, sizeof(struct posix_acl_entry),
+	     cmp_acl_entry, NULL);
+
+	/* Clear undefined identifier fields and find the ACL_GROUP_OBJ
+	   and ACL_MASK entries. */
+	FOREACH_ACL_ENTRY(pa, acl, pe) {
+		switch(pa->e_tag) {
+			case ACL_USER_OBJ:
+				pa->e_id = ACL_UNDEFINED_ID;
+				break;
+			case ACL_GROUP_OBJ:
+				pa->e_id = ACL_UNDEFINED_ID;
+				group_obj = pa;
+				break;
+			case ACL_MASK:
+				mask = pa;
+				/* fall through */
+			case ACL_OTHER:
+				pa->e_id = ACL_UNDEFINED_ID;
+				break;
+		}
+	}
+	if (acl->a_count == 4 && group_obj && mask &&
+	    mask->e_perm == group_obj->e_perm) {
+		/* remove bogus ACL_MASK entry */
+		memmove(mask, mask+1, (3 - (mask - acl->a_entries)) *
+				      sizeof(struct posix_acl_entry));
+		acl->a_count = 3;
+	}
+	return 0;
+}
+
+unsigned int
+nfsacl_decode(struct xdr_buf *buf, unsigned int base, unsigned int *aclcnt,
+	      struct posix_acl **pacl)
+{
+	struct nfsacl_decode_desc nfsacl_desc = {
+		.desc = {
+			.elem_size = 12,
+			.xcode = pacl ? xdr_nfsace_decode : NULL,
+		},
+	};
+	u32 entries;
+	int err;
+
+	if (xdr_decode_word(buf, base, &entries) ||
+	    entries > NFS_ACL_MAX_ENTRIES)
+		return -EINVAL;
+	err = xdr_decode_array2(buf, base + 4, &nfsacl_desc.desc);
+	if (err)
+		return err;
+	if (pacl) {
+		if (entries != nfsacl_desc.desc.array_len ||
+		    posix_acl_from_nfsacl(nfsacl_desc.acl) != 0) {
+			posix_acl_release(nfsacl_desc.acl);
+			return -EINVAL;
+		}
+		*pacl = nfsacl_desc.acl;
+	}
+	if (aclcnt)
+		*aclcnt = entries;
+	return 8 + nfsacl_desc.desc.elem_size *
+		   nfsacl_desc.desc.array_len;
+}
diff --git a/fs/nfsd/Makefile b/fs/nfsd/Makefile
index b8680a2..ce341dc 100644
--- a/fs/nfsd/Makefile
+++ b/fs/nfsd/Makefile
@@ -6,7 +6,9 @@
 
 nfsd-y 			:= nfssvc.o nfsctl.o nfsproc.o nfsfh.o vfs.o \
 			   export.o auth.o lockd.o nfscache.o nfsxdr.o stats.o
+nfsd-$(CONFIG_NFSD_V2_ACL) += nfs2acl.o
 nfsd-$(CONFIG_NFSD_V3)	+= nfs3proc.o nfs3xdr.o
+nfsd-$(CONFIG_NFSD_V3_ACL) += nfs3acl.o
 nfsd-$(CONFIG_NFSD_V4)	+= nfs4proc.o nfs4xdr.o nfs4state.o nfs4idmap.o \
-			   nfs4acl.o nfs4callback.o
+			   nfs4acl.o nfs4callback.o nfs4recover.o
 nfsd-objs		:= $(nfsd-y)
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
new file mode 100644
index 0000000..7cbf068
--- /dev/null
+++ b/fs/nfsd/nfs2acl.c
@@ -0,0 +1,336 @@
+/*
+ * linux/fs/nfsd/nfsacl.c
+ *
+ * Process version 2 NFSACL requests.
+ *
+ * Copyright (C) 2002-2003 Andreas Gruenbacher <agruen@suse.de>
+ */
+
+#include <linux/sunrpc/svc.h>
+#include <linux/nfs.h>
+#include <linux/nfsd/nfsd.h>
+#include <linux/nfsd/cache.h>
+#include <linux/nfsd/xdr.h>
+#include <linux/nfsd/xdr3.h>
+#include <linux/posix_acl.h>
+#include <linux/nfsacl.h>
+
+#define NFSDDBG_FACILITY		NFSDDBG_PROC
+#define RETURN_STATUS(st)	{ resp->status = (st); return (st); }
+
+/*
+ * NULL call.
+ */
+static int
+nfsacld_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
+{
+	return nfs_ok;
+}
+
+/*
+ * Get the Access and/or Default ACL of a file.
+ */
+static int nfsacld_proc_getacl(struct svc_rqst * rqstp,
+		struct nfsd3_getaclargs *argp, struct nfsd3_getaclres *resp)
+{
+	svc_fh *fh;
+	struct posix_acl *acl;
+	int nfserr = 0;
+
+	dprintk("nfsd: GETACL(2acl)   %s\n", SVCFH_fmt(&argp->fh));
+
+	fh = fh_copy(&resp->fh, &argp->fh);
+	if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP)))
+		RETURN_STATUS(nfserr_inval);
+
+	if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
+		RETURN_STATUS(nfserr_inval);
+	resp->mask = argp->mask;
+
+	if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {
+		acl = nfsd_get_posix_acl(fh, ACL_TYPE_ACCESS);
+		if (IS_ERR(acl)) {
+			int err = PTR_ERR(acl);
+
+			if (err == -ENODATA || err == -EOPNOTSUPP)
+				acl = NULL;
+			else {
+				nfserr = nfserrno(err);
+				goto fail;
+			}
+		}
+		if (acl == NULL) {
+			/* Solaris returns the inode's minimum ACL. */
+
+			struct inode *inode = fh->fh_dentry->d_inode;
+			acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
+		}
+		resp->acl_access = acl;
+	}
+	if (resp->mask & (NFS_DFACL|NFS_DFACLCNT)) {
+		/* Check how Solaris handles requests for the Default ACL
+		   of a non-directory! */
+
+		acl = nfsd_get_posix_acl(fh, ACL_TYPE_DEFAULT);
+		if (IS_ERR(acl)) {
+			int err = PTR_ERR(acl);
+
+			if (err == -ENODATA || err == -EOPNOTSUPP)
+				acl = NULL;
+			else {
+				nfserr = nfserrno(err);
+				goto fail;
+			}
+		}
+		resp->acl_default = acl;
+	}
+
+	/* resp->acl_{access,default} are released in nfssvc_release_getacl. */
+	RETURN_STATUS(0);
+
+fail:
+	posix_acl_release(resp->acl_access);
+	posix_acl_release(resp->acl_default);
+	RETURN_STATUS(nfserr);
+}
+
+/*
+ * Set the Access and/or Default ACL of a file.
+ */
+static int nfsacld_proc_setacl(struct svc_rqst * rqstp,
+		struct nfsd3_setaclargs *argp,
+		struct nfsd_attrstat *resp)
+{
+	svc_fh *fh;
+	int nfserr = 0;
+
+	dprintk("nfsd: SETACL(2acl)   %s\n", SVCFH_fmt(&argp->fh));
+
+	fh = fh_copy(&resp->fh, &argp->fh);
+	nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
+
+	if (!nfserr) {
+		nfserr = nfserrno( nfsd_set_posix_acl(
+			fh, ACL_TYPE_ACCESS, argp->acl_access) );
+	}
+	if (!nfserr) {
+		nfserr = nfserrno( nfsd_set_posix_acl(
+			fh, ACL_TYPE_DEFAULT, argp->acl_default) );
+	}
+
+	/* argp->acl_{access,default} may have been allocated in
+	   nfssvc_decode_setaclargs. */
+	posix_acl_release(argp->acl_access);
+	posix_acl_release(argp->acl_default);
+	return nfserr;
+}
+
+/*
+ * Check file attributes
+ */
+static int nfsacld_proc_getattr(struct svc_rqst * rqstp,
+		struct nfsd_fhandle *argp, struct nfsd_attrstat *resp)
+{
+	dprintk("nfsd: GETATTR  %s\n", SVCFH_fmt(&argp->fh));
+
+	fh_copy(&resp->fh, &argp->fh);
+	return fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
+}
+
+/*
+ * Check file access
+ */
+static int nfsacld_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessargs *argp,
+		struct nfsd3_accessres *resp)
+{
+	int nfserr;
+
+	dprintk("nfsd: ACCESS(2acl)   %s 0x%x\n",
+			SVCFH_fmt(&argp->fh),
+			argp->access);
+
+	fh_copy(&resp->fh, &argp->fh);
+	resp->access = argp->access;
+	nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL);
+	return nfserr;
+}
+
+/*
+ * XDR decode functions
+ */
+static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, u32 *p,
+		struct nfsd3_getaclargs *argp)
+{
+	if (!(p = nfs2svc_decode_fh(p, &argp->fh)))
+		return 0;
+	argp->mask = ntohl(*p); p++;
+
+	return xdr_argsize_check(rqstp, p);
+}
+
+
+static int nfsaclsvc_decode_setaclargs(struct svc_rqst *rqstp, u32 *p,
+		struct nfsd3_setaclargs *argp)
+{
+	struct kvec *head = rqstp->rq_arg.head;
+	unsigned int base;
+	int n;
+
+	if (!(p = nfs2svc_decode_fh(p, &argp->fh)))
+		return 0;
+	argp->mask = ntohl(*p++);
+	if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT) ||
+	    !xdr_argsize_check(rqstp, p))
+		return 0;
+
+	base = (char *)p - (char *)head->iov_base;
+	n = nfsacl_decode(&rqstp->rq_arg, base, NULL,
+			  (argp->mask & NFS_ACL) ?
+			  &argp->acl_access : NULL);
+	if (n > 0)
+		n = nfsacl_decode(&rqstp->rq_arg, base + n, NULL,
+				  (argp->mask & NFS_DFACL) ?
+				  &argp->acl_default : NULL);
+	return (n > 0);
+}
+
+static int nfsaclsvc_decode_fhandleargs(struct svc_rqst *rqstp, u32 *p,
+		struct nfsd_fhandle *argp)
+{
+	if (!(p = nfs2svc_decode_fh(p, &argp->fh)))
+		return 0;
+	return xdr_argsize_check(rqstp, p);
+}
+
+static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, u32 *p,
+		struct nfsd3_accessargs *argp)
+{
+	if (!(p = nfs2svc_decode_fh(p, &argp->fh)))
+		return 0;
+	argp->access = ntohl(*p++);
+
+	return xdr_argsize_check(rqstp, p);
+}
+
+/*
+ * XDR encode functions
+ */
+
+/* GETACL */
+static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, u32 *p,
+		struct nfsd3_getaclres *resp)
+{
+	struct dentry *dentry = resp->fh.fh_dentry;
+	struct inode *inode = dentry->d_inode;
+	int w = nfsacl_size(
+		(resp->mask & NFS_ACL)   ? resp->acl_access  : NULL,
+		(resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
+	struct kvec *head = rqstp->rq_res.head;
+	unsigned int base;
+	int n;
+
+	if (dentry == NULL || dentry->d_inode == NULL)
+		return 0;
+	inode = dentry->d_inode;
+
+	p = nfs2svc_encode_fattr(rqstp, p, &resp->fh);
+	*p++ = htonl(resp->mask);
+	if (!xdr_ressize_check(rqstp, p))
+		return 0;
+	base = (char *)p - (char *)head->iov_base;
+
+	rqstp->rq_res.page_len = w;
+	while (w > 0) {
+		if (!svc_take_res_page(rqstp))
+			return 0;
+		w -= PAGE_SIZE;
+	}
+
+	n = nfsacl_encode(&rqstp->rq_res, base, inode,
+			  resp->acl_access,
+			  resp->mask & NFS_ACL, 0);
+	if (n > 0)
+		n = nfsacl_encode(&rqstp->rq_res, base + n, inode,
+				  resp->acl_default,
+				  resp->mask & NFS_DFACL,
+				  NFS_ACL_DEFAULT);
+	if (n <= 0)
+		return 0;
+	return 1;
+}
+
+static int nfsaclsvc_encode_attrstatres(struct svc_rqst *rqstp, u32 *p,
+		struct nfsd_attrstat *resp)
+{
+	p = nfs2svc_encode_fattr(rqstp, p, &resp->fh);
+	return xdr_ressize_check(rqstp, p);
+}
+
+/* ACCESS */
+static int nfsaclsvc_encode_accessres(struct svc_rqst *rqstp, u32 *p,
+		struct nfsd3_accessres *resp)
+{
+	p = nfs2svc_encode_fattr(rqstp, p, &resp->fh);
+	*p++ = htonl(resp->access);
+	return xdr_ressize_check(rqstp, p);
+}
+
+/*
+ * XDR release functions
+ */
+static int nfsaclsvc_release_getacl(struct svc_rqst *rqstp, u32 *p,
+		struct nfsd3_getaclres *resp)
+{
+	fh_put(&resp->fh);
+	posix_acl_release(resp->acl_access);
+	posix_acl_release(resp->acl_default);
+	return 1;
+}
+
+static int nfsaclsvc_release_fhandle(struct svc_rqst *rqstp, u32 *p,
+		struct nfsd_fhandle *resp)
+{
+	fh_put(&resp->fh);
+	return 1;
+}
+
+#define nfsaclsvc_decode_voidargs	NULL
+#define nfsaclsvc_encode_voidres	NULL
+#define nfsaclsvc_release_void		NULL
+#define nfsd3_fhandleargs	nfsd_fhandle
+#define nfsd3_attrstatres	nfsd_attrstat
+#define nfsd3_voidres		nfsd3_voidargs
+struct nfsd3_voidargs { int dummy; };
+
+#define PROC(name, argt, rest, relt, cache, respsize)	\
+ { (svc_procfunc) nfsacld_proc_##name,		\
+   (kxdrproc_t) nfsaclsvc_decode_##argt##args,	\
+   (kxdrproc_t) nfsaclsvc_encode_##rest##res,	\
+   (kxdrproc_t) nfsaclsvc_release_##relt,		\
+   sizeof(struct nfsd3_##argt##args),		\
+   sizeof(struct nfsd3_##rest##res),		\
+   0,						\
+   cache,					\
+   respsize,					\
+ }
+
+#define ST 1		/* status*/
+#define AT 21		/* attributes */
+#define pAT (1+AT)	/* post attributes - conditional */
+#define ACL (1+NFS_ACL_MAX_ENTRIES*3)  /* Access Control List */
+
+static struct svc_procedure		nfsd_acl_procedures2[] = {
+  PROC(null,	void,		void,		void,	  RC_NOCACHE, ST),
+  PROC(getacl,	getacl,		getacl,		getacl,	  RC_NOCACHE, ST+1+2*(1+ACL)),
+  PROC(setacl,	setacl,		attrstat,	fhandle,  RC_NOCACHE, ST+AT),
+  PROC(getattr, fhandle,	attrstat,	fhandle,  RC_NOCACHE, ST+AT),
+  PROC(access,	access,		access,		fhandle,  RC_NOCACHE, ST+AT+1),
+};
+
+struct svc_version	nfsd_acl_version2 = {
+		.vs_vers	= 2,
+		.vs_nproc	= 5,
+		.vs_proc	= nfsd_acl_procedures2,
+		.vs_dispatch	= nfsd_dispatch,
+		.vs_xdrsize	= NFS3_SVC_XDRSIZE,
+};
diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
new file mode 100644
index 0000000..64ba405
--- /dev/null
+++ b/fs/nfsd/nfs3acl.c
@@ -0,0 +1,267 @@
+/*
+ * linux/fs/nfsd/nfs3acl.c
+ *
+ * Process version 3 NFSACL requests.
+ *
+ * Copyright (C) 2002-2003 Andreas Gruenbacher <agruen@suse.de>
+ */
+
+#include <linux/sunrpc/svc.h>
+#include <linux/nfs3.h>
+#include <linux/nfsd/nfsd.h>
+#include <linux/nfsd/cache.h>
+#include <linux/nfsd/xdr3.h>
+#include <linux/posix_acl.h>
+#include <linux/nfsacl.h>
+
+#define RETURN_STATUS(st)	{ resp->status = (st); return (st); }
+
+/*
+ * NULL call.
+ */
+static int
+nfsd3_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
+{
+	return nfs_ok;
+}
+
+/*
+ * Get the Access and/or Default ACL of a file.
+ */
+static int nfsd3_proc_getacl(struct svc_rqst * rqstp,
+		struct nfsd3_getaclargs *argp, struct nfsd3_getaclres *resp)
+{
+	svc_fh *fh;
+	struct posix_acl *acl;
+	int nfserr = 0;
+
+	fh = fh_copy(&resp->fh, &argp->fh);
+	if ((nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP)))
+		RETURN_STATUS(nfserr_inval);
+
+	if (argp->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
+		RETURN_STATUS(nfserr_inval);
+	resp->mask = argp->mask;
+
+	if (resp->mask & (NFS_ACL|NFS_ACLCNT)) {
+		acl = nfsd_get_posix_acl(fh, ACL_TYPE_ACCESS);
+		if (IS_ERR(acl)) {
+			int err = PTR_ERR(acl);
+
+			if (err == -ENODATA || err == -EOPNOTSUPP)
+				acl = NULL;
+			else {
+				nfserr = nfserrno(err);
+				goto fail;
+			}
+		}
+		if (acl == NULL) {
+			/* Solaris returns the inode's minimum ACL. */
+
+			struct inode *inode = fh->fh_dentry->d_inode;
+			acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
+		}
+		resp->acl_access = acl;
+	}
+	if (resp->mask & (NFS_DFACL|NFS_DFACLCNT)) {
+		/* Check how Solaris handles requests for the Default ACL
+		   of a non-directory! */
+
+		acl = nfsd_get_posix_acl(fh, ACL_TYPE_DEFAULT);
+		if (IS_ERR(acl)) {
+			int err = PTR_ERR(acl);
+
+			if (err == -ENODATA || err == -EOPNOTSUPP)
+				acl = NULL;
+			else {
+				nfserr = nfserrno(err);
+				goto fail;
+			}
+		}
+		resp->acl_default = acl;
+	}
+
+	/* resp->acl_{access,default} are released in nfs3svc_release_getacl. */
+	RETURN_STATUS(0);
+
+fail:
+	posix_acl_release(resp->acl_access);
+	posix_acl_release(resp->acl_default);
+	RETURN_STATUS(nfserr);
+}
+
+/*
+ * Set the Access and/or Default ACL of a file.
+ */
+static int nfsd3_proc_setacl(struct svc_rqst * rqstp,
+		struct nfsd3_setaclargs *argp,
+		struct nfsd3_attrstat *resp)
+{
+	svc_fh *fh;
+	int nfserr = 0;
+
+	fh = fh_copy(&resp->fh, &argp->fh);
+	nfserr = fh_verify(rqstp, &resp->fh, 0, MAY_NOP);
+
+	if (!nfserr) {
+		nfserr = nfserrno( nfsd_set_posix_acl(
+			fh, ACL_TYPE_ACCESS, argp->acl_access) );
+	}
+	if (!nfserr) {
+		nfserr = nfserrno( nfsd_set_posix_acl(
+			fh, ACL_TYPE_DEFAULT, argp->acl_default) );
+	}
+
+	/* argp->acl_{access,default} may have been allocated in
+	   nfs3svc_decode_setaclargs. */
+	posix_acl_release(argp->acl_access);
+	posix_acl_release(argp->acl_default);
+	RETURN_STATUS(nfserr);
+}
+
+/*
+ * XDR decode functions
+ */
+static int nfs3svc_decode_getaclargs(struct svc_rqst *rqstp, u32 *p,
+		struct nfsd3_getaclargs *args)
+{
+	if (!(p = nfs3svc_decode_fh(p, &args->fh)))
+		return 0;
+	args->mask = ntohl(*p); p++;
+
+	return xdr_argsize_check(rqstp, p);
+}
+
+
+static int nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, u32 *p,
+		struct nfsd3_setaclargs *args)
+{
+	struct kvec *head = rqstp->rq_arg.head;
+	unsigned int base;
+	int n;
+
+	if (!(p = nfs3svc_decode_fh(p, &args->fh)))
+		return 0;
+	args->mask = ntohl(*p++);
+	if (args->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT) ||
+	    !xdr_argsize_check(rqstp, p))
+		return 0;
+
+	base = (char *)p - (char *)head->iov_base;
+	n = nfsacl_decode(&rqstp->rq_arg, base, NULL,
+			  (args->mask & NFS_ACL) ?
+			  &args->acl_access : NULL);
+	if (n > 0)
+		n = nfsacl_decode(&rqstp->rq_arg, base + n, NULL,
+				  (args->mask & NFS_DFACL) ?
+				  &args->acl_default : NULL);
+	return (n > 0);
+}
+
+/*
+ * XDR encode functions
+ */
+
+/* GETACL */
+static int nfs3svc_encode_getaclres(struct svc_rqst *rqstp, u32 *p,
+		struct nfsd3_getaclres *resp)
+{
+	struct dentry *dentry = resp->fh.fh_dentry;
+
+	p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
+	if (resp->status == 0 && dentry && dentry->d_inode) {
+		struct inode *inode = dentry->d_inode;
+		int w = nfsacl_size(
+			(resp->mask & NFS_ACL)   ? resp->acl_access  : NULL,
+			(resp->mask & NFS_DFACL) ? resp->acl_default : NULL);
+		struct kvec *head = rqstp->rq_res.head;
+		unsigned int base;
+		int n;
+
+		*p++ = htonl(resp->mask);
+		if (!xdr_ressize_check(rqstp, p))
+			return 0;
+		base = (char *)p - (char *)head->iov_base;
+
+		rqstp->rq_res.page_len = w;
+		while (w > 0) {
+			if (!svc_take_res_page(rqstp))
+				return 0;
+			w -= PAGE_SIZE;
+		}
+
+		n = nfsacl_encode(&rqstp->rq_res, base, inode,
+				  resp->acl_access,
+				  resp->mask & NFS_ACL, 0);
+		if (n > 0)
+			n = nfsacl_encode(&rqstp->rq_res, base + n, inode,
+					  resp->acl_default,
+					  resp->mask & NFS_DFACL,
+					  NFS_ACL_DEFAULT);
+		if (n <= 0)
+			return 0;
+	} else
+		if (!xdr_ressize_check(rqstp, p))
+			return 0;
+
+	return 1;
+}
+
+/* SETACL */
+static int nfs3svc_encode_setaclres(struct svc_rqst *rqstp, u32 *p,
+		struct nfsd3_attrstat *resp)
+{
+	p = nfs3svc_encode_post_op_attr(rqstp, p, &resp->fh);
+
+	return xdr_ressize_check(rqstp, p);
+}
+
+/*
+ * XDR release functions
+ */
+static int nfs3svc_release_getacl(struct svc_rqst *rqstp, u32 *p,
+		struct nfsd3_getaclres *resp)
+{
+	fh_put(&resp->fh);
+	posix_acl_release(resp->acl_access);
+	posix_acl_release(resp->acl_default);
+	return 1;
+}
+
+#define nfs3svc_decode_voidargs		NULL
+#define nfs3svc_release_void		NULL
+#define nfsd3_setaclres			nfsd3_attrstat
+#define nfsd3_voidres			nfsd3_voidargs
+struct nfsd3_voidargs { int dummy; };
+
+#define PROC(name, argt, rest, relt, cache, respsize)	\
+ { (svc_procfunc) nfsd3_proc_##name,		\
+   (kxdrproc_t) nfs3svc_decode_##argt##args,	\
+   (kxdrproc_t) nfs3svc_encode_##rest##res,	\
+   (kxdrproc_t) nfs3svc_release_##relt,		\
+   sizeof(struct nfsd3_##argt##args),		\
+   sizeof(struct nfsd3_##rest##res),		\
+   0,						\
+   cache,					\
+   respsize,					\
+ }
+
+#define ST 1		/* status*/
+#define AT 21		/* attributes */
+#define pAT (1+AT)	/* post attributes - conditional */
+#define ACL (1+NFS_ACL_MAX_ENTRIES*3)  /* Access Control List */
+
+static struct svc_procedure		nfsd_acl_procedures3[] = {
+  PROC(null,	void,		void,		void,	  RC_NOCACHE, ST),
+  PROC(getacl,	getacl,		getacl,		getacl,	  RC_NOCACHE, ST+1+2*(1+ACL)),
+  PROC(setacl,	setacl,		setacl,		fhandle,  RC_NOCACHE, ST+pAT),
+};
+
+struct svc_version	nfsd_acl_version3 = {
+		.vs_vers	= 3,
+		.vs_nproc	= 3,
+		.vs_proc	= nfsd_acl_procedures3,
+		.vs_dispatch	= nfsd_dispatch,
+		.vs_xdrsize	= NFS3_SVC_XDRSIZE,
+};
+
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 11f8068..e0e134d 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -71,6 +71,12 @@
 	return p + XDR_QUADLEN(size);
 }
 
+/* Helper function for NFSv3 ACL code */
+u32 *nfs3svc_decode_fh(u32 *p, struct svc_fh *fhp)
+{
+	return decode_fh(p, fhp);
+}
+
 static inline u32 *
 encode_fh(u32 *p, struct svc_fh *fhp)
 {
@@ -233,6 +239,13 @@
 	return p;
 }
 
+/* Helper for NFSv3 ACLs */
+u32 *
+nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
+{
+	return encode_post_op_attr(rqstp, p, fhp);
+}
+
 /*
  * Enocde weak cache consistency data
  */
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 11ebf6c..4a21055 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -125,7 +125,7 @@
 static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int);
 static struct posix_acl *_nfsv4_to_posix_one(struct nfs4_acl *, unsigned int);
 int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
-int nfs4_acl_split(struct nfs4_acl *, struct nfs4_acl *);
+static int nfs4_acl_split(struct nfs4_acl *, struct nfs4_acl *);
 
 struct nfs4_acl *
 nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl,
@@ -775,7 +775,7 @@
 	return pacl;
 }
 
-int
+static int
 nfs4_acl_split(struct nfs4_acl *acl, struct nfs4_acl *dacl)
 {
 	struct list_head *h, *n;
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 1a55dfc..583c071 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -54,7 +54,6 @@
 
 /* declarations */
 static void nfs4_cb_null(struct rpc_task *task);
-extern spinlock_t recall_lock;
 
 /* Index of predefined Linux callback client operations */
 
@@ -329,12 +328,12 @@
         .p_bufsiz = MAX(NFS4_##argtype##_sz,NFS4_##restype##_sz) << 2,  \
 }
 
-struct rpc_procinfo     nfs4_cb_procedures[] = {
+static struct rpc_procinfo     nfs4_cb_procedures[] = {
     PROC(CB_NULL,      NULL,     enc_cb_null,     dec_cb_null),
     PROC(CB_RECALL,    COMPOUND,   enc_cb_recall,      dec_cb_recall),
 };
 
-struct rpc_version              nfs_cb_version4 = {
+static struct rpc_version       nfs_cb_version4 = {
         .number                 = 1,
         .nrprocs                = sizeof(nfs4_cb_procedures)/sizeof(nfs4_cb_procedures[0]),
         .procs                  = nfs4_cb_procedures
@@ -348,7 +347,7 @@
 /*
  * Use the SETCLIENTID credential
  */
-struct rpc_cred *
+static struct rpc_cred *
 nfsd4_lookupcred(struct nfs4_client *clp, int taskflags)
 {
         struct auth_cred acred;
@@ -387,9 +386,7 @@
 	char                    hostname[32];
 	int status;
 
-	dprintk("NFSD: probe_callback. cb_parsed %d cb_set %d\n",
-			cb->cb_parsed, atomic_read(&cb->cb_set));
-	if (!cb->cb_parsed || atomic_read(&cb->cb_set))
+	if (atomic_read(&cb->cb_set))
 		return;
 
 	/* Initialize address */
@@ -427,10 +424,10 @@
 	 * XXX AUTH_UNIX only - need AUTH_GSS....
 	 */
 	sprintf(hostname, "%u.%u.%u.%u", NIPQUAD(addr.sin_addr.s_addr));
-	clnt = rpc_create_client(xprt, hostname, program, 1, RPC_AUTH_UNIX);
+	clnt = rpc_new_client(xprt, hostname, program, 1, RPC_AUTH_UNIX);
 	if (IS_ERR(clnt)) {
 		dprintk("NFSD: couldn't create callback client\n");
-		goto out_xprt;
+		goto out_err;
 	}
 	clnt->cl_intr = 0;
 	clnt->cl_softrtry = 1;
@@ -465,8 +462,6 @@
 out_clnt:
 	rpc_shutdown_client(clnt);
 	goto out_err;
-out_xprt:
-	xprt_destroy(xprt);
 out_err:
 	dprintk("NFSD: warning: no callback path to client %.*s\n",
 		(int)clp->cl_name.len, clp->cl_name.data);
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index 4ba5408..5605a26 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -104,7 +104,7 @@
 	ent_init(new, itm);
 }
 
-void
+static void
 ent_put(struct cache_head *ch, struct cache_detail *cd)
 {
 	if (cache_put(ch, cd)) {
@@ -186,7 +186,7 @@
 static int         idtoname_parse(struct cache_detail *, char *, int);
 static struct ent *idtoname_lookup(struct ent *, int);
 
-struct cache_detail idtoname_cache = {
+static struct cache_detail idtoname_cache = {
 	.hash_size	= ENT_HASHMAX,
 	.hash_table	= idtoname_table,
 	.name		= "nfs4.idtoname",
@@ -277,7 +277,7 @@
 	return hash_str(ent->name, ENT_HASHBITS);
 }
 
-void
+static void
 nametoid_request(struct cache_detail *cd, struct cache_head *ch, char **bpp,
     int *blen)
 {
@@ -317,9 +317,9 @@
 }
 
 static struct ent *nametoid_lookup(struct ent *, int);
-int                nametoid_parse(struct cache_detail *, char *, int);
+static int         nametoid_parse(struct cache_detail *, char *, int);
 
-struct cache_detail nametoid_cache = {
+static struct cache_detail nametoid_cache = {
 	.hash_size	= ENT_HASHMAX,
 	.hash_table	= nametoid_table,
 	.name		= "nfs4.nametoid",
@@ -330,7 +330,7 @@
 	.warn_no_listener = warn_no_idmapd,
 };
 
-int
+static int
 nametoid_parse(struct cache_detail *cd, char *buf, int buflen)
 {
 	struct ent ent, *res;
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index e815874..d71f145 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -45,6 +45,7 @@
 #include <linux/param.h>
 #include <linux/major.h>
 #include <linux/slab.h>
+#include <linux/file.h>
 
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
@@ -198,6 +199,11 @@
 	if (status)
 		goto out;
 	switch (open->op_claim_type) {
+		case NFS4_OPEN_CLAIM_DELEGATE_CUR:
+			status = nfserr_inval;
+			if (open->op_create)
+				goto out;
+			/* fall through */
 		case NFS4_OPEN_CLAIM_NULL:
 			/*
 			 * (1) set CURRENT_FH to the file being opened,
@@ -220,7 +226,6 @@
 			if (status)
 				goto out;
 			break;
-		case NFS4_OPEN_CLAIM_DELEGATE_CUR:
              	case NFS4_OPEN_CLAIM_DELEGATE_PREV:
 			printk("NFSD: unsupported OPEN claim type %d\n",
 				open->op_claim_type);
@@ -473,26 +478,27 @@
 nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read)
 {
 	int status;
-	struct file *filp = NULL;
 
 	/* no need to check permission - this will be done in nfsd_read() */
 
+	read->rd_filp = NULL;
 	if (read->rd_offset >= OFFSET_MAX)
 		return nfserr_inval;
 
 	nfs4_lock_state();
 	/* check stateid */
 	if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid,
-					CHECK_FH | RD_STATE, &filp))) {
+				CHECK_FH | RD_STATE, &read->rd_filp))) {
 		dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
 		goto out;
 	}
+	if (read->rd_filp)
+		get_file(read->rd_filp);
 	status = nfs_ok;
 out:
 	nfs4_unlock_state();
 	read->rd_rqstp = rqstp;
 	read->rd_fhp = current_fh;
-	read->rd_filp = filp;
 	return status;
 }
 
@@ -532,6 +538,8 @@
 {
 	int status;
 
+	if (nfs4_in_grace())
+		return nfserr_grace;
 	status = nfsd_unlink(rqstp, current_fh, 0, remove->rm_name, remove->rm_namelen);
 	if (status == nfserr_symlink)
 		return nfserr_notdir;
@@ -550,6 +558,9 @@
 
 	if (!save_fh->fh_dentry)
 		return status;
+	if (nfs4_in_grace() && !(save_fh->fh_export->ex_flags
+					& NFSEXP_NOSUBTREECHECK))
+		return nfserr_grace;
 	status = nfsd_rename(rqstp, save_fh, rename->rn_sname,
 			     rename->rn_snamelen, current_fh,
 			     rename->rn_tname, rename->rn_tnamelen);
@@ -624,6 +635,8 @@
 		dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
 		goto out;
 	}
+	if (filp)
+		get_file(filp);
 	nfs4_unlock_state();
 
 	write->wr_bytes_written = write->wr_buflen;
@@ -635,6 +648,8 @@
 	status =  nfsd_write(rqstp, current_fh, filp, write->wr_offset,
 			write->wr_vec, write->wr_vlen, write->wr_buflen,
 			&write->wr_how_written);
+	if (filp)
+		fput(filp);
 
 	if (status == nfserr_symlink)
 		status = nfserr_inval;
@@ -923,6 +938,9 @@
 			nfs4_put_stateowner(replay_owner);
 			replay_owner = NULL;
 		}
+		/* XXX Ugh, we need to get rid of this kind of special case: */
+		if (op->opnum == OP_READ && op->u.read.rd_filp)
+			fput(op->u.read.rd_filp);
 	}
 
 out:
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
new file mode 100644
index 0000000..095f174
--- /dev/null
+++ b/fs/nfsd/nfs4recover.c
@@ -0,0 +1,431 @@
+/*
+*  linux/fs/nfsd/nfs4recover.c
+*
+*  Copyright (c) 2004 The Regents of the University of Michigan.
+*  All rights reserved.
+*
+*  Andy Adamson <andros@citi.umich.edu>
+*
+*  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 ``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.
+*
+*/
+
+
+#include <linux/sunrpc/svc.h>
+#include <linux/nfsd/nfsd.h>
+#include <linux/nfs4.h>
+#include <linux/nfsd/state.h>
+#include <linux/nfsd/xdr4.h>
+#include <linux/param.h>
+#include <linux/file.h>
+#include <linux/namei.h>
+#include <asm/uaccess.h>
+#include <asm/scatterlist.h>
+#include <linux/crypto.h>
+
+
+#define NFSDDBG_FACILITY                NFSDDBG_PROC
+
+/* Globals */
+static struct nameidata rec_dir;
+static int rec_dir_init = 0;
+
+static void
+nfs4_save_user(uid_t *saveuid, gid_t *savegid)
+{
+	*saveuid = current->fsuid;
+	*savegid = current->fsgid;
+	current->fsuid = 0;
+	current->fsgid = 0;
+}
+
+static void
+nfs4_reset_user(uid_t saveuid, gid_t savegid)
+{
+	current->fsuid = saveuid;
+	current->fsgid = savegid;
+}
+
+static void
+md5_to_hex(char *out, char *md5)
+{
+	int i;
+
+	for (i=0; i<16; i++) {
+		unsigned char c = md5[i];
+
+		*out++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'9'-1);
+		*out++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'9'-1);
+	}
+	*out = '\0';
+}
+
+int
+nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname)
+{
+	struct xdr_netobj cksum;
+	struct crypto_tfm *tfm;
+	struct scatterlist sg[1];
+	int status = nfserr_resource;
+
+	dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n",
+			clname->len, clname->data);
+	tfm = crypto_alloc_tfm("md5", 0);
+	if (tfm == NULL)
+		goto out;
+	cksum.len = crypto_tfm_alg_digestsize(tfm);
+	cksum.data = kmalloc(cksum.len, GFP_KERNEL);
+	if (cksum.data == NULL)
+ 		goto out;
+	crypto_digest_init(tfm);
+
+	sg[0].page = virt_to_page(clname->data);
+	sg[0].offset = offset_in_page(clname->data);
+	sg[0].length = clname->len;
+
+	crypto_digest_update(tfm, sg, 1);
+	crypto_digest_final(tfm, cksum.data);
+
+	md5_to_hex(dname, cksum.data);
+
+	kfree(cksum.data);
+	status = nfs_ok;
+out:
+	if (tfm)
+		crypto_free_tfm(tfm);
+	return status;
+}
+
+static int
+nfsd4_rec_fsync(struct dentry *dentry)
+{
+	struct file *filp;
+	int status = nfs_ok;
+
+	dprintk("NFSD: nfs4_fsync_rec_dir\n");
+	filp = dentry_open(dget(dentry), mntget(rec_dir.mnt), O_RDWR);
+	if (IS_ERR(filp)) {
+		status = PTR_ERR(filp);
+		goto out;
+	}
+	if (filp->f_op && filp->f_op->fsync)
+		status = filp->f_op->fsync(filp, filp->f_dentry, 0);
+	fput(filp);
+out:
+	if (status)
+		printk("nfsd4: unable to sync recovery directory\n");
+	return status;
+}
+
+int
+nfsd4_create_clid_dir(struct nfs4_client *clp)
+{
+	char *dname = clp->cl_recdir;
+	struct dentry *dentry;
+	uid_t uid;
+	gid_t gid;
+	int status;
+
+	dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname);
+
+	if (!rec_dir_init || clp->cl_firststate)
+		return 0;
+
+	nfs4_save_user(&uid, &gid);
+
+	/* lock the parent */
+	down(&rec_dir.dentry->d_inode->i_sem);
+
+	dentry = lookup_one_len(dname, rec_dir.dentry, HEXDIR_LEN-1);
+	if (IS_ERR(dentry)) {
+		status = PTR_ERR(dentry);
+		goto out_unlock;
+	}
+	status = -EEXIST;
+	if (dentry->d_inode) {
+		dprintk("NFSD: nfsd4_create_clid_dir: DIRECTORY EXISTS\n");
+		goto out_put;
+	}
+	status = vfs_mkdir(rec_dir.dentry->d_inode, dentry, S_IRWXU);
+out_put:
+	dput(dentry);
+out_unlock:
+	up(&rec_dir.dentry->d_inode->i_sem);
+	if (status == 0) {
+		clp->cl_firststate = 1;
+		status = nfsd4_rec_fsync(rec_dir.dentry);
+	}
+	nfs4_reset_user(uid, gid);
+	dprintk("NFSD: nfsd4_create_clid_dir returns %d\n", status);
+	return status;
+}
+
+typedef int (recdir_func)(struct dentry *, struct dentry *);
+
+struct dentry_list {
+	struct dentry *dentry;
+	struct list_head list;
+};
+
+struct dentry_list_arg {
+	struct list_head dentries;
+	struct dentry *parent;
+};
+
+static int
+nfsd4_build_dentrylist(void *arg, const char *name, int namlen,
+		loff_t offset, ino_t ino, unsigned int d_type)
+{
+	struct dentry_list_arg *dla = arg;
+	struct list_head *dentries = &dla->dentries;
+	struct dentry *parent = dla->parent;
+	struct dentry *dentry;
+	struct dentry_list *child;
+
+	if (name && isdotent(name, namlen))
+		return nfs_ok;
+	dentry = lookup_one_len(name, parent, namlen);
+	if (IS_ERR(dentry))
+		return PTR_ERR(dentry);
+	child = kmalloc(sizeof(*child), GFP_KERNEL);
+	if (child == NULL)
+		return -ENOMEM;
+	child->dentry = dentry;
+	list_add(&child->list, dentries);
+	return 0;
+}
+
+static int
+nfsd4_list_rec_dir(struct dentry *dir, recdir_func *f)
+{
+	struct file *filp;
+	struct dentry_list_arg dla = {
+		.parent = dir,
+	};
+	struct list_head *dentries = &dla.dentries;
+	struct dentry_list *child;
+	uid_t uid;
+	gid_t gid;
+	int status;
+
+	if (!rec_dir_init)
+		return 0;
+
+	nfs4_save_user(&uid, &gid);
+
+	filp = dentry_open(dget(dir), mntget(rec_dir.mnt),
+			O_RDWR);
+	status = PTR_ERR(filp);
+	if (IS_ERR(filp))
+		goto out;
+	INIT_LIST_HEAD(dentries);
+	status = vfs_readdir(filp, nfsd4_build_dentrylist, &dla);
+	fput(filp);
+	while (!list_empty(dentries)) {
+		child = list_entry(dentries->next, struct dentry_list, list);
+		status = f(dir, child->dentry);
+		if (status)
+			goto out;
+		list_del(&child->list);
+		dput(child->dentry);
+		kfree(child);
+	}
+out:
+	while (!list_empty(dentries)) {
+		child = list_entry(dentries->next, struct dentry_list, list);
+		list_del(&child->list);
+		dput(child->dentry);
+		kfree(child);
+	}
+	nfs4_reset_user(uid, gid);
+	return status;
+}
+
+static int
+nfsd4_remove_clid_file(struct dentry *dir, struct dentry *dentry)
+{
+	int status;
+
+	if (!S_ISREG(dir->d_inode->i_mode)) {
+		printk("nfsd4: non-file found in client recovery directory\n");
+		return -EINVAL;
+	}
+	down(&dir->d_inode->i_sem);
+	status = vfs_unlink(dir->d_inode, dentry);
+	up(&dir->d_inode->i_sem);
+	return status;
+}
+
+static int
+nfsd4_clear_clid_dir(struct dentry *dir, struct dentry *dentry)
+{
+	int status;
+
+	/* For now this directory should already be empty, but we empty it of
+	 * any regular files anyway, just in case the directory was created by
+	 * a kernel from the future.... */
+	nfsd4_list_rec_dir(dentry, nfsd4_remove_clid_file);
+	down(&dir->d_inode->i_sem);
+	status = vfs_rmdir(dir->d_inode, dentry);
+	up(&dir->d_inode->i_sem);
+	return status;
+}
+
+static int
+nfsd4_unlink_clid_dir(char *name, int namlen)
+{
+	struct dentry *dentry;
+	int status;
+
+	dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
+
+	dentry = lookup_one_len(name, rec_dir.dentry, namlen);
+	if (IS_ERR(dentry)) {
+		status = PTR_ERR(dentry);
+		return status;
+	}
+	status = -ENOENT;
+	if (!dentry->d_inode)
+		goto out;
+
+	status = nfsd4_clear_clid_dir(rec_dir.dentry, dentry);
+out:
+	dput(dentry);
+	return status;
+}
+
+void
+nfsd4_remove_clid_dir(struct nfs4_client *clp)
+{
+	uid_t uid;
+	gid_t gid;
+	int status;
+
+	if (!rec_dir_init || !clp->cl_firststate)
+		return;
+
+	nfs4_save_user(&uid, &gid);
+	status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1);
+	nfs4_reset_user(uid, gid);
+	if (status == 0)
+		status = nfsd4_rec_fsync(rec_dir.dentry);
+	if (status)
+		printk("NFSD: Failed to remove expired client state directory"
+				" %.*s\n", HEXDIR_LEN, clp->cl_recdir);
+	return;
+}
+
+static int
+purge_old(struct dentry *parent, struct dentry *child)
+{
+	int status;
+
+	if (nfs4_has_reclaimed_state(child->d_name.name))
+		return nfs_ok;
+
+	status = nfsd4_clear_clid_dir(parent, child);
+	if (status)
+		printk("failed to remove client recovery directory %s\n",
+				child->d_name.name);
+	/* Keep trying, success or failure: */
+	return nfs_ok;
+}
+
+void
+nfsd4_recdir_purge_old(void) {
+	int status;
+
+	if (!rec_dir_init)
+		return;
+	status = nfsd4_list_rec_dir(rec_dir.dentry, purge_old);
+	if (status == 0)
+		status = nfsd4_rec_fsync(rec_dir.dentry);
+	if (status)
+		printk("nfsd4: failed to purge old clients from recovery"
+			" directory %s\n", rec_dir.dentry->d_name.name);
+	return;
+}
+
+static int
+load_recdir(struct dentry *parent, struct dentry *child)
+{
+	if (child->d_name.len != HEXDIR_LEN - 1) {
+		printk("nfsd4: illegal name %s in recovery directory\n",
+				child->d_name.name);
+		/* Keep trying; maybe the others are OK: */
+		return nfs_ok;
+	}
+	nfs4_client_to_reclaim(child->d_name.name);
+	return nfs_ok;
+}
+
+int
+nfsd4_recdir_load(void) {
+	int status;
+
+	status = nfsd4_list_rec_dir(rec_dir.dentry, load_recdir);
+	if (status)
+		printk("nfsd4: failed loading clients from recovery"
+			" directory %s\n", rec_dir.dentry->d_name.name);
+	return status;
+}
+
+/*
+ * Hold reference to the recovery directory.
+ */
+
+void
+nfsd4_init_recdir(char *rec_dirname)
+{
+	uid_t			uid = 0;
+	gid_t			gid = 0;
+	int 			status;
+
+	printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
+			rec_dirname);
+
+	BUG_ON(rec_dir_init);
+
+	nfs4_save_user(&uid, &gid);
+
+	status = path_lookup(rec_dirname, LOOKUP_FOLLOW, &rec_dir);
+	if (status == -ENOENT)
+		printk("NFSD: recovery directory %s doesn't exist\n",
+				rec_dirname);
+
+	if (!status)
+		rec_dir_init = 1;
+	nfs4_reset_user(uid, gid);
+}
+
+void
+nfsd4_shutdown_recdir(void)
+{
+	if (!rec_dir_init)
+		return;
+	rec_dir_init = 0;
+	path_release(&rec_dir);
+}
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 75e8b13..89e3652 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -48,39 +48,32 @@
 #include <linux/nfs4.h>
 #include <linux/nfsd/state.h>
 #include <linux/nfsd/xdr4.h>
+#include <linux/namei.h>
 
 #define NFSDDBG_FACILITY                NFSDDBG_PROC
 
 /* Globals */
 static time_t lease_time = 90;     /* default lease time */
-static time_t old_lease_time = 90; /* past incarnation lease time */
-static u32 nfs4_reclaim_init = 0;
-time_t boot_time;
-static time_t grace_end = 0;
+static time_t user_lease_time = 90;
+static time_t boot_time;
+static int in_grace = 1;
 static u32 current_clientid = 1;
 static u32 current_ownerid = 1;
 static u32 current_fileid = 1;
 static u32 current_delegid = 1;
 static u32 nfs4_init;
-stateid_t zerostateid;             /* bits all 0 */
-stateid_t onestateid;              /* bits all 1 */
+static stateid_t zerostateid;             /* bits all 0 */
+static stateid_t onestateid;              /* bits all 1 */
 
-/* debug counters */
-u32 list_add_perfile = 0; 
-u32 list_del_perfile = 0;
-u32 add_perclient = 0;
-u32 del_perclient = 0;
-u32 alloc_file = 0;
-u32 free_file = 0;
-u32 vfsopen = 0;
-u32 vfsclose = 0;
-u32 alloc_delegation= 0;
-u32 free_delegation= 0;
+#define ZERO_STATEID(stateid) (!memcmp((stateid), &zerostateid, sizeof(stateid_t)))
+#define ONE_STATEID(stateid)  (!memcmp((stateid), &onestateid, sizeof(stateid_t)))
 
 /* forward declarations */
-struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
+static struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
 static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid);
 static void release_stateid_lockowners(struct nfs4_stateid *open_stp);
+static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
+static void nfs4_set_recdir(char *recdir);
 
 /* Locking:
  *
@@ -90,6 +83,11 @@
  */
 static DECLARE_MUTEX(client_sema);
 
+static kmem_cache_t *stateowner_slab = NULL;
+static kmem_cache_t *file_slab = NULL;
+static kmem_cache_t *stateid_slab = NULL;
+static kmem_cache_t *deleg_slab = NULL;
+
 void
 nfs4_lock_state(void)
 {
@@ -118,16 +116,36 @@
 /* forward declarations */
 static void release_stateowner(struct nfs4_stateowner *sop);
 static void release_stateid(struct nfs4_stateid *stp, int flags);
-static void release_file(struct nfs4_file *fp);
 
 /*
  * Delegation state
  */
 
 /* recall_lock protects the del_recall_lru */
-spinlock_t recall_lock;
+static spinlock_t recall_lock = SPIN_LOCK_UNLOCKED;
 static struct list_head del_recall_lru;
 
+static void
+free_nfs4_file(struct kref *kref)
+{
+	struct nfs4_file *fp = container_of(kref, struct nfs4_file, fi_ref);
+	list_del(&fp->fi_hash);
+	iput(fp->fi_inode);
+	kmem_cache_free(file_slab, fp);
+}
+
+static inline void
+put_nfs4_file(struct nfs4_file *fi)
+{
+	kref_put(&fi->fi_ref, free_nfs4_file);
+}
+
+static inline void
+get_nfs4_file(struct nfs4_file *fi)
+{
+	kref_get(&fi->fi_ref);
+}
+
 static struct nfs4_delegation *
 alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type)
 {
@@ -136,13 +154,14 @@
 	struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback;
 
 	dprintk("NFSD alloc_init_deleg\n");
-	if ((dp = kmalloc(sizeof(struct nfs4_delegation),
-		GFP_KERNEL)) == NULL)
+	dp = kmem_cache_alloc(deleg_slab, GFP_KERNEL);
+	if (dp == NULL)
 		return dp;
-	INIT_LIST_HEAD(&dp->dl_del_perfile);
-	INIT_LIST_HEAD(&dp->dl_del_perclnt);
+	INIT_LIST_HEAD(&dp->dl_perfile);
+	INIT_LIST_HEAD(&dp->dl_perclnt);
 	INIT_LIST_HEAD(&dp->dl_recall_lru);
 	dp->dl_client = clp;
+	get_nfs4_file(fp);
 	dp->dl_file = fp;
 	dp->dl_flock = NULL;
 	get_file(stp->st_vfs_file);
@@ -160,9 +179,8 @@
 		        current_fh->fh_handle.fh_size);
 	dp->dl_time = 0;
 	atomic_set(&dp->dl_count, 1);
-	list_add(&dp->dl_del_perfile, &fp->fi_del_perfile);
-	list_add(&dp->dl_del_perclnt, &clp->cl_del_perclnt);
-	alloc_delegation++;
+	list_add(&dp->dl_perfile, &fp->fi_delegations);
+	list_add(&dp->dl_perclnt, &clp->cl_delegations);
 	return dp;
 }
 
@@ -171,8 +189,8 @@
 {
 	if (atomic_dec_and_test(&dp->dl_count)) {
 		dprintk("NFSD: freeing dp %p\n",dp);
-		kfree(dp);
-		free_delegation++;
+		put_nfs4_file(dp->dl_file);
+		kmem_cache_free(deleg_slab, dp);
 	}
 }
 
@@ -193,15 +211,14 @@
 	if (dp->dl_flock)
 		setlease(filp, F_UNLCK, &dp->dl_flock);
 	nfsd_close(filp);
-	vfsclose++;
 }
 
 /* Called under the state lock. */
 static void
 unhash_delegation(struct nfs4_delegation *dp)
 {
-	list_del_init(&dp->dl_del_perfile);
-	list_del_init(&dp->dl_del_perclnt);
+	list_del_init(&dp->dl_perfile);
+	list_del_init(&dp->dl_perclnt);
 	spin_lock(&recall_lock);
 	list_del_init(&dp->dl_recall_lru);
 	spin_unlock(&recall_lock);
@@ -220,8 +237,8 @@
 
 #define clientid_hashval(id) \
 	((id) & CLIENT_HASH_MASK)
-#define clientstr_hashval(name, namelen) \
-	(opaque_hashval((name), (namelen)) & CLIENT_HASH_MASK)
+#define clientstr_hashval(name) \
+	(opaque_hashval((name), 8) & CLIENT_HASH_MASK)
 /*
  * reclaim_str_hashtbl[] holds known client info from previous reset/reboot
  * used in reboot/reset lease grace period processing
@@ -331,11 +348,11 @@
 
 	INIT_LIST_HEAD(&reaplist);
 	spin_lock(&recall_lock);
-	while (!list_empty(&clp->cl_del_perclnt)) {
-		dp = list_entry(clp->cl_del_perclnt.next, struct nfs4_delegation, dl_del_perclnt);
+	while (!list_empty(&clp->cl_delegations)) {
+		dp = list_entry(clp->cl_delegations.next, struct nfs4_delegation, dl_perclnt);
 		dprintk("NFSD: expire client. dp %p, fp %p\n", dp,
 				dp->dl_flock);
-		list_del_init(&dp->dl_del_perclnt);
+		list_del_init(&dp->dl_perclnt);
 		list_move(&dp->dl_recall_lru, &reaplist);
 	}
 	spin_unlock(&recall_lock);
@@ -347,26 +364,26 @@
 	list_del(&clp->cl_idhash);
 	list_del(&clp->cl_strhash);
 	list_del(&clp->cl_lru);
-	while (!list_empty(&clp->cl_perclient)) {
-		sop = list_entry(clp->cl_perclient.next, struct nfs4_stateowner, so_perclient);
+	while (!list_empty(&clp->cl_openowners)) {
+		sop = list_entry(clp->cl_openowners.next, struct nfs4_stateowner, so_perclient);
 		release_stateowner(sop);
 	}
 	put_nfs4_client(clp);
 }
 
 static struct nfs4_client *
-create_client(struct xdr_netobj name) {
+create_client(struct xdr_netobj name, char *recdir) {
 	struct nfs4_client *clp;
 
 	if (!(clp = alloc_client(name)))
 		goto out;
+	memcpy(clp->cl_recdir, recdir, HEXDIR_LEN);
 	atomic_set(&clp->cl_count, 1);
 	atomic_set(&clp->cl_callback.cb_set, 0);
-	clp->cl_callback.cb_parsed = 0;
 	INIT_LIST_HEAD(&clp->cl_idhash);
 	INIT_LIST_HEAD(&clp->cl_strhash);
-	INIT_LIST_HEAD(&clp->cl_perclient);
-	INIT_LIST_HEAD(&clp->cl_del_perclnt);
+	INIT_LIST_HEAD(&clp->cl_openowners);
+	INIT_LIST_HEAD(&clp->cl_delegations);
 	INIT_LIST_HEAD(&clp->cl_lru);
 out:
 	return clp;
@@ -392,11 +409,9 @@
 	get_group_info(target->cr_group_info);
 }
 
-static int
-cmp_name(struct xdr_netobj *n1, struct xdr_netobj *n2) {
-	if (!n1 || !n2)
-		return 0;
-	return((n1->len == n2->len) && !memcmp(n1->data, n2->data, n2->len));
+static inline int
+same_name(const char *n1, const char *n2) {
+	return 0 == memcmp(n1, n2, HEXDIR_LEN);
 }
 
 static int
@@ -446,7 +461,7 @@
 	return 1;
 }
 
-void
+static void
 add_to_unconfirmed(struct nfs4_client *clp, unsigned int strhashval)
 {
 	unsigned int idhashval;
@@ -458,7 +473,7 @@
 	clp->cl_time = get_seconds();
 }
 
-void
+static void
 move_to_confirmed(struct nfs4_client *clp)
 {
 	unsigned int idhashval = clientid_hashval(clp->cl_clientid.cl_id);
@@ -468,8 +483,7 @@
 	list_del_init(&clp->cl_strhash);
 	list_del_init(&clp->cl_idhash);
 	list_add(&clp->cl_idhash, &conf_id_hashtbl[idhashval]);
-	strhashval = clientstr_hashval(clp->cl_name.data, 
-			clp->cl_name.len);
+	strhashval = clientstr_hashval(clp->cl_recdir);
 	list_add(&clp->cl_strhash, &conf_str_hashtbl[strhashval]);
 	renew_client(clp);
 }
@@ -500,6 +514,30 @@
 	return NULL;
 }
 
+static struct nfs4_client *
+find_confirmed_client_by_str(const char *dname, unsigned int hashval)
+{
+	struct nfs4_client *clp;
+
+	list_for_each_entry(clp, &conf_str_hashtbl[hashval], cl_strhash) {
+		if (same_name(clp->cl_recdir, dname))
+			return clp;
+	}
+	return NULL;
+}
+
+static struct nfs4_client *
+find_unconfirmed_client_by_str(const char *dname, unsigned int hashval)
+{
+	struct nfs4_client *clp;
+
+	list_for_each_entry(clp, &unconf_str_hashtbl[hashval], cl_strhash) {
+		if (same_name(clp->cl_recdir, dname))
+			return clp;
+	}
+	return NULL;
+}
+
 /* a helper function for parse_callback */
 static int
 parse_octet(unsigned int *lenp, char **addrp)
@@ -534,7 +572,7 @@
 }
 
 /* parse and set the setclientid ipv4 callback address */
-int
+static int
 parse_ipv4(unsigned int addr_len, char *addr_val, unsigned int *cbaddrp, unsigned short *cbportp)
 {
 	int temp = 0;
@@ -570,7 +608,7 @@
 	return 1;
 }
 
-void
+static void
 gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se)
 {
 	struct nfs4_callback *cb = &clp->cl_callback;
@@ -584,14 +622,12 @@
 		goto out_err;
 	cb->cb_prog = se->se_callback_prog;
 	cb->cb_ident = se->se_callback_ident;
-	cb->cb_parsed = 1;
 	return;
 out_err:
 	printk(KERN_INFO "NFSD: this client (clientid %08x/%08x) "
 		"will not receive delegations\n",
 		clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
 
-	cb->cb_parsed = 0;
 	return;
 }
 
@@ -638,59 +674,43 @@
 	};
 	nfs4_verifier		clverifier = setclid->se_verf;
 	unsigned int 		strhashval;
-	struct nfs4_client *	conf, * unconf, * new, * clp;
+	struct nfs4_client	*conf, *unconf, *new;
 	int 			status;
+	char                    dname[HEXDIR_LEN];
 	
 	status = nfserr_inval;
 	if (!check_name(clname))
 		goto out;
 
+	status = nfs4_make_rec_clidname(dname, &clname);
+	if (status)
+		goto out;
+
 	/* 
 	 * XXX The Duplicate Request Cache (DRC) has been checked (??)
 	 * We get here on a DRC miss.
 	 */
 
-	strhashval = clientstr_hashval(clname.data, clname.len);
+	strhashval = clientstr_hashval(dname);
 
-	conf = NULL;
 	nfs4_lock_state();
-	list_for_each_entry(clp, &conf_str_hashtbl[strhashval], cl_strhash) {
-		if (!cmp_name(&clp->cl_name, &clname))
-			continue;
+	conf = find_confirmed_client_by_str(dname, strhashval);
+	if (conf) {
 		/* 
 		 * CASE 0:
 		 * clname match, confirmed, different principal
 		 * or different ip_address
 		 */
 		status = nfserr_clid_inuse;
-		if (!cmp_creds(&clp->cl_cred,&rqstp->rq_cred)) {
+		if (!cmp_creds(&conf->cl_cred, &rqstp->rq_cred)
+				|| conf->cl_addr != ip_addr) {
 			printk("NFSD: setclientid: string in use by client"
 			"(clientid %08x/%08x)\n",
-			clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
+			conf->cl_clientid.cl_boot, conf->cl_clientid.cl_id);
 			goto out;
 		}
-		if (clp->cl_addr != ip_addr) { 
-			printk("NFSD: setclientid: string in use by client"
-			"(clientid %08x/%08x)\n",
-			clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
-			goto out;
-		}
-
-		/* 
-	 	 * cl_name match from a previous SETCLIENTID operation
-	 	 * XXX check for additional matches?
-		 */
-		conf = clp;
-		break;
 	}
-	unconf = NULL;
-	list_for_each_entry(clp, &unconf_str_hashtbl[strhashval], cl_strhash) {
-		if (!cmp_name(&clp->cl_name, &clname))
-			continue;
-		/* cl_name match from a previous SETCLIENTID operation */
-		unconf = clp;
-		break;
-	}
+	unconf = find_unconfirmed_client_by_str(dname, strhashval);
 	status = nfserr_resource;
 	if (!conf) {
 		/* 
@@ -699,7 +719,8 @@
 		 */
 		if (unconf)
 			expire_client(unconf);
-		if (!(new = create_client(clname)))
+		new = create_client(clname, dname);
+		if (new == NULL)
 			goto out;
 		copy_verf(new, &clverifier);
 		new->cl_addr = ip_addr;
@@ -722,12 +743,16 @@
 		 * nfs4_client,  but with the new callback info and a 
 		 * new cl_confirm
 		 */
-		if ((unconf) && 
-		    cmp_verf(&unconf->cl_verifier, &conf->cl_verifier) &&
-		     cmp_clid(&unconf->cl_clientid, &conf->cl_clientid)) {
-				expire_client(unconf);
+		if (unconf) {
+			/* Note this is removing unconfirmed {*x***},
+			 * which is stronger than RFC recommended {vxc**}.
+			 * This has the advantage that there is at most
+			 * one {*x***} in either list at any time.
+			 */
+			expire_client(unconf);
 		}
-		if (!(new = create_client(clname)))
+		new = create_client(clname, dname);
+		if (new == NULL)
 			goto out;
 		copy_verf(new,&conf->cl_verifier);
 		new->cl_addr = ip_addr;
@@ -745,7 +770,8 @@
 		 * using input clverifier, clname, and callback info
 		 * and generate a new cl_clientid and cl_confirm.
 		 */
-		if (!(new = create_client(clname)))
+		new = create_client(clname, dname);
+		if (new == NULL)
 			goto out;
 		copy_verf(new,&clverifier);
 		new->cl_addr = ip_addr;
@@ -771,7 +797,8 @@
 		 * new cl_verifier and a new cl_confirm
 		 */
 		expire_client(unconf);
-		if (!(new = create_client(clname)))
+		new = create_client(clname, dname);
+		if (new == NULL)
 			goto out;
 		copy_verf(new,&clverifier);
 		new->cl_addr = ip_addr;
@@ -807,7 +834,7 @@
 nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm)
 {
 	u32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
-	struct nfs4_client *clp, *conf = NULL, *unconf = NULL;
+	struct nfs4_client *conf, *unconf;
 	nfs4_verifier confirm = setclientid_confirm->sc_confirm; 
 	clientid_t * clid = &setclientid_confirm->sc_clientid;
 	int status;
@@ -820,102 +847,90 @@
 	 */
 
 	nfs4_lock_state();
-	clp = find_confirmed_client(clid);
-	if (clp) {
-		status = nfserr_inval;
-		/* 
-		 * Found a record for this clientid. If the IP addresses
-		 * don't match, return ERR_INVAL just as if the record had
-		 * not been found.
-		 */
-		if (clp->cl_addr != ip_addr) { 
-			printk("NFSD: setclientid: string in use by client"
-			"(clientid %08x/%08x)\n",
-			clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
-			goto out;
-		}
-		conf = clp;
-	}
-	clp = find_unconfirmed_client(clid);
-	if (clp) {
-		status = nfserr_inval;
-		if (clp->cl_addr != ip_addr) { 
-			printk("NFSD: setclientid: string in use by client"
-			"(clientid %08x/%08x)\n",
-			clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
-			goto out;
-		}
-		unconf = clp;
-	}
-	/* CASE 1: 
-	* unconf record that matches input clientid and input confirm.
-	* conf record that matches input clientid.
-	* conf  and unconf records match names, verifiers 
-	*/
+
+	conf = find_confirmed_client(clid);
+	unconf = find_unconfirmed_client(clid);
+
+	status = nfserr_clid_inuse;
+	if (conf && conf->cl_addr != ip_addr)
+		goto out;
+	if (unconf && unconf->cl_addr != ip_addr)
+		goto out;
+
 	if ((conf && unconf) && 
 	    (cmp_verf(&unconf->cl_confirm, &confirm)) &&
 	    (cmp_verf(&conf->cl_verifier, &unconf->cl_verifier)) &&
-	    (cmp_name(&conf->cl_name,&unconf->cl_name))  &&
+	    (same_name(conf->cl_recdir,unconf->cl_recdir))  &&
 	    (!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm))) {
+		/* CASE 1:
+		* unconf record that matches input clientid and input confirm.
+		* conf record that matches input clientid.
+		* conf and unconf records match names, verifiers
+		*/
 		if (!cmp_creds(&conf->cl_cred, &unconf->cl_cred)) 
 			status = nfserr_clid_inuse;
 		else {
-			expire_client(conf);
-			clp = unconf;
-			move_to_confirmed(unconf);
+			/* XXX: We just turn off callbacks until we can handle
+			  * change request correctly. */
+			atomic_set(&conf->cl_callback.cb_set, 0);
+			gen_confirm(conf);
+			expire_client(unconf);
 			status = nfs_ok;
+
 		}
-		goto out;
-	} 
-	/* CASE 2:
-	 * conf record that matches input clientid.
-	 * if unconf record that matches input clientid, then unconf->cl_name
-	 * or unconf->cl_verifier don't match the conf record.
-	 */
-	if ((conf && !unconf) || 
+	} else if ((conf && !unconf) ||
 	    ((conf && unconf) && 
 	     (!cmp_verf(&conf->cl_verifier, &unconf->cl_verifier) ||
-	      !cmp_name(&conf->cl_name, &unconf->cl_name)))) {
-		if (!cmp_creds(&conf->cl_cred,&rqstp->rq_cred)) {
+	      !same_name(conf->cl_recdir, unconf->cl_recdir)))) {
+		/* CASE 2:
+		 * conf record that matches input clientid.
+		 * if unconf record matches input clientid, then
+		 * unconf->cl_name or unconf->cl_verifier don't match the
+		 * conf record.
+		 */
+		if (!cmp_creds(&conf->cl_cred,&rqstp->rq_cred))
 			status = nfserr_clid_inuse;
-		} else {
-			clp = conf;
+		else
 			status = nfs_ok;
-		}
-		goto out;
-	}
-	/* CASE 3:
-	 * conf record not found.
-	 * unconf record found. 
-	 * unconf->cl_confirm matches input confirm
-	 */ 
-	if (!conf && unconf && cmp_verf(&unconf->cl_confirm, &confirm)) {
+	} else if (!conf && unconf
+			&& cmp_verf(&unconf->cl_confirm, &confirm)) {
+		/* CASE 3:
+		 * conf record not found.
+		 * unconf record found.
+		 * unconf->cl_confirm matches input confirm
+		 */
 		if (!cmp_creds(&unconf->cl_cred, &rqstp->rq_cred)) {
 			status = nfserr_clid_inuse;
 		} else {
-			status = nfs_ok;
-			clp = unconf;
+			unsigned int hash =
+				clientstr_hashval(unconf->cl_recdir);
+			conf = find_confirmed_client_by_str(unconf->cl_recdir,
+									hash);
+			if (conf) {
+				nfsd4_remove_clid_dir(conf);
+				expire_client(conf);
+			}
 			move_to_confirmed(unconf);
+			conf = unconf;
+			status = nfs_ok;
 		}
-		goto out;
-	}
-	/* CASE 4:
-	 * conf record not found, or if conf, then conf->cl_confirm does not
-	 * match input confirm.
-	 * unconf record not found, or if unconf, then unconf->cl_confirm 
-	 * does not match input confirm.
-	 */
-	if ((!conf || (conf && !cmp_verf(&conf->cl_confirm, &confirm))) &&
-	    (!unconf || (unconf && !cmp_verf(&unconf->cl_confirm, &confirm)))) {
+	} else if ((!conf || (conf && !cmp_verf(&conf->cl_confirm, &confirm)))
+	    && (!unconf || (unconf && !cmp_verf(&unconf->cl_confirm,
+				    				&confirm)))) {
+		/* CASE 4:
+		 * conf record not found, or if conf, conf->cl_confirm does not
+		 * match input confirm.
+		 * unconf record not found, or if unconf, unconf->cl_confirm
+		 * does not match input confirm.
+		 */
 		status = nfserr_stale_clientid;
-		goto out;
+	} else {
+		/* check that we have hit one of the cases...*/
+		status = nfserr_clid_inuse;
 	}
-	/* check that we have hit one of the cases...*/
-	status = nfserr_inval;
-	goto out;
 out:
 	if (!status)
-		nfsd4_probe_callback(clp);
+		nfsd4_probe_callback(conf);
 	nfs4_unlock_state();
 	return status;
 }
@@ -961,60 +976,65 @@
 	struct nfs4_file *fp;
 	unsigned int hashval = file_hashval(ino);
 
-	if ((fp = kmalloc(sizeof(struct nfs4_file),GFP_KERNEL))) {
+	fp = kmem_cache_alloc(file_slab, GFP_KERNEL);
+	if (fp) {
+		kref_init(&fp->fi_ref);
 		INIT_LIST_HEAD(&fp->fi_hash);
-		INIT_LIST_HEAD(&fp->fi_perfile);
-		INIT_LIST_HEAD(&fp->fi_del_perfile);
+		INIT_LIST_HEAD(&fp->fi_stateids);
+		INIT_LIST_HEAD(&fp->fi_delegations);
 		list_add(&fp->fi_hash, &file_hashtbl[hashval]);
 		fp->fi_inode = igrab(ino);
 		fp->fi_id = current_fileid++;
-		alloc_file++;
 		return fp;
 	}
 	return NULL;
 }
 
 static void
-release_all_files(void)
+nfsd4_free_slab(kmem_cache_t **slab)
 {
-	int i;
-	struct nfs4_file *fp;
+	int status;
 
-	for (i=0;i<FILE_HASH_SIZE;i++) {
-		while (!list_empty(&file_hashtbl[i])) {
-			fp = list_entry(file_hashtbl[i].next, struct nfs4_file, fi_hash);
-			/* this should never be more than once... */
-			if (!list_empty(&fp->fi_perfile) || !list_empty(&fp->fi_del_perfile)) {
-				printk("ERROR: release_all_files: file %p is open, creating dangling state !!!\n",fp);
-			}
-			release_file(fp);
-		}
-	}
+	if (*slab == NULL)
+		return;
+	status = kmem_cache_destroy(*slab);
+	*slab = NULL;
+	WARN_ON(status);
 }
 
-kmem_cache_t *stateowner_slab = NULL;
+static void
+nfsd4_free_slabs(void)
+{
+	nfsd4_free_slab(&stateowner_slab);
+	nfsd4_free_slab(&file_slab);
+	nfsd4_free_slab(&stateid_slab);
+	nfsd4_free_slab(&deleg_slab);
+}
 
 static int
 nfsd4_init_slabs(void)
 {
 	stateowner_slab = kmem_cache_create("nfsd4_stateowners",
 			sizeof(struct nfs4_stateowner), 0, 0, NULL, NULL);
-	if (stateowner_slab == NULL) {
-		dprintk("nfsd4: out of memory while initializing nfsv4\n");
-		return -ENOMEM;
-	}
+	if (stateowner_slab == NULL)
+		goto out_nomem;
+	file_slab = kmem_cache_create("nfsd4_files",
+			sizeof(struct nfs4_file), 0, 0, NULL, NULL);
+	if (file_slab == NULL)
+		goto out_nomem;
+	stateid_slab = kmem_cache_create("nfsd4_stateids",
+			sizeof(struct nfs4_stateid), 0, 0, NULL, NULL);
+	if (stateid_slab == NULL)
+		goto out_nomem;
+	deleg_slab = kmem_cache_create("nfsd4_delegations",
+			sizeof(struct nfs4_delegation), 0, 0, NULL, NULL);
+	if (deleg_slab == NULL)
+		goto out_nomem;
 	return 0;
-}
-
-static void
-nfsd4_free_slabs(void)
-{
-	int status = 0;
-
-	if (stateowner_slab)
-		status = kmem_cache_destroy(stateowner_slab);
-	stateowner_slab = NULL;
-	BUG_ON(status);
+out_nomem:
+	nfsd4_free_slabs();
+	dprintk("nfsd4: out of memory while initializing nfsv4\n");
+	return -ENOMEM;
 }
 
 void
@@ -1055,14 +1075,13 @@
 	INIT_LIST_HEAD(&sop->so_idhash);
 	INIT_LIST_HEAD(&sop->so_strhash);
 	INIT_LIST_HEAD(&sop->so_perclient);
-	INIT_LIST_HEAD(&sop->so_perfilestate);
-	INIT_LIST_HEAD(&sop->so_perlockowner);  /* not used */
+	INIT_LIST_HEAD(&sop->so_stateids);
+	INIT_LIST_HEAD(&sop->so_perstateid);  /* not used */
 	INIT_LIST_HEAD(&sop->so_close_lru);
 	sop->so_time = 0;
 	list_add(&sop->so_idhash, &ownerid_hashtbl[idhashval]);
 	list_add(&sop->so_strhash, &ownerstr_hashtbl[strhashval]);
-	list_add(&sop->so_perclient, &clp->cl_perclient);
-	add_perclient++;
+	list_add(&sop->so_perclient, &clp->cl_openowners);
 	sop->so_is_open_owner = 1;
 	sop->so_id = current_ownerid++;
 	sop->so_client = clp;
@@ -1080,10 +1099,10 @@
 {
 	struct nfs4_stateowner *lock_sop;
 
-	while (!list_empty(&open_stp->st_perlockowner)) {
-		lock_sop = list_entry(open_stp->st_perlockowner.next,
-				struct nfs4_stateowner, so_perlockowner);
-		/* list_del(&open_stp->st_perlockowner);  */
+	while (!list_empty(&open_stp->st_lockowners)) {
+		lock_sop = list_entry(open_stp->st_lockowners.next,
+				struct nfs4_stateowner, so_perstateid);
+		/* list_del(&open_stp->st_lockowners);  */
 		BUG_ON(lock_sop->so_is_open_owner);
 		release_stateowner(lock_sop);
 	}
@@ -1096,14 +1115,12 @@
 
 	list_del(&sop->so_idhash);
 	list_del(&sop->so_strhash);
-	if (sop->so_is_open_owner) {
+	if (sop->so_is_open_owner)
 		list_del(&sop->so_perclient);
-		del_perclient++;
-	}
-	list_del(&sop->so_perlockowner);
-	while (!list_empty(&sop->so_perfilestate)) {
-		stp = list_entry(sop->so_perfilestate.next, 
-			struct nfs4_stateid, st_perfilestate);
+	list_del(&sop->so_perstateid);
+	while (!list_empty(&sop->so_stateids)) {
+		stp = list_entry(sop->so_stateids.next,
+			struct nfs4_stateid, st_perstateowner);
 		if (sop->so_is_open_owner)
 			release_stateid(stp, OPEN_STATE);
 		else
@@ -1125,14 +1142,14 @@
 	unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id);
 
 	INIT_LIST_HEAD(&stp->st_hash);
-	INIT_LIST_HEAD(&stp->st_perfilestate);
-	INIT_LIST_HEAD(&stp->st_perlockowner);
+	INIT_LIST_HEAD(&stp->st_perstateowner);
+	INIT_LIST_HEAD(&stp->st_lockowners);
 	INIT_LIST_HEAD(&stp->st_perfile);
 	list_add(&stp->st_hash, &stateid_hashtbl[hashval]);
-	list_add(&stp->st_perfilestate, &sop->so_perfilestate);
-	list_add_perfile++;
-	list_add(&stp->st_perfile, &fp->fi_perfile);
+	list_add(&stp->st_perstateowner, &sop->so_stateids);
+	list_add(&stp->st_perfile, &fp->fi_stateids);
 	stp->st_stateowner = sop;
+	get_nfs4_file(fp);
 	stp->st_file = fp;
 	stp->st_stateid.si_boot = boot_time;
 	stp->st_stateid.si_stateownerid = sop->so_id;
@@ -1150,30 +1167,20 @@
 	struct file *filp = stp->st_vfs_file;
 
 	list_del(&stp->st_hash);
-	list_del_perfile++;
 	list_del(&stp->st_perfile);
-	list_del(&stp->st_perfilestate);
+	list_del(&stp->st_perstateowner);
 	if (flags & OPEN_STATE) {
 		release_stateid_lockowners(stp);
 		stp->st_vfs_file = NULL;
 		nfsd_close(filp);
-		vfsclose++;
 	} else if (flags & LOCK_STATE)
 		locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
-	kfree(stp);
+	put_nfs4_file(stp->st_file);
+	kmem_cache_free(stateid_slab, stp);
 	stp = NULL;
 }
 
 static void
-release_file(struct nfs4_file *fp)
-{
-	free_file++;
-	list_del(&fp->fi_hash);
-	iput(fp->fi_inode);
-	kfree(fp);
-}	
-
-void
 move_to_close_lru(struct nfs4_stateowner *sop)
 {
 	dprintk("NFSD: move_to_close_lru nfs4_stateowner %p\n", sop);
@@ -1183,11 +1190,10 @@
 	sop->so_time = get_seconds();
 }
 
-void
+static void
 release_state_owner(struct nfs4_stateid *stp, int flag)
 {
 	struct nfs4_stateowner *sop = stp->st_stateowner;
-	struct nfs4_file *fp = stp->st_file;
 
 	dprintk("NFSD: release_state_owner\n");
 	release_stateid(stp, flag);
@@ -1196,12 +1202,8 @@
 	 * released by the laundromat service after the lease period
 	 * to enable us to handle CLOSE replay
 	 */
-	if (sop->so_confirmed && list_empty(&sop->so_perfilestate))
+	if (sop->so_confirmed && list_empty(&sop->so_stateids))
 		move_to_close_lru(sop);
-	/* unused nfs4_file's are releseed. XXX slab cache? */
-	if (list_empty(&fp->fi_perfile) && list_empty(&fp->fi_del_perfile)) {
-		release_file(fp);
-	}
 }
 
 static int
@@ -1231,8 +1233,10 @@
 	struct nfs4_file *fp;
 
 	list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) {
-		if (fp->fi_inode == ino)
+		if (fp->fi_inode == ino) {
+			get_nfs4_file(fp);
 			return fp;
+		}
 	}
 	return NULL;
 }
@@ -1240,7 +1244,7 @@
 #define TEST_ACCESS(x) ((x > 0 || x < 4)?1:0)
 #define TEST_DENY(x) ((x >= 0 || x < 5)?1:0)
 
-void
+static void
 set_access(unsigned int *access, unsigned long bmap) {
 	int i;
 
@@ -1251,7 +1255,7 @@
 	}
 }
 
-void
+static void
 set_deny(unsigned int *deny, unsigned long bmap) {
 	int i;
 
@@ -1277,25 +1281,30 @@
  * Called to check deny when READ with all zero stateid or
  * WRITE with all zero or all one stateid
  */
-int
+static int
 nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
 {
 	struct inode *ino = current_fh->fh_dentry->d_inode;
 	struct nfs4_file *fp;
 	struct nfs4_stateid *stp;
+	int ret;
 
 	dprintk("NFSD: nfs4_share_conflict\n");
 
 	fp = find_file(ino);
-	if (fp) {
+	if (!fp)
+		return nfs_ok;
+	ret = nfserr_share_denied;
 	/* Search for conflicting share reservations */
-		list_for_each_entry(stp, &fp->fi_perfile, st_perfile) {
-			if (test_bit(deny_type, &stp->st_deny_bmap) ||
-			    test_bit(NFS4_SHARE_DENY_BOTH, &stp->st_deny_bmap))
-				return nfserr_share_denied;
-		}
+	list_for_each_entry(stp, &fp->fi_stateids, st_perfile) {
+		if (test_bit(deny_type, &stp->st_deny_bmap) ||
+		    test_bit(NFS4_SHARE_DENY_BOTH, &stp->st_deny_bmap))
+			goto out;
 	}
-	return nfs_ok;
+	ret = nfs_ok;
+out:
+	put_nfs4_file(fp);
+	return ret;
 }
 
 static inline void
@@ -1427,7 +1436,7 @@
 		return -EAGAIN;
 }
 
-struct lock_manager_operations nfsd_lease_mng_ops = {
+static struct lock_manager_operations nfsd_lease_mng_ops = {
 	.fl_break = nfsd_break_deleg_cb,
 	.fl_release_private = nfsd_release_deleg_cb,
 	.fl_copy_lock = nfsd_copy_lock_deleg_cb,
@@ -1526,6 +1535,51 @@
 	return status;
 }
 
+static inline int
+nfs4_check_delegmode(struct nfs4_delegation *dp, int flags)
+{
+	if ((flags & WR_STATE) && (dp->dl_type == NFS4_OPEN_DELEGATE_READ))
+		return nfserr_openmode;
+	else
+		return nfs_ok;
+}
+
+static struct nfs4_delegation *
+find_delegation_file(struct nfs4_file *fp, stateid_t *stid)
+{
+	struct nfs4_delegation *dp;
+
+	list_for_each_entry(dp, &fp->fi_delegations, dl_perfile) {
+		if (dp->dl_stateid.si_stateownerid == stid->si_stateownerid)
+			return dp;
+	}
+	return NULL;
+}
+
+static int
+nfs4_check_deleg(struct nfs4_file *fp, struct nfsd4_open *open,
+		struct nfs4_delegation **dp)
+{
+	int flags;
+	int status = nfserr_bad_stateid;
+
+	*dp = find_delegation_file(fp, &open->op_delegate_stateid);
+	if (*dp == NULL)
+		goto out;
+	flags = open->op_share_access == NFS4_SHARE_ACCESS_READ ?
+						RD_STATE : WR_STATE;
+	status = nfs4_check_delegmode(*dp, flags);
+	if (status)
+		*dp = NULL;
+out:
+	if (open->op_claim_type != NFS4_OPEN_CLAIM_DELEGATE_CUR)
+		return nfs_ok;
+	if (status)
+		return status;
+	open->op_stateowner->so_confirmed = 1;
+	return nfs_ok;
+}
+
 static int
 nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_stateid **stpp)
 {
@@ -1533,7 +1587,7 @@
 	int status = nfserr_share_denied;
 	struct nfs4_stateowner *sop = open->op_stateowner;
 
-	list_for_each_entry(local, &fp->fi_perfile, st_perfile) {
+	list_for_each_entry(local, &fp->fi_stateids, st_perfile) {
 		/* ignore lock owners */
 		if (local->st_stateowner->so_is_open_owner == 0)
 			continue;
@@ -1549,25 +1603,37 @@
 	return status;
 }
 
+static inline struct nfs4_stateid *
+nfs4_alloc_stateid(void)
+{
+	return kmem_cache_alloc(stateid_slab, GFP_KERNEL);
+}
+
 static int
 nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp,
+		struct nfs4_delegation *dp,
 		struct svc_fh *cur_fh, int flags)
 {
 	struct nfs4_stateid *stp;
-	int status;
 
-	stp = kmalloc(sizeof(struct nfs4_stateid), GFP_KERNEL);
+	stp = nfs4_alloc_stateid();
 	if (stp == NULL)
 		return nfserr_resource;
 
-	status = nfsd_open(rqstp, cur_fh, S_IFREG, flags, &stp->st_vfs_file);
-	if (status) {
-		if (status == nfserr_dropit)
-			status = nfserr_jukebox;
-		kfree(stp);
-		return status;
+	if (dp) {
+		get_file(dp->dl_vfs_file);
+		stp->st_vfs_file = dp->dl_vfs_file;
+	} else {
+		int status;
+		status = nfsd_open(rqstp, cur_fh, S_IFREG, flags,
+				&stp->st_vfs_file);
+		if (status) {
+			if (status == nfserr_dropit)
+				status = nfserr_jukebox;
+			kmem_cache_free(stateid_slab, stp);
+			return status;
+		}
 	}
-	vfsopen++;
 	*stpp = stp;
 	return 0;
 }
@@ -1628,6 +1694,7 @@
 			*status = nfserr_reclaim_bad;
 		else {
 			open->op_stateowner->so_confirmed = 1;
+			open->op_stateowner->so_client->cl_firststate = 1;
 			open->op_stateowner->so_seqid--;
 		}
 	}
@@ -1646,14 +1713,30 @@
 	int status, flag = 0;
 
 	flag = NFS4_OPEN_DELEGATE_NONE;
-	if (open->op_claim_type != NFS4_OPEN_CLAIM_NULL
-	     || !atomic_read(&cb->cb_set) || !sop->so_confirmed)
-		goto out;
-
-	if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
-		flag = NFS4_OPEN_DELEGATE_WRITE;
-	else
-		flag = NFS4_OPEN_DELEGATE_READ;
+	open->op_recall = 0;
+	switch (open->op_claim_type) {
+		case NFS4_OPEN_CLAIM_PREVIOUS:
+			if (!atomic_read(&cb->cb_set))
+				open->op_recall = 1;
+			flag = open->op_delegate_type;
+			if (flag == NFS4_OPEN_DELEGATE_NONE)
+				goto out;
+			break;
+		case NFS4_OPEN_CLAIM_NULL:
+			/* Let's not give out any delegations till everyone's
+			 * had the chance to reclaim theirs.... */
+			if (nfs4_in_grace())
+				goto out;
+			if (!atomic_read(&cb->cb_set) || !sop->so_confirmed)
+				goto out;
+			if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
+				flag = NFS4_OPEN_DELEGATE_WRITE;
+			else
+				flag = NFS4_OPEN_DELEGATE_READ;
+			break;
+		default:
+			goto out;
+	}
 
 	dp = alloc_init_deleg(sop->so_client, stp, fh, flag);
 	if (dp == NULL) {
@@ -1687,6 +1770,10 @@
 	             dp->dl_stateid.si_fileid,
 	             dp->dl_stateid.si_generation);
 out:
+	if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS
+			&& flag == NFS4_OPEN_DELEGATE_NONE
+			&& open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE)
+		printk("NFSD: WARNING: refusing delegation reclaim\n");
 	open->op_delegate_type = flag;
 }
 
@@ -1699,6 +1786,7 @@
 	struct nfs4_file *fp = NULL;
 	struct inode *ino = current_fh->fh_dentry->d_inode;
 	struct nfs4_stateid *stp = NULL;
+	struct nfs4_delegation *dp = NULL;
 	int status;
 
 	status = nfserr_inval;
@@ -1713,7 +1801,13 @@
 	if (fp) {
 		if ((status = nfs4_check_open(fp, open, &stp)))
 			goto out;
+		status = nfs4_check_deleg(fp, open, &dp);
+		if (status)
+			goto out;
 	} else {
+		status = nfserr_bad_stateid;
+		if (open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR)
+			goto out;
 		status = nfserr_resource;
 		fp = alloc_init_file(ino);
 		if (fp == NULL)
@@ -1736,7 +1830,8 @@
 			flags = MAY_WRITE;
 		else
 			flags = MAY_READ;
-		if ((status = nfs4_new_open(rqstp, &stp, current_fh, flags)))
+		status = nfs4_new_open(rqstp, &stp, dp, current_fh, flags);
+		if (status)
 			goto out;
 		init_stateid(stp, fp, open);
 		status = nfsd4_truncate(rqstp, current_fh, open);
@@ -1759,10 +1854,8 @@
 	            stp->st_stateid.si_boot, stp->st_stateid.si_stateownerid,
 	            stp->st_stateid.si_fileid, stp->st_stateid.si_generation);
 out:
-	/* take the opportunity to clean up unused state */
-	if (fp && list_empty(&fp->fi_perfile) && list_empty(&fp->fi_del_perfile))
-		release_file(fp);
-
+	if (fp)
+		put_nfs4_file(fp);
 	/* CLAIM_PREVIOUS has different error returns */
 	nfs4_set_claim_prev(open, &status);
 	/*
@@ -1775,6 +1868,7 @@
 	return status;
 }
 
+static struct workqueue_struct *laundry_wq;
 static struct work_struct laundromat_work;
 static void laundromat_main(void *);
 static DECLARE_WORK(laundromat_work, laundromat_main, NULL);
@@ -1800,7 +1894,7 @@
 	}
 	renew_client(clp);
 	status = nfserr_cb_path_down;
-	if (!list_empty(&clp->cl_del_perclnt)
+	if (!list_empty(&clp->cl_delegations)
 			&& !atomic_read(&clp->cl_callback.cb_set))
 		goto out;
 	status = nfs_ok;
@@ -1809,7 +1903,15 @@
 	return status;
 }
 
-time_t
+static void
+end_grace(void)
+{
+	dprintk("NFSD: end of grace period\n");
+	nfsd4_recdir_purge_old();
+	in_grace = 0;
+}
+
+static time_t
 nfs4_laundromat(void)
 {
 	struct nfs4_client *clp;
@@ -1823,6 +1925,8 @@
 	nfs4_lock_state();
 
 	dprintk("NFSD: laundromat service - starting\n");
+	if (in_grace)
+		end_grace();
 	list_for_each_safe(pos, next, &client_lru) {
 		clp = list_entry(pos, struct nfs4_client, cl_lru);
 		if (time_after((unsigned long)clp->cl_time, (unsigned long)cutoff)) {
@@ -1833,6 +1937,7 @@
 		}
 		dprintk("NFSD: purging unused client (clientid %08x)\n",
 			clp->cl_clientid.cl_id);
+		nfsd4_remove_clid_dir(clp);
 		expire_client(clp);
 	}
 	INIT_LIST_HEAD(&reaplist);
@@ -1882,13 +1987,13 @@
 
 	t = nfs4_laundromat();
 	dprintk("NFSD: laundromat_main - sleeping for %ld seconds\n", t);
-	schedule_delayed_work(&laundromat_work, t*HZ);
+	queue_delayed_work(laundry_wq, &laundromat_work, t*HZ);
 }
 
 /* search ownerid_hashtbl[] and close_lru for stateid owner
  * (stateid->si_stateownerid)
  */
-struct nfs4_stateowner *
+static struct nfs4_stateowner *
 find_openstateowner_id(u32 st_id, int flags) {
 	struct nfs4_stateowner *local = NULL;
 
@@ -1949,15 +2054,6 @@
 }
 
 static inline int
-nfs4_check_delegmode(struct nfs4_delegation *dp, int flags)
-{
-	if ((flags & WR_STATE) && (dp->dl_type == NFS4_OPEN_DELEGATE_READ))
-		return nfserr_openmode;
-	else
-		return nfs_ok;
-}
-
-static inline int
 check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
 {
 	/* Trying to call delegreturn with a special stateid? Yuch: */
@@ -2071,7 +2167,7 @@
 /* 
  * Checks for sequence id mutating operations. 
  */
-int
+static int
 nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, clientid_t *lockclid)
 {
 	int status;
@@ -2230,6 +2326,8 @@
 		         stp->st_stateid.si_stateownerid,
 		         stp->st_stateid.si_fileid,
 		         stp->st_stateid.si_generation);
+
+	nfsd4_create_clid_dir(sop->so_client);
 out:
 	if (oc->oc_stateowner)
 		nfs4_get_stateowner(oc->oc_stateowner);
@@ -2387,7 +2485,7 @@
 static struct list_head	lock_ownerstr_hashtbl[LOCK_HASH_SIZE];
 static struct list_head lockstateid_hashtbl[STATEID_HASH_SIZE];
 
-struct nfs4_stateid *
+static struct nfs4_stateid *
 find_stateid(stateid_t *stid, int flags)
 {
 	struct nfs4_stateid *local = NULL;
@@ -2419,25 +2517,19 @@
 static struct nfs4_delegation *
 find_delegation_stateid(struct inode *ino, stateid_t *stid)
 {
-	struct nfs4_delegation *dp = NULL;
-	struct nfs4_file *fp = NULL;
-	u32 st_id;
+	struct nfs4_file *fp;
+	struct nfs4_delegation *dl;
 
 	dprintk("NFSD:find_delegation_stateid stateid=(%08x/%08x/%08x/%08x)\n",
                     stid->si_boot, stid->si_stateownerid,
                     stid->si_fileid, stid->si_generation);
 
-	st_id = stid->si_stateownerid;
 	fp = find_file(ino);
-	if (fp) {
-		list_for_each_entry(dp, &fp->fi_del_perfile, dl_del_perfile) {
-			if(dp->dl_stateid.si_stateownerid == st_id) {
-				dprintk("NFSD: find_delegation dp %p\n",dp);
-				return dp;
-			}
-		}
-	}
-	return NULL;
+	if (!fp)
+		return NULL;
+	dl = find_delegation_file(fp, stid);
+	put_nfs4_file(fp);
+	return dl;
 }
 
 /*
@@ -2457,7 +2549,7 @@
 		lock->fl_end = OFFSET_MAX;
 }
 
-int
+static int
 nfs4_verify_lock_stateowner(struct nfs4_stateowner *sop, unsigned int hashval)
 {
 	struct nfs4_stateowner *local = NULL;
@@ -2498,22 +2590,6 @@
 }
 
 static struct nfs4_stateowner *
-find_lockstateowner(struct xdr_netobj *owner, clientid_t *clid)
-{
-	struct nfs4_stateowner *local = NULL;
-	int i;
-
-	for (i = 0; i < LOCK_HASH_SIZE; i++) {
-		list_for_each_entry(local, &lock_ownerid_hashtbl[i], so_idhash) {
-			if (!cmp_owner_str(local, owner, clid))
-				continue;
-			return local;
-		}
-	}
-	return NULL;
-}
-
-static struct nfs4_stateowner *
 find_lockstateowner_str(struct inode *inode, clientid_t *clid,
 		struct xdr_netobj *owner)
 {
@@ -2548,13 +2624,13 @@
 	INIT_LIST_HEAD(&sop->so_idhash);
 	INIT_LIST_HEAD(&sop->so_strhash);
 	INIT_LIST_HEAD(&sop->so_perclient);
-	INIT_LIST_HEAD(&sop->so_perfilestate);
-	INIT_LIST_HEAD(&sop->so_perlockowner);
+	INIT_LIST_HEAD(&sop->so_stateids);
+	INIT_LIST_HEAD(&sop->so_perstateid);
 	INIT_LIST_HEAD(&sop->so_close_lru); /* not used */
 	sop->so_time = 0;
 	list_add(&sop->so_idhash, &lock_ownerid_hashtbl[idhashval]);
 	list_add(&sop->so_strhash, &lock_ownerstr_hashtbl[strhashval]);
-	list_add(&sop->so_perlockowner, &open_stp->st_perlockowner);
+	list_add(&sop->so_perstateid, &open_stp->st_lockowners);
 	sop->so_is_open_owner = 0;
 	sop->so_id = current_ownerid++;
 	sop->so_client = clp;
@@ -2567,24 +2643,24 @@
 	return sop;
 }
 
-struct nfs4_stateid *
+static struct nfs4_stateid *
 alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struct nfs4_stateid *open_stp)
 {
 	struct nfs4_stateid *stp;
 	unsigned int hashval = stateid_hashval(sop->so_id, fp->fi_id);
 
-	if ((stp = kmalloc(sizeof(struct nfs4_stateid), 
-					GFP_KERNEL)) == NULL)
+	stp = nfs4_alloc_stateid();
+	if (stp == NULL)
 		goto out;
 	INIT_LIST_HEAD(&stp->st_hash);
 	INIT_LIST_HEAD(&stp->st_perfile);
-	INIT_LIST_HEAD(&stp->st_perfilestate);
-	INIT_LIST_HEAD(&stp->st_perlockowner); /* not used */
+	INIT_LIST_HEAD(&stp->st_perstateowner);
+	INIT_LIST_HEAD(&stp->st_lockowners); /* not used */
 	list_add(&stp->st_hash, &lockstateid_hashtbl[hashval]);
-	list_add(&stp->st_perfile, &fp->fi_perfile);
-	list_add_perfile++;
-	list_add(&stp->st_perfilestate, &sop->so_perfilestate);
+	list_add(&stp->st_perfile, &fp->fi_stateids);
+	list_add(&stp->st_perstateowner, &sop->so_stateids);
 	stp->st_stateowner = sop;
+	get_nfs4_file(fp);
 	stp->st_file = fp;
 	stp->st_stateid.si_boot = boot_time;
 	stp->st_stateid.si_stateownerid = sop->so_id;
@@ -2598,7 +2674,7 @@
 	return stp;
 }
 
-int
+static int
 check_lock_length(u64 offset, u64 length)
 {
 	return ((length == 0)  || ((length != ~(u64)0) &&
@@ -2611,7 +2687,7 @@
 int
 nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock)
 {
-	struct nfs4_stateowner *lock_sop = NULL, *open_sop = NULL;
+	struct nfs4_stateowner *open_sop = NULL;
 	struct nfs4_stateid *lock_stp;
 	struct file *filp;
 	struct file_lock file_lock;
@@ -2670,16 +2746,9 @@
 		strhashval = lock_ownerstr_hashval(fp->fi_inode, 
 				open_sop->so_client->cl_clientid.cl_id, 
 				&lock->v.new.owner);
-		/* 
-		 * If we already have this lock owner, the client is in 
-		 * error (or our bookeeping is wrong!) 
-		 * for asking for a 'new lock'.
-		 */
-		status = nfserr_bad_stateid;
-		lock_sop = find_lockstateowner(&lock->v.new.owner,
-						&lock->v.new.clientid);
-		if (lock_sop)
-			goto out;
+		/* XXX: Do we need to check for duplicate stateowners on
+		 * the same file, or should they just be allowed (and
+		 * create new stateids)? */
 		status = nfserr_resource;
 		if (!(lock->lk_stateowner = alloc_init_lock_stateowner(strhashval, open_sop->so_client, open_stp, lock)))
 			goto out;
@@ -2970,8 +3039,11 @@
 nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *rlockowner)
 {
 	clientid_t *clid = &rlockowner->rl_clientid;
-	struct nfs4_stateowner *local = NULL;
+	struct nfs4_stateowner *sop;
+	struct nfs4_stateid *stp;
 	struct xdr_netobj *owner = &rlockowner->rl_owner;
+	struct list_head matches;
+	int i;
 	int status;
 
 	dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n",
@@ -2987,22 +3059,32 @@
 
 	nfs4_lock_state();
 
-	status = nfs_ok;
-	local = find_lockstateowner(owner, clid);
-	if (local) {
-		struct nfs4_stateid *stp;
-
-		/* check for any locks held by any stateid
-		 * associated with the (lock) stateowner */
-		status = nfserr_locks_held;
-		list_for_each_entry(stp, &local->so_perfilestate,
-				st_perfilestate) {
-			if (check_for_locks(stp->st_vfs_file, local))
-				goto out;
+	status = nfserr_locks_held;
+	/* XXX: we're doing a linear search through all the lockowners.
+	 * Yipes!  For now we'll just hope clients aren't really using
+	 * release_lockowner much, but eventually we have to fix these
+	 * data structures. */
+	INIT_LIST_HEAD(&matches);
+	for (i = 0; i < LOCK_HASH_SIZE; i++) {
+		list_for_each_entry(sop, &lock_ownerid_hashtbl[i], so_idhash) {
+			if (!cmp_owner_str(sop, owner, clid))
+				continue;
+			list_for_each_entry(stp, &sop->so_stateids,
+					st_perstateowner) {
+				if (check_for_locks(stp->st_vfs_file, sop))
+					goto out;
+				/* Note: so_perclient unused for lockowners,
+				 * so it's OK to fool with here. */
+				list_add(&sop->so_perclient, &matches);
+			}
 		}
-		/* no locks held by (lock) stateowner */
-		status = nfs_ok;
-		release_stateowner(local);
+	}
+	/* Clients probably won't expect us to return with some (but not all)
+	 * of the lockowner state released; so don't release any until all
+	 * have been checked. */
+	status = nfs_ok;
+	list_for_each_entry(sop, &matches, so_perclient) {
+		release_stateowner(sop);
 	}
 out:
 	nfs4_unlock_state();
@@ -3010,39 +3092,38 @@
 }
 
 static inline struct nfs4_client_reclaim *
-alloc_reclaim(int namelen)
+alloc_reclaim(void)
 {
-	struct nfs4_client_reclaim *crp = NULL;
+	return kmalloc(sizeof(struct nfs4_client_reclaim), GFP_KERNEL);
+}
 
-	crp = kmalloc(sizeof(struct nfs4_client_reclaim), GFP_KERNEL);
-	if (!crp)
-		return NULL;
-	crp->cr_name.data = kmalloc(namelen, GFP_KERNEL);
-	if (!crp->cr_name.data) {
-		kfree(crp);
-		return NULL;
-	}
-	return crp;
+int
+nfs4_has_reclaimed_state(const char *name)
+{
+	unsigned int strhashval = clientstr_hashval(name);
+	struct nfs4_client *clp;
+
+	clp = find_confirmed_client_by_str(name, strhashval);
+	return clp ? 1 : 0;
 }
 
 /*
  * failure => all reset bets are off, nfserr_no_grace...
  */
-static int
-nfs4_client_to_reclaim(char *name, int namlen)
+int
+nfs4_client_to_reclaim(const char *name)
 {
 	unsigned int strhashval;
 	struct nfs4_client_reclaim *crp = NULL;
 
-	dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", namlen, name);
-	crp = alloc_reclaim(namlen);
+	dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", HEXDIR_LEN, name);
+	crp = alloc_reclaim();
 	if (!crp)
 		return 0;
-	strhashval = clientstr_hashval(name, namlen);
+	strhashval = clientstr_hashval(name);
 	INIT_LIST_HEAD(&crp->cr_strhash);
 	list_add(&crp->cr_strhash, &reclaim_str_hashtbl[strhashval]);
-	memcpy(crp->cr_name.data, name, namlen);
-	crp->cr_name.len = namlen;
+	memcpy(crp->cr_recdir, name, HEXDIR_LEN);
 	reclaim_str_hashtbl_size++;
 	return 1;
 }
@@ -3053,13 +3134,11 @@
 	struct nfs4_client_reclaim *crp = NULL;
 	int i;
 
-	BUG_ON(!nfs4_reclaim_init);
 	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
 		while (!list_empty(&reclaim_str_hashtbl[i])) {
 			crp = list_entry(reclaim_str_hashtbl[i].next,
 			                struct nfs4_client_reclaim, cr_strhash);
 			list_del(&crp->cr_strhash);
-			kfree(crp->cr_name.data);
 			kfree(crp);
 			reclaim_str_hashtbl_size--;
 		}
@@ -3069,7 +3148,7 @@
 
 /*
  * called from OPEN, CLAIM_PREVIOUS with a new clientid. */
-struct nfs4_client_reclaim *
+static struct nfs4_client_reclaim *
 nfs4_find_reclaim_client(clientid_t *clid)
 {
 	unsigned int strhashval;
@@ -3082,13 +3161,14 @@
 	if (clp == NULL)
 		return NULL;
 
-	dprintk("NFSD: nfs4_find_reclaim_client for %.*s\n",
-		            clp->cl_name.len, clp->cl_name.data);
+	dprintk("NFSD: nfs4_find_reclaim_client for %.*s with recdir %s\n",
+		            clp->cl_name.len, clp->cl_name.data,
+			    clp->cl_recdir);
 
 	/* find clp->cl_name in reclaim_str_hashtbl */
-	strhashval = clientstr_hashval(clp->cl_name.data, clp->cl_name.len);
+	strhashval = clientstr_hashval(clp->cl_recdir);
 	list_for_each_entry(crp, &reclaim_str_hashtbl[strhashval], cr_strhash) {
-		if (cmp_name(&crp->cr_name, &clp->cl_name)) {
+		if (same_name(crp->cr_recdir, clp->cl_recdir)) {
 			return crp;
 		}
 	}
@@ -3101,30 +3181,16 @@
 int
 nfs4_check_open_reclaim(clientid_t *clid)
 {
-	struct nfs4_client_reclaim *crp;
-
-	if ((crp = nfs4_find_reclaim_client(clid)) == NULL)
-		return nfserr_reclaim_bad;
-	return nfs_ok;
+	return nfs4_find_reclaim_client(clid) ? nfs_ok : nfserr_reclaim_bad;
 }
 
+/* initialization to perform at module load time: */
 
-/* 
- * Start and stop routines
- */
-
-static void
-__nfs4_state_init(void)
+void
+nfs4_state_init(void)
 {
 	int i;
-	time_t grace_time;
 
-	if (!nfs4_reclaim_init) {
-		for (i = 0; i < CLIENT_HASH_SIZE; i++)
-			INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
-		reclaim_str_hashtbl_size = 0;
-		nfs4_reclaim_init = 1;
-	}
 	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
 		INIT_LIST_HEAD(&conf_id_hashtbl[i]);
 		INIT_LIST_HEAD(&conf_str_hashtbl[i]);
@@ -3146,26 +3212,46 @@
 		INIT_LIST_HEAD(&lock_ownerid_hashtbl[i]);
 		INIT_LIST_HEAD(&lock_ownerstr_hashtbl[i]);
 	}
-	memset(&zerostateid, 0, sizeof(stateid_t));
 	memset(&onestateid, ~0, sizeof(stateid_t));
-
 	INIT_LIST_HEAD(&close_lru);
 	INIT_LIST_HEAD(&client_lru);
 	INIT_LIST_HEAD(&del_recall_lru);
-	spin_lock_init(&recall_lock);
+	for (i = 0; i < CLIENT_HASH_SIZE; i++)
+		INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
+	reclaim_str_hashtbl_size = 0;
+}
+
+static void
+nfsd4_load_reboot_recovery_data(void)
+{
+	int status;
+
+	nfs4_lock_state();
+	nfsd4_init_recdir(user_recovery_dirname);
+	status = nfsd4_recdir_load();
+	nfs4_unlock_state();
+	if (status)
+		printk("NFSD: Failure reading reboot recovery data\n");
+}
+
+/* initialization to perform when the nfsd service is started: */
+
+static void
+__nfs4_state_start(void)
+{
+	time_t grace_time;
+
 	boot_time = get_seconds();
-	grace_time = max(old_lease_time, lease_time);
-	if (reclaim_str_hashtbl_size == 0)
-		grace_time = 0;
-	if (grace_time)
-		printk("NFSD: starting %ld-second grace period\n", grace_time);
-	grace_end = boot_time + grace_time;
-	INIT_WORK(&laundromat_work,laundromat_main, NULL);
-	schedule_delayed_work(&laundromat_work, NFSD_LEASE_TIME*HZ);
+	grace_time = max(user_lease_time, lease_time);
+	lease_time = user_lease_time;
+	in_grace = 1;
+	printk("NFSD: starting %ld-second grace period\n", grace_time);
+	laundry_wq = create_singlethread_workqueue("nfsd4");
+	queue_delayed_work(laundry_wq, &laundromat_work, grace_time*HZ);
 }
 
 int
-nfs4_state_init(void)
+nfs4_state_start(void)
 {
 	int status;
 
@@ -3174,7 +3260,8 @@
 	status = nfsd4_init_slabs();
 	if (status)
 		return status;
-	__nfs4_state_init();
+	nfsd4_load_reboot_recovery_data();
+	__nfs4_state_start();
 	nfs4_init = 1;
 	return 0;
 }
@@ -3182,14 +3269,7 @@
 int
 nfs4_in_grace(void)
 {
-	return get_seconds() < grace_end;
-}
-
-void
-set_no_grace(void)
-{
-	printk("NFSD: ERROR in reboot recovery.  State reclaims will fail.\n");
-	grace_end = get_seconds();
+	return in_grace;
 }
 
 time_t
@@ -3236,21 +3316,11 @@
 		unhash_delegation(dp);
 	}
 
-	release_all_files();
 	cancel_delayed_work(&laundromat_work);
-	flush_scheduled_work();
+	flush_workqueue(laundry_wq);
+	destroy_workqueue(laundry_wq);
+	nfsd4_shutdown_recdir();
 	nfs4_init = 0;
-	dprintk("NFSD: list_add_perfile %d list_del_perfile %d\n",
-			list_add_perfile, list_del_perfile);
-	dprintk("NFSD: add_perclient %d del_perclient %d\n",
-			add_perclient, del_perclient);
-	dprintk("NFSD: alloc_file %d free_file %d\n",
-			alloc_file, free_file);
-	dprintk("NFSD: vfsopen %d vfsclose %d\n",
-			vfsopen, vfsclose);
-	dprintk("NFSD: alloc_delegation %d free_delegation %d\n",
-			alloc_delegation, free_delegation);
-
 }
 
 void
@@ -3263,56 +3333,48 @@
 	nfs4_unlock_state();
 }
 
+static void
+nfs4_set_recdir(char *recdir)
+{
+	nfs4_lock_state();
+	strcpy(user_recovery_dirname, recdir);
+	nfs4_unlock_state();
+}
+
+/*
+ * Change the NFSv4 recovery directory to recdir.
+ */
+int
+nfs4_reset_recoverydir(char *recdir)
+{
+	int status;
+	struct nameidata nd;
+
+	status = path_lookup(recdir, LOOKUP_FOLLOW, &nd);
+	if (status)
+		return status;
+	status = -ENOTDIR;
+	if (S_ISDIR(nd.dentry->d_inode->i_mode)) {
+		nfs4_set_recdir(recdir);
+		status = 0;
+	}
+	path_release(&nd);
+	return status;
+}
+
 /*
  * Called when leasetime is changed.
  *
- * if nfsd is not started, simply set the global lease.
- *
- * if nfsd(s) are running, lease change requires nfsv4 state to be reset.
- * e.g: boot_time is reset, existing nfs4_client structs are
- * used to fill reclaim_str_hashtbl, then all state (except for the
- * reclaim_str_hashtbl) is re-initialized.
- *
- * if the old lease time is greater than the new lease time, the grace
- * period needs to be set to the old lease time to allow clients to reclaim
- * their state. XXX - we may want to set the grace period == lease time
- * after an initial grace period == old lease time
- *
- * if an error occurs in this process, the new lease is set, but the server
- * will not honor OPEN or LOCK reclaims, and will return nfserr_no_grace
- * which means OPEN/LOCK/READ/WRITE will fail during grace period.
- *
- * clients will attempt to reset all state with SETCLIENTID/CONFIRM, and
- * OPEN and LOCK reclaims.
+ * The only way the protocol gives us to handle on-the-fly lease changes is to
+ * simulate a reboot.  Instead of doing that, we just wait till the next time
+ * we start to register any changes in lease time.  If the administrator
+ * really wants to change the lease time *now*, they can go ahead and bring
+ * nfsd down and then back up again after changing the lease time.
  */
 void
 nfs4_reset_lease(time_t leasetime)
 {
-	struct nfs4_client *clp;
-	int i;
-
-	printk("NFSD: New leasetime %ld\n",leasetime);
-	if (!nfs4_init)
-		return;
-	nfs4_lock_state();
-	old_lease_time = lease_time;
-	lease_time = leasetime;
-
-	nfs4_release_reclaim();
-
-	/* populate reclaim_str_hashtbl with current confirmed nfs4_clientid */
-	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
-		list_for_each_entry(clp, &conf_id_hashtbl[i], cl_idhash) {
-			if (!nfs4_client_to_reclaim(clp->cl_name.data,
-						clp->cl_name.len)) {
-				nfs4_release_reclaim();
-				goto init_state;
-			}
-		}
-	}
-init_state:
-	__nfs4_state_shutdown();
-	__nfs4_state_init();
-	nfs4_unlock_state();
+	lock_kernel();
+	user_lease_time = leasetime;
+	unlock_kernel();
 }
-
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 36a058a..91fb171 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -136,7 +136,7 @@
 	}					\
 } while (0)
 
-u32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes)
+static u32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes)
 {
 	/* We want more bytes than seem to be available.
 	 * Maybe we need a new page, maybe we have just run out
@@ -190,7 +190,7 @@
 	return 0;
 }
 
-char *savemem(struct nfsd4_compoundargs *argp, u32 *p, int nbytes)
+static char *savemem(struct nfsd4_compoundargs *argp, u32 *p, int nbytes)
 {
 	void *new = NULL;
 	if (p == argp->tmp) {
@@ -1366,7 +1366,10 @@
 	if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) {
 		if ((buflen -= 4) < 0)
 			goto out_resource;
-		WRITE32( NFS4_FH_NOEXPIRE_WITH_OPEN | NFS4_FH_VOL_RENAME );
+		if (exp->ex_flags & NFSEXP_NOSUBTREECHECK)
+			WRITE32(NFS4_FH_VOLATILE_ANY);
+		else
+			WRITE32(NFS4_FH_VOLATILE_ANY|NFS4_FH_VOL_RENAME);
 	}
 	if (bmval0 & FATTR4_WORD0_CHANGE) {
 		/*
@@ -1969,7 +1972,7 @@
 	case NFS4_OPEN_DELEGATE_READ:
 		RESERVE_SPACE(20 + sizeof(stateid_t));
 		WRITEMEM(&open->op_delegate_stateid, sizeof(stateid_t));
-		WRITE32(0);
+		WRITE32(open->op_recall);
 
 		/*
 		 * TODO: ACE's in delegations
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 161afdc..841c562 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -51,6 +51,7 @@
 	NFSD_Fh,
 	NFSD_Threads,
 	NFSD_Leasetime,
+	NFSD_RecoveryDir,
 };
 
 /*
@@ -66,6 +67,7 @@
 static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
 static ssize_t write_threads(struct file *file, char *buf, size_t size);
 static ssize_t write_leasetime(struct file *file, char *buf, size_t size);
+static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
 
 static ssize_t (*write_op[])(struct file *, char *, size_t) = {
 	[NFSD_Svc] = write_svc,
@@ -78,6 +80,7 @@
 	[NFSD_Fh] = write_filehandle,
 	[NFSD_Threads] = write_threads,
 	[NFSD_Leasetime] = write_leasetime,
+	[NFSD_RecoveryDir] = write_recoverydir,
 };
 
 static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
@@ -349,6 +352,25 @@
 	return strlen(buf);
 }
 
+static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
+{
+	char *mesg = buf;
+	char *recdir;
+	int len, status;
+
+	if (size > PATH_MAX || buf[size-1] != '\n')
+		return -EINVAL;
+	buf[size-1] = 0;
+
+	recdir = mesg;
+	len = qword_get(&mesg, recdir, size);
+	if (len <= 0)
+		return -EINVAL;
+
+	status = nfs4_reset_recoverydir(recdir);
+	return strlen(buf);
+}
+
 /*----------------------------------------------------------------------------*/
 /*
  *	populating the filesystem.
@@ -369,6 +391,7 @@
 		[NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR},
 #ifdef CONFIG_NFSD_V4
 		[NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
+		[NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR},
 #endif
 		/* last one */ {""}
 	};
@@ -397,9 +420,8 @@
 	nfsd_cache_init();	/* RPC reply cache */
 	nfsd_export_init();	/* Exports table */
 	nfsd_lockd_init();	/* lockd->nfsd callbacks */
-#ifdef CONFIG_NFSD_V4
+	nfs4_state_init();	/* NFSv4 locking state */
 	nfsd_idmap_init();      /* Name to ID mapping */
-#endif /* CONFIG_NFSD_V4 */
 	if (proc_mkdir("fs/nfs", NULL)) {
 		struct proc_dir_entry *entry;
 		entry = create_proc_entry("fs/nfs/exports", 0, NULL);
@@ -426,9 +448,7 @@
 	remove_proc_entry("fs/nfs", NULL);
 	nfsd_stat_shutdown();
 	nfsd_lockd_shutdown();
-#ifdef CONFIG_NFSD_V4
 	nfsd_idmap_shutdown();
-#endif /* CONFIG_NFSD_V4 */
 	unregister_filesystem(&nfsd_fs_type);
 }
 
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 757f9d2..0aa1b96 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -591,6 +591,7 @@
 		{ nfserr_dropit, -ENOMEM },
 		{ nfserr_badname, -ESRCH },
 		{ nfserr_io, -ETXTBSY },
+		{ nfserr_notsupp, -EOPNOTSUPP },
 		{ -1, -EIO }
 	};
 	int	i;
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 02ded7c..07b9a06 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -31,6 +31,7 @@
 #include <linux/nfsd/stats.h>
 #include <linux/nfsd/cache.h>
 #include <linux/lockd/bind.h>
+#include <linux/nfsacl.h>
 
 #define NFSDDBG_FACILITY	NFSDDBG_SVC
 
@@ -94,7 +95,7 @@
 	error =	nfsd_racache_init(2*nrservs);
 	if (error<0)
 		goto out;
-	error = nfs4_state_init();
+	error = nfs4_state_start();
 	if (error<0)
 		goto out;
 	if (!nfsd_serv) {
@@ -362,6 +363,32 @@
 	return 1;
 }
 
+#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+static struct svc_stat	nfsd_acl_svcstats;
+static struct svc_version *	nfsd_acl_version[] = {
+	[2] = &nfsd_acl_version2,
+	[3] = &nfsd_acl_version3,
+};
+
+#define NFSD_ACL_NRVERS		(sizeof(nfsd_acl_version)/sizeof(nfsd_acl_version[0]))
+static struct svc_program	nfsd_acl_program = {
+	.pg_prog		= NFS_ACL_PROGRAM,
+	.pg_nvers		= NFSD_ACL_NRVERS,
+	.pg_vers		= nfsd_acl_version,
+	.pg_name		= "nfsd",
+	.pg_class		= "nfsd",
+	.pg_stats		= &nfsd_acl_svcstats,
+};
+
+static struct svc_stat	nfsd_acl_svcstats = {
+	.program	= &nfsd_acl_program,
+};
+
+#define nfsd_acl_program_p	&nfsd_acl_program
+#else
+#define nfsd_acl_program_p	NULL
+#endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
+
 extern struct svc_version nfsd_version2, nfsd_version3, nfsd_version4;
 
 static struct svc_version *	nfsd_version[] = {
@@ -376,6 +403,7 @@
 
 #define NFSD_NRVERS		(sizeof(nfsd_version)/sizeof(nfsd_version[0]))
 struct svc_program		nfsd_program = {
+	.pg_next		= nfsd_acl_program_p,
 	.pg_prog		= NFS_PROGRAM,		/* program number */
 	.pg_nvers		= NFSD_NRVERS,		/* nr of entries in nfsd_version */
 	.pg_vers		= nfsd_version,		/* version table */
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 948b082..b45999f 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -49,6 +49,12 @@
 	return p + (NFS_FHSIZE >> 2);
 }
 
+/* Helper function for NFSv2 ACL code */
+u32 *nfs2svc_decode_fh(u32 *p, struct svc_fh *fhp)
+{
+	return decode_fh(p, fhp);
+}
+
 static inline u32 *
 encode_fh(u32 *p, struct svc_fh *fhp)
 {
@@ -190,6 +196,11 @@
 	return p;
 }
 
+/* Helper function for NFSv2 ACL code */
+u32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
+{
+	return encode_fattr(rqstp, p, fhp);
+}
 
 /*
  * XDR decode functions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index e3e9d21..de340ff 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -46,10 +46,10 @@
 #include <linux/nfsd/nfsfh.h>
 #include <linux/quotaops.h>
 #include <linux/dnotify.h>
-#ifdef CONFIG_NFSD_V4
-#include <linux/posix_acl.h>
-#include <linux/posix_acl_xattr.h>
 #include <linux/xattr_acl.h>
+#include <linux/posix_acl.h>
+#ifdef CONFIG_NFSD_V4
+#include <linux/posix_acl_xattr.h>
 #include <linux/xattr.h>
 #include <linux/nfs4.h>
 #include <linux/nfs4_acl.h>
@@ -424,13 +424,13 @@
 		goto out_nfserr;
 
 	if (pacl) {
-		error = set_nfsv4_acl_one(dentry, pacl, XATTR_NAME_ACL_ACCESS);
+		error = set_nfsv4_acl_one(dentry, pacl, POSIX_ACL_XATTR_ACCESS);
 		if (error < 0)
 			goto out_nfserr;
 	}
 
 	if (dpacl) {
-		error = set_nfsv4_acl_one(dentry, dpacl, XATTR_NAME_ACL_DEFAULT);
+		error = set_nfsv4_acl_one(dentry, dpacl, POSIX_ACL_XATTR_DEFAULT);
 		if (error < 0)
 			goto out_nfserr;
 	}
@@ -497,7 +497,7 @@
 	struct posix_acl *pacl = NULL, *dpacl = NULL;
 	unsigned int flags = 0;
 
-	pacl = _get_posix_acl(dentry, XATTR_NAME_ACL_ACCESS);
+	pacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_ACCESS);
 	if (IS_ERR(pacl) && PTR_ERR(pacl) == -ENODATA)
 		pacl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL);
 	if (IS_ERR(pacl)) {
@@ -507,7 +507,7 @@
 	}
 
 	if (S_ISDIR(inode->i_mode)) {
-		dpacl = _get_posix_acl(dentry, XATTR_NAME_ACL_DEFAULT);
+		dpacl = _get_posix_acl(dentry, POSIX_ACL_XATTR_DEFAULT);
 		if (IS_ERR(dpacl) && PTR_ERR(dpacl) == -ENODATA)
 			dpacl = NULL;
 		else if (IS_ERR(dpacl)) {
@@ -1857,3 +1857,107 @@
 	nfsdstats.ra_size = cache_size;
 	return 0;
 }
+
+#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+struct posix_acl *
+nfsd_get_posix_acl(struct svc_fh *fhp, int type)
+{
+	struct inode *inode = fhp->fh_dentry->d_inode;
+	char *name;
+	void *value = NULL;
+	ssize_t size;
+	struct posix_acl *acl;
+
+	if (!IS_POSIXACL(inode) || !inode->i_op || !inode->i_op->getxattr)
+		return ERR_PTR(-EOPNOTSUPP);
+	switch(type) {
+		case ACL_TYPE_ACCESS:
+			name = XATTR_NAME_ACL_ACCESS;
+			break;
+		case ACL_TYPE_DEFAULT:
+			name = XATTR_NAME_ACL_DEFAULT;
+			break;
+		default:
+			return ERR_PTR(-EOPNOTSUPP);
+	}
+
+	size = inode->i_op->getxattr(fhp->fh_dentry, name, NULL, 0);
+
+	if (size < 0) {
+		acl = ERR_PTR(size);
+		goto getout;
+	} else if (size > 0) {
+		value = kmalloc(size, GFP_KERNEL);
+		if (!value) {
+			acl = ERR_PTR(-ENOMEM);
+			goto getout;
+		}
+		size = inode->i_op->getxattr(fhp->fh_dentry, name, value, size);
+		if (size < 0) {
+			acl = ERR_PTR(size);
+			goto getout;
+		}
+	}
+	acl = posix_acl_from_xattr(value, size);
+
+getout:
+	kfree(value);
+	return acl;
+}
+
+int
+nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl)
+{
+	struct inode *inode = fhp->fh_dentry->d_inode;
+	char *name;
+	void *value = NULL;
+	size_t size;
+	int error;
+
+	if (!IS_POSIXACL(inode) || !inode->i_op ||
+	    !inode->i_op->setxattr || !inode->i_op->removexattr)
+		return -EOPNOTSUPP;
+	switch(type) {
+		case ACL_TYPE_ACCESS:
+			name = XATTR_NAME_ACL_ACCESS;
+			break;
+		case ACL_TYPE_DEFAULT:
+			name = XATTR_NAME_ACL_DEFAULT;
+			break;
+		default:
+			return -EOPNOTSUPP;
+	}
+
+	if (acl && acl->a_count) {
+		size = xattr_acl_size(acl->a_count);
+		value = kmalloc(size, GFP_KERNEL);
+		if (!value)
+			return -ENOMEM;
+		size = posix_acl_to_xattr(acl, value, size);
+		if (size < 0) {
+			error = size;
+			goto getout;
+		}
+	} else
+		size = 0;
+
+	if (!fhp->fh_locked)
+		fh_lock(fhp);  /* unlocking is done automatically */
+	if (size)
+		error = inode->i_op->setxattr(fhp->fh_dentry, name,
+					      value, size, 0);
+	else {
+		if (!S_ISDIR(inode->i_mode) && type == ACL_TYPE_DEFAULT)
+			error = 0;
+		else {
+			error = inode->i_op->removexattr(fhp->fh_dentry, name);
+			if (error == -ENODATA)
+				error = 0;
+		}
+	}
+
+getout:
+	kfree(value);
+	return error;
+}
+#endif  /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */
diff --git a/fs/open.c b/fs/open.c
index 963bd81..3f4a428 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -21,6 +21,7 @@
 #include <linux/vfs.h>
 #include <asm/uaccess.h>
 #include <linux/fs.h>
+#include <linux/personality.h>
 #include <linux/pagemap.h>
 #include <linux/syscalls.h>
 
@@ -807,7 +808,9 @@
 
 	/* NB: we're sure to have correct a_ops only after f_op->open */
 	if (f->f_flags & O_DIRECT) {
-		if (!f->f_mapping->a_ops || !f->f_mapping->a_ops->direct_IO) {
+		if (!f->f_mapping->a_ops ||
+		    ((!f->f_mapping->a_ops->direct_IO) &&
+		    (!f->f_mapping->a_ops->get_xip_page))) {
 			fput(f);
 			f = ERR_PTR(-EINVAL);
 		}
@@ -933,31 +936,27 @@
 asmlinkage long sys_open(const char __user * filename, int flags, int mode)
 {
 	char * tmp;
-	int fd, error;
+	int fd;
 
-#if BITS_PER_LONG != 32
-	flags |= O_LARGEFILE;
-#endif
+	if (force_o_largefile())
+		flags |= O_LARGEFILE;
+
 	tmp = getname(filename);
 	fd = PTR_ERR(tmp);
 	if (!IS_ERR(tmp)) {
 		fd = get_unused_fd();
 		if (fd >= 0) {
 			struct file *f = filp_open(tmp, flags, mode);
-			error = PTR_ERR(f);
-			if (IS_ERR(f))
-				goto out_error;
-			fd_install(fd, f);
+			if (IS_ERR(f)) {
+				put_unused_fd(fd);
+				fd = PTR_ERR(f);
+			} else {
+				fd_install(fd, f);
+			}
 		}
-out:
 		putname(tmp);
 	}
 	return fd;
-
-out_error:
-	put_unused_fd(fd);
-	fd = error;
-	goto out;
 }
 EXPORT_SYMBOL_GPL(sys_open);
 
@@ -980,23 +979,15 @@
  */
 int filp_close(struct file *filp, fl_owner_t id)
 {
-	int retval;
-
-	/* Report and clear outstanding errors */
-	retval = filp->f_error;
-	if (retval)
-		filp->f_error = 0;
+	int retval = 0;
 
 	if (!file_count(filp)) {
 		printk(KERN_ERR "VFS: Close: file count is 0\n");
-		return retval;
+		return 0;
 	}
 
-	if (filp->f_op && filp->f_op->flush) {
-		int err = filp->f_op->flush(filp);
-		if (!retval)
-			retval = err;
-	}
+	if (filp->f_op && filp->f_op->flush)
+		retval = filp->f_op->flush(filp);
 
 	dnotify_flush(filp, id);
 	locks_remove_posix(filp, id);
diff --git a/fs/partitions/Makefile b/fs/partitions/Makefile
index 4c83c17..66d5cc2 100644
--- a/fs/partitions/Makefile
+++ b/fs/partitions/Makefile
@@ -17,4 +17,3 @@
 obj-$(CONFIG_ULTRIX_PARTITION) += ultrix.o
 obj-$(CONFIG_IBM_PARTITION) += ibm.o
 obj-$(CONFIG_EFI_PARTITION) += efi.o
-obj-$(CONFIG_NEC98_PARTITION) += nec98.o msdos.o
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 2cab98a..77e178f 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -79,9 +79,6 @@
 #ifdef CONFIG_LDM_PARTITION
 	ldm_partition,		/* this must come before msdos */
 #endif
-#ifdef CONFIG_NEC98_PARTITION
-	nec98_partition,	/* must be come before `msdos_partition' */
-#endif
 #ifdef CONFIG_MSDOS_PARTITION
 	msdos_partition,
 #endif
diff --git a/fs/partitions/check.h b/fs/partitions/check.h
index 43adcc6..17ae8ec 100644
--- a/fs/partitions/check.h
+++ b/fs/partitions/check.h
@@ -30,7 +30,3 @@
 
 extern int warn_no_part;
 
-extern void parse_bsd(struct parsed_partitions *state,
-			struct block_device *bdev, u32 offset, u32 size,
-			int origin, char *flavour, int max_partitions);
-
diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c
index 584a27b..9935d25 100644
--- a/fs/partitions/msdos.c
+++ b/fs/partitions/msdos.c
@@ -202,12 +202,12 @@
 #endif
 }
 
-#if defined(CONFIG_BSD_DISKLABEL) || defined(CONFIG_NEC98_PARTITION)
+#if defined(CONFIG_BSD_DISKLABEL)
 /* 
  * Create devices for BSD partitions listed in a disklabel, under a
  * dos-like partition. See parse_extended() for more information.
  */
-void
+static void
 parse_bsd(struct parsed_partitions *state, struct block_device *bdev,
 		u32 offset, u32 size, int origin, char *flavour,
 		int max_partitions)
diff --git a/fs/proc/Makefile b/fs/proc/Makefile
index 738b9b6..7431d7b 100644
--- a/fs/proc/Makefile
+++ b/fs/proc/Makefile
@@ -11,4 +11,5 @@
 		kmsg.o proc_tty.o proc_misc.o
 
 proc-$(CONFIG_PROC_KCORE)	+= kcore.o
+proc-$(CONFIG_PROC_VMCORE)	+= vmcore.o
 proc-$(CONFIG_PROC_DEVICETREE)	+= proc_devtree.o
diff --git a/fs/proc/base.c b/fs/proc/base.c
index e31903a..ace151f 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -314,7 +314,7 @@
 	     (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
 		goto out;
 	rmb();
-	if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
+	if (task->mm->dumpable != 1 && !capable(CAP_SYS_PTRACE))
 		goto out;
 	if (security_ptrace(current, task))
 		goto out;
@@ -1113,7 +1113,9 @@
 	if (mm)
 		dumpable = mm->dumpable;
 	task_unlock(task);
-	return dumpable;
+	if(dumpable == 1)
+		return 1;
+	return 0;
 }
 
 
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index a60a3b3..a345355 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -44,6 +44,7 @@
 #include <linux/jiffies.h>
 #include <linux/sysrq.h>
 #include <linux/vmalloc.h>
+#include <linux/crash_dump.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
@@ -219,6 +220,19 @@
 	.release	= seq_release,
 };
 
+extern struct seq_operations zoneinfo_op;
+static int zoneinfo_open(struct inode *inode, struct file *file)
+{
+	return seq_open(file, &zoneinfo_op);
+}
+
+static struct file_operations proc_zoneinfo_file_operations = {
+	.open		= zoneinfo_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 static int version_read_proc(char *page, char **start, off_t off,
 				 int count, int *eof, void *data)
 {
@@ -438,7 +452,7 @@
 				 int count, int *eof, void *data)
 {
 	int len = get_chrdev_list(page);
-	len += get_blkdev_list(page+len);
+	len += get_blkdev_list(page+len, len);
 	return proc_calc_metrics(page, start, off, count, eof, len);
 }
 
@@ -589,6 +603,7 @@
 	create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
 	create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations);
 	create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations);
+	create_seq_entry("zoneinfo",S_IRUGO, &proc_zoneinfo_file_operations);
 	create_seq_entry("diskstats", 0, &proc_diskstats_operations);
 #ifdef CONFIG_MODULES
 	create_seq_entry("modules", 0, &proc_modules_operations);
@@ -604,6 +619,11 @@
 				(size_t)high_memory - PAGE_OFFSET + PAGE_SIZE;
 	}
 #endif
+#ifdef CONFIG_PROC_VMCORE
+	proc_vmcore = create_proc_entry("vmcore", S_IRUSR, NULL);
+	if (proc_vmcore)
+		proc_vmcore->proc_fops = &proc_vmcore_operations;
+#endif
 #ifdef CONFIG_MAGIC_SYSRQ
 	entry = create_proc_entry("sysrq-trigger", S_IWUSR, NULL);
 	if (entry)
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
new file mode 100644
index 0000000..3b2e7b6
--- /dev/null
+++ b/fs/proc/vmcore.c
@@ -0,0 +1,669 @@
+/*
+ *	fs/proc/vmcore.c Interface for accessing the crash
+ * 				 dump from the system's previous life.
+ * 	Heavily borrowed from fs/proc/kcore.c
+ *	Created by: Hariprasad Nellitheertha (hari@in.ibm.com)
+ *	Copyright (C) IBM Corporation, 2004. All rights reserved
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/proc_fs.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/elf.h>
+#include <linux/elfcore.h>
+#include <linux/proc_fs.h>
+#include <linux/highmem.h>
+#include <linux/bootmem.h>
+#include <linux/init.h>
+#include <linux/crash_dump.h>
+#include <linux/list.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+/* List representing chunks of contiguous memory areas and their offsets in
+ * vmcore file.
+ */
+static LIST_HEAD(vmcore_list);
+
+/* Stores the pointer to the buffer containing kernel elf core headers. */
+static char *elfcorebuf;
+static size_t elfcorebuf_sz;
+
+/* Total size of vmcore file. */
+static u64 vmcore_size;
+
+struct proc_dir_entry *proc_vmcore = NULL;
+
+/* Reads a page from the oldmem device from given offset. */
+static ssize_t read_from_oldmem(char *buf, size_t count,
+			     loff_t *ppos, int userbuf)
+{
+	unsigned long pfn, offset;
+	size_t nr_bytes;
+	ssize_t read = 0, tmp;
+
+	if (!count)
+		return 0;
+
+	offset = (unsigned long)(*ppos % PAGE_SIZE);
+	pfn = (unsigned long)(*ppos / PAGE_SIZE);
+	if (pfn > saved_max_pfn)
+		return -EINVAL;
+
+	do {
+		if (count > (PAGE_SIZE - offset))
+			nr_bytes = PAGE_SIZE - offset;
+		else
+			nr_bytes = count;
+
+		tmp = copy_oldmem_page(pfn, buf, nr_bytes, offset, userbuf);
+		if (tmp < 0)
+			return tmp;
+		*ppos += nr_bytes;
+		count -= nr_bytes;
+		buf += nr_bytes;
+		read += nr_bytes;
+		++pfn;
+		offset = 0;
+	} while (count);
+
+	return read;
+}
+
+/* Maps vmcore file offset to respective physical address in memroy. */
+static u64 map_offset_to_paddr(loff_t offset, struct list_head *vc_list,
+					struct vmcore **m_ptr)
+{
+	struct vmcore *m;
+	u64 paddr;
+
+	list_for_each_entry(m, vc_list, list) {
+		u64 start, end;
+		start = m->offset;
+		end = m->offset + m->size - 1;
+		if (offset >= start && offset <= end) {
+			paddr = m->paddr + offset - start;
+			*m_ptr = m;
+			return paddr;
+		}
+	}
+	*m_ptr = NULL;
+	return 0;
+}
+
+/* Read from the ELF header and then the crash dump. On error, negative value is
+ * returned otherwise number of bytes read are returned.
+ */
+static ssize_t read_vmcore(struct file *file, char __user *buffer,
+				size_t buflen, loff_t *fpos)
+{
+	ssize_t acc = 0, tmp;
+	size_t tsz, nr_bytes;
+	u64 start;
+	struct vmcore *curr_m = NULL;
+
+	if (buflen == 0 || *fpos >= vmcore_size)
+		return 0;
+
+	/* trim buflen to not go beyond EOF */
+	if (buflen > vmcore_size - *fpos)
+		buflen = vmcore_size - *fpos;
+
+	/* Read ELF core header */
+	if (*fpos < elfcorebuf_sz) {
+		tsz = elfcorebuf_sz - *fpos;
+		if (buflen < tsz)
+			tsz = buflen;
+		if (copy_to_user(buffer, elfcorebuf + *fpos, tsz))
+			return -EFAULT;
+		buflen -= tsz;
+		*fpos += tsz;
+		buffer += tsz;
+		acc += tsz;
+
+		/* leave now if filled buffer already */
+		if (buflen == 0)
+			return acc;
+	}
+
+	start = map_offset_to_paddr(*fpos, &vmcore_list, &curr_m);
+	if (!curr_m)
+        	return -EINVAL;
+	if ((tsz = (PAGE_SIZE - (start & ~PAGE_MASK))) > buflen)
+		tsz = buflen;
+
+	/* Calculate left bytes in current memory segment. */
+	nr_bytes = (curr_m->size - (start - curr_m->paddr));
+	if (tsz > nr_bytes)
+		tsz = nr_bytes;
+
+	while (buflen) {
+		tmp = read_from_oldmem(buffer, tsz, &start, 1);
+		if (tmp < 0)
+			return tmp;
+		buflen -= tsz;
+		*fpos += tsz;
+		buffer += tsz;
+		acc += tsz;
+		if (start >= (curr_m->paddr + curr_m->size)) {
+			if (curr_m->list.next == &vmcore_list)
+				return acc;	/*EOF*/
+			curr_m = list_entry(curr_m->list.next,
+						struct vmcore, list);
+			start = curr_m->paddr;
+		}
+		if ((tsz = (PAGE_SIZE - (start & ~PAGE_MASK))) > buflen)
+			tsz = buflen;
+		/* Calculate left bytes in current memory segment. */
+		nr_bytes = (curr_m->size - (start - curr_m->paddr));
+		if (tsz > nr_bytes)
+			tsz = nr_bytes;
+	}
+	return acc;
+}
+
+static int open_vmcore(struct inode *inode, struct file *filp)
+{
+	return 0;
+}
+
+struct file_operations proc_vmcore_operations = {
+	.read		= read_vmcore,
+	.open		= open_vmcore,
+};
+
+static struct vmcore* __init get_new_element(void)
+{
+	struct vmcore *p;
+
+	p = kmalloc(sizeof(*p), GFP_KERNEL);
+	if (p)
+		memset(p, 0, sizeof(*p));
+	return p;
+}
+
+static u64 __init get_vmcore_size_elf64(char *elfptr)
+{
+	int i;
+	u64 size;
+	Elf64_Ehdr *ehdr_ptr;
+	Elf64_Phdr *phdr_ptr;
+
+	ehdr_ptr = (Elf64_Ehdr *)elfptr;
+	phdr_ptr = (Elf64_Phdr*)(elfptr + sizeof(Elf64_Ehdr));
+	size = sizeof(Elf64_Ehdr) + ((ehdr_ptr->e_phnum) * sizeof(Elf64_Phdr));
+	for (i = 0; i < ehdr_ptr->e_phnum; i++) {
+		size += phdr_ptr->p_memsz;
+		phdr_ptr++;
+	}
+	return size;
+}
+
+static u64 __init get_vmcore_size_elf32(char *elfptr)
+{
+	int i;
+	u64 size;
+	Elf32_Ehdr *ehdr_ptr;
+	Elf32_Phdr *phdr_ptr;
+
+	ehdr_ptr = (Elf32_Ehdr *)elfptr;
+	phdr_ptr = (Elf32_Phdr*)(elfptr + sizeof(Elf32_Ehdr));
+	size = sizeof(Elf32_Ehdr) + ((ehdr_ptr->e_phnum) * sizeof(Elf32_Phdr));
+	for (i = 0; i < ehdr_ptr->e_phnum; i++) {
+		size += phdr_ptr->p_memsz;
+		phdr_ptr++;
+	}
+	return size;
+}
+
+/* Merges all the PT_NOTE headers into one. */
+static int __init merge_note_headers_elf64(char *elfptr, size_t *elfsz,
+						struct list_head *vc_list)
+{
+	int i, nr_ptnote=0, rc=0;
+	char *tmp;
+	Elf64_Ehdr *ehdr_ptr;
+	Elf64_Phdr phdr, *phdr_ptr;
+	Elf64_Nhdr *nhdr_ptr;
+	u64 phdr_sz = 0, note_off;
+
+	ehdr_ptr = (Elf64_Ehdr *)elfptr;
+	phdr_ptr = (Elf64_Phdr*)(elfptr + sizeof(Elf64_Ehdr));
+	for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
+		int j;
+		void *notes_section;
+		struct vmcore *new;
+		u64 offset, max_sz, sz, real_sz = 0;
+		if (phdr_ptr->p_type != PT_NOTE)
+			continue;
+		nr_ptnote++;
+		max_sz = phdr_ptr->p_memsz;
+		offset = phdr_ptr->p_offset;
+		notes_section = kmalloc(max_sz, GFP_KERNEL);
+		if (!notes_section)
+			return -ENOMEM;
+		rc = read_from_oldmem(notes_section, max_sz, &offset, 0);
+		if (rc < 0) {
+			kfree(notes_section);
+			return rc;
+		}
+		nhdr_ptr = notes_section;
+		for (j = 0; j < max_sz; j += sz) {
+			if (nhdr_ptr->n_namesz == 0)
+				break;
+			sz = sizeof(Elf64_Nhdr) +
+				((nhdr_ptr->n_namesz + 3) & ~3) +
+				((nhdr_ptr->n_descsz + 3) & ~3);
+			real_sz += sz;
+			nhdr_ptr = (Elf64_Nhdr*)((char*)nhdr_ptr + sz);
+		}
+
+		/* Add this contiguous chunk of notes section to vmcore list.*/
+		new = get_new_element();
+		if (!new) {
+			kfree(notes_section);
+			return -ENOMEM;
+		}
+		new->paddr = phdr_ptr->p_offset;
+		new->size = real_sz;
+		list_add_tail(&new->list, vc_list);
+		phdr_sz += real_sz;
+		kfree(notes_section);
+	}
+
+	/* Prepare merged PT_NOTE program header. */
+	phdr.p_type    = PT_NOTE;
+	phdr.p_flags   = 0;
+	note_off = sizeof(Elf64_Ehdr) +
+			(ehdr_ptr->e_phnum - nr_ptnote +1) * sizeof(Elf64_Phdr);
+	phdr.p_offset  = note_off;
+	phdr.p_vaddr   = phdr.p_paddr = 0;
+	phdr.p_filesz  = phdr.p_memsz = phdr_sz;
+	phdr.p_align   = 0;
+
+	/* Add merged PT_NOTE program header*/
+	tmp = elfptr + sizeof(Elf64_Ehdr);
+	memcpy(tmp, &phdr, sizeof(phdr));
+	tmp += sizeof(phdr);
+
+	/* Remove unwanted PT_NOTE program headers. */
+	i = (nr_ptnote - 1) * sizeof(Elf64_Phdr);
+	*elfsz = *elfsz - i;
+	memmove(tmp, tmp+i, ((*elfsz)-sizeof(Elf64_Ehdr)-sizeof(Elf64_Phdr)));
+
+	/* Modify e_phnum to reflect merged headers. */
+	ehdr_ptr->e_phnum = ehdr_ptr->e_phnum - nr_ptnote + 1;
+
+	return 0;
+}
+
+/* Merges all the PT_NOTE headers into one. */
+static int __init merge_note_headers_elf32(char *elfptr, size_t *elfsz,
+						struct list_head *vc_list)
+{
+	int i, nr_ptnote=0, rc=0;
+	char *tmp;
+	Elf32_Ehdr *ehdr_ptr;
+	Elf32_Phdr phdr, *phdr_ptr;
+	Elf32_Nhdr *nhdr_ptr;
+	u64 phdr_sz = 0, note_off;
+
+	ehdr_ptr = (Elf32_Ehdr *)elfptr;
+	phdr_ptr = (Elf32_Phdr*)(elfptr + sizeof(Elf32_Ehdr));
+	for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
+		int j;
+		void *notes_section;
+		struct vmcore *new;
+		u64 offset, max_sz, sz, real_sz = 0;
+		if (phdr_ptr->p_type != PT_NOTE)
+			continue;
+		nr_ptnote++;
+		max_sz = phdr_ptr->p_memsz;
+		offset = phdr_ptr->p_offset;
+		notes_section = kmalloc(max_sz, GFP_KERNEL);
+		if (!notes_section)
+			return -ENOMEM;
+		rc = read_from_oldmem(notes_section, max_sz, &offset, 0);
+		if (rc < 0) {
+			kfree(notes_section);
+			return rc;
+		}
+		nhdr_ptr = notes_section;
+		for (j = 0; j < max_sz; j += sz) {
+			if (nhdr_ptr->n_namesz == 0)
+				break;
+			sz = sizeof(Elf32_Nhdr) +
+				((nhdr_ptr->n_namesz + 3) & ~3) +
+				((nhdr_ptr->n_descsz + 3) & ~3);
+			real_sz += sz;
+			nhdr_ptr = (Elf32_Nhdr*)((char*)nhdr_ptr + sz);
+		}
+
+		/* Add this contiguous chunk of notes section to vmcore list.*/
+		new = get_new_element();
+		if (!new) {
+			kfree(notes_section);
+			return -ENOMEM;
+		}
+		new->paddr = phdr_ptr->p_offset;
+		new->size = real_sz;
+		list_add_tail(&new->list, vc_list);
+		phdr_sz += real_sz;
+		kfree(notes_section);
+	}
+
+	/* Prepare merged PT_NOTE program header. */
+	phdr.p_type    = PT_NOTE;
+	phdr.p_flags   = 0;
+	note_off = sizeof(Elf32_Ehdr) +
+			(ehdr_ptr->e_phnum - nr_ptnote +1) * sizeof(Elf32_Phdr);
+	phdr.p_offset  = note_off;
+	phdr.p_vaddr   = phdr.p_paddr = 0;
+	phdr.p_filesz  = phdr.p_memsz = phdr_sz;
+	phdr.p_align   = 0;
+
+	/* Add merged PT_NOTE program header*/
+	tmp = elfptr + sizeof(Elf32_Ehdr);
+	memcpy(tmp, &phdr, sizeof(phdr));
+	tmp += sizeof(phdr);
+
+	/* Remove unwanted PT_NOTE program headers. */
+	i = (nr_ptnote - 1) * sizeof(Elf32_Phdr);
+	*elfsz = *elfsz - i;
+	memmove(tmp, tmp+i, ((*elfsz)-sizeof(Elf32_Ehdr)-sizeof(Elf32_Phdr)));
+
+	/* Modify e_phnum to reflect merged headers. */
+	ehdr_ptr->e_phnum = ehdr_ptr->e_phnum - nr_ptnote + 1;
+
+	return 0;
+}
+
+/* Add memory chunks represented by program headers to vmcore list. Also update
+ * the new offset fields of exported program headers. */
+static int __init process_ptload_program_headers_elf64(char *elfptr,
+						size_t elfsz,
+						struct list_head *vc_list)
+{
+	int i;
+	Elf64_Ehdr *ehdr_ptr;
+	Elf64_Phdr *phdr_ptr;
+	loff_t vmcore_off;
+	struct vmcore *new;
+
+	ehdr_ptr = (Elf64_Ehdr *)elfptr;
+	phdr_ptr = (Elf64_Phdr*)(elfptr + sizeof(Elf64_Ehdr)); /* PT_NOTE hdr */
+
+	/* First program header is PT_NOTE header. */
+	vmcore_off = sizeof(Elf64_Ehdr) +
+			(ehdr_ptr->e_phnum) * sizeof(Elf64_Phdr) +
+			phdr_ptr->p_memsz; /* Note sections */
+
+	for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
+		if (phdr_ptr->p_type != PT_LOAD)
+			continue;
+
+		/* Add this contiguous chunk of memory to vmcore list.*/
+		new = get_new_element();
+		if (!new)
+			return -ENOMEM;
+		new->paddr = phdr_ptr->p_offset;
+		new->size = phdr_ptr->p_memsz;
+		list_add_tail(&new->list, vc_list);
+
+		/* Update the program header offset. */
+		phdr_ptr->p_offset = vmcore_off;
+		vmcore_off = vmcore_off + phdr_ptr->p_memsz;
+	}
+	return 0;
+}
+
+static int __init process_ptload_program_headers_elf32(char *elfptr,
+						size_t elfsz,
+						struct list_head *vc_list)
+{
+	int i;
+	Elf32_Ehdr *ehdr_ptr;
+	Elf32_Phdr *phdr_ptr;
+	loff_t vmcore_off;
+	struct vmcore *new;
+
+	ehdr_ptr = (Elf32_Ehdr *)elfptr;
+	phdr_ptr = (Elf32_Phdr*)(elfptr + sizeof(Elf32_Ehdr)); /* PT_NOTE hdr */
+
+	/* First program header is PT_NOTE header. */
+	vmcore_off = sizeof(Elf32_Ehdr) +
+			(ehdr_ptr->e_phnum) * sizeof(Elf32_Phdr) +
+			phdr_ptr->p_memsz; /* Note sections */
+
+	for (i = 0; i < ehdr_ptr->e_phnum; i++, phdr_ptr++) {
+		if (phdr_ptr->p_type != PT_LOAD)
+			continue;
+
+		/* Add this contiguous chunk of memory to vmcore list.*/
+		new = get_new_element();
+		if (!new)
+			return -ENOMEM;
+		new->paddr = phdr_ptr->p_offset;
+		new->size = phdr_ptr->p_memsz;
+		list_add_tail(&new->list, vc_list);
+
+		/* Update the program header offset */
+		phdr_ptr->p_offset = vmcore_off;
+		vmcore_off = vmcore_off + phdr_ptr->p_memsz;
+	}
+	return 0;
+}
+
+/* Sets offset fields of vmcore elements. */
+static void __init set_vmcore_list_offsets_elf64(char *elfptr,
+						struct list_head *vc_list)
+{
+	loff_t vmcore_off;
+	Elf64_Ehdr *ehdr_ptr;
+	struct vmcore *m;
+
+	ehdr_ptr = (Elf64_Ehdr *)elfptr;
+
+	/* Skip Elf header and program headers. */
+	vmcore_off = sizeof(Elf64_Ehdr) +
+			(ehdr_ptr->e_phnum) * sizeof(Elf64_Phdr);
+
+	list_for_each_entry(m, vc_list, list) {
+		m->offset = vmcore_off;
+		vmcore_off += m->size;
+	}
+}
+
+/* Sets offset fields of vmcore elements. */
+static void __init set_vmcore_list_offsets_elf32(char *elfptr,
+						struct list_head *vc_list)
+{
+	loff_t vmcore_off;
+	Elf32_Ehdr *ehdr_ptr;
+	struct vmcore *m;
+
+	ehdr_ptr = (Elf32_Ehdr *)elfptr;
+
+	/* Skip Elf header and program headers. */
+	vmcore_off = sizeof(Elf32_Ehdr) +
+			(ehdr_ptr->e_phnum) * sizeof(Elf32_Phdr);
+
+	list_for_each_entry(m, vc_list, list) {
+		m->offset = vmcore_off;
+		vmcore_off += m->size;
+	}
+}
+
+static int __init parse_crash_elf64_headers(void)
+{
+	int rc=0;
+	Elf64_Ehdr ehdr;
+	u64 addr;
+
+	addr = elfcorehdr_addr;
+
+	/* Read Elf header */
+	rc = read_from_oldmem((char*)&ehdr, sizeof(Elf64_Ehdr), &addr, 0);
+	if (rc < 0)
+		return rc;
+
+	/* Do some basic Verification. */
+	if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
+		(ehdr.e_type != ET_CORE) ||
+		!elf_check_arch(&ehdr) ||
+		ehdr.e_ident[EI_CLASS] != ELFCLASS64 ||
+		ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
+		ehdr.e_version != EV_CURRENT ||
+		ehdr.e_ehsize != sizeof(Elf64_Ehdr) ||
+		ehdr.e_phentsize != sizeof(Elf64_Phdr) ||
+		ehdr.e_phnum == 0) {
+		printk(KERN_WARNING "Warning: Core image elf header is not"
+					"sane\n");
+		return -EINVAL;
+	}
+
+	/* Read in all elf headers. */
+	elfcorebuf_sz = sizeof(Elf64_Ehdr) + ehdr.e_phnum * sizeof(Elf64_Phdr);
+	elfcorebuf = kmalloc(elfcorebuf_sz, GFP_KERNEL);
+	if (!elfcorebuf)
+		return -ENOMEM;
+	addr = elfcorehdr_addr;
+	rc = read_from_oldmem(elfcorebuf, elfcorebuf_sz, &addr, 0);
+	if (rc < 0) {
+		kfree(elfcorebuf);
+		return rc;
+	}
+
+	/* Merge all PT_NOTE headers into one. */
+	rc = merge_note_headers_elf64(elfcorebuf, &elfcorebuf_sz, &vmcore_list);
+	if (rc) {
+		kfree(elfcorebuf);
+		return rc;
+	}
+	rc = process_ptload_program_headers_elf64(elfcorebuf, elfcorebuf_sz,
+							&vmcore_list);
+	if (rc) {
+		kfree(elfcorebuf);
+		return rc;
+	}
+	set_vmcore_list_offsets_elf64(elfcorebuf, &vmcore_list);
+	return 0;
+}
+
+static int __init parse_crash_elf32_headers(void)
+{
+	int rc=0;
+	Elf32_Ehdr ehdr;
+	u64 addr;
+
+	addr = elfcorehdr_addr;
+
+	/* Read Elf header */
+	rc = read_from_oldmem((char*)&ehdr, sizeof(Elf32_Ehdr), &addr, 0);
+	if (rc < 0)
+		return rc;
+
+	/* Do some basic Verification. */
+	if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
+		(ehdr.e_type != ET_CORE) ||
+		!elf_check_arch(&ehdr) ||
+		ehdr.e_ident[EI_CLASS] != ELFCLASS32||
+		ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
+		ehdr.e_version != EV_CURRENT ||
+		ehdr.e_ehsize != sizeof(Elf32_Ehdr) ||
+		ehdr.e_phentsize != sizeof(Elf32_Phdr) ||
+		ehdr.e_phnum == 0) {
+		printk(KERN_WARNING "Warning: Core image elf header is not"
+					"sane\n");
+		return -EINVAL;
+	}
+
+	/* Read in all elf headers. */
+	elfcorebuf_sz = sizeof(Elf32_Ehdr) + ehdr.e_phnum * sizeof(Elf32_Phdr);
+	elfcorebuf = kmalloc(elfcorebuf_sz, GFP_KERNEL);
+	if (!elfcorebuf)
+		return -ENOMEM;
+	addr = elfcorehdr_addr;
+	rc = read_from_oldmem(elfcorebuf, elfcorebuf_sz, &addr, 0);
+	if (rc < 0) {
+		kfree(elfcorebuf);
+		return rc;
+	}
+
+	/* Merge all PT_NOTE headers into one. */
+	rc = merge_note_headers_elf32(elfcorebuf, &elfcorebuf_sz, &vmcore_list);
+	if (rc) {
+		kfree(elfcorebuf);
+		return rc;
+	}
+	rc = process_ptload_program_headers_elf32(elfcorebuf, elfcorebuf_sz,
+								&vmcore_list);
+	if (rc) {
+		kfree(elfcorebuf);
+		return rc;
+	}
+	set_vmcore_list_offsets_elf32(elfcorebuf, &vmcore_list);
+	return 0;
+}
+
+static int __init parse_crash_elf_headers(void)
+{
+	unsigned char e_ident[EI_NIDENT];
+	u64 addr;
+	int rc=0;
+
+	addr = elfcorehdr_addr;
+	rc = read_from_oldmem(e_ident, EI_NIDENT, &addr, 0);
+	if (rc < 0)
+		return rc;
+	if (memcmp(e_ident, ELFMAG, SELFMAG) != 0) {
+		printk(KERN_WARNING "Warning: Core image elf header"
+					" not found\n");
+		return -EINVAL;
+	}
+
+	if (e_ident[EI_CLASS] == ELFCLASS64) {
+		rc = parse_crash_elf64_headers();
+		if (rc)
+			return rc;
+
+		/* Determine vmcore size. */
+		vmcore_size = get_vmcore_size_elf64(elfcorebuf);
+	} else if (e_ident[EI_CLASS] == ELFCLASS32) {
+		rc = parse_crash_elf32_headers();
+		if (rc)
+			return rc;
+
+		/* Determine vmcore size. */
+		vmcore_size = get_vmcore_size_elf32(elfcorebuf);
+	} else {
+		printk(KERN_WARNING "Warning: Core image elf header is not"
+					" sane\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/* Init function for vmcore module. */
+static int __init vmcore_init(void)
+{
+	int rc = 0;
+
+	/* If elfcorehdr= has been passed in cmdline, then capture the dump.*/
+	if (!(elfcorehdr_addr < ELFCORE_ADDR_MAX))
+		return rc;
+	rc = parse_crash_elf_headers();
+	if (rc) {
+		printk(KERN_WARNING "Kdump: vmcore not initialized\n");
+		return rc;
+	}
+
+	/* Initialize /proc/vmcore size if proc is already up. */
+	if (proc_vmcore)
+		proc_vmcore->size = vmcore_size;
+	return 0;
+}
+module_init(vmcore_init)
diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c
index cd66147..7a8f559 100644
--- a/fs/qnx4/dir.c
+++ b/fs/qnx4/dir.c
@@ -61,7 +61,7 @@
 						ino = blknum * QNX4_INODES_PER_BLOCK + ix - 1;
 					else {
 						le  = (struct qnx4_link_info*)de;
-						ino = ( le->dl_inode_blk - 1 ) *
+						ino = ( le32_to_cpu(le->dl_inode_blk) - 1 ) *
 							QNX4_INODES_PER_BLOCK +
 							le->dl_inode_ndx;
 					}
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index aa92d6b..b79162a 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -236,7 +236,7 @@
 	struct buffer_head *bh = NULL;
 	struct qnx4_xblk *xblk = NULL;
 	struct qnx4_inode_entry *qnx4_inode = qnx4_raw_inode(inode);
-	qnx4_nxtnt_t nxtnt = le16_to_cpu(qnx4_inode->di_num_xtnts);
+	u16 nxtnt = le16_to_cpu(qnx4_inode->di_num_xtnts);
 
 	if ( iblock < le32_to_cpu(qnx4_inode->di_first_xtnt.xtnt_size) ) {
 		// iblock is in the first extent. This is easy.
@@ -372,7 +372,7 @@
 		printk("qnx4: unable to read the superblock\n");
 		goto outnobh;
 	}
-	if ( le32_to_cpu( *(__u32*)bh->b_data ) != QNX4_SUPER_MAGIC ) {
+	if ( le32_to_cpup((__le32*) bh->b_data) != QNX4_SUPER_MAGIC ) {
 		if (!silent)
 			printk("qnx4: wrong fsid in superblock.\n");
 		goto out;
diff --git a/fs/quota.c b/fs/quota.c
index 3f0333a..f5d1cff 100644
--- a/fs/quota.c
+++ b/fs/quota.c
@@ -149,36 +149,6 @@
 	return error;
 }
 
-static struct super_block *get_super_to_sync(int type)
-{
-	struct list_head *head;
-	int cnt, dirty;
-
-restart:
-	spin_lock(&sb_lock);
-	list_for_each(head, &super_blocks) {
-		struct super_block *sb = list_entry(head, struct super_block, s_list);
-
-		/* This test just improves performance so it needn't be reliable... */
-		for (cnt = 0, dirty = 0; cnt < MAXQUOTAS; cnt++)
-			if ((type == cnt || type == -1) && sb_has_quota_enabled(sb, cnt)
-			    && info_any_dirty(&sb_dqopt(sb)->info[cnt]))
-				dirty = 1;
-		if (!dirty)
-			continue;
-		sb->s_count++;
-		spin_unlock(&sb_lock);
-		down_read(&sb->s_umount);
-		if (!sb->s_root) {
-			drop_super(sb);
-			goto restart;
-		}
-		return sb;
-	}
-	spin_unlock(&sb_lock);
-	return NULL;
-}
-
 static void quota_sync_sb(struct super_block *sb, int type)
 {
 	int cnt;
@@ -219,17 +189,35 @@
 
 void sync_dquots(struct super_block *sb, int type)
 {
+	int cnt, dirty;
+
 	if (sb) {
 		if (sb->s_qcop->quota_sync)
 			quota_sync_sb(sb, type);
+		return;
 	}
-	else {
-		while ((sb = get_super_to_sync(type)) != NULL) {
-			if (sb->s_qcop->quota_sync)
-				quota_sync_sb(sb, type);
-			drop_super(sb);
-		}
+
+	spin_lock(&sb_lock);
+restart:
+	list_for_each_entry(sb, &super_blocks, s_list) {
+		/* This test just improves performance so it needn't be reliable... */
+		for (cnt = 0, dirty = 0; cnt < MAXQUOTAS; cnt++)
+			if ((type == cnt || type == -1) && sb_has_quota_enabled(sb, cnt)
+			    && info_any_dirty(&sb_dqopt(sb)->info[cnt]))
+				dirty = 1;
+		if (!dirty)
+			continue;
+		sb->s_count++;
+		spin_unlock(&sb_lock);
+		down_read(&sb->s_umount);
+		if (sb->s_root && sb->s_qcop->quota_sync)
+			quota_sync_sb(sb, type);
+		up_read(&sb->s_umount);
+		spin_lock(&sb_lock);
+		if (__put_super_and_need_restart(sb))
+			goto restart;
 	}
+	spin_unlock(&sb_lock);
 }
 
 /* Copy parameters and call proper function */
diff --git a/fs/read_write.c b/fs/read_write.c
index c4c2bee..9292f5f 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -203,6 +203,16 @@
 	return -EINVAL;
 }
 
+static void wait_on_retry_sync_kiocb(struct kiocb *iocb)
+{
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	if (!kiocbIsKicked(iocb))
+		schedule();
+	else
+		kiocbClearKicked(iocb);
+	__set_current_state(TASK_RUNNING);
+}
+
 ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
 {
 	struct kiocb kiocb;
@@ -210,7 +220,10 @@
 
 	init_sync_kiocb(&kiocb, filp);
 	kiocb.ki_pos = *ppos;
-	ret = filp->f_op->aio_read(&kiocb, buf, len, kiocb.ki_pos);
+	while (-EIOCBRETRY ==
+		(ret = filp->f_op->aio_read(&kiocb, buf, len, kiocb.ki_pos)))
+		wait_on_retry_sync_kiocb(&kiocb);
+
 	if (-EIOCBQUEUED == ret)
 		ret = wait_on_sync_kiocb(&kiocb);
 	*ppos = kiocb.ki_pos;
@@ -258,7 +271,10 @@
 
 	init_sync_kiocb(&kiocb, filp);
 	kiocb.ki_pos = *ppos;
-	ret = filp->f_op->aio_write(&kiocb, buf, len, kiocb.ki_pos);
+	while (-EIOCBRETRY ==
+	       (ret = filp->f_op->aio_write(&kiocb, buf, len, kiocb.ki_pos)))
+		wait_on_retry_sync_kiocb(&kiocb);
+
 	if (-EIOCBQUEUED == ret)
 		ret = wait_on_sync_kiocb(&kiocb);
 	*ppos = kiocb.ki_pos;
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index 2230aff..12e9120 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -201,7 +201,7 @@
     /* If we came here, it means we absolutely need to open a transaction,
        since we need to allocate some blocks */
     reiserfs_write_lock(inode->i_sb); // Journaling stuff and we need that.
-    res = journal_begin(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS); // Wish I know if this number enough
+    res = journal_begin(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb)); // Wish I know if this number enough
     if (res)
         goto error_exit;
     reiserfs_update_inode_transaction(inode) ;
@@ -576,7 +576,7 @@
         int err;
         // update any changes we made to blk count
         reiserfs_update_sd(th, inode);
-        err = journal_end(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS);
+        err = journal_end(th, inode->i_sb, JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb));
         if (err)
             res = err;
     }
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index 2711dff..289d864 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -28,7 +28,7 @@
 void reiserfs_delete_inode (struct inode * inode)
 {
     /* We need blocks for transaction + (user+group) quota update (possibly delete) */
-    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * REISERFS_QUOTA_INIT_BLOCKS;
+    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb);
     struct reiserfs_transaction_handle th ;
   
     reiserfs_write_lock(inode->i_sb);
@@ -254,6 +254,7 @@
     char * p = NULL;
     int chars;
     int ret ;
+    int result ;
     int done = 0 ;
     unsigned long offset ;
 
@@ -262,10 +263,13 @@
 		  (loff_t)block * inode->i_sb->s_blocksize + 1, TYPE_ANY, 3);
 
 research:
-    if (search_for_position_by_key (inode->i_sb, &key, &path) != POSITION_FOUND) {
+    result = search_for_position_by_key (inode->i_sb, &key, &path) ;
+    if (result != POSITION_FOUND) {
 	pathrelse (&path);
         if (p)
             kunmap(bh_result->b_page) ;
+	if (result == IO_ERROR)
+	    return -EIO;
 	// We do not return -ENOENT if there is a hole but page is uptodate, because it means
 	// That there is some MMAPED data associated with it that is yet to be written to disk.
 	if ((args & GET_BLOCK_NO_HOLE) && !PageUptodate(bh_result->b_page) ) {
@@ -382,8 +386,9 @@
 
 	// update key to look for the next piece
 	set_cpu_key_k_offset (&key, cpu_key_k_offset (&key) + chars);
-	if (search_for_position_by_key (inode->i_sb, &key, &path) != POSITION_FOUND)
-	    // we read something from tail, even if now we got IO_ERROR
+	result = search_for_position_by_key (inode->i_sb, &key, &path);
+	if (result != POSITION_FOUND)
+	    // i/o error most likely
 	    break;
 	bh = get_last_bh (&path);
 	ih = get_ih (&path);
@@ -394,6 +399,10 @@
 
 finished:
     pathrelse (&path);
+
+    if (result == IO_ERROR)
+	return -EIO;
+
     /* this buffer has valid data, but isn't valid for io.  mapping it to
      * block #0 tells the rest of reiserfs it just has a tail in it
      */
@@ -591,7 +600,7 @@
        XXX in practically impossible worst case direct2indirect()
        can incur (much) more than 3 balancings.
        quota update for user, group */
-    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS;
+    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 1 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(inode->i_sb);
     int version;
     int dangle = 1;
     loff_t new_offset = (((loff_t)block) << inode->i_sb->s_blocksize_bits) + 1 ;
@@ -2796,12 +2805,15 @@
 
                 if (!error) {
 		    struct reiserfs_transaction_handle th;
+		    int jbegin_count = 2*(REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb)+REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb))+2;
 
 		    /* (user+group)*(old+new) structure - we count quota info and , inode write (sb, inode) */
-		    journal_begin(&th, inode->i_sb, 4*REISERFS_QUOTA_INIT_BLOCKS+2);
+		    error = journal_begin(&th, inode->i_sb, jbegin_count);
+ 		    if (error)
+ 			goto out;
                     error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0;
 		    if (error) {
-			journal_end(&th, inode->i_sb, 4*REISERFS_QUOTA_INIT_BLOCKS+2);
+			journal_end(&th, inode->i_sb, jbegin_count);
 			goto out;
 		    }
 		    /* Update corresponding info in inode so that everything is in
@@ -2811,7 +2823,7 @@
 		    if (attr->ia_valid & ATTR_GID)
 			inode->i_gid = attr->ia_gid;
 		    mark_inode_dirty(inode);
-		    journal_end(&th, inode->i_sb, 4*REISERFS_QUOTA_INIT_BLOCKS+2);
+		    error = journal_end(&th, inode->i_sb, jbegin_count);
 		}
         }
         if (!error)
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 3072cfd..d1bcf0d 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -645,18 +645,22 @@
 
 static void write_chunk(struct buffer_chunk *chunk) {
     int i;
+    get_fs_excl();
     for (i = 0; i < chunk->nr ; i++) {
 	submit_logged_buffer(chunk->bh[i]) ;
     }
     chunk->nr = 0;
+    put_fs_excl();
 }
 
 static void write_ordered_chunk(struct buffer_chunk *chunk) {
     int i;
+    get_fs_excl();
     for (i = 0; i < chunk->nr ; i++) {
 	submit_ordered_buffer(chunk->bh[i]) ;
     }
     chunk->nr = 0;
+    put_fs_excl();
 }
 
 static int add_to_chunk(struct buffer_chunk *chunk, struct buffer_head *bh,
@@ -918,6 +922,8 @@
     return 0 ;
   }
 
+  get_fs_excl();
+
   /* before we can put our commit blocks on disk, we have to make sure everyone older than
   ** us is on disk too
   */
@@ -1055,6 +1061,7 @@
 
   if (retval)
     reiserfs_abort (s, retval, "Journal write error in %s", __FUNCTION__);
+  put_fs_excl();
   return retval;
 }
 
@@ -1251,6 +1258,8 @@
     return 0 ;
   }
 
+  get_fs_excl();
+
   /* if all the work is already done, get out of here */
   if (atomic_read(&(jl->j_nonzerolen)) <= 0 && 
       atomic_read(&(jl->j_commit_left)) <= 0) {
@@ -1450,6 +1459,7 @@
   put_journal_list(s, jl);
   if (flushall)
     up(&journal->j_flush_sem);
+  put_fs_excl();
   return err ;
 } 
 
@@ -2631,6 +2641,8 @@
   int retval;
 
   reiserfs_check_lock_depth(p_s_sb, "journal_begin") ;
+  if (nblocks > journal->j_trans_max)
+	BUG();
 
   PROC_INFO_INC( p_s_sb, journal.journal_being );
   /* set here for journal_join */
@@ -2717,6 +2729,7 @@
   th->t_trans_id = journal->j_trans_id ;
   unlock_journal(p_s_sb) ;
   INIT_LIST_HEAD (&th->t_list);
+  get_fs_excl();
   return 0 ;
 
 out_fail:
@@ -3524,6 +3537,7 @@
   BUG_ON (th->t_refcount > 1);
   BUG_ON (!th->t_trans_id);
 
+  put_fs_excl();
   current->journal_info = th->t_handle_save;
   reiserfs_check_lock_depth(p_s_sb, "journal end");
   if (journal->j_len == 0) {
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 7d4dc5f..4a33325 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -586,7 +586,7 @@
     int retval;
     struct inode * inode;
     /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
-    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS);
+    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb)+REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
     struct reiserfs_transaction_handle th ;
     int locked;
 
@@ -653,7 +653,7 @@
     struct inode * inode;
     struct reiserfs_transaction_handle th ;
     /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
-    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS);
+    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb)+REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
     int locked;
 
     if (!new_valid_dev(rdev))
@@ -727,7 +727,7 @@
     struct inode * inode;
     struct reiserfs_transaction_handle th ;
     /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
-    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS);
+    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb)+REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb));
     int locked;
 
 #ifdef DISPLACE_NEW_PACKING_LOCALITIES
@@ -829,8 +829,10 @@
 
 
     /* we will be doing 2 balancings and update 2 stat data, we change quotas
-     * of the owner of the directory and of the owner of the parent directory */
-    jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS);
+     * of the owner of the directory and of the owner of the parent directory.
+     * The quota structure is possibly deleted only on last iput => outside
+     * of this transaction */
+    jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
 
     reiserfs_write_lock(dir->i_sb);
     retval = journal_begin(&th, dir->i_sb, jbegin_count) ;
@@ -913,9 +915,10 @@
     inode = dentry->d_inode;
 
     /* in this transaction we can be doing at max two balancings and update
-       two stat datas, we change quotas of the owner of the directory and of
-       the owner of the parent directory */
-    jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS);
+     * two stat datas, we change quotas of the owner of the directory and of
+     * the owner of the parent directory. The quota structure is possibly
+     * deleted only on iput => outside of this transaction */
+    jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 + 4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
 
     reiserfs_write_lock(dir->i_sb);
     retval = journal_begin(&th, dir->i_sb, jbegin_count) ;
@@ -1000,7 +1003,7 @@
     struct reiserfs_transaction_handle th ;
     int mode = S_IFLNK | S_IRWXUGO;
     /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */
-    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS+REISERFS_QUOTA_TRANS_BLOCKS);
+    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(parent_dir->i_sb)+REISERFS_QUOTA_TRANS_BLOCKS(parent_dir->i_sb));
 
     if (!(inode = new_inode(parent_dir->i_sb))) {
 	return -ENOMEM ;
@@ -1076,7 +1079,7 @@
     struct inode *inode = old_dentry->d_inode;
     struct reiserfs_transaction_handle th ;
     /* We need blocks for transaction + update of quotas for the owners of the directory */
-    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * REISERFS_QUOTA_TRANS_BLOCKS;
+    int jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 2 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
 
     reiserfs_write_lock(dir->i_sb);
     if (inode->i_nlink >= REISERFS_LINK_MAX) {
@@ -1196,7 +1199,7 @@
        pointed initially and (5) maybe block containing ".." of
        renamed directory
        quota updates: two parent directories */
-    jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 5 + 4 * REISERFS_QUOTA_TRANS_BLOCKS;
+    jbegin_count = JOURNAL_PER_BALANCE_CNT * 3 + 5 + 4 * REISERFS_QUOTA_TRANS_BLOCKS(old_dir->i_sb);
 
     old_inode = old_dentry->d_inode;
     new_dentry_inode = new_dentry->d_inode;
diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c
index c47f8fd..6315849 100644
--- a/fs/reiserfs/stree.c
+++ b/fs/reiserfs/stree.c
@@ -223,7 +223,7 @@
 const struct reiserfs_key  MIN_KEY = {0, 0, {{0, 0},}};
 
 /* Maximal possible key. It is never in the tree. */
-const struct reiserfs_key  MAX_KEY = {
+static const struct reiserfs_key  MAX_KEY = {
 	__constant_cpu_to_le32(0xffffffff),
 	__constant_cpu_to_le32(0xffffffff),
 	{{__constant_cpu_to_le32(0xffffffff),
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index b35b877..660aefc 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -866,8 +866,9 @@
 	{"jdev",	.arg_required = 'j', .values = NULL},
 	{"nolargeio",	.arg_required = 'w', .values = NULL},
 	{"commit",	.arg_required = 'c', .values = NULL},
-	{"usrquota",},
-	{"grpquota",},
+	{"usrquota",	.setmask = 1<<REISERFS_QUOTA},
+	{"grpquota",	.setmask = 1<<REISERFS_QUOTA},
+	{"noquota",	.clrmask = 1<<REISERFS_QUOTA},
 	{"errors", 	.arg_required = 'e', .values = error_actions},
 	{"usrjquota",	.arg_required = 'u'|(1<<REISERFS_OPT_ALLOWEMPTY), .values = NULL},
 	{"grpjquota",	.arg_required = 'g'|(1<<REISERFS_OPT_ALLOWEMPTY), .values = NULL},
@@ -964,6 +965,7 @@
 		    return 0;
 		}
 		strcpy(REISERFS_SB(s)->s_qf_names[qtype], arg);
+		*mount_options |= 1<<REISERFS_QUOTA;
 	    }
 	    else {
 		if (REISERFS_SB(s)->s_qf_names[qtype]) {
@@ -995,7 +997,13 @@
 	reiserfs_warning(s, "reiserfs_parse_options: journalled quota format not specified.");
 	return 0;
     }
+    /* This checking is not precise wrt the quota type but for our purposes it is sufficient */
+    if (!(*mount_options & (1<<REISERFS_QUOTA)) && sb_any_quota_enabled(s)) {
+	reiserfs_warning(s, "reiserfs_parse_options: quota options must be present when quota is turned on.");
+	return 0;
+    }
 #endif
+
     return 1;
 }
 
@@ -1105,6 +1113,7 @@
   safe_mask |= 1 << REISERFS_ERROR_RO;
   safe_mask |= 1 << REISERFS_ERROR_CONTINUE;
   safe_mask |= 1 << REISERFS_ERROR_PANIC;
+  safe_mask |= 1 << REISERFS_QUOTA;
 
   /* Update the bitmask, taking care to keep
    * the bits we're not allowed to change here */
@@ -1841,13 +1850,18 @@
 static int reiserfs_dquot_initialize(struct inode *inode, int type)
 {
     struct reiserfs_transaction_handle th;
-    int ret;
+    int ret, err;
 
     /* We may create quota structure so we need to reserve enough blocks */
     reiserfs_write_lock(inode->i_sb);
-    journal_begin(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS);
+    ret = journal_begin(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb));
+    if (ret)
+	goto out;
     ret = dquot_initialize(inode, type);
-    journal_end(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS);
+    err = journal_end(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb));
+    if (!ret && err)
+	ret = err;
+out:
     reiserfs_write_unlock(inode->i_sb);
     return ret;
 }
@@ -1855,13 +1869,18 @@
 static int reiserfs_dquot_drop(struct inode *inode)
 {
     struct reiserfs_transaction_handle th;
-    int ret;
+    int ret, err;
 
     /* We may delete quota structure so we need to reserve enough blocks */
     reiserfs_write_lock(inode->i_sb);
-    journal_begin(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS);
+    ret = journal_begin(&th, inode->i_sb, 2*REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb));
+    if (ret)
+ 	goto out;
     ret = dquot_drop(inode);
-    journal_end(&th, inode->i_sb, 2*REISERFS_QUOTA_INIT_BLOCKS);
+    err = journal_end(&th, inode->i_sb, 2*REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb));
+    if (!ret && err)
+	ret = err;
+out:
     reiserfs_write_unlock(inode->i_sb);
     return ret;
 }
@@ -1869,12 +1888,17 @@
 static int reiserfs_write_dquot(struct dquot *dquot)
 {
     struct reiserfs_transaction_handle th;
-    int ret;
+    int ret, err;
 
     reiserfs_write_lock(dquot->dq_sb);
-    journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_TRANS_BLOCKS);
+    ret = journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
+    if (ret)
+	goto out;
     ret = dquot_commit(dquot);
-    journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_TRANS_BLOCKS);
+    err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
+    if (!ret && err)
+	ret = err;
+out:
     reiserfs_write_unlock(dquot->dq_sb);
     return ret;
 }
@@ -1882,12 +1906,17 @@
 static int reiserfs_acquire_dquot(struct dquot *dquot)
 {
     struct reiserfs_transaction_handle th;
-    int ret;
+    int ret, err;
 
     reiserfs_write_lock(dquot->dq_sb);
-    journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS);
+    ret = journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
+    if (ret)
+	goto out;
     ret = dquot_acquire(dquot);
-    journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS);
+    err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
+    if (!ret && err)
+	ret = err;
+out:
     reiserfs_write_unlock(dquot->dq_sb);
     return ret;
 }
@@ -1895,12 +1924,17 @@
 static int reiserfs_release_dquot(struct dquot *dquot)
 {
     struct reiserfs_transaction_handle th;
-    int ret;
+    int ret, err;
 
     reiserfs_write_lock(dquot->dq_sb);
-    journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS);
+    ret = journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
+    if (ret)
+ 	goto out;
     ret = dquot_release(dquot);
-    journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS);
+    err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
+    if (!ret && err)
+	ret = err;
+out:
     reiserfs_write_unlock(dquot->dq_sb);
     return ret;
 }
@@ -1920,39 +1954,29 @@
 static int reiserfs_write_info(struct super_block *sb, int type)
 {
     struct reiserfs_transaction_handle th;
-    int ret;
+    int ret, err;
 
     /* Data block + inode block */
     reiserfs_write_lock(sb);
-    journal_begin(&th, sb, 2);
+    ret = journal_begin(&th, sb, 2);
+    if (ret)
+	goto out;
     ret = dquot_commit_info(sb, type);
-    journal_end(&th, sb, 2);
+    err = journal_end(&th, sb, 2);
+    if (!ret && err)
+	ret = err;
+out:
     reiserfs_write_unlock(sb);
     return ret;
 }
 
 /*
- * Turn on quotas during mount time - we need to find
- * the quota file and such...
+ * Turn on quotas during mount time - we need to find the quota file and such...
  */
 static int reiserfs_quota_on_mount(struct super_block *sb, int type)
 {
-    int err;
-    struct dentry *dentry;
-    struct qstr name = { .name = REISERFS_SB(sb)->s_qf_names[type],
-                         .hash = 0,
-                         .len = strlen(REISERFS_SB(sb)->s_qf_names[type])};
-
-    dentry = lookup_hash(&name, sb->s_root);
-    if (IS_ERR(dentry))
-            return PTR_ERR(dentry);
-    err = vfs_quota_on_mount(type, REISERFS_SB(sb)->s_jquota_fmt, dentry);
-    /* Now invalidate and put the dentry - quota got its own reference
-     * to inode and dentry has at least wrong hash so we had better
-     * throw it away */
-    d_invalidate(dentry);
-    dput(dentry);
-    return err;
+	return vfs_quota_on_mount(sb, REISERFS_SB(sb)->s_qf_names[type],
+			REISERFS_SB(sb)->s_jquota_fmt, type);
 }
 
 /*
@@ -1963,6 +1987,8 @@
     int err;
     struct nameidata nd;
 
+    if (!(REISERFS_SB(sb)->s_mount_opt & (1<<REISERFS_QUOTA)))
+	return -EINVAL;
     err = path_lookup(path, LOOKUP_FOLLOW, &nd);
     if (err)
         return err;
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
index e302071..c312881 100644
--- a/fs/reiserfs/xattr_acl.c
+++ b/fs/reiserfs/xattr_acl.c
@@ -4,7 +4,7 @@
 #include <linux/errno.h>
 #include <linux/pagemap.h>
 #include <linux/xattr.h>
-#include <linux/xattr_acl.h>
+#include <linux/posix_acl_xattr.h>
 #include <linux/reiserfs_xattr.h>
 #include <linux/reiserfs_acl.h>
 #include <asm/uaccess.h>
@@ -192,11 +192,11 @@
 
         switch (type) {
             case ACL_TYPE_ACCESS:
-                name = XATTR_NAME_ACL_ACCESS;
+                name = POSIX_ACL_XATTR_ACCESS;
                 p_acl = &reiserfs_i->i_acl_access;
                 break;
             case ACL_TYPE_DEFAULT:
-                name = XATTR_NAME_ACL_DEFAULT;
+                name = POSIX_ACL_XATTR_DEFAULT;
                 p_acl = &reiserfs_i->i_acl_default;
                 break;
             default:
@@ -260,7 +260,7 @@
 
         switch (type) {
             case ACL_TYPE_ACCESS:
-                name = XATTR_NAME_ACL_ACCESS;
+                name = POSIX_ACL_XATTR_ACCESS;
                 p_acl = &reiserfs_i->i_acl_access;
                 if (acl) {
                     mode_t mode = inode->i_mode;
@@ -275,7 +275,7 @@
                 }
                 break;
             case ACL_TYPE_DEFAULT:
-                name = XATTR_NAME_ACL_DEFAULT;
+                name = POSIX_ACL_XATTR_DEFAULT;
                 p_acl = &reiserfs_i->i_acl_default;
                 if (!S_ISDIR (inode->i_mode))
                     return acl ? -EACCES : 0;
@@ -468,7 +468,7 @@
 posix_acl_access_get(struct inode *inode, const char *name,
 			  void *buffer, size_t size)
 {
-	if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1)
+	if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS)-1)
 		return -EINVAL;
 	return xattr_get_acl(inode, ACL_TYPE_ACCESS, buffer, size);
 }
@@ -477,7 +477,7 @@
 posix_acl_access_set(struct inode *inode, const char *name,
 			  const void *value, size_t size, int flags)
 {
-	if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1)
+	if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS)-1)
 		return -EINVAL;
 	return xattr_set_acl(inode, ACL_TYPE_ACCESS, value, size);
 }
@@ -487,7 +487,7 @@
 {
     struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode);
     struct posix_acl **acl = &reiserfs_i->i_acl_access;
-    if (strlen(name) != sizeof(XATTR_NAME_ACL_ACCESS)-1)
+    if (strlen(name) != sizeof(POSIX_ACL_XATTR_ACCESS)-1)
 	return -EINVAL;
     if (!IS_ERR (*acl) && *acl) {
         posix_acl_release (*acl);
@@ -510,7 +510,7 @@
 }
 
 struct reiserfs_xattr_handler posix_acl_access_handler = {
-	.prefix = XATTR_NAME_ACL_ACCESS,
+	.prefix = POSIX_ACL_XATTR_ACCESS,
 	.get = posix_acl_access_get,
 	.set = posix_acl_access_set,
 	.del = posix_acl_access_del,
@@ -521,7 +521,7 @@
 posix_acl_default_get (struct inode *inode, const char *name,
 			   void *buffer, size_t size)
 {
-	if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1)
+	if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT)-1)
 		return -EINVAL;
 	return xattr_get_acl(inode, ACL_TYPE_DEFAULT, buffer, size);
 }
@@ -530,7 +530,7 @@
 posix_acl_default_set(struct inode *inode, const char *name,
 			   const void *value, size_t size, int flags)
 {
-	if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1)
+	if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT)-1)
 		return -EINVAL;
 	return xattr_set_acl(inode, ACL_TYPE_DEFAULT, value, size);
 }
@@ -540,7 +540,7 @@
 {
     struct reiserfs_inode_info *reiserfs_i = REISERFS_I(inode);
     struct posix_acl **acl = &reiserfs_i->i_acl_default;
-    if (strlen(name) != sizeof(XATTR_NAME_ACL_DEFAULT)-1)
+    if (strlen(name) != sizeof(POSIX_ACL_XATTR_DEFAULT)-1)
 	return -EINVAL;
     if (!IS_ERR (*acl) && *acl) {
         posix_acl_release (*acl);
@@ -563,7 +563,7 @@
 }
 
 struct reiserfs_xattr_handler posix_acl_default_handler = {
-	.prefix = XATTR_NAME_ACL_DEFAULT,
+	.prefix = POSIX_ACL_XATTR_DEFAULT,
 	.get = posix_acl_default_get,
 	.set = posix_acl_default_set,
 	.del = posix_acl_default_del,
diff --git a/fs/super.c b/fs/super.c
index 3a1b8ca..25bc1ec 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -341,20 +341,22 @@
  */
 void sync_supers(void)
 {
-	struct super_block * sb;
-restart:
+	struct super_block *sb;
+
 	spin_lock(&sb_lock);
-	sb = sb_entry(super_blocks.next);
-	while (sb != sb_entry(&super_blocks))
+restart:
+	list_for_each_entry(sb, &super_blocks, s_list) {
 		if (sb->s_dirt) {
 			sb->s_count++;
 			spin_unlock(&sb_lock);
 			down_read(&sb->s_umount);
 			write_super(sb);
-			drop_super(sb);
-			goto restart;
-		} else
-			sb = sb_entry(sb->s_list.next);
+			up_read(&sb->s_umount);
+			spin_lock(&sb_lock);
+			if (__put_super_and_need_restart(sb))
+				goto restart;
+		}
+	}
 	spin_unlock(&sb_lock);
 }
 
@@ -381,20 +383,16 @@
 
 	down(&mutex);		/* Could be down_interruptible */
 	spin_lock(&sb_lock);
-	for (sb = sb_entry(super_blocks.next); sb != sb_entry(&super_blocks);
-			sb = sb_entry(sb->s_list.next)) {
+	list_for_each_entry(sb, &super_blocks, s_list) {
 		if (!sb->s_op->sync_fs)
 			continue;
 		if (sb->s_flags & MS_RDONLY)
 			continue;
 		sb->s_need_sync_fs = 1;
 	}
-	spin_unlock(&sb_lock);
 
 restart:
-	spin_lock(&sb_lock);
-	for (sb = sb_entry(super_blocks.next); sb != sb_entry(&super_blocks);
-			sb = sb_entry(sb->s_list.next)) {
+	list_for_each_entry(sb, &super_blocks, s_list) {
 		if (!sb->s_need_sync_fs)
 			continue;
 		sb->s_need_sync_fs = 0;
@@ -405,8 +403,11 @@
 		down_read(&sb->s_umount);
 		if (sb->s_root && (wait || sb->s_dirt))
 			sb->s_op->sync_fs(sb, wait);
-		drop_super(sb);
-		goto restart;
+		up_read(&sb->s_umount);
+		/* restart only when sb is no longer on the list */
+		spin_lock(&sb_lock);
+		if (__put_super_and_need_restart(sb))
+			goto restart;
 	}
 	spin_unlock(&sb_lock);
 	up(&mutex);
@@ -422,21 +423,25 @@
 
 struct super_block * get_super(struct block_device *bdev)
 {
-	struct list_head *p;
+	struct super_block *sb;
+
 	if (!bdev)
 		return NULL;
-rescan:
+
 	spin_lock(&sb_lock);
-	list_for_each(p, &super_blocks) {
-		struct super_block *s = sb_entry(p);
-		if (s->s_bdev == bdev) {
-			s->s_count++;
+rescan:
+	list_for_each_entry(sb, &super_blocks, s_list) {
+		if (sb->s_bdev == bdev) {
+			sb->s_count++;
 			spin_unlock(&sb_lock);
-			down_read(&s->s_umount);
-			if (s->s_root)
-				return s;
-			drop_super(s);
-			goto rescan;
+			down_read(&sb->s_umount);
+			if (sb->s_root)
+				return sb;
+			up_read(&sb->s_umount);
+			/* restart only when sb is no longer on the list */
+			spin_lock(&sb_lock);
+			if (__put_super_and_need_restart(sb))
+				goto rescan;
 		}
 	}
 	spin_unlock(&sb_lock);
@@ -447,20 +452,22 @@
  
 struct super_block * user_get_super(dev_t dev)
 {
-	struct list_head *p;
+	struct super_block *sb;
 
-rescan:
 	spin_lock(&sb_lock);
-	list_for_each(p, &super_blocks) {
-		struct super_block *s = sb_entry(p);
-		if (s->s_dev ==  dev) {
-			s->s_count++;
+rescan:
+	list_for_each_entry(sb, &super_blocks, s_list) {
+		if (sb->s_dev ==  dev) {
+			sb->s_count++;
 			spin_unlock(&sb_lock);
-			down_read(&s->s_umount);
-			if (s->s_root)
-				return s;
-			drop_super(s);
-			goto rescan;
+			down_read(&sb->s_umount);
+			if (sb->s_root)
+				return sb;
+			up_read(&sb->s_umount);
+			/* restart only when sb is no longer on the list */
+			spin_lock(&sb_lock);
+			if (__put_super_and_need_restart(sb))
+				goto rescan;
 		}
 	}
 	spin_unlock(&sb_lock);
@@ -835,6 +842,7 @@
 	mnt->mnt_parent = mnt;
 	mnt->mnt_namespace = current->namespace;
 	up_write(&sb->s_umount);
+	free_secdata(secdata);
 	put_filesystem(type);
 	return mnt;
 out_sb:
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index d4aaa88..78899ee 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -25,7 +25,7 @@
 	struct kobject * kobj = to_kobj(dentry->d_parent);
 
 	if (!attr->read)
-		return -EINVAL;
+		return -EIO;
 
 	return attr->read(kobj, buffer, off, count);
 }
@@ -71,7 +71,7 @@
 	struct kobject *kobj = to_kobj(dentry->d_parent);
 
 	if (!attr->write)
-		return -EINVAL;
+		return -EIO;
 
 	return attr->write(kobj, buffer, offset, count);
 }
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index fe19821..59734ba 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -8,6 +8,7 @@
 #include <linux/mount.h>
 #include <linux/module.h>
 #include <linux/kobject.h>
+#include <linux/namei.h>
 #include "sysfs.h"
 
 DECLARE_RWSEM(sysfs_rename_sem);
@@ -99,20 +100,21 @@
 	umode_t mode = S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO;
 
 	down(&p->d_inode->i_sem);
-	*d = sysfs_get_dentry(p,n);
+	*d = lookup_one_len(n, p, strlen(n));
 	if (!IS_ERR(*d)) {
-		error = sysfs_create(*d, mode, init_dir);
+		error = sysfs_make_dirent(p->d_fsdata, *d, k, mode, SYSFS_DIR);
 		if (!error) {
-			error = sysfs_make_dirent(p->d_fsdata, *d, k, mode,
-						SYSFS_DIR);
+			error = sysfs_create(*d, mode, init_dir);
 			if (!error) {
 				p->d_inode->i_nlink++;
 				(*d)->d_op = &sysfs_dentry_ops;
 				d_rehash(*d);
 			}
 		}
-		if (error && (error != -EEXIST))
+		if (error && (error != -EEXIST)) {
+			sysfs_put((*d)->d_fsdata);
 			d_drop(*d);
+		}
 		dput(*d);
 	} else
 		error = PTR_ERR(*d);
@@ -171,17 +173,19 @@
                 init = init_file;
         }
 
+	dentry->d_fsdata = sysfs_get(sd);
+	sd->s_dentry = dentry;
 	error = sysfs_create(dentry, (attr->mode & S_IALLUGO) | S_IFREG, init);
-	if (error)
+	if (error) {
+		sysfs_put(sd);
 		return error;
+	}
 
         if (bin_attr) {
 		dentry->d_inode->i_size = bin_attr->size;
 		dentry->d_inode->i_fop = &bin_fops;
 	}
 	dentry->d_op = &sysfs_dentry_ops;
-	dentry->d_fsdata = sysfs_get(sd);
-	sd->s_dentry = dentry;
 	d_rehash(dentry);
 
 	return 0;
@@ -191,13 +195,15 @@
 {
 	int err = 0;
 
+	dentry->d_fsdata = sysfs_get(sd);
+	sd->s_dentry = dentry;
 	err = sysfs_create(dentry, S_IFLNK|S_IRWXUGO, init_symlink);
 	if (!err) {
 		dentry->d_op = &sysfs_dentry_ops;
-		dentry->d_fsdata = sysfs_get(sd);
-		sd->s_dentry = dentry;
 		d_rehash(dentry);
-	}
+	} else
+		sysfs_put(sd);
+
 	return err;
 }
 
@@ -228,6 +234,7 @@
 
 struct inode_operations sysfs_dir_inode_operations = {
 	.lookup		= sysfs_lookup,
+	.setattr	= sysfs_setattr,
 };
 
 static void remove_dir(struct dentry * d)
@@ -309,7 +316,7 @@
 
 	down(&parent->d_inode->i_sem);
 
-	new_dentry = sysfs_get_dentry(parent, new_name);
+	new_dentry = lookup_one_len(new_name, parent, strlen(new_name));
 	if (!IS_ERR(new_dentry)) {
   		if (!new_dentry->d_inode) {
 			error = kobject_set_name(kobj, "%s", new_name);
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index 3642080..d72c1ce 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -5,6 +5,7 @@
 #include <linux/module.h>
 #include <linux/dnotify.h>
 #include <linux/kobject.h>
+#include <linux/namei.h>
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
 
@@ -13,7 +14,7 @@
 #define to_subsys(k) container_of(k,struct subsystem,kset.kobj)
 #define to_sattr(a) container_of(a,struct subsys_attribute,attr)
 
-/**
+/*
  * Subsystem file operations.
  * These operations allow subsystems to have files that can be 
  * read/written. 
@@ -23,7 +24,7 @@
 {
 	struct subsystem * s = to_subsys(kobj);
 	struct subsys_attribute * sattr = to_sattr(attr);
-	ssize_t ret = 0;
+	ssize_t ret = -EIO;
 
 	if (sattr->show)
 		ret = sattr->show(s,page);
@@ -36,7 +37,7 @@
 {
 	struct subsystem * s = to_subsys(kobj);
 	struct subsys_attribute * sattr = to_sattr(attr);
-	ssize_t ret = 0;
+	ssize_t ret = -EIO;
 
 	if (sattr->store)
 		ret = sattr->store(s,page,count);
@@ -182,7 +183,7 @@
 		return -ENOMEM;
 
 	if (count >= PAGE_SIZE)
-		count = PAGE_SIZE - 1;
+		count = PAGE_SIZE;
 	error = copy_from_user(buffer->page,buf,count);
 	buffer->needs_read_fill = 1;
 	return error ? -EFAULT : count;
@@ -191,8 +192,9 @@
 
 /**
  *	flush_write_buffer - push buffer to kobject.
- *	@file:		file pointer.
+ *	@dentry:	dentry to the attribute
  *	@buffer:	data buffer for file.
+ *	@count:		number of bytes
  *
  *	Get the correct pointers for the kobject and the attribute we're
  *	dealing with, then call the store() method for the attribute, 
@@ -400,7 +402,7 @@
 	int res = -ENOENT;
 
 	down(&dir->d_inode->i_sem);
-	victim = sysfs_get_dentry(dir, attr->name);
+	victim = lookup_one_len(attr->name, dir, strlen(attr->name));
 	if (!IS_ERR(victim)) {
 		/* make sure dentry is really there */
 		if (victim->d_inode && 
@@ -443,7 +445,7 @@
 	int res = -ENOENT;
 
 	down(&dir->d_inode->i_sem);
-	victim = sysfs_get_dentry(dir, attr->name);
+	victim = lookup_one_len(attr->name, dir, strlen(attr->name));
 	if (!IS_ERR(victim)) {
 		if (victim->d_inode &&
 		    (victim->d_parent->d_inode == dir->d_inode)) {
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index f11ac5e..122145b 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -11,6 +11,7 @@
 #include <linux/kobject.h>
 #include <linux/module.h>
 #include <linux/dcache.h>
+#include <linux/namei.h>
 #include <linux/err.h>
 #include "sysfs.h"
 
@@ -68,7 +69,8 @@
 	struct dentry * dir;
 
 	if (grp->name)
-		dir = sysfs_get_dentry(kobj->dentry,grp->name);
+		dir = lookup_one_len(grp->name, kobj->dentry,
+				strlen(grp->name));
 	else
 		dir = dget(kobj->dentry);
 
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index aff7b2d..8de13ba 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -26,18 +26,107 @@
 	.capabilities	= BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK,
 };
 
-struct inode * sysfs_new_inode(mode_t mode)
+static struct inode_operations sysfs_inode_operations ={
+	.setattr	= sysfs_setattr,
+};
+
+int sysfs_setattr(struct dentry * dentry, struct iattr * iattr)
+{
+	struct inode * inode = dentry->d_inode;
+	struct sysfs_dirent * sd = dentry->d_fsdata;
+	struct iattr * sd_iattr;
+	unsigned int ia_valid = iattr->ia_valid;
+	int error;
+
+	if (!sd)
+		return -EINVAL;
+
+	sd_iattr = sd->s_iattr;
+
+	error = inode_change_ok(inode, iattr);
+	if (error)
+		return error;
+
+	error = inode_setattr(inode, iattr);
+	if (error)
+		return error;
+
+	if (!sd_iattr) {
+		/* setting attributes for the first time, allocate now */
+		sd_iattr = kmalloc(sizeof(struct iattr), GFP_KERNEL);
+		if (!sd_iattr)
+			return -ENOMEM;
+		/* assign default attributes */
+		memset(sd_iattr, 0, sizeof(struct iattr));
+		sd_iattr->ia_mode = sd->s_mode;
+		sd_iattr->ia_uid = 0;
+		sd_iattr->ia_gid = 0;
+		sd_iattr->ia_atime = sd_iattr->ia_mtime = sd_iattr->ia_ctime = CURRENT_TIME;
+		sd->s_iattr = sd_iattr;
+	}
+
+	/* attributes were changed atleast once in past */
+
+	if (ia_valid & ATTR_UID)
+		sd_iattr->ia_uid = iattr->ia_uid;
+	if (ia_valid & ATTR_GID)
+		sd_iattr->ia_gid = iattr->ia_gid;
+	if (ia_valid & ATTR_ATIME)
+		sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime,
+						inode->i_sb->s_time_gran);
+	if (ia_valid & ATTR_MTIME)
+		sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime,
+						inode->i_sb->s_time_gran);
+	if (ia_valid & ATTR_CTIME)
+		sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime,
+						inode->i_sb->s_time_gran);
+	if (ia_valid & ATTR_MODE) {
+		umode_t mode = iattr->ia_mode;
+
+		if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
+			mode &= ~S_ISGID;
+		sd_iattr->ia_mode = mode;
+	}
+
+	return error;
+}
+
+static inline void set_default_inode_attr(struct inode * inode, mode_t mode)
+{
+	inode->i_mode = mode;
+	inode->i_uid = 0;
+	inode->i_gid = 0;
+	inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+}
+
+static inline void set_inode_attr(struct inode * inode, struct iattr * iattr)
+{
+	inode->i_mode = iattr->ia_mode;
+	inode->i_uid = iattr->ia_uid;
+	inode->i_gid = iattr->ia_gid;
+	inode->i_atime = iattr->ia_atime;
+	inode->i_mtime = iattr->ia_mtime;
+	inode->i_ctime = iattr->ia_ctime;
+}
+
+struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent * sd)
 {
 	struct inode * inode = new_inode(sysfs_sb);
 	if (inode) {
-		inode->i_mode = mode;
-		inode->i_uid = 0;
-		inode->i_gid = 0;
 		inode->i_blksize = PAGE_CACHE_SIZE;
 		inode->i_blocks = 0;
-		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 		inode->i_mapping->a_ops = &sysfs_aops;
 		inode->i_mapping->backing_dev_info = &sysfs_backing_dev_info;
+		inode->i_op = &sysfs_inode_operations;
+
+		if (sd->s_iattr) {
+			/* sysfs_dirent has non-default attributes
+			 * get them for the new inode from persistent copy
+			 * in sysfs_dirent
+			 */
+			set_inode_attr(inode, sd->s_iattr);
+		} else
+			set_default_inode_attr(inode, mode);
 	}
 	return inode;
 }
@@ -48,7 +137,8 @@
 	struct inode * inode = NULL;
 	if (dentry) {
 		if (!dentry->d_inode) {
-			if ((inode = sysfs_new_inode(mode))) {
+			struct sysfs_dirent * sd = dentry->d_fsdata;
+			if ((inode = sysfs_new_inode(mode, sd))) {
 				if (dentry->d_parent && dentry->d_parent->d_inode) {
 					struct inode *p_inode = dentry->d_parent->d_inode;
 					p_inode->i_mtime = p_inode->i_ctime = CURRENT_TIME;
@@ -76,16 +166,6 @@
 	return error;
 }
 
-struct dentry * sysfs_get_dentry(struct dentry * parent, const char * name)
-{
-	struct qstr qstr;
-
-	qstr.name = name;
-	qstr.len = strlen(name);
-	qstr.hash = full_name_hash(name,qstr.len);
-	return lookup_hash(&qstr,parent);
-}
-
 /*
  * Get the name for corresponding element represented by the given sysfs_dirent
  */
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index 5c805bb..f1117e8 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -28,6 +28,7 @@
 	.s_children	= LIST_HEAD_INIT(sysfs_root.s_children),
 	.s_element	= NULL,
 	.s_type		= SYSFS_ROOT,
+	.s_iattr	= NULL,
 };
 
 static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
@@ -42,7 +43,8 @@
 	sb->s_time_gran = 1;
 	sysfs_sb = sb;
 
-	inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO);
+	inode = sysfs_new_inode(S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
+				 &sysfs_root);
 	if (inode) {
 		inode->i_op = &sysfs_dir_inode_operations;
 		inode->i_fop = &sysfs_dir_operations;
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index dfdf701..fae57c8 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -43,7 +43,7 @@
 	}
 }
 
-static int sysfs_add_link(struct dentry * parent, char * name, struct kobject * target)
+static int sysfs_add_link(struct dentry * parent, const char * name, struct kobject * target)
 {
 	struct sysfs_dirent * parent_sd = parent->d_fsdata;
 	struct sysfs_symlink * sl;
@@ -79,7 +79,7 @@
  *	@target:	object we're pointing to.
  *	@name:		name of the symlink.
  */
-int sysfs_create_link(struct kobject * kobj, struct kobject * target, char * name)
+int sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name)
 {
 	struct dentry * dentry = kobj->dentry;
 	int error = 0;
@@ -99,13 +99,13 @@
  *	@name:	name of the symlink to remove.
  */
 
-void sysfs_remove_link(struct kobject * kobj, char * name)
+void sysfs_remove_link(struct kobject * kobj, const char * name)
 {
 	sysfs_hash_and_remove(kobj->dentry,name);
 }
 
 static int sysfs_get_target_path(struct kobject * kobj, struct kobject * target,
-				   char *path)
+				 char *path)
 {
 	char * s;
 	int depth, size;
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index a8a24a0..3f8953e 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -2,12 +2,11 @@
 extern struct vfsmount * sysfs_mount;
 extern kmem_cache_t *sysfs_dir_cachep;
 
-extern struct inode * sysfs_new_inode(mode_t mode);
+extern struct inode * sysfs_new_inode(mode_t mode, struct sysfs_dirent *);
 extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *));
 
 extern int sysfs_make_dirent(struct sysfs_dirent *, struct dentry *, void *,
 				umode_t, int);
-extern struct dentry * sysfs_get_dentry(struct dentry *, const char *);
 
 extern int sysfs_add_file(struct dentry *, const struct attribute *, int);
 extern void sysfs_hash_and_remove(struct dentry * dir, const char * name);
@@ -17,6 +16,7 @@
 
 extern const unsigned char * sysfs_get_name(struct sysfs_dirent *sd);
 extern void sysfs_drop_dentry(struct sysfs_dirent *sd, struct dentry *parent);
+extern int sysfs_setattr(struct dentry *dentry, struct iattr *iattr);
 
 extern struct rw_semaphore sysfs_rename_sem;
 extern struct super_block * sysfs_sb;
@@ -75,6 +75,7 @@
 		kobject_put(sl->target_kobj);
 		kfree(sl);
 	}
+	kfree(sd->s_iattr);
 	kmem_cache_free(sysfs_dir_cachep, sd);
 }
 
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 93ce257..a3a4b5a 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -149,11 +149,12 @@
  */
 STATIC void
 linvfs_unwritten_convert_direct(
-	struct inode	*inode,
+	struct kiocb	*iocb,
 	loff_t		offset,
 	ssize_t		size,
 	void		*private)
 {
+	struct inode	*inode = iocb->ki_filp->f_dentry->d_inode;
 	ASSERT(!private || inode == (struct inode *)private);
 
 	/* private indicates an unwritten extent lay beneath this IO */
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index 997963e..df0cba2 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -61,12 +61,13 @@
  * File wide globals
  */
 
-STATIC kmem_cache_t *pagebuf_cache;
+STATIC kmem_cache_t *pagebuf_zone;
 STATIC kmem_shaker_t pagebuf_shake;
-STATIC int pagebuf_daemon_wakeup(int, unsigned int);
+STATIC int xfsbufd_wakeup(int, unsigned int);
 STATIC void pagebuf_delwri_queue(xfs_buf_t *, int);
-STATIC struct workqueue_struct *pagebuf_logio_workqueue;
-STATIC struct workqueue_struct *pagebuf_dataio_workqueue;
+
+STATIC struct workqueue_struct *xfslogd_workqueue;
+STATIC struct workqueue_struct *xfsdatad_workqueue;
 
 /*
  * Pagebuf debugging
@@ -123,9 +124,9 @@
 
 
 #define pagebuf_allocate(flags) \
-	kmem_zone_alloc(pagebuf_cache, pb_to_km(flags))
+	kmem_zone_alloc(pagebuf_zone, pb_to_km(flags))
 #define pagebuf_deallocate(pb) \
-	kmem_zone_free(pagebuf_cache, (pb));
+	kmem_zone_free(pagebuf_zone, (pb));
 
 /*
  * Page Region interfaces.
@@ -425,7 +426,7 @@
 					__FUNCTION__, gfp_mask);
 
 			XFS_STATS_INC(pb_page_retries);
-			pagebuf_daemon_wakeup(0, gfp_mask);
+			xfsbufd_wakeup(0, gfp_mask);
 			blk_congestion_wait(WRITE, HZ/50);
 			goto retry;
 		}
@@ -1136,8 +1137,8 @@
 	if ((pb->pb_iodone) || (pb->pb_flags & PBF_ASYNC)) {
 		if (schedule) {
 			INIT_WORK(&pb->pb_iodone_work, pagebuf_iodone_work, pb);
-			queue_work(dataio ? pagebuf_dataio_workqueue :
-				pagebuf_logio_workqueue, &pb->pb_iodone_work);
+			queue_work(dataio ? xfsdatad_workqueue :
+				xfslogd_workqueue, &pb->pb_iodone_work);
 		} else {
 			pagebuf_iodone_work(pb);
 		}
@@ -1562,16 +1563,6 @@
 	kmem_free(btp, sizeof(*btp));
 }
 
-void
-xfs_incore_relse(
-	xfs_buftarg_t		*btp,
-	int			delwri_only,
-	int			wait)
-{
-	invalidate_bdev(btp->pbr_bdev, 1);
-	truncate_inode_pages(btp->pbr_mapping, 0LL);
-}
-
 STATIC int
 xfs_setsize_buftarg_flags(
 	xfs_buftarg_t		*btp,
@@ -1742,27 +1733,27 @@
 }
 
 /* Defines for pagebuf daemon */
-STATIC DECLARE_COMPLETION(pagebuf_daemon_done);
-STATIC struct task_struct *pagebuf_daemon_task;
-STATIC int pagebuf_daemon_active;
-STATIC int force_flush;
-STATIC int force_sleep;
+STATIC DECLARE_COMPLETION(xfsbufd_done);
+STATIC struct task_struct *xfsbufd_task;
+STATIC int xfsbufd_active;
+STATIC int xfsbufd_force_flush;
+STATIC int xfsbufd_force_sleep;
 
 STATIC int
-pagebuf_daemon_wakeup(
+xfsbufd_wakeup(
 	int			priority,
 	unsigned int		mask)
 {
-	if (force_sleep)
+	if (xfsbufd_force_sleep)
 		return 0;
-	force_flush = 1;
+	xfsbufd_force_flush = 1;
 	barrier();
-	wake_up_process(pagebuf_daemon_task);
+	wake_up_process(xfsbufd_task);
 	return 0;
 }
 
 STATIC int
-pagebuf_daemon(
+xfsbufd(
 	void			*data)
 {
 	struct list_head	tmp;
@@ -1774,17 +1765,17 @@
 	daemonize("xfsbufd");
 	current->flags |= PF_MEMALLOC;
 
-	pagebuf_daemon_task = current;
-	pagebuf_daemon_active = 1;
+	xfsbufd_task = current;
+	xfsbufd_active = 1;
 	barrier();
 
 	INIT_LIST_HEAD(&tmp);
 	do {
-		if (unlikely(current->flags & PF_FREEZE)) {
-			force_sleep = 1;
-			refrigerator(PF_FREEZE);
+		if (unlikely(freezing(current))) {
+			xfsbufd_force_sleep = 1;
+			refrigerator();
 		} else {
-			force_sleep = 0;
+			xfsbufd_force_sleep = 0;
 		}
 
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -1797,7 +1788,7 @@
 			ASSERT(pb->pb_flags & PBF_DELWRI);
 
 			if (!pagebuf_ispin(pb) && !pagebuf_cond_lock(pb)) {
-				if (!force_flush &&
+				if (!xfsbufd_force_flush &&
 				    time_before(jiffies,
 						pb->pb_queuetime + age)) {
 					pagebuf_unlock(pb);
@@ -1824,10 +1815,10 @@
 		if (as_list_len > 0)
 			purge_addresses();
 
-		force_flush = 0;
-	} while (pagebuf_daemon_active);
+		xfsbufd_force_flush = 0;
+	} while (xfsbufd_active);
 
-	complete_and_exit(&pagebuf_daemon_done, 0);
+	complete_and_exit(&xfsbufd_done, 0);
 }
 
 /*
@@ -1844,8 +1835,8 @@
 	xfs_buf_t		*pb, *n;
 	int			pincount = 0;
 
-	pagebuf_runall_queues(pagebuf_dataio_workqueue);
-	pagebuf_runall_queues(pagebuf_logio_workqueue);
+	pagebuf_runall_queues(xfsdatad_workqueue);
+	pagebuf_runall_queues(xfslogd_workqueue);
 
 	INIT_LIST_HEAD(&tmp);
 	spin_lock(&pbd_delwrite_lock);
@@ -1898,43 +1889,43 @@
 }
 
 STATIC int
-pagebuf_daemon_start(void)
+xfs_buf_daemons_start(void)
 {
-	int		rval;
+	int		error = -ENOMEM;
 
-	pagebuf_logio_workqueue = create_workqueue("xfslogd");
-	if (!pagebuf_logio_workqueue)
-		return -ENOMEM;
+	xfslogd_workqueue = create_workqueue("xfslogd");
+	if (!xfslogd_workqueue)
+		goto out;
 
-	pagebuf_dataio_workqueue = create_workqueue("xfsdatad");
-	if (!pagebuf_dataio_workqueue) {
-		destroy_workqueue(pagebuf_logio_workqueue);
-		return -ENOMEM;
-	}
+	xfsdatad_workqueue = create_workqueue("xfsdatad");
+	if (!xfsdatad_workqueue)
+		goto out_destroy_xfslogd_workqueue;
 
-	rval = kernel_thread(pagebuf_daemon, NULL, CLONE_FS|CLONE_FILES);
-	if (rval < 0) {
-		destroy_workqueue(pagebuf_logio_workqueue);
-		destroy_workqueue(pagebuf_dataio_workqueue);
-	}
+	error = kernel_thread(xfsbufd, NULL, CLONE_FS|CLONE_FILES);
+	if (error < 0)
+		goto out_destroy_xfsdatad_workqueue;
+	return 0;
 
-	return rval;
+ out_destroy_xfsdatad_workqueue:
+	destroy_workqueue(xfsdatad_workqueue);
+ out_destroy_xfslogd_workqueue:
+	destroy_workqueue(xfslogd_workqueue);
+ out:
+	return error;
 }
 
 /*
- * pagebuf_daemon_stop
- *
  * Note: do not mark as __exit, it is called from pagebuf_terminate.
  */
 STATIC void
-pagebuf_daemon_stop(void)
+xfs_buf_daemons_stop(void)
 {
-	pagebuf_daemon_active = 0;
+	xfsbufd_active = 0;
 	barrier();
-	wait_for_completion(&pagebuf_daemon_done);
+	wait_for_completion(&xfsbufd_done);
 
-	destroy_workqueue(pagebuf_logio_workqueue);
-	destroy_workqueue(pagebuf_dataio_workqueue);
+	destroy_workqueue(xfslogd_workqueue);
+	destroy_workqueue(xfsdatad_workqueue);
 }
 
 /*
@@ -1944,27 +1935,37 @@
 int __init
 pagebuf_init(void)
 {
-	pagebuf_cache = kmem_cache_create("xfs_buf_t", sizeof(xfs_buf_t), 0,
-			SLAB_HWCACHE_ALIGN, NULL, NULL);
-	if (pagebuf_cache == NULL) {
-		printk("XFS: couldn't init xfs_buf_t cache\n");
-		pagebuf_terminate();
-		return -ENOMEM;
-	}
+	int		error = -ENOMEM;
+
+	pagebuf_zone = kmem_zone_init(sizeof(xfs_buf_t), "xfs_buf");
+	if (!pagebuf_zone)
+		goto out;
 
 #ifdef PAGEBUF_TRACE
 	pagebuf_trace_buf = ktrace_alloc(PAGEBUF_TRACE_SIZE, KM_SLEEP);
 #endif
 
-	pagebuf_daemon_start();
+	error = xfs_buf_daemons_start();
+	if (error)
+		goto out_free_buf_zone;
 
-	pagebuf_shake = kmem_shake_register(pagebuf_daemon_wakeup);
-	if (pagebuf_shake == NULL) {
-		pagebuf_terminate();
-		return -ENOMEM;
+	pagebuf_shake = kmem_shake_register(xfsbufd_wakeup);
+	if (!pagebuf_shake) {
+		error = -ENOMEM;
+		goto out_stop_daemons;
 	}
 
 	return 0;
+
+ out_stop_daemons:
+	xfs_buf_daemons_stop();
+ out_free_buf_zone:
+#ifdef PAGEBUF_TRACE
+	ktrace_free(pagebuf_trace_buf);
+#endif
+	kmem_zone_destroy(pagebuf_zone);
+ out:
+	return error;
 }
 
 
@@ -1976,12 +1977,12 @@
 void
 pagebuf_terminate(void)
 {
-	pagebuf_daemon_stop();
+	xfs_buf_daemons_stop();
 
 #ifdef PAGEBUF_TRACE
 	ktrace_free(pagebuf_trace_buf);
 #endif
 
-	kmem_zone_destroy(pagebuf_cache);
+	kmem_zone_destroy(pagebuf_zone);
 	kmem_shake_deregister(pagebuf_shake);
 }
diff --git a/fs/xfs/linux-2.6/xfs_buf.h b/fs/xfs/linux-2.6/xfs_buf.h
index 74deed8..3f8f69a 100644
--- a/fs/xfs/linux-2.6/xfs_buf.h
+++ b/fs/xfs/linux-2.6/xfs_buf.h
@@ -576,7 +576,6 @@
 extern void xfs_free_buftarg(xfs_buftarg_t *, int);
 extern void xfs_wait_buftarg(xfs_buftarg_t *);
 extern int xfs_setsize_buftarg(xfs_buftarg_t *, unsigned int, unsigned int);
-extern void xfs_incore_relse(xfs_buftarg_t *, int, int);
 extern int xfs_flush_buftarg(xfs_buftarg_t *, int);
 
 #define xfs_getsize_buftarg(buftarg) \
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index 24fa3b1..f1ce432 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -57,7 +57,9 @@
 #include <linux/smp_lock.h>
 
 static struct vm_operations_struct linvfs_file_vm_ops;
-
+#ifdef CONFIG_XFS_DMAPI
+static struct vm_operations_struct linvfs_dmapi_file_vm_ops;
+#endif
 
 STATIC inline ssize_t
 __linvfs_read(
@@ -388,6 +390,14 @@
 	return -error;
 }
 
+#ifdef CONFIG_XFS_DMAPI
+STATIC void
+linvfs_mmap_close(
+	struct vm_area_struct	*vma)
+{
+	xfs_dm_mm_put(vma);
+}
+#endif /* CONFIG_XFS_DMAPI */
 
 STATIC int
 linvfs_file_mmap(
@@ -399,16 +409,19 @@
 	vattr_t		va = { .va_mask = XFS_AT_UPDATIME };
 	int		error;
 
+	vma->vm_ops = &linvfs_file_vm_ops;
+
 	if (vp->v_vfsp->vfs_flag & VFS_DMI) {
 		xfs_mount_t	*mp = XFS_VFSTOM(vp->v_vfsp);
 
 		error = -XFS_SEND_MMAP(mp, vma, 0);
 		if (error)
 			return error;
+#ifdef CONFIG_XFS_DMAPI
+		vma->vm_ops = &linvfs_dmapi_file_vm_ops;
+#endif
 	}
 
-	vma->vm_ops = &linvfs_file_vm_ops;
-
 	VOP_SETATTR(vp, &va, XFS_AT_UPDATIME, NULL, error);
 	if (!error)
 		vn_revalidate(vp);	/* update Linux inode flags */
@@ -609,7 +622,15 @@
 static struct vm_operations_struct linvfs_file_vm_ops = {
 	.nopage		= filemap_nopage,
 	.populate	= filemap_populate,
+};
+
+#ifdef CONFIG_XFS_DMAPI
+static struct vm_operations_struct linvfs_dmapi_file_vm_ops = {
+	.close		= linvfs_mmap_close,
+	.nopage		= filemap_nopage,
+	.populate	= filemap_populate,
 #ifdef HAVE_VMOP_MPROTECT
 	.mprotect	= linvfs_mprotect,
 #endif
 };
+#endif /* CONFIG_XFS_DMAPI */
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c
index 69809ee..05a447e 100644
--- a/fs/xfs/linux-2.6/xfs_ioctl.c
+++ b/fs/xfs/linux-2.6/xfs_ioctl.c
@@ -1174,7 +1174,8 @@
 
 	switch (cmd) {
 	case XFS_IOC_FSGETXATTR: {
-		va.va_mask = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_NEXTENTS;
+		va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
+			     XFS_AT_NEXTENTS | XFS_AT_PROJID;
 		VOP_GETATTR(vp, &va, 0, NULL, error);
 		if (error)
 			return -error;
@@ -1182,6 +1183,7 @@
 		fa.fsx_xflags	= va.va_xflags;
 		fa.fsx_extsize	= va.va_extsize;
 		fa.fsx_nextents = va.va_nextents;
+		fa.fsx_projid	= va.va_projid;
 
 		if (copy_to_user(arg, &fa, sizeof(fa)))
 			return -XFS_ERROR(EFAULT);
@@ -1196,9 +1198,10 @@
 		if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
 			attr_flags |= ATTR_NONBLOCK;
 
-		va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE;
+		va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | XFS_AT_PROJID;
 		va.va_xflags  = fa.fsx_xflags;
 		va.va_extsize = fa.fsx_extsize;
+		va.va_projid  = fa.fsx_projid;
 
 		VOP_SETATTR(vp, &va, attr_flags, NULL, error);
 		if (!error)
@@ -1207,7 +1210,8 @@
 	}
 
 	case XFS_IOC_FSGETXATTRA: {
-		va.va_mask = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_ANEXTENTS;
+		va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \
+			     XFS_AT_ANEXTENTS | XFS_AT_PROJID;
 		VOP_GETATTR(vp, &va, 0, NULL, error);
 		if (error)
 			return -error;
@@ -1215,6 +1219,7 @@
 		fa.fsx_xflags	= va.va_xflags;
 		fa.fsx_extsize	= va.va_extsize;
 		fa.fsx_nextents = va.va_anextents;
+		fa.fsx_projid	= va.va_projid;
 
 		if (copy_to_user(arg, &fa, sizeof(fa)))
 			return -XFS_ERROR(EFAULT);
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 71bb410..42dc5e4 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -145,10 +145,10 @@
 #define xfs_inherit_nosymlinks	xfs_params.inherit_nosym.val
 #define xfs_rotorstep		xfs_params.rotorstep.val
 
-#ifndef __smp_processor_id
-#define __smp_processor_id()	smp_processor_id()
+#ifndef raw_smp_processor_id
+#define raw_smp_processor_id()	smp_processor_id()
 #endif
-#define current_cpu()		__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)
@@ -230,8 +230,10 @@
  * field (see the QCMD macro in quota.h).  These macros help keep the
  * code portable - they are not visible from the syscall interface.
  */
-#define Q_XSETGQLIM	XQM_CMD(0x8)	/* set groups disk limits */
-#define Q_XGETGQUOTA	XQM_CMD(0x9)	/* get groups disk limits */
+#define Q_XSETGQLIM	XQM_CMD(8)	/* set groups disk limits */
+#define Q_XGETGQUOTA	XQM_CMD(9)	/* get groups disk limits */
+#define Q_XSETPQLIM	XQM_CMD(10)	/* set projects disk limits */
+#define Q_XGETPQUOTA	XQM_CMD(11)	/* get projects disk limits */
 
 /* IRIX uses a dynamic sizing algorithm (ndquot = 200 + numprocs*2) */
 /* we may well need to fine-tune this if it ever becomes an issue.  */
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
index aa9daae..acab58c 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ b/fs/xfs/linux-2.6/xfs_lrw.c
@@ -209,30 +209,6 @@
 	return (-status);
 }
 
-/*
- * xfs_inval_cached_pages
- * 
- * This routine is responsible for keeping direct I/O and buffered I/O
- * somewhat coherent.  From here we make sure that we're at least
- * temporarily holding the inode I/O lock exclusively and then call
- * the page cache to flush and invalidate any cached pages.  If there
- * are no cached pages this routine will be very quick.
- */
-void
-xfs_inval_cached_pages(
-	vnode_t		*vp,
-	xfs_iocore_t	*io,
-	xfs_off_t	offset,
-	int		write,
-	int		relock)
-{
-	if (VN_CACHED(vp)) {
-		xfs_inval_cached_trace(io, offset, -1, ctooff(offtoct(offset)), -1);
-		VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(offset)), -1, FI_REMAPF_LOCKED);
-	}
-
-}
-
 ssize_t			/* bytes read, or (-)  error */
 xfs_read(
 	bhv_desc_t		*bdp,
@@ -304,10 +280,11 @@
 	if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) &&
 	    !(ioflags & IO_INVIS)) {
 		vrwlock_t locktype = VRWLOCK_READ;
+		int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
 
 		ret = -XFS_SEND_DATA(mp, DM_EVENT_READ,
 					BHV_TO_VNODE(bdp), *offset, size,
-					FILP_DELAY_FLAG(file), &locktype);
+					dmflags, &locktype);
 		if (ret) {
 			xfs_iunlock(ip, XFS_IOLOCK_SHARED);
 			goto unlock_isem;
@@ -867,11 +844,15 @@
 	    !(ioflags & IO_INVIS)) {
 
 		xfs_rwunlock(bdp, locktype);
+		if (need_isem)
+			up(&inode->i_sem);
 		error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, vp,
 				DM_RIGHT_NULL, vp, DM_RIGHT_NULL, NULL, NULL,
 				0, 0, 0); /* Delay flag intentionally  unused */
 		if (error)
-			goto out_unlock_isem;
+			goto out_nounlocks;
+		if (need_isem)
+			down(&inode->i_sem);
 		xfs_rwlock(bdp, locktype);
 		pos = xip->i_d.di_size;
 		ret = 0;
@@ -986,6 +967,7 @@
  out_unlock_isem:
 	if (need_isem)
 		up(&inode->i_sem);
+ out_nounlocks:
 	return -error;
 }
 
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
index d723e35..f197a72 100644
--- a/fs/xfs/linux-2.6/xfs_lrw.h
+++ b/fs/xfs/linux-2.6/xfs_lrw.h
@@ -94,8 +94,6 @@
 
 extern int xfs_zero_eof(struct vnode *, struct xfs_iocore *, xfs_off_t,
 				xfs_fsize_t, xfs_fsize_t);
-extern void xfs_inval_cached_pages(struct vnode	*, struct xfs_iocore *,
-				xfs_off_t, int, int);
 extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *,
 				const struct iovec *, unsigned int,
 				loff_t *, int, struct cred *);
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index 455e2b2..f6dd7de 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -483,7 +483,7 @@
 		set_current_state(TASK_INTERRUPTIBLE);
 		timeleft = schedule_timeout(timeleft);
 		/* swsusp */
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 		if (vfsp->vfs_flag & VFS_UMOUNT)
 			break;
 
@@ -590,8 +590,10 @@
 	int		error;
 	int		flags = SYNC_FSDATA;
 
-	if (wait)
-		flags |= SYNC_WAIT;
+	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);
 	sb->s_dirt = 0;
@@ -701,7 +703,8 @@
 	struct vfs		*vfsp = LINVFS_GET_VFS(sb);
 	int			error, getmode;
 
-	getmode = (type == GRPQUOTA) ? Q_XGETGQUOTA : Q_XGETQUOTA;
+	getmode = (type == USRQUOTA) ? Q_XGETQUOTA :
+		 ((type == GRPQUOTA) ? Q_XGETGQUOTA : Q_XGETPQUOTA);
 	VFS_QUOTACTL(vfsp, getmode, id, (caddr_t)fdq, error);
 	return -error;
 }
@@ -716,7 +719,8 @@
 	struct vfs		*vfsp = LINVFS_GET_VFS(sb);
 	int			error, setmode;
 
-	setmode = (type == GRPQUOTA) ? Q_XSETGQLIM : Q_XSETQLIM;
+	setmode = (type == USRQUOTA) ? Q_XSETQLIM :
+		 ((type == GRPQUOTA) ? Q_XSETGQLIM : Q_XSETPQLIM);
 	VFS_QUOTACTL(vfsp, setmode, id, (caddr_t)fdq, error);
 	return -error;
 }
diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h
index 7649399..7ee1f71 100644
--- a/fs/xfs/linux-2.6/xfs_vfs.h
+++ b/fs/xfs/linux-2.6/xfs_vfs.h
@@ -107,6 +107,7 @@
 #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 fileystem for a snapshot */
 
 typedef int	(*vfs_mount_t)(bhv_desc_t *,
 				struct xfs_mount_args *, struct cred *);
diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c
index a832d16..250cad5 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.c
+++ b/fs/xfs/linux-2.6/xfs_vnode.c
@@ -411,13 +411,13 @@
 /*  0 */		(void *)(__psint_t)(vk),		\
 /*  1 */		(void *)(s),				\
 /*  2 */		(void *)(__psint_t) line,		\
-/*  3 */		(void *)(vn_count(vp)), \
+/*  3 */		(void *)(__psint_t)(vn_count(vp)),	\
 /*  4 */		(void *)(ra),				\
 /*  5 */		(void *)(__psunsigned_t)(vp)->v_flag,	\
 /*  6 */		(void *)(__psint_t)current_cpu(),	\
 /*  7 */		(void *)(__psint_t)current_pid(),	\
 /*  8 */		(void *)__return_address,		\
-/*  9 */		0, 0, 0, 0, 0, 0, 0)
+/*  9 */		NULL, NULL, NULL, NULL, NULL, NULL, NULL)
 
 /*
  * Vnode tracing code.
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h
index 00466c3..a6e57c6 100644
--- a/fs/xfs/linux-2.6/xfs_vnode.h
+++ b/fs/xfs/linux-2.6/xfs_vnode.h
@@ -426,7 +426,7 @@
 	u_long		va_extsize;	/* file extent size */
 	u_long		va_nextents;	/* number of extents in file */
 	u_long		va_anextents;	/* number of attr extents in file */
-	int		va_projid;	/* project id */
+	prid_t		va_projid;	/* project id */
 } vattr_t;
 
 /*
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c
index 740d20d..46ce1e3 100644
--- a/fs/xfs/quota/xfs_dquot.c
+++ b/fs/xfs/quota/xfs_dquot.c
@@ -101,7 +101,7 @@
  * is the d_id field. The idea is to fill in the entire q_core
  * when we read in the on disk dquot.
  */
-xfs_dquot_t *
+STATIC xfs_dquot_t *
 xfs_qm_dqinit(
 	xfs_mount_t  *mp,
 	xfs_dqid_t   id,
@@ -286,7 +286,9 @@
  * We also return 0 as the values of the timers in Q_GETQUOTA calls, when
  * enforcement's off.
  * In contrast, warnings are a little different in that they don't
- * 'automatically' get started when limits get exceeded.
+ * 'automatically' get started when limits get exceeded.  They do
+ * get reset to zero, however, when we find the count to be under
+ * the soft limit (they are only ever set non-zero via userspace).
  */
 void
 xfs_qm_adjust_dqtimers(
@@ -315,6 +317,8 @@
 				INT_GET(d->d_blk_hardlimit, ARCH_CONVERT)))) {
 			INT_SET(d->d_btimer, ARCH_CONVERT,
 				get_seconds() + XFS_QI_BTIMELIMIT(mp));
+		} else {
+			d->d_bwarns = 0;
 		}
 	} else {
 		if ((!d->d_blk_softlimit ||
@@ -336,6 +340,8 @@
 				INT_GET(d->d_ino_hardlimit, ARCH_CONVERT)))) {
 			INT_SET(d->d_itimer, ARCH_CONVERT,
 				get_seconds() + XFS_QI_ITIMELIMIT(mp));
+		} else {
+			d->d_iwarns = 0;
 		}
 	} else {
 		if ((!d->d_ino_softlimit ||
@@ -357,6 +363,8 @@
 				INT_GET(d->d_rtb_hardlimit, ARCH_CONVERT)))) {
 			INT_SET(d->d_rtbtimer, ARCH_CONVERT,
 				get_seconds() + XFS_QI_RTBTIMELIMIT(mp));
+		} else {
+			d->d_rtbwarns = 0;
 		}
 	} else {
 		if ((!d->d_rtb_softlimit ||
@@ -371,68 +379,6 @@
 }
 
 /*
- * Increment or reset warnings of a given dquot.
- */
-int
-xfs_qm_dqwarn(
-	xfs_disk_dquot_t	*d,
-	uint			flags)
-{
-	int	warned;
-
-	/*
-	 * root's limits are not real limits.
-	 */
-	if (!d->d_id)
-		return (0);
-
-	warned = 0;
-	if (INT_GET(d->d_blk_softlimit, ARCH_CONVERT) &&
-	    (INT_GET(d->d_bcount, ARCH_CONVERT) >=
-	     INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) {
-		if (flags & XFS_QMOPT_DOWARN) {
-			INT_MOD(d->d_bwarns, ARCH_CONVERT, +1);
-			warned++;
-		}
-	} else {
-		if (!d->d_blk_softlimit ||
-		    (INT_GET(d->d_bcount, ARCH_CONVERT) <
-		     INT_GET(d->d_blk_softlimit, ARCH_CONVERT))) {
-			d->d_bwarns = 0;
-		}
-	}
-
-	if (INT_GET(d->d_ino_softlimit, ARCH_CONVERT) > 0 &&
-	    (INT_GET(d->d_icount, ARCH_CONVERT) >=
-	     INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) {
-		if (flags & XFS_QMOPT_DOWARN) {
-			INT_MOD(d->d_iwarns, ARCH_CONVERT, +1);
-			warned++;
-		}
-	} else {
-		if (!d->d_ino_softlimit ||
-		    (INT_GET(d->d_icount, ARCH_CONVERT) <
-		     INT_GET(d->d_ino_softlimit, ARCH_CONVERT))) {
-			d->d_iwarns = 0;
-		}
-	}
-#ifdef QUOTADEBUG
-	if (INT_GET(d->d_iwarns, ARCH_CONVERT))
-		cmn_err(CE_DEBUG,
-			"--------@@Inode warnings running : %Lu >= %Lu",
-			INT_GET(d->d_icount, ARCH_CONVERT),
-			INT_GET(d->d_ino_softlimit, ARCH_CONVERT));
-	if (INT_GET(d->d_bwarns, ARCH_CONVERT))
-		cmn_err(CE_DEBUG,
-			"--------@@Blks warnings running : %Lu >= %Lu",
-			INT_GET(d->d_bcount, ARCH_CONVERT),
-			INT_GET(d->d_blk_softlimit, ARCH_CONVERT));
-#endif
-	return (warned);
-}
-
-
-/*
  * initialize a buffer full of dquots and log the whole thing
  */
 STATIC void
@@ -461,9 +407,9 @@
 	for (i = 0; i < XFS_QM_DQPERBLK(mp); i++, d++, curid++)
 		xfs_qm_dqinit_core(curid, type, d);
 	xfs_trans_dquot_buf(tp, bp,
-			    type & XFS_DQ_USER ?
-			    XFS_BLI_UDQUOT_BUF :
-			    XFS_BLI_GDQUOT_BUF);
+			    (type & XFS_DQ_USER ? XFS_BLI_UDQUOT_BUF :
+			    ((type & XFS_DQ_PROJ) ? XFS_BLI_PDQUOT_BUF :
+			     XFS_BLI_GDQUOT_BUF)));
 	xfs_trans_log_buf(tp, bp, 0, BBTOB(XFS_QI_DQCHUNKLEN(mp)) - 1);
 }
 
@@ -544,8 +490,7 @@
 	 * the entire thing.
 	 */
 	xfs_qm_init_dquot_blk(tp, mp, INT_GET(dqp->q_core.d_id, ARCH_CONVERT),
-			      dqp->dq_flags & (XFS_DQ_USER|XFS_DQ_GROUP),
-			      bp);
+			      dqp->dq_flags & XFS_DQ_ALLTYPES, bp);
 
 	if ((error = xfs_bmap_finish(&tp, &flist, firstblock, &committed))) {
 		goto error1;
@@ -675,8 +620,7 @@
 	/*
 	 * A simple sanity check in case we got a corrupted dquot...
 	 */
-	if (xfs_qm_dqcheck(ddq, id,
-			   dqp->dq_flags & (XFS_DQ_USER|XFS_DQ_GROUP),
+	if (xfs_qm_dqcheck(ddq, id, dqp->dq_flags & XFS_DQ_ALLTYPES,
 			   flags & (XFS_QMOPT_DQREPAIR|XFS_QMOPT_DOWARN),
 			   "dqtobp")) {
 		if (!(flags & XFS_QMOPT_DQREPAIR)) {
@@ -953,8 +897,8 @@
 xfs_qm_dqget(
 	xfs_mount_t	*mp,
 	xfs_inode_t	*ip,	  /* locked inode (optional) */
-	xfs_dqid_t	id,	  /* gid or uid, depending on type */
-	uint		type,	  /* UDQUOT or GDQUOT */
+	xfs_dqid_t	id,	  /* uid/projid/gid depending on type */
+	uint		type,	  /* XFS_DQ_USER/XFS_DQ_PROJ/XFS_DQ_GROUP */
 	uint		flags,	  /* DQALLOC, DQSUSER, DQREPAIR, DOWARN */
 	xfs_dquot_t	**O_dqpp) /* OUT : locked incore dquot */
 {
@@ -965,6 +909,7 @@
 
 	ASSERT(XFS_IS_QUOTA_RUNNING(mp));
 	if ((! XFS_IS_UQUOTA_ON(mp) && type == XFS_DQ_USER) ||
+	    (! XFS_IS_PQUOTA_ON(mp) && type == XFS_DQ_PROJ) ||
 	    (! XFS_IS_GQUOTA_ON(mp) && type == XFS_DQ_GROUP)) {
 		return (ESRCH);
 	}
@@ -983,7 +928,9 @@
  again:
 
 #ifdef DEBUG
-	ASSERT(type == XFS_DQ_USER || type == XFS_DQ_GROUP);
+	ASSERT(type == XFS_DQ_USER ||
+	       type == XFS_DQ_PROJ ||
+	       type == XFS_DQ_GROUP);
 	if (ip) {
 		ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
 		if (type == XFS_DQ_USER)
@@ -1306,8 +1253,8 @@
 		return (error);
 	}
 
-	if (xfs_qm_dqcheck(&dqp->q_core, INT_GET(ddqp->d_id, ARCH_CONVERT), 0, XFS_QMOPT_DOWARN,
-			   "dqflush (incore copy)")) {
+	if (xfs_qm_dqcheck(&dqp->q_core, INT_GET(ddqp->d_id, ARCH_CONVERT),
+			   0, XFS_QMOPT_DOWARN, "dqflush (incore copy)")) {
 		xfs_force_shutdown(dqp->q_mount, XFS_CORRUPT_INCORE);
 		return XFS_ERROR(EIO);
 	}
@@ -1459,7 +1406,8 @@
 {
 	if (d1 && d2) {
 		ASSERT(d1 != d2);
-		if (INT_GET(d1->q_core.d_id, ARCH_CONVERT) > INT_GET(d2->q_core.d_id, ARCH_CONVERT)) {
+		if (INT_GET(d1->q_core.d_id, ARCH_CONVERT) >
+		    INT_GET(d2->q_core.d_id, ARCH_CONVERT)) {
 			xfs_dqlock(d2);
 			xfs_dqlock(d1);
 		} else {
@@ -1582,8 +1530,7 @@
 	cmn_err(CE_DEBUG, "-----------KERNEL DQUOT----------------");
 	cmn_err(CE_DEBUG, "---- dquotID =  %d",
 		(int)INT_GET(dqp->q_core.d_id, ARCH_CONVERT));
-	cmn_err(CE_DEBUG, "---- type    =  %s",
-		XFS_QM_ISUDQ(dqp) ? "USR" : "GRP");
+	cmn_err(CE_DEBUG, "---- type    =  %s", DQFLAGTO_TYPESTR(dqp));
 	cmn_err(CE_DEBUG, "---- fs      =  0x%p", dqp->q_mount);
 	cmn_err(CE_DEBUG, "---- blkno   =  0x%x", (int) dqp->q_blkno);
 	cmn_err(CE_DEBUG, "---- boffset =  0x%x", (int) dqp->q_bufoffset);
diff --git a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h
index 0c3fe31..3917510 100644
--- a/fs/xfs/quota/xfs_dquot.h
+++ b/fs/xfs/quota/xfs_dquot.h
@@ -114,25 +114,18 @@
 #define XFS_DQHOLD(dqp)		((dqp)->q_nrefs++)
 
 /*
- * Quota Accounting flags
+ * Quota Accounting/Enforcement flags
  */
-#define XFS_ALL_QUOTA_ACCT	(XFS_UQUOTA_ACCT | XFS_GQUOTA_ACCT)
-#define XFS_ALL_QUOTA_ENFD	(XFS_UQUOTA_ENFD | XFS_GQUOTA_ENFD)
-#define XFS_ALL_QUOTA_CHKD	(XFS_UQUOTA_CHKD | XFS_GQUOTA_CHKD)
-#define XFS_ALL_QUOTA_ACTV	(XFS_UQUOTA_ACTIVE | XFS_GQUOTA_ACTIVE)
-#define XFS_ALL_QUOTA_ACCT_ENFD (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
-				 XFS_GQUOTA_ACCT|XFS_GQUOTA_ENFD)
+#define XFS_ALL_QUOTA_ACCT	\
+		(XFS_UQUOTA_ACCT | XFS_GQUOTA_ACCT | XFS_PQUOTA_ACCT)
+#define XFS_ALL_QUOTA_ENFD	(XFS_UQUOTA_ENFD | XFS_OQUOTA_ENFD)
+#define XFS_ALL_QUOTA_CHKD	(XFS_UQUOTA_CHKD | XFS_OQUOTA_CHKD)
 
-#define XFS_IS_QUOTA_RUNNING(mp)  ((mp)->m_qflags & XFS_ALL_QUOTA_ACCT)
-#define XFS_IS_UQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_UQUOTA_ACCT)
-#define XFS_IS_GQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_GQUOTA_ACCT)
-
-/*
- * Quota Limit Enforcement flags
- */
+#define XFS_IS_QUOTA_RUNNING(mp)	((mp)->m_qflags & XFS_ALL_QUOTA_ACCT)
 #define XFS_IS_QUOTA_ENFORCED(mp)	((mp)->m_qflags & XFS_ALL_QUOTA_ENFD)
-#define XFS_IS_UQUOTA_ENFORCED(mp)	((mp)->m_qflags & XFS_UQUOTA_ENFD)
-#define XFS_IS_GQUOTA_ENFORCED(mp)	((mp)->m_qflags & XFS_GQUOTA_ENFD)
+#define XFS_IS_UQUOTA_RUNNING(mp)	((mp)->m_qflags & XFS_UQUOTA_ACCT)
+#define XFS_IS_PQUOTA_RUNNING(mp)	((mp)->m_qflags & XFS_PQUOTA_ACCT)
+#define XFS_IS_GQUOTA_RUNNING(mp)	((mp)->m_qflags & XFS_GQUOTA_ACCT)
 
 #ifdef DEBUG
 static inline int
@@ -167,6 +160,8 @@
 #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)
+#define XFS_QM_ISPDQ(dqp)	((dqp)->dq_flags & XFS_DQ_PROJ)
+#define XFS_QM_ISGDQ(dqp)	((dqp)->dq_flags & XFS_DQ_GROUP)
 #define XFS_DQ_TO_QINF(dqp)	((dqp)->q_mount->m_quotainfo)
 #define XFS_DQ_TO_QIP(dqp)	(XFS_QM_ISUDQ(dqp) ? \
 				 XFS_DQ_TO_QINF(dqp)->qi_uquotaip : \
@@ -174,7 +169,7 @@
 
 #define XFS_IS_THIS_QUOTA_OFF(d) (! (XFS_QM_ISUDQ(d) ? \
 				     (XFS_IS_UQUOTA_ON((d)->q_mount)) : \
-				     (XFS_IS_GQUOTA_ON((d)->q_mount))))
+				     (XFS_IS_OQUOTA_ON((d)->q_mount))))
 
 #ifdef XFS_DQUOT_TRACE
 /*
@@ -211,7 +206,6 @@
 					xfs_disk_dquot_t *);
 extern void		xfs_qm_adjust_dqlimits(xfs_mount_t *,
 					xfs_disk_dquot_t *);
-extern int		xfs_qm_dqwarn(xfs_disk_dquot_t *, uint);
 extern int		xfs_qm_dqget(xfs_mount_t *, xfs_inode_t *,
 					xfs_dqid_t, uint, uint, xfs_dquot_t **);
 extern void		xfs_qm_dqput(xfs_dquot_t *);
diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c
index a5425ee..f5271b7 100644
--- a/fs/xfs/quota/xfs_dquot_item.c
+++ b/fs/xfs/quota/xfs_dquot_item.c
@@ -428,7 +428,7 @@
 /*
  * This is the ops vector for dquots
  */
-struct xfs_item_ops xfs_dquot_item_ops = {
+STATIC struct xfs_item_ops xfs_dquot_item_ops = {
 	.iop_size	= (uint(*)(xfs_log_item_t*))xfs_qm_dquot_logitem_size,
 	.iop_format	= (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
 					xfs_qm_dquot_logitem_format,
@@ -646,7 +646,7 @@
 	return;
 }
 
-struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
+STATIC struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
 	.iop_size	= (uint(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_size,
 	.iop_format	= (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
 					xfs_qm_qoff_logitem_format,
@@ -669,7 +669,7 @@
 /*
  * This is the ops vector shared by all quotaoff-start log items.
  */
-struct xfs_item_ops xfs_qm_qoff_logitem_ops = {
+STATIC struct xfs_item_ops xfs_qm_qoff_logitem_ops = {
 	.iop_size	= (uint(*)(xfs_log_item_t*))xfs_qm_qoff_logitem_size,
 	.iop_format	= (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
 					xfs_qm_qoff_logitem_format,
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c
index 89f2cd6..f665ca8f 100644
--- a/fs/xfs/quota/xfs_qm.c
+++ b/fs/xfs/quota/xfs_qm.c
@@ -81,12 +81,18 @@
 
 kmem_zone_t	*qm_dqzone;
 kmem_zone_t	*qm_dqtrxzone;
-kmem_shaker_t	xfs_qm_shaker;
+STATIC kmem_shaker_t	xfs_qm_shaker;
 
 STATIC void	xfs_qm_list_init(xfs_dqlist_t *, char *, int);
 STATIC void	xfs_qm_list_destroy(xfs_dqlist_t *);
 
+STATIC void	xfs_qm_freelist_init(xfs_frlist_t *);
+STATIC void	xfs_qm_freelist_destroy(xfs_frlist_t *);
+STATIC int	xfs_qm_mplist_nowait(xfs_mount_t *);
+STATIC int	xfs_qm_dqhashlock_nowait(xfs_dquot_t *);
+
 STATIC int	xfs_qm_init_quotainos(xfs_mount_t *);
+STATIC int	xfs_qm_init_quotainfo(xfs_mount_t *);
 STATIC int	xfs_qm_shake(int, unsigned int);
 
 #ifdef DEBUG
@@ -184,7 +190,7 @@
 /*
  * Destroy the global quota manager when its reference count goes to zero.
  */
-void
+STATIC void
 xfs_qm_destroy(
 	struct xfs_qm	*xqm)
 {
@@ -304,9 +310,9 @@
 	uint		flags)
 {
 	/*
-	 * User or group quotas has to be on.
+	 * User, projects or group quotas has to be on.
 	 */
-	ASSERT(flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA));
+	ASSERT(flags & (XFSMNT_UQUOTA | XFSMNT_PQUOTA | XFSMNT_GQUOTA));
 
 	/*
 	 * Initialize the flags in the mount structure. From this point
@@ -324,7 +330,11 @@
 	if (flags & XFSMNT_GQUOTA) {
 		mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);
 		if (flags & XFSMNT_GQUOTAENF)
-			mp->m_qflags |= XFS_GQUOTA_ENFD;
+			mp->m_qflags |= XFS_OQUOTA_ENFD;
+	} else if (flags & XFSMNT_PQUOTA) {
+		mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE);
+		if (flags & XFSMNT_PQUOTAENF)
+			mp->m_qflags |= XFS_OQUOTA_ENFD;
 	}
 }
 
@@ -357,11 +367,11 @@
 
 	/*
 	 * If a file system had quotas running earlier, but decided to
-	 * mount without -o quota/uquota/gquota options, revoke the
+	 * mount without -o uquota/pquota/gquota options, revoke the
 	 * quotachecked license, and bail out.
 	 */
 	if (! XFS_IS_QUOTA_ON(mp) &&
-	    (mp->m_sb.sb_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT))) {
+	    (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT)) {
 		mp->m_qflags = 0;
 		goto write_changes;
 	}
@@ -509,7 +519,7 @@
  * Flush all dquots of the given file system to disk. The dquots are
  * _not_ purged from memory here, just their data written to disk.
  */
-int
+STATIC int
 xfs_qm_dqflush_all(
 	xfs_mount_t	*mp,
 	int		flags)
@@ -613,7 +623,7 @@
 STATIC int
 xfs_qm_dqpurge_int(
 	xfs_mount_t	*mp,
-	uint		flags) /* QUOTAOFF/UMOUNTING/UQUOTA/GQUOTA */
+	uint		flags) /* QUOTAOFF/UMOUNTING/UQUOTA/PQUOTA/GQUOTA */
 {
 	xfs_dquot_t	*dqp;
 	uint		dqtype;
@@ -625,6 +635,7 @@
 		return (0);
 
 	dqtype = (flags & XFS_QMOPT_UQUOTA) ? XFS_DQ_USER : 0;
+	dqtype |= (flags & XFS_QMOPT_PQUOTA) ? XFS_DQ_PROJ : 0;
 	dqtype |= (flags & XFS_QMOPT_GQUOTA) ? XFS_DQ_GROUP : 0;
 
 	xfs_qm_mplist_lock(mp);
@@ -734,11 +745,11 @@
 
 	/*
 	 * udqhint is the i_udquot field in inode, and is non-NULL only
-	 * when the type arg is XFS_DQ_GROUP. Its purpose is to save a
+	 * when the type arg is group/project. Its purpose is to save a
 	 * lookup by dqid (xfs_qm_dqget) by caching a group dquot inside
 	 * the user dquot.
 	 */
-	ASSERT(!udqhint || type == XFS_DQ_GROUP);
+	ASSERT(!udqhint || type == XFS_DQ_GROUP || type == XFS_DQ_PROJ);
 	if (udqhint && !dolock)
 		xfs_dqlock(udqhint);
 
@@ -897,8 +908,8 @@
 
 
 /*
- * Given a locked inode, attach dquot(s) to it, taking UQUOTAON / GQUOTAON
- * in to account.
+ * Given a locked inode, attach dquot(s) to it, taking U/G/P-QUOTAON
+ * into account.
  * If XFS_QMOPT_DQALLOC, the dquot(s) will be allocated if needed.
  * If XFS_QMOPT_DQLOCK, the dquot(s) will be returned locked. This option pretty
  * much made this code a complete mess, but it has been pretty useful.
@@ -937,8 +948,13 @@
 		nquotas++;
 	}
 	ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
-	if (XFS_IS_GQUOTA_ON(mp)) {
-		error = xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
+	if (XFS_IS_OQUOTA_ON(mp)) {
+		error = XFS_IS_GQUOTA_ON(mp) ?
+			xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
+						flags & XFS_QMOPT_DQALLOC,
+						flags & XFS_QMOPT_DQLOCK,
+						ip->i_udquot, &ip->i_gdquot) :
+			xfs_qm_dqattach_one(ip, ip->i_d.di_projid, XFS_DQ_PROJ,
 						flags & XFS_QMOPT_DQALLOC,
 						flags & XFS_QMOPT_DQLOCK,
 						ip->i_udquot, &ip->i_gdquot);
@@ -989,7 +1005,7 @@
 		}
 		if (XFS_IS_UQUOTA_ON(mp))
 			ASSERT(ip->i_udquot);
-		if (XFS_IS_GQUOTA_ON(mp))
+		if (XFS_IS_OQUOTA_ON(mp))
 			ASSERT(ip->i_gdquot);
 	}
 #endif
@@ -1018,13 +1034,13 @@
 
 	ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_uquotino);
 	ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_gquotino);
-	if (ip->i_udquot)
-		xfs_dqtrace_entry_ino(ip->i_udquot, "DQDETTACH", ip);
 	if (ip->i_udquot) {
+		xfs_dqtrace_entry_ino(ip->i_udquot, "DQDETTACH", ip);
 		xfs_qm_dqrele(ip->i_udquot);
 		ip->i_udquot = NULL;
 	}
 	if (ip->i_gdquot) {
+		xfs_dqtrace_entry_ino(ip->i_gdquot, "DQDETTACH", ip);
 		xfs_qm_dqrele(ip->i_gdquot);
 		ip->i_gdquot = NULL;
 	}
@@ -1149,7 +1165,7 @@
  * This initializes all the quota information that's kept in the
  * mount structure
  */
-int
+STATIC int
 xfs_qm_init_quotainfo(
 	xfs_mount_t	*mp)
 {
@@ -1202,8 +1218,9 @@
 	 * and group quotas, at least not at this point.
 	 */
 	error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)0,
-			     (XFS_IS_UQUOTA_RUNNING(mp)) ?
-			     XFS_DQ_USER : XFS_DQ_GROUP,
+			     XFS_IS_UQUOTA_RUNNING(mp) ? XFS_DQ_USER : 
+			     (XFS_IS_GQUOTA_RUNNING(mp) ? XFS_DQ_GROUP :
+				XFS_DQ_PROJ),
 			     XFS_QMOPT_DQSUSER|XFS_QMOPT_DOWARN,
 			     &dqp);
 	if (! error) {
@@ -1234,6 +1251,10 @@
 				INT_GET(ddqp->d_iwarns, ARCH_CONVERT) ?
 				INT_GET(ddqp->d_iwarns, ARCH_CONVERT) :
 				XFS_QM_IWARNLIMIT;
+		qinf->qi_rtbwarnlimit =
+				INT_GET(ddqp->d_rtbwarns, ARCH_CONVERT) ?
+				INT_GET(ddqp->d_rtbwarns, ARCH_CONVERT) :
+				XFS_QM_RTBWARNLIMIT;
 		qinf->qi_bhardlimit =
 				INT_GET(ddqp->d_blk_hardlimit, ARCH_CONVERT);
 		qinf->qi_bsoftlimit =
@@ -1259,6 +1280,7 @@
 		qinf->qi_rtbtimelimit = XFS_QM_RTBTIMELIMIT;
 		qinf->qi_bwarnlimit = XFS_QM_BWARNLIMIT;
 		qinf->qi_iwarnlimit = XFS_QM_IWARNLIMIT;
+		qinf->qi_rtbwarnlimit = XFS_QM_RTBWARNLIMIT;
 	}
 
 	return (0);
@@ -1366,13 +1388,20 @@
 		ASSERT(udqp);
 	}
 
-	if (XFS_IS_GQUOTA_ON(mp)) {
+	if (XFS_IS_OQUOTA_ON(mp)) {
 		ASSERT(ip->i_gdquot == NULL);
 		if (udqp)
 			xfs_dqunlock(udqp);
-		if ((error = xfs_qm_dqget(mp, ip, ip->i_d.di_gid, XFS_DQ_GROUP,
-					 XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN,
-					 &gdqp))) {
+		error = XFS_IS_GQUOTA_ON(mp) ?
+				xfs_qm_dqget(mp, ip,
+					     ip->i_d.di_gid, XFS_DQ_GROUP,
+					     XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN,
+					     &gdqp) :
+				xfs_qm_dqget(mp, ip,
+					     ip->i_d.di_projid, XFS_DQ_PROJ,
+					     XFS_QMOPT_DQALLOC|XFS_QMOPT_DOWARN,
+					     &gdqp);
+		if (error) {
 			if (udqp)
 				xfs_qm_dqrele(udqp);
 			ASSERT(error != ESRCH);
@@ -1521,8 +1550,10 @@
 		INT_SET(ddq->d_rtbcount, ARCH_CONVERT, 0ULL);
 		INT_SET(ddq->d_btimer, ARCH_CONVERT, (time_t)0);
 		INT_SET(ddq->d_itimer, ARCH_CONVERT, (time_t)0);
+		INT_SET(ddq->d_rtbtimer, ARCH_CONVERT, (time_t)0);
 		INT_SET(ddq->d_bwarns, ARCH_CONVERT, 0UL);
 		INT_SET(ddq->d_iwarns, ARCH_CONVERT, 0UL);
+		INT_SET(ddq->d_rtbwarns, ARCH_CONVERT, 0UL);
 		ddq = (xfs_disk_dquot_t *) ((xfs_dqblk_t *)ddq + 1);
 	}
 
@@ -1541,11 +1572,14 @@
 	int		error;
 	int		notcommitted;
 	int		incr;
+	int		type;
 
 	ASSERT(blkcnt > 0);
 	notcommitted = 0;
 	incr = (blkcnt > XFS_QM_MAX_DQCLUSTER_LOGSZ) ?
 		XFS_QM_MAX_DQCLUSTER_LOGSZ : blkcnt;
+	type = flags & XFS_QMOPT_UQUOTA ? XFS_DQ_USER :
+		(flags & XFS_QMOPT_PQUOTA ? XFS_DQ_PROJ : XFS_DQ_GROUP);
 	error = 0;
 
 	/*
@@ -1564,9 +1598,7 @@
 		if (error)
 			break;
 
-		(void) xfs_qm_reset_dqcounts(mp, bp, firstid,
-					     flags & XFS_QMOPT_UQUOTA ?
-					     XFS_DQ_USER : XFS_DQ_GROUP);
+		(void) xfs_qm_reset_dqcounts(mp, bp, firstid, type);
 		xfs_bdwrite(mp, bp);
 		/*
 		 * goto the next block.
@@ -1578,7 +1610,7 @@
 }
 
 /*
- * Iterate over all allocated USR/GRP dquots in the system, calling a
+ * Iterate over all allocated USR/GRP/PRJ dquots in the system, calling a
  * caller supplied function for every chunk of dquots that we find.
  */
 STATIC int
@@ -1849,7 +1881,7 @@
 		xfs_qm_quotacheck_dqadjust(udqp, nblks, rtblks);
 		xfs_qm_dqput(udqp);
 	}
-	if (XFS_IS_GQUOTA_ON(mp)) {
+	if (XFS_IS_OQUOTA_ON(mp)) {
 		ASSERT(gdqp);
 		xfs_qm_quotacheck_dqadjust(gdqp, nblks, rtblks);
 		xfs_qm_dqput(gdqp);
@@ -1898,7 +1930,7 @@
 	cmn_err(CE_NOTE, "XFS quotacheck %s: Please wait.", mp->m_fsname);
 
 	/*
-	 * First we go thru all the dquots on disk, USR and GRP, and reset
+	 * First we go thru all the dquots on disk, USR and GRP/PRJ, and reset
 	 * their counters to zero. We need a clean slate.
 	 * We don't log our changes till later.
 	 */
@@ -1909,9 +1941,10 @@
 	}
 
 	if ((gip = XFS_QI_GQIP(mp))) {
-		if ((error = xfs_qm_dqiterate(mp, gip, XFS_QMOPT_GQUOTA)))
+		if ((error = xfs_qm_dqiterate(mp, gip, XFS_IS_GQUOTA_ON(mp) ?
+					XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA)))
 			goto error_return;
-		flags |= XFS_GQUOTA_CHKD;
+		flags |= XFS_OQUOTA_CHKD;
 	}
 
 	do {
@@ -1938,7 +1971,7 @@
 	if (error) {
 		xfs_qm_dqpurge_all(mp,
 				   XFS_QMOPT_UQUOTA|XFS_QMOPT_GQUOTA|
-				   XFS_QMOPT_QUOTAOFF);
+				   XFS_QMOPT_PQUOTA|XFS_QMOPT_QUOTAOFF);
 		goto error_return;
 	}
 	/*
@@ -1961,7 +1994,7 @@
 	 * quotachecked status, since we won't be doing accounting for
 	 * that type anymore.
 	 */
-	mp->m_qflags &= ~(XFS_GQUOTA_CHKD | XFS_UQUOTA_CHKD);
+	mp->m_qflags &= ~(XFS_OQUOTA_CHKD | XFS_UQUOTA_CHKD);
 	mp->m_qflags |= flags;
 
 	XQM_LIST_PRINT(&(XFS_QI_MPL_LIST(mp)), MPL_NEXT, "++++ Mp list +++");
@@ -2013,7 +2046,7 @@
 					     0, 0, &uip, 0)))
 				return XFS_ERROR(error);
 		}
-		if (XFS_IS_GQUOTA_ON(mp) &&
+		if (XFS_IS_OQUOTA_ON(mp) &&
 		    mp->m_sb.sb_gquotino != NULLFSINO) {
 			ASSERT(mp->m_sb.sb_gquotino > 0);
 			if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
@@ -2043,10 +2076,12 @@
 
 		flags &= ~XFS_QMOPT_SBVERSION;
 	}
-	if (XFS_IS_GQUOTA_ON(mp) && gip == NULL) {
-		if ((error = xfs_qm_qino_alloc(mp, &gip,
-					      sbflags | XFS_SB_GQUOTINO,
-					      flags | XFS_QMOPT_GQUOTA))) {
+	if (XFS_IS_OQUOTA_ON(mp) && gip == NULL) {
+		flags |= (XFS_IS_GQUOTA_ON(mp) ?
+				XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA);
+		error = xfs_qm_qino_alloc(mp, &gip,
+					  sbflags | XFS_SB_GQUOTINO, flags);
+		if (error) {
 			if (uip)
 				VN_RELE(XFS_ITOV(uip));
 
@@ -2452,6 +2487,7 @@
 	xfs_inode_t	*ip,
 	uid_t		uid,
 	gid_t		gid,
+	prid_t		prid,
 	uint		flags,
 	xfs_dquot_t	**O_udqpp,
 	xfs_dquot_t	**O_gdqpp)
@@ -2483,8 +2519,7 @@
 	}
 
 	uq = gq = NULL;
-	if ((flags & XFS_QMOPT_UQUOTA) &&
-	    XFS_IS_UQUOTA_ON(mp)) {
+	if ((flags & XFS_QMOPT_UQUOTA) && XFS_IS_UQUOTA_ON(mp)) {
 		if (ip->i_d.di_uid != uid) {
 			/*
 			 * What we need is the dquot that has this uid, and
@@ -2522,8 +2557,7 @@
 			xfs_dqunlock(uq);
 		}
 	}
-	if ((flags & XFS_QMOPT_GQUOTA) &&
-	    XFS_IS_GQUOTA_ON(mp)) {
+	if ((flags & XFS_QMOPT_GQUOTA) && XFS_IS_GQUOTA_ON(mp)) {
 		if (ip->i_d.di_gid != gid) {
 			xfs_iunlock(ip, lockflags);
 			if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)gid,
@@ -2546,6 +2580,29 @@
 			XFS_DQHOLD(gq);
 			xfs_dqunlock(gq);
 		}
+	} else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) {
+		if (ip->i_d.di_projid != prid) {
+			xfs_iunlock(ip, lockflags);
+			if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid,
+						 XFS_DQ_PROJ,
+						 XFS_QMOPT_DQALLOC |
+						 XFS_QMOPT_DOWARN,
+						 &gq))) {
+				if (uq)
+					xfs_qm_dqrele(uq);
+				ASSERT(error != ENOENT);
+				return (error);
+			}
+			xfs_dqunlock(gq);
+			lockflags = XFS_ILOCK_SHARED;
+			xfs_ilock(ip, lockflags);
+		} else {
+			ASSERT(ip->i_gdquot);
+			gq = ip->i_gdquot;
+			xfs_dqlock(gq);
+			XFS_DQHOLD(gq);
+			xfs_dqunlock(gq);
+		}
 	}
 	if (uq)
 		xfs_dqtrace_entry_ino(uq, "DQALLOC", ip);
@@ -2574,6 +2631,9 @@
 	xfs_dquot_t	*newdq)
 {
 	xfs_dquot_t	*prevdq;
+	uint		bfield = XFS_IS_REALTIME_INODE(ip) ?
+				 XFS_TRANS_DQ_RTBCOUNT : XFS_TRANS_DQ_BCOUNT;
+
 	ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
 	ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));
 
@@ -2582,20 +2642,12 @@
 	ASSERT(prevdq);
 	ASSERT(prevdq != newdq);
 
-	xfs_trans_mod_dquot(tp, prevdq,
-			    XFS_TRANS_DQ_BCOUNT,
-			    -(ip->i_d.di_nblocks));
-	xfs_trans_mod_dquot(tp, prevdq,
-			    XFS_TRANS_DQ_ICOUNT,
-			    -1);
+	xfs_trans_mod_dquot(tp, prevdq, bfield, -(ip->i_d.di_nblocks));
+	xfs_trans_mod_dquot(tp, prevdq, XFS_TRANS_DQ_ICOUNT, -1);
 
 	/* the sparkling new dquot */
-	xfs_trans_mod_dquot(tp, newdq,
-			    XFS_TRANS_DQ_BCOUNT,
-			    ip->i_d.di_nblocks);
-	xfs_trans_mod_dquot(tp, newdq,
-			    XFS_TRANS_DQ_ICOUNT,
-			    1);
+	xfs_trans_mod_dquot(tp, newdq, bfield, ip->i_d.di_nblocks);
+	xfs_trans_mod_dquot(tp, newdq, XFS_TRANS_DQ_ICOUNT, 1);
 
 	/*
 	 * Take an extra reference, because the inode
@@ -2611,7 +2663,7 @@
 }
 
 /*
- * Quota reservations for setattr(AT_UID|AT_GID).
+ * Quota reservations for setattr(AT_UID|AT_GID|AT_PROJID).
  */
 int
 xfs_qm_vop_chown_reserve(
@@ -2623,7 +2675,7 @@
 {
 	int		error;
 	xfs_mount_t	*mp;
-	uint		delblks;
+	uint		delblks, blkflags;
 	xfs_dquot_t	*unresudq, *unresgdq, *delblksudq, *delblksgdq;
 
 	ASSERT(XFS_ISLOCKED_INODE(ip));
@@ -2632,6 +2684,8 @@
 
 	delblks = ip->i_delayed_blks;
 	delblksudq = delblksgdq = unresudq = unresgdq = NULL;
+	blkflags = XFS_IS_REALTIME_INODE(ip) ?
+			XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS;
 
 	if (XFS_IS_UQUOTA_ON(mp) && udqp &&
 	    ip->i_d.di_uid != (uid_t)INT_GET(udqp->q_core.d_id, ARCH_CONVERT)) {
@@ -2646,18 +2700,22 @@
 			unresudq = ip->i_udquot;
 		}
 	}
-	if (XFS_IS_GQUOTA_ON(ip->i_mount) && gdqp &&
-	    ip->i_d.di_gid != INT_GET(gdqp->q_core.d_id, ARCH_CONVERT)) {
-		delblksgdq = gdqp;
-		if (delblks) {
-			ASSERT(ip->i_gdquot);
-			unresgdq = ip->i_gdquot;
+	if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) {
+		if ((XFS_IS_GQUOTA_ON(ip->i_mount) && ip->i_d.di_gid !=
+				INT_GET(gdqp->q_core.d_id, ARCH_CONVERT)) ||
+		    (XFS_IS_PQUOTA_ON(ip->i_mount) && ip->i_d.di_projid !=
+				INT_GET(gdqp->q_core.d_id, ARCH_CONVERT))) {
+			delblksgdq = gdqp;
+			if (delblks) {
+				ASSERT(ip->i_gdquot);
+				unresgdq = ip->i_gdquot;
+			}
 		}
 	}
 
 	if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
 				delblksudq, delblksgdq, ip->i_d.di_nblocks, 1,
-				flags | XFS_QMOPT_RES_REGBLKS)))
+				flags | blkflags)))
 		return (error);
 
 	/*
@@ -2674,11 +2732,11 @@
 		ASSERT(unresudq || unresgdq);
 		if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
 				delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0,
-				flags | XFS_QMOPT_RES_REGBLKS)))
+				flags | blkflags)))
 			return (error);
 		xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
 				unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0,
-				XFS_QMOPT_RES_REGBLKS);
+				blkflags);
 	}
 
 	return (0);
@@ -2751,7 +2809,7 @@
 }
 
 /* ------------- list stuff -----------------*/
-void
+STATIC void
 xfs_qm_freelist_init(xfs_frlist_t *ql)
 {
 	ql->qh_next = ql->qh_prev = (xfs_dquot_t *) ql;
@@ -2760,7 +2818,7 @@
 	ql->qh_nelems = 0;
 }
 
-void
+STATIC void
 xfs_qm_freelist_destroy(xfs_frlist_t *ql)
 {
 	xfs_dquot_t	*dqp, *nextdqp;
@@ -2786,7 +2844,7 @@
 	ASSERT(ql->qh_nelems == 0);
 }
 
-void
+STATIC void
 xfs_qm_freelist_insert(xfs_frlist_t *ql, xfs_dquot_t *dq)
 {
 	dq->dq_flnext = ql->qh_next;
@@ -2816,7 +2874,7 @@
 	xfs_qm_freelist_insert((xfs_frlist_t *)ql->qh_prev, dq);
 }
 
-int
+STATIC int
 xfs_qm_dqhashlock_nowait(
 	xfs_dquot_t *dqp)
 {
@@ -2836,7 +2894,7 @@
 	return (locked);
 }
 
-int
+STATIC int
 xfs_qm_mplist_nowait(
 	xfs_mount_t	*mp)
 {
diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h
index dcf1a7a..b03eecf 100644
--- a/fs/xfs/quota/xfs_qm.h
+++ b/fs/xfs/quota/xfs_qm.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ * 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 version 2 of the GNU General Public License as
@@ -133,8 +133,9 @@
 	time_t		 qi_btimelimit;	 /* limit for blks timer */
 	time_t		 qi_itimelimit;	 /* limit for inodes timer */
 	time_t		 qi_rtbtimelimit;/* limit for rt blks timer */
-	xfs_qwarncnt_t	 qi_bwarnlimit;	 /* limit for num warnings */
-	xfs_qwarncnt_t	 qi_iwarnlimit;	 /* limit for num warnings */
+	xfs_qwarncnt_t	 qi_bwarnlimit;	 /* limit for blks warnings */
+	xfs_qwarncnt_t	 qi_iwarnlimit;	 /* limit for inodes warnings */
+	xfs_qwarncnt_t	 qi_rtbwarnlimit;/* limit for rt blks warnings */
 	mutex_t		 qi_quotaofflock;/* to serialize quotaoff */
 	xfs_filblks_t	 qi_dqchunklen;	 /* # BBs in a chunk of dqs */
 	uint		 qi_dqperchunk;	 /* # ondisk dqs in above chunk */
@@ -176,6 +177,7 @@
 
 #define XFS_QM_BWARNLIMIT	5
 #define XFS_QM_IWARNLIMIT	5
+#define XFS_QM_RTBWARNLIMIT	5
 
 #define XFS_QM_LOCK(xqm)	(mutex_lock(&xqm##_lock, PINOD))
 #define XFS_QM_UNLOCK(xqm)	(mutex_unlock(&xqm##_lock))
@@ -184,7 +186,6 @@
 
 extern void		xfs_mount_reset_sbqflags(xfs_mount_t *);
 
-extern int		xfs_qm_init_quotainfo(xfs_mount_t *);
 extern void		xfs_qm_destroy_quotainfo(xfs_mount_t *);
 extern int		xfs_qm_mount_quotas(xfs_mount_t *, int);
 extern void		xfs_qm_mount_quotainit(xfs_mount_t *, uint);
@@ -203,7 +204,7 @@
 
 /* vop stuff */
 extern int		xfs_qm_vop_dqalloc(xfs_mount_t *, xfs_inode_t *,
-					uid_t, gid_t, uint,
+					uid_t, gid_t, prid_t, uint,
 					xfs_dquot_t **, xfs_dquot_t **);
 extern void		xfs_qm_vop_dqattach_and_dqmod_newinode(
 					xfs_trans_t *, xfs_inode_t *,
@@ -215,14 +216,9 @@
 					xfs_dquot_t *, xfs_dquot_t *, uint);
 
 /* list stuff */
-extern void		xfs_qm_freelist_init(xfs_frlist_t *);
-extern void		xfs_qm_freelist_destroy(xfs_frlist_t *);
-extern void		xfs_qm_freelist_insert(xfs_frlist_t *, xfs_dquot_t *);
 extern void		xfs_qm_freelist_append(xfs_frlist_t *, xfs_dquot_t *);
 extern void		xfs_qm_freelist_unlink(xfs_dquot_t *);
 extern int		xfs_qm_freelist_lock_nowait(xfs_qm_t *);
-extern int		xfs_qm_mplist_nowait(xfs_mount_t *);
-extern int		xfs_qm_dqhashlock_nowait(xfs_dquot_t *);
 
 /* system call interface */
 extern int		xfs_qm_quotactl(bhv_desc_t *, int, int, xfs_caddr_t);
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c
index be67d9c..dc3c37a 100644
--- a/fs/xfs/quota/xfs_qm_bhv.c
+++ b/fs/xfs/quota/xfs_qm_bhv.c
@@ -71,10 +71,13 @@
 #define MNTOPT_NOQUOTA	"noquota"	/* no quotas */
 #define MNTOPT_USRQUOTA	"usrquota"	/* user quota enabled */
 #define MNTOPT_GRPQUOTA	"grpquota"	/* group quota enabled */
+#define MNTOPT_PRJQUOTA	"prjquota"	/* project quota enabled */
 #define MNTOPT_UQUOTA	"uquota"	/* user quota (IRIX variant) */
 #define MNTOPT_GQUOTA	"gquota"	/* group quota (IRIX variant) */
+#define MNTOPT_PQUOTA	"pquota"	/* project quota (IRIX variant) */
 #define MNTOPT_UQUOTANOENF "uqnoenforce"/* user quota limit enforcement */
 #define MNTOPT_GQUOTANOENF "gqnoenforce"/* group quota limit enforcement */
+#define MNTOPT_PQUOTANOENF "pqnoenforce"/* project quota limit enforcement */
 #define MNTOPT_QUOTANOENF  "qnoenforce"	/* same as uqnoenforce */
 
 STATIC int
@@ -109,6 +112,14 @@
 			args->flags |= XFSMNT_UQUOTA;
 			args->flags &= ~XFSMNT_UQUOTAENF;
 			referenced = 1;
+		} else if (!strcmp(this_char, MNTOPT_PQUOTA) ||
+			   !strcmp(this_char, MNTOPT_PRJQUOTA)) {
+			args->flags |= XFSMNT_PQUOTA | XFSMNT_PQUOTAENF;
+			referenced = 1;
+		} else if (!strcmp(this_char, MNTOPT_PQUOTANOENF)) {
+			args->flags |= XFSMNT_PQUOTA;
+			args->flags &= ~XFSMNT_PQUOTAENF;
+			referenced = 1;
 		} else if (!strcmp(this_char, MNTOPT_GQUOTA) ||
 			   !strcmp(this_char, MNTOPT_GRPQUOTA)) {
 			args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF;
@@ -127,6 +138,12 @@
 			*this_char++ = ',';
 	}
 
+	if ((args->flags & XFSMNT_GQUOTA) && (args->flags & XFSMNT_PQUOTA)) {
+		cmn_err(CE_WARN,
+			"XFS: cannot mount with both project and group quota");
+		return XFS_ERROR(EINVAL);
+	}
+
 	PVFS_PARSEARGS(BHV_NEXT(bhv), options, args, update, error);
 	if (!error && !referenced)
 		bhv_remove_vfsops(bhvtovfs(bhv), VFS_POSITION_QM);
@@ -148,13 +165,19 @@
 			seq_puts(m, "," MNTOPT_UQUOTANOENF);
 	}
 
+	if (mp->m_qflags & XFS_PQUOTA_ACCT) {
+		(mp->m_qflags & XFS_OQUOTA_ENFD) ?
+			seq_puts(m, "," MNTOPT_PRJQUOTA) :
+			seq_puts(m, "," MNTOPT_PQUOTANOENF);
+	}
+
 	if (mp->m_qflags & XFS_GQUOTA_ACCT) {
-		(mp->m_qflags & XFS_GQUOTA_ENFD) ?
+		(mp->m_qflags & XFS_OQUOTA_ENFD) ?
 			seq_puts(m, "," MNTOPT_GRPQUOTA) :
 			seq_puts(m, "," MNTOPT_GQUOTANOENF);
 	}
 
-	if (!(mp->m_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT)))
+	if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
 		seq_puts(m, "," MNTOPT_NOQUOTA);
 
 	PVFS_SHOWARGS(BHV_NEXT(bhv), m, error);
@@ -171,7 +194,7 @@
 	struct xfs_mount	*mp = XFS_VFSTOM(vfsp);
 	int			error;
 
-	if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA))
+	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;
@@ -255,16 +278,17 @@
 	uint		*quotaflags)
 {
 	uint		quotaondisk;
-	uint		uquotaondisk = 0, gquotaondisk = 0;
+	uint		uquotaondisk = 0, gquotaondisk = 0, pquotaondisk = 0;
 
 	*quotaflags = 0;
 	*needquotamount = B_FALSE;
 
 	quotaondisk = XFS_SB_VERSION_HASQUOTA(&mp->m_sb) &&
-		mp->m_sb.sb_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT);
+				(mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT);
 
 	if (quotaondisk) {
 		uquotaondisk = mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT;
+		pquotaondisk = mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT;
 		gquotaondisk = mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT;
 	}
 
@@ -277,13 +301,16 @@
 
 	if (((uquotaondisk && !XFS_IS_UQUOTA_ON(mp)) ||
 	    (!uquotaondisk &&  XFS_IS_UQUOTA_ON(mp)) ||
+	     (pquotaondisk && !XFS_IS_PQUOTA_ON(mp)) ||
+	    (!pquotaondisk &&  XFS_IS_PQUOTA_ON(mp)) ||
 	     (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) ||
-	    (!gquotaondisk &&  XFS_IS_GQUOTA_ON(mp)))  &&
+	    (!gquotaondisk &&  XFS_IS_OQUOTA_ON(mp)))  &&
 	    xfs_dev_is_read_only(mp, "changing quota state")) {
 		cmn_err(CE_WARN,
-			"XFS: please mount with%s%s%s.",
+			"XFS: please mount with%s%s%s%s.",
 			(!quotaondisk ? "out quota" : ""),
 			(uquotaondisk ? " usrquota" : ""),
+			(pquotaondisk ? " prjquota" : ""),
 			(gquotaondisk ? " grpquota" : ""));
 		return XFS_ERROR(EPERM);
 	}
@@ -359,7 +386,7 @@
 }
 
 
-struct xfs_qmops xfs_qmcore_xfs = {
+STATIC struct xfs_qmops xfs_qmcore_xfs = {
 	.xfs_qminit		= xfs_qm_newmount,
 	.xfs_qmdone		= xfs_qm_unmount_quotadestroy,
 	.xfs_qmmount		= xfs_qm_endmount,
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index 229f5b5..68e9896 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -118,40 +118,41 @@
 	 * The following commands are valid even when quotaoff.
 	 */
 	switch (cmd) {
+	case Q_XQUOTARM:
 		/*
-		 * truncate quota files. quota must be off.
+		 * Truncate quota files. quota must be off.
 		 */
-	      case Q_XQUOTARM:
 		if (XFS_IS_QUOTA_ON(mp) || addr == NULL)
 			return XFS_ERROR(EINVAL);
 		if (vfsp->vfs_flag & VFS_RDONLY)
 			return XFS_ERROR(EROFS);
 		return (xfs_qm_scall_trunc_qfiles(mp,
 			       xfs_qm_import_qtype_flags(*(uint *)addr)));
+
+	case Q_XGETQSTAT:
 		/*
 		 * Get quota status information.
 		 */
-	      case Q_XGETQSTAT:
 		return (xfs_qm_scall_getqstat(mp, (fs_quota_stat_t *)addr));
 
+	case Q_XQUOTAON:
 		/*
-		 * QUOTAON for root f/s and quota enforcement on others..
-		 * Quota accounting for non-root f/s's must be turned on
-		 * at mount time.
+		 * QUOTAON - enabling quota enforcement.
+		 * Quota accounting must be turned on at mount time.
 		 */
-	      case Q_XQUOTAON:
 		if (addr == NULL)
 			return XFS_ERROR(EINVAL);
 		if (vfsp->vfs_flag & VFS_RDONLY)
 			return XFS_ERROR(EROFS);
 		return (xfs_qm_scall_quotaon(mp,
 					  xfs_qm_import_flags(*(uint *)addr)));
-	      case Q_XQUOTAOFF:
+
+	case Q_XQUOTAOFF:
 		if (vfsp->vfs_flag & VFS_RDONLY)
 			return XFS_ERROR(EROFS);
 		break;
 
-	      default:
+	default:
 		break;
 	}
 
@@ -159,7 +160,7 @@
 		return XFS_ERROR(ESRCH);
 
 	switch (cmd) {
-	      case Q_XQUOTAOFF:
+	case Q_XQUOTAOFF:
 		if (vfsp->vfs_flag & VFS_RDONLY)
 			return XFS_ERROR(EROFS);
 		error = xfs_qm_scall_quotaoff(mp,
@@ -167,42 +168,39 @@
 					    B_FALSE);
 		break;
 
-		/*
-		 * Defaults to XFS_GETUQUOTA.
-		 */
-	      case Q_XGETQUOTA:
+	case Q_XGETQUOTA:
 		error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_USER,
 					(fs_disk_quota_t *)addr);
 		break;
-		/*
-		 * Set limits, both hard and soft. Defaults to Q_SETUQLIM.
-		 */
-	      case Q_XSETQLIM:
+	case Q_XGETGQUOTA:
+		error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_GROUP,
+					(fs_disk_quota_t *)addr);
+		break;
+	case Q_XGETPQUOTA:
+		error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_PROJ,
+					(fs_disk_quota_t *)addr);
+		break;
+
+	case Q_XSETQLIM:
 		if (vfsp->vfs_flag & VFS_RDONLY)
 			return XFS_ERROR(EROFS);
 		error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_USER,
 					     (fs_disk_quota_t *)addr);
 		break;
-
-	       case Q_XSETGQLIM:
+	case Q_XSETGQLIM:
 		if (vfsp->vfs_flag & VFS_RDONLY)
 			return XFS_ERROR(EROFS);
 		error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_GROUP,
 					     (fs_disk_quota_t *)addr);
 		break;
-
-
-	      case Q_XGETGQUOTA:
-		error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_GROUP,
-					(fs_disk_quota_t *)addr);
+	case Q_XSETPQLIM:
+		if (vfsp->vfs_flag & VFS_RDONLY)
+			return XFS_ERROR(EROFS);
+		error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_PROJ,
+					     (fs_disk_quota_t *)addr);
 		break;
 
-		/*
-		 * Quotas are entirely undefined after quotaoff in XFS quotas.
-		 * For instance, there's no way to set limits when quotaoff.
-		 */
-
-	      default:
+	default:
 		error = XFS_ERROR(EINVAL);
 		break;
 	}
@@ -286,8 +284,12 @@
 	}
 	if (flags & XFS_GQUOTA_ACCT) {
 		dqtype |= XFS_QMOPT_GQUOTA;
-		flags |= (XFS_GQUOTA_CHKD | XFS_GQUOTA_ENFD);
+		flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
 		inactivate_flags |= XFS_GQUOTA_ACTIVE;
+	} else if (flags & XFS_PQUOTA_ACCT) {
+		dqtype |= XFS_QMOPT_PQUOTA;
+		flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
+		inactivate_flags |= XFS_PQUOTA_ACTIVE;
 	}
 
 	/*
@@ -364,7 +366,8 @@
 	/*
 	 * If quotas is completely disabled, close shop.
 	 */
-	if ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_ALL) {
+	if (((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET1) ||
+	    ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET2)) {
 		mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
 		xfs_qm_destroy_quotainfo(mp);
 		return (0);
@@ -378,7 +381,7 @@
 		XFS_PURGE_INODE(XFS_QI_UQIP(mp));
 		XFS_QI_UQIP(mp) = NULL;
 	}
-	if ((dqtype & XFS_QMOPT_GQUOTA) && XFS_QI_GQIP(mp)) {
+	if ((dqtype & (XFS_QMOPT_GQUOTA|XFS_QMOPT_PQUOTA)) && XFS_QI_GQIP(mp)) {
 		XFS_PURGE_INODE(XFS_QI_GQIP(mp));
 		XFS_QI_GQIP(mp) = NULL;
 	}
@@ -411,7 +414,8 @@
 		}
 	}
 
-	if ((flags & XFS_DQ_GROUP) && mp->m_sb.sb_gquotino != NULLFSINO) {
+	if ((flags & (XFS_DQ_GROUP|XFS_DQ_PROJ)) &&
+	    mp->m_sb.sb_gquotino != NULLFSINO) {
 		error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip, 0);
 		if (! error) {
 			(void) xfs_truncate_file(mp, qip);
@@ -434,7 +438,7 @@
 	uint		flags)
 {
 	int		error;
-	unsigned long s;
+	unsigned long	s;
 	uint		qf;
 	uint		accflags;
 	__int64_t	sbflags;
@@ -468,9 +472,13 @@
 	    (mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
 	    (flags & XFS_UQUOTA_ENFD))
 	    ||
+	    ((flags & XFS_PQUOTA_ACCT) == 0 &&
+	    (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
+	    (flags & XFS_OQUOTA_ENFD))
+	    ||
 	    ((flags & XFS_GQUOTA_ACCT) == 0 &&
 	    (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
-	    (flags & XFS_GQUOTA_ENFD))) {
+	    (flags & XFS_OQUOTA_ENFD))) {
 		qdprintk("Can't enforce without acct, flags=%x sbflags=%x\n",
 			flags, mp->m_sb.sb_qflags);
 		return XFS_ERROR(EINVAL);
@@ -504,6 +512,10 @@
 	 */
 	if  (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) !=
 	     (mp->m_qflags & XFS_UQUOTA_ACCT)) ||
+	     ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) !=
+	     (mp->m_qflags & XFS_PQUOTA_ACCT)) ||
+	     ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) !=
+	     (mp->m_qflags & XFS_GQUOTA_ACCT)) ||
 	    (flags & XFS_ALL_QUOTA_ENFD) == 0)
 		return (0);
 
@@ -521,7 +533,6 @@
 }
 
 
-
 /*
  * Return quota status information, such as uquota-off, enforcements, etc.
  */
@@ -606,7 +617,8 @@
 	if (!capable(CAP_SYS_ADMIN))
 		return XFS_ERROR(EPERM);
 
-	if ((newlim->d_fieldmask & (FS_DQ_LIMIT_MASK|FS_DQ_TIMER_MASK)) == 0)
+	if ((newlim->d_fieldmask &
+	    (FS_DQ_LIMIT_MASK|FS_DQ_TIMER_MASK|FS_DQ_WARNS_MASK)) == 0)
 		return (0);
 
 	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SETQLIM);
@@ -691,12 +703,23 @@
 		qdprintk("ihard %Ld < isoft %Ld\n", hard, soft);
 	}
 
+	/*
+	 * Update warnings counter(s) if requested
+	 */
+	if (newlim->d_fieldmask & FS_DQ_BWARNS)
+		INT_SET(ddq->d_bwarns, ARCH_CONVERT, newlim->d_bwarns);
+	if (newlim->d_fieldmask & FS_DQ_IWARNS)
+		INT_SET(ddq->d_iwarns, ARCH_CONVERT, newlim->d_iwarns);
+	if (newlim->d_fieldmask & FS_DQ_RTBWARNS)
+		INT_SET(ddq->d_rtbwarns, ARCH_CONVERT, newlim->d_rtbwarns);
+
 	if (id == 0) {
 		/*
 		 * Timelimits for the super user set the relative time
 		 * the other users can be over quota for this file system.
 		 * If it is zero a default is used.  Ditto for the default
-		 * soft and hard limit values (already done, above).
+		 * soft and hard limit values (already done, above), and
+		 * for warnings.
 		 */
 		if (newlim->d_fieldmask & FS_DQ_BTIMER) {
 			mp->m_quotainfo->qi_btimelimit = newlim->d_btimer;
@@ -710,7 +733,13 @@
 			mp->m_quotainfo->qi_rtbtimelimit = newlim->d_rtbtimer;
 			INT_SET(ddq->d_rtbtimer, ARCH_CONVERT, newlim->d_rtbtimer);
 		}
-	} else /* if (XFS_IS_QUOTA_ENFORCED(mp)) */ {
+		if (newlim->d_fieldmask & FS_DQ_BWARNS)
+			mp->m_quotainfo->qi_bwarnlimit = newlim->d_bwarns;
+		if (newlim->d_fieldmask & FS_DQ_IWARNS)
+			mp->m_quotainfo->qi_iwarnlimit = newlim->d_iwarns;
+		if (newlim->d_fieldmask & FS_DQ_RTBWARNS)
+			mp->m_quotainfo->qi_rtbwarnlimit = newlim->d_rtbwarns;
+	} else {
 		/*
 		 * If the user is now over quota, start the timelimit.
 		 * The user will not be 'warned'.
@@ -776,9 +805,9 @@
 	xfs_qoff_logitem_t	*startqoff,
 	uint			flags)
 {
-	xfs_trans_t	       *tp;
+	xfs_trans_t		*tp;
 	int			error;
-	xfs_qoff_logitem_t     *qoffi;
+	xfs_qoff_logitem_t	*qoffi;
 
 	tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QUOTAOFF_END);
 
@@ -928,18 +957,26 @@
 
 STATIC uint
 xfs_qm_import_qtype_flags(
-	uint uflags)
+	uint		uflags)
 {
+	uint		oflags = 0;
+
 	/*
-	 * Can't be both at the same time.
+	 * Can't be more than one, or none.
 	 */
 	if (((uflags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) ==
-	     (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) ||
-	    ((uflags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) == 0))
+			(XFS_GROUP_QUOTA | XFS_USER_QUOTA)) ||
+	    ((uflags & (XFS_GROUP_QUOTA | XFS_PROJ_QUOTA)) ==
+			(XFS_GROUP_QUOTA | XFS_PROJ_QUOTA)) ||
+	    ((uflags & (XFS_USER_QUOTA | XFS_PROJ_QUOTA)) ==
+			(XFS_USER_QUOTA | XFS_PROJ_QUOTA)) ||
+	    ((uflags & (XFS_GROUP_QUOTA|XFS_USER_QUOTA|XFS_PROJ_QUOTA)) == 0))
 		return (0);
 
-	return (uflags & XFS_USER_QUOTA) ?
-		XFS_DQ_USER : XFS_DQ_GROUP;
+	oflags |= (uflags & XFS_USER_QUOTA) ? XFS_DQ_USER : 0;
+	oflags |= (uflags & XFS_PROJ_QUOTA) ? XFS_DQ_PROJ : 0;
+	oflags |= (uflags & XFS_GROUP_QUOTA) ? XFS_DQ_GROUP: 0;
+	return oflags;
 }
 
 STATIC uint
@@ -947,14 +984,19 @@
 	uint flags)
 {
 	/*
-	 * Can't be both at the same time.
+	 * Can't be more than one, or none.
 	 */
-	ASSERT((flags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) !=
-		(XFS_GROUP_QUOTA | XFS_USER_QUOTA));
-	ASSERT((flags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) != 0);
+	ASSERT((flags & (XFS_PROJ_QUOTA | XFS_USER_QUOTA)) !=
+		(XFS_PROJ_QUOTA | XFS_USER_QUOTA));
+	ASSERT((flags & (XFS_PROJ_QUOTA | XFS_GROUP_QUOTA)) !=
+		(XFS_PROJ_QUOTA | XFS_GROUP_QUOTA));
+	ASSERT((flags & (XFS_USER_QUOTA | XFS_GROUP_QUOTA)) !=
+		(XFS_USER_QUOTA | XFS_GROUP_QUOTA));
+	ASSERT((flags & (XFS_PROJ_QUOTA|XFS_USER_QUOTA|XFS_GROUP_QUOTA)) != 0);
 
 	return (flags & XFS_DQ_USER) ?
-		XFS_USER_QUOTA : XFS_GROUP_QUOTA;
+		XFS_USER_QUOTA : (flags & XFS_DQ_PROJ) ?
+			XFS_PROJ_QUOTA : XFS_GROUP_QUOTA;
 }
 
 STATIC uint
@@ -965,12 +1007,14 @@
 
 	if (uflags & XFS_QUOTA_UDQ_ACCT)
 		flags |= XFS_UQUOTA_ACCT;
+	if (uflags & XFS_QUOTA_PDQ_ACCT)
+		flags |= XFS_PQUOTA_ACCT;
 	if (uflags & XFS_QUOTA_GDQ_ACCT)
 		flags |= XFS_GQUOTA_ACCT;
 	if (uflags & XFS_QUOTA_UDQ_ENFD)
 		flags |= XFS_UQUOTA_ENFD;
-	if (uflags & XFS_QUOTA_GDQ_ENFD)
-		flags |= XFS_GQUOTA_ENFD;
+	if (uflags & (XFS_QUOTA_PDQ_ENFD|XFS_QUOTA_GDQ_ENFD))
+		flags |= XFS_OQUOTA_ENFD;
 	return (flags);
 }
 
@@ -984,12 +1028,16 @@
 	uflags = 0;
 	if (flags & XFS_UQUOTA_ACCT)
 		uflags |= XFS_QUOTA_UDQ_ACCT;
+	if (flags & XFS_PQUOTA_ACCT)
+		uflags |= XFS_QUOTA_PDQ_ACCT;
 	if (flags & XFS_GQUOTA_ACCT)
 		uflags |= XFS_QUOTA_GDQ_ACCT;
 	if (flags & XFS_UQUOTA_ENFD)
 		uflags |= XFS_QUOTA_UDQ_ENFD;
-	if (flags & XFS_GQUOTA_ENFD)
-		uflags |= XFS_QUOTA_GDQ_ENFD;
+	if (flags & (XFS_OQUOTA_ENFD)) {
+		uflags |= (flags & XFS_GQUOTA_ACCT) ?
+			XFS_QUOTA_GDQ_ENFD : XFS_QUOTA_PDQ_ENFD;
+	}
 	return (uflags);
 }
 
@@ -1070,7 +1118,7 @@
 			xfs_qm_dqrele(ip->i_udquot);
 			ip->i_udquot = NULL;
 		}
-		if ((flags & XFS_GQUOTA_ACCT) && ip->i_gdquot) {
+		if (flags & (XFS_PQUOTA_ACCT|XFS_GQUOTA_ACCT) && ip->i_gdquot) {
 			xfs_qm_dqrele(ip->i_gdquot);
 			ip->i_gdquot = NULL;
 		}
@@ -1160,7 +1208,6 @@
 {
 	cmn_err(CE_DEBUG, "-----------DQTEST DQUOT----------------");
 	cmn_err(CE_DEBUG, "---- dquot ID = %d", d->d_id);
-	cmn_err(CE_DEBUG, "---- type     = %s", XFS_QM_ISUDQ(d)? "USR" : "GRP");
 	cmn_err(CE_DEBUG, "---- fs       = 0x%p", d->q_mount);
 	cmn_err(CE_DEBUG, "---- bcount   = %Lu (0x%x)",
 		d->d_bcount, (int)d->d_bcount);
@@ -1231,7 +1278,7 @@
 #ifdef QUOTADEBUG
 	if (!err) {
 		cmn_err(CE_DEBUG, "%d [%s] [0x%p] qchecked",
-			d->d_id, XFS_QM_ISUDQ(d) ? "USR" : "GRP", d->q_mount);
+			d->d_id, DQFLAGTO_TYPESTR(d), d->q_mount);
 	}
 #endif
 	return (err);
@@ -1287,6 +1334,7 @@
 xfs_qm_internalqcheck_get_dquots(
 	xfs_mount_t	*mp,
 	xfs_dqid_t	uid,
+	xfs_dqid_t	projid,
 	xfs_dqid_t	gid,
 	xfs_dqtest_t	**ud,
 	xfs_dqtest_t	**gd)
@@ -1295,6 +1343,8 @@
 		xfs_qm_internalqcheck_dqget(mp, uid, XFS_DQ_USER, ud);
 	if (XFS_IS_GQUOTA_ON(mp))
 		xfs_qm_internalqcheck_dqget(mp, gid, XFS_DQ_GROUP, gd);
+	else if (XFS_IS_PQUOTA_ON(mp))
+		xfs_qm_internalqcheck_dqget(mp, projid, XFS_DQ_PROJ, gd);
 }
 
 
@@ -1362,13 +1412,14 @@
 	}
 	xfs_qm_internalqcheck_get_dquots(mp,
 					(xfs_dqid_t) ip->i_d.di_uid,
+					(xfs_dqid_t) ip->i_d.di_projid,
 					(xfs_dqid_t) ip->i_d.di_gid,
 					&ud, &gd);
 	if (XFS_IS_UQUOTA_ON(mp)) {
 		ASSERT(ud);
 		xfs_qm_internalqcheck_dqadjust(ip, ud);
 	}
-	if (XFS_IS_GQUOTA_ON(mp)) {
+	if (XFS_IS_OQUOTA_ON(mp)) {
 		ASSERT(gd);
 		xfs_qm_internalqcheck_dqadjust(ip, gd);
 	}
diff --git a/fs/xfs/quota/xfs_quota_priv.h b/fs/xfs/quota/xfs_quota_priv.h
index 414b600..bf413e7 100644
--- a/fs/xfs/quota/xfs_quota_priv.h
+++ b/fs/xfs/quota/xfs_quota_priv.h
@@ -56,6 +56,7 @@
 #define XFS_QI_RTBTIMELIMIT(mp) ((mp)->m_quotainfo->qi_rtbtimelimit)
 #define XFS_QI_ITIMELIMIT(mp)	((mp)->m_quotainfo->qi_itimelimit)
 #define XFS_QI_BWARNLIMIT(mp)	((mp)->m_quotainfo->qi_bwarnlimit)
+#define XFS_QI_RTBWARNLIMIT(mp)	((mp)->m_quotainfo->qi_rtbwarnlimit)
 #define XFS_QI_IWARNLIMIT(mp)	((mp)->m_quotainfo->qi_iwarnlimit)
 #define XFS_QI_QOFFLOCK(mp)	((mp)->m_quotainfo->qi_quotaofflock)
 
@@ -102,7 +103,8 @@
 				     (xfs_Gqm->qm_grp_dqhtable + \
 				      XFS_DQ_HASHVAL(mp, id)))
 #define XFS_IS_DQTYPE_ON(mp, type)   (type == XFS_DQ_USER ? \
-				      XFS_IS_UQUOTA_ON(mp):XFS_IS_GQUOTA_ON(mp))
+					XFS_IS_UQUOTA_ON(mp) : \
+					XFS_IS_OQUOTA_ON(mp))
 #define XFS_IS_DQUOT_UNINITIALIZED(dqp) ( \
 	!dqp->q_core.d_blk_hardlimit && \
 	!dqp->q_core.d_blk_softlimit && \
@@ -177,16 +179,11 @@
 	(!((dqp)->q_core.d_id))
 
 #define XFS_PURGE_INODE(ip)		\
-	{				\
-	  vmap_t dqvmap;		\
-	  vnode_t *dqvp;		\
-	  dqvp = XFS_ITOV(ip);		\
-	  VMAP(dqvp, dqvmap);		\
-	  VN_RELE(dqvp);		\
-	}
+	IRELE(ip);
 
 #define DQFLAGTO_TYPESTR(d)	(((d)->dq_flags & XFS_DQ_USER) ? "USR" : \
-				 (((d)->dq_flags & XFS_DQ_GROUP) ? "GRP" : "???"))
+				 (((d)->dq_flags & XFS_DQ_GROUP) ? "GRP" : \
+				 (((d)->dq_flags & XFS_DQ_PROJ) ? "PRJ":"???")))
 #define DQFLAGTO_DIRTYSTR(d)	(XFS_DQ_IS_DIRTY(d) ? "DIRTY" : "NOTDIRTY")
 
 #endif	/* __XFS_QUOTA_PRIV_H__ */
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c
index 149b2a1..3b99daf 100644
--- a/fs/xfs/quota/xfs_trans_dquot.c
+++ b/fs/xfs/quota/xfs_trans_dquot.c
@@ -187,7 +187,7 @@
 /*
  * Wrap around mod_dquot to account for both user and group quotas.
  */
-void
+STATIC void
 xfs_trans_mod_dquot_byino(
 	xfs_trans_t	*tp,
 	xfs_inode_t	*ip,
@@ -207,12 +207,10 @@
 	if (tp->t_dqinfo == NULL)
 		xfs_trans_alloc_dqinfo(tp);
 
-	if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot) {
+	if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot)
 		(void) xfs_trans_mod_dquot(tp, ip->i_udquot, field, delta);
-	}
-	if (XFS_IS_GQUOTA_ON(mp) && ip->i_gdquot) {
+	if (XFS_IS_OQUOTA_ON(mp) && ip->i_gdquot)
 		(void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta);
-	}
 }
 
 STATIC xfs_dqtrx_t *
@@ -368,7 +366,7 @@
  * Unreserve just the reservations done by this transaction.
  * dquot is still left locked at exit.
  */
-void
+STATIC void
 xfs_trans_apply_dquot_deltas(
 	xfs_trans_t		*tp)
 {
@@ -499,7 +497,7 @@
 			 * Adjust the RT reservation.
 			 */
 			if (qtrx->qt_rtblk_res != 0) {
-				if (qtrx->qt_blk_res != qtrx->qt_blk_res_used) {
+				if (qtrx->qt_rtblk_res != qtrx->qt_rtblk_res_used) {
 					if (qtrx->qt_rtblk_res >
 					    qtrx->qt_rtblk_res_used)
 					       dqp->q_res_rtbcount -= (xfs_qcnt_t)
@@ -532,12 +530,6 @@
 					    (xfs_qcnt_t)qtrx->qt_icount_delta;
 			}
 
-
-#ifdef QUOTADEBUG
-			if (qtrx->qt_rtblk_res != 0)
-				cmn_err(CE_DEBUG, "RT res %d for 0x%p\n",
-					(int) qtrx->qt_rtblk_res, dqp);
-#endif
 			ASSERT(dqp->q_res_bcount >=
 				INT_GET(dqp->q_core.d_bcount, ARCH_CONVERT));
 			ASSERT(dqp->q_res_icount >=
@@ -638,7 +630,10 @@
 	int		error;
 	xfs_qcnt_t	hardlimit;
 	xfs_qcnt_t	softlimit;
-	time_t		btimer;
+	time_t		timer;
+	xfs_qwarncnt_t	warns;
+	xfs_qwarncnt_t	warnlimit;
+	xfs_qcnt_t	count;
 	xfs_qcnt_t	*resbcountp;
 	xfs_quotainfo_t	*q = mp->m_quotainfo;
 
@@ -653,7 +648,9 @@
 		softlimit = INT_GET(dqp->q_core.d_blk_softlimit, ARCH_CONVERT);
 		if (!softlimit)
 			softlimit = q->qi_bsoftlimit;
-		btimer = INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT);
+		timer = INT_GET(dqp->q_core.d_btimer, ARCH_CONVERT);
+		warns = INT_GET(dqp->q_core.d_bwarns, ARCH_CONVERT);
+		warnlimit = XFS_QI_BWARNLIMIT(dqp->q_mount);
 		resbcountp = &dqp->q_res_bcount;
 	} else {
 		ASSERT(flags & XFS_TRANS_DQ_RES_RTBLKS);
@@ -663,7 +660,9 @@
 		softlimit = INT_GET(dqp->q_core.d_rtb_softlimit, ARCH_CONVERT);
 		if (!softlimit)
 			softlimit = q->qi_rtbsoftlimit;
-		btimer = INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT);
+		timer = INT_GET(dqp->q_core.d_rtbtimer, ARCH_CONVERT);
+		warns = INT_GET(dqp->q_core.d_rtbwarns, ARCH_CONVERT);
+		warnlimit = XFS_QI_RTBWARNLIMIT(dqp->q_mount);
 		resbcountp = &dqp->q_res_rtbcount;
 	}
 	error = 0;
@@ -693,37 +692,36 @@
 				 * If timer or warnings has expired,
 				 * return EDQUOT
 				 */
-				if ((btimer != 0 && get_seconds() > btimer) ||
-				    (dqp->q_core.d_bwarns &&
-				     INT_GET(dqp->q_core.d_bwarns, ARCH_CONVERT) >=
-				     XFS_QI_BWARNLIMIT(dqp->q_mount))) {
+				if ((timer != 0 && get_seconds() > timer) ||
+				    (warns != 0 && warns >= warnlimit)) {
 					error = EDQUOT;
 					goto error_return;
 				}
 			}
 		}
 		if (ninos > 0) {
-			hardlimit = INT_GET(dqp->q_core.d_ino_hardlimit, ARCH_CONVERT);
+			count = INT_GET(dqp->q_core.d_icount, ARCH_CONVERT);
+			timer = INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT);
+			warns = INT_GET(dqp->q_core.d_iwarns, ARCH_CONVERT);
+			warnlimit = XFS_QI_IWARNLIMIT(dqp->q_mount);
+			hardlimit = INT_GET(dqp->q_core.d_ino_hardlimit,
+						ARCH_CONVERT);
 			if (!hardlimit)
 				hardlimit = q->qi_ihardlimit;
-			softlimit = INT_GET(dqp->q_core.d_ino_softlimit, ARCH_CONVERT);
+			softlimit = INT_GET(dqp->q_core.d_ino_softlimit,
+						ARCH_CONVERT);
 			if (!softlimit)
 				softlimit = q->qi_isoftlimit;
-			if (hardlimit > 0ULL &&
-			    INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= hardlimit) {
+			if (hardlimit > 0ULL && count >= hardlimit) {
 				error = EDQUOT;
 				goto error_return;
-			} else if (softlimit > 0ULL &&
-				   INT_GET(dqp->q_core.d_icount, ARCH_CONVERT) >= softlimit) {
+			} else if (softlimit > 0ULL && count >= softlimit) {
 				/*
 				 * If timer or warnings has expired,
 				 * return EDQUOT
 				 */
-				if ((dqp->q_core.d_itimer &&
-				     get_seconds() > INT_GET(dqp->q_core.d_itimer, ARCH_CONVERT)) ||
-				    (dqp->q_core.d_iwarns &&
-				     INT_GET(dqp->q_core.d_iwarns, ARCH_CONVERT) >=
-				     XFS_QI_IWARNLIMIT(dqp->q_mount))) {
+				if ((timer != 0 && get_seconds() > timer) ||
+				     (warns != 0 && warns >= warnlimit)) {
 					error = EDQUOT;
 					goto error_return;
 				}
diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c
index 7d6e1f3..4ed7b69 100644
--- a/fs/xfs/support/debug.c
+++ b/fs/xfs/support/debug.c
@@ -36,7 +36,6 @@
 #include <linux/sched.h>
 #include <linux/kernel.h>
 
-int			doass = 1;
 static char		message[256];	/* keep it off the stack */
 static DEFINE_SPINLOCK(xfs_err_lock);
 
diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h
index 40b0f4c..c5b9365 100644
--- a/fs/xfs/support/debug.h
+++ b/fs/xfs/support/debug.h
@@ -50,16 +50,11 @@
 #endif
 
 #ifdef DEBUG
-# ifdef lint
-#  define ASSERT(EX)	((void)0) /* avoid "constant in conditional" babble */
-# else
-#  define ASSERT(EX) ((!doass||(EX))?((void)0):assfail(#EX, __FILE__, __LINE__))
-# endif	/* lint */
+# define ASSERT(EX)	((EX) ? ((void)0) : assfail(#EX, __FILE__, __LINE__))
 #else
 # define ASSERT(x)	((void)0)
 #endif
 
-extern int doass;		/* dynamically turn off asserts */
 extern void assfail(char *, char *, int);
 #ifdef DEBUG
 extern unsigned long random(void);
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 36603db..dcfe197 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -59,7 +59,7 @@
 #define	XFSA_FIXUP_BNO_OK	1
 #define	XFSA_FIXUP_CNT_OK	2
 
-int
+STATIC int
 xfs_alloc_search_busy(xfs_trans_t *tp,
 		    xfs_agnumber_t agno,
 		    xfs_agblock_t bno,
@@ -2562,7 +2562,7 @@
 /*
  * returns non-zero if any of (agno,bno):len is in a busy list
  */
-int
+STATIC int
 xfs_alloc_search_busy(xfs_trans_t *tp,
 		    xfs_agnumber_t agno,
 		    xfs_agblock_t bno,
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c
index ee8b590..a41ad3a 100644
--- a/fs/xfs/xfs_attr.c
+++ b/fs/xfs/xfs_attr.c
@@ -71,6 +71,11 @@
  * Provide the external interfaces to manage attribute lists.
  */
 
+#define ATTR_SYSCOUNT	2
+STATIC struct attrnames posix_acl_access;
+STATIC struct attrnames posix_acl_default;
+STATIC struct attrnames *attr_system_names[ATTR_SYSCOUNT];
+
 /*========================================================================
  * Function prototypes for the kernel.
  *========================================================================*/
@@ -83,6 +88,7 @@
 /*
  * Internal routines when attribute list is one block.
  */
+STATIC int xfs_attr_leaf_get(xfs_da_args_t *args);
 STATIC int xfs_attr_leaf_addname(xfs_da_args_t *args);
 STATIC int xfs_attr_leaf_removename(xfs_da_args_t *args);
 STATIC int xfs_attr_leaf_list(xfs_attr_list_context_t *context);
@@ -90,6 +96,7 @@
 /*
  * Internal routines when attribute list is more than one block.
  */
+STATIC int xfs_attr_node_get(xfs_da_args_t *args);
 STATIC int xfs_attr_node_addname(xfs_da_args_t *args);
 STATIC int xfs_attr_node_removename(xfs_da_args_t *args);
 STATIC int xfs_attr_node_list(xfs_attr_list_context_t *context);
@@ -1102,7 +1109,7 @@
  * This leaf block cannot have a "remote" value, we only call this routine
  * if bmap_one_block() says there is only one block (ie: no remote blks).
  */
-int
+STATIC int
 xfs_attr_leaf_get(xfs_da_args_t *args)
 {
 	xfs_dabuf_t *bp;
@@ -1707,7 +1714,7 @@
  * block, ie: both true Btree attr lists and for single-leaf-blocks with
  * "remote" values taking up more blocks.
  */
-int
+STATIC int
 xfs_attr_node_get(xfs_da_args_t *args)
 {
 	xfs_da_state_t *state;
@@ -2398,7 +2405,7 @@
 	return xfs_acl_vhasacl_default(vp);
 }
 
-struct attrnames posix_acl_access = {
+STATIC struct attrnames posix_acl_access = {
 	.attr_name	= "posix_acl_access",
 	.attr_namelen	= sizeof("posix_acl_access") - 1,
 	.attr_get	= posix_acl_access_get,
@@ -2407,7 +2414,7 @@
 	.attr_exists	= posix_acl_access_exists,
 };
 
-struct attrnames posix_acl_default = {
+STATIC struct attrnames posix_acl_default = {
 	.attr_name	= "posix_acl_default",
 	.attr_namelen	= sizeof("posix_acl_default") - 1,
 	.attr_get	= posix_acl_default_get,
@@ -2416,7 +2423,7 @@
 	.attr_exists	= posix_acl_default_exists,
 };
 
-struct attrnames *attr_system_names[] =
+STATIC struct attrnames *attr_system_names[] =
 	{ &posix_acl_access, &posix_acl_default };
 
 
diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h
index 67cd0f5..45ab1c5 100644
--- a/fs/xfs/xfs_attr.h
+++ b/fs/xfs/xfs_attr.h
@@ -76,11 +76,6 @@
 extern struct attrnames attr_trusted;
 extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT];
 
-#define ATTR_SYSCOUNT	2
-extern struct attrnames posix_acl_access;
-extern struct attrnames posix_acl_default;
-extern struct attrnames *attr_system_names[ATTR_SYSCOUNT];
-
 extern attrnames_t *attr_lookup_namespace(char *, attrnames_t **, int);
 extern int attr_generic_list(struct vnode *, void *, size_t, int, ssize_t *);
 
@@ -184,8 +179,6 @@
 			 struct attrlist_cursor_kern *, struct cred *);
 int xfs_attr_inactive(struct xfs_inode *dp);
 
-int xfs_attr_node_get(struct xfs_da_args *);
-int xfs_attr_leaf_get(struct xfs_da_args *);
 int xfs_attr_shortform_getvalue(struct xfs_da_args *);
 int xfs_attr_fetch(struct xfs_inode *, char *, int,
 			char *, int *, int, struct cred *);
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c
index b11256e..1cdd574 100644
--- a/fs/xfs/xfs_attr_leaf.c
+++ b/fs/xfs/xfs_attr_leaf.c
@@ -79,6 +79,8 @@
 /*
  * Routines used for growing the Btree.
  */
+STATIC int xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t which_block,
+				    xfs_dabuf_t **bpp);
 STATIC int xfs_attr_leaf_add_work(xfs_dabuf_t *leaf_buffer, xfs_da_args_t *args,
 					      int freemap_index);
 STATIC void xfs_attr_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *leaf_buffer);
@@ -92,6 +94,16 @@
 					   int *number_usedbytes_in_blk1);
 
 /*
+ * Routines used for shrinking the Btree.
+ */
+STATIC int xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp,
+				  xfs_dabuf_t *bp, int level);
+STATIC int xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp,
+				  xfs_dabuf_t *bp);
+STATIC int xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp,
+				   xfs_dablk_t blkno, int blkcnt);
+
+/*
  * Utility routines.
  */
 STATIC void xfs_attr_leaf_moveents(xfs_attr_leafblock_t *src_leaf,
@@ -99,6 +111,10 @@
 					 xfs_attr_leafblock_t *dst_leaf,
 					 int dst_start, int move_count,
 					 xfs_mount_t *mp);
+STATIC int xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index);
+STATIC int xfs_attr_put_listent(xfs_attr_list_context_t *context,
+			     attrnames_t *, char *name, int namelen,
+			     int valuelen);
 
 
 /*========================================================================
@@ -774,7 +790,7 @@
  * Create the initial contents of a leaf attribute list
  * or a leaf in a node attribute list.
  */
-int
+STATIC int
 xfs_attr_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
 {
 	xfs_attr_leafblock_t *leaf;
@@ -2209,7 +2225,7 @@
  * Calculate the number of bytes used to store the indicated attribute
  * (whether local or remote only calculate bytes in this block).
  */
-int
+STATIC int
 xfs_attr_leaf_entsize(xfs_attr_leafblock_t *leaf, int index)
 {
 	xfs_attr_leaf_name_local_t *name_loc;
@@ -2380,7 +2396,7 @@
  * we may be reading them directly out of a user buffer.
  */
 /*ARGSUSED*/
-int
+STATIC int
 xfs_attr_put_listent(xfs_attr_list_context_t *context,
 		     attrnames_t *namesp, char *name, int namelen, int valuelen)
 {
@@ -2740,7 +2756,7 @@
  * Recurse (gasp!) through the attribute nodes until we find leaves.
  * We're doing a depth-first traversal in order to invalidate everything.
  */
-int
+STATIC int
 xfs_attr_node_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp,
 				   int level)
 {
@@ -2849,7 +2865,7 @@
  * Note that we must release the lock on the buffer so that we are not
  * caught holding something that the logging code wants to flush to disk.
  */
-int
+STATIC int
 xfs_attr_leaf_inactive(xfs_trans_t **trans, xfs_inode_t *dp, xfs_dabuf_t *bp)
 {
 	xfs_attr_leafblock_t *leaf;
@@ -2934,7 +2950,7 @@
  * Look at all the extents for this logical region,
  * invalidate any buffers that are incore/in transactions.
  */
-int
+STATIC int
 xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp,
 				    xfs_dablk_t blkno, int blkcnt)
 {
diff --git a/fs/xfs/xfs_attr_leaf.h b/fs/xfs/xfs_attr_leaf.h
index b1480e0..0a4cfad 100644
--- a/fs/xfs/xfs_attr_leaf.h
+++ b/fs/xfs/xfs_attr_leaf.h
@@ -261,8 +261,6 @@
 /*
  * Routines used for growing the Btree.
  */
-int	xfs_attr_leaf_create(struct xfs_da_args *args, xfs_dablk_t which_block,
-				    struct xfs_dabuf **bpp);
 int	xfs_attr_leaf_split(struct xfs_da_state *state,
 				   struct xfs_da_state_blk *oldblk,
 				   struct xfs_da_state_blk *newblk);
@@ -284,12 +282,6 @@
 				       struct xfs_da_state_blk *drop_blk,
 				       struct xfs_da_state_blk *save_blk);
 int	xfs_attr_root_inactive(struct xfs_trans **trans, struct xfs_inode *dp);
-int	xfs_attr_node_inactive(struct xfs_trans **trans, struct xfs_inode *dp,
-				      struct xfs_dabuf *bp, int level);
-int	xfs_attr_leaf_inactive(struct xfs_trans **trans, struct xfs_inode *dp,
-				      struct xfs_dabuf *bp);
-int	xfs_attr_leaf_freextent(struct xfs_trans **trans, struct xfs_inode *dp,
-				       xfs_dablk_t blkno, int blkcnt);
 
 /*
  * Utility routines.
@@ -299,10 +291,6 @@
 				   struct xfs_dabuf *leaf2_bp);
 int	xfs_attr_leaf_newentsize(struct xfs_da_args *args, int blocksize,
 					int *local);
-int	xfs_attr_leaf_entsize(struct xfs_attr_leafblock *leaf, int index);
-int	xfs_attr_put_listent(struct xfs_attr_list_context *context,
-			     struct attrnames *, char *name, int namelen,
-			     int valuelen);
 int	xfs_attr_rolltrans(struct xfs_trans **transp, struct xfs_inode *dp);
 
 #endif	/* __XFS_ATTR_LEAF_H__ */
diff --git a/fs/xfs/xfs_bit.c b/fs/xfs/xfs_bit.c
index a20a6c3..76c9ad3 100644
--- a/fs/xfs/xfs_bit.c
+++ b/fs/xfs/xfs_bit.c
@@ -45,7 +45,7 @@
 /*
  * Index of high bit number in byte, -1 for none set, 0..7 otherwise.
  */
-const char xfs_highbit[256] = {
+STATIC const char xfs_highbit[256] = {
        -1, 0, 1, 1, 2, 2, 2, 2,			/* 00 .. 07 */
 	3, 3, 3, 3, 3, 3, 3, 3,			/* 08 .. 0f */
 	4, 4, 4, 4, 4, 4, 4, 4,			/* 10 .. 17 */
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index de31624..6f5d283 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -301,6 +301,19 @@
 	xfs_bmbt_irec_t	*gotp,		/* out: extent entry found */
 	xfs_bmbt_irec_t	*prevp);	/* out: previous extent entry found */
 
+/*
+ * Check the last inode extent to determine whether this allocation will result
+ * in blocks being allocated at the end of the file. When we allocate new data
+ * blocks at the end of the file which do not start at the previous data block,
+ * we will try to align the new blocks at stripe unit boundaries.
+ */
+STATIC int				/* error */
+xfs_bmap_isaeof(
+	xfs_inode_t	*ip,		/* incore inode pointer */
+	xfs_fileoff_t   off,		/* file offset in fsblocks */
+	int             whichfork,	/* data or attribute fork */
+	char		*aeof);		/* return value */
+
 #ifdef XFS_BMAP_TRACE
 /*
  * Add a bmap trace buffer entry.  Base routine for the others.
@@ -4532,18 +4545,17 @@
 	xfs_extlen_t	alen;		/* allocated extent length */
 	xfs_fileoff_t	aoff;		/* allocated file offset */
 	xfs_bmalloca_t	bma;		/* args for xfs_bmap_alloc */
-	char		contig;		/* allocation must be one extent */
 	xfs_btree_cur_t	*cur;		/* bmap btree cursor */
-	char		delay;		/* this request is for delayed alloc */
 	xfs_fileoff_t	end;		/* end of mapped file region */
 	int		eof;		/* we've hit the end of extent list */
+	char		contig;		/* allocation must be one extent */
+	char		delay;		/* this request is for delayed alloc */
+	char		exact;		/* don't do all of wasdelayed extent */
 	xfs_bmbt_rec_t	*ep;		/* extent list entry pointer */
 	int		error;		/* error return */
-	char		exact;		/* don't do all of wasdelayed extent */
 	xfs_bmbt_irec_t	got;		/* current extent list record */
 	xfs_ifork_t	*ifp;		/* inode fork pointer */
 	xfs_extlen_t	indlen;		/* indirect blocks length */
-	char		inhole;		/* current location is hole in file */
 	xfs_extnum_t	lastx;		/* last useful extent number */
 	int		logflags;	/* flags for transaction logging */
 	xfs_extlen_t	minleft;	/* min blocks left after allocation */
@@ -4554,13 +4566,15 @@
 	xfs_extnum_t	nextents;	/* number of extents in file */
 	xfs_fileoff_t	obno;		/* old block number (offset) */
 	xfs_bmbt_irec_t	prev;		/* previous extent list record */
-	char		stateless;	/* ignore state flag set */
 	int		tmp_logflags;	/* temp flags holder */
+	int		whichfork;	/* data or attr fork */
+	char		inhole;		/* current location is hole in file */
+	char		stateless;	/* ignore state flag set */
 	char		trim;		/* output trimmed to match range */
 	char		userdata;	/* allocating non-metadata */
 	char		wasdelay;	/* old extent was delayed */
-	int		whichfork;	/* data or attr fork */
 	char		wr;		/* this is a write request */
+	char		rt;		/* this is a realtime file */
 	char		rsvd;		/* OK to allocate reserved blocks */
 #ifdef DEBUG
 	xfs_fileoff_t	orig_bno;	/* original block number value */
@@ -4590,6 +4604,7 @@
 	}
 	if (XFS_FORCED_SHUTDOWN(mp))
 		return XFS_ERROR(EIO);
+	rt = XFS_IS_REALTIME_INODE(ip);
 	ifp = XFS_IFORK_PTR(ip, whichfork);
 	ASSERT(ifp->if_ext_max ==
 	       XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t));
@@ -4694,9 +4709,16 @@
 			}
 			minlen = contig ? alen : 1;
 			if (delay) {
-				indlen = (xfs_extlen_t)
-					xfs_bmap_worst_indlen(ip, alen);
-				ASSERT(indlen > 0);
+				xfs_extlen_t	extsz = 0;
+
+				/* Figure out the extent size, adjust alen */
+				if (rt) {
+					if (!(extsz = ip->i_d.di_extsize))
+						extsz = mp->m_sb.sb_rextsize;
+					alen = roundup(alen, extsz);
+					extsz = alen / mp->m_sb.sb_rextsize;
+				}
+
 				/*
 				 * Make a transaction-less quota reservation for
 				 * delayed allocation blocks. This number gets
@@ -4704,8 +4726,10 @@
 				 * We return EDQUOT if we haven't allocated
 				 * blks already inside this loop;
 				 */
-				if (XFS_TRANS_RESERVE_BLKQUOTA(
-						mp, NULL, ip, (long)alen)) {
+				if (XFS_TRANS_RESERVE_QUOTA_NBLKS(
+						mp, NULL, ip, (long)alen, 0,
+						rt ? XFS_QMOPT_RES_RTBLKS :
+						     XFS_QMOPT_RES_REGBLKS)) {
 					if (n == 0) {
 						*nmap = 0;
 						ASSERT(cur == NULL);
@@ -4718,40 +4742,34 @@
 				 * Split changing sb for alen and indlen since
 				 * they could be coming from different places.
 				 */
-				if (ip->i_d.di_flags & XFS_DIFLAG_REALTIME) {
-					xfs_extlen_t	extsz;
-					xfs_extlen_t	ralen;
-					if (!(extsz = ip->i_d.di_extsize))
-						extsz = mp->m_sb.sb_rextsize;
-					ralen = roundup(alen, extsz);
-					ralen = ralen / mp->m_sb.sb_rextsize;
-					if (xfs_mod_incore_sb(mp,
-						XFS_SBS_FREXTENTS,
-						-(ralen), rsvd)) {
-						if (XFS_IS_QUOTA_ON(ip->i_mount))
-							XFS_TRANS_UNRESERVE_BLKQUOTA(
-						     		mp, NULL, ip,
-								(long)alen);
-						break;
-					}
-				} else {
-					if (xfs_mod_incore_sb(mp,
-							      XFS_SBS_FDBLOCKS,
-							      -(alen), rsvd)) {
-						if (XFS_IS_QUOTA_ON(ip->i_mount))
-							XFS_TRANS_UNRESERVE_BLKQUOTA(
-								mp, NULL, ip,
-								(long)alen);
-						break;
-					}
-				}
+				indlen = (xfs_extlen_t)
+					xfs_bmap_worst_indlen(ip, alen);
+				ASSERT(indlen > 0);
 
-				if (xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
-						-(indlen), rsvd)) {
-					XFS_TRANS_UNRESERVE_BLKQUOTA(
-						mp, NULL, ip, (long)alen);
+				if (rt)
+					error = xfs_mod_incore_sb(mp,
+							XFS_SBS_FREXTENTS,
+							-(extsz), rsvd);
+				else
+					error = xfs_mod_incore_sb(mp,
+							XFS_SBS_FDBLOCKS,
+							-(alen), rsvd);
+				if (!error)
+					error = xfs_mod_incore_sb(mp,
+							XFS_SBS_FDBLOCKS,
+							-(indlen), rsvd);
+
+				if (error) {
+					if (XFS_IS_QUOTA_ON(ip->i_mount))
+						/* unreserve the blocks now */
+						XFS_TRANS_UNRESERVE_QUOTA_NBLKS(
+							mp, NULL, ip,
+							(long)alen, 0, rt ?
+							XFS_QMOPT_RES_RTBLKS :
+							XFS_QMOPT_RES_REGBLKS);
 					break;
 				}
+
 				ip->i_delayed_blks += alen;
 				abno = NULLSTARTBLOCK(indlen);
 			} else {
@@ -5376,13 +5394,24 @@
 		}
 		if (wasdel) {
 			ASSERT(STARTBLOCKVAL(del.br_startblock) > 0);
-			xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
-				(int)del.br_blockcount, rsvd);
-			/* Unreserve our quota space */
-			XFS_TRANS_RESERVE_QUOTA_NBLKS(
-				mp, NULL, ip, -((long)del.br_blockcount), 0,
-				isrt ?	XFS_QMOPT_RES_RTBLKS :
+			/* Update realtim/data freespace, unreserve quota */
+			if (isrt) {
+				xfs_filblks_t rtexts;
+
+				rtexts = XFS_FSB_TO_B(mp, del.br_blockcount);
+				do_div(rtexts, mp->m_sb.sb_rextsize);
+				xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS,
+						(int)rtexts, rsvd);
+				XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, NULL, ip,
+					-((long)del.br_blockcount), 0,
+					XFS_QMOPT_RES_RTBLKS);
+			} else {
+				xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS,
+						(int)del.br_blockcount, rsvd);
+				XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, NULL, ip,
+					-((long)del.br_blockcount), 0,
 					XFS_QMOPT_RES_REGBLKS);
+			}
 			ip->i_delayed_blks -= del.br_blockcount;
 			if (cur)
 				cur->bc_private.b.flags |=
@@ -5714,7 +5743,7 @@
  * blocks at the end of the file which do not start at the previous data block,
  * we will try to align the new blocks at stripe unit boundaries.
  */
-int					/* error */
+STATIC int				/* error */
 xfs_bmap_isaeof(
 	xfs_inode_t	*ip,		/* incore inode pointer */
 	xfs_fileoff_t   off,		/* file offset in fsblocks */
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h
index f1bc22f..e6d22ec 100644
--- a/fs/xfs/xfs_bmap.h
+++ b/fs/xfs/xfs_bmap.h
@@ -332,19 +332,6 @@
 	int			iflags);	/* interface flags */
 
 /*
- * Check the last inode extent to determine whether this allocation will result
- * in blocks being allocated at the end of the file. When we allocate new data
- * blocks at the end of the file which do not start at the previous data block,
- * we will try to align the new blocks at stripe unit boundaries.
- */
-int
-xfs_bmap_isaeof(
-	struct xfs_inode	*ip,
-	xfs_fileoff_t		off,
-	int			whichfork,
-	char			*aeof);
-
-/*
  * Check if the endoff is outside the last extent. If so the caller will grow
  * the allocation to a stripe unit boundary
  */
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index 163305a..09c4135 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -2331,20 +2331,6 @@
 	return xfs_bmbt_lookup(cur, XFS_LOOKUP_GE, stat);
 }
 
-int					/* error */
-xfs_bmbt_lookup_le(
-	xfs_btree_cur_t	*cur,
-	xfs_fileoff_t	off,
-	xfs_fsblock_t	bno,
-	xfs_filblks_t	len,
-	int		*stat)		/* success/failure */
-{
-	cur->bc_rec.b.br_startoff = off;
-	cur->bc_rec.b.br_startblock = bno;
-	cur->bc_rec.b.br_blockcount = len;
-	return xfs_bmbt_lookup(cur, XFS_LOOKUP_LE, stat);
-}
-
 /*
  * Give the bmap btree a new root block.  Copy the old broot contents
  * down into a real block and make the broot point to it.
diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h
index 843ff12..0a40cf1 100644
--- a/fs/xfs/xfs_bmap_btree.h
+++ b/fs/xfs/xfs_bmap_btree.h
@@ -580,14 +580,6 @@
 	xfs_filblks_t,
 	int *);
 
-int
-xfs_bmbt_lookup_le(
-	struct xfs_btree_cur *,
-	xfs_fileoff_t,
-	xfs_fsblock_t,
-	xfs_filblks_t,
-	int *);
-
 /*
  * Give the bmap btree a new root block.  Copy the old broot contents
  * down into a real block and make the broot point to it.
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c
index 9dd22dd..0cc63d6 100644
--- a/fs/xfs/xfs_btree.c
+++ b/fs/xfs/xfs_btree.c
@@ -90,6 +90,16 @@
  */
 
 /*
+ * Retrieve the block pointer from the cursor at the given level.
+ * This may be a bmap btree root or from a buffer.
+ */
+STATIC xfs_btree_block_t *			/* generic btree block pointer */
+xfs_btree_get_block(
+	xfs_btree_cur_t		*cur,	/* btree cursor */
+	int			level,	/* level in btree */
+	struct xfs_buf		**bpp);	/* buffer containing the block */
+
+/*
  * Checking routine: return maxrecs for the block.
  */
 STATIC int				/* number of records fitting in block */
@@ -497,7 +507,7 @@
  * Retrieve the block pointer from the cursor at the given level.
  * This may be a bmap btree root or from a buffer.
  */
-xfs_btree_block_t *			/* generic btree block pointer */
+STATIC xfs_btree_block_t *		/* generic btree block pointer */
 xfs_btree_get_block(
 	xfs_btree_cur_t		*cur,	/* btree cursor */
 	int			level,	/* level in btree */
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h
index 93872bb..09b4e15 100644
--- a/fs/xfs/xfs_btree.h
+++ b/fs/xfs/xfs_btree.h
@@ -325,16 +325,6 @@
 	int			level);	/* level to change */
 
 /*
- * Retrieve the block pointer from the cursor at the given level.
- * This may be a bmap btree root or from a buffer.
- */
-xfs_btree_block_t *			/* generic btree block pointer */
-xfs_btree_get_block(
-	xfs_btree_cur_t		*cur,	/* btree cursor */
-	int			level,	/* level in btree */
-	struct xfs_buf		**bpp);	/* buffer containing the block */
-
-/*
  * Get a buffer for the block, return it with no data read.
  * Long-form addressing.
  */
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 9ab0039..30b8285 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -172,7 +172,7 @@
  *
  * If the XFS_BLI_STALE flag has been set, then log nothing.
  */
-uint
+STATIC uint
 xfs_buf_item_size(
 	xfs_buf_log_item_t	*bip)
 {
@@ -240,7 +240,7 @@
  * format structure, and the rest point to contiguous chunks
  * within the buffer.
  */
-void
+STATIC void
 xfs_buf_item_format(
 	xfs_buf_log_item_t	*bip,
 	xfs_log_iovec_t		*log_vector)
@@ -365,7 +365,7 @@
  * item in memory so it cannot be written out.  Simply call bpin()
  * on the buffer to do this.
  */
-void
+STATIC void
 xfs_buf_item_pin(
 	xfs_buf_log_item_t	*bip)
 {
@@ -391,7 +391,7 @@
  * If the XFS_BLI_STALE flag is set and we are the last reference,
  * then free up the buf log item and unlock the buffer.
  */
-void
+STATIC void
 xfs_buf_item_unpin(
 	xfs_buf_log_item_t	*bip,
 	int			stale)
@@ -446,7 +446,7 @@
  * so we need to free the item's descriptor (that points to the item)
  * in the transaction.
  */
-void
+STATIC void
 xfs_buf_item_unpin_remove(
 	xfs_buf_log_item_t	*bip,
 	xfs_trans_t		*tp)
@@ -493,7 +493,7 @@
  * the lock right away, return 0.  If we can get the lock, pull the
  * buffer from the free list, mark it busy, and return 1.
  */
-uint
+STATIC uint
 xfs_buf_item_trylock(
 	xfs_buf_log_item_t	*bip)
 {
@@ -537,7 +537,7 @@
  * This is for support of xfs_trans_bhold(). Make sure the
  * XFS_BLI_HOLD field is cleared if we don't free the item.
  */
-void
+STATIC void
 xfs_buf_item_unlock(
 	xfs_buf_log_item_t	*bip)
 {
@@ -635,7 +635,7 @@
  * by returning the original lsn of that transaction here rather than
  * the current one.
  */
-xfs_lsn_t
+STATIC xfs_lsn_t
 xfs_buf_item_committed(
 	xfs_buf_log_item_t	*bip,
 	xfs_lsn_t		lsn)
@@ -654,7 +654,7 @@
  * and have aborted this transaction, we'll trap this buffer when it tries to
  * get written out.
  */
-void
+STATIC void
 xfs_buf_item_abort(
 	xfs_buf_log_item_t	*bip)
 {
@@ -674,7 +674,7 @@
  * B_DELWRI set, then get it going out to disk with a call to bawrite().
  * If not, then just release the buffer.
  */
-void
+STATIC void
 xfs_buf_item_push(
 	xfs_buf_log_item_t	*bip)
 {
@@ -693,7 +693,7 @@
 }
 
 /* ARGSUSED */
-void
+STATIC void
 xfs_buf_item_committing(xfs_buf_log_item_t *bip, xfs_lsn_t commit_lsn)
 {
 }
@@ -701,7 +701,7 @@
 /*
  * This is the ops vector shared by all buf log items.
  */
-struct xfs_item_ops xfs_buf_item_ops = {
+STATIC struct xfs_item_ops xfs_buf_item_ops = {
 	.iop_size	= (uint(*)(xfs_log_item_t*))xfs_buf_item_size,
 	.iop_format	= (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
 					xfs_buf_item_format,
diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h
index 5f1b0c9..01aed5f 100644
--- a/fs/xfs/xfs_buf_item.h
+++ b/fs/xfs/xfs_buf_item.h
@@ -80,7 +80,7 @@
  * user or group dquots and may require special recovery handling.
  */
 #define	XFS_BLI_UDQUOT_BUF	0x4
-/* #define XFS_BLI_PDQUOT_BUF	0x8 */
+#define XFS_BLI_PDQUOT_BUF	0x8
 #define	XFS_BLI_GDQUOT_BUF	0x10
 
 #define	XFS_BLI_CHUNK		128
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index d7fe288..8b792dd 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -113,7 +113,10 @@
 STATIC uint	xfs_da_node_lasthash(xfs_dabuf_t *bp, int *count);
 STATIC int	xfs_da_node_order(xfs_dabuf_t *node1_bp, xfs_dabuf_t *node2_bp);
 STATIC xfs_dabuf_t *xfs_da_buf_make(int nbuf, xfs_buf_t **bps, inst_t *ra);
-
+STATIC int	xfs_da_blk_unlink(xfs_da_state_t *state,
+				  xfs_da_state_blk_t *drop_blk,
+				  xfs_da_state_blk_t *save_blk);
+STATIC void	xfs_da_state_kill_altpath(xfs_da_state_t *state);
 
 /*========================================================================
  * Routines used for growing the Btree.
@@ -1424,7 +1427,7 @@
 /*
  * Unlink a block from a doubly linked list of blocks.
  */
-int							/* error */
+STATIC int						/* error */
 xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
 				 xfs_da_state_blk_t *save_blk)
 {
@@ -2381,7 +2384,7 @@
 /*
  * Kill the altpath contents of a da-state structure.
  */
-void
+STATIC void
 xfs_da_state_kill_altpath(xfs_da_state_t *state)
 {
 	int	i;
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h
index 9fc699d..3a9b9e8 100644
--- a/fs/xfs/xfs_da_btree.h
+++ b/fs/xfs/xfs_da_btree.h
@@ -296,8 +296,6 @@
 /*
  * Utility routines.
  */
-int	xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk,
-					 xfs_da_state_blk_t *save_blk);
 int	xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk,
 				       xfs_da_state_blk_t *new_blk);
 
@@ -320,7 +318,6 @@
 uint xfs_da_log2_roundup(uint i);
 xfs_da_state_t *xfs_da_state_alloc(void);
 void xfs_da_state_free(xfs_da_state_t *state);
-void xfs_da_state_kill_altpath(xfs_da_state_t *state);
 
 void xfs_da_buf_done(xfs_dabuf_t *dabuf);
 void xfs_da_log_buf(struct xfs_trans *tp, xfs_dabuf_t *dabuf, uint first,
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index 63abdc2..681be5c 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -180,9 +180,10 @@
 		goto error0;
 	}
 
-	if (VN_CACHED(tvp) != 0)
-		xfs_inval_cached_pages(XFS_ITOV(tip), &(tip->i_iocore),
-						(xfs_off_t)0, 0, 0);
+	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);
+	}
 
 	/* Verify O_DIRECT for ftmp */
 	if (VN_CACHED(tvp) != 0) {
diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c
index db9887a..a0aa0e4 100644
--- a/fs/xfs/xfs_dir2_data.c
+++ b/fs/xfs/xfs_dir2_data.c
@@ -304,7 +304,7 @@
 /*
  * Remove a bestfree entry from the table.
  */
-void
+STATIC void
 xfs_dir2_data_freeremove(
 	xfs_dir2_data_t		*d,		/* data block pointer */
 	xfs_dir2_data_free_t	*dfp,		/* bestfree entry pointer */
diff --git a/fs/xfs/xfs_dir2_data.h b/fs/xfs/xfs_dir2_data.h
index 3f02294..476cac9 100644
--- a/fs/xfs/xfs_dir2_data.h
+++ b/fs/xfs/xfs_dir2_data.h
@@ -193,10 +193,6 @@
 				 xfs_dir2_data_unused_t *dup, int *loghead);
 
 extern void
-	xfs_dir2_data_freeremove(xfs_dir2_data_t *d,
-				 xfs_dir2_data_free_t *dfp, int *loghead);
-
-extern void
 	xfs_dir2_data_freescan(struct xfs_mount *mp, xfs_dir2_data_t *d,
 			       int *loghead, char *aendp);
 
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index 262d1e8..056f528 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -77,6 +77,10 @@
 #endif
 static int xfs_dir2_leaf_lookup_int(xfs_da_args_t *args, xfs_dabuf_t **lbpp,
 				    int *indexp, xfs_dabuf_t **dbpp);
+static void xfs_dir2_leaf_log_bests(struct xfs_trans *tp, struct xfs_dabuf *bp,
+				    int first, int last);
+static void xfs_dir2_leaf_log_tail(struct xfs_trans *tp, struct xfs_dabuf *bp);
+
 
 /*
  * Convert a block form directory to a leaf form directory.
@@ -1214,7 +1218,7 @@
 /*
  * Log the bests entries indicated from a leaf1 block.
  */
-void
+static void
 xfs_dir2_leaf_log_bests(
 	xfs_trans_t		*tp,		/* transaction pointer */
 	xfs_dabuf_t		*bp,		/* leaf buffer */
@@ -1278,7 +1282,7 @@
 /*
  * Log the tail of the leaf1 block.
  */
-void
+STATIC void
 xfs_dir2_leaf_log_tail(
 	xfs_trans_t		*tp,		/* transaction pointer */
 	xfs_dabuf_t		*bp)		/* leaf buffer */
diff --git a/fs/xfs/xfs_dir2_leaf.h b/fs/xfs/xfs_dir2_leaf.h
index 7f20eee..3303cd6 100644
--- a/fs/xfs/xfs_dir2_leaf.h
+++ b/fs/xfs/xfs_dir2_leaf.h
@@ -330,15 +330,8 @@
 			       int first, int last);
 
 extern void
-	xfs_dir2_leaf_log_bests(struct xfs_trans *tp, struct xfs_dabuf *bp,
-				int first, int last);
-
-extern void
 	xfs_dir2_leaf_log_header(struct xfs_trans *tp, struct xfs_dabuf *bp);
 
-extern void
-	xfs_dir2_leaf_log_tail(struct xfs_trans *tp, struct xfs_dabuf *bp);
-
 extern int
 	xfs_dir2_leaf_lookup(struct xfs_da_args *args);
 
diff --git a/fs/xfs/xfs_dir_leaf.c b/fs/xfs/xfs_dir_leaf.c
index 617018d..c2ea617 100644
--- a/fs/xfs/xfs_dir_leaf.c
+++ b/fs/xfs/xfs_dir_leaf.c
@@ -91,6 +91,10 @@
 					  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.
  */
@@ -781,7 +785,7 @@
  * Create the initial contents of a leaf directory
  * or a leaf in a node directory.
  */
-int
+STATIC int
 xfs_dir_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp)
 {
 	xfs_dir_leafblock_t *leaf;
diff --git a/fs/xfs/xfs_dir_leaf.h b/fs/xfs/xfs_dir_leaf.h
index 00d68d3..dd423ce 100644
--- a/fs/xfs/xfs_dir_leaf.h
+++ b/fs/xfs/xfs_dir_leaf.h
@@ -202,8 +202,6 @@
 /*
  * Routines used for growing the Btree.
  */
-int	xfs_dir_leaf_create(struct xfs_da_args *args, xfs_dablk_t which_block,
-				   struct xfs_dabuf **bpp);
 int	xfs_dir_leaf_split(struct xfs_da_state *state,
 				  struct xfs_da_state_blk *oldblk,
 				  struct xfs_da_state_blk *newblk);
diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h
index 55ae3e6..55c17ad 100644
--- a/fs/xfs/xfs_dmapi.h
+++ b/fs/xfs/xfs_dmapi.h
@@ -166,27 +166,32 @@
 #define DM_FLAGS_NDELAY		0x001	/* return EAGAIN after dm_pending() */
 #define DM_FLAGS_UNWANTED	0x002	/* event not in fsys dm_eventset_t */
 #define DM_FLAGS_ISEM		0x004	/* thread holds i_sem */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21)
-/* i_alloc_sem was added in 2.4.22-pre1 */
 #define DM_FLAGS_IALLOCSEM_RD	0x010	/* thread holds i_alloc_sem rd */
 #define DM_FLAGS_IALLOCSEM_WR	0x020	/* thread holds i_alloc_sem wr */
-#endif
-#endif
 
 /*
  *	Based on IO_ISDIRECT, decide which i_ flag is set.
  */
-#ifdef DM_FLAGS_IALLOCSEM_RD
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
+#define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
+			      DM_FLAGS_ISEM : 0)
+#define DM_SEM_FLAG_WR	(DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_ISEM)
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) && \
+    (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,22))
 #define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
 			      DM_FLAGS_IALLOCSEM_RD : DM_FLAGS_ISEM)
 #define DM_SEM_FLAG_WR	(DM_FLAGS_IALLOCSEM_WR | DM_FLAGS_ISEM)
-#else
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,21)
 #define DM_SEM_FLAG_RD(ioflags) (((ioflags) & IO_ISDIRECT) ? \
 			      0 : DM_FLAGS_ISEM)
 #define DM_SEM_FLAG_WR	(DM_FLAGS_ISEM)
 #endif
 
+
 /*
  *	Macros to turn caller specified delay/block flags into
  *	dm_send_xxxx_event flag DM_FLAGS_NDELAY.
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index bbe1dea..dcd3fdd 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -280,7 +280,7 @@
 	}
 }
 
-void
+STATIC void
 xfs_hex_dump(void *p, int length)
 {
 	__uint8_t *uip = (__uint8_t*)p;
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h
index 6bc0535..52ee2b9 100644
--- a/fs/xfs/xfs_error.h
+++ b/fs/xfs/xfs_error.h
@@ -73,9 +73,6 @@
 	int		linenum,
 	inst_t		*ra);
 
-extern void
-xfs_hex_dump(void *p, int length);
-
 #define	XFS_ERROR_REPORT(e, lvl, mp)	\
 	xfs_error_report(e, lvl, mp, __FILE__, __LINE__, __return_address)
 #define	XFS_CORRUPTION_ERROR(e, lvl, mp, mem)	\
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index 5eafd5b..db7cbd1 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -59,6 +59,18 @@
 STATIC void	xfs_efd_item_abort(xfs_efd_log_item_t *);
 
 
+void
+xfs_efi_item_free(xfs_efi_log_item_t *efip)
+{
+	int nexts = efip->efi_format.efi_nextents;
+
+	if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
+		kmem_free(efip, sizeof(xfs_efi_log_item_t) +
+				(nexts - 1) * sizeof(xfs_extent_t));
+	} else {
+		kmem_zone_free(xfs_efi_zone, efip);
+	}
+}
 
 /*
  * This returns the number of iovecs needed to log the given efi item.
@@ -120,8 +132,6 @@
 STATIC void
 xfs_efi_item_unpin(xfs_efi_log_item_t *efip, int stale)
 {
-	int		nexts;
-	int		size;
 	xfs_mount_t	*mp;
 	SPLDECL(s);
 
@@ -132,21 +142,11 @@
 		 * xfs_trans_delete_ail() drops the AIL lock.
 		 */
 		xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
-
-		nexts = efip->efi_format.efi_nextents;
-		if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
-			size = sizeof(xfs_efi_log_item_t);
-			size += (nexts - 1) * sizeof(xfs_extent_t);
-			kmem_free(efip, size);
-		} else {
-			kmem_zone_free(xfs_efi_zone, efip);
-		}
+		xfs_efi_item_free(efip);
 	} else {
 		efip->efi_flags |= XFS_EFI_COMMITTED;
 		AIL_UNLOCK(mp, s);
 	}
-
-	return;
 }
 
 /*
@@ -159,8 +159,6 @@
 STATIC void
 xfs_efi_item_unpin_remove(xfs_efi_log_item_t *efip, xfs_trans_t *tp)
 {
-	int		nexts;
-	int		size;
 	xfs_mount_t	*mp;
 	xfs_log_item_desc_t	*lidp;
 	SPLDECL(s);
@@ -178,23 +176,11 @@
 		 * xfs_trans_delete_ail() drops the AIL lock.
 		 */
 		xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
-		/*
-		 * now free the item itself
-		 */
-		nexts = efip->efi_format.efi_nextents;
-		if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
-			size = sizeof(xfs_efi_log_item_t);
-			size += (nexts - 1) * sizeof(xfs_extent_t);
-			kmem_free(efip, size);
-		} else {
-			kmem_zone_free(xfs_efi_zone, efip);
-		}
+		xfs_efi_item_free(efip);
 	} else {
 		efip->efi_flags |= XFS_EFI_COMMITTED;
 		AIL_UNLOCK(mp, s);
 	}
-
-	return;
 }
 
 /*
@@ -245,18 +231,7 @@
 STATIC void
 xfs_efi_item_abort(xfs_efi_log_item_t *efip)
 {
-	int	nexts;
-	int	size;
-
-	nexts = efip->efi_format.efi_nextents;
-	if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
-		size = sizeof(xfs_efi_log_item_t);
-		size += (nexts - 1) * sizeof(xfs_extent_t);
-		kmem_free(efip, size);
-	} else {
-		kmem_zone_free(xfs_efi_zone, efip);
-	}
-	return;
+	xfs_efi_item_free(efip);
 }
 
 /*
@@ -288,7 +263,7 @@
 /*
  * This is the ops vector shared by all efi log items.
  */
-struct xfs_item_ops xfs_efi_item_ops = {
+STATIC struct xfs_item_ops xfs_efi_item_ops = {
 	.iop_size	= (uint(*)(xfs_log_item_t*))xfs_efi_item_size,
 	.iop_format	= (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
 					xfs_efi_item_format,
@@ -355,8 +330,6 @@
 {
 	xfs_mount_t	*mp;
 	int		extents_left;
-	uint		size;
-	int		nexts;
 	SPLDECL(s);
 
 	mp = efip->efi_item.li_mountp;
@@ -372,20 +345,10 @@
 		 * xfs_trans_delete_ail() drops the AIL lock.
 		 */
 		xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
+		xfs_efi_item_free(efip);
 	} else {
 		AIL_UNLOCK(mp, s);
 	}
-
-	if (extents_left == 0) {
-		nexts = efip->efi_format.efi_nextents;
-		if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
-			size = sizeof(xfs_efi_log_item_t);
-			size += (nexts - 1) * sizeof(xfs_extent_t);
-			kmem_free(efip, size);
-		} else {
-			kmem_zone_free(xfs_efi_zone, efip);
-		}
-	}
 }
 
 /*
@@ -398,8 +361,6 @@
 xfs_efi_cancel(
 	xfs_efi_log_item_t	*efip)
 {
-	int		nexts;
-	int		size;
 	xfs_mount_t	*mp;
 	SPLDECL(s);
 
@@ -410,26 +371,25 @@
 		 * xfs_trans_delete_ail() drops the AIL lock.
 		 */
 		xfs_trans_delete_ail(mp, (xfs_log_item_t *)efip, s);
-
-		nexts = efip->efi_format.efi_nextents;
-		if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
-			size = sizeof(xfs_efi_log_item_t);
-			size += (nexts - 1) * sizeof(xfs_extent_t);
-			kmem_free(efip, size);
-		} else {
-			kmem_zone_free(xfs_efi_zone, efip);
-		}
+		xfs_efi_item_free(efip);
 	} else {
 		efip->efi_flags |= XFS_EFI_CANCELED;
 		AIL_UNLOCK(mp, s);
 	}
-
-	return;
 }
 
+STATIC void
+xfs_efd_item_free(xfs_efd_log_item_t *efdp)
+{
+	int nexts = efdp->efd_format.efd_nextents;
 
-
-
+	if (nexts > XFS_EFD_MAX_FAST_EXTENTS) {
+		kmem_free(efdp, sizeof(xfs_efd_log_item_t) +
+				(nexts - 1) * sizeof(xfs_extent_t));
+	} else {
+		kmem_zone_free(xfs_efd_zone, efdp);
+	}
+}
 
 /*
  * This returns the number of iovecs needed to log the given efd item.
@@ -533,9 +493,6 @@
 STATIC xfs_lsn_t
 xfs_efd_item_committed(xfs_efd_log_item_t *efdp, xfs_lsn_t lsn)
 {
-	uint	size;
-	int	nexts;
-
 	/*
 	 * If we got a log I/O error, it's always the case that the LR with the
 	 * EFI got unpinned and freed before the EFD got aborted.
@@ -543,15 +500,7 @@
 	if ((efdp->efd_item.li_flags & XFS_LI_ABORTED) == 0)
 		xfs_efi_release(efdp->efd_efip, efdp->efd_format.efd_nextents);
 
-	nexts = efdp->efd_format.efd_nextents;
-	if (nexts > XFS_EFD_MAX_FAST_EXTENTS) {
-		size = sizeof(xfs_efd_log_item_t);
-		size += (nexts - 1) * sizeof(xfs_extent_t);
-		kmem_free(efdp, size);
-	} else {
-		kmem_zone_free(xfs_efd_zone, efdp);
-	}
-
+	xfs_efd_item_free(efdp);
 	return (xfs_lsn_t)-1;
 }
 
@@ -565,9 +514,6 @@
 STATIC void
 xfs_efd_item_abort(xfs_efd_log_item_t *efdp)
 {
-	int	nexts;
-	int	size;
-
 	/*
 	 * If we got a log I/O error, it's always the case that the LR with the
 	 * EFI got unpinned and freed before the EFD got aborted. So don't
@@ -576,15 +522,7 @@
 	if ((efdp->efd_item.li_flags & XFS_LI_ABORTED) == 0)
 		xfs_efi_cancel(efdp->efd_efip);
 
-	nexts = efdp->efd_format.efd_nextents;
-	if (nexts > XFS_EFD_MAX_FAST_EXTENTS) {
-		size = sizeof(xfs_efd_log_item_t);
-		size += (nexts - 1) * sizeof(xfs_extent_t);
-		kmem_free(efdp, size);
-	} else {
-		kmem_zone_free(xfs_efd_zone, efdp);
-	}
-	return;
+	xfs_efd_item_free(efdp);
 }
 
 /*
@@ -615,7 +553,7 @@
 /*
  * This is the ops vector shared by all efd log items.
  */
-struct xfs_item_ops xfs_efd_item_ops = {
+STATIC struct xfs_item_ops xfs_efd_item_ops = {
 	.iop_size	= (uint(*)(xfs_log_item_t*))xfs_efd_item_size,
 	.iop_format	= (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
 					xfs_efd_item_format,
diff --git a/fs/xfs/xfs_extfree_item.h b/fs/xfs/xfs_extfree_item.h
index 7122d61..d433bac 100644
--- a/fs/xfs/xfs_extfree_item.h
+++ b/fs/xfs/xfs_extfree_item.h
@@ -118,6 +118,8 @@
 xfs_efd_log_item_t	*xfs_efd_init(struct xfs_mount *, xfs_efi_log_item_t *,
 				      uint);
 
+void			xfs_efi_item_free(xfs_efi_log_item_t *);
+
 #endif	/* __KERNEL__ */
 
 #endif	/* __XFS_EXTFREE_ITEM_H__ */
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index 6ee8443..095af0a 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -60,7 +60,8 @@
 	__u32		fsx_xflags;	/* xflags field value (get/set) */
 	__u32		fsx_extsize;	/* extsize field value (get/set)*/
 	__u32		fsx_nextents;	/* nextents field value (get)	*/
-	unsigned char	fsx_pad[16];
+	__u32		fsx_projid;	/* project identifier (get/set) */
+	unsigned char	fsx_pad[12];
 };
 #endif
 
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index 2121305..ca535d6 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -559,32 +559,6 @@
 	return(0);
 }
 
-void
-xfs_fs_log_dummy(xfs_mount_t *mp)
-{
-	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;
-	}
-
-	ip = mp->m_rootip;
-	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);
-	xfs_trans_commit(tp, 0, NULL);
-
-	xfs_iunlock(ip, XFS_ILOCK_EXCL);
-}
-
 int
 xfs_fs_goingdown(
 	xfs_mount_t	*mp,
diff --git a/fs/xfs/xfs_ialloc_btree.h b/fs/xfs/xfs_ialloc_btree.h
index 803c4d1..44be188 100644
--- a/fs/xfs/xfs_ialloc_btree.h
+++ b/fs/xfs/xfs_ialloc_btree.h
@@ -100,9 +100,13 @@
 #endif
 #if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_INOBT_IS_FREE)
 int xfs_inobt_is_free(xfs_inobt_rec_t *rp, int i);
-#define	XFS_INOBT_IS_FREE(rp,i)	xfs_inobt_is_free(rp,i)
+#define	XFS_INOBT_IS_FREE(rp,i)		xfs_inobt_is_free(rp,i)
+#define	XFS_INOBT_IS_FREE_DISK(rp,i)	xfs_inobt_is_free_disk(rp,i)
 #else
-#define	XFS_INOBT_IS_FREE(rp,i)	(((rp)->ir_free & XFS_INOBT_MASK(i)) != 0)
+#define	XFS_INOBT_IS_FREE(rp,i)	\
+	(((rp)->ir_free & XFS_INOBT_MASK(i)) != 0)
+#define XFS_INOBT_IS_FREE_DISK(rp,i) \
+	((INT_GET((rp)->ir_free, ARCH_CONVERT) & XFS_INOBT_MASK(i)) != 0)
 #endif
 #if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_INOBT_SET_FREE)
 void xfs_inobt_set_free(xfs_inobt_rec_t *rp, int i);
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index bc8c8c7..34bdf59 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -146,51 +146,6 @@
 #endif
 
 /*
- * called from bwrite on xfs inode buffers
- */
-void
-xfs_inobp_bwcheck(xfs_buf_t *bp)
-{
-	xfs_mount_t	*mp;
-	int		i;
-	int		j;
-	xfs_dinode_t	*dip;
-
-	ASSERT(XFS_BUF_FSPRIVATE3(bp, void *) != NULL);
-
-	mp = XFS_BUF_FSPRIVATE3(bp, xfs_mount_t *);
-
-
-	j = mp->m_inode_cluster_size >> mp->m_sb.sb_inodelog;
-
-	for (i = 0; i < j; i++)  {
-		dip = (xfs_dinode_t *) xfs_buf_offset(bp,
-						i * mp->m_sb.sb_inodesize);
-		if (INT_GET(dip->di_core.di_magic, ARCH_CONVERT) != XFS_DINODE_MAGIC) {
-			cmn_err(CE_WARN,
-"Bad magic # 0x%x in XFS inode buffer 0x%Lx, starting blockno %Ld, offset 0x%x",
-				INT_GET(dip->di_core.di_magic, ARCH_CONVERT),
-				(__uint64_t)(__psunsigned_t) bp,
-				(__int64_t) XFS_BUF_ADDR(bp),
-				xfs_buf_offset(bp, i * mp->m_sb.sb_inodesize));
-			xfs_fs_cmn_err(CE_WARN, mp,
-				"corrupt, unmount and run xfs_repair");
-		}
-		if (!dip->di_next_unlinked)  {
-			cmn_err(CE_WARN,
-"Bad next_unlinked field (0) in XFS inode buffer 0x%p, starting blockno %Ld, offset 0x%x",
-				(__uint64_t)(__psunsigned_t) bp,
-				(__int64_t) XFS_BUF_ADDR(bp),
-				xfs_buf_offset(bp, i * mp->m_sb.sb_inodesize));
-			xfs_fs_cmn_err(CE_WARN, mp,
-				"corrupt, unmount and run xfs_repair");
-		}
-	}
-
-	return;
-}
-
-/*
  * This routine is called to map an inode number within a file
  * system to the buffer containing the on-disk version of the
  * inode.  It returns a pointer to the buffer containing the
@@ -203,7 +158,7 @@
  * Use xfs_imap() to determine the size and location of the
  * buffer to read from disk.
  */
-int
+STATIC int
 xfs_inotobp(
 	xfs_mount_t	*mp,
 	xfs_trans_t	*tp,
@@ -1247,26 +1202,32 @@
 	case S_IFREG:
 	case S_IFDIR:
 		if (unlikely(pip->i_d.di_flags & XFS_DIFLAG_ANY)) {
-			if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) {
-				if ((mode & S_IFMT) == S_IFDIR) {
-					ip->i_d.di_flags |= XFS_DIFLAG_RTINHERIT;
-				} else {
-					ip->i_d.di_flags |= XFS_DIFLAG_REALTIME;
+			uint	di_flags = 0;
+
+			if ((mode & S_IFMT) == S_IFDIR) {
+				if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT)
+					di_flags |= XFS_DIFLAG_RTINHERIT;
+			} else {
+				if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) {
+					di_flags |= XFS_DIFLAG_REALTIME;
 					ip->i_iocore.io_flags |= XFS_IOCORE_RT;
 				}
 			}
 			if ((pip->i_d.di_flags & XFS_DIFLAG_NOATIME) &&
 			    xfs_inherit_noatime)
-				ip->i_d.di_flags |= XFS_DIFLAG_NOATIME;
+				di_flags |= XFS_DIFLAG_NOATIME;
 			if ((pip->i_d.di_flags & XFS_DIFLAG_NODUMP) &&
 			    xfs_inherit_nodump)
-				ip->i_d.di_flags |= XFS_DIFLAG_NODUMP;
+				di_flags |= XFS_DIFLAG_NODUMP;
 			if ((pip->i_d.di_flags & XFS_DIFLAG_SYNC) &&
 			    xfs_inherit_sync)
-				ip->i_d.di_flags |= XFS_DIFLAG_SYNC;
+				di_flags |= XFS_DIFLAG_SYNC;
 			if ((pip->i_d.di_flags & XFS_DIFLAG_NOSYMLINKS) &&
 			    xfs_inherit_nosymlinks)
-				ip->i_d.di_flags |= XFS_DIFLAG_NOSYMLINKS;
+				di_flags |= XFS_DIFLAG_NOSYMLINKS;
+			if (pip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
+				di_flags |= XFS_DIFLAG_PROJINHERIT;
+			ip->i_d.di_flags |= di_flags;
 		}
 		/* FALLTHROUGH */
 	case S_IFLNK:
@@ -2156,7 +2117,7 @@
 		(ip->i_update_core == 0));
 }
 
-void
+STATIC void
 xfs_ifree_cluster(
 	xfs_inode_t	*free_ip,
 	xfs_trans_t	*tp,
@@ -2875,7 +2836,7 @@
  * be subsequently pinned once someone is waiting for it to be
  * unpinned.
  */
-void
+STATIC void
 xfs_iunpin_wait(
 	xfs_inode_t	*ip)
 {
@@ -3601,106 +3562,42 @@
 
 
 /*
- * Flush all inactive inodes in mp.  Return true if no user references
- * were found, false otherwise.
+ * Flush all inactive inodes in mp.
  */
-int
+void
 xfs_iflush_all(
-	xfs_mount_t	*mp,
-	int		flag)
+	xfs_mount_t	*mp)
 {
-	int		busy;
-	int		done;
-	int		purged;
 	xfs_inode_t	*ip;
-	vmap_t		vmap;
 	vnode_t		*vp;
 
-	busy = done = 0;
-	while (!done) {
-		purged = 0;
-		XFS_MOUNT_ILOCK(mp);
-		ip = mp->m_inodes;
-		if (ip == NULL) {
-			break;
+ again:
+	XFS_MOUNT_ILOCK(mp);
+	ip = mp->m_inodes;
+	if (ip == NULL)
+		goto out;
+
+	do {
+		/* Make sure we skip markers inserted by sync */
+		if (ip->i_mount == NULL) {
+			ip = ip->i_mnext;
+			continue;
 		}
-		do {
-			/* Make sure we skip markers inserted by sync */
-			if (ip->i_mount == NULL) {
-				ip = ip->i_mnext;
-				continue;
-			}
 
-			/*
-			 * It's up to our caller to purge the root
-			 * and quota vnodes later.
-			 */
-			vp = XFS_ITOV_NULL(ip);
-
-			if (!vp) {
-				XFS_MOUNT_IUNLOCK(mp);
-				xfs_finish_reclaim(ip, 0, XFS_IFLUSH_ASYNC);
-				purged = 1;
-				break;
-			}
-
-			if (vn_count(vp) != 0) {
-				if (vn_count(vp) == 1 &&
-				    (ip == mp->m_rootip ||
-				     (mp->m_quotainfo &&
-				      (ip->i_ino == mp->m_sb.sb_uquotino ||
-				       ip->i_ino == mp->m_sb.sb_gquotino)))) {
-
-					ip = ip->i_mnext;
-					continue;
-				}
-				if (!(flag & XFS_FLUSH_ALL)) {
-					busy = 1;
-					done = 1;
-					break;
-				}
-				/*
-				 * Ignore busy inodes but continue flushing
-				 * others.
-				 */
-				ip = ip->i_mnext;
-				continue;
-			}
-			/*
-			 * Sample vp mapping while holding mp locked on MP
-			 * systems, so we don't purge a reclaimed or
-			 * nonexistent vnode.  We break from the loop
-			 * since we know that we modify
-			 * it by pulling ourselves from it in xfs_reclaim()
-			 * called via vn_purge() below.  Set ip to the next
-			 * entry in the list anyway so we'll know below
-			 * whether we reached the end or not.
-			 */
-			VMAP(vp, vmap);
+		vp = XFS_ITOV_NULL(ip);
+		if (!vp) {
 			XFS_MOUNT_IUNLOCK(mp);
-
-			vn_purge(vp, &vmap);
-
-			purged = 1;
-			break;
-		} while (ip != mp->m_inodes);
-		/*
-		 * We need to distinguish between when we exit the loop
-		 * after a purge and when we simply hit the end of the
-		 * list.  We can't use the (ip == mp->m_inodes) test,
-		 * because when we purge an inode at the start of the list
-		 * the next inode on the list becomes mp->m_inodes.  That
-		 * would cause such a test to bail out early.  The purged
-		 * variable tells us how we got out of the loop.
-		 */
-		if (!purged) {
-			done = 1;
+			xfs_finish_reclaim(ip, 0, XFS_IFLUSH_ASYNC);
+			goto again;
 		}
-	}
-	XFS_MOUNT_IUNLOCK(mp);
-	return !busy;
-}
 
+		ASSERT(vn_count(vp) == 0);
+
+		ip = ip->i_mnext;
+	} while (ip != mp->m_inodes);
+ out:
+	XFS_MOUNT_IUNLOCK(mp);
+}
 
 /*
  * xfs_iaccess: check accessibility of inode for mode.
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 37e1c31..54d9e54 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -412,11 +412,6 @@
 #define	XFS_IFLUSH_DELWRI		5
 
 /*
- * Flags for xfs_iflush_all.
- */
-#define	XFS_FLUSH_ALL		0x1
-
-/*
  * Flags for xfs_itruncate_start().
  */
 #define	XFS_ITRUNC_DEFINITE	0x1
@@ -487,8 +482,6 @@
 /*
  * xfs_inode.c prototypes.
  */
-int		xfs_inotobp(struct xfs_mount *, struct xfs_trans *, xfs_ino_t,
-			    xfs_dinode_t **, struct xfs_buf **, int *);
 int		xfs_itobp(struct xfs_mount *, struct xfs_trans *,
 			  xfs_inode_t *, xfs_dinode_t **, struct xfs_buf **,
 			  xfs_daddr_t);
@@ -522,7 +515,7 @@
 void		xfs_iunpin(xfs_inode_t *);
 int		xfs_iextents_copy(xfs_inode_t *, xfs_bmbt_rec_t *, int);
 int		xfs_iflush(xfs_inode_t *, uint);
-int		xfs_iflush_all(struct xfs_mount *, int);
+void		xfs_iflush_all(struct xfs_mount *);
 int		xfs_iaccess(xfs_inode_t *, mode_t, cred_t *);
 uint		xfs_iroundup(uint);
 void		xfs_ichgtime(xfs_inode_t *, int);
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 768cb18..0eed30f 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -910,7 +910,7 @@
 /*
  * This is the ops vector shared by all buf log items.
  */
-struct xfs_item_ops xfs_inode_item_ops = {
+STATIC struct xfs_item_ops xfs_inode_item_ops = {
 	.iop_size	= (uint(*)(xfs_log_item_t*))xfs_inode_item_size,
 	.iop_format	= (void(*)(xfs_log_item_t*, xfs_log_iovec_t*))
 					xfs_inode_item_format,
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 469e1a7..2edd676 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -385,15 +385,15 @@
 	int		nimaps, maps;
 	int		error;
 	int		bmapi_flag;
+	int		quota_flag;
 	int		rt;
 	xfs_trans_t	*tp;
 	xfs_bmbt_irec_t imap[XFS_WRITE_IMAPS], *imapp;
 	xfs_bmap_free_t free_list;
 	int		aeof;
-	xfs_filblks_t	datablocks;
+	xfs_filblks_t	datablocks, qblocks, resblks;
 	int		committed;
 	int		numrtextents;
-	uint		resblks;
 
 	/*
 	 * Make sure that the dquots are there. This doesn't hold
@@ -419,7 +419,6 @@
 		xfs_fileoff_t	map_last_fsb;
 
 		map_last_fsb = ret_imap->br_blockcount + ret_imap->br_startoff;
-
 		if (map_last_fsb < last_fsb) {
 			last_fsb = map_last_fsb;
 			count_fsb = last_fsb - offset_fsb;
@@ -428,56 +427,47 @@
 	}
 
 	/*
-	 * determine if reserving space on
-	 * the data or realtime partition.
+	 * Determine if reserving space on the data or realtime partition.
 	 */
 	if ((rt = XFS_IS_REALTIME_INODE(ip))) {
-		int	sbrtextsize, iprtextsize;
+		xfs_extlen_t	extsz;
 
-		sbrtextsize = mp->m_sb.sb_rextsize;
-		iprtextsize =
-			ip->i_d.di_extsize ? ip->i_d.di_extsize : sbrtextsize;
-		numrtextents = (count_fsb + iprtextsize - 1);
-		do_div(numrtextents, sbrtextsize);
+		if (!(extsz = ip->i_d.di_extsize))
+			extsz = mp->m_sb.sb_rextsize;
+		numrtextents = qblocks = (count_fsb + extsz - 1);
+		do_div(numrtextents, mp->m_sb.sb_rextsize);
+		quota_flag = XFS_QMOPT_RES_RTBLKS;
 		datablocks = 0;
 	} else {
-		datablocks = count_fsb;
+		datablocks = qblocks = count_fsb;
+		quota_flag = XFS_QMOPT_RES_REGBLKS;
 		numrtextents = 0;
 	}
 
 	/*
-	 * allocate and setup the transaction
+	 * Allocate and setup the transaction
 	 */
 	xfs_iunlock(ip, XFS_ILOCK_EXCL);
 	tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT);
-
 	resblks = XFS_DIOSTRAT_SPACE_RES(mp, datablocks);
-
 	error = xfs_trans_reserve(tp, resblks,
 			XFS_WRITE_LOG_RES(mp), numrtextents,
 			XFS_TRANS_PERM_LOG_RES,
 			XFS_WRITE_LOG_COUNT);
 
 	/*
-	 * check for running out of space
+	 * Check for running out of space, note: need lock to return
 	 */
 	if (error)
-		/*
-		 * Free the transaction structure.
-		 */
 		xfs_trans_cancel(tp, 0);
-
 	xfs_ilock(ip, XFS_ILOCK_EXCL);
-
 	if (error)
-		goto error_out; /* Don't return in above if .. trans ..,
-					need lock to return */
+		goto error_out;
 
-	if (XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, resblks)) {
+	if (XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag)) {
 		error = (EDQUOT);
 		goto error1;
 	}
-	nimaps = 1;
 
 	bmapi_flag = XFS_BMAPI_WRITE;
 	xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
@@ -487,31 +477,29 @@
 		bmapi_flag |= XFS_BMAPI_PREALLOC;
 
 	/*
-	 * issue the bmapi() call to allocate the blocks
+	 * Issue the bmapi() call to allocate the blocks
 	 */
 	XFS_BMAP_INIT(&free_list, &firstfsb);
+	nimaps = 1;
 	imapp = &imap[0];
 	error = xfs_bmapi(tp, ip, offset_fsb, count_fsb,
 		bmapi_flag, &firstfsb, 0, imapp, &nimaps, &free_list);
-	if (error) {
+	if (error)
 		goto error0;
-	}
 
 	/*
-	 * complete the transaction
+	 * Complete the transaction
 	 */
-
 	error = xfs_bmap_finish(&tp, &free_list, firstfsb, &committed);
-	if (error) {
+	if (error)
 		goto error0;
-	}
-
 	error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES, NULL);
-	if (error) {
+	if (error)
 		goto error_out;
-	}
 
-	/* copy any maps to caller's array and return any error. */
+	/*
+	 * Copy any maps to caller's array and return any error.
+	 */
 	if (nimaps == 0) {
 		error = (ENOSPC);
 		goto error_out;
@@ -530,10 +518,11 @@
         }
 	return 0;
 
- error0:	/* Cancel bmap, unlock inode, and cancel trans */
+error0:	/* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */
 	xfs_bmap_cancel(&free_list);
+	XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp, tp, ip, qblocks, 0, quota_flag);
 
- error1:	/* Just cancel transaction */
+error1:	/* Just cancel transaction */
 	xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES | XFS_TRANS_ABORT);
 	*nmaps = 0;	/* nothing set-up here */
 
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 092d5fb..1cd2ac1 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -134,7 +134,7 @@
 #define xlog_verify_tail_lsn(a,b,c)
 #endif
 
-int		xlog_iclogs_empty(xlog_t *log);
+STATIC int	xlog_iclogs_empty(xlog_t *log);
 
 #ifdef DEBUG
 int xlog_do_error = 0;
@@ -1857,7 +1857,7 @@
  *
  * State Change: DIRTY -> ACTIVE
  */
-void
+STATIC void
 xlog_state_clean_log(xlog_t *log)
 {
 	xlog_in_core_t	*iclog;
@@ -3542,7 +3542,7 @@
 	return (retval);
 }
 
-int
+STATIC int
 xlog_iclogs_empty(xlog_t *log)
 {
 	xlog_in_core_t	*iclog;
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index c31e3ce..1a1d452 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -535,7 +535,6 @@
 
 /* common routines */
 extern xfs_lsn_t xlog_assign_tail_lsn(struct xfs_mount *mp);
-extern int	 xlog_find_head(xlog_t *log, xfs_daddr_t *head_blk);
 extern int	 xlog_find_tail(xlog_t	*log,
 				xfs_daddr_t *head_blk,
 				xfs_daddr_t *tail_blk,
@@ -548,7 +547,6 @@
 extern struct xfs_buf *xlog_get_bp(xlog_t *, int);
 extern void	 xlog_put_bp(struct xfs_buf *);
 extern int	 xlog_bread(xlog_t *, xfs_daddr_t, int, struct xfs_buf *);
-extern xfs_caddr_t xlog_align(xlog_t *, xfs_daddr_t, int, struct xfs_buf *);
 
 /* iclog tracing */
 #define XLOG_TRACE_GRAB_FLUSH  1
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 9824b5b..0aac28d 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -148,7 +148,7 @@
  * The buffer is kept locked across the write and is returned locked.
  * This can only be used for synchronous log writes.
  */
-int
+STATIC int
 xlog_bwrite(
 	xlog_t		*log,
 	xfs_daddr_t	blk_no,
@@ -179,7 +179,7 @@
 	return error;
 }
 
-xfs_caddr_t
+STATIC xfs_caddr_t
 xlog_align(
 	xlog_t		*log,
 	xfs_daddr_t	blk_no,
@@ -528,7 +528,7 @@
  *
  * Return: zero if normal, non-zero if error.
  */
-int
+STATIC int
 xlog_find_head(
 	xlog_t 		*log,
 	xfs_daddr_t	*return_head_blk)
@@ -1964,7 +1964,8 @@
 		 * probably a good thing to do for other buf types also.
 		 */
 		error = 0;
-		if (buf_f->blf_flags & (XFS_BLI_UDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) {
+		if (buf_f->blf_flags &
+		   (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) {
 			error = xfs_qm_dqcheck((xfs_disk_dquot_t *)
 					       item->ri_buf[i].i_addr,
 					       -1, 0, XFS_QMOPT_DOWARN,
@@ -2030,6 +2031,7 @@
 	}
 
 	if (INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_USER &&
+	    INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_PROJ &&
 	    INT_GET(ddq->d_flags, ARCH_CONVERT) != XFS_DQ_GROUP) {
 		if (flags & XFS_QMOPT_DOWARN)
 			cmn_err(CE_ALERT,
@@ -2135,6 +2137,8 @@
 	type = 0;
 	if (buf_f->blf_flags & XFS_BLI_UDQUOT_BUF)
 		type |= XFS_DQ_USER;
+	if (buf_f->blf_flags & XFS_BLI_PDQUOT_BUF)
+		type |= XFS_DQ_PROJ;
 	if (buf_f->blf_flags & XFS_BLI_GDQUOT_BUF)
 		type |= XFS_DQ_GROUP;
 	/*
@@ -2247,7 +2251,8 @@
 	error = 0;
 	if (flags & XFS_BLI_INODE_BUF) {
 		error = xlog_recover_do_inode_buffer(mp, item, bp, buf_f);
-	} else if (flags & (XFS_BLI_UDQUOT_BUF | XFS_BLI_GDQUOT_BUF)) {
+	} else if (flags &
+		  (XFS_BLI_UDQUOT_BUF|XFS_BLI_PDQUOT_BUF|XFS_BLI_GDQUOT_BUF)) {
 		xlog_recover_do_dquot_buffer(mp, log, item, bp, buf_f);
 	} else {
 		xlog_recover_do_reg_buffer(mp, item, bp, buf_f);
@@ -2619,7 +2624,7 @@
 	 * This type of quotas was turned off, so ignore this record.
 	 */
 	type = INT_GET(recddq->d_flags, ARCH_CONVERT) &
-			(XFS_DQ_USER | XFS_DQ_GROUP);
+			(XFS_DQ_USER | XFS_DQ_PROJ | XFS_DQ_GROUP);
 	ASSERT(type);
 	if (log->l_quotaoffs_flag & type)
 		return (0);
@@ -2742,7 +2747,6 @@
 	xfs_efi_log_item_t	*efip = NULL;
 	xfs_log_item_t		*lip;
 	int			gen;
-	int			nexts;
 	__uint64_t		efi_id;
 	SPLDECL(s);
 
@@ -2777,22 +2781,15 @@
 		}
 		lip = xfs_trans_next_ail(mp, lip, &gen, NULL);
 	}
-	if (lip == NULL) {
-		AIL_UNLOCK(mp, s);
-	}
 
 	/*
 	 * If we found it, then free it up.  If it wasn't there, it
 	 * must have been overwritten in the log.  Oh well.
 	 */
 	if (lip != NULL) {
-		nexts = efip->efi_format.efi_nextents;
-		if (nexts > XFS_EFI_MAX_FAST_EXTENTS) {
-			kmem_free(lip, sizeof(xfs_efi_log_item_t) +
-				  ((nexts - 1) * sizeof(xfs_extent_t)));
-		} else {
-			kmem_zone_free(xfs_efi_zone, efip);
-		}
+		xfs_efi_item_free(efip);
+	} else {
+		AIL_UNLOCK(mp, s);
 	}
 }
 
diff --git a/fs/xfs/xfs_macros.c b/fs/xfs/xfs_macros.c
index ce4f46c..698c2cd 100644
--- a/fs/xfs/xfs_macros.c
+++ b/fs/xfs/xfs_macros.c
@@ -1658,6 +1658,11 @@
 {
 	return XFS_INOBT_IS_FREE(rp, i);
 }
+int
+xfs_inobt_is_free_disk(xfs_inobt_rec_t *rp, int i)
+{
+	return XFS_INOBT_IS_FREE_DISK(rp, i);
+}
 #endif
 
 #if XFS_WANT_FUNCS_C || (XFS_WANT_SPACE_C && XFSSO_XFS_INOBT_IS_LAST_REC)
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 2ec967d..82e1646 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -64,6 +64,7 @@
 STATIC void	xfs_mount_log_sbunit(xfs_mount_t *, __int64_t);
 STATIC int	xfs_uuid_mount(xfs_mount_t *);
 STATIC void	xfs_uuid_unmount(xfs_mount_t *mp);
+STATIC void	xfs_unmountfs_wait(xfs_mount_t *);
 
 static struct {
     short offset;
@@ -555,7 +556,7 @@
  * fields from the superblock associated with the given
  * mount structure
  */
-void
+STATIC void
 xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp)
 {
 	int	i;
@@ -1081,7 +1082,7 @@
 	int64_t		fsid;
 #endif
 
-	xfs_iflush_all(mp, XFS_FLUSH_ALL);
+	xfs_iflush_all(mp);
 
 	XFS_QM_DQPURGEALL(mp,
 		XFS_QMOPT_UQUOTA | XFS_QMOPT_GQUOTA | XFS_QMOPT_UMOUNTING);
@@ -1111,15 +1112,6 @@
 	 */
 	ASSERT(mp->m_inodes == NULL);
 
-	/*
-	 * We may have bufs that are in the process of getting written still.
-	 * We must wait for the I/O completion of those. The sync flag here
-	 * does a two pass iteration thru the bufcache.
-	 */
-	if (XFS_FORCED_SHUTDOWN(mp)) {
-		xfs_incore_relse(mp->m_ddev_targp, 0, 1); /* synchronous */
-	}
-
 	xfs_unmountfs_close(mp, cr);
 	if ((mp->m_flags & XFS_MOUNT_NOUUID) == 0)
 		xfs_uuid_unmount(mp);
@@ -1146,7 +1138,7 @@
 	xfs_free_buftarg(mp->m_ddev_targp, 0);
 }
 
-void
+STATIC void
 xfs_unmountfs_wait(xfs_mount_t *mp)
 {
 	if (mp->m_logdev_targp != mp->m_ddev_targp)
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 30dd08f..5affba3 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -141,7 +141,7 @@
 typedef void	(*xfs_dqdetach_t)(struct xfs_inode *);
 typedef int	(*xfs_dqpurgeall_t)(struct xfs_mount *, uint);
 typedef int	(*xfs_dqvopalloc_t)(struct xfs_mount *,
-			struct xfs_inode *, uid_t, gid_t, uint,
+			struct xfs_inode *, uid_t, gid_t, prid_t, uint,
 			struct xfs_dquot **, struct xfs_dquot **);
 typedef void	(*xfs_dqvopcreate_t)(struct xfs_trans *, struct xfs_inode *,
 			struct xfs_dquot *, struct xfs_dquot *);
@@ -185,8 +185,8 @@
 	(*(mp)->m_qm_ops.xfs_dqdetach)(ip)
 #define XFS_QM_DQPURGEALL(mp, fl) \
 	(*(mp)->m_qm_ops.xfs_dqpurgeall)(mp, fl)
-#define XFS_QM_DQVOPALLOC(mp, ip, uid, gid, fl, dq1, dq2) \
-	(*(mp)->m_qm_ops.xfs_dqvopalloc)(mp, ip, uid, gid, fl, dq1, dq2)
+#define XFS_QM_DQVOPALLOC(mp, ip, uid, gid, prid, fl, dq1, dq2) \
+	(*(mp)->m_qm_ops.xfs_dqvopalloc)(mp, ip, uid, gid, prid, fl, dq1, dq2)
 #define XFS_QM_DQVOPCREATE(mp, tp, ip, dq1, dq2) \
 	(*(mp)->m_qm_ops.xfs_dqvopcreate)(tp, ip, dq1, dq2)
 #define XFS_QM_DQVOPRENAME(mp, ip) \
@@ -544,7 +544,6 @@
 extern int	xfs_mountfs(struct vfs *, xfs_mount_t *mp, int);
 
 extern int	xfs_unmountfs(xfs_mount_t *, struct cred *);
-extern void	xfs_unmountfs_wait(xfs_mount_t *);
 extern void	xfs_unmountfs_close(xfs_mount_t *, struct cred *);
 extern int	xfs_unmountfs_writesb(xfs_mount_t *);
 extern int	xfs_unmount_flush(xfs_mount_t *, int);
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 703ec4e..7134576 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -96,7 +96,7 @@
  * flags for q_flags field in the dquot.
  */
 #define XFS_DQ_USER		0x0001		/* a user quota */
-/* #define XFS_DQ_PROJ		0x0002		-- project quota (IRIX) */
+#define XFS_DQ_PROJ		0x0002		/* project quota */
 #define XFS_DQ_GROUP		0x0004		/* a group quota */
 #define XFS_DQ_FLOCKED		0x0008		/* flush lock taken */
 #define XFS_DQ_DIRTY		0x0010		/* dquot is dirty */
@@ -104,6 +104,8 @@
 #define XFS_DQ_INACTIVE		0x0040		/* dq off mplist & hashlist */
 #define XFS_DQ_MARKER		0x0080		/* sentinel */
 
+#define XFS_DQ_ALLTYPES		(XFS_DQ_USER|XFS_DQ_PROJ|XFS_DQ_GROUP)
+
 /*
  * In the worst case, when both user and group quotas are on,
  * we can have a max of three dquots changing in a single transaction.
@@ -124,7 +126,7 @@
 typedef struct xfs_dq_logformat {
 	__uint16_t		qlf_type;      /* dquot log item type */
 	__uint16_t		qlf_size;      /* size of this item */
-	xfs_dqid_t		qlf_id;	       /* usr/grp id number : 32 bits */
+	xfs_dqid_t		qlf_id;	       /* usr/grp/proj id : 32 bits */
 	__int64_t		qlf_blkno;     /* blkno of dquot buffer */
 	__int32_t		qlf_len;       /* len of dquot buffer */
 	__uint32_t		qlf_boffset;   /* off of dquot in buffer */
@@ -152,9 +154,9 @@
 #define XFS_UQUOTA_ACCT	0x0001  /* user quota accounting ON */
 #define XFS_UQUOTA_ENFD	0x0002  /* user quota limits enforced */
 #define XFS_UQUOTA_CHKD	0x0004  /* quotacheck run on usr quotas */
-#define XFS_PQUOTA_ACCT	0x0008  /* (IRIX) project quota accounting ON */
-#define XFS_GQUOTA_ENFD	0x0010  /* group quota limits enforced */
-#define XFS_GQUOTA_CHKD	0x0020  /* quotacheck run on grp quotas */
+#define XFS_PQUOTA_ACCT	0x0008  /* project quota accounting ON */
+#define XFS_OQUOTA_ENFD	0x0010  /* other (grp/prj) quota limits enforced */
+#define XFS_OQUOTA_CHKD	0x0020  /* quotacheck run on other (grp/prj) quotas */
 #define XFS_GQUOTA_ACCT	0x0040  /* group quota accounting ON */
 
 /*
@@ -162,17 +164,22 @@
  * are in the process of getting turned off. These flags are in m_qflags but
  * never in sb_qflags.
  */
-#define XFS_UQUOTA_ACTIVE	0x0080  /* uquotas are being turned off */
-#define XFS_GQUOTA_ACTIVE	0x0100  /* gquotas are being turned off */
+#define XFS_UQUOTA_ACTIVE	0x0100  /* uquotas are being turned off */
+#define XFS_PQUOTA_ACTIVE	0x0200  /* pquotas are being turned off */
+#define XFS_GQUOTA_ACTIVE	0x0400  /* gquotas are being turned off */
 
 /*
  * Checking XFS_IS_*QUOTA_ON() while holding any inode lock guarantees
  * quota will be not be switched off as long as that inode lock is held.
  */
 #define XFS_IS_QUOTA_ON(mp)	((mp)->m_qflags & (XFS_UQUOTA_ACTIVE | \
-						   XFS_GQUOTA_ACTIVE))
+						   XFS_GQUOTA_ACTIVE | \
+						   XFS_PQUOTA_ACTIVE))
+#define XFS_IS_OQUOTA_ON(mp)	((mp)->m_qflags & (XFS_GQUOTA_ACTIVE | \
+						   XFS_PQUOTA_ACTIVE))
 #define XFS_IS_UQUOTA_ON(mp)	((mp)->m_qflags & XFS_UQUOTA_ACTIVE)
 #define XFS_IS_GQUOTA_ON(mp)	((mp)->m_qflags & XFS_GQUOTA_ACTIVE)
+#define XFS_IS_PQUOTA_ON(mp)	((mp)->m_qflags & XFS_PQUOTA_ACTIVE)
 
 /*
  * Flags to tell various functions what to do. Not all of these are meaningful
@@ -182,7 +189,7 @@
 #define XFS_QMOPT_DQLOCK	0x0000001 /* dqlock */
 #define XFS_QMOPT_DQALLOC	0x0000002 /* alloc dquot ondisk if needed */
 #define XFS_QMOPT_UQUOTA	0x0000004 /* user dquot requested */
-#define XFS_QMOPT_GQUOTA	0x0000008 /* group dquot requested */
+#define XFS_QMOPT_PQUOTA	0x0000008 /* project dquot requested */
 #define XFS_QMOPT_FORCE_RES	0x0000010 /* ignore quota limits */
 #define XFS_QMOPT_DQSUSER	0x0000020 /* don't cache super users dquot */
 #define XFS_QMOPT_SBVERSION	0x0000040 /* change superblock version num */
@@ -192,6 +199,7 @@
 #define XFS_QMOPT_DOWARN        0x0000400 /* increase warning cnt if necessary */
 #define XFS_QMOPT_ILOCKED	0x0000800 /* inode is already locked (excl) */
 #define XFS_QMOPT_DQREPAIR	0x0001000 /* repair dquot, if damaged. */
+#define XFS_QMOPT_GQUOTA	0x0002000 /* group dquot requested */
 
 /*
  * flags to xfs_trans_mod_dquot to indicate which field needs to be
@@ -231,7 +239,8 @@
 #define XFS_TRANS_DQ_DELRTBCOUNT XFS_QMOPT_DELRTBCOUNT
 
 
-#define XFS_QMOPT_QUOTALL	(XFS_QMOPT_UQUOTA|XFS_QMOPT_GQUOTA)
+#define XFS_QMOPT_QUOTALL	\
+		(XFS_QMOPT_UQUOTA | XFS_QMOPT_PQUOTA | XFS_QMOPT_GQUOTA)
 #define XFS_QMOPT_RESBLK_MASK	(XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_RES_RTBLKS)
 
 #ifdef __KERNEL__
@@ -246,21 +255,33 @@
  */
 #define XFS_NOT_DQATTACHED(mp, ip) ((XFS_IS_UQUOTA_ON(mp) &&\
 				     (ip)->i_udquot == NULL) || \
-				    (XFS_IS_GQUOTA_ON(mp) && \
+				    (XFS_IS_OQUOTA_ON(mp) && \
 				     (ip)->i_gdquot == NULL))
 
-#define XFS_QM_NEED_QUOTACHECK(mp) ((XFS_IS_UQUOTA_ON(mp) && \
-				     (mp->m_sb.sb_qflags & \
-				      XFS_UQUOTA_CHKD) == 0) || \
-				    (XFS_IS_GQUOTA_ON(mp) && \
-				     (mp->m_sb.sb_qflags & \
-				      XFS_GQUOTA_CHKD) == 0))
+#define XFS_QM_NEED_QUOTACHECK(mp) \
+	((XFS_IS_UQUOTA_ON(mp) && \
+		(mp->m_sb.sb_qflags & XFS_UQUOTA_CHKD) == 0) || \
+	 (XFS_IS_GQUOTA_ON(mp) && \
+		((mp->m_sb.sb_qflags & XFS_OQUOTA_CHKD) == 0 || \
+		 (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT))) || \
+	 (XFS_IS_PQUOTA_ON(mp) && \
+		((mp->m_sb.sb_qflags & XFS_OQUOTA_CHKD) == 0 || \
+		 (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT))))
+
+#define XFS_MOUNT_QUOTA_SET1	(XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
+				 XFS_UQUOTA_CHKD|XFS_PQUOTA_ACCT|\
+				 XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD)
+
+#define XFS_MOUNT_QUOTA_SET2	(XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
+				 XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\
+				 XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD)
 
 #define XFS_MOUNT_QUOTA_ALL	(XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
-				 XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\
-				 XFS_GQUOTA_ENFD|XFS_GQUOTA_CHKD)
+				 XFS_UQUOTA_CHKD|XFS_PQUOTA_ACCT|\
+				 XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD|\
+				 XFS_GQUOTA_ACCT)
 #define XFS_MOUNT_QUOTA_MASK	(XFS_MOUNT_QUOTA_ALL | XFS_UQUOTA_ACTIVE | \
-				 XFS_GQUOTA_ACTIVE)
+				 XFS_GQUOTA_ACTIVE | XFS_PQUOTA_ACTIVE)
 
 
 /*
@@ -331,15 +352,8 @@
 #define XFS_TRANS_UNRESERVE_AND_MOD_DQUOTS(mp, tp) \
 	XFS_DQTRXOP_VOID(mp, tp, qo_unreserve_and_mod_dquots)
 
-#define XFS_TRANS_RESERVE_BLKQUOTA(mp, tp, ip, nblks) \
-	XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, 0, \
-				XFS_QMOPT_RES_REGBLKS)
-#define XFS_TRANS_RESERVE_BLKQUOTA_FORCE(mp, tp, ip, nblks) \
-	XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, 0, \
-				XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES)
-#define XFS_TRANS_UNRESERVE_BLKQUOTA(mp, tp, ip, nblks) \
-	XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, -(nblks), 0, \
-				XFS_QMOPT_RES_REGBLKS)
+#define XFS_TRANS_UNRESERVE_QUOTA_NBLKS(mp, tp, ip, nblks, ninos, flags) \
+	XFS_TRANS_RESERVE_QUOTA_NBLKS(mp, tp, ip, -(nblks), -(ninos), flags)
 #define XFS_TRANS_RESERVE_QUOTA(mp, tp, ud, gd, nb, ni, f) \
 	XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp, ud, gd, nb, ni, \
 				f | XFS_QMOPT_RES_REGBLKS)
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c
index cb13f9a..23b48ac 100644
--- a/fs/xfs/xfs_rename.c
+++ b/fs/xfs/xfs_rename.c
@@ -234,9 +234,6 @@
 	return 0;
 }
 
-
-int rename_which_error_return = 0;
-
 /*
  * xfs_rename
  */
@@ -316,7 +313,6 @@
 			&num_inodes);
 
 	if (error) {
-		rename_which_error_return = __LINE__;
 		/*
 		 * We have nothing locked, no inode references, and
 		 * no transaction, so just get out.
@@ -332,7 +328,6 @@
 		 */
 		if (target_ip == NULL && (src_dp != target_dp) &&
 		    target_dp->i_d.di_nlink >= XFS_MAXLINK) {
-			rename_which_error_return = __LINE__;
 			error = XFS_ERROR(EMLINK);
 			xfs_rename_unlock4(inodes, XFS_ILOCK_SHARED);
 			goto rele_return;
@@ -359,7 +354,6 @@
 				XFS_TRANS_PERM_LOG_RES, XFS_RENAME_LOG_COUNT);
 	}
 	if (error) {
-		rename_which_error_return = __LINE__;
 		xfs_trans_cancel(tp, 0);
 		goto rele_return;
 	}
@@ -369,7 +363,6 @@
 	 */
 	if ((error = XFS_QM_DQVOPRENAME(mp, inodes))) {
 		xfs_trans_cancel(tp, cancel_flags);
-		rename_which_error_return = __LINE__;
 		goto rele_return;
 	}
 
@@ -413,7 +406,6 @@
 		if (spaceres == 0 &&
 		    (error = XFS_DIR_CANENTER(mp, tp, target_dp, target_name,
 				target_namelen))) {
-			rename_which_error_return = __LINE__;
 			goto error_return;
 		}
 		/*
@@ -425,11 +417,9 @@
 					   target_namelen, src_ip->i_ino,
 					   &first_block, &free_list, spaceres);
 		if (error == ENOSPC) {
-			rename_which_error_return = __LINE__;
 			goto error_return;
 		}
 		if (error) {
-			rename_which_error_return = __LINE__;
 			goto abort_return;
 		}
 		xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
@@ -437,7 +427,6 @@
 		if (new_parent && src_is_directory) {
 			error = xfs_bumplink(tp, target_dp);
 			if (error) {
-				rename_which_error_return = __LINE__;
 				goto abort_return;
 			}
 		}
@@ -455,7 +444,6 @@
 			if (!(XFS_DIR_ISEMPTY(target_ip->i_mount, target_ip)) ||
 			    (target_ip->i_d.di_nlink > 2)) {
 				error = XFS_ERROR(EEXIST);
-				rename_which_error_return = __LINE__;
 				goto error_return;
 			}
 		}
@@ -473,7 +461,6 @@
 			target_namelen, src_ip->i_ino, &first_block,
 			&free_list, spaceres);
 		if (error) {
-			rename_which_error_return = __LINE__;
 			goto abort_return;
 		}
 		xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
@@ -484,7 +471,6 @@
 		 */
 		error = xfs_droplink(tp, target_ip);
 		if (error) {
-			rename_which_error_return = __LINE__;
 			goto abort_return;
 		}
 		target_ip_dropped = 1;
@@ -495,7 +481,6 @@
 			 */
 			error = xfs_droplink(tp, target_ip);
 			if (error) {
-				rename_which_error_return = __LINE__;
 				goto abort_return;
 			}
 		}
@@ -519,7 +504,6 @@
 					&free_list, spaceres);
 		ASSERT(error != EEXIST);
 		if (error) {
-			rename_which_error_return = __LINE__;
 			goto abort_return;
 		}
 		xfs_ichgtime(src_ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
@@ -550,7 +534,6 @@
 		 */
 		error = xfs_droplink(tp, src_dp);
 		if (error) {
-			rename_which_error_return = __LINE__;
 			goto abort_return;
 		}
 	}
@@ -558,7 +541,6 @@
 	error = XFS_DIR_REMOVENAME(mp, tp, src_dp, src_name, src_namelen,
 			src_ip->i_ino, &first_block, &free_list, spaceres);
 	if (error) {
-		rename_which_error_return = __LINE__;
 		goto abort_return;
 	}
 	xfs_ichgtime(src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 3db0e22..06dfca5 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -332,25 +332,6 @@
 
 
 /*
- * This is called to set the a callback to be called when the given
- * transaction is committed to disk.  The transaction pointer and the
- * argument pointer will be passed to the callback routine.
- *
- * Only one callback can be associated with any single transaction.
- */
-void
-xfs_trans_callback(
-	xfs_trans_t		*tp,
-	xfs_trans_callback_t	callback,
-	void			*arg)
-{
-	ASSERT(tp->t_callback == NULL);
-	tp->t_callback = callback;
-	tp->t_callarg = arg;
-}
-
-
-/*
  * Record the indicated change to the given field for application
  * to the file system's superblock when the transaction commits.
  * For now, just store the change in the transaction structure.
@@ -551,7 +532,7 @@
  *
  * This is done efficiently with a single call to xfs_mod_incore_sb_batch().
  */
-void
+STATIC void
 xfs_trans_unreserve_and_mod_sb(
 	xfs_trans_t	*tp)
 {
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index bd37ccb..ec541d6 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -987,8 +987,6 @@
 xfs_trans_t	*xfs_trans_dup(xfs_trans_t *);
 int		xfs_trans_reserve(xfs_trans_t *, uint, uint, uint,
 				  uint, uint);
-void		xfs_trans_callback(xfs_trans_t *,
-				   void (*)(xfs_trans_t *, void *), void *);
 void		xfs_trans_mod_sb(xfs_trans_t *, uint, long);
 struct xfs_buf	*xfs_trans_get_buf(xfs_trans_t *, struct xfs_buftarg *, xfs_daddr_t,
 				   int, uint);
@@ -1010,7 +1008,6 @@
 			       xfs_ino_t , uint, uint, struct xfs_inode **);
 void		xfs_trans_ijoin(xfs_trans_t *, struct xfs_inode *, uint);
 void		xfs_trans_ihold(xfs_trans_t *, struct xfs_inode *);
-void		xfs_trans_ihold_release(xfs_trans_t *, struct xfs_inode *);
 void		xfs_trans_log_buf(xfs_trans_t *, struct xfs_buf *, uint, uint);
 void		xfs_trans_log_inode(xfs_trans_t *, struct xfs_inode *, uint);
 struct xfs_efi_log_item	*xfs_trans_get_efi(xfs_trans_t *, uint);
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index a9682b9..144da7a 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -976,6 +976,7 @@
 	ASSERT(XFS_BUF_FSPRIVATE2(bp, xfs_trans_t *) == tp);
 	ASSERT(XFS_BUF_FSPRIVATE(bp, void *) != NULL);
 	ASSERT(type == XFS_BLI_UDQUOT_BUF ||
+	       type == XFS_BLI_PDQUOT_BUF ||
 	       type == XFS_BLI_GDQUOT_BUF);
 
 	bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c
index e2c3706..7e7631c 100644
--- a/fs/xfs/xfs_trans_inode.c
+++ b/fs/xfs/xfs_trans_inode.c
@@ -253,24 +253,6 @@
 	ip->i_itemp->ili_flags |= XFS_ILI_HOLD;
 }
 
-/*
- * Cancel the previous inode hold request made on this inode
- * for this transaction.
- */
-/*ARGSUSED*/
-void
-xfs_trans_ihold_release(
-	xfs_trans_t	*tp,
-	xfs_inode_t	*ip)
-{
-	ASSERT(ip->i_transp == tp);
-	ASSERT(ip->i_itemp != NULL);
-	ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
-	ASSERT(ip->i_itemp->ili_flags & XFS_ILI_HOLD);
-
-	ip->i_itemp->ili_flags &= ~XFS_ILI_HOLD;
-}
-
 
 /*
  * This is called to mark the fields indicated in fieldmask as needing
diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h
index e4bf711..16f5371 100644
--- a/fs/xfs/xfs_types.h
+++ b/fs/xfs/xfs_types.h
@@ -55,7 +55,7 @@
 typedef unsigned long long int	__uint64_t;
 
 typedef enum { B_FALSE,B_TRUE }	boolean_t;
-typedef __int64_t		prid_t;		/* project ID */
+typedef __uint32_t		prid_t;		/* project ID */
 typedef __uint32_t		inst_t;		/* an instruction */
 
 typedef __s64			xfs_off_t;	/* <file offset> type */
diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c
index d1f8146..11351f0 100644
--- a/fs/xfs/xfs_utils.c
+++ b/fs/xfs/xfs_utils.c
@@ -428,7 +428,7 @@
 		if (ip->i_ino != mp->m_sb.sb_uquotino)
 			ASSERT(ip->i_udquot);
 	}
-	if (XFS_IS_GQUOTA_ON(mp)) {
+	if (XFS_IS_OQUOTA_ON(mp)) {
 		if (ip->i_ino != mp->m_sb.sb_gquotino)
 			ASSERT(ip->i_gdquot);
 	}
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c
index b537366..42bcc02 100644
--- a/fs/xfs/xfs_vfsops.c
+++ b/fs/xfs/xfs_vfsops.c
@@ -368,16 +368,6 @@
 	}
 
 	/*
-	 * disallow mount attempts with (IRIX) project quota enabled
-	 */
-	if (XFS_SB_VERSION_HASQUOTA(&mp->m_sb) &&
-	    (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT)) {
-		cmn_err(CE_WARN,
-	"XFS: cannot mount a filesystem with IRIX project quota enabled");
-		return XFS_ERROR(ENOSYS);
-	}
-
-	/*
 	 * check for shared mount.
 	 */
 	if (ap->flags & XFSMNT_SHARED) {
@@ -622,7 +612,34 @@
 	return XFS_ERROR(error);
 }
 
-#define REMOUNT_READONLY_FLAGS	(SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT)
+STATIC int
+xfs_quiesce_fs(
+	xfs_mount_t		*mp)
+{
+	int			count = 0, pincount;
+		
+	xfs_refcache_purge_mp(mp);
+	xfs_flush_buftarg(mp->m_ddev_targp, 0);
+	xfs_finish_reclaim_all(mp, 0);
+
+	/* This loop must run at least twice.
+	 * The first instance of the loop will flush
+	 * most meta data but that will generate more
+	 * meta data (typically directory updates).
+	 * Which then must be flushed and logged before
+	 * we can write the unmount record.
+	 */ 
+	do {
+		xfs_syncsub(mp, SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT, 0, NULL);
+		pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1);
+		if (!pincount) {
+			delay(50);
+			count++;
+		}
+	} while (count < 2);
+
+	return 0;
+}
 
 STATIC int
 xfs_mntupdate(
@@ -632,8 +649,7 @@
 {
 	struct vfs	*vfsp = bhvtovfs(bdp);
 	xfs_mount_t	*mp = XFS_BHVTOM(bdp);
-	int		pincount, error;
-	int		count = 0;
+	int		error;
 
 	if (args->flags & XFSMNT_NOATIME)
 		mp->m_flags |= XFS_MOUNT_NOATIME;
@@ -645,25 +661,7 @@
 	}
 
 	if (*flags & MS_RDONLY) {
-		xfs_refcache_purge_mp(mp);
-		xfs_flush_buftarg(mp->m_ddev_targp, 0);
-		xfs_finish_reclaim_all(mp, 0);
-
-		/* This loop must run at least twice.
-		 * The first instance of the loop will flush
-		 * most meta data but that will generate more
-		 * meta data (typically directory updates).
-		 * Which then must be flushed and logged before
-		 * we can write the unmount record.
-		 */ 
-		do {
-			VFS_SYNC(vfsp, REMOUNT_READONLY_FLAGS, NULL, error);
-			pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1);
-			if (!pincount) {
-				delay(50);
-				count++;
-			}
-		} while (count < 2);
+		xfs_quiesce_fs(mp);
 
 		/* Ok now write out an unmount record */
 		xfs_log_unmount_write(mp);
@@ -879,10 +877,12 @@
 	int		flags,
 	cred_t		*credp)
 {
-	xfs_mount_t	*mp;
+	xfs_mount_t	*mp = XFS_BHVTOM(bdp);
 
-	mp = XFS_BHVTOM(bdp);
-	return (xfs_syncsub(mp, flags, 0, NULL));
+	if (unlikely(flags == SYNC_QUIESCE))
+		return xfs_quiesce_fs(mp);
+	else
+		return xfs_syncsub(mp, flags, 0, NULL);
 }
 
 /*
@@ -1681,7 +1681,7 @@
 	return simple_strtoul(cp, endp, base) << shift_left_factor;
 }
 
-int
+STATIC int
 xfs_parseargs(
 	struct bhv_desc		*bhv,
 	char			*options,
@@ -1867,7 +1867,7 @@
 	return 0;
 }
 
-int
+STATIC int
 xfs_showargs(
 	struct bhv_desc		*bhv,
 	struct seq_file		*m)
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 25a5266..1377c86 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2004 Silicon Graphics, Inc.  All Rights Reserved.
+ * 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 version 2 of the GNU General Public License as
@@ -351,21 +351,28 @@
 	 * If the IDs do change before we take the ilock, we're covered
 	 * because the i_*dquot fields will get updated anyway.
 	 */
-	if (XFS_IS_QUOTA_ON(mp) && (mask & (XFS_AT_UID|XFS_AT_GID))) {
+	if (XFS_IS_QUOTA_ON(mp) &&
+	    (mask & (XFS_AT_UID|XFS_AT_GID|XFS_AT_PROJID))) {
 		uint	qflags = 0;
 
-		if (mask & XFS_AT_UID) {
+		if ((mask & XFS_AT_UID) && XFS_IS_UQUOTA_ON(mp)) {
 			uid = vap->va_uid;
 			qflags |= XFS_QMOPT_UQUOTA;
 		} else {
 			uid = ip->i_d.di_uid;
 		}
-		if (mask & XFS_AT_GID) {
+		if ((mask & XFS_AT_GID) && XFS_IS_GQUOTA_ON(mp)) {
 			gid = vap->va_gid;
 			qflags |= XFS_QMOPT_GQUOTA;
 		}  else {
 			gid = ip->i_d.di_gid;
 		}
+		if ((mask & XFS_AT_PROJID) && XFS_IS_PQUOTA_ON(mp)) {
+			projid = vap->va_projid;
+			qflags |= XFS_QMOPT_PQUOTA;
+		}  else {
+			projid = ip->i_d.di_projid;
+		}
 		/*
 		 * We take a reference when we initialize udqp and gdqp,
 		 * so it is important that we never blindly double trip on
@@ -373,7 +380,8 @@
 		 */
 		ASSERT(udqp == NULL);
 		ASSERT(gdqp == NULL);
-		code = XFS_QM_DQVOPALLOC(mp, ip, uid,gid, qflags, &udqp, &gdqp);
+		code = XFS_QM_DQVOPALLOC(mp, ip, uid, gid, projid, qflags,
+					 &udqp, &gdqp);
 		if (code)
 			return (code);
 	}
@@ -499,8 +507,6 @@
 		 * that the group ID supplied to the chown() function
 		 * shall be equal to either the group ID or one of the
 		 * supplementary group IDs of the calling process.
-		 *
-		 * XXX: How does restricted_chown affect projid?
 		 */
 		if (restricted_chown &&
 		    (iuid != uid || (igid != gid &&
@@ -510,10 +516,11 @@
 			goto error_return;
 		}
 		/*
-		 * Do a quota reservation only if uid or gid is actually
+		 * Do a quota reservation only if uid/projid/gid is actually
 		 * going to change.
 		 */
 		if ((XFS_IS_UQUOTA_ON(mp) && iuid != uid) ||
+		    (XFS_IS_PQUOTA_ON(mp) && iprojid != projid) ||
 		    (XFS_IS_GQUOTA_ON(mp) && igid != gid)) {
 			ASSERT(tp);
 			code = XFS_QM_DQVOPCHOWNRESV(mp, tp, ip, udqp, gdqp,
@@ -774,6 +781,7 @@
 		}
 		if (igid != gid) {
 			if (XFS_IS_GQUOTA_ON(mp)) {
+				ASSERT(!XFS_IS_PQUOTA_ON(mp));
 				ASSERT(mask & XFS_AT_GID);
 				ASSERT(gdqp);
 				olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip,
@@ -782,6 +790,13 @@
 			ip->i_d.di_gid = gid;
 		}
 		if (iprojid != projid) {
+			if (XFS_IS_PQUOTA_ON(mp)) {
+				ASSERT(!XFS_IS_GQUOTA_ON(mp));
+				ASSERT(mask & XFS_AT_PROJID);
+				ASSERT(gdqp);
+				olddquot2 = XFS_QM_DQVOPCHOWN(mp, tp, ip,
+							&ip->i_gdquot, gdqp);
+			}
 			ip->i_d.di_projid = projid;
 			/*
 			 * We may have to rev the inode as well as
@@ -843,6 +858,8 @@
 				di_flags |= XFS_DIFLAG_NOATIME;
 			if (vap->va_xflags & XFS_XFLAG_NODUMP)
 				di_flags |= XFS_DIFLAG_NODUMP;
+			if (vap->va_xflags & XFS_XFLAG_PROJINHERIT)
+				di_flags |= XFS_DIFLAG_PROJINHERIT;
 			if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) {
 				if (vap->va_xflags & XFS_XFLAG_RTINHERIT)
 					di_flags |= XFS_DIFLAG_RTINHERIT;
@@ -1898,7 +1915,9 @@
 	/* Return through std_return after this point. */
 
 	udqp = gdqp = NULL;
-	if (vap->va_mask & XFS_AT_PROJID)
+	if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
+		prid = dp->i_d.di_projid;
+	else if (vap->va_mask & XFS_AT_PROJID)
 		prid = (xfs_prid_t)vap->va_projid;
 	else
 		prid = (xfs_prid_t)dfltprid;
@@ -1907,7 +1926,7 @@
 	 * Make sure that we have allocated dquot(s) on disk.
 	 */
 	error = XFS_QM_DQVOPALLOC(mp, dp,
-			current_fsuid(credp), current_fsgid(credp),
+			current_fsuid(credp), current_fsgid(credp), prid,
 			XFS_QMOPT_QUOTALL|XFS_QMOPT_INHERIT, &udqp, &gdqp);
 	if (error)
 		goto std_return;
@@ -2604,17 +2623,7 @@
 	if (src_vp->v_type == VDIR)
 		return XFS_ERROR(EPERM);
 
-	/*
-	 * For now, manually find the XFS behavior descriptor for
-	 * the source vnode.  If it doesn't exist then something
-	 * is wrong and we should just return an error.
-	 * Eventually we need to figure out how link is going to
-	 * work in the face of stacked vnodes.
-	 */
 	src_bdp = vn_bhv_lookup_unlocked(VN_BHV_HEAD(src_vp), &xfs_vnodeops);
-	if (src_bdp == NULL) {
-		return XFS_ERROR(EXDEV);
-	}
 	sip = XFS_BHVTOI(src_bdp);
 	tdp = XFS_BHVTOI(target_dir_bdp);
 	mp = tdp->i_mount;
@@ -2681,6 +2690,17 @@
 		goto error_return;
 	}
 
+	/*
+	 * If we are using project inheritance, we only allow hard link
+	 * creation in our tree when the project IDs are the same; else
+	 * the tree quota mechanism could be circumvented.
+	 */
+	if (unlikely((tdp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
+		     (tdp->i_d.di_projid != sip->i_d.di_projid))) {
+		error = XFS_ERROR(EPERM);
+		goto error_return;
+	}
+
 	if (resblks == 0 &&
 	    (error = XFS_DIR_CANENTER(mp, tp, tdp, target_name,
 			target_namelen)))
@@ -2803,7 +2823,9 @@
 
 	mp = dp->i_mount;
 	udqp = gdqp = NULL;
-	if (vap->va_mask & XFS_AT_PROJID)
+	if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
+		prid = dp->i_d.di_projid;
+	else if (vap->va_mask & XFS_AT_PROJID)
 		prid = (xfs_prid_t)vap->va_projid;
 	else
 		prid = (xfs_prid_t)dfltprid;
@@ -2812,7 +2834,7 @@
 	 * Make sure that we have allocated dquot(s) on disk.
 	 */
 	error = XFS_QM_DQVOPALLOC(mp, dp,
-			current_fsuid(credp), current_fsgid(credp),
+			current_fsuid(credp), current_fsgid(credp), prid,
 			XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
 	if (error)
 		goto std_return;
@@ -3357,7 +3379,9 @@
 	/* Return through std_return after this point. */
 
 	udqp = gdqp = NULL;
-	if (vap->va_mask & XFS_AT_PROJID)
+	if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)
+		prid = dp->i_d.di_projid;
+	else if (vap->va_mask & XFS_AT_PROJID)
 		prid = (xfs_prid_t)vap->va_projid;
 	else
 		prid = (xfs_prid_t)dfltprid;
@@ -3366,7 +3390,7 @@
 	 * Make sure that we have allocated dquot(s) on disk.
 	 */
 	error = XFS_QM_DQVOPALLOC(mp, dp,
-			current_fsuid(credp), current_fsgid(credp),
+			current_fsuid(credp), current_fsgid(credp), prid,
 			XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
 	if (error)
 		goto std_return;
@@ -4028,7 +4052,7 @@
  *      errno on error
  *
  */
-int
+STATIC int
 xfs_alloc_file_space(
 	xfs_inode_t		*ip,
 	xfs_off_t		offset,
@@ -4151,9 +4175,8 @@
 			break;
 		}
 		xfs_ilock(ip, XFS_ILOCK_EXCL);
-		error = XFS_TRANS_RESERVE_QUOTA_BYDQUOTS(mp, tp,
-				ip->i_udquot, ip->i_gdquot, resblks, 0, rt ?
-				XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS);
+		error = XFS_TRANS_RESERVE_QUOTA(mp, tp,
+				ip->i_udquot, ip->i_gdquot, resblks, 0, 0);
 		if (error)
 			goto error1;
 
@@ -4305,6 +4328,7 @@
 	xfs_off_t		len,
 	int			attr_flags)
 {
+	vnode_t			*vp;
 	int			committed;
 	int			done;
 	xfs_off_t		end_dmi_offset;
@@ -4325,9 +4349,11 @@
 	xfs_trans_t		*tp;
 	int			need_iolock = 1;
 
-	vn_trace_entry(XFS_ITOV(ip), __FUNCTION__, (inst_t *)__return_address);
+	vp = XFS_ITOV(ip);
 	mp = ip->i_mount;
 
+	vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address);
+
 	if ((error = XFS_QM_DQATTACH(mp, ip, 0)))
 		return error;
 
@@ -4344,7 +4370,7 @@
 	    DM_EVENT_ENABLED(XFS_MTOVFS(mp), ip, DM_EVENT_WRITE)) {
 		if (end_dmi_offset > ip->i_d.di_size)
 			end_dmi_offset = ip->i_d.di_size;
-		error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, XFS_ITOV(ip),
+		error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, vp,
 				offset, end_dmi_offset - offset,
 				AT_DELAY_FLAG(attr_flags), NULL);
 		if (error)
@@ -4363,7 +4389,14 @@
 	ioffset = offset & ~(rounding - 1);
 	if (ilen & (rounding - 1))
 		ilen = (ilen + rounding) & ~(rounding - 1);
-	xfs_inval_cached_pages(XFS_ITOV(ip), &(ip->i_iocore), ioffset, 0, 0);
+
+	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)),
+				-1, FI_REMAPF_LOCKED);
+	}
+
 	/*
 	 * Need to zero the stuff we're not freeing, on disk.
 	 * If its a realtime file & can't use unwritten extents then we
diff --git a/include/asm-alpha/agp.h b/include/asm-alpha/agp.h
index c99dbbb..ef855a3 100644
--- a/include/asm-alpha/agp.h
+++ b/include/asm-alpha/agp.h
@@ -10,4 +10,14 @@
 #define flush_agp_mappings() 
 #define flush_agp_cache() mb()
 
+/* Convert a physical address to an address suitable for the GART. */
+#define phys_to_gart(x) (x)
+#define gart_to_phys(x) (x)
+
+/* GATT allocation. Returns/accepts GATT kernel virtual address. */
+#define alloc_gatt_pages(order)		\
+	((char *)__get_free_pages(GFP_KERNEL, (order)))
+#define free_gatt_pages(table, order)	\
+	free_pages((unsigned long)(table), (order))
+
 #endif
diff --git a/include/asm-alpha/mmzone.h b/include/asm-alpha/mmzone.h
index 726c150..a011ef4 100644
--- a/include/asm-alpha/mmzone.h
+++ b/include/asm-alpha/mmzone.h
@@ -57,7 +57,6 @@
  * Given a kernel address, find the home node of the underlying memory.
  */
 #define kvaddr_to_nid(kaddr)	pa_to_nid(__pa(kaddr))
-#define node_mem_map(nid)	(NODE_DATA(nid)->node_mem_map)
 #define node_start_pfn(nid)	(NODE_DATA(nid)->node_start_pfn)
 
 #define local_mapnr(kvaddr) \
@@ -108,7 +107,7 @@
 #define pfn_to_page(pfn)						\
 ({									\
  	unsigned long kaddr = (unsigned long)__va((pfn) << PAGE_SHIFT);	\
-	(node_mem_map(kvaddr_to_nid(kaddr)) + local_mapnr(kaddr));	\
+	(NODE_DATA(kvaddr_to_nid(kaddr))->node_mem_map + local_mapnr(kaddr));	\
 })
 
 #define page_to_pfn(page)						\
diff --git a/include/asm-alpha/smp.h b/include/asm-alpha/smp.h
index cbc173a..9950706 100644
--- a/include/asm-alpha/smp.h
+++ b/include/asm-alpha/smp.h
@@ -43,7 +43,7 @@
 #define PROC_CHANGE_PENALTY     20
 
 #define hard_smp_processor_id()	__hard_smp_processor_id()
-#define smp_processor_id()	(current_thread_info()->cpu)
+#define raw_smp_processor_id()	(current_thread_info()->cpu)
 
 extern cpumask_t cpu_present_mask;
 extern cpumask_t cpu_online_map;
diff --git a/include/asm-arm/arch-aaec2000/aaec2000.h b/include/asm-arm/arch-aaec2000/aaec2000.h
new file mode 100644
index 0000000..0e9b7e1
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/aaec2000.h
@@ -0,0 +1,151 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/aaec2000.h
+ *
+ *  AAEC-2000 registers definition
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  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_AAEC2000_H
+#define __ASM_ARCH_AAEC2000_H
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#error You must include hardware.h not this file
+#endif /* __ASM_ARCH_HARDWARE_H */
+
+/* Interrupt controller */
+#define IRQ_BASE	__REG(0x80000500)
+#define IRQ_INTSR	__REG(0x80000500)	/* Int Status Register */
+#define IRQ_INTRSR	__REG(0x80000504)	/* Int Raw (unmasked) Status */
+#define IRQ_INTENS	__REG(0x80000508)	/* Int Enable Set */
+#define IRQ_INTENC	__REG(0x8000050c)	/* Int Enable Clear */
+
+/* UART 1 */
+#define UART1_BASE	__REG(0x80000600)
+#define UART1_DR	__REG(0x80000600) /* Data/FIFO Register */
+#define UART1_LCR	__REG(0x80000604) /* Link Control Register */
+#define UART1_BRCR	__REG(0x80000608) /* Baud Rate Control Register */
+#define UART1_CR	__REG(0x8000060c) /* Control Register */
+#define UART1_SR	__REG(0x80000610) /* Status Register */
+#define UART1_INT	__REG(0x80000614) /* Interrupt Status Register */
+#define UART1_INTM	__REG(0x80000618) /* Interrupt Mask Register */
+#define UART1_INTRES	__REG(0x8000061c) /* Int Result (masked status) Register */
+
+/* UART 2 */
+#define UART2_BASE	__REG(0x80000700)
+#define UART2_DR	__REG(0x80000700) /* Data/FIFO Register */
+#define UART2_LCR	__REG(0x80000704) /* Link Control Register */
+#define UART2_BRCR	__REG(0x80000708) /* Baud Rate Control Register */
+#define UART2_CR	__REG(0x8000070c) /* Control Register */
+#define UART2_SR	__REG(0x80000710) /* Status Register */
+#define UART2_INT	__REG(0x80000714) /* Interrupt Status Register */
+#define UART2_INTM	__REG(0x80000718) /* Interrupt Mask Register */
+#define UART2_INTRES	__REG(0x8000071c) /* Int Result (masked status) Register */
+
+/* UART 3 */
+#define UART3_BASE	__REG(0x80000800)
+#define UART3_DR	__REG(0x80000800) /* Data/FIFO Register */
+#define UART3_LCR	__REG(0x80000804) /* Link Control Register */
+#define UART3_BRCR	__REG(0x80000808) /* Baud Rate Control Register */
+#define UART3_CR	__REG(0x8000080c) /* Control Register */
+#define UART3_SR	__REG(0x80000810) /* Status Register */
+#define UART3_INT	__REG(0x80000814) /* Interrupt Status Register */
+#define UART3_INTM	__REG(0x80000818) /* Interrupt Mask Register */
+#define UART3_INTRES	__REG(0x8000081c) /* Int Result (masked status) Register */
+
+/* These are used in some places */
+#define _UART1_BASE __PREG(UART1_BASE)
+#define _UART2_BASE __PREG(UART2_BASE)
+#define _UART3_BASE __PREG(UART3_BASE)
+
+/* UART Registers Offsets */
+#define UART_DR		0x00
+#define UART_LCR	0x04
+#define UART_BRCR	0x08
+#define UART_CR		0x0c
+#define UART_SR		0x10
+#define UART_INT	0x14
+#define UART_INTM	0x18
+#define UART_INTRES	0x1c
+
+/* UART_LCR Bitmask */
+#define UART_LCR_BRK	(1 << 0) /* Send Break */
+#define UART_LCR_PEN	(1 << 1) /* Parity Enable */
+#define UART_LCR_EP	(1 << 2) /* Even/Odd Parity */
+#define UART_LCR_S2	(1 << 3) /* One/Two Stop bits */
+#define UART_LCR_FIFO	(1 << 4) /* FIFO Enable */
+#define UART_LCR_WL5	(0 << 5) /* Word Length - 5 bits */
+#define UART_LCR_WL6	(1 << 5) /* Word Length - 6 bits */
+#define UART_LCR_WL7	(1 << 6) /* Word Length - 7 bits */
+#define UART_LCR_WL8	(1 << 7) /* Word Length - 8 bits */
+
+/* UART_CR Bitmask */
+#define UART_CR_EN	(1 << 0) /* UART Enable */
+#define UART_CR_SIR	(1 << 1) /* IrDA SIR Enable */
+#define UART_CR_SIRLP	(1 << 2) /* Low Power IrDA Enable */
+#define UART_CR_RXP	(1 << 3) /* Receive Pin Polarity */
+#define UART_CR_TXP	(1 << 4) /* Transmit Pin Polarity */
+#define UART_CR_MXP	(1 << 5) /* Modem Pin Polarity */
+#define UART_CR_LOOP	(1 << 6) /* Loopback Mode */
+
+/* UART_SR Bitmask */
+#define UART_SR_CTS	(1 << 0) /* Clear To Send Status */
+#define UART_SR_DSR	(1 << 1) /* Data Set Ready Status */
+#define UART_SR_DCD	(1 << 2) /* Data Carrier Detect Status */
+#define UART_SR_TxBSY	(1 << 3) /* Transmitter Busy Status */
+#define UART_SR_RxFE	(1 << 4) /* Receive FIFO Empty Status */
+#define UART_SR_TxFF	(1 << 5) /* Transmit FIFO Full Status */
+#define UART_SR_RxFF	(1 << 6) /* Receive FIFO Full Status */
+#define UART_SR_TxFE	(1 << 7) /* Transmit FIFO Empty Status */
+
+/* UART_INT Bitmask */
+#define UART_INT_RIS	(1 << 0) /* Rx Interrupt */
+#define UART_INT_TIS	(1 << 1) /* Tx Interrupt */
+#define UART_INT_MIS	(1 << 2) /* Modem Interrupt */
+#define UART_INT_RTIS	(1 << 3) /* Receive Timeout Interrupt */
+
+/* Timer 1 */
+#define TIMER1_BASE	__REG(0x80000c00)
+#define TIMER1_LOAD	__REG(0x80000c00)	/* Timer 1 Load Register */
+#define TIMER1_VAL	__REG(0x80000c04)	/* Timer 1 Value Register */
+#define TIMER1_CTRL	__REG(0x80000c08)	/* Timer 1 Control Register */
+#define TIMER1_CLEAR	__REG(0x80000c0c)	/* Timer 1 Clear Register */
+
+/* Timer 2 */
+#define TIMER2_BASE	__REG(0x80000d00)
+#define TIMER2_LOAD	__REG(0x80000d00)	/* Timer 2 Load Register */
+#define TIMER2_VAL	__REG(0x80000d04)	/* Timer 2 Value Register */
+#define TIMER2_CTRL	__REG(0x80000d08)	/* Timer 2 Control Register */
+#define TIMER2_CLEAR	__REG(0x80000d0c)	/* Timer 2 Clear Register */
+
+/* Timer 3 */
+#define TIMER3_BASE	__REG(0x80000e00)
+#define TIMER3_LOAD	__REG(0x80000e00)	/* Timer 3 Load Register */
+#define TIMER3_VAL	__REG(0x80000e04)	/* Timer 3 Value Register */
+#define TIMER3_CTRL	__REG(0x80000e08)	/* Timer 3 Control Register */
+#define TIMER3_CLEAR	__REG(0x80000e0c)	/* Timer 3 Clear Register */
+
+/* Timer Control register bits */
+#define TIMER_CTRL_ENABLE	(1 << 7) /* Enable (Start° Timer */
+#define TIMER_CTRL_PERIODIC	(1 << 6) /* Periodic Running Mode */
+#define TIMER_CTRL_FREE_RUNNING (0 << 6) /* Normal Running Mode */
+#define TIMER_CTRL_CLKSEL_508K	(1 << 3) /* 508KHz Clock select (Timer 1, 2) */
+#define TIMER_CTRL_CLKSEL_2K	(0 << 3) /* 2KHz Clock Select (Timer 1, 2)*/
+
+/* Power and State Control */
+#define POWER_BASE	__REG(0x80000400)
+#define POWER_PWRSR	__REG(0x80000400) /* Power Status Register */
+#define POWER_PWRCNT	__REG(0x80000404) /* Power/Clock control */
+#define POWER_HALT	__REG(0x80000408) /* Power Idle Mode */
+#define POWER_STDBY	__REG(0x8000040c) /* Power Standby Mode */
+#define POWER_BLEOI	__REG(0x80000410) /* Battery Low End of Interrupt */
+#define POWER_MCEOI	__REG(0x80000414) /* Media Changed EoI */
+#define POWER_TEOI	__REG(0x80000418) /* Tick EoI */
+#define POWER_STFCLR	__REG(0x8000041c) /* NbFlg, RSTFlg, PFFlg, CLDFlg Clear */
+#define POWER_CLKSET	__REG(0x80000420) /* Clock Speed Control */
+
+#endif /* __ARM_ARCH_AAEC2000_H */
diff --git a/include/asm-arm/arch-aaec2000/debug-macro.S b/include/asm-arm/arch-aaec2000/debug-macro.S
new file mode 100644
index 0000000..e4f1fa5
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/debug-macro.S
@@ -0,0 +1,36 @@
+/*  linux/include/asm-arm/arch-aaec2000/debug-macro.S
+ *
+ *  Debugging macro include header
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  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?
+		moveq	\rx, #0x80000000		@ physical
+		movne	\rx, #io_p2v(0x80000000)	@ virtual
+		orr	\rx, \rx, #0x00000800
+		.endm
+
+		.macro	senduart,rd,rx
+		str	\rd, [\rx, #0]
+		.endm
+
+		.macro	busyuart,rd,rx
+1002:		ldr	\rd, [\rx, #0x10]
+		tst	\rd, #(1 << 7)
+		beq	1002b
+		.endm
+
+		.macro	waituart,rd,rx
+#if 0
+1001:		ldr	\rd, [\rx, #0x10]
+		tst	\rd, #(1 << 5)
+		beq	1001b
+#endif
+		.endm
diff --git a/include/asm-arm/arch-aaec2000/dma.h b/include/asm-arm/arch-aaec2000/dma.h
new file mode 100644
index 0000000..28c890b
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/dma.h
@@ -0,0 +1,17 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/dma.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  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
+
+#define MAX_DMA_ADDRESS         0xffffffff
+#define MAX_DMA_CHANNELS        0
+
+#endif
diff --git a/include/asm-arm/arch-aaec2000/entry-macro.S b/include/asm-arm/arch-aaec2000/entry-macro.S
new file mode 100644
index 0000000..df31313
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/entry-macro.S
@@ -0,0 +1,33 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/entry-macro.S
+ *
+ *  Low-level IRQ helper for aaec-2000 based platforms
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  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	disable_fiq
+		.endm
+
+		.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+		mov	r4, #0xf8000000
+		add	r4, r4, #0x00000500
+		mov	\base, r4
+		ldr	\irqstat, [\base, #0]
+		cmp	\irqstat, #0
+		bne	1001f
+		ldr	\irqnr, =NR_IRQS+1
+		b       1003f
+1001:		mov	\irqnr, #0
+1002:		ands	\tmp, \irqstat, #1
+		mov	\irqstat, \irqstat, LSR #1
+		add	\irqnr, \irqnr, #1
+		beq	1002b
+		sub	\irqnr, \irqnr, #1
+1003:
+		.endm
diff --git a/include/asm-arm/arch-aaec2000/hardware.h b/include/asm-arm/arch-aaec2000/hardware.h
new file mode 100644
index 0000000..4c37219
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/hardware.h
@@ -0,0 +1,49 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/hardware.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  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_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <linux/config.h>
+
+/* The kernel is loaded at physical address 0xf8000000.
+ * We map the IO space a bit after
+ */
+#define PIO_APB_BASE	0x80000000
+#define VIO_APB_BASE	0xf8000000
+#define IO_APB_LENGTH	0x2000
+#define PIO_AHB_BASE	0x80002000
+#define VIO_AHB_BASE	0xf8002000
+#define IO_AHB_LENGTH	0x2000
+
+#define VIO_BASE    VIO_APB_BASE
+#define PIO_BASE    PIO_APB_BASE
+
+#define io_p2v(x) ( (x) - PIO_BASE + VIO_BASE )
+#define io_v2p(x) ( (x) + PIO_BASE - VIO_BASE )
+
+#ifndef __ASSEMBLY__
+
+#include <asm/types.h>
+
+/* FIXME: Is it needed to optimize this a la pxa ?? */
+#define __REG(x)    (*((volatile u32 *)io_p2v(x)))
+#define __PREG(x)   (io_v2p((u32)&(x)))
+
+#else /* __ASSEMBLY__ */
+
+#define __REG(x)    io_p2v(x)
+#define __PREG(x)   io_v2p(x)
+
+#endif
+
+#include "aaec2000.h"
+
+#endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/include/asm-arm/arch-aaec2000/io.h b/include/asm-arm/arch-aaec2000/io.h
new file mode 100644
index 0000000..c58a8d1
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/io.h
@@ -0,0 +1,19 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/io.h
+ *
+ *  Copied from asm/arch/sa1100/io.h
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+/*
+ * We don't actually have real ISA nor PCI buses, but there is so many
+ * drivers out there that might just work if we fake them...
+ */
+#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/irqs.h b/include/asm-arm/arch-aaec2000/irqs.h
new file mode 100644
index 0000000..de25222
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/irqs.h
@@ -0,0 +1,46 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/irqs.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  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_IRQS_H
+#define __ASM_ARCH_IRQS_H
+
+
+#define INT_GPIOF0_FIQ	0  /* External GPIO Port F O Fast Interrupt Input */
+#define INT_BL_FIQ	1  /* Battery Low Fast Interrupt */
+#define INT_WE_FIQ	2  /* Watchdog Expired Fast Interrupt */
+#define INT_MV_FIQ	3  /* Media Changed Interrupt */
+#define INT_SC		4  /* Sound Codec Interrupt */
+#define INT_GPIO1	5  /* GPIO Port F Configurable Int 1 */
+#define INT_GPIO2	6  /* GPIO Port F Configurable Int 2 */
+#define INT_GPIO3	7  /* GPIO Port F Configurable Int 3 */
+#define INT_TMR1_OFL	8  /* Timer 1 Overflow Interrupt */
+#define INT_TMR2_OFL	9  /* Timer 2 Overflow Interrupt */
+#define INT_RTC_CM	10 /* RTC Compare Match Interrupt */
+#define INT_TICK	11 /* 64Hz Tick Interrupt */
+#define INT_UART1	12 /* UART1 Interrupt */
+#define INT_UART2	13 /* UART2 & Modem State Changed Interrupt */
+#define INT_LCD		14 /* LCD Interrupt */
+#define INT_SSI		15 /* SSI End of Transfer Interrupt */
+#define INT_UART3	16 /* UART3 Interrupt */
+#define INT_SCI		17 /* SCI Interrupt */
+#define INT_AAC		18 /* Advanced Audio Codec Interrupt */
+#define INT_MMC		19 /* MMC Interrupt */
+#define INT_USB		20 /* USB Interrupt */
+#define INT_DMA		21 /* DMA Interrupt */
+#define INT_TMR3_UOFL	22 /* Timer 3 Underflow Interrupt */
+#define INT_GPIO4	23 /* GPIO Port F Configurable Int 4 */
+#define INT_GPIO5	24 /* GPIO Port F Configurable Int 4 */
+#define INT_GPIO6	25 /* GPIO Port F Configurable Int 4 */
+#define INT_GPIO7	26 /* GPIO Port F Configurable Int 4 */
+#define INT_BMI		27 /* BMI Interrupt */
+
+#define NR_IRQS		(INT_BMI + 1)
+
+#endif /* __ASM_ARCH_IRQS_H */
diff --git a/include/asm-arm/arch-aaec2000/memory.h b/include/asm-arm/arch-aaec2000/memory.h
new file mode 100644
index 0000000..681b6a6
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/memory.h
@@ -0,0 +1,73 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/memory.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  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_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+#include <linux/config.h>
+
+#define PHYS_OFFSET	(0xf0000000UL)
+
+#define __virt_to_bus(x)	__virt_to_phys(x)
+#define __bus_to_virt(x)	__phys_to_virt(x)
+
+#ifdef CONFIG_DISCONTIGMEM
+
+/*
+ * The nodes are the followings:
+ *
+ *   node 0: 0xf000.0000 - 0xf3ff.ffff
+ *   node 1: 0xf400.0000 - 0xf7ff.ffff
+ *   node 2: 0xf800.0000 - 0xfbff.ffff
+ *   node 3: 0xfc00.0000 - 0xffff.ffff
+ */
+
+/*
+ * Given a kernel address, find the home node of the underlying memory.
+ */
+#define KVADDR_TO_NID(addr) \
+	(((unsigned long)(addr) - PAGE_OFFSET) >> NODE_MAX_MEM_SHIFT)
+
+/*
+ * Given a page frame number, convert it to a node id.
+ */
+#define PFN_TO_NID(pfn) \
+	(((pfn) - PHYS_PFN_OFFSET) >> (NODE_MAX_MEM_SHIFT - PAGE_SHIFT))
+
+/*
+ * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
+ * and return the mem_map of that node.
+ */
+#define ADDR_TO_MAPBASE(kaddr)  NODE_MEM_MAP(KVADDR_TO_NID(kaddr))
+
+/*
+ * Given a page frame number, find the owning node of the memory
+ * and return the mem_map of that node.
+ */
+#define PFN_TO_MAPBASE(pfn)     NODE_MEM_MAP(PFN_TO_NID(pfn))
+
+/*
+ *  Given a kaddr, LOCAL_MEM_MAP finds the owning node of the memory
+ *  and returns the index corresponding to the appropriate page in the
+ *  node's mem_map.
+ */
+#define LOCAL_MAP_NR(addr) \
+        (((unsigned long)(addr) & (NODE_MAX_MEM_SIZE - 1)) >> PAGE_SHIFT)
+
+#define NODE_MAX_MEM_SHIFT	26
+#define NODE_MAX_MEM_SIZE	(1 << NODE_MAX_MEM_SHIFT)
+
+#else
+
+#define PFN_TO_NID(addr)	(0)
+
+#endif /* CONFIG_DISCONTIGMEM */
+
+#endif /* __ASM_ARCH_MEMORY_H */
diff --git a/include/asm-arm/arch-aaec2000/param.h b/include/asm-arm/arch-aaec2000/param.h
new file mode 100644
index 0000000..139936c
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/param.h
@@ -0,0 +1,15 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/param.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  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_PARAM_H
+#define __ASM_ARCH_PARAM_H
+
+#endif /* __ASM_ARCH_PARAM_H */
+
diff --git a/include/asm-arm/arch-aaec2000/system.h b/include/asm-arm/arch-aaec2000/system.h
new file mode 100644
index 0000000..08de97b
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/system.h
@@ -0,0 +1,24 @@
+/*
+ *  linux/include/asm-arm/arch-aaed2000/system.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  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_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+static inline void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode)
+{
+	cpu_reset(0);
+}
+
+#endif /* __ASM_ARCH_SYSTEM_H */
diff --git a/include/asm-arm/arch-aaec2000/timex.h b/include/asm-arm/arch-aaec2000/timex.h
new file mode 100644
index 0000000..f5708b3
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/timex.h
@@ -0,0 +1,18 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/timex.h
+ *
+ *  AAEC-2000 Architecture timex specification
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  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_TIMEX_H
+#define __ASM_ARCH_TIMEX_H
+
+#define CLOCK_TICK_RATE		508000
+
+#endif /* __ASM_ARCH_TIMEX_H */
diff --git a/include/asm-arm/arch-aaec2000/uncompress.h b/include/asm-arm/arch-aaec2000/uncompress.h
new file mode 100644
index 0000000..fff0c94
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/uncompress.h
@@ -0,0 +1,47 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/uncompress.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  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_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H
+
+#include "hardware.h"
+
+#define UART(x)         (*(volatile unsigned long *)(serial_port + (x)))
+
+static void putstr( const char *s )
+{
+	unsigned long serial_port;
+        do {
+		serial_port = _UART3_BASE;
+		if (UART(UART_CR) & UART_CR_EN) break;
+		serial_port = _UART1_BASE;
+		if (UART(UART_CR) & UART_CR_EN) break;
+		serial_port = _UART2_BASE;
+		if (UART(UART_CR) & UART_CR_EN) break;
+		return;
+	} while (0);
+
+	for (; *s; s++) {
+		/* wait for space in the UART's transmitter */
+		while ((UART(UART_SR) & UART_SR_TxFF));
+		/* send the character out. */
+		UART(UART_DR) = *s;
+		/* if a LF, also do CR... */
+		if (*s == 10) {
+			while ((UART(UART_SR) & UART_SR_TxFF));
+			UART(UART_DR) = 13;
+		}
+	}
+}
+
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
+
+#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff --git a/include/asm-arm/arch-aaec2000/vmalloc.h b/include/asm-arm/arch-aaec2000/vmalloc.h
new file mode 100644
index 0000000..ecb991e
--- /dev/null
+++ b/include/asm-arm/arch-aaec2000/vmalloc.h
@@ -0,0 +1,16 @@
+/*
+ *  linux/include/asm-arm/arch-aaec2000/vmalloc.h
+ *
+ *  Copyright (c) 2005 Nicolas Bellido Y Ortega
+ *
+ *  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_VMALLOC_H
+#define __ASM_ARCH_VMALLOC_H
+
+#define VMALLOC_END		(PAGE_OFFSET + 0x10000000)
+
+#endif /* __ASM_ARCH_VMALLOC_H */
diff --git a/include/asm-arm/arch-integrator/platform.h b/include/asm-arm/arch-integrator/platform.h
index bd364f5..96ad3d2 100644
--- a/include/asm-arm/arch-integrator/platform.h
+++ b/include/asm-arm/arch-integrator/platform.h
@@ -293,7 +293,11 @@
 #define INTEGRATOR_DBG_SWITCH           (INTEGRATOR_DBG_BASE + INTEGRATOR_DBG_SWITCH_OFFSET)
 
 
+#if defined(CONFIG_ARCH_INTEGRATOR_AP)
 #define INTEGRATOR_GPIO_BASE            0x1B000000	 /*  GPIO */
+#elif defined(CONFIG_ARCH_INTEGRATOR_CP)
+#define INTEGRATOR_GPIO_BASE            0xC9000000	 /*  GPIO */
+#endif
 
 /* ------------------------------------------------------------------------
  *  KMI keyboard/mouse definitions
diff --git a/include/asm-arm/arch-integrator/smp.h b/include/asm-arm/arch-integrator/smp.h
new file mode 100644
index 0000000..0ec7093
--- /dev/null
+++ b/include/asm-arm/arch-integrator/smp.h
@@ -0,0 +1,19 @@
+#ifndef ASMARM_ARCH_SMP_H
+#define ASMARM_ARCH_SMP_H
+
+#include <linux/config.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/io.h>
+
+#define hard_smp_processor_id()				\
+	({						\
+		unsigned int cpunum;			\
+		__asm__("mrc p15, 0, %0, c0, c0, 5"	\
+			: "=r" (cpunum));		\
+		cpunum &= 0x0F;				\
+	})
+
+extern void secondary_scan_irqs(void);
+
+#endif
diff --git a/include/asm-arm/arch-ixp2000/gpio.h b/include/asm-arm/arch-ixp2000/gpio.h
index 84634af..03cbbe1 100644
--- a/include/asm-arm/arch-ixp2000/gpio.h
+++ b/include/asm-arm/arch-ixp2000/gpio.h
@@ -1,5 +1,5 @@
 /*
- * include/asm-arm/arch-ixp2000/ixp2000-gpio.h
+ * include/asm-arm/arch-ixp2000/gpio.h
  *
  * Copyright (C) 2002 Intel Corporation.
  *
@@ -16,26 +16,18 @@
  * Use this instead of directly setting the GPIO registers.
  * GPIOs may also be used as GPIOs (e.g. for emulating i2c/smb)
  */
-#ifndef _ASM_ARCH_IXP2000_GPIO_H_
-#define _ASM_ARCH_IXP2000_GPIO_H_
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H
 
 #ifndef __ASSEMBLY__
-#define GPIO_OUT			0x0
-#define GPIO_IN				0x80
+
+#define GPIO_IN				0
+#define GPIO_OUT			1
 
 #define IXP2000_GPIO_LOW		0
 #define IXP2000_GPIO_HIGH		1
 
-#define GPIO_NO_EDGES           	0
-#define GPIO_FALLING_EDGE       	1
-#define GPIO_RISING_EDGE        	2
-#define GPIO_BOTH_EDGES         	3
-#define GPIO_LEVEL_LOW          	4
-#define GPIO_LEVEL_HIGH         	8
-
-extern void set_GPIO_IRQ_edge(int gpio_nr, int edge);
-extern void set_GPIO_IRQ_level(int gpio_nr, int level);
-extern void gpio_line_config(int line, int style);
+extern void gpio_line_config(int line, int direction);
 
 static inline int gpio_line_get(int line)
 {
@@ -45,11 +37,12 @@
 static inline void gpio_line_set(int line, int value)
 {
 	if (value == IXP2000_GPIO_HIGH) {
-		ixp_reg_write(IXP2000_GPIO_POSR, BIT(line));
-	} else if (value == IXP2000_GPIO_LOW)
-		ixp_reg_write(IXP2000_GPIO_POCR, BIT(line));
+		ixp2000_reg_write(IXP2000_GPIO_POSR, 1 << line);
+	} else if (value == IXP2000_GPIO_LOW) {
+		ixp2000_reg_write(IXP2000_GPIO_POCR, 1 << line);
+	}
 }
 
 #endif /* !__ASSEMBLY__ */
-#endif /* ASM_ARCH_IXP2000_GPIO_H_ */
 
+#endif /* ASM_ARCH_IXP2000_GPIO_H_ */
diff --git a/include/asm-arm/arch-ixp2000/io.h b/include/asm-arm/arch-ixp2000/io.h
index a8e3c2d..3241cd6 100644
--- a/include/asm-arm/arch-ixp2000/io.h
+++ b/include/asm-arm/arch-ixp2000/io.h
@@ -17,18 +17,23 @@
 
 #define IO_SPACE_LIMIT		0xffffffff
 #define __mem_pci(a)		(a)
-#define ___io(p)		((void __iomem *)((p)+IXP2000_PCI_IO_VIRT_BASE))
 
 /*
- * The IXP2400 before revision B0 asserts byte lanes for PCI I/O
+ * The A? revisions of the IXP2000s assert byte lanes for PCI I/O
  * transactions the other way round (MEM transactions don't have this
- * issue), so we need to override the standard functions.  B0 and later
- * have a bit that can be set to 1 to get the 'proper' behavior, but
- * since that isn't available on the A? revisions we just keep doing
- * things manually.
+ * issue), so if we want to support those models, we need to override
+ * the standard I/O functions.
+ *
+ * B0 and later have a bit that can be set to 1 to get the proper
+ * behavior for I/O transactions, which then allows us to use the
+ * standard I/O functions.  This is what we do if the user does not
+ * explicitly ask for support for pre-B0.
  */
-#define alignb(addr)		(void __iomem *)((unsigned long)addr ^ 3)
-#define alignw(addr)		(void __iomem *)((unsigned long)addr ^ 2)
+#ifdef CONFIG_IXP2000_SUPPORT_BROKEN_PCI_IO
+#define ___io(p)		((void __iomem *)((p)+IXP2000_PCI_IO_VIRT_BASE))
+
+#define alignb(addr)		(void __iomem *)((unsigned long)(addr) ^ 3)
+#define alignw(addr)		(void __iomem *)((unsigned long)(addr) ^ 2)
 
 #define outb(v,p)		__raw_writeb((v),alignb(___io(p)))
 #define outw(v,p)		__raw_writew((v),alignw(___io(p)))
@@ -48,6 +53,81 @@
 #define insw(p,d,l)		__raw_readsw(alignw(___io(p)),d,l)
 #define insl(p,d,l)		__raw_readsl(___io(p),d,l)
 
+#define __is_io_address(p)	((((unsigned long)(p)) & ~(IXP2000_PCI_IO_SIZE - 1)) == IXP2000_PCI_IO_VIRT_BASE)
+
+#define ioread8(p)						\
+	({							\
+		unsigned int __v;				\
+								\
+		if (__is_io_address(p)) {			\
+			__v = __raw_readb(alignb(p));		\
+		} else {					\
+			__v = __raw_readb(p);			\
+		}						\
+								\
+		__v;						\
+	})							\
+
+#define ioread16(p)						\
+	({							\
+		unsigned int __v;				\
+								\
+		if (__is_io_address(p)) {			\
+			__v = __raw_readw(alignw(p));		\
+		} else {					\
+			__v = le16_to_cpu(__raw_readw(p));	\
+		}						\
+								\
+		__v;						\
+	})
+
+#define ioread32(p)						\
+	({							\
+		unsigned int __v;				\
+								\
+		if (__is_io_address(p)) {			\
+			__v = __raw_readl(p);			\
+		} else {					\
+			__v = le32_to_cpu(__raw_readl(p));	\
+		}						\
+								\
+		 __v;						\
+	})
+
+#define iowrite8(v,p)						\
+	({							\
+		if (__is_io_address(p)) {			\
+			__raw_writeb((v), alignb(p));		\
+		} else {					\
+			__raw_writeb((v), p);			\
+		}						\
+	})
+
+#define iowrite16(v,p)						\
+	({							\
+		if (__is_io_address(p)) {			\
+			__raw_writew((v), alignw(p));		\
+		} else {					\
+			__raw_writew(cpu_to_le16(v), p);	\
+		}						\
+	})
+
+#define iowrite32(v,p)						\
+	({							\
+		if (__is_io_address(p)) {			\
+			__raw_writel((v), p);			\
+		} else {					\
+			__raw_writel(cpu_to_le32(v), p);	\
+		}						\
+	})
+
+#define ioport_map(port, nr)	___io(port)
+
+#define ioport_unmap(addr)
+#else
+#define __io(p)			((void __iomem *)((p)+IXP2000_PCI_IO_VIRT_BASE))
+#endif
+
 
 #ifdef CONFIG_ARCH_IXDP2X01
 /*
@@ -75,8 +155,8 @@
 	 * Is this cycle meant for the CS8900?
 	 */
 	if ((machine_is_ixdp2401() || machine_is_ixdp2801()) && 
-		((port >= IXDP2X01_CS8900_VIRT_BASE) && 
-		 (port <= IXDP2X01_CS8900_VIRT_END))) {
+		(((u32)port >= (u32)IXDP2X01_CS8900_VIRT_BASE) &&
+		 ((u32)port <= (u32)IXDP2X01_CS8900_VIRT_END))) {
 		u8 *buf8 = (u8*)buf;
 		register u32 tmp32;
 
@@ -100,8 +180,8 @@
 	 * Is this cycle meant for the CS8900?
 	 */
 	if ((machine_is_ixdp2401() || machine_is_ixdp2801()) && 
-		((port >= IXDP2X01_CS8900_VIRT_BASE) && 
-		 (port <= IXDP2X01_CS8900_VIRT_END))) {
+		(((u32)port >= (u32)IXDP2X01_CS8900_VIRT_BASE) &&
+		 ((u32)port <= (u32)IXDP2X01_CS8900_VIRT_END))) {
 		register u32 tmp32;
 		u8 *buf8 = (u8*)buf;
 		do {
@@ -124,8 +204,8 @@
 	 * Is this cycle meant for the CS8900?
 	 */
 	if ((machine_is_ixdp2401() || machine_is_ixdp2801()) && 
-		((port >= IXDP2X01_CS8900_VIRT_BASE) && 
-		 (port <= IXDP2X01_CS8900_VIRT_END))) {
+		(((u32)port >= (u32)IXDP2X01_CS8900_VIRT_BASE) &&
+		 ((u32)port <= (u32)IXDP2X01_CS8900_VIRT_END))) {
 		return (u16)(*port);  
 	}
 
@@ -137,8 +217,8 @@
 	register volatile u32 *port = (volatile u32 *)ptr;
 
 	if ((machine_is_ixdp2401() || machine_is_ixdp2801()) && 
-		((port >= IXDP2X01_CS8900_VIRT_BASE) && 
-		 (port <= IXDP2X01_CS8900_VIRT_END))) {
+		(((u32)port >= (u32)IXDP2X01_CS8900_VIRT_BASE) &&
+		 ((u32)port <= (u32)IXDP2X01_CS8900_VIRT_END))) {
 		*port = value;  
 		return;
 	}
diff --git a/include/asm-arm/arch-ixp2000/ixdp2x00.h b/include/asm-arm/arch-ixp2000/ixdp2x00.h
index 3a398df..229381c 100644
--- a/include/asm-arm/arch-ixp2000/ixdp2x00.h
+++ b/include/asm-arm/arch-ixp2000/ixdp2x00.h
@@ -21,8 +21,8 @@
  * On board CPLD memory map
  */
 #define IXDP2X00_PHYS_CPLD_BASE		0xc7000000
-#define IXDP2X00_VIRT_CPLD_BASE		0xfafff000
-#define IXDP2X00_CPLD_SIZE		0x00001000
+#define IXDP2X00_VIRT_CPLD_BASE		0xfe000000
+#define IXDP2X00_CPLD_SIZE		0x00100000
 
 
 #define IXDP2X00_CPLD_REG(x)  	\
diff --git a/include/asm-arm/arch-ixp2000/ixdp2x01.h b/include/asm-arm/arch-ixp2000/ixdp2x01.h
index b3a1bcd..b768009 100644
--- a/include/asm-arm/arch-ixp2000/ixdp2x01.h
+++ b/include/asm-arm/arch-ixp2000/ixdp2x01.h
@@ -18,8 +18,8 @@
 #define __IXDP2X01_H__
 
 #define	IXDP2X01_PHYS_CPLD_BASE		0xc6024000
-#define	IXDP2X01_VIRT_CPLD_BASE		0xfafff000
-#define	IXDP2X01_CPLD_REGION_SIZE	0x00001000
+#define	IXDP2X01_VIRT_CPLD_BASE		0xfe000000
+#define	IXDP2X01_CPLD_REGION_SIZE	0x00100000
 
 #define IXDP2X01_CPLD_VIRT_REG(reg) (volatile unsigned long*)(IXDP2X01_VIRT_CPLD_BASE | reg)
 #define IXDP2X01_CPLD_PHYS_REG(reg) (volatile u32*)(IXDP2X01_PHYS_CPLD_BASE | reg)
diff --git a/include/asm-arm/arch-ixp2000/ixp2000-regs.h b/include/asm-arm/arch-ixp2000/ixp2000-regs.h
index 6c56708..75623f8 100644
--- a/include/asm-arm/arch-ixp2000/ixp2000-regs.h
+++ b/include/asm-arm/arch-ixp2000/ixp2000-regs.h
@@ -18,6 +18,21 @@
 #ifndef _IXP2000_REGS_H_
 #define _IXP2000_REGS_H_
 
+/*
+ * IXP2000 linux memory map:
+ *
+ * virt		phys		size
+ * fb000000	db000000	16M		PCI CFG1
+ * fc000000	da000000	16M		PCI CFG0
+ * fd000000	d8000000	16M		PCI I/O
+ * fe[0-7]00000			8M		per-platform mappings
+ * feb00000	c8000000	1M		MSF
+ * fec00000	df000000	1M		PCI CSRs
+ * fed00000	de000000	1M		PCI CREG
+ * fee00000	d6000000	1M		INTCTL
+ * fef00000	c0000000	1M		CAP
+ */
+
 /* 
  * Static I/O regions.
  *
@@ -71,6 +86,10 @@
 #define	IXP2000_PCI_CSR_VIRT_BASE	0xfec00000
 #define	IXP2000_PCI_CSR_SIZE		0x00100000
 
+#define IXP2000_MSF_PHYS_BASE		0xc8000000
+#define IXP2000_MSF_VIRT_BASE		0xfeb00000
+#define IXP2000_MSF_SIZE		0x00100000
+
 #define IXP2000_PCI_IO_PHYS_BASE	0xd8000000
 #define	IXP2000_PCI_IO_VIRT_BASE	0xfd000000
 #define IXP2000_PCI_IO_SIZE     	0x01000000
@@ -241,7 +260,7 @@
 #define PCI_CONTROL_BE_DEI		(1 << 21)	/* Big Endian Data Enable In  */
 #define PCI_CONTROL_BE_BEO		(1 << 20)	/* Big Endian Byte Enable Out */
 #define PCI_CONTROL_BE_BEI		(1 << 19)	/* Big Endian Byte Enable In  */
-#define PCI_CONTROL_PNR			(1 << 17)	/* PCI Not Reset bit */
+#define PCI_CONTROL_IEE			(1 << 17)	/* I/O cycle Endian swap Enable */
 
 #define IXP2000_PCI_RST_REL		(1 << 2)
 #define CFG_RST_DIR			(*IXP2000_PCI_CONTROL & IXP2000_PCICNTL_PCF)
@@ -363,6 +382,7 @@
 #define IXP2000_MIN_REV_MASK	      	0x0000000F
 #define IXP2000_PROD_ID_MASK		0xFFFFFFFF
 
+#define IXP2000_PRODUCT_ID		GLOBAL_REG(0x00)
 #define IXP2000_MISC_CONTROL		GLOBAL_REG(0x04)
 #define IXP2000_MSF_CLK_CNTRL  		GLOBAL_REG(0x08)
 #define IXP2000_RESET0      		GLOBAL_REG(0x0c)
diff --git a/include/asm-arm/arch-ixp2000/platform.h b/include/asm-arm/arch-ixp2000/platform.h
index 901bba6..52ded51 100644
--- a/include/asm-arm/arch-ixp2000/platform.h
+++ b/include/asm-arm/arch-ixp2000/platform.h
@@ -138,30 +138,10 @@
 	unsigned long (*bank_setup)(unsigned long);
 };
 
-/*
- * GPIO helper functions
- */
-#define	GPIO_IN		0
-#define	GPIO_OUT	1
-
-extern void gpio_line_config(int line, int style);
-
-static inline int gpio_line_get(int line)
-{
-	return (((*IXP2000_GPIO_PLR) >> line) & 1);
-}
-
-static inline void gpio_line_set(int line, int value)
-{
-	if (value) 
-		ixp2000_reg_write(IXP2000_GPIO_POSR, (1 << line));
-	else 
-		ixp2000_reg_write(IXP2000_GPIO_POCR, (1 << line));
-}
-
 struct ixp2000_i2c_pins {
 	unsigned long sda_pin;
 	unsigned long scl_pin;
 };
 
+
 #endif /*  !__ASSEMBLY__ */
diff --git a/include/asm-arm/arch-ixp2000/vmalloc.h b/include/asm-arm/arch-ixp2000/vmalloc.h
index 473dff4..2751369 100644
--- a/include/asm-arm/arch-ixp2000/vmalloc.h
+++ b/include/asm-arm/arch-ixp2000/vmalloc.h
@@ -17,4 +17,4 @@
  * The vmalloc() routines leaves a hole of 4kB between each vmalloced
  * area for the same reason. ;)
  */
-#define VMALLOC_END	    0xfaffefff
+#define VMALLOC_END	    0xfb000000
diff --git a/include/asm-arm/arch-ixp4xx/debug-macro.S b/include/asm-arm/arch-ixp4xx/debug-macro.S
index 4499ae8..45a6c6c 100644
--- a/include/asm-arm/arch-ixp4xx/debug-macro.S
+++ b/include/asm-arm/arch-ixp4xx/debug-macro.S
@@ -14,6 +14,7 @@
                 mrc     p15, 0, \rx, c1, c0
                 tst     \rx, #1                 @ MMU enabled?
                 moveq   \rx, #0xc8000000
+		orrne	\rx, \rx, #0x00b00000
                 movne   \rx, #0xff000000
                 add     \rx,\rx,#3              @ Uart regs are at off set of 3 if
 						@ byte writes used - Big Endian.
diff --git a/include/asm-arm/arch-ixp4xx/ixp4xx-regs.h b/include/asm-arm/arch-ixp4xx/ixp4xx-regs.h
index 8eeb1db..004696a 100644
--- a/include/asm-arm/arch-ixp4xx/ixp4xx-regs.h
+++ b/include/asm-arm/arch-ixp4xx/ixp4xx-regs.h
@@ -69,6 +69,16 @@
 #define IXP4XX_PERIPHERAL_BASE_VIRT	(0xFFBF2000)
 #define IXP4XX_PERIPHERAL_REGION_SIZE	(0x0000C000)
 
+/*
+ * Debug UART
+ *
+ * This is basically a remap of UART1 into a region that is section
+ * aligned so that it * can be used with the low-level debug code.
+ */
+#define	IXP4XX_DEBUG_UART_BASE_PHYS	(0xC8000000)
+#define	IXP4XX_DEBUG_UART_BASE_VIRT	(0xffb00000)
+#define	IXP4XX_DEBUG_UART_REGION_SIZE	(0x00001000)
+
 #define IXP4XX_EXP_CS0_OFFSET	0x00
 #define IXP4XX_EXP_CS1_OFFSET   0x04
 #define IXP4XX_EXP_CS2_OFFSET   0x08
diff --git a/include/asm-arm/arch-omap/tps65010.h b/include/asm-arm/arch-omap/tps65010.h
index 0f97bb2..b9aa2b3 100644
--- a/include/asm-arm/arch-omap/tps65010.h
+++ b/include/asm-arm/arch-omap/tps65010.h
@@ -30,6 +30,66 @@
 
 /*
  * ----------------------------------------------------------------------------
+ * Registers, all 8 bits
+ * ----------------------------------------------------------------------------
+ */
+
+#define	TPS_CHGSTATUS		0x01
+#	define	TPS_CHG_USB		(1 << 7)
+#	define	TPS_CHG_AC		(1 << 6)
+#	define	TPS_CHG_THERM		(1 << 5)
+#	define	TPS_CHG_TERM		(1 << 4)
+#	define	TPS_CHG_TAPER_TMO	(1 << 3)
+#	define	TPS_CHG_CHG_TMO		(1 << 2)
+#	define	TPS_CHG_PRECHG_TMO	(1 << 1)
+#	define	TPS_CHG_TEMP_ERR	(1 << 0)
+#define	TPS_REGSTATUS		0x02
+#	define	TPS_REG_ONOFF		(1 << 7)
+#	define	TPS_REG_COVER		(1 << 6)
+#	define	TPS_REG_UVLO		(1 << 5)
+#	define	TPS_REG_NO_CHG		(1 << 4)	/* tps65013 */
+#	define	TPS_REG_PG_LD02		(1 << 3)
+#	define	TPS_REG_PG_LD01		(1 << 2)
+#	define	TPS_REG_PG_MAIN		(1 << 1)
+#	define	TPS_REG_PG_CORE		(1 << 0)
+#define	TPS_MASK1		0x03
+#define	TPS_MASK2		0x04
+#define	TPS_ACKINT1		0x05
+#define	TPS_ACKINT2		0x06
+#define	TPS_CHGCONFIG		0x07
+#	define	TPS_CHARGE_POR		(1 << 7)	/* 65010/65012 */
+#	define	TPS65013_AUA		(1 << 7)	/* 65011/65013 */
+#	define	TPS_CHARGE_RESET	(1 << 6)
+#	define	TPS_CHARGE_FAST		(1 << 5)
+#	define	TPS_CHARGE_CURRENT	(3 << 3)
+#	define	TPS_VBUS_500MA		(1 << 2)
+#	define	TPS_VBUS_CHARGING	(1 << 1)
+#	define	TPS_CHARGE_ENABLE	(1 << 0)
+#define	TPS_LED1_ON		0x08
+#define	TPS_LED1_PER		0x09
+#define	TPS_LED2_ON		0x0a
+#define	TPS_LED2_PER		0x0b
+#define	TPS_VDCDC1		0x0c
+#	define	TPS_ENABLE_LP		(1 << 3)
+#define	TPS_VDCDC2		0x0d
+#define	TPS_VREGS1		0x0e
+#	define	TPS_LDO2_ENABLE	(1 << 7)
+#	define	TPS_LDO2_OFF	(1 << 6)
+#	define	TPS_VLDO2_3_0V	(3 << 4)
+#	define	TPS_VLDO2_2_75V	(2 << 4)
+#	define	TPS_VLDO2_2_5V	(1 << 4)
+#	define	TPS_VLDO2_1_8V	(0 << 4)
+#	define	TPS_LDO1_ENABLE	(1 << 3)
+#	define	TPS_LDO1_OFF	(1 << 2)
+#	define	TPS_VLDO1_3_0V	(3 << 0)
+#	define	TPS_VLDO1_2_75V	(2 << 0)
+#	define	TPS_VLDO1_2_5V	(1 << 0)
+#	define	TPS_VLDO1_ADJ	(0 << 0)
+#define	TPS_MASK3		0x0f
+#define	TPS_DEFGPIO		0x10
+
+/*
+ * ----------------------------------------------------------------------------
  * Macros used by exported functions
  * ----------------------------------------------------------------------------
  */
@@ -71,10 +131,26 @@
  */
 extern int tps65010_set_led(unsigned led, unsigned mode);
 
+/* tps65010_set_vib parameter:
+ * value: ON or OFF
+ */
+extern int tps65010_set_vib(unsigned value);
+
 /* tps65010_set_low_pwr parameter:
  * mode: ON or OFF
  */
 extern int tps65010_set_low_pwr(unsigned mode);
 
+/* tps65010_config_vregs1 parameter:
+ * value to be written to VREGS1 register
+ * Note: The complete register is written, set all bits you need
+ */
+extern int tps65010_config_vregs1(unsigned value);
+
+/* tps65013_set_low_pwr parameter:
+ * mode: ON or OFF
+ */
+extern int tps65013_set_low_pwr(unsigned mode);
+
 #endif /*  __ASM_ARCH_TPS65010_H */
 
diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h
index 39741d3..b5e54a9 100644
--- a/include/asm-arm/arch-pxa/pxa-regs.h
+++ b/include/asm-arm/arch-pxa/pxa-regs.h
@@ -1296,6 +1296,7 @@
 #define GPIO111_MMCDAT3		111	/* MMC DAT3 (PXA27x) */
 #define GPIO111_MMCCS1		111	/* MMC Chip Select 1 (PXA27x) */
 #define GPIO112_MMCCMD		112	/* MMC CMD (PXA27x) */
+#define GPIO113_I2S_SYSCLK	113	/* I2S System Clock (PXA27x) */
 #define GPIO113_AC97_RESET_N	113	/* AC97 NRESET on (PXA27x) */
 
 /* GPIO alternate function mode & direction */
@@ -1428,6 +1429,7 @@
 #define GPIO111_MMCDAT3_MD	(111 | GPIO_ALT_FN_1_OUT)
 #define GPIO110_MMCCS1_MD	(111 | GPIO_ALT_FN_1_OUT)
 #define GPIO112_MMCCMD_MD	(112 | GPIO_ALT_FN_1_OUT)
+#define GPIO113_I2S_SYSCLK_MD	(113 | GPIO_ALT_FN_1_OUT)
 #define GPIO113_AC97_RESET_N_MD	(113 | GPIO_ALT_FN_2_OUT)
 #define GPIO117_I2CSCL_MD	(117 | GPIO_ALT_FN_1_OUT)
 #define GPIO118_I2CSDA_MD	(118 | GPIO_ALT_FN_1_IN)
diff --git a/include/asm-arm/arch-versatile/hardware.h b/include/asm-arm/arch-versatile/hardware.h
index d5fb4a2..41c1bee 100644
--- a/include/asm-arm/arch-versatile/hardware.h
+++ b/include/asm-arm/arch-versatile/hardware.h
@@ -25,19 +25,26 @@
 #include <asm/sizes.h>
 #include <asm/arch/platform.h>
 
-// FIXME = PCI settings need to be fixed!!!!!
-
 /*
- * Similar to above, but for PCI addresses (memory, IO, Config and the
- * V3 chip itself).  WARNING: this has to mirror definitions in platform.h
+ * PCI space virtual addresses
  */
-#define PCI_MEMORY_VADDR       0xe8000000
-#define PCI_CONFIG_VADDR       0xec000000
-#define PCI_V3_VADDR           0xed000000
-#define PCI_IO_VADDR           0xee000000
+#define VERSATILE_PCI_VIRT_BASE		0xe8000000
+#define VERSATILE_PCI_CFG_VIRT_BASE	0xe9000000
 
-#define PCIO_BASE		PCI_IO_VADDR
-#define PCIMEM_BASE		PCI_MEMORY_VADDR
+#if 0
+#define VERSATILE_PCI_VIRT_MEM_BASE0	0xf4000000
+#define VERSATILE_PCI_VIRT_MEM_BASE1	0xf5000000
+#define VERSATILE_PCI_VIRT_MEM_BASE2	0xf6000000
+
+#define PCIO_BASE			VERSATILE_PCI_VIRT_MEM_BASE0
+#define PCIMEM_BASE			VERSATILE_PCI_VIRT_MEM_BASE1
+#endif
+
+/* CIK guesswork */
+#define PCIBIOS_MIN_IO			0x44000000
+#define PCIBIOS_MIN_MEM			0x50000000
+
+#define pcibios_assign_all_busses()     1
 
 /* macro to get at IO space when running virtually */
 #define IO_ADDRESS(x)		(((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
diff --git a/include/asm-arm/arch-versatile/io.h b/include/asm-arm/arch-versatile/io.h
index dbb7158..9f895bf 100644
--- a/include/asm-arm/arch-versatile/io.h
+++ b/include/asm-arm/arch-versatile/io.h
@@ -20,7 +20,7 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
-#define IO_SPACE_LIMIT 0xffff
+#define IO_SPACE_LIMIT 0xffffffff
 
 #define __io(a)			((void __iomem *)(a))
 #define __mem_pci(a)		(a)
diff --git a/include/asm-arm/arch-versatile/platform.h b/include/asm-arm/arch-versatile/platform.h
index 2598d1f..cbdd9fb 100644
--- a/include/asm-arm/arch-versatile/platform.h
+++ b/include/asm-arm/arch-versatile/platform.h
@@ -76,7 +76,7 @@
 #define VERSATILE_SYS_NVFLAGSSET_OFFSET       0x38
 #define VERSATILE_SYS_NVFLAGSCLR_OFFSET       0x3C
 #define VERSATILE_SYS_RESETCTL_OFFSET         0x40
-#define VERSATILE_SYS_PICCTL_OFFSET           0x44
+#define VERSATILE_SYS_PCICTL_OFFSET           0x44
 #define VERSATILE_SYS_MCI_OFFSET              0x48
 #define VERSATILE_SYS_FLASH_OFFSET            0x4C
 #define VERSATILE_SYS_CLCD_OFFSET             0x50
@@ -114,7 +114,7 @@
 #define VERSATILE_SYS_NVFLAGSSET              (VERSATILE_SYS_BASE + VERSATILE_SYS_NVFLAGSSET_OFFSET)
 #define VERSATILE_SYS_NVFLAGSCLR              (VERSATILE_SYS_BASE + VERSATILE_SYS_NVFLAGSCLR_OFFSET)
 #define VERSATILE_SYS_RESETCTL                (VERSATILE_SYS_BASE + VERSATILE_SYS_RESETCTL_OFFSET)
-#define VERSATILE_SYS_PICCTL                  (VERSATILE_SYS_BASE + VERSATILE_SYS_PICCTL_OFFSET)
+#define VERSATILE_SYS_PCICTL                  (VERSATILE_SYS_BASE + VERSATILE_SYS_PCICTL_OFFSET)
 #define VERSATILE_SYS_MCI                     (VERSATILE_SYS_BASE + VERSATILE_SYS_MCI_OFFSET)
 #define VERSATILE_SYS_FLASH                   (VERSATILE_SYS_BASE + VERSATILE_SYS_FLASH_OFFSET)
 #define VERSATILE_SYS_CLCD                    (VERSATILE_SYS_BASE + VERSATILE_SYS_CLCD_OFFSET)
@@ -225,7 +225,20 @@
 #define VERSATILE_SSMC_BASE            0x20000000	/* SSMC */
 #define VERSATILE_IB2_BASE             0x24000000	/* IB2 module */
 #define VERSATILE_MBX_BASE             0x40000000	/* MBX */
+
+/* PCI space */
 #define VERSATILE_PCI_BASE             0x41000000	/* PCI Interface */
+#define VERSATILE_PCI_CFG_BASE	       0x42000000
+#define VERSATILE_PCI_MEM_BASE0        0x44000000
+#define VERSATILE_PCI_MEM_BASE1        0x50000000
+#define VERSATILE_PCI_MEM_BASE2        0x60000000
+/* Sizes of above maps */
+#define VERSATILE_PCI_BASE_SIZE	       0x01000000
+#define VERSATILE_PCI_CFG_BASE_SIZE    0x02000000
+#define VERSATILE_PCI_MEM_BASE0_SIZE   0x0c000000	/* 32Mb */
+#define VERSATILE_PCI_MEM_BASE1_SIZE   0x10000000	/* 256Mb */
+#define VERSATILE_PCI_MEM_BASE2_SIZE   0x10000000	/* 256Mb */
+
 #define VERSATILE_SDRAM67_BASE         0x70000000	/* SDRAM banks 6 and 7 */
 #define VERSATILE_LT_BASE              0x80000000	/* Logic Tile expansion */
 
@@ -498,11 +511,17 @@
 /*
  * IB2 Versatile/AB expansion board definitions
  */
-#define VERSATILE_IB2_CAMERA_BANK	0x24000000
-#define VERSATILE_IB2_KBD_DATAREG	0x25000000
-#define VERSATILE_IB2_IER		0x26000000	/* for VICINTSOURCE27 */
-#define VERSATILE_IB2_CTRL		0x27000000
-#define VERSATILE_IB2_STAT		0x27000004
+#define VERSATILE_IB2_CAMERA_BANK	VERSATILE_IB2_BASE
+#define VERSATILE_IB2_KBD_DATAREG	(VERSATILE_IB2_BASE + 0x01000000)
+
+/* VICINTSOURCE27 */
+#define VERSATILE_IB2_INT_BASE		(VERSATILE_IB2_BASE + 0x02000000)
+#define VERSATILE_IB2_IER		(VERSATILE_IB2_INT_BASE + 0)
+#define VERSATILE_IB2_ISR		(VERSATILE_IB2_INT_BASE + 4)
+
+#define VERSATILE_IB2_CTL_BASE		(VERSATILE_IB2_BASE + 0x03000000)
+#define VERSATILE_IB2_CTRL		(VERSATILE_IB2_CTL_BASE + 0)
+#define VERSATILE_IB2_STAT		(VERSATILE_IB2_CTL_BASE + 4)
 #endif
 
 #endif
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h
index 09ffeed..035cdcf 100644
--- a/include/asm-arm/cacheflush.h
+++ b/include/asm-arm/cacheflush.h
@@ -16,6 +16,9 @@
 
 #include <asm/mman.h>
 #include <asm/glue.h>
+#include <asm/shmparam.h>
+
+#define CACHE_COLOUR(vaddr)	((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
 
 /*
  *	Cache Model
diff --git a/include/asm-arm/elf.h b/include/asm-arm/elf.h
index cbceacbe..a1696ba 100644
--- a/include/asm-arm/elf.h
+++ b/include/asm-arm/elf.h
@@ -38,9 +38,9 @@
  */
 #define ELF_CLASS	ELFCLASS32
 #ifdef __ARMEB__
-#define ELF_DATA	ELFDATA2MSB;
+#define ELF_DATA	ELFDATA2MSB
 #else
-#define ELF_DATA	ELFDATA2LSB;
+#define ELF_DATA	ELFDATA2LSB
 #endif
 #define ELF_ARCH	EM_ARM
 
diff --git a/include/asm-arm/io.h b/include/asm-arm/io.h
index 658ffa3..cc4b5f5 100644
--- a/include/asm-arm/io.h
+++ b/include/asm-arm/io.h
@@ -273,6 +273,35 @@
 #endif
 
 /*
+ * io{read,write}{8,16,32} macros
+ */
+#ifndef ioread8
+#define ioread8(p)	({ unsigned int __v = __raw_readb(p); __v; })
+#define ioread16(p)	({ unsigned int __v = le16_to_cpu(__raw_readw(p)); __v; })
+#define ioread32(p)	({ unsigned int __v = le32_to_cpu(__raw_readl(p)); __v; })
+
+#define iowrite8(v,p)	__raw_writeb(v, p)
+#define iowrite16(v,p)	__raw_writew(cpu_to_le16(v), p)
+#define iowrite32(v,p)	__raw_writel(cpu_to_le32(v), p)
+
+#define ioread8_rep(p,d,c)	__raw_readsb(p,d,c)
+#define ioread16_rep(p,d,c)	__raw_readsw(p,d,c)
+#define ioread32_rep(p,d,c)	__raw_readsl(p,d,c)
+
+#define iowrite8_rep(p,s,c)	__raw_writesb(p,s,c)
+#define iowrite16_rep(p,s,c)	__raw_writesw(p,s,c)
+#define iowrite32_rep(p,s,c)	__raw_writesl(p,s,c)
+
+extern void __iomem *ioport_map(unsigned long port, unsigned int nr);
+extern void ioport_unmap(void __iomem *addr);
+#endif
+
+struct pci_dev;
+
+extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen);
+extern void pci_iounmap(struct pci_dev *dev, void __iomem *addr);
+
+/*
  * can the hardware map this into one segment or not, given no other
  * constraints.
  */
diff --git a/include/asm-arm/mach/time.h b/include/asm-arm/mach/time.h
index 5cf4fd6..047980a 100644
--- a/include/asm-arm/mach/time.h
+++ b/include/asm-arm/mach/time.h
@@ -39,8 +39,29 @@
 	void			(*suspend)(void);
 	void			(*resume)(void);
 	unsigned long		(*offset)(void);
+
+#ifdef CONFIG_NO_IDLE_HZ
+	struct dyn_tick_timer	*dyn_tick;
+#endif
 };
 
+#ifdef CONFIG_NO_IDLE_HZ
+
+#define DYN_TICK_SKIPPING	(1 << 2)
+#define DYN_TICK_ENABLED	(1 << 1)
+#define DYN_TICK_SUITABLE	(1 << 0)
+
+struct dyn_tick_timer {
+	unsigned int	state;			/* Current state */
+	int		(*enable)(void);	/* Enables dynamic tick */
+	int		(*disable)(void);	/* Disables dynamic tick */
+	void		(*reprogram)(unsigned long); /* Reprograms the timer */
+	int		(*handler)(int, void *, struct pt_regs *);
+};
+
+void timer_dyn_reprogram(void);
+#endif
+
 extern struct sys_timer *system_timer;
 extern void timer_tick(struct pt_regs *);
 
diff --git a/include/asm-arm/pgalloc.h b/include/asm-arm/pgalloc.h
index e814f81..bc18ff4 100644
--- a/include/asm-arm/pgalloc.h
+++ b/include/asm-arm/pgalloc.h
@@ -89,6 +89,13 @@
 	__free_page(pte);
 }
 
+static inline void __pmd_populate(pmd_t *pmdp, unsigned long pmdval)
+{
+	pmdp[0] = __pmd(pmdval);
+	pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
+	flush_pmd_entry(pmdp);
+}
+
 /*
  * Populate the pmdp entry with a pointer to the pte.  This pmd is part
  * of the mm address space.
@@ -99,32 +106,19 @@
 pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
 {
 	unsigned long pte_ptr = (unsigned long)ptep;
-	unsigned long pmdval;
-
-	BUG_ON(mm != &init_mm);
 
 	/*
 	 * The pmd must be loaded with the physical
 	 * address of the PTE table
 	 */
 	pte_ptr -= PTRS_PER_PTE * sizeof(void *);
-	pmdval = __pa(pte_ptr) | _PAGE_KERNEL_TABLE;
-	pmdp[0] = __pmd(pmdval);
-	pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
-	flush_pmd_entry(pmdp);
+	__pmd_populate(pmdp, __pa(pte_ptr) | _PAGE_KERNEL_TABLE);
 }
 
 static inline void
 pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *ptep)
 {
-	unsigned long pmdval;
-
-	BUG_ON(mm == &init_mm);
-
-	pmdval = page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE;
-	pmdp[0] = __pmd(pmdval);
-	pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
-	flush_pmd_entry(pmdp);
+	__pmd_populate(pmdp, page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE);
 }
 
 #endif
diff --git a/include/asm-arm/signal.h b/include/asm-arm/signal.h
index 46e69ae..760f6e6 100644
--- a/include/asm-arm/signal.h
+++ b/include/asm-arm/signal.h
@@ -114,6 +114,7 @@
 #define SIGSTKSZ	8192
 
 #ifdef __KERNEL__
+#define SA_TIMER		0x40000000
 #define SA_IRQNOMASK		0x08000000
 #endif
 
diff --git a/include/asm-arm/smp.h b/include/asm-arm/smp.h
index f21fd8f..6c6c60a 100644
--- a/include/asm-arm/smp.h
+++ b/include/asm-arm/smp.h
@@ -21,7 +21,7 @@
 # error "<asm-arm/smp.h> included in non-SMP build"
 #endif
 
-#define smp_processor_id()	(current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
 
 extern cpumask_t cpu_present_mask;
 #define cpu_possible_map cpu_present_mask
@@ -55,4 +55,18 @@
  */
 extern int boot_secondary(unsigned int cpu, struct task_struct *);
 
+/*
+ * Perform platform specific initialisation of the specified CPU.
+ */
+extern void platform_secondary_init(unsigned int cpu);
+
+/*
+ * Initial data for bringing up a secondary CPU.
+ */
+struct secondary_data {
+	unsigned long pgdir;
+	void *stack;
+};
+extern struct secondary_data secondary_data;
+
 #endif /* ifndef __ASM_ARM_SMP_H */
diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h
index b13a8da..3d0d286 100644
--- a/include/asm-arm/system.h
+++ b/include/asm-arm/system.h
@@ -104,6 +104,7 @@
 extern void __show_regs(struct pt_regs *);
 
 extern int cpu_architecture(void);
+extern void cpu_init(void);
 
 #define set_cr(x)					\
 	__asm__ __volatile__(				\
@@ -144,34 +145,12 @@
 #define set_wmb(var, value) do { var = value; wmb(); } while (0)
 #define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
 
-#ifdef CONFIG_SMP
 /*
- * Define our own context switch locking.  This allows us to enable
- * interrupts over the context switch, otherwise we end up with high
- * interrupt latency.  The real problem area is switch_mm() which may
- * do a full cache flush.
+ * switch_mm() may do a full cache flush over the context switch,
+ * so enable interrupts over the context switch to avoid high
+ * latency.
  */
-#define prepare_arch_switch(rq,next)					\
-do {									\
-	spin_lock(&(next)->switch_lock);				\
-	spin_unlock_irq(&(rq)->lock);					\
-} while (0)
-
-#define finish_arch_switch(rq,prev)					\
-	spin_unlock(&(prev)->switch_lock)
-
-#define task_running(rq,p)						\
-	((rq)->curr == (p) || spin_is_locked(&(p)->switch_lock))
-#else
-/*
- * Our UP-case is more simple, but we assume knowledge of how
- * spin_unlock_irq() and friends are implemented.  This avoids
- * us needlessly decrementing and incrementing the preempt count.
- */
-#define prepare_arch_switch(rq,next)	local_irq_enable()
-#define finish_arch_switch(rq,prev)	spin_unlock(&(rq)->lock)
-#define task_running(rq,p)		((rq)->curr == (p))
-#endif
+#define __ARCH_WANT_INTERRUPTS_ON_CTXSW
 
 /*
  * switch_to(prev, next) should switch from task `prev' to `next'
@@ -307,7 +286,7 @@
 ({					\
 	unsigned long flags;		\
 	local_save_flags(flags);	\
-	flags & PSR_I_BIT;		\
+	(int)(flags & PSR_I_BIT);	\
 })
 
 #ifdef CONFIG_SMP
diff --git a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h
index 66c585c..8252a4c 100644
--- a/include/asm-arm/thread_info.h
+++ b/include/asm-arm/thread_info.h
@@ -49,7 +49,7 @@
  */
 struct thread_info {
 	unsigned long		flags;		/* low level flags */
-	__s32			preempt_count;	/* 0 => preemptable, <0 => bug */
+	int			preempt_count;	/* 0 => preemptable, <0 => bug */
 	mm_segment_t		addr_limit;	/* address limit */
 	struct task_struct	*task;		/* main task structure */
 	struct exec_domain	*exec_domain;	/* execution domain */
diff --git a/include/asm-arm26/elf.h b/include/asm-arm26/elf.h
index 8b14947..5a47fdb 100644
--- a/include/asm-arm26/elf.h
+++ b/include/asm-arm26/elf.h
@@ -36,7 +36,7 @@
  * These are used to set parameters in the core dumps.
  */
 #define ELF_CLASS	ELFCLASS32
-#define ELF_DATA	ELFDATA2LSB;
+#define ELF_DATA	ELFDATA2LSB
 #define ELF_ARCH	EM_ARM
 
 #define USE_ELF_CORE_DUMP
diff --git a/include/asm-arm26/signal.h b/include/asm-arm26/signal.h
index dedb292..37ad253 100644
--- a/include/asm-arm26/signal.h
+++ b/include/asm-arm26/signal.h
@@ -166,9 +166,6 @@
 #include <asm/sigcontext.h>
 
 #define sigmask(sig)	(1UL << ((sig) - 1))
-//FIXME!!!
-//#define HAVE_ARCH_GET_SIGNAL_TO_DELIVER
-
 #endif
 
 
diff --git a/include/asm-arm26/thread_info.h b/include/asm-arm26/thread_info.h
index 50f41b5..aff3e56 100644
--- a/include/asm-arm26/thread_info.h
+++ b/include/asm-arm26/thread_info.h
@@ -44,7 +44,7 @@
  */
 struct thread_info {
 	unsigned long		flags;		/* low level flags */
-	__s32			preempt_count;	/* 0 => preemptable, <0 => bug */
+	int			preempt_count;	/* 0 => preemptable, <0 => bug */
 	mm_segment_t		addr_limit;	/* address limit */
 	struct task_struct	*task;		/* main task structure */
 	struct exec_domain      *exec_domain;   /* execution domain */
diff --git a/include/asm-cris/thread_info.h b/include/asm-cris/thread_info.h
index 53193fe..5ba4b78 100644
--- a/include/asm-cris/thread_info.h
+++ b/include/asm-cris/thread_info.h
@@ -31,7 +31,7 @@
 	struct exec_domain	*exec_domain;	/* execution domain */
 	unsigned long		flags;		/* low level flags */
 	__u32			cpu;		/* current CPU */
-	__s32			preempt_count; /* 0 => preemptable, <0 => BUG */
+	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user-thead
diff --git a/include/asm-frv/thread_info.h b/include/asm-frv/thread_info.h
index b80a97f..c8cba78 100644
--- a/include/asm-frv/thread_info.h
+++ b/include/asm-frv/thread_info.h
@@ -33,7 +33,7 @@
 	unsigned long		flags;		/* low level flags */
 	unsigned long		status;		/* thread-synchronous flags */
 	__u32			cpu;		/* current CPU */
-	__s32			preempt_count;	/* 0 => preemptable, <0 => BUG */
+	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user-thead
diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h
index 3b709b8..9044aeb 100644
--- a/include/asm-generic/percpu.h
+++ b/include/asm-generic/percpu.h
@@ -29,7 +29,7 @@
 #define DEFINE_PER_CPU(type, name) \
     __typeof__(type) per_cpu__##name
 
-#define per_cpu(var, cpu)			(*((void)cpu, &per_cpu__##var))
+#define per_cpu(var, cpu)			(*((void)(cpu), &per_cpu__##var))
 #define __get_cpu_var(var)			per_cpu__##var
 
 #endif	/* SMP */
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 1f4ec7b..f405935 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -125,6 +125,9 @@
 
 #ifndef __HAVE_ARCH_PAGE_TEST_AND_CLEAR_DIRTY
 #define page_test_and_clear_dirty(page) (0)
+#define pte_maybe_dirty(pte)		pte_dirty(pte)
+#else
+#define pte_maybe_dirty(pte)		(1)
 #endif
 
 #ifndef __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG
diff --git a/include/asm-generic/topology.h b/include/asm-generic/topology.h
index ec96e8b..5d9d70c 100644
--- a/include/asm-generic/topology.h
+++ b/include/asm-generic/topology.h
@@ -41,8 +41,15 @@
 #ifndef node_to_first_cpu
 #define node_to_first_cpu(node)	(0)
 #endif
+#ifndef pcibus_to_node
+#define pcibus_to_node(node)	(-1)
+#endif
+
 #ifndef pcibus_to_cpumask
-#define pcibus_to_cpumask(bus)	(cpu_online_map)
+#define pcibus_to_cpumask(bus)	(pcibus_to_node(bus) == -1 ? \
+					CPU_MASK_ALL : \
+					node_to_cpumask(pcibus_to_node(bus)) \
+				)
 #endif
 
 #endif /* _ASM_GENERIC_TOPOLOGY_H */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 99cef06..b3bb326 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -73,7 +73,7 @@
 	}
 
 #define SECURITY_INIT							\
-	.security_initcall.init : {					\
+	.security_initcall.init : AT(ADDR(.security_initcall.init) - LOAD_OFFSET) { \
 		VMLINUX_SYMBOL(__security_initcall_start) = .;		\
 		*(.security_initcall.init) 				\
 		VMLINUX_SYMBOL(__security_initcall_end) = .;		\
diff --git a/include/asm-h8300/kmap_types.h b/include/asm-h8300/kmap_types.h
index 82431ed..1ec8a34 100644
--- a/include/asm-h8300/kmap_types.h
+++ b/include/asm-h8300/kmap_types.h
@@ -1,5 +1,5 @@
-#ifndef _ASM_KMAP_TYPES_H
-#define _ASM_KMAP_TYPES_H
+#ifndef _ASM_H8300_KMAP_TYPES_H
+#define _ASM_H8300_KMAP_TYPES_H
 
 enum km_type {
 	KM_BOUNCE_READ,
@@ -13,6 +13,8 @@
 	KM_PTE1,
 	KM_IRQ0,
 	KM_IRQ1,
+	KM_SOFTIRQ0,
+	KM_SOFTIRQ1,
 	KM_TYPE_NR
 };
 
diff --git a/include/asm-h8300/mman.h b/include/asm-h8300/mman.h
index abe0885..63f727a 100644
--- a/include/asm-h8300/mman.h
+++ b/include/asm-h8300/mman.h
@@ -4,6 +4,7 @@
 #define PROT_READ	0x1		/* page can be read */
 #define PROT_WRITE	0x2		/* page can be written */
 #define PROT_EXEC	0x4		/* page can be executed */
+#define PROT_SEM	0x8		/* page may be used for atomic ops */
 #define PROT_NONE	0x0		/* page can not be accessed */
 #define PROT_GROWSDOWN	0x01000000	/* mprotect flag: extend change to start of growsdown vma */
 #define PROT_GROWSUP	0x02000000	/* mprotect flag: extend change to end of growsup vma */
@@ -19,6 +20,8 @@
 #define MAP_EXECUTABLE	0x1000		/* mark it as an executable */
 #define MAP_LOCKED	0x2000		/* pages are locked */
 #define MAP_NORESERVE	0x4000		/* don't check for reservations */
+#define MAP_POPULATE	0x8000		/* populate (prefault) pagetables */
+#define MAP_NONBLOCK	0x10000		/* do not block on IO */
 
 #define MS_ASYNC	1		/* sync memory asynchronously */
 #define MS_INVALIDATE	2		/* invalidate the caches */
diff --git a/include/asm-h8300/thread_info.h b/include/asm-h8300/thread_info.h
index b07c934..bfcc755 100644
--- a/include/asm-h8300/thread_info.h
+++ b/include/asm-h8300/thread_info.h
@@ -23,7 +23,7 @@
 	struct exec_domain *exec_domain;	/* execution domain */
 	unsigned long	   flags;		/* low level flags */
 	int		   cpu;			/* cpu we're on */
-	int		   preempt_count;	/* 0 => preemptable, <0 => BUG*/
+	int		   preempt_count;	/* 0 => preemptable, <0 => BUG */
 	struct restart_block restart_block;
 };
 
diff --git a/include/asm-i386/agp.h b/include/asm-i386/agp.h
index a917ff5..b82f5f3 100644
--- a/include/asm-i386/agp.h
+++ b/include/asm-i386/agp.h
@@ -21,4 +21,14 @@
    worth it. Would need a page for it. */
 #define flush_agp_cache() asm volatile("wbinvd":::"memory")
 
+/* Convert a physical address to an address suitable for the GART. */
+#define phys_to_gart(x) (x)
+#define gart_to_phys(x) (x)
+
+/* GATT allocation. Returns/accepts GATT kernel virtual address. */
+#define alloc_gatt_pages(order)		\
+	((char *)__get_free_pages(GFP_KERNEL, (order)))
+#define free_gatt_pages(table, order)	\
+	free_pages((unsigned long)(table), (order))
+
 #endif
diff --git a/include/asm-i386/apic.h b/include/asm-i386/apic.h
index a5810cf..6a1b188 100644
--- a/include/asm-i386/apic.h
+++ b/include/asm-i386/apic.h
@@ -5,6 +5,7 @@
 #include <linux/pm.h>
 #include <asm/fixmap.h>
 #include <asm/apicdef.h>
+#include <asm/processor.h>
 #include <asm/system.h>
 
 #define Dprintk(x...)
@@ -16,8 +17,20 @@
 #define APIC_VERBOSE 1
 #define APIC_DEBUG   2
 
+extern int enable_local_apic;
 extern int apic_verbosity;
 
+static inline void lapic_disable(void)
+{
+	enable_local_apic = -1;
+	clear_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability);
+}
+
+static inline void lapic_enable(void)
+{
+	enable_local_apic = 1;
+}
+
 /*
  * Define the default level of output to be very little
  * This can be turned up by using apic=verbose for more
@@ -87,7 +100,7 @@
 extern int get_maxlvt(void);
 extern void clear_local_APIC(void);
 extern void connect_bsp_APIC (void);
-extern void disconnect_bsp_APIC (void);
+extern void disconnect_bsp_APIC (int virt_wire_setup);
 extern void disable_local_APIC (void);
 extern void lapic_shutdown (void);
 extern int verify_local_APIC (void);
diff --git a/include/asm-i386/apicdef.h b/include/asm-i386/apicdef.h
index c689554..0fed5e3 100644
--- a/include/asm-i386/apicdef.h
+++ b/include/asm-i386/apicdef.h
@@ -86,11 +86,12 @@
 #define			APIC_LVT_REMOTE_IRR		(1<<14)
 #define			APIC_INPUT_POLARITY		(1<<13)
 #define			APIC_SEND_PENDING		(1<<12)
+#define			APIC_MODE_MASK			0x700
 #define			GET_APIC_DELIVERY_MODE(x)	(((x)>>8)&0x7)
 #define			SET_APIC_DELIVERY_MODE(x,y)	(((x)&~0x700)|((y)<<8))
 #define				APIC_MODE_FIXED		0x0
 #define				APIC_MODE_NMI		0x4
-#define				APIC_MODE_EXINT		0x7
+#define				APIC_MODE_EXTINT	0x7
 #define 	APIC_LVT1	0x360
 #define		APIC_LVTERR	0x370
 #define		APIC_TMICT	0x380
diff --git a/include/asm-i386/checksum.h b/include/asm-i386/checksum.h
index 6413420..f949e44 100644
--- a/include/asm-i386/checksum.h
+++ b/include/asm-i386/checksum.h
@@ -3,6 +3,8 @@
 
 #include <linux/in6.h>
 
+#include <asm/uaccess.h>
+
 /*
  * computes the checksum of a memory block at buff, length len,
  * and adds in "sum" (32-bit)
diff --git a/include/asm-i386/cpu.h b/include/asm-i386/cpu.h
index 002740b..e7252c2 100644
--- a/include/asm-i386/cpu.h
+++ b/include/asm-i386/cpu.h
@@ -5,6 +5,7 @@
 #include <linux/cpu.h>
 #include <linux/topology.h>
 #include <linux/nodemask.h>
+#include <linux/percpu.h>
 
 #include <asm/node.h>
 
@@ -16,4 +17,5 @@
 extern void arch_unregister_cpu(int);
 #endif
 
+DECLARE_PER_CPU(int, cpu_state);
 #endif /* _ASM_I386_CPU_H_ */
diff --git a/include/asm-i386/genapic.h b/include/asm-i386/genapic.h
index fc813b2..b3783a3 100644
--- a/include/asm-i386/genapic.h
+++ b/include/asm-i386/genapic.h
@@ -78,7 +78,6 @@
 	.int_delivery_mode = INT_DELIVERY_MODE, \
 	.int_dest_mode = INT_DEST_MODE, \
 	.no_balance_irq = NO_BALANCE_IRQ, \
-	.no_ioapic_check = NO_IOAPIC_CHECK, \
 	.ESR_DISABLE = esr_disable, \
 	.apic_destination_logical = APIC_DEST_LOGICAL, \
 	APICFUNC(apic_id_registered), \
diff --git a/include/asm-i386/highmem.h b/include/asm-i386/highmem.h
index 1df42bf..0fd3313 100644
--- a/include/asm-i386/highmem.h
+++ b/include/asm-i386/highmem.h
@@ -70,6 +70,7 @@
 void kunmap(struct page *page);
 void *kmap_atomic(struct page *page, enum km_type type);
 void kunmap_atomic(void *kvaddr, enum km_type type);
+void *kmap_atomic_pfn(unsigned long pfn, enum km_type type);
 struct page *kmap_atomic_to_page(void *ptr);
 
 #define flush_cache_kmaps()	do { } while (0)
diff --git a/include/asm-i386/irq.h b/include/asm-i386/irq.h
index 05b9e61..270f198 100644
--- a/include/asm-i386/irq.h
+++ b/include/asm-i386/irq.h
@@ -29,13 +29,19 @@
 
 #ifdef CONFIG_4KSTACKS
   extern void irq_ctx_init(int cpu);
+  extern void irq_ctx_exit(int cpu);
 # define __ARCH_HAS_DO_SOFTIRQ
 #else
 # define irq_ctx_init(cpu) do { } while (0)
+# define irq_ctx_exit(cpu) do { } while (0)
 #endif
 
 #ifdef CONFIG_IRQBALANCE
 extern int irqbalance_disable(char *str);
 #endif
 
+#ifdef CONFIG_HOTPLUG_CPU
+extern void fixup_irqs(cpumask_t map);
+#endif
+
 #endif /* _ASM_IRQ_H */
diff --git a/include/asm-i386/kdebug.h b/include/asm-i386/kdebug.h
index de6498b..b3f8d5f 100644
--- a/include/asm-i386/kdebug.h
+++ b/include/asm-i386/kdebug.h
@@ -18,7 +18,7 @@
 };
 
 /* Note - you should never unregister because that can race with NMIs.
-   If you really want to do it first unregister - then synchronize_kernel - then free.
+   If you really want to do it first unregister - then synchronize_sched - then free.
   */
 int register_die_notifier(struct notifier_block *nb);
 extern struct notifier_block *i386die_chain;
diff --git a/include/asm-i386/kexec.h b/include/asm-i386/kexec.h
new file mode 100644
index 0000000..6ed2a03
--- /dev/null
+++ b/include/asm-i386/kexec.h
@@ -0,0 +1,33 @@
+#ifndef _I386_KEXEC_H
+#define _I386_KEXEC_H
+
+#include <asm/fixmap.h>
+
+/*
+ * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.
+ * I.e. Maximum page that is mapped directly into kernel memory,
+ * and kmap is not required.
+ *
+ * Someone correct me if FIXADDR_START - PAGEOFFSET is not the correct
+ * calculation for the amount of memory directly mappable into the
+ * kernel memory space.
+ */
+
+/* Maximum physical address we can use pages from */
+#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
+/* Maximum address we can reach in physical address mode */
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
+/* Maximum address we can use for the control code buffer */
+#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE
+
+#define KEXEC_CONTROL_CODE_SIZE	4096
+
+/* The native architecture */
+#define KEXEC_ARCH KEXEC_ARCH_386
+
+#define MAX_NOTE_BYTES 1024
+typedef u32 note_buf_t[MAX_NOTE_BYTES/4];
+
+extern note_buf_t crash_notes[];
+
+#endif /* _I386_KEXEC_H */
diff --git a/include/asm-i386/kprobes.h b/include/asm-i386/kprobes.h
index 4092f68..8b6d3a9 100644
--- a/include/asm-i386/kprobes.h
+++ b/include/asm-i386/kprobes.h
@@ -39,6 +39,9 @@
 	: (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR)))
 
 #define JPROBE_ENTRY(pentry)	(kprobe_opcode_t *)pentry
+#define ARCH_SUPPORTS_KRETPROBES
+
+void kretprobe_trampoline(void);
 
 /* Architecture specific copy of original instruction*/
 struct arch_specific_insn {
diff --git a/include/asm-i386/mach-bigsmp/mach_apic.h b/include/asm-i386/mach-bigsmp/mach_apic.h
index 2339868..ba936d4 100644
--- a/include/asm-i386/mach-bigsmp/mach_apic.h
+++ b/include/asm-i386/mach-bigsmp/mach_apic.h
@@ -14,8 +14,6 @@
 #define NO_BALANCE_IRQ (1)
 #define esr_disable (1)
 
-#define NO_IOAPIC_CHECK (0)
-
 static inline int apic_id_registered(void)
 {
 	return (1);
diff --git a/include/asm-i386/mach-default/mach_apic.h b/include/asm-i386/mach-default/mach_apic.h
index 627f1cd..3ef6292 100644
--- a/include/asm-i386/mach-default/mach_apic.h
+++ b/include/asm-i386/mach-default/mach_apic.h
@@ -19,8 +19,6 @@
 #define NO_BALANCE_IRQ (0)
 #define esr_disable (0)
 
-#define NO_IOAPIC_CHECK (0)
-
 #define INT_DELIVERY_MODE dest_LowestPrio
 #define INT_DEST_MODE 1     /* logical delivery broadcast to all procs */
 
diff --git a/include/asm-i386/mach-default/mach_ipi.h b/include/asm-i386/mach-default/mach_ipi.h
index 6f2b17a..cc756a6 100644
--- a/include/asm-i386/mach-default/mach_ipi.h
+++ b/include/asm-i386/mach-default/mach_ipi.h
@@ -4,11 +4,34 @@
 void send_IPI_mask_bitmask(cpumask_t mask, int vector);
 void __send_IPI_shortcut(unsigned int shortcut, int vector);
 
+extern int no_broadcast;
+
 static inline void send_IPI_mask(cpumask_t mask, int vector)
 {
 	send_IPI_mask_bitmask(mask, vector);
 }
 
+static inline void __local_send_IPI_allbutself(int vector)
+{
+	if (no_broadcast) {
+		cpumask_t mask = cpu_online_map;
+		int this_cpu = get_cpu();
+
+		cpu_clear(this_cpu, mask);
+		send_IPI_mask(mask, vector);
+		put_cpu();
+	} else
+		__send_IPI_shortcut(APIC_DEST_ALLBUT, vector);
+}
+
+static inline void __local_send_IPI_all(int vector)
+{
+	if (no_broadcast)
+		send_IPI_mask(cpu_online_map, vector);
+	else
+		__send_IPI_shortcut(APIC_DEST_ALLINC, vector);
+}
+
 static inline void send_IPI_allbutself(int vector)
 {
 	/*
@@ -18,13 +41,13 @@
 	if (!(num_online_cpus() > 1))
 		return;
 
-	__send_IPI_shortcut(APIC_DEST_ALLBUT, vector);
+	__local_send_IPI_allbutself(vector);
 	return;
 }
 
 static inline void send_IPI_all(int vector)
 {
-	__send_IPI_shortcut(APIC_DEST_ALLINC, vector);
+	__local_send_IPI_all(vector);
 }
 
 #endif /* __ASM_MACH_IPI_H */
diff --git a/include/asm-i386/mach-es7000/mach_apic.h b/include/asm-i386/mach-es7000/mach_apic.h
index ceab2c4..b5f3f0d 100644
--- a/include/asm-i386/mach-es7000/mach_apic.h
+++ b/include/asm-i386/mach-es7000/mach_apic.h
@@ -38,8 +38,6 @@
 #define WAKE_SECONDARY_VIA_INIT
 #endif
 
-#define NO_IOAPIC_CHECK (1)
-
 static inline unsigned long check_apicid_used(physid_mask_t bitmap, int apicid)
 { 
 	return 0;
diff --git a/include/asm-i386/mach-generic/mach_apic.h b/include/asm-i386/mach-generic/mach_apic.h
index ab36d02..b13767a 100644
--- a/include/asm-i386/mach-generic/mach_apic.h
+++ b/include/asm-i386/mach-generic/mach_apic.h
@@ -5,7 +5,6 @@
 
 #define esr_disable (genapic->ESR_DISABLE)
 #define NO_BALANCE_IRQ (genapic->no_balance_irq)
-#define NO_IOAPIC_CHECK	(genapic->no_ioapic_check)
 #define INT_DELIVERY_MODE (genapic->int_delivery_mode)
 #define INT_DEST_MODE (genapic->int_dest_mode)
 #undef APIC_DEST_LOGICAL
diff --git a/include/asm-i386/mach-numaq/mach_apic.h b/include/asm-i386/mach-numaq/mach_apic.h
index e1a0449..9d15809 100644
--- a/include/asm-i386/mach-numaq/mach_apic.h
+++ b/include/asm-i386/mach-numaq/mach_apic.h
@@ -17,8 +17,6 @@
 #define NO_BALANCE_IRQ (1)
 #define esr_disable (1)
 
-#define NO_IOAPIC_CHECK (0)
-
 #define INT_DELIVERY_MODE dest_LowestPrio
 #define INT_DEST_MODE 0     /* physical delivery on LOCAL quad */
  
diff --git a/include/asm-i386/mach-numaq/mach_ipi.h b/include/asm-i386/mach-numaq/mach_ipi.h
index 1b46fd3..c604448 100644
--- a/include/asm-i386/mach-numaq/mach_ipi.h
+++ b/include/asm-i386/mach-numaq/mach_ipi.h
@@ -1,7 +1,7 @@
 #ifndef __ASM_MACH_IPI_H
 #define __ASM_MACH_IPI_H
 
-inline void send_IPI_mask_sequence(cpumask_t, int vector);
+void send_IPI_mask_sequence(cpumask_t, int vector);
 
 static inline void send_IPI_mask(cpumask_t mask, int vector)
 {
diff --git a/include/asm-i386/mach-summit/mach_apic.h b/include/asm-i386/mach-summit/mach_apic.h
index 74e9cbc..3d6d129 100644
--- a/include/asm-i386/mach-summit/mach_apic.h
+++ b/include/asm-i386/mach-summit/mach_apic.h
@@ -7,8 +7,6 @@
 #define esr_disable (1)
 #define NO_BALANCE_IRQ (0)
 
-#define NO_IOAPIC_CHECK (1)	/* Don't check I/O APIC ID for xAPIC */
-
 /* In clustered mode, the high nibble of APIC ID is a cluster number.
  * The low nibble is a 4-bit bitmap. */
 #define XAPIC_DEST_CPUS_SHIFT	4
diff --git a/include/asm-i386/mach-visws/mach_apic.h b/include/asm-i386/mach-visws/mach_apic.h
index 4e6cdfb..de438c7 100644
--- a/include/asm-i386/mach-visws/mach_apic.h
+++ b/include/asm-i386/mach-visws/mach_apic.h
@@ -9,8 +9,6 @@
 #define no_balance_irq (0)
 #define esr_disable (0)
 
-#define NO_IOAPIC_CHECK (0)
-
 #define INT_DELIVERY_MODE dest_LowestPrio
 #define INT_DEST_MODE 1     /* logical delivery broadcast to all procs */
 
diff --git a/include/asm-i386/mmzone.h b/include/asm-i386/mmzone.h
index 13830ae..33ce5d3 100644
--- a/include/asm-i386/mmzone.h
+++ b/include/asm-i386/mmzone.h
@@ -8,7 +8,9 @@
 
 #include <asm/smp.h>
 
-#ifdef CONFIG_DISCONTIGMEM
+#if CONFIG_NUMA
+extern struct pglist_data *node_data[];
+#define NODE_DATA(nid)	(node_data[nid])
 
 #ifdef CONFIG_NUMA
 	#ifdef CONFIG_X86_NUMAQ
@@ -21,8 +23,28 @@
 	#define get_zholes_size(n) (0)
 #endif /* CONFIG_NUMA */
 
-extern struct pglist_data *node_data[];
-#define NODE_DATA(nid)		(node_data[nid])
+extern int get_memcfg_numa_flat(void );
+/*
+ * This allows any one NUMA architecture to be compiled
+ * for, and still fall back to the flat function if it
+ * fails.
+ */
+static inline void get_memcfg_numa(void)
+{
+#ifdef CONFIG_X86_NUMAQ
+	if (get_memcfg_numaq())
+		return;
+#elif CONFIG_ACPI_SRAT
+	if (get_memcfg_from_srat())
+		return;
+#endif
+
+	get_memcfg_numa_flat();
+}
+
+#endif /* CONFIG_NUMA */
+
+#ifdef CONFIG_DISCONTIGMEM
 
 /*
  * generic node memory support, the following assumptions apply:
@@ -48,26 +70,6 @@
 #endif
 }
 
-/*
- * Following are macros that are specific to this numa platform.
- */
-#define reserve_bootmem(addr, size) \
-	reserve_bootmem_node(NODE_DATA(0), (addr), (size))
-#define alloc_bootmem(x) \
-	__alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
-#define alloc_bootmem_low(x) \
-	__alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, 0)
-#define alloc_bootmem_pages(x) \
-	__alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
-#define alloc_bootmem_low_pages(x) \
-	__alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0)
-#define alloc_bootmem_node(ignore, x) \
-	__alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
-#define alloc_bootmem_pages_node(ignore, x) \
-	__alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
-#define alloc_bootmem_low_pages_node(ignore, x) \
-	__alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0)
-
 #define node_localnr(pfn, nid)		((pfn) - node_data[nid]->node_start_pfn)
 
 /*
@@ -79,7 +81,6 @@
  */
 #define kvaddr_to_nid(kaddr)	pfn_to_nid(__pa(kaddr) >> PAGE_SHIFT)
 
-#define node_mem_map(nid)	(NODE_DATA(nid)->node_mem_map)
 #define node_start_pfn(nid)	(NODE_DATA(nid)->node_start_pfn)
 #define node_end_pfn(nid)						\
 ({									\
@@ -100,7 +101,7 @@
 ({									\
 	unsigned long __pfn = pfn;					\
 	int __node  = pfn_to_nid(__pfn);				\
-	&node_mem_map(__node)[node_localnr(__pfn,__node)];		\
+	&NODE_DATA(__node)->node_mem_map[node_localnr(__pfn,__node)];	\
 })
 
 #define page_to_pfn(pg)							\
@@ -122,26 +123,34 @@
 		return (pfn < node_end_pfn(nid));
 	return 0;
 }
-#endif
-
-extern int get_memcfg_numa_flat(void );
-/*
- * This allows any one NUMA architecture to be compiled
- * for, and still fall back to the flat function if it
- * fails.
- */
-static inline void get_memcfg_numa(void)
-{
-#ifdef CONFIG_X86_NUMAQ
-	if (get_memcfg_numaq())
-		return;
-#elif CONFIG_ACPI_SRAT
-	if (get_memcfg_from_srat())
-		return;
-#endif
-
-	get_memcfg_numa_flat();
-}
+#endif /* CONFIG_X86_NUMAQ */
 
 #endif /* CONFIG_DISCONTIGMEM */
+
+#ifdef CONFIG_NEED_MULTIPLE_NODES
+
+/*
+ * Following are macros that are specific to this numa platform.
+ */
+#define reserve_bootmem(addr, size) \
+	reserve_bootmem_node(NODE_DATA(0), (addr), (size))
+#define alloc_bootmem(x) \
+	__alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
+#define alloc_bootmem_low(x) \
+	__alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, 0)
+#define alloc_bootmem_pages(x) \
+	__alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
+#define alloc_bootmem_low_pages(x) \
+	__alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0)
+#define alloc_bootmem_node(ignore, x) \
+	__alloc_bootmem_node(NODE_DATA(0), (x), SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
+#define alloc_bootmem_pages_node(ignore, x) \
+	__alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, __pa(MAX_DMA_ADDRESS))
+#define alloc_bootmem_low_pages_node(ignore, x) \
+	__alloc_bootmem_node(NODE_DATA(0), (x), PAGE_SIZE, 0)
+
+#endif /* CONFIG_NEED_MULTIPLE_NODES */
+
+extern int early_pfn_to_nid(unsigned long pfn);
+
 #endif /* _ASM_MMZONE_H_ */
diff --git a/include/asm-i386/page.h b/include/asm-i386/page.h
index ed13969..8d93f73 100644
--- a/include/asm-i386/page.h
+++ b/include/asm-i386/page.h
@@ -68,6 +68,7 @@
 #define HPAGE_MASK	(~(HPAGE_SIZE - 1))
 #define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
 #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
+#define ARCH_HAS_HUGETLB_CLEAN_STALE_PGTABLE
 #endif
 
 #define pgd_val(x)	((x).pgd)
@@ -119,13 +120,18 @@
 
 extern int sysctl_legacy_va_layout;
 
+extern int page_is_ram(unsigned long pagenr);
+
 #endif /* __ASSEMBLY__ */
 
 #ifdef __ASSEMBLY__
 #define __PAGE_OFFSET		(0xC0000000)
+#define __PHYSICAL_START	CONFIG_PHYSICAL_START
 #else
 #define __PAGE_OFFSET		(0xC0000000UL)
+#define __PHYSICAL_START	((unsigned long)CONFIG_PHYSICAL_START)
 #endif
+#define __KERNEL_START		(__PAGE_OFFSET + __PHYSICAL_START)
 
 
 #define PAGE_OFFSET		((unsigned long)__PAGE_OFFSET)
@@ -134,11 +140,11 @@
 #define __pa(x)			((unsigned long)(x)-PAGE_OFFSET)
 #define __va(x)			((void *)((unsigned long)(x)+PAGE_OFFSET))
 #define pfn_to_kaddr(pfn)      __va((pfn) << PAGE_SHIFT)
-#ifndef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_FLATMEM
 #define pfn_to_page(pfn)	(mem_map + (pfn))
 #define page_to_pfn(page)	((unsigned long)((page) - mem_map))
 #define pfn_valid(pfn)		((pfn) < max_mapnr)
-#endif /* !CONFIG_DISCONTIGMEM */
+#endif /* CONFIG_FLATMEM */
 #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-i386/param.h b/include/asm-i386/param.h
index b644052..fa02e67 100644
--- a/include/asm-i386/param.h
+++ b/include/asm-i386/param.h
@@ -1,8 +1,10 @@
+#include <linux/config.h>
+
 #ifndef _ASMi386_PARAM_H
 #define _ASMi386_PARAM_H
 
 #ifdef __KERNEL__
-# define HZ		1000		/* 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-i386/pgtable.h b/include/asm-i386/pgtable.h
index 8d60c2b..77c6497 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -236,6 +236,7 @@
 static inline pte_t pte_mkdirty(pte_t pte)	{ (pte).pte_low |= _PAGE_DIRTY; return pte; }
 static inline pte_t pte_mkyoung(pte_t pte)	{ (pte).pte_low |= _PAGE_ACCESSED; return pte; }
 static inline pte_t pte_mkwrite(pte_t pte)	{ (pte).pte_low |= _PAGE_RW; return pte; }
+static inline pte_t pte_mkhuge(pte_t pte)	{ (pte).pte_low |= _PAGE_PRESENT | _PAGE_PSE; return pte; }
 
 #ifdef CONFIG_X86_PAE
 # include <asm/pgtable-3level.h>
@@ -275,7 +276,6 @@
  */
 
 #define mk_pte(page, pgprot)	pfn_pte(page_to_pfn(page), (pgprot))
-#define mk_pte_huge(entry) ((entry).pte_low |= _PAGE_PRESENT | _PAGE_PSE)
 
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
@@ -398,9 +398,9 @@
 
 #endif /* !__ASSEMBLY__ */
 
-#ifndef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_FLATMEM
 #define kern_addr_valid(addr)	(1)
-#endif /* !CONFIG_DISCONTIGMEM */
+#endif /* CONFIG_FLATMEM */
 
 #define io_remap_page_range(vma, vaddr, paddr, size, prot)		\
 		remap_pfn_range(vma, vaddr, (paddr) >> PAGE_SHIFT, size, prot)
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h
index 359bb01..6f0f93d 100644
--- a/include/asm-i386/processor.h
+++ b/include/asm-i386/processor.h
@@ -501,12 +501,16 @@
 } while (0)
 
 /*
- * This special macro can be used to load a debugging register
+ * These special macros can be used to get or set a debugging register
  */
-#define loaddebug(thread,register) \
-               __asm__("movl %0,%%db" #register  \
-                       : /* no output */ \
-                       :"r" ((thread)->debugreg[register]))
+#define get_debugreg(var, register)				\
+		__asm__("movl %%db" #register ", %0"		\
+			:"=r" (var))
+#define set_debugreg(value, register)			\
+		__asm__("movl %0,%%db" #register		\
+			: /* no output */			\
+			:"r" (value))
+
 
 /* Forward declaration, a strange C thing */
 struct task_struct;
@@ -687,5 +691,7 @@
 #define cache_line_size() (boot_cpu_data.x86_cache_alignment)
 
 extern unsigned long boot_option_idle_override;
+extern void enable_sep_cpu(void);
+extern int sysenter_setup(void);
 
 #endif /* __ASM_I386_PROCESSOR_H */
diff --git a/include/asm-i386/ptrace.h b/include/asm-i386/ptrace.h
index 8618914..eef9f93 100644
--- a/include/asm-i386/ptrace.h
+++ b/include/asm-i386/ptrace.h
@@ -57,7 +57,8 @@
 #ifdef __KERNEL__
 struct task_struct;
 extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code);
-#define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs))
+#define user_mode(regs)		(3 & (regs)->xcs)
+#define user_mode_vm(regs)	((VM_MASK & (regs)->eflags) || user_mode(regs))
 #define instruction_pointer(regs) ((regs)->eip)
 #if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER)
 extern unsigned long profile_pc(struct pt_regs *regs);
diff --git a/include/asm-i386/smp.h b/include/asm-i386/smp.h
index e03a206..edad9b4 100644
--- a/include/asm-i386/smp.h
+++ b/include/asm-i386/smp.h
@@ -42,16 +42,23 @@
 extern void smp_invalidate_rcv(void);		/* Process an NMI */
 extern void (*mtrr_hook) (void);
 extern void zap_low_mappings (void);
+extern void lock_ipi_call_lock(void);
+extern void unlock_ipi_call_lock(void);
 
 #define MAX_APICID 256
 extern u8 x86_cpu_to_apicid[];
 
+#ifdef CONFIG_HOTPLUG_CPU
+extern void cpu_exit_clear(void);
+extern void cpu_uninit(void);
+#endif
+
 /*
  * This function is needed by all SMP systems. It must _always_ be valid
  * from the initial startup. We map APIC_BASE very early in page_setup(),
  * so this is correct in the x86 case.
  */
-#define __smp_processor_id() (current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
 
 extern cpumask_t cpu_callout_map;
 extern cpumask_t cpu_callin_map;
@@ -83,6 +90,9 @@
 }
 
 #endif
+
+extern int __cpu_disable(void);
+extern void __cpu_die(unsigned int cpu);
 #endif /* !__ASSEMBLY__ */
 
 #define NO_PROC_ID		0xFF		/* No processor magic marker */
diff --git a/include/asm-i386/sparsemem.h b/include/asm-i386/sparsemem.h
new file mode 100644
index 0000000..cfeed99
--- /dev/null
+++ b/include/asm-i386/sparsemem.h
@@ -0,0 +1,31 @@
+#ifndef _I386_SPARSEMEM_H
+#define _I386_SPARSEMEM_H
+#ifdef CONFIG_SPARSEMEM
+
+/*
+ * generic non-linear memory support:
+ *
+ * 1) we will not split memory into more chunks than will fit into the
+ *    flags field of the struct page
+ */
+
+/*
+ * SECTION_SIZE_BITS		2^N: how big each section will be
+ * MAX_PHYSADDR_BITS		2^N: how much physical address space we have
+ * MAX_PHYSMEM_BITS		2^N: how much memory we can have in that space
+ */
+#ifdef CONFIG_X86_PAE
+#define SECTION_SIZE_BITS       30
+#define MAX_PHYSADDR_BITS       36
+#define MAX_PHYSMEM_BITS	36
+#else
+#define SECTION_SIZE_BITS       26
+#define MAX_PHYSADDR_BITS       32
+#define MAX_PHYSMEM_BITS	32
+#endif
+
+/* XXX: FIXME -- wli */
+#define kern_addr_valid(kaddr)  (0)
+
+#endif /* CONFIG_SPARSEMEM */
+#endif /* _I386_SPARSEMEM_H */
diff --git a/include/asm-i386/string.h b/include/asm-i386/string.h
index 6a78ac5..02c8f5d 100644
--- a/include/asm-i386/string.h
+++ b/include/asm-i386/string.h
@@ -116,7 +116,8 @@
 	"orb $1,%%al\n"
 	"3:"
 	:"=a" (__res), "=&S" (d0), "=&D" (d1)
-		     :"1" (cs),"2" (ct));
+	:"1" (cs),"2" (ct)
+	:"memory");
 return __res;
 }
 
@@ -138,8 +139,9 @@
 	"3:\tsbbl %%eax,%%eax\n\t"
 	"orb $1,%%al\n"
 	"4:"
-		     :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
-		     :"1" (cs),"2" (ct),"3" (count));
+	:"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
+	:"1" (cs),"2" (ct),"3" (count)
+	:"memory");
 return __res;
 }
 
@@ -158,7 +160,9 @@
 	"movl $1,%1\n"
 	"2:\tmovl %1,%0\n\t"
 	"decl %0"
-	:"=a" (__res), "=&S" (d0) : "1" (s),"0" (c));
+	:"=a" (__res), "=&S" (d0)
+	:"1" (s),"0" (c)
+	:"memory");
 return __res;
 }
 
@@ -175,7 +179,9 @@
 	"leal -1(%%esi),%0\n"
 	"2:\ttestb %%al,%%al\n\t"
 	"jne 1b"
-	:"=g" (__res), "=&S" (d0), "=&a" (d1) :"0" (0),"1" (s),"2" (c));
+	:"=g" (__res), "=&S" (d0), "=&a" (d1)
+	:"0" (0),"1" (s),"2" (c)
+	:"memory");
 return __res;
 }
 
@@ -189,7 +195,9 @@
 	"scasb\n\t"
 	"notl %0\n\t"
 	"decl %0"
-	:"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffffu));
+	:"=c" (__res), "=&D" (d0)
+	:"1" (s),"a" (0), "0" (0xffffffffu)
+	:"memory");
 return __res;
 }
 
@@ -333,7 +341,9 @@
 	"je 1f\n\t"
 	"movl $1,%0\n"
 	"1:\tdecl %0"
-	:"=D" (__res), "=&c" (d0) : "a" (c),"0" (cs),"1" (count));
+	:"=D" (__res), "=&c" (d0)
+	:"a" (c),"0" (cs),"1" (count)
+	:"memory");
 return __res;
 }
 
@@ -369,7 +379,7 @@
 	"je 2f\n\t"
 	"stosb\n"
 	"2:"
-	: "=&c" (d0), "=&D" (d1)
+	:"=&c" (d0), "=&D" (d1)
 	:"a" (c), "q" (count), "0" (count/4), "1" ((long) s)
 	:"memory");
 return (s);	
@@ -392,7 +402,8 @@
 	"jne 1b\n"
 	"3:\tsubl %2,%0"
 	:"=a" (__res), "=&d" (d0)
-	:"c" (s),"1" (count));
+	:"c" (s),"1" (count)
+	:"memory");
 return __res;
 }
 /* end of additional stuff */
@@ -473,7 +484,8 @@
 		"dec %%edi\n"
 		"1:"
 		: "=D" (addr), "=c" (size)
-		: "0" (addr), "1" (size), "a" (c));
+		: "0" (addr), "1" (size), "a" (c)
+		: "memory");
 	return addr;
 }
 
diff --git a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
index 2cd5727..95add81 100644
--- a/include/asm-i386/thread_info.h
+++ b/include/asm-i386/thread_info.h
@@ -31,7 +31,7 @@
 	unsigned long		flags;		/* low level flags */
 	unsigned long		status;		/* thread-synchronous flags */
 	__u32			cpu;		/* current CPU */
-	__s32			preempt_count; /* 0 => preemptable, <0 => BUG */
+	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
 
 
 	mm_segment_t		addr_limit;	/* thread address space:
diff --git a/include/asm-i386/timer.h b/include/asm-i386/timer.h
index c347098..dcf1e07 100644
--- a/include/asm-i386/timer.h
+++ b/include/asm-i386/timer.h
@@ -22,6 +22,7 @@
 	unsigned long (*get_offset)(void);
 	unsigned long long (*monotonic_clock)(void);
 	void (*delay)(unsigned long);
+	unsigned long (*read_timer)(void);
 };
 
 struct init_timer_opts {
@@ -52,6 +53,7 @@
 #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
diff --git a/include/asm-i386/timex.h b/include/asm-i386/timex.h
index b41e484..292b5a6 100644
--- a/include/asm-i386/timex.h
+++ b/include/asm-i386/timex.h
@@ -47,6 +47,9 @@
 	return ret;
 }
 
-extern unsigned long cpu_khz;
+extern unsigned int cpu_khz;
+
+extern int read_current_timer(unsigned long *timer_value);
+#define ARCH_HAS_READ_CURRENT_TIMER	1
 
 #endif
diff --git a/include/asm-i386/topology.h b/include/asm-i386/topology.h
index 98f9e68..2461b73 100644
--- a/include/asm-i386/topology.h
+++ b/include/asm-i386/topology.h
@@ -60,12 +60,8 @@
 	return first_cpu(mask);
 }
 
-/* Returns the number of the node containing PCI bus number 'busnr' */
-static inline cpumask_t __pcibus_to_cpumask(int busnr)
-{
-	return node_to_cpumask(mp_bus_id_to_node[busnr]);
-}
-#define pcibus_to_cpumask(bus)	__pcibus_to_cpumask(bus->number)
+#define pcibus_to_node(bus) mp_bus_id_to_node[(bus)->number]
+#define pcibus_to_cpumask(bus) node_to_cpumask(pcibus_to_node(bus))
 
 /* sched_domains SD_NODE_INIT for NUMAQ machines */
 #define SD_NODE_INIT (struct sched_domain) {		\
@@ -78,11 +74,14 @@
 	.imbalance_pct		= 125,			\
 	.cache_hot_time		= (10*1000000),		\
 	.cache_nice_tries	= 1,			\
+	.busy_idx		= 3,			\
+	.idle_idx		= 1,			\
+	.newidle_idx		= 2,			\
+	.wake_idx		= 1,			\
 	.per_cpu_gain		= 100,			\
 	.flags			= SD_LOAD_BALANCE	\
 				| SD_BALANCE_EXEC	\
-				| SD_BALANCE_NEWIDLE	\
-				| SD_WAKE_IDLE		\
+				| SD_BALANCE_FORK	\
 				| SD_WAKE_BALANCE,	\
 	.last_balance		= jiffies,		\
 	.balance_interval	= 1,			\
diff --git a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
index 61bcc1b..e25e4c7 100644
--- a/include/asm-i386/unistd.h
+++ b/include/asm-i386/unistd.h
@@ -256,7 +256,7 @@
 #define __NR_io_submit		248
 #define __NR_io_cancel		249
 #define __NR_fadvise64		250
-
+#define __NR_set_zone_reclaim	251
 #define __NR_exit_group		252
 #define __NR_lookup_dcookie	253
 #define __NR_epoll_create	254
@@ -294,8 +294,10 @@
 #define __NR_add_key		286
 #define __NR_request_key	287
 #define __NR_keyctl		288
+#define __NR_ioprio_set		289
+#define __NR_ioprio_get		290
 
-#define NR_syscalls 289
+#define NR_syscalls 291
 
 /*
  * user-visible error numbers are in the range -1 - -128: see
diff --git a/include/asm-ia64/agp.h b/include/asm-ia64/agp.h
index d1316f1..4e517f0 100644
--- a/include/asm-ia64/agp.h
+++ b/include/asm-ia64/agp.h
@@ -18,4 +18,14 @@
 #define flush_agp_mappings()		/* nothing */
 #define flush_agp_cache()		mb()
 
+/* Convert a physical address to an address suitable for the GART. */
+#define phys_to_gart(x) (x)
+#define gart_to_phys(x) (x)
+
+/* GATT allocation. Returns/accepts GATT kernel virtual address. */
+#define alloc_gatt_pages(order)		\
+	((char *)__get_free_pages(GFP_KERNEL, (order)))
+#define free_gatt_pages(table, order)	\
+	free_pages((unsigned long)(table), (order))
+
 #endif /* _ASM_IA64_AGP_H */
diff --git a/include/asm-ia64/break.h b/include/asm-ia64/break.h
index 97c7b2d..8167828 100644
--- a/include/asm-ia64/break.h
+++ b/include/asm-ia64/break.h
@@ -12,6 +12,8 @@
  * OS-specific debug break numbers:
  */
 #define __IA64_BREAK_KDB		0x80100
+#define __IA64_BREAK_KPROBE		0x80200
+#define __IA64_BREAK_JPROBE		0x80300
 
 /*
  * OS-specific break numbers:
diff --git a/include/asm-ia64/compat.h b/include/asm-ia64/compat.h
index cc0ff0a..0c05e5b 100644
--- a/include/asm-ia64/compat.h
+++ b/include/asm-ia64/compat.h
@@ -27,6 +27,7 @@
 typedef s32		compat_daddr_t;
 typedef u32		compat_caddr_t;
 typedef __kernel_fsid_t	compat_fsid_t;
+typedef s32		compat_timer_t;
 
 typedef s32		compat_int_t;
 typedef s32		compat_long_t;
diff --git a/include/asm-ia64/fcntl.h b/include/asm-ia64/fcntl.h
index d193981..c9f8d83 100644
--- a/include/asm-ia64/fcntl.h
+++ b/include/asm-ia64/fcntl.h
@@ -81,4 +81,6 @@
 
 #define F_LINUX_SPECIFIC_BASE	1024
 
+#define force_o_largefile() ( ! (current->personality & PER_LINUX32) )
+
 #endif /* _ASM_IA64_FCNTL_H */
diff --git a/include/asm-ia64/kdebug.h b/include/asm-ia64/kdebug.h
new file mode 100644
index 0000000..4d376e1
--- /dev/null
+++ b/include/asm-ia64/kdebug.h
@@ -0,0 +1,61 @@
+#ifndef _IA64_KDEBUG_H
+#define _IA64_KDEBUG_H 1
+/*
+ * include/asm-ia64/kdebug.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.
+ *
+ * Copyright (C) Intel Corporation, 2005
+ *
+ * 2005-Apr     Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
+ *              <anil.s.keshavamurthy@intel.com> adopted from
+ *              include/asm-x86_64/kdebug.h
+ */
+#include <linux/notifier.h>
+
+struct pt_regs;
+
+struct die_args {
+	struct pt_regs *regs;
+	const char *str;
+	long err;
+	int trapnr;
+	int signr;
+};
+
+int register_die_notifier(struct notifier_block *nb);
+extern struct notifier_block *ia64die_chain;
+
+enum die_val {
+	DIE_BREAK = 1,
+	DIE_SS,
+	DIE_PAGE_FAULT,
+};
+
+static inline int notify_die(enum die_val val, 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 notifier_call_chain(&ia64die_chain, val, &args);
+}
+
+#endif
diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h
new file mode 100644
index 0000000..7b70003
--- /dev/null
+++ b/include/asm-ia64/kprobes.h
@@ -0,0 +1,116 @@
+#ifndef _ASM_KPROBES_H
+#define _ASM_KPROBES_H
+/*
+ *  Kernel Probes (KProbes)
+ *  include/asm-ia64/kprobes.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.
+ *
+ * Copyright (C) IBM Corporation, 2002, 2004
+ * Copyright (C) Intel Corporation, 2005
+ *
+ * 2005-Apr     Rusty Lynch <rusty.lynch@intel.com> and Anil S Keshavamurthy
+ *              <anil.s.keshavamurthy@intel.com> adapted from i386
+ */
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <asm/break.h>
+
+#define BREAK_INST	(long)(__IA64_BREAK_KPROBE << 6)
+
+typedef union cmp_inst {
+	struct {
+	unsigned long long qp : 6;
+	unsigned long long p1 : 6;
+	unsigned long long c  : 1;
+	unsigned long long r2 : 7;
+	unsigned long long r3 : 7;
+	unsigned long long p2 : 6;
+	unsigned long long ta : 1;
+	unsigned long long x2 : 2;
+	unsigned long long tb : 1;
+	unsigned long long opcode : 4;
+	unsigned long long reserved : 23;
+	}f;
+	unsigned long long l;
+} cmp_inst_t;
+
+struct kprobe;
+
+typedef struct _bundle {
+	struct {
+		unsigned long long template : 5;
+		unsigned long long slot0 : 41;
+		unsigned long long slot1_p0 : 64-46;
+	} quad0;
+	struct {
+		unsigned long long slot1_p1 : 41 - (64-46);
+		unsigned long long slot2 : 41;
+	} quad1;
+} __attribute__((__aligned__(16)))  bundle_t;
+
+#define JPROBE_ENTRY(pentry)	(kprobe_opcode_t *)pentry
+
+#define SLOT0_OPCODE_SHIFT	(37)
+#define SLOT1_p1_OPCODE_SHIFT	(37 - (64-46))
+#define SLOT2_OPCODE_SHIFT 	(37)
+
+#define INDIRECT_CALL_OPCODE		(1)
+#define IP_RELATIVE_CALL_OPCODE		(5)
+#define IP_RELATIVE_BRANCH_OPCODE	(4)
+#define IP_RELATIVE_PREDICT_OPCODE	(7)
+#define LONG_BRANCH_OPCODE		(0xC)
+#define LONG_CALL_OPCODE		(0xD)
+
+typedef struct kprobe_opcode {
+	bundle_t bundle;
+} kprobe_opcode_t;
+
+struct fnptr {
+	unsigned long ip;
+	unsigned long gp;
+};
+
+/* Architecture specific copy of original instruction*/
+struct arch_specific_insn {
+	/* copy of the instruction to be emulated */
+	kprobe_opcode_t insn;
+ #define INST_FLAG_FIX_RELATIVE_IP_ADDR		1
+ #define INST_FLAG_FIX_BRANCH_REG		2
+ 	unsigned long inst_flag;
+ 	unsigned short target_br_reg;
+};
+
+/* ia64 does not need this */
+static inline void jprobe_return(void)
+{
+}
+
+/* ia64 does not need this */
+static inline void arch_copy_kprobe(struct kprobe *p)
+{
+}
+
+#ifdef CONFIG_KPROBES
+extern int kprobe_exceptions_notify(struct notifier_block *self,
+				    unsigned long val, void *data);
+#else				/* !CONFIG_KPROBES */
+static inline int kprobe_exceptions_notify(struct notifier_block *self,
+					   unsigned long val, void *data)
+{
+	return 0;
+}
+#endif
+#endif				/* _ASM_KPROBES_H */
diff --git a/include/asm-ia64/mmzone.h b/include/asm-ia64/mmzone.h
index 9491dac..d32f51e 100644
--- a/include/asm-ia64/mmzone.h
+++ b/include/asm-ia64/mmzone.h
@@ -17,6 +17,20 @@
 
 #ifdef CONFIG_DISCONTIGMEM
 
+static inline int pfn_to_nid(unsigned long pfn)
+{
+#ifdef CONFIG_NUMA
+	extern int paddr_to_nid(unsigned long);
+	int nid = paddr_to_nid(pfn << PAGE_SHIFT);
+	if (nid < 0)
+		return 0;
+	else
+		return nid;
+#else
+	return 0;
+#endif
+}
+
 #ifdef CONFIG_IA64_DIG /* DIG systems are small */
 # define MAX_PHYSNODE_ID	8
 # define NR_NODE_MEMBLKS	(MAX_NUMNODES * 8)
diff --git a/include/asm-ia64/param.h b/include/asm-ia64/param.h
index 6c6b679..5e1e0d2 100644
--- a/include/asm-ia64/param.h
+++ b/include/asm-ia64/param.h
@@ -27,7 +27,7 @@
    */
 #  define HZ	  32
 # else
-#  define HZ	1024
+#  define HZ	CONFIG_HZ
 # endif
 # define USER_HZ	HZ
 # define CLOCKS_PER_SEC	HZ	/* frequency at which times() counts */
diff --git a/include/asm-ia64/percpu.h b/include/asm-ia64/percpu.h
index 1e87f19..2b14dee 100644
--- a/include/asm-ia64/percpu.h
+++ b/include/asm-ia64/percpu.h
@@ -50,7 +50,7 @@
 
 #else /* ! SMP */
 
-#define per_cpu(var, cpu)			(*((void)cpu, &per_cpu__##var))
+#define per_cpu(var, cpu)			(*((void)(cpu), &per_cpu__##var))
 #define __get_cpu_var(var)			per_cpu__##var
 #define per_cpu_init()				(__phys_per_cpu_start)
 
diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
index ea121a0..48586e0 100644
--- a/include/asm-ia64/pgtable.h
+++ b/include/asm-ia64/pgtable.h
@@ -8,7 +8,7 @@
  * This hopefully works with any (fixed) IA-64 page-size, as defined
  * in <asm/page.h>.
  *
- * Copyright (C) 1998-2004 Hewlett-Packard Co
+ * Copyright (C) 1998-2005 Hewlett-Packard Co
  *	David Mosberger-Tang <davidm@hpl.hp.com>
  */
 
@@ -283,6 +283,7 @@
 #define pte_mkyoung(pte)	(__pte(pte_val(pte) | _PAGE_A))
 #define pte_mkclean(pte)	(__pte(pte_val(pte) & ~_PAGE_D))
 #define pte_mkdirty(pte)	(__pte(pte_val(pte) | _PAGE_D))
+#define pte_mkhuge(pte)		(__pte(pte_val(pte) | _PAGE_P))
 
 /*
  * Macro to a page protection value as "uncacheable".  Note that "protection" is really a
@@ -551,7 +552,11 @@
 
 /* These tell get_user_pages() that the first gate page is accessible from user-level.  */
 #define FIXADDR_USER_START	GATE_ADDR
-#define FIXADDR_USER_END	(GATE_ADDR + 2*PERCPU_PAGE_SIZE)
+#ifdef HAVE_BUGGY_SEGREL
+# define FIXADDR_USER_END	(GATE_ADDR + 2*PAGE_SIZE)
+#else
+# define FIXADDR_USER_END	(GATE_ADDR + 2*PERCPU_PAGE_SIZE)
+#endif
 
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
diff --git a/include/asm-ia64/processor.h b/include/asm-ia64/processor.h
index 9e1ba8b..91bbd1f 100644
--- a/include/asm-ia64/processor.h
+++ b/include/asm-ia64/processor.h
@@ -403,7 +403,10 @@
  * task_struct at this point.
  */
 
-/* Return TRUE if task T owns the fph partition of the CPU we're running on. */
+/*
+ * Return TRUE if task T owns the fph partition of the CPU we're running on.
+ * Must be called from code that has preemption disabled.
+ */
 #define ia64_is_local_fpu_owner(t)								\
 ({												\
 	struct task_struct *__ia64_islfo_task = (t);						\
@@ -411,7 +414,10 @@
 	 && __ia64_islfo_task == (struct task_struct *) ia64_get_kr(IA64_KR_FPU_OWNER));	\
 })
 
-/* Mark task T as owning the fph partition of the CPU we're running on. */
+/*
+ * Mark task T as owning the fph partition of the CPU we're running on.
+ * Must be called from code that has preemption disabled.
+ */
 #define ia64_set_local_fpu_owner(t) do {						\
 	struct task_struct *__ia64_slfo_task = (t);					\
 	__ia64_slfo_task->thread.last_fph_cpu = smp_processor_id();			\
diff --git a/include/asm-ia64/smp.h b/include/asm-ia64/smp.h
index 3ba1a06..a391435 100644
--- a/include/asm-ia64/smp.h
+++ b/include/asm-ia64/smp.h
@@ -46,7 +46,7 @@
 #define SMP_IRQ_REDIRECTION	(1 << 0)
 #define SMP_IPI_REDIRECTION	(1 << 1)
 
-#define smp_processor_id()	(current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
 
 extern struct smp_boot_data {
 	int cpu_count;
diff --git a/include/asm-ia64/sn/mspec.h b/include/asm-ia64/sn/mspec.h
new file mode 100644
index 0000000..dbe13c6
--- /dev/null
+++ b/include/asm-ia64/sn/mspec.h
@@ -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) 2001-2004 Silicon Graphics, Inc.  All rights reserved.
+ */
+
+#ifndef _ASM_IA64_SN_MSPEC_H
+#define _ASM_IA64_SN_MSPEC_H
+
+#define FETCHOP_VAR_SIZE 64 /* 64 byte per fetchop variable */
+
+#define FETCHOP_LOAD		0
+#define FETCHOP_INCREMENT	8
+#define FETCHOP_DECREMENT	16
+#define FETCHOP_CLEAR		24
+
+#define FETCHOP_STORE		0
+#define FETCHOP_AND		24
+#define FETCHOP_OR		32
+
+#define FETCHOP_CLEAR_CACHE	56
+
+#define FETCHOP_LOAD_OP(addr, op) ( \
+         *(volatile long *)((char*) (addr) + (op)))
+
+#define FETCHOP_STORE_OP(addr, op, x) ( \
+         *(volatile long *)((char*) (addr) + (op)) = (long) (x))
+
+#ifdef __KERNEL__
+
+/*
+ * Each Atomic Memory Operation (AMO formerly known as fetchop)
+ * variable is 64 bytes long.  The first 8 bytes are used.  The
+ * remaining 56 bytes are unaddressable due to the operation taking
+ * that portion of the address.
+ *
+ * NOTE: The AMO_t _MUST_ be placed in either the first or second half
+ * of the cache line.  The cache line _MUST NOT_ be used for anything
+ * other than additional AMO_t entries.  This is because there are two
+ * addresses which reference the same physical cache line.  One will
+ * be a cached entry with the memory type bits all set.  This address
+ * may be loaded into processor cache.  The AMO_t will be referenced
+ * uncached via the memory special memory type.  If any portion of the
+ * cached cache-line is modified, when that line is flushed, it will
+ * overwrite the uncached value in physical memory and lead to
+ * inconsistency.
+ */
+typedef struct {
+        u64 variable;
+        u64 unused[7];
+} AMO_t;
+
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_IA64_SN_MSPEC_H */
diff --git a/include/asm-ia64/system.h b/include/asm-ia64/system.h
index 6f516e7..cd2cf76 100644
--- a/include/asm-ia64/system.h
+++ b/include/asm-ia64/system.h
@@ -183,8 +183,6 @@
 
 #ifdef __KERNEL__
 
-#define prepare_to_switch()    do { } while(0)
-
 #ifdef CONFIG_IA32_SUPPORT
 # define IS_IA32_PROCESS(regs)	(ia64_psr(regs)->is != 0)
 #else
@@ -274,13 +272,7 @@
  * of that CPU which will not be released, because there we wait for the
  * tasklist_lock to become available.
  */
-#define prepare_arch_switch(rq, next)		\
-do {						\
-	spin_lock(&(next)->switch_lock);	\
-	spin_unlock(&(rq)->lock);		\
-} while (0)
-#define finish_arch_switch(rq, prev)	spin_unlock_irq(&(prev)->switch_lock)
-#define task_running(rq, p) 		((rq)->curr == (p) || spin_is_locked(&(p)->switch_lock))
+#define __ARCH_WANT_UNLOCKED_CTXSW
 
 #define ia64_platform_is(x) (strcmp(x, platform_name) == 0)
 
diff --git a/include/asm-ia64/thread_info.h b/include/asm-ia64/thread_info.h
index 8d5b7e7..7dc8951 100644
--- a/include/asm-ia64/thread_info.h
+++ b/include/asm-ia64/thread_info.h
@@ -25,7 +25,7 @@
 	__u32 flags;			/* thread_info flags (see TIF_*) */
 	__u32 cpu;			/* current CPU */
 	mm_segment_t addr_limit;	/* user-level address space limit */
-	__s32 preempt_count;		/* 0=premptable, <0=BUG; will also serve as bh-counter */
+	int preempt_count;		/* 0=premptable, <0=BUG; will also serve as bh-counter */
 	struct restart_block restart_block;
 	struct {
 		int signo;
diff --git a/include/asm-ia64/topology.h b/include/asm-ia64/topology.h
index 21cf351..4e64c2a 100644
--- a/include/asm-ia64/topology.h
+++ b/include/asm-ia64/topology.h
@@ -42,25 +42,54 @@
 
 void build_cpu_to_node_map(void);
 
+#define SD_CPU_INIT (struct sched_domain) {		\
+	.span			= CPU_MASK_NONE,	\
+	.parent			= NULL,			\
+	.groups			= NULL,			\
+	.min_interval		= 1,			\
+	.max_interval		= 4,			\
+	.busy_factor		= 64,			\
+	.imbalance_pct		= 125,			\
+	.cache_hot_time		= (10*1000000),		\
+	.per_cpu_gain		= 100,			\
+	.cache_nice_tries	= 2,			\
+	.busy_idx		= 2,			\
+	.idle_idx		= 1,			\
+	.newidle_idx		= 2,			\
+	.wake_idx		= 1,			\
+	.forkexec_idx		= 1,			\
+	.flags			= SD_LOAD_BALANCE	\
+				| SD_BALANCE_NEWIDLE	\
+				| SD_BALANCE_EXEC	\
+				| SD_WAKE_AFFINE,	\
+	.last_balance		= jiffies,		\
+	.balance_interval	= 1,			\
+	.nr_balance_failed	= 0,			\
+}
+
 /* sched_domains SD_NODE_INIT for IA64 NUMA machines */
 #define SD_NODE_INIT (struct sched_domain) {		\
 	.span			= CPU_MASK_NONE,	\
 	.parent			= NULL,			\
 	.groups			= NULL,			\
-	.min_interval		= 80,			\
-	.max_interval		= 320,			\
-	.busy_factor		= 320,			\
+	.min_interval		= 8,			\
+	.max_interval		= 8*(min(num_online_cpus(), 32)), \
+	.busy_factor		= 64,			\
 	.imbalance_pct		= 125,			\
 	.cache_hot_time		= (10*1000000),		\
-	.cache_nice_tries	= 1,			\
+	.cache_nice_tries	= 2,			\
+	.busy_idx		= 3,			\
+	.idle_idx		= 2,			\
+	.newidle_idx		= 0, /* unused */	\
+	.wake_idx		= 1,			\
+	.forkexec_idx		= 1,			\
 	.per_cpu_gain		= 100,			\
 	.flags			= SD_LOAD_BALANCE	\
 				| SD_BALANCE_EXEC	\
-				| SD_BALANCE_NEWIDLE	\
-				| SD_WAKE_IDLE		\
+				| SD_BALANCE_FORK	\
 				| SD_WAKE_BALANCE,	\
 	.last_balance		= jiffies,		\
-	.balance_interval	= 1,			\
+	.balance_interval	= 64,			\
 	.nr_balance_failed	= 0,			\
 }
 
@@ -69,17 +98,21 @@
 	.span			= CPU_MASK_NONE,	\
 	.parent			= NULL,			\
 	.groups			= NULL,			\
-	.min_interval		= 80,			\
-	.max_interval		= 320,			\
-	.busy_factor		= 320,			\
-	.imbalance_pct		= 125,			\
+	.min_interval		= 64,			\
+	.max_interval		= 64*num_online_cpus(),	\
+	.busy_factor		= 128,			\
+	.imbalance_pct		= 133,			\
 	.cache_hot_time		= (10*1000000),		\
 	.cache_nice_tries	= 1,			\
+	.busy_idx		= 3,			\
+	.idle_idx		= 3,			\
+	.newidle_idx		= 0, /* unused */	\
+	.wake_idx		= 0, /* unused */	\
+	.forkexec_idx		= 0, /* unused */	\
 	.per_cpu_gain		= 100,			\
-	.flags			= SD_LOAD_BALANCE	\
-				| SD_BALANCE_EXEC,	\
+	.flags			= SD_LOAD_BALANCE,	\
 	.last_balance		= jiffies,		\
-	.balance_interval	= 100*(63+num_online_cpus())/64,   \
+	.balance_interval	= 64,			\
 	.nr_balance_failed	= 0,			\
 }
 
diff --git a/include/asm-ia64/uncached.h b/include/asm-ia64/uncached.h
new file mode 100644
index 0000000..b82d923
--- /dev/null
+++ b/include/asm-ia64/uncached.h
@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 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 version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * Prototypes for the uncached page allocator
+ */
+
+extern unsigned long uncached_alloc_page(int nid);
+extern void uncached_free_page(unsigned long);
diff --git a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
index 33e26c5..517f164 100644
--- a/include/asm-ia64/unistd.h
+++ b/include/asm-ia64/unistd.h
@@ -263,6 +263,9 @@
 #define __NR_add_key			1271
 #define __NR_request_key		1272
 #define __NR_keyctl			1273
+#define __NR_ioprio_set			1274
+#define __NR_ioprio_get			1275
+#define __NR_set_zone_reclaim		1276
 
 #ifdef __KERNEL__
 
diff --git a/include/asm-m32r/div64.h b/include/asm-m32r/div64.h
index 417a51b..6cd978c 100644
--- a/include/asm-m32r/div64.h
+++ b/include/asm-m32r/div64.h
@@ -1,38 +1 @@
-#ifndef _ASM_M32R_DIV64
-#define _ASM_M32R_DIV64
-
-/* $Id$ */
-
-/* unsigned long long division.
- * Input:
- *  unsigned long long  n
- *  unsigned long  base
- * Output:
- *  n = n / base;
- *  return value = n % base;
- */
-#define do_div(n, base)						\
-({								\
-	unsigned long _res, _high, _mid, _low;			\
-								\
-	_low = (n) & 0xffffffffUL;				\
-	_high = (n) >> 32;					\
-	if (_high) {						\
-		_mid = (_high % (unsigned long)(base)) << 16;	\
-		_high = _high / (unsigned long)(base);		\
-		_mid += _low >> 16;				\
-		_low &= 0x0000ffffUL;				\
-		_low += (_mid % (unsigned long)(base)) << 16;	\
-		_mid = _mid / (unsigned long)(base);		\
-		_res = _low % (unsigned long)(base);		\
-		_low = _low / (unsigned long)(base);		\
-		n = _low + ((long long)_mid << 16) +		\
-			((long long)_high << 32);		\
-	} else {						\
-		_res = _low % (unsigned long)(base);		\
-		n = (_low / (unsigned long)(base));		\
-	}							\
-	_res;							\
-})
-
-#endif  /* _ASM_M32R_DIV64 */
+#include <asm-generic/div64.h>
diff --git a/include/asm-m32r/ide.h b/include/asm-m32r/ide.h
index be64f24..194393b 100644
--- a/include/asm-m32r/ide.h
+++ b/include/asm-m32r/ide.h
@@ -35,7 +35,7 @@
 static __inline__ int ide_default_irq(unsigned long base)
 {
 	switch (base) {
-#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_MAPPI2)
+#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3)
 		case 0x1f0: return PLD_IRQ_CFIREQ;
 		default:
 			return 0;
diff --git a/include/asm-m32r/m32102.h b/include/asm-m32r/m32102.h
index b560340..cb98101 100644
--- a/include/asm-m32r/m32102.h
+++ b/include/asm-m32r/m32102.h
@@ -175,6 +175,7 @@
 #define M32R_ICU_CR5_PORTL    (0x210+M32R_ICU_OFFSET)  /* INT4 */
 #define M32R_ICU_CR6_PORTL    (0x214+M32R_ICU_OFFSET)  /* INT5 */
 #define M32R_ICU_CR7_PORTL    (0x218+M32R_ICU_OFFSET)  /* INT6 */
+#define M32R_ICU_CR8_PORTL    (0x219+M32R_ICU_OFFSET)  /* INT7 */
 #define M32R_ICU_CR16_PORTL   (0x23C+M32R_ICU_OFFSET)  /* MFT0 */
 #define M32R_ICU_CR17_PORTL   (0x240+M32R_ICU_OFFSET)  /* MFT1 */
 #define M32R_ICU_CR18_PORTL   (0x244+M32R_ICU_OFFSET)  /* MFT2 */
diff --git a/include/asm-m32r/m32102peri.h b/include/asm-m32r/m32102peri.h
deleted file mode 100644
index 3c12955..0000000
--- a/include/asm-m32r/m32102peri.h
+++ /dev/null
@@ -1,468 +0,0 @@
-/* $Id$
- *
- * 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) 2000,2001 by Hiroyuki Kondo
- */
-
-#ifndef __ASSEMBLY__
-
-typedef	void	V;
-typedef	char	B;
-typedef	short	S;
-typedef	int		W;
-typedef	long	L;
-typedef	float	F;
-typedef	double	D;
-typedef	unsigned char	UB;
-typedef	unsigned short	US;
-typedef	unsigned int	UW;
-typedef	unsigned long	UL;
-typedef	const unsigned int	CUW;
-
-/*********************************
-
-M32102 ICU
-
-*********************************/
-#define		ICUISTS		(UW *)0xa0EFF004
-#define		ICUIREQ0	(UW *)0xa0EFF008
-#define		ICUIREQ1	(UW *)0xa0EFF00C
-
-#define		ICUSBICR	(UW *)0xa0EFF018
-#define		ICUIMASK	(UW *)0xa0EFF01C
-
-#define		ICUCR1		(UW *)0xa0EFF200	/* INT0 */
-#define		ICUCR2		(UW *)0xa0EFF204	/* INT1 */
-#define		ICUCR3		(UW *)0xa0EFF208	/* INT2 */
-#define		ICUCR4		(UW *)0xa0EFF20C	/* INT3 */
-#define		ICUCR5		(UW *)0xa0EFF210	/* INT4 */
-#define		ICUCR6		(UW *)0xa0EFF214	/* INT5 */
-#define		ICUCR7		(UW *)0xa0EFF218	/* INT6 */
-
-#define		ICUCR16		(UW *)0xa0EFF23C	/* MFT0 */
-#define		ICUCR17		(UW *)0xa0EFF240	/* MFT1 */
-#define		ICUCR18		(UW *)0xa0EFF244	/* MFT2 */
-#define		ICUCR19		(UW *)0xa0EFF248	/* MFT3 */
-#define		ICUCR20		(UW *)0xa0EFF24C	/* MFT4 */
-#define		ICUCR21		(UW *)0xa0EFF250	/* MFT5 */
-
-#define		ICUCR32		(UW *)0xa0EFF27C	/* DMA0 */
-#define		ICUCR33		(UW *)0xa0EFF280	/* DMA1 */
-
-#define		ICUCR48		(UW *)0xa0EFF2BC	/* SIO0R */
-#define		ICUCR49		(UW *)0xa0EFF2C0	/* SIO0S */
-#define		ICUCR50		(UW *)0xa0EFF2C4	/* SIO1R */
-#define		ICUCR51		(UW *)0xa0EFF2C8	/* SIO1S */
-#define		ICUCR52		(UW *)0xa0EFF2CC	/* SIO2R */
-#define		ICUCR53		(UW *)0xa0EFF2D0	/* SIO2S */
-#define		ICUCR54		(UW *)0xa0EFF2D4	/* SIO3R */
-#define		ICUCR55		(UW *)0xa0EFF2D8	/* SIO3S */
-#define		ICUCR56		(UW *)0xa0EFF2DC	/* SIO4R */
-#define		ICUCR57		(UW *)0xa0EFF2E0	/* SIO4S */
-
-/*********************************
-
-M32102 MFT
-
-*********************************/
-#define		MFTCR		(US *)0xa0EFC002
-#define		MFTRPR		(UB *)0xa0EFC006
-
-#define		MFT0MOD		(US *)0xa0EFC102
-#define		MFT0BOS		(US *)0xa0EFC106
-#define		MFT0CUT		(US *)0xa0EFC10A
-#define		MFT0RLD		(US *)0xa0EFC10E
-#define		MFT0CRLD	(US *)0xa0EFC112
-
-#define		MFT1MOD		(US *)0xa0EFC202
-#define		MFT1BOS		(US *)0xa0EFC206
-#define		MFT1CUT		(US *)0xa0EFC20A
-#define		MFT1RLD		(US *)0xa0EFC20E
-#define		MFT1CRLD	(US *)0xa0EFC212
-
-#define		MFT2MOD		(US *)0xa0EFC302
-#define		MFT2BOS		(US *)0xa0EFC306
-#define		MFT2CUT		(US *)0xa0EFC30A
-#define		MFT2RLD		(US *)0xa0EFC30E
-#define		MFT2CRLD	(US *)0xa0EFC312
-
-#define		MFT3MOD		(US *)0xa0EFC402
-#define		MFT3CUT		(US *)0xa0EFC40A
-#define		MFT3RLD		(US *)0xa0EFC40E
-#define		MFT3CRLD	(US *)0xa0EFC412
-
-#define		MFT4MOD		(US *)0xa0EFC502
-#define		MFT4CUT		(US *)0xa0EFC50A
-#define		MFT4RLD		(US *)0xa0EFC50E
-#define		MFT4CRLD	(US *)0xa0EFC512
-
-#define		MFT5MOD		(US *)0xa0EFC602
-#define		MFT5CUT		(US *)0xa0EFC60A
-#define		MFT5RLD		(US *)0xa0EFC60E
-#define		MFT5CRLD	(US *)0xa0EFC612
-
-/*********************************
-
-M32102 SIO
-
-*********************************/
-
-#define SIO0CR     (volatile int *)0xa0efd000
-#define SIO0MOD0   (volatile int *)0xa0efd004
-#define SIO0MOD1   (volatile int *)0xa0efd008
-#define SIO0STS    (volatile int *)0xa0efd00c
-#define SIO0IMASK  (volatile int *)0xa0efd010
-#define SIO0BAUR   (volatile int *)0xa0efd014
-#define SIO0RBAUR  (volatile int *)0xa0efd018
-#define SIO0TXB    (volatile int *)0xa0efd01c
-#define SIO0RXB    (volatile int *)0xa0efd020
-
-#define SIO1CR     (volatile int *)0xa0efd100
-#define SIO1MOD0   (volatile int *)0xa0efd104
-#define SIO1MOD1   (volatile int *)0xa0efd108
-#define SIO1STS    (volatile int *)0xa0efd10c
-#define SIO1IMASK  (volatile int *)0xa0efd110
-#define SIO1BAUR   (volatile int *)0xa0efd114
-#define SIO1RBAUR  (volatile int *)0xa0efd118
-#define SIO1TXB    (volatile int *)0xa0efd11c
-#define SIO1RXB    (volatile int *)0xa0efd120
-/*********************************
-
-M32102 PORT
-
-*********************************/
-#define		PIEN		(UB *)0xa0EF1003	/* input enable */
-
-#define		P0DATA		(UB *)0xa0EF1020	/* data */
-#define		P1DATA		(UB *)0xa0EF1021
-#define		P2DATA		(UB *)0xa0EF1022
-#define		P3DATA		(UB *)0xa0EF1023
-#define		P4DATA		(UB *)0xa0EF1024
-#define		P5DATA		(UB *)0xa0EF1025
-#define		P6DATA		(UB *)0xa0EF1026
-#define		P7DATA		(UB *)0xa0EF1027
-
-#define		P0DIR		(UB *)0xa0EF1040	/* direction */
-#define		P1DIR		(UB *)0xa0EF1041
-#define		P2DIR		(UB *)0xa0EF1042
-#define		P3DIR		(UB *)0xa0EF1043
-#define		P4DIR		(UB *)0xa0EF1044
-#define		P5DIR		(UB *)0xa0EF1045
-#define		P6DIR		(UB *)0xa0EF1046
-#define		P7DIR		(UB *)0xa0EF1047
-
-#define		P0MOD		(US *)0xa0EF1060	/* mode control */
-#define		P1MOD		(US *)0xa0EF1062
-#define		P2MOD		(US *)0xa0EF1064
-#define		P3MOD		(US *)0xa0EF1066
-#define		P4MOD		(US *)0xa0EF1068
-#define		P5MOD		(US *)0xa0EF106A
-#define		P6MOD		(US *)0xa0EF106C
-#define		P7MOD		(US *)0xa0EF106E
-
-#define		P0ODCR		(UB *)0xa0EF1080	/* open-drain control */
-#define		P1ODCR		(UB *)0xa0EF1081
-#define		P2ODCR		(UB *)0xa0EF1082
-#define		P3ODCR		(UB *)0xa0EF1083
-#define		P4ODCR		(UB *)0xa0EF1084
-#define		P5ODCR		(UB *)0xa0EF1085
-#define		P6ODCR		(UB *)0xa0EF1086
-#define		P7ODCR		(UB *)0xa0EF1087
-
-/*********************************
-
-M32102 Cache
-
-********************************/
-
-#define		MCCR	(US *)0xFFFFFFFE
-
-
-#else  /* __ASSEMBLY__ */
-
-;;
-;; PIO     0x80ef1000
-;;
-
-#define PIEN          0xa0ef1000
-
-#define P0DATA        0xa0ef1020
-#define P1DATA        0xa0ef1021
-#define P2DATA        0xa0ef1022
-#define P3DATA        0xa0ef1023
-#define P4DATA        0xa0ef1024
-#define P5DATA        0xa0ef1025
-#define P6DATA        0xa0ef1026
-#define P7DATA        0xa0ef1027
-
-#define P0DIR         0xa0ef1040
-#define P1DIR         0xa0ef1041
-#define P2DIR         0xa0ef1042
-#define P3DIR         0xa0ef1043
-#define P4DIR         0xa0ef1044
-#define P5DIR         0xa0ef1045
-#define P6DIR         0xa0ef1046
-#define P7DIR         0xa0ef1047
-
-#define P0MOD         0xa0ef1060
-#define P1MOD         0xa0ef1062
-#define P2MOD         0xa0ef1064
-#define P3MOD         0xa0ef1066
-#define P4MOD         0xa0ef1068
-#define P5MOD         0xa0ef106a
-#define P6MOD         0xa0ef106c
-#define P7MOD         0xa0ef106e
-;
-#define P0ODCR        0xa0ef1080
-#define P1ODCR        0xa0ef1081
-#define P2ODCR        0xa0ef1082
-#define P3ODCR        0xa0ef1083
-#define P4ODCR        0xa0ef1084
-#define P5ODCR        0xa0ef1085
-#define P6ODCR        0xa0ef1086
-#define P7ODCR        0xa0ef1087
-
-;;
-;; WDT     0xa0ef2000
-;;
-
-#define WDTCR         0xa0ef2000
-
-
-;;
-;; CLK     0xa0ef4000
-;;
-
-#define CPUCLKCR      0xa0ef4000
-#define CLKMOD        0xa0ef4004
-#define PLLCR         0xa0ef4008
-
-
-;;
-;; BSEL    0xa0ef5000
-;;
-
-#define BSEL0CR       0xa0ef5000
-#define BSEL1CR       0xa0ef5004
-#define BSEL2CR       0xa0ef5008
-#define BSEL3CR       0xa0ef500c
-#define BSEL4CR       0xa0ef5010
-#define BSEL5CR       0xa0ef5014
-
-
-;;
-;; SDRAMC  0xa0ef6000
-;;
-
-#define SDRF0         0xa0ef6000
-#define SDRF1         0xa0ef6004
-#define SDIR0         0xa0ef6008
-#define SDIR1         0xa0ef600c
-#define SDBR          0xa0ef6010
-
-;; CH0
-#define SD0ADR        0xa0ef6020
-#define SD0SZ         0xa0ef6022
-#define SD0ER         0xa0ef6024
-#define SD0TR         0xa0ef6028
-#define SD0MOD        0xa0ef602c
-
-;; CH1
-#define SD1ADR        0xa0ef6040
-#define SD1SZ         0xa0ef6042
-#define SD1ER         0xa0ef6044
-#define SD1TR         0xa0ef6048
-#define SD1MOD        0xa0ef604c
-
-
-;;
-;; DMAC    0xa0ef8000
-;;
-
-#define DMAEN         0xa0ef8000
-#define DMAISTS       0xa0ef8004
-#define DMAEDET       0xa0ef8008
-#define DMAASTS       0xa0ef800c
-
-;; CH0
-#define DMA0CR0       0xa0ef8100
-#define DMA0CR1       0xa0ef8104
-#define DMA0CSA       0xa0ef8108
-#define DMA0RSA       0xa0ef810c
-#define DMA0CDA       0xa0ef8110
-#define DMA0RDA       0xa0ef8114
-#define DMA0CBCUT     0xa0ef8118
-#define DMA0RBCUT     0xa0ef811c
-
-;; CH1
-#define DMA1CR0       0xa0ef8200
-#define DMA1CR1       0xa0ef8204
-#define DMA1CSA       0xa0ef8208
-#define DMA1RSA       0xa0ef820c
-#define DMA1CDA       0xa0ef8210
-#define DMA1RDA       0xa0ef8214
-#define DMA1CBCUT     0xa0ef8218
-#define DMA1RBCUT     0xa0ef821c
-
-
-;;
-;; MFT     0xa0efc000
-;;
-
-#define MFTCR        0xa0efc000
-#define MFTRPR       0xa0efc004
-
-;; CH0
-#define MFT0MOD      0xa0efc100
-#define MFT0BOS      0xa0efc104
-#define MFT0CUT      0xa0efc108
-#define MFT0RLD      0xa0efc10c
-#define MFT0CMPRLD   0xa0efc110
-
-;; CH1
-#define MFT1MOD      0xa0efc200
-#define MFT1BOS      0xa0efc204
-#define MFT1CUT      0xa0efc208
-#define MFT1RLD      0xa0efc20c
-#define MFT1CMPRLD   0xa0efc210
-
-;; CH2
-#define MFT2MOD      0xa0efc300
-#define MFT2BOS      0xa0efc304
-#define MFT2CUT      0xa0efc308
-#define MFT2RLD      0xa0efc30c
-#define MFT2CMPRLD   0xa0efc310
-
-;; CH3
-#define MFT3MOD      0xa0efc400
-#define MFT3BOS      0xa0efc404
-#define MFT3CUT      0xa0efc408
-#define MFT3RLD      0xa0efc40c
-#define MFT3CMPRLD   0xa0efc410
-
-;; CH4
-#define MFT4MOD      0xa0efc500
-#define MFT4BOS      0xa0efc504
-#define MFT4CUT      0xa0efc508
-#define MFT4RLD      0xa0efc50c
-#define MFT4CMPRLD   0xa0efc510
-
-;; CH5
-#define MFT5MOD      0xa0efc600
-#define MFT5BOS      0xa0efc604
-#define MFT5CUT      0xa0efc608
-#define MFT5RLD      0xa0efc60c
-#define MFT5CMPRLD   0xa0efc610
-
-
-;;
-;; SIO     0xa0efd000
-;;
-
-;; CH0
-#define SIO0CR        0xa0efd000
-#define SIO0MOD0      0xa0efd004
-#define SIO0MOD1      0xa0efd008
-#define SIO0STS       0xa0efd00c
-#define SIO0IMASK     0xa0efd010
-#define SIO0BAUR      0xa0efd014
-#define SIO0RBAUR     0xa0efd018
-#define SIO0TXB       0xa0efd01c
-#define SIO0RXB       0xa0efd020
-
-;; CH1
-#define SIO1CR        0xa0efd100
-#define SIO1MOD0      0xa0efd104
-#define SIO1MOD1      0xa0efd108
-#define SIO1STS       0xa0efd10c
-#define SIO1IMASK     0xa0efd110
-#define SIO1BAUR      0xa0efd114
-#define SIO1RBAUR     0xa0efd118
-#define SIO1TXB       0xa0efd11c
-#define SIO1RXB       0xa0efd120
-
-;; CH2
-#define SIO2CR        0xa0efd200
-#define SIO2MOD0      0xa0efd204
-#define SIO2MOD1      0xa0efd208
-#define SIO2STS       0xa0efd20c
-#define SIO2IMASK     0xa0efd210
-#define SIO2BAUR      0xa0efd214
-#define SIO2RBAUR     0xa0efd218
-#define SIO2TXB       0xa0efd21c
-#define SIO2RXB       0xa0efd220
-
-;; CH3
-#define SIO3CR        0xa0efd300
-#define SIO3MOD0      0xa0efd304
-#define SIO3MOD1      0xa0efd308
-#define SIO3STS       0xa0efd30c
-#define SIO3IMASK     0xa0efd310
-#define SIO3BAUR      0xa0efd314
-#define SIO3RBAUR     0xa0efd318
-#define SIO3TXB       0xa0efd31c
-#define SIO3RXB       0xa0efd320
-
-;; CH4
-#define SIO4CR        0xa0efd400
-#define SIO4MOD0      0xa0efd404
-#define SIO4MOD1      0xa0efd408
-#define SIO4STS       0xa0efd40c
-#define SIO4IMASK     0xa0efd410
-#define SIO4BAUR      0xa0efd414
-#define SIO4RBAUR     0xa0efd418
-#define SIO4TXB       0xa0efd41c
-#define SIO4RXB       0xa0efd420
-
-
-;;
-;; ICU     0xa0eff000
-;;
-
-#define ICUISTS       0xa0eff004
-#define ICUIREQ0      0xa0eff008
-#define ICUIREQ1      0xa0eff00c
-
-#define ICUSBICR      0xa0eff018
-#define ICUIMASK      0xa0eff01c
-
-#define ICUCR1        0xa0eff200
-#define ICUCR2        0xa0eff204
-#define ICUCR3        0xa0eff208
-#define ICUCR4        0xa0eff20c
-#define ICUCR5        0xa0eff210
-#define ICUCR6        0xa0eff214
-#define ICUCR7        0xa0eff218
-
-#define ICUCR16       0xa0eff23c
-#define ICUCR17       0xa0eff240
-#define ICUCR18       0xa0eff244
-#define ICUCR19       0xa0eff248
-#define ICUCR20       0xa0eff24c
-#define ICUCR21       0xa0eff250
-
-#define ICUCR32       0xa0eff27c
-#define ICUCR33       0xa0eff280
-
-#define ICUCR48       0xa0eff2bc
-#define ICUCR49       0xa0eff2c0
-#define ICUCR50       0xa0eff2c4
-#define ICUCR51       0xa0eff2c8
-#define ICUCR52       0xa0eff2cc
-#define ICUCR53       0xa0eff2d0
-#define ICUCR54       0xa0eff2d4
-#define ICUCR55       0xa0eff2d8
-#define ICUCR56       0xa0eff2dc
-#define ICUCR57       0xa0eff2e0
-
-;;
-;; CACHE
-;;
-
-#define MCCR		  0xfffffffc
-
-
-#endif  /* __ASSEMBLY__ */
diff --git a/include/asm-m32r/m32r.h b/include/asm-m32r/m32r.h
index f116649..ec142be 100644
--- a/include/asm-m32r/m32r.h
+++ b/include/asm-m32r/m32r.h
@@ -16,7 +16,6 @@
 	|| defined(CONFIG_CHIP_M32700) || defined(CONFIG_CHIP_M32102) \
         || defined(CONFIG_CHIP_OPSP)
 #include <asm/m32102.h>
-#include <asm/m32102peri.h>
 #endif
 
 /* Platform type */
@@ -36,6 +35,10 @@
 #include <asm/mappi2/mappi2_pld.h>
 #endif	/* CONFIG_PLAT_MAPPI2 */
 
+#if defined(CONFIG_PLAT_MAPPI3)
+#include <asm/mappi3/mappi3_pld.h>
+#endif	/* CONFIG_PLAT_MAPPI3 */
+
 #if defined(CONFIG_PLAT_USRV)
 #include <asm/m32700ut/m32700ut_pld.h>
 #endif
diff --git a/include/asm-m32r/mappi3/mappi3_pld.h b/include/asm-m32r/mappi3/mappi3_pld.h
new file mode 100644
index 0000000..3f1551f
--- /dev/null
+++ b/include/asm-m32r/mappi3/mappi3_pld.h
@@ -0,0 +1,143 @@
+/*
+ * include/asm/mappi3/mappi3_pld.h
+ *
+ * Definitions for Extended IO Logic on MAPPI3 board.
+ *  based on m32700ut_pld.h
+ *
+ * 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.
+ *
+ */
+
+#ifndef _MAPPI3_PLD_H
+#define _MAPPI3_PLD_H
+
+#ifndef __ASSEMBLY__
+/* FIXME:
+ * Some C functions use non-cache address, so can't define non-cache address.
+ */
+#define PLD_BASE		(0x1c000000 /* + NONCACHE_OFFSET */)
+#define __reg8			(volatile unsigned char *)
+#define __reg16			(volatile unsigned short *)
+#define __reg32			(volatile unsigned int *)
+#else
+#define PLD_BASE		(0x1c000000 + NONCACHE_OFFSET)
+#define __reg8
+#define __reg16
+#define __reg32
+#endif	/* __ASSEMBLY__ */
+
+/* CFC */
+#define	PLD_CFRSTCR		__reg16(PLD_BASE + 0x0000)
+#define PLD_CFSTS		__reg16(PLD_BASE + 0x0002)
+#define PLD_CFIMASK		__reg16(PLD_BASE + 0x0004)
+#define PLD_CFBUFCR		__reg16(PLD_BASE + 0x0006)
+#define PLD_CFCR0		__reg16(PLD_BASE + 0x000a)
+#define PLD_CFCR1		__reg16(PLD_BASE + 0x000c)
+
+/* MMC */
+#define PLD_MMCCR		__reg16(PLD_BASE + 0x4000)
+#define PLD_MMCMOD		__reg16(PLD_BASE + 0x4002)
+#define PLD_MMCSTS		__reg16(PLD_BASE + 0x4006)
+#define PLD_MMCBAUR		__reg16(PLD_BASE + 0x400a)
+#define PLD_MMCCMDBCUT		__reg16(PLD_BASE + 0x400c)
+#define PLD_MMCCDTBCUT		__reg16(PLD_BASE + 0x400e)
+#define PLD_MMCDET		__reg16(PLD_BASE + 0x4010)
+#define PLD_MMCWP		__reg16(PLD_BASE + 0x4012)
+#define PLD_MMCWDATA		__reg16(PLD_BASE + 0x5000)
+#define PLD_MMCRDATA		__reg16(PLD_BASE + 0x6000)
+#define PLD_MMCCMDDATA		__reg16(PLD_BASE + 0x7000)
+#define PLD_MMCRSPDATA		__reg16(PLD_BASE + 0x7006)
+
+/* Power Control of MMC and CF */
+#define PLD_CPCR		__reg16(PLD_BASE + 0x14000)
+
+
+/*==== ICU ====*/
+#define  M32R_IRQ_PC104        (5)   /* INT4(PC/104) */
+#define  M32R_IRQ_I2C          (28)  /* I2C-BUS     */
+#define  PLD_IRQ_CFIREQ       (6)  /* INT5 CFC Card Interrupt */
+#define  PLD_IRQ_CFC_INSERT   (7)  /* INT6 CFC Card Insert */
+#define  PLD_IRQ_CFC_EJECT    (8)  /* INT7 CFC Card Eject */
+#define  PLD_IRQ_MMCCARD      (43)  /* MMC Card Insert */
+#define  PLD_IRQ_MMCIRQ       (44)  /* MMC Transfer Done */
+
+
+#if 0
+/* LED Control
+ *
+ * 1: DIP swich side
+ * 2: Reset switch side
+ */
+#define PLD_IOLEDCR		__reg16(PLD_BASE + 0x14002)
+#define PLD_IOLED_1_ON		0x001
+#define PLD_IOLED_1_OFF		0x000
+#define PLD_IOLED_2_ON		0x002
+#define PLD_IOLED_2_OFF		0x000
+
+/* DIP Switch
+ *  0: Write-protect of Flash Memory (0:protected, 1:non-protected)
+ *  1: -
+ *  2: -
+ *  3: -
+ */
+#define PLD_IOSWSTS		__reg16(PLD_BASE + 0x14004)
+#define	PLD_IOSWSTS_IOSW2	0x0200
+#define	PLD_IOSWSTS_IOSW1	0x0100
+#define	PLD_IOSWSTS_IOWP0	0x0001
+
+#endif
+
+/* CRC */
+#define PLD_CRC7DATA		__reg16(PLD_BASE + 0x18000)
+#define PLD_CRC7INDATA		__reg16(PLD_BASE + 0x18002)
+#define PLD_CRC16DATA		__reg16(PLD_BASE + 0x18004)
+#define PLD_CRC16INDATA		__reg16(PLD_BASE + 0x18006)
+#define PLD_CRC16ADATA		__reg16(PLD_BASE + 0x18008)
+#define PLD_CRC16AINDATA	__reg16(PLD_BASE + 0x1800a)
+
+
+#if 0
+/* RTC */
+#define PLD_RTCCR		__reg16(PLD_BASE + 0x1c000)
+#define PLD_RTCBAUR		__reg16(PLD_BASE + 0x1c002)
+#define PLD_RTCWRDATA		__reg16(PLD_BASE + 0x1c004)
+#define PLD_RTCRDDATA		__reg16(PLD_BASE + 0x1c006)
+#define PLD_RTCRSTODT		__reg16(PLD_BASE + 0x1c008)
+
+/* SIO0 */
+#define PLD_ESIO0CR		__reg16(PLD_BASE + 0x20000)
+#define	PLD_ESIO0CR_TXEN	0x0001
+#define	PLD_ESIO0CR_RXEN	0x0002
+#define PLD_ESIO0MOD0		__reg16(PLD_BASE + 0x20002)
+#define	PLD_ESIO0MOD0_CTSS	0x0040
+#define	PLD_ESIO0MOD0_RTSS	0x0080
+#define PLD_ESIO0MOD1		__reg16(PLD_BASE + 0x20004)
+#define	PLD_ESIO0MOD1_LMFS	0x0010
+#define PLD_ESIO0STS		__reg16(PLD_BASE + 0x20006)
+#define	PLD_ESIO0STS_TEMP	0x0001
+#define	PLD_ESIO0STS_TXCP	0x0002
+#define	PLD_ESIO0STS_RXCP	0x0004
+#define	PLD_ESIO0STS_TXSC	0x0100
+#define	PLD_ESIO0STS_RXSC	0x0200
+#define PLD_ESIO0STS_TXREADY	(PLD_ESIO0STS_TXCP | PLD_ESIO0STS_TEMP)
+#define PLD_ESIO0INTCR		__reg16(PLD_BASE + 0x20008)
+#define	PLD_ESIO0INTCR_TXIEN	0x0002
+#define	PLD_ESIO0INTCR_RXCEN	0x0004
+#define PLD_ESIO0BAUR		__reg16(PLD_BASE + 0x2000a)
+#define PLD_ESIO0TXB		__reg16(PLD_BASE + 0x2000c)
+#define PLD_ESIO0RXB		__reg16(PLD_BASE + 0x2000e)
+
+/* SIM Card */
+#define PLD_SCCR		__reg16(PLD_BASE + 0x38000)
+#define PLD_SCMOD		__reg16(PLD_BASE + 0x38004)
+#define PLD_SCSTS		__reg16(PLD_BASE + 0x38006)
+#define PLD_SCINTCR		__reg16(PLD_BASE + 0x38008)
+#define PLD_SCBAUR		__reg16(PLD_BASE + 0x3800a)
+#define PLD_SCTXB		__reg16(PLD_BASE + 0x3800c)
+#define PLD_SCRXB		__reg16(PLD_BASE + 0x3800e)
+
+#endif
+
+#endif	/* _MAPPI3_PLD.H */
diff --git a/include/asm-m32r/mmzone.h b/include/asm-m32r/mmzone.h
index ebf0228..d58878e 100644
--- a/include/asm-m32r/mmzone.h
+++ b/include/asm-m32r/mmzone.h
@@ -14,7 +14,6 @@
 #define NODE_DATA(nid)		(node_data[nid])
 
 #define node_localnr(pfn, nid)	((pfn) - NODE_DATA(nid)->node_start_pfn)
-#define node_mem_map(nid)	(NODE_DATA(nid)->node_mem_map)
 #define node_start_pfn(nid)	(NODE_DATA(nid)->node_start_pfn)
 #define node_end_pfn(nid)						\
 ({									\
@@ -32,7 +31,7 @@
 ({									\
 	unsigned long __pfn = pfn;					\
 	int __node  = pfn_to_nid(__pfn);				\
-	&node_mem_map(__node)[node_localnr(__pfn,__node)];		\
+	&NODE_DATA(__node)->node_mem_map[node_localnr(__pfn,__node)];	\
 })
 
 #define page_to_pfn(pg)							\
diff --git a/include/asm-m32r/smp.h b/include/asm-m32r/smp.h
index 8cd4d0d..b9a20cd 100644
--- a/include/asm-m32r/smp.h
+++ b/include/asm-m32r/smp.h
@@ -66,7 +66,7 @@
 #define physid_to_cpu(physid)	physid_2_cpu[physid]
 #define cpu_to_physid(cpu_id)	cpu_2_physid[cpu_id]
 
-#define smp_processor_id()	(current_thread_info()->cpu)
+#define raw_smp_processor_id()	(current_thread_info()->cpu)
 
 extern cpumask_t cpu_callout_map;
 #define cpu_possible_map cpu_callout_map
diff --git a/include/asm-m32r/thread_info.h b/include/asm-m32r/thread_info.h
index 9f3a0fc..7a6be77 100644
--- a/include/asm-m32r/thread_info.h
+++ b/include/asm-m32r/thread_info.h
@@ -28,7 +28,7 @@
 	unsigned long		flags;		/* low level flags */
 	unsigned long		status;		/* thread-synchronous flags */
 	__u32			cpu;		/* current CPU */
-	__s32			preempt_count; /* 0 => preemptable, <0 => BUG */
+	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user-thread
diff --git a/include/asm-m32r/topology.h b/include/asm-m32r/topology.h
index 299a89d..d607eb3 100644
--- a/include/asm-m32r/topology.h
+++ b/include/asm-m32r/topology.h
@@ -1,48 +1,6 @@
-/*
- * linux/include/asm-generic/topology.h
- *
- * Written by: Matthew Dobson, IBM Corporation
- *
- * Copyright (C) 2002, IBM Corp.
- *
- * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <colpatch@us.ibm.com>
- */
 #ifndef _ASM_M32R_TOPOLOGY_H
 #define _ASM_M32R_TOPOLOGY_H
 
-/* Other architectures wishing to use this simple topology API should fill
-   in the below functions as appropriate in their own <asm/topology.h> file. */
-
-#define cpu_to_node(cpu)	(0)
-
-#ifndef parent_node
-#define parent_node(node)	(0)
-#endif
-#ifndef node_to_cpumask
-#define node_to_cpumask(node)	(cpu_online_map)
-#endif
-#ifndef node_to_first_cpu
-#define node_to_first_cpu(node)	(0)
-#endif
-#ifndef pcibus_to_cpumask
-#define pcibus_to_cpumask(bus)	(cpu_online_map)
-#endif
+#include <asm-generic/topology.h>
 
 #endif /* _ASM_M32R_TOPOLOGY_H */
diff --git a/include/asm-m68k/thread_info.h b/include/asm-m68k/thread_info.h
index 5f58939..2aed24f 100644
--- a/include/asm-m68k/thread_info.h
+++ b/include/asm-m68k/thread_info.h
@@ -8,7 +8,7 @@
 struct thread_info {
 	struct task_struct	*task;		/* main task structure */
 	struct exec_domain	*exec_domain;	/* execution domain */
-	__s32			preempt_count; /* 0 => preemptable, <0 => BUG */
+	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
 	__u32 cpu; /* should always be 0 on m68k */
 	struct restart_block    restart_block;
 
diff --git a/include/asm-m68knommu/thread_info.h b/include/asm-m68knommu/thread_info.h
index c8153b7..7b9a3fa 100644
--- a/include/asm-m68knommu/thread_info.h
+++ b/include/asm-m68knommu/thread_info.h
@@ -36,7 +36,7 @@
 	struct exec_domain *exec_domain;	/* execution domain */
 	unsigned long	   flags;		/* low level flags */
 	int		   cpu;			/* cpu we're on */
-	int		   preempt_count;	/* 0 => preemptable, <0 => BUG*/
+	int		   preempt_count;	/* 0 => preemptable, <0 => BUG */
 	struct restart_block restart_block;
 };
 
diff --git a/include/asm-mips/compat.h b/include/asm-mips/compat.h
index dce9207..d78002a 100644
--- a/include/asm-mips/compat.h
+++ b/include/asm-mips/compat.h
@@ -29,6 +29,7 @@
 typedef struct {
 	s32	val[2];
 } compat_fsid_t;
+typedef s32		compat_timer_t;
 
 typedef s32		compat_int_t;
 typedef s32		compat_long_t;
diff --git a/include/asm-mips/mmzone.h b/include/asm-mips/mmzone.h
index 29ee13b..d721143 100644
--- a/include/asm-mips/mmzone.h
+++ b/include/asm-mips/mmzone.h
@@ -8,6 +8,8 @@
 #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)
 
@@ -36,4 +38,6 @@
 /* XXX: FIXME -- wli */
 #define kern_addr_valid(addr)	(0)
 
+#endif /* CONFIG_DISCONTIGMEM */
+
 #endif /* _ASM_MMZONE_H_ */
diff --git a/include/asm-mips/page.h b/include/asm-mips/page.h
index d1bf824..5cae35c 100644
--- a/include/asm-mips/page.h
+++ b/include/asm-mips/page.h
@@ -127,7 +127,7 @@
 
 #define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
 
-#ifndef CONFIG_DISCONTIGMEM
+#ifndef CONFIG_NEED_MULTIPLE_NODES
 #define pfn_to_page(pfn)	(mem_map + (pfn))
 #define page_to_pfn(page)	((unsigned long)((page) - mem_map))
 #define pfn_valid(pfn)		((pfn) < max_mapnr)
diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h
index 8788432..e76ccd6 100644
--- a/include/asm-mips/pgtable.h
+++ b/include/asm-mips/pgtable.h
@@ -350,7 +350,7 @@
 	__update_cache(vma, address, pte);
 }
 
-#ifndef CONFIG_DISCONTIGMEM
+#ifndef CONFIG_NEED_MULTIPLE_NODES
 #define kern_addr_valid(addr)	(1)
 #endif
 
diff --git a/include/asm-mips/smp.h b/include/asm-mips/smp.h
index 8ba370e..5618f1e 100644
--- a/include/asm-mips/smp.h
+++ b/include/asm-mips/smp.h
@@ -21,7 +21,7 @@
 #include <linux/cpumask.h>
 #include <asm/atomic.h>
 
-#define smp_processor_id()	(current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
 
 /* Map from cpu id to sequential logical cpu number.  This will only
    not be idempotent when cpus failed to come on-line.  */
diff --git a/include/asm-mips/system.h b/include/asm-mips/system.h
index 888fd89..169f3d4 100644
--- a/include/asm-mips/system.h
+++ b/include/asm-mips/system.h
@@ -422,16 +422,10 @@
 extern int stop_a_enabled;
 
 /*
- * Taken from include/asm-ia64/system.h; prevents deadlock on SMP
+ * See include/asm-ia64/system.h; prevents deadlock on SMP
  * systems.
  */
-#define prepare_arch_switch(rq, next)		\
-do {						\
-	spin_lock(&(next)->switch_lock);	\
-	spin_unlock(&(rq)->lock);		\
-} while (0)
-#define finish_arch_switch(rq, prev)	spin_unlock_irq(&(prev)->switch_lock)
-#define task_running(rq, p) 		((rq)->curr == (p) || spin_is_locked(&(p)->switch_lock))
+#define __ARCH_WANT_UNLOCKED_CTXSW
 
 #define arch_align_stack(x) (x)
 
diff --git a/include/asm-mips/thread_info.h b/include/asm-mips/thread_info.h
index 7689003..42fcd6f 100644
--- a/include/asm-mips/thread_info.h
+++ b/include/asm-mips/thread_info.h
@@ -27,7 +27,7 @@
 	struct exec_domain	*exec_domain;	/* execution domain */
 	unsigned long		flags;		/* low level flags */
 	__u32			cpu;		/* current CPU */
-	__s32			preempt_count; /* 0 => preemptable, <0 => BUG */
+	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
 
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user-thead
diff --git a/include/asm-mips/vr41xx/giu.h b/include/asm-mips/vr41xx/giu.h
new file mode 100644
index 0000000..8590885
--- /dev/null
+++ b/include/asm-mips/vr41xx/giu.h
@@ -0,0 +1,69 @@
+/*
+ *  Include file for NEC VR4100 series General-purpose I/O Unit.
+ *
+ *  Copyright (C) 2005  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ *  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 __NEC_VR41XX_GIU_H
+#define __NEC_VR41XX_GIU_H
+
+typedef enum {
+	IRQ_TRIGGER_LEVEL,
+	IRQ_TRIGGER_EDGE,
+	IRQ_TRIGGER_EDGE_FALLING,
+	IRQ_TRIGGER_EDGE_RISING,
+} irq_trigger_t;
+
+typedef enum {
+	IRQ_SIGNAL_THROUGH,
+	IRQ_SIGNAL_HOLD,
+} irq_signal_t;
+
+extern void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal);
+
+typedef enum {
+	IRQ_LEVEL_LOW,
+	IRQ_LEVEL_HIGH,
+} irq_level_t;
+
+extern void vr41xx_set_irq_level(unsigned int pin, irq_level_t level);
+
+typedef enum {
+	GPIO_DATA_LOW,
+	GPIO_DATA_HIGH,
+	GPIO_DATA_INVAL,
+} gpio_data_t;
+
+extern gpio_data_t vr41xx_gpio_get_pin(unsigned int pin);
+extern int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data);
+
+typedef enum {
+	GPIO_INPUT,
+	GPIO_OUTPUT,
+	GPIO_OUTPUT_DISABLE,
+} gpio_direction_t;
+
+extern int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir);
+
+typedef enum {
+	GPIO_PULL_DOWN,
+	GPIO_PULL_UP,
+	GPIO_PULL_DISABLE,
+} gpio_pull_t;
+
+extern int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull);
+
+#endif /* __NEC_VR41XX_GIU_H */
diff --git a/include/asm-mips/vr41xx/vr41xx.h b/include/asm-mips/vr41xx/vr41xx.h
index ad0d1ea..7d41e44 100644
--- a/include/asm-mips/vr41xx/vr41xx.h
+++ b/include/asm-mips/vr41xx/vr41xx.h
@@ -126,7 +126,6 @@
 #define GIU_IRQ_BASE		40
 #define GIU_IRQ(x)		(GIU_IRQ_BASE + (x))	/* IRQ 40-71 */
 #define GIU_IRQ_LAST		GIU_IRQ(31)
-#define GIU_IRQ_TO_PIN(x)	((x) - GIU_IRQ_BASE)	/* Pin 0-31 */
 
 extern int vr41xx_set_intassign(unsigned int irq, unsigned char intassign);
 extern int vr41xx_cascade_irq(unsigned int irq, int (*get_irq_number)(int irq));
@@ -197,38 +196,4 @@
 extern void vr41xx_enable_bcuint(void);
 extern void vr41xx_disable_bcuint(void);
 
-/*
- * General-Purpose I/O Unit
- */
-enum {
-	TRIGGER_LEVEL,
-	TRIGGER_EDGE,
-	TRIGGER_EDGE_FALLING,
-	TRIGGER_EDGE_RISING
-};
-
-enum {
-	SIGNAL_THROUGH,
-	SIGNAL_HOLD
-};
-
-extern void vr41xx_set_irq_trigger(int pin, int trigger, int hold);
-
-enum {
-	LEVEL_LOW,
-	LEVEL_HIGH
-};
-
-extern void vr41xx_set_irq_level(int pin, int level);
-
-enum {
-	PIO_INPUT,
-	PIO_OUTPUT
-};
-
-enum {
-	DATA_LOW,
-	DATA_HIGH
-};
-
 #endif /* __NEC_VR41XX_H */
diff --git a/include/asm-parisc/compat.h b/include/asm-parisc/compat.h
index ca0eac6..7630d1a 100644
--- a/include/asm-parisc/compat.h
+++ b/include/asm-parisc/compat.h
@@ -24,7 +24,7 @@
 typedef u16	compat_ipc_pid_t;
 typedef s32	compat_daddr_t;
 typedef u32	compat_caddr_t;
-typedef u32	compat_timer_t;
+typedef s32	compat_timer_t;
 
 typedef s32	compat_int_t;
 typedef s32	compat_long_t;
diff --git a/include/asm-parisc/mmzone.h b/include/asm-parisc/mmzone.h
index 928bf50..595d3dc 100644
--- a/include/asm-parisc/mmzone.h
+++ b/include/asm-parisc/mmzone.h
@@ -19,7 +19,6 @@
  */
 #define kvaddr_to_nid(kaddr)	pfn_to_nid(__pa(kaddr) >> PAGE_SHIFT)
 
-#define node_mem_map(nid)	(NODE_DATA(nid)->node_mem_map)
 #define node_start_pfn(nid)	(NODE_DATA(nid)->node_start_pfn)
 #define node_end_pfn(nid)						\
 ({									\
@@ -38,7 +37,7 @@
 ({									\
 	unsigned long __pfn = (pfn);					\
 	int __node  = pfn_to_nid(__pfn);				\
-	&node_mem_map(__node)[node_localnr(__pfn,__node)];		\
+	&NODE_DATA(__node)->node_mem_map[node_localnr(__pfn,__node)];	\
 })
 
 #define page_to_pfn(pg)							\
diff --git a/include/asm-parisc/smp.h b/include/asm-parisc/smp.h
index fde77ac..9413f67 100644
--- a/include/asm-parisc/smp.h
+++ b/include/asm-parisc/smp.h
@@ -51,7 +51,7 @@
 
 extern unsigned long cpu_present_mask;
 
-#define smp_processor_id()	(current_thread_info()->cpu)
+#define raw_smp_processor_id()	(current_thread_info()->cpu)
 
 #endif /* CONFIG_SMP */
 
diff --git a/include/asm-parisc/thread_info.h b/include/asm-parisc/thread_info.h
index fe9b7f8..57bbb76 100644
--- a/include/asm-parisc/thread_info.h
+++ b/include/asm-parisc/thread_info.h
@@ -12,7 +12,7 @@
 	unsigned long flags;		/* thread_info flags (see TIF_*) */
 	mm_segment_t addr_limit;	/* user-level address space limit */
 	__u32 cpu;			/* current CPU */
-	__s32 preempt_count;		/* 0=premptable, <0=BUG; will also serve as bh-counter */
+	int preempt_count;		/* 0=premptable, <0=BUG; will also serve as bh-counter */
 	struct restart_block restart_block;
 };
 
diff --git a/include/asm-ppc/agp.h b/include/asm-ppc/agp.h
index be27cfa..ca9e423 100644
--- a/include/asm-ppc/agp.h
+++ b/include/asm-ppc/agp.h
@@ -10,4 +10,14 @@
 #define flush_agp_mappings()
 #define flush_agp_cache() mb()
 
+/* Convert a physical address to an address suitable for the GART. */
+#define phys_to_gart(x) (x)
+#define gart_to_phys(x) (x)
+
+/* GATT allocation. Returns/accepts GATT kernel virtual address. */
+#define alloc_gatt_pages(order)		\
+	((char *)__get_free_pages(GFP_KERNEL, (order)))
+#define free_gatt_pages(table, order)	\
+	free_pages((unsigned long)(table), (order))
+
 #endif
diff --git a/include/asm-ppc/fsl_ocp.h b/include/asm-ppc/fsl_ocp.h
deleted file mode 100644
index 050fbba..0000000
--- a/include/asm-ppc/fsl_ocp.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * include/asm-ppc/fsl_ocp.h
- *
- * Definitions for the on-chip peripherals on Freescale PPC processors
- *
- * Maintainer: Kumar Gala (kumar.gala@freescale.com)
- *
- * 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_FS_OCP_H__
-#define __ASM_FS_OCP_H__
-
-/* A table of information for supporting the Gianfar Ethernet Controller
- * This helps identify which enet controller we are dealing with,
- * and what type of enet controller it is
- */
-struct ocp_gfar_data {
-	uint interruptTransmit;
-	uint interruptError;
-	uint interruptReceive;
-	uint interruptPHY;
-	uint flags;
-	uint phyid;
-	uint phyregidx;
-	unsigned char mac_addr[6];
-};
-
-/* Flags in the flags field */
-#define GFAR_HAS_COALESCE		0x20
-#define GFAR_HAS_RMON			0x10
-#define GFAR_HAS_MULTI_INTR		0x08
-#define GFAR_FIRM_SET_MACADDR		0x04
-#define GFAR_HAS_PHY_INTR		0x02	/* if not set use a timer */
-#define GFAR_HAS_GIGABIT		0x01
-
-/* Data structure for I2C support.  Just contains a couple flags
- * to distinguish various I2C implementations*/
-struct ocp_fs_i2c_data {
-	uint flags;
-};
-
-/* Flags for I2C */
-#define FS_I2C_SEPARATE_DFSRR	0x02
-#define FS_I2C_CLOCK_5200	0x01
-
-#endif	/* __ASM_FS_OCP_H__ */
-#endif	/* __KERNEL__ */
diff --git a/include/asm-ppc/irq.h b/include/asm-ppc/irq.h
index 06b86be..a9b3332 100644
--- a/include/asm-ppc/irq.h
+++ b/include/asm-ppc/irq.h
@@ -176,7 +176,7 @@
 */
 #include <asm/mpc85xx.h>
 
-/* The MPC8560 openpic has  32 internal interrupts and 12 external
+/* The MPC8548 openpic has 48 internal interrupts and 12 external
  * interrupts.
  *
  * We are "flattening" the interrupt vectors of the cascaded CPM
@@ -184,7 +184,7 @@
  * single integer.
  */
 #define NR_CPM_INTS	64
-#define NR_EPIC_INTS	44
+#define NR_EPIC_INTS	60
 #ifndef NR_8259_INTS
 #define NR_8259_INTS	0
 #endif
@@ -223,9 +223,15 @@
 #define MPC85xx_IRQ_RIO_RX	(12 + MPC85xx_OPENPIC_IRQ_OFFSET)
 #define MPC85xx_IRQ_TSEC1_TX	(13 + MPC85xx_OPENPIC_IRQ_OFFSET)
 #define MPC85xx_IRQ_TSEC1_RX	(14 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC3_TX	(15 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC3_RX	(16 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC3_ERROR	(17 + MPC85xx_OPENPIC_IRQ_OFFSET)
 #define MPC85xx_IRQ_TSEC1_ERROR	(18 + MPC85xx_OPENPIC_IRQ_OFFSET)
 #define MPC85xx_IRQ_TSEC2_TX	(19 + MPC85xx_OPENPIC_IRQ_OFFSET)
 #define MPC85xx_IRQ_TSEC2_RX	(20 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC4_TX	(21 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC4_RX	(22 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_TSEC4_ERROR	(23 + MPC85xx_OPENPIC_IRQ_OFFSET)
 #define MPC85xx_IRQ_TSEC2_ERROR	(24 + MPC85xx_OPENPIC_IRQ_OFFSET)
 #define MPC85xx_IRQ_FEC		(25 + MPC85xx_OPENPIC_IRQ_OFFSET)
 #define MPC85xx_IRQ_DUART	(26 + MPC85xx_OPENPIC_IRQ_OFFSET)
@@ -235,18 +241,18 @@
 #define MPC85xx_IRQ_CPM		(30 + MPC85xx_OPENPIC_IRQ_OFFSET)
 
 /* The 12 external interrupt lines */
-#define MPC85xx_IRQ_EXT0        (32 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT1        (33 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT2        (34 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT3        (35 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT4        (36 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT5        (37 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT6        (38 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT7        (39 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT8        (40 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT9        (41 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT10       (42 + MPC85xx_OPENPIC_IRQ_OFFSET)
-#define MPC85xx_IRQ_EXT11       (43 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT0        (48 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT1        (49 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT2        (50 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT3        (51 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT4        (52 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT5        (53 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT6        (54 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT7        (55 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT8        (56 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT9        (57 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT10       (58 + MPC85xx_OPENPIC_IRQ_OFFSET)
+#define MPC85xx_IRQ_EXT11       (59 + MPC85xx_OPENPIC_IRQ_OFFSET)
 
 /* CPM related interrupts */
 #define	SIU_INT_ERROR		((uint)0x00+CPM_IRQ_OFFSET)
diff --git a/include/asm-ppc/kexec.h b/include/asm-ppc/kexec.h
new file mode 100644
index 0000000..7319131
--- /dev/null
+++ b/include/asm-ppc/kexec.h
@@ -0,0 +1,38 @@
+#ifndef _PPC_KEXEC_H
+#define _PPC_KEXEC_H
+
+#ifdef CONFIG_KEXEC
+
+/*
+ * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.
+ * I.e. Maximum page that is mapped directly into kernel memory,
+ * and kmap is not required.
+ *
+ * Someone correct me if FIXADDR_START - PAGEOFFSET is not the correct
+ * calculation for the amount of memory directly mappable into the
+ * kernel memory space.
+ */
+
+/* Maximum physical address we can use pages from */
+#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
+/* Maximum address we can reach in physical address mode */
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
+/* Maximum address we can use for the control code buffer */
+#define KEXEC_CONTROL_MEMORY_LIMIT TASK_SIZE
+
+#define KEXEC_CONTROL_CODE_SIZE	4096
+
+/* The native architecture */
+#define KEXEC_ARCH KEXEC_ARCH_PPC
+
+#ifndef __ASSEMBLY__
+
+struct kimage;
+
+extern void machine_kexec_simple(struct kimage *image);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* CONFIG_KEXEC */
+
+#endif /* _PPC_KEXEC_H */
diff --git a/include/asm-ppc/machdep.h b/include/asm-ppc/machdep.h
index b78d408..1d4ab70 100644
--- a/include/asm-ppc/machdep.h
+++ b/include/asm-ppc/machdep.h
@@ -4,6 +4,7 @@
 
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/kexec.h>
 
 #include <asm/setup.h>
 #include <asm/page.h>
@@ -114,6 +115,36 @@
 	/* functions for dealing with other cpus */
 	struct smp_ops_t *smp_ops;
 #endif /* CONFIG_SMP */
+
+#ifdef CONFIG_KEXEC
+	/* Called to shutdown machine specific hardware not already controlled
+	 * by other drivers.
+	 * XXX Should we move this one out of kexec scope?
+	 */
+	void (*machine_shutdown)(void);
+
+	/* Called to do the minimal shutdown needed to run a kexec'd kernel
+	 * to run successfully.
+	 * XXX Should we move this one out of kexec scope?
+	 */
+	void (*machine_crash_shutdown)(void);
+
+	/* Called to do what every setup is needed on image and the
+	 * reboot code buffer. Returns 0 on success.
+	 * Provide your own (maybe dummy) implementation if your platform
+	 * claims to support kexec.
+	 */
+	int (*machine_kexec_prepare)(struct kimage *image);
+
+	/* Called to handle any machine specific cleanup on image */
+	void (*machine_kexec_cleanup)(struct kimage *image);
+
+	/* Called to perform the _real_ kexec.
+	 * Do NOT allocate memory or fail here. We are past the point of
+	 * no return.
+	 */
+	void (*machine_kexec)(struct kimage *image);
+#endif /* CONFIG_KEXEC */
 };
 
 extern struct machdep_calls ppc_md;
diff --git a/include/asm-ppc/mmu.h b/include/asm-ppc/mmu.h
index d465aee..9205db4 100644
--- a/include/asm-ppc/mmu.h
+++ b/include/asm-ppc/mmu.h
@@ -405,7 +405,7 @@
 
 #define MAS0_TLBSEL(x)	((x << 28) & 0x30000000)
 #define MAS0_ESEL(x)	((x << 16) & 0x0FFF0000)
-#define MAS0_NV		0x00000FFF
+#define MAS0_NV(x)	((x) & 0x00000FFF)
 
 #define MAS1_VALID 	0x80000000
 #define MAS1_IPROT	0x40000000
diff --git a/include/asm-ppc/mmu_context.h b/include/asm-ppc/mmu_context.h
index 9222fa6..ccabbce 100644
--- a/include/asm-ppc/mmu_context.h
+++ b/include/asm-ppc/mmu_context.h
@@ -63,7 +63,7 @@
 #define LAST_CONTEXT    	255
 #define FIRST_CONTEXT    	1
 
-#elif defined(CONFIG_E500)
+#elif defined(CONFIG_E200) || defined(CONFIG_E500)
 #define NO_CONTEXT      	256
 #define LAST_CONTEXT    	255
 #define FIRST_CONTEXT    	1
diff --git a/include/asm-ppc/mpc10x.h b/include/asm-ppc/mpc10x.h
index d8e7e2d..f5196a4 100644
--- a/include/asm-ppc/mpc10x.h
+++ b/include/asm-ppc/mpc10x.h
@@ -159,6 +159,12 @@
 #define	MPC10X_MAPA_EUMB_BASE		(ioremap_base - MPC10X_EUMB_SIZE)
 #define	MPC10X_MAPB_EUMB_BASE		MPC10X_MAPA_EUMB_BASE
 
+enum ppc_sys_devices {
+	MPC10X_IIC1,
+	MPC10X_DMA0,
+	MPC10X_DMA1,
+	MPC10X_DUART,
+};
 
 int mpc10x_bridge_init(struct pci_controller *hose,
 		       uint current_map,
diff --git a/include/asm-ppc/mpc85xx.h b/include/asm-ppc/mpc85xx.h
index 22713e3..516984e 100644
--- a/include/asm-ppc/mpc85xx.h
+++ b/include/asm-ppc/mpc85xx.h
@@ -25,7 +25,7 @@
 #ifdef CONFIG_MPC8540_ADS
 #include <platforms/85xx/mpc8540_ads.h>
 #endif
-#ifdef CONFIG_MPC8555_CDS
+#if defined(CONFIG_MPC8555_CDS) || defined(CONFIG_MPC8548_CDS)
 #include <platforms/85xx/mpc8555_cds.h>
 #endif
 #ifdef CONFIG_MPC8560_ADS
@@ -74,7 +74,7 @@
 #define MPC85xx_GUTS_OFFSET	(0xe0000)
 #define MPC85xx_GUTS_SIZE	(0x01000)
 #define MPC85xx_IIC1_OFFSET	(0x03000)
-#define MPC85xx_IIC1_SIZE	(0x01000)
+#define MPC85xx_IIC1_SIZE	(0x00100)
 #define MPC85xx_OPENPIC_OFFSET	(0x40000)
 #define MPC85xx_OPENPIC_SIZE	(0x40000)
 #define MPC85xx_PCI1_OFFSET	(0x08000)
@@ -127,8 +127,64 @@
 	MPC85xx_CPM_MCC2,
 	MPC85xx_CPM_SMC1,
 	MPC85xx_CPM_SMC2,
+	MPC85xx_eTSEC1,
+	MPC85xx_eTSEC2,
+	MPC85xx_eTSEC3,
+	MPC85xx_eTSEC4,
+	MPC85xx_IIC2,
 };
 
+/* Internal interrupts are all Level Sensitive, and Positive Polarity */
+#define MPC85XX_INTERNAL_IRQ_SENSES \
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  0 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  1 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  2 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  3 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  4 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  5 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  6 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  7 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  8 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  9 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 10 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 11 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 12 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 13 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 14 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 15 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 16 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 17 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 18 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 19 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 20 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 21 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 22 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 23 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 24 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 25 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 26 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 27 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 28 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 29 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 30 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 31 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 32 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 33 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 34 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 35 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 36 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 37 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 38 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 39 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 40 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 41 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 42 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 43 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 44 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 45 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 46 */	\
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE)	/* Internal 47 */
+
 #endif /* CONFIG_85xx */
 #endif /* __ASM_MPC85xx_H__ */
 #endif /* __KERNEL__ */
diff --git a/include/asm-ppc/ocp.h b/include/asm-ppc/ocp.h
index b98db3c..983116f 100644
--- a/include/asm-ppc/ocp.h
+++ b/include/asm-ppc/ocp.h
@@ -189,7 +189,7 @@
 /* Sysfs support */
 #define OCP_SYSFS_ADDTL(type, format, name, field)			\
 static ssize_t								\
-show_##name##_##field(struct device *dev, char *buf)			\
+show_##name##_##field(struct device *dev, struct device_attribute *attr, char *buf)			\
 {									\
 	struct ocp_device *odev = to_ocp_dev(dev);			\
 	type *add = odev->def->additions;				\
@@ -202,10 +202,6 @@
 #include <asm/ibm_ocp.h>
 #endif
 
-#ifdef CONFIG_FSL_OCP
-#include <asm/fsl_ocp.h>
-#endif
-
 #endif				/* CONFIG_PPC_OCP */
 #endif				/* __OCP_H__ */
 #endif				/* __KERNEL__ */
diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
index a38606d..4d4b20c 100644
--- a/include/asm-ppc/pgtable.h
+++ b/include/asm-ppc/pgtable.h
@@ -267,8 +267,6 @@
 #define _PMD_PRESENT_MASK (PAGE_MASK)
 #define _PMD_BAD	(~PAGE_MASK)
 
-#define NUM_TLBCAMS	(16)
-
 #elif defined(CONFIG_8xx)
 /* Definitions for 8xx embedded chips. */
 #define _PAGE_PRESENT	0x0001	/* Page is valid */
diff --git a/include/asm-ppc/ppc_asm.h b/include/asm-ppc/ppc_asm.h
index 13fa8e7..f76221d 100644
--- a/include/asm-ppc/ppc_asm.h
+++ b/include/asm-ppc/ppc_asm.h
@@ -174,6 +174,8 @@
 #define CLR_TOP32(r)
 #endif /* CONFIG_PPC64BRIDGE */
 
+#define RFCI		.long 0x4c000066	/* rfci instruction */
+#define RFDI		.long 0x4c00004e	/* rfdi instruction */
 #define RFMCI		.long 0x4c00004c	/* rfmci instruction */
 
 #ifdef CONFIG_IBM405_ERR77
diff --git a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h
index 24b991c..8ea6245 100644
--- a/include/asm-ppc/ppc_sys.h
+++ b/include/asm-ppc/ppc_sys.h
@@ -27,6 +27,8 @@
 #include <asm/mpc85xx.h>
 #elif defined(CONFIG_PPC_MPC52xx)
 #include <asm/mpc52xx.h>
+#elif defined(CONFIG_MPC10X_BRIDGE)
+#include <asm/mpc10x.h>
 #else
 #error "need definition of ppc_sys_devices"
 #endif
diff --git a/include/asm-ppc/reg.h b/include/asm-ppc/reg.h
index c418aab..88b4222 100644
--- a/include/asm-ppc/reg.h
+++ b/include/asm-ppc/reg.h
@@ -160,6 +160,7 @@
 #define HID0_ICFI	(1<<11)		/* Instr. Cache Flash Invalidate */
 #define HID0_DCI	(1<<10)		/* Data Cache Invalidate */
 #define HID0_SPD	(1<<9)		/* Speculative disable */
+#define HID0_DAPUEN	(1<<8)		/* Debug APU enable */
 #define HID0_SGE	(1<<7)		/* Store Gathering Enable */
 #define HID0_SIED	(1<<7)		/* Serial Instr. Execution [Disable] */
 #define HID0_DFCA	(1<<6)		/* Data Cache Flush Assist */
diff --git a/include/asm-ppc/reg_booke.h b/include/asm-ppc/reg_booke.h
index 45c5e6f..00ad9c7 100644
--- a/include/asm-ppc/reg_booke.h
+++ b/include/asm-ppc/reg_booke.h
@@ -165,6 +165,8 @@
 #define SPRN_MCSRR1	0x23B	/* Machine Check Save and Restore Register 1 */
 #define SPRN_MCSR	0x23C	/* Machine Check Status Register */
 #define SPRN_MCAR	0x23D	/* Machine Check Address Register */
+#define SPRN_DSRR0	0x23E	/* Debug Save and Restore Register 0 */
+#define SPRN_DSRR1	0x23F	/* Debug Save and Restore Register 1 */
 #define SPRN_MAS0	0x270	/* MMU Assist Register 0 */
 #define SPRN_MAS1	0x271	/* MMU Assist Register 1 */
 #define SPRN_MAS2	0x272	/* MMU Assist Register 2 */
@@ -264,6 +266,17 @@
 #define MCSR_BUS_IPERR 	0x00000002UL /* Instruction parity Error */
 #define MCSR_BUS_RPERR 	0x00000001UL /* Read parity Error */
 #endif
+#ifdef CONFIG_E200
+#define MCSR_MCP 	0x80000000UL /* Machine Check Input Pin */
+#define MCSR_CP_PERR 	0x20000000UL /* Cache Push Parity Error */
+#define MCSR_CPERR 	0x10000000UL /* Cache Parity Error */
+#define MCSR_EXCP_ERR 	0x08000000UL /* ISI, ITLB, or Bus Error on 1st insn
+					fetch for an exception handler */
+#define MCSR_BUS_IRERR 	0x00000010UL /* Read Bus Error on instruction fetch*/
+#define MCSR_BUS_DRERR 	0x00000008UL /* Read Bus Error on data load */
+#define MCSR_BUS_WRERR 	0x00000004UL /* Write Bus Error on buffered
+					store or cache line push */
+#endif
 
 /* Bit definitions for the DBSR. */
 /*
@@ -311,6 +324,7 @@
 #define ESR_ST		0x00800000	/* Store Operation */
 #define ESR_DLK		0x00200000	/* Data Cache Locking */
 #define ESR_ILK		0x00100000	/* Instr. Cache Locking */
+#define ESR_PUO		0x00040000	/* Unimplemented Operation exception */
 #define ESR_BO		0x00020000	/* Byte Ordering */
 
 /* Bit definitions related to the DBCR0. */
@@ -387,10 +401,12 @@
 #define ICCR_CACHE	1		/* Cacheable */
 
 /* Bit definitions for L1CSR0. */
+#define L1CSR0_CLFC	0x00000100	/* Cache Lock Bits Flash Clear */
 #define L1CSR0_DCFI	0x00000002	/* Data Cache Flash Invalidate */
+#define L1CSR0_CFI	0x00000002	/* Cache Flash Invalidate */
 #define L1CSR0_DCE	0x00000001	/* Data Cache Enable */
 
-/* Bit definitions for L1CSR0. */
+/* Bit definitions for L1CSR1. */
 #define L1CSR1_ICLFR	0x00000100	/* Instr Cache Lock Bits Flash Reset */
 #define L1CSR1_ICFI	0x00000002	/* Instr Cache Flash Invalidate */
 #define L1CSR1_ICE	0x00000001	/* Instr Cache Enable */
diff --git a/include/asm-ppc/seccomp.h b/include/asm-ppc/seccomp.h
new file mode 100644
index 0000000..666c4da
--- /dev/null
+++ b/include/asm-ppc/seccomp.h
@@ -0,0 +1,10 @@
+#ifndef _ASM_SECCOMP_H
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_read __NR_read
+#define __NR_seccomp_write __NR_write
+#define __NR_seccomp_exit __NR_exit
+#define __NR_seccomp_sigreturn __NR_rt_sigreturn
+
+#endif /* _ASM_SECCOMP_H */
diff --git a/include/asm-ppc/sigcontext.h b/include/asm-ppc/sigcontext.h
index f82dccc..b7a417e 100644
--- a/include/asm-ppc/sigcontext.h
+++ b/include/asm-ppc/sigcontext.h
@@ -2,7 +2,7 @@
 #define _ASM_PPC_SIGCONTEXT_H
 
 #include <asm/ptrace.h>
-
+#include <linux/compiler.h>
 
 struct sigcontext {
 	unsigned long	_unused[4];
diff --git a/include/asm-ppc/smp.h b/include/asm-ppc/smp.h
index ebfb614..17530c2 100644
--- a/include/asm-ppc/smp.h
+++ b/include/asm-ppc/smp.h
@@ -44,7 +44,7 @@
 #define NO_PROC_ID		0xFF            /* No processor magic marker */
 #define PROC_CHANGE_PENALTY	20
 
-#define smp_processor_id() (current_thread_info()->cpu)
+#define raw_smp_processor_id()	(current_thread_info()->cpu)
 
 extern int __cpu_up(unsigned int cpu);
 
diff --git a/include/asm-ppc/thread_info.h b/include/asm-ppc/thread_info.h
index f7f0152..27903db 100644
--- a/include/asm-ppc/thread_info.h
+++ b/include/asm-ppc/thread_info.h
@@ -20,7 +20,8 @@
 	unsigned long		flags;		/* low level flags */
 	unsigned long		local_flags;	/* non-racy flags */
 	int			cpu;		/* cpu we're on */
-	int			preempt_count;
+	int			preempt_count;	/* 0 => preemptable,
+						   <0 => BUG */
 	struct restart_block	restart_block;
 };
 
@@ -77,12 +78,19 @@
 #define TIF_POLLING_NRFLAG	4	/* true if poll_idle() is polling
 					   TIF_NEED_RESCHED */
 #define TIF_MEMDIE		5
+#define TIF_SYSCALL_AUDIT       6       /* syscall auditing active */
+#define TIF_SECCOMP             7      /* secure computing */
+
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+#define _TIF_SYSCALL_AUDIT      (1<<TIF_SYSCALL_AUDIT)
+#define _TIF_SECCOMP            (1<<TIF_SECCOMP)
+
+#define _TIF_SYSCALL_T_OR_A     (_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP)
 
 /*
  * Non racy (local) flags bit numbers
diff --git a/include/asm-ppc/unistd.h b/include/asm-ppc/unistd.h
index cc51e5c..e8b7922 100644
--- a/include/asm-ppc/unistd.h
+++ b/include/asm-ppc/unistd.h
@@ -277,8 +277,10 @@
 #define __NR_request_key	270
 #define __NR_keyctl		271
 #define __NR_waitid		272
+#define __NR_ioprio_set		273
+#define __NR_ioprio_get		274
 
-#define __NR_syscalls		273
+#define __NR_syscalls		275
 
 #define __NR(n)	#n
 
diff --git a/include/asm-ppc64/agp.h b/include/asm-ppc64/agp.h
index be27cfa..ca9e423 100644
--- a/include/asm-ppc64/agp.h
+++ b/include/asm-ppc64/agp.h
@@ -10,4 +10,14 @@
 #define flush_agp_mappings()
 #define flush_agp_cache() mb()
 
+/* Convert a physical address to an address suitable for the GART. */
+#define phys_to_gart(x) (x)
+#define gart_to_phys(x) (x)
+
+/* GATT allocation. Returns/accepts GATT kernel virtual address. */
+#define alloc_gatt_pages(order)		\
+	((char *)__get_free_pages(GFP_KERNEL, (order)))
+#define free_gatt_pages(table, order)	\
+	free_pages((unsigned long)(table), (order))
+
 #endif
diff --git a/include/asm-ppc64/compat.h b/include/asm-ppc64/compat.h
index 09c28d2..12414f5 100644
--- a/include/asm-ppc64/compat.h
+++ b/include/asm-ppc64/compat.h
@@ -26,6 +26,7 @@
 typedef u32		compat_caddr_t;
 typedef __kernel_fsid_t	compat_fsid_t;
 typedef s32		compat_key_t;
+typedef s32		compat_timer_t;
 
 typedef s32		compat_int_t;
 typedef s32		compat_long_t;
diff --git a/include/asm-ppc64/dma.h b/include/asm-ppc64/dma.h
index d693b80..dfd1f69 100644
--- a/include/asm-ppc64/dma.h
+++ b/include/asm-ppc64/dma.h
@@ -27,6 +27,8 @@
 /* Doesn't really apply... */
 #define MAX_DMA_ADDRESS  (~0UL)
 
+#if !defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI)
+
 #define dma_outb	outb
 #define dma_inb		inb
 
@@ -323,4 +325,5 @@
 #else                                                         
 #define isa_dma_bridge_buggy   (0)
 #endif
+#endif	/* !defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI) */
 #endif /* _ASM_DMA_H */
diff --git a/include/asm-ppc64/elf.h b/include/asm-ppc64/elf.h
index 6c42d61..085eedb 100644
--- a/include/asm-ppc64/elf.h
+++ b/include/asm-ppc64/elf.h
@@ -221,9 +221,7 @@
 		set_thread_flag(TIF_ABI_PENDING);		\
 	else							\
 		clear_thread_flag(TIF_ABI_PENDING);		\
-	if (ibcs2)						\
-		set_personality(PER_SVR4);			\
-	else if (current->personality != PER_LINUX32)		\
+	if (personality(current->personality) != PER_LINUX32)	\
 		set_personality(PER_LINUX);			\
 } while (0)
 
diff --git a/include/asm-ppc64/iSeries/HvCall.h b/include/asm-ppc64/iSeries/HvCall.h
index d9a2e74..c3f1947 100644
--- a/include/asm-ppc64/iSeries/HvCall.h
+++ b/include/asm-ppc64/iSeries/HvCall.h
@@ -1,84 +1,36 @@
 /*
  * HvCall.h
  * Copyright (C) 2001  Mike Corrigan 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
  */
-
-//===========================================================================
-//
-//	This file contains the "hypervisor call" interface which is used to
-//	drive the hypervisor from the OS.
-//
-//===========================================================================
+/*
+ * This file contains the "hypervisor call" interface which is used to
+ * drive the hypervisor from the OS.
+ */
 #ifndef _HVCALL_H
 #define _HVCALL_H
 
-//-------------------------------------------------------------------
-// Standard Includes
-//-------------------------------------------------------------------
 #include <asm/iSeries/HvCallSc.h>
 #include <asm/iSeries/HvTypes.h>
 #include <asm/paca.h>
 
-/*
-enum HvCall_ReturnCode
-{
-	HvCall_Good		= 0,
-	HvCall_Partial		= 1,
-	HvCall_NotOwned		= 2,
-	HvCall_NotFreed		= 3,
-	HvCall_UnspecifiedError	= 4
-};
-
-enum HvCall_TypeOfSIT
-{
-	HvCall_ReduceOnly	= 0,
-	HvCall_Unconditional	= 1
-};
-
-enum HvCall_TypeOfYield
-{
-	HvCall_YieldTimed	= 0,	// Yield until specified time
-	HvCall_YieldToActive	= 1,	// Yield until all active procs have run
-	HvCall_YieldToProc	= 2	// Yield until the specified processor has run
-};
-
-enum HvCall_InterruptMasks
-{
-	HvCall_MaskIPI		= 0x00000001,
-	HvCall_MaskLpEvent	= 0x00000002,
-	HvCall_MaskLpProd	= 0x00000004,
-	HvCall_MaskTimeout	= 0x00000008
-};
-
-enum HvCall_VaryOffChunkRc
-{
-	HvCall_VaryOffSucceeded		= 0,
-	HvCall_VaryOffWithdrawn		= 1,
-	HvCall_ChunkInLoadArea		= 2,
-	HvCall_ChunkInHPT		= 3,
-	HvCall_ChunkNotAccessible	= 4,
-	HvCall_ChunkInUse		= 5
-};
-*/
-
 /* Type of yield for HvCallBaseYieldProcessor */
-#define HvCall_YieldTimed 	0	// Yield until specified time (tb)
-#define HvCall_YieldToActive	1	// Yield until all active procs have run
-#define HvCall_YieldToProc	2	// Yield until the specified processor has run
+#define HvCall_YieldTimed	0	/* Yield until specified time (tb) */
+#define HvCall_YieldToActive	1	/* Yield until all active procs have run */
+#define HvCall_YieldToProc	2	/* Yield until the specified processor has run */
 
 /* interrupt masks for setEnabledInterrupts */
 #define HvCall_MaskIPI		0x00000001
@@ -86,7 +38,7 @@
 #define HvCall_MaskLpProd	0x00000004
 #define HvCall_MaskTimeout	0x00000008
 
-/* Log buffer formats                       */
+/* Log buffer formats */
 #define HvCall_LogBuffer_ASCII          0
 #define HvCall_LogBuffer_EBCDIC         1
 
@@ -95,7 +47,7 @@
 #define HvCallBaseGetHwPatch				HvCallBase +  2
 #define HvCallBaseReIplSpAttn				HvCallBase +  3
 #define HvCallBaseSetASR				HvCallBase +  4
-#define HvCallBaseSetASRAndRfi				HvCallBase +  5 
+#define HvCallBaseSetASRAndRfi				HvCallBase +  5
 #define HvCallBaseSetIMR				HvCallBase +  6
 #define HvCallBaseSendIPI				HvCallBase +  7
 #define HvCallBaseTerminateMachine			HvCallBase +  8
@@ -115,91 +67,47 @@
 #define HvCallBaseGetLogBufferCodePage			HvCallBase + 22
 #define HvCallBaseGetLogBufferFormat			HvCallBase + 23
 #define HvCallBaseGetLogBufferLength			HvCallBase + 24
-#define HvCallBaseReadLogBuffer 			HvCallBase + 25
+#define HvCallBaseReadLogBuffer				HvCallBase + 25
 #define HvCallBaseSetLogBufferFormatAndCodePage		HvCallBase + 26
-#define HvCallBaseWriteLogBuffer               		HvCallBase + 27
+#define HvCallBaseWriteLogBuffer			HvCallBase + 27
 #define HvCallBaseRouter28				HvCallBase + 28
 #define HvCallBaseRouter29				HvCallBase + 29
 #define HvCallBaseRouter30				HvCallBase + 30
-#define HvCallBaseSetDebugBus 				HvCallBase + 31
+#define HvCallBaseSetDebugBus				HvCallBase + 31
 
-#define HvCallCcSetDABR  				HvCallCc + 7
+#define HvCallCcSetDABR					HvCallCc + 7
 
-//=====================================================================================
-static inline void		HvCall_setVirtualDecr(void)
+static inline void HvCall_setVirtualDecr(void)
 {
-	/* Ignore any error return codes - most likely means that the target value for the
-	 * LP has been increased and this vary off would bring us below the new target. */
+	/*
+	 * Ignore any error return codes - most likely means that the
+	 * target value for the LP has been increased and this vary off
+	 * would bring us below the new target.
+	 */
 	HvCall0(HvCallBaseSetVirtualDecr);
 }
-//=====================================================================
-static inline void		HvCall_yieldProcessor(unsigned typeOfYield, u64 yieldParm)
+
+static inline void HvCall_yieldProcessor(unsigned typeOfYield, u64 yieldParm)
 {
-	HvCall2( HvCallBaseYieldProcessor, typeOfYield, yieldParm );
-}
-//=====================================================================
-static inline void		HvCall_setEnabledInterrupts(u64 enabledInterrupts)
-{
-	HvCall1(HvCallBaseSetEnabledInterrupts,enabledInterrupts);
+	HvCall2(HvCallBaseYieldProcessor, typeOfYield, yieldParm);
 }
 
-//=====================================================================
-static inline void		HvCall_clearLogBuffer(HvLpIndex lpindex)
+static inline void HvCall_setEnabledInterrupts(u64 enabledInterrupts)
 {
-	HvCall1(HvCallBaseClearLogBuffer,lpindex);
+	HvCall1(HvCallBaseSetEnabledInterrupts, enabledInterrupts);
 }
 
-//=====================================================================
-static inline u32  		HvCall_getLogBufferCodePage(HvLpIndex lpindex)
+static inline void HvCall_setLogBufferFormatAndCodepage(int format,
+		u32 codePage)
 {
-	u32 retVal = HvCall1(HvCallBaseGetLogBufferCodePage,lpindex);
-	return retVal;
+	HvCall2(HvCallBaseSetLogBufferFormatAndCodePage, format, codePage);
 }
 
-//=====================================================================
-static inline int  		HvCall_getLogBufferFormat(HvLpIndex lpindex)
-{
-	int retVal = HvCall1(HvCallBaseGetLogBufferFormat,lpindex);
-	return retVal;
-}
+extern void HvCall_writeLogBuffer(const void *buffer, u64 bufLen);
 
-//=====================================================================
-static inline u32  		HvCall_getLogBufferLength(HvLpIndex lpindex)
+static inline void HvCall_sendIPI(struct paca_struct *targetPaca)
 {
-	u32 retVal = HvCall1(HvCallBaseGetLogBufferLength,lpindex);
-	return retVal;
-}
-
-//=====================================================================
-static inline void  		HvCall_setLogBufferFormatAndCodepage(int format, u32 codePage)
-{
-	HvCall2(HvCallBaseSetLogBufferFormatAndCodePage,format, codePage);
-}
-
-//=====================================================================
-int HvCall_readLogBuffer(HvLpIndex lpindex, void *buffer, u64 bufLen);
-void HvCall_writeLogBuffer(const void *buffer, u64 bufLen);
-
-//=====================================================================
-static inline void		HvCall_sendIPI(struct paca_struct * targetPaca)
-{
-	HvCall1( HvCallBaseSendIPI, targetPaca->paca_index );
-}
-
-//=====================================================================
-static inline void		HvCall_terminateMachineSrc(void)
-{
-	HvCall0( HvCallBaseTerminateMachineSrc );
-}
-
-static inline void HvCall_setDABR(unsigned long val)
-{
-	HvCall1(HvCallCcSetDABR, val);
-}
-
-static inline void HvCall_setDebugBus(unsigned long val)
-{
-	HvCall1(HvCallBaseSetDebugBus, val);
+	HvCall1(HvCallBaseSendIPI, targetPaca->paca_index);
 }
 
 #endif /* _HVCALL_H */
diff --git a/include/asm-ppc64/iSeries/HvCallCfg.h b/include/asm-ppc64/iSeries/HvCallCfg.h
deleted file mode 100644
index 9f40f16..0000000
--- a/include/asm-ppc64/iSeries/HvCallCfg.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * HvCallCfg.h
- * Copyright (C) 2001  Mike Corrigan 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
- */
-
-//=====================================================================================
-//
-//	This file contains the "hypervisor call" interface which is used to
-//	drive the hypervisor from the OS.
-//
-//=====================================================================================
-#ifndef _HVCALLCFG_H
-#define _HVCALLCFG_H
-
-//-------------------------------------------------------------------
-// Standard Includes
-//-------------------------------------------------------------------
-#include <asm/iSeries/HvCallSc.h>
-#include <asm/iSeries/HvTypes.h>
-
-//-------------------------------------------------------------------------------------
-// Constants
-//-------------------------------------------------------------------------------------
-
-enum HvCallCfg_ReqQual
-{
-	HvCallCfg_Cur	= 0,
-	HvCallCfg_Init	= 1,
-	HvCallCfg_Max	= 2,
-	HvCallCfg_Min	= 3
-};
-
-#define HvCallCfgGetLps					HvCallCfg +  0
-#define HvCallCfgGetActiveLpMap				HvCallCfg +  1
-#define HvCallCfgGetLpVrmIndex				HvCallCfg +  2
-#define HvCallCfgGetLpMinSupportedPlicVrmIndex		HvCallCfg +  3
-#define HvCallCfgGetLpMinCompatablePlicVrmIndex		HvCallCfg +  4
-#define HvCallCfgGetLpVrmName				HvCallCfg +  5 
-#define HvCallCfgGetSystemPhysicalProcessors		HvCallCfg +  6
-#define HvCallCfgGetPhysicalProcessors			HvCallCfg +  7
-#define HvCallCfgGetSystemMsChunks			HvCallCfg +  8
-#define HvCallCfgGetMsChunks				HvCallCfg +  9
-#define HvCallCfgGetInteractivePercentage		HvCallCfg + 10
-#define HvCallCfgIsBusDedicated				HvCallCfg + 11
-#define HvCallCfgGetBusOwner				HvCallCfg + 12
-#define HvCallCfgGetBusAllocation			HvCallCfg + 13
-#define HvCallCfgGetBusUnitOwner			HvCallCfg + 14
-#define HvCallCfgGetBusUnitAllocation			HvCallCfg + 15
-#define HvCallCfgGetVirtualBusPool			HvCallCfg + 16
-#define HvCallCfgGetBusUnitInterruptProc		HvCallCfg + 17
-#define HvCallCfgGetConfiguredBusUnitsForIntProc	HvCallCfg + 18
-#define HvCallCfgGetRioSanBusPool			HvCallCfg + 19
-#define HvCallCfgGetSharedPoolIndex			HvCallCfg + 20
-#define HvCallCfgGetSharedProcUnits			HvCallCfg + 21
-#define HvCallCfgGetNumProcsInSharedPool		HvCallCfg + 22
-#define HvCallCfgRouter23				HvCallCfg + 23
-#define HvCallCfgRouter24				HvCallCfg + 24
-#define HvCallCfgRouter25				HvCallCfg + 25
-#define HvCallCfgRouter26				HvCallCfg + 26
-#define HvCallCfgRouter27				HvCallCfg + 27
-#define HvCallCfgGetMinRuntimeMsChunks			HvCallCfg + 28
-#define HvCallCfgSetMinRuntimeMsChunks			HvCallCfg + 29
-#define HvCallCfgGetVirtualLanIndexMap			HvCallCfg + 30
-#define HvCallCfgGetLpExecutionMode			HvCallCfg + 31
-#define HvCallCfgGetHostingLpIndex 			HvCallCfg + 32
-
-//====================================================================
-static inline HvLpIndex	HvCallCfg_getLps(void)
-{
-	HvLpIndex retVal = HvCall0(HvCallCfgGetLps);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
-}
-//====================================================================
-static inline int		HvCallCfg_isBusDedicated(u64 busIndex)
-{
-	int retVal = HvCall1(HvCallCfgIsBusDedicated,busIndex);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
-}
-//====================================================================
-static inline HvLpIndex	HvCallCfg_getBusOwner(u64 busIndex)
-{
-	HvLpIndex retVal = HvCall1(HvCallCfgGetBusOwner,busIndex);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
-}
-//====================================================================
-static inline HvLpIndexMap	HvCallCfg_getBusAllocation(u64 busIndex)
-{
-	HvLpIndexMap retVal = HvCall1(HvCallCfgGetBusAllocation,busIndex);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
-}
-//====================================================================
-static inline HvLpIndexMap	HvCallCfg_getActiveLpMap(void)
-{
-	HvLpIndexMap retVal = HvCall0(HvCallCfgGetActiveLpMap);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
-}
-//====================================================================
-static inline HvLpVirtualLanIndexMap	HvCallCfg_getVirtualLanIndexMap(HvLpIndex lp)
-{
-	// This is a new function in V5R1 so calls to this on older 
-	// hypervisors will return -1
-	u64 retVal = HvCall1(HvCallCfgGetVirtualLanIndexMap, lp);
-	if(retVal == -1)
-		retVal = 0;
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
-}
-//===================================================================
-static inline u64		HvCallCfg_getSystemMsChunks(void)
-{
-	u64 retVal = HvCall0(HvCallCfgGetSystemMsChunks);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
-}
-//===================================================================
-static inline u64		HvCallCfg_getMsChunks(HvLpIndex lp,enum HvCallCfg_ReqQual qual)
-{
-	u64 retVal = HvCall2(HvCallCfgGetMsChunks,lp,qual);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
-}
-//===================================================================
-static inline u64		HvCallCfg_getMinRuntimeMsChunks(HvLpIndex lp)
-{
-	// NOTE: This function was added in v5r1 so older hypervisors will return a -1 value
-	u64 retVal = HvCall1(HvCallCfgGetMinRuntimeMsChunks,lp);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
-}
-//===================================================================
-static inline u64		HvCallCfg_setMinRuntimeMsChunks(u64 chunks)
-{
-	u64 retVal = HvCall1(HvCallCfgSetMinRuntimeMsChunks,chunks);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
-}
-//===================================================================
-static inline u64		HvCallCfg_getSystemPhysicalProcessors(void)
-{
-	u64 retVal = HvCall0(HvCallCfgGetSystemPhysicalProcessors);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
-}
-//===================================================================
-static inline u64		HvCallCfg_getPhysicalProcessors(HvLpIndex lp,enum HvCallCfg_ReqQual qual)
-{
-	u64 retVal = HvCall2(HvCallCfgGetPhysicalProcessors,lp,qual);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
-}
-//===================================================================
-static inline u64		HvCallCfg_getConfiguredBusUnitsForInterruptProc(HvLpIndex lp,
-										u16 hvLogicalProcIndex)
-{
-	u64 retVal = HvCall2(HvCallCfgGetConfiguredBusUnitsForIntProc,lp,hvLogicalProcIndex);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
-
-}
-//==================================================================
-static inline HvLpSharedPoolIndex	HvCallCfg_getSharedPoolIndex(HvLpIndex lp)
-{
-	HvLpSharedPoolIndex retVal =
-		HvCall1(HvCallCfgGetSharedPoolIndex,lp);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
-
-}
-//==================================================================
-static inline u64	HvCallCfg_getSharedProcUnits(HvLpIndex lp,enum HvCallCfg_ReqQual qual)
-{
-	u64 retVal = HvCall2(HvCallCfgGetSharedProcUnits,lp,qual);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
-
-}
-//==================================================================
-static inline u64	HvCallCfg_getNumProcsInSharedPool(HvLpSharedPoolIndex sPI)
-{
-	u16 retVal = HvCall1(HvCallCfgGetNumProcsInSharedPool,sPI);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
-
-}
-//==================================================================
-static inline HvLpIndex	HvCallCfg_getHostingLpIndex(HvLpIndex lp)
-{
-	u64 retVal = HvCall1(HvCallCfgGetHostingLpIndex,lp);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
-
-}
-
-#endif /* _HVCALLCFG_H */
diff --git a/include/asm-ppc64/iSeries/HvCallEvent.h b/include/asm-ppc64/iSeries/HvCallEvent.h
index 191ddce..5d9a327 100644
--- a/include/asm-ppc64/iSeries/HvCallEvent.h
+++ b/include/asm-ppc64/iSeries/HvCallEvent.h
@@ -1,32 +1,28 @@
 /*
  * HvCallEvent.h
  * Copyright (C) 2001  Mike Corrigan 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
  */
-
 /*
- *	This file contains the "hypervisor call" interface which is used to
- *	drive the hypervisor from the OS.
+ * This file contains the "hypervisor call" interface which is used to
+ * drive the hypervisor from the OS.
  */
 #ifndef _HVCALLEVENT_H
 #define _HVCALLEVENT_H
 
-/*
- * Standard Includes
- */
 #include <asm/iSeries/HvCallSc.h>
 #include <asm/iSeries/HvTypes.h>
 #include <asm/abs_addr.h>
@@ -71,7 +67,7 @@
 #define HvCallEventCloseLpEventPath			HvCallEvent +  2
 #define HvCallEventDmaBufList				HvCallEvent +  3
 #define HvCallEventDmaSingle				HvCallEvent +  4
-#define HvCallEventDmaToSp				HvCallEvent +  5 
+#define HvCallEventDmaToSp				HvCallEvent +  5
 #define HvCallEventGetOverflowLpEvents			HvCallEvent +  6
 #define HvCallEventGetSourceLpInstanceId		HvCallEvent +  7
 #define HvCallEventGetTargetLpInstanceId		HvCallEvent +  8
@@ -85,14 +81,12 @@
 
 static inline void HvCallEvent_getOverflowLpEvents(u8 queueIndex)
 {
-	HvCall1(HvCallEventGetOverflowLpEvents,queueIndex);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
+	HvCall1(HvCallEventGetOverflowLpEvents, queueIndex);
 }
 
 static inline void HvCallEvent_setInterLpQueueIndex(u8 queueIndex)
 {
-	HvCall1(HvCallEventSetInterLpQueueIndex,queueIndex);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
+	HvCall1(HvCallEventSetInterLpQueueIndex, queueIndex);
 }
 
 static inline void HvCallEvent_setLpEventStack(u8 queueIndex,
@@ -103,7 +97,6 @@
 	abs_addr = virt_to_abs(eventStackAddr);
 	HvCall3(HvCallEventSetLpEventStack, queueIndex, abs_addr,
 			eventStackSize);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
 }
 
 static inline void HvCallEvent_setLpEventQueueInterruptProc(u8 queueIndex,
@@ -111,22 +104,18 @@
 {
 	HvCall2(HvCallEventSetLpEventQueueInterruptProc, queueIndex,
 			lpLogicalProcIndex);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
 }
 
 static inline HvLpEvent_Rc HvCallEvent_signalLpEvent(struct HvLpEvent *event)
 {
 	u64 abs_addr;
-	HvLpEvent_Rc retVal;
 
 #ifdef DEBUG_SENDEVENT
 	printk("HvCallEvent_signalLpEvent: *event = %016lx\n ",
 			(unsigned long)event);
 #endif
 	abs_addr = virt_to_abs(event);
-	retVal = (HvLpEvent_Rc)HvCall1(HvCallEventSignalLpEvent, abs_addr);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
+	return HvCall1(HvCallEventSignalLpEvent, abs_addr);
 }
 
 static inline HvLpEvent_Rc HvCallEvent_signalLpEventFast(HvLpIndex targetLp,
@@ -136,9 +125,7 @@
 		u64 eventData1, u64 eventData2, u64 eventData3,
 		u64 eventData4, u64 eventData5)
 {
-	HvLpEvent_Rc retVal;
-
-	// Pack the misc bits into a single Dword to pass to PLIC
+	/* Pack the misc bits into a single Dword to pass to PLIC */
 	union {
 		struct HvCallEvent_PackedParms	parms;
 		u64		dword;
@@ -152,67 +139,49 @@
 	packed.parms.xSourceInstId	= sourceInstanceId;
 	packed.parms.xTargetInstId	= targetInstanceId;
 
-	retVal = (HvLpEvent_Rc)HvCall7(HvCallEventSignalLpEventParms,
-			packed.dword, correlationToken, eventData1,eventData2,
-			eventData3,eventData4, eventData5);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
+	return HvCall7(HvCallEventSignalLpEventParms, packed.dword,
+			correlationToken, eventData1, eventData2,
+			eventData3, eventData4, eventData5);
 }
 
 static inline HvLpEvent_Rc HvCallEvent_ackLpEvent(struct HvLpEvent *event)
 {
 	u64 abs_addr;
-	HvLpEvent_Rc retVal;
 
 	abs_addr = virt_to_abs(event);
-	retVal = (HvLpEvent_Rc)HvCall1(HvCallEventAckLpEvent, abs_addr);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
+	return HvCall1(HvCallEventAckLpEvent, abs_addr);
 }
 
 static inline HvLpEvent_Rc HvCallEvent_cancelLpEvent(struct HvLpEvent *event)
 {
 	u64 abs_addr;
-	HvLpEvent_Rc retVal;
 
 	abs_addr = virt_to_abs(event);
-	retVal = (HvLpEvent_Rc)HvCall1(HvCallEventCancelLpEvent, abs_addr);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
+	return HvCall1(HvCallEventCancelLpEvent, abs_addr);
 }
 
 static inline HvLpInstanceId HvCallEvent_getSourceLpInstanceId(
 		HvLpIndex targetLp, HvLpEvent_Type type)
 {
-	HvLpInstanceId retVal;	
-
-	retVal = HvCall2(HvCallEventGetSourceLpInstanceId, targetLp, type);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
+	return HvCall2(HvCallEventGetSourceLpInstanceId, targetLp, type);
 }
 
 static inline HvLpInstanceId HvCallEvent_getTargetLpInstanceId(
 		HvLpIndex targetLp, HvLpEvent_Type type)
 {
-	HvLpInstanceId retVal;	
-
-	retVal = HvCall2(HvCallEventGetTargetLpInstanceId, targetLp, type);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
+	return HvCall2(HvCallEventGetTargetLpInstanceId, targetLp, type);
 }
 
 static inline void HvCallEvent_openLpEventPath(HvLpIndex targetLp,
 		HvLpEvent_Type type)
 {
 	HvCall2(HvCallEventOpenLpEventPath, targetLp, type);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
 }
 
 static inline void HvCallEvent_closeLpEventPath(HvLpIndex targetLp,
 		HvLpEvent_Type type)
 {
 	HvCall2(HvCallEventCloseLpEventPath, targetLp, type);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
 }
 
 static inline HvLpDma_Rc HvCallEvent_dmaBufList(HvLpEvent_Type type,
@@ -224,8 +193,7 @@
 		/* Do these need to be converted to absolute addresses? */
 		u64 localBufList, u64 remoteBufList, u32 transferLength)
 {
-	HvLpDma_Rc retVal;
-	// Pack the misc bits into a single Dword to pass to PLIC
+	/* Pack the misc bits into a single Dword to pass to PLIC */
 	union {
 		struct HvCallEvent_PackedDmaParms	parms;
 		u64		dword;
@@ -241,11 +209,8 @@
 	packed.parms.xLocalInstId	= localInstanceId;
 	packed.parms.xRemoteInstId	= remoteInstanceId;
 
-	retVal = (HvLpDma_Rc)HvCall4(HvCallEventDmaBufList,
-			packed.dword, localBufList, remoteBufList,
-			transferLength);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
+	return HvCall4(HvCallEventDmaBufList, packed.dword, localBufList,
+			remoteBufList, transferLength);
 }
 
 static inline HvLpDma_Rc HvCallEvent_dmaSingle(HvLpEvent_Type type,
@@ -256,8 +221,7 @@
 		HvLpDma_AddressType remoteAddressType,
 		u64 localAddrOrTce, u64 remoteAddrOrTce, u32 transferLength)
 {
-	HvLpDma_Rc retVal;
-	// Pack the misc bits into a single Dword to pass to PLIC
+	/* Pack the misc bits into a single Dword to pass to PLIC */
 	union {
 		struct HvCallEvent_PackedDmaParms	parms;
 		u64		dword;
@@ -273,25 +237,17 @@
 	packed.parms.xLocalInstId	= localInstanceId;
 	packed.parms.xRemoteInstId	= remoteInstanceId;
 
-	retVal = (HvLpDma_Rc)HvCall4(HvCallEventDmaSingle,
-			packed.dword, localAddrOrTce, remoteAddrOrTce,
-			transferLength);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
+	return (HvLpDma_Rc)HvCall4(HvCallEventDmaSingle, packed.dword,
+			localAddrOrTce, remoteAddrOrTce, transferLength);
 }
 
-static inline HvLpDma_Rc HvCallEvent_dmaToSp(void* local, u32 remote,
+static inline HvLpDma_Rc HvCallEvent_dmaToSp(void *local, u32 remote,
 		u32 length, HvLpDma_Direction dir)
 {
 	u64 abs_addr;
-	HvLpDma_Rc retVal;
 
 	abs_addr = virt_to_abs(local);
-	retVal = (HvLpDma_Rc)HvCall4(HvCallEventDmaToSp, abs_addr, remote,
-			length, dir);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
+	return HvCall4(HvCallEventDmaToSp, abs_addr, remote, length, dir);
 }
 
-
 #endif /* _HVCALLEVENT_H */
diff --git a/include/asm-ppc64/iSeries/HvCallHpt.h b/include/asm-ppc64/iSeries/HvCallHpt.h
index da76987..66f3822 100644
--- a/include/asm-ppc64/iSeries/HvCallHpt.h
+++ b/include/asm-ppc64/iSeries/HvCallHpt.h
@@ -1,17 +1,17 @@
 /*
  * HvCallHpt.h
  * Copyright (C) 2001  Mike Corrigan 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
@@ -19,21 +19,15 @@
 #ifndef _HVCALLHPT_H
 #define _HVCALLHPT_H
 
-//============================================================================
-//
-//	This file contains the "hypervisor call" interface which is used to
-//	drive the hypervisor from the OS.
-//
-//============================================================================
+/*
+ * This file contains the "hypervisor call" interface which is used to
+ * drive the hypervisor from the OS.
+ */
 
 #include <asm/iSeries/HvCallSc.h>
 #include <asm/iSeries/HvTypes.h>
 #include <asm/mmu.h>
 
-//-----------------------------------------------------------------------------
-// Constants
-//-----------------------------------------------------------------------------
-
 #define HvCallHptGetHptAddress		HvCallHpt +  0
 #define HvCallHptGetHptPages		HvCallHpt +  1
 #define HvCallHptSetPp			HvCallHpt +  5
@@ -47,81 +41,63 @@
 #define HvCallHptInvalidateSetSwBitsGet HvCallHpt + 18
 
 
-//============================================================================
-static inline u64		HvCallHpt_getHptAddress(void)
+static inline u64 HvCallHpt_getHptAddress(void)
 {
-	u64 retval = HvCall0(HvCallHptGetHptAddress);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retval;
+	return HvCall0(HvCallHptGetHptAddress);
 }
-//============================================================================
-static inline u64		HvCallHpt_getHptPages(void)
-{	
-	u64 retval = HvCall0(HvCallHptGetHptPages);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retval;
-}
-//=============================================================================
-static inline void		HvCallHpt_setPp(u32 hpteIndex, u8 value)
+
+static inline u64 HvCallHpt_getHptPages(void)
 {
-	HvCall2( HvCallHptSetPp, hpteIndex, value );
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
+	return HvCall0(HvCallHptGetHptPages);
 }
-//=============================================================================
-static inline void		HvCallHpt_setSwBits(u32 hpteIndex, u8 bitson, u8 bitsoff )
+
+static inline void HvCallHpt_setPp(u32 hpteIndex, u8 value)
 {
-	HvCall3( HvCallHptSetSwBits, hpteIndex, bitson, bitsoff );
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
+	HvCall2(HvCallHptSetPp, hpteIndex, value);
 }
-//=============================================================================
-static inline void		HvCallHpt_invalidateNoSyncICache(u32 hpteIndex)
-						
+
+static inline void HvCallHpt_setSwBits(u32 hpteIndex, u8 bitson, u8 bitsoff)
 {
-	HvCall1( HvCallHptInvalidateNoSyncICache, hpteIndex );
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
+	HvCall3(HvCallHptSetSwBits, hpteIndex, bitson, bitsoff);
 }
-//=============================================================================
-static inline u64		HvCallHpt_invalidateSetSwBitsGet(u32 hpteIndex, u8 bitson, u8 bitsoff )
-						
+
+static inline void HvCallHpt_invalidateNoSyncICache(u32 hpteIndex)
+{
+	HvCall1(HvCallHptInvalidateNoSyncICache, hpteIndex);
+}
+
+static inline u64 HvCallHpt_invalidateSetSwBitsGet(u32 hpteIndex, u8 bitson,
+		u8 bitsoff)
 {
 	u64 compressedStatus;
-	compressedStatus = HvCall4( HvCallHptInvalidateSetSwBitsGet, hpteIndex, bitson, bitsoff, 1 );
-	HvCall1( HvCallHptInvalidateNoSyncICache, hpteIndex );
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
+
+	compressedStatus = HvCall4(HvCallHptInvalidateSetSwBitsGet,
+			hpteIndex, bitson, bitsoff, 1);
+	HvCall1(HvCallHptInvalidateNoSyncICache, hpteIndex);
 	return compressedStatus;
 }
-//=============================================================================
-static inline u64		HvCallHpt_findValid( HPTE *hpte, u64 vpn )
+
+static inline u64 HvCallHpt_findValid(HPTE *hpte, u64 vpn)
 {
-	u64 retIndex = HvCall3Ret16( HvCallHptFindValid, hpte, vpn, 0, 0 );
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retIndex;
-}
-//=============================================================================
-static inline u64		HvCallHpt_findNextValid( HPTE *hpte, u32 hpteIndex, u8 bitson, u8 bitsoff )
-{
-	u64 retIndex = HvCall3Ret16( HvCallHptFindNextValid, hpte, hpteIndex, bitson, bitsoff );
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retIndex;
-}
-//=============================================================================
-static inline void		HvCallHpt_get( HPTE *hpte, u32 hpteIndex )
-{
-	HvCall2Ret16( HvCallHptGet, hpte, hpteIndex, 0 );
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-}
-//============================================================================
-static inline void		HvCallHpt_addValidate( u32 hpteIndex,
-						       u32 hBit,
-						       HPTE *hpte )
-						
-{
-	HvCall4( HvCallHptAddValidate, hpteIndex,
-		 hBit, (*((u64 *)hpte)), (*(((u64 *)hpte)+1)) );
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
+	return HvCall3Ret16(HvCallHptFindValid, hpte, vpn, 0, 0);
 }
 
+static inline u64 HvCallHpt_findNextValid(HPTE *hpte, u32 hpteIndex,
+		u8 bitson, u8 bitsoff)
+{
+	return HvCall3Ret16(HvCallHptFindNextValid, hpte, hpteIndex,
+			bitson, bitsoff);
+}
 
-//=============================================================================
+static inline void HvCallHpt_get(HPTE *hpte, u32 hpteIndex)
+{
+	HvCall2Ret16(HvCallHptGet, hpte, hpteIndex, 0);
+}
+
+static inline void HvCallHpt_addValidate(u32 hpteIndex, u32 hBit, HPTE *hpte)
+{
+	HvCall4(HvCallHptAddValidate, hpteIndex, hBit, (*((u64 *)hpte)),
+			(*(((u64 *)hpte)+1)));
+}
 
 #endif /* _HVCALLHPT_H */
diff --git a/include/asm-ppc64/iSeries/HvCallPci.h b/include/asm-ppc64/iSeries/HvCallPci.h
index 6887b61..c8d675c 100644
--- a/include/asm-ppc64/iSeries/HvCallPci.h
+++ b/include/asm-ppc64/iSeries/HvCallPci.h
@@ -1,26 +1,26 @@
-/************************************************************************/
-/* Provides the Hypervisor PCI calls for iSeries Linux Parition.        */
-/* Copyright (C) 2001  <Wayne G Holm> <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                                          */
-/************************************************************************/
-/* Change Activity:                                                     */
-/*   Created, Jan 9, 2001                                               */
-/************************************************************************/
+/*
+ * Provides the Hypervisor PCI calls for iSeries Linux Parition.
+ * Copyright (C) 2001  <Wayne G Holm> <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
+ *
+ * Change Activity:
+ *   Created, Jan 9, 2001
+ */
 
 #ifndef _HVCALLPCI_H
 #define _HVCALLPCI_H
@@ -34,8 +34,8 @@
  */
 struct HvCallPci_DsaAddr {
 	u16		busNumber;		/* PHB index? */
-	u8		subBusNumber; 		/* PCI bus number? */
-	u8		deviceId;     		/* device and function? */
+	u8		subBusNumber;		/* PCI bus number? */
+	u8		deviceId;		/* device and function? */
 	u8		barNumber;
 	u8		reserved[3];
 };
@@ -52,34 +52,37 @@
 
 enum HvCallPci_DeviceType {
 	HvCallPci_NodeDevice	= 1,
-	HvCallPci_SpDevice	= 2,	
-	HvCallPci_IopDevice     = 3,	
-	HvCallPci_BridgeDevice	= 4,	
-	HvCallPci_MultiFunctionDevice = 5,	
-	HvCallPci_IoaDevice	= 6	
+	HvCallPci_SpDevice	= 2,
+	HvCallPci_IopDevice     = 3,
+	HvCallPci_BridgeDevice	= 4,
+	HvCallPci_MultiFunctionDevice = 5,
+	HvCallPci_IoaDevice	= 6
 };
 
 
 struct HvCallPci_DeviceInfo {
-	u32	deviceType;		// See DeviceType enum for values
+	u32	deviceType;		/* See DeviceType enum for values */
 };
-    
+
 struct HvCallPci_BusUnitInfo {
-	u32	sizeReturned;		// length of data returned
-	u32	deviceType;		// see DeviceType enum for values
+	u32	sizeReturned;		/* length of data returned */
+	u32	deviceType;		/* see DeviceType enum for values */
 };
 
 struct HvCallPci_BridgeInfo {
-	struct HvCallPci_BusUnitInfo busUnitInfo;  // Generic bus unit info
-	u8		subBusNumber;		// Bus number of secondary bus
-	u8		maxAgents;		// Max idsels on secondary bus
-        u8              maxSubBusNumber;        // Max Sub Bus
-	u8		logicalSlotNumber;	// Logical Slot Number for IOA 
+	struct HvCallPci_BusUnitInfo busUnitInfo;  /* Generic bus unit info */
+	u8		subBusNumber;	/* Bus number of secondary bus */
+	u8		maxAgents;	/* Max idsels on secondary bus */
+        u8              maxSubBusNumber; /* Max Sub Bus */
+	u8		logicalSlotNumber; /* Logical Slot Number for IOA */
 };
-    
 
-//  Maximum BusUnitInfo buffer size.  Provided for clients so they can allocate
-//  a buffer big enough for any type of bus unit.  Increase as needed.
+
+/*
+ * Maximum BusUnitInfo buffer size.  Provided for clients so
+ * they can allocate a buffer big enough for any type of bus
+ * unit.  Increase as needed.
+ */
 enum {HvCallPci_MaxBusUnitInfoSize = 128};
 
 struct HvCallPci_BarParms {
@@ -89,12 +92,12 @@
 	u64		protectStart;
 	u64		protectEnd;
 	u64		relocationOffset;
-	u64		pciAddress;		
+	u64		pciAddress;
 	u64		reserved[3];
-};					
+};
 
 enum HvCallPci_VpdType {
-	HvCallPci_BusVpd		= 1,
+	HvCallPci_BusVpd	= 1,
 	HvCallPci_BusAdapterVpd	= 2
 };
 
@@ -123,15 +126,13 @@
 #define HvCallPciUnmaskInterrupts	HvCallPci + 49
 #define HvCallPciGetBusUnitInfo		HvCallPci + 50
 
-//============================================================================
 static inline u64 HvCallPci_configLoad8(u16 busNumber, u8 subBusNumber,
-					u8 deviceId, u32 offset,
-					u8 *value)
+		u8 deviceId, u32 offset, u8 *value)
 {
 	struct HvCallPci_DsaAddr dsa;
 	struct HvCallPci_LoadReturn retVal;
 
-	*((u64*)&dsa) = 0;				
+	*((u64*)&dsa) = 0;
 
 	dsa.busNumber = busNumber;
 	dsa.subBusNumber = subBusNumber;
@@ -139,21 +140,18 @@
 
 	HvCall3Ret16(HvCallPciConfigLoad8, &retVal, *(u64 *)&dsa, offset, 0);
 
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
 	*value = retVal.value;
 
 	return retVal.rc;
 }
-//============================================================================
+
 static inline u64 HvCallPci_configLoad16(u16 busNumber, u8 subBusNumber,
-					 u8 deviceId, u32 offset,
-					 u16 *value)
+		u8 deviceId, u32 offset, u16 *value)
 {
 	struct HvCallPci_DsaAddr dsa;
 	struct HvCallPci_LoadReturn retVal;
 
-	*((u64*)&dsa) = 0;				
+	*((u64*)&dsa) = 0;
 
 	dsa.busNumber = busNumber;
 	dsa.subBusNumber = subBusNumber;
@@ -161,21 +159,18 @@
 
 	HvCall3Ret16(HvCallPciConfigLoad16, &retVal, *(u64 *)&dsa, offset, 0);
 
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
 	*value = retVal.value;
 
 	return retVal.rc;
 }
-//============================================================================
-static inline u64	HvCallPci_configLoad32(u16 busNumber, u8 subBusNumber,
-					      u8 deviceId, u32 offset,
-					      u32 *value)
+
+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;				
+	*((u64*)&dsa) = 0;
 
 	dsa.busNumber = busNumber;
 	dsa.subBusNumber = subBusNumber;
@@ -183,84 +178,61 @@
 
 	HvCall3Ret16(HvCallPciConfigLoad32, &retVal, *(u64 *)&dsa, offset, 0);
 
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
 	*value = retVal.value;
 
 	return retVal.rc;
 }
-//============================================================================
-static inline u64	HvCallPci_configStore8(u16 busNumber, u8 subBusNumber,
-					      u8 deviceId, u32 offset,
-					      u8  value)
+
+static inline u64 HvCallPci_configStore8(u16 busNumber, u8 subBusNumber,
+		u8 deviceId, u32 offset, u8 value)
 {
 	struct HvCallPci_DsaAddr dsa;
-	u64 retVal;
 
-	*((u64*)&dsa) = 0;				
+	*((u64*)&dsa) = 0;
 
 	dsa.busNumber = busNumber;
 	dsa.subBusNumber = subBusNumber;
 	dsa.deviceId = deviceId;
 
-	retVal = HvCall4(HvCallPciConfigStore8, *(u64 *)&dsa, offset, value, 0);
-
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-	return retVal;
+	return HvCall4(HvCallPciConfigStore8, *(u64 *)&dsa, offset, value, 0);
 }
-//============================================================================
-static inline u64	HvCallPci_configStore16(u16 busNumber, u8 subBusNumber,
-					      u8 deviceId, u32 offset,
-					      u16  value)
+
+static inline u64 HvCallPci_configStore16(u16 busNumber, u8 subBusNumber,
+		u8 deviceId, u32 offset, u16 value)
 {
 	struct HvCallPci_DsaAddr dsa;
-	u64 retVal;
 
-	*((u64*)&dsa) = 0;				
+	*((u64*)&dsa) = 0;
 
 	dsa.busNumber = busNumber;
 	dsa.subBusNumber = subBusNumber;
 	dsa.deviceId = deviceId;
 
-	retVal = HvCall4(HvCallPciConfigStore16, *(u64 *)&dsa, offset, value, 0);
-
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-	return retVal;
+	return HvCall4(HvCallPciConfigStore16, *(u64 *)&dsa, offset, value, 0);
 }
-//============================================================================
-static inline u64	HvCallPci_configStore32(u16 busNumber, u8 subBusNumber,
-					      u8 deviceId, u32 offset,
-					      u32  value)
+
+static inline u64 HvCallPci_configStore32(u16 busNumber, u8 subBusNumber,
+		u8 deviceId, u32 offset, u32 value)
 {
 	struct HvCallPci_DsaAddr dsa;
-	u64 retVal;
 
-	*((u64*)&dsa) = 0;				
+	*((u64*)&dsa) = 0;
 
 	dsa.busNumber = busNumber;
 	dsa.subBusNumber = subBusNumber;
 	dsa.deviceId = deviceId;
 
-	retVal = HvCall4(HvCallPciConfigStore32, *(u64 *)&dsa, offset, value, 0);
-
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-	return retVal;
+	return HvCall4(HvCallPciConfigStore32, *(u64 *)&dsa, offset, value, 0);
 }
-//============================================================================
-static inline u64	HvCallPci_barLoad8(u16	busNumberParm,
-					   u8		subBusParm,
-					   u8		deviceIdParm,
-					   u8		barNumberParm,
-					   u64		offsetParm,
-					   u8*		valueParm)
+
+static inline u64 HvCallPci_barLoad8(u16 busNumberParm, u8 subBusParm,
+		u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+		u8 *valueParm)
 {
 	struct HvCallPci_DsaAddr dsa;
 	struct HvCallPci_LoadReturn retVal;
 
-	*((u64*)&dsa) = 0;				
+	*((u64*)&dsa) = 0;
 
 	dsa.busNumber = busNumberParm;
 	dsa.subBusNumber = subBusParm;
@@ -269,24 +241,19 @@
 
 	HvCall3Ret16(HvCallPciBarLoad8, &retVal, *(u64 *)&dsa, offsetParm, 0);
 
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
 	*valueParm = retVal.value;
 
 	return retVal.rc;
 }
-//============================================================================
-static inline u64	HvCallPci_barLoad16(u16	busNumberParm,
-					   u8		subBusParm,
-					   u8		deviceIdParm,
-					   u8		barNumberParm,
-					   u64		offsetParm,
-					   u16*		valueParm)
+
+static inline u64 HvCallPci_barLoad16(u16 busNumberParm, u8 subBusParm,
+		u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+		u16 *valueParm)
 {
 	struct HvCallPci_DsaAddr dsa;
 	struct HvCallPci_LoadReturn retVal;
 
-	*((u64*)&dsa) = 0;				
+	*((u64*)&dsa) = 0;
 
 	dsa.busNumber = busNumberParm;
 	dsa.subBusNumber = subBusParm;
@@ -295,24 +262,19 @@
 
 	HvCall3Ret16(HvCallPciBarLoad16, &retVal, *(u64 *)&dsa, offsetParm, 0);
 
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
 	*valueParm = retVal.value;
 
 	return retVal.rc;
 }
-//============================================================================
-static inline u64	HvCallPci_barLoad32(u16	busNumberParm,
-					   u8		subBusParm,
-					   u8		deviceIdParm,
-					   u8		barNumberParm,
-					   u64		offsetParm,
-					   u32*		valueParm)
+
+static inline u64 HvCallPci_barLoad32(u16 busNumberParm, u8 subBusParm,
+		u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+		u32 *valueParm)
 {
 	struct HvCallPci_DsaAddr dsa;
 	struct HvCallPci_LoadReturn retVal;
 
-	*((u64*)&dsa) = 0;				
+	*((u64*)&dsa) = 0;
 
 	dsa.busNumber = busNumberParm;
 	dsa.subBusNumber = subBusParm;
@@ -321,24 +283,19 @@
 
 	HvCall3Ret16(HvCallPciBarLoad32, &retVal, *(u64 *)&dsa, offsetParm, 0);
 
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
 	*valueParm = retVal.value;
 
 	return retVal.rc;
 }
-//============================================================================
-static inline u64	HvCallPci_barLoad64(u16	busNumberParm,
-					   u8		subBusParm,
-					   u8		deviceIdParm,
-					   u8		barNumberParm,
-					   u64		offsetParm,
-					   u64*		valueParm)
+
+static inline u64 HvCallPci_barLoad64(u16 busNumberParm, u8 subBusParm,
+		u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+		u64 *valueParm)
 {
 	struct HvCallPci_DsaAddr dsa;
 	struct HvCallPci_LoadReturn retVal;
 
-	*((u64*)&dsa) = 0;				
+	*((u64*)&dsa) = 0;
 
 	dsa.busNumber = busNumberParm;
 	dsa.subBusNumber = subBusParm;
@@ -347,112 +304,81 @@
 
 	HvCall3Ret16(HvCallPciBarLoad64, &retVal, *(u64 *)&dsa, offsetParm, 0);
 
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
 	*valueParm = retVal.value;
 
 	return retVal.rc;
 }
-//============================================================================
-static inline u64	HvCallPci_barStore8(u16	busNumberParm,
-					    u8		subBusParm,
-					    u8		deviceIdParm,
-					    u8		barNumberParm,
-					    u64		offsetParm,
-					    u8		valueParm)
+
+static inline u64 HvCallPci_barStore8(u16 busNumberParm, u8 subBusParm,
+		u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+		u8 valueParm)
 {
 	struct HvCallPci_DsaAddr dsa;
-	u64 retVal;
 
 	*((u64*)&dsa) = 0;
-				
+
 	dsa.busNumber = busNumberParm;
 	dsa.subBusNumber = subBusParm;
 	dsa.deviceId = deviceIdParm;
 	dsa.barNumber = barNumberParm;
 
-	retVal = HvCall4(HvCallPciBarStore8, *(u64 *)&dsa, offsetParm, valueParm, 0);
-
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-	return retVal;
+	return HvCall4(HvCallPciBarStore8, *(u64 *)&dsa, offsetParm,
+			valueParm, 0);
 }
-//============================================================================
-static inline u64	HvCallPci_barStore16(u16	busNumberParm,
-					     u8		subBusParm,
-					     u8		deviceIdParm,
-					     u8		barNumberParm,
-					     u64	offsetParm,
-					     u16	valueParm)
+
+static inline u64 HvCallPci_barStore16(u16 busNumberParm, u8 subBusParm,
+		u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+		u16 valueParm)
 {
 	struct HvCallPci_DsaAddr dsa;
-	u64 retVal;
 
 	*((u64*)&dsa) = 0;
-				
+
 	dsa.busNumber = busNumberParm;
 	dsa.subBusNumber = subBusParm;
 	dsa.deviceId = deviceIdParm;
 	dsa.barNumber = barNumberParm;
 
-	retVal = HvCall4(HvCallPciBarStore16, *(u64 *)&dsa, offsetParm, valueParm, 0);
-
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-	return retVal;
+	return HvCall4(HvCallPciBarStore16, *(u64 *)&dsa, offsetParm,
+			valueParm, 0);
 }
-//============================================================================
-static inline u64	HvCallPci_barStore32(u16	busNumberParm,
-					     u8		subBusParm,
-					     u8		deviceIdParm,
-					     u8		barNumberParm,
-					     u64	offsetParm,
-					     u32	valueParm)
+
+static inline u64 HvCallPci_barStore32(u16 busNumberParm, u8 subBusParm,
+		u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+		u32 valueParm)
 {
 	struct HvCallPci_DsaAddr dsa;
-	u64 retVal;
 
 	*((u64*)&dsa) = 0;
-				
+
 	dsa.busNumber = busNumberParm;
 	dsa.subBusNumber = subBusParm;
 	dsa.deviceId = deviceIdParm;
 	dsa.barNumber = barNumberParm;
 
-	retVal = HvCall4(HvCallPciBarStore32, *(u64 *)&dsa, offsetParm, valueParm, 0);
-
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-	return retVal;
+	return HvCall4(HvCallPciBarStore32, *(u64 *)&dsa, offsetParm,
+			valueParm, 0);
 }
-//============================================================================
-static inline u64	HvCallPci_barStore64(u16	busNumberParm,
-					     u8		subBusParm,
-					     u8		deviceIdParm,
-					     u8		barNumberParm,
-					     u64	offsetParm,
-					     u64	valueParm)
+
+static inline u64 HvCallPci_barStore64(u16 busNumberParm, u8 subBusParm,
+		u8 deviceIdParm, u8 barNumberParm, u64 offsetParm,
+		u64 valueParm)
 {
 	struct HvCallPci_DsaAddr dsa;
-	u64 retVal;
 
 	*((u64*)&dsa) = 0;
-				
+
 	dsa.busNumber = busNumberParm;
 	dsa.subBusNumber = subBusParm;
 	dsa.deviceId = deviceIdParm;
 	dsa.barNumber = barNumberParm;
 
-	retVal = HvCall4(HvCallPciBarStore64, *(u64 *)&dsa, offsetParm, valueParm, 0);
-
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-	return retVal;
+	return HvCall4(HvCallPciBarStore64, *(u64 *)&dsa, offsetParm,
+			valueParm, 0);
 }
-//============================================================================
-static inline u64	HvCallPci_eoi(u16	busNumberParm,
-				      u8	subBusParm,  
-				      u8	deviceIdParm)
+
+static inline u64 HvCallPci_eoi(u16 busNumberParm, u8 subBusParm,
+		u8 deviceIdParm)
 {
 	struct HvCallPci_DsaAddr dsa;
 	struct HvCallPci_LoadReturn retVal;
@@ -465,20 +391,13 @@
 
 	HvCall1Ret16(HvCallPciEoi, &retVal, *(u64*)&dsa);
 
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
 	return retVal.rc;
 }
-//============================================================================
-static inline u64	HvCallPci_getBarParms(u16	busNumberParm,
-					      u8	subBusParm,  
-					      u8	deviceIdParm,
-					      u8	barNumberParm,
-					      u64	parms,
-					      u32	sizeofParms)
+
+static inline u64 HvCallPci_getBarParms(u16 busNumberParm, u8 subBusParm,
+		u8 deviceIdParm, u8 barNumberParm, u64 parms, u32 sizeofParms)
 {
 	struct HvCallPci_DsaAddr dsa;
-	u64 retVal;
 
 	*((u64*)&dsa) = 0;
 
@@ -487,62 +406,13 @@
 	dsa.deviceId = deviceIdParm;
 	dsa.barNumber = barNumberParm;
 
-	retVal = HvCall3(HvCallPciGetBarParms, *(u64*)&dsa, parms, sizeofParms);
-
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-	return retVal;
+	return HvCall3(HvCallPciGetBarParms, *(u64*)&dsa, parms, sizeofParms);
 }
-//============================================================================
-static inline u64	HvCallPci_maskFisr(u16	busNumberParm,
-					   u8	subBusParm,  
-					   u8	deviceIdParm,
-					   u64	fisrMask)
+
+static inline u64 HvCallPci_maskFisr(u16 busNumberParm, u8 subBusParm,
+		u8 deviceIdParm, u64 fisrMask)
 {
 	struct HvCallPci_DsaAddr dsa;
-	u64 retVal;
-
-	*((u64*)&dsa) = 0;		
-
-	dsa.busNumber = busNumberParm;
-	dsa.subBusNumber = subBusParm;
-	dsa.deviceId = deviceIdParm;
-
-	retVal = HvCall2(HvCallPciMaskFisr, *(u64*)&dsa, fisrMask);
-
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-	return retVal;
-}
-//============================================================================
-static inline u64	HvCallPci_unmaskFisr(u16	busNumberParm,
-					     u8		subBusParm,  
-					     u8		deviceIdParm,
-					     u64	fisrMask)
-{
-	struct HvCallPci_DsaAddr dsa;
-	u64 retVal;
-
-	*((u64*)&dsa) = 0;		
-
-	dsa.busNumber = busNumberParm;
-	dsa.subBusNumber = subBusParm;
-	dsa.deviceId = deviceIdParm;
-
-	retVal = HvCall2(HvCallPciUnmaskFisr, *(u64*)&dsa, fisrMask);
-
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-	return retVal;
-}
-//============================================================================
-static inline u64	HvCallPci_setSlotReset(u16		busNumberParm,
-					       u8		subBusParm,
-					       u8		deviceIdParm,
-					       u64		onNotOff)
-{
-	struct HvCallPci_DsaAddr dsa;
-	u64 retVal;
 
 	*((u64*)&dsa) = 0;
 
@@ -550,21 +420,41 @@
 	dsa.subBusNumber = subBusParm;
 	dsa.deviceId = deviceIdParm;
 
-	retVal = HvCall2(HvCallPciSetSlotReset, *(u64*)&dsa, onNotOff);
-
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-	return retVal;
+	return HvCall2(HvCallPciMaskFisr, *(u64*)&dsa, fisrMask);
 }
-//============================================================================
-static inline u64	HvCallPci_getDeviceInfo(u16	busNumberParm,
-						u8	subBusParm,  
-						u8	deviceNumberParm,
-						u64     parms,
-						u32	sizeofParms)
+
+static inline u64 HvCallPci_unmaskFisr(u16 busNumberParm, u8 subBusParm,
+		u8 deviceIdParm, u64 fisrMask)
 {
 	struct HvCallPci_DsaAddr dsa;
-	u64 retVal;
+
+	*((u64*)&dsa) = 0;
+
+	dsa.busNumber = busNumberParm;
+	dsa.subBusNumber = subBusParm;
+	dsa.deviceId = deviceIdParm;
+
+	return HvCall2(HvCallPciUnmaskFisr, *(u64*)&dsa, fisrMask);
+}
+
+static inline u64 HvCallPci_setSlotReset(u16 busNumberParm, u8 subBusParm,
+		u8 deviceIdParm, u64 onNotOff)
+{
+	struct HvCallPci_DsaAddr dsa;
+
+	*((u64*)&dsa) = 0;
+
+	dsa.busNumber = busNumberParm;
+	dsa.subBusNumber = subBusParm;
+	dsa.deviceId = deviceIdParm;
+
+	return HvCall2(HvCallPciSetSlotReset, *(u64*)&dsa, onNotOff);
+}
+
+static inline u64 HvCallPci_getDeviceInfo(u16 busNumberParm, u8 subBusParm,
+		u8 deviceNumberParm, u64 parms, u32 sizeofParms)
+{
+	struct HvCallPci_DsaAddr dsa;
 
 	*((u64*)&dsa) = 0;
 
@@ -572,102 +462,72 @@
 	dsa.subBusNumber = subBusParm;
 	dsa.deviceId = deviceNumberParm << 4;
 
-	retVal = HvCall3(HvCallPciGetDeviceInfo, *(u64*)&dsa, parms, sizeofParms);
-
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-	return retVal;
+	return HvCall3(HvCallPciGetDeviceInfo, *(u64*)&dsa, parms, sizeofParms);
 }
-//============================================================================
-static inline u64	HvCallPci_maskInterrupts(u16	busNumberParm,
-						 u8	subBusParm,  
-						 u8	deviceIdParm,
-						 u64	interruptMask)
+
+static inline u64 HvCallPci_maskInterrupts(u16 busNumberParm, u8 subBusParm,
+		u8 deviceIdParm, u64 interruptMask)
 {
 	struct HvCallPci_DsaAddr dsa;
-	u64 retVal;
 
-	*((u64*)&dsa) = 0;		
+	*((u64*)&dsa) = 0;
 
 	dsa.busNumber = busNumberParm;
 	dsa.subBusNumber = subBusParm;
 	dsa.deviceId = deviceIdParm;
 
-	retVal = HvCall2(HvCallPciMaskInterrupts, *(u64*)&dsa, interruptMask);
-
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-	return retVal;
+	return HvCall2(HvCallPciMaskInterrupts, *(u64*)&dsa, interruptMask);
 }
-//============================================================================
-static inline u64	HvCallPci_unmaskInterrupts(u16	busNumberParm,
-						 u8		subBusParm,  
-						 u8		deviceIdParm,
-						 u64		interruptMask)
+
+static inline u64 HvCallPci_unmaskInterrupts(u16 busNumberParm, u8 subBusParm,
+		u8 deviceIdParm, u64 interruptMask)
 {
 	struct HvCallPci_DsaAddr dsa;
-	u64 retVal;
 
-	*((u64*)&dsa) = 0;		
+	*((u64*)&dsa) = 0;
 
 	dsa.busNumber = busNumberParm;
 	dsa.subBusNumber = subBusParm;
 	dsa.deviceId = deviceIdParm;
 
-	retVal = HvCall2(HvCallPciUnmaskInterrupts, *(u64*)&dsa, interruptMask);
-
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-	return retVal;
+	return HvCall2(HvCallPciUnmaskInterrupts, *(u64*)&dsa, interruptMask);
 }
-//============================================================================
 
-static inline u64	HvCallPci_getBusUnitInfo(u16		busNumberParm,
-						 u8		subBusParm,  
-						 u8		deviceIdParm,
-						 u64            parms,
-						 u32		sizeofParms)
+static inline u64 HvCallPci_getBusUnitInfo(u16 busNumberParm, u8 subBusParm,
+		u8 deviceIdParm, u64 parms, u32 sizeofParms)
 {
 	struct HvCallPci_DsaAddr dsa;
-	u64 retVal;
 
-	*((u64*)&dsa) = 0;		
+	*((u64*)&dsa) = 0;
 
 	dsa.busNumber = busNumberParm;
 	dsa.subBusNumber = subBusParm;
 	dsa.deviceId = deviceIdParm;
 
-	retVal = HvCall3(HvCallPciGetBusUnitInfo, *(u64*)&dsa, parms, sizeofParms);
-
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-
-	return retVal;
+	return HvCall3(HvCallPciGetBusUnitInfo, *(u64*)&dsa, parms,
+			sizeofParms);
 }
-//============================================================================
 
-static inline int HvCallPci_getBusVpd(u16 busNumParm, u64 destParm, u16 sizeParm)
+static inline int HvCallPci_getBusVpd(u16 busNumParm, u64 destParm,
+		u16 sizeParm)
 {
-	int xRetSize;
-	u64 xRc = HvCall4(HvCallPciGetCardVpd, busNumParm, destParm, sizeParm, HvCallPci_BusVpd);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
+	u64 xRc = HvCall4(HvCallPciGetCardVpd, busNumParm, destParm,
+			sizeParm, HvCallPci_BusVpd);
 	if (xRc == -1)
-		xRetSize = -1;
+		return -1;
 	else
-		xRetSize = xRc & 0xFFFF;
-	return xRetSize;
+		return xRc & 0xFFFF;
 }
-//============================================================================
 
-static inline int HvCallPci_getBusAdapterVpd(u16 busNumParm, u64 destParm, u16 sizeParm)
+static inline int HvCallPci_getBusAdapterVpd(u16 busNumParm, u64 destParm,
+		u16 sizeParm)
 {
-	int xRetSize;
-	u64 xRc = HvCall4(HvCallPciGetCardVpd, busNumParm, destParm, sizeParm, HvCallPci_BusAdapterVpd);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
+	u64 xRc = HvCall4(HvCallPciGetCardVpd, busNumParm, destParm,
+			sizeParm, HvCallPci_BusAdapterVpd);
 	if (xRc == -1)
-		xRetSize = -1;
+		return -1;
 	else
-		xRetSize = xRc & 0xFFFF;
-	return xRetSize;
+		return xRc & 0xFFFF;
 }
-//============================================================================
+
 #endif /* _HVCALLPCI_H */
diff --git a/include/asm-ppc64/iSeries/HvCallSc.h b/include/asm-ppc64/iSeries/HvCallSc.h
index eea2584..a62cef3 100644
--- a/include/asm-ppc64/iSeries/HvCallSc.h
+++ b/include/asm-ppc64/iSeries/HvCallSc.h
@@ -1,17 +1,17 @@
 /*
  * HvCallSc.h
  * Copyright (C) 2001  Mike Corrigan 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
@@ -19,7 +19,7 @@
 #ifndef _HVCALLSC_H
 #define _HVCALLSC_H
 
-#include <asm/iSeries/HvTypes.h>
+#include <linux/types.h>
 
 #define HvCallBase		0x8000000000000000ul
 #define HvCallCc		0x8001000000000000ul
@@ -30,22 +30,22 @@
 #define HvCallSm		0x8007000000000000ul
 #define HvCallXm		0x8009000000000000ul
 
-u64 HvCall0( u64 );
-u64 HvCall1( u64, u64 );
-u64 HvCall2( u64, u64, u64 );
-u64 HvCall3( u64, u64, u64, u64 );
-u64 HvCall4( u64, u64, u64, u64, u64 );
-u64 HvCall5( u64, u64, u64, u64, u64, u64 );
-u64 HvCall6( u64, u64, u64, u64, u64, u64, u64 );
-u64 HvCall7( u64, u64, u64, u64, u64, u64, u64, u64 );
+extern u64 HvCall0(u64);
+extern u64 HvCall1(u64, u64);
+extern u64 HvCall2(u64, u64, u64);
+extern u64 HvCall3(u64, u64, u64, u64);
+extern u64 HvCall4(u64, u64, u64, u64, u64);
+extern u64 HvCall5(u64, u64, u64, u64, u64, u64);
+extern u64 HvCall6(u64, u64, u64, u64, u64, u64, u64);
+extern u64 HvCall7(u64, u64, u64, u64, u64, u64, u64, u64);
 
-u64 HvCall0Ret16( u64, void * );
-u64 HvCall1Ret16( u64, void *, u64 );
-u64 HvCall2Ret16( u64, void *, u64, u64 );
-u64 HvCall3Ret16( u64, void *, u64, u64, u64 );
-u64 HvCall4Ret16( u64, void *, u64, u64, u64, u64 );
-u64 HvCall5Ret16( u64, void *, u64, u64, u64, u64, u64 );
-u64 HvCall6Ret16( u64, void *, u64, u64, u64, u64, u64, u64 );
-u64 HvCall7Ret16( u64, void *, u64, u64 ,u64 ,u64 ,u64 ,u64 ,u64 );
+extern u64 HvCall0Ret16(u64, void *);
+extern u64 HvCall1Ret16(u64, void *, u64);
+extern u64 HvCall2Ret16(u64, void *, u64, u64);
+extern u64 HvCall3Ret16(u64, void *, u64, u64, u64);
+extern u64 HvCall4Ret16(u64, void *, u64, u64, u64, u64);
+extern u64 HvCall5Ret16(u64, void *, u64, u64, u64, u64, u64);
+extern u64 HvCall6Ret16(u64, void *, u64, u64, u64, u64, u64, u64);
+extern u64 HvCall7Ret16(u64, void *, u64, u64 ,u64 ,u64 ,u64 ,u64 ,u64);
 
 #endif /* _HVCALLSC_H */
diff --git a/include/asm-ppc64/iSeries/HvCallSm.h b/include/asm-ppc64/iSeries/HvCallSm.h
index 9050c94..8a3dbb0 100644
--- a/include/asm-ppc64/iSeries/HvCallSm.h
+++ b/include/asm-ppc64/iSeries/HvCallSm.h
@@ -1,17 +1,17 @@
 /*
  * HvCallSm.h
  * Copyright (C) 2001  Mike Corrigan 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
@@ -19,34 +19,20 @@
 #ifndef _HVCALLSM_H
 #define _HVCALLSM_H
 
-//============================================================================
-//
-//	This file contains the "hypervisor call" interface which is used to
-//	drive the hypervisor from the OS.
-//
-//============================================================================
+/*
+ * This file contains the "hypervisor call" interface which is used to
+ * drive the hypervisor from the OS.
+ */
 
-//-------------------------------------------------------------------
-// Standard Includes
-//-------------------------------------------------------------------
 #include <asm/iSeries/HvCallSc.h>
 #include <asm/iSeries/HvTypes.h>
 
-//-----------------------------------------------------------------------------
-// Constants
-//-----------------------------------------------------------------------------
-
 #define HvCallSmGet64BitsOfAccessMap	HvCallSm  + 11
 
-
-//============================================================================
-static inline u64		HvCallSm_get64BitsOfAccessMap(
-					HvLpIndex lpIndex, u64 indexIntoBitMap )
+static inline u64 HvCallSm_get64BitsOfAccessMap(HvLpIndex lpIndex,
+		u64 indexIntoBitMap)
 {
-	u64 retval = HvCall2(HvCallSmGet64BitsOfAccessMap, lpIndex,
-			     indexIntoBitMap );
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retval;
+	return HvCall2(HvCallSmGet64BitsOfAccessMap, lpIndex, indexIntoBitMap);
 }
-//============================================================================
+
 #endif /* _HVCALLSM_H */
diff --git a/include/asm-ppc64/iSeries/HvCallXm.h b/include/asm-ppc64/iSeries/HvCallXm.h
index bfb898f..8b9ba60 100644
--- a/include/asm-ppc64/iSeries/HvCallXm.h
+++ b/include/asm-ppc64/iSeries/HvCallXm.h
@@ -1,30 +1,13 @@
-//============================================================================
-//							 Header File Id
-// Name______________:	HvCallXm.H
-//
-// Description_______:
-//
-//	This file contains the "hypervisor call" interface which is used to
-//	drive the hypervisor from SLIC.
-//
-//============================================================================
+/*
+ * This file contains the "hypervisor call" interface which is used to
+ * drive the hypervisor from SLIC.
+ */
 #ifndef _HVCALLXM_H
 #define _HVCALLXM_H
 
-//-------------------------------------------------------------------
-// Forward declarations 
-//-------------------------------------------------------------------
-
-//-------------------------------------------------------------------
-// Standard Includes
-//-------------------------------------------------------------------
 #include <asm/iSeries/HvCallSc.h>
 #include <asm/iSeries/HvTypes.h>
 
-//-----------------------------------------------------------------------------
-// Constants
-//-----------------------------------------------------------------------------
-
 #define HvCallXmGetTceTableParms	HvCallXm +  0
 #define HvCallXmTestBus			HvCallXm +  1
 #define HvCallXmConnectBusUnit		HvCallXm +  2
@@ -33,63 +16,63 @@
 #define HvCallXmSetTce			HvCallXm + 11
 #define HvCallXmSetTces			HvCallXm + 13
 
+/*
+ * Structure passed to HvCallXm_getTceTableParms
+ */
+struct iommu_table_cb {
+	unsigned long	itc_busno;	/* Bus number for this tce table */
+	unsigned long	itc_start;	/* Will be NULL for secondary */
+	unsigned long	itc_totalsize;	/* Size (in pages) of whole table */
+	unsigned long	itc_offset;	/* Index into real tce table of the
+					   start of our section */
+	unsigned long	itc_size;	/* Size (in pages) of our section */
+	unsigned long	itc_index;	/* Index of this tce table */
+	unsigned short	itc_maxtables;	/* Max num of tables for partition */
+	unsigned char	itc_virtbus;	/* Flag to indicate virtual bus */
+	unsigned char	itc_slotno;	/* IOA Tce Slot Index */
+	unsigned char	itc_rsvd[4];
+};
 
-
-//============================================================================
-static inline void		HvCallXm_getTceTableParms(u64 cb)
+static inline void HvCallXm_getTceTableParms(u64 cb)
 {
 	HvCall1(HvCallXmGetTceTableParms, cb);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
 }
-//============================================================================
-static inline u64		HvCallXm_setTce(u64 tceTableToken, u64 tceOffset, u64 tce)
-{	
-	u64 retval = HvCall3(HvCallXmSetTce, tceTableToken, tceOffset, tce );
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retval;
-}
-//============================================================================
-static inline u64		HvCallXm_setTces(u64 tceTableToken, u64 tceOffset, u64 numTces, u64 tce1, u64 tce2, u64 tce3, u64 tce4)
-{	
-	u64 retval = HvCall7(HvCallXmSetTces, tceTableToken, tceOffset, numTces,
-			     tce1, tce2, tce3, tce4 );
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retval;
-}
-//=============================================================================
-static inline u64	HvCallXm_testBus(u16 busNumber)
-{
-	u64 retVal = HvCall1(HvCallXmTestBus, busNumber);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
-}
-//=====================================================================================
-static inline u64	HvCallXm_testBusUnit(u16 busNumber, u8 subBusNumber, u8 deviceId)
-{
-	u64 busUnitNumber = (subBusNumber << 8) | deviceId;
-	u64 retVal = HvCall2(HvCallXmTestBusUnit, busNumber, busUnitNumber);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
-}
-//=====================================================================================
-static inline u64	HvCallXm_connectBusUnit(u16 busNumber, u8 subBusNumber, u8 deviceId,
-						u64 interruptToken)
-{
-	u64 busUnitNumber = (subBusNumber << 8) | deviceId;
-	u64 queueIndex = 0; // HvLpConfig::mapDsaToQueueIndex(HvLpDSA(busNumber, xBoard, xCard));  
 
-	u64 retVal = HvCall5(HvCallXmConnectBusUnit, busNumber, busUnitNumber,
-			     interruptToken, 0, queueIndex);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
-}
-//=====================================================================================
-static inline u64	HvCallXm_loadTod(void)
+static inline u64 HvCallXm_setTce(u64 tceTableToken, u64 tceOffset, u64 tce)
 {
-	u64 retVal = HvCall0(HvCallXmLoadTod);
-	// getPaca()->adjustHmtForNoOfSpinLocksHeld();
-	return retVal;
+	return HvCall3(HvCallXmSetTce, tceTableToken, tceOffset, tce);
 }
-//=====================================================================================
+
+static inline u64 HvCallXm_setTces(u64 tceTableToken, u64 tceOffset,
+		u64 numTces, u64 tce1, u64 tce2, u64 tce3, u64 tce4)
+{
+	return HvCall7(HvCallXmSetTces, tceTableToken, tceOffset, numTces,
+			     tce1, tce2, tce3, tce4);
+}
+
+static inline u64 HvCallXm_testBus(u16 busNumber)
+{
+	return HvCall1(HvCallXmTestBus, busNumber);
+}
+
+static inline u64 HvCallXm_testBusUnit(u16 busNumber, u8 subBusNumber,
+		u8 deviceId)
+{
+	return HvCall2(HvCallXmTestBusUnit, busNumber,
+			(subBusNumber << 8) | deviceId);
+}
+
+static inline u64 HvCallXm_connectBusUnit(u16 busNumber, u8 subBusNumber,
+		u8 deviceId, u64 interruptToken)
+{
+	return HvCall5(HvCallXmConnectBusUnit, busNumber,
+			(subBusNumber << 8) | deviceId, interruptToken, 0,
+			0 /* HvLpConfig::mapDsaToQueueIndex(HvLpDSA(busNumber, xBoard, xCard)) */);
+}
+
+static inline u64 HvCallXm_loadTod(void)
+{
+	return HvCall0(HvCallXmLoadTod);
+}
 
 #endif /* _HVCALLXM_H */
diff --git a/include/asm-ppc64/iSeries/HvLpConfig.h b/include/asm-ppc64/iSeries/HvLpConfig.h
index bdbd70f..f1cf1e7 100644
--- a/include/asm-ppc64/iSeries/HvLpConfig.h
+++ b/include/asm-ppc64/iSeries/HvLpConfig.h
@@ -1,17 +1,17 @@
 /*
  * HvLpConfig.h
  * Copyright (C) 2001  Mike Corrigan 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
@@ -19,262 +19,120 @@
 #ifndef _HVLPCONFIG_H
 #define _HVLPCONFIG_H
 
-//===========================================================================
-//
-//      This file contains the interface to the LPAR configuration data
-//  to determine which resources should be allocated to each partition.
-//
-//===========================================================================
+/*
+ * This file contains the interface to the LPAR configuration data
+ * to determine which resources should be allocated to each partition.
+ */
 
-#include <asm/iSeries/HvCallCfg.h>
+#include <asm/iSeries/HvCallSc.h>
 #include <asm/iSeries/HvTypes.h>
 #include <asm/iSeries/ItLpNaca.h>
-#include <asm/iSeries/LparData.h>
 
-//-------------------------------------------------------------------
-// Constants
-//-------------------------------------------------------------------
+enum {
+	HvCallCfg_Cur	= 0,
+	HvCallCfg_Init	= 1,
+	HvCallCfg_Max	= 2,
+	HvCallCfg_Min	= 3
+};
+
+#define HvCallCfgGetSystemPhysicalProcessors		HvCallCfg +  6
+#define HvCallCfgGetPhysicalProcessors			HvCallCfg +  7
+#define HvCallCfgGetMsChunks				HvCallCfg +  9
+#define HvCallCfgGetSharedPoolIndex			HvCallCfg + 20
+#define HvCallCfgGetSharedProcUnits			HvCallCfg + 21
+#define HvCallCfgGetNumProcsInSharedPool		HvCallCfg + 22
+#define HvCallCfgGetVirtualLanIndexMap			HvCallCfg + 30
+#define HvCallCfgGetHostingLpIndex			HvCallCfg + 32
 
 extern HvLpIndex HvLpConfig_getLpIndex_outline(void);
 
-//===================================================================
 static inline HvLpIndex	HvLpConfig_getLpIndex(void)
 {
 	return itLpNaca.xLpIndex;
 }
-//===================================================================
+
 static inline HvLpIndex	HvLpConfig_getPrimaryLpIndex(void)
 {
 	return itLpNaca.xPrimaryLpIndex;
 }
-//=================================================================
-static inline HvLpIndex	HvLpConfig_getLps(void)
+
+static inline u64 HvLpConfig_getMsChunks(void)
 {
-	return HvCallCfg_getLps();
+	return HvCall2(HvCallCfgGetMsChunks, HvLpConfig_getLpIndex(),
+			HvCallCfg_Cur);
 }
-//=================================================================
-static inline HvLpIndexMap	HvLpConfig_getActiveLpMap(void)
+
+static inline u64 HvLpConfig_getSystemPhysicalProcessors(void)
 {
-	return HvCallCfg_getActiveLpMap();
+	return HvCall0(HvCallCfgGetSystemPhysicalProcessors);
 }
-//=================================================================
-static inline u64		HvLpConfig_getSystemMsMegs(void)
+
+static inline u64 HvLpConfig_getNumProcsInSharedPool(HvLpSharedPoolIndex sPI)
 {
-	return HvCallCfg_getSystemMsChunks() / HVCHUNKSPERMEG;
+	return (u16)HvCall1(HvCallCfgGetNumProcsInSharedPool, sPI);
 }
-//=================================================================
-static inline u64		HvLpConfig_getSystemMsChunks(void)
+
+static inline u64 HvLpConfig_getPhysicalProcessors(void)
 {
-	return HvCallCfg_getSystemMsChunks();
+	return HvCall2(HvCallCfgGetPhysicalProcessors, HvLpConfig_getLpIndex(),
+			HvCallCfg_Cur);
 }
-//=================================================================
-static inline u64		HvLpConfig_getSystemMsPages(void)
+
+static inline HvLpSharedPoolIndex HvLpConfig_getSharedPoolIndex(void)
 {
-	return HvCallCfg_getSystemMsChunks() * HVPAGESPERCHUNK;
+	return HvCall1(HvCallCfgGetSharedPoolIndex, HvLpConfig_getLpIndex());
 }
-//================================================================
-static inline u64		HvLpConfig_getMsMegs(void)
+
+static inline u64 HvLpConfig_getSharedProcUnits(void)
 {
-	return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Cur) / HVCHUNKSPERMEG;
+	return HvCall2(HvCallCfgGetSharedProcUnits, HvLpConfig_getLpIndex(),
+			HvCallCfg_Cur);
 }
-//================================================================
-static inline u64		HvLpConfig_getMsChunks(void)
+
+static inline u64 HvLpConfig_getMaxSharedProcUnits(void)
 {
-	return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Cur);
+	return HvCall2(HvCallCfgGetSharedProcUnits, HvLpConfig_getLpIndex(),
+			HvCallCfg_Max);
 }
-//================================================================
-static inline u64		HvLpConfig_getMsPages(void)
+
+static inline u64 HvLpConfig_getMaxPhysicalProcessors(void)
 {
-	return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Cur) * HVPAGESPERCHUNK;
+	return HvCall2(HvCallCfgGetPhysicalProcessors, HvLpConfig_getLpIndex(),
+			HvCallCfg_Max);
 }
-//================================================================
-static inline u64		HvLpConfig_getMinMsMegs(void)
+
+static inline HvLpVirtualLanIndexMap HvLpConfig_getVirtualLanIndexMapForLp(
+		HvLpIndex lp)
 {
-	return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Min) / HVCHUNKSPERMEG;
+	/*
+	 * This is a new function in V5R1 so calls to this on older
+	 * hypervisors will return -1
+	 */
+	u64 retVal = HvCall1(HvCallCfgGetVirtualLanIndexMap, lp);
+	if (retVal == -1)
+		retVal = 0;
+	return retVal;
 }
-//================================================================
-static inline u64		HvLpConfig_getMinMsChunks(void)
+
+static inline HvLpVirtualLanIndexMap HvLpConfig_getVirtualLanIndexMap(void)
 {
-	return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Min);
+	return HvLpConfig_getVirtualLanIndexMapForLp(
+			HvLpConfig_getLpIndex_outline());
 }
-//================================================================
-static inline u64		HvLpConfig_getMinMsPages(void)
+
+static inline int HvLpConfig_doLpsCommunicateOnVirtualLan(HvLpIndex lp1,
+		HvLpIndex lp2)
 {
-	return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Min) * HVPAGESPERCHUNK;
-}
-//================================================================
-static inline u64		HvLpConfig_getMinRuntimeMsMegs(void)
-{
-	return HvCallCfg_getMinRuntimeMsChunks(HvLpConfig_getLpIndex()) / HVCHUNKSPERMEG;
-}
-//===============================================================
-static inline u64		HvLpConfig_getMinRuntimeMsChunks(void)
-{
-	return HvCallCfg_getMinRuntimeMsChunks(HvLpConfig_getLpIndex());
-}
-//===============================================================
-static inline u64		HvLpConfig_getMinRuntimeMsPages(void)
-{
-	return HvCallCfg_getMinRuntimeMsChunks(HvLpConfig_getLpIndex()) * HVPAGESPERCHUNK;
-}
-//===============================================================
-static inline u64		HvLpConfig_getMaxMsMegs(void)
-{
-	return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Max) / HVCHUNKSPERMEG;
-}
-//===============================================================
-static inline u64		HvLpConfig_getMaxMsChunks(void)
-{
-	return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Max);
-}
-//===============================================================
-static inline u64		HvLpConfig_getMaxMsPages(void)
-{
-	return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Max) * HVPAGESPERCHUNK;
-}
-//===============================================================
-static inline u64		HvLpConfig_getInitMsMegs(void)
-{
-	return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Init) / HVCHUNKSPERMEG;
-}
-//===============================================================
-static inline u64		HvLpConfig_getInitMsChunks(void)
-{
-	return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Init);
-}
-//===============================================================
-static inline u64		HvLpConfig_getInitMsPages(void)
-{    return HvCallCfg_getMsChunks(HvLpConfig_getLpIndex(),HvCallCfg_Init) * HVPAGESPERCHUNK;
-}
-//===============================================================
-static inline u64		HvLpConfig_getSystemPhysicalProcessors(void)
-{
-	return HvCallCfg_getSystemPhysicalProcessors();
-}
-//===============================================================
-static inline u64		HvLpConfig_getSystemLogicalProcessors(void)
-{
-	return HvCallCfg_getSystemPhysicalProcessors() * (/*getPaca()->getSecondaryThreadCount() +*/ 1);
-}
-//===============================================================
-static inline u64		HvLpConfig_getNumProcsInSharedPool(HvLpSharedPoolIndex sPI)
-{
-	return HvCallCfg_getNumProcsInSharedPool(sPI);
-}
-//===============================================================
-static inline u64		HvLpConfig_getPhysicalProcessors(void)
-{
-	return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Cur);
-}
-//===============================================================
-static inline u64		HvLpConfig_getLogicalProcessors(void)
-{
-	return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Cur) * (/*getPaca()->getSecondaryThreadCount() +*/ 1);
-}
-//===============================================================
-static inline HvLpSharedPoolIndex	HvLpConfig_getSharedPoolIndex(void)
-{
-	return HvCallCfg_getSharedPoolIndex(HvLpConfig_getLpIndex());
-}
-//===============================================================
-static inline u64		HvLpConfig_getSharedProcUnits(void)
-{
-	return HvCallCfg_getSharedProcUnits(HvLpConfig_getLpIndex(),HvCallCfg_Cur);
-}
-//===============================================================
-static inline u64		HvLpConfig_getMinSharedProcUnits(void)
-{
-	return HvCallCfg_getSharedProcUnits(HvLpConfig_getLpIndex(),HvCallCfg_Min);
-}
-//===============================================================
-static inline u64		HvLpConfig_getMaxSharedProcUnits(void)
-{
-	return HvCallCfg_getSharedProcUnits(HvLpConfig_getLpIndex(),HvCallCfg_Max);
-}
-//===============================================================
-static inline u64		HvLpConfig_getMinPhysicalProcessors(void)
-{
-	return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Min);
-}
-//===============================================================
-static inline u64		HvLpConfig_getMinLogicalProcessors(void)
-{
-	return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Min) * (/*getPaca()->getSecondaryThreadCount() +*/ 1);
-}
-//===============================================================
-static inline u64		HvLpConfig_getMaxPhysicalProcessors(void)
-{
-	return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Max);
-}
-//===============================================================
-static inline u64		HvLpConfig_getMaxLogicalProcessors(void)
-{
-	return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Max) * (/*getPaca()->getSecondaryThreadCount() +*/ 1);
-}
-//===============================================================
-static inline u64		HvLpConfig_getInitPhysicalProcessors(void)
-{
-	return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Init);
-}
-//===============================================================
-static inline u64		HvLpConfig_getInitLogicalProcessors(void)
-{
-	return HvCallCfg_getPhysicalProcessors(HvLpConfig_getLpIndex(),HvCallCfg_Init) * (/*getPaca()->getSecondaryThreadCount() +*/ 1);
-}
-//================================================================
-static inline HvLpVirtualLanIndexMap	HvLpConfig_getVirtualLanIndexMap(void)
-{
-	return HvCallCfg_getVirtualLanIndexMap(HvLpConfig_getLpIndex_outline());
-}
-//===============================================================
-static inline HvLpVirtualLanIndexMap	HvLpConfig_getVirtualLanIndexMapForLp(HvLpIndex lp)
-{
-	return HvCallCfg_getVirtualLanIndexMap(lp);
-}
-//================================================================
-static inline HvLpIndex	HvLpConfig_getBusOwner(HvBusNumber busNumber)
-{
-	return HvCallCfg_getBusOwner(busNumber);
-}
-//===============================================================
-static inline int		HvLpConfig_isBusDedicated(HvBusNumber busNumber)
-{
-	return HvCallCfg_isBusDedicated(busNumber);
-}
-//================================================================
-static inline HvLpIndexMap	HvLpConfig_getBusAllocation(HvBusNumber busNumber)
-{
-	return HvCallCfg_getBusAllocation(busNumber);
-}
-//================================================================
-// returns the absolute real address of the load area
-static inline u64		HvLpConfig_getLoadAddress(void)
-{
-	return itLpNaca.xLoadAreaAddr & 0x7fffffffffffffff;
-}
-//================================================================
-static inline u64		HvLpConfig_getLoadPages(void)
-{
-	return itLpNaca.xLoadAreaChunks * HVPAGESPERCHUNK;
-}
-//================================================================
-static inline int		HvLpConfig_isBusOwnedByThisLp(HvBusNumber busNumber)
-{
-	HvLpIndex busOwner = HvLpConfig_getBusOwner(busNumber);
-	return (busOwner == HvLpConfig_getLpIndex());
-}
-//================================================================
-static inline int         HvLpConfig_doLpsCommunicateOnVirtualLan(HvLpIndex lp1, HvLpIndex lp2)
-{
-	HvLpVirtualLanIndexMap virtualLanIndexMap1 = HvCallCfg_getVirtualLanIndexMap( lp1 );
-	HvLpVirtualLanIndexMap virtualLanIndexMap2 = HvCallCfg_getVirtualLanIndexMap( lp2 );
+	HvLpVirtualLanIndexMap virtualLanIndexMap1 =
+		HvLpConfig_getVirtualLanIndexMapForLp(lp1);
+	HvLpVirtualLanIndexMap virtualLanIndexMap2 =
+		HvLpConfig_getVirtualLanIndexMapForLp(lp2);
 	return ((virtualLanIndexMap1 & virtualLanIndexMap2) != 0);
 }
-//================================================================
-static inline HvLpIndex		HvLpConfig_getHostingLpIndex(HvLpIndex lp)
+
+static inline HvLpIndex HvLpConfig_getHostingLpIndex(HvLpIndex lp)
 {
-	return HvCallCfg_getHostingLpIndex(lp);
+	return HvCall1(HvCallCfgGetHostingLpIndex, lp);
 }
-//================================================================
 
 #endif /* _HVLPCONFIG_H */
diff --git a/include/asm-ppc64/iSeries/HvLpEvent.h b/include/asm-ppc64/iSeries/HvLpEvent.h
index 30936e43..865000d 100644
--- a/include/asm-ppc64/iSeries/HvLpEvent.h
+++ b/include/asm-ppc64/iSeries/HvLpEvent.h
@@ -1,27 +1,24 @@
 /*
  * HvLpEvent.h
  * Copyright (C) 2001  Mike Corrigan 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
  */
 
-//======================================================================
-//
-//	This file contains the class for HV events in the system.
-//
-//=====================================================================
+/* This file contains the class for HV events in the system. */
+
 #ifndef _HVLPEVENT_H
 #define _HVLPEVENT_H
 
@@ -30,69 +27,70 @@
 #include <asm/iSeries/HvTypes.h>
 #include <asm/iSeries/HvCallEvent.h>
 
-//=====================================================================
-//
-// HvLpEvent is the structure for Lp Event messages passed between
-// partitions through PLIC. 
-//
-//=====================================================================
+/*
+ * HvLpEvent is the structure for Lp Event messages passed between
+ * partitions through PLIC.
+ */
 
-struct HvEventFlags
-{
-	u8	xValid:1;		// Indicates a valid request	x00-x00
-	u8	xRsvd1:4;		// Reserved			...
-	u8	xAckType:1;		// Immediate or deferred	...
-	u8	xAckInd:1;		// Indicates if ACK required	...
-	u8	xFunction:1;		// Interrupt or Acknowledge	...
+struct HvEventFlags {
+	u8	xValid:1;	/* Indicates a valid request	x00-x00 */
+	u8	xRsvd1:4;	/* Reserved			... */
+	u8	xAckType:1;	/* Immediate or deferred	... */
+	u8	xAckInd:1;	/* Indicates if ACK required	... */
+	u8	xFunction:1;	/* Interrupt or Acknowledge	... */
 };
 
 
-struct HvLpEvent
-{
-	struct HvEventFlags xFlags;	// Event flags			x00-x00
-	u8	xType;			// Type of message		x01-x01
-	u16	xSubtype;		// Subtype for event		x02-x03
-	u8	xSourceLp;		// Source LP			x04-x04
-	u8	xTargetLp;		// Target LP			x05-x05
-	u8	xSizeMinus1;		// Size of Derived class - 1	x06-x06
-	u8	xRc;			// RC for Ack flows		x07-x07
-	u16	xSourceInstanceId;	// Source sides instance id	x08-x09
-	u16	xTargetInstanceId;	// Target sides instance id	x0A-x0B
+struct HvLpEvent {
+	struct HvEventFlags xFlags;	/* Event flags		      x00-x00 */
+	u8	xType;			/* Type of message	      x01-x01 */
+	u16	xSubtype;		/* Subtype for event	      x02-x03 */
+	u8	xSourceLp;		/* Source LP		      x04-x04 */
+	u8	xTargetLp;		/* Target LP		      x05-x05 */
+	u8	xSizeMinus1;		/* Size of Derived class - 1  x06-x06 */
+	u8	xRc;			/* RC for Ack flows	      x07-x07 */
+	u16	xSourceInstanceId;	/* Source sides instance id   x08-x09 */
+	u16	xTargetInstanceId;	/* Target sides instance id   x0A-x0B */
 	union {
-		u32	xSubtypeData;	// Data usable by the subtype	x0C-x0F
-		u16	xSubtypeDataShort[2];	// Data as 2 shorts
-		u8	xSubtypeDataChar[4];	// Data as 4 chars
+		u32	xSubtypeData;	/* Data usable by the subtype x0C-x0F */
+		u16	xSubtypeDataShort[2];	/* Data as 2 shorts */
+		u8	xSubtypeDataChar[4];	/* Data as 4 chars */
 	} x;
 
-	u64	xCorrelationToken;	// Unique value for source/type x10-x17
+	u64	xCorrelationToken;	/* Unique value for source/type x10-x17 */
 };
 
-// Lp Event handler function
 typedef void (*LpEventHandler)(struct HvLpEvent *, struct pt_regs *);
 
-// Register a handler for an event type
-//  returns 0 on success
-extern int HvLpEvent_registerHandler( HvLpEvent_Type eventType, LpEventHandler hdlr);
+/* Register a handler for an event type - returns 0 on success */
+extern int HvLpEvent_registerHandler(HvLpEvent_Type eventType,
+		LpEventHandler hdlr);
 
-// Unregister a handler for an event type
-//  This call will sleep until the handler being removed is guaranteed to
-//  be no longer executing on any CPU. Do not call with locks held.
-//
-//  returns 0 on success
-//  Unregister will fail if there are any paths open for the type
-extern int HvLpEvent_unregisterHandler( HvLpEvent_Type eventType );
+/*
+ * Unregister a handler for an event type
+ *
+ * This call will sleep until the handler being removed is guaranteed to
+ * be no longer executing on any CPU. Do not call with locks held.
+ *
+ *  returns 0 on success
+ *  Unregister will fail if there are any paths open for the type
+ */
+extern int HvLpEvent_unregisterHandler(HvLpEvent_Type eventType);
 
-// Open an Lp Event Path for an event type
-//  returns 0 on success
-//  openPath will fail if there is no handler registered for the event type.
-//  The lpIndex specified is the partition index for the target partition
-//  (for VirtualIo, VirtualLan and SessionMgr) other types specify zero) 
-extern int HvLpEvent_openPath( HvLpEvent_Type eventType, HvLpIndex lpIndex );
+/*
+ * Open an Lp Event Path for an event type
+ * returns 0 on success
+ * openPath will fail if there is no handler registered for the event type.
+ * The lpIndex specified is the partition index for the target partition
+ * (for VirtualIo, VirtualLan and SessionMgr) other types specify zero)
+ */
+extern int HvLpEvent_openPath(HvLpEvent_Type eventType, HvLpIndex lpIndex);
 
-
-// Close an Lp Event Path for a type and partition
-//  returns 0 on sucess
-extern int HvLpEvent_closePath( HvLpEvent_Type eventType, HvLpIndex lpIndex );
+/*
+ * Close an Lp Event Path for a type and partition
+ * returns 0 on sucess
+ */
+extern int HvLpEvent_closePath(HvLpEvent_Type eventType, HvLpIndex lpIndex);
 
 #define HvLpEvent_Type_Hypervisor 0
 #define HvLpEvent_Type_MachineFac 1
@@ -141,4 +139,4 @@
 #define HvLpDma_Rc_InvalidAddress 4
 #define HvLpDma_Rc_InvalidLength 5
 
-#endif // _HVLPEVENT_H
+#endif /* _HVLPEVENT_H */
diff --git a/include/asm-ppc64/iSeries/HvReleaseData.h b/include/asm-ppc64/iSeries/HvReleaseData.h
index 183e5e7..01a1f13 100644
--- a/include/asm-ppc64/iSeries/HvReleaseData.h
+++ b/include/asm-ppc64/iSeries/HvReleaseData.h
@@ -1,17 +1,17 @@
 /*
  * HvReleaseData.h
  * Copyright (C) 2001  Mike Corrigan 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
@@ -19,47 +19,45 @@
 #ifndef _HVRELEASEDATA_H
 #define _HVRELEASEDATA_H
 
-//=============================================================================
-//
-//   This control block contains the critical information about the 
-//   release so that it can be changed in the future (ie, the virtual 
-//   address of the OS's NACA).
-//
+/*
+ * This control block contains the critical information about the
+ * release so that it can be changed in the future (ie, the virtual
+ * address of the OS's NACA).
+ */
 #include <asm/types.h>
 #include <asm/naca.h>
 
-//=============================================================================
-//
-//	When we IPL a secondary partition, we will check if if the 
-//	secondary xMinPlicVrmIndex > the primary xVrmIndex.  
-//	If it is then this tells PLIC that this secondary is not 
-//	supported running on this "old" of a level of PLIC.
-//
-//	Likewise, we will compare the primary xMinSlicVrmIndex to 
-//	the secondary xVrmIndex. 
-//	If the primary xMinSlicVrmDelta > secondary xVrmDelta then we 
-//	know that this PLIC does not support running an OS "that old".
-//
-//=============================================================================
+/*
+ * When we IPL a secondary partition, we will check if if the
+ * secondary xMinPlicVrmIndex > the primary xVrmIndex.
+ * If it is then this tells PLIC that this secondary is not
+ * supported running on this "old" of a level of PLIC.
+ *
+ * Likewise, we will compare the primary xMinSlicVrmIndex to
+ * the secondary xVrmIndex.
+ * If the primary xMinSlicVrmDelta > secondary xVrmDelta then we
+ * know that this PLIC does not support running an OS "that old".
+ */
 
-struct	HvReleaseData
-{
-	u32	xDesc;			// Descriptor	"HvRD" ebcdic	x00-x03
-	u16	xSize;			// Size of this control block	x04-x05
-	u16	xVpdAreasPtrOffset;	// Offset in NACA of ItVpdAreas	x06-x07
-	struct  naca_struct * xSlicNacaAddr; // Virt addr of SLIC NACA  x08-x0F
-	u32	xMsNucDataOffset;	// Offset of Linux Mapping Data x10-x13
-	u32	xRsvd1;			// Reserved			x14-x17
-	u16	xTagsMode:1;		// 0 == tags active, 1 == tags inactive
-	u16	xAddressSize:1;		// 0 == 64-bit, 1 == 32-bit
-	u16	xNoSharedProcs:1;	// 0 == shared procs, 1 == no shared
-	u16	xNoHMT:1;		// 0 == allow HMT, 1 == no HMT
-	u16	xRsvd2:12;		// Reserved			x18-x19
-	u16	xVrmIndex;		// VRM Index of OS image	x1A-x1B
-	u16	xMinSupportedPlicVrmIndex;// Min PLIC level  (soft)	x1C-x1D
-	u16	xMinCompatablePlicVrmIndex;// Min PLIC levelP (hard)	x1E-x1F
-	char	xVrmName[12];		// Displayable name  		x20-x2B
-	char	xRsvd3[20];		// Reserved			x2C-x3F
+struct HvReleaseData {
+	u32	xDesc;		/* Descriptor "HvRD" ebcdic	x00-x03 */
+	u16	xSize;		/* Size of this control block	x04-x05 */
+	u16	xVpdAreasPtrOffset; /* Offset in NACA of ItVpdAreas x06-x07 */
+	struct  naca_struct	*xSlicNacaAddr; /* Virt addr of SLIC NACA x08-x0F */
+	u32	xMsNucDataOffset; /* Offset of Linux Mapping Data x10-x13 */
+	u32	xRsvd1;		/* Reserved			x14-x17 */
+	u16	xTagsMode:1;	/* 0 == tags active, 1 == tags inactive */
+	u16	xAddressSize:1;	/* 0 == 64-bit, 1 == 32-bit */
+	u16	xNoSharedProcs:1; /* 0 == shared procs, 1 == no shared */
+	u16	xNoHMT:1;	/* 0 == allow HMT, 1 == no HMT */
+	u16	xRsvd2:12;	/* Reserved			x18-x19 */
+	u16	xVrmIndex;	/* VRM Index of OS image	x1A-x1B */
+	u16	xMinSupportedPlicVrmIndex; /* Min PLIC level  (soft) x1C-x1D */
+	u16	xMinCompatablePlicVrmIndex; /* Min PLIC levelP (hard) x1E-x1F */
+	char	xVrmName[12];	/* Displayable name		x20-x2B */
+	char	xRsvd3[20];	/* Reserved			x2C-x3F */
 };
 
+extern struct HvReleaseData	hvReleaseData;
+
 #endif /* _HVRELEASEDATA_H */
diff --git a/include/asm-ppc64/iSeries/HvTypes.h b/include/asm-ppc64/iSeries/HvTypes.h
index 3ec49c1..b1ef2b4 100644
--- a/include/asm-ppc64/iSeries/HvTypes.h
+++ b/include/asm-ppc64/iSeries/HvTypes.h
@@ -1,17 +1,17 @@
 /*
  * HvTypes.h
  * Copyright (C) 2001  Mike Corrigan 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
@@ -19,74 +19,60 @@
 #ifndef _HVTYPES_H
 #define _HVTYPES_H
 
-//===========================================================================
-//                                                             Header File Id
-// Name______________:  HvTypes.H
-//
-// Description_______:
-//
-//	General typedefs for the hypervisor.
-//
-// Declared Class(es):
-//
-//===========================================================================
+/*
+ * General typedefs for the hypervisor.
+ */
 
 #include <asm/types.h>
 
-//-------------------------------------------------------------------
-// Typedefs
-//-------------------------------------------------------------------
 typedef u8	HvLpIndex;
 typedef u16	HvLpInstanceId;
-typedef u64     HvLpTOD;
-typedef u64     HvLpSystemSerialNum;
-typedef u8      HvLpDeviceSerialNum[12];
-typedef u16     HvLpSanHwSet;
-typedef u16     HvLpBus;
-typedef u16     HvLpBoard;
-typedef u16     HvLpCard;
-typedef u8      HvLpDeviceType[4];
-typedef u8      HvLpDeviceModel[3];
-typedef u64     HvIoToken;
-typedef u8      HvLpName[8];
+typedef u64	HvLpTOD;
+typedef u64	HvLpSystemSerialNum;
+typedef u8	HvLpDeviceSerialNum[12];
+typedef u16	HvLpSanHwSet;
+typedef u16	HvLpBus;
+typedef u16	HvLpBoard;
+typedef u16	HvLpCard;
+typedef u8	HvLpDeviceType[4];
+typedef u8	HvLpDeviceModel[3];
+typedef u64	HvIoToken;
+typedef u8	HvLpName[8];
 typedef u32	HvIoId;
 typedef u64	HvRealMemoryIndex;
-typedef u32     HvLpIndexMap;		// Must hold HvMaxArchitectedLps bits!!!
+typedef u32	HvLpIndexMap;	/* Must hold HVMAXARCHITECTEDLPS bits!!! */
 typedef u16	HvLpVrmIndex;
 typedef u32	HvXmGenerationId;
-typedef u8	HvLpBusPool;			
-typedef u8	HvLpSharedPoolIndex;		
+typedef u8	HvLpBusPool;
+typedef u8	HvLpSharedPoolIndex;
 typedef u16	HvLpSharedProcUnitsX100;
 typedef u8	HvLpVirtualLanIndex;
-typedef u16	HvLpVirtualLanIndexMap;	// Must hold HvMaxArchitectedVirtualLans bits!!!
-typedef u16	HvBusNumber;		// Hypervisor Bus Number
-typedef u8	HvSubBusNumber;		// Hypervisor SubBus Number
-typedef u8	HvAgentId;		// Hypervisor DevFn
+typedef u16	HvLpVirtualLanIndexMap;	/* Must hold HVMAXARCHITECTEDVIRTUALLANS bits!!! */
+typedef u16	HvBusNumber;	/* Hypervisor Bus Number */
+typedef u8	HvSubBusNumber;	/* Hypervisor SubBus Number */
+typedef u8	HvAgentId;	/* Hypervisor DevFn */
 
 
-#define HVMAXARCHITECTEDLPS 32
-#define HVMAXARCHITECTEDVIRTUALLANS 16
-#define HVMAXARCHITECTEDVIRTUALDISKS 32
-#define HVMAXARCHITECTEDVIRTUALCDROMS 8
-#define HVMAXARCHITECTEDVIRTUALTAPES 8
-#define HVCHUNKSIZE 256 * 1024
-#define HVPAGESIZE 4 * 1024
-#define HVLPMINMEGSPRIMARY 256
-#define HVLPMINMEGSSECONDARY 64
-#define HVCHUNKSPERMEG 4
-#define HVPAGESPERMEG 256
-#define HVPAGESPERCHUNK 64
- 
-#define HvMaxArchitectedLps 		((HvLpIndex)HVMAXARCHITECTEDLPS)
-#define HvMaxArchitectedVirtualLans	((HvLpVirtualLanIndex)16)
+#define HVMAXARCHITECTEDLPS		32
+#define HVMAXARCHITECTEDVIRTUALLANS	16
+#define HVMAXARCHITECTEDVIRTUALDISKS	32
+#define HVMAXARCHITECTEDVIRTUALCDROMS	8
+#define HVMAXARCHITECTEDVIRTUALTAPES	8
+#define HVCHUNKSIZE			(256 * 1024)
+#define HVPAGESIZE			(4 * 1024)
+#define HVLPMINMEGSPRIMARY		256
+#define HVLPMINMEGSSECONDARY		64
+#define HVCHUNKSPERMEG			4
+#define HVPAGESPERMEG			256
+#define HVPAGESPERCHUNK			64
+
 #define HvLpIndexInvalid		((HvLpIndex)0xff)
 
-//--------------------------------------------------------------------
-// Enums for the sub-components under PLIC
-// Used in HvCall  and HvPrimaryCall
-//--------------------------------------------------------------------
-enum   HvCallCompIds
-{
+/*
+ * Enums for the sub-components under PLIC
+ * Used in HvCall  and HvPrimaryCall
+ */
+enum {
 	HvCallCompId = 0,
 	HvCallCpuCtlsCompId = 1,
 	HvCallCfgCompId = 2,
@@ -97,18 +83,18 @@
 	HvCallSmCompId = 7,
 	HvCallSpdCompId = 8,
 	HvCallXmCompId = 9,
-	HvCallRioCompId = 10, 
+	HvCallRioCompId = 10,
 	HvCallRsvd3CompId = 11,
 	HvCallRsvd2CompId = 12,
 	HvCallRsvd1CompId = 13,
 	HvCallMaxCompId = 14,
-	HvPrimaryCallCompId = 0,    
+	HvPrimaryCallCompId = 0,
 	HvPrimaryCallCfgCompId = 1,
-	HvPrimaryCallPciCompId = 2,    
+	HvPrimaryCallPciCompId = 2,
 	HvPrimaryCallSmCompId = 3,
 	HvPrimaryCallSpdCompId = 4,
 	HvPrimaryCallXmCompId = 5,
-	HvPrimaryCallRioCompId = 6, 
+	HvPrimaryCallRioCompId = 6,
 	HvPrimaryCallRsvd7CompId = 7,
 	HvPrimaryCallRsvd6CompId = 8,
 	HvPrimaryCallRsvd5CompId = 9,
@@ -116,7 +102,7 @@
 	HvPrimaryCallRsvd3CompId = 11,
 	HvPrimaryCallRsvd2CompId = 12,
 	HvPrimaryCallRsvd1CompId = 13,
-	HvPrimaryCallMaxCompId = HvCallMaxCompId     
+	HvPrimaryCallMaxCompId = HvCallMaxCompId
 };
 
 struct HvLpBufferList {
diff --git a/include/asm-ppc64/iSeries/IoHriMainStore.h b/include/asm-ppc64/iSeries/IoHriMainStore.h
index ff00e86..45ed3ea 100644
--- a/include/asm-ppc64/iSeries/IoHriMainStore.h
+++ b/include/asm-ppc64/iSeries/IoHriMainStore.h
@@ -1,17 +1,17 @@
 /*
  * IoHriMainStore.h
  * Copyright (C) 2001  Mike Corrigan 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
@@ -21,7 +21,7 @@
 #define _IOHRIMAINSTORE_H
 
 /* Main Store Vpd for Condor,iStar,sStar */
-struct IoHriMainStoreSegment4 {    
+struct IoHriMainStoreSegment4 {
 	u8	msArea0Exists:1;
 	u8	msArea1Exists:1;
 	u8	msArea2Exists:1;
@@ -51,7 +51,7 @@
 	u8	msArea1HasRiserVpd:1;
 	u8	msArea2HasRiserVpd:1;
 	u8	msArea3HasRiserVpd:1;
-	u8	reserved5:4;	
+	u8	reserved5:4;
 	u8	reserved6;
 	u16	reserved7;
 
@@ -82,8 +82,8 @@
 };
 
 struct IoHriMainStoreAdrRangeBlock {
-	void *	blockStart      __attribute((packed));
-	void *	blockEnd        __attribute((packed));
+	void	*blockStart      __attribute((packed));
+	void	*blockEnd        __attribute((packed));
 	u32	blockProcChipId __attribute((packed));
 };
 
@@ -102,7 +102,7 @@
 	u32	procNodeId			__attribute((packed));
 
 	u32	numAdrRangeBlocks		__attribute((packed));
-	struct IoHriMainStoreAdrRangeBlock xAdrRangeBlock[MaxAreaAdrRangeBlocks] __attribute((packed));
+	struct IoHriMainStoreAdrRangeBlock xAdrRangeBlock[MaxAreaAdrRangeBlocks]	__attribute((packed));
 
 	struct IoHriMainStoreChipInfo1	chipInfo0	__attribute((packed));
 	struct IoHriMainStoreChipInfo1	chipInfo1	__attribute((packed));
@@ -113,17 +113,17 @@
 	struct IoHriMainStoreChipInfo1	chipInfo6	__attribute((packed));
 	struct IoHriMainStoreChipInfo1	chipInfo7	__attribute((packed));
 
-	void *   msRamAreaArray			__attribute((packed));
+	void	*msRamAreaArray			__attribute((packed));
 	u32	msRamAreaArrayNumEntries	__attribute((packed));
 	u32	msRamAreaArrayEntrySize		__attribute((packed));
 
 	u32	numaDimmExists			__attribute((packed));
 	u32	numaDimmFunctional		__attribute((packed));
-	void *	numaDimmArray			__attribute((packed));
+	void	*numaDimmArray			__attribute((packed));
 	u32	numaDimmArrayNumEntries		__attribute((packed));
 	u32	numaDimmArrayEntrySize		__attribute((packed));
 
-	struct IoHriMainStoreVpdIdData  idData	__attribute((packed));
+	struct IoHriMainStoreVpdIdData idData	__attribute((packed));
 
 	u64	powerData			__attribute((packed));
 	u64	cardAssemblyPartNum		__attribute((packed));
@@ -143,7 +143,7 @@
 };
 
 
-struct IoHriMainStoreSegment5 {    
+struct IoHriMainStoreSegment5 {
 	u16	reserved1;
 	u8	reserved2;
 	u8	msVpdFormat;
@@ -151,17 +151,16 @@
 	u32	totalMainStore;
 	u64	maxConfiguredMsAdr;
 
-	struct IoHriMainStoreArea4*	msAreaArray;
+	struct IoHriMainStoreArea4	*msAreaArray;
 	u32	msAreaArrayNumEntries;
 	u32	msAreaArrayEntrySize;
 
-	u32	msAreaExists;    
+	u32	msAreaExists;
 	u32	msAreaFunctional;
 
 	u64	reserved3;
 };
 
+extern u64	xMsVpd[];
 
-
-#endif // _IOHRIMAINSTORE_H
-
+#endif	/* _IOHRIMAINSTORE_H */
diff --git a/include/asm-ppc64/iSeries/IoHriProcessorVpd.h b/include/asm-ppc64/iSeries/IoHriProcessorVpd.h
index 9654338..73b73d8 100644
--- a/include/asm-ppc64/iSeries/IoHriProcessorVpd.h
+++ b/include/asm-ppc64/iSeries/IoHriProcessorVpd.h
@@ -1,17 +1,17 @@
 /*
  * IoHriProcessorVpd.h
  * Copyright (C) 2001  Mike Corrigan 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
@@ -19,16 +19,12 @@
 #ifndef _IOHRIPROCESSORVPD_H
 #define _IOHRIPROCESSORVPD_H
 
-//===================================================================
-//
-//	This struct maps Processor Vpd that is DMAd to SLIC by CSP 
-//
-
 #include <asm/types.h>
 
-struct IoHriProcessorVpd
-{
-
+/*
+ * This struct maps Processor Vpd that is DMAd to SLIC by CSP
+ */
+struct IoHriProcessorVpd {
 	u8	xFormat;		// VPD format indicator		x00-x00
 	u8	xProcStatus:8;		// Processor State		x01-x01
 	u8	xSecondaryThreadCount;	// Secondary thread cnt		x02-x02
@@ -40,12 +36,12 @@
 	u16	xRsvd2;			// Reserved			x06-x07
 	u32	xHwNodeId;		// Hardware node id		x08-x0B
 	u32	xHwProcId;		// Hardware processor id	x0C-x0F
-	
+
 	u32	xTypeNum;		// Card Type/CCIN number	x10-x13
 	u32	xModelNum;		// Model/Feature number		x14-x17
 	u64	xSerialNum;		// Serial number		x18-x1F
-	char xPartNum[12];		// Book Part or FPU number	x20-x2B
-	char xMfgID[4];			// Manufacturing ID		x2C-x2F
+	char	xPartNum[12];		// Book Part or FPU number	x20-x2B
+	char	xMfgID[4];		// Manufacturing ID		x2C-x2F
 
 	u32	xProcFreq;		// Processor Frequency		x30-x33
 	u32	xTimeBaseFreq;		// Time Base Frequency		x34-x37
@@ -71,7 +67,7 @@
 	u32	xDataL3CacheSizeKB;	// L3 data cache size in KB	x80-x83
 	u32	xDataL3CacheLineSize;	// L3 data cache block size	x84-x87
 	u64	xRsvd6;			// Reserved			x88-x8F
-   
+
 	u64	xFruLabel;		// Card Location Label		x90-x97
 	u8	xSlotsOnCard;		// Slots on card (0=no slots)	x98-x98
 	u8	xPartLocFlag;		// Location flag (0-pluggable 1-imbedded) x99-x99
@@ -79,10 +75,12 @@
 	u8	xSmartCardPortNo;	// Smart card port number	x9C-x9C
 	u8	xRsvd7;			// Reserved			x9D-x9D
 	u16	xFrameIdAndRackUnit;	// Frame ID and rack unit adr	x9E-x9F
-    
+
 	u8	xRsvd8[24];		// Reserved			xA0-xB7
 
-	char xProcSrc[72];		// CSP format SRC		xB8-xFF
+	char	xProcSrc[72];		// CSP format SRC		xB8-xFF
 };
 
+extern struct IoHriProcessorVpd	xIoHriProcessorVpd[];
+
 #endif /* _IOHRIPROCESSORVPD_H */
diff --git a/include/asm-ppc64/iSeries/ItExtVpdPanel.h b/include/asm-ppc64/iSeries/ItExtVpdPanel.h
index dee6b12..4c546a8 100644
--- a/include/asm-ppc64/iSeries/ItExtVpdPanel.h
+++ b/include/asm-ppc64/iSeries/ItExtVpdPanel.h
@@ -1,17 +1,17 @@
 /*
  * ItExtVpdPanel.h
  * Copyright (C) 2002  Dave Boutcher 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
@@ -20,39 +20,33 @@
 #define _ITEXTVPDPANEL_H
 
 /*
- *
- *	This struct maps the panel information 
+ *	This struct maps the panel information
  *
  * Warning:
  *	This data must match the architecture for the panel information
- *
  */
 
-
-/*-------------------------------------------------------------------
- * Standard Includes
- *------------------------------------------------------------------- 
-*/
 #include <asm/types.h>
 
-struct ItExtVpdPanel
-{
-  // Definition of the Extended Vpd On Panel Data Area
-  char                      systemSerial[8];
-  char                      mfgID[4];
-  char                      reserved1[24];
-  char                      machineType[4];
-  char                      systemID[6];
-  char                      somUniqueCnt[4];
-  char                      serialNumberCount;
-  char                      reserved2[7];
-  u16                       bbu3;
-  u16                       bbu2;
-  u16                       bbu1;
-  char                      xLocationLabel[8];
-  u8                        xRsvd1[6];
-  u16                       xFrameId;
-  u8                        xRsvd2[48];
+struct ItExtVpdPanel {
+	/* Definition of the Extended Vpd On Panel Data Area */
+	char	systemSerial[8];
+	char	mfgID[4];
+	char	reserved1[24];
+	char	machineType[4];
+	char	systemID[6];
+	char	somUniqueCnt[4];
+	char	serialNumberCount;
+	char	reserved2[7];
+	u16	bbu3;
+	u16	bbu2;
+	u16	bbu1;
+	char	xLocationLabel[8];
+	u8	xRsvd1[6];
+	u16	xFrameId;
+	u8	xRsvd2[48];
 };
 
-#endif /* _ITEXTVPDPANEL_H  */
+extern struct ItExtVpdPanel	xItExtVpdPanel;
+
+#endif /* _ITEXTVPDPANEL_H */
diff --git a/include/asm-ppc64/iSeries/ItIplParmsReal.h b/include/asm-ppc64/iSeries/ItIplParmsReal.h
index 4d8b430..ae3417d 100644
--- a/include/asm-ppc64/iSeries/ItIplParmsReal.h
+++ b/include/asm-ppc64/iSeries/ItIplParmsReal.h
@@ -1,17 +1,17 @@
 /*
  * ItIplParmsReal.h
  * Copyright (C) 2001  Mike Corrigan 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
@@ -19,58 +19,53 @@
 #ifndef _ITIPLPARMSREAL_H
 #define _ITIPLPARMSREAL_H
 
-//==============================================================================
-//
-//	This struct maps the IPL Parameters DMA'd from the SP.                  
-//
-// Warning:
-//	This data must map in exactly 64 bytes and match the architecture for
-//	the IPL parms
-//
-//=============================================================================
+/*
+ *	This struct maps the IPL Parameters DMA'd from the SP.
+ *
+ * Warning:
+ *	This data must map in exactly 64 bytes and match the architecture for
+ *	the IPL parms
+ */
 
-
-//-------------------------------------------------------------------
-// Standard Includes
-//-------------------------------------------------------------------
 #include <asm/types.h>
 
-struct ItIplParmsReal
-{
-	u8	xFormat;		// Defines format of IplParms		x00-x00
-	u8	xRsvd01:6;		// Reserved				x01-x01
-	u8	xAlternateSearch:1;	// Alternate search indicator		...
-	u8	xUaSupplied:1;		// UA Supplied on programmed IPL	...
-	u8	xLsUaFormat;		// Format byte for UA			x02-x02
-	u8	xRsvd02;		// Reserved				x03-x03
-	u32	xLsUa;			// LS UA				x04-x07
-	u32	xUnusedLsLid;		// First OS LID to load			x08-x0B
-	u16	xLsBusNumber;		// LS Bus Number			x0C-x0D
-	u8	xLsCardAdr;		// LS Card Address			x0E-x0E
-	u8	xLsBoardAdr;		// LS Board Address			x0F-x0F
-	u32	xRsvd03;		// Reserved				x10-x13
-	u8	xSpcnPresent:1;		// SPCN present				x14-x14
-	u8	xCpmPresent:1;		// CPM present				...
-	u8	xRsvd04:6;		// Reserved				...
-	u8	xRsvd05:4;		// Reserved				x15-x15
-	u8	xKeyLock:4;		// Keylock setting			...
-	u8	xRsvd06:6;		// Reserved				x16-x16
-	u8	xIplMode:2;		// Ipl mode (A|B|C|D)			...
-	u8	xHwIplType;		// Fast v slow v slow EC HW IPL		x17-x17
-	u16	xCpmEnabledIpl:1;	// CPM in effect when IPL initiated	x18-x19
-	u16	xPowerOnResetIpl:1;	// Indicate POR condition		...
-	u16	xMainStorePreserved:1;	// Main Storage is preserved		...
-	u16	xRsvd07:13;		// Reserved				...
-	u16	xIplSource:16;		// Ipl source				x1A-x1B
-	u8	xIplReason:8;		// Reason for this IPL			x1C-x1C
-	u8	xRsvd08;		// Reserved				x1D-x1D
-	u16	xRsvd09;		// Reserved				x1E-x1F
-	u16	xSysBoxType;		// System Box Type			x20-x21
-	u16	xSysProcType;		// System Processor Type		x22-x23
-	u32	xRsvd10;		// Reserved				x24-x27
-	u64	xRsvd11;		// Reserved				x28-x2F
-	u64	xRsvd12;		// Reserved				x30-x37
-	u64	xRsvd13;		// Reserved				x38-x3F
+struct ItIplParmsReal {
+	u8	xFormat;		// Defines format of IplParms	x00-x00
+	u8	xRsvd01:6;		// Reserved			x01-x01
+	u8	xAlternateSearch:1;	// Alternate search indicator	...
+	u8	xUaSupplied:1;		// UA Supplied on programmed IPL...
+	u8	xLsUaFormat;		// Format byte for UA		x02-x02
+	u8	xRsvd02;		// Reserved			x03-x03
+	u32	xLsUa;			// LS UA			x04-x07
+	u32	xUnusedLsLid;		// First OS LID to load		x08-x0B
+	u16	xLsBusNumber;		// LS Bus Number		x0C-x0D
+	u8	xLsCardAdr;		// LS Card Address		x0E-x0E
+	u8	xLsBoardAdr;		// LS Board Address		x0F-x0F
+	u32	xRsvd03;		// Reserved			x10-x13
+	u8	xSpcnPresent:1;		// SPCN present			x14-x14
+	u8	xCpmPresent:1;		// CPM present			...
+	u8	xRsvd04:6;		// Reserved			...
+	u8	xRsvd05:4;		// Reserved			x15-x15
+	u8	xKeyLock:4;		// Keylock setting		...
+	u8	xRsvd06:6;		// Reserved			x16-x16
+	u8	xIplMode:2;		// Ipl mode (A|B|C|D)		...
+	u8	xHwIplType;		// Fast v slow v slow EC HW IPL	x17-x17
+	u16	xCpmEnabledIpl:1;	// CPM in effect when IPL initiatedx18-x19
+	u16	xPowerOnResetIpl:1;	// Indicate POR condition	...
+	u16	xMainStorePreserved:1;	// Main Storage is preserved	...
+	u16	xRsvd07:13;		// Reserved			...
+	u16	xIplSource:16;		// Ipl source			x1A-x1B
+	u8	xIplReason:8;		// Reason for this IPL		x1C-x1C
+	u8	xRsvd08;		// Reserved			x1D-x1D
+	u16	xRsvd09;		// Reserved			x1E-x1F
+	u16	xSysBoxType;		// System Box Type		x20-x21
+	u16	xSysProcType;		// System Processor Type	x22-x23
+	u32	xRsvd10;		// Reserved			x24-x27
+	u64	xRsvd11;		// Reserved			x28-x2F
+	u64	xRsvd12;		// Reserved			x30-x37
+	u64	xRsvd13;		// Reserved			x38-x3F
 };
 
+extern struct ItIplParmsReal	xItIplParmsReal;
+
 #endif /* _ITIPLPARMSREAL_H */
diff --git a/include/asm-ppc64/iSeries/ItLpNaca.h b/include/asm-ppc64/iSeries/ItLpNaca.h
index 5baffdd..225d017 100644
--- a/include/asm-ppc64/iSeries/ItLpNaca.h
+++ b/include/asm-ppc64/iSeries/ItLpNaca.h
@@ -1,17 +1,17 @@
 /*
  * ItLpNaca.h
  * Copyright (C) 2001  Mike Corrigan 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
@@ -19,18 +19,15 @@
 #ifndef _ITLPNACA_H
 #define _ITLPNACA_H
 
-//=============================================================================
-//
-//	This control block contains the data that is shared between the
-//	hypervisor (PLIC) and the OS.
-//
-//=============================================================================
+#include <linux/types.h>
 
-struct ItLpNaca
-{
-//=============================================================================
+/*
+ *	This control block contains the data that is shared between the
+ *	hypervisor (PLIC) and the OS.
+ */
+
+struct ItLpNaca {
 // CACHE_LINE_1 0x0000 - 0x007F Contains read-only data
-//=============================================================================
 	u32	xDesc;			// Eye catcher			x00-x03
 	u16	xSize;			// Size of this class		x04-x05
 	u16	xIntHdlrOffset;		// Offset to IntHdlr array	x06-x07
@@ -59,30 +56,25 @@
 	u64	xLoadAreaAddr;		// ER address of load area	x28-x2F
 	u32	xLoadAreaChunks;	// Chunks for the load area	x30-x33
 	u32	xPaseSysCallCRMask;	// Mask used to test CR before  x34-x37
-	// doing an ASR switch on PASE
-	// system call.
-	u64	xSlicSegmentTablePtr;   // Pointer to Slic seg table.   x38-x3f
-	u8	xRsvd1_4[64];		//         			x40-x7F 
-   
-//=============================================================================
+					// doing an ASR switch on PASE
+					// system call.
+	u64	xSlicSegmentTablePtr;	// Pointer to Slic seg table.   x38-x3f
+	u8	xRsvd1_4[64];		//				x40-x7F
+
 // CACHE_LINE_2 0x0080 - 0x00FF Contains local read-write data
-//=============================================================================
 	u8	xRsvd2_0[128];		// Reserved			x00-x7F
 
-//=============================================================================
 // CACHE_LINE_3-6 0x0100 - 0x02FF Contains LP Queue indicators
-// NB: Padding required to keep xInterrruptHdlr at x300 which is required 
+// NB: Padding required to keep xInterrruptHdlr at x300 which is required
 // for v4r4 PLIC.
-//=============================================================================
 	u8	xOldLpQueue[128];	// LP Queue needed for v4r4	100-17F
 	u8	xRsvd3_0[384];		// Reserved			180-2FF
-//=============================================================================
+
 // CACHE_LINE_7-8 0x0300 - 0x03FF Contains the address of the OS interrupt
 //  handlers
-//=============================================================================
 	u64	xInterruptHdlr[32];	// Interrupt handlers		300-x3FF
 };
 
-//=============================================================================
+extern struct ItLpNaca		itLpNaca;
 
 #endif /* _ITLPNACA_H */
diff --git a/include/asm-ppc64/iSeries/ItLpQueue.h b/include/asm-ppc64/iSeries/ItLpQueue.h
index 4f4dde2..393299e 100644
--- a/include/asm-ppc64/iSeries/ItLpQueue.h
+++ b/include/asm-ppc64/iSeries/ItLpQueue.h
@@ -1,17 +1,17 @@
 /*
  * ItLpQueue.h
  * Copyright (C) 2001  Mike Corrigan 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
@@ -19,54 +19,54 @@
 #ifndef _ITLPQUEUE_H
 #define _ITLPQUEUE_H
 
-//=============================================================================
-//
-//	This control block defines the simple LP queue structure that is 
-//	shared between the hypervisor (PLIC) and the OS in order to send 
-//	events to an LP.  
-//    
+/*
+ *	This control block defines the simple LP queue structure that is
+ *	shared between the hypervisor (PLIC) and the OS in order to send
+ *	events to an LP.
+ */
 
 #include <asm/types.h>
 #include <asm/ptrace.h>
 
 struct HvLpEvent;
 
-#define ITMaxLpQueues 8
+#define ITMaxLpQueues	8
 
 #define NotUsed		0	// Queue will not be used by PLIC
 #define DedicatedIo	1	// Queue dedicated to IO processor specified
 #define DedicatedLp	2	// Queue dedicated to LP specified
 #define Shared		3	// Queue shared for both IO and LP
 
-#define LpEventStackSize 4096
-#define LpEventMaxSize   256
-#define LpEventAlign	 64
+#define LpEventStackSize	4096
+#define LpEventMaxSize		256
+#define LpEventAlign		64
 
-struct ItLpQueue
-{
-//
-//  The xSlicCurEventPtr is the pointer to the next event stack entry that will
-//  become valid.  The OS must peek at this entry to determine if it is valid.
-//  PLIC will set the valid indicator as the very last store into that entry.
-//
-//  When the OS has completed processing of the event then it will mark the event
-//  as invalid so that PLIC knows it can store into that event location again.
-//
-// If the event stack fills and there are overflow events, then PLIC will set 
-// the xPlicOverflowIntPending flag in which case the OS will have to fetch the 
-// additional LP events once they have drained the event stack.
-//
-// The first 16-bytes are known by both the OS and PLIC.  The remainder of the
-// cache line is for use by the OS.
-//
-//=============================================================================
+struct ItLpQueue {
+/*
+ * The xSlicCurEventPtr is the pointer to the next event stack entry
+ * that will become valid.  The OS must peek at this entry to determine
+ * if it is valid.  PLIC will set the valid indicator as the very last
+ * store into that entry.
+ *
+ * When the OS has completed processing of the event then it will mark
+ * the event as invalid so that PLIC knows it can store into that event
+ * location again.
+ *
+ * If the event stack fills and there are overflow events, then PLIC
+ * will set the xPlicOverflowIntPending flag in which case the OS will
+ * have to fetch the additional LP events once they have drained the
+ * event stack.
+ *
+ * The first 16-bytes are known by both the OS and PLIC.  The remainder
+ * of the cache line is for use by the OS.
+ */
 	u8	xPlicOverflowIntPending;// 0x00 Overflow events are pending
 	u8	xPlicStatus;		// 0x01 DedicatedIo or DedicatedLp or NotUsed
 	u16	xSlicLogicalProcIndex;	// 0x02 Logical Proc Index for correlation
 	u8	xPlicRsvd[12];		// 0x04
-	char*	xSlicCurEventPtr;	// 0x10
-	char*	xSlicLastValidEventPtr;	// 0x18
-	char*	xSlicEventStackPtr;	// 0x20
+	char	*xSlicCurEventPtr;	// 0x10
+	char	*xSlicLastValidEventPtr; // 0x18
+	char	*xSlicEventStackPtr;	// 0x20
 	u8	xIndex;			// 0x28 unique sequential index.
 	u8	xSlicRsvd[3];		// 0x29-2b
 	u32	xInUseWord;		// 0x2C
@@ -76,17 +76,9 @@
 
 extern struct ItLpQueue xItLpQueue;
 
-extern struct HvLpEvent * ItLpQueue_getNextLpEvent( struct ItLpQueue * );
-extern int ItLpQueue_isLpIntPending( struct ItLpQueue * ); 
-extern unsigned ItLpQueue_process( struct ItLpQueue *, struct pt_regs * );
-extern void ItLpQueue_clearValid( struct HvLpEvent * );
-
-static __inline__ void process_iSeries_events( void )
-{
-	__asm__ __volatile__ (
-	"	li	0,0x5555	\n\
-		sc"
-	: : : "r0", "r3" );	
-}
+extern struct HvLpEvent *ItLpQueue_getNextLpEvent(struct ItLpQueue *);
+extern int ItLpQueue_isLpIntPending(struct ItLpQueue *);
+extern unsigned ItLpQueue_process(struct ItLpQueue *, struct pt_regs *);
+extern void ItLpQueue_clearValid(struct HvLpEvent *);
 
 #endif /* _ITLPQUEUE_H */
diff --git a/include/asm-ppc64/iSeries/ItLpRegSave.h b/include/asm-ppc64/iSeries/ItLpRegSave.h
index dafc4c8..1b3087e 100644
--- a/include/asm-ppc64/iSeries/ItLpRegSave.h
+++ b/include/asm-ppc64/iSeries/ItLpRegSave.h
@@ -1,17 +1,17 @@
 /*
  * ItLpRegSave.h
  * Copyright (C) 2001  Mike Corrigan 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
@@ -19,33 +19,30 @@
 #ifndef _ITLPREGSAVE_H
 #define _ITLPREGSAVE_H
 
-//=====================================================================================
-//
-//	This control block contains the data that is shared between PLIC
-//	and the OS
-//    
-//
+/*
+ * This control block contains the data that is shared between PLIC
+ * and the OS
+ */
 
-struct ItLpRegSave
-{
+struct ItLpRegSave {
 	u32	xDesc;		// Eye catcher  "LpRS" ebcdic	000-003
 	u16	xSize;		// Size of this class		004-005
 	u8	xInUse;         // Area is live                 006-007
-	u8	xRsvd1[9]; 	// Reserved			007-00F
+	u8	xRsvd1[9];	// Reserved			007-00F
 
-	u8      xFixedRegSave[352]; // Fixed Register Save Area 010-16F 
+	u8      xFixedRegSave[352]; // Fixed Register Save Area 010-16F
 	u32	xCTRL;		// Control Register		170-173
-	u32	xDEC;		// Decrementer			174-177    
+	u32	xDEC;		// Decrementer			174-177
 	u32	xFPSCR;		// FP Status and Control Reg	178-17B
 	u32	xPVR;		// Processor Version Number	17C-17F
-    
+
 	u64	xMMCR0;		// Monitor Mode Control Reg 0	180-187
 	u32	xPMC1;		// Perf Monitor Counter 1	188-18B
 	u32	xPMC2;		// Perf Monitor Counter 2	18C-18F
 	u32	xPMC3;		// Perf Monitor Counter 3	190-193
 	u32	xPMC4;		// Perf Monitor Counter 4	194-197
 	u32	xPIR;		// Processor ID Reg		198-19B
-    
+
 	u32	xMMCR1;		// Monitor Mode Control Reg 1	19C-19F
 	u32	xMMCRA;		// Monitor Mode Control Reg A	1A0-1A3
 	u32	xPMC5;		// Perf Monitor Counter 5	1A4-1A7
@@ -57,17 +54,17 @@
 	u32	xRsvd;          // Reserved                     1BC-1BF
 
 	u64	xACCR;		// Address Compare Control Reg	1C0-1C7
-	u64	xIMR;		// Instruction Match Register	1C8-1CF    
-	u64	xSDR1;		// Storage Description Reg 1	1D0-1D7    
+	u64	xIMR;		// Instruction Match Register	1C8-1CF
+	u64	xSDR1;		// Storage Description Reg 1	1D0-1D7
 	u64	xSPRG0;		// Special Purpose Reg General0	1D8-1DF
 	u64	xSPRG1;		// Special Purpose Reg General1	1E0-1E7
 	u64	xSPRG2;		// Special Purpose Reg General2	1E8-1EF
 	u64	xSPRG3;		// Special Purpose Reg General3	1F0-1F7
 	u64	xTB;		// Time Base Register		1F8-1FF
-   
+
 	u64	xFPR[32];	// Floating Point Registers	200-2FF
 
-	u64	xMSR;		// Machine State Register  	300-307
+	u64	xMSR;		// Machine State Register	300-307
 	u64	xNIA;		// Next Instruction Address	308-30F
 
 	u64	xDABR;		// Data Address Breakpoint Reg	310-317
@@ -76,8 +73,8 @@
 	u64	xHID0;		// HW Implementation Dependent0	320-327
 
 	u64	xHID4;		// HW Implementation Dependent4	328-32F
-	u64	xSCOMd;		// SCON Data Reg (SPRG4)       	330-337
-	u64	xSCOMc;		// SCON Command Reg (SPRG5)    	338-33F
+	u64	xSCOMd;		// SCON Data Reg (SPRG4)	330-337
+	u64	xSCOMc;		// SCON Command Reg (SPRG5)	338-33F
 	u64	xSDAR;		// Sample Data Address Register	340-347
 	u64	xSIAR;		// Sample Inst Address Register	348-34F
 
diff --git a/include/asm-ppc64/iSeries/ItSpCommArea.h b/include/asm-ppc64/iSeries/ItSpCommArea.h
index f1b56f9..5535f82 100644
--- a/include/asm-ppc64/iSeries/ItSpCommArea.h
+++ b/include/asm-ppc64/iSeries/ItSpCommArea.h
@@ -1,29 +1,27 @@
 /*
  * ItSpCommArea.h
  * Copyright (C) 2001  Mike Corrigan 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 _ITSPCOMMAREA_H
 #define _ITSPCOMMAREA_H
 
 
-struct SpCommArea
-{
+struct SpCommArea {
 	u32	xDesc;			// Descriptor (only in new formats)	000-003
 	u8	xFormat;		// Format (only in new formats)		004-004
 	u8	xRsvd1[11];		// Reserved				005-00F
diff --git a/include/asm-ppc64/iSeries/ItVpdAreas.h b/include/asm-ppc64/iSeries/ItVpdAreas.h
index d120439..71b3ad2 100644
--- a/include/asm-ppc64/iSeries/ItVpdAreas.h
+++ b/include/asm-ppc64/iSeries/ItVpdAreas.h
@@ -1,17 +1,17 @@
 /*
  * ItVpdAreas.h
  * Copyright (C) 2001  Mike Corrigan 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
@@ -19,78 +19,71 @@
 #ifndef _ITVPDAREAS_H
 #define _ITVPDAREAS_H
 
-//=====================================================================================
-//
-//      This file defines the address and length of all of the VPD area passed to
-//	the OS from PLIC (most of which start from the SP).
-//
+/*
+ * This file defines the address and length of all of the VPD area passed to
+ * the OS from PLIC (most of which start from the SP).
+ */
 
 #include <asm/types.h>
 
-// VPD Entry index is carved in stone - cannot be changed (easily).
-#define ItVpdCecVpd				   0
-#define ItVpdDynamicSpace			   1
-#define ItVpdExtVpd				   2
-#define ItVpdExtVpdOnPanel			   3
-#define ItVpdFirstPaca				   4
-#define ItVpdIoVpd				   5
-#define ItVpdIplParms				   6
-#define ItVpdMsVpd				   7
-#define ItVpdPanelVpd				   8
-#define ItVpdLpNaca				   9
-#define ItVpdBackplaneAndMaybeClockCardVpd        10 
-#define ItVpdRecoveryLogBuffer		          11
-#define ItVpdSpCommArea				  12
-#define ItVpdSpLogBuffer			  13
-#define ItVpdSpLogBufferSave			  14
-#define ItVpdSpCardVpd				  15
-#define ItVpdFirstProcVpd			  16	
-#define ItVpdApModelVpd				  17
-#define ItVpdClockCardVpd			  18
-#define ItVpdBusExtCardVpd			  19
-#define ItVpdProcCapacityVpd			  20
-#define ItVpdInteractiveCapacityVpd		  21
-#define ItVpdFirstSlotLabel			  22
-#define ItVpdFirstLpQueue			  23
-#define ItVpdFirstL3CacheVpd			  24	
-#define ItVpdFirstProcFruVpd			  25
+/* VPD Entry index is carved in stone - cannot be changed (easily). */
+#define ItVpdCecVpd				0
+#define ItVpdDynamicSpace			1
+#define ItVpdExtVpd				2
+#define ItVpdExtVpdOnPanel			3
+#define ItVpdFirstPaca				4
+#define ItVpdIoVpd				5
+#define ItVpdIplParms				6
+#define ItVpdMsVpd				7
+#define ItVpdPanelVpd				8
+#define ItVpdLpNaca				9
+#define ItVpdBackplaneAndMaybeClockCardVpd	10
+#define ItVpdRecoveryLogBuffer			11
+#define ItVpdSpCommArea				12
+#define ItVpdSpLogBuffer			13
+#define ItVpdSpLogBufferSave			14
+#define ItVpdSpCardVpd				15
+#define ItVpdFirstProcVpd			16
+#define ItVpdApModelVpd				17
+#define ItVpdClockCardVpd			18
+#define ItVpdBusExtCardVpd			19
+#define ItVpdProcCapacityVpd			20
+#define ItVpdInteractiveCapacityVpd		21
+#define ItVpdFirstSlotLabel			22
+#define ItVpdFirstLpQueue			23
+#define ItVpdFirstL3CacheVpd			24
+#define ItVpdFirstProcFruVpd			25
 
-#define ItVpdMaxEntries				  26
+#define ItVpdMaxEntries				26
+
+#define ItDmaMaxEntries				10
+
+#define ItVpdAreasMaxSlotLabels			192
 
 
-#define ItDmaMaxEntries				  10
-
-#define ItVpdAreasMaxSlotLabels		 192 
-
-
-struct SlicVpdAdrs {
-	u32	pad1;
-	void *  vpdAddr;
+struct ItVpdAreas {
+	u32	xSlicDesc;		// Descriptor			000-003
+	u16	xSlicSize;		// Size of this control block	004-005
+	u16	xPlicAdjustVpdLens:1;	// Flag to indicate new interface006-007
+	u16	xRsvd1:15;		// Reserved bits		...
+	u16	xSlicVpdEntries;	// Number of VPD entries	008-009
+	u16	xSlicDmaEntries;	// Number of DMA entries	00A-00B
+	u16	xSlicMaxLogicalProcs;	// Maximum logical processors	00C-00D
+	u16	xSlicMaxPhysicalProcs;	// Maximum physical processors	00E-00F
+	u16	xSlicDmaToksOffset;	// Offset into this of array	010-011
+	u16	xSlicVpdAdrsOffset;	// Offset into this of array	012-013
+	u16	xSlicDmaLensOffset;	// Offset into this of array	014-015
+	u16	xSlicVpdLensOffset;	// Offset into this of array	016-017
+	u16	xSlicMaxSlotLabels;	// Maximum number of slot labels018-019
+	u16	xSlicMaxLpQueues;	// Maximum number of LP Queues	01A-01B
+	u8	xRsvd2[4];		// Reserved			01C-01F
+	u64	xRsvd3[12];		// Reserved			020-07F
+	u32	xPlicDmaLens[ItDmaMaxEntries];// Array of DMA lengths	080-0A7
+	u32	xPlicDmaToks[ItDmaMaxEntries];// Array of DMA tokens	0A8-0CF
+	u32	xSlicVpdLens[ItVpdMaxEntries];// Array of VPD lengths	0D0-12F
+	void	*xSlicVpdAdrs[ItVpdMaxEntries];// Array of VPD buffers	130-1EF
 };
 
-
-struct	ItVpdAreas
-{
-	u32	xSlicDesc;		// Descriptor				000-003
-	u16	xSlicSize;		// Size of this control block		004-005
-	u16	xPlicAdjustVpdLens:1;	// Flag to indicate new interface 	006-007
-	u16	xRsvd1:15;		// Reserved bits			...
-	u16	xSlicVpdEntries;	// Number of VPD entries		008-009
-	u16	xSlicDmaEntries;	// Number of DMA entries		00A-00B
-	u16	xSlicMaxLogicalProcs;	// Maximum logical processors		00C-00D
-	u16	xSlicMaxPhysicalProcs;	// Maximum physical processors		00E-00F
-	u16	xSlicDmaToksOffset;	// Offset into this of array		010-011
-	u16	xSlicVpdAdrsOffset;	// Offset into this of array		012-013
-	u16	xSlicDmaLensOffset;	// Offset into this of array		014-015
-	u16	xSlicVpdLensOffset;	// Offset into this of array		016-017
-	u16	xSlicMaxSlotLabels;	// Maximum number of slot labels	018-019
-	u16	xSlicMaxLpQueues;	// Maximum number of LP Queues		01A-01B
-	u8	xRsvd2[4];		// Reserved				01C-01F
-	u64	xRsvd3[12];		// Reserved				020-07F
-	u32	xPlicDmaLens[ItDmaMaxEntries];// Array of DMA lengths		080-0A7
-	u32	xPlicDmaToks[ItDmaMaxEntries];// Array of DMA tokens		0A8-0CF
-	u32	xSlicVpdLens[ItVpdMaxEntries];// Array of VPD lengths		0D0-12F
-	void * xSlicVpdAdrs[ItVpdMaxEntries];// Array of VPD buffers	130-1EF
-};
+extern struct ItVpdAreas	itVpdAreas;
 
 #endif /* _ITVPDAREAS_H */
diff --git a/include/asm-ppc64/iSeries/LparData.h b/include/asm-ppc64/iSeries/LparData.h
deleted file mode 100644
index e54f3b6..0000000
--- a/include/asm-ppc64/iSeries/LparData.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * LparData.h
- * Copyright (C) 2001  Mike Corrigan 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 _LPARDATA_H
-#define _LPARDATA_H
-
-#include <asm/types.h>
-#include <asm/page.h>
-#include <asm/abs_addr.h>
-
-#include <asm/iSeries/ItLpNaca.h>
-#include <asm/iSeries/ItLpRegSave.h>
-#include <asm/iSeries/HvReleaseData.h>
-#include <asm/iSeries/LparMap.h>
-#include <asm/iSeries/ItVpdAreas.h>
-#include <asm/iSeries/ItIplParmsReal.h>
-#include <asm/iSeries/ItExtVpdPanel.h>
-#include <asm/iSeries/ItLpQueue.h>
-#include <asm/iSeries/IoHriProcessorVpd.h>
-
-extern struct LparMap	xLparMap;
-extern struct HvReleaseData hvReleaseData;
-extern struct ItLpNaca	itLpNaca;
-extern struct ItIplParmsReal xItIplParmsReal;
-extern struct ItExtVpdPanel xItExtVpdPanel;
-extern struct IoHriProcessorVpd xIoHriProcessorVpd[];
-extern struct ItLpQueue xItLpQueue;
-extern struct ItVpdAreas itVpdAreas;
-extern u64    xMsVpd[];
-extern struct msChunks msChunks;
-
-
-#endif /* _LPARDATA_H */
diff --git a/include/asm-ppc64/iSeries/LparMap.h b/include/asm-ppc64/iSeries/LparMap.h
index 075205b..038e5df 100644
--- a/include/asm-ppc64/iSeries/LparMap.h
+++ b/include/asm-ppc64/iSeries/LparMap.h
@@ -1,17 +1,17 @@
 /*
  * LparMap.h
  * Copyright (C) 2001  Mike Corrigan 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
@@ -21,13 +21,14 @@
 
 #include <asm/types.h>
 
-/* The iSeries hypervisor will set up mapping for one or more 
+/*
+ * The iSeries hypervisor will set up mapping for one or more
  * ESID/VSID pairs (in SLB/segment registers) and will set up
  * mappings of one or more ranges of pages to VAs.
  * We will have the hypervisor set up the ESID->VSID mapping
  * for the four kernel segments (C-F).  With shared processors,
  * the hypervisor will clear all segment registers and reload
- * these four whenever the processor is switched from one 
+ * these four whenever the processor is switched from one
  * partition to another.
  */
 
@@ -38,30 +39,31 @@
  * need to be located within the load area (if the total partition size
  * is 64 MB), but cannot be mapped.  Typically, this should specify
  * to map half (32 MB) of the load area.
- * 
- * The hypervisor will set up page table entries for the number of 
+ *
+ * The hypervisor will set up page table entries for the number of
  * pages specified.
  *
  * In 32-bit mode, the hypervisor will load all four of the
- * segment registers (identified by the low-order four bits of the 
+ * segment registers (identified by the low-order four bits of the
  * Esid field.  In 64-bit mode, the hypervisor will load one SLB
  * entry to map the Esid to the Vsid.
 */
 
-// Hypervisor initially maps 32MB of the load area 
-#define HvPagesToMap 8192
+/* Hypervisor initially maps 32MB of the load area */
+#define HvPagesToMap	8192
 
-struct LparMap
-{
-	u64	  xNumberEsids;		// Number of ESID/VSID pairs (1)
-	u64	  xNumberRanges;	// Number of VA ranges to map (1)
-	u64	  xSegmentTableOffs;	// Page number within load area of seg table (0)
-	u64	  xRsvd[5];		// Reserved (0)
-	u64	  xKernelEsid;  	// Esid used to map kernel load (0x0C00000000)	
-	u64	  xKernelVsid;		// Vsid used to map kernel load (0x0C00000000)
-	u64	  xPages;		// Number of pages to be mapped	(8192)
-	u64	  xOffset;		// Offset from start of load area (0)
-	u64	  xVPN;			// Virtual Page Number (0x000C000000000000)
+struct LparMap {
+	u64	xNumberEsids;	// Number of ESID/VSID pairs (1)
+	u64	xNumberRanges;	// Number of VA ranges to map (1)
+	u64	xSegmentTableOffs; // Page number within load area of seg table (0)
+	u64	xRsvd[5];
+	u64	xKernelEsid;	// Esid used to map kernel load (0x0C00000000)
+	u64	xKernelVsid;	// Vsid used to map kernel load (0x0C00000000)
+	u64	xPages;		// Number of pages to be mapped	(8192)
+	u64	xOffset;	// Offset from start of load area (0)
+	u64	xVPN;		// Virtual Page Number (0x000C000000000000)
 };
 
+extern struct LparMap		xLparMap;
+
 #endif /* _LPARMAP_H */
diff --git a/include/asm-ppc64/iSeries/XmPciLpEvent.h b/include/asm-ppc64/iSeries/XmPciLpEvent.h
deleted file mode 100644
index a3d27f1..0000000
--- a/include/asm-ppc64/iSeries/XmPciLpEvent.h
+++ /dev/null
@@ -1,18 +0,0 @@
-
-#ifndef	__XMPCILPEVENT_H__
-#define	__XMPCILPEVENT_H__
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int XmPciLpEvent_init(void);
-void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __XMPCILPEVENT_H__ */
diff --git a/include/asm-ppc64/iSeries/iSeries_io.h b/include/asm-ppc64/iSeries/iSeries_io.h
index f52b759..9f79413 100644
--- a/include/asm-ppc64/iSeries/iSeries_io.h
+++ b/include/asm-ppc64/iSeries/iSeries_io.h
@@ -5,32 +5,33 @@
 
 #ifdef CONFIG_PPC_ISERIES
 #include <linux/types.h>
-/************************************************************************/
-/* File iSeries_io.h created by Allan Trautman on Thu Dec 28 2000.      */
-/************************************************************************/
-/* Remaps the io.h for the iSeries Io                                   */
-/* Copyright (C) 20yy  Allan H Trautman, 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                                          */
-/************************************************************************/
-/* Change Activity:                                                     */
-/*   Created December 28, 2000                                          */
-/* End Change Activity                                                  */
-/************************************************************************/
+/*
+ * File iSeries_io.h created by Allan Trautman on Thu Dec 28 2000.
+ *
+ * Remaps the io.h for the iSeries Io
+ * Copyright (C) 2000  Allan H Trautman, 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
+ *
+ * Change Activity:
+ *   Created December 28, 2000
+ * End Change Activity
+ */
+
 extern u8   iSeries_Read_Byte(const volatile void __iomem * IoAddress);
 extern u16  iSeries_Read_Word(const volatile void __iomem * IoAddress);
 extern u32  iSeries_Read_Long(const volatile void __iomem * IoAddress);
@@ -39,8 +40,10 @@
 extern void iSeries_Write_Long(u32 IoData, volatile void __iomem * IoAddress);
 
 extern void iSeries_memset_io(volatile void __iomem *dest, char x, size_t n);
-extern void iSeries_memcpy_toio(volatile void __iomem *dest, void *source, size_t n);
-extern void iSeries_memcpy_fromio(void *dest, const volatile void __iomem *source, size_t n);
+extern void iSeries_memcpy_toio(volatile void __iomem *dest, void *source,
+		size_t n);
+extern void iSeries_memcpy_fromio(void *dest,
+		const volatile void __iomem *source, size_t n);
 
 #endif /* CONFIG_PPC_ISERIES */
 #endif /* _ISERIES_IO_H */
diff --git a/include/asm-ppc64/iSeries/iSeries_irq.h b/include/asm-ppc64/iSeries/iSeries_irq.h
index ff8dded..6c9767a 100644
--- a/include/asm-ppc64/iSeries/iSeries_irq.h
+++ b/include/asm-ppc64/iSeries/iSeries_irq.h
@@ -1,19 +1,8 @@
 #ifndef	__ISERIES_IRQ_H__
 #define	__ISERIES_IRQ_H__
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void iSeries_init_IRQ(void);
-int  iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, HvAgentId);
-int  iSeries_assign_IRQ(int, HvBusNumber, HvSubBusNumber, HvAgentId);
-void iSeries_activate_IRQs(void);
-
-int XmPciLpEvent_init(void);
-
-#ifdef __cplusplus
-}
-#endif
+extern void iSeries_init_IRQ(void);
+extern int  iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, HvAgentId);
+extern void iSeries_activate_IRQs(void);
 
 #endif /* __ISERIES_IRQ_H__ */
diff --git a/include/asm-ppc64/iSeries/iSeries_pci.h b/include/asm-ppc64/iSeries/iSeries_pci.h
index 5769cff..575f611 100644
--- a/include/asm-ppc64/iSeries/iSeries_pci.h
+++ b/include/asm-ppc64/iSeries/iSeries_pci.h
@@ -1,112 +1,88 @@
 #ifndef _ISERIES_64_PCI_H
 #define _ISERIES_64_PCI_H
 
-/************************************************************************/
-/* File iSeries_pci.h created by Allan Trautman on Tue Feb 20, 2001.    */
-/************************************************************************/
-/* Define some useful macros for the iSeries pci routines.              */
-/* Copyright (C) 2001  Allan H Trautman, 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                                          */
-/************************************************************************/
-/* Change Activity:                                                     */
-/*   Created Feb 20, 2001                                               */
-/*   Added device reset, March 22, 2001                                 */
-/*   Ported to ppc64, May 25, 2001                                      */
-/* End Change Activity                                                  */
-/************************************************************************/
+/*
+ * File iSeries_pci.h created by Allan Trautman on Tue Feb 20, 2001.
+ *
+ * Define some useful macros for the iSeries pci routines.
+ * Copyright (C) 2001  Allan H Trautman, 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
+ *
+ * Change Activity:
+ *   Created Feb 20, 2001
+ *   Added device reset, March 22, 2001
+ *   Ported to ppc64, May 25, 2001
+ * End Change Activity
+ */
 
 #include <asm/iSeries/HvCallPci.h>
 #include <asm/abs_addr.h>
 
-struct pci_dev;				/* For Forward Reference        */
+struct pci_dev;				/* For Forward Reference */
 struct iSeries_Device_Node;
 
-/************************************************************************/
-/* Gets iSeries Bus, SubBus, DevFn using iSeries_Device_Node structure */
-/************************************************************************/
+/*
+ * Gets iSeries Bus, SubBus, DevFn using iSeries_Device_Node structure
+ */
 
 #define ISERIES_BUS(DevPtr)	DevPtr->DsaAddr.Dsa.busNumber
 #define ISERIES_SUBBUS(DevPtr)	DevPtr->DsaAddr.Dsa.subBusNumber
 #define ISERIES_DEVICE(DevPtr)	DevPtr->DsaAddr.Dsa.deviceId
 #define ISERIES_DSA(DevPtr)	DevPtr->DsaAddr.DsaAddr
-#define ISERIES_DEVFUN(DevPtr)	DevPtr->DevFn
-#define ISERIES_DEVNODE(PciDev) ((struct iSeries_Device_Node*)PciDev->sysdata)
+#define ISERIES_DEVNODE(PciDev)	((struct iSeries_Device_Node *)PciDev->sysdata)
 
 #define EADsMaxAgents 7
 
-/************************************************************************/
-/* Decodes Linux DevFn to iSeries DevFn, bridge device, or function.    */
-/* For Linux, see PCI_SLOT and PCI_FUNC in include/linux/pci.h          */
-/************************************************************************/
+/*
+ * Decodes Linux DevFn to iSeries DevFn, bridge device, or function.
+ * For Linux, see PCI_SLOT and PCI_FUNC in include/linux/pci.h
+ */
 
-#define ISERIES_PCI_AGENTID(idsel,func)	((idsel & 0x0F) << 4) | (func  & 0x07)
-#define ISERIES_ENCODE_DEVICE(agentid)	((0x10) | ((agentid&0x20)>>2) | (agentid&07))
+#define ISERIES_PCI_AGENTID(idsel, func)	\
+	(((idsel & 0x0F) << 4) | (func & 0x07))
+#define ISERIES_ENCODE_DEVICE(agentid)		\
+	((0x10) | ((agentid & 0x20) >> 2) | (agentid & 0x07))
 
-#define ISERIES_GET_DEVICE_FROM_SUBBUS(subbus)   ((subbus >> 5) & 0x7)
-#define ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus) ((subbus >> 2) & 0x7)
+#define ISERIES_GET_DEVICE_FROM_SUBBUS(subbus)		((subbus >> 5) & 0x7)
+#define ISERIES_GET_FUNCTION_FROM_SUBBUS(subbus)	((subbus >> 2) & 0x7)
 
 /*
- * N.B. the ISERIES_DECODE_* macros are not used anywhere, and I think
- * the 0x71 (at least) must be wrong - 0x78 maybe?  -- paulus.
+ * Converts Virtual Address to Real Address for Hypervisor calls
  */
-#define ISERIES_DECODE_DEVFN(linuxdevfn)  (((linuxdevfn & 0x71) << 1) | (linuxdevfn & 0x07))
-#define ISERIES_DECODE_DEVICE(linuxdevfn) (((linuxdevfn & 0x38) >> 3) |(((linuxdevfn & 0x40) >> 2) + 0x10))
-#define ISERIES_DECODE_FUNCTION(linuxdevfn) (linuxdevfn & 0x07)
+#define ISERIES_HV_ADDR(virtaddr)	\
+	(0x8000000000000000 | virt_to_abs(virtaddr))
 
-/************************************************************************/
-/* Converts Virtual Address to Real Address for Hypervisor calls        */
-/************************************************************************/
-
-#define ISERIES_HV_ADDR(virtaddr)  (0x8000000000000000 | virt_to_abs(virtaddr))
-
-/************************************************************************/
-/* iSeries Device Information                                           */
-/************************************************************************/
-
+/*
+ * iSeries Device Information
+ */
 struct iSeries_Device_Node {
 	struct list_head Device_List;
-	struct pci_dev* PciDev;         /* Pointer to pci_dev structure*/
-        union HvDsaMap	DsaAddr;	/* Direct Select Address       */
-                                        /* busNumber,subBusNumber,     */ 
-	                                /* deviceId, barNumber         */
-	HvAgentId       AgentId;	/* Hypervisor DevFn            */
-	int             DevFn;          /* Linux devfn                 */
-	int             BarOffset;
-	int             Irq;            /* Assigned IRQ                */
-	int             ReturnCode;	/* Return Code Holder          */
-	int             IoRetry;        /* Current Retry Count         */
-	int             Flags;          /* Possible flags(disable/bist)*/
-	u16             Vendor;         /* Vendor ID                   */
-	u8              LogicalSlot;    /* Hv Slot Index for Tces      */
-	struct iommu_table* iommu_table;/* Device TCE Table            */ 
-	u8              PhbId;          /* Phb Card is on.             */
-	u16             Board;          /* Board Number                */
-	u8              FrameId;	/* iSeries spcn Frame Id       */
-	char            CardLocation[4];/* Char format of planar vpd   */
-	char            Location[20];   /* Frame  1, Card C10          */
+	struct pci_dev	*PciDev;
+	union HvDsaMap	DsaAddr;	/* Direct Select Address */
+					/* busNumber, subBusNumber, */
+					/* deviceId, barNumber */
+	int		DevFn;		/* Linux devfn */
+	int		Irq;		/* Assigned IRQ */
+	int		Flags;		/* Possible flags(disable/bist)*/
+	u8		LogicalSlot;	/* Hv Slot Index for Tces */
+	struct iommu_table *iommu_table;/* Device TCE Table */
 };
 
-/************************************************************************/
-/* Functions                                                            */
-/************************************************************************/
-
-extern int           iSeries_Device_Information(struct pci_dev*,char*, int);
-extern void          iSeries_Get_Location_Code(struct iSeries_Device_Node*);
-extern int           iSeries_Device_ToggleReset(struct pci_dev* PciDev, int AssertTime, int DelayTime);
+extern void	iSeries_Device_Information(struct pci_dev*, int);
 
 #endif /* _ISERIES_64_PCI_H */
diff --git a/include/asm-ppc64/iSeries/iSeries_proc.h b/include/asm-ppc64/iSeries/iSeries_proc.h
deleted file mode 100644
index adb6dc1..0000000
--- a/include/asm-ppc64/iSeries/iSeries_proc.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * iSeries_proc.h
- * Copyright (C) 2001  Kyle A. Lucke 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 _ISERIES_PROC_H
-#define _ISERIES_PROC_H
-
-extern void iSeries_proc_early_init(void);
-
-#endif /* _iSeries_PROC_H */
diff --git a/include/asm-ppc64/iSeries/mf.h b/include/asm-ppc64/iSeries/mf.h
index db333e1..7e6a0d9 100644
--- a/include/asm-ppc64/iSeries/mf.h
+++ b/include/asm-ppc64/iSeries/mf.h
@@ -9,17 +9,16 @@
  * all partitions in the iSeries.  It also provides miscellaneous low-level
  * machine facility type 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 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-ppc64/iSeries/vio.h b/include/asm-ppc64/iSeries/vio.h
index 3e5766a..6c05e62 100644
--- a/include/asm-ppc64/iSeries/vio.h
+++ b/include/asm-ppc64/iSeries/vio.h
@@ -8,32 +8,32 @@
  *           Colin Devilbiss <devilbis@us.ibm.com>
  *
  * (C) Copyright 2000 IBM Corporation
- * 
+ *
  * This header file is used by the iSeries virtual I/O device
  * drivers.  It defines the interfaces to the common functions
  * (implemented in drivers/char/viopath.h) as well as defining
- * common functions and structures.  Currently (at the time I 
+ * common functions and structures.  Currently (at the time I
  * wrote this comment) the iSeries virtual I/O device drivers
- * that use this are 
- *   drivers/block/viodasd.c 
+ * that use this are
+ *   drivers/block/viodasd.c
  *   drivers/char/viocons.c
  *   drivers/char/viotape.c
  *   drivers/cdrom/viocd.c
  *
  * The iSeries virtual ethernet support (veth.c) uses a whole
  * different set of functions.
- * 
+ *
  * 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) anyu later version.
  *
  * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of 
+ * 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.  
+ * General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License 
+ * 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
  *
@@ -44,39 +44,41 @@
 #include <asm/iSeries/HvTypes.h>
 #include <asm/iSeries/HvLpEvent.h>
 
-/* iSeries virtual I/O events use the subtype field in
+/*
+ * iSeries virtual I/O events use the subtype field in
  * HvLpEvent to figure out what kind of vio event is coming
  * in.  We use a table to route these, and this defines
  * the maximum number of distinct subtypes
  */
 #define VIO_MAX_SUBTYPES 8
 
-/* Each subtype can register a handler to process their events.
+/*
+ * Each subtype can register a handler to process their events.
  * The handler must have this interface.
  */
 typedef void (vio_event_handler_t) (struct HvLpEvent * event);
 
-int viopath_open(HvLpIndex remoteLp, int subtype, int numReq);
-int viopath_close(HvLpIndex remoteLp, int subtype, int numReq);
-int vio_setHandler(int subtype, vio_event_handler_t * beh);
-int vio_clearHandler(int subtype);
-int viopath_isactive(HvLpIndex lp);
-HvLpInstanceId viopath_sourceinst(HvLpIndex lp);
-HvLpInstanceId viopath_targetinst(HvLpIndex lp);
-void vio_set_hostlp(void);
-void *vio_get_event_buffer(int subtype);
-void vio_free_event_buffer(int subtype, void *buffer);
+extern int viopath_open(HvLpIndex remoteLp, int subtype, int numReq);
+extern int viopath_close(HvLpIndex remoteLp, int subtype, int numReq);
+extern int vio_setHandler(int subtype, vio_event_handler_t * beh);
+extern int vio_clearHandler(int subtype);
+extern int viopath_isactive(HvLpIndex lp);
+extern HvLpInstanceId viopath_sourceinst(HvLpIndex lp);
+extern HvLpInstanceId viopath_targetinst(HvLpIndex lp);
+extern void vio_set_hostlp(void);
+extern void *vio_get_event_buffer(int subtype);
+extern void vio_free_event_buffer(int subtype, void *buffer);
 
 extern HvLpIndex viopath_hostLp;
 extern HvLpIndex viopath_ourLp;
 
-#define VIOCHAR_MAX_DATA 200
+#define VIOCHAR_MAX_DATA	200
 
-#define VIOMAJOR_SUBTYPE_MASK 0xff00
-#define VIOMINOR_SUBTYPE_MASK 0x00ff
-#define VIOMAJOR_SUBTYPE_SHIFT 8
+#define VIOMAJOR_SUBTYPE_MASK	0xff00
+#define VIOMINOR_SUBTYPE_MASK	0x00ff
+#define VIOMAJOR_SUBTYPE_SHIFT	8
 
-#define VIOVERSION            0x0101
+#define VIOVERSION		0x0101
 
 /*
  * This is the general structure for VIO errors; each module should have
@@ -89,8 +91,8 @@
 	int errno;
 	const char *msg;
 };
-const struct vio_error_entry *vio_lookup_rc(const struct vio_error_entry
-					    *local_table, u16 rc);
+extern const struct vio_error_entry *vio_lookup_rc(
+		const struct vio_error_entry *local_table, u16 rc);
 
 enum viosubtypes {
 	viomajorsubtype_monitor = 0x0100,
@@ -102,7 +104,6 @@
 	viomajorsubtype_scsi = 0x0700
 };
 
-
 enum vioconfigsubtype {
 	vioconfigget = 0x0001,
 };
diff --git a/include/asm-ppc64/imalloc.h b/include/asm-ppc64/imalloc.h
index 3a45e91..e46ff68 100644
--- a/include/asm-ppc64/imalloc.h
+++ b/include/asm-ppc64/imalloc.h
@@ -4,9 +4,9 @@
 /*
  * Define the address range of the imalloc VM area.
  */
-#define PHBS_IO_BASE  	  IOREGIONBASE
-#define IMALLOC_BASE      (IOREGIONBASE + 0x80000000ul)	/* Reserve 2 gigs for PHBs */
-#define IMALLOC_END       (IOREGIONBASE + EADDR_MASK)
+#define PHBS_IO_BASE  	  VMALLOC_END
+#define IMALLOC_BASE      (PHBS_IO_BASE + 0x80000000ul)	/* Reserve 2 gigs for PHBs */
+#define IMALLOC_END       (VMALLOC_START + EADDR_MASK)
 
 
 /* imalloc region types */
@@ -18,7 +18,9 @@
 
 extern struct vm_struct * im_get_free_area(unsigned long size);
 extern struct vm_struct * im_get_area(unsigned long v_addr, unsigned long size,
-			int region_type);
-unsigned long im_free(void *addr);
+				      int region_type);
+extern void im_free(void *addr);
+
+extern unsigned long ioremap_bot;
 
 #endif /* _PPC64_IMALLOC_H */
diff --git a/include/asm-ppc64/iommu.h b/include/asm-ppc64/iommu.h
index bd53ca4..729de5c 100644
--- a/include/asm-ppc64/iommu.h
+++ b/include/asm-ppc64/iommu.h
@@ -82,24 +82,6 @@
 	unsigned long *it_map;       /* A simple allocation bitmap for now */
 };
 
-#ifdef CONFIG_PPC_ISERIES
-struct iommu_table_cb {
-	unsigned long	itc_busno;	/* Bus number for this tce table */
-	unsigned long	itc_start;	/* Will be NULL for secondary */
-	unsigned long	itc_totalsize;	/* Size (in pages) of whole table */
-	unsigned long	itc_offset;	/* Index into real tce table of the
-					   start of our section */
-	unsigned long	itc_size;	/* Size (in pages) of our section */
-	unsigned long	itc_index;	/* Index of this tce table */
-	unsigned short	itc_maxtables;	/* Max num of tables for partition */
-	unsigned char	itc_virtbus;	/* Flag to indicate virtual bus */
- 	unsigned char	itc_slotno;	/* IOA Tce Slot Index */
- 	unsigned char	itc_rsvd[4];
-};
-
-extern struct iommu_table vio_tce_table;      /* Tce table for virtual bus */
-#endif /* CONFIG_PPC_ISERIES */
-
 struct scatterlist;
 
 #ifdef CONFIG_PPC_MULTIPLATFORM
@@ -122,9 +104,6 @@
 
 #ifdef CONFIG_PPC_ISERIES
 
-/* Walks all buses and creates iommu tables */
-extern void iommu_setup_iSeries(void);
-
 /* Initializes tables for bio buses */
 extern void __init iommu_vio_init(void);
 
@@ -158,8 +137,12 @@
 extern void iommu_init_early_iSeries(void);
 extern void iommu_init_early_u3(void);
 
+#ifdef CONFIG_PCI
 extern void pci_iommu_init(void);
 extern void pci_direct_iommu_init(void);
+#else
+static inline void pci_iommu_init(void) { }
+#endif
 
 extern void alloc_u3_dart_table(void);
 
diff --git a/include/asm-ppc64/kdebug.h b/include/asm-ppc64/kdebug.h
index 4886342..d383d16 100644
--- a/include/asm-ppc64/kdebug.h
+++ b/include/asm-ppc64/kdebug.h
@@ -17,7 +17,7 @@
 
 /*
    Note - you should never unregister because that can race with NMIs.
-   If you really want to do it first unregister - then synchronize_kernel -
+   If you really want to do it first unregister - then synchronize_sched -
    then free.
  */
 int register_die_notifier(struct notifier_block *nb);
diff --git a/include/asm-ppc64/kexec.h b/include/asm-ppc64/kexec.h
new file mode 100644
index 0000000..511908a
--- /dev/null
+++ b/include/asm-ppc64/kexec.h
@@ -0,0 +1,41 @@
+#ifndef _PPC64_KEXEC_H
+#define _PPC64_KEXEC_H
+
+/*
+ * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.
+ * I.e. Maximum page that is mapped directly into kernel memory,
+ * and kmap is not required.
+ */
+
+/* Maximum physical address we can use pages from */
+/* XXX: since we copy virt we can use any page we allocate */
+#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
+
+/* Maximum address we can reach in physical address mode */
+/* XXX: I want to allow initrd in highmem.  otherwise set to rmo on lpar */
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
+
+/* Maximum address we can use for the control code buffer */
+/* XXX: unused today, ppc32 uses TASK_SIZE, probably left over from use_mm  */
+#define KEXEC_CONTROL_MEMORY_LIMIT (-1UL)
+
+/* XXX: today we don't use this at all, althogh we have a static stack */
+#define KEXEC_CONTROL_CODE_SIZE 4096
+
+/* The native architecture */
+#define KEXEC_ARCH KEXEC_ARCH_PPC64
+
+#define MAX_NOTE_BYTES 1024
+
+#ifndef __ASSEMBLY__
+
+typedef u32 note_buf_t[MAX_NOTE_BYTES/4];
+
+extern note_buf_t crash_notes[];
+
+extern void kexec_smp_wait(void);	/* get and clear naca physid, wait for
+					  master to copy new code to 0 */
+
+#endif /* __ASSEMBLY__ */
+#endif /* _PPC_KEXEC_H */
+
diff --git a/include/asm-ppc64/machdep.h b/include/asm-ppc64/machdep.h
index 5d3cd9d..9cdad3e 100644
--- a/include/asm-ppc64/machdep.h
+++ b/include/asm-ppc64/machdep.h
@@ -76,6 +76,7 @@
 	void		(*tce_flush)(struct iommu_table *tbl);
 	void		(*iommu_dev_setup)(struct pci_dev *dev);
 	void		(*iommu_bus_setup)(struct pci_bus *bus);
+	void		(*irq_bus_setup)(struct pci_bus *bus);
 
 	int		(*probe)(int platform);
 	void		(*setup_arch)(void);
@@ -85,6 +86,7 @@
 
 	void		(*init_IRQ)(void);
 	int		(*get_irq)(struct pt_regs *);
+	void		(*cpu_irq_down)(void);
 
 	/* PCI stuff */
 	void		(*pcibios_fixup)(void);
diff --git a/include/asm-ppc64/mmu.h b/include/asm-ppc64/mmu.h
index c78282a..f373de5 100644
--- a/include/asm-ppc64/mmu.h
+++ b/include/asm-ppc64/mmu.h
@@ -47,9 +47,10 @@
 #define SLB_VSID_KS		ASM_CONST(0x0000000000000800)
 #define SLB_VSID_KP		ASM_CONST(0x0000000000000400)
 #define SLB_VSID_N		ASM_CONST(0x0000000000000200) /* no-execute */
-#define SLB_VSID_L		ASM_CONST(0x0000000000000100) /* largepage 16M */
+#define SLB_VSID_L		ASM_CONST(0x0000000000000100) /* largepage */
 #define SLB_VSID_C		ASM_CONST(0x0000000000000080) /* class */
-
+#define SLB_VSID_LS		ASM_CONST(0x0000000000000070) /* size of largepage */
+ 
 #define SLB_VSID_KERNEL		(SLB_VSID_KP|SLB_VSID_C)
 #define SLB_VSID_USER		(SLB_VSID_KP|SLB_VSID_KS)
 
@@ -180,6 +181,28 @@
 	asm volatile("ptesync": : :"memory");
 }
 
+static inline unsigned long slot2va(unsigned long avpn, unsigned long large,
+		unsigned long secondary, unsigned long slot)
+{
+	unsigned long va;
+
+	va = avpn << 23;
+
+	if (!large) {
+		unsigned long vpi, pteg;
+
+		pteg = slot / HPTES_PER_GROUP;
+		if (secondary)
+			pteg = ~pteg;
+
+		vpi = ((va >> 28) ^ pteg) & htab_hash_mask;
+
+		va |= vpi << PAGE_SHIFT;
+	}
+
+	return va;
+}
+
 /*
  * Handle a fault by adding an HPTE. If the address can't be determined
  * to be valid via Linux page tables, return 1. If handled return 0
diff --git a/include/asm-ppc64/mmzone.h b/include/asm-ppc64/mmzone.h
index 0619a41..ed473f4 100644
--- a/include/asm-ppc64/mmzone.h
+++ b/include/asm-ppc64/mmzone.h
@@ -10,9 +10,20 @@
 #include <linux/config.h>
 #include <asm/smp.h>
 
-#ifdef CONFIG_DISCONTIGMEM
+/* generic non-linear memory support:
+ *
+ * 1) we will not split memory into more chunks than will fit into the
+ *    flags field of the struct page
+ */
+
+
+#ifdef CONFIG_NEED_MULTIPLE_NODES
 
 extern struct pglist_data *node_data[];
+/*
+ * Return a pointer to the node data for node n.
+ */
+#define NODE_DATA(nid)		(node_data[nid])
 
 /*
  * Following are specific to this numa platform.
@@ -47,36 +58,32 @@
 	return nid;
 }
 
-#define pfn_to_nid(pfn)		pa_to_nid((pfn) << PAGE_SHIFT)
-
-/*
- * Return a pointer to the node data for node n.
- */
-#define NODE_DATA(nid)		(node_data[nid])
-
 #define node_localnr(pfn, nid)	((pfn) - NODE_DATA(nid)->node_start_pfn)
 
 /*
  * Following are macros that each numa implmentation must define.
  */
 
-/*
- * Given a kernel address, find the home node of the underlying memory.
- */
-#define kvaddr_to_nid(kaddr)	pa_to_nid(__pa(kaddr))
-
-#define node_mem_map(nid)	(NODE_DATA(nid)->node_mem_map)
 #define node_start_pfn(nid)	(NODE_DATA(nid)->node_start_pfn)
 #define node_end_pfn(nid)	(NODE_DATA(nid)->node_end_pfn)
 
 #define local_mapnr(kvaddr) \
 	( (__pa(kvaddr) >> PAGE_SHIFT) - node_start_pfn(kvaddr_to_nid(kvaddr)) 
 
+#ifdef CONFIG_DISCONTIGMEM
+
+/*
+ * Given a kernel address, find the home node of the underlying memory.
+ */
+#define kvaddr_to_nid(kaddr)	pa_to_nid(__pa(kaddr))
+
+#define pfn_to_nid(pfn)		pa_to_nid((unsigned long)(pfn) << PAGE_SHIFT)
+
 /* Written this way to avoid evaluating arguments twice */
 #define discontigmem_pfn_to_page(pfn) \
 ({ \
 	unsigned long __tmp = pfn; \
-	(node_mem_map(pfn_to_nid(__tmp)) + \
+	(NODE_DATA(pfn_to_nid(__tmp))->node_mem_map + \
 	 node_localnr(__tmp, pfn_to_nid(__tmp))); \
 })
 
@@ -91,4 +98,11 @@
 #define discontigmem_pfn_valid(pfn)		((pfn) < num_physpages)
 
 #endif /* CONFIG_DISCONTIGMEM */
+
+#endif /* CONFIG_NEED_MULTIPLE_NODES */
+
+#ifdef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
+#define early_pfn_to_nid(pfn)  pa_to_nid(((unsigned long)pfn) << PAGE_SHIFT)
+#endif
+
 #endif /* _ASM_MMZONE_H_ */
diff --git a/include/asm-ppc64/nvram.h b/include/asm-ppc64/nvram.h
index 4e6dd37..dfaa215 100644
--- a/include/asm-ppc64/nvram.h
+++ b/include/asm-ppc64/nvram.h
@@ -70,6 +70,7 @@
 
 extern int pSeries_nvram_init(void);
 extern int pmac_nvram_init(void);
+extern int bpa_nvram_init(void);
 
 /* PowerMac specific nvram stuffs */
 
diff --git a/include/asm-ppc64/paca.h b/include/asm-ppc64/paca.h
index 1a0223b..ae76cae 100644
--- a/include/asm-ppc64/paca.h
+++ b/include/asm-ppc64/paca.h
@@ -20,13 +20,13 @@
 #include	<asm/types.h>
 #include	<asm/lppaca.h>
 #include	<asm/iSeries/ItLpRegSave.h>
+#include	<asm/iSeries/ItLpQueue.h>
 #include	<asm/mmu.h>
 
 register struct paca_struct *local_paca asm("r13");
 #define get_paca()	local_paca
 
 struct task_struct;
-struct ItLpQueue;
 
 /*
  * Defines the layout of the paca.
diff --git a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h
index bcd2178..a5893a3 100644
--- a/include/asm-ppc64/page.h
+++ b/include/asm-ppc64/page.h
@@ -202,9 +202,7 @@
 #define PAGE_OFFSET     ASM_CONST(0xC000000000000000)
 #define KERNELBASE      PAGE_OFFSET
 #define VMALLOCBASE     ASM_CONST(0xD000000000000000)
-#define IOREGIONBASE    ASM_CONST(0xE000000000000000)
 
-#define IO_REGION_ID       (IOREGIONBASE >> REGION_SHIFT)
 #define VMALLOC_REGION_ID  (VMALLOCBASE >> REGION_SHIFT)
 #define KERNEL_REGION_ID   (KERNELBASE >> REGION_SHIFT)
 #define USER_REGION_ID     (0UL)
@@ -219,7 +217,8 @@
 #define page_to_pfn(page)	discontigmem_page_to_pfn(page)
 #define pfn_to_page(pfn)	discontigmem_pfn_to_page(pfn)
 #define pfn_valid(pfn)		discontigmem_pfn_valid(pfn)
-#else
+#endif
+#ifdef CONFIG_FLATMEM
 #define pfn_to_page(pfn)	(mem_map + (pfn))
 #define page_to_pfn(page)	((unsigned long)((page) - mem_map))
 #define pfn_valid(pfn)		((pfn) < max_mapnr)
diff --git a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h
index 264c4f7..46cf61c 100644
--- a/include/asm-ppc64/pgtable.h
+++ b/include/asm-ppc64/pgtable.h
@@ -53,7 +53,8 @@
  * Define the address range of the vmalloc VM area.
  */
 #define VMALLOC_START (0xD000000000000000ul)
-#define VMALLOC_END   (VMALLOC_START + EADDR_MASK)
+#define VMALLOC_SIZE  (0x10000000000UL)
+#define VMALLOC_END   (VMALLOC_START + VMALLOC_SIZE)
 
 /*
  * Bits in a linux-style PTE.  These match the bits in the
@@ -239,9 +240,6 @@
 /* This now only contains the vmalloc pages */
 #define pgd_offset_k(address) pgd_offset(&init_mm, address)
 
-/* to find an entry in the ioremap page-table-directory */
-#define pgd_offset_i(address) (ioremap_pgd + pgd_index(address))
-
 /*
  * The following only work if pte_present() is true.
  * Undefined behaviour if not..
@@ -459,15 +457,12 @@
 #define __HAVE_ARCH_PTE_SAME
 #define pte_same(A,B)	(((pte_val(A) ^ pte_val(B)) & ~_PAGE_HPTEFLAGS) == 0)
 
-extern unsigned long ioremap_bot, ioremap_base;
-
 #define pmd_ERROR(e) \
 	printk("%s:%d: bad pmd %08x.\n", __FILE__, __LINE__, pmd_val(e))
 #define pgd_ERROR(e) \
 	printk("%s:%d: bad pgd %08x.\n", __FILE__, __LINE__, pgd_val(e))
 
 extern pgd_t swapper_pg_dir[];
-extern pgd_t ioremap_dir[];
 
 extern void paging_init(void);
 
diff --git a/include/asm-ppc64/ppc32.h b/include/asm-ppc64/ppc32.h
index 1d04048..6b44a8c 100644
--- a/include/asm-ppc64/ppc32.h
+++ b/include/asm-ppc64/ppc32.h
@@ -32,7 +32,7 @@
 
 		/* POSIX.1b timers */
 		struct {
-			timer_t _tid;			/* timer id */
+			compat_timer_t _tid;			/* timer id */
 			int _overrun;			/* overrun count */
 			compat_sigval_t _sigval;		/* same as below */
 			int _sys_private;		/* not to be passed to user */
diff --git a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h
index 809c634b..af28aa5 100644
--- a/include/asm-ppc64/processor.h
+++ b/include/asm-ppc64/processor.h
@@ -138,8 +138,16 @@
 #define	SPRN_NIADORM	0x3F3	/* Hardware Implementation Register 2 */
 #define SPRN_HID4	0x3F4	/* 970 HID4 */
 #define SPRN_HID5	0x3F6	/* 970 HID5 */
-#define	SPRN_TSC 	0x3FD	/* Thread switch control */
-#define	SPRN_TST 	0x3FC	/* Thread switch timeout */
+#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_TSCR	0x399   /* Thread switch control on BE */
+#define	SPRN_TTR	0x39A   /* Thread switch timeout on BE */
+#define	  TSCR_DEC_ENABLE	0x200000 /* Decrementer Interrupt */
+#define	  TSCR_EE_ENABLE	0x100000 /* External Interrupt */
+#define	  TSCR_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_L2CR	0x3F9	/* Level 2 Cache Control Regsiter */
 #define	SPRN_LR		0x008	/* Link Register */
 #define	SPRN_PIR	0x3FF	/* Processor Identification Register */
@@ -259,6 +267,7 @@
 #define PV_970FX	0x003C
 #define	PV_630        	0x0040
 #define	PV_630p	        0x0041
+#define	PV_BE		0x0070
 
 /* Platforms supported by PPC64 */
 #define PLATFORM_PSERIES      0x0100
@@ -267,6 +276,7 @@
 #define PLATFORM_LPAR         0x0001
 #define PLATFORM_POWERMAC     0x0400
 #define PLATFORM_MAPLE        0x0500
+#define PLATFORM_BPA          0x1000
 
 /* Compatibility with drivers coming from PPC32 world */
 #define _machine	(systemcfg->platform)
@@ -278,6 +288,7 @@
 #define IC_INVALID    0
 #define IC_OPEN_PIC   1
 #define IC_PPC_XIC    2
+#define IC_BPA_IIC    3
 
 #define XGLUE(a,b) a##b
 #define GLUE(a,b) XGLUE(a,b)
@@ -430,16 +441,6 @@
 }
 
 /*
- * Note: the vm_start and vm_end fields here should *not*
- * be in kernel space.  (Could vm_end == vm_start perhaps?)
- */
-#define IOREMAP_MMAP { &ioremap_mm, 0, 0x1000, NULL, \
-		    PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, \
-		    1, NULL, NULL }
-
-extern struct mm_struct ioremap_mm;
-
-/*
  * Return saved PC of a blocked thread. For now, this is the "user" PC
  */
 #define thread_saved_pc(tsk)    \
diff --git a/include/asm-ppc64/rtas.h b/include/asm-ppc64/rtas.h
index a8ab0e9..e7d1b52 100644
--- a/include/asm-ppc64/rtas.h
+++ b/include/asm-ppc64/rtas.h
@@ -186,8 +186,14 @@
 extern int rtas_get_power_level(int powerdomain, int *level);
 extern int rtas_set_power_level(int powerdomain, int level, int *setlevel);
 extern int rtas_set_indicator(int indicator, int index, int new_value);
+extern void rtas_progress(char *s, unsigned short hex);
 extern void rtas_initialize(void);
 
+struct rtc_time;
+extern void rtas_get_boot_time(struct rtc_time *rtc_time);
+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)
diff --git a/include/asm-ppc64/smp.h b/include/asm-ppc64/smp.h
index c8646fa..d86f742 100644
--- a/include/asm-ppc64/smp.h
+++ b/include/asm-ppc64/smp.h
@@ -45,7 +45,7 @@
 void generic_mach_cpu_die(void);
 #endif
 
-#define __smp_processor_id() (get_paca()->paca_index)
+#define raw_smp_processor_id()	(get_paca()->paca_index)
 #define hard_smp_processor_id() (get_paca()->hw_cpu_id)
 
 extern cpumask_t cpu_sibling_map[NR_CPUS];
@@ -85,6 +85,14 @@
 
 extern struct smp_ops_t *smp_ops;
 
+#ifdef CONFIG_PPC_PSERIES
+void vpa_init(int cpu);
+#else
+static inline void vpa_init(int cpu)
+{
+}
+#endif /* CONFIG_PPC_PSERIES */
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* !(_PPC64_SMP_H) */
diff --git a/include/asm-ppc64/sparsemem.h b/include/asm-ppc64/sparsemem.h
new file mode 100644
index 0000000..c5bd47e
--- /dev/null
+++ b/include/asm-ppc64/sparsemem.h
@@ -0,0 +1,16 @@
+#ifndef _ASM_PPC64_SPARSEMEM_H
+#define _ASM_PPC64_SPARSEMEM_H 1
+
+#ifdef CONFIG_SPARSEMEM
+/*
+ * SECTION_SIZE_BITS		2^N: how big each section will be
+ * MAX_PHYSADDR_BITS		2^N: how much physical address space we have
+ * MAX_PHYSMEM_BITS		2^N: how much memory we can have in that space
+ */
+#define SECTION_SIZE_BITS       24
+#define MAX_PHYSADDR_BITS       38
+#define MAX_PHYSMEM_BITS        36
+
+#endif /* CONFIG_SPARSEMEM */
+
+#endif /* _ASM_PPC64_SPARSEMEM_H */
diff --git a/include/asm-ppc64/thread_info.h b/include/asm-ppc64/thread_info.h
index 48b7900..0494df6 100644
--- a/include/asm-ppc64/thread_info.h
+++ b/include/asm-ppc64/thread_info.h
@@ -24,7 +24,7 @@
 	struct task_struct *task;		/* main task structure */
 	struct exec_domain *exec_domain;	/* execution domain */
 	int		cpu;			/* cpu we're on */
-	int		preempt_count;
+	int		preempt_count;		/* 0 => preemptable, <0 => BUG */
 	struct restart_block restart_block;
 	/* set by force_successful_syscall_return */
 	unsigned char	syscall_noerror;
diff --git a/include/asm-ppc64/time.h b/include/asm-ppc64/time.h
index 8d6e376..c6c762c 100644
--- a/include/asm-ppc64/time.h
+++ b/include/asm-ppc64/time.h
@@ -34,6 +34,15 @@
 extern void to_tm(int tim, struct rtc_time * tm);
 extern time_t last_rtc_update;
 
+void generic_calibrate_decr(void);
+void setup_default_decr(void);
+
+/* Some sane defaults: 125 MHz timebase, 1GHz processor */
+extern unsigned long ppc_proc_freq;
+#define DEFAULT_PROC_FREQ	(DEFAULT_TB_FREQ * 8)
+extern unsigned long ppc_tb_freq;
+#define DEFAULT_TB_FREQ		125000000UL
+
 /*
  * By putting all of this stuff into a single struct we 
  * reduce the number of cache lines touched by do_gettimeofday.
diff --git a/include/asm-ppc64/topology.h b/include/asm-ppc64/topology.h
index d58d9dd..fcdcfd2 100644
--- a/include/asm-ppc64/topology.h
+++ b/include/asm-ppc64/topology.h
@@ -59,10 +59,8 @@
 	.nr_balance_failed	= 0,			\
 }
 
-#else /* !CONFIG_NUMA */
+#endif /* CONFIG_NUMA */
 
 #include <asm-generic/topology.h>
 
-#endif /* CONFIG_NUMA */
-
 #endif /* _ASM_PPC64_TOPOLOGY_H */
diff --git a/include/asm-ppc64/xics.h b/include/asm-ppc64/xics.h
index fdec5e7..0c45e14 100644
--- a/include/asm-ppc64/xics.h
+++ b/include/asm-ppc64/xics.h
@@ -17,6 +17,7 @@
 void xics_init_IRQ(void);
 int xics_get_irq(struct pt_regs *);
 void xics_setup_cpu(void);
+void xics_teardown_cpu(void);
 void xics_cause_IPI(int cpu);
 void xics_request_IPIs(void);
 void xics_migrate_irqs_away(void);
diff --git a/include/asm-s390/cpcmd.h b/include/asm-s390/cpcmd.h
index 1d33c5da..1fcf65b 100644
--- a/include/asm-s390/cpcmd.h
+++ b/include/asm-s390/cpcmd.h
@@ -11,14 +11,28 @@
 #define __CPCMD__
 
 /*
+ * the lowlevel function for cpcmd
  * the caller of __cpcmd has to ensure that the response buffer is below 2 GB
  */
-extern void __cpcmd(char *cmd, char *response, int rlen);
+extern int __cpcmd(const char *cmd, char *response, int rlen, int *response_code);
 
 #ifndef __s390x__
 #define cpcmd __cpcmd
 #else
-extern void cpcmd(char *cmd, char *response, int rlen);
+/*
+ * cpcmd is the in-kernel interface for issuing CP commands
+ *
+ * cmd:		null-terminated command string, max 240 characters
+ * response:	response buffer for VM's textual response
+ * rlen:	size of the response buffer, cpcmd will not exceed this size
+ *		but will cap the output, if its too large. Everything that
+ *		did not fit into the buffer will be silently dropped
+ * response_code: return pointer for VM's error code
+ * return value: the size of the response. The caller can check if the buffer
+ *		was large enough by comparing the return value and rlen
+ * NOTE: If the response buffer is not below 2 GB, cpcmd can sleep
+ */
+extern int cpcmd(const char *cmd, char *response, int rlen, int *response_code);
 #endif /*__s390x__*/
 
 #endif
diff --git a/include/asm-s390/debug.h b/include/asm-s390/debug.h
index 6bbcdea..92360d9 100644
--- a/include/asm-s390/debug.h
+++ b/include/asm-s390/debug.h
@@ -9,6 +9,8 @@
 #ifndef DEBUG_H
 #define DEBUG_H
 
+#include <linux/config.h>
+#include <linux/fs.h>
 #include <linux/string.h>
 
 /* Note:
@@ -31,19 +33,18 @@
 } __attribute__((packed));
 
 
-#define __DEBUG_FEATURE_VERSION      1  /* version of debug feature */
+#define __DEBUG_FEATURE_VERSION      2  /* version of debug feature */
 
 #ifdef __KERNEL__
 #include <linux/spinlock.h>
 #include <linux/kernel.h>
 #include <linux/time.h>
-#include <linux/proc_fs.h>
 
 #define DEBUG_MAX_LEVEL            6  /* debug levels range from 0 to 6 */
 #define DEBUG_OFF_LEVEL            -1 /* level where debug is switched off */
 #define DEBUG_FLUSH_ALL            -1 /* parameter to flush all areas */
 #define DEBUG_MAX_VIEWS            10 /* max number of views in proc fs */
-#define DEBUG_MAX_PROCF_LEN        64 /* max length for a proc file name */
+#define DEBUG_MAX_NAME_LEN         64 /* max length for a debugfs file name */
 #define DEBUG_DEFAULT_LEVEL        3  /* initial debug level */
 
 #define DEBUG_DIR_ROOT "s390dbf" /* name of debug root directory in proc fs */
@@ -64,16 +65,17 @@
 	spinlock_t lock;			
 	int level;
 	int nr_areas;
-	int page_order;
+	int pages_per_area;
 	int buf_size;
 	int entry_size;	
-	debug_entry_t** areas;
+	debug_entry_t*** areas;
 	int active_area;
-	int *active_entry;
-	struct proc_dir_entry* proc_root_entry;
-	struct proc_dir_entry* proc_entries[DEBUG_MAX_VIEWS];
+	int *active_pages;
+	int *active_entries;
+	struct dentry* debugfs_root_entry;
+	struct dentry* debugfs_entries[DEBUG_MAX_VIEWS];
 	struct debug_view* views[DEBUG_MAX_VIEWS];	
-	char name[DEBUG_MAX_PROCF_LEN];
+	char name[DEBUG_MAX_NAME_LEN];
 } debug_info_t;
 
 typedef int (debug_header_proc_t) (debug_info_t* id,
@@ -98,7 +100,7 @@
 		         int area, debug_entry_t* entry, char* out_buf);						
 				
 struct debug_view {
-	char name[DEBUG_MAX_PROCF_LEN];
+	char name[DEBUG_MAX_NAME_LEN];
 	debug_prolog_proc_t* prolog_proc;
 	debug_header_proc_t* header_proc;
 	debug_format_proc_t* format_proc;
@@ -120,7 +122,7 @@
 
 /* Debug Feature API: */
 
-debug_info_t* debug_register(char* name, int pages_index, int nr_areas,
+debug_info_t* debug_register(char* name, int pages, int nr_areas,
                              int buf_size);
 
 void debug_unregister(debug_info_t* id);
@@ -132,7 +134,8 @@
 extern inline debug_entry_t* 
 debug_event(debug_info_t* id, int level, void* data, int length)
 {
-	if ((!id) || (level > id->level)) return NULL;
+	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
+		return NULL;
         return debug_event_common(id,level,data,length);
 }
 
@@ -140,7 +143,8 @@
 debug_int_event(debug_info_t* id, int level, unsigned int tag)
 {
         unsigned int t=tag;
-	if ((!id) || (level > id->level)) return NULL;
+	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
+		return NULL;
         return debug_event_common(id,level,&t,sizeof(unsigned int));
 }
 
@@ -148,14 +152,16 @@
 debug_long_event (debug_info_t* id, int level, unsigned long tag)
 {
         unsigned long t=tag;
-	if ((!id) || (level > id->level)) return NULL;
+	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
+		return NULL;
         return debug_event_common(id,level,&t,sizeof(unsigned long));
 }
 
 extern inline debug_entry_t* 
 debug_text_event(debug_info_t* id, int level, const char* txt)
 {
-	if ((!id) || (level > id->level)) return NULL;
+	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
+		return NULL;
         return debug_event_common(id,level,txt,strlen(txt));
 }
 
@@ -167,7 +173,8 @@
 extern inline debug_entry_t* 
 debug_exception(debug_info_t* id, int level, void* data, int length)
 {
-	if ((!id) || (level > id->level)) return NULL;
+	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
+		return NULL;
         return debug_exception_common(id,level,data,length);
 }
 
@@ -175,7 +182,8 @@
 debug_int_exception(debug_info_t* id, int level, unsigned int tag)
 {
         unsigned int t=tag;
-	if ((!id) || (level > id->level)) return NULL;
+	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
+		return NULL;
         return debug_exception_common(id,level,&t,sizeof(unsigned int));
 }
 
@@ -183,14 +191,16 @@
 debug_long_exception (debug_info_t* id, int level, unsigned long tag)
 {
         unsigned long t=tag;
-	if ((!id) || (level > id->level)) return NULL;
+	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
+		return NULL;
         return debug_exception_common(id,level,&t,sizeof(unsigned long));
 }
 
 extern inline debug_entry_t* 
 debug_text_exception(debug_info_t* id, int level, const char* txt)
 {
-	if ((!id) || (level > id->level)) return NULL;
+	if ((!id) || (level > id->level) || (id->pages_per_area == 0))
+		return NULL;
         return debug_exception_common(id,level,txt,strlen(txt));
 }
 
diff --git a/include/asm-s390/kexec.h b/include/asm-s390/kexec.h
new file mode 100644
index 0000000..54cf7d9
--- /dev/null
+++ b/include/asm-s390/kexec.h
@@ -0,0 +1,42 @@
+/*
+ * include/asm-s390/kexec.h
+ *
+ * (C) Copyright IBM Corp. 2005
+ *
+ * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
+ *
+ */
+
+#ifndef _S390_KEXEC_H
+#define _S390_KEXEC_H
+
+#include <asm/page.h>
+#include <asm/processor.h>
+/*
+ * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.
+ * I.e. Maximum page that is mapped directly into kernel memory,
+ * and kmap is not required.
+ */
+
+/* Maximum physical address we can use pages from */
+#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
+
+/* Maximum address we can reach in physical address mode */
+#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
+
+/* Maximum address we can use for the control pages */
+/* Not more than 2GB */
+#define KEXEC_CONTROL_MEMORY_LIMIT (1<<31)
+
+/* Allocate one page for the pdp and the second for the code */
+#define KEXEC_CONTROL_CODE_SIZE 4096
+
+/* The native architecture */
+#define KEXEC_ARCH KEXEC_ARCH_S390
+
+#define MAX_NOTE_BYTES 1024
+typedef u32 note_buf_t[MAX_NOTE_BYTES/4];
+
+extern note_buf_t crash_notes[];
+
+#endif /*_S390_KEXEC_H */
diff --git a/include/asm-s390/lowcore.h b/include/asm-s390/lowcore.h
index df5172f..76b5b19 100644
--- a/include/asm-s390/lowcore.h
+++ b/include/asm-s390/lowcore.h
@@ -109,10 +109,14 @@
 
 #ifndef __s390x__
 #define __LC_PFAULT_INTPARM             0x080
+#define __LC_CPU_TIMER_SAVE_AREA        0x0D8
 #define __LC_AREGS_SAVE_AREA            0x120
+#define __LC_GPREGS_SAVE_AREA           0x180
 #define __LC_CREGS_SAVE_AREA            0x1C0
 #else /* __s390x__ */
 #define __LC_PFAULT_INTPARM             0x11B8
+#define __LC_GPREGS_SAVE_AREA           0x1280
+#define __LC_CPU_TIMER_SAVE_AREA        0x1328
 #define __LC_AREGS_SAVE_AREA            0x1340
 #define __LC_CREGS_SAVE_AREA            0x1380
 #endif /* __s390x__ */
@@ -167,7 +171,8 @@
 	__u16        subchannel_nr;            /* 0x0ba */
 	__u32        io_int_parm;              /* 0x0bc */
 	__u32        io_int_word;              /* 0x0c0 */
-        __u8         pad3[0xD8-0xC4];          /* 0x0c4 */
+        __u8         pad3[0xD4-0xC4];          /* 0x0c4 */
+	__u32        extended_save_area_addr;  /* 0x0d4 */
 	__u32        cpu_timer_save_area[2];   /* 0x0d8 */
 	__u32        clock_comp_save_area[2];  /* 0x0e0 */
 	__u32        mcck_interruption_code[2]; /* 0x0e8 */
diff --git a/include/asm-s390/processor.h b/include/asm-s390/processor.h
index fb46e90..8bd14de 100644
--- a/include/asm-s390/processor.h
+++ b/include/asm-s390/processor.h
@@ -207,6 +207,18 @@
 #endif /* __s390x__ */
 
 /*
+ * Set PSW to specified value.
+ */
+static inline void __load_psw(psw_t psw)
+{
+#ifndef __s390x__
+	asm volatile ("lpsw  0(%0)" : : "a" (&psw), "m" (psw) : "cc" );
+#else
+	asm volatile ("lpswe 0(%0)" : : "a" (&psw), "m" (psw) : "cc" );
+#endif
+}
+
+/*
  * Set PSW mask to specified value, while leaving the
  * PSW addr pointing to the next instruction.
  */
@@ -214,8 +226,8 @@
 static inline void __load_psw_mask (unsigned long mask)
 {
 	unsigned long addr;
-
 	psw_t psw;
+
 	psw.mask = mask;
 
 #ifndef __s390x__
@@ -241,30 +253,8 @@
  */
 static inline void enabled_wait(void)
 {
-	unsigned long reg;
-	psw_t wait_psw;
-
-	wait_psw.mask = PSW_BASE_BITS | PSW_MASK_IO | PSW_MASK_EXT |
-		PSW_MASK_MCHECK | PSW_MASK_WAIT | PSW_DEFAULT_KEY;
-#ifndef __s390x__
-	asm volatile (
-		"    basr %0,0\n"
-		"0:  la   %0,1f-0b(%0)\n"
-		"    st   %0,4(%1)\n"
-		"    oi   4(%1),0x80\n"
-		"    lpsw 0(%1)\n"
-		"1:"
-		: "=&a" (reg) : "a" (&wait_psw), "m" (wait_psw)
-		: "memory", "cc" );
-#else /* __s390x__ */
-	asm volatile (
-		"    larl  %0,0f\n"
-		"    stg   %0,8(%1)\n"
-		"    lpswe 0(%1)\n"
-		"0:"
-		: "=&a" (reg) : "a" (&wait_psw), "m" (wait_psw)
-		: "memory", "cc" );
-#endif /* __s390x__ */
+	__load_psw_mask(PSW_BASE_BITS | PSW_MASK_IO | PSW_MASK_EXT |
+			PSW_MASK_MCHECK | PSW_MASK_WAIT | PSW_DEFAULT_KEY);
 }
 
 /*
@@ -273,13 +263,11 @@
 
 static inline void disabled_wait(unsigned long code)
 {
-        char psw_buffer[2*sizeof(psw_t)];
         unsigned long ctl_buf;
-        psw_t *dw_psw = (psw_t *)(((unsigned long) &psw_buffer+sizeof(psw_t)-1)
-                                  & -sizeof(psw_t));
+        psw_t dw_psw;
 
-        dw_psw->mask = PSW_BASE_BITS | PSW_MASK_WAIT;
-        dw_psw->addr = code;
+        dw_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT;
+        dw_psw.addr = code;
         /* 
          * Store status and then load disabled wait psw,
          * the processor is dead afterwards
@@ -301,7 +289,7 @@
                       "    oi    0x1c0,0x10\n" /* fake protection bit */
                       "    lpsw 0(%1)"
                       : "=m" (ctl_buf)
-		      : "a" (dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc" );
+		      : "a" (&dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc" );
 #else /* __s390x__ */
         asm volatile ("    stctg 0,0,0(%2)\n"
                       "    ni    4(%2),0xef\n" /* switch off protection */
@@ -333,7 +321,7 @@
                       "    oi    0x384(1),0x10\n" /* fake protection bit */
                       "    lpswe 0(%1)"
                       : "=m" (ctl_buf)
-		      : "a" (dw_psw), "a" (&ctl_buf),
+		      : "a" (&dw_psw), "a" (&ctl_buf),
 		        "m" (dw_psw) : "cc", "0", "1");
 #endif /* __s390x__ */
 }
diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h
index 4eff8f2..fc7c96e 100644
--- a/include/asm-s390/ptrace.h
+++ b/include/asm-s390/ptrace.h
@@ -276,7 +276,7 @@
 #endif /* __s390x__ */
 
 #define PSW_KERNEL_BITS	(PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_PRIMARY | \
-			 PSW_DEFAULT_KEY)
+			 PSW_MASK_MCHECK | PSW_DEFAULT_KEY)
 #define PSW_USER_BITS	(PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME | \
 			 PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK | \
 			 PSW_MASK_PSTATE | PSW_DEFAULT_KEY)
diff --git a/include/asm-s390/smp.h b/include/asm-s390/smp.h
index 9473786..dd50e57 100644
--- a/include/asm-s390/smp.h
+++ b/include/asm-s390/smp.h
@@ -47,7 +47,7 @@
  
 #define PROC_CHANGE_PENALTY	20		/* Schedule penalty */
 
-#define smp_processor_id() (S390_lowcore.cpu_data.cpu_nr)
+#define raw_smp_processor_id()	(S390_lowcore.cpu_data.cpu_nr)
 
 extern int smp_get_cpu(cpumask_t cpu_map);
 extern void smp_put_cpu(int cpu);
diff --git a/include/asm-s390/system.h b/include/asm-s390/system.h
index 81514d7..b4a9f05a 100644
--- a/include/asm-s390/system.h
+++ b/include/asm-s390/system.h
@@ -16,6 +16,7 @@
 #include <asm/types.h>
 #include <asm/ptrace.h>
 #include <asm/setup.h>
+#include <asm/processor.h>
 
 #ifdef __KERNEL__
 
@@ -103,29 +104,18 @@
 	prev = __switch_to(prev,next);					     \
 } while (0)
 
-#define prepare_arch_switch(rq, next)	do { } while(0)
-#define task_running(rq, p)		((rq)->curr == (p))
-
 #ifdef CONFIG_VIRT_CPU_ACCOUNTING
 extern void account_user_vtime(struct task_struct *);
 extern void account_system_vtime(struct task_struct *);
-
-#define finish_arch_switch(rq, prev) do {				     \
-	set_fs(current->thread.mm_segment);				     \
-	spin_unlock(&(rq)->lock);					     \
-	account_system_vtime(prev);					     \
-	local_irq_enable();						     \
-} while (0)
-
 #else
+#define account_system_vtime(prev) do { } while (0)
+#endif
 
 #define finish_arch_switch(rq, prev) do {				     \
 	set_fs(current->thread.mm_segment);				     \
-	spin_unlock_irq(&(rq)->lock);					     \
+	account_system_vtime(prev);					     \
 } while (0)
 
-#endif
-
 #define nop() __asm__ __volatile__ ("nop")
 
 #define xchg(ptr,x) \
@@ -331,9 +321,6 @@
 
 #ifdef __s390x__
 
-#define __load_psw(psw) \
-        __asm__ __volatile__("lpswe 0(%0)" : : "a" (&psw), "m" (psw) : "cc" );
-
 #define __ctl_load(array, low, high) ({ \
 	typedef struct { char _[sizeof(array)]; } addrtype; \
 	__asm__ __volatile__ ( \
@@ -390,9 +377,6 @@
 
 #else /* __s390x__ */
 
-#define __load_psw(psw) \
-	__asm__ __volatile__("lpsw 0(%0)" : : "a" (&psw) : "cc" );
-
 #define __ctl_load(array, low, high) ({ \
 	typedef struct { char _[sizeof(array)]; } addrtype; \
 	__asm__ __volatile__ ( \
@@ -451,6 +435,20 @@
 /* For spinlocks etc */
 #define local_irq_save(x)	((x) = local_irq_disable())
 
+/*
+ * Use to set psw mask except for the first byte which
+ * won't be changed by this function.
+ */
+static inline void
+__set_psw_mask(unsigned long mask)
+{
+	local_save_flags(mask);
+	__load_psw_mask(mask);
+}
+
+#define local_mcck_enable()  __set_psw_mask(PSW_KERNEL_BITS)
+#define local_mcck_disable() __set_psw_mask(PSW_KERNEL_BITS & ~PSW_MASK_MCHECK)
+
 #ifdef CONFIG_SMP
 
 extern void smp_ctl_set_bit(int cr, int bit);
diff --git a/include/asm-s390/thread_info.h b/include/asm-s390/thread_info.h
index aade85c..6c18a3f 100644
--- a/include/asm-s390/thread_info.h
+++ b/include/asm-s390/thread_info.h
@@ -50,7 +50,7 @@
 	struct exec_domain	*exec_domain;	/* execution domain */
 	unsigned long		flags;		/* low level flags */
 	unsigned int		cpu;		/* current CPU */
-	unsigned int		preempt_count; /* 0 => preemptable */
+	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
 	struct restart_block	restart_block;
 };
 
@@ -96,6 +96,7 @@
 #define TIF_RESTART_SVC		4	/* restart svc with new svc number */
 #define TIF_SYSCALL_AUDIT	5	/* syscall auditing active */
 #define TIF_SINGLE_STEP		6	/* deliver sigtrap on return to user */
+#define TIF_MCCK_PENDING	7	/* machine check handling is pending */
 #define TIF_USEDFPU		16	/* FPU was used by this task this quantum (SMP) */
 #define TIF_POLLING_NRFLAG	17	/* true if poll_idle() is polling 
 					   TIF_NEED_RESCHED */
@@ -109,6 +110,7 @@
 #define _TIF_RESTART_SVC	(1<<TIF_RESTART_SVC)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SINGLE_STEP	(1<<TIF_SINGLE_STEP)
+#define _TIF_MCCK_PENDING	(1<<TIF_MCCK_PENDING)
 #define _TIF_USEDFPU		(1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_31BIT		(1<<TIF_31BIT)
diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h
index f1a204f..363db45 100644
--- a/include/asm-s390/unistd.h
+++ b/include/asm-s390/unistd.h
@@ -269,7 +269,7 @@
 #define __NR_mq_timedreceive	274
 #define __NR_mq_notify		275
 #define __NR_mq_getsetattr	276
-/* Number 277 is reserved for new sys_kexec_load */
+#define __NR_kexec_load		277
 #define __NR_add_key		278
 #define __NR_request_key	279
 #define __NR_keyctl		280
diff --git a/include/asm-sh/page.h b/include/asm-sh/page.h
index 4c6d129..180467b 100644
--- a/include/asm-sh/page.h
+++ b/include/asm-sh/page.h
@@ -31,6 +31,7 @@
 #define HPAGE_SIZE		(1UL << HPAGE_SHIFT)
 #define HPAGE_MASK		(~(HPAGE_SIZE-1))
 #define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT-PAGE_SHIFT)
+#define ARCH_HAS_SETCLEAR_HUGE_PTE
 #endif
 
 #ifdef __KERNEL__
diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
index cd847a4..ecb9095 100644
--- a/include/asm-sh/pgtable.h
+++ b/include/asm-sh/pgtable.h
@@ -196,6 +196,7 @@
 static inline pte_t pte_mkdirty(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
 static inline pte_t pte_mkyoung(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
 static inline pte_t pte_mkwrite(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; }
+static inline pte_t pte_mkhuge(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; }
 
 /*
  * Macro and implementation to make a page protection as uncachable.
diff --git a/include/asm-sh/smp.h b/include/asm-sh/smp.h
index 38b5446..f19a8b3 100644
--- a/include/asm-sh/smp.h
+++ b/include/asm-sh/smp.h
@@ -25,7 +25,7 @@
 
 #define cpu_online(cpu)		cpu_isset(cpu, cpu_online_map)
 
-#define smp_processor_id()	(current_thread_info()->cpu)
+#define raw_smp_processor_id()	(current_thread_info()->cpu)
 
 /* I've no idea what the real meaning of this is */
 #define PROC_CHANGE_PENALTY	20
diff --git a/include/asm-sh/thread_info.h b/include/asm-sh/thread_info.h
index 4bbbd9f..46080ce 100644
--- a/include/asm-sh/thread_info.h
+++ b/include/asm-sh/thread_info.h
@@ -20,7 +20,7 @@
 	struct exec_domain	*exec_domain;	/* execution domain */
 	__u32			flags;		/* low level flags */
 	__u32			cpu;
-	__s32			preempt_count; /* 0 => preemptable, <0 => BUG */
+	int			preempt_count; /* 0 => preemptable, <0 => BUG */
 	struct restart_block	restart_block;
 	__u8			supervisor_stack[0];
 };
diff --git a/include/asm-sh64/page.h b/include/asm-sh64/page.h
index e1f7f5a..d6167f1 100644
--- a/include/asm-sh64/page.h
+++ b/include/asm-sh64/page.h
@@ -41,6 +41,7 @@
 #define HPAGE_SIZE		(1UL << HPAGE_SHIFT)
 #define HPAGE_MASK		(~(HPAGE_SIZE-1))
 #define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT-PAGE_SHIFT)
+#define ARCH_HAS_SETCLEAR_HUGE_PTE
 #endif
 
 #ifdef __KERNEL__
diff --git a/include/asm-sh64/pgtable.h b/include/asm-sh64/pgtable.h
index 525e152..78ac6be 100644
--- a/include/asm-sh64/pgtable.h
+++ b/include/asm-sh64/pgtable.h
@@ -430,6 +430,8 @@
 extern inline pte_t pte_mkexec(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_EXECUTE)); return pte; }
 extern inline pte_t pte_mkdirty(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
 extern inline pte_t pte_mkyoung(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
+extern inline pte_t pte_mkhuge(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; }
+
 
 /*
  * Conversion functions: convert a page and protection to a page entry.
diff --git a/include/asm-sh64/thread_info.h b/include/asm-sh64/thread_info.h
index 8a32d6b..10f024c 100644
--- a/include/asm-sh64/thread_info.h
+++ b/include/asm-sh64/thread_info.h
@@ -22,7 +22,7 @@
 	struct exec_domain	*exec_domain;	/* execution domain */
 	unsigned long		flags;		/* low level flags */
 	/* Put the 4 32-bit fields together to make asm offsetting easier. */
-	__s32			preempt_count; /* 0 => preemptable, <0 => BUG */
+	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
 	__u16			cpu;
 
 	mm_segment_t		addr_limit;
diff --git a/include/asm-sparc/smp.h b/include/asm-sparc/smp.h
index f986c0d..4f96d83 100644
--- a/include/asm-sparc/smp.h
+++ b/include/asm-sparc/smp.h
@@ -148,7 +148,7 @@
 }
 #endif
 
-#define smp_processor_id()	(current_thread_info()->cpu)
+#define raw_smp_processor_id()		(current_thread_info()->cpu)
 
 #define prof_multiplier(__cpu)		cpu_data(__cpu).multiplier
 #define prof_counter(__cpu)		cpu_data(__cpu).counter
diff --git a/include/asm-sparc/system.h b/include/asm-sparc/system.h
index 80cf20c..898562e 100644
--- a/include/asm-sparc/system.h
+++ b/include/asm-sparc/system.h
@@ -101,7 +101,7 @@
  * SWITCH_ENTER and SWITH_DO_LAZY_FPU do not work yet (e.g. SMP does not work)
  * XXX WTF is the above comment? Found in late teen 2.4.x.
  */
-#define prepare_arch_switch(rq, next) do { \
+#define prepare_arch_switch(next) do { \
 	__asm__ __volatile__( \
 	".globl\tflush_patch_switch\nflush_patch_switch:\n\t" \
 	"save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \
@@ -109,8 +109,6 @@
 	"save %sp, -0x40, %sp\n\t" \
 	"restore; restore; restore; restore; restore; restore; restore"); \
 } while(0)
-#define finish_arch_switch(rq, next)	spin_unlock_irq(&(rq)->lock)
-#define task_running(rq, p)		((rq)->curr == (p))
 
 	/* Much care has gone into this code, do not touch it.
 	 *
diff --git a/include/asm-sparc/thread_info.h b/include/asm-sparc/thread_info.h
index 104f03c..ff6ccb3 100644
--- a/include/asm-sparc/thread_info.h
+++ b/include/asm-sparc/thread_info.h
@@ -30,9 +30,9 @@
 	struct task_struct	*task;		/* main task structure */
 	struct exec_domain	*exec_domain;	/* execution domain */
 	unsigned long		flags;		/* low level flags */
-
 	int			cpu;		/* cpu we're on */
-	int			preempt_count;
+	int			preempt_count;	/* 0 => preemptable,
+						   <0 => BUG */
 	int			softirq_count;
 	int			hardirq_count;
 
diff --git a/include/asm-sparc/uaccess.h b/include/asm-sparc/uaccess.h
index f461144..0a780e8 100644
--- a/include/asm-sparc/uaccess.h
+++ b/include/asm-sparc/uaccess.h
@@ -41,10 +41,11 @@
  * No one can read/write anything from userland in the kernel space by setting
  * large size and address near to PAGE_OFFSET - a fault will break his intentions.
  */
-#define __user_ok(addr,size) ((addr) < STACK_TOP)
+#define __user_ok(addr, size) ({ (void)(size); (addr) < STACK_TOP; })
 #define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
 #define __access_ok(addr,size) (__user_ok((addr) & get_fs().seg,(size)))
-#define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size))
+#define access_ok(type, addr, size)					\
+	({ (void)(type); __access_ok((unsigned long)(addr), size); })
 
 /* this function will go away soon - use access_ok() instead */
 static inline int __deprecated verify_area(int type, const void __user * addr, unsigned long size)
diff --git a/include/asm-sparc64/agp.h b/include/asm-sparc64/agp.h
index ba05bdf..58f8cb6 100644
--- a/include/asm-sparc64/agp.h
+++ b/include/asm-sparc64/agp.h
@@ -8,4 +8,14 @@
 #define flush_agp_mappings() 
 #define flush_agp_cache() mb()
 
+/* Convert a physical address to an address suitable for the GART. */
+#define phys_to_gart(x) (x)
+#define gart_to_phys(x) (x)
+
+/* GATT allocation. Returns/accepts GATT kernel virtual address. */
+#define alloc_gatt_pages(order)		\
+	((char *)__get_free_pages(GFP_KERNEL, (order)))
+#define free_gatt_pages(table, order)	\
+	free_pages((unsigned long)(table), (order))
+
 #endif
diff --git a/include/asm-sparc64/compat.h b/include/asm-sparc64/compat.h
index 22f5805..b59122d 100644
--- a/include/asm-sparc64/compat.h
+++ b/include/asm-sparc64/compat.h
@@ -25,6 +25,7 @@
 typedef u32		compat_caddr_t;
 typedef __kernel_fsid_t	compat_fsid_t;
 typedef s32		compat_key_t;
+typedef s32		compat_timer_t;
 
 typedef s32		compat_int_t;
 typedef s32		compat_long_t;
diff --git a/include/asm-sparc64/kdebug.h b/include/asm-sparc64/kdebug.h
index f70d3da..6321f5a 100644
--- a/include/asm-sparc64/kdebug.h
+++ b/include/asm-sparc64/kdebug.h
@@ -16,7 +16,7 @@
 };
 
 /* Note - you should never unregister because that can race with NMIs.
- * If you really want to do it first unregister - then synchronize_kernel
+ * If you really want to do it first unregister - then synchronize_sched
  * - then free.
  */
 int register_die_notifier(struct notifier_block *nb);
diff --git a/include/asm-sparc64/page.h b/include/asm-sparc64/page.h
index 219ea04..b87dbbd 100644
--- a/include/asm-sparc64/page.h
+++ b/include/asm-sparc64/page.h
@@ -95,6 +95,8 @@
 #define HPAGE_SIZE		(_AC(1,UL) << HPAGE_SHIFT)
 #define HPAGE_MASK		(~(HPAGE_SIZE - 1UL))
 #define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
+#define ARCH_HAS_SETCLEAR_HUGE_PTE
+#define ARCH_HAS_HUGETLB_PREFAULT_HOOK
 #endif
 
 #define TASK_UNMAPPED_BASE	(test_thread_flag(TIF_32BIT) ? \
diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
index ae2cd5b..1ae00c5 100644
--- a/include/asm-sparc64/pgtable.h
+++ b/include/asm-sparc64/pgtable.h
@@ -286,6 +286,7 @@
 #define pte_mkyoung(pte)	(__pte(pte_val(pte) | _PAGE_ACCESSED | _PAGE_R))
 #define pte_mkwrite(pte)	(__pte(pte_val(pte) | _PAGE_WRITE))
 #define pte_mkdirty(pte)	(__pte(pte_val(pte) | _PAGE_MODIFIED | _PAGE_W))
+#define pte_mkhuge(pte)		(__pte(pte_val(pte) | _PAGE_SZHUGE))
 
 /* to find an entry in a page-table-directory. */
 #define pgd_index(address)	(((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
diff --git a/include/asm-sparc64/processor.h b/include/asm-sparc64/processor.h
index bc1445b..d0bee24 100644
--- a/include/asm-sparc64/processor.h
+++ b/include/asm-sparc64/processor.h
@@ -192,6 +192,40 @@
 
 #define cpu_relax()	barrier()
 
+/* Prefetch support.  This is tuned for UltraSPARC-III and later.
+ * UltraSPARC-I will treat these as nops, and UltraSPARC-II has
+ * a shallower prefetch queue than later chips.
+ */
+#define ARCH_HAS_PREFETCH
+#define ARCH_HAS_PREFETCHW
+#define ARCH_HAS_SPINLOCK_PREFETCH
+
+static inline void prefetch(const void *x)
+{
+	/* We do not use the read prefetch mnemonic because that
+	 * prefetches into the prefetch-cache which only is accessible
+	 * by floating point operations in UltraSPARC-III and later.
+	 * By contrast, "#one_write" prefetches into the L2 cache
+	 * in shared state.
+	 */
+	__asm__ __volatile__("prefetch [%0], #one_write"
+			     : /* no outputs */
+			     : "r" (x));
+}
+
+static inline void prefetchw(const void *x)
+{
+	/* The most optimal prefetch to use for writes is
+	 * "#n_writes".  This brings the cacheline into the
+	 * L2 cache in "owned" state.
+	 */
+	__asm__ __volatile__("prefetch [%0], #n_writes"
+			     : /* no outputs */
+			     : "r" (x));
+}
+
+#define spin_lock_prefetch(x)	prefetchw(x)
+
 #endif /* !(__ASSEMBLY__) */
 
 #endif /* !(__ASM_SPARC64_PROCESSOR_H) */
diff --git a/include/asm-sparc64/smp.h b/include/asm-sparc64/smp.h
index 5e3e06d..110a2de 100644
--- a/include/asm-sparc64/smp.h
+++ b/include/asm-sparc64/smp.h
@@ -64,7 +64,7 @@
 	}
 }
 
-#define smp_processor_id() (current_thread_info()->cpu)
+#define raw_smp_processor_id() (current_thread_info()->cpu)
 
 #endif /* !(__ASSEMBLY__) */
 
diff --git a/include/asm-sparc64/system.h b/include/asm-sparc64/system.h
index fd12ca3..f9be2c5 100644
--- a/include/asm-sparc64/system.h
+++ b/include/asm-sparc64/system.h
@@ -139,19 +139,13 @@
 #define flush_user_windows flushw_user
 #define flush_register_windows flushw_all
 
-#define prepare_arch_switch(rq, next)		\
-do {	spin_lock(&(next)->switch_lock);	\
-	spin_unlock(&(rq)->lock);		\
+/* Don't hold the runqueue lock over context switch */
+#define __ARCH_WANT_UNLOCKED_CTXSW
+#define prepare_arch_switch(next)		\
+do {						\
 	flushw_all();				\
 } while (0)
 
-#define finish_arch_switch(rq, prev)		\
-do {	spin_unlock_irq(&(prev)->switch_lock);	\
-} while (0)
-
-#define task_running(rq, p) \
-	((rq)->curr == (p) || spin_is_locked(&(p)->switch_lock))
-
 	/* See what happens when you design the chip correctly?
 	 *
 	 * We tell gcc we clobber all non-fixed-usage registers except
diff --git a/include/asm-sparc64/termios.h b/include/asm-sparc64/termios.h
index 8effce0..9777a9c 100644
--- a/include/asm-sparc64/termios.h
+++ b/include/asm-sparc64/termios.h
@@ -100,16 +100,17 @@
 #define user_termio_to_kernel_termios(termios, termio) \
 ({ \
 	unsigned short tmp; \
-	get_user(tmp, &(termio)->c_iflag); \
+	int err; \
+	err = get_user(tmp, &(termio)->c_iflag); \
 	(termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \
-	get_user(tmp, &(termio)->c_oflag); \
+	err |= get_user(tmp, &(termio)->c_oflag); \
 	(termios)->c_oflag = (0xffff0000 & ((termios)->c_oflag)) | tmp; \
-	get_user(tmp, &(termio)->c_cflag); \
+	err |= get_user(tmp, &(termio)->c_cflag); \
 	(termios)->c_cflag = (0xffff0000 & ((termios)->c_cflag)) | tmp; \
-	get_user(tmp, &(termio)->c_lflag); \
+	err |= get_user(tmp, &(termio)->c_lflag); \
 	(termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \
-	copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
-	0; \
+	err |= copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
+	err; \
 })
 
 /*
@@ -119,53 +120,56 @@
  */
 #define kernel_termios_to_user_termio(termio, termios) \
 ({ \
-	put_user((termios)->c_iflag, &(termio)->c_iflag); \
-	put_user((termios)->c_oflag, &(termio)->c_oflag); \
-	put_user((termios)->c_cflag, &(termio)->c_cflag); \
-	put_user((termios)->c_lflag, &(termio)->c_lflag); \
-	put_user((termios)->c_line,  &(termio)->c_line); \
-	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
+	int err; \
+	err  = put_user((termios)->c_iflag, &(termio)->c_iflag); \
+	err |= put_user((termios)->c_oflag, &(termio)->c_oflag); \
+	err |= put_user((termios)->c_cflag, &(termio)->c_cflag); \
+	err |= put_user((termios)->c_lflag, &(termio)->c_lflag); \
+	err |= put_user((termios)->c_line,  &(termio)->c_line); \
+	err |= copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
 	if (!((termios)->c_lflag & ICANON)) { \
-		put_user((termios)->c_cc[VMIN], &(termio)->c_cc[_VMIN]); \
-		put_user((termios)->c_cc[VTIME], &(termio)->c_cc[_VTIME]); \
+		err |= put_user((termios)->c_cc[VMIN], &(termio)->c_cc[_VMIN]); \
+		err |= put_user((termios)->c_cc[VTIME], &(termio)->c_cc[_VTIME]); \
 	} \
-	0; \
+	err; \
 })
 
 #define user_termios_to_kernel_termios(k, u) \
 ({ \
-	get_user((k)->c_iflag, &(u)->c_iflag); \
-	get_user((k)->c_oflag, &(u)->c_oflag); \
-	get_user((k)->c_cflag, &(u)->c_cflag); \
-	get_user((k)->c_lflag, &(u)->c_lflag); \
-	get_user((k)->c_line,  &(u)->c_line); \
-	copy_from_user((k)->c_cc, (u)->c_cc, NCCS); \
+	int err; \
+	err  = get_user((k)->c_iflag, &(u)->c_iflag); \
+	err |= get_user((k)->c_oflag, &(u)->c_oflag); \
+	err |= get_user((k)->c_cflag, &(u)->c_cflag); \
+	err |= get_user((k)->c_lflag, &(u)->c_lflag); \
+	err |= get_user((k)->c_line,  &(u)->c_line); \
+	err |= copy_from_user((k)->c_cc, (u)->c_cc, NCCS); \
 	if((k)->c_lflag & ICANON) { \
-		get_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \
-		get_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \
+		err |= get_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \
+		err |= get_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \
 	} else { \
-		get_user((k)->c_cc[VMIN],  &(u)->c_cc[_VMIN]); \
-		get_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \
+		err |= get_user((k)->c_cc[VMIN],  &(u)->c_cc[_VMIN]); \
+		err |= get_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \
 	} \
-	0; \
+	err; \
 })
 
 #define kernel_termios_to_user_termios(u, k) \
 ({ \
-	put_user((k)->c_iflag, &(u)->c_iflag); \
-	put_user((k)->c_oflag, &(u)->c_oflag); \
-	put_user((k)->c_cflag, &(u)->c_cflag); \
-	put_user((k)->c_lflag, &(u)->c_lflag); \
-	put_user((k)->c_line, &(u)->c_line); \
-	copy_to_user((u)->c_cc, (k)->c_cc, NCCS); \
+	int err; \
+	err  = put_user((k)->c_iflag, &(u)->c_iflag); \
+	err |= put_user((k)->c_oflag, &(u)->c_oflag); \
+	err |= put_user((k)->c_cflag, &(u)->c_cflag); \
+	err |= put_user((k)->c_lflag, &(u)->c_lflag); \
+	err |= put_user((k)->c_line, &(u)->c_line); \
+	err |= copy_to_user((u)->c_cc, (k)->c_cc, NCCS); \
 	if(!((k)->c_lflag & ICANON)) { \
-		put_user((k)->c_cc[VMIN],  &(u)->c_cc[_VMIN]); \
-		put_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \
+		err |= put_user((k)->c_cc[VMIN],  &(u)->c_cc[_VMIN]); \
+		err |= put_user((k)->c_cc[VTIME], &(u)->c_cc[_VTIME]); \
 	} else { \
-		put_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \
-		put_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \
+		err |= put_user((k)->c_cc[VEOF], &(u)->c_cc[VEOF]); \
+		err |= put_user((k)->c_cc[VEOL], &(u)->c_cc[VEOL]); \
 	} \
-	0; \
+	err; \
 })
 
 #endif	/* __KERNEL__ */
diff --git a/include/asm-sparc64/thread_info.h b/include/asm-sparc64/thread_info.h
index 517caab..0cd6529 100644
--- a/include/asm-sparc64/thread_info.h
+++ b/include/asm-sparc64/thread_info.h
@@ -46,7 +46,7 @@
 	unsigned long		fault_address;
 	struct pt_regs		*kregs;
 	struct exec_domain	*exec_domain;
-	int			preempt_count;
+	int			preempt_count;	/* 0 => preemptable, <0 => BUG */
 	int			__pad;
 
 	unsigned long		*utraps;
diff --git a/include/asm-um/ptrace-i386.h b/include/asm-um/ptrace-i386.h
index 04222f3..fe882b9 100644
--- a/include/asm-um/ptrace-i386.h
+++ b/include/asm-um/ptrace-i386.h
@@ -32,6 +32,10 @@
 #define PT_REGS_SYSCALL_RET(r) PT_REGS_EAX(r)
 #define PT_FIX_EXEC_STACK(sp) do ; while(0)
 
+/* Cope with a conditional i386 definition. */
+#undef profile_pc
+#define profile_pc(regs) PT_REGS_IP(regs)
+
 #define user_mode(r) UPT_IS_USER(&(r)->regs)
 
 #endif
diff --git a/include/asm-um/smp.h b/include/asm-um/smp.h
index 4412d5d..d879eba 100644
--- a/include/asm-um/smp.h
+++ b/include/asm-um/smp.h
@@ -8,7 +8,8 @@
 #include "asm/current.h"
 #include "linux/cpumask.h"
 
-#define smp_processor_id() (current_thread->cpu)
+#define raw_smp_processor_id() (current_thread->cpu)
+
 #define cpu_logical_map(n) (n)
 #define cpu_number_map(n) (n)
 #define PROC_CHANGE_PENALTY	15 /* Pick a number, any number */
diff --git a/include/asm-um/thread_info.h b/include/asm-um/thread_info.h
index 1feaaf1..97267f0 100644
--- a/include/asm-um/thread_info.h
+++ b/include/asm-um/thread_info.h
@@ -17,7 +17,7 @@
 	struct exec_domain	*exec_domain;	/* execution domain */
 	unsigned long		flags;		/* low level flags */
 	__u32			cpu;		/* current CPU */
-	__s32			preempt_count;  /* 0 => preemptable, 
+	int			preempt_count;  /* 0 => preemptable,
 						   <0 => BUG */
 	mm_segment_t		addr_limit;	/* thread address space:
 					 	   0-0xBFFFFFFF for user
diff --git a/include/asm-v850/thread_info.h b/include/asm-v850/thread_info.h
index e2ef445..e4cfad9 100644
--- a/include/asm-v850/thread_info.h
+++ b/include/asm-v850/thread_info.h
@@ -30,7 +30,8 @@
 	struct exec_domain	*exec_domain;	/* execution domain */
 	unsigned long		flags;		/* low level flags */
 	int			cpu;		/* cpu we're on */
-	int			preempt_count;
+	int			preempt_count;	/* 0 => preemptable,
+						   <0 => BUG */
 	struct restart_block	restart_block;
 };
 
diff --git a/include/asm-x86_64/a.out.h b/include/asm-x86_64/a.out.h
index 5952914..7255cde 100644
--- a/include/asm-x86_64/a.out.h
+++ b/include/asm-x86_64/a.out.h
@@ -21,7 +21,7 @@
 
 #ifdef __KERNEL__
 #include <linux/thread_info.h>
-#define STACK_TOP (test_thread_flag(TIF_IA32) ? IA32_PAGE_OFFSET : TASK_SIZE)
+#define STACK_TOP TASK_SIZE
 #endif
 
 #endif /* __A_OUT_GNU_H__ */
diff --git a/include/asm-x86_64/agp.h b/include/asm-x86_64/agp.h
index 0bb9019..06c52ee 100644
--- a/include/asm-x86_64/agp.h
+++ b/include/asm-x86_64/agp.h
@@ -19,4 +19,14 @@
    worth it. Would need a page for it. */
 #define flush_agp_cache() asm volatile("wbinvd":::"memory")
 
+/* Convert a physical address to an address suitable for the GART. */
+#define phys_to_gart(x) (x)
+#define gart_to_phys(x) (x)
+
+/* GATT allocation. Returns/accepts GATT kernel virtual address. */
+#define alloc_gatt_pages(order)		\
+	((char *)__get_free_pages(GFP_KERNEL, (order)))
+#define free_gatt_pages(table, order)	\
+	free_pages((unsigned long)(table), (order))
+
 #endif
diff --git a/include/asm-x86_64/apic.h b/include/asm-x86_64/apic.h
index e4b1017..16ec82e 100644
--- a/include/asm-x86_64/apic.h
+++ b/include/asm-x86_64/apic.h
@@ -77,7 +77,7 @@
 extern int get_maxlvt (void);
 extern void clear_local_APIC (void);
 extern void connect_bsp_APIC (void);
-extern void disconnect_bsp_APIC (void);
+extern void disconnect_bsp_APIC (int virt_wire_setup);
 extern void disable_local_APIC (void);
 extern int verify_local_APIC (void);
 extern void cache_APIC_registers (void);
diff --git a/include/asm-x86_64/apicdef.h b/include/asm-x86_64/apicdef.h
index bfebdb6..9388062 100644
--- a/include/asm-x86_64/apicdef.h
+++ b/include/asm-x86_64/apicdef.h
@@ -94,7 +94,7 @@
 #define			SET_APIC_DELIVERY_MODE(x,y)	(((x)&~0x700)|((y)<<8))
 #define				APIC_MODE_FIXED		0x0
 #define				APIC_MODE_NMI		0x4
-#define				APIC_MODE_EXINT		0x7
+#define				APIC_MODE_EXTINT	0x7
 #define 	APIC_LVT1	0x360
 #define		APIC_LVTERR	0x370
 #define		APIC_TMICT	0x380
diff --git a/include/asm-x86_64/bitops.h b/include/asm-x86_64/bitops.h
index 5dd7727..a31bb99 100644
--- a/include/asm-x86_64/bitops.h
+++ b/include/asm-x86_64/bitops.h
@@ -411,8 +411,6 @@
 /* find last set bit */
 #define fls(x) generic_fls(x)
 
-#define ARCH_HAS_ATOMIC_UNSIGNED 1
-
 #endif /* __KERNEL__ */
 
 #endif /* _X86_64_BITOPS_H */
diff --git a/include/asm-x86_64/ia32.h b/include/asm-x86_64/ia32.h
index c0a7717..6efa00f 100644
--- a/include/asm-x86_64/ia32.h
+++ b/include/asm-x86_64/ia32.h
@@ -94,7 +94,7 @@
 
 		/* POSIX.1b timers */
 		struct {
-			int _tid;		/* timer id */
+			compat_timer_t _tid;	/* timer id */
 			int _overrun;		/* overrun count */
 			compat_sigval_t _sigval;	/* same as below */
 			int _sys_private;	/* not to be passed to user */
diff --git a/include/asm-x86_64/io.h b/include/asm-x86_64/io.h
index 9420270..37fc3f1 100644
--- a/include/asm-x86_64/io.h
+++ b/include/asm-x86_64/io.h
@@ -124,12 +124,7 @@
 /*
  * Change "struct page" to physical address.
  */
-#ifdef CONFIG_DISCONTIGMEM
-#include <asm/mmzone.h>
 #define page_to_phys(page)    ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
-#else
-#define page_to_phys(page)	((page - mem_map) << PAGE_SHIFT)
-#endif
 
 #include <asm-generic/iomap.h>
 
diff --git a/include/asm-x86_64/irq.h b/include/asm-x86_64/irq.h
index 3af50b3..eb3b7aa 100644
--- a/include/asm-x86_64/irq.h
+++ b/include/asm-x86_64/irq.h
@@ -52,4 +52,9 @@
 struct pt_regs;
 int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
 
+#ifdef CONFIG_HOTPLUG_CPU
+#include <linux/cpumask.h>
+extern void fixup_irqs(cpumask_t map);
+#endif
+
 #endif /* _ASM_IRQ_H */
diff --git a/include/asm-x86_64/kdebug.h b/include/asm-x86_64/kdebug.h
index 6277f75..b903419 100644
--- a/include/asm-x86_64/kdebug.h
+++ b/include/asm-x86_64/kdebug.h
@@ -14,7 +14,7 @@
 }; 
 
 /* Note - you should never unregister because that can race with NMIs.
-   If you really want to do it first unregister - then synchronize_kernel - then free. 
+   If you really want to do it first unregister - then synchronize_sched - then free.
   */
 int register_die_notifier(struct notifier_block *nb);
 extern struct notifier_block *die_chain;
diff --git a/include/asm-x86_64/kexec.h b/include/asm-x86_64/kexec.h
new file mode 100644
index 0000000..42d2ff1
--- /dev/null
+++ b/include/asm-x86_64/kexec.h
@@ -0,0 +1,33 @@
+#ifndef _X86_64_KEXEC_H
+#define _X86_64_KEXEC_H
+
+#include <asm/page.h>
+#include <asm/proto.h>
+
+/*
+ * KEXEC_SOURCE_MEMORY_LIMIT maximum page get_free_page can return.
+ * I.e. Maximum page that is mapped directly into kernel memory,
+ * and kmap is not required.
+ *
+ * So far x86_64 is limited to 40 physical address bits.
+ */
+
+/* Maximum physical address we can use pages from */
+#define KEXEC_SOURCE_MEMORY_LIMIT      (0xFFFFFFFFFFUL)
+/* Maximum address we can reach in physical address mode */
+#define KEXEC_DESTINATION_MEMORY_LIMIT (0xFFFFFFFFFFUL)
+/* Maximum address we can use for the control pages */
+#define KEXEC_CONTROL_MEMORY_LIMIT     (0xFFFFFFFFFFUL)
+
+/* Allocate one page for the pdp and the second for the code */
+#define KEXEC_CONTROL_CODE_SIZE  (4096UL + 4096UL)
+
+/* The native architecture */
+#define KEXEC_ARCH KEXEC_ARCH_X86_64
+
+#define MAX_NOTE_BYTES 1024
+typedef u32 note_buf_t[MAX_NOTE_BYTES/4];
+
+extern note_buf_t crash_notes[];
+
+#endif /* _X86_64_KEXEC_H */
diff --git a/include/asm-x86_64/kprobes.h b/include/asm-x86_64/kprobes.h
index bfea52d..6d6d883 100644
--- a/include/asm-x86_64/kprobes.h
+++ b/include/asm-x86_64/kprobes.h
@@ -38,6 +38,9 @@
 	: (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR)))
 
 #define JPROBE_ENTRY(pentry)	(kprobe_opcode_t *)pentry
+#define ARCH_SUPPORTS_KRETPROBES
+
+void kretprobe_trampoline(void);
 
 /* Architecture specific copy of original instruction*/
 struct arch_specific_insn {
diff --git a/include/asm-x86_64/mmzone.h b/include/asm-x86_64/mmzone.h
index d95b7c2..7684137 100644
--- a/include/asm-x86_64/mmzone.h
+++ b/include/asm-x86_64/mmzone.h
@@ -6,7 +6,7 @@
 
 #include <linux/config.h>
 
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
 
 #define VIRTUAL_BUG_ON(x) 
 
@@ -30,27 +30,23 @@
 	return nid; 
 } 
 
-#define pfn_to_nid(pfn) phys_to_nid((unsigned long)(pfn) << PAGE_SHIFT)
-
-#define kvaddr_to_nid(kaddr)	phys_to_nid(__pa(kaddr))
 #define NODE_DATA(nid)		(node_data[nid])
 
-#define node_mem_map(nid)	(NODE_DATA(nid)->node_mem_map)
-
-#define node_mem_map(nid)	(NODE_DATA(nid)->node_mem_map)
 #define node_start_pfn(nid)	(NODE_DATA(nid)->node_start_pfn)
 #define node_end_pfn(nid)       (NODE_DATA(nid)->node_start_pfn + \
 				 NODE_DATA(nid)->node_spanned_pages)
 
-#define local_mapnr(kvaddr) \
-	( (__pa(kvaddr) >> PAGE_SHIFT) - node_start_pfn(kvaddr_to_nid(kvaddr)) )
+#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))
 
 /* AK: this currently doesn't deal with invalid addresses. We'll see 
    if the 2.5 kernel doesn't pass them
    (2.4 used to). */
 #define pfn_to_page(pfn) ({ \
 	int nid = phys_to_nid(((unsigned long)(pfn)) << PAGE_SHIFT); 	\
-	((pfn) - node_start_pfn(nid)) + node_mem_map(nid);		\
+	((pfn) - node_start_pfn(nid)) + NODE_DATA(nid)->node_mem_map;	\
 })
 
 #define page_to_pfn(page) \
@@ -60,4 +56,8 @@
 			({ u8 nid__ = pfn_to_nid(pfn); \
 			   nid__ != 0xff && (pfn) >= node_start_pfn(nid__) && (pfn) <= node_end_pfn(nid__); }))
 #endif
+
+#define local_mapnr(kvaddr) \
+	( (__pa(kvaddr) >> PAGE_SHIFT) - node_start_pfn(kvaddr_to_nid(kvaddr)) )
+#endif
 #endif
diff --git a/include/asm-x86_64/msr.h b/include/asm-x86_64/msr.h
index 513e52c..bc70023 100644
--- a/include/asm-x86_64/msr.h
+++ b/include/asm-x86_64/msr.h
@@ -57,11 +57,6 @@
      (val) = ((unsigned long)__a) | (((unsigned long)__d)<<32); \
 } while(0)
 
-#define rdpmc(counter,low,high) \
-     __asm__ __volatile__("rdpmc" \
-			  : "=a" (low), "=d" (high) \
-			  : "c" (counter))
-
 #define write_tsc(val1,val2) wrmsr(0x10, val1, val2)
 
 #define rdpmc(counter,low,high) \
diff --git a/include/asm-x86_64/page.h b/include/asm-x86_64/page.h
index f430480..4313187 100644
--- a/include/asm-x86_64/page.h
+++ b/include/asm-x86_64/page.h
@@ -28,6 +28,7 @@
 #define HPAGE_SIZE	((1UL) << HPAGE_SHIFT)
 #define HPAGE_MASK	(~(HPAGE_SIZE - 1))
 #define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
+#define ARCH_HAS_HUGETLB_CLEAN_STALE_PGTABLE
 
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
@@ -63,12 +64,14 @@
 #define __pgd(x) ((pgd_t) { (x) } )
 #define __pgprot(x)	((pgprot_t) { (x) } )
 
-#define __START_KERNEL		0xffffffff80100000UL
+#define __PHYSICAL_START	((unsigned long)CONFIG_PHYSICAL_START)
+#define __START_KERNEL		(__START_KERNEL_map + __PHYSICAL_START)
 #define __START_KERNEL_map	0xffffffff80000000UL
 #define __PAGE_OFFSET           0xffff810000000000UL
 
 #else
-#define __START_KERNEL		0xffffffff80100000
+#define __PHYSICAL_START	CONFIG_PHYSICAL_START
+#define __START_KERNEL		(__START_KERNEL_map + __PHYSICAL_START)
 #define __START_KERNEL_map	0xffffffff80000000
 #define __PAGE_OFFSET           0xffff810000000000
 #endif /* !__ASSEMBLY__ */
@@ -118,7 +121,9 @@
 	  __pa(v); })
 
 #define __va(x)			((void *)((unsigned long)(x)+PAGE_OFFSET))
-#ifndef CONFIG_DISCONTIGMEM
+#define __boot_va(x)		__va(x)
+#define __boot_pa(x)		__pa(x)
+#ifdef CONFIG_FLATMEM
 #define pfn_to_page(pfn)	(mem_map + (pfn))
 #define page_to_pfn(page)	((unsigned long)((page) - mem_map))
 #define pfn_valid(pfn)		((pfn) < max_mapnr)
diff --git a/include/asm-x86_64/param.h b/include/asm-x86_64/param.h
index b707f05..40b1193 100644
--- a/include/asm-x86_64/param.h
+++ b/include/asm-x86_64/param.h
@@ -1,9 +1,11 @@
+#include <linux/config.h>
+
 #ifndef _ASMx86_64_PARAM_H
 #define _ASMx86_64_PARAM_H
 
 #ifdef __KERNEL__
-# define HZ            1000            /* Internal kernel timer frequency */
-# define USER_HZ       100          /* .. some user interfaces are in "ticks */
+# 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-x86_64/percpu.h b/include/asm-x86_64/percpu.h
index 415d73f..9c71855 100644
--- a/include/asm-x86_64/percpu.h
+++ b/include/asm-x86_64/percpu.h
@@ -39,7 +39,7 @@
 #define DEFINE_PER_CPU(type, name) \
     __typeof__(type) per_cpu__##name
 
-#define per_cpu(var, cpu)			(*((void)cpu, &per_cpu__##var))
+#define per_cpu(var, cpu)			(*((void)(cpu), &per_cpu__##var))
 #define __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 db2a0ef..4eec176 100644
--- a/include/asm-x86_64/pgtable.h
+++ b/include/asm-x86_64/pgtable.h
@@ -253,6 +253,7 @@
 extern inline int pte_write(pte_t pte)		{ return pte_val(pte) & _PAGE_RW; }
 static inline int pte_file(pte_t pte)		{ return pte_val(pte) & _PAGE_FILE; }
 
+#define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT)
 extern inline pte_t pte_rdprotect(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
 extern inline pte_t pte_exprotect(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
 extern inline pte_t pte_mkclean(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; }
@@ -263,6 +264,7 @@
 extern inline pte_t pte_mkdirty(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
 extern inline pte_t pte_mkyoung(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
 extern inline pte_t pte_mkwrite(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; }
+extern inline pte_t pte_mkhuge(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | __LARGE_PTE)); return pte; }
 
 struct vm_area_struct;
 
@@ -290,7 +292,6 @@
  */
 #define pgprot_noncached(prot)	(__pgprot(pgprot_val(prot) | _PAGE_PCD | _PAGE_PWT))
 
-#define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT) 
 static inline int pmd_large(pmd_t pte) { 
 	return (pmd_val(pte) & __LARGE_PTE) == __LARGE_PTE; 
 } 	
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h
index d641b19..106f666 100644
--- a/include/asm-x86_64/processor.h
+++ b/include/asm-x86_64/processor.h
@@ -160,16 +160,17 @@
 /*
  * User space process size. 47bits minus one guard page.
  */
-#define TASK_SIZE	(0x800000000000UL - 4096)
+#define TASK_SIZE64	(0x800000000000UL - 4096)
 
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
 #define IA32_PAGE_OFFSET ((current->personality & ADDR_LIMIT_3GB) ? 0xc0000000 : 0xFFFFe000)
-#define TASK_UNMAPPED_32 PAGE_ALIGN(IA32_PAGE_OFFSET/3)
-#define TASK_UNMAPPED_64 PAGE_ALIGN(TASK_SIZE/3) 
-#define TASK_UNMAPPED_BASE	\
-	(test_thread_flag(TIF_IA32) ? TASK_UNMAPPED_32 : TASK_UNMAPPED_64)  
+
+#define TASK_SIZE 		(test_thread_flag(TIF_IA32) ? IA32_PAGE_OFFSET : TASK_SIZE64)
+#define TASK_SIZE_OF(child) 	((test_tsk_thread_flag(child, TIF_IA32)) ? IA32_PAGE_OFFSET : TASK_SIZE64)
+
+#define TASK_UNMAPPED_BASE	PAGE_ALIGN(TASK_SIZE/3)
 
 /*
  * Size of io_bitmap.
@@ -279,6 +280,14 @@
 	set_fs(USER_DS);							 \
 } while(0) 
 
+#define get_debugreg(var, register)				\
+		__asm__("movq %%db" #register ", %0"		\
+			:"=r" (var))
+#define set_debugreg(value, register)			\
+		__asm__("movq %0,%%db" #register		\
+			: /* no output */			\
+			:"r" (value))
+
 struct task_struct;
 struct mm_struct;
 
diff --git a/include/asm-x86_64/ptrace.h b/include/asm-x86_64/ptrace.h
index 5bbc8d3..ca6f15f 100644
--- a/include/asm-x86_64/ptrace.h
+++ b/include/asm-x86_64/ptrace.h
@@ -82,6 +82,7 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__) 
 #define user_mode(regs) (!!((regs)->cs & 3))
+#define user_mode_vm(regs) user_mode(regs)
 #define instruction_pointer(regs) ((regs)->rip)
 extern unsigned long profile_pc(struct pt_regs *regs);
 void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
diff --git a/include/asm-x86_64/smp.h b/include/asm-x86_64/smp.h
index 96844fe..aeb1b73 100644
--- a/include/asm-x86_64/smp.h
+++ b/include/asm-x86_64/smp.h
@@ -43,6 +43,8 @@
 extern void smp_alloc_memory(void);
 extern volatile unsigned long smp_invalidate_needed;
 extern int pic_mode;
+extern void lock_ipi_call_lock(void);
+extern void unlock_ipi_call_lock(void);
 extern int smp_num_siblings;
 extern void smp_flush_tlb(void);
 extern void smp_message_irq(int cpl, void *dev_id, struct pt_regs *regs);
@@ -68,7 +70,7 @@
 	return cpus_weight(cpu_callout_map);
 }
 
-#define __smp_processor_id() read_pda(cpunumber)
+#define raw_smp_processor_id() read_pda(cpunumber)
 
 extern __inline int hard_smp_processor_id(void)
 {
@@ -77,6 +79,8 @@
 }
 
 extern int safe_smp_processor_id(void);
+extern int __cpu_disable(void);
+extern void __cpu_die(unsigned int cpu);
 
 #endif /* !ASSEMBLY */
 
diff --git a/include/asm-x86_64/sparsemem.h b/include/asm-x86_64/sparsemem.h
new file mode 100644
index 0000000..dabb167
--- /dev/null
+++ b/include/asm-x86_64/sparsemem.h
@@ -0,0 +1,26 @@
+#ifndef _ASM_X86_64_SPARSEMEM_H
+#define _ASM_X86_64_SPARSEMEM_H 1
+
+#ifdef CONFIG_SPARSEMEM
+
+/*
+ * generic non-linear memory support:
+ *
+ * 1) we will not split memory into more chunks than will fit into the flags
+ *    field of the struct page
+ *
+ * SECTION_SIZE_BITS		2^n: size of each section
+ * MAX_PHYSADDR_BITS		2^n: max size of physical address space
+ * MAX_PHYSMEM_BITS		2^n: how much memory we can have in that space
+ *
+ */
+
+#define SECTION_SIZE_BITS	27 /* matt - 128 is convenient right now */
+#define MAX_PHYSADDR_BITS	40
+#define MAX_PHYSMEM_BITS	40
+
+extern int early_pfn_to_nid(unsigned long pfn);
+
+#endif /* CONFIG_SPARSEMEM */
+
+#endif /* _ASM_X86_64_SPARSEMEM_H */
diff --git a/include/asm-x86_64/suspend.h b/include/asm-x86_64/suspend.h
index ec74580..bb9f405 100644
--- a/include/asm-x86_64/suspend.h
+++ b/include/asm-x86_64/suspend.h
@@ -16,7 +16,7 @@
 struct saved_context {
   	u16 ds, es, fs, gs, ss;
 	unsigned long gs_base, gs_kernel_base, fs_base;
-	unsigned long cr0, cr2, cr3, cr4;
+	unsigned long cr0, cr2, cr3, cr4, cr8;
 	u16 gdt_pad;
 	u16 gdt_limit;
 	unsigned long gdt_base;
diff --git a/include/asm-x86_64/thread_info.h b/include/asm-x86_64/thread_info.h
index f4b3b24..08eb6e4 100644
--- a/include/asm-x86_64/thread_info.h
+++ b/include/asm-x86_64/thread_info.h
@@ -29,7 +29,7 @@
 	__u32			flags;		/* low level flags */
 	__u32			status;		/* thread synchronous flags */
 	__u32			cpu;		/* current CPU */
-	int 			preempt_count;
+	int 			preempt_count;	/* 0 => preemptable, <0 => BUG */
 
 	mm_segment_t		addr_limit;	
 	struct restart_block    restart_block;
diff --git a/include/asm-x86_64/timex.h b/include/asm-x86_64/timex.h
index 34f31a1..24ecf6a 100644
--- a/include/asm-x86_64/timex.h
+++ b/include/asm-x86_64/timex.h
@@ -26,6 +26,9 @@
 
 extern unsigned int cpu_khz;
 
+extern int read_current_timer(unsigned long *timer_value);
+#define ARCH_HAS_READ_CURRENT_TIMER	1
+
 extern struct vxtime_data vxtime;
 
 #endif
diff --git a/include/asm-x86_64/topology.h b/include/asm-x86_64/topology.h
index 67f24e0..c1bc3fa 100644
--- a/include/asm-x86_64/topology.h
+++ b/include/asm-x86_64/topology.h
@@ -3,7 +3,7 @@
 
 #include <linux/config.h>
 
-#ifdef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_NUMA
 
 #include <asm/mpspec.h>
 #include <asm/bitops.h>
@@ -13,8 +13,8 @@
 extern cpumask_t cpu_online_map;
 
 extern unsigned char cpu_to_node[];
+extern unsigned char pci_bus_to_node[];
 extern cpumask_t     node_to_cpumask[];
-extern cpumask_t pci_bus_to_cpumask[];
 
 #ifdef CONFIG_ACPI_NUMA
 extern int __node_distance(int, int);
@@ -26,18 +26,9 @@
 #define parent_node(node)		(node)
 #define node_to_first_cpu(node) 	(__ffs(node_to_cpumask[node]))
 #define node_to_cpumask(node)		(node_to_cpumask[node])
+#define pcibus_to_node(bus)		pci_bus_to_node[(bus)->number]
+#define pcibus_to_cpumask(bus)		node_to_cpumask(pcibus_to_node(bus));
 
-static inline cpumask_t __pcibus_to_cpumask(int bus)
-{
-	cpumask_t busmask = pci_bus_to_cpumask[bus];
-	cpumask_t online = cpu_online_map;
-	cpumask_t res;
-	cpus_and(res, busmask, online);
-	return res;
-}
-#define pcibus_to_cpumask(bus) __pcibus_to_cpumask(bus->number)
-
-#ifdef CONFIG_NUMA
 /* sched_domains SD_NODE_INIT for x86_64 machines */
 #define SD_NODE_INIT (struct sched_domain) {		\
 	.span			= CPU_MASK_NONE,	\
@@ -48,18 +39,21 @@
 	.busy_factor		= 32,			\
 	.imbalance_pct		= 125,			\
 	.cache_hot_time		= (10*1000000),		\
-	.cache_nice_tries	= 1,			\
+	.cache_nice_tries	= 2,			\
+	.busy_idx		= 3,			\
+	.idle_idx		= 2,			\
+	.newidle_idx		= 0, 			\
+	.wake_idx		= 1,			\
+	.forkexec_idx		= 1,			\
 	.per_cpu_gain		= 100,			\
 	.flags			= SD_LOAD_BALANCE	\
-				| SD_BALANCE_NEWIDLE	\
+				| SD_BALANCE_FORK	\
 				| SD_BALANCE_EXEC	\
-				| SD_WAKE_IDLE		\
 				| SD_WAKE_BALANCE,	\
 	.last_balance		= jiffies,		\
 	.balance_interval	= 1,			\
 	.nr_balance_failed	= 0,			\
 }
-#endif
 
 #endif
 
diff --git a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
index 3c9af6f..6560439 100644
--- a/include/asm-x86_64/unistd.h
+++ b/include/asm-x86_64/unistd.h
@@ -552,7 +552,7 @@
 #define __NR_mq_getsetattr 	245
 __SYSCALL(__NR_mq_getsetattr, sys_mq_getsetattr)
 #define __NR_kexec_load 	246
-__SYSCALL(__NR_kexec_load, sys_ni_syscall)
+__SYSCALL(__NR_kexec_load, sys_kexec_load)
 #define __NR_waitid		247
 __SYSCALL(__NR_waitid, sys_waitid)
 #define __NR_add_key		248
@@ -561,8 +561,12 @@
 __SYSCALL(__NR_request_key, sys_request_key)
 #define __NR_keyctl		250
 __SYSCALL(__NR_keyctl, sys_keyctl)
+#define __NR_ioprio_set		251
+__SYSCALL(__NR_ioprio_set, sys_ioprio_set)
+#define __NR_ioprio_get		252
+__SYSCALL(__NR_ioprio_get, sys_ioprio_get)
 
-#define __NR_syscall_max __NR_keyctl
+#define __NR_syscall_max __NR_ioprio_get
 #ifndef __NO_STUBS
 
 /* user-visible error numbers are in the range -1 - -4095 */
diff --git a/include/asm-xtensa/a.out.h b/include/asm-xtensa/a.out.h
new file mode 100644
index 0000000..3be701d
--- /dev/null
+++ b/include/asm-xtensa/a.out.h
@@ -0,0 +1,33 @@
+/*
+ * include/asm-xtensa/addrspace.h
+ *
+ * Dummy a.out file. Xtensa does not support the a.out format, but the kernel
+ * seems to depend on it.
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_A_OUT_H
+#define _XTENSA_A_OUT_H
+
+/* Note: the kernel needs the a.out definitions, even if only ELF is used. */
+
+#define STACK_TOP	TASK_SIZE
+
+struct exec
+{
+  unsigned long a_info;
+  unsigned a_text;
+  unsigned a_data;
+  unsigned a_bss;
+  unsigned a_syms;
+  unsigned a_entry;
+  unsigned a_trsize;
+  unsigned a_drsize;
+};
+
+#endif /* _XTENSA_A_OUT_H */
diff --git a/include/asm-xtensa/atomic.h b/include/asm-xtensa/atomic.h
new file mode 100644
index 0000000..d72bcb3
--- /dev/null
+++ b/include/asm-xtensa/atomic.h
@@ -0,0 +1,272 @@
+/*
+ * include/asm-xtensa/atomic.h
+ *
+ * Atomic operations that C can't guarantee us.  Useful for resource counting..
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_ATOMIC_H
+#define _XTENSA_ATOMIC_H
+
+#include <linux/config.h>
+#include <linux/stringify.h>
+
+typedef struct { volatile int counter; } atomic_t;
+
+#ifdef __KERNEL__
+#include <asm/processor.h>
+#include <asm/system.h>
+
+#define ATOMIC_INIT(i)	( (atomic_t) { (i) } )
+
+/*
+ * This Xtensa implementation assumes that the right mechanism
+ * for exclusion is for locking interrupts to level 1.
+ *
+ * Locking interrupts looks like this:
+ *
+ *    rsil a15, 1
+ *    <code>
+ *    wsr  a15, PS
+ *    rsync
+ *
+ * Note that a15 is used here because the register allocation
+ * done by the compiler is not guaranteed and a window overflow
+ * may not occur between the rsil and wsr instructions. By using
+ * a15 in the rsil, the machine is guaranteed to be in a state
+ * where no register reference will cause an overflow.
+ */
+
+/**
+ * atomic_read - read atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically reads the value of @v.
+ */
+#define atomic_read(v)		((v)->counter)
+
+/**
+ * atomic_set - set atomic variable
+ * @v: pointer of type atomic_t
+ * @i: required value
+ *
+ * Atomically sets the value of @v to @i.
+ */
+#define atomic_set(v,i)		((v)->counter = (i))
+
+/**
+ * atomic_add - add integer to atomic variable
+ * @i: integer value to add
+ * @v: pointer of type atomic_t
+ *
+ * Atomically adds @i to @v.
+ */
+extern __inline__ void atomic_add(int i, atomic_t * v)
+{
+    unsigned int vval;
+
+    __asm__ __volatile__(
+	"rsil    a15, "__stringify(LOCKLEVEL)"\n\t"
+	"l32i    %0, %2, 0              \n\t"
+	"add     %0, %0, %1             \n\t"
+	"s32i    %0, %2, 0              \n\t"
+	"wsr     a15, "__stringify(PS)"       \n\t"
+	"rsync                          \n"
+	: "=&a" (vval)
+	: "a" (i), "a" (v)
+	: "a15", "memory"
+	);
+}
+
+/**
+ * atomic_sub - subtract the atomic variable
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ *
+ * Atomically subtracts @i from @v.
+ */
+extern __inline__ void atomic_sub(int i, atomic_t *v)
+{
+    unsigned int vval;
+
+    __asm__ __volatile__(
+	"rsil    a15, "__stringify(LOCKLEVEL)"\n\t"
+	"l32i    %0, %2, 0              \n\t"
+	"sub     %0, %0, %1             \n\t"
+	"s32i    %0, %2, 0              \n\t"
+	"wsr     a15, "__stringify(PS)"       \n\t"
+	"rsync                          \n"
+	: "=&a" (vval)
+	: "a" (i), "a" (v)
+	: "a15", "memory"
+	);
+}
+
+/*
+ * We use atomic_{add|sub}_return to define other functions.
+ */
+
+extern __inline__ int atomic_add_return(int i, atomic_t * v)
+{
+     unsigned int vval;
+
+    __asm__ __volatile__(
+	"rsil    a15,"__stringify(LOCKLEVEL)"\n\t"
+	"l32i    %0, %2, 0             \n\t"
+	"add     %0, %0, %1            \n\t"
+	"s32i    %0, %2, 0             \n\t"
+	"wsr     a15, "__stringify(PS)"      \n\t"
+	"rsync                         \n"
+	: "=&a" (vval)
+	: "a" (i), "a" (v)
+	: "a15", "memory"
+	);
+
+    return vval;
+}
+
+extern __inline__ int atomic_sub_return(int i, atomic_t * v)
+{
+    unsigned int vval;
+
+    __asm__ __volatile__(
+	"rsil    a15,"__stringify(LOCKLEVEL)"\n\t"
+	"l32i    %0, %2, 0             \n\t"
+	"sub     %0, %0, %1            \n\t"
+	"s32i    %0, %2, 0             \n\t"
+	"wsr     a15, "__stringify(PS)"       \n\t"
+	"rsync                         \n"
+	: "=&a" (vval)
+	: "a" (i), "a" (v)
+	: "a15", "memory"
+	);
+
+    return vval;
+}
+
+/**
+ * atomic_sub_and_test - subtract value from variable and test result
+ * @i: integer value to subtract
+ * @v: pointer of type atomic_t
+ *
+ * Atomically subtracts @i from @v and returns
+ * true if the result is zero, or false for all
+ * other cases.
+ */
+#define atomic_sub_and_test(i,v) (atomic_sub_return((i),(v)) == 0)
+
+/**
+ * atomic_inc - increment atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1.
+ */
+#define atomic_inc(v) atomic_add(1,(v))
+
+/**
+ * atomic_inc - increment atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1.
+ */
+#define atomic_inc_return(v) atomic_add_return(1,(v))
+
+/**
+ * atomic_dec - decrement atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1.
+ */
+#define atomic_dec(v) atomic_sub(1,(v))
+
+/**
+ * atomic_dec_return - decrement atomic variable
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1.
+ */
+#define atomic_dec_return(v) atomic_sub_return(1,(v))
+
+/**
+ * atomic_dec_and_test - decrement and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically decrements @v by 1 and
+ * returns true if the result is 0, or false for all other
+ * cases.
+ */
+#define atomic_dec_and_test(v) (atomic_sub_return(1,(v)) == 0)
+
+/**
+ * atomic_inc_and_test - increment and test
+ * @v: pointer of type atomic_t
+ *
+ * Atomically increments @v by 1
+ * and returns true if the result is zero, or false for all
+ * other cases.
+ */
+#define atomic_inc_and_test(v) (atomic_add_return(1,(v)) == 0)
+
+/**
+ * atomic_add_negative - add and test if negative
+ * @v: pointer of type atomic_t
+ * @i: integer value to add
+ *
+ * Atomically adds @i to @v and returns true
+ * if the result is negative, or false when
+ * result is greater than or equal to zero.
+ */
+#define atomic_add_negative(i,v) (atomic_add_return((i),(v)) < 0)
+
+
+extern __inline__ void atomic_clear_mask(unsigned int mask, atomic_t *v)
+{
+    unsigned int all_f = -1;
+    unsigned int vval;
+
+    __asm__ __volatile__(
+	"rsil    a15,"__stringify(LOCKLEVEL)"\n\t"
+	"l32i    %0, %2, 0             \n\t"
+	"xor     %1, %4, %3            \n\t"
+	"and     %0, %0, %4            \n\t"
+	"s32i    %0, %2, 0             \n\t"
+	"wsr     a15, "__stringify(PS)"      \n\t"
+	"rsync                         \n"
+	: "=&a" (vval), "=a" (mask)
+	: "a" (v), "a" (all_f), "1" (mask)
+	: "a15", "memory"
+	);
+}
+
+extern __inline__ void atomic_set_mask(unsigned int mask, atomic_t *v)
+{
+    unsigned int vval;
+
+    __asm__ __volatile__(
+	"rsil    a15,"__stringify(LOCKLEVEL)"\n\t"
+	"l32i    %0, %2, 0             \n\t"
+	"or      %0, %0, %1            \n\t"
+	"s32i    %0, %2, 0             \n\t"
+	"wsr     a15, "__stringify(PS)"       \n\t"
+	"rsync                         \n"
+	: "=&a" (vval)
+	: "a" (mask), "a" (v)
+	: "a15", "memory"
+	);
+}
+
+/* Atomic operations are already serializing */
+#define smp_mb__before_atomic_dec()	barrier()
+#define smp_mb__after_atomic_dec()	barrier()
+#define smp_mb__before_atomic_inc()	barrier()
+#define smp_mb__after_atomic_inc()	barrier()
+
+#endif /* __KERNEL__ */
+
+#endif /* _XTENSA_ATOMIC_H */
+
diff --git a/include/asm-xtensa/bitops.h b/include/asm-xtensa/bitops.h
new file mode 100644
index 0000000..d395ef2
--- /dev/null
+++ b/include/asm-xtensa/bitops.h
@@ -0,0 +1,446 @@
+/*
+ * include/asm-xtensa/bitops.h
+ *
+ * Atomic operations that C can't guarantee us.Useful for resource counting etc.
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_BITOPS_H
+#define _XTENSA_BITOPS_H
+
+#ifdef __KERNEL__
+
+#include <asm/processor.h>
+#include <asm/byteorder.h>
+#include <asm/system.h>
+
+#ifdef CONFIG_SMP
+# error SMP not supported on this architecture
+#endif
+
+static __inline__ void set_bit(int nr, volatile void * addr)
+{
+	unsigned long mask = 1 << (nr & 0x1f);
+	unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+	unsigned long flags;
+
+	local_irq_save(flags);
+	*a |= mask;
+	local_irq_restore(flags);
+}
+
+static __inline__ void __set_bit(int nr, volatile unsigned long * addr)
+{
+	unsigned long mask = 1 << (nr & 0x1f);
+	unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+
+	*a |= mask;
+}
+
+static __inline__ void clear_bit(int nr, volatile void * addr)
+{
+	unsigned long mask = 1 << (nr & 0x1f);
+	unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+	unsigned long flags;
+
+	local_irq_save(flags);
+	*a &= ~mask;
+	local_irq_restore(flags);
+}
+
+static __inline__ void __clear_bit(int nr, volatile unsigned long *addr)
+{
+	unsigned long mask = 1 << (nr & 0x1f);
+	unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+
+	*a &= ~mask;
+}
+
+/*
+ * clear_bit() doesn't provide any barrier for the compiler.
+ */
+
+#define smp_mb__before_clear_bit()	barrier()
+#define smp_mb__after_clear_bit()	barrier()
+
+static __inline__ void change_bit(int nr, volatile void * addr)
+{
+	unsigned long mask = 1 << (nr & 0x1f);
+	unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+	unsigned long flags;
+
+	local_irq_save(flags);
+	*a ^= mask;
+	local_irq_restore(flags);
+}
+
+static __inline__ void __change_bit(int nr, volatile void * addr)
+{
+	unsigned long mask = 1 << (nr & 0x1f);
+	unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+
+	*a ^= mask;
+}
+
+static __inline__ int test_and_set_bit(int nr, volatile void * addr)
+{
+  	unsigned long retval;
+	unsigned long mask = 1 << (nr & 0x1f);
+	unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+	unsigned long flags;
+
+	local_irq_save(flags);
+	retval = (mask & *a) != 0;
+	*a |= mask;
+	local_irq_restore(flags);
+
+	return retval;
+}
+
+static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
+{
+  	unsigned long retval;
+	unsigned long mask = 1 << (nr & 0x1f);
+	unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+
+	retval = (mask & *a) != 0;
+	*a |= mask;
+
+	return retval;
+}
+
+static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
+{
+  	unsigned long retval;
+	unsigned long mask = 1 << (nr & 0x1f);
+	unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+	unsigned long flags;
+
+	local_irq_save(flags);
+	retval = (mask & *a) != 0;
+	*a &= ~mask;
+	local_irq_restore(flags);
+
+	return retval;
+}
+
+static __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
+{
+	unsigned long mask = 1 << (nr & 0x1f);
+	unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+  	unsigned long old = *a;
+
+	*a = old & ~mask;
+	return (old & mask) != 0;
+}
+
+static __inline__ int test_and_change_bit(int nr, volatile void * addr)
+{
+  	unsigned long retval;
+	unsigned long mask = 1 << (nr & 0x1f);
+	unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	retval = (mask & *a) != 0;
+	*a ^= mask;
+	local_irq_restore(flags);
+
+	return retval;
+}
+
+/*
+ * non-atomic version; can be reordered
+ */
+
+static __inline__ int __test_and_change_bit(int nr, volatile void *addr)
+{
+	unsigned long mask = 1 << (nr & 0x1f);
+	unsigned long *a = ((unsigned long *)addr) + (nr >> 5);
+	unsigned long old = *a;
+
+	*a = old ^ mask;
+	return (old & mask) != 0;
+}
+
+static __inline__ int test_bit(int nr, const volatile void *addr)
+{
+	return 1UL & (((const volatile unsigned int *)addr)[nr>>5] >> (nr&31));
+}
+
+#if XCHAL_HAVE_NSAU
+
+static __inline__ int __cntlz (unsigned long x)
+{
+	int lz;
+	asm ("nsau %0, %1" : "=r" (lz) : "r" (x));
+	return 31 - lz;
+}
+
+#else
+
+static __inline__ int __cntlz (unsigned long x)
+{
+	unsigned long sum, x1, x2, x4, x8, x16;
+	x1  = x & 0xAAAAAAAA;
+	x2  = x & 0xCCCCCCCC;
+	x4  = x & 0xF0F0F0F0;
+	x8  = x & 0xFF00FF00;
+	x16 = x & 0xFFFF0000;
+	sum = x2 ? 2 : 0;
+	sum += (x16 != 0) * 16;
+	sum += (x8 != 0) * 8;
+	sum += (x4 != 0) * 4;
+	sum += (x1 != 0);
+
+	return sum;
+}
+
+#endif
+
+/*
+ * ffz: Find first zero in word. Undefined if no zero exists.
+ * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
+ */
+
+static __inline__ int ffz(unsigned long x)
+{
+	if ((x = ~x) == 0)
+		return 32;
+	return __cntlz(x & -x);
+}
+
+/*
+ * __ffs: Find first bit set in word. Return 0 for bit 0
+ */
+
+static __inline__ int __ffs(unsigned long x)
+{
+	return __cntlz(x & -x);
+}
+
+/*
+ * ffs: Find first bit set in word. This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+
+static __inline__ int ffs(unsigned long x)
+{
+	return __cntlz(x & -x) + 1;
+}
+
+/*
+ * fls: Find last (most-significant) bit set in word.
+ * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
+ */
+
+static __inline__ int fls (unsigned int x)
+{
+	return __cntlz(x);
+}
+
+static __inline__ int
+find_next_bit(const unsigned long *addr, int size, int offset)
+{
+	const unsigned long *p = addr + (offset >> 5);
+	unsigned long result = offset & ~31UL;
+	unsigned long tmp;
+
+	if (offset >= size)
+		return size;
+	size -= result;
+	offset &= 31UL;
+	if (offset) {
+		tmp = *p++;
+		tmp &= ~0UL << offset;
+		if (size < 32)
+			goto found_first;
+		if (tmp)
+			goto found_middle;
+		size -= 32;
+		result += 32;
+	}
+	while (size >= 32) {
+		if ((tmp = *p++) != 0)
+			goto found_middle;
+		result += 32;
+		size -= 32;
+	}
+	if (!size)
+		return result;
+	tmp = *p;
+
+found_first:
+	tmp &= ~0UL >> (32 - size);
+	if (tmp == 0UL)	/* Are any bits set? */
+		return result + size;	/* Nope. */
+found_middle:
+	return result + __ffs(tmp);
+}
+
+/**
+ * find_first_bit - find the first set bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit-number of the first set bit, not the number of the byte
+ * containing a bit.
+ */
+
+#define find_first_bit(addr, size) \
+        find_next_bit((addr), (size), 0)
+
+static __inline__ int
+find_next_zero_bit(const unsigned long *addr, int size, int offset)
+{
+	const unsigned long *p = addr + (offset >> 5);
+	unsigned long result = offset & ~31UL;
+	unsigned long tmp;
+
+	if (offset >= size)
+		return size;
+	size -= result;
+	offset &= 31UL;
+	if (offset) {
+		tmp = *p++;
+		tmp |= ~0UL >> (32-offset);
+		if (size < 32)
+			goto found_first;
+		if (~tmp)
+			goto found_middle;
+		size -= 32;
+		result += 32;
+	}
+	while (size & ~31UL) {
+		if (~(tmp = *p++))
+			goto found_middle;
+		result += 32;
+		size -= 32;
+	}
+	if (!size)
+		return result;
+	tmp = *p;
+
+found_first:
+	tmp |= ~0UL << size;
+found_middle:
+	return result + ffz(tmp);
+}
+
+#define find_first_zero_bit(addr, size) \
+        find_next_zero_bit((addr), (size), 0)
+
+#ifdef __XTENSA_EL__
+# define ext2_set_bit(nr,addr) __test_and_set_bit((nr), (addr))
+# define ext2_set_bit_atomic(lock,nr,addr) test_and_set_bit((nr),(addr))
+# define ext2_clear_bit(nr,addr) __test_and_clear_bit((nr), (addr))
+# define ext2_clear_bit_atomic(lock,nr,addr) test_and_clear_bit((nr),(addr))
+# define ext2_test_bit(nr,addr) test_bit((nr), (addr))
+# define ext2_find_first_zero_bit(addr, size) find_first_zero_bit((addr),(size))
+# define ext2_find_next_zero_bit(addr, size, offset) \
+                find_next_zero_bit((addr), (size), (offset))
+#elif defined(__XTENSA_EB__)
+# define ext2_set_bit(nr,addr) __test_and_set_bit((nr) ^ 0x18, (addr))
+# define ext2_set_bit_atomic(lock,nr,addr) test_and_set_bit((nr) ^ 0x18, (addr))
+# define ext2_clear_bit(nr,addr) __test_and_clear_bit((nr) ^ 18, (addr))
+# define ext2_clear_bit_atomic(lock,nr,addr) test_and_clear_bit((nr)^0x18,(addr))
+# define ext2_test_bit(nr,addr) test_bit((nr) ^ 0x18, (addr))
+# define ext2_find_first_zero_bit(addr, size) \
+        ext2_find_next_zero_bit((addr), (size), 0)
+
+static __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
+{
+	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
+	unsigned long result = offset & ~31UL;
+	unsigned long tmp;
+
+	if (offset >= size)
+		return size;
+	size -= result;
+	offset &= 31UL;
+	if(offset) {
+		/* We hold the little endian value in tmp, but then the
+		 * shift is illegal. So we could keep a big endian value
+		 * in tmp, like this:
+		 *
+		 * tmp = __swab32(*(p++));
+		 * tmp |= ~0UL >> (32-offset);
+		 *
+		 * but this would decrease preformance, so we change the
+		 * shift:
+		 */
+		tmp = *(p++);
+		tmp |= __swab32(~0UL >> (32-offset));
+		if(size < 32)
+			goto found_first;
+		if(~tmp)
+			goto found_middle;
+		size -= 32;
+		result += 32;
+	}
+	while(size & ~31UL) {
+		if(~(tmp = *(p++)))
+			goto found_middle;
+		result += 32;
+		size -= 32;
+	}
+	if(!size)
+		return result;
+	tmp = *p;
+
+found_first:
+	/* tmp is little endian, so we would have to swab the shift,
+	 * see above. But then we have to swab tmp below for ffz, so
+	 * we might as well do this here.
+	 */
+	return result + ffz(__swab32(tmp) | (~0UL << size));
+found_middle:
+	return result + ffz(__swab32(tmp));
+}
+
+#else
+# error processor byte order undefined!
+#endif
+
+
+#define hweight32(x)	generic_hweight32(x)
+#define hweight16(x)	generic_hweight16(x)
+#define hweight8(x)	generic_hweight8(x)
+
+/*
+ * Find the first bit set in a 140-bit bitmap.
+ * The first 100 bits are unlikely to be set.
+ */
+
+static inline int sched_find_first_bit(const unsigned long *b)
+{
+	if (unlikely(b[0]))
+		return __ffs(b[0]);
+	if (unlikely(b[1]))
+		return __ffs(b[1]) + 32;
+	if (unlikely(b[2]))
+		return __ffs(b[2]) + 64;
+	if (b[3])
+		return __ffs(b[3]) + 96;
+	return __ffs(b[4]) + 128;
+}
+
+
+/* Bitmap functions for the minix filesystem.  */
+
+#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
+#define minix_set_bit(nr,addr) set_bit(nr,addr)
+#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
+#define minix_test_bit(nr,addr) test_bit(nr,addr)
+#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
+
+#endif	/* __KERNEL__ */
+
+#endif	/* _XTENSA_BITOPS_H */
diff --git a/include/asm-xtensa/bootparam.h b/include/asm-xtensa/bootparam.h
new file mode 100644
index 0000000..9983f2c
--- /dev/null
+++ b/include/asm-xtensa/bootparam.h
@@ -0,0 +1,61 @@
+/*
+ * include/asm-xtensa/bootparam.h
+ *
+ * Definition of the Linux/Xtensa boot parameter structure
+ *
+ * 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) 2001 - 2005  Tensilica Inc.
+ *
+ * (Concept borrowed from the 68K port)
+ */
+
+#ifndef _XTENSA_BOOTPARAM_H
+#define _XTENSA_BOOTPARAM_H
+
+#define BP_VERSION 0x0001
+
+#define BP_TAG_COMMAND_LINE	0x1001	/* command line (0-terminated string)*/
+#define BP_TAG_INITRD		0x1002	/* ramdisk addr and size (bp_meminfo) */
+#define BP_TAG_MEMORY		0x1003	/* memory addr and size (bp_meminfo) */
+#define BP_TAG_SERIAL_BAUSRATE	0x1004	/* baud rate of current console. */
+#define BP_TAG_SERIAL_PORT	0x1005	/* serial device of current console */
+
+#define BP_TAG_FIRST		0x7B0B  /* first tag with a version number */
+#define BP_TAG_LAST 		0x7E0B	/* last tag */
+
+#ifndef __ASSEMBLY__
+
+/* All records are aligned to 4 bytes */
+
+typedef struct bp_tag {
+  unsigned short id;		/* tag id */
+  unsigned short size;		/* size of this record excluding the structure*/
+  unsigned long data[0];	/* data */
+} bp_tag_t;
+
+typedef struct meminfo {
+  unsigned long type;
+  unsigned long start;
+  unsigned long end;
+} meminfo_t;
+
+#define SYSMEM_BANKS_MAX 5
+
+#define MEMORY_TYPE_CONVENTIONAL	0x1000
+#define MEMORY_TYPE_NONE		0x2000
+
+typedef struct sysmem_info {
+  int nr_banks;
+  meminfo_t bank[SYSMEM_BANKS_MAX];
+} sysmem_info_t;
+
+extern sysmem_info_t sysmem;
+
+#endif
+#endif
+
+
+
diff --git a/include/asm-xtensa/bug.h b/include/asm-xtensa/bug.h
new file mode 100644
index 0000000..5670365
--- /dev/null
+++ b/include/asm-xtensa/bug.h
@@ -0,0 +1,41 @@
+/*
+ * include/asm-xtensa/bug.h
+ *
+ * Macros to cause a 'bug' message.
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_BUG_H
+#define _XTENSA_BUG_H
+
+#include <linux/stringify.h>
+
+#define ILL	__asm__ __volatile__ (".byte 0,0,0\n")
+
+#ifdef CONFIG_KALLSYMS
+# define BUG() do {							\
+	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__);		\
+	ILL;								\
+} while (0)
+#else
+# define BUG() do {							\
+	printk("kernel BUG!\n");					\
+      	ILL;								\
+} while (0)
+#endif
+
+#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
+#define PAGE_BUG(page) do {  BUG(); } while (0)
+#define WARN_ON(condition) do {						   \
+  if (unlikely((condition)!=0)) {					   \
+    printk ("Warning in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+      dump_stack();							   \
+  }									   \
+} while (0)
+
+#endif	/* _XTENSA_BUG_H */
diff --git a/include/asm-xtensa/bugs.h b/include/asm-xtensa/bugs.h
new file mode 100644
index 0000000..c422853
--- /dev/null
+++ b/include/asm-xtensa/bugs.h
@@ -0,0 +1,22 @@
+/*
+ * include/asm-xtensa/bugs.h
+ *
+ * This is included by init/main.c to check for architecture-dependent bugs.
+ *
+ * Xtensa processors don't have any bugs.  :)
+ *
+ * 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.
+ */
+
+#ifndef _XTENSA_BUGS_H
+#define _XTENSA_BUGS_H
+
+#include <asm/processor.h>
+
+static void __init check_bugs(void)
+{
+}
+
+#endif /* _XTENSA_BUGS_H */
diff --git a/include/asm-xtensa/byteorder.h b/include/asm-xtensa/byteorder.h
new file mode 100644
index 0000000..0b15525
--- /dev/null
+++ b/include/asm-xtensa/byteorder.h
@@ -0,0 +1,82 @@
+/*
+ * include/asm-xtensa/byteorder.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_BYTEORDER_H
+#define _XTENSA_BYTEORDER_H
+
+#include <asm/processor.h>
+#include <asm/types.h>
+
+static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
+{
+    __u32 res;
+    /* instruction sequence from Xtensa ISA release 2/2000 */
+    __asm__("ssai     8           \n\t"
+	    "srli     %0, %1, 16  \n\t"
+	    "src      %0, %0, %1  \n\t"
+	    "src      %0, %0, %0  \n\t"
+	    "src      %0, %1, %0  \n"
+	    : "=&a" (res)
+	    : "a" (x)
+	    );
+    return res;
+}
+
+static __inline__ __const__ __u16 ___arch__swab16(__u16 x)
+{
+    /* Given that 'short' values are signed (i.e., can be negative),
+     * we cannot assume that the upper 16-bits of the register are
+     * zero.  We are careful to mask values after shifting.
+     */
+
+    /* There exists an anomaly between xt-gcc and xt-xcc.  xt-gcc
+     * inserts an extui instruction after putting this function inline
+     * to ensure that it uses only the least-significant 16 bits of
+     * the result.  xt-xcc doesn't use an extui, but assumes the
+     * __asm__ macro follows convention that the upper 16 bits of an
+     * 'unsigned short' result are still zero.  This macro doesn't
+     * follow convention; indeed, it leaves garbage in the upport 16
+     * bits of the register.
+
+     * Declaring the temporary variables 'res' and 'tmp' to be 32-bit
+     * types while the return type of the function is a 16-bit type
+     * forces both compilers to insert exactly one extui instruction
+     * (or equivalent) to mask off the upper 16 bits. */
+
+    __u32 res;
+    __u32 tmp;
+
+    __asm__("extui    %1, %2, 8, 8\n\t"
+	    "slli     %0, %2, 8   \n\t"
+	    "or       %0, %0, %1  \n"
+	    : "=&a" (res), "=&a" (tmp)
+	    : "a" (x)
+	    );
+
+    return res;
+}
+
+#define __arch__swab32(x) ___arch__swab32(x)
+#define __arch__swab16(x) ___arch__swab16(x)
+
+#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+#  define __BYTEORDER_HAS_U64__
+#  define __SWAB_64_THRU_32__
+#endif
+
+#ifdef __XTENSA_EL__
+# include <linux/byteorder/little_endian.h>
+#elif defined(__XTENSA_EB__)
+# include <linux/byteorder/big_endian.h>
+#else
+# error processor byte order undefined!
+#endif
+
+#endif /* __ASM_XTENSA_BYTEORDER_H */
diff --git a/include/asm-xtensa/cache.h b/include/asm-xtensa/cache.h
new file mode 100644
index 0000000..5aae3f1
--- /dev/null
+++ b/include/asm-xtensa/cache.h
@@ -0,0 +1,32 @@
+/*
+ * include/asm-xtensa/cacheflush.h
+ *
+ * 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.
+ * 2 of the License, or (at your option) any later version.
+ *
+ * (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_CACHE_H
+#define _XTENSA_CACHE_H
+
+#include <xtensa/config/core.h>
+
+#if XCHAL_ICACHE_SIZE > 0
+# if (XCHAL_ICACHE_SIZE % (XCHAL_ICACHE_LINESIZE*XCHAL_ICACHE_WAYS*4)) != 0
+#  error cache configuration outside expected/supported range!
+# endif
+#endif
+
+#if XCHAL_DCACHE_SIZE > 0
+# if (XCHAL_DCACHE_SIZE % (XCHAL_DCACHE_LINESIZE*XCHAL_DCACHE_WAYS*4)) != 0
+#  error cache configuration outside expected/supported range!
+# endif
+#endif
+
+#define L1_CACHE_SHIFT		XCHAL_CACHE_LINEWIDTH_MAX
+#define L1_CACHE_BYTES		XCHAL_CACHE_LINESIZE_MAX
+
+#endif	/* _XTENSA_CACHE_H */
diff --git a/include/asm-xtensa/cacheflush.h b/include/asm-xtensa/cacheflush.h
new file mode 100644
index 0000000..44a36e0
--- /dev/null
+++ b/include/asm-xtensa/cacheflush.h
@@ -0,0 +1,122 @@
+/*
+ * include/asm-xtensa/cacheflush.h
+ *
+ * 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.
+ *
+ * (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_CACHEFLUSH_H
+#define _XTENSA_CACHEFLUSH_H
+
+#ifdef __KERNEL__
+
+#include <linux/mm.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+
+/*
+ * flush and invalidate data cache, invalidate instruction cache:
+ *
+ * __flush_invalidate_cache_all()
+ * __flush_invalidate_cache_range(from,sze)
+ *
+ * invalidate data or instruction cache:
+ *
+ * __invalidate_icache_all()
+ * __invalidate_icache_page(adr)
+ * __invalidate_dcache_page(adr)
+ * __invalidate_icache_range(from,size)
+ * __invalidate_dcache_range(from,size)
+ *
+ * flush data cache:
+ *
+ * __flush_dcache_page(adr)
+ *
+ * flush and invalidate data cache:
+ *
+ * __flush_invalidate_dcache_all()
+ * __flush_invalidate_dcache_page(adr)
+ * __flush_invalidate_dcache_range(from,size)
+ */
+
+extern void __flush_invalidate_cache_all(void);
+extern void __flush_invalidate_cache_range(unsigned long, unsigned long);
+extern void __flush_invalidate_dcache_all(void);
+extern void __invalidate_icache_all(void);
+
+extern void __invalidate_dcache_page(unsigned long);
+extern void __invalidate_icache_page(unsigned long);
+extern void __invalidate_icache_range(unsigned long, unsigned long);
+extern void __invalidate_dcache_range(unsigned long, unsigned long);
+
+#if XCHAL_DCACHE_IS_WRITEBACK
+extern void __flush_dcache_page(unsigned long);
+extern void __flush_invalidate_dcache_page(unsigned long);
+extern void __flush_invalidate_dcache_range(unsigned long, unsigned long);
+#else
+# define __flush_dcache_page(p)				do { } while(0)
+# define __flush_invalidate_dcache_page(p) 		do { } while(0)
+# define __flush_invalidate_dcache_range(p,s)		do { } while(0)
+#endif
+
+/*
+ * We have physically tagged caches - nothing to do here -
+ * unless we have cache aliasing.
+ *
+ * Pages can get remapped. Because this might change the 'color' of that page,
+ * we have to flush the cache before the PTE is changed.
+ * (see also Documentation/cachetlb.txt)
+ */
+
+#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
+
+#define flush_cache_all()		__flush_invalidate_cache_all();
+#define flush_cache_mm(mm)		__flush_invalidate_cache_all();
+
+#define flush_cache_vmap(start,end)	__flush_invalidate_cache_all();
+#define flush_cache_vunmap(start,end)	__flush_invalidate_cache_all();
+
+extern void flush_dcache_page(struct page*);
+
+extern void flush_cache_range(struct vm_area_struct*, ulong, ulong);
+extern void flush_cache_page(struct vm_area_struct*, unsigned long, unsigned long);
+
+#else
+
+#define flush_cache_all()				do { } while (0)
+#define flush_cache_mm(mm)				do { } while (0)
+
+#define flush_cache_vmap(start,end)			do { } while (0)
+#define flush_cache_vunmap(start,end)			do { } while (0)
+
+#define flush_dcache_page(page)				do { } while (0)
+
+#define flush_cache_page(vma,addr,pfn)			do { } while (0)
+#define flush_cache_range(vma,start,end)		do { } while (0)
+
+#endif
+
+#define flush_icache_range(start,end) 					\
+	__invalidate_icache_range(start,(end)-(start))
+
+/* This is not required, see Documentation/cachetlb.txt */
+
+#define	flush_icache_page(vma,page)			do { } while(0)
+
+#define flush_dcache_mmap_lock(mapping)			do { } while (0)
+#define flush_dcache_mmap_unlock(mapping)		do { } while (0)
+
+
+#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
+	memcpy(dst, src, len)
+
+#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
+	memcpy(dst, src, len)
+
+#endif /* __KERNEL__ */
+
+#endif /* _XTENSA_CACHEFLUSH_H */
+
diff --git a/include/asm-xtensa/checksum.h b/include/asm-xtensa/checksum.h
new file mode 100644
index 0000000..1a00fad
--- /dev/null
+++ b/include/asm-xtensa/checksum.h
@@ -0,0 +1,264 @@
+/*
+ * include/asm-xtensa/checksum.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_CHECKSUM_H
+#define _XTENSA_CHECKSUM_H
+
+#include <linux/config.h>
+#include <linux/in6.h>
+#include <xtensa/config/core.h>
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+asmlinkage unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums, and handles user-space pointer exceptions correctly, when needed.
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
+asmlinkage unsigned int csum_partial_copy_generic( const char *src, char *dst, int len, int sum,
+						   int *src_err_ptr, int *dst_err_ptr);
+
+/*
+ *	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().
+ */
+extern __inline__
+unsigned int csum_partial_copy_nocheck ( const char *src, char *dst,
+					int len, int sum)
+{
+	return csum_partial_copy_generic ( src, dst, len, sum, NULL, NULL);
+}
+
+extern __inline__
+unsigned int csum_partial_copy_from_user ( const char *src, char *dst,
+						int len, int sum, int *err_ptr)
+{
+	return csum_partial_copy_generic ( src, dst, len, sum, err_ptr, NULL);
+}
+
+/*
+ * These are the old (and unsafe) way of doing checksums, a warning message will be
+ * printed if they are used and an exeption occurs.
+ *
+ * these functions should go away after some time.
+ */
+
+#define csum_partial_copy_fromuser csum_partial_copy
+unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum);
+
+/*
+ *	Fold a partial checksum
+ */
+
+static __inline__ unsigned int csum_fold(unsigned int sum)
+{
+	unsigned int __dummy;
+	__asm__("extui	%1, %0, 16, 16\n\t"
+		"extui	%0 ,%0, 0, 16\n\t"
+		"add	%0, %0, %1\n\t"
+		"slli	%1, %0, 16\n\t"
+		"add	%0, %0, %1\n\t"
+		"extui	%0, %0, 16, 16\n\t"
+		"neg	%0, %0\n\t"
+		"addi	%0, %0, -1\n\t"
+		"extui	%0, %0, 0, 16\n\t"
+		: "=r" (sum), "=&r" (__dummy)
+		: "0" (sum));
+	return sum;
+}
+
+/*
+ *	This is a version of ip_compute_csum() optimized for IP headers,
+ *	which always checksum on 4 octet boundaries.
+ */
+static __inline__ unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
+{
+	unsigned int sum, tmp, endaddr;
+
+	__asm__ __volatile__(
+		"sub		%0, %0, %0\n\t"
+#if XCHAL_HAVE_LOOPS
+		"loopgtz	%2, 2f\n\t"
+#else
+		"beqz		%2, 2f\n\t"
+		"slli		%4, %2, 2\n\t"
+		"add		%4, %4, %1\n\t"
+		"0:\t"
+#endif
+		"l32i		%3, %1, 0\n\t"
+		"add		%0, %0, %3\n\t"
+		"bgeu		%0, %3, 1f\n\t"
+		"addi		%0, %0, 1\n\t"
+		"1:\t"
+		"addi		%1, %1, 4\n\t"
+#if !XCHAL_HAVE_LOOPS
+		"blt		%1, %4, 0b\n\t"
+#endif
+		"2:\t"
+	/* Since the input registers which are loaded with iph and ihl
+	   are modified, we must also specify them as outputs, or gcc
+	   will assume they contain their original values. */
+		: "=r" (sum), "=r" (iph), "=r" (ihl), "=&r" (tmp), "=&r" (endaddr)
+		: "1" (iph), "2" (ihl));
+
+	return	csum_fold(sum);
+}
+
+static __inline__ unsigned long csum_tcpudp_nofold(unsigned long saddr,
+						   unsigned long daddr,
+						   unsigned short len,
+						   unsigned short proto,
+						   unsigned int sum)
+{
+
+#ifdef __XTENSA_EL__
+	unsigned long len_proto = (ntohs(len)<<16)+proto*256;
+#elif defined(__XTENSA_EB__)
+	unsigned long len_proto = (proto<<16)+len;
+#else
+# error processor byte order undefined!
+#endif
+	__asm__("add	%0, %0, %1\n\t"
+		"bgeu	%0, %1, 1f\n\t"
+		"addi	%0, %0, 1\n\t"
+		"1:\t"
+		"add	%0, %0, %2\n\t"
+		"bgeu	%0, %2, 1f\n\t"
+		"addi	%0, %0, 1\n\t"
+		"1:\t"
+		"add	%0, %0, %3\n\t"
+		"bgeu	%0, %3, 1f\n\t"
+		"addi	%0, %0, 1\n\t"
+		"1:\t"
+		: "=r" (sum), "=r" (len_proto)
+		: "r" (daddr), "r" (saddr), "1" (len_proto), "0" (sum));
+	return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+static __inline__ unsigned short int csum_tcpudp_magic(unsigned long saddr,
+						       unsigned long daddr,
+						       unsigned short len,
+						       unsigned short proto,
+						       unsigned int sum)
+{
+	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+
+static __inline__ unsigned short ip_compute_csum(unsigned char * buff, int len)
+{
+    return csum_fold (csum_partial(buff, len, 0));
+}
+
+#define _HAVE_ARCH_IPV6_CSUM
+static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
+						     struct in6_addr *daddr,
+						     __u32 len,
+						     unsigned short proto,
+						     unsigned int sum)
+{
+	unsigned int __dummy;
+	__asm__("l32i	%1, %2, 0\n\t"
+		"add	%0, %0, %1\n\t"
+		"bgeu	%0, %1, 1f\n\t"
+		"addi	%0, %0, 1\n\t"
+		"1:\t"
+		"l32i	%1, %2, 4\n\t"
+		"add	%0, %0, %1\n\t"
+		"bgeu	%0, %1, 1f\n\t"
+		"addi	%0, %0, 1\n\t"
+		"1:\t"
+		"l32i	%1, %2, 8\n\t"
+		"add	%0, %0, %1\n\t"
+		"bgeu	%0, %1, 1f\n\t"
+		"addi	%0, %0, 1\n\t"
+		"1:\t"
+		"l32i	%1, %2, 12\n\t"
+		"add	%0, %0, %1\n\t"
+		"bgeu	%0, %1, 1f\n\t"
+		"addi	%0, %0, 1\n\t"
+		"1:\t"
+		"l32i	%1, %3, 0\n\t"
+		"add	%0, %0, %1\n\t"
+		"bgeu	%0, %1, 1f\n\t"
+		"addi	%0, %0, 1\n\t"
+		"1:\t"
+		"l32i	%1, %3, 4\n\t"
+		"add	%0, %0, %1\n\t"
+		"bgeu	%0, %1, 1f\n\t"
+		"addi	%0, %0, 1\n\t"
+		"1:\t"
+		"l32i	%1, %3, 8\n\t"
+		"add	%0, %0, %1\n\t"
+		"bgeu	%0, %1, 1f\n\t"
+		"addi	%0, %0, 1\n\t"
+		"1:\t"
+		"l32i	%1, %3, 12\n\t"
+		"add	%0, %0, %1\n\t"
+		"bgeu	%0, %1, 1f\n\t"
+		"addi	%0, %0, 1\n\t"
+		"1:\t"
+		"add	%0, %0, %4\n\t"
+		"bgeu	%0, %4, 1f\n\t"
+		"addi	%0, %0, 1\n\t"
+		"1:\t"
+		"add	%0, %0, %5\n\t"
+		"bgeu	%0, %5, 1f\n\t"
+		"addi	%0, %0, 1\n\t"
+		"1:\t"
+		: "=r" (sum), "=&r" (__dummy)
+		: "r" (saddr), "r" (daddr),
+		  "r" (htonl(len)), "r" (htonl(proto)), "0" (sum));
+
+	return csum_fold(sum);
+}
+
+/*
+ *	Copy and checksum to user
+ */
+#define HAVE_CSUM_COPY_USER
+static __inline__ unsigned int csum_and_copy_to_user (const char *src, char *dst,
+				    int len, int sum, int *err_ptr)
+{
+	if (access_ok(VERIFY_WRITE, dst, len))
+		return csum_partial_copy_generic(src, dst, len, sum, NULL, err_ptr);
+
+	if (len)
+		*err_ptr = -EFAULT;
+
+	return -1; /* invalid checksum */
+}
+#endif
diff --git a/include/asm-xtensa/coprocessor.h b/include/asm-xtensa/coprocessor.h
new file mode 100644
index 0000000..a91b96d
--- /dev/null
+++ b/include/asm-xtensa/coprocessor.h
@@ -0,0 +1,70 @@
+/*
+ * include/asm-xtensa/cpextra.h
+ *
+ * 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 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_COPROCESSOR_H
+#define _XTENSA_COPROCESSOR_H
+
+#include <xtensa/config/core.h>
+
+#define XTOFS(last_start,last_size,align) \
+	((last_start+last_size+align-1) & -align)
+
+#define XTENSA_CP_EXTRA_OFFSET	0
+#define XTENSA_CP_EXTRA_ALIGN	XCHAL_EXTRA_SA_ALIGN
+
+#define XTENSA_CPE_CP0_OFFSET	\
+	XTOFS(XTENSA_CP_EXTRA_OFFSET, XCHAL_EXTRA_SA_SIZE, XCHAL_CP0_SA_ALIGN)
+#define XTENSA_CPE_CP1_OFFSET	\
+	XTOFS(XTENSA_CPE_CP0_OFFSET, XCHAL_CP0_SA_SIZE, XCHAL_CP1_SA_ALIGN)
+#define XTENSA_CPE_CP2_OFFSET	\
+	XTOFS(XTENSA_CPE_CP1_OFFSET, XCHAL_CP1_SA_SIZE, XCHAL_CP2_SA_ALIGN)
+#define XTENSA_CPE_CP3_OFFSET	\
+	XTOFS(XTENSA_CPE_CP2_OFFSET, XCHAL_CP2_SA_SIZE, XCHAL_CP3_SA_ALIGN)
+#define XTENSA_CPE_CP4_OFFSET	\
+	XTOFS(XTENSA_CPE_CP3_OFFSET, XCHAL_CP3_SA_SIZE, XCHAL_CP4_SA_ALIGN)
+#define XTENSA_CPE_CP5_OFFSET	\
+	XTOFS(XTENSA_CPE_CP4_OFFSET, XCHAL_CP4_SA_SIZE, XCHAL_CP5_SA_ALIGN)
+#define XTENSA_CPE_CP6_OFFSET	\
+	XTOFS(XTENSA_CPE_CP5_OFFSET, XCHAL_CP5_SA_SIZE, XCHAL_CP6_SA_ALIGN)
+#define XTENSA_CPE_CP7_OFFSET	\
+	XTOFS(XTENSA_CPE_CP6_OFFSET, XCHAL_CP6_SA_SIZE, XCHAL_CP7_SA_ALIGN)
+#define XTENSA_CP_EXTRA_SIZE	\
+	XTOFS(XTENSA_CPE_CP7_OFFSET, XCHAL_CP7_SA_SIZE, 16)
+
+#if XCHAL_CP_NUM > 0
+# ifndef __ASSEMBLY__
+/*
+ * Tasks that own contents of (last user) each coprocessor.
+ * Entries are 0 for not-owned or non-existent coprocessors.
+ * Note: The size of this structure is fixed to 8 bytes in entry.S
+ */
+typedef struct {
+	struct task_struct *owner;	/* owner */
+	int offset;			/* offset in cpextra space. */
+} coprocessor_info_t;
+# else
+#  define COPROCESSOR_INFO_OWNER 0
+#  define COPROCESSOR_INFO_OFFSET 4
+#  define COPROCESSOR_INFO_SIZE 8
+# endif
+#endif
+
+
+#ifndef __ASSEMBLY__
+# if XCHAL_CP_NUM > 0
+struct task_struct;
+extern void release_coprocessors (struct task_struct*);
+extern void save_coprocessor_registers(void*, int);
+# else
+#  define release_coprocessors(task)
+# endif
+#endif
+
+#endif	/* _XTENSA_COPROCESSOR_H */
diff --git a/include/asm-xtensa/cpumask.h b/include/asm-xtensa/cpumask.h
new file mode 100644
index 0000000..ebeede3
--- /dev/null
+++ b/include/asm-xtensa/cpumask.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/cpumask.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_CPUMASK_H
+#define _XTENSA_CPUMASK_H
+
+#include <asm-generic/cpumask.h>
+
+#endif /* _XTENSA_CPUMASK_H */
diff --git a/include/asm-xtensa/cputime.h b/include/asm-xtensa/cputime.h
new file mode 100644
index 0000000..a7fb864
--- /dev/null
+++ b/include/asm-xtensa/cputime.h
@@ -0,0 +1,6 @@
+#ifndef _XTENSA_CPUTIME_H
+#define _XTENSA_CPUTIME_H
+
+#include <asm-generic/cputime.h>
+
+#endif /* _XTENSA_CPUTIME_H */
diff --git a/include/asm-xtensa/current.h b/include/asm-xtensa/current.h
new file mode 100644
index 0000000..8d1eb5d
--- /dev/null
+++ b/include/asm-xtensa/current.h
@@ -0,0 +1,38 @@
+/*
+ * include/asm-xtensa/current.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_CURRENT_H
+#define _XTENSA_CURRENT_H
+
+#ifndef __ASSEMBLY__
+
+#include <linux/thread_info.h>
+
+struct task_struct;
+
+static inline struct task_struct *get_current(void)
+{
+	return current_thread_info()->task;
+}
+
+#define current get_current()
+
+#else
+
+#define CURRENT_SHIFT 13
+
+#define GET_CURRENT(reg,sp)		\
+	GET_THREAD_INFO(reg,sp);	\
+  	l32i reg, reg, TI_TASK		\
+
+#endif
+
+
+#endif /* XTENSA_CURRENT_H */
diff --git a/include/asm-xtensa/delay.h b/include/asm-xtensa/delay.h
new file mode 100644
index 0000000..6359c55
--- /dev/null
+++ b/include/asm-xtensa/delay.h
@@ -0,0 +1,50 @@
+/*
+ * include/asm-xtensa/delay.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ *
+ */
+
+#ifndef _XTENSA_DELAY_H
+#define _XTENSA_DELAY_H
+
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/param.h>
+
+extern unsigned long loops_per_jiffy;
+
+extern __inline__ void __delay(unsigned long loops)
+{
+  /* 2 cycles per loop. */
+  __asm__ __volatile__ ("1: addi %0, %0, -2; bgeui %0, 1, 1b"
+			: "=r" (loops) : "0" (loops));
+}
+
+static __inline__ u32 xtensa_get_ccount(void)
+{
+	u32 ccount;
+	asm volatile ("rsr %0, 234; # CCOUNT\n" : "=r" (ccount));
+	return ccount;
+}
+
+/* For SMP/NUMA systems, change boot_cpu_data to something like
+ * local_cpu_data->... where local_cpu_data points to the current
+ * cpu. */
+
+static __inline__ void udelay (unsigned long usecs)
+{
+	unsigned long start = xtensa_get_ccount();
+	unsigned long cycles = usecs * (loops_per_jiffy / (1000000UL / HZ));
+
+	/* Note: all variables are unsigned (can wrap around)! */
+	while (((unsigned long)xtensa_get_ccount()) - start < cycles)
+		;
+}
+
+#endif
+
diff --git a/include/asm-xtensa/div64.h b/include/asm-xtensa/div64.h
new file mode 100644
index 0000000..c4a1057
--- /dev/null
+++ b/include/asm-xtensa/div64.h
@@ -0,0 +1,19 @@
+/*
+ * include/asm-xtensa/div64.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_DIV64_H
+#define _XTENSA_DIV64_H
+
+#define do_div(n,base) ({ \
+	int __res = n % ((unsigned int) base); \
+	n /= (unsigned int) base; \
+	__res; })
+
+#endif
diff --git a/include/asm-xtensa/dma-mapping.h b/include/asm-xtensa/dma-mapping.h
new file mode 100644
index 0000000..e86a206
--- /dev/null
+++ b/include/asm-xtensa/dma-mapping.h
@@ -0,0 +1,182 @@
+/*
+ * include/asm-xtensa/dma_mapping.h
+ *
+ * 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 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_DMA_MAPPING_H
+#define _XTENSA_DMA_MAPPING_H
+
+#include <asm/scatterlist.h>
+#include <asm/cache.h>
+#include <asm/io.h>
+#include <linux/mm.h>
+
+/*
+ * DMA-consistent mapping functions.
+ */
+
+extern void *consistent_alloc(int, size_t, dma_addr_t, unsigned long);
+extern void consistent_free(void*, size_t, dma_addr_t);
+extern void consistent_sync(void*, size_t, int);
+
+#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)
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+			   dma_addr_t *dma_handle, int flag);
+
+void dma_free_coherent(struct device *dev, size_t size,
+			 void *vaddr, dma_addr_t dma_handle);
+
+static inline dma_addr_t
+dma_map_single(struct device *dev, void *ptr, size_t size,
+	       enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+	consistent_sync(ptr, size, direction);
+	return virt_to_phys(ptr);
+}
+
+static inline void
+dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+		 enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+}
+
+static inline int
+dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+	   enum dma_data_direction direction)
+{
+	int i;
+
+	BUG_ON(direction == DMA_NONE);
+
+	for (i = 0; i < nents; i++, sg++ ) {
+		BUG_ON(!sg->page);
+
+		sg->dma_address = page_to_phys(sg->page) + sg->offset;
+		consistent_sync(page_address(sg->page) + sg->offset,
+				sg->length, direction);
+	}
+
+	return nents;
+}
+
+static inline dma_addr_t
+dma_map_page(struct device *dev, struct page *page, unsigned long offset,
+	     size_t size, enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+	return (dma_addr_t)(page_to_pfn(page)) * PAGE_SIZE + offset;
+}
+
+static inline void
+dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
+	       enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+}
+
+
+static inline void
+dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
+	     enum dma_data_direction direction)
+{
+	BUG_ON(direction == DMA_NONE);
+}
+
+static inline void
+dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
+		enum dma_data_direction direction)
+{
+	consistent_sync((void *)bus_to_virt(dma_handle), size, direction);
+}
+
+static inline void
+dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
+		enum dma_data_direction direction)
+{
+	consistent_sync((void *)bus_to_virt(dma_handle), size, direction);
+}
+
+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)
+{
+
+	consistent_sync((void *)bus_to_virt(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)
+{
+
+	consistent_sync((void *)bus_to_virt(dma_handle)+offset,size,direction);
+}
+static inline void
+dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
+		 enum dma_data_direction dir)
+{
+	int i;
+	for (i = 0; i < nelems; i++, sg++)
+		consistent_sync(page_address(sg->page) + sg->offset,
+				sg->length, dir);
+}
+
+static inline void
+dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
+		 enum dma_data_direction dir)
+{
+	int i;
+	for (i = 0; i < nelems; i++, sg++)
+		consistent_sync(page_address(sg->page) + sg->offset,
+				sg->length, dir);
+}
+static inline int
+dma_mapping_error(dma_addr_t dma_addr)
+{
+	return 0;
+}
+
+static inline int
+dma_supported(struct device *dev, u64 mask)
+{
+	return 1;
+}
+
+static inline int
+dma_set_mask(struct device *dev, u64 mask)
+{
+	if(!dev->dma_mask || !dma_supported(dev, mask))
+		return -EIO;
+
+	*dev->dma_mask = mask;
+
+	return 0;
+}
+
+static inline int
+dma_get_cache_alignment(void)
+{
+	return L1_CACHE_BYTES;
+}
+
+#define dma_is_consistent(d)	(1)
+
+static inline void
+dma_cache_sync(void *vaddr, size_t size,
+	       enum dma_data_direction direction)
+{
+	consistent_sync(vaddr, size, direction);
+}
+
+#endif	/* _XTENSA_DMA_MAPPING_H */
diff --git a/include/asm-xtensa/dma.h b/include/asm-xtensa/dma.h
new file mode 100644
index 0000000..1c22b02
--- /dev/null
+++ b/include/asm-xtensa/dma.h
@@ -0,0 +1,61 @@
+/*
+ * include/asm-xtensa/dma.h
+ *
+ * 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 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_DMA_H
+#define _XTENSA_DMA_H
+
+#include <linux/config.h>
+#include <asm/io.h>		/* need byte IO */
+#include <xtensa/config/core.h>
+
+/*
+ * This is only to be defined if we have PC-like DMA.
+ * By default this is not true on an Xtensa processor,
+ * however on boards with a PCI bus, such functionality
+ * might be emulated externally.
+ *
+ * NOTE:  there still exists driver code that assumes
+ * this is defined, eg. drivers/sound/soundcard.c (as of 2.4).
+ */
+#define MAX_DMA_CHANNELS	8
+
+/*
+ * The maximum virtual address to which DMA transfers
+ * can be performed on this platform.
+ *
+ * NOTE: This is board (platform) specific, not processor-specific!
+ *
+ * NOTE: This assumes DMA transfers can only be performed on
+ *	the section of physical memory contiguously mapped in virtual
+ *	space for the kernel.  For the Xtensa architecture, this
+ *	means the maximum possible size of this DMA area is
+ *	the size of the statically mapped kernel segment
+ *	(XCHAL_KSEG_{CACHED,BYPASS}_SIZE), ie. 128 MB.
+ *
+ * NOTE: When the entire KSEG area is DMA capable, we substract
+ *	one from the max address so that the virt_to_phys() macro
+ *	works correctly on the address (otherwise the address
+ *	enters another area, and virt_to_phys() may not return
+ *	the value desired).
+ */
+#define MAX_DMA_ADDRESS		(PAGE_OFFSET + XCHAL_KSEG_CACHED_SIZE - 1)
+
+/* Reserve and release a DMA channel */
+extern int request_dma(unsigned int dmanr, const char * device_id);
+extern void free_dma(unsigned int dmanr);
+
+#ifdef CONFIG_PCI
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy 	(0)
+#endif
+
+
+#endif
diff --git a/include/asm-xtensa/elf.h b/include/asm-xtensa/elf.h
new file mode 100644
index 0000000..64f1f53
--- /dev/null
+++ b/include/asm-xtensa/elf.h
@@ -0,0 +1,222 @@
+/*
+ * include/asm-xtensa/elf.h
+ *
+ * ELF register definitions
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_ELF_H
+#define _XTENSA_ELF_H
+
+#include <asm/ptrace.h>
+#include <asm/coprocessor.h>
+#include <xtensa/config/core.h>
+
+/* Xtensa processor ELF architecture-magic number */
+
+#define EM_XTENSA	94
+#define EM_XTENSA_OLD	0xABC7
+
+/* ELF register definitions. This is needed for core dump support.  */
+
+/*
+ * elf_gregset_t contains the application-level state in the following order:
+ * Processor info: 	config_version, cpuxy
+ * Processor state:	pc, ps, exccause, excvaddr, wb, ws,
+ *			lbeg, lend, lcount, sar
+ * GP regs:		ar0 - arXX
+ */
+
+typedef unsigned long elf_greg_t;
+
+typedef struct {
+	elf_greg_t xchal_config_id0;
+	elf_greg_t xchal_config_id1;
+	elf_greg_t cpux;
+	elf_greg_t cpuy;
+	elf_greg_t pc;
+	elf_greg_t ps;
+	elf_greg_t exccause;
+	elf_greg_t excvaddr;
+	elf_greg_t windowbase;
+	elf_greg_t windowstart;
+	elf_greg_t lbeg;
+	elf_greg_t lend;
+	elf_greg_t lcount;
+	elf_greg_t sar;
+	elf_greg_t syscall;
+	elf_greg_t ar[XCHAL_NUM_AREGS];
+} xtensa_gregset_t;
+
+#define ELF_NGREG	(sizeof(xtensa_gregset_t) / sizeof(elf_greg_t))
+
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+/*
+ *  Compute the size of the coprocessor and extra state layout (register info)
+ *  table (in bytes).
+ *  This is actually the maximum size of the table, as opposed to the size,
+ *  which is available from the _xtensa_reginfo_table_size global variable.
+ *
+ *  (See also arch/xtensa/kernel/coprocessor.S)
+ *
+ */
+
+#ifndef XCHAL_EXTRA_SA_CONTENTS_LIBDB_NUM
+# define XTENSA_CPE_LTABLE_SIZE		0
+#else
+# define XTENSA_CPE_SEGMENT(num)	(num ? (1+num) : 0)
+# define XTENSA_CPE_LTABLE_ENTRIES	\
+		( XTENSA_CPE_SEGMENT(XCHAL_EXTRA_SA_CONTENTS_LIBDB_NUM)	\
+		+ XTENSA_CPE_SEGMENT(XCHAL_CP0_SA_CONTENTS_LIBDB_NUM)	\
+		+ XTENSA_CPE_SEGMENT(XCHAL_CP1_SA_CONTENTS_LIBDB_NUM)	\
+		+ XTENSA_CPE_SEGMENT(XCHAL_CP2_SA_CONTENTS_LIBDB_NUM)	\
+		+ XTENSA_CPE_SEGMENT(XCHAL_CP3_SA_CONTENTS_LIBDB_NUM)	\
+		+ XTENSA_CPE_SEGMENT(XCHAL_CP4_SA_CONTENTS_LIBDB_NUM)	\
+		+ XTENSA_CPE_SEGMENT(XCHAL_CP5_SA_CONTENTS_LIBDB_NUM)	\
+		+ XTENSA_CPE_SEGMENT(XCHAL_CP6_SA_CONTENTS_LIBDB_NUM)	\
+		+ XTENSA_CPE_SEGMENT(XCHAL_CP7_SA_CONTENTS_LIBDB_NUM)	\
+		+ 1		/* final entry */			\
+		)
+# define XTENSA_CPE_LTABLE_SIZE		(XTENSA_CPE_LTABLE_ENTRIES * 8)
+#endif
+
+
+/*
+ * Instantiations of the elf_fpregset_t type contain, in most
+ * architectures, the floating point (FPU) register set.
+ * For Xtensa, this type is extended to contain all custom state,
+ * ie. coprocessor and "extra" (non-coprocessor) state (including,
+ * for example, TIE-defined states and register files; as well
+ * as other optional processor state).
+ * This includes FPU state if a floating-point coprocessor happens
+ * to have been configured within the Xtensa processor.
+ *
+ * TOTAL_FPREGS_SIZE is the required size (without rounding)
+ * of elf_fpregset_t.  It provides space for the following:
+ *
+ *  a)	32-bit mask of active coprocessors for this task (similar
+ *	to CPENABLE in single-threaded Xtensa processor systems)
+ *
+ *  b)	table describing the layout of custom states (ie. of
+ *      individual registers, etc) within the save areas
+ *
+ *  c)  save areas for each coprocessor and for non-coprocessor
+ *      ("extra") state
+ *
+ * Note that save areas may require up to 16-byte alignment when
+ * accessed by save/restore sequences.  We do not need to ensure
+ * such alignment in an elf_fpregset_t structure because custom
+ * state is not directly loaded/stored into it; rather, save area
+ * contents are copied to elf_fpregset_t from the active save areas
+ * (see 'struct task_struct' definition in processor.h for that)
+ * using memcpy().  But we do allow space for such alignment,
+ * to allow optimizations of layout and copying.
+ */
+
+#define TOTAL_FPREGS_SIZE						\
+  	(4 + XTENSA_CPE_LTABLE_SIZE + XTENSA_CP_EXTRA_SIZE)
+#define ELF_NFPREG							\
+	((TOTAL_FPREGS_SIZE + sizeof(elf_fpreg_t) - 1) / sizeof(elf_fpreg_t))
+
+typedef unsigned int elf_fpreg_t;
+typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
+
+#define ELF_CORE_COPY_REGS(_eregs, _pregs) 				\
+	xtensa_elf_core_copy_regs (&_eregs, _pregs);
+
+extern void xtensa_elf_core_copy_regs (xtensa_gregset_t *, struct pt_regs *);
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+
+#define elf_check_arch(x) ( ( (x)->e_machine == EM_XTENSA )  || \
+			    ( (x)->e_machine == EM_XTENSA_OLD ) )
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+
+#ifdef __XTENSA_EL__
+# define ELF_DATA	ELFDATA2LSB
+#elif defined(__XTENSA_EB__)
+# define ELF_DATA	ELFDATA2MSB
+#else
+# error processor byte order undefined!
+#endif
+
+#define ELF_CLASS	ELFCLASS32
+#define ELF_ARCH	EM_XTENSA
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE	PAGE_SIZE
+
+/*
+ * This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+ * use of this is to invoke "./ld.so someprog" to test out a new version of
+ * the loader.  We need to make sure that it is out of the way of the program
+ * that it will "exec", and that there is sufficient room for the brk.
+ */
+
+#define ELF_ET_DYN_BASE         (2 * TASK_SIZE / 3)
+
+/*
+ * This yields a mask that user programs can use to figure out what
+ * instruction set this CPU supports.  This could be done in user space,
+ * but it's not easy, and we've already done it here.
+ */
+
+#define ELF_HWCAP	(0)
+
+/*
+ * This yields a string that ld.so will use to load implementation
+ * specific libraries for optimization.  This is more specific in
+ * intent than poking at uname or /proc/cpuinfo.
+ * For the moment, we have only optimizations for the Intel generations,
+ * but that could change...
+ */
+
+#define ELF_PLATFORM  (NULL)
+
+/*
+ * The Xtensa processor ABI says that when the program starts, a2
+ * contains a pointer to a function which might be registered using
+ * `atexit'.  This provides a mean for the dynamic linker to call
+ * DT_FINI functions for shared libraries that have been loaded before
+ * the code runs.
+ *
+ * A value of 0 tells we have no such handler.
+ *
+ * We might as well make sure everything else is cleared too (except
+ * for the stack pointer in a1), just to make things more
+ * deterministic.  Also, clearing a0 terminates debugger backtraces.
+ */
+
+#define ELF_PLAT_INIT(_r, load_addr) \
+  do { _r->areg[0]=0; /*_r->areg[1]=0;*/ _r->areg[2]=0;  _r->areg[3]=0;  \
+       _r->areg[4]=0;  _r->areg[5]=0;    _r->areg[6]=0;  _r->areg[7]=0;  \
+       _r->areg[8]=0;  _r->areg[9]=0;    _r->areg[10]=0; _r->areg[11]=0; \
+       _r->areg[12]=0; _r->areg[13]=0;   _r->areg[14]=0; _r->areg[15]=0; \
+  } while (0)
+
+#ifdef __KERNEL__
+
+#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
+
+extern void do_copy_regs (xtensa_gregset_t*, struct pt_regs*,
+			  struct task_struct*);
+extern void do_restore_regs (xtensa_gregset_t*, struct pt_regs*,
+			     struct task_struct*);
+extern void do_save_fpregs (elf_fpregset_t*, struct pt_regs*,
+			    struct task_struct*);
+extern int do_restore_fpregs (elf_fpregset_t*, struct pt_regs*,
+			      struct task_struct*);
+
+#endif	/* __KERNEL__ */
+#endif	/* _XTENSA_ELF_H */
diff --git a/include/asm-xtensa/errno.h b/include/asm-xtensa/errno.h
new file mode 100644
index 0000000..ced5194
--- /dev/null
+++ b/include/asm-xtensa/errno.h
@@ -0,0 +1,142 @@
+/*
+ * include/asm-xtensa/errno.h
+ *
+ * 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) 2002 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_ERRNO_H
+#define _XTENSA_ERRNO_H
+
+#define	EPERM		 1	/* Operation not permitted */
+#define	ENOENT		 2	/* No such file or directory */
+#define	ESRCH		 3	/* No such process */
+#define	EINTR		 4	/* Interrupted system call */
+#define	EIO		 5	/* I/O error */
+#define	ENXIO		 6	/* No such device or address */
+#define	E2BIG		 7	/* Arg list too long */
+#define	ENOEXEC		 8	/* Exec format error */
+#define	EBADF		 9	/* Bad file number */
+#define	ECHILD		10	/* No child processes */
+#define	EAGAIN		11	/* Try again */
+#define	ENOMEM		12	/* Out of memory */
+#define	EACCES		13	/* Permission denied */
+#define	EFAULT		14	/* Bad address */
+#define	ENOTBLK		15	/* Block device required */
+#define	EBUSY		16	/* Device or resource busy */
+#define	EEXIST		17	/* File exists */
+#define	EXDEV		18	/* Cross-device link */
+#define	ENODEV		19	/* No such device */
+#define	ENOTDIR		20	/* Not a directory */
+#define	EISDIR		21	/* Is a directory */
+#define	EINVAL		22	/* Invalid argument */
+#define	ENFILE		23	/* File table overflow */
+#define	EMFILE		24	/* Too many open files */
+#define	ENOTTY		25	/* Not a typewriter */
+#define	ETXTBSY		26	/* Text file busy */
+#define	EFBIG		27	/* File too large */
+#define	ENOSPC		28	/* No space left on device */
+#define	ESPIPE		29	/* Illegal seek */
+#define	EROFS		30	/* Read-only file system */
+#define	EMLINK		31	/* Too many links */
+#define	EPIPE		32	/* Broken pipe */
+#define	EDOM		33	/* Math argument out of domain of func */
+#define	ERANGE		34	/* Math result not representable */
+#define	EDEADLK		35	/* Resource deadlock would occur */
+#define	ENAMETOOLONG	36	/* File name too long */
+#define	ENOLCK		37	/* No record locks available */
+#define	ENOSYS		38	/* Function not implemented */
+#define	ENOTEMPTY	39	/* Directory not empty */
+#define	ELOOP		40	/* Too many symbolic links encountered */
+#define	EWOULDBLOCK	EAGAIN	/* Operation would block */
+#define	ENOMSG		42	/* No message of desired type */
+#define	EIDRM		43	/* Identifier removed */
+#define	ECHRNG		44	/* Channel number out of range */
+#define	EL2NSYNC	45	/* Level 2 not synchronized */
+#define	EL3HLT		46	/* Level 3 halted */
+#define	EL3RST		47	/* Level 3 reset */
+#define	ELNRNG		48	/* Link number out of range */
+#define	EUNATCH		49	/* Protocol driver not attached */
+#define	ENOCSI		50	/* No CSI structure available */
+#define	EL2HLT		51	/* Level 2 halted */
+#define	EBADE		52	/* Invalid exchange */
+#define	EBADR		53	/* Invalid request descriptor */
+#define	EXFULL		54	/* Exchange full */
+#define	ENOANO		55	/* No anode */
+#define	EBADRQC		56	/* Invalid request code */
+#define	EBADSLT		57	/* Invalid slot */
+
+#define	EDEADLOCK	EDEADLK
+
+#define	EBFONT		59	/* Bad font file format */
+#define	ENOSTR		60	/* Device not a stream */
+#define	ENODATA		61	/* No data available */
+#define	ETIME		62	/* Timer expired */
+#define	ENOSR		63	/* Out of streams resources */
+#define	ENONET		64	/* Machine is not on the network */
+#define	ENOPKG		65	/* Package not installed */
+#define	EREMOTE		66	/* Object is remote */
+#define	ENOLINK		67	/* Link has been severed */
+#define	EADV		68	/* Advertise error */
+#define	ESRMNT		69	/* Srmount error */
+#define	ECOMM		70	/* Communication error on send */
+#define	EPROTO		71	/* Protocol error */
+#define	EMULTIHOP	72	/* Multihop attempted */
+#define	EDOTDOT		73	/* RFS specific error */
+#define	EBADMSG		74	/* Not a data message */
+#define	EOVERFLOW	75	/* Value too large for defined data type */
+#define	ENOTUNIQ	76	/* Name not unique on network */
+#define	EBADFD		77	/* File descriptor in bad state */
+#define	EREMCHG		78	/* Remote address changed */
+#define	ELIBACC		79	/* Can not access a needed shared library */
+#define	ELIBBAD		80	/* Accessing a corrupted shared library */
+#define	ELIBSCN		81	/* .lib section in a.out corrupted */
+#define	ELIBMAX		82	/* Attempting to link in too many shared libraries */
+#define	ELIBEXEC	83	/* Cannot exec a shared library directly */
+#define	EILSEQ		84	/* Illegal byte sequence */
+#define	ERESTART	85	/* Interrupted system call should be restarted */
+#define	ESTRPIPE	86	/* Streams pipe error */
+#define	EUSERS		87	/* Too many users */
+#define	ENOTSOCK	88	/* Socket operation on non-socket */
+#define	EDESTADDRREQ	89	/* Destination address required */
+#define	EMSGSIZE	90	/* Message too long */
+#define	EPROTOTYPE	91	/* Protocol wrong type for socket */
+#define	ENOPROTOOPT	92	/* Protocol not available */
+#define	EPROTONOSUPPORT	93	/* Protocol not supported */
+#define	ESOCKTNOSUPPORT	94	/* Socket type not supported */
+#define	EOPNOTSUPP	95	/* Operation not supported on transport endpoint */
+#define	EPFNOSUPPORT	96	/* Protocol family not supported */
+#define	EAFNOSUPPORT	97	/* Address family not supported by protocol */
+#define	EADDRINUSE	98	/* Address already in use */
+#define	EADDRNOTAVAIL	99	/* Cannot assign requested address */
+#define	ENETDOWN	100	/* Network is down */
+#define	ENETUNREACH	101	/* Network is unreachable */
+#define	ENETRESET	102	/* Network dropped connection because of reset */
+#define	ECONNABORTED	103	/* Software caused connection abort */
+#define	ECONNRESET	104	/* Connection reset by peer */
+#define	ENOBUFS		105	/* No buffer space available */
+#define	EISCONN		106	/* Transport endpoint is already connected */
+#define	ENOTCONN	107	/* Transport endpoint is not connected */
+#define	ESHUTDOWN	108	/* Cannot send after transport endpoint shutdown */
+#define	ETOOMANYREFS	109	/* Too many references: cannot splice */
+#define	ETIMEDOUT	110	/* Connection timed out */
+#define	ECONNREFUSED	111	/* Connection refused */
+#define	EHOSTDOWN	112	/* Host is down */
+#define	EHOSTUNREACH	113	/* No route to host */
+#define	EALREADY	114	/* Operation already in progress */
+#define	EINPROGRESS	115	/* Operation now in progress */
+#define	ESTALE		116	/* Stale NFS file handle */
+#define	EUCLEAN		117	/* Structure needs cleaning */
+#define	ENOTNAM		118	/* Not a XENIX named type file */
+#define	ENAVAIL		119	/* No XENIX semaphores available */
+#define	EISNAM		120	/* Is a named type file */
+#define	EREMOTEIO	121	/* Remote I/O error */
+#define	EDQUOT		122	/* Quota exceeded */
+
+#define	ENOMEDIUM	123	/* No medium found */
+#define	EMEDIUMTYPE	124	/* Wrong medium type */
+
+#endif	/* _XTENSA_ERRNO_H */
diff --git a/include/asm-xtensa/fcntl.h b/include/asm-xtensa/fcntl.h
new file mode 100644
index 0000000..48876bb
--- /dev/null
+++ b/include/asm-xtensa/fcntl.h
@@ -0,0 +1,101 @@
+/*
+ * include/asm-xtensa/fcntl.h
+ *
+ * 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, 1998 by Ralf Baechle
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_FCNTL_H
+#define _XTENSA_FCNTL_H
+
+/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
+   located on an ext2 file system */
+#define O_ACCMODE	0x0003
+#define O_RDONLY	0x0000
+#define O_WRONLY	0x0001
+#define O_RDWR		0x0002
+#define O_APPEND	0x0008
+#define O_SYNC		0x0010
+#define O_NONBLOCK	0x0080
+#define O_CREAT         0x0100	/* not fcntl */
+#define O_TRUNC		0x0200	/* not fcntl */
+#define O_EXCL		0x0400	/* not fcntl */
+#define O_NOCTTY	0x0800	/* not fcntl */
+#define FASYNC		0x1000	/* fcntl, for BSD compatibility */
+#define O_LARGEFILE	0x2000	/* allow large file opens - currently ignored */
+#define O_DIRECT	0x8000	/* direct disk access hint - currently ignored*/
+#define O_DIRECTORY	0x10000	/* must be a directory */
+#define O_NOFOLLOW	0x20000	/* don't follow links */
+#define O_NOATIME	0x100000
+
+#define O_NDELAY	O_NONBLOCK
+
+#define F_DUPFD		0	/* dup */
+#define F_GETFD		1	/* get close_on_exec */
+#define F_SETFD		2	/* set/clear close_on_exec */
+#define F_GETFL		3	/* get file->f_flags */
+#define F_SETFL		4	/* set file->f_flags */
+#define F_GETLK		14
+#define F_GETLK64       15
+#define F_SETLK		6
+#define F_SETLKW	7
+#define F_SETLK64       16
+#define F_SETLKW64      17
+
+#define F_SETOWN	24	/*  for sockets. */
+#define F_GETOWN	23	/*  for sockets. */
+#define F_SETSIG	10	/*  for sockets. */
+#define F_GETSIG	11	/*  for sockets. */
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC	1	/* actually anything with low bit set goes */
+
+/* for posix fcntl() and lockf() */
+#define F_RDLCK		0
+#define F_WRLCK		1
+#define F_UNLCK		2
+
+/* for old implementation of bsd flock () */
+#define F_EXLCK		4	/* or 3 */
+#define F_SHLCK		8	/* or 4 */
+
+/* for leases */
+#define F_INPROGRESS	16
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH		1	/* shared lock */
+#define LOCK_EX		2	/* exclusive lock */
+#define LOCK_NB		4	/* or'd with one of the above to prevent
+				   blocking */
+#define LOCK_UN		8	/* remove lock */
+
+#define LOCK_MAND	32	/* This is a mandatory flock ... */
+#define LOCK_READ	64	/*  which allows concurrent read operations */
+#define LOCK_WRITE	128	/*  which allows concurrent write operations */
+#define LOCK_RW		192	/*  which allows concurrent read & write ops */
+
+typedef struct flock {
+	short l_type;
+	short l_whence;
+	__kernel_off_t l_start;
+	__kernel_off_t l_len;
+	long  l_sysid;
+	__kernel_pid_t l_pid;
+	long  pad[4];
+} flock_t;
+
+struct flock64 {
+	short  l_type;
+	short  l_whence;
+	__kernel_off_t l_start;
+	__kernel_off_t l_len;
+	pid_t  l_pid;
+};
+
+#define F_LINUX_SPECIFIC_BASE	1024
+
+#endif /* _XTENSA_FCNTL_H */
diff --git a/include/asm-xtensa/fixmap.h b/include/asm-xtensa/fixmap.h
new file mode 100644
index 0000000..4423b8a
--- /dev/null
+++ b/include/asm-xtensa/fixmap.h
@@ -0,0 +1,252 @@
+/*
+ * include/asm-xtensa/fixmap.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_FIXMAP_H
+#define _XTENSA_FIXMAP_H
+
+#include <asm/processor.h>
+
+#ifdef CONFIG_MMU
+
+/*
+ * Here we define all the compile-time virtual addresses.
+ */
+
+#if XCHAL_SEG_MAPPABLE_VADDR != 0
+# error "Current port requires virtual user space starting at 0"
+#endif
+#if XCHAL_SEG_MAPPABLE_SIZE < 0x80000000
+# error "Current port requires at least 0x8000000 bytes for user space"
+#endif
+
+/* Verify instruction/data ram/rom and xlmi don't overlay vmalloc space. */
+
+#define __IN_VMALLOC(addr)						\
+	(((addr) >= VMALLOC_START) && ((addr) < VMALLOC_END))
+#define __SPAN_VMALLOC(start,end)					\
+	(((start) < VMALLOC_START) && ((end) >= VMALLOC_END))
+#define INSIDE_VMALLOC(start,end) 					\
+	(__IN_VMALLOC((start)) || __IN_VMALLOC(end) || __SPAN_VMALLOC((start),(end)))
+
+#if XCHAL_NUM_INSTROM
+# if XCHAL_NUM_INSTROM == 1
+#  if INSIDE_VMALLOC(XCHAL_INSTROM0_VADDR,XCHAL_INSTROM0_VADDR+XCHAL_INSTROM0_SIZE)
+#   error vmalloc range conflicts with instrom0
+#  endif
+# endif
+# if XCHAL_NUM_INSTROM == 2
+#  if INSIDE_VMALLOC(XCHAL_INSTROM1_VADDR,XCHAL_INSTROM1_VADDR+XCHAL_INSTROM1_SIZE)
+#   error vmalloc range conflicts with instrom1
+#  endif
+# endif
+#endif
+
+#if XCHAL_NUM_INSTRAM
+# if XCHAL_NUM_INSTRAM == 1
+#  if INSIDE_VMALLOC(XCHAL_INSTRAM0_VADDR,XCHAL_INSTRAM0_VADDR+XCHAL_INSTRAM0_SIZE)
+#   error vmalloc range conflicts with instram0
+#  endif
+# endif
+# if XCHAL_NUM_INSTRAM == 2
+#  if INSIDE_VMALLOC(XCHAL_INSTRAM1_VADDR,XCHAL_INSTRAM1_VADDR+XCHAL_INSTRAM1_SIZE)
+#   error vmalloc range conflicts with instram1
+#  endif
+# endif
+#endif
+
+#if XCHAL_NUM_DATAROM
+# if XCHAL_NUM_DATAROM == 1
+#  if INSIDE_VMALLOC(XCHAL_DATAROM0_VADDR,XCHAL_DATAROM0_VADDR+XCHAL_DATAROM0_SIZE)
+#   error vmalloc range conflicts with datarom0
+#  endif
+# endif
+# if XCHAL_NUM_DATAROM == 2
+#  if INSIDE_VMALLOC(XCHAL_DATAROM1_VADDR,XCHAL_DATAROM1_VADDR+XCHAL_DATAROM1_SIZE)
+#   error vmalloc range conflicts with datarom1
+#  endif
+# endif
+#endif
+
+#if XCHAL_NUM_DATARAM
+# if XCHAL_NUM_DATARAM == 1
+#  if INSIDE_VMALLOC(XCHAL_DATARAM0_VADDR,XCHAL_DATARAM0_VADDR+XCHAL_DATARAM0_SIZE)
+#   error vmalloc range conflicts with dataram0
+#  endif
+# endif
+# if XCHAL_NUM_DATARAM == 2
+#  if INSIDE_VMALLOC(XCHAL_DATARAM1_VADDR,XCHAL_DATARAM1_VADDR+XCHAL_DATARAM1_SIZE)
+#   error vmalloc range conflicts with dataram1
+#  endif
+# endif
+#endif
+
+#if XCHAL_NUM_XLMI
+# if XCHAL_NUM_XLMI == 1
+#  if INSIDE_VMALLOC(XCHAL_XLMI0_VADDR,XCHAL_XLMI0_VADDR+XCHAL_XLMI0_SIZE)
+#   error vmalloc range conflicts with xlmi0
+#  endif
+# endif
+# if XCHAL_NUM_XLMI == 2
+#  if INSIDE_VMALLOC(XCHAL_XLMI1_VADDR,XCHAL_XLMI1_VADDR+XCHAL_XLMI1_SIZE)
+#   error vmalloc range conflicts with xlmi1
+#  endif
+# endif
+#endif
+
+#if (XCHAL_NUM_INSTROM > 2) || \
+    (XCHAL_NUM_INSTRAM > 2) || \
+    (XCHAL_NUM_DATARAM > 2) || \
+    (XCHAL_NUM_DATAROM > 2) || \
+    (XCHAL_NUM_XLMI    > 2)
+# error Insufficient checks on vmalloc above for more than 2 devices
+#endif
+
+/*
+ * USER_VM_SIZE does not necessarily equal TASK_SIZE.  We bumped
+ * TASK_SIZE down to 0x4000000 to simplify the handling of windowed
+ * call instructions (currently limited to a range of 1 GByte).  User
+ * tasks may very well reclaim the VM space from 0x40000000 to
+ * 0x7fffffff in the future, so we do not want the kernel becoming
+ * accustomed to having any of its stuff (e.g., page tables) in this
+ * region.  This VM region is no-man's land for now.
+ */
+
+#define USER_VM_START		XCHAL_SEG_MAPPABLE_VADDR
+#define USER_VM_SIZE		0x80000000
+
+/*  Size of page table:  */
+
+#define PGTABLE_SIZE_BITS	(32 - XCHAL_MMU_MIN_PTE_PAGE_SIZE + 2)
+#define PGTABLE_SIZE		(1L << PGTABLE_SIZE_BITS)
+
+/*  All kernel-mappable space:  */
+
+#define KERNEL_ALLMAP_START	(USER_VM_START + USER_VM_SIZE)
+#define KERNEL_ALLMAP_SIZE	(XCHAL_SEG_MAPPABLE_SIZE - KERNEL_ALLMAP_START)
+
+/*  Carve out page table at start of kernel-mappable area:  */
+
+#if KERNEL_ALLMAP_SIZE < PGTABLE_SIZE
+#error "Gimme some space for page table!"
+#endif
+#define PGTABLE_START		KERNEL_ALLMAP_START
+
+/*  Remaining kernel-mappable space:  */
+
+#define KERNEL_MAPPED_START	(KERNEL_ALLMAP_START + PGTABLE_SIZE)
+#define KERNEL_MAPPED_SIZE	(KERNEL_ALLMAP_SIZE - PGTABLE_SIZE)
+
+#if KERNEL_MAPPED_SIZE < 0x01000000	/* 16 MB is arbitrary for now */
+# error "Shouldn't the kernel have at least *some* mappable space?"
+#endif
+
+#define MAX_LOW_MEMORY		XCHAL_KSEG_CACHED_SIZE
+
+#endif
+
+/*
+ *  Some constants used elsewhere, but perhaps only in Xtensa header
+ *  files, so maybe we can get rid of some and access compile-time HAL
+ *  directly...
+ *
+ *  Note:  We assume that system RAM is located at the very start of the
+ *  	   kernel segments !!
+ */
+#define KERNEL_VM_LOW           XCHAL_KSEG_CACHED_VADDR
+#define KERNEL_VM_HIGH          XCHAL_KSEG_BYPASS_VADDR
+#define KERNEL_SPACE            XCHAL_KSEG_CACHED_VADDR
+
+/*
+ * Returns the physical/virtual addresses of the kernel space
+ * (works with the cached kernel segment only, which is the
+ *  one normally used for kernel operation).
+ */
+
+/*			PHYSICAL	BYPASS		CACHED
+ *
+ *  bypass vaddr	bypass paddr	*		cached vaddr
+ *  cached vaddr	cached paddr	bypass vaddr	*
+ *  bypass paddr	*		bypass vaddr	cached vaddr
+ *  cached paddr	*		bypass vaddr	cached vaddr
+ *  other		*		*		*
+ */
+
+#define PHYSADDR(a)							      \
+(((unsigned)(a) >= XCHAL_KSEG_BYPASS_VADDR				      \
+  && (unsigned)(a) < XCHAL_KSEG_BYPASS_VADDR + XCHAL_KSEG_BYPASS_SIZE) ?      \
+    (unsigned)(a) - XCHAL_KSEG_BYPASS_VADDR + XCHAL_KSEG_BYPASS_PADDR :       \
+    ((unsigned)(a) >= XCHAL_KSEG_CACHED_VADDR				      \
+     && (unsigned)(a) < XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_CACHED_SIZE) ?   \
+        (unsigned)(a) - XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_CACHED_PADDR :   \
+	(unsigned)(a))
+
+#define BYPASS_ADDR(a)							      \
+(((unsigned)(a) >= XCHAL_KSEG_BYPASS_PADDR				      \
+  && (unsigned)(a) < XCHAL_KSEG_BYPASS_PADDR + XCHAL_KSEG_BYPASS_SIZE) ?      \
+    (unsigned)(a) - XCHAL_KSEG_BYPASS_PADDR + XCHAL_KSEG_BYPASS_VADDR :       \
+    ((unsigned)(a) >= XCHAL_KSEG_CACHED_PADDR				      \
+     && (unsigned)(a) < XCHAL_KSEG_CACHED_PADDR + XCHAL_KSEG_CACHED_SIZE) ?   \
+        (unsigned)(a) - XCHAL_KSEG_CACHED_PADDR + XCHAL_KSEG_BYPASS_VADDR :   \
+        ((unsigned)(a) >= XCHAL_KSEG_CACHED_VADDR			      \
+         && (unsigned)(a) < XCHAL_KSEG_CACHED_VADDR+XCHAL_KSEG_CACHED_SIZE)?  \
+            (unsigned)(a) - XCHAL_KSEG_CACHED_VADDR+XCHAL_KSEG_BYPASS_VADDR:  \
+	    (unsigned)(a))
+
+#define CACHED_ADDR(a)							      \
+(((unsigned)(a) >= XCHAL_KSEG_BYPASS_PADDR				      \
+  && (unsigned)(a) < XCHAL_KSEG_BYPASS_PADDR + XCHAL_KSEG_BYPASS_SIZE) ?      \
+    (unsigned)(a) - XCHAL_KSEG_BYPASS_PADDR + XCHAL_KSEG_CACHED_VADDR :       \
+    ((unsigned)(a) >= XCHAL_KSEG_CACHED_PADDR			              \
+     && (unsigned)(a) < XCHAL_KSEG_CACHED_PADDR + XCHAL_KSEG_CACHED_SIZE) ?   \
+        (unsigned)(a) - XCHAL_KSEG_CACHED_PADDR + XCHAL_KSEG_CACHED_VADDR :   \
+        ((unsigned)(a) >= XCHAL_KSEG_BYPASS_VADDR			      \
+         && (unsigned)(a) < XCHAL_KSEG_BYPASS_VADDR+XCHAL_KSEG_BYPASS_SIZE) ? \
+            (unsigned)(a) - XCHAL_KSEG_BYPASS_VADDR+XCHAL_KSEG_CACHED_VADDR : \
+	    (unsigned)(a))
+
+#define PHYSADDR_IO(a)							      \
+(((unsigned)(a) >= XCHAL_KIO_BYPASS_VADDR				      \
+  && (unsigned)(a) < XCHAL_KIO_BYPASS_VADDR + XCHAL_KIO_BYPASS_SIZE) ?	      \
+    (unsigned)(a) - XCHAL_KIO_BYPASS_VADDR + XCHAL_KIO_BYPASS_PADDR :	      \
+    ((unsigned)(a) >= XCHAL_KIO_CACHED_VADDR				      \
+     && (unsigned)(a) < XCHAL_KIO_CACHED_VADDR + XCHAL_KIO_CACHED_SIZE) ?     \
+        (unsigned)(a) - XCHAL_KIO_CACHED_VADDR + XCHAL_KIO_CACHED_PADDR :     \
+	(unsigned)(a))
+
+#define BYPASS_ADDR_IO(a)						      \
+(((unsigned)(a) >= XCHAL_KIO_BYPASS_PADDR				      \
+  && (unsigned)(a) < XCHAL_KIO_BYPASS_PADDR + XCHAL_KIO_BYPASS_SIZE) ?	      \
+    (unsigned)(a) - XCHAL_KIO_BYPASS_PADDR + XCHAL_KIO_BYPASS_VADDR :	      \
+    ((unsigned)(a) >= XCHAL_KIO_CACHED_PADDR				      \
+     && (unsigned)(a) < XCHAL_KIO_CACHED_PADDR + XCHAL_KIO_CACHED_SIZE) ?     \
+        (unsigned)(a) - XCHAL_KIO_CACHED_PADDR + XCHAL_KIO_BYPASS_VADDR :     \
+        ((unsigned)(a) >= XCHAL_KIO_CACHED_VADDR			      \
+         && (unsigned)(a) < XCHAL_KIO_CACHED_VADDR + XCHAL_KIO_CACHED_SIZE) ? \
+            (unsigned)(a) - XCHAL_KIO_CACHED_VADDR + XCHAL_KIO_BYPASS_VADDR : \
+	    (unsigned)(a))
+
+#define CACHED_ADDR_IO(a)						      \
+(((unsigned)(a) >= XCHAL_KIO_BYPASS_PADDR				      \
+  && (unsigned)(a) < XCHAL_KIO_BYPASS_PADDR + XCHAL_KIO_BYPASS_SIZE) ?	      \
+    (unsigned)(a) - XCHAL_KIO_BYPASS_PADDR + XCHAL_KIO_CACHED_VADDR :	      \
+    ((unsigned)(a) >= XCHAL_KIO_CACHED_PADDR				      \
+     && (unsigned)(a) < XCHAL_KIO_CACHED_PADDR + XCHAL_KIO_CACHED_SIZE) ?     \
+        (unsigned)(a) - XCHAL_KIO_CACHED_PADDR + XCHAL_KIO_CACHED_VADDR :     \
+        ((unsigned)(a) >= XCHAL_KIO_BYPASS_VADDR			      \
+         && (unsigned)(a) < XCHAL_KIO_BYPASS_VADDR + XCHAL_KIO_BYPASS_SIZE) ? \
+            (unsigned)(a) - XCHAL_KIO_BYPASS_VADDR + XCHAL_KIO_CACHED_VADDR : \
+	    (unsigned)(a))
+
+#endif /* _XTENSA_ADDRSPACE_H */
+
+
+
+
+
diff --git a/include/asm-xtensa/hardirq.h b/include/asm-xtensa/hardirq.h
new file mode 100644
index 0000000..e07c76c
--- /dev/null
+++ b/include/asm-xtensa/hardirq.h
@@ -0,0 +1,28 @@
+/*
+ * include/asm-xtensa/hardirq.h
+ *
+ * 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) 2002 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_HARDIRQ_H
+#define _XTENSA_HARDIRQ_H
+
+#include <linux/config.h>
+#include <linux/cache.h>
+#include <asm/irq.h>
+
+/* headers.S is sensitive to the offsets of these fields */
+typedef struct {
+	unsigned int __softirq_pending;
+	unsigned int __syscall_count;
+	struct task_struct * __ksoftirqd_task; /* waitqueue is too large */
+	unsigned int __nmi_count;	       /* arch dependent */
+} ____cacheline_aligned irq_cpustat_t;
+
+#include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
+
+#endif	/* _XTENSA_HARDIRQ_H */
diff --git a/include/asm-xtensa/hdreg.h b/include/asm-xtensa/hdreg.h
new file mode 100644
index 0000000..64b8060
--- /dev/null
+++ b/include/asm-xtensa/hdreg.h
@@ -0,0 +1,17 @@
+/*
+ * include/asm-xtensa/hdreg.h
+ *
+ * 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) 2002 - 2005 Tensilica Inc.
+ * Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+#ifndef _XTENSA_HDREG_H
+#define _XTENSA_HDREG_H
+
+typedef unsigned int ide_ioreg_t;
+
+#endif
diff --git a/include/asm-xtensa/highmem.h b/include/asm-xtensa/highmem.h
new file mode 100644
index 0000000..0a046ca
--- /dev/null
+++ b/include/asm-xtensa/highmem.h
@@ -0,0 +1,17 @@
+/*
+ * include/asm-xtensa/highmem.h
+ *
+ * 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 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_HIGHMEM_H
+#define _XTENSA_HIGHMEM_H
+
+extern void flush_cache_kmaps(void);
+
+#endif
+
diff --git a/include/asm-xtensa/hw_irq.h b/include/asm-xtensa/hw_irq.h
new file mode 100644
index 0000000..ccf4362
--- /dev/null
+++ b/include/asm-xtensa/hw_irq.h
@@ -0,0 +1,18 @@
+/*
+ * include/asm-xtensa/hw_irq.h
+ *
+ * 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) 2002 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_HW_IRQ_H
+#define _XTENSA_HW_IRQ_H
+
+static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i)
+{
+}
+
+#endif
diff --git a/include/asm-xtensa/ide.h b/include/asm-xtensa/ide.h
new file mode 100644
index 0000000..b523cd4
--- /dev/null
+++ b/include/asm-xtensa/ide.h
@@ -0,0 +1,36 @@
+/*
+ * include/asm-xtensa/ide.h
+ *
+ * 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) 1994 - 1996  Linus Torvalds & authors
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_IDE_H
+#define _XTENSA_IDE_H
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+
+#ifndef MAX_HWIFS
+# define MAX_HWIFS	1
+#endif
+
+static __inline__ int ide_default_irq(unsigned long base)
+{
+	/* Unsupported! */
+  	return 0;
+}
+
+static __inline__ unsigned long ide_default_io_base(int index)
+{
+	/* Unsupported! */
+  	return 0;
+}
+
+#endif	/* __KERNEL__ */
+#endif	/* _XTENSA_IDE_H */
diff --git a/include/asm-xtensa/io.h b/include/asm-xtensa/io.h
new file mode 100644
index 0000000..2c471c4
--- /dev/null
+++ b/include/asm-xtensa/io.h
@@ -0,0 +1,197 @@
+/*
+ * linux/include/asm-xtensa/io.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_IO_H
+#define _XTENSA_IO_H
+
+#ifdef __KERNEL__
+#include <linux/config.h>
+#include <asm/byteorder.h>
+
+#include <linux/types.h>
+#include <asm/fixmap.h>
+
+#define _IO_BASE 0
+
+
+/*
+ * swap functions to change byte order from little-endian to big-endian and
+ * vice versa.
+ */
+
+static inline unsigned short _swapw (unsigned short v)
+{
+	return (v << 8) | (v >> 8);
+}
+
+static inline unsigned int _swapl (unsigned int v)
+{
+	return (v << 24) | ((v & 0xff00) << 8) | ((v >> 8) & 0xff00) | (v >> 24);
+}
+
+/*
+ * Change virtual addresses to physical addresses and vv.
+ * These are trivial on the 1:1 Linux/Xtensa mapping
+ */
+
+extern inline unsigned long virt_to_phys(volatile void * address)
+{
+	return PHYSADDR((unsigned long)address);
+}
+
+extern inline void * phys_to_virt(unsigned long address)
+{
+	return (void*) CACHED_ADDR(address);
+}
+
+/*
+ * IO bus memory addresses are also 1:1 with the physical address
+ */
+
+extern inline unsigned long virt_to_bus(volatile void * address)
+{
+	return PHYSADDR((unsigned long)address);
+}
+
+extern inline void * bus_to_virt (unsigned long address)
+{
+	return (void *) CACHED_ADDR(address);
+}
+
+/*
+ * Change "struct page" to physical address.
+ */
+
+extern inline void *ioremap(unsigned long offset, unsigned long size)
+{
+        return (void *) CACHED_ADDR_IO(offset);
+}
+
+extern inline void *ioremap_nocache(unsigned long offset, unsigned long size)
+{
+        return (void *) BYPASS_ADDR_IO(offset);
+}
+
+extern inline void iounmap(void *addr)
+{
+}
+
+/*
+ * Generic I/O
+ */
+
+#define readb(addr) \
+	({ unsigned char __v = (*(volatile unsigned char *)(addr)); __v; })
+#define readw(addr) \
+	({ unsigned short __v = (*(volatile unsigned short *)(addr)); __v; })
+#define readl(addr) \
+	({ unsigned int __v = (*(volatile unsigned int *)(addr)); __v; })
+#define writeb(b, addr) (void)((*(volatile unsigned char *)(addr)) = (b))
+#define writew(b, addr) (void)((*(volatile unsigned short *)(addr)) = (b))
+#define writel(b, addr) (void)((*(volatile unsigned int *)(addr)) = (b))
+
+static inline __u8 __raw_readb(const volatile void __iomem *addr)
+{
+          return *(__force volatile __u8 *)(addr);
+}
+static inline __u16 __raw_readw(const volatile void __iomem *addr)
+{
+          return *(__force volatile __u16 *)(addr);
+}
+static inline __u32 __raw_readl(const volatile void __iomem *addr)
+{
+          return *(__force volatile __u32 *)(addr);
+}
+static inline void __raw_writeb(__u8 b, volatile void __iomem *addr)
+{
+          *(__force volatile __u8 *)(addr) = b;
+}
+static inline void __raw_writew(__u16 b, volatile void __iomem *addr)
+{
+          *(__force volatile __u16 *)(addr) = b;
+}
+static inline void __raw_writel(__u32 b, volatile void __iomem *addr)
+{
+          *(__force volatile __u32 *)(addr) = b;
+}
+
+
+
+
+/* These are the definitions for the x86 IO instructions
+ * inb/inw/inl/outb/outw/outl, the "string" versions
+ * insb/insw/insl/outsb/outsw/outsl, and the "pausing" versions
+ * inb_p/inw_p/...
+ * The macros don't do byte-swapping.
+ */
+
+#define inb(port)		readb((u8 *)((port)+_IO_BASE))
+#define outb(val, port)		writeb((val),(u8 *)((unsigned long)(port)+_IO_BASE))
+#define inw(port)		readw((u16 *)((port)+_IO_BASE))
+#define outw(val, port)		writew((val),(u16 *)((unsigned long)(port)+_IO_BASE))
+#define inl(port)		readl((u32 *)((port)+_IO_BASE))
+#define outl(val, port)		writel((val),(u32 *)((unsigned long)(port)))
+
+#define inb_p(port)		inb((port))
+#define outb_p(val, port)	outb((val), (port))
+#define inw_p(port)		inw((port))
+#define outw_p(val, port)	outw((val), (port))
+#define inl_p(port)		inl((port))
+#define outl_p(val, port)	outl((val), (port))
+
+extern void insb (unsigned long port, void *dst, unsigned long count);
+extern void insw (unsigned long port, void *dst, unsigned long count);
+extern void insl (unsigned long port, void *dst, unsigned long count);
+extern void outsb (unsigned long port, const void *src, unsigned long count);
+extern void outsw (unsigned long port, const void *src, unsigned long count);
+extern void outsl (unsigned long port, const void *src, unsigned long count);
+
+#define IO_SPACE_LIMIT ~0
+
+#define memset_io(a,b,c)       memset((void *)(a),(b),(c))
+#define memcpy_fromio(a,b,c)   memcpy((a),(void *)(b),(c))
+#define memcpy_toio(a,b,c)      memcpy((void *)(a),(b),(c))
+
+/* At this point the Xtensa doesn't provide byte swap instructions */
+
+#ifdef __XTENSA_EB__
+# define in_8(addr) (*(u8*)(addr))
+# define in_le16(addr) _swapw(*(u16*)(addr))
+# define in_le32(addr) _swapl(*(u32*)(addr))
+# define out_8(b, addr) *(u8*)(addr) = (b)
+# define out_le16(b, addr) *(u16*)(addr) = _swapw(b)
+# define out_le32(b, addr) *(u32*)(addr) = _swapl(b)
+#elif defined(__XTENSA_EL__)
+# define in_8(addr)  (*(u8*)(addr))
+# define in_le16(addr) (*(u16*)(addr))
+# define in_le32(addr) (*(u32*)(addr))
+# define out_8(b, addr) *(u8*)(addr) = (b)
+# define out_le16(b, addr) *(u16*)(addr) = (b)
+# define out_le32(b, addr) *(u32*)(addr) = (b)
+#else
+# error processor byte order undefined!
+#endif
+
+
+/*
+ *  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ *   * access
+ *    */
+#define xlate_dev_mem_ptr(p)    __va(p)
+
+/*
+ *  * Convert a virtual cached pointer to an uncached pointer
+ *   */
+#define xlate_dev_kmem_ptr(p)   p
+
+
+#endif	/* __KERNEL__ */
+
+#endif	/* _XTENSA_IO_H */
diff --git a/include/asm-xtensa/ioctl.h b/include/asm-xtensa/ioctl.h
new file mode 100644
index 0000000..856c605
--- /dev/null
+++ b/include/asm-xtensa/ioctl.h
@@ -0,0 +1,83 @@
+/*
+ * include/asm-xtensa/ioctl.h
+ *
+ * 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 - 2005 Tensilica Inc.
+ *
+ * Derived from "include/asm-i386/ioctl.h"
+ */
+
+#ifndef _XTENSA_IOCTL_H
+#define _XTENSA_IOCTL_H
+
+
+/* ioctl command encoding: 32 bits total, command in lower 16 bits,
+ * size of the parameter structure in the lower 14 bits of the
+ * upper 16 bits.
+ * Encoding the size of the parameter structure in the ioctl request
+ * is useful for catching programs compiled with old versions
+ * and to avoid overwriting user space outside the user buffer area.
+ * The highest 2 bits are reserved for indicating the ``access mode''.
+ * NOTE: This limits the max parameter size to 16kB -1 !
+ */
+
+/*
+ * The following is for compatibility across the various Linux
+ * platforms.  The i386 ioctl numbering scheme doesn't really enforce
+ * a type field.  De facto, however, the top 8 bits of the lower 16
+ * bits are indeed used as a type field, so we might just as well make
+ * this explicit here.  Please be sure to use the decoding macros
+ * below from now on.
+ */
+#define _IOC_NRBITS	8
+#define _IOC_TYPEBITS	8
+#define _IOC_SIZEBITS	14
+#define _IOC_DIRBITS	2
+
+#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
+#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
+#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
+#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
+
+#define _IOC_NRSHIFT	0
+#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
+#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
+#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
+
+/*
+ * Direction bits.
+ */
+#define _IOC_NONE	0U
+#define _IOC_WRITE	1U
+#define _IOC_READ	2U
+
+#define _IOC(dir,type,nr,size) \
+	(((dir)  << _IOC_DIRSHIFT) | \
+	 ((type) << _IOC_TYPESHIFT) | \
+	 ((nr)   << _IOC_NRSHIFT) | \
+	 ((size) << _IOC_SIZESHIFT))
+
+/* used to create numbers */
+#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+
+/* used to decode ioctl numbers.. */
+#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
+#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
+#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
+#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
+
+/* ...and for the drivers/sound files... */
+
+#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
+#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
+#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
+#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
+#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
+
+#endif
diff --git a/include/asm-xtensa/ioctls.h b/include/asm-xtensa/ioctls.h
new file mode 100644
index 0000000..10c4434
--- /dev/null
+++ b/include/asm-xtensa/ioctls.h
@@ -0,0 +1,112 @@
+/*
+ * include/asm-xtensa/ioctl.h
+ *
+ * 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 - 2005 Tensilica Inc.
+ *
+ * Derived from "include/asm-i386/ioctls.h"
+ */
+
+#ifndef _XTENSA_IOCTLS_H
+#define _XTENSA_IOCTLS_H
+
+#include <asm/ioctl.h>
+
+#define FIOCLEX		_IO('f', 1)
+#define FIONCLEX	_IO('f', 2)
+#define FIOASYNC	_IOW('f', 125, int)
+#define FIONBIO		_IOW('f', 126, int)
+#define FIONREAD	_IOR('f', 127, int)
+#define TIOCINQ		FIONREAD
+#define FIOQSIZE	_IOR('f', 128, loff_t)
+
+#define TCGETS		0x5401
+#define TCSETS		0x5402
+#define TCSETSW		0x5403
+#define TCSETSF		0x5404
+
+#define TCGETA		_IOR('t', 23, struct termio)
+#define TCSETA		_IOW('t', 24, struct termio)
+#define TCSETAW		_IOW('t', 25, struct termio)
+#define TCSETAF		_IOW('t', 28, struct termio)
+
+#define TCSBRK		_IO('t', 29)
+#define TCXONC		_IO('t', 30)
+#define TCFLSH		_IO('t', 31)
+
+#define TIOCSWINSZ	_IOW('t', 103, struct winsize)
+#define TIOCGWINSZ	_IOR('t', 104, struct winsize)
+#define	TIOCSTART	_IO('t', 110)		/* start output, like ^Q */
+#define	TIOCSTOP	_IO('t', 111)		/* stop output, like ^S */
+#define TIOCOUTQ        _IOR('t', 115, int)     /* output queue size */
+
+#define TIOCSPGRP	_IOW('t', 118, int)
+#define TIOCGPGRP	_IOR('t', 119, int)
+
+#define TIOCEXCL	_IO('T', 12)
+#define TIOCNXCL	_IO('T', 13)
+#define TIOCSCTTY	_IO('T', 14)
+
+#define TIOCSTI		_IOW('T', 18, char)
+#define TIOCMGET	_IOR('T', 21, unsigned int)
+#define TIOCMBIS	_IOW('T', 22, unsigned int)
+#define TIOCMBIC	_IOW('T', 23, unsigned int)
+#define TIOCMSET	_IOW('T', 24, unsigned int)
+# define TIOCM_LE	0x001
+# define TIOCM_DTR	0x002
+# define TIOCM_RTS	0x004
+# define TIOCM_ST	0x008
+# define TIOCM_SR	0x010
+# define TIOCM_CTS	0x020
+# define TIOCM_CAR	0x040
+# define TIOCM_RNG	0x080
+# define TIOCM_DSR	0x100
+# define TIOCM_CD	TIOCM_CAR
+# define TIOCM_RI	TIOCM_RNG
+
+#define TIOCGSOFTCAR	_IOR('T', 25, unsigned int)
+#define TIOCSSOFTCAR	_IOW('T', 26, unsigned int)
+#define TIOCLINUX	_IOW('T', 28, char)
+#define TIOCCONS	_IO('T', 29)
+#define TIOCGSERIAL	_IOR('T', 30, struct serial_struct)
+#define TIOCSSERIAL	_IOW('T', 31, struct serial_struct)
+#define TIOCPKT		_IOW('T', 32, int)
+# define TIOCPKT_DATA		 0
+# define TIOCPKT_FLUSHREAD	 1
+# define TIOCPKT_FLUSHWRITE	 2
+# define TIOCPKT_STOP		 4
+# define TIOCPKT_START		 8
+# define TIOCPKT_NOSTOP		16
+# define TIOCPKT_DOSTOP		32
+
+
+#define TIOCNOTTY	_IO('T', 34)
+#define TIOCSETD	_IOW('T', 35, int)
+#define TIOCGETD	_IOR('T', 36, int)
+#define TCSBRKP		_IOW('T', 37, int)   /* Needed for POSIX tcsendbreak()*/
+#define TIOCTTYGSTRUCT	_IOR('T', 38, struct tty_struct) /* For debugging only*/
+#define TIOCSBRK	_IO('T', 39) 	     /* BSD compatibility */
+#define TIOCCBRK	_IO('T', 40)	     /* BSD compatibility */
+#define TIOCGSID	_IOR('T', 41, pid_t) /* Return the session ID of FD*/
+#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
+
+#define TIOCSERCONFIG	_IO('T', 83)
+#define TIOCSERGWILD	_IOR('T', 84,  int)
+#define TIOCSERSWILD	_IOW('T', 85,  int)
+#define TIOCGLCKTRMIOS	0x5456
+#define TIOCSLCKTRMIOS	0x5457
+#define TIOCSERGSTRUCT	0x5458		     /* For debugging only */
+#define TIOCSERGETLSR   _IOR('T', 89, unsigned int) /* Get line status reg. */
+  /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+# define TIOCSER_TEMT    0x01		     /* Transmitter physically empty */
+#define TIOCSERGETMULTI _IOR('T', 90, struct serial_multiport_struct) /* Get multiport config  */
+#define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* Set multiport config */
+
+#define TIOCMIWAIT	_IO('T', 92) /* wait for a change on serial input line(s) */
+#define TIOCGICOUNT	_IOR('T', 93, struct async_icount) /* read serial port inline interrupt counts */
+
+#endif /* _XTENSA_IOCTLS_H */
diff --git a/include/asm-xtensa/ipc.h b/include/asm-xtensa/ipc.h
new file mode 100644
index 0000000..d37bdb4d4c
--- /dev/null
+++ b/include/asm-xtensa/ipc.h
@@ -0,0 +1,34 @@
+/*
+ * include/asm-xtensa/ipc.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_IPC_H
+#define _XTENSA_IPC_H
+
+struct ipc_kludge {
+	struct msgbuf __user *msgp;
+	long msgtyp;
+};
+
+#define SEMOP		 1
+#define SEMGET		 2
+#define SEMCTL		 3
+#define SEMTIMEDOP	 4
+#define MSGSND		11
+#define MSGRCV		12
+#define MSGGET		13
+#define MSGCTL		14
+#define SHMAT		21
+#define SHMDT		22
+#define SHMGET		23
+#define SHMCTL		24
+
+#define IPCCALL(version,op)	((version)<<16 | (op))
+
+#endif	/* _XTENSA_IPC_H */
diff --git a/include/asm-xtensa/ipcbuf.h b/include/asm-xtensa/ipcbuf.h
new file mode 100644
index 0000000..c33aa6a
--- /dev/null
+++ b/include/asm-xtensa/ipcbuf.h
@@ -0,0 +1,37 @@
+/*
+ * include/asm-xtensa/ipcbuf.h
+ *
+ * The ipc64_perm structure for the Xtensa architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_IPCBUF_H
+#define _XTENSA_IPCBUF_H
+
+/*
+ * Pad space is left for:
+ * - 32-bit mode_t and seq
+ * - 2 miscellaneous 32-bit values
+ *
+ * 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.
+ */
+
+struct ipc64_perm
+{
+	__kernel_key_t		key;
+	__kernel_uid32_t	uid;
+	__kernel_gid32_t	gid;
+	__kernel_uid32_t	cuid;
+	__kernel_gid32_t	cgid;
+	__kernel_mode_t		mode;
+	unsigned long		seq;
+	unsigned long		__unused1;
+	unsigned long		__unused2;
+};
+
+#endif /* _XTENSA_IPCBUF_H */
diff --git a/include/asm-xtensa/irq.h b/include/asm-xtensa/irq.h
new file mode 100644
index 0000000..d984e95
--- /dev/null
+++ b/include/asm-xtensa/irq.h
@@ -0,0 +1,37 @@
+/*
+ * include/asm-xtensa/irq.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_IRQ_H
+#define _XTENSA_IRQ_H
+
+#include <linux/config.h>
+#include <asm/platform/hardware.h>
+
+#include <xtensa/config/core.h>
+
+#ifndef PLATFORM_NR_IRQS
+# define PLATFORM_NR_IRQS 0
+#endif
+#define XTENSA_NR_IRQS XCHAL_NUM_INTERRUPTS
+#define NR_IRQS (XTENSA_NR_IRQS + PLATFORM_NR_IRQS)
+
+static __inline__ int irq_canonicalize(int irq)
+{
+	return (irq);
+}
+
+struct irqaction;
+#if 0 // FIXME
+extern void disable_irq_nosync(unsigned int);
+extern void disable_irq(unsigned int);
+extern void enable_irq(unsigned int);
+#endif
+
+#endif	/* _XTENSA_IRQ_H */
diff --git a/include/asm-xtensa/kmap_types.h b/include/asm-xtensa/kmap_types.h
new file mode 100644
index 0000000..9e822d2
--- /dev/null
+++ b/include/asm-xtensa/kmap_types.h
@@ -0,0 +1,31 @@
+/*
+ * include/asm-xtensa/kmap_types.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_KMAP_TYPES_H
+#define _XTENSA_KMAP_TYPES_H
+
+enum km_type {
+  KM_BOUNCE_READ,
+  KM_SKB_SUNRPC_DATA,
+  KM_SKB_DATA_SOFTIRQ,
+  KM_USER0,
+  KM_USER1,
+  KM_BIO_SRC_IRQ,
+  KM_BIO_DST_IRQ,
+  KM_PTE0,
+  KM_PTE1,
+  KM_IRQ0,
+  KM_IRQ1,
+  KM_SOFTIRQ0,
+  KM_SOFTIRQ1,
+  KM_TYPE_NR
+};
+
+#endif	/* _XTENSA_KMAP_TYPES_H */
diff --git a/include/asm-xtensa/linkage.h b/include/asm-xtensa/linkage.h
new file mode 100644
index 0000000..bf2128a
--- /dev/null
+++ b/include/asm-xtensa/linkage.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/linkage.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_LINKAGE_H
+#define _XTENSA_LINKAGE_H
+
+/* Nothing to do here ... */
+
+#endif	/* _XTENSA_LINKAGE_H */
diff --git a/include/asm-xtensa/local.h b/include/asm-xtensa/local.h
new file mode 100644
index 0000000..48723e5
--- /dev/null
+++ b/include/asm-xtensa/local.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/local.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_LOCAL_H
+#define _XTENSA_LOCAL_H
+
+#include <asm-generic/local.h>
+
+#endif /* _XTENSA_LOCAL_H */
diff --git a/include/asm-xtensa/mman.h b/include/asm-xtensa/mman.h
new file mode 100644
index 0000000..9a95a45
--- /dev/null
+++ b/include/asm-xtensa/mman.h
@@ -0,0 +1,80 @@
+/*
+ * include/asm-xtensa/mman.h
+ *
+ * Xtensa Processor memory-manager definitions
+ *
+ * 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 by Ralf Baechle
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_MMAN_H
+#define _XTENSA_MMAN_H
+
+/*
+ * Protections are chosen from these bits, OR'd together.  The
+ * implementation does not necessarily support PROT_EXEC or PROT_WRITE
+ * without PROT_READ.  The only guarantees are that no writing will be
+ * allowed without PROT_WRITE and no access will be allowed for PROT_NONE.
+ */
+
+#define PROT_NONE	0x0		/* page can not be accessed */
+#define PROT_READ	0x1		/* page can be read */
+#define PROT_WRITE	0x2		/* page can be written */
+#define PROT_EXEC	0x4		/* page can be executed */
+
+#define PROT_SEM	0x10		/* page may be used for atomic ops */
+#define PROT_GROWSDOWN	0x01000000	/* mprotect flag: extend change to start of growsdown vma */
+#define PROT_GROWSUP	0x02000000	/* mprotect flag: extend change to end fo growsup vma */
+
+/*
+ * Flags for mmap
+ */
+#define MAP_SHARED	0x001		/* Share changes */
+#define MAP_PRIVATE	0x002		/* Changes are private */
+#define MAP_TYPE	0x00f		/* Mask for type of mapping */
+#define MAP_FIXED	0x010		/* Interpret addr exactly */
+
+/* not used by linux, but here to make sure we don't clash with ABI defines */
+#define MAP_RENAME	0x020		/* Assign page to file */
+#define MAP_AUTOGROW	0x040		/* File may grow by writing */
+#define MAP_LOCAL	0x080		/* Copy on fork/sproc */
+#define MAP_AUTORSRV	0x100		/* Logical swap reserved on demand */
+
+/* These are linux-specific */
+#define MAP_NORESERVE	0x0400		/* don't check for reservations */
+#define MAP_ANONYMOUS	0x0800		/* don't use a file */
+#define MAP_GROWSDOWN	0x1000		/* stack-like segment */
+#define MAP_DENYWRITE	0x2000		/* ETXTBSY */
+#define MAP_EXECUTABLE	0x4000		/* mark it as an executable */
+#define MAP_LOCKED	0x8000		/* pages are locked */
+#define MAP_POPULATE	0x10000		/* populate (prefault) pagetables */
+#define MAP_NONBLOCK	0x20000		/* do not block on IO */
+
+/*
+ * Flags for msync
+ */
+#define MS_ASYNC	0x0001		/* sync memory asynchronously */
+#define MS_INVALIDATE	0x0002		/* invalidate mappings & caches */
+#define MS_SYNC		0x0004		/* synchronous memory sync */
+
+/*
+ * Flags for mlockall
+ */
+#define MCL_CURRENT	1		/* lock all current mappings */
+#define MCL_FUTURE	2		/* lock all future mappings */
+
+#define MADV_NORMAL	0x0		/* default page-in behavior */
+#define MADV_RANDOM	0x1		/* page-in minimum required */
+#define MADV_SEQUENTIAL	0x2		/* read-ahead aggressively */
+#define MADV_WILLNEED	0x3		/* pre-fault pages */
+#define MADV_DONTNEED	0x4		/* discard these pages */
+
+/* compatibility flags */
+#define MAP_ANON       MAP_ANONYMOUS
+#define MAP_FILE       0
+
+#endif /* _XTENSA_MMAN_H */
diff --git a/include/asm-xtensa/mmu.h b/include/asm-xtensa/mmu.h
new file mode 100644
index 0000000..44c5bb0
--- /dev/null
+++ b/include/asm-xtensa/mmu.h
@@ -0,0 +1,17 @@
+/*
+ * include/asm-xtensa/mmu.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_MMU_H
+#define _XTENSA_MMU_H
+
+/* Default "unsigned long" context */
+typedef unsigned long mm_context_t;
+
+#endif	/* _XTENSA_MMU_H */
diff --git a/include/asm-xtensa/mmu_context.h b/include/asm-xtensa/mmu_context.h
new file mode 100644
index 0000000..1b08015
--- /dev/null
+++ b/include/asm-xtensa/mmu_context.h
@@ -0,0 +1,330 @@
+/*
+ * include/asm-xtensa/mmu_context.h
+ *
+ * Switch an MMU context.
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_MMU_CONTEXT_H
+#define _XTENSA_MMU_CONTEXT_H
+
+#include <linux/config.h>
+#include <linux/stringify.h>
+
+#include <asm/pgtable.h>
+#include <asm/mmu_context.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+
+/*
+ * Linux was ported to Xtensa assuming all auto-refill ways in set 0
+ * had the same properties (a very likely assumption).  Multiple sets
+ * of auto-refill ways will still work properly, but not as optimally
+ * as the Xtensa designer may have assumed.
+ *
+ * We make this case a hard #error, killing the kernel build, to alert
+ * the developer to this condition (which is more likely an error).
+ * You super-duper clever developers can change it to a warning or
+ * remove it altogether if you think you know what you're doing.  :)
+ */
+
+#if (XCHAL_HAVE_TLBS != 1)
+# error "Linux must have an MMU!"
+#endif
+
+#if ((XCHAL_ITLB_ARF_WAYS == 0) || (XCHAL_DTLB_ARF_WAYS == 0))
+# error "MMU must have auto-refill ways"
+#endif
+
+#if ((XCHAL_ITLB_ARF_SETS != 1) || (XCHAL_DTLB_ARF_SETS != 1))
+# error Linux may not use all auto-refill ways as efficiently as you think
+#endif
+
+#if (XCHAL_MMU_MAX_PTE_PAGE_SIZE != XCHAL_MMU_MIN_PTE_PAGE_SIZE)
+# error Only one page size allowed!
+#endif
+
+extern unsigned long asid_cache;
+extern pgd_t *current_pgd;
+
+/*
+ * Define the number of entries per auto-refill way in set 0 of both I and D
+ * TLBs.  We deal only with set 0 here (an assumption further explained in
+ * assertions.h).  Also, define the total number of ARF entries in both TLBs.
+ */
+
+#define ITLB_ENTRIES_PER_ARF_WAY  (XCHAL_ITLB_SET(XCHAL_ITLB_ARF_SET0,ENTRIES))
+#define DTLB_ENTRIES_PER_ARF_WAY  (XCHAL_DTLB_SET(XCHAL_DTLB_ARF_SET0,ENTRIES))
+
+#define ITLB_ENTRIES							\
+ 	(ITLB_ENTRIES_PER_ARF_WAY * (XCHAL_ITLB_SET(XCHAL_ITLB_ARF_SET0,WAYS)))
+#define DTLB_ENTRIES							\
+	(DTLB_ENTRIES_PER_ARF_WAY * (XCHAL_DTLB_SET(XCHAL_DTLB_ARF_SET0,WAYS)))
+
+
+/*
+ * SMALLEST_NTLB_ENTRIES is the smaller of ITLB_ENTRIES and DTLB_ENTRIES.
+ * In practice, they are probably equal.  This macro simplifies function
+ * flush_tlb_range().
+ */
+
+#if (DTLB_ENTRIES < ITLB_ENTRIES)
+# define SMALLEST_NTLB_ENTRIES  DTLB_ENTRIES
+#else
+# define SMALLEST_NTLB_ENTRIES  ITLB_ENTRIES
+#endif
+
+
+/*
+ * asid_cache tracks only the ASID[USER_RING] field of the RASID special
+ * register, which is the current user-task asid allocation value.
+ * mm->context has the same meaning.  When it comes time to write the
+ * asid_cache or mm->context values to the RASID special register, we first
+ * shift the value left by 8, then insert the value.
+ * ASID[0] always contains the kernel's asid value, and we reserve three
+ * other asid values that we never assign to user tasks.
+ */
+
+#define ASID_INC	0x1
+#define ASID_MASK	((1 << XCHAL_MMU_ASID_BITS) - 1)
+
+/*
+ * XCHAL_MMU_ASID_INVALID is a configurable Xtensa processor constant
+ * indicating invalid address space.  XCHAL_MMU_ASID_KERNEL is a configurable
+ * Xtensa processor constant indicating the kernel address space.  They can
+ * be arbitrary values.
+ *
+ * We identify three more unique, reserved ASID values to use in the unused
+ * ring positions.  No other user process will be assigned these reserved
+ * ASID values.
+ *
+ * For example, given that
+ *
+ *	XCHAL_MMU_ASID_INVALID == 0
+ *	XCHAL_MMU_ASID_KERNEL  == 1
+ *
+ * the following maze of #if statements would generate
+ *
+ *	ASID_RESERVED_1        == 2
+ *	ASID_RESERVED_2        == 3
+ *	ASID_RESERVED_3        == 4
+ *	ASID_FIRST_NONRESERVED == 5
+ */
+
+#if (XCHAL_MMU_ASID_INVALID != XCHAL_MMU_ASID_KERNEL + 1)
+# define ASID_RESERVED_1         ((XCHAL_MMU_ASID_KERNEL + 1) & ASID_MASK)
+#else
+# define ASID_RESERVED_1         ((XCHAL_MMU_ASID_KERNEL + 2) & ASID_MASK)
+#endif
+
+#if (XCHAL_MMU_ASID_INVALID != ASID_RESERVED_1 + 1)
+# define ASID_RESERVED_2         ((ASID_RESERVED_1 + 1) & ASID_MASK)
+#else
+# define ASID_RESERVED_2         ((ASID_RESERVED_1 + 2) & ASID_MASK)
+#endif
+
+#if (XCHAL_MMU_ASID_INVALID != ASID_RESERVED_2 + 1)
+# define ASID_RESERVED_3         ((ASID_RESERVED_2 + 1) & ASID_MASK)
+#else
+# define ASID_RESERVED_3         ((ASID_RESERVED_2 + 2) & ASID_MASK)
+#endif
+
+#if (XCHAL_MMU_ASID_INVALID != ASID_RESERVED_3 + 1)
+# define ASID_FIRST_NONRESERVED  ((ASID_RESERVED_3 + 1) & ASID_MASK)
+#else
+# define ASID_FIRST_NONRESERVED  ((ASID_RESERVED_3 + 2) & ASID_MASK)
+#endif
+
+#define ASID_ALL_RESERVED ( ((ASID_RESERVED_1) << 24) + \
+                            ((ASID_RESERVED_2) << 16) + \
+                            ((ASID_RESERVED_3) <<  8) + \
+                            ((XCHAL_MMU_ASID_KERNEL))   )
+
+
+/*
+ * NO_CONTEXT is the invalid ASID value that we don't ever assign to
+ * any user or kernel context.  NO_CONTEXT is a better mnemonic than
+ * XCHAL_MMU_ASID_INVALID, so we use it in code instead.
+ */
+
+#define NO_CONTEXT   XCHAL_MMU_ASID_INVALID
+
+#if (KERNEL_RING != 0)
+# error The KERNEL_RING really should be zero.
+#endif
+
+#if (USER_RING >= XCHAL_MMU_RINGS)
+# error USER_RING cannot be greater than the highest numbered ring.
+#endif
+
+#if (USER_RING == KERNEL_RING)
+# error The user and kernel rings really should not be equal.
+#endif
+
+#if (USER_RING == 1)
+#define ASID_INSERT(x) ( ((ASID_RESERVED_1)   << 24) + \
+                         ((ASID_RESERVED_2)   << 16) + \
+                         (((x) & (ASID_MASK)) <<  8) + \
+                         ((XCHAL_MMU_ASID_KERNEL))   )
+
+#elif (USER_RING == 2)
+#define ASID_INSERT(x) ( ((ASID_RESERVED_1)   << 24) + \
+                         (((x) & (ASID_MASK)) << 16) + \
+                         ((ASID_RESERVED_2)   <<  8) + \
+                         ((XCHAL_MMU_ASID_KERNEL))   )
+
+#elif (USER_RING == 3)
+#define ASID_INSERT(x) ( (((x) & (ASID_MASK)) << 24) + \
+			 ((ASID_RESERVED_1)   << 16) + \
+                         ((ASID_RESERVED_2)   <<  8) + \
+                         ((XCHAL_MMU_ASID_KERNEL))   )
+
+#else
+#error Goofy value for USER_RING
+
+#endif /* USER_RING == 1 */
+
+
+/*
+ *  All unused by hardware upper bits will be considered
+ *  as a software asid extension.
+ */
+
+#define ASID_VERSION_MASK  ((unsigned long)~(ASID_MASK|(ASID_MASK-1)))
+#define ASID_FIRST_VERSION						\
+	((unsigned long)(~ASID_VERSION_MASK) + 1 + ASID_FIRST_NONRESERVED)
+
+extern inline void set_rasid_register (unsigned long val)
+{
+	__asm__ __volatile__ (" wsr %0, "__stringify(RASID)"\n\t"
+			      " isync\n" : : "a" (val));
+}
+
+extern inline unsigned long get_rasid_register (void)
+{
+	unsigned long tmp;
+	__asm__ __volatile__ (" rsr %0, "__stringify(RASID)"\n\t" : "=a" (tmp));
+	return tmp;
+}
+
+
+#if ((XCHAL_MMU_ASID_INVALID == 0) && (XCHAL_MMU_ASID_KERNEL == 1))
+
+extern inline void
+get_new_mmu_context(struct mm_struct *mm, unsigned long asid)
+{
+	extern void flush_tlb_all(void);
+	if (! ((asid += ASID_INC) & ASID_MASK) ) {
+		flush_tlb_all(); /* start new asid cycle */
+		if (!asid)      /* fix version if needed */
+			asid = ASID_FIRST_VERSION - ASID_FIRST_NONRESERVED;
+		asid += ASID_FIRST_NONRESERVED;
+	}
+	mm->context = asid_cache = asid;
+}
+
+#else
+#warning ASID_{INVALID,KERNEL} values impose non-optimal get_new_mmu_context implementation
+
+/* XCHAL_MMU_ASID_INVALID == 0 and XCHAL_MMU_ASID_KERNEL ==1 are
+   really the best, but if you insist... */
+
+extern inline int validate_asid (unsigned long asid)
+{
+	switch (asid) {
+	case XCHAL_MMU_ASID_INVALID:
+	case XCHAL_MMU_ASID_KERNEL:
+	case ASID_RESERVED_1:
+	case ASID_RESERVED_2:
+	case ASID_RESERVED_3:
+		return 0; /* can't use these values as ASIDs */
+	}
+	return 1; /* valid */
+}
+
+extern inline void
+get_new_mmu_context(struct mm_struct *mm, unsigned long asid)
+{
+	extern void flush_tlb_all(void);
+	while (1) {
+		asid += ASID_INC;
+		if ( ! (asid & ASID_MASK) ) {
+			flush_tlb_all(); /* start new asid cycle */
+			if (!asid)      /* fix version if needed */
+				asid = ASID_FIRST_VERSION - ASID_FIRST_NONRESERVED;
+			asid += ASID_FIRST_NONRESERVED;
+			break; /* no need to validate here */
+		}
+		if (validate_asid (asid & ASID_MASK))
+			break;
+	}
+	mm->context = asid_cache = asid;
+}
+
+#endif
+
+
+/*
+ * Initialize the context related info for a new mm_struct
+ * instance.
+ */
+
+extern inline int
+init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+	mm->context = NO_CONTEXT;
+	return 0;
+}
+
+extern inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+                             struct task_struct *tsk)
+{
+	unsigned long asid = asid_cache;
+
+	/* Check if our ASID is of an older version and thus invalid */
+
+	if ((next->context ^ asid) & ASID_VERSION_MASK)
+		get_new_mmu_context(next, asid);
+
+	set_rasid_register (ASID_INSERT(next->context));
+	invalidate_page_directory();
+}
+
+#define deactivate_mm(tsk, mm)	do { } while(0)
+
+/*
+ * Destroy context related info for an mm_struct that is about
+ * to be put to rest.
+ */
+extern inline void destroy_context(struct mm_struct *mm)
+{
+	/* Nothing to do. */
+}
+
+/*
+ * After we have set current->mm to a new value, this activates
+ * the context for the new mm so we see the new mappings.
+ */
+extern inline void
+activate_mm(struct mm_struct *prev, struct mm_struct *next)
+{
+	/* Unconditionally get a new ASID.  */
+
+	get_new_mmu_context(next, asid_cache);
+	set_rasid_register (ASID_INSERT(next->context));
+	invalidate_page_directory();
+}
+
+
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+{
+	/* Nothing to do. */
+
+}
+
+#endif /* _XTENSA_MMU_CONTEXT_H */
diff --git a/include/asm-xtensa/module.h b/include/asm-xtensa/module.h
new file mode 100644
index 0000000..ffb25bf
--- /dev/null
+++ b/include/asm-xtensa/module.h
@@ -0,0 +1,25 @@
+/*
+ * include/asm-xtensa/module.h
+ *
+ * This file contains the module code specific to the Xtensa architecture.
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_MODULE_H
+#define _XTENSA_MODULE_H
+
+struct mod_arch_specific
+{
+	/* Module support is not completely implemented. */
+};
+
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Ehdr Elf32_Ehdr
+
+#endif	/* _XTENSA_MODULE_H */
diff --git a/include/asm-xtensa/msgbuf.h b/include/asm-xtensa/msgbuf.h
new file mode 100644
index 0000000..693c967
--- /dev/null
+++ b/include/asm-xtensa/msgbuf.h
@@ -0,0 +1,48 @@
+/*
+ * include/asm-xtensa/msgbuf.h
+ *
+ * The msqid64_ds structure for the Xtensa architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ *
+ * 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.
+ */
+
+#ifndef _XTENSA_MSGBUF_H
+#define _XTENSA_MSGBUF_H
+
+struct msqid64_ds {
+	struct ipc64_perm msg_perm;
+#ifdef __XTENSA_EB__
+	unsigned int	__unused1;
+	__kernel_time_t msg_stime;	/* last msgsnd time */
+	unsigned int	__unused2;
+	__kernel_time_t msg_rtime;	/* last msgrcv time */
+	unsigned int	__unused3;
+	__kernel_time_t msg_ctime;	/* last change time */
+#elif defined(__XTENSA_EL__)
+	__kernel_time_t msg_stime;	/* last msgsnd time */
+	unsigned int	__unused1;
+	__kernel_time_t msg_rtime;	/* last msgrcv time */
+	unsigned int	__unused2;
+	__kernel_time_t msg_ctime;	/* last change time */
+	unsigned int	__unused3;
+#else
+# error processor byte order undefined!
+#endif
+	unsigned long  msg_cbytes;	/* current number of bytes on queue */
+	unsigned long  msg_qnum;	/* number of messages in queue */
+	unsigned long  msg_qbytes;	/* max number of bytes on queue */
+	__kernel_pid_t msg_lspid;	/* pid of last msgsnd */
+	__kernel_pid_t msg_lrpid;	/* last receive pid */
+	unsigned long  __unused4;
+	unsigned long  __unused5;
+};
+
+#endif	/* _XTENSA_MSGBUF_H */
diff --git a/include/asm-xtensa/namei.h b/include/asm-xtensa/namei.h
new file mode 100644
index 0000000..3fdff03
--- /dev/null
+++ b/include/asm-xtensa/namei.h
@@ -0,0 +1,26 @@
+/*
+ * include/asm-xtensa/namei.h
+ *
+ * Included from linux/fs/namei.c
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_NAMEI_H
+#define _XTENSA_NAMEI_H
+
+#ifdef __KERNEL__
+
+/* This dummy routine maybe changed to something useful
+ * for /usr/gnemul/ emulation stuff.
+ * Look at asm-sparc/namei.h for details.
+ */
+
+#define __emul_prefix() NULL
+
+#endif	/* __KERNEL__ */
+#endif	/* _XTENSA_NAMEI_H */
diff --git a/include/asm-xtensa/page.h b/include/asm-xtensa/page.h
new file mode 100644
index 0000000..b495e5b
--- /dev/null
+++ b/include/asm-xtensa/page.h
@@ -0,0 +1,133 @@
+/*
+ * linux/include/asm-xtensa/page.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version2 as
+ * published by the Free Software Foundation.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PAGE_H
+#define _XTENSA_PAGE_H
+
+#ifdef __KERNEL__
+
+#include <asm/processor.h>
+#include <linux/config.h>
+
+/*
+ * PAGE_SHIFT determines the page size
+ * PAGE_ALIGN(x) aligns the pointer to the (next) page boundary
+ */
+
+#define PAGE_SHIFT		XCHAL_MMU_MIN_PTE_PAGE_SIZE
+#define PAGE_SIZE		(1 << PAGE_SHIFT)
+#define PAGE_MASK		(~(PAGE_SIZE-1))
+#define PAGE_ALIGN(addr)	(((addr)+PAGE_SIZE - 1) & PAGE_MASK)
+
+#define DCACHE_WAY_SIZE		(XCHAL_DCACHE_SIZE / XCHAL_DCACHE_WAYS)
+#define PAGE_OFFSET		XCHAL_KSEG_CACHED_VADDR
+
+#ifdef __ASSEMBLY__
+
+#define __pgprot(x)	(x)
+
+#else
+
+/*
+ * These are used to make use of C type-checking..
+ */
+
+typedef struct { unsigned long pte; } pte_t;		/* page table entry */
+typedef struct { unsigned long pgd; } pgd_t;		/* PGD table entry */
+typedef struct { unsigned long pgprot; } pgprot_t;
+
+#define pte_val(x)	((x).pte)
+#define pgd_val(x)	((x).pgd)
+#define pgprot_val(x)	((x).pgprot)
+
+#define __pte(x)	((pte_t) { (x) } )
+#define __pgd(x)	((pgd_t) { (x) } )
+#define __pgprot(x)	((pgprot_t) { (x) } )
+
+/*
+ * Pure 2^n version of get_order
+ */
+
+extern __inline__ int get_order(unsigned long size)
+{
+	int order;
+#ifndef XCHAL_HAVE_NSU
+	unsigned long x1, x2, x4, x8, x16;
+
+	size = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	x1  = size & 0xAAAAAAAA;
+	x2  = size & 0xCCCCCCCC;
+	x4  = size & 0xF0F0F0F0;
+	x8  = size & 0xFF00FF00;
+	x16 = size & 0xFFFF0000;
+	order = x2 ? 2 : 0;
+	order += (x16 != 0) * 16;
+	order += (x8 != 0) * 8;
+	order += (x4 != 0) * 4;
+	order += (x1 != 0);
+
+	return order;
+#else
+	size = (size - 1) >> PAGE_SHIFT;
+	asm ("nsau %0, %1" : "=r" (order) : "r" (size));
+	return 32 - order;
+#endif
+}
+
+
+struct page;
+extern void clear_page(void *page);
+extern void copy_page(void *to, void *from);
+
+/*
+ * If we have cache aliasing and writeback caches, we might have to do
+ * some extra work
+ */
+
+#if (DCACHE_WAY_SIZE > PAGE_SIZE)
+void clear_user_page(void *addr, unsigned long vaddr, struct page* page);
+void copy_user_page(void *to,void* from,unsigned long vaddr,struct page* page);
+#else
+# define clear_user_page(page,vaddr,pg)		clear_page(page)
+# define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
+#endif
+
+/*
+ * This handles the memory map.  We handle pages at
+ * XCHAL_KSEG_CACHED_VADDR for kernels with 32 bit address space.
+ * These macros are for conversion of kernel address, not user
+ * addresses.
+ */
+
+#define __pa(x)			((unsigned long) (x) - PAGE_OFFSET)
+#define __va(x)			((void *)((unsigned long) (x) + PAGE_OFFSET))
+#define pfn_valid(pfn)		((unsigned long)pfn < max_mapnr)
+#ifndef CONFIG_DISCONTIGMEM
+# define pfn_to_page(pfn)	(mem_map + (pfn))
+# define page_to_pfn(page)	((unsigned long)((page) - mem_map))
+#else
+# error CONFIG_DISCONTIGMEM not supported
+#endif
+
+#define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+#define page_to_virt(page)	__va(page_to_pfn(page) << PAGE_SHIFT)
+#define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+#define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
+
+#define WANT_PAGE_VIRTUAL
+
+
+#endif /* __ASSEMBLY__ */
+
+#define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
+				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#endif /* __KERNEL__ */
+#endif /* _XTENSA_PAGE_H */
diff --git a/include/asm-xtensa/page.h.n b/include/asm-xtensa/page.h.n
new file mode 100644
index 0000000..546cc66
--- /dev/null
+++ b/include/asm-xtensa/page.h.n
@@ -0,0 +1,135 @@
+/*
+ * linux/include/asm-xtensa/page.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version2 as
+ * published by the Free Software Foundation.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PAGE_H
+#define _XTENSA_PAGE_H
+
+#ifdef __KERNEL__
+
+#include <asm/processor.h>
+#include <linux/config.h>
+
+/*
+ * PAGE_SHIFT determines the page size
+ * PAGE_ALIGN(x) aligns the pointer to the (next) page boundary
+ */
+#define PAGE_SHIFT		XCHAL_MMU_MIN_PTE_PAGE_SIZE
+#define PAGE_SIZE		(1 << PAGE_SHIFT)
+#define PAGE_MASK		(~(PAGE_SIZE-1))
+#define PAGE_ALIGN(addr)	(((addr)+PAGE_SIZE - 1) & PAGE_MASK)
+
+#define DCACHE_WAY_SIZE		(XCHAL_DCACHE_SIZE / XCHAL_DCACHE_WAYS)
+#define PAGE_OFFSET		XCHAL_KSEG_CACHED_VADDR
+
+#ifdef __ASSEMBLY__
+
+#define __pgprot(x)	(x)
+
+#else
+
+
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { unsigned long pte; } pte_t;		/* page table entry */
+typedef struct { unsigned long pmd; } pmd_t;		/* PMD table entry */
+typedef struct { unsigned long pgd; } pgd_t;		/* PGD table entry */
+typedef struct { unsigned long pgprot; } pgprot_t;
+
+#define pte_val(x)	((x).pte)
+#define pmd_val(x)	((x).pmd)
+#define pgd_val(x)	((x).pgd)
+#define pgprot_val(x)	((x).pgprot)
+
+#define __pte(x)	((pte_t) { (x) } )
+#define __pmd(x)	((pmd_t) { (x) } )
+#define __pgd(x)	((pgd_t) { (x) } )
+#define __pgprot(x)	((pgprot_t) { (x) } )
+
+/*
+ * Pure 2^n version of get_order
+ */
+extern __inline__ int get_order(unsigned long size)
+{
+	int order;
+#ifndef XCHAL_HAVE_NSU
+	unsigned long x1, x2, x4, x8, x16;
+
+	size = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	x1  = size & 0xAAAAAAAA;
+	x2  = size & 0xCCCCCCCC;
+	x4  = size & 0xF0F0F0F0;
+	x8  = size & 0xFF00FF00;
+	x16 = size & 0xFFFF0000;
+	order = x2 ? 2 : 0;
+	order += (x16 != 0) * 16;
+	order += (x8 != 0) * 8;
+	order += (x4 != 0) * 4;
+	order += (x1 != 0);
+
+	return order;
+#else
+	size = (size - 1) >> PAGE_SHIFT;
+	asm ("nsau %0, %1" : "=r" (order) : "r" (size));
+	return 32 - order;
+#endif
+}
+
+
+struct page;
+extern void clear_page(void *page);
+extern void copy_page(void *to, void *from);
+
+/*
+ * If we have cache aliasing and writeback caches, we might have to do
+ * some extra work
+ */
+
+#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
+void clear_user_page(void *addr, unsigned long vaddr, struct page* page);
+void copy_user_page(void *to, void* from, unsigned long vaddr, struct page* page);
+#else
+# define clear_user_page(page,vaddr,pg)		clear_page(page)
+# define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
+#endif
+
+
+/*
+ * This handles the memory map.  We handle pages at
+ * XCHAL_KSEG_CACHED_VADDR for kernels with 32 bit address space.
+ * These macros are for conversion of kernel address, not user
+ * addresses.
+ */
+
+#define __pa(x)			((unsigned long) (x) - PAGE_OFFSET)
+#define __va(x)			((void *)((unsigned long) (x) + PAGE_OFFSET))
+#define pfn_valid(pfn)		((unsigned long)pfn < max_mapnr)
+#ifndef CONFIG_DISCONTIGMEM
+# define pfn_to_page(pfn)	(mem_map + (pfn))
+# define page_to_pfn(page)	((unsigned long)((page) - mem_map))
+#else
+# error CONFIG_DISCONTIGMEM not supported
+#endif
+
+#define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+#define page_to_virt(page)	__va(page_to_pfn(page) << PAGE_SHIFT)
+#define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
+#define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
+
+#define WANT_PAGE_VIRTUAL
+
+
+#endif /* __ASSEMBLY__ */
+
+#define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
+				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#endif /* __KERNEL__ */
+#endif /* _XTENSA_PAGE_H */
diff --git a/include/asm-xtensa/param.h b/include/asm-xtensa/param.h
new file mode 100644
index 0000000..c0eec82
--- /dev/null
+++ b/include/asm-xtensa/param.h
@@ -0,0 +1,34 @@
+/*
+ * include/asm-xtensa/param.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PARAM_H
+#define _XTENSA_PARAM_H
+
+#include <xtensa/config/core.h>
+
+#ifdef __KERNEL__
+# define HZ		100		/* internal timer frequency */
+# define USER_HZ	100		/* for user interfaces in "ticks" */
+# define CLOCKS_PER_SEC (USER_HZ)	/* frequnzy at which times() counts */
+#endif
+
+#define EXEC_PAGESIZE	(1 << XCHAL_MMU_MIN_PTE_PAGE_SIZE)
+
+#ifndef NGROUPS
+#define NGROUPS		32
+#endif
+
+#ifndef NOGROUP
+#define NOGROUP		(-1)
+#endif
+
+#define MAXHOSTNAMELEN	64	/* max length of hostname */
+
+#endif /* _XTENSA_PARAM_H */
diff --git a/include/asm-xtensa/pci-bridge.h b/include/asm-xtensa/pci-bridge.h
new file mode 100644
index 0000000..00fcbd7
--- /dev/null
+++ b/include/asm-xtensa/pci-bridge.h
@@ -0,0 +1,88 @@
+/*
+ * include/asm-xtensa/pci-bridge.h
+ *
+ * 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 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PCI_BRIDGE_H
+#define _XTENSA_PCI_BRIDGE_H
+
+#ifdef __KERNEL__
+
+struct device_node;
+struct pci_controller;
+
+/*
+ * pciauto_bus_scan() enumerates the pci space.
+ */
+
+extern int pciauto_bus_scan(struct pci_controller *, int);
+
+struct pci_space {
+	unsigned long start;
+	unsigned long end;
+	unsigned long base;
+};
+
+/*
+ * Structure of a PCI controller (host bridge)
+ */
+
+struct pci_controller {
+	int index;			/* used for pci_controller_num */
+	struct pci_controller *next;
+        struct pci_bus *bus;
+	void *arch_data;
+
+	int first_busno;
+	int last_busno;
+
+	struct pci_ops *ops;
+	volatile unsigned int *cfg_addr;
+	volatile unsigned char *cfg_data;
+
+	/* Currently, we limit ourselves to 1 IO range and 3 mem
+	 * ranges since the common pci_bus structure can't handle more
+	 */
+	struct resource	io_resource;
+	struct resource mem_resources[3];
+	int mem_resource_count;
+
+	/* Host bridge I/O and Memory space
+	 * Used for BAR placement algorithms
+	 */
+	struct pci_space io_space;
+	struct pci_space mem_space;
+
+	/* Return the interrupt number fo a device. */
+	int (*map_irq)(struct pci_dev*, u8, u8);
+
+};
+
+static inline void pcibios_init_resource(struct resource *res,
+		unsigned long start, unsigned long end, int flags, char *name)
+{
+	res->start = start;
+	res->end = end;
+	res->flags = flags;
+	res->name = name;
+	res->parent = NULL;
+	res->sibling = NULL;
+	res->child = NULL;
+}
+
+
+/* These are used for config access before all the PCI probing has been done. */
+int early_read_config_byte(struct pci_controller*, int, int, int, u8*);
+int early_read_config_word(struct pci_controller*, int, int, int, u16*);
+int early_read_config_dword(struct pci_controller*, int, int, int, u32*);
+int early_write_config_byte(struct pci_controller*, int, int, int, u8);
+int early_write_config_word(struct pci_controller*, int, int, int, u16);
+int early_write_config_dword(struct pci_controller*, int, int, int, u32);
+
+#endif	/* __KERNEL__ */
+#endif	/* _XTENSA_PCI_BRIDGE_H */
diff --git a/include/asm-xtensa/pci.h b/include/asm-xtensa/pci.h
new file mode 100644
index 0000000..6817742
--- /dev/null
+++ b/include/asm-xtensa/pci.h
@@ -0,0 +1,89 @@
+/*
+ * linux/include/asm-xtensa/pci.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PCI_H
+#define _XTENSA_PCI_H
+
+#ifdef __KERNEL__
+
+/* Can be used to override the logic in pci_scan_bus for skipping
+ * already-configured bus numbers - to be used for buggy BIOSes
+ * or architectures with incomplete PCI setup by the loader
+ */
+
+#define pcibios_assign_all_busses()	0
+
+extern struct pci_controller* pcibios_alloc_controller(void);
+
+extern inline void pcibios_set_master(struct pci_dev *dev)
+{
+	/* No special bus mastering setup handling */
+}
+
+extern inline void pcibios_penalize_isa_irq(int irq)
+{
+	/* We don't do dynamic PCI IRQ allocation */
+}
+
+/* Assume some values. (We should revise them, if necessary) */
+
+#define PCIBIOS_MIN_IO		0x2000
+#define PCIBIOS_MIN_MEM		0x10000000
+
+/* Dynamic DMA mapping stuff.
+ * Xtensa has everything mapped statically like x86.
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <asm/scatterlist.h>
+#include <linux/string.h>
+#include <asm/io.h>
+
+struct pci_dev;
+
+/* The PCI address space does equal the physical memory address space.
+ * The networking and block device layers use this boolean for bounce buffer
+ * decisions.
+ */
+
+#define PCI_DMA_BUS_IS_PHYS	(1)
+
+/* pci_unmap_{page,single} is a no-op, so */
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
+#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
+#define pci_unmap_addr(PTR, ADDR_NAME)		(0)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)	do { } while (0)
+#define pci_ubnmap_len(PTR, LEN_NAME)		(0)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
+
+/* We cannot access memory above 4GB */
+#define pci_dac_dma_supported(pci_dev, mask)	(0)
+
+/* Map a range of PCI memory or I/O space for a device into user space */
+int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
+                        enum pci_mmap_state mmap_state, int write_combine);
+
+/* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */
+#define HAVE_PCI_MMAP	1
+
+static inline void pcibios_add_platform_entries(struct pci_dev *dev)
+{
+}
+
+#endif /* __KERNEL__ */
+
+/* Implement the pci_ DMA API in terms of the generic device dma_ one */
+#include <asm-generic/pci-dma-compat.h>
+
+/* Generic PCI */
+#include <asm-generic/pci.h>
+
+#endif	/* _XTENSA_PCI_H */
diff --git a/include/asm-xtensa/percpu.h b/include/asm-xtensa/percpu.h
new file mode 100644
index 0000000..6d2bc2a
--- /dev/null
+++ b/include/asm-xtensa/percpu.h
@@ -0,0 +1,16 @@
+/*
+ * linux/include/asm-xtensa/percpu.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PERCPU__
+#define _XTENSA_PERCPU__
+
+#include <asm-generic/percpu.h>
+
+#endif /* _XTENSA_PERCPU__ */
diff --git a/include/asm-xtensa/pgalloc.h b/include/asm-xtensa/pgalloc.h
new file mode 100644
index 0000000..734a8d0
--- /dev/null
+++ b/include/asm-xtensa/pgalloc.h
@@ -0,0 +1,116 @@
+/*
+ * linux/include/asm-xtensa/pgalloc.h
+ *
+ * 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.
+ *
+ * Copyright (C) 2001-2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PGALLOC_H
+#define _XTENSA_PGALLOC_H
+
+#ifdef __KERNEL__
+
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <linux/highmem.h>
+#include <asm/processor.h>
+#include <asm/cacheflush.h>
+
+
+/* Cache aliasing:
+ *
+ * If the cache size for one way is greater than the page size, we have to
+ * deal with cache aliasing. The cache index is wider than the page size:
+ *
+ *      |cache |
+ * |pgnum |page|	virtual address
+ * |xxxxxX|zzzz|
+ * |      |    |
+ *   \  / |    |
+ *  trans.|    |
+ *   /  \ |    |
+ * |yyyyyY|zzzz|	physical address
+ *
+ * When the page number is translated to the physical page address, the lowest
+ * bit(s) (X) that are also part of the cache index are also translated (Y).
+ * If this translation changes this bit (X), the cache index is also afected,
+ * thus resulting in a different cache line than before.
+ * The kernel does not provide a mechanism to ensure that the page color
+ * (represented by this bit) remains the same when allocated or when pages
+ * are remapped. When user pages are mapped into kernel space, the color of
+ * the page might also change.
+ *
+ * We use the address space VMALLOC_END ... VMALLOC_END + DCACHE_WAY_SIZE * 2
+ * to temporarily map a patch so we can match the color.
+ */
+
+#if (DCACHE_WAY_SIZE > PAGE_SIZE)
+# define PAGE_COLOR_MASK	(PAGE_MASK & (DCACHE_WAY_SIZE-1))
+# define PAGE_COLOR(a)		\
+	(((unsigned long)(a)&PAGE_COLOR_MASK) >> PAGE_SHIFT)
+# define PAGE_COLOR_EQ(a,b)	\
+	((((unsigned long)(a) ^ (unsigned long)(b)) & PAGE_COLOR_MASK) == 0)
+# define PAGE_COLOR_MAP0(v)	\
+	(VMALLOC_END + ((unsigned long)(v) & PAGE_COLOR_MASK))
+# define PAGE_COLOR_MAP1(v)	\
+	(VMALLOC_END + ((unsigned long)(v) & PAGE_COLOR_MASK) + DCACHE_WAY_SIZE)
+#endif
+
+/*
+ * Allocating and freeing a pmd is trivial: the 1-entry pmd is
+ * inside the pgd, so has no extra memory associated with it.
+ */
+
+#define pgd_free(pgd)	free_page((unsigned long)(pgd))
+
+#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
+
+static inline void
+pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *pte)
+{
+	pmd_val(*(pmdp)) = (unsigned long)(pte);
+	__asm__ __volatile__ ("memw; dhwb %0, 0; dsync" :: "a" (pmdp));
+}
+
+static inline void
+pmd_populate(struct mm_struct *mm, pmd_t *pmdp, struct page *page)
+{
+	pmd_val(*(pmdp)) = (unsigned long)page_to_virt(page);
+	__asm__ __volatile__ ("memw; dhwb %0, 0; dsync" :: "a" (pmdp));
+}
+
+
+
+#else
+
+# define pmd_populate_kernel(mm, pmdp, pte)				     \
+	(pmd_val(*(pmdp)) = (unsigned long)(pte))
+# define pmd_populate(mm, pmdp, page)					     \
+	(pmd_val(*(pmdp)) = (unsigned long)page_to_virt(page))
+
+#endif
+
+static inline pgd_t*
+pgd_alloc(struct mm_struct *mm)
+{
+	pgd_t *pgd;
+
+	pgd = (pgd_t *)__get_free_pages(GFP_KERNEL|__GFP_ZERO, PGD_ORDER);
+
+	if (likely(pgd != NULL))
+		__flush_dcache_page((unsigned long)pgd);
+
+	return pgd;
+}
+
+extern pte_t* pte_alloc_one_kernel(struct mm_struct* mm, unsigned long addr);
+extern struct page* pte_alloc_one(struct mm_struct* mm, unsigned long addr);
+
+#define pte_free_kernel(pte) free_page((unsigned long)pte)
+#define pte_free(pte) __free_page(pte)
+
+#endif /* __KERNEL__ */
+#endif /* _XTENSA_PGALLOC_H */
diff --git a/include/asm-xtensa/pgtable.h b/include/asm-xtensa/pgtable.h
new file mode 100644
index 0000000..0bb6416
--- /dev/null
+++ b/include/asm-xtensa/pgtable.h
@@ -0,0 +1,468 @@
+/*
+ * linux/include/asm-xtensa/page.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version2 as
+ * published by the Free Software Foundation.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PGTABLE_H
+#define _XTENSA_PGTABLE_H
+
+#include <asm-generic/pgtable-nopmd.h>
+#include <asm/page.h>
+
+/* Assertions. */
+
+#ifdef CONFIG_MMU
+
+
+#if (XCHAL_MMU_RINGS < 2)
+# error Linux build assumes at least 2 ring levels.
+#endif
+
+#if (XCHAL_MMU_CA_BITS != 4)
+# error We assume exactly four bits for CA.
+#endif
+
+#if (XCHAL_MMU_SR_BITS != 0)
+# error We have no room for SR bits.
+#endif
+
+/*
+ * Use the first min-wired way for mapping page-table pages.
+ * Page coloring requires a second min-wired way.
+ */
+
+#if (XCHAL_DTLB_MINWIRED_SETS == 0)
+# error Need a min-wired way for mapping page-table pages
+#endif
+
+#define DTLB_WAY_PGTABLE XCHAL_DTLB_SET(XCHAL_DTLB_MINWIRED_SET0, WAY)
+
+#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
+# if XCHAL_DTLB_SET(XCHAL_DTLB_MINWIRED_SET0, WAYS) >= 2
+#  define DTLB_WAY_DCACHE_ALIAS0 (DTLB_WAY_PGTABLE + 1)
+#  define DTLB_WAY_DCACHE_ALIAS1 (DTLB_WAY_PGTABLE + 2)
+# else
+#  error Page coloring requires its own wired dtlb way!
+# endif
+#endif
+
+#endif /* CONFIG_MMU */
+
+/*
+ * We only use two ring levels, user and kernel space.
+ */
+
+#define USER_RING		1	/* user ring level */
+#define KERNEL_RING		0	/* kernel ring level */
+
+/*
+ * The Xtensa architecture port of Linux has a two-level page table system,
+ * i.e. the logical three-level Linux page table layout are folded.
+ * Each task has the following memory page tables:
+ *
+ *   PGD table (page directory), ie. 3rd-level page table:
+ *	One page (4 kB) of 1024 (PTRS_PER_PGD) pointers to PTE tables
+ *	(Architectures that don't have the PMD folded point to the PMD tables)
+ *
+ *	The pointer to the PGD table for a given task can be retrieved from
+ *	the task structure (struct task_struct*) t, e.g. current():
+ *	  (t->mm ? t->mm : t->active_mm)->pgd
+ *
+ *   PMD tables (page middle-directory), ie. 2nd-level page tables:
+ *	Absent for the Xtensa architecture (folded, PTRS_PER_PMD == 1).
+ *
+ *   PTE tables (page table entry), ie. 1st-level page tables:
+ *	One page (4 kB) of 1024 (PTRS_PER_PTE) PTEs with a special PTE
+ *	invalid_pte_table for absent mappings.
+ *
+ * The individual pages are 4 kB big with special pages for the empty_zero_page.
+ */
+#define PGDIR_SHIFT	22
+#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
+#define PGDIR_MASK	(~(PGDIR_SIZE-1))
+
+/*
+ * Entries per page directory level: we use two-level, so
+ * we don't really have any PMD directory physically.
+ */
+#define PTRS_PER_PTE		1024
+#define PTRS_PER_PTE_SHIFT	10
+#define PTRS_PER_PMD		1
+#define PTRS_PER_PGD		1024
+#define PGD_ORDER		0
+#define PMD_ORDER		0
+#define USER_PTRS_PER_PGD	(TASK_SIZE/PGDIR_SIZE)
+#define FIRST_USER_ADDRESS      XCHAL_SEG_MAPPABLE_VADDR
+#define FIRST_USER_PGD_NR	(FIRST_USER_ADDRESS >> PGDIR_SHIFT)
+
+/* virtual memory area. We keep a distance to other memory regions to be
+ * on the safe side. We also use this area for cache aliasing.
+ */
+
+// FIXME: virtual memory area must be configuration-dependent
+
+#define VMALLOC_START		0xC0000000
+#define VMALLOC_END		0xC7FF0000
+
+/* Xtensa Linux config PTE layout (when present):
+ *	31-12:	PPN
+ *	11-6:	Software
+ *	5-4:	RING
+ *	3-0:	CA
+ *
+ * Similar to the Alpha and MIPS ports, we need to keep track of the ref
+ * and mod bits in software.  We have a software "you can read
+ * from this page" bit, and a hardware one which actually lets the
+ * process read from the page.  On the same token we have a software
+ * writable bit and the real hardware one which actually lets the
+ * process write to the page.
+ *
+ * See further below for PTE layout for swapped-out pages.
+ */
+
+#define _PAGE_VALID		(1<<0)	/* hardware: page is accessible */
+#define _PAGE_WRENABLE		(1<<1)	/* hardware: page is writable */
+
+/* None of these cache modes include MP coherency:  */
+#define _PAGE_NO_CACHE		(0<<2)	/* bypass, non-speculative */
+#if XCHAL_DCACHE_IS_WRITEBACK
+# define _PAGE_WRITEBACK	(1<<2)	/* write back */
+# define _PAGE_WRITETHRU	(2<<2)	/* write through */
+#else
+# define _PAGE_WRITEBACK	(1<<2)	/* assume write through */
+# define _PAGE_WRITETHRU	(1<<2)
+#endif
+#define _PAGE_NOALLOC		(3<<2)	/* don't allocate cache,if not cached */
+#define _CACHE_MASK		(3<<2)
+
+#define _PAGE_USER		(1<<4)	/* user access (ring=1) */
+#define _PAGE_KERNEL		(0<<4)	/* kernel access (ring=0) */
+
+/* Software */
+#define _PAGE_RW		(1<<6)	/* software: page writable */
+#define _PAGE_DIRTY		(1<<7)	/* software: page dirty */
+#define _PAGE_ACCESSED		(1<<8)	/* software: page accessed (read) */
+#define _PAGE_FILE		(1<<9)	/* nonlinear file mapping*/
+
+#define _PAGE_CHG_MASK	(PAGE_MASK | _PAGE_ACCESSED | _CACHE_MASK | _PAGE_DIRTY)
+#define _PAGE_PRESENT	( _PAGE_VALID | _PAGE_WRITEBACK | _PAGE_ACCESSED)
+
+#ifdef CONFIG_MMU
+
+# define PAGE_NONE	__pgprot(_PAGE_PRESENT)
+# define PAGE_SHARED	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_RW)
+# define PAGE_COPY	__pgprot(_PAGE_PRESENT | _PAGE_USER)
+# define PAGE_READONLY	__pgprot(_PAGE_PRESENT | _PAGE_USER)
+# define PAGE_KERNEL	__pgprot(_PAGE_PRESENT | _PAGE_KERNEL | _PAGE_WRENABLE)
+# define PAGE_INVALID	__pgprot(_PAGE_USER)
+
+# if (DCACHE_WAY_SIZE > PAGE_SIZE)
+#  define PAGE_DIRECTORY  __pgprot(_PAGE_VALID | _PAGE_ACCESSED | _PAGE_KERNEL)
+# else
+#  define PAGE_DIRECTORY  __pgprot(_PAGE_PRESENT | _PAGE_KERNEL)
+# endif
+
+#else /* no mmu */
+
+# define PAGE_NONE       __pgprot(0)
+# define PAGE_SHARED     __pgprot(0)
+# define PAGE_COPY       __pgprot(0)
+# define PAGE_READONLY   __pgprot(0)
+# define PAGE_KERNEL     __pgprot(0)
+
+#endif
+
+/*
+ * On certain configurations of Xtensa MMUs (eg. the initial Linux config),
+ * the MMU can't do page protection for execute, and considers that the same as
+ * read.  Also, write permissions may imply read permissions.
+ * What follows is the closest we can get by reasonable means..
+ * See linux/mm/mmap.c for protection_map[] array that uses these definitions.
+ */
+#define __P000	PAGE_NONE	/* private --- */
+#define __P001	PAGE_READONLY	/* private --r */
+#define __P010	PAGE_COPY	/* private -w- */
+#define __P011	PAGE_COPY	/* private -wr */
+#define __P100	PAGE_READONLY	/* private x-- */
+#define __P101	PAGE_READONLY	/* private x-r */
+#define __P110	PAGE_COPY	/* private xw- */
+#define __P111	PAGE_COPY	/* private xwr */
+
+#define __S000	PAGE_NONE	/* shared  --- */
+#define __S001	PAGE_READONLY	/* shared  --r */
+#define __S010	PAGE_SHARED	/* shared  -w- */
+#define __S011	PAGE_SHARED	/* shared  -wr */
+#define __S100	PAGE_READONLY	/* shared  x-- */
+#define __S101	PAGE_READONLY	/* shared  x-r */
+#define __S110	PAGE_SHARED	/* shared  xw- */
+#define __S111	PAGE_SHARED	/* shared  xwr */
+
+#ifndef __ASSEMBLY__
+
+#define pte_ERROR(e) \
+	printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e))
+#define pgd_ERROR(e) \
+	printk("%s:%d: bad pgd entry %08lx.\n", __FILE__, __LINE__, pgd_val(e))
+
+extern unsigned long empty_zero_page[1024];
+
+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+
+extern pgd_t swapper_pg_dir[PAGE_SIZE/sizeof(pgd_t)];
+
+/*
+ * The pmd contains the kernel virtual address of the pte page.
+ */
+#define pmd_page_kernel(pmd) ((unsigned long)(pmd_val(pmd) & PAGE_MASK))
+#define pmd_page(pmd) virt_to_page(pmd_val(pmd))
+
+/*
+ * The following only work if pte_present() is true.
+ */
+#define pte_none(pte)	 (!(pte_val(pte) ^ _PAGE_USER))
+#define pte_present(pte) (pte_val(pte) & _PAGE_VALID)
+#define pte_clear(mm,addr,ptep)						\
+	do { update_pte(ptep, __pte(_PAGE_USER)); } while(0)
+
+#define pmd_none(pmd)	 (!pmd_val(pmd))
+#define pmd_present(pmd) (pmd_val(pmd) & PAGE_MASK)
+#define pmd_clear(pmdp)	 do { set_pmd(pmdp, __pmd(0)); } while (0)
+#define pmd_bad(pmd)	 (pmd_val(pmd) & ~PAGE_MASK)
+
+/* Note: We use the _PAGE_USER bit to indicate write-protect kernel memory */
+
+static inline int pte_read(pte_t pte)  { return pte_val(pte) & _PAGE_USER; }
+static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
+static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
+static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
+static inline int pte_file(pte_t pte)  { return pte_val(pte) & _PAGE_FILE; }
+static inline pte_t pte_wrprotect(pte_t pte)	{ pte_val(pte) &= ~(_PAGE_RW | _PAGE_WRENABLE); return pte; }
+static inline pte_t pte_rdprotect(pte_t pte)	{ pte_val(pte) &= ~_PAGE_USER; return pte; }
+static inline pte_t pte_mkclean(pte_t pte)	{ pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
+static inline pte_t pte_mkold(pte_t pte)	{ pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
+static inline pte_t pte_mkread(pte_t pte)	{ pte_val(pte) |= _PAGE_USER; return pte; }
+static inline pte_t pte_mkdirty(pte_t pte)	{ pte_val(pte) |= _PAGE_DIRTY; return pte; }
+static inline pte_t pte_mkyoung(pte_t pte)	{ pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+static inline pte_t pte_mkwrite(pte_t pte)	{ pte_val(pte) |= _PAGE_RW; return pte; }
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+#define pte_pfn(pte)		(pte_val(pte) >> PAGE_SHIFT)
+#define pte_same(a,b)		(pte_val(a) == pte_val(b))
+#define pte_page(x)		pfn_to_page(pte_pfn(x))
+#define pfn_pte(pfn, prot)	__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+#define mk_pte(page, prot)	pfn_pte(page_to_pfn(page), prot)
+
+extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot));
+}
+
+/*
+ * Certain architectures need to do special things when pte's
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+static inline void update_pte(pte_t *ptep, pte_t pteval)
+{
+	*ptep = pteval;
+#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
+	__asm__ __volatile__ ("memw; dhwb %0, 0; dsync" :: "a" (ptep));
+#endif
+}
+
+extern inline void
+set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pteval)
+{
+	update_pte(ptep, pteval);
+}
+
+
+extern inline void
+set_pmd(pmd_t *pmdp, pmd_t pmdval)
+{
+	*pmdp = pmdval;
+#if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK
+	__asm__ __volatile__ ("memw; dhwb %0, 0; dsync" :: "a" (pmdp));
+#endif
+}
+
+
+static inline int
+ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr,
+    			  pte_t *ptep)
+{
+	pte_t pte = *ptep;
+	if (!pte_young(pte))
+		return 0;
+	update_pte(ptep, pte_mkold(pte));
+	return 1;
+}
+
+static inline int
+ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr,
+   			  pte_t *ptep)
+{
+	pte_t pte = *ptep;
+	if (!pte_dirty(pte))
+		return 0;
+	update_pte(ptep, pte_mkclean(pte));
+	return 1;
+}
+
+static inline pte_t
+ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+	pte_t pte = *ptep;
+	pte_clear(mm, addr, ptep);
+	return pte;
+}
+
+static inline void
+ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+  	pte_t pte = *ptep;
+  	update_pte(ptep, pte_wrprotect(pte));
+}
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(address)	pgd_offset(&init_mm, address)
+
+/* to find an entry in a page-table-directory */
+#define pgd_offset(mm,address)	((mm)->pgd + pgd_index(address))
+
+#define pgd_index(address)	((address) >> PGDIR_SHIFT)
+
+/* Find an entry in the second-level page table.. */
+#define pmd_offset(dir,address) ((pmd_t*)(dir))
+
+/* Find an entry in the third-level page table.. */
+#define pte_index(address)	(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+#define pte_offset_kernel(dir,addr) 					\
+	((pte_t*) pmd_page_kernel(*(dir)) + pte_index(addr))
+#define pte_offset_map(dir,addr)	pte_offset_kernel((dir),(addr))
+#define pte_offset_map_nested(dir,addr)	pte_offset_kernel((dir),(addr))
+
+#define pte_unmap(pte)		do { } while (0)
+#define pte_unmap_nested(pte)	do { } while (0)
+
+
+/*
+ * Encode and decode a swap entry.
+ * Each PTE in a process VM's page table is either:
+ *   "present" -- valid and not swapped out, protection bits are meaningful;
+ *   "not present" -- which further subdivides in these two cases:
+ *      "none" -- no mapping at all; identified by pte_none(), set by pte_clear(
+ *      "swapped out" -- the page is swapped out, and the SWP macros below
+ *                      are used to store swap file info in the PTE itself.
+ *
+ * In the Xtensa processor MMU, any PTE entries in user space (or anywhere
+ * in virtual memory that can map differently across address spaces)
+ * must have a correct ring value that represents the RASID field that
+ * is changed when switching address spaces.  Eg. such PTE entries cannot
+ * be set to ring zero, because that can cause a (global) kernel ASID
+ * entry to be created in the TLBs (even with invalid cache attribute),
+ * potentially causing a multihit exception when going back to another
+ * address space that mapped the same virtual address at another ring.
+ *
+ * SO: we avoid using ring bits (_PAGE_RING_MASK) in "not present" PTEs.
+ * We also avoid using the _PAGE_VALID bit which must be zero for non-present
+ * pages.
+ *
+ * We end up with the following available bits:  1..3 and 7..31.
+ * We don't bother with 1..3 for now (we can use them later if needed),
+ * and chose to allocate 6 bits for SWP_TYPE and the remaining 19 bits
+ * for SWP_OFFSET.  At least 5 bits are needed for SWP_TYPE, because it
+ * is currently implemented as an index into swap_info[MAX_SWAPFILES]
+ * and MAX_SWAPFILES is currently defined as 32 in <linux/swap.h>.
+ * However, for some reason all other architectures in the 2.4 kernel
+ * reserve either 6, 7, or 8 bits so I'll not detract from that for now.  :)
+ * SWP_OFFSET is an offset into the swap file in page-size units, so
+ * with 4 kB pages, 19 bits supports a maximum swap file size of 2 GB.
+ *
+ * FIXME:  2 GB isn't very big.  Other bits can be used to allow
+ * larger swap sizes.  In the meantime, it appears relatively easy to get
+ * around the 2 GB limitation by simply using multiple swap files.
+ */
+
+#define __swp_type(entry)	(((entry).val >> 7) & 0x3f)
+#define __swp_offset(entry)	((entry).val >> 13)
+#define __swp_entry(type,offs)	((swp_entry_t) {((type) << 7) | ((offs) << 13)})
+#define __pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
+#define __swp_entry_to_pte(x)	((pte_t) { (x).val })
+
+#define PTE_FILE_MAX_BITS	29
+#define pte_to_pgoff(pte)	(pte_val(pte) >> 3)
+#define pgoff_to_pte(off)	((pte_t) { ((off) << 3) | _PAGE_FILE })
+
+
+#endif /*  !defined (__ASSEMBLY__) */
+
+
+#ifdef __ASSEMBLY__
+
+/* Assembly macro _PGD_INDEX is the same as C pgd_index(unsigned long),
+ *                _PGD_OFFSET as C pgd_offset(struct mm_struct*, unsigned long),
+ *                _PMD_OFFSET as C pmd_offset(pgd_t*, unsigned long)
+ *                _PTE_OFFSET as C pte_offset(pmd_t*, unsigned long)
+ *
+ * Note: We require an additional temporary register which can be the same as
+ *       the register that holds the address.
+ *
+ * ((pte_t*) ((unsigned long)(pmd_val(*pmd) & PAGE_MASK)) + pte_index(addr))
+ *
+ */
+#define _PGD_INDEX(rt,rs)	extui	rt, rs, PGDIR_SHIFT, 32-PGDIR_SHIFT
+#define _PTE_INDEX(rt,rs)	extui	rt, rs, PAGE_SHIFT, PTRS_PER_PTE_SHIFT
+
+#define _PGD_OFFSET(mm,adr,tmp)		l32i	mm, mm, MM_PGD;		\
+					_PGD_INDEX(tmp, adr);		\
+					addx4	mm, tmp, mm
+
+#define _PTE_OFFSET(pmd,adr,tmp)	_PTE_INDEX(tmp, adr);		\
+					srli	pmd, pmd, PAGE_SHIFT;	\
+					slli	pmd, pmd, PAGE_SHIFT;	\
+					addx4	pmd, tmp, pmd
+
+#else
+
+extern void paging_init(void);
+
+#define kern_addr_valid(addr)	(1)
+
+extern  void update_mmu_cache(struct vm_area_struct * vma,
+			      unsigned long address, pte_t pte);
+
+/*
+ * remap a physical address `phys' of size `size' with page protection `prot'
+ * into virtual address `from'
+ */
+#define io_remap_page_range(vma,from,phys,size,prot) \
+                remap_pfn_range(vma, from, (phys) >> PAGE_SHIFT, size, prot)
+
+
+/* No page table caches to init */
+
+#define pgtable_cache_init()	do { } while (0)
+
+typedef pte_t *pte_addr_t;
+
+#endif /* !defined (__ASSEMBLY__) */
+
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+#define __HAVE_ARCH_PTEP_SET_WRPROTECT
+#define __HAVE_ARCH_PTEP_MKDIRTY
+#define __HAVE_ARCH_PTE_SAME
+
+#include <asm-generic/pgtable.h>
+
+#endif /* _XTENSA_PGTABLE_H */
diff --git a/include/asm-xtensa/platform-iss/hardware.h b/include/asm-xtensa/platform-iss/hardware.h
new file mode 100644
index 0000000..22240f0
--- /dev/null
+++ b/include/asm-xtensa/platform-iss/hardware.h
@@ -0,0 +1,29 @@
+/*
+ * include/asm-xtensa/platform-iss/hardware.h
+ *
+ * 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) 2001 Tensilica Inc.
+ */
+
+/*
+ * This file contains the default configuration of ISS.
+ */
+
+#ifndef __ASM_XTENSA_ISS_HARDWARE
+#define __ASM_XTENSA_ISS_HARDWARE
+
+/*
+ * Memory configuration.
+ */
+
+#define PLATFORM_DEFAULT_MEM_START XSHAL_RAM_PADDR
+#define PLATFORM_DEFAULT_MEM_SIZE XSHAL_RAM_VSIZE
+
+/*
+ * Interrupt configuration.
+ */
+
+#endif /* __ASM_XTENSA_ISS_HARDWARE */
diff --git a/include/asm-xtensa/platform.h b/include/asm-xtensa/platform.h
new file mode 100644
index 0000000..3616389
--- /dev/null
+++ b/include/asm-xtensa/platform.h
@@ -0,0 +1,92 @@
+/*
+ * include/asm-xtensa/platform.h
+ *
+ * Platform specific functions
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PLATFORM_H
+#define _XTENSA_PLATFORM_H
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+#include <asm/bootparam.h>
+
+/*
+ * platform_init is called before the mmu is initialized to give the
+ * platform a early hook-up. bp_tag_t is a list of configuration tags
+ * passed from the boot-loader.
+ */
+extern void platform_init(bp_tag_t*);
+
+/*
+ * platform_setup is called from setup_arch with a pointer to the command-line
+ * string.
+ */
+extern void platform_setup (char **);
+
+/*
+ * platform_init_irq is called from init_IRQ.
+ */
+extern void platform_init_irq (void);
+
+/*
+ * platform_restart is called to restart the system.
+ */
+extern void platform_restart (void);
+
+/*
+ * platform_halt is called to stop the system and halt.
+ */
+extern void platform_halt (void);
+
+/*
+ * platform_power_off is called to stop the system and power it off.
+ */
+extern void platform_power_off (void);
+
+/*
+ * platform_idle is called from the idle function.
+ */
+extern void platform_idle (void);
+
+/*
+ * platform_heartbeat is called every HZ
+ */
+extern void platform_heartbeat (void);
+
+/*
+ * platform_pcibios_init is called to allow the platform to setup the pci bus.
+ */
+extern void platform_pcibios_init (void);
+
+/*
+ * platform_pcibios_fixup allows to modify the PCI configuration.
+ */
+extern int platform_pcibios_fixup (void);
+
+/*
+ * platform_calibrate_ccount calibrates cpu clock freq (CONFIG_XTENSA_CALIBRATE)
+ */
+extern void platform_calibrate_ccount (void);
+
+/*
+ * platform_get_rtc_time returns RTC seconds (returns 0 for no error)
+ */
+extern int platform_get_rtc_time(time_t*);
+
+/*
+ * platform_set_rtc_time set RTC seconds (returns 0 for no error)
+ */
+extern int platform_set_rtc_time(time_t);
+
+
+#endif	/* _XTENSA_PLATFORM_H */
+
diff --git a/include/asm-xtensa/poll.h b/include/asm-xtensa/poll.h
new file mode 100644
index 0000000..dffe447
--- /dev/null
+++ b/include/asm-xtensa/poll.h
@@ -0,0 +1,37 @@
+/*
+ * include/asm-xtensa/poll.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_POLL_H
+#define _XTENSA_POLL_H
+
+
+#define POLLIN		0x0001
+#define POLLPRI		0x0002
+#define POLLOUT		0x0004
+
+#define POLLERR		0x0008
+#define POLLHUP		0x0010
+#define POLLNVAL	0x0020
+
+#define POLLRDNORM	0x0040
+#define POLLRDBAND	0x0080
+#define POLLWRNORM	POLLOUT
+#define POLLWRBAND	0x0100
+
+#define POLLMSG		0x0400
+#define POLLREMOVE	0x0800
+
+struct pollfd {
+	int fd;
+	short events;
+	short revents;
+};
+
+#endif /* _XTENSA_POLL_H */
diff --git a/include/asm-xtensa/posix_types.h b/include/asm-xtensa/posix_types.h
new file mode 100644
index 0000000..2c816b0
--- /dev/null
+++ b/include/asm-xtensa/posix_types.h
@@ -0,0 +1,123 @@
+/*
+ * include/asm-xtensa/posix_types.h
+ *
+ * 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.
+ *
+ * Largely copied from include/asm-ppc/posix_types.h
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_POSIX_TYPES_H
+#define _XTENSA_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned long	__kernel_ino_t;
+typedef unsigned int	__kernel_mode_t;
+typedef unsigned short	__kernel_nlink_t;
+typedef long		__kernel_off_t;
+typedef int		__kernel_pid_t;
+typedef unsigned short	__kernel_ipc_pid_t;
+typedef unsigned int	__kernel_uid_t;
+typedef unsigned int	__kernel_gid_t;
+typedef unsigned int	__kernel_size_t;
+typedef int		__kernel_ssize_t;
+typedef long		__kernel_ptrdiff_t;
+typedef long		__kernel_time_t;
+typedef long		__kernel_suseconds_t;
+typedef long		__kernel_clock_t;
+typedef int		__kernel_timer_t;
+typedef int		__kernel_clockid_t;
+typedef int		__kernel_daddr_t;
+typedef char *		__kernel_caddr_t;
+typedef unsigned short	__kernel_uid16_t;
+typedef unsigned short	__kernel_gid16_t;
+typedef unsigned int	__kernel_uid32_t;
+typedef unsigned int	__kernel_gid32_t;
+
+typedef unsigned short	__kernel_old_uid_t;
+typedef unsigned short	__kernel_old_gid_t;
+typedef unsigned short	__kernel_old_dev_t;
+
+#ifdef __GNUC__
+typedef long long	__kernel_loff_t;
+#endif
+
+typedef struct {
+	int	val[2];
+} __kernel_fsid_t;
+
+#ifndef __GNUC__
+
+#define	__FD_SET(d, set)	((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
+#define	__FD_CLR(d, set)	((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
+#define	__FD_ISSET(d, set)	((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
+#define	__FD_ZERO(set)	\
+  ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set)))
+
+#else /* __GNUC__ */
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) \
+    || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
+/* With GNU C, use inline functions instead so args are evaluated only once: */
+
+#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_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_ISSET
+static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set *p)
+{
+	unsigned long _tmp = fd / __NFDBITS;
+	unsigned long _rem = fd % __NFDBITS;
+	return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
+}
+
+/*
+ * This will unroll the loop for the normal constant case (8 ints,
+ * for a 256-bit fd_set)
+ */
+#undef __FD_ZERO
+static __inline__ void __FD_ZERO(__kernel_fd_set *p)
+{
+	unsigned int *tmp = (unsigned int *)p->fds_bits;
+	int i;
+
+	if (__builtin_constant_p(__FDSET_LONGS)) {
+		switch (__FDSET_LONGS) {
+			case 8:
+				tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0;
+				tmp[4] = 0; tmp[5] = 0; tmp[6] = 0; tmp[7] = 0;
+				return;
+		}
+	}
+	i = __FDSET_LONGS;
+	while (i) {
+		i--;
+		*tmp = 0;
+		tmp++;
+	}
+}
+
+#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+#endif /* __GNUC__ */
+#endif /* _XTENSA_POSIX_TYPES_H */
diff --git a/include/asm-xtensa/processor.h b/include/asm-xtensa/processor.h
new file mode 100644
index 0000000..9cab5e4
--- /dev/null
+++ b/include/asm-xtensa/processor.h
@@ -0,0 +1,205 @@
+/*
+ * include/asm-xtensa/processor.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PROCESSOR_H
+#define _XTENSA_PROCESSOR_H
+
+#ifdef __ASSEMBLY__
+#define _ASMLANGUAGE
+#endif
+
+#include <xtensa/config/core.h>
+#include <xtensa/config/specreg.h>
+#include <xtensa/config/tie.h>
+#include <xtensa/config/system.h>
+
+#include <asm/ptrace.h>
+#include <asm/types.h>
+#include <asm/coprocessor.h>
+
+/* Assertions. */
+
+#if (XCHAL_HAVE_WINDOWED != 1)
+#error Linux requires the Xtensa Windowed Registers Option.
+#endif
+
+/*
+ * User space process size: 1 GB.
+ * Windowed call ABI requires caller and callee to be located within the same
+ * 1 GB region. The C compiler places trampoline code on the stack for sources
+ * that take the address of a nested C function (a feature used by glibc), so
+ * the 1 GB requirement applies to the stack as well.
+ */
+
+#define TASK_SIZE	0x40000000
+
+/*
+ * General exception cause assigned to debug exceptions. Debug exceptions go
+ * to their own vector, rather than the general exception vectors (user,
+ * kernel, double); and their specific causes are reported via DEBUGCAUSE
+ * rather than EXCCAUSE.  However it is sometimes convenient to redirect debug
+ * exceptions to the general exception mechanism.  To do this, an otherwise
+ * unused EXCCAUSE value was assigned to debug exceptions for this purpose.
+ */
+
+#define EXCCAUSE_MAPPED_DEBUG	63
+
+/*
+ * We use DEPC also as a flag to distinguish between double and regular
+ * exceptions. For performance reasons, DEPC might contain the value of
+ * EXCCAUSE for regular exceptions, so we use this definition to mark a
+ * valid double exception address.
+ * (Note: We use it in bgeui, so it should be 64, 128, or 256)
+ */
+
+#define VALID_DOUBLE_EXCEPTION_ADDRESS	64
+
+/* LOCKLEVEL defines the interrupt level that masks all
+ * general-purpose interrupts.
+ */
+#define LOCKLEVEL 1
+
+/* WSBITS and WBBITS are the width of the WINDOWSTART and WINDOWBASE
+ * registers
+ */
+#define WSBITS  (XCHAL_NUM_AREGS / 4)      /* width of WINDOWSTART in bits */
+#define WBBITS  (XCHAL_NUM_AREGS_LOG2 - 2) /* width of WINDOWBASE in bits */
+
+#ifndef __ASSEMBLY__
+
+/* Build a valid return address for the specified call winsize.
+ * winsize must be 1 (call4), 2 (call8), or 3 (call12)
+ */
+#define MAKE_RA_FOR_CALL(ra,ws)   (((ra) & 0x3fffffff) | (ws) << 30)
+
+/* Convert return address to a valid pc
+ * Note: We assume that the stack pointer is in the same 1GB ranges as the ra
+ */
+#define MAKE_PC_FROM_RA(ra,sp)    (((ra) & 0x3fffffff) | ((sp) & 0xc0000000))
+
+typedef struct {
+    unsigned long seg;
+} mm_segment_t;
+
+struct thread_struct {
+
+	/* kernel's return address and stack pointer for context switching */
+	unsigned long ra; /* kernel's a0: return address and window call size */
+	unsigned long sp; /* kernel's a1: stack pointer */
+
+	mm_segment_t current_ds;    /* see uaccess.h for example uses */
+
+	/* struct xtensa_cpuinfo info; */
+
+	unsigned long bad_vaddr; /* last user fault */
+	unsigned long bad_uaddr; /* last kernel fault accessing user space */
+	unsigned long error_code;
+
+	unsigned long ibreak[XCHAL_NUM_IBREAK];
+	unsigned long dbreaka[XCHAL_NUM_DBREAK];
+	unsigned long dbreakc[XCHAL_NUM_DBREAK];
+
+	/* Allocate storage for extra state and coprocessor state. */
+	unsigned char cp_save[XTENSA_CP_EXTRA_SIZE]
+		__attribute__ ((aligned(XTENSA_CP_EXTRA_ALIGN)));
+
+	/* Make structure 16 bytes aligned. */
+	int align[0] __attribute__ ((aligned(16)));
+};
+
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr()  ({ __label__ _l; _l: &&_l;})
+
+
+/* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE	(TASK_SIZE / 2)
+
+#define INIT_THREAD  \
+{									\
+	ra:		0, 						\
+	sp:		sizeof(init_stack) + (long) &init_stack,	\
+	current_ds:	{0},						\
+	/*info:		{0}, */						\
+	bad_vaddr:	0,						\
+	bad_uaddr:	0,						\
+	error_code:	0,						\
+}
+
+
+/*
+ * Do necessary setup to start up a newly executed thread.
+ * Note: We set-up ps as if we did a call4 to the new pc.
+ *       set_thread_state in signal.c depends on it.
+ */
+#define USER_PS_VALUE ( (1 << XCHAL_PS_WOE_SHIFT) + \
+                        (1 << XCHAL_PS_CALLINC_SHIFT) + \
+                        (USER_RING << XCHAL_PS_RING_SHIFT) + \
+                        (1 << XCHAL_PS_PROGSTACK_SHIFT) + \
+                        (1 << XCHAL_PS_EXCM_SHIFT) )
+
+/* Clearing a0 terminates the backtrace. */
+#define start_thread(regs, new_pc, new_sp) \
+	regs->pc = new_pc; \
+	regs->ps = USER_PS_VALUE; \
+	regs->areg[1] = new_sp; \
+	regs->areg[0] = 0; \
+	regs->wmask = 1; \
+	regs->depc = 0; \
+	regs->windowbase = 0; \
+	regs->windowstart = 1;
+
+/* Forward declaration */
+struct task_struct;
+struct mm_struct;
+
+// FIXME: do we need release_thread for CP??
+/* Free all resources held by a thread. */
+#define release_thread(thread) do { } while(0)
+
+// FIXME: do we need prepare_to_copy (lazy status) for CP??
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
+/*
+ * create a kernel thread without removing it from tasklists
+ */
+extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+
+/* Copy and release all segment info associated with a VM */
+
+#define copy_segments(p, mm)	do { } while(0)
+#define release_segments(mm)	do { } while(0)
+#define forget_segments()	do { } while (0)
+
+#define thread_saved_pc(tsk)	(xtensa_pt_regs(tsk)->pc)
+
+extern unsigned long get_wchan(struct task_struct *p);
+
+#define KSTK_EIP(tsk)		(xtensa_pt_regs(tsk)->pc)
+#define KSTK_ESP(tsk)		(xtensa_pt_regs(tsk)->areg[1])
+
+#define cpu_relax()  do { } while (0)
+
+/* Special register access. */
+
+#define WSR(v,sr) __asm__ __volatile__ ("wsr %0,"__stringify(sr) :: "a"(v));
+#define RSR(v,sr) __asm__ __volatile__ ("rsr %0,"__stringify(sr) : "=a"(v));
+
+#define set_sr(x,sr) ({unsigned int v=(unsigned int)x; WSR(v,sr);})
+#define get_sr(sr) ({unsigned int v; RSR(v,sr); v; })
+
+#endif	/* __ASSEMBLY__ */
+#endif	/* _XTENSA_PROCESSOR_H */
diff --git a/include/asm-xtensa/ptrace.h b/include/asm-xtensa/ptrace.h
new file mode 100644
index 0000000..2848a5f
--- /dev/null
+++ b/include/asm-xtensa/ptrace.h
@@ -0,0 +1,135 @@
+/*
+ * include/asm-xtensa/ptrace.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_PTRACE_H
+#define _XTENSA_PTRACE_H
+
+#include <xtensa/config/core.h>
+
+/*
+ * Kernel stack
+ *
+ * 		+-----------------------+  -------- STACK_SIZE
+ * 		|     register file     |  |
+ * 		+-----------------------+  |
+ * 		|    struct pt_regs     |  |
+ * 		+-----------------------+  | ------ PT_REGS_OFFSET
+ * double 	:  16 bytes spill area  :  |  ^
+ * excetion 	:- - - - - - - - - - - -:  |  |
+ * frame	:    struct pt_regs     :  |  |
+ * 		:- - - - - - - - - - - -:  |  |
+ * 		|                       |  |  |
+ * 		|     memory stack      |  |  |
+ * 		|                       |  |  |
+ * 		~                       ~  ~  ~
+ * 		~                       ~  ~  ~
+ * 		|                       |  |  |
+ * 		|                       |  |  |
+ * 		+-----------------------+  |  | --- STACK_BIAS
+ * 		|  struct task_struct   |  |  |  ^
+ *  current --> +-----------------------+  |  |  |
+ * 		|  struct thread_info   |  |  |  |
+ *		+-----------------------+ --------
+ */
+
+#define KERNEL_STACK_SIZE (2 * PAGE_SIZE)
+
+/*  Offsets for exception_handlers[] (3 x 64-entries x 4-byte tables). */
+
+#define EXC_TABLE_KSTK		0x004	/* Kernel Stack */
+#define EXC_TABLE_DOUBLE_SAVE	0x008	/* Double exception save area for a0 */
+#define EXC_TABLE_FIXUP		0x00c	/* Fixup handler */
+#define EXC_TABLE_PARAM		0x010	/* For passing a parameter to fixup */
+#define EXC_TABLE_SYSCALL_SAVE	0x014	/* For fast syscall handler */
+#define EXC_TABLE_FAST_USER	0x100	/* Fast user exception handler */
+#define EXC_TABLE_FAST_KERNEL	0x200	/* Fast kernel exception handler */
+#define EXC_TABLE_DEFAULT	0x300	/* Default C-Handler */
+#define EXC_TABLE_SIZE		0x400
+
+/* Registers used by strace */
+
+#define REG_A_BASE	0xfc000000
+#define REG_AR_BASE	0x04000000
+#define REG_PC		0x14000000
+#define REG_PS		0x080000e6
+#define REG_WB		0x08000048
+#define REG_WS		0x08000049
+#define REG_LBEG	0x08000000
+#define REG_LEND	0x08000001
+#define REG_LCOUNT	0x08000002
+#define REG_SAR		0x08000003
+#define REG_DEPC	0x080000c0
+#define	REG_EXCCAUSE	0x080000e8
+#define REG_EXCVADDR	0x080000ee
+#define SYSCALL_NR	0x1
+
+#define AR_REGNO_TO_A_REGNO(ar, wb) (ar - wb*4) & ~(XCHAL_NUM_AREGS - 1)
+
+/* Other PTRACE_ values defined in <linux/ptrace.h> using values 0-9,16,17,24 */
+
+#define PTRACE_GETREGS            12
+#define PTRACE_SETREGS            13
+#define PTRACE_GETFPREGS          14
+#define PTRACE_SETFPREGS          15
+#define PTRACE_GETFPREGSIZE       18
+
+#ifndef __ASSEMBLY__
+
+/*
+ * This struct defines the way the registers are stored on the
+ * kernel stack during a system call or other kernel entry.
+ */
+struct pt_regs {
+	unsigned long pc;		/*   4 */
+	unsigned long ps;		/*   8 */
+	unsigned long depc;		/*  12 */
+	unsigned long exccause;		/*  16 */
+	unsigned long excvaddr;		/*  20 */
+	unsigned long debugcause;	/*  24 */
+	unsigned long wmask;		/*  28 */
+	unsigned long lbeg;		/*  32 */
+	unsigned long lend;		/*  36 */
+	unsigned long lcount;		/*  40 */
+	unsigned long sar;		/*  44 */
+	unsigned long windowbase;	/*  48 */
+	unsigned long windowstart;	/*  52 */
+	unsigned long syscall;		/*  56 */
+	int reserved[2];		/*  64 */
+
+	/* Make sure the areg field is 16 bytes aligned. */
+	int align[0] __attribute__ ((aligned(16)));
+
+	/* current register frame.
+	 * Note: The ESF for kernel exceptions ends after 16 registers!
+	 */
+	unsigned long areg[16];		/* 128 (64) */
+};
+
+#ifdef __KERNEL__
+# define xtensa_pt_regs(tsk) ((struct pt_regs*) \
+  (((long)(tsk)->thread_info + KERNEL_STACK_SIZE - (XCHAL_NUM_AREGS-16)*4)) - 1)
+# define user_mode(regs) (((regs)->ps & 0x00000020)!=0)
+# define instruction_pointer(regs) ((regs)->pc)
+extern void show_regs(struct pt_regs *);
+
+# ifndef CONFIG_SMP
+#  define profile_pc(regs) instruction_pointer(regs)
+# endif
+#endif /* __KERNEL__ */
+
+#else	/* __ASSEMBLY__ */
+
+#ifdef __KERNEL__
+# include <asm/offsets.h>
+#define PT_REGS_OFFSET	  (KERNEL_STACK_SIZE - PT_USER_SIZE)
+#endif
+
+#endif	/* !__ASSEMBLY__ */
+#endif	/* _XTENSA_PTRACE_H */
diff --git a/include/asm-xtensa/resource.h b/include/asm-xtensa/resource.h
new file mode 100644
index 0000000..17b5ab3
--- /dev/null
+++ b/include/asm-xtensa/resource.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/resource.h
+ *
+ * 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 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_RESOURCE_H
+#define _XTENSA_RESOURCE_H
+
+#include <asm-generic/resource.h>
+
+#endif	/* _XTENSA_RESOURCE_H */
diff --git a/include/asm-xtensa/rmap.h b/include/asm-xtensa/rmap.h
new file mode 100644
index 0000000..649588b
--- /dev/null
+++ b/include/asm-xtensa/rmap.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/rmap.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_RMAP_H
+#define _XTENSA_RMAP_H
+
+#include <asm-generic/rmap.h>
+
+#endif
diff --git a/include/asm-xtensa/rwsem.h b/include/asm-xtensa/rwsem.h
new file mode 100644
index 0000000..3c02b0e
--- /dev/null
+++ b/include/asm-xtensa/rwsem.h
@@ -0,0 +1,175 @@
+/*
+ * include/asm-xtensa/rwsem.h
+ *
+ * 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.
+ *
+ * Largely copied from include/asm-ppc/rwsem.h
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_RWSEM_H
+#define _XTENSA_RWSEM_H
+
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+
+/*
+ * the semaphore definition
+ */
+struct rw_semaphore {
+	signed long		count;
+#define RWSEM_UNLOCKED_VALUE		0x00000000
+#define RWSEM_ACTIVE_BIAS		0x00000001
+#define RWSEM_ACTIVE_MASK		0x0000ffff
+#define RWSEM_WAITING_BIAS		(-0x00010000)
+#define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
+#define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
+	spinlock_t		wait_lock;
+	struct list_head	wait_list;
+#if RWSEM_DEBUG
+	int			debug;
+#endif
+};
+
+/*
+ * initialisation
+ */
+#if RWSEM_DEBUG
+#define __RWSEM_DEBUG_INIT      , 0
+#else
+#define __RWSEM_DEBUG_INIT	/* */
+#endif
+
+#define __RWSEM_INITIALIZER(name) \
+	{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
+	  LIST_HEAD_INIT((name).wait_list) \
+	  __RWSEM_DEBUG_INIT }
+
+#define DECLARE_RWSEM(name)		\
+	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
+
+extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
+
+static inline void init_rwsem(struct rw_semaphore *sem)
+{
+	sem->count = RWSEM_UNLOCKED_VALUE;
+	spin_lock_init(&sem->wait_lock);
+	INIT_LIST_HEAD(&sem->wait_list);
+#if RWSEM_DEBUG
+	sem->debug = 0;
+#endif
+}
+
+/*
+ * lock for reading
+ */
+static inline void __down_read(struct rw_semaphore *sem)
+{
+	if (atomic_add_return(1,(atomic_t *)(&sem->count)) > 0)
+		smp_wmb();
+	else
+		rwsem_down_read_failed(sem);
+}
+
+static inline int __down_read_trylock(struct rw_semaphore *sem)
+{
+	int tmp;
+
+	while ((tmp = sem->count) >= 0) {
+		if (tmp == cmpxchg(&sem->count, tmp,
+				   tmp + RWSEM_ACTIVE_READ_BIAS)) {
+			smp_wmb();
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/*
+ * lock for writing
+ */
+static inline void __down_write(struct rw_semaphore *sem)
+{
+	int tmp;
+
+	tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS,
+				(atomic_t *)(&sem->count));
+	if (tmp == RWSEM_ACTIVE_WRITE_BIAS)
+		smp_wmb();
+	else
+		rwsem_down_write_failed(sem);
+}
+
+static inline int __down_write_trylock(struct rw_semaphore *sem)
+{
+	int tmp;
+
+	tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
+		      RWSEM_ACTIVE_WRITE_BIAS);
+	smp_wmb();
+	return tmp == RWSEM_UNLOCKED_VALUE;
+}
+
+/*
+ * unlock after reading
+ */
+static inline void __up_read(struct rw_semaphore *sem)
+{
+	int tmp;
+
+	smp_wmb();
+	tmp = atomic_sub_return(1,(atomic_t *)(&sem->count));
+	if (tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0)
+		rwsem_wake(sem);
+}
+
+/*
+ * unlock after writing
+ */
+static inline void __up_write(struct rw_semaphore *sem)
+{
+	smp_wmb();
+	if (atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
+			      (atomic_t *)(&sem->count)) < 0)
+		rwsem_wake(sem);
+}
+
+/*
+ * implement atomic add functionality
+ */
+static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
+{
+	atomic_add(delta, (atomic_t *)(&sem->count));
+}
+
+/*
+ * downgrade write lock to read lock
+ */
+static inline void __downgrade_write(struct rw_semaphore *sem)
+{
+	int tmp;
+
+	smp_wmb();
+	tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count));
+	if (tmp < 0)
+		rwsem_downgrade_wake(sem);
+}
+
+/*
+ * implement exchange and add functionality
+ */
+static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
+{
+	smp_mb();
+	return atomic_add_return(delta, (atomic_t *)(&sem->count));
+}
+
+#endif	/* _XTENSA_RWSEM_XADD_H */
diff --git a/include/asm-xtensa/scatterlist.h b/include/asm-xtensa/scatterlist.h
new file mode 100644
index 0000000..38a2b9a
--- /dev/null
+++ b/include/asm-xtensa/scatterlist.h
@@ -0,0 +1,34 @@
+/*
+ * include/asm-xtensa/scatterlist.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SCATTERLIST_H
+#define _XTENSA_SCATTERLIST_H
+
+struct scatterlist {
+	struct page 	*page;
+	unsigned int	offset;
+	dma_addr_t	dma_address;
+	unsigned int	length;
+};
+
+/*
+ * These macros should be used after a pci_map_sg call has been done
+ * to get bus addresses of each of the SG entries and their lengths.
+ * You should only work with the number of sg entries pci_map_sg
+ * returns, or alternatively stop on the first sg_dma_len(sg) which
+ * is 0.
+ */
+#define sg_dma_address(sg)      ((sg)->dma_address)
+#define sg_dma_len(sg)          ((sg)->length)
+
+
+#define ISA_DMA_THRESHOLD (~0UL)
+
+#endif	/* _XTENSA_SCATTERLIST_H */
diff --git a/include/asm-xtensa/sections.h b/include/asm-xtensa/sections.h
new file mode 100644
index 0000000..40b5191
--- /dev/null
+++ b/include/asm-xtensa/sections.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/sections.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SECTIONS_H
+#define _XTENSA_SECTIONS_H
+
+#include <asm-generic/sections.h>
+
+#endif	/* _XTENSA_SECTIONS_H */
diff --git a/include/asm-xtensa/segment.h b/include/asm-xtensa/segment.h
new file mode 100644
index 0000000..a2eb547
--- /dev/null
+++ b/include/asm-xtensa/segment.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/segment.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SEGMENT_H
+#define _XTENSA_SEGMENT_H
+
+#include <asm/uaccess.h>
+
+#endif	/* _XTENSA_SEGEMENT_H */
diff --git a/include/asm-xtensa/semaphore.h b/include/asm-xtensa/semaphore.h
new file mode 100644
index 0000000..c8a7574
--- /dev/null
+++ b/include/asm-xtensa/semaphore.h
@@ -0,0 +1,129 @@
+/*
+ * linux/include/asm-xtensa/semaphore.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SEMAPHORE_H
+#define _XTENSA_SEMAPHORE_H
+
+#include <asm/atomic.h>
+#include <asm/system.h>
+#include <linux/wait.h>
+#include <linux/rwsem.h>
+
+struct semaphore {
+	atomic_t count;
+	int sleepers;
+	wait_queue_head_t wait;
+#if WAITQUEUE_DEBUG
+	long __magic;
+#endif
+};
+
+#if WAITQUEUE_DEBUG
+# define __SEM_DEBUG_INIT(name) \
+		, (int)&(name).__magic
+#else
+# define __SEM_DEBUG_INIT(name)
+#endif
+
+#define __SEMAPHORE_INITIALIZER(name,count)			\
+	{ ATOMIC_INIT(count), 					\
+	  0,							\
+	  __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)		\
+	__SEM_DEBUG_INIT(name) }
+
+#define __MUTEX_INITIALIZER(name) \
+	__SEMAPHORE_INITIALIZER(name, 1)
+
+#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+
+#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+
+extern inline void sema_init (struct semaphore *sem, int val)
+{
+/*
+ *	*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+ *
+ * i'd rather use the more flexible initialization above, but sadly
+ * GCC 2.7.2.3 emits a bogus warning. EGCS doesnt. Oh well.
+ */
+	atomic_set(&sem->count, val);
+	init_waitqueue_head(&sem->wait);
+#if WAITQUEUE_DEBUG
+	sem->__magic = (int)&sem->__magic;
+#endif
+}
+
+static inline void init_MUTEX (struct semaphore *sem)
+{
+	sema_init(sem, 1);
+}
+
+static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+{
+	sema_init(sem, 0);
+}
+
+asmlinkage void __down(struct semaphore * sem);
+asmlinkage int  __down_interruptible(struct semaphore * sem);
+asmlinkage int  __down_trylock(struct semaphore * sem);
+asmlinkage void __up(struct semaphore * sem);
+
+extern spinlock_t semaphore_wake_lock;
+
+extern __inline__ void down(struct semaphore * sem)
+{
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	if (atomic_sub_return(1, &sem->count) < 0)
+		__down(sem);
+}
+
+extern __inline__ int down_interruptible(struct semaphore * sem)
+{
+	int ret = 0;
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	if (atomic_sub_return(1, &sem->count) < 0)
+		ret = __down_interruptible(sem);
+	return ret;
+}
+
+extern __inline__ int down_trylock(struct semaphore * sem)
+{
+	int ret = 0;
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	if (atomic_sub_return(1, &sem->count) < 0)
+		ret = __down_trylock(sem);
+	return ret;
+}
+
+/*
+ * Note! This is subtle. We jump to wake people up only if
+ * the semaphore was negative (== somebody was waiting on it).
+ */
+extern __inline__ void up(struct semaphore * sem)
+{
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+	if (atomic_add_return(1, &sem->count) <= 0)
+		__up(sem);
+}
+
+#endif /* _XTENSA_SEMAPHORE_H */
diff --git a/include/asm-xtensa/sembuf.h b/include/asm-xtensa/sembuf.h
new file mode 100644
index 0000000..2d26c47
--- /dev/null
+++ b/include/asm-xtensa/sembuf.h
@@ -0,0 +1,44 @@
+/*
+ * include/asm-xtensa/sembuf.h
+ *
+ * The semid64_ds structure for Xtensa architecture.
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ *
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ *
+ */
+
+#ifndef _XTENSA_SEMBUF_H
+#define _XTENSA_SEMBUF_H
+
+#include <asm/byteorder.h>
+
+struct semid64_ds {
+	struct ipc64_perm sem_perm;		/* permissions .. see ipc.h */
+#if XCHAL_HAVE_LE
+	__kernel_time_t	sem_otime;		/* last semop time */
+	unsigned long	__unused1;
+	__kernel_time_t	sem_ctime;		/* last change time */
+	unsigned long	__unused2;
+#else
+	unsigned long	__unused1;
+	__kernel_time_t	sem_otime;		/* last semop time */
+	unsigned long	__unused2;
+	__kernel_time_t	sem_ctime;		/* last change time */
+#endif
+	unsigned long	sem_nsems;		/* no. of semaphores in array */
+	unsigned long	__unused3;
+	unsigned long	__unused4;
+};
+
+#endif /* __ASM_XTENSA_SEMBUF_H */
diff --git a/include/asm-xtensa/serial.h b/include/asm-xtensa/serial.h
new file mode 100644
index 0000000..ec04114
--- /dev/null
+++ b/include/asm-xtensa/serial.h
@@ -0,0 +1,18 @@
+/*
+ * include/asm-xtensa/serial.h
+ *
+ * Configuration details for 8250, 16450, 16550, etc. serial ports
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SERIAL_H
+#define _XTENSA_SERIAL_H
+
+#include <asm/platform/serial.h>
+
+#endif	/* _XTENSA_SERIAL_H */
diff --git a/include/asm-xtensa/setup.h b/include/asm-xtensa/setup.h
new file mode 100644
index 0000000..e363652
--- /dev/null
+++ b/include/asm-xtensa/setup.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/setup.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SETUP_H
+#define _XTENSA_SETUP_H
+
+#define COMMAND_LINE_SIZE	256
+
+#endif
diff --git a/include/asm-xtensa/shmbuf.h b/include/asm-xtensa/shmbuf.h
new file mode 100644
index 0000000..a30b81a
--- /dev/null
+++ b/include/asm-xtensa/shmbuf.h
@@ -0,0 +1,50 @@
+/*
+ * include/asm-xtensa/shmbuf.h
+ *
+ * The shmid64_ds structure for Xtensa architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SHMBUF_H
+#define _XTENSA_SHMBUF_H
+
+struct shmid64_ds {
+	struct ipc64_perm	shm_perm;	/* operation perms */
+	size_t			shm_segsz;	/* size of segment (bytes) */
+	__kernel_time_t		shm_atime;	/* last attach time */
+	unsigned long		__unused1;
+	__kernel_time_t		shm_dtime;	/* last detach time */
+	unsigned long		__unused2;
+	__kernel_time_t		shm_ctime;	/* last change time */
+	unsigned long		__unused3;
+	__kernel_pid_t		shm_cpid;	/* pid of creator */
+	__kernel_pid_t		shm_lpid;	/* pid of last operator */
+	unsigned long		shm_nattch;	/* no. of current attaches */
+	unsigned long		__unused4;
+	unsigned long		__unused5;
+};
+
+struct shminfo64 {
+	unsigned long	shmmax;
+	unsigned long	shmmin;
+	unsigned long	shmmni;
+	unsigned long	shmseg;
+	unsigned long	shmall;
+	unsigned long	__unused1;
+	unsigned long	__unused2;
+	unsigned long	__unused3;
+	unsigned long	__unused4;
+};
+
+#endif	/* _XTENSA_SHMBUF_H */
diff --git a/include/asm-xtensa/shmparam.h b/include/asm-xtensa/shmparam.h
new file mode 100644
index 0000000..d3b65bf
--- /dev/null
+++ b/include/asm-xtensa/shmparam.h
@@ -0,0 +1,23 @@
+/*
+ * include/asm-xtensa/shmparam.h
+ *
+ * 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.
+ */
+
+#ifndef _XTENSA_SHMPARAM_H
+#define _XTENSA_SHMPARAM_H
+
+#include <asm/processor.h>
+
+/*
+ * Xtensa can have variable size caches, and if
+ * the size of single way is larger than the page size,
+ * then we have to start worrying about cache aliasing
+ * problems.
+ */
+
+#define SHMLBA	((PAGE_SIZE > DCACHE_WAY_SIZE)? PAGE_SIZE : DCACHE_WAY_SIZE)
+
+#endif /* _XTENSA_SHMPARAM_H */
diff --git a/include/asm-xtensa/sigcontext.h b/include/asm-xtensa/sigcontext.h
new file mode 100644
index 0000000..a751772
--- /dev/null
+++ b/include/asm-xtensa/sigcontext.h
@@ -0,0 +1,44 @@
+/*
+ * include/asm-xtensa/sigcontext.h
+ *
+ * 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) 2001 - 2003 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SIGCONTEXT_H
+#define _XTENSA_SIGCONTEXT_H
+
+#define _ASMLANGUAGE
+#include <asm/processor.h>
+#include <asm/coprocessor.h>
+
+
+struct _cpstate {
+	unsigned char _cpstate[XTENSA_CP_EXTRA_SIZE];
+} __attribute__ ((aligned (XTENSA_CP_EXTRA_ALIGN)));
+
+
+struct sigcontext {
+	unsigned long	oldmask;
+
+	/* CPU registers */
+	unsigned long sc_pc;
+	unsigned long sc_ps;
+	unsigned long sc_wmask;
+	unsigned long sc_windowbase;
+	unsigned long sc_windowstart;
+	unsigned long sc_lbeg;
+	unsigned long sc_lend;
+	unsigned long sc_lcount;
+	unsigned long sc_sar;
+	unsigned long sc_depc;
+	unsigned long sc_dareg0;
+	unsigned long sc_treg[4];
+	unsigned long sc_areg[XCHAL_NUM_AREGS];
+	struct _cpstate *sc_cpstate;
+};
+
+#endif /* __ASM_XTENSA_SIGCONTEXT_H */
diff --git a/include/asm-xtensa/siginfo.h b/include/asm-xtensa/siginfo.h
new file mode 100644
index 0000000..44f0ae7
--- /dev/null
+++ b/include/asm-xtensa/siginfo.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/processor.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SIGINFO_H
+#define _XTENSA_SIGINFO_H
+
+#include <asm-generic/siginfo.h>
+
+#endif	/* _XTENSA_SIGINFO_H */
diff --git a/include/asm-xtensa/signal.h b/include/asm-xtensa/signal.h
new file mode 100644
index 0000000..5d6fc9c
--- /dev/null
+++ b/include/asm-xtensa/signal.h
@@ -0,0 +1,187 @@
+/*
+ * include/asm-xtensa/signal.h
+ *
+ * Swiped from SH.
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SIGNAL_H
+#define _XTENSA_SIGNAL_H
+
+
+#define _NSIG		64
+#define _NSIG_BPW	32
+#define _NSIG_WORDS	(_NSIG / _NSIG_BPW)
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+/* Avoid too many header ordering problems.  */
+struct siginfo;
+typedef unsigned long old_sigset_t;		/* at least 32 bits */
+typedef struct {
+	unsigned long sig[_NSIG_WORDS];
+} sigset_t;
+
+#endif
+
+#define SIGHUP		 1
+#define SIGINT		 2
+#define SIGQUIT		 3
+#define SIGILL		 4
+#define SIGTRAP		 5
+#define SIGABRT		 6
+#define SIGIOT		 6
+#define SIGBUS		 7
+#define SIGFPE		 8
+#define SIGKILL		 9
+#define SIGUSR1		10
+#define SIGSEGV		11
+#define SIGUSR2		12
+#define SIGPIPE		13
+#define SIGALRM		14
+#define SIGTERM		15
+#define SIGSTKFLT	16
+#define SIGCHLD		17
+#define SIGCONT		18
+#define SIGSTOP		19
+#define SIGTSTP		20
+#define SIGTTIN		21
+#define SIGTTOU		22
+#define SIGURG		23
+#define SIGXCPU		24
+#define SIGXFSZ		25
+#define SIGVTALRM	26
+#define SIGPROF		27
+#define SIGWINCH	28
+#define SIGIO		29
+#define SIGPOLL		SIGIO
+/* #define SIGLOST		29 */
+#define SIGPWR		30
+#define SIGSYS		31
+#define	SIGUNUSED	31
+
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN	32
+#define SIGRTMAX	(_NSIG-1)
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_NOCLDSTOP	0x00000001
+#define SA_NOCLDWAIT	0x00000002 /* not supported yet */
+#define SA_SIGINFO	0x00000004
+#define SA_ONSTACK	0x08000000
+#define SA_RESTART	0x10000000
+#define SA_NODEFER	0x40000000
+#define SA_RESETHAND	0x80000000
+
+#define SA_NOMASK	SA_NODEFER
+#define SA_ONESHOT	SA_RESETHAND
+#define SA_INTERRUPT	0x20000000 /* dummy -- ignored */
+
+#define SA_RESTORER	0x04000000
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK	1
+#define SS_DISABLE	2
+
+#define MINSIGSTKSZ	2048
+#define SIGSTKSZ	8192
+
+#ifndef __ASSEMBLY__
+#ifdef __KERNEL__
+
+/*
+ * These values of sa_flags are used only by the kernel as part of the
+ * irq handling routines.
+ *
+ * SA_INTERRUPT is also used by the irq handling routines.
+ * SA_SHIRQ is for shared interrupt support on PCI and EISA.
+ */
+#define SA_PROBE		SA_ONESHOT
+#define SA_SAMPLE_RANDOM	SA_RESTART
+#define SA_SHIRQ		0x04000000
+#endif
+
+#define SIG_BLOCK          0	/* for blocking signals */
+#define SIG_UNBLOCK        1	/* for unblocking signals */
+#define SIG_SETMASK        2	/* for setting the signal mask */
+
+/* Type of a signal handler.  */
+typedef void (*__sighandler_t)(int);
+
+#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
+#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
+#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+
+#ifdef __KERNEL__
+struct old_sigaction {
+	__sighandler_t sa_handler;
+	old_sigset_t sa_mask;
+	unsigned long sa_flags;
+	void (*sa_restorer)(void);
+};
+
+struct sigaction {
+	__sighandler_t sa_handler;
+	unsigned long sa_flags;
+	void (*sa_restorer)(void);
+	sigset_t sa_mask;		/* mask last for extensibility */
+};
+
+struct k_sigaction {
+	struct sigaction sa;
+};
+
+#else
+
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+struct sigaction {
+	union {
+	  __sighandler_t _sa_handler;
+	  void (*_sa_sigaction)(int, struct siginfo *, void *);
+	} _u;
+	sigset_t sa_mask;
+	unsigned long sa_flags;
+	void (*sa_restorer)(void);
+};
+
+#define sa_handler	_u._sa_handler
+#define sa_sigaction	_u._sa_sigaction
+
+#endif /* __KERNEL__ */
+
+typedef struct sigaltstack {
+	void *ss_sp;
+	int ss_flags;
+	size_t ss_size;
+} stack_t;
+
+#ifdef __KERNEL__
+#include <asm/sigcontext.h>
+#define ptrace_signal_deliver(regs, cookie) do { } while (0)
+
+#endif	/* __KERNEL__ */
+#endif	/* __ASSEMBLY__ */
+#endif	/* _XTENSA_SIGNAL_H */
diff --git a/include/asm-xtensa/smp.h b/include/asm-xtensa/smp.h
new file mode 100644
index 0000000..83c569e
--- /dev/null
+++ b/include/asm-xtensa/smp.h
@@ -0,0 +1,27 @@
+/*
+ * include/asm-xtensa/smp.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SMP_H
+#define _XTENSA_SMP_H
+
+extern struct xtensa_cpuinfo boot_cpu_data;
+
+#define cpu_data (&boot_cpu_data)
+#define current_cpu_data boot_cpu_data
+
+struct xtensa_cpuinfo {
+	unsigned long	*pgd_cache;
+	unsigned long	*pte_cache;
+	unsigned long	pgtable_cache_sz;
+};
+
+#define cpu_logical_map(cpu)	(cpu)
+
+#endif	/* _XTENSA_SMP_H */
diff --git a/include/asm-xtensa/socket.h b/include/asm-xtensa/socket.h
new file mode 100644
index 0000000..daccd05
--- /dev/null
+++ b/include/asm-xtensa/socket.h
@@ -0,0 +1,61 @@
+/*
+ * include/asm-xtensa/socket.h
+ *
+ * Copied from i386.
+ *
+ * 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.
+ */
+
+#ifndef _XTENSA_SOCKET_H
+#define _XTENSA_SOCKET_H
+
+#include <asm/sockios.h>
+
+/* For setsockoptions(2) */
+#define SOL_SOCKET	1
+
+#define SO_DEBUG	1
+#define SO_REUSEADDR	2
+#define SO_TYPE		3
+#define SO_ERROR	4
+#define SO_DONTROUTE	5
+#define SO_BROADCAST	6
+#define SO_SNDBUF	7
+#define SO_RCVBUF	8
+#define SO_KEEPALIVE	9
+#define SO_OOBINLINE	10
+#define SO_NO_CHECK	11
+#define SO_PRIORITY	12
+#define SO_LINGER	13
+#define SO_BSDCOMPAT	14
+/* To add :#define SO_REUSEPORT 15 */
+#define SO_PASSCRED	16
+#define SO_PEERCRED	17
+#define SO_RCVLOWAT	18
+#define SO_SNDLOWAT	19
+#define SO_RCVTIMEO	20
+#define SO_SNDTIMEO	21
+
+/* Security levels - as per NRL IPv6 - don't actually do anything */
+
+#define SO_SECURITY_AUTHENTICATION		22
+#define SO_SECURITY_ENCRYPTION_TRANSPORT	23
+#define SO_SECURITY_ENCRYPTION_NETWORK		24
+
+#define SO_BINDTODEVICE	25
+
+/* Socket filtering */
+
+#define SO_ATTACH_FILTER        26
+#define SO_DETACH_FILTER        27
+
+#define SO_PEERNAME		28
+#define SO_TIMESTAMP		29
+#define SCM_TIMESTAMP		SO_TIMESTAMP
+
+#define SO_ACCEPTCONN		30
+#define SO_PEERSEC		31
+
+#endif	/* _XTENSA_SOCKET_H */
diff --git a/include/asm-xtensa/sockios.h b/include/asm-xtensa/sockios.h
new file mode 100644
index 0000000..20d2ba1
--- /dev/null
+++ b/include/asm-xtensa/sockios.h
@@ -0,0 +1,30 @@
+/*
+ * include/asm-xtensa/sockios.h
+ *
+ * Socket-level I/O control calls.  Copied from MIPS.
+ *
+ * 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 by Ralf Baechle
+ * Copyright (C) 2001 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SOCKIOS_H
+#define _XTENSA_SOCKIOS_H
+
+#include <asm/ioctl.h>
+
+/* Socket-level I/O control calls. */
+
+#define FIOGETOWN	_IOR('f', 123, int)
+#define FIOSETOWN 	_IOW('f', 124, int)
+
+#define SIOCATMARK	_IOR('s', 7, int)
+#define SIOCSPGRP	_IOW('s', 8, pid_t)
+#define SIOCGPGRP	_IOR('s', 9, pid_t)
+
+#define SIOCGSTAMP	0x8906		/* Get stamp - linux-specific */
+
+#endif	/* _XTENSA_SOCKIOS_H */
diff --git a/include/asm-xtensa/spinlock.h b/include/asm-xtensa/spinlock.h
new file mode 100644
index 0000000..8ff2364
--- /dev/null
+++ b/include/asm-xtensa/spinlock.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/spinlock.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SPINLOCK_H
+#define _XTENSA_SPINLOCK_H
+
+#include <linux/spinlock.h>
+
+#endif	/* _XTENSA_SPINLOCK_H */
diff --git a/include/asm-xtensa/stat.h b/include/asm-xtensa/stat.h
new file mode 100644
index 0000000..2f4662f
--- /dev/null
+++ b/include/asm-xtensa/stat.h
@@ -0,0 +1,105 @@
+/*
+ * include/asm-xtensa/stat.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_STAT_H
+#define _XTENSA_STAT_H
+
+#include <linux/types.h>
+
+struct __old_kernel_stat {
+	unsigned short st_dev;
+	unsigned short st_ino;
+	unsigned short st_mode;
+	unsigned short st_nlink;
+	unsigned short st_uid;
+	unsigned short st_gid;
+	unsigned short st_rdev;
+	unsigned long  st_size;
+	unsigned long  st_atime;
+	unsigned long  st_mtime;
+	unsigned long  st_ctime;
+};
+
+#define STAT_HAVE_NSEC 1
+
+struct stat {
+	unsigned short st_dev;
+	unsigned short __pad1;
+	unsigned long st_ino;
+	unsigned short st_mode;
+	unsigned short st_nlink;
+	unsigned short st_uid;
+	unsigned short st_gid;
+	unsigned short st_rdev;
+	unsigned short __pad2;
+	unsigned long  st_size;
+	unsigned long  st_blksize;
+	unsigned long  st_blocks;
+	unsigned long  st_atime;
+	unsigned long  st_atime_nsec;
+	unsigned long  st_mtime;
+	unsigned long  st_mtime_nsec;
+	unsigned long  st_ctime;
+	unsigned long  st_ctime_nsec;
+	unsigned long  __unused4;
+	unsigned long  __unused5;
+};
+
+/* This matches struct stat64 in glibc-2.2.3. */
+
+struct stat64  {
+#ifdef __XTENSA_EL__
+	unsigned short	st_dev;		/* Device */
+	unsigned char	__pad0[10];
+#else
+	unsigned char	__pad0[6];
+	unsigned short	st_dev;
+	unsigned char	__pad1[2];
+#endif
+
+#define STAT64_HAS_BROKEN_ST_INO	1
+	unsigned long __st_ino;		/* 32bit file serial number. */
+
+	unsigned int  st_mode;		/* File mode. */
+	unsigned int  st_nlink;		/* Link count. */
+	unsigned int  st_uid;		/* User ID of the file's owner. */
+	unsigned int  st_gid;		/* Group ID of the file's group. */
+
+#ifdef __XTENSA_EL__
+	unsigned short	st_rdev;	/* Device number, if device. */
+	unsigned char	__pad3[10];
+#else
+	unsigned char	__pad2[6];
+	unsigned short	st_rdev;
+	unsigned char	__pad3[2];
+#endif
+
+	long long int  st_size;		/* Size of file, in bytes. */
+	long int st_blksize;		/* Optimal block size for I/O. */
+
+#ifdef __XTENSA_EL__
+	unsigned long  st_blocks;	/* Number 512-byte blocks allocated. */
+	unsigned long  __pad4;
+#else
+	unsigned long  __pad4;
+	unsigned long  st_blocks;
+#endif
+
+	unsigned long  __pad5;
+	long int st_atime;		/* Time of last access. */
+	unsigned long  st_atime_nsec;
+	long int st_mtime;		/* Time of last modification. */
+	unsigned long  st_mtime_nsec;
+	long int  st_ctime;		/* Time of last status change. */
+	unsigned long  st_ctime_nsec;
+	unsigned long long int st_ino;	/* File serial number. */
+};
+
+#endif	/* _XTENSA_STAT_H */
diff --git a/include/asm-xtensa/statfs.h b/include/asm-xtensa/statfs.h
new file mode 100644
index 0000000..9c3d1a2
--- /dev/null
+++ b/include/asm-xtensa/statfs.h
@@ -0,0 +1,17 @@
+/*
+ * include/asm-xtensa/statfs.h
+ *
+ * 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 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_STATFS_H
+#define _XTENSA_STATFS_H
+
+#include <asm-generic/statfs.h>
+
+#endif	/* _XTENSA_STATFS_H */
+
diff --git a/include/asm-xtensa/string.h b/include/asm-xtensa/string.h
new file mode 100644
index 0000000..3f81b27
--- /dev/null
+++ b/include/asm-xtensa/string.h
@@ -0,0 +1,124 @@
+/*
+ * include/asm-xtensa/string.h
+ *
+ * These trivial string functions are considered part of the public domain.
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+/* We should optimize these. See arch/xtensa/lib/strncpy_user.S */
+
+#ifndef _XTENSA_STRING_H
+#define _XTENSA_STRING_H
+
+#define __HAVE_ARCH_STRCPY
+extern __inline__ char *strcpy(char *__dest, const char *__src)
+{
+	register char *__xdest = __dest;
+	unsigned long __dummy;
+
+	__asm__ __volatile__("1:\n\t"
+		"l8ui	%2, %1, 0\n\t"
+		"s8i	%2, %0, 0\n\t"
+		"addi	%1, %1, 1\n\t"
+		"addi	%0, %0, 1\n\t"
+		"bnez	%2, 1b\n\t"
+		: "=r" (__dest), "=r" (__src), "=&r" (__dummy)
+		: "0" (__dest), "1" (__src)
+		: "memory");
+
+	return __xdest;
+}
+
+#define __HAVE_ARCH_STRNCPY
+extern __inline__ char *strncpy(char *__dest, const char *__src, size_t __n)
+{
+	register char *__xdest = __dest;
+	unsigned long __dummy;
+
+	if (__n == 0)
+		return __xdest;
+
+	__asm__ __volatile__(
+		"1:\n\t"
+		"l8ui	%2, %1, 0\n\t"
+		"s8i	%2, %0, 0\n\t"
+		"addi	%1, %1, 1\n\t"
+		"addi	%0, %0, 1\n\t"
+		"beqz	%2, 2f\n\t"
+		"bne	%1, %5, 1b\n"
+		"2:"
+		: "=r" (__dest), "=r" (__src), "=&r" (__dummy)
+		: "0" (__dest), "1" (__src), "r" (__src+__n)
+		: "memory");
+
+	return __xdest;
+}
+
+#define __HAVE_ARCH_STRCMP
+extern __inline__ int strcmp(const char *__cs, const char *__ct)
+{
+	register int __res;
+	unsigned long __dummy;
+
+	__asm__ __volatile__(
+		"1:\n\t"
+		"l8ui	%3, %1, 0\n\t"
+		"addi	%1, %1, 1\n\t"
+		"l8ui	%2, %0, 0\n\t"
+		"addi	%0, %0, 1\n\t"
+		"beqz	%2, 2f\n\t"
+		"beq	%2, %3, 1b\n"
+		"2:\n\t"
+		"sub	%2, %3, %2"
+		: "=r" (__cs), "=r" (__ct), "=&r" (__res), "=&r" (__dummy)
+		: "0" (__cs), "1" (__ct));
+
+	return __res;
+}
+
+#define __HAVE_ARCH_STRNCMP
+extern __inline__ int strncmp(const char *__cs, const char *__ct, size_t __n)
+{
+	register int __res;
+	unsigned long __dummy;
+
+	__asm__ __volatile__(
+		"mov	%2, %3\n"
+		"1:\n\t"
+		"beq	%0, %6, 2f\n\t"
+		"l8ui	%3, %1, 0\n\t"
+		"addi	%1, %1, 1\n\t"
+		"l8ui	%2, %0, 0\n\t"
+		"addi	%0, %0, 1\n\t"
+		"beqz	%2, 2f\n\t"
+		"beqz	%3, 2f\n\t"
+		"beq	%2, %3, 1b\n"
+		"2:\n\t"
+		"sub	%2, %3, %2"
+		: "=r" (__cs), "=r" (__ct), "=&r" (__res), "=&r" (__dummy)
+		: "0" (__cs), "1" (__ct), "r" (__cs+__n));
+
+	return __res;
+}
+
+#define __HAVE_ARCH_MEMSET
+extern void *memset(void *__s, int __c, size_t __count);
+
+#define __HAVE_ARCH_MEMCPY
+extern void *memcpy(void *__to, __const__ void *__from, size_t __n);
+
+#define __HAVE_ARCH_MEMMOVE
+extern void *memmove(void *__dest, __const__ void *__src, size_t __n);
+
+/* Don't build bcopy at all ...  */
+#define __HAVE_ARCH_BCOPY
+
+#define __HAVE_ARCH_MEMSCAN
+#define memscan memchr
+
+#endif	/* _XTENSA_STRING_H */
diff --git a/include/asm-xtensa/system.h b/include/asm-xtensa/system.h
new file mode 100644
index 0000000..690fe32
--- /dev/null
+++ b/include/asm-xtensa/system.h
@@ -0,0 +1,252 @@
+/*
+ * include/asm-xtensa/system.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SYSTEM_H
+#define _XTENSA_SYSTEM_H
+
+#include <linux/config.h>
+#include <linux/stringify.h>
+
+#include <asm/processor.h>
+
+/* interrupt control */
+
+#define local_save_flags(x)						\
+	__asm__ __volatile__ ("rsr %0,"__stringify(PS) : "=a" (x));
+#define local_irq_restore(x)	do {					\
+	__asm__ __volatile__ ("wsr %0, "__stringify(PS)" ; rsync" 	\
+	    		      :: "a" (x) : "memory"); } while(0);
+#define local_irq_save(x)	do {					\
+	__asm__ __volatile__ ("rsil %0, "__stringify(LOCKLEVEL) 	\
+	    		      : "=a" (x) :: "memory");} while(0);
+
+static inline void local_irq_disable(void)
+{
+	unsigned long flags;
+	__asm__ __volatile__ ("rsil %0, "__stringify(LOCKLEVEL)
+	    		      : "=a" (flags) :: "memory");
+}
+static inline void local_irq_enable(void)
+{
+	unsigned long flags;
+	__asm__ __volatile__ ("rsil %0, 0" : "=a" (flags) :: "memory");
+
+}
+
+static inline int irqs_disabled(void)
+{
+	unsigned long flags;
+	local_save_flags(flags);
+	return flags & 0xf;
+}
+
+#define RSR_CPENABLE(x)	do {						  \
+	__asm__ __volatile__("rsr %0," __stringify(CPENABLE) : "=a" (x)); \
+	} while(0);
+#define WSR_CPENABLE(x)	do {						  \
+  	__asm__ __volatile__("wsr %0," __stringify(CPENABLE)";rsync" 	  \
+	    		     :: "a" (x));} while(0);
+
+#define clear_cpenable() __clear_cpenable()
+
+extern __inline__ void __clear_cpenable(void)
+{
+#if XCHAL_HAVE_CP
+	unsigned long i = 0;
+	WSR_CPENABLE(i);
+#endif
+}
+
+extern __inline__ void enable_coprocessor(int i)
+{
+#if XCHAL_HAVE_CP
+	int cp;
+	RSR_CPENABLE(cp);
+	cp |= 1 << i;
+	WSR_CPENABLE(cp);
+#endif
+}
+
+extern __inline__ void disable_coprocessor(int i)
+{
+#if XCHAL_HAVE_CP
+	int cp;
+	RSR_CPENABLE(cp);
+	cp &= ~(1 << i);
+	WSR_CPENABLE(cp);
+#endif
+}
+
+#define smp_read_barrier_depends() do { } while(0)
+#define read_barrier_depends() do { } while(0)
+
+#define mb()  barrier()
+#define rmb() mb()
+#define wmb() mb()
+
+#ifdef CONFIG_SMP
+#error smp_* not defined
+#else
+#define smp_mb()	barrier()
+#define smp_rmb()	barrier()
+#define smp_wmb()	barrier()
+#endif
+
+#define set_mb(var, value)	do { var = value; mb(); } while (0)
+#define set_wmb(var, value)	do { var = value; wmb(); } while (0)
+
+#if !defined (__ASSEMBLY__)
+
+/* * switch_to(n) should switch tasks to task nr n, first
+ * checking that n isn't the current task, in which case it does nothing.
+ */
+extern void *_switch_to(void *last, void *next);
+
+#endif	/* __ASSEMBLY__ */
+
+#define prepare_to_switch()	do { } while(0)
+
+#define switch_to(prev,next,last)		\
+do {						\
+	clear_cpenable();			\
+	(last) = _switch_to(prev, next);	\
+} while(0)
+
+/*
+ * cmpxchg
+ */
+
+extern __inline__ unsigned long
+__cmpxchg_u32(volatile int *p, int old, int new)
+{
+  __asm__ __volatile__("rsil    a15, "__stringify(LOCKLEVEL)"\n\t"
+		       "l32i    %0, %1, 0              \n\t"
+		       "bne	%0, %2, 1f             \n\t"
+		       "s32i    %3, %1, 0              \n\t"
+		       "1:                             \n\t"
+		       "wsr     a15, "__stringify(PS)" \n\t"
+		       "rsync                          \n\t"
+		       : "=&a" (old)
+		       : "a" (p), "a" (old), "r" (new)
+		       : "a15", "memory");
+  return old;
+}
+/* This function doesn't exist, so you'll get a linker error
+ * if something tries to do an invalid cmpxchg(). */
+
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+static __inline__ unsigned long
+__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
+{
+	switch (size) {
+	case 4:  return __cmpxchg_u32(ptr, old, new);
+	default: __cmpxchg_called_with_bad_pointer();
+		 return old;
+	}
+}
+
+#define cmpxchg(ptr,o,n)						      \
+	({ __typeof__(*(ptr)) _o_ = (o);				      \
+	   __typeof__(*(ptr)) _n_ = (n);				      \
+	   (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,	      \
+	   			        (unsigned long)_n_, sizeof (*(ptr))); \
+	})
+
+
+
+
+/*
+ * xchg_u32
+ *
+ * Note that a15 is used here because the register allocation
+ * done by the compiler is not guaranteed and a window overflow
+ * may not occur between the rsil and wsr instructions. By using
+ * a15 in the rsil, the machine is guaranteed to be in a state
+ * where no register reference will cause an overflow.
+ */
+
+extern __inline__ unsigned long xchg_u32(volatile int * m, unsigned long val)
+{
+  unsigned long tmp;
+  __asm__ __volatile__("rsil    a15, "__stringify(LOCKLEVEL)"\n\t"
+		       "l32i    %0, %1, 0              \n\t"
+		       "s32i    %2, %1, 0              \n\t"
+		       "wsr     a15, "__stringify(PS)" \n\t"
+		       "rsync                          \n\t"
+		       : "=&a" (tmp)
+		       : "a" (m), "a" (val)
+		       : "a15", "memory");
+  return tmp;
+}
+
+#define tas(ptr) (xchg((ptr),1))
+
+#if ( __XCC__ == 1 )
+
+/* xt-xcc processes __inline__ differently than xt-gcc and decides to
+ * insert an out-of-line copy of function __xchg.  This presents the
+ * unresolved symbol at link time of __xchg_called_with_bad_pointer,
+ * even though such a function would never be called at run-time.
+ * xt-gcc always inlines __xchg, and optimizes away the undefined
+ * bad_pointer function.
+ */
+
+#define xchg(ptr,x) xchg_u32(ptr,x)
+
+#else  /* assume xt-gcc */
+
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+
+/*
+ * This only works if the compiler isn't horribly bad at optimizing.
+ * gcc-2.5.8 reportedly can't handle this, but I define that one to
+ * be dead anyway.
+ */
+
+extern void __xchg_called_with_bad_pointer(void);
+
+static __inline__ unsigned long
+__xchg(unsigned long x, volatile void * ptr, int size)
+{
+	switch (size) {
+		case 4:
+			return xchg_u32(ptr, x);
+	}
+	__xchg_called_with_bad_pointer();
+	return x;
+}
+
+#endif
+
+extern void set_except_vector(int n, void *addr);
+
+static inline void spill_registers(void)
+{
+	unsigned int a0, ps;
+
+	__asm__ __volatile__ (
+		"movi	a14," __stringify (PS_EXCM_MASK) " | 1\n\t"
+		"mov	a12, a0\n\t"
+		"rsr	a13," __stringify(SAR) "\n\t"
+		"xsr	a14," __stringify(PS) "\n\t"
+		"movi	a0, _spill_registers\n\t"
+		"rsync\n\t"
+		"callx0 a0\n\t"
+		"mov	a0, a12\n\t"
+		"wsr	a13," __stringify(SAR) "\n\t"
+		"wsr	a14," __stringify(PS) "\n\t"
+		:: "a" (&a0), "a" (&ps)
+		: "a2", "a3", "a12", "a13", "a14", "a15", "memory");
+}
+
+#define arch_align_stack(x) (x)
+
+#endif	/* _XTENSA_SYSTEM_H */
diff --git a/include/asm-xtensa/termbits.h b/include/asm-xtensa/termbits.h
new file mode 100644
index 0000000..c780593
--- /dev/null
+++ b/include/asm-xtensa/termbits.h
@@ -0,0 +1,194 @@
+/*
+ * include/asm-xtensa/termbits.h
+ *
+ * Copied from SH.
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_TERMBITS_H
+#define _XTENSA_TERMBITS_H
+
+
+#include <linux/posix_types.h>
+
+typedef unsigned char	cc_t;
+typedef unsigned int	speed_t;
+typedef unsigned int	tcflag_t;
+
+#define NCCS 19
+struct termios {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+};
+
+/* c_cc characters */
+
+#define VINTR 0
+#define VQUIT 1
+#define VERASE 2
+#define VKILL 3
+#define VEOF 4
+#define VTIME 5
+#define VMIN 6
+#define VSWTC 7
+#define VSTART 8
+#define VSTOP 9
+#define VSUSP 10
+#define VEOL 11
+#define VREPRINT 12
+#define VDISCARD 13
+#define VWERASE 14
+#define VLNEXT 15
+#define VEOL2 16
+
+/* c_iflag bits */
+
+#define IGNBRK	0000001
+#define BRKINT	0000002
+#define IGNPAR	0000004
+#define PARMRK	0000010
+#define INPCK	0000020
+#define ISTRIP	0000040
+#define INLCR	0000100
+#define IGNCR	0000200
+#define ICRNL	0000400
+#define IUCLC	0001000
+#define IXON	0002000
+#define IXANY	0004000
+#define IXOFF	0010000
+#define IMAXBEL	0020000
+#define IUTF8	0040000
+
+/* c_oflag bits */
+
+#define OPOST	0000001
+#define OLCUC	0000002
+#define ONLCR	0000004
+#define OCRNL	0000010
+#define ONOCR	0000020
+#define ONLRET	0000040
+#define OFILL	0000100
+#define OFDEL	0000200
+#define NLDLY	0000400
+#define   NL0	0000000
+#define   NL1	0000400
+#define CRDLY	0003000
+#define   CR0	0000000
+#define   CR1	0001000
+#define   CR2	0002000
+#define   CR3	0003000
+#define TABDLY	0014000
+#define   TAB0	0000000
+#define   TAB1	0004000
+#define   TAB2	0010000
+#define   TAB3	0014000
+#define   XTABS	0014000
+#define BSDLY	0020000
+#define   BS0	0000000
+#define   BS1	0020000
+#define VTDLY	0040000
+#define   VT0	0000000
+#define   VT1	0040000
+#define FFDLY	0100000
+#define   FF0	0000000
+#define   FF1	0100000
+
+/* c_cflag bit meaning */
+
+#define CBAUD	0010017
+#define  B0	0000000		/* hang up */
+#define  B50	0000001
+#define  B75	0000002
+#define  B110	0000003
+#define  B134	0000004
+#define  B150	0000005
+#define  B200	0000006
+#define  B300	0000007
+#define  B600	0000010
+#define  B1200	0000011
+#define  B1800	0000012
+#define  B2400	0000013
+#define  B4800	0000014
+#define  B9600	0000015
+#define  B19200	0000016
+#define  B38400	0000017
+#define EXTA B19200
+#define EXTB B38400
+#define CSIZE	0000060
+#define   CS5	0000000
+#define   CS6	0000020
+#define   CS7	0000040
+#define   CS8	0000060
+#define CSTOPB	0000100
+#define CREAD	0000200
+#define PARENB	0000400
+#define PARODD	0001000
+#define HUPCL	0002000
+#define CLOCAL	0004000
+#define CBAUDEX 0010000
+#define    B57600 0010001
+#define   B115200 0010002
+#define   B230400 0010003
+#define   B460800 0010004
+#define   B500000 0010005
+#define   B576000 0010006
+#define   B921600 0010007
+#define  B1000000 0010010
+#define  B1152000 0010011
+#define  B1500000 0010012
+#define  B2000000 0010013
+#define  B2500000 0010014
+#define  B3000000 0010015
+#define  B3500000 0010016
+#define  B4000000 0010017
+#define CIBAUD	  002003600000	/* input baud rate (not used) */
+#define CMSPAR	  010000000000		/* mark or space (stick) parity */
+#define CRTSCTS	  020000000000		/* flow control */
+
+/* c_lflag bits */
+
+#define ISIG	0000001
+#define ICANON	0000002
+#define XCASE	0000004
+#define ECHO	0000010
+#define ECHOE	0000020
+#define ECHOK	0000040
+#define ECHONL	0000100
+#define NOFLSH	0000200
+#define TOSTOP	0000400
+#define ECHOCTL	0001000
+#define ECHOPRT	0002000
+#define ECHOKE	0004000
+#define FLUSHO	0010000
+#define PENDIN	0040000
+#define IEXTEN	0100000
+
+/* tcflow() and TCXONC use these */
+
+#define	TCOOFF		0
+#define	TCOON		1
+#define	TCIOFF		2
+#define	TCION		3
+
+/* tcflush() and TCFLSH use these */
+
+#define	TCIFLUSH	0
+#define	TCOFLUSH	1
+#define	TCIOFLUSH	2
+
+/* tcsetattr uses these */
+
+#define	TCSANOW		0
+#define	TCSADRAIN	1
+#define	TCSAFLUSH	2
+
+#endif	/* _XTENSA_TERMBITS_H */
diff --git a/include/asm-xtensa/termios.h b/include/asm-xtensa/termios.h
new file mode 100644
index 0000000..83c6aed
--- /dev/null
+++ b/include/asm-xtensa/termios.h
@@ -0,0 +1,122 @@
+/*
+ * include/asm-xtensa/termios.h
+ *
+ * Copied from SH.
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_TERMIOS_H
+#define _XTENSA_TERMIOS_H
+
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+struct winsize {
+	unsigned short ws_row;
+	unsigned short ws_col;
+	unsigned short ws_xpixel;
+	unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+	unsigned short c_iflag;		/* input mode flags */
+	unsigned short c_oflag;		/* output mode flags */
+	unsigned short c_cflag;		/* control mode flags */
+	unsigned short c_lflag;		/* local mode flags */
+	unsigned char c_line;		/* line discipline */
+	unsigned char c_cc[NCC];	/* control characters */
+};
+
+/* Modem lines */
+
+#define TIOCM_LE	0x001
+#define TIOCM_DTR	0x002
+#define TIOCM_RTS	0x004
+#define TIOCM_ST	0x008
+#define TIOCM_SR	0x010
+#define TIOCM_CTS	0x020
+#define TIOCM_CAR	0x040
+#define TIOCM_RNG	0x080
+#define TIOCM_DSR	0x100
+#define TIOCM_CD	TIOCM_CAR
+#define TIOCM_RI	TIOCM_RNG
+#define TIOCM_OUT1	0x2000
+#define TIOCM_OUT2	0x4000
+#define TIOCM_LOOP	0x8000
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+
+/* Line disciplines */
+
+#define N_TTY		0
+#define N_SLIP		1
+#define N_MOUSE		2
+#define N_PPP		3
+#define N_STRIP		4
+#define N_AX25		5
+#define N_X25		6	/* X.25 async */
+#define N_6PACK		7
+#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
+#define N_R3964		9	/* Reserved for Simatic R3964 module */
+#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
+#define N_IRDA		11	/* Linux IR - http://irda.sourceforge.net/ */
+#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
+#define N_HDLC		13	/* synchronous HDLC */
+#define N_SYNC_PPP	14
+#define N_HCI		15      /* Bluetooth HCI UART */
+
+#ifdef __KERNEL__
+
+/*	intr=^C		quit=^\		erase=del	kill=^U
+	eof=^D		vtime=\0	vmin=\1		sxtc=\0
+	start=^Q	stop=^S		susp=^Z		eol=\0
+	reprint=^R	discard=^U	werase=^W	lnext=^V
+	eol2=\0
+*/
+#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
+
+/*
+ * Translate a "termio" structure into a "termios". Ugh.
+ */
+
+#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
+	unsigned short __tmp; \
+	get_user(__tmp,&(termio)->x); \
+	*(unsigned short *) &(termios)->x = __tmp; \
+}
+
+#define user_termio_to_kernel_termios(termios, termio) \
+({ \
+	SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
+	SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
+	SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
+	SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
+	copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
+})
+
+/*
+ * Translate a "termios" structure into a "termio". Ugh.
+ */
+
+#define kernel_termios_to_user_termio(termio, termios) \
+({ \
+	put_user((termios)->c_iflag, &(termio)->c_iflag); \
+	put_user((termios)->c_oflag, &(termio)->c_oflag); \
+	put_user((termios)->c_cflag, &(termio)->c_cflag); \
+	put_user((termios)->c_lflag, &(termio)->c_lflag); \
+	put_user((termios)->c_line,  &(termio)->c_line); \
+	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
+})
+
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+
+#endif	/* __KERNEL__ */
+
+#endif	/* _XTENSA_TERMIOS_H */
diff --git a/include/asm-xtensa/thread_info.h b/include/asm-xtensa/thread_info.h
new file mode 100644
index 0000000..af208d4
--- /dev/null
+++ b/include/asm-xtensa/thread_info.h
@@ -0,0 +1,146 @@
+/*
+ * include/asm-xtensa/thread_info.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_THREAD_INFO_H
+#define _XTENSA_THREAD_INFO_H
+
+#ifdef __KERNEL__
+
+#ifndef __ASSEMBLY__
+# include <asm/processor.h>
+#endif
+
+/*
+ * low level task data that entry.S needs immediate access to
+ * - this struct should fit entirely inside of one cache line
+ * - this struct shares the supervisor stack pages
+ * - if the contents of this structure are changed, the assembly constants
+ *   must also be changed
+ */
+
+#ifndef __ASSEMBLY__
+
+struct thread_info {
+	struct task_struct	*task;		/* main task structure */
+	struct exec_domain	*exec_domain;	/* execution domain */
+	unsigned long		flags;		/* low level flags */
+	unsigned long		status;		/* thread-synchronous flags */
+	__u32			cpu;		/* current CPU */
+	__s32			preempt_count;	/* 0 => preemptable,< 0 => BUG*/
+
+	mm_segment_t		addr_limit;	/* thread address space */
+	struct restart_block    restart_block;
+
+
+};
+
+#else /* !__ASSEMBLY__ */
+
+/* offsets into the thread_info struct for assembly code access */
+#define TI_TASK		 0x00000000
+#define TI_EXEC_DOMAIN	 0x00000004
+#define TI_FLAGS	 0x00000008
+#define TI_STATUS	 0x0000000C
+#define TI_CPU		 0x00000010
+#define TI_PRE_COUNT	 0x00000014
+#define TI_ADDR_LIMIT	 0x00000018
+#define TI_RESTART_BLOCK 0x000001C
+
+#endif
+
+#define PREEMPT_ACTIVE		0x10000000
+
+/*
+ * macros/functions for gaining access to the thread information structure
+ *
+ * preempt_count needs to be 1 initially, until the scheduler is functional.
+ */
+
+#ifndef __ASSEMBLY__
+
+#define INIT_THREAD_INFO(tsk)			\
+{						\
+	.task		= &tsk,			\
+	.exec_domain	= &default_exec_domain,	\
+	.flags		= 0,			\
+	.cpu		= 0,			\
+	.preempt_count	= 1,			\
+	.addr_limit	= KERNEL_DS,		\
+	.restart_block = {			\
+		.fn = do_no_restart_syscall,	\
+	},					\
+}
+
+#define init_thread_info	(init_thread_union.thread_info)
+#define init_stack		(init_thread_union.stack)
+
+/* how to get the thread information struct from C */
+static inline struct thread_info *current_thread_info(void)
+{
+	struct thread_info *ti;
+	 __asm__("extui %0,a1,0,13\n\t"
+	         "xor %0, a1, %0" : "=&r" (ti) : );
+	return ti;
+}
+
+/* thread information allocation */
+#define alloc_thread_info(tsk) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
+#define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
+#define get_thread_info(ti) get_task_struct((ti)->task)
+#define put_thread_info(ti) put_task_struct((ti)->task)
+
+#else /* !__ASSEMBLY__ */
+
+/* how to get the thread information struct from ASM */
+#define GET_THREAD_INFO(reg,sp) \
+	extui reg, sp, 0, 13; \
+	xor   reg, sp, reg
+#endif
+
+
+/*
+ * thread information flags
+ * - these are process state flags that various assembly files may need to access
+ * - pending work-to-be-done flags are in LSW
+ * - other flags in MSW
+ */
+#define TIF_SYSCALL_TRACE	0	/* syscall trace active */
+#define TIF_NOTIFY_RESUME	1	/* resumption notification requested */
+#define TIF_SIGPENDING		2	/* signal pending */
+#define TIF_NEED_RESCHED	3	/* rescheduling necessary */
+#define TIF_SINGLESTEP		4	/* restore singlestep on return to user mode */
+#define TIF_IRET		5	/* return with iret */
+#define TIF_MEMDIE		6
+#define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
+
+#define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING		(1<<TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
+#define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
+#define _TIF_IRET		(1<<TIF_IRET)
+#define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
+
+#define _TIF_WORK_MASK		0x0000FFFE	/* work to do on interrupt/exception return */
+#define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
+
+/*
+ * Thread-synchronous status.
+ *
+ * This is different from the flags in that nobody else
+ * ever touches our thread-synchronous status, so we don't
+ * have to worry about atomic accesses.
+ */
+#define TS_USEDFPU		0x0001	/* FPU was used by this task this quantum (SMP) */
+
+#define THREAD_SIZE 8192	//(2*PAGE_SIZE)
+
+#endif	/* __KERNEL__ */
+#endif	/* _XTENSA_THREAD_INFO */
diff --git a/include/asm-xtensa/timex.h b/include/asm-xtensa/timex.h
new file mode 100644
index 0000000..d14a375
--- /dev/null
+++ b/include/asm-xtensa/timex.h
@@ -0,0 +1,94 @@
+/*
+ * include/asm-xtensa/timex.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_TIMEX_H
+#define _XTENSA_TIMEX_H
+
+#ifdef __KERNEL__
+
+#include <asm/processor.h>
+#include <linux/stringify.h>
+
+#if XCHAL_INT_LEVEL(XCHAL_TIMER0_INTERRUPT) == 1
+# define LINUX_TIMER     0
+#elif XCHAL_INT_LEVEL(XCHAL_TIMER1_INTERRUPT) == 1
+# define LINUX_TIMER     1
+#elif XCHAL_INT_LEVEL(XCHAL_TIMER2_INTERRUPT) == 1
+# define LINUX_TIMER     2
+#else
+# error "Bad timer number for Linux configurations!"
+#endif
+
+#define LINUX_TIMER_INT         XCHAL_TIMER_INTERRUPT(LINUX_TIMER)
+#define LINUX_TIMER_MASK        (1L << LINUX_TIMER_INT)
+
+#define CLOCK_TICK_RATE 	1193180	/* (everyone is using this value) */
+#define CLOCK_TICK_FACTOR       20 /* Factor of both 10^6 and CLOCK_TICK_RATE */
+#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
+	(1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \
+		<< (SHIFT_SCALE-SHIFT_HZ)) / HZ)
+
+#ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT
+extern unsigned long ccount_per_jiffy;
+extern unsigned long ccount_nsec;
+#define CCOUNT_PER_JIFFY ccount_per_jiffy
+#define CCOUNT_NSEC ccount_nsec
+#else
+#define CCOUNT_PER_JIFFY (CONFIG_XTENSA_CPU_CLOCK*(1000000UL/HZ))
+#define CCOUNT_NSEC (1000000000UL / CONFIG_XTENSA_CPU_CLOCK)
+#endif
+
+
+typedef unsigned long long cycles_t;
+
+/*
+ * Only used for SMP.
+ */
+
+extern cycles_t cacheflush_time;
+
+#define get_cycles()	(0)
+
+
+/*
+ * Register access.
+ */
+
+#define WSR_CCOUNT(r)	  __asm__("wsr %0,"__stringify(CCOUNT) :: "a" (r))
+#define RSR_CCOUNT(r)	  __asm__("rsr %0,"__stringify(CCOUNT) : "=a" (r))
+#define WSR_CCOMPARE(x,r) __asm__("wsr %0,"__stringify(CCOMPARE_0)"+"__stringify(x) :: "a"(r))
+#define RSR_CCOMPARE(x,r) __asm__("rsr %0,"__stringify(CCOMPARE_0)"+"__stringify(x) : "=a"(r))
+
+static inline unsigned long get_ccount (void)
+{
+	unsigned long ccount;
+	RSR_CCOUNT(ccount);
+	return ccount;
+}
+
+static inline void set_ccount (unsigned long ccount)
+{
+	WSR_CCOUNT(ccount);
+}
+
+static inline unsigned long get_linux_timer (void)
+{
+	unsigned ccompare;
+	RSR_CCOMPARE(LINUX_TIMER, ccompare);
+	return ccompare;
+}
+
+static inline void set_linux_timer (unsigned long ccompare)
+{
+	WSR_CCOMPARE(LINUX_TIMER, ccompare);
+}
+
+#endif	/* __KERNEL__ */
+#endif	/* _XTENSA_TIMEX_H */
diff --git a/include/asm-xtensa/tlb.h b/include/asm-xtensa/tlb.h
new file mode 100644
index 0000000..4562b2d
--- /dev/null
+++ b/include/asm-xtensa/tlb.h
@@ -0,0 +1,25 @@
+/*
+ * include/asm-xtensa/tlb.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_TLB_H
+#define _XTENSA_TLB_H
+
+#define tlb_start_vma(tlb,vma)			do { } while (0)
+#define tlb_end_vma(tlb,vma)			do { } while (0)
+#define __tlb_remove_tlb_entry(tlb,pte,addr)	do { } while (0)
+
+#define tlb_flush(tlb)				flush_tlb_mm((tlb)->mm)
+
+#include <asm-generic/tlb.h>
+#include <asm/page.h>
+
+#define __pte_free_tlb(tlb,pte)			pte_free(pte)
+
+#endif	/* _XTENSA_TLB_H */
diff --git a/include/asm-xtensa/tlbflush.h b/include/asm-xtensa/tlbflush.h
new file mode 100644
index 0000000..23bfe9d
--- /dev/null
+++ b/include/asm-xtensa/tlbflush.h
@@ -0,0 +1,200 @@
+/*
+ * include/asm-xtensa/tlbflush.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_TLBFLUSH_H
+#define _XTENSA_TLBFLUSH_H
+
+#define DEBUG_TLB
+
+#ifdef __KERNEL__
+
+#include <asm/processor.h>
+#include <linux/stringify.h>
+
+/* TLB flushing:
+ *
+ *  - flush_tlb_all() flushes all processes TLB entries
+ *  - flush_tlb_mm(mm) flushes the specified mm context TLB entries
+ *  - flush_tlb_page(mm, vmaddr) flushes a single page
+ *  - flush_tlb_range(mm, start, end) flushes a range of pages
+ */
+
+extern void flush_tlb_all(void);
+extern void flush_tlb_mm(struct mm_struct*);
+extern void flush_tlb_page(struct vm_area_struct*,unsigned long);
+extern void flush_tlb_range(struct vm_area_struct*,unsigned long,unsigned long);
+
+#define flush_tlb_kernel_range(start,end) flush_tlb_all()
+
+
+/* This is calld in munmap when we have freed up some page-table pages.
+ * We don't need to do anything here, there's nothing special about our
+ * page-table pages.
+ */
+
+extern inline void flush_tlb_pgtables(struct mm_struct *mm,
+                                      unsigned long start, unsigned long end)
+{
+}
+
+/* TLB operations. */
+
+#define ITLB_WAYS_LOG2      XCHAL_ITLB_WAY_BITS
+#define DTLB_WAYS_LOG2      XCHAL_DTLB_WAY_BITS
+#define ITLB_PROBE_SUCCESS  (1 << ITLB_WAYS_LOG2)
+#define DTLB_PROBE_SUCCESS  (1 << DTLB_WAYS_LOG2)
+
+extern inline unsigned long itlb_probe(unsigned long addr)
+{
+	unsigned long tmp;
+	__asm__ __volatile__("pitlb  %0, %1\n\t" : "=a" (tmp) : "a" (addr));
+	return tmp;
+}
+
+extern inline unsigned long dtlb_probe(unsigned long addr)
+{
+	unsigned long tmp;
+	__asm__ __volatile__("pdtlb  %0, %1\n\t" : "=a" (tmp) : "a" (addr));
+	return tmp;
+}
+
+extern inline void invalidate_itlb_entry (unsigned long probe)
+{
+	__asm__ __volatile__("iitlb  %0; isync\n\t" : : "a" (probe));
+}
+
+extern inline void invalidate_dtlb_entry (unsigned long probe)
+{
+	__asm__ __volatile__("idtlb  %0; dsync\n\t" : : "a" (probe));
+}
+
+/* Use the .._no_isync functions with caution.  Generally, these are
+ * handy for bulk invalidates followed by a single 'isync'.  The
+ * caller must follow up with an 'isync', which can be relatively
+ * expensive on some Xtensa implementations.
+ */
+extern inline void invalidate_itlb_entry_no_isync (unsigned entry)
+{
+	/* Caller must follow up with 'isync'. */
+	__asm__ __volatile__ ("iitlb  %0\n" : : "a" (entry) );
+}
+
+extern inline void invalidate_dtlb_entry_no_isync (unsigned entry)
+{
+	/* Caller must follow up with 'isync'. */
+	__asm__ __volatile__ ("idtlb  %0\n" : : "a" (entry) );
+}
+
+extern inline void set_itlbcfg_register (unsigned long val)
+{
+	__asm__ __volatile__("wsr  %0, "__stringify(ITLBCFG)"\n\t" "isync\n\t"
+			     : : "a" (val));
+}
+
+extern inline void set_dtlbcfg_register (unsigned long val)
+{
+	__asm__ __volatile__("wsr  %0, "__stringify(DTLBCFG)"; dsync\n\t"
+	    		     : : "a" (val));
+}
+
+extern inline void set_ptevaddr_register (unsigned long val)
+{
+	__asm__ __volatile__(" wsr  %0, "__stringify(PTEVADDR)"; isync\n"
+			     : : "a" (val));
+}
+
+extern inline unsigned long read_ptevaddr_register (void)
+{
+	unsigned long tmp;
+	__asm__ __volatile__("rsr  %0, "__stringify(PTEVADDR)"\n\t" : "=a" (tmp));
+	return tmp;
+}
+
+extern inline void write_dtlb_entry (pte_t entry, int way)
+{
+	__asm__ __volatile__("wdtlb  %1, %0; dsync\n\t"
+			     : : "r" (way), "r" (entry) );
+}
+
+extern inline void write_itlb_entry (pte_t entry, int way)
+{
+	__asm__ __volatile__("witlb  %1, %0; isync\n\t"
+	                     : : "r" (way), "r" (entry) );
+}
+
+extern inline void invalidate_page_directory (void)
+{
+	invalidate_dtlb_entry (DTLB_WAY_PGTABLE);
+}
+
+extern inline void invalidate_itlb_mapping (unsigned address)
+{
+	unsigned long tlb_entry;
+	while ((tlb_entry = itlb_probe (address)) & ITLB_PROBE_SUCCESS)
+		invalidate_itlb_entry (tlb_entry);
+}
+
+extern inline void invalidate_dtlb_mapping (unsigned address)
+{
+	unsigned long tlb_entry;
+	while ((tlb_entry = dtlb_probe (address)) & DTLB_PROBE_SUCCESS)
+		invalidate_dtlb_entry (tlb_entry);
+}
+
+#define check_pgt_cache()	do { } while (0)
+
+
+#ifdef DEBUG_TLB
+
+/* DO NOT USE THESE FUNCTIONS.  These instructions aren't part of the Xtensa
+ * ISA and exist only for test purposes..
+ * You may find it helpful for MMU debugging, however.
+ *
+ * 'at' is the unmodified input register
+ * 'as' is the output register, as follows (specific to the Linux config):
+ *
+ *      as[31..12] contain the virtual address
+ *      as[11..08] are meaningless
+ *      as[07..00] contain the asid
+ */
+
+extern inline unsigned long read_dtlb_virtual (int way)
+{
+	unsigned long tmp;
+	__asm__ __volatile__("rdtlb0  %0, %1\n\t" : "=a" (tmp), "+a" (way));
+	return tmp;
+}
+
+extern inline unsigned long read_dtlb_translation (int way)
+{
+	unsigned long tmp;
+	__asm__ __volatile__("rdtlb1  %0, %1\n\t" : "=a" (tmp), "+a" (way));
+	return tmp;
+}
+
+extern inline unsigned long read_itlb_virtual (int way)
+{
+	unsigned long tmp;
+	__asm__ __volatile__("ritlb0  %0, %1\n\t" : "=a" (tmp), "+a" (way));
+	return tmp;
+}
+
+extern inline unsigned long read_itlb_translation (int way)
+{
+	unsigned long tmp;
+	__asm__ __volatile__("ritlb1  %0, %1\n\t" : "=a" (tmp), "+a" (way));
+	return tmp;
+}
+
+#endif	/* DEBUG_TLB */
+
+
+#endif	/* __KERNEL__ */
+#endif	/* _XTENSA_PGALLOC_H */
diff --git a/include/asm-xtensa/topology.h b/include/asm-xtensa/topology.h
new file mode 100644
index 0000000..7309e38
--- /dev/null
+++ b/include/asm-xtensa/topology.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/topology.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_TOPOLOGY_H
+#define _XTENSA_TOPOLOGY_H
+
+#include <asm-generic/topology.h>
+
+#endif	/* _XTENSA_TOPOLOGY_H */
diff --git a/include/asm-xtensa/types.h b/include/asm-xtensa/types.h
new file mode 100644
index 0000000..ebac004
--- /dev/null
+++ b/include/asm-xtensa/types.h
@@ -0,0 +1,66 @@
+/*
+ * include/asm-xtensa/types.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_TYPES_H
+#define _XTENSA_TYPES_H
+
+#ifndef __ASSEMBLY__
+
+typedef unsigned short umode_t;
+
+/*
+ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+ * header files exported to user space
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+#endif
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+#ifdef __KERNEL__
+
+typedef __signed__ char s8;
+typedef unsigned char u8;
+
+typedef __signed__ short s16;
+typedef unsigned short u16;
+
+typedef __signed__ int s32;
+typedef unsigned int u32;
+
+typedef __signed__ long long s64;
+typedef unsigned long long u64;
+
+
+#define BITS_PER_LONG 32
+
+/* Dma addresses are 32-bits wide.  */
+
+typedef u32 dma_addr_t;
+
+typedef unsigned int kmem_bufctl_t;
+
+#endif	/* __KERNEL__ */
+#endif
+
+#endif	/* _XTENSA_TYPES_H */
diff --git a/include/asm-xtensa/uaccess.h b/include/asm-xtensa/uaccess.h
new file mode 100644
index 0000000..35576b2
--- /dev/null
+++ b/include/asm-xtensa/uaccess.h
@@ -0,0 +1,532 @@
+/*
+ * include/asm-xtensa/uaccess.h
+ *
+ * User space memory access functions
+ *
+ * These routines provide basic accessing functions to the user memory
+ * space for the kernel. This header file provides fuctions such as:
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_UACCESS_H
+#define _XTENSA_UACCESS_H
+
+#include <linux/errno.h>
+
+#define VERIFY_READ    0
+#define VERIFY_WRITE   1
+
+#ifdef __ASSEMBLY__
+
+#define _ASMLANGUAGE
+#include <asm/current.h>
+#include <asm/offsets.h>
+#include <asm/processor.h>
+
+/*
+ * These assembly macros mirror the C macros that follow below.  They
+ * should always have identical functionality.  See
+ * arch/xtensa/kernel/sys.S for usage.
+ */
+
+#define KERNEL_DS	0
+#define USER_DS		1
+
+#define get_ds		(KERNEL_DS)
+
+/*
+ * get_fs reads current->thread.current_ds into a register.
+ * On Entry:
+ * 	<ad>	anything
+ * 	<sp>	stack
+ * On Exit:
+ * 	<ad>	contains current->thread.current_ds
+ */
+	.macro	get_fs	ad, sp
+	GET_CURRENT(\ad,\sp)
+	l32i	\ad, \ad, THREAD_CURRENT_DS
+	.endm
+
+/*
+ * set_fs sets current->thread.current_ds to some value.
+ * On Entry:
+ *	<at>	anything (temp register)
+ *	<av>	value to write
+ *	<sp>	stack
+ * On Exit:
+ *	<at>	destroyed (actually, current)
+ *	<av>	preserved, value to write
+ */
+	.macro	set_fs	at, av, sp
+	GET_CURRENT(\at,\sp)
+	s32i	\av, \at, THREAD_CURRENT_DS
+	.endm
+
+/*
+ * kernel_ok determines whether we should bypass addr/size checking.
+ * See the equivalent C-macro version below for clarity.
+ * On success, kernel_ok branches to a label indicated by parameter
+ * <success>.  This implies that the macro falls through to the next
+ * insruction on an error.
+ *
+ * Note that while this macro can be used independently, we designed
+ * in for optimal use in the access_ok macro below (i.e., we fall
+ * through on error).
+ *
+ * On Entry:
+ * 	<at>		anything (temp register)
+ * 	<success>	label to branch to on success; implies
+ * 			fall-through macro on error
+ * 	<sp>		stack pointer
+ * On Exit:
+ * 	<at>		destroyed (actually, current->thread.current_ds)
+ */
+
+#if ((KERNEL_DS != 0) || (USER_DS == 0))
+# error Assembly macro kernel_ok fails
+#endif
+	.macro	kernel_ok  at, sp, success
+	get_fs	\at, \sp
+	beqz	\at, \success
+	.endm
+
+/*
+ * user_ok determines whether the access to user-space memory is allowed.
+ * See the equivalent C-macro version below for clarity.
+ *
+ * On error, user_ok branches to a label indicated by parameter
+ * <error>.  This implies that the macro falls through to the next
+ * instruction on success.
+ *
+ * Note that while this macro can be used independently, we designed
+ * in for optimal use in the access_ok macro below (i.e., we fall
+ * through 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 (actually, (TASK_SIZE + 1 - size))
+ */
+	.macro	user_ok	aa, as, at, error
+	movi	\at, (TASK_SIZE+1)
+	bgeu	\as, \at, \error
+	sub	\at, \at, \as
+	bgeu	\aa, \at, \error
+	.endm
+
+/*
+ * access_ok determines whether a memory access is allowed.  See the
+ * equivalent C-macro version below for clarity.
+ *
+ * On error, access_ok 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
+ * 	<sp>
+ * 	<error>	label to branch to on error; implies fall-through
+ * 		macro on success
+ * On Exit:
+ * 	<aa>	preserved
+ * 	<as>	preserved
+ * 	<at>	destroyed
+ */
+	.macro	access_ok  aa, as, at, sp, error
+	kernel_ok  \at, \sp, .Laccess_ok_\@
+	user_ok    \aa, \as, \at, \error
+.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>
+#include <asm/types.h>
+
+/*
+ * The fs value determines whether argument validity checking should
+ * be performed or not.  If get_fs() == USER_DS, checking is
+ * performed, with get_fs() == KERNEL_DS, checking is bypassed.
+ *
+ * For historical reasons (Data Segment Register?), these macros are
+ * grossly misnamed.
+ */
+
+#define KERNEL_DS	((mm_segment_t) { 0 })
+#define USER_DS		((mm_segment_t) { 1 })
+
+#define get_ds()	(KERNEL_DS)
+#define get_fs()	(current->thread.current_ds)
+#define set_fs(val)	(current->thread.current_ds = (val))
+
+#define segment_eq(a,b)	((a).seg == (b).seg)
+
+#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
+#define __user_ok(addr,size) (((size) <= TASK_SIZE)&&((addr) <= TASK_SIZE-(size)))
+#define __access_ok(addr,size) (__kernel_ok || __user_ok((addr),(size)))
+#define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size))
+
+extern 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
+ * type.
+ *
+ * This gets kind of ugly. We want to return _two_ values in
+ * "get_user()" and yet we don't want to do any pointers, because that
+ * is too much of a performance impact. Thus we have a few rather ugly
+ * macros here, and hide all the uglyness from the user.
+ *
+ * Careful to not
+ * (a) re-use the arguments for side effects (sizeof is ok)
+ * (b) require any knowledge of processes at this stage
+ */
+#define put_user(x,ptr)	__put_user_check((x),(ptr),sizeof(*(ptr)))
+#define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr)))
+
+/*
+ * The "__xxx" versions of the user access functions are versions that
+ * do not verify the address space, that must have been done previously
+ * with a separate "access_ok()" call (this is used when we do multiple
+ * accesses to the same area of user memory).
+ */
+#define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr)))
+#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+
+
+extern long __put_user_bad(void);
+
+#define __put_user_nocheck(x,ptr,size)			\
+({							\
+	long __pu_err;					\
+	__put_user_size((x),(ptr),(size),__pu_err);	\
+	__pu_err;					\
+})
+
+#define __put_user_check(x,ptr,size)				\
+({								\
+	long __pu_err = -EFAULT;				\
+	__typeof__(*(ptr)) *__pu_addr = (ptr);			\
+	if (access_ok(VERIFY_WRITE,__pu_addr,size))		\
+		__put_user_size((x),__pu_addr,(size),__pu_err);	\
+	__pu_err;						\
+})
+
+#define __put_user_size(x,ptr,size,retval)			\
+do {								\
+	retval = 0;						\
+	switch (size) {						\
+        case 1: __put_user_asm(x,ptr,retval,1,"s8i");  break;	\
+        case 2: __put_user_asm(x,ptr,retval,2,"s16i"); break;   \
+        case 4: __put_user_asm(x,ptr,retval,4,"s32i"); break;   \
+        case 8: {						\
+		     __typeof__(*ptr) __v64 = x;		\
+		     retval = __copy_to_user(ptr,&__v64,8);	\
+		     break;					\
+	        }						\
+	default: __put_user_bad();				\
+	}							\
+} while (0)
+
+
+/*
+ * Consider a case of a user single load/store would cause both an
+ * unaligned exception and an MMU-related exception (unaligned
+ * exceptions happen first):
+ *
+ * User code passes a bad variable ptr to a system call.
+ * Kernel tries to access the variable.
+ * Unaligned exception occurs.
+ * Unaligned exception handler tries to make aligned accesses.
+ * Double exception occurs for MMU-related cause (e.g., page not mapped).
+ * do_page_fault() thinks the fault address belongs to the kernel, not the
+ * user, and panics.
+ *
+ * The kernel currently prohibits user unaligned accesses.  We use the
+ * __check_align_* macros to check for unaligned addresses before
+ * accessing user space so we don't crash the kernel.  Both
+ * __put_user_asm and __get_user_asm use these alignment macros, so
+ * macro-specific labels such as 0f, 1f, %0, %2, and %3 must stay in
+ * sync.
+ */
+
+#define __check_align_1  ""
+
+#define __check_align_2				\
+	"   _bbci.l %2,  0, 1f		\n"	\
+	"   movi    %0, %3		\n"	\
+	"   _j      2f			\n"
+
+#define __check_align_4				\
+	"   _bbsi.l %2,  0, 0f		\n"	\
+	"   _bbci.l %2,  1, 1f		\n"	\
+	"0: movi    %0, %3		\n"	\
+	"   _j      2f			\n"
+
+
+/*
+ * We don't tell gcc that we are accessing memory, but this is OK
+ * because we do not write to any memory gcc knows about, so there
+ * are no aliasing issues.
+ *
+ * WARNING: If you modify this macro at all, verify that the
+ * __check_align_* macros still work.
+ */
+#define __put_user_asm(x, addr, err, align, insn) \
+   __asm__ __volatile__(			\
+	__check_align_##align			\
+	"1: "insn"  %1, %2, 0		\n"	\
+	"2:				\n"	\
+	"   .section  .fixup,\"ax\"	\n"	\
+	"   .align 4			\n"	\
+	"4:				\n"	\
+	"   .long  2b			\n"	\
+	"5:				\n"	\
+	"   l32r   %2, 4b		\n"	\
+        "   movi   %0, %3		\n"	\
+        "   jx     %2			\n"	\
+	"   .previous			\n"	\
+	"   .section  __ex_table,\"a\"	\n"	\
+	"   .long	1b, 5b		\n"	\
+	"   .previous"				\
+	:"=r" (err)				\
+	:"r" ((int)(x)), "r" (addr), "i" (-EFAULT), "0" (err))
+
+#define __get_user_nocheck(x,ptr,size)				\
+({								\
+	long __gu_err, __gu_val;				\
+	__get_user_size(__gu_val,(ptr),(size),__gu_err);	\
+	(x) = (__typeof__(*(ptr)))__gu_val;			\
+	__gu_err;						\
+})
+
+#define __get_user_check(x,ptr,size)					\
+({									\
+	long __gu_err = -EFAULT, __gu_val = 0;				\
+	const __typeof__(*(ptr)) *__gu_addr = (ptr);			\
+	if (access_ok(VERIFY_READ,__gu_addr,size))			\
+		__get_user_size(__gu_val,__gu_addr,(size),__gu_err);	\
+	(x) = (__typeof__(*(ptr)))__gu_val;				\
+	__gu_err;							\
+})
+
+extern long __get_user_bad(void);
+
+#define __get_user_size(x,ptr,size,retval)				\
+do {									\
+	retval = 0;							\
+        switch (size) {							\
+          case 1: __get_user_asm(x,ptr,retval,1,"l8ui");  break;	\
+          case 2: __get_user_asm(x,ptr,retval,2,"l16ui"); break;	\
+          case 4: __get_user_asm(x,ptr,retval,4,"l32i");  break;	\
+          case 8: retval = __copy_from_user(&x,ptr,8);    break;	\
+          default: (x) = __get_user_bad();				\
+        }								\
+} while (0)
+
+
+/*
+ * WARNING: If you modify this macro at all, verify that the
+ * __check_align_* macros still work.
+ */
+#define __get_user_asm(x, addr, err, align, insn) \
+   __asm__ __volatile__(			\
+	__check_align_##align			\
+	"1: "insn"  %1, %2, 0		\n"	\
+	"2:				\n"	\
+	"   .section  .fixup,\"ax\"	\n"	\
+	"   .align 4			\n"	\
+	"4:				\n"	\
+	"   .long  2b			\n"	\
+	"5:				\n"	\
+	"   l32r   %2, 4b		\n"	\
+	"   movi   %1, 0		\n"	\
+        "   movi   %0, %3		\n"	\
+        "   jx     %2			\n"	\
+	"   .previous			\n"	\
+	"   .section  __ex_table,\"a\"	\n"	\
+	"   .long	1b, 5b		\n"	\
+	"   .previous"				\
+	:"=r" (err), "=r" (x)			\
+	:"r" (addr), "i" (-EFAULT), "0" (err))
+
+
+/*
+ * Copy to/from user space
+ */
+
+/*
+ * We use a generic, arbitrary-sized copy subroutine.  The Xtensa
+ * architecture would cause heavy code bloat if we tried to inline
+ * these functions and provide __constant_copy_* equivalents like the
+ * i386 versions.  __xtensa_copy_user is quite efficient.  See the
+ * .fixup section of __xtensa_copy_user for a discussion on the
+ * X_zeroing equivalents for Xtensa.
+ */
+
+extern unsigned __xtensa_copy_user(void *to, const void *from, unsigned n);
+#define __copy_user(to,from,size) __xtensa_copy_user(to,from,size)
+
+
+static inline unsigned long
+__generic_copy_from_user_nocheck(void *to, const void *from, unsigned long n)
+{
+	return __copy_user(to,from,n);
+}
+
+static inline unsigned long
+__generic_copy_to_user_nocheck(void *to, const void *from, unsigned long n)
+{
+	return __copy_user(to,from,n);
+}
+
+static inline unsigned long
+__generic_copy_to_user(void *to, const void *from, unsigned long n)
+{
+	prefetch(from);
+	if (access_ok(VERIFY_WRITE, to, n))
+		return __copy_user(to,from,n);
+	return n;
+}
+
+static inline unsigned long
+__generic_copy_from_user(void *to, const void *from, unsigned long n)
+{
+	prefetchw(to);
+	if (access_ok(VERIFY_READ, from, n))
+		return __copy_user(to,from,n);
+	else
+		memset(to, 0, n);
+	return n;
+}
+
+#define copy_to_user(to,from,n) __generic_copy_to_user((to),(from),(n))
+#define copy_from_user(to,from,n) __generic_copy_from_user((to),(from),(n))
+#define __copy_to_user(to,from,n) __generic_copy_to_user_nocheck((to),(from),(n))
+#define __copy_from_user(to,from,n) __generic_copy_from_user_nocheck((to),(from),(n))
+#define __copy_to_user_inatomic __copy_to_user
+#define __copy_from_user_inatomic __copy_from_user
+
+
+/*
+ * We need to return the number of bytes not cleared.  Our memset()
+ * returns zero if a problem occurs while accessing user-space memory.
+ * In that event, return no memory cleared.  Otherwise, zero for
+ * success.
+ */
+
+extern inline unsigned long
+__xtensa_clear_user(void *addr, unsigned long size)
+{
+	if ( ! memset(addr, 0, size) )
+		return size;
+	return 0;
+}
+
+extern inline unsigned long
+clear_user(void *addr, unsigned long size)
+{
+	if (access_ok(VERIFY_WRITE, addr, size))
+		return __xtensa_clear_user(addr, size);
+	return size ? -EFAULT : 0;
+}
+
+#define __clear_user  __xtensa_clear_user
+
+
+extern long __strncpy_user(char *, const char *, long);
+#define __strncpy_from_user __strncpy_user
+
+extern inline long
+strncpy_from_user(char *dst, const char *src, long count)
+{
+	if (access_ok(VERIFY_READ, src, 1))
+		return __strncpy_from_user(dst, src, count);
+	return -EFAULT;
+}
+
+
+#define strlen_user(str) strnlen_user((str), TASK_SIZE - 1)
+
+/*
+ * Return the size of a string (including the ending 0!)
+ */
+extern long __strnlen_user(const char *, long);
+
+extern inline long strnlen_user(const char *str, long len)
+{
+	unsigned long top = __kernel_ok ? ~0UL : TASK_SIZE - 1;
+
+	if ((unsigned long)str > top)
+		return 0;
+	return __strnlen_user(str, len);
+}
+
+
+struct exception_table_entry
+{
+	unsigned long insn, fixup;
+};
+
+/* Returns 0 if exception not found and fixup.unit otherwise.  */
+
+extern unsigned long search_exception_table(unsigned long addr);
+extern void sort_exception_table(void);
+
+/* Returns the new pc */
+#define fixup_exception(map_reg, fixup_unit, pc)                \
+({                                                              \
+	fixup_unit;                                             \
+})
+
+#endif	/* __ASSEMBLY__ */
+#endif	/* _XTENSA_UACCESS_H */
diff --git a/include/asm-xtensa/ucontext.h b/include/asm-xtensa/ucontext.h
new file mode 100644
index 0000000..94c94ed
--- /dev/null
+++ b/include/asm-xtensa/ucontext.h
@@ -0,0 +1,22 @@
+/*
+ * include/asm-xtensa/ucontext.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_UCONTEXT_H
+#define _XTENSA_UCONTEXT_H
+
+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 */
+};
+
+#endif /* _XTENSA_UCONTEXT_H */
diff --git a/include/asm-xtensa/unaligned.h b/include/asm-xtensa/unaligned.h
new file mode 100644
index 0000000..2822089
--- /dev/null
+++ b/include/asm-xtensa/unaligned.h
@@ -0,0 +1,28 @@
+/*
+ * include/asm-xtensa/unaligned.h
+ *
+ * Xtensa doesn't handle unaligned accesses efficiently.
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_UNALIGNED_H
+#define _XTENSA_UNALIGNED_H
+
+#include <linux/string.h>
+
+/* Use memmove here, so gcc does not insert a __builtin_memcpy. */
+
+#define get_unaligned(ptr) \
+  ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; })
+
+#define put_unaligned(val, ptr)				\
+  ({ __typeof__(*(ptr)) __tmp = (val);			\
+     memmove((ptr), &__tmp, sizeof(*(ptr)));		\
+     (void)0; })
+
+#endif	/* _XTENSA_UNALIGNED_H */
diff --git a/include/asm-xtensa/unistd.h b/include/asm-xtensa/unistd.h
new file mode 100644
index 0000000..64c64dd
--- /dev/null
+++ b/include/asm-xtensa/unistd.h
@@ -0,0 +1,537 @@
+/*
+ * include/asm-xtensa/unistd.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_UNISTD_H
+#define _XTENSA_UNISTD_H
+
+#include <linux/linkage.h>
+
+//#define __NR_setup		  0 /* used only by init, to get system going */
+#define __NR_spill		  0
+#define __NR_exit		  1
+#define __NR_fork		  2
+#define __NR_read		  3
+#define __NR_write		  4
+#define __NR_open		  5
+#define __NR_close		  6
+#define __NR_waitpid		  7
+#define __NR_creat		  8
+#define __NR_link		  9
+#define __NR_unlink		 10
+#define __NR_execve		 11
+#define __NR_chdir		 12
+#define __NR_time		 13
+#define __NR_mknod		 14
+#define __NR_chmod		 15
+#define __NR_lchown		 16
+#define __NR_break		 17
+#define __NR_oldstat		 18
+#define __NR_lseek		 19
+#define __NR_getpid		 20
+#define __NR_mount		 21
+#define __NR_oldumount		 22
+#define __NR_setuid		 23
+#define __NR_getuid		 24
+#define __NR_stime		 25
+#define __NR_ptrace		 26
+#define __NR_alarm		 27
+#define __NR_oldfstat		 28
+#define __NR_pause		 29
+#define __NR_utime		 30
+#define __NR_stty		 31
+#define __NR_gtty		 32
+#define __NR_access		 33
+#define __NR_nice		 34
+#define __NR_ftime		 35
+#define __NR_sync		 36
+#define __NR_kill		 37
+#define __NR_rename		 38
+#define __NR_mkdir		 39
+#define __NR_rmdir		 40
+#define __NR_dup		 41
+#define __NR_pipe		 42
+#define __NR_times		 43
+#define __NR_prof		 44
+#define __NR_brk		 45
+#define __NR_setgid		 46
+#define __NR_getgid		 47
+#define __NR_signal		 48
+#define __NR_geteuid		 49
+#define __NR_getegid		 50
+#define __NR_acct		 51
+#define __NR_umount		 52
+#define __NR_lock		 53
+#define __NR_ioctl		 54
+#define __NR_fcntl		 55
+#define __NR_mpx		 56
+#define __NR_setpgid		 57
+#define __NR_ulimit		 58
+#define __NR_oldolduname	 59
+#define __NR_umask		 60
+#define __NR_chroot		 61
+#define __NR_ustat		 62
+#define __NR_dup2		 63
+#define __NR_getppid		 64
+#define __NR_getpgrp		 65
+#define __NR_setsid		 66
+#define __NR_sigaction		 67
+#define __NR_sgetmask		 68
+#define __NR_ssetmask		 69
+#define __NR_setreuid		 70
+#define __NR_setregid		 71
+#define __NR_sigsuspend		 72
+#define __NR_sigpending		 73
+#define __NR_sethostname	 74
+#define __NR_setrlimit		 75
+#define __NR_getrlimit	 	 76	/* Back compatible 2Gig limited rlimit */
+#define __NR_getrusage		 77
+#define __NR_gettimeofday	 78
+#define __NR_settimeofday	 79
+#define __NR_getgroups		 80
+#define __NR_setgroups		 81
+#define __NR_select		 82
+#define __NR_symlink		 83
+#define __NR_oldlstat		 84
+#define __NR_readlink		 85
+#define __NR_uselib		 86
+#define __NR_swapon		 87
+#define __NR_reboot		 88
+#define __NR_readdir		 89
+#define __NR_mmap		 90
+#define __NR_munmap		 91
+#define __NR_truncate		 92
+#define __NR_ftruncate		 93
+#define __NR_fchmod		 94
+#define __NR_fchown		 95
+#define __NR_getpriority	 96
+#define __NR_setpriority	 97
+#define __NR_profil		 98
+#define __NR_statfs		 99
+#define __NR_fstatfs		100
+#define __NR_ioperm		101
+#define __NR_socketcall		102
+#define __NR_syslog		103
+#define __NR_setitimer		104
+#define __NR_getitimer		105
+#define __NR_stat		106
+#define __NR_lstat		107
+#define __NR_fstat		108
+#define __NR_olduname		109
+#define __NR_iopl		110
+#define __NR_vhangup		111
+#define __NR_idle		112
+#define __NR_vm86		113
+#define __NR_wait4		114
+#define __NR_swapoff		115
+#define __NR_sysinfo		116
+#define __NR_ipc		117
+#define __NR_fsync		118
+#define __NR_sigreturn		119
+#define __NR_clone		120
+#define __NR_setdomainname	121
+#define __NR_uname		122
+#define __NR_modify_ldt		123
+#define __NR_adjtimex		124
+#define __NR_mprotect		125
+#define __NR_sigprocmask	126
+#define __NR_create_module	127
+#define __NR_init_module	128
+#define __NR_delete_module	129
+#define __NR_get_kernel_syms	130
+#define __NR_quotactl		131
+#define __NR_getpgid		132
+#define __NR_fchdir		133
+#define __NR_bdflush		134
+#define __NR_sysfs		135
+#define __NR_personality	136
+#define __NR_afs_syscall	137 /* Syscall for Andrew File System */
+#define __NR_setfsuid		138
+#define __NR_setfsgid		139
+#define __NR__llseek		140
+#define __NR_getdents		141
+#define __NR__newselect		142
+#define __NR_flock		143
+#define __NR_msync		144
+#define __NR_readv		145
+#define __NR_writev		146
+#define __NR_cacheflush         147
+#define __NR_cachectl           148
+#define __NR_sysxtensa          149
+#define __NR_sysdummy           150
+#define __NR_getsid		151
+#define __NR_fdatasync		152
+#define __NR__sysctl		153
+#define __NR_mlock		154
+#define __NR_munlock		155
+#define __NR_mlockall		156
+#define __NR_munlockall		157
+#define __NR_sched_setparam		158
+#define __NR_sched_getparam		159
+#define __NR_sched_setscheduler		160
+#define __NR_sched_getscheduler		161
+#define __NR_sched_yield		162
+#define __NR_sched_get_priority_max	163
+#define __NR_sched_get_priority_min	164
+#define __NR_sched_rr_get_interval	165
+#define __NR_nanosleep		166
+#define __NR_mremap		167
+#define __NR_accept             168
+#define __NR_bind               169
+#define __NR_connect            170
+#define __NR_getpeername        171
+#define __NR_getsockname        172
+#define __NR_getsockopt         173
+#define __NR_listen             174
+#define __NR_recv               175
+#define __NR_recvfrom           176
+#define __NR_recvmsg            177
+#define __NR_send               178
+#define __NR_sendmsg            179
+#define __NR_sendto             180
+#define __NR_setsockopt         181
+#define __NR_shutdown           182
+#define __NR_socket             183
+#define __NR_socketpair         184
+#define __NR_setresuid		185
+#define __NR_getresuid		186
+#define __NR_query_module	187
+#define __NR_poll		188
+#define __NR_nfsservctl		189
+#define __NR_setresgid		190
+#define __NR_getresgid		191
+#define __NR_prctl              192
+#define __NR_rt_sigreturn	193
+#define __NR_rt_sigaction	194
+#define __NR_rt_sigprocmask	195
+#define __NR_rt_sigpending	196
+#define __NR_rt_sigtimedwait	197
+#define __NR_rt_sigqueueinfo	198
+#define __NR_rt_sigsuspend	199
+#define __NR_pread		200
+#define __NR_pwrite		201
+#define __NR_chown		202
+#define __NR_getcwd		203
+#define __NR_capget		204
+#define __NR_capset		205
+#define __NR_sigaltstack	206
+#define __NR_sendfile		207
+#define __NR_streams1		208	/* some people actually want it */
+#define __NR_streams2		209	/* some people actually want it */
+#define __NR_mmap2		210
+#define __NR_truncate64		211
+#define __NR_ftruncate64	212
+#define __NR_stat64		213
+#define __NR_lstat64		214
+#define __NR_fstat64		215
+#define __NR_pivot_root		216
+#define __NR_mincore		217
+#define __NR_madvise		218
+#define __NR_getdents64		219
+#define __NR_vfork		220
+
+/* Keep this last; should always equal the last valid call number. */
+#define __NR_Linux_syscalls     220
+
+/* user-visible error numbers are in the range -1 - -125: see
+ * <asm-xtensa/errno.h> */
+
+#define SYSXTENSA_RESERVED	   0	/* don't use this */
+#define SYSXTENSA_ATOMIC_SET	   1	/* set variable */
+#define SYSXTENSA_ATOMIC_EXG_ADD   2	/* exchange memory and add */
+#define SYSXTENSA_ATOMIC_ADD	   3	/* add to memory */
+#define SYSXTENSA_ATOMIC_CMP_SWP   4	/* compare and swap */
+
+#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
+
+
+/* Tensilica's xt-xcc compiler is much more agressive at code
+ * optimization than gcc.  Multiple __asm__ statements are
+ * insufficient for xt-xcc because subsequent optimization passes
+ * (beyond the front-end that knows of __asm__ statements and other
+ * such GNU Extensions to C) can modify the register selection for
+ * containment of C variables.
+ *
+ * xt-xcc cannot modify the contents of a single __asm__ statement, so
+ * we create single-asm versions of the syscall macros that are
+ * suitable and optimal for both xt-xcc and gcc.
+ *
+ * Linux takes system-call arguments in registers.  The following
+ * design is optimized for user-land apps (e.g., glibc) which
+ * typically have a function wrapper around the "syscall" assembly
+ * instruction.  It satisfies the Xtensa ABI while minizing argument
+ * shifting.
+ *
+ * The Xtensa ABI and software conventions require the system-call
+ * number in a2.  If an argument exists in a2, we move it to the next
+ * available register.  Note that for improved efficiency, we do NOT
+ * shift all parameters down one register to maintain the original
+ * order.
+ *
+ * At best case (zero arguments), we just write the syscall number to
+ * a2.  At worst case (1 to 6 arguments), we move the argument in a2
+ * to the next available register, then write the syscall number to
+ * a2.
+ *
+ * For clarity, the following truth table enumerates all possibilities.
+ *
+ * arguments	syscall number	arg0, arg1, arg2, arg3, arg4, arg5
+ * ---------	--------------	----------------------------------
+ *	0	      a2
+ *	1	      a2	a3
+ *	2	      a2	a4,   a3
+ *	3	      a2	a5,   a3,   a4
+ *	4	      a2	a6,   a3,   a4,   a5
+ *	5	      a2	a7,   a3,   a4,   a5,   a6
+ *	6	      a2	a8,   a3,   a4,   a5,   a6,   a7
+ */
+
+#define _syscall0(type,name) \
+type name(void) \
+{ \
+long __res; \
+__asm__ __volatile__ ( \
+	"  movi  a2, %1 \n" \
+	"  syscall      \n" \
+	"  mov   %0, a2 \n" \
+	: "=a" (__res) \
+	: "i" (__NR_##name) \
+	: "a2" \
+	); \
+__syscall_return(type,__res); \
+}
+
+#define _syscall1(type,name,type0,arg0) \
+type name(type0 arg0) \
+{ \
+long __res; \
+__asm__ __volatile__ ( \
+	"  mov   a3, %2 \n" \
+	"  movi  a2, %1 \n" \
+	"  syscall      \n" \
+	"  mov   %0, a2 \n" \
+	: "=a" (__res) \
+	: "i" (__NR_##name), "a" (arg0) \
+	: "a2", "a3" \
+	); \
+__syscall_return(type,__res); \
+}
+
+#define _syscall2(type,name,type0,arg0,type1,arg1) \
+type name(type0 arg0,type1 arg1) \
+{ \
+long __res; \
+__asm__ __volatile__ ( \
+	"  mov   a4, %2 \n" \
+	"  mov   a3, %3 \n" \
+	"  movi  a2, %1 \n" \
+	"  syscall      \n" \
+	"  mov   %0, a2 \n" \
+	: "=a" (__res) \
+	: "i" (__NR_##name), "a" (arg0), "a" (arg1) \
+	: "a2", "a3", "a4" \
+	); \
+__syscall_return(type,__res); \
+}
+
+#define _syscall3(type,name,type0,arg0,type1,arg1,type2,arg2) \
+type name(type0 arg0,type1 arg1,type2 arg2) \
+{ \
+long __res; \
+__asm__ __volatile__ ( \
+	"  mov   a5, %2 \n" \
+	"  mov   a4, %4 \n" \
+	"  mov   a3, %3 \n" \
+	"  movi  a2, %1 \n" \
+	"  syscall      \n" \
+	"  mov   %0, a2 \n" \
+	: "=a" (__res) \
+	: "i" (__NR_##name), "a" (arg0), "a" (arg1), "a" (arg2) \
+	: "a2", "a3", "a4", "a5" \
+	); \
+__syscall_return(type,__res); \
+}
+
+#define _syscall4(type,name,type0,arg0,type1,arg1,type2,arg2,type3,arg3) \
+type name(type0 arg0,type1 arg1,type2 arg2,type3 arg3) \
+{ \
+long __res; \
+__asm__ __volatile__ ( \
+	"  mov   a6, %2 \n" \
+	"  mov   a5, %5 \n" \
+	"  mov   a4, %4 \n" \
+	"  mov   a3, %3 \n" \
+	"  movi  a2, %1 \n" \
+	"  syscall      \n" \
+	"  mov   %0, a2 \n" \
+	: "=a" (__res) \
+	: "i" (__NR_##name), "a" (arg0), "a" (arg1), "a" (arg2), "a" (arg3) \
+	: "a2", "a3", "a4", "a5", "a6" \
+	); \
+__syscall_return(type,__res); \
+}
+
+/* Note that we save and restore the a7 frame pointer.
+ * Including a7 in the clobber list doesn't do what you'd expect.
+ */
+#define _syscall5(type,name,type0,arg0,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+type name(type0 arg0,type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
+{ \
+long __res; \
+__asm__ __volatile__ ( \
+	"  mov   a9, a7 \n" \
+	"  mov   a7, %2 \n" \
+	"  mov   a6, %6 \n" \
+	"  mov   a5, %5 \n" \
+	"  mov   a4, %4 \n" \
+	"  mov   a3, %3 \n" \
+	"  movi  a2, %1 \n" \
+	"  syscall      \n" \
+	"  mov   a7, a9 \n" \
+	"  mov   %0, a2 \n" \
+	: "=a" (__res) \
+	: "i" (__NR_##name), "a" (arg0), "a" (arg1), "a" (arg2), \
+                             "a" (arg3), "a" (arg4) \
+	: "a2", "a3", "a4", "a5", "a6", "a9" \
+	); \
+__syscall_return(type,__res); \
+}
+
+/* Note that we save and restore the a7 frame pointer.
+ * Including a7 in the clobber list doesn't do what you'd expect.
+ */
+#define _syscall6(type,name,type0,arg0,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
+type name(type0 arg0,type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
+{ \
+long __res; \
+__asm__ __volatile__ ( \
+	"  mov   a9, a7 \n" \
+	"  mov   a8, %2 \n" \
+	"  mov   a7, %7 \n" \
+	"  mov   a6, %6 \n" \
+	"  mov   a5, %5 \n" \
+	"  mov   a4, %4 \n" \
+	"  mov   a3, %3 \n" \
+	"  movi  a2, %1 \n" \
+	"  syscall      \n" \
+	"  mov   a7, a9 \n" \
+	"  mov   %0, a2 \n" \
+	: "=a" (__res) \
+	: "i" (__NR_##name), "a" (arg0), "a" (arg1), "a" (arg2), \
+                             "a" (arg3), "a" (arg4), "a" (arg5)  \
+	: "a2", "a3", "a4", "a5", "a6", "a8", "a9" \
+	); \
+__syscall_return(type,__res); \
+}
+
+
+#ifdef __KERNEL_SYSCALLS__
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <linux/syscalls.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(int,pause)
+//static __inline__ _syscall1(int,setup,int,magic) FIXME
+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)
+
+struct stat;
+static __inline__ _syscall2(int,fstat,int,fd,struct stat *,buf)
+static __inline__ _syscall0(pid_t,getpid)
+static __inline__ _syscall2(int,kill,int,pid,int,sig)
+static __inline__ _syscall2(int,stat,const char *, path,struct stat *,buf)
+static __inline__ _syscall1(int,unlink,char *,pathname)
+
+
+
+extern pid_t waitpid(int, int*, int );
+static __inline__ pid_t wait(int * wait_stat)
+{
+	return waitpid(-1,wait_stat,0);
+}
+#endif
+
+/*
+ * "Conditional" syscalls
+ *
+ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
+ * but it doesn't work on all toolchains, so we just do it by hand
+ */
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+
+#ifdef __KERNEL__
+#define __ARCH_WANT_IPC_PARSE_VERSION
+#define __ARCH_WANT_OLD_READDIR
+#define __ARCH_WANT_OLD_STAT
+#define __ARCH_WANT_STAT64
+#define __ARCH_WANT_SYS_ALARM
+#define __ARCH_WANT_SYS_GETHOSTNAME
+#define __ARCH_WANT_SYS_PAUSE
+#define __ARCH_WANT_SYS_SGETMASK
+#define __ARCH_WANT_SYS_SIGNAL
+#define __ARCH_WANT_SYS_TIME
+#define __ARCH_WANT_SYS_UTIME
+#define __ARCH_WANT_SYS_WAITPID
+#define __ARCH_WANT_SYS_SOCKETCALL
+#define __ARCH_WANT_SYS_FADVISE64
+#define __ARCH_WANT_SYS_GETPGRP
+#define __ARCH_WANT_SYS_LLSEEK
+#define __ARCH_WANT_SYS_NICE
+#define __ARCH_WANT_SYS_OLD_GETRLIMIT
+#define __ARCH_WANT_SYS_OLDUMOUNT
+#define __ARCH_WANT_SYS_SIGPENDING
+#define __ARCH_WANT_SYS_SIGPROCMASK
+#define __ARCH_WANT_SYS_RT_SIGACTION
+#endif
+
+
+
+#endif	/* _XTENSA_UNISTD_H */
diff --git a/include/asm-xtensa/user.h b/include/asm-xtensa/user.h
new file mode 100644
index 0000000..2c3ed23
--- /dev/null
+++ b/include/asm-xtensa/user.h
@@ -0,0 +1,20 @@
+/*
+ * include/asm-xtensa/user.h
+ *
+ * Xtensa Processor version.
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_USER_H
+#define _XTENSA_USER_H
+
+/* This file usually defines a 'struct user' structure. However, it it only
+ * used for a.out file, which are not supported on Xtensa.
+ */
+
+#endif	/* _XTENSA_USER_H */
diff --git a/include/asm-xtensa/vga.h b/include/asm-xtensa/vga.h
new file mode 100644
index 0000000..23d82f6
--- /dev/null
+++ b/include/asm-xtensa/vga.h
@@ -0,0 +1,19 @@
+/*
+ * include/asm-xtensa/vga.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_VGA_H
+#define _XTENSA_VGA_H
+
+#define VGA_MAP_MEM(x) (unsigned long)phys_to_virt(x)
+
+#define vga_readb(x)	(*(x))
+#define vga_writeb(x,y)	(*(y) = (x))
+
+#endif
diff --git a/include/asm-xtensa/xor.h b/include/asm-xtensa/xor.h
new file mode 100644
index 0000000..e7b1f08
--- /dev/null
+++ b/include/asm-xtensa/xor.h
@@ -0,0 +1,16 @@
+/*
+ * include/asm-xtensa/xor.h
+ *
+ * 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) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_XOR_H
+#define _XTENSA_XOR_H
+
+#include <asm-generic/xor.h>
+
+#endif
diff --git a/include/asm-xtensa/xtensa/cacheasm.h b/include/asm-xtensa/xtensa/cacheasm.h
new file mode 100644
index 0000000..0cdbb0b
--- /dev/null
+++ b/include/asm-xtensa/xtensa/cacheasm.h
@@ -0,0 +1,708 @@
+#ifndef XTENSA_CACHEASM_H
+#define XTENSA_CACHEASM_H
+
+/*
+ * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
+ *
+ * include/asm-xtensa/xtensa/cacheasm.h -- assembler-specific cache
+ * related definitions that depend on CORE configuration.
+ *
+ * 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) 2002 Tensilica Inc.
+ */
+
+
+#include <xtensa/coreasm.h>
+
+
+/*
+ *  This header file defines assembler macros of the form:
+ *	<x>cache_<func>
+ *  where <x> is 'i' or 'd' for instruction and data caches,
+ *  and <func> indicates the function of the macro.
+ *
+ *  The following functions <func> are defined,
+ *  and apply only to the specified cache (I or D):
+ *
+ *  reset
+ *	Resets the cache.
+ *
+ *  sync
+ *	Makes sure any previous cache instructions have been completed;
+ *	ie. makes sure any previous cache control operations
+ *	have had full effect and been synchronized to memory.
+ *	Eg. any invalidate completed [so as not to generate a hit],
+ *	any writebacks or other pipelined writes written to memory, etc.
+ *
+ *  invalidate_line		(single cache line)
+ *  invalidate_region		(specified memory range)
+ *  invalidate_all		(entire cache)
+ *	Invalidates all cache entries that cache
+ *	data from the specified memory range.
+ *	NOTE: locked entries are not invalidated.
+ *
+ *  writeback_line		(single cache line)
+ *  writeback_region		(specified memory range)
+ *  writeback_all		(entire cache)
+ *	Writes back to memory all dirty cache entries
+ *	that cache data from the specified memory range,
+ *	and marks these entries as clean.
+ *	NOTE: on some future implementations, this might
+ *		also invalidate.
+ *	NOTE: locked entries are written back, but never invalidated.
+ *	NOTE: instruction caches never implement writeback.
+ *
+ *  writeback_inv_line		(single cache line)
+ *  writeback_inv_region	(specified memory range)
+ *  writeback_inv_all		(entire cache)
+ *	Writes back to memory all dirty cache entries
+ *	that cache data from the specified memory range,
+ *	and invalidates these entries (including all clean
+ *	cache entries that cache data from that range).
+ *	NOTE: locked entries are written back but not invalidated.
+ *	NOTE: instruction caches never implement writeback.
+ *
+ *  lock_line			(single cache line)
+ *  lock_region			(specified memory range)
+ *	Prefetch and lock the specified memory range into cache.
+ *	NOTE:  if any part of the specified memory range cannot
+ *	be locked, a ??? exception occurs.  These macros don't
+ *	do anything special (yet anyway) to handle this situation.
+ *
+ *  unlock_line			(single cache line)
+ *  unlock_region		(specified memory range)
+ *  unlock_all			(entire cache)
+ *	Unlock cache entries that cache the specified memory range.
+ *	Entries not already locked are unaffected.
+ */
+
+
+
+/***************************   GENERIC -- ALL CACHES   ***************************/
+
+
+/*
+ *  The following macros assume the following cache size/parameter limits
+ *  in the current Xtensa core implementation:
+ *	cache size:	1024 bytes minimum
+ *	line size:	16 - 64 bytes
+ *	way count:	1 - 4
+ *
+ *  Minimum entries per way (ie. per associativity) = 1024 / 64 / 4 = 4
+ *  Hence the assumption that each loop can execute four cache instructions.
+ *
+ *  Correspondingly, the offset range of instructions is assumed able to cover
+ *  four lines, ie. offsets {0,1,2,3} * line_size are assumed valid for
+ *  both hit and indexed cache instructions.  Ie. these offsets are all
+ *  valid:  0, 16, 32, 48, 64, 96, 128, 192 (for line sizes 16, 32, 64).
+ *  This is true of all original cache instructions
+ *  (dhi, ihi, dhwb, dhwbi, dii, iii) which have offsets
+ *  of 0 to 1020 in multiples of 4 (ie. 8 bits shifted by 2).
+ *  This is also true of subsequent cache instructions
+ *  (dhu, ihu, diu, iiu, diwb, diwbi, dpfl, ipfl) which have offsets
+ *  of 0 to 240 in multiples of 16 (ie. 4 bits shifted by 4).
+ *
+ *  (Maximum cache size, currently 32k, doesn't affect the following macros.
+ *  Cache ways > MMU min page size cause aliasing but that's another matter.)
+ */
+
+
+
+/*
+ *  Macro to apply an 'indexed' cache instruction to the entire cache.
+ *
+ *  Parameters:
+ *	cainst		instruction/ that takes an address register parameter
+ *			and an offset parameter (in range 0 .. 3*linesize).
+ *	size		size of cache in bytes
+ *	linesize	size of cache line in bytes
+ *	assoc_or1	number of associativities (ways/sets) in cache
+ *			if all sets affected by cainst,
+ *			or 1 if only one set (or not all sets) of the cache
+ *			is affected by cainst (eg. DIWB or DIWBI [not yet ISA defined]).
+ *	aa, ab		unique address registers (temporaries)
+ */
+
+	.macro	cache_index_all		cainst, size, linesize, assoc_or1, aa, ab
+
+	//  Sanity-check on cache parameters:
+	.ifne	(\size % (\linesize * \assoc_or1 * 4))
+	.err	//  cache configuration outside expected/supported range!
+	.endif
+
+	//  \size byte cache, \linesize byte lines, \assoc_or1 way(s) affected by each \cainst.
+	movi	\aa, (\size / (\linesize * \assoc_or1 * 4))
+	// Possible improvement: need only loop if \aa > 1 ;
+	// however that particular condition is highly unlikely.
+	movi	\ab, 0		// to iterate over cache
+	floop		\aa, cachex\@
+	\cainst		\ab, 0*\linesize
+	\cainst		\ab, 1*\linesize
+	\cainst		\ab, 2*\linesize
+	\cainst		\ab, 3*\linesize
+	addi		\ab, \ab, 4*\linesize	// move to next line
+	floopend	\aa, cachex\@
+
+	.endm
+
+
+/*
+ *  Macro to apply a 'hit' cache instruction to a memory region,
+ *  ie. to any cache entries that cache a specified portion (region) of memory.
+ *  Takes care of the unaligned cases, ie. may apply to one
+ *  more cache line than $asize / lineSize if $aaddr is not aligned.
+ *
+ *
+ *  Parameters are:
+ *	cainst	instruction/macro that takes an address register parameter
+ *		and an offset parameter (currently always zero)
+ *		and generates a cache instruction (eg. "dhi", "dhwb", "ihi", etc.)
+ *	linesize_log2	log2(size of cache line in bytes)
+ *	addr	register containing start address of region (clobbered)
+ *	asize	register containing size of the region in bytes (clobbered)
+ *	askew	unique register used as temporary
+ *
+ * !?!?! 2DO: optimization: iterate max(cache_size and \asize) / linesize
+ */
+
+	.macro	cache_hit_region	cainst, linesize_log2, addr, asize, askew
+
+	//  Make \asize the number of iterations:
+	extui	\askew, \addr, 0, \linesize_log2	// get unalignment amount of \addr
+	add	\asize, \asize, \askew			// ... and add it to \asize
+	addi	\asize, \asize, (1 << \linesize_log2) - 1	// round up!
+	srli	\asize, \asize, \linesize_log2
+
+	//  Iterate over region:
+	floopnez	\asize, cacheh\@
+	\cainst		\addr, 0
+	addi		\addr, \addr, (1 << \linesize_log2)	// move to next line
+	floopend	\asize, cacheh\@
+
+	.endm
+
+
+
+
+
+/***************************   INSTRUCTION CACHE   ***************************/
+
+
+/*
+ *  Reset/initialize the instruction cache by simply invalidating it:
+ *  (need to unlock first also, if cache locking implemented):
+ *
+ *  Parameters:
+ *	aa, ab		unique address registers (temporaries)
+ */
+	.macro	icache_reset	aa, ab
+	icache_unlock_all	\aa, \ab
+	icache_invalidate_all	\aa, \ab
+	.endm
+
+
+/*
+ * Synchronize after an instruction cache operation,
+ * to be sure everything is in sync with memory as to be
+ * expected following any previous instruction cache control operations.
+ *
+ * Parameters are:
+ *	ar	an address register (temporary) (currently unused, but may be used in future)
+ */
+	.macro	icache_sync	ar
+#if XCHAL_ICACHE_SIZE > 0
+	isync
+#endif
+	.endm
+
+
+
+/*
+ *  Invalidate a single line of the instruction cache.
+ *  Parameters are:
+ *	ar	address register that contains (virtual) address to invalidate
+ *		(may get clobbered in a future implementation, but not currently)
+ *	offset	(optional) offset to add to \ar to compute effective address to invalidate
+ *		(note: some number of lsbits are ignored)
+ */
+	.macro	icache_invalidate_line	ar, offset
+#if XCHAL_ICACHE_SIZE > 0
+	ihi	\ar, \offset		// invalidate icache line
+	/*
+	 *  NOTE:  in some version of the silicon [!!!SHOULD HAVE BEEN DOCUMENTED!!!]
+	 *  'ihi' doesn't work, so it had been replaced with 'iii'
+	 *  (which would just invalidate more than it should,
+	 *  which should be okay other than the performance hit
+	 *  because cache locking did not exist in that version,
+	 *  unless user somehow relies on something being cached).
+	 *  [WHAT VERSION IS IT!!?!?
+	 *  IS THERE ANY WAY TO TEST FOR THAT HERE, TO OUTPUT 'III' ONLY IF NEEDED!?!?].
+	 *
+	 *	iii	\ar, \offset
+	 */
+	icache_sync	\ar
+#endif
+	.endm
+
+
+
+
+/*
+ *  Invalidate instruction  cache entries that cache a specified portion of memory.
+ *  Parameters are:
+ *	astart	start address (register gets clobbered)
+ *	asize	size of the region in bytes (register gets clobbered)
+ *	ac	unique register used as temporary
+ */
+	.macro	icache_invalidate_region	astart, asize, ac
+#if XCHAL_ICACHE_SIZE > 0
+	//  Instruction cache region invalidation:
+	cache_hit_region	ihi, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac
+	icache_sync	\ac
+	//  End of instruction cache region invalidation
+#endif
+	.endm
+
+
+
+/*
+ *  Invalidate entire instruction cache.
+ *
+ *  Parameters:
+ *	aa, ab		unique address registers (temporaries)
+ */
+	.macro	icache_invalidate_all	aa, ab
+#if XCHAL_ICACHE_SIZE > 0
+	//  Instruction cache invalidation:
+	cache_index_all		iii, XCHAL_ICACHE_SIZE, XCHAL_ICACHE_LINESIZE, XCHAL_ICACHE_WAYS, \aa, \ab
+	icache_sync	\aa
+	//  End of instruction cache invalidation
+#endif
+	.endm
+
+
+
+/*
+ *  Lock (prefetch & lock) a single line of the instruction cache.
+ *
+ *  Parameters are:
+ *	ar	address register that contains (virtual) address to lock
+ *		(may get clobbered in a future implementation, but not currently)
+ *	offset	offset to add to \ar to compute effective address to lock
+ *		(note: some number of lsbits are ignored)
+ */
+	.macro	icache_lock_line	ar, offset
+#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
+	ipfl	\ar, \offset	/* prefetch and lock icache line */
+	icache_sync	\ar
+#endif
+	.endm
+
+
+
+/*
+ *  Lock (prefetch & lock) a specified portion of memory into the instruction cache.
+ *  Parameters are:
+ *	astart	start address (register gets clobbered)
+ *	asize	size of the region in bytes (register gets clobbered)
+ *	ac	unique register used as temporary
+ */
+	.macro	icache_lock_region	astart, asize, ac
+#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
+	//  Instruction cache region lock:
+	cache_hit_region	ipfl, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac
+	icache_sync	\ac
+	//  End of instruction cache region lock
+#endif
+	.endm
+
+
+
+/*
+ *  Unlock a single line of the instruction cache.
+ *
+ *  Parameters are:
+ *	ar	address register that contains (virtual) address to unlock
+ *		(may get clobbered in a future implementation, but not currently)
+ *	offset	offset to add to \ar to compute effective address to unlock
+ *		(note: some number of lsbits are ignored)
+ */
+	.macro	icache_unlock_line	ar, offset
+#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
+	ihu	\ar, \offset	/* unlock icache line */
+	icache_sync	\ar
+#endif
+	.endm
+
+
+
+/*
+ *  Unlock a specified portion of memory from the instruction cache.
+ *  Parameters are:
+ *	astart	start address (register gets clobbered)
+ *	asize	size of the region in bytes (register gets clobbered)
+ *	ac	unique register used as temporary
+ */
+	.macro	icache_unlock_region	astart, asize, ac
+#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
+	//  Instruction cache region unlock:
+	cache_hit_region	ihu, XCHAL_ICACHE_LINEWIDTH, \astart, \asize, \ac
+	icache_sync	\ac
+	//  End of instruction cache region unlock
+#endif
+	.endm
+
+
+
+/*
+ *  Unlock entire instruction cache.
+ *
+ *  Parameters:
+ *	aa, ab		unique address registers (temporaries)
+ */
+	.macro	icache_unlock_all	aa, ab
+#if XCHAL_ICACHE_SIZE > 0 && XCHAL_ICACHE_LINE_LOCKABLE
+	//  Instruction cache unlock:
+	cache_index_all		iiu, XCHAL_ICACHE_SIZE, XCHAL_ICACHE_LINESIZE, 1, \aa, \ab
+	icache_sync	\aa
+	//  End of instruction cache unlock
+#endif
+	.endm
+
+
+
+
+
+/***************************   DATA CACHE   ***************************/
+
+
+
+/*
+ *  Reset/initialize the data cache by simply invalidating it
+ *  (need to unlock first also, if cache locking implemented):
+ *
+ *  Parameters:
+ *	aa, ab		unique address registers (temporaries)
+ */
+	.macro	dcache_reset	aa, ab
+	dcache_unlock_all	\aa, \ab
+	dcache_invalidate_all	\aa, \ab
+	.endm
+
+
+
+
+/*
+ * Synchronize after a data cache operation,
+ * to be sure everything is in sync with memory as to be
+ * expected following any previous data cache control operations.
+ *
+ * Parameters are:
+ *	ar	an address register (temporary) (currently unused, but may be used in future)
+ */
+	.macro	dcache_sync	ar
+#if XCHAL_DCACHE_SIZE > 0
+	//  This previous sequence errs on the conservative side (too much so); a DSYNC should be sufficient:
+	//memw		// synchronize data cache changes relative to subsequent memory accesses
+	//isync		// be conservative and ISYNC as well (just to be sure)
+
+	dsync
+#endif
+	.endm
+
+
+
+/*
+ * Synchronize after a data store operation,
+ * to be sure the stored data is completely off the processor
+ * (and assuming there is no buffering outside the processor,
+ *  that the data is in memory).  This may be required to
+ * ensure that the processor's write buffers are emptied.
+ * A MEMW followed by a read guarantees this, by definition.
+ * We also try to make sure the read itself completes.
+ *
+ * Parameters are:
+ *	ar	an address register (temporary)
+ */
+	.macro	write_sync	ar
+	memw			// ensure previous memory accesses are complete prior to subsequent memory accesses
+	l32i	\ar, sp, 0	// completing this read ensures any previous write has completed, because of MEMW
+	//slot
+	add	\ar, \ar, \ar	// use the result of the read to help ensure the read completes (in future architectures)
+	.endm
+
+
+/*
+ *  Invalidate a single line of the data cache.
+ *  Parameters are:
+ *	ar	address register that contains (virtual) address to invalidate
+ *		(may get clobbered in a future implementation, but not currently)
+ *	offset	(optional) offset to add to \ar to compute effective address to invalidate
+ *		(note: some number of lsbits are ignored)
+ */
+	.macro	dcache_invalidate_line	ar, offset
+#if XCHAL_DCACHE_SIZE > 0
+	dhi	\ar, \offset
+	dcache_sync	\ar
+#endif
+	.endm
+
+
+
+
+
+/*
+ *  Invalidate data cache entries that cache a specified portion of memory.
+ *  Parameters are:
+ *	astart	start address (register gets clobbered)
+ *	asize	size of the region in bytes (register gets clobbered)
+ *	ac	unique register used as temporary
+ */
+	.macro	dcache_invalidate_region	astart, asize, ac
+#if XCHAL_DCACHE_SIZE > 0
+	//  Data cache region invalidation:
+	cache_hit_region	dhi, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
+	dcache_sync	\ac
+	//  End of data cache region invalidation
+#endif
+	.endm
+
+
+
+#if 0
+/*
+ *  This is a work-around for a bug in SiChip1 (???).
+ *  There should be a proper mechanism for not outputting
+ *  these instructions when not needed.
+ *  To enable work-around, uncomment this and replace 'dii'
+ *  with 'dii_s1' everywhere, eg. in dcache_invalidate_all
+ *  macro below.
+ */
+	.macro	dii_s1	ar, offset
+	dii	\ar, \offset
+	or	\ar, \ar, \ar
+	or	\ar, \ar, \ar
+	or	\ar, \ar, \ar
+	or	\ar, \ar, \ar
+	.endm
+#endif
+
+
+/*
+ *  Invalidate entire data cache.
+ *
+ *  Parameters:
+ *	aa, ab		unique address registers (temporaries)
+ */
+	.macro	dcache_invalidate_all	aa, ab
+#if XCHAL_DCACHE_SIZE > 0
+	//  Data cache invalidation:
+	cache_index_all		dii, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, XCHAL_DCACHE_WAYS, \aa, \ab
+	dcache_sync	\aa
+	//  End of data cache invalidation
+#endif
+	.endm
+
+
+
+/*
+ *  Writeback a single line of the data cache.
+ *  Parameters are:
+ *	ar	address register that contains (virtual) address to writeback
+ *		(may get clobbered in a future implementation, but not currently)
+ *	offset	offset to add to \ar to compute effective address to writeback
+ *		(note: some number of lsbits are ignored)
+ */
+	.macro	dcache_writeback_line	ar, offset
+#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK
+	dhwb	\ar, \offset
+	dcache_sync	\ar
+#endif
+	.endm
+
+
+
+/*
+ *  Writeback dirty data cache entries that cache a specified portion of memory.
+ *  Parameters are:
+ *	astart	start address (register gets clobbered)
+ *	asize	size of the region in bytes (register gets clobbered)
+ *	ac	unique register used as temporary
+ */
+	.macro	dcache_writeback_region		astart, asize, ac
+#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK
+	//  Data cache region writeback:
+	cache_hit_region	dhwb, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
+	dcache_sync	\ac
+	//  End of data cache region writeback
+#endif
+	.endm
+
+
+
+/*
+ *  Writeback entire data cache.
+ *  Parameters:
+ *	aa, ab		unique address registers (temporaries)
+ */
+	.macro	dcache_writeback_all	aa, ab
+#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_IS_WRITEBACK
+	//  Data cache writeback:
+	cache_index_all		diwb, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab
+	dcache_sync	\aa
+	//  End of data cache writeback
+#endif
+	.endm
+
+
+
+/*
+ *  Writeback and invalidate a single line of the data cache.
+ *  Parameters are:
+ *	ar	address register that contains (virtual) address to writeback and invalidate
+ *		(may get clobbered in a future implementation, but not currently)
+ *	offset	offset to add to \ar to compute effective address to writeback and invalidate
+ *		(note: some number of lsbits are ignored)
+ */
+	.macro	dcache_writeback_inv_line	ar, offset
+#if XCHAL_DCACHE_SIZE > 0
+	dhwbi	\ar, \offset	/* writeback and invalidate dcache line */
+	dcache_sync	\ar
+#endif
+	.endm
+
+
+
+/*
+ *  Writeback and invalidate data cache entries that cache a specified portion of memory.
+ *  Parameters are:
+ *	astart	start address (register gets clobbered)
+ *	asize	size of the region in bytes (register gets clobbered)
+ *	ac	unique register used as temporary
+ */
+	.macro	dcache_writeback_inv_region	astart, asize, ac
+#if XCHAL_DCACHE_SIZE > 0
+	//  Data cache region writeback and invalidate:
+	cache_hit_region	dhwbi, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
+	dcache_sync	\ac
+	//  End of data cache region writeback and invalidate
+#endif
+	.endm
+
+
+
+/*
+ *  Writeback and invalidate entire data cache.
+ *  Parameters:
+ *	aa, ab		unique address registers (temporaries)
+ */
+	.macro	dcache_writeback_inv_all	aa, ab
+#if XCHAL_DCACHE_SIZE > 0
+	//  Data cache writeback and invalidate:
+#if XCHAL_DCACHE_IS_WRITEBACK
+	cache_index_all		diwbi, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab
+	dcache_sync	\aa
+#else /*writeback*/
+	//  Data cache does not support writeback, so just invalidate: */
+	dcache_invalidate_all	\aa, \ab
+#endif /*writeback*/
+	//  End of data cache writeback and invalidate
+#endif
+	.endm
+
+
+
+
+/*
+ *  Lock (prefetch & lock) a single line of the data cache.
+ *
+ *  Parameters are:
+ *	ar	address register that contains (virtual) address to lock
+ *		(may get clobbered in a future implementation, but not currently)
+ *	offset	offset to add to \ar to compute effective address to lock
+ *		(note: some number of lsbits are ignored)
+ */
+	.macro	dcache_lock_line	ar, offset
+#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
+	dpfl	\ar, \offset	/* prefetch and lock dcache line */
+	dcache_sync	\ar
+#endif
+	.endm
+
+
+
+/*
+ *  Lock (prefetch & lock) a specified portion of memory into the data cache.
+ *  Parameters are:
+ *	astart	start address (register gets clobbered)
+ *	asize	size of the region in bytes (register gets clobbered)
+ *	ac	unique register used as temporary
+ */
+	.macro	dcache_lock_region	astart, asize, ac
+#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
+	//  Data cache region lock:
+	cache_hit_region	dpfl, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
+	dcache_sync	\ac
+	//  End of data cache region lock
+#endif
+	.endm
+
+
+
+/*
+ *  Unlock a single line of the data cache.
+ *
+ *  Parameters are:
+ *	ar	address register that contains (virtual) address to unlock
+ *		(may get clobbered in a future implementation, but not currently)
+ *	offset	offset to add to \ar to compute effective address to unlock
+ *		(note: some number of lsbits are ignored)
+ */
+	.macro	dcache_unlock_line	ar, offset
+#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
+	dhu	\ar, \offset	/* unlock dcache line */
+	dcache_sync	\ar
+#endif
+	.endm
+
+
+
+/*
+ *  Unlock a specified portion of memory from the data cache.
+ *  Parameters are:
+ *	astart	start address (register gets clobbered)
+ *	asize	size of the region in bytes (register gets clobbered)
+ *	ac	unique register used as temporary
+ */
+	.macro	dcache_unlock_region	astart, asize, ac
+#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
+	//  Data cache region unlock:
+	cache_hit_region	dhu, XCHAL_DCACHE_LINEWIDTH, \astart, \asize, \ac
+	dcache_sync	\ac
+	//  End of data cache region unlock
+#endif
+	.endm
+
+
+
+/*
+ *  Unlock entire data cache.
+ *
+ *  Parameters:
+ *	aa, ab		unique address registers (temporaries)
+ */
+	.macro	dcache_unlock_all	aa, ab
+#if XCHAL_DCACHE_SIZE > 0 && XCHAL_DCACHE_LINE_LOCKABLE
+	//  Data cache unlock:
+	cache_index_all		diu, XCHAL_DCACHE_SIZE, XCHAL_DCACHE_LINESIZE, 1, \aa, \ab
+	dcache_sync	\aa
+	//  End of data cache unlock
+#endif
+	.endm
+
+
+#endif /*XTENSA_CACHEASM_H*/
+
diff --git a/include/asm-xtensa/xtensa/cacheattrasm.h b/include/asm-xtensa/xtensa/cacheattrasm.h
new file mode 100644
index 0000000..1c3e117
--- /dev/null
+++ b/include/asm-xtensa/xtensa/cacheattrasm.h
@@ -0,0 +1,432 @@
+#ifndef XTENSA_CACHEATTRASM_H
+#define XTENSA_CACHEATTRASM_H
+
+/*
+ * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
+ *
+ * include/asm-xtensa/xtensa/cacheattrasm.h -- assembler-specific
+ * CACHEATTR register related definitions that depend on CORE
+ * configuration.
+ *
+ * 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) 2002 Tensilica Inc.
+ */
+
+
+#include <xtensa/coreasm.h>
+
+
+/*
+ *  This header file defines assembler macros of the form:
+ *	<x>cacheattr_<func>
+ *  where:
+ *	<x> is 'i', 'd' or absent for instruction, data
+ *		or both caches; and
+ *	<func> indicates the function of the macro.
+ *
+ *  The following functions are defined:
+ *
+ *  icacheattr_get
+ *	Reads I-cache CACHEATTR into a2 (clobbers a3-a5).
+ *
+ *  dcacheattr_get
+ *	Reads D-cache CACHEATTR into a2 (clobbers a3-a5).
+ *	(Note:  for configs with a real CACHEATTR register, the
+ *	 above two macros are identical.)
+ *
+ *  cacheattr_set
+ *	Writes both I-cache and D-cache CACHEATTRs from a2 (a3-a8 clobbered).
+ *	Works even when changing one's own code's attributes.
+ *
+ *  icacheattr_is_enabled  label
+ *	Branches to \label if I-cache appears to have been enabled
+ *	(eg. if CACHEATTR contains a cache-enabled attribute).
+ *	(clobbers a2-a5,SAR)
+ *
+ *  dcacheattr_is_enabled  label
+ *	Branches to \label if D-cache appears to have been enabled
+ *	(eg. if CACHEATTR contains a cache-enabled attribute).
+ *	(clobbers a2-a5,SAR)
+ *
+ *  cacheattr_is_enabled  label
+ *	Branches to \label if either I-cache or D-cache appears to have been enabled
+ *	(eg. if CACHEATTR contains a cache-enabled attribute).
+ *	(clobbers a2-a5,SAR)
+ *
+ *  The following macros are only defined under certain conditions:
+ *
+ *  icacheattr_set	(if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR)
+ *	Writes I-cache CACHEATTR from a2 (a3-a8 clobbered).
+ *
+ *  dcacheattr_set	(if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR)
+ *	Writes D-cache CACHEATTR from a2 (a3-a8 clobbered).
+ */
+
+
+
+/***************************   GENERIC -- ALL CACHES   ***************************/
+
+/*
+ *  _cacheattr_get
+ *
+ *  (Internal macro.)
+ *  Returns value of CACHEATTR register (or closest equivalent) in a2.
+ *
+ *  Entry:
+ *	(none)
+ *  Exit:
+ *	a2	value read from CACHEATTR
+ *	a3-a5	clobbered (temporaries)
+ */
+	.macro	_cacheattr_get	tlb
+#if XCHAL_HAVE_CACHEATTR
+	rsr	a2, CACHEATTR
+#elif XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
+	//  We have a config that "mimics" CACHEATTR using a simplified
+	//  "MMU" composed of a single statically-mapped way.
+	//  DTLB and ITLB are independent, so there's no single
+	//  cache attribute that can describe both.  So for now
+	//  just return the DTLB state.
+	movi	a5, 0xE0000000
+	movi	a2, 0
+	movi	a3, 0
+1:	add	a3, a3, a5	// next segment
+	r&tlb&1	a4, a3		// get PPN+CA of segment at 0xE0000000, 0xC0000000, ..., 0
+	dsync	// interlock???
+	slli	a2, a2, 4
+	extui	a4, a4, 0, 4	// extract CA
+	or	a2, a2, a4
+	bnez	a3, 1b
+#else
+	//  This macro isn't applicable to arbitrary MMU configurations.
+	//  Just return zero.
+	movi	a2, 0
+#endif
+	.endm
+
+	.macro	icacheattr_get
+	_cacheattr_get	itlb
+	.endm
+
+	.macro	dcacheattr_get
+	_cacheattr_get	dtlb
+	.endm
+
+
+#define XCHAL_CACHEATTR_ALL_BYPASS	0x22222222	/* default (powerup/reset) value of CACHEATTR, all BYPASS
+							   mode (ie. disabled/bypassed caches) */
+
+#if XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
+
+#define XCHAL_FCA_ENAMASK	0x001A	/* bitmap of fetch attributes that require enabled icache */
+#define XCHAL_LCA_ENAMASK	0x0003	/* bitmap of load  attributes that require enabled dcache */
+#define XCHAL_SCA_ENAMASK	0x0003	/* bitmap of store attributes that require enabled dcache */
+#define XCHAL_LSCA_ENAMASK	(XCHAL_LCA_ENAMASK|XCHAL_SCA_ENAMASK)	/* l/s attrs requiring enabled dcache */
+#define XCHAL_ALLCA_ENAMASK	(XCHAL_FCA_ENAMASK|XCHAL_LSCA_ENAMASK)	/* all attrs requiring enabled caches */
+
+/*
+ *  _cacheattr_is_enabled
+ *
+ *  (Internal macro.)
+ *  Branches to \label if CACHEATTR in a2 indicates an enabled
+ *  cache, using mask in a3.
+ *
+ *  Parameters:
+ *	label	where to branch to if cache is enabled
+ *  Entry:
+ *	a2	contains CACHEATTR value used to determine whether
+ *		caches are enabled
+ *	a3	16-bit constant where each bit correspond to
+ *		one of the 16 possible CA values (in a CACHEATTR mask);
+ *		CA values that indicate the cache is enabled
+ *		have their corresponding bit set in this mask
+ *		(eg. use XCHAL_xCA_ENAMASK , above)
+ *  Exit:
+ *	a2,a4,a5	clobbered
+ *	SAR		clobbered
+ */
+	.macro	_cacheattr_is_enabled	label
+	movi	a4, 8		// loop 8 times
+.Lcaife\@:
+	extui	a5, a2, 0, 4	// get CA nibble
+	ssr	a5		// index into mask according to CA...
+	srl	a5, a3		// ...and get CA's mask bit in a5 bit 0
+	bbsi.l	a5, 0, \label	// if CA indicates cache enabled, jump to label
+	srli	a2, a2, 4	// next nibble
+	addi	a4, a4, -1
+	bnez	a4, .Lcaife\@	// loop for each nibble
+	.endm
+
+#else /* XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR */
+	.macro	_cacheattr_is_enabled	label
+	j	\label		// macro not applicable, assume caches always enabled
+	.endm
+#endif /* XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR */
+
+
+
+/*
+ *  icacheattr_is_enabled
+ *
+ *  Branches to \label if I-cache is enabled.
+ *
+ *  Parameters:
+ *	label	where to branch to if icache is enabled
+ *  Entry:
+ *	(none)
+ *  Exit:
+ *	a2-a5, SAR	clobbered (temporaries)
+ */
+	.macro	icacheattr_is_enabled	label
+#if XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
+	icacheattr_get
+	movi	a3, XCHAL_FCA_ENAMASK
+#endif
+	_cacheattr_is_enabled	\label
+	.endm
+
+/*
+ *  dcacheattr_is_enabled
+ *
+ *  Branches to \label if D-cache is enabled.
+ *
+ *  Parameters:
+ *	label	where to branch to if dcache is enabled
+ *  Entry:
+ *	(none)
+ *  Exit:
+ *	a2-a5, SAR	clobbered (temporaries)
+ */
+	.macro	dcacheattr_is_enabled	label
+#if XCHAL_HAVE_CACHEATTR || XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
+	dcacheattr_get
+	movi	a3, XCHAL_LSCA_ENAMASK
+#endif
+	_cacheattr_is_enabled	\label
+	.endm
+
+/*
+ *  cacheattr_is_enabled
+ *
+ *  Branches to \label if either I-cache or D-cache is enabled.
+ *
+ *  Parameters:
+ *	label	where to branch to if a cache is enabled
+ *  Entry:
+ *	(none)
+ *  Exit:
+ *	a2-a5, SAR	clobbered (temporaries)
+ */
+	.macro	cacheattr_is_enabled	label
+#if XCHAL_HAVE_CACHEATTR
+	rsr	a2, CACHEATTR
+	movi	a3, XCHAL_ALLCA_ENAMASK
+#elif XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
+	icacheattr_get
+	movi	a3, XCHAL_FCA_ENAMASK
+	_cacheattr_is_enabled	\label
+	dcacheattr_get
+	movi	a3, XCHAL_LSCA_ENAMASK
+#endif
+	_cacheattr_is_enabled	\label
+	.endm
+
+
+
+/*
+ *  The ISA does not have a defined way to change the
+ *  instruction cache attributes of the running code,
+ *  ie. of the memory area that encloses the current PC.
+ *  However, each micro-architecture (or class of
+ *  configurations within a micro-architecture)
+ *  provides a way to deal with this issue.
+ *
+ *  Here are a few macros used to implement the relevant
+ *  approach taken.
+ */
+
+#if XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
+	//  We have a config that "mimics" CACHEATTR using a simplified
+	//  "MMU" composed of a single statically-mapped way.
+
+/*
+ *  icacheattr_set
+ *
+ *  Entry:
+ *	a2		cacheattr value to set
+ *  Exit:
+ *	a2		unchanged
+ *	a3-a8		clobbered (temporaries)
+ */
+	.macro	icacheattr_set
+
+	movi	a5, 0xE0000000	// mask of upper 3 bits
+	movi	a6, 3f		// PC where ITLB is set
+	movi	a3, 0		// start at region 0 (0 .. 7)
+	and	a6, a6, a5	// upper 3 bits of local PC area
+	mov	a7, a2		// copy a2 so it doesn't get clobbered
+	j	3f
+
+# if XCHAL_HAVE_XLT_CACHEATTR
+	//  Can do translations, use generic method:
+1:	sub	a6, a3, a5	// address of some other segment
+	ritlb1	a8, a6		// save its PPN+CA
+	dsync	// interlock??
+	witlb	a4, a6		// make it translate to this code area
+	movi	a6, 5f		// where to jump into it
+	isync
+	sub	a6, a6, a5	// adjust jump address within that other segment
+	jx	a6
+
+	//  Note that in the following code snippet, which runs at a different virtual
+	//  address than it is assembled for, we avoid using literals (eg. via movi/l32r)
+	//  just in case literals end up in a different 512 MB segment, and we avoid
+	//  instructions that rely on the current PC being what is expected.
+	//
+	.align	4
+	_j	6f		// this is at label '5' minus 4 bytes
+	.align	4
+5:	witlb	a4, a3		// we're in other segment, now can write previous segment's CA
+	isync
+	add	a6, a6, a5	// back to previous segment
+	addi	a6, a6, -4	// next jump label
+	jx	a6
+
+6:	sub	a6, a3, a5	// address of some other segment
+	witlb	a8, a6		// restore PPN+CA of other segment
+	mov	a6, a3		// restore a6
+	isync
+# else /* XCHAL_HAVE_XLT_CACHEATTR */
+	//  Use micro-architecture specific method.
+	//  The following 4-instruction sequence is aligned such that
+	//  it all fits within a single I-cache line.  Sixteen byte
+	//  alignment is sufficient for this (using XCHAL_ICACHE_LINESIZE
+	//  actually causes problems because that can be greater than
+	//  the alignment of the reset vector, where this macro is often
+	//  invoked, which would cause the linker to align the reset
+	//  vector code away from the reset vector!!).
+	.align	16 /*XCHAL_ICACHE_LINESIZE*/
+1:	_witlb	a4, a3		// write wired PTE (CA, no PPN) of 512MB segment to ITLB
+	_isync
+	nop
+	nop
+# endif /* XCHAL_HAVE_XLT_CACHEATTR */
+	beq	a3, a5, 4f	// done?
+
+	//  Note that in the WITLB loop, we don't do any load/stores
+	//  (may not be an issue here, but it is important in the DTLB case).
+2:	srli	a7, a7, 4	// next CA
+	sub	a3, a3, a5	// next segment (add 0x20000000)
+3:
+# if XCHAL_HAVE_XLT_CACHEATTR	/* if have translation, preserve it */
+	ritlb1	a8, a3		// get current PPN+CA of segment
+	dsync	// interlock???
+	extui	a4, a7, 0, 4	// extract CA to set
+	srli	a8, a8, 4	// clear CA but keep PPN ...
+	slli	a8, a8, 4	// ...
+	add	a4, a4, a8	// combine new CA with PPN to preserve
+# else
+	extui	a4, a7, 0, 4	// extract CA
+# endif
+	beq	a3, a6, 1b	// current PC's region? if so, do it in a safe way
+	witlb	a4, a3		// write wired PTE (CA [+PPN]) of 512MB segment to ITLB
+	bne	a3, a5, 2b
+	isync			// make sure all ifetch changes take effect
+4:
+	.endm	// icacheattr_set
+
+
+/*
+ *  dcacheattr_set
+ *
+ *  Entry:
+ *	a2		cacheattr value to set
+ *  Exit:
+ *	a2		unchanged
+ *	a3-a8		clobbered (temporaries)
+ */
+
+	.macro	dcacheattr_set
+
+	movi	a5, 0xE0000000	// mask of upper 3 bits
+	movi	a3, 0		// start at region 0 (0 .. 7)
+	mov	a7, a2		// copy a2 so it doesn't get clobbered
+	j	3f
+	//  Note that in the WDTLB loop, we don't do any load/stores
+	//  (including implicit l32r via movi) because it isn't safe.
+2:	srli	a7, a7, 4	// next CA
+	sub	a3, a3, a5	// next segment (add 0x20000000)
+3:
+# if XCHAL_HAVE_XLT_CACHEATTR	/* if have translation, preserve it */
+	rdtlb1	a8, a3		// get current PPN+CA of segment
+	dsync	// interlock???
+	extui	a4, a7, 0, 4	// extract CA to set
+	srli	a8, a8, 4	// clear CA but keep PPN ...
+	slli	a8, a8, 4	// ...
+	add	a4, a4, a8	// combine new CA with PPN to preserve
+# else
+	extui	a4, a7, 0, 4	// extract CA to set
+# endif
+	wdtlb	a4, a3		// write wired PTE (CA [+PPN]) of 512MB segment to DTLB
+	bne	a3, a5, 2b
+	dsync			// make sure all data path changes take effect
+	.endm	// dcacheattr_set
+
+#endif /* XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR */
+
+
+
+/*
+ *  cacheattr_set
+ *
+ *  Macro that sets the current CACHEATTR safely
+ *  (both i and d) according to the current contents of a2.
+ *  It works even when changing the cache attributes of
+ *  the currently running code.
+ *
+ *  Entry:
+ *	a2		cacheattr value to set
+ *  Exit:
+ *	a2		unchanged
+ *	a3-a8		clobbered (temporaries)
+ */
+	.macro	cacheattr_set
+
+#if XCHAL_HAVE_CACHEATTR
+# if XCHAL_ICACHE_LINESIZE < 4
+	//  No i-cache, so can always safely write to CACHEATTR:
+	wsr	a2, CACHEATTR
+# else
+	//  The Athens micro-architecture, when using the old
+	//  exception architecture option (ie. with the CACHEATTR register)
+	//  allows changing the cache attributes of the running code
+	//  using the following exact sequence aligned to be within
+	//  an instruction cache line.  (NOTE: using XCHAL_ICACHE_LINESIZE
+	//  alignment actually causes problems because that can be greater
+	//  than the alignment of the reset vector, where this macro is often
+	//  invoked, which would cause the linker to align the reset
+	//  vector code away from the reset vector!!).
+	j	1f
+	.align	16 /*XCHAL_ICACHE_LINESIZE*/	// align to within an I-cache line
+1:	_wsr	a2, CACHEATTR
+	_isync
+	nop
+	nop
+# endif
+#elif XCHAL_HAVE_MIMIC_CACHEATTR || XCHAL_HAVE_XLT_CACHEATTR
+	//  DTLB and ITLB are independent, but to keep semantics
+	//  of this macro we simply write to both.
+	icacheattr_set
+	dcacheattr_set
+#else
+	//  This macro isn't applicable to arbitrary MMU configurations.
+	//  Do nothing in this case.
+#endif
+	.endm
+
+
+#endif /*XTENSA_CACHEATTRASM_H*/
+
diff --git a/include/asm-xtensa/xtensa/config-linux_be/core.h b/include/asm-xtensa/xtensa/config-linux_be/core.h
new file mode 100644
index 0000000..d54fe5e
--- /dev/null
+++ b/include/asm-xtensa/xtensa/config-linux_be/core.h
@@ -0,0 +1,1270 @@
+/*
+ * xtensa/config/core.h -- HAL definitions that are dependent on CORE configuration
+ *
+ *  This header file is sometimes referred to as the "compile-time HAL" or CHAL.
+ *  It was generated for a specific Xtensa processor configuration.
+ *
+ *  Source for configuration-independent binaries (which link in a
+ *  configuration-specific HAL library) must NEVER include this file.
+ *  It is perfectly normal, however, for the HAL source itself to include this file.
+ */
+
+/*
+ * Copyright (c) 2003 Tensilica, Inc.  All Rights Reserved.
+ *
+ * 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 would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ * USA.
+ */
+
+
+#ifndef XTENSA_CONFIG_CORE_H
+#define XTENSA_CONFIG_CORE_H
+
+#include <xtensa/hal.h>
+
+
+/*----------------------------------------------------------------------
+				GENERAL
+  ----------------------------------------------------------------------*/
+
+/*
+ *  Separators for macros that expand into arrays.
+ *  These can be predefined by files that #include this one,
+ *  when different separators are required.
+ */
+/*  Element separator for macros that expand into 1-dimensional arrays:  */
+#ifndef XCHAL_SEP
+#define XCHAL_SEP			,
+#endif
+/*  Array separator for macros that expand into 2-dimensional arrays:  */
+#ifndef XCHAL_SEP2
+#define XCHAL_SEP2			},{
+#endif
+
+
+/*----------------------------------------------------------------------
+				ENDIANNESS
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_BE			1
+#define XCHAL_HAVE_LE			0
+#define XCHAL_MEMORY_ORDER		XTHAL_BIGENDIAN
+
+
+/*----------------------------------------------------------------------
+				REGISTER WINDOWS
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_WINDOWED		1	/* 1 if windowed registers option configured, 0 otherwise */
+#define XCHAL_NUM_AREGS			64	/* number of physical address regs */
+#define XCHAL_NUM_AREGS_LOG2		6	/* log2(XCHAL_NUM_AREGS) */
+
+
+/*----------------------------------------------------------------------
+				ADDRESS ALIGNMENT
+  ----------------------------------------------------------------------*/
+
+/*  These apply to a selected set of core load and store instructions only (see ISA):  */
+#define XCHAL_UNALIGNED_LOAD_EXCEPTION	1	/* 1 if unaligned loads cause an exception, 0 otherwise */
+#define XCHAL_UNALIGNED_STORE_EXCEPTION	1	/* 1 if unaligned stores cause an exception, 0 otherwise */
+
+
+/*----------------------------------------------------------------------
+				INTERRUPTS
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_INTERRUPTS		1	/* 1 if interrupt option configured, 0 otherwise */
+#define XCHAL_HAVE_HIGHPRI_INTERRUPTS	1	/* 1 if high-priority interrupt option configured, 0 otherwise */
+#define XCHAL_HAVE_HIGHLEVEL_INTERRUPTS	XCHAL_HAVE_HIGHPRI_INTERRUPTS
+#define XCHAL_HAVE_NMI			0	/* 1 if NMI option configured, 0 otherwise */
+#define XCHAL_NUM_INTERRUPTS		17	/* number of interrupts */
+#define XCHAL_NUM_INTERRUPTS_LOG2	5	/* number of bits to hold an interrupt number: roundup(log2(number of interrupts)) */
+#define XCHAL_NUM_EXTINTERRUPTS		10	/* number of external interrupts */
+#define XCHAL_NUM_INTLEVELS		4	/* number of interrupt levels (not including level zero!) */
+#define XCHAL_NUM_LOWPRI_LEVELS		1			/* number of low-priority interrupt levels (always 1) */
+#define XCHAL_FIRST_HIGHPRI_LEVEL	(XCHAL_NUM_LOWPRI_LEVELS+1)	/* level of first high-priority interrupt (always 2) */
+#define XCHAL_EXCM_LEVEL		1			/* level of interrupts masked by PS.EXCM (XEA2 only; always 1 in T10xx);
+								   for XEA1, where there is no PS.EXCM, this is always 1;
+								   interrupts at levels FIRST_HIGHPRI <= n <= EXCM_LEVEL, if any,
+								   are termed "medium priority" interrupts (post T10xx only) */
+/*  Note:  1 <= LOWPRI_LEVELS <= EXCM_LEVEL < DEBUGLEVEL <= NUM_INTLEVELS < NMILEVEL <= 15  */
+
+/*  Masks of interrupts at each interrupt level:  */
+#define XCHAL_INTLEVEL0_MASK		0x00000000
+#define XCHAL_INTLEVEL1_MASK		0x000064F9
+#define XCHAL_INTLEVEL2_MASK		0x00008902
+#define XCHAL_INTLEVEL3_MASK		0x00011204
+#define XCHAL_INTLEVEL4_MASK		0x00000000
+#define XCHAL_INTLEVEL5_MASK		0x00000000
+#define XCHAL_INTLEVEL6_MASK		0x00000000
+#define XCHAL_INTLEVEL7_MASK		0x00000000
+#define XCHAL_INTLEVEL8_MASK		0x00000000
+#define XCHAL_INTLEVEL9_MASK		0x00000000
+#define XCHAL_INTLEVEL10_MASK		0x00000000
+#define XCHAL_INTLEVEL11_MASK		0x00000000
+#define XCHAL_INTLEVEL12_MASK		0x00000000
+#define XCHAL_INTLEVEL13_MASK		0x00000000
+#define XCHAL_INTLEVEL14_MASK		0x00000000
+#define XCHAL_INTLEVEL15_MASK		0x00000000
+/*  As an array of entries (eg. for C constant arrays):  */
+#define XCHAL_INTLEVEL_MASKS		0x00000000	XCHAL_SEP \
+					0x000064F9	XCHAL_SEP \
+					0x00008902	XCHAL_SEP \
+					0x00011204	XCHAL_SEP \
+					0x00000000	XCHAL_SEP \
+					0x00000000	XCHAL_SEP \
+					0x00000000	XCHAL_SEP \
+					0x00000000	XCHAL_SEP \
+					0x00000000	XCHAL_SEP \
+					0x00000000	XCHAL_SEP \
+					0x00000000	XCHAL_SEP \
+					0x00000000	XCHAL_SEP \
+					0x00000000	XCHAL_SEP \
+					0x00000000	XCHAL_SEP \
+					0x00000000	XCHAL_SEP \
+					0x00000000
+
+/*  Masks of interrupts at each range 1..n of interrupt levels:  */
+#define XCHAL_INTLEVEL0_ANDBELOW_MASK	0x00000000
+#define XCHAL_INTLEVEL1_ANDBELOW_MASK	0x000064F9
+#define XCHAL_INTLEVEL2_ANDBELOW_MASK	0x0000EDFB
+#define XCHAL_INTLEVEL3_ANDBELOW_MASK	0x0001FFFF
+#define XCHAL_INTLEVEL4_ANDBELOW_MASK	0x0001FFFF
+#define XCHAL_INTLEVEL5_ANDBELOW_MASK	0x0001FFFF
+#define XCHAL_INTLEVEL6_ANDBELOW_MASK	0x0001FFFF
+#define XCHAL_INTLEVEL7_ANDBELOW_MASK	0x0001FFFF
+#define XCHAL_INTLEVEL8_ANDBELOW_MASK	0x0001FFFF
+#define XCHAL_INTLEVEL9_ANDBELOW_MASK	0x0001FFFF
+#define XCHAL_INTLEVEL10_ANDBELOW_MASK	0x0001FFFF
+#define XCHAL_INTLEVEL11_ANDBELOW_MASK	0x0001FFFF
+#define XCHAL_INTLEVEL12_ANDBELOW_MASK	0x0001FFFF
+#define XCHAL_INTLEVEL13_ANDBELOW_MASK	0x0001FFFF
+#define XCHAL_INTLEVEL14_ANDBELOW_MASK	0x0001FFFF
+#define XCHAL_INTLEVEL15_ANDBELOW_MASK	0x0001FFFF
+#define XCHAL_LOWPRI_MASK		XCHAL_INTLEVEL1_ANDBELOW_MASK	/* mask of all low-priority interrupts */
+#define XCHAL_EXCM_MASK			XCHAL_INTLEVEL1_ANDBELOW_MASK	/* mask of all interrupts masked by PS.EXCM (or CEXCM) */
+/*  As an array of entries (eg. for C constant arrays):  */
+#define XCHAL_INTLEVEL_ANDBELOW_MASKS	0x00000000	XCHAL_SEP \
+					0x000064F9	XCHAL_SEP \
+					0x0000EDFB	XCHAL_SEP \
+					0x0001FFFF	XCHAL_SEP \
+					0x0001FFFF	XCHAL_SEP \
+					0x0001FFFF	XCHAL_SEP \
+					0x0001FFFF	XCHAL_SEP \
+					0x0001FFFF	XCHAL_SEP \
+					0x0001FFFF	XCHAL_SEP \
+					0x0001FFFF	XCHAL_SEP \
+					0x0001FFFF	XCHAL_SEP \
+					0x0001FFFF	XCHAL_SEP \
+					0x0001FFFF	XCHAL_SEP \
+					0x0001FFFF	XCHAL_SEP \
+					0x0001FFFF	XCHAL_SEP \
+					0x0001FFFF
+
+/*  Interrupt numbers for each interrupt level at which only one interrupt was configured:  */
+/*#define XCHAL_INTLEVEL1_NUM		...more than one interrupt at this level...*/
+/*#define XCHAL_INTLEVEL2_NUM		...more than one interrupt at this level...*/
+/*#define XCHAL_INTLEVEL3_NUM		...more than one interrupt at this level...*/
+
+/*  Level of each interrupt:  */
+#define XCHAL_INT0_LEVEL		1
+#define XCHAL_INT1_LEVEL		2
+#define XCHAL_INT2_LEVEL		3
+#define XCHAL_INT3_LEVEL		1
+#define XCHAL_INT4_LEVEL		1
+#define XCHAL_INT5_LEVEL		1
+#define XCHAL_INT6_LEVEL		1
+#define XCHAL_INT7_LEVEL		1
+#define XCHAL_INT8_LEVEL		2
+#define XCHAL_INT9_LEVEL		3
+#define XCHAL_INT10_LEVEL		1
+#define XCHAL_INT11_LEVEL		2
+#define XCHAL_INT12_LEVEL		3
+#define XCHAL_INT13_LEVEL		1
+#define XCHAL_INT14_LEVEL		1
+#define XCHAL_INT15_LEVEL		2
+#define XCHAL_INT16_LEVEL		3
+#define XCHAL_INT17_LEVEL		0
+#define XCHAL_INT18_LEVEL		0
+#define XCHAL_INT19_LEVEL		0
+#define XCHAL_INT20_LEVEL		0
+#define XCHAL_INT21_LEVEL		0
+#define XCHAL_INT22_LEVEL		0
+#define XCHAL_INT23_LEVEL		0
+#define XCHAL_INT24_LEVEL		0
+#define XCHAL_INT25_LEVEL		0
+#define XCHAL_INT26_LEVEL		0
+#define XCHAL_INT27_LEVEL		0
+#define XCHAL_INT28_LEVEL		0
+#define XCHAL_INT29_LEVEL		0
+#define XCHAL_INT30_LEVEL		0
+#define XCHAL_INT31_LEVEL		0
+/*  As an array of entries (eg. for C constant arrays):  */
+#define XCHAL_INT_LEVELS		1	XCHAL_SEP \
+					2	XCHAL_SEP \
+					3	XCHAL_SEP \
+					1	XCHAL_SEP \
+					1	XCHAL_SEP \
+					1	XCHAL_SEP \
+					1	XCHAL_SEP \
+					1	XCHAL_SEP \
+					2	XCHAL_SEP \
+					3	XCHAL_SEP \
+					1	XCHAL_SEP \
+					2	XCHAL_SEP \
+					3	XCHAL_SEP \
+					1	XCHAL_SEP \
+					1	XCHAL_SEP \
+					2	XCHAL_SEP \
+					3	XCHAL_SEP \
+					0	XCHAL_SEP \
+					0	XCHAL_SEP \
+					0	XCHAL_SEP \
+					0	XCHAL_SEP \
+					0	XCHAL_SEP \
+					0	XCHAL_SEP \
+					0	XCHAL_SEP \
+					0	XCHAL_SEP \
+					0	XCHAL_SEP \
+					0	XCHAL_SEP \
+					0	XCHAL_SEP \
+					0	XCHAL_SEP \
+					0	XCHAL_SEP \
+					0	XCHAL_SEP \
+					0
+
+/*  Type of each interrupt:  */
+#define XCHAL_INT0_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT1_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT2_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT3_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT4_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT5_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT6_TYPE 	XTHAL_INTTYPE_EXTERN_LEVEL
+#define XCHAL_INT7_TYPE 	XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT8_TYPE 	XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT9_TYPE 	XTHAL_INTTYPE_EXTERN_EDGE
+#define XCHAL_INT10_TYPE 	XTHAL_INTTYPE_TIMER
+#define XCHAL_INT11_TYPE 	XTHAL_INTTYPE_TIMER
+#define XCHAL_INT12_TYPE 	XTHAL_INTTYPE_TIMER
+#define XCHAL_INT13_TYPE 	XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT14_TYPE 	XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT15_TYPE 	XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT16_TYPE 	XTHAL_INTTYPE_SOFTWARE
+#define XCHAL_INT17_TYPE 	XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT18_TYPE 	XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT19_TYPE 	XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT20_TYPE 	XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT21_TYPE 	XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT22_TYPE 	XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT23_TYPE 	XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT24_TYPE 	XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT25_TYPE 	XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT26_TYPE 	XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT27_TYPE 	XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT28_TYPE 	XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT29_TYPE 	XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT30_TYPE 	XTHAL_INTTYPE_UNCONFIGURED
+#define XCHAL_INT31_TYPE 	XTHAL_INTTYPE_UNCONFIGURED
+/*  As an array of entries (eg. for C constant arrays):  */
+#define XCHAL_INT_TYPES		XTHAL_INTTYPE_EXTERN_LEVEL     	XCHAL_SEP \
+				XTHAL_INTTYPE_EXTERN_LEVEL     	XCHAL_SEP \
+				XTHAL_INTTYPE_EXTERN_LEVEL     	XCHAL_SEP \
+				XTHAL_INTTYPE_EXTERN_LEVEL     	XCHAL_SEP \
+				XTHAL_INTTYPE_EXTERN_LEVEL     	XCHAL_SEP \
+				XTHAL_INTTYPE_EXTERN_LEVEL     	XCHAL_SEP \
+				XTHAL_INTTYPE_EXTERN_LEVEL     	XCHAL_SEP \
+				XTHAL_INTTYPE_EXTERN_EDGE     	XCHAL_SEP \
+				XTHAL_INTTYPE_EXTERN_EDGE     	XCHAL_SEP \
+				XTHAL_INTTYPE_EXTERN_EDGE     	XCHAL_SEP \
+				XTHAL_INTTYPE_TIMER     	XCHAL_SEP \
+				XTHAL_INTTYPE_TIMER     	XCHAL_SEP \
+				XTHAL_INTTYPE_TIMER     	XCHAL_SEP \
+				XTHAL_INTTYPE_SOFTWARE     	XCHAL_SEP \
+				XTHAL_INTTYPE_SOFTWARE     	XCHAL_SEP \
+				XTHAL_INTTYPE_SOFTWARE     	XCHAL_SEP \
+				XTHAL_INTTYPE_SOFTWARE     	XCHAL_SEP \
+				XTHAL_INTTYPE_UNCONFIGURED     	XCHAL_SEP \
+				XTHAL_INTTYPE_UNCONFIGURED     	XCHAL_SEP \
+				XTHAL_INTTYPE_UNCONFIGURED     	XCHAL_SEP \
+				XTHAL_INTTYPE_UNCONFIGURED     	XCHAL_SEP \
+				XTHAL_INTTYPE_UNCONFIGURED     	XCHAL_SEP \
+				XTHAL_INTTYPE_UNCONFIGURED     	XCHAL_SEP \
+				XTHAL_INTTYPE_UNCONFIGURED     	XCHAL_SEP \
+				XTHAL_INTTYPE_UNCONFIGURED     	XCHAL_SEP \
+				XTHAL_INTTYPE_UNCONFIGURED     	XCHAL_SEP \
+				XTHAL_INTTYPE_UNCONFIGURED     	XCHAL_SEP \
+				XTHAL_INTTYPE_UNCONFIGURED     	XCHAL_SEP \
+				XTHAL_INTTYPE_UNCONFIGURED     	XCHAL_SEP \
+				XTHAL_INTTYPE_UNCONFIGURED     	XCHAL_SEP \
+				XTHAL_INTTYPE_UNCONFIGURED     	XCHAL_SEP \
+				XTHAL_INTTYPE_UNCONFIGURED
+
+/*  Masks of interrupts for each type of interrupt:  */
+#define XCHAL_INTTYPE_MASK_UNCONFIGURED	0xFFFE0000
+#define XCHAL_INTTYPE_MASK_SOFTWARE	0x0001E000
+#define XCHAL_INTTYPE_MASK_EXTERN_EDGE	0x00000380
+#define XCHAL_INTTYPE_MASK_EXTERN_LEVEL	0x0000007F
+#define XCHAL_INTTYPE_MASK_TIMER	0x00001C00
+#define XCHAL_INTTYPE_MASK_NMI		0x00000000
+/*  As an array of entries (eg. for C constant arrays):  */
+#define XCHAL_INTTYPE_MASKS		0xFFFE0000	XCHAL_SEP \
+					0x0001E000	XCHAL_SEP \
+					0x00000380	XCHAL_SEP \
+					0x0000007F	XCHAL_SEP \
+					0x00001C00	XCHAL_SEP \
+					0x00000000
+
+/*  Interrupts assigned to each timer (CCOMPARE0 to CCOMPARE3), -1 if unassigned  */
+#define XCHAL_TIMER0_INTERRUPT	10
+#define XCHAL_TIMER1_INTERRUPT	11
+#define XCHAL_TIMER2_INTERRUPT	12
+#define XCHAL_TIMER3_INTERRUPT	XTHAL_TIMER_UNCONFIGURED
+/*  As an array of entries (eg. for C constant arrays):  */
+#define XCHAL_TIMER_INTERRUPTS	10	XCHAL_SEP \
+				11	XCHAL_SEP \
+				12	XCHAL_SEP \
+				XTHAL_TIMER_UNCONFIGURED
+
+/*  Indexing macros:  */
+#define _XCHAL_INTLEVEL_MASK(n)		XCHAL_INTLEVEL ## n ## _MASK
+#define XCHAL_INTLEVEL_MASK(n)		_XCHAL_INTLEVEL_MASK(n)		/* n = 0 .. 15 */
+#define _XCHAL_INTLEVEL_ANDBELOWMASK(n)	XCHAL_INTLEVEL ## n ## _ANDBELOW_MASK
+#define XCHAL_INTLEVEL_ANDBELOW_MASK(n)	_XCHAL_INTLEVEL_ANDBELOWMASK(n)	/* n = 0 .. 15 */
+#define _XCHAL_INT_LEVEL(n)		XCHAL_INT ## n ## _LEVEL
+#define XCHAL_INT_LEVEL(n)		_XCHAL_INT_LEVEL(n)		/* n = 0 .. 31 */
+#define _XCHAL_INT_TYPE(n)		XCHAL_INT ## n ## _TYPE
+#define XCHAL_INT_TYPE(n)		_XCHAL_INT_TYPE(n)		/* n = 0 .. 31 */
+#define _XCHAL_TIMER_INTERRUPT(n)	XCHAL_TIMER ## n ## _INTERRUPT
+#define XCHAL_TIMER_INTERRUPT(n)	_XCHAL_TIMER_INTERRUPT(n)	/* n = 0 .. 3 */
+
+
+
+/*
+ *  External interrupt vectors/levels.
+ *  These macros describe how Xtensa processor interrupt numbers
+ *  (as numbered internally, eg. in INTERRUPT and INTENABLE registers)
+ *  map to external BInterrupt<n> pins, for those interrupts
+ *  configured as external (level-triggered, edge-triggered, or NMI).
+ *  See the Xtensa processor databook for more details.
+ */
+
+/*  Core interrupt numbers mapped to each EXTERNAL interrupt number:  */
+#define XCHAL_EXTINT0_NUM		0	/* (intlevel 1) */
+#define XCHAL_EXTINT1_NUM		1	/* (intlevel 2) */
+#define XCHAL_EXTINT2_NUM		2	/* (intlevel 3) */
+#define XCHAL_EXTINT3_NUM		3	/* (intlevel 1) */
+#define XCHAL_EXTINT4_NUM		4	/* (intlevel 1) */
+#define XCHAL_EXTINT5_NUM		5	/* (intlevel 1) */
+#define XCHAL_EXTINT6_NUM		6	/* (intlevel 1) */
+#define XCHAL_EXTINT7_NUM		7	/* (intlevel 1) */
+#define XCHAL_EXTINT8_NUM		8	/* (intlevel 2) */
+#define XCHAL_EXTINT9_NUM		9	/* (intlevel 3) */
+
+/*  Corresponding interrupt masks:  */
+#define XCHAL_EXTINT0_MASK		0x00000001
+#define XCHAL_EXTINT1_MASK		0x00000002
+#define XCHAL_EXTINT2_MASK		0x00000004
+#define XCHAL_EXTINT3_MASK		0x00000008
+#define XCHAL_EXTINT4_MASK		0x00000010
+#define XCHAL_EXTINT5_MASK		0x00000020
+#define XCHAL_EXTINT6_MASK		0x00000040
+#define XCHAL_EXTINT7_MASK		0x00000080
+#define XCHAL_EXTINT8_MASK		0x00000100
+#define XCHAL_EXTINT9_MASK		0x00000200
+
+/*  Core config interrupt levels mapped to each external interrupt:  */
+#define XCHAL_EXTINT0_LEVEL		1	/* (int number 0) */
+#define XCHAL_EXTINT1_LEVEL		2	/* (int number 1) */
+#define XCHAL_EXTINT2_LEVEL		3	/* (int number 2) */
+#define XCHAL_EXTINT3_LEVEL		1	/* (int number 3) */
+#define XCHAL_EXTINT4_LEVEL		1	/* (int number 4) */
+#define XCHAL_EXTINT5_LEVEL		1	/* (int number 5) */
+#define XCHAL_EXTINT6_LEVEL		1	/* (int number 6) */
+#define XCHAL_EXTINT7_LEVEL		1	/* (int number 7) */
+#define XCHAL_EXTINT8_LEVEL		2	/* (int number 8) */
+#define XCHAL_EXTINT9_LEVEL		3	/* (int number 9) */
+
+
+/*----------------------------------------------------------------------
+			EXCEPTIONS and VECTORS
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_EXCEPTIONS		1	/* 1 if exception option configured, 0 otherwise */
+
+#define XCHAL_XEA_VERSION		2	/* Xtensa Exception Architecture number: 1 for XEA1 (old), 2 for XEA2 (new) */
+#define XCHAL_HAVE_XEA1			0	/* 1 if XEA1, 0 otherwise */
+#define XCHAL_HAVE_XEA2			1	/* 1 if XEA2, 0 otherwise */
+/*  For backward compatibility ONLY -- DO NOT USE (will be removed in future release):  */
+#define XCHAL_HAVE_OLD_EXC_ARCH		XCHAL_HAVE_XEA1	/* (DEPRECATED) 1 if old exception architecture (XEA1), 0 otherwise (eg. XEA2) */
+#define XCHAL_HAVE_EXCM			XCHAL_HAVE_XEA2	/* (DEPRECATED) 1 if PS.EXCM bit exists (currently equals XCHAL_HAVE_TLBS) */
+
+#define XCHAL_RESET_VECTOR_VADDR	0xFE000020
+#define XCHAL_RESET_VECTOR_PADDR	0xFE000020
+#define XCHAL_USER_VECTOR_VADDR		0xD0000220
+#define XCHAL_PROGRAMEXC_VECTOR_VADDR	XCHAL_USER_VECTOR_VADDR		/* for backward compatibility */
+#define XCHAL_USEREXC_VECTOR_VADDR	XCHAL_USER_VECTOR_VADDR		/* for backward compatibility */
+#define XCHAL_USER_VECTOR_PADDR		0x00000220
+#define XCHAL_PROGRAMEXC_VECTOR_PADDR	XCHAL_USER_VECTOR_PADDR		/* for backward compatibility */
+#define XCHAL_USEREXC_VECTOR_PADDR	XCHAL_USER_VECTOR_PADDR		/* for backward compatibility */
+#define XCHAL_KERNEL_VECTOR_VADDR	0xD0000200
+#define XCHAL_STACKEDEXC_VECTOR_VADDR	XCHAL_KERNEL_VECTOR_VADDR	/* for backward compatibility */
+#define XCHAL_KERNELEXC_VECTOR_VADDR	XCHAL_KERNEL_VECTOR_VADDR	/* for backward compatibility */
+#define XCHAL_KERNEL_VECTOR_PADDR	0x00000200
+#define XCHAL_STACKEDEXC_VECTOR_PADDR	XCHAL_KERNEL_VECTOR_PADDR	/* for backward compatibility */
+#define XCHAL_KERNELEXC_VECTOR_PADDR	XCHAL_KERNEL_VECTOR_PADDR	/* for backward compatibility */
+#define XCHAL_DOUBLEEXC_VECTOR_VADDR	0xD0000290
+#define XCHAL_DOUBLEEXC_VECTOR_PADDR	0x00000290
+#define XCHAL_WINDOW_VECTORS_VADDR	0xD0000000
+#define XCHAL_WINDOW_VECTORS_PADDR	0x00000000
+#define XCHAL_INTLEVEL2_VECTOR_VADDR	0xD0000240
+#define XCHAL_INTLEVEL2_VECTOR_PADDR	0x00000240
+#define XCHAL_INTLEVEL3_VECTOR_VADDR	0xD0000250
+#define XCHAL_INTLEVEL3_VECTOR_PADDR	0x00000250
+#define XCHAL_INTLEVEL4_VECTOR_VADDR	0xFE000520
+#define XCHAL_INTLEVEL4_VECTOR_PADDR	0xFE000520
+#define XCHAL_DEBUG_VECTOR_VADDR	XCHAL_INTLEVEL4_VECTOR_VADDR
+#define XCHAL_DEBUG_VECTOR_PADDR	XCHAL_INTLEVEL4_VECTOR_PADDR
+
+/*  Indexing macros:  */
+#define _XCHAL_INTLEVEL_VECTOR_VADDR(n)		XCHAL_INTLEVEL ## n ## _VECTOR_VADDR
+#define XCHAL_INTLEVEL_VECTOR_VADDR(n)		_XCHAL_INTLEVEL_VECTOR_VADDR(n)		/* n = 0 .. 15 */
+
+/*
+ *  General Exception Causes
+ *  (values of EXCCAUSE special register set by general exceptions,
+ *   which vector to the user, kernel, or double-exception vectors):
+ */
+#define XCHAL_EXCCAUSE_ILLEGAL_INSTRUCTION		0	/* Illegal Instruction (IllegalInstruction) */
+#define XCHAL_EXCCAUSE_SYSTEM_CALL			1	/* System Call (SystemCall) */
+#define XCHAL_EXCCAUSE_INSTRUCTION_FETCH_ERROR		2	/* Instruction Fetch Error (InstructionFetchError) */
+#define XCHAL_EXCCAUSE_LOAD_STORE_ERROR			3	/* Load Store Error (LoadStoreError) */
+#define XCHAL_EXCCAUSE_LEVEL1_INTERRUPT			4	/* Level 1 Interrupt (Level1Interrupt) */
+#define XCHAL_EXCCAUSE_ALLOCA				5	/* Stack Extension Assist (Alloca) */
+#define XCHAL_EXCCAUSE_INTEGER_DIVIDE_BY_ZERO		6	/* Integer Divide by Zero (IntegerDivideByZero) */
+#define XCHAL_EXCCAUSE_SPECULATION			7	/* Speculation (Speculation) */
+#define XCHAL_EXCCAUSE_PRIVILEGED			8	/* Privileged Instruction (Privileged) */
+#define XCHAL_EXCCAUSE_UNALIGNED			9	/* Unaligned Load Store (Unaligned) */
+#define XCHAL_EXCCAUSE_ITLB_MISS			16	/* ITlb Miss Exception (ITlbMiss) */
+#define XCHAL_EXCCAUSE_ITLB_MULTIHIT			17	/* ITlb Mutltihit Exception (ITlbMultihit) */
+#define XCHAL_EXCCAUSE_ITLB_PRIVILEGE			18	/* ITlb Privilege Exception (ITlbPrivilege) */
+#define XCHAL_EXCCAUSE_ITLB_SIZE_RESTRICTION		19	/* ITlb Size Restriction Exception (ITlbSizeRestriction) */
+#define XCHAL_EXCCAUSE_FETCH_CACHE_ATTRIBUTE		20	/* Fetch Cache Attribute Exception (FetchCacheAttribute) */
+#define XCHAL_EXCCAUSE_DTLB_MISS			24	/* DTlb Miss Exception (DTlbMiss) */
+#define XCHAL_EXCCAUSE_DTLB_MULTIHIT			25	/* DTlb Multihit Exception (DTlbMultihit) */
+#define XCHAL_EXCCAUSE_DTLB_PRIVILEGE			26	/* DTlb Privilege Exception (DTlbPrivilege) */
+#define XCHAL_EXCCAUSE_DTLB_SIZE_RESTRICTION		27	/* DTlb Size Restriction Exception (DTlbSizeRestriction) */
+#define XCHAL_EXCCAUSE_LOAD_CACHE_ATTRIBUTE		28	/* Load Cache Attribute Exception (LoadCacheAttribute) */
+#define XCHAL_EXCCAUSE_STORE_CACHE_ATTRIBUTE		29	/* Store Cache Attribute Exception (StoreCacheAttribute) */
+#define XCHAL_EXCCAUSE_FLOATING_POINT			40	/* Floating Point Exception (FloatingPoint) */
+
+
+
+/*----------------------------------------------------------------------
+				TIMERS
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_CCOUNT		1	/* 1 if have CCOUNT, 0 otherwise */
+/*#define XCHAL_HAVE_TIMERS		XCHAL_HAVE_CCOUNT*/
+#define XCHAL_NUM_TIMERS		3	/* number of CCOMPAREn regs */
+
+
+
+/*----------------------------------------------------------------------
+				DEBUG
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_DEBUG		1	/* 1 if debug option configured, 0 otherwise */
+#define XCHAL_HAVE_OCD			1	/* 1 if OnChipDebug option configured, 0 otherwise */
+#define XCHAL_NUM_IBREAK		2	/* number of IBREAKn regs */
+#define XCHAL_NUM_DBREAK		2	/* number of DBREAKn regs */
+#define XCHAL_DEBUGLEVEL		4	/* debug interrupt level */
+/*DebugExternalInterrupt		0		0|1*/
+/*DebugUseDIRArray			0		0|1*/
+
+
+
+
+/*----------------------------------------------------------------------
+			COPROCESSORS and EXTRA STATE
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_CP			0	/* 1 if coprocessor option configured (CPENABLE present) */
+#define XCHAL_CP_MAXCFG			0	/* max allowed cp id plus one (per cfg) */
+
+#include <xtensa/config/tie.h>
+
+
+
+
+/*----------------------------------------------------------------------
+			INTERNAL I/D RAM/ROMs and XLMI
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_INSTROM		0	/* number of core instruction ROMs configured */
+#define XCHAL_NUM_INSTRAM		0	/* number of core instruction RAMs configured */
+#define XCHAL_NUM_DATAROM		0	/* number of core data ROMs configured */
+#define XCHAL_NUM_DATARAM		0	/* number of core data RAMs configured */
+#define XCHAL_NUM_XLMI			0	/* number of core XLMI ports configured */
+#define  XCHAL_NUM_IROM			XCHAL_NUM_INSTROM	/* (DEPRECATED) */
+#define  XCHAL_NUM_IRAM			XCHAL_NUM_INSTRAM	/* (DEPRECATED) */
+#define  XCHAL_NUM_DROM			XCHAL_NUM_DATAROM	/* (DEPRECATED) */
+#define  XCHAL_NUM_DRAM			XCHAL_NUM_DATARAM	/* (DEPRECATED) */
+
+
+
+/*----------------------------------------------------------------------
+				CACHE
+  ----------------------------------------------------------------------*/
+
+/*  Size of the cache lines in log2(bytes):  */
+#define XCHAL_ICACHE_LINEWIDTH		4
+#define XCHAL_DCACHE_LINEWIDTH		4
+/*  Size of the cache lines in bytes:  */
+#define XCHAL_ICACHE_LINESIZE		16
+#define XCHAL_DCACHE_LINESIZE		16
+/*  Max for both I-cache and D-cache (used for general alignment):  */
+#define XCHAL_CACHE_LINEWIDTH_MAX	4
+#define XCHAL_CACHE_LINESIZE_MAX	16
+
+/*  Number of cache sets in log2(lines per way):  */
+#define XCHAL_ICACHE_SETWIDTH		8
+#define XCHAL_DCACHE_SETWIDTH		8
+/*  Max for both I-cache and D-cache (used for general cache-coherency page alignment):  */
+#define XCHAL_CACHE_SETWIDTH_MAX	8
+#define XCHAL_CACHE_SETSIZE_MAX		256
+
+/*  Cache set associativity (number of ways):  */
+#define XCHAL_ICACHE_WAYS		2
+#define XCHAL_DCACHE_WAYS		2
+
+/*  Size of the caches in bytes (ways * 2^(linewidth + setwidth)):  */
+#define XCHAL_ICACHE_SIZE		8192
+#define XCHAL_DCACHE_SIZE		8192
+
+/*  Cache features:  */
+#define XCHAL_DCACHE_IS_WRITEBACK	0
+/*  Whether cache locking feature is available:  */
+#define XCHAL_ICACHE_LINE_LOCKABLE	0
+#define XCHAL_DCACHE_LINE_LOCKABLE	0
+
+/*  Number of (encoded) cache attribute bits:  */
+#define XCHAL_CA_BITS			4	/* number of bits needed to hold cache attribute encoding */
+/*  (The number of access mode bits (decoded cache attribute bits) is defined by the architecture; see xtensa/hal.h?)  */
+
+
+/*  Cache Attribute encodings -- lists of access modes for each cache attribute:  */
+#define XCHAL_FCA_LIST		XTHAL_FAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_FAM_BYPASS	XCHAL_SEP \
+				XTHAL_FAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_FAM_BYPASS	XCHAL_SEP \
+				XTHAL_FAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_FAM_CACHED	XCHAL_SEP \
+				XTHAL_FAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_FAM_CACHED	XCHAL_SEP \
+				XTHAL_FAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_FAM_CACHED	XCHAL_SEP \
+				XTHAL_FAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_FAM_CACHED	XCHAL_SEP \
+				XTHAL_FAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_FAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_FAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_FAM_EXCEPTION
+#define XCHAL_LCA_LIST		XTHAL_LAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_LAM_BYPASSG	XCHAL_SEP \
+				XTHAL_LAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_LAM_BYPASSG	XCHAL_SEP \
+				XTHAL_LAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_LAM_CACHED	XCHAL_SEP \
+				XTHAL_LAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_LAM_CACHED	XCHAL_SEP \
+				XTHAL_LAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_LAM_NACACHED	XCHAL_SEP \
+				XTHAL_LAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_LAM_NACACHED	XCHAL_SEP \
+				XTHAL_LAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_LAM_ISOLATE	XCHAL_SEP \
+				XTHAL_LAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_LAM_CACHED
+#define XCHAL_SCA_LIST		XTHAL_SAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_SAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_SAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_SAM_BYPASS	XCHAL_SEP \
+				XTHAL_SAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_SAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_SAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_SAM_WRITETHRU	XCHAL_SEP \
+				XTHAL_SAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_SAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_SAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_SAM_WRITETHRU	XCHAL_SEP \
+				XTHAL_SAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_SAM_ISOLATE	XCHAL_SEP \
+				XTHAL_SAM_EXCEPTION	XCHAL_SEP \
+				XTHAL_SAM_WRITETHRU
+
+/*  Test:
+	read/only: 0 + 1 + 2 + 4 + 5 + 6 + 8 + 9 + 10 + 12 + 14
+	read/only: 0 + 1 + 2 + 4 + 5 + 6 + 8 + 9 + 10 + 12 + 14
+	all:       0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15
+	fault:     0 + 2 + 4 + 6 + 8 + 10 + 12 + 14
+	r/w/x cached:
+	r/w/x dcached:
+	I-bypass:  1 + 3
+
+	load guard bit set: 1 + 3
+	load guard bit clr: 0 + 2 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15
+	hit-cache r/w/x: 7 + 11
+
+	fams: 5
+	fams: 0 / 6 / 18 / 1 / 2
+	fams: Bypass / Isolate / Cached / Exception / NACached
+
+        MMU okay:  yes
+*/
+
+
+/*----------------------------------------------------------------------
+				MMU
+  ----------------------------------------------------------------------*/
+
+/*
+ *  General notes on MMU parameters.
+ *
+ *  Terminology:
+ *	ASID = address-space ID (acts as an "extension" of virtual addresses)
+ *	VPN  = virtual page number
+ *	PPN  = physical page number
+ *	CA   = encoded cache attribute (access modes)
+ *	TLB  = translation look-aside buffer (term is stretched somewhat here)
+ *	I    = instruction (fetch accesses)
+ *	D    = data (load and store accesses)
+ *	way  = each TLB (ITLB and DTLB) consists of a number of "ways"
+ *		that simultaneously match the virtual address of an access;
+ *		a TLB successfully translates a virtual address if exactly
+ *		one way matches the vaddr; if none match, it is a miss;
+ *		if multiple match, one gets a "multihit" exception;
+ *		each way can be independently configured in terms of number of
+ *		entries, page sizes, which fields are writable or constant, etc.
+ *	set  = group of contiguous ways with exactly identical parameters
+ *	ARF  = auto-refill; hardware services a 1st-level miss by loading a PTE
+ *		from the page table and storing it in one of the auto-refill ways;
+ *		if this PTE load also misses, a miss exception is posted for s/w.
+ *	min-wired = a "min-wired" way can be used to map a single (minimum-sized)
+ * 		page arbitrarily under program control; it has a single entry,
+ *		is non-auto-refill (some other way(s) must be auto-refill),
+ *		all its fields (VPN, PPN, ASID, CA) are all writable, and it
+ *		supports the XCHAL_MMU_MIN_PTE_PAGE_SIZE page size (a current
+ *		restriction is that this be the only page size it supports).
+ *
+ *  TLB way entries are virtually indexed.
+ *  TLB ways that support multiple page sizes:
+ *	- must have all writable VPN and PPN fields;
+ *	- can only use one page size at any given time (eg. setup at startup),
+ *	  selected by the respective ITLBCFG or DTLBCFG special register,
+ *	  whose bits n*4+3 .. n*4 index the list of page sizes for way n
+ *	  (XCHAL_xTLB_SETm_PAGESZ_LOG2_LIST for set m corresponding to way n);
+ *	  this list may be sparse for auto-refill ways because auto-refill
+ *	  ways have independent lists of supported page sizes sharing a
+ *	  common encoding with PTE entries; the encoding is the index into
+ *	  this list; unsupported sizes for a given way are zero in the list;
+ *	  selecting unsupported sizes results in undefined hardware behaviour;
+ *	- is only possible for ways 0 thru 7 (due to ITLBCFG/DTLBCFG definition).
+ */
+
+#define XCHAL_HAVE_CACHEATTR		0	/* 1 if CACHEATTR register present, 0 if TLBs present instead */
+#define XCHAL_HAVE_TLBS			1	/* 1 if TLBs present, 0 if CACHEATTR present instead */
+#define XCHAL_HAVE_MMU			XCHAL_HAVE_TLBS	/* (DEPRECATED; use XCHAL_HAVE_TLBS instead; will be removed in future release) */
+#define XCHAL_HAVE_SPANNING_WAY		0	/* 1 if single way maps entire virtual address space in I+D */
+#define XCHAL_HAVE_IDENTITY_MAP		0	/* 1 if virtual addr == physical addr always, 0 otherwise */
+#define XCHAL_HAVE_MIMIC_CACHEATTR	0	/* 1 if have MMU that mimics a CACHEATTR config (CaMMU) */
+#define XCHAL_HAVE_XLT_CACHEATTR	0	/* 1 if have MMU that mimics a CACHEATTR config, but with translation (CaXltMMU) */
+
+#define XCHAL_MMU_ASID_BITS		8	/* number of bits in ASIDs (address space IDs) */
+#define XCHAL_MMU_ASID_INVALID		0	/* ASID value indicating invalid address space */
+#define XCHAL_MMU_ASID_KERNEL		1	/* ASID value indicating kernel (ring 0) address space */
+#define XCHAL_MMU_RINGS			4	/* number of rings supported (1..4) */
+#define XCHAL_MMU_RING_BITS		2	/* number of bits needed to hold ring number */
+#define XCHAL_MMU_SR_BITS		0	/* number of size-restriction bits supported */
+#define XCHAL_MMU_CA_BITS		4	/* number of bits needed to hold cache attribute encoding */
+#define XCHAL_MMU_MAX_PTE_PAGE_SIZE	12	/* max page size in a PTE structure (log2) */
+#define XCHAL_MMU_MIN_PTE_PAGE_SIZE	12	/* min page size in a PTE structure (log2) */
+
+
+/***  Instruction TLB:  ***/
+
+#define XCHAL_ITLB_WAY_BITS		3	/* number of bits holding the ways */
+#define XCHAL_ITLB_WAYS			7	/* number of ways (n-way set-associative TLB) */
+#define XCHAL_ITLB_ARF_WAYS		4	/* number of auto-refill ways */
+#define XCHAL_ITLB_SETS			4	/* number of sets (groups of ways with identical settings) */
+
+/*  Way set to which each way belongs:  */
+#define XCHAL_ITLB_WAY0_SET		0
+#define XCHAL_ITLB_WAY1_SET		0
+#define XCHAL_ITLB_WAY2_SET		0
+#define XCHAL_ITLB_WAY3_SET		0
+#define XCHAL_ITLB_WAY4_SET		1
+#define XCHAL_ITLB_WAY5_SET		2
+#define XCHAL_ITLB_WAY6_SET		3
+
+/*  Ways sets that are used by hardware auto-refill (ARF):  */
+#define XCHAL_ITLB_ARF_SETS		1	/* number of auto-refill sets */
+#define XCHAL_ITLB_ARF_SET0		0	/* index of n'th auto-refill set */
+
+/*  Way sets that are "min-wired" (see terminology comment above):  */
+#define XCHAL_ITLB_MINWIRED_SETS	0	/* number of "min-wired" sets */
+
+
+/*  ITLB way set 0 (group of ways 0 thru 3):  */
+#define XCHAL_ITLB_SET0_WAY			0	/* index of first way in this way set */
+#define XCHAL_ITLB_SET0_WAYS			4	/* number of (contiguous) ways in this way set */
+#define XCHAL_ITLB_SET0_ENTRIES_LOG2		2	/* log2(number of entries in this way) */
+#define XCHAL_ITLB_SET0_ENTRIES			4	/* number of entries in this way (always a power of 2) */
+#define XCHAL_ITLB_SET0_ARF			1	/* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
+#define XCHAL_ITLB_SET0_PAGESIZES		1	/* number of supported page sizes in this way */
+#define XCHAL_ITLB_SET0_PAGESZ_BITS		0	/* number of bits to encode the page size */
+#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MIN		12	/* log2(minimum supported page size) */
+#define XCHAL_ITLB_SET0_PAGESZ_LOG2_MAX		12	/* log2(maximum supported page size) */
+#define XCHAL_ITLB_SET0_PAGESZ_LOG2_LIST	12	/* list of log2(page size)s, separated by XCHAL_SEP;
+							   2^PAGESZ_BITS entries in list, unsupported entries are zero */
+#define XCHAL_ITLB_SET0_ASID_CONSTMASK		0	/* constant ASID bits; 0 if all writable */
+#define XCHAL_ITLB_SET0_VPN_CONSTMASK		0	/* constant VPN bits, not including entry index bits; 0 if all writable */
+#define XCHAL_ITLB_SET0_PPN_CONSTMASK		0	/* constant PPN bits, including entry index bits; 0 if all writable */
+#define XCHAL_ITLB_SET0_CA_CONSTMASK		0	/* constant CA bits; 0 if all writable */
+#define XCHAL_ITLB_SET0_ASID_RESET		0	/* 1 if ASID reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET0_VPN_RESET		0	/* 1 if VPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET0_PPN_RESET		0	/* 1 if PPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET0_CA_RESET		0	/* 1 if CA reset values defined (and all writable); 0 otherwise */
+
+/*  ITLB way set 1 (group of ways 4 thru 4):  */
+#define XCHAL_ITLB_SET1_WAY			4	/* index of first way in this way set */
+#define XCHAL_ITLB_SET1_WAYS			1	/* number of (contiguous) ways in this way set */
+#define XCHAL_ITLB_SET1_ENTRIES_LOG2		2	/* log2(number of entries in this way) */
+#define XCHAL_ITLB_SET1_ENTRIES			4	/* number of entries in this way (always a power of 2) */
+#define XCHAL_ITLB_SET1_ARF			0	/* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
+#define XCHAL_ITLB_SET1_PAGESIZES		4	/* number of supported page sizes in this way */
+#define XCHAL_ITLB_SET1_PAGESZ_BITS		2	/* number of bits to encode the page size */
+#define XCHAL_ITLB_SET1_PAGESZ_LOG2_MIN		20	/* log2(minimum supported page size) */
+#define XCHAL_ITLB_SET1_PAGESZ_LOG2_MAX		26	/* log2(maximum supported page size) */
+#define XCHAL_ITLB_SET1_PAGESZ_LOG2_LIST	20 XCHAL_SEP 22 XCHAL_SEP 24 XCHAL_SEP 26	/* list of log2(page size)s, separated by XCHAL_SEP;
+							   2^PAGESZ_BITS entries in list, unsupported entries are zero */
+#define XCHAL_ITLB_SET1_ASID_CONSTMASK		0	/* constant ASID bits; 0 if all writable */
+#define XCHAL_ITLB_SET1_VPN_CONSTMASK		0	/* constant VPN bits, not including entry index bits; 0 if all writable */
+#define XCHAL_ITLB_SET1_PPN_CONSTMASK		0	/* constant PPN bits, including entry index bits; 0 if all writable */
+#define XCHAL_ITLB_SET1_CA_CONSTMASK		0	/* constant CA bits; 0 if all writable */
+#define XCHAL_ITLB_SET1_ASID_RESET		0	/* 1 if ASID reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET1_VPN_RESET		0	/* 1 if VPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET1_PPN_RESET		0	/* 1 if PPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET1_CA_RESET		0	/* 1 if CA reset values defined (and all writable); 0 otherwise */
+
+/*  ITLB way set 2 (group of ways 5 thru 5):  */
+#define XCHAL_ITLB_SET2_WAY			5	/* index of first way in this way set */
+#define XCHAL_ITLB_SET2_WAYS			1	/* number of (contiguous) ways in this way set */
+#define XCHAL_ITLB_SET2_ENTRIES_LOG2		1	/* log2(number of entries in this way) */
+#define XCHAL_ITLB_SET2_ENTRIES			2	/* number of entries in this way (always a power of 2) */
+#define XCHAL_ITLB_SET2_ARF			0	/* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
+#define XCHAL_ITLB_SET2_PAGESIZES		1	/* number of supported page sizes in this way */
+#define XCHAL_ITLB_SET2_PAGESZ_BITS		0	/* number of bits to encode the page size */
+#define XCHAL_ITLB_SET2_PAGESZ_LOG2_MIN		27	/* log2(minimum supported page size) */
+#define XCHAL_ITLB_SET2_PAGESZ_LOG2_MAX		27	/* log2(maximum supported page size) */
+#define XCHAL_ITLB_SET2_PAGESZ_LOG2_LIST	27	/* list of log2(page size)s, separated by XCHAL_SEP;
+							   2^PAGESZ_BITS entries in list, unsupported entries are zero */
+#define XCHAL_ITLB_SET2_ASID_CONSTMASK		0xFF	/* constant ASID bits; 0 if all writable */
+#define XCHAL_ITLB_SET2_VPN_CONSTMASK		0xF0000000	/* constant VPN bits, not including entry index bits; 0 if all writable */
+#define XCHAL_ITLB_SET2_PPN_CONSTMASK		0xF8000000	/* constant PPN bits, including entry index bits; 0 if all writable */
+#define XCHAL_ITLB_SET2_CA_CONSTMASK		0x0000000F	/* constant CA bits; 0 if all writable */
+#define XCHAL_ITLB_SET2_ASID_RESET		0	/* 1 if ASID reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET2_VPN_RESET		0	/* 1 if VPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET2_PPN_RESET		0	/* 1 if PPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET2_CA_RESET		0	/* 1 if CA reset values defined (and all writable); 0 otherwise */
+/*  Constant ASID values for each entry of ITLB way set 2 (because ASID_CONSTMASK is non-zero):  */
+#define XCHAL_ITLB_SET2_E0_ASID_CONST		0x01
+#define XCHAL_ITLB_SET2_E1_ASID_CONST		0x01
+/*  Constant VPN values for each entry of ITLB way set 2 (because VPN_CONSTMASK is non-zero):  */
+#define XCHAL_ITLB_SET2_E0_VPN_CONST		0xD0000000
+#define XCHAL_ITLB_SET2_E1_VPN_CONST		0xD8000000
+/*  Constant PPN values for each entry of ITLB way set 2 (because PPN_CONSTMASK is non-zero):  */
+#define XCHAL_ITLB_SET2_E0_PPN_CONST		0x00000000
+#define XCHAL_ITLB_SET2_E1_PPN_CONST		0x00000000
+/*  Constant CA values for each entry of ITLB way set 2 (because CA_CONSTMASK is non-zero):  */
+#define XCHAL_ITLB_SET2_E0_CA_CONST		0x07
+#define XCHAL_ITLB_SET2_E1_CA_CONST		0x03
+
+/*  ITLB way set 3 (group of ways 6 thru 6):  */
+#define XCHAL_ITLB_SET3_WAY			6	/* index of first way in this way set */
+#define XCHAL_ITLB_SET3_WAYS			1	/* number of (contiguous) ways in this way set */
+#define XCHAL_ITLB_SET3_ENTRIES_LOG2		1	/* log2(number of entries in this way) */
+#define XCHAL_ITLB_SET3_ENTRIES			2	/* number of entries in this way (always a power of 2) */
+#define XCHAL_ITLB_SET3_ARF			0	/* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
+#define XCHAL_ITLB_SET3_PAGESIZES		1	/* number of supported page sizes in this way */
+#define XCHAL_ITLB_SET3_PAGESZ_BITS		0	/* number of bits to encode the page size */
+#define XCHAL_ITLB_SET3_PAGESZ_LOG2_MIN		28	/* log2(minimum supported page size) */
+#define XCHAL_ITLB_SET3_PAGESZ_LOG2_MAX		28	/* log2(maximum supported page size) */
+#define XCHAL_ITLB_SET3_PAGESZ_LOG2_LIST	28	/* list of log2(page size)s, separated by XCHAL_SEP;
+							   2^PAGESZ_BITS entries in list, unsupported entries are zero */
+#define XCHAL_ITLB_SET3_ASID_CONSTMASK		0xFF	/* constant ASID bits; 0 if all writable */
+#define XCHAL_ITLB_SET3_VPN_CONSTMASK		0xE0000000	/* constant VPN bits, not including entry index bits; 0 if all writable */
+#define XCHAL_ITLB_SET3_PPN_CONSTMASK		0xF0000000	/* constant PPN bits, including entry index bits; 0 if all writable */
+#define XCHAL_ITLB_SET3_CA_CONSTMASK		0x0000000F	/* constant CA bits; 0 if all writable */
+#define XCHAL_ITLB_SET3_ASID_RESET		0	/* 1 if ASID reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET3_VPN_RESET		0	/* 1 if VPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET3_PPN_RESET		0	/* 1 if PPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_ITLB_SET3_CA_RESET		0	/* 1 if CA reset values defined (and all writable); 0 otherwise */
+/*  Constant ASID values for each entry of ITLB way set 3 (because ASID_CONSTMASK is non-zero):  */
+#define XCHAL_ITLB_SET3_E0_ASID_CONST		0x01
+#define XCHAL_ITLB_SET3_E1_ASID_CONST		0x01
+/*  Constant VPN values for each entry of ITLB way set 3 (because VPN_CONSTMASK is non-zero):  */
+#define XCHAL_ITLB_SET3_E0_VPN_CONST		0xE0000000
+#define XCHAL_ITLB_SET3_E1_VPN_CONST		0xF0000000
+/*  Constant PPN values for each entry of ITLB way set 3 (because PPN_CONSTMASK is non-zero):  */
+#define XCHAL_ITLB_SET3_E0_PPN_CONST		0xF0000000
+#define XCHAL_ITLB_SET3_E1_PPN_CONST		0xF0000000
+/*  Constant CA values for each entry of ITLB way set 3 (because CA_CONSTMASK is non-zero):  */
+#define XCHAL_ITLB_SET3_E0_CA_CONST		0x07
+#define XCHAL_ITLB_SET3_E1_CA_CONST		0x03
+
+/*  Indexing macros:  */
+#define _XCHAL_ITLB_SET(n,_what)	XCHAL_ITLB_SET ## n ## _what
+#define XCHAL_ITLB_SET(n,what)		_XCHAL_ITLB_SET(n, _ ## what )
+#define _XCHAL_ITLB_SET_E(n,i,_what)	XCHAL_ITLB_SET ## n ## _E ## i ## _what
+#define XCHAL_ITLB_SET_E(n,i,what)	_XCHAL_ITLB_SET_E(n,i, _ ## what )
+/*
+ *  Example use:  XCHAL_ITLB_SET(XCHAL_ITLB_ARF_SET0,ENTRIES)
+ *	to get the value of XCHAL_ITLB_SET<n>_ENTRIES where <n> is the first auto-refill set.
+ */
+
+
+/***  Data TLB:  ***/
+
+#define XCHAL_DTLB_WAY_BITS		4	/* number of bits holding the ways */
+#define XCHAL_DTLB_WAYS			10	/* number of ways (n-way set-associative TLB) */
+#define XCHAL_DTLB_ARF_WAYS		4	/* number of auto-refill ways */
+#define XCHAL_DTLB_SETS			5	/* number of sets (groups of ways with identical settings) */
+
+/*  Way set to which each way belongs:  */
+#define XCHAL_DTLB_WAY0_SET		0
+#define XCHAL_DTLB_WAY1_SET		0
+#define XCHAL_DTLB_WAY2_SET		0
+#define XCHAL_DTLB_WAY3_SET		0
+#define XCHAL_DTLB_WAY4_SET		1
+#define XCHAL_DTLB_WAY5_SET		2
+#define XCHAL_DTLB_WAY6_SET		3
+#define XCHAL_DTLB_WAY7_SET		4
+#define XCHAL_DTLB_WAY8_SET		4
+#define XCHAL_DTLB_WAY9_SET		4
+
+/*  Ways sets that are used by hardware auto-refill (ARF):  */
+#define XCHAL_DTLB_ARF_SETS		1	/* number of auto-refill sets */
+#define XCHAL_DTLB_ARF_SET0		0	/* index of n'th auto-refill set */
+
+/*  Way sets that are "min-wired" (see terminology comment above):  */
+#define XCHAL_DTLB_MINWIRED_SETS	1	/* number of "min-wired" sets */
+#define XCHAL_DTLB_MINWIRED_SET0	4	/* index of n'th "min-wired" set */
+
+
+/*  DTLB way set 0 (group of ways 0 thru 3):  */
+#define XCHAL_DTLB_SET0_WAY			0	/* index of first way in this way set */
+#define XCHAL_DTLB_SET0_WAYS			4	/* number of (contiguous) ways in this way set */
+#define XCHAL_DTLB_SET0_ENTRIES_LOG2		2	/* log2(number of entries in this way) */
+#define XCHAL_DTLB_SET0_ENTRIES			4	/* number of entries in this way (always a power of 2) */
+#define XCHAL_DTLB_SET0_ARF			1	/* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
+#define XCHAL_DTLB_SET0_PAGESIZES		1	/* number of supported page sizes in this way */
+#define XCHAL_DTLB_SET0_PAGESZ_BITS		0	/* number of bits to encode the page size */
+#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MIN		12	/* log2(minimum supported page size) */
+#define XCHAL_DTLB_SET0_PAGESZ_LOG2_MAX		12	/* log2(maximum supported page size) */
+#define XCHAL_DTLB_SET0_PAGESZ_LOG2_LIST	12	/* list of log2(page size)s, separated by XCHAL_SEP;
+							   2^PAGESZ_BITS entries in list, unsupported entries are zero */
+#define XCHAL_DTLB_SET0_ASID_CONSTMASK		0	/* constant ASID bits; 0 if all writable */
+#define XCHAL_DTLB_SET0_VPN_CONSTMASK		0	/* constant VPN bits, not including entry index bits; 0 if all writable */
+#define XCHAL_DTLB_SET0_PPN_CONSTMASK		0	/* constant PPN bits, including entry index bits; 0 if all writable */
+#define XCHAL_DTLB_SET0_CA_CONSTMASK		0	/* constant CA bits; 0 if all writable */
+#define XCHAL_DTLB_SET0_ASID_RESET		0	/* 1 if ASID reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET0_VPN_RESET		0	/* 1 if VPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET0_PPN_RESET		0	/* 1 if PPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET0_CA_RESET		0	/* 1 if CA reset values defined (and all writable); 0 otherwise */
+
+/*  DTLB way set 1 (group of ways 4 thru 4):  */
+#define XCHAL_DTLB_SET1_WAY			4	/* index of first way in this way set */
+#define XCHAL_DTLB_SET1_WAYS			1	/* number of (contiguous) ways in this way set */
+#define XCHAL_DTLB_SET1_ENTRIES_LOG2		2	/* log2(number of entries in this way) */
+#define XCHAL_DTLB_SET1_ENTRIES			4	/* number of entries in this way (always a power of 2) */
+#define XCHAL_DTLB_SET1_ARF			0	/* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
+#define XCHAL_DTLB_SET1_PAGESIZES		4	/* number of supported page sizes in this way */
+#define XCHAL_DTLB_SET1_PAGESZ_BITS		2	/* number of bits to encode the page size */
+#define XCHAL_DTLB_SET1_PAGESZ_LOG2_MIN		20	/* log2(minimum supported page size) */
+#define XCHAL_DTLB_SET1_PAGESZ_LOG2_MAX		26	/* log2(maximum supported page size) */
+#define XCHAL_DTLB_SET1_PAGESZ_LOG2_LIST	20 XCHAL_SEP 22 XCHAL_SEP 24 XCHAL_SEP 26	/* list of log2(page size)s, separated by XCHAL_SEP;
+							   2^PAGESZ_BITS entries in list, unsupported entries are zero */
+#define XCHAL_DTLB_SET1_ASID_CONSTMASK		0	/* constant ASID bits; 0 if all writable */
+#define XCHAL_DTLB_SET1_VPN_CONSTMASK		0	/* constant VPN bits, not including entry index bits; 0 if all writable */
+#define XCHAL_DTLB_SET1_PPN_CONSTMASK		0	/* constant PPN bits, including entry index bits; 0 if all writable */
+#define XCHAL_DTLB_SET1_CA_CONSTMASK		0	/* constant CA bits; 0 if all writable */
+#define XCHAL_DTLB_SET1_ASID_RESET		0	/* 1 if ASID reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET1_VPN_RESET		0	/* 1 if VPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET1_PPN_RESET		0	/* 1 if PPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET1_CA_RESET		0	/* 1 if CA reset values defined (and all writable); 0 otherwise */
+
+/*  DTLB way set 2 (group of ways 5 thru 5):  */
+#define XCHAL_DTLB_SET2_WAY			5	/* index of first way in this way set */
+#define XCHAL_DTLB_SET2_WAYS			1	/* number of (contiguous) ways in this way set */
+#define XCHAL_DTLB_SET2_ENTRIES_LOG2		1	/* log2(number of entries in this way) */
+#define XCHAL_DTLB_SET2_ENTRIES			2	/* number of entries in this way (always a power of 2) */
+#define XCHAL_DTLB_SET2_ARF			0	/* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
+#define XCHAL_DTLB_SET2_PAGESIZES		1	/* number of supported page sizes in this way */
+#define XCHAL_DTLB_SET2_PAGESZ_BITS		0	/* number of bits to encode the page size */
+#define XCHAL_DTLB_SET2_PAGESZ_LOG2_MIN		27	/* log2(minimum supported page size) */
+#define XCHAL_DTLB_SET2_PAGESZ_LOG2_MAX		27	/* log2(maximum supported page size) */
+#define XCHAL_DTLB_SET2_PAGESZ_LOG2_LIST	27	/* list of log2(page size)s, separated by XCHAL_SEP;
+							   2^PAGESZ_BITS entries in list, unsupported entries are zero */
+#define XCHAL_DTLB_SET2_ASID_CONSTMASK		0xFF	/* constant ASID bits; 0 if all writable */
+#define XCHAL_DTLB_SET2_VPN_CONSTMASK		0xF0000000	/* constant VPN bits, not including entry index bits; 0 if all writable */
+#define XCHAL_DTLB_SET2_PPN_CONSTMASK		0xF8000000	/* constant PPN bits, including entry index bits; 0 if all writable */
+#define XCHAL_DTLB_SET2_CA_CONSTMASK		0x0000000F	/* constant CA bits; 0 if all writable */
+#define XCHAL_DTLB_SET2_ASID_RESET		0	/* 1 if ASID reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET2_VPN_RESET		0	/* 1 if VPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET2_PPN_RESET		0	/* 1 if PPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET2_CA_RESET		0	/* 1 if CA reset values defined (and all writable); 0 otherwise */
+/*  Constant ASID values for each entry of DTLB way set 2 (because ASID_CONSTMASK is non-zero):  */
+#define XCHAL_DTLB_SET2_E0_ASID_CONST		0x01
+#define XCHAL_DTLB_SET2_E1_ASID_CONST		0x01
+/*  Constant VPN values for each entry of DTLB way set 2 (because VPN_CONSTMASK is non-zero):  */
+#define XCHAL_DTLB_SET2_E0_VPN_CONST		0xD0000000
+#define XCHAL_DTLB_SET2_E1_VPN_CONST		0xD8000000
+/*  Constant PPN values for each entry of DTLB way set 2 (because PPN_CONSTMASK is non-zero):  */
+#define XCHAL_DTLB_SET2_E0_PPN_CONST		0x00000000
+#define XCHAL_DTLB_SET2_E1_PPN_CONST		0x00000000
+/*  Constant CA values for each entry of DTLB way set 2 (because CA_CONSTMASK is non-zero):  */
+#define XCHAL_DTLB_SET2_E0_CA_CONST		0x07
+#define XCHAL_DTLB_SET2_E1_CA_CONST		0x03
+
+/*  DTLB way set 3 (group of ways 6 thru 6):  */
+#define XCHAL_DTLB_SET3_WAY			6	/* index of first way in this way set */
+#define XCHAL_DTLB_SET3_WAYS			1	/* number of (contiguous) ways in this way set */
+#define XCHAL_DTLB_SET3_ENTRIES_LOG2		1	/* log2(number of entries in this way) */
+#define XCHAL_DTLB_SET3_ENTRIES			2	/* number of entries in this way (always a power of 2) */
+#define XCHAL_DTLB_SET3_ARF			0	/* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
+#define XCHAL_DTLB_SET3_PAGESIZES		1	/* number of supported page sizes in this way */
+#define XCHAL_DTLB_SET3_PAGESZ_BITS		0	/* number of bits to encode the page size */
+#define XCHAL_DTLB_SET3_PAGESZ_LOG2_MIN		28	/* log2(minimum supported page size) */
+#define XCHAL_DTLB_SET3_PAGESZ_LOG2_MAX		28	/* log2(maximum supported page size) */
+#define XCHAL_DTLB_SET3_PAGESZ_LOG2_LIST	28	/* list of log2(page size)s, separated by XCHAL_SEP;
+							   2^PAGESZ_BITS entries in list, unsupported entries are zero */
+#define XCHAL_DTLB_SET3_ASID_CONSTMASK		0xFF	/* constant ASID bits; 0 if all writable */
+#define XCHAL_DTLB_SET3_VPN_CONSTMASK		0xE0000000	/* constant VPN bits, not including entry index bits; 0 if all writable */
+#define XCHAL_DTLB_SET3_PPN_CONSTMASK		0xF0000000	/* constant PPN bits, including entry index bits; 0 if all writable */
+#define XCHAL_DTLB_SET3_CA_CONSTMASK		0x0000000F	/* constant CA bits; 0 if all writable */
+#define XCHAL_DTLB_SET3_ASID_RESET		0	/* 1 if ASID reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET3_VPN_RESET		0	/* 1 if VPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET3_PPN_RESET		0	/* 1 if PPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET3_CA_RESET		0	/* 1 if CA reset values defined (and all writable); 0 otherwise */
+/*  Constant ASID values for each entry of DTLB way set 3 (because ASID_CONSTMASK is non-zero):  */
+#define XCHAL_DTLB_SET3_E0_ASID_CONST		0x01
+#define XCHAL_DTLB_SET3_E1_ASID_CONST		0x01
+/*  Constant VPN values for each entry of DTLB way set 3 (because VPN_CONSTMASK is non-zero):  */
+#define XCHAL_DTLB_SET3_E0_VPN_CONST		0xE0000000
+#define XCHAL_DTLB_SET3_E1_VPN_CONST		0xF0000000
+/*  Constant PPN values for each entry of DTLB way set 3 (because PPN_CONSTMASK is non-zero):  */
+#define XCHAL_DTLB_SET3_E0_PPN_CONST		0xF0000000
+#define XCHAL_DTLB_SET3_E1_PPN_CONST		0xF0000000
+/*  Constant CA values for each entry of DTLB way set 3 (because CA_CONSTMASK is non-zero):  */
+#define XCHAL_DTLB_SET3_E0_CA_CONST		0x07
+#define XCHAL_DTLB_SET3_E1_CA_CONST		0x03
+
+/*  DTLB way set 4 (group of ways 7 thru 9):  */
+#define XCHAL_DTLB_SET4_WAY			7	/* index of first way in this way set */
+#define XCHAL_DTLB_SET4_WAYS			3	/* number of (contiguous) ways in this way set */
+#define XCHAL_DTLB_SET4_ENTRIES_LOG2		0	/* log2(number of entries in this way) */
+#define XCHAL_DTLB_SET4_ENTRIES			1	/* number of entries in this way (always a power of 2) */
+#define XCHAL_DTLB_SET4_ARF			0	/* 1=autorefill by h/w, 0=non-autorefill (wired/constant/static) */
+#define XCHAL_DTLB_SET4_PAGESIZES		1	/* number of supported page sizes in this way */
+#define XCHAL_DTLB_SET4_PAGESZ_BITS		0	/* number of bits to encode the page size */
+#define XCHAL_DTLB_SET4_PAGESZ_LOG2_MIN		12	/* log2(minimum supported page size) */
+#define XCHAL_DTLB_SET4_PAGESZ_LOG2_MAX		12	/* log2(maximum supported page size) */
+#define XCHAL_DTLB_SET4_PAGESZ_LOG2_LIST	12	/* list of log2(page size)s, separated by XCHAL_SEP;
+							   2^PAGESZ_BITS entries in list, unsupported entries are zero */
+#define XCHAL_DTLB_SET4_ASID_CONSTMASK		0	/* constant ASID bits; 0 if all writable */
+#define XCHAL_DTLB_SET4_VPN_CONSTMASK		0	/* constant VPN bits, not including entry index bits; 0 if all writable */
+#define XCHAL_DTLB_SET4_PPN_CONSTMASK		0	/* constant PPN bits, including entry index bits; 0 if all writable */
+#define XCHAL_DTLB_SET4_CA_CONSTMASK		0	/* constant CA bits; 0 if all writable */
+#define XCHAL_DTLB_SET4_ASID_RESET		0	/* 1 if ASID reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET4_VPN_RESET		0	/* 1 if VPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET4_PPN_RESET		0	/* 1 if PPN reset values defined (and all writable); 0 otherwise */
+#define XCHAL_DTLB_SET4_CA_RESET		0	/* 1 if CA reset values defined (and all writable); 0 otherwise */
+
+/*  Indexing macros:  */
+#define _XCHAL_DTLB_SET(n,_what)	XCHAL_DTLB_SET ## n ## _what
+#define XCHAL_DTLB_SET(n,what)		_XCHAL_DTLB_SET(n, _ ## what )
+#define _XCHAL_DTLB_SET_E(n,i,_what)	XCHAL_DTLB_SET ## n ## _E ## i ## _what
+#define XCHAL_DTLB_SET_E(n,i,what)	_XCHAL_DTLB_SET_E(n,i, _ ## what )
+/*
+ *  Example use:  XCHAL_DTLB_SET(XCHAL_DTLB_ARF_SET0,ENTRIES)
+ *	to get the value of XCHAL_DTLB_SET<n>_ENTRIES where <n> is the first auto-refill set.
+ */
+
+
+/*
+ *  Determine whether we have a full MMU (with Page Table and Protection)
+ *  usable for an MMU-based OS:
+ */
+#if XCHAL_HAVE_TLBS && !XCHAL_HAVE_SPANNING_WAY && XCHAL_ITLB_ARF_WAYS > 0 && XCHAL_DTLB_ARF_WAYS > 0 && XCHAL_MMU_RINGS >= 2
+# define XCHAL_HAVE_PTP_MMU		1	/* have full MMU (with page table [autorefill] and protection) */
+#else
+# define XCHAL_HAVE_PTP_MMU		0	/* don't have full MMU */
+#endif
+
+/*
+ *  For full MMUs, report kernel RAM segment and kernel I/O segment static page mappings:
+ */
+#if XCHAL_HAVE_PTP_MMU
+#define XCHAL_KSEG_CACHED_VADDR		0xD0000000	/* virt.addr of kernel RAM cached static map */
+#define XCHAL_KSEG_CACHED_PADDR		0x00000000	/* phys.addr of kseg_cached */
+#define XCHAL_KSEG_CACHED_SIZE		0x08000000	/* size in bytes of kseg_cached (assumed power of 2!!!) */
+#define XCHAL_KSEG_BYPASS_VADDR		0xD8000000	/* virt.addr of kernel RAM bypass (uncached) static map */
+#define XCHAL_KSEG_BYPASS_PADDR		0x00000000	/* phys.addr of kseg_bypass */
+#define XCHAL_KSEG_BYPASS_SIZE		0x08000000	/* size in bytes of kseg_bypass (assumed power of 2!!!) */
+
+#define XCHAL_KIO_CACHED_VADDR		0xE0000000	/* virt.addr of kernel I/O cached static map */
+#define XCHAL_KIO_CACHED_PADDR		0xF0000000	/* phys.addr of kio_cached */
+#define XCHAL_KIO_CACHED_SIZE		0x10000000	/* size in bytes of kio_cached (assumed power of 2!!!) */
+#define XCHAL_KIO_BYPASS_VADDR		0xF0000000	/* virt.addr of kernel I/O bypass (uncached) static map */
+#define XCHAL_KIO_BYPASS_PADDR		0xF0000000	/* phys.addr of kio_bypass */
+#define XCHAL_KIO_BYPASS_SIZE		0x10000000	/* size in bytes of kio_bypass (assumed power of 2!!!) */
+
+#define XCHAL_SEG_MAPPABLE_VADDR	0x00000000	/* start of largest non-static-mapped virtual addr area */
+#define XCHAL_SEG_MAPPABLE_SIZE		0xD0000000	/* size in bytes of  "  */
+/* define XCHAL_SEG_MAPPABLE2_xxx if more areas present, sorted in order of descending size.  */
+#endif
+
+
+/*----------------------------------------------------------------------
+				MISC
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_NUM_WRITEBUFFER_ENTRIES	4	/* number of write buffer entries */
+
+#define XCHAL_CORE_ID			"linux_be"	/* configuration's alphanumeric core identifier
+							   (CoreID) set in the Xtensa Processor Generator */
+
+#define XCHAL_BUILD_UNIQUE_ID		0x00003256	/* software build-unique ID (22-bit) */
+
+/*  These definitions describe the hardware targeted by this software:  */
+#define XCHAL_HW_CONFIGID0		0xC103D1FF	/* config ID reg 0 value (upper 32 of 64 bits) */
+#define XCHAL_HW_CONFIGID1		0x00803256	/* config ID reg 1 value (lower 32 of 64 bits) */
+#define XCHAL_CONFIGID0			XCHAL_HW_CONFIGID0	/* for backward compatibility only -- don't use! */
+#define XCHAL_CONFIGID1			XCHAL_HW_CONFIGID1	/* for backward compatibility only -- don't use! */
+#define XCHAL_HW_RELEASE_MAJOR		1050	/* major release of targeted hardware */
+#define XCHAL_HW_RELEASE_MINOR		1	/* minor release of targeted hardware */
+#define XCHAL_HW_RELEASE_NAME		"T1050.1"	/* full release name of targeted hardware */
+#define XTHAL_HW_REL_T1050	1
+#define XTHAL_HW_REL_T1050_1	1
+#define XCHAL_HW_CONFIGID_RELIABLE	1
+
+
+/*
+ *  Miscellaneous special register fields:
+ */
+
+
+/*  DBREAKC (special register number 160):  */
+#define XCHAL_DBREAKC_VALIDMASK	0xC000003F	/* bits of DBREAKC that are defined */
+/*  MASK field:  */
+#define XCHAL_DBREAKC_MASK_BITS 	6		/* number of bits in MASK field */
+#define XCHAL_DBREAKC_MASK_NUM  	64		/* max number of possible causes (2^bits) */
+#define XCHAL_DBREAKC_MASK_SHIFT	0		/* position of MASK bits in DBREAKC, starting from lsbit */
+#define XCHAL_DBREAKC_MASK_MASK 	0x0000003F	/* mask of bits in MASK field of DBREAKC */
+/*  LOADBREAK field:  */
+#define XCHAL_DBREAKC_LOADBREAK_BITS 	1		/* number of bits in LOADBREAK field */
+#define XCHAL_DBREAKC_LOADBREAK_NUM  	2		/* max number of possible causes (2^bits) */
+#define XCHAL_DBREAKC_LOADBREAK_SHIFT	30		/* position of LOADBREAK bits in DBREAKC, starting from lsbit */
+#define XCHAL_DBREAKC_LOADBREAK_MASK 	0x40000000	/* mask of bits in LOADBREAK field of DBREAKC */
+/*  STOREBREAK field:  */
+#define XCHAL_DBREAKC_STOREBREAK_BITS 	1		/* number of bits in STOREBREAK field */
+#define XCHAL_DBREAKC_STOREBREAK_NUM  	2		/* max number of possible causes (2^bits) */
+#define XCHAL_DBREAKC_STOREBREAK_SHIFT	31		/* position of STOREBREAK bits in DBREAKC, starting from lsbit */
+#define XCHAL_DBREAKC_STOREBREAK_MASK 	0x80000000	/* mask of bits in STOREBREAK field of DBREAKC */
+
+/*  PS (special register number 230):  */
+#define XCHAL_PS_VALIDMASK	0x00070FFF	/* bits of PS that are defined */
+/*  INTLEVEL field:  */
+#define XCHAL_PS_INTLEVEL_BITS 	4		/* number of bits in INTLEVEL field */
+#define XCHAL_PS_INTLEVEL_NUM  	16		/* max number of possible causes (2^bits) */
+#define XCHAL_PS_INTLEVEL_SHIFT	0		/* position of INTLEVEL bits in PS, starting from lsbit */
+#define XCHAL_PS_INTLEVEL_MASK 	0x0000000F	/* mask of bits in INTLEVEL field of PS */
+/*  EXCM field:  */
+#define XCHAL_PS_EXCM_BITS 	1		/* number of bits in EXCM field */
+#define XCHAL_PS_EXCM_NUM  	2		/* max number of possible causes (2^bits) */
+#define XCHAL_PS_EXCM_SHIFT	4		/* position of EXCM bits in PS, starting from lsbit */
+#define XCHAL_PS_EXCM_MASK 	0x00000010	/* mask of bits in EXCM field of PS */
+/*  PROGSTACK field:  */
+#define XCHAL_PS_PROGSTACK_BITS 	1		/* number of bits in PROGSTACK field */
+#define XCHAL_PS_PROGSTACK_NUM  	2		/* max number of possible causes (2^bits) */
+#define XCHAL_PS_PROGSTACK_SHIFT	5		/* position of PROGSTACK bits in PS, starting from lsbit */
+#define XCHAL_PS_PROGSTACK_MASK 	0x00000020	/* mask of bits in PROGSTACK field of PS */
+/*  RING field:  */
+#define XCHAL_PS_RING_BITS 	2		/* number of bits in RING field */
+#define XCHAL_PS_RING_NUM  	4		/* max number of possible causes (2^bits) */
+#define XCHAL_PS_RING_SHIFT	6		/* position of RING bits in PS, starting from lsbit */
+#define XCHAL_PS_RING_MASK 	0x000000C0	/* mask of bits in RING field of PS */
+/*  OWB field:  */
+#define XCHAL_PS_OWB_BITS 	4		/* number of bits in OWB field */
+#define XCHAL_PS_OWB_NUM  	16		/* max number of possible causes (2^bits) */
+#define XCHAL_PS_OWB_SHIFT	8		/* position of OWB bits in PS, starting from lsbit */
+#define XCHAL_PS_OWB_MASK 	0x00000F00	/* mask of bits in OWB field of PS */
+/*  CALLINC field:  */
+#define XCHAL_PS_CALLINC_BITS 	2		/* number of bits in CALLINC field */
+#define XCHAL_PS_CALLINC_NUM  	4		/* max number of possible causes (2^bits) */
+#define XCHAL_PS_CALLINC_SHIFT	16		/* position of CALLINC bits in PS, starting from lsbit */
+#define XCHAL_PS_CALLINC_MASK 	0x00030000	/* mask of bits in CALLINC field of PS */
+/*  WOE field:  */
+#define XCHAL_PS_WOE_BITS 	1		/* number of bits in WOE field */
+#define XCHAL_PS_WOE_NUM  	2		/* max number of possible causes (2^bits) */
+#define XCHAL_PS_WOE_SHIFT	18		/* position of WOE bits in PS, starting from lsbit */
+#define XCHAL_PS_WOE_MASK 	0x00040000	/* mask of bits in WOE field of PS */
+
+/*  EXCCAUSE (special register number 232):  */
+#define XCHAL_EXCCAUSE_VALIDMASK	0x0000003F	/* bits of EXCCAUSE that are defined */
+/*  EXCCAUSE field:  */
+#define XCHAL_EXCCAUSE_BITS 		6		/* number of bits in EXCCAUSE register */
+#define XCHAL_EXCCAUSE_NUM  		64		/* max number of possible causes (2^bits) */
+#define XCHAL_EXCCAUSE_SHIFT		0		/* position of EXCCAUSE bits in register, starting from lsbit */
+#define XCHAL_EXCCAUSE_MASK 		0x0000003F	/* mask of bits in EXCCAUSE register */
+
+/*  DEBUGCAUSE (special register number 233):  */
+#define XCHAL_DEBUGCAUSE_VALIDMASK	0x0000003F	/* bits of DEBUGCAUSE that are defined */
+/*  ICOUNT field:  */
+#define XCHAL_DEBUGCAUSE_ICOUNT_BITS 	1		/* number of bits in ICOUNT field */
+#define XCHAL_DEBUGCAUSE_ICOUNT_NUM  	2		/* max number of possible causes (2^bits) */
+#define XCHAL_DEBUGCAUSE_ICOUNT_SHIFT	0		/* position of ICOUNT bits in DEBUGCAUSE, starting from lsbit */
+#define XCHAL_DEBUGCAUSE_ICOUNT_MASK 	0x00000001	/* mask of bits in ICOUNT field of DEBUGCAUSE */
+/*  IBREAK field:  */
+#define XCHAL_DEBUGCAUSE_IBREAK_BITS 	1		/* number of bits in IBREAK field */
+#define XCHAL_DEBUGCAUSE_IBREAK_NUM  	2		/* max number of possible causes (2^bits) */
+#define XCHAL_DEBUGCAUSE_IBREAK_SHIFT	1		/* position of IBREAK bits in DEBUGCAUSE, starting from lsbit */
+#define XCHAL_DEBUGCAUSE_IBREAK_MASK 	0x00000002	/* mask of bits in IBREAK field of DEBUGCAUSE */
+/*  DBREAK field:  */
+#define XCHAL_DEBUGCAUSE_DBREAK_BITS 	1		/* number of bits in DBREAK field */
+#define XCHAL_DEBUGCAUSE_DBREAK_NUM  	2		/* max number of possible causes (2^bits) */
+#define XCHAL_DEBUGCAUSE_DBREAK_SHIFT	2		/* position of DBREAK bits in DEBUGCAUSE, starting from lsbit */
+#define XCHAL_DEBUGCAUSE_DBREAK_MASK 	0x00000004	/* mask of bits in DBREAK field of DEBUGCAUSE */
+/*  BREAK field:  */
+#define XCHAL_DEBUGCAUSE_BREAK_BITS 	1		/* number of bits in BREAK field */
+#define XCHAL_DEBUGCAUSE_BREAK_NUM  	2		/* max number of possible causes (2^bits) */
+#define XCHAL_DEBUGCAUSE_BREAK_SHIFT	3		/* position of BREAK bits in DEBUGCAUSE, starting from lsbit */
+#define XCHAL_DEBUGCAUSE_BREAK_MASK 	0x00000008	/* mask of bits in BREAK field of DEBUGCAUSE */
+/*  BREAKN field:  */
+#define XCHAL_DEBUGCAUSE_BREAKN_BITS 	1		/* number of bits in BREAKN field */
+#define XCHAL_DEBUGCAUSE_BREAKN_NUM  	2		/* max number of possible causes (2^bits) */
+#define XCHAL_DEBUGCAUSE_BREAKN_SHIFT	4		/* position of BREAKN bits in DEBUGCAUSE, starting from lsbit */
+#define XCHAL_DEBUGCAUSE_BREAKN_MASK 	0x00000010	/* mask of bits in BREAKN field of DEBUGCAUSE */
+/*  DEBUGINT field:  */
+#define XCHAL_DEBUGCAUSE_DEBUGINT_BITS 	1		/* number of bits in DEBUGINT field */
+#define XCHAL_DEBUGCAUSE_DEBUGINT_NUM  	2		/* max number of possible causes (2^bits) */
+#define XCHAL_DEBUGCAUSE_DEBUGINT_SHIFT	5		/* position of DEBUGINT bits in DEBUGCAUSE, starting from lsbit */
+#define XCHAL_DEBUGCAUSE_DEBUGINT_MASK 	0x00000020	/* mask of bits in DEBUGINT field of DEBUGCAUSE */
+
+
+
+/*----------------------------------------------------------------------
+				ISA
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_HAVE_DENSITY		1	/* 1 if density option configured, 0 otherwise */
+#define XCHAL_HAVE_LOOPS		1	/* 1 if zero-overhead loops option configured, 0 otherwise */
+/*  Misc instructions:  */
+#define XCHAL_HAVE_NSA			0	/* 1 if NSA/NSAU instructions option configured, 0 otherwise */
+#define XCHAL_HAVE_MINMAX		0	/* 1 if MIN/MAX instructions option configured, 0 otherwise */
+#define XCHAL_HAVE_SEXT			0	/* 1 if sign-extend instruction option configured, 0 otherwise */
+#define XCHAL_HAVE_CLAMPS		0	/* 1 if CLAMPS instruction option configured, 0 otherwise */
+#define XCHAL_HAVE_MAC16		0	/* 1 if MAC16 option configured, 0 otherwise */
+#define XCHAL_HAVE_MUL16		0	/* 1 if 16-bit integer multiply option configured, 0 otherwise */
+/*#define XCHAL_HAVE_POPC		0*/	/* 1 if CRC instruction option configured, 0 otherwise */
+/*#define XCHAL_HAVE_CRC		0*/	/* 1 if POPC instruction option configured, 0 otherwise */
+
+#define XCHAL_HAVE_SPECULATION		0	/* 1 if speculation option configured, 0 otherwise */
+/*#define XCHAL_HAVE_MP_SYNC		0*/	/* 1 if multiprocessor sync. option configured, 0 otherwise */
+#define XCHAL_HAVE_PRID			0	/* 1 if processor ID register configured, 0 otherwise */
+
+#define XCHAL_NUM_MISC_REGS		2	/* number of miscellaneous registers (0..4) */
+
+/*  These relate a bit more to TIE:  */
+#define XCHAL_HAVE_BOOLEANS		0	/* 1 if booleans option configured, 0 otherwise */
+#define XCHAL_HAVE_MUL32		0	/* 1 if 32-bit integer multiply option configured, 0 otherwise */
+#define XCHAL_HAVE_MUL32_HIGH		0	/* 1 if MUL32 option includes MULUH and MULSH, 0 otherwise */
+#define XCHAL_HAVE_FP			0	/* 1 if floating point option configured, 0 otherwise */
+
+
+/*----------------------------------------------------------------------
+				DERIVED
+  ----------------------------------------------------------------------*/
+
+#if XCHAL_HAVE_BE
+#define XCHAL_INST_ILLN			0xD60F		/* 2-byte illegal instruction, msb-first */
+#define XCHAL_INST_ILLN_BYTE0		0xD6		/* 2-byte illegal instruction, 1st byte */
+#define XCHAL_INST_ILLN_BYTE1		0x0F		/* 2-byte illegal instruction, 2nd byte */
+#else
+#define XCHAL_INST_ILLN			0xF06D		/* 2-byte illegal instruction, lsb-first */
+#define XCHAL_INST_ILLN_BYTE0		0x6D		/* 2-byte illegal instruction, 1st byte */
+#define XCHAL_INST_ILLN_BYTE1		0xF0		/* 2-byte illegal instruction, 2nd byte */
+#endif
+/*  Belongs in xtensa/hal.h:  */
+#define XTHAL_INST_ILL			0x000000	/* 3-byte illegal instruction */
+
+
+/*
+ *  Because information as to exactly which hardware release is targeted
+ *  by a given software build is not always available, compile-time HAL
+ *  Hardware-Release "_AT" macros are fuzzy (return 0, 1, or XCHAL_MAYBE):
+ */
+#ifndef XCHAL_HW_RELEASE_MAJOR
+# define XCHAL_HW_CONFIGID_RELIABLE	0
+#endif
+#if XCHAL_HW_CONFIGID_RELIABLE
+# define XCHAL_HW_RELEASE_AT_OR_BELOW(major,minor)	(XTHAL_REL_LE( XCHAL_HW_RELEASE_MAJOR,XCHAL_HW_RELEASE_MINOR, major,minor ) ? 1 : 0)
+# define XCHAL_HW_RELEASE_AT_OR_ABOVE(major,minor)	(XTHAL_REL_GE( XCHAL_HW_RELEASE_MAJOR,XCHAL_HW_RELEASE_MINOR, major,minor ) ? 1 : 0)
+# define XCHAL_HW_RELEASE_AT(major,minor)		(XTHAL_REL_EQ( XCHAL_HW_RELEASE_MAJOR,XCHAL_HW_RELEASE_MINOR, major,minor ) ? 1 : 0)
+# define XCHAL_HW_RELEASE_MAJOR_AT(major)		((XCHAL_HW_RELEASE_MAJOR == (major)) ? 1 : 0)
+#else
+# define XCHAL_HW_RELEASE_AT_OR_BELOW(major,minor)	( ((major) < 1040 && XCHAL_HAVE_XEA2) ? 0 \
+							: ((major) > 1050 && XCHAL_HAVE_XEA1) ? 1 \
+							: XTHAL_MAYBE )
+# define XCHAL_HW_RELEASE_AT_OR_ABOVE(major,minor)	( ((major) >= 2000 && XCHAL_HAVE_XEA1) ? 0 \
+							: (XTHAL_REL_LE(major,minor, 1040,0) && XCHAL_HAVE_XEA2) ? 1 \
+							: XTHAL_MAYBE )
+# define XCHAL_HW_RELEASE_AT(major,minor)		( (((major) < 1040 && XCHAL_HAVE_XEA2) || \
+							   ((major) >= 2000 && XCHAL_HAVE_XEA1)) ? 0 : XTHAL_MAYBE)
+# define XCHAL_HW_RELEASE_MAJOR_AT(major)		XCHAL_HW_RELEASE_AT(major,0)
+#endif
+
+/*
+ *  Specific errata:
+ */
+
+/*
+ *  Erratum T1020.H13, T1030.H7, T1040.H10, T1050.H4 (fixed in T1040.3 and T1050.1;
+ *  relevant only in XEA1, kernel-vector mode, level-one interrupts and overflows enabled):
+ */
+#define XCHAL_MAYHAVE_ERRATUM_XEA1KWIN	(XCHAL_HAVE_XEA1 && \
+					 (XCHAL_HW_RELEASE_AT_OR_BELOW(1040,2) != 0 \
+					  || XCHAL_HW_RELEASE_AT(1050,0)))
+
+
+
+#endif /*XTENSA_CONFIG_CORE_H*/
+
diff --git a/include/asm-xtensa/xtensa/config-linux_be/defs.h b/include/asm-xtensa/xtensa/config-linux_be/defs.h
new file mode 100644
index 0000000..f7c58b2
--- /dev/null
+++ b/include/asm-xtensa/xtensa/config-linux_be/defs.h
@@ -0,0 +1,270 @@
+/* Definitions for Xtensa instructions, types, and protos. */
+
+/*
+ * Copyright (c) 2003 Tensilica, Inc.  All Rights Reserved.
+ *
+ * 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 would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ * USA.
+ */
+
+/* Do not modify. This is automatically generated.*/
+
+#ifndef _XTENSA_BASE_HEADER
+#define _XTENSA_BASE_HEADER
+
+#ifdef __XTENSA__
+#if defined(__GNUC__) && !defined(__XCC__)
+
+#define L8UI_ASM(arr, ars, imm) { \
+  __asm__ volatile("l8ui %0, %1, %2" : "=a" (arr) : "a" (ars) , "i" (imm)); \
+}
+
+#define XT_L8UI(ars, imm) \
+({ \
+  unsigned char _arr; \
+  const unsigned char *_ars = ars; \
+  L8UI_ASM(_arr, _ars, imm); \
+  _arr; \
+})
+
+#define L16UI_ASM(arr, ars, imm) { \
+  __asm__ volatile("l16ui %0, %1, %2" : "=a" (arr) : "a" (ars) , "i" (imm)); \
+}
+
+#define XT_L16UI(ars, imm) \
+({ \
+  unsigned short _arr; \
+  const unsigned short *_ars = ars; \
+  L16UI_ASM(_arr, _ars, imm); \
+  _arr; \
+})
+
+#define L16SI_ASM(arr, ars, imm) {\
+  __asm__ volatile("l16si %0, %1, %2" : "=a" (arr) : "a" (ars) , "i" (imm)); \
+}
+
+#define XT_L16SI(ars, imm) \
+({ \
+  signed short _arr; \
+  const signed short *_ars = ars; \
+  L16SI_ASM(_arr, _ars, imm); \
+  _arr; \
+})
+
+#define L32I_ASM(arr, ars, imm) { \
+  __asm__ volatile("l32i %0, %1, %2" : "=a" (arr) : "a" (ars) , "i" (imm)); \
+}
+
+#define XT_L32I(ars, imm) \
+({ \
+  unsigned _arr; \
+  const unsigned *_ars = ars; \
+  L32I_ASM(_arr, _ars, imm); \
+  _arr; \
+})
+
+#define S8I_ASM(arr, ars, imm) {\
+  __asm__ volatile("s8i %0, %1, %2" : : "a" (arr), "a" (ars) , "i" (imm) : "memory" ); \
+}
+
+#define XT_S8I(arr, ars, imm) \
+({ \
+  signed char _arr = arr; \
+  const signed char *_ars = ars; \
+  S8I_ASM(_arr, _ars, imm); \
+})
+
+#define S16I_ASM(arr, ars, imm) {\
+  __asm__ volatile("s16i %0, %1, %2" : : "a" (arr), "a" (ars) , "i" (imm) : "memory" ); \
+}
+
+#define XT_S16I(arr, ars, imm) \
+({ \
+  signed short _arr = arr; \
+  const signed short *_ars = ars; \
+  S16I_ASM(_arr, _ars, imm); \
+})
+
+#define S32I_ASM(arr, ars, imm) { \
+  __asm__ volatile("s32i %0, %1, %2" : : "a" (arr), "a" (ars) , "i" (imm) : "memory" ); \
+}
+
+#define XT_S32I(arr, ars, imm) \
+({ \
+  signed int _arr = arr; \
+  const signed int *_ars = ars; \
+  S32I_ASM(_arr, _ars, imm); \
+})
+
+#define ADDI_ASM(art, ars, imm) {\
+   __asm__ ("addi %0, %1, %2" : "=a" (art) : "a" (ars), "i" (imm)); \
+}
+
+#define XT_ADDI(ars, imm) \
+({ \
+   unsigned _art; \
+   unsigned _ars = ars; \
+   ADDI_ASM(_art, _ars, imm); \
+   _art; \
+})
+
+#define ABS_ASM(arr, art) {\
+   __asm__ ("abs %0, %1" : "=a" (arr) : "a" (art)); \
+}
+
+#define XT_ABS(art) \
+({ \
+   unsigned _arr; \
+   signed _art = art; \
+   ABS_ASM(_arr, _art); \
+   _arr; \
+})
+
+/* Note: In the following macros that reference SAR, the magic "state"
+   register is used to capture the dependency on SAR.  This is because
+   SAR is a 5-bit register and thus there are no C types that can be
+   used to represent it.  It doesn't appear that the SAR register is
+   even relevant to GCC, but it is marked as "clobbered" just in
+   case.  */
+
+#define SRC_ASM(arr, ars, art) {\
+   register int _xt_sar __asm__ ("state"); \
+   __asm__ ("src %0, %1, %2" \
+	    : "=a" (arr) : "a" (ars), "a" (art), "t" (_xt_sar)); \
+}
+
+#define XT_SRC(ars, art) \
+({ \
+   unsigned _arr; \
+   unsigned _ars = ars; \
+   unsigned _art = art; \
+   SRC_ASM(_arr, _ars, _art); \
+   _arr; \
+})
+
+#define SSR_ASM(ars) {\
+   register int _xt_sar __asm__ ("state"); \
+   __asm__ ("ssr %1" : "=t" (_xt_sar) : "a" (ars) : "sar"); \
+}
+
+#define XT_SSR(ars) \
+({ \
+   unsigned _ars = ars; \
+   SSR_ASM(_ars); \
+})
+
+#define SSL_ASM(ars) {\
+   register int _xt_sar __asm__ ("state"); \
+   __asm__ ("ssl %1" : "=t" (_xt_sar) : "a" (ars) : "sar"); \
+}
+
+#define XT_SSL(ars) \
+({ \
+   unsigned _ars = ars; \
+   SSL_ASM(_ars); \
+})
+
+#define SSA8B_ASM(ars) {\
+   register int _xt_sar __asm__ ("state"); \
+   __asm__ ("ssa8b %1" : "=t" (_xt_sar) : "a" (ars) : "sar"); \
+}
+
+#define XT_SSA8B(ars) \
+({ \
+   unsigned _ars = ars; \
+   SSA8B_ASM(_ars); \
+})
+
+#define SSA8L_ASM(ars) {\
+   register int _xt_sar __asm__ ("state"); \
+   __asm__ ("ssa8l %1" : "=t" (_xt_sar) : "a" (ars) : "sar"); \
+}
+
+#define XT_SSA8L(ars) \
+({ \
+   unsigned _ars = ars; \
+   SSA8L_ASM(_ars); \
+})
+
+#define SSAI_ASM(imm) {\
+   register int _xt_sar __asm__ ("state"); \
+   __asm__ ("ssai %1" : "=t" (_xt_sar) : "i" (imm) : "sar"); \
+}
+
+#define XT_SSAI(imm) \
+({ \
+   SSAI_ASM(imm); \
+})
+
+
+
+
+
+
+
+
+#endif /* __GNUC__ && !__XCC__ */
+
+#ifdef __XCC__
+
+/* Core load/store instructions */
+extern unsigned char _TIE_L8UI(const unsigned char * ars, immediate imm);
+extern unsigned short _TIE_L16UI(const unsigned short * ars, immediate imm);
+extern signed short _TIE_L16SI(const signed short * ars, immediate imm);
+extern unsigned _TIE_L32I(const unsigned * ars, immediate imm);
+extern void _TIE_S8I(unsigned char arr, unsigned char * ars, immediate imm);
+extern void _TIE_S16I(unsigned short arr, unsigned short * ars, immediate imm);
+extern void _TIE_S32I(unsigned arr, unsigned * ars, immediate imm);
+
+#define XT_L8UI  _TIE_L8UI
+#define XT_L16UI _TIE_L16UI
+#define XT_L16SI _TIE_L16SI
+#define XT_L32I  _TIE_L32I
+#define XT_S8I   _TIE_S8I
+#define XT_S16I  _TIE_S16I
+#define XT_S32I  _TIE_S32I
+
+/* Add-immediate instruction */
+extern unsigned _TIE_ADDI(unsigned ars, immediate imm);
+#define XT_ADDI  _TIE_ADDI
+
+/* Absolute value instruction */
+extern unsigned _TIE_ABS(int art);
+#define XT_ABS _TIE_ABS
+
+/* funnel shift instructions */
+extern unsigned _TIE_SRC(unsigned ars, unsigned art);
+#define XT_SRC _TIE_SRC
+extern void _TIE_SSR(unsigned ars);
+#define XT_SSR _TIE_SSR
+extern void _TIE_SSL(unsigned ars);
+#define XT_SSL _TIE_SSL
+extern void _TIE_SSA8B(unsigned ars);
+#define XT_SSA8B _TIE_SSA8B
+extern void _TIE_SSA8L(unsigned ars);
+#define XT_SSA8L _TIE_SSA8L
+extern void _TIE_SSAI(immediate imm);
+#define XT_SSAI _TIE_SSAI
+
+
+#endif /* __XCC__ */
+
+#endif /* __XTENSA__ */
+#endif /* !_XTENSA_BASE_HEADER */
diff --git a/include/asm-xtensa/xtensa/config-linux_be/specreg.h b/include/asm-xtensa/xtensa/config-linux_be/specreg.h
new file mode 100644
index 0000000..fa4106a
--- /dev/null
+++ b/include/asm-xtensa/xtensa/config-linux_be/specreg.h
@@ -0,0 +1,99 @@
+/*
+ * Xtensa Special Register symbolic names
+ */
+
+/* $Id: specreg.h,v 1.2 2003/03/07 19:15:18 joetaylor Exp $ */
+
+/*
+ * Copyright (c) 2003 Tensilica, Inc.  All Rights Reserved.
+ *
+ * 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 would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ * USA.
+ */
+
+#ifndef XTENSA_SPECREG_H
+#define XTENSA_SPECREG_H
+
+/*  Include these special register bitfield definitions, for historical reasons:  */
+#include <xtensa/corebits.h>
+
+
+/*  Special registers:  */
+#define LBEG		0
+#define LEND		1
+#define LCOUNT		2
+#define SAR		3
+#define WINDOWBASE	72
+#define WINDOWSTART	73
+#define PTEVADDR	83
+#define RASID		90
+#define ITLBCFG		91
+#define DTLBCFG		92
+#define IBREAKENABLE	96
+#define DDR		104
+#define IBREAKA_0	128
+#define IBREAKA_1	129
+#define DBREAKA_0	144
+#define DBREAKA_1	145
+#define DBREAKC_0	160
+#define DBREAKC_1	161
+#define EPC_1		177
+#define EPC_2		178
+#define EPC_3		179
+#define EPC_4		180
+#define DEPC		192
+#define EPS_2		194
+#define EPS_3		195
+#define EPS_4		196
+#define EXCSAVE_1	209
+#define EXCSAVE_2	210
+#define EXCSAVE_3	211
+#define EXCSAVE_4	212
+#define INTERRUPT	226
+#define INTENABLE	228
+#define PS		230
+#define EXCCAUSE	232
+#define DEBUGCAUSE	233
+#define CCOUNT		234
+#define ICOUNT		236
+#define ICOUNTLEVEL	237
+#define EXCVADDR	238
+#define CCOMPARE_0	240
+#define CCOMPARE_1	241
+#define CCOMPARE_2	242
+#define MISC_REG_0	244
+#define MISC_REG_1	245
+
+/*  Special cases (bases of special register series):  */
+#define IBREAKA		128
+#define DBREAKA		144
+#define DBREAKC		160
+#define EPC		176
+#define EPS		192
+#define EXCSAVE		208
+#define CCOMPARE	240
+
+/*  Special names for read-only and write-only interrupt registers:  */
+#define INTREAD		226
+#define INTSET		226
+#define INTCLEAR	227
+
+#endif /* XTENSA_SPECREG_H */
+
diff --git a/include/asm-xtensa/xtensa/config-linux_be/system.h b/include/asm-xtensa/xtensa/config-linux_be/system.h
new file mode 100644
index 0000000..cf9d4d3
--- /dev/null
+++ b/include/asm-xtensa/xtensa/config-linux_be/system.h
@@ -0,0 +1,198 @@
+/*
+ * xtensa/config/system.h -- HAL definitions that are dependent on SYSTEM configuration
+ *
+ *  NOTE: The location and contents of this file are highly subject to change.
+ *
+ *  Source for configuration-independent binaries (which link in a
+ *  configuration-specific HAL library) must NEVER include this file.
+ *  The HAL itself has historically included this file in some instances,
+ *  but this is not appropriate either, because the HAL is meant to be
+ *  core-specific but system independent.
+ */
+
+/*
+ * Copyright (c) 2003 Tensilica, Inc.  All Rights Reserved.
+ *
+ * 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 would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ * USA.
+ */
+
+
+#ifndef XTENSA_CONFIG_SYSTEM_H
+#define XTENSA_CONFIG_SYSTEM_H
+
+/*#include <xtensa/hal.h>*/
+
+
+
+/*----------------------------------------------------------------------
+				DEVICE ADDRESSES
+  ----------------------------------------------------------------------*/
+
+/*
+ *  Strange place to find these, but the configuration GUI
+ *  allows moving these around to account for various core
+ *  configurations.  Specific boards (and their BSP software)
+ *  will have specific meanings for these components.
+ */
+
+/*  I/O Block areas:  */
+#define XSHAL_IOBLOCK_CACHED_VADDR	0xE0000000
+#define XSHAL_IOBLOCK_CACHED_PADDR	0xF0000000
+#define XSHAL_IOBLOCK_CACHED_SIZE	0x0E000000
+
+#define XSHAL_IOBLOCK_BYPASS_VADDR	0xF0000000
+#define XSHAL_IOBLOCK_BYPASS_PADDR	0xF0000000
+#define XSHAL_IOBLOCK_BYPASS_SIZE	0x0E000000
+
+/*  System ROM:  */
+#define XSHAL_ROM_VADDR		0xEE000000
+#define XSHAL_ROM_PADDR		0xFE000000
+#define XSHAL_ROM_SIZE		0x00400000
+/*  Largest available area (free of vectors):  */
+#define XSHAL_ROM_AVAIL_VADDR	0xEE00052C
+#define XSHAL_ROM_AVAIL_VSIZE	0x003FFAD4
+
+/*  System RAM:  */
+#define XSHAL_RAM_VADDR		0xD0000000
+#define XSHAL_RAM_PADDR		0x00000000
+#define XSHAL_RAM_VSIZE		0x08000000
+#define XSHAL_RAM_PSIZE		0x10000000
+#define XSHAL_RAM_SIZE		XSHAL_RAM_PSIZE
+/*  Largest available area (free of vectors):  */
+#define XSHAL_RAM_AVAIL_VADDR	0xD0000370
+#define XSHAL_RAM_AVAIL_VSIZE	0x07FFFC90
+
+/*
+ *  Shadow system RAM (same device as system RAM, at different address).
+ *  (Emulation boards need this for the SONIC Ethernet driver
+ *   when data caches are configured for writeback mode.)
+ *  NOTE: on full MMU configs, this points to the BYPASS virtual address
+ *  of system RAM, ie. is the same as XSHAL_RAM_* except that virtual
+ *  addresses are viewed through the BYPASS static map rather than
+ *  the CACHED static map.
+ */
+#define XSHAL_RAM_BYPASS_VADDR		0xD8000000
+#define XSHAL_RAM_BYPASS_PADDR		0x00000000
+#define XSHAL_RAM_BYPASS_PSIZE		0x08000000
+
+/*  Alternate system RAM (different device than system RAM):  */
+#define XSHAL_ALTRAM_VADDR		0xCEE00000
+#define XSHAL_ALTRAM_PADDR		0xC0000000
+#define XSHAL_ALTRAM_SIZE		0x00200000
+
+
+/*----------------------------------------------------------------------
+ *			DEVICE-ADDRESS DEPENDENT...
+ *
+ *  Values written to CACHEATTR special register (or its equivalent)
+ *  to enable and disable caches in various modes.
+ *----------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------
+			BACKWARD COMPATIBILITY ...
+  ----------------------------------------------------------------------*/
+
+/*
+ *  NOTE:  the following two macros are DEPRECATED.  Use the latter
+ *  board-specific macros instead, which are specially tuned for the
+ *  particular target environments' memory maps.
+ */
+#define XSHAL_CACHEATTR_BYPASS		XSHAL_XT2000_CACHEATTR_BYPASS	/* disable caches in bypass mode */
+#define XSHAL_CACHEATTR_DEFAULT		XSHAL_XT2000_CACHEATTR_DEFAULT	/* default setting to enable caches (no writeback!) */
+
+/*----------------------------------------------------------------------
+			ISS (Instruction Set Simulator) SPECIFIC ...
+  ----------------------------------------------------------------------*/
+
+#define XSHAL_ISS_CACHEATTR_WRITEBACK	0x1122222F	/* enable caches in write-back mode */
+#define XSHAL_ISS_CACHEATTR_WRITEALLOC	0x1122222F	/* enable caches in write-allocate mode */
+#define XSHAL_ISS_CACHEATTR_WRITETHRU	0x1122222F	/* enable caches in write-through mode */
+#define XSHAL_ISS_CACHEATTR_BYPASS	0x2222222F	/* disable caches in bypass mode */
+#define XSHAL_ISS_CACHEATTR_DEFAULT	XSHAL_ISS_CACHEATTR_WRITEBACK	/* default setting to enable caches */
+
+/*  For Coware only:  */
+#define XSHAL_COWARE_CACHEATTR_WRITEBACK	0x11222222	/* enable caches in write-back mode */
+#define XSHAL_COWARE_CACHEATTR_WRITEALLOC	0x11222222	/* enable caches in write-allocate mode */
+#define XSHAL_COWARE_CACHEATTR_WRITETHRU	0x11222222	/* enable caches in write-through mode */
+#define XSHAL_COWARE_CACHEATTR_BYPASS		0x22222222	/* disable caches in bypass mode */
+#define XSHAL_COWARE_CACHEATTR_DEFAULT		XSHAL_COWARE_CACHEATTR_WRITEBACK	/* default setting to enable caches */
+
+/*  For BFM and other purposes:  */
+#define XSHAL_ALLVALID_CACHEATTR_WRITEBACK	0x11222222	/* enable caches without any invalid regions */
+#define XSHAL_ALLVALID_CACHEATTR_DEFAULT	XSHAL_ALLVALID_CACHEATTR_WRITEBACK	/* default setting for caches without any invalid regions */
+
+#define XSHAL_ISS_PIPE_REGIONS	0
+#define XSHAL_ISS_SDRAM_REGIONS	0
+
+
+/*----------------------------------------------------------------------
+			XT2000 BOARD SPECIFIC ...
+  ----------------------------------------------------------------------*/
+
+#define XSHAL_XT2000_CACHEATTR_WRITEBACK	0x22FFFFFF	/* enable caches in write-back mode */
+#define XSHAL_XT2000_CACHEATTR_WRITEALLOC	0x22FFFFFF	/* enable caches in write-allocate mode */
+#define XSHAL_XT2000_CACHEATTR_WRITETHRU	0x22FFFFFF	/* enable caches in write-through mode */
+#define XSHAL_XT2000_CACHEATTR_BYPASS		0x22FFFFFF	/* disable caches in bypass mode */
+#define XSHAL_XT2000_CACHEATTR_DEFAULT		XSHAL_XT2000_CACHEATTR_WRITEBACK	/* default setting to enable caches */
+
+#define XSHAL_XT2000_PIPE_REGIONS	0x00001000	/* BusInt pipeline regions */
+#define XSHAL_XT2000_SDRAM_REGIONS	0x00000005	/* BusInt SDRAM regions */
+
+
+/*----------------------------------------------------------------------
+				VECTOR SIZES
+  ----------------------------------------------------------------------*/
+
+/*
+ *  Sizes allocated to vectors by the system (memory map) configuration.
+ *  These sizes are constrained by core configuration (eg. one vector's
+ *  code cannot overflow into another vector) but are dependent on the
+ *  system or board (or LSP) memory map configuration.
+ *
+ *  Whether or not each vector happens to be in a system ROM is also
+ *  a system configuration matter, sometimes useful, included here also:
+ */
+#define XSHAL_RESET_VECTOR_SIZE	0x000004E0
+#define XSHAL_RESET_VECTOR_ISROM	1
+#define XSHAL_USER_VECTOR_SIZE	0x0000001C
+#define XSHAL_USER_VECTOR_ISROM	0
+#define XSHAL_PROGRAMEXC_VECTOR_SIZE	XSHAL_USER_VECTOR_SIZE	/* for backward compatibility */
+#define XSHAL_USEREXC_VECTOR_SIZE	XSHAL_USER_VECTOR_SIZE	/* for backward compatibility */
+#define XSHAL_KERNEL_VECTOR_SIZE	0x0000001C
+#define XSHAL_KERNEL_VECTOR_ISROM	0
+#define XSHAL_STACKEDEXC_VECTOR_SIZE	XSHAL_KERNEL_VECTOR_SIZE	/* for backward compatibility */
+#define XSHAL_KERNELEXC_VECTOR_SIZE	XSHAL_KERNEL_VECTOR_SIZE	/* for backward compatibility */
+#define XSHAL_DOUBLEEXC_VECTOR_SIZE	0x000000E0
+#define XSHAL_DOUBLEEXC_VECTOR_ISROM	0
+#define XSHAL_WINDOW_VECTORS_SIZE	0x00000180
+#define XSHAL_WINDOW_VECTORS_ISROM	0
+#define XSHAL_INTLEVEL2_VECTOR_SIZE	0x0000000C
+#define XSHAL_INTLEVEL2_VECTOR_ISROM	0
+#define XSHAL_INTLEVEL3_VECTOR_SIZE	0x0000000C
+#define XSHAL_INTLEVEL3_VECTOR_ISROM	0
+#define XSHAL_INTLEVEL4_VECTOR_SIZE	0x0000000C
+#define XSHAL_INTLEVEL4_VECTOR_ISROM	1
+#define XSHAL_DEBUG_VECTOR_SIZE		XSHAL_INTLEVEL4_VECTOR_SIZE
+#define XSHAL_DEBUG_VECTOR_ISROM	XSHAL_INTLEVEL4_VECTOR_ISROM
+
+
+#endif /*XTENSA_CONFIG_SYSTEM_H*/
+
diff --git a/include/asm-xtensa/xtensa/config-linux_be/tie.h b/include/asm-xtensa/xtensa/config-linux_be/tie.h
new file mode 100644
index 0000000..3c2e514
--- /dev/null
+++ b/include/asm-xtensa/xtensa/config-linux_be/tie.h
@@ -0,0 +1,275 @@
+/*
+ * xtensa/config/tie.h -- HAL definitions that are dependent on CORE and TIE configuration
+ *
+ *  This header file is sometimes referred to as the "compile-time HAL" or CHAL.
+ *  It was generated for a specific Xtensa processor configuration,
+ *  and furthermore for a specific set of TIE source files that extend
+ *  basic core functionality.
+ *
+ *  Source for configuration-independent binaries (which link in a
+ *  configuration-specific HAL library) must NEVER include this file.
+ *  It is perfectly normal, however, for the HAL source itself to include this file.
+ */
+
+/*
+ * Copyright (c) 2003 Tensilica, Inc.  All Rights Reserved.
+ *
+ * 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 would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
+ * USA.
+ */
+
+
+#ifndef XTENSA_CONFIG_TIE_H
+#define XTENSA_CONFIG_TIE_H
+
+#include <xtensa/hal.h>
+
+
+/*----------------------------------------------------------------------
+				GENERAL
+  ----------------------------------------------------------------------*/
+
+/*
+ *  Separators for macros that expand into arrays.
+ *  These can be predefined by files that #include this one,
+ *  when different separators are required.
+ */
+/*  Element separator for macros that expand into 1-dimensional arrays:  */
+#ifndef XCHAL_SEP
+#define XCHAL_SEP			,
+#endif
+/*  Array separator for macros that expand into 2-dimensional arrays:  */
+#ifndef XCHAL_SEP2
+#define XCHAL_SEP2			},{
+#endif
+
+
+
+
+
+
+/*----------------------------------------------------------------------
+			COPROCESSORS and EXTRA STATE
+  ----------------------------------------------------------------------*/
+
+#define XCHAL_CP_NUM			0	/* number of coprocessors */
+#define XCHAL_CP_MAX			0	/* max coprocessor id plus one (0 if none) */
+#define XCHAL_CP_MASK			0x00	/* bitmask of coprocessors by id */
+
+/*  Space for coprocessors' state save areas:  */
+#define XCHAL_CP0_SA_SIZE		0
+#define XCHAL_CP1_SA_SIZE		0
+#define XCHAL_CP2_SA_SIZE		0
+#define XCHAL_CP3_SA_SIZE		0
+#define XCHAL_CP4_SA_SIZE		0
+#define XCHAL_CP5_SA_SIZE		0
+#define XCHAL_CP6_SA_SIZE		0
+#define XCHAL_CP7_SA_SIZE		0
+/*  Minimum required alignments of CP state save areas:  */
+#define XCHAL_CP0_SA_ALIGN		1
+#define XCHAL_CP1_SA_ALIGN		1
+#define XCHAL_CP2_SA_ALIGN		1
+#define XCHAL_CP3_SA_ALIGN		1
+#define XCHAL_CP4_SA_ALIGN		1
+#define XCHAL_CP5_SA_ALIGN		1
+#define XCHAL_CP6_SA_ALIGN		1
+#define XCHAL_CP7_SA_ALIGN		1
+
+/*  Indexing macros:  */
+#define _XCHAL_CP_SA_SIZE(n)		XCHAL_CP ## n ## _SA_SIZE
+#define XCHAL_CP_SA_SIZE(n)		_XCHAL_CP_SA_SIZE(n)	/* n = 0 .. 7 */
+#define _XCHAL_CP_SA_ALIGN(n)		XCHAL_CP ## n ## _SA_ALIGN
+#define XCHAL_CP_SA_ALIGN(n)		_XCHAL_CP_SA_ALIGN(n)	/* n = 0 .. 7 */
+
+
+/*  Space for "extra" state (user special registers and non-cp TIE) save area:  */
+#define XCHAL_EXTRA_SA_SIZE		0
+#define XCHAL_EXTRA_SA_ALIGN		1
+
+/*  Total save area size (extra + all coprocessors)  */
+/*  (not useful until xthal_{save,restore}_all_extra() is implemented,  */
+/*   but included for Tor2 beta; doesn't account for alignment!):  */
+#define XCHAL_CPEXTRA_SA_SIZE_TOR2	0	/* Tor2Beta temporary definition -- do not use */
+
+/*  Combined required alignment for all CP and EXTRA state save areas  */
+/*  (does not include required alignment for any base config registers):  */
+#define XCHAL_CPEXTRA_SA_ALIGN		1
+
+/* ... */
+
+
+#ifdef _ASMLANGUAGE
+/*
+ *  Assembly-language specific definitions (assembly macros, etc.).
+ */
+#include <xtensa/config/specreg.h>
+
+/********************
+ *  Macros to save and restore the non-coprocessor TIE portion of EXTRA state.
+ */
+
+/* (none) */
+
+
+/********************
+ *  Macros to create functions that save and restore all EXTRA (non-coprocessor) state
+ *  (does not include zero-overhead loop registers and non-optional registers).
+ */
+
+	/*
+	 *  Macro that expands to the body of a function that
+	 *  stores the extra (non-coprocessor) optional/custom state.
+	 *	Entry:	a2 = ptr to save area in which to save extra state
+	 *	Exit:	any register a2-a15 (?) may have been clobbered.
+	 */
+	.macro	xchal_extra_store_funcbody
+	.endm
+
+
+	/*
+	 *  Macro that expands to the body of a function that
+	 *  loads the extra (non-coprocessor) optional/custom state.
+	 *	Entry:	a2 = ptr to save area from which to restore extra state
+	 *	Exit:	any register a2-a15 (?) may have been clobbered.
+	 */
+	.macro	xchal_extra_load_funcbody
+	.endm
+
+
+/********************
+ *  Macros to save and restore the state of each TIE coprocessor.
+ */
+
+
+
+/********************
+ *  Macros to create functions that save and restore the state of *any* TIE coprocessor.
+ */
+
+	/*
+	 *  Macro that expands to the body of a function
+	 *  that stores the selected coprocessor's state (registers etc).
+	 *	Entry:	a2 = ptr to save area in which to save cp state
+	 *		a3 = coprocessor number
+	 *	Exit:	any register a2-a15 (?) may have been clobbered.
+	 */
+	.macro	xchal_cpi_store_funcbody
+	.endm
+
+
+	/*
+	 *  Macro that expands to the body of a function
+	 *  that loads the selected coprocessor's state (registers etc).
+	 *	Entry:	a2 = ptr to save area from which to restore cp state
+	 *		a3 = coprocessor number
+	 *	Exit:	any register a2-a15 (?) may have been clobbered.
+	 */
+	.macro	xchal_cpi_load_funcbody
+	.endm
+
+#endif /*_ASMLANGUAGE*/
+
+
+/*
+ *  Contents of save areas in terms of libdb register numbers.
+ *  NOTE:  CONTENTS_LIBDB_{UREG,REGF} macros are not defined in this file;
+ *  it is up to the user of this header file to define these macros
+ *  usefully before each expansion of the CONTENTS_LIBDB macros.
+ *  (Fields rsv[123] are reserved for future additions; they are currently
+ *   set to zero but may be set to some useful values in the future.)
+ *
+ *	CONTENTS_LIBDB_SREG(libdbnum, offset, size, align, rsv1, name, sregnum, bitmask, rsv2, rsv3)
+ *	CONTENTS_LIBDB_UREG(libdbnum, offset, size, align, rsv1, name, uregnum, bitmask, rsv2, rsv3)
+ *	CONTENTS_LIBDB_REGF(libdbnum, offset, size, align, rsv1, name, index, numentries, contentsize, regname_base, regfile_name, rsv2, rsv3)
+ */
+
+#define XCHAL_EXTRA_SA_CONTENTS_LIBDB_NUM	0
+#define XCHAL_EXTRA_SA_CONTENTS_LIBDB	/* empty */
+
+#define XCHAL_CP0_SA_CONTENTS_LIBDB_NUM	0
+#define XCHAL_CP0_SA_CONTENTS_LIBDB	/* empty */
+
+#define XCHAL_CP1_SA_CONTENTS_LIBDB_NUM	0
+#define XCHAL_CP1_SA_CONTENTS_LIBDB	/* empty */
+
+#define XCHAL_CP2_SA_CONTENTS_LIBDB_NUM	0
+#define XCHAL_CP2_SA_CONTENTS_LIBDB	/* empty */
+
+#define XCHAL_CP3_SA_CONTENTS_LIBDB_NUM	0
+#define XCHAL_CP3_SA_CONTENTS_LIBDB	/* empty */
+
+#define XCHAL_CP4_SA_CONTENTS_LIBDB_NUM	0
+#define XCHAL_CP4_SA_CONTENTS_LIBDB	/* empty */
+
+#define XCHAL_CP5_SA_CONTENTS_LIBDB_NUM	0
+#define XCHAL_CP5_SA_CONTENTS_LIBDB	/* empty */
+
+#define XCHAL_CP6_SA_CONTENTS_LIBDB_NUM	0
+#define XCHAL_CP6_SA_CONTENTS_LIBDB	/* empty */
+
+#define XCHAL_CP7_SA_CONTENTS_LIBDB_NUM	0
+#define XCHAL_CP7_SA_CONTENTS_LIBDB	/* empty */
+
+
+
+
+
+
+/*----------------------------------------------------------------------
+				MISC
+  ----------------------------------------------------------------------*/
+
+#if 0	/* is there something equivalent for user TIE? */
+#define XCHAL_CORE_ID			"linux_be"	/* configuration's alphanumeric core identifier
+							   (CoreID) set in the Xtensa Processor Generator */
+
+#define XCHAL_BUILD_UNIQUE_ID		0x00003256	/* software build-unique ID (22-bit) */
+
+/*  These definitions describe the hardware targeted by this software:  */
+#define XCHAL_HW_CONFIGID0		0xC103D1FF	/* config ID reg 0 value (upper 32 of 64 bits) */
+#define XCHAL_HW_CONFIGID1		0x00803256	/* config ID reg 1 value (lower 32 of 64 bits) */
+#define XCHAL_CONFIGID0			XCHAL_HW_CONFIGID0	/* for backward compatibility only -- don't use! */
+#define XCHAL_CONFIGID1			XCHAL_HW_CONFIGID1	/* for backward compatibility only -- don't use! */
+#define XCHAL_HW_RELEASE_MAJOR		1050	/* major release of targeted hardware */
+#define XCHAL_HW_RELEASE_MINOR		1	/* minor release of targeted hardware */
+#define XCHAL_HW_RELEASE_NAME		"T1050.1"	/* full release name of targeted hardware */
+#define XTHAL_HW_REL_T1050	1
+#define XTHAL_HW_REL_T1050_1	1
+#define XCHAL_HW_CONFIGID_RELIABLE	1
+#endif /*0*/
+
+
+
+/*----------------------------------------------------------------------
+				ISA
+  ----------------------------------------------------------------------*/
+
+#if 0	/* these probably don't belong here, but are related to or implemented using TIE */
+#define XCHAL_HAVE_BOOLEANS		0	/* 1 if booleans option configured, 0 otherwise */
+/*  Misc instructions:  */
+#define XCHAL_HAVE_MUL32		0	/* 1 if 32-bit integer multiply option configured, 0 otherwise */
+#define XCHAL_HAVE_MUL32_HIGH		0	/* 1 if MUL32 option includes MULUH and MULSH, 0 otherwise */
+
+#define XCHAL_HAVE_FP			0	/* 1 if floating point option configured, 0 otherwise */
+#endif /*0*/
+
+
+#endif /*XTENSA_CONFIG_TIE_H*/
+
diff --git a/include/asm-xtensa/xtensa/coreasm.h b/include/asm-xtensa/xtensa/coreasm.h
new file mode 100644
index 0000000..a8cfb54
--- /dev/null
+++ b/include/asm-xtensa/xtensa/coreasm.h
@@ -0,0 +1,526 @@
+#ifndef XTENSA_COREASM_H
+#define XTENSA_COREASM_H
+
+/*
+ * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
+ *
+ * include/asm-xtensa/xtensa/coreasm.h -- assembler-specific
+ * definitions that depend on CORE configuration.
+ *
+ * Source for configuration-independent binaries (which link in a
+ * configuration-specific HAL library) must NEVER include this file.
+ * It is perfectly normal, however, for the HAL itself to include this
+ * file.
+ *
+ * This file must NOT include xtensa/config/system.h.  Any assembler
+ * header file that depends on system information should likely go in
+ * a new systemasm.h (or sysasm.h) header file.
+ *
+ *  NOTE: macro beqi32 is NOT configuration-dependent, and is placed
+ *        here til we will have configuration-independent header file.
+ *
+ * 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) 2002 Tensilica Inc.
+ */
+
+
+#include <xtensa/config/core.h>
+#include <xtensa/config/specreg.h>
+
+/*
+ *  Assembly-language specific definitions (assembly macros, etc.).
+ */
+
+/*----------------------------------------------------------------------
+ *  find_ms_setbit
+ *
+ *  This macro finds the most significant bit that is set in <as>
+ *  and return its index + <base> in <ad>, or <base> - 1 if <as> is zero.
+ *  The index counts starting at zero for the lsbit, so the return
+ *  value ranges from <base>-1 (no bit set) to <base>+31 (msbit set).
+ *
+ *  Parameters:
+ *	<ad>	destination address register (any register)
+ *	<as>	source address register
+ *	<at>	temporary address register (must be different than <as>)
+ *	<base>	constant value added to result (usually 0 or 1)
+ *  On entry:
+ *	<ad> = undefined if different than <as>
+ *	<as> = value whose most significant set bit is to be found
+ *	<at> = undefined
+ *	no other registers are used by this macro.
+ *  On exit:
+ *	<ad> = <base> + index of msbit set in original <as>,
+ *	     = <base> - 1 if original <as> was zero.
+ *	<as> clobbered (if not <ad>)
+ *	<at> clobbered (if not <ad>)
+ *  Example:
+ *	find_ms_setbit a0, a4, a0, 0		-- return in a0 index of msbit set in a4
+ */
+
+	.macro	find_ms_setbit ad, as, at, base
+#if XCHAL_HAVE_NSA
+	movi	\at, 31+\base
+	nsau	\as, \as	// get index of \as, numbered from msbit (32 if absent)
+	sub	\ad, \at, \as	// get numbering from lsbit (0..31, -1 if absent)
+#else /* XCHAL_HAVE_NSA */
+	movi	\at, \base	// start with result of 0 (point to lsbit of 32)
+
+	beqz	\as, 2f		// special case for zero argument: return -1
+	bltui	\as, 0x10000, 1f	// is it one of the 16 lsbits? (if so, check lower 16 bits)
+	addi	\at, \at, 16	// no, increment result to upper 16 bits (of 32)
+	//srli	\as, \as, 16	// check upper half (shift right 16 bits)
+	extui	\as, \as, 16, 16	// check upper half (shift right 16 bits)
+1:	bltui	\as, 0x100, 1f	// is it one of the 8 lsbits? (if so, check lower 8 bits)
+	addi	\at, \at, 8	// no, increment result to upper 8 bits (of 16)
+	srli	\as, \as, 8	// shift right to check upper 8 bits
+1:	bltui	\as, 0x10, 1f	// is it one of the 4 lsbits? (if so, check lower 4 bits)
+	addi	\at, \at, 4	// no, increment result to upper 4 bits (of 8)
+	srli	\as, \as, 4	// shift right 4 bits to check upper half
+1:	bltui	\as, 0x4, 1f	// is it one of the 2 lsbits? (if so, check lower 2 bits)
+	addi	\at, \at, 2	// no, increment result to upper 2 bits (of 4)
+	srli	\as, \as, 2	// shift right 2 bits to check upper half
+1:	bltui	\as, 0x2, 1f	// is it the lsbit?
+	addi	\at, \at, 2	// no, increment result to upper bit (of 2)
+2:	addi	\at, \at, -1	// (from just above: add 1;  from beqz: return -1)
+	//srli	\as, \as, 1
+1:				// done! \at contains index of msbit set (or -1 if none set)
+	.if	0x\ad - 0x\at	// destination different than \at ? (works because regs are a0-a15)
+	mov	\ad, \at	// then move result to \ad
+	.endif
+#endif /* XCHAL_HAVE_NSA */
+	.endm	// find_ms_setbit
+
+/*----------------------------------------------------------------------
+ *  find_ls_setbit
+ *
+ *  This macro finds the least significant bit that is set in <as>,
+ *  and return its index in <ad>.
+ *  Usage is the same as for the find_ms_setbit macro.
+ *  Example:
+ *	find_ls_setbit a0, a4, a0, 0	-- return in a0 index of lsbit set in a4
+ */
+
+	.macro	find_ls_setbit ad, as, at, base
+	neg	\at, \as	// keep only the least-significant bit that is set...
+	and	\as, \at, \as	// ... in \as
+	find_ms_setbit	\ad, \as, \at, \base
+	.endm	// find_ls_setbit
+
+/*----------------------------------------------------------------------
+ *  find_ls_one
+ *
+ *  Same as find_ls_setbit with base zero.
+ *  Source (as) and destination (ad) registers must be different.
+ *  Provided for backward compatibility.
+ */
+
+	.macro	find_ls_one ad, as
+	find_ls_setbit	\ad, \as, \ad, 0
+	.endm	// find_ls_one
+
+/*----------------------------------------------------------------------
+ *  floop, floopnez, floopgtz, floopend
+ *
+ *  These macros are used for fast inner loops that
+ *  work whether or not the Loops options is configured.
+ *  If the Loops option is configured, they simply use
+ *  the zero-overhead LOOP instructions; otherwise
+ *  they use explicit decrement and branch instructions.
+ *
+ *  They are used in pairs, with floop, floopnez or floopgtz
+ *  at the beginning of the loop, and floopend at the end.
+ *
+ *  Each pair of loop macro calls must be given the loop count
+ *  address register and a unique label for that loop.
+ *
+ *  Example:
+ *
+ *	movi	 a3, 16     // loop 16 times
+ *	floop    a3, myloop1
+ *	:
+ *	bnez     a7, end1	// exit loop if a7 != 0
+ *	:
+ *	floopend a3, myloop1
+ *  end1:
+ *
+ *  Like the LOOP instructions, these macros cannot be
+ *  nested, must include at least one instruction,
+ *  cannot call functions inside the loop, etc.
+ *  The loop can be exited by jumping to the instruction
+ *  following floopend (or elsewhere outside the loop),
+ *  or continued by jumping to a NOP instruction placed
+ *  immediately before floopend.
+ *
+ *  Unlike LOOP instructions, the register passed to floop*
+ *  cannot be used inside the loop, because it is used as
+ *  the loop counter if the Loops option is not configured.
+ *  And its value is undefined after exiting the loop.
+ *  And because the loop counter register is active inside
+ *  the loop, you can't easily use this construct to loop
+ *  across a register file using ROTW as you might with LOOP
+ *  instructions, unless you copy the loop register along.
+ */
+
+	/*  Named label version of the macros:  */
+
+	.macro	floop		ar, endlabel
+	floop_		\ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel
+	.endm
+
+	.macro	floopnez	ar, endlabel
+	floopnez_	\ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel
+	.endm
+
+	.macro	floopgtz	ar, endlabel
+	floopgtz_	\ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel
+	.endm
+
+	.macro	floopend	ar, endlabel
+	floopend_	\ar, .Lfloopstart_\endlabel, .Lfloopend_\endlabel
+	.endm
+
+	/*  Numbered local label version of the macros:  */
+#if 0 /*UNTESTED*/
+	.macro	floop89		ar
+	floop_		\ar, 8, 9f
+	.endm
+
+	.macro	floopnez89	ar
+	floopnez_	\ar, 8, 9f
+	.endm
+
+	.macro	floopgtz89	ar
+	floopgtz_	\ar, 8, 9f
+	.endm
+
+	.macro	floopend89	ar
+	floopend_	\ar, 8b, 9
+	.endm
+#endif /*0*/
+
+	/*  Underlying version of the macros:  */
+
+	.macro	floop_	ar, startlabel, endlabelref
+	.ifdef	_infloop_
+	.if	_infloop_
+	.err	// Error: floop cannot be nested
+	.endif
+	.endif
+	.set	_infloop_, 1
+#if XCHAL_HAVE_LOOPS
+	loop	\ar, \endlabelref
+#else /* XCHAL_HAVE_LOOPS */
+\startlabel:
+	addi	\ar, \ar, -1
+#endif /* XCHAL_HAVE_LOOPS */
+	.endm	// floop_
+
+	.macro	floopnez_	ar, startlabel, endlabelref
+	.ifdef	_infloop_
+	.if	_infloop_
+	.err	// Error: floopnez cannot be nested
+	.endif
+	.endif
+	.set	_infloop_, 1
+#if XCHAL_HAVE_LOOPS
+	loopnez	\ar, \endlabelref
+#else /* XCHAL_HAVE_LOOPS */
+	beqz	\ar, \endlabelref
+\startlabel:
+	addi	\ar, \ar, -1
+#endif /* XCHAL_HAVE_LOOPS */
+	.endm	// floopnez_
+
+	.macro	floopgtz_	ar, startlabel, endlabelref
+	.ifdef	_infloop_
+	.if	_infloop_
+	.err	// Error: floopgtz cannot be nested
+	.endif
+	.endif
+	.set	_infloop_, 1
+#if XCHAL_HAVE_LOOPS
+	loopgtz	\ar, \endlabelref
+#else /* XCHAL_HAVE_LOOPS */
+	bltz	\ar, \endlabelref
+	beqz	\ar, \endlabelref
+\startlabel:
+	addi	\ar, \ar, -1
+#endif /* XCHAL_HAVE_LOOPS */
+	.endm	// floopgtz_
+
+
+	.macro	floopend_	ar, startlabelref, endlabel
+	.ifndef	_infloop_
+	.err	// Error: floopend without matching floopXXX
+	.endif
+	.ifeq	_infloop_
+	.err	// Error: floopend without matching floopXXX
+	.endif
+	.set	_infloop_, 0
+#if ! XCHAL_HAVE_LOOPS
+	bnez	\ar, \startlabelref
+#endif /* XCHAL_HAVE_LOOPS */
+\endlabel:
+	.endm	// floopend_
+
+/*----------------------------------------------------------------------
+ *  crsil  --  conditional RSIL (read/set interrupt level)
+ *
+ *  Executes the RSIL instruction if it exists, else just reads PS.
+ *  The RSIL instruction does not exist in the new exception architecture
+ *  if the interrupt option is not selected.
+ */
+
+	.macro	crsil	ar, newlevel
+#if XCHAL_HAVE_OLD_EXC_ARCH || XCHAL_HAVE_INTERRUPTS
+	rsil	\ar, \newlevel
+#else
+	rsr	\ar, PS
+#endif
+	.endm	// crsil
+
+/*----------------------------------------------------------------------
+ *  window_spill{4,8,12}
+ *
+ *  These macros spill callers' register windows to the stack.
+ *  They work for both privileged and non-privileged tasks.
+ *  Must be called from a windowed ABI context, eg. within
+ *  a windowed ABI function (ie. valid stack frame, window
+ *  exceptions enabled, not in exception mode, etc).
+ *
+ *  This macro requires a single invocation of the window_spill_common
+ *  macro in the same assembly unit and section.
+ *
+ *  Note that using window_spill{4,8,12} macros is more efficient
+ *  than calling a function implemented using window_spill_function,
+ *  because the latter needs extra code to figure out the size of
+ *  the call to the spilling function.
+ *
+ *  Example usage:
+ *
+ *		.text
+ *		.align	4
+ *		.global	some_function
+ *		.type	some_function,@function
+ *	some_function:
+ *		entry	a1, 16
+ *		:
+ *		:
+ *
+ *		window_spill4	// spill windows of some_function's callers; preserves a0..a3 only;
+ *				// to use window_spill{8,12} in this example function we'd have
+ *				// to increase space allocated by the entry instruction, because
+ *				// 16 bytes only allows call4; 32 or 48 bytes (+locals) are needed
+ *				// for call8/window_spill8 or call12/window_spill12 respectively.
+ *		:
+ *
+ *		retw
+ *
+ *		window_spill_common	// instantiates code used by window_spill4
+ *
+ *
+ *  On entry:
+ *	none (if window_spill4)
+ *	stack frame has enough space allocated for call8 (if window_spill8)
+ *	stack frame has enough space allocated for call12 (if window_spill12)
+ *  On exit:
+ *	 a4..a15 clobbered (if window_spill4)
+ *	 a8..a15 clobbered (if window_spill8)
+ *	a12..a15 clobbered (if window_spill12)
+ *	no caller windows are in live registers
+ */
+
+	.macro	window_spill4
+#if XCHAL_HAVE_WINDOWED
+# if XCHAL_NUM_AREGS == 16
+	movi	a15, 0			// for 16-register files, no need to call to reach the end
+# elif XCHAL_NUM_AREGS == 32
+	call4	.L__wdwspill_assist28	// call deep enough to clear out any live callers
+# elif XCHAL_NUM_AREGS == 64
+	call4	.L__wdwspill_assist60	// call deep enough to clear out any live callers
+# endif
+#endif
+	.endm	// window_spill4
+
+	.macro	window_spill8
+#if XCHAL_HAVE_WINDOWED
+# if XCHAL_NUM_AREGS == 16
+	movi	a15, 0			// for 16-register files, no need to call to reach the end
+# elif XCHAL_NUM_AREGS == 32
+	call8	.L__wdwspill_assist24	// call deep enough to clear out any live callers
+# elif XCHAL_NUM_AREGS == 64
+	call8	.L__wdwspill_assist56	// call deep enough to clear out any live callers
+# endif
+#endif
+	.endm	// window_spill8
+
+	.macro	window_spill12
+#if XCHAL_HAVE_WINDOWED
+# if XCHAL_NUM_AREGS == 16
+	movi	a15, 0			// for 16-register files, no need to call to reach the end
+# elif XCHAL_NUM_AREGS == 32
+	call12	.L__wdwspill_assist20	// call deep enough to clear out any live callers
+# elif XCHAL_NUM_AREGS == 64
+	call12	.L__wdwspill_assist52	// call deep enough to clear out any live callers
+# endif
+#endif
+	.endm	// window_spill12
+
+/*----------------------------------------------------------------------
+ *  window_spill_function
+ *
+ *  This macro outputs a function that will spill its caller's callers'
+ *  register windows to the stack.  Eg. it could be used to implement
+ *  a version of xthal_window_spill() that works in non-privileged tasks.
+ *  This works for both privileged and non-privileged tasks.
+ *
+ *  Typical usage:
+ *
+ *		.text
+ *		.align	4
+ *		.global	my_spill_function
+ *		.type	my_spill_function,@function
+ *	my_spill_function:
+ *		window_spill_function
+ *
+ *  On entry to resulting function:
+ *	none
+ *  On exit from resulting function:
+ *	none (no caller windows are in live registers)
+ */
+
+	.macro	window_spill_function
+#if XCHAL_HAVE_WINDOWED
+# if XCHAL_NUM_AREGS == 32
+	entry	sp, 48
+	bbci.l	a0, 31, 1f		// branch if called with call4
+	bbsi.l	a0, 30, 2f		// branch if called with call12
+	call8	.L__wdwspill_assist16	// called with call8, only need another 8
+	retw
+1:	call12	.L__wdwspill_assist16	// called with call4, only need another 12
+	retw
+2:	call4	.L__wdwspill_assist16	// called with call12, only need another 4
+	retw
+# elif XCHAL_NUM_AREGS == 64
+	entry	sp, 48
+	bbci.l	a0, 31, 1f		// branch if called with call4
+	bbsi.l	a0, 30, 2f		// branch if called with call12
+	call4	.L__wdwspill_assist52	// called with call8, only need a call4
+	retw
+1:	call8	.L__wdwspill_assist52	// called with call4, only need a call8
+	retw
+2:	call12	.L__wdwspill_assist40	// called with call12, can skip a call12
+	retw
+# elif XCHAL_NUM_AREGS == 16
+	entry	sp, 16
+	bbci.l	a0, 31, 1f	// branch if called with call4
+	bbsi.l	a0, 30, 2f	// branch if called with call12
+	movi	a7, 0		// called with call8
+	retw
+1:	movi	a11, 0		// called with call4
+2:	retw			// if called with call12, everything already spilled
+
+//	movi	a15, 0		// trick to spill all but the direct caller
+//	j	1f
+//	//  The entry instruction is magical in the assembler (gets auto-aligned)
+//	//  so we have to jump to it to avoid falling through the padding.
+//	//  We need entry/retw to know where to return.
+//1:	entry	sp, 16
+//	retw
+# else
+#  error "unrecognized address register file size"
+# endif
+#endif /* XCHAL_HAVE_WINDOWED */
+	window_spill_common
+	.endm	// window_spill_function
+
+/*----------------------------------------------------------------------
+ *  window_spill_common
+ *
+ *  Common code used by any number of invocations of the window_spill##
+ *  and window_spill_function macros.
+ *
+ *  Must be instantiated exactly once within a given assembly unit,
+ *  within call/j range of and same section as window_spill##
+ *  macro invocations for that assembly unit.
+ *  (Is automatically instantiated by the window_spill_function macro.)
+ */
+
+	.macro	window_spill_common
+#if XCHAL_HAVE_WINDOWED && (XCHAL_NUM_AREGS == 32 || XCHAL_NUM_AREGS == 64)
+	.ifndef	.L__wdwspill_defined
+# if XCHAL_NUM_AREGS >= 64
+.L__wdwspill_assist60:
+	entry	sp, 32
+	call8	.L__wdwspill_assist52
+	retw
+.L__wdwspill_assist56:
+	entry	sp, 16
+	call4	.L__wdwspill_assist52
+	retw
+.L__wdwspill_assist52:
+	entry	sp, 48
+	call12	.L__wdwspill_assist40
+	retw
+.L__wdwspill_assist40:
+	entry	sp, 48
+	call12	.L__wdwspill_assist28
+	retw
+# endif
+.L__wdwspill_assist28:
+	entry	sp, 48
+	call12	.L__wdwspill_assist16
+	retw
+.L__wdwspill_assist24:
+	entry	sp, 32
+	call8	.L__wdwspill_assist16
+	retw
+.L__wdwspill_assist20:
+	entry	sp, 16
+	call4	.L__wdwspill_assist16
+	retw
+.L__wdwspill_assist16:
+	entry	sp, 16
+	movi	a15, 0
+	retw
+	.set	.L__wdwspill_defined, 1
+	.endif
+#endif /* XCHAL_HAVE_WINDOWED with 32 or 64 aregs */
+	.endm	// window_spill_common
+
+/*----------------------------------------------------------------------
+ *  beqi32
+ *
+ *  macro implements version of beqi for arbitrary 32-bit immidiate value
+ *
+ *     beqi32 ax, ay, imm32, label
+ *
+ *  Compares value in register ax with imm32 value and jumps to label if
+ *  equal. Clobberes register ay if needed
+ *
+ */
+   .macro beqi32	ax, ay, imm, label
+    .ifeq ((\imm-1) & ~7)	// 1..8 ?
+		beqi	\ax, \imm, \label
+    .else
+      .ifeq (\imm+1)		// -1 ?
+		beqi	\ax, \imm, \label
+      .else
+        .ifeq (\imm)		// 0 ?
+		beqz	\ax, \label
+        .else
+		//  We could also handle immediates 10,12,16,32,64,128,256
+		//  but it would be a long macro...
+		movi	\ay, \imm
+		beq	\ax, \ay, \label
+        .endif
+      .endif
+    .endif
+   .endm // beqi32
+
+#endif /*XTENSA_COREASM_H*/
+
diff --git a/include/asm-xtensa/xtensa/corebits.h b/include/asm-xtensa/xtensa/corebits.h
new file mode 100644
index 0000000..e578ade
--- /dev/null
+++ b/include/asm-xtensa/xtensa/corebits.h
@@ -0,0 +1,77 @@
+#ifndef XTENSA_COREBITS_H
+#define XTENSA_COREBITS_H
+
+/*
+ * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
+ *
+ * xtensa/corebits.h - Xtensa Special Register field positions and masks.
+ *
+ * (In previous releases, these were defined in specreg.h, a generated file.
+ *  This file is not generated, i.e. it is processor configuration independent.)
+ */
+
+
+/*  EXCCAUSE register fields:  */
+#define EXCCAUSE_EXCCAUSE_SHIFT	0
+#define EXCCAUSE_EXCCAUSE_MASK	0x3F
+/*  Exception causes (mostly incomplete!):  */
+#define EXCCAUSE_ILLEGAL		0
+#define EXCCAUSE_SYSCALL		1
+#define EXCCAUSE_IFETCHERROR		2
+#define EXCCAUSE_LOADSTOREERROR		3
+#define EXCCAUSE_LEVEL1INTERRUPT	4
+#define EXCCAUSE_ALLOCA			5
+
+/*  PS register fields:  */
+#define PS_WOE_SHIFT		18
+#define PS_WOE_MASK		0x00040000
+#define PS_WOE			PS_WOE_MASK
+#define PS_CALLINC_SHIFT	16
+#define PS_CALLINC_MASK		0x00030000
+#define PS_CALLINC(n)		(((n)&3)<<PS_CALLINC_SHIFT)	/* n = 0..3 */
+#define PS_OWB_SHIFT		8
+#define PS_OWB_MASK		0x00000F00
+#define PS_OWB(n)		(((n)&15)<<PS_OWB_SHIFT)	/* n = 0..15 (or 0..7) */
+#define PS_RING_SHIFT		6
+#define PS_RING_MASK		0x000000C0
+#define PS_RING(n)		(((n)&3)<<PS_RING_SHIFT)	/* n = 0..3 */
+#define PS_UM_SHIFT		5
+#define PS_UM_MASK		0x00000020
+#define PS_UM			PS_UM_MASK
+#define PS_EXCM_SHIFT		4
+#define PS_EXCM_MASK		0x00000010
+#define PS_EXCM			PS_EXCM_MASK
+#define PS_INTLEVEL_SHIFT	0
+#define PS_INTLEVEL_MASK	0x0000000F
+#define PS_INTLEVEL(n)		((n)&PS_INTLEVEL_MASK)		/* n = 0..15 */
+/*  Backward compatibility (deprecated):  */
+#define PS_PROGSTACK_SHIFT	PS_UM_SHIFT
+#define PS_PROGSTACK_MASK	PS_UM_MASK
+#define PS_PROG_SHIFT		PS_UM_SHIFT
+#define PS_PROG_MASK		PS_UM_MASK
+#define PS_PROG			PS_UM
+
+/*  DBREAKCn register fields:  */
+#define DBREAKC_MASK_SHIFT		0
+#define DBREAKC_MASK_MASK		0x0000003F
+#define DBREAKC_LOADBREAK_SHIFT		30
+#define DBREAKC_LOADBREAK_MASK		0x40000000
+#define DBREAKC_STOREBREAK_SHIFT	31
+#define DBREAKC_STOREBREAK_MASK		0x80000000
+
+/*  DEBUGCAUSE register fields:  */
+#define DEBUGCAUSE_DEBUGINT_SHIFT	5
+#define DEBUGCAUSE_DEBUGINT_MASK	0x20	/* debug interrupt */
+#define DEBUGCAUSE_BREAKN_SHIFT		4
+#define DEBUGCAUSE_BREAKN_MASK		0x10	/* BREAK.N instruction */
+#define DEBUGCAUSE_BREAK_SHIFT		3
+#define DEBUGCAUSE_BREAK_MASK		0x08	/* BREAK instruction */
+#define DEBUGCAUSE_DBREAK_SHIFT		2
+#define DEBUGCAUSE_DBREAK_MASK		0x04	/* DBREAK match */
+#define DEBUGCAUSE_IBREAK_SHIFT		1
+#define DEBUGCAUSE_IBREAK_MASK		0x02	/* IBREAK match */
+#define DEBUGCAUSE_ICOUNT_SHIFT		0
+#define DEBUGCAUSE_ICOUNT_MASK		0x01	/* ICOUNT would increment to zero */
+
+#endif /*XTENSA_COREBITS_H*/
+
diff --git a/include/asm-xtensa/xtensa/hal.h b/include/asm-xtensa/xtensa/hal.h
new file mode 100644
index 0000000..d104725
--- /dev/null
+++ b/include/asm-xtensa/xtensa/hal.h
@@ -0,0 +1,822 @@
+#ifndef XTENSA_HAL_H
+#define XTENSA_HAL_H
+
+/*
+ * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
+ *
+ * include/asm-xtensa/xtensa/hal.h -- contains a definition of the
+ * Core HAL interface.
+ *
+ * All definitions in this header file are independent of any specific
+ * Xtensa processor configuration.  Thus an OS or other software can
+ * include this header file and be compiled into configuration-
+ * independent objects that can be distributed and eventually linked
+ * to the HAL library (libhal.a) to create a configuration-specific
+ * final executable.
+ *
+ * Certain definitions, however, are release-specific -- such as the
+ * XTHAL_RELEASE_xxx macros (or additions made in later releases).
+ *
+ * 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) 2002 Tensilica Inc.
+ */
+
+
+/*----------------------------------------------------------------------
+  			 Constant Definitions
+			(shared with assembly)
+  ----------------------------------------------------------------------*/
+
+/*  Software release information (not configuration-specific!):  */
+#define XTHAL_RELEASE_MAJOR	1050
+#define XTHAL_RELEASE_MINOR	0
+#define XTHAL_RELEASE_NAME	"T1050.0-2002-08-06-eng0"
+#define XTHAL_RELEASE_INTERNAL	"2002-08-06-eng0"
+#define XTHAL_REL_T1050	1
+#define XTHAL_REL_T1050_0	1
+#define XTHAL_REL_T1050_0_2002	1
+#define XTHAL_REL_T1050_0_2002_08	1
+#define XTHAL_REL_T1050_0_2002_08_06	1
+#define XTHAL_REL_T1050_0_2002_08_06_ENG0	1
+
+/*  HAL version numbers (these names are for backward compatibility):  */
+#define XTHAL_MAJOR_REV		XTHAL_RELEASE_MAJOR
+#define XTHAL_MINOR_REV		XTHAL_RELEASE_MINOR
+/*
+ *  A bit of software release history on values of XTHAL_{MAJOR,MINOR}_REV:
+ *
+ *	Release		MAJOR	MINOR		Comment
+ *	=======		=====	=====		=======
+ *	T1015.n		n/a	n/a		(HAL not yet available)
+ *	T1020.{0,1,2}	0	1		(HAL beta)
+ *	T1020.{3,4}	0	2		First release.
+ *	T1020.n (n>4)	0	2 or >3		(TBD)
+ *	T1030.0		0	1		(HAL beta)
+ *	T1030.{1,2}	0	3		Equivalent to first release.
+ *	T1030.n (n>=3)	0	>= 3		(TBD)
+ *	T1040.n		1040	n		Full CHAL available from T1040.2
+ *	T1050.n		1050	n		Current release.
+ *
+ *
+ *  Note:  there is a distinction between the software release with
+ *  which something is compiled (accessible using XTHAL_RELEASE_* macros)
+ *  and the software release with which the HAL library was compiled
+ *  (accessible using Xthal_release_* global variables).  This
+ *  distinction is particularly relevant for vendors that distribute
+ *  configuration-independent binaries (eg. an OS), where their customer
+ *  might link it with a HAL of a different Xtensa software release.
+ *  In this case, it may be appropriate for the OS to verify at run-time
+ *  whether XTHAL_RELEASE_* and Xthal_release_* are compatible.
+ *  [Guidelines as to which release is compatible with which are not
+ *  currently provided explicitly, but might be inferred from reading
+ *  OSKit documentation for all releases -- compatibility is also highly
+ *  dependent on which HAL features are used.  Each release is usually
+ *  backward compatible, with very few exceptions if any.]
+ *
+ *  Notes:
+ *	Tornado 2.0 supported in T1020.3+, T1030.1+, and T1040.{0,1} only.
+ *	Tornado 2.0.2 supported in T1040.2+, and T1050.
+ *	Compile-time HAL port of NucleusPlus supported by T1040.2+ and T1050.
+ */
+
+
+/*
+ *  Architectural limits, independent of configuration.
+ *  Note that these are ISA-defined limits, not micro-architecture implementation
+ *  limits enforced by the Xtensa Processor Generator (which may be stricter than
+ *  these below).
+ */
+#define XTHAL_MAX_CPS		8	/* max number of coprocessors (0..7) */
+#define XTHAL_MAX_INTERRUPTS	32	/* max number of interrupts (0..31) */
+#define XTHAL_MAX_INTLEVELS	16	/* max number of interrupt levels (0..15) */
+					/* (as of T1040, implementation limit is 7: 0..6) */
+#define XTHAL_MAX_TIMERS	4	/* max number of timers (CCOMPARE0..CCOMPARE3) */
+					/* (as of T1040, implementation limit is 3: 0..2) */
+
+/*  Misc:  */
+#define XTHAL_LITTLEENDIAN		0
+#define XTHAL_BIGENDIAN			1
+
+
+/*  Interrupt types:  */
+#define XTHAL_INTTYPE_UNCONFIGURED	0
+#define XTHAL_INTTYPE_SOFTWARE		1
+#define XTHAL_INTTYPE_EXTERN_EDGE	2
+#define XTHAL_INTTYPE_EXTERN_LEVEL	3
+#define XTHAL_INTTYPE_TIMER		4
+#define XTHAL_INTTYPE_NMI		5
+#define XTHAL_MAX_INTTYPES		6	/* number of interrupt types */
+
+/*  Timer related:  */
+#define XTHAL_TIMER_UNCONFIGURED	-1	/* Xthal_timer_interrupt[] value for non-existent timers */
+#define XTHAL_TIMER_UNASSIGNED	XTHAL_TIMER_UNCONFIGURED	/* (for backwards compatibility only) */
+
+
+/*  Access Mode bits (tentative):  */	/* bit abbr unit short_name       PPC equ - Description */
+#define XTHAL_AMB_EXCEPTION	0	/* 001 E EX fls: EXception        none    - generate exception on any access (aka "illegal") */
+#define XTHAL_AMB_HITCACHE	1	/* 002 C CH fls: use Cache on Hit ~(I CI) - use cache on hit -- way from tag match [or H HC, or U UC] (ISA: same, except for Isolate case) */
+#define XTHAL_AMB_ALLOCATE	2	/* 004 A AL fl?: ALlocate         none    - refill cache on miss -- way from LRU [or F FI fill] (ISA: Read/Write Miss Refill) */
+#define XTHAL_AMB_WRITETHRU	3	/* 008 W WT --s: WriteThrough     W WT    - store immediately to memory (ISA: same) */
+#define XTHAL_AMB_ISOLATE	4	/* 010 I IS fls: ISolate          none    - use cache regardless of hit-vs-miss -- way from vaddr (ISA: use-cache-on-miss+hit) */
+#define XTHAL_AMB_GUARD		5	/* 020 G GU ?l?: GUard            G *     - non-speculative; spec/replay refs not permitted */
+#if 0
+#define XTHAL_AMB_ORDERED	x	/* 000 O OR fls: ORdered          G *     - mem accesses cannot be out of order */
+#define XTHAL_AMB_FUSEWRITES	x	/* 000 F FW --s: FuseWrites       none    - allow combining/merging multiple writes (to same datapath data unit) into one (implied by writeback) */
+#define XTHAL_AMB_COHERENT	x	/* 000 M MC fl?: Mem/MP Coherent  M       - on reads, other CPUs/bus-masters may need to supply data */
+#define XTHAL_AMB_TRUSTED	x	/* 000 T TR ?l?: TRusted          none    - memory will not bus error (if it does, handle as fatal imprecise interrupt) */
+#define XTHAL_AMB_PREFETCH	x	/* 000 P PR fl?: PRefetch         none    - on refill, read line+1 into prefetch buffers */
+#define XTHAL_AMB_STREAM	x	/* 000 S ST ???: STreaming        none    - access one of N stream buffers */
+#endif /*0*/
+
+#define XTHAL_AM_EXCEPTION	(1<<XTHAL_AMB_EXCEPTION)
+#define XTHAL_AM_HITCACHE	(1<<XTHAL_AMB_HITCACHE)
+#define XTHAL_AM_ALLOCATE	(1<<XTHAL_AMB_ALLOCATE)
+#define XTHAL_AM_WRITETHRU	(1<<XTHAL_AMB_WRITETHRU)
+#define XTHAL_AM_ISOLATE	(1<<XTHAL_AMB_ISOLATE)
+#define XTHAL_AM_GUARD		(1<<XTHAL_AMB_GUARD)
+#if 0
+#define XTHAL_AM_ORDERED	(1<<XTHAL_AMB_ORDERED)
+#define XTHAL_AM_FUSEWRITES	(1<<XTHAL_AMB_FUSEWRITES)
+#define XTHAL_AM_COHERENT	(1<<XTHAL_AMB_COHERENT)
+#define XTHAL_AM_TRUSTED	(1<<XTHAL_AMB_TRUSTED)
+#define XTHAL_AM_PREFETCH	(1<<XTHAL_AMB_PREFETCH)
+#define XTHAL_AM_STREAM		(1<<XTHAL_AMB_STREAM)
+#endif /*0*/
+
+/*
+ *  Allowed Access Modes (bit combinations).
+ *
+ *  Columns are:
+ *  "FOGIWACE"
+ *	Access mode bits (see XTHAL_AMB_xxx above).
+ *	<letter> = bit is set
+ *	'-'      = bit is clear
+ *	'.'      = bit is irrelevant / don't care, as follows:
+ *			E=1 makes all others irrelevant
+ *			W,F relevant only for stores
+ *  "2345"
+ *	Indicates which Xtensa releases support the corresponding
+ *	access mode.  Releases for each character column are:
+ *		2 = prior to T1020.2:   T1015 (V1.5), T1020.0, T1020.1
+ *		3 = T1020.2 and later:  T1020.2+, T1030
+ *		4 = T1040
+ *		5 = T1050 (maybe)
+ *	And the character column contents are:
+ *		<number> = support by release(s)
+ *		"." = unsupported by release(s)
+ *		"?" = support unknown
+ */
+					/* FOGIWACE 2345 */
+/*  For instruction fetch:  */
+#define XTHAL_FAM_EXCEPTION	0x001	/* .......E 2345 exception */
+#define XTHAL_FAM_ISOLATE	0x012	/* .--I.-C- .... isolate */
+#define XTHAL_FAM_BYPASS	0x000	/* .---.--- 2345 bypass */
+#define XTHAL_FAM_NACACHED	0x002	/* .---.-C- .... cached no-allocate (frozen) */
+#define XTHAL_FAM_CACHED	0x006	/* .---.AC- 2345 cached */
+/*  For data load:  */
+#define XTHAL_LAM_EXCEPTION	0x001	/* .......E 2345 exception */
+#define XTHAL_LAM_ISOLATE	0x012	/* .--I.-C- 2345 isolate */
+#define XTHAL_LAM_BYPASS	0x000	/* .O--.--- 2... bypass speculative */
+#define XTHAL_LAM_BYPASSG	0x020	/* .OG-.--- .345 bypass guarded */
+#define XTHAL_LAM_NACACHED	0x002	/* .O--.-C- 2... cached no-allocate speculative */
+#define XTHAL_LAM_NACACHEDG	0x022	/* .OG-.-C- .345 cached no-allocate guarded */
+#define XTHAL_LAM_CACHED	0x006	/* .---.AC- 2345 cached speculative */
+#define XTHAL_LAM_CACHEDG	0x026	/* .?G-.AC- .... cached guarded */
+/*  For data store:  */
+#define XTHAL_SAM_EXCEPTION	0x001	/* .......E 2345 exception */
+#define XTHAL_SAM_ISOLATE	0x032	/* .-GI--C- 2345 isolate */
+#define XTHAL_SAM_BYPASS	0x028	/* -OG-W--- 2345 bypass */
+/*efine XTHAL_SAM_BYPASSF	0x028*/	/* F-G-W--- ...? bypass write-combined */
+#define XTHAL_SAM_WRITETHRU	0x02A	/* -OG-W-C- 234? writethrough */
+/*efine XTHAL_SAM_WRITETHRUF	0x02A*/	/* F-G-W-C- ...5 writethrough write-combined */
+#define XTHAL_SAM_WRITEALLOC	0x02E	/* -OG-WAC- ...? writethrough-allocate */
+/*efine XTHAL_SAM_WRITEALLOCF	0x02E*/	/* F-G-WAC- ...? writethrough-allocate write-combined */
+#define XTHAL_SAM_WRITEBACK	0x026	/* F-G--AC- ...5 writeback */
+
+#if 0
+/*
+    Cache attribute encoding for CACHEATTR (per ISA):
+    (Note:  if this differs from ISA Ref Manual, ISA has precedence)
+
+	Inst-fetches	Loads		Stores
+	-------------	------------	-------------
+0x0	FCA_EXCEPTION  ?LCA_NACACHED_G*	SCA_WRITETHRU	"uncached"
+0x1	FCA_CACHED	LCA_CACHED	SCA_WRITETHRU	cached
+0x2	FCA_BYPASS	LCA_BYPASS_G*	SCA_BYPASS	bypass
+0x3	FCA_CACHED	LCA_CACHED	SCA_WRITEALLOCF	write-allocate
+		     or LCA_EXCEPTION	SCA_EXCEPTION	(if unimplemented)
+0x4	FCA_CACHED	LCA_CACHED	SCA_WRITEBACK	write-back
+		     or LCA_EXCEPTION	SCA_EXCEPTION	(if unimplemented)
+0x5..D	FCA_EXCEPTION	LCA_EXCEPTION	SCA_EXCEPTION	(reserved)
+0xE	FCA_EXCEPTION	LCA_ISOLATE	SCA_ISOLATE	isolate
+0xF	FCA_EXCEPTION	LCA_EXCEPTION	SCA_EXCEPTION	illegal
+     *  Prior to T1020.2?, guard feature not supported, this defaulted to speculative (no _G)
+*/
+#endif /*0*/
+
+
+#if !defined(__ASSEMBLY__) && !defined(_NOCLANGUAGE)
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*----------------------------------------------------------------------
+  			     HAL
+  ----------------------------------------------------------------------*/
+
+/* Constant to be checked in build = (XTHAL_MAJOR_REV<<16)|XTHAL_MINOR_REV */
+extern const unsigned int Xthal_rev_no;
+
+
+/*----------------------------------------------------------------------
+  			Processor State
+  ----------------------------------------------------------------------*/
+/* save & restore the extra processor state */
+extern void xthal_save_extra(void *base);
+extern void xthal_restore_extra(void *base);
+
+extern void xthal_save_cpregs(void *base, int);
+extern void xthal_restore_cpregs(void *base, int);
+
+/*extern void xthal_save_all_extra(void *base);*/
+/*extern void xthal_restore_all_extra(void *base);*/
+
+/* space for processor state */
+extern const unsigned int Xthal_extra_size;
+extern const unsigned int Xthal_extra_align;
+/* space for TIE register files */
+extern const unsigned int Xthal_cpregs_size[XTHAL_MAX_CPS];
+extern const unsigned int Xthal_cpregs_align[XTHAL_MAX_CPS];
+
+/* total of space for the processor state (for Tor2) */
+extern const unsigned int Xthal_all_extra_size;
+extern const unsigned int Xthal_all_extra_align;
+
+/* initialize the extra processor */
+/*extern void xthal_init_extra(void);*/
+/* initialize the TIE coprocessor */
+/*extern void xthal_init_cp(int);*/
+
+/* initialize the extra processor */
+extern void xthal_init_mem_extra(void *);
+/* initialize the TIE coprocessor */
+extern void xthal_init_mem_cp(void *, int);
+
+/* validate & invalidate the TIE register file */
+extern void xthal_validate_cp(int);
+extern void xthal_invalidate_cp(int);
+
+/* the number of TIE coprocessors contiguous from zero (for Tor2) */
+extern const unsigned int Xthal_num_coprocessors;
+
+/* actual number of coprocessors */
+extern const unsigned char Xthal_cp_num;
+/* index of highest numbered coprocessor, plus one */
+extern const unsigned char Xthal_cp_max;
+/* index of highest allowed coprocessor number, per cfg, plus one */
+/*extern const unsigned char Xthal_cp_maxcfg;*/
+/* bitmask of which coprocessors are present */
+extern const unsigned int  Xthal_cp_mask;
+
+/* read and write cpenable register */
+extern void xthal_set_cpenable(unsigned);
+extern unsigned xthal_get_cpenable(void);
+
+/* read & write extra state register */
+/*extern int xthal_read_extra(void *base, unsigned reg, unsigned *value);*/
+/*extern int xthal_write_extra(void *base, unsigned reg, unsigned value);*/
+
+/* read & write a TIE coprocessor register */
+/*extern int xthal_read_cpreg(void *base, int cp, unsigned reg, unsigned *value);*/
+/*extern int xthal_write_cpreg(void *base, int cp, unsigned reg, unsigned value);*/
+
+/* return coprocessor number based on register */
+/*extern int xthal_which_cp(unsigned reg);*/
+
+/*----------------------------------------------------------------------
+   				Interrupts
+  ----------------------------------------------------------------------*/
+
+/* the number of interrupt levels */
+extern const unsigned char Xthal_num_intlevels;
+/* the number of interrupts */
+extern const unsigned char Xthal_num_interrupts;
+
+/* mask for level of interrupts */
+extern const unsigned int Xthal_intlevel_mask[XTHAL_MAX_INTLEVELS];
+/* mask for level 0 to N interrupts */
+extern const unsigned int Xthal_intlevel_andbelow_mask[XTHAL_MAX_INTLEVELS];
+
+/* level of each interrupt */
+extern const unsigned char Xthal_intlevel[XTHAL_MAX_INTERRUPTS];
+
+/* type per interrupt */
+extern const unsigned char Xthal_inttype[XTHAL_MAX_INTERRUPTS];
+
+/* masks of each type of interrupt */
+extern const unsigned int Xthal_inttype_mask[XTHAL_MAX_INTTYPES];
+
+/* interrupt numbers assigned to each timer interrupt */
+extern const int Xthal_timer_interrupt[XTHAL_MAX_TIMERS];
+
+/***  Virtual interrupt prioritization:  ***/
+
+/*  Convert between interrupt levels (as per PS.INTLEVEL) and virtual interrupt priorities:  */
+extern unsigned	xthal_vpri_to_intlevel(unsigned vpri);
+extern unsigned	xthal_intlevel_to_vpri(unsigned intlevel);
+
+/*  Enables/disables given set (mask) of interrupts; returns previous enabled-mask of all ints:  */
+extern unsigned	xthal_int_enable(unsigned);
+extern unsigned	xthal_int_disable(unsigned);
+
+/*  Set/get virtual priority of an interrupt:  */
+extern int	xthal_set_int_vpri(int intnum, int vpri);
+extern int	xthal_get_int_vpri(int intnum);
+
+/*  Set/get interrupt lockout level for exclusive access to virtual priority data structures:  */
+extern void	xthal_set_vpri_locklevel(unsigned intlevel);
+extern unsigned	xthal_get_vpri_locklevel(void);
+
+/*  Set/get current virtual interrupt priority:  */
+extern unsigned	xthal_set_vpri(unsigned vpri);
+extern unsigned	xthal_get_vpri(unsigned vpri);
+extern unsigned	xthal_set_vpri_intlevel(unsigned intlevel);
+extern unsigned	xthal_set_vpri_lock(void);
+
+
+
+/*----------------------------------------------------------------------
+   			Generic Interrupt Trampolining Support
+  ----------------------------------------------------------------------*/
+
+typedef void (XtHalVoidFunc)(void);
+
+/*
+ *  Bitmask of interrupts currently trampolining down:
+ */
+extern unsigned Xthal_tram_pending;
+
+/*
+ *  Bitmask of which interrupts currently trampolining down
+ *  synchronously are actually enabled; this bitmask is necessary
+ *  because INTENABLE cannot hold that state (sync-trampolining
+ *  interrupts must be kept disabled while trampolining);
+ *  in the current implementation, any bit set here is not set
+ *  in INTENABLE, and vice-versa; once a sync-trampoline is
+ *  handled (at level one), its enable bit must be moved from
+ *  here to INTENABLE:
+ */
+extern unsigned Xthal_tram_enabled;
+
+/*
+ *  Bitmask of interrupts configured for sync trampolining:
+ */
+extern unsigned Xthal_tram_sync;
+
+
+/*  Trampoline support functions:  */
+extern unsigned  xthal_tram_pending_to_service( void );
+extern void      xthal_tram_done( unsigned serviced_mask );
+extern int       xthal_tram_set_sync( int intnum, int sync );
+extern XtHalVoidFunc* xthal_set_tram_trigger_func( XtHalVoidFunc *trigger_fn );
+
+/*  INTENABLE,INTREAD,INTSET,INTCLEAR register access functions:  */
+extern unsigned  xthal_get_intenable( void );
+extern void      xthal_set_intenable( unsigned );
+extern unsigned  xthal_get_intread( void );
+extern void      xthal_set_intset( unsigned );
+extern void      xthal_set_intclear( unsigned );
+
+
+/*----------------------------------------------------------------------
+   				Register Windows
+  ----------------------------------------------------------------------*/
+
+/* number of registers in register window */
+extern const unsigned int  Xthal_num_aregs;
+extern const unsigned char Xthal_num_aregs_log2;
+
+/*  This spill any live register windows (other than the caller's):  */
+extern void      xthal_window_spill( void );
+
+
+/*----------------------------------------------------------------------
+   				Cache
+  ----------------------------------------------------------------------*/
+
+/* size of the cache lines in log2(bytes) */
+extern const unsigned char Xthal_icache_linewidth;
+extern const unsigned char Xthal_dcache_linewidth;
+/* size of the cache lines in bytes */
+extern const unsigned short Xthal_icache_linesize;
+extern const unsigned short Xthal_dcache_linesize;
+/* number of cache sets in log2(lines per way) */
+extern const unsigned char Xthal_icache_setwidth;
+extern const unsigned char Xthal_dcache_setwidth;
+/* cache set associativity (number of ways) */
+extern const unsigned int  Xthal_icache_ways;
+extern const unsigned int  Xthal_dcache_ways;
+/* size of the caches in bytes (ways * 2^(linewidth + setwidth)) */
+extern const unsigned int  Xthal_icache_size;
+extern const unsigned int  Xthal_dcache_size;
+/* cache features */
+extern const unsigned char Xthal_dcache_is_writeback;
+extern const unsigned char Xthal_icache_line_lockable;
+extern const unsigned char Xthal_dcache_line_lockable;
+
+/* cache attribute register control (used by other HAL routines) */
+extern unsigned xthal_get_cacheattr( void );
+extern unsigned xthal_get_icacheattr( void );
+extern unsigned xthal_get_dcacheattr( void );
+extern void     xthal_set_cacheattr( unsigned );
+extern void     xthal_set_icacheattr( unsigned );
+extern void     xthal_set_dcacheattr( unsigned );
+
+/* initialize cache support (must be called once at startup, before all other cache calls) */
+/*extern void xthal_cache_startinit( void );*/
+/* reset caches */
+/*extern void xthal_icache_reset( void );*/
+/*extern void xthal_dcache_reset( void );*/
+/* enable caches */
+extern void xthal_icache_enable( void );	/* DEPRECATED */
+extern void xthal_dcache_enable( void );	/* DEPRECATED */
+/* disable caches */
+extern void xthal_icache_disable( void );	/* DEPRECATED */
+extern void xthal_dcache_disable( void );	/* DEPRECATED */
+
+/* invalidate the caches */
+extern void xthal_icache_all_invalidate( void );
+extern void xthal_dcache_all_invalidate( void );
+extern void xthal_icache_region_invalidate( void *addr, unsigned size );
+extern void xthal_dcache_region_invalidate( void *addr, unsigned size );
+extern void xthal_icache_line_invalidate(void *addr);
+extern void xthal_dcache_line_invalidate(void *addr);
+/* write dirty data back */
+extern void xthal_dcache_all_writeback( void );
+extern void xthal_dcache_region_writeback( void *addr, unsigned size );
+extern void xthal_dcache_line_writeback(void *addr);
+/* write dirty data back and invalidate */
+extern void xthal_dcache_all_writeback_inv( void );
+extern void xthal_dcache_region_writeback_inv( void *addr, unsigned size );
+extern void xthal_dcache_line_writeback_inv(void *addr);
+/* prefetch and lock specified memory range into cache */
+extern void xthal_icache_region_lock( void *addr, unsigned size );
+extern void xthal_dcache_region_lock( void *addr, unsigned size );
+extern void xthal_icache_line_lock(void *addr);
+extern void xthal_dcache_line_lock(void *addr);
+/* unlock from cache */
+extern void xthal_icache_all_unlock( void );
+extern void xthal_dcache_all_unlock( void );
+extern void xthal_icache_region_unlock( void *addr, unsigned size );
+extern void xthal_dcache_region_unlock( void *addr, unsigned size );
+extern void xthal_icache_line_unlock(void *addr);
+extern void xthal_dcache_line_unlock(void *addr);
+
+
+/* sync icache and memory */
+extern void xthal_icache_sync( void );
+/* sync dcache and memory */
+extern void xthal_dcache_sync( void );
+
+/*----------------------------------------------------------------------
+   				Debug
+  ----------------------------------------------------------------------*/
+
+/*  1 if debug option configured, 0 if not:  */
+extern const int Xthal_debug_configured;
+
+/*  Number of instruction and data break registers:  */
+extern const int Xthal_num_ibreak;
+extern const int Xthal_num_dbreak;
+
+/*  Set (plant) and remove software breakpoint, both synchronizing cache:  */
+extern unsigned int xthal_set_soft_break(void *addr);
+extern void         xthal_remove_soft_break(void *addr, unsigned int);
+
+
+/*----------------------------------------------------------------------
+   				Disassembler
+  ----------------------------------------------------------------------*/
+
+/*  Max expected size of the return buffer for a disassembled instruction (hint only):  */
+#define XTHAL_DISASM_BUFSIZE	80
+
+/*  Disassembly option bits for selecting what to return:  */
+#define XTHAL_DISASM_OPT_ADDR	0x0001	/* display address */
+#define XTHAL_DISASM_OPT_OPHEX	0x0002	/* display opcode bytes in hex */
+#define XTHAL_DISASM_OPT_OPCODE	0x0004	/* display opcode name (mnemonic) */
+#define XTHAL_DISASM_OPT_PARMS	0x0008	/* display parameters */
+#define XTHAL_DISASM_OPT_ALL	0x0FFF	/* display everything */
+
+/* routine to get a string for the disassembled instruction */
+extern int xthal_disassemble( unsigned char *instr_buf, void *tgt_addr,
+		       char *buffer, unsigned buflen, unsigned options );
+
+/* routine to get the size of the next instruction. Returns 0 for
+   illegal instruction */
+extern int xthal_disassemble_size( unsigned char *instr_buf );
+
+
+/*----------------------------------------------------------------------
+   				Core Counter
+  ----------------------------------------------------------------------*/
+
+/* counter info */
+extern const unsigned char Xthal_have_ccount;	/* set if CCOUNT register present */
+extern const unsigned char Xthal_num_ccompare;	/* number of CCOMPAREn registers */
+
+/* get CCOUNT register (if not present return 0) */
+extern unsigned xthal_get_ccount(void);
+
+/* set and get CCOMPAREn registers (if not present, get returns 0) */
+extern void     xthal_set_ccompare(int, unsigned);
+extern unsigned xthal_get_ccompare(int);
+
+
+/*----------------------------------------------------------------------
+			Instruction/Data RAM/ROM Access
+  ----------------------------------------------------------------------*/
+
+extern void* xthal_memcpy(void *dst, const void *src, unsigned len);
+extern void* xthal_bcopy(const void *src, void *dst, unsigned len);
+
+/*----------------------------------------------------------------------
+                           MP Synchronization
+  ----------------------------------------------------------------------*/
+extern int      xthal_compare_and_set( int *addr, int test_val, int compare_val );
+extern unsigned xthal_get_prid( void );
+
+/*extern const char  Xthal_have_s32c1i;*/
+extern const unsigned char Xthal_have_prid;
+
+
+/*----------------------------------------------------------------------
+                             Miscellaneous
+  ----------------------------------------------------------------------*/
+
+extern const unsigned int  Xthal_release_major;
+extern const unsigned int  Xthal_release_minor;
+extern const char * const  Xthal_release_name;
+extern const char * const  Xthal_release_internal;
+
+extern const unsigned char Xthal_memory_order;
+extern const unsigned char Xthal_have_windowed;
+extern const unsigned char Xthal_have_density;
+extern const unsigned char Xthal_have_booleans;
+extern const unsigned char Xthal_have_loops;
+extern const unsigned char Xthal_have_nsa;
+extern const unsigned char Xthal_have_minmax;
+extern const unsigned char Xthal_have_sext;
+extern const unsigned char Xthal_have_clamps;
+extern const unsigned char Xthal_have_mac16;
+extern const unsigned char Xthal_have_mul16;
+extern const unsigned char Xthal_have_fp;
+extern const unsigned char Xthal_have_speculation;
+extern const unsigned char Xthal_have_exceptions;
+extern const unsigned char Xthal_xea_version;
+extern const unsigned char Xthal_have_interrupts;
+extern const unsigned char Xthal_have_highlevel_interrupts;
+extern const unsigned char Xthal_have_nmi;
+
+extern const unsigned short Xthal_num_writebuffer_entries;
+
+extern const unsigned int  Xthal_build_unique_id;
+/*  Release info for hardware targeted by software upgrades:  */
+extern const unsigned int  Xthal_hw_configid0;
+extern const unsigned int  Xthal_hw_configid1;
+extern const unsigned int  Xthal_hw_release_major;
+extern const unsigned int  Xthal_hw_release_minor;
+extern const char * const  Xthal_hw_release_name;
+extern const char * const  Xthal_hw_release_internal;
+
+
+/*  Internal memories...  */
+
+extern const unsigned char Xthal_num_instrom;
+extern const unsigned char Xthal_num_instram;
+extern const unsigned char Xthal_num_datarom;
+extern const unsigned char Xthal_num_dataram;
+extern const unsigned char Xthal_num_xlmi;
+extern const unsigned int  Xthal_instrom_vaddr[1];
+extern const unsigned int  Xthal_instrom_paddr[1];
+extern const unsigned int  Xthal_instrom_size [1];
+extern const unsigned int  Xthal_instram_vaddr[1];
+extern const unsigned int  Xthal_instram_paddr[1];
+extern const unsigned int  Xthal_instram_size [1];
+extern const unsigned int  Xthal_datarom_vaddr[1];
+extern const unsigned int  Xthal_datarom_paddr[1];
+extern const unsigned int  Xthal_datarom_size [1];
+extern const unsigned int  Xthal_dataram_vaddr[1];
+extern const unsigned int  Xthal_dataram_paddr[1];
+extern const unsigned int  Xthal_dataram_size [1];
+extern const unsigned int  Xthal_xlmi_vaddr[1];
+extern const unsigned int  Xthal_xlmi_paddr[1];
+extern const unsigned int  Xthal_xlmi_size [1];
+
+
+
+/*----------------------------------------------------------------------
+                         Memory Management Unit
+  ----------------------------------------------------------------------*/
+
+extern const unsigned char Xthal_have_spanning_way;
+extern const unsigned char Xthal_have_identity_map;
+extern const unsigned char Xthal_have_mimic_cacheattr;
+extern const unsigned char Xthal_have_xlt_cacheattr;
+extern const unsigned char Xthal_have_cacheattr;
+extern const unsigned char Xthal_have_tlbs;
+
+extern const unsigned char Xthal_mmu_asid_bits;		/* 0 .. 8 */
+extern const unsigned char Xthal_mmu_asid_kernel;
+extern const unsigned char Xthal_mmu_rings;		/* 1 .. 4 (perhaps 0 if no MMU and/or no protection?) */
+extern const unsigned char Xthal_mmu_ring_bits;
+extern const unsigned char Xthal_mmu_sr_bits;
+extern const unsigned char Xthal_mmu_ca_bits;
+extern const unsigned int  Xthal_mmu_max_pte_page_size;
+extern const unsigned int  Xthal_mmu_min_pte_page_size;
+
+extern const unsigned char Xthal_itlb_way_bits;
+extern const unsigned char Xthal_itlb_ways;
+extern const unsigned char Xthal_itlb_arf_ways;
+extern const unsigned char Xthal_dtlb_way_bits;
+extern const unsigned char Xthal_dtlb_ways;
+extern const unsigned char Xthal_dtlb_arf_ways;
+
+/*  Convert between virtual and physical addresses (through static maps only):  */
+/*** WARNING: these two functions may go away in a future release; don't depend on them! ***/
+extern int  xthal_static_v2p( unsigned vaddr, unsigned *paddrp );
+extern int  xthal_static_p2v( unsigned paddr, unsigned *vaddrp, unsigned cached );
+
+#if 0
+/*******************   EXPERIMENTAL AND TENTATIVE ONLY   ********************/
+
+#define XTHAL_MMU_PAGESZ_COUNT_MAX	8	/* maximum number of different page sizes */
+extern const char	Xthal_mmu_pagesz_count;		/* 0 .. 8		number of different page sizes configured */
+
+/*  Note:  the following table doesn't necessarily have page sizes in increasing order: */
+extern const char	Xthal_mmu_pagesz_log2[XTHAL_MMU_PAGESZ_COUNT_MAX];	/* 10 .. 28 (0 past count) */
+
+/*  Sorted (increasing) table of page sizes, that indexes into the above table: */
+extern const char	Xthal_mmu_pagesz_sorted[XTHAL_MMU_PAGESZ_COUNT_MAX];	/* 0 .. 7 (0 past count) */
+
+/*u32	Xthal_virtual_exceptions;*/	/* bitmask of which exceptions execute in virtual mode... */
+
+extern const char	Xthal_mmu_pte_pagesz_log2_min;	/* ?? minimum page size in PTEs */
+extern const char	Xthal_mmu_pte_pagesz_log2_max;	/* ?? maximum page size in PTEs */
+
+/*  Cache Attribute Bits Implemented by the Cache (part of the cache abstraction) */
+extern const char	Xthal_icache_fca_bits_implemented;	/* ITLB/UTLB only! */
+extern const char	Xthal_dcache_lca_bits_implemented;	/* DTLB/UTLB only! */
+extern const char	Xthal_dcache_sca_bits_implemented; 	/* DTLB/UTLB only! */
+
+/*  Per TLB Parameters (Instruction, Data, Unified)  */
+struct XtHalMmuTlb	Xthal_itlb;	/* description of MMU I-TLB generic features */
+struct XtHalMmuTlb	Xthal_dtlb;	/* description of MMU D-TLB generic features */
+struct XtHalMmuTlb	Xthal_utlb;	/* description of MMU U-TLB generic features */
+
+#define XTHAL_MMU_WAYS_MAX	8	/* maximum number of ways (associativities) for each TLB */
+
+/*  Structure for common information described for each possible TLB (instruction, data and unified): */
+typedef struct XtHalMmuTlb {
+    u8  	va_bits;		/* 32		(number of virtual address bits) */
+    u8  	pa_bits;		/* 32		(number of physical address bits) */
+    bool	tlb_va_indexed;		/* 1	(set if TLB is indexed by virtual address) */
+    bool	tlb_va_tagged;		/* 0	(set if TLB is tagged by virtual address) */
+    bool	cache_va_indexed;	/* 1	(set if cache is indexed by virtual address) */
+    bool	cache_va_tagged;	/* 0	(set if cache is tagged by virtual address) */
+    /*bool	(whether page tables are traversed in vaddr sorted order, paddr sorted order, ...) */
+    /*u8	(set of available page attribute bits, other than cache attribute bits defined above) */
+    /*u32	(various masks for pages, MMU table/TLB entries, etc.) */
+    u8  	way_count;		/* 0 .. 8	(number of ways, a.k.a. associativities, for this TLB) */
+    XtHalMmuTlbWay *	ways[XTHAL_MMU_WAYS_MAX];	/* pointers to per-way parms for each way */
+} XtHalMmuTlb;
+
+/*  Per TLB Way (Per Associativity) Parameters  */
+typedef struct XtHalMmuTlbWay {
+     u32	index_count_log2;	/* 0 .. 4 */
+     u32	pagesz_mask;		/* 0 .. 2^pagesz_count - 1	(each bit corresponds to a size */
+					/*		defined in the Xthal_mmu_pagesz_log2[] table) */
+     u32	vpn_const_mask;
+     u32	vpn_const_value;
+     u64	ppn_const_mask;		/* future may support pa_bits > 32 */
+     u64	ppn_const_value;
+     u32	ppn_id_mask;		/* paddr bits taken directly from vaddr */
+     bool	backgnd_match;		/* 0 or 1 */
+     /*  These are defined in terms of the XTHAL_CACHE_xxx bits: */
+     u8 	fca_const_mask;		/* ITLB/UTLB only! */
+     u8 	fca_const_value;	/* ITLB/UTLB only! */
+     u8 	lca_const_mask;		/* DTLB/UTLB only! */
+     u8 	lca_const_value; 	/* DTLB/UTLB only! */
+     u8 	sca_const_mask; 	/* DTLB/UTLB only! */
+     u8 	sca_const_value; 	/* DTLB/UTLB only! */
+     /*  These define an encoding that map 5 bits in TLB and PTE entries to */
+     /*  8 bits (FCA, ITLB), 16 bits (LCA+SCA, DTLB) or 24 bits (FCA+LCA+SCA, UTLB): */
+     /*  (they may be moved to struct XtHalMmuTlb) */
+     u8		ca_bits;		/* number of bits in TLB/PTE entries for cache attributes */
+     u32 *	ca_map;			/* pointer to array of 2^ca_bits entries of FCA+LCA+SCA bits */
+} XtHalMmuTlbWay;
+
+/*
+ *  The way to determine whether protection support is present in core
+ *  is to [look at Xthal_mmu_rings ???].
+ *  Give info on memory requirements for MMU tables and other in-memory
+ *  data structures (globally, per task, base and per page, etc.) - whatever bounds can be calculated.
+ */
+
+
+/*  Default vectors:  */
+xthal_immu_fetch_miss_vector
+xthal_dmmu_load_miss_vector
+xthal_dmmu_store_miss_vector
+
+/*  Functions called when a fault is detected:  */
+typedef void (XtHalMmuFaultFunc)( unsigned vaddr, ...context... );
+/*  Or, */
+/*	a? = vaddr */
+/*	a? = context... */
+/*	PS.xxx = xxx */
+XtHalMMuFaultFunc *Xthal_immu_fetch_fault_func;
+XtHalMMuFaultFunc *Xthal_dmmu_load_fault_func;
+XtHalMMuFaultFunc *Xthal_dmmu_store_fault_func;
+
+/*  Default Handlers:  */
+/*  The user and/or kernel exception handlers may jump to these handlers to handle the relevant exceptions,
+ *  according to the value of EXCCAUSE.  The exact register state on entry to these handlers is TBD.  */
+/*  When multiple TLB entries match (hit) on the same access:  */
+xthal_immu_fetch_multihit_handler
+xthal_dmmu_load_multihit_handler
+xthal_dmmu_store_multihit_handler
+/*  Protection violations according to cache attributes, and other cache attribute mismatches:  */
+xthal_immu_fetch_attr_handler
+xthal_dmmu_load_attr_handler
+xthal_dmmu_store_attr_handler
+/*  Protection violations due to insufficient ring level:  */
+xthal_immu_fetch_priv_handler
+xthal_dmmu_load_priv_handler
+xthal_dmmu_store_priv_handler
+/*  Alignment exception handlers (if supported by the particular Xtensa MMU configuration):  */
+xthal_dmmu_load_align_handler
+xthal_dmmu_store_align_handler
+
+/*  Or, alternatively, the OS user and/or kernel exception handlers may simply jump to the
+ *  following entry points which will handle any values of EXCCAUSE not handled by the OS:  */
+xthal_user_exc_default_handler
+xthal_kernel_exc_default_handler
+
+#endif /*0*/
+
+#ifdef INCLUDE_DEPRECATED_HAL_CODE
+extern const unsigned char Xthal_have_old_exc_arch;
+extern const unsigned char Xthal_have_mmu;
+extern const unsigned int  Xthal_num_regs;
+extern const unsigned char Xthal_num_iroms;
+extern const unsigned char Xthal_num_irams;
+extern const unsigned char Xthal_num_droms;
+extern const unsigned char Xthal_num_drams;
+extern const unsigned int  Xthal_configid0;
+extern const unsigned int  Xthal_configid1;
+#endif
+
+#ifdef INCLUDE_DEPRECATED_HAL_DEBUG_CODE
+#define XTHAL_24_BIT_BREAK		0x80000000
+#define XTHAL_16_BIT_BREAK		0x40000000
+extern const unsigned short	Xthal_ill_inst_16[16];
+#define XTHAL_DEST_REG		0xf0000000	/* Mask for destination register */
+#define XTHAL_DEST_REG_INST	0x08000000	/* Branch address is in register */
+#define XTHAL_DEST_REL_INST	0x04000000	/* Branch address is relative */
+#define XTHAL_RFW_INST		0x00000800
+#define XTHAL_RFUE_INST		0x00000400
+#define XTHAL_RFI_INST		0x00000200
+#define XTHAL_RFE_INST		0x00000100
+#define XTHAL_RET_INST		0x00000080
+#define XTHAL_BREAK_INST	0x00000040
+#define XTHAL_SYSCALL_INST	0x00000020
+#define XTHAL_LOOP_END		0x00000010	/* Not set by xthal_inst_type */
+#define XTHAL_JUMP_INST		0x00000008	/* Call or jump instruction */
+#define XTHAL_BRANCH_INST	0x00000004	/* Branch instruction */
+#define XTHAL_24_BIT_INST	0x00000002
+#define XTHAL_16_BIT_INST   0x00000001
+typedef struct xthal_state {
+    unsigned	pc;
+    unsigned	ar[16];
+    unsigned	lbeg;
+    unsigned	lend;
+    unsigned	lcount;
+    unsigned	extra_ptr;
+    unsigned	cpregs_ptr[XTHAL_MAX_CPS];
+} XTHAL_STATE;
+extern unsigned int xthal_inst_type(void *addr);
+extern unsigned int xthal_branch_addr(void *addr);
+extern unsigned int xthal_get_npc(XTHAL_STATE *user_state);
+#endif /* INCLUDE_DEPRECATED_HAL_DEBUG_CODE */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*!__ASSEMBLY__ */
+
+#endif /*XTENSA_HAL_H*/
+
diff --git a/include/asm-xtensa/xtensa/simcall.h b/include/asm-xtensa/xtensa/simcall.h
new file mode 100644
index 0000000..a2b8689
--- /dev/null
+++ b/include/asm-xtensa/xtensa/simcall.h
@@ -0,0 +1,130 @@
+#ifndef SIMCALL_INCLUDED
+#define SIMCALL_INCLUDED
+
+/*
+ * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
+ *
+ * include/asm-xtensa/xtensa/simcall.h  -  Simulator call numbers
+ *
+ * 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) 2002 Tensilica Inc.
+ */
+
+
+/*
+ *  System call like services offered by the simulator host.
+ *  These are modeled after the Linux 2.4 kernel system calls
+ *  for Xtensa processors.  However not all system calls and
+ *  not all functionality of a given system call are implemented,
+ *  or necessarily have well defined or equivalent semantics in
+ *  the context of a simulation (as opposed to a Unix kernel).
+ *
+ *  These services behave largely as if they had been invoked
+ *  as a task in the simulator host's operating system
+ *  (eg. files accessed are those of the simulator host).
+ *  However, these SIMCALLs model a virtual operating system
+ *  so that various definitions, bit assignments etc
+ *  (eg. open mode bits, errno values, etc) are independent
+ *  of the host operating system used to run the simulation.
+ *  Rather these definitions are specific to the Xtensa ISS.
+ *  This way Xtensa ISA code written to use these SIMCALLs
+ *  can (in principle) be simulated on any host.
+ *
+ *  Up to 6 parameters are passed in registers a3 to a8
+ *  (note the 6th parameter isn't passed on the stack,
+ *   unlike windowed function calling conventions).
+ *  The return value is in a2.  A negative value in the
+ *  range -4096 to -1 indicates a negated error code to be
+ *  reported in errno with a return value of -1, otherwise
+ *  the value in a2 is returned as is.
+ */
+
+/* These #defines need to match what's in Xtensa/OS/vxworks/xtiss/simcalls.c */
+
+#define SYS_nop		0	/* n/a - setup; used to flush register windows */
+#define SYS_exit	1	/*x*/
+#define SYS_fork	2
+#define SYS_read	3	/*x*/
+#define SYS_write	4	/*x*/
+#define SYS_open	5	/*x*/
+#define SYS_close	6	/*x*/
+#define SYS_rename	7	/*x 38 - waitpid */
+#define SYS_creat	8	/*x*/
+#define SYS_link	9	/*x (not implemented on WIN32) */
+#define SYS_unlink	10	/*x*/
+#define SYS_execv	11	/* n/a - execve */
+#define SYS_execve	12	/* 11 - chdir */
+#define SYS_pipe	13	/* 42 - time */
+#define SYS_stat	14	/* 106 - mknod */
+#define SYS_chmod	15
+#define SYS_chown	16	/* 202 - lchown */
+#define SYS_utime	17	/* 30 - break */
+#define SYS_wait	18	/* n/a - oldstat */
+#define SYS_lseek	19	/*x*/
+#define SYS_getpid	20
+#define SYS_isatty	21	/* n/a - mount */
+#define SYS_fstat	22	/* 108 - oldumount */
+#define SYS_time	23	/* 13 - setuid */
+#define SYS_gettimeofday 24	/*x 78 - getuid (not implemented on WIN32) */
+#define SYS_times	25	/*X 43 - stime (Xtensa-specific implementation) */
+#define SYS_socket      26
+#define SYS_sendto      27
+#define SYS_recvfrom    28
+#define SYS_select_one  29      /* not compitible select, one file descriptor at the time */
+#define SYS_bind        30
+#define SYS_ioctl	31
+
+/*
+ *  Other...
+ */
+#define SYS_iss_argc      1000	/* returns value of argc */
+#define SYS_iss_argv_size 1001	/* bytes needed for argv & arg strings */
+#define SYS_iss_set_argv  1002	/* saves argv & arg strings at given addr */
+
+/*
+ * SIMCALLs for the ferret memory debugger. All are invoked by
+ * libferret.a ...  ( Xtensa/Target-Libs/ferret )
+ */
+#define SYS_ferret           1010
+#define SYS_malloc           1011
+#define SYS_free             1012
+#define SYS_more_heap        1013
+#define SYS_no_heap          1014
+
+
+/*
+ *  Extra SIMCALLs for GDB:
+ */
+#define SYS_gdb_break         -1	/* invoked by XTOS on user exceptions if EPC points
+					   to a break.n/break, regardless of cause! */
+#define SYS_xmon_out          -2	/* invoked by XMON: ... */
+#define SYS_xmon_in           -3	/* invoked by XMON: ... */
+#define SYS_xmon_flush        -4	/* invoked by XMON: ... */
+#define SYS_gdb_abort         -5	/* invoked by XTOS in _xtos_panic() */
+#define SYS_gdb_illegal_inst  -6	/* invoked by XTOS for illegal instructions (too deeply) */
+#define SYS_xmon_init         -7	/* invoked by XMON: ... */
+#define SYS_gdb_enter_sktloop -8	/* invoked by XTOS on debug exceptions */
+
+/*
+ *  SIMCALLs for vxWorks xtiss BSP:
+ */
+#define SYS_setup_ppp_pipes   -83
+#define SYS_log_msg           -84
+
+/*
+ *  Test SIMCALLs:
+ */
+#define SYS_test_write_state  -100
+#define SYS_test_read_state   -101
+
+/*
+ * SYS_select_one specifiers
+ */
+#define  XTISS_SELECT_ONE_READ    1
+#define  XTISS_SELECT_ONE_WRITE   2
+#define  XTISS_SELECT_ONE_EXCEPT  3
+
+#endif /* !SIMCALL_INCLUDED */
diff --git a/include/asm-xtensa/xtensa/xt2000-uart.h b/include/asm-xtensa/xtensa/xt2000-uart.h
new file mode 100644
index 0000000..0154460
--- /dev/null
+++ b/include/asm-xtensa/xtensa/xt2000-uart.h
@@ -0,0 +1,155 @@
+#ifndef _uart_h_included_
+#define _uart_h_included_
+
+/*
+ * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
+ *
+ * include/asm-xtensa/xtensa/xt2000-uart.h -- NatSemi PC16552D DUART
+ * definitions
+ *
+ * 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) 2002 Tensilica Inc.
+ */
+
+
+#include <xtensa/xt2000.h>
+
+
+/* 16550 UART DEVICE REGISTERS
+   The XT2000 board aligns each register to a 32-bit word but the UART device only uses
+   one byte of the word, which is the least-significant byte regardless of the
+   endianness of the core (ie. byte offset 0 for little-endian and 3 for big-endian).
+   So if using word accesses then endianness doesn't matter.
+   The macros provided here do that.
+*/
+struct uart_dev_s {
+  union {
+    unsigned int rxb;	/* DLAB=0: receive buffer, read-only */
+    unsigned int txb;	/* DLAB=0: transmit buffer, write-only */
+    unsigned int dll;	/* DLAB=1: divisor, least-significant byte latch (was write-only?) */
+  } w0;
+  union {
+    unsigned int ier;	/* DLAB=0: interrupt-enable register (was write-only?) */
+    unsigned int dlm;	/* DLAB=1: divisor, most-significant byte latch (was write-only?) */
+  } w1;
+
+  union {
+    unsigned int isr;	/* DLAB=0: interrupt status register, read-only */
+    unsigned int fcr;	/* DLAB=0: FIFO control register, write-only */
+    unsigned int afr;	/* DLAB=1: alternate function register */
+  } w2;
+
+  unsigned int lcr;	/* line control-register, write-only */
+  unsigned int mcr;	/* modem control-regsiter, write-only */
+  unsigned int lsr;	/* line status register, read-only */
+  unsigned int msr;	/* modem status register, read-only */
+  unsigned int scr;	/* scratch regsiter, read/write */
+};
+
+#define _RXB(u) ((u)->w0.rxb)
+#define _TXB(u) ((u)->w0.txb)
+#define _DLL(u) ((u)->w0.dll)
+#define _IER(u) ((u)->w1.ier)
+#define _DLM(u) ((u)->w1.dlm)
+#define _ISR(u) ((u)->w2.isr)
+#define _FCR(u) ((u)->w2.fcr)
+#define _AFR(u) ((u)->w2.afr)
+#define _LCR(u) ((u)->lcr)
+#define _MCR(u) ((u)->mcr)
+#define _LSR(u) ((u)->lsr)
+#define _MSR(u) ((u)->msr)
+#define _SCR(u) ((u)->scr)
+
+typedef volatile struct uart_dev_s uart_dev_t;
+
+/* IER bits */
+#define RCVR_DATA_REG_INTENABLE 0x01
+#define XMIT_HOLD_REG_INTENABLE    0x02
+#define RCVR_STATUS_INTENABLE   0x04
+#define MODEM_STATUS_INTENABLE     0x08
+
+/* FCR bits */
+#define _FIFO_ENABLE      0x01
+#define RCVR_FIFO_RESET  0x02
+#define XMIT_FIFO_RESET  0x04
+#define DMA_MODE_SELECT  0x08
+#define RCVR_TRIGGER_LSB 0x40
+#define RCVR_TRIGGER_MSB 0x80
+
+/* AFR bits */
+#define AFR_CONC_WRITE	0x01
+#define AFR_BAUDOUT_SEL	0x02
+#define AFR_RXRDY_SEL	0x04
+
+/* ISR bits */
+#define INT_STATUS(r)   ((r)&1)
+#define INT_PRIORITY(r) (((r)>>1)&0x7)
+
+/* LCR bits */
+#define WORD_LENGTH(n)  (((n)-5)&0x3)
+#define STOP_BIT_ENABLE 0x04
+#define PARITY_ENABLE   0x08
+#define EVEN_PARITY     0x10
+#define FORCE_PARITY    0x20
+#define XMIT_BREAK      0x40
+#define DLAB_ENABLE     0x80
+
+/* MCR bits */
+#define _DTR 0x01
+#define _RTS 0x02
+#define _OP1 0x04
+#define _OP2 0x08
+#define LOOP_BACK 0x10
+
+/* LSR Bits */
+#define RCVR_DATA_READY 0x01
+#define OVERRUN_ERROR   0x02
+#define PARITY_ERROR    0x04
+#define FRAMING_ERROR   0x08
+#define BREAK_INTERRUPT 0x10
+#define XMIT_HOLD_EMPTY 0x20
+#define XMIT_EMPTY      0x40
+#define FIFO_ERROR      0x80
+#define RCVR_READY(u)   (_LSR(u)&RCVR_DATA_READY)
+#define XMIT_READY(u)   (_LSR(u)&XMIT_HOLD_EMPTY)
+
+/* MSR bits */
+#define _RDR       0x01
+#define DELTA_DSR 0x02
+#define DELTA_RI  0x04
+#define DELTA_CD  0x08
+#define _CTS       0x10
+#define _DSR       0x20
+#define _RI        0x40
+#define _CD        0x80
+
+/* prototypes */
+void uart_init( uart_dev_t *u, int bitrate );
+void uart_out( uart_dev_t *u, char c );
+void uart_puts( uart_dev_t *u, char *s );
+char uart_in( uart_dev_t *u );
+void uart_enable_rcvr_int( uart_dev_t *u );
+void uart_disable_rcvr_int( uart_dev_t *u );
+
+#ifdef DUART16552_1_VADDR
+/*  DUART present.  */
+#define DUART_1_BASE	(*(uart_dev_t*)DUART16552_1_VADDR)
+#define DUART_2_BASE	(*(uart_dev_t*)DUART16552_2_VADDR)
+#define UART1_PUTS(s)	uart_puts( &DUART_1_BASE, s )
+#define UART2_PUTS(s)	uart_puts( &DUART_2_BASE, s )
+#else
+/*  DUART not configured, use dummy placeholders to allow compiles to work.  */
+#define DUART_1_BASE	(*(uart_dev_t*)0)
+#define DUART_2_BASE	(*(uart_dev_t*)0)
+#define UART1_PUTS(s)
+#define UART2_PUTS(s)
+#endif
+
+/*  Compute 16-bit divisor for baudrate generator, with rounding:  */
+#define DUART_DIVISOR(crystal,speed)	(((crystal)/16 + (speed)/2)/(speed))
+
+#endif /*_uart_h_included_*/
+
diff --git a/include/asm-xtensa/xtensa/xt2000.h b/include/asm-xtensa/xtensa/xt2000.h
new file mode 100644
index 0000000..703a450
--- /dev/null
+++ b/include/asm-xtensa/xtensa/xt2000.h
@@ -0,0 +1,408 @@
+#ifndef _INC_XT2000_H_
+#define _INC_XT2000_H_
+
+/*
+ * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
+ *
+ * include/asm-xtensa/xtensa/xt2000.h - Definitions specific to the
+ * Tensilica XT2000 Emulation Board
+ *
+ * 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) 2002 Tensilica Inc.
+ */
+
+
+#include <xtensa/config/core.h>
+#include <xtensa/config/system.h>
+
+
+/*
+ *  Default assignment of XT2000 devices to external interrupts.
+ */
+
+/*  Ethernet interrupt:  */
+#ifdef XCHAL_EXTINT3_NUM
+#define SONIC83934_INTNUM	XCHAL_EXTINT3_NUM
+#define SONIC83934_INTLEVEL	XCHAL_EXTINT3_LEVEL
+#define SONIC83934_INTMASK	XCHAL_EXTINT3_MASK
+#else
+#define SONIC83934_INTMASK	0
+#endif
+
+/*  DUART channel 1 interrupt (P1 - console):  */
+#ifdef XCHAL_EXTINT4_NUM
+#define DUART16552_1_INTNUM	XCHAL_EXTINT4_NUM
+#define DUART16552_1_INTLEVEL	XCHAL_EXTINT4_LEVEL
+#define DUART16552_1_INTMASK	XCHAL_EXTINT4_MASK
+#else
+#define DUART16552_1_INTMASK	0
+#endif
+
+/*  DUART channel 2 interrupt (P2 - 2nd serial port):  */
+#ifdef XCHAL_EXTINT5_NUM
+#define DUART16552_2_INTNUM	XCHAL_EXTINT5_NUM
+#define DUART16552_2_INTLEVEL	XCHAL_EXTINT5_LEVEL
+#define DUART16552_2_INTMASK	XCHAL_EXTINT5_MASK
+#else
+#define DUART16552_2_INTMASK	0
+#endif
+
+/*  FPGA-combined PCI/etc interrupts:  */
+#ifdef XCHAL_EXTINT6_NUM
+#define XT2000_FPGAPCI_INTNUM	XCHAL_EXTINT6_NUM
+#define XT2000_FPGAPCI_INTLEVEL	XCHAL_EXTINT6_LEVEL
+#define XT2000_FPGAPCI_INTMASK	XCHAL_EXTINT6_MASK
+#else
+#define XT2000_FPGAPCI_INTMASK	0
+#endif
+
+
+
+/*
+ *  Device addresses.
+ *
+ *  Note:  for endianness-independence, use 32-bit loads and stores for all
+ *  register accesses to Ethernet, DUART and LED devices.  Undefined bits
+ *  may need to be masked out if needed when reading if the actual register
+ *  size is smaller than 32 bits.
+ *
+ *  Note:  XT2000 bus byte lanes are defined in terms of msbyte and lsbyte
+ *  relative to the processor.  So 32-bit registers are accessed consistently
+ *  from both big and little endian processors.  However, this means byte
+ *  sequences are not consistent between big and little endian processors.
+ *  This is fine for RAM, and for ROM if ROM is created for a specific
+ *  processor (and thus has correct byte sequences).  However this may be
+ *  unexpected for Flash, which might contain a file-system that one wants
+ *  to use for multiple processor configurations (eg. the Flash might contain
+ *  the Ethernet card's address, endianness-independent application data, etc).
+ *  That is, byte sequences written in Flash by a core of a given endianness
+ *  will be byte-swapped when seen by a core of the other endianness.
+ *  Someone implementing an endianness-independent Flash file system will
+ *  likely handle this byte-swapping issue in the Flash driver software.
+ */
+
+#define DUART16552_XTAL_FREQ	18432000	/* crystal frequency in Hz */
+#define XTBOARD_FLASH_MAXSIZE	0x4000000	/* 64 MB (max; depends on what is socketed!) */
+#define XTBOARD_EPROM_MAXSIZE	0x0400000	/* 4 MB (max; depends on what is socketed!) */
+#define XTBOARD_EEPROM_MAXSIZE	0x0080000	/* 512 kB (max; depends on what is socketed!) */
+#define XTBOARD_ASRAM_SIZE	0x0100000	/* 1 MB */
+#define XTBOARD_PCI_MEM_SIZE	0x8000000	/* 128 MB (allocated) */
+#define XTBOARD_PCI_IO_SIZE	0x1000000	/* 16 MB (allocated) */
+
+#ifdef XSHAL_IOBLOCK_BYPASS_PADDR
+/*  PCI memory space:  */
+# define XTBOARD_PCI_MEM_PADDR	(XSHAL_IOBLOCK_BYPASS_PADDR+0x0000000)
+/*  Socketed Flash (eg. 2 x 16-bit devices):  */
+# define XTBOARD_FLASH_PADDR	(XSHAL_IOBLOCK_BYPASS_PADDR+0x8000000)
+/*  PCI I/O space:  */
+# define XTBOARD_PCI_IO_PADDR	(XSHAL_IOBLOCK_BYPASS_PADDR+0xC000000)
+/*  V3 PCI interface chip register/config space:  */
+# define XTBOARD_V3PCI_PADDR	(XSHAL_IOBLOCK_BYPASS_PADDR+0xD000000)
+/*  Bus Interface registers:  */
+# define XTBOARD_BUSINT_PADDR	(XSHAL_IOBLOCK_BYPASS_PADDR+0xD010000)
+/*  FPGA registers:  */
+# define XT2000_FPGAREGS_PADDR	(XSHAL_IOBLOCK_BYPASS_PADDR+0xD020000)
+/*  SONIC SN83934 Ethernet controller/transceiver:  */
+# define SONIC83934_PADDR	(XSHAL_IOBLOCK_BYPASS_PADDR+0xD030000)
+/*  8-character bitmapped LED display:  */
+# define XTBOARD_LED_PADDR	(XSHAL_IOBLOCK_BYPASS_PADDR+0xD040000)
+/*  National-Semi PC16552D DUART:  */
+# define DUART16552_1_PADDR	(XSHAL_IOBLOCK_BYPASS_PADDR+0xD050020)	/* channel 1 (P1 - console) */
+# define DUART16552_2_PADDR	(XSHAL_IOBLOCK_BYPASS_PADDR+0xD050000)	/* channel 2 (P2) */
+/*  Asynchronous Static RAM:  */
+# define XTBOARD_ASRAM_PADDR	(XSHAL_IOBLOCK_BYPASS_PADDR+0xD400000)
+/*  8-bit EEPROM:  */
+# define XTBOARD_EEPROM_PADDR	(XSHAL_IOBLOCK_BYPASS_PADDR+0xD600000)
+/*  2 x 16-bit EPROMs:  */
+# define XTBOARD_EPROM_PADDR	(XSHAL_IOBLOCK_BYPASS_PADDR+0xD800000)
+#endif /* XSHAL_IOBLOCK_BYPASS_PADDR */
+
+/*  These devices might be accessed cached:  */
+#ifdef XSHAL_IOBLOCK_CACHED_PADDR
+# define XTBOARD_PCI_MEM_CACHED_PADDR	(XSHAL_IOBLOCK_CACHED_PADDR+0x0000000)
+# define XTBOARD_FLASH_CACHED_PADDR	(XSHAL_IOBLOCK_CACHED_PADDR+0x8000000)
+# define XTBOARD_ASRAM_CACHED_PADDR	(XSHAL_IOBLOCK_CACHED_PADDR+0xD400000)
+# define XTBOARD_EEPROM_CACHED_PADDR	(XSHAL_IOBLOCK_CACHED_PADDR+0xD600000)
+# define XTBOARD_EPROM_CACHED_PADDR	(XSHAL_IOBLOCK_CACHED_PADDR+0xD800000)
+#endif /* XSHAL_IOBLOCK_CACHED_PADDR */
+
+
+/***  Same thing over again, this time with virtual addresses:  ***/
+
+#ifdef XSHAL_IOBLOCK_BYPASS_VADDR
+/*  PCI memory space:  */
+# define XTBOARD_PCI_MEM_VADDR	(XSHAL_IOBLOCK_BYPASS_VADDR+0x0000000)
+/*  Socketed Flash (eg. 2 x 16-bit devices):  */
+# define XTBOARD_FLASH_VADDR	(XSHAL_IOBLOCK_BYPASS_VADDR+0x8000000)
+/*  PCI I/O space:  */
+# define XTBOARD_PCI_IO_VADDR	(XSHAL_IOBLOCK_BYPASS_VADDR+0xC000000)
+/*  V3 PCI interface chip register/config space:  */
+# define XTBOARD_V3PCI_VADDR	(XSHAL_IOBLOCK_BYPASS_VADDR+0xD000000)
+/*  Bus Interface registers:  */
+# define XTBOARD_BUSINT_VADDR	(XSHAL_IOBLOCK_BYPASS_VADDR+0xD010000)
+/*  FPGA registers:  */
+# define XT2000_FPGAREGS_VADDR	(XSHAL_IOBLOCK_BYPASS_VADDR+0xD020000)
+/*  SONIC SN83934 Ethernet controller/transceiver:  */
+# define SONIC83934_VADDR	(XSHAL_IOBLOCK_BYPASS_VADDR+0xD030000)
+/*  8-character bitmapped LED display:  */
+# define XTBOARD_LED_VADDR	(XSHAL_IOBLOCK_BYPASS_VADDR+0xD040000)
+/*  National-Semi PC16552D DUART:  */
+# define DUART16552_1_VADDR	(XSHAL_IOBLOCK_BYPASS_VADDR+0xD050020)	/* channel 1 (P1 - console) */
+# define DUART16552_2_VADDR	(XSHAL_IOBLOCK_BYPASS_VADDR+0xD050000)	/* channel 2 (P2) */
+/*  Asynchronous Static RAM:  */
+# define XTBOARD_ASRAM_VADDR	(XSHAL_IOBLOCK_BYPASS_VADDR+0xD400000)
+/*  8-bit EEPROM:  */
+# define XTBOARD_EEPROM_VADDR	(XSHAL_IOBLOCK_BYPASS_VADDR+0xD600000)
+/*  2 x 16-bit EPROMs:  */
+# define XTBOARD_EPROM_VADDR	(XSHAL_IOBLOCK_BYPASS_VADDR+0xD800000)
+#endif /* XSHAL_IOBLOCK_BYPASS_VADDR */
+
+/*  These devices might be accessed cached:  */
+#ifdef XSHAL_IOBLOCK_CACHED_VADDR
+# define XTBOARD_PCI_MEM_CACHED_VADDR	(XSHAL_IOBLOCK_CACHED_VADDR+0x0000000)
+# define XTBOARD_FLASH_CACHED_VADDR	(XSHAL_IOBLOCK_CACHED_VADDR+0x8000000)
+# define XTBOARD_ASRAM_CACHED_VADDR	(XSHAL_IOBLOCK_CACHED_VADDR+0xD400000)
+# define XTBOARD_EEPROM_CACHED_VADDR	(XSHAL_IOBLOCK_CACHED_VADDR+0xD600000)
+# define XTBOARD_EPROM_CACHED_VADDR	(XSHAL_IOBLOCK_CACHED_VADDR+0xD800000)
+#endif /* XSHAL_IOBLOCK_CACHED_VADDR */
+
+
+/*  System ROM:  */
+#define XTBOARD_ROM_SIZE		XSHAL_ROM_SIZE
+#ifdef XSHAL_ROM_VADDR
+#define XTBOARD_ROM_VADDR		XSHAL_ROM_VADDR
+#endif
+#ifdef XSHAL_ROM_PADDR
+#define XTBOARD_ROM_PADDR		XSHAL_ROM_PADDR
+#endif
+
+/*  System RAM:  */
+#define XTBOARD_RAM_SIZE		XSHAL_RAM_SIZE
+#ifdef XSHAL_RAM_VADDR
+#define XTBOARD_RAM_VADDR		XSHAL_RAM_VADDR
+#endif
+#ifdef XSHAL_RAM_PADDR
+#define XTBOARD_RAM_PADDR		XSHAL_RAM_PADDR
+#endif
+#define XTBOARD_RAM_BYPASS_VADDR	XSHAL_RAM_BYPASS_VADDR
+#define XTBOARD_RAM_BYPASS_PADDR	XSHAL_RAM_BYPASS_PADDR
+
+
+
+/*
+ *  Things that depend on device addresses.
+ */
+
+
+#define XTBOARD_CACHEATTR_WRITEBACK	XSHAL_XT2000_CACHEATTR_WRITEBACK
+#define XTBOARD_CACHEATTR_WRITEALLOC	XSHAL_XT2000_CACHEATTR_WRITEALLOC
+#define XTBOARD_CACHEATTR_WRITETHRU	XSHAL_XT2000_CACHEATTR_WRITETHRU
+#define XTBOARD_CACHEATTR_BYPASS	XSHAL_XT2000_CACHEATTR_BYPASS
+#define XTBOARD_CACHEATTR_DEFAULT	XSHAL_XT2000_CACHEATTR_DEFAULT
+
+#define XTBOARD_BUSINT_PIPE_REGIONS	XSHAL_XT2000_PIPE_REGIONS
+#define XTBOARD_BUSINT_SDRAM_REGIONS	XSHAL_XT2000_SDRAM_REGIONS
+
+
+
+/*
+ *  BusLogic (FPGA) registers.
+ *  All these registers are normally accessed using 32-bit loads/stores.
+ */
+
+/*  Register offsets:  */
+#define XT2000_DATECD_OFS	0x00	/* date code (read-only) */
+#define XT2000_STSREG_OFS	0x04	/* status (read-only) */
+#define XT2000_SYSLED_OFS	0x08	/* system LED */
+#define XT2000_WRPROT_OFS	0x0C	/* write protect */
+#define XT2000_SWRST_OFS	0x10	/* software reset */
+#define XT2000_SYSRST_OFS	0x14	/* system (peripherals) reset */
+#define XT2000_IMASK_OFS	0x18	/* interrupt mask */
+#define XT2000_ISTAT_OFS	0x1C	/* interrupt status */
+#define XT2000_V3CFG_OFS	0x20	/* V3 config (V320 PCI) */
+
+/*  Physical register addresses:  */
+#ifdef XT2000_FPGAREGS_PADDR
+#define XT2000_DATECD_PADDR	(XT2000_FPGAREGS_PADDR+XT2000_DATECD_OFS)
+#define XT2000_STSREG_PADDR	(XT2000_FPGAREGS_PADDR+XT2000_STSREG_OFS)
+#define XT2000_SYSLED_PADDR	(XT2000_FPGAREGS_PADDR+XT2000_SYSLED_OFS)
+#define XT2000_WRPROT_PADDR	(XT2000_FPGAREGS_PADDR+XT2000_WRPROT_OFS)
+#define XT2000_SWRST_PADDR	(XT2000_FPGAREGS_PADDR+XT2000_SWRST_OFS)
+#define XT2000_SYSRST_PADDR	(XT2000_FPGAREGS_PADDR+XT2000_SYSRST_OFS)
+#define XT2000_IMASK_PADDR	(XT2000_FPGAREGS_PADDR+XT2000_IMASK_OFS)
+#define XT2000_ISTAT_PADDR	(XT2000_FPGAREGS_PADDR+XT2000_ISTAT_OFS)
+#define XT2000_V3CFG_PADDR	(XT2000_FPGAREGS_PADDR+XT2000_V3CFG_OFS)
+#endif
+
+/*  Virtual register addresses:  */
+#ifdef XT2000_FPGAREGS_VADDR
+#define XT2000_DATECD_VADDR	(XT2000_FPGAREGS_VADDR+XT2000_DATECD_OFS)
+#define XT2000_STSREG_VADDR	(XT2000_FPGAREGS_VADDR+XT2000_STSREG_OFS)
+#define XT2000_SYSLED_VADDR	(XT2000_FPGAREGS_VADDR+XT2000_SYSLED_OFS)
+#define XT2000_WRPROT_VADDR	(XT2000_FPGAREGS_VADDR+XT2000_WRPROT_OFS)
+#define XT2000_SWRST_VADDR	(XT2000_FPGAREGS_VADDR+XT2000_SWRST_OFS)
+#define XT2000_SYSRST_VADDR	(XT2000_FPGAREGS_VADDR+XT2000_SYSRST_OFS)
+#define XT2000_IMASK_VADDR	(XT2000_FPGAREGS_VADDR+XT2000_IMASK_OFS)
+#define XT2000_ISTAT_VADDR	(XT2000_FPGAREGS_VADDR+XT2000_ISTAT_OFS)
+#define XT2000_V3CFG_VADDR	(XT2000_FPGAREGS_VADDR+XT2000_V3CFG_OFS)
+/*  Register access (for C code):  */
+#define XT2000_DATECD_REG	(*(volatile unsigned*) XT2000_DATECD_VADDR)
+#define XT2000_STSREG_REG	(*(volatile unsigned*) XT2000_STSREG_VADDR)
+#define XT2000_SYSLED_REG	(*(volatile unsigned*) XT2000_SYSLED_VADDR)
+#define XT2000_WRPROT_REG	(*(volatile unsigned*) XT2000_WRPROT_VADDR)
+#define XT2000_SWRST_REG	(*(volatile unsigned*) XT2000_SWRST_VADDR)
+#define XT2000_SYSRST_REG	(*(volatile unsigned*) XT2000_SYSRST_VADDR)
+#define XT2000_IMASK_REG	(*(volatile unsigned*) XT2000_IMASK_VADDR)
+#define XT2000_ISTAT_REG	(*(volatile unsigned*) XT2000_ISTAT_VADDR)
+#define XT2000_V3CFG_REG	(*(volatile unsigned*) XT2000_V3CFG_VADDR)
+#endif
+
+/*  DATECD (date code) bit fields:  */
+
+/*  BCD-coded month (01..12):  */
+#define XT2000_DATECD_MONTH_SHIFT	24
+#define XT2000_DATECD_MONTH_BITS	8
+#define XT2000_DATECD_MONTH_MASK	0xFF000000
+/*  BCD-coded day (01..31):  */
+#define XT2000_DATECD_DAY_SHIFT		16
+#define XT2000_DATECD_DAY_BITS		8
+#define XT2000_DATECD_DAY_MASK		0x00FF0000
+/*  BCD-coded year (2001..9999):  */
+#define XT2000_DATECD_YEAR_SHIFT	0
+#define XT2000_DATECD_YEAR_BITS		16
+#define XT2000_DATECD_YEAR_MASK		0x0000FFFF
+
+/*  STSREG (status) bit fields:  */
+
+/*  Switch SW3 setting bit fields (0=off/up, 1=on/down):  */
+#define XT2000_STSREG_SW3_SHIFT		0
+#define XT2000_STSREG_SW3_BITS		4
+#define XT2000_STSREG_SW3_MASK		0x0000000F
+/*  Boot-select bits of switch SW3:  */
+#define XT2000_STSREG_BOOTSEL_SHIFT	0
+#define XT2000_STSREG_BOOTSEL_BITS	2
+#define XT2000_STSREG_BOOTSEL_MASK	0x00000003
+/*  Boot-select values:  */
+#define XT2000_STSREG_BOOTSEL_FLASH	0
+#define XT2000_STSREG_BOOTSEL_EPROM16	1
+#define XT2000_STSREG_BOOTSEL_PROM8	2
+#define XT2000_STSREG_BOOTSEL_ASRAM	3
+/*  User-defined bits of switch SW3:  */
+#define XT2000_STSREG_SW3_2_SHIFT	2
+#define XT2000_STSREG_SW3_2_MASK	0x00000004
+#define XT2000_STSREG_SW3_3_SHIFT	3
+#define XT2000_STSREG_SW3_3_MASK	0x00000008
+
+/*  SYSLED (system LED) bit fields:  */
+
+/*  LED control bit (0=off, 1=on):  */
+#define XT2000_SYSLED_LEDON_SHIFT	0
+#define XT2000_SYSLED_LEDON_MASK	0x00000001
+
+/*  WRPROT (write protect) bit fields (0=writable, 1=write-protected [default]):  */
+
+/*  Flash write protect:  */
+#define XT2000_WRPROT_FLWP_SHIFT	0
+#define XT2000_WRPROT_FLWP_MASK		0x00000001
+/*  Reserved but present write protect bits:  */
+#define XT2000_WRPROT_WRP_SHIFT		1
+#define XT2000_WRPROT_WRP_BITS		7
+#define XT2000_WRPROT_WRP_MASK		0x000000FE
+
+/*  SWRST (software reset; allows s/w to generate power-on equivalent reset):  */
+
+/*  Software reset bits:  */
+#define XT2000_SWRST_SWR_SHIFT		0
+#define XT2000_SWRST_SWR_BITS		16
+#define XT2000_SWRST_SWR_MASK		0x0000FFFF
+/*  Software reset value -- writing this value resets the board:  */
+#define XT2000_SWRST_RESETVALUE		0x0000DEAD
+
+/*  SYSRST (system reset; controls reset of individual peripherals):  */
+
+/*  All-device reset:  */
+#define XT2000_SYSRST_ALL_SHIFT		0
+#define XT2000_SYSRST_ALL_BITS		4
+#define XT2000_SYSRST_ALL_MASK		0x0000000F
+/*  HDSP-2534 LED display reset (1=reset, 0=nothing):  */
+#define XT2000_SYSRST_LED_SHIFT		0
+#define XT2000_SYSRST_LED_MASK		0x00000001
+/*  Sonic DP83934 Ethernet controller reset (1=reset, 0=nothing):  */
+#define XT2000_SYSRST_SONIC_SHIFT	1
+#define XT2000_SYSRST_SONIC_MASK	0x00000002
+/*  DP16552 DUART reset (1=reset, 0=nothing):  */
+#define XT2000_SYSRST_DUART_SHIFT	2
+#define XT2000_SYSRST_DUART_MASK	0x00000004
+/*  V3 V320 PCI bridge controller reset (1=reset, 0=nothing):  */
+#define XT2000_SYSRST_V3_SHIFT		3
+#define XT2000_SYSRST_V3_MASK		0x00000008
+
+/*  IMASK (interrupt mask; 0=disable, 1=enable):  */
+/*  ISTAT (interrupt status; 0=inactive, 1=pending):  */
+
+/*  PCI INTP interrupt:  */
+#define XT2000_INTMUX_PCI_INTP_SHIFT	2
+#define XT2000_INTMUX_PCI_INTP_MASK	0x00000004
+/*  PCI INTS interrupt:  */
+#define XT2000_INTMUX_PCI_INTS_SHIFT	3
+#define XT2000_INTMUX_PCI_INTS_MASK	0x00000008
+/*  PCI INTD interrupt:  */
+#define XT2000_INTMUX_PCI_INTD_SHIFT	4
+#define XT2000_INTMUX_PCI_INTD_MASK	0x00000010
+/*  V320 PCI controller interrupt:  */
+#define XT2000_INTMUX_V3_SHIFT		5
+#define XT2000_INTMUX_V3_MASK		0x00000020
+/*  PCI ENUM interrupt:  */
+#define XT2000_INTMUX_PCI_ENUM_SHIFT	6
+#define XT2000_INTMUX_PCI_ENUM_MASK	0x00000040
+/*  PCI DEG interrupt:  */
+#define XT2000_INTMUX_PCI_DEG_SHIFT	7
+#define XT2000_INTMUX_PCI_DEG_MASK	0x00000080
+
+/*  V3CFG (V3 config, V320 PCI controller):  */
+
+/*  V3 address control (0=pass-thru, 1=V3 address bits 31:28 set to 4'b0001 [default]):  */
+#define XT2000_V3CFG_V3ADC_SHIFT	0
+#define XT2000_V3CFG_V3ADC_MASK		0x00000001
+
+/* I2C Devices */
+
+#define	XT2000_I2C_RTC_ID		0x68
+#define	XT2000_I2C_NVRAM0_ID		0x56	/* 1st 256 byte block */
+#define	XT2000_I2C_NVRAM1_ID		0x57	/* 2nd 256 byte block */
+
+/*  NVRAM Board Info structure:  */
+
+#define XT2000_NVRAM_SIZE		512
+
+#define XT2000_NVRAM_BINFO_START	0x100
+#define XT2000_NVRAM_BINFO_SIZE		0x20
+#define XT2000_NVRAM_BINFO_VERSION	0x10	/* version 1.0 */
+#if 0
+#define XT2000_NVRAM_BINFO_VERSION_OFFSET	0x00
+#define XT2000_NVRAM_BINFO_VERSION_SIZE			0x1
+#define XT2000_NVRAM_BINFO_ETH_ADDR_OFFSET	0x02
+#define XT2000_NVRAM_BINFO_ETH_ADDR_SIZE		0x6
+#define XT2000_NVRAM_BINFO_SN_OFFSET		0x10
+#define XT2000_NVRAM_BINFO_SN_SIZE			0xE
+#define	XT2000_NVRAM_BINFO_CRC_OFFSET		0x1E
+#define	XT2000_NVRAM_BINFO_CRC_SIZE			0x2
+#endif /*0*/
+
+#if !defined(__ASSEMBLY__) && !defined(_NOCLANGUAGE)
+typedef struct xt2000_nvram_binfo {
+    unsigned char	version;
+    unsigned char	reserved1;
+    unsigned char	eth_addr[6];
+    unsigned char	reserved8[8];
+    unsigned char	serialno[14];
+    unsigned char	crc[2];		/* 16-bit CRC */
+} xt2000_nvram_binfo;
+#endif /*!__ASSEMBLY__ && !_NOCLANGUAGE*/
+
+
+#endif /*_INC_XT2000_H_*/
+
diff --git a/include/asm-xtensa/xtensa/xtboard.h b/include/asm-xtensa/xtensa/xtboard.h
new file mode 100644
index 0000000..22469c1
--- /dev/null
+++ b/include/asm-xtensa/xtensa/xtboard.h
@@ -0,0 +1,120 @@
+#ifndef _xtboard_h_included_
+#define _xtboard_h_included_
+
+/*
+ * THIS FILE IS GENERATED -- DO NOT MODIFY BY HAND
+ *
+ *  xtboard.h  --  Routines for getting useful information from the board.
+ *
+ * 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) 2002 Tensilica Inc.
+ */
+
+
+#include <xtensa/xt2000.h>
+
+#define	XTBOARD_RTC_ERROR	-1
+#define	XTBOARD_RTC_STOPPED	-2
+
+
+/*  xt2000-i2cdev.c:  */
+typedef void XtboardDelayFunc( unsigned );
+extern XtboardDelayFunc* xtboard_set_nsdelay_func( XtboardDelayFunc *delay_fn );
+extern int xtboard_i2c_read (unsigned id, unsigned char *buf, unsigned addr, unsigned size);
+extern int xtboard_i2c_write(unsigned id, unsigned char *buf, unsigned addr, unsigned size);
+extern int xtboard_i2c_wait_nvram_ack(unsigned id, unsigned swtimer);
+
+/*  xtboard.c:  */
+extern int xtboard_nvram_read (unsigned addr, unsigned len, unsigned char *buf);
+extern int xtboard_nvram_write(unsigned addr, unsigned len, unsigned char *buf);
+extern int xtboard_nvram_binfo_read (xt2000_nvram_binfo *buf);
+extern int xtboard_nvram_binfo_write(xt2000_nvram_binfo *buf);
+extern int xtboard_nvram_binfo_valid(xt2000_nvram_binfo *buf);
+extern int xtboard_ethermac_get(unsigned char *buf);
+extern int xtboard_ethermac_set(unsigned char *buf);
+
+/*+*----------------------------------------------------------------------------
+/ Function: xtboard_get_rtc_time
+/
+/ Description:  Get time stored in real-time clock.
+/
+/ Returns: time in seconds stored in real-time clock.
+/-**----------------------------------------------------------------------------*/
+
+extern unsigned xtboard_get_rtc_time(void);
+
+/*+*----------------------------------------------------------------------------
+/ Function: xtboard_set_rtc_time
+/
+/ Description:  Set time stored in real-time clock.
+/
+/ Parameters: 	time -- time in seconds to store to real-time clock
+/
+/ Returns: 0 on success, xtboard_i2c_write() error code otherwise.
+/-**----------------------------------------------------------------------------*/
+
+extern int xtboard_set_rtc_time(unsigned time);
+
+
+/*  xtfreq.c:  */
+/*+*----------------------------------------------------------------------------
+/ Function: xtboard_measure_sys_clk
+/
+/ Description:  Get frequency of system clock.
+/
+/ Parameters:	none
+/
+/ Returns: frequency of system clock.
+/-**----------------------------------------------------------------------------*/
+
+extern unsigned xtboard_measure_sys_clk(void);
+
+
+#if 0	/* old stuff from xtboard.c: */
+
+/*+*----------------------------------------------------------------------------
+/ Function: xtboard_nvram valid
+/
+/ Description:  Determines if data in NVRAM is valid.
+/
+/ Parameters:	delay -- 10us delay function
+/
+/ Returns: 1 if NVRAM is valid, 0 otherwise
+/-**----------------------------------------------------------------------------*/
+
+extern unsigned xtboard_nvram_valid(void (*delay)( void ));
+
+/*+*----------------------------------------------------------------------------
+/ Function: xtboard_get_nvram_contents
+/
+/ Description:  Returns contents of NVRAM.
+/
+/ Parameters: 	buf -- buffer to NVRAM contents.
+/		delay -- 10us delay function
+/
+/ Returns: 1 if NVRAM is valid, 0 otherwise
+/-**----------------------------------------------------------------------------*/
+
+extern unsigned xtboard_get_nvram_contents(unsigned char *buf, void (*delay)( void ));
+
+/*+*----------------------------------------------------------------------------
+/ Function: xtboard_get_ether_addr
+/
+/ Description:  Returns ethernet address of board.
+/
+/ Parameters: 	buf -- buffer to store ethernet address
+/		delay -- 10us delay function
+/
+/ Returns: nothing.
+/-**----------------------------------------------------------------------------*/
+
+extern void xtboard_get_ether_addr(unsigned char *buf, void (*delay)( void ));
+
+#endif /*0*/
+
+
+#endif /*_xtboard_h_included_*/
+
diff --git a/include/linux/a.out.h b/include/linux/a.out.h
index af8a1df..f913cc3 100644
--- a/include/linux/a.out.h
+++ b/include/linux/a.out.h
@@ -138,7 +138,7 @@
 #endif
 #endif
 
-#define _N_SEGMENT_ROUND(x) (((x) + SEGMENT_SIZE - 1) & ~(SEGMENT_SIZE - 1))
+#define _N_SEGMENT_ROUND(x) ALIGN(x, SEGMENT_SIZE)
 
 #define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
 
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index d5a55bd..b123cc0 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -25,6 +25,8 @@
 #ifndef _LINUX_ACPI_H
 #define _LINUX_ACPI_H
 
+#include <linux/config.h>
+
 #ifdef	CONFIG_ACPI
 
 #ifndef _LINUX
diff --git a/include/linux/arcfb.h b/include/linux/arcfb.h
new file mode 100644
index 0000000..721e765
--- /dev/null
+++ b/include/linux/arcfb.h
@@ -0,0 +1,8 @@
+#ifndef __LINUX_ARCFB_H__
+#define __LINUX_ARCFB_H__
+
+#define FBIO_WAITEVENT		_IO('F', 0x88)
+#define FBIO_GETCONTROL2	_IOR('F', 0x89, size_t)
+
+#endif
+
diff --git a/include/linux/ata.h b/include/linux/ata.h
index f178894..ca5fcad 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -224,6 +224,7 @@
 };
 
 #define ata_id_is_ata(id)	(((id)[0] & (1 << 15)) == 0)
+#define ata_id_is_sata(id)	((id)[93] == 0)
 #define ata_id_rahead_enabled(id) ((id)[85] & (1 << 6))
 #define ata_id_wcache_enabled(id) ((id)[85] & (1 << 5))
 #define ata_id_has_flush(id) ((id)[83] & (1 << 12))
diff --git a/include/linux/atalk.h b/include/linux/atalk.h
index 31d3fc2..911c09c 100644
--- a/include/linux/atalk.h
+++ b/include/linux/atalk.h
@@ -1,6 +1,8 @@
 #ifndef __LINUX_ATALK_H__
 #define __LINUX_ATALK_H__
 
+#include <asm/byteorder.h>
+
 /*
  * AppleTalk networking structures
  *
@@ -20,7 +22,7 @@
 #define SIOCATALKDIFADDR       (SIOCPROTOPRIVATE + 0)
 
 struct atalk_addr {
-	__u16	s_net;
+	__be16	s_net;
 	__u8	s_node;
 };
 
@@ -33,8 +35,8 @@
 
 struct atalk_netrange {
 	__u8	nr_phase;
-	__u16	nr_firstnet;
-	__u16	nr_lastnet;
+	__be16	nr_firstnet;
+	__be16	nr_lastnet;
 };
 
 #ifdef __KERNEL__
@@ -70,8 +72,8 @@
 struct atalk_sock {
 	/* struct sock has to be the first member of atalk_sock */
 	struct sock	sk;
-	unsigned short	dest_net;
-	unsigned short	src_net;
+	__be16		dest_net;
+	__be16		src_net;
 	unsigned char	dest_node;
 	unsigned char	src_node;
 	unsigned char	dest_port;
@@ -95,9 +97,9 @@
 		deh_hops:4,
 		deh_len:10;
 #endif
-	__u16	deh_sum;
-	__u16	deh_dnet;
-	__u16	deh_snet;
+	__be16	deh_sum;
+	__be16	deh_dnet;
+	__be16	deh_snet;
 	__u8	deh_dnode;
 	__u8	deh_snode;
 	__u8	deh_dport;
@@ -142,24 +144,24 @@
 
 /* AppleTalk AARP headers */
 struct elapaarp {
-	__u16	hw_type;
+	__be16	hw_type;
 #define AARP_HW_TYPE_ETHERNET		1
 #define AARP_HW_TYPE_TOKENRING		2
-	__u16	pa_type;
+	__be16	pa_type;
 	__u8	hw_len;
 	__u8	pa_len;
 #define AARP_PA_ALEN			4
-	__u16	function;
+	__be16	function;
 #define AARP_REQUEST			1
 #define AARP_REPLY			2
 #define AARP_PROBE			3
 	__u8	hw_src[ETH_ALEN]	__attribute__ ((packed));
 	__u8	pa_src_zero		__attribute__ ((packed));
-	__u16	pa_src_net		__attribute__ ((packed));
+	__be16	pa_src_net		__attribute__ ((packed));
 	__u8	pa_src_node		__attribute__ ((packed));
 	__u8	hw_dst[ETH_ALEN]	__attribute__ ((packed));
 	__u8	pa_dst_zero		__attribute__ ((packed));
-	__u16	pa_dst_net		__attribute__ ((packed));
+	__be16	pa_dst_net		__attribute__ ((packed));
 	__u8	pa_dst_node		__attribute__ ((packed));	
 };
 
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 19f04b0..bf2ad3b 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -27,15 +27,52 @@
 #include <linux/sched.h>
 #include <linux/elf.h>
 
-/* Request and reply types */
-#define AUDIT_GET      1000	/* Get status */
-#define AUDIT_SET      1001	/* Set status (enable/disable/auditd) */
-#define AUDIT_LIST     1002	/* List filtering rules */
-#define AUDIT_ADD      1003	/* Add filtering rule */
-#define AUDIT_DEL      1004	/* Delete filtering rule */
-#define AUDIT_USER     1005	/* Send a message from user-space */
-#define AUDIT_LOGIN    1006     /* Define the login id and informaiton */
-#define AUDIT_KERNEL   2000	/* Asynchronous audit record. NOT A REQUEST. */
+/* The netlink messages for the audit system is divided into blocks:
+ * 1000 - 1099 are for commanding the audit system
+ * 1100 - 1199 user space trusted application messages
+ * 1200 - 1299 messages internal to the audit daemon
+ * 1300 - 1399 audit event messages
+ * 1400 - 1499 SE Linux use
+ * 1500 - 1999 future use
+ * 2000 is for otherwise unclassified kernel audit messages
+ *
+ * Messages from 1000-1199 are bi-directional. 1200-1299 are exclusively user
+ * space. Anything over that is kernel --> user space communication.
+ */
+#define AUDIT_GET		1000	/* Get status */
+#define AUDIT_SET		1001	/* Set status (enable/disable/auditd) */
+#define AUDIT_LIST		1002	/* List syscall filtering rules */
+#define AUDIT_ADD		1003	/* Add syscall filtering rule */
+#define AUDIT_DEL		1004	/* Delete syscall filtering rule */
+#define AUDIT_USER		1005	/* Message from userspace -- deprecated */
+#define AUDIT_LOGIN		1006	/* Define the login id and information */
+#define AUDIT_WATCH_INS		1007	/* Insert file/dir watch entry */
+#define AUDIT_WATCH_REM		1008	/* Remove file/dir watch entry */
+#define AUDIT_WATCH_LIST	1009	/* List all file/dir watches */
+#define AUDIT_SIGNAL_INFO	1010	/* Get info about sender of signal to auditd */
+
+#define AUDIT_FIRST_USER_MSG	1100	/* Userspace messages uninteresting to kernel */
+#define AUDIT_LAST_USER_MSG	1199
+ 
+#define AUDIT_DAEMON_START      1200    /* Daemon startup record */
+#define AUDIT_DAEMON_END        1201    /* Daemon normal stop record */
+#define AUDIT_DAEMON_ABORT      1202    /* Daemon error stop record */
+#define AUDIT_DAEMON_CONFIG     1203    /* Daemon config change */
+
+#define AUDIT_SYSCALL		1300	/* Syscall event */
+#define AUDIT_FS_WATCH		1301	/* Filesystem watch event */
+#define AUDIT_PATH		1302	/* Filename path information */
+#define AUDIT_IPC		1303	/* IPC record */
+#define AUDIT_SOCKETCALL	1304	/* sys_socketcall arguments */
+#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_AVC		1400	/* SE Linux avc denial or grant */
+#define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
+#define AUDIT_AVC_PATH		1402	/* dentry, vfsmount pair from avc */
+
+#define AUDIT_KERNEL		2000	/* Asynchronous audit record. NOT A REQUEST. */
 
 /* Rule flags */
 #define AUDIT_PER_TASK 0x01	/* Apply rule at task creation (not syscall) */
@@ -132,16 +169,9 @@
 #define AUDIT_ARCH_V850		(EM_V850|__AUDIT_ARCH_LE)
 #define AUDIT_ARCH_X86_64	(EM_X86_64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
 
-#ifndef __KERNEL__
-struct audit_message {
-	struct nlmsghdr nlh;
-	char		data[1200];
-};
-#endif
-
 struct audit_status {
 	__u32		mask;		/* Bit mask for valid entries */
-	__u32		enabled;	/* 1 = enabled, 0 = disbaled */
+	__u32		enabled;	/* 1 = enabled, 0 = disabled */
 	__u32		failure;	/* Failure-to-log action */
 	__u32		pid;		/* pid of auditd process */
 	__u32		rate_limit;	/* messages rate limit (per second) */
@@ -161,6 +191,11 @@
 
 #ifdef __KERNEL__
 
+struct audit_sig_info {
+	uid_t		uid;
+	pid_t		pid;
+};
+
 struct audit_buffer;
 struct audit_context;
 struct inode;
@@ -185,11 +220,16 @@
 				/* Private API (for audit.c only) */
 extern int  audit_receive_filter(int type, int pid, int uid, int seq,
 				 void *data, uid_t loginuid);
-extern void audit_get_stamp(struct audit_context *ctx,
-			    struct timespec *t, unsigned int *serial);
+extern unsigned int audit_serial(void);
+extern void auditsc_get_stamp(struct audit_context *ctx,
+			      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_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
+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);
 #else
 #define audit_alloc(t) ({ 0; })
 #define audit_free(t) do { ; } while (0)
@@ -198,18 +238,24 @@
 #define audit_getname(n) do { ; } while (0)
 #define audit_putname(n) do { ; } while (0)
 #define audit_inode(n,i) do { ; } while (0)
+#define audit_receive_filter(t,p,u,s,d,l) ({ -EOPNOTSUPP; })
+#define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
 #define audit_get_loginuid(c) ({ -1; })
 #define audit_ipc_perms(q,u,g,m) ({ 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)
 #endif
 
 #ifdef CONFIG_AUDIT
 /* These are defined in audit.c */
 				/* Public API */
-extern void		    audit_log(struct audit_context *ctx,
+extern void		    audit_log(struct audit_context *ctx, int type,
 				      const char *fmt, ...)
-			    __attribute__((format(printf,2,3)));
+			    __attribute__((format(printf,3,4)));
 
-extern struct audit_buffer *audit_log_start(struct audit_context *ctx);
+extern struct audit_buffer *audit_log_start(struct audit_context *ctx,int type);
 extern void		    audit_log_format(struct audit_buffer *ab,
 					     const char *fmt, ...)
 			    __attribute__((format(printf,2,3)));
@@ -229,8 +275,8 @@
 					     void *payload, int size);
 extern void		    audit_log_lost(const char *message);
 #else
-#define audit_log(t,f,...) do { ; } while (0)
-#define audit_log_start(t) ({ NULL; })
+#define audit_log(c,t,f,...) do { ; } while (0)
+#define audit_log_start(c,t) ({ NULL; })
 #define audit_log_vformat(b,f,a) do { ; } while (0)
 #define audit_log_format(b,f,...) do { ; } while (0)
 #define audit_log_end(b) do { ; } while (0)
diff --git a/include/linux/auto_fs4.h b/include/linux/auto_fs4.h
index a1657fb..9343c89 100644
--- a/include/linux/auto_fs4.h
+++ b/include/linux/auto_fs4.h
@@ -23,7 +23,7 @@
 #define AUTOFS_MIN_PROTO_VERSION	3
 #define AUTOFS_MAX_PROTO_VERSION	4
 
-#define AUTOFS_PROTO_SUBVERSION		6
+#define AUTOFS_PROTO_SUBVERSION		7
 
 /* Mask for expire behaviour */
 #define AUTOFS_EXP_IMMEDIATE		1
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 7e736e2..c1e82c5 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -69,6 +69,11 @@
 extern int search_binary_handler(struct linux_binprm *,struct pt_regs *);
 extern int flush_old_exec(struct linux_binprm * bprm);
 
+extern int suid_dumpable;
+#define SUID_DUMP_DISABLE	0	/* No setuid dumping */
+#define SUID_DUMP_USER		1	/* Dump as user of process */
+#define SUID_DUMP_ROOT		2	/* Dump as root */
+
 /* Stack area protections */
 #define EXSTACK_DEFAULT   0	/* Whatever the arch defaults to */
 #define EXSTACK_DISABLE_X 1	/* Disable executable stacks */
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 0380227..36ef29f 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -22,6 +22,7 @@
 
 #include <linux/highmem.h>
 #include <linux/mempool.h>
+#include <linux/ioprio.h>
 
 /* Platforms may set this to teach the BIO layer about IOMMU hardware. */
 #include <asm/io.h>
@@ -150,6 +151,19 @@
 #define BIO_RW_SYNC	4
 
 /*
+ * upper 16 bits of bi_rw define the io priority of this bio
+ */
+#define BIO_PRIO_SHIFT	(8 * sizeof(unsigned long) - IOPRIO_BITS)
+#define bio_prio(bio)	((bio)->bi_rw >> BIO_PRIO_SHIFT)
+#define bio_prio_valid(bio)	ioprio_valid(bio_prio(bio))
+
+#define bio_set_prio(bio, prio)		do {			\
+	WARN_ON(prio >= (1 << IOPRIO_BITS));			\
+	(bio)->bi_rw &= ((1UL << BIO_PRIO_SHIFT) - 1);		\
+	(bio)->bi_rw |= ((unsigned long) (prio) << BIO_PRIO_SHIFT);	\
+} while (0)
+
+/*
  * various member access, note that bio_data should of course not be used
  * on highmem page vectors
  */
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index ef1afc1..21a8674 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -54,16 +54,23 @@
 
 struct cfq_queue;
 struct cfq_io_context {
-	void (*dtor)(struct cfq_io_context *);
-	void (*exit)(struct cfq_io_context *);
-
-	struct io_context *ioc;
-
 	/*
 	 * circular list of cfq_io_contexts belonging to a process io context
 	 */
 	struct list_head list;
 	struct cfq_queue *cfqq;
+	void *key;
+
+	struct io_context *ioc;
+
+	unsigned long last_end_request;
+	unsigned long last_queue;
+	unsigned long ttime_total;
+	unsigned long ttime_samples;
+	unsigned long ttime_mean;
+
+	void (*dtor)(struct cfq_io_context *);
+	void (*exit)(struct cfq_io_context *);
 };
 
 /*
@@ -73,7 +80,9 @@
  */
 struct io_context {
 	atomic_t refcount;
-	pid_t pid;
+	struct task_struct *task;
+
+	int (*set_ioprio)(struct io_context *, unsigned int);
 
 	/*
 	 * For request batching
@@ -81,8 +90,6 @@
 	unsigned long last_waited; /* Time last woken after wait for request */
 	int nr_batch_requests;     /* Number of requests left in the batch */
 
-	spinlock_t lock;
-
 	struct as_io_context *aic;
 	struct cfq_io_context *cic;
 };
@@ -134,6 +141,8 @@
 
 	void *elevator_private;
 
+	unsigned short ioprio;
+
 	int rq_status;	/* should split this into a few status bits */
 	struct gendisk *rq_disk;
 	int errors;
@@ -285,16 +294,12 @@
 	Queue_up,
 };
 
-#define BLK_TAGS_PER_LONG	(sizeof(unsigned long) * 8)
-#define BLK_TAGS_MASK		(BLK_TAGS_PER_LONG - 1)
-
 struct blk_queue_tag {
 	struct request **tag_index;	/* map of busy tags */
 	unsigned long *tag_map;		/* bit map of free/busy tags */
 	struct list_head busy_list;	/* fifo list of busy tags */
 	int busy;			/* current depth */
 	int max_depth;			/* what we will send to device */
-	int real_max_depth;		/* what the array can hold */
 	atomic_t refcnt;		/* map can be shared */
 };
 
@@ -396,6 +401,7 @@
 	 */
 	unsigned int		sg_timeout;
 	unsigned int		sg_reserved_size;
+	int			node;
 
 	struct list_head	drain_list;
 
@@ -542,15 +548,12 @@
 extern void blk_put_request(struct request *);
 extern void blk_end_sync_rq(struct request *rq);
 extern void blk_attempt_remerge(request_queue_t *, struct request *);
-extern void __blk_attempt_remerge(request_queue_t *, struct request *);
 extern struct request *blk_get_request(request_queue_t *, int, int);
-extern void blk_insert_request(request_queue_t *, struct request *, int, void *, int);
+extern void blk_insert_request(request_queue_t *, struct request *, int, void *);
 extern void blk_requeue_request(request_queue_t *, struct request *);
 extern void blk_plug_device(request_queue_t *);
 extern int blk_remove_plug(request_queue_t *);
 extern void blk_recount_segments(request_queue_t *, struct bio *);
-extern int blk_phys_contig_segment(request_queue_t *q, struct bio *, struct bio *);
-extern int blk_hw_contig_segment(request_queue_t *q, struct bio *, struct bio *);
 extern int scsi_cmd_ioctl(struct file *, struct gendisk *, unsigned int, void __user *);
 extern void blk_start_queue(request_queue_t *q);
 extern void blk_stop_queue(request_queue_t *q);
@@ -615,6 +618,8 @@
 /*
  * Access functions for manipulating queue properties
  */
+extern request_queue_t *blk_init_queue_node(request_fn_proc *rfn,
+					spinlock_t *lock, int node_id);
 extern request_queue_t *blk_init_queue(request_fn_proc *, spinlock_t *);
 extern void blk_cleanup_queue(request_queue_t *);
 extern void blk_queue_make_request(request_queue_t *, make_request_fn *);
@@ -632,7 +637,6 @@
 extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev);
 extern void blk_queue_ordered(request_queue_t *, int);
 extern void blk_queue_issue_flush_fn(request_queue_t *, issue_flush_fn *);
-extern int blkdev_scsi_issue_flush_fn(request_queue_t *, struct gendisk *, sector_t *);
 extern struct request *blk_start_pre_flush(request_queue_t *,struct request *);
 extern int blk_complete_barrier_rq(request_queue_t *, struct request *, int);
 extern int blk_complete_barrier_rq_locked(request_queue_t *, struct request *, int);
@@ -646,7 +650,8 @@
 extern void blk_finish_queue_drain(request_queue_t *);
 
 int blk_get_queue(request_queue_t *);
-request_queue_t *blk_alloc_queue(int);
+request_queue_t *blk_alloc_queue(int gfp_mask);
+request_queue_t *blk_alloc_queue_node(int,int);
 #define blk_put_queue(q) blk_cleanup_queue((q))
 
 /*
@@ -675,8 +680,6 @@
 
 #define blkdev_entry_to_request(entry) list_entry((entry), struct request, queuelist)
 
-extern void drive_stat_acct(struct request *, int, int);
-
 static inline int queue_hardsect_size(request_queue_t *q)
 {
 	int retval = 512;
diff --git a/include/linux/bootmem.h b/include/linux/bootmem.h
index 0dd8ca1..82bd884 100644
--- a/include/linux/bootmem.h
+++ b/include/linux/bootmem.h
@@ -22,6 +22,10 @@
  */
 extern unsigned long max_pfn;
 
+#ifdef CONFIG_CRASH_DUMP
+extern unsigned long saved_max_pfn;
+#endif
+
 /*
  * node_bootmem_map is a map pointer - the bits represent all physical 
  * memory pages (including holes) on the node.
@@ -67,6 +71,15 @@
 	__alloc_bootmem_node((pgdat), (x), PAGE_SIZE, 0)
 #endif /* !CONFIG_HAVE_ARCH_BOOTMEM_NODE */
 
+#ifdef CONFIG_HAVE_ARCH_ALLOC_REMAP
+extern void *alloc_remap(int nid, unsigned long size);
+#else
+static inline void *alloc_remap(int nid, unsigned long size)
+{
+	return NULL;
+}
+#endif
+
 extern unsigned long __initdata nr_kernel_pages;
 extern unsigned long __initdata nr_all_pages;
 
diff --git a/include/linux/chio.h b/include/linux/chio.h
new file mode 100644
index 0000000..63035ae
--- /dev/null
+++ b/include/linux/chio.h
@@ -0,0 +1,168 @@
+/*
+ * ioctl interface for the scsi media changer driver
+ */
+
+/* changer element types */
+#define CHET_MT   0	/* media transport element (robot) */
+#define CHET_ST   1	/* storage element (media slots) */
+#define CHET_IE   2	/* import/export element */
+#define CHET_DT   3	/* data transfer element (tape/cdrom/whatever) */
+#define CHET_V1   4	/* vendor specific #1 */
+#define CHET_V2   5	/* vendor specific #2 */
+#define CHET_V3   6	/* vendor specific #3 */
+#define CHET_V4   7	/* vendor specific #4 */
+
+
+/*
+ * CHIOGPARAMS
+ *    query changer properties
+ *
+ * CHIOVGPARAMS
+ *    query vendor-specific element types
+ *
+ *    accessing elements works by specifing type and unit of the element.
+ *    for eample, storage elements are addressed with type = CHET_ST and
+ *    unit = 0 .. cp_nslots-1
+ *
+ */
+struct changer_params {
+	int cp_curpicker;  /* current transport element */
+	int cp_npickers;   /* number of transport elements      (CHET_MT) */
+	int cp_nslots;     /* number of storage elements        (CHET_ST) */
+	int cp_nportals;   /* number of import/export elements  (CHET_IE) */
+	int cp_ndrives;    /* number of data transfer elements  (CHET_DT) */
+};
+struct changer_vendor_params {
+	int  cvp_n1;       /* number of vendor specific elems   (CHET_V1) */
+	char cvp_label1[16];
+	int  cvp_n2;       /* number of vendor specific elems   (CHET_V2) */
+	char cvp_label2[16];
+	int  cvp_n3;       /* number of vendor specific elems   (CHET_V3) */
+	char cvp_label3[16];
+	int  cvp_n4;       /* number of vendor specific elems   (CHET_V4) */
+	char cvp_label4[16];
+	int  reserved[8];
+};
+
+
+/*
+ * CHIOMOVE
+ *    move a medium from one element to another
+ */
+struct changer_move {
+	int cm_fromtype;	/* type/unit of source element */
+	int cm_fromunit;	
+	int cm_totype;	/* type/unit of destination element */
+	int cm_tounit;
+	int cm_flags;
+};
+#define CM_INVERT   1   /* flag: rotate media (for double-sided like MOD) */
+
+
+/*
+ * CHIOEXCHANGE
+ *    move one medium from element #1 to element #2,
+ *    and another one from element #2 to element #3.
+ *    element #1 and #3 are allowed to be identical.
+ */
+struct changer_exchange {
+	int ce_srctype;	    /* type/unit of element #1 */
+	int ce_srcunit;
+	int ce_fdsttype;    /* type/unit of element #2 */
+	int ce_fdstunit;
+	int ce_sdsttype;    /* type/unit of element #3 */
+	int ce_sdstunit;
+	int ce_flags;
+};
+#define CE_INVERT1   1
+#define CE_INVERT2   2
+
+
+/*
+ * CHIOPOSITION
+ *    move the transport element (robot arm) to a specific element.
+ */
+struct changer_position {
+	int cp_type;
+	int cp_unit;
+	int cp_flags;
+};
+#define CP_INVERT   1
+
+
+/*
+ * CHIOGSTATUS
+ *    get element status for all elements of a specific type
+ */
+struct changer_element_status {
+	int             ces_type;
+	unsigned char   *ces_data;
+};
+#define CESTATUS_FULL     0x01 /* full */
+#define CESTATUS_IMPEXP   0x02	/* media was imported (inserted by sysop) */
+#define CESTATUS_EXCEPT   0x04	/* error condition */
+#define CESTATUS_ACCESS   0x08	/* access allowed */
+#define CESTATUS_EXENAB   0x10	/* element can export media */
+#define CESTATUS_INENAB   0x20	/* element can import media */
+
+
+/*
+ * CHIOGELEM
+ *    get more detailed status informtion for a single element
+ */
+struct changer_get_element {
+	int	cge_type;	 /* type/unit */
+	int	cge_unit;
+	int	cge_status;      /* status */
+	int     cge_errno;       /* errno */
+	int     cge_srctype;     /* source element of the last move/exchange */
+	int     cge_srcunit;
+	int     cge_id;          /* scsi id  (for data transfer elements) */
+	int     cge_lun;         /* scsi lun (for data transfer elements) */
+	char    cge_pvoltag[36]; /* primary volume tag */
+	char    cge_avoltag[36]; /* alternate volume tag */
+	int     cge_flags;
+};
+/* flags */
+#define CGE_ERRNO     0x01       /* errno available       */
+#define CGE_INVERT    0x02       /* media inverted        */
+#define CGE_SRC       0x04       /* media src available   */
+#define CGE_IDLUN     0x08       /* ID+LUN available      */
+#define CGE_PVOLTAG   0x10       /* primary volume tag available */
+#define CGE_AVOLTAG   0x20       /* alternate volume tag available */
+
+
+/*
+ * CHIOSVOLTAG
+ *    set volume tag
+ */
+struct changer_set_voltag {
+	int	csv_type;	 /* type/unit */
+	int	csv_unit;
+	char    csv_voltag[36];  /* volume tag */
+	int     csv_flags;
+};
+#define CSV_PVOLTAG   0x01       /* primary volume tag */
+#define CSV_AVOLTAG   0x02       /* alternate volume tag */
+#define CSV_CLEARTAG  0x04       /* clear volume tag */
+
+/* ioctls */
+#define CHIOMOVE       _IOW('c', 1,struct changer_move)
+#define CHIOEXCHANGE   _IOW('c', 2,struct changer_exchange)
+#define CHIOPOSITION   _IOW('c', 3,struct changer_position)
+#define CHIOGPICKER    _IOR('c', 4,int)                        /* not impl. */
+#define CHIOSPICKER    _IOW('c', 5,int)                        /* not impl. */
+#define CHIOGPARAMS    _IOR('c', 6,struct changer_params)
+#define CHIOGSTATUS    _IOW('c', 8,struct changer_element_status)
+#define CHIOGELEM      _IOW('c',16,struct changer_get_element)
+#define CHIOINITELEM   _IO('c',17)
+#define CHIOSVOLTAG    _IOW('c',18,struct changer_set_voltag)
+#define CHIOGVPARAMS   _IOR('c',19,struct changer_vendor_params)
+
+/* ---------------------------------------------------------------------- */
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index fe0298e..e8904c0 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -69,6 +69,7 @@
 	register_cpu_notifier(&fn##_nb);			\
 }
 int cpu_down(unsigned int cpu);
+extern int __attribute__((weak)) smp_prepare_cpu(int cpu);
 #define cpu_is_offline(cpu) unlikely(!cpu_online(cpu))
 #else
 #define lock_cpu_hotplug()	do { } while (0)
diff --git a/include/linux/crash_dump.h b/include/linux/crash_dump.h
new file mode 100644
index 0000000..534d750
--- /dev/null
+++ b/include/linux/crash_dump.h
@@ -0,0 +1,18 @@
+#ifndef LINUX_CRASH_DUMP_H
+#define LINUX_CRASH_DUMP_H
+
+#ifdef CONFIG_CRASH_DUMP
+#include <linux/kexec.h>
+#include <linux/smp_lock.h>
+#include <linux/device.h>
+#include <linux/proc_fs.h>
+
+#define ELFCORE_ADDR_MAX	(-1ULL)
+extern unsigned long long elfcorehdr_addr;
+extern ssize_t copy_oldmem_page(unsigned long, char *, size_t,
+						unsigned long, int);
+extern struct file_operations proc_vmcore_operations;
+extern struct proc_dir_entry *proc_vmcore;
+
+#endif /* CONFIG_CRASH_DUMP */
+#endif /* LINUX_CRASHDUMP_H */
diff --git a/include/linux/device.h b/include/linux/device.h
index df94c0d..7b781a7 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -14,6 +14,7 @@
 #include <linux/config.h>
 #include <linux/ioport.h>
 #include <linux/kobject.h>
+#include <linux/klist.h>
 #include <linux/list.h>
 #include <linux/types.h>
 #include <linux/module.h>
@@ -44,14 +45,15 @@
 struct device_driver;
 struct class;
 struct class_device;
-struct class_simple;
 
 struct bus_type {
-	char			* name;
+	const char		* name;
 
 	struct subsystem	subsys;
 	struct kset		drivers;
 	struct kset		devices;
+	struct klist		klist_devices;
+	struct klist		klist_drivers;
 
 	struct bus_attribute	* bus_attrs;
 	struct device_attribute	* dev_attrs;
@@ -98,17 +100,18 @@
 extern void bus_remove_file(struct bus_type *, struct bus_attribute *);
 
 struct device_driver {
-	char			* name;
+	const char		* name;
 	struct bus_type		* bus;
 
 	struct completion	unloaded;
 	struct kobject		kobj;
-	struct list_head	devices;
+	struct klist		klist_devices;
+	struct klist_node	knode_bus;
 
-	struct module 		* owner;
+	struct module		* owner;
 
 	int	(*probe)	(struct device * dev);
-	int 	(*remove)	(struct device * dev);
+	int	(*remove)	(struct device * dev);
 	void	(*shutdown)	(struct device * dev);
 	int	(*suspend)	(struct device * dev, pm_message_t state, u32 level);
 	int	(*resume)	(struct device * dev, u32 level);
@@ -137,12 +140,16 @@
 extern int driver_create_file(struct device_driver *, struct driver_attribute *);
 extern void driver_remove_file(struct device_driver *, struct driver_attribute *);
 
+extern int driver_for_each_device(struct device_driver * drv, struct device * start,
+				  void * data, int (*fn)(struct device *, void *));
+
 
 /*
  * device classes
  */
 struct class {
-	char			* name;
+	const char		* name;
+	struct module		* owner;
 
 	struct subsystem	subsys;
 	struct list_head	children;
@@ -185,6 +192,7 @@
 	struct kobject		kobj;
 	struct class		* class;	/* required */
 	dev_t			devt;		/* dev_t, creates the sysfs "dev" */
+	struct class_device_attribute *devt_attr;
 	struct device		* dev;		/* not necessary, but nice to have */
 	void			* class_data;	/* class-specific data */
 
@@ -245,26 +253,28 @@
 extern int class_interface_register(struct class_interface *);
 extern void class_interface_unregister(struct class_interface *);
 
-/* interface for class simple stuff */
-extern struct class_simple *class_simple_create(struct module *owner, char *name);
-extern void class_simple_destroy(struct class_simple *cs);
-extern struct class_device *class_simple_device_add(struct class_simple *cs, dev_t dev, struct device *device, const char *fmt, ...)
-	__attribute__((format(printf,4,5)));
-extern int class_simple_set_hotplug(struct class_simple *, 
-	int (*hotplug)(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size));
-extern void class_simple_device_remove(dev_t dev);
+extern struct class *class_create(struct module *owner, char *name);
+extern void class_destroy(struct class *cls);
+extern struct class_device *class_device_create(struct class *cls, dev_t devt,
+						struct device *device, char *fmt, ...)
+					__attribute__((format(printf,4,5)));
+extern void class_device_destroy(struct class *cls, dev_t devt);
 
 
 struct device {
-	struct list_head node;		/* node in sibling list */
-	struct list_head bus_list;	/* node in bus's list */
-	struct list_head driver_list;
-	struct list_head children;
+	struct klist		klist_children;
+	struct klist_node	knode_parent;		/* node in sibling list */
+	struct klist_node	knode_driver;
+	struct klist_node	knode_bus;
 	struct device 	* parent;
 
 	struct kobject kobj;
 	char	bus_id[BUS_ID_SIZE];	/* position on parent bus */
 
+	struct semaphore	sem;	/* semaphore to synchronize calls to
+					 * its driver.
+					 */
+
 	struct bus_type	* bus;		/* type of bus device is on */
 	struct device_driver *driver;	/* which driver has allocated this
 					   device */
@@ -288,12 +298,6 @@
 	void	(*release)(struct device * dev);
 };
 
-static inline struct device *
-list_to_dev(struct list_head *node)
-{
-	return list_entry(node, struct device, node);
-}
-
 static inline void *
 dev_get_drvdata (struct device *dev)
 {
@@ -321,7 +325,6 @@
  * Manual binding of a device to driver. See drivers/base/bus.c
  * for information on use.
  */
-extern int  driver_probe_device(struct device_driver * drv, struct device * dev);
 extern void device_bind_driver(struct device * dev);
 extern void device_release_driver(struct device * dev);
 extern int  device_attach(struct device * dev);
@@ -332,8 +335,10 @@
 
 struct device_attribute {
 	struct attribute	attr;
-	ssize_t (*show)(struct device * dev, char * buf);
-	ssize_t (*store)(struct device * dev, const char * buf, size_t count);
+	ssize_t (*show)(struct device *dev, struct device_attribute *attr,
+			char *buf);
+	ssize_t (*store)(struct device *dev, struct device_attribute *attr,
+			 const char *buf, size_t count);
 };
 
 #define DEVICE_ATTR(_name,_mode,_show,_store) \
@@ -360,13 +365,12 @@
  */
 extern struct device * get_device(struct device * dev);
 extern void put_device(struct device * dev);
-extern struct device *device_find(const char *name, struct bus_type *bus);
 
 
 /* drivers/base/platform.c */
 
 struct platform_device {
-	char		* name;
+	const char	* name;
 	u32		id;
 	struct device	dev;
 	u32		num_resources;
diff --git a/include/linux/dm9000.h b/include/linux/dm9000.h
new file mode 100644
index 0000000..0008e2a
--- /dev/null
+++ b/include/linux/dm9000.h
@@ -0,0 +1,36 @@
+/* include/linux/dm9000.h
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *   Ben Dooks <ben@simtec.co.uk>
+ *
+ * Header file for dm9000 platform data
+ *
+ * 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 __DM9000_PLATFORM_DATA
+#define __DM9000_PLATFORM_DATA __FILE__
+
+/* IO control flags */
+
+#define DM9000_PLATF_8BITONLY	(0x0001)
+#define DM9000_PLATF_16BITONLY	(0x0002)
+#define DM9000_PLATF_32BITONLY	(0x0004)
+
+/* platfrom data for platfrom device structure's platfrom_data field */
+
+struct dm9000_plat_data {
+	unsigned int	flags;
+
+	/* allow replacement IO routines */
+
+	void	(*inblk)(void __iomem *reg, void *data, int len);
+	void	(*outblk)(void __iomem *reg, void *data, int len);
+	void	(*dumpblk)(void __iomem *reg, int len);
+};
+
+#endif /* __DM9000_PLATFORM_DATA */
+
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 806c305..2d80cc7 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -14,7 +14,12 @@
 };
 
 #define DMA_64BIT_MASK	0xffffffffffffffffULL
+#define DMA_40BIT_MASK	0x000000ffffffffffULL
+#define DMA_39BIT_MASK	0x0000007fffffffffULL
 #define DMA_32BIT_MASK	0x00000000ffffffffULL
+#define DMA_31BIT_MASK	0x000000007fffffffULL
+#define DMA_30BIT_MASK	0x000000003fffffffULL
+#define DMA_29BIT_MASK	0x000000001fffffffULL
 
 #include <asm/dma-mapping.h>
 
diff --git a/include/linux/dmi.h b/include/linux/dmi.h
index d2bcf55..5e93e6d 100644
--- a/include/linux/dmi.h
+++ b/include/linux/dmi.h
@@ -9,6 +9,7 @@
 	DMI_SYS_VENDOR,
 	DMI_PRODUCT_NAME,
 	DMI_PRODUCT_VERSION,
+	DMI_PRODUCT_SERIAL,
 	DMI_BOARD_VENDOR,
 	DMI_BOARD_NAME,
 	DMI_BOARD_VERSION,
diff --git a/include/linux/dqblk_v1.h b/include/linux/dqblk_v1.h
index 42fbf47..57f1250 100644
--- a/include/linux/dqblk_v1.h
+++ b/include/linux/dqblk_v1.h
@@ -11,6 +11,12 @@
 /* Root squash turned on */
 #define V1_DQF_RSQUASH 1
 
+/* Numbers of blocks needed for updates */
+#define V1_INIT_ALLOC 1
+#define V1_INIT_REWRITE 1
+#define V1_DEL_ALLOC 0
+#define V1_DEL_REWRITE 2
+
 /* Special information about quotafile */
 struct v1_mem_dqinfo {
 };
diff --git a/include/linux/dqblk_v2.h b/include/linux/dqblk_v2.h
index 4a6c5f6..4f85332 100644
--- a/include/linux/dqblk_v2.h
+++ b/include/linux/dqblk_v2.h
@@ -10,6 +10,12 @@
 /* id numbers of quota format */
 #define QFMT_VFS_V0 2
 
+/* Numbers of blocks needed for updates */
+#define V2_INIT_ALLOC 4
+#define V2_INIT_REWRITE 2
+#define V2_DEL_ALLOC 0
+#define V2_DEL_REWRITE 6
+
 /* Inmemory copy of version specific information */
 struct v2_mem_dqinfo {
 	unsigned int dqi_blocks;
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 047e722..73781ec 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -315,7 +315,7 @@
  */
 static inline int efi_range_is_wc(unsigned long start, unsigned long len)
 {
-	int i;
+	unsigned long i;
 
 	for (i = 0; i < len; i += (1UL << EFI_PAGE_SHIFT)) {
 		unsigned long paddr = __pa(start + i);
diff --git a/include/linux/elevator.h b/include/linux/elevator.h
index ee54f81..ea6bbc2 100644
--- a/include/linux/elevator.h
+++ b/include/linux/elevator.h
@@ -16,9 +16,9 @@
 typedef void (elevator_requeue_req_fn) (request_queue_t *, struct request *);
 typedef struct request *(elevator_request_list_fn) (request_queue_t *, struct request *);
 typedef void (elevator_completed_req_fn) (request_queue_t *, struct request *);
-typedef int (elevator_may_queue_fn) (request_queue_t *, int);
+typedef int (elevator_may_queue_fn) (request_queue_t *, int, struct bio *);
 
-typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, int);
+typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, struct bio *, int);
 typedef void (elevator_put_req_fn) (request_queue_t *, struct request *);
 typedef void (elevator_deactivate_req_fn) (request_queue_t *, struct request *);
 
@@ -96,9 +96,9 @@
 extern struct request *elv_latter_request(request_queue_t *, struct request *);
 extern int elv_register_queue(request_queue_t *q);
 extern void elv_unregister_queue(request_queue_t *q);
-extern int elv_may_queue(request_queue_t *, int);
+extern int elv_may_queue(request_queue_t *, int, struct bio *);
 extern void elv_completed_request(request_queue_t *, struct request *);
-extern int elv_set_request(request_queue_t *, struct request *, int);
+extern int elv_set_request(request_queue_t *, struct request *, struct bio *, int);
 extern void elv_put_request(request_queue_t *, struct request *);
 
 /*
diff --git a/include/linux/ext2_fs.h b/include/linux/ext2_fs.h
index fab4352..a657130b 100644
--- a/include/linux/ext2_fs.h
+++ b/include/linux/ext2_fs.h
@@ -300,18 +300,19 @@
 /*
  * Mount flags
  */
-#define EXT2_MOUNT_CHECK		0x0001	/* Do mount-time checks */
-#define EXT2_MOUNT_OLDALLOC		0x0002  /* Don't use the new Orlov allocator */
-#define EXT2_MOUNT_GRPID		0x0004	/* Create files with directory's group */
-#define EXT2_MOUNT_DEBUG		0x0008	/* Some debugging messages */
-#define EXT2_MOUNT_ERRORS_CONT		0x0010	/* Continue on errors */
-#define EXT2_MOUNT_ERRORS_RO		0x0020	/* Remount fs ro on errors */
-#define EXT2_MOUNT_ERRORS_PANIC		0x0040	/* Panic on errors */
-#define EXT2_MOUNT_MINIX_DF		0x0080	/* Mimics the Minix statfs */
-#define EXT2_MOUNT_NOBH			0x0100	/* No buffer_heads */
-#define EXT2_MOUNT_NO_UID32		0x0200  /* Disable 32-bit UIDs */
-#define EXT2_MOUNT_XATTR_USER		0x4000	/* Extended user attributes */
-#define EXT2_MOUNT_POSIX_ACL		0x8000	/* POSIX Access Control Lists */
+#define EXT2_MOUNT_CHECK		0x000001  /* Do mount-time checks */
+#define EXT2_MOUNT_OLDALLOC		0x000002  /* Don't use the new Orlov allocator */
+#define EXT2_MOUNT_GRPID		0x000004  /* Create files with directory's group */
+#define EXT2_MOUNT_DEBUG		0x000008  /* Some debugging messages */
+#define EXT2_MOUNT_ERRORS_CONT		0x000010  /* Continue on errors */
+#define EXT2_MOUNT_ERRORS_RO		0x000020  /* Remount fs ro on errors */
+#define EXT2_MOUNT_ERRORS_PANIC		0x000040  /* Panic on errors */
+#define EXT2_MOUNT_MINIX_DF		0x000080  /* Mimics the Minix statfs */
+#define EXT2_MOUNT_NOBH			0x000100  /* No buffer_heads */
+#define EXT2_MOUNT_NO_UID32		0x000200  /* Disable 32-bit UIDs */
+#define EXT2_MOUNT_XATTR_USER		0x004000  /* Extended user attributes */
+#define EXT2_MOUNT_POSIX_ACL		0x008000  /* POSIX Access Control Lists */
+#define EXT2_MOUNT_XIP			0x010000  /* Execute in place */
 
 #define clear_opt(o, opt)		o &= ~EXT2_MOUNT_##opt
 #define set_opt(o, opt)			o |= EXT2_MOUNT_##opt
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h
index 74ad317..4b6e1ab 100644
--- a/include/linux/ext3_fs.h
+++ b/include/linux/ext3_fs.h
@@ -358,6 +358,7 @@
 #define EXT3_MOUNT_RESERVATION		0x10000	/* Preallocation */
 #define EXT3_MOUNT_BARRIER		0x20000 /* Use block barriers */
 #define EXT3_MOUNT_NOBH			0x40000 /* No bufferheads */
+#define EXT3_MOUNT_QUOTA		0x80000 /* Some quota option set */
 
 /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
 #ifndef _LINUX_EXT2_FS_H
diff --git a/include/linux/ext3_jbd.h b/include/linux/ext3_jbd.h
index e8292af..c8307c0 100644
--- a/include/linux/ext3_jbd.h
+++ b/include/linux/ext3_jbd.h
@@ -42,15 +42,15 @@
  * superblock only gets updated once, of course, so don't bother
  * counting that again for the quota updates. */
 
-#define EXT3_DATA_TRANS_BLOCKS		(EXT3_SINGLEDATA_TRANS_BLOCKS + \
+#define EXT3_DATA_TRANS_BLOCKS(sb)	(EXT3_SINGLEDATA_TRANS_BLOCKS + \
 					 EXT3_XATTR_TRANS_BLOCKS - 2 + \
-					 2*EXT3_QUOTA_TRANS_BLOCKS)
+					 2*EXT3_QUOTA_TRANS_BLOCKS(sb))
 
 /* Delete operations potentially hit one directory's namespace plus an
  * entire inode, plus arbitrary amounts of bitmap/indirection data.  Be
  * generous.  We can grow the delete transaction later if necessary. */
 
-#define EXT3_DELETE_TRANS_BLOCKS	(2 * EXT3_DATA_TRANS_BLOCKS + 64)
+#define EXT3_DELETE_TRANS_BLOCKS(sb)	(2 * EXT3_DATA_TRANS_BLOCKS(sb) + 64)
 
 /* Define an arbitrary limit for the amount of data we will anticipate
  * writing to any given transaction.  For unbounded transactions such as
@@ -74,14 +74,17 @@
 #ifdef CONFIG_QUOTA
 /* Amount of blocks needed for quota update - we know that the structure was
  * allocated so we need to update only inode+data */
-#define EXT3_QUOTA_TRANS_BLOCKS 2
+#define EXT3_QUOTA_TRANS_BLOCKS(sb) (test_opt(sb, QUOTA) ? 2 : 0)
 /* Amount of blocks needed for quota insert/delete - we do some block writes
  * but inode, sb and group updates are done only once */
-#define EXT3_QUOTA_INIT_BLOCKS (DQUOT_MAX_WRITES*\
-				(EXT3_SINGLEDATA_TRANS_BLOCKS-3)+3)
+#define EXT3_QUOTA_INIT_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_INIT_ALLOC*\
+		(EXT3_SINGLEDATA_TRANS_BLOCKS-3)+3+DQUOT_INIT_REWRITE) : 0)
+#define EXT3_QUOTA_DEL_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_DEL_ALLOC*\
+		(EXT3_SINGLEDATA_TRANS_BLOCKS-3)+3+DQUOT_DEL_REWRITE) : 0)
 #else
-#define EXT3_QUOTA_TRANS_BLOCKS 0
-#define EXT3_QUOTA_INIT_BLOCKS 0
+#define EXT3_QUOTA_TRANS_BLOCKS(sb) 0
+#define EXT3_QUOTA_INIT_BLOCKS(sb) 0
+#define EXT3_QUOTA_DEL_BLOCKS(sb) 0
 #endif
 
 int
diff --git a/include/linux/fb.h b/include/linux/fb.h
index b468bf4..bc24bee 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -524,11 +524,11 @@
 	u32 offset;		/* current offset to buffer		*/
 	u32 buf_align;		/* byte alignment of each bitmap	*/
 	u32 scan_align;		/* alignment per scanline		*/
-	u32 access_align;	/* alignment per read/write		*/
+	u32 access_align;	/* alignment per read/write (bits)	*/
 	u32 flags;		/* see FB_PIXMAP_*			*/
 	/* access methods */
-	void (*outbuf)(struct fb_info *info, u8 *addr, u8 *src, unsigned int size);
-	u8   (*inbuf) (struct fb_info *info, u8 *addr);
+	void (*writeio)(struct fb_info *info, void __iomem *dst, void *src, unsigned int size);
+	void (*readio) (struct fb_info *info, void *dst, void __iomem *src, unsigned int size);
 };
 
 
@@ -816,18 +816,9 @@
 extern int fb_prepare_logo(struct fb_info *fb_info);
 extern int fb_show_logo(struct fb_info *fb_info);
 extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size);
-extern void fb_iomove_buf_unaligned(struct fb_info *info, struct fb_pixmap *buf,
-				u8 *dst, u32 d_pitch, u8 *src, u32 idx,
+extern void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx,
 				u32 height, u32 shift_high, u32 shift_low, u32 mod);
-extern void fb_iomove_buf_aligned(struct fb_info *info, struct fb_pixmap *buf,
-				u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch,
-				u32 height);
-extern void fb_sysmove_buf_unaligned(struct fb_info *info, struct fb_pixmap *buf,
-				u8 *dst, u32 d_pitch, u8 *src, u32 idx,
-				u32 height, u32 shift_high, u32 shift_low, u32 mod);
-extern void fb_sysmove_buf_aligned(struct fb_info *info, struct fb_pixmap *buf,
-				u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch,
-				u32 height);
+extern void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height);
 extern void fb_set_suspend(struct fb_info *info, int state);
 extern int fb_get_color_depth(struct fb_var_screeninfo *var);
 extern int fb_get_options(char *name, char **option);
diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h
index 704fb76..8a7c821 100644
--- a/include/linux/fcntl.h
+++ b/include/linux/fcntl.h
@@ -25,6 +25,10 @@
 
 #ifdef __KERNEL__
 
+#ifndef force_o_largefile
+#define force_o_largefile() (BITS_PER_LONG != 32)
+#endif
+
 #if BITS_PER_LONG == 32
 #define IS_GETLK32(cmd)		((cmd) == F_GETLK)
 #define IS_SETLK32(cmd)		((cmd) == F_SETLK)
diff --git a/include/linux/font.h b/include/linux/font.h
index fc2d690..8fc80a7 100644
--- a/include/linux/font.h
+++ b/include/linux/font.h
@@ -25,19 +25,23 @@
 #define VGA8x16_IDX	1
 #define PEARL8x8_IDX	2
 #define VGA6x11_IDX	3
-#define SUN8x16_IDX	4
-#define SUN12x22_IDX	5
-#define ACORN8x8_IDX	6
-#define	MINI4x6_IDX	7
+#define FONT7x14_IDX	4
+#define	FONT10x18_IDX	5
+#define SUN8x16_IDX	6
+#define SUN12x22_IDX	7
+#define ACORN8x8_IDX	8
+#define	MINI4x6_IDX	9
 
 extern struct font_desc	font_vga_8x8,
-				font_vga_8x16,
-				font_pearl_8x8,
-				font_vga_6x11,
-				font_sun_8x16,
-				font_sun_12x22,
-				font_acorn_8x8,
-				font_mini_4x6;
+			font_vga_8x16,
+			font_pearl_8x8,
+			font_vga_6x11,
+			font_7x14,
+			font_10x18,
+			font_sun_8x16,
+			font_sun_12x22,
+			font_acorn_8x8,
+			font_mini_4x6;
 
 /* Find a font with a specific name */
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 0180102..047bde3 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -213,6 +213,7 @@
 #include <linux/radix-tree.h>
 #include <linux/prio_tree.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 
 #include <asm/atomic.h>
 #include <asm/semaphore.h>
@@ -220,6 +221,7 @@
 
 struct iovec;
 struct nameidata;
+struct kiocb;
 struct pipe_inode_info;
 struct poll_table_struct;
 struct kstatfs;
@@ -240,7 +242,7 @@
 typedef int (get_blocks_t)(struct inode *inode, sector_t iblock,
 			unsigned long max_blocks,
 			struct buffer_head *bh_result, int create);
-typedef void (dio_iodone_t)(struct inode *inode, loff_t offset,
+typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
 			ssize_t bytes, void *private);
 
 /*
@@ -302,7 +304,6 @@
 struct page;
 struct address_space;
 struct writeback_control;
-struct kiocb;
 
 struct address_space_operations {
 	int (*writepage)(struct page *page, struct writeback_control *wbc);
@@ -330,6 +331,8 @@
 	int (*releasepage) (struct page *, int);
 	ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
 			loff_t offset, unsigned long nr_segs);
+	struct page* (*get_xip_page)(struct address_space *, sector_t,
+			int);
 };
 
 struct backing_dev_info;
@@ -581,7 +584,6 @@
 	atomic_t		f_count;
 	unsigned int 		f_flags;
 	mode_t			f_mode;
-	int			f_error;
 	loff_t			f_pos;
 	struct fown_struct	f_owner;
 	unsigned int		f_uid, f_gid;
@@ -674,6 +676,7 @@
 	struct lock_manager_operations *fl_lmops;	/* Callbacks for lockmanagers */
 	union {
 		struct nfs_lock_info	nfs_fl;
+		struct nfs4_lock_info	nfs4_fl;
 	} fl_u;
 };
 
@@ -820,16 +823,34 @@
 #define vfs_check_frozen(sb, level) \
 	wait_event((sb)->s_wait_unfrozen, ((sb)->s_frozen < (level)))
 
+static inline void get_fs_excl(void)
+{
+	atomic_inc(&current->fs_excl);
+}
+
+static inline void put_fs_excl(void)
+{
+	atomic_dec(&current->fs_excl);
+}
+
+static inline int has_fs_excl(void)
+{
+	return atomic_read(&current->fs_excl);
+}
+
+
 /*
  * Superblock locking.
  */
 static inline void lock_super(struct super_block * sb)
 {
+	get_fs_excl();
 	down(&sb->s_lock);
 }
 
 static inline void unlock_super(struct super_block * sb)
 {
+	put_fs_excl();
 	up(&sb->s_lock);
 }
 
@@ -883,7 +904,9 @@
 	int (*open) (struct inode *, struct file *);
 	int (*release) (struct inode *, struct file *);
 	int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long);
+	long (*unlocked_ioctl) (struct file *, unsigned, unsigned long);
 	long (*compat_ioctl) (struct file *, unsigned, unsigned long);
+	int (*direct_access) (struct block_device *, sector_t, unsigned long *);
 	int (*media_changed) (struct gendisk *);
 	int (*revalidate_disk) (struct gendisk *);
 	struct module *owner;
@@ -1024,6 +1047,7 @@
 #define I_FREEING		16
 #define I_CLEAR			32
 #define I_NEW			64
+#define I_WILL_FREE		128
 
 #define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES)
 
@@ -1494,6 +1518,23 @@
 extern int generic_file_open(struct inode * inode, struct file * filp);
 extern int nonseekable_open(struct inode * inode, struct file * filp);
 
+#ifdef CONFIG_FS_XIP
+extern ssize_t xip_file_read(struct file *filp, char __user *buf, size_t len,
+			     loff_t *ppos);
+extern ssize_t xip_file_sendfile(struct file *in_file, loff_t *ppos,
+				 size_t count, read_actor_t actor,
+				 void *target);
+extern int xip_file_mmap(struct file * file, struct vm_area_struct * vma);
+extern ssize_t xip_file_write(struct file *filp, const char __user *buf,
+			      size_t len, loff_t *ppos);
+extern int xip_truncate_page(struct address_space *mapping, loff_t from);
+#else
+static inline int xip_truncate_page(struct address_space *mapping, loff_t from)
+{
+	return 0;
+}
+#endif
+
 static inline void do_generic_file_read(struct file * filp, loff_t *ppos,
 					read_descriptor_t * desc,
 					read_actor_t actor)
@@ -1657,6 +1698,52 @@
 	ar->size = n;
 }
 
+/*
+ * simple attribute files
+ *
+ * These attributes behave similar to those in sysfs:
+ *
+ * Writing to an attribute immediately sets a value, an open file can be
+ * written to multiple times.
+ *
+ * Reading from an attribute creates a buffer from the value that might get
+ * read with multiple read calls. When the attribute has been read
+ * completely, no further read calls are possible until the file is opened
+ * again.
+ *
+ * All attributes contain a text representation of a numeric value
+ * that are accessed with the get() and set() functions.
+ */
+#define DEFINE_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt)		\
+static int __fops ## _open(struct inode *inode, struct file *file)	\
+{									\
+	__simple_attr_check_format(__fmt, 0ull);			\
+	return simple_attr_open(inode, file, __get, __set, __fmt);	\
+}									\
+static struct file_operations __fops = {				\
+	.owner	 = THIS_MODULE,						\
+	.open	 = __fops ## _open,					\
+	.release = simple_attr_close,					\
+	.read	 = simple_attr_read,					\
+	.write	 = simple_attr_write,					\
+};
+
+static inline void __attribute__((format(printf, 1, 2)))
+__simple_attr_check_format(const char *fmt, ...)
+{
+	/* don't do anything, just let the compiler check the arguments; */
+}
+
+int simple_attr_open(struct inode *inode, struct file *file,
+		     u64 (*get)(void *), void (*set)(void *, u64),
+		     const char *fmt);
+int simple_attr_close(struct inode *inode, struct file *file);
+ssize_t simple_attr_read(struct file *file, char __user *buf,
+			 size_t len, loff_t *ppos);
+ssize_t simple_attr_write(struct file *file, const char __user *buf,
+			  size_t len, loff_t *ppos);
+
+
 #ifdef CONFIG_SECURITY
 static inline char *alloc_secdata(void)
 {
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index faaff4c..70f54af 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -51,6 +51,7 @@
 
 	/* board specific information */
 	u32 board_flags;
+	u32 phy_flags;
 	u32 phyid;
 	u32 interruptPHY;
 	u8 mac_addr[6];
@@ -61,9 +62,14 @@
 #define FSL_GIANFAR_DEV_HAS_COALESCE		0x00000002
 #define FSL_GIANFAR_DEV_HAS_RMON		0x00000004
 #define FSL_GIANFAR_DEV_HAS_MULTI_INTR		0x00000008
+#define FSL_GIANFAR_DEV_HAS_CSUM		0x00000010
+#define FSL_GIANFAR_DEV_HAS_VLAN		0x00000020
+#define FSL_GIANFAR_DEV_HAS_EXTENDED_HASH	0x00000040
+#define FSL_GIANFAR_DEV_HAS_PADDING		0x00000080
 
 /* Flags in gianfar_platform_data */
-#define FSL_GIANFAR_BRD_HAS_PHY_INTR	0x00000001	/* if not set use a timer */
+#define FSL_GIANFAR_BRD_HAS_PHY_INTR	0x00000001 /* set or use a timer */
+#define FSL_GIANFAR_BRD_IS_REDUCED	0x00000002 /* Set if RGMII, RMII */
 
 struct fsl_i2c_platform_data {
 	/* device specific information */
diff --git a/include/linux/genalloc.h b/include/linux/genalloc.h
new file mode 100644
index 0000000..7fd0576
--- /dev/null
+++ b/include/linux/genalloc.h
@@ -0,0 +1,40 @@
+/*
+ * Basic general purpose allocator for managing special purpose memory
+ * not managed by the regular kmalloc/kfree interface.
+ * 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.
+ */
+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;
+};
+
+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);
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 47dedaf..01796c4 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -224,7 +224,7 @@
 extern void disk_round_stats(struct gendisk *disk);
 
 /* drivers/block/genhd.c */
-extern int get_blkdev_list(char *);
+extern int get_blkdev_list(char *, int);
 extern void add_disk(struct gendisk *disk);
 extern void del_gendisk(struct gendisk *gp);
 extern void unlink_gendisk(struct gendisk *gp);
@@ -403,6 +403,7 @@
 extern void add_partition(struct gendisk *, int, sector_t, sector_t);
 extern void delete_partition(struct gendisk *, int);
 
+extern struct gendisk *alloc_disk_node(int minors, int node_id);
 extern struct gendisk *alloc_disk(int minors);
 extern struct kobject *get_disk(struct gendisk *disk);
 extern void put_disk(struct gendisk *disk);
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index af7407e..8d6bf60 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -39,6 +39,7 @@
 #define __GFP_COMP	0x4000u	/* Add compound page metadata */
 #define __GFP_ZERO	0x8000u	/* Return zeroed page on success */
 #define __GFP_NOMEMALLOC 0x10000u /* Don't use emergency reserves */
+#define __GFP_NORECLAIM  0x20000u /* No realy zone reclaim during allocation */
 
 #define __GFP_BITS_SHIFT 20	/* Room for 20 __GFP_FOO bits */
 #define __GFP_BITS_MASK ((1 << __GFP_BITS_SHIFT) - 1)
@@ -47,7 +48,7 @@
 #define GFP_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS| \
 			__GFP_COLD|__GFP_NOWARN|__GFP_REPEAT| \
 			__GFP_NOFAIL|__GFP_NORETRY|__GFP_NO_GROW|__GFP_COMP| \
-			__GFP_NOMEMALLOC)
+			__GFP_NOMEMALLOC|__GFP_NORECLAIM)
 
 #define GFP_ATOMIC	(__GFP_HIGH)
 #define GFP_NOIO	(__GFP_WAIT)
@@ -132,5 +133,10 @@
 #define free_page(addr) free_pages((addr),0)
 
 void page_alloc_init(void);
+#ifdef CONFIG_NUMA
+void drain_remote_pages(void);
+#else
+static inline void drain_remote_pages(void) { };
+#endif
 
 #endif /* __LINUX_GFP_H */
diff --git a/include/linux/hdlc.h b/include/linux/hdlc.h
index 503194e..ed2927e 100644
--- a/include/linux/hdlc.h
+++ b/include/linux/hdlc.h
@@ -1,7 +1,7 @@
 /*
  * Generic HDLC support routines for Linux
  *
- * Copyright (C) 1999-2003 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 1999-2005 Krzysztof Halasa <khc@pm.waw.pl>
  *
  * 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
@@ -41,6 +41,7 @@
 #define LMI_NONE		1 /* No LMI, all PVCs are static */
 #define LMI_ANSI		2 /* ANSI Annex D */
 #define LMI_CCITT		3 /* ITU-T Annex A */
+#define LMI_CISCO		4 /* The "original" LMI, aka Gang of Four */
 
 #define HDLC_MAX_MTU 1500	/* Ethernet 1500 bytes */
 #define HDLC_MAX_MRU (HDLC_MAX_MTU + 10 + 14 + 4) /* for ETH+VLAN over FR */
@@ -89,6 +90,7 @@
 		unsigned int deleted: 1;
 		unsigned int fecn: 1;
 		unsigned int becn: 1;
+		unsigned int bandwidth;	/* Cisco LMI reporting only */
 	}state;
 }pvc_device;
 
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index 2a7e6c6..6bece92 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -28,6 +28,7 @@
 
 #define kmap_atomic(page, idx)		page_address(page)
 #define kunmap_atomic(addr, idx)	do { } while (0)
+#define kmap_atomic_pfn(pfn, idx)	page_address(pfn_to_page(pfn))
 #define kmap_atomic_to_page(ptr)	virt_to_page(ptr)
 
 #endif /* CONFIG_HIGHMEM */
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 6af1ae4..f529d14 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -4,6 +4,7 @@
 #ifdef CONFIG_HUGETLB_PAGE
 
 #include <linux/mempolicy.h>
+#include <asm/tlbflush.h>
 
 struct ctl_table;
 
@@ -22,12 +23,6 @@
 int hugetlb_report_node_meminfo(int, char *);
 int is_hugepage_mem_enough(size_t);
 unsigned long hugetlb_total_pages(void);
-struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
-			      int write);
-struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
-				pmd_t *pmd, int write);
-int is_aligned_hugepage_range(unsigned long addr, unsigned long len);
-int pmd_huge(pmd_t pmd);
 struct page *alloc_huge_page(void);
 void free_huge_page(struct page *);
 
@@ -35,6 +30,17 @@
 extern const unsigned long hugetlb_zero, hugetlb_infinity;
 extern int sysctl_hugetlb_shm_group;
 
+/* arch callbacks */
+
+pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr);
+pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr);
+struct page *follow_huge_addr(struct mm_struct *mm, unsigned long address,
+			      int write);
+struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
+				pmd_t *pmd, int write);
+int is_aligned_hugepage_range(unsigned long addr, unsigned long len);
+int pmd_huge(pmd_t pmd);
+
 #ifndef ARCH_HAS_HUGEPAGE_ONLY_RANGE
 #define is_hugepage_only_range(mm, addr, len)	0
 #define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) \
@@ -48,6 +54,28 @@
 int prepare_hugepage_range(unsigned long addr, unsigned long len);
 #endif
 
+#ifndef ARCH_HAS_SETCLEAR_HUGE_PTE
+#define set_huge_pte_at(mm, addr, ptep, pte)	set_pte_at(mm, addr, ptep, pte)
+#define huge_ptep_get_and_clear(mm, addr, ptep) ptep_get_and_clear(mm, addr, ptep)
+#else
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+		     pte_t *ptep, pte_t pte);
+pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+			      pte_t *ptep);
+#endif
+
+#ifndef ARCH_HAS_HUGETLB_PREFAULT_HOOK
+#define hugetlb_prefault_arch_hook(mm)		do { } while (0)
+#else
+void hugetlb_prefault_arch_hook(struct mm_struct *mm);
+#endif
+
+#ifndef ARCH_HAS_HUGETLB_CLEAN_STALE_PGTABLE
+#define hugetlb_clean_stale_pgtable(pte)	BUG()
+#else
+void hugetlb_clean_stale_pgtable(pte_t *pte);
+#endif
+
 #else /* !CONFIG_HUGETLB_PAGE */
 
 static inline int is_vm_hugetlb_page(struct vm_area_struct *vma)
diff --git a/include/linux/hwmon-sysfs.h b/include/linux/hwmon-sysfs.h
new file mode 100644
index 0000000..1b5018a
--- /dev/null
+++ b/include/linux/hwmon-sysfs.h
@@ -0,0 +1,36 @@
+/*
+ *  hwmon-sysfs.h - hardware monitoring chip driver sysfs defines
+ *
+ *  Copyright (C) 2005 Yani Ioannou <yani.ioannou@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.
+ */
+#ifndef _LINUX_HWMON_SYSFS_H
+#define _LINUX_HWMON_SYSFS_H
+
+struct sensor_device_attribute{
+	struct device_attribute dev_attr;
+	int index;
+};
+#define to_sensor_dev_attr(_dev_attr) \
+	container_of(_dev_attr, struct sensor_device_attribute, dev_attr)
+
+#define SENSOR_DEVICE_ATTR(_name,_mode,_show,_store,_index)	\
+struct sensor_device_attribute sensor_dev_attr_##_name = {	\
+	.dev_attr =	__ATTR(_name,_mode,_show,_store),	\
+	.index =	_index,					\
+}
+
+#endif /* _LINUX_HWMON_SYSFS_H */
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index 89270ce..33f0825 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -108,6 +108,7 @@
 #define I2C_DRIVERID_TDA7313	62	/* TDA7313 audio processor	*/
 #define I2C_DRIVERID_MAX6900	63	/* MAX6900 real-time clock	*/
 #define I2C_DRIVERID_SAA7114H	64	/* video decoder		*/
+#define I2C_DRIVERID_DS1374	65	/* DS1374 real time clock	*/
 
 
 #define I2C_DRIVERID_EXP0	0xF0	/* experimental use id's	*/
diff --git a/include/linux/i2c-vid.h b/include/linux/i2c-vid.h
index 974835e..41d0635 100644
--- a/include/linux/i2c-vid.h
+++ b/include/linux/i2c-vid.h
@@ -97,3 +97,15 @@
 		                     2050 - (val) * 50);
 	}
 }
+
+static inline int vid_to_reg(int val, int vrm)
+{
+	switch (vrm) {
+	case 91:		/* VRM 9.1 */
+	case 90:		/* VRM 9.0 */
+		return ((val >= 1100) && (val <= 1850) ?
+			((18499 - val * 10) / 25 + 5) / 10 : -1);
+	default:
+		return -1;
+	}
+}
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index ebcd745..be837b1 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -290,11 +290,8 @@
  */
 struct i2c_client_address_data {
 	unsigned short *normal_i2c;
-	unsigned short *normal_i2c_range;
 	unsigned short *probe;
-	unsigned short *probe_range;
 	unsigned short *ignore;
-	unsigned short *ignore_range;
 	unsigned short *force;
 };
 
@@ -563,24 +560,15 @@
 #define I2C_CLIENT_INSMOD \
   I2C_CLIENT_MODULE_PARM(probe, \
                       "List of adapter,address pairs to scan additionally"); \
-  I2C_CLIENT_MODULE_PARM(probe_range, \
-                      "List of adapter,start-addr,end-addr triples to scan " \
-                      "additionally"); \
   I2C_CLIENT_MODULE_PARM(ignore, \
                       "List of adapter,address pairs not to scan"); \
-  I2C_CLIENT_MODULE_PARM(ignore_range, \
-                      "List of adapter,start-addr,end-addr triples not to " \
-                      "scan"); \
   I2C_CLIENT_MODULE_PARM(force, \
                       "List of adapter,address pairs to boldly assume " \
                       "to be present"); \
 	static struct i2c_client_address_data addr_data = {		\
 			.normal_i2c = 		normal_i2c,		\
-			.normal_i2c_range =	normal_i2c_range,	\
 			.probe =		probe,			\
-			.probe_range =		probe_range,		\
 			.ignore =		ignore,			\
-			.ignore_range =		ignore_range,		\
 			.force =		force,			\
 		}
 
diff --git a/include/linux/i2o-dev.h b/include/linux/i2o-dev.h
index ef7f644..36fd18c 100644
--- a/include/linux/i2o-dev.h
+++ b/include/linux/i2o-dev.h
@@ -24,6 +24,13 @@
 #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__ */
 
 /*
  * I2O Control IOCTLs and structures
@@ -113,6 +120,10 @@
 	int lost;
 };
 
+typedef struct i2o_sg_io_hdr {
+	unsigned int flags;	/* see I2O_DPT_SG_IO_FLAGS */
+} i2o_sg_io_hdr_t;
+
 /**************************************************************************
  * HRT related constants and structures
  **************************************************************************/
@@ -126,14 +137,6 @@
 #define I2O_BUS_CARDBUS 7
 #define I2O_BUS_UNKNOWN 0x80
 
-#ifndef __KERNEL__
-
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned int u32;
-
-#endif				/* __KERNEL__ */
-
 typedef struct _i2o_pci_bus {
 	u8 PciFunctionNumber;
 	u8 PciDeviceNumber;
@@ -333,7 +336,7 @@
 #define I2O_CLASS_ATE_PERIPHERAL		0x061
 #define I2O_CLASS_FLOPPY_CONTROLLER		0x070
 #define I2O_CLASS_FLOPPY_DEVICE 		0x071
-#define I2O_CLASS_BUS_ADAPTER_PORT		0x080
+#define I2O_CLASS_BUS_ADAPTER			0x080
 #define I2O_CLASS_PEER_TRANSPORT_AGENT		0x090
 #define I2O_CLASS_PEER_TRANSPORT		0x091
 #define	I2O_CLASS_END				0xfff
@@ -399,4 +402,26 @@
 #define ADAPTER_STATE_FAILED			0x10
 #define ADAPTER_STATE_FAULTED			0x11
 
+/*
+ *	Software module types
+ */
+#define I2O_SOFTWARE_MODULE_IRTOS		0x11
+#define I2O_SOFTWARE_MODULE_IOP_PRIVATE		0x22
+#define I2O_SOFTWARE_MODULE_IOP_CONFIG		0x23
+
+/*
+ *	Vendors
+ */
+#define I2O_VENDOR_DPT				0x001b
+
+/*
+ * DPT / Adaptec specific values for i2o_sg_io_hdr flags.
+ */
+#define I2O_DPT_SG_FLAG_INTERPRET		0x00010000
+#define I2O_DPT_SG_FLAG_PHYSICAL		0x00020000
+
+#define I2O_DPT_FLASH_FRAG_SIZE			0x10000
+#define I2O_DPT_FLASH_READ			0x0101
+#define I2O_DPT_FLASH_WRITE			0x0102
+
 #endif				/* _I2O_DEV_H */
diff --git a/include/linux/i2o.h b/include/linux/i2o.h
index ea9a3ad..bdc286e 100644
--- a/include/linux/i2o.h
+++ b/include/linux/i2o.h
@@ -119,12 +119,21 @@
 };
 
 /*
- *	Contains all information which are necessary for DMA operations
+ *	Contains DMA mapped address information
  */
 struct i2o_dma {
 	void *virt;
 	dma_addr_t phys;
-	u32 len;
+	size_t len;
+};
+
+/*
+ *	Contains IO mapped address information
+ */
+struct i2o_io {
+	void __iomem *virt;
+	unsigned long phys;
+	unsigned long len;
 };
 
 /*
@@ -147,28 +156,25 @@
 
 	struct pci_dev *pdev;	/* PCI device */
 
-	unsigned int short_req:1;	/* use small block sizes */
+	unsigned int promise:1;	/* Promise controller */
+	unsigned int adaptec:1;	/* DPT / Adaptec controller */
+	unsigned int raptor:1;	/* split bar */
 	unsigned int no_quiesce:1;	/* dont quiesce before reset */
-	unsigned int raptor:1;		/* split bar */
-	unsigned int promise:1;		/* Promise controller */
-
-#ifdef CONFIG_MTRR
-	int mtrr_reg0;
-	int mtrr_reg1;
-#endif
+	unsigned int short_req:1;	/* use small block sizes */
+	unsigned int limit_sectors:1;	/* limit number of sectors / request */
+	unsigned int pae_support:1;	/* controller has 64-bit SGL support */
 
 	struct list_head devices;	/* list of I2O devices */
-
-	struct notifier_block *event_notifer;	/* Events */
-	atomic_t users;
 	struct list_head list;	/* Controller list */
-	void __iomem *post_port;	/* Inbout port address */
-	void __iomem *reply_port;	/* Outbound port address */
-	void __iomem *irq_mask;		/* Interrupt register address */
+
+	void __iomem *in_port;	/* Inbout port address */
+	void __iomem *out_port;	/* Outbound port address */
+	void __iomem *irq_status;	/* Interrupt status register address */
+	void __iomem *irq_mask;	/* Interrupt mask register address */
 
 	/* Dynamic LCT related data */
 
-	struct i2o_dma status;	/* status of IOP */
+	struct i2o_dma status;	/* IOP status block */
 
 	struct i2o_dma hrt;	/* HW Resource Table */
 	i2o_lct *lct;		/* Logical Config Table */
@@ -176,21 +182,19 @@
 	struct semaphore lct_lock;	/* Lock for LCT updates */
 	struct i2o_dma status_block;	/* IOP status block */
 
-	struct i2o_dma base;	/* controller messaging unit */
-	struct i2o_dma in_queue;	/* inbound message queue Host->IOP */
+	struct i2o_io base;	/* controller messaging unit */
+	struct i2o_io in_queue;	/* inbound message queue Host->IOP */
 	struct i2o_dma out_queue;	/* outbound message queue IOP->Host */
 
-	unsigned int battery:1;		/* Has a battery backup */
+	unsigned int battery:1;	/* Has a battery backup */
 	unsigned int io_alloc:1;	/* An I/O resource was allocated */
 	unsigned int mem_alloc:1;	/* A memory resource was allocated */
 
 	struct resource io_resource;	/* I/O resource allocated to the IOP */
 	struct resource mem_resource;	/* Mem resource allocated to the IOP */
 
-	struct proc_dir_entry *proc_entry;	/* /proc dir */
-
-	struct list_head bus_list;	/* list of busses on IOP */
 	struct device device;
+	struct class_device classdev;	/* I2O controller class */
 	struct i2o_device *exec;	/* Executive */
 #if BITS_PER_LONG == 64
 	spinlock_t context_list_lock;	/* lock for context_list */
@@ -241,9 +245,10 @@
 extern struct list_head i2o_controllers;
 
 /* Message functions */
-static inline u32 i2o_msg_get(struct i2o_controller *, struct i2o_message __iomem **);
-extern u32 i2o_msg_get_wait(struct i2o_controller *, struct i2o_message __iomem **,
-			    int);
+static inline u32 i2o_msg_get(struct i2o_controller *,
+			      struct i2o_message __iomem **);
+extern u32 i2o_msg_get_wait(struct i2o_controller *,
+			    struct i2o_message __iomem **, int);
 static inline void i2o_msg_post(struct i2o_controller *, u32);
 static inline int i2o_msg_post_wait(struct i2o_controller *, u32,
 				    unsigned long);
@@ -252,15 +257,6 @@
 extern void i2o_msg_nop(struct i2o_controller *, u32);
 static inline void i2o_flush_reply(struct i2o_controller *, u32);
 
-/* DMA handling functions */
-static inline int i2o_dma_alloc(struct device *, struct i2o_dma *, size_t,
-				unsigned int);
-static inline void i2o_dma_free(struct device *, struct i2o_dma *);
-int i2o_dma_realloc(struct device *, struct i2o_dma *, size_t, unsigned int);
-
-static inline int i2o_dma_map(struct device *, struct i2o_dma *);
-static inline void i2o_dma_unmap(struct device *, struct i2o_dma *);
-
 /* IOP functions */
 extern int i2o_status_get(struct i2o_controller *);
 
@@ -285,6 +281,16 @@
 {
 	return (u32) ((u64) ptr >> 32);
 };
+
+static inline u32 i2o_dma_low(dma_addr_t dma_addr)
+{
+	return (u32) (u64) dma_addr;
+};
+
+static inline u32 i2o_dma_high(dma_addr_t dma_addr)
+{
+	return (u32) ((u64) dma_addr >> 32);
+};
 #else
 static inline u32 i2o_cntxt_list_add(struct i2o_controller *c, void *ptr)
 {
@@ -315,8 +321,246 @@
 {
 	return 0;
 };
+
+static inline u32 i2o_dma_low(dma_addr_t dma_addr)
+{
+	return (u32) dma_addr;
+};
+
+static inline u32 i2o_dma_high(dma_addr_t dma_addr)
+{
+	return 0;
+};
 #endif
 
+/**
+ *	i2o_sg_tablesize - Calculate the maximum number of elements in a SGL
+ *	@c: I2O controller for which the calculation should be done
+ *	@body_size: maximum body size used for message in 32-bit words.
+ *
+ *	Return the maximum number of SG elements in a SG list.
+ */
+static inline u16 i2o_sg_tablesize(struct i2o_controller *c, u16 body_size)
+{
+	i2o_status_block *sb = c->status_block.virt;
+	u16 sg_count =
+	    (sb->inbound_frame_size - sizeof(struct i2o_message) / 4) -
+	    body_size;
+
+	if (c->pae_support) {
+		/*
+		 * for 64-bit a SG attribute element must be added and each
+		 * SG element needs 12 bytes instead of 8.
+		 */
+		sg_count -= 2;
+		sg_count /= 3;
+	} else
+		sg_count /= 2;
+
+	if (c->short_req && (sg_count > 8))
+		sg_count = 8;
+
+	return sg_count;
+};
+
+/**
+ *	i2o_dma_map_single - Map pointer to controller and fill in I2O message.
+ *	@c: I2O controller
+ *	@ptr: pointer to the data which should be mapped
+ *	@size: size of data in bytes
+ *	@direction: DMA_TO_DEVICE / DMA_FROM_DEVICE
+ *	@sg_ptr: pointer to the SG list inside the I2O message
+ *
+ *	This function does all necessary DMA handling and also writes the I2O
+ *	SGL elements into the I2O message. For details on DMA handling see also
+ *	dma_map_single(). The pointer sg_ptr will only be set to the end of the
+ *	SG list if the allocation was successful.
+ *
+ *	Returns DMA address which must be checked for failures using
+ *	dma_mapping_error().
+ */
+static inline dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr,
+					    size_t size,
+					    enum dma_data_direction direction,
+					    u32 __iomem ** sg_ptr)
+{
+	u32 sg_flags;
+	u32 __iomem *mptr = *sg_ptr;
+	dma_addr_t dma_addr;
+
+	switch (direction) {
+	case DMA_TO_DEVICE:
+		sg_flags = 0xd4000000;
+		break;
+	case DMA_FROM_DEVICE:
+		sg_flags = 0xd0000000;
+		break;
+	default:
+		return 0;
+	}
+
+	dma_addr = dma_map_single(&c->pdev->dev, ptr, size, direction);
+	if (!dma_mapping_error(dma_addr)) {
+#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
+		if ((sizeof(dma_addr_t) > 4) && c->pae_support) {
+			writel(0x7C020002, mptr++);
+			writel(PAGE_SIZE, mptr++);
+		}
+#endif
+
+		writel(sg_flags | size, mptr++);
+		writel(i2o_dma_low(dma_addr), mptr++);
+#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
+		if ((sizeof(dma_addr_t) > 4) && c->pae_support)
+			writel(i2o_dma_high(dma_addr), mptr++);
+#endif
+		*sg_ptr = mptr;
+	}
+	return dma_addr;
+};
+
+/**
+ *	i2o_dma_map_sg - Map a SG List to controller and fill in I2O message.
+ *	@c: I2O controller
+ *	@sg: SG list to be mapped
+ *	@sg_count: number of elements in the SG list
+ *	@direction: DMA_TO_DEVICE / DMA_FROM_DEVICE
+ *	@sg_ptr: pointer to the SG list inside the I2O message
+ *
+ *	This function does all necessary DMA handling and also writes the I2O
+ *	SGL elements into the I2O message. For details on DMA handling see also
+ *	dma_map_sg(). The pointer sg_ptr will only be set to the end of the SG
+ *	list if the allocation was successful.
+ *
+ *	Returns 0 on failure or 1 on success.
+ */
+static inline int i2o_dma_map_sg(struct i2o_controller *c,
+				 struct scatterlist *sg, int sg_count,
+				 enum dma_data_direction direction,
+				 u32 __iomem ** sg_ptr)
+{
+	u32 sg_flags;
+	u32 __iomem *mptr = *sg_ptr;
+
+	switch (direction) {
+	case DMA_TO_DEVICE:
+		sg_flags = 0x14000000;
+		break;
+	case DMA_FROM_DEVICE:
+		sg_flags = 0x10000000;
+		break;
+	default:
+		return 0;
+	}
+
+	sg_count = dma_map_sg(&c->pdev->dev, sg, sg_count, direction);
+	if (!sg_count)
+		return 0;
+
+#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
+	if ((sizeof(dma_addr_t) > 4) && c->pae_support) {
+		writel(0x7C020002, mptr++);
+		writel(PAGE_SIZE, mptr++);
+	}
+#endif
+
+	while (sg_count-- > 0) {
+		if (!sg_count)
+			sg_flags |= 0xC0000000;
+		writel(sg_flags | sg_dma_len(sg), mptr++);
+		writel(i2o_dma_low(sg_dma_address(sg)), mptr++);
+#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
+		if ((sizeof(dma_addr_t) > 4) && c->pae_support)
+			writel(i2o_dma_high(sg_dma_address(sg)), mptr++);
+#endif
+		sg++;
+	}
+	*sg_ptr = mptr;
+
+	return 1;
+};
+
+/**
+ *	i2o_dma_alloc - Allocate DMA memory
+ *	@dev: struct device pointer to the PCI device of the I2O controller
+ *	@addr: i2o_dma struct which should get the DMA buffer
+ *	@len: length of the new DMA memory
+ *	@gfp_mask: GFP mask
+ *
+ *	Allocate a coherent DMA memory and write the pointers into addr.
+ *
+ *	Returns 0 on success or -ENOMEM on failure.
+ */
+static inline int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr,
+				size_t len, unsigned int gfp_mask)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	int dma_64 = 0;
+
+	if ((sizeof(dma_addr_t) > 4) && (pdev->dma_mask == DMA_64BIT_MASK)) {
+		dma_64 = 1;
+		if (pci_set_dma_mask(pdev, DMA_32BIT_MASK))
+			return -ENOMEM;
+	}
+
+	addr->virt = dma_alloc_coherent(dev, len, &addr->phys, gfp_mask);
+
+	if ((sizeof(dma_addr_t) > 4) && dma_64)
+		if (pci_set_dma_mask(pdev, DMA_64BIT_MASK))
+			printk(KERN_WARNING "i2o: unable to set 64-bit DMA");
+
+	if (!addr->virt)
+		return -ENOMEM;
+
+	memset(addr->virt, 0, len);
+	addr->len = len;
+
+	return 0;
+};
+
+/**
+ *	i2o_dma_free - Free DMA memory
+ *	@dev: struct device pointer to the PCI device of the I2O controller
+ *	@addr: i2o_dma struct which contains the DMA buffer
+ *
+ *	Free a coherent DMA memory and set virtual address of addr to NULL.
+ */
+static inline void i2o_dma_free(struct device *dev, struct i2o_dma *addr)
+{
+	if (addr->virt) {
+		if (addr->phys)
+			dma_free_coherent(dev, addr->len, addr->virt,
+					  addr->phys);
+		else
+			kfree(addr->virt);
+		addr->virt = NULL;
+	}
+};
+
+/**
+ *	i2o_dma_realloc - Realloc DMA memory
+ *	@dev: struct device pointer to the PCI device of the I2O controller
+ *	@addr: pointer to a i2o_dma struct DMA buffer
+ *	@len: new length of memory
+ *	@gfp_mask: GFP mask
+ *
+ *	If there was something allocated in the addr, free it first. If len > 0
+ *	than try to allocate it and write the addresses back to the addr
+ *	structure. If len == 0 set the virtual address to NULL.
+ *
+ *	Returns the 0 on success or negative error code on failure.
+ */
+static inline int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr,
+				  size_t len, unsigned int gfp_mask)
+{
+	i2o_dma_free(dev, addr);
+
+	if (len)
+		return i2o_dma_alloc(dev, addr, len, gfp_mask);
+
+	return 0;
+};
+
 /* I2O driver (OSM) functions */
 extern int i2o_driver_register(struct i2o_driver *);
 extern void i2o_driver_unregister(struct i2o_driver *);
@@ -385,49 +629,11 @@
 /* Exec OSM functions */
 extern int i2o_exec_lct_get(struct i2o_controller *);
 
-/* device to i2o_device and driver to i2o_driver convertion functions */
+/* device / driver / kobject conversion functions */
 #define to_i2o_driver(drv) container_of(drv,struct i2o_driver, driver)
 #define to_i2o_device(dev) container_of(dev, struct i2o_device, device)
-
-/*
- *	Messenger inlines
- */
-static inline u32 I2O_POST_READ32(struct i2o_controller *c)
-{
-	rmb();
-	return readl(c->post_port);
-};
-
-static inline void I2O_POST_WRITE32(struct i2o_controller *c, u32 val)
-{
-	wmb();
-	writel(val, c->post_port);
-};
-
-static inline u32 I2O_REPLY_READ32(struct i2o_controller *c)
-{
-	rmb();
-	return readl(c->reply_port);
-};
-
-static inline void I2O_REPLY_WRITE32(struct i2o_controller *c, u32 val)
-{
-	wmb();
-	writel(val, c->reply_port);
-};
-
-static inline u32 I2O_IRQ_READ32(struct i2o_controller *c)
-{
-	rmb();
-	return readl(c->irq_mask);
-};
-
-static inline void I2O_IRQ_WRITE32(struct i2o_controller *c, u32 val)
-{
-	wmb();
-	writel(val, c->irq_mask);
-	wmb();
-};
+#define to_i2o_controller(dev) container_of(dev, struct i2o_controller, device)
+#define kobj_to_i2o_device(kobj) to_i2o_device(container_of(kobj, struct device, kobj))
 
 /**
  *	i2o_msg_get - obtain an I2O message from the IOP
@@ -443,11 +649,11 @@
  *	available returns I2O_QUEUE_EMPTY and msg is leaved untouched.
  */
 static inline u32 i2o_msg_get(struct i2o_controller *c,
-			      struct i2o_message __iomem **msg)
+			      struct i2o_message __iomem ** msg)
 {
-	u32 m;
+	u32 m = readl(c->in_port);
 
-	if ((m = I2O_POST_READ32(c)) != I2O_QUEUE_EMPTY)
+	if (m != I2O_QUEUE_EMPTY)
 		*msg = c->in_queue.virt + m;
 
 	return m;
@@ -462,7 +668,7 @@
  */
 static inline void i2o_msg_post(struct i2o_controller *c, u32 m)
 {
-	I2O_POST_WRITE32(c, m);
+	writel(m, c->in_port);
 };
 
 /**
@@ -491,12 +697,10 @@
  *	The I2O controller must be informed that the reply message is not needed
  *	anymore. If you forget to flush the reply, the message frame can't be
  *	used by the controller anymore and is therefore lost.
- *
- *	FIXME: is there a timeout after which the controller reuse the message?
  */
 static inline void i2o_flush_reply(struct i2o_controller *c, u32 m)
 {
-	I2O_REPLY_WRITE32(c, m);
+	writel(m, c->out_port);
 };
 
 /**
@@ -530,97 +734,13 @@
  *	work for receive side messages as they are kmalloc objects
  *	in a different pool.
  */
-static inline struct i2o_message __iomem *i2o_msg_in_to_virt(struct i2o_controller *c,
-						     u32 m)
+static inline struct i2o_message __iomem *i2o_msg_in_to_virt(struct
+							     i2o_controller *c,
+							     u32 m)
 {
 	return c->in_queue.virt + m;
 };
 
-/**
- *	i2o_dma_alloc - Allocate DMA memory
- *	@dev: struct device pointer to the PCI device of the I2O controller
- *	@addr: i2o_dma struct which should get the DMA buffer
- *	@len: length of the new DMA memory
- *	@gfp_mask: GFP mask
- *
- *	Allocate a coherent DMA memory and write the pointers into addr.
- *
- *	Returns 0 on success or -ENOMEM on failure.
- */
-static inline int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr,
-				size_t len, unsigned int gfp_mask)
-{
-	addr->virt = dma_alloc_coherent(dev, len, &addr->phys, gfp_mask);
-	if (!addr->virt)
-		return -ENOMEM;
-
-	memset(addr->virt, 0, len);
-	addr->len = len;
-
-	return 0;
-};
-
-/**
- *	i2o_dma_free - Free DMA memory
- *	@dev: struct device pointer to the PCI device of the I2O controller
- *	@addr: i2o_dma struct which contains the DMA buffer
- *
- *	Free a coherent DMA memory and set virtual address of addr to NULL.
- */
-static inline void i2o_dma_free(struct device *dev, struct i2o_dma *addr)
-{
-	if (addr->virt) {
-		if (addr->phys)
-			dma_free_coherent(dev, addr->len, addr->virt,
-					  addr->phys);
-		else
-			kfree(addr->virt);
-		addr->virt = NULL;
-	}
-};
-
-/**
- *	i2o_dma_map - Map the memory to DMA
- *	@dev: struct device pointer to the PCI device of the I2O controller
- *	@addr: i2o_dma struct which should be mapped
- *
- *	Map the memory in addr->virt to coherent DMA memory and write the
- *	physical address into addr->phys.
- *
- *	Returns 0 on success or -ENOMEM on failure.
- */
-static inline int i2o_dma_map(struct device *dev, struct i2o_dma *addr)
-{
-	if (!addr->virt)
-		return -EFAULT;
-
-	if (!addr->phys)
-		addr->phys = dma_map_single(dev, addr->virt, addr->len,
-					    DMA_BIDIRECTIONAL);
-	if (!addr->phys)
-		return -ENOMEM;
-
-	return 0;
-};
-
-/**
- *	i2o_dma_unmap - Unmap the DMA memory
- *	@dev: struct device pointer to the PCI device of the I2O controller
- *	@addr: i2o_dma struct which should be unmapped
- *
- *	Unmap the memory in addr->virt from DMA memory.
- */
-static inline void i2o_dma_unmap(struct device *dev, struct i2o_dma *addr)
-{
-	if (!addr->virt)
-		return;
-
-	if (addr->phys) {
-		dma_unmap_single(dev, addr->phys, addr->len, DMA_BIDIRECTIONAL);
-		addr->phys = 0;
-	}
-};
-
 /*
  *	Endian handling wrapped into the macro - keeps the core code
  *	cleaner.
@@ -773,6 +893,14 @@
 #define I2O_CMD_SCSI_BUSRESET		0x27
 
 /*
+ * Bus Adapter Class
+ */
+#define I2O_CMD_BUS_ADAPTER_RESET	0x85
+#define I2O_CMD_BUS_RESET		0x87
+#define I2O_CMD_BUS_SCAN		0x89
+#define I2O_CMD_BUS_QUIESCE		0x8b
+
+/*
  * Random Block Storage Class
  */
 #define I2O_CMD_BLOCK_READ		0x30
@@ -784,7 +912,7 @@
 #define I2O_CMD_BLOCK_MEJECT		0x43
 #define I2O_CMD_BLOCK_POWER		0x70
 
-#define I2O_PRIVATE_MSG			0xFF
+#define I2O_CMD_PRIVATE			0xFF
 
 /* Command status values  */
 
@@ -922,7 +1050,7 @@
 #define I2OVER15	0x0001
 #define I2OVER20	0x0002
 
-/* Default is 1.5, FIXME: Need support for both 1.5 and 2.0 */
+/* Default is 1.5 */
 #define I2OVERSION	I2OVER15
 
 #define SGL_OFFSET_0    I2OVERSION
@@ -933,9 +1061,9 @@
 #define SGL_OFFSET_8    (0x0080 | I2OVERSION)
 #define SGL_OFFSET_9    (0x0090 | I2OVERSION)
 #define SGL_OFFSET_10   (0x00A0 | I2OVERSION)
-
-#define TRL_OFFSET_5    (0x0050 | I2OVERSION)
-#define TRL_OFFSET_6    (0x0060 | I2OVERSION)
+#define SGL_OFFSET_11   (0x00B0 | I2OVERSION)
+#define SGL_OFFSET_12   (0x00C0 | I2OVERSION)
+#define SGL_OFFSET(x)   (((x)<<4) | I2OVERSION)
 
 /* Transaction Reply Lists (TRL) Control Word structure */
 #define TRL_SINGLE_FIXED_LENGTH		0x00
@@ -962,17 +1090,13 @@
 #define ELEVEN_WORD_MSG_SIZE	0x000B0000
 #define I2O_MESSAGE_SIZE(x)	((x)<<16)
 
-/* Special TID Assignments */
-
+/* special TID assignments */
 #define ADAPTER_TID		0
 #define HOST_TID		1
 
-#define MSG_FRAME_SIZE		128	/* i2o_scsi assumes >= 32 */
-#define REPLY_FRAME_SIZE	17
-#define SG_TABLESIZE		30
-#define NMBR_MSG_FRAMES		128
-
-#define MSG_POOL_SIZE		(MSG_FRAME_SIZE*NMBR_MSG_FRAMES*sizeof(u32))
+/* outbound queue defines */
+#define I2O_MAX_OUTBOUND_MSG_FRAMES	128
+#define I2O_OUTBOUND_MSG_FRAME_SIZE	128	/* in 32-bit words */
 
 #define I2O_POST_WAIT_OK	0
 #define I2O_POST_WAIT_TIMEOUT	-ETIMEDOUT
@@ -993,11 +1117,10 @@
 #define I2O_HRT_GET_TRIES		3
 #define I2O_LCT_GET_TRIES		3
 
-/* request queue sizes */
+/* defines for max_sectors and max_phys_segments */
 #define I2O_MAX_SECTORS			1024
-#define I2O_MAX_SEGMENTS		128
-
-#define I2O_REQ_MEMPOOL_SIZE		32
+#define I2O_MAX_SECTORS_LIMITED		256
+#define I2O_MAX_PHYS_SEGMENTS		MAX_PHYS_SEGMENTS
 
 #endif				/* __KERNEL__ */
 #endif				/* _I2O_H */
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 336d6e5..9212907 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -917,7 +917,7 @@
 	unsigned dma;
 
 	void (*led_act)(void *data, int rw);
-} ide_hwif_t;
+} ____cacheline_maxaligned_in_smp ide_hwif_t;
 
 /*
  *  internal ide interrupt handler type
diff --git a/include/linux/if.h b/include/linux/if.h
index d73a9d6..ce627d9 100644
--- a/include/linux/if.h
+++ b/include/linux/if.h
@@ -33,7 +33,7 @@
 #define	IFF_LOOPBACK	0x8		/* is a loopback net		*/
 #define	IFF_POINTOPOINT	0x10		/* interface is has p-p link	*/
 #define	IFF_NOTRAILERS	0x20		/* avoid use of trailers	*/
-#define	IFF_RUNNING	0x40		/* resources allocated		*/
+#define	IFF_RUNNING	0x40		/* interface running and carrier ok */
 #define	IFF_NOARP	0x80		/* no ARP protocol		*/
 #define	IFF_PROMISC	0x100		/* receive all packets		*/
 #define	IFF_ALLMULTI	0x200		/* receive all multicast packets*/
diff --git a/include/linux/if_bonding.h b/include/linux/if_bonding.h
index 57024ce..84598fa 100644
--- a/include/linux/if_bonding.h
+++ b/include/linux/if_bonding.h
@@ -35,6 +35,9 @@
  *
  * 2003/12/01 - Shmulik Hen <shmulik.hen at intel dot com>
  *	- Code cleanup and style changes
+ *
+ * 2005/05/05 - Jason Gabler <jygabler at lbl dot gov>
+ *      - added definitions for various XOR hashing policies
  */
 
 #ifndef _LINUX_IF_BONDING_H
@@ -80,6 +83,10 @@
 
 #define BOND_DEFAULT_MAX_BONDS  1   /* Default maximum number of devices to support */
 
+/* hashing types */
+#define BOND_XMIT_POLICY_LAYER2		0 /* layer 2 (MAC only), default */
+#define BOND_XMIT_POLICY_LAYER34	1 /* layer 3+4 (IP ^ MAC) */
+
 typedef struct ifbond {
 	__s32 bond_mode;
 	__s32 num_slaves;
diff --git a/include/linux/if_tr.h b/include/linux/if_tr.h
index 6688b41..3fba9e2 100644
--- a/include/linux/if_tr.h
+++ b/include/linux/if_tr.h
@@ -19,6 +19,8 @@
 #ifndef _LINUX_IF_TR_H
 #define _LINUX_IF_TR_H
 
+#include <asm/byteorder.h>	/* For __be16 */
+
 /* IEEE 802.5 Token-Ring magic constants.  The frame sizes omit the preamble
    and FCS/CRC (frame check sequence). */
 #define TR_ALEN		6		/* Octets in one token-ring addr */
diff --git a/include/linux/init.h b/include/linux/init.h
index 05c83e0..59008c3 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -229,6 +229,18 @@
 #define __devexitdata __exitdata
 #endif
 
+#ifdef CONFIG_HOTPLUG_CPU
+#define __cpuinit
+#define __cpuinitdata
+#define __cpuexit
+#define __cpuexitdata
+#else
+#define __cpuinit	__init
+#define __cpuinitdata __initdata
+#define __cpuexit __exit
+#define __cpuexitdata	__exitdata
+#endif
+
 /* Functions marked as __devexit may be discarded at kernel link time, depending
    on config options.  Newer versions of binutils detect references from
    retained sections to discarded sections and flag an error.  Pointers to
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index a6a8c1a..c727c195 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -81,6 +81,7 @@
 	.mm		= NULL,						\
 	.active_mm	= &init_mm,					\
 	.run_list	= LIST_HEAD_INIT(tsk.run_list),			\
+	.ioprio		= 0,						\
 	.time_slice	= HZ,						\
 	.tasks		= LIST_HEAD_INIT(tsk.tasks),			\
 	.ptrace_children= LIST_HEAD_INIT(tsk.ptrace_children),		\
@@ -108,9 +109,9 @@
 	.blocked	= {{0}},					\
 	.alloc_lock	= SPIN_LOCK_UNLOCKED,				\
 	.proc_lock	= SPIN_LOCK_UNLOCKED,				\
-	.switch_lock	= SPIN_LOCK_UNLOCKED,				\
 	.journal_info	= NULL,						\
 	.cpu_timers	= INIT_CPU_TIMERS(tsk.cpu_timers),		\
+	.fs_excl	= ATOMIC_INIT(0),				\
 }
 
 
diff --git a/include/linux/input.h b/include/linux/input.h
index 43e8ece..b9cc0ac 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -1019,7 +1019,7 @@
 	dev->absbit[LONG(axis)] |= BIT(axis);
 }
 
-extern struct class_simple *input_class;
+extern struct class *input_class;
 
 #endif
 #endif
diff --git a/include/linux/ioc4.h b/include/linux/ioc4.h
new file mode 100644
index 0000000..3dd18b7
--- /dev/null
+++ b/include/linux/ioc4.h
@@ -0,0 +1,179 @@
+/*
+ * 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 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#ifndef _LINUX_IOC4_H
+#define _LINUX_IOC4_H
+
+#include <linux/interrupt.h>
+
+/***************
+ * Definitions *
+ ***************/
+
+/* Miscellaneous values inherent to hardware */
+
+#define IOC4_EXTINT_COUNT_DIVISOR 520	/* PCI clocks per COUNT tick */
+
+/***********************************
+ * Structures needed by subdrivers *
+ ***********************************/
+
+/* This structure fully describes the IOC4 miscellaneous registers which
+ * appear at bar[0]+0x00000 through bar[0]+0x0005c.  The corresponding
+ * PCI resource is managed by the main IOC4 driver because it contains
+ * registers of interest to many different IOC4 subdrivers.
+ */
+struct ioc4_misc_regs {
+	/* Miscellaneous IOC4 registers */
+	union ioc4_pci_err_addr_l {
+		uint32_t raw;
+		struct {
+			uint32_t valid:1;	/* Address captured */
+			uint32_t master_id:4;	/* Unit causing error
+						 * 0/1: Serial port 0 TX/RX
+						 * 2/3: Serial port 1 TX/RX
+						 * 4/5: Serial port 2 TX/RX
+						 * 6/7: Serial port 3 TX/RX
+						 * 8: ATA/ATAPI
+						 * 9-15: Undefined
+						 */
+			uint32_t mul_err:1;	/* Multiple errors occurred */
+			uint32_t addr:26;	/* Bits 31-6 of error addr */
+		} fields;
+	} pci_err_addr_l;
+	uint32_t pci_err_addr_h;	/* Bits 63-32 of error addr */
+	union ioc4_sio_int {
+		uint32_t raw;
+		struct {
+			uint8_t tx_mt:1;	/* TX ring buffer empty */
+			uint8_t rx_full:1;	/* RX ring buffer full */
+			uint8_t rx_high:1;	/* RX high-water exceeded */
+			uint8_t rx_timer:1;	/* RX timer has triggered */
+			uint8_t delta_dcd:1;	/* DELTA_DCD seen */
+			uint8_t delta_cts:1;	/* DELTA_CTS seen */
+			uint8_t intr_pass:1;	/* Interrupt pass-through */
+			uint8_t tx_explicit:1;	/* TX, MCW, or delay complete */
+		} fields[4];
+	} sio_ir;		/* Serial interrupt state */
+	union ioc4_other_int {
+		uint32_t raw;
+		struct {
+			uint32_t ata_int:1;	/* ATA port passthru */
+			uint32_t ata_memerr:1;	/* ATA halted by mem error */
+			uint32_t memerr:4;	/* Serial halted by mem err */
+			uint32_t kbd_int:1;	/* kbd/mouse intr asserted */
+			uint32_t reserved:16;	/* zero */
+			uint32_t rt_int:1;	/* INT_OUT section latch */
+			uint32_t gen_int:8;	/* Intr. from generic pins */
+		} fields;
+	} other_ir;		/* Other interrupt state */
+	union ioc4_sio_int sio_ies;	/* Serial interrupt enable set */
+	union ioc4_other_int other_ies;	/* Other interrupt enable set */
+	union ioc4_sio_int sio_iec;	/* Serial interrupt enable clear */
+	union ioc4_other_int other_iec;	/* Other interrupt enable clear */
+	union ioc4_sio_cr {
+		uint32_t raw;
+		struct {
+			uint32_t cmd_pulse:4;	/* Bytebus strobe width */
+			uint32_t arb_diag:3;	/* PCI bus requester */
+			uint32_t sio_diag_idle:1;	/* Active ser req? */
+			uint32_t ata_diag_idle:1;	/* Active ATA req? */
+			uint32_t ata_diag_active:1;	/* ATA req is winner */
+			uint32_t reserved:22;	/* zero */
+		} fields;
+	} sio_cr;
+	uint32_t unused1;
+	union ioc4_int_out {
+		uint32_t raw;
+		struct {
+			uint32_t count:16;	/* Period control */
+			uint32_t mode:3;	/* Output signal shape */
+			uint32_t reserved:11;	/* zero */
+			uint32_t diag:1;	/* Timebase control */
+			uint32_t int_out:1;	/* Current value */
+		} fields;
+	} int_out;		/* External interrupt output control */
+	uint32_t unused2;
+	union ioc4_gpcr {
+		uint32_t raw;
+		struct {
+			uint32_t dir:8;	/* Pin direction */
+			uint32_t edge:8;	/* Edge/level mode */
+			uint32_t reserved1:4;	/* zero */
+			uint32_t int_out_en:1;	/* INT_OUT enable */
+			uint32_t reserved2:11;	/* zero */
+		} fields;
+	} gpcr_s;		/* Generic PIO control set */
+	union ioc4_gpcr gpcr_c;	/* Generic PIO control clear */
+	union ioc4_gpdr {
+		uint32_t raw;
+		struct {
+			uint32_t gen_pin:8;	/* State of pins */
+			uint32_t reserved:24;
+		} fields;
+	} gpdr;			/* Generic PIO data */
+	uint32_t unused3;
+	union ioc4_gppr {
+		uint32_t raw;
+		struct {
+			uint32_t gen_pin:1;	/* Single pin state */
+			uint32_t reserved:31;
+		} fields;
+	} gppr[8];		/* Generic PIO pins */
+};
+
+/* Masks for GPCR DIR pins */
+#define IOC4_GPCR_DIR_0 0x01	/* External interrupt output */
+#define IOC4_GPCR_DIR_1 0x02	/* External interrupt input */
+#define IOC4_GPCR_DIR_2 0x04
+#define IOC4_GPCR_DIR_3 0x08	/* Keyboard/mouse presence */
+#define IOC4_GPCR_DIR_4 0x10	/* Ser. port 0 xcvr select (0=232, 1=422) */
+#define IOC4_GPCR_DIR_5 0x20	/* Ser. port 1 xcvr select (0=232, 1=422) */
+#define IOC4_GPCR_DIR_6 0x40	/* Ser. port 2 xcvr select (0=232, 1=422) */
+#define IOC4_GPCR_DIR_7 0x80	/* Ser. port 3 xcvr select (0=232, 1=422) */
+
+/* Masks for GPCR EDGE pins */
+#define IOC4_GPCR_EDGE_0 0x01
+#define IOC4_GPCR_EDGE_1 0x02	/* External interrupt input */
+#define IOC4_GPCR_EDGE_2 0x04
+#define IOC4_GPCR_EDGE_3 0x08
+#define IOC4_GPCR_EDGE_4 0x10
+#define IOC4_GPCR_EDGE_5 0x20
+#define IOC4_GPCR_EDGE_6 0x40
+#define IOC4_GPCR_EDGE_7 0x80
+
+/* One of these per IOC4 */
+struct ioc4_driver_data {
+	struct list_head idd_list;
+	unsigned long idd_bar0;
+	struct pci_dev *idd_pdev;
+	const struct pci_device_id *idd_pci_id;
+	struct __iomem ioc4_misc_regs *idd_misc_regs;
+	unsigned long count_period;
+	void *idd_serial_data;
+};
+
+/* One per submodule */
+struct ioc4_submodule {
+	struct list_head is_list;
+	char *is_name;
+	struct module *is_owner;
+	int (*is_probe) (struct ioc4_driver_data *);
+	int (*is_remove) (struct ioc4_driver_data *);
+};
+
+#define IOC4_NUM_CARDS		8	/* max cards per partition */
+
+/**********************************
+ * Functions needed by submodules *
+ **********************************/
+
+extern int ioc4_register_submodule(struct ioc4_submodule *);
+extern void ioc4_unregister_submodule(struct ioc4_submodule *);
+
+#endif				/* _LINUX_IOC4_H */
diff --git a/include/linux/ioc4_common.h b/include/linux/ioc4_common.h
deleted file mode 100644
index b03bcc4..0000000
--- a/include/linux/ioc4_common.h
+++ /dev/null
@@ -1,21 +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 Silicon Graphics, Inc.  All Rights Reserved.
- */
-
-#ifndef _LINUX_IOC4_COMMON_H
-#define _LINUX_IOC4_COMMON_H
-
-/* prototypes */
-
-int ioc4_serial_init(void);
-
-int ioc4_serial_attach_one(struct pci_dev *pdev, const struct
-				pci_device_id *pci_id);
-int ioc4_ide_attach_one(struct pci_dev *pdev, const struct
-				pci_device_id *pci_id);
-
-#endif	/* _LINUX_IOC4_COMMON_H */
diff --git a/include/linux/ioprio.h b/include/linux/ioprio.h
new file mode 100644
index 0000000..8a453a0
--- /dev/null
+++ b/include/linux/ioprio.h
@@ -0,0 +1,88 @@
+#ifndef IOPRIO_H
+#define IOPRIO_H
+
+#include <linux/sched.h>
+
+/*
+ * Gives us 8 prio classes with 13-bits of data for each class
+ */
+#define IOPRIO_BITS		(16)
+#define IOPRIO_CLASS_SHIFT	(13)
+#define IOPRIO_PRIO_MASK	((1UL << IOPRIO_CLASS_SHIFT) - 1)
+
+#define IOPRIO_PRIO_CLASS(mask)	((mask) >> IOPRIO_CLASS_SHIFT)
+#define IOPRIO_PRIO_DATA(mask)	((mask) & IOPRIO_PRIO_MASK)
+#define IOPRIO_PRIO_VALUE(class, data)	(((class) << IOPRIO_CLASS_SHIFT) | data)
+
+#define ioprio_valid(mask)	(IOPRIO_PRIO_CLASS((mask)) != IOPRIO_CLASS_NONE)
+
+/*
+ * These are the io priority groups as implemented by CFQ. RT is the realtime
+ * class, it always gets premium service. BE is the best-effort scheduling
+ * class, the default for any process. IDLE is the idle scheduling class, it
+ * is only served when no one else is using the disk.
+ */
+enum {
+	IOPRIO_CLASS_NONE,
+	IOPRIO_CLASS_RT,
+	IOPRIO_CLASS_BE,
+	IOPRIO_CLASS_IDLE,
+};
+
+/*
+ * 8 best effort priority levels are supported
+ */
+#define IOPRIO_BE_NR	(8)
+
+asmlinkage int sys_ioprio_set(int, int, int);
+asmlinkage int sys_ioprio_get(int, int);
+
+enum {
+	IOPRIO_WHO_PROCESS = 1,
+	IOPRIO_WHO_PGRP,
+	IOPRIO_WHO_USER,
+};
+
+/*
+ * if process has set io priority explicitly, use that. if not, convert
+ * the cpu scheduler nice value to an io priority
+ */
+#define IOPRIO_NORM	(4)
+static inline int task_ioprio(struct task_struct *task)
+{
+	WARN_ON(!ioprio_valid(task->ioprio));
+	return IOPRIO_PRIO_DATA(task->ioprio);
+}
+
+static inline int task_nice_ioprio(struct task_struct *task)
+{
+	return (task_nice(task) + 20) / 5;
+}
+
+/*
+ * For inheritance, return the highest of the two given priorities
+ */
+static inline int ioprio_best(unsigned short aprio, unsigned short bprio)
+{
+	unsigned short aclass = IOPRIO_PRIO_CLASS(aprio);
+	unsigned short bclass = IOPRIO_PRIO_CLASS(bprio);
+
+	if (!ioprio_valid(aprio))
+		return bprio;
+	if (!ioprio_valid(bprio))
+		return aprio;
+
+	if (aclass == IOPRIO_CLASS_NONE)
+		aclass = IOPRIO_CLASS_BE;
+	if (bclass == IOPRIO_CLASS_NONE)
+		bclass = IOPRIO_CLASS_BE;
+
+	if (aclass == bclass)
+		return min(aprio, bprio);
+	if (aclass > bclass)
+		return bprio;
+	else
+		return aprio;
+}
+
+#endif
diff --git a/include/linux/ip.h b/include/linux/ip.h
index 8438c68..31e7ced 100644
--- a/include/linux/ip.h
+++ b/include/linux/ip.h
@@ -81,6 +81,7 @@
 #ifdef __KERNEL__
 #include <linux/config.h>
 #include <linux/types.h>
+#include <net/request_sock.h>
 #include <net/sock.h>
 #include <linux/igmp.h>
 #include <net/flow.h>
@@ -107,6 +108,26 @@
 
 #define optlength(opt) (sizeof(struct ip_options) + opt->optlen)
 
+struct inet_request_sock {
+	struct request_sock	req;
+	u32			loc_addr;
+	u32			rmt_addr;
+	u16			rmt_port;
+	u16			snd_wscale : 4, 
+				rcv_wscale : 4, 
+				tstamp_ok  : 1,
+				sack_ok	   : 1,
+				wscale_ok  : 1,
+				ecn_ok	   : 1,
+				acked	   : 1;
+	struct ip_options	*opt;
+};
+
+static inline struct inet_request_sock *inet_rsk(const struct request_sock *sk)
+{
+	return (struct inet_request_sock *)sk;
+}
+
 struct ipv6_pinfo;
 
 struct inet_sock {
diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h
index 2ec265e..596ca61 100644
--- a/include/linux/ipmi.h
+++ b/include/linux/ipmi.h
@@ -209,6 +209,11 @@
 #include <linux/list.h>
 #include <linux/module.h>
 
+#ifdef CONFIG_PROC_FS
+#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. */
 typedef struct ipmi_user *ipmi_user_t;
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index ab0d0ef..6fcd6a0 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -193,6 +193,19 @@
 
 #define IP6CB(skb)	((struct inet6_skb_parm*)((skb)->cb))
 
+struct tcp6_request_sock {
+	struct tcp_request_sock	req;
+	struct in6_addr		loc_addr;
+	struct in6_addr		rmt_addr;
+	struct sk_buff		*pktopts;
+	int			iif;
+};
+
+static inline struct tcp6_request_sock *tcp6_rsk(const struct request_sock *sk)
+{
+	return (struct tcp6_request_sock *)sk;
+}
+
 /**
  * struct ipv6_pinfo - ipv6 private area
  *
diff --git a/include/linux/irq.h b/include/linux/irq.h
index c3ff4d1..1227779 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -47,6 +47,10 @@
 	void (*ack)(unsigned int irq);
 	void (*end)(unsigned int irq);
 	void (*set_affinity)(unsigned int irq, cpumask_t dest);
+	/* Currently used only by UML, might disappear one day.*/
+#ifdef CONFIG_IRQ_RELEASE_METHOD
+	void (*release)(unsigned int irq, void *dev_id);
+#endif
 };
 
 typedef struct hw_interrupt_type  hw_irq_controller;
@@ -84,7 +88,6 @@
 				       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, int action_ret);
-extern void report_bad_irq(unsigned int irq, irq_desc_t *desc, int action_ret);
 extern int can_request_irq(unsigned int irq, unsigned long irqflags);
 
 extern void init_irq_proc(void);
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index e25b970..687ba8c 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -58,15 +58,23 @@
  * be biten later when the calling function happens to sleep when it is not
  * supposed to.
  */
-#ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
-#define might_sleep() __might_sleep(__FILE__, __LINE__)
-#define might_sleep_if(cond) do { if (unlikely(cond)) might_sleep(); } while (0)
-void __might_sleep(char *file, int line);
+#ifdef CONFIG_PREEMPT_VOLUNTARY
+extern int cond_resched(void);
+# define might_resched() cond_resched()
 #else
-#define might_sleep() do {} while(0)
-#define might_sleep_if(cond) do {} while (0)
+# define might_resched() do { } while (0)
 #endif
 
+#ifdef CONFIG_DEBUG_SPINLOCK_SLEEP
+  void __might_sleep(char *file, int line);
+# define might_sleep() \
+	do { __might_sleep(__FILE__, __LINE__); might_resched(); } while (0)
+#else
+# define might_sleep() do { might_resched(); } while (0)
+#endif
+
+#define might_sleep_if(cond) do { if (unlikely(cond)) might_sleep(); } while (0)
+
 #define abs(x) ({				\
 		int __x = (x);			\
 		(__x < 0) ? -__x : __x;		\
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
new file mode 100644
index 0000000..c846847
--- /dev/null
+++ b/include/linux/kexec.h
@@ -0,0 +1,135 @@
+#ifndef LINUX_KEXEC_H
+#define LINUX_KEXEC_H
+
+#ifdef CONFIG_KEXEC
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/linkage.h>
+#include <linux/compat.h>
+#include <asm/kexec.h>
+
+/* Verify architecture specific macros are defined */
+
+#ifndef KEXEC_SOURCE_MEMORY_LIMIT
+#error KEXEC_SOURCE_MEMORY_LIMIT not defined
+#endif
+
+#ifndef KEXEC_DESTINATION_MEMORY_LIMIT
+#error KEXEC_DESTINATION_MEMORY_LIMIT not defined
+#endif
+
+#ifndef KEXEC_CONTROL_MEMORY_LIMIT
+#error KEXEC_CONTROL_MEMORY_LIMIT not defined
+#endif
+
+#ifndef KEXEC_CONTROL_CODE_SIZE
+#error KEXEC_CONTROL_CODE_SIZE not defined
+#endif
+
+#ifndef KEXEC_ARCH
+#error KEXEC_ARCH not defined
+#endif
+
+/*
+ * This structure is used to hold the arguments that are used when loading
+ * kernel binaries.
+ */
+
+typedef unsigned long kimage_entry_t;
+#define IND_DESTINATION  0x1
+#define IND_INDIRECTION  0x2
+#define IND_DONE         0x4
+#define IND_SOURCE       0x8
+
+#define KEXEC_SEGMENT_MAX 8
+struct kexec_segment {
+	void __user *buf;
+	size_t bufsz;
+	unsigned long mem;	/* User space sees this as a (void *) ... */
+	size_t memsz;
+};
+
+#ifdef CONFIG_COMPAT
+struct compat_kexec_segment {
+	compat_uptr_t buf;
+	compat_size_t bufsz;
+	compat_ulong_t mem;	/* User space sees this as a (void *) ... */
+	compat_size_t memsz;
+};
+#endif
+
+struct kimage {
+	kimage_entry_t head;
+	kimage_entry_t *entry;
+	kimage_entry_t *last_entry;
+
+	unsigned long destination;
+
+	unsigned long start;
+	struct page *control_code_page;
+
+	unsigned long nr_segments;
+	struct kexec_segment segment[KEXEC_SEGMENT_MAX];
+
+	struct list_head control_pages;
+	struct list_head dest_pages;
+	struct list_head unuseable_pages;
+
+	/* Address of next control page to allocate for crash kernels. */
+	unsigned long control_page;
+
+	/* Flags to indicate special processing */
+	unsigned int type : 1;
+#define KEXEC_TYPE_DEFAULT 0
+#define KEXEC_TYPE_CRASH   1
+};
+
+
+
+/* kexec interface functions */
+extern NORET_TYPE void machine_kexec(struct kimage *image) ATTRIB_NORET;
+extern int machine_kexec_prepare(struct kimage *image);
+extern void machine_kexec_cleanup(struct kimage *image);
+extern asmlinkage long sys_kexec_load(unsigned long entry,
+					unsigned long nr_segments,
+					struct kexec_segment __user *segments,
+					unsigned long flags);
+#ifdef CONFIG_COMPAT
+extern asmlinkage long compat_sys_kexec_load(unsigned long entry,
+				unsigned long nr_segments,
+				struct compat_kexec_segment __user *segments,
+				unsigned long flags);
+#endif
+extern struct page *kimage_alloc_control_pages(struct kimage *image,
+						unsigned int order);
+extern void crash_kexec(struct pt_regs *);
+int kexec_should_crash(struct task_struct *);
+extern struct kimage *kexec_image;
+
+#define KEXEC_ON_CRASH  0x00000001
+#define KEXEC_ARCH_MASK 0xffff0000
+
+/* These values match the ELF architecture values.
+ * Unless there is a good reason that should continue to be the case.
+ */
+#define KEXEC_ARCH_DEFAULT ( 0 << 16)
+#define KEXEC_ARCH_386     ( 3 << 16)
+#define KEXEC_ARCH_X86_64  (62 << 16)
+#define KEXEC_ARCH_PPC     (20 << 16)
+#define KEXEC_ARCH_PPC64   (21 << 16)
+#define KEXEC_ARCH_IA_64   (50 << 16)
+#define KEXEC_ARCH_S390    (22 << 16)
+
+#define KEXEC_FLAGS    (KEXEC_ON_CRASH)  /* List of defined/legal kexec flags */
+
+/* Location of a reserved region to hold the crash kernel.
+ */
+extern struct resource crashk_res;
+
+#else /* !CONFIG_KEXEC */
+struct pt_regs;
+struct task_struct;
+static inline void crash_kexec(struct pt_regs *regs) { }
+static inline int kexec_should_crash(struct task_struct *p) { return 0; }
+#endif /* CONFIG_KEXEC */
+#endif /* LINUX_KEXEC_H */
diff --git a/include/linux/key-ui.h b/include/linux/key-ui.h
index 60cc7b7..cc32617 100644
--- a/include/linux/key-ui.h
+++ b/include/linux/key-ui.h
@@ -1,4 +1,4 @@
-/* key-ui.h: key userspace interface stuff for use by keyfs
+/* key-ui.h: key userspace interface stuff
  *
  * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
  * Written by David Howells (dhowells@redhat.com)
@@ -31,8 +31,10 @@
  * subscribed
  */
 struct keyring_list {
-	unsigned	maxkeys;	/* max keys this list can hold */
-	unsigned	nkeys;		/* number of keys currently held */
+	struct rcu_head	rcu;		/* RCU deletion hook */
+	unsigned short	maxkeys;	/* max keys this list can hold */
+	unsigned short	nkeys;		/* number of keys currently held */
+	unsigned short	delkey;		/* key to be unlinked by RCU */
 	struct key	*keys[0];
 };
 
@@ -82,8 +84,45 @@
 	return kperm != 0;
 }
 
+static inline int key_task_groups_search(struct task_struct *tsk, gid_t gid)
+{
+	int ret;
 
-extern struct key *lookup_user_key(key_serial_t id, int create, int part,
+	task_lock(tsk);
+	ret = groups_search(tsk->group_info, gid);
+	task_unlock(tsk);
+	return ret;
+}
+
+static inline int key_task_permission(const struct key *key,
+				      struct task_struct *context,
+				      key_perm_t perm)
+{
+	key_perm_t kperm;
+
+	if (key->uid == context->fsuid) {
+		kperm = key->perm >> 16;
+	}
+	else if (key->gid != -1 &&
+		 key->perm & KEY_GRP_ALL && (
+			 key->gid == context->fsgid ||
+			 key_task_groups_search(context, key->gid)
+			 )
+		 ) {
+		kperm = key->perm >> 8;
+	}
+	else {
+		kperm = key->perm;
+	}
+
+	kperm = kperm & perm & KEY_ALL;
+
+	return kperm == perm;
+
+}
+
+extern struct key *lookup_user_key(struct task_struct *context,
+				   key_serial_t id, int create, int partial,
 				   key_perm_t perm);
 
 extern long join_session_keyring(const char *name);
diff --git a/include/linux/key.h b/include/linux/key.h
index 6aa46d0..970bbd9 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -18,7 +18,7 @@
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/rbtree.h>
-#include <linux/spinlock.h>
+#include <linux/rcupdate.h>
 #include <asm/atomic.h>
 
 #ifdef __KERNEL__
@@ -78,7 +78,6 @@
 	key_serial_t		serial;		/* key serial number */
 	struct rb_node		serial_node;
 	struct key_type		*type;		/* type of key */
-	rwlock_t		lock;		/* examination vs change lock */
 	struct rw_semaphore	sem;		/* change vs change sem */
 	struct key_user		*user;		/* owner of this key */
 	time_t			expiry;		/* time at which key expires (or 0) */
@@ -86,14 +85,10 @@
 	gid_t			gid;
 	key_perm_t		perm;		/* access permissions */
 	unsigned short		quotalen;	/* length added to quota */
-	unsigned short		datalen;	/* payload data length */
-	unsigned short		flags;		/* status flags (change with lock writelocked) */
-#define KEY_FLAG_INSTANTIATED	0x00000001	/* set if key has been instantiated */
-#define KEY_FLAG_DEAD		0x00000002	/* set if key type has been deleted */
-#define KEY_FLAG_REVOKED	0x00000004	/* set if key had been revoked */
-#define KEY_FLAG_IN_QUOTA	0x00000008	/* set if key consumes quota */
-#define KEY_FLAG_USER_CONSTRUCT	0x00000010	/* set if key is being constructed in userspace */
-#define KEY_FLAG_NEGATIVE	0x00000020	/* set if key is negative */
+	unsigned short		datalen;	/* payload data length
+						 * - may not match RCU dereferenced payload
+						 * - payload should contain own length
+						 */
 
 #ifdef KEY_DEBUGGING
 	unsigned		magic;
@@ -101,6 +96,14 @@
 #define KEY_DEBUG_MAGIC_X	0xf8e9dacbu
 #endif
 
+	unsigned long		flags;		/* status flags (change with bitops) */
+#define KEY_FLAG_INSTANTIATED	0	/* set if key has been instantiated */
+#define KEY_FLAG_DEAD		1	/* set if key type has been deleted */
+#define KEY_FLAG_REVOKED	2	/* set if key had been revoked */
+#define KEY_FLAG_IN_QUOTA	3	/* set if key consumes quota */
+#define KEY_FLAG_USER_CONSTRUCT	4	/* set if key is being constructed in userspace */
+#define KEY_FLAG_NEGATIVE	5	/* set if key is negative */
+
 	/* the description string
 	 * - this is used to match a key against search criteria
 	 * - this should be a printable string
@@ -196,10 +199,12 @@
 extern int key_instantiate_and_link(struct key *key,
 				    const void *data,
 				    size_t datalen,
-				    struct key *keyring);
+				    struct key *keyring,
+				    struct key *instkey);
 extern int key_negate_and_link(struct key *key,
 			       unsigned timeout,
-			       struct key *keyring);
+			       struct key *keyring,
+			       struct key *instkey);
 extern void key_revoke(struct key *key);
 extern void key_put(struct key *key);
 
@@ -242,14 +247,13 @@
 				  struct key_type *type,
 				  const char *description);
 
-extern struct key *search_process_keyrings(struct key_type *type,
-					   const char *description);
-
 extern int keyring_add_key(struct key *keyring,
 			   struct key *key);
 
 extern struct key *key_lookup(key_serial_t id);
 
+extern void keyring_replace_payload(struct key *key, void *replacement);
+
 #define key_serial(key) ((key) ? (key)->serial : 0)
 
 /*
@@ -268,14 +272,22 @@
 extern void key_fsgid_changed(struct task_struct *tsk);
 extern void key_init(void);
 
+#define __install_session_keyring(tsk, keyring)			\
+({								\
+	struct key *old_session = tsk->signal->session_keyring;	\
+	tsk->signal->session_keyring = keyring;			\
+	old_session;						\
+})
+
 #else /* CONFIG_KEYS */
 
 #define key_validate(k)			0
 #define key_serial(k)			0
-#define key_get(k) 			NULL
+#define key_get(k) 			({ NULL; })
 #define key_put(k)			do { } while(0)
 #define alloc_uid_keyring(u)		0
 #define switch_uid_keyring(u)		do { } while(0)
+#define __install_session_keyring(t, k)	({ NULL; })
 #define copy_keys(f,t)			0
 #define copy_thread_group_keys(t)	0
 #define exit_keys(t)			do { } while(0)
diff --git a/include/linux/keyctl.h b/include/linux/keyctl.h
index 381dedc..8d7c59a 100644
--- a/include/linux/keyctl.h
+++ b/include/linux/keyctl.h
@@ -20,6 +20,16 @@
 #define KEY_SPEC_USER_SESSION_KEYRING	-5	/* - key ID for UID-session keyring */
 #define KEY_SPEC_GROUP_KEYRING		-6	/* - key ID for GID-specific keyring */
 
+/* request-key default keyrings */
+#define KEY_REQKEY_DEFL_NO_CHANGE		-1
+#define KEY_REQKEY_DEFL_DEFAULT			0
+#define KEY_REQKEY_DEFL_THREAD_KEYRING		1
+#define KEY_REQKEY_DEFL_PROCESS_KEYRING		2
+#define KEY_REQKEY_DEFL_SESSION_KEYRING		3
+#define KEY_REQKEY_DEFL_USER_KEYRING		4
+#define KEY_REQKEY_DEFL_USER_SESSION_KEYRING	5
+#define KEY_REQKEY_DEFL_GROUP_KEYRING		6
+
 /* keyctl commands */
 #define KEYCTL_GET_KEYRING_ID		0	/* ask for a keyring's ID */
 #define KEYCTL_JOIN_SESSION_KEYRING	1	/* join or start named session keyring */
@@ -35,5 +45,6 @@
 #define KEYCTL_READ			11	/* read a key or keyring's contents */
 #define KEYCTL_INSTANTIATE		12	/* instantiate a partially constructed key */
 #define KEYCTL_NEGATE			13	/* negate a partially constructed key */
+#define KEYCTL_SET_REQKEY_KEYRING	14	/* set default request-key keyring */
 
 #endif /*  _LINUX_KEYCTL_H */
diff --git a/include/linux/klist.h b/include/linux/klist.h
new file mode 100644
index 0000000..eebf5e5
--- /dev/null
+++ b/include/linux/klist.h
@@ -0,0 +1,55 @@
+/*
+ *	klist.h - Some generic list helpers, extending struct list_head a bit.
+ *
+ *	Implementations are found in lib/klist.c
+ *
+ *
+ *	Copyright (C) 2005 Patrick Mochel
+ *
+ *	This file is rleased under the GPL v2.
+ */
+
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/kref.h>
+#include <linux/list.h>
+
+
+struct klist {
+	spinlock_t		k_lock;
+	struct list_head	k_list;
+};
+
+
+extern void klist_init(struct klist * k);
+
+
+struct klist_node {
+	struct klist		* n_klist;
+	struct list_head	n_node;
+	struct kref		n_ref;
+	struct completion	n_removed;
+};
+
+extern void klist_add_tail(struct klist * k, struct klist_node * n);
+extern void klist_add_head(struct klist * k, struct klist_node * n);
+
+extern void klist_del(struct klist_node * n);
+extern void klist_remove(struct klist_node * n);
+
+extern int klist_node_attached(struct klist_node * n);
+
+
+struct klist_iter {
+	struct klist		* i_klist;
+	struct list_head	* i_head;
+	struct klist_node	* i_cur;
+};
+
+
+extern void klist_iter_init(struct klist * k, struct klist_iter * i);
+extern void klist_iter_init_node(struct klist * k, struct klist_iter * i, 
+				 struct klist_node * n);
+extern void klist_iter_exit(struct klist_iter * i);
+extern struct klist_node * klist_next(struct klist_iter * i);
+
diff --git a/include/linux/kmod.h b/include/linux/kmod.h
index 95d0e4b..e4a2315 100644
--- a/include/linux/kmod.h
+++ b/include/linux/kmod.h
@@ -19,6 +19,7 @@
  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/stddef.h>
 #include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/compiler.h>
@@ -34,7 +35,17 @@
 #endif
 
 #define try_then_request_module(x, mod...) ((x) ?: (request_module(mod), (x)))
-extern int call_usermodehelper(char *path, char *argv[], char *envp[], int wait);
+
+struct key;
+extern int call_usermodehelper_keys(char *path, char *argv[], char *envp[],
+				    struct key *session_keyring, int wait);
+
+static inline int
+call_usermodehelper(char *path, char **argv, char **envp, int wait)
+{
+	return call_usermodehelper_keys(path, argv, envp, NULL, wait);
+}
+
 extern void usermodehelper_init(void);
 
 #endif /* __LINUX_KMOD_H__ */
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 765d660..3b22304 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -33,7 +33,7 @@
 extern u64 hotplug_seqnum;
 
 struct kobject {
-	char			* k_name;
+	const char		* k_name;
 	char			name[KOBJ_NAME_LEN];
 	struct kref		kref;
 	struct list_head	entry;
@@ -46,7 +46,7 @@
 extern int kobject_set_name(struct kobject *, const char *, ...)
 	__attribute__((format(printf,2,3)));
 
-static inline char * kobject_name(struct kobject * kobj)
+static inline const char * kobject_name(const struct kobject * kobj)
 {
 	return kobj->k_name;
 }
@@ -57,7 +57,7 @@
 extern int kobject_add(struct kobject *);
 extern void kobject_del(struct kobject *);
 
-extern int kobject_rename(struct kobject *, char *new_name);
+extern int kobject_rename(struct kobject *, const char *new_name);
 
 extern int kobject_register(struct kobject *);
 extern void kobject_unregister(struct kobject *);
@@ -94,7 +94,7 @@
  */
 struct kset_hotplug_ops {
 	int (*filter)(struct kset *kset, struct kobject *kobj);
-	char *(*name)(struct kset *kset, struct kobject *kobj);
+	const char *(*name)(struct kset *kset, struct kobject *kobj);
 	int (*hotplug)(struct kset *kset, struct kobject *kobj, char **envp,
 			int num_envp, char *buffer, int buffer_size);
 };
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 99ddba5..5e1a7b0 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -25,27 +25,45 @@
  *		Rusty Russell).
  * 2004-July	Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes
  *		interface to access function arguments.
+ * 2005-May	Hien Nguyen <hien@us.ibm.com> and Jim Keniston
+ *		<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>
+
 #include <asm/kprobes.h>
 
+/* kprobe_status settings */
+#define KPROBE_HIT_ACTIVE	0x00000001
+#define KPROBE_HIT_SS		0x00000002
+#define KPROBE_REENTER		0x00000004
+#define KPROBE_HIT_SSDONE	0x00000008
+
 struct kprobe;
 struct pt_regs;
+struct kretprobe;
+struct kretprobe_instance;
 typedef int (*kprobe_pre_handler_t) (struct kprobe *, struct pt_regs *);
 typedef int (*kprobe_break_handler_t) (struct kprobe *, struct pt_regs *);
 typedef void (*kprobe_post_handler_t) (struct kprobe *, struct pt_regs *,
 				       unsigned long flags);
 typedef int (*kprobe_fault_handler_t) (struct kprobe *, struct pt_regs *,
 				       int trapnr);
+typedef int (*kretprobe_handler_t) (struct kretprobe_instance *,
+				    struct pt_regs *);
+
 struct kprobe {
 	struct hlist_node hlist;
 
 	/* list of kprobes for multi-handler support */
 	struct list_head list;
 
+	/*count the number of times this probe was temporarily disarmed */
+	unsigned long nmissed;
+
 	/* location of the probe point */
 	kprobe_opcode_t *addr;
 
@@ -85,6 +103,62 @@
 	kprobe_opcode_t *entry;	/* probe handling code to jump to */
 };
 
+#ifdef ARCH_SUPPORTS_KRETPROBES
+extern int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs);
+extern void trampoline_post_handler(struct kprobe *p, struct pt_regs *regs,
+							unsigned long flags);
+extern struct task_struct *arch_get_kprobe_task(void *ptr);
+extern void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs);
+extern void arch_kprobe_flush_task(struct task_struct *tk);
+#else /* ARCH_SUPPORTS_KRETPROBES */
+static inline void kretprobe_trampoline(void)
+{
+}
+static inline int trampoline_probe_handler(struct kprobe *p,
+						struct pt_regs *regs)
+{
+	return 0;
+}
+static inline void trampoline_post_handler(struct kprobe *p,
+				struct pt_regs *regs, unsigned long flags)
+{
+}
+static inline void arch_prepare_kretprobe(struct kretprobe *rp,
+					struct pt_regs *regs)
+{
+}
+static inline void arch_kprobe_flush_task(struct task_struct *tk)
+{
+}
+#define arch_get_kprobe_task(ptr) ((struct task_struct *)NULL)
+#endif /* ARCH_SUPPORTS_KRETPROBES */
+/*
+ * Function-return probe -
+ * Note:
+ * User needs to provide a handler function, and initialize maxactive.
+ * maxactive - The maximum number of instances of the probed function that
+ * can be active concurrently.
+ * nmissed - tracks the number of times the probed function's return was
+ * ignored, due to maxactive being too low.
+ *
+ */
+struct kretprobe {
+	struct kprobe kp;
+	kretprobe_handler_t handler;
+	int maxactive;
+	int nmissed;
+	struct hlist_head free_instances;
+	struct hlist_head used_instances;
+};
+
+struct kretprobe_instance {
+	struct hlist_node uflist; /* either on free list or used list */
+	struct hlist_node hlist;
+	struct kretprobe *rp;
+	void *ret_addr;
+	void *stack_addr;
+};
+
 #ifdef CONFIG_KPROBES
 /* Locks kprobe: irq must be disabled */
 void lock_kprobes(void);
@@ -99,11 +173,14 @@
 
 extern int arch_prepare_kprobe(struct kprobe *p);
 extern void arch_copy_kprobe(struct kprobe *p);
+extern void arch_arm_kprobe(struct kprobe *p);
+extern void arch_disarm_kprobe(struct kprobe *p);
 extern void arch_remove_kprobe(struct kprobe *p);
 extern void show_registers(struct pt_regs *regs);
 
 /* Get the kprobe at this addr (if any).  Must have called lock_kprobes */
 struct kprobe *get_kprobe(void *addr);
+struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk);
 
 int register_kprobe(struct kprobe *p);
 void unregister_kprobe(struct kprobe *p);
@@ -113,7 +190,16 @@
 void unregister_jprobe(struct jprobe *p);
 void jprobe_return(void);
 
-#else
+int register_kretprobe(struct kretprobe *rp);
+void unregister_kretprobe(struct kretprobe *rp);
+
+struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp);
+struct kretprobe_instance *get_rp_inst(void *sara);
+struct kretprobe_instance *get_rp_inst_tsk(struct task_struct *tk);
+void add_rp_inst(struct kretprobe_instance *ri);
+void kprobe_flush_task(struct task_struct *tk);
+void recycle_rp_inst(struct kretprobe_instance *ri);
+#else /* CONFIG_KPROBES */
 static inline int kprobe_running(void)
 {
 	return 0;
@@ -135,5 +221,15 @@
 static inline void jprobe_return(void)
 {
 }
-#endif
+static inline int register_kretprobe(struct kretprobe *rp)
+{
+	return -ENOSYS;
+}
+static inline void unregister_kretprobe(struct kretprobe *rp)
+{
+}
+static inline void kprobe_flush_task(struct task_struct *tk)
+{
+}
+#endif				/* CONFIG_KPROBES */
 #endif				/* _LINUX_KPROBES_H */
diff --git a/include/linux/libata.h b/include/linux/libata.h
index b009f80..6cd9ba6 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -421,6 +421,7 @@
 extern unsigned int ata_dev_classify(struct ata_taskfile *tf);
 extern void ata_dev_id_string(u16 *id, unsigned char *s,
 			      unsigned int ofs, unsigned int len);
+extern void ata_dev_config(struct ata_port *ap, unsigned int i);
 extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
 extern void ata_bmdma_start (struct ata_queued_cmd *qc);
 extern void ata_bmdma_stop(struct ata_port *ap);
diff --git a/include/linux/list.h b/include/linux/list.h
index 399b51d..aab2db2 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -185,7 +185,7 @@
  * list_for_each_entry_rcu().
  *
  * Note that the caller is not permitted to immediately free
- * the newly deleted entry.  Instead, either synchronize_kernel()
+ * the newly deleted entry.  Instead, either synchronize_rcu()
  * or call_rcu() must be used to defer freeing until an RCU
  * grace period has elapsed.
  */
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index 0d9d225..16d4e5a 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -72,6 +72,8 @@
 	uint32_t pid;
 };
 
+struct nlm_wait;
+
 /*
  * Memory chunk for NLM client RPC request.
  */
@@ -81,6 +83,7 @@
 	struct nlm_host *	a_host;		/* host handle */
 	struct nlm_args		a_args;		/* arguments */
 	struct nlm_res		a_res;		/* result */
+	struct nlm_wait *	a_block;
 	char			a_owner[NLMCLNT_OHSIZE];
 };
 
@@ -142,7 +145,9 @@
  * Lockd client functions
  */
 struct nlm_rqst * nlmclnt_alloc_call(void);
-int		  nlmclnt_block(struct nlm_host *, struct file_lock *, u32 *);
+int		  nlmclnt_prepare_block(struct nlm_rqst *req, struct nlm_host *host, struct file_lock *fl);
+void		  nlmclnt_finish_block(struct nlm_rqst *req);
+long		  nlmclnt_block(struct nlm_rqst *req, long timeout);
 int		  nlmclnt_cancel(struct nlm_host *, struct file_lock *);
 u32		  nlmclnt_grant(struct nlm_lock *);
 void		  nlmclnt_recovery(struct nlm_host *, u32);
diff --git a/include/linux/loop.h b/include/linux/loop.h
index 8220d9c..53fa515 100644
--- a/include/linux/loop.h
+++ b/include/linux/loop.h
@@ -61,7 +61,7 @@
 	struct semaphore	lo_sem;
 	struct semaphore	lo_ctl_mutex;
 	struct semaphore	lo_bh_mutex;
-	atomic_t		lo_pending;
+	int			lo_pending;
 
 	request_queue_t		*lo_queue;
 };
diff --git a/include/linux/major.h b/include/linux/major.h
index 4b62c42..e36a467 100644
--- a/include/linux/major.h
+++ b/include/linux/major.h
@@ -100,6 +100,7 @@
 #define I2O_MAJOR		80	/* 80->87 */
 
 #define SHMIQ_MAJOR		85   /* Linux/mips, SGI /dev/shmiq */
+#define SCSI_CHANGER_MAJOR      86
 
 #define IDE6_MAJOR		88
 #define IDE7_MAJOR		89
diff --git a/include/linux/mempool.h b/include/linux/mempool.h
index 4a36edf..796220ce 100644
--- a/include/linux/mempool.h
+++ b/include/linux/mempool.h
@@ -20,9 +20,14 @@
 	mempool_free_t *free;
 	wait_queue_head_t wait;
 } mempool_t;
-extern mempool_t * mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
-				 mempool_free_t *free_fn, void *pool_data);
-extern int mempool_resize(mempool_t *pool, int new_min_nr, unsigned int __nocast gfp_mask);
+
+extern mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
+			mempool_free_t *free_fn, void *pool_data);
+extern mempool_t *mempool_create_node(int min_nr, mempool_alloc_t *alloc_fn,
+			mempool_free_t *free_fn, void *pool_data, int nid);
+
+extern int mempool_resize(mempool_t *pool, int new_min_nr,
+			unsigned int __nocast gfp_mask);
 extern void mempool_destroy(mempool_t *pool);
 extern void * mempool_alloc(mempool_t *pool, unsigned int __nocast gfp_mask);
 extern void mempool_free(void *element, mempool_t *pool);
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 17518fe..6eb7f48 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -395,19 +395,81 @@
 /*
  * The zone field is never updated after free_area_init_core()
  * sets it, so none of the operations on it need to be atomic.
- * We'll have up to (MAX_NUMNODES * MAX_NR_ZONES) zones total,
- * so we use (MAX_NODES_SHIFT + MAX_ZONES_SHIFT) here to get enough bits.
  */
-#define NODEZONE_SHIFT (sizeof(page_flags_t)*8 - MAX_NODES_SHIFT - MAX_ZONES_SHIFT)
-#define NODEZONE(node, zone)	((node << ZONES_SHIFT) | zone)
+
+
+/*
+ * page->flags layout:
+ *
+ * There are three possibilities for how page->flags get
+ * laid out.  The first is for the normal case, without
+ * sparsemem.  The second is for sparsemem when there is
+ * plenty of space for node and section.  The last is when
+ * we have run out of space and have to fall back to an
+ * alternate (slower) way of determining the node.
+ *
+ *        No sparsemem: |       NODE     | ZONE | ... | FLAGS |
+ * with space for node: | SECTION | NODE | ZONE | ... | FLAGS |
+ *   no space for node: | SECTION |     ZONE    | ... | FLAGS |
+ */
+#ifdef CONFIG_SPARSEMEM
+#define SECTIONS_WIDTH		SECTIONS_SHIFT
+#else
+#define SECTIONS_WIDTH		0
+#endif
+
+#define ZONES_WIDTH		ZONES_SHIFT
+
+#if SECTIONS_WIDTH+ZONES_WIDTH+NODES_SHIFT <= FLAGS_RESERVED
+#define NODES_WIDTH		NODES_SHIFT
+#else
+#define NODES_WIDTH		0
+#endif
+
+/* Page flags: | [SECTION] | [NODE] | ZONE | ... | FLAGS | */
+#define SECTIONS_PGOFF		((sizeof(page_flags_t)*8) - SECTIONS_WIDTH)
+#define NODES_PGOFF		(SECTIONS_PGOFF - NODES_WIDTH)
+#define ZONES_PGOFF		(NODES_PGOFF - ZONES_WIDTH)
+
+/*
+ * We are going to use the flags for the page to node mapping if its in
+ * there.  This includes the case where there is no node, so it is implicit.
+ */
+#define FLAGS_HAS_NODE		(NODES_WIDTH > 0 || NODES_SHIFT == 0)
+
+#ifndef PFN_SECTION_SHIFT
+#define PFN_SECTION_SHIFT 0
+#endif
+
+/*
+ * Define the bit shifts to access each section.  For non-existant
+ * sections we define the shift as 0; that plus a 0 mask ensures
+ * the compiler will optimise away reference to them.
+ */
+#define SECTIONS_PGSHIFT	(SECTIONS_PGOFF * (SECTIONS_WIDTH != 0))
+#define NODES_PGSHIFT		(NODES_PGOFF * (NODES_WIDTH != 0))
+#define ZONES_PGSHIFT		(ZONES_PGOFF * (ZONES_WIDTH != 0))
+
+/* NODE:ZONE or SECTION:ZONE is used to lookup the zone from a page. */
+#if FLAGS_HAS_NODE
+#define ZONETABLE_SHIFT		(NODES_SHIFT + ZONES_SHIFT)
+#else
+#define ZONETABLE_SHIFT		(SECTIONS_SHIFT + ZONES_SHIFT)
+#endif
+#define ZONETABLE_PGSHIFT	ZONES_PGSHIFT
+
+#if SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > FLAGS_RESERVED
+#error SECTIONS_WIDTH+NODES_WIDTH+ZONES_WIDTH > FLAGS_RESERVED
+#endif
+
+#define ZONES_MASK		((1UL << ZONES_WIDTH) - 1)
+#define NODES_MASK		((1UL << NODES_WIDTH) - 1)
+#define SECTIONS_MASK		((1UL << SECTIONS_WIDTH) - 1)
+#define ZONETABLE_MASK		((1UL << ZONETABLE_SHIFT) - 1)
 
 static inline unsigned long page_zonenum(struct page *page)
 {
-	return (page->flags >> NODEZONE_SHIFT) & (~(~0UL << ZONES_SHIFT));
-}
-static inline unsigned long page_to_nid(struct page *page)
-{
-	return (page->flags >> (NODEZONE_SHIFT + ZONES_SHIFT));
+	return (page->flags >> ZONES_PGSHIFT) & ZONES_MASK;
 }
 
 struct zone;
@@ -415,13 +477,44 @@
 
 static inline struct zone *page_zone(struct page *page)
 {
-	return zone_table[page->flags >> NODEZONE_SHIFT];
+	return zone_table[(page->flags >> ZONETABLE_PGSHIFT) &
+			ZONETABLE_MASK];
 }
 
-static inline void set_page_zone(struct page *page, unsigned long nodezone_num)
+static inline unsigned long page_to_nid(struct page *page)
 {
-	page->flags &= ~(~0UL << NODEZONE_SHIFT);
-	page->flags |= nodezone_num << NODEZONE_SHIFT;
+	if (FLAGS_HAS_NODE)
+		return (page->flags >> NODES_PGSHIFT) & NODES_MASK;
+	else
+		return page_zone(page)->zone_pgdat->node_id;
+}
+static inline unsigned long page_to_section(struct page *page)
+{
+	return (page->flags >> SECTIONS_PGSHIFT) & SECTIONS_MASK;
+}
+
+static inline void set_page_zone(struct page *page, unsigned long zone)
+{
+	page->flags &= ~(ZONES_MASK << ZONES_PGSHIFT);
+	page->flags |= (zone & ZONES_MASK) << ZONES_PGSHIFT;
+}
+static inline void set_page_node(struct page *page, unsigned long node)
+{
+	page->flags &= ~(NODES_MASK << NODES_PGSHIFT);
+	page->flags |= (node & NODES_MASK) << NODES_PGSHIFT;
+}
+static inline void set_page_section(struct page *page, unsigned long section)
+{
+	page->flags &= ~(SECTIONS_MASK << SECTIONS_PGSHIFT);
+	page->flags |= (section & SECTIONS_MASK) << SECTIONS_PGSHIFT;
+}
+
+static inline void set_page_links(struct page *page, unsigned long zone,
+	unsigned long node, unsigned long pfn)
+{
+	set_page_zone(page, zone);
+	set_page_node(page, node);
+	set_page_section(page, pfn_to_section_nr(pfn));
 }
 
 #ifndef CONFIG_DISCONTIGMEM
@@ -691,6 +784,12 @@
 extern void si_meminfo(struct sysinfo * val);
 extern void si_meminfo_node(struct sysinfo *val, int nid);
 
+#ifdef CONFIG_NUMA
+extern void setup_per_cpu_pageset(void);
+#else
+static inline void setup_per_cpu_pageset(void) {}
+#endif
+
 /* prio_tree.c */
 void vma_prio_tree_add(struct vm_area_struct *, struct vm_area_struct *old);
 void vma_prio_tree_insert(struct vm_area_struct *, struct prio_tree_root *);
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index e530c6c..6c90461 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -63,6 +63,12 @@
 #endif
 } ____cacheline_aligned_in_smp;
 
+#ifdef CONFIG_NUMA
+#define zone_pcp(__z, __cpu) ((__z)->pageset[(__cpu)])
+#else
+#define zone_pcp(__z, __cpu) (&(__z)->pageset[(__cpu)])
+#endif
+
 #define ZONE_DMA		0
 #define ZONE_NORMAL		1
 #define ZONE_HIGHMEM		2
@@ -122,8 +128,11 @@
 	 */
 	unsigned long		lowmem_reserve[MAX_NR_ZONES];
 
+#ifdef CONFIG_NUMA
+	struct per_cpu_pageset	*pageset[NR_CPUS];
+#else
 	struct per_cpu_pageset	pageset[NR_CPUS];
-
+#endif
 	/*
 	 * free areas of different sizes
 	 */
@@ -145,6 +154,14 @@
 	int			all_unreclaimable; /* All pages pinned */
 
 	/*
+	 * Does the allocator try to reclaim pages from the zone as soon
+	 * as it fails a watermark_ok() in __alloc_pages?
+	 */
+	int			reclaim_pages;
+	/* A count of how many reclaimers are scanning this zone */
+	atomic_t		reclaim_in_progress;
+
+	/*
 	 * prev_priority holds the scanning priority for this zone.  It is
 	 * defined as the scanning priority at which we achieved our reclaim
 	 * target at the previous try_to_free_pages() or balance_pgdat()
@@ -252,7 +269,9 @@
 	struct zone node_zones[MAX_NR_ZONES];
 	struct zonelist node_zonelists[GFP_ZONETYPES];
 	int nr_zones;
+#ifdef CONFIG_FLAT_NODE_MEM_MAP
 	struct page *node_mem_map;
+#endif
 	struct bootmem_data *bdata;
 	unsigned long node_start_pfn;
 	unsigned long node_present_pages; /* total number of physical pages */
@@ -267,6 +286,12 @@
 
 #define node_present_pages(nid)	(NODE_DATA(nid)->node_present_pages)
 #define node_spanned_pages(nid)	(NODE_DATA(nid)->node_spanned_pages)
+#ifdef CONFIG_FLAT_NODE_MEM_MAP
+#define pgdat_page_nr(pgdat, pagenr)	((pgdat)->node_mem_map + (pagenr))
+#else
+#define pgdat_page_nr(pgdat, pagenr)	pfn_to_page((pgdat)->node_start_pfn + (pagenr))
+#endif
+#define nid_page_nr(nid, pagenr) 	pgdat_page_nr(NODE_DATA(nid),(pagenr))
 
 extern struct pglist_data *pgdat_list;
 
@@ -381,9 +406,9 @@
 
 #include <linux/topology.h>
 /* Returns the number of the current Node. */
-#define numa_node_id()		(cpu_to_node(_smp_processor_id()))
+#define numa_node_id()		(cpu_to_node(raw_smp_processor_id()))
 
-#ifndef CONFIG_DISCONTIGMEM
+#ifndef CONFIG_NEED_MULTIPLE_NODES
 
 extern struct pglist_data contig_page_data;
 #define NODE_DATA(nid)		(&contig_page_data)
@@ -391,36 +416,177 @@
 #define MAX_NODES_SHIFT		1
 #define pfn_to_nid(pfn)		(0)
 
-#else /* CONFIG_DISCONTIGMEM */
+#else /* CONFIG_NEED_MULTIPLE_NODES */
 
 #include <asm/mmzone.h>
 
+#endif /* !CONFIG_NEED_MULTIPLE_NODES */
+
+#ifdef CONFIG_SPARSEMEM
+#include <asm/sparsemem.h>
+#endif
+
 #if BITS_PER_LONG == 32 || defined(ARCH_HAS_ATOMIC_UNSIGNED)
 /*
  * with 32 bit page->flags field, we reserve 8 bits for node/zone info.
  * there are 3 zones (2 bits) and this leaves 8-2=6 bits for nodes.
  */
-#define MAX_NODES_SHIFT		6
+#define FLAGS_RESERVED		8
+
 #elif BITS_PER_LONG == 64
 /*
  * with 64 bit flags field, there's plenty of room.
  */
-#define MAX_NODES_SHIFT		10
+#define FLAGS_RESERVED		32
+
+#else
+
+#error BITS_PER_LONG not defined
+
 #endif
 
-#endif /* !CONFIG_DISCONTIGMEM */
-
-#if NODES_SHIFT > MAX_NODES_SHIFT
-#error NODES_SHIFT > MAX_NODES_SHIFT
+#ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
+#define early_pfn_to_nid(nid)  (0UL)
 #endif
 
-/* There are currently 3 zones: DMA, Normal & Highmem, thus we need 2 bits */
-#define MAX_ZONES_SHIFT		2
+#define pfn_to_section_nr(pfn) ((pfn) >> PFN_SECTION_SHIFT)
+#define section_nr_to_pfn(sec) ((sec) << PFN_SECTION_SHIFT)
 
-#if ZONES_SHIFT > MAX_ZONES_SHIFT
-#error ZONES_SHIFT > MAX_ZONES_SHIFT
+#ifdef CONFIG_SPARSEMEM
+
+/*
+ * SECTION_SHIFT    		#bits space required to store a section #
+ *
+ * PA_SECTION_SHIFT		physical address to/from section number
+ * PFN_SECTION_SHIFT		pfn to/from section number
+ */
+#define SECTIONS_SHIFT		(MAX_PHYSMEM_BITS - SECTION_SIZE_BITS)
+
+#define PA_SECTION_SHIFT	(SECTION_SIZE_BITS)
+#define PFN_SECTION_SHIFT	(SECTION_SIZE_BITS - PAGE_SHIFT)
+
+#define NR_MEM_SECTIONS		(1UL << SECTIONS_SHIFT)
+
+#define PAGES_PER_SECTION       (1UL << PFN_SECTION_SHIFT)
+#define PAGE_SECTION_MASK	(~(PAGES_PER_SECTION-1))
+
+#if (MAX_ORDER - 1 + PAGE_SHIFT) > SECTION_SIZE_BITS
+#error Allocator MAX_ORDER exceeds SECTION_SIZE
 #endif
 
+struct page;
+struct mem_section {
+	/*
+	 * This is, logically, a pointer to an array of struct
+	 * pages.  However, it is stored with some other magic.
+	 * (see sparse.c::sparse_init_one_section())
+	 *
+	 * Making it a UL at least makes someone do a cast
+	 * before using it wrong.
+	 */
+	unsigned long section_mem_map;
+};
+
+extern struct mem_section mem_section[NR_MEM_SECTIONS];
+
+static inline struct mem_section *__nr_to_section(unsigned long nr)
+{
+	return &mem_section[nr];
+}
+
+/*
+ * We use the lower bits of the mem_map pointer to store
+ * a little bit of information.  There should be at least
+ * 3 bits here due to 32-bit alignment.
+ */
+#define	SECTION_MARKED_PRESENT	(1UL<<0)
+#define SECTION_HAS_MEM_MAP	(1UL<<1)
+#define SECTION_MAP_LAST_BIT	(1UL<<2)
+#define SECTION_MAP_MASK	(~(SECTION_MAP_LAST_BIT-1))
+
+static inline struct page *__section_mem_map_addr(struct mem_section *section)
+{
+	unsigned long map = section->section_mem_map;
+	map &= SECTION_MAP_MASK;
+	return (struct page *)map;
+}
+
+static inline int valid_section(struct mem_section *section)
+{
+	return (section->section_mem_map & SECTION_MARKED_PRESENT);
+}
+
+static inline int section_has_mem_map(struct mem_section *section)
+{
+	return (section->section_mem_map & SECTION_HAS_MEM_MAP);
+}
+
+static inline int valid_section_nr(unsigned long nr)
+{
+	return valid_section(__nr_to_section(nr));
+}
+
+/*
+ * Given a kernel address, find the home node of the underlying memory.
+ */
+#define kvaddr_to_nid(kaddr)	pfn_to_nid(__pa(kaddr) >> PAGE_SHIFT)
+
+static inline struct mem_section *__pfn_to_section(unsigned long pfn)
+{
+	return __nr_to_section(pfn_to_section_nr(pfn));
+}
+
+#define pfn_to_page(pfn) 						\
+({ 									\
+	unsigned long __pfn = (pfn);					\
+	__section_mem_map_addr(__pfn_to_section(__pfn)) + __pfn;	\
+})
+#define page_to_pfn(page)						\
+({									\
+	page - __section_mem_map_addr(__nr_to_section(			\
+		page_to_section(page)));				\
+})
+
+static inline int pfn_valid(unsigned long pfn)
+{
+	if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS)
+		return 0;
+	return valid_section(__nr_to_section(pfn_to_section_nr(pfn)));
+}
+
+/*
+ * These are _only_ used during initialisation, therefore they
+ * can use __initdata ...  They could have names to indicate
+ * this restriction.
+ */
+#ifdef CONFIG_NUMA
+#define pfn_to_nid		early_pfn_to_nid
+#endif
+
+#define pfn_to_pgdat(pfn)						\
+({									\
+	NODE_DATA(pfn_to_nid(pfn));					\
+})
+
+#define early_pfn_valid(pfn)	pfn_valid(pfn)
+void sparse_init(void);
+#else
+#define sparse_init()	do {} while (0)
+#endif /* CONFIG_SPARSEMEM */
+
+#ifdef CONFIG_NODES_SPAN_OTHER_NODES
+#define early_pfn_in_nid(pfn, nid)	(early_pfn_to_nid(pfn) == (nid))
+#else
+#define early_pfn_in_nid(pfn, nid)	(1)
+#endif
+
+#ifndef early_pfn_valid
+#define early_pfn_valid(pfn)	(1)
+#endif
+
+void memory_present(int nid, unsigned long start, unsigned long end);
+unsigned long __init node_memmap_size_bytes(int, unsigned long, unsigned long);
+
 #endif /* !__ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _LINUX_MMZONE_H */
diff --git a/include/linux/module.h b/include/linux/module.h
index 0e432a0..f05372b 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -51,6 +51,9 @@
         ssize_t (*show)(struct module_attribute *, struct module *, char *);
         ssize_t (*store)(struct module_attribute *, struct module *,
 			 const char *, size_t count);
+	void (*setup)(struct module *, const char *);
+	int (*test)(struct module *);
+	void (*free)(struct module *);
 };
 
 struct module_kobject
@@ -239,6 +242,8 @@
 	/* Sysfs stuff. */
 	struct module_kobject mkobj;
 	struct module_param_attrs *param_attrs;
+	const char *version;
+	const char *srcversion;
 
 	/* Exported symbols */
 	const struct kernel_symbol *syms;
diff --git a/include/linux/namespace.h b/include/linux/namespace.h
index 9eca155..697991b 100644
--- a/include/linux/namespace.h
+++ b/include/linux/namespace.h
@@ -12,7 +12,6 @@
 	struct rw_semaphore	sem;
 };
 
-extern void umount_tree(struct vfsmount *);
 extern int copy_namespace(int, struct task_struct *);
 extern void __put_namespace(struct namespace *namespace);
 
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index ba5d123..3a0ed7f 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -41,7 +41,7 @@
 struct divert_blk;
 struct vlan_group;
 struct ethtool_ops;
-struct netpoll;
+struct netpoll_info;
 					/* source back-compat hooks */
 #define SET_ETHTOOL_OPS(netdev,ops) \
 	( (netdev)->ethtool_ops = (ops) )
@@ -164,12 +164,6 @@
 	unsigned total;
 	unsigned dropped;
 	unsigned time_squeeze;
-	unsigned throttled;
-	unsigned fastroute_hit;
-	unsigned fastroute_success;
-	unsigned fastroute_defer;
-	unsigned fastroute_deferred_out;
-	unsigned fastroute_latency_reduction;
 	unsigned cpu_collision;
 };
 
@@ -468,7 +462,7 @@
 						     unsigned char *haddr);
 	int			(*neigh_setup)(struct net_device *dev, struct neigh_parms *);
 #ifdef CONFIG_NETPOLL
-	struct netpoll		*np;
+	struct netpoll_info	*npinfo;
 #endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	void                    (*poll_controller)(struct net_device *dev);
@@ -562,12 +556,9 @@
 
 struct softnet_data
 {
-	int			throttle;
-	int			cng_level;
-	int			avg_blog;
+	struct net_device	*output_queue;
 	struct sk_buff_head	input_pkt_queue;
 	struct list_head	poll_list;
-	struct net_device	*output_queue;
 	struct sk_buff		*completion_queue;
 
 	struct net_device	backlog_dev;	/* Sorry. 8) */
@@ -925,10 +916,6 @@
 extern void		net_enable_timestamp(void);
 extern void		net_disable_timestamp(void);
 
-#ifdef CONFIG_SYSCTL
-extern char *net_sysctl_strdup(const char *s);
-#endif
-
 #endif /* __KERNEL__ */
 
 #endif	/* _LINUX_DEV_H */
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
index 9e57500..3ebc36a 100644
--- a/include/linux/netfilter_ipv4.h
+++ b/include/linux/netfilter_ipv4.h
@@ -75,12 +75,6 @@
 #define SO_ORIGINAL_DST 80
 
 #ifdef __KERNEL__
-#ifdef CONFIG_NETFILTER_DEBUG
-void nf_debug_ip_local_deliver(struct sk_buff *skb);
-void nf_debug_ip_loopback_xmit(struct sk_buff *newskb);
-void nf_debug_ip_finish_output2(struct sk_buff *skb);
-#endif /*CONFIG_NETFILTER_DEBUG*/
-
 extern int ip_route_me_harder(struct sk_buff **pskb);
 
 /* Call this before modifying an existing IP packet: ensures it is
diff --git a/include/linux/netfilter_ipv4/ip_conntrack_core.h b/include/linux/netfilter_ipv4/ip_conntrack_core.h
index d84be02..694aec9 100644
--- a/include/linux/netfilter_ipv4/ip_conntrack_core.h
+++ b/include/linux/netfilter_ipv4/ip_conntrack_core.h
@@ -1,7 +1,6 @@
 #ifndef _IP_CONNTRACK_CORE_H
 #define _IP_CONNTRACK_CORE_H
 #include <linux/netfilter.h>
-#include <linux/netfilter_ipv4/lockhelp.h>
 
 /* This header is used to share core functionality between the
    standalone connection tracking module, and the compatibility layer's use
@@ -47,6 +46,6 @@
 
 extern struct list_head *ip_conntrack_hash;
 extern struct list_head ip_conntrack_expect_list;
-DECLARE_RWLOCK_EXTERN(ip_conntrack_lock);
+extern rwlock_t ip_conntrack_lock;
 #endif /* _IP_CONNTRACK_CORE_H */
 
diff --git a/include/linux/netfilter_ipv4/ip_nat.h b/include/linux/netfilter_ipv4/ip_nat.h
index 2b72b86..e201ec6 100644
--- a/include/linux/netfilter_ipv4/ip_nat.h
+++ b/include/linux/netfilter_ipv4/ip_nat.h
@@ -50,10 +50,9 @@
 
 #ifdef __KERNEL__
 #include <linux/list.h>
-#include <linux/netfilter_ipv4/lockhelp.h>
 
 /* Protects NAT hash tables, and NAT-private part of conntracks. */
-DECLARE_RWLOCK_EXTERN(ip_nat_lock);
+extern rwlock_t ip_nat_lock;
 
 /* The structure embedded in the conntrack structure. */
 struct ip_nat_info
diff --git a/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h b/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h
index baa83e7..d9bceed 100644
--- a/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h
+++ b/include/linux/netfilter_ipv4/ipt_CLUSTERIP.h
@@ -18,7 +18,6 @@
 struct ipt_clusterip_tgt_info {
 
 	u_int32_t flags;
-	struct clusterip_config *config;
 	
 	/* only relevant for new ones */
 	u_int8_t clustermac[6];
@@ -27,6 +26,8 @@
 	u_int16_t local_nodes[CLUSTERIP_MAX_NODES];
 	enum clusterip_hashmode hash_mode;
 	u_int32_t hash_initval;
+
+	struct clusterip_config *config;
 };
 
 #endif /*_IPT_CLUSTERIP_H_target*/
diff --git a/include/linux/netfilter_ipv4/listhelp.h b/include/linux/netfilter_ipv4/listhelp.h
index f2ae7c5..360429f 100644
--- a/include/linux/netfilter_ipv4/listhelp.h
+++ b/include/linux/netfilter_ipv4/listhelp.h
@@ -2,7 +2,6 @@
 #define _LISTHELP_H
 #include <linux/config.h>
 #include <linux/list.h>
-#include <linux/netfilter_ipv4/lockhelp.h>
 
 /* Header to do more comprehensive job than linux/list.h; assume list
    is first entry in structure. */
diff --git a/include/linux/netfilter_ipv4/lockhelp.h b/include/linux/netfilter_ipv4/lockhelp.h
deleted file mode 100644
index a328863..0000000
--- a/include/linux/netfilter_ipv4/lockhelp.h
+++ /dev/null
@@ -1,129 +0,0 @@
-#ifndef _LOCKHELP_H
-#define _LOCKHELP_H
-#include <linux/config.h>
-
-#include <linux/spinlock.h>
-#include <asm/atomic.h>
-#include <linux/interrupt.h>
-#include <linux/smp.h>
-
-/* Header to do help in lock debugging. */
-
-#ifdef CONFIG_NETFILTER_DEBUG
-struct spinlock_debug
-{
-	spinlock_t l;
-	atomic_t locked_by;
-};
-
-struct rwlock_debug
-{
-	rwlock_t l;
-	long read_locked_map;
-	long write_locked_map;
-};
-
-#define DECLARE_LOCK(l) 						\
-struct spinlock_debug l = { SPIN_LOCK_UNLOCKED, ATOMIC_INIT(-1) }
-#define DECLARE_LOCK_EXTERN(l) 			\
-extern struct spinlock_debug l
-#define DECLARE_RWLOCK(l)				\
-struct rwlock_debug l = { RW_LOCK_UNLOCKED, 0, 0 }
-#define DECLARE_RWLOCK_EXTERN(l)		\
-extern struct rwlock_debug l
-
-#define MUST_BE_LOCKED(l)						\
-do { if (atomic_read(&(l)->locked_by) != smp_processor_id())		\
-	printk("ASSERT %s:%u %s unlocked\n", __FILE__, __LINE__, #l);	\
-} while(0)
-
-#define MUST_BE_UNLOCKED(l)						\
-do { if (atomic_read(&(l)->locked_by) == smp_processor_id())		\
-	printk("ASSERT %s:%u %s locked\n", __FILE__, __LINE__, #l);	\
-} while(0)
-
-/* Write locked OK as well. */
-#define MUST_BE_READ_LOCKED(l)						    \
-do { if (!((l)->read_locked_map & (1UL << smp_processor_id()))		    \
-	 && !((l)->write_locked_map & (1UL << smp_processor_id())))	    \
-	printk("ASSERT %s:%u %s not readlocked\n", __FILE__, __LINE__, #l); \
-} while(0)
-
-#define MUST_BE_WRITE_LOCKED(l)						     \
-do { if (!((l)->write_locked_map & (1UL << smp_processor_id())))	     \
-	printk("ASSERT %s:%u %s not writelocked\n", __FILE__, __LINE__, #l); \
-} while(0)
-
-#define MUST_BE_READ_WRITE_UNLOCKED(l)					  \
-do { if ((l)->read_locked_map & (1UL << smp_processor_id()))		  \
-	printk("ASSERT %s:%u %s readlocked\n", __FILE__, __LINE__, #l);	  \
- else if ((l)->write_locked_map & (1UL << smp_processor_id()))		  \
-	 printk("ASSERT %s:%u %s writelocked\n", __FILE__, __LINE__, #l); \
-} while(0)
-
-#define LOCK_BH(lk)						\
-do {								\
-	MUST_BE_UNLOCKED(lk);					\
-	spin_lock_bh(&(lk)->l);					\
-	atomic_set(&(lk)->locked_by, smp_processor_id());	\
-} while(0)
-
-#define UNLOCK_BH(lk)				\
-do {						\
-	MUST_BE_LOCKED(lk);			\
-	atomic_set(&(lk)->locked_by, -1);	\
-	spin_unlock_bh(&(lk)->l);		\
-} while(0)
-
-#define READ_LOCK(lk) 						\
-do {								\
-	MUST_BE_READ_WRITE_UNLOCKED(lk);			\
-	read_lock_bh(&(lk)->l);					\
-	set_bit(smp_processor_id(), &(lk)->read_locked_map);	\
-} while(0)
-
-#define WRITE_LOCK(lk)							  \
-do {									  \
-	MUST_BE_READ_WRITE_UNLOCKED(lk);				  \
-	write_lock_bh(&(lk)->l);					  \
-	set_bit(smp_processor_id(), &(lk)->write_locked_map);		  \
-} while(0)
-
-#define READ_UNLOCK(lk)							\
-do {									\
-	if (!((lk)->read_locked_map & (1UL << smp_processor_id())))	\
-		printk("ASSERT: %s:%u %s not readlocked\n", 		\
-		       __FILE__, __LINE__, #lk);			\
-	clear_bit(smp_processor_id(), &(lk)->read_locked_map);		\
-	read_unlock_bh(&(lk)->l);					\
-} while(0)
-
-#define WRITE_UNLOCK(lk)					\
-do {								\
-	MUST_BE_WRITE_LOCKED(lk);				\
-	clear_bit(smp_processor_id(), &(lk)->write_locked_map);	\
-	write_unlock_bh(&(lk)->l);				\
-} while(0)
-
-#else
-#define DECLARE_LOCK(l) spinlock_t l = SPIN_LOCK_UNLOCKED
-#define DECLARE_LOCK_EXTERN(l) extern spinlock_t l
-#define DECLARE_RWLOCK(l) rwlock_t l = RW_LOCK_UNLOCKED
-#define DECLARE_RWLOCK_EXTERN(l) extern rwlock_t l
-
-#define MUST_BE_LOCKED(l)
-#define MUST_BE_UNLOCKED(l)
-#define MUST_BE_READ_LOCKED(l)
-#define MUST_BE_WRITE_LOCKED(l)
-#define MUST_BE_READ_WRITE_UNLOCKED(l)
-
-#define LOCK_BH(l) spin_lock_bh(l)
-#define UNLOCK_BH(l) spin_unlock_bh(l)
-
-#define READ_LOCK(l) read_lock_bh(l)
-#define WRITE_LOCK(l) write_lock_bh(l)
-#define READ_UNLOCK(l) read_unlock_bh(l)
-#define WRITE_UNLOCK(l) write_unlock_bh(l)
-#endif /*CONFIG_NETFILTER_DEBUG*/
-
-#endif /* _LOCKHELP_H */
diff --git a/include/linux/netlink.h b/include/linux/netlink.h
index b2738ac..3029cad 100644
--- a/include/linux/netlink.h
+++ b/include/linux/netlink.h
@@ -14,6 +14,7 @@
 #define NETLINK_SELINUX		7	/* SELinux event notifications */
 #define NETLINK_ARPD		8
 #define NETLINK_AUDIT		9	/* auditing */
+#define NETLINK_FIB_LOOKUP	10	
 #define NETLINK_ROUTE6		11	/* af_inet6 route comm channel */
 #define NETLINK_IP6_FW		13
 #define NETLINK_DNRTMSG		14	/* DECnet routing messages */
@@ -146,7 +147,7 @@
 	int		(*dump)(struct sk_buff * skb, struct netlink_callback *cb);
 	int		(*done)(struct netlink_callback *cb);
 	int		family;
-	long		args[4];
+	long		args[5];
 };
 
 struct netlink_notify
@@ -156,7 +157,7 @@
 };
 
 static __inline__ struct nlmsghdr *
-__nlmsg_put(struct sk_buff *skb, u32 pid, u32 seq, int type, int len)
+__nlmsg_put(struct sk_buff *skb, u32 pid, u32 seq, int type, int len, int flags)
 {
 	struct nlmsghdr *nlh;
 	int size = NLMSG_LENGTH(len);
@@ -164,15 +165,31 @@
 	nlh = (struct nlmsghdr*)skb_put(skb, NLMSG_ALIGN(size));
 	nlh->nlmsg_type = type;
 	nlh->nlmsg_len = size;
-	nlh->nlmsg_flags = 0;
+	nlh->nlmsg_flags = flags;
 	nlh->nlmsg_pid = pid;
 	nlh->nlmsg_seq = seq;
 	return nlh;
 }
 
+#define NLMSG_NEW(skb, pid, seq, type, len, flags) \
+({	if (skb_tailroom(skb) < (int)NLMSG_SPACE(len)) \
+		goto nlmsg_failure; \
+	__nlmsg_put(skb, pid, seq, type, len, flags); })
+
 #define NLMSG_PUT(skb, pid, seq, type, len) \
-({ if (skb_tailroom(skb) < (int)NLMSG_SPACE(len)) goto nlmsg_failure; \
-   __nlmsg_put(skb, pid, seq, type, len); })
+	NLMSG_NEW(skb, pid, seq, type, len, 0)
+
+#define NLMSG_NEW_ANSWER(skb, cb, type, len, flags) \
+	NLMSG_NEW(skb, NETLINK_CB((cb)->skb).pid, \
+		  (cb)->nlh->nlmsg_seq, type, len, flags)
+
+#define NLMSG_END(skb, nlh) \
+({	(nlh)->nlmsg_len = (skb)->tail - (unsigned char *) (nlh); \
+	(skb)->len; })
+
+#define NLMSG_CANCEL(skb, nlh) \
+({	skb_trim(skb, (unsigned char *) (nlh) - (skb)->data); \
+	-1; })
 
 extern int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
 			      struct nlmsghdr *nlh,
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h
index c0d8b90..bcd0ac3 100644
--- a/include/linux/netpoll.h
+++ b/include/linux/netpoll.h
@@ -16,14 +16,19 @@
 struct netpoll {
 	struct net_device *dev;
 	char dev_name[16], *name;
-	int rx_flags;
 	void (*rx_hook)(struct netpoll *, int, char *, int);
 	void (*drop)(struct sk_buff *skb);
 	u32 local_ip, remote_ip;
 	u16 local_port, remote_port;
 	unsigned char local_mac[6], remote_mac[6];
+};
+
+struct netpoll_info {
 	spinlock_t poll_lock;
 	int poll_owner;
+	int rx_flags;
+	spinlock_t rx_lock;
+	struct netpoll *rx_np; /* netpoll that registered an rx_hook */
 };
 
 void netpoll_poll(struct netpoll *np);
@@ -39,22 +44,35 @@
 #ifdef CONFIG_NETPOLL
 static inline int netpoll_rx(struct sk_buff *skb)
 {
-	return skb->dev->np && skb->dev->np->rx_flags && __netpoll_rx(skb);
+	struct netpoll_info *npinfo = skb->dev->npinfo;
+	unsigned long flags;
+	int ret = 0;
+
+	if (!npinfo || (!npinfo->rx_np && !npinfo->rx_flags))
+		return 0;
+
+	spin_lock_irqsave(&npinfo->rx_lock, flags);
+	/* check rx_flags again with the lock held */
+	if (npinfo->rx_flags && __netpoll_rx(skb))
+		ret = 1;
+	spin_unlock_irqrestore(&npinfo->rx_lock, flags);
+
+	return ret;
 }
 
 static inline void netpoll_poll_lock(struct net_device *dev)
 {
-	if (dev->np) {
-		spin_lock(&dev->np->poll_lock);
-		dev->np->poll_owner = smp_processor_id();
+	if (dev->npinfo) {
+		spin_lock(&dev->npinfo->poll_lock);
+		dev->npinfo->poll_owner = smp_processor_id();
 	}
 }
 
 static inline void netpoll_poll_unlock(struct net_device *dev)
 {
-	if (dev->np) {
-		spin_unlock(&dev->np->poll_lock);
-		dev->np->poll_owner = -1;
+	if (dev->npinfo) {
+		dev->npinfo->poll_owner = -1;
+		spin_unlock(&dev->npinfo->poll_lock);
 	}
 }
 
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
index 5ca8a8d..0c1c306 100644
--- a/include/linux/nfs4.h
+++ b/include/linux/nfs4.h
@@ -28,7 +28,7 @@
 #define NFS4_ACCESS_DELETE      0x0010
 #define NFS4_ACCESS_EXECUTE     0x0020
 
-#define NFS4_FH_PERISTENT		0x0000
+#define NFS4_FH_PERSISTENT		0x0000
 #define NFS4_FH_NOEXPIRE_WITH_OPEN	0x0001
 #define NFS4_FH_VOLATILE_ANY		0x0002
 #define NFS4_FH_VOL_MIGRATION		0x0004
@@ -382,6 +382,8 @@
 	NFSPROC4_CLNT_READDIR,
 	NFSPROC4_CLNT_SERVER_CAPS,
 	NFSPROC4_CLNT_DELEGRETURN,
+	NFSPROC4_CLNT_GETACL,
+	NFSPROC4_CLNT_SETACL,
 };
 
 #endif
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index dbac7f3..8ea2491 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -15,7 +15,6 @@
 #include <linux/pagemap.h>
 #include <linux/rwsem.h>
 #include <linux/wait.h>
-#include <linux/uio.h>
 
 #include <linux/nfs_fs_sb.h>
 
@@ -29,7 +28,6 @@
 #include <linux/nfs4.h>
 #include <linux/nfs_xdr.h>
 #include <linux/rwsem.h>
-#include <linux/workqueue.h>
 #include <linux/mempool.h>
 
 /*
@@ -44,13 +42,6 @@
 #define NFS_DEF_FILE_IO_BUFFER_SIZE	4096
 
 /*
- * The upper limit on timeouts for the exponential backoff algorithm.
- */
-#define NFS_WRITEBACK_DELAY		(5*HZ)
-#define NFS_WRITEBACK_LOCKDELAY		(60*HZ)
-#define NFS_COMMIT_DELAY		(5*HZ)
-
-/*
  * superblock magic number for NFS
  */
 #define NFS_SUPER_MAGIC			0x6969
@@ -60,9 +51,6 @@
  */
 #define NFS_RPC_SWAPFLAGS		(RPC_TASK_SWAPPER|RPC_TASK_ROOTCREDS)
 
-#define NFS_RW_SYNC		0x0001	/* O_SYNC handling */
-#define NFS_RW_SWAP		0x0002	/* This is a swap request */
-
 /*
  * When flushing a cluster of dirty pages, there can be different
  * strategies:
@@ -96,7 +84,8 @@
 	int error;
 
 	struct list_head list;
-	wait_queue_head_t waitq;
+
+	__u64 dir_cookie;
 };
 
 /*
@@ -104,6 +93,8 @@
  */
 struct nfs_delegation;
 
+struct posix_acl;
+
 /*
  * nfs fs inode data in memory
  */
@@ -140,7 +131,6 @@
 	 *
 	 *	mtime != read_cache_mtime
 	 */
-	unsigned long		readdir_timestamp;
 	unsigned long		read_cache_jiffies;
 	unsigned long		attrtimeo;
 	unsigned long		attrtimeo_timestamp;
@@ -158,6 +148,10 @@
 	atomic_t		data_updates;
 
 	struct nfs_access_entry	cache_access;
+#ifdef CONFIG_NFS_V3_ACL
+	struct posix_acl	*acl_access;
+	struct posix_acl	*acl_default;
+#endif
 
 	/*
 	 * This is the cookie verifier used for NFSv3 readdir
@@ -183,13 +177,13 @@
 	wait_queue_head_t	nfs_i_wait;
 
 #ifdef CONFIG_NFS_V4
+	struct nfs4_cached_acl	*nfs4_acl;
         /* NFSv4 state */
 	struct list_head	open_states;
 	struct nfs_delegation	*delegation;
 	int			 delegation_state;
 	struct rw_semaphore	rwsem;
 #endif /* CONFIG_NFS_V4*/
-
 	struct inode		vfs_inode;
 };
 
@@ -203,6 +197,8 @@
 #define NFS_INO_INVALID_DATA	0x0010		/* cached data is invalid */
 #define NFS_INO_INVALID_ATIME	0x0020		/* cached atime is invalid */
 #define NFS_INO_INVALID_ACCESS	0x0040		/* cached access cred invalid */
+#define NFS_INO_INVALID_ACL	0x0080		/* cached acls are invalid */
+#define NFS_INO_REVAL_PAGECACHE	0x1000		/* must revalidate pagecache */
 
 static inline struct nfs_inode *NFS_I(struct inode *inode)
 {
@@ -294,12 +290,12 @@
 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_setattr(struct dentry *, struct iattr *);
 extern void nfs_begin_attr_update(struct inode *);
 extern void nfs_end_attr_update(struct inode *);
 extern void nfs_begin_data_update(struct inode *);
 extern void nfs_end_data_update(struct inode *);
-extern void nfs_end_data_update_defer(struct inode *);
 extern struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rpc_cred *cred);
 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);
@@ -314,6 +310,9 @@
  * linux/fs/nfs/file.c
  */
 extern struct inode_operations nfs_file_inode_operations;
+#ifdef CONFIG_NFS_V3
+extern struct inode_operations nfs3_file_inode_operations;
+#endif /* CONFIG_NFS_V3 */
 extern struct file_operations nfs_file_operations;
 extern struct address_space_operations nfs_file_aops;
 
@@ -329,6 +328,22 @@
 }
 
 /*
+ * linux/fs/nfs/xattr.c
+ */
+#ifdef CONFIG_NFS_V3_ACL
+extern ssize_t nfs3_listxattr(struct dentry *, char *, size_t);
+extern ssize_t nfs3_getxattr(struct dentry *, const char *, void *, size_t);
+extern int nfs3_setxattr(struct dentry *, const char *,
+			const void *, size_t, int);
+extern int nfs3_removexattr (struct dentry *, const char *name);
+#else
+# define nfs3_listxattr NULL
+# define nfs3_getxattr NULL
+# define nfs3_setxattr NULL
+# define nfs3_removexattr NULL
+#endif
+
+/*
  * linux/fs/nfs/direct.c
  */
 extern ssize_t nfs_direct_IO(int, struct kiocb *, const struct iovec *, loff_t,
@@ -342,6 +357,9 @@
  * linux/fs/nfs/dir.c
  */
 extern struct inode_operations nfs_dir_inode_operations;
+#ifdef CONFIG_NFS_V3
+extern struct inode_operations nfs3_dir_inode_operations;
+#endif /* CONFIG_NFS_V3 */
 extern struct file_operations nfs_dir_operations;
 extern struct dentry_operations nfs_dentry_operations;
 
@@ -377,10 +395,10 @@
  */
 extern int  nfs_sync_inode(struct inode *, unsigned long, unsigned int, int);
 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
-extern int  nfs_commit_inode(struct inode *, unsigned long, unsigned int, int);
+extern int  nfs_commit_inode(struct inode *, int);
 #else
 static inline int
-nfs_commit_inode(struct inode *inode, unsigned long idx_start, unsigned int npages, int how)
+nfs_commit_inode(struct inode *inode, int how)
 {
 	return 0;
 }
@@ -434,11 +452,6 @@
 	mempool_free(p, nfs_wdata_mempool);
 }
 
-/* Hack for future NFS swap support */
-#ifndef IS_SWAPFILE
-# define IS_SWAPFILE(inode)	(0)
-#endif
-
 /*
  * linux/fs/nfs/read.c
  */
@@ -468,6 +481,29 @@
 extern void  nfs_readdata_release(struct rpc_task *task);
 
 /*
+ * linux/fs/nfs3proc.c
+ */
+#ifdef CONFIG_NFS_V3_ACL
+extern struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type);
+extern int nfs3_proc_setacl(struct inode *inode, int type,
+			    struct posix_acl *acl);
+extern int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode,
+		mode_t mode);
+extern void nfs3_forget_cached_acls(struct inode *inode);
+#else
+static inline int nfs3_proc_set_default_acl(struct inode *dir,
+					    struct inode *inode,
+					    mode_t mode)
+{
+	return 0;
+}
+
+static inline void nfs3_forget_cached_acls(struct inode *inode)
+{
+}
+#endif /* CONFIG_NFS_V3_ACL */
+
+/*
  * linux/fs/mount_clnt.c
  * (Used only by nfsroot module)
  */
@@ -515,230 +551,6 @@
 
 #define NFS_JUKEBOX_RETRY_TIME (5 * HZ)
 
-#ifdef CONFIG_NFS_V4
-
-struct idmap;
-
-/*
- * In a seqid-mutating op, this macro controls which error return
- * values trigger incrementation of the seqid.
- *
- * from rfc 3010:
- * The client MUST monotonically increment the sequence number for the
- * CLOSE, LOCK, LOCKU, OPEN, OPEN_CONFIRM, and OPEN_DOWNGRADE
- * operations.  This is true even in the event that the previous
- * operation that used the sequence number received an error.  The only
- * exception to this rule is if the previous operation received one of
- * the following errors: NFSERR_STALE_CLIENTID, NFSERR_STALE_STATEID,
- * NFSERR_BAD_STATEID, NFSERR_BAD_SEQID, NFSERR_BADXDR,
- * NFSERR_RESOURCE, NFSERR_NOFILEHANDLE.
- *
- */
-#define seqid_mutating_err(err)       \
-(((err) != NFSERR_STALE_CLIENTID) &&  \
- ((err) != NFSERR_STALE_STATEID)  &&  \
- ((err) != NFSERR_BAD_STATEID)    &&  \
- ((err) != NFSERR_BAD_SEQID)      &&  \
- ((err) != NFSERR_BAD_XDR)        &&  \
- ((err) != NFSERR_RESOURCE)       &&  \
- ((err) != NFSERR_NOFILEHANDLE))
-
-enum nfs4_client_state {
-	NFS4CLNT_OK  = 0,
-};
-
-/*
- * The nfs4_client identifies our client state to the server.
- */
-struct nfs4_client {
-	struct list_head	cl_servers;	/* Global list of servers */
-	struct in_addr		cl_addr;	/* Server identifier */
-	u64			cl_clientid;	/* constant */
-	nfs4_verifier		cl_confirm;
-	unsigned long		cl_state;
-
-	u32			cl_lockowner_id;
-
-	/*
-	 * The following rwsem ensures exclusive access to the server
-	 * while we recover the state following a lease expiration.
-	 */
-	struct rw_semaphore	cl_sem;
-
-	struct list_head	cl_delegations;
-	struct list_head	cl_state_owners;
-	struct list_head	cl_unused;
-	int			cl_nunused;
-	spinlock_t		cl_lock;
-	atomic_t		cl_count;
-
-	struct rpc_clnt *	cl_rpcclient;
-	struct rpc_cred *	cl_cred;
-
-	struct list_head	cl_superblocks;	/* List of nfs_server structs */
-
-	unsigned long		cl_lease_time;
-	unsigned long		cl_last_renewal;
-	struct work_struct	cl_renewd;
-	struct work_struct	cl_recoverd;
-
-	wait_queue_head_t	cl_waitq;
-	struct rpc_wait_queue	cl_rpcwaitq;
-
-	/* used for the setclientid verifier */
-	struct timespec		cl_boot_time;
-
-	/* idmapper */
-	struct idmap *		cl_idmap;
-
-	/* Our own IP address, as a null-terminated string.
-	 * This is used to generate the clientid, and the callback address.
-	 */
-	char			cl_ipaddr[16];
-	unsigned char		cl_id_uniquifier;
-};
-
-/*
- * NFS4 state_owners and lock_owners are simply labels for ordered
- * sequences of RPC calls. Their sole purpose is to provide once-only
- * semantics by allowing the server to identify replayed requests.
- *
- * The ->so_sema is held during all state_owner seqid-mutating operations:
- * OPEN, OPEN_DOWNGRADE, and CLOSE. Its purpose is to properly serialize
- * so_seqid.
- */
-struct nfs4_state_owner {
-	struct list_head     so_list;	 /* per-clientid list of state_owners */
-	struct nfs4_client   *so_client;
-	u32                  so_id;      /* 32-bit identifier, unique */
-	struct semaphore     so_sema;
-	u32                  so_seqid;   /* protected by so_sema */
-	atomic_t	     so_count;
-
-	struct rpc_cred	     *so_cred;	 /* Associated cred */
-	struct list_head     so_states;
-	struct list_head     so_delegations;
-};
-
-/*
- * struct nfs4_state maintains the client-side state for a given
- * (state_owner,inode) tuple (OPEN) or state_owner (LOCK).
- *
- * OPEN:
- * In order to know when to OPEN_DOWNGRADE or CLOSE the state on the server,
- * we need to know how many files are open for reading or writing on a
- * given inode. This information too is stored here.
- *
- * LOCK: one nfs4_state (LOCK) to hold the lock stateid nfs4_state(OPEN)
- */
-
-struct nfs4_lock_state {
-	struct list_head	ls_locks;	/* Other lock stateids */
-	fl_owner_t		ls_owner;	/* POSIX lock owner */
-#define NFS_LOCK_INITIALIZED 1
-	int			ls_flags;
-	u32			ls_seqid;
-	u32			ls_id;
-	nfs4_stateid		ls_stateid;
-	atomic_t		ls_count;
-};
-
-/* bits for nfs4_state->flags */
-enum {
-	LK_STATE_IN_USE,
-	NFS_DELEGATED_STATE,
-};
-
-struct nfs4_state {
-	struct list_head open_states;	/* List of states for the same state_owner */
-	struct list_head inode_states;	/* List of states for the same inode */
-	struct list_head lock_states;	/* List of subservient lock stateids */
-
-	struct nfs4_state_owner *owner;	/* Pointer to the open owner */
-	struct inode *inode;		/* Pointer to the inode */
-
-	unsigned long flags;		/* Do we hold any locks? */
-	struct semaphore lock_sema;	/* Serializes file locking operations */
-	rwlock_t state_lock;		/* Protects the lock_states list */
-
-	nfs4_stateid stateid;
-
-	unsigned int nreaders;
-	unsigned int nwriters;
-	int state;			/* State on the server (R,W, or RW) */
-	atomic_t count;
-};
-
-
-struct nfs4_exception {
-	long timeout;
-	int retry;
-};
-
-struct nfs4_state_recovery_ops {
-	int (*recover_open)(struct nfs4_state_owner *, struct nfs4_state *);
-	int (*recover_lock)(struct nfs4_state *, struct file_lock *);
-};
-
-extern struct dentry_operations nfs4_dentry_operations;
-extern struct inode_operations nfs4_dir_inode_operations;
-
-/* nfs4proc.c */
-extern int nfs4_map_errors(int err);
-extern int nfs4_proc_setclientid(struct nfs4_client *, u32, unsigned short);
-extern int nfs4_proc_setclientid_confirm(struct nfs4_client *);
-extern int nfs4_proc_async_renew(struct nfs4_client *);
-extern int nfs4_proc_renew(struct nfs4_client *);
-extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode);
-extern struct inode *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
-extern int nfs4_open_revalidate(struct inode *, struct dentry *, int);
-
-extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
-extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;
-
-/* nfs4renewd.c */
-extern void nfs4_schedule_state_renewal(struct nfs4_client *);
-extern void nfs4_renewd_prepare_shutdown(struct nfs_server *);
-extern void nfs4_kill_renewd(struct nfs4_client *);
-
-/* nfs4state.c */
-extern void init_nfsv4_state(struct nfs_server *);
-extern void destroy_nfsv4_state(struct nfs_server *);
-extern struct nfs4_client *nfs4_get_client(struct in_addr *);
-extern void nfs4_put_client(struct nfs4_client *clp);
-extern int nfs4_init_client(struct nfs4_client *clp);
-extern struct nfs4_client *nfs4_find_client(struct in_addr *);
-extern u32 nfs4_alloc_lockowner_id(struct nfs4_client *);
-
-extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
-extern void nfs4_put_state_owner(struct nfs4_state_owner *);
-extern void nfs4_drop_state_owner(struct nfs4_state_owner *);
-extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
-extern void nfs4_put_open_state(struct nfs4_state *);
-extern void nfs4_close_state(struct nfs4_state *, mode_t);
-extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode);
-extern void nfs4_increment_seqid(int status, struct nfs4_state_owner *sp);
-extern void nfs4_schedule_state_recovery(struct nfs4_client *);
-extern struct nfs4_lock_state *nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t);
-extern struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t);
-extern void nfs4_put_lock_state(struct nfs4_lock_state *state);
-extern void nfs4_increment_lock_seqid(int status, struct nfs4_lock_state *ls);
-extern void nfs4_notify_setlk(struct nfs4_state *, struct file_lock *, struct nfs4_lock_state *);
-extern void nfs4_notify_unlck(struct nfs4_state *, struct file_lock *, struct nfs4_lock_state *);
-extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t);
-
-
-
-struct nfs4_mount_data;
-#else
-#define init_nfsv4_state(server)  do { } while (0)
-#define destroy_nfsv4_state(server)       do { } while (0)
-#define nfs4_put_state_owner(inode, owner) do { } while (0)
-#define nfs4_put_open_state(state) do { } while (0)
-#define nfs4_close_state(a, b) do { } while (0)
-#define nfs4_renewd_prepare_shutdown(server) do { } while (0)
-#endif
-
 #endif /* __KERNEL__ */
 
 /*
diff --git a/include/linux/nfs_fs_i.h b/include/linux/nfs_fs_i.h
index e9a7495..e2c18dab 100644
--- a/include/linux/nfs_fs_i.h
+++ b/include/linux/nfs_fs_i.h
@@ -16,6 +16,11 @@
 	struct nlm_lockowner *owner;
 };
 
+struct nfs4_lock_state;
+struct nfs4_lock_info {
+	struct nfs4_lock_state *owner;
+};
+
 /*
  * Lock flag values
  */
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index fc51645..3d3a305 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -10,6 +10,7 @@
 struct nfs_server {
 	struct rpc_clnt *	client;		/* RPC client handle */
 	struct rpc_clnt *	client_sys;	/* 2nd handle for FSINFO */
+	struct rpc_clnt *	client_acl;	/* ACL RPC client handle */
 	struct nfs_rpc_ops *	rpc_ops;	/* NFS protocol vector */
 	struct backing_dev_info	backing_dev_info;
 	int			flags;		/* various flags */
diff --git a/include/linux/nfs_mount.h b/include/linux/nfs_mount.h
index 0071428..659c754 100644
--- a/include/linux/nfs_mount.h
+++ b/include/linux/nfs_mount.h
@@ -58,6 +58,7 @@
 #define NFS_MOUNT_KERBEROS	0x0100	/* 3 */
 #define NFS_MOUNT_NONLM		0x0200	/* 3 */
 #define NFS_MOUNT_BROKEN_SUID	0x0400	/* 4 */
+#define NFS_MOUNT_NOACL		0x0800	/* 4 */
 #define NFS_MOUNT_STRICTLOCK	0x1000	/* reserved for NFSv4 */
 #define NFS_MOUNT_SECFLAVOUR	0x2000	/* 5 */
 #define NFS_MOUNT_FLAGMASK	0xFFFF
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h
index 39e4895..da2e077 100644
--- a/include/linux/nfs_page.h
+++ b/include/linux/nfs_page.h
@@ -20,12 +20,19 @@
 #include <asm/atomic.h>
 
 /*
+ * Valid flags for the radix tree
+ */
+#define NFS_PAGE_TAG_DIRTY	0
+#define NFS_PAGE_TAG_WRITEBACK	1
+
+/*
  * Valid flags for a dirty buffer
  */
 #define PG_BUSY			0
 #define PG_NEED_COMMIT		1
 #define PG_NEED_RESCHED		2
 
+struct nfs_inode;
 struct nfs_page {
 	struct list_head	wb_list,	/* Defines state of page: */
 				*wb_list_head;	/*      read/write/commit */
@@ -54,14 +61,17 @@
 extern	void nfs_release_request(struct nfs_page *req);
 
 
-extern	void nfs_list_add_request(struct nfs_page *, struct list_head *);
-
+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_coalesce_requests(struct list_head *, struct list_head *,
 				  unsigned int);
 extern  int nfs_wait_on_request(struct nfs_page *);
 extern	void nfs_unlock_request(struct nfs_page *req);
+extern  int nfs_set_page_writeback_locked(struct nfs_page *req);
+extern  void nfs_clear_page_writeback(struct nfs_page *req);
+
 
 /*
  * Lock the page of an asynchronous request without incrementing the wb_count
@@ -86,6 +96,18 @@
 	return 1;
 }
 
+/**
+ * nfs_list_add_request - Insert a request into a list
+ * @req: request
+ * @head: head of list into which to insert the request.
+ */
+static inline void
+nfs_list_add_request(struct nfs_page *req, struct list_head *head)
+{
+	list_add_tail(&req->wb_list, head);
+	req->wb_list_head = head;
+}
+
 
 /**
  * nfs_list_remove_request - Remove a request from its wb_list
@@ -96,10 +118,6 @@
 {
 	if (list_empty(&req->wb_list))
 		return;
-	if (!NFS_WBACK_BUSY(req)) {
-		printk(KERN_ERR "NFS: unlocked request attempted removed from list!\n");
-		BUG();
-	}
 	list_del_init(&req->wb_list);
 	req->wb_list_head = NULL;
 }
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 47037d9..a2bf691 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -2,6 +2,7 @@
 #define _LINUX_NFS_XDR_H
 
 #include <linux/sunrpc/xprt.h>
+#include <linux/nfsacl.h>
 
 struct nfs4_fsid {
 	__u64 major;
@@ -326,6 +327,20 @@
 	const u32 *			bitmask;
 };
 
+struct nfs_setaclargs {
+	struct nfs_fh *			fh;
+	size_t				acl_len;
+	unsigned int			acl_pgbase;
+	struct page **			acl_pages;
+};
+
+struct nfs_getaclargs {
+	struct nfs_fh *			fh;
+	size_t				acl_len;
+	unsigned int			acl_pgbase;
+	struct page **			acl_pages;
+};
+
 struct nfs_setattrres {
 	struct nfs_fattr *              fattr;
 	const struct nfs_server *	server;
@@ -354,6 +369,20 @@
 	struct page **		pages;
 };
 
+struct nfs3_getaclargs {
+	struct nfs_fh *		fh;
+	int			mask;
+	struct page **		pages;
+};
+
+struct nfs3_setaclargs {
+	struct inode *		inode;
+	int			mask;
+	struct posix_acl *	acl_access;
+	struct posix_acl *	acl_default;
+	struct page **		pages;
+};
+
 struct nfs_diropok {
 	struct nfs_fh *		fh;
 	struct nfs_fattr *	fattr;
@@ -477,6 +506,15 @@
 	int			plus;
 };
 
+struct nfs3_getaclres {
+	struct nfs_fattr *	fattr;
+	int			mask;
+	unsigned int		acl_access_count;
+	unsigned int		acl_default_count;
+	struct posix_acl *	acl_access;
+	struct posix_acl *	acl_default;
+};
+
 #ifdef CONFIG_NFS_V4
 
 typedef u64 clientid4;
@@ -667,6 +705,7 @@
 	int	version;		/* Protocol version */
 	struct dentry_operations *dentry_ops;
 	struct inode_operations *dir_inode_ops;
+	struct inode_operations *file_inode_ops;
 
 	int	(*getroot) (struct nfs_server *, struct nfs_fh *,
 			    struct nfs_fsinfo *);
@@ -713,6 +752,7 @@
 	int	(*file_open)   (struct inode *, struct file *);
 	int	(*file_release) (struct inode *, struct file *);
 	int	(*lock)(struct file *, int, struct file_lock *);
+	void	(*clear_acl_cache)(struct inode *);
 };
 
 /*
@@ -732,4 +772,7 @@
 extern struct rpc_version	nfs_version3;
 extern struct rpc_version	nfs_version4;
 
+extern struct rpc_version	nfsacl_version3;
+extern struct rpc_program	nfsacl_program;
+
 #endif
diff --git a/include/linux/nfsacl.h b/include/linux/nfsacl.h
new file mode 100644
index 0000000..54487a9
--- /dev/null
+++ b/include/linux/nfsacl.h
@@ -0,0 +1,58 @@
+/*
+ * File: linux/nfsacl.h
+ *
+ * (C) 2003 Andreas Gruenbacher <agruen@suse.de>
+ */
+#ifndef __LINUX_NFSACL_H
+#define __LINUX_NFSACL_H
+
+#define NFS_ACL_PROGRAM	100227
+
+#define ACLPROC2_GETACL		1
+#define ACLPROC2_SETACL		2
+#define ACLPROC2_GETATTR	3
+#define ACLPROC2_ACCESS		4
+
+#define ACLPROC3_GETACL		1
+#define ACLPROC3_SETACL		2
+
+
+/* Flags for the getacl/setacl mode */
+#define NFS_ACL			0x0001
+#define NFS_ACLCNT		0x0002
+#define NFS_DFACL		0x0004
+#define NFS_DFACLCNT		0x0008
+
+/* Flag for Default ACL entries */
+#define NFS_ACL_DEFAULT		0x1000
+
+#ifdef __KERNEL__
+
+#include <linux/posix_acl.h>
+
+/* Maximum number of ACL entries over NFS */
+#define NFS_ACL_MAX_ENTRIES	1024
+
+#define NFSACL_MAXWORDS		(2*(2+3*NFS_ACL_MAX_ENTRIES))
+#define NFSACL_MAXPAGES		((2*(8+12*NFS_ACL_MAX_ENTRIES) + PAGE_SIZE-1) \
+				 >> PAGE_SHIFT)
+
+static inline unsigned int
+nfsacl_size(struct posix_acl *acl_access, struct posix_acl *acl_default)
+{
+	unsigned int w = 16;
+	w += max(acl_access ? (int)acl_access->a_count : 3, 4) * 12;
+	if (acl_default)
+		w += max((int)acl_default->a_count, 4) * 12;
+	return w;
+}
+
+extern unsigned int
+nfsacl_encode(struct xdr_buf *buf, unsigned int base, struct inode *inode,
+	      struct posix_acl *acl, int encode_entries, int typeflag);
+extern unsigned int
+nfsacl_decode(struct xdr_buf *buf, unsigned int base, unsigned int *aclcnt,
+	      struct posix_acl **pacl);
+
+#endif /* __KERNEL__ */
+#endif  /* __LINUX_NFSACL_H */
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index 8f85d9a..5791dfd 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -15,6 +15,7 @@
 #include <linux/unistd.h>
 #include <linux/dirent.h>
 #include <linux/fs.h>
+#include <linux/posix_acl.h>
 #include <linux/mount.h>
 
 #include <linux/nfsd/debug.h>
@@ -124,20 +125,39 @@
 int		nfsd_notify_change(struct inode *, struct iattr *);
 int		nfsd_permission(struct svc_export *, struct dentry *, int);
 
+#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
+#ifdef CONFIG_NFSD_V2_ACL
+extern struct svc_version nfsd_acl_version2;
+#else
+#define nfsd_acl_version2 NULL
+#endif
+#ifdef CONFIG_NFSD_V3_ACL
+extern struct svc_version nfsd_acl_version3;
+#else
+#define nfsd_acl_version3 NULL
+#endif
+struct posix_acl *nfsd_get_posix_acl(struct svc_fh *, int);
+int nfsd_set_posix_acl(struct svc_fh *, int, struct posix_acl *);
+#endif
+
 
 /* 
  * NFSv4 State
  */
 #ifdef CONFIG_NFSD_V4
-int nfs4_state_init(void);
+void nfs4_state_init(void);
+int nfs4_state_start(void);
 void nfs4_state_shutdown(void);
 time_t nfs4_lease_time(void);
 void nfs4_reset_lease(time_t leasetime);
+int nfs4_reset_recoverydir(char *recdir);
 #else
-static inline int nfs4_state_init(void){return 0;}
+static inline void nfs4_state_init(void){};
+static inline int nfs4_state_start(void){return 0;}
 static inline void nfs4_state_shutdown(void){}
 static inline time_t nfs4_lease_time(void){return 0;}
 static inline void nfs4_reset_lease(time_t leasetime){}
+static inline int nfs4_reset_recoverydir(char *recdir) {return 0;}
 #endif
 
 /*
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index b6b2fe1..a84a3fa 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -61,11 +61,6 @@
 #define si_stateownerid   si_opaque.so_stateownerid
 #define si_fileid         si_opaque.so_fileid
 
-extern stateid_t zerostateid;
-extern stateid_t onestateid;
-
-#define ZERO_STATEID(stateid)       (!memcmp((stateid), &zerostateid, sizeof(stateid_t)))
-#define ONE_STATEID(stateid)        (!memcmp((stateid), &onestateid, sizeof(stateid_t)))
 
 struct nfs4_cb_recall {
 	u32			cbr_ident;
@@ -77,8 +72,8 @@
 };
 
 struct nfs4_delegation {
-	struct list_head	dl_del_perfile; /* nfs4_file->fi_del_perfile */
-	struct list_head	dl_del_perclnt; /* nfs4_client->cl_del_perclnt*/
+	struct list_head	dl_perfile;
+	struct list_head	dl_perclnt;
 	struct list_head	dl_recall_lru;  /* delegation recalled */
 	atomic_t		dl_count;       /* ref count */
 	struct nfs4_client	*dl_client;
@@ -97,7 +92,6 @@
 /* client delegation callback info */
 struct nfs4_callback {
 	/* SETCLIENTID info */
-	u32			cb_parsed;  /* addr parsed */
 	u32                     cb_addr;
 	unsigned short          cb_port;
 	u32                     cb_prog;
@@ -109,6 +103,8 @@
 	struct rpc_clnt *       cb_client;
 };
 
+#define HEXDIR_LEN     33 /* hex version of 16 byte md5 of cl_name plus '\0' */
+
 /*
  * struct nfs4_client - one per client.  Clientids live here.
  * 	o Each nfs4_client is hashed by clientid.
@@ -122,10 +118,11 @@
 struct nfs4_client {
 	struct list_head	cl_idhash; 	/* hash by cl_clientid.id */
 	struct list_head	cl_strhash; 	/* hash by cl_name */
-	struct list_head	cl_perclient; 	/* list: stateowners */
-	struct list_head	cl_del_perclnt; /* list: delegations */
+	struct list_head	cl_openowners;
+	struct list_head	cl_delegations;
 	struct list_head        cl_lru;         /* tail queue */
 	struct xdr_netobj	cl_name; 	/* id generated by client */
+	char                    cl_recdir[HEXDIR_LEN]; /* recovery dir */
 	nfs4_verifier		cl_verifier; 	/* generated by client */
 	time_t                  cl_time;        /* time of last lease renewal */
 	u32			cl_addr; 	/* client ipaddress */
@@ -134,6 +131,7 @@
 	nfs4_verifier		cl_confirm;	/* generated by server */
 	struct nfs4_callback	cl_callback;    /* callback info */
 	atomic_t		cl_count;	/* ref count */
+	u32			cl_firststate;	/* recovery dir creation */
 };
 
 /* struct nfs4_client_reset
@@ -143,7 +141,7 @@
  */
 struct nfs4_client_reclaim {
 	struct list_head	cr_strhash;	/* hash by cr_name */
-	struct xdr_netobj 	cr_name; 	/* id generated by client */
+	char			cr_recdir[HEXDIR_LEN]; /* recover dir */
 };
 
 static inline void
@@ -197,9 +195,9 @@
 	struct kref		so_ref;
 	struct list_head        so_idhash;   /* hash by so_id */
 	struct list_head        so_strhash;   /* hash by op_name */
-	struct list_head        so_perclient; /* nfs4_client->cl_perclient */
-	struct list_head        so_perfilestate; /* list: nfs4_stateid */
-	struct list_head        so_perlockowner; /* nfs4_stateid->st_perlockowner */
+	struct list_head        so_perclient;
+	struct list_head        so_stateids;
+	struct list_head        so_perstateid; /* for lockowners only */
 	struct list_head	so_close_lru; /* tail queue */
 	time_t			so_time; /* time of placement on so_close_lru */
 	int			so_is_open_owner; /* 1=openowner,0=lockowner */
@@ -217,9 +215,10 @@
 *      share_acces, share_deny on the file.
 */
 struct nfs4_file {
+	struct kref		fi_ref;
 	struct list_head        fi_hash;    /* hash by "struct inode *" */
-	struct list_head        fi_perfile; /* list: nfs4_stateid */
-	struct list_head	fi_del_perfile; /* list: nfs4_delegation */
+	struct list_head        fi_stateids;
+	struct list_head	fi_delegations;
 	struct inode		*fi_inode;
 	u32                     fi_id;      /* used with stateowner->so_id 
 					     * for stateid_hashtbl hash */
@@ -241,8 +240,8 @@
 struct nfs4_stateid {
 	struct list_head              st_hash; 
 	struct list_head              st_perfile;
-	struct list_head              st_perfilestate; 
-	struct list_head              st_perlockowner;
+	struct list_head              st_perstateowner;
+	struct list_head              st_lockowners;
 	struct nfs4_stateowner      * st_stateowner;
 	struct nfs4_file            * st_file;
 	stateid_t                     st_stateid;
@@ -267,12 +266,9 @@
 	((err) != nfserr_stale_stateid) &&      \
 	((err) != nfserr_bad_stateid))
 
-extern time_t nfs4_laundromat(void);
 extern int nfsd4_renew(clientid_t *clid);
 extern int nfs4_preprocess_stateid_op(struct svc_fh *current_fh, 
 		stateid_t *stateid, int flags, struct file **filp);
-extern int nfs4_share_conflict(struct svc_fh *current_fh, 
-		unsigned int deny_type);
 extern void nfs4_lock_state(void);
 extern void nfs4_unlock_state(void);
 extern int nfs4_in_grace(void);
@@ -282,6 +278,15 @@
 extern void nfsd4_probe_callback(struct nfs4_client *clp);
 extern void nfsd4_cb_recall(struct nfs4_delegation *dp);
 extern void nfs4_put_delegation(struct nfs4_delegation *dp);
+extern int nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
+extern void nfsd4_init_recdir(char *recdir_name);
+extern int nfsd4_recdir_load(void);
+extern void nfsd4_shutdown_recdir(void);
+extern int nfs4_client_to_reclaim(const char *name);
+extern int nfs4_has_reclaimed_state(const char *name);
+extern void nfsd4_recdir_purge_old(void);
+extern int nfsd4_create_clid_dir(struct nfs4_client *clp);
+extern void nfsd4_remove_clid_dir(struct nfs4_client *clp);
 
 static inline void
 nfs4_put_stateowner(struct nfs4_stateowner *so)
diff --git a/include/linux/nfsd/xdr.h b/include/linux/nfsd/xdr.h
index ecccef7..130d4f5 100644
--- a/include/linux/nfsd/xdr.h
+++ b/include/linux/nfsd/xdr.h
@@ -169,4 +169,8 @@
 
 int nfssvc_release_fhandle(struct svc_rqst *, u32 *, struct nfsd_fhandle *);
 
+/* Helper functions for NFSv2 ACL code */
+u32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp);
+u32 *nfs2svc_decode_fh(u32 *p, struct svc_fh *fhp);
+
 #endif /* LINUX_NFSD_H */
diff --git a/include/linux/nfsd/xdr3.h b/include/linux/nfsd/xdr3.h
index 0ae9e0e..21e18ce 100644
--- a/include/linux/nfsd/xdr3.h
+++ b/include/linux/nfsd/xdr3.h
@@ -110,6 +110,19 @@
 	__u32			count;
 };
 
+struct nfsd3_getaclargs {
+	struct svc_fh		fh;
+	int			mask;
+};
+
+struct posix_acl;
+struct nfsd3_setaclargs {
+	struct svc_fh		fh;
+	int			mask;
+	struct posix_acl	*acl_access;
+	struct posix_acl	*acl_default;
+};
+
 struct nfsd3_attrstat {
 	__u32			status;
 	struct svc_fh		fh;
@@ -209,6 +222,14 @@
 	struct svc_fh		fh;
 };
 
+struct nfsd3_getaclres {
+	__u32			status;
+	struct svc_fh		fh;
+	int			mask;
+	struct posix_acl	*acl_access;
+	struct posix_acl	*acl_default;
+};
+
 /* dummy type for release */
 struct nfsd3_fhandle_pair {
 	__u32			dummy;
@@ -241,6 +262,7 @@
 	struct nfsd3_fsinfores		fsinfores;
 	struct nfsd3_pathconfres	pathconfres;
 	struct nfsd3_commitres		commitres;
+	struct nfsd3_getaclres		getaclres;
 };
 
 #define NFS3_SVC_XDRSIZE		sizeof(union nfsd3_xdrstore)
@@ -316,6 +338,10 @@
 int nfs3svc_encode_entry_plus(struct readdir_cd *, const char *name,
 				int namlen, loff_t offset, ino_t ino,
 				unsigned int);
+/* Helper functions for NFSv3 ACL code */
+u32 *nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, u32 *p,
+				struct svc_fh *fhp);
+u32 *nfs3svc_decode_fh(u32 *p, struct svc_fh *fhp);
 
 
 #endif /* _LINUX_NFSD_XDR3_H */
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index a1f5ad0..4d24d65 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -210,6 +210,7 @@
 	u32		op_share_access;    /* request */
 	u32		op_share_deny;      /* request */
 	stateid_t	op_stateid;         /* response */
+	u32		op_recall;          /* recall */
 	struct nfsd4_change_info  op_cinfo; /* response */
 	u32		op_rflags;          /* response */
 	int		op_truncate;        /* used during processing */
diff --git a/include/linux/nfsd_idmap.h b/include/linux/nfsd_idmap.h
index 9bb7f30..e82746f 100644
--- a/include/linux/nfsd_idmap.h
+++ b/include/linux/nfsd_idmap.h
@@ -43,8 +43,13 @@
 /* XXX from linux/nfs_idmap.h */
 #define IDMAP_NAMESZ 128
 
+#ifdef CONFIG_NFSD_V4
 void nfsd_idmap_init(void);
 void nfsd_idmap_shutdown(void);
+#else
+static inline void nfsd_idmap_init(void) {};
+static inline void nfsd_idmap_shutdown(void) {};
+#endif
 
 int nfsd_map_name_to_uid(struct svc_rqst *, const char *, size_t, __u32 *);
 int nfsd_map_name_to_gid(struct svc_rqst *, const char *, size_t, __u32 *);
diff --git a/include/linux/node.h b/include/linux/node.h
index 6e0a697..254dc3d 100644
--- a/include/linux/node.h
+++ b/include/linux/node.h
@@ -27,6 +27,7 @@
 };
 
 extern int register_node(struct node *, int, struct node *);
+extern void unregister_node(struct node *node);
 
 #define to_node(sys_device) container_of(sys_device, struct node, sysdev)
 
diff --git a/include/linux/numa.h b/include/linux/numa.h
index bd0c8c4..f0c539b 100644
--- a/include/linux/numa.h
+++ b/include/linux/numa.h
@@ -3,7 +3,7 @@
 
 #include <linux/config.h>
 
-#ifdef CONFIG_DISCONTIGMEM
+#ifndef CONFIG_FLATMEM
 #include <asm/numnodes.h>
 #endif
 
diff --git a/include/linux/nvram.h b/include/linux/nvram.h
index b031e41..9189829 100644
--- a/include/linux/nvram.h
+++ b/include/linux/nvram.h
@@ -20,8 +20,6 @@
 extern void nvram_write_byte(unsigned char c, int i);
 extern int __nvram_check_checksum(void);
 extern int nvram_check_checksum(void);
-extern void __nvram_set_checksum(void);
-extern void nvram_set_checksum(void);
 #endif
 
 #endif  /* _LINUX_NVRAM_H */
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 39ab8c6..f5a6695 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -61,21 +61,20 @@
 #define PG_active		 6
 #define PG_slab			 7	/* slab debug (Suparna wants this) */
 
-#define PG_highmem		 8
-#define PG_checked		 9	/* kill me in 2.5.<early>. */
-#define PG_arch_1		10
-#define PG_reserved		11
+#define PG_checked		 8	/* kill me in 2.5.<early>. */
+#define PG_arch_1		 9
+#define PG_reserved		10
+#define PG_private		11	/* Has something at ->private */
 
-#define PG_private		12	/* Has something at ->private */
-#define PG_writeback		13	/* Page is under writeback */
-#define PG_nosave		14	/* Used for system suspend/resume */
-#define PG_compound		15	/* Part of a compound page */
+#define PG_writeback		12	/* Page is under writeback */
+#define PG_nosave		13	/* Used for system suspend/resume */
+#define PG_compound		14	/* Part of a compound page */
+#define PG_swapcache		15	/* Swap page: swp_entry_t in private */
 
-#define PG_swapcache		16	/* Swap page: swp_entry_t in private */
-#define PG_mappedtodisk		17	/* Has blocks allocated on-disk */
-#define PG_reclaim		18	/* To be reclaimed asap */
-#define PG_nosave_free		19	/* Free, should not be written */
-#define PG_uncached		20	/* Page has been mapped as uncached */
+#define PG_mappedtodisk		16	/* Has blocks allocated on-disk */
+#define PG_reclaim		17	/* To be reclaimed asap */
+#define PG_nosave_free		18	/* Free, should not be written */
+#define PG_uncached		19	/* Page has been mapped as uncached */
 
 /*
  * Global page accounting.  One instance per CPU.  Only unsigned longs are
@@ -136,8 +135,8 @@
 
 extern void get_page_state(struct page_state *ret);
 extern void get_full_page_state(struct page_state *ret);
-extern unsigned long __read_page_state(unsigned offset);
-extern void __mod_page_state(unsigned offset, unsigned long delta);
+extern unsigned long __read_page_state(unsigned long offset);
+extern void __mod_page_state(unsigned long offset, unsigned long delta);
 
 #define read_page_state(member) \
 	__read_page_state(offsetof(struct page_state, member))
@@ -215,7 +214,7 @@
 #define TestSetPageSlab(page)	test_and_set_bit(PG_slab, &(page)->flags)
 
 #ifdef CONFIG_HIGHMEM
-#define PageHighMem(page)	test_bit(PG_highmem, &(page)->flags)
+#define PageHighMem(page)	is_highmem(page_zone(page))
 #else
 #define PageHighMem(page)	0 /* needed to optimize away at compile time */
 #endif
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 0422031..d9a2564 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -52,12 +52,12 @@
 
 static inline struct page *page_cache_alloc(struct address_space *x)
 {
-	return alloc_pages(mapping_gfp_mask(x), 0);
+	return alloc_pages(mapping_gfp_mask(x)|__GFP_NORECLAIM, 0);
 }
 
 static inline struct page *page_cache_alloc_cold(struct address_space *x)
 {
-	return alloc_pages(mapping_gfp_mask(x)|__GFP_COLD, 0);
+	return alloc_pages(mapping_gfp_mask(x)|__GFP_COLD|__GFP_NORECLAIM, 0);
 }
 
 typedef int filler_t(void *, struct page *);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index b0d6134..bf60880 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -575,6 +575,7 @@
 #define PCI_DEVICE_ID_CT_65550		0x00e0
 #define PCI_DEVICE_ID_CT_65554		0x00e4
 #define PCI_DEVICE_ID_CT_65555		0x00e5
+#define PCI_DEVICE_ID_CT_69000		0x00c0
 
 #define PCI_VENDOR_ID_MIRO		0x1031
 #define PCI_DEVICE_ID_MIRO_36050	0x5601
@@ -874,6 +875,7 @@
 #define PCI_DEVICE_ID_APPLE_KL_USB_P	0x0026
 #define PCI_DEVICE_ID_APPLE_UNI_N_AGP_P	0x0027
 #define PCI_DEVICE_ID_APPLE_UNI_N_AGP15	0x002d
+#define PCI_DEVICE_ID_APPLE_UNI_N_PCI15	0x002e
 #define PCI_DEVICE_ID_APPLE_UNI_N_FW2	0x0030
 #define PCI_DEVICE_ID_APPLE_UNI_N_GMAC2	0x0032
 #define PCI_DEVIEC_ID_APPLE_UNI_N_ATA	0x0033
@@ -1566,6 +1568,7 @@
 #define PCI_DEVICE_ID_SERVERWORKS_OSB4USB 0x0220
 #define PCI_DEVICE_ID_SERVERWORKS_CSB5USB PCI_DEVICE_ID_SERVERWORKS_OSB4USB
 #define PCI_DEVICE_ID_SERVERWORKS_CSB6USB 0x0221
+#define PCI_DEVICE_ID_SERVERWORKS_CSB6LPC 0x0227
 #define PCI_DEVICE_ID_SERVERWORKS_GCLE    0x0225
 #define PCI_DEVICE_ID_SERVERWORKS_GCLE2   0x0227
 #define PCI_DEVICE_ID_SERVERWORKS_CSB5ISA 0x0230
@@ -2382,6 +2385,8 @@
 #define PCI_DEVICE_ID_INTEL_82915G_IG	0x2582
 #define PCI_DEVICE_ID_INTEL_82915GM_HB	0x2590
 #define PCI_DEVICE_ID_INTEL_82915GM_IG	0x2592
+#define PCI_DEVICE_ID_INTEL_82945G_HB	0x2770
+#define PCI_DEVICE_ID_INTEL_82945G_IG	0x2772
 #define PCI_DEVICE_ID_INTEL_ICH6_0	0x2640
 #define PCI_DEVICE_ID_INTEL_ICH6_1	0x2641
 #define PCI_DEVICE_ID_INTEL_ICH6_2	0x2642
diff --git a/include/linux/pfkeyv2.h b/include/linux/pfkeyv2.h
index e6b5192..7240667 100644
--- a/include/linux/pfkeyv2.h
+++ b/include/linux/pfkeyv2.h
@@ -245,6 +245,7 @@
 
 /* Security Association flags */
 #define SADB_SAFLAGS_PFS	1
+#define SADB_SAFLAGS_NOPMTUDISC	0x20000000
 #define SADB_SAFLAGS_DECAP_DSCP	0x40000000
 #define SADB_SAFLAGS_NOECN	0x80000000
 
diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h
index d2aa214..25d2d67 100644
--- a/include/linux/pkt_cls.h
+++ b/include/linux/pkt_cls.h
@@ -408,6 +408,7 @@
 	TCF_EM_NBYTE,
 	TCF_EM_U32,
 	TCF_EM_META,
+	TCF_EM_TEXT,
 	__TCF_EM_MAX
 };
 
diff --git a/include/linux/pktcdvd.h b/include/linux/pktcdvd.h
index 4e2d2a9..4b32bce 100644
--- a/include/linux/pktcdvd.h
+++ b/include/linux/pktcdvd.h
@@ -159,7 +159,7 @@
 	struct bio		*read_queue_tail;
 	struct bio		*write_queue;
 	struct bio		*write_queue_tail;
-	int			high_prio_read;	/* An important read request has been queued */
+	sector_t		last_write;	/* The sector where the last write ended */
 	int			successive_reads;
 };
 
diff --git a/include/linux/pm.h b/include/linux/pm.h
index ed2b76e..1447932 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -103,7 +103,8 @@
 /*
  * Register a device with power management
  */
-struct pm_dev __deprecated *pm_register(pm_dev_t type, unsigned long id, pm_callback callback);
+struct pm_dev __deprecated *
+pm_register(pm_dev_t type, unsigned long id, pm_callback callback);
 
 /*
  * Unregister a device with power management
@@ -190,17 +191,18 @@
 /*
  * There are 4 important states driver can be in:
  * ON     -- driver is working
- * FREEZE -- stop operations and apply whatever policy is applicable to a suspended driver
- *           of that class, freeze queues for block like IDE does, drop packets for
- *           ethernet, etc... stop DMA engine too etc... so a consistent image can be
- *           saved; but do not power any hardware down.
- * SUSPEND - like FREEZE, but hardware is doing as much powersaving as possible. Roughly
- *           pci D3.
+ * FREEZE -- stop operations and apply whatever policy is applicable to a
+ *           suspended driver of that class, freeze queues for block like IDE
+ *           does, drop packets for ethernet, etc... stop DMA engine too etc...
+ *           so a consistent image can be saved; but do not power any hardware
+ *           down.
+ * SUSPEND - like FREEZE, but hardware is doing as much powersaving as
+ *           possible. Roughly pci D3.
  *
- * Unfortunately, current drivers only recognize numeric values 0 (ON) and 3 (SUSPEND).
- * We'll need to fix the drivers. So yes, putting 3 to all diferent defines is intentional,
- * and will go away as soon as drivers are fixed. Also note that typedef is neccessary,
- * we'll probably want to switch to
+ * Unfortunately, current drivers only recognize numeric values 0 (ON) and 3
+ * (SUSPEND).  We'll need to fix the drivers. So yes, putting 3 to all different
+ * defines is intentional, and will go away as soon as drivers are fixed.  Also
+ * note that typedef is neccessary, we'll probably want to switch to
  *   typedef struct pm_message_t { int event; int flags; } pm_message_t
  * or something similar soon.
  */
@@ -222,11 +224,18 @@
 
 extern void device_pm_set_parent(struct device * dev, struct device * parent);
 
-extern int device_suspend(pm_message_t state);
 extern int device_power_down(pm_message_t state);
 extern void device_power_up(void);
 extern void device_resume(void);
 
+#ifdef CONFIG_PM
+extern int device_suspend(pm_message_t state);
+#else
+static inline int device_suspend(pm_message_t state)
+{
+	return 0;
+}
+#endif
 
 #endif /* __KERNEL__ */
 
diff --git a/include/linux/posix_acl_xattr.h b/include/linux/posix_acl_xattr.h
index 5efd0a6..6e53c34 100644
--- a/include/linux/posix_acl_xattr.h
+++ b/include/linux/posix_acl_xattr.h
@@ -23,13 +23,13 @@
 #define ACL_UNDEFINED_ID	(-1)
 
 typedef struct {
-	__u16			e_tag;
-	__u16			e_perm;
-	__u32			e_id;
+	__le16			e_tag;
+	__le16			e_perm;
+	__le32			e_id;
 } posix_acl_xattr_entry;
 
 typedef struct {
-	__u32			a_version;
+	__le32			a_version;
 	posix_acl_xattr_entry	a_entries[0];
 } posix_acl_xattr_header;
 
@@ -52,4 +52,7 @@
 	return size / sizeof(posix_acl_xattr_entry);
 }
 
+struct posix_acl *posix_acl_from_xattr(const void *value, size_t size);
+int posix_acl_to_xattr(const struct posix_acl *acl, void *buffer, size_t size);
+
 #endif	/* _POSIX_ACL_XATTR_H */
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 59e5052..0563581 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -74,6 +74,13 @@
 	size_t size;
 };
 
+struct vmcore {
+	struct list_head list;
+	unsigned long long paddr;
+	unsigned long size;
+	loff_t offset;
+};
+
 #ifdef CONFIG_PROC_FS
 
 extern struct proc_dir_entry proc_root;
diff --git a/include/linux/qnx4_fs.h b/include/linux/qnx4_fs.h
index 22ba580..fc610bb 100644
--- a/include/linux/qnx4_fs.h
+++ b/include/linux/qnx4_fs.h
@@ -46,11 +46,11 @@
 	char		di_fname[QNX4_SHORT_NAME_MAX];
 	qnx4_off_t	di_size;
 	qnx4_xtnt_t	di_first_xtnt;
-	__u32		di_xblk;
-	__s32		di_ftime;
-	__s32		di_mtime;
-	__s32		di_atime;
-	__s32		di_ctime;
+	__le32		di_xblk;
+	__le32		di_ftime;
+	__le32		di_mtime;
+	__le32		di_atime;
+	__le32		di_ctime;
 	qnx4_nxtnt_t	di_num_xtnts;
 	qnx4_mode_t	di_mode;
 	qnx4_muid_t	di_uid;
@@ -63,18 +63,18 @@
 
 struct qnx4_link_info {
 	char		dl_fname[QNX4_NAME_MAX];
-	__u32		dl_inode_blk;
+	__le32		dl_inode_blk;
 	__u8		dl_inode_ndx;
 	__u8		dl_spare[10];
 	__u8		dl_status;
 };
 
 struct qnx4_xblk {
-	__u32		xblk_next_xblk;
-	__u32		xblk_prev_xblk;
+	__le32		xblk_next_xblk;
+	__le32		xblk_prev_xblk;
 	__u8		xblk_num_xtnts;
 	__u8		xblk_spare[3];
-	__s32		xblk_num_blocks;
+	__le32		xblk_num_blocks;
 	qnx4_xtnt_t	xblk_xtnts[QNX4_MAX_XTNTS_PER_XBLK];
 	char		xblk_signature[8];
 	qnx4_xtnt_t	xblk_first_xtnt;
diff --git a/include/linux/qnxtypes.h b/include/linux/qnxtypes.h
index fb518e3..a3eb113 100644
--- a/include/linux/qnxtypes.h
+++ b/include/linux/qnxtypes.h
@@ -12,18 +12,18 @@
 #ifndef _QNX4TYPES_H
 #define _QNX4TYPES_H
 
-typedef __u16 qnx4_nxtnt_t;
+typedef __le16 qnx4_nxtnt_t;
 typedef __u8  qnx4_ftype_t;
 
 typedef struct {
-	__u32 xtnt_blk;
-	__u32 xtnt_size;
+	__le32 xtnt_blk;
+	__le32 xtnt_size;
 } qnx4_xtnt_t;
 
-typedef __u16 qnx4_mode_t;
-typedef __u16 qnx4_muid_t;
-typedef __u16 qnx4_mgid_t;
-typedef __u32 qnx4_off_t;
-typedef __u16 qnx4_nlink_t;
+typedef __le16 qnx4_mode_t;
+typedef __le16 qnx4_muid_t;
+typedef __le16 qnx4_mgid_t;
+typedef __le32 qnx4_off_t;
+typedef __le16 qnx4_nlink_t;
 
 #endif
diff --git a/include/linux/quota.h b/include/linux/quota.h
index ac5b90f..700ead4 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -138,8 +138,11 @@
 #include <linux/dqblk_v2.h>
 
 /* Maximal numbers of writes for quota operation (insert/delete/update)
- * (over all formats) - info block, 4 pointer blocks, data block */
-#define DQUOT_MAX_WRITES	6
+ * (over VFS all formats) */
+#define DQUOT_INIT_ALLOC max(V1_INIT_ALLOC, V2_INIT_ALLOC)
+#define DQUOT_INIT_REWRITE max(V1_INIT_REWRITE, V2_INIT_REWRITE)
+#define DQUOT_DEL_ALLOC max(V1_DEL_ALLOC, V2_DEL_ALLOC)
+#define DQUOT_DEL_REWRITE max(V1_DEL_REWRITE, V2_DEL_REWRITE)
 
 /*
  * Data for one user/group kept in memory
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index e57baa8..d211507 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -39,7 +39,8 @@
 extern int dquot_mark_dquot_dirty(struct dquot *dquot);
 
 extern int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path);
-extern int vfs_quota_on_mount(int type, int format_id, struct dentry *dentry);
+extern int vfs_quota_on_mount(struct super_block *sb, char *qf_name,
+		int format_id, int type);
 extern int vfs_quota_off(struct super_block *sb, int type);
 #define vfs_quota_off_mount(sb, type) vfs_quota_off(sb, type)
 extern int vfs_quota_sync(struct super_block *sb, int type);
diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h
new file mode 100644
index 0000000..e24b74b
--- /dev/null
+++ b/include/linux/raid/bitmap.h
@@ -0,0 +1,273 @@
+/*
+ * bitmap.h: Copyright (C) Peter T. Breuer (ptb@ot.uc3m.es) 2003
+ *
+ * additions: Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc.
+ */
+#ifndef BITMAP_H
+#define BITMAP_H 1
+
+#define BITMAP_MAJOR 3
+#define BITMAP_MINOR 38
+
+/*
+ * in-memory bitmap:
+ *
+ * Use 16 bit block counters to track pending writes to each "chunk".
+ * The 2 high order bits are special-purpose, the first is a flag indicating
+ * whether a resync is needed.  The second is a flag indicating whether a
+ * resync is active.
+ * This means that the counter is actually 14 bits:
+ *
+ * +--------+--------+------------------------------------------------+
+ * | resync | resync |               counter                          |
+ * | needed | active |                                                |
+ * |  (0-1) |  (0-1) |              (0-16383)                         |
+ * +--------+--------+------------------------------------------------+
+ *
+ * The "resync needed" bit is set when:
+ *    a '1' bit is read from storage at startup.
+ *    a write request fails on some drives
+ *    a resync is aborted on a chunk with 'resync active' set
+ * It is cleared (and resync-active set) when a resync starts across all drives
+ * of the chunk.
+ *
+ *
+ * The "resync active" bit is set when:
+ *    a resync is started on all drives, and resync_needed is set.
+ *       resync_needed will be cleared (as long as resync_active wasn't already set).
+ * It is cleared when a resync completes.
+ *
+ * The counter counts pending write requests, plus the on-disk bit.
+ * When the counter is '1' and the resync bits are clear, the on-disk
+ * bit can be cleared aswell, thus setting the counter to 0.
+ * When we set a bit, or in the counter (to start a write), if the fields is
+ * 0, we first set the disk bit and set the counter to 1.
+ *
+ * If the counter is 0, the on-disk bit is clear and the stipe is clean
+ * Anything that dirties the stipe pushes the counter to 2 (at least)
+ * and sets the on-disk bit (lazily).
+ * If a periodic sweep find the counter at 2, it is decremented to 1.
+ * If the sweep find the counter at 1, the on-disk bit is cleared and the
+ * counter goes to zero.
+ *
+ * Also, we'll hijack the "map" pointer itself and use it as two 16 bit block
+ * counters as a fallback when "page" memory cannot be allocated:
+ *
+ * Normal case (page memory allocated):
+ *
+ *     page pointer (32-bit)
+ *
+ *     [ ] ------+
+ *               |
+ *               +-------> [   ][   ]..[   ] (4096 byte page == 2048 counters)
+ *                          c1   c2    c2048
+ *
+ * Hijacked case (page memory allocation failed):
+ *
+ *     hijacked page pointer (32-bit)
+ *
+ *     [		  ][		  ] (no page memory allocated)
+ *      counter #1 (16-bit) counter #2 (16-bit)
+ *
+ */
+
+#ifdef __KERNEL__
+
+#define PAGE_BITS (PAGE_SIZE << 3)
+#define PAGE_BIT_SHIFT (PAGE_SHIFT + 3)
+
+typedef __u16 bitmap_counter_t;
+#define COUNTER_BITS 16
+#define COUNTER_BIT_SHIFT 4
+#define COUNTER_BYTE_RATIO (COUNTER_BITS / 8)
+#define COUNTER_BYTE_SHIFT (COUNTER_BIT_SHIFT - 3)
+
+#define NEEDED_MASK ((bitmap_counter_t) (1 << (COUNTER_BITS - 1)))
+#define RESYNC_MASK ((bitmap_counter_t) (1 << (COUNTER_BITS - 2)))
+#define COUNTER_MAX ((bitmap_counter_t) RESYNC_MASK - 1)
+#define NEEDED(x) (((bitmap_counter_t) x) & NEEDED_MASK)
+#define RESYNC(x) (((bitmap_counter_t) x) & RESYNC_MASK)
+#define COUNTER(x) (((bitmap_counter_t) x) & COUNTER_MAX)
+
+/* how many counters per page? */
+#define PAGE_COUNTER_RATIO (PAGE_BITS / COUNTER_BITS)
+/* same, except a shift value for more efficient bitops */
+#define PAGE_COUNTER_SHIFT (PAGE_BIT_SHIFT - COUNTER_BIT_SHIFT)
+/* same, except a mask value for more efficient bitops */
+#define PAGE_COUNTER_MASK  (PAGE_COUNTER_RATIO - 1)
+
+#define BITMAP_BLOCK_SIZE 512
+#define BITMAP_BLOCK_SHIFT 9
+
+/* how many blocks per chunk? (this is variable) */
+#define CHUNK_BLOCK_RATIO(bitmap) ((bitmap)->chunksize >> BITMAP_BLOCK_SHIFT)
+#define CHUNK_BLOCK_SHIFT(bitmap) ((bitmap)->chunkshift - BITMAP_BLOCK_SHIFT)
+#define CHUNK_BLOCK_MASK(bitmap) (CHUNK_BLOCK_RATIO(bitmap) - 1)
+
+/* when hijacked, the counters and bits represent even larger "chunks" */
+/* there will be 1024 chunks represented by each counter in the page pointers */
+#define PAGEPTR_BLOCK_RATIO(bitmap) \
+			(CHUNK_BLOCK_RATIO(bitmap) << PAGE_COUNTER_SHIFT >> 1)
+#define PAGEPTR_BLOCK_SHIFT(bitmap) \
+			(CHUNK_BLOCK_SHIFT(bitmap) + PAGE_COUNTER_SHIFT - 1)
+#define PAGEPTR_BLOCK_MASK(bitmap) (PAGEPTR_BLOCK_RATIO(bitmap) - 1)
+
+/*
+ * on-disk bitmap:
+ *
+ * Use one bit per "chunk" (block set). We do the disk I/O on the bitmap
+ * file a page at a time. There's a superblock at the start of the file.
+ */
+
+/* map chunks (bits) to file pages - offset by the size of the superblock */
+#define CHUNK_BIT_OFFSET(chunk) ((chunk) + (sizeof(bitmap_super_t) << 3))
+
+#endif
+
+/*
+ * bitmap structures:
+ */
+
+#define BITMAP_MAGIC 0x6d746962
+
+/* use these for bitmap->flags and bitmap->sb->state bit-fields */
+enum bitmap_state {
+	BITMAP_ACTIVE = 0x001, /* the bitmap is in use */
+	BITMAP_STALE  = 0x002  /* the bitmap file is out of date or had -EIO */
+};
+
+/* the superblock at the front of the bitmap file -- little endian */
+typedef struct bitmap_super_s {
+	__u32 magic;        /*  0  BITMAP_MAGIC */
+	__u32 version;      /*  4  the bitmap major for now, could change... */
+	__u8  uuid[16];     /*  8  128 bit uuid - must match md device uuid */
+	__u64 events;       /* 24  event counter for the bitmap (1)*/
+	__u64 events_cleared;/*32  event counter when last bit cleared (2) */
+	__u64 sync_size;    /* 40  the size of the md device's sync range(3) */
+	__u32 state;        /* 48  bitmap state information */
+	__u32 chunksize;    /* 52  the bitmap chunk size in bytes */
+	__u32 daemon_sleep; /* 56  seconds between disk flushes */
+
+	__u8  pad[256 - 60]; /* set to zero */
+} bitmap_super_t;
+
+/* notes:
+ * (1) This event counter is updated before the eventcounter in the md superblock
+ *    When a bitmap is loaded, it is only accepted if this event counter is equal
+ *    to, or one greater than, the event counter in the superblock.
+ * (2) This event counter is updated when the other one is *if*and*only*if* the
+ *    array is not degraded.  As bits are not cleared when the array is degraded,
+ *    this represents the last time that any bits were cleared.
+ *    If a device is being added that has an event count with this value or
+ *    higher, it is accepted as conforming to the bitmap.
+ * (3)This is the number of sectors represented by the bitmap, and is the range that
+ *    resync happens across.  For raid1 and raid5/6 it is the size of individual
+ *    devices.  For raid10 it is the size of the array.
+ */
+
+#ifdef __KERNEL__
+
+/* the in-memory bitmap is represented by bitmap_pages */
+struct bitmap_page {
+	/*
+	 * map points to the actual memory page
+	 */
+	char *map;
+	/*
+	 * in emergencies (when map cannot be alloced), hijack the map
+	 * pointer and use it as two counters itself
+	 */
+	unsigned int hijacked:1;
+	/*
+	 * count of dirty bits on the page
+	 */
+	unsigned int  count:31;
+};
+
+/* keep track of bitmap file pages that have pending writes on them */
+struct page_list {
+	struct list_head list;
+	struct page *page;
+};
+
+/* the main bitmap structure - one per mddev */
+struct bitmap {
+	struct bitmap_page *bp;
+	unsigned long pages; /* total number of pages in the bitmap */
+	unsigned long missing_pages; /* number of pages not yet allocated */
+
+	mddev_t *mddev; /* the md device that the bitmap is for */
+
+	int counter_bits; /* how many bits per block counter */
+
+	/* bitmap chunksize -- how much data does each bit represent? */
+	unsigned long chunksize;
+	unsigned long chunkshift; /* chunksize = 2^chunkshift (for bitops) */
+	unsigned long chunks; /* total number of data chunks for the array */
+
+	/* We hold a count on the chunk currently being synced, and drop
+	 * it when the last block is started.  If the resync is aborted
+	 * midway, we need to be able to drop that count, so we remember
+	 * the counted chunk..
+	 */
+	unsigned long syncchunk;
+
+	__u64	events_cleared;
+
+	/* bitmap spinlock */
+	spinlock_t lock;
+
+	long offset; /* offset from superblock if file is NULL */
+	struct file *file; /* backing disk file */
+	struct page *sb_page; /* cached copy of the bitmap file superblock */
+	struct page **filemap; /* list of cache pages for the file */
+	unsigned long *filemap_attr; /* attributes associated w/ filemap pages */
+	unsigned long file_pages; /* number of pages in the file */
+
+	unsigned long flags;
+
+	/*
+	 * the bitmap daemon - periodically wakes up and sweeps the bitmap
+	 * file, cleaning up bits and flushing out pages to disk as necessary
+	 */
+	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;
+	wait_queue_head_t write_wait;
+	struct list_head complete_pages;
+	mempool_t *write_pool;
+};
+
+/* the bitmap API */
+
+/* these are used only by md/bitmap */
+int  bitmap_create(mddev_t *mddev);
+void bitmap_destroy(mddev_t *mddev);
+int  bitmap_active(struct bitmap *bitmap);
+
+char *file_path(struct file *file, char *buf, int count);
+void bitmap_print_sb(struct bitmap *bitmap);
+int bitmap_update_sb(struct bitmap *bitmap);
+
+int  bitmap_setallbits(struct bitmap *bitmap);
+void bitmap_write_all(struct bitmap *bitmap);
+
+/* these are exported */
+int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors);
+void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors,
+		     int success);
+int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks);
+void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted);
+void bitmap_close_sync(struct bitmap *bitmap);
+
+int bitmap_unplug(struct bitmap *bitmap);
+int bitmap_daemon_work(struct bitmap *bitmap);
+#endif
+
+#endif
diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h
index a6a67d1..ffa316c 100644
--- a/include/linux/raid/md.h
+++ b/include/linux/raid/md.h
@@ -60,7 +60,14 @@
  */
 #define MD_MAJOR_VERSION                0
 #define MD_MINOR_VERSION                90
-#define MD_PATCHLEVEL_VERSION           1
+/*
+ * MD_PATCHLEVEL_VERSION indicates kernel functionality.
+ * >=1 means different superblock formats are selectable using SET_ARRAY_INFO
+ *     and major_version/minor_version accordingly
+ * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT
+ *     in the super status byte
+ */
+#define MD_PATCHLEVEL_VERSION           2
 
 extern int register_md_personality (int p_num, mdk_personality_t *p);
 extern int unregister_md_personality (int p_num);
@@ -69,7 +76,7 @@
 extern void md_unregister_thread (mdk_thread_t *thread);
 extern void md_wakeup_thread(mdk_thread_t *thread);
 extern void md_check_recovery(mddev_t *mddev);
-extern void md_write_start(mddev_t *mddev);
+extern void md_write_start(mddev_t *mddev, struct bio *bi);
 extern void md_write_end(mddev_t *mddev);
 extern void md_handle_safemode(mddev_t *mddev);
 extern void md_done_sync(mddev_t *mddev, int blocks, int ok);
@@ -78,6 +85,12 @@
 
 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 int sync_page_io(struct block_device *bdev, sector_t sector, int size,
+			struct page *page, int rw);
+
+
 #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 c9a0d40..8c14ba5 100644
--- a/include/linux/raid/md_k.h
+++ b/include/linux/raid/md_k.h
@@ -15,6 +15,9 @@
 #ifndef _MD_K_H
 #define _MD_K_H
 
+/* and dm-bio-list.h is not under include/linux because.... ??? */
+#include "../../../drivers/md/dm-bio-list.h"
+
 #define MD_RESERVED       0UL
 #define LINEAR            1UL
 #define RAID0             2UL
@@ -180,6 +183,10 @@
 
 	int desc_nr;			/* descriptor index in the superblock */
 	int raid_disk;			/* role of device in array */
+	int saved_raid_disk;		/* role that device used to have in the
+					 * array and could again if we did a partial
+					 * resync from the bitmap
+					 */
 
 	atomic_t	nr_pending;	/* number of pending requests.
 					 * only maintained for arrays that
@@ -252,6 +259,11 @@
 	atomic_t			recovery_active; /* blocks scheduled, but not written */
 	wait_queue_head_t		recovery_wait;
 	sector_t			recovery_cp;
+
+	spinlock_t			write_lock;
+	wait_queue_head_t		sb_wait;	/* for waiting on superblock updates */
+	atomic_t			pending_writes;	/* number of active superblock writes */
+
 	unsigned int			safemode;	/* if set, update "clean" superblock
 							 * when no writes pending.
 							 */ 
@@ -260,6 +272,13 @@
 	atomic_t			writes_pending; 
 	request_queue_t			*queue;	/* for plugging ... */
 
+	struct bitmap                   *bitmap; /* the bitmap for the device */
+	struct file			*bitmap_file; /* the bitmap file */
+	long				bitmap_offset; /* offset from superblock of
+							* start of bitmap. May be
+							* negative, but not '0'
+							*/
+
 	struct list_head		all_mddevs;
 };
 
@@ -291,7 +310,7 @@
 	int (*hot_add_disk) (mddev_t *mddev, mdk_rdev_t *rdev);
 	int (*hot_remove_disk) (mddev_t *mddev, int number);
 	int (*spare_active) (mddev_t *mddev);
-	int (*sync_request)(mddev_t *mddev, sector_t sector_nr, int go_faster);
+	sector_t (*sync_request)(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster);
 	int (*resize) (mddev_t *mddev, sector_t sectors);
 	int (*reshape) (mddev_t *mddev, int raid_disks);
 	int (*reconfig) (mddev_t *mddev, int layout, int chunk_size);
@@ -334,6 +353,7 @@
 	unsigned long           flags;
 	struct completion	*event;
 	struct task_struct	*tsk;
+	unsigned long		timeout;
 	const char		*name;
 } mdk_thread_t;
 
diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h
index 8ba95d6..dc65cd4 100644
--- a/include/linux/raid/md_p.h
+++ b/include/linux/raid/md_p.h
@@ -96,6 +96,7 @@
 #define MD_SB_CLEAN		0
 #define MD_SB_ERRORS		1
 
+#define	MD_SB_BITMAP_PRESENT	8 /* bitmap may be present nearby */
 typedef struct mdp_superblock_s {
 	/*
 	 * Constant generic information
@@ -184,7 +185,7 @@
 	/* constant array information - 128 bytes */
 	__u32	magic;		/* MD_SB_MAGIC: 0xa92b4efc - little endian */
 	__u32	major_version;	/* 1 */
-	__u32	feature_map;	/* 0 for now */
+	__u32	feature_map;	/* bit 0 set if 'bitmap_offset' is meaningful */
 	__u32	pad0;		/* always set to 0 when writing */
 
 	__u8	set_uuid[16];	/* user-space generated. */
@@ -197,7 +198,11 @@
 
 	__u32	chunksize;	/* in 512byte sectors */
 	__u32	raid_disks;
-	__u8	pad1[128-96];	/* set to 0 when written */
+	__u32	bitmap_offset;	/* sectors after start of superblock that bitmap starts
+				 * NOTE: signed, so bitmap can be before superblock
+				 * only meaningful of feature_map[0] is set.
+				 */
+	__u8	pad1[128-100];	/* set to 0 when written */
 
 	/* constant this-device information - 64 bytes */
 	__u64	data_offset;	/* sector start of data, often 0 */
diff --git a/include/linux/raid/md_u.h b/include/linux/raid/md_u.h
index a2df5c2..81da20c 100644
--- a/include/linux/raid/md_u.h
+++ b/include/linux/raid/md_u.h
@@ -23,6 +23,7 @@
 #define GET_DISK_INFO		_IOR (MD_MAJOR, 0x12, mdu_disk_info_t)
 #define PRINT_RAID_DEBUG	_IO (MD_MAJOR, 0x13)
 #define RAID_AUTORUN		_IO (MD_MAJOR, 0x14)
+#define GET_BITMAP_FILE		_IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t)
 
 /* configuration */
 #define CLEAR_ARRAY		_IO (MD_MAJOR, 0x20)
@@ -36,6 +37,7 @@
 #define HOT_ADD_DISK		_IO (MD_MAJOR, 0x28)
 #define SET_DISK_FAULTY		_IO (MD_MAJOR, 0x29)
 #define HOT_GENERATE_ERROR	_IO (MD_MAJOR, 0x2a)
+#define SET_BITMAP_FILE		_IOW (MD_MAJOR, 0x2b, int)
 
 /* usage */
 #define RUN_ARRAY		_IOW (MD_MAJOR, 0x30, mdu_param_t)
@@ -106,6 +108,11 @@
 
 } mdu_start_info_t;
 
+typedef struct mdu_bitmap_file_s
+{
+	char pathname[4096];
+} mdu_bitmap_file_t;
+
 typedef struct mdu_param_s
 {
 	int			personality;	/* 1,2,3,4 */
diff --git a/include/linux/raid/raid1.h b/include/linux/raid/raid1.h
index abbfdd9..9d93cf1 100644
--- a/include/linux/raid/raid1.h
+++ b/include/linux/raid/raid1.h
@@ -36,12 +36,21 @@
 	spinlock_t		device_lock;
 
 	struct list_head	retry_list;
+	/* queue pending writes and submit them on unplug */
+	struct bio_list		pending_bio_list;
+	/* queue of writes that have been unplugged */
+	struct bio_list		flushing_bio_list;
+
 	/* for use when syncing mirrors: */
 
 	spinlock_t		resync_lock;
-	int nr_pending;
-	int barrier;
+	int			nr_pending;
+	int			barrier;
 	sector_t		next_resync;
+	int			fullsync;  /* set to 1 if a full sync is needed,
+					    * (fresh device added).
+					    * Cleared when a sync completes.
+					    */
 
 	wait_queue_head_t	wait_idle;
 	wait_queue_head_t	wait_resume;
@@ -85,14 +94,17 @@
 	int			read_disk;
 
 	struct list_head	retry_list;
+	struct bitmap_update	*bitmap_update;
 	/*
 	 * if the IO is in WRITE direction, then multiple bios are used.
 	 * We choose the number when they are allocated.
 	 */
 	struct bio		*bios[0];
+	/* DO NOT PUT ANY NEW FIELDS HERE - bios array is contiguously alloced*/
 };
 
 /* bits for r1bio.state */
 #define	R1BIO_Uptodate	0
 #define	R1BIO_IsSync	1
+#define	R1BIO_Degraded	2
 #endif
diff --git a/include/linux/reboot.h b/include/linux/reboot.h
index d60fafc..2d4dd23 100644
--- a/include/linux/reboot.h
+++ b/include/linux/reboot.h
@@ -51,6 +51,10 @@
 extern void machine_halt(void);
 extern void machine_power_off(void);
 
+extern void machine_shutdown(void);
+struct pt_regs;
+extern void machine_crash_shutdown(struct pt_regs *);
+
 #endif
 
 #endif /* _LINUX_REBOOT_H */
diff --git a/include/linux/reiserfs_acl.h b/include/linux/reiserfs_acl.h
index 2aef9c3..0760507 100644
--- a/include/linux/reiserfs_acl.h
+++ b/include/linux/reiserfs_acl.h
@@ -1,6 +1,5 @@
 #include <linux/init.h>
 #include <linux/posix_acl.h>
-#include <linux/xattr_acl.h>
 
 #define REISERFS_ACL_VERSION	0x0001
 
diff --git a/include/linux/reiserfs_fs.h b/include/linux/reiserfs_fs.h
index 3214862..4c7c568 100644
--- a/include/linux/reiserfs_fs.h
+++ b/include/linux/reiserfs_fs.h
@@ -1644,11 +1644,18 @@
 #define JOURNAL_MAX_TRANS_AGE 30
 #define JOURNAL_PER_BALANCE_CNT (3 * (MAX_HEIGHT-2) + 9)
 #ifdef CONFIG_QUOTA
-#define REISERFS_QUOTA_TRANS_BLOCKS 2	/* We need to update data and inode (atime) */
-#define REISERFS_QUOTA_INIT_BLOCKS (DQUOT_MAX_WRITES*(JOURNAL_PER_BALANCE_CNT+2)+1)	/* 1 balancing, 1 bitmap, 1 data per write + stat data update */
+/* We need to update data and inode (atime) */
+#define REISERFS_QUOTA_TRANS_BLOCKS(s) (REISERFS_SB(s)->s_mount_opt & (1<<REISERFS_QUOTA) ? 2 : 0)
+/* 1 balancing, 1 bitmap, 1 data per write + stat data update */
+#define REISERFS_QUOTA_INIT_BLOCKS(s) (REISERFS_SB(s)->s_mount_opt & (1<<REISERFS_QUOTA) ? \
+(DQUOT_INIT_ALLOC*(JOURNAL_PER_BALANCE_CNT+2)+DQUOT_INIT_REWRITE+1) : 0)
+/* same as with INIT */
+#define REISERFS_QUOTA_DEL_BLOCKS(s) (REISERFS_SB(s)->s_mount_opt & (1<<REISERFS_QUOTA) ? \
+(DQUOT_DEL_ALLOC*(JOURNAL_PER_BALANCE_CNT+2)+DQUOT_DEL_REWRITE+1) : 0)
 #else
-#define REISERFS_QUOTA_TRANS_BLOCKS 0
-#define REISERFS_QUOTA_INIT_BLOCKS 0
+#define REISERFS_QUOTA_TRANS_BLOCKS(s) 0
+#define REISERFS_QUOTA_INIT_BLOCKS(s) 0
+#define REISERFS_QUOTA_DEL_BLOCKS(s) 0
 #endif
 
 /* both of these can be as low as 1, or as high as you want.  The min is the
diff --git a/include/linux/reiserfs_fs_sb.h b/include/linux/reiserfs_fs_sb.h
index 37a3a7a..31c709d 100644
--- a/include/linux/reiserfs_fs_sb.h
+++ b/include/linux/reiserfs_fs_sb.h
@@ -467,6 +467,8 @@
     REISERFS_ERROR_RO,
     REISERFS_ERROR_CONTINUE,
 
+    REISERFS_QUOTA,		/* Some quota option specified */
+
     REISERFS_TEST1,
     REISERFS_TEST2,
     REISERFS_TEST3,
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index 11b484e..e80fb7ee 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -93,6 +93,12 @@
 int try_to_unmap(struct page *);
 
 /*
+ * Called from mm/filemap_xip.c to unmap empty zero page
+ */
+pte_t *page_check_address(struct page *, struct mm_struct *, unsigned long);
+
+
+/*
  * Used by swapoff to help locate where page is expected in vma.
  */
 unsigned long page_address_in_vma(struct page *, struct vm_area_struct *);
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 91ac97c..d021888 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -89,6 +89,13 @@
 	RTM_GETANYCAST	= 62,
 #define RTM_GETANYCAST	RTM_GETANYCAST
 
+	RTM_NEWNEIGHTBL	= 64,
+#define RTM_NEWNEIGHTBL	RTM_NEWNEIGHTBL
+	RTM_GETNEIGHTBL	= 66,
+#define RTM_GETNEIGHTBL	RTM_GETNEIGHTBL
+	RTM_SETNEIGHTBL,
+#define RTM_SETNEIGHTBL	RTM_SETNEIGHTBL
+
 	__RTM_MAX,
 #define RTM_MAX		(((__RTM_MAX + 3) & ~3) - 1)
 };
@@ -493,6 +500,106 @@
 	__u32		ndm_refcnt;
 };
 
+
+/*****************************************************************
+ *		Neighbour tables specific messages.
+ *
+ * To retrieve the neighbour tables send RTM_GETNEIGHTBL with the
+ * NLM_F_DUMP flag set. Every neighbour table configuration is
+ * spread over multiple messages to avoid running into message
+ * size limits on systems with many interfaces. The first message
+ * in the sequence transports all not device specific data such as
+ * statistics, configuration, and the default parameter set.
+ * This message is followed by 0..n messages carrying device
+ * specific parameter sets.
+ * Although the ordering should be sufficient, NDTA_NAME can be
+ * used to identify sequences. The initial message can be identified
+ * by checking for NDTA_CONFIG. The device specific messages do
+ * not contain this TLV but have NDTPA_IFINDEX set to the
+ * corresponding interface index.
+ *
+ * To change neighbour table attributes, send RTM_SETNEIGHTBL
+ * with NDTA_NAME set. Changeable attribute include NDTA_THRESH[1-3],
+ * NDTA_GC_INTERVAL, and all TLVs in NDTA_PARMS unless marked
+ * otherwise. Device specific parameter sets can be changed by
+ * setting NDTPA_IFINDEX to the interface index of the corresponding
+ * device.
+ ****/
+
+struct ndt_stats
+{
+	__u64		ndts_allocs;
+	__u64		ndts_destroys;
+	__u64		ndts_hash_grows;
+	__u64		ndts_res_failed;
+	__u64		ndts_lookups;
+	__u64		ndts_hits;
+	__u64		ndts_rcv_probes_mcast;
+	__u64		ndts_rcv_probes_ucast;
+	__u64		ndts_periodic_gc_runs;
+	__u64		ndts_forced_gc_runs;
+};
+
+enum {
+	NDTPA_UNSPEC,
+	NDTPA_IFINDEX,			/* u32, unchangeable */
+	NDTPA_REFCNT,			/* u32, read-only */
+	NDTPA_REACHABLE_TIME,		/* u64, read-only, msecs */
+	NDTPA_BASE_REACHABLE_TIME,	/* u64, msecs */
+	NDTPA_RETRANS_TIME,		/* u64, msecs */
+	NDTPA_GC_STALETIME,		/* u64, msecs */
+	NDTPA_DELAY_PROBE_TIME,		/* u64, msecs */
+	NDTPA_QUEUE_LEN,		/* u32 */
+	NDTPA_APP_PROBES,		/* u32 */
+	NDTPA_UCAST_PROBES,		/* u32 */
+	NDTPA_MCAST_PROBES,		/* u32 */
+	NDTPA_ANYCAST_DELAY,		/* u64, msecs */
+	NDTPA_PROXY_DELAY,		/* u64, msecs */
+	NDTPA_PROXY_QLEN,		/* u32 */
+	NDTPA_LOCKTIME,			/* u64, msecs */
+	__NDTPA_MAX
+};
+#define NDTPA_MAX (__NDTPA_MAX - 1)
+
+struct ndtmsg
+{
+	__u8		ndtm_family;
+	__u8		ndtm_pad1;
+	__u16		ndtm_pad2;
+};
+
+struct ndt_config
+{
+	__u16		ndtc_key_len;
+	__u16		ndtc_entry_size;
+	__u32		ndtc_entries;
+	__u32		ndtc_last_flush;	/* delta to now in msecs */
+	__u32		ndtc_last_rand;		/* delta to now in msecs */
+	__u32		ndtc_hash_rnd;
+	__u32		ndtc_hash_mask;
+	__u32		ndtc_hash_chain_gc;
+	__u32		ndtc_proxy_qlen;
+};
+
+enum {
+	NDTA_UNSPEC,
+	NDTA_NAME,			/* char *, unchangeable */
+	NDTA_THRESH1,			/* u32 */
+	NDTA_THRESH2,			/* u32 */
+	NDTA_THRESH3,			/* u32 */
+	NDTA_CONFIG,			/* struct ndt_config, read-only */
+	NDTA_PARMS,			/* nested TLV NDTPA_* */
+	NDTA_STATS,			/* struct ndt_stats, read-only */
+	NDTA_GC_INTERVAL,		/* u64, msecs */
+	__NDTA_MAX
+};
+#define NDTA_MAX (__NDTA_MAX - 1)
+
+#define NDTA_RTA(r) ((struct rtattr*)(((char*)(r)) + \
+		     NLMSG_ALIGN(sizeof(struct ndtmsg))))
+#define NDTA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndtmsg))
+
+
 /****
  *		General form of address family dependent message.
  ****/
@@ -785,10 +892,82 @@
 		 goto rtattr_failure; \
    	__rta_fill(skb, attrtype, attrlen, data); }) 
 
-#define RTA_PUT_NOHDR(skb, attrlen, data) \
+#define RTA_APPEND(skb, attrlen, data) \
 ({	if (unlikely(skb_tailroom(skb) < (int)(attrlen))) \
 		goto rtattr_failure; \
-	memcpy(skb_put(skb, RTA_ALIGN(attrlen)), data, attrlen); })
+	memcpy(skb_put(skb, attrlen), data, attrlen); })
+
+#define RTA_PUT_NOHDR(skb, attrlen, data) \
+	RTA_APPEND(skb, RTA_ALIGN(attrlen), data)
+
+#define RTA_PUT_U8(skb, attrtype, value) \
+({	u8 _tmp = (value); \
+	RTA_PUT(skb, attrtype, sizeof(u8), &_tmp); })
+
+#define RTA_PUT_U16(skb, attrtype, value) \
+({	u16 _tmp = (value); \
+	RTA_PUT(skb, attrtype, sizeof(u16), &_tmp); })
+
+#define RTA_PUT_U32(skb, attrtype, value) \
+({	u32 _tmp = (value); \
+	RTA_PUT(skb, attrtype, sizeof(u32), &_tmp); })
+
+#define RTA_PUT_U64(skb, attrtype, value) \
+({	u64 _tmp = (value); \
+	RTA_PUT(skb, attrtype, sizeof(u64), &_tmp); })
+
+#define RTA_PUT_SECS(skb, attrtype, value) \
+	RTA_PUT_U64(skb, attrtype, (value) / HZ)
+
+#define RTA_PUT_MSECS(skb, attrtype, value) \
+	RTA_PUT_U64(skb, attrtype, jiffies_to_msecs(value))
+
+#define RTA_PUT_STRING(skb, attrtype, value) \
+	RTA_PUT(skb, attrtype, strlen(value) + 1, value)
+
+#define RTA_PUT_FLAG(skb, attrtype) \
+	RTA_PUT(skb, attrtype, 0, NULL);
+
+#define RTA_NEST(skb, type) \
+({	struct rtattr *__start = (struct rtattr *) (skb)->tail; \
+	RTA_PUT(skb, type, 0, NULL); \
+	__start;  })
+
+#define RTA_NEST_END(skb, start) \
+({	(start)->rta_len = ((skb)->tail - (unsigned char *) (start)); \
+	(skb)->len; })
+
+#define RTA_NEST_CANCEL(skb, start) \
+({	if (start) \
+		skb_trim(skb, (unsigned char *) (start) - (skb)->data); \
+	-1; })
+
+#define RTA_GET_U8(rta) \
+({	if (!rta || RTA_PAYLOAD(rta) < sizeof(u8)) \
+		goto rtattr_failure; \
+	*(u8 *) RTA_DATA(rta); })
+
+#define RTA_GET_U16(rta) \
+({	if (!rta || RTA_PAYLOAD(rta) < sizeof(u16)) \
+		goto rtattr_failure; \
+	*(u16 *) RTA_DATA(rta); })
+
+#define RTA_GET_U32(rta) \
+({	if (!rta || RTA_PAYLOAD(rta) < sizeof(u32)) \
+		goto rtattr_failure; \
+	*(u32 *) RTA_DATA(rta); })
+
+#define RTA_GET_U64(rta) \
+({	u64 _tmp; \
+	if (!rta || RTA_PAYLOAD(rta) < sizeof(u64)) \
+		goto rtattr_failure; \
+	memcpy(&_tmp, RTA_DATA(rta), sizeof(_tmp)); \
+	_tmp; })
+
+#define RTA_GET_FLAG(rta) (!!(rta))
+
+#define RTA_GET_SECS(rta) ((unsigned long) RTA_GET_U64(rta) * HZ)
+#define RTA_GET_MSECS(rta) (msecs_to_jiffies((unsigned long) RTA_GET_U64(rta)))
 		
 static inline struct rtattr *
 __rta_reserve(struct sk_buff *skb, int attrtype, int attrlen)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 4dbb109..ff48815 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -201,8 +201,8 @@
 arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
 			  unsigned long len, unsigned long pgoff,
 			  unsigned long flags);
-extern void arch_unmap_area(struct vm_area_struct *area);
-extern void arch_unmap_area_topdown(struct vm_area_struct *area);
+extern void arch_unmap_area(struct mm_struct *, unsigned long);
+extern void arch_unmap_area_topdown(struct mm_struct *, unsigned long);
 
 #define set_mm_counter(mm, member, value) (mm)->_##member = (value)
 #define get_mm_counter(mm, member) ((mm)->_##member)
@@ -218,9 +218,10 @@
 	unsigned long (*get_unmapped_area) (struct file *filp,
 				unsigned long addr, unsigned long len,
 				unsigned long pgoff, unsigned long flags);
-	void (*unmap_area) (struct vm_area_struct *area);
-	unsigned long mmap_base;		/* base of mmap area */
-	unsigned long free_area_cache;		/* first hole */
+	void (*unmap_area) (struct mm_struct *mm, unsigned long addr);
+        unsigned long mmap_base;		/* base of mmap area */
+        unsigned long cached_hole_size;         /* if non-zero, the largest hole below free_area_cache */
+	unsigned long free_area_cache;		/* first hole of size cached_hole_size or larger */
 	pgd_t * pgd;
 	atomic_t mm_users;			/* How many users with user space? */
 	atomic_t mm_count;			/* How many references to "struct mm_struct" (users count as 1) */
@@ -245,7 +246,7 @@
 
 	unsigned long saved_auxv[42]; /* for /proc/PID/auxv */
 
-	unsigned dumpable:1;
+	unsigned dumpable:2;
 	cpumask_t cpu_vm_mask;
 
 	/* Architecture-specific MM context */
@@ -367,6 +368,11 @@
 #endif
 };
 
+/* Context switch must be unlocked if interrupts are to be enabled */
+#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
+# define __ARCH_WANT_UNLOCKED_CTXSW
+#endif
+
 /*
  * Bits in flags field of signal_struct.
  */
@@ -459,10 +465,11 @@
 #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 */
-#define SD_WAKE_IDLE		8	/* Wake to idle CPU on task wakeup */
-#define SD_WAKE_AFFINE		16	/* Wake task to waking CPU */
-#define SD_WAKE_BALANCE		32	/* Perform balancing at task wakeup */
-#define SD_SHARE_CPUPOWER	64	/* Domain members share cpu power */
+#define SD_BALANCE_FORK		8	/* Balance on fork, clone */
+#define SD_WAKE_IDLE		16	/* Wake to idle CPU on task wakeup */
+#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 */
 
 struct sched_group {
 	struct sched_group *next;	/* Must be a circular list */
@@ -487,6 +494,11 @@
 	unsigned long long cache_hot_time; /* Task considered cache hot (ns) */
 	unsigned int cache_nice_tries;	/* Leave cache hot tasks for # tries */
 	unsigned int per_cpu_gain;	/* CPU % gained by adding domain cpus */
+	unsigned int busy_idx;
+	unsigned int idle_idx;
+	unsigned int newidle_idx;
+	unsigned int wake_idx;
+	unsigned int forkexec_idx;
 	int flags;			/* See SD_* */
 
 	/* Runtime fields. */
@@ -510,10 +522,16 @@
 	unsigned long alb_failed;
 	unsigned long alb_pushed;
 
-	/* sched_balance_exec() stats */
-	unsigned long sbe_attempts;
+	/* SD_BALANCE_EXEC stats */
+	unsigned long sbe_cnt;
+	unsigned long sbe_balanced;
 	unsigned long sbe_pushed;
 
+	/* SD_BALANCE_FORK stats */
+	unsigned long sbf_cnt;
+	unsigned long sbf_balanced;
+	unsigned long sbf_pushed;
+
 	/* try_to_wake_up() stats */
 	unsigned long ttwu_wake_remote;
 	unsigned long ttwu_move_affine;
@@ -521,6 +539,8 @@
 #endif
 };
 
+extern void partition_sched_domains(cpumask_t *partition1,
+				    cpumask_t *partition2);
 #ifdef ARCH_HAS_SCHED_DOMAIN
 /* Useful helpers that arch setup code may use. Defined in kernel/sched.c */
 extern cpumask_t cpu_isolated_map;
@@ -560,9 +580,10 @@
 		groups_free(group_info); \
 } while (0)
 
-struct group_info *groups_alloc(int gidsetsize);
-void groups_free(struct group_info *group_info);
-int set_current_groups(struct group_info *group_info);
+extern struct group_info *groups_alloc(int gidsetsize);
+extern void groups_free(struct group_info *group_info);
+extern int set_current_groups(struct group_info *group_info);
+extern int groups_search(struct group_info *group_info, gid_t grp);
 /* access the groups "array" with this macro */
 #define GROUP_AT(gi, i) \
     ((gi)->blocks[(i)/NGROUPS_PER_BLOCK][(i)%NGROUPS_PER_BLOCK])
@@ -580,10 +601,15 @@
 
 	int lock_depth;		/* BKL lock depth */
 
+#if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
+	int oncpu;
+#endif
 	int prio, static_prio;
 	struct list_head run_list;
 	prio_array_t *array;
 
+	unsigned short ioprio;
+
 	unsigned long sleep_avg;
 	unsigned long long timestamp, last_ran;
 	unsigned long long sched_time; /* sched_clock time spent running */
@@ -659,6 +685,7 @@
 	struct user_struct *user;
 #ifdef CONFIG_KEYS
 	struct key *thread_keyring;	/* keyring private to this thread */
+	unsigned char jit_keyring;	/* default keyring to attach requested keys to */
 #endif
 	int oomkilladj; /* OOM kill score adjustment (bit shift). */
 	char comm[TASK_COMM_LEN]; /* executable name excluding path
@@ -701,8 +728,6 @@
 	spinlock_t alloc_lock;
 /* Protection of proc_dentry: nesting proc_lock, dcache_lock, write_lock_irq(&tasklist_lock); */
 	spinlock_t proc_lock;
-/* context-switch lock */
-	spinlock_t switch_lock;
 
 /* journalling filesystem info */
 	void *journal_info;
@@ -740,6 +765,7 @@
 	nodemask_t mems_allowed;
 	int cpuset_mems_generation;
 #endif
+	atomic_t fs_excl;	/* holding fs exclusive resources */
 };
 
 static inline pid_t process_group(struct task_struct *tsk)
@@ -909,7 +935,7 @@
 #else
  static inline void kick_process(struct task_struct *tsk) { }
 #endif
-extern void FASTCALL(sched_fork(task_t * p));
+extern void FASTCALL(sched_fork(task_t * p, int clone_flags));
 extern void FASTCALL(sched_exit(task_t * p));
 
 extern int in_group_p(gid_t);
@@ -1089,7 +1115,8 @@
 
 /*
  * Protects ->fs, ->files, ->mm, ->ptrace, ->group_info, ->comm, keyring
- * subscriptions and synchronises with wait4().  Also used in procfs.
+ * subscriptions and synchronises with wait4().  Also used in procfs.  Also
+ * pins the final release of task.io_context.
  *
  * Nests both inside and outside of read_lock(&tasklist_lock).
  * It must not be nested with write_lock_irq(&tasklist_lock),
@@ -1242,33 +1269,78 @@
 
 #endif
 
-/* try_to_freeze
- *
- * Checks whether we need to enter the refrigerator
- * and returns 1 if we did so.
- */
 #ifdef CONFIG_PM
-extern void refrigerator(unsigned long);
+/*
+ * Check if a process has been frozen
+ */
+static inline int frozen(struct task_struct *p)
+{
+	return p->flags & PF_FROZEN;
+}
+
+/*
+ * Check if there is a request to freeze a process
+ */
+static inline int freezing(struct task_struct *p)
+{
+	return p->flags & PF_FREEZE;
+}
+
+/*
+ * Request that a process be frozen
+ * FIXME: SMP problem. We may not modify other process' flags!
+ */
+static inline void freeze(struct task_struct *p)
+{
+	p->flags |= PF_FREEZE;
+}
+
+/*
+ * Wake up a frozen process
+ */
+static inline int thaw_process(struct task_struct *p)
+{
+	if (frozen(p)) {
+		p->flags &= ~PF_FROZEN;
+		wake_up_process(p);
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * freezing is complete, mark process as frozen
+ */
+static inline void frozen_process(struct task_struct *p)
+{
+	p->flags = (p->flags & ~PF_FREEZE) | PF_FROZEN;
+}
+
+extern void refrigerator(void);
 extern int freeze_processes(void);
 extern void thaw_processes(void);
 
-static inline int try_to_freeze(unsigned long refrigerator_flags)
+static inline int try_to_freeze(void)
 {
-	if (unlikely(current->flags & PF_FREEZE)) {
-		refrigerator(refrigerator_flags);
+	if (freezing(current)) {
+		refrigerator();
 		return 1;
 	} else
 		return 0;
 }
 #else
-static inline void refrigerator(unsigned long flag) {}
+static inline int frozen(struct task_struct *p) { return 0; }
+static inline int freezing(struct task_struct *p) { return 0; }
+static inline void freeze(struct task_struct *p) { BUG(); }
+static inline int thaw_process(struct task_struct *p) { return 1; }
+static inline void frozen_process(struct task_struct *p) { BUG(); }
+
+static inline void refrigerator(void) {}
 static inline int freeze_processes(void) { BUG(); return 0; }
 static inline void thaw_processes(void) {}
 
-static inline int try_to_freeze(unsigned long refrigerator_flags)
-{
-	return 0;
-}
+static inline int try_to_freeze(void) { return 0; }
+
 #endif /* CONFIG_PM */
 #endif /* __KERNEL__ */
 
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 0a98f5e..7be18b5 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -231,10 +231,8 @@
 extern long do_sigpending(void __user *, unsigned long);
 extern int sigprocmask(int, sigset_t *, sigset_t *);
 
-#ifndef HAVE_ARCH_GET_SIGNAL_TO_DELIVER
 struct pt_regs;
 extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie);
-#endif
 
 #endif /* __KERNEL__ */
 
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index cc04f5c..416a2e4 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -27,6 +27,7 @@
 #include <linux/highmem.h>
 #include <linux/poll.h>
 #include <linux/net.h>
+#include <linux/textsearch.h>
 #include <net/checksum.h>
 
 #define HAVE_ALLOC_SKB		/* For the drivers to know */
@@ -193,7 +194,6 @@
  *	@nfcache: Cache info
  *	@nfct: Associated connection, if any
  *	@nfctinfo: Relationship of this skb to the connection
- *	@nf_debug: Netfilter debugging
  *	@nf_bridge: Saved data about a bridged frame - see br_netfilter.c
  *      @private: Data which is private to the HIPPI implementation
  *	@tc_index: Traffic control index
@@ -264,9 +264,6 @@
 	__u32			nfcache;
 	__u32			nfctinfo;
 	struct nf_conntrack	*nfct;
-#ifdef CONFIG_NETFILTER_DEBUG
-        unsigned int		nf_debug;
-#endif
 #ifdef CONFIG_BRIDGE_NETFILTER
 	struct nf_bridge_info	*nf_bridge;
 #endif
@@ -325,6 +322,28 @@
 extern void	      skb_under_panic(struct sk_buff *skb, int len,
 				      void *here);
 
+struct skb_seq_state
+{
+	__u32		lower_offset;
+	__u32		upper_offset;
+	__u32		frag_idx;
+	__u32		stepped_offset;
+	struct sk_buff	*root_skb;
+	struct sk_buff	*cur_skb;
+	__u8		*frag_data;
+};
+
+extern void	      skb_prepare_seq_read(struct sk_buff *skb,
+					   unsigned int from, unsigned int to,
+					   struct skb_seq_state *st);
+extern unsigned int   skb_seq_read(unsigned int consumed, const u8 **data,
+				   struct skb_seq_state *st);
+extern void	      skb_abort_seq_read(struct skb_seq_state *st);
+
+extern unsigned int   skb_find_text(struct sk_buff *skb, unsigned int from,
+				    unsigned int to, struct ts_config *config,
+				    struct ts_state *state);
+
 /* Internal */
 #define skb_shinfo(SKB)		((struct skb_shared_info *)((SKB)->end))
 
@@ -1219,15 +1238,6 @@
 {
 	nf_conntrack_put(skb->nfct);
 	skb->nfct = NULL;
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#endif
-}
-static inline void nf_reset_debug(struct sk_buff *skb)
-{
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#endif
 }
 
 #ifdef CONFIG_BRIDGE_NETFILTER
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 7d66385..76cf7e6 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -64,6 +64,7 @@
 extern void *kmem_cache_alloc(kmem_cache_t *, unsigned int __nocast);
 extern void kmem_cache_free(kmem_cache_t *, void *);
 extern unsigned int kmem_cache_size(kmem_cache_t *);
+extern const char *kmem_cache_name(kmem_cache_t *);
 extern kmem_cache_t *kmem_find_general_cachep(size_t size, int gfpflags);
 
 /* Size description struct for general caches. */
diff --git a/include/linux/smp.h b/include/linux/smp.h
index dcf1db3..9dfa3ee 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -92,10 +92,7 @@
 /*
  *	These macros fold the SMP functionality into a single CPU system
  */
-
-#if !defined(__smp_processor_id) || !defined(CONFIG_PREEMPT)
-# define smp_processor_id()			0
-#endif
+#define raw_smp_processor_id()			0
 #define hard_smp_processor_id()			0
 #define smp_call_function(func,info,retry,wait)	({ 0; })
 #define on_each_cpu(func,info,retry,wait)	({ func(info); 0; })
@@ -106,30 +103,25 @@
 #endif /* !SMP */
 
 /*
- * DEBUG_PREEMPT support: check whether smp_processor_id() is being
- * used in a preemption-safe way.
+ * smp_processor_id(): get the current CPU ID.
  *
- * An architecture has to enable this debugging code explicitly.
- * It can do so by renaming the smp_processor_id() macro to
- * __smp_processor_id().  This should only be done after some minimal
- * testing, because usually there are a number of false positives
- * that an architecture will trigger.
+ * if DEBUG_PREEMPT is enabled the we check whether it is
+ * used in a preemption-safe way. (smp_processor_id() is safe
+ * if it's used in a preemption-off critical section, or in
+ * a thread that is bound to the current CPU.)
  *
- * To fix a false positive (i.e. smp_processor_id() use that the
- * debugging code reports but which use for some reason is legal),
- * change the smp_processor_id() reference to _smp_processor_id(),
- * which is the nondebug variant.  NOTE: don't use this to hack around
- * real bugs.
+ * NOTE: raw_smp_processor_id() is for internal use only
+ * (smp_processor_id() is the preferred variant), but in rare
+ * instances it might also be used to turn off false positives
+ * (i.e. smp_processor_id() use that the debugging code reports but
+ * which use for some reason is legal). Don't use this to hack around
+ * the warning message, as your code might not work under PREEMPT.
  */
-#ifdef __smp_processor_id
-# if defined(CONFIG_PREEMPT) && defined(CONFIG_DEBUG_PREEMPT)
-   extern unsigned int smp_processor_id(void);
-# else
-#  define smp_processor_id() __smp_processor_id()
-# endif
-# define _smp_processor_id() __smp_processor_id()
+#ifdef CONFIG_DEBUG_PREEMPT
+  extern unsigned int debug_smp_processor_id(void);
+# define smp_processor_id() debug_smp_processor_id()
 #else
-# define _smp_processor_id() smp_processor_id()
+# define smp_processor_id() raw_smp_processor_id()
 #endif
 
 #define get_cpu()		({ preempt_disable(); smp_processor_id(); })
diff --git a/include/linux/string.h b/include/linux/string.h
index b9fc594..93994c6 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -88,6 +88,8 @@
 extern void * memchr(const void *,int,__kernel_size_t);
 #endif
 
+extern char *kstrdup(const char *s, int gfp);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 2709caf..ab151bb 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -111,6 +111,11 @@
 struct rpc_clnt *rpc_create_client(struct rpc_xprt *xprt, char *servname,
 				struct rpc_program *info,
 				u32 version, rpc_authflavor_t authflavor);
+struct rpc_clnt *rpc_new_client(struct rpc_xprt *xprt, char *servname,
+				struct rpc_program *info,
+				u32 version, rpc_authflavor_t authflavor);
+struct rpc_clnt	*rpc_bind_new_program(struct rpc_clnt *,
+				struct rpc_program *, int);
 struct rpc_clnt *rpc_clone_client(struct rpc_clnt *);
 int		rpc_shutdown_client(struct rpc_clnt *);
 int		rpc_destroy_client(struct rpc_clnt *);
@@ -129,6 +134,7 @@
 void		rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset);
 void		rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
 size_t		rpc_max_payload(struct rpc_clnt *);
+int		rpc_ping(struct rpc_clnt *clnt, int flags);
 
 static __inline__
 int rpc_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 99d17ed..4d77e90 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -31,7 +31,6 @@
 struct rpc_wait {
 	struct list_head	list;		/* wait queue links */
 	struct list_head	links;		/* Links to related tasks */
-	wait_queue_head_t	waitq;		/* sync: sleep on this q */
 	struct rpc_wait_queue *	rpc_waitq;	/* RPC wait queue we're on */
 };
 
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 3700397..5af8800 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -185,6 +185,17 @@
 	return vec->iov_len <= PAGE_SIZE;
 }
 
+static inline struct page *
+svc_take_res_page(struct svc_rqst *rqstp)
+{
+	if (rqstp->rq_arghi <= rqstp->rq_argused)
+		return NULL;
+	rqstp->rq_arghi--;
+	rqstp->rq_respages[rqstp->rq_resused] =
+		rqstp->rq_argpages[rqstp->rq_arghi];
+	return rqstp->rq_respages[rqstp->rq_resused++];
+}
+
 static inline int svc_take_page(struct svc_rqst *rqstp)
 {
 	if (rqstp->rq_arghi <= rqstp->rq_argused)
@@ -240,9 +251,10 @@
 };
 
 /*
- * RPC program
+ * List of RPC programs on the same transport endpoint
  */
 struct svc_program {
+	struct svc_program *	pg_next;	/* other programs (same xprt) */
 	u32			pg_prog;	/* program number */
 	unsigned int		pg_lovers;	/* lowest version */
 	unsigned int		pg_hivers;	/* lowest version */
diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h
index 541dcf8..34ec3e8 100644
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -146,7 +146,8 @@
 extern void xdr_buf_from_iov(struct kvec *, struct xdr_buf *);
 extern int xdr_buf_subsegment(struct xdr_buf *, struct xdr_buf *, int, int);
 extern int xdr_buf_read_netobj(struct xdr_buf *, struct xdr_netobj *, int);
-extern int read_bytes_from_xdr_buf(struct xdr_buf *buf, int base, void *obj, int len);
+extern int read_bytes_from_xdr_buf(struct xdr_buf *, int, void *, int);
+extern int write_bytes_to_xdr_buf(struct xdr_buf *, int, void *, int);
 
 /*
  * Helper structure for copying from an sk_buff.
@@ -160,7 +161,7 @@
 
 typedef size_t (*skb_read_actor_t)(skb_reader_t *desc, void *to, size_t len);
 
-extern void xdr_partial_copy_from_skb(struct xdr_buf *, unsigned int,
+extern ssize_t xdr_partial_copy_from_skb(struct xdr_buf *, unsigned int,
 		skb_reader_t *, skb_read_actor_t);
 
 struct socket;
@@ -168,6 +169,22 @@
 extern int xdr_sendpages(struct socket *, struct sockaddr *, int,
 		struct xdr_buf *, unsigned int, int);
 
+extern int xdr_encode_word(struct xdr_buf *, int, u32);
+extern int xdr_decode_word(struct xdr_buf *, int, u32 *);
+
+struct xdr_array2_desc;
+typedef int (*xdr_xcode_elem_t)(struct xdr_array2_desc *desc, void *elem);
+struct xdr_array2_desc {
+	unsigned int elem_size;
+	unsigned int array_len;
+	xdr_xcode_elem_t xcode;
+};
+
+extern int xdr_decode_array2(struct xdr_buf *buf, unsigned int base,
+                             struct xdr_array2_desc *desc);
+extern int xdr_encode_array2(struct xdr_buf *buf, unsigned int base,
+			     struct xdr_array2_desc *desc);
+
 /*
  * Provide some simple tools for XDR buffer overflow-checking etc.
  */
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 2bf0d5f..f2e96fd 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -58,7 +58,7 @@
 }
 #endif
 
-#ifdef CONFIG_SMP
+#ifdef CONFIG_SUSPEND_SMP
 extern void disable_nonboot_cpus(void);
 extern void enable_nonboot_cpus(void);
 #else
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 3bbc41b..2343f99 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -172,7 +172,8 @@
 extern void swap_setup(void);
 
 /* linux/mm/vmscan.c */
-extern int try_to_free_pages(struct zone **, unsigned int, unsigned int);
+extern int try_to_free_pages(struct zone **, unsigned int);
+extern int zone_reclaim(struct zone *, unsigned int, unsigned int);
 extern int shrink_all_memory(int);
 extern int vm_swappiness;
 
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index c39f6f7..52830b6 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -159,8 +159,9 @@
 asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd,
 				void __user *arg);
 asmlinkage long sys_restart_syscall(void);
-asmlinkage long sys_kexec_load(void *entry, unsigned long nr_segments,
-			struct kexec_segment *segments, unsigned long flags);
+asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments,
+				struct kexec_segment __user *segments,
+				unsigned long flags);
 
 asmlinkage long sys_exit(int error_code);
 asmlinkage void sys_exit_group(int error_code);
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 23032d9..ebfe125 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -136,6 +136,7 @@
 	KERN_UNKNOWN_NMI_PANIC=66, /* int: unknown nmi panic flag */
 	KERN_BOOTLOADER_TYPE=67, /* int: boot loader type */
 	KERN_RANDOMIZE=68, /* int: randomize virtual address space */
+	KERN_SETUID_DUMPABLE=69, /* int: behaviour of dumps for setuid core */
 };
 
 
@@ -242,6 +243,7 @@
 	NET_CORE_MOD_CONG=16,
 	NET_CORE_DEV_WEIGHT=17,
 	NET_CORE_SOMAXCONN=18,
+	NET_CORE_BUDGET=19,
 };
 
 /* /proc/sys/net/ethernet */
@@ -332,20 +334,14 @@
 	NET_TCP_FRTO=92,
 	NET_TCP_LOW_LATENCY=93,
 	NET_IPV4_IPFRAG_SECRET_INTERVAL=94,
-	NET_TCP_WESTWOOD=95,
 	NET_IPV4_IGMP_MAX_MSF=96,
 	NET_TCP_NO_METRICS_SAVE=97,
-	NET_TCP_VEGAS=98,
-	NET_TCP_VEGAS_ALPHA=99,
-	NET_TCP_VEGAS_BETA=100,
-	NET_TCP_VEGAS_GAMMA=101,
- 	NET_TCP_BIC=102,
- 	NET_TCP_BIC_FAST_CONVERGENCE=103,
-	NET_TCP_BIC_LOW_WINDOW=104,
 	NET_TCP_DEFAULT_WIN_SCALE=105,
 	NET_TCP_MODERATE_RCVBUF=106,
 	NET_TCP_TSO_WIN_DIVISOR=107,
 	NET_TCP_BIC_BETA=108,
+	NET_IPV4_ICMP_ERRORS_USE_INBOUND_IFADDR=109,
+	NET_TCP_CONG_CONTROL=110,
 };
 
 enum {
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 38b58b3..392da5a 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -16,13 +16,13 @@
 struct module;
 
 struct attribute {
-	char			* name;
+	const char		* name;
 	struct module 		* owner;
 	mode_t			mode;
 };
 
 struct attribute_group {
-	char			* name;
+	const char		* name;
 	struct attribute	** attrs;
 };
 
@@ -73,6 +73,7 @@
 	int			s_type;
 	umode_t			s_mode;
 	struct dentry		* s_dentry;
+	struct iattr		* s_iattr;
 };
 
 #define SYSFS_ROOT		0x0001
@@ -105,11 +106,11 @@
 extern void
 sysfs_remove_file(struct kobject *, const struct attribute *);
 
-extern int 
-sysfs_create_link(struct kobject * kobj, struct kobject * target, char * name);
+extern int
+sysfs_create_link(struct kobject * kobj, struct kobject * target, const char * name);
 
 extern void
-sysfs_remove_link(struct kobject *, char * name);
+sysfs_remove_link(struct kobject *, const char * name);
 
 int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr);
 int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr);
@@ -153,12 +154,12 @@
 	;
 }
 
-static inline int sysfs_create_link(struct kobject * k, struct kobject * t, char * n)
+static inline int sysfs_create_link(struct kobject * k, struct kobject * t, const char * n)
 {
 	return 0;
 }
 
-static inline void sysfs_remove_link(struct kobject * k, char * name)
+static inline void sysfs_remove_link(struct kobject * k, const char * name)
 {
 	;
 }
diff --git a/include/linux/tc_ematch/tc_em_meta.h b/include/linux/tc_ematch/tc_em_meta.h
index aa6b48bb..a6b2cc5 100644
--- a/include/linux/tc_ematch/tc_em_meta.h
+++ b/include/linux/tc_ematch/tc_em_meta.h
@@ -56,6 +56,36 @@
 	TCF_META_ID_TCCLASSID,
 	TCF_META_ID_RTCLASSID,
 	TCF_META_ID_RTIIF,
+	TCF_META_ID_SK_FAMILY,
+	TCF_META_ID_SK_STATE,
+	TCF_META_ID_SK_REUSE,
+	TCF_META_ID_SK_BOUND_IF,
+	TCF_META_ID_SK_REFCNT,
+	TCF_META_ID_SK_SHUTDOWN,
+	TCF_META_ID_SK_PROTO,
+	TCF_META_ID_SK_TYPE,
+	TCF_META_ID_SK_RCVBUF,
+	TCF_META_ID_SK_RMEM_ALLOC,
+	TCF_META_ID_SK_WMEM_ALLOC,
+	TCF_META_ID_SK_OMEM_ALLOC,
+	TCF_META_ID_SK_WMEM_QUEUED,
+	TCF_META_ID_SK_RCV_QLEN,
+	TCF_META_ID_SK_SND_QLEN,
+ 	TCF_META_ID_SK_ERR_QLEN,
+	TCF_META_ID_SK_FORWARD_ALLOCS,
+	TCF_META_ID_SK_SNDBUF,
+ 	TCF_META_ID_SK_ALLOCS,
+ 	TCF_META_ID_SK_ROUTE_CAPS,
+ 	TCF_META_ID_SK_HASHENT,
+ 	TCF_META_ID_SK_LINGERTIME,
+ 	TCF_META_ID_SK_ACK_BACKLOG,
+ 	TCF_META_ID_SK_MAX_ACK_BACKLOG,
+ 	TCF_META_ID_SK_PRIO,
+ 	TCF_META_ID_SK_RCVLOWAT,
+ 	TCF_META_ID_SK_RCVTIMEO,
+ 	TCF_META_ID_SK_SNDTIMEO,
+ 	TCF_META_ID_SK_SENDMSG_OFF,
+ 	TCF_META_ID_SK_WRITE_PENDING,
 	__TCF_META_ID_MAX
 };
 #define TCF_META_ID_MAX (__TCF_META_ID_MAX - 1)
diff --git a/include/linux/tc_ematch/tc_em_text.h b/include/linux/tc_ematch/tc_em_text.h
new file mode 100644
index 0000000..7cd43e9
--- /dev/null
+++ b/include/linux/tc_ematch/tc_em_text.h
@@ -0,0 +1,19 @@
+#ifndef __LINUX_TC_EM_TEXT_H
+#define __LINUX_TC_EM_TEXT_H
+
+#include <linux/pkt_cls.h>
+
+#define TC_EM_TEXT_ALGOSIZ	16
+
+struct tcf_em_text
+{
+	char		algo[TC_EM_TEXT_ALGOSIZ];
+	__u16		from_offset;
+	__u16		to_offset;
+	__u16		pattern_len;
+	__u8		from_layer:4;
+	__u8		to_layer:4;
+	__u8		pad;
+};
+
+#endif
diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 14a55e3..dfd93d0 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -127,6 +127,7 @@
 #define TCP_WINDOW_CLAMP	10	/* Bound advertised window */
 #define TCP_INFO		11	/* Information about this connection. */
 #define TCP_QUICKACK		12	/* Block/reenable quick acks */
+#define TCP_CONGESTION		13	/* Congestion control algorithm */
 
 #define TCPI_OPT_TIMESTAMPS	1
 #define TCPI_OPT_SACK		2
@@ -203,13 +204,6 @@
 	__u32	end_seq;
 };
 
-enum tcp_congestion_algo {
-	TCP_RENO=0,
-	TCP_VEGAS,
-	TCP_WESTWOOD,
-	TCP_BIC,
-};
-
 struct tcp_options_received {
 /*	PAWS/RTTM data	*/
 	long	ts_recent_stamp;/* Time we stored ts_recent (for aging) */
@@ -230,6 +224,17 @@
 	__u16	mss_clamp;	/* Maximal mss, negotiated at connection setup */
 };
 
+struct tcp_request_sock {
+	struct inet_request_sock req;
+	__u32			 rcv_isn;
+	__u32			 snt_isn;
+};
+
+static inline struct tcp_request_sock *tcp_rsk(const struct request_sock *req)
+{
+	return (struct tcp_request_sock *)req;
+}
+
 struct tcp_sock {
 	/* inet_sock has to be the first member of tcp_sock */
 	struct inet_sock	inet;
@@ -294,7 +299,7 @@
 	__u8	reordering;	/* Packet reordering metric.		*/
 	__u8	frto_counter;	/* Number of new acks after RTO */
 
-	__u8	adv_cong;	/* Using Vegas, Westwood, or BIC */
+	__u8	unused;
 	__u8	defer_accept;	/* User waits for some data after accept() */
 
 /* RTT measurement */
@@ -368,22 +373,7 @@
 
 	__u32	total_retrans;	/* Total retransmits for entire connection */
 
-	/* The syn_wait_lock is necessary only to avoid proc interface having
-	 * to grab the main lock sock while browsing the listening hash
-	 * (otherwise it's deadlock prone).
-	 * This lock is acquired in read mode only from listening_get_next()
-	 * and it's acquired in write mode _only_ from code that is actively
-	 * changing the syn_wait_queue. All readers that are holding
-	 * the master sock lock don't need to grab this lock in read mode
-	 * too as the syn_wait_queue writes are always protected from
-	 * the main sock lock.
-	 */
-	rwlock_t		syn_wait_lock;
-	struct tcp_listen_opt	*listen_opt;
-
-	/* FIFO of established children */
-	struct open_request	*accept_queue;
-	struct open_request	*accept_queue_tail;
+	struct request_sock_queue accept_queue; /* FIFO of established children */
 
 	unsigned int		keepalive_time;	  /* time before keep alive takes place */
 	unsigned int		keepalive_intvl;  /* time interval between keep alive probes */
@@ -405,37 +395,10 @@
 		__u32	time;
 	} rcvq_space;
 
-/* TCP Westwood structure */
-        struct {
-                __u32    bw_ns_est;        /* first bandwidth estimation..not too smoothed 8) */
-                __u32    bw_est;           /* bandwidth estimate */
-                __u32    rtt_win_sx;       /* here starts a new evaluation... */
-                __u32    bk;
-                __u32    snd_una;          /* used for evaluating the number of acked bytes */
-                __u32    cumul_ack;
-                __u32    accounted;
-                __u32    rtt;
-                __u32    rtt_min;          /* minimum observed RTT */
-        } westwood;
-
-/* Vegas variables */
-	struct {
-		__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) */
-	} vegas;
-
-	/* BI TCP Parameters */
-	struct {
-		__u32	cnt;		/* increase cwnd by 1 after this number of ACKs */
-		__u32 	last_max_cwnd;	/* last maximium snd_cwnd */
-		__u32	last_cwnd;	/* the last snd_cwnd */
-		__u32   last_stamp;     /* time when updated last_cwnd */
-	} bictcp;
+	/* Pluggable TCP congestion control hook */
+	struct tcp_congestion_ops *ca_ops;
+	u32	ca_priv[16];
+#define TCP_CA_PRIV_SIZE	(16*sizeof(u32))
 };
 
 static inline struct tcp_sock *tcp_sk(const struct sock *sk)
@@ -443,6 +406,11 @@
 	return (struct tcp_sock *)sk;
 }
 
+static inline void *tcp_ca(const struct tcp_sock *tp)
+{
+	return (void *) tp->ca_priv;
+}
+
 #endif
 
 #endif	/* _LINUX_TCP_H */
diff --git a/include/linux/tcp_diag.h b/include/linux/tcp_diag.h
index ceee962..7a59967 100644
--- a/include/linux/tcp_diag.h
+++ b/include/linux/tcp_diag.h
@@ -99,9 +99,10 @@
 	TCPDIAG_MEMINFO,
 	TCPDIAG_INFO,
 	TCPDIAG_VEGASINFO,
+	TCPDIAG_CONG,
 };
 
-#define TCPDIAG_MAX TCPDIAG_VEGASINFO
+#define TCPDIAG_MAX TCPDIAG_CONG
 
 
 /* TCPDIAG_MEM */
@@ -123,5 +124,4 @@
 	__u32	tcpv_minrtt;
 };
 
-
 #endif /* _TCP_DIAG_H_ */
diff --git a/include/linux/textsearch.h b/include/linux/textsearch.h
new file mode 100644
index 0000000..941f45a
--- /dev/null
+++ b/include/linux/textsearch.h
@@ -0,0 +1,180 @@
+#ifndef __LINUX_TEXTSEARCH_H
+#define __LINUX_TEXTSEARCH_H
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+
+struct ts_config;
+
+/**
+ * TS_AUTOLOAD - Automatically load textsearch modules when needed
+ */
+#define TS_AUTOLOAD	1
+
+/**
+ * struct ts_state - search state
+ * @offset: offset for next match
+ * @cb: control buffer, for persistant variables of get_next_block()
+ */
+struct ts_state
+{
+	unsigned int		offset;
+	char			cb[40];
+};
+
+/**
+ * struct ts_ops - search module operations
+ * @name: name of search algorithm
+ * @init: initialization function to prepare a search
+ * @find: find the next occurrence of the pattern
+ * @destroy: destroy algorithm specific parts of a search configuration
+ * @get_pattern: return head of pattern
+ * @get_pattern_len: return length of pattern
+ * @owner: module reference to algorithm
+ */
+struct ts_ops
+{
+	const char		*name;
+	struct ts_config *	(*init)(const void *, unsigned int, int);
+	unsigned int		(*find)(struct ts_config *,
+					struct ts_state *);
+	void			(*destroy)(struct ts_config *);
+	void *			(*get_pattern)(struct ts_config *);
+	unsigned int		(*get_pattern_len)(struct ts_config *);
+	struct module		*owner;
+	struct list_head	list;
+};
+
+/**
+ * struct ts_config - search configuration
+ * @ops: operations of chosen algorithm
+ * @get_next_block: callback to fetch the next block to search in
+ * @finish: callback to finalize a search
+ */
+struct ts_config
+{
+	struct ts_ops		*ops;
+
+	/**
+	 * get_next_block - fetch next block of data
+	 * @consumed: number of bytes consumed by the caller
+	 * @dst: destination buffer
+	 * @conf: search configuration
+	 * @state: search state
+	 *
+	 * Called repeatedly until 0 is returned. Must assign the
+	 * head of the next block of data to &*dst and return the length
+	 * of the block or 0 if at the end. consumed == 0 indicates
+	 * a new search. May store/read persistant values in state->cb.
+	 */
+	unsigned int		(*get_next_block)(unsigned int consumed,
+						  const u8 **dst,
+						  struct ts_config *conf,
+						  struct ts_state *state);
+
+	/**
+	 * finish - finalize/clean a series of get_next_block() calls
+	 * @conf: search configuration
+	 * @state: search state
+	 *
+	 * Called after the last use of get_next_block(), may be used
+	 * to cleanup any leftovers.
+	 */
+	void			(*finish)(struct ts_config *conf,
+					  struct ts_state *state);
+};
+
+/**
+ * textsearch_next - continue searching for a pattern
+ * @conf: search configuration
+ * @state: search state
+ *
+ * Continues a search looking for more occurrences of the pattern.
+ * textsearch_find() must be called to find the first occurrence
+ * in order to reset the state.
+ *
+ * Returns the position of the next occurrence of the pattern or
+ * UINT_MAX if not match was found.
+ */ 
+static inline unsigned int textsearch_next(struct ts_config *conf,
+					   struct ts_state *state)
+{
+	unsigned int ret = conf->ops->find(conf, state);
+
+	if (conf->finish)
+		conf->finish(conf, state);
+
+	return ret;
+}
+
+/**
+ * textsearch_find - start searching for a pattern
+ * @conf: search configuration
+ * @state: search state
+ *
+ * Returns the position of first occurrence of the pattern or
+ * UINT_MAX if no match was found.
+ */ 
+static inline unsigned int textsearch_find(struct ts_config *conf,
+					   struct ts_state *state)
+{
+	state->offset = 0;
+	return textsearch_next(conf, state);
+}
+
+/**
+ * textsearch_get_pattern - return head of the pattern
+ * @conf: search configuration
+ */
+static inline void *textsearch_get_pattern(struct ts_config *conf)
+{
+	return conf->ops->get_pattern(conf);
+}
+
+/**
+ * textsearch_get_pattern_len - return length of the pattern
+ * @conf: search configuration
+ */
+static inline unsigned int textsearch_get_pattern_len(struct ts_config *conf)
+{
+	return conf->ops->get_pattern_len(conf);
+}
+
+extern int textsearch_register(struct ts_ops *);
+extern int textsearch_unregister(struct ts_ops *);
+extern struct ts_config *textsearch_prepare(const char *, const void *,
+					    unsigned int, int, int);
+extern void textsearch_destroy(struct ts_config *conf);
+extern unsigned int textsearch_find_continuous(struct ts_config *,
+					       struct ts_state *,
+					       const void *, unsigned int);
+
+
+#define TS_PRIV_ALIGNTO	8
+#define TS_PRIV_ALIGN(len) (((len) + TS_PRIV_ALIGNTO-1) & ~(TS_PRIV_ALIGNTO-1))
+
+static inline struct ts_config *alloc_ts_config(size_t payload, int gfp_mask)
+{
+	struct ts_config *conf;
+
+	conf = kmalloc(TS_PRIV_ALIGN(sizeof(*conf)) + payload, gfp_mask);
+	if (conf == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	memset(conf, 0, TS_PRIV_ALIGN(sizeof(*conf)) + payload);
+	return conf;
+}
+
+static inline void *ts_config_priv(struct ts_config *conf)
+{
+	return ((u8 *) conf + TS_PRIV_ALIGN(sizeof(struct ts_config)));
+}
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/include/linux/textsearch_fsm.h b/include/linux/textsearch_fsm.h
new file mode 100644
index 0000000..fdfa078
--- /dev/null
+++ b/include/linux/textsearch_fsm.h
@@ -0,0 +1,48 @@
+#ifndef __LINUX_TEXTSEARCH_FSM_H
+#define __LINUX_TEXTSEARCH_FSM_H
+
+#include <linux/types.h>
+
+enum {
+	TS_FSM_SPECIFIC,	/* specific character */
+	TS_FSM_WILDCARD,	/* any character */
+	TS_FSM_DIGIT,		/* isdigit() */
+	TS_FSM_XDIGIT,		/* isxdigit() */
+	TS_FSM_PRINT,		/* isprint() */
+	TS_FSM_ALPHA,		/* isalpha() */
+	TS_FSM_ALNUM,		/* isalnum() */
+	TS_FSM_ASCII,		/* isascii() */
+	TS_FSM_CNTRL,		/* iscntrl() */
+	TS_FSM_GRAPH,		/* isgraph() */
+	TS_FSM_LOWER,		/* islower() */
+	TS_FSM_UPPER,		/* isupper() */
+	TS_FSM_PUNCT,		/* ispunct() */
+	TS_FSM_SPACE,		/* isspace() */
+	__TS_FSM_TYPE_MAX,
+};
+#define TS_FSM_TYPE_MAX (__TS_FSM_TYPE_MAX - 1)
+
+enum {
+	TS_FSM_SINGLE,		/* 1 occurrence */
+	TS_FSM_PERHAPS,		/* 1 or 0 occurrence */
+	TS_FSM_ANY,		/* 0..n occurrences */
+	TS_FSM_MULTI,		/* 1..n occurrences */
+	TS_FSM_HEAD_IGNORE,	/* 0..n ignored occurrences at head */
+	__TS_FSM_RECUR_MAX,
+};
+#define TS_FSM_RECUR_MAX (__TS_FSM_RECUR_MAX - 1)
+
+/**
+ * struct ts_fsm_token - state machine token (state)
+ * @type: type of token
+ * @recur: number of recurrences
+ * @value: character value for TS_FSM_SPECIFIC
+ */
+struct ts_fsm_token
+{
+	__u16		type;
+	__u8		recur;
+	__u8		value;
+};
+
+#endif
diff --git a/include/linux/timer.h b/include/linux/timer.h
index 90db1cc..221f81a 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -6,45 +6,33 @@
 #include <linux/spinlock.h>
 #include <linux/stddef.h>
 
-struct tvec_t_base_s;
+struct timer_base_s;
 
 struct timer_list {
 	struct list_head entry;
 	unsigned long expires;
 
-	spinlock_t lock;
 	unsigned long magic;
 
 	void (*function)(unsigned long);
 	unsigned long data;
 
-	struct tvec_t_base_s *base;
+	struct timer_base_s *base;
 };
 
 #define TIMER_MAGIC	0x4b87ad6e
 
+extern struct timer_base_s __init_timer_base;
+
 #define TIMER_INITIALIZER(_function, _expires, _data) {		\
 		.function = (_function),			\
 		.expires = (_expires),				\
 		.data = (_data),				\
-		.base = NULL,					\
+		.base = &__init_timer_base,			\
 		.magic = TIMER_MAGIC,				\
-		.lock = SPIN_LOCK_UNLOCKED,			\
 	}
 
-/***
- * init_timer - initialize a timer.
- * @timer: the timer to be initialized
- *
- * init_timer() must be done to a timer prior calling *any* of the
- * other timer functions.
- */
-static inline void init_timer(struct timer_list * timer)
-{
-	timer->base = NULL;
-	timer->magic = TIMER_MAGIC;
-	spin_lock_init(&timer->lock);
-}
+void fastcall init_timer(struct timer_list * timer);
 
 /***
  * timer_pending - is a timer pending?
@@ -58,7 +46,7 @@
  */
 static inline int timer_pending(const struct timer_list * timer)
 {
-	return timer->base != NULL;
+	return timer->entry.next != NULL;
 }
 
 extern void add_timer_on(struct timer_list *timer, int cpu);
@@ -88,13 +76,15 @@
 }
 
 #ifdef CONFIG_SMP
+  extern int try_to_del_timer_sync(struct timer_list *timer);
   extern int del_timer_sync(struct timer_list *timer);
-  extern int del_singleshot_timer_sync(struct timer_list *timer);
 #else
-# define del_timer_sync(t) del_timer(t)
-# define del_singleshot_timer_sync(t) del_timer(t)
+# define try_to_del_timer_sync(t)	del_timer(t)
+# define del_timer_sync(t)		del_timer(t)
 #endif
 
+#define del_singleshot_timer_sync(t) del_timer_sync(t)
+
 extern void init_timers(void);
 extern void run_local_timers(void);
 extern void it_real_fn(unsigned long);
diff --git a/include/linux/topology.h b/include/linux/topology.h
index d70e897..0320225 100644
--- a/include/linux/topology.h
+++ b/include/linux/topology.h
@@ -89,6 +89,11 @@
 	.cache_hot_time		= 0,			\
 	.cache_nice_tries	= 0,			\
 	.per_cpu_gain		= 25,			\
+	.busy_idx		= 0,			\
+	.idle_idx		= 0,			\
+	.newidle_idx		= 1,			\
+	.wake_idx		= 0,			\
+	.forkexec_idx		= 0,			\
 	.flags			= SD_LOAD_BALANCE	\
 				| SD_BALANCE_NEWIDLE	\
 				| SD_BALANCE_EXEC	\
@@ -115,12 +120,15 @@
 	.cache_hot_time		= (5*1000000/2),	\
 	.cache_nice_tries	= 1,			\
 	.per_cpu_gain		= 100,			\
+	.busy_idx		= 2,			\
+	.idle_idx		= 1,			\
+	.newidle_idx		= 2,			\
+	.wake_idx		= 1,			\
+	.forkexec_idx		= 1,			\
 	.flags			= SD_LOAD_BALANCE	\
 				| SD_BALANCE_NEWIDLE	\
 				| SD_BALANCE_EXEC	\
-				| SD_WAKE_AFFINE	\
-				| SD_WAKE_IDLE		\
-				| SD_WAKE_BALANCE,	\
+				| SD_WAKE_AFFINE,	\
 	.last_balance		= jiffies,		\
 	.balance_interval	= 1,			\
 	.nr_balance_failed	= 0,			\
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 1b76106..59ff42c 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -345,6 +345,7 @@
 extern void stop_tty(struct tty_struct * tty);
 extern void start_tty(struct tty_struct * tty);
 extern int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc);
+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);
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 2d1ac50..eb282b5 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -287,15 +287,14 @@
 
 	struct dentry *usbfs_dentry;	/* usbfs dentry entry for the bus */
 
-	struct class_device class_dev;	/* class device for this bus */
+	struct class_device *class_dev;	/* class device for this bus */
+	struct kref kref;		/* handles reference counting this bus */
 	void (*release)(struct usb_bus *bus);	/* function to destroy this bus's memory */
-#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
+#if defined(CONFIG_USB_MON)
 	struct mon_bus *mon_bus;	/* non-null when associated */
 	int monitored;			/* non-zero when monitored */
 #endif
 };
-#define	to_usb_bus(d) container_of(d, struct usb_bus, class_dev)
-
 
 /* -------------------------------------------------------------------------- */
 
diff --git a/include/linux/wait.h b/include/linux/wait.h
index c9486c3..d38c9fe 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -33,7 +33,7 @@
 struct __wait_queue {
 	unsigned int flags;
 #define WQ_FLAG_EXCLUSIVE	0x01
-	struct task_struct * task;
+	void *private;
 	wait_queue_func_t func;
 	struct list_head task_list;
 };
@@ -60,7 +60,7 @@
  */
 
 #define __WAITQUEUE_INITIALIZER(name, tsk) {				\
-	.task		= tsk,						\
+	.private	= tsk,						\
 	.func		= default_wake_function,			\
 	.task_list	= { NULL, NULL } }
 
@@ -86,7 +86,7 @@
 static inline void init_waitqueue_entry(wait_queue_t *q, struct task_struct *p)
 {
 	q->flags = 0;
-	q->task = p;
+	q->private = p;
 	q->func = default_wake_function;
 }
 
@@ -94,7 +94,7 @@
 					wait_queue_func_t func)
 {
 	q->flags = 0;
-	q->task = NULL;
+	q->private = NULL;
 	q->func = func;
 }
 
@@ -110,7 +110,7 @@
  * aio specifies a wait queue entry with an async notification
  * callback routine, not associated with any task.
  */
-#define is_sync_wait(wait)	(!(wait) || ((wait)->task))
+#define is_sync_wait(wait)	(!(wait) || ((wait)->private))
 
 extern void FASTCALL(add_wait_queue(wait_queue_head_t *q, wait_queue_t * wait));
 extern void FASTCALL(add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t * wait));
@@ -384,7 +384,7 @@
 
 #define DEFINE_WAIT(name)						\
 	wait_queue_t name = {						\
-		.task		= current,				\
+		.private	= current,				\
 		.func		= autoremove_wake_function,		\
 		.task_list	= LIST_HEAD_INIT((name).task_list),	\
 	}
@@ -393,7 +393,7 @@
 	struct wait_bit_queue name = {					\
 		.key = __WAIT_BIT_KEY_INITIALIZER(word, bit),		\
 		.wait	= {						\
-			.task		= current,			\
+			.private	= current,			\
 			.func		= wake_bit_function,		\
 			.task_list	=				\
 				LIST_HEAD_INIT((name).wait.task_list),	\
@@ -402,7 +402,7 @@
 
 #define init_wait(wait)							\
 	do {								\
-		(wait)->task = current;					\
+		(wait)->private = current;				\
 		(wait)->func = autoremove_wake_function;		\
 		INIT_LIST_HEAD(&(wait)->task_list);			\
 	} while (0)
diff --git a/include/linux/wireless.h b/include/linux/wireless.h
index 2f51f2b..ae485f9 100644
--- a/include/linux/wireless.h
+++ b/include/linux/wireless.h
@@ -1,10 +1,10 @@
 /*
  * This file define a set of standard wireless extensions
  *
- * Version :	17	21.6.04
+ * Version :	18	12.3.05
  *
  * Authors :	Jean Tourrilhes - HPL - <jt@hpl.hp.com>
- * Copyright (c) 1997-2004 Jean Tourrilhes, All Rights Reserved.
+ * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
  */
 
 #ifndef _LINUX_WIRELESS_H
@@ -82,7 +82,7 @@
  * (there is some stuff that will be added in the future...)
  * I just plan to increment with each new version.
  */
-#define WIRELESS_EXT	17
+#define WIRELESS_EXT	18
 
 /*
  * Changes :
@@ -182,6 +182,21 @@
  *	- Document (struct iw_quality *)->updated, add new flags (INVALID)
  *	- Wireless Event capability in struct iw_range
  *	- Add support for relative TxPower (yick !)
+ *
+ * V17 to V18 (From Jouni Malinen <jkmaline@cc.hut.fi>)
+ * ----------
+ *	- Add support for WPA/WPA2
+ *	- Add extended encoding configuration (SIOCSIWENCODEEXT and
+ *	  SIOCGIWENCODEEXT)
+ *	- Add SIOCSIWGENIE/SIOCGIWGENIE
+ *	- Add SIOCSIWMLME
+ *	- Add SIOCSIWPMKSA
+ *	- Add struct iw_range bit field for supported encoding capabilities
+ *	- Add optional scan request parameters for SIOCSIWSCAN
+ *	- Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA
+ *	  related parameters (extensible up to 4096 parameter values)
+ *	- Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE,
+ *	  IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND
  */
 
 /**************************** CONSTANTS ****************************/
@@ -256,6 +271,30 @@
 #define SIOCSIWPOWER	0x8B2C		/* set Power Management settings */
 #define SIOCGIWPOWER	0x8B2D		/* get Power Management settings */
 
+/* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM).
+ * This ioctl uses struct iw_point and data buffer that includes IE id and len
+ * fields. More than one IE may be included in the request. Setting the generic
+ * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers
+ * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers
+ * are required to report the used IE as a wireless event, e.g., when
+ * associating with an AP. */
+#define SIOCSIWGENIE	0x8B30		/* set generic IE */
+#define SIOCGIWGENIE	0x8B31		/* get generic IE */
+
+/* WPA : IEEE 802.11 MLME requests */
+#define SIOCSIWMLME	0x8B16		/* request MLME operation; uses
+					 * struct iw_mlme */
+/* WPA : Authentication mode parameters */
+#define SIOCSIWAUTH	0x8B32		/* set authentication mode params */
+#define SIOCGIWAUTH	0x8B33		/* get authentication mode params */
+
+/* WPA : Extended version of encoding configuration */
+#define SIOCSIWENCODEEXT 0x8B34		/* set encoding token & mode */
+#define SIOCGIWENCODEEXT 0x8B35		/* get encoding token & mode */
+
+/* WPA2 : PMKSA cache management */
+#define SIOCSIWPMKSA	0x8B36		/* PMKSA cache operation */
+
 /* -------------------- DEV PRIVATE IOCTL LIST -------------------- */
 
 /* These 32 ioctl are wireless device private, for 16 commands.
@@ -297,6 +336,34 @@
 #define IWEVCUSTOM	0x8C02		/* Driver specific ascii string */
 #define IWEVREGISTERED	0x8C03		/* Discovered a new node (AP mode) */
 #define IWEVEXPIRED	0x8C04		/* Expired a node (AP mode) */
+#define IWEVGENIE	0x8C05		/* Generic IE (WPA, RSN, WMM, ..)
+					 * (scan results); This includes id and
+					 * length fields. One IWEVGENIE may
+					 * contain more than one IE. Scan
+					 * results may contain one or more
+					 * IWEVGENIE events. */
+#define IWEVMICHAELMICFAILURE 0x8C06	/* Michael MIC failure
+					 * (struct iw_michaelmicfailure)
+					 */
+#define IWEVASSOCREQIE	0x8C07		/* IEs used in (Re)Association Request.
+					 * The data includes id and length
+					 * fields and may contain more than one
+					 * IE. This event is required in
+					 * Managed mode if the driver
+					 * generates its own WPA/RSN IE. This
+					 * should be sent just before
+					 * IWEVREGISTERED event for the
+					 * association. */
+#define IWEVASSOCRESPIE	0x8C08		/* IEs used in (Re)Association
+					 * Response. The data includes id and
+					 * length fields and may contain more
+					 * than one IE. This may be sent
+					 * between IWEVASSOCREQIE and
+					 * IWEVREGISTERED events for the
+					 * association. */
+#define IWEVPMKIDCAND	0x8C09		/* PMKID candidate for RSN
+					 * pre-authentication
+					 * (struct iw_pmkid_cand) */
 
 #define IWEVFIRST	0x8C00
 
@@ -432,12 +499,94 @@
 #define IW_SCAN_THIS_MODE	0x0020	/* Scan only this Mode */
 #define IW_SCAN_ALL_RATE	0x0040	/* Scan all Bit-Rates */
 #define IW_SCAN_THIS_RATE	0x0080	/* Scan only this Bit-Rate */
+/* struct iw_scan_req scan_type */
+#define IW_SCAN_TYPE_ACTIVE 0
+#define IW_SCAN_TYPE_PASSIVE 1
 /* Maximum size of returned data */
 #define IW_SCAN_MAX_DATA	4096	/* In bytes */
 
 /* Max number of char in custom event - use multiple of them if needed */
 #define IW_CUSTOM_MAX		256	/* In bytes */
 
+/* Generic information element */
+#define IW_GENERIC_IE_MAX	1024
+
+/* MLME requests (SIOCSIWMLME / struct iw_mlme) */
+#define IW_MLME_DEAUTH		0
+#define IW_MLME_DISASSOC	1
+
+/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */
+#define IW_AUTH_INDEX		0x0FFF
+#define IW_AUTH_FLAGS		0xF000
+/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095)
+ * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the
+ * parameter that is being set/get to; value will be read/written to
+ * struct iw_param value field) */
+#define IW_AUTH_WPA_VERSION		0
+#define IW_AUTH_CIPHER_PAIRWISE		1
+#define IW_AUTH_CIPHER_GROUP		2
+#define IW_AUTH_KEY_MGMT		3
+#define IW_AUTH_TKIP_COUNTERMEASURES	4
+#define IW_AUTH_DROP_UNENCRYPTED	5
+#define IW_AUTH_80211_AUTH_ALG		6
+#define IW_AUTH_WPA_ENABLED		7
+#define IW_AUTH_RX_UNENCRYPTED_EAPOL	8
+#define IW_AUTH_ROAMING_CONTROL		9
+#define IW_AUTH_PRIVACY_INVOKED		10
+
+/* IW_AUTH_WPA_VERSION values (bit field) */
+#define IW_AUTH_WPA_VERSION_DISABLED	0x00000001
+#define IW_AUTH_WPA_VERSION_WPA		0x00000002
+#define IW_AUTH_WPA_VERSION_WPA2	0x00000004
+
+/* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */
+#define IW_AUTH_CIPHER_NONE	0x00000001
+#define IW_AUTH_CIPHER_WEP40	0x00000002
+#define IW_AUTH_CIPHER_TKIP	0x00000004
+#define IW_AUTH_CIPHER_CCMP	0x00000008
+#define IW_AUTH_CIPHER_WEP104	0x00000010
+
+/* IW_AUTH_KEY_MGMT values (bit field) */
+#define IW_AUTH_KEY_MGMT_802_1X	1
+#define IW_AUTH_KEY_MGMT_PSK	2
+
+/* IW_AUTH_80211_AUTH_ALG values (bit field) */
+#define IW_AUTH_ALG_OPEN_SYSTEM	0x00000001
+#define IW_AUTH_ALG_SHARED_KEY	0x00000002
+#define IW_AUTH_ALG_LEAP	0x00000004
+
+/* IW_AUTH_ROAMING_CONTROL values */
+#define IW_AUTH_ROAMING_ENABLE	0	/* driver/firmware based roaming */
+#define IW_AUTH_ROAMING_DISABLE	1	/* user space program used for roaming
+					 * control */
+
+/* SIOCSIWENCODEEXT definitions */
+#define IW_ENCODE_SEQ_MAX_SIZE	8
+/* struct iw_encode_ext ->alg */
+#define IW_ENCODE_ALG_NONE	0
+#define IW_ENCODE_ALG_WEP	1
+#define IW_ENCODE_ALG_TKIP	2
+#define IW_ENCODE_ALG_CCMP	3
+/* struct iw_encode_ext ->ext_flags */
+#define IW_ENCODE_EXT_TX_SEQ_VALID	0x00000001
+#define IW_ENCODE_EXT_RX_SEQ_VALID	0x00000002
+#define IW_ENCODE_EXT_GROUP_KEY		0x00000004
+#define IW_ENCODE_EXT_SET_TX_KEY	0x00000008
+
+/* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */
+#define IW_MICFAILURE_KEY_ID	0x00000003 /* Key ID 0..3 */
+#define IW_MICFAILURE_GROUP	0x00000004
+#define IW_MICFAILURE_PAIRWISE	0x00000008
+#define IW_MICFAILURE_STAKEY	0x00000010
+#define IW_MICFAILURE_COUNT	0x00000060 /* 1 or 2 (0 = count not supported)
+					    */
+
+/* Bit field values for enc_capa in struct iw_range */
+#define IW_ENC_CAPA_WPA		0x00000001
+#define IW_ENC_CAPA_WPA2	0x00000002
+#define IW_ENC_CAPA_CIPHER_TKIP	0x00000004
+#define IW_ENC_CAPA_CIPHER_CCMP	0x00000008
+
 /* Event capability macros - in (struct iw_range *)->event_capa
  * Because we have more than 32 possible events, we use an array of
  * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */
@@ -546,6 +695,132 @@
 	struct iw_quality	high;		/* High threshold */
 };
 
+/*
+ *	Optional data for scan request
+ *
+ *	Note: these optional parameters are controlling parameters for the
+ *	scanning behavior, these do not apply to getting scan results
+ *	(SIOCGIWSCAN). Drivers are expected to keep a local BSS table and
+ *	provide a merged results with all BSSes even if the previous scan
+ *	request limited scanning to a subset, e.g., by specifying an SSID.
+ *	Especially, scan results are required to include an entry for the
+ *	current BSS if the driver is in Managed mode and associated with an AP.
+ */
+struct	iw_scan_req
+{
+	__u8		scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */
+	__u8		essid_len;
+	__u8		num_channels; /* num entries in channel_list;
+				       * 0 = scan all allowed channels */
+	__u8		flags; /* reserved as padding; use zero, this may
+				* be used in the future for adding flags
+				* to request different scan behavior */
+	struct sockaddr	bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or
+				* individual address of a specific BSS */
+
+	/*
+	 * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using
+	 * the current ESSID. This allows scan requests for specific ESSID
+	 * without having to change the current ESSID and potentially breaking
+	 * the current association.
+	 */
+	__u8		essid[IW_ESSID_MAX_SIZE];
+
+	/*
+	 * Optional parameters for changing the default scanning behavior.
+	 * These are based on the MLME-SCAN.request from IEEE Std 802.11.
+	 * TU is 1.024 ms. If these are set to 0, driver is expected to use
+	 * reasonable default values. min_channel_time defines the time that
+	 * will be used to wait for the first reply on each channel. If no
+	 * replies are received, next channel will be scanned after this. If
+	 * replies are received, total time waited on the channel is defined by
+	 * max_channel_time.
+	 */
+	__u32		min_channel_time; /* in TU */
+	__u32		max_channel_time; /* in TU */
+
+	struct iw_freq	channel_list[IW_MAX_FREQUENCIES];
+};
+
+/* ------------------------- WPA SUPPORT ------------------------- */
+
+/*
+ *	Extended data structure for get/set encoding (this is used with
+ *	SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_*
+ *	flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and
+ *	only the data contents changes (key data -> this structure, including
+ *	key data).
+ *
+ *	If the new key is the first group key, it will be set as the default
+ *	TX key. Otherwise, default TX key index is only changed if
+ *	IW_ENCODE_EXT_SET_TX_KEY flag is set.
+ *
+ *	Key will be changed with SIOCSIWENCODEEXT in all cases except for
+ *	special "change TX key index" operation which is indicated by setting
+ *	key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY.
+ *
+ *	tx_seq/rx_seq are only used when respective
+ *	IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal
+ *	TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start
+ *	TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally
+ *	used only by an Authenticator (AP or an IBSS station) to get the
+ *	current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and
+ *	RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for
+ *	debugging/testing.
+ */
+struct	iw_encode_ext
+{
+	__u32		ext_flags; /* IW_ENCODE_EXT_* */
+	__u8		tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
+	__u8		rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
+	struct sockaddr	addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast
+			       * (group) keys or unicast address for
+			       * individual keys */
+	__u16		alg; /* IW_ENCODE_ALG_* */
+	__u16		key_len;
+	__u8		key[0];
+};
+
+/* SIOCSIWMLME data */
+struct	iw_mlme
+{
+	__u16		cmd; /* IW_MLME_* */
+	__u16		reason_code;
+	struct sockaddr	addr;
+};
+
+/* SIOCSIWPMKSA data */
+#define IW_PMKSA_ADD		1
+#define IW_PMKSA_REMOVE		2
+#define IW_PMKSA_FLUSH		3
+
+#define IW_PMKID_LEN	16
+
+struct	iw_pmksa
+{
+	__u32		cmd; /* IW_PMKSA_* */
+	struct sockaddr	bssid;
+	__u8		pmkid[IW_PMKID_LEN];
+};
+
+/* IWEVMICHAELMICFAILURE data */
+struct	iw_michaelmicfailure
+{
+	__u32		flags;
+	struct sockaddr	src_addr;
+	__u8		tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
+};
+
+/* IWEVPMKIDCAND data */
+#define IW_PMKID_CAND_PREAUTH	0x00000001 /* RNS pre-authentication enabled */
+struct	iw_pmkid_cand
+{
+	__u32		flags; /* IW_PMKID_CAND_* */
+	__u32		index; /* the smaller the index, the higher the
+				* priority */
+	struct sockaddr	bssid;
+};
+
 /* ------------------------ WIRELESS STATS ------------------------ */
 /*
  * Wireless statistics (used for /proc/net/wireless)
@@ -725,6 +1000,8 @@
 	struct iw_freq	freq[IW_MAX_FREQUENCIES];	/* list */
 	/* Note : this frequency list doesn't need to fit channel numbers,
 	 * because each entry contain its channel index */
+
+	__u32		enc_capa; /* IW_ENC_CAPA_* bit field */
 };
 
 /*
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 1262cb4..d5c3fe1 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -14,11 +14,13 @@
  * Yes, writeback.h requires sched.h
  * No, sched.h is not included from here.
  */
-static inline int current_is_pdflush(void)
+static inline int task_is_pdflush(struct task_struct *task)
 {
-	return current->flags & PF_FLUSHER;
+	return task->flags & PF_FLUSHER;
 }
 
+#define current_is_pdflush()	task_is_pdflush(current)
+
 /*
  * fs/fs-writeback.c
  */
diff --git a/include/linux/x25.h b/include/linux/x25.h
index 7531cfe..16d4493 100644
--- a/include/linux/x25.h
+++ b/include/linux/x25.h
@@ -4,6 +4,8 @@
  * 	History
  *	mar/20/00	Daniela Squassoni Disabling/enabling of facilities 
  *					  negotiation.
+ *	apr/02/05	Shaun Pereira Selective sub address matching with
+ *					call user data
  */
 
 #ifndef	X25_KERNEL_H
@@ -16,6 +18,9 @@
 #define	SIOCX25GCALLUSERDATA	(SIOCPROTOPRIVATE + 4)
 #define	SIOCX25SCALLUSERDATA	(SIOCPROTOPRIVATE + 5)
 #define	SIOCX25GCAUSEDIAG	(SIOCPROTOPRIVATE + 6)
+#define SIOCX25SCUDMATCHLEN	(SIOCPROTOPRIVATE + 7)
+#define SIOCX25CALLACCPTAPPRV   (SIOCPROTOPRIVATE + 8)
+#define SIOCX25SENDCALLACCPT    (SIOCPROTOPRIVATE + 9)
 
 /*
  *	Values for {get,set}sockopt.
@@ -109,4 +114,11 @@
 	unsigned char	diagnostic;
 };
 
+/*
+ *	Further optional call user data match length selection
+ */
+struct x25_subaddr {
+	unsigned int cudmatchlength;
+};
+
 #endif
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h
index fd2ef74..f0d4233 100644
--- a/include/linux/xfrm.h
+++ b/include/linux/xfrm.h
@@ -174,6 +174,8 @@
 	XFRMA_ALG_COMP,		/* struct xfrm_algo */
 	XFRMA_ENCAP,		/* struct xfrm_algo + struct xfrm_encap_tmpl */
 	XFRMA_TMPL,		/* 1 or more struct xfrm_user_tmpl */
+	XFRMA_SA,
+	XFRMA_POLICY,
 	__XFRMA_MAX
 
 #define XFRMA_MAX (__XFRMA_MAX - 1)
@@ -194,6 +196,7 @@
 	__u8				flags;
 #define XFRM_STATE_NOECN	1
 #define XFRM_STATE_DECAP_DSCP	2
+#define XFRM_STATE_NOPMTUDISC	4
 };
 
 struct xfrm_usersa_id {
@@ -257,5 +260,7 @@
 
 #define XFRMGRP_ACQUIRE		1
 #define XFRMGRP_EXPIRE		2
+#define XFRMGRP_SA		4
+#define XFRMGRP_POLICY		8
 
 #endif /* _LINUX_XFRM_H */
diff --git a/include/media/audiochip.h b/include/media/audiochip.h
index d3e9e30..f345a61 100644
--- a/include/media/audiochip.h
+++ b/include/media/audiochip.h
@@ -1,3 +1,7 @@
+/*
+ * $Id: audiochip.h,v 1.3 2005/06/12 04:19:19 mchehab Exp $
+ */
+
 #ifndef AUDIOCHIP_H
 #define AUDIOCHIP_H
 
diff --git a/include/media/id.h b/include/media/id.h
index 1b0320d..a39a642 100644
--- a/include/media/id.h
+++ b/include/media/id.h
@@ -1,3 +1,7 @@
+/*
+ * $Id: id.h,v 1.4 2005/06/12 04:19:19 mchehab Exp $
+ */
+
 /* FIXME: this temporarely, until these are included in linux/i2c-id.h */
 
 /* drivers */
diff --git a/include/media/ir-common.h b/include/media/ir-common.h
index 62c963a..6986705 100644
--- a/include/media/ir-common.h
+++ b/include/media/ir-common.h
@@ -1,5 +1,5 @@
 /*
- * $Id: ir-common.h,v 1.8 2005/02/22 12:28:40 kraxel Exp $
+ * $Id: ir-common.h,v 1.9 2005/05/15 19:01:26 mchehab Exp $
  *
  * some common structs and functions to handle infrared remotes via
  * input layer ...
@@ -50,6 +50,7 @@
 extern IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_empty[IR_KEYTAB_SIZE];
 extern IR_KEYTAB_TYPE ir_codes_hauppauge_new[IR_KEYTAB_SIZE];
+extern IR_KEYTAB_TYPE ir_codes_pixelview[IR_KEYTAB_SIZE];
 
 void ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
 		   int ir_type, IR_KEYTAB_TYPE *ir_codes);
diff --git a/include/media/tuner.h b/include/media/tuner.h
index 156a9c5..2dd8310 100644
--- a/include/media/tuner.h
+++ b/include/media/tuner.h
@@ -25,6 +25,8 @@
 
 #include "id.h"
 
+#define ADDR_UNSET (255)
+
 #define TUNER_TEMIC_PAL     0        /* 4002 FH5 (3X 7756, 9483) */
 #define TUNER_PHILIPS_PAL_I 1
 #define TUNER_PHILIPS_NTSC  2
@@ -98,12 +100,23 @@
 #define TUNER_PHILIPS_FQ1216AME_MK4 56 /* Hauppauge PVR-150 PAL */
 #define TUNER_PHILIPS_FQ1236A_MK4 57   /* Hauppauge PVR-500MCE NTSC */
 
+#define TUNER_YMEC_TVF_8531MF 58
+#define TUNER_YMEC_TVF_5533MF 59	/* Pixelview Pro Ultra NTSC */
+#define TUNER_THOMSON_DTT7611 60
+#define TUNER_TENA_9533_DI    61
+#define TUNER_TEA5767         62	/* Only FM Radio Tuner */
+
+#define TEA5767_TUNER_NAME "Philips TEA5767HN FM Radio"
+
+#define TUNER_THOMSON_DTT7611    60
+
 #define NOTUNER 0
 #define PAL     1	/* PAL_BG */
 #define PAL_I   2
 #define NTSC    3
 #define SECAM   4
 #define ATSC    5
+#define RADIO	6
 
 #define NoTuner 0
 #define Philips 1
@@ -119,10 +132,20 @@
 #define TCL     11
 #define THOMSON 12
 
+enum v4l_radio_tuner {
+        TEA5767_LOW_LO_32768    = 0,
+        TEA5767_HIGH_LO_32768   = 1,
+        TEA5767_LOW_LO_13MHz    = 2,
+        TEA5767_HIGH_LO_13MHz   = 3,
+};
+
+
 #define TUNER_SET_TYPE               _IOW('t',1,int)    /* set tuner type */
 #define TUNER_SET_TVFREQ             _IOW('t',2,int)    /* set tv freq */
+#define TUNER_SET_TYPE_ADDR          _IOW('T',3,int)	/* set tuner type and I2C addr */
 
 #define  TDA9887_SET_CONFIG          _IOW('t',5,int)
+
 /* tv card specific */
 # define TDA9887_PRESENT             (1<<0)
 # define TDA9887_PORT1_INACTIVE      (1<<1)
@@ -143,6 +166,12 @@
 #define I2C_ADDR_TDA8290        0x4b
 #define I2C_ADDR_TDA8275        0x61
 
+struct tuner_addr {
+	enum v4l2_tuner_type	v4l2_tuner;
+	unsigned int		type;
+	unsigned short		addr;
+};
+
 struct tuner {
 	/* device */
 	struct i2c_client i2c;
diff --git a/include/media/tveeprom.h b/include/media/tveeprom.h
index 627603e..5c4fe30 100644
--- a/include/media/tveeprom.h
+++ b/include/media/tveeprom.h
@@ -1,3 +1,7 @@
+/*
+ * $Id: tveeprom.h,v 1.2 2005/06/12 04:19:19 mchehab Exp $
+ */
+
 struct tveeprom {
 	u32 has_radio;
 
diff --git a/include/net/ax25.h b/include/net/ax25.h
index 9e6368a..828a3a9 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -220,7 +220,7 @@
 	}
 }
 
-static inline unsigned short ax25_type_trans(struct sk_buff *skb, struct net_device *dev)
+static inline __be16 ax25_type_trans(struct sk_buff *skb, struct net_device *dev)
 {
 	skb->dev      = dev;
 	skb->pkt_type = PACKET_HOST;
diff --git a/include/net/ip.h b/include/net/ip.h
index 3f63992..32360bb 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -163,6 +163,7 @@
 
 extern int sysctl_local_port_range[2];
 extern int sysctl_ip_default_ttl;
+extern int sysctl_ip_nonlocal_bind;
 
 #ifdef CONFIG_INET
 /* The function in 2.2 was invalid, producing wrong result for
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 3199045..a66e9de 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -167,14 +167,17 @@
 extern int			fib6_add(struct fib6_node *root,
 					 struct rt6_info *rt,
 					 struct nlmsghdr *nlh,
-					 void *rtattr);
+					 void *rtattr,
+					 struct netlink_skb_parms *req);
 
 extern int			fib6_del(struct rt6_info *rt,
 					 struct nlmsghdr *nlh,
-					 void *rtattr);
+					 void *rtattr,
+					 struct netlink_skb_parms *req);
 
 extern void			inet6_rt_notify(int event, struct rt6_info *rt,
-						struct nlmsghdr *nlh);
+						struct nlmsghdr *nlh,
+						struct netlink_skb_parms *req);
 
 extern void			fib6_run_gc(unsigned long dummy);
 
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index d5d1dd1..f920706 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -41,13 +41,16 @@
 
 extern int			ip6_route_add(struct in6_rtmsg *rtmsg,
 					      struct nlmsghdr *,
-					      void *rtattr);
+					      void *rtattr,
+					      struct netlink_skb_parms *req);
 extern int			ip6_ins_rt(struct rt6_info *,
 					   struct nlmsghdr *,
-					   void *rtattr);
+					   void *rtattr,
+					   struct netlink_skb_parms *req);
 extern int			ip6_del_rt(struct rt6_info *,
 					   struct nlmsghdr *,
-					   void *rtattr);
+					   void *rtattr,
+					   struct netlink_skb_parms *req);
 
 extern int			ip6_rt_addr_add(struct in6_addr *addr,
 						struct net_device *dev,
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index e5a5f6b..a4208a3 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -109,6 +109,20 @@
 #endif
 };
 
+struct fib_result_nl {
+	u32		fl_addr;   /* To be looked up*/ 
+	u32		fl_fwmark; 
+	unsigned char	fl_tos;
+	unsigned char   fl_scope;
+	unsigned char   tb_id_in;
+
+	unsigned char   tb_id;      /* Results */
+	unsigned char	prefixlen;
+	unsigned char	nh_sel;
+	unsigned char	type;
+	unsigned char	scope;
+	int             err;      
+};
 
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 4f33bbc..8980989 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -65,11 +65,10 @@
 
 struct neigh_parms
 {
+	struct net_device *dev;
 	struct neigh_parms *next;
 	int	(*neigh_setup)(struct neighbour *);
 	struct neigh_table *tbl;
-	int	entries;
-	void	*priv;
 
 	void	*sysctl_table;
 
@@ -192,7 +191,6 @@
 	atomic_t		entries;
 	rwlock_t		lock;
 	unsigned long		last_rand;
-	struct neigh_parms	*parms_list;
 	kmem_cache_t		*kmem_cachep;
 	struct neigh_statistics	*stats;
 	struct neighbour	**hash_buckets;
@@ -252,6 +250,9 @@
 extern int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
 extern void neigh_app_ns(struct neighbour *n);
 
+extern int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb);
+extern int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg);
+
 extern void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie);
 extern void __neigh_for_each_release(struct neigh_table *tbl, int (*cb)(struct neighbour *));
 extern void pneigh_for_each(struct neigh_table *tbl, void (*cb)(struct pneigh_entry *));
diff --git a/include/net/request_sock.h b/include/net/request_sock.h
new file mode 100644
index 0000000..72fd6f5
--- /dev/null
+++ b/include/net/request_sock.h
@@ -0,0 +1,255 @@
+/*
+ * NET		Generic infrastructure for Network protocols.
+ *
+ *		Definitions for request_sock 
+ *
+ * Authors:	Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * 		From code originally in include/net/tcp.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.
+ */
+#ifndef _REQUEST_SOCK_H
+#define _REQUEST_SOCK_H
+
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <net/sock.h>
+
+struct request_sock;
+struct sk_buff;
+struct dst_entry;
+struct proto;
+
+struct request_sock_ops {
+	int		family;
+	kmem_cache_t	*slab;
+	int		obj_size;
+	int		(*rtx_syn_ack)(struct sock *sk,
+				       struct request_sock *req,
+				       struct dst_entry *dst);
+	void		(*send_ack)(struct sk_buff *skb,
+				    struct request_sock *req);
+	void		(*send_reset)(struct sk_buff *skb);
+	void		(*destructor)(struct request_sock *req);
+};
+
+/* struct request_sock - mini sock to represent a connection request
+ */
+struct request_sock {
+	struct request_sock		*dl_next; /* Must be first member! */
+	u16				mss;
+	u8				retrans;
+	u8				__pad;
+	/* The following two fields can be easily recomputed I think -AK */
+	u32				window_clamp; /* window clamp at creation time */
+	u32				rcv_wnd;	  /* rcv_wnd offered first time */
+	u32				ts_recent;
+	unsigned long			expires;
+	struct request_sock_ops		*rsk_ops;
+	struct sock			*sk;
+};
+
+static inline struct request_sock *reqsk_alloc(struct request_sock_ops *ops)
+{
+	struct request_sock *req = kmem_cache_alloc(ops->slab, SLAB_ATOMIC);
+
+	if (req != NULL)
+		req->rsk_ops = ops;
+
+	return req;
+}
+
+static inline void __reqsk_free(struct request_sock *req)
+{
+	kmem_cache_free(req->rsk_ops->slab, req);
+}
+
+static inline void reqsk_free(struct request_sock *req)
+{
+	req->rsk_ops->destructor(req);
+	__reqsk_free(req);
+}
+
+extern int sysctl_max_syn_backlog;
+
+/** struct listen_sock - listen state
+ *
+ * @max_qlen_log - log_2 of maximal queued SYNs/REQUESTs
+ */
+struct listen_sock {
+	u8			max_qlen_log;
+	/* 3 bytes hole, try to use */
+	int			qlen;
+	int			qlen_young;
+	int			clock_hand;
+	u32			hash_rnd;
+	struct request_sock	*syn_table[0];
+};
+
+/** struct request_sock_queue - queue of request_socks
+ *
+ * @rskq_accept_head - FIFO head of established children
+ * @rskq_accept_tail - FIFO tail of established children
+ * @syn_wait_lock - serializer
+ *
+ * %syn_wait_lock is necessary only to avoid proc interface having to grab the main
+ * lock sock while browsing the listening hash (otherwise it's deadlock prone).
+ *
+ * This lock is acquired in read mode only from listening_get_next() seq_file
+ * op and it's acquired in write mode _only_ from code that is actively
+ * changing rskq_accept_head. All readers that are holding the master sock lock
+ * don't need to grab this lock in read mode too as rskq_accept_head. writes
+ * are always protected from the main sock lock.
+ */
+struct request_sock_queue {
+	struct request_sock	*rskq_accept_head;
+	struct request_sock	*rskq_accept_tail;
+	rwlock_t		syn_wait_lock;
+	struct listen_sock	*listen_opt;
+};
+
+extern int reqsk_queue_alloc(struct request_sock_queue *queue,
+			     const int nr_table_entries);
+
+static inline struct listen_sock *reqsk_queue_yank_listen_sk(struct request_sock_queue *queue)
+{
+	struct listen_sock *lopt;
+
+	write_lock_bh(&queue->syn_wait_lock);
+	lopt = queue->listen_opt;
+	queue->listen_opt = NULL;
+	write_unlock_bh(&queue->syn_wait_lock);
+
+	return lopt;
+}
+
+static inline void reqsk_queue_destroy(struct request_sock_queue *queue)
+{
+	kfree(reqsk_queue_yank_listen_sk(queue));
+}
+
+static inline struct request_sock *
+	reqsk_queue_yank_acceptq(struct request_sock_queue *queue)
+{
+	struct request_sock *req = queue->rskq_accept_head;
+
+	queue->rskq_accept_head = queue->rskq_accept_head = NULL;
+	return req;
+}
+
+static inline int reqsk_queue_empty(struct request_sock_queue *queue)
+{
+	return queue->rskq_accept_head == NULL;
+}
+
+static inline void reqsk_queue_unlink(struct request_sock_queue *queue,
+				      struct request_sock *req,
+				      struct request_sock **prev_req)
+{
+	write_lock(&queue->syn_wait_lock);
+	*prev_req = req->dl_next;
+	write_unlock(&queue->syn_wait_lock);
+}
+
+static inline void reqsk_queue_add(struct request_sock_queue *queue,
+				   struct request_sock *req,
+				   struct sock *parent,
+				   struct sock *child)
+{
+	req->sk = child;
+	sk_acceptq_added(parent);
+
+	if (queue->rskq_accept_head == NULL)
+		queue->rskq_accept_head = req;
+	else
+		queue->rskq_accept_tail->dl_next = req;
+
+	queue->rskq_accept_tail = req;
+	req->dl_next = NULL;
+}
+
+static inline struct request_sock *reqsk_queue_remove(struct request_sock_queue *queue)
+{
+	struct request_sock *req = queue->rskq_accept_head;
+
+	BUG_TRAP(req != NULL);
+
+	queue->rskq_accept_head = req->dl_next;
+	if (queue->rskq_accept_head == NULL)
+		queue->rskq_accept_tail = NULL;
+
+	return req;
+}
+
+static inline struct sock *reqsk_queue_get_child(struct request_sock_queue *queue,
+						 struct sock *parent)
+{
+	struct request_sock *req = reqsk_queue_remove(queue);
+	struct sock *child = req->sk;
+
+	BUG_TRAP(child != NULL);
+
+	sk_acceptq_removed(parent);
+	__reqsk_free(req);
+	return child;
+}
+
+static inline int reqsk_queue_removed(struct request_sock_queue *queue,
+				      struct request_sock *req)
+{
+	struct listen_sock *lopt = queue->listen_opt;
+
+	if (req->retrans == 0)
+		--lopt->qlen_young;
+
+	return --lopt->qlen;
+}
+
+static inline int reqsk_queue_added(struct request_sock_queue *queue)
+{
+	struct listen_sock *lopt = queue->listen_opt;
+	const int prev_qlen = lopt->qlen;
+
+	lopt->qlen_young++;
+	lopt->qlen++;
+	return prev_qlen;
+}
+
+static inline int reqsk_queue_len(struct request_sock_queue *queue)
+{
+	return queue->listen_opt != NULL ? queue->listen_opt->qlen : 0;
+}
+
+static inline int reqsk_queue_len_young(struct request_sock_queue *queue)
+{
+	return queue->listen_opt->qlen_young;
+}
+
+static inline int reqsk_queue_is_full(struct request_sock_queue *queue)
+{
+	return queue->listen_opt->qlen >> queue->listen_opt->max_qlen_log;
+}
+
+static inline void reqsk_queue_hash_req(struct request_sock_queue *queue,
+					u32 hash, struct request_sock *req,
+					unsigned timeout)
+{
+	struct listen_sock *lopt = queue->listen_opt;
+
+	req->expires = jiffies + timeout;
+	req->retrans = 0;
+	req->sk = NULL;
+	req->dl_next = lopt->syn_table[hash];
+
+	write_lock(&queue->syn_wait_lock);
+	lopt->syn_table[hash] = req;
+	write_unlock(&queue->syn_wait_lock);
+}
+
+#endif /* _REQUEST_SOCK_H */
diff --git a/include/net/route.h b/include/net/route.h
index d34ca8f..c3cd069 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -107,7 +107,7 @@
 
 extern struct rt_cache_stat *rt_cache_stat;
 #define RT_CACHE_STAT_INC(field)					  \
-		(per_cpu_ptr(rt_cache_stat, _smp_processor_id())->field++)
+		(per_cpu_ptr(rt_cache_stat, raw_smp_processor_id())->field++)
 
 extern struct ip_rt_acct *ip_rt_acct;
 
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index c57504b..7b97405 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -172,4 +172,126 @@
 	kfree(tp);
 }
 
+static inline int __qdisc_enqueue_tail(struct sk_buff *skb, struct Qdisc *sch,
+				       struct sk_buff_head *list)
+{
+	__skb_queue_tail(list, skb);
+	sch->qstats.backlog += skb->len;
+	sch->bstats.bytes += skb->len;
+	sch->bstats.packets++;
+
+	return NET_XMIT_SUCCESS;
+}
+
+static inline int qdisc_enqueue_tail(struct sk_buff *skb, struct Qdisc *sch)
+{
+	return __qdisc_enqueue_tail(skb, sch, &sch->q);
+}
+
+static inline struct sk_buff *__qdisc_dequeue_head(struct Qdisc *sch,
+						   struct sk_buff_head *list)
+{
+	struct sk_buff *skb = __skb_dequeue(list);
+
+	if (likely(skb != NULL))
+		sch->qstats.backlog -= skb->len;
+
+	return skb;
+}
+
+static inline struct sk_buff *qdisc_dequeue_head(struct Qdisc *sch)
+{
+	return __qdisc_dequeue_head(sch, &sch->q);
+}
+
+static inline struct sk_buff *__qdisc_dequeue_tail(struct Qdisc *sch,
+						   struct sk_buff_head *list)
+{
+	struct sk_buff *skb = __skb_dequeue_tail(list);
+
+	if (likely(skb != NULL))
+		sch->qstats.backlog -= skb->len;
+
+	return skb;
+}
+
+static inline struct sk_buff *qdisc_dequeue_tail(struct Qdisc *sch)
+{
+	return __qdisc_dequeue_tail(sch, &sch->q);
+}
+
+static inline int __qdisc_requeue(struct sk_buff *skb, struct Qdisc *sch,
+				  struct sk_buff_head *list)
+{
+	__skb_queue_head(list, skb);
+	sch->qstats.backlog += skb->len;
+	sch->qstats.requeues++;
+
+	return NET_XMIT_SUCCESS;
+}
+
+static inline int qdisc_requeue(struct sk_buff *skb, struct Qdisc *sch)
+{
+	return __qdisc_requeue(skb, sch, &sch->q);
+}
+
+static inline void __qdisc_reset_queue(struct Qdisc *sch,
+				       struct sk_buff_head *list)
+{
+	/*
+	 * We do not know the backlog in bytes of this list, it
+	 * is up to the caller to correct it
+	 */
+	skb_queue_purge(list);
+}
+
+static inline void qdisc_reset_queue(struct Qdisc *sch)
+{
+	__qdisc_reset_queue(sch, &sch->q);
+	sch->qstats.backlog = 0;
+}
+
+static inline unsigned int __qdisc_queue_drop(struct Qdisc *sch,
+					      struct sk_buff_head *list)
+{
+	struct sk_buff *skb = __qdisc_dequeue_tail(sch, list);
+
+	if (likely(skb != NULL)) {
+		unsigned int len = skb->len;
+		kfree_skb(skb);
+		return len;
+	}
+
+	return 0;
+}
+
+static inline unsigned int qdisc_queue_drop(struct Qdisc *sch)
+{
+	return __qdisc_queue_drop(sch, &sch->q);
+}
+
+static inline int qdisc_drop(struct sk_buff *skb, struct Qdisc *sch)
+{
+	kfree_skb(skb);
+	sch->qstats.drops++;
+
+	return NET_XMIT_DROP;
+}
+
+static inline int qdisc_reshape_fail(struct sk_buff *skb, struct Qdisc *sch)
+{
+	sch->qstats.drops++;
+
+#ifdef CONFIG_NET_CLS_POLICE
+	if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch))
+		goto drop;
+
+	return NET_XMIT_SUCCESS;
+
+drop:
+#endif
+	kfree_skb(skb);
+	return NET_XMIT_DROP;
+}
+
 #endif
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index ebc5282..dc107ff 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -65,9 +65,11 @@
 	SCTP_CMD_TIMER_START,	/* Start a timer.  */
 	SCTP_CMD_TIMER_RESTART,	/* Restart a timer. */
 	SCTP_CMD_TIMER_STOP,	/* Stop a timer. */
-	SCTP_CMD_COUNTER_RESET, /* Reset a counter. */
-	SCTP_CMD_COUNTER_INC,   /* Increment a counter. */
+	SCTP_CMD_INIT_CHOOSE_TRANSPORT, /* Choose transport for an INIT. */
+	SCTP_CMD_INIT_COUNTER_RESET, /* Reset init counter. */
+	SCTP_CMD_INIT_COUNTER_INC,   /* Increment init counter. */
 	SCTP_CMD_INIT_RESTART,  /* High level, do init timer work. */
+	SCTP_CMD_COOKIEECHO_RESTART,  /* High level, do cookie-echo timer work. */
 	SCTP_CMD_INIT_FAILED,   /* High level, do init failure work. */
 	SCTP_CMD_REPORT_DUP,	/* Report a duplicate TSN.  */
 	SCTP_CMD_STRIKE,	/* Mark a strike against a transport.  */
@@ -118,7 +120,6 @@
 	int error;
 	sctp_state_t state;
 	sctp_event_timeout_t to;
-	sctp_counter_t counter;
 	void *ptr;
 	struct sctp_chunk *chunk;
 	struct sctp_association *asoc;
@@ -165,7 +166,6 @@
 SCTP_ARG_CONSTRUCTOR(U8,	__u8, u8)
 SCTP_ARG_CONSTRUCTOR(ERROR,     int, error)
 SCTP_ARG_CONSTRUCTOR(STATE,	sctp_state_t, state)
-SCTP_ARG_CONSTRUCTOR(COUNTER,	sctp_counter_t, counter)
 SCTP_ARG_CONSTRUCTOR(TO,	sctp_event_timeout_t, to)
 SCTP_ARG_CONSTRUCTOR(PTR,	void *, ptr)
 SCTP_ARG_CONSTRUCTOR(CHUNK,	struct sctp_chunk *, chunk)
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
index 2b76c0f..4868c7f 100644
--- a/include/net/sctp/constants.h
+++ b/include/net/sctp/constants.h
@@ -263,13 +263,6 @@
 enum { SCTP_MAX_DUP_TSNS = 16 };
 enum { SCTP_MAX_GABS = 16 };
 
-typedef enum {
-	SCTP_COUNTER_INIT_ERROR,
-} sctp_counter_t;
-
-/* How many counters does an association need? */
-#define SCTP_NUMBER_COUNTERS	5
-
 /* Here we define the default timers.  */
 
 /* cookie timer def = ? seconds */
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 960abfa..ef27381 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -223,6 +223,22 @@
 extern int sctp_debug_flag;
 #define SCTP_DEBUG_PRINTK(whatever...) \
 	((void) (sctp_debug_flag && printk(KERN_DEBUG whatever)))
+#define SCTP_DEBUG_PRINTK_IPADDR(lead, trail, leadparm, saddr, otherparms...) \
+	if (sctp_debug_flag) { \
+		if (saddr->sa.sa_family == AF_INET6) { \
+			printk(KERN_DEBUG \
+			       lead "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" trail, \
+			       leadparm, \
+			       NIP6(saddr->v6.sin6_addr), \
+			       otherparms); \
+		} else { \
+			printk(KERN_DEBUG \
+			       lead "%u.%u.%u.%u" trail, \
+			       leadparm, \
+			       NIPQUAD(saddr->v4.sin_addr.s_addr), \
+			       otherparms); \
+		} \
+	}
 #define SCTP_ENABLE_DEBUG { sctp_debug_flag = 1; }
 #define SCTP_DISABLE_DEBUG { sctp_debug_flag = 0; }
 
@@ -236,6 +252,7 @@
 #else	/* SCTP_DEBUG */
 
 #define SCTP_DEBUG_PRINTK(whatever...)
+#define SCTP_DEBUG_PRINTK_IPADDR(whatever...)
 #define SCTP_ENABLE_DEBUG
 #define SCTP_DISABLE_DEBUG
 #define SCTP_ASSERT(expr, str, func)
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index f4fcee1..88d9fe5 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -116,7 +116,8 @@
 sctp_state_fn_t sctp_sf_eat_sack_6_2;
 sctp_state_fn_t sctp_sf_tabort_8_4_8;
 sctp_state_fn_t sctp_sf_operr_notify;
-sctp_state_fn_t sctp_sf_t1_timer_expire;
+sctp_state_fn_t sctp_sf_t1_init_timer_expire;
+sctp_state_fn_t sctp_sf_t1_cookie_timer_expire;
 sctp_state_fn_t sctp_sf_t2_timer_expire;
 sctp_state_fn_t sctp_sf_t4_timer_expire;
 sctp_state_fn_t sctp_sf_t5_timer_expire;
@@ -130,7 +131,6 @@
 sctp_state_fn_t sctp_sf_ootb;
 sctp_state_fn_t sctp_sf_pdiscard;
 sctp_state_fn_t sctp_sf_violation;
-sctp_state_fn_t sctp_sf_violation_chunklen;
 sctp_state_fn_t sctp_sf_discard_chunk;
 sctp_state_fn_t sctp_sf_do_5_2_1_siminit;
 sctp_state_fn_t sctp_sf_do_5_2_2_dupinit;
@@ -258,8 +258,6 @@
 void sctp_chunk_assign_tsn(struct sctp_chunk *);
 void sctp_chunk_assign_ssn(struct sctp_chunk *);
 
-void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error);
-
 /* Prototypes for statetable processing. */
 
 int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype,
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 6c24d9c..dfad4d3 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -867,10 +867,13 @@
 	 */
 	unsigned long last_time_ecne_reduced;
 
-	/* active      : The current active state of this destination,
-	 *	       :  i.e. DOWN, UP, etc.
+	/* The number of times INIT has been sent on this transport. */
+	int init_sent_count;
+
+	/* state       : The current state of this destination,
+	 *             : i.e. SCTP_ACTIVE, SCTP_INACTIVE, SCTP_UNKOWN.
 	 */
-	int active;
+	int state;
 
 	/* hb_allowed  : The current heartbeat state of this destination,
 	 *	       :  i.e. ALLOW-HB, NO-HEARTBEAT, etc.
@@ -1222,9 +1225,6 @@
 
 	/* sendbuf acct. policy.	*/
 	__u32 sndbuf_policy;
-
-	/* Name for debugging output... */
-	char *debug_name;
 };
 
 /* Recover the outter endpoint structure. */
@@ -1314,11 +1314,23 @@
 		 *	       : association. Normally this information is
 		 *	       : hashed or keyed for quick lookup and access
 		 *	       : of the TCB.
+		 *	       : The list is also initialized with the list
+		 *	       : of addresses passed with the sctp_connectx()
+		 *	       : call.
 		 *
 		 * It is a list of SCTP_transport's.
 		 */
 		struct list_head transport_addr_list;
 
+		/* transport_count
+		 *
+		 * Peer        : A count of the number of peer addresses
+		 * Transport   : in the Peer Transport Address List.
+		 * Address     :
+		 * Count       :
+		 */
+		__u16 transport_count;
+
 		/* port
 		 *   The transport layer port number.
 		 */
@@ -1486,6 +1498,9 @@
 	/* Transport to which SHUTDOWN chunk was last sent.  */
 	struct sctp_transport *shutdown_last_sent_to;
 
+	/* Transport to which INIT chunk was last sent.  */
+	struct sctp_transport *init_last_sent_to;
+
 	/* Next TSN    : The next TSN number to be assigned to a new
 	 *	       : DATA chunk.  This is sent in the INIT or INIT
 	 *	       : ACK chunk to the peer and incremented each
@@ -1549,8 +1564,11 @@
 	/* The message size at which SCTP fragmentation will occur. */
 	__u32 frag_point;
 
-	/* Currently only one counter is used to count INIT errors. */
-	int counters[SCTP_NUMBER_COUNTERS];
+	/* Counter used to count INIT errors. */
+	int init_err_counter;
+
+	/* Count the number of INIT cycles (for doubling timeout). */
+	int init_cycle;
 
 	/* Default send parameters. */
 	__u16 default_stream;
@@ -1708,6 +1726,8 @@
 void sctp_association_put(struct sctp_association *);
 void sctp_association_hold(struct sctp_association *);
 
+struct sctp_transport *sctp_assoc_choose_init_transport(
+	struct sctp_association *);
 struct sctp_transport *sctp_assoc_choose_shutdown_transport(
 	struct sctp_association *);
 void sctp_assoc_update_retran_path(struct sctp_association *);
@@ -1717,9 +1737,12 @@
 			    const union sctp_addr *laddr);
 struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *,
 				     const union sctp_addr *address,
-				     const int gfp);
+				     const int gfp,
+				     const int peer_state);
 void sctp_assoc_del_peer(struct sctp_association *asoc,
 			 const union sctp_addr *addr);
+void sctp_assoc_rm_peer(struct sctp_association *asoc,
+			 struct sctp_transport *peer);
 void sctp_assoc_control_transport(struct sctp_association *,
 				  struct sctp_transport *,
 				  sctp_transport_cmd_t, sctp_sn_error_t);
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h
index 2758e8c..f6328ae 100644
--- a/include/net/sctp/user.h
+++ b/include/net/sctp/user.h
@@ -111,6 +111,8 @@
 #define SCTP_GET_LOCAL_ADDRS_NUM	SCTP_GET_LOCAL_ADDRS_NUM
 	SCTP_GET_LOCAL_ADDRS, 	/* Get all local addresss. */
 #define SCTP_GET_LOCAL_ADDRS	SCTP_GET_LOCAL_ADDRS
+	SCTP_SOCKOPT_CONNECTX, /* CONNECTX requests. */
+#define SCTP_SOCKOPT_CONNECTX	SCTP_SOCKOPT_CONNECTX
 };
 
 /*
@@ -527,6 +529,7 @@
 enum sctp_spinfo_state {
 	SCTP_INACTIVE,
 	SCTP_ACTIVE,
+	SCTP_UNKNOWN = 0xffff  /* Value used for transport state unknown */
 };
 
 /*
diff --git a/include/net/snmp.h b/include/net/snmp.h
index a15ab25..a36bed8 100644
--- a/include/net/snmp.h
+++ b/include/net/snmp.h
@@ -128,18 +128,18 @@
 #define SNMP_STAT_USRPTR(name)	(name[1])
 
 #define SNMP_INC_STATS_BH(mib, field) 	\
-	(per_cpu_ptr(mib[0], _smp_processor_id())->mibs[field]++)
+	(per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field]++)
 #define SNMP_INC_STATS_OFFSET_BH(mib, field, offset)	\
-	(per_cpu_ptr(mib[0], _smp_processor_id())->mibs[field + (offset)]++)
+	(per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field + (offset)]++)
 #define SNMP_INC_STATS_USER(mib, field) \
-	(per_cpu_ptr(mib[1], _smp_processor_id())->mibs[field]++)
+	(per_cpu_ptr(mib[1], raw_smp_processor_id())->mibs[field]++)
 #define SNMP_INC_STATS(mib, field) 	\
-	(per_cpu_ptr(mib[!in_softirq()], _smp_processor_id())->mibs[field]++)
+	(per_cpu_ptr(mib[!in_softirq()], raw_smp_processor_id())->mibs[field]++)
 #define SNMP_DEC_STATS(mib, field) 	\
-	(per_cpu_ptr(mib[!in_softirq()], _smp_processor_id())->mibs[field]--)
+	(per_cpu_ptr(mib[!in_softirq()], raw_smp_processor_id())->mibs[field]--)
 #define SNMP_ADD_STATS_BH(mib, field, addend) 	\
-	(per_cpu_ptr(mib[0], _smp_processor_id())->mibs[field] += addend)
+	(per_cpu_ptr(mib[0], raw_smp_processor_id())->mibs[field] += addend)
 #define SNMP_ADD_STATS_USER(mib, field, addend) 	\
-	(per_cpu_ptr(mib[1], _smp_processor_id())->mibs[field] += addend)
+	(per_cpu_ptr(mib[1], raw_smp_processor_id())->mibs[field] += addend)
 
 #endif
diff --git a/include/net/sock.h b/include/net/sock.h
index a9ef3a6..e593af5 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -484,6 +484,8 @@
 
 extern int sk_wait_data(struct sock *sk, long *timeo);
 
+struct request_sock_ops;
+
 /* Networking protocol blocks we attach to sockets.
  * socket layer -> transport layer interface
  * transport -> network interface is defined by struct inet_proto
@@ -547,6 +549,8 @@
 	kmem_cache_t		*slab;
 	unsigned int		obj_size;
 
+	struct request_sock_ops	*rsk_prot;
+
 	struct module		*owner;
 
 	char			name[32];
diff --git a/include/net/tcp.h b/include/net/tcp.h
index e71f8ba..ec9e20c 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -31,6 +31,7 @@
 #include <linux/cache.h>
 #include <linux/percpu.h>
 #include <net/checksum.h>
+#include <net/request_sock.h>
 #include <net/sock.h>
 #include <net/snmp.h>
 #include <net/ip.h>
@@ -504,25 +505,6 @@
 #else
 # define TCP_TW_RECYCLE_TICK (12+2-TCP_TW_RECYCLE_SLOTS_LOG)
 #endif
-
-#define BICTCP_BETA_SCALE    1024	/* Scale factor beta calculation
-					 * max_cwnd = snd_cwnd * beta
-					 */
-#define BICTCP_MAX_INCREMENT 32		/*
-					 * Limit on the amount of
-					 * increment allowed during
-					 * binary search.
-					 */
-#define BICTCP_FUNC_OF_MIN_INCR 11	/*
-					 * log(B/Smin)/log(B/(B-1))+1,
-					 * Smin:min increment
-					 * B:log factor
-					 */
-#define BICTCP_B		4	 /*
-					  * In binary search,
-					  * go to point (max+min)/N
-					  */
-
 /*
  *	TCP option
  */
@@ -563,7 +545,6 @@
 #define TCP_NAGLE_PUSH		4	/* Cork is overriden for already queued data */
 
 /* sysctl variables for tcp */
-extern int sysctl_max_syn_backlog;
 extern int sysctl_tcp_timestamps;
 extern int sysctl_tcp_window_scaling;
 extern int sysctl_tcp_sack;
@@ -596,16 +577,7 @@
 extern int sysctl_tcp_tw_reuse;
 extern int sysctl_tcp_frto;
 extern int sysctl_tcp_low_latency;
-extern int sysctl_tcp_westwood;
-extern int sysctl_tcp_vegas_cong_avoid;
-extern int sysctl_tcp_vegas_alpha;
-extern int sysctl_tcp_vegas_beta;
-extern int sysctl_tcp_vegas_gamma;
 extern int sysctl_tcp_nometrics_save;
-extern int sysctl_tcp_bic;
-extern int sysctl_tcp_bic_fast_convergence;
-extern int sysctl_tcp_bic_low_window;
-extern int sysctl_tcp_bic_beta;
 extern int sysctl_tcp_moderate_rcvbuf;
 extern int sysctl_tcp_tso_win_divisor;
 
@@ -613,74 +585,6 @@
 extern atomic_t tcp_sockets_allocated;
 extern int tcp_memory_pressure;
 
-struct open_request;
-
-struct or_calltable {
-	int  family;
-	int  (*rtx_syn_ack)	(struct sock *sk, struct open_request *req, struct dst_entry*);
-	void (*send_ack)	(struct sk_buff *skb, struct open_request *req);
-	void (*destructor)	(struct open_request *req);
-	void (*send_reset)	(struct sk_buff *skb);
-};
-
-struct tcp_v4_open_req {
-	__u32			loc_addr;
-	__u32			rmt_addr;
-	struct ip_options	*opt;
-};
-
-#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-struct tcp_v6_open_req {
-	struct in6_addr		loc_addr;
-	struct in6_addr		rmt_addr;
-	struct sk_buff		*pktopts;
-	int			iif;
-};
-#endif
-
-/* this structure is too big */
-struct open_request {
-	struct open_request	*dl_next; /* Must be first member! */
-	__u32			rcv_isn;
-	__u32			snt_isn;
-	__u16			rmt_port;
-	__u16			mss;
-	__u8			retrans;
-	__u8			__pad;
-	__u16	snd_wscale : 4, 
-		rcv_wscale : 4, 
-		tstamp_ok : 1,
-		sack_ok : 1,
-		wscale_ok : 1,
-		ecn_ok : 1,
-		acked : 1;
-	/* The following two fields can be easily recomputed I think -AK */
-	__u32			window_clamp;	/* window clamp at creation time */
-	__u32			rcv_wnd;	/* rcv_wnd offered first time */
-	__u32			ts_recent;
-	unsigned long		expires;
-	struct or_calltable	*class;
-	struct sock		*sk;
-	union {
-		struct tcp_v4_open_req v4_req;
-#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
-		struct tcp_v6_open_req v6_req;
-#endif
-	} af;
-};
-
-/* SLAB cache for open requests. */
-extern kmem_cache_t *tcp_openreq_cachep;
-
-#define tcp_openreq_alloc()		kmem_cache_alloc(tcp_openreq_cachep, SLAB_ATOMIC)
-#define tcp_openreq_fastfree(req)	kmem_cache_free(tcp_openreq_cachep, req)
-
-static inline void tcp_openreq_free(struct open_request *req)
-{
-	req->class->destructor(req);
-	tcp_openreq_fastfree(req);
-}
-
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 #define TCP_INET_FAMILY(fam) ((fam) == AF_INET)
 #else
@@ -708,7 +612,7 @@
 
 	struct sock *		(*syn_recv_sock)	(struct sock *sk,
 							 struct sk_buff *skb,
-							 struct open_request *req,
+							 struct request_sock *req,
 							 struct dst_entry *dst);
     
 	int			(*remember_stamp)	(struct sock *sk);
@@ -852,8 +756,8 @@
 							   unsigned len);
 
 extern struct sock *		tcp_check_req(struct sock *sk,struct sk_buff *skb,
-					      struct open_request *req,
-					      struct open_request **prev);
+					      struct request_sock *req,
+					      struct request_sock **prev);
 extern int			tcp_child_process(struct sock *parent,
 						  struct sock *child,
 						  struct sk_buff *skb);
@@ -903,12 +807,12 @@
 						    struct sk_buff *skb);
 
 extern struct sock *		tcp_create_openreq_child(struct sock *sk,
-							 struct open_request *req,
+							 struct request_sock *req,
 							 struct sk_buff *skb);
 
 extern struct sock *		tcp_v4_syn_recv_sock(struct sock *sk,
 						     struct sk_buff *skb,
-						     struct open_request *req,
+						     struct request_sock *req,
 							struct dst_entry *dst);
 
 extern int			tcp_v4_do_rcv(struct sock *sk,
@@ -922,7 +826,7 @@
 
 extern struct sk_buff *		tcp_make_synack(struct sock *sk,
 						struct dst_entry *dst,
-						struct open_request *req);
+						struct request_sock *req);
 
 extern int			tcp_disconnect(struct sock *sk, int flags);
 
@@ -1204,6 +1108,82 @@
 	tp->packets_out -= tcp_skb_pcount(skb);
 }
 
+/* Events passed to congestion control interface */
+enum tcp_ca_event {
+	CA_EVENT_TX_START,	/* first transmit when no packets in flight */
+	CA_EVENT_CWND_RESTART,	/* congestion window restart */
+	CA_EVENT_COMPLETE_CWR,	/* end of congestion recovery */
+	CA_EVENT_FRTO,		/* fast recovery timeout */
+	CA_EVENT_LOSS,		/* loss timeout */
+	CA_EVENT_FAST_ACK,	/* in sequence ack */
+	CA_EVENT_SLOW_ACK,	/* other ack */
+};
+
+/*
+ * Interface for adding new TCP congestion control handlers
+ */
+#define TCP_CA_NAME_MAX	16
+struct tcp_congestion_ops {
+	struct list_head	list;
+
+	/* initialize private data (optional) */
+	void (*init)(struct tcp_sock *tp);
+	/* cleanup private data  (optional) */
+	void (*release)(struct tcp_sock *tp);
+
+	/* return slow start threshold (required) */
+	u32 (*ssthresh)(struct tcp_sock *tp);
+	/* lower bound for congestion window (optional) */
+	u32 (*min_cwnd)(struct tcp_sock *tp);
+	/* do new cwnd calculation (required) */
+	void (*cong_avoid)(struct tcp_sock *tp, u32 ack,
+			   u32 rtt, u32 in_flight, int good_ack);
+	/* round trip time sample per acked packet (optional) */
+	void (*rtt_sample)(struct tcp_sock *tp, u32 usrtt);
+	/* call before changing ca_state (optional) */
+	void (*set_state)(struct tcp_sock *tp, u8 new_state);
+	/* call when cwnd event occurs (optional) */
+	void (*cwnd_event)(struct tcp_sock *tp, enum tcp_ca_event ev);
+	/* new value of cwnd after loss (optional) */
+	u32  (*undo_cwnd)(struct tcp_sock *tp);
+	/* hook for packet ack accounting (optional) */
+	void (*pkts_acked)(struct tcp_sock *tp, u32 num_acked);
+	/* get info for tcp_diag (optional) */
+	void (*get_info)(struct tcp_sock *tp, u32 ext, struct sk_buff *skb);
+
+	char 		name[TCP_CA_NAME_MAX];
+	struct module 	*owner;
+};
+
+extern int tcp_register_congestion_control(struct tcp_congestion_ops *type);
+extern void tcp_unregister_congestion_control(struct tcp_congestion_ops *type);
+
+extern void tcp_init_congestion_control(struct tcp_sock *tp);
+extern void tcp_cleanup_congestion_control(struct tcp_sock *tp);
+extern int tcp_set_default_congestion_control(const char *name);
+extern void tcp_get_default_congestion_control(char *name);
+extern int tcp_set_congestion_control(struct tcp_sock *tp, const char *name);
+
+extern struct tcp_congestion_ops tcp_init_congestion_ops;
+extern u32 tcp_reno_ssthresh(struct tcp_sock *tp);
+extern void tcp_reno_cong_avoid(struct tcp_sock *tp, u32 ack,
+				u32 rtt, u32 in_flight, int flag);
+extern u32 tcp_reno_min_cwnd(struct tcp_sock *tp);
+extern struct tcp_congestion_ops tcp_reno;
+
+static inline void tcp_set_ca_state(struct tcp_sock *tp, u8 ca_state)
+{
+	if (tp->ca_ops->set_state)
+		tp->ca_ops->set_state(tp, ca_state);
+	tp->ca_state = ca_state;
+}
+
+static inline void tcp_ca_event(struct tcp_sock *tp, enum tcp_ca_event event)
+{
+	if (tp->ca_ops->cwnd_event)
+		tp->ca_ops->cwnd_event(tp, event);
+}
+
 /* This determines how many packets are "in the network" to the best
  * of our knowledge.  In many cases it is conservative, but where
  * detailed information is available from the receiver (via SACK
@@ -1223,91 +1203,6 @@
 	return (tp->packets_out - tp->left_out + tp->retrans_out);
 }
 
-/*
- * Which congestion algorithim is in use on the connection.
- */
-#define tcp_is_vegas(__tp)	((__tp)->adv_cong == TCP_VEGAS)
-#define tcp_is_westwood(__tp)	((__tp)->adv_cong == TCP_WESTWOOD)
-#define tcp_is_bic(__tp)	((__tp)->adv_cong == TCP_BIC)
-
-/* Recalculate snd_ssthresh, we want to set it to:
- *
- * Reno:
- * 	one half the current congestion window, but no
- *	less than two segments
- *
- * BIC:
- *	behave like Reno until low_window is reached,
- *	then increase congestion window slowly
- */
-static inline __u32 tcp_recalc_ssthresh(struct tcp_sock *tp)
-{
-	if (tcp_is_bic(tp)) {
-		if (sysctl_tcp_bic_fast_convergence &&
-		    tp->snd_cwnd < tp->bictcp.last_max_cwnd)
-			tp->bictcp.last_max_cwnd = (tp->snd_cwnd * 
-						    (BICTCP_BETA_SCALE
-						     + sysctl_tcp_bic_beta))
-				/ (2 * BICTCP_BETA_SCALE);
-		else
-			tp->bictcp.last_max_cwnd = tp->snd_cwnd;
-
-		if (tp->snd_cwnd > sysctl_tcp_bic_low_window)
-			return max((tp->snd_cwnd * sysctl_tcp_bic_beta)
-				   / BICTCP_BETA_SCALE, 2U);
-	}
-
-	return max(tp->snd_cwnd >> 1U, 2U);
-}
-
-/* Stop taking Vegas samples for now. */
-#define tcp_vegas_disable(__tp)	((__tp)->vegas.doing_vegas_now = 0)
-    
-static inline void tcp_vegas_enable(struct tcp_sock *tp)
-{
-	/* 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.
-	 */
-    
-	/* Begin taking Vegas samples next time we send something. */
-	tp->vegas.doing_vegas_now = 1;
-     
-	/* Set the beginning of the next send window. */
-	tp->vegas.beg_snd_nxt = tp->snd_nxt;
-
-	tp->vegas.cntRTT = 0;
-	tp->vegas.minRTT = 0x7fffffff;
-}
-
-/* Should we be taking Vegas samples right now? */
-#define tcp_vegas_enabled(__tp)	((__tp)->vegas.doing_vegas_now)
-
-extern void tcp_ca_init(struct tcp_sock *tp);
-
-static inline void tcp_set_ca_state(struct tcp_sock *tp, u8 ca_state)
-{
-	if (tcp_is_vegas(tp)) {
-		if (ca_state == TCP_CA_Open) 
-			tcp_vegas_enable(tp);
-		else
-			tcp_vegas_disable(tp);
-	}
-	tp->ca_state = ca_state;
-}
-
 /* If cwnd > ssthresh, we may raise ssthresh to be half-way to cwnd.
  * The exception is rate halving phase, when cwnd is decreasing towards
  * ssthresh.
@@ -1356,7 +1251,7 @@
 static inline void __tcp_enter_cwr(struct tcp_sock *tp)
 {
 	tp->undo_marker = 0;
-	tp->snd_ssthresh = tcp_recalc_ssthresh(tp);
+	tp->snd_ssthresh = tp->ca_ops->ssthresh(tp);
 	tp->snd_cwnd = min(tp->snd_cwnd,
 			   tcp_packets_in_flight(tp) + 1U);
 	tp->snd_cwnd_cnt = 0;
@@ -1750,99 +1645,71 @@
 	return tcp_win_from_space(sk->sk_rcvbuf); 
 }
 
-static inline void tcp_acceptq_queue(struct sock *sk, struct open_request *req,
+static inline void tcp_acceptq_queue(struct sock *sk, struct request_sock *req,
 					 struct sock *child)
 {
-	struct tcp_sock *tp = tcp_sk(sk);
-
-	req->sk = child;
-	sk_acceptq_added(sk);
-
-	if (!tp->accept_queue_tail) {
-		tp->accept_queue = req;
-	} else {
-		tp->accept_queue_tail->dl_next = req;
-	}
-	tp->accept_queue_tail = req;
-	req->dl_next = NULL;
+	reqsk_queue_add(&tcp_sk(sk)->accept_queue, req, sk, child);
 }
 
-struct tcp_listen_opt
-{
-	u8			max_qlen_log;	/* log_2 of maximal queued SYNs */
-	int			qlen;
-	int			qlen_young;
-	int			clock_hand;
-	u32			hash_rnd;
-	struct open_request	*syn_table[TCP_SYNQ_HSIZE];
-};
-
 static inline void
-tcp_synq_removed(struct sock *sk, struct open_request *req)
+tcp_synq_removed(struct sock *sk, struct request_sock *req)
 {
-	struct tcp_listen_opt *lopt = tcp_sk(sk)->listen_opt;
-
-	if (--lopt->qlen == 0)
+	if (reqsk_queue_removed(&tcp_sk(sk)->accept_queue, req) == 0)
 		tcp_delete_keepalive_timer(sk);
-	if (req->retrans == 0)
-		lopt->qlen_young--;
 }
 
 static inline void tcp_synq_added(struct sock *sk)
 {
-	struct tcp_listen_opt *lopt = tcp_sk(sk)->listen_opt;
-
-	if (lopt->qlen++ == 0)
+	if (reqsk_queue_added(&tcp_sk(sk)->accept_queue) == 0)
 		tcp_reset_keepalive_timer(sk, TCP_TIMEOUT_INIT);
-	lopt->qlen_young++;
 }
 
 static inline int tcp_synq_len(struct sock *sk)
 {
-	return tcp_sk(sk)->listen_opt->qlen;
+	return reqsk_queue_len(&tcp_sk(sk)->accept_queue);
 }
 
 static inline int tcp_synq_young(struct sock *sk)
 {
-	return tcp_sk(sk)->listen_opt->qlen_young;
+	return reqsk_queue_len_young(&tcp_sk(sk)->accept_queue);
 }
 
 static inline int tcp_synq_is_full(struct sock *sk)
 {
-	return tcp_synq_len(sk) >> tcp_sk(sk)->listen_opt->max_qlen_log;
+	return reqsk_queue_is_full(&tcp_sk(sk)->accept_queue);
 }
 
-static inline void tcp_synq_unlink(struct tcp_sock *tp, struct open_request *req,
-				       struct open_request **prev)
+static inline void tcp_synq_unlink(struct tcp_sock *tp, struct request_sock *req,
+				   struct request_sock **prev)
 {
-	write_lock(&tp->syn_wait_lock);
-	*prev = req->dl_next;
-	write_unlock(&tp->syn_wait_lock);
+	reqsk_queue_unlink(&tp->accept_queue, req, prev);
 }
 
-static inline void tcp_synq_drop(struct sock *sk, struct open_request *req,
-				     struct open_request **prev)
+static inline void tcp_synq_drop(struct sock *sk, struct request_sock *req,
+				     struct request_sock **prev)
 {
 	tcp_synq_unlink(tcp_sk(sk), req, prev);
 	tcp_synq_removed(sk, req);
-	tcp_openreq_free(req);
+	reqsk_free(req);
 }
 
-static __inline__ void tcp_openreq_init(struct open_request *req,
+static __inline__ void tcp_openreq_init(struct request_sock *req,
 					struct tcp_options_received *rx_opt,
 					struct sk_buff *skb)
 {
+	struct inet_request_sock *ireq = inet_rsk(req);
+
 	req->rcv_wnd = 0;		/* So that tcp_send_synack() knows! */
-	req->rcv_isn = TCP_SKB_CB(skb)->seq;
+	tcp_rsk(req)->rcv_isn = TCP_SKB_CB(skb)->seq;
 	req->mss = rx_opt->mss_clamp;
 	req->ts_recent = rx_opt->saw_tstamp ? rx_opt->rcv_tsval : 0;
-	req->tstamp_ok = rx_opt->tstamp_ok;
-	req->sack_ok = rx_opt->sack_ok;
-	req->snd_wscale = rx_opt->snd_wscale;
-	req->wscale_ok = rx_opt->wscale_ok;
-	req->acked = 0;
-	req->ecn_ok = 0;
-	req->rmt_port = skb->h.th->source;
+	ireq->tstamp_ok = rx_opt->tstamp_ok;
+	ireq->sack_ok = rx_opt->sack_ok;
+	ireq->snd_wscale = rx_opt->snd_wscale;
+	ireq->wscale_ok = rx_opt->wscale_ok;
+	ireq->acked = 0;
+	ireq->ecn_ok = 0;
+	ireq->rmt_port = skb->h.th->source;
 }
 
 extern void tcp_enter_memory_pressure(void);
@@ -1972,52 +1839,4 @@
 extern int tcp_proc_register(struct tcp_seq_afinfo *afinfo);
 extern void tcp_proc_unregister(struct tcp_seq_afinfo *afinfo);
 
-/* TCP Westwood functions and constants */
-
-#define TCP_WESTWOOD_INIT_RTT  (20*HZ)           /* maybe too conservative?! */
-#define TCP_WESTWOOD_RTT_MIN   (HZ/20)           /* 50ms */
-
-static inline void tcp_westwood_update_rtt(struct tcp_sock *tp, __u32 rtt_seq)
-{
-        if (tcp_is_westwood(tp))
-                tp->westwood.rtt = rtt_seq;
-}
-
-static inline __u32 __tcp_westwood_bw_rttmin(const struct tcp_sock *tp)
-{
-        return max((tp->westwood.bw_est) * (tp->westwood.rtt_min) /
-		   (__u32) (tp->mss_cache_std),
-		   2U);
-}
-
-static inline __u32 tcp_westwood_bw_rttmin(const struct tcp_sock *tp)
-{
-	return tcp_is_westwood(tp) ? __tcp_westwood_bw_rttmin(tp) : 0;
-}
-
-static inline int tcp_westwood_ssthresh(struct tcp_sock *tp)
-{
-	__u32 ssthresh = 0;
-
-	if (tcp_is_westwood(tp)) {
-		ssthresh = __tcp_westwood_bw_rttmin(tp);
-		if (ssthresh)
-			tp->snd_ssthresh = ssthresh;  
-	}
-
-	return (ssthresh != 0);
-}
-
-static inline int tcp_westwood_cwnd(struct tcp_sock *tp)
-{
-	__u32 cwnd = 0;
-
-	if (tcp_is_westwood(tp)) {
-		cwnd = __tcp_westwood_bw_rttmin(tp);
-		if (cwnd)
-			tp->snd_cwnd = cwnd;
-	}
-
-	return (cwnd != 0);
-}
 #endif	/* _TCP_H */
diff --git a/include/net/tcp_ecn.h b/include/net/tcp_ecn.h
index dc14563..64980ee 100644
--- a/include/net/tcp_ecn.h
+++ b/include/net/tcp_ecn.h
@@ -2,6 +2,7 @@
 #define _NET_TCP_ECN_H_ 1
 
 #include <net/inet_ecn.h>
+#include <net/request_sock.h>
 
 #define TCP_HP_BITS (~(TCP_RESERVED_BITS|TCP_FLAG_PSH))
 
@@ -38,9 +39,9 @@
 }
 
 static __inline__ void
-TCP_ECN_make_synack(struct open_request *req, struct tcphdr *th)
+TCP_ECN_make_synack(struct request_sock *req, struct tcphdr *th)
 {
-	if (req->ecn_ok)
+	if (inet_rsk(req)->ecn_ok)
 		th->ece = 1;
 }
 
@@ -111,16 +112,16 @@
 }
 
 static inline void TCP_ECN_openreq_child(struct tcp_sock *tp,
-					 struct open_request *req)
+					 struct request_sock *req)
 {
-	tp->ecn_flags = req->ecn_ok ? TCP_ECN_OK : 0;
+	tp->ecn_flags = inet_rsk(req)->ecn_ok ? TCP_ECN_OK : 0;
 }
 
 static __inline__ void
-TCP_ECN_create_request(struct open_request *req, struct tcphdr *th)
+TCP_ECN_create_request(struct request_sock *req, struct tcphdr *th)
 {
 	if (sysctl_tcp_ecn && th->ece && th->cwr)
-		req->ecn_ok = 1;
+		inet_rsk(req)->ecn_ok = 1;
 }
 
 #endif
diff --git a/include/net/x25.h b/include/net/x25.h
index 7a1ba5b..8b39b98 100644
--- a/include/net/x25.h
+++ b/include/net/x25.h
@@ -79,6 +79,8 @@
 #define	X25_DEFAULT_PACKET_SIZE	X25_PS128		/* Default Packet Size */
 #define	X25_DEFAULT_THROUGHPUT	0x0A			/* Deafult Throughput */
 #define	X25_DEFAULT_REVERSE	0x00			/* Default Reverse Charging */
+#define X25_DENY_ACCPT_APPRV   0x01			/* Default value */
+#define X25_ALLOW_ACCPT_APPRV  0x00			/* Control enabled */
 
 #define X25_SMODULUS 		8
 #define	X25_EMODULUS		128
@@ -94,7 +96,7 @@
 #define	X25_FAC_CLASS_C		0x80
 #define	X25_FAC_CLASS_D		0xC0
 
-#define	X25_FAC_REVERSE		0x01
+#define	X25_FAC_REVERSE		0x01			/* also fast select */
 #define	X25_FAC_THROUGHPUT	0x02
 #define	X25_FAC_PACKET_SIZE	0x42
 #define	X25_FAC_WINDOW_SIZE	0x43
@@ -134,8 +136,8 @@
 	struct sock		sk;
 	struct x25_address	source_addr, dest_addr;
 	struct x25_neigh	*neighbour;
-	unsigned int		lci;
-	unsigned char		state, condition, qbitincl, intflag;
+	unsigned int		lci, cudmatchlength;
+	unsigned char		state, condition, qbitincl, intflag, accptapprv;
 	unsigned short		vs, vr, va, vl;
 	unsigned long		t2, t21, t22, t23;
 	unsigned short		fraglen;
@@ -242,7 +244,6 @@
 extern void x25_write_internal(struct sock *, int);
 extern int  x25_decode(struct sock *, struct sk_buff *, int *, int *, int *, int *, int *);
 extern void x25_disconnect(struct sock *, int, unsigned char, unsigned char);
-extern int x25_check_calluserdata(struct x25_calluserdata *,struct x25_calluserdata *);
 
 /* x25_timer.c */
 extern void x25_start_heartbeat(struct sock *);
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index d675836..029522a 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -158,6 +158,20 @@
 	XFRM_STATE_DEAD
 };
 
+/* callback structure passed from either netlink or pfkey */
+struct km_event
+{
+	union {
+		u32 hard;
+		u32 proto;
+		u32 byid;
+	} data;
+
+	u32	seq;
+	u32	pid;
+	u32	event;
+};
+
 struct xfrm_type;
 struct xfrm_dst;
 struct xfrm_policy_afinfo {
@@ -179,6 +193,8 @@
 
 extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo);
 extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo);
+extern void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c);
+extern void km_state_notify(struct xfrm_state *x, struct km_event *c);
 
 #define XFRM_ACQ_EXPIRES	30
 
@@ -188,6 +204,7 @@
 	rwlock_t		lock;
 	struct list_head	*state_bydst;
 	struct list_head	*state_byspi;
+	int			(*init_flags)(struct xfrm_state *x);
 	void			(*init_tempsel)(struct xfrm_state *x, struct flowi *fl,
 						struct xfrm_tmpl *tmpl,
 						xfrm_address_t *daddr, xfrm_address_t *saddr);
@@ -209,7 +226,7 @@
 	struct module		*owner;
 	__u8			proto;
 
-	int			(*init_state)(struct xfrm_state *x, void *args);
+	int			(*init_state)(struct xfrm_state *x);
 	void			(*destructor)(struct xfrm_state *);
 	int			(*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
 	int			(*post_input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
@@ -290,11 +307,11 @@
 {
 	struct list_head	list;
 	char			*id;
-	int			(*notify)(struct xfrm_state *x, int event);
+	int			(*notify)(struct xfrm_state *x, struct km_event *c);
 	int			(*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir);
 	struct xfrm_policy	*(*compile_policy)(u16 family, int opt, u8 *data, int len, int *dir);
 	int			(*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport);
-	int			(*notify_policy)(struct xfrm_policy *x, int dir, int event);
+	int			(*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c);
 };
 
 extern int xfrm_register_km(struct xfrm_mgr *km);
@@ -656,7 +673,7 @@
 	return 0;
 }
 
-extern void xfrm_policy_delete(struct xfrm_policy *pol, int dir);
+extern int xfrm_policy_delete(struct xfrm_policy *pol, int dir);
 
 static inline void xfrm_sk_free_policy(struct sock *sk)
 {
@@ -817,12 +834,13 @@
 extern int xfrm_state_update(struct xfrm_state *x);
 extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family);
 extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
-extern void xfrm_state_delete(struct xfrm_state *x);
+extern int xfrm_state_delete(struct xfrm_state *x);
 extern void xfrm_state_flush(u8 proto);
 extern int xfrm_replay_check(struct xfrm_state *x, u32 seq);
 extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq);
 extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb);
 extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
+extern int xfrm_init_state(struct xfrm_state *x);
 extern int xfrm4_rcv(struct sk_buff *skb);
 extern int xfrm4_output(struct sk_buff *skb);
 extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h
index 6d3413a..67b867f3 100644
--- a/include/pcmcia/ss.h
+++ b/include/pcmcia/ss.h
@@ -77,6 +77,11 @@
 /* Use this just for bridge windows */
 #define MAP_IOSPACE	0x20
 
+/* power hook operations */
+#define HOOK_POWER_PRE	0x01
+#define HOOK_POWER_POST	0x02
+
+
 typedef struct pccard_io_map {
     u_char	map;
     u_char	flags;
@@ -222,6 +227,9 @@
 	/* Zoom video behaviour is so chip specific its not worth adding
 	   this to _ops */
 	void 				(*zoom_video)(struct pcmcia_socket *, int);
+
+	/* so is power hook */
+	int (*power_hook)(struct pcmcia_socket *sock, int operation);
                            
 	/* state thread */
 	struct semaphore		skt_sem;	/* protects socket h/w state */
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 659ecf4..1fb2337 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -41,6 +41,7 @@
 #define FORMAT_UNIT           0x04
 #define READ_BLOCK_LIMITS     0x05
 #define REASSIGN_BLOCKS       0x07
+#define INITIALIZE_ELEMENT_STATUS 0x07
 #define READ_6                0x08
 #define WRITE_6               0x0a
 #define SEEK_6                0x0b
@@ -65,6 +66,7 @@
 #define READ_10               0x28
 #define WRITE_10              0x2a
 #define SEEK_10               0x2b
+#define POSITION_TO_ELEMENT   0x2b
 #define WRITE_VERIFY          0x2e
 #define VERIFY                0x2f
 #define SEARCH_HIGH           0x30
@@ -97,6 +99,7 @@
 #define PERSISTENT_RESERVE_OUT 0x5f
 #define REPORT_LUNS           0xa0
 #define MOVE_MEDIUM           0xa5
+#define EXCHANGE_MEDIUM       0xa6
 #define READ_12               0xa8
 #define WRITE_12              0xaa
 #define WRITE_VERIFY_12       0xae
@@ -210,6 +213,7 @@
 #define TYPE_COMM           0x09    /* Communications device */
 #define TYPE_ENCLOSURE      0x0d    /* Enclosure Services Device */
 #define TYPE_RAID           0x0c
+#define TYPE_RBC	    0x0e
 #define TYPE_NO_LUN         0x7f
 
 /*
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index c018020..63c91dd 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -154,7 +154,9 @@
 	unsigned int		id; /* target id ... replace
 				     * scsi_device.id eventually */
 	unsigned long		create:1; /* signal that it needs to be added */
-	unsigned long		starget_data[0];
+	void 			*hostdata; /* available to low-level driver */
+	unsigned long		starget_data[0]; /* for the transport */
+	/* starget_data must be the last element!!!! */
 } __attribute__((aligned(sizeof(unsigned long))));
 
 #define to_scsi_target(d)	container_of(d, struct scsi_target, dev)
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 1cee1e1..db9914a 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -10,6 +10,7 @@
 struct module;
 struct scsi_cmnd;
 struct scsi_device;
+struct scsi_target;
 struct Scsi_Host;
 struct scsi_host_cmd_pool;
 struct scsi_transport_template;
@@ -228,6 +229,30 @@
 	void (* slave_destroy)(struct scsi_device *);
 
 	/*
+	 * Before the mid layer attempts to scan for a new device attached
+	 * to a target where no target currently exists, it will call this
+	 * entry in your driver.  Should your driver need to allocate any
+	 * structs or perform any other init items in order to send commands
+	 * to a currently unused target, then this is where you can perform
+	 * those allocations.
+	 *
+	 * Return values: 0 on success, non-0 on failure
+	 *
+	 * Status: OPTIONAL
+	 */
+	int (* target_alloc)(struct scsi_target *);
+
+	/*
+	 * Immediately prior to deallocating the target structure, and
+	 * after all activity to attached scsi devices has ceased, the
+	 * midlayer calls this point so that the driver may deallocate
+	 * and terminate any references to the target.
+	 *
+	 * Status: OPTIONAL
+	 */
+	void (* target_destroy)(struct scsi_target *);
+
+	/*
 	 * fill in this function to allow the queue depth of this host
 	 * to be changeable (on a per device basis).  returns either
 	 * the current queue depth setting (may be different from what
diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h
index 2dcee7a..a4f1837 100644
--- a/include/scsi/scsi_transport.h
+++ b/include/scsi/scsi_transport.h
@@ -21,6 +21,7 @@
 #define SCSI_TRANSPORT_H
 
 #include <linux/transport_class.h>
+#include <scsi/scsi_host.h>
 
 struct scsi_transport_template {
 	/* the attribute containers */
@@ -32,8 +33,11 @@
 	 * space of this size will be left at the end of the
 	 * scsi_* structure */
 	int	device_size;
+	int	device_private_offset;
 	int	target_size;
+	int	target_private_offset;
 	int	host_size;
+	/* no private offset for the host; there's an alternative mechanism */
 
 	/*
 	 * True if the transport wants to use a host-based work-queue
@@ -45,4 +49,38 @@
 	dev_to_shost((tc)->dev)
 
 
+/* Private area maintenance. The driver requested allocations come
+ * directly after the transport class allocations (if any).  The idea
+ * is that you *must* call these only once.  The code assumes that the
+ * initial values are the ones the transport specific code requires */
+static inline void
+scsi_transport_reserve_target(struct scsi_transport_template * t, int space)
+{
+	BUG_ON(t->target_private_offset != 0);
+	t->target_private_offset = ALIGN(t->target_size, sizeof(void *));
+	t->target_size = t->target_private_offset + space;
+}
+static inline void
+scsi_transport_reserve_device(struct scsi_transport_template * t, int space)
+{
+	BUG_ON(t->device_private_offset != 0);
+	t->device_private_offset = ALIGN(t->device_size, sizeof(void *));
+	t->device_size = t->device_private_offset + space;
+}
+static inline void *
+scsi_transport_target_data(struct scsi_target *starget)
+{
+	struct Scsi_Host *shost = dev_to_shost(&starget->dev);
+	return (u8 *)starget->starget_data
+		+ shost->transportt->target_private_offset;
+
+}
+static inline void *
+scsi_transport_device_data(struct scsi_device *sdev)
+{
+	struct Scsi_Host *shost = sdev->host;
+	return (u8 *)sdev->sdev_data
+		+ shost->transportt->device_private_offset;
+}
+
 #endif /* SCSI_TRANSPORT_H */
diff --git a/include/scsi/sg_request.h b/include/scsi/sg_request.h
new file mode 100644
index 0000000..57ff525
--- /dev/null
+++ b/include/scsi/sg_request.h
@@ -0,0 +1,26 @@
+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/sound/ac97_codec.h b/include/sound/ac97_codec.h
index 2433e27..1309c12 100644
--- a/include/sound/ac97_codec.h
+++ b/include/sound/ac97_codec.h
@@ -437,6 +437,7 @@
 	void (*suspend) (ac97_t *ac97);
 	void (*resume) (ac97_t *ac97);
 #endif
+	void (*update_jacks) (ac97_t *ac97);	/* for jack-sharing */
 };
 
 struct _snd_ac97_bus_ops {
@@ -516,6 +517,9 @@
 		} ad18xx;
 		unsigned int dev_flags;		/* device specific */
 	} spec;
+	/* jack-sharing info */
+	unsigned char indep_surround;
+	unsigned char channel_mode;
 };
 
 /* conditions */
@@ -569,8 +573,8 @@
 };
 
 struct ac97_quirk {
-	unsigned short vendor;	/* PCI vendor id */
-	unsigned short device;	/* PCI device id */
+	unsigned short subvendor; /* PCI subsystem vendor id */
+	unsigned short subdevice; /* PCI sybsystem device id */
 	unsigned short mask;	/* device id bit mask, 0 = accept all */
 	unsigned int codec_id;	/* codec id (if any), 0 = accept all */
 	const char *name;	/* name shown as info */
diff --git a/include/sound/asound.h b/include/sound/asound.h
index a4d149f..9974f83 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -113,9 +113,10 @@
 	SNDRV_HWDEP_IFACE_BLUETOOTH,	/* Bluetooth audio */
 	SNDRV_HWDEP_IFACE_USX2Y_PCM,	/* Tascam US122, US224 & US428 rawusb pcm */
 	SNDRV_HWDEP_IFACE_PCXHR,	/* Digigram PCXHR */
+	SNDRV_HWDEP_IFACE_SB_RC,	/* SB Extigy/Audigy2NX remote control */
 
 	/* Don't forget to change the following: */
-	SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_PCXHR
+	SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_SB_RC
 };
 
 struct sndrv_hwdep_info {
@@ -344,7 +345,7 @@
 	SNDRV_PCM_HW_PARAM_LAST_INTERVAL = SNDRV_PCM_HW_PARAM_TICK_TIME
 };
 
-#define SNDRV_PCM_HW_PARAMS_RUNTIME		(1<<0)
+#define SNDRV_PCM_HW_PARAMS_NORESAMPLE		(1<<0)	/* avoid rate resampling */
 
 struct sndrv_interval {
 	unsigned int min, max;
@@ -559,7 +560,7 @@
  *  Timer section - /dev/snd/timer
  */
 
-#define SNDRV_TIMER_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 2)
+#define SNDRV_TIMER_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 4)
 
 enum sndrv_timer_class {
 	SNDRV_TIMER_CLASS_NONE = -1,
@@ -672,10 +673,11 @@
 	SNDRV_TIMER_IOCTL_INFO = _IOR('T', 0x11, struct sndrv_timer_info),
 	SNDRV_TIMER_IOCTL_PARAMS = _IOW('T', 0x12, struct sndrv_timer_params),
 	SNDRV_TIMER_IOCTL_STATUS = _IOR('T', 0x14, struct sndrv_timer_status),
-	SNDRV_TIMER_IOCTL_START = _IO('T', 0x20),
-	SNDRV_TIMER_IOCTL_STOP = _IO('T', 0x21),
-	SNDRV_TIMER_IOCTL_CONTINUE = _IO('T', 0x22),
-	SNDRV_TIMER_IOCTL_PAUSE = _IO('T', 0x23),
+	/* The following four ioctls are changed since 1.0.9 due to confliction */
+	SNDRV_TIMER_IOCTL_START = _IO('T', 0xa0),
+	SNDRV_TIMER_IOCTL_STOP = _IO('T', 0xa1),
+	SNDRV_TIMER_IOCTL_CONTINUE = _IO('T', 0xa2),
+	SNDRV_TIMER_IOCTL_PAUSE = _IO('T', 0xa3),
 };
 
 struct sndrv_timer_read {
diff --git a/include/sound/control.h b/include/sound/control.h
index 7b9444c..ef7903c 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -106,7 +106,7 @@
 void snd_ctl_notify(snd_card_t * card, unsigned int mask, snd_ctl_elem_id_t * id);
 
 snd_kcontrol_t *snd_ctl_new(snd_kcontrol_t * kcontrol, unsigned int access);
-snd_kcontrol_t *snd_ctl_new1(snd_kcontrol_new_t * kcontrolnew, void * private_data);
+snd_kcontrol_t *snd_ctl_new1(const snd_kcontrol_new_t * kcontrolnew, void * private_data);
 void snd_ctl_free_one(snd_kcontrol_t * kcontrol);
 int snd_ctl_add(snd_card_t * card, snd_kcontrol_t * kcontrol);
 int snd_ctl_remove(snd_card_t * card, snd_kcontrol_t * kcontrol);
diff --git a/include/sound/core.h b/include/sound/core.h
index 9117c23..f8c4ef0a 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -292,6 +292,7 @@
 void snd_hidden_kfree(const void *obj);
 void *snd_hidden_vmalloc(unsigned long size);
 void snd_hidden_vfree(void *obj);
+char *snd_hidden_kstrdup(const char *s, int flags);
 #define kmalloc(size, flags) snd_hidden_kmalloc(size, flags)
 #define kcalloc(n, size, flags) snd_hidden_kcalloc(n, size, flags)
 #define kfree(obj) snd_hidden_kfree(obj)
@@ -301,6 +302,7 @@
 #define vmalloc_nocheck(size) snd_wrapper_vmalloc(size)
 #define kfree_nocheck(obj) snd_wrapper_kfree(obj)
 #define vfree_nocheck(obj) snd_wrapper_vfree(obj)
+#define kstrdup(s, flags)  snd_hidden_kstrdup(s, flags)
 #else
 #define snd_memory_init() /*NOP*/
 #define snd_memory_done() /*NOP*/
@@ -311,7 +313,6 @@
 #define kfree_nocheck(obj) kfree(obj)
 #define vfree_nocheck(obj) vfree(obj)
 #endif
-char *snd_kmalloc_strdup(const char *string, int flags);
 int copy_to_user_fromio(void __user *dst, const volatile void __iomem *src, size_t count);
 int copy_from_user_toio(volatile void __iomem *dst, const void __user *src, size_t count);
 
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index 43b6786..c50b919 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -83,7 +83,8 @@
 #define IPR			0x08		/* Global interrupt pending register		*/
 						/* Clear pending interrupts by writing a 1 to	*/
 						/* the relevant bits and zero to the other bits	*/
-
+#define IPR_P16V		0x80000000	/* Bit set when the CA0151 P16V chip wishes
+						   to interrupt */
 #define IPR_GPIOMSG		0x20000000	/* GPIO message interrupt (RE'd, still not sure 
 						   which INTE bits enable it)			*/
 
@@ -746,6 +747,7 @@
 						/* Assumes sample lock				*/
 
 /* These three bitfields apply to CDSRCS, GPSRCS, and (except as noted) ZVSRCS.			*/
+#define SRCS_SPDIFVALID		0x04000000	/* SPDIF stream valid				*/
 #define SRCS_SPDIFLOCKED	0x02000000	/* SPDIF stream locked				*/
 #define SRCS_RATELOCKED		0x01000000	/* Sample rate locked				*/
 #define SRCS_ESTSAMPLERATE	0x0007ffff	/* Do not modify this field.			*/
@@ -803,10 +805,26 @@
 #define A_FXWC2			0x75		/* Selects 0x9f-0x80 for FX recording           */
 
 #define A_SPDIF_SAMPLERATE	0x76		/* Set the sample rate of SPDIF output		*/
-#define A_SPDIF_RATE_MASK	0x000000c0
+#define A_SAMPLE_RATE		0x76		/* Various sample rate settings. */
+#define A_SAMPLE_RATE_NOT_USED  0x0ffc111e	/* Bits that are not used and cannot be set. 	*/
+#define A_SAMPLE_RATE_UNKNOWN	0xf0030001	/* Bits that can be set, but have unknown use. 	*/
+#define A_SPDIF_RATE_MASK	0x000000e0	/* Any other values for rates, just use 48000	*/
 #define A_SPDIF_48000		0x00000000
-#define A_SPDIF_44100		0x00000080
+#define A_SPDIF_192000		0x00000020
 #define A_SPDIF_96000		0x00000040
+#define A_SPDIF_44100		0x00000080
+
+#define A_I2S_CAPTURE_RATE_MASK	0x00000e00	/* This sets the capture PCM rate, but it is    */
+#define A_I2S_CAPTURE_48000	0x00000000	/* unclear if this sets the ADC rate as well.	*/
+#define A_I2S_CAPTURE_192000	0x00000200
+#define A_I2S_CAPTURE_96000	0x00000400
+#define A_I2S_CAPTURE_44100	0x00000800
+
+#define A_PCM_RATE_MASK		0x0000e000	/* This sets the playback PCM rate on the P16V	*/
+#define A_PCM_48000		0x00000000
+#define A_PCM_192000		0x00002000
+#define A_PCM_96000		0x00004000
+#define A_PCM_44100		0x00008000
 
 /* 0x77,0x78,0x79 "something i2s-related" - default to 0x01080000 on my audigy 2 ZS --rlrevell	*/
 /* 0x7a, 0x7b - lookup tables */
@@ -1039,28 +1057,28 @@
 	u32 vendor;
 	u32 device;
 	u32 subsystem;
+	unsigned char revision;
 	unsigned char emu10k1_chip; /* Original SB Live. Not SB Live 24bit. */
 	unsigned char emu10k2_chip; /* Audigy 1 or Audigy 2. */
 	unsigned char ca0102_chip;  /* Audigy 1 or Audigy 2. Not SB Audigy 2 Value. */
 	unsigned char ca0108_chip;  /* Audigy 2 Value */
 	unsigned char ca0151_chip;  /* P16V */
 	unsigned char spk71;        /* Has 7.1 speakers */
+	unsigned char sblive51;	    /* SBLive! 5.1 - extout 0x11 -> center, 0x12 -> lfe */
 	unsigned char spdif_bug;    /* Has Spdif phasing bug */
 	unsigned char ac97_chip;    /* Has an AC97 chip */
 	unsigned char ecard;        /* APS EEPROM */
-	char * driver;
-	char * name;
+	const char *driver;
+	const char *name;
+	const char *id;		/* for backward compatibility - can be NULL if not needed */
 } emu_chip_details_t;
 
 struct _snd_emu10k1 {
 	int irq;
 
 	unsigned long port;			/* I/O port number */
-	unsigned int APS: 1,			/* APS flag */
-	    no_ac97: 1,				/* no AC'97 */
-	    tos_link: 1,			/* tos link detected */
-	    rear_ac97: 1,			/* rear channels are on AC'97 */
-	    spk71:1;				/* 7.1 configuration (Audigy 2 ZS) */
+	unsigned int tos_link: 1,		/* tos link detected */
+	    rear_ac97: 1;			/* rear channels are on AC'97 */
 	const emu_chip_details_t *card_capabilities;	/* Contains profile of card capabilities */
 	unsigned int audigy;			/* is Audigy? */
 	unsigned int revision;			/* chip revision */
@@ -1109,7 +1127,10 @@
 
 	emu10k1_voice_t voices[NUM_G];
 	emu10k1_voice_t p16v_voices[4];
+	emu10k1_voice_t p16v_capture_voice;
 	int p16v_device_offset;
+	u32 p16v_capture_source;
+	u32 p16v_capture_channel;
 	emu10k1_pcm_mixer_t pcm_mixer[32];
 	emu10k1_pcm_mixer_t efx_pcm_mixer[NUM_EFX_PLAYBACK];
 	snd_kcontrol_t *ctl_send_routing;
@@ -1453,7 +1474,6 @@
 #endif
 
 typedef struct {
-	unsigned int card;			/* card type */
 	unsigned int internal_tram_size;	/* in samples */
 	unsigned int external_tram_size;	/* in samples */
 	char fxbus_names[16][32];		/* names of FXBUSes */
diff --git a/include/sound/gus.h b/include/sound/gus.h
index 8b6287a..b4b461c 100644
--- a/include/sound/gus.h
+++ b/include/sound/gus.h
@@ -526,9 +526,6 @@
 extern void snd_gf1_dram_addr(snd_gus_card_t * gus, unsigned int addr);
 extern void snd_gf1_poke(snd_gus_card_t * gus, unsigned int addr, unsigned char data);
 extern unsigned char snd_gf1_peek(snd_gus_card_t * gus, unsigned int addr);
-extern void snd_gf1_pokew(snd_gus_card_t * gus, unsigned int addr, unsigned short data);
-extern unsigned short snd_gf1_peekw(snd_gus_card_t * gus, unsigned int addr);
-extern void snd_gf1_dram_setmem(snd_gus_card_t * gus, unsigned int addr, unsigned short value, unsigned int count);
 extern void snd_gf1_write_addr(snd_gus_card_t * gus, unsigned char reg, unsigned int addr, short w_16bit);
 extern unsigned int snd_gf1_read_addr(snd_gus_card_t * gus, unsigned char reg, short w_16bit);
 extern void snd_gf1_i_ctrl_stop(snd_gus_card_t * gus, unsigned char reg);
@@ -544,9 +541,6 @@
 {
 	return snd_gf1_i_look16(gus, reg | 0x80);
 }
-extern void snd_gf1_i_adlib_write(snd_gus_card_t * gus, unsigned char reg, unsigned char data);
-extern void snd_gf1_i_write_addr(snd_gus_card_t * gus, unsigned char reg, unsigned int addr, short w_16bit);
-extern unsigned int snd_gf1_i_read_addr(snd_gus_card_t * gus, unsigned char reg, short w_16bit);
 
 extern void snd_gf1_select_active_voices(snd_gus_card_t * gus);
 
@@ -580,10 +574,6 @@
 
 void snd_gf1_mem_lock(snd_gf1_mem_t * alloc, int xup);
 int snd_gf1_mem_xfree(snd_gf1_mem_t * alloc, snd_gf1_mem_block_t * block);
-snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc,
-				      unsigned int address);
-snd_gf1_mem_block_t *snd_gf1_mem_share(snd_gf1_mem_t * alloc,
-				       unsigned int *share_id);
 snd_gf1_mem_block_t *snd_gf1_mem_alloc(snd_gf1_mem_t * alloc, int owner,
 				       char *name, int size, int w_16,
 				       int align, unsigned int *share_id);
@@ -608,23 +598,13 @@
 /* gus_volume.c */
 
 unsigned short snd_gf1_lvol_to_gvol_raw(unsigned int vol);
-unsigned int snd_gf1_gvol_to_lvol_raw(unsigned short gf1_vol);
-unsigned int snd_gf1_calc_ramp_rate(snd_gus_card_t * gus,
-				    unsigned short start,
-				    unsigned short end,
-				    unsigned int us);
 unsigned short snd_gf1_translate_freq(snd_gus_card_t * gus, unsigned int freq2);
-unsigned short snd_gf1_compute_pitchbend(unsigned short pitchbend, unsigned short sens);
-unsigned short snd_gf1_compute_freq(unsigned int freq,
-				    unsigned int rate,
-				    unsigned short mix_rate);
 
 /* gus_reset.c */
 
 void snd_gf1_set_default_handlers(snd_gus_card_t * gus, unsigned int what);
 void snd_gf1_smart_stop_voice(snd_gus_card_t * gus, unsigned short voice);
 void snd_gf1_stop_voice(snd_gus_card_t * gus, unsigned short voice);
-void snd_gf1_clear_voices(snd_gus_card_t * gus, unsigned short v_min, unsigned short v_max);
 void snd_gf1_stop_voices(snd_gus_card_t * gus, unsigned short v_min, unsigned short v_max);
 snd_gus_voice_t *snd_gf1_alloc_voice(snd_gus_card_t * gus, int type, int client, int port);
 void snd_gf1_free_voice(snd_gus_card_t * gus, snd_gus_voice_t *voice);
@@ -641,9 +621,6 @@
 
 #ifdef CONFIG_SND_DEBUG
 extern void snd_gf1_print_voice_registers(snd_gus_card_t * gus);
-extern void snd_gf1_print_global_registers(snd_gus_card_t * gus);
-extern void snd_gf1_print_setup_registers(snd_gus_card_t * gus);
-extern void snd_gf1_peek_print_block(snd_gus_card_t * gus, unsigned int addr, int count, int w_16bit);
 #endif
 
 /* gus.c */
diff --git a/include/sound/hdspm.h b/include/sound/hdspm.h
new file mode 100644
index 0000000..c34427c
--- /dev/null
+++ b/include/sound/hdspm.h
@@ -0,0 +1,131 @@
+#ifndef __SOUND_HDSPM_H		/* -*- linux-c -*- */
+#define __SOUND_HDSPM_H
+/*
+ *   Copyright (C) 2003 Winfried Ritsch (IEM)
+ *   based on hdsp.h from Thomas Charbonnel (thomas@undata.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.
+ */
+
+/* Maximum channels is 64 even on 56Mode you have 64playbacks to matrix */
+#define HDSPM_MAX_CHANNELS      64
+
+/* -------------------- IOCTL Peak/RMS Meters -------------------- */
+
+typedef struct _snd_hdspm_peak_rms hdspm_peak_rms_t;
+
+/* peam rms level structure like we get from hardware 
+  
+   maybe in future we can memory map it so I just copy it
+   to user on ioctl call now an dont change anything
+   rms are made out of low and high values
+   where (long) ????_rms = (????_rms_l >> 8) + ((????_rms_h & 0xFFFFFF00)<<24)
+   (i asume so from the code)
+*/
+
+struct _snd_hdspm_peak_rms {
+
+	unsigned int level_offset[1024];
+
+	unsigned int input_peak[64];
+	unsigned int playback_peak[64];
+	unsigned int output_peak[64];
+	unsigned int xxx_peak[64];	/* not used */
+
+	unsigned int reserved[256];	/* not used */
+
+	unsigned int input_rms_l[64];
+	unsigned int playback_rms_l[64];
+	unsigned int output_rms_l[64];
+	unsigned int xxx_rms_l[64];	/* not used */
+
+	unsigned int input_rms_h[64];
+	unsigned int playback_rms_h[64];
+	unsigned int output_rms_h[64];
+	unsigned int xxx_rms_h[64];	/* not used */
+};
+
+struct sndrv_hdspm_peak_rms_ioctl {
+	hdspm_peak_rms_t *peak;
+};
+
+/* use indirect access due to the limit of ioctl bit size */
+#define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS _IOR('H', 0x40, struct sndrv_hdspm_peak_rms_ioctl)
+
+/* ------------ CONFIG block IOCTL ---------------------- */
+
+typedef struct _snd_hdspm_config_info hdspm_config_info_t;
+
+struct _snd_hdspm_config_info {
+	unsigned char pref_sync_ref;
+	unsigned char wordclock_sync_check;
+	unsigned char madi_sync_check;
+	unsigned int system_sample_rate;
+	unsigned int autosync_sample_rate;
+	unsigned char system_clock_mode;
+	unsigned char clock_source;
+	unsigned char autosync_ref;
+	unsigned char line_out;
+	unsigned int passthru;
+	unsigned int analog_out;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO _IOR('H', 0x41, hdspm_config_info_t)
+
+
+/* get Soundcard Version */
+
+typedef struct _snd_hdspm_version hdspm_version_t;
+
+struct _snd_hdspm_version {
+	unsigned short firmware_rev;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_VERSION _IOR('H', 0x43, hdspm_version_t)
+
+
+/* ------------- get Matrix Mixer IOCTL --------------- */
+
+/* MADI mixer: 64inputs+64playback in 64outputs = 8192 => *4Byte = 32768 Bytes */
+
+/* organisation is 64 channelfader in a continous memory block */
+/* equivalent to hardware definition, maybe for future feature of mmap of them */
+/* each of 64 outputs has 64 infader and 64 outfader: 
+   Ins to Outs mixer[out].in[in], Outstreams to Outs mixer[out].pb[pb] */
+
+#define HDSPM_MIXER_CHANNELS HDSPM_MAX_CHANNELS
+
+typedef struct _snd_hdspm_channelfader snd_hdspm_channelfader_t;
+
+struct _snd_hdspm_channelfader {
+	unsigned int in[HDSPM_MIXER_CHANNELS];
+	unsigned int pb[HDSPM_MIXER_CHANNELS];
+};
+
+typedef struct _snd_hdspm_mixer hdspm_mixer_t;
+
+struct _snd_hdspm_mixer {
+	snd_hdspm_channelfader_t ch[HDSPM_MIXER_CHANNELS];
+};
+
+struct sndrv_hdspm_mixer_ioctl {
+	hdspm_mixer_t *mixer;
+};
+
+/* use indirect access due to the limit of ioctl bit size */
+#define SNDRV_HDSPM_IOCTL_GET_MIXER _IOR('H', 0x44, struct sndrv_hdspm_mixer_ioctl)
+
+#endif				/* __SOUND_HDSPM_H */
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 53fc04d..d935417 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -848,23 +848,6 @@
 
 void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params);
 void _snd_pcm_hw_param_setempty(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var);
-int snd_pcm_hw_param_min(snd_pcm_substream_t *substream, 
-			 snd_pcm_hw_params_t *params,
-			 snd_pcm_hw_param_t var,
-			 unsigned int val, int *dir);
-int snd_pcm_hw_param_max(snd_pcm_substream_t *substream, 
-			 snd_pcm_hw_params_t *params,
-			 snd_pcm_hw_param_t var,
-			 unsigned int val, int *dir);
-int snd_pcm_hw_param_setinteger(snd_pcm_substream_t *substream, 
-				snd_pcm_hw_params_t *params,
-				snd_pcm_hw_param_t var);
-int snd_pcm_hw_param_first(snd_pcm_substream_t *substream, 
-			   snd_pcm_hw_params_t *params,
-			   snd_pcm_hw_param_t var, int *dir);
-int snd_pcm_hw_param_last(snd_pcm_substream_t *substream, 
-			  snd_pcm_hw_params_t *params,
-			  snd_pcm_hw_param_t var, int *dir);
 int snd_pcm_hw_param_near(snd_pcm_substream_t *substream, 
 			  snd_pcm_hw_params_t *params,
 			  snd_pcm_hw_param_t var, 
@@ -876,7 +859,6 @@
 int snd_pcm_hw_params_choose(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params);
 
 int snd_pcm_hw_refine(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params);
-int snd_pcm_hw_params(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *params);
 
 int snd_pcm_hw_constraints_init(snd_pcm_substream_t *substream);
 int snd_pcm_hw_constraints_complete(snd_pcm_substream_t *substream);
@@ -922,8 +904,22 @@
 int snd_pcm_format_linear(snd_pcm_format_t format);
 int snd_pcm_format_little_endian(snd_pcm_format_t format);
 int snd_pcm_format_big_endian(snd_pcm_format_t format);
+/**
+ * snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian
+ * @format: the format to check
+ *
+ * Returns 1 if the given PCM format is CPU-endian, 0 if
+ * opposite, or a negative error code if endian not specified.
+ */
+/* int snd_pcm_format_cpu_endian(snd_pcm_format_t format); */
+#ifdef SNDRV_LITTLE_ENDIAN
+#define snd_pcm_format_cpu_endian	snd_pcm_format_little_endian
+#else
+#define snd_pcm_format_cpu_endian	snd_pcm_format_big_endian
+#endif
 int snd_pcm_format_width(snd_pcm_format_t format);			/* in bits */
 int snd_pcm_format_physical_width(snd_pcm_format_t format);		/* in bits */
+ssize_t snd_pcm_format_size(snd_pcm_format_t format, size_t samples);
 const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format);
 int snd_pcm_format_set_silence(snd_pcm_format_t format, void *buf, unsigned int frames);
 snd_pcm_format_t snd_pcm_build_linear_format(int width, int unsignd, int big_endian);
diff --git a/include/sound/seq_midi_event.h b/include/sound/seq_midi_event.h
index 4357cac..8857e2b 100644
--- a/include/sound/seq_midi_event.h
+++ b/include/sound/seq_midi_event.h
@@ -41,9 +41,7 @@
 };
 
 int snd_midi_event_new(int bufsize, snd_midi_event_t **rdev);
-int snd_midi_event_resize_buffer(snd_midi_event_t *dev, int bufsize);
 void snd_midi_event_free(snd_midi_event_t *dev);
-void snd_midi_event_init(snd_midi_event_t *dev);
 void snd_midi_event_reset_encode(snd_midi_event_t *dev);
 void snd_midi_event_reset_decode(snd_midi_event_t *dev);
 void snd_midi_event_no_status(snd_midi_event_t *dev, int on);
diff --git a/include/sound/seq_virmidi.h b/include/sound/seq_virmidi.h
index cf4e238..1ad27e8 100644
--- a/include/sound/seq_virmidi.h
+++ b/include/sound/seq_virmidi.h
@@ -79,6 +79,5 @@
 #define SNDRV_VIRMIDI_SEQ_DISPATCH	2
 
 int snd_virmidi_new(snd_card_t *card, int device, snd_rawmidi_t **rrmidi);
-int snd_virmidi_receive(snd_rawmidi_t *rmidi, snd_seq_event_t *ev);
 
 #endif /* __SOUND_SEQ_VIRMIDI */
diff --git a/include/sound/timer.h b/include/sound/timer.h
index 57fde99..1898511 100644
--- a/include/sound/timer.h
+++ b/include/sound/timer.h
@@ -152,6 +152,4 @@
 
 extern void snd_timer_interrupt(snd_timer_t * timer, unsigned long ticks_left);
 
-extern unsigned int snd_timer_system_resolution(void);
-
 #endif /* __SOUND_TIMER_H */
diff --git a/include/sound/version.h b/include/sound/version.h
index 98b4230..46acfa8 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.9rc2"
-#define CONFIG_SND_DATE "  (Thu Mar 24 10:33:39 2005 UTC)"
+#define CONFIG_SND_VERSION "1.0.9"
+#define CONFIG_SND_DATE " (Sun May 29 07:31:02 2005 UTC)"
diff --git a/init/Kconfig b/init/Kconfig
index a7660cc..b1091d7 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -164,6 +164,7 @@
 
 config AUDIT
 	bool "Auditing support"
+	depends on NET
 	default y if SECURITY_SELINUX
 	help
 	  Enable auditing infrastructure that can be used with another
@@ -173,7 +174,7 @@
 
 config AUDITSYSCALL
 	bool "Enable system-call auditing support"
-	depends on AUDIT && (X86 || PPC64 || ARCH_S390 || IA64 || UML)
+	depends on AUDIT && (X86 || PPC || PPC64 || ARCH_S390 || IA64 || UML)
 	default y if SECURITY_SELINUX
 	help
 	  Enable low-overhead system-call auditing infrastructure that
diff --git a/init/calibrate.c b/init/calibrate.c
index c698e04..d206c75 100644
--- a/init/calibrate.c
+++ b/init/calibrate.c
@@ -8,6 +8,8 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 
+#include <asm/timex.h>
+
 static unsigned long preset_lpj;
 static int __init lpj_setup(char *str)
 {
@@ -17,6 +19,92 @@
 
 __setup("lpj=", lpj_setup);
 
+#ifdef ARCH_HAS_READ_CURRENT_TIMER
+
+/* This routine uses the read_current_timer() routine and gets the
+ * loops per jiffy directly, instead of guessing it using delay().
+ * Also, this code tries to handle non-maskable asynchronous events
+ * (like SMIs)
+ */
+#define DELAY_CALIBRATION_TICKS			((HZ < 100) ? 1 : (HZ/100))
+#define MAX_DIRECT_CALIBRATION_RETRIES		5
+
+static unsigned long __devinit calibrate_delay_direct(void)
+{
+	unsigned long pre_start, start, post_start;
+	unsigned long pre_end, end, post_end;
+	unsigned long start_jiffies;
+	unsigned long tsc_rate_min, tsc_rate_max;
+	unsigned long good_tsc_sum = 0;
+	unsigned long good_tsc_count = 0;
+	int i;
+
+	if (read_current_timer(&pre_start) < 0 )
+		return 0;
+
+	/*
+	 * A simple loop like
+	 *	while ( jiffies < start_jiffies+1)
+	 *		start = read_current_timer();
+	 * will not do. As we don't really know whether jiffy switch
+	 * happened first or timer_value was read first. And some asynchronous
+	 * event can happen between these two events introducing errors in lpj.
+	 *
+	 * So, we do
+	 * 1. pre_start <- When we are sure that jiffy switch hasn't happened
+	 * 2. check jiffy switch
+	 * 3. start <- timer value before or after jiffy switch
+	 * 4. post_start <- When we are sure that jiffy switch has happened
+	 *
+	 * Note, we don't know anything about order of 2 and 3.
+	 * Now, by looking at post_start and pre_start difference, we can
+	 * check whether any asynchronous event happened or not
+	 */
+
+	for (i = 0; i < MAX_DIRECT_CALIBRATION_RETRIES; i++) {
+		pre_start = 0;
+		read_current_timer(&start);
+		start_jiffies = jiffies;
+		while (jiffies <= (start_jiffies + 1)) {
+			pre_start = start;
+			read_current_timer(&start);
+		}
+		read_current_timer(&post_start);
+
+		pre_end = 0;
+		end = post_start;
+		while (jiffies <=
+		       (start_jiffies + 1 + DELAY_CALIBRATION_TICKS)) {
+			pre_end = end;
+			read_current_timer(&end);
+		}
+		read_current_timer(&post_end);
+
+		tsc_rate_max = (post_end - pre_start) / DELAY_CALIBRATION_TICKS;
+		tsc_rate_min = (pre_end - post_start) / DELAY_CALIBRATION_TICKS;
+
+		/*
+	 	 * If the upper limit and lower limit of the tsc_rate is
+		 * >= 12.5% apart, redo calibration.
+		 */
+		if (pre_start != 0 && pre_end != 0 &&
+		    (tsc_rate_max - tsc_rate_min) < (tsc_rate_max >> 3)) {
+			good_tsc_count++;
+			good_tsc_sum += tsc_rate_max;
+		}
+	}
+
+	if (good_tsc_count)
+		return (good_tsc_sum/good_tsc_count);
+
+	printk(KERN_WARNING "calibrate_delay_direct() failed to get a good "
+	       "estimate for loops_per_jiffy.\nProbably due to long platform interrupts. Consider using \"lpj=\" boot option.\n");
+	return 0;
+}
+#else
+static unsigned long __devinit calibrate_delay_direct(void) {return 0;}
+#endif
+
 /*
  * This is the number of bits of precision for the loops_per_jiffy.  Each
  * bit takes on average 1.5/HZ seconds.  This (like the original) is a little
@@ -35,6 +123,12 @@
 			"%lu.%02lu BogoMIPS preset\n",
 			loops_per_jiffy/(500000/HZ),
 			(loops_per_jiffy/(5000/HZ)) % 100);
+	} else if ((loops_per_jiffy = calibrate_delay_direct()) != 0) {
+		printk("Calibrating delay using timer specific routine.. ");
+		printk("%lu.%02lu BogoMIPS (lpj=%lu)\n",
+			loops_per_jiffy/(500000/HZ),
+			(loops_per_jiffy/(5000/HZ)) % 100,
+			loops_per_jiffy);
 	} else {
 		loops_per_jiffy = (1<<12);
 
diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c
index 07e7d31..4def882 100644
--- a/init/do_mounts_initrd.c
+++ b/init/do_mounts_initrd.c
@@ -41,7 +41,7 @@
 static void __init handle_initrd(void)
 {
 	int error;
-	int i, pid;
+	int pid;
 
 	real_root_dev = new_encode_dev(ROOT_DEV);
 	create_dev("/dev/root.old", Root_RAM0, NULL);
@@ -58,7 +58,7 @@
 
 	pid = kernel_thread(do_linuxrc, "/linuxrc", SIGCHLD);
 	if (pid > 0) {
-		while (pid != sys_wait4(-1, &i, 0, NULL))
+		while (pid != sys_wait4(-1, NULL, 0, NULL))
 			yield();
 	}
 
diff --git a/init/main.c b/init/main.c
index 40bf367..d324801 100644
--- a/init/main.c
+++ b/init/main.c
@@ -490,6 +490,7 @@
 	vfs_caches_init_early();
 	mem_init();
 	kmem_cache_init();
+	setup_per_cpu_pageset();
 	numa_policy_init();
 	if (late_time_init)
 		late_time_init();
diff --git a/ipc/sem.c b/ipc/sem.c
index 5ad7ac0..7e8a25c 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -1054,7 +1054,7 @@
 	struct sembuf fast_sops[SEMOPM_FAST];
 	struct sembuf* sops = fast_sops, *sop;
 	struct sem_undo *un;
-	int undos = 0, decrease = 0, alter = 0, max;
+	int undos = 0, alter = 0, max;
 	struct sem_queue queue;
 	unsigned long jiffies_left = 0;
 
@@ -1089,13 +1089,10 @@
 		if (sop->sem_num >= max)
 			max = sop->sem_num;
 		if (sop->sem_flg & SEM_UNDO)
-			undos++;
-		if (sop->sem_op < 0)
-			decrease = 1;
-		if (sop->sem_op > 0)
+			undos = 1;
+		if (sop->sem_op != 0)
 			alter = 1;
 	}
-	alter |= decrease;
 
 retry_undos:
 	if (undos) {
diff --git a/kernel/Kconfig.hz b/kernel/Kconfig.hz
new file mode 100644
index 0000000..248e1c3
--- /dev/null
+++ b/kernel/Kconfig.hz
@@ -0,0 +1,46 @@
+#
+# Timer Interrupt Frequency Configuration
+#
+
+choice
+	prompt "Timer frequency"
+	default HZ_250
+	help
+	 Allows the configuration of the timer frequency. It is customary
+	 to have the timer interrupt run at 1000 HZ but 100 HZ may be more
+	 beneficial for servers and NUMA systems that do not need to have
+	 a fast response for user interaction and that may experience bus
+	 contention and cacheline bounces as a result of timer interrupts.
+	 Note that the timer interrupt occurs on each processor in an SMP
+	 environment leading to NR_CPUS * HZ number of timer interrupts
+	 per second.
+
+
+	config HZ_100
+		bool "100 HZ"
+	help
+	  100 HZ is a typical choice for servers, SMP and NUMA systems
+	  with lots of processors that may show reduced performance if
+	  too many timer interrupts are occurring.
+
+	config HZ_250
+		bool "250 HZ"
+	help
+	 250 HZ is a good compromise choice allowing server performance
+	 while also showing good interactive responsiveness even
+	 on SMP and NUMA systems.
+
+	config HZ_1000
+		bool "1000 HZ"
+	help
+	 1000 HZ is the preferred choice for desktop systems and other
+	 systems requiring fast interactive responses to events.
+
+endchoice
+
+config HZ
+	int
+	default 100 if HZ_100
+	default 250 if HZ_250
+	default 1000 if HZ_1000
+
diff --git a/kernel/Kconfig.preempt b/kernel/Kconfig.preempt
new file mode 100644
index 0000000..0b46a5d
--- /dev/null
+++ b/kernel/Kconfig.preempt
@@ -0,0 +1,65 @@
+
+choice
+	prompt "Preemption Model"
+	default PREEMPT_NONE
+
+config PREEMPT_NONE
+	bool "No Forced Preemption (Server)"
+	help
+	  This is the traditional Linux preemption model, geared towards
+	  throughput. It will still provide good latencies most of the
+	  time, but there are no guarantees and occasional longer delays
+	  are possible.
+
+	  Select this option if you are building a kernel for a server or
+	  scientific/computation system, or if you want to maximize the
+	  raw processing power of the kernel, irrespective of scheduling
+	  latencies.
+
+config PREEMPT_VOLUNTARY
+	bool "Voluntary Kernel Preemption (Desktop)"
+	help
+	  This option reduces the latency of the kernel by adding more
+	  "explicit preemption points" to the kernel code. These new
+	  preemption points have been selected to reduce the maximum
+	  latency of rescheduling, providing faster application reactions,
+	  at the cost of slighly lower throughput.
+
+	  This allows reaction to interactive events by allowing a
+	  low priority process to voluntarily preempt itself even if it
+	  is in kernel mode executing a system call. This allows
+	  applications to run more 'smoothly' even when the system is
+	  under load.
+
+	  Select this if you are building a kernel for a desktop system.
+
+config PREEMPT
+	bool "Preemptible Kernel (Low-Latency Desktop)"
+	help
+	  This option reduces the latency of the kernel by making
+	  all kernel code (that is not executing in a critical section)
+	  preemptible.  This allows reaction to interactive events by
+	  permitting a low priority process to be preempted involuntarily
+	  even if it is in kernel mode executing a system call and would
+	  otherwise not be about to reach a natural preemption point.
+	  This allows applications to run more 'smoothly' even when the
+	  system is under load, at the cost of slighly lower throughput
+	  and a slight runtime overhead to kernel code.
+
+	  Select this if you are building a kernel for a desktop or
+	  embedded system with latency requirements in the milliseconds
+	  range.
+
+endchoice
+
+config PREEMPT_BKL
+	bool "Preempt The Big Kernel Lock"
+	depends on SMP || PREEMPT
+	default y
+	help
+	  This option reduces the latency of the kernel by making the
+	  big kernel lock preemptible.
+
+	  Say Y here if you are building a kernel for a desktop system.
+	  Say N if you are unsure.
+
diff --git a/kernel/Makefile b/kernel/Makefile
index b01d26f..cb05cd0 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -17,6 +17,7 @@
 obj-$(CONFIG_KALLSYMS) += kallsyms.o
 obj-$(CONFIG_PM) += power/
 obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
+obj-$(CONFIG_KEXEC) += kexec.o
 obj-$(CONFIG_COMPAT) += compat.o
 obj-$(CONFIG_CPUSETS) += cpuset.o
 obj-$(CONFIG_IKCONFIG) += configs.o
@@ -27,6 +28,7 @@
 obj-$(CONFIG_KPROBES) += kprobes.o
 obj-$(CONFIG_SYSFS) += ksysfs.o
 obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
+obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
 obj-$(CONFIG_SECCOMP) += seccomp.o
 
 ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y)
diff --git a/kernel/audit.c b/kernel/audit.c
index 9c4f1af..ef35166 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -46,6 +46,8 @@
 #include <asm/types.h>
 #include <linux/mm.h>
 #include <linux/module.h>
+#include <linux/err.h>
+#include <linux/kthread.h>
 
 #include <linux/audit.h>
 
@@ -68,7 +70,7 @@
 
 /* If audit records are to be written to the netlink socket, audit_pid
  * contains the (non-zero) pid. */
-static int	audit_pid;
+int		audit_pid;
 
 /* If audit_limit is non-zero, limit the rate of sending audit records
  * to that number per second.  This prevents DoS attacks, but results in
@@ -77,7 +79,10 @@
 
 /* Number of outstanding audit_buffers allowed. */
 static int	audit_backlog_limit = 64;
-static atomic_t	audit_backlog	    = ATOMIC_INIT(0);
+
+/* The identity of the user shutting down the audit system. */
+uid_t		audit_sig_uid = -1;
+pid_t		audit_sig_pid = -1;
 
 /* Records can be lost in several ways:
    0) [suppressed in audit_alloc]
@@ -91,19 +96,17 @@
 /* The netlink socket. */
 static struct sock *audit_sock;
 
-/* There are two lists of audit buffers.  The txlist contains audit
- * buffers that cannot be sent immediately to the netlink device because
- * we are in an irq context (these are sent later in a tasklet).
- *
- * The second list is a list of pre-allocated audit buffers (if more
+/* 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). */
-static DEFINE_SPINLOCK(audit_txlist_lock);
 static DEFINE_SPINLOCK(audit_freelist_lock);
 static int	   audit_freelist_count = 0;
-static LIST_HEAD(audit_txlist);
 static LIST_HEAD(audit_freelist);
 
+static struct sk_buff_head audit_skb_queue;
+static struct task_struct *kauditd_task;
+static DECLARE_WAIT_QUEUE_HEAD(kauditd_wait);
+
 /* 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. */
@@ -112,7 +115,7 @@
 static LIST_HEAD(audit_extlist);
 
 /* The netlink socket is only to be read by 1 CPU, which lets us assume
- * that list additions and deletions never happen simultaneiously in
+ * that list additions and deletions never happen simultaneously in
  * auditsc.c */
 static DECLARE_MUTEX(audit_netlink_sem);
 
@@ -132,21 +135,14 @@
  * use simultaneously. */
 struct audit_buffer {
 	struct list_head     list;
-	struct sk_buff_head  sklist;	/* formatted skbs ready to send */
+	struct sk_buff       *skb;	/* formatted skb ready to send */
 	struct audit_context *ctx;	/* NULL or associated context */
-	int		     len;	/* used area of tmp */
-	char		     tmp[AUDIT_BUFSIZ];
-
-				/* Pointer to header and contents */
-	struct nlmsghdr      *nlh;
-	int		     total;
-	int		     type;
-	int		     pid;
 };
 
-void audit_set_type(struct audit_buffer *ab, int type)
+static void audit_set_pid(struct audit_buffer *ab, pid_t pid)
 {
-	ab->type = type;
+	struct nlmsghdr *nlh = (struct nlmsghdr *)ab->skb->data;
+	nlh->nlmsg_pid = pid;
 }
 
 struct audit_entry {
@@ -154,9 +150,6 @@
 	struct audit_rule rule;
 };
 
-static void audit_log_end_irq(struct audit_buffer *ab);
-static void audit_log_end_fast(struct audit_buffer *ab);
-
 static void audit_panic(const char *message)
 {
 	switch (audit_failure)
@@ -227,10 +220,8 @@
 
 	if (print) {
 		printk(KERN_WARNING
-		       "audit: audit_lost=%d audit_backlog=%d"
-		       " audit_rate_limit=%d audit_backlog_limit=%d\n",
+		       "audit: audit_lost=%d audit_rate_limit=%d audit_backlog_limit=%d\n",
 		       atomic_read(&audit_lost),
-		       atomic_read(&audit_backlog),
 		       audit_rate_limit,
 		       audit_backlog_limit);
 		audit_panic(message);
@@ -242,7 +233,8 @@
 {
 	int old		 = audit_rate_limit;
 	audit_rate_limit = limit;
-	audit_log(NULL, "audit_rate_limit=%d old=%d by auid %u",
+	audit_log(NULL, AUDIT_CONFIG_CHANGE, 
+			"audit_rate_limit=%d old=%d by auid=%u",
 			audit_rate_limit, old, loginuid);
 	return old;
 }
@@ -251,7 +243,8 @@
 {
 	int old		 = audit_backlog_limit;
 	audit_backlog_limit = limit;
-	audit_log(NULL, "audit_backlog_limit=%d old=%d by auid %u",
+	audit_log(NULL, AUDIT_CONFIG_CHANGE,
+			"audit_backlog_limit=%d old=%d by auid=%u",
 			audit_backlog_limit, old, loginuid);
 	return old;
 }
@@ -262,8 +255,9 @@
 	if (state != 0 && state != 1)
 		return -EINVAL;
 	audit_enabled = state;
-	audit_log(NULL, "audit_enabled=%d old=%d by auid %u",
-		  audit_enabled, old, loginuid);
+	audit_log(NULL, AUDIT_CONFIG_CHANGE,
+			"audit_enabled=%d old=%d by auid=%u",
+			audit_enabled, old, loginuid);
 	return old;
 }
 
@@ -275,12 +269,44 @@
 	    && state != AUDIT_FAIL_PANIC)
 		return -EINVAL;
 	audit_failure = state;
-	audit_log(NULL, "audit_failure=%d old=%d by auid %u",
-		  audit_failure, old, loginuid);
+	audit_log(NULL, AUDIT_CONFIG_CHANGE,
+			"audit_failure=%d old=%d by auid=%u",
+			audit_failure, old, loginuid);
 	return old;
 }
 
-#ifdef CONFIG_NET
+int kauditd_thread(void *dummy)
+{
+	struct sk_buff *skb;
+
+	while (1) {
+		skb = skb_dequeue(&audit_skb_queue);
+		if (skb) {
+			if (audit_pid) {
+				int err = netlink_unicast(audit_sock, skb, audit_pid, 0);
+				if (err < 0) {
+					BUG_ON(err != -ECONNREFUSED); /* Shoudn't happen */
+					printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid);
+					audit_pid = 0;
+				}
+			} else {
+				printk(KERN_ERR "%s\n", skb->data + NLMSG_SPACE(0));
+				kfree_skb(skb);
+			}
+		} else {
+			DECLARE_WAITQUEUE(wait, current);
+			set_current_state(TASK_INTERRUPTIBLE);
+			add_wait_queue(&kauditd_wait, &wait);
+
+			if (!skb_queue_len(&audit_skb_queue))
+				schedule();
+
+			__set_current_state(TASK_RUNNING);
+			remove_wait_queue(&kauditd_wait, &wait);
+		}
+	}
+}
+
 void audit_send_reply(int pid, int seq, int type, int done, int multi,
 		      void *payload, int size)
 {
@@ -293,13 +319,16 @@
 
 	skb = alloc_skb(len, GFP_KERNEL);
 	if (!skb)
-		goto nlmsg_failure;
+		return;
 
-	nlh		 = NLMSG_PUT(skb, pid, seq, t, len - sizeof(*nlh));
+	nlh		 = NLMSG_PUT(skb, pid, seq, t, size);
 	nlh->nlmsg_flags = flags;
 	data		 = NLMSG_DATA(nlh);
 	memcpy(data, payload, size);
-	netlink_unicast(audit_sock, skb, pid, MSG_DONTWAIT);
+
+	/* 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 */
@@ -321,10 +350,12 @@
 	case AUDIT_SET:
 	case AUDIT_ADD:
 	case AUDIT_DEL:
+	case AUDIT_SIGNAL_INFO:
 		if (!cap_raised(eff_cap, CAP_AUDIT_CONTROL))
 			err = -EPERM;
 		break;
 	case AUDIT_USER:
+	case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG:
 		if (!cap_raised(eff_cap, CAP_AUDIT_WRITE))
 			err = -EPERM;
 		break;
@@ -344,11 +375,21 @@
 	struct audit_buffer	*ab;
 	u16			msg_type = nlh->nlmsg_type;
 	uid_t			loginuid; /* loginuid of sender */
+	struct audit_sig_info   sig_data;
 
 	err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type);
 	if (err)
 		return err;
 
+	/* As soon as there's any sign of userspace auditd, start kauditd to talk to it */
+	if (!kauditd_task)
+		kauditd_task = kthread_run(kauditd_thread, NULL, "kauditd");
+	if (IS_ERR(kauditd_task)) {
+		err = PTR_ERR(kauditd_task);
+		kauditd_task = NULL;
+		return err;
+	}
+
 	pid  = NETLINK_CREDS(skb)->pid;
 	uid  = NETLINK_CREDS(skb)->uid;
 	loginuid = NETLINK_CB(skb).loginuid;
@@ -363,7 +404,7 @@
 		status_set.rate_limit	 = audit_rate_limit;
 		status_set.backlog_limit = audit_backlog_limit;
 		status_set.lost		 = atomic_read(&audit_lost);
-		status_set.backlog	 = atomic_read(&audit_backlog);
+		status_set.backlog	 = skb_queue_len(&audit_skb_queue);
 		audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_GET, 0, 0,
 				 &status_set, sizeof(status_set));
 		break;
@@ -382,7 +423,8 @@
 		if (status_get->mask & AUDIT_STATUS_PID) {
 			int old   = audit_pid;
 			audit_pid = status_get->pid;
-			audit_log(NULL, "audit_pid=%d old=%d by auid %u",
+			audit_log(NULL, AUDIT_CONFIG_CHANGE,
+				"audit_pid=%d old=%d by auid=%u",
 				  audit_pid, old, loginuid);
 		}
 		if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
@@ -392,18 +434,15 @@
 							loginuid);
 		break;
 	case AUDIT_USER:
-		ab = audit_log_start(NULL);
+	case AUDIT_FIRST_USER_MSG...AUDIT_LAST_USER_MSG:
+		ab = audit_log_start(NULL, msg_type);
 		if (!ab)
 			break;	/* audit_panic has been called */
 		audit_log_format(ab,
-				 "user pid=%d uid=%d length=%d loginuid=%u"
+				 "user pid=%d uid=%u auid=%u"
 				 " msg='%.1024s'",
-				 pid, uid,
-				 (int)(nlh->nlmsg_len
-				       - ((char *)data - (char *)nlh)),
-				 loginuid, (char *)data);
-		ab->type = AUDIT_USER;
-		ab->pid  = pid;
+				 pid, uid, loginuid, (char *)data);
+		audit_set_pid(ab, pid);
 		audit_log_end(ab);
 		break;
 	case AUDIT_ADD:
@@ -412,12 +451,14 @@
 			return -EINVAL;
 		/* fallthrough */
 	case AUDIT_LIST:
-#ifdef CONFIG_AUDITSYSCALL
 		err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
 					   uid, seq, data, loginuid);
-#else
-		err = -EOPNOTSUPP;
-#endif
+		break;
+	case AUDIT_SIGNAL_INFO:
+		sig_data.uid = audit_sig_uid;
+		sig_data.pid = audit_sig_pid;
+		audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_SIGNAL_INFO, 
+				0, 0, &sig_data, sizeof(sig_data));
 		break;
 	default:
 		err = -EINVAL;
@@ -467,87 +508,6 @@
 	up(&audit_netlink_sem);
 }
 
-/* Move data from tmp buffer into an skb.  This is an extra copy, and
- * that is unfortunate.  However, the copy will only occur when a record
- * is being written to user space, which is already a high-overhead
- * operation.  (Elimination of the copy is possible, for example, by
- * writing directly into a pre-allocated skb, at the cost of wasting
- * memory. */
-static void audit_log_move(struct audit_buffer *ab)
-{
-	struct sk_buff	*skb;
-	char		*start;
-	int		extra = ab->nlh ? 0 : NLMSG_SPACE(0);
-
-	/* possible resubmission */
-	if (ab->len == 0)
-		return;
-
-	skb = skb_peek_tail(&ab->sklist);
-	if (!skb || skb_tailroom(skb) <= ab->len + extra) {
-		skb = alloc_skb(2 * ab->len + extra, GFP_ATOMIC);
-		if (!skb) {
-			ab->len = 0; /* Lose information in ab->tmp */
-			audit_log_lost("out of memory in audit_log_move");
-			return;
-		}
-		__skb_queue_tail(&ab->sklist, skb);
-		if (!ab->nlh)
-			ab->nlh = (struct nlmsghdr *)skb_put(skb,
-							     NLMSG_SPACE(0));
-	}
-	start = skb_put(skb, ab->len);
-	memcpy(start, ab->tmp, ab->len);
-	ab->len = 0;
-}
-
-/* Iterate over the skbuff in the audit_buffer, sending their contents
- * to user space. */
-static inline int audit_log_drain(struct audit_buffer *ab)
-{
-	struct sk_buff *skb;
-
-	while ((skb = skb_dequeue(&ab->sklist))) {
-		int retval = 0;
-
-		if (audit_pid) {
-			if (ab->nlh) {
-				ab->nlh->nlmsg_len   = ab->total;
-				ab->nlh->nlmsg_type  = ab->type;
-				ab->nlh->nlmsg_flags = 0;
-				ab->nlh->nlmsg_seq   = 0;
-				ab->nlh->nlmsg_pid   = ab->pid;
-			}
-			skb_get(skb); /* because netlink_* frees */
-			retval = netlink_unicast(audit_sock, skb, audit_pid,
-						 MSG_DONTWAIT);
-		}
-		if (retval == -EAGAIN &&
-		    (atomic_read(&audit_backlog)) < audit_backlog_limit) {
-			skb_queue_head(&ab->sklist, skb);
-			audit_log_end_irq(ab);
-			return 1;
-		}
-		if (retval < 0) {
-			if (retval == -ECONNREFUSED) {
-				printk(KERN_ERR
-				       "audit: *NO* daemon at audit_pid=%d\n",
-				       audit_pid);
-				audit_pid = 0;
-			} else
-				audit_log_lost("netlink socket too busy");
-		}
-		if (!audit_pid) { /* No daemon */
-			int offset = ab->nlh ? NLMSG_SPACE(0) : 0;
-			int len    = skb->len - offset;
-			skb->data[offset + len] = '\0';
-			printk(KERN_ERR "%s\n", skb->data + offset);
-		}
-		kfree_skb(skb);
-		ab->nlh = NULL;
-	}
-	return 0;
-}
 
 /* Initialize audit support at boot time. */
 static int __init audit_init(void)
@@ -558,40 +518,13 @@
 	if (!audit_sock)
 		audit_panic("cannot initialize netlink socket");
 
+	audit_sock->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
+	skb_queue_head_init(&audit_skb_queue);
 	audit_initialized = 1;
 	audit_enabled = audit_default;
-	audit_log(NULL, "initialized");
+	audit_log(NULL, AUDIT_KERNEL, "initialized");
 	return 0;
 }
-
-#else
-/* Without CONFIG_NET, we have no skbuffs.  For now, print what we have
- * in the buffer. */
-static void audit_log_move(struct audit_buffer *ab)
-{
-	printk(KERN_ERR "%*.*s\n", ab->len, ab->len, ab->tmp);
-	ab->len = 0;
-}
-
-static inline int audit_log_drain(struct audit_buffer *ab)
-{
-	return 0;
-}
-
-/* Initialize audit support at boot time. */
-int __init audit_init(void)
-{
-	printk(KERN_INFO "audit: initializing WITHOUT netlink support\n");
-	audit_sock = NULL;
-	audit_pid  = 0;
-
-	audit_initialized = 1;
-	audit_enabled = audit_default;
-	audit_log(NULL, "initialized");
-	return 0;
-}
-#endif
-
 __initcall(audit_init);
 
 /* Process kernel command-line parameter at boot time.  audit=0 or audit=1. */
@@ -608,34 +541,30 @@
 
 __setup("audit=", audit_enable);
 
-
-/* Obtain an audit buffer.  This routine does locking to obtain the
- * audit buffer, but then no locking is required for calls to
- * audit_log_*format.  If the tsk is a task that is currently in a
- * syscall, then the syscall is marked as auditable and an audit record
- * will be written at syscall exit.  If there is no associated task, tsk
- * should be NULL. */
-struct audit_buffer *audit_log_start(struct audit_context *ctx)
+static void audit_buffer_free(struct audit_buffer *ab)
 {
-	struct audit_buffer	*ab	= NULL;
-	unsigned long		flags;
-	struct timespec		t;
-	unsigned int		serial;
+	unsigned long flags;
 
-	if (!audit_initialized)
-		return NULL;
+	if (!ab)
+		return;
 
-	if (audit_backlog_limit
-	    && atomic_read(&audit_backlog) > audit_backlog_limit) {
-		if (audit_rate_check())
-			printk(KERN_WARNING
-			       "audit: audit_backlog=%d > "
-			       "audit_backlog_limit=%d\n",
-			       atomic_read(&audit_backlog),
-			       audit_backlog_limit);
-		audit_log_lost("backlog limit exceeded");
-		return NULL;
-	}
+	if (ab->skb)
+		kfree_skb(ab->skb);
+
+	spin_lock_irqsave(&audit_freelist_lock, flags);
+	if (++audit_freelist_count > AUDIT_MAXFREE)
+		kfree(ab);
+	else
+		list_add(&ab->list, &audit_freelist);
+	spin_unlock_irqrestore(&audit_freelist_lock, flags);
+}
+
+static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx,
+						int gfp_mask, int type)
+{
+	unsigned long flags;
+	struct audit_buffer *ab = NULL;
+	struct nlmsghdr *nlh;
 
 	spin_lock_irqsave(&audit_freelist_lock, flags);
 	if (!list_empty(&audit_freelist)) {
@@ -646,37 +575,127 @@
 	}
 	spin_unlock_irqrestore(&audit_freelist_lock, flags);
 
-	if (!ab)
-		ab = kmalloc(sizeof(*ab), GFP_ATOMIC);
+	if (!ab) {
+		ab = kmalloc(sizeof(*ab), gfp_mask);
+		if (!ab)
+			goto err;
+	}
+
+	ab->skb = alloc_skb(AUDIT_BUFSIZ, gfp_mask);
+	if (!ab->skb)
+		goto err;
+
+	ab->ctx = ctx;
+	nlh = (struct nlmsghdr *)skb_put(ab->skb, NLMSG_SPACE(0));
+	nlh->nlmsg_type = type;
+	nlh->nlmsg_flags = 0;
+	nlh->nlmsg_pid = 0;
+	nlh->nlmsg_seq = 0;
+	return ab;
+err:
+	audit_buffer_free(ab);
+	return NULL;
+}
+
+/* Compute a serial number for the audit record.  Audit records are
+ * written to user-space as soon as they are generated, so a complete
+ * audit record may be written in several pieces.  The timestamp of the
+ * record and this serial number are used by the user-space tools to
+ * determine which pieces belong to the same audit record.  The
+ * (timestamp,serial) tuple is unique for each syscall and is live from
+ * syscall entry to syscall exit.
+ *
+ * Atomic values are only guaranteed to be 24-bit, so we count down.
+ *
+ * NOTE: Another possibility is to store the formatted records off the
+ * audit context (for those records that have a context), and emit them
+ * all at syscall exit.  However, this could delay the reporting of
+ * significant errors until syscall exit (or never, if the system
+ * halts). */
+unsigned int audit_serial(void)
+{
+	static atomic_t serial = ATOMIC_INIT(0xffffff);
+	unsigned int a, b;
+
+	do {
+		a = atomic_read(&serial);
+		if (atomic_dec_and_test(&serial))
+			atomic_set(&serial, 0xffffff);
+		b = atomic_read(&serial);
+	} while (b != a - 1);
+
+	return 0xffffff - b;
+}
+
+static inline void audit_get_stamp(struct audit_context *ctx, 
+				   struct timespec *t, unsigned int *serial)
+{
+	if (ctx)
+		auditsc_get_stamp(ctx, t, serial);
+	else {
+		*t = CURRENT_TIME;
+		*serial = audit_serial();
+	}
+}
+
+/* Obtain an audit buffer.  This routine does locking to obtain the
+ * audit buffer, but then no locking is required for calls to
+ * audit_log_*format.  If the tsk is a task that is currently in a
+ * syscall, then the syscall is marked as auditable and an audit record
+ * will be written at syscall exit.  If there is no associated task, tsk
+ * should be NULL. */
+struct audit_buffer *audit_log_start(struct audit_context *ctx, int type)
+{
+	struct audit_buffer	*ab	= NULL;
+	struct timespec		t;
+	unsigned int		serial;
+
+	if (!audit_initialized)
+		return NULL;
+
+	if (audit_backlog_limit
+	    && skb_queue_len(&audit_skb_queue) > audit_backlog_limit) {
+		if (audit_rate_check())
+			printk(KERN_WARNING
+			       "audit: audit_backlog=%d > "
+			       "audit_backlog_limit=%d\n",
+			       skb_queue_len(&audit_skb_queue),
+			       audit_backlog_limit);
+		audit_log_lost("backlog limit exceeded");
+		return NULL;
+	}
+
+	ab = audit_buffer_alloc(ctx, GFP_ATOMIC, type);
 	if (!ab) {
 		audit_log_lost("out of memory in audit_log_start");
 		return NULL;
 	}
 
-	atomic_inc(&audit_backlog);
-	skb_queue_head_init(&ab->sklist);
+	audit_get_stamp(ab->ctx, &t, &serial);
 
-	ab->ctx   = ctx;
-	ab->len   = 0;
-	ab->nlh   = NULL;
-	ab->total = 0;
-	ab->type  = AUDIT_KERNEL;
-	ab->pid   = 0;
-
-#ifdef CONFIG_AUDITSYSCALL
-	if (ab->ctx)
-		audit_get_stamp(ab->ctx, &t, &serial);
-	else
-#endif
-	{
-		t = CURRENT_TIME;
-		serial = 0;
-	}
 	audit_log_format(ab, "audit(%lu.%03lu:%u): ",
 			 t.tv_sec, t.tv_nsec/1000000, serial);
 	return ab;
 }
 
+/**
+ * audit_expand - expand skb in the audit buffer
+ * @ab: audit_buffer
+ *
+ * Returns 0 (no space) on failed expansion, or available space if
+ * successful.
+ */
+static inline int audit_expand(struct audit_buffer *ab, int extra)
+{
+	struct sk_buff *skb = ab->skb;
+	int ret = pskb_expand_head(skb, skb_headroom(skb), extra,
+				   GFP_ATOMIC);
+	if (ret < 0) {
+		audit_log_lost("out of memory in audit_expand");
+		return 0;
+	}
+	return skb_tailroom(skb);
+}
 
 /* Format an audit message into the audit buffer.  If there isn't enough
  * room in the audit buffer, more room will be allocated and vsnprint
@@ -686,26 +705,35 @@
 			      va_list args)
 {
 	int len, avail;
+	struct sk_buff *skb;
+	va_list args2;
 
 	if (!ab)
 		return;
 
-	avail = sizeof(ab->tmp) - ab->len;
-	if (avail <= 0) {
-		audit_log_move(ab);
-		avail = sizeof(ab->tmp) - ab->len;
+	BUG_ON(!ab->skb);
+	skb = ab->skb;
+	avail = skb_tailroom(skb);
+	if (avail == 0) {
+		avail = audit_expand(ab, AUDIT_BUFSIZ);
+		if (!avail)
+			goto out;
 	}
-	len   = vsnprintf(ab->tmp + ab->len, avail, fmt, args);
+	va_copy(args2, args);
+	len = vsnprintf(skb->tail, avail, fmt, args);
 	if (len >= avail) {
 		/* The printk buffer is 1024 bytes long, so if we get
 		 * here and AUDIT_BUFSIZ is at least 1024, then we can
 		 * log everything that printk could have logged. */
-		audit_log_move(ab);
-		avail = sizeof(ab->tmp) - ab->len;
-		len   = vsnprintf(ab->tmp + ab->len, avail, fmt, args);
+		avail = audit_expand(ab, max_t(unsigned, AUDIT_BUFSIZ, 1+len-avail));
+		if (!avail)
+			goto out;
+		len = vsnprintf(skb->tail, avail, fmt, args2);
 	}
-	ab->len   += (len < avail) ? len : avail;
-	ab->total += (len < avail) ? len : avail;
+	if (len > 0)
+		skb_put(skb, len);
+out:
+	return;
 }
 
 /* Format a message into the audit buffer.  All the work is done in
@@ -721,20 +749,47 @@
 	va_end(args);
 }
 
-void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf, size_t len)
+/* This function will take the passed buf and convert it into a string of
+ * ascii hex digits. The new string is placed onto the skb. */
+void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf, 
+		size_t len)
 {
-	int i;
+	int i, avail, new_len;
+	unsigned char *ptr;
+	struct sk_buff *skb;
+	static const unsigned char *hex = "0123456789ABCDEF";
 
-	for (i=0; i<len; i++)
-		audit_log_format(ab, "%02x", buf[i]);
+	BUG_ON(!ab->skb);
+	skb = ab->skb;
+	avail = skb_tailroom(skb);
+	new_len = len<<1;
+	if (new_len >= avail) {
+		/* Round the buffer request up to the next multiple */
+		new_len = AUDIT_BUFSIZ*(((new_len-avail)/AUDIT_BUFSIZ) + 1);
+		avail = audit_expand(ab, new_len);
+		if (!avail)
+			return;
+	}
+
+	ptr = skb->tail;
+	for (i=0; i<len; i++) {
+		*ptr++ = hex[(buf[i] & 0xF0)>>4]; /* Upper nibble */
+		*ptr++ = hex[buf[i] & 0x0F];	  /* Lower nibble */
+	}
+	*ptr = 0;
+	skb_put(skb, len << 1); /* new string is twice the old string */
 }
 
+/* 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). */
 void audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
 {
 	const unsigned char *p = string;
 
 	while (*p) {
-		if (*p == '"' || *p == ' ' || *p < 0x20 || *p > 0x7f) {
+		if (*p == '"' || *p < 0x21 || *p > 0x7f) {
 			audit_log_hex(ab, string, strlen(string));
 			return;
 		}
@@ -743,117 +798,63 @@
 	audit_log_format(ab, "\"%s\"", string);
 }
 
-
-/* This is a helper-function to print the d_path without using a static
- * buffer or allocating another buffer in addition to the one in
- * audit_buffer. */
+/* This is a helper-function to print the escaped d_path */
 void audit_log_d_path(struct audit_buffer *ab, const char *prefix,
 		      struct dentry *dentry, struct vfsmount *vfsmnt)
 {
-	char *p;
-	int  len, avail;
+	char *p, *path;
 
-	if (prefix) audit_log_format(ab, " %s", prefix);
+	if (prefix)
+		audit_log_format(ab, " %s", prefix);
 
-	if (ab->len > 128)
-		audit_log_move(ab);
-	avail = sizeof(ab->tmp) - ab->len;
-	p = d_path(dentry, vfsmnt, ab->tmp + ab->len, avail);
-	if (IS_ERR(p)) {
+	/* We will allow 11 spaces for ' (deleted)' to be appended */
+	path = kmalloc(PATH_MAX+11, GFP_KERNEL);
+	if (!path) {
+		audit_log_format(ab, "<no memory>");
+		return;
+	}
+	p = d_path(dentry, vfsmnt, path, PATH_MAX+11);
+	if (IS_ERR(p)) { /* Should never happen since we send PATH_MAX */
 		/* FIXME: can we save some information here? */
-		audit_log_format(ab, "<toolong>");
-	} else {
-				/* path isn't at start of buffer */
-		len	   = (ab->tmp + sizeof(ab->tmp) - 1) - p;
-		memmove(ab->tmp + ab->len, p, len);
-		ab->len   += len;
-		ab->total += len;
-	}
+		audit_log_format(ab, "<too long>");
+	} else 
+		audit_log_untrustedstring(ab, p);
+	kfree(path);
 }
 
-/* Remove queued messages from the audit_txlist and send them to userspace. */
-static void audit_tasklet_handler(unsigned long arg)
-{
-	LIST_HEAD(list);
-	struct audit_buffer *ab;
-	unsigned long	    flags;
-
-	spin_lock_irqsave(&audit_txlist_lock, flags);
-	list_splice_init(&audit_txlist, &list);
-	spin_unlock_irqrestore(&audit_txlist_lock, flags);
-
-	while (!list_empty(&list)) {
-		ab = list_entry(list.next, struct audit_buffer, list);
-		list_del(&ab->list);
-		audit_log_end_fast(ab);
-	}
-}
-
-static DECLARE_TASKLET(audit_tasklet, audit_tasklet_handler, 0);
-
 /* The netlink_* functions cannot be called inside an irq context, so
  * the audit buffer is places on a queue and a tasklet is scheduled to
  * remove them from the queue outside the irq context.  May be called in
  * any context. */
-static void audit_log_end_irq(struct audit_buffer *ab)
+void audit_log_end(struct audit_buffer *ab)
 {
-	unsigned long flags;
-
-	if (!ab)
-		return;
-	spin_lock_irqsave(&audit_txlist_lock, flags);
-	list_add_tail(&ab->list, &audit_txlist);
-	spin_unlock_irqrestore(&audit_txlist_lock, flags);
-
-	tasklet_schedule(&audit_tasklet);
-}
-
-/* Send the message in the audit buffer directly to user space.  May not
- * be called in an irq context. */
-static void audit_log_end_fast(struct audit_buffer *ab)
-{
-	unsigned long flags;
-
-	BUG_ON(in_irq());
 	if (!ab)
 		return;
 	if (!audit_rate_check()) {
 		audit_log_lost("rate limit exceeded");
 	} else {
-		audit_log_move(ab);
-		if (audit_log_drain(ab))
-			return;
+		if (audit_pid) {
+			struct nlmsghdr *nlh = (struct nlmsghdr *)ab->skb->data;
+			nlh->nlmsg_len = ab->skb->len - NLMSG_SPACE(0);
+			skb_queue_tail(&audit_skb_queue, ab->skb);
+			ab->skb = NULL;
+			wake_up_interruptible(&kauditd_wait);
+		} else {
+			printk("%s\n", ab->skb->data + NLMSG_SPACE(0));
+		}
 	}
-
-	atomic_dec(&audit_backlog);
-	spin_lock_irqsave(&audit_freelist_lock, flags);
-	if (++audit_freelist_count > AUDIT_MAXFREE)
-		kfree(ab);
-	else
-		list_add(&ab->list, &audit_freelist);
-	spin_unlock_irqrestore(&audit_freelist_lock, flags);
-}
-
-/* Send or queue the message in the audit buffer, depending on the
- * current context.  (A convenience function that may be called in any
- * context.) */
-void audit_log_end(struct audit_buffer *ab)
-{
-	if (in_irq())
-		audit_log_end_irq(ab);
-	else
-		audit_log_end_fast(ab);
+	audit_buffer_free(ab);
 }
 
 /* Log an audit record.  This is a convenience function that calls
  * audit_log_start, audit_log_vformat, and audit_log_end.  It may be
  * called in any context. */
-void audit_log(struct audit_context *ctx, const char *fmt, ...)
+void audit_log(struct audit_context *ctx, int type, const char *fmt, ...)
 {
 	struct audit_buffer *ab;
 	va_list args;
 
-	ab = audit_log_start(ctx);
+	ab = audit_log_start(ctx, type);
 	if (ab) {
 		va_start(args, fmt);
 		audit_log_vformat(ab, fmt, args);
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 37b3ac9..e75f84e 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -34,7 +34,8 @@
 #include <asm/types.h>
 #include <linux/mm.h>
 #include <linux/module.h>
-
+#include <linux/mount.h>
+#include <linux/socket.h>
 #include <linux/audit.h>
 #include <linux/personality.h>
 #include <linux/time.h>
@@ -112,6 +113,23 @@
 	mode_t			mode;
 };
 
+struct audit_aux_data_socketcall {
+	struct audit_aux_data	d;
+	int			nargs;
+	unsigned long		args[0];
+};
+
+struct audit_aux_data_sockaddr {
+	struct audit_aux_data	d;
+	int			len;
+	char			a[0];
+};
+
+struct audit_aux_data_path {
+	struct audit_aux_data	d;
+	struct dentry		*dentry;
+	struct vfsmount		*mnt;
+};
 
 /* The per-task audit context. */
 struct audit_context {
@@ -127,6 +145,8 @@
 	int		    auditable;  /* 1 if record should be written */
 	int		    name_count;
 	struct audit_names  names[AUDIT_NAMES];
+	struct dentry *	    pwd;
+	struct vfsmount *   pwdmnt;
 	struct audit_context *previous; /* For nested syscalls */
 	struct audit_aux_data *aux;
 
@@ -157,6 +177,8 @@
 	struct audit_rule rule;
 };
 
+extern int audit_pid;
+
 /* Check to see if two rules are identical.  It is called from
  * audit_del_rule during AUDIT_DEL. */
 static int audit_compare_rule(struct audit_rule *a, struct audit_rule *b)
@@ -226,7 +248,6 @@
 	return -EFAULT;		/* No matching rule */
 }
 
-#ifdef CONFIG_NET
 /* Copy rule from user-space to kernel-space.  Called during
  * AUDIT_ADD. */
 static int audit_copy_rule(struct audit_rule *d, struct audit_rule *s)
@@ -287,7 +308,8 @@
 			err = audit_add_rule(entry, &audit_entlist);
 		if (!err && (flags & AUDIT_AT_EXIT))
 			err = audit_add_rule(entry, &audit_extlist);
-		audit_log(NULL, "auid %u added an audit rule\n", loginuid);
+		audit_log(NULL, AUDIT_CONFIG_CHANGE, 
+				"auid=%u added an audit rule\n", loginuid);
 		break;
 	case AUDIT_DEL:
 		flags =((struct audit_rule *)data)->flags;
@@ -297,7 +319,8 @@
 			err = audit_del_rule(data, &audit_entlist);
 		if (!err && (flags & AUDIT_AT_EXIT))
 			err = audit_del_rule(data, &audit_extlist);
-		audit_log(NULL, "auid %u removed an audit rule\n", loginuid);
+		audit_log(NULL, AUDIT_CONFIG_CHANGE,
+				"auid=%u removed an audit rule\n", loginuid);
 		break;
 	default:
 		return -EINVAL;
@@ -305,7 +328,6 @@
 
 	return err;
 }
-#endif
 
 /* Compare a task_struct with an audit_rule.  Return 1 on match, 0
  * otherwise. */
@@ -444,7 +466,7 @@
 
 /* At syscall entry and exit time, this filter is called if the
  * audit_state is not low enough that auditing cannot take place, but is
- * also not high enough that we already know we have to write and audit
+ * also not high enough that we already know we have to write an audit
  * record (i.e., the state is AUDIT_SETUP_CONTEXT or  AUDIT_BUILD_CONTEXT).
  */
 static enum audit_state audit_filter_syscall(struct task_struct *tsk,
@@ -532,6 +554,12 @@
 		if (context->names[i].name)
 			__putname(context->names[i].name);
 	context->name_count = 0;
+	if (context->pwd)
+		dput(context->pwd);
+	if (context->pwdmnt)
+		mntput(context->pwdmnt);
+	context->pwd = NULL;
+	context->pwdmnt = NULL;
 }
 
 static inline void audit_free_aux(struct audit_context *context)
@@ -539,6 +567,11 @@
 	struct audit_aux_data *aux;
 
 	while ((aux = context->aux)) {
+		if (aux->type == AUDIT_AVC_PATH) {
+			struct audit_aux_data_path *axi = (void *)aux;
+			dput(axi->dentry);
+			mntput(axi->mnt);
+		}
 		context->aux = aux->next;
 		kfree(aux);
 	}
@@ -625,7 +658,8 @@
 	struct vm_area_struct *vma;
 
 	get_task_comm(name, current);
-	audit_log_format(ab, " comm=%s", name);
+	audit_log_format(ab, " comm=");
+	audit_log_untrustedstring(ab, name);
 
 	if (!mm)
 		return;
@@ -649,23 +683,24 @@
 {
 	int i;
 	struct audit_buffer *ab;
+	struct audit_aux_data *aux;
 
-	ab = audit_log_start(context);
+	ab = audit_log_start(context, AUDIT_SYSCALL);
 	if (!ab)
 		return;		/* audit_panic has been called */
-	audit_log_format(ab, "syscall=%d", context->major);
+	audit_log_format(ab, "arch=%x syscall=%d",
+			 context->arch, context->major);
 	if (context->personality != PER_LINUX)
 		audit_log_format(ab, " per=%lx", context->personality);
-	audit_log_format(ab, " arch=%x", context->arch);
 	if (context->return_valid)
 		audit_log_format(ab, " success=%s exit=%ld", 
 				 (context->return_valid==AUDITSC_SUCCESS)?"yes":"no",
 				 context->return_code);
 	audit_log_format(ab,
 		  " a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
-		  " pid=%d loginuid=%d uid=%d gid=%d"
-		  " euid=%d suid=%d fsuid=%d"
-		  " egid=%d sgid=%d fsgid=%d",
+		  " pid=%d auid=%u uid=%u gid=%u"
+		  " euid=%u suid=%u fsuid=%u"
+		  " egid=%u sgid=%u fsgid=%u",
 		  context->argv[0],
 		  context->argv[1],
 		  context->argv[2],
@@ -679,33 +714,57 @@
 		  context->egid, context->sgid, context->fsgid);
 	audit_log_task_info(ab);
 	audit_log_end(ab);
-	while (context->aux) {
-		struct audit_aux_data *aux;
 
-		ab = audit_log_start(context);
+	for (aux = context->aux; aux; aux = aux->next) {
+
+		ab = audit_log_start(context, aux->type);
 		if (!ab)
 			continue; /* audit_panic has been called */
 
-		aux = context->aux;
-		context->aux = aux->next;
-
-		audit_log_format(ab, "auxitem=%d", aux->type);
 		switch (aux->type) {
-		case AUDIT_AUX_IPCPERM: {
+		case AUDIT_IPC: {
 			struct audit_aux_data_ipcctl *axi = (void *)aux;
 			audit_log_format(ab, 
-					 " qbytes=%lx uid=%d gid=%d mode=%x",
+					 " qbytes=%lx iuid=%u igid=%u mode=%x",
 					 axi->qbytes, axi->uid, axi->gid, axi->mode);
-			}
+			break; }
+
+		case AUDIT_SOCKETCALL: {
+			int i;
+			struct audit_aux_data_socketcall *axs = (void *)aux;
+			audit_log_format(ab, "nargs=%d", axs->nargs);
+			for (i=0; i<axs->nargs; i++)
+				audit_log_format(ab, " a%d=%lx", i, axs->args[i]);
+			break; }
+
+		case AUDIT_SOCKADDR: {
+			struct audit_aux_data_sockaddr *axs = (void *)aux;
+
+			audit_log_format(ab, "saddr=");
+			audit_log_hex(ab, axs->a, axs->len);
+			break; }
+
+		case AUDIT_AVC_PATH: {
+			struct audit_aux_data_path *axi = (void *)aux;
+			audit_log_d_path(ab, "path=", axi->dentry, axi->mnt);
+			break; }
+
 		}
 		audit_log_end(ab);
-		kfree(aux);
 	}
 
+	if (context->pwd && context->pwdmnt) {
+		ab = audit_log_start(context, AUDIT_CWD);
+		if (ab) {
+			audit_log_d_path(ab, "cwd=", context->pwd, context->pwdmnt);
+			audit_log_end(ab);
+		}
+	}
 	for (i = 0; i < context->name_count; i++) {
-		ab = audit_log_start(context);
+		ab = audit_log_start(context, AUDIT_PATH);
 		if (!ab)
 			continue; /* audit_panic has been called */
+
 		audit_log_format(ab, "item=%d", i);
 		if (context->names[i].name) {
 			audit_log_format(ab, " name=");
@@ -713,7 +772,7 @@
 		}
 		if (context->names[i].ino != (unsigned long)-1)
 			audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#o"
-					     " uid=%d gid=%d rdev=%02x:%02x",
+					     " ouid=%u ogid=%u rdev=%02x:%02x",
 					 context->names[i].ino,
 					 MAJOR(context->names[i].dev),
 					 MINOR(context->names[i].dev),
@@ -741,42 +800,12 @@
 
 	/* Check for system calls that do not go through the exit
 	 * function (e.g., exit_group), then free context block. */
-	if (context->in_syscall && context->auditable)
+	if (context->in_syscall && context->auditable && context->pid != audit_pid)
 		audit_log_exit(context);
 
 	audit_free_context(context);
 }
 
-/* Compute a serial number for the audit record.  Audit records are
- * written to user-space as soon as they are generated, so a complete
- * audit record may be written in several pieces.  The timestamp of the
- * record and this serial number are used by the user-space daemon to
- * determine which pieces belong to the same audit record.  The
- * (timestamp,serial) tuple is unique for each syscall and is live from
- * syscall entry to syscall exit.
- *
- * Atomic values are only guaranteed to be 24-bit, so we count down.
- *
- * NOTE: Another possibility is to store the formatted records off the
- * audit context (for those records that have a context), and emit them
- * all at syscall exit.  However, this could delay the reporting of
- * significant errors until syscall exit (or never, if the system
- * halts). */
-static inline unsigned int audit_serial(void)
-{
-	static atomic_t serial = ATOMIC_INIT(0xffffff);
-	unsigned int a, b;
-
-	do {
-		a = atomic_read(&serial);
-		if (atomic_dec_and_test(&serial))
-			atomic_set(&serial, 0xffffff);
-		b = atomic_read(&serial);
-	} while (b != a - 1);
-
-	return 0xffffff - b;
-}
-
 /* Fill in audit context at syscall entry.  This only happens if the
  * audit context was created when the task was created and the state or
  * filters demand the audit context be built.  If the state from the
@@ -876,7 +905,7 @@
 	if (likely(!context))
 		return;
 
-	if (context->in_syscall && context->auditable)
+	if (context->in_syscall && context->auditable && context->pid != audit_pid)
 		audit_log_exit(context);
 
 	context->in_syscall = 0;
@@ -916,6 +945,13 @@
 	context->names[context->name_count].name = name;
 	context->names[context->name_count].ino  = (unsigned long)-1;
 	++context->name_count;
+	if (!context->pwd) {
+		read_lock(&current->fs->lock);
+		context->pwd = dget(current->fs->pwd);
+		context->pwdmnt = mntget(current->fs->pwdmnt);
+		read_unlock(&current->fs->lock);
+	}
+		
 }
 
 /* Intercept a putname request.  Called from
@@ -994,34 +1030,26 @@
 	context->names[idx].rdev = inode->i_rdev;
 }
 
-void audit_get_stamp(struct audit_context *ctx,
-		     struct timespec *t, unsigned int *serial)
+void auditsc_get_stamp(struct audit_context *ctx,
+		       struct timespec *t, unsigned int *serial)
 {
-	if (ctx) {
-		t->tv_sec  = ctx->ctime.tv_sec;
-		t->tv_nsec = ctx->ctime.tv_nsec;
-		*serial    = ctx->serial;
-		ctx->auditable = 1;
-	} else {
-		*t      = CURRENT_TIME;
-		*serial = 0;
-	}
+	t->tv_sec  = ctx->ctime.tv_sec;
+	t->tv_nsec = ctx->ctime.tv_nsec;
+	*serial    = ctx->serial;
+	ctx->auditable = 1;
 }
 
-extern int audit_set_type(struct audit_buffer *ab, int type);
-
 int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
 {
 	if (task->audit_context) {
 		struct audit_buffer *ab;
 
-		ab = audit_log_start(NULL);
+		ab = audit_log_start(NULL, AUDIT_LOGIN);
 		if (ab) {
 			audit_log_format(ab, "login pid=%d uid=%u "
-				"old loginuid=%u new loginuid=%u",
+				"old auid=%u new auid=%u",
 				task->pid, task->uid, 
 				task->audit_context->loginuid, loginuid);
-			audit_set_type(ab, AUDIT_LOGIN);
 			audit_log_end(ab);
 		}
 		task->audit_context->loginuid = loginuid;
@@ -1051,8 +1079,89 @@
 	ax->gid = gid;
 	ax->mode = mode;
 
-	ax->d.type = AUDIT_AUX_IPCPERM;
+	ax->d.type = AUDIT_IPC;
 	ax->d.next = context->aux;
 	context->aux = (void *)ax;
 	return 0;
 }
+
+int audit_socketcall(int nargs, unsigned long *args)
+{
+	struct audit_aux_data_socketcall *ax;
+	struct audit_context *context = current->audit_context;
+
+	if (likely(!context))
+		return 0;
+
+	ax = kmalloc(sizeof(*ax) + nargs * sizeof(unsigned long), GFP_KERNEL);
+	if (!ax)
+		return -ENOMEM;
+
+	ax->nargs = nargs;
+	memcpy(ax->args, args, nargs * sizeof(unsigned long));
+
+	ax->d.type = AUDIT_SOCKETCALL;
+	ax->d.next = context->aux;
+	context->aux = (void *)ax;
+	return 0;
+}
+
+int audit_sockaddr(int len, void *a)
+{
+	struct audit_aux_data_sockaddr *ax;
+	struct audit_context *context = current->audit_context;
+
+	if (likely(!context))
+		return 0;
+
+	ax = kmalloc(sizeof(*ax) + len, GFP_KERNEL);
+	if (!ax)
+		return -ENOMEM;
+
+	ax->len = len;
+	memcpy(ax->a, a, len);
+
+	ax->d.type = AUDIT_SOCKADDR;
+	ax->d.next = context->aux;
+	context->aux = (void *)ax;
+	return 0;
+}
+
+int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt)
+{
+	struct audit_aux_data_path *ax;
+	struct audit_context *context = current->audit_context;
+
+	if (likely(!context))
+		return 0;
+
+	ax = kmalloc(sizeof(*ax), GFP_ATOMIC);
+	if (!ax)
+		return -ENOMEM;
+
+	ax->dentry = dget(dentry);
+	ax->mnt = mntget(mnt);
+
+	ax->d.type = AUDIT_AVC_PATH;
+	ax->d.next = context->aux;
+	context->aux = (void *)ax;
+	return 0;
+}
+
+void audit_signal_info(int sig, struct task_struct *t)
+{
+	extern pid_t audit_sig_pid;
+	extern uid_t audit_sig_uid;
+
+	if (unlikely(audit_pid && t->pid == 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;
+		}
+	}
+}
+
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 628f4cc..53d8263 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -63,19 +63,15 @@
 {
 	int err;
 
-	/* Take offline: makes arch_cpu_down somewhat easier. */
-	cpu_clear(smp_processor_id(), cpu_online_map);
-
 	/* Ensure this CPU doesn't handle any more interrupts. */
 	err = __cpu_disable();
 	if (err < 0)
-		cpu_set(smp_processor_id(), cpu_online_map);
-	else
-		/* Force idle task to run as soon as we yield: it should
-		   immediately notice cpu is offline and die quickly. */
-		sched_idle_next();
+		return err;
 
-	return err;
+	/* Force idle task to run as soon as we yield: it should
+	   immediately notice cpu is offline and die quickly. */
+	sched_idle_next();
+	return 0;
 }
 
 int cpu_down(unsigned int cpu)
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 00e8f25..984c0bf 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -228,13 +228,7 @@
 
 static struct dentry *cpuset_get_dentry(struct dentry *parent, const char *name)
 {
-	struct qstr qstr;
-	struct dentry *d;
-
-	qstr.name = name;
-	qstr.len = strlen(name);
-	qstr.hash = full_name_hash(name, qstr.len);
-	d = lookup_hash(&qstr, parent);
+	struct dentry *d = lookup_one_len(name, parent, strlen(name));
 	if (!IS_ERR(d))
 		d->d_op = &cpuset_dops;
 	return d;
@@ -601,10 +595,62 @@
 	return 0;
 }
 
+/*
+ * For a given cpuset cur, partition the system as follows
+ * a. All cpus in the parent cpuset's cpus_allowed that are not part of any
+ *    exclusive child cpusets
+ * b. All cpus in the current cpuset's cpus_allowed that are not part of any
+ *    exclusive child cpusets
+ * Build these two partitions by calling partition_sched_domains
+ *
+ * Call with cpuset_sem held.  May nest a call to the
+ * lock_cpu_hotplug()/unlock_cpu_hotplug() pair.
+ */
+static void update_cpu_domains(struct cpuset *cur)
+{
+	struct cpuset *c, *par = cur->parent;
+	cpumask_t pspan, cspan;
+
+	if (par == NULL || cpus_empty(cur->cpus_allowed))
+		return;
+
+	/*
+	 * Get all cpus from parent's cpus_allowed not part of exclusive
+	 * children
+	 */
+	pspan = par->cpus_allowed;
+	list_for_each_entry(c, &par->children, sibling) {
+		if (is_cpu_exclusive(c))
+			cpus_andnot(pspan, pspan, c->cpus_allowed);
+	}
+	if (is_removed(cur) || !is_cpu_exclusive(cur)) {
+		cpus_or(pspan, pspan, cur->cpus_allowed);
+		if (cpus_equal(pspan, cur->cpus_allowed))
+			return;
+		cspan = CPU_MASK_NONE;
+	} else {
+		if (cpus_empty(pspan))
+			return;
+		cspan = cur->cpus_allowed;
+		/*
+		 * Get all cpus from current cpuset's cpus_allowed not part
+		 * of exclusive children
+		 */
+		list_for_each_entry(c, &cur->children, sibling) {
+			if (is_cpu_exclusive(c))
+				cpus_andnot(cspan, cspan, c->cpus_allowed);
+		}
+	}
+
+	lock_cpu_hotplug();
+	partition_sched_domains(&pspan, &cspan);
+	unlock_cpu_hotplug();
+}
+
 static int update_cpumask(struct cpuset *cs, char *buf)
 {
 	struct cpuset trialcs;
-	int retval;
+	int retval, cpus_unchanged;
 
 	trialcs = *cs;
 	retval = cpulist_parse(buf, trialcs.cpus_allowed);
@@ -614,9 +660,13 @@
 	if (cpus_empty(trialcs.cpus_allowed))
 		return -ENOSPC;
 	retval = validate_change(cs, &trialcs);
-	if (retval == 0)
-		cs->cpus_allowed = trialcs.cpus_allowed;
-	return retval;
+	if (retval < 0)
+		return retval;
+	cpus_unchanged = cpus_equal(cs->cpus_allowed, trialcs.cpus_allowed);
+	cs->cpus_allowed = trialcs.cpus_allowed;
+	if (is_cpu_exclusive(cs) && !cpus_unchanged)
+		update_cpu_domains(cs);
+	return 0;
 }
 
 static int update_nodemask(struct cpuset *cs, char *buf)
@@ -652,7 +702,7 @@
 {
 	int turning_on;
 	struct cpuset trialcs;
-	int err;
+	int err, cpu_exclusive_changed;
 
 	turning_on = (simple_strtoul(buf, NULL, 10) != 0);
 
@@ -663,13 +713,18 @@
 		clear_bit(bit, &trialcs.flags);
 
 	err = validate_change(cs, &trialcs);
-	if (err == 0) {
-		if (turning_on)
-			set_bit(bit, &cs->flags);
-		else
-			clear_bit(bit, &cs->flags);
-	}
-	return err;
+	if (err < 0)
+		return err;
+	cpu_exclusive_changed =
+		(is_cpu_exclusive(cs) != is_cpu_exclusive(&trialcs));
+	if (turning_on)
+		set_bit(bit, &cs->flags);
+	else
+		clear_bit(bit, &cs->flags);
+
+	if (cpu_exclusive_changed)
+                update_cpu_domains(cs);
+	return 0;
 }
 
 static int attach_task(struct cpuset *cs, char *buf)
@@ -1315,12 +1370,14 @@
 		up(&cpuset_sem);
 		return -EBUSY;
 	}
-	spin_lock(&cs->dentry->d_lock);
 	parent = cs->parent;
 	set_bit(CS_REMOVED, &cs->flags);
+	if (is_cpu_exclusive(cs))
+		update_cpu_domains(cs);
 	list_del(&cs->sibling);	/* delete my sibling from parent->children */
 	if (list_empty(&parent->children))
 		check_for_release(parent);
+	spin_lock(&cs->dentry->d_lock);
 	d = dget(cs->dentry);
 	cs->dentry = NULL;
 	spin_unlock(&d->d_lock);
diff --git a/kernel/crash_dump.c b/kernel/crash_dump.c
new file mode 100644
index 0000000..459ba49
--- /dev/null
+++ b/kernel/crash_dump.c
@@ -0,0 +1,52 @@
+/*
+ *	kernel/crash_dump.c - Memory preserving reboot related code.
+ *
+ *	Created by: Hariprasad Nellitheertha (hari@in.ibm.com)
+ *	Copyright (C) IBM Corporation, 2004. All rights reserved
+ */
+
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+#include <linux/bootmem.h>
+#include <linux/highmem.h>
+#include <linux/crash_dump.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+/* Stores the physical address of elf header of crash image. */
+unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
+
+/*
+ * Copy a page from "oldmem". For this page, there is no pte mapped
+ * in the current kernel. We stitch up a pte, similar to kmap_atomic.
+ */
+ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
+				size_t csize, unsigned long offset, int userbuf)
+{
+	void *page, *vaddr;
+
+	if (!csize)
+		return 0;
+
+	page = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+
+	vaddr = kmap_atomic_pfn(pfn, KM_PTE0);
+	copy_page(page, vaddr);
+	kunmap_atomic(vaddr, KM_PTE0);
+
+	if (userbuf) {
+		if (copy_to_user(buf, (page + offset), csize)) {
+			kfree(page);
+			return -EFAULT;
+		}
+	} else {
+		memcpy(buf, (page + offset), csize);
+	}
+
+	kfree(page);
+	return csize;
+}
diff --git a/kernel/exit.c b/kernel/exit.c
index edaa50b..9d1b10e 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -72,6 +72,11 @@
 	BUG_ON(!list_empty(&p->ptrace_list) || !list_empty(&p->ptrace_children));
 	__exit_signal(p);
 	__exit_sighand(p);
+	/*
+	 * Note that the fastpath in sys_times depends on __exit_signal having
+	 * updated the counters before a task is removed from the tasklist of
+	 * the process by __unhash_process.
+	 */
 	__unhash_process(p);
 
 	/*
@@ -779,6 +784,8 @@
 
 	profile_task_exit(tsk);
 
+	WARN_ON(atomic_read(&tsk->fs_excl));
+
 	if (unlikely(in_interrupt()))
 		panic("Aiee, killing interrupt handler!");
 	if (unlikely(!tsk->pid))
@@ -793,6 +800,17 @@
 		ptrace_notify((PTRACE_EVENT_EXIT << 8) | SIGTRAP);
 	}
 
+	/*
+	 * We're taking recursive faults here in do_exit. Safest is to just
+	 * leave this task alone and wait for reboot.
+	 */
+	if (unlikely(tsk->flags & PF_EXITING)) {
+		printk(KERN_ALERT
+			"Fixing recursive fault but reboot is needed!\n");
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule();
+	}
+
 	tsk->flags |= PF_EXITING;
 
 	/*
@@ -811,10 +829,8 @@
 	acct_update_integrals(tsk);
 	update_mem_hiwater(tsk);
 	group_dead = atomic_dec_and_test(&tsk->signal->live);
-	if (group_dead) {
- 		del_timer_sync(&tsk->signal->real_timer);
+	if (group_dead)
 		acct_process(code);
-	}
 	exit_mm(tsk);
 
 	exit_sem(tsk);
diff --git a/kernel/fork.c b/kernel/fork.c
index f42a17f..cdef6ce 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -194,6 +194,7 @@
 	mm->mmap = NULL;
 	mm->mmap_cache = NULL;
 	mm->free_area_cache = oldmm->mmap_base;
+	mm->cached_hole_size = ~0UL;
 	mm->map_count = 0;
 	set_mm_counter(mm, rss, 0);
 	set_mm_counter(mm, anon_rss, 0);
@@ -249,8 +250,9 @@
 
 		/*
 		 * Link in the new vma and copy the page table entries:
-		 * link in first so that swapoff can see swap entries,
-		 * and try_to_unmap_one's find_vma find the new vma.
+		 * link in first so that swapoff can see swap entries.
+		 * Note that, exceptionally, here the vma is inserted
+		 * without holding mm->mmap_sem.
 		 */
 		spin_lock(&mm->page_table_lock);
 		*pprev = tmp;
@@ -322,6 +324,7 @@
 	mm->ioctx_list = NULL;
 	mm->default_kioctx = (struct kioctx)INIT_KIOCTX(mm->default_kioctx, *mm);
 	mm->free_area_cache = TASK_UNMAPPED_BASE;
+	mm->cached_hole_size = ~0UL;
 
 	if (likely(!mm_alloc_pgd(mm))) {
 		mm->def_flags = 0;
@@ -1000,9 +1003,6 @@
 	p->pdeath_signal = 0;
 	p->exit_state = 0;
 
-	/* Perform scheduler related setup */
-	sched_fork(p);
-
 	/*
 	 * Ok, make it visible to the rest of the system.
 	 * We dont wake it up yet.
@@ -1011,18 +1011,24 @@
 	INIT_LIST_HEAD(&p->ptrace_children);
 	INIT_LIST_HEAD(&p->ptrace_list);
 
+	/* Perform scheduler related setup. Assign this task to a CPU. */
+	sched_fork(p, clone_flags);
+
 	/* Need tasklist lock for parent etc handling! */
 	write_lock_irq(&tasklist_lock);
 
 	/*
-	 * The task hasn't been attached yet, so cpus_allowed mask cannot
-	 * have changed. The cpus_allowed mask of the parent may have
-	 * changed after it was copied first time, and it may then move to
-	 * another CPU - so we re-copy it here and set the child's CPU to
-	 * the parent's CPU. This avoids alot of nasty races.
+	 * The task hasn't been attached yet, so its cpus_allowed mask will
+	 * not be changed, nor will its assigned CPU.
+	 *
+	 * The cpus_allowed mask of the parent may have changed after it was
+	 * copied first time - so re-copy it here, then check the child's CPU
+	 * to ensure it is on a valid CPU (and if not, just force it back to
+	 * parent's CPU). This avoids alot of nasty races.
 	 */
 	p->cpus_allowed = current->cpus_allowed;
-	set_task_cpu(p, smp_processor_id());
+	if (unlikely(!cpu_isset(task_cpu(p), p->cpus_allowed)))
+		set_task_cpu(p, smp_processor_id());
 
 	/*
 	 * Check for pending SIGKILL! The new thread should not be allowed
@@ -1084,6 +1090,11 @@
 		spin_unlock(&current->sighand->siglock);
 	}
 
+	/*
+	 * inherit ioprio
+	 */
+	p->ioprio = current->ioprio;
+
 	SET_LINKS(p);
 	if (unlikely(p->ptrace & PT_PTRACED))
 		__ptrace_link(p, current->parent);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 5202e4c..ac67009 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -6,6 +6,7 @@
  * This file contains driver APIs to the irq subsystem.
  */
 
+#include <linux/config.h>
 #include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/random.h>
@@ -255,6 +256,13 @@
 
 			/* Found it - now remove it from the list of entries */
 			*pp = action->next;
+
+			/* Currently used only by UML, might disappear one day.*/
+#ifdef CONFIG_IRQ_RELEASE_METHOD
+			if (desc->handler->release)
+				desc->handler->release(irq, dev_id);
+#endif
+
 			if (!desc->action) {
 				desc->status |= IRQ_DISABLED;
 				if (desc->handler->shutdown)
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index f6297c3..ba039e8 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -45,7 +45,7 @@
 	}
 }
 
-void report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
+static void report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
 {
 	static int count = 100;
 
diff --git a/kernel/kexec.c b/kernel/kexec.c
new file mode 100644
index 0000000..7843548
--- /dev/null
+++ b/kernel/kexec.c
@@ -0,0 +1,1063 @@
+/*
+ * kexec.c - kexec system call
+ * Copyright (C) 2002-2004 Eric Biederman  <ebiederm@xmission.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+
+#include <linux/mm.h>
+#include <linux/file.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/kexec.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/highmem.h>
+#include <linux/syscalls.h>
+#include <linux/reboot.h>
+#include <linux/syscalls.h>
+#include <linux/ioport.h>
+#include <linux/hardirq.h>
+
+#include <asm/page.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/semaphore.h>
+
+/* Location of the reserved area for the crash kernel */
+struct resource crashk_res = {
+	.name  = "Crash kernel",
+	.start = 0,
+	.end   = 0,
+	.flags = IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+int kexec_should_crash(struct task_struct *p)
+{
+	if (in_interrupt() || !p->pid || p->pid == 1 || panic_on_oops)
+		return 1;
+	return 0;
+}
+
+/*
+ * When kexec transitions to the new kernel there is a one-to-one
+ * mapping between physical and virtual addresses.  On processors
+ * where you can disable the MMU this is trivial, and easy.  For
+ * others it is still a simple predictable page table to setup.
+ *
+ * In that environment kexec copies the new kernel to its final
+ * resting place.  This means I can only support memory whose
+ * physical address can fit in an unsigned long.  In particular
+ * addresses where (pfn << PAGE_SHIFT) > ULONG_MAX cannot be handled.
+ * If the assembly stub has more restrictive requirements
+ * KEXEC_SOURCE_MEMORY_LIMIT and KEXEC_DEST_MEMORY_LIMIT can be
+ * defined more restrictively in <asm/kexec.h>.
+ *
+ * The code for the transition from the current kernel to the
+ * the new kernel is placed in the control_code_buffer, whose size
+ * is given by KEXEC_CONTROL_CODE_SIZE.  In the best case only a single
+ * page of memory is necessary, but some architectures require more.
+ * Because this memory must be identity mapped in the transition from
+ * virtual to physical addresses it must live in the range
+ * 0 - TASK_SIZE, as only the user space mappings are arbitrarily
+ * modifiable.
+ *
+ * The assembly stub in the control code buffer is passed a linked list
+ * of descriptor pages detailing the source pages of the new kernel,
+ * and the destination addresses of those source pages.  As this data
+ * structure is not used in the context of the current OS, it must
+ * be self-contained.
+ *
+ * The code has been made to work with highmem pages and will use a
+ * destination page in its final resting place (if it happens
+ * to allocate it).  The end product of this is that most of the
+ * physical address space, and most of RAM can be used.
+ *
+ * Future directions include:
+ *  - allocating a page table with the control code buffer identity
+ *    mapped, to simplify machine_kexec and make kexec_on_panic more
+ *    reliable.
+ */
+
+/*
+ * KIMAGE_NO_DEST is an impossible destination address..., for
+ * allocating pages whose destination address we do not care about.
+ */
+#define KIMAGE_NO_DEST (-1UL)
+
+static int kimage_is_destination_range(struct kimage *image,
+				       unsigned long start, unsigned long end);
+static struct page *kimage_alloc_page(struct kimage *image,
+				       unsigned int gfp_mask,
+				       unsigned long dest);
+
+static int do_kimage_alloc(struct kimage **rimage, unsigned long entry,
+	                    unsigned long nr_segments,
+                            struct kexec_segment __user *segments)
+{
+	size_t segment_bytes;
+	struct kimage *image;
+	unsigned long i;
+	int result;
+
+	/* Allocate a controlling structure */
+	result = -ENOMEM;
+	image = kmalloc(sizeof(*image), GFP_KERNEL);
+	if (!image)
+		goto out;
+
+	memset(image, 0, sizeof(*image));
+	image->head = 0;
+	image->entry = &image->head;
+	image->last_entry = &image->head;
+	image->control_page = ~0; /* By default this does not apply */
+	image->start = entry;
+	image->type = KEXEC_TYPE_DEFAULT;
+
+	/* Initialize the list of control pages */
+	INIT_LIST_HEAD(&image->control_pages);
+
+	/* Initialize the list of destination pages */
+	INIT_LIST_HEAD(&image->dest_pages);
+
+	/* Initialize the list of unuseable pages */
+	INIT_LIST_HEAD(&image->unuseable_pages);
+
+	/* Read in the segments */
+	image->nr_segments = nr_segments;
+	segment_bytes = nr_segments * sizeof(*segments);
+	result = copy_from_user(image->segment, segments, segment_bytes);
+	if (result)
+		goto out;
+
+	/*
+	 * Verify we have good destination addresses.  The caller is
+	 * responsible for making certain we don't attempt to load
+	 * the new image into invalid or reserved areas of RAM.  This
+	 * just verifies it is an address we can use.
+	 *
+	 * Since the kernel does everything in page size chunks ensure
+	 * the destination addreses are page aligned.  Too many
+	 * special cases crop of when we don't do this.  The most
+	 * insidious is getting overlapping destination addresses
+	 * simply because addresses are changed to page size
+	 * granularity.
+	 */
+	result = -EADDRNOTAVAIL;
+	for (i = 0; i < nr_segments; i++) {
+		unsigned long mstart, mend;
+
+		mstart = image->segment[i].mem;
+		mend   = mstart + image->segment[i].memsz;
+		if ((mstart & ~PAGE_MASK) || (mend & ~PAGE_MASK))
+			goto out;
+		if (mend >= KEXEC_DESTINATION_MEMORY_LIMIT)
+			goto out;
+	}
+
+	/* Verify our destination addresses do not overlap.
+	 * If we alloed overlapping destination addresses
+	 * through very weird things can happen with no
+	 * easy explanation as one segment stops on another.
+	 */
+	result = -EINVAL;
+	for (i = 0; i < nr_segments; i++) {
+		unsigned long mstart, mend;
+		unsigned long j;
+
+		mstart = image->segment[i].mem;
+		mend   = mstart + image->segment[i].memsz;
+		for (j = 0; j < i; j++) {
+			unsigned long pstart, pend;
+			pstart = image->segment[j].mem;
+			pend   = pstart + image->segment[j].memsz;
+			/* Do the segments overlap ? */
+			if ((mend > pstart) && (mstart < pend))
+				goto out;
+		}
+	}
+
+	/* Ensure our buffer sizes are strictly less than
+	 * our memory sizes.  This should always be the case,
+	 * and it is easier to check up front than to be surprised
+	 * later on.
+	 */
+	result = -EINVAL;
+	for (i = 0; i < nr_segments; i++) {
+		if (image->segment[i].bufsz > image->segment[i].memsz)
+			goto out;
+	}
+
+	result = 0;
+out:
+	if (result == 0)
+		*rimage = image;
+	else
+		kfree(image);
+
+	return result;
+
+}
+
+static int kimage_normal_alloc(struct kimage **rimage, unsigned long entry,
+				unsigned long nr_segments,
+				struct kexec_segment __user *segments)
+{
+	int result;
+	struct kimage *image;
+
+	/* Allocate and initialize a controlling structure */
+	image = NULL;
+	result = do_kimage_alloc(&image, entry, nr_segments, segments);
+	if (result)
+		goto out;
+
+	*rimage = image;
+
+	/*
+	 * Find a location for the control code buffer, and add it
+	 * the vector of segments so that it's pages will also be
+	 * counted as destination pages.
+	 */
+	result = -ENOMEM;
+	image->control_code_page = kimage_alloc_control_pages(image,
+					   get_order(KEXEC_CONTROL_CODE_SIZE));
+	if (!image->control_code_page) {
+		printk(KERN_ERR "Could not allocate control_code_buffer\n");
+		goto out;
+	}
+
+	result = 0;
+ out:
+	if (result == 0)
+		*rimage = image;
+	else
+		kfree(image);
+
+	return result;
+}
+
+static int kimage_crash_alloc(struct kimage **rimage, unsigned long entry,
+				unsigned long nr_segments,
+				struct kexec_segment *segments)
+{
+	int result;
+	struct kimage *image;
+	unsigned long i;
+
+	image = NULL;
+	/* Verify we have a valid entry point */
+	if ((entry < crashk_res.start) || (entry > crashk_res.end)) {
+		result = -EADDRNOTAVAIL;
+		goto out;
+	}
+
+	/* Allocate and initialize a controlling structure */
+	result = do_kimage_alloc(&image, entry, nr_segments, segments);
+	if (result)
+		goto out;
+
+	/* Enable the special crash kernel control page
+	 * allocation policy.
+	 */
+	image->control_page = crashk_res.start;
+	image->type = KEXEC_TYPE_CRASH;
+
+	/*
+	 * Verify we have good destination addresses.  Normally
+	 * the caller is responsible for making certain we don't
+	 * attempt to load the new image into invalid or reserved
+	 * areas of RAM.  But crash kernels are preloaded into a
+	 * reserved area of ram.  We must ensure the addresses
+	 * are in the reserved area otherwise preloading the
+	 * kernel could corrupt things.
+	 */
+	result = -EADDRNOTAVAIL;
+	for (i = 0; i < nr_segments; i++) {
+		unsigned long mstart, mend;
+
+		mstart = image->segment[i].mem;
+		mend = mstart + image->segment[i].memsz - 1;
+		/* Ensure we are within the crash kernel limits */
+		if ((mstart < crashk_res.start) || (mend > crashk_res.end))
+			goto out;
+	}
+
+	/*
+	 * Find a location for the control code buffer, and add
+	 * the vector of segments so that it's pages will also be
+	 * counted as destination pages.
+	 */
+	result = -ENOMEM;
+	image->control_code_page = kimage_alloc_control_pages(image,
+					   get_order(KEXEC_CONTROL_CODE_SIZE));
+	if (!image->control_code_page) {
+		printk(KERN_ERR "Could not allocate control_code_buffer\n");
+		goto out;
+	}
+
+	result = 0;
+out:
+	if (result == 0)
+		*rimage = image;
+	else
+		kfree(image);
+
+	return result;
+}
+
+static int kimage_is_destination_range(struct kimage *image,
+					unsigned long start,
+					unsigned long end)
+{
+	unsigned long i;
+
+	for (i = 0; i < image->nr_segments; i++) {
+		unsigned long mstart, mend;
+
+		mstart = image->segment[i].mem;
+		mend = mstart + image->segment[i].memsz;
+		if ((end > mstart) && (start < mend))
+			return 1;
+	}
+
+	return 0;
+}
+
+static struct page *kimage_alloc_pages(unsigned int gfp_mask,
+					unsigned int order)
+{
+	struct page *pages;
+
+	pages = alloc_pages(gfp_mask, order);
+	if (pages) {
+		unsigned int count, i;
+		pages->mapping = NULL;
+		pages->private = order;
+		count = 1 << order;
+		for (i = 0; i < count; i++)
+			SetPageReserved(pages + i);
+	}
+
+	return pages;
+}
+
+static void kimage_free_pages(struct page *page)
+{
+	unsigned int order, count, i;
+
+	order = page->private;
+	count = 1 << order;
+	for (i = 0; i < count; i++)
+		ClearPageReserved(page + i);
+	__free_pages(page, order);
+}
+
+static void kimage_free_page_list(struct list_head *list)
+{
+	struct list_head *pos, *next;
+
+	list_for_each_safe(pos, next, list) {
+		struct page *page;
+
+		page = list_entry(pos, struct page, lru);
+		list_del(&page->lru);
+		kimage_free_pages(page);
+	}
+}
+
+static struct page *kimage_alloc_normal_control_pages(struct kimage *image,
+							unsigned int order)
+{
+	/* Control pages are special, they are the intermediaries
+	 * that are needed while we copy the rest of the pages
+	 * to their final resting place.  As such they must
+	 * not conflict with either the destination addresses
+	 * or memory the kernel is already using.
+	 *
+	 * The only case where we really need more than one of
+	 * these are for architectures where we cannot disable
+	 * the MMU and must instead generate an identity mapped
+	 * page table for all of the memory.
+	 *
+	 * At worst this runs in O(N) of the image size.
+	 */
+	struct list_head extra_pages;
+	struct page *pages;
+	unsigned int count;
+
+	count = 1 << order;
+	INIT_LIST_HEAD(&extra_pages);
+
+	/* Loop while I can allocate a page and the page allocated
+	 * is a destination page.
+	 */
+	do {
+		unsigned long pfn, epfn, addr, eaddr;
+
+		pages = kimage_alloc_pages(GFP_KERNEL, order);
+		if (!pages)
+			break;
+		pfn   = page_to_pfn(pages);
+		epfn  = pfn + count;
+		addr  = pfn << PAGE_SHIFT;
+		eaddr = epfn << PAGE_SHIFT;
+		if ((epfn >= (KEXEC_CONTROL_MEMORY_LIMIT >> PAGE_SHIFT)) ||
+			      kimage_is_destination_range(image, addr, eaddr)) {
+			list_add(&pages->lru, &extra_pages);
+			pages = NULL;
+		}
+	} while (!pages);
+
+	if (pages) {
+		/* Remember the allocated page... */
+		list_add(&pages->lru, &image->control_pages);
+
+		/* Because the page is already in it's destination
+		 * location we will never allocate another page at
+		 * that address.  Therefore kimage_alloc_pages
+		 * will not return it (again) and we don't need
+		 * to give it an entry in image->segment[].
+		 */
+	}
+	/* Deal with the destination pages I have inadvertently allocated.
+	 *
+	 * Ideally I would convert multi-page allocations into single
+	 * page allocations, and add everyting to image->dest_pages.
+	 *
+	 * For now it is simpler to just free the pages.
+	 */
+	kimage_free_page_list(&extra_pages);
+
+	return pages;
+}
+
+static struct page *kimage_alloc_crash_control_pages(struct kimage *image,
+						      unsigned int order)
+{
+	/* Control pages are special, they are the intermediaries
+	 * that are needed while we copy the rest of the pages
+	 * to their final resting place.  As such they must
+	 * not conflict with either the destination addresses
+	 * or memory the kernel is already using.
+	 *
+	 * Control pages are also the only pags we must allocate
+	 * when loading a crash kernel.  All of the other pages
+	 * are specified by the segments and we just memcpy
+	 * into them directly.
+	 *
+	 * The only case where we really need more than one of
+	 * these are for architectures where we cannot disable
+	 * the MMU and must instead generate an identity mapped
+	 * page table for all of the memory.
+	 *
+	 * Given the low demand this implements a very simple
+	 * allocator that finds the first hole of the appropriate
+	 * size in the reserved memory region, and allocates all
+	 * of the memory up to and including the hole.
+	 */
+	unsigned long hole_start, hole_end, size;
+	struct page *pages;
+
+	pages = NULL;
+	size = (1 << order) << PAGE_SHIFT;
+	hole_start = (image->control_page + (size - 1)) & ~(size - 1);
+	hole_end   = hole_start + size - 1;
+	while (hole_end <= crashk_res.end) {
+		unsigned long i;
+
+		if (hole_end > KEXEC_CONTROL_MEMORY_LIMIT)
+			break;
+		if (hole_end > crashk_res.end)
+			break;
+		/* See if I overlap any of the segments */
+		for (i = 0; i < image->nr_segments; i++) {
+			unsigned long mstart, mend;
+
+			mstart = image->segment[i].mem;
+			mend   = mstart + image->segment[i].memsz - 1;
+			if ((hole_end >= mstart) && (hole_start <= mend)) {
+				/* Advance the hole to the end of the segment */
+				hole_start = (mend + (size - 1)) & ~(size - 1);
+				hole_end   = hole_start + size - 1;
+				break;
+			}
+		}
+		/* If I don't overlap any segments I have found my hole! */
+		if (i == image->nr_segments) {
+			pages = pfn_to_page(hole_start >> PAGE_SHIFT);
+			break;
+		}
+	}
+	if (pages)
+		image->control_page = hole_end;
+
+	return pages;
+}
+
+
+struct page *kimage_alloc_control_pages(struct kimage *image,
+					 unsigned int order)
+{
+	struct page *pages = NULL;
+
+	switch (image->type) {
+	case KEXEC_TYPE_DEFAULT:
+		pages = kimage_alloc_normal_control_pages(image, order);
+		break;
+	case KEXEC_TYPE_CRASH:
+		pages = kimage_alloc_crash_control_pages(image, order);
+		break;
+	}
+
+	return pages;
+}
+
+static int kimage_add_entry(struct kimage *image, kimage_entry_t entry)
+{
+	if (*image->entry != 0)
+		image->entry++;
+
+	if (image->entry == image->last_entry) {
+		kimage_entry_t *ind_page;
+		struct page *page;
+
+		page = kimage_alloc_page(image, GFP_KERNEL, KIMAGE_NO_DEST);
+		if (!page)
+			return -ENOMEM;
+
+		ind_page = page_address(page);
+		*image->entry = virt_to_phys(ind_page) | IND_INDIRECTION;
+		image->entry = ind_page;
+		image->last_entry = ind_page +
+				      ((PAGE_SIZE/sizeof(kimage_entry_t)) - 1);
+	}
+	*image->entry = entry;
+	image->entry++;
+	*image->entry = 0;
+
+	return 0;
+}
+
+static int kimage_set_destination(struct kimage *image,
+				   unsigned long destination)
+{
+	int result;
+
+	destination &= PAGE_MASK;
+	result = kimage_add_entry(image, destination | IND_DESTINATION);
+	if (result == 0)
+		image->destination = destination;
+
+	return result;
+}
+
+
+static int kimage_add_page(struct kimage *image, unsigned long page)
+{
+	int result;
+
+	page &= PAGE_MASK;
+	result = kimage_add_entry(image, page | IND_SOURCE);
+	if (result == 0)
+		image->destination += PAGE_SIZE;
+
+	return result;
+}
+
+
+static void kimage_free_extra_pages(struct kimage *image)
+{
+	/* Walk through and free any extra destination pages I may have */
+	kimage_free_page_list(&image->dest_pages);
+
+	/* Walk through and free any unuseable pages I have cached */
+	kimage_free_page_list(&image->unuseable_pages);
+
+}
+static int kimage_terminate(struct kimage *image)
+{
+	if (*image->entry != 0)
+		image->entry++;
+
+	*image->entry = IND_DONE;
+
+	return 0;
+}
+
+#define for_each_kimage_entry(image, ptr, entry) \
+	for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \
+		ptr = (entry & IND_INDIRECTION)? \
+			phys_to_virt((entry & PAGE_MASK)): ptr +1)
+
+static void kimage_free_entry(kimage_entry_t entry)
+{
+	struct page *page;
+
+	page = pfn_to_page(entry >> PAGE_SHIFT);
+	kimage_free_pages(page);
+}
+
+static void kimage_free(struct kimage *image)
+{
+	kimage_entry_t *ptr, entry;
+	kimage_entry_t ind = 0;
+
+	if (!image)
+		return;
+
+	kimage_free_extra_pages(image);
+	for_each_kimage_entry(image, ptr, entry) {
+		if (entry & IND_INDIRECTION) {
+			/* Free the previous indirection page */
+			if (ind & IND_INDIRECTION)
+				kimage_free_entry(ind);
+			/* Save this indirection page until we are
+			 * done with it.
+			 */
+			ind = entry;
+		}
+		else if (entry & IND_SOURCE)
+			kimage_free_entry(entry);
+	}
+	/* Free the final indirection page */
+	if (ind & IND_INDIRECTION)
+		kimage_free_entry(ind);
+
+	/* Handle any machine specific cleanup */
+	machine_kexec_cleanup(image);
+
+	/* Free the kexec control pages... */
+	kimage_free_page_list(&image->control_pages);
+	kfree(image);
+}
+
+static kimage_entry_t *kimage_dst_used(struct kimage *image,
+					unsigned long page)
+{
+	kimage_entry_t *ptr, entry;
+	unsigned long destination = 0;
+
+	for_each_kimage_entry(image, ptr, entry) {
+		if (entry & IND_DESTINATION)
+			destination = entry & PAGE_MASK;
+		else if (entry & IND_SOURCE) {
+			if (page == destination)
+				return ptr;
+			destination += PAGE_SIZE;
+		}
+	}
+
+	return 0;
+}
+
+static struct page *kimage_alloc_page(struct kimage *image,
+					unsigned int gfp_mask,
+					unsigned long destination)
+{
+	/*
+	 * Here we implement safeguards to ensure that a source page
+	 * is not copied to its destination page before the data on
+	 * the destination page is no longer useful.
+	 *
+	 * To do this we maintain the invariant that a source page is
+	 * either its own destination page, or it is not a
+	 * destination page at all.
+	 *
+	 * That is slightly stronger than required, but the proof
+	 * that no problems will not occur is trivial, and the
+	 * implementation is simply to verify.
+	 *
+	 * When allocating all pages normally this algorithm will run
+	 * in O(N) time, but in the worst case it will run in O(N^2)
+	 * time.   If the runtime is a problem the data structures can
+	 * be fixed.
+	 */
+	struct page *page;
+	unsigned long addr;
+
+	/*
+	 * Walk through the list of destination pages, and see if I
+	 * have a match.
+	 */
+	list_for_each_entry(page, &image->dest_pages, lru) {
+		addr = page_to_pfn(page) << PAGE_SHIFT;
+		if (addr == destination) {
+			list_del(&page->lru);
+			return page;
+		}
+	}
+	page = NULL;
+	while (1) {
+		kimage_entry_t *old;
+
+		/* Allocate a page, if we run out of memory give up */
+		page = kimage_alloc_pages(gfp_mask, 0);
+		if (!page)
+			return 0;
+		/* If the page cannot be used file it away */
+		if (page_to_pfn(page) >
+				(KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) {
+			list_add(&page->lru, &image->unuseable_pages);
+			continue;
+		}
+		addr = page_to_pfn(page) << PAGE_SHIFT;
+
+		/* If it is the destination page we want use it */
+		if (addr == destination)
+			break;
+
+		/* If the page is not a destination page use it */
+		if (!kimage_is_destination_range(image, addr,
+						  addr + PAGE_SIZE))
+			break;
+
+		/*
+		 * I know that the page is someones destination page.
+		 * See if there is already a source page for this
+		 * destination page.  And if so swap the source pages.
+		 */
+		old = kimage_dst_used(image, addr);
+		if (old) {
+			/* If so move it */
+			unsigned long old_addr;
+			struct page *old_page;
+
+			old_addr = *old & PAGE_MASK;
+			old_page = pfn_to_page(old_addr >> PAGE_SHIFT);
+			copy_highpage(page, old_page);
+			*old = addr | (*old & ~PAGE_MASK);
+
+			/* The old page I have found cannot be a
+			 * destination page, so return it.
+			 */
+			addr = old_addr;
+			page = old_page;
+			break;
+		}
+		else {
+			/* Place the page on the destination list I
+			 * will use it later.
+			 */
+			list_add(&page->lru, &image->dest_pages);
+		}
+	}
+
+	return page;
+}
+
+static int kimage_load_normal_segment(struct kimage *image,
+					 struct kexec_segment *segment)
+{
+	unsigned long maddr;
+	unsigned long ubytes, mbytes;
+	int result;
+	unsigned char *buf;
+
+	result = 0;
+	buf = segment->buf;
+	ubytes = segment->bufsz;
+	mbytes = segment->memsz;
+	maddr = segment->mem;
+
+	result = kimage_set_destination(image, maddr);
+	if (result < 0)
+		goto out;
+
+	while (mbytes) {
+		struct page *page;
+		char *ptr;
+		size_t uchunk, mchunk;
+
+		page = kimage_alloc_page(image, GFP_HIGHUSER, maddr);
+		if (page == 0) {
+			result  = -ENOMEM;
+			goto out;
+		}
+		result = kimage_add_page(image, page_to_pfn(page)
+								<< PAGE_SHIFT);
+		if (result < 0)
+			goto out;
+
+		ptr = kmap(page);
+		/* Start with a clear page */
+		memset(ptr, 0, PAGE_SIZE);
+		ptr += maddr & ~PAGE_MASK;
+		mchunk = PAGE_SIZE - (maddr & ~PAGE_MASK);
+		if (mchunk > mbytes)
+			mchunk = mbytes;
+
+		uchunk = mchunk;
+		if (uchunk > ubytes)
+			uchunk = ubytes;
+
+		result = copy_from_user(ptr, buf, uchunk);
+		kunmap(page);
+		if (result) {
+			result = (result < 0) ? result : -EIO;
+			goto out;
+		}
+		ubytes -= uchunk;
+		maddr  += mchunk;
+		buf    += mchunk;
+		mbytes -= mchunk;
+	}
+out:
+	return result;
+}
+
+static int kimage_load_crash_segment(struct kimage *image,
+					struct kexec_segment *segment)
+{
+	/* For crash dumps kernels we simply copy the data from
+	 * user space to it's destination.
+	 * We do things a page at a time for the sake of kmap.
+	 */
+	unsigned long maddr;
+	unsigned long ubytes, mbytes;
+	int result;
+	unsigned char *buf;
+
+	result = 0;
+	buf = segment->buf;
+	ubytes = segment->bufsz;
+	mbytes = segment->memsz;
+	maddr = segment->mem;
+	while (mbytes) {
+		struct page *page;
+		char *ptr;
+		size_t uchunk, mchunk;
+
+		page = pfn_to_page(maddr >> PAGE_SHIFT);
+		if (page == 0) {
+			result  = -ENOMEM;
+			goto out;
+		}
+		ptr = kmap(page);
+		ptr += maddr & ~PAGE_MASK;
+		mchunk = PAGE_SIZE - (maddr & ~PAGE_MASK);
+		if (mchunk > mbytes)
+			mchunk = mbytes;
+
+		uchunk = mchunk;
+		if (uchunk > ubytes) {
+			uchunk = ubytes;
+			/* Zero the trailing part of the page */
+			memset(ptr + uchunk, 0, mchunk - uchunk);
+		}
+		result = copy_from_user(ptr, buf, uchunk);
+		kunmap(page);
+		if (result) {
+			result = (result < 0) ? result : -EIO;
+			goto out;
+		}
+		ubytes -= uchunk;
+		maddr  += mchunk;
+		buf    += mchunk;
+		mbytes -= mchunk;
+	}
+out:
+	return result;
+}
+
+static int kimage_load_segment(struct kimage *image,
+				struct kexec_segment *segment)
+{
+	int result = -ENOMEM;
+
+	switch (image->type) {
+	case KEXEC_TYPE_DEFAULT:
+		result = kimage_load_normal_segment(image, segment);
+		break;
+	case KEXEC_TYPE_CRASH:
+		result = kimage_load_crash_segment(image, segment);
+		break;
+	}
+
+	return result;
+}
+
+/*
+ * Exec Kernel system call: for obvious reasons only root may call it.
+ *
+ * This call breaks up into three pieces.
+ * - A generic part which loads the new kernel from the current
+ *   address space, and very carefully places the data in the
+ *   allocated pages.
+ *
+ * - A generic part that interacts with the kernel and tells all of
+ *   the devices to shut down.  Preventing on-going dmas, and placing
+ *   the devices in a consistent state so a later kernel can
+ *   reinitialize them.
+ *
+ * - A machine specific part that includes the syscall number
+ *   and the copies the image to it's final destination.  And
+ *   jumps into the image at entry.
+ *
+ * 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;
+/*
+ * A home grown binary mutex.
+ * Nothing can wait so this mutex is safe to use
+ * in interrupt context :)
+ */
+static int kexec_lock = 0;
+
+asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments,
+				struct kexec_segment __user *segments,
+				unsigned long flags)
+{
+	struct kimage **dest_image, *image;
+	int locked;
+	int result;
+
+	/* We only trust the superuser with rebooting the system. */
+	if (!capable(CAP_SYS_BOOT))
+		return -EPERM;
+
+	/*
+	 * Verify we have a legal set of flags
+	 * This leaves us room for future extensions.
+	 */
+	if ((flags & KEXEC_FLAGS) != (flags & ~KEXEC_ARCH_MASK))
+		return -EINVAL;
+
+	/* Verify we are on the appropriate architecture */
+	if (((flags & KEXEC_ARCH_MASK) != KEXEC_ARCH) &&
+		((flags & KEXEC_ARCH_MASK) != KEXEC_ARCH_DEFAULT))
+		return -EINVAL;
+
+	/* Put an artificial cap on the number
+	 * of segments passed to kexec_load.
+	 */
+	if (nr_segments > KEXEC_SEGMENT_MAX)
+		return -EINVAL;
+
+	image = NULL;
+	result = 0;
+
+	/* Because we write directly to the reserved memory
+	 * region when loading crash kernels we need a mutex here to
+	 * prevent multiple crash  kernels from attempting to load
+	 * simultaneously, and to prevent a crash kernel from loading
+	 * over the top of a in use crash kernel.
+	 *
+	 * KISS: always take the mutex.
+	 */
+	locked = xchg(&kexec_lock, 1);
+	if (locked)
+		return -EBUSY;
+
+	dest_image = &kexec_image;
+	if (flags & KEXEC_ON_CRASH)
+		dest_image = &kexec_crash_image;
+	if (nr_segments > 0) {
+		unsigned long i;
+
+		/* Loading another kernel to reboot into */
+		if ((flags & KEXEC_ON_CRASH) == 0)
+			result = kimage_normal_alloc(&image, entry,
+							nr_segments, segments);
+		/* Loading another kernel to switch to if this one crashes */
+		else if (flags & KEXEC_ON_CRASH) {
+			/* Free any current crash dump kernel before
+			 * we corrupt it.
+			 */
+			kimage_free(xchg(&kexec_crash_image, NULL));
+			result = kimage_crash_alloc(&image, entry,
+						     nr_segments, segments);
+		}
+		if (result)
+			goto out;
+
+		result = machine_kexec_prepare(image);
+		if (result)
+			goto out;
+
+		for (i = 0; i < nr_segments; i++) {
+			result = kimage_load_segment(image, &image->segment[i]);
+			if (result)
+				goto out;
+		}
+		result = kimage_terminate(image);
+		if (result)
+			goto out;
+	}
+	/* Install the new kernel, and  Uninstall the old */
+	image = xchg(dest_image, image);
+
+out:
+	xchg(&kexec_lock, 0); /* Release the mutex */
+	kimage_free(image);
+
+	return result;
+}
+
+#ifdef CONFIG_COMPAT
+asmlinkage long compat_sys_kexec_load(unsigned long entry,
+				unsigned long nr_segments,
+				struct compat_kexec_segment __user *segments,
+				unsigned long flags)
+{
+	struct compat_kexec_segment in;
+	struct kexec_segment out, __user *ksegments;
+	unsigned long i, result;
+
+	/* Don't allow clients that don't understand the native
+	 * architecture to do anything.
+	 */
+	if ((flags & KEXEC_ARCH_MASK) == KEXEC_ARCH_DEFAULT)
+		return -EINVAL;
+
+	if (nr_segments > KEXEC_SEGMENT_MAX)
+		return -EINVAL;
+
+	ksegments = compat_alloc_user_space(nr_segments * sizeof(out));
+	for (i=0; i < nr_segments; i++) {
+		result = copy_from_user(&in, &segments[i], sizeof(in));
+		if (result)
+			return -EFAULT;
+
+		out.buf   = compat_ptr(in.buf);
+		out.bufsz = in.bufsz;
+		out.mem   = in.mem;
+		out.memsz = in.memsz;
+
+		result = copy_to_user(&ksegments[i], &out, sizeof(out));
+		if (result)
+			return -EFAULT;
+	}
+
+	return sys_kexec_load(entry, nr_segments, ksegments, flags);
+}
+#endif
+
+void crash_kexec(struct pt_regs *regs)
+{
+	struct kimage *image;
+	int locked;
+
+
+	/* Take the kexec_lock here to prevent sys_kexec_load
+	 * running on one cpu from replacing the crash kernel
+	 * we are using after a panic on a different cpu.
+	 *
+	 * If the crash kernel was not located in a fixed area
+	 * of memory the xchg(&kexec_crash_image) would be
+	 * sufficient.  But since I reuse the memory...
+	 */
+	locked = xchg(&kexec_lock, 1);
+	if (!locked) {
+		image = xchg(&kexec_crash_image, NULL);
+		if (image) {
+			machine_crash_shutdown(regs);
+			machine_kexec(image);
+		}
+		xchg(&kexec_lock, 0);
+	}
+}
diff --git a/kernel/kmod.c b/kernel/kmod.c
index eed53d4..44166e3 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -120,6 +120,7 @@
 	char *path;
 	char **argv;
 	char **envp;
+	struct key *ring;
 	int wait;
 	int retval;
 };
@@ -130,16 +131,21 @@
 static int ____call_usermodehelper(void *data)
 {
 	struct subprocess_info *sub_info = data;
+	struct key *old_session;
 	int retval;
 
-	/* Unblock all signals. */
+	/* Unblock all signals and set the session keyring. */
+	key_get(sub_info->ring);
 	flush_signals(current);
 	spin_lock_irq(&current->sighand->siglock);
+	old_session = __install_session_keyring(current, sub_info->ring);
 	flush_signal_handlers(current, 1);
 	sigemptyset(&current->blocked);
 	recalc_sigpending();
 	spin_unlock_irq(&current->sighand->siglock);
 
+	key_put(old_session);
+
 	/* We can run anywhere, unlike our parent keventd(). */
 	set_cpus_allowed(current, CPU_MASK_ALL);
 
@@ -211,10 +217,11 @@
 }
 
 /**
- * call_usermodehelper - start a usermode application
+ * call_usermodehelper_keys - start a usermode application
  * @path: pathname for the application
  * @argv: null-terminated argument list
  * @envp: null-terminated environment list
+ * @session_keyring: session keyring for process (NULL for an empty keyring)
  * @wait: wait for the application to finish and return status.
  *
  * Runs a user-space application.  The application is started
@@ -224,7 +231,8 @@
  * Must be called from process context.  Returns a negative error code
  * if program was not execed successfully, or 0.
  */
-int call_usermodehelper(char *path, char **argv, char **envp, int wait)
+int call_usermodehelper_keys(char *path, char **argv, char **envp,
+			     struct key *session_keyring, int wait)
 {
 	DECLARE_COMPLETION(done);
 	struct subprocess_info sub_info = {
@@ -232,6 +240,7 @@
 		.path		= path,
 		.argv		= argv,
 		.envp		= envp,
+		.ring		= session_keyring,
 		.wait		= wait,
 		.retval		= 0,
 	};
@@ -247,7 +256,7 @@
 	wait_for_completion(&done);
 	return sub_info.retval;
 }
-EXPORT_SYMBOL(call_usermodehelper);
+EXPORT_SYMBOL(call_usermodehelper_keys);
 
 void __init usermodehelper_init(void)
 {
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 037142b7..334f374 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -27,6 +27,9 @@
  *		interface to access function arguments.
  * 2004-Sep	Prasanna S Panchamukhi <prasanna@in.ibm.com> Changed Kprobes
  *		exceptions notifier to be first on the priority list.
+ * 2005-May	Hien Nguyen <hien@us.ibm.com>, Jim Keniston
+ *		<jkenisto@us.ibm.com> and Prasanna S Panchamukhi
+ *		<prasanna@in.ibm.com> added function-return probes.
  */
 #include <linux/kprobes.h>
 #include <linux/spinlock.h>
@@ -41,6 +44,7 @@
 #define KPROBE_TABLE_SIZE (1 << KPROBE_HASH_BITS)
 
 static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
+static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
 
 unsigned int kprobe_cpu = NR_CPUS;
 static DEFINE_SPINLOCK(kprobe_lock);
@@ -78,22 +82,23 @@
  * Aggregate handlers for multiple kprobes support - these handlers
  * take care of invoking the individual kprobe handlers on p->list
  */
-int aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)
+static int aggr_pre_handler(struct kprobe *p, struct pt_regs *regs)
 {
 	struct kprobe *kp;
 
 	list_for_each_entry(kp, &p->list, list) {
 		if (kp->pre_handler) {
 			curr_kprobe = kp;
-			kp->pre_handler(kp, regs);
-			curr_kprobe = NULL;
+			if (kp->pre_handler(kp, regs))
+				return 1;
 		}
+		curr_kprobe = NULL;
 	}
 	return 0;
 }
 
-void aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
-		unsigned long flags)
+static void aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
+			      unsigned long flags)
 {
 	struct kprobe *kp;
 
@@ -107,7 +112,8 @@
 	return;
 }
 
-int aggr_fault_handler(struct kprobe *p, struct pt_regs *regs, int trapnr)
+static int aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
+			      int trapnr)
 {
 	/*
 	 * if we faulted "during" the execution of a user specified
@@ -120,19 +126,191 @@
 	return 0;
 }
 
+static int aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	struct kprobe *kp = curr_kprobe;
+	if (curr_kprobe && kp->break_handler) {
+		if (kp->break_handler(kp, regs)) {
+			curr_kprobe = NULL;
+			return 1;
+		}
+	}
+	curr_kprobe = NULL;
+	return 0;
+}
+
+struct kprobe trampoline_p = {
+		.addr = (kprobe_opcode_t *) &kretprobe_trampoline,
+		.pre_handler = trampoline_probe_handler,
+		.post_handler = trampoline_post_handler
+};
+
+struct kretprobe_instance *get_free_rp_inst(struct kretprobe *rp)
+{
+	struct hlist_node *node;
+	struct kretprobe_instance *ri;
+	hlist_for_each_entry(ri, node, &rp->free_instances, uflist)
+		return ri;
+	return NULL;
+}
+
+static struct kretprobe_instance *get_used_rp_inst(struct kretprobe *rp)
+{
+	struct hlist_node *node;
+	struct kretprobe_instance *ri;
+	hlist_for_each_entry(ri, node, &rp->used_instances, uflist)
+		return ri;
+	return NULL;
+}
+
+struct kretprobe_instance *get_rp_inst(void *sara)
+{
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct task_struct *tsk;
+	struct kretprobe_instance *ri;
+
+	tsk = arch_get_kprobe_task(sara);
+	head = &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)];
+	hlist_for_each_entry(ri, node, head, hlist) {
+		if (ri->stack_addr == sara)
+			return ri;
+	}
+	return NULL;
+}
+
+void add_rp_inst(struct kretprobe_instance *ri)
+{
+	struct task_struct *tsk;
+	/*
+	 * Remove rp inst off the free list -
+	 * Add it back when probed function returns
+	 */
+	hlist_del(&ri->uflist);
+	tsk = arch_get_kprobe_task(ri->stack_addr);
+	/* Add rp inst onto table */
+	INIT_HLIST_NODE(&ri->hlist);
+	hlist_add_head(&ri->hlist,
+			&kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)]);
+
+	/* Also add this rp inst to the used list. */
+	INIT_HLIST_NODE(&ri->uflist);
+	hlist_add_head(&ri->uflist, &ri->rp->used_instances);
+}
+
+void recycle_rp_inst(struct kretprobe_instance *ri)
+{
+	/* remove rp inst off the rprobe_inst_table */
+	hlist_del(&ri->hlist);
+	if (ri->rp) {
+		/* remove rp inst off the used list */
+		hlist_del(&ri->uflist);
+		/* put rp inst back onto the free list */
+		INIT_HLIST_NODE(&ri->uflist);
+		hlist_add_head(&ri->uflist, &ri->rp->free_instances);
+	} else
+		/* Unregistering */
+		kfree(ri);
+}
+
+struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk)
+{
+	return &kretprobe_inst_table[hash_ptr(tsk, KPROBE_HASH_BITS)];
+}
+
+struct kretprobe_instance *get_rp_inst_tsk(struct task_struct *tk)
+{
+	struct task_struct *tsk;
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct kretprobe_instance *ri;
+
+	head = &kretprobe_inst_table[hash_ptr(tk, KPROBE_HASH_BITS)];
+
+	hlist_for_each_entry(ri, node, head, hlist) {
+		tsk = arch_get_kprobe_task(ri->stack_addr);
+		if (tsk == tk)
+			return ri;
+	}
+	return NULL;
+}
+
+/*
+ * This function is called from do_exit or do_execv when task tk's stack is
+ * about to be recycled. Recycle any function-return probe instances
+ * associated with this task. These represent probed functions that have
+ * been called but may never return.
+ */
+void kprobe_flush_task(struct task_struct *tk)
+{
+	unsigned long flags = 0;
+	spin_lock_irqsave(&kprobe_lock, flags);
+	arch_kprobe_flush_task(tk);
+	spin_unlock_irqrestore(&kprobe_lock, flags);
+}
+
+/*
+ * This kprobe pre_handler is registered with every kretprobe. When probe
+ * hits it will set up the return probe.
+ */
+static int pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs)
+{
+	struct kretprobe *rp = container_of(p, struct kretprobe, kp);
+
+	/*TODO: consider to only swap the RA after the last pre_handler fired */
+	arch_prepare_kretprobe(rp, regs);
+	return 0;
+}
+
+static inline void free_rp_inst(struct kretprobe *rp)
+{
+	struct kretprobe_instance *ri;
+	while ((ri = get_free_rp_inst(rp)) != NULL) {
+		hlist_del(&ri->uflist);
+		kfree(ri);
+	}
+}
+
+/*
+ * Keep all fields in the kprobe consistent
+ */
+static inline void copy_kprobe(struct kprobe *old_p, struct kprobe *p)
+{
+	memcpy(&p->opcode, &old_p->opcode, sizeof(kprobe_opcode_t));
+	memcpy(&p->ainsn, &old_p->ainsn, sizeof(struct arch_specific_insn));
+}
+
+/*
+* Add the new probe to old_p->list. Fail if this is the
+* second jprobe at the address - two jprobes can't coexist
+*/
+static int add_new_kprobe(struct kprobe *old_p, struct kprobe *p)
+{
+        struct kprobe *kp;
+
+	if (p->break_handler) {
+		list_for_each_entry(kp, &old_p->list, list) {
+			if (kp->break_handler)
+				return -EEXIST;
+		}
+		list_add_tail(&p->list, &old_p->list);
+	} else
+		list_add(&p->list, &old_p->list);
+	return 0;
+}
+
 /*
  * Fill in the required fields of the "manager kprobe". Replace the
  * earlier kprobe in the hlist with the manager kprobe
  */
 static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p)
 {
+	copy_kprobe(p, ap);
 	ap->addr = p->addr;
-	ap->opcode = p->opcode;
-	memcpy(&ap->ainsn, &p->ainsn, sizeof(struct arch_specific_insn));
-
 	ap->pre_handler = aggr_pre_handler;
 	ap->post_handler = aggr_post_handler;
 	ap->fault_handler = aggr_fault_handler;
+	ap->break_handler = aggr_break_handler;
 
 	INIT_LIST_HEAD(&ap->list);
 	list_add(&p->list, &ap->list);
@@ -153,16 +331,16 @@
 	int ret = 0;
 	struct kprobe *ap;
 
-	if (old_p->break_handler || p->break_handler) {
-		ret = -EEXIST;	/* kprobe and jprobe can't (yet) coexist */
-	} else if (old_p->pre_handler == aggr_pre_handler) {
-		list_add(&p->list, &old_p->list);
+	if (old_p->pre_handler == aggr_pre_handler) {
+		copy_kprobe(old_p, p);
+		ret = add_new_kprobe(old_p, p);
 	} else {
 		ap = kcalloc(1, sizeof(struct kprobe), GFP_ATOMIC);
 		if (!ap)
 			return -ENOMEM;
 		add_aggr_kprobe(ap, old_p);
-		list_add(&p->list, &ap->list);
+		copy_kprobe(ap, p);
+		ret = add_new_kprobe(ap, p);
 	}
 	return ret;
 }
@@ -170,10 +348,8 @@
 /* kprobe removal house-keeping routines */
 static inline void cleanup_kprobe(struct kprobe *p, unsigned long flags)
 {
-	*p->addr = p->opcode;
+	arch_disarm_kprobe(p);
 	hlist_del(&p->hlist);
-	flush_icache_range((unsigned long) p->addr,
-		   (unsigned long) p->addr + sizeof(kprobe_opcode_t));
 	spin_unlock_irqrestore(&kprobe_lock, flags);
 	arch_remove_kprobe(p);
 }
@@ -200,6 +376,7 @@
 	}
 	spin_lock_irqsave(&kprobe_lock, flags);
 	old_p = get_kprobe(p->addr);
+	p->nmissed = 0;
 	if (old_p) {
 		ret = register_aggr_kprobe(old_p, p);
 		goto out;
@@ -210,10 +387,8 @@
 	hlist_add_head(&p->hlist,
 		       &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]);
 
-	p->opcode = *p->addr;
-	*p->addr = BREAKPOINT_INSTRUCTION;
-	flush_icache_range((unsigned long) p->addr,
-			   (unsigned long) p->addr + sizeof(kprobe_opcode_t));
+  	arch_arm_kprobe(p);
+
 out:
 	spin_unlock_irqrestore(&kprobe_lock, flags);
 rm_kprobe:
@@ -257,16 +432,82 @@
 	unregister_kprobe(&jp->kp);
 }
 
+#ifdef ARCH_SUPPORTS_KRETPROBES
+
+int register_kretprobe(struct kretprobe *rp)
+{
+	int ret = 0;
+	struct kretprobe_instance *inst;
+	int i;
+
+	rp->kp.pre_handler = pre_handler_kretprobe;
+
+	/* Pre-allocate memory for max kretprobe instances */
+	if (rp->maxactive <= 0) {
+#ifdef CONFIG_PREEMPT
+		rp->maxactive = max(10, 2 * NR_CPUS);
+#else
+		rp->maxactive = NR_CPUS;
+#endif
+	}
+	INIT_HLIST_HEAD(&rp->used_instances);
+	INIT_HLIST_HEAD(&rp->free_instances);
+	for (i = 0; i < rp->maxactive; i++) {
+		inst = kmalloc(sizeof(struct kretprobe_instance), GFP_KERNEL);
+		if (inst == NULL) {
+			free_rp_inst(rp);
+			return -ENOMEM;
+		}
+		INIT_HLIST_NODE(&inst->uflist);
+		hlist_add_head(&inst->uflist, &rp->free_instances);
+	}
+
+	rp->nmissed = 0;
+	/* Establish function entry probe point */
+	if ((ret = register_kprobe(&rp->kp)) != 0)
+		free_rp_inst(rp);
+	return ret;
+}
+
+#else /* ARCH_SUPPORTS_KRETPROBES */
+
+int register_kretprobe(struct kretprobe *rp)
+{
+	return -ENOSYS;
+}
+
+#endif /* ARCH_SUPPORTS_KRETPROBES */
+
+void unregister_kretprobe(struct kretprobe *rp)
+{
+	unsigned long flags;
+	struct kretprobe_instance *ri;
+
+	unregister_kprobe(&rp->kp);
+	/* No race here */
+	spin_lock_irqsave(&kprobe_lock, flags);
+	free_rp_inst(rp);
+	while ((ri = get_used_rp_inst(rp)) != NULL) {
+		ri->rp = NULL;
+		hlist_del(&ri->uflist);
+	}
+	spin_unlock_irqrestore(&kprobe_lock, flags);
+}
+
 static int __init init_kprobes(void)
 {
 	int i, err = 0;
 
 	/* FIXME allocate the probe table, currently defined statically */
 	/* initialize all list heads */
-	for (i = 0; i < KPROBE_TABLE_SIZE; i++)
+	for (i = 0; i < KPROBE_TABLE_SIZE; i++) {
 		INIT_HLIST_HEAD(&kprobe_table[i]);
+		INIT_HLIST_HEAD(&kretprobe_inst_table[i]);
+	}
 
 	err = register_die_notifier(&kprobe_exceptions_nb);
+	/* Register the trampoline probe for return probe */
+	register_kprobe(&trampoline_p);
 	return err;
 }
 
@@ -277,3 +518,6 @@
 EXPORT_SYMBOL_GPL(register_jprobe);
 EXPORT_SYMBOL_GPL(unregister_jprobe);
 EXPORT_SYMBOL_GPL(jprobe_return);
+EXPORT_SYMBOL_GPL(register_kretprobe);
+EXPORT_SYMBOL_GPL(unregister_kretprobe);
+
diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c
index 1f064a6..015fb69 100644
--- a/kernel/ksysfs.c
+++ b/kernel/ksysfs.c
@@ -30,6 +30,16 @@
 KERNEL_ATTR_RO(hotplug_seqnum);
 #endif
 
+#ifdef CONFIG_KEXEC
+#include <asm/kexec.h>
+
+static ssize_t crash_notes_show(struct subsystem *subsys, char *page)
+{
+	return sprintf(page, "%p\n", (void *)crash_notes);
+}
+KERNEL_ATTR_RO(crash_notes);
+#endif
+
 decl_subsys(kernel, NULL, NULL);
 EXPORT_SYMBOL_GPL(kernel_subsys);
 
@@ -37,6 +47,9 @@
 #ifdef CONFIG_HOTPLUG
 	&hotplug_seqnum_attr.attr,
 #endif
+#ifdef CONFIG_KEXEC
+	&crash_notes_attr.attr,
+#endif
 	NULL
 };
 
diff --git a/kernel/module.c b/kernel/module.c
index 83b3d37..068e271 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -35,6 +35,7 @@
 #include <linux/notifier.h>
 #include <linux/stop_machine.h>
 #include <linux/device.h>
+#include <linux/string.h>
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
 #include <asm/cacheflush.h>
@@ -370,6 +371,43 @@
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_MODULE_UNLOAD
+#define MODINFO_ATTR(field)	\
+static void setup_modinfo_##field(struct module *mod, const char *s)  \
+{                                                                     \
+	mod->field = kstrdup(s, GFP_KERNEL);                          \
+}                                                                     \
+static ssize_t show_modinfo_##field(struct module_attribute *mattr,   \
+	                struct module *mod, char *buffer)             \
+{                                                                     \
+	return sprintf(buffer, "%s\n", mod->field);                   \
+}                                                                     \
+static int modinfo_##field##_exists(struct module *mod)               \
+{                                                                     \
+	return mod->field != NULL;                                    \
+}                                                                     \
+static void free_modinfo_##field(struct module *mod)                  \
+{                                                                     \
+        kfree(mod->field);                                            \
+        mod->field = NULL;                                            \
+}                                                                     \
+static struct module_attribute modinfo_##field = {                    \
+	.attr = { .name = __stringify(field), .mode = 0444,           \
+		  .owner = THIS_MODULE },                             \
+	.show = show_modinfo_##field,                                 \
+	.setup = setup_modinfo_##field,                               \
+	.test = modinfo_##field##_exists,                             \
+	.free = free_modinfo_##field,                                 \
+};
+
+MODINFO_ATTR(version);
+MODINFO_ATTR(srcversion);
+
+static struct module_attribute *modinfo_attrs[] = {
+	&modinfo_version,
+	&modinfo_srcversion,
+	NULL,
+};
+
 /* Init the unload section of the module. */
 static void module_unload_init(struct module *mod)
 {
@@ -379,7 +417,7 @@
 	for (i = 0; i < NR_CPUS; i++)
 		local_set(&mod->ref[i].count, 0);
 	/* Hold reference count during initialization. */
-	local_set(&mod->ref[_smp_processor_id()].count, 1);
+	local_set(&mod->ref[raw_smp_processor_id()].count, 1);
 	/* Backwards compatibility macros put refcount during init. */
 	mod->waiter = current;
 }
@@ -692,7 +730,7 @@
 	return 0;
 }
 
-int set_obsolete(const char *val, struct kernel_param *kp)
+static int set_obsolete(const char *val, struct kernel_param *kp)
 {
 	unsigned int min, max;
 	unsigned int size, maxsize;
@@ -1031,6 +1069,32 @@
 }
 #endif
 
+#ifdef CONFIG_MODULE_UNLOAD
+static int module_add_modinfo_attrs(struct module *mod)
+{
+	struct module_attribute *attr;
+	int error = 0;
+	int i;
+
+	for (i = 0; (attr = modinfo_attrs[i]) && !error; i++) {
+		if (!attr->test ||
+		    (attr->test && attr->test(mod)))
+			error = sysfs_create_file(&mod->mkobj.kobj,&attr->attr);
+	}
+	return error;
+}
+
+static void module_remove_modinfo_attrs(struct module *mod)
+{
+	struct module_attribute *attr;
+	int i;
+
+	for (i = 0; (attr = modinfo_attrs[i]); i++) {
+		sysfs_remove_file(&mod->mkobj.kobj,&attr->attr);
+		attr->free(mod);
+	}
+}
+#endif
 
 static int mod_sysfs_setup(struct module *mod,
 			   struct kernel_param *kparam,
@@ -1056,6 +1120,12 @@
 	if (err)
 		goto out_unreg;
 
+#ifdef CONFIG_MODULE_UNLOAD
+	err = module_add_modinfo_attrs(mod);
+	if (err)
+		goto out_unreg;
+#endif
+
 	return 0;
 
 out_unreg:
@@ -1066,6 +1136,9 @@
 
 static void mod_kobject_remove(struct module *mod)
 {
+#ifdef CONFIG_MODULE_UNLOAD
+	module_remove_modinfo_attrs(mod);
+#endif
 	module_remove_refcnt_attr(mod);
 	module_param_sysfs_remove(mod);
 
@@ -1311,6 +1384,23 @@
 	return NULL;
 }
 
+#ifdef CONFIG_MODULE_UNLOAD
+static void setup_modinfo(struct module *mod, Elf_Shdr *sechdrs,
+			  unsigned int infoindex)
+{
+	struct module_attribute *attr;
+	int i;
+
+	for (i = 0; (attr = modinfo_attrs[i]); i++) {
+		if (attr->setup)
+			attr->setup(mod,
+				    get_modinfo(sechdrs,
+						infoindex,
+						attr->attr.name));
+	}
+}
+#endif
+
 #ifdef CONFIG_KALLSYMS
 int is_exported(const char *name, const struct module *mod)
 {
@@ -1615,6 +1705,11 @@
 	/* Set up license info based on the info section */
 	set_license(mod, get_modinfo(sechdrs, infoindex, "license"));
 
+#ifdef CONFIG_MODULE_UNLOAD
+	/* Set up MODINFO_ATTR fields */
+	setup_modinfo(mod, sechdrs, infoindex);
+#endif
+
 	/* Fix up syms, so that st_value is a pointer to location. */
 	err = simplify_symbols(sechdrs, symindex, strtab, versindex, pcpuindex,
 			       mod);
diff --git a/kernel/panic.c b/kernel/panic.c
index 081f746..74ba5f3 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -18,6 +18,7 @@
 #include <linux/sysrq.h>
 #include <linux/interrupt.h>
 #include <linux/nmi.h>
+#include <linux/kexec.h>
 
 int panic_timeout;
 int panic_on_oops;
@@ -63,6 +64,13 @@
         unsigned long caller = (unsigned long) __builtin_return_address(0);
 #endif
 
+	/*
+	 * It's possible to come here directly from a panic-assertion and not
+	 * have preempt disabled. Some functions called from here want
+	 * preempt to be disabled. No point enabling it later though...
+	 */
+	preempt_disable();
+
 	bust_spinlocks(1);
 	va_start(args, fmt);
 	vsnprintf(buf, sizeof(buf), fmt, args);
@@ -70,7 +78,19 @@
 	printk(KERN_EMERG "Kernel panic - not syncing: %s\n",buf);
 	bust_spinlocks(0);
 
+	/*
+	 * If we have crashed and we have a crash kernel loaded let it handle
+	 * everything else.
+	 * Do we want to call this before we try to display a message?
+	 */
+	crash_kexec(NULL);
+
 #ifdef CONFIG_SMP
+	/*
+	 * Note smp_send_stop is the usual smp shutdown function, which
+	 * unfortunately means it may not be hardened to work in a panic
+	 * situation.
+	 */
 	smp_send_stop();
 #endif
 
@@ -79,8 +99,7 @@
 	if (!panic_blink)
 		panic_blink = no_blink;
 
-	if (panic_timeout > 0)
-	{
+	if (panic_timeout > 0) {
 		/*
 	 	 * Delay timeout seconds before rebooting the machine. 
 		 * We can't use the "normal" timers since we just panicked..
diff --git a/kernel/params.c b/kernel/params.c
index 5513844..d586c35 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -629,7 +629,7 @@
 	mk = to_module_kobject(kobj);
 
 	if (!attribute->show)
-		return -EPERM;
+		return -EIO;
 
 	if (!try_module_get(mk->mod))
 		return -ENODEV;
@@ -653,7 +653,7 @@
 	mk = to_module_kobject(kobj);
 
 	if (!attribute->store)
-		return -EPERM;
+		return -EIO;
 
 	if (!try_module_get(mk->mod))
 		return -ENODEV;
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c
index fd316c2..5b7b473 100644
--- a/kernel/posix-timers.c
+++ b/kernel/posix-timers.c
@@ -89,23 +89,6 @@
 static DEFINE_SPINLOCK(idr_lock);
 
 /*
- * Just because the timer is not in the timer list does NOT mean it is
- * inactive.  It could be in the "fire" routine getting a new expire time.
- */
-#define TIMER_INACTIVE 1
-
-#ifdef CONFIG_SMP
-# define timer_active(tmr) \
-		((tmr)->it.real.timer.entry.prev != (void *)TIMER_INACTIVE)
-# define set_timer_inactive(tmr) \
-		do { \
-			(tmr)->it.real.timer.entry.prev = (void *)TIMER_INACTIVE; \
-		} while (0)
-#else
-# define timer_active(tmr) BARFY	// error to use outside of SMP
-# define set_timer_inactive(tmr) do { } while (0)
-#endif
-/*
  * we assume that the new SIGEV_THREAD_ID shares no bits with the other
  * SIGEV values.  Here we put out an error if this assumption fails.
  */
@@ -226,7 +209,6 @@
 	init_timer(&new_timer->it.real.timer);
 	new_timer->it.real.timer.data = (unsigned long) new_timer;
 	new_timer->it.real.timer.function = posix_timer_fn;
-	set_timer_inactive(new_timer);
 	return 0;
 }
 
@@ -480,7 +462,6 @@
 	int do_notify = 1;
 
 	spin_lock_irqsave(&timr->it_lock, flags);
- 	set_timer_inactive(timr);
 	if (!list_empty(&timr->it.real.abs_timer_entry)) {
 		spin_lock(&abs_list.lock);
 		do {
@@ -983,8 +964,8 @@
 	 * careful here.  If smp we could be in the "fire" routine which will
 	 * be spinning as we hold the lock.  But this is ONLY an SMP issue.
 	 */
+	if (try_to_del_timer_sync(&timr->it.real.timer) < 0) {
 #ifdef CONFIG_SMP
-	if (timer_active(timr) && !del_timer(&timr->it.real.timer))
 		/*
 		 * It can only be active if on an other cpu.  Since
 		 * we have cleared the interval stuff above, it should
@@ -994,11 +975,9 @@
 		 * a "retry" exit status.
 		 */
 		return TIMER_RETRY;
-
-	set_timer_inactive(timr);
-#else
-	del_timer(&timr->it.real.timer);
 #endif
+	}
+
 	remove_from_abslist(timr);
 
 	timr->it_requeue_pending = (timr->it_requeue_pending + 2) & 
@@ -1083,8 +1062,9 @@
 static inline int common_timer_del(struct k_itimer *timer)
 {
 	timer->it.real.incr = 0;
+
+	if (try_to_del_timer_sync(&timer->it.real.timer) < 0) {
 #ifdef CONFIG_SMP
-	if (timer_active(timer) && !del_timer(&timer->it.real.timer))
 		/*
 		 * It can only be active if on an other cpu.  Since
 		 * we have cleared the interval stuff above, it should
@@ -1094,9 +1074,9 @@
 		 * a "retry" exit status.
 		 */
 		return TIMER_RETRY;
-#else
-	del_timer(&timer->it.real.timer);
 #endif
+	}
+
 	remove_from_abslist(timer);
 
 	return 0;
@@ -1197,6 +1177,7 @@
 		tmr = list_entry(sig->posix_timers.next, struct k_itimer, list);
 		itimer_delete(tmr);
 	}
+	del_timer_sync(&sig->real_timer);
 }
 
 /*
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 696387f..2c7121d 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -27,8 +27,8 @@
 	like suspend support.
 
 config SOFTWARE_SUSPEND
-	bool "Software Suspend (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && PM && SWAP
+	bool "Software Suspend"
+	depends on EXPERIMENTAL && PM && SWAP && ((X86 && SMP) || ((FVR || PPC32 || X86) && !SMP))
 	---help---
 	  Enable the possibility of suspending the machine.
 	  It doesn't need APM.
@@ -72,3 +72,7 @@
 	  suspended image to. It will simply pick the first available swap 
 	  device.
 
+config SUSPEND_SMP
+	bool
+	depends on HOTPLUG_CPU && X86 && PM
+	default y
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index fbdc634..2f438d0 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -3,9 +3,9 @@
 EXTRA_CFLAGS	+=	-DDEBUG
 endif
 
-swsusp-smp-$(CONFIG_SMP)	+= smp.o
-
 obj-y				:= main.o process.o console.o pm.o
-obj-$(CONFIG_SOFTWARE_SUSPEND)	+= swsusp.o $(swsusp-smp-y) disk.o
+obj-$(CONFIG_SOFTWARE_SUSPEND)	+= swsusp.o disk.o
+
+obj-$(CONFIG_SUSPEND_SMP)	+= smp.o
 
 obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index 02b6764..fb8de63 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -117,8 +117,8 @@
 {
 	device_resume();
 	platform_finish();
-	enable_nonboot_cpus();
 	thaw_processes();
+	enable_nonboot_cpus();
 	pm_restore_console();
 }
 
@@ -131,28 +131,35 @@
 
 	sys_sync();
 
+	disable_nonboot_cpus();
+
 	if (freeze_processes()) {
 		error = -EBUSY;
-		return error;
+		goto thaw;
 	}
 
 	if (pm_disk_mode == PM_DISK_PLATFORM) {
 		if (pm_ops && pm_ops->prepare) {
 			if ((error = pm_ops->prepare(PM_SUSPEND_DISK)))
-				return error;
+				goto thaw;
 		}
 	}
 
 	/* Free memory before shutting down devices. */
 	free_some_memory();
-
 	return 0;
+thaw:
+	thaw_processes();
+	enable_nonboot_cpus();
+	pm_restore_console();
+	return error;
 }
 
 static void unprepare_processes(void)
 {
-	enable_nonboot_cpus();
+	platform_finish();
 	thaw_processes();
+	enable_nonboot_cpus();
 	pm_restore_console();
 }
 
@@ -160,15 +167,9 @@
 {
 	int error;
 
-	disable_nonboot_cpus();
-	if ((error = device_suspend(PMSG_FREEZE))) {
+	if ((error = device_suspend(PMSG_FREEZE)))
 		printk("Some devices failed to suspend\n");
-		platform_finish();
-		enable_nonboot_cpus();
-		return error;
-	}
-
-	return 0;
+	return error;
 }
 
 /**
@@ -185,9 +186,9 @@
 	int error;
 
 	error = prepare_processes();
-	if (!error) {
-		error = prepare_devices();
-	}
+	if (error)
+		return error;
+	error = prepare_devices();
 
 	if (error) {
 		unprepare_processes();
@@ -250,7 +251,7 @@
 
 	if ((error = prepare_processes())) {
 		swsusp_close();
-		goto Cleanup;
+		goto Done;
 	}
 
 	pr_debug("PM: Reading swsusp image.\n");
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 4cdebc9..c94cb9e 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -55,6 +55,13 @@
 
 	pm_prepare_console();
 
+	disable_nonboot_cpus();
+
+	if (num_online_cpus() != 1) {
+		error = -EPERM;
+		goto Enable_cpu;
+	}
+
 	if (freeze_processes()) {
 		error = -EAGAIN;
 		goto Thaw;
@@ -75,6 +82,8 @@
 		pm_ops->finish(state);
  Thaw:
 	thaw_processes();
+ Enable_cpu:
+	enable_nonboot_cpus();
 	pm_restore_console();
 	return error;
 }
@@ -113,6 +122,7 @@
 	if (pm_ops && pm_ops->finish)
 		pm_ops->finish(state);
 	thaw_processes();
+	enable_nonboot_cpus();
 	pm_restore_console();
 }
 
@@ -150,12 +160,6 @@
 		goto Unlock;
 	}
 
-	/* Suspend is hard to get right on SMP. */
-	if (num_online_cpus() != 1) {
-		error = -EPERM;
-		goto Unlock;
-	}
-
 	pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]);
 	if ((error = suspend_prepare(state)))
 		goto Unlock;
diff --git a/kernel/power/process.c b/kernel/power/process.c
index 78d92dc..0a08664 100644
--- a/kernel/power/process.c
+++ b/kernel/power/process.c
@@ -32,7 +32,7 @@
 }
 
 /* Refrigerator is place where frozen processes are stored :-). */
-void refrigerator(unsigned long flag)
+void refrigerator(void)
 {
 	/* Hmm, should we be allowed to suspend when there are realtime
 	   processes around? */
@@ -41,14 +41,13 @@
 	current->state = TASK_UNINTERRUPTIBLE;
 	pr_debug("%s entered refrigerator\n", current->comm);
 	printk("=");
-	current->flags &= ~PF_FREEZE;
 
+	frozen_process(current);
 	spin_lock_irq(&current->sighand->siglock);
 	recalc_sigpending(); /* We sent fake signal, clean it up */
 	spin_unlock_irq(&current->sighand->siglock);
 
-	current->flags |= PF_FROZEN;
-	while (current->flags & PF_FROZEN)
+	while (frozen(current))
 		schedule();
 	pr_debug("%s left refrigerator\n", current->comm);
 	current->state = save;
@@ -57,10 +56,10 @@
 /* 0 = success, else # of processes that we failed to stop */
 int freeze_processes(void)
 {
-       int todo;
-       unsigned long start_time;
+	int todo;
+	unsigned long start_time;
 	struct task_struct *g, *p;
-	
+
 	printk( "Stopping tasks: " );
 	start_time = jiffies;
 	do {
@@ -70,14 +69,12 @@
 			unsigned long flags;
 			if (!freezeable(p))
 				continue;
-			if ((p->flags & PF_FROZEN) ||
+			if ((frozen(p)) ||
 			    (p->state == TASK_TRACED) ||
 			    (p->state == TASK_STOPPED))
 				continue;
 
-			/* FIXME: smp problem here: we may not access other process' flags
-			   without locking */
-			p->flags |= PF_FREEZE;
+			freeze(p);
 			spin_lock_irqsave(&p->sighand->siglock, flags);
 			signal_wake_up(p, 0);
 			spin_unlock_irqrestore(&p->sighand->siglock, flags);
@@ -91,7 +88,7 @@
 			return todo;
 		}
 	} while(todo);
-	
+
 	printk( "|\n" );
 	BUG_ON(in_atomic());
 	return 0;
@@ -106,10 +103,7 @@
 	do_each_thread(g, p) {
 		if (!freezeable(p))
 			continue;
-		if (p->flags & PF_FROZEN) {
-			p->flags &= ~PF_FROZEN;
-			wake_up_process(p);
-		} else
+		if (!thaw_process(p))
 			printk(KERN_INFO " Strange, %s not stopped\n", p->comm );
 	} while_each_thread(g, p);
 
diff --git a/kernel/power/smp.c b/kernel/power/smp.c
index cba3584b..bbe2307 100644
--- a/kernel/power/smp.c
+++ b/kernel/power/smp.c
@@ -13,73 +13,52 @@
 #include <linux/interrupt.h>
 #include <linux/suspend.h>
 #include <linux/module.h>
+#include <linux/cpu.h>
 #include <asm/atomic.h>
 #include <asm/tlbflush.h>
 
-static atomic_t cpu_counter, freeze;
-
-
-static void smp_pause(void * data)
-{
-	struct saved_context ctxt;
-	__save_processor_state(&ctxt);
-	printk("Sleeping in:\n");
-	dump_stack();
-	atomic_inc(&cpu_counter);
-	while (atomic_read(&freeze)) {
-		/* FIXME: restore takes place at random piece inside this.
-		   This should probably be written in assembly, and
-		   preserve general-purpose registers, too
-
-		   What about stack? We may need to move to new stack here.
-
-		   This should better be ran with interrupts disabled.
-		 */
-		cpu_relax();
-		barrier();
-	}
-	atomic_dec(&cpu_counter);
-	__restore_processor_state(&ctxt);
-}
-
-static cpumask_t oldmask;
+/* This is protected by pm_sem semaphore */
+static cpumask_t frozen_cpus;
 
 void disable_nonboot_cpus(void)
 {
-	oldmask = current->cpus_allowed;
-	set_cpus_allowed(current, cpumask_of_cpu(0));
-	printk("Freezing CPUs (at %d)", _smp_processor_id());
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(HZ);
-	printk("...");
-	BUG_ON(_smp_processor_id() != 0);
+	int cpu, error;
 
-	/* FIXME: for this to work, all the CPUs must be running
-	 * "idle" thread (or we deadlock). Is that guaranteed? */
-
-	atomic_set(&cpu_counter, 0);
-	atomic_set(&freeze, 1);
-	smp_call_function(smp_pause, NULL, 0, 0);
-	while (atomic_read(&cpu_counter) < (num_online_cpus() - 1)) {
-		cpu_relax();
-		barrier();
+	error = 0;
+	cpus_clear(frozen_cpus);
+	printk("Freezing cpus ...\n");
+	for_each_online_cpu(cpu) {
+		if (cpu == 0)
+			continue;
+		error = cpu_down(cpu);
+		if (!error) {
+			cpu_set(cpu, frozen_cpus);
+			printk("CPU%d is down\n", cpu);
+			continue;
+		}
+		printk("Error taking cpu %d down: %d\n", cpu, error);
 	}
-	printk("ok\n");
+	BUG_ON(smp_processor_id() != 0);
+	if (error)
+		panic("cpus not sleeping");
 }
 
 void enable_nonboot_cpus(void)
 {
-	printk("Restarting CPUs");
-	atomic_set(&freeze, 0);
-	while (atomic_read(&cpu_counter)) {
-		cpu_relax();
-		barrier();
+	int cpu, error;
+
+	printk("Thawing cpus ...\n");
+	for_each_cpu_mask(cpu, frozen_cpus) {
+		error = smp_prepare_cpu(cpu);
+		if (!error)
+			error = cpu_up(cpu);
+		if (!error) {
+			printk("CPU%d is up\n", cpu);
+			continue;
+		}
+		printk("Error taking cpu %d up: %d\n", cpu, error);
+		panic("Not enough cpus");
 	}
-	printk("...");
-	set_cpus_allowed(current, oldmask);
-	schedule();
-	printk("ok\n");
-
+	cpus_clear(frozen_cpus);
 }
 
-
diff --git a/kernel/power/swsusp.c b/kernel/power/swsusp.c
index 90b3b68..c285fc5 100644
--- a/kernel/power/swsusp.c
+++ b/kernel/power/swsusp.c
@@ -10,12 +10,12 @@
  * This file is released under the GPLv2.
  *
  * I'd like to thank the following people for their work:
- * 
+ *
  * Pavel Machek <pavel@ucw.cz>:
  * Modifications, defectiveness pointing, being with me at the very beginning,
  * suspend to swap space, stop all tasks. Port to 2.4.18-ac and 2.5.17.
  *
- * Steve Doddi <dirk@loth.demon.co.uk>: 
+ * Steve Doddi <dirk@loth.demon.co.uk>:
  * Support the possibility of hardware state restoring.
  *
  * Raph <grey.havens@earthling.net>:
@@ -81,14 +81,14 @@
 extern char resume_file[];
 
 /* Local variables that should not be affected by save */
-unsigned int nr_copy_pages __nosavedata = 0;
+static unsigned int nr_copy_pages __nosavedata = 0;
 
 /* Suspend pagedir is allocated before final copy, therefore it
-   must be freed after resume 
+   must be freed after resume
 
    Warning: this is evil. There are actually two pagedirs at time of
    resume. One is "pagedir_save", which is empty frame allocated at
-   time of suspend, that must be freed. Second is "pagedir_nosave", 
+   time of suspend, that must be freed. Second is "pagedir_nosave",
    allocated at time of resume, that travels through memory not to
    collide with anything.
 
@@ -132,7 +132,7 @@
 {
 	int error;
 
-	rw_swap_page_sync(READ, 
+	rw_swap_page_sync(READ,
 			  swp_entry(root_swap, 0),
 			  virt_to_page((unsigned long)&swsusp_header));
 	if (!memcmp("SWAP-SPACE",swsusp_header.sig, 10) ||
@@ -140,7 +140,7 @@
 		memcpy(swsusp_header.orig_sig,swsusp_header.sig, 10);
 		memcpy(swsusp_header.sig,SWSUSP_SIG, 10);
 		swsusp_header.swsusp_info = prev;
-		error = rw_swap_page_sync(WRITE, 
+		error = rw_swap_page_sync(WRITE,
 					  swp_entry(root_swap, 0),
 					  virt_to_page((unsigned long)
 						       &swsusp_header));
@@ -174,22 +174,22 @@
 static int swsusp_swap_check(void) /* This is called before saving image */
 {
 	int i, len;
-	
+
 	len=strlen(resume_file);
 	root_swap = 0xFFFF;
-	
+
 	swap_list_lock();
-	for(i=0; i<MAX_SWAPFILES; i++) {
+	for (i=0; i<MAX_SWAPFILES; i++) {
 		if (swap_info[i].flags == 0) {
 			swapfile_used[i]=SWAPFILE_UNUSED;
 		} else {
-			if(!len) {
+			if (!len) {
 	    			printk(KERN_WARNING "resume= option should be used to set suspend device" );
-				if(root_swap == 0xFFFF) {
+				if (root_swap == 0xFFFF) {
 					swapfile_used[i] = SWAPFILE_SUSPEND;
 					root_swap = i;
 				} else
-					swapfile_used[i] = SWAPFILE_IGNORED;				  
+					swapfile_used[i] = SWAPFILE_IGNORED;
 			} else {
 	  			/* we ignore all swap devices that are not the resume_file */
 				if (is_resume_device(&swap_info[i])) {
@@ -209,15 +209,15 @@
  * This is called after saving image so modification
  * will be lost after resume... and that's what we want.
  * we make the device unusable. A new call to
- * lock_swapdevices can unlock the devices. 
+ * lock_swapdevices can unlock the devices.
  */
 static void lock_swapdevices(void)
 {
 	int i;
 
 	swap_list_lock();
-	for(i = 0; i< MAX_SWAPFILES; i++)
-		if(swapfile_used[i] == SWAPFILE_IGNORED) {
+	for (i = 0; i< MAX_SWAPFILES; i++)
+		if (swapfile_used[i] == SWAPFILE_IGNORED) {
 			swap_info[i].flags ^= 0xFF;
 		}
 	swap_list_unlock();
@@ -229,7 +229,7 @@
  *	@loc:	Place to store the entry we used.
  *
  *	Allocate a new swap entry and 'sync' it. Note we discard -EIO
- *	errors. That is an artifact left over from swsusp. It did not 
+ *	errors. That is an artifact left over from swsusp. It did not
  *	check the return of rw_swap_page_sync() at all, since most pages
  *	written back to swap would return -EIO.
  *	This is a partial improvement, since we will at least return other
@@ -241,7 +241,7 @@
 	int error = 0;
 
 	entry = get_swap_page();
-	if (swp_offset(entry) && 
+	if (swp_offset(entry) &&
 	    swapfile_used[swp_type(entry)] == SWAPFILE_SUSPEND) {
 		error = rw_swap_page_sync(WRITE, entry,
 					  virt_to_page(addr));
@@ -257,7 +257,7 @@
 /**
  *	data_free - Free the swap entries used by the saved image.
  *
- *	Walk the list of used swap entries and free each one. 
+ *	Walk the list of used swap entries and free each one.
  *	This is only used for cleanup when suspend fails.
  */
 static void data_free(void)
@@ -290,7 +290,7 @@
 		mod = 1;
 
 	printk( "Writing data to swap (%d pages)...     ", nr_copy_pages );
-	for_each_pbe(p, pagedir_nosave) {
+	for_each_pbe (p, pagedir_nosave) {
 		if (!(i%mod))
 			printk( "\b\b\b\b%3d%%", i / mod );
 		if ((error = write_page(p->address, &(p->swap_address))))
@@ -335,7 +335,7 @@
 
 	dump_info();
 	error = write_page((unsigned long)&swsusp_info, &entry);
-	if (!error) { 
+	if (!error) {
 		printk( "S" );
 		error = mark_swapfiles(entry);
 		printk( "|\n" );
@@ -370,7 +370,7 @@
 	struct pbe * pbe;
 
 	printk( "Writing pagedir...");
-	for_each_pb_page(pbe, pagedir_nosave) {
+	for_each_pb_page (pbe, pagedir_nosave) {
 		if ((error = write_page((unsigned long)pbe, &swsusp_info.pagedir[n++])))
 			return error;
 	}
@@ -472,7 +472,7 @@
 	int res = 0;
 
 	pr_debug("swsusp: Saving Highmem\n");
-	for_each_zone(zone) {
+	for_each_zone (zone) {
 		if (is_highmem(zone))
 			res = save_highmem_zone(zone);
 		if (res)
@@ -547,7 +547,7 @@
 
 	nr_copy_pages = 0;
 
-	for_each_zone(zone) {
+	for_each_zone (zone) {
 		if (is_highmem(zone))
 			continue;
 		mark_free_pages(zone);
@@ -562,9 +562,9 @@
 	struct zone *zone;
 	unsigned long zone_pfn;
 	struct pbe * pbe = pagedir_nosave;
-	
+
 	pr_debug("copy_data_pages(): pages to copy: %d\n", nr_copy_pages);
-	for_each_zone(zone) {
+	for_each_zone (zone) {
 		if (is_highmem(zone))
 			continue;
 		mark_free_pages(zone);
@@ -702,7 +702,7 @@
 {
 	struct pbe * p;
 
-	for_each_pbe(p, pagedir_save) {
+	for_each_pbe (p, pagedir_save) {
 		if (p->address) {
 			ClearPageNosave(virt_to_page(p->address));
 			free_page(p->address);
@@ -719,7 +719,7 @@
 {
 	struct pbe * p;
 
-	for_each_pbe(p, pagedir_save) {
+	for_each_pbe (p, pagedir_save) {
 		p->address = get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
 		if (!p->address)
 			return -ENOMEM;
@@ -740,7 +740,7 @@
 /**
  *	enough_free_mem - Make sure we enough free memory to snapshot.
  *
- *	Returns TRUE or FALSE after checking the number of available 
+ *	Returns TRUE or FALSE after checking the number of available
  *	free pages.
  */
 
@@ -758,11 +758,11 @@
 /**
  *	enough_swap - Make sure we have enough swap to save the image.
  *
- *	Returns TRUE or FALSE after checking the total amount of swap 
+ *	Returns TRUE or FALSE after checking the total amount of swap
  *	space avaiable.
  *
  *	FIXME: si_swapinfo(&i) returns all swap devices information.
- *	We should only consider resume_device. 
+ *	We should only consider resume_device.
  */
 
 static int enough_swap(void)
@@ -781,18 +781,18 @@
 {
 	int error;
 
+	pagedir_nosave = NULL;
+	nr_copy_pages = calc_nr(nr_copy_pages);
+
 	pr_debug("suspend: (pages needed: %d + %d free: %d)\n",
 		 nr_copy_pages, PAGES_FOR_IO, nr_free_pages());
 
-	pagedir_nosave = NULL;
 	if (!enough_free_mem())
 		return -ENOMEM;
 
 	if (!enough_swap())
 		return -ENOSPC;
 
-	nr_copy_pages = calc_nr(nr_copy_pages);
-
 	if (!(pagedir_save = alloc_pagedir(nr_copy_pages))) {
 		printk(KERN_ERR "suspend: Allocating pagedir failed.\n");
 		return -ENOMEM;
@@ -827,8 +827,8 @@
 	error = swsusp_alloc();
 	if (error)
 		return error;
-	
-	/* During allocating of suspend pagedir, new cold pages may appear. 
+
+	/* During allocating of suspend pagedir, new cold pages may appear.
 	 * Kill them.
 	 */
 	drain_local_pages();
@@ -929,21 +929,6 @@
 	return error;
 }
 
-/* More restore stuff */
-
-/*
- * Returns true if given address/order collides with any orig_address 
- */
-static int does_collide_order(unsigned long addr, int order)
-{
-	int i;
-	
-	for (i=0; i < (1<<order); i++)
-		if (!PageNosaveFree(virt_to_page(addr + i * PAGE_SIZE)))
-			return 1;
-	return 0;
-}
-
 /**
  *	On resume, for storing the PBE list and the image,
  *	we can only use memory pages that do not conflict with the pages
@@ -973,7 +958,7 @@
 	unsigned long m;
 
 	m = get_zeroed_page(gfp_mask);
-	while (does_collide_order(m, 0)) {
+	while (!PageNosaveFree(virt_to_page(m))) {
 		eat_page((void *)m);
 		m = get_zeroed_page(gfp_mask);
 		if (!m)
@@ -1045,7 +1030,7 @@
 
 	/* Set page flags */
 
-	for_each_zone(zone) {
+	for_each_zone (zone) {
         	for (zone_pfn = 0; zone_pfn < zone->spanned_pages; ++zone_pfn)
                 	SetPageNosaveFree(pfn_to_page(zone_pfn +
 					zone->zone_start_pfn));
@@ -1061,7 +1046,7 @@
 	/* Relocate colliding pages */
 
 	for_each_pb_page (pbpage, pblist) {
-		if (does_collide_order((unsigned long)pbpage, 0)) {
+		if (!PageNosaveFree(virt_to_page((unsigned long)pbpage))) {
 			m = (void *)get_usable_page(GFP_ATOMIC | __GFP_COLD);
 			if (!m) {
 				error = -ENOMEM;
@@ -1193,8 +1178,10 @@
 		return "version";
 	if (strcmp(swsusp_info.uts.machine,system_utsname.machine))
 		return "machine";
+#if 0
 	if(swsusp_info.cpus != num_online_cpus())
 		return "number of cpus";
+#endif
 	return NULL;
 }
 
diff --git a/kernel/printk.c b/kernel/printk.c
index 01b58d7..5092397 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -588,8 +588,7 @@
 			log_level_unknown = 1;
 	}
 
-	if (!cpu_online(smp_processor_id()) &&
-	    system_state != SYSTEM_RUNNING) {
+	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
@@ -876,8 +875,10 @@
 			break;
 		console->flags |= CON_ENABLED;
 		console->index = console_cmdline[i].index;
-		if (i == preferred_console)
+		if (i == selected_console) {
 			console->flags |= CON_CONSDEV;
+			preferred_console = selected_console;
+		}
 		break;
 	}
 
@@ -897,6 +898,8 @@
 	if ((console->flags & CON_CONSDEV) || console_drivers == NULL) {
 		console->next = console_drivers;
 		console_drivers = console;
+		if (console->next)
+			console->next->flags &= ~CON_CONSDEV;
 	} else {
 		console->next = console_drivers->next;
 		console_drivers->next = console;
@@ -937,10 +940,14 @@
 	/* If last console is removed, we re-enable picking the first
 	 * one that gets registered. Without that, pmac early boot console
 	 * would prevent fbcon from taking over.
+	 *
+	 * If this isn't the last console and it has CON_CONSDEV set, we
+	 * need to set it on the next preferred console.
 	 */
 	if (console_drivers == NULL)
 		preferred_console = selected_console;
-		
+	else if (console->flags & CON_CONSDEV)
+		console_drivers->flags |= CON_CONSDEV;
 
 	release_console_sem();
 	return res;
diff --git a/kernel/resource.c b/kernel/resource.c
index 52f696f..26967e0 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -263,7 +263,7 @@
 			new->start = min;
 		if (new->end > max)
 			new->end = max;
-		new->start = (new->start + align - 1) & ~(align - 1);
+		new->start = ALIGN(new->start, align);
 		if (alignf)
 			alignf(alignf_data, new, size, align);
 		if (new->start < new->end && new->end - new->start >= size - 1) {
diff --git a/kernel/sched.c b/kernel/sched.c
index 66b2ed7..e2b0d3e 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -166,7 +166,7 @@
 #define SCALE_PRIO(x, prio) \
 	max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO/2), MIN_TIMESLICE)
 
-static inline unsigned int task_timeslice(task_t *p)
+static unsigned int task_timeslice(task_t *p)
 {
 	if (p->static_prio < NICE_TO_PRIO(0))
 		return SCALE_PRIO(DEF_TIMESLICE*4, p->static_prio);
@@ -206,7 +206,7 @@
 	 */
 	unsigned long nr_running;
 #ifdef CONFIG_SMP
-	unsigned long cpu_load;
+	unsigned long cpu_load[3];
 #endif
 	unsigned long long nr_switches;
 
@@ -260,22 +260,86 @@
 
 static DEFINE_PER_CPU(struct runqueue, runqueues);
 
+/*
+ * The domain tree (rq->sd) is protected by RCU's quiescent state transition.
+ * See detach_destroy_domains: synchronize_sched for details.
+ *
+ * The domain tree of any CPU may only be accessed from within
+ * preempt-disabled sections.
+ */
 #define for_each_domain(cpu, domain) \
-	for (domain = cpu_rq(cpu)->sd; domain; domain = domain->parent)
+for (domain = rcu_dereference(cpu_rq(cpu)->sd); domain; domain = domain->parent)
 
 #define cpu_rq(cpu)		(&per_cpu(runqueues, (cpu)))
 #define this_rq()		(&__get_cpu_var(runqueues))
 #define task_rq(p)		cpu_rq(task_cpu(p))
 #define cpu_curr(cpu)		(cpu_rq(cpu)->curr)
 
-/*
- * Default context-switch locking:
- */
 #ifndef prepare_arch_switch
-# define prepare_arch_switch(rq, next)	do { } while (0)
-# define finish_arch_switch(rq, next)	spin_unlock_irq(&(rq)->lock)
-# define task_running(rq, p)		((rq)->curr == (p))
+# define prepare_arch_switch(next)	do { } while (0)
 #endif
+#ifndef finish_arch_switch
+# define finish_arch_switch(prev)	do { } while (0)
+#endif
+
+#ifndef __ARCH_WANT_UNLOCKED_CTXSW
+static inline int task_running(runqueue_t *rq, task_t *p)
+{
+	return rq->curr == p;
+}
+
+static inline void prepare_lock_switch(runqueue_t *rq, task_t *next)
+{
+}
+
+static inline void finish_lock_switch(runqueue_t *rq, task_t *prev)
+{
+	spin_unlock_irq(&rq->lock);
+}
+
+#else /* __ARCH_WANT_UNLOCKED_CTXSW */
+static inline int task_running(runqueue_t *rq, task_t *p)
+{
+#ifdef CONFIG_SMP
+	return p->oncpu;
+#else
+	return rq->curr == p;
+#endif
+}
+
+static inline void prepare_lock_switch(runqueue_t *rq, task_t *next)
+{
+#ifdef CONFIG_SMP
+	/*
+	 * We can optimise this out completely for !SMP, because the
+	 * SMP rebalancing from interrupt is the only thing that cares
+	 * here.
+	 */
+	next->oncpu = 1;
+#endif
+#ifdef __ARCH_WANT_INTERRUPTS_ON_CTXSW
+	spin_unlock_irq(&rq->lock);
+#else
+	spin_unlock(&rq->lock);
+#endif
+}
+
+static inline void finish_lock_switch(runqueue_t *rq, task_t *prev)
+{
+#ifdef CONFIG_SMP
+	/*
+	 * After ->oncpu is cleared, the task can be moved to a different CPU.
+	 * We must ensure this doesn't happen until the switch is completely
+	 * finished.
+	 */
+	smp_wmb();
+	prev->oncpu = 0;
+#endif
+#ifndef __ARCH_WANT_INTERRUPTS_ON_CTXSW
+	local_irq_enable();
+#endif
+}
+#endif /* __ARCH_WANT_UNLOCKED_CTXSW */
 
 /*
  * task_rq_lock - lock the runqueue a given task resides on and disable
@@ -309,7 +373,7 @@
  * bump this up when changing the output format or the meaning of an existing
  * format, so that tools can adapt (or abort)
  */
-#define SCHEDSTAT_VERSION 11
+#define SCHEDSTAT_VERSION 12
 
 static int show_schedstat(struct seq_file *seq, void *v)
 {
@@ -338,6 +402,7 @@
 
 #ifdef CONFIG_SMP
 		/* domain-specific stats */
+		preempt_disable();
 		for_each_domain(cpu, sd) {
 			enum idle_type itype;
 			char mask_str[NR_CPUS];
@@ -356,11 +421,13 @@
 				    sd->lb_nobusyq[itype],
 				    sd->lb_nobusyg[itype]);
 			}
-			seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu %lu\n",
+			seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
 			    sd->alb_cnt, sd->alb_failed, sd->alb_pushed,
-			    sd->sbe_pushed, sd->sbe_attempts,
+			    sd->sbe_cnt, sd->sbe_balanced, sd->sbe_pushed,
+			    sd->sbf_cnt, sd->sbf_balanced, sd->sbf_pushed,
 			    sd->ttwu_wake_remote, sd->ttwu_move_affine, sd->ttwu_move_balance);
 		}
+		preempt_enable();
 #endif
 	}
 	return 0;
@@ -414,22 +481,6 @@
 	return rq;
 }
 
-#ifdef CONFIG_SCHED_SMT
-static int cpu_and_siblings_are_idle(int cpu)
-{
-	int sib;
-	for_each_cpu_mask(sib, cpu_sibling_map[cpu]) {
-		if (idle_cpu(sib))
-			continue;
-		return 0;
-	}
-
-	return 1;
-}
-#else
-#define cpu_and_siblings_are_idle(A) idle_cpu(A)
-#endif
-
 #ifdef CONFIG_SCHEDSTATS
 /*
  * Called when a process is dequeued from the active array and given
@@ -622,7 +673,7 @@
 	rq->nr_running++;
 }
 
-static void recalc_task_prio(task_t *p, unsigned long long now)
+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;
@@ -681,7 +732,7 @@
 		}
 	}
 
-	p->prio = effective_prio(p);
+	return effective_prio(p);
 }
 
 /*
@@ -704,7 +755,7 @@
 	}
 #endif
 
-	recalc_task_prio(p, now);
+	p->prio = recalc_task_prio(p, now);
 
 	/*
 	 * This checks to make sure it's not an uninterruptible task
@@ -782,22 +833,12 @@
 }
 
 #ifdef CONFIG_SMP
-enum request_type {
-	REQ_MOVE_TASK,
-	REQ_SET_DOMAIN,
-};
-
 typedef struct {
 	struct list_head list;
-	enum request_type type;
 
-	/* For REQ_MOVE_TASK */
 	task_t *task;
 	int dest_cpu;
 
-	/* For REQ_SET_DOMAIN */
-	struct sched_domain *sd;
-
 	struct completion done;
 } migration_req_t;
 
@@ -819,7 +860,6 @@
 	}
 
 	init_completion(&req->done);
-	req->type = REQ_MOVE_TASK;
 	req->task = p;
 	req->dest_cpu = dest_cpu;
 	list_add(&req->list, &rq->migration_queue);
@@ -886,26 +926,154 @@
  * We want to under-estimate the load of migration sources, to
  * balance conservatively.
  */
-static inline unsigned long source_load(int cpu)
+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, load_now);
+	return min(rq->cpu_load[type-1], load_now);
 }
 
 /*
  * Return a high guess at the load of a migration-target cpu
  */
-static inline unsigned long target_load(int cpu)
+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, load_now);
+	return max(rq->cpu_load[type-1], load_now);
 }
 
-#endif
+/*
+ * find_idlest_group finds and returns the least busy CPU group within the
+ * domain.
+ */
+static struct sched_group *
+find_idlest_group(struct sched_domain *sd, struct task_struct *p, int this_cpu)
+{
+	struct sched_group *idlest = NULL, *this = NULL, *group = sd->groups;
+	unsigned long min_load = ULONG_MAX, this_load = 0;
+	int load_idx = sd->forkexec_idx;
+	int imbalance = 100 + (sd->imbalance_pct-100)/2;
+
+	do {
+		unsigned long load, avg_load;
+		int local_group;
+		int i;
+
+		local_group = cpu_isset(this_cpu, group->cpumask);
+		/* XXX: put a cpus allowed check */
+
+		/* Tally up the load of all CPUs in the group */
+		avg_load = 0;
+
+		for_each_cpu_mask(i, group->cpumask) {
+			/* Bias balancing toward cpus of our domain */
+			if (local_group)
+				load = source_load(i, load_idx);
+			else
+				load = target_load(i, load_idx);
+
+			avg_load += load;
+		}
+
+		/* Adjust by relative CPU power of the group */
+		avg_load = (avg_load * SCHED_LOAD_SCALE) / group->cpu_power;
+
+		if (local_group) {
+			this_load = avg_load;
+			this = group;
+		} else if (avg_load < min_load) {
+			min_load = avg_load;
+			idlest = group;
+		}
+		group = group->next;
+	} while (group != sd->groups);
+
+	if (!idlest || 100*this_load < imbalance*min_load)
+		return NULL;
+	return idlest;
+}
+
+/*
+ * find_idlest_queue - find the idlest runqueue among the cpus in group.
+ */
+static int find_idlest_cpu(struct sched_group *group, int this_cpu)
+{
+	unsigned long load, min_load = ULONG_MAX;
+	int idlest = -1;
+	int i;
+
+	for_each_cpu_mask(i, group->cpumask) {
+		load = source_load(i, 0);
+
+		if (load < min_load || (load == min_load && i == this_cpu)) {
+			min_load = load;
+			idlest = i;
+		}
+	}
+
+	return idlest;
+}
+
+/*
+ * sched_balance_self: balance the current task (running on cpu) in domains
+ * that have the 'flag' flag set. In practice, this is SD_BALANCE_FORK and
+ * SD_BALANCE_EXEC.
+ *
+ * Balance, ie. select the least loaded group.
+ *
+ * Returns the target CPU number, or the same CPU if no balancing is needed.
+ *
+ * preempt must be disabled.
+ */
+static int sched_balance_self(int cpu, int flag)
+{
+	struct task_struct *t = current;
+	struct sched_domain *tmp, *sd = NULL;
+
+	for_each_domain(cpu, tmp)
+		if (tmp->flags & flag)
+			sd = tmp;
+
+	while (sd) {
+		cpumask_t span;
+		struct sched_group *group;
+		int new_cpu;
+		int weight;
+
+		span = sd->span;
+		group = find_idlest_group(sd, t, cpu);
+		if (!group)
+			goto nextlevel;
+
+		new_cpu = find_idlest_cpu(group, cpu);
+		if (new_cpu == -1 || new_cpu == cpu)
+			goto nextlevel;
+
+		/* Now try balancing at a lower domain level */
+		cpu = new_cpu;
+nextlevel:
+		sd = NULL;
+		weight = cpus_weight(span);
+		for_each_domain(cpu, tmp) {
+			if (weight <= cpus_weight(tmp->span))
+				break;
+			if (tmp->flags & flag)
+				sd = tmp;
+		}
+		/* while loop will break here if sd == NULL */
+	}
+
+	return cpu;
+}
+
+#endif /* CONFIG_SMP */
 
 /*
  * wake_idle() will wake a task on an idle cpu if task->cpu is
@@ -927,14 +1095,14 @@
 
 	for_each_domain(cpu, sd) {
 		if (sd->flags & SD_WAKE_IDLE) {
-			cpus_and(tmp, sd->span, cpu_online_map);
-			cpus_and(tmp, tmp, p->cpus_allowed);
+			cpus_and(tmp, sd->span, p->cpus_allowed);
 			for_each_cpu_mask(i, tmp) {
 				if (idle_cpu(i))
 					return i;
 			}
 		}
-		else break;
+		else
+			break;
 	}
 	return cpu;
 }
@@ -967,7 +1135,7 @@
 	runqueue_t *rq;
 #ifdef CONFIG_SMP
 	unsigned long load, this_load;
-	struct sched_domain *sd;
+	struct sched_domain *sd, *this_sd = NULL;
 	int new_cpu;
 #endif
 
@@ -986,70 +1154,69 @@
 	if (unlikely(task_running(rq, p)))
 		goto out_activate;
 
-#ifdef CONFIG_SCHEDSTATS
+	new_cpu = cpu;
+
 	schedstat_inc(rq, ttwu_cnt);
 	if (cpu == this_cpu) {
 		schedstat_inc(rq, ttwu_local);
-	} else {
-		for_each_domain(this_cpu, sd) {
-			if (cpu_isset(cpu, sd->span)) {
-				schedstat_inc(sd, ttwu_wake_remote);
-				break;
-			}
+		goto out_set_cpu;
+	}
+
+	for_each_domain(this_cpu, sd) {
+		if (cpu_isset(cpu, sd->span)) {
+			schedstat_inc(sd, ttwu_wake_remote);
+			this_sd = sd;
+			break;
 		}
 	}
-#endif
 
-	new_cpu = cpu;
-	if (cpu == this_cpu || unlikely(!cpu_isset(this_cpu, p->cpus_allowed)))
+	if (unlikely(!cpu_isset(this_cpu, p->cpus_allowed)))
 		goto out_set_cpu;
 
-	load = source_load(cpu);
-	this_load = target_load(this_cpu);
-
 	/*
-	 * If sync wakeup then subtract the (maximum possible) effect of
-	 * the currently running task from the load of the current CPU:
+	 * Check for affine wakeup and passive balancing possibilities.
 	 */
-	if (sync)
-		this_load -= SCHED_LOAD_SCALE;
-
-	/* Don't pull the task off an idle CPU to a busy one */
-	if (load < SCHED_LOAD_SCALE/2 && this_load > SCHED_LOAD_SCALE/2)
-		goto out_set_cpu;
-
-	new_cpu = this_cpu; /* Wake to this CPU if we can */
-
-	/*
-	 * Scan domains for affine wakeup and passive balancing
-	 * possibilities.
-	 */
-	for_each_domain(this_cpu, sd) {
+	if (this_sd) {
+		int idx = this_sd->wake_idx;
 		unsigned int imbalance;
+
+		imbalance = 100 + (this_sd->imbalance_pct - 100) / 2;
+
+		load = source_load(cpu, idx);
+		this_load = target_load(this_cpu, idx);
+
+		new_cpu = this_cpu; /* Wake to this CPU if we can */
+
+		if (this_sd->flags & SD_WAKE_AFFINE) {
+			unsigned long tl = this_load;
+			/*
+			 * 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;
+
+			if ((tl <= load &&
+				tl + target_load(cpu, idx) <= SCHED_LOAD_SCALE) ||
+				100*(tl + SCHED_LOAD_SCALE) <= imbalance*load) {
+				/*
+				 * This domain has SD_WAKE_AFFINE and
+				 * p is cache cold in this domain, and
+				 * there is no bad imbalance.
+				 */
+				schedstat_inc(this_sd, ttwu_move_affine);
+				goto out_set_cpu;
+			}
+		}
+
 		/*
 		 * Start passive balancing when half the imbalance_pct
 		 * limit is reached.
 		 */
-		imbalance = sd->imbalance_pct + (sd->imbalance_pct - 100) / 2;
-
-		if ((sd->flags & SD_WAKE_AFFINE) &&
-				!task_hot(p, rq->timestamp_last_tick, sd)) {
-			/*
-			 * This domain has SD_WAKE_AFFINE and p is cache cold
-			 * in this domain.
-			 */
-			if (cpu_isset(cpu, sd->span)) {
-				schedstat_inc(sd, ttwu_move_affine);
-				goto out_set_cpu;
-			}
-		} else if ((sd->flags & SD_WAKE_BALANCE) &&
-				imbalance*this_load <= 100*load) {
-			/*
-			 * This domain has SD_WAKE_BALANCE and there is
-			 * an imbalance.
-			 */
-			if (cpu_isset(cpu, sd->span)) {
-				schedstat_inc(sd, ttwu_move_balance);
+		if (this_sd->flags & SD_WAKE_BALANCE) {
+			if (imbalance*this_load <= 100*load) {
+				schedstat_inc(this_sd, ttwu_move_balance);
 				goto out_set_cpu;
 			}
 		}
@@ -1120,17 +1287,19 @@
 	return try_to_wake_up(p, state, 0);
 }
 
-#ifdef CONFIG_SMP
-static int find_idlest_cpu(struct task_struct *p, int this_cpu,
-			   struct sched_domain *sd);
-#endif
-
 /*
  * Perform scheduler related setup for a newly forked process p.
  * p is forked by current.
  */
-void fastcall sched_fork(task_t *p)
+void fastcall sched_fork(task_t *p, int clone_flags)
 {
+	int cpu = get_cpu();
+
+#ifdef CONFIG_SMP
+	cpu = sched_balance_self(cpu, SD_BALANCE_FORK);
+#endif
+	set_task_cpu(p, cpu);
+
 	/*
 	 * We mark the process as running here, but have not actually
 	 * inserted it onto the runqueue yet. This guarantees that
@@ -1140,17 +1309,14 @@
 	p->state = TASK_RUNNING;
 	INIT_LIST_HEAD(&p->run_list);
 	p->array = NULL;
-	spin_lock_init(&p->switch_lock);
 #ifdef CONFIG_SCHEDSTATS
 	memset(&p->sched_info, 0, sizeof(p->sched_info));
 #endif
+#if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
+	p->oncpu = 0;
+#endif
 #ifdef CONFIG_PREEMPT
-	/*
-	 * During context-switch we hold precisely one spinlock, which
-	 * schedule_tail drops. (in the common case it's this_rq()->lock,
-	 * but it also can be p->switch_lock.) So we compensate with a count
-	 * of 1. Also, we want to start with kernel preemption disabled.
-	 */
+	/* Want to start with kernel preemption disabled. */
 	p->thread_info->preempt_count = 1;
 #endif
 	/*
@@ -1174,12 +1340,10 @@
 		 * runqueue lock is not a problem.
 		 */
 		current->time_slice = 1;
-		preempt_disable();
 		scheduler_tick();
-		local_irq_enable();
-		preempt_enable();
-	} else
-		local_irq_enable();
+	}
+	local_irq_enable();
+	put_cpu();
 }
 
 /*
@@ -1196,10 +1360,9 @@
 	runqueue_t *rq, *this_rq;
 
 	rq = task_rq_lock(p, &flags);
-	cpu = task_cpu(p);
-	this_cpu = smp_processor_id();
-
 	BUG_ON(p->state != TASK_RUNNING);
+	this_cpu = smp_processor_id();
+	cpu = task_cpu(p);
 
 	/*
 	 * We decrease the sleep average of forking parents
@@ -1296,22 +1459,40 @@
 }
 
 /**
+ * prepare_task_switch - prepare to switch tasks
+ * @rq: the runqueue preparing to switch
+ * @next: the task we are going to switch to.
+ *
+ * This is called with the rq lock held and interrupts off. It must
+ * be paired with a subsequent finish_task_switch after the context
+ * switch.
+ *
+ * prepare_task_switch sets up locking and calls architecture specific
+ * hooks.
+ */
+static inline void prepare_task_switch(runqueue_t *rq, task_t *next)
+{
+	prepare_lock_switch(rq, next);
+	prepare_arch_switch(next);
+}
+
+/**
  * finish_task_switch - clean up after a task-switch
  * @prev: the thread we just switched away from.
  *
- * We enter this with the runqueue still locked, and finish_arch_switch()
- * will unlock it along with doing any other architecture-specific cleanup
- * actions.
+ * finish_task_switch must be called after the context switch, paired
+ * with a prepare_task_switch call before the context switch.
+ * finish_task_switch will reconcile locking set up by prepare_task_switch,
+ * and do any other architecture-specific cleanup actions.
  *
  * Note that we may have delayed dropping an mm in context_switch(). If
  * so, we finish that here outside of the runqueue lock.  (Doing it
  * with the lock held can cause deadlocks; see schedule() for
  * details.)
  */
-static inline void finish_task_switch(task_t *prev)
+static inline void finish_task_switch(runqueue_t *rq, task_t *prev)
 	__releases(rq->lock)
 {
-	runqueue_t *rq = this_rq();
 	struct mm_struct *mm = rq->prev_mm;
 	unsigned long prev_task_flags;
 
@@ -1329,7 +1510,8 @@
 	 *		Manfred Spraul <manfred@colorfullife.com>
 	 */
 	prev_task_flags = prev->flags;
-	finish_arch_switch(rq, prev);
+	finish_arch_switch(prev);
+	finish_lock_switch(rq, prev);
 	if (mm)
 		mmdrop(mm);
 	if (unlikely(prev_task_flags & PF_DEAD))
@@ -1343,8 +1525,12 @@
 asmlinkage void schedule_tail(task_t *prev)
 	__releases(rq->lock)
 {
-	finish_task_switch(prev);
-
+	runqueue_t *rq = this_rq();
+	finish_task_switch(rq, prev);
+#ifdef __ARCH_WANT_UNLOCKED_CTXSW
+	/* In this case, finish_task_switch does not reenable preemption */
+	preempt_enable();
+#endif
 	if (current->set_child_tid)
 		put_user(current->pid, current->set_child_tid);
 }
@@ -1494,51 +1680,6 @@
 }
 
 /*
- * find_idlest_cpu - find the least busy runqueue.
- */
-static int find_idlest_cpu(struct task_struct *p, int this_cpu,
-			   struct sched_domain *sd)
-{
-	unsigned long load, min_load, this_load;
-	int i, min_cpu;
-	cpumask_t mask;
-
-	min_cpu = UINT_MAX;
-	min_load = ULONG_MAX;
-
-	cpus_and(mask, sd->span, p->cpus_allowed);
-
-	for_each_cpu_mask(i, mask) {
-		load = target_load(i);
-
-		if (load < min_load) {
-			min_cpu = i;
-			min_load = load;
-
-			/* break out early on an idle CPU: */
-			if (!min_load)
-				break;
-		}
-	}
-
-	/* add +1 to account for the new task */
-	this_load = source_load(this_cpu) + SCHED_LOAD_SCALE;
-
-	/*
-	 * Would with the addition of the new task to the
-	 * current CPU there be an imbalance between this
-	 * CPU and the idlest CPU?
-	 *
-	 * Use half of the balancing threshold - new-context is
-	 * a good opportunity to balance.
-	 */
-	if (min_load*(100 + (sd->imbalance_pct-100)/2) < this_load*100)
-		return min_cpu;
-
-	return this_cpu;
-}
-
-/*
  * If dest_cpu is allowed for this process, migrate the task to it.
  * This is accomplished by forcing the cpu_allowed mask to only
  * allow dest_cpu, which will force the cpu onto dest_cpu.  Then
@@ -1571,37 +1712,16 @@
 }
 
 /*
- * sched_exec(): find the highest-level, exec-balance-capable
- * domain and try to migrate the task to the least loaded CPU.
- *
- * execve() is a valuable balancing opportunity, because at this point
- * the task has the smallest effective memory and cache footprint.
+ * sched_exec - execve() is a valuable balancing opportunity, because at
+ * this point the task has the smallest effective memory and cache footprint.
  */
 void sched_exec(void)
 {
-	struct sched_domain *tmp, *sd = NULL;
 	int new_cpu, this_cpu = get_cpu();
-
-	/* Prefer the current CPU if there's only this task running */
-	if (this_rq()->nr_running <= 1)
-		goto out;
-
-	for_each_domain(this_cpu, tmp)
-		if (tmp->flags & SD_BALANCE_EXEC)
-			sd = tmp;
-
-	if (sd) {
-		schedstat_inc(sd, sbe_attempts);
-		new_cpu = find_idlest_cpu(current, this_cpu, sd);
-		if (new_cpu != this_cpu) {
-			schedstat_inc(sd, sbe_pushed);
-			put_cpu();
-			sched_migrate_task(current, new_cpu);
-			return;
-		}
-	}
-out:
+	new_cpu = sched_balance_self(this_cpu, SD_BALANCE_EXEC);
 	put_cpu();
+	if (new_cpu != this_cpu)
+		sched_migrate_task(current, new_cpu);
 }
 
 /*
@@ -1632,7 +1752,7 @@
  */
 static inline
 int can_migrate_task(task_t *p, runqueue_t *rq, int this_cpu,
-		     struct sched_domain *sd, enum idle_type idle)
+	     struct sched_domain *sd, enum idle_type idle, int *all_pinned)
 {
 	/*
 	 * We do not migrate tasks that are:
@@ -1640,23 +1760,24 @@
 	 * 2) cannot be migrated to this CPU due to cpus_allowed, or
 	 * 3) are cache-hot on their current CPU.
 	 */
-	if (task_running(rq, p))
-		return 0;
 	if (!cpu_isset(this_cpu, p->cpus_allowed))
 		return 0;
+	*all_pinned = 0;
+
+	if (task_running(rq, p))
+		return 0;
 
 	/*
 	 * Aggressive migration if:
-	 * 1) the [whole] cpu is idle, or
+	 * 1) task is cache cold, or
 	 * 2) too many balance attempts have failed.
 	 */
 
-	if (cpu_and_siblings_are_idle(this_cpu) || \
-			sd->nr_balance_failed > sd->cache_nice_tries)
+	if (sd->nr_balance_failed > sd->cache_nice_tries)
 		return 1;
 
 	if (task_hot(p, rq->timestamp_last_tick, sd))
-			return 0;
+		return 0;
 	return 1;
 }
 
@@ -1669,16 +1790,18 @@
  */
 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)
+		      enum idle_type idle, int *all_pinned)
 {
 	prio_array_t *array, *dst_array;
 	struct list_head *head, *curr;
-	int idx, pulled = 0;
+	int idx, pulled = 0, pinned = 0;
 	task_t *tmp;
 
-	if (max_nr_move <= 0 || busiest->nr_running <= 1)
+	if (max_nr_move == 0)
 		goto out;
 
+	pinned = 1;
+
 	/*
 	 * We first consider expired tasks. Those will likely not be
 	 * executed in the near future, and they are most likely to
@@ -1717,7 +1840,7 @@
 
 	curr = curr->prev;
 
-	if (!can_migrate_task(tmp, busiest, this_cpu, sd, idle)) {
+	if (!can_migrate_task(tmp, busiest, this_cpu, sd, idle, &pinned)) {
 		if (curr != head)
 			goto skip_queue;
 		idx++;
@@ -1746,6 +1869,9 @@
 	 * inside pull_task().
 	 */
 	schedstat_add(sd, lb_gained[idle], pulled);
+
+	if (all_pinned)
+		*all_pinned = pinned;
 	return pulled;
 }
 
@@ -1760,8 +1886,15 @@
 {
 	struct sched_group *busiest = NULL, *this = NULL, *group = sd->groups;
 	unsigned long max_load, avg_load, total_load, this_load, total_pwr;
+	int load_idx;
 
 	max_load = this_load = total_load = total_pwr = 0;
+	if (idle == NOT_IDLE)
+		load_idx = sd->busy_idx;
+	else if (idle == NEWLY_IDLE)
+		load_idx = sd->newidle_idx;
+	else
+		load_idx = sd->idle_idx;
 
 	do {
 		unsigned long load;
@@ -1776,9 +1909,9 @@
 		for_each_cpu_mask(i, group->cpumask) {
 			/* Bias balancing toward cpus of our domain */
 			if (local_group)
-				load = target_load(i);
+				load = target_load(i, load_idx);
 			else
-				load = source_load(i);
+				load = source_load(i, load_idx);
 
 			avg_load += load;
 		}
@@ -1792,12 +1925,10 @@
 		if (local_group) {
 			this_load = avg_load;
 			this = group;
-			goto nextgroup;
 		} else if (avg_load > max_load) {
 			max_load = avg_load;
 			busiest = group;
 		}
-nextgroup:
 		group = group->next;
 	} while (group != sd->groups);
 
@@ -1870,15 +2001,9 @@
 
 	/* Get rid of the scaling factor, rounding down as we divide */
 	*imbalance = *imbalance / SCHED_LOAD_SCALE;
-
 	return busiest;
 
 out_balanced:
-	if (busiest && (idle == NEWLY_IDLE ||
-			(idle == SCHED_IDLE && max_load > SCHED_LOAD_SCALE)) ) {
-		*imbalance = 1;
-		return busiest;
-	}
 
 	*imbalance = 0;
 	return NULL;
@@ -1894,7 +2019,7 @@
 	int i;
 
 	for_each_cpu_mask(i, group->cpumask) {
-		load = source_load(i);
+		load = source_load(i, 0);
 
 		if (load > max_load) {
 			max_load = load;
@@ -1906,6 +2031,12 @@
 }
 
 /*
+ * Max backoff if we encounter pinned tasks. Pretty arbitrary value, but
+ * so long as it is large enough.
+ */
+#define MAX_PINNED_INTERVAL	512
+
+/*
  * Check this_cpu to ensure it is balanced within domain. Attempt to move
  * tasks if there is an imbalance.
  *
@@ -1917,7 +2048,8 @@
 	struct sched_group *group;
 	runqueue_t *busiest;
 	unsigned long imbalance;
-	int nr_moved;
+	int nr_moved, all_pinned = 0;
+	int active_balance = 0;
 
 	spin_lock(&this_rq->lock);
 	schedstat_inc(sd, lb_cnt[idle]);
@@ -1934,15 +2066,7 @@
 		goto out_balanced;
 	}
 
-	/*
-	 * This should be "impossible", but since load
-	 * balancing is inherently racy and statistical,
-	 * it could happen in theory.
-	 */
-	if (unlikely(busiest == this_rq)) {
-		WARN_ON(1);
-		goto out_balanced;
-	}
+	BUG_ON(busiest == this_rq);
 
 	schedstat_add(sd, lb_imbalance[idle], imbalance);
 
@@ -1956,9 +2080,15 @@
 		 */
 		double_lock_balance(this_rq, busiest);
 		nr_moved = move_tasks(this_rq, this_cpu, busiest,
-						imbalance, sd, idle);
+						imbalance, sd, idle,
+						&all_pinned);
 		spin_unlock(&busiest->lock);
+
+		/* All tasks on this runqueue were pinned by CPU affinity */
+		if (unlikely(all_pinned))
+			goto out_balanced;
 	}
+
 	spin_unlock(&this_rq->lock);
 
 	if (!nr_moved) {
@@ -1966,36 +2096,38 @@
 		sd->nr_balance_failed++;
 
 		if (unlikely(sd->nr_balance_failed > sd->cache_nice_tries+2)) {
-			int wake = 0;
 
 			spin_lock(&busiest->lock);
 			if (!busiest->active_balance) {
 				busiest->active_balance = 1;
 				busiest->push_cpu = this_cpu;
-				wake = 1;
+				active_balance = 1;
 			}
 			spin_unlock(&busiest->lock);
-			if (wake)
+			if (active_balance)
 				wake_up_process(busiest->migration_thread);
 
 			/*
 			 * We've kicked active balancing, reset the failure
 			 * counter.
 			 */
-			sd->nr_balance_failed = sd->cache_nice_tries;
+			sd->nr_balance_failed = sd->cache_nice_tries+1;
 		}
-
-		/*
-		 * We were unbalanced, but unsuccessful in move_tasks(),
-		 * so bump the balance_interval to lessen the lock contention.
-		 */
-		if (sd->balance_interval < sd->max_interval)
-			sd->balance_interval++;
-	} else {
+	} else
 		sd->nr_balance_failed = 0;
 
+	if (likely(!active_balance)) {
 		/* We were unbalanced, so reset the balancing interval */
 		sd->balance_interval = sd->min_interval;
+	} else {
+		/*
+		 * If we've begun active balancing, start to back off. This
+		 * case may not be covered by the all_pinned logic if there
+		 * is only 1 task on the busy runqueue (because we don't call
+		 * move_tasks).
+		 */
+		if (sd->balance_interval < sd->max_interval)
+			sd->balance_interval *= 2;
 	}
 
 	return nr_moved;
@@ -2005,8 +2137,10 @@
 
 	schedstat_inc(sd, lb_balanced[idle]);
 
+	sd->nr_balance_failed = 0;
 	/* tune up the balancing interval */
-	if (sd->balance_interval < sd->max_interval)
+	if ((all_pinned && sd->balance_interval < MAX_PINNED_INTERVAL) ||
+			(sd->balance_interval < sd->max_interval))
 		sd->balance_interval *= 2;
 
 	return 0;
@@ -2030,31 +2164,36 @@
 	schedstat_inc(sd, lb_cnt[NEWLY_IDLE]);
 	group = find_busiest_group(sd, this_cpu, &imbalance, NEWLY_IDLE);
 	if (!group) {
-		schedstat_inc(sd, lb_balanced[NEWLY_IDLE]);
 		schedstat_inc(sd, lb_nobusyg[NEWLY_IDLE]);
-		goto out;
+		goto out_balanced;
 	}
 
 	busiest = find_busiest_queue(group);
-	if (!busiest || busiest == this_rq) {
-		schedstat_inc(sd, lb_balanced[NEWLY_IDLE]);
+	if (!busiest) {
 		schedstat_inc(sd, lb_nobusyq[NEWLY_IDLE]);
-		goto out;
+		goto out_balanced;
 	}
 
+	BUG_ON(busiest == this_rq);
+
 	/* Attempt to move tasks */
 	double_lock_balance(this_rq, busiest);
 
 	schedstat_add(sd, lb_imbalance[NEWLY_IDLE], imbalance);
 	nr_moved = move_tasks(this_rq, this_cpu, busiest,
-					imbalance, sd, NEWLY_IDLE);
+					imbalance, sd, NEWLY_IDLE, NULL);
 	if (!nr_moved)
 		schedstat_inc(sd, lb_failed[NEWLY_IDLE]);
+	else
+		sd->nr_balance_failed = 0;
 
 	spin_unlock(&busiest->lock);
-
-out:
 	return nr_moved;
+
+out_balanced:
+	schedstat_inc(sd, lb_balanced[NEWLY_IDLE]);
+	sd->nr_balance_failed = 0;
+	return 0;
 }
 
 /*
@@ -2086,56 +2225,42 @@
 static void active_load_balance(runqueue_t *busiest_rq, int busiest_cpu)
 {
 	struct sched_domain *sd;
-	struct sched_group *cpu_group;
 	runqueue_t *target_rq;
-	cpumask_t visited_cpus;
-	int cpu;
+	int target_cpu = busiest_rq->push_cpu;
+
+	if (busiest_rq->nr_running <= 1)
+		/* no task to move */
+		return;
+
+	target_rq = cpu_rq(target_cpu);
 
 	/*
-	 * Search for suitable CPUs to push tasks to in successively higher
-	 * domains with SD_LOAD_BALANCE set.
+	 * This condition is "impossible", if it occurs
+	 * we need to fix it.  Originally reported by
+	 * Bjorn Helgaas on a 128-cpu setup.
 	 */
-	visited_cpus = CPU_MASK_NONE;
-	for_each_domain(busiest_cpu, sd) {
-		if (!(sd->flags & SD_LOAD_BALANCE))
-			/* no more domains to search */
-			break;
+	BUG_ON(busiest_rq == target_rq);
 
-		schedstat_inc(sd, alb_cnt);
+	/* move a task from busiest_rq to target_rq */
+	double_lock_balance(busiest_rq, target_rq);
 
-		cpu_group = sd->groups;
-		do {
-			for_each_cpu_mask(cpu, cpu_group->cpumask) {
-				if (busiest_rq->nr_running <= 1)
-					/* no more tasks left to move */
-					return;
-				if (cpu_isset(cpu, visited_cpus))
-					continue;
-				cpu_set(cpu, visited_cpus);
-				if (!cpu_and_siblings_are_idle(cpu) || cpu == busiest_cpu)
-					continue;
+	/* Search for an sd spanning us and the target CPU. */
+	for_each_domain(target_cpu, sd)
+		if ((sd->flags & SD_LOAD_BALANCE) &&
+			cpu_isset(busiest_cpu, sd->span))
+				break;
 
-				target_rq = cpu_rq(cpu);
-				/*
-				 * This condition is "impossible", if it occurs
-				 * we need to fix it.  Originally reported by
-				 * Bjorn Helgaas on a 128-cpu setup.
-				 */
-				BUG_ON(busiest_rq == target_rq);
+	if (unlikely(sd == NULL))
+		goto out;
 
-				/* move a task from busiest_rq to target_rq */
-				double_lock_balance(busiest_rq, target_rq);
-				if (move_tasks(target_rq, cpu, busiest_rq,
-						1, sd, SCHED_IDLE)) {
-					schedstat_inc(sd, alb_pushed);
-				} else {
-					schedstat_inc(sd, alb_failed);
-				}
-				spin_unlock(&target_rq->lock);
-			}
-			cpu_group = cpu_group->next;
-		} while (cpu_group != sd->groups);
-	}
+	schedstat_inc(sd, alb_cnt);
+
+	if (move_tasks(target_rq, target_cpu, busiest_rq, 1, sd, SCHED_IDLE, NULL))
+		schedstat_inc(sd, alb_pushed);
+	else
+		schedstat_inc(sd, alb_failed);
+out:
+	spin_unlock(&target_rq->lock);
 }
 
 /*
@@ -2156,18 +2281,23 @@
 	unsigned long old_load, this_load;
 	unsigned long j = jiffies + CPU_OFFSET(this_cpu);
 	struct sched_domain *sd;
+	int i;
 
-	/* Update our load */
-	old_load = this_rq->cpu_load;
 	this_load = this_rq->nr_running * SCHED_LOAD_SCALE;
-	/*
-	 * Round up the averaging division if load is increasing. This
-	 * prevents us from getting stuck on 9 if the load is 10, for
-	 * example.
-	 */
-	if (this_load > old_load)
-		old_load++;
-	this_rq->cpu_load = (old_load + this_load) / 2;
+	/* Update our load */
+	for (i = 0; i < 3; i++) {
+		unsigned long new_load = this_load;
+		int scale = 1 << i;
+		old_load = this_rq->cpu_load[i];
+		/*
+		 * Round up the averaging division if load is increasing. This
+		 * prevents us from getting stuck on 9 if the load is 10, for
+		 * example.
+		 */
+		if (new_load > old_load)
+			new_load += scale-1;
+		this_rq->cpu_load[i] = (old_load*(scale-1) + new_load) / scale;
+	}
 
 	for_each_domain(this_cpu, sd) {
 		unsigned long interval;
@@ -2447,11 +2577,15 @@
 #ifdef CONFIG_SCHED_SMT
 static inline void wake_sleeping_dependent(int this_cpu, runqueue_t *this_rq)
 {
-	struct sched_domain *sd = this_rq->sd;
+	struct sched_domain *tmp, *sd = NULL;
 	cpumask_t sibling_map;
 	int i;
 
-	if (!(sd->flags & SD_SHARE_CPUPOWER))
+	for_each_domain(this_cpu, tmp)
+		if (tmp->flags & SD_SHARE_CPUPOWER)
+			sd = tmp;
+
+	if (!sd)
 		return;
 
 	/*
@@ -2492,13 +2626,17 @@
 
 static inline int dependent_sleeper(int this_cpu, runqueue_t *this_rq)
 {
-	struct sched_domain *sd = this_rq->sd;
+	struct sched_domain *tmp, *sd = NULL;
 	cpumask_t sibling_map;
 	prio_array_t *array;
 	int ret = 0, i;
 	task_t *p;
 
-	if (!(sd->flags & SD_SHARE_CPUPOWER))
+	for_each_domain(this_cpu, tmp)
+		if (tmp->flags & SD_SHARE_CPUPOWER)
+			sd = tmp;
+
+	if (!sd)
 		return 0;
 
 	/*
@@ -2576,7 +2714,7 @@
 	/*
 	 * Underflow?
 	 */
-	BUG_ON(((int)preempt_count() < 0));
+	BUG_ON((preempt_count() < 0));
 	preempt_count() += val;
 	/*
 	 * Spinlock count overflowing soon?
@@ -2613,7 +2751,7 @@
 	struct list_head *queue;
 	unsigned long long now;
 	unsigned long run_time;
-	int cpu, idx;
+	int cpu, idx, new_prio;
 
 	/*
 	 * Test if we are atomic.  Since do_exit() needs to call into
@@ -2735,9 +2873,14 @@
 			delta = delta * (ON_RUNQUEUE_WEIGHT * 128 / 100) / 128;
 
 		array = next->array;
-		dequeue_task(next, array);
-		recalc_task_prio(next, next->timestamp + delta);
-		enqueue_task(next, array);
+		new_prio = recalc_task_prio(next, next->timestamp + delta);
+
+		if (unlikely(next->prio != new_prio)) {
+			dequeue_task(next, array);
+			next->prio = new_prio;
+			enqueue_task(next, array);
+		} else
+			requeue_task(next, array);
 	}
 	next->activated = 0;
 switch_tasks:
@@ -2761,11 +2904,15 @@
 		rq->curr = next;
 		++*switch_count;
 
-		prepare_arch_switch(rq, next);
+		prepare_task_switch(rq, next);
 		prev = context_switch(rq, prev, next);
 		barrier();
-
-		finish_task_switch(prev);
+		/*
+		 * this_rq must be evaluated again because prev may have moved
+		 * CPUs since it called schedule(), thus the 'rq' on its stack
+		 * frame will be invalid.
+		 */
+		finish_task_switch(this_rq(), prev);
 	} else
 		spin_unlock_irq(&rq->lock);
 
@@ -2869,7 +3016,7 @@
 
 int default_wake_function(wait_queue_t *curr, unsigned mode, int sync, void *key)
 {
-	task_t *p = curr->task;
+	task_t *p = curr->private;
 	return try_to_wake_up(p, mode, sync);
 }
 
@@ -3301,15 +3448,7 @@
 {
 	return TASK_NICE(p);
 }
-
-/*
- * The only users of task_nice are binfmt_elf and binfmt_elf32.
- * binfmt_elf is no longer modular, but binfmt_elf32 still is.
- * Therefore, task_nice is needed if there is a compat_mode.
- */
-#ifdef CONFIG_COMPAT
 EXPORT_SYMBOL_GPL(task_nice);
-#endif
 
 /**
  * idle_cpu - is a given cpu idle currently?
@@ -3384,13 +3523,24 @@
 	if ((policy == SCHED_NORMAL) != (param->sched_priority == 0))
 		return -EINVAL;
 
-	if ((policy == SCHED_FIFO || policy == SCHED_RR) &&
-	    param->sched_priority > p->signal->rlim[RLIMIT_RTPRIO].rlim_cur &&
-	    !capable(CAP_SYS_NICE))
-		return -EPERM;
-	if ((current->euid != p->euid) && (current->euid != p->uid) &&
-	    !capable(CAP_SYS_NICE))
-		return -EPERM;
+	/*
+	 * Allow unprivileged RT tasks to decrease priority:
+	 */
+	if (!capable(CAP_SYS_NICE)) {
+		/* can't change policy */
+		if (policy != p->policy)
+			return -EPERM;
+		/* can't increase priority */
+		if (policy != SCHED_NORMAL &&
+		    param->sched_priority > p->rt_priority &&
+		    param->sched_priority >
+				p->signal->rlim[RLIMIT_RTPRIO].rlim_cur)
+			return -EPERM;
+		/* can't change other user's priorities */
+		if ((current->euid != p->euid) &&
+		    (current->euid != p->uid))
+			return -EPERM;
+	}
 
 	retval = security_task_setscheduler(p, policy, param);
 	if (retval)
@@ -3755,19 +3905,22 @@
  */
 int cond_resched_lock(spinlock_t * lock)
 {
+	int ret = 0;
+
 	if (need_lockbreak(lock)) {
 		spin_unlock(lock);
 		cpu_relax();
+		ret = 1;
 		spin_lock(lock);
 	}
 	if (need_resched()) {
 		_raw_spin_unlock(lock);
 		preempt_enable_no_resched();
 		__cond_resched();
+		ret = 1;
 		spin_lock(lock);
-		return 1;
 	}
-	return 0;
+	return ret;
 }
 
 EXPORT_SYMBOL(cond_resched_lock);
@@ -3811,7 +3964,7 @@
  */
 void __sched io_schedule(void)
 {
-	struct runqueue *rq = &per_cpu(runqueues, _smp_processor_id());
+	struct runqueue *rq = &per_cpu(runqueues, raw_smp_processor_id());
 
 	atomic_inc(&rq->nr_iowait);
 	schedule();
@@ -3822,7 +3975,7 @@
 
 long __sched io_schedule_timeout(long timeout)
 {
-	struct runqueue *rq = &per_cpu(runqueues, _smp_processor_id());
+	struct runqueue *rq = &per_cpu(runqueues, raw_smp_processor_id());
 	long ret;
 
 	atomic_inc(&rq->nr_iowait);
@@ -4027,6 +4180,9 @@
 
 	spin_lock_irqsave(&rq->lock, flags);
 	rq->curr = rq->idle = idle;
+#if defined(CONFIG_SMP) && defined(__ARCH_WANT_UNLOCKED_CTXSW)
+	idle->oncpu = 1;
+#endif
 	set_tsk_need_resched(idle);
 	spin_unlock_irqrestore(&rq->lock, flags);
 
@@ -4171,8 +4327,7 @@
 		struct list_head *head;
 		migration_req_t *req;
 
-		if (current->flags & PF_FREEZE)
-			refrigerator(PF_FREEZE);
+		try_to_freeze();
 
 		spin_lock_irq(&rq->lock);
 
@@ -4197,17 +4352,9 @@
 		req = list_entry(head->next, migration_req_t, list);
 		list_del_init(head->next);
 
-		if (req->type == REQ_MOVE_TASK) {
-			spin_unlock(&rq->lock);
-			__migrate_task(req->task, cpu, req->dest_cpu);
-			local_irq_enable();
-		} else if (req->type == REQ_SET_DOMAIN) {
-			rq->sd = req->sd;
-			spin_unlock_irq(&rq->lock);
-		} else {
-			spin_unlock_irq(&rq->lock);
-			WARN_ON(1);
-		}
+		spin_unlock(&rq->lock);
+		__migrate_task(req->task, cpu, req->dest_cpu);
+		local_irq_enable();
 
 		complete(&req->done);
 	}
@@ -4438,7 +4585,6 @@
 			migration_req_t *req;
 			req = list_entry(rq->migration_queue.next,
 					 migration_req_t, list);
-			BUG_ON(req->type != REQ_MOVE_TASK);
 			list_del_init(&req->list);
 			complete(&req->done);
 		}
@@ -4469,12 +4615,17 @@
 #endif
 
 #ifdef CONFIG_SMP
-#define SCHED_DOMAIN_DEBUG
+#undef SCHED_DOMAIN_DEBUG
 #ifdef SCHED_DOMAIN_DEBUG
 static void sched_domain_debug(struct sched_domain *sd, int cpu)
 {
 	int level = 0;
 
+	if (!sd) {
+		printk(KERN_DEBUG "CPU%d attaching NULL sched-domain.\n", cpu);
+		return;
+	}
+
 	printk(KERN_DEBUG "CPU%d attaching sched-domain:\n", cpu);
 
 	do {
@@ -4557,37 +4708,81 @@
 #define sched_domain_debug(sd, cpu) {}
 #endif
 
+static int sd_degenerate(struct sched_domain *sd)
+{
+	if (cpus_weight(sd->span) == 1)
+		return 1;
+
+	/* Following flags need at least 2 groups */
+	if (sd->flags & (SD_LOAD_BALANCE |
+			 SD_BALANCE_NEWIDLE |
+			 SD_BALANCE_FORK |
+			 SD_BALANCE_EXEC)) {
+		if (sd->groups != sd->groups->next)
+			return 0;
+	}
+
+	/* Following flags don't use groups */
+	if (sd->flags & (SD_WAKE_IDLE |
+			 SD_WAKE_AFFINE |
+			 SD_WAKE_BALANCE))
+		return 0;
+
+	return 1;
+}
+
+static int sd_parent_degenerate(struct sched_domain *sd,
+						struct sched_domain *parent)
+{
+	unsigned long cflags = sd->flags, pflags = parent->flags;
+
+	if (sd_degenerate(parent))
+		return 1;
+
+	if (!cpus_equal(sd->span, parent->span))
+		return 0;
+
+	/* Does parent contain flags not in child? */
+	/* WAKE_BALANCE is a subset of WAKE_AFFINE */
+	if (cflags & SD_WAKE_AFFINE)
+		pflags &= ~SD_WAKE_BALANCE;
+	/* Flags needing groups don't count if only 1 group in parent */
+	if (parent->groups == parent->groups->next) {
+		pflags &= ~(SD_LOAD_BALANCE |
+				SD_BALANCE_NEWIDLE |
+				SD_BALANCE_FORK |
+				SD_BALANCE_EXEC);
+	}
+	if (~cflags & pflags)
+		return 0;
+
+	return 1;
+}
+
 /*
  * Attach the domain 'sd' to 'cpu' as its base domain.  Callers must
  * hold the hotplug lock.
  */
-void __devinit cpu_attach_domain(struct sched_domain *sd, int cpu)
+void cpu_attach_domain(struct sched_domain *sd, int cpu)
 {
-	migration_req_t req;
-	unsigned long flags;
 	runqueue_t *rq = cpu_rq(cpu);
-	int local = 1;
+	struct sched_domain *tmp;
+
+	/* Remove the sched domains which do not contribute to scheduling. */
+	for (tmp = sd; tmp; tmp = tmp->parent) {
+		struct sched_domain *parent = tmp->parent;
+		if (!parent)
+			break;
+		if (sd_parent_degenerate(tmp, parent))
+			tmp->parent = parent->parent;
+	}
+
+	if (sd && sd_degenerate(sd))
+		sd = sd->parent;
 
 	sched_domain_debug(sd, cpu);
 
-	spin_lock_irqsave(&rq->lock, flags);
-
-	if (cpu == smp_processor_id() || !cpu_online(cpu)) {
-		rq->sd = sd;
-	} else {
-		init_completion(&req.done);
-		req.type = REQ_SET_DOMAIN;
-		req.sd = sd;
-		list_add(&req.list, &rq->migration_queue);
-		local = 0;
-	}
-
-	spin_unlock_irqrestore(&rq->lock, flags);
-
-	if (!local) {
-		wake_up_process(rq->migration_thread);
-		wait_for_completion(&req.done);
-	}
+	rcu_assign_pointer(rq->sd, sd);
 }
 
 /* cpus with isolated domains */
@@ -4619,7 +4814,7 @@
  * covered by the given span, and will set each group's ->cpumask correctly,
  * and ->cpu_power to 0.
  */
-void __devinit init_sched_build_groups(struct sched_group groups[],
+void init_sched_build_groups(struct sched_group groups[],
 			cpumask_t span, int (*group_fn)(int cpu))
 {
 	struct sched_group *first = NULL, *last = NULL;
@@ -4655,13 +4850,14 @@
 
 
 #ifdef ARCH_HAS_SCHED_DOMAIN
-extern void __devinit arch_init_sched_domains(void);
-extern void __devinit arch_destroy_sched_domains(void);
+extern void build_sched_domains(const cpumask_t *cpu_map);
+extern void arch_init_sched_domains(const cpumask_t *cpu_map);
+extern void arch_destroy_sched_domains(const cpumask_t *cpu_map);
 #else
 #ifdef CONFIG_SCHED_SMT
 static DEFINE_PER_CPU(struct sched_domain, cpu_domains);
 static struct sched_group sched_group_cpus[NR_CPUS];
-static int __devinit cpu_to_cpu_group(int cpu)
+static int cpu_to_cpu_group(int cpu)
 {
 	return cpu;
 }
@@ -4669,7 +4865,7 @@
 
 static DEFINE_PER_CPU(struct sched_domain, phys_domains);
 static struct sched_group sched_group_phys[NR_CPUS];
-static int __devinit cpu_to_phys_group(int cpu)
+static int cpu_to_phys_group(int cpu)
 {
 #ifdef CONFIG_SCHED_SMT
 	return first_cpu(cpu_sibling_map[cpu]);
@@ -4682,7 +4878,7 @@
 
 static DEFINE_PER_CPU(struct sched_domain, node_domains);
 static struct sched_group sched_group_nodes[MAX_NUMNODES];
-static int __devinit cpu_to_node_group(int cpu)
+static int cpu_to_node_group(int cpu)
 {
 	return cpu_to_node(cpu);
 }
@@ -4713,39 +4909,28 @@
 #endif
 
 /*
- * Set up scheduler domains and groups.  Callers must hold the hotplug lock.
+ * Build sched domains for a given set of cpus and attach the sched domains
+ * to the individual cpus
  */
-static void __devinit arch_init_sched_domains(void)
+static void build_sched_domains(const cpumask_t *cpu_map)
 {
 	int i;
-	cpumask_t cpu_default_map;
-
-#if defined(CONFIG_SCHED_SMT) && defined(CONFIG_NUMA)
-	check_sibling_maps();
-#endif
-	/*
-	 * Setup mask for cpus without special case scheduling requirements.
-	 * For now this just excludes isolated cpus, but could be used to
-	 * exclude other special cases in the future.
-	 */
-	cpus_complement(cpu_default_map, cpu_isolated_map);
-	cpus_and(cpu_default_map, cpu_default_map, cpu_online_map);
 
 	/*
-	 * Set up domains. Isolated domains just stay on the dummy domain.
+	 * Set up domains for cpus specified by the cpu_map.
 	 */
-	for_each_cpu_mask(i, cpu_default_map) {
+	for_each_cpu_mask(i, *cpu_map) {
 		int group;
 		struct sched_domain *sd = NULL, *p;
 		cpumask_t nodemask = node_to_cpumask(cpu_to_node(i));
 
-		cpus_and(nodemask, nodemask, cpu_default_map);
+		cpus_and(nodemask, nodemask, *cpu_map);
 
 #ifdef CONFIG_NUMA
 		sd = &per_cpu(node_domains, i);
 		group = cpu_to_node_group(i);
 		*sd = SD_NODE_INIT;
-		sd->span = cpu_default_map;
+		sd->span = *cpu_map;
 		sd->groups = &sched_group_nodes[group];
 #endif
 
@@ -4763,7 +4948,7 @@
 		group = cpu_to_cpu_group(i);
 		*sd = SD_SIBLING_INIT;
 		sd->span = cpu_sibling_map[i];
-		cpus_and(sd->span, sd->span, cpu_default_map);
+		cpus_and(sd->span, sd->span, *cpu_map);
 		sd->parent = p;
 		sd->groups = &sched_group_cpus[group];
 #endif
@@ -4773,7 +4958,7 @@
 	/* Set up CPU (sibling) groups */
 	for_each_online_cpu(i) {
 		cpumask_t this_sibling_map = cpu_sibling_map[i];
-		cpus_and(this_sibling_map, this_sibling_map, cpu_default_map);
+		cpus_and(this_sibling_map, this_sibling_map, *cpu_map);
 		if (i != first_cpu(this_sibling_map))
 			continue;
 
@@ -4786,7 +4971,7 @@
 	for (i = 0; i < MAX_NUMNODES; i++) {
 		cpumask_t nodemask = node_to_cpumask(i);
 
-		cpus_and(nodemask, nodemask, cpu_default_map);
+		cpus_and(nodemask, nodemask, *cpu_map);
 		if (cpus_empty(nodemask))
 			continue;
 
@@ -4796,12 +4981,12 @@
 
 #ifdef CONFIG_NUMA
 	/* Set up node groups */
-	init_sched_build_groups(sched_group_nodes, cpu_default_map,
+	init_sched_build_groups(sched_group_nodes, *cpu_map,
 					&cpu_to_node_group);
 #endif
 
 	/* Calculate CPU power for physical packages and nodes */
-	for_each_cpu_mask(i, cpu_default_map) {
+	for_each_cpu_mask(i, *cpu_map) {
 		int power;
 		struct sched_domain *sd;
 #ifdef CONFIG_SCHED_SMT
@@ -4825,7 +5010,7 @@
 	}
 
 	/* Attach the domains */
-	for_each_online_cpu(i) {
+	for_each_cpu_mask(i, *cpu_map) {
 		struct sched_domain *sd;
 #ifdef CONFIG_SCHED_SMT
 		sd = &per_cpu(cpu_domains, i);
@@ -4835,41 +5020,85 @@
 		cpu_attach_domain(sd, i);
 	}
 }
+/*
+ * Set up scheduler domains and groups.  Callers must hold the hotplug lock.
+ */
+static void arch_init_sched_domains(cpumask_t *cpu_map)
+{
+	cpumask_t cpu_default_map;
 
-#ifdef CONFIG_HOTPLUG_CPU
-static void __devinit arch_destroy_sched_domains(void)
+#if defined(CONFIG_SCHED_SMT) && defined(CONFIG_NUMA)
+	check_sibling_maps();
+#endif
+	/*
+	 * Setup mask for cpus without special case scheduling requirements.
+	 * For now this just excludes isolated cpus, but could be used to
+	 * exclude other special cases in the future.
+	 */
+	cpus_andnot(cpu_default_map, *cpu_map, cpu_isolated_map);
+
+	build_sched_domains(&cpu_default_map);
+}
+
+static void arch_destroy_sched_domains(const cpumask_t *cpu_map)
 {
 	/* Do nothing: everything is statically allocated. */
 }
-#endif
 
 #endif /* ARCH_HAS_SCHED_DOMAIN */
 
 /*
- * Initial dummy domain for early boot and for hotplug cpu. Being static,
- * it is initialized to zero, so all balancing flags are cleared which is
- * what we want.
+ * Detach sched domains from a group of cpus specified in cpu_map
+ * These cpus will now be attached to the NULL domain
  */
-static struct sched_domain sched_domain_dummy;
+static inline void detach_destroy_domains(const cpumask_t *cpu_map)
+{
+	int i;
+
+	for_each_cpu_mask(i, *cpu_map)
+		cpu_attach_domain(NULL, i);
+	synchronize_sched();
+	arch_destroy_sched_domains(cpu_map);
+}
+
+/*
+ * Partition sched domains as specified by the cpumasks below.
+ * This attaches all cpus from the cpumasks to the NULL domain,
+ * waits for a RCU quiescent period, recalculates sched
+ * domain information and then attaches them back to the
+ * correct sched domains
+ * Call with hotplug lock held
+ */
+void partition_sched_domains(cpumask_t *partition1, cpumask_t *partition2)
+{
+	cpumask_t change_map;
+
+	cpus_and(*partition1, *partition1, cpu_online_map);
+	cpus_and(*partition2, *partition2, cpu_online_map);
+	cpus_or(change_map, *partition1, *partition2);
+
+	/* 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);
+}
 
 #ifdef CONFIG_HOTPLUG_CPU
 /*
  * Force a reinitialization of the sched domains hierarchy.  The domains
  * and groups cannot be updated in place without racing with the balancing
- * code, so we temporarily attach all running cpus to a "dummy" domain
+ * code, so we temporarily attach all running cpus to the NULL domain
  * which will prevent rebalancing while the sched domains are recalculated.
  */
 static int update_sched_domains(struct notifier_block *nfb,
 				unsigned long action, void *hcpu)
 {
-	int i;
-
 	switch (action) {
 	case CPU_UP_PREPARE:
 	case CPU_DOWN_PREPARE:
-		for_each_online_cpu(i)
-			cpu_attach_domain(&sched_domain_dummy, i);
-		arch_destroy_sched_domains();
+		detach_destroy_domains(&cpu_online_map);
 		return NOTIFY_OK;
 
 	case CPU_UP_CANCELED:
@@ -4885,7 +5114,7 @@
 	}
 
 	/* The hotplug lock is already held by cpu_up/cpu_down */
-	arch_init_sched_domains();
+	arch_init_sched_domains(&cpu_online_map);
 
 	return NOTIFY_OK;
 }
@@ -4894,7 +5123,7 @@
 void __init sched_init_smp(void)
 {
 	lock_cpu_hotplug();
-	arch_init_sched_domains();
+	arch_init_sched_domains(&cpu_online_map);
 	unlock_cpu_hotplug();
 	/* XXX: Theoretical race here - CPU may be hotplugged now */
 	hotcpu_notifier(update_sched_domains, 0);
@@ -4924,13 +5153,15 @@
 
 		rq = cpu_rq(i);
 		spin_lock_init(&rq->lock);
+		rq->nr_running = 0;
 		rq->active = rq->arrays;
 		rq->expired = rq->arrays + 1;
 		rq->best_expired_prio = MAX_PRIO;
 
 #ifdef CONFIG_SMP
-		rq->sd = &sched_domain_dummy;
-		rq->cpu_load = 0;
+		rq->sd = NULL;
+		for (j = 1; j < 3; j++)
+			rq->cpu_load[j] = 0;
 		rq->active_balance = 0;
 		rq->push_cpu = 0;
 		rq->migration_thread = NULL;
diff --git a/kernel/signal.c b/kernel/signal.c
index b3c24c7..ca1186e 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -24,6 +24,7 @@
 #include <linux/ptrace.h>
 #include <linux/posix-timers.h>
 #include <linux/signal.h>
+#include <linux/audit.h>
 #include <asm/param.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -212,6 +213,7 @@
 fastcall void recalc_sigpending_tsk(struct task_struct *t)
 {
 	if (t->signal->group_stop_count > 0 ||
+	    (freezing(t)) ||
 	    PENDING(&t->pending, &t->blocked) ||
 	    PENDING(&t->signal->shared_pending, &t->blocked))
 		set_tsk_thread_flag(t, TIF_SIGPENDING);
@@ -667,7 +669,11 @@
 	    && (current->uid ^ t->suid) && (current->uid ^ t->uid)
 	    && !capable(CAP_KILL))
 		return error;
-	return security_task_kill(t, info, sig);
+
+	error = security_task_kill(t, info, sig);
+	if (!error)
+		audit_signal_info(sig, t); /* Let audit system see the signal */
+	return error;
 }
 
 /* forward decl */
@@ -2225,8 +2231,7 @@
 			current->state = TASK_INTERRUPTIBLE;
 			timeout = schedule_timeout(timeout);
 
-			if (current->flags & PF_FREEZE)
-				refrigerator(PF_FREEZE);
+			try_to_freeze();
 			spin_lock_irq(&current->sighand->siglock);
 			sig = dequeue_signal(current, &these, &info);
 			current->blocked = current->real_blocked;
diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c
index 6116b25..84a9d18 100644
--- a/kernel/stop_machine.c
+++ b/kernel/stop_machine.c
@@ -100,7 +100,7 @@
 	stopmachine_state = STOPMACHINE_WAIT;
 
 	for_each_online_cpu(i) {
-		if (i == _smp_processor_id())
+		if (i == raw_smp_processor_id())
 			continue;
 		ret = kernel_thread(stopmachine, (void *)(long)i,CLONE_KERNEL);
 		if (ret < 0)
@@ -182,7 +182,7 @@
 
 	/* If they don't care which CPU fn runs on, bind to any online one. */
 	if (cpu == NR_CPUS)
-		cpu = _smp_processor_id();
+		cpu = raw_smp_processor_id();
 
 	p = kthread_create(do_stop, &smdata, "kstopmachine");
 	if (!IS_ERR(p)) {
diff --git a/kernel/sys.c b/kernel/sys.c
index f006632..9a24374 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -16,6 +16,8 @@
 #include <linux/init.h>
 #include <linux/highuid.h>
 #include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/kexec.h>
 #include <linux/workqueue.h>
 #include <linux/device.h>
 #include <linux/key.h>
@@ -405,6 +407,7 @@
 	case LINUX_REBOOT_CMD_HALT:
 		notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL);
 		system_state = SYSTEM_HALT;
+		device_suspend(PMSG_SUSPEND);
 		device_shutdown();
 		printk(KERN_EMERG "System halted.\n");
 		machine_halt();
@@ -415,6 +418,7 @@
 	case LINUX_REBOOT_CMD_POWER_OFF:
 		notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL);
 		system_state = SYSTEM_POWER_OFF;
+		device_suspend(PMSG_SUSPEND);
 		device_shutdown();
 		printk(KERN_EMERG "Power down.\n");
 		machine_power_off();
@@ -431,11 +435,30 @@
 
 		notifier_call_chain(&reboot_notifier_list, SYS_RESTART, buffer);
 		system_state = SYSTEM_RESTART;
+		device_suspend(PMSG_FREEZE);
 		device_shutdown();
 		printk(KERN_EMERG "Restarting system with command '%s'.\n", buffer);
 		machine_restart(buffer);
 		break;
 
+#ifdef CONFIG_KEXEC
+	case LINUX_REBOOT_CMD_KEXEC:
+	{
+		struct kimage *image;
+		image = xchg(&kexec_image, 0);
+		if (!image) {
+			unlock_kernel();
+			return -EINVAL;
+		}
+		notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
+		system_state = SYSTEM_RESTART;
+		device_shutdown();
+		printk(KERN_EMERG "Starting new kernel\n");
+		machine_shutdown();
+		machine_kexec(image);
+		break;
+	}
+#endif
 #ifdef CONFIG_SOFTWARE_SUSPEND
 	case LINUX_REBOOT_CMD_SW_SUSPEND:
 		{
@@ -525,7 +548,7 @@
 	}
 	if (new_egid != old_egid)
 	{
-		current->mm->dumpable = 0;
+		current->mm->dumpable = suid_dumpable;
 		smp_wmb();
 	}
 	if (rgid != (gid_t) -1 ||
@@ -556,7 +579,7 @@
 	{
 		if(old_egid != gid)
 		{
-			current->mm->dumpable=0;
+			current->mm->dumpable = suid_dumpable;
 			smp_wmb();
 		}
 		current->gid = current->egid = current->sgid = current->fsgid = gid;
@@ -565,7 +588,7 @@
 	{
 		if(old_egid != gid)
 		{
-			current->mm->dumpable=0;
+			current->mm->dumpable = suid_dumpable;
 			smp_wmb();
 		}
 		current->egid = current->fsgid = gid;
@@ -596,7 +619,7 @@
 
 	if(dumpclear)
 	{
-		current->mm->dumpable = 0;
+		current->mm->dumpable = suid_dumpable;
 		smp_wmb();
 	}
 	current->uid = new_ruid;
@@ -653,7 +676,7 @@
 
 	if (new_euid != old_euid)
 	{
-		current->mm->dumpable=0;
+		current->mm->dumpable = suid_dumpable;
 		smp_wmb();
 	}
 	current->fsuid = current->euid = new_euid;
@@ -703,7 +726,7 @@
 
 	if (old_euid != uid)
 	{
-		current->mm->dumpable = 0;
+		current->mm->dumpable = suid_dumpable;
 		smp_wmb();
 	}
 	current->fsuid = current->euid = uid;
@@ -748,7 +771,7 @@
 	if (euid != (uid_t) -1) {
 		if (euid != current->euid)
 		{
-			current->mm->dumpable = 0;
+			current->mm->dumpable = suid_dumpable;
 			smp_wmb();
 		}
 		current->euid = euid;
@@ -798,7 +821,7 @@
 	if (egid != (gid_t) -1) {
 		if (egid != current->egid)
 		{
-			current->mm->dumpable = 0;
+			current->mm->dumpable = suid_dumpable;
 			smp_wmb();
 		}
 		current->egid = egid;
@@ -845,7 +868,7 @@
 	{
 		if (uid != old_fsuid)
 		{
-			current->mm->dumpable = 0;
+			current->mm->dumpable = suid_dumpable;
 			smp_wmb();
 		}
 		current->fsuid = uid;
@@ -875,7 +898,7 @@
 	{
 		if (gid != old_fsgid)
 		{
-			current->mm->dumpable = 0;
+			current->mm->dumpable = suid_dumpable;
 			smp_wmb();
 		}
 		current->fsgid = gid;
@@ -894,35 +917,69 @@
 	 */
 	if (tbuf) {
 		struct tms tmp;
-		struct task_struct *tsk = current;
-		struct task_struct *t;
 		cputime_t utime, stime, cutime, cstime;
 
-		read_lock(&tasklist_lock);
-		utime = tsk->signal->utime;
-		stime = tsk->signal->stime;
-		t = tsk;
-		do {
-			utime = cputime_add(utime, t->utime);
-			stime = cputime_add(stime, t->stime);
-			t = next_thread(t);
-		} while (t != tsk);
+#ifdef CONFIG_SMP
+		if (thread_group_empty(current)) {
+			/*
+			 * Single thread case without the use of any locks.
+			 *
+			 * We may race with release_task if two threads are
+			 * executing. However, release task first adds up the
+			 * counters (__exit_signal) before  removing the task
+			 * from the process tasklist (__unhash_process).
+			 * __exit_signal also acquires and releases the
+			 * siglock which results in the proper memory ordering
+			 * so that the list modifications are always visible
+			 * after the counters have been updated.
+			 *
+			 * If the counters have been updated by the second thread
+			 * but the thread has not yet been removed from the list
+			 * then the other branch will be executing which will
+			 * block on tasklist_lock until the exit handling of the
+			 * other task is finished.
+			 *
+			 * This also implies that the sighand->siglock cannot
+			 * be held by another processor. So we can also
+			 * skip acquiring that lock.
+			 */
+			utime = cputime_add(current->signal->utime, current->utime);
+			stime = cputime_add(current->signal->utime, current->stime);
+			cutime = current->signal->cutime;
+			cstime = current->signal->cstime;
+		} else
+#endif
+		{
 
-		/*
-		 * While we have tasklist_lock read-locked, no dying thread
-		 * can be updating current->signal->[us]time.  Instead,
-		 * we got their counts included in the live thread loop.
-		 * However, another thread can come in right now and
-		 * do a wait call that updates current->signal->c[us]time.
-		 * To make sure we always see that pair updated atomically,
-		 * we take the siglock around fetching them.
-		 */
-		spin_lock_irq(&tsk->sighand->siglock);
-		cutime = tsk->signal->cutime;
-		cstime = tsk->signal->cstime;
-		spin_unlock_irq(&tsk->sighand->siglock);
-		read_unlock(&tasklist_lock);
+			/* Process with multiple threads */
+			struct task_struct *tsk = current;
+			struct task_struct *t;
 
+			read_lock(&tasklist_lock);
+			utime = tsk->signal->utime;
+			stime = tsk->signal->stime;
+			t = tsk;
+			do {
+				utime = cputime_add(utime, t->utime);
+				stime = cputime_add(stime, t->stime);
+				t = next_thread(t);
+			} while (t != tsk);
+
+			/*
+			 * While we have tasklist_lock read-locked, no dying thread
+			 * can be updating current->signal->[us]time.  Instead,
+			 * we got their counts included in the live thread loop.
+			 * However, another thread can come in right now and
+			 * do a wait call that updates current->signal->c[us]time.
+			 * To make sure we always see that pair updated atomically,
+			 * we take the siglock around fetching them.
+			 */
+			spin_lock_irq(&tsk->sighand->siglock);
+			cutime = tsk->signal->cutime;
+			cstime = tsk->signal->cstime;
+			spin_unlock_irq(&tsk->sighand->siglock);
+			read_unlock(&tasklist_lock);
+		}
 		tmp.tms_utime = cputime_to_clock_t(utime);
 		tmp.tms_stime = cputime_to_clock_t(stime);
 		tmp.tms_cutime = cputime_to_clock_t(cutime);
@@ -1225,7 +1282,7 @@
 }
 
 /* a simple bsearch */
-static int groups_search(struct group_info *group_info, gid_t grp)
+int groups_search(struct group_info *group_info, gid_t grp)
 {
 	int left, right;
 
@@ -1652,7 +1709,7 @@
 				error = 1;
 			break;
 		case PR_SET_DUMPABLE:
-			if (arg2 != 0 && arg2 != 1) {
+			if (arg2 < 0 || arg2 > 2) {
 				error = -EINVAL;
 				break;
 			}
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 0dda70e..29196ce 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -18,6 +18,8 @@
 cond_syscall(sys_lookup_dcookie);
 cond_syscall(sys_swapon);
 cond_syscall(sys_swapoff);
+cond_syscall(sys_kexec_load);
+cond_syscall(compat_sys_kexec_load);
 cond_syscall(sys_init_module);
 cond_syscall(sys_delete_module);
 cond_syscall(sys_socketpair);
@@ -77,6 +79,7 @@
 cond_syscall(sys_keyctl);
 cond_syscall(compat_sys_keyctl);
 cond_syscall(compat_sys_socketcall);
+cond_syscall(sys_set_zone_reclaim);
 
 /* arch-specific weak syscall entries */
 cond_syscall(sys_pciconfig_read);
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 701d12c..270ee7f 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -58,6 +58,7 @@
 extern int max_threads;
 extern int sysrq_enabled;
 extern int core_uses_pid;
+extern int suid_dumpable;
 extern char core_pattern[];
 extern int cad_pid;
 extern int pid_max;
@@ -950,6 +951,14 @@
 		.proc_handler	= &proc_dointvec,
 	},
 #endif
+	{
+		.ctl_name	= KERN_SETUID_DUMPABLE,
+		.procname	= "suid_dumpable",
+		.data		= &suid_dumpable,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
 	{ .ctl_name = 0 }
 };
 
@@ -991,8 +1000,7 @@
 		int error = parse_table(name, nlen, oldval, oldlenp, 
 					newval, newlen, head->ctl_table,
 					&context);
-		if (context)
-			kfree(context);
+		kfree(context);
 		if (error != -ENOTDIR)
 			return error;
 		tmp = tmp->next;
diff --git a/kernel/timer.c b/kernel/timer.c
index 207aa4f0..f2a1188 100644
--- a/kernel/timer.c
+++ b/kernel/timer.c
@@ -57,6 +57,11 @@
 #define TVN_MASK (TVN_SIZE - 1)
 #define TVR_MASK (TVR_SIZE - 1)
 
+struct timer_base_s {
+	spinlock_t lock;
+	struct timer_list *running_timer;
+};
+
 typedef struct tvec_s {
 	struct list_head vec[TVN_SIZE];
 } tvec_t;
@@ -66,9 +71,8 @@
 } tvec_root_t;
 
 struct tvec_t_base_s {
-	spinlock_t lock;
+	struct timer_base_s t_base;
 	unsigned long timer_jiffies;
-	struct timer_list *running_timer;
 	tvec_root_t tv1;
 	tvec_t tv2;
 	tvec_t tv3;
@@ -77,18 +81,16 @@
 } ____cacheline_aligned_in_smp;
 
 typedef struct tvec_t_base_s tvec_base_t;
+static DEFINE_PER_CPU(tvec_base_t, tvec_bases);
 
 static inline void set_running_timer(tvec_base_t *base,
 					struct timer_list *timer)
 {
 #ifdef CONFIG_SMP
-	base->running_timer = timer;
+	base->t_base.running_timer = timer;
 #endif
 }
 
-/* Fake initialization */
-static DEFINE_PER_CPU(tvec_base_t, tvec_bases) = { SPIN_LOCK_UNLOCKED };
-
 static void check_timer_failed(struct timer_list *timer)
 {
 	static int whine_count;
@@ -103,7 +105,6 @@
 	/*
 	 * Now fix it up
 	 */
-	spin_lock_init(&timer->lock);
 	timer->magic = TIMER_MAGIC;
 }
 
@@ -156,65 +157,113 @@
 	list_add_tail(&timer->entry, vec);
 }
 
+typedef struct timer_base_s timer_base_t;
+/*
+ * Used by TIMER_INITIALIZER, we can't use per_cpu(tvec_bases)
+ * at compile time, and we need timer->base to lock the timer.
+ */
+timer_base_t __init_timer_base
+	____cacheline_aligned_in_smp = { .lock = SPIN_LOCK_UNLOCKED };
+EXPORT_SYMBOL(__init_timer_base);
+
+/***
+ * init_timer - initialize a timer.
+ * @timer: the timer to be initialized
+ *
+ * init_timer() must be done to a timer prior calling *any* of the
+ * other timer functions.
+ */
+void fastcall init_timer(struct timer_list *timer)
+{
+	timer->entry.next = NULL;
+	timer->base = &per_cpu(tvec_bases, raw_smp_processor_id()).t_base;
+	timer->magic = TIMER_MAGIC;
+}
+EXPORT_SYMBOL(init_timer);
+
+static inline void detach_timer(struct timer_list *timer,
+					int clear_pending)
+{
+	struct list_head *entry = &timer->entry;
+
+	__list_del(entry->prev, entry->next);
+	if (clear_pending)
+		entry->next = NULL;
+	entry->prev = LIST_POISON2;
+}
+
+/*
+ * We are using hashed locking: holding per_cpu(tvec_bases).t_base.lock
+ * means that all timers which are tied to this base via timer->base are
+ * locked, and the base itself is locked too.
+ *
+ * So __run_timers/migrate_timers can safely modify all timers which could
+ * be found on ->tvX lists.
+ *
+ * When the timer's base is locked, and the timer removed from list, it is
+ * possible to set timer->base = NULL and drop the lock: the timer remains
+ * locked.
+ */
+static timer_base_t *lock_timer_base(struct timer_list *timer,
+					unsigned long *flags)
+{
+	timer_base_t *base;
+
+	for (;;) {
+		base = timer->base;
+		if (likely(base != NULL)) {
+			spin_lock_irqsave(&base->lock, *flags);
+			if (likely(base == timer->base))
+				return base;
+			/* The timer has migrated to another CPU */
+			spin_unlock_irqrestore(&base->lock, *flags);
+		}
+		cpu_relax();
+	}
+}
+
 int __mod_timer(struct timer_list *timer, unsigned long expires)
 {
-	tvec_base_t *old_base, *new_base;
+	timer_base_t *base;
+	tvec_base_t *new_base;
 	unsigned long flags;
 	int ret = 0;
 
 	BUG_ON(!timer->function);
-
 	check_timer(timer);
 
-	spin_lock_irqsave(&timer->lock, flags);
-	new_base = &__get_cpu_var(tvec_bases);
-repeat:
-	old_base = timer->base;
+	base = lock_timer_base(timer, &flags);
 
-	/*
-	 * Prevent deadlocks via ordering by old_base < new_base.
-	 */
-	if (old_base && (new_base != old_base)) {
-		if (old_base < new_base) {
-			spin_lock(&new_base->lock);
-			spin_lock(&old_base->lock);
-		} else {
-			spin_lock(&old_base->lock);
-			spin_lock(&new_base->lock);
-		}
-		/*
-		 * The timer base might have been cancelled while we were
-		 * trying to take the lock(s):
-		 */
-		if (timer->base != old_base) {
-			spin_unlock(&new_base->lock);
-			spin_unlock(&old_base->lock);
-			goto repeat;
-		}
-	} else {
-		spin_lock(&new_base->lock);
-		if (timer->base != old_base) {
-			spin_unlock(&new_base->lock);
-			goto repeat;
-		}
-	}
-
-	/*
-	 * Delete the previous timeout (if there was any), and install
-	 * the new one:
-	 */
-	if (old_base) {
-		list_del(&timer->entry);
+	if (timer_pending(timer)) {
+		detach_timer(timer, 0);
 		ret = 1;
 	}
+
+	new_base = &__get_cpu_var(tvec_bases);
+
+	if (base != &new_base->t_base) {
+		/*
+		 * We are trying to schedule the timer on the local CPU.
+		 * However we can't change timer's base while it is running,
+		 * otherwise del_timer_sync() can't detect that the timer's
+		 * handler yet has not finished. This also guarantees that
+		 * the timer is serialized wrt itself.
+		 */
+		if (unlikely(base->running_timer == timer)) {
+			/* The timer remains on a former base */
+			new_base = container_of(base, tvec_base_t, t_base);
+		} else {
+			/* See the comment in lock_timer_base() */
+			timer->base = NULL;
+			spin_unlock(&base->lock);
+			spin_lock(&new_base->t_base.lock);
+			timer->base = &new_base->t_base;
+		}
+	}
+
 	timer->expires = expires;
 	internal_add_timer(new_base, timer);
-	timer->base = new_base;
-
-	if (old_base && (new_base != old_base))
-		spin_unlock(&old_base->lock);
-	spin_unlock(&new_base->lock);
-	spin_unlock_irqrestore(&timer->lock, flags);
+	spin_unlock_irqrestore(&new_base->t_base.lock, flags);
 
 	return ret;
 }
@@ -232,15 +281,15 @@
 {
 	tvec_base_t *base = &per_cpu(tvec_bases, cpu);
   	unsigned long flags;
-  
+
   	BUG_ON(timer_pending(timer) || !timer->function);
 
 	check_timer(timer);
 
-	spin_lock_irqsave(&base->lock, flags);
+	spin_lock_irqsave(&base->t_base.lock, flags);
+	timer->base = &base->t_base;
 	internal_add_timer(base, timer);
-	timer->base = base;
-	spin_unlock_irqrestore(&base->lock, flags);
+	spin_unlock_irqrestore(&base->t_base.lock, flags);
 }
 
 
@@ -295,32 +344,55 @@
  */
 int del_timer(struct timer_list *timer)
 {
+	timer_base_t *base;
 	unsigned long flags;
-	tvec_base_t *base;
+	int ret = 0;
 
 	check_timer(timer);
 
-repeat:
- 	base = timer->base;
-	if (!base)
-		return 0;
-	spin_lock_irqsave(&base->lock, flags);
-	if (base != timer->base) {
+	if (timer_pending(timer)) {
+		base = lock_timer_base(timer, &flags);
+		if (timer_pending(timer)) {
+			detach_timer(timer, 1);
+			ret = 1;
+		}
 		spin_unlock_irqrestore(&base->lock, flags);
-		goto repeat;
 	}
-	list_del(&timer->entry);
-	/* Need to make sure that anybody who sees a NULL base also sees the list ops */
-	smp_wmb();
-	timer->base = NULL;
-	spin_unlock_irqrestore(&base->lock, flags);
 
-	return 1;
+	return ret;
 }
 
 EXPORT_SYMBOL(del_timer);
 
 #ifdef CONFIG_SMP
+/*
+ * This function tries to deactivate a timer. Upon successful (ret >= 0)
+ * exit the timer is not queued and the handler is not running on any CPU.
+ *
+ * It must not be called from interrupt contexts.
+ */
+int try_to_del_timer_sync(struct timer_list *timer)
+{
+	timer_base_t *base;
+	unsigned long flags;
+	int ret = -1;
+
+	base = lock_timer_base(timer, &flags);
+
+	if (base->running_timer == timer)
+		goto out;
+
+	ret = 0;
+	if (timer_pending(timer)) {
+		detach_timer(timer, 1);
+		ret = 1;
+	}
+out:
+	spin_unlock_irqrestore(&base->lock, flags);
+
+	return ret;
+}
+
 /***
  * del_timer_sync - deactivate a timer and wait for the handler to finish.
  * @timer: the timer to be deactivated
@@ -332,72 +404,24 @@
  * Synchronization rules: callers must prevent restarting of the timer,
  * otherwise this function is meaningless. It must not be called from
  * interrupt contexts. The caller must not hold locks which would prevent
- * completion of the timer's handler.  Upon exit the timer is not queued and
- * the handler is not running on any CPU.
+ * completion of the timer's handler. The timer's handler must not call
+ * add_timer_on(). Upon exit the timer is not queued and the handler is
+ * not running on any CPU.
  *
  * The function returns whether it has deactivated a pending timer or not.
- *
- * del_timer_sync() is slow and complicated because it copes with timer
- * handlers which re-arm the timer (periodic timers).  If the timer handler
- * is known to not do this (a single shot timer) then use
- * del_singleshot_timer_sync() instead.
  */
 int del_timer_sync(struct timer_list *timer)
 {
-	tvec_base_t *base;
-	int i, ret = 0;
-
 	check_timer(timer);
 
-del_again:
-	ret += del_timer(timer);
-
-	for_each_online_cpu(i) {
-		base = &per_cpu(tvec_bases, i);
-		if (base->running_timer == timer) {
-			while (base->running_timer == timer) {
-				cpu_relax();
-				preempt_check_resched();
-			}
-			break;
-		}
+	for (;;) {
+		int ret = try_to_del_timer_sync(timer);
+		if (ret >= 0)
+			return ret;
 	}
-	smp_rmb();
-	if (timer_pending(timer))
-		goto del_again;
-
-	return ret;
 }
+
 EXPORT_SYMBOL(del_timer_sync);
-
-/***
- * del_singleshot_timer_sync - deactivate a non-recursive timer
- * @timer: the timer to be deactivated
- *
- * This function is an optimization of del_timer_sync for the case where the
- * caller can guarantee the timer does not reschedule itself in its timer
- * function.
- *
- * Synchronization rules: callers must prevent restarting of the timer,
- * otherwise this function is meaningless. It must not be called from
- * interrupt contexts. The caller must not hold locks which wold prevent
- * completion of the timer's handler.  Upon exit the timer is not queued and
- * the handler is not running on any CPU.
- *
- * The function returns whether it has deactivated a pending timer or not.
- */
-int del_singleshot_timer_sync(struct timer_list *timer)
-{
-	int ret = del_timer(timer);
-
-	if (!ret) {
-		ret = del_timer_sync(timer);
-		BUG_ON(ret);
-	}
-
-	return ret;
-}
-EXPORT_SYMBOL(del_singleshot_timer_sync);
 #endif
 
 static int cascade(tvec_base_t *base, tvec_t *tv, int index)
@@ -415,7 +439,7 @@
 		struct timer_list *tmp;
 
 		tmp = list_entry(curr, struct timer_list, entry);
-		BUG_ON(tmp->base != base);
+		BUG_ON(tmp->base != &base->t_base);
 		curr = curr->next;
 		internal_add_timer(base, tmp);
 	}
@@ -437,7 +461,7 @@
 {
 	struct timer_list *timer;
 
-	spin_lock_irq(&base->lock);
+	spin_lock_irq(&base->t_base.lock);
 	while (time_after_eq(jiffies, base->timer_jiffies)) {
 		struct list_head work_list = LIST_HEAD_INIT(work_list);
 		struct list_head *head = &work_list;
@@ -453,8 +477,7 @@
 			cascade(base, &base->tv5, INDEX(3));
 		++base->timer_jiffies; 
 		list_splice_init(base->tv1.vec + index, &work_list);
-repeat:
-		if (!list_empty(head)) {
+		while (!list_empty(head)) {
 			void (*fn)(unsigned long);
 			unsigned long data;
 
@@ -462,25 +485,26 @@
  			fn = timer->function;
  			data = timer->data;
 
-			list_del(&timer->entry);
 			set_running_timer(base, timer);
-			smp_wmb();
-			timer->base = NULL;
-			spin_unlock_irq(&base->lock);
+			detach_timer(timer, 1);
+			spin_unlock_irq(&base->t_base.lock);
 			{
-				u32 preempt_count = preempt_count();
+				int preempt_count = preempt_count();
 				fn(data);
 				if (preempt_count != preempt_count()) {
-					printk("huh, entered %p with %08x, exited with %08x?\n", fn, preempt_count, preempt_count());
+					printk(KERN_WARNING "huh, entered %p "
+					       "with preempt_count %08x, exited"
+					       " with %08x?\n",
+					       fn, preempt_count,
+					       preempt_count());
 					BUG();
 				}
 			}
-			spin_lock_irq(&base->lock);
-			goto repeat;
+			spin_lock_irq(&base->t_base.lock);
 		}
 	}
 	set_running_timer(base, NULL);
-	spin_unlock_irq(&base->lock);
+	spin_unlock_irq(&base->t_base.lock);
 }
 
 #ifdef CONFIG_NO_IDLE_HZ
@@ -499,7 +523,7 @@
 	int i, j;
 
 	base = &__get_cpu_var(tvec_bases);
-	spin_lock(&base->lock);
+	spin_lock(&base->t_base.lock);
 	expires = base->timer_jiffies + (LONG_MAX >> 1);
 	list = 0;
 
@@ -547,7 +571,7 @@
 				expires = nte->expires;
 		}
 	}
-	spin_unlock(&base->lock);
+	spin_unlock(&base->t_base.lock);
 	return expires;
 }
 #endif
@@ -1286,9 +1310,9 @@
 {
 	int j;
 	tvec_base_t *base;
-       
+
 	base = &per_cpu(tvec_bases, cpu);
-	spin_lock_init(&base->lock);
+	spin_lock_init(&base->t_base.lock);
 	for (j = 0; j < TVN_SIZE; j++) {
 		INIT_LIST_HEAD(base->tv5.vec + j);
 		INIT_LIST_HEAD(base->tv4.vec + j);
@@ -1302,22 +1326,16 @@
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-static int migrate_timer_list(tvec_base_t *new_base, struct list_head *head)
+static void migrate_timer_list(tvec_base_t *new_base, struct list_head *head)
 {
 	struct timer_list *timer;
 
 	while (!list_empty(head)) {
 		timer = list_entry(head->next, struct timer_list, entry);
-		/* We're locking backwards from __mod_timer order here,
-		   beware deadlock. */
-		if (!spin_trylock(&timer->lock))
-			return 0;
-		list_del(&timer->entry);
+		detach_timer(timer, 0);
+		timer->base = &new_base->t_base;
 		internal_add_timer(new_base, timer);
-		timer->base = new_base;
-		spin_unlock(&timer->lock);
 	}
-	return 1;
 }
 
 static void __devinit migrate_timers(int cpu)
@@ -1331,39 +1349,24 @@
 	new_base = &get_cpu_var(tvec_bases);
 
 	local_irq_disable();
-again:
-	/* Prevent deadlocks via ordering by old_base < new_base. */
-	if (old_base < new_base) {
-		spin_lock(&new_base->lock);
-		spin_lock(&old_base->lock);
-	} else {
-		spin_lock(&old_base->lock);
-		spin_lock(&new_base->lock);
-	}
+	spin_lock(&new_base->t_base.lock);
+	spin_lock(&old_base->t_base.lock);
 
-	if (old_base->running_timer)
+	if (old_base->t_base.running_timer)
 		BUG();
 	for (i = 0; i < TVR_SIZE; i++)
-		if (!migrate_timer_list(new_base, old_base->tv1.vec + i))
-			goto unlock_again;
-	for (i = 0; i < TVN_SIZE; i++)
-		if (!migrate_timer_list(new_base, old_base->tv2.vec + i)
-		    || !migrate_timer_list(new_base, old_base->tv3.vec + i)
-		    || !migrate_timer_list(new_base, old_base->tv4.vec + i)
-		    || !migrate_timer_list(new_base, old_base->tv5.vec + i))
-			goto unlock_again;
-	spin_unlock(&old_base->lock);
-	spin_unlock(&new_base->lock);
+		migrate_timer_list(new_base, old_base->tv1.vec + i);
+	for (i = 0; i < TVN_SIZE; i++) {
+		migrate_timer_list(new_base, old_base->tv2.vec + i);
+		migrate_timer_list(new_base, old_base->tv3.vec + i);
+		migrate_timer_list(new_base, old_base->tv4.vec + i);
+		migrate_timer_list(new_base, old_base->tv5.vec + i);
+	}
+
+	spin_unlock(&old_base->t_base.lock);
+	spin_unlock(&new_base->t_base.lock);
 	local_irq_enable();
 	put_cpu_var(tvec_bases);
-	return;
-
-unlock_again:
-	/* Avoid deadlock with __mod_timer, by backing off. */
-	spin_unlock(&old_base->lock);
-	spin_unlock(&new_base->lock);
-	cpu_relax();
-	goto again;
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
@@ -1594,7 +1597,7 @@
 EXPORT_SYMBOL(msleep);
 
 /**
- * msleep_interruptible - sleep waiting for waitqueue interruptions
+ * msleep_interruptible - sleep waiting for signals
  * @msecs: Time in milliseconds to sleep for
  */
 unsigned long msleep_interruptible(unsigned int msecs)
diff --git a/lib/Kconfig b/lib/Kconfig
index eeb4522..eeb429a 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -40,6 +40,12 @@
 	tristate
 
 #
+# Generic allocator support is selected if needed
+#
+config GENERIC_ALLOCATOR
+	boolean
+
+#
 # reed solomon support is select'ed if needed
 #
 config REED_SOLOMON
@@ -57,5 +63,16 @@
 config REED_SOLOMON_DEC16
 	boolean
 
-endmenu
+#
+# Textsearch support is select'ed if needed
+#
+config TEXTSEARCH
+	boolean
 
+config TEXTSEARCH_KMP
+	tristate
+
+config TEXTSEARCH_FSM
+	tristate
+
+endmenu
diff --git a/lib/Makefile b/lib/Makefile
index 7c70db7..beed158 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -4,9 +4,10 @@
 
 lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
 	 bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
-	 kobject.o kref.o idr.o div64.o int_sqrt.o \
-	 bitmap.o extable.o kobject_uevent.o prio_tree.o sha1.o \
-	 halfmd4.o
+	 idr.o div64.o int_sqrt.o bitmap.o extable.o prio_tree.o \
+	 sha1.o halfmd4.o
+
+lib-y	+= kobject.o kref.o kobject_uevent.o klist.o
 
 obj-y += sort.o parser.o
 
@@ -19,6 +20,7 @@
 lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
 lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
 obj-$(CONFIG_LOCK_KERNEL) += kernel_lock.o
+obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
 
 ifneq ($(CONFIG_HAVE_DEC_LOCK),y) 
   lib-y += dec_and_lock.o
@@ -28,11 +30,16 @@
 obj-$(CONFIG_CRC32)	+= crc32.o
 obj-$(CONFIG_LIBCRC32C)	+= libcrc32c.o
 obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
+obj-$(CONFIG_GENERIC_ALLOCATOR) += genalloc.o
 
 obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
 obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/
 obj-$(CONFIG_REED_SOLOMON) += reed_solomon/
 
+obj-$(CONFIG_TEXTSEARCH) += textsearch.o
+obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o
+obj-$(CONFIG_TEXTSEARCH_FSM) += ts_fsm.o
+
 hostprogs-y	:= gen_crc32table
 clean-files	:= crc32table.h
 
diff --git a/lib/bitmap.c b/lib/bitmap.c
index d1388a5..fb9371f 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -289,7 +289,6 @@
 
 #define CHUNKSZ				32
 #define nbits_to_hold_value(val)	fls(val)
-#define roundup_power2(val,modulus)	(((val) + (modulus) - 1) & ~((modulus) - 1))
 #define unhex(c)			(isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10))
 #define BASEDEC 10		/* fancier cpuset lists input in decimal */
 
@@ -316,7 +315,7 @@
 	if (chunksz == 0)
 		chunksz = CHUNKSZ;
 
-	i = roundup_power2(nmaskbits, CHUNKSZ) - CHUNKSZ;
+	i = ALIGN(nmaskbits, CHUNKSZ) - CHUNKSZ;
 	for (; i >= 0; i -= CHUNKSZ) {
 		chunkmask = ((1ULL << chunksz) - 1);
 		word = i / BITS_PER_LONG;
diff --git a/lib/genalloc.c b/lib/genalloc.c
new file mode 100644
index 0000000..d6d30d2e
--- /dev/null
+++ b/lib/genalloc.c
@@ -0,0 +1,188 @@
+/*
+ * Basic general purpose allocator for managing special purpose memory
+ * not managed by the regular kmalloc/kfree interface.
+ * 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,
+ * Version 2.  See the file COPYING for more details.
+ */
+
+#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)
+{
+	struct gen_pool *poolp;
+	unsigned long tmp;
+	int i;
+
+	/*
+	 * 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;
+	}
+	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;
+}
+EXPORT_SYMBOL(gen_pool_create);
+
+
+/*
+ *  Simple power of two buddy-like generic allocator.
+ *  Provides naturally aligned memory chunks.
+ */
+unsigned long gen_pool_alloc(struct gen_pool *poolp, int size)
+{
+	int j, i, s, max_chunk_size;
+	unsigned long a, flags;
+	struct gen_pool_link *h = poolp->h;
+
+	max_chunk_size = 1 << poolp->max_chunk_shift;
+
+	if (size > max_chunk_size)
+		return 0;
+
+	i = 0;
+
+	size = max(size, 1 << ALLOC_MIN_SHIFT);
+	s = roundup_pow_of_two(size);
+
+	j = i;
+
+	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;
+		}
+		j++;
+		s <<= 1;
+	}
+	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;
+}
+EXPORT_SYMBOL(gen_pool_alloc);
+
+
+/*
+ *  Counter-part of the generic allocator.
+ */
+void gen_pool_free(struct gen_pool *poolp, unsigned long ptr, int size)
+{
+	struct gen_pool_link *q;
+	struct gen_pool_link *h = poolp->h;
+	unsigned long a, b, flags;
+	int i, s, max_chunk_size;
+
+	max_chunk_size = 1 << poolp->max_chunk_shift;
+
+	if (size > max_chunk_size)
+		return;
+
+	i = 0;
+
+	size = max(size, 1 << ALLOC_MIN_SHIFT);
+	s = roundup_pow_of_two(size);
+
+	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;
+			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);
+}
+EXPORT_SYMBOL(gen_pool_free);
diff --git a/lib/idr.c b/lib/idr.c
index 81fc430..c5be889 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -175,7 +175,7 @@
 	 * Add a new layer to the top of the tree if the requested
 	 * id is larger than the currently allocated space.
 	 */
-	while ((layers < MAX_LEVEL) && (id >= (1 << (layers*IDR_BITS)))) {
+	while ((layers < (MAX_LEVEL - 1)) && (id >= (1 << (layers*IDR_BITS)))) {
 		layers++;
 		if (!p->count)
 			continue;
diff --git a/lib/kernel_lock.c b/lib/kernel_lock.c
index 99b0ae3..bd2bc5d 100644
--- a/lib/kernel_lock.c
+++ b/lib/kernel_lock.c
@@ -9,61 +9,6 @@
 #include <linux/module.h>
 #include <linux/kallsyms.h>
 
-#if defined(CONFIG_PREEMPT) && defined(__smp_processor_id) && \
-		defined(CONFIG_DEBUG_PREEMPT)
-
-/*
- * Debugging check.
- */
-unsigned int smp_processor_id(void)
-{
-	unsigned long preempt_count = preempt_count();
-	int this_cpu = __smp_processor_id();
-	cpumask_t this_mask;
-
-	if (likely(preempt_count))
-		goto out;
-
-	if (irqs_disabled())
-		goto out;
-
-	/*
-	 * Kernel threads bound to a single CPU can safely use
-	 * smp_processor_id():
-	 */
-	this_mask = cpumask_of_cpu(this_cpu);
-
-	if (cpus_equal(current->cpus_allowed, this_mask))
-		goto out;
-
-	/*
-	 * It is valid to assume CPU-locality during early bootup:
-	 */
-	if (system_state != SYSTEM_RUNNING)
-		goto out;
-
-	/*
-	 * Avoid recursion:
-	 */
-	preempt_disable();
-
-	if (!printk_ratelimit())
-		goto out_enable;
-
-	printk(KERN_ERR "BUG: using smp_processor_id() in preemptible [%08x] code: %s/%d\n", preempt_count(), current->comm, current->pid);
-	print_symbol("caller is %s\n", (long)__builtin_return_address(0));
-	dump_stack();
-
-out_enable:
-	preempt_enable_no_resched();
-out:
-	return this_cpu;
-}
-
-EXPORT_SYMBOL(smp_processor_id);
-
-#endif /* PREEMPT && __smp_processor_id && DEBUG_PREEMPT */
-
 #ifdef CONFIG_PREEMPT_BKL
 /*
  * The 'big kernel semaphore'
diff --git a/lib/klist.c b/lib/klist.c
new file mode 100644
index 0000000..738ab81
--- /dev/null
+++ b/lib/klist.c
@@ -0,0 +1,265 @@
+/*
+ *	klist.c - Routines for manipulating klists.
+ *
+ *
+ *	This klist interface provides a couple of structures that wrap around 
+ *	struct list_head to provide explicit list "head" (struct klist) and 
+ *	list "node" (struct klist_node) objects. For struct klist, a spinlock
+ *	is included that protects access to the actual list itself. struct 
+ *	klist_node provides a pointer to the klist that owns it and a kref
+ *	reference count that indicates the number of current users of that node
+ *	in the list.
+ *
+ *	The entire point is to provide an interface for iterating over a list
+ *	that is safe and allows for modification of the list during the
+ *	iteration (e.g. insertion and removal), including modification of the
+ *	current node on the list.
+ *
+ *	It works using a 3rd object type - struct klist_iter - that is declared
+ *	and initialized before an iteration. klist_next() is used to acquire the
+ *	next element in the list. It returns NULL if there are no more items.
+ *	Internally, that routine takes the klist's lock, decrements the reference
+ *	count of the previous klist_node and increments the count of the next
+ *	klist_node. It then drops the lock and returns.
+ *
+ *	There are primitives for adding and removing nodes to/from a klist. 
+ *	When deleting, klist_del() will simply decrement the reference count. 
+ *	Only when the count goes to 0 is the node removed from the list. 
+ *	klist_remove() will try to delete the node from the list and block
+ *	until it is actually removed. This is useful for objects (like devices)
+ *	that have been removed from the system and must be freed (but must wait
+ *	until all accessors have finished).
+ *
+ *	Copyright (C) 2005 Patrick Mochel
+ *
+ *	This file is released under the GPL v2.
+ */
+
+#include <linux/klist.h>
+#include <linux/module.h>
+
+
+/**
+ *	klist_init - Initialize a klist structure. 
+ *	@k:	The klist we're initializing.
+ */
+
+void klist_init(struct klist * k)
+{
+	INIT_LIST_HEAD(&k->k_list);
+	spin_lock_init(&k->k_lock);
+}
+
+EXPORT_SYMBOL_GPL(klist_init);
+
+
+static void add_head(struct klist * k, struct klist_node * n)
+{
+	spin_lock(&k->k_lock);
+	list_add(&n->n_node, &k->k_list);
+	spin_unlock(&k->k_lock);
+}
+
+static void add_tail(struct klist * k, struct klist_node * n)
+{
+	spin_lock(&k->k_lock);
+	list_add_tail(&n->n_node, &k->k_list);
+	spin_unlock(&k->k_lock);
+}
+
+
+static void klist_node_init(struct klist * k, struct klist_node * n)
+{
+	INIT_LIST_HEAD(&n->n_node);
+	init_completion(&n->n_removed);
+	kref_init(&n->n_ref);
+	n->n_klist = k;
+}
+
+
+/**
+ *	klist_add_head - Initialize a klist_node and add it to front.
+ *	@k:	klist it's going on.
+ *	@n:	node we're adding.
+ */
+
+void klist_add_head(struct klist * k, struct klist_node * n)
+{
+	klist_node_init(k, n);
+	add_head(k, n);
+}
+
+EXPORT_SYMBOL_GPL(klist_add_head);
+
+
+/**
+ *	klist_add_tail - Initialize a klist_node and add it to back.
+ *	@k:	klist it's going on.
+ *	@n:	node we're adding.
+ */
+
+void klist_add_tail(struct klist * k, struct klist_node * n)
+{
+	klist_node_init(k, n);
+	add_tail(k, n);
+}
+
+EXPORT_SYMBOL_GPL(klist_add_tail);
+
+
+static void klist_release(struct kref * kref)
+{
+	struct klist_node * n = container_of(kref, struct klist_node, n_ref);
+	list_del(&n->n_node);
+	complete(&n->n_removed);
+	n->n_klist = NULL;
+}
+
+static int klist_dec_and_del(struct klist_node * n)
+{
+	return kref_put(&n->n_ref, klist_release);
+}
+
+
+/**
+ *	klist_del - Decrement the reference count of node and try to remove.
+ *	@n:	node we're deleting.
+ */
+
+void klist_del(struct klist_node * n)
+{
+	struct klist * k = n->n_klist;
+
+	spin_lock(&k->k_lock);
+	klist_dec_and_del(n);
+	spin_unlock(&k->k_lock);
+}
+
+EXPORT_SYMBOL_GPL(klist_del);
+
+
+/**
+ *	klist_remove - Decrement the refcount of node and wait for it to go away.
+ *	@n:	node we're removing.
+ */
+
+void klist_remove(struct klist_node * n)
+{
+	struct klist * k = n->n_klist;
+	spin_lock(&k->k_lock);
+	klist_dec_and_del(n);
+	spin_unlock(&k->k_lock);
+	wait_for_completion(&n->n_removed);
+}
+
+EXPORT_SYMBOL_GPL(klist_remove);
+
+
+/**
+ *	klist_node_attached - Say whether a node is bound to a list or not.
+ *	@n:	Node that we're testing.
+ */
+
+int klist_node_attached(struct klist_node * n)
+{
+	return (n->n_klist != NULL);
+}
+
+EXPORT_SYMBOL_GPL(klist_node_attached);
+
+
+/**
+ *	klist_iter_init_node - Initialize a klist_iter structure.
+ *	@k:	klist we're iterating.
+ *	@i:	klist_iter we're filling.
+ *	@n:	node to start with.
+ *
+ *	Similar to klist_iter_init(), but starts the action off with @n, 
+ *	instead of with the list head.
+ */
+
+void klist_iter_init_node(struct klist * k, struct klist_iter * i, struct klist_node * n)
+{
+	i->i_klist = k;
+	i->i_head = &k->k_list;
+	i->i_cur = n;
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_init_node);
+
+
+/**
+ *	klist_iter_init - Iniitalize a klist_iter structure.
+ *	@k:	klist we're iterating.
+ *	@i:	klist_iter structure we're filling.
+ *
+ *	Similar to klist_iter_init_node(), but start with the list head.
+ */
+
+void klist_iter_init(struct klist * k, struct klist_iter * i)
+{
+	klist_iter_init_node(k, i, NULL);
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_init);
+
+
+/**
+ *	klist_iter_exit - Finish a list iteration.
+ *	@i:	Iterator structure.
+ *
+ *	Must be called when done iterating over list, as it decrements the 
+ *	refcount of the current node. Necessary in case iteration exited before
+ *	the end of the list was reached, and always good form.
+ */
+
+void klist_iter_exit(struct klist_iter * i)
+{
+	if (i->i_cur) {
+		klist_del(i->i_cur);
+		i->i_cur = NULL;
+	}
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_exit);
+
+
+static struct klist_node * to_klist_node(struct list_head * n)
+{
+	return container_of(n, struct klist_node, n_node);
+}
+
+
+/**
+ *	klist_next - Ante up next node in list.
+ *	@i:	Iterator structure.
+ *
+ *	First grab list lock. Decrement the reference count of the previous
+ *	node, if there was one. Grab the next node, increment its reference 
+ *	count, drop the lock, and return that next node.
+ */
+
+struct klist_node * klist_next(struct klist_iter * i)
+{
+	struct list_head * next;
+	struct klist_node * knode = NULL;
+
+	spin_lock(&i->i_klist->k_lock);
+	if (i->i_cur) {
+		next = i->i_cur->n_node.next;
+		klist_dec_and_del(i->i_cur);
+	} else
+		next = i->i_head->next;
+
+	if (next != i->i_head) {
+		knode = to_klist_node(next);
+		kref_get(&knode->n_ref);
+	}
+	i->i_cur = knode;
+	spin_unlock(&i->i_klist->k_lock);
+	return knode;
+}
+
+EXPORT_SYMBOL_GPL(klist_next);
+
+
diff --git a/lib/kobject.c b/lib/kobject.c
index 9404882..dd0917d 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -279,7 +279,7 @@
  *	@new_name: object's new name
  */
 
-int kobject_rename(struct kobject * kobj, char *new_name)
+int kobject_rename(struct kobject * kobj, const char *new_name)
 {
 	int error = 0;
 
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 2a4e767..8e49d21 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -197,7 +197,7 @@
 	int i = 0;
 	int retval;
 	char *kobj_path = NULL;
-	char *name = NULL;
+	const char *name = NULL;
 	char *action_string;
 	u64 seq;
 	struct kobject *top_kobj = kobj;
@@ -246,10 +246,10 @@
 	if (hotplug_ops->name)
 		name = hotplug_ops->name(kset, kobj);
 	if (name == NULL)
-		name = kset->kobj.name;
+		name = kobject_name(&kset->kobj);
 
 	argv [0] = hotplug_path;
-	argv [1] = name;
+	argv [1] = (char *)name; /* won't be changed but 'const' has to go */
 	argv [2] = NULL;
 
 	/* minimal command environment */
diff --git a/lib/sha1.c b/lib/sha1.c
index 2f7f114..1cdabe3 100644
--- a/lib/sha1.c
+++ b/lib/sha1.c
@@ -41,7 +41,7 @@
 	__u32 a, b, c, d, e, t, i;
 
 	for (i = 0; i < 16; i++)
-		W[i] = be32_to_cpu(((const __u32 *)in)[i]);
+		W[i] = be32_to_cpu(((const __be32 *)in)[i]);
 
 	for (i = 0; i < 64; i++)
 		W[i+16] = rol32(W[i+13] ^ W[i+8] ^ W[i+2] ^ W[i], 1);
diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c
new file mode 100644
index 0000000..42c08ef
--- /dev/null
+++ b/lib/smp_processor_id.c
@@ -0,0 +1,55 @@
+/*
+ * lib/smp_processor_id.c
+ *
+ * DEBUG_PREEMPT variant of smp_processor_id().
+ */
+#include <linux/module.h>
+#include <linux/kallsyms.h>
+
+unsigned int debug_smp_processor_id(void)
+{
+	unsigned long preempt_count = preempt_count();
+	int this_cpu = raw_smp_processor_id();
+	cpumask_t this_mask;
+
+	if (likely(preempt_count))
+		goto out;
+
+	if (irqs_disabled())
+		goto out;
+
+	/*
+	 * Kernel threads bound to a single CPU can safely use
+	 * smp_processor_id():
+	 */
+	this_mask = cpumask_of_cpu(this_cpu);
+
+	if (cpus_equal(current->cpus_allowed, this_mask))
+		goto out;
+
+	/*
+	 * It is valid to assume CPU-locality during early bootup:
+	 */
+	if (system_state != SYSTEM_RUNNING)
+		goto out;
+
+	/*
+	 * Avoid recursion:
+	 */
+	preempt_disable();
+
+	if (!printk_ratelimit())
+		goto out_enable;
+
+	printk(KERN_ERR "BUG: using smp_processor_id() in preemptible [%08x] code: %s/%d\n", preempt_count(), current->comm, current->pid);
+	print_symbol("caller is %s\n", (long)__builtin_return_address(0));
+	dump_stack();
+
+out_enable:
+	preempt_enable_no_resched();
+out:
+	return this_cpu;
+}
+
+EXPORT_SYMBOL(debug_smp_processor_id);
+
diff --git a/lib/textsearch.c b/lib/textsearch.c
new file mode 100644
index 0000000..1e934c1
--- /dev/null
+++ b/lib/textsearch.c
@@ -0,0 +1,317 @@
+/*
+ * lib/textsearch.c	Generic text search interface
+ *
+ *		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.
+ *
+ * Authors:	Thomas Graf <tgraf@suug.ch>
+ * 		Pablo Neira Ayuso <pablo@eurodev.net>
+ *
+ * ==========================================================================
+ *
+ * INTRODUCTION
+ *
+ *   The textsearch infrastructure provides text searching facitilies for
+ *   both linear and non-linear data. Individual search algorithms are
+ *   implemented in modules and chosen by the user.
+ *
+ * ARCHITECTURE
+ *
+ *      User
+ *     +----------------+
+ *     |        finish()|<--------------(6)-----------------+
+ *     |get_next_block()|<--------------(5)---------------+ |
+ *     |                |                     Algorithm   | |
+ *     |                |                    +------------------------------+
+ *     |                |                    |  init()   find()   destroy() |
+ *     |                |                    +------------------------------+
+ *     |                |       Core API           ^       ^          ^
+ *     |                |      +---------------+  (2)     (4)        (8)
+ *     |             (1)|----->| prepare()     |---+       |          |
+ *     |             (3)|----->| find()/next() |-----------+          |
+ *     |             (7)|----->| destroy()     |----------------------+
+ *     +----------------+      +---------------+
+ *  
+ *   (1) User configures a search by calling _prepare() specifying the
+ *       search parameters such as the pattern and algorithm name.
+ *   (2) Core requests the algorithm to allocate and initialize a search
+ *       configuration according to the specified parameters.
+ *   (3) User starts the search(es) by calling _find() or _next() to
+ *       fetch subsequent occurrences. A state variable is provided
+ *       to the algorihtm to store persistant variables.
+ *   (4) Core eventually resets the search offset and forwards the find()
+ *       request to the algorithm.
+ *   (5) Algorithm calls get_next_block() provided by the user continously
+ *       to fetch the data to be searched in block by block.
+ *   (6) Algorithm invokes finish() after the last call to get_next_block
+ *       to clean up any leftovers from get_next_block. (Optional)
+ *   (7) User destroys the configuration by calling _destroy().
+ *   (8) Core notifies the algorithm to destroy algorithm specific
+ *       allocations. (Optional)
+ *
+ * USAGE
+ *
+ *   Before a search can be performed, a configuration must be created
+ *   by calling textsearch_prepare() specyfing the searching algorithm and
+ *   the pattern to look for. The returned configuration may then be used
+ *   for an arbitary amount of times and even in parallel as long as a
+ *   separate struct ts_state variable is provided to every instance.
+ *
+ *   The actual search is performed by either calling textsearch_find_-
+ *   continuous() for linear data or by providing an own get_next_block()
+ *   implementation and calling textsearch_find(). Both functions return
+ *   the position of the first occurrence of the patern or UINT_MAX if
+ *   no match was found. Subsequent occurences can be found by calling
+ *   textsearch_next() regardless of the linearity of the data.
+ *
+ *   Once you're done using a configuration it must be given back via
+ *   textsearch_destroy.
+ *
+ * EXAMPLE
+ *
+ *   int pos;
+ *   struct ts_config *conf;
+ *   struct ts_state state;
+ *   const char *pattern = "chicken";
+ *   const char *example = "We dance the funky chicken";
+ *
+ *   conf = textsearch_prepare("kmp", pattern, strlen(pattern),
+ *                             GFP_KERNEL, TS_AUTOLOAD);
+ *   if (IS_ERR(conf)) {
+ *       err = PTR_ERR(conf);
+ *       goto errout;
+ *   }
+ *
+ *   pos = textsearch_find_continuous(conf, &state, example, strlen(example));
+ *   if (pos != UINT_MAX)
+ *       panic("Oh my god, dancing chickens at %d\n", pos);
+ *
+ *   textsearch_destroy(conf);
+ *
+ * ==========================================================================
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/rcupdate.h>
+#include <linux/err.h>
+#include <linux/textsearch.h>
+
+static LIST_HEAD(ts_ops);
+static DEFINE_SPINLOCK(ts_mod_lock);
+
+static inline struct ts_ops *lookup_ts_algo(const char *name)
+{
+	struct ts_ops *o;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(o, &ts_ops, list) {
+		if (!strcmp(name, o->name)) {
+			if (!try_module_get(o->owner))
+				o = NULL;
+			rcu_read_unlock();
+			return o;
+		}
+	}
+	rcu_read_unlock();
+
+	return NULL;
+}
+
+/**
+ * textsearch_register - register a textsearch module
+ * @ops: operations lookup table
+ *
+ * This function must be called by textsearch modules to announce
+ * their presence. The specified &@ops must have %name set to a
+ * unique identifier and the callbacks find(), init(), get_pattern(),
+ * and get_pattern_len() must be implemented.
+ *
+ * Returns 0 or -EEXISTS if another module has already registered
+ * with same name.
+ */
+int textsearch_register(struct ts_ops *ops)
+{
+	int err = -EEXIST;
+	struct ts_ops *o;
+
+	if (ops->name == NULL || ops->find == NULL || ops->init == NULL ||
+	    ops->get_pattern == NULL || ops->get_pattern_len == NULL)
+		return -EINVAL;
+
+	spin_lock(&ts_mod_lock);
+	list_for_each_entry(o, &ts_ops, list) {
+		if (!strcmp(ops->name, o->name))
+			goto errout;
+	}
+
+	list_add_tail_rcu(&ops->list, &ts_ops);
+	err = 0;
+errout:
+	spin_unlock(&ts_mod_lock);
+	return err;
+}
+
+/**
+ * textsearch_unregister - unregister a textsearch module
+ * @ops: operations lookup table
+ *
+ * This function must be called by textsearch modules to announce
+ * their disappearance for examples when the module gets unloaded.
+ * The &ops parameter must be the same as the one during the
+ * registration.
+ *
+ * Returns 0 on success or -ENOENT if no matching textsearch
+ * registration was found.
+ */
+int textsearch_unregister(struct ts_ops *ops)
+{
+	int err = 0;
+	struct ts_ops *o;
+
+	spin_lock(&ts_mod_lock);
+	list_for_each_entry(o, &ts_ops, list) {
+		if (o == ops) {
+			list_del_rcu(&o->list);
+			goto out;
+		}
+	}
+
+	err = -ENOENT;
+out:
+	spin_unlock(&ts_mod_lock);
+	return err;
+}
+
+struct ts_linear_state
+{
+	unsigned int	len;
+	const void	*data;
+};
+
+static unsigned int get_linear_data(unsigned int consumed, const u8 **dst,
+				    struct ts_config *conf,
+				    struct ts_state *state)
+{
+	struct ts_linear_state *st = (struct ts_linear_state *) state->cb;
+
+	if (likely(consumed < st->len)) {
+		*dst = st->data + consumed;
+		return st->len - consumed;
+	}
+
+	return 0;
+}
+
+/**
+ * textsearch_find_continuous - search a pattern in continuous/linear data
+ * @conf: search configuration
+ * @state: search state
+ * @data: data to search in
+ * @len: length of data
+ *
+ * A simplified version of textsearch_find() for continuous/linear data.
+ * Call textsearch_next() to retrieve subsequent matches.
+ *
+ * Returns the position of first occurrence of the pattern or
+ * UINT_MAX if no occurrence was found.
+ */ 
+unsigned int textsearch_find_continuous(struct ts_config *conf,
+					struct ts_state *state,
+					const void *data, unsigned int len)
+{
+	struct ts_linear_state *st = (struct ts_linear_state *) state->cb;
+
+	conf->get_next_block = get_linear_data;
+	st->data = data;
+	st->len = len;
+
+	return textsearch_find(conf, state);
+}
+
+/**
+ * textsearch_prepare - Prepare a search
+ * @algo: name of search algorithm
+ * @pattern: pattern data
+ * @len: length of pattern
+ * @gfp_mask: allocation mask
+ * @flags: search flags
+ *
+ * Looks up the search algorithm module and creates a new textsearch
+ * configuration for the specified pattern. Upon completion all
+ * necessary refcnts are held and the configuration must be put back
+ * using textsearch_put() after usage.
+ *
+ * Note: The format of the pattern may not be compatible between
+ *       the various search algorithms.
+ *
+ * Returns a new textsearch configuration according to the specified
+ *         parameters or a ERR_PTR().
+ */
+struct ts_config *textsearch_prepare(const char *algo, const void *pattern,
+				     unsigned int len, int gfp_mask, int flags)
+{
+	int err = -ENOENT;
+	struct ts_config *conf;
+	struct ts_ops *ops;
+	
+	ops = lookup_ts_algo(algo);
+#ifdef CONFIG_KMOD
+	/*
+	 * Why not always autoload you may ask. Some users are
+	 * in a situation where requesting a module may deadlock,
+	 * especially when the module is located on a NFS mount.
+	 */
+	if (ops == NULL && flags & TS_AUTOLOAD) {
+		request_module("ts_%s", algo);
+		ops = lookup_ts_algo(algo);
+	}
+#endif
+
+	if (ops == NULL)
+		goto errout;
+
+	conf = ops->init(pattern, len, gfp_mask);
+	if (IS_ERR(conf)) {
+		err = PTR_ERR(conf);
+		goto errout;
+	}
+
+	conf->ops = ops;
+	return conf;
+
+errout:
+	if (ops)
+		module_put(ops->owner);
+		
+	return ERR_PTR(err);
+}
+
+/**
+ * textsearch_destroy - destroy a search configuration
+ * @conf: search configuration
+ *
+ * Releases all references of the configuration and frees
+ * up the memory.
+ */
+void textsearch_destroy(struct ts_config *conf)
+{
+	if (conf->ops) {
+		if (conf->ops->destroy)
+			conf->ops->destroy(conf);
+		module_put(conf->ops->owner);
+	}
+
+	kfree(conf);
+}
+
+EXPORT_SYMBOL(textsearch_register);
+EXPORT_SYMBOL(textsearch_unregister);
+EXPORT_SYMBOL(textsearch_prepare);
+EXPORT_SYMBOL(textsearch_find_continuous);
+EXPORT_SYMBOL(textsearch_destroy);
diff --git a/lib/ts_fsm.c b/lib/ts_fsm.c
new file mode 100644
index 0000000..d27c0a0
--- /dev/null
+++ b/lib/ts_fsm.c
@@ -0,0 +1,338 @@
+/*
+ * lib/ts_fsm.c	   A naive finite state machine text search approach
+ *
+ *		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.
+ *
+ * Authors:	Thomas Graf <tgraf@suug.ch>
+ *
+ * ==========================================================================
+ *
+ *   A finite state machine consists of n states (struct ts_fsm_token)
+ *   representing the pattern as a finite automation. The data is read
+ *   sequentially on a octet basis. Every state token specifies the number
+ *   of recurrences and the type of value accepted which can be either a
+ *   specific character or ctype based set of characters. The available
+ *   type of recurrences include 1, (0|1), [0 n], and [1 n].
+ *
+ *   The algorithm differs between strict/non-strict mode specyfing
+ *   whether the pattern has to start at the first octect. Strict mode
+ *   is enabled by default and can be disabled by inserting
+ *   TS_FSM_HEAD_IGNORE as the first token in the chain.
+ *
+ *   The runtime performance of the algorithm should be around O(n),
+ *   however while in strict mode the average runtime can be better.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/textsearch.h>
+#include <linux/textsearch_fsm.h>
+
+struct ts_fsm
+{
+	unsigned int		ntokens;
+	struct ts_fsm_token	tokens[0];
+};
+
+/* other values derived from ctype.h */
+#define _A		0x100 /* ascii */
+#define _W		0x200 /* wildcard */
+
+/* Map to _ctype flags and some magic numbers */
+static u16 token_map[TS_FSM_TYPE_MAX+1] = {
+	[TS_FSM_SPECIFIC] = 0,
+	[TS_FSM_WILDCARD] = _W,
+	[TS_FSM_CNTRL]	  = _C,
+	[TS_FSM_LOWER]	  = _L,
+	[TS_FSM_UPPER]	  = _U,
+	[TS_FSM_PUNCT]	  = _P,
+	[TS_FSM_SPACE]	  = _S,
+	[TS_FSM_DIGIT]	  = _D,
+	[TS_FSM_XDIGIT]	  = _D | _X,
+	[TS_FSM_ALPHA]	  = _U | _L,
+	[TS_FSM_ALNUM]	  = _U | _L | _D,
+	[TS_FSM_PRINT]	  = _P | _U | _L | _D | _SP,
+	[TS_FSM_GRAPH]	  = _P | _U | _L | _D,
+	[TS_FSM_ASCII]	  = _A,
+};
+
+static u16 token_lookup_tbl[256] = {
+_W|_A|_C,      _W|_A|_C,     _W|_A|_C,     _W|_A|_C,		/*   0-  3 */
+_W|_A|_C,      _W|_A|_C,     _W|_A|_C,     _W|_A|_C,		/*   4-  7 */
+_W|_A|_C,      _W|_A|_C|_S,  _W|_A|_C|_S,  _W|_A|_C|_S,		/*   8- 11 */
+_W|_A|_C|_S,   _W|_A|_C|_S,  _W|_A|_C,     _W|_A|_C,		/*  12- 15 */
+_W|_A|_C,      _W|_A|_C,     _W|_A|_C,     _W|_A|_C,		/*  16- 19 */
+_W|_A|_C,      _W|_A|_C,     _W|_A|_C,     _W|_A|_C,		/*  20- 23 */
+_W|_A|_C,      _W|_A|_C,     _W|_A|_C,     _W|_A|_C,		/*  24- 27 */
+_W|_A|_C,      _W|_A|_C,     _W|_A|_C,     _W|_A|_C,		/*  28- 31 */
+_W|_A|_S|_SP,  _W|_A|_P,     _W|_A|_P,     _W|_A|_P,		/*  32- 35 */
+_W|_A|_P,      _W|_A|_P,     _W|_A|_P,     _W|_A|_P,		/*  36- 39 */
+_W|_A|_P,      _W|_A|_P,     _W|_A|_P,     _W|_A|_P,		/*  40- 43 */
+_W|_A|_P,      _W|_A|_P,     _W|_A|_P,     _W|_A|_P,		/*  44- 47 */
+_W|_A|_D,      _W|_A|_D,     _W|_A|_D,     _W|_A|_D,		/*  48- 51 */
+_W|_A|_D,      _W|_A|_D,     _W|_A|_D,     _W|_A|_D,		/*  52- 55 */
+_W|_A|_D,      _W|_A|_D,     _W|_A|_P,     _W|_A|_P,		/*  56- 59 */
+_W|_A|_P,      _W|_A|_P,     _W|_A|_P,     _W|_A|_P,		/*  60- 63 */
+_W|_A|_P,      _W|_A|_U|_X,  _W|_A|_U|_X,  _W|_A|_U|_X,		/*  64- 67 */
+_W|_A|_U|_X,   _W|_A|_U|_X,  _W|_A|_U|_X,  _W|_A|_U,		/*  68- 71 */
+_W|_A|_U,      _W|_A|_U,     _W|_A|_U,     _W|_A|_U,		/*  72- 75 */
+_W|_A|_U,      _W|_A|_U,     _W|_A|_U,     _W|_A|_U,		/*  76- 79 */
+_W|_A|_U,      _W|_A|_U,     _W|_A|_U,     _W|_A|_U,		/*  80- 83 */
+_W|_A|_U,      _W|_A|_U,     _W|_A|_U,     _W|_A|_U,		/*  84- 87 */
+_W|_A|_U,      _W|_A|_U,     _W|_A|_U,     _W|_A|_P,		/*  88- 91 */
+_W|_A|_P,      _W|_A|_P,     _W|_A|_P,     _W|_A|_P,		/*  92- 95 */
+_W|_A|_P,      _W|_A|_L|_X,  _W|_A|_L|_X,  _W|_A|_L|_X,		/*  96- 99 */
+_W|_A|_L|_X,   _W|_A|_L|_X,  _W|_A|_L|_X,  _W|_A|_L,		/* 100-103 */
+_W|_A|_L,      _W|_A|_L,     _W|_A|_L,     _W|_A|_L,		/* 104-107 */
+_W|_A|_L,      _W|_A|_L,     _W|_A|_L,     _W|_A|_L,		/* 108-111 */
+_W|_A|_L,      _W|_A|_L,     _W|_A|_L,     _W|_A|_L,		/* 112-115 */
+_W|_A|_L,      _W|_A|_L,     _W|_A|_L,     _W|_A|_L,		/* 116-119 */
+_W|_A|_L,      _W|_A|_L,     _W|_A|_L,     _W|_A|_P,		/* 120-123 */
+_W|_A|_P,      _W|_A|_P,     _W|_A|_P,     _W|_A|_C,		/* 124-127 */
+_W,            _W,           _W,           _W,			/* 128-131 */
+_W,            _W,           _W,           _W,			/* 132-135 */
+_W,            _W,           _W,           _W,			/* 136-139 */
+_W,            _W,           _W,           _W,			/* 140-143 */
+_W,            _W,           _W,           _W,			/* 144-147 */
+_W,            _W,           _W,           _W,			/* 148-151 */
+_W,            _W,           _W,           _W,			/* 152-155 */
+_W,            _W,           _W,           _W,			/* 156-159 */
+_W|_S|_SP,     _W|_P,        _W|_P,        _W|_P,		/* 160-163 */
+_W|_P,         _W|_P,        _W|_P,        _W|_P,		/* 164-167 */
+_W|_P,         _W|_P,        _W|_P,        _W|_P,		/* 168-171 */
+_W|_P,         _W|_P,        _W|_P,        _W|_P,		/* 172-175 */
+_W|_P,         _W|_P,        _W|_P,        _W|_P,		/* 176-179 */
+_W|_P,         _W|_P,        _W|_P,        _W|_P,		/* 180-183 */
+_W|_P,         _W|_P,        _W|_P,        _W|_P,		/* 184-187 */
+_W|_P,         _W|_P,        _W|_P,        _W|_P,		/* 188-191 */
+_W|_U,         _W|_U,        _W|_U,        _W|_U,		/* 192-195 */
+_W|_U,         _W|_U,        _W|_U,        _W|_U,		/* 196-199 */
+_W|_U,         _W|_U,        _W|_U,        _W|_U,		/* 200-203 */
+_W|_U,         _W|_U,        _W|_U,        _W|_U,		/* 204-207 */
+_W|_U,         _W|_U,        _W|_U,        _W|_U,		/* 208-211 */
+_W|_U,         _W|_U,        _W|_U,        _W|_P,		/* 212-215 */
+_W|_U,         _W|_U,        _W|_U,        _W|_U,		/* 216-219 */
+_W|_U,         _W|_U,        _W|_U,        _W|_L,		/* 220-223 */
+_W|_L,         _W|_L,        _W|_L,        _W|_L,		/* 224-227 */
+_W|_L,         _W|_L,        _W|_L,        _W|_L,		/* 228-231 */
+_W|_L,         _W|_L,        _W|_L,        _W|_L,		/* 232-235 */
+_W|_L,         _W|_L,        _W|_L,        _W|_L,		/* 236-239 */
+_W|_L,         _W|_L,        _W|_L,        _W|_L,		/* 240-243 */
+_W|_L,         _W|_L,        _W|_L,        _W|_P,		/* 244-247 */
+_W|_L,         _W|_L,        _W|_L,        _W|_L,		/* 248-251 */
+_W|_L,         _W|_L,        _W|_L,        _W|_L};		/* 252-255 */
+
+static inline int match_token(struct ts_fsm_token *t, u8 d)
+{
+	if (t->type)
+		return (token_lookup_tbl[d] & t->type) != 0;
+	else
+		return t->value == d;
+}
+
+static unsigned int fsm_find(struct ts_config *conf, struct ts_state *state)
+{
+	struct ts_fsm *fsm = ts_config_priv(conf);
+	struct ts_fsm_token *cur = NULL, *next;
+	unsigned int match_start, block_idx = 0, tok_idx;
+	unsigned block_len = 0, strict, consumed = state->offset;
+	const u8 *data;
+
+#define GET_NEXT_BLOCK()		\
+({	consumed += block_idx;		\
+	block_idx = 0;			\
+	block_len = conf->get_next_block(consumed, &data, conf, state); })
+
+#define TOKEN_MISMATCH()		\
+	do {				\
+		if (strict)		\
+			goto no_match;	\
+		block_idx++;		\
+		goto startover;		\
+	} while(0)
+
+#define end_of_data() unlikely(block_idx >= block_len && !GET_NEXT_BLOCK())
+
+	if (end_of_data())
+		goto no_match;
+
+	strict = fsm->tokens[0].recur != TS_FSM_HEAD_IGNORE;
+
+startover:
+	match_start = consumed + block_idx;
+
+	for (tok_idx = 0; tok_idx < fsm->ntokens; tok_idx++) {
+		cur = &fsm->tokens[tok_idx];
+
+		if (likely(tok_idx < (fsm->ntokens - 1)))
+			next = &fsm->tokens[tok_idx + 1];
+		else
+			next = NULL;
+
+		switch (cur->recur) {
+		case TS_FSM_SINGLE:
+			if (end_of_data())
+				goto no_match;
+
+			if (!match_token(cur, data[block_idx]))
+				TOKEN_MISMATCH();
+			break;
+
+		case TS_FSM_PERHAPS:
+			if (end_of_data() ||
+			    !match_token(cur, data[block_idx]))
+				continue;
+			break;
+
+		case TS_FSM_MULTI:
+			if (end_of_data())
+				goto no_match;
+
+			if (!match_token(cur, data[block_idx]))
+				TOKEN_MISMATCH();
+
+			block_idx++;
+			/* fall through */
+
+		case TS_FSM_ANY:
+			if (next == NULL)
+				goto found_match;
+
+			if (end_of_data())
+				continue;
+
+			while (!match_token(next, data[block_idx])) {
+				if (!match_token(cur, data[block_idx]))
+					TOKEN_MISMATCH();
+				block_idx++;
+				if (end_of_data())
+					goto no_match;
+			}
+			continue;
+
+		/*
+		 * Optimization: Prefer small local loop over jumping
+		 * back and forth until garbage at head is munched.
+		 */
+		case TS_FSM_HEAD_IGNORE:
+			if (end_of_data())
+				continue;
+
+			while (!match_token(next, data[block_idx])) {
+				/*
+				 * Special case, don't start over upon
+				 * a mismatch, give the user the
+				 * chance to specify the type of data
+				 * allowed to be ignored.
+				 */
+				if (!match_token(cur, data[block_idx]))
+					goto no_match;
+
+				block_idx++;
+				if (end_of_data())
+					goto no_match;
+			}
+
+			match_start = consumed + block_idx;
+			continue;
+		}
+
+		block_idx++;
+	}
+
+	if (end_of_data())
+		goto found_match;
+
+no_match:
+	return UINT_MAX;
+
+found_match:
+	state->offset = consumed + block_idx;
+	return match_start;
+}
+
+static struct ts_config *fsm_init(const void *pattern, unsigned int len,
+				     int gfp_mask)
+{
+	int i, err = -EINVAL;
+	struct ts_config *conf;
+	struct ts_fsm *fsm;
+	struct ts_fsm_token *tokens = (struct ts_fsm_token *) pattern;
+	unsigned int ntokens = len / sizeof(*tokens);
+	size_t priv_size = sizeof(*fsm) + len;
+
+	if (len  % sizeof(struct ts_fsm_token) || ntokens < 1)
+		goto errout;
+
+	for (i = 0; i < ntokens; i++) {
+		struct ts_fsm_token *t = &tokens[i];
+
+		if (t->type > TS_FSM_TYPE_MAX || t->recur > TS_FSM_RECUR_MAX)
+			goto errout;
+
+		if (t->recur == TS_FSM_HEAD_IGNORE &&
+		    (i != 0 || i == (ntokens - 1)))
+			goto errout;
+	}
+
+	conf = alloc_ts_config(priv_size, gfp_mask);
+	if (IS_ERR(conf))
+		return conf;
+
+	fsm = ts_config_priv(conf);
+	fsm->ntokens = ntokens;
+	memcpy(fsm->tokens, pattern, len);
+
+	for (i = 0; i < fsm->ntokens; i++) {
+		struct ts_fsm_token *t = &fsm->tokens[i];
+		t->type = token_map[t->type];
+	}
+
+	return conf;
+
+errout:
+	return ERR_PTR(err);
+}
+
+static void *fsm_get_pattern(struct ts_config *conf)
+{
+	struct ts_fsm *fsm = ts_config_priv(conf);
+	return fsm->tokens;
+}
+
+static unsigned int fsm_get_pattern_len(struct ts_config *conf)
+{
+	struct ts_fsm *fsm = ts_config_priv(conf);
+	return fsm->ntokens * sizeof(struct ts_fsm_token);
+}
+
+static struct ts_ops fsm_ops = {
+	.name		  = "fsm",
+	.find		  = fsm_find,
+	.init		  = fsm_init,
+	.get_pattern	  = fsm_get_pattern,
+	.get_pattern_len  = fsm_get_pattern_len,
+	.owner		  = THIS_MODULE,
+	.list		  = LIST_HEAD_INIT(fsm_ops.list)
+};
+
+static int __init init_fsm(void)
+{
+	return textsearch_register(&fsm_ops);
+}
+
+static void __exit exit_fsm(void)
+{
+	textsearch_unregister(&fsm_ops);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_fsm);
+module_exit(exit_fsm);
diff --git a/lib/ts_kmp.c b/lib/ts_kmp.c
new file mode 100644
index 0000000..73266b9
--- /dev/null
+++ b/lib/ts_kmp.c
@@ -0,0 +1,145 @@
+/*
+ * lib/ts_kmp.c		Knuth-Morris-Pratt text search implementation
+ *
+ *		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.
+ *
+ * Authors:	Thomas Graf <tgraf@suug.ch>
+ *
+ * ==========================================================================
+ * 
+ *   Implements a linear-time string-matching algorithm due to Knuth,
+ *   Morris, and Pratt [1]. Their algorithm avoids the explicit
+ *   computation of the transition function DELTA altogether. Its
+ *   matching time is O(n), for n being length(text), using just an
+ *   auxiliary function PI[1..m], for m being length(pattern),
+ *   precomputed from the pattern in time O(m). The array PI allows
+ *   the transition function DELTA to be computed efficiently
+ *   "on the fly" as needed. Roughly speaking, for any state
+ *   "q" = 0,1,...,m and any character "a" in SIGMA, the value
+ *   PI["q"] contains the information that is independent of "a" and
+ *   is needed to compute DELTA("q", "a") [2]. Since the array PI
+ *   has only m entries, whereas DELTA has O(m|SIGMA|) entries, we
+ *   save a factor of |SIGMA| in the preprocessing time by computing
+ *   PI rather than DELTA.
+ *
+ *   [1] Cormen, Leiserson, Rivest, Stein
+ *       Introdcution to Algorithms, 2nd Edition, MIT Press
+ *   [2] See finite automation theory
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/textsearch.h>
+
+struct ts_kmp
+{
+	u8 *		pattern;
+	unsigned int	pattern_len;
+	unsigned int 	prefix_tbl[0];
+};
+
+static unsigned int kmp_find(struct ts_config *conf, struct ts_state *state)
+{
+	struct ts_kmp *kmp = ts_config_priv(conf);
+	unsigned int i, q = 0, text_len, consumed = state->offset;
+	const u8 *text;
+
+	for (;;) {
+		text_len = conf->get_next_block(consumed, &text, conf, state);
+
+		if (unlikely(text_len == 0))
+			break;
+
+		for (i = 0; i < text_len; i++) {
+			while (q > 0 && kmp->pattern[q] != text[i])
+				q = kmp->prefix_tbl[q - 1];
+			if (kmp->pattern[q] == text[i])
+				q++;
+			if (unlikely(q == kmp->pattern_len)) {
+				state->offset = consumed + i + 1;
+				return state->offset - kmp->pattern_len;
+			}
+		}
+
+		consumed += text_len;
+	}
+
+	return UINT_MAX;
+}
+
+static inline void compute_prefix_tbl(const u8 *pattern, unsigned int len,
+				      unsigned int *prefix_tbl)
+{
+	unsigned int k, q;
+
+	for (k = 0, q = 1; q < len; q++) {
+		while (k > 0 && pattern[k] != pattern[q])
+			k = prefix_tbl[k-1];
+		if (pattern[k] == pattern[q])
+			k++;
+		prefix_tbl[q] = k;
+	}
+}
+
+static struct ts_config *kmp_init(const void *pattern, unsigned int len,
+				  int gfp_mask)
+{
+	struct ts_config *conf;
+	struct ts_kmp *kmp;
+	unsigned int prefix_tbl_len = len * sizeof(unsigned int);
+	size_t priv_size = sizeof(*kmp) + len + prefix_tbl_len;
+
+	conf = alloc_ts_config(priv_size, gfp_mask);
+	if (IS_ERR(conf))
+		return conf;
+
+	kmp = ts_config_priv(conf);
+	kmp->pattern_len = len;
+	compute_prefix_tbl(pattern, len, kmp->prefix_tbl);
+	kmp->pattern = (u8 *) kmp->prefix_tbl + prefix_tbl_len;
+	memcpy(kmp->pattern, pattern, len);
+
+	return conf;
+}
+
+static void *kmp_get_pattern(struct ts_config *conf)
+{
+	struct ts_kmp *kmp = ts_config_priv(conf);
+	return kmp->pattern;
+}
+
+static unsigned int kmp_get_pattern_len(struct ts_config *conf)
+{
+	struct ts_kmp *kmp = ts_config_priv(conf);
+	return kmp->pattern_len;
+}
+
+static struct ts_ops kmp_ops = {
+	.name		  = "kmp",
+	.find		  = kmp_find,
+	.init		  = kmp_init,
+	.get_pattern	  = kmp_get_pattern,
+	.get_pattern_len  = kmp_get_pattern_len,
+	.owner		  = THIS_MODULE,
+	.list		  = LIST_HEAD_INIT(kmp_ops.list)
+};
+
+static int __init init_kmp(void)
+{
+	return textsearch_register(&kmp_ops);
+}
+
+static void __exit exit_kmp(void)
+{
+	textsearch_unregister(&kmp_ops);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_kmp);
+module_exit(exit_kmp);
diff --git a/mm/Kconfig b/mm/Kconfig
new file mode 100644
index 0000000..cd37993
--- /dev/null
+++ b/mm/Kconfig
@@ -0,0 +1,91 @@
+config SELECT_MEMORY_MODEL
+	def_bool y
+	depends on EXPERIMENTAL || ARCH_SELECT_MEMORY_MODEL
+
+choice
+	prompt "Memory model"
+	depends on SELECT_MEMORY_MODEL
+	default DISCONTIGMEM_MANUAL if ARCH_DISCONTIGMEM_DEFAULT
+	default SPARSEMEM_MANUAL if ARCH_SPARSEMEM_DEFAULT
+	default FLATMEM_MANUAL
+
+config FLATMEM_MANUAL
+	bool "Flat Memory"
+	depends on !ARCH_DISCONTIGMEM_ENABLE || ARCH_FLATMEM_ENABLE
+	help
+	  This option allows you to change some of the ways that
+	  Linux manages its memory internally.  Most users will
+	  only have one option here: FLATMEM.  This is normal
+	  and a correct option.
+
+	  Some users of more advanced features like NUMA and
+	  memory hotplug may have different options here.
+	  DISCONTIGMEM is an more mature, better tested system,
+	  but is incompatible with memory hotplug and may suffer
+	  decreased performance over SPARSEMEM.  If unsure between
+	  "Sparse Memory" and "Discontiguous Memory", choose
+	  "Discontiguous Memory".
+
+	  If unsure, choose this option (Flat Memory) over any other.
+
+config DISCONTIGMEM_MANUAL
+	bool "Discontigious Memory"
+	depends on ARCH_DISCONTIGMEM_ENABLE
+	help
+	  This option provides enhanced support for discontiguous
+	  memory systems, over FLATMEM.  These systems have holes
+	  in their physical address spaces, and this option provides
+	  more efficient handling of these holes.  However, the vast
+	  majority of hardware has quite flat address spaces, and
+	  can have degraded performance from extra overhead that
+	  this option imposes.
+
+	  Many NUMA configurations will have this as the only option.
+
+	  If unsure, choose "Flat Memory" over this option.
+
+config SPARSEMEM_MANUAL
+	bool "Sparse Memory"
+	depends on ARCH_SPARSEMEM_ENABLE
+	help
+	  This will be the only option for some systems, including
+	  memory hotplug systems.  This is normal.
+
+	  For many other systems, this will be an alternative to
+	  "Discontigious Memory".  This option provides some potential
+	  performance benefits, along with decreased code complexity,
+	  but it is newer, and more experimental.
+
+	  If unsure, choose "Discontiguous Memory" or "Flat Memory"
+	  over this option.
+
+endchoice
+
+config DISCONTIGMEM
+	def_bool y
+	depends on (!SELECT_MEMORY_MODEL && ARCH_DISCONTIGMEM_ENABLE) || DISCONTIGMEM_MANUAL
+
+config SPARSEMEM
+	def_bool y
+	depends on SPARSEMEM_MANUAL
+
+config FLATMEM
+	def_bool y
+	depends on (!DISCONTIGMEM && !SPARSEMEM) || FLATMEM_MANUAL
+
+config FLAT_NODE_MEM_MAP
+	def_bool y
+	depends on !SPARSEMEM
+
+#
+# Both the NUMA code and DISCONTIGMEM use arrays of pg_data_t's
+# to represent different areas of memory.  This variable allows
+# those dependencies to exist individually.
+#
+config NEED_MULTIPLE_NODES
+	def_bool y
+	depends on DISCONTIGMEM || NUMA
+
+config HAVE_MEMORY_PRESENT
+	def_bool y
+	depends on ARCH_HAVE_MEMORY_PRESENT || SPARSEMEM
diff --git a/mm/Makefile b/mm/Makefile
index 0974080..4cd69e3 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -15,6 +15,8 @@
 obj-$(CONFIG_SWAP)	+= page_io.o swap_state.o swapfile.o thrash.o
 obj-$(CONFIG_HUGETLBFS)	+= hugetlb.o
 obj-$(CONFIG_NUMA) 	+= mempolicy.o
+obj-$(CONFIG_SPARSEMEM)	+= sparse.o
 obj-$(CONFIG_SHMEM) += shmem.o
 obj-$(CONFIG_TINY_SHMEM) += tiny-shmem.o
 
+obj-$(CONFIG_FS_XIP) += filemap_xip.o
diff --git a/mm/bootmem.c b/mm/bootmem.c
index 260e703..c1330cc 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -33,6 +33,14 @@
 				 * dma_get_required_mask(), which uses
 				 * it, can be an inline function */
 
+#ifdef CONFIG_CRASH_DUMP
+/*
+ * If we have booted due to a crash, max_pfn will be a very low value. We need
+ * to know the amount of memory that the previous kernel used.
+ */
+unsigned long saved_max_pfn;
+#endif
+
 /* return the number of _pages_ that will be allocated for the boot bitmap */
 unsigned long __init bootmem_bootmap_pages (unsigned long pages)
 {
@@ -57,7 +65,7 @@
 	pgdat->pgdat_next = pgdat_list;
 	pgdat_list = pgdat;
 
-	mapsize = (mapsize + (sizeof(long) - 1UL)) & ~(sizeof(long) - 1UL);
+	mapsize = ALIGN(mapsize, sizeof(long));
 	bdata->node_bootmem_map = phys_to_virt(mapstart << PAGE_SHIFT);
 	bdata->node_boot_start = (start << PAGE_SHIFT);
 	bdata->node_low_pfn = end;
@@ -178,7 +186,7 @@
 	} else
 		preferred = 0;
 
-	preferred = ((preferred + align - 1) & ~(align - 1)) >> PAGE_SHIFT;
+	preferred = ALIGN(preferred, align) >> PAGE_SHIFT;
 	preferred += offset;
 	areasize = (size+PAGE_SIZE-1)/PAGE_SIZE;
 	incr = align >> PAGE_SHIFT ? : 1;
@@ -219,7 +227,7 @@
 	 */
 	if (align < PAGE_SIZE &&
 	    bdata->last_offset && bdata->last_pos+1 == start) {
-		offset = (bdata->last_offset+align-1) & ~(align-1);
+		offset = ALIGN(bdata->last_offset, align);
 		BUG_ON(offset > PAGE_SIZE);
 		remaining_size = PAGE_SIZE-offset;
 		if (size < remaining_size) {
@@ -256,6 +264,7 @@
 static unsigned long __init free_all_bootmem_core(pg_data_t *pgdat)
 {
 	struct page *page;
+	unsigned long pfn;
 	bootmem_data_t *bdata = pgdat->bdata;
 	unsigned long i, count, total = 0;
 	unsigned long idx;
@@ -266,7 +275,7 @@
 
 	count = 0;
 	/* first extant page of the node */
-	page = virt_to_page(phys_to_virt(bdata->node_boot_start));
+	pfn = bdata->node_boot_start >> PAGE_SHIFT;
 	idx = bdata->node_low_pfn - (bdata->node_boot_start >> PAGE_SHIFT);
 	map = bdata->node_bootmem_map;
 	/* Check physaddr is O(LOG2(BITS_PER_LONG)) page aligned */
@@ -275,9 +284,11 @@
 		gofast = 1;
 	for (i = 0; i < idx; ) {
 		unsigned long v = ~map[i / BITS_PER_LONG];
+
 		if (gofast && v == ~0UL) {
 			int j, order;
 
+			page = pfn_to_page(pfn);
 			count += BITS_PER_LONG;
 			__ClearPageReserved(page);
 			order = ffs(BITS_PER_LONG) - 1;
@@ -292,6 +303,8 @@
 			page += BITS_PER_LONG;
 		} else if (v) {
 			unsigned long m;
+
+			page = pfn_to_page(pfn);
 			for (m = 1; m && i < idx; m<<=1, page++, i++) {
 				if (v & m) {
 					count++;
@@ -302,8 +315,8 @@
 			}
 		} else {
 			i+=BITS_PER_LONG;
-			page += BITS_PER_LONG;
 		}
+		pfn += BITS_PER_LONG;
 	}
 	total += count;
 
diff --git a/mm/fadvise.c b/mm/fadvise.c
index 57264d7..5f19e87 100644
--- a/mm/fadvise.c
+++ b/mm/fadvise.c
@@ -43,6 +43,10 @@
 		goto out;
 	}
 
+	if (mapping->a_ops->get_xip_page)
+		/* no bad return value, but ignore advice */
+		goto out;
+
 	/* Careful about overflows. Len == 0 means "as much as possible" */
 	endbyte = offset + len;
 	if (!len || endbyte < len)
diff --git a/mm/filemap.c b/mm/filemap.c
index 1d33fec..c11418d 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -28,6 +28,7 @@
 #include <linux/blkdev.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
+#include "filemap.h"
 /*
  * FIXME: remove all knowledge of the buffer layer from the core VM
  */
@@ -1714,32 +1715,7 @@
 }
 EXPORT_SYMBOL(remove_suid);
 
-/*
- * 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.
- */
-static inline size_t
-filemap_copy_from_user(struct page *page, unsigned long offset,
-			const char __user *buf, unsigned bytes)
-{
-	char *kaddr;
-	int left;
-
-	kaddr = kmap_atomic(page, KM_USER0);
-	left = __copy_from_user_inatomic(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);
-		kunmap(page);
-	}
-	return bytes - left;
-}
-
-static size_t
+size_t
 __filemap_copy_from_user_iovec(char *vaddr, 
 			const struct iovec *iov, size_t base, size_t bytes)
 {
@@ -1767,52 +1743,6 @@
 }
 
 /*
- * This has the same sideeffects and return value as filemap_copy_from_user().
- * The difference is that on a fault we need to memset the remainder of the
- * page (out to offset+bytes), to emulate filemap_copy_from_user()'s
- * single-segment behaviour.
- */
-static inline size_t
-filemap_copy_from_user_iovec(struct page *page, unsigned long offset,
-			const struct iovec *iov, size_t base, size_t bytes)
-{
-	char *kaddr;
-	size_t copied;
-
-	kaddr = kmap_atomic(page, KM_USER0);
-	copied = __filemap_copy_from_user_iovec(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);
-		kunmap(page);
-	}
-	return copied;
-}
-
-static inline void
-filemap_set_next_iovec(const struct iovec **iovp, size_t *basep, size_t bytes)
-{
-	const struct iovec *iov = *iovp;
-	size_t base = *basep;
-
-	while (bytes) {
-		int copy = min(bytes, iov->iov_len - base);
-
-		bytes -= copy;
-		base += copy;
-		if (iov->iov_len == base) {
-			iov++;
-			base = 0;
-		}
-	}
-	*iovp = iov;
-	*basep = base;
-}
-
-/*
  * Performs necessary checks before doing a write
  *
  * Can adjust writing position aor amount of bytes to write.
@@ -1827,12 +1757,6 @@
         if (unlikely(*pos < 0))
                 return -EINVAL;
 
-        if (unlikely(file->f_error)) {
-                int err = file->f_error;
-                file->f_error = 0;
-                return err;
-        }
-
 	if (!isblk) {
 		/* FIXME: this is for backwards compatibility with 2.4 */
 		if (file->f_flags & O_APPEND)
@@ -1927,8 +1851,11 @@
 	 * i_sem is held, which protects generic_osync_inode() from
 	 * livelocking.
 	 */
-	if (written >= 0 && file->f_flags & O_SYNC)
-		generic_osync_inode(inode, mapping, OSYNC_METADATA);
+	if (written >= 0 && ((file->f_flags & O_SYNC) || IS_SYNC(inode))) {
+		int err = generic_osync_inode(inode, mapping, OSYNC_METADATA);
+		if (err < 0)
+			written = err;
+	}
 	if (written == count && !is_sync_kiocb(iocb))
 		written = -EIOCBQUEUED;
 	return written;
@@ -1968,6 +1895,7 @@
 	do {
 		unsigned long index;
 		unsigned long offset;
+		unsigned long maxlen;
 		size_t copied;
 
 		offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
@@ -1982,7 +1910,10 @@
 		 * same page as we're writing to, without it being marked
 		 * up-to-date.
 		 */
-		fault_in_pages_readable(buf, bytes);
+		maxlen = cur_iov->iov_len - iov_base;
+		if (maxlen > bytes)
+			maxlen = bytes;
+		fault_in_pages_readable(buf, maxlen);
 
 		page = __grab_cache_page(mapping,index,&cached_page,&lru_pvec);
 		if (!page) {
@@ -2023,7 +1954,11 @@
 				if (unlikely(nr_segs > 1)) {
 					filemap_set_next_iovec(&cur_iov,
 							&iov_base, status);
-					buf = cur_iov->iov_base + iov_base;
+					if (count)
+						buf = cur_iov->iov_base +
+							iov_base;
+				} else {
+					iov_base += status;
 				}
 			}
 		}
diff --git a/mm/filemap.h b/mm/filemap.h
new file mode 100644
index 0000000..13793ba
--- /dev/null
+++ b/mm/filemap.h
@@ -0,0 +1,94 @@
+/*
+ *	linux/mm/filemap.h
+ *
+ * Copyright (C) 1994-1999  Linus Torvalds
+ */
+
+#ifndef __FILEMAP_H
+#define __FILEMAP_H
+
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/highmem.h>
+#include <linux/uio.h>
+#include <linux/config.h>
+#include <asm/uaccess.h>
+
+size_t
+__filemap_copy_from_user_iovec(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.
+ */
+static inline size_t
+filemap_copy_from_user(struct page *page, unsigned long offset,
+			const char __user *buf, unsigned bytes)
+{
+	char *kaddr;
+	int left;
+
+	kaddr = kmap_atomic(page, KM_USER0);
+	left = __copy_from_user_inatomic(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);
+		kunmap(page);
+	}
+	return bytes - left;
+}
+
+/*
+ * This has the same sideeffects and return value as filemap_copy_from_user().
+ * The difference is that on a fault we need to memset the remainder of the
+ * page (out to offset+bytes), to emulate filemap_copy_from_user()'s
+ * single-segment behaviour.
+ */
+static inline size_t
+filemap_copy_from_user_iovec(struct page *page, unsigned long offset,
+			const struct iovec *iov, size_t base, size_t bytes)
+{
+	char *kaddr;
+	size_t copied;
+
+	kaddr = kmap_atomic(page, KM_USER0);
+	copied = __filemap_copy_from_user_iovec(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);
+		kunmap(page);
+	}
+	return copied;
+}
+
+static inline void
+filemap_set_next_iovec(const struct iovec **iovp, size_t *basep, size_t bytes)
+{
+	const struct iovec *iov = *iovp;
+	size_t base = *basep;
+
+	while (bytes) {
+		int copy = min(bytes, iov->iov_len - base);
+
+		bytes -= copy;
+		base += copy;
+		if (iov->iov_len == base) {
+			iov++;
+			base = 0;
+		}
+	}
+	*iovp = iov;
+	*basep = base;
+}
+#endif
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
new file mode 100644
index 0000000..3b6e384
--- /dev/null
+++ b/mm/filemap_xip.c
@@ -0,0 +1,447 @@
+/*
+ *	linux/mm/filemap_xip.c
+ *
+ * Copyright (C) 2005 IBM Corporation
+ * Author: Carsten Otte <cotte@de.ibm.com>
+ *
+ * derived from linux/mm/filemap.c - Copyright (C) Linus Torvalds
+ *
+ */
+
+#include <linux/fs.h>
+#include <linux/pagemap.h>
+#include <linux/module.h>
+#include <linux/uio.h>
+#include <linux/rmap.h>
+#include <asm/tlbflush.h>
+#include "filemap.h"
+
+/*
+ * This is a file read routine for execute in place files, and uses
+ * the mapping->a_ops->get_xip_page() function for the actual low-level
+ * stuff.
+ *
+ * Note the struct file* is not used at all.  It may be NULL.
+ */
+static void
+do_xip_mapping_read(struct address_space *mapping,
+		    struct file_ra_state *_ra,
+		    struct file *filp,
+		    loff_t *ppos,
+		    read_descriptor_t *desc,
+		    read_actor_t actor)
+{
+	struct inode *inode = mapping->host;
+	unsigned long index, end_index, offset;
+	loff_t isize;
+
+	BUG_ON(!mapping->a_ops->get_xip_page);
+
+	index = *ppos >> PAGE_CACHE_SHIFT;
+	offset = *ppos & ~PAGE_CACHE_MASK;
+
+	isize = i_size_read(inode);
+	if (!isize)
+		goto out;
+
+	end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
+	for (;;) {
+		struct page *page;
+		unsigned long nr, ret;
+
+		/* nr is the maximum number of bytes to copy from this page */
+		nr = PAGE_CACHE_SIZE;
+		if (index >= end_index) {
+			if (index > end_index)
+				goto out;
+			nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
+			if (nr <= offset) {
+				goto out;
+			}
+		}
+		nr = nr - offset;
+
+		page = mapping->a_ops->get_xip_page(mapping,
+			index*(PAGE_SIZE/512), 0);
+		if (!page)
+			goto no_xip_page;
+		if (unlikely(IS_ERR(page))) {
+			if (PTR_ERR(page) == -ENODATA) {
+				/* sparse */
+				page = virt_to_page(empty_zero_page);
+			} else {
+				desc->error = PTR_ERR(page);
+				goto out;
+			}
+		} else
+			BUG_ON(!PageUptodate(page));
+
+		/* If users can be writing to this page using arbitrary
+		 * virtual addresses, take care about potential aliasing
+		 * before reading the page on the kernel side.
+		 */
+		if (mapping_writably_mapped(mapping))
+			flush_dcache_page(page);
+
+		/*
+		 * Ok, we have the page, and it's up-to-date, so
+		 * now we can copy it to user space...
+		 *
+		 * The actor routine returns how many bytes were actually used..
+		 * NOTE! This may not be the same as how much of a user buffer
+		 * we filled up (we may be padding etc), so we can only update
+		 * "pos" here (the actor routine has to update the user buffer
+		 * pointers and the remaining count).
+		 */
+		ret = actor(desc, page, offset, nr);
+		offset += ret;
+		index += offset >> PAGE_CACHE_SHIFT;
+		offset &= ~PAGE_CACHE_MASK;
+
+		if (ret == nr && desc->count)
+			continue;
+		goto out;
+
+no_xip_page:
+		/* Did not get the page. Report it */
+		desc->error = -EIO;
+		goto out;
+	}
+
+out:
+	*ppos = ((loff_t) index << PAGE_CACHE_SHIFT) + offset;
+	if (filp)
+		file_accessed(filp);
+}
+
+ssize_t
+xip_file_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos)
+{
+	read_descriptor_t desc;
+
+	if (!access_ok(VERIFY_WRITE, buf, len))
+		return -EFAULT;
+
+	desc.written = 0;
+	desc.arg.buf = buf;
+	desc.count = len;
+	desc.error = 0;
+
+	do_xip_mapping_read(filp->f_mapping, &filp->f_ra, filp,
+			    ppos, &desc, file_read_actor);
+
+	if (desc.written)
+		return desc.written;
+	else
+		return desc.error;
+}
+EXPORT_SYMBOL_GPL(xip_file_read);
+
+ssize_t
+xip_file_sendfile(struct file *in_file, loff_t *ppos,
+	     size_t count, read_actor_t actor, void *target)
+{
+	read_descriptor_t desc;
+
+	if (!count)
+		return 0;
+
+	desc.written = 0;
+	desc.count = count;
+	desc.arg.data = target;
+	desc.error = 0;
+
+	do_xip_mapping_read(in_file->f_mapping, &in_file->f_ra, in_file,
+			    ppos, &desc, actor);
+	if (desc.written)
+		return desc.written;
+	return desc.error;
+}
+EXPORT_SYMBOL_GPL(xip_file_sendfile);
+
+/*
+ * __xip_unmap is invoked from xip_unmap and
+ * xip_write
+ *
+ * This function walks all vmas of the address_space and unmaps the
+ * empty_zero_page when found at pgoff. Should it go in rmap.c?
+ */
+static void
+__xip_unmap (struct address_space * mapping,
+		     unsigned long pgoff)
+{
+	struct vm_area_struct *vma;
+	struct mm_struct *mm;
+	struct prio_tree_iter iter;
+	unsigned long address;
+	pte_t *pte;
+	pte_t pteval;
+
+	spin_lock(&mapping->i_mmap_lock);
+	vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) {
+		mm = vma->vm_mm;
+		address = vma->vm_start +
+			((pgoff - vma->vm_pgoff) << PAGE_SHIFT);
+		BUG_ON(address < vma->vm_start || address >= vma->vm_end);
+		/*
+		 * We need the page_table_lock to protect us from page faults,
+		 * munmap, fork, etc...
+		 */
+		pte = page_check_address(virt_to_page(empty_zero_page), mm,
+					 address);
+		if (!IS_ERR(pte)) {
+			/* Nuke the page table entry. */
+			flush_cache_page(vma, address, pte_pfn(pte));
+			pteval = ptep_clear_flush(vma, address, pte);
+			BUG_ON(pte_dirty(pteval));
+			pte_unmap(pte);
+			spin_unlock(&mm->page_table_lock);
+		}
+	}
+	spin_unlock(&mapping->i_mmap_lock);
+}
+
+/*
+ * xip_nopage() is invoked via the vma operations vector for a
+ * mapped memory region to read in file data during a page fault.
+ *
+ * This function is derived from filemap_nopage, but used for execute in place
+ */
+static struct page *
+xip_file_nopage(struct vm_area_struct * area,
+		   unsigned long address,
+		   int *type)
+{
+	struct file *file = area->vm_file;
+	struct address_space *mapping = file->f_mapping;
+	struct inode *inode = mapping->host;
+	struct page *page;
+	unsigned long size, pgoff, endoff;
+
+	pgoff = ((address - area->vm_start) >> PAGE_CACHE_SHIFT)
+		+ area->vm_pgoff;
+	endoff = ((area->vm_end - area->vm_start) >> PAGE_CACHE_SHIFT)
+		+ area->vm_pgoff;
+
+	size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+	if (pgoff >= size) {
+		return NULL;
+	}
+
+	page = mapping->a_ops->get_xip_page(mapping, pgoff*(PAGE_SIZE/512), 0);
+	if (!IS_ERR(page)) {
+		BUG_ON(!PageUptodate(page));
+		return page;
+	}
+	if (PTR_ERR(page) != -ENODATA)
+		return NULL;
+
+	/* sparse block */
+	if ((area->vm_flags & (VM_WRITE | VM_MAYWRITE)) &&
+	    (area->vm_flags & (VM_SHARED| VM_MAYSHARE)) &&
+	    (!(mapping->host->i_sb->s_flags & MS_RDONLY))) {
+		/* maybe shared writable, allocate new block */
+		page = mapping->a_ops->get_xip_page (mapping,
+			pgoff*(PAGE_SIZE/512), 1);
+		if (IS_ERR(page))
+			return NULL;
+		BUG_ON(!PageUptodate(page));
+		/* unmap page at pgoff from all other vmas */
+		__xip_unmap(mapping, pgoff);
+	} else {
+		/* not shared and writable, use empty_zero_page */
+		page = virt_to_page(empty_zero_page);
+	}
+
+	return page;
+}
+
+static struct vm_operations_struct xip_file_vm_ops = {
+	.nopage         = xip_file_nopage,
+};
+
+int xip_file_mmap(struct file * file, struct vm_area_struct * vma)
+{
+	BUG_ON(!file->f_mapping->a_ops->get_xip_page);
+
+	file_accessed(file);
+	vma->vm_ops = &xip_file_vm_ops;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(xip_file_mmap);
+
+static ssize_t
+__xip_file_write(struct file *filp, const char __user *buf,
+		  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;
+	struct inode 	*inode = mapping->host;
+	long		status = 0;
+	struct page	*page;
+	size_t		bytes;
+	ssize_t		written = 0;
+
+	BUG_ON(!mapping->a_ops->get_xip_page);
+
+	do {
+		unsigned long index;
+		unsigned long offset;
+		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;
+
+		/*
+		 * Bring in the user page that we will copy from _first_.
+		 * Otherwise there's a nasty deadlock on copying from the
+		 * same page as we're writing to, without it being marked
+		 * up-to-date.
+		 */
+		fault_in_pages_readable(buf, bytes);
+
+		page = a_ops->get_xip_page(mapping,
+					   index*(PAGE_SIZE/512), 0);
+		if (IS_ERR(page) && (PTR_ERR(page) == -ENODATA)) {
+			/* we allocate a new page unmap it */
+			page = a_ops->get_xip_page(mapping,
+						   index*(PAGE_SIZE/512), 1);
+			if (!IS_ERR(page))
+				/* unmap page at pgoff from all other vmas */
+				__xip_unmap(mapping, index);
+		}
+
+		if (IS_ERR(page)) {
+			status = PTR_ERR(page);
+			break;
+		}
+
+		BUG_ON(!PageUptodate(page));
+
+		copied = filemap_copy_from_user(page, offset, buf, bytes);
+		flush_dcache_page(page);
+		if (likely(copied > 0)) {
+			status = copied;
+
+			if (status >= 0) {
+				written += status;
+				count -= status;
+				pos += status;
+				buf += status;
+			}
+		}
+		if (unlikely(copied != bytes))
+			if (status >= 0)
+				status = -EFAULT;
+		if (status < 0)
+			break;
+	} while (count);
+	*ppos = pos;
+	/*
+	 * No need to use i_size_read() here, the i_size
+	 * cannot change under us because we hold i_sem.
+	 */
+	if (pos > inode->i_size) {
+		i_size_write(inode, pos);
+		mark_inode_dirty(inode);
+	}
+
+	return written ? written : status;
+}
+
+ssize_t
+xip_file_write(struct file *filp, const char __user *buf, size_t len,
+	       loff_t *ppos)
+{
+	struct address_space *mapping = filp->f_mapping;
+	struct inode *inode = mapping->host;
+	size_t count;
+	loff_t pos;
+	ssize_t ret;
+
+	down(&inode->i_sem);
+
+	if (!access_ok(VERIFY_READ, buf, len)) {
+		ret=-EFAULT;
+		goto out_up;
+	}
+
+	pos = *ppos;
+	count = len;
+
+	vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE);
+
+	/* We can write back this queue in page reclaim */
+	current->backing_dev_info = mapping->backing_dev_info;
+
+	ret = generic_write_checks(filp, &pos, &count, S_ISBLK(inode->i_mode));
+	if (ret)
+		goto out_backing;
+	if (count == 0)
+		goto out_backing;
+
+	ret = remove_suid(filp->f_dentry);
+	if (ret)
+		goto out_backing;
+
+	inode_update_time(inode, 1);
+
+	ret = __xip_file_write (filp, buf, count, pos, ppos);
+
+ out_backing:
+	current->backing_dev_info = NULL;
+ out_up:
+	up(&inode->i_sem);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(xip_file_write);
+
+/*
+ * truncate a page used for execute in place
+ * functionality is analog to block_truncate_page but does use get_xip_page
+ * to get the page instead of page cache
+ */
+int
+xip_truncate_page(struct address_space *mapping, loff_t from)
+{
+	pgoff_t index = from >> PAGE_CACHE_SHIFT;
+	unsigned offset = from & (PAGE_CACHE_SIZE-1);
+	unsigned blocksize;
+	unsigned length;
+	struct page *page;
+	void *kaddr;
+
+	BUG_ON(!mapping->a_ops->get_xip_page);
+
+	blocksize = 1 << mapping->host->i_blkbits;
+	length = offset & (blocksize - 1);
+
+	/* Block boundary? Nothing to do */
+	if (!length)
+		return 0;
+
+	length = blocksize - length;
+
+	page = mapping->a_ops->get_xip_page(mapping,
+					    index*(PAGE_SIZE/512), 0);
+	if (!page)
+		return -ENOMEM;
+	if (unlikely(IS_ERR(page))) {
+		if (PTR_ERR(page) == -ENODATA)
+			/* Hole? No need to truncate */
+			return 0;
+		else
+			return PTR_ERR(page);
+	} else
+		BUG_ON(!PageUptodate(page));
+	kaddr = kmap_atomic(page, KM_USER0);
+	memset(kaddr + offset, 0, length);
+	kunmap_atomic(kaddr, KM_USER0);
+
+	flush_dcache_page(page);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(xip_truncate_page);
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 4eb5ae3..fbd1111 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -7,10 +7,14 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/mm.h>
-#include <linux/hugetlb.h>
 #include <linux/sysctl.h>
 #include <linux/highmem.h>
 #include <linux/nodemask.h>
+#include <linux/pagemap.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#include <linux/hugetlb.h>
 
 const unsigned long hugetlb_zero = 0, hugetlb_infinity = ~0UL;
 static unsigned long nr_huge_pages, free_huge_pages;
@@ -249,6 +253,72 @@
 	.nopage = hugetlb_nopage,
 };
 
+static pte_t make_huge_pte(struct vm_area_struct *vma, struct page *page)
+{
+	pte_t entry;
+
+	if (vma->vm_flags & VM_WRITE) {
+		entry =
+		    pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
+	} else {
+		entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot));
+	}
+	entry = pte_mkyoung(entry);
+	entry = pte_mkhuge(entry);
+
+	return entry;
+}
+
+int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
+			    struct vm_area_struct *vma)
+{
+	pte_t *src_pte, *dst_pte, entry;
+	struct page *ptepage;
+	unsigned long addr = vma->vm_start;
+	unsigned long end = vma->vm_end;
+
+	while (addr < end) {
+		dst_pte = huge_pte_alloc(dst, addr);
+		if (!dst_pte)
+			goto nomem;
+		src_pte = huge_pte_offset(src, addr);
+		BUG_ON(!src_pte || pte_none(*src_pte)); /* prefaulted */
+		entry = *src_pte;
+		ptepage = pte_page(entry);
+		get_page(ptepage);
+		add_mm_counter(dst, rss, HPAGE_SIZE / PAGE_SIZE);
+		set_huge_pte_at(dst, addr, dst_pte, entry);
+		addr += HPAGE_SIZE;
+	}
+	return 0;
+
+nomem:
+	return -ENOMEM;
+}
+
+void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
+			  unsigned long end)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	unsigned long address;
+	pte_t pte;
+	struct page *page;
+
+	WARN_ON(!is_vm_hugetlb_page(vma));
+	BUG_ON(start & ~HPAGE_MASK);
+	BUG_ON(end & ~HPAGE_MASK);
+
+	for (address = start; address < end; address += HPAGE_SIZE) {
+		pte = huge_ptep_get_and_clear(mm, address, huge_pte_offset(mm, address));
+		if (pte_none(pte))
+			continue;
+		page = pte_page(pte);
+		put_page(page);
+	}
+	add_mm_counter(mm, rss,  -((end - start) >> PAGE_SHIFT));
+	flush_tlb_range(vma, start, end);
+}
+
 void zap_hugepage_range(struct vm_area_struct *vma,
 			unsigned long start, unsigned long length)
 {
@@ -258,3 +328,108 @@
 	unmap_hugepage_range(vma, start, start + length);
 	spin_unlock(&mm->page_table_lock);
 }
+
+int hugetlb_prefault(struct address_space *mapping, struct vm_area_struct *vma)
+{
+	struct mm_struct *mm = current->mm;
+	unsigned long addr;
+	int ret = 0;
+
+	WARN_ON(!is_vm_hugetlb_page(vma));
+	BUG_ON(vma->vm_start & ~HPAGE_MASK);
+	BUG_ON(vma->vm_end & ~HPAGE_MASK);
+
+	hugetlb_prefault_arch_hook(mm);
+
+	spin_lock(&mm->page_table_lock);
+	for (addr = vma->vm_start; addr < vma->vm_end; addr += HPAGE_SIZE) {
+		unsigned long idx;
+		pte_t *pte = huge_pte_alloc(mm, addr);
+		struct page *page;
+
+		if (!pte) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		if (! pte_none(*pte))
+			hugetlb_clean_stale_pgtable(pte);
+
+		idx = ((addr - vma->vm_start) >> HPAGE_SHIFT)
+			+ (vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT));
+		page = find_get_page(mapping, idx);
+		if (!page) {
+			/* charge the fs quota first */
+			if (hugetlb_get_quota(mapping)) {
+				ret = -ENOMEM;
+				goto out;
+			}
+			page = alloc_huge_page();
+			if (!page) {
+				hugetlb_put_quota(mapping);
+				ret = -ENOMEM;
+				goto out;
+			}
+			ret = add_to_page_cache(page, mapping, idx, GFP_ATOMIC);
+			if (! ret) {
+				unlock_page(page);
+			} else {
+				hugetlb_put_quota(mapping);
+				free_huge_page(page);
+				goto out;
+			}
+		}
+		add_mm_counter(mm, rss, HPAGE_SIZE / PAGE_SIZE);
+		set_huge_pte_at(mm, addr, pte, make_huge_pte(vma, page));
+	}
+out:
+	spin_unlock(&mm->page_table_lock);
+	return ret;
+}
+
+int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
+			struct page **pages, struct vm_area_struct **vmas,
+			unsigned long *position, int *length, int i)
+{
+	unsigned long vpfn, vaddr = *position;
+	int remainder = *length;
+
+	BUG_ON(!is_vm_hugetlb_page(vma));
+
+	vpfn = vaddr/PAGE_SIZE;
+	while (vaddr < vma->vm_end && remainder) {
+
+		if (pages) {
+			pte_t *pte;
+			struct page *page;
+
+			/* Some archs (sparc64, sh*) have multiple
+			 * pte_ts to each hugepage.  We have to make
+			 * sure we get the first, for the page
+			 * indexing below to work. */
+			pte = huge_pte_offset(mm, vaddr & HPAGE_MASK);
+
+			/* hugetlb should be locked, and hence, prefaulted */
+			WARN_ON(!pte || pte_none(*pte));
+
+			page = &pte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)];
+
+			WARN_ON(!PageCompound(page));
+
+			get_page(page);
+			pages[i] = page;
+		}
+
+		if (vmas)
+			vmas[i] = vma;
+
+		vaddr += PAGE_SIZE;
+		++vpfn;
+		--remainder;
+		++i;
+	}
+
+	*length = remainder;
+	*position = vaddr;
+
+	return i;
+}
diff --git a/mm/madvise.c b/mm/madvise.c
index 944b5e5..73180a2 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -8,17 +8,47 @@
 #include <linux/mman.h>
 #include <linux/pagemap.h>
 #include <linux/syscalls.h>
+#include <linux/mempolicy.h>
 #include <linux/hugetlb.h>
 
 /*
  * We can potentially split a vm area into separate
  * areas, each area with its own behavior.
  */
-static long madvise_behavior(struct vm_area_struct * vma, unsigned long start,
-			     unsigned long end, int behavior)
+static long madvise_behavior(struct vm_area_struct * vma,
+		     struct vm_area_struct **prev,
+		     unsigned long start, unsigned long end, int behavior)
 {
 	struct mm_struct * mm = vma->vm_mm;
 	int error = 0;
+	pgoff_t pgoff;
+	int new_flags = vma->vm_flags & ~VM_READHINTMASK;
+
+	switch (behavior) {
+	case MADV_SEQUENTIAL:
+		new_flags |= VM_SEQ_READ;
+		break;
+	case MADV_RANDOM:
+		new_flags |= VM_RAND_READ;
+		break;
+	default:
+		break;
+	}
+
+	if (new_flags == vma->vm_flags) {
+		*prev = vma;
+		goto success;
+	}
+
+	pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
+	*prev = vma_merge(mm, *prev, start, end, new_flags, vma->anon_vma,
+				vma->vm_file, pgoff, vma_policy(vma));
+	if (*prev) {
+		vma = *prev;
+		goto success;
+	}
+
+	*prev = vma;
 
 	if (start != vma->vm_start) {
 		error = split_vma(mm, vma, start, 1);
@@ -35,22 +65,12 @@
 	/*
 	 * vm_flags is protected by the mmap_sem held in write mode.
 	 */
-	VM_ClearReadHint(vma);
-
-	switch (behavior) {
-	case MADV_SEQUENTIAL:
-		vma->vm_flags |= VM_SEQ_READ;
-		break;
-	case MADV_RANDOM:
-		vma->vm_flags |= VM_RAND_READ;
-		break;
-	default:
-		break;
-	}
+	vma->vm_flags = new_flags;
 
 out:
 	if (error == -ENOMEM)
 		error = -EAGAIN;
+success:
 	return error;
 }
 
@@ -58,6 +78,7 @@
  * Schedule all required I/O operations.  Do not wait for completion.
  */
 static long madvise_willneed(struct vm_area_struct * vma,
+			     struct vm_area_struct ** prev,
 			     unsigned long start, unsigned long end)
 {
 	struct file *file = vma->vm_file;
@@ -65,6 +86,12 @@
 	if (!file)
 		return -EBADF;
 
+	if (file->f_mapping->a_ops->get_xip_page) {
+		/* no bad return value, but ignore advice */
+		return 0;
+	}
+
+	*prev = vma;
 	start = ((start - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
 	if (end > vma->vm_end)
 		end = vma->vm_end;
@@ -95,8 +122,10 @@
  * dirty pages is already available as msync(MS_INVALIDATE).
  */
 static long madvise_dontneed(struct vm_area_struct * vma,
+			     struct vm_area_struct ** prev,
 			     unsigned long start, unsigned long end)
 {
+	*prev = vma;
 	if ((vma->vm_flags & VM_LOCKED) || is_vm_hugetlb_page(vma))
 		return -EINVAL;
 
@@ -111,8 +140,8 @@
 	return 0;
 }
 
-static long madvise_vma(struct vm_area_struct * vma, unsigned long start,
-			unsigned long end, int behavior)
+static long madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev,
+			unsigned long start, unsigned long end, int behavior)
 {
 	long error = -EBADF;
 
@@ -120,15 +149,15 @@
 	case MADV_NORMAL:
 	case MADV_SEQUENTIAL:
 	case MADV_RANDOM:
-		error = madvise_behavior(vma, start, end, behavior);
+		error = madvise_behavior(vma, prev, start, end, behavior);
 		break;
 
 	case MADV_WILLNEED:
-		error = madvise_willneed(vma, start, end);
+		error = madvise_willneed(vma, prev, start, end);
 		break;
 
 	case MADV_DONTNEED:
-		error = madvise_dontneed(vma, start, end);
+		error = madvise_dontneed(vma, prev, start, end);
 		break;
 
 	default:
@@ -175,8 +204,8 @@
  */
 asmlinkage long sys_madvise(unsigned long start, size_t len_in, int behavior)
 {
-	unsigned long end;
-	struct vm_area_struct * vma;
+	unsigned long end, tmp;
+	struct vm_area_struct * vma, *prev;
 	int unmapped_error = 0;
 	int error = -EINVAL;
 	size_t len;
@@ -202,40 +231,42 @@
 	/*
 	 * If the interval [start,end) covers some unmapped address
 	 * ranges, just ignore them, but return -ENOMEM at the end.
+	 * - different from the way of handling in mlock etc.
 	 */
-	vma = find_vma(current->mm, start);
+	vma = find_vma_prev(current->mm, start, &prev);
+	if (!vma && prev)
+		vma = prev->vm_next;
 	for (;;) {
 		/* Still start < end. */
 		error = -ENOMEM;
 		if (!vma)
 			goto out;
 
-		/* Here start < vma->vm_end. */
+		/* Here start < (end|vma->vm_end). */
 		if (start < vma->vm_start) {
 			unmapped_error = -ENOMEM;
 			start = vma->vm_start;
+			if (start >= end)
+				goto out;
 		}
 
-		/* Here vma->vm_start <= start < vma->vm_end. */
-		if (end <= vma->vm_end) {
-			if (start < end) {
-				error = madvise_vma(vma, start, end,
-							behavior);
-				if (error)
-					goto out;
-			}
-			error = unmapped_error;
-			goto out;
-		}
+		/* Here vma->vm_start <= start < (end|vma->vm_end) */
+		tmp = vma->vm_end;
+		if (end < tmp)
+			tmp = end;
 
-		/* Here vma->vm_start <= start < vma->vm_end < end. */
-		error = madvise_vma(vma, start, vma->vm_end, behavior);
+		/* Here vma->vm_start <= start < tmp <= (end|vma->vm_end). */
+		error = madvise_vma(vma, &prev, start, tmp, behavior);
 		if (error)
 			goto out;
-		start = vma->vm_end;
-		vma = vma->vm_next;
+		start = tmp;
+		if (start < prev->vm_end)
+			start = prev->vm_end;
+		error = unmapped_error;
+		if (start >= end)
+			goto out;
+		vma = prev->vm_next;
 	}
-
 out:
 	up_write(&current->mm->mmap_sem);
 	return error;
diff --git a/mm/memory.c b/mm/memory.c
index d209f74..beabdef 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -58,7 +58,7 @@
 #include <linux/swapops.h>
 #include <linux/elf.h>
 
-#ifndef CONFIG_DISCONTIGMEM
+#ifndef CONFIG_NEED_MULTIPLE_NODES
 /* use the per-pgdat data instead for discontigmem - mbligh */
 unsigned long max_mapnr;
 struct page *mem_map;
@@ -840,23 +840,8 @@
 {
 	return __follow_page(mm, address, /*read*/1, /*write*/0) != NULL;
 }
-
 EXPORT_SYMBOL(check_user_page_readable);
 
-/* 
- * Given a physical address, is there a useful struct page pointing to
- * it?  This may become more complex in the future if we start dealing
- * with IO-aperture pages for direct-IO.
- */
-
-static inline struct page *get_page_map(struct page *page)
-{
-	if (!pfn_valid(page_to_pfn(page)))
-		return NULL;
-	return page;
-}
-
-
 static inline int
 untouched_anonymous_page(struct mm_struct* mm, struct vm_area_struct *vma,
 			 unsigned long address)
@@ -887,7 +872,6 @@
 	return 0;
 }
 
-
 int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
 		unsigned long start, int len, int write, int force,
 		struct page **pages, struct vm_area_struct **vmas)
@@ -951,21 +935,21 @@
 		}
 		spin_lock(&mm->page_table_lock);
 		do {
-			struct page *map;
+			struct page *page;
 			int lookup_write = write;
 
 			cond_resched_lock(&mm->page_table_lock);
-			while (!(map = follow_page(mm, start, lookup_write))) {
+			while (!(page = follow_page(mm, start, lookup_write))) {
 				/*
 				 * Shortcut for anonymous pages. We don't want
 				 * to force the creation of pages tables for
-				 * insanly big anonymously mapped areas that
+				 * insanely big anonymously mapped areas that
 				 * nobody touched so far. This is important
 				 * for doing a core dump for these mappings.
 				 */
 				if (!lookup_write &&
 				    untouched_anonymous_page(mm,vma,start)) {
-					map = ZERO_PAGE(start);
+					page = ZERO_PAGE(start);
 					break;
 				}
 				spin_unlock(&mm->page_table_lock);
@@ -994,30 +978,21 @@
 				spin_lock(&mm->page_table_lock);
 			}
 			if (pages) {
-				pages[i] = get_page_map(map);
-				if (!pages[i]) {
-					spin_unlock(&mm->page_table_lock);
-					while (i--)
-						page_cache_release(pages[i]);
-					i = -EFAULT;
-					goto out;
-				}
-				flush_dcache_page(pages[i]);
-				if (!PageReserved(pages[i]))
-					page_cache_get(pages[i]);
+				pages[i] = page;
+				flush_dcache_page(page);
+				if (!PageReserved(page))
+					page_cache_get(page);
 			}
 			if (vmas)
 				vmas[i] = vma;
 			i++;
 			start += PAGE_SIZE;
 			len--;
-		} while(len && start < vma->vm_end);
+		} while (len && start < vma->vm_end);
 		spin_unlock(&mm->page_table_lock);
-	} while(len);
-out:
+	} while (len);
 	return i;
 }
-
 EXPORT_SYMBOL(get_user_pages);
 
 static int zeromap_pte_range(struct mm_struct *mm, pmd_t *pmd,
@@ -1164,7 +1139,7 @@
 {
 	pgd_t *pgd;
 	unsigned long next;
-	unsigned long end = addr + size;
+	unsigned long end = addr + PAGE_ALIGN(size);
 	struct mm_struct *mm = vma->vm_mm;
 	int err;
 
@@ -1264,7 +1239,7 @@
 	}
 	old_page = pfn_to_page(pfn);
 
-	if (!TestSetPageLocked(old_page)) {
+	if (PageAnon(old_page) && !TestSetPageLocked(old_page)) {
 		int reuse = can_share_swap_page(old_page);
 		unlock_page(old_page);
 		if (reuse) {
@@ -1483,7 +1458,7 @@
  * unmap_mapping_range - unmap the portion of all mmaps
  * in the specified address_space corresponding to the specified
  * page range in the underlying file.
- * @address_space: the address space containing mmaps to be unmapped.
+ * @mapping: the address space containing mmaps to be unmapped.
  * @holebegin: byte in first page to unmap, relative to the start of
  * the underlying file.  This will be rounded down to a PAGE_SIZE
  * boundary.  Note that this is different from vmtruncate(), which
@@ -1711,10 +1686,6 @@
 	}
 
 	/* The page isn't present yet, go ahead with the fault. */
-		
-	swap_free(entry);
-	if (vm_swap_full())
-		remove_exclusive_swap_page(page);
 
 	inc_mm_counter(mm, rss);
 	pte = mk_pte(page, vma->vm_page_prot);
@@ -1722,12 +1693,16 @@
 		pte = maybe_mkwrite(pte_mkdirty(pte), vma);
 		write_access = 0;
 	}
-	unlock_page(page);
 
 	flush_icache_page(vma, page);
 	set_pte_at(mm, address, page_table, pte);
 	page_add_anon_rmap(page, vma, address);
 
+	swap_free(entry);
+	if (vm_swap_full())
+		remove_exclusive_swap_page(page);
+	unlock_page(page);
+
 	if (write_access) {
 		if (do_wp_page(mm, vma, address,
 				page_table, pmd, pte) == VM_FAULT_OOM)
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 08c41da..cb41c31 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -238,46 +238,80 @@
 }
 
 /* Ensure all existing pages follow the policy. */
-static int
-verify_pages(struct mm_struct *mm,
-	     unsigned long addr, unsigned long end, unsigned long *nodes)
+static int check_pte_range(struct mm_struct *mm, pmd_t *pmd,
+		unsigned long addr, unsigned long end, unsigned long *nodes)
 {
-	while (addr < end) {
-		struct page *p;
-		pte_t *pte;
-		pmd_t *pmd;
-		pud_t *pud;
-		pgd_t *pgd;
-		pgd = pgd_offset(mm, addr);
-		if (pgd_none(*pgd)) {
-			unsigned long next = (addr + PGDIR_SIZE) & PGDIR_MASK;
-			if (next > addr)
-				break;
-			addr = next;
+	pte_t *orig_pte;
+	pte_t *pte;
+
+	spin_lock(&mm->page_table_lock);
+	orig_pte = pte = pte_offset_map(pmd, addr);
+	do {
+		unsigned long pfn;
+		unsigned int nid;
+
+		if (!pte_present(*pte))
 			continue;
-		}
-		pud = pud_offset(pgd, addr);
-		if (pud_none(*pud)) {
-			addr = (addr + PUD_SIZE) & PUD_MASK;
+		pfn = pte_pfn(*pte);
+		if (!pfn_valid(pfn))
 			continue;
-		}
-		pmd = pmd_offset(pud, addr);
-		if (pmd_none(*pmd)) {
-			addr = (addr + PMD_SIZE) & PMD_MASK;
+		nid = pfn_to_nid(pfn);
+		if (!test_bit(nid, nodes))
+			break;
+	} while (pte++, addr += PAGE_SIZE, addr != end);
+	pte_unmap(orig_pte);
+	spin_unlock(&mm->page_table_lock);
+	return addr != end;
+}
+
+static inline int check_pmd_range(struct mm_struct *mm, pud_t *pud,
+		unsigned long addr, unsigned long end, unsigned long *nodes)
+{
+	pmd_t *pmd;
+	unsigned long next;
+
+	pmd = pmd_offset(pud, addr);
+	do {
+		next = pmd_addr_end(addr, end);
+		if (pmd_none_or_clear_bad(pmd))
 			continue;
-		}
-		p = NULL;
-		pte = pte_offset_map(pmd, addr);
-		if (pte_present(*pte))
-			p = pte_page(*pte);
-		pte_unmap(pte);
-		if (p) {
-			unsigned nid = page_to_nid(p);
-			if (!test_bit(nid, nodes))
-				return -EIO;
-		}
-		addr += PAGE_SIZE;
-	}
+		if (check_pte_range(mm, pmd, addr, next, nodes))
+			return -EIO;
+	} while (pmd++, addr = next, addr != end);
+	return 0;
+}
+
+static inline int check_pud_range(struct mm_struct *mm, pgd_t *pgd,
+		unsigned long addr, unsigned long end, unsigned long *nodes)
+{
+	pud_t *pud;
+	unsigned long next;
+
+	pud = pud_offset(pgd, addr);
+	do {
+		next = pud_addr_end(addr, end);
+		if (pud_none_or_clear_bad(pud))
+			continue;
+		if (check_pmd_range(mm, pud, addr, next, nodes))
+			return -EIO;
+	} while (pud++, addr = next, addr != end);
+	return 0;
+}
+
+static inline int check_pgd_range(struct mm_struct *mm,
+		unsigned long addr, unsigned long end, unsigned long *nodes)
+{
+	pgd_t *pgd;
+	unsigned long next;
+
+	pgd = pgd_offset(mm, addr);
+	do {
+		next = pgd_addr_end(addr, end);
+		if (pgd_none_or_clear_bad(pgd))
+			continue;
+		if (check_pud_range(mm, pgd, addr, next, nodes))
+			return -EIO;
+	} while (pgd++, addr = next, addr != end);
 	return 0;
 }
 
@@ -299,7 +333,7 @@
 		if (prev && prev->vm_end < vma->vm_start)
 			return ERR_PTR(-EFAULT);
 		if ((flags & MPOL_MF_STRICT) && !is_vm_hugetlb_page(vma)) {
-			err = verify_pages(vma->vm_mm,
+			err = check_pgd_range(vma->vm_mm,
 					   vma->vm_start, vma->vm_end, nodes);
 			if (err) {
 				first = ERR_PTR(err);
@@ -721,7 +755,7 @@
 	zl = NODE_DATA(nid)->node_zonelists + (gfp & GFP_ZONEMASK);
 	page = __alloc_pages(gfp, order, zl);
 	if (page && page_zone(page) == zl->zones[0]) {
-		zl->zones[0]->pageset[get_cpu()].interleave_hit++;
+		zone_pcp(zl->zones[0],get_cpu())->interleave_hit++;
 		put_cpu();
 	}
 	return page;
diff --git a/mm/mempool.c b/mm/mempool.c
index c9f3d46..9a72f7d 100644
--- a/mm/mempool.c
+++ b/mm/mempool.c
@@ -51,16 +51,23 @@
  * functions might sleep - as long as the mempool_alloc function is not called
  * from IRQ contexts.
  */
-mempool_t * mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
+mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn,
 				mempool_free_t *free_fn, void *pool_data)
 {
-	mempool_t *pool;
+	return  mempool_create_node(min_nr,alloc_fn,free_fn, pool_data,-1);
+}
+EXPORT_SYMBOL(mempool_create);
 
-	pool = kmalloc(sizeof(*pool), GFP_KERNEL);
+mempool_t *mempool_create_node(int min_nr, mempool_alloc_t *alloc_fn,
+			mempool_free_t *free_fn, void *pool_data, int node_id)
+{
+	mempool_t *pool;
+	pool = kmalloc_node(sizeof(*pool), GFP_KERNEL, node_id);
 	if (!pool)
 		return NULL;
 	memset(pool, 0, sizeof(*pool));
-	pool->elements = kmalloc(min_nr * sizeof(void *), GFP_KERNEL);
+	pool->elements = kmalloc_node(min_nr * sizeof(void *),
+					GFP_KERNEL, node_id);
 	if (!pool->elements) {
 		kfree(pool);
 		return NULL;
@@ -87,7 +94,7 @@
 	}
 	return pool;
 }
-EXPORT_SYMBOL(mempool_create);
+EXPORT_SYMBOL(mempool_create_node);
 
 /**
  * mempool_resize - resize an existing memory pool
@@ -197,7 +204,7 @@
 {
 	void *element;
 	unsigned long flags;
-	DEFINE_WAIT(wait);
+	wait_queue_t wait;
 	int gfp_temp;
 
 	might_sleep_if(gfp_mask & __GFP_WAIT);
@@ -228,6 +235,7 @@
 
 	/* Now start performing page reclaim */
 	gfp_temp = gfp_mask;
+	init_wait(&wait);
 	prepare_to_wait(&pool->wait, &wait, TASK_UNINTERRUPTIBLE);
 	smp_mb();
 	if (!pool->curr_nr)
diff --git a/mm/mmap.c b/mm/mmap.c
index de54acd..da3fa90 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1175,7 +1175,12 @@
 		    (!vma || addr + len <= vma->vm_start))
 			return addr;
 	}
-	start_addr = addr = mm->free_area_cache;
+	if (len > mm->cached_hole_size) {
+	        start_addr = addr = mm->free_area_cache;
+	} else {
+	        start_addr = addr = TASK_UNMAPPED_BASE;
+	        mm->cached_hole_size = 0;
+	}
 
 full_search:
 	for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
@@ -1186,7 +1191,9 @@
 			 * some holes.
 			 */
 			if (start_addr != TASK_UNMAPPED_BASE) {
-				start_addr = addr = TASK_UNMAPPED_BASE;
+				addr = TASK_UNMAPPED_BASE;
+			        start_addr = addr;
+				mm->cached_hole_size = 0;
 				goto full_search;
 			}
 			return -ENOMEM;
@@ -1198,19 +1205,22 @@
 			mm->free_area_cache = addr + len;
 			return addr;
 		}
+		if (addr + mm->cached_hole_size < vma->vm_start)
+		        mm->cached_hole_size = vma->vm_start - addr;
 		addr = vma->vm_end;
 	}
 }
 #endif	
 
-void arch_unmap_area(struct vm_area_struct *area)
+void arch_unmap_area(struct mm_struct *mm, unsigned long addr)
 {
 	/*
 	 * Is this a new hole at the lowest possible address?
 	 */
-	if (area->vm_start >= TASK_UNMAPPED_BASE &&
-			area->vm_start < area->vm_mm->free_area_cache)
-		area->vm_mm->free_area_cache = area->vm_start;
+	if (addr >= TASK_UNMAPPED_BASE && addr < mm->free_area_cache) {
+		mm->free_area_cache = addr;
+		mm->cached_hole_size = ~0UL;
+	}
 }
 
 /*
@@ -1240,6 +1250,12 @@
 			return addr;
 	}
 
+	/* check if free_area_cache is useful for us */
+	if (len <= mm->cached_hole_size) {
+ 	        mm->cached_hole_size = 0;
+ 		mm->free_area_cache = mm->mmap_base;
+ 	}
+
 	/* either no address requested or can't fit in requested address hole */
 	addr = mm->free_area_cache;
 
@@ -1251,6 +1267,9 @@
 			return (mm->free_area_cache = addr-len);
 	}
 
+	if (mm->mmap_base < len)
+		goto bottomup;
+
 	addr = mm->mmap_base-len;
 
 	do {
@@ -1264,38 +1283,45 @@
 			/* remember the address as a hint for next time */
 			return (mm->free_area_cache = addr);
 
+ 		/* remember the largest hole we saw so far */
+ 		if (addr + mm->cached_hole_size < vma->vm_start)
+ 		        mm->cached_hole_size = vma->vm_start - addr;
+
 		/* try just below the current vma->vm_start */
 		addr = vma->vm_start-len;
 	} while (len < vma->vm_start);
 
+bottomup:
 	/*
 	 * A failed mmap() very likely causes application failure,
 	 * so fall back to the bottom-up function here. This scenario
 	 * can happen with large stack limits and large mmap()
 	 * allocations.
 	 */
-	mm->free_area_cache = TASK_UNMAPPED_BASE;
+	mm->cached_hole_size = ~0UL;
+  	mm->free_area_cache = TASK_UNMAPPED_BASE;
 	addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
 	/*
 	 * Restore the topdown base:
 	 */
 	mm->free_area_cache = mm->mmap_base;
+	mm->cached_hole_size = ~0UL;
 
 	return addr;
 }
 #endif
 
-void arch_unmap_area_topdown(struct vm_area_struct *area)
+void arch_unmap_area_topdown(struct mm_struct *mm, unsigned long addr)
 {
 	/*
 	 * Is this a new hole at the highest possible address?
 	 */
-	if (area->vm_end > area->vm_mm->free_area_cache)
-		area->vm_mm->free_area_cache = area->vm_end;
+	if (addr > mm->free_area_cache)
+		mm->free_area_cache = addr;
 
 	/* dont allow allocations above current base */
-	if (area->vm_mm->free_area_cache > area->vm_mm->mmap_base)
-		area->vm_mm->free_area_cache = area->vm_mm->mmap_base;
+	if (mm->free_area_cache > mm->mmap_base)
+		mm->free_area_cache = mm->mmap_base;
 }
 
 unsigned long
@@ -1595,7 +1621,6 @@
 	if (area->vm_flags & VM_LOCKED)
 		area->vm_mm->locked_vm -= len >> PAGE_SHIFT;
 	vm_stat_unaccount(area);
-	area->vm_mm->unmap_area(area);
 	remove_vm_struct(area);
 }
 
@@ -1649,6 +1674,7 @@
 {
 	struct vm_area_struct **insertion_point;
 	struct vm_area_struct *tail_vma = NULL;
+	unsigned long addr;
 
 	insertion_point = (prev ? &prev->vm_next : &mm->mmap);
 	do {
@@ -1659,6 +1685,11 @@
 	} while (vma && vma->vm_start < end);
 	*insertion_point = vma;
 	tail_vma->vm_next = NULL;
+	if (mm->unmap_area == arch_unmap_area)
+		addr = prev ? prev->vm_end : mm->mmap_base;
+	else
+		addr = vma ?  vma->vm_start : mm->mmap_base;
+	mm->unmap_area(mm, addr);
 	mm->mmap_cache = NULL;		/* Kill the cache. */
 }
 
diff --git a/mm/msync.c b/mm/msync.c
index 090f426..d0f5a1b 100644
--- a/mm/msync.c
+++ b/mm/msync.c
@@ -34,6 +34,8 @@
 
 		if (!pte_present(*pte))
 			continue;
+		if (!pte_maybe_dirty(*pte))
+			continue;
 		pfn = pte_pfn(*pte);
 		if (!pfn_valid(pfn))
 			continue;
diff --git a/mm/nommu.c b/mm/nommu.c
index c53e9c8..ce74452 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1067,7 +1067,7 @@
 	return -ENOMEM;
 }
 
-void arch_unmap_area(struct vm_area_struct *area)
+void arch_unmap_area(struct mm_struct *mm, unsigned long addr)
 {
 }
 
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 4bbb1cb..59666d9 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -258,6 +258,10 @@
 	struct mm_struct *mm = NULL;
 	task_t * p;
 
+	printk("oom-killer: gfp_mask=0x%x\n", gfp_mask);
+	/* print memory stats */
+	show_mem();
+
 	read_lock(&tasklist_lock);
 retry:
 	p = select_bad_process();
@@ -268,12 +272,9 @@
 	/* Found nothing?!?! Either we hang forever, or we panic. */
 	if (!p) {
 		read_unlock(&tasklist_lock);
-		show_free_areas();
 		panic("Out of memory and no killable processes...\n");
 	}
 
-	printk("oom-killer: gfp_mask=0x%x\n", gfp_mask);
-	show_free_areas();
 	mm = oom_kill_process(p);
 	if (!mm)
 		goto retry;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index b1061b1..7ee675a 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -68,7 +68,7 @@
  * Used by page_zone() to look up the address of the struct zone whose
  * id is encoded in the upper bits of page->flags
  */
-struct zone *zone_table[1 << (ZONES_SHIFT + NODES_SHIFT)];
+struct zone *zone_table[1 << ZONETABLE_SHIFT];
 EXPORT_SYMBOL(zone_table);
 
 static char *zone_names[MAX_NR_ZONES] = { "DMA", "Normal", "HighMem" };
@@ -105,11 +105,13 @@
 	printk(KERN_EMERG "Backtrace:\n");
 	dump_stack();
 	printk(KERN_EMERG "Trying to fix it up, but a reboot is needed\n");
-	page->flags &= ~(1 << PG_private	|
+	page->flags &= ~(1 << PG_lru	|
+			1 << PG_private |
 			1 << PG_locked	|
-			1 << PG_lru	|
 			1 << PG_active	|
 			1 << PG_dirty	|
+			1 << PG_reclaim |
+			1 << PG_slab    |
 			1 << PG_swapcache |
 			1 << PG_writeback);
 	set_page_count(page, 0);
@@ -440,14 +442,17 @@
  */
 static void prep_new_page(struct page *page, int order)
 {
-	if (page->mapping || page_mapcount(page) ||
-	    (page->flags & (
+	if (	page_mapcount(page) ||
+		page->mapping != NULL ||
+		page_count(page) != 0 ||
+		(page->flags & (
+			1 << PG_lru	|
 			1 << PG_private	|
 			1 << PG_locked	|
-			1 << PG_lru	|
 			1 << PG_active	|
 			1 << PG_dirty	|
 			1 << PG_reclaim	|
+			1 << PG_slab    |
 			1 << PG_swapcache |
 			1 << PG_writeback )))
 		bad_page(__FUNCTION__, page);
@@ -511,6 +516,36 @@
 	return allocated;
 }
 
+#ifdef CONFIG_NUMA
+/* Called from the slab reaper to drain remote pagesets */
+void drain_remote_pages(void)
+{
+	struct zone *zone;
+	int i;
+	unsigned long flags;
+
+	local_irq_save(flags);
+	for_each_zone(zone) {
+		struct per_cpu_pageset *pset;
+
+		/* Do not drain local pagesets */
+		if (zone->zone_pgdat->node_id == numa_node_id())
+			continue;
+
+		pset = zone->pageset[smp_processor_id()];
+		for (i = 0; i < ARRAY_SIZE(pset->pcp); i++) {
+			struct per_cpu_pages *pcp;
+
+			pcp = &pset->pcp[i];
+			if (pcp->count)
+				pcp->count -= free_pages_bulk(zone, pcp->count,
+						&pcp->list, 0);
+		}
+	}
+	local_irq_restore(flags);
+}
+#endif
+
 #if defined(CONFIG_PM) || defined(CONFIG_HOTPLUG_CPU)
 static void __drain_pages(unsigned int cpu)
 {
@@ -520,7 +555,7 @@
 	for_each_zone(zone) {
 		struct per_cpu_pageset *pset;
 
-		pset = &zone->pageset[cpu];
+		pset = zone_pcp(zone, cpu);
 		for (i = 0; i < ARRAY_SIZE(pset->pcp); i++) {
 			struct per_cpu_pages *pcp;
 
@@ -583,12 +618,12 @@
 
 	local_irq_save(flags);
 	cpu = smp_processor_id();
-	p = &z->pageset[cpu];
+	p = zone_pcp(z,cpu);
 	if (pg == orig) {
-		z->pageset[cpu].numa_hit++;
+		p->numa_hit++;
 	} else {
 		p->numa_miss++;
-		zonelist->zones[0]->pageset[cpu].numa_foreign++;
+		zone_pcp(zonelist->zones[0], cpu)->numa_foreign++;
 	}
 	if (pg == NODE_DATA(numa_node_id()))
 		p->local_node++;
@@ -615,12 +650,12 @@
 	if (PageAnon(page))
 		page->mapping = NULL;
 	free_pages_check(__FUNCTION__, page);
-	pcp = &zone->pageset[get_cpu()].pcp[cold];
+	pcp = &zone_pcp(zone, get_cpu())->pcp[cold];
 	local_irq_save(flags);
-	if (pcp->count >= pcp->high)
-		pcp->count -= free_pages_bulk(zone, pcp->batch, &pcp->list, 0);
 	list_add(&page->lru, &pcp->list);
 	pcp->count++;
+	if (pcp->count >= pcp->high)
+		pcp->count -= free_pages_bulk(zone, pcp->batch, &pcp->list, 0);
 	local_irq_restore(flags);
 	put_cpu();
 }
@@ -659,7 +694,7 @@
 	if (order == 0) {
 		struct per_cpu_pages *pcp;
 
-		pcp = &zone->pageset[get_cpu()].pcp[cold];
+		pcp = &zone_pcp(zone, get_cpu())->pcp[cold];
 		local_irq_save(flags);
 		if (pcp->count <= pcp->low)
 			pcp->count += rmqueue_bulk(zone, 0,
@@ -724,6 +759,16 @@
 	return 1;
 }
 
+static inline int
+should_reclaim_zone(struct zone *z, unsigned int gfp_mask)
+{
+	if (!z->reclaim_pages)
+		return 0;
+	if (gfp_mask & __GFP_NORECLAIM)
+		return 0;
+	return 1;
+}
+
 /*
  * This is the 'heart' of the zoned buddy allocator.
  */
@@ -760,17 +805,32 @@
 
 	classzone_idx = zone_idx(zones[0]);
 
- restart:
+restart:
 	/* Go through the zonelist once, looking for a zone with enough free */
 	for (i = 0; (z = zones[i]) != NULL; i++) {
-
-		if (!zone_watermark_ok(z, order, z->pages_low,
-				       classzone_idx, 0, 0))
-			continue;
+		int do_reclaim = should_reclaim_zone(z, gfp_mask);
 
 		if (!cpuset_zone_allowed(z))
 			continue;
 
+		/*
+		 * If the zone is to attempt early page reclaim then this loop
+		 * will try to reclaim pages and check the watermark a second
+		 * time before giving up and falling back to the next zone.
+		 */
+zone_reclaim_retry:
+		if (!zone_watermark_ok(z, order, z->pages_low,
+				       classzone_idx, 0, 0)) {
+			if (!do_reclaim)
+				continue;
+			else {
+				zone_reclaim(z, gfp_mask, order);
+				/* Only try reclaim once */
+				do_reclaim = 0;
+				goto zone_reclaim_retry;
+			}
+		}
+
 		page = buffered_rmqueue(z, order, gfp_mask);
 		if (page)
 			goto got_pg;
@@ -829,7 +889,7 @@
 	reclaim_state.reclaimed_slab = 0;
 	p->reclaim_state = &reclaim_state;
 
-	did_some_progress = try_to_free_pages(zones, gfp_mask, order);
+	did_some_progress = try_to_free_pages(zones, gfp_mask);
 
 	p->reclaim_state = NULL;
 	p->flags &= ~PF_MEMALLOC;
@@ -905,6 +965,7 @@
 			" order:%d, mode:0x%x\n",
 			p->comm, order, gfp_mask);
 		dump_stack();
+		show_mem();
 	}
 	return NULL;
 got_pg:
@@ -1114,7 +1175,7 @@
 	__get_page_state(ret, sizeof(*ret) / sizeof(unsigned long));
 }
 
-unsigned long __read_page_state(unsigned offset)
+unsigned long __read_page_state(unsigned long offset)
 {
 	unsigned long ret = 0;
 	int cpu;
@@ -1128,7 +1189,7 @@
 	return ret;
 }
 
-void __mod_page_state(unsigned offset, unsigned long delta)
+void __mod_page_state(unsigned long offset, unsigned long delta)
 {
 	unsigned long flags;
 	void* ptr;
@@ -1237,22 +1298,23 @@
 			if (!cpu_possible(cpu))
 				continue;
 
-			pageset = zone->pageset + cpu;
+			pageset = zone_pcp(zone, cpu);
 
 			for (temperature = 0; temperature < 2; temperature++)
-				printk("cpu %d %s: low %d, high %d, batch %d\n",
+				printk("cpu %d %s: low %d, high %d, batch %d used:%d\n",
 					cpu,
 					temperature ? "cold" : "hot",
 					pageset->pcp[temperature].low,
 					pageset->pcp[temperature].high,
-					pageset->pcp[temperature].batch);
+					pageset->pcp[temperature].batch,
+					pageset->pcp[temperature].count);
 		}
 	}
 
 	get_page_state(&ps);
 	get_zone_counts(&active, &inactive, &free);
 
-	printk("\nFree pages: %11ukB (%ukB HighMem)\n",
+	printk("Free pages: %11ukB (%ukB HighMem)\n",
 		K(nr_free_pages()),
 		K(nr_free_highpages()));
 
@@ -1587,11 +1649,17 @@
 void __init memmap_init_zone(unsigned long size, int nid, unsigned long zone,
 		unsigned long start_pfn)
 {
-	struct page *start = pfn_to_page(start_pfn);
 	struct page *page;
+	unsigned long end_pfn = start_pfn + size;
+	unsigned long pfn;
 
-	for (page = start; page < (start + size); page++) {
-		set_page_zone(page, NODEZONE(nid, zone));
+	for (pfn = start_pfn; pfn < end_pfn; pfn++, page++) {
+		if (!early_pfn_valid(pfn))
+			continue;
+		if (!early_pfn_in_nid(pfn, nid))
+			continue;
+		page = pfn_to_page(pfn);
+		set_page_links(page, zone, nid, pfn);
 		set_page_count(page, 0);
 		reset_page_mapcount(page);
 		SetPageReserved(page);
@@ -1615,11 +1683,181 @@
 	}
 }
 
+#define ZONETABLE_INDEX(x, zone_nr)	((x << ZONES_SHIFT) | zone_nr)
+void zonetable_add(struct zone *zone, int nid, int zid, unsigned long pfn,
+		unsigned long size)
+{
+	unsigned long snum = pfn_to_section_nr(pfn);
+	unsigned long end = pfn_to_section_nr(pfn + size);
+
+	if (FLAGS_HAS_NODE)
+		zone_table[ZONETABLE_INDEX(nid, zid)] = zone;
+	else
+		for (; snum <= end; snum++)
+			zone_table[ZONETABLE_INDEX(snum, zid)] = zone;
+}
+
 #ifndef __HAVE_ARCH_MEMMAP_INIT
 #define memmap_init(size, nid, zone, start_pfn) \
 	memmap_init_zone((size), (nid), (zone), (start_pfn))
 #endif
 
+static int __devinit zone_batchsize(struct zone *zone)
+{
+	int batch;
+
+	/*
+	 * The per-cpu-pages pools are set to around 1000th of the
+	 * size of the zone.  But no more than 1/4 of a meg - there's
+	 * no point in going beyond the size of L2 cache.
+	 *
+	 * OK, so we don't know how big the cache is.  So guess.
+	 */
+	batch = zone->present_pages / 1024;
+	if (batch * PAGE_SIZE > 256 * 1024)
+		batch = (256 * 1024) / PAGE_SIZE;
+	batch /= 4;		/* We effectively *= 4 below */
+	if (batch < 1)
+		batch = 1;
+
+	/*
+	 * Clamp the batch to a 2^n - 1 value. Having a power
+	 * of 2 value was found to be more likely to have
+	 * suboptimal cache aliasing properties in some cases.
+	 *
+	 * For example if 2 tasks are alternately allocating
+	 * batches of pages, one task can end up with a lot
+	 * of pages of one half of the possible page colors
+	 * and the other with pages of the other colors.
+	 */
+	batch = (1 << fls(batch + batch/2)) - 1;
+	return batch;
+}
+
+inline void setup_pageset(struct per_cpu_pageset *p, unsigned long batch)
+{
+	struct per_cpu_pages *pcp;
+
+	pcp = &p->pcp[0];		/* hot */
+	pcp->count = 0;
+	pcp->low = 2 * batch;
+	pcp->high = 6 * batch;
+	pcp->batch = max(1UL, 1 * batch);
+	INIT_LIST_HEAD(&pcp->list);
+
+	pcp = &p->pcp[1];		/* cold*/
+	pcp->count = 0;
+	pcp->low = 0;
+	pcp->high = 2 * batch;
+	pcp->batch = max(1UL, 1 * batch);
+	INIT_LIST_HEAD(&pcp->list);
+}
+
+#ifdef CONFIG_NUMA
+/*
+ * Boot pageset table. One per cpu which is going to be used for all
+ * zones and all nodes. The parameters will be set in such a way
+ * that an item put on a list will immediately be handed over to
+ * the buddy list. This is safe since pageset manipulation is done
+ * with interrupts disabled.
+ *
+ * Some NUMA counter updates may also be caught by the boot pagesets.
+ *
+ * The boot_pagesets must be kept even after bootup is complete for
+ * unused processors and/or zones. They do play a role for bootstrapping
+ * hotplugged processors.
+ *
+ * zoneinfo_show() and maybe other functions do
+ * not check if the processor is online before following the pageset pointer.
+ * Other parts of the kernel may not check if the zone is available.
+ */
+static struct per_cpu_pageset
+	boot_pageset[NR_CPUS];
+
+/*
+ * Dynamically allocate memory for the
+ * per cpu pageset array in struct zone.
+ */
+static int __devinit process_zones(int cpu)
+{
+	struct zone *zone, *dzone;
+
+	for_each_zone(zone) {
+
+		zone->pageset[cpu] = kmalloc_node(sizeof(struct per_cpu_pageset),
+					 GFP_KERNEL, cpu_to_node(cpu));
+		if (!zone->pageset[cpu])
+			goto bad;
+
+		setup_pageset(zone->pageset[cpu], zone_batchsize(zone));
+	}
+
+	return 0;
+bad:
+	for_each_zone(dzone) {
+		if (dzone == zone)
+			break;
+		kfree(dzone->pageset[cpu]);
+		dzone->pageset[cpu] = NULL;
+	}
+	return -ENOMEM;
+}
+
+static inline void free_zone_pagesets(int cpu)
+{
+#ifdef CONFIG_NUMA
+	struct zone *zone;
+
+	for_each_zone(zone) {
+		struct per_cpu_pageset *pset = zone_pcp(zone, cpu);
+
+		zone_pcp(zone, cpu) = NULL;
+		kfree(pset);
+	}
+#endif
+}
+
+static int __devinit pageset_cpuup_callback(struct notifier_block *nfb,
+		unsigned long action,
+		void *hcpu)
+{
+	int cpu = (long)hcpu;
+	int ret = NOTIFY_OK;
+
+	switch (action) {
+		case CPU_UP_PREPARE:
+			if (process_zones(cpu))
+				ret = NOTIFY_BAD;
+			break;
+#ifdef CONFIG_HOTPLUG_CPU
+		case CPU_DEAD:
+			free_zone_pagesets(cpu);
+			break;
+#endif
+		default:
+			break;
+	}
+	return ret;
+}
+
+static struct notifier_block pageset_notifier =
+	{ &pageset_cpuup_callback, NULL, 0 };
+
+void __init setup_per_cpu_pageset()
+{
+	int err;
+
+	/* Initialize per_cpu_pageset for cpu 0.
+	 * A cpuup callback will do this for every cpu
+	 * as it comes online
+	 */
+	err = process_zones(smp_processor_id());
+	BUG_ON(err);
+	register_cpu_notifier(&pageset_notifier);
+}
+
+#endif
+
 /*
  * Set up the zone data structures:
  *   - mark all pages reserved
@@ -1643,7 +1881,6 @@
 		unsigned long size, realsize;
 		unsigned long batch;
 
-		zone_table[NODEZONE(nid, j)] = zone;
 		realsize = size = zones_size[j];
 		if (zholes_size)
 			realsize -= zholes_size[j];
@@ -1662,48 +1899,16 @@
 
 		zone->temp_priority = zone->prev_priority = DEF_PRIORITY;
 
-		/*
-		 * The per-cpu-pages pools are set to around 1000th of the
-		 * size of the zone.  But no more than 1/4 of a meg - there's
-		 * no point in going beyond the size of L2 cache.
-		 *
-		 * OK, so we don't know how big the cache is.  So guess.
-		 */
-		batch = zone->present_pages / 1024;
-		if (batch * PAGE_SIZE > 256 * 1024)
-			batch = (256 * 1024) / PAGE_SIZE;
-		batch /= 4;		/* We effectively *= 4 below */
-		if (batch < 1)
-			batch = 1;
-
-		/*
-		 * Clamp the batch to a 2^n - 1 value. Having a power
-		 * of 2 value was found to be more likely to have
-		 * suboptimal cache aliasing properties in some cases.
-		 *
-		 * For example if 2 tasks are alternately allocating
-		 * batches of pages, one task can end up with a lot
-		 * of pages of one half of the possible page colors
-		 * and the other with pages of the other colors.
-		 */
-		batch = (1 << fls(batch + batch/2)) - 1;
+		batch = zone_batchsize(zone);
 
 		for (cpu = 0; cpu < NR_CPUS; cpu++) {
-			struct per_cpu_pages *pcp;
-
-			pcp = &zone->pageset[cpu].pcp[0];	/* hot */
-			pcp->count = 0;
-			pcp->low = 2 * batch;
-			pcp->high = 6 * batch;
-			pcp->batch = 1 * batch;
-			INIT_LIST_HEAD(&pcp->list);
-
-			pcp = &zone->pageset[cpu].pcp[1];	/* cold */
-			pcp->count = 0;
-			pcp->low = 0;
-			pcp->high = 2 * batch;
-			pcp->batch = 1 * batch;
-			INIT_LIST_HEAD(&pcp->list);
+#ifdef CONFIG_NUMA
+			/* Early boot. Slab allocator not functional yet */
+			zone->pageset[cpu] = &boot_pageset[cpu];
+			setup_pageset(&boot_pageset[cpu],0);
+#else
+			setup_pageset(zone_pcp(zone,cpu), batch);
+#endif
 		}
 		printk(KERN_DEBUG "  %s zone: %lu pages, LIFO batch:%lu\n",
 				zone_names[j], realsize, batch);
@@ -1713,6 +1918,7 @@
 		zone->nr_scan_inactive = 0;
 		zone->nr_active = 0;
 		zone->nr_inactive = 0;
+		atomic_set(&zone->reclaim_in_progress, -1);
 		if (!size)
 			continue;
 
@@ -1740,6 +1946,8 @@
 
 		memmap_init(size, nid, j, zone_start_pfn);
 
+		zonetable_add(zone, nid, j, zone_start_pfn, size);
+
 		zone_start_pfn += size;
 
 		zone_init_free_lists(pgdat, zone, zone->spanned_pages);
@@ -1748,24 +1956,30 @@
 
 static void __init alloc_node_mem_map(struct pglist_data *pgdat)
 {
-	unsigned long size;
-
 	/* Skip empty nodes */
 	if (!pgdat->node_spanned_pages)
 		return;
 
+#ifdef CONFIG_FLAT_NODE_MEM_MAP
 	/* ia64 gets its own node_mem_map, before this, without bootmem */
 	if (!pgdat->node_mem_map) {
+		unsigned long size;
+		struct page *map;
+
 		size = (pgdat->node_spanned_pages + 1) * sizeof(struct page);
-		pgdat->node_mem_map = alloc_bootmem_node(pgdat, size);
+		map = alloc_remap(pgdat->node_id, size);
+		if (!map)
+			map = alloc_bootmem_node(pgdat, size);
+		pgdat->node_mem_map = map;
 	}
-#ifndef CONFIG_DISCONTIGMEM
+#ifdef CONFIG_FLATMEM
 	/*
 	 * With no DISCONTIG, the global mem_map is just set as node 0's
 	 */
 	if (pgdat == NODE_DATA(0))
 		mem_map = NODE_DATA(0)->node_mem_map;
 #endif
+#endif /* CONFIG_FLAT_NODE_MEM_MAP */
 }
 
 void __init free_area_init_node(int nid, struct pglist_data *pgdat,
@@ -1781,18 +1995,18 @@
 	free_area_init_core(pgdat, zones_size, zholes_size);
 }
 
-#ifndef CONFIG_DISCONTIGMEM
+#ifndef CONFIG_NEED_MULTIPLE_NODES
 static bootmem_data_t contig_bootmem_data;
 struct pglist_data contig_page_data = { .bdata = &contig_bootmem_data };
 
 EXPORT_SYMBOL(contig_page_data);
+#endif
 
 void __init free_area_init(unsigned long *zones_size)
 {
-	free_area_init_node(0, &contig_page_data, zones_size,
+	free_area_init_node(0, NODE_DATA(0), zones_size,
 			__pa(PAGE_OFFSET) >> PAGE_SHIFT, NULL);
 }
-#endif
 
 #ifdef CONFIG_PROC_FS
 
@@ -1853,6 +2067,115 @@
 	.show	= frag_show,
 };
 
+/*
+ * Output information about zones in @pgdat.
+ */
+static int zoneinfo_show(struct seq_file *m, void *arg)
+{
+	pg_data_t *pgdat = arg;
+	struct zone *zone;
+	struct zone *node_zones = pgdat->node_zones;
+	unsigned long flags;
+
+	for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; zone++) {
+		int i;
+
+		if (!zone->present_pages)
+			continue;
+
+		spin_lock_irqsave(&zone->lock, flags);
+		seq_printf(m, "Node %d, zone %8s", pgdat->node_id, zone->name);
+		seq_printf(m,
+			   "\n  pages free     %lu"
+			   "\n        min      %lu"
+			   "\n        low      %lu"
+			   "\n        high     %lu"
+			   "\n        active   %lu"
+			   "\n        inactive %lu"
+			   "\n        scanned  %lu (a: %lu i: %lu)"
+			   "\n        spanned  %lu"
+			   "\n        present  %lu",
+			   zone->free_pages,
+			   zone->pages_min,
+			   zone->pages_low,
+			   zone->pages_high,
+			   zone->nr_active,
+			   zone->nr_inactive,
+			   zone->pages_scanned,
+			   zone->nr_scan_active, zone->nr_scan_inactive,
+			   zone->spanned_pages,
+			   zone->present_pages);
+		seq_printf(m,
+			   "\n        protection: (%lu",
+			   zone->lowmem_reserve[0]);
+		for (i = 1; i < ARRAY_SIZE(zone->lowmem_reserve); i++)
+			seq_printf(m, ", %lu", zone->lowmem_reserve[i]);
+		seq_printf(m,
+			   ")"
+			   "\n  pagesets");
+		for (i = 0; i < ARRAY_SIZE(zone->pageset); i++) {
+			struct per_cpu_pageset *pageset;
+			int j;
+
+			pageset = zone_pcp(zone, i);
+			for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) {
+				if (pageset->pcp[j].count)
+					break;
+			}
+			if (j == ARRAY_SIZE(pageset->pcp))
+				continue;
+			for (j = 0; j < ARRAY_SIZE(pageset->pcp); j++) {
+				seq_printf(m,
+					   "\n    cpu: %i pcp: %i"
+					   "\n              count: %i"
+					   "\n              low:   %i"
+					   "\n              high:  %i"
+					   "\n              batch: %i",
+					   i, j,
+					   pageset->pcp[j].count,
+					   pageset->pcp[j].low,
+					   pageset->pcp[j].high,
+					   pageset->pcp[j].batch);
+			}
+#ifdef CONFIG_NUMA
+			seq_printf(m,
+				   "\n            numa_hit:       %lu"
+				   "\n            numa_miss:      %lu"
+				   "\n            numa_foreign:   %lu"
+				   "\n            interleave_hit: %lu"
+				   "\n            local_node:     %lu"
+				   "\n            other_node:     %lu",
+				   pageset->numa_hit,
+				   pageset->numa_miss,
+				   pageset->numa_foreign,
+				   pageset->interleave_hit,
+				   pageset->local_node,
+				   pageset->other_node);
+#endif
+		}
+		seq_printf(m,
+			   "\n  all_unreclaimable: %u"
+			   "\n  prev_priority:     %i"
+			   "\n  temp_priority:     %i"
+			   "\n  start_pfn:         %lu",
+			   zone->all_unreclaimable,
+			   zone->prev_priority,
+			   zone->temp_priority,
+			   zone->zone_start_pfn);
+		spin_unlock_irqrestore(&zone->lock, flags);
+		seq_putc(m, '\n');
+	}
+	return 0;
+}
+
+struct seq_operations zoneinfo_op = {
+	.start	= frag_start, /* iterate over all zones. The same as in
+			       * fragmentation. */
+	.next	= frag_next,
+	.stop	= frag_stop,
+	.show	= zoneinfo_show,
+};
+
 static char *vmstat_text[] = {
 	"nr_dirty",
 	"nr_writeback",
@@ -2058,10 +2381,10 @@
 				min_pages = 128;
 			zone->pages_min = min_pages;
 		} else {
-			/* if it's a lowmem zone, reserve a number of pages 
+			/* if it's a lowmem zone, reserve a number of pages
 			 * proportionate to the zone's size.
 			 */
-			zone->pages_min = (pages_min * zone->present_pages) / 
+			zone->pages_min = (pages_min * zone->present_pages) /
 			                   lowmem_pages;
 		}
 
diff --git a/mm/page_io.c b/mm/page_io.c
index 667c76d..2e605a1 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -127,7 +127,7 @@
 	return ret;
 }
 
-#if defined(CONFIG_SOFTWARE_SUSPEND) || defined(CONFIG_PM_DISK)
+#ifdef CONFIG_SOFTWARE_SUSPEND
 /*
  * A scruffy utility function to read or write an arbitrary swap page
  * and wait on the I/O.  The caller must have a ref on the page.
diff --git a/mm/pdflush.c b/mm/pdflush.c
index 38ce279..d678195 100644
--- a/mm/pdflush.c
+++ b/mm/pdflush.c
@@ -105,7 +105,7 @@
 		spin_unlock_irq(&pdflush_lock);
 
 		schedule();
-		if (try_to_freeze(PF_FREEZE)) {
+		if (try_to_freeze()) {
 			spin_lock_irq(&pdflush_lock);
 			continue;
 		}
diff --git a/mm/rmap.c b/mm/rmap.c
index 9827409..08ac5c7 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -247,8 +247,8 @@
  *
  * On success returns with mapped pte and locked mm->page_table_lock.
  */
-static pte_t *page_check_address(struct page *page, struct mm_struct *mm,
-					unsigned long address)
+pte_t *page_check_address(struct page *page, struct mm_struct *mm,
+			  unsigned long address)
 {
 	pgd_t *pgd;
 	pud_t *pud;
@@ -539,27 +539,6 @@
 		goto out_unmap;
 	}
 
-	/*
-	 * Don't pull an anonymous page out from under get_user_pages.
-	 * GUP carefully breaks COW and raises page count (while holding
-	 * page_table_lock, as we have here) to make sure that the page
-	 * cannot be freed.  If we unmap that page here, a user write
-	 * access to the virtual address will bring back the page, but
-	 * its raised count will (ironically) be taken to mean it's not
-	 * an exclusive swap page, do_wp_page will replace it by a copy
-	 * page, and the user never get to see the data GUP was holding
-	 * the original page for.
-	 *
-	 * This test is also useful for when swapoff (unuse_process) has
-	 * to drop page lock: its reference to the page stops existing
-	 * ptes from being unmapped, so swapoff can make progress.
-	 */
-	if (PageSwapCache(page) &&
-	    page_count(page) != page_mapcount(page) + 2) {
-		ret = SWAP_FAIL;
-		goto out_unmap;
-	}
-
 	/* Nuke the page table entry. */
 	flush_cache_page(vma, address, page_to_pfn(page));
 	pteval = ptep_clear_flush(vma, address, pte);
diff --git a/mm/shmem.c b/mm/shmem.c
index 61574b8..e64fa72 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -6,8 +6,8 @@
  *		 2000-2001 Christoph Rohland
  *		 2000-2001 SAP AG
  *		 2002 Red Hat Inc.
- * Copyright (C) 2002-2004 Hugh Dickins.
- * Copyright (C) 2002-2004 VERITAS Software Corporation.
+ * Copyright (C) 2002-2005 Hugh Dickins.
+ * Copyright (C) 2002-2005 VERITAS Software Corporation.
  * Copyright (C) 2004 Andi Kleen, SuSE Labs
  *
  * Extended attribute support for tmpfs:
@@ -194,7 +194,7 @@
 static void shmem_free_blocks(struct inode *inode, long pages)
 {
 	struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
-	if (sbinfo) {
+	if (sbinfo->max_blocks) {
 		spin_lock(&sbinfo->stat_lock);
 		sbinfo->free_blocks += pages;
 		inode->i_blocks -= pages*BLOCKS_PER_PAGE;
@@ -357,7 +357,7 @@
 		 * page (and perhaps indirect index pages) yet to allocate:
 		 * a waste to allocate index if we cannot allocate data.
 		 */
-		if (sbinfo) {
+		if (sbinfo->max_blocks) {
 			spin_lock(&sbinfo->stat_lock);
 			if (sbinfo->free_blocks <= 1) {
 				spin_unlock(&sbinfo->stat_lock);
@@ -677,8 +677,8 @@
 			spin_unlock(&shmem_swaplist_lock);
 		}
 	}
-	if (sbinfo) {
-		BUG_ON(inode->i_blocks);
+	BUG_ON(inode->i_blocks);
+	if (sbinfo->max_inodes) {
 		spin_lock(&sbinfo->stat_lock);
 		sbinfo->free_inodes++;
 		spin_unlock(&sbinfo->stat_lock);
@@ -1080,7 +1080,7 @@
 	} else {
 		shmem_swp_unmap(entry);
 		sbinfo = SHMEM_SB(inode->i_sb);
-		if (sbinfo) {
+		if (sbinfo->max_blocks) {
 			spin_lock(&sbinfo->stat_lock);
 			if (sbinfo->free_blocks == 0 ||
 			    shmem_acct_block(info->flags)) {
@@ -1269,7 +1269,7 @@
 	struct shmem_inode_info *info;
 	struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
 
-	if (sbinfo) {
+	if (sbinfo->max_inodes) {
 		spin_lock(&sbinfo->stat_lock);
 		if (!sbinfo->free_inodes) {
 			spin_unlock(&sbinfo->stat_lock);
@@ -1319,7 +1319,7 @@
 			mpol_shared_policy_init(&info->policy);
 			break;
 		}
-	} else if (sbinfo) {
+	} else if (sbinfo->max_inodes) {
 		spin_lock(&sbinfo->stat_lock);
 		sbinfo->free_inodes++;
 		spin_unlock(&sbinfo->stat_lock);
@@ -1328,31 +1328,6 @@
 }
 
 #ifdef CONFIG_TMPFS
-
-static int shmem_set_size(struct shmem_sb_info *sbinfo,
-			  unsigned long max_blocks, unsigned long max_inodes)
-{
-	int error;
-	unsigned long blocks, inodes;
-
-	spin_lock(&sbinfo->stat_lock);
-	blocks = sbinfo->max_blocks - sbinfo->free_blocks;
-	inodes = sbinfo->max_inodes - sbinfo->free_inodes;
-	error = -EINVAL;
-	if (max_blocks < blocks)
-		goto out;
-	if (max_inodes < inodes)
-		goto out;
-	error = 0;
-	sbinfo->max_blocks  = max_blocks;
-	sbinfo->free_blocks = max_blocks - blocks;
-	sbinfo->max_inodes  = max_inodes;
-	sbinfo->free_inodes = max_inodes - inodes;
-out:
-	spin_unlock(&sbinfo->stat_lock);
-	return error;
-}
-
 static struct inode_operations shmem_symlink_inode_operations;
 static struct inode_operations shmem_symlink_inline_operations;
 
@@ -1607,15 +1582,17 @@
 	buf->f_type = TMPFS_MAGIC;
 	buf->f_bsize = PAGE_CACHE_SIZE;
 	buf->f_namelen = NAME_MAX;
-	if (sbinfo) {
-		spin_lock(&sbinfo->stat_lock);
+	spin_lock(&sbinfo->stat_lock);
+	if (sbinfo->max_blocks) {
 		buf->f_blocks = sbinfo->max_blocks;
 		buf->f_bavail = buf->f_bfree = sbinfo->free_blocks;
+	}
+	if (sbinfo->max_inodes) {
 		buf->f_files = sbinfo->max_inodes;
 		buf->f_ffree = sbinfo->free_inodes;
-		spin_unlock(&sbinfo->stat_lock);
 	}
 	/* else leave those fields 0 like simple_statfs */
+	spin_unlock(&sbinfo->stat_lock);
 	return 0;
 }
 
@@ -1672,7 +1649,7 @@
 	 * but each new link needs a new dentry, pinning lowmem, and
 	 * tmpfs dentries cannot be pruned until they are unlinked.
 	 */
-	if (sbinfo) {
+	if (sbinfo->max_inodes) {
 		spin_lock(&sbinfo->stat_lock);
 		if (!sbinfo->free_inodes) {
 			spin_unlock(&sbinfo->stat_lock);
@@ -1697,7 +1674,7 @@
 
 	if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode)) {
 		struct shmem_sb_info *sbinfo = SHMEM_SB(inode->i_sb);
-		if (sbinfo) {
+		if (sbinfo->max_inodes) {
 			spin_lock(&sbinfo->stat_lock);
 			sbinfo->free_inodes++;
 			spin_unlock(&sbinfo->stat_lock);
@@ -1921,22 +1898,42 @@
 static int shmem_remount_fs(struct super_block *sb, int *flags, char *data)
 {
 	struct shmem_sb_info *sbinfo = SHMEM_SB(sb);
-	unsigned long max_blocks = 0;
-	unsigned long max_inodes = 0;
+	unsigned long max_blocks = sbinfo->max_blocks;
+	unsigned long max_inodes = sbinfo->max_inodes;
+	unsigned long blocks;
+	unsigned long inodes;
+	int error = -EINVAL;
 
-	if (sbinfo) {
-		max_blocks = sbinfo->max_blocks;
-		max_inodes = sbinfo->max_inodes;
-	}
-	if (shmem_parse_options(data, NULL, NULL, NULL, &max_blocks, &max_inodes))
-		return -EINVAL;
-	/* Keep it simple: disallow limited <-> unlimited remount */
-	if ((max_blocks || max_inodes) == !sbinfo)
-		return -EINVAL;
-	/* But allow the pointless unlimited -> unlimited remount */
-	if (!sbinfo)
-		return 0;
-	return shmem_set_size(sbinfo, max_blocks, max_inodes);
+	if (shmem_parse_options(data, NULL, NULL, NULL,
+				&max_blocks, &max_inodes))
+		return error;
+
+	spin_lock(&sbinfo->stat_lock);
+	blocks = sbinfo->max_blocks - sbinfo->free_blocks;
+	inodes = sbinfo->max_inodes - sbinfo->free_inodes;
+	if (max_blocks < blocks)
+		goto out;
+	if (max_inodes < inodes)
+		goto out;
+	/*
+	 * Those tests also disallow limited->unlimited while any are in
+	 * use, so i_blocks will always be zero when max_blocks is zero;
+	 * but we must separately disallow unlimited->limited, because
+	 * in that case we have no record of how much is already in use.
+	 */
+	if (max_blocks && !sbinfo->max_blocks)
+		goto out;
+	if (max_inodes && !sbinfo->max_inodes)
+		goto out;
+
+	error = 0;
+	sbinfo->max_blocks  = max_blocks;
+	sbinfo->free_blocks = max_blocks - blocks;
+	sbinfo->max_inodes  = max_inodes;
+	sbinfo->free_inodes = max_inodes - inodes;
+out:
+	spin_unlock(&sbinfo->stat_lock);
+	return error;
 }
 #endif
 
@@ -1961,11 +1958,11 @@
 	uid_t uid = current->fsuid;
 	gid_t gid = current->fsgid;
 	int err = -ENOMEM;
-
-#ifdef CONFIG_TMPFS
+	struct shmem_sb_info *sbinfo;
 	unsigned long blocks = 0;
 	unsigned long inodes = 0;
 
+#ifdef CONFIG_TMPFS
 	/*
 	 * Per default we only allow half of the physical ram per
 	 * tmpfs instance, limiting inodes to one per page of lowmem;
@@ -1976,34 +1973,34 @@
 		inodes = totalram_pages - totalhigh_pages;
 		if (inodes > blocks)
 			inodes = blocks;
-
-		if (shmem_parse_options(data, &mode,
-					&uid, &gid, &blocks, &inodes))
+		if (shmem_parse_options(data, &mode, &uid, &gid,
+					&blocks, &inodes))
 			return -EINVAL;
 	}
-
-	if (blocks || inodes) {
-		struct shmem_sb_info *sbinfo;
-		sbinfo = kmalloc(sizeof(struct shmem_sb_info), GFP_KERNEL);
-		if (!sbinfo)
-			return -ENOMEM;
-		sb->s_fs_info = sbinfo;
-		spin_lock_init(&sbinfo->stat_lock);
-		sbinfo->max_blocks = blocks;
-		sbinfo->free_blocks = blocks;
-		sbinfo->max_inodes = inodes;
-		sbinfo->free_inodes = inodes;
-	}
-	sb->s_xattr = shmem_xattr_handlers;
 #else
 	sb->s_flags |= MS_NOUSER;
 #endif
 
+	/* Round up to L1_CACHE_BYTES to resist false sharing */
+	sbinfo = kmalloc(max((int)sizeof(struct shmem_sb_info),
+				L1_CACHE_BYTES), GFP_KERNEL);
+	if (!sbinfo)
+		return -ENOMEM;
+
+	spin_lock_init(&sbinfo->stat_lock);
+	sbinfo->max_blocks = blocks;
+	sbinfo->free_blocks = blocks;
+	sbinfo->max_inodes = inodes;
+	sbinfo->free_inodes = inodes;
+
+	sb->s_fs_info = sbinfo;
 	sb->s_maxbytes = SHMEM_MAX_BYTES;
 	sb->s_blocksize = PAGE_CACHE_SIZE;
 	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
 	sb->s_magic = TMPFS_MAGIC;
 	sb->s_op = &shmem_ops;
+	sb->s_xattr = shmem_xattr_handlers;
+
 	inode = shmem_get_inode(sb, S_IFDIR | mode, 0);
 	if (!inode)
 		goto failed;
diff --git a/mm/slab.c b/mm/slab.c
index 8407426..122d031 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -92,6 +92,7 @@
 #include	<linux/sysctl.h>
 #include	<linux/module.h>
 #include	<linux/rcupdate.h>
+#include	<linux/string.h>
 
 #include	<asm/uaccess.h>
 #include	<asm/cacheflush.h>
@@ -2620,6 +2621,12 @@
 }
 EXPORT_SYMBOL(kmem_cache_size);
 
+const char *kmem_cache_name(kmem_cache_t *cachep)
+{
+	return cachep->name;
+}
+EXPORT_SYMBOL_GPL(kmem_cache_name);
+
 struct ccupdate_struct {
 	kmem_cache_t *cachep;
 	struct array_cache *new[NR_CPUS];
@@ -2845,6 +2852,7 @@
 	}
 	check_irq_on();
 	up(&cache_chain_sem);
+	drain_remote_pages();
 	/* Setup the next iteration */
 	schedule_delayed_work(&__get_cpu_var(reap_work), REAPTIMEOUT_CPUC + smp_processor_id());
 }
@@ -3075,3 +3083,26 @@
 
 	return size;
 }
+
+
+/*
+ * kstrdup - allocate space for and copy an existing string
+ *
+ * @s: the string to duplicate
+ * @gfp: the GFP mask used in the kmalloc() call when allocating memory
+ */
+char *kstrdup(const char *s, int gfp)
+{
+	size_t len;
+	char *buf;
+
+	if (!s)
+		return NULL;
+
+	len = strlen(s) + 1;
+	buf = kmalloc(len, gfp);
+	if (buf)
+		memcpy(buf, s, len);
+	return buf;
+}
+EXPORT_SYMBOL(kstrdup);
diff --git a/mm/sparse.c b/mm/sparse.c
new file mode 100644
index 0000000..b54e304
--- /dev/null
+++ b/mm/sparse.c
@@ -0,0 +1,137 @@
+/*
+ * sparse memory mappings.
+ */
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/mmzone.h>
+#include <linux/bootmem.h>
+#include <linux/module.h>
+#include <asm/dma.h>
+
+/*
+ * Permanent SPARSEMEM data:
+ *
+ * 1) mem_section	- memory sections, mem_map's for valid memory
+ */
+struct mem_section mem_section[NR_MEM_SECTIONS];
+EXPORT_SYMBOL(mem_section);
+
+/* Record a memory area against a node. */
+void memory_present(int nid, unsigned long start, unsigned long end)
+{
+	unsigned long pfn;
+
+	start &= PAGE_SECTION_MASK;
+	for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) {
+		unsigned long section = pfn_to_section_nr(pfn);
+		if (!mem_section[section].section_mem_map)
+			mem_section[section].section_mem_map = SECTION_MARKED_PRESENT;
+	}
+}
+
+/*
+ * Only used by the i386 NUMA architecures, but relatively
+ * generic code.
+ */
+unsigned long __init node_memmap_size_bytes(int nid, unsigned long start_pfn,
+						     unsigned long end_pfn)
+{
+	unsigned long pfn;
+	unsigned long nr_pages = 0;
+
+	for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
+		if (nid != early_pfn_to_nid(pfn))
+			continue;
+
+		if (pfn_valid(pfn))
+			nr_pages += PAGES_PER_SECTION;
+	}
+
+	return nr_pages * sizeof(struct page);
+}
+
+/*
+ * Subtle, we encode the real pfn into the mem_map such that
+ * the identity pfn - section_mem_map will return the actual
+ * physical page frame number.
+ */
+static unsigned long sparse_encode_mem_map(struct page *mem_map, unsigned long pnum)
+{
+	return (unsigned long)(mem_map - (section_nr_to_pfn(pnum)));
+}
+
+/*
+ * We need this if we ever free the mem_maps.  While not implemented yet,
+ * this function is included for parity with its sibling.
+ */
+static __attribute((unused))
+struct page *sparse_decode_mem_map(unsigned long coded_mem_map, unsigned long pnum)
+{
+	return ((struct page *)coded_mem_map) + section_nr_to_pfn(pnum);
+}
+
+static int sparse_init_one_section(struct mem_section *ms,
+		unsigned long pnum, struct page *mem_map)
+{
+	if (!valid_section(ms))
+		return -EINVAL;
+
+	ms->section_mem_map |= sparse_encode_mem_map(mem_map, pnum);
+
+	return 1;
+}
+
+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));
+
+	map = alloc_remap(nid, sizeof(struct page) * PAGES_PER_SECTION);
+	if (map)
+		return map;
+
+	map = alloc_bootmem_node(NODE_DATA(nid),
+			sizeof(struct page) * PAGES_PER_SECTION);
+	if (map)
+		return map;
+
+	printk(KERN_WARNING "%s: allocation failed\n", __FUNCTION__);
+	mem_section[pnum].section_mem_map = 0;
+	return NULL;
+}
+
+/*
+ * Allocate the accumulated non-linear sections, allocate a mem_map
+ * for each and record the physical to section mapping.
+ */
+void sparse_init(void)
+{
+	unsigned long pnum;
+	struct page *map;
+
+	for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
+		if (!valid_section_nr(pnum))
+			continue;
+
+		map = sparse_early_mem_map_alloc(pnum);
+		if (map)
+			sparse_init_one_section(&mem_section[pnum], pnum, map);
+	}
+}
+
+/*
+ * returns the number of sections whose mem_maps were properly
+ * set.  If this is <=0, then that means that the passed-in
+ * map was not consumed and must be freed.
+ */
+int sparse_add_one_section(unsigned long start_pfn, int nr_pages, struct page *map)
+{
+	struct mem_section *ms = __pfn_to_section(start_pfn);
+
+	if (ms->section_mem_map & SECTION_MARKED_PRESENT)
+		return -EEXIST;
+
+	ms->section_mem_map |= SECTION_MARKED_PRESENT;
+
+	return sparse_init_one_section(ms, pfn_to_section_nr(start_pfn), map);
+}
diff --git a/mm/swapfile.c b/mm/swapfile.c
index da48405..60cd24a 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -276,61 +276,37 @@
 }
 
 /*
- * Check if we're the only user of a swap page,
- * when the page is locked.
+ * How many references to page are currently swapped out?
  */
-static int exclusive_swap_page(struct page *page)
+static inline int page_swapcount(struct page *page)
 {
-	int retval = 0;
-	struct swap_info_struct * p;
+	int count = 0;
+	struct swap_info_struct *p;
 	swp_entry_t entry;
 
 	entry.val = page->private;
 	p = swap_info_get(entry);
 	if (p) {
-		/* Is the only swap cache user the cache itself? */
-		if (p->swap_map[swp_offset(entry)] == 1) {
-			/* Recheck the page count with the swapcache lock held.. */
-			write_lock_irq(&swapper_space.tree_lock);
-			if (page_count(page) == 2)
-				retval = 1;
-			write_unlock_irq(&swapper_space.tree_lock);
-		}
+		/* Subtract the 1 for the swap cache itself */
+		count = p->swap_map[swp_offset(entry)] - 1;
 		swap_info_put(p);
 	}
-	return retval;
+	return count;
 }
 
 /*
  * We can use this swap cache entry directly
  * if there are no other references to it.
- *
- * Here "exclusive_swap_page()" does the real
- * work, but we opportunistically check whether
- * we need to get all the locks first..
  */
 int can_share_swap_page(struct page *page)
 {
-	int retval = 0;
+	int count;
 
-	if (!PageLocked(page))
-		BUG();
-	switch (page_count(page)) {
-	case 3:
-		if (!PagePrivate(page))
-			break;
-		/* Fallthrough */
-	case 2:
-		if (!PageSwapCache(page))
-			break;
-		retval = exclusive_swap_page(page);
-		break;
-	case 1:
-		if (PageReserved(page))
-			break;
-		retval = 1;
-	}
-	return retval;
+	BUG_ON(!PageLocked(page));
+	count = page_mapcount(page);
+	if (count <= 1 && PageSwapCache(page))
+		count += page_swapcount(page);
+	return count == 1;
 }
 
 /*
@@ -529,9 +505,10 @@
 
 	if (!down_read_trylock(&mm->mmap_sem)) {
 		/*
-		 * Our reference to the page stops try_to_unmap_one from
-		 * unmapping its ptes, so swapoff can make progress.
+		 * Activate page so shrink_cache is unlikely to unmap its
+		 * ptes while lock is dropped, so swapoff can make progress.
 		 */
+		activate_page(page);
 		unlock_page(page);
 		down_read(&mm->mmap_sem);
 		lock_page(page);
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 269eded..1fa312a 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -74,6 +74,9 @@
 
 	int may_writepage;
 
+	/* Can pages be swapped as part of reclaim? */
+	int may_swap;
+
 	/* This context's SWAP_CLUSTER_MAX. If freeing memory for
 	 * suspend, we effectively ignore SWAP_CLUSTER_MAX.
 	 * In this context, it doesn't matter that we scan the
@@ -180,17 +183,20 @@
  * `lru_pages' represents the number of on-LRU pages in all the zones which
  * are eligible for the caller's allocation attempt.  It is used for balancing
  * slab reclaim versus page reclaim.
+ *
+ * Returns the number of slab objects which we shrunk.
  */
 static int shrink_slab(unsigned long scanned, unsigned int gfp_mask,
 			unsigned long lru_pages)
 {
 	struct shrinker *shrinker;
+	int ret = 0;
 
 	if (scanned == 0)
 		scanned = SWAP_CLUSTER_MAX;
 
 	if (!down_read_trylock(&shrinker_rwsem))
-		return 0;
+		return 1;	/* Assume we'll be able to shrink next time */
 
 	list_for_each_entry(shrinker, &shrinker_list, list) {
 		unsigned long long delta;
@@ -209,10 +215,14 @@
 		while (total_scan >= SHRINK_BATCH) {
 			long this_scan = SHRINK_BATCH;
 			int shrink_ret;
+			int nr_before;
 
+			nr_before = (*shrinker->shrinker)(0, gfp_mask);
 			shrink_ret = (*shrinker->shrinker)(this_scan, gfp_mask);
 			if (shrink_ret == -1)
 				break;
+			if (shrink_ret < nr_before)
+				ret += nr_before - shrink_ret;
 			mod_page_state(slabs_scanned, this_scan);
 			total_scan -= this_scan;
 
@@ -222,7 +232,7 @@
 		shrinker->nr += total_scan;
 	}
 	up_read(&shrinker_rwsem);
-	return 0;
+	return ret;
 }
 
 /* Called without lock on whether page is mapped, so answer is unstable */
@@ -407,7 +417,7 @@
 		 * Anonymous process memory has backing store?
 		 * Try to allocate it some swap space here.
 		 */
-		if (PageAnon(page) && !PageSwapCache(page)) {
+		if (PageAnon(page) && !PageSwapCache(page) && sc->may_swap) {
 			if (!add_to_swap(page))
 				goto activate_locked;
 		}
@@ -890,7 +900,9 @@
 		if (zone->all_unreclaimable && sc->priority != DEF_PRIORITY)
 			continue;	/* Let kswapd poll it */
 
+		atomic_inc(&zone->reclaim_in_progress);
 		shrink_zone(zone, sc);
+		atomic_dec(&zone->reclaim_in_progress);
 	}
 }
  
@@ -907,8 +919,7 @@
  * holds filesystem locks which prevent writeout this might not work, and the
  * allocation attempt will fail.
  */
-int try_to_free_pages(struct zone **zones,
-		unsigned int gfp_mask, unsigned int order)
+int try_to_free_pages(struct zone **zones, unsigned int gfp_mask)
 {
 	int priority;
 	int ret = 0;
@@ -920,6 +931,7 @@
 
 	sc.gfp_mask = gfp_mask;
 	sc.may_writepage = 0;
+	sc.may_swap = 1;
 
 	inc_page_state(allocstall);
 
@@ -1020,6 +1032,7 @@
 	total_reclaimed = 0;
 	sc.gfp_mask = GFP_KERNEL;
 	sc.may_writepage = 0;
+	sc.may_swap = 1;
 	sc.nr_mapped = read_page_state(nr_mapped);
 
 	inc_page_state(pageoutrun);
@@ -1079,6 +1092,7 @@
 		 */
 		for (i = 0; i <= end_zone; i++) {
 			struct zone *zone = pgdat->node_zones + i;
+			int nr_slab;
 
 			if (zone->present_pages == 0)
 				continue;
@@ -1098,16 +1112,19 @@
 			sc.nr_reclaimed = 0;
 			sc.priority = priority;
 			sc.swap_cluster_max = nr_pages? nr_pages : SWAP_CLUSTER_MAX;
+			atomic_inc(&zone->reclaim_in_progress);
 			shrink_zone(zone, &sc);
+			atomic_dec(&zone->reclaim_in_progress);
 			reclaim_state->reclaimed_slab = 0;
-			shrink_slab(sc.nr_scanned, GFP_KERNEL, lru_pages);
+			nr_slab = shrink_slab(sc.nr_scanned, GFP_KERNEL,
+						lru_pages);
 			sc.nr_reclaimed += reclaim_state->reclaimed_slab;
 			total_reclaimed += sc.nr_reclaimed;
 			total_scanned += sc.nr_scanned;
 			if (zone->all_unreclaimable)
 				continue;
-			if (zone->pages_scanned >= (zone->nr_active +
-							zone->nr_inactive) * 4)
+			if (nr_slab == 0 && zone->pages_scanned >=
+				    (zone->nr_active + zone->nr_inactive) * 4)
 				zone->all_unreclaimable = 1;
 			/*
 			 * If we've done a decent amount of scanning and
@@ -1199,8 +1216,8 @@
 	order = 0;
 	for ( ; ; ) {
 		unsigned long new_order;
-		if (current->flags & PF_FREEZE)
-			refrigerator(PF_FREEZE);
+
+		try_to_freeze();
 
 		prepare_to_wait(&pgdat->kswapd_wait, &wait, TASK_INTERRUPTIBLE);
 		new_order = pgdat->kswapd_max_order;
@@ -1309,3 +1326,73 @@
 }
 
 module_init(kswapd_init)
+
+
+/*
+ * Try to free up some pages from this zone through reclaim.
+ */
+int zone_reclaim(struct zone *zone, unsigned int gfp_mask, unsigned int order)
+{
+	struct scan_control sc;
+	int nr_pages = 1 << order;
+	int total_reclaimed = 0;
+
+	/* The reclaim may sleep, so don't do it if sleep isn't allowed */
+	if (!(gfp_mask & __GFP_WAIT))
+		return 0;
+	if (zone->all_unreclaimable)
+		return 0;
+
+	sc.gfp_mask = gfp_mask;
+	sc.may_writepage = 0;
+	sc.may_swap = 0;
+	sc.nr_mapped = read_page_state(nr_mapped);
+	sc.nr_scanned = 0;
+	sc.nr_reclaimed = 0;
+	/* scan at the highest priority */
+	sc.priority = 0;
+
+	if (nr_pages > SWAP_CLUSTER_MAX)
+		sc.swap_cluster_max = nr_pages;
+	else
+		sc.swap_cluster_max = SWAP_CLUSTER_MAX;
+
+	/* Don't reclaim the zone if there are other reclaimers active */
+	if (!atomic_inc_and_test(&zone->reclaim_in_progress))
+		goto out;
+
+	shrink_zone(zone, &sc);
+	total_reclaimed = sc.nr_reclaimed;
+
+ out:
+	atomic_dec(&zone->reclaim_in_progress);
+	return total_reclaimed;
+}
+
+asmlinkage long sys_set_zone_reclaim(unsigned int node, unsigned int zone,
+				     unsigned int state)
+{
+	struct zone *z;
+	int i;
+
+	if (node >= MAX_NUMNODES || !node_online(node))
+		return -EINVAL;
+
+	/* This will break if we ever add more zones */
+	if (!(zone & (1<<ZONE_DMA|1<<ZONE_NORMAL|1<<ZONE_HIGHMEM)))
+		return -EINVAL;
+
+	for (i = 0; i < MAX_NR_ZONES; i++) {
+		if (!(zone & 1<<i))
+			continue;
+
+		z = &NODE_DATA(node)->node_zones[i];
+
+		if (state)
+			z->reclaim_pages = 1;
+		else
+			z->reclaim_pages = 0;
+	}
+
+	return 0;
+}
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c
index 54640c0..c34614e 100644
--- a/net/appletalk/aarp.c
+++ b/net/appletalk/aarp.c
@@ -35,6 +35,7 @@
 #include <net/datalink.h>
 #include <net/psnap.h>
 #include <linux/atalk.h>
+#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
@@ -462,8 +463,7 @@
 			aarp_send_probe(atif->dev, &atif->address);
 
 			/* Defer 1/10th */
-			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(HZ / 10);
+			msleep(100);
 
 			if (atif->status & ATIF_PROBE_FAIL)
 				break;
@@ -510,9 +510,8 @@
 		aarp_send_probe(atif->dev, sa);
 
 		/* Defer 1/10th */
-		current->state = TASK_INTERRUPTIBLE;
 		write_unlock_bh(&aarp_lock);
-		schedule_timeout(HZ / 10);
+		msleep(100);
 		write_lock_bh(&aarp_lock);
 
 		if (entry->status & ATIF_PROBE_FAIL)
@@ -565,7 +564,7 @@
 			 *	numbers	we just happen to need. Now put the
 			 *	length in the lower two.
 			 */
-			*((__u16 *)skb->data) = htons(skb->len);
+			*((__be16 *)skb->data) = htons(skb->len);
 			ft = 1;
 		}
 		/*
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 876dbac..192b529 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -401,7 +401,7 @@
 }
 
 /* Find a match for a specific network:node pair */
-static struct atalk_iface *atalk_find_interface(int net, int node)
+static struct atalk_iface *atalk_find_interface(__be16 net, int node)
 {
 	struct atalk_iface *iface;
 
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index ef9f209..069253f 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -57,9 +57,6 @@
 static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
 {
 	skb->dev = to->dev;
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#endif
 	NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
 			br_forward_finish);
 }
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 8f5f2e7..9a45e62 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -23,11 +23,7 @@
 
 static int br_pass_frame_up_finish(struct sk_buff *skb)
 {
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#endif
 	netif_receive_skb(skb);
-
 	return 0;
 }
 
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index be03d3a..03ae4ed 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -102,10 +102,6 @@
 {
 	struct nf_bridge_info *nf_bridge = skb->nf_bridge;
 
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug ^= (1 << NF_BR_PRE_ROUTING);
-#endif
-
 	if (nf_bridge->mask & BRNF_PKT_TYPE) {
 		skb->pkt_type = PACKET_OTHERHOST;
 		nf_bridge->mask ^= BRNF_PKT_TYPE;
@@ -182,10 +178,6 @@
  * --Bart, 20021007 (updated) */
 static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb)
 {
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug |= (1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_FORWARD);
-#endif
-
 	if (skb->pkt_type == PACKET_OTHERHOST) {
 		skb->pkt_type = PACKET_HOST;
 		skb->nf_bridge->mask |= BRNF_PKT_TYPE;
@@ -207,10 +199,6 @@
 	struct iphdr *iph = skb->nh.iph;
 	struct nf_bridge_info *nf_bridge = skb->nf_bridge;
 
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug ^= (1 << NF_BR_PRE_ROUTING);
-#endif
-
 	if (nf_bridge->mask & BRNF_PKT_TYPE) {
 		skb->pkt_type = PACKET_OTHERHOST;
 		nf_bridge->mask ^= BRNF_PKT_TYPE;
@@ -382,9 +370,6 @@
 	if (hdr->nexthdr == NEXTHDR_HOP && check_hbh_len(skb))
 			goto inhdr_error;
 
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug ^= (1 << NF_IP6_PRE_ROUTING);
-#endif
 	if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
 		return NF_DROP;
 	setup_pre_routing(skb);
@@ -468,9 +453,6 @@
 			skb->ip_summed = CHECKSUM_NONE;
 	}
 
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug ^= (1 << NF_IP_PRE_ROUTING);
-#endif
 	if ((nf_bridge = nf_bridge_alloc(skb)) == NULL)
 		return NF_DROP;
 	setup_pre_routing(skb);
@@ -517,10 +499,6 @@
 	struct net_device *in;
 	struct vlan_ethhdr *hdr = vlan_eth_hdr(skb);
 
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug ^= (1 << NF_BR_FORWARD);
-#endif
-
 	if (skb->protocol != __constant_htons(ETH_P_ARP) && !IS_VLAN_ARP) {
 		in = nf_bridge->physindev;
 		if (nf_bridge->mask & BRNF_PKT_TYPE) {
@@ -566,9 +544,6 @@
 		(*pskb)->nh.raw += VLAN_HLEN;
 	}
 
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug ^= (1 << NF_BR_FORWARD);
-#endif
 	nf_bridge = skb->nf_bridge;
 	if (skb->pkt_type == PACKET_OTHERHOST) {
 		skb->pkt_type = PACKET_HOST;
@@ -605,10 +580,6 @@
 		(*pskb)->nh.raw += VLAN_HLEN;
 	}
 
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug ^= (1 << NF_BR_FORWARD);
-#endif
-
 	if (skb->nh.arph->ar_pln != 4) {
 		if (IS_VLAN_ARP) {
 			skb_push(*pskb, VLAN_HLEN);
@@ -627,9 +598,6 @@
 /* PF_BRIDGE/LOCAL_OUT ***********************************************/
 static int br_nf_local_out_finish(struct sk_buff *skb)
 {
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug &= ~(1 << NF_BR_LOCAL_OUT);
-#endif
 	if (skb->protocol == __constant_htons(ETH_P_8021Q)) {
 		skb_push(skb, VLAN_HLEN);
 		skb->nh.raw -= VLAN_HLEN;
@@ -731,10 +699,6 @@
 			       realoutdev, br_nf_local_out_finish,
 			       NF_IP_PRI_BRIDGE_SABOTAGE_FORWARD + 1);
 	} else {
-#ifdef CONFIG_NETFILTER_DEBUG
-		skb->nf_debug ^= (1 << NF_IP_LOCAL_OUT);
-#endif
-
 		NF_HOOK_THRESH(pf, NF_IP_LOCAL_OUT, skb, realindev,
 			       realoutdev, br_nf_local_out_finish,
 			       NF_IP_PRI_BRIDGE_SABOTAGE_LOCAL_OUT + 1);
@@ -779,8 +743,6 @@
 		printk(KERN_CRIT "br_netfilter: skb->dst == NULL.");
 		goto print_error;
 	}
-
-	skb->nf_debug ^= (1 << NF_IP_POST_ROUTING);
 #endif
 
 	/* We assume any code from br_dev_queue_push_xmit onwards doesn't care
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 18ebc66..c454014 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -859,8 +859,7 @@
 		if (repl->valid_hooks & (1 << i))
 			if (check_chainloops(newinfo->hook_entry[i],
 			   cl_s, udc_cnt, i, newinfo->entries)) {
-				if (cl_s)
-					vfree(cl_s);
+				vfree(cl_s);
 				return -EINVAL;
 			}
 
@@ -883,8 +882,7 @@
 		EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
 		   ebt_cleanup_entry, &i);
 	}
-	if (cl_s)
-		vfree(cl_s);
+	vfree(cl_s);
 	return ret;
 }
 
@@ -1030,8 +1028,7 @@
 	}
 	vfree(table);
 
-	if (counterstmp)
-		vfree(counterstmp);
+	vfree(counterstmp);
 	return ret;
 
 free_unlock:
@@ -1040,8 +1037,7 @@
 	EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
 	   ebt_cleanup_entry, NULL);
 free_counterstmp:
-	if (counterstmp)
-		vfree(counterstmp);
+	vfree(counterstmp);
 	/* can be initialized in translate_table() */
 	if (newinfo->chainstack) {
 		for (i = 0; i < num_possible_cpus(); i++)
@@ -1049,11 +1045,9 @@
 		vfree(newinfo->chainstack);
 	}
 free_entries:
-	if (newinfo->entries)
-		vfree(newinfo->entries);
+	vfree(newinfo->entries);
 free_newinfo:
-	if (newinfo)
-		vfree(newinfo);
+	vfree(newinfo);
 	return ret;
 }
 
@@ -1213,8 +1207,7 @@
 	down(&ebt_mutex);
 	LIST_DELETE(&ebt_tables, table);
 	up(&ebt_mutex);
-	if (table->private->entries)
-		vfree(table->private->entries);
+	vfree(table->private->entries);
 	if (table->private->chainstack) {
 		for (i = 0; i < num_possible_cpus(); i++)
 			vfree(table->private->chainstack[i]);
diff --git a/net/core/Makefile b/net/core/Makefile
index 81f0324..5e0c56b 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -2,7 +2,8 @@
 # Makefile for the Linux networking core.
 #
 
-obj-y := sock.o skbuff.o iovec.o datagram.o stream.o scm.o gen_stats.o gen_estimator.o
+obj-y := sock.o request_sock.o skbuff.o iovec.o datagram.o stream.o scm.o \
+	 gen_stats.o gen_estimator.o
 
 obj-$(CONFIG_SYSCTL) += sysctl_net_core.o
 
diff --git a/net/core/dev.c b/net/core/dev.c
index f15a3ff..7016e0c 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -115,18 +115,6 @@
 #endif	/* CONFIG_NET_RADIO */
 #include <asm/current.h>
 
-/* This define, if set, will randomly drop a packet when congestion
- * is more than moderate.  It helps fairness in the multi-interface
- * case when one of them is a hog, but it kills performance for the
- * single interface case so it is off now by default.
- */
-#undef RAND_LIE
-
-/* Setting this will sample the queue lengths and thus congestion
- * via a timer instead of as each packet is received.
- */
-#undef OFFLINE_SAMPLE
-
 /*
  *	The list of packet types we will receive (as opposed to discard)
  *	and the routines to invoke.
@@ -159,11 +147,6 @@
 static struct list_head ptype_base[16];	/* 16 way hashed list */
 static struct list_head ptype_all;		/* Taps */
 
-#ifdef OFFLINE_SAMPLE
-static void sample_queue(unsigned long dummy);
-static struct timer_list samp_timer = TIMER_INITIALIZER(sample_queue, 0, 0);
-#endif
-
 /*
  * The @dev_base list is protected by @dev_base_lock and the rtln
  * semaphore.
@@ -215,7 +198,7 @@
  *	Device drivers call our routines to queue packets here. We empty the
  *	queue in the local softnet handler.
  */
-DEFINE_PER_CPU(struct softnet_data, softnet_data) = { 0, };
+DEFINE_PER_CPU(struct softnet_data, softnet_data) = { NULL };
 
 #ifdef CONFIG_SYSFS
 extern int netdev_sysfs_init(void);
@@ -1363,71 +1346,13 @@
 			Receiver routines
   =======================================================================*/
 
-int netdev_max_backlog = 300;
+int netdev_max_backlog = 1000;
+int netdev_budget = 300;
 int weight_p = 64;            /* old backlog weight */
-/* These numbers are selected based on intuition and some
- * experimentatiom, if you have more scientific way of doing this
- * please go ahead and fix things.
- */
-int no_cong_thresh = 10;
-int no_cong = 20;
-int lo_cong = 100;
-int mod_cong = 290;
 
 DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, };
 
 
-static void get_sample_stats(int cpu)
-{
-#ifdef RAND_LIE
-	unsigned long rd;
-	int rq;
-#endif
-	struct softnet_data *sd = &per_cpu(softnet_data, cpu);
-	int blog = sd->input_pkt_queue.qlen;
-	int avg_blog = sd->avg_blog;
-
-	avg_blog = (avg_blog >> 1) + (blog >> 1);
-
-	if (avg_blog > mod_cong) {
-		/* Above moderate congestion levels. */
-		sd->cng_level = NET_RX_CN_HIGH;
-#ifdef RAND_LIE
-		rd = net_random();
-		rq = rd % netdev_max_backlog;
-		if (rq < avg_blog) /* unlucky bastard */
-			sd->cng_level = NET_RX_DROP;
-#endif
-	} else if (avg_blog > lo_cong) {
-		sd->cng_level = NET_RX_CN_MOD;
-#ifdef RAND_LIE
-		rd = net_random();
-		rq = rd % netdev_max_backlog;
-			if (rq < avg_blog) /* unlucky bastard */
-				sd->cng_level = NET_RX_CN_HIGH;
-#endif
-	} else if (avg_blog > no_cong)
-		sd->cng_level = NET_RX_CN_LOW;
-	else  /* no congestion */
-		sd->cng_level = NET_RX_SUCCESS;
-
-	sd->avg_blog = avg_blog;
-}
-
-#ifdef OFFLINE_SAMPLE
-static void sample_queue(unsigned long dummy)
-{
-/* 10 ms 0r 1ms -- i don't care -- JHS */
-	int next_tick = 1;
-	int cpu = smp_processor_id();
-
-	get_sample_stats(cpu);
-	next_tick += jiffies;
-	mod_timer(&samp_timer, next_tick);
-}
-#endif
-
-
 /**
  *	netif_rx	-	post buffer to the network code
  *	@skb: buffer to post
@@ -1448,7 +1373,6 @@
 
 int netif_rx(struct sk_buff *skb)
 {
-	int this_cpu;
 	struct softnet_data *queue;
 	unsigned long flags;
 
@@ -1464,38 +1388,22 @@
 	 * short when CPU is congested, but is still operating.
 	 */
 	local_irq_save(flags);
-	this_cpu = smp_processor_id();
 	queue = &__get_cpu_var(softnet_data);
 
 	__get_cpu_var(netdev_rx_stat).total++;
 	if (queue->input_pkt_queue.qlen <= netdev_max_backlog) {
 		if (queue->input_pkt_queue.qlen) {
-			if (queue->throttle)
-				goto drop;
-
 enqueue:
 			dev_hold(skb->dev);
 			__skb_queue_tail(&queue->input_pkt_queue, skb);
-#ifndef OFFLINE_SAMPLE
-			get_sample_stats(this_cpu);
-#endif
 			local_irq_restore(flags);
-			return queue->cng_level;
+			return NET_RX_SUCCESS;
 		}
 
-		if (queue->throttle)
-			queue->throttle = 0;
-
 		netif_rx_schedule(&queue->backlog_dev);
 		goto enqueue;
 	}
 
-	if (!queue->throttle) {
-		queue->throttle = 1;
-		__get_cpu_var(netdev_rx_stat).throttled++;
-	}
-
-drop:
 	__get_cpu_var(netdev_rx_stat).dropped++;
 	local_irq_restore(flags);
 
@@ -1744,6 +1652,7 @@
 	struct softnet_data *queue = &__get_cpu_var(softnet_data);
 	unsigned long start_time = jiffies;
 
+	backlog_dev->weight = weight_p;
 	for (;;) {
 		struct sk_buff *skb;
 		struct net_device *dev;
@@ -1779,8 +1688,6 @@
 	smp_mb__before_clear_bit();
 	netif_poll_enable(backlog_dev);
 
-	if (queue->throttle)
-		queue->throttle = 0;
 	local_irq_enable();
 	return 0;
 }
@@ -1789,8 +1696,7 @@
 {
 	struct softnet_data *queue = &__get_cpu_var(softnet_data);
 	unsigned long start_time = jiffies;
-	int budget = netdev_max_backlog;
-
+	int budget = netdev_budget;
 	
 	local_irq_disable();
 
@@ -2054,15 +1960,9 @@
 	struct netif_rx_stats *s = v;
 
 	seq_printf(seq, "%08x %08x %08x %08x %08x %08x %08x %08x %08x\n",
-		   s->total, s->dropped, s->time_squeeze, s->throttled,
-		   s->fastroute_hit, s->fastroute_success, s->fastroute_defer,
-		   s->fastroute_deferred_out,
-#if 0
-		   s->fastroute_latency_reduction
-#else
-		   s->cpu_collision
-#endif
-		  );
+		   s->total, s->dropped, s->time_squeeze, 0,
+		   0, 0, 0, 0, /* was fastroute */
+		   s->cpu_collision );
 	return 0;
 }
 
@@ -3304,9 +3204,6 @@
 
 		queue = &per_cpu(softnet_data, i);
 		skb_queue_head_init(&queue->input_pkt_queue);
-		queue->throttle = 0;
-		queue->cng_level = 0;
-		queue->avg_blog = 10; /* arbitrary non-zero */
 		queue->completion_queue = NULL;
 		INIT_LIST_HEAD(&queue->poll_list);
 		set_bit(__LINK_STATE_START, &queue->backlog_dev.state);
@@ -3315,11 +3212,6 @@
 		atomic_set(&queue->backlog_dev.refcnt, 1);
 	}
 
-#ifdef OFFLINE_SAMPLE
-	samp_timer.expires = jiffies + (10 * HZ);
-	add_timer(&samp_timer);
-#endif
-
 	dev_boot_phase = 0;
 
 	open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL);
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 8ec4848..a3eeb88 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -356,7 +356,7 @@
 {
 	struct ethtool_coalesce coalesce;
 
-	if (!dev->ethtool_ops->get_coalesce)
+	if (!dev->ethtool_ops->set_coalesce)
 		return -EOPNOTSUPP;
 
 	if (copy_from_user(&coalesce, useraddr, sizeof(coalesce)))
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 43bdc52..851eb92 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -32,6 +32,7 @@
 #include <net/sock.h>
 #include <linux/rtnetlink.h>
 #include <linux/random.h>
+#include <linux/string.h>
 
 #define NEIGH_DEBUG 1
 
@@ -1276,9 +1277,14 @@
 		INIT_RCU_HEAD(&p->rcu_head);
 		p->reachable_time =
 				neigh_rand_reach_time(p->base_reachable_time);
-		if (dev && dev->neigh_setup && dev->neigh_setup(dev, p)) {
-			kfree(p);
-			return NULL;
+		if (dev) {
+			if (dev->neigh_setup && dev->neigh_setup(dev, p)) {
+				kfree(p);
+				return NULL;
+			}
+
+			dev_hold(dev);
+			p->dev = dev;
 		}
 		p->sysctl_table = NULL;
 		write_lock_bh(&tbl->lock);
@@ -1309,6 +1315,8 @@
 			*p = parms->next;
 			parms->dead = 1;
 			write_unlock_bh(&tbl->lock);
+			if (parms->dev)
+				dev_put(parms->dev);
 			call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
 			return;
 		}
@@ -1546,20 +1554,323 @@
 	return err;
 }
 
+static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
+{
+	struct rtattr *nest = NULL;
+	
+	nest = RTA_NEST(skb, NDTA_PARMS);
+
+	if (parms->dev)
+		RTA_PUT_U32(skb, NDTPA_IFINDEX, parms->dev->ifindex);
+
+	RTA_PUT_U32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt));
+	RTA_PUT_U32(skb, NDTPA_QUEUE_LEN, parms->queue_len);
+	RTA_PUT_U32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen);
+	RTA_PUT_U32(skb, NDTPA_APP_PROBES, parms->app_probes);
+	RTA_PUT_U32(skb, NDTPA_UCAST_PROBES, parms->ucast_probes);
+	RTA_PUT_U32(skb, NDTPA_MCAST_PROBES, parms->mcast_probes);
+	RTA_PUT_MSECS(skb, NDTPA_REACHABLE_TIME, parms->reachable_time);
+	RTA_PUT_MSECS(skb, NDTPA_BASE_REACHABLE_TIME,
+		      parms->base_reachable_time);
+	RTA_PUT_MSECS(skb, NDTPA_GC_STALETIME, parms->gc_staletime);
+	RTA_PUT_MSECS(skb, NDTPA_DELAY_PROBE_TIME, parms->delay_probe_time);
+	RTA_PUT_MSECS(skb, NDTPA_RETRANS_TIME, parms->retrans_time);
+	RTA_PUT_MSECS(skb, NDTPA_ANYCAST_DELAY, parms->anycast_delay);
+	RTA_PUT_MSECS(skb, NDTPA_PROXY_DELAY, parms->proxy_delay);
+	RTA_PUT_MSECS(skb, NDTPA_LOCKTIME, parms->locktime);
+
+	return RTA_NEST_END(skb, nest);
+
+rtattr_failure:
+	return RTA_NEST_CANCEL(skb, nest);
+}
+
+static int neightbl_fill_info(struct neigh_table *tbl, struct sk_buff *skb,
+			      struct netlink_callback *cb)
+{
+	struct nlmsghdr *nlh;
+	struct ndtmsg *ndtmsg;
+
+	nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWNEIGHTBL, sizeof(struct ndtmsg),
+			       NLM_F_MULTI);
+
+	ndtmsg = NLMSG_DATA(nlh);
+
+	read_lock_bh(&tbl->lock);
+	ndtmsg->ndtm_family = tbl->family;
+
+	RTA_PUT_STRING(skb, NDTA_NAME, tbl->id);
+	RTA_PUT_MSECS(skb, NDTA_GC_INTERVAL, tbl->gc_interval);
+	RTA_PUT_U32(skb, NDTA_THRESH1, tbl->gc_thresh1);
+	RTA_PUT_U32(skb, NDTA_THRESH2, tbl->gc_thresh2);
+	RTA_PUT_U32(skb, NDTA_THRESH3, tbl->gc_thresh3);
+
+	{
+		unsigned long now = jiffies;
+		unsigned int flush_delta = now - tbl->last_flush;
+		unsigned int rand_delta = now - tbl->last_rand;
+
+		struct ndt_config ndc = {
+			.ndtc_key_len		= tbl->key_len,
+			.ndtc_entry_size	= tbl->entry_size,
+			.ndtc_entries		= atomic_read(&tbl->entries),
+			.ndtc_last_flush	= jiffies_to_msecs(flush_delta),
+			.ndtc_last_rand		= jiffies_to_msecs(rand_delta),
+			.ndtc_hash_rnd		= tbl->hash_rnd,
+			.ndtc_hash_mask		= tbl->hash_mask,
+			.ndtc_hash_chain_gc	= tbl->hash_chain_gc,
+			.ndtc_proxy_qlen	= tbl->proxy_queue.qlen,
+		};
+
+		RTA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc);
+	}
+
+	{
+		int cpu;
+		struct ndt_stats ndst;
+
+		memset(&ndst, 0, sizeof(ndst));
+
+		for (cpu = 0; cpu < NR_CPUS; cpu++) {
+			struct neigh_statistics	*st;
+
+			if (!cpu_possible(cpu))
+				continue;
+
+			st = per_cpu_ptr(tbl->stats, cpu);
+			ndst.ndts_allocs		+= st->allocs;
+			ndst.ndts_destroys		+= st->destroys;
+			ndst.ndts_hash_grows		+= st->hash_grows;
+			ndst.ndts_res_failed		+= st->res_failed;
+			ndst.ndts_lookups		+= st->lookups;
+			ndst.ndts_hits			+= st->hits;
+			ndst.ndts_rcv_probes_mcast	+= st->rcv_probes_mcast;
+			ndst.ndts_rcv_probes_ucast	+= st->rcv_probes_ucast;
+			ndst.ndts_periodic_gc_runs	+= st->periodic_gc_runs;
+			ndst.ndts_forced_gc_runs	+= st->forced_gc_runs;
+		}
+
+		RTA_PUT(skb, NDTA_STATS, sizeof(ndst), &ndst);
+	}
+
+	BUG_ON(tbl->parms.dev);
+	if (neightbl_fill_parms(skb, &tbl->parms) < 0)
+		goto rtattr_failure;
+
+	read_unlock_bh(&tbl->lock);
+	return NLMSG_END(skb, nlh);
+
+rtattr_failure:
+	read_unlock_bh(&tbl->lock);
+	return NLMSG_CANCEL(skb, nlh);
+ 
+nlmsg_failure:
+	return -1;
+}
+
+static int neightbl_fill_param_info(struct neigh_table *tbl,
+				    struct neigh_parms *parms,
+				    struct sk_buff *skb,
+				    struct netlink_callback *cb)
+{
+	struct ndtmsg *ndtmsg;
+	struct nlmsghdr *nlh;
+
+	nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWNEIGHTBL, sizeof(struct ndtmsg),
+			       NLM_F_MULTI);
+
+	ndtmsg = NLMSG_DATA(nlh);
+
+	read_lock_bh(&tbl->lock);
+	ndtmsg->ndtm_family = tbl->family;
+	RTA_PUT_STRING(skb, NDTA_NAME, tbl->id);
+
+	if (neightbl_fill_parms(skb, parms) < 0)
+		goto rtattr_failure;
+
+	read_unlock_bh(&tbl->lock);
+	return NLMSG_END(skb, nlh);
+
+rtattr_failure:
+	read_unlock_bh(&tbl->lock);
+	return NLMSG_CANCEL(skb, nlh);
+
+nlmsg_failure:
+	return -1;
+}
+ 
+static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
+						      int ifindex)
+{
+	struct neigh_parms *p;
+	
+	for (p = &tbl->parms; p; p = p->next)
+		if ((p->dev && p->dev->ifindex == ifindex) ||
+		    (!p->dev && !ifindex))
+			return p;
+
+	return NULL;
+}
+
+int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
+{
+	struct neigh_table *tbl;
+	struct ndtmsg *ndtmsg = NLMSG_DATA(nlh);
+	struct rtattr **tb = arg;
+	int err = -EINVAL;
+
+	if (!tb[NDTA_NAME - 1] || !RTA_PAYLOAD(tb[NDTA_NAME - 1]))
+		return -EINVAL;
+
+	read_lock(&neigh_tbl_lock);
+	for (tbl = neigh_tables; tbl; tbl = tbl->next) {
+		if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
+			continue;
+
+		if (!rtattr_strcmp(tb[NDTA_NAME - 1], tbl->id))
+			break;
+	}
+
+	if (tbl == NULL) {
+		err = -ENOENT;
+		goto errout;
+	}
+
+	/* 
+	 * We acquire tbl->lock to be nice to the periodic timers and
+	 * make sure they always see a consistent set of values.
+	 */
+	write_lock_bh(&tbl->lock);
+
+	if (tb[NDTA_THRESH1 - 1])
+		tbl->gc_thresh1 = RTA_GET_U32(tb[NDTA_THRESH1 - 1]);
+
+	if (tb[NDTA_THRESH2 - 1])
+		tbl->gc_thresh2 = RTA_GET_U32(tb[NDTA_THRESH2 - 1]);
+
+	if (tb[NDTA_THRESH3 - 1])
+		tbl->gc_thresh3 = RTA_GET_U32(tb[NDTA_THRESH3 - 1]);
+
+	if (tb[NDTA_GC_INTERVAL - 1])
+		tbl->gc_interval = RTA_GET_MSECS(tb[NDTA_GC_INTERVAL - 1]);
+
+	if (tb[NDTA_PARMS - 1]) {
+		struct rtattr *tbp[NDTPA_MAX];
+		struct neigh_parms *p;
+		u32 ifindex = 0;
+
+		if (rtattr_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS - 1]) < 0)
+			goto rtattr_failure;
+
+		if (tbp[NDTPA_IFINDEX - 1])
+			ifindex = RTA_GET_U32(tbp[NDTPA_IFINDEX - 1]);
+
+		p = lookup_neigh_params(tbl, ifindex);
+		if (p == NULL) {
+			err = -ENOENT;
+			goto rtattr_failure;
+		}
+	
+		if (tbp[NDTPA_QUEUE_LEN - 1])
+			p->queue_len = RTA_GET_U32(tbp[NDTPA_QUEUE_LEN - 1]);
+
+		if (tbp[NDTPA_PROXY_QLEN - 1])
+			p->proxy_qlen = RTA_GET_U32(tbp[NDTPA_PROXY_QLEN - 1]);
+
+		if (tbp[NDTPA_APP_PROBES - 1])
+			p->app_probes = RTA_GET_U32(tbp[NDTPA_APP_PROBES - 1]);
+
+		if (tbp[NDTPA_UCAST_PROBES - 1])
+			p->ucast_probes =
+			   RTA_GET_U32(tbp[NDTPA_UCAST_PROBES - 1]);
+
+		if (tbp[NDTPA_MCAST_PROBES - 1])
+			p->mcast_probes =
+			   RTA_GET_U32(tbp[NDTPA_MCAST_PROBES - 1]);
+
+		if (tbp[NDTPA_BASE_REACHABLE_TIME - 1])
+			p->base_reachable_time =
+			   RTA_GET_MSECS(tbp[NDTPA_BASE_REACHABLE_TIME - 1]);
+
+		if (tbp[NDTPA_GC_STALETIME - 1])
+			p->gc_staletime =
+			   RTA_GET_MSECS(tbp[NDTPA_GC_STALETIME - 1]);
+
+		if (tbp[NDTPA_DELAY_PROBE_TIME - 1])
+			p->delay_probe_time =
+			   RTA_GET_MSECS(tbp[NDTPA_DELAY_PROBE_TIME - 1]);
+
+		if (tbp[NDTPA_RETRANS_TIME - 1])
+			p->retrans_time =
+			   RTA_GET_MSECS(tbp[NDTPA_RETRANS_TIME - 1]);
+
+		if (tbp[NDTPA_ANYCAST_DELAY - 1])
+			p->anycast_delay =
+			   RTA_GET_MSECS(tbp[NDTPA_ANYCAST_DELAY - 1]);
+
+		if (tbp[NDTPA_PROXY_DELAY - 1])
+			p->proxy_delay =
+			   RTA_GET_MSECS(tbp[NDTPA_PROXY_DELAY - 1]);
+
+		if (tbp[NDTPA_LOCKTIME - 1])
+			p->locktime = RTA_GET_MSECS(tbp[NDTPA_LOCKTIME - 1]);
+	}
+
+	err = 0;
+
+rtattr_failure:
+	write_unlock_bh(&tbl->lock);
+errout:
+	read_unlock(&neigh_tbl_lock);
+	return err;
+}
+
+int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	int idx, family;
+	int s_idx = cb->args[0];
+	struct neigh_table *tbl;
+
+	family = ((struct rtgenmsg *)NLMSG_DATA(cb->nlh))->rtgen_family;
+
+	read_lock(&neigh_tbl_lock);
+	for (tbl = neigh_tables, idx = 0; tbl; tbl = tbl->next) {
+		struct neigh_parms *p;
+
+		if (idx < s_idx || (family && tbl->family != family))
+			continue;
+
+		if (neightbl_fill_info(tbl, skb, cb) <= 0)
+			break;
+
+		for (++idx, p = tbl->parms.next; p; p = p->next, idx++) {
+			if (idx < s_idx)
+				continue;
+
+			if (neightbl_fill_param_info(tbl, p, skb, cb) <= 0)
+				goto out;
+		}
+
+	}
+out:
+	read_unlock(&neigh_tbl_lock);
+	cb->args[0] = idx;
+
+	return skb->len;
+}
 
 static int neigh_fill_info(struct sk_buff *skb, struct neighbour *n,
-			   u32 pid, u32 seq, int event)
+			   u32 pid, u32 seq, int event, unsigned int flags)
 {
 	unsigned long now = jiffies;
 	unsigned char *b = skb->tail;
 	struct nda_cacheinfo ci;
 	int locked = 0;
 	u32 probes;
-	struct nlmsghdr *nlh = NLMSG_PUT(skb, pid, seq, event,
-					 sizeof(struct ndmsg));
+	struct nlmsghdr *nlh = NLMSG_NEW(skb, pid, seq, event,
+					 sizeof(struct ndmsg), flags);
 	struct ndmsg *ndm = NLMSG_DATA(nlh);
 
-	nlh->nlmsg_flags = pid ? NLM_F_MULTI : 0;
 	ndm->ndm_family	 = n->ops->family;
 	ndm->ndm_flags	 = n->flags;
 	ndm->ndm_type	 = n->type;
@@ -1609,7 +1920,8 @@
 				continue;
 			if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).pid,
 					    cb->nlh->nlmsg_seq,
-					    RTM_NEWNEIGH) <= 0) {
+					    RTM_NEWNEIGH,
+					    NLM_F_MULTI) <= 0) {
 				read_unlock_bh(&tbl->lock);
 				rc = -1;
 				goto out;
@@ -2018,7 +2330,7 @@
 	if (!skb)
 		return;
 
-	if (neigh_fill_info(skb, n, 0, 0, RTM_GETNEIGH) < 0) {
+	if (neigh_fill_info(skb, n, 0, 0, RTM_GETNEIGH, 0) < 0) {
 		kfree_skb(skb);
 		return;
 	}
@@ -2037,7 +2349,7 @@
 	if (!skb)
 		return;
 
-	if (neigh_fill_info(skb, n, 0, 0, RTM_NEWNEIGH) < 0) {
+	if (neigh_fill_info(skb, n, 0, 0, RTM_NEWNEIGH, 0) < 0) {
 		kfree_skb(skb);
 		return;
 	}
@@ -2281,7 +2593,7 @@
 		t->neigh_vars[17].extra1 = dev;
 	}
 
-	dev_name = net_sysctl_strdup(dev_name_source);
+	dev_name = kstrdup(dev_name_source, GFP_KERNEL);
 	if (!dev_name) {
 		err = -ENOBUFS;
 		goto free;
@@ -2352,6 +2664,8 @@
 EXPORT_SYMBOL(neigh_update_hhs);
 EXPORT_SYMBOL(pneigh_enqueue);
 EXPORT_SYMBOL(pneigh_lookup);
+EXPORT_SYMBOL(neightbl_dump_info);
+EXPORT_SYMBOL(neightbl_set);
 
 #ifdef CONFIG_ARPD
 EXPORT_SYMBOL(neigh_app_ns);
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 910eb4c..e2137f3 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -185,6 +185,22 @@
 static CLASS_DEVICE_ATTR(tx_queue_len, S_IRUGO | S_IWUSR, show_tx_queue_len, 
 			 store_tx_queue_len);
 
+NETDEVICE_SHOW(weight, fmt_dec);
+
+static int change_weight(struct net_device *net, unsigned long new_weight)
+{
+	net->weight = new_weight;
+	return 0;
+}
+
+static ssize_t store_weight(struct class_device *dev, const char *buf, size_t len)
+{
+	return netdev_store(dev, buf, len, change_weight);
+}
+
+static CLASS_DEVICE_ATTR(weight, S_IRUGO | S_IWUSR, show_weight, 
+			 store_weight);
+
 
 static struct class_device_attribute *net_class_attributes[] = {
 	&class_device_attr_ifindex,
@@ -194,6 +210,7 @@
 	&class_device_attr_features,
 	&class_device_attr_mtu,
 	&class_device_attr_flags,
+	&class_device_attr_weight,
 	&class_device_attr_type,
 	&class_device_attr_address,
 	&class_device_attr_broadcast,
diff --git a/net/core/netfilter.c b/net/core/netfilter.c
index 22a8f12..076c156 100644
--- a/net/core/netfilter.c
+++ b/net/core/netfilter.c
@@ -141,136 +141,6 @@
 	up(&nf_sockopt_mutex);
 }
 
-#ifdef CONFIG_NETFILTER_DEBUG
-#include <net/ip.h>
-#include <net/tcp.h>
-#include <linux/netfilter_ipv4.h>
-
-static void debug_print_hooks_ip(unsigned int nf_debug)
-{
-	if (nf_debug & (1 << NF_IP_PRE_ROUTING)) {
-		printk("PRE_ROUTING ");
-		nf_debug ^= (1 << NF_IP_PRE_ROUTING);
-	}
-	if (nf_debug & (1 << NF_IP_LOCAL_IN)) {
-		printk("LOCAL_IN ");
-		nf_debug ^= (1 << NF_IP_LOCAL_IN);
-	}
-	if (nf_debug & (1 << NF_IP_FORWARD)) {
-		printk("FORWARD ");
-		nf_debug ^= (1 << NF_IP_FORWARD);
-	}
-	if (nf_debug & (1 << NF_IP_LOCAL_OUT)) {
-		printk("LOCAL_OUT ");
-		nf_debug ^= (1 << NF_IP_LOCAL_OUT);
-	}
-	if (nf_debug & (1 << NF_IP_POST_ROUTING)) {
-		printk("POST_ROUTING ");
-		nf_debug ^= (1 << NF_IP_POST_ROUTING);
-	}
-	if (nf_debug)
-		printk("Crap bits: 0x%04X", nf_debug);
-	printk("\n");
-}
-
-static void nf_dump_skb(int pf, struct sk_buff *skb)
-{
-	printk("skb: pf=%i %s dev=%s len=%u\n", 
-	       pf,
-	       skb->sk ? "(owned)" : "(unowned)",
-	       skb->dev ? skb->dev->name : "(no dev)",
-	       skb->len);
-	switch (pf) {
-	case PF_INET: {
-		const struct iphdr *ip = skb->nh.iph;
-		__u32 *opt = (__u32 *) (ip + 1);
-		int opti;
-		__u16 src_port = 0, dst_port = 0;
-
-		if (ip->protocol == IPPROTO_TCP
-		    || ip->protocol == IPPROTO_UDP) {
-			struct tcphdr *tcp=(struct tcphdr *)((__u32 *)ip+ip->ihl);
-			src_port = ntohs(tcp->source);
-			dst_port = ntohs(tcp->dest);
-		}
-	
-		printk("PROTO=%d %u.%u.%u.%u:%hu %u.%u.%u.%u:%hu"
-		       " L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu",
-		       ip->protocol, NIPQUAD(ip->saddr),
-		       src_port, NIPQUAD(ip->daddr),
-		       dst_port,
-		       ntohs(ip->tot_len), ip->tos, ntohs(ip->id),
-		       ntohs(ip->frag_off), ip->ttl);
-
-		for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++)
-			printk(" O=0x%8.8X", *opt++);
-		printk("\n");
-	}
-	}
-}
-
-void nf_debug_ip_local_deliver(struct sk_buff *skb)
-{
-	/* If it's a loopback packet, it must have come through
-	 * NF_IP_LOCAL_OUT, NF_IP_RAW_INPUT, NF_IP_PRE_ROUTING and
-	 * NF_IP_LOCAL_IN.  Otherwise, must have gone through
-	 * NF_IP_RAW_INPUT and NF_IP_PRE_ROUTING.  */
-	if (!skb->dev) {
-		printk("ip_local_deliver: skb->dev is NULL.\n");
-	} else {
-		if (skb->nf_debug != ((1<<NF_IP_PRE_ROUTING)
-				      | (1<<NF_IP_LOCAL_IN))) {
-			printk("ip_local_deliver: bad skb: ");
-			debug_print_hooks_ip(skb->nf_debug);
-			nf_dump_skb(PF_INET, skb);
-		}
-	}
-}
-
-void nf_debug_ip_loopback_xmit(struct sk_buff *newskb)
-{
-	if (newskb->nf_debug != ((1 << NF_IP_LOCAL_OUT)
-				 | (1 << NF_IP_POST_ROUTING))) {
-		printk("ip_dev_loopback_xmit: bad owned skb = %p: ", 
-		       newskb);
-		debug_print_hooks_ip(newskb->nf_debug);
-		nf_dump_skb(PF_INET, newskb);
-	}
-}
-
-void nf_debug_ip_finish_output2(struct sk_buff *skb)
-{
-	/* If it's owned, it must have gone through the
-	 * NF_IP_LOCAL_OUT and NF_IP_POST_ROUTING.
-	 * Otherwise, must have gone through
-	 * NF_IP_PRE_ROUTING, NF_IP_FORWARD and NF_IP_POST_ROUTING.
-	 */
-	if (skb->sk) {
-		if (skb->nf_debug != ((1 << NF_IP_LOCAL_OUT)
-				      | (1 << NF_IP_POST_ROUTING))) {
-			printk("ip_finish_output: bad owned skb = %p: ", skb);
-			debug_print_hooks_ip(skb->nf_debug);
-			nf_dump_skb(PF_INET, skb);
-		}
-	} else {
-		if (skb->nf_debug != ((1 << NF_IP_PRE_ROUTING)
-				      | (1 << NF_IP_FORWARD)
-				      | (1 << NF_IP_POST_ROUTING))) {
-			/* Fragments, entunnelled packets, TCP RSTs
-                           generated by ipt_REJECT will have no
-                           owners, but still may be local */
-			if (skb->nf_debug != ((1 << NF_IP_LOCAL_OUT)
-					      | (1 << NF_IP_POST_ROUTING))){
-				printk("ip_finish_output:"
-				       " bad unowned skb = %p: ",skb);
-				debug_print_hooks_ip(skb->nf_debug);
-				nf_dump_skb(PF_INET, skb);
-			}
-		}
-	}
-}
-#endif /*CONFIG_NETFILTER_DEBUG*/
-
 /* Call get/setsockopt() */
 static int nf_sockopt(struct sock *sk, int pf, int val, 
 		      char __user *opt, int *len, int get)
@@ -488,14 +358,6 @@
 	/* We may already have this, but read-locks nest anyway */
 	rcu_read_lock();
 
-#ifdef CONFIG_NETFILTER_DEBUG
-	if (unlikely((*pskb)->nf_debug & (1 << hook))) {
-		printk("nf_hook: hook %i already set.\n", hook);
-		nf_dump_skb(pf, *pskb);
-	}
-	(*pskb)->nf_debug |= (1 << hook);
-#endif
-
 	elem = &nf_hooks[pf][hook];
 next_hook:
 	verdict = nf_iterate(&nf_hooks[pf][hook], pskb, hook, indev,
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index a119696..c327c9e 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -130,19 +130,20 @@
  */
 static void poll_napi(struct netpoll *np)
 {
+	struct netpoll_info *npinfo = np->dev->npinfo;
 	int budget = 16;
 
 	if (test_bit(__LINK_STATE_RX_SCHED, &np->dev->state) &&
-	    np->poll_owner != smp_processor_id() &&
-	    spin_trylock(&np->poll_lock)) {
-		np->rx_flags |= NETPOLL_RX_DROP;
+	    npinfo->poll_owner != smp_processor_id() &&
+	    spin_trylock(&npinfo->poll_lock)) {
+		npinfo->rx_flags |= NETPOLL_RX_DROP;
 		atomic_inc(&trapped);
 
 		np->dev->poll(np->dev, &budget);
 
 		atomic_dec(&trapped);
-		np->rx_flags &= ~NETPOLL_RX_DROP;
-		spin_unlock(&np->poll_lock);
+		npinfo->rx_flags &= ~NETPOLL_RX_DROP;
+		spin_unlock(&npinfo->poll_lock);
 	}
 }
 
@@ -245,6 +246,7 @@
 static void netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
 {
 	int status;
+	struct netpoll_info *npinfo;
 
 repeat:
 	if(!np || !np->dev || !netif_running(np->dev)) {
@@ -253,8 +255,9 @@
 	}
 
 	/* avoid recursion */
-	if(np->poll_owner == smp_processor_id() ||
-	   np->dev->xmit_lock_owner == smp_processor_id()) {
+	npinfo = np->dev->npinfo;
+	if (npinfo->poll_owner == smp_processor_id() ||
+	    np->dev->xmit_lock_owner == smp_processor_id()) {
 		if (np->drop)
 			np->drop(skb);
 		else
@@ -341,14 +344,22 @@
 
 static void arp_reply(struct sk_buff *skb)
 {
+	struct netpoll_info *npinfo = skb->dev->npinfo;
 	struct arphdr *arp;
 	unsigned char *arp_ptr;
 	int size, type = ARPOP_REPLY, ptype = ETH_P_ARP;
 	u32 sip, tip;
+	unsigned long flags;
 	struct sk_buff *send_skb;
-	struct netpoll *np = skb->dev->np;
+	struct netpoll *np = NULL;
 
-	if (!np) return;
+	spin_lock_irqsave(&npinfo->rx_lock, flags);
+	if (npinfo->rx_np && npinfo->rx_np->dev == skb->dev)
+		np = npinfo->rx_np;
+	spin_unlock_irqrestore(&npinfo->rx_lock, flags);
+
+	if (!np)
+		return;
 
 	/* No arp on this interface */
 	if (skb->dev->flags & IFF_NOARP)
@@ -429,9 +440,9 @@
 	int proto, len, ulen;
 	struct iphdr *iph;
 	struct udphdr *uh;
-	struct netpoll *np = skb->dev->np;
+	struct netpoll *np = skb->dev->npinfo->rx_np;
 
-	if (!np->rx_hook)
+	if (!np)
 		goto out;
 	if (skb->dev->type != ARPHRD_ETHER)
 		goto out;
@@ -611,9 +622,8 @@
 {
 	struct net_device *ndev = NULL;
 	struct in_device *in_dev;
-
-	np->poll_lock = SPIN_LOCK_UNLOCKED;
-	np->poll_owner = -1;
+	struct netpoll_info *npinfo;
+	unsigned long flags;
 
 	if (np->dev_name)
 		ndev = dev_get_by_name(np->dev_name);
@@ -624,7 +634,17 @@
 	}
 
 	np->dev = ndev;
-	ndev->np = np;
+	if (!ndev->npinfo) {
+		npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL);
+		if (!npinfo)
+			goto release;
+
+		npinfo->rx_np = NULL;
+		npinfo->poll_lock = SPIN_LOCK_UNLOCKED;
+		npinfo->poll_owner = -1;
+		npinfo->rx_lock = SPIN_LOCK_UNLOCKED;
+	} else
+		npinfo = ndev->npinfo;
 
 	if (!ndev->poll_controller) {
 		printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n",
@@ -692,13 +712,20 @@
 		       np->name, HIPQUAD(np->local_ip));
 	}
 
-	if(np->rx_hook)
-		np->rx_flags = NETPOLL_RX_ENABLED;
+	if (np->rx_hook) {
+		spin_lock_irqsave(&npinfo->rx_lock, flags);
+		npinfo->rx_flags |= NETPOLL_RX_ENABLED;
+		npinfo->rx_np = np;
+		spin_unlock_irqrestore(&npinfo->rx_lock, flags);
+	}
+	/* last thing to do is link it to the net device structure */
+	ndev->npinfo = npinfo;
 
 	return 0;
 
  release:
-	ndev->np = NULL;
+	if (!ndev->npinfo)
+		kfree(npinfo);
 	np->dev = NULL;
 	dev_put(ndev);
 	return -1;
@@ -706,9 +733,20 @@
 
 void netpoll_cleanup(struct netpoll *np)
 {
-	if (np->dev)
-		np->dev->np = NULL;
-	dev_put(np->dev);
+	struct netpoll_info *npinfo;
+	unsigned long flags;
+
+	if (np->dev) {
+		npinfo = np->dev->npinfo;
+		if (npinfo && npinfo->rx_np == np) {
+			spin_lock_irqsave(&npinfo->rx_lock, flags);
+			npinfo->rx_np = NULL;
+			npinfo->rx_flags &= ~NETPOLL_RX_ENABLED;
+			spin_unlock_irqrestore(&npinfo->rx_lock, flags);
+		}
+		dev_put(np->dev);
+	}
+
 	np->dev = NULL;
 }
 
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index c57b06b..975d651 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -151,7 +151,7 @@
 #include <asm/timex.h>
 
 
-#define VERSION  "pktgen v2.61: Packet Generator for packet performance testing.\n"
+#define VERSION  "pktgen v2.62: Packet Generator for packet performance testing.\n"
 
 /* #define PG_DEBUG(a) a */
 #define PG_DEBUG(a) 
@@ -1921,6 +1921,11 @@
 	struct iphdr *iph;
         struct pktgen_hdr *pgh = NULL;
         
+	/* Update any of the values, used when we're incrementing various
+	 * fields.
+	 */
+	mod_cur_headers(pkt_dev);
+
 	skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16, GFP_ATOMIC);
 	if (!skb) {
 		sprintf(pkt_dev->result, "No memory");
@@ -1934,11 +1939,6 @@
 	iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr));
 	udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
 
-        /* Update any of the values, used when we're incrementing various
-         * fields.
-         */
-        mod_cur_headers(pkt_dev);
-
 	memcpy(eth, pkt_dev->hh, 12);
 	*(u16*)&eth[12] = __constant_htons(ETH_P_IP);
 
@@ -2192,7 +2192,12 @@
 	int datalen;
 	struct ipv6hdr *iph;
         struct pktgen_hdr *pgh = NULL;
-        
+
+	/* Update any of the values, used when we're incrementing various
+	 * fields.
+	 */
+	mod_cur_headers(pkt_dev);
+
 	skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16, GFP_ATOMIC);
 	if (!skb) {
 		sprintf(pkt_dev->result, "No memory");
@@ -2206,17 +2211,9 @@
 	iph = (struct ipv6hdr *)skb_put(skb, sizeof(struct ipv6hdr));
 	udph = (struct udphdr *)skb_put(skb, sizeof(struct udphdr));
 
-
-        /* Update any of the values, used when we're incrementing various
-         * fields.
-         */
-	mod_cur_headers(pkt_dev);
-
-	
 	memcpy(eth, pkt_dev->hh, 12);
 	*(u16*)&eth[12] = __constant_htons(ETH_P_IPV6);
-	
-        
+
 	datalen = pkt_dev->cur_pkt_size-14- 
 		sizeof(struct ipv6hdr)-sizeof(struct udphdr); /* Eth + IPh + UDPh */
 
diff --git a/net/core/request_sock.c b/net/core/request_sock.c
new file mode 100644
index 0000000..bb55675
--- /dev/null
+++ b/net/core/request_sock.c
@@ -0,0 +1,64 @@
+/*
+ * NET		Generic infrastructure for Network protocols.
+ *
+ * Authors:	Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * 		From code originally in include/net/tcp.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.
+ */
+
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include <net/request_sock.h>
+
+/*
+ * Maximum number of SYN_RECV sockets in queue per LISTEN socket.
+ * One SYN_RECV socket costs about 80bytes on a 32bit machine.
+ * It would be better to replace it with a global counter for all sockets
+ * but then some measure against one socket starving all other sockets
+ * would be needed.
+ *
+ * It was 128 by default. Experiments with real servers show, that
+ * it is absolutely not enough even at 100conn/sec. 256 cures most
+ * of problems. This value is adjusted to 128 for very small machines
+ * (<=32Mb of memory) and to 1024 on normal or better ones (>=256Mb).
+ * Further increasing requires to change hash table size.
+ */
+int sysctl_max_syn_backlog = 256;
+EXPORT_SYMBOL(sysctl_max_syn_backlog);
+
+int reqsk_queue_alloc(struct request_sock_queue *queue,
+		      const int nr_table_entries)
+{
+	const int lopt_size = sizeof(struct listen_sock) +
+			      nr_table_entries * sizeof(struct request_sock *);
+	struct listen_sock *lopt = kmalloc(lopt_size, GFP_KERNEL);
+
+	if (lopt == NULL)
+		return -ENOMEM;
+
+	memset(lopt, 0, lopt_size);
+
+	for (lopt->max_qlen_log = 6;
+	     (1 << lopt->max_qlen_log) < sysctl_max_syn_backlog;
+	     lopt->max_qlen_log++);
+
+	get_random_bytes(&lopt->hash_rnd, sizeof(lopt->hash_rnd));
+	rwlock_init(&queue->syn_wait_lock);
+	queue->rskq_accept_head = queue->rskq_accept_head = NULL;
+
+	write_lock_bh(&queue->syn_wait_lock);
+	queue->listen_opt = lopt;
+	write_unlock_bh(&queue->syn_wait_lock);
+
+	return 0;
+}
+
+EXPORT_SYMBOL(reqsk_queue_alloc);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 00caf4b..e013d83 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -100,6 +100,7 @@
 	[RTM_FAM(RTM_NEWPREFIX)]    = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
 	[RTM_FAM(RTM_GETMULTICAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
 	[RTM_FAM(RTM_GETANYCAST)]   = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
+	[RTM_FAM(RTM_NEWNEIGHTBL)]  = NLMSG_LENGTH(sizeof(struct ndtmsg)),
 };
 
 static const int rta_max[RTM_NR_FAMILIES] =
@@ -113,6 +114,7 @@
 	[RTM_FAM(RTM_NEWTCLASS)]    = TCA_MAX,
 	[RTM_FAM(RTM_NEWTFILTER)]   = TCA_MAX,
 	[RTM_FAM(RTM_NEWACTION)]    = TCAA_MAX,
+	[RTM_FAM(RTM_NEWNEIGHTBL)]  = NDTA_MAX,
 };
 
 void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data)
@@ -176,14 +178,14 @@
 
 
 static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
-				 int type, u32 pid, u32 seq, u32 change)
+				 int type, u32 pid, u32 seq, u32 change, 
+				 unsigned int flags)
 {
 	struct ifinfomsg *r;
 	struct nlmsghdr  *nlh;
 	unsigned char	 *b = skb->tail;
 
-	nlh = NLMSG_PUT(skb, pid, seq, type, sizeof(*r));
-	if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;
+	nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*r), flags);
 	r = NLMSG_DATA(nlh);
 	r->ifi_family = AF_UNSPEC;
 	r->ifi_type = dev->type;
@@ -273,7 +275,10 @@
 	for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) {
 		if (idx < s_idx)
 			continue;
-		if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, 0) <= 0)
+		if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK,
+					  NETLINK_CB(cb->skb).pid,
+					  cb->nlh->nlmsg_seq, 0,
+					  NLM_F_MULTI) <= 0)
 			break;
 	}
 	read_unlock(&dev_base_lock);
@@ -447,7 +452,7 @@
 	if (!skb)
 		return;
 
-	if (rtnetlink_fill_ifinfo(skb, dev, type, 0, 0, change) < 0) {
+	if (rtnetlink_fill_ifinfo(skb, dev, type, current->pid, 0, change, 0) < 0) {
 		kfree_skb(skb);
 		return;
 	}
@@ -649,14 +654,16 @@
 
 static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] =
 {
-	[RTM_GETLINK  - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo },
-	[RTM_SETLINK  - RTM_BASE] = { .doit   = do_setlink	      },
-	[RTM_GETADDR  - RTM_BASE] = { .dumpit = rtnetlink_dump_all    },
-	[RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all    },
-	[RTM_NEWNEIGH - RTM_BASE] = { .doit   = neigh_add	      },
-	[RTM_DELNEIGH - RTM_BASE] = { .doit   = neigh_delete	      },
-	[RTM_GETNEIGH - RTM_BASE] = { .dumpit = neigh_dump_info	      },
-	[RTM_GETRULE  - RTM_BASE] = { .dumpit = rtnetlink_dump_all    },
+	[RTM_GETLINK     - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo },
+	[RTM_SETLINK     - RTM_BASE] = { .doit   = do_setlink		 },
+	[RTM_GETADDR     - RTM_BASE] = { .dumpit = rtnetlink_dump_all	 },
+	[RTM_GETROUTE    - RTM_BASE] = { .dumpit = rtnetlink_dump_all	 },
+	[RTM_NEWNEIGH    - RTM_BASE] = { .doit   = neigh_add		 },
+	[RTM_DELNEIGH    - RTM_BASE] = { .doit   = neigh_delete		 },
+	[RTM_GETNEIGH    - RTM_BASE] = { .dumpit = neigh_dump_info	 },
+	[RTM_GETRULE     - RTM_BASE] = { .dumpit = rtnetlink_dump_all	 },
+	[RTM_GETNEIGHTBL - RTM_BASE] = { .dumpit = neightbl_dump_info	 },
+	[RTM_SETNEIGHTBL - RTM_BASE] = { .doit   = neightbl_set		 },
 };
 
 static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index f65b3de..bb73b21 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -365,9 +365,6 @@
 	C(nfct);
 	nf_conntrack_get(skb->nfct);
 	C(nfctinfo);
-#ifdef CONFIG_NETFILTER_DEBUG
-	C(nf_debug);
-#endif
 #ifdef CONFIG_BRIDGE_NETFILTER
 	C(nf_bridge);
 	nf_bridge_get(skb->nf_bridge);
@@ -432,9 +429,6 @@
 	new->nfct	= old->nfct;
 	nf_conntrack_get(old->nfct);
 	new->nfctinfo	= old->nfctinfo;
-#ifdef CONFIG_NETFILTER_DEBUG
-	new->nf_debug	= old->nf_debug;
-#endif
 #ifdef CONFIG_BRIDGE_NETFILTER
 	new->nf_bridge	= old->nf_bridge;
 	nf_bridge_get(old->nf_bridge);
@@ -1506,6 +1500,159 @@
 		skb_split_no_header(skb, skb1, len, pos);
 }
 
+/**
+ * skb_prepare_seq_read - Prepare a sequential read of skb data
+ * @skb: the buffer to read
+ * @from: lower offset of data to be read
+ * @to: upper offset of data to be read
+ * @st: state variable
+ *
+ * Initializes the specified state variable. Must be called before
+ * invoking skb_seq_read() for the first time.
+ */
+void skb_prepare_seq_read(struct sk_buff *skb, unsigned int from,
+			  unsigned int to, struct skb_seq_state *st)
+{
+	st->lower_offset = from;
+	st->upper_offset = to;
+	st->root_skb = st->cur_skb = skb;
+	st->frag_idx = st->stepped_offset = 0;
+	st->frag_data = NULL;
+}
+
+/**
+ * skb_seq_read - Sequentially read skb data
+ * @consumed: number of bytes consumed by the caller so far
+ * @data: destination pointer for data to be returned
+ * @st: state variable
+ *
+ * Reads a block of skb data at &consumed relative to the
+ * lower offset specified to skb_prepare_seq_read(). Assigns
+ * the head of the data block to &data and returns the length
+ * of the block or 0 if the end of the skb data or the upper
+ * offset has been reached.
+ *
+ * The caller is not required to consume all of the data
+ * returned, i.e. &consumed is typically set to the number
+ * of bytes already consumed and the next call to
+ * skb_seq_read() will return the remaining part of the block.
+ *
+ * Note: The size of each block of data returned can be arbitary,
+ *       this limitation is the cost for zerocopy seqeuental
+ *       reads of potentially non linear data.
+ *
+ * Note: Fragment lists within fragments are not implemented
+ *       at the moment, state->root_skb could be replaced with
+ *       a stack for this purpose.
+ */
+unsigned int skb_seq_read(unsigned int consumed, const u8 **data,
+			  struct skb_seq_state *st)
+{
+	unsigned int block_limit, abs_offset = consumed + st->lower_offset;
+	skb_frag_t *frag;
+
+	if (unlikely(abs_offset >= st->upper_offset))
+		return 0;
+
+next_skb:
+	block_limit = skb_headlen(st->cur_skb);
+
+	if (abs_offset < block_limit) {
+		*data = st->cur_skb->data + abs_offset;
+		return block_limit - abs_offset;
+	}
+
+	if (st->frag_idx == 0 && !st->frag_data)
+		st->stepped_offset += skb_headlen(st->cur_skb);
+
+	while (st->frag_idx < skb_shinfo(st->cur_skb)->nr_frags) {
+		frag = &skb_shinfo(st->cur_skb)->frags[st->frag_idx];
+		block_limit = frag->size + st->stepped_offset;
+
+		if (abs_offset < block_limit) {
+			if (!st->frag_data)
+				st->frag_data = kmap_skb_frag(frag);
+
+			*data = (u8 *) st->frag_data + frag->page_offset +
+				(abs_offset - st->stepped_offset);
+
+			return block_limit - abs_offset;
+		}
+
+		if (st->frag_data) {
+			kunmap_skb_frag(st->frag_data);
+			st->frag_data = NULL;
+		}
+
+		st->frag_idx++;
+		st->stepped_offset += frag->size;
+	}
+
+	if (st->cur_skb->next) {
+		st->cur_skb = st->cur_skb->next;
+		st->frag_idx = 0;
+		goto next_skb;
+	} else if (st->root_skb == st->cur_skb &&
+		   skb_shinfo(st->root_skb)->frag_list) {
+		st->cur_skb = skb_shinfo(st->root_skb)->frag_list;
+		goto next_skb;
+	}
+
+	return 0;
+}
+
+/**
+ * skb_abort_seq_read - Abort a sequential read of skb data
+ * @st: state variable
+ *
+ * Must be called if skb_seq_read() was not called until it
+ * returned 0.
+ */
+void skb_abort_seq_read(struct skb_seq_state *st)
+{
+	if (st->frag_data)
+		kunmap_skb_frag(st->frag_data);
+}
+
+#define TS_SKB_CB(state)	((struct skb_seq_state *) &((state)->cb))
+
+static unsigned int skb_ts_get_next_block(unsigned int offset, const u8 **text,
+					  struct ts_config *conf,
+					  struct ts_state *state)
+{
+	return skb_seq_read(offset, text, TS_SKB_CB(state));
+}
+
+static void skb_ts_finish(struct ts_config *conf, struct ts_state *state)
+{
+	skb_abort_seq_read(TS_SKB_CB(state));
+}
+
+/**
+ * skb_find_text - Find a text pattern in skb data
+ * @skb: the buffer to look in
+ * @from: search offset
+ * @to: search limit
+ * @config: textsearch configuration
+ * @state: uninitialized textsearch state variable
+ *
+ * Finds a pattern in the skb data according to the specified
+ * textsearch configuration. Use textsearch_next() to retrieve
+ * subsequent occurrences of the pattern. Returns the offset
+ * to the first occurrence or UINT_MAX if no match was found.
+ */
+unsigned int skb_find_text(struct sk_buff *skb, unsigned int from,
+			   unsigned int to, struct ts_config *config,
+			   struct ts_state *state)
+{
+	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);
+}
+
 void __init skb_init(void)
 {
 	skbuff_head_cache = kmem_cache_create("skbuff_head_cache",
@@ -1544,3 +1691,7 @@
 EXPORT_SYMBOL(skb_unlink);
 EXPORT_SYMBOL(skb_append);
 EXPORT_SYMBOL(skb_split);
+EXPORT_SYMBOL(skb_prepare_seq_read);
+EXPORT_SYMBOL(skb_seq_read);
+EXPORT_SYMBOL(skb_abort_seq_read);
+EXPORT_SYMBOL(skb_find_text);
diff --git a/net/core/sock.c b/net/core/sock.c
index 96e00b0..a6ec3ad 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -118,6 +118,7 @@
 #include <linux/netdevice.h>
 #include <net/protocol.h>
 #include <linux/skbuff.h>
+#include <net/request_sock.h>
 #include <net/sock.h>
 #include <net/xfrm.h>
 #include <linux/ipsec.h>
@@ -1363,6 +1364,7 @@
 
 int proto_register(struct proto *prot, int alloc_slab)
 {
+	char *request_sock_slab_name;
 	int rc = -ENOBUFS;
 
 	if (alloc_slab) {
@@ -1374,6 +1376,25 @@
 			       prot->name);
 			goto out;
 		}
+
+		if (prot->rsk_prot != NULL) {
+			static const char mask[] = "request_sock_%s";
+
+			request_sock_slab_name = kmalloc(strlen(prot->name) + sizeof(mask) - 1, GFP_KERNEL);
+			if (request_sock_slab_name == NULL)
+				goto out_free_sock_slab;
+
+			sprintf(request_sock_slab_name, mask, prot->name);
+			prot->rsk_prot->slab = kmem_cache_create(request_sock_slab_name,
+								 prot->rsk_prot->obj_size, 0,
+								 SLAB_HWCACHE_ALIGN, NULL, NULL);
+
+			if (prot->rsk_prot->slab == NULL) {
+				printk(KERN_CRIT "%s: Can't create request sock SLAB cache!\n",
+				       prot->name);
+				goto out_free_request_sock_slab_name;
+			}
+		}
 	}
 
 	write_lock(&proto_list_lock);
@@ -1382,6 +1403,12 @@
 	rc = 0;
 out:
 	return rc;
+out_free_request_sock_slab_name:
+	kfree(request_sock_slab_name);
+out_free_sock_slab:
+	kmem_cache_destroy(prot->slab);
+	prot->slab = NULL;
+	goto out;
 }
 
 EXPORT_SYMBOL(proto_register);
@@ -1395,6 +1422,14 @@
 		prot->slab = NULL;
 	}
 
+	if (prot->rsk_prot != NULL && prot->rsk_prot->slab != NULL) {
+		const char *name = kmem_cache_name(prot->rsk_prot->slab);
+
+		kmem_cache_destroy(prot->rsk_prot->slab);
+		kfree(name);
+		prot->rsk_prot->slab = NULL;
+	}
+
 	list_del(&prot->node);
 	write_unlock(&proto_list_lock);
 }
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index c8be646..8f817ad 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -13,12 +13,8 @@
 #ifdef CONFIG_SYSCTL
 
 extern int netdev_max_backlog;
+extern int netdev_budget;
 extern int weight_p;
-extern int no_cong_thresh;
-extern int no_cong;
-extern int lo_cong;
-extern int mod_cong;
-extern int netdev_fastroute;
 extern int net_msg_cost;
 extern int net_msg_burst;
 
@@ -35,19 +31,6 @@
 extern char sysctl_divert_version[];
 #endif /* CONFIG_NET_DIVERT */
 
-/*
- * This strdup() is used for creating copies of network 
- * device names to be handed over to sysctl.
- */
- 
-char *net_sysctl_strdup(const char *s)
-{
-	char *rv = kmalloc(strlen(s)+1, GFP_KERNEL);
-	if (rv)
-		strcpy(rv, s);
-	return rv;
-}
-
 ctl_table core_table[] = {
 #ifdef CONFIG_NET
 	{
@@ -99,38 +82,6 @@
 		.proc_handler	= &proc_dointvec
 	},
 	{
-		.ctl_name	= NET_CORE_NO_CONG_THRESH,
-		.procname	= "no_cong_thresh",
-		.data		= &no_cong_thresh,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
-	},
-	{
-		.ctl_name	= NET_CORE_NO_CONG,
-		.procname	= "no_cong",
-		.data		= &no_cong,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
-	},
-	{
-		.ctl_name	= NET_CORE_LO_CONG,
-		.procname	= "lo_cong",
-		.data		= &lo_cong,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
-	},
-	{
-		.ctl_name	= NET_CORE_MOD_CONG,
-		.procname	= "mod_cong",
-		.data		= &mod_cong,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec
-	},
-	{
 		.ctl_name	= NET_CORE_MSG_COST,
 		.procname	= "message_cost",
 		.data		= &net_msg_cost,
@@ -174,9 +125,15 @@
 		.mode		= 0644,
 		.proc_handler	= &proc_dointvec
 	},
+	{
+		.ctl_name	= NET_CORE_BUDGET,
+		.procname	= "netdev_budget",
+		.data		= &netdev_budget,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec
+	},
 	{ .ctl_name = 0 }
 };
 
-EXPORT_SYMBOL(net_sysctl_strdup);
-
 #endif
diff --git a/net/core/wireless.c b/net/core/wireless.c
index 750cc5d..b2fe378 100644
--- a/net/core/wireless.c
+++ b/net/core/wireless.c
@@ -2,7 +2,7 @@
  * This file implement the Wireless Extensions APIs.
  *
  * Authors :	Jean Tourrilhes - HPL - <jt@hpl.hp.com>
- * Copyright (c) 1997-2004 Jean Tourrilhes, All Rights Reserved.
+ * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved.
  *
  * (As all part of the Linux kernel, this file is GPL)
  */
@@ -187,6 +187,12 @@
 		.header_type	= IW_HEADER_TYPE_ADDR,
 		.flags		= IW_DESCR_FLAG_DUMP,
 	},
+	[SIOCSIWMLME	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= 1,
+		.min_tokens	= sizeof(struct iw_mlme),
+		.max_tokens	= sizeof(struct iw_mlme),
+	},
 	[SIOCGIWAPLIST	- SIOCIWFIRST] = {
 		.header_type	= IW_HEADER_TYPE_POINT,
 		.token_size	= sizeof(struct sockaddr) +
@@ -195,7 +201,10 @@
 		.flags		= IW_DESCR_FLAG_NOMAX,
 	},
 	[SIOCSIWSCAN	- SIOCIWFIRST] = {
-		.header_type	= IW_HEADER_TYPE_PARAM,
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= 1,
+		.min_tokens	= 0,
+		.max_tokens	= sizeof(struct iw_scan_req),
 	},
 	[SIOCGIWSCAN	- SIOCIWFIRST] = {
 		.header_type	= IW_HEADER_TYPE_POINT,
@@ -273,6 +282,42 @@
 	[SIOCGIWPOWER	- SIOCIWFIRST] = {
 		.header_type	= IW_HEADER_TYPE_PARAM,
 	},
+	[SIOCSIWGENIE	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= 1,
+		.max_tokens	= IW_GENERIC_IE_MAX,
+	},
+	[SIOCGIWGENIE	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= 1,
+		.max_tokens	= IW_GENERIC_IE_MAX,
+	},
+	[SIOCSIWAUTH	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_PARAM,
+	},
+	[SIOCGIWAUTH	- SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_PARAM,
+	},
+	[SIOCSIWENCODEEXT - SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= 1,
+		.min_tokens	= sizeof(struct iw_encode_ext),
+		.max_tokens	= sizeof(struct iw_encode_ext) +
+				  IW_ENCODING_TOKEN_MAX,
+	},
+	[SIOCGIWENCODEEXT - SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= 1,
+		.min_tokens	= sizeof(struct iw_encode_ext),
+		.max_tokens	= sizeof(struct iw_encode_ext) +
+				  IW_ENCODING_TOKEN_MAX,
+	},
+	[SIOCSIWPMKSA - SIOCIWFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= 1,
+		.min_tokens	= sizeof(struct iw_pmksa),
+		.max_tokens	= sizeof(struct iw_pmksa),
+	},
 };
 static const int standard_ioctl_num = (sizeof(standard_ioctl) /
 				       sizeof(struct iw_ioctl_description));
@@ -299,6 +344,31 @@
 	[IWEVEXPIRED	- IWEVFIRST] = {
 		.header_type	= IW_HEADER_TYPE_ADDR, 
 	},
+	[IWEVGENIE	- IWEVFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= 1,
+		.max_tokens	= IW_GENERIC_IE_MAX,
+	},
+	[IWEVMICHAELMICFAILURE	- IWEVFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT, 
+		.token_size	= 1,
+		.max_tokens	= sizeof(struct iw_michaelmicfailure),
+	},
+	[IWEVASSOCREQIE	- IWEVFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= 1,
+		.max_tokens	= IW_GENERIC_IE_MAX,
+	},
+	[IWEVASSOCRESPIE	- IWEVFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= 1,
+		.max_tokens	= IW_GENERIC_IE_MAX,
+	},
+	[IWEVPMKIDCAND	- IWEVFIRST] = {
+		.header_type	= IW_HEADER_TYPE_POINT,
+		.token_size	= 1,
+		.max_tokens	= sizeof(struct iw_pmkid_cand),
+	},
 };
 static const int standard_event_num = (sizeof(standard_event) /
 				       sizeof(struct iw_ioctl_description));
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index ee7bf46..00233ec 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -716,13 +716,13 @@
 }
 
 static int dn_dev_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa,
-				u32 pid, u32 seq, int event)
+				u32 pid, u32 seq, int event, unsigned int flags)
 {
 	struct ifaddrmsg *ifm;
 	struct nlmsghdr *nlh;
 	unsigned char *b = skb->tail;
 
-	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm));
+	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
 	ifm = NLMSG_DATA(nlh);
 
 	ifm->ifa_family = AF_DECnet;
@@ -755,7 +755,7 @@
 		netlink_set_err(rtnl, 0, RTMGRP_DECnet_IFADDR, ENOBUFS);
 		return;
 	}
-	if (dn_dev_fill_ifaddr(skb, ifa, 0, 0, event) < 0) {
+	if (dn_dev_fill_ifaddr(skb, ifa, 0, 0, event, 0) < 0) {
 		kfree_skb(skb);
 		netlink_set_err(rtnl, 0, RTMGRP_DECnet_IFADDR, EINVAL);
 		return;
@@ -790,7 +790,8 @@
 			if (dn_dev_fill_ifaddr(skb, ifa,
 					       NETLINK_CB(cb->skb).pid,
 					       cb->nlh->nlmsg_seq,
-					       RTM_NEWADDR) <= 0)
+					       RTM_NEWADDR,
+					       NLM_F_MULTI) <= 0)
 				goto done;
 		}
 	}
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
index f6dfe96..f32dba9 100644
--- a/net/decnet/dn_neigh.c
+++ b/net/decnet/dn_neigh.c
@@ -101,7 +101,6 @@
 	.id =				"dn_neigh_cache",
 	.parms ={
 		.tbl =			&dn_neigh_table,
-		.entries =		0,
 		.base_reachable_time =	30 * HZ,
 		.retrans_time =	1 * HZ,
 		.gc_staletime =	60 * HZ,
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index 1e7b5c3..2399fa8 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -1465,7 +1465,8 @@
 	return dn_route_input_slow(skb);
 }
 
-static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, int nowait)
+static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
+			   int event, int nowait, unsigned int flags)
 {
 	struct dn_route *rt = (struct dn_route *)skb->dst;
 	struct rtmsg *r;
@@ -1473,9 +1474,8 @@
 	unsigned char *b = skb->tail;
 	struct rta_cacheinfo ci;
 
-	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*r));
+	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags);
 	r = NLMSG_DATA(nlh);
-	nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0;
 	r->rtm_family = AF_DECnet;
 	r->rtm_dst_len = 16;
 	r->rtm_src_len = 0;
@@ -1596,7 +1596,7 @@
 
 	NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
 
-	err = dn_rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, RTM_NEWROUTE, 0);
+	err = dn_rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, RTM_NEWROUTE, 0, 0);
 
 	if (err == 0)
 		goto out_free;
@@ -1644,7 +1644,8 @@
 				continue;
 			skb->dst = dst_clone(&rt->u.dst);
 			if (dn_rt_fill_info(skb, NETLINK_CB(cb->skb).pid,
-					cb->nlh->nlmsg_seq, RTM_NEWROUTE, 1) <= 0) {
+					cb->nlh->nlmsg_seq, RTM_NEWROUTE, 
+					1, NLM_F_MULTI) <= 0) {
 				dst_release(xchg(&skb->dst, NULL));
 				rcu_read_unlock_bh();
 				goto done;
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index 597587d..1060de7 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -342,14 +342,15 @@
 	.notifier_call =	dn_fib_rules_event,
 };
 
-static int dn_fib_fill_rule(struct sk_buff *skb, struct dn_fib_rule *r, struct netlink_callback *cb)
+static int dn_fib_fill_rule(struct sk_buff *skb, struct dn_fib_rule *r,
+			    struct netlink_callback *cb, unsigned int flags)
 {
 	struct rtmsg *rtm;
 	struct nlmsghdr *nlh;
 	unsigned char *b = skb->tail;
 
 
-	nlh = NLMSG_PUT(skb, NETLINK_CREDS(cb->skb)->pid, cb->nlh->nlmsg_seq, RTM_NEWRULE, sizeof(*rtm));
+	nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWRULE, sizeof(*rtm), flags);
 	rtm = NLMSG_DATA(nlh);
 	rtm->rtm_family = AF_DECnet;
 	rtm->rtm_dst_len = r->r_dst_len;
@@ -394,7 +395,7 @@
 	for(r = dn_fib_rules, idx = 0; r; r = r->r_next, idx++) {
 		if (idx < s_idx)
 			continue;
-		if (dn_fib_fill_rule(skb, r, cb) < 0)
+		if (dn_fib_fill_rule(skb, r, cb, NLM_F_MULTI) < 0)
 			break;
 	}
 	read_unlock(&dn_fib_rules_lock);
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
index dad5603..28ba5777a 100644
--- a/net/decnet/dn_table.c
+++ b/net/decnet/dn_table.c
@@ -270,13 +270,13 @@
 
 static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
                         u8 tb_id, u8 type, u8 scope, void *dst, int dst_len,
-                        struct dn_fib_info *fi)
+                        struct dn_fib_info *fi, unsigned int flags)
 {
         struct rtmsg *rtm;
         struct nlmsghdr *nlh;
         unsigned char *b = skb->tail;
 
-        nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*rtm));
+        nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*rtm), flags);
         rtm = NLMSG_DATA(nlh);
         rtm->rtm_family = AF_DECnet;
         rtm->rtm_dst_len = dst_len;
@@ -345,7 +345,7 @@
 
         if (dn_fib_dump_info(skb, pid, nlh->nlmsg_seq, event, tb_id, 
                                 f->fn_type, f->fn_scope, &f->fn_key, z, 
-                                DN_FIB_INFO(f)) < 0) {
+                                DN_FIB_INFO(f), 0) < 0) {
                 kfree_skb(skb);
                 return;
         }
@@ -377,7 +377,7 @@
 				tb->n, 
 				(f->fn_state & DN_S_ZOMBIE) ? 0 : f->fn_type,
 				f->fn_scope, &f->fn_key, dz->dz_order, 
-				f->fn_info) < 0) {
+				f->fn_info, NLM_F_MULTI) < 0) {
 			cb->args[3] = i;
 			return -1;
 		}
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 6d3e8b1..3e63123 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -53,6 +53,44 @@
 
 	  If unsure, say N here.
 
+choice 
+	prompt "Choose IP: FIB lookup algorithm (choose FIB_HASH if unsure)"
+	depends on IP_ADVANCED_ROUTER
+	default IP_FIB_HASH
+
+config IP_FIB_HASH
+	bool "FIB_HASH"
+	---help---
+	Current FIB is very proven and good enough for most users.
+
+config IP_FIB_TRIE
+	bool "FIB_TRIE"
+	---help---
+	Use new experimental LC-trie as FIB lookup algoritm. 
+        This improves lookup performance if you have a large
+	number of routes.
+
+	LC-trie is a longest matching prefix lookup algorithm which
+	performs better than FIB_HASH for large routing tables.
+	But, it consumes more memory and is more complex.
+	
+	LC-trie is described in:
+	
+ 	IP-address lookup using LC-tries. Stefan Nilsson and Gunnar Karlsson
+ 	IEEE Journal on Selected Areas in Communications, 17(6):1083-1092, June 1999
+	An experimental study of compression methods for dynamic tries
+ 	Stefan Nilsson and Matti Tikkanen. Algorithmica, 33(1):19-33, 2002.
+ 	http://www.nada.kth.se/~snilsson/public/papers/dyntrie2/
+       
+endchoice
+
+# If the user does not enable advanced routing, he gets the safe
+# default of the fib-hash algorithm.
+config IP_FIB_HASH
+	bool
+	depends on !IP_ADVANCED_ROUTER
+	default y
+
 config IP_MULTIPLE_TABLES
 	bool "IP: policy routing"
 	depends on IP_ADVANCED_ROUTER
@@ -407,5 +445,112 @@
 config IP_TCPDIAG_IPV6
 	def_bool (IP_TCPDIAG=y && IPV6=y) || (IP_TCPDIAG=m && IPV6)
 
+config TCP_CONG_ADVANCED
+	bool "TCP: advanced congestion control"
+	depends on INET
+	---help---
+	  Support for selection of various TCP congestion control
+	  modules.
+
+	  Nearly all users can safely say no here, and a safe default
+	  selection will be made (BIC-TCP with new Reno as a fallback).
+
+	  If unsure, say N.
+
+# TCP Reno is builtin (required as fallback)
+menu "TCP congestion control"
+	depends on TCP_CONG_ADVANCED
+
+config TCP_CONG_BIC
+	tristate "Binary Increase Congestion (BIC) control"
+	depends on INET
+	default y
+	---help---
+	BIC-TCP is a sender-side only change that ensures a linear RTT
+	fairness under large windows while offering both scalability and
+	bounded TCP-friendliness. The protocol combines two schemes
+	called additive increase and binary search increase. When the
+	congestion window is large, additive increase with a large
+	increment ensures linear RTT fairness as well as good
+	scalability. Under small congestion windows, binary search
+	increase provides TCP friendliness.
+	See http://www.csc.ncsu.edu/faculty/rhee/export/bitcp/
+
+config TCP_CONG_WESTWOOD
+	tristate "TCP Westwood+"
+	depends on INET
+	default m
+	---help---
+	TCP Westwood+ is a sender-side only modification of the TCP Reno
+	protocol stack that optimizes the performance of TCP congestion
+	control. It is based on end-to-end bandwidth estimation to set
+	congestion window and slow start threshold after a congestion
+	episode. Using this estimation, TCP Westwood+ adaptively sets a
+	slow start threshold and a congestion window which takes into
+	account the bandwidth used  at the time congestion is experienced.
+	TCP Westwood+ significantly increases fairness wrt TCP Reno in
+	wired networks and throughput over wireless links.
+
+config TCP_CONG_HTCP
+        tristate "H-TCP"
+	depends on INET
+        default m
+	---help---
+	H-TCP is a send-side only modifications of the TCP Reno
+	protocol stack that optimizes the performance of TCP
+	congestion control for high speed network links. It uses a
+	modeswitch to change the alpha and beta parameters of TCP Reno
+	based on network conditions and in a way so as to be fair with
+	other Reno and H-TCP flows.
+
+config TCP_CONG_HSTCP
+	tristate "High Speed TCP"
+	depends on INET && EXPERIMENTAL
+	default n
+	---help---
+	Sally Floyd's High Speed TCP (RFC 3649) congestion control.
+	A modification to TCP's congestion control mechanism for use
+	with large congestion windows. A table indicates how much to
+	increase the congestion window by when an ACK is received.
+ 	For more detail	see http://www.icir.org/floyd/hstcp.html
+
+config TCP_CONG_HYBLA
+	tristate "TCP-Hybla congestion control algorithm"
+	depends on INET && EXPERIMENTAL
+	default n
+	---help---
+	TCP-Hybla is a sender-side only change that eliminates penalization of
+	long-RTT, large-bandwidth connections, like when satellite legs are
+	involved, expecially when sharing a common bottleneck with normal
+	terrestrial connections.
+
+config TCP_CONG_VEGAS
+	tristate "TCP Vegas"
+	depends on INET && EXPERIMENTAL
+	default n
+	---help---
+	TCP Vegas is a sender-side only change to TCP that anticipates
+	the onset of congestion by estimating the bandwidth. TCP Vegas
+	adjusts the sending rate by modifying the congestion
+	window. TCP Vegas should provide less packet loss, but it is
+	not as aggressive as TCP Reno.
+
+config TCP_CONG_SCALABLE
+	tristate "Scalable TCP"
+	depends on INET && EXPERIMENTAL
+	default n
+	---help---
+	Scalable TCP is a sender-side only change to TCP which uses a
+	MIMD congestion control algorithm which has some nice scaling
+	properties, though is known to have fairness issues.
+	See http://www-lce.eng.cam.ac.uk/~ctk21/scalable/
+
+endmenu
+
+config TCP_CONG_BIC
+	tristate
+	depends on !TCP_CONG_ADVANCED
+	default y
+
 source "net/ipv4/ipvs/Kconfig"
 
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 8b37962..5718cdb 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -5,10 +5,13 @@
 obj-y     := utils.o route.o inetpeer.o protocol.o \
 	     ip_input.o ip_fragment.o ip_forward.o ip_options.o \
 	     ip_output.o ip_sockglue.o \
-	     tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o tcp_minisocks.o \
+	     tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o \
+	     tcp_minisocks.o tcp_cong.o \
 	     datagram.o raw.o udp.o arp.o icmp.o devinet.o af_inet.o igmp.o \
-	     sysctl_net_ipv4.o fib_frontend.o fib_semantics.o fib_hash.o
+	     sysctl_net_ipv4.o fib_frontend.o fib_semantics.o
 
+obj-$(CONFIG_IP_FIB_HASH) += fib_hash.o
+obj-$(CONFIG_IP_FIB_TRIE) += fib_trie.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o
 obj-$(CONFIG_IP_MROUTE) += ipmr.o
@@ -28,6 +31,13 @@
 obj-$(CONFIG_IP_VS) += ipvs/
 obj-$(CONFIG_IP_TCPDIAG) += tcp_diag.o 
 obj-$(CONFIG_IP_ROUTE_MULTIPATH_CACHED) += multipath.o
+obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o
+obj-$(CONFIG_TCP_CONG_WESTWOOD) += tcp_westwood.o
+obj-$(CONFIG_TCP_CONG_HSTCP) += tcp_highspeed.o
+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_SCALABLE) += tcp_scalable.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 b3cb49c..658e797 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1119,6 +1119,10 @@
 #ifdef CONFIG_PROC_FS
 extern int  fib_proc_init(void);
 extern void fib_proc_exit(void);
+#ifdef CONFIG_IP_FIB_TRIE
+extern int  fib_stat_proc_init(void);
+extern void fib_stat_proc_exit(void);
+#endif
 extern int  ip_misc_proc_init(void);
 extern int  raw_proc_init(void);
 extern void raw_proc_exit(void);
@@ -1139,11 +1143,19 @@
 		goto out_udp;
 	if (fib_proc_init())
 		goto out_fib;
+#ifdef CONFIG_IP_FIB_TRIE
+         if (fib_stat_proc_init())
+                 goto out_fib_stat;
+ #endif
 	if (ip_misc_proc_init())
 		goto out_misc;
 out:
 	return rc;
 out_misc:
+#ifdef CONFIG_IP_FIB_TRIE
+ 	fib_stat_proc_exit();
+out_fib_stat:
+#endif
 	fib_proc_exit();
 out_fib:
 	udp4_proc_exit();
@@ -1181,6 +1193,7 @@
 EXPORT_SYMBOL(inet_stream_ops);
 EXPORT_SYMBOL(inet_unregister_protosw);
 EXPORT_SYMBOL(net_statistics);
+EXPORT_SYMBOL(sysctl_ip_nonlocal_bind);
 
 #ifdef INET_REFCNT_DEBUG
 EXPORT_SYMBOL(inet_sock_nr);
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index 0e98f22..514c85b 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -200,7 +200,7 @@
 	xfrm_state_put(x);
 }
 
-static int ah_init_state(struct xfrm_state *x, void *args)
+static int ah_init_state(struct xfrm_state *x)
 {
 	struct ah_data *ahp = NULL;
 	struct xfrm_algo_desc *aalg_desc;
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 478a301..d8a10e3 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1030,14 +1030,13 @@
 };
 
 static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
-			    u32 pid, u32 seq, int event)
+			    u32 pid, u32 seq, int event, unsigned int flags)
 {
 	struct ifaddrmsg *ifm;
 	struct nlmsghdr  *nlh;
 	unsigned char	 *b = skb->tail;
 
-	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm));
-	if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;
+	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
 	ifm = NLMSG_DATA(nlh);
 	ifm->ifa_family = AF_INET;
 	ifm->ifa_prefixlen = ifa->ifa_prefixlen;
@@ -1090,7 +1089,7 @@
 				continue;
 			if (inet_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).pid,
 					     cb->nlh->nlmsg_seq,
-					     RTM_NEWADDR) <= 0) {
+					     RTM_NEWADDR, NLM_F_MULTI) <= 0) {
 				rcu_read_unlock();
 				goto done;
 			}
@@ -1113,7 +1112,7 @@
 
 	if (!skb)
 		netlink_set_err(rtnl, 0, RTMGRP_IPV4_IFADDR, ENOBUFS);
-	else if (inet_fill_ifaddr(skb, ifa, 0, 0, event) < 0) {
+	else if (inet_fill_ifaddr(skb, ifa, current->pid, 0, event, 0) < 0) {
 		kfree_skb(skb);
 		netlink_set_err(rtnl, 0, RTMGRP_IPV4_IFADDR, EINVAL);
 	} else {
@@ -1472,7 +1471,7 @@
 	 * by sysctl and we wouldn't want anyone to change it under our feet
 	 * (see SIOCSIFNAME).
 	 */	
-	dev_name = net_sysctl_strdup(dev_name);
+	dev_name = kstrdup(dev_name, GFP_KERNEL);
 	if (!dev_name)
 	    goto free;
 
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index eae84cc..ba57446 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -362,7 +362,7 @@
 	kfree(esp);
 }
 
-static int esp_init_state(struct xfrm_state *x, void *args)
+static int esp_init_state(struct xfrm_state *x)
 {
 	struct esp_data *esp = NULL;
 
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 563e7d6..cd8e45a 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -516,6 +516,60 @@
 #undef BRD1_OK
 }
 
+static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb )
+{
+	
+	struct fib_result       res;
+	struct flowi            fl = { .nl_u = { .ip4_u = { .daddr = frn->fl_addr, 
+							    .fwmark = frn->fl_fwmark,
+							    .tos = frn->fl_tos,
+							    .scope = frn->fl_scope } } };
+	if (tb) {
+		local_bh_disable();
+
+		frn->tb_id = tb->tb_id;
+		frn->err = tb->tb_lookup(tb, &fl, &res);
+
+		if (!frn->err) {
+			frn->prefixlen = res.prefixlen;
+			frn->nh_sel = res.nh_sel;
+			frn->type = res.type;
+			frn->scope = res.scope;
+		}
+		local_bh_enable();
+	}
+}
+
+static void nl_fib_input(struct sock *sk, int len)
+{
+	struct sk_buff *skb = NULL;
+        struct nlmsghdr *nlh = NULL;
+	struct fib_result_nl *frn;
+	int err;
+	u32 pid;     
+	struct fib_table *tb;
+	
+	skb = skb_recv_datagram(sk, 0, 0, &err);
+	nlh = (struct nlmsghdr *)skb->data;
+	
+	frn = (struct fib_result_nl *) NLMSG_DATA(nlh);
+	tb = fib_get_table(frn->tb_id_in);
+
+	nl_fib_lookup(frn, tb);
+	
+	pid = nlh->nlmsg_pid;           /*pid of sending process */
+	NETLINK_CB(skb).groups = 0;     /* not in mcast group */
+	NETLINK_CB(skb).pid = 0;         /* from kernel */
+	NETLINK_CB(skb).dst_pid = pid;
+	NETLINK_CB(skb).dst_groups = 0;  /* unicast */
+	netlink_unicast(sk, skb, pid, MSG_DONTWAIT);
+}    
+
+static void nl_fib_lookup_init(void)
+{
+      netlink_kernel_create(NETLINK_FIB_LOOKUP, nl_fib_input);
+}
+
 static void fib_disable_ip(struct net_device *dev, int force)
 {
 	if (fib_sync_down(0, dev, force))
@@ -604,6 +658,7 @@
 
 	register_netdevice_notifier(&fib_netdev_notifier);
 	register_inetaddr_notifier(&fib_inetaddr_notifier);
+	nl_fib_lookup_init();
 }
 
 EXPORT_SYMBOL(inet_addr_type);
diff --git a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
index 6506dcc..b10d6bb 100644
--- a/net/ipv4/fib_hash.c
+++ b/net/ipv4/fib_hash.c
@@ -703,7 +703,8 @@
 					  &f->fn_key,
 					  fz->fz_order,
 					  fa->fa_tos,
-					  fa->fa_info) < 0) {
+					  fa->fa_info,
+					  NLM_F_MULTI) < 0) {
 				cb->args[3] = i;
 				return -1;
 			}
diff --git a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h
index ac4485f..b729d97 100644
--- a/net/ipv4/fib_lookup.h
+++ b/net/ipv4/fib_lookup.h
@@ -30,7 +30,8 @@
 			struct kern_rta *rta, struct fib_info *fi);
 extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
 			 u8 tb_id, u8 type, u8 scope, void *dst,
-			 int dst_len, u8 tos, struct fib_info *fi);
+			 int dst_len, u8 tos, struct fib_info *fi,
+			 unsigned int);
 extern void rtmsg_fib(int event, u32 key, struct fib_alias *fa,
 		      int z, int tb_id,
 		      struct nlmsghdr *n, struct netlink_skb_parms *req);
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 39d0aad..0b298bb 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -367,13 +367,14 @@
 
 static __inline__ int inet_fill_rule(struct sk_buff *skb,
 				     struct fib_rule *r,
-				     struct netlink_callback *cb)
+				     struct netlink_callback *cb,
+				     unsigned int flags)
 {
 	struct rtmsg *rtm;
 	struct nlmsghdr  *nlh;
 	unsigned char	 *b = skb->tail;
 
-	nlh = NLMSG_PUT(skb, NETLINK_CREDS(cb->skb)->pid, cb->nlh->nlmsg_seq, RTM_NEWRULE, sizeof(*rtm));
+	nlh = NLMSG_NEW_ANSWER(skb, cb, RTM_NEWRULE, sizeof(*rtm), flags);
 	rtm = NLMSG_DATA(nlh);
 	rtm->rtm_family = AF_INET;
 	rtm->rtm_dst_len = r->r_dst_len;
@@ -422,7 +423,7 @@
 	for (r=fib_rules, idx=0; r; r = r->r_next, idx++) {
 		if (idx < s_idx)
 			continue;
-		if (inet_fill_rule(skb, r, cb) < 0)
+		if (inet_fill_rule(skb, r, cb, NLM_F_MULTI) < 0)
 			break;
 	}
 	read_unlock(&fib_rules_lock);
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 029362d..c886b28 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -276,7 +276,7 @@
 	       struct nlmsghdr *n, struct netlink_skb_parms *req)
 {
 	struct sk_buff *skb;
-	u32 pid = req ? req->pid : 0;
+	u32 pid = req ? req->pid : n->nlmsg_pid;
 	int size = NLMSG_SPACE(sizeof(struct rtmsg)+256);
 
 	skb = alloc_skb(size, GFP_KERNEL);
@@ -286,7 +286,7 @@
 	if (fib_dump_info(skb, pid, n->nlmsg_seq, event, tb_id,
 			  fa->fa_type, fa->fa_scope, &key, z,
 			  fa->fa_tos,
-			  fa->fa_info) < 0) {
+			  fa->fa_info, 0) < 0) {
 		kfree_skb(skb);
 		return;
 	}
@@ -932,13 +932,13 @@
 int
 fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
 	      u8 tb_id, u8 type, u8 scope, void *dst, int dst_len, u8 tos,
-	      struct fib_info *fi)
+	      struct fib_info *fi, unsigned int flags)
 {
 	struct rtmsg *rtm;
 	struct nlmsghdr  *nlh;
 	unsigned char	 *b = skb->tail;
 
-	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*rtm));
+	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*rtm), flags);
 	rtm = NLMSG_DATA(nlh);
 	rtm->rtm_family = AF_INET;
 	rtm->rtm_dst_len = dst_len;
@@ -1035,7 +1035,7 @@
 	}
 
 	nl->nlmsg_flags = NLM_F_REQUEST;
-	nl->nlmsg_pid = 0;
+	nl->nlmsg_pid = current->pid;
 	nl->nlmsg_seq = 0;
 	nl->nlmsg_len = NLMSG_LENGTH(sizeof(*rtm));
 	if (cmd == SIOCDELRT) {
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
new file mode 100644
index 0000000..0671569
--- /dev/null
+++ b/net/ipv4/fib_trie.c
@@ -0,0 +1,2454 @@
+/*
+ *   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.
+ *
+ *   Robert Olsson <robert.olsson@its.uu.se> Uppsala Universitet
+ *     & Swedish University of Agricultural Sciences.
+ *
+ *   Jens Laas <jens.laas@data.slu.se> Swedish University of 
+ *     Agricultural Sciences.
+ * 
+ *   Hans Liss <hans.liss@its.uu.se>  Uppsala Universitet
+ *
+ * This work is based on the LPC-trie which is originally descibed in:
+ * 
+ * An experimental study of compression methods for dynamic tries
+ * Stefan Nilsson and Matti Tikkanen. Algorithmica, 33(1):19-33, 2002.
+ * http://www.nada.kth.se/~snilsson/public/papers/dyntrie2/
+ *
+ *
+ * IP-address lookup using LC-tries. Stefan Nilsson and Gunnar Karlsson
+ * IEEE Journal on Selected Areas in Communications, 17(6):1083-1092, June 1999
+ *
+ * Version:	$Id: fib_trie.c,v 1.3 2005/06/08 14:20:01 robert Exp $
+ *
+ *
+ * Code from fib_hash has been reused which includes the following header:
+ *
+ *
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the  BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		IPv4 FIB: lookup engine and maintenance routines.
+ *
+ *
+ * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.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.
+ */
+
+#define VERSION "0.323"
+
+#include <linux/config.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/route.h>
+#include <net/tcp.h>
+#include <net/sock.h>
+#include <net/ip_fib.h>
+#include "fib_lookup.h"
+
+#undef CONFIG_IP_FIB_TRIE_STATS
+#define MAX_CHILDS 16384
+
+#define EXTRACT(p, n, str) ((str)<<(p)>>(32-(n)))
+#define KEYLENGTH (8*sizeof(t_key))
+#define MASK_PFX(k, l) (((l)==0)?0:(k >> (KEYLENGTH-l)) << (KEYLENGTH-l))
+#define TKEY_GET_MASK(offset, bits) (((bits)==0)?0:((t_key)(-1) << (KEYLENGTH - bits) >> offset))
+
+static DEFINE_RWLOCK(fib_lock);
+
+typedef unsigned int t_key;
+
+#define T_TNODE 0
+#define T_LEAF  1
+#define NODE_TYPE_MASK	0x1UL
+#define NODE_PARENT(_node) \
+((struct tnode *)((_node)->_parent & ~NODE_TYPE_MASK))
+#define NODE_SET_PARENT(_node, _ptr) \
+((_node)->_parent = (((unsigned long)(_ptr)) | \
+                     ((_node)->_parent & NODE_TYPE_MASK)))
+#define NODE_INIT_PARENT(_node, _type) \
+((_node)->_parent = (_type))
+#define NODE_TYPE(_node) \
+((_node)->_parent & NODE_TYPE_MASK)
+
+#define IS_TNODE(n) (!(n->_parent & T_LEAF))
+#define IS_LEAF(n) (n->_parent & T_LEAF)
+
+struct node {
+        t_key key;
+	unsigned long _parent;
+};
+
+struct leaf {
+        t_key key;
+	unsigned long _parent;
+	struct hlist_head list;
+};
+
+struct leaf_info {
+	struct hlist_node hlist;
+	int plen;
+	struct list_head falh;
+};
+
+struct tnode {
+        t_key key;
+	unsigned long _parent;
+        unsigned short pos:5;        /* 2log(KEYLENGTH) bits needed */
+        unsigned short bits:5;       /* 2log(KEYLENGTH) bits needed */
+        unsigned short full_children;  /* KEYLENGTH bits needed */
+        unsigned short empty_children; /* KEYLENGTH bits needed */
+        struct node *child[0];
+};
+
+#ifdef CONFIG_IP_FIB_TRIE_STATS
+struct trie_use_stats {
+	unsigned int gets;
+	unsigned int backtrack;
+	unsigned int semantic_match_passed;
+	unsigned int semantic_match_miss;
+	unsigned int null_node_hit;
+};
+#endif
+
+struct trie_stat {
+	unsigned int totdepth;
+	unsigned int maxdepth;
+	unsigned int tnodes;
+	unsigned int leaves;
+	unsigned int nullpointers;
+	unsigned int nodesizes[MAX_CHILDS];
+};    
+
+struct trie {
+        struct node *trie;
+#ifdef CONFIG_IP_FIB_TRIE_STATS
+	struct trie_use_stats stats;
+#endif
+        int size;
+	unsigned int revision;
+};
+
+static int trie_debug = 0;
+
+static int tnode_full(struct tnode *tn, struct node *n);
+static void put_child(struct trie *t, struct tnode *tn, int i, struct node *n);
+static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n, int wasfull);
+static int tnode_child_length(struct tnode *tn);
+static struct node *resize(struct trie *t, struct tnode *tn);
+static struct tnode *inflate(struct trie *t, struct tnode *tn);
+static struct tnode *halve(struct trie *t, struct tnode *tn);
+static void tnode_free(struct tnode *tn);
+static void trie_dump_seq(struct seq_file *seq, struct trie *t);
+extern struct fib_alias *fib_find_alias(struct list_head *fah, u8 tos, u32 prio);
+extern int fib_detect_death(struct fib_info *fi, int order,
+                            struct fib_info **last_resort, int *last_idx, int *dflt);
+
+extern void rtmsg_fib(int event, u32 key, struct fib_alias *fa, int z, int tb_id,
+               struct nlmsghdr *n, struct netlink_skb_parms *req);
+
+static kmem_cache_t *fn_alias_kmem;
+static struct trie *trie_local = NULL, *trie_main = NULL;
+
+static void trie_bug(char *err)
+{
+	printk("Trie Bug: %s\n", err);
+	BUG();
+}
+
+static inline struct node *tnode_get_child(struct tnode *tn, int i) 
+{
+        if (i >=  1<<tn->bits) 
+                trie_bug("tnode_get_child");
+
+        return tn->child[i];
+}
+
+static inline int tnode_child_length(struct tnode *tn)
+{
+        return 1<<tn->bits;
+}
+
+/*
+  _________________________________________________________________
+  | i | i | i | i | i | i | i | N | N | N | S | S | S | S | S | C |
+  ----------------------------------------------------------------
+    0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15 
+
+  _________________________________________________________________
+  | C | C | C | u | u | u | u | u | u | u | u | u | u | u | u | u |
+  -----------------------------------------------------------------
+   16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31
+
+  tp->pos = 7
+  tp->bits = 3
+  n->pos = 15
+  n->bits=4
+  KEYLENGTH=32
+*/
+
+static inline t_key tkey_extract_bits(t_key a, int offset, int bits)
+{
+        if (offset < KEYLENGTH)
+		return ((t_key)(a << offset)) >> (KEYLENGTH - bits);
+        else
+		return 0;
+}
+
+static inline int tkey_equals(t_key a, t_key b)
+{
+  return a == b;
+}
+
+static inline int tkey_sub_equals(t_key a, int offset, int bits, t_key b)
+{
+     if (bits == 0 || offset >= KEYLENGTH)
+            return 1;
+        bits = bits > KEYLENGTH ? KEYLENGTH : bits;
+        return ((a ^ b) << offset) >> (KEYLENGTH - bits) == 0;
+}	
+
+static inline int tkey_mismatch(t_key a, int offset, t_key b)
+{
+	t_key diff = a ^ b;
+	int i = offset;
+
+	if(!diff) 
+	  return 0;
+	while((diff << i) >> (KEYLENGTH-1) == 0)
+		i++;
+	return i;
+}
+
+/* Candiate for fib_semantics */
+
+static void fn_free_alias(struct fib_alias *fa)
+{
+	fib_release_info(fa->fa_info);
+	kmem_cache_free(fn_alias_kmem, fa);
+}
+
+/*
+  To understand this stuff, an understanding of keys and all their bits is 
+  necessary. Every node in the trie has a key associated with it, but not 
+  all of the bits in that key are significant.
+
+  Consider a node 'n' and its parent 'tp'.
+
+  If n is a leaf, every bit in its key is significant. Its presence is 
+  necessitaded by path compression, since during a tree traversal (when 
+  searching for a leaf - unless we are doing an insertion) we will completely 
+  ignore all skipped bits we encounter. Thus we need to verify, at the end of 
+  a potentially successful search, that we have indeed been walking the 
+  correct key path.
+
+  Note that we can never "miss" the correct key in the tree if present by 
+  following the wrong path. Path compression ensures that segments of the key 
+  that are the same for all keys with a given prefix are skipped, but the 
+  skipped part *is* identical for each node in the subtrie below the skipped 
+  bit! trie_insert() in this implementation takes care of that - note the 
+  call to tkey_sub_equals() in trie_insert().
+
+  if n is an internal node - a 'tnode' here, the various parts of its key 
+  have many different meanings.
+
+  Example:  
+  _________________________________________________________________
+  | i | i | i | i | i | i | i | N | N | N | S | S | S | S | S | C |
+  -----------------------------------------------------------------
+    0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15 
+
+  _________________________________________________________________
+  | C | C | C | u | u | u | u | u | u | u | u | u | u | u | u | u |
+  -----------------------------------------------------------------
+   16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31
+
+  tp->pos = 7
+  tp->bits = 3
+  n->pos = 15
+  n->bits=4
+
+  First, let's just ignore the bits that come before the parent tp, that is 
+  the bits from 0 to (tp->pos-1). They are *known* but at this point we do 
+  not use them for anything.
+
+  The bits from (tp->pos) to (tp->pos + tp->bits - 1) - "N", above - are the
+  index into the parent's child array. That is, they will be used to find 
+  'n' among tp's children.
+
+  The bits from (tp->pos + tp->bits) to (n->pos - 1) - "S" - are skipped bits
+  for the node n.
+
+  All the bits we have seen so far are significant to the node n. The rest 
+  of the bits are really not needed or indeed known in n->key.
+
+  The bits from (n->pos) to (n->pos + n->bits - 1) - "C" - are the index into 
+  n's child array, and will of course be different for each child.
+  
+  The rest of the bits, from (n->pos + n->bits) onward, are completely unknown
+  at this point.
+
+*/
+
+static void check_tnode(struct tnode *tn)
+{
+	if(tn && tn->pos+tn->bits > 32) {
+		printk("TNODE ERROR tn=%p, pos=%d, bits=%d\n", tn, tn->pos, tn->bits);
+	}
+}
+
+static int halve_threshold = 25;
+static int inflate_threshold = 50;
+
+static struct leaf *leaf_new(void)
+{
+	struct leaf *l = kmalloc(sizeof(struct leaf),  GFP_KERNEL);
+	if(l) {
+		NODE_INIT_PARENT(l, T_LEAF);
+		INIT_HLIST_HEAD(&l->list);
+	}
+	return l;
+}
+
+static struct leaf_info *leaf_info_new(int plen)
+{
+	struct leaf_info *li = kmalloc(sizeof(struct leaf_info),  GFP_KERNEL);
+	li->plen = plen;
+	INIT_LIST_HEAD(&li->falh);
+	return li;
+}
+
+static inline void free_leaf(struct leaf *l)
+{
+	kfree(l);
+}
+
+static inline void free_leaf_info(struct leaf_info *li)
+{
+	kfree(li);
+}
+
+static struct tnode* tnode_new(t_key key, int pos, int bits)
+{
+	int nchildren = 1<<bits;
+	int sz = sizeof(struct tnode) + nchildren * sizeof(struct node *);
+	struct tnode *tn = kmalloc(sz,  GFP_KERNEL);
+
+	if(tn)  {
+		memset(tn, 0, sz);
+		NODE_INIT_PARENT(tn, T_TNODE);
+		tn->pos = pos;
+		tn->bits = bits;
+		tn->key = key;
+		tn->full_children = 0;
+		tn->empty_children = 1<<bits;
+	}
+	if(trie_debug > 0) 
+		printk("AT %p s=%u %u\n", tn, (unsigned int) sizeof(struct tnode),
+		       (unsigned int) (sizeof(struct node) * 1<<bits));
+	return tn;
+}
+
+static void tnode_free(struct tnode *tn)
+{
+	if(!tn) {
+		trie_bug("tnode_free\n");
+	}
+	if(IS_LEAF(tn)) {
+		free_leaf((struct leaf *)tn);
+		if(trie_debug > 0 ) 
+			printk("FL %p \n", tn);
+	}
+	else if(IS_TNODE(tn)) { 
+		kfree(tn);
+		if(trie_debug > 0 ) 
+			printk("FT %p \n", tn);
+	}
+	else {
+		trie_bug("tnode_free\n");
+	}
+}
+
+/*
+ * Check whether a tnode 'n' is "full", i.e. it is an internal node
+ * and no bits are skipped. See discussion in dyntree paper p. 6
+ */
+
+static inline int tnode_full(struct tnode *tn, struct node *n)
+{
+	if(n == NULL || IS_LEAF(n))
+		return 0;
+
+	return ((struct tnode *) n)->pos == tn->pos + tn->bits;
+}
+
+static inline void put_child(struct trie *t, struct tnode *tn, int i, struct node *n) 
+{
+	tnode_put_child_reorg(tn, i, n, -1);
+}
+
+ /* 
+  * Add a child at position i overwriting the old value.
+  * Update the value of full_children and empty_children.
+  */
+
+static void tnode_put_child_reorg(struct tnode *tn, int i, struct node *n, int wasfull) 
+{
+	struct node *chi;
+	int isfull;
+
+	if(i >=  1<<tn->bits) {
+		printk("bits=%d, i=%d\n", tn->bits, i);
+		trie_bug("tnode_put_child_reorg bits");
+	}
+	write_lock_bh(&fib_lock);
+	chi = tn->child[i];	
+
+	/* update emptyChildren */
+	if (n == NULL && chi != NULL)
+		tn->empty_children++;
+	else if (n != NULL && chi == NULL)
+		tn->empty_children--;
+  
+	/* update fullChildren */
+        if (wasfull == -1)
+		wasfull = tnode_full(tn, chi);
+
+	isfull = tnode_full(tn, n);
+	if (wasfull && !isfull) 
+		tn->full_children--;
+	
+	else if (!wasfull && isfull) 
+		tn->full_children++;
+	if(n) 
+		NODE_SET_PARENT(n, tn);	
+
+	tn->child[i] = n;
+	write_unlock_bh(&fib_lock);
+}
+
+static struct node *resize(struct trie *t, struct tnode *tn) 
+{
+	int i;
+
+ 	if (!tn)
+		return NULL;
+
+	if(trie_debug) 
+		printk("In tnode_resize %p inflate_threshold=%d threshold=%d\n", 
+		      tn, inflate_threshold, halve_threshold);
+
+	/* No children */
+	if (tn->empty_children == tnode_child_length(tn)) {
+		tnode_free(tn);
+		return NULL;
+	}
+	/* One child */
+	if (tn->empty_children == tnode_child_length(tn) - 1)
+		for (i = 0; i < tnode_child_length(tn); i++) {
+
+			write_lock_bh(&fib_lock);
+			if (tn->child[i] != NULL) {
+
+				/* compress one level */
+				struct node *n = tn->child[i];
+				if(n)
+					NODE_INIT_PARENT(n, NODE_TYPE(n));
+
+				write_unlock_bh(&fib_lock);
+				tnode_free(tn);
+				return n;
+			}
+			write_unlock_bh(&fib_lock);
+		}
+	/* 
+	 * Double as long as the resulting node has a number of
+	 * nonempty nodes that are above the threshold.
+	 */
+
+	/*
+	 * From "Implementing a dynamic compressed trie" by Stefan Nilsson of 
+	 * the Helsinki University of Technology and Matti Tikkanen of Nokia 
+	 * Telecommunications, page 6:
+	 * "A node is doubled if the ratio of non-empty children to all 
+	 * children in the *doubled* node is at least 'high'."
+	 *
+	 * 'high' in this instance is the variable 'inflate_threshold'. It 
+	 * is expressed as a percentage, so we multiply it with 
+	 * tnode_child_length() and instead of multiplying by 2 (since the 
+	 * child array will be doubled by inflate()) and multiplying 
+	 * the left-hand side by 100 (to handle the percentage thing) we 
+	 * multiply the left-hand side by 50.
+	 * 
+	 * The left-hand side may look a bit weird: tnode_child_length(tn) 
+	 * - tn->empty_children is of course the number of non-null children 
+	 * in the current node. tn->full_children is the number of "full" 
+	 * children, that is non-null tnodes with a skip value of 0.
+	 * All of those will be doubled in the resulting inflated tnode, so 
+	 * we just count them one extra time here.
+	 * 
+	 * A clearer way to write this would be:
+	 * 
+	 * to_be_doubled = tn->full_children;
+	 * not_to_be_doubled = tnode_child_length(tn) - tn->empty_children - 
+	 *     tn->full_children;
+	 *
+	 * new_child_length = tnode_child_length(tn) * 2;
+	 *
+	 * new_fill_factor = 100 * (not_to_be_doubled + 2*to_be_doubled) / 
+	 *      new_child_length;
+	 * if (new_fill_factor >= inflate_threshold)
+	 * 
+	 * ...and so on, tho it would mess up the while() loop.
+	 * 
+	 * anyway,
+	 * 100 * (not_to_be_doubled + 2*to_be_doubled) / new_child_length >=
+	 *      inflate_threshold
+	 * 
+	 * avoid a division:
+	 * 100 * (not_to_be_doubled + 2*to_be_doubled) >=
+	 *      inflate_threshold * new_child_length
+	 * 
+	 * expand not_to_be_doubled and to_be_doubled, and shorten:
+	 * 100 * (tnode_child_length(tn) - tn->empty_children + 
+	 *    tn->full_children ) >= inflate_threshold * new_child_length
+	 * 
+	 * expand new_child_length:
+	 * 100 * (tnode_child_length(tn) - tn->empty_children + 
+	 *    tn->full_children ) >=
+	 *      inflate_threshold * tnode_child_length(tn) * 2
+	 * 
+	 * shorten again:
+	 * 50 * (tn->full_children + tnode_child_length(tn) - 
+	 *    tn->empty_children ) >= inflate_threshold * 
+	 *    tnode_child_length(tn)
+	 * 
+	 */
+
+	check_tnode(tn);
+
+	while ((tn->full_children > 0 &&
+	       50 * (tn->full_children + tnode_child_length(tn) - tn->empty_children) >=
+				inflate_threshold * tnode_child_length(tn))) {
+
+		tn = inflate(t, tn);
+	}
+
+	check_tnode(tn);
+
+	/*
+	 * Halve as long as the number of empty children in this
+	 * node is above threshold.
+	 */
+	while (tn->bits > 1 &&
+	       100 * (tnode_child_length(tn) - tn->empty_children) <
+	       halve_threshold * tnode_child_length(tn))
+
+		tn = halve(t, tn);
+  
+	/* Only one child remains */
+
+	if (tn->empty_children == tnode_child_length(tn) - 1)
+		for (i = 0; i < tnode_child_length(tn); i++) {
+			
+			write_lock_bh(&fib_lock);
+			if (tn->child[i] != NULL) {
+				/* compress one level */
+				struct node *n = tn->child[i];
+
+				if(n)
+					NODE_INIT_PARENT(n, NODE_TYPE(n));
+
+				write_unlock_bh(&fib_lock);
+				tnode_free(tn);
+				return n;
+			}
+			write_unlock_bh(&fib_lock);
+		}
+
+	return (struct node *) tn;
+}
+
+static struct tnode *inflate(struct trie *t, struct tnode *tn)
+{
+	struct tnode *inode;
+	struct tnode *oldtnode = tn;
+	int olen = tnode_child_length(tn);
+	int i;
+
+  	if(trie_debug) 
+		printk("In inflate\n");
+
+	tn = tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits + 1);
+
+	if (!tn)
+		trie_bug("tnode_new failed");
+
+	for(i = 0; i < olen; i++) {
+		struct node *node = tnode_get_child(oldtnode, i);
+      
+		/* An empty child */
+		if (node == NULL)
+			continue;
+
+		/* A leaf or an internal node with skipped bits */
+
+		if(IS_LEAF(node) || ((struct tnode *) node)->pos >
+		   tn->pos + tn->bits - 1) {
+			if(tkey_extract_bits(node->key, tn->pos + tn->bits - 1,
+					     1) == 0)
+				put_child(t, tn, 2*i, node);
+			else
+				put_child(t, tn, 2*i+1, node);
+			continue;
+		}
+
+		/* An internal node with two children */
+		inode = (struct tnode *) node;
+
+		if (inode->bits == 1) {
+			put_child(t, tn, 2*i, inode->child[0]);
+			put_child(t, tn, 2*i+1, inode->child[1]);
+
+			tnode_free(inode);
+		}
+
+			/* An internal node with more than two children */
+		else {
+			struct tnode *left, *right;
+			int size, j;
+
+			/* We will replace this node 'inode' with two new 
+			 * ones, 'left' and 'right', each with half of the 
+			 * original children. The two new nodes will have 
+			 * a position one bit further down the key and this 
+			 * means that the "significant" part of their keys 
+			 * (see the discussion near the top of this file) 
+			 * will differ by one bit, which will be "0" in 
+			 * left's key and "1" in right's key. Since we are 
+			 * moving the key position by one step, the bit that 
+			 * we are moving away from - the bit at position 
+			 * (inode->pos) - is the one that will differ between 
+			 * left and right. So... we synthesize that bit in the
+			 * two  new keys.
+			 * The mask 'm' below will be a single "one" bit at 
+			 * the position (inode->pos)
+			 */
+
+			t_key m = TKEY_GET_MASK(inode->pos, 1);
+ 
+			/* Use the old key, but set the new significant 
+			 *   bit to zero. 
+			 */
+			left = tnode_new(inode->key&(~m), inode->pos + 1,
+					 inode->bits - 1);
+
+			if(!left) 
+				trie_bug("tnode_new failed");
+			
+			
+			/* Use the old key, but set the new significant 
+			 * bit to one. 
+			 */
+			right = tnode_new(inode->key|m, inode->pos + 1,
+					  inode->bits - 1);
+
+			if(!right) 
+				trie_bug("tnode_new failed");
+			
+			size = tnode_child_length(left);
+			for(j = 0; j < size; j++) {
+				put_child(t, left, j, inode->child[j]);
+				put_child(t, right, j, inode->child[j + size]);
+			}
+			put_child(t, tn, 2*i, resize(t, left));
+			put_child(t, tn, 2*i+1, resize(t, right));
+
+			tnode_free(inode);
+		}
+	}
+	tnode_free(oldtnode);
+	return tn;
+}
+
+static struct tnode *halve(struct trie *t, struct tnode *tn)
+{
+	struct tnode *oldtnode = tn;
+	struct node *left, *right;
+	int i;
+	int olen = tnode_child_length(tn);
+
+	if(trie_debug) printk("In halve\n");
+  
+	tn=tnode_new(oldtnode->key, oldtnode->pos, oldtnode->bits - 1);
+
+	if(!tn) 
+		trie_bug("tnode_new failed");
+
+	for(i = 0; i < olen; i += 2) {
+		left = tnode_get_child(oldtnode, i);
+		right = tnode_get_child(oldtnode, i+1);
+    
+		/* At least one of the children is empty */
+		if (left == NULL) {
+			if (right == NULL)    /* Both are empty */
+				continue;
+			put_child(t, tn, i/2, right);
+		} else if (right == NULL)
+			put_child(t, tn, i/2, left);
+     
+		/* Two nonempty children */
+		else {
+			struct tnode *newBinNode =
+				tnode_new(left->key, tn->pos + tn->bits, 1);
+
+			if(!newBinNode) 
+				trie_bug("tnode_new failed");
+
+			put_child(t, newBinNode, 0, left);
+			put_child(t, newBinNode, 1, right);
+			put_child(t, tn, i/2, resize(t, newBinNode));
+		}
+	}
+	tnode_free(oldtnode);
+	return tn;
+}
+
+static void *trie_init(struct trie *t)
+{
+	if(t) {
+		t->size = 0;
+		t->trie = NULL;
+		t->revision = 0;
+#ifdef CONFIG_IP_FIB_TRIE_STATS
+       		memset(&t->stats, 0, sizeof(struct trie_use_stats));
+#endif
+	}
+	return t;
+}
+
+static struct leaf_info *find_leaf_info(struct hlist_head *head, int plen)
+{
+	struct hlist_node *node;
+	struct leaf_info *li;
+
+	hlist_for_each_entry(li, node, head, hlist) {
+		  
+		if ( li->plen == plen )
+			return li;
+	}
+	return NULL;
+}
+
+static inline struct list_head * get_fa_head(struct leaf *l, int plen)
+{
+	struct list_head *fa_head=NULL;
+	struct leaf_info *li = find_leaf_info(&l->list, plen);
+	
+	if(li) 
+		fa_head = &li->falh;
+	
+	return fa_head;
+}
+
+static void insert_leaf_info(struct hlist_head *head, struct leaf_info *new)
+{
+	struct leaf_info *li=NULL, *last=NULL;
+	struct hlist_node *node, *tmp;
+
+	write_lock_bh(&fib_lock);
+	
+	if(hlist_empty(head))
+		hlist_add_head(&new->hlist, head);
+	else {
+		hlist_for_each_entry_safe(li, node, tmp, head, hlist) {
+			
+			if (new->plen > li->plen) 
+				break;
+			
+			last = li;
+		}
+		if(last) 
+			hlist_add_after(&last->hlist, &new->hlist);
+		else 
+			hlist_add_before(&new->hlist, &li->hlist);
+	}
+	write_unlock_bh(&fib_lock);
+}
+
+static struct leaf *
+fib_find_node(struct trie *t, u32 key)
+{
+	int pos;
+	struct tnode *tn;
+	struct node *n;
+
+	pos = 0;
+	n=t->trie;
+
+	while (n != NULL &&  NODE_TYPE(n) == T_TNODE) {
+		tn = (struct tnode *) n;
+			
+		check_tnode(tn);
+			
+		if(tkey_sub_equals(tn->key, pos, tn->pos-pos, key)) {
+			pos=tn->pos + tn->bits;
+			n = tnode_get_child(tn, tkey_extract_bits(key, tn->pos, tn->bits));
+		}
+		else
+			break;
+	}
+	/* Case we have found a leaf. Compare prefixes */
+
+	if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key)) {
+		struct leaf *l = (struct leaf *) n;
+		return l;
+	}
+	return NULL;
+}
+
+static struct node *trie_rebalance(struct trie *t, struct tnode *tn)
+{
+	int i = 0;
+	int wasfull;
+	t_key cindex, key;
+	struct tnode *tp = NULL;
+
+	if(!tn) 
+		BUG();
+	
+	key = tn->key;
+	i = 0;
+
+	while (tn != NULL && NODE_PARENT(tn) != NULL) {
+
+		if( i > 10 ) {
+			printk("Rebalance tn=%p \n", tn);
+			if(tn) 		printk("tn->parent=%p \n", NODE_PARENT(tn));
+			
+			printk("Rebalance tp=%p \n", tp);
+			if(tp) 		printk("tp->parent=%p \n", NODE_PARENT(tp));
+		}
+
+		if( i > 12 ) BUG();
+		i++;
+
+		tp = NODE_PARENT(tn);
+		cindex = tkey_extract_bits(key, tp->pos, tp->bits);
+		wasfull = tnode_full(tp, tnode_get_child(tp, cindex));
+		tn = (struct tnode *) resize (t, (struct tnode *)tn);
+		tnode_put_child_reorg((struct tnode *)tp, cindex,(struct node*)tn, wasfull);
+		
+		if(!NODE_PARENT(tn))
+			break;
+
+		tn = NODE_PARENT(tn);
+	}
+	/* Handle last (top) tnode */
+	if (IS_TNODE(tn)) 
+		tn = (struct tnode*) resize(t, (struct tnode *)tn);
+
+	return (struct node*) tn;
+}
+
+static struct list_head *
+fib_insert_node(struct trie *t, u32 key, int plen)
+{
+	int pos, newpos;
+	struct tnode *tp = NULL, *tn = NULL;
+	struct node *n;
+	struct leaf *l;
+	int missbit;
+	struct list_head *fa_head=NULL;
+	struct leaf_info *li;
+	t_key cindex;
+
+	pos = 0;
+	n=t->trie;
+
+	/* If we point to NULL, stop. Either the tree is empty and we should 
+	 * just put a new leaf in if, or we have reached an empty child slot, 
+	 * and we should just put our new leaf in that.
+	 * If we point to a T_TNODE, check if it matches our key. Note that 
+	 * a T_TNODE might be skipping any number of bits - its 'pos' need 
+	 * not be the parent's 'pos'+'bits'!
+	 *
+	 * If it does match the current key, get pos/bits from it, extract 
+	 * the index from our key, push the T_TNODE and walk the tree.
+	 *
+	 * If it doesn't, we have to replace it with a new T_TNODE.
+	 *
+	 * If we point to a T_LEAF, it might or might not have the same key 
+	 * as we do. If it does, just change the value, update the T_LEAF's 
+	 * value, and return it. 
+	 * If it doesn't, we need to replace it with a T_TNODE.
+	 */
+
+	while (n != NULL &&  NODE_TYPE(n) == T_TNODE) {
+		tn = (struct tnode *) n;
+			
+		check_tnode(tn);
+		
+		if(tkey_sub_equals(tn->key, pos, tn->pos-pos, key)) {
+			tp = tn;
+			pos=tn->pos + tn->bits;
+			n = tnode_get_child(tn, tkey_extract_bits(key, tn->pos, tn->bits));
+
+			if(n && NODE_PARENT(n) != tn) {
+				printk("BUG tn=%p, n->parent=%p\n", tn, NODE_PARENT(n));
+				BUG();
+			}
+		}
+		else
+			break;
+	}
+
+	/*
+	 * n  ----> NULL, LEAF or TNODE
+	 *
+	 * tp is n's (parent) ----> NULL or TNODE  
+	 */
+
+	if(tp && IS_LEAF(tp))
+		BUG();
+
+	t->revision++;
+
+	/* Case 1: n is a leaf. Compare prefixes */
+
+	if (n != NULL && IS_LEAF(n) && tkey_equals(key, n->key)) { 
+		struct leaf *l = ( struct leaf *)  n;
+		
+		li = leaf_info_new(plen);
+		
+		if(! li) 
+			BUG();
+
+		fa_head = &li->falh;
+		insert_leaf_info(&l->list, li);
+		goto done;
+	}
+	t->size++;
+	l = leaf_new();
+
+	if(! l) 
+		BUG();
+
+	l->key = key;
+	li = leaf_info_new(plen);
+
+	if(! li) 
+		BUG();
+
+	fa_head = &li->falh;
+	insert_leaf_info(&l->list, li);
+
+	/* Case 2: n is NULL, and will just insert a new leaf */
+	if (t->trie && n == NULL) {
+
+		NODE_SET_PARENT(l, tp);
+		
+		if (!tp) 
+			BUG();
+
+		else {
+			cindex = tkey_extract_bits(key, tp->pos, tp->bits);
+			put_child(t, (struct tnode *)tp, cindex, (struct node *)l);
+		}
+	}
+	/* Case 3: n is a LEAF or a TNODE and the key doesn't match. */
+	else {
+		/* 
+		 *  Add a new tnode here 
+		 *  first tnode need some special handling
+		 */
+
+		if (tp)
+			pos=tp->pos+tp->bits;
+		else
+			pos=0;
+		if(n) {
+			newpos = tkey_mismatch(key, pos, n->key);
+			tn = tnode_new(n->key, newpos, 1);
+		}
+		else {
+			newpos = 0;
+			tn = tnode_new(key, newpos, 1); /* First tnode */ 
+		}
+		if(!tn) 
+			trie_bug("tnode_pfx_new failed");
+
+		NODE_SET_PARENT(tn, tp);
+
+		missbit=tkey_extract_bits(key, newpos, 1);
+		put_child(t, tn, missbit, (struct node *)l);
+		put_child(t, tn, 1-missbit, n);
+
+		if(tp) {
+			cindex = tkey_extract_bits(key, tp->pos, tp->bits);
+			put_child(t, (struct tnode *)tp, cindex, (struct node *)tn);
+		}
+		else { 
+			t->trie = (struct node*) tn; /* First tnode */
+			tp = tn;
+		}
+	}
+	if(tp && tp->pos+tp->bits > 32) {
+		printk("ERROR tp=%p pos=%d, bits=%d, key=%0x plen=%d\n", 
+		       tp, tp->pos, tp->bits, key, plen);
+	}
+	/* Rebalance the trie */
+	t->trie = trie_rebalance(t, tp);
+done:;
+	return fa_head;
+}
+
+static int
+fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
+	       struct nlmsghdr *nlhdr, struct netlink_skb_parms *req)
+{
+	struct trie *t = (struct trie *) tb->tb_data;
+	struct fib_alias *fa, *new_fa;
+	struct list_head *fa_head=NULL;
+	struct fib_info *fi;
+	int plen = r->rtm_dst_len;
+	int type = r->rtm_type;
+	u8 tos = r->rtm_tos;
+	u32 key, mask;
+	int err;
+	struct leaf *l;
+
+	if (plen > 32)
+		return -EINVAL;
+
+	key = 0;
+	if (rta->rta_dst) 
+		memcpy(&key, rta->rta_dst, 4);
+
+	key = ntohl(key);
+
+	if(trie_debug)
+		printk("Insert table=%d %08x/%d\n", tb->tb_id, key, plen);
+
+	mask =  ntohl( inet_make_mask(plen) );
+
+	if(key & ~mask)
+		return -EINVAL;
+
+	key = key & mask;
+
+	if  ((fi = fib_create_info(r, rta, nlhdr, &err)) == NULL)
+		goto err;
+
+	l = fib_find_node(t, key);
+	fa = NULL;	
+
+	if(l) {
+		fa_head = get_fa_head(l, plen);
+		fa = fib_find_alias(fa_head, tos, fi->fib_priority);
+	}
+
+	/* Now fa, if non-NULL, points to the first fib alias
+	 * with the same keys [prefix,tos,priority], if such key already
+	 * exists or to the node before which we will insert new one.
+	 *
+	 * If fa is NULL, we will need to allocate a new one and
+	 * insert to the head of f.
+	 *
+	 * If f is NULL, no fib node matched the destination key
+	 * and we need to allocate a new one of those as well.
+	 */
+
+	if (fa &&
+	    fa->fa_info->fib_priority == fi->fib_priority) {
+		struct fib_alias *fa_orig;
+
+		err = -EEXIST;
+		if (nlhdr->nlmsg_flags & NLM_F_EXCL)
+			goto out;
+
+		if (nlhdr->nlmsg_flags & NLM_F_REPLACE) {
+			struct fib_info *fi_drop;
+			u8 state;
+
+			write_lock_bh(&fib_lock);
+
+			fi_drop = fa->fa_info;
+			fa->fa_info = fi;
+			fa->fa_type = type;
+			fa->fa_scope = r->rtm_scope;
+			state = fa->fa_state;
+			fa->fa_state &= ~FA_S_ACCESSED;
+
+			write_unlock_bh(&fib_lock);
+
+			fib_release_info(fi_drop);
+			if (state & FA_S_ACCESSED)
+			  rt_cache_flush(-1);
+
+			    goto succeeded;
+		}
+		/* Error if we find a perfect match which
+		 * uses the same scope, type, and nexthop
+		 * information.
+		 */
+		fa_orig = fa;
+		list_for_each_entry(fa, fa_orig->fa_list.prev, fa_list) {
+			if (fa->fa_tos != tos)
+				break;
+			if (fa->fa_info->fib_priority != fi->fib_priority)
+				break;
+			if (fa->fa_type == type &&
+			    fa->fa_scope == r->rtm_scope &&
+			    fa->fa_info == fi) {
+				goto out;
+			}
+		}
+		if (!(nlhdr->nlmsg_flags & NLM_F_APPEND))
+			fa = fa_orig;
+	}
+	err = -ENOENT;
+	if (!(nlhdr->nlmsg_flags&NLM_F_CREATE))
+		goto out;
+
+	err = -ENOBUFS;
+	new_fa = kmem_cache_alloc(fn_alias_kmem, SLAB_KERNEL);
+	if (new_fa == NULL)
+		goto out;
+
+	new_fa->fa_info = fi;
+	new_fa->fa_tos = tos;
+	new_fa->fa_type = type;
+	new_fa->fa_scope = r->rtm_scope;
+	new_fa->fa_state = 0;
+#if 0
+	new_fa->dst  = NULL;
+#endif
+	/*
+	 * Insert new entry to the list.
+	 */
+
+	if(!fa_head)
+		fa_head = fib_insert_node(t, key, plen);
+
+	write_lock_bh(&fib_lock);
+
+	list_add_tail(&new_fa->fa_list,
+		 (fa ? &fa->fa_list : fa_head));
+
+	write_unlock_bh(&fib_lock);
+
+	rt_cache_flush(-1);
+	rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id, nlhdr, req);
+succeeded:
+	return 0;
+out:
+	fib_release_info(fi);
+err:;	
+	return err;
+}
+
+static inline int check_leaf(struct trie *t, struct leaf *l,  t_key key, int *plen, const struct flowi *flp, 
+			     struct fib_result *res, int *err)
+{
+	int i;
+	t_key mask;
+	struct leaf_info *li;
+	struct hlist_head *hhead = &l->list;
+	struct hlist_node *node;
+	
+	hlist_for_each_entry(li, node, hhead, hlist) {
+
+		i = li->plen;
+		mask = ntohl(inet_make_mask(i));
+		if (l->key != (key & mask)) 
+			continue;
+
+		if (((*err) = fib_semantic_match(&li->falh, flp, res, l->key, mask, i)) == 0) {
+			*plen = i;
+#ifdef CONFIG_IP_FIB_TRIE_STATS
+			t->stats.semantic_match_passed++;
+#endif
+			return 1;
+		}
+#ifdef CONFIG_IP_FIB_TRIE_STATS
+		t->stats.semantic_match_miss++;
+#endif
+	}
+	return 0;
+}
+
+static int
+fn_trie_lookup(struct fib_table *tb, const struct flowi *flp, struct fib_result *res)
+{
+	struct trie *t = (struct trie *) tb->tb_data;
+	int plen, ret = 0;
+	struct node *n;
+	struct tnode *pn;
+	int pos, bits;
+	t_key key=ntohl(flp->fl4_dst);
+	int chopped_off;
+	t_key cindex = 0;
+	int current_prefix_length = KEYLENGTH;
+	n = t->trie;
+
+	read_lock(&fib_lock);
+	if(!n)
+		goto failed;
+
+#ifdef CONFIG_IP_FIB_TRIE_STATS
+	t->stats.gets++;
+#endif
+
+	/* Just a leaf? */
+	if (IS_LEAF(n)) {
+		if( check_leaf(t, (struct leaf *)n, key, &plen, flp, res, &ret) )
+			goto found;
+		goto failed;
+	}
+	pn = (struct tnode *) n;
+	chopped_off = 0;
+	
+        while (pn) {
+
+		pos = pn->pos;
+		bits = pn->bits;
+
+		if(!chopped_off) 
+			cindex = tkey_extract_bits(MASK_PFX(key, current_prefix_length), pos, bits);
+
+		n = tnode_get_child(pn, cindex);
+
+		if (n == NULL) {
+#ifdef CONFIG_IP_FIB_TRIE_STATS
+			t->stats.null_node_hit++;
+#endif
+			goto backtrace;
+		}
+
+		if (IS_TNODE(n)) {
+#define HL_OPTIMIZE
+#ifdef HL_OPTIMIZE
+			struct tnode *cn = (struct tnode *)n;
+			t_key node_prefix, key_prefix, pref_mismatch;
+			int mp;
+
+			/*
+			 * It's a tnode, and we can do some extra checks here if we 
+			 * like, to avoid descending into a dead-end branch.
+			 * This tnode is in the parent's child array at index 
+			 * key[p_pos..p_pos+p_bits] but potentially with some bits 
+			 * chopped off, so in reality the index may be just a 
+			 * subprefix, padded with zero at the end.
+			 * We can also take a look at any skipped bits in this 
+			 * tnode - everything up to p_pos is supposed to be ok, 
+			 * and the non-chopped bits of the index (se previous
+			 * paragraph) are also guaranteed ok, but the rest is 
+			 * considered unknown.
+			 *
+			 * The skipped bits are key[pos+bits..cn->pos].
+			 */
+			
+			/* If current_prefix_length < pos+bits, we are already doing 
+			 * actual prefix  matching, which means everything from 
+			 * pos+(bits-chopped_off) onward must be zero along some 
+			 * branch of this subtree - otherwise there is *no* valid 
+			 * prefix present. Here we can only check the skipped
+			 * bits. Remember, since we have already indexed into the 
+			 * parent's child array, we know that the bits we chopped of 
+			 * *are* zero.
+			 */
+
+			/* NOTA BENE: CHECKING ONLY SKIPPED BITS FOR THE NEW NODE HERE */
+			
+			if (current_prefix_length < pos+bits) {
+				if (tkey_extract_bits(cn->key, current_prefix_length,
+						      cn->pos - current_prefix_length) != 0 ||
+				    !(cn->child[0]))
+					goto backtrace;
+			}
+
+			/*
+			 * If chopped_off=0, the index is fully validated and we 
+			 * only need to look at the skipped bits for this, the new, 
+			 * tnode. What we actually want to do is to find out if
+			 * these skipped bits match our key perfectly, or if we will
+			 * have to count on finding a matching prefix further down, 
+			 * because if we do, we would like to have some way of 
+			 * verifying the existence of such a prefix at this point. 
+			 */
+
+			/* The only thing we can do at this point is to verify that
+			 * any such matching prefix can indeed be a prefix to our
+			 * key, and if the bits in the node we are inspecting that
+			 * do not match our key are not ZERO, this cannot be true.
+			 * Thus, find out where there is a mismatch (before cn->pos)
+			 * and verify that all the mismatching bits are zero in the
+			 * new tnode's key.
+			 */
+
+			/* Note: We aren't very concerned about the piece of the key 
+			 * that precede pn->pos+pn->bits, since these have already been 
+			 * checked. The bits after cn->pos aren't checked since these are 
+			 * by definition "unknown" at this point. Thus, what we want to 
+			 * see is if we are about to enter the "prefix matching" state, 
+			 * and in that case verify that the skipped bits that will prevail 
+			 * throughout this subtree are zero, as they have to be if we are 
+			 * to find a matching prefix.
+			 */
+
+			node_prefix = MASK_PFX(cn->key, cn->pos);
+			key_prefix =  MASK_PFX(key, cn->pos);
+			pref_mismatch = key_prefix^node_prefix;
+			mp = 0;
+
+			/* In short: If skipped bits in this node do not match the search 
+			 * key, enter the "prefix matching" state.directly.
+			 */
+			if (pref_mismatch) {
+				while (!(pref_mismatch & (1<<(KEYLENGTH-1)))) {
+					mp++;
+					pref_mismatch = pref_mismatch <<1;
+				}
+				key_prefix = tkey_extract_bits(cn->key, mp, cn->pos-mp);
+				
+				if (key_prefix != 0)
+					goto backtrace;
+
+				if (current_prefix_length >= cn->pos)
+					current_prefix_length=mp;
+		       }
+#endif
+		       pn = (struct tnode *)n; /* Descend */
+		       chopped_off = 0;
+		       continue;
+		} 
+		if (IS_LEAF(n)) {	
+			if( check_leaf(t, (struct leaf *)n, key, &plen, flp, res, &ret))
+				goto found;
+	       }
+backtrace:
+		chopped_off++;
+
+		/* As zero don't change the child key (cindex) */
+		while ((chopped_off <= pn->bits) && !(cindex & (1<<(chopped_off-1)))) {
+			chopped_off++;
+		}
+
+		/* Decrease current_... with bits chopped off */
+		if (current_prefix_length > pn->pos + pn->bits - chopped_off)
+			current_prefix_length = pn->pos + pn->bits - chopped_off;
+		
+		/*
+		 * Either we do the actual chop off according or if we have 
+		 * chopped off all bits in this tnode walk up to our parent.
+		 */
+
+		if(chopped_off <= pn->bits)
+			cindex &= ~(1 << (chopped_off-1));
+		else {
+			if( NODE_PARENT(pn) == NULL)
+				goto failed;
+			
+			/* Get Child's index */
+			cindex = tkey_extract_bits(pn->key, NODE_PARENT(pn)->pos, NODE_PARENT(pn)->bits);
+			pn = NODE_PARENT(pn);
+			chopped_off = 0;
+
+#ifdef CONFIG_IP_FIB_TRIE_STATS
+			t->stats.backtrack++;
+#endif
+			goto backtrace;
+		} 
+	}
+failed:
+	ret =  1;
+found:
+	read_unlock(&fib_lock);
+	return ret;
+}
+
+static int trie_leaf_remove(struct trie *t, t_key key)
+{
+	t_key cindex;
+	struct tnode *tp = NULL;
+	struct node *n = t->trie;
+	struct leaf *l;
+
+	if(trie_debug) 
+		printk("entering trie_leaf_remove(%p)\n", n);
+
+	/* Note that in the case skipped bits, those bits are *not* checked!
+	 * When we finish this, we will have NULL or a T_LEAF, and the 
+	 * T_LEAF may or may not match our key.
+	 */
+
+        while (n != NULL && IS_TNODE(n)) {
+		struct tnode *tn = (struct tnode *) n;
+		check_tnode(tn);
+		n = tnode_get_child(tn ,tkey_extract_bits(key, tn->pos, tn->bits));
+
+			if(n && NODE_PARENT(n) != tn) {
+				printk("BUG tn=%p, n->parent=%p\n", tn, NODE_PARENT(n));
+				BUG();
+			}
+        }
+	l = (struct leaf *) n;
+
+	if(!n || !tkey_equals(l->key, key)) 
+		return 0;
+    
+	/* 
+	 * Key found. 
+	 * Remove the leaf and rebalance the tree 
+	 */
+
+	t->revision++;
+	t->size--;
+
+	tp = NODE_PARENT(n);
+	tnode_free((struct tnode *) n);
+
+	if(tp) {
+		cindex = tkey_extract_bits(key, tp->pos, tp->bits);
+		put_child(t, (struct tnode *)tp, cindex, NULL);
+		t->trie = trie_rebalance(t, tp);
+	}
+	else
+		t->trie = NULL;
+
+	return 1;
+}
+
+static int
+fn_trie_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
+	       struct nlmsghdr *nlhdr, struct netlink_skb_parms *req)
+{
+	struct trie *t = (struct trie *) tb->tb_data;
+	u32 key, mask;
+	int plen = r->rtm_dst_len;
+	u8 tos = r->rtm_tos;
+	struct fib_alias *fa, *fa_to_delete;
+	struct list_head *fa_head;
+	struct leaf *l;
+
+	if (plen > 32) 
+		return -EINVAL;
+
+	key = 0;
+	if (rta->rta_dst) 
+		memcpy(&key, rta->rta_dst, 4);
+
+	key = ntohl(key);
+	mask =  ntohl( inet_make_mask(plen) );
+
+	if(key & ~mask)
+		return -EINVAL;
+
+	key = key & mask;
+	l = fib_find_node(t, key);
+
+	if(!l)
+		return -ESRCH;
+
+	fa_head = get_fa_head(l, plen);
+	fa = fib_find_alias(fa_head, tos, 0);
+
+	if (!fa)
+		return -ESRCH;
+
+	if (trie_debug)
+		printk("Deleting %08x/%d tos=%d t=%p\n", key, plen, tos, t);
+
+	fa_to_delete = NULL;
+	fa_head = fa->fa_list.prev;
+	list_for_each_entry(fa, fa_head, fa_list) {
+		struct fib_info *fi = fa->fa_info;
+
+		if (fa->fa_tos != tos)
+			break;
+
+		if ((!r->rtm_type ||
+		     fa->fa_type == r->rtm_type) &&
+		    (r->rtm_scope == RT_SCOPE_NOWHERE ||
+		     fa->fa_scope == r->rtm_scope) &&
+		    (!r->rtm_protocol ||
+		     fi->fib_protocol == r->rtm_protocol) &&
+		    fib_nh_match(r, nlhdr, rta, fi) == 0) {
+			fa_to_delete = fa;
+			break;
+		}
+	}
+
+	if (fa_to_delete) {
+		int kill_li = 0;
+		struct leaf_info *li;
+
+		fa = fa_to_delete;
+		rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id, nlhdr, req);
+
+		l = fib_find_node(t, key);
+		li = find_leaf_info(&l->list, plen);
+
+		write_lock_bh(&fib_lock);
+
+		list_del(&fa->fa_list);
+
+		if(list_empty(fa_head)) {
+			hlist_del(&li->hlist);
+			kill_li = 1;
+		}
+		write_unlock_bh(&fib_lock);
+		
+		if(kill_li)
+			free_leaf_info(li);
+
+		if(hlist_empty(&l->list))
+			trie_leaf_remove(t, key);
+
+		if (fa->fa_state & FA_S_ACCESSED)
+			rt_cache_flush(-1);
+
+		fn_free_alias(fa);
+		return 0;
+	}
+	return -ESRCH;
+}
+
+static int trie_flush_list(struct trie *t, struct list_head *head)
+{
+	struct fib_alias *fa, *fa_node;
+	int found = 0;
+
+	list_for_each_entry_safe(fa, fa_node, head, fa_list) {
+		struct fib_info *fi = fa->fa_info;
+		
+		if (fi && (fi->fib_flags&RTNH_F_DEAD)) {
+
+ 			write_lock_bh(&fib_lock);	
+			list_del(&fa->fa_list);
+			write_unlock_bh(&fib_lock); 
+
+			fn_free_alias(fa);
+			found++;
+		}
+	}
+	return found;
+}
+
+static int trie_flush_leaf(struct trie *t, struct leaf *l)
+{
+	int found = 0;
+	struct hlist_head *lih = &l->list;
+	struct hlist_node *node, *tmp;
+	struct leaf_info *li = NULL;
+
+	hlist_for_each_entry_safe(li, node, tmp, lih, hlist) {
+			
+		found += trie_flush_list(t, &li->falh);
+
+		if (list_empty(&li->falh)) {
+
+ 			write_lock_bh(&fib_lock); 
+			hlist_del(&li->hlist);
+			write_unlock_bh(&fib_lock); 
+
+			free_leaf_info(li);
+		}
+	}
+	return found;
+}
+
+static struct leaf *nextleaf(struct trie *t, struct leaf *thisleaf)
+{
+	struct node *c = (struct node *) thisleaf;
+	struct tnode *p;
+	int idx;
+
+	if(c == NULL) {
+		if(t->trie == NULL)
+			return NULL;
+
+		if (IS_LEAF(t->trie))          /* trie w. just a leaf */
+			return (struct leaf *) t->trie;
+
+		p = (struct tnode*) t->trie;  /* Start */
+	}
+	else 
+		p = (struct tnode *) NODE_PARENT(c);
+	while (p) {
+		int pos, last;
+
+		/*  Find the next child of the parent */
+		if(c)
+			pos  = 1 + tkey_extract_bits(c->key, p->pos, p->bits);
+		else 
+			pos = 0;
+
+		last = 1 << p->bits;
+		for(idx = pos; idx < last ; idx++) {
+			if( p->child[idx]) {
+
+				/* Decend if tnode */
+
+				while (IS_TNODE(p->child[idx])) {
+					p = (struct tnode*) p->child[idx];
+					idx = 0;
+					
+					/* Rightmost non-NULL branch */
+					if( p && IS_TNODE(p) )
+						while ( p->child[idx] == NULL && idx < (1 << p->bits) ) idx++;
+
+					/* Done with this tnode? */
+					if( idx >= (1 << p->bits) || p->child[idx] == NULL ) 
+						goto up;
+				}
+				return (struct leaf*) p->child[idx];
+			}
+		}
+up:
+		/* No more children go up one step  */
+		c = (struct node*) p;
+		p = (struct tnode *) NODE_PARENT(p);
+	}
+	return NULL; /* Ready. Root of trie */
+}
+
+static int fn_trie_flush(struct fib_table *tb)
+{
+	struct trie *t = (struct trie *) tb->tb_data;
+	struct leaf *ll = NULL, *l = NULL;
+	int found = 0, h;
+
+	t->revision++;
+
+	for (h=0; (l = nextleaf(t, l)) != NULL; h++) {
+		found += trie_flush_leaf(t, l);
+
+		if (ll && hlist_empty(&ll->list))
+			trie_leaf_remove(t, ll->key);
+		ll = l;
+	}
+
+	if (ll && hlist_empty(&ll->list))
+		trie_leaf_remove(t, ll->key);
+
+	if(trie_debug) 
+		printk("trie_flush found=%d\n", found);
+	return found;
+}
+
+static int trie_last_dflt=-1;
+
+static void
+fn_trie_select_default(struct fib_table *tb, const struct flowi *flp, struct fib_result *res)
+{
+	struct trie *t = (struct trie *) tb->tb_data;
+	int order, last_idx;
+	struct fib_info *fi = NULL;
+	struct fib_info *last_resort;
+	struct fib_alias *fa = NULL;
+	struct list_head *fa_head;
+	struct leaf *l;
+
+	last_idx = -1;
+	last_resort = NULL;
+	order = -1;
+
+	read_lock(&fib_lock);
+	
+	l = fib_find_node(t, 0);
+	if(!l) 
+		goto out;
+
+	fa_head = get_fa_head(l, 0);
+	if(!fa_head)
+		goto out;
+
+	if (list_empty(fa_head)) 
+		goto out;
+
+	list_for_each_entry(fa, fa_head, fa_list) {
+		struct fib_info *next_fi = fa->fa_info;
+		
+		if (fa->fa_scope != res->scope ||
+		    fa->fa_type != RTN_UNICAST)
+			continue;
+		
+		if (next_fi->fib_priority > res->fi->fib_priority)
+			break;
+		if (!next_fi->fib_nh[0].nh_gw ||
+		    next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
+			continue;
+		fa->fa_state |= FA_S_ACCESSED;
+		
+		if (fi == NULL) {
+			if (next_fi != res->fi)
+				break;
+		} else if (!fib_detect_death(fi, order, &last_resort,
+					     &last_idx, &trie_last_dflt)) {
+			if (res->fi)
+				fib_info_put(res->fi);
+			res->fi = fi;
+			atomic_inc(&fi->fib_clntref);
+			trie_last_dflt = order;
+			goto out;
+		}
+		fi = next_fi;
+		order++;
+	}
+	if (order <= 0 || fi == NULL) {
+		trie_last_dflt = -1;
+		goto out;
+	}
+
+	if (!fib_detect_death(fi, order, &last_resort, &last_idx, &trie_last_dflt)) {
+		if (res->fi)
+			fib_info_put(res->fi);
+		res->fi = fi;
+		atomic_inc(&fi->fib_clntref);
+		trie_last_dflt = order;
+		goto out;
+	}
+	if (last_idx >= 0) {
+		if (res->fi)
+			fib_info_put(res->fi);
+		res->fi = last_resort;
+		if (last_resort)
+			atomic_inc(&last_resort->fib_clntref);
+	}
+	trie_last_dflt = last_idx;
+ out:;
+	read_unlock(&fib_lock);	
+}
+
+static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah, struct fib_table *tb, 
+			   struct sk_buff *skb, struct netlink_callback *cb)
+{
+	int i, s_i;
+	struct fib_alias *fa;
+
+	u32 xkey=htonl(key);
+
+	s_i=cb->args[3];
+	i = 0;
+
+	list_for_each_entry(fa, fah, fa_list) {
+		if (i < s_i) {
+			i++;
+			continue;
+		}
+		if (fa->fa_info->fib_nh == NULL) {
+			printk("Trie error _fib_nh=NULL in fa[%d] k=%08x plen=%d\n", i, key, plen);
+			i++;
+			continue;
+		}
+		if (fa->fa_info == NULL) {
+			printk("Trie error fa_info=NULL in fa[%d] k=%08x plen=%d\n", i, key, plen);
+			i++;
+			continue;
+		}
+
+		if (fib_dump_info(skb, NETLINK_CB(cb->skb).pid,
+				  cb->nlh->nlmsg_seq,
+				  RTM_NEWROUTE,
+				  tb->tb_id,
+				  fa->fa_type,
+				  fa->fa_scope,
+				  &xkey,
+				  plen,
+				  fa->fa_tos,
+				  fa->fa_info, 0) < 0) {
+			cb->args[3] = i;
+			return -1;
+			}
+		i++;
+	}
+	cb->args[3]=i;
+	return skb->len;
+}
+
+static int fn_trie_dump_plen(struct trie *t, int plen, struct fib_table *tb, struct sk_buff *skb, 
+			     struct netlink_callback *cb)
+{
+	int h, s_h;
+	struct list_head *fa_head;
+	struct leaf *l = NULL;
+	s_h=cb->args[2];
+
+	for (h=0; (l = nextleaf(t, l)) != NULL; h++) {
+
+		if (h < s_h)
+			continue;
+		if (h > s_h)
+			memset(&cb->args[3], 0,
+			       sizeof(cb->args) - 3*sizeof(cb->args[0]));
+
+		fa_head = get_fa_head(l, plen);
+		
+		if(!fa_head)
+			continue;
+
+		if(list_empty(fa_head))
+			continue;
+
+		if (fn_trie_dump_fa(l->key, plen, fa_head, tb, skb, cb)<0) {
+			cb->args[2]=h;
+			return -1;
+		}
+	}
+	cb->args[2]=h;
+	return skb->len;
+}
+
+static int fn_trie_dump(struct fib_table *tb, struct sk_buff *skb, struct netlink_callback *cb)
+{
+	int m, s_m;
+	struct trie *t = (struct trie *) tb->tb_data;
+
+	s_m = cb->args[1];
+
+	read_lock(&fib_lock);
+	for (m=0; m<=32; m++) {
+
+		if (m < s_m)
+			continue;
+		if (m > s_m)
+			memset(&cb->args[2], 0,
+			       sizeof(cb->args) - 2*sizeof(cb->args[0]));
+
+		if (fn_trie_dump_plen(t, 32-m, tb, skb, cb)<0) {
+			cb->args[1] = m;
+			goto out;
+		}
+	}
+	read_unlock(&fib_lock);
+	cb->args[1] = m;
+	return skb->len;
+ out:
+	read_unlock(&fib_lock);
+	return -1;
+}
+
+/* Fix more generic FIB names for init later */
+
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+struct fib_table * fib_hash_init(int id)
+#else
+struct fib_table * __init fib_hash_init(int id)
+#endif
+{
+	struct fib_table *tb;
+	struct trie *t;
+
+	if (fn_alias_kmem == NULL)
+		fn_alias_kmem = kmem_cache_create("ip_fib_alias",
+						  sizeof(struct fib_alias),
+						  0, SLAB_HWCACHE_ALIGN,
+						  NULL, NULL);
+
+	tb = kmalloc(sizeof(struct fib_table) + sizeof(struct trie),
+		     GFP_KERNEL);
+	if (tb == NULL)
+		return NULL;
+
+	tb->tb_id = id;
+	tb->tb_lookup = fn_trie_lookup;
+	tb->tb_insert = fn_trie_insert;
+	tb->tb_delete = fn_trie_delete;
+	tb->tb_flush = fn_trie_flush;
+	tb->tb_select_default = fn_trie_select_default;
+	tb->tb_dump = fn_trie_dump;
+	memset(tb->tb_data, 0, sizeof(struct trie));
+
+	t = (struct trie *) tb->tb_data;
+
+	trie_init(t);
+
+	if (id == RT_TABLE_LOCAL) 
+                trie_local=t;
+	  else if (id == RT_TABLE_MAIN) 
+                trie_main=t;
+
+	if (id == RT_TABLE_LOCAL)
+		printk("IPv4 FIB: Using LC-trie version %s\n", VERSION);
+
+	return tb;
+}
+
+/* Trie dump functions */
+
+static void putspace_seq(struct seq_file *seq, int n)
+{
+	while (n--) seq_printf(seq, " ");
+}
+
+static void printbin_seq(struct seq_file *seq, unsigned int v, int bits)
+{
+	while (bits--)
+		seq_printf(seq, "%s", (v & (1<<bits))?"1":"0");
+}
+
+static void printnode_seq(struct seq_file *seq, int indent, struct node *n, 
+		   int pend, int cindex, int bits)
+{
+	putspace_seq(seq, indent);
+	if (IS_LEAF(n))
+		seq_printf(seq, "|");
+	else
+		seq_printf(seq, "+");
+	if (bits) {
+		seq_printf(seq, "%d/", cindex);
+		printbin_seq(seq, cindex, bits);
+		seq_printf(seq, ": ");
+	}
+	else
+		seq_printf(seq, "<root>: ");
+	seq_printf(seq, "%s:%p ", IS_LEAF(n)?"Leaf":"Internal node", n);
+
+	if (IS_LEAF(n))
+		seq_printf(seq, "key=%d.%d.%d.%d\n", 
+			   n->key >> 24, (n->key >> 16) % 256, (n->key >> 8) % 256, n->key % 256);
+	else {
+		int plen=((struct tnode *)n)->pos;
+		t_key prf=MASK_PFX(n->key, plen);
+		seq_printf(seq, "key=%d.%d.%d.%d/%d\n", 
+			   prf >> 24, (prf >> 16) % 256, (prf >> 8) % 256, prf % 256, plen);
+	}
+	if (IS_LEAF(n)) {
+		struct leaf *l=(struct leaf *)n;
+		struct fib_alias *fa;
+		int i;
+		for (i=32; i>=0; i--)
+		  if(find_leaf_info(&l->list, i)) {
+			
+				struct list_head *fa_head = get_fa_head(l, i);
+				
+				if(!fa_head)
+					continue;
+
+				if(list_empty(fa_head))
+					continue;
+
+				putspace_seq(seq, indent+2);
+				seq_printf(seq, "{/%d...dumping}\n", i);
+
+
+				list_for_each_entry(fa, fa_head, fa_list) {
+					putspace_seq(seq, indent+2);
+					if (fa->fa_info->fib_nh == NULL) {
+						seq_printf(seq, "Error _fib_nh=NULL\n");
+						continue;
+					}
+					if (fa->fa_info == NULL) {
+						seq_printf(seq, "Error fa_info=NULL\n");
+						continue;
+					}
+
+					seq_printf(seq, "{type=%d scope=%d TOS=%d}\n",
+					      fa->fa_type,
+					      fa->fa_scope,
+					      fa->fa_tos);
+				}
+			}
+	}
+	else if (IS_TNODE(n)) {
+		struct tnode *tn=(struct tnode *)n;
+		putspace_seq(seq, indent); seq_printf(seq, "|    ");
+		seq_printf(seq, "{key prefix=%08x/", tn->key&TKEY_GET_MASK(0, tn->pos));
+		printbin_seq(seq, tkey_extract_bits(tn->key, 0, tn->pos), tn->pos);
+		seq_printf(seq, "}\n");
+		putspace_seq(seq, indent); seq_printf(seq, "|    ");
+		seq_printf(seq, "{pos=%d", tn->pos);
+		seq_printf(seq, " (skip=%d bits)", tn->pos - pend);
+		seq_printf(seq, " bits=%d (%u children)}\n", tn->bits, (1 << tn->bits));
+		putspace_seq(seq, indent); seq_printf(seq, "|    ");
+		seq_printf(seq, "{empty=%d full=%d}\n", tn->empty_children, tn->full_children);
+	}
+}
+
+static void trie_dump_seq(struct seq_file *seq, struct trie *t)
+{
+	struct node *n=t->trie;
+	int cindex=0;
+	int indent=1;
+	int pend=0;
+	int depth = 0;
+
+  	read_lock(&fib_lock);
+
+	seq_printf(seq, "------ trie_dump of t=%p ------\n", t);
+	if (n) {
+		printnode_seq(seq, indent, n, pend, cindex, 0);
+		if (IS_TNODE(n)) {
+			struct tnode *tn=(struct tnode *)n;
+			pend = tn->pos+tn->bits;
+			putspace_seq(seq, indent); seq_printf(seq, "\\--\n");
+			indent += 3;
+			depth++;
+
+			while (tn && cindex < (1 << tn->bits)) {
+				if (tn->child[cindex]) {
+					
+					/* Got a child */
+					
+					printnode_seq(seq, indent, tn->child[cindex], pend, cindex, tn->bits);
+					if (IS_LEAF(tn->child[cindex])) { 
+						cindex++;
+						
+					}
+					else {
+						/* 
+						 * New tnode. Decend one level 
+						 */
+						
+						depth++;
+						n=tn->child[cindex];
+						tn=(struct tnode *)n;
+						pend=tn->pos+tn->bits;
+						putspace_seq(seq, indent); seq_printf(seq, "\\--\n");
+						indent+=3;
+						cindex=0;
+					}
+				}
+				else 
+					cindex++;
+
+				/*
+				 * Test if we are done 
+				 */
+				
+				while (cindex >= (1 << tn->bits)) {
+
+					/*
+					 * Move upwards and test for root
+					 * pop off all traversed  nodes
+					 */
+					
+					if (NODE_PARENT(tn) == NULL) {
+						tn = NULL;
+						n = NULL;
+						break;
+					}
+					else {
+						cindex = tkey_extract_bits(tn->key, NODE_PARENT(tn)->pos, NODE_PARENT(tn)->bits);
+						tn = NODE_PARENT(tn);
+						cindex++;
+						n=(struct node *)tn;
+						pend=tn->pos+tn->bits;
+						indent-=3;
+						depth--;
+					}
+				}
+			}
+		}
+		else n = NULL;
+	}
+	else seq_printf(seq, "------ trie is empty\n");
+
+  	read_unlock(&fib_lock);
+}
+
+static struct trie_stat *trie_stat_new(void)
+{
+	struct trie_stat *s = kmalloc(sizeof(struct trie_stat), GFP_KERNEL);
+	int i;
+	
+	if(s) {
+		s->totdepth = 0;
+		s->maxdepth = 0;
+		s->tnodes = 0;
+		s->leaves = 0;
+		s->nullpointers = 0;
+		
+		for(i=0; i< MAX_CHILDS; i++)
+			s->nodesizes[i] = 0;
+	}
+	return s;
+}    
+
+static struct trie_stat *trie_collect_stats(struct trie *t)
+{
+	struct node *n=t->trie;
+	struct trie_stat *s = trie_stat_new();
+	int cindex = 0;
+	int indent = 1;
+	int pend = 0;
+	int depth = 0;
+
+	read_lock(&fib_lock);		
+
+	if (s) {
+		if (n) {
+			if (IS_TNODE(n)) {
+				struct tnode *tn = (struct tnode *)n;
+				pend=tn->pos+tn->bits;
+				indent += 3;
+				s->nodesizes[tn->bits]++;
+				depth++;
+
+				while (tn && cindex < (1 << tn->bits)) {
+					if (tn->child[cindex]) {
+						/* Got a child */
+					
+						if (IS_LEAF(tn->child[cindex])) { 
+							cindex++;
+						
+							/* stats */
+							if (depth > s->maxdepth)
+								s->maxdepth = depth;
+							s->totdepth += depth;
+							s->leaves++;
+						}
+					
+						else {
+							/* 
+							 * New tnode. Decend one level 
+							 */
+						
+							s->tnodes++;
+							s->nodesizes[tn->bits]++;
+							depth++;
+						
+							n = tn->child[cindex];
+							tn = (struct tnode *)n;
+							pend = tn->pos+tn->bits;
+
+							indent += 3;
+							cindex = 0;
+						}
+					}
+					else {
+						cindex++;
+						s->nullpointers++; 
+					}
+
+					/*
+					 * Test if we are done 
+					 */
+				
+					while (cindex >= (1 << tn->bits)) {
+
+						/*
+						 * Move upwards and test for root
+						 * pop off all traversed  nodes
+						 */
+
+						
+						if (NODE_PARENT(tn) == NULL) {
+							tn = NULL;
+							n = NULL;
+							break;
+						}
+						else {
+							cindex = tkey_extract_bits(tn->key, NODE_PARENT(tn)->pos, NODE_PARENT(tn)->bits);
+							tn = NODE_PARENT(tn);
+							cindex++; 
+							n = (struct node *)tn;
+							pend=tn->pos+tn->bits;
+							indent -= 3;
+							depth--;
+						}
+ 					}
+				}
+			}
+			else n = NULL;
+		}
+	}
+
+	read_unlock(&fib_lock);		
+	return s;
+}
+
+#ifdef CONFIG_PROC_FS
+
+static struct fib_alias *fib_triestat_get_first(struct seq_file *seq)
+{
+	return NULL;
+}
+
+static struct fib_alias *fib_triestat_get_next(struct seq_file *seq)
+{
+	return NULL;
+}
+
+static void *fib_triestat_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	void *v = NULL;
+
+	if (ip_fib_main_table)
+		v = *pos ? fib_triestat_get_next(seq) : SEQ_START_TOKEN;
+	return v;
+}
+
+static void *fib_triestat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	++*pos;
+	return v == SEQ_START_TOKEN ? fib_triestat_get_first(seq) : fib_triestat_get_next(seq);
+}
+
+static void fib_triestat_seq_stop(struct seq_file *seq, void *v)
+{
+
+}
+
+/* 
+ *	This outputs /proc/net/fib_triestats
+ *
+ *	It always works in backward compatibility mode.
+ *	The format of the file is not supposed to be changed.
+ */
+
+static void collect_and_show(struct trie *t, struct seq_file *seq)
+{
+	int bytes = 0; /* How many bytes are used, a ref is 4 bytes */
+	int i, max, pointers;
+        struct trie_stat *stat;
+	int avdepth;
+
+	stat = trie_collect_stats(t);
+
+	bytes=0;
+	seq_printf(seq, "trie=%p\n", t);
+
+	if (stat) {
+		if (stat->leaves)
+			avdepth=stat->totdepth*100 / stat->leaves;
+		else
+			avdepth=0;
+		seq_printf(seq, "Aver depth: %d.%02d\n", avdepth / 100, avdepth % 100 );
+		seq_printf(seq, "Max depth: %4d\n", stat->maxdepth);
+				
+		seq_printf(seq, "Leaves: %d\n", stat->leaves);
+		bytes += sizeof(struct leaf) * stat->leaves;
+		seq_printf(seq, "Internal nodes: %d\n", stat->tnodes);
+		bytes += sizeof(struct tnode) * stat->tnodes;
+
+		max = MAX_CHILDS-1;
+
+		while (max >= 0 && stat->nodesizes[max] == 0)
+			max--;
+		pointers = 0;
+
+		for (i = 1; i <= max; i++) 
+			if (stat->nodesizes[i] != 0) {
+				seq_printf(seq, "  %d: %d",  i, stat->nodesizes[i]);
+				pointers += (1<<i) * stat->nodesizes[i];
+			}
+		seq_printf(seq, "\n");
+		seq_printf(seq, "Pointers: %d\n", pointers);
+		bytes += sizeof(struct node *) * pointers;
+		seq_printf(seq, "Null ptrs: %d\n", stat->nullpointers);
+		seq_printf(seq, "Total size: %d  kB\n", bytes / 1024);
+
+		kfree(stat);
+	}
+
+#ifdef CONFIG_IP_FIB_TRIE_STATS
+	seq_printf(seq, "Counters:\n---------\n");
+	seq_printf(seq,"gets = %d\n", t->stats.gets);
+	seq_printf(seq,"backtracks = %d\n", t->stats.backtrack);
+	seq_printf(seq,"semantic match passed = %d\n", t->stats.semantic_match_passed);
+	seq_printf(seq,"semantic match miss = %d\n", t->stats.semantic_match_miss);
+	seq_printf(seq,"null node hit= %d\n", t->stats.null_node_hit);
+#ifdef CLEAR_STATS
+	memset(&(t->stats), 0, sizeof(t->stats));
+#endif
+#endif /*  CONFIG_IP_FIB_TRIE_STATS */
+}
+
+static int fib_triestat_seq_show(struct seq_file *seq, void *v)
+{
+	char bf[128];
+    
+	if (v == SEQ_START_TOKEN) {
+		seq_printf(seq, "Basic info: size of leaf: %Zd bytes, size of tnode: %Zd bytes.\n", 
+			   sizeof(struct leaf), sizeof(struct tnode));
+		if (trie_local) 
+			collect_and_show(trie_local, seq);
+
+		if (trie_main) 
+			collect_and_show(trie_main, seq);
+	}
+	else {
+		snprintf(bf, sizeof(bf),
+			 "*\t%08X\t%08X", 200, 400);
+		
+		seq_printf(seq, "%-127s\n", bf);
+	}
+	return 0;
+}
+
+static struct seq_operations fib_triestat_seq_ops = {
+	.start  = fib_triestat_seq_start,
+	.next   = fib_triestat_seq_next,
+	.stop   = fib_triestat_seq_stop,
+	.show   = fib_triestat_seq_show,
+};
+
+static int fib_triestat_seq_open(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq;
+	int rc = -ENOMEM;
+
+	rc = seq_open(file, &fib_triestat_seq_ops);
+	if (rc)
+		goto out_kfree;
+
+	seq	     = file->private_data;
+out:
+	return rc;
+out_kfree:
+	goto out;
+}
+
+static struct file_operations fib_triestat_seq_fops = {
+	.owner		= THIS_MODULE,
+	.open           = fib_triestat_seq_open,
+	.read           = seq_read,
+	.llseek         = seq_lseek,
+	.release	= seq_release_private,
+};
+
+int __init fib_stat_proc_init(void)
+{
+	if (!proc_net_fops_create("fib_triestat", S_IRUGO, &fib_triestat_seq_fops))
+		return -ENOMEM;
+	return 0;
+}
+
+void __init fib_stat_proc_exit(void)
+{
+	proc_net_remove("fib_triestat");
+}
+
+static struct fib_alias *fib_trie_get_first(struct seq_file *seq)
+{
+	return NULL;
+}
+
+static struct fib_alias *fib_trie_get_next(struct seq_file *seq)
+{
+	return NULL;
+}
+
+static void *fib_trie_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	void *v = NULL;
+
+	if (ip_fib_main_table)
+		v = *pos ? fib_trie_get_next(seq) : SEQ_START_TOKEN;
+	return v;
+}
+
+static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	++*pos;
+	return v == SEQ_START_TOKEN ? fib_trie_get_first(seq) : fib_trie_get_next(seq);
+}
+
+static void fib_trie_seq_stop(struct seq_file *seq, void *v)
+{
+
+}
+
+/* 
+ *	This outputs /proc/net/fib_trie.
+ *
+ *	It always works in backward compatibility mode.
+ *	The format of the file is not supposed to be changed.
+ */
+
+static int fib_trie_seq_show(struct seq_file *seq, void *v)
+{
+	char bf[128];
+
+	if (v == SEQ_START_TOKEN) {
+		if (trie_local) 
+			trie_dump_seq(seq, trie_local);
+
+		if (trie_main) 
+			trie_dump_seq(seq, trie_main);
+	}
+
+	else {
+		snprintf(bf, sizeof(bf),
+			 "*\t%08X\t%08X", 200, 400);
+		seq_printf(seq, "%-127s\n", bf);
+	}
+
+	return 0;
+}
+
+static struct seq_operations fib_trie_seq_ops = {
+	.start  = fib_trie_seq_start,
+	.next   = fib_trie_seq_next,
+	.stop   = fib_trie_seq_stop,
+	.show   = fib_trie_seq_show,
+};
+
+static int fib_trie_seq_open(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq;
+	int rc = -ENOMEM;
+
+	rc = seq_open(file, &fib_trie_seq_ops);
+	if (rc)
+		goto out_kfree;
+
+	seq	     = file->private_data;
+out:
+	return rc;
+out_kfree:
+	goto out;
+}
+
+static struct file_operations fib_trie_seq_fops = {
+	.owner		= THIS_MODULE,
+	.open           = fib_trie_seq_open,
+	.read           = seq_read,
+	.llseek         = seq_lseek,
+	.release	= seq_release_private,
+};
+
+int __init fib_proc_init(void)
+{
+	if (!proc_net_fops_create("fib_trie", S_IRUGO, &fib_trie_seq_fops))
+		return -ENOMEM;
+	return 0;
+}
+
+void __init fib_proc_exit(void)
+{
+	proc_net_remove("fib_trie");
+}
+
+#endif /* CONFIG_PROC_FS */
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 85bf0d3..cb75948 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -207,6 +207,7 @@
 
 int sysctl_icmp_ratelimit = 1 * HZ;
 int sysctl_icmp_ratemask = 0x1818;
+int sysctl_icmp_errors_use_inbound_ifaddr;
 
 /*
  *	ICMP control array. This specifies what to do with each ICMP.
@@ -511,8 +512,12 @@
 	 */
 
 	saddr = iph->daddr;
-	if (!(rt->rt_flags & RTCF_LOCAL))
-		saddr = 0;
+	if (!(rt->rt_flags & RTCF_LOCAL)) {
+		if (sysctl_icmp_errors_use_inbound_ifaddr)
+			saddr = inet_select_addr(skb_in->dev, 0, RT_SCOPE_LINK);
+		else
+			saddr = 0;
+	}
 
 	tos = icmp_pointers[type].error ? ((iph->tos & IPTOS_TOS_MASK) |
 					   IPTOS_PREC_INTERNETCONTROL) :
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index 4e47a26..af2ec88 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -184,6 +184,7 @@
 					raw_rcv(last, skb2);
 			}
 			last = sk;
+			nf_reset(skb);
 		}
 	}
 
@@ -200,10 +201,6 @@
 {
 	int ihl = skb->nh.iph->ihl*4;
 
-#ifdef CONFIG_NETFILTER_DEBUG
-	nf_debug_ip_local_deliver(skb);
-#endif /*CONFIG_NETFILTER_DEBUG*/
-
 	__skb_pull(skb, ihl);
 
 	/* Free reference early: we don't need it any more, and it may
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 760dc82..ee07aec 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -107,10 +107,6 @@
 	newskb->pkt_type = PACKET_LOOPBACK;
 	newskb->ip_summed = CHECKSUM_UNNECESSARY;
 	BUG_TRAP(newskb->dst);
-
-#ifdef CONFIG_NETFILTER_DEBUG
-	nf_debug_ip_loopback_xmit(newskb);
-#endif
 	nf_reset(newskb);
 	netif_rx(newskb);
 	return 0;
@@ -192,10 +188,6 @@
 		skb = skb2;
 	}
 
-#ifdef CONFIG_NETFILTER_DEBUG
-	nf_debug_ip_finish_output2(skb);
-#endif /*CONFIG_NETFILTER_DEBUG*/
-
 	nf_reset(skb);
 
 	if (hh) {
@@ -415,9 +407,6 @@
 	to->nf_bridge = from->nf_bridge;
 	nf_bridge_get(to->nf_bridge);
 #endif
-#ifdef CONFIG_NETFILTER_DEBUG
-	to->nf_debug = from->nf_debug;
-#endif
 #endif
 }
 
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 47012b9..f8b172f 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -360,14 +360,14 @@
 	err = copied;
 
 	/* Reset and regenerate socket error */
-	spin_lock_irq(&sk->sk_error_queue.lock);
+	spin_lock_bh(&sk->sk_error_queue.lock);
 	sk->sk_err = 0;
 	if ((skb2 = skb_peek(&sk->sk_error_queue)) != NULL) {
 		sk->sk_err = SKB_EXT_ERR(skb2)->ee.ee_errno;
-		spin_unlock_irq(&sk->sk_error_queue.lock);
+		spin_unlock_bh(&sk->sk_error_queue.lock);
 		sk->sk_error_report(sk);
 	} else
-		spin_unlock_irq(&sk->sk_error_queue.lock);
+		spin_unlock_bh(&sk->sk_error_queue.lock);
 
 out_free_skb:	
 	kfree_skb(skb);
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 1a23c52..2065944 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -236,15 +236,10 @@
 	t->props.mode = 1;
 	t->props.saddr.a4 = x->props.saddr.a4;
 	t->props.flags = x->props.flags;
-	
-	t->type = xfrm_get_type(IPPROTO_IPIP, t->props.family);
-	if (t->type == NULL)
-		goto error;
-		
-	if (t->type->init_state(t, NULL))
+
+	if (xfrm_init_state(t))
 		goto error;
 
-	t->km.state = XFRM_STATE_VALID;
 	atomic_set(&t->tunnel_users, 1);
 out:
 	return t;
@@ -422,7 +417,7 @@
 	kfree(ipcd);
 }
 
-static int ipcomp_init_state(struct xfrm_state *x, void *args)
+static int ipcomp_init_state(struct xfrm_state *x)
 {
 	int err;
 	struct ipcomp_data *ipcd;
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index e21c049..e4f809a 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1350,6 +1350,7 @@
 			     */
 			    read_lock(&mrt_lock);
 			    if (mroute_socket) {
+				    nf_reset(skb);
 				    raw_rcv(mroute_socket, skb);
 				    read_unlock(&mrt_lock);
 				    return 0;
diff --git a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
index 218d970..12a82e9 100644
--- a/net/ipv4/ipvs/ip_vs_ctl.c
+++ b/net/ipv4/ipvs/ip_vs_ctl.c
@@ -2059,7 +2059,7 @@
 	dst->addr = src->addr;
 	dst->port = src->port;
 	dst->fwmark = src->fwmark;
-	strcpy(dst->sched_name, src->scheduler->name);
+	strlcpy(dst->sched_name, src->scheduler->name, sizeof(dst->sched_name));
 	dst->flags = src->flags;
 	dst->timeout = src->timeout / HZ;
 	dst->netmask = src->netmask;
@@ -2080,6 +2080,7 @@
 		list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) {
 			if (count >= get->num_services)
 				goto out;
+			memset(&entry, 0, sizeof(entry));
 			ip_vs_copy_service(&entry, svc);
 			if (copy_to_user(&uptr->entrytable[count],
 					 &entry, sizeof(entry))) {
@@ -2094,6 +2095,7 @@
 		list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) {
 			if (count >= get->num_services)
 				goto out;
+			memset(&entry, 0, sizeof(entry));
 			ip_vs_copy_service(&entry, svc);
 			if (copy_to_user(&uptr->entrytable[count],
 					 &entry, sizeof(entry))) {
@@ -2304,12 +2306,12 @@
 		memset(&d, 0, sizeof(d));
 		if (ip_vs_sync_state & IP_VS_STATE_MASTER) {
 			d[0].state = IP_VS_STATE_MASTER;
-			strcpy(d[0].mcast_ifn, ip_vs_master_mcast_ifn);
+			strlcpy(d[0].mcast_ifn, ip_vs_master_mcast_ifn, sizeof(d[0].mcast_ifn));
 			d[0].syncid = ip_vs_master_syncid;
 		}
 		if (ip_vs_sync_state & IP_VS_STATE_BACKUP) {
 			d[1].state = IP_VS_STATE_BACKUP;
-			strcpy(d[1].mcast_ifn, ip_vs_backup_mcast_ifn);
+			strlcpy(d[1].mcast_ifn, ip_vs_backup_mcast_ifn, sizeof(d[1].mcast_ifn));
 			d[1].syncid = ip_vs_backup_syncid;
 		}
 		if (copy_to_user(user, &d, sizeof(d)) != 0)
diff --git a/net/ipv4/ipvs/ip_vs_sync.c b/net/ipv4/ipvs/ip_vs_sync.c
index 25c4795..574d1f5 100644
--- a/net/ipv4/ipvs/ip_vs_sync.c
+++ b/net/ipv4/ipvs/ip_vs_sync.c
@@ -839,10 +839,10 @@
 
 	ip_vs_sync_state |= state;
 	if (state == IP_VS_STATE_MASTER) {
-		strcpy(ip_vs_master_mcast_ifn, mcast_ifn);
+		strlcpy(ip_vs_master_mcast_ifn, mcast_ifn, sizeof(ip_vs_master_mcast_ifn));
 		ip_vs_master_syncid = syncid;
 	} else {
-		strcpy(ip_vs_backup_mcast_ifn, mcast_ifn);
+		strlcpy(ip_vs_backup_mcast_ifn, mcast_ifn, sizeof(ip_vs_backup_mcast_ifn));
 		ip_vs_backup_syncid = syncid;
 	}
 
diff --git a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c
index de21da0..a8512a3 100644
--- a/net/ipv4/ipvs/ip_vs_xmit.c
+++ b/net/ipv4/ipvs/ip_vs_xmit.c
@@ -127,7 +127,6 @@
 
 #define IP_VS_XMIT(skb, rt)				\
 do {							\
-	nf_reset_debug(skb);				\
 	(skb)->nfcache |= NFC_IPVS_PROPERTY;		\
 	(skb)->ip_summed = CHECKSUM_NONE;		\
 	NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, (skb), NULL,	\
diff --git a/net/ipv4/multipath_drr.c b/net/ipv4/multipath_drr.c
index cf2e6bc..c9cf872 100644
--- a/net/ipv4/multipath_drr.c
+++ b/net/ipv4/multipath_drr.c
@@ -31,6 +31,7 @@
 #include <linux/igmp.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/module.h>
 #include <linux/mroute.h>
 #include <linux/init.h>
 #include <net/ip.h>
@@ -247,3 +248,4 @@
 
 module_init(drr_init);
 module_exit(drr_exit);
+MODULE_LICENSE("GPL");
diff --git a/net/ipv4/multipath_random.c b/net/ipv4/multipath_random.c
index 805a16e..5249dbe 100644
--- a/net/ipv4/multipath_random.c
+++ b/net/ipv4/multipath_random.c
@@ -31,6 +31,7 @@
 #include <linux/igmp.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/module.h>
 #include <linux/mroute.h>
 #include <linux/init.h>
 #include <net/ip.h>
@@ -126,3 +127,4 @@
 
 module_init(random_init);
 module_exit(random_exit);
+MODULE_LICENSE("GPL");
diff --git a/net/ipv4/multipath_rr.c b/net/ipv4/multipath_rr.c
index 061b6b2..b6cd287 100644
--- a/net/ipv4/multipath_rr.c
+++ b/net/ipv4/multipath_rr.c
@@ -31,6 +31,7 @@
 #include <linux/igmp.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/module.h>
 #include <linux/mroute.h>
 #include <linux/init.h>
 #include <net/ip.h>
@@ -93,3 +94,4 @@
 
 module_init(rr_init);
 module_exit(rr_exit);
+MODULE_LICENSE("GPL");
diff --git a/net/ipv4/multipath_wrandom.c b/net/ipv4/multipath_wrandom.c
index c3d2ca1..bd7d75b 100644
--- a/net/ipv4/multipath_wrandom.c
+++ b/net/ipv4/multipath_wrandom.c
@@ -31,6 +31,7 @@
 #include <linux/igmp.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/module.h>
 #include <linux/mroute.h>
 #include <linux/init.h>
 #include <net/ip.h>
@@ -342,3 +343,4 @@
 
 module_init(wrandom_init);
 module_exit(wrandom_exit);
+MODULE_LICENSE("GPL");
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index df79f5e..fa16342 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -60,7 +60,6 @@
 
 #define ASSERT_READ_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0)
 #define ASSERT_WRITE_LOCK(x) ARP_NF_ASSERT(down_trylock(&arpt_mutex) != 0)
-#include <linux/netfilter_ipv4/lockhelp.h>
 #include <linux/netfilter_ipv4/listhelp.h>
 
 struct arpt_table_info {
diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c
index 3dbddd0..a78a320 100644
--- a/net/ipv4/netfilter/ip_conntrack_amanda.c
+++ b/net/ipv4/netfilter/ip_conntrack_amanda.c
@@ -26,7 +26,6 @@
 #include <net/checksum.h>
 #include <net/udp.h>
 
-#include <linux/netfilter_ipv4/lockhelp.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
 
@@ -42,7 +41,7 @@
 
 /* This is slow, but it's simple. --RR */
 static char amanda_buffer[65536];
-static DECLARE_LOCK(amanda_buffer_lock);
+static DEFINE_SPINLOCK(amanda_buffer_lock);
 
 unsigned int (*ip_nat_amanda_hook)(struct sk_buff **pskb,
 				   enum ip_conntrack_info ctinfo,
@@ -76,7 +75,7 @@
 		return NF_ACCEPT;
 	}
 
-	LOCK_BH(&amanda_buffer_lock);
+	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;
@@ -134,7 +133,7 @@
 	}
 
 out:
-	UNLOCK_BH(&amanda_buffer_lock);
+	spin_unlock_bh(&amanda_buffer_lock);
 	return ret;
 }
 
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index 09e8246..4b78ebe 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/net/ipv4/netfilter/ip_conntrack_core.c
@@ -38,10 +38,10 @@
 #include <linux/percpu.h>
 #include <linux/moduleparam.h>
 
-/* This rwlock protects the main hash table, protocol/helper/expected
+/* ip_conntrack_lock protects the main hash table, protocol/helper/expected
    registrations, conntrack timers*/
-#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock)
-#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock)
+#define ASSERT_READ_LOCK(x)
+#define ASSERT_WRITE_LOCK(x)
 
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
@@ -57,7 +57,7 @@
 #define DEBUGP(format, args...)
 #endif
 
-DECLARE_RWLOCK(ip_conntrack_lock);
+DEFINE_RWLOCK(ip_conntrack_lock);
 
 /* ip_conntrack_standalone needs this */
 atomic_t ip_conntrack_count = ATOMIC_INIT(0);
@@ -147,7 +147,7 @@
 
 static void unlink_expect(struct ip_conntrack_expect *exp)
 {
-	MUST_BE_WRITE_LOCKED(&ip_conntrack_lock);
+	ASSERT_WRITE_LOCK(&ip_conntrack_lock);
 	list_del(&exp->list);
 	/* Logically in destroy_expect, but we hold the lock here. */
 	exp->master->expecting--;
@@ -157,9 +157,9 @@
 {
 	struct ip_conntrack_expect *exp = (void *)ul_expect;
 
-	WRITE_LOCK(&ip_conntrack_lock);
+	write_lock_bh(&ip_conntrack_lock);
 	unlink_expect(exp);
-	WRITE_UNLOCK(&ip_conntrack_lock);
+	write_unlock_bh(&ip_conntrack_lock);
 	destroy_expect(exp);
 }
 
@@ -209,7 +209,7 @@
 	unsigned int ho, hr;
 	
 	DEBUGP("clean_from_lists(%p)\n", ct);
-	MUST_BE_WRITE_LOCKED(&ip_conntrack_lock);
+	ASSERT_WRITE_LOCK(&ip_conntrack_lock);
 
 	ho = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
 	hr = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
@@ -240,7 +240,7 @@
 	if (ip_conntrack_destroyed)
 		ip_conntrack_destroyed(ct);
 
-	WRITE_LOCK(&ip_conntrack_lock);
+	write_lock_bh(&ip_conntrack_lock);
 	/* Expectations will have been removed in clean_from_lists,
 	 * except TFTP can create an expectation on the first packet,
 	 * before connection is in the list, so we need to clean here,
@@ -254,7 +254,7 @@
 	}
 
 	CONNTRACK_STAT_INC(delete);
-	WRITE_UNLOCK(&ip_conntrack_lock);
+	write_unlock_bh(&ip_conntrack_lock);
 
 	if (ct->master)
 		ip_conntrack_put(ct->master);
@@ -268,12 +268,12 @@
 {
 	struct ip_conntrack *ct = (void *)ul_conntrack;
 
-	WRITE_LOCK(&ip_conntrack_lock);
+	write_lock_bh(&ip_conntrack_lock);
 	/* Inside lock so preempt is disabled on module removal path.
 	 * Otherwise we can get spurious warnings. */
 	CONNTRACK_STAT_INC(delete_list);
 	clean_from_lists(ct);
-	WRITE_UNLOCK(&ip_conntrack_lock);
+	write_unlock_bh(&ip_conntrack_lock);
 	ip_conntrack_put(ct);
 }
 
@@ -282,7 +282,7 @@
 		    const struct ip_conntrack_tuple *tuple,
 		    const struct ip_conntrack *ignored_conntrack)
 {
-	MUST_BE_READ_LOCKED(&ip_conntrack_lock);
+	ASSERT_READ_LOCK(&ip_conntrack_lock);
 	return tuplehash_to_ctrack(i) != ignored_conntrack
 		&& ip_ct_tuple_equal(tuple, &i->tuple);
 }
@@ -294,7 +294,7 @@
 	struct ip_conntrack_tuple_hash *h;
 	unsigned int hash = hash_conntrack(tuple);
 
-	MUST_BE_READ_LOCKED(&ip_conntrack_lock);
+	ASSERT_READ_LOCK(&ip_conntrack_lock);
 	list_for_each_entry(h, &ip_conntrack_hash[hash], list) {
 		if (conntrack_tuple_cmp(h, tuple, ignored_conntrack)) {
 			CONNTRACK_STAT_INC(found);
@@ -313,11 +313,11 @@
 {
 	struct ip_conntrack_tuple_hash *h;
 
-	READ_LOCK(&ip_conntrack_lock);
+	read_lock_bh(&ip_conntrack_lock);
 	h = __ip_conntrack_find(tuple, ignored_conntrack);
 	if (h)
 		atomic_inc(&tuplehash_to_ctrack(h)->ct_general.use);
-	READ_UNLOCK(&ip_conntrack_lock);
+	read_unlock_bh(&ip_conntrack_lock);
 
 	return h;
 }
@@ -352,7 +352,7 @@
 	IP_NF_ASSERT(!is_confirmed(ct));
 	DEBUGP("Confirming conntrack %p\n", ct);
 
-	WRITE_LOCK(&ip_conntrack_lock);
+	write_lock_bh(&ip_conntrack_lock);
 
 	/* See if there's one in the list already, including reverse:
            NAT could have grabbed it without realizing, since we're
@@ -380,12 +380,12 @@
 		atomic_inc(&ct->ct_general.use);
 		set_bit(IPS_CONFIRMED_BIT, &ct->status);
 		CONNTRACK_STAT_INC(insert);
-		WRITE_UNLOCK(&ip_conntrack_lock);
+		write_unlock_bh(&ip_conntrack_lock);
 		return NF_ACCEPT;
 	}
 
 	CONNTRACK_STAT_INC(insert_failed);
-	WRITE_UNLOCK(&ip_conntrack_lock);
+	write_unlock_bh(&ip_conntrack_lock);
 
 	return NF_DROP;
 }
@@ -398,9 +398,9 @@
 {
 	struct ip_conntrack_tuple_hash *h;
 
-	READ_LOCK(&ip_conntrack_lock);
+	read_lock_bh(&ip_conntrack_lock);
 	h = __ip_conntrack_find(tuple, ignored_conntrack);
-	READ_UNLOCK(&ip_conntrack_lock);
+	read_unlock_bh(&ip_conntrack_lock);
 
 	return h != NULL;
 }
@@ -419,13 +419,13 @@
 	struct ip_conntrack *ct = NULL;
 	int dropped = 0;
 
-	READ_LOCK(&ip_conntrack_lock);
+	read_lock_bh(&ip_conntrack_lock);
 	h = LIST_FIND_B(chain, unreplied, struct ip_conntrack_tuple_hash *);
 	if (h) {
 		ct = tuplehash_to_ctrack(h);
 		atomic_inc(&ct->ct_general.use);
 	}
-	READ_UNLOCK(&ip_conntrack_lock);
+	read_unlock_bh(&ip_conntrack_lock);
 
 	if (!ct)
 		return dropped;
@@ -508,7 +508,7 @@
 	conntrack->timeout.data = (unsigned long)conntrack;
 	conntrack->timeout.function = death_by_timeout;
 
-	WRITE_LOCK(&ip_conntrack_lock);
+	write_lock_bh(&ip_conntrack_lock);
 	exp = find_expectation(tuple);
 
 	if (exp) {
@@ -532,7 +532,7 @@
 	list_add(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list, &unconfirmed);
 
 	atomic_inc(&ip_conntrack_count);
-	WRITE_UNLOCK(&ip_conntrack_lock);
+	write_unlock_bh(&ip_conntrack_lock);
 
 	if (exp) {
 		if (exp->expectfn)
@@ -723,17 +723,17 @@
 {
 	struct ip_conntrack_expect *i;
 
-	WRITE_LOCK(&ip_conntrack_lock);
+	write_lock_bh(&ip_conntrack_lock);
 	/* choose the the oldest expectation to evict */
 	list_for_each_entry_reverse(i, &ip_conntrack_expect_list, list) {
 		if (expect_matches(i, exp) && del_timer(&i->timeout)) {
 			unlink_expect(i);
-			WRITE_UNLOCK(&ip_conntrack_lock);
+			write_unlock_bh(&ip_conntrack_lock);
 			destroy_expect(i);
 			return;
 		}
 	}
-	WRITE_UNLOCK(&ip_conntrack_lock);
+	write_unlock_bh(&ip_conntrack_lock);
 }
 
 struct ip_conntrack_expect *ip_conntrack_expect_alloc(void)
@@ -760,15 +760,11 @@
 	exp->master->expecting++;
 	list_add(&exp->list, &ip_conntrack_expect_list);
 
-	if (exp->master->helper->timeout) {
-		init_timer(&exp->timeout);
-		exp->timeout.data = (unsigned long)exp;
-		exp->timeout.function = expectation_timed_out;
-		exp->timeout.expires
-			= jiffies + exp->master->helper->timeout * HZ;
-		add_timer(&exp->timeout);
-	} else
-		exp->timeout.function = NULL;
+	init_timer(&exp->timeout);
+	exp->timeout.data = (unsigned long)exp;
+	exp->timeout.function = expectation_timed_out;
+	exp->timeout.expires = jiffies + exp->master->helper->timeout * HZ;
+	add_timer(&exp->timeout);
 
 	CONNTRACK_STAT_INC(expect_create);
 }
@@ -808,7 +804,7 @@
 	DEBUGP("tuple: "); DUMP_TUPLE(&expect->tuple);
 	DEBUGP("mask:  "); DUMP_TUPLE(&expect->mask);
 
-	WRITE_LOCK(&ip_conntrack_lock);
+	write_lock_bh(&ip_conntrack_lock);
 	list_for_each_entry(i, &ip_conntrack_expect_list, list) {
 		if (expect_matches(i, expect)) {
 			/* Refresh timer: if it's dying, ignore.. */
@@ -832,7 +828,7 @@
 	ip_conntrack_expect_insert(expect);
 	ret = 0;
 out:
-	WRITE_UNLOCK(&ip_conntrack_lock);
+	write_unlock_bh(&ip_conntrack_lock);
  	return ret;
 }
 
@@ -841,7 +837,7 @@
 void ip_conntrack_alter_reply(struct ip_conntrack *conntrack,
 			      const struct ip_conntrack_tuple *newreply)
 {
-	WRITE_LOCK(&ip_conntrack_lock);
+	write_lock_bh(&ip_conntrack_lock);
 	/* Should be unconfirmed, so not in hash table yet */
 	IP_NF_ASSERT(!is_confirmed(conntrack));
 
@@ -851,15 +847,15 @@
 	conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = *newreply;
 	if (!conntrack->master && conntrack->expecting == 0)
 		conntrack->helper = ip_ct_find_helper(newreply);
-	WRITE_UNLOCK(&ip_conntrack_lock);
+	write_unlock_bh(&ip_conntrack_lock);
 }
 
 int ip_conntrack_helper_register(struct ip_conntrack_helper *me)
 {
 	BUG_ON(me->timeout == 0);
-	WRITE_LOCK(&ip_conntrack_lock);
+	write_lock_bh(&ip_conntrack_lock);
 	list_prepend(&helpers, me);
-	WRITE_UNLOCK(&ip_conntrack_lock);
+	write_unlock_bh(&ip_conntrack_lock);
 
 	return 0;
 }
@@ -878,7 +874,7 @@
 	struct ip_conntrack_expect *exp, *tmp;
 
 	/* Need write lock here, to delete helper. */
-	WRITE_LOCK(&ip_conntrack_lock);
+	write_lock_bh(&ip_conntrack_lock);
 	LIST_DELETE(&helpers, me);
 
 	/* Get rid of expectations */
@@ -893,7 +889,7 @@
 	for (i = 0; i < ip_conntrack_htable_size; i++)
 		LIST_FIND_W(&ip_conntrack_hash[i], unhelp,
 			    struct ip_conntrack_tuple_hash *, me);
-	WRITE_UNLOCK(&ip_conntrack_lock);
+	write_unlock_bh(&ip_conntrack_lock);
 
 	/* Someone could be still looking at the helper in a bh. */
 	synchronize_net();
@@ -925,14 +921,14 @@
 		ct->timeout.expires = extra_jiffies;
 		ct_add_counters(ct, ctinfo, skb);
 	} else {
-		WRITE_LOCK(&ip_conntrack_lock);
+		write_lock_bh(&ip_conntrack_lock);
 		/* Need del_timer for race avoidance (may already be dying). */
 		if (del_timer(&ct->timeout)) {
 			ct->timeout.expires = jiffies + extra_jiffies;
 			add_timer(&ct->timeout);
 		}
 		ct_add_counters(ct, ctinfo, skb);
-		WRITE_UNLOCK(&ip_conntrack_lock);
+		write_unlock_bh(&ip_conntrack_lock);
 	}
 }
 
@@ -940,10 +936,6 @@
 struct sk_buff *
 ip_ct_gather_frags(struct sk_buff *skb, u_int32_t user)
 {
-#ifdef CONFIG_NETFILTER_DEBUG
-	unsigned int olddebug = skb->nf_debug;
-#endif
-
 	skb_orphan(skb);
 
 	local_bh_disable(); 
@@ -953,12 +945,7 @@
 	if (skb) {
 		ip_send_check(skb->nh.iph);
 		skb->nfcache |= NFC_ALTERED;
-#ifdef CONFIG_NETFILTER_DEBUG
-		/* Packet path as if nothing had happened. */
-		skb->nf_debug = olddebug;
-#endif
 	}
-
 	return skb;
 }
 
@@ -997,7 +984,7 @@
 {
 	struct ip_conntrack_tuple_hash *h = NULL;
 
-	WRITE_LOCK(&ip_conntrack_lock);
+	write_lock_bh(&ip_conntrack_lock);
 	for (; *bucket < ip_conntrack_htable_size; (*bucket)++) {
 		h = LIST_FIND_W(&ip_conntrack_hash[*bucket], do_iter,
 				struct ip_conntrack_tuple_hash *, iter, data);
@@ -1009,7 +996,7 @@
 				struct ip_conntrack_tuple_hash *, iter, data);
 	if (h)
 		atomic_inc(&tuplehash_to_ctrack(h)->ct_general.use);
-	WRITE_UNLOCK(&ip_conntrack_lock);
+	write_unlock_bh(&ip_conntrack_lock);
 
 	return h;
 }
@@ -1201,14 +1188,14 @@
 	}
 
 	/* Don't NEED lock here, but good form anyway. */
-	WRITE_LOCK(&ip_conntrack_lock);
+	write_lock_bh(&ip_conntrack_lock);
 	for (i = 0; i < MAX_IP_CT_PROTO; i++)
 		ip_ct_protos[i] = &ip_conntrack_generic_protocol;
 	/* Sew in builtin protocols. */
 	ip_ct_protos[IPPROTO_TCP] = &ip_conntrack_protocol_tcp;
 	ip_ct_protos[IPPROTO_UDP] = &ip_conntrack_protocol_udp;
 	ip_ct_protos[IPPROTO_ICMP] = &ip_conntrack_protocol_icmp;
-	WRITE_UNLOCK(&ip_conntrack_lock);
+	write_unlock_bh(&ip_conntrack_lock);
 
 	for (i = 0; i < ip_conntrack_htable_size; i++)
 		INIT_LIST_HEAD(&ip_conntrack_hash[i]);
diff --git a/net/ipv4/netfilter/ip_conntrack_ftp.c b/net/ipv4/netfilter/ip_conntrack_ftp.c
index dd86503..fea6dd2 100644
--- a/net/ipv4/netfilter/ip_conntrack_ftp.c
+++ b/net/ipv4/netfilter/ip_conntrack_ftp.c
@@ -16,7 +16,6 @@
 #include <net/checksum.h>
 #include <net/tcp.h>
 
-#include <linux/netfilter_ipv4/lockhelp.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
 #include <linux/moduleparam.h>
@@ -28,7 +27,7 @@
 /* This is slow, but it's simple. --RR */
 static char ftp_buffer[65536];
 
-static DECLARE_LOCK(ip_ftp_lock);
+static DEFINE_SPINLOCK(ip_ftp_lock);
 
 #define MAX_PORTS 8
 static int ports[MAX_PORTS];
@@ -319,7 +318,7 @@
 	}
 	datalen = (*pskb)->len - dataoff;
 
-	LOCK_BH(&ip_ftp_lock);
+	spin_lock_bh(&ip_ftp_lock);
 	fb_ptr = skb_header_pointer(*pskb, dataoff,
 				    (*pskb)->len - dataoff, ftp_buffer);
 	BUG_ON(fb_ptr == NULL);
@@ -442,7 +441,7 @@
 	if (ends_in_nl)
 		update_nl_seq(seq, ct_ftp_info,dir);
  out:
-	UNLOCK_BH(&ip_ftp_lock);
+	spin_unlock_bh(&ip_ftp_lock);
 	return ret;
 }
 
diff --git a/net/ipv4/netfilter/ip_conntrack_irc.c b/net/ipv4/netfilter/ip_conntrack_irc.c
index 33cc734..cd98772 100644
--- a/net/ipv4/netfilter/ip_conntrack_irc.c
+++ b/net/ipv4/netfilter/ip_conntrack_irc.c
@@ -29,7 +29,6 @@
 #include <net/checksum.h>
 #include <net/tcp.h>
 
-#include <linux/netfilter_ipv4/lockhelp.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
 #include <linux/netfilter_ipv4/ip_conntrack_irc.h>
 #include <linux/moduleparam.h>
@@ -41,7 +40,7 @@
 static unsigned int dcc_timeout = 300;
 /* This is slow, but it's simple. --RR */
 static char irc_buffer[65536];
-static DECLARE_LOCK(irc_buffer_lock);
+static DEFINE_SPINLOCK(irc_buffer_lock);
 
 unsigned int (*ip_nat_irc_hook)(struct sk_buff **pskb,
 				enum ip_conntrack_info ctinfo,
@@ -141,7 +140,7 @@
 	if (dataoff >= (*pskb)->len)
 		return NF_ACCEPT;
 
-	LOCK_BH(&irc_buffer_lock);
+	spin_lock_bh(&irc_buffer_lock);
 	ib_ptr = skb_header_pointer(*pskb, dataoff,
 				    (*pskb)->len - dataoff, irc_buffer);
 	BUG_ON(ib_ptr == NULL);
@@ -237,7 +236,7 @@
 	} /* while data < ... */
 
  out:
-	UNLOCK_BH(&irc_buffer_lock);
+	spin_unlock_bh(&irc_buffer_lock);
 	return ret;
 }
 
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
index ff8c34a..31d7539 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
@@ -26,7 +26,6 @@
 
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
-#include <linux/netfilter_ipv4/lockhelp.h>
 
 #if 0
 #define DEBUGP(format, ...) printk(format, ## __VA_ARGS__)
@@ -35,7 +34,7 @@
 #endif
 
 /* Protects conntrack->proto.sctp */
-static DECLARE_RWLOCK(sctp_lock);
+static DEFINE_RWLOCK(sctp_lock);
 
 /* FIXME: Examine ipfilter's timeouts and conntrack transitions more
    closely.  They're more complex. --RR 
@@ -199,9 +198,9 @@
 	DEBUGP(__FUNCTION__);
 	DEBUGP("\n");
 
-	READ_LOCK(&sctp_lock);
+	read_lock_bh(&sctp_lock);
 	state = conntrack->proto.sctp.state;
-	READ_UNLOCK(&sctp_lock);
+	read_unlock_bh(&sctp_lock);
 
 	return seq_printf(s, "%s ", sctp_conntrack_names[state]);
 }
@@ -343,13 +342,13 @@
 
 	oldsctpstate = newconntrack = SCTP_CONNTRACK_MAX;
 	for_each_sctp_chunk (skb, sch, _sch, offset, count) {
-		WRITE_LOCK(&sctp_lock);
+		write_lock_bh(&sctp_lock);
 
 		/* Special cases of Verification tag check (Sec 8.5.1) */
 		if (sch->type == SCTP_CID_INIT) {
 			/* Sec 8.5.1 (A) */
 			if (sh->vtag != 0) {
-				WRITE_UNLOCK(&sctp_lock);
+				write_unlock_bh(&sctp_lock);
 				return -1;
 			}
 		} else if (sch->type == SCTP_CID_ABORT) {
@@ -357,7 +356,7 @@
 			if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])
 				&& !(sh->vtag == conntrack->proto.sctp.vtag
 							[1 - CTINFO2DIR(ctinfo)])) {
-				WRITE_UNLOCK(&sctp_lock);
+				write_unlock_bh(&sctp_lock);
 				return -1;
 			}
 		} else if (sch->type == SCTP_CID_SHUTDOWN_COMPLETE) {
@@ -366,13 +365,13 @@
 				&& !(sh->vtag == conntrack->proto.sctp.vtag
 							[1 - CTINFO2DIR(ctinfo)] 
 					&& (sch->flags & 1))) {
-				WRITE_UNLOCK(&sctp_lock);
+				write_unlock_bh(&sctp_lock);
 				return -1;
 			}
 		} else if (sch->type == SCTP_CID_COOKIE_ECHO) {
 			/* Sec 8.5.1 (D) */
 			if (!(sh->vtag == conntrack->proto.sctp.vtag[CTINFO2DIR(ctinfo)])) {
-				WRITE_UNLOCK(&sctp_lock);
+				write_unlock_bh(&sctp_lock);
 				return -1;
 			}
 		}
@@ -384,7 +383,7 @@
 		if (newconntrack == SCTP_CONNTRACK_MAX) {
 			DEBUGP("ip_conntrack_sctp: Invalid dir=%i ctype=%u conntrack=%u\n",
 			       CTINFO2DIR(ctinfo), sch->type, oldsctpstate);
-			WRITE_UNLOCK(&sctp_lock);
+			write_unlock_bh(&sctp_lock);
 			return -1;
 		}
 
@@ -396,7 +395,7 @@
 			ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
 			                        sizeof(_inithdr), &_inithdr);
 			if (ih == NULL) {
-					WRITE_UNLOCK(&sctp_lock);
+					write_unlock_bh(&sctp_lock);
 					return -1;
 			}
 			DEBUGP("Setting vtag %x for dir %d\n", 
@@ -405,7 +404,7 @@
 		}
 
 		conntrack->proto.sctp.state = newconntrack;
-		WRITE_UNLOCK(&sctp_lock);
+		write_unlock_bh(&sctp_lock);
 	}
 
 	ip_ct_refresh_acct(conntrack, ctinfo, skb, *sctp_timeouts[newconntrack]);
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
index 721ddbf..809dfed 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
@@ -36,7 +36,6 @@
 #include <linux/netfilter_ipv4.h>
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
-#include <linux/netfilter_ipv4/lockhelp.h>
 
 #if 0
 #define DEBUGP printk
@@ -46,7 +45,7 @@
 #endif
 
 /* Protects conntrack->proto.tcp */
-static DECLARE_RWLOCK(tcp_lock);
+static DEFINE_RWLOCK(tcp_lock);
 
 /* "Be conservative in what you do, 
     be liberal in what you accept from others." 
@@ -330,9 +329,9 @@
 {
 	enum tcp_conntrack state;
 
-	READ_LOCK(&tcp_lock);
+	read_lock_bh(&tcp_lock);
 	state = conntrack->proto.tcp.state;
-	READ_UNLOCK(&tcp_lock);
+	read_unlock_bh(&tcp_lock);
 
 	return seq_printf(s, "%s ", tcp_conntrack_names[state]);
 }
@@ -738,14 +737,14 @@
 
 	end = segment_seq_plus_len(ntohl(tcph->seq), skb->len, iph, tcph);
 	
-	WRITE_LOCK(&tcp_lock);
+	write_lock_bh(&tcp_lock);
 	/*
 	 * We have to worry for the ack in the reply packet only...
 	 */
 	if (after(end, conntrack->proto.tcp.seen[dir].td_end))
 		conntrack->proto.tcp.seen[dir].td_end = end;
 	conntrack->proto.tcp.last_end = end;
-	WRITE_UNLOCK(&tcp_lock);
+	write_unlock_bh(&tcp_lock);
 	DEBUGP("tcp_update: sender end=%u maxend=%u maxwin=%u scale=%i "
 	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
 		sender->td_end, sender->td_maxend, sender->td_maxwin,
@@ -857,7 +856,7 @@
 				sizeof(_tcph), &_tcph);
 	BUG_ON(th == NULL);
 	
-	WRITE_LOCK(&tcp_lock);
+	write_lock_bh(&tcp_lock);
 	old_state = conntrack->proto.tcp.state;
 	dir = CTINFO2DIR(ctinfo);
 	index = get_conntrack_index(th);
@@ -879,7 +878,7 @@
 			 * that the client cannot but retransmit its SYN and 
 			 * thus initiate a clean new session.
 			 */
-		    	WRITE_UNLOCK(&tcp_lock);
+		    	write_unlock_bh(&tcp_lock);
 			if (LOG_INVALID(IPPROTO_TCP))
 				nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
 					  "ip_ct_tcp: killing out of sync session ");
@@ -894,7 +893,7 @@
 		conntrack->proto.tcp.last_end = 
 		    segment_seq_plus_len(ntohl(th->seq), skb->len, iph, th);
 		
-		WRITE_UNLOCK(&tcp_lock);
+		write_unlock_bh(&tcp_lock);
 		if (LOG_INVALID(IPPROTO_TCP))
 			nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
 				  "ip_ct_tcp: invalid packet ignored ");
@@ -904,7 +903,7 @@
 		DEBUGP("ip_ct_tcp: Invalid dir=%i index=%u ostate=%u\n",
 		       dir, get_conntrack_index(th),
 		       old_state);
-		WRITE_UNLOCK(&tcp_lock);
+		write_unlock_bh(&tcp_lock);
 		if (LOG_INVALID(IPPROTO_TCP))
 			nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
 				  "ip_ct_tcp: invalid state ");
@@ -918,13 +917,13 @@
 		    	     conntrack->proto.tcp.seen[dir].td_end)) {	
 		    	/* Attempt to reopen a closed connection.
 		    	* Delete this connection and look up again. */
-		    	WRITE_UNLOCK(&tcp_lock);
+		    	write_unlock_bh(&tcp_lock);
 		    	if (del_timer(&conntrack->timeout))
 		    		conntrack->timeout.function((unsigned long)
 		    					    conntrack);
 		    	return -NF_REPEAT;
 		} else {
-			WRITE_UNLOCK(&tcp_lock);
+			write_unlock_bh(&tcp_lock);
 			if (LOG_INVALID(IPPROTO_TCP))
 				nf_log_packet(PF_INET, 0, skb, NULL, NULL,
 				              "ip_ct_tcp: invalid SYN");
@@ -949,7 +948,7 @@
 
 	if (!tcp_in_window(&conntrack->proto.tcp, dir, index, 
 			   skb, iph, th)) {
-		WRITE_UNLOCK(&tcp_lock);
+		write_unlock_bh(&tcp_lock);
 		return -NF_ACCEPT;
 	}
     in_window:
@@ -972,7 +971,7 @@
 	timeout = conntrack->proto.tcp.retrans >= ip_ct_tcp_max_retrans
 		  && *tcp_timeouts[new_state] > ip_ct_tcp_timeout_max_retrans
 		  ? ip_ct_tcp_timeout_max_retrans : *tcp_timeouts[new_state];
-	WRITE_UNLOCK(&tcp_lock);
+	write_unlock_bh(&tcp_lock);
 
 	if (!test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
 		/* If only reply is a RST, we can consider ourselves not to
diff --git a/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
index 5bc28a2..8c1eaba 100644
--- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c
+++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c
@@ -120,6 +120,7 @@
 	 * and moreover root might send raw packets.
 	 * FIXME: Source route IP option packets --RR */
 	if (hooknum == NF_IP_PRE_ROUTING
+	    && skb->ip_summed != CHECKSUM_UNNECESSARY
 	    && csum_tcpudp_magic(iph->saddr, iph->daddr, udplen, IPPROTO_UDP,
 			         skb->ip_summed == CHECKSUM_HW ? skb->csum
 			      	 : skb_checksum(skb, iph->ihl*4, udplen, 0))) {
diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
index 46ca45f..42dc951 100644
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -28,8 +28,8 @@
 #include <net/checksum.h>
 #include <net/ip.h>
 
-#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_conntrack_lock)
-#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_conntrack_lock)
+#define ASSERT_READ_LOCK(x)
+#define ASSERT_WRITE_LOCK(x)
 
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 #include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
@@ -119,7 +119,7 @@
 
 static void *ct_seq_start(struct seq_file *seq, loff_t *pos)
 {
-	READ_LOCK(&ip_conntrack_lock);
+	read_lock_bh(&ip_conntrack_lock);
 	return ct_get_idx(seq, *pos);
 }
 
@@ -131,7 +131,7 @@
   
 static void ct_seq_stop(struct seq_file *s, void *v)
 {
-	READ_UNLOCK(&ip_conntrack_lock);
+	read_unlock_bh(&ip_conntrack_lock);
 }
  
 static int ct_seq_show(struct seq_file *s, void *v)
@@ -140,7 +140,7 @@
 	const struct ip_conntrack *conntrack = tuplehash_to_ctrack(hash);
 	struct ip_conntrack_protocol *proto;
 
-	MUST_BE_READ_LOCKED(&ip_conntrack_lock);
+	ASSERT_READ_LOCK(&ip_conntrack_lock);
 	IP_NF_ASSERT(conntrack);
 
 	/* we only want to print DIR_ORIGINAL */
@@ -239,7 +239,7 @@
 
 	/* strange seq_file api calls stop even if we fail,
 	 * thus we need to grab lock since stop unlocks */
-	READ_LOCK(&ip_conntrack_lock);
+	read_lock_bh(&ip_conntrack_lock);
 
 	if (list_empty(e))
 		return NULL;
@@ -256,6 +256,7 @@
 {
  	struct list_head *e = v;
 
+	++*pos;
 	e = e->next;
 
 	if (e == &ip_conntrack_expect_list)
@@ -266,7 +267,7 @@
 
 static void exp_seq_stop(struct seq_file *s, void *v)
 {
-	READ_UNLOCK(&ip_conntrack_lock);
+	read_unlock_bh(&ip_conntrack_lock);
 }
 
 static int exp_seq_show(struct seq_file *s, void *v)
@@ -920,22 +921,22 @@
 {
 	int ret = 0;
 
-	WRITE_LOCK(&ip_conntrack_lock);
+	write_lock_bh(&ip_conntrack_lock);
 	if (ip_ct_protos[proto->proto] != &ip_conntrack_generic_protocol) {
 		ret = -EBUSY;
 		goto out;
 	}
 	ip_ct_protos[proto->proto] = proto;
  out:
-	WRITE_UNLOCK(&ip_conntrack_lock);
+	write_unlock_bh(&ip_conntrack_lock);
 	return ret;
 }
 
 void ip_conntrack_protocol_unregister(struct ip_conntrack_protocol *proto)
 {
-	WRITE_LOCK(&ip_conntrack_lock);
+	write_lock_bh(&ip_conntrack_lock);
 	ip_ct_protos[proto->proto] = &ip_conntrack_generic_protocol;
-	WRITE_UNLOCK(&ip_conntrack_lock);
+	write_unlock_bh(&ip_conntrack_lock);
 	
 	/* Somebody could be still looking at the proto in bh. */
 	synchronize_net();
diff --git a/net/ipv4/netfilter/ip_nat_core.c b/net/ipv4/netfilter/ip_nat_core.c
index 9fc6f93..739b6dd 100644
--- a/net/ipv4/netfilter/ip_nat_core.c
+++ b/net/ipv4/netfilter/ip_nat_core.c
@@ -22,8 +22,8 @@
 #include <linux/udp.h>
 #include <linux/jhash.h>
 
-#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock)
-#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock)
+#define ASSERT_READ_LOCK(x)
+#define ASSERT_WRITE_LOCK(x)
 
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 #include <linux/netfilter_ipv4/ip_conntrack_core.h>
@@ -41,7 +41,7 @@
 #define DEBUGP(format, args...)
 #endif
 
-DECLARE_RWLOCK(ip_nat_lock);
+DEFINE_RWLOCK(ip_nat_lock);
 
 /* Calculated at init based on memory size */
 static unsigned int ip_nat_htable_size;
@@ -65,9 +65,9 @@
 	if (!(conn->status & IPS_NAT_DONE_MASK))
 		return;
 
-	WRITE_LOCK(&ip_nat_lock);
+	write_lock_bh(&ip_nat_lock);
 	list_del(&conn->nat.info.bysource);
-	WRITE_UNLOCK(&ip_nat_lock);
+	write_unlock_bh(&ip_nat_lock);
 }
 
 /* We do checksum mangling, so if they were wrong before they're still
@@ -142,7 +142,7 @@
 	unsigned int h = hash_by_src(tuple);
 	struct ip_conntrack *ct;
 
-	READ_LOCK(&ip_nat_lock);
+	read_lock_bh(&ip_nat_lock);
 	list_for_each_entry(ct, &bysource[h], nat.info.bysource) {
 		if (same_src(ct, tuple)) {
 			/* Copy source part from reply tuple. */
@@ -151,12 +151,12 @@
 			result->dst = tuple->dst;
 
 			if (in_range(result, range)) {
-				READ_UNLOCK(&ip_nat_lock);
+				read_unlock_bh(&ip_nat_lock);
 				return 1;
 			}
 		}
 	}
-	READ_UNLOCK(&ip_nat_lock);
+	read_unlock_bh(&ip_nat_lock);
 	return 0;
 }
 
@@ -297,9 +297,9 @@
 		unsigned int srchash
 			= hash_by_src(&conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
 				      .tuple);
-		WRITE_LOCK(&ip_nat_lock);
+		write_lock_bh(&ip_nat_lock);
 		list_add(&info->bysource, &bysource[srchash]);
-		WRITE_UNLOCK(&ip_nat_lock);
+		write_unlock_bh(&ip_nat_lock);
 	}
 
 	/* It's done. */
@@ -474,23 +474,23 @@
 {
 	int ret = 0;
 
-	WRITE_LOCK(&ip_nat_lock);
+	write_lock_bh(&ip_nat_lock);
 	if (ip_nat_protos[proto->protonum] != &ip_nat_unknown_protocol) {
 		ret = -EBUSY;
 		goto out;
 	}
 	ip_nat_protos[proto->protonum] = proto;
  out:
-	WRITE_UNLOCK(&ip_nat_lock);
+	write_unlock_bh(&ip_nat_lock);
 	return ret;
 }
 
 /* Noone stores the protocol anywhere; simply delete it. */
 void ip_nat_protocol_unregister(struct ip_nat_protocol *proto)
 {
-	WRITE_LOCK(&ip_nat_lock);
+	write_lock_bh(&ip_nat_lock);
 	ip_nat_protos[proto->protonum] = &ip_nat_unknown_protocol;
-	WRITE_UNLOCK(&ip_nat_lock);
+	write_unlock_bh(&ip_nat_lock);
 
 	/* Someone could be still looking at the proto in a bh. */
 	synchronize_net();
@@ -509,13 +509,13 @@
 		return -ENOMEM;
 
 	/* Sew in builtin protocols. */
-	WRITE_LOCK(&ip_nat_lock);
+	write_lock_bh(&ip_nat_lock);
 	for (i = 0; i < MAX_IP_NAT_PROTO; i++)
 		ip_nat_protos[i] = &ip_nat_unknown_protocol;
 	ip_nat_protos[IPPROTO_TCP] = &ip_nat_protocol_tcp;
 	ip_nat_protos[IPPROTO_UDP] = &ip_nat_protocol_udp;
 	ip_nat_protos[IPPROTO_ICMP] = &ip_nat_protocol_icmp;
-	WRITE_UNLOCK(&ip_nat_lock);
+	write_unlock_bh(&ip_nat_lock);
 
 	for (i = 0; i < ip_nat_htable_size; i++) {
 		INIT_LIST_HEAD(&bysource[i]);
diff --git a/net/ipv4/netfilter/ip_nat_helper.c b/net/ipv4/netfilter/ip_nat_helper.c
index 1637b96..158f34f 100644
--- a/net/ipv4/netfilter/ip_nat_helper.c
+++ b/net/ipv4/netfilter/ip_nat_helper.c
@@ -28,8 +28,8 @@
 #include <net/tcp.h>
 #include <net/udp.h>
 
-#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock)
-#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock)
+#define ASSERT_READ_LOCK(x)
+#define ASSERT_WRITE_LOCK(x)
 
 #include <linux/netfilter_ipv4/ip_conntrack.h>
 #include <linux/netfilter_ipv4/ip_conntrack_helper.h>
@@ -47,7 +47,7 @@
 #define DUMP_OFFSET(x)
 #endif
 
-static DECLARE_LOCK(ip_nat_seqofs_lock);
+static DEFINE_SPINLOCK(ip_nat_seqofs_lock);
 
 /* Setup TCP sequence correction given this change at this sequence */
 static inline void 
@@ -70,7 +70,7 @@
 	DEBUGP("ip_nat_resize_packet: Seq_offset before: ");
 	DUMP_OFFSET(this_way);
 
-	LOCK_BH(&ip_nat_seqofs_lock);
+	spin_lock_bh(&ip_nat_seqofs_lock);
 
 	/* SYN adjust. If it's uninitialized, or this is after last
 	 * correction, record it: we don't handle more than one
@@ -82,7 +82,7 @@
 		    this_way->offset_before = this_way->offset_after;
 		    this_way->offset_after += sizediff;
 	}
-	UNLOCK_BH(&ip_nat_seqofs_lock);
+	spin_unlock_bh(&ip_nat_seqofs_lock);
 
 	DEBUGP("ip_nat_resize_packet: Seq_offset after: ");
 	DUMP_OFFSET(this_way);
@@ -142,9 +142,6 @@
 	/* Transfer socket to new skb. */
 	if ((*pskb)->sk)
 		skb_set_owner_w(nskb, (*pskb)->sk);
-#ifdef CONFIG_NETFILTER_DEBUG
-	nskb->nf_debug = (*pskb)->nf_debug;
-#endif
 	kfree_skb(*pskb);
 	*pskb = nskb;
 	return 1;
diff --git a/net/ipv4/netfilter/ip_nat_rule.c b/net/ipv4/netfilter/ip_nat_rule.c
index 581f097..60d70fa 100644
--- a/net/ipv4/netfilter/ip_nat_rule.c
+++ b/net/ipv4/netfilter/ip_nat_rule.c
@@ -19,8 +19,8 @@
 #include <net/route.h>
 #include <linux/bitops.h>
 
-#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock)
-#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock)
+#define ASSERT_READ_LOCK(x)
+#define ASSERT_WRITE_LOCK(x)
 
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ip_nat.h>
diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c
index 79f56f6..bc59d0d 100644
--- a/net/ipv4/netfilter/ip_nat_standalone.c
+++ b/net/ipv4/netfilter/ip_nat_standalone.c
@@ -31,8 +31,8 @@
 #include <net/checksum.h>
 #include <linux/spinlock.h>
 
-#define ASSERT_READ_LOCK(x) MUST_BE_READ_LOCKED(&ip_nat_lock)
-#define ASSERT_WRITE_LOCK(x) MUST_BE_WRITE_LOCKED(&ip_nat_lock)
+#define ASSERT_READ_LOCK(x)
+#define ASSERT_WRITE_LOCK(x)
 
 #include <linux/netfilter_ipv4/ip_nat.h>
 #include <linux/netfilter_ipv4/ip_nat_rule.h>
@@ -373,7 +373,6 @@
  cleanup_rule_init:
 	ip_nat_rule_cleanup();
  cleanup_nothing:
-	MUST_BE_READ_WRITE_UNLOCKED(&ip_nat_lock);
 	return ret;
 }
 
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 8a54f92..c88dfcd 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -67,7 +67,6 @@
 /* Must have mutex */
 #define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0)
 #define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ipt_mutex) != 0)
-#include <linux/netfilter_ipv4/lockhelp.h>
 #include <linux/netfilter_ipv4/listhelp.h>
 
 #if 0
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 0f12e3a..9cde8c6 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -29,7 +29,6 @@
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ipt_CLUSTERIP.h>
 #include <linux/netfilter_ipv4/ip_conntrack.h>
-#include <linux/netfilter_ipv4/lockhelp.h>
 
 #define CLUSTERIP_VERSION "0.6"
 
@@ -41,6 +40,8 @@
 #define DEBUGP
 #endif
 
+#define ASSERT_READ_LOCK(x)
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
 MODULE_DESCRIPTION("iptables target for CLUSTERIP");
@@ -67,7 +68,7 @@
 
 /* clusterip_lock protects the clusterip_configs list _AND_ the configurable
  * data within all structurses (num_local_nodes, local_nodes[]) */
-static DECLARE_RWLOCK(clusterip_lock);
+static DEFINE_RWLOCK(clusterip_lock);
 
 #ifdef CONFIG_PROC_FS
 static struct file_operations clusterip_proc_fops;
@@ -82,9 +83,9 @@
 static inline void
 clusterip_config_put(struct clusterip_config *c) {
 	if (atomic_dec_and_test(&c->refcount)) {
-		WRITE_LOCK(&clusterip_lock);
+		write_lock_bh(&clusterip_lock);
 		list_del(&c->list);
-		WRITE_UNLOCK(&clusterip_lock);
+		write_unlock_bh(&clusterip_lock);
 		dev_mc_delete(c->dev, c->clustermac, ETH_ALEN, 0);
 		dev_put(c->dev);
 		kfree(c);
@@ -97,7 +98,7 @@
 {
 	struct list_head *pos;
 
-	MUST_BE_READ_LOCKED(&clusterip_lock);
+	ASSERT_READ_LOCK(&clusterip_lock);
 	list_for_each(pos, &clusterip_configs) {
 		struct clusterip_config *c = list_entry(pos, 
 					struct clusterip_config, list);
@@ -114,14 +115,14 @@
 {
 	struct clusterip_config *c;
 
-	READ_LOCK(&clusterip_lock);
+	read_lock_bh(&clusterip_lock);
 	c = __clusterip_config_find(clusterip);
 	if (!c) {
-		READ_UNLOCK(&clusterip_lock);
+		read_unlock_bh(&clusterip_lock);
 		return NULL;
 	}
 	atomic_inc(&c->refcount);
-	READ_UNLOCK(&clusterip_lock);
+	read_unlock_bh(&clusterip_lock);
 
 	return c;
 }
@@ -160,9 +161,9 @@
 	c->pde->data = c;
 #endif
 
-	WRITE_LOCK(&clusterip_lock);
+	write_lock_bh(&clusterip_lock);
 	list_add(&c->list, &clusterip_configs);
-	WRITE_UNLOCK(&clusterip_lock);
+	write_unlock_bh(&clusterip_lock);
 
 	return c;
 }
@@ -172,25 +173,25 @@
 {
 	int i;
 
-	WRITE_LOCK(&clusterip_lock);
+	write_lock_bh(&clusterip_lock);
 
 	if (c->num_local_nodes >= CLUSTERIP_MAX_NODES
 	    || nodenum > CLUSTERIP_MAX_NODES) {
-		WRITE_UNLOCK(&clusterip_lock);
+		write_unlock_bh(&clusterip_lock);
 		return 1;
 	}
 
 	/* check if we alrady have this number in our array */
 	for (i = 0; i < c->num_local_nodes; i++) {
 		if (c->local_nodes[i] == nodenum) {
-			WRITE_UNLOCK(&clusterip_lock);
+			write_unlock_bh(&clusterip_lock);
 			return 1;
 		}
 	}
 
 	c->local_nodes[c->num_local_nodes++] = nodenum;
 
-	WRITE_UNLOCK(&clusterip_lock);
+	write_unlock_bh(&clusterip_lock);
 	return 0;
 }
 
@@ -199,10 +200,10 @@
 {
 	int i;
 
-	WRITE_LOCK(&clusterip_lock);
+	write_lock_bh(&clusterip_lock);
 
 	if (c->num_local_nodes <= 1 || nodenum > CLUSTERIP_MAX_NODES) {
-		WRITE_UNLOCK(&clusterip_lock);
+		write_unlock_bh(&clusterip_lock);
 		return 1;
 	}
 		
@@ -211,12 +212,12 @@
 			int size = sizeof(u_int16_t)*(c->num_local_nodes-(i+1));
 			memmove(&c->local_nodes[i], &c->local_nodes[i+1], size);
 			c->num_local_nodes--;
-			WRITE_UNLOCK(&clusterip_lock);
+			write_unlock_bh(&clusterip_lock);
 			return 0;
 		}
 	}
 
-	WRITE_UNLOCK(&clusterip_lock);
+	write_unlock_bh(&clusterip_lock);
 	return 1;
 }
 
@@ -286,21 +287,21 @@
 {
 	int i;
 
-	READ_LOCK(&clusterip_lock);
+	read_lock_bh(&clusterip_lock);
 
 	if (config->num_local_nodes == 0) {
-		READ_UNLOCK(&clusterip_lock);
+		read_unlock_bh(&clusterip_lock);
 		return 0;
 	}
 
 	for (i = 0; i < config->num_local_nodes; i++) {
 		if (config->local_nodes[i] == hash) {
-			READ_UNLOCK(&clusterip_lock);
+			read_unlock_bh(&clusterip_lock);
 			return 1;
 		}
 	}
 
-	READ_UNLOCK(&clusterip_lock);
+	read_unlock_bh(&clusterip_lock);
 
 	return 0;
 }
@@ -338,7 +339,7 @@
 	 * error messages (RELATED) and information requests (see below) */
 	if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP
 	    && (ctinfo == IP_CT_RELATED 
-		|| ctinfo == IP_CT_IS_REPLY+IP_CT_IS_REPLY))
+		|| ctinfo == IP_CT_RELATED+IP_CT_IS_REPLY))
 		return IPT_CONTINUE;
 
 	/* ip_conntrack_icmp guarantees us that we only have ICMP_ECHO, 
@@ -578,7 +579,7 @@
 	struct clusterip_config *c = pde->data;
 	unsigned int *nodeidx;
 
-	READ_LOCK(&clusterip_lock);
+	read_lock_bh(&clusterip_lock);
 	if (*pos >= c->num_local_nodes)
 		return NULL;
 
@@ -608,7 +609,7 @@
 {
 	kfree(v);
 
-	READ_UNLOCK(&clusterip_lock);
+	read_unlock_bh(&clusterip_lock);
 }
 
 static int clusterip_seq_show(struct seq_file *s, void *v)
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index 57e9f6c..91e7450 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -33,7 +33,7 @@
 #endif
 
 /* Lock protects masq region inside conntrack */
-static DECLARE_RWLOCK(masq_lock);
+static DEFINE_RWLOCK(masq_lock);
 
 /* FIXME: Multiple targets. --RR */
 static int
@@ -103,9 +103,9 @@
 		return NF_DROP;
 	}
 
-	WRITE_LOCK(&masq_lock);
+	write_lock_bh(&masq_lock);
 	ct->nat.masq_index = out->ifindex;
-	WRITE_UNLOCK(&masq_lock);
+	write_unlock_bh(&masq_lock);
 
 	/* Transfer from original range. */
 	newrange = ((struct ip_nat_range)
@@ -122,9 +122,9 @@
 {
 	int ret;
 
-	READ_LOCK(&masq_lock);
+	read_lock_bh(&masq_lock);
 	ret = (i->nat.masq_index == (int)(long)ifindex);
-	READ_UNLOCK(&masq_lock);
+	read_unlock_bh(&masq_lock);
 
 	return ret;
 }
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
index 266d649..9156964 100644
--- a/net/ipv4/netfilter/ipt_REJECT.c
+++ b/net/ipv4/netfilter/ipt_REJECT.c
@@ -104,10 +104,12 @@
 static void send_reset(struct sk_buff *oldskb, int hook)
 {
 	struct sk_buff *nskb;
+	struct iphdr *iph = oldskb->nh.iph;
 	struct tcphdr _otcph, *oth, *tcph;
 	struct rtable *rt;
 	u_int16_t tmp_port;
 	u_int32_t tmp_addr;
+	unsigned int tcplen;
 	int needs_ack;
 	int hh_len;
 
@@ -124,7 +126,16 @@
 	if (oth->rst)
 		return;
 
-	/* FIXME: Check checksum --RR */
+	/* Check checksum */
+	tcplen = oldskb->len - iph->ihl * 4;
+	if (((hook != NF_IP_LOCAL_IN && oldskb->ip_summed != CHECKSUM_HW) ||
+	     (hook == NF_IP_LOCAL_IN &&
+	      oldskb->ip_summed != CHECKSUM_UNNECESSARY)) &&
+	    csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP,
+	                      oldskb->ip_summed == CHECKSUM_HW ? oldskb->csum :
+	                      skb_checksum(oldskb, iph->ihl * 4, tcplen, 0)))
+		return;
+
 	if ((rt = route_reverse(oldskb, oth, hook)) == NULL)
 		return;
 
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 6f2cefb..52a0076 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -56,7 +56,6 @@
 #include <linux/netfilter.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ipt_ULOG.h>
-#include <linux/netfilter_ipv4/lockhelp.h>
 #include <net/sock.h>
 #include <linux/bitops.h>
 
@@ -99,8 +98,8 @@
 
 static ulog_buff_t ulog_buffers[ULOG_MAXNLGROUPS];	/* array of buffers */
 
-static struct sock *nflognl;	/* our socket */
-static DECLARE_LOCK(ulog_lock);	/* spinlock */
+static struct sock *nflognl;		/* our socket */
+static DEFINE_SPINLOCK(ulog_lock);	/* spinlock */
 
 /* send one ulog_buff_t to userspace */
 static void ulog_send(unsigned int nlgroupnum)
@@ -135,9 +134,9 @@
 
 	/* lock to protect against somebody modifying our structure
 	 * from ipt_ulog_target at the same time */
-	LOCK_BH(&ulog_lock);
+	spin_lock_bh(&ulog_lock);
 	ulog_send(data);
-	UNLOCK_BH(&ulog_lock);
+	spin_unlock_bh(&ulog_lock);
 }
 
 static struct sk_buff *ulog_alloc_skb(unsigned int size)
@@ -193,7 +192,7 @@
 
 	ub = &ulog_buffers[groupnum];
 	
-	LOCK_BH(&ulog_lock);
+	spin_lock_bh(&ulog_lock);
 
 	if (!ub->skb) {
 		if (!(ub->skb = ulog_alloc_skb(size)))
@@ -278,7 +277,7 @@
 		ulog_send(groupnum);
 	}
 
-	UNLOCK_BH(&ulog_lock);
+	spin_unlock_bh(&ulog_lock);
 
 	return;
 
@@ -288,7 +287,7 @@
 alloc_failure:
 	PRINTR("ipt_ULOG: Error building netlink message\n");
 
-	UNLOCK_BH(&ulog_lock);
+	spin_unlock_bh(&ulog_lock);
 }
 
 static unsigned int ipt_ulog_target(struct sk_buff **pskb,
diff --git a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c
index f1937190..564b49b 100644
--- a/net/ipv4/netfilter/ipt_hashlimit.c
+++ b/net/ipv4/netfilter/ipt_hashlimit.c
@@ -37,7 +37,6 @@
 
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ipt_hashlimit.h>
-#include <linux/netfilter_ipv4/lockhelp.h>
 
 /* FIXME: this is just for IP_NF_ASSERRT */
 #include <linux/netfilter_ipv4/ip_conntrack.h>
@@ -92,7 +91,7 @@
 	struct hlist_head hash[0];	/* hashtable itself */
 };
 
-static DECLARE_LOCK(hashlimit_lock);	/* protects htables list */
+static DEFINE_SPINLOCK(hashlimit_lock);	/* protects htables list */
 static DECLARE_MUTEX(hlimit_mutex);	/* additional checkentry protection */
 static HLIST_HEAD(hashlimit_htables);
 static kmem_cache_t *hashlimit_cachep;
@@ -233,9 +232,9 @@
 	hinfo->timer.function = htable_gc;
 	add_timer(&hinfo->timer);
 
-	LOCK_BH(&hashlimit_lock);
+	spin_lock_bh(&hashlimit_lock);
 	hlist_add_head(&hinfo->node, &hashlimit_htables);
-	UNLOCK_BH(&hashlimit_lock);
+	spin_unlock_bh(&hashlimit_lock);
 
 	return 0;
 }
@@ -301,15 +300,15 @@
 	struct ipt_hashlimit_htable *hinfo;
 	struct hlist_node *pos;
 
-	LOCK_BH(&hashlimit_lock);
+	spin_lock_bh(&hashlimit_lock);
 	hlist_for_each_entry(hinfo, pos, &hashlimit_htables, node) {
 		if (!strcmp(name, hinfo->pde->name)) {
 			atomic_inc(&hinfo->use);
-			UNLOCK_BH(&hashlimit_lock);
+			spin_unlock_bh(&hashlimit_lock);
 			return hinfo;
 		}
 	}
-	UNLOCK_BH(&hashlimit_lock);
+	spin_unlock_bh(&hashlimit_lock);
 
 	return NULL;
 }
@@ -317,9 +316,9 @@
 static void htable_put(struct ipt_hashlimit_htable *hinfo)
 {
 	if (atomic_dec_and_test(&hinfo->use)) {
-		LOCK_BH(&hashlimit_lock);
+		spin_lock_bh(&hashlimit_lock);
 		hlist_del(&hinfo->node);
-		UNLOCK_BH(&hashlimit_lock);
+		spin_unlock_bh(&hashlimit_lock);
 		htable_destroy(hinfo);
 	}
 }
diff --git a/net/ipv4/netfilter/ipt_helper.c b/net/ipv4/netfilter/ipt_helper.c
index 33fdf36..3e7dd01 100644
--- a/net/ipv4/netfilter/ipt_helper.c
+++ b/net/ipv4/netfilter/ipt_helper.c
@@ -53,7 +53,7 @@
 		return ret;
 	}
 
-	READ_LOCK(&ip_conntrack_lock);
+	read_lock_bh(&ip_conntrack_lock);
 	if (!ct->master->helper) {
 		DEBUGP("ipt_helper: master ct %p has no helper\n", 
 			exp->expectant);
@@ -69,7 +69,7 @@
 		ret ^= !strncmp(ct->master->helper->name, info->name, 
 		                strlen(ct->master->helper->name));
 out_unlock:
-	READ_UNLOCK(&ip_conntrack_lock);
+	read_unlock_bh(&ip_conntrack_lock);
 	return ret;
 }
 
diff --git a/net/ipv4/netfilter/ipt_recent.c b/net/ipv4/netfilter/ipt_recent.c
index 25ab9fa..2d44b07 100644
--- a/net/ipv4/netfilter/ipt_recent.c
+++ b/net/ipv4/netfilter/ipt_recent.c
@@ -223,7 +223,7 @@
 			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(u_int32_t));
+			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;
@@ -502,7 +502,7 @@
 		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(u_int32_t));
+		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;
@@ -631,7 +631,7 @@
 			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(u_int32_t));
+			memset(r_list[location].last_pkts,0,ip_pkt_list_tot*sizeof(unsigned long));
 			r_list[location].oldest_pkt = 0;
 			ans = !info->invert;
 		}
@@ -734,10 +734,10 @@
 	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(u_int32_t)*ip_pkt_list_tot*ip_list_tot);
+			sizeof(unsigned long)*ip_pkt_list_tot*ip_list_tot);
 #endif
 
-	hold = vmalloc(sizeof(u_int32_t)*ip_pkt_list_tot*ip_list_tot);
+	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
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 5b1ec58..d1835b1 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -259,7 +259,7 @@
 	return 0;
 }
 
-static int raw_send_hdrinc(struct sock *sk, void *from, int length,
+static int raw_send_hdrinc(struct sock *sk, void *from, size_t length,
 			struct rtable *rt, 
 			unsigned int flags)
 {
@@ -298,7 +298,7 @@
 		goto error_fault;
 
 	/* We don't modify invalid header */
-	if (length >= sizeof(*iph) && iph->ihl * 4 <= length) {
+	if (length >= sizeof(*iph) && iph->ihl * 4U <= length) {
 		if (!iph->saddr)
 			iph->saddr = rt->rt_src;
 		iph->check   = 0;
@@ -332,7 +332,7 @@
 	u8 __user *type = NULL;
 	u8 __user *code = NULL;
 	int probed = 0;
-	int i;
+	unsigned int i;
 
 	if (!msg->msg_iov)
 		return;
@@ -384,7 +384,7 @@
 	int err;
 
 	err = -EMSGSIZE;
-	if (len < 0 || len > 0xFFFF)
+	if (len > 0xFFFF)
 		goto out;
 
 	/*
@@ -514,7 +514,10 @@
 		kfree(ipc.opt);
 	ip_rt_put(rt);
 
-out:	return err < 0 ? err : len;
+out:
+	if (err < 0)
+		return err;
+	return len;
 
 do_confirm:
 	dst_confirm(&rt->u.dst);
@@ -610,7 +613,10 @@
 		copied = skb->len;
 done:
 	skb_free_datagram(sk, skb);
-out:	return err ? err : copied;
+out:
+	if (err)
+		return err;
+	return copied;
 }
 
 static int raw_init(struct sock *sk)
@@ -691,11 +697,11 @@
 			struct sk_buff *skb;
 			int amount = 0;
 
-			spin_lock_irq(&sk->sk_receive_queue.lock);
+			spin_lock_bh(&sk->sk_receive_queue.lock);
 			skb = skb_peek(&sk->sk_receive_queue);
 			if (skb != NULL)
 				amount = skb->len;
-			spin_unlock_irq(&sk->sk_receive_queue.lock);
+			spin_unlock_bh(&sk->sk_receive_queue.lock);
 			return put_user(amount, (int __user *)arg);
 		}
 
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index a682d28..80cf633 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1767,7 +1767,7 @@
 				       struct in_device *in_dev,
 				       u32 daddr, u32 saddr, u32 tos)
 {
-	struct rtable* rth;
+	struct rtable* rth = NULL;
 	int err;
 	unsigned hash;
 
@@ -1794,7 +1794,7 @@
 				   u32 daddr, u32 saddr, u32 tos)
 {
 #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED
-	struct rtable* rth;
+	struct rtable* rth = NULL;
 	unsigned char hop, hopcount, lasthop;
 	int err = -EINVAL;
 	unsigned int hash;
@@ -2239,7 +2239,7 @@
 					struct net_device *dev_out,
 					unsigned flags)
 {
-	struct rtable *rth;
+	struct rtable *rth = NULL;
 	int err = __mkroute_output(&rth, res, fl, oldflp, dev_out, flags);
 	unsigned hash;
 	if (err == 0) {
@@ -2267,7 +2267,7 @@
 	unsigned char hop;
 	unsigned hash;
 	int err = -EINVAL;
-	struct rtable *rth;
+	struct rtable *rth = NULL;
 
 	if (res->fi && res->fi->fib_nhs > 1) {
 		unsigned char hopcount = res->fi->fib_nhs;
@@ -2581,7 +2581,7 @@
 }
 
 static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
-			int nowait)
+			int nowait, unsigned int flags)
 {
 	struct rtable *rt = (struct rtable*)skb->dst;
 	struct rtmsg *r;
@@ -2591,9 +2591,8 @@
 #ifdef CONFIG_IP_MROUTE
 	struct rtattr *eptr;
 #endif
-	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*r));
+	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags);
 	r = NLMSG_DATA(nlh);
-	nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0;
 	r->rtm_family	 = AF_INET;
 	r->rtm_dst_len	= 32;
 	r->rtm_src_len	= 0;
@@ -2744,7 +2743,7 @@
 	NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
 
 	err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
-				RTM_NEWROUTE, 0);
+				RTM_NEWROUTE, 0, 0);
 	if (!err)
 		goto out_free;
 	if (err < 0) {
@@ -2781,8 +2780,8 @@
 				continue;
 			skb->dst = dst_clone(&rt->u.dst);
 			if (rt_fill_info(skb, NETLINK_CB(cb->skb).pid,
-					 cb->nlh->nlmsg_seq,
-					 RTM_NEWROUTE, 1) <= 0) {
+					 cb->nlh->nlmsg_seq, RTM_NEWROUTE, 
+					 1, NLM_F_MULTI) <= 0) {
 				dst_release(xchg(&skb->dst, NULL));
 				rcu_read_unlock_bh();
 				goto done;
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index e923d2f..72d0144 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -169,10 +169,10 @@
 	return mssind < NUM_MSS ? msstab[mssind] + 1 : 0;
 }
 
-extern struct or_calltable or_ipv4;
+extern struct request_sock_ops tcp_request_sock_ops;
 
 static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
-					   struct open_request *req,
+					   struct request_sock *req,
 					   struct dst_entry *dst)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
@@ -182,7 +182,7 @@
 	if (child)
 		tcp_acceptq_queue(sk, req, child);
 	else
-		tcp_openreq_free(req);
+		reqsk_free(req);
 
 	return child;
 }
@@ -190,10 +190,12 @@
 struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
 			     struct ip_options *opt)
 {
+	struct inet_request_sock *ireq;
+	struct tcp_request_sock *treq;
 	struct tcp_sock *tp = tcp_sk(sk);
 	__u32 cookie = ntohl(skb->h.th->ack_seq) - 1; 
 	struct sock *ret = sk;
-	struct open_request *req; 
+	struct request_sock *req; 
 	int mss; 
 	struct rtable *rt; 
 	__u8 rcv_wscale;
@@ -209,19 +211,20 @@
 
 	NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESRECV);
 
-	req = tcp_openreq_alloc();
 	ret = NULL;
+	req = reqsk_alloc(&tcp_request_sock_ops); /* for safety */
 	if (!req)
 		goto out;
 
-	req->rcv_isn		= htonl(skb->h.th->seq) - 1;
-	req->snt_isn		= cookie; 
+	ireq = inet_rsk(req);
+	treq = tcp_rsk(req);
+	treq->rcv_isn		= htonl(skb->h.th->seq) - 1;
+	treq->snt_isn		= cookie; 
 	req->mss		= mss;
- 	req->rmt_port		= skb->h.th->source;
-	req->af.v4_req.loc_addr = skb->nh.iph->daddr;
-	req->af.v4_req.rmt_addr = skb->nh.iph->saddr;
-	req->class		= &or_ipv4; /* for savety */
-	req->af.v4_req.opt	= NULL;
+ 	ireq->rmt_port		= skb->h.th->source;
+	ireq->loc_addr		= skb->nh.iph->daddr;
+	ireq->rmt_addr		= skb->nh.iph->saddr;
+	ireq->opt		= NULL;
 
 	/* We throwed the options of the initial SYN away, so we hope
 	 * the ACK carries the same options again (see RFC1122 4.2.3.8)
@@ -229,17 +232,15 @@
 	if (opt && opt->optlen) {
 		int opt_size = sizeof(struct ip_options) + opt->optlen;
 
-		req->af.v4_req.opt = kmalloc(opt_size, GFP_ATOMIC);
-		if (req->af.v4_req.opt) {
-			if (ip_options_echo(req->af.v4_req.opt, skb)) {
-				kfree(req->af.v4_req.opt);
-				req->af.v4_req.opt = NULL;
-			}
+		ireq->opt = kmalloc(opt_size, GFP_ATOMIC);
+		if (ireq->opt != NULL && ip_options_echo(ireq->opt, skb)) {
+			kfree(ireq->opt);
+			ireq->opt = NULL;
 		}
 	}
 
-	req->snd_wscale = req->rcv_wscale = req->tstamp_ok = 0;
-	req->wscale_ok	= req->sack_ok = 0; 
+	ireq->snd_wscale = ireq->rcv_wscale = ireq->tstamp_ok = 0;
+	ireq->wscale_ok	 = ireq->sack_ok = 0; 
 	req->expires	= 0UL; 
 	req->retrans	= 0; 
 	
@@ -253,15 +254,15 @@
 		struct flowi fl = { .nl_u = { .ip4_u =
 					      { .daddr = ((opt && opt->srr) ?
 							  opt->faddr :
-							  req->af.v4_req.rmt_addr),
-						.saddr = req->af.v4_req.loc_addr,
+							  ireq->rmt_addr),
+						.saddr = ireq->loc_addr,
 						.tos = RT_CONN_FLAGS(sk) } },
 				    .proto = IPPROTO_TCP,
 				    .uli_u = { .ports =
 					       { .sport = skb->h.th->dest,
 						 .dport = skb->h.th->source } } };
 		if (ip_route_output_key(&rt, &fl)) {
-			tcp_openreq_free(req);
+			reqsk_free(req);
 			goto out; 
 		}
 	}
@@ -272,7 +273,7 @@
 				  &req->rcv_wnd, &req->window_clamp, 
 				  0, &rcv_wscale);
 	/* BTW win scale with syncookies is 0 by definition */
-	req->rcv_wscale	  = rcv_wscale; 
+	ireq->rcv_wscale  = rcv_wscale; 
 
 	ret = get_cookie_sock(sk, skb, req, &rt->u.dst);
 out:	return ret;
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 3aafb29..e328945 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -23,6 +23,7 @@
 extern int sysctl_icmp_echo_ignore_all;
 extern int sysctl_icmp_echo_ignore_broadcasts;
 extern int sysctl_icmp_ignore_bogus_error_responses;
+extern int sysctl_icmp_errors_use_inbound_ifaddr;
 
 /* From ip_fragment.c */
 extern int sysctl_ipfrag_low_thresh;
@@ -117,6 +118,45 @@
 	return 1;
 }
 
+static int proc_tcp_congestion_control(ctl_table *ctl, int write, struct file * filp,
+				       void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+	char val[TCP_CA_NAME_MAX];
+	ctl_table tbl = {
+		.data = val,
+		.maxlen = TCP_CA_NAME_MAX,
+	};
+	int ret;
+
+	tcp_get_default_congestion_control(val);
+
+	ret = proc_dostring(&tbl, write, filp, buffer, lenp, ppos);
+	if (write && ret == 0)
+		ret = tcp_set_default_congestion_control(val);
+	return ret;
+}
+
+int sysctl_tcp_congestion_control(ctl_table *table, int __user *name, int nlen,
+				  void __user *oldval, size_t __user *oldlenp,
+				  void __user *newval, size_t newlen,
+				  void **context)
+{
+	char val[TCP_CA_NAME_MAX];
+	ctl_table tbl = {
+		.data = val,
+		.maxlen = TCP_CA_NAME_MAX,
+	};
+	int ret;
+
+	tcp_get_default_congestion_control(val);
+	ret = sysctl_string(&tbl, name, nlen, oldval, oldlenp, newval, newlen,
+			    context);
+	if (ret == 0 && newval && newlen)
+		ret = tcp_set_default_congestion_control(val);
+	return ret;
+}
+
+
 ctl_table ipv4_table[] = {
         {
 		.ctl_name	= NET_IPV4_TCP_TIMESTAMPS,
@@ -396,6 +436,14 @@
 		.proc_handler	= &proc_dointvec
 	},
 	{
+		.ctl_name	= NET_IPV4_ICMP_ERRORS_USE_INBOUND_IFADDR,
+		.procname	= "icmp_errors_use_inbound_ifaddr",
+		.data		= &sysctl_icmp_errors_use_inbound_ifaddr,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec
+	},
+	{
 		.ctl_name	= NET_IPV4_ROUTE,
 		.procname	= "route",
 		.maxlen		= 0,
@@ -603,70 +651,6 @@
 		.proc_handler	= &proc_dointvec,
 	},
 	{
-		.ctl_name	= NET_TCP_WESTWOOD, 
-		.procname	= "tcp_westwood",
-		.data		= &sysctl_tcp_westwood,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-	},
-	{
-		.ctl_name	= NET_TCP_VEGAS,
-		.procname	= "tcp_vegas_cong_avoid",
-		.data		= &sysctl_tcp_vegas_cong_avoid,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-	},
-	{
-		.ctl_name	= NET_TCP_VEGAS_ALPHA,
-		.procname	= "tcp_vegas_alpha",
-		.data		= &sysctl_tcp_vegas_alpha,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-	},
-	{
-		.ctl_name	= NET_TCP_VEGAS_BETA,
-		.procname	= "tcp_vegas_beta",
-		.data		= &sysctl_tcp_vegas_beta,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-	},
-	{
-		.ctl_name	= NET_TCP_VEGAS_GAMMA,
-		.procname	= "tcp_vegas_gamma",
-		.data		= &sysctl_tcp_vegas_gamma,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-	},
-	{
-		.ctl_name	= NET_TCP_BIC,
-		.procname	= "tcp_bic",
-		.data		= &sysctl_tcp_bic,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-	},
-	{
-		.ctl_name	= NET_TCP_BIC_FAST_CONVERGENCE,
-		.procname	= "tcp_bic_fast_convergence",
-		.data		= &sysctl_tcp_bic_fast_convergence,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-	},
-	{
-		.ctl_name	= NET_TCP_BIC_LOW_WINDOW,
-		.procname	= "tcp_bic_low_window",
-		.data		= &sysctl_tcp_bic_low_window,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
-	},
-	{
 		.ctl_name	= NET_TCP_MODERATE_RCVBUF,
 		.procname	= "tcp_moderate_rcvbuf",
 		.data		= &sysctl_tcp_moderate_rcvbuf,
@@ -683,13 +667,14 @@
 		.proc_handler	= &proc_dointvec,
 	},
 	{
-		.ctl_name	= NET_TCP_BIC_BETA,
-		.procname	= "tcp_bic_beta",
-		.data		= &sysctl_tcp_bic_beta,
-		.maxlen		= sizeof(int),
+		.ctl_name	= NET_TCP_CONG_CONTROL,
+		.procname	= "tcp_congestion_control",
 		.mode		= 0644,
-		.proc_handler	= &proc_dointvec,
+		.maxlen		= TCP_CA_NAME_MAX,
+		.proc_handler	= &proc_tcp_congestion_control,
+		.strategy	= &sysctl_tcp_congestion_control,
 	},
+
 	{ .ctl_name = 0 }
 };
 
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index a037baf..882436d 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -271,7 +271,6 @@
 
 DEFINE_SNMP_STAT(struct tcp_mib, tcp_statistics);
 
-kmem_cache_t *tcp_openreq_cachep;
 kmem_cache_t *tcp_bucket_cachep;
 kmem_cache_t *tcp_timewait_cachep;
 
@@ -317,7 +316,7 @@
 static __inline__ unsigned int tcp_listen_poll(struct sock *sk,
 					       poll_table *wait)
 {
-	return tcp_sk(sk)->accept_queue ? (POLLIN | POLLRDNORM) : 0;
+	return !reqsk_queue_empty(&tcp_sk(sk)->accept_queue) ? (POLLIN | POLLRDNORM) : 0;
 }
 
 /*
@@ -463,28 +462,15 @@
 {
 	struct inet_sock *inet = inet_sk(sk);
 	struct tcp_sock *tp = tcp_sk(sk);
-	struct tcp_listen_opt *lopt;
+	int rc = reqsk_queue_alloc(&tp->accept_queue, TCP_SYNQ_HSIZE);
+
+	if (rc != 0)
+		return rc;
 
 	sk->sk_max_ack_backlog = 0;
 	sk->sk_ack_backlog = 0;
-	tp->accept_queue = tp->accept_queue_tail = NULL;
-	rwlock_init(&tp->syn_wait_lock);
 	tcp_delack_init(tp);
 
-	lopt = kmalloc(sizeof(struct tcp_listen_opt), GFP_KERNEL);
-	if (!lopt)
-		return -ENOMEM;
-
-	memset(lopt, 0, sizeof(struct tcp_listen_opt));
-	for (lopt->max_qlen_log = 6; ; lopt->max_qlen_log++)
-		if ((1 << lopt->max_qlen_log) >= sysctl_max_syn_backlog)
-			break;
-	get_random_bytes(&lopt->hash_rnd, 4);
-
-	write_lock_bh(&tp->syn_wait_lock);
-	tp->listen_opt = lopt;
-	write_unlock_bh(&tp->syn_wait_lock);
-
 	/* There is race window here: we announce ourselves listening,
 	 * but this transition is still not validated by get_port().
 	 * It is OK, because this socket enters to hash table only
@@ -501,10 +487,7 @@
 	}
 
 	sk->sk_state = TCP_CLOSE;
-	write_lock_bh(&tp->syn_wait_lock);
-	tp->listen_opt = NULL;
-	write_unlock_bh(&tp->syn_wait_lock);
-	kfree(lopt);
+	reqsk_queue_destroy(&tp->accept_queue);
 	return -EADDRINUSE;
 }
 
@@ -516,25 +499,23 @@
 static void tcp_listen_stop (struct sock *sk)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
-	struct tcp_listen_opt *lopt = tp->listen_opt;
-	struct open_request *acc_req = tp->accept_queue;
-	struct open_request *req;
+	struct listen_sock *lopt;
+	struct request_sock *acc_req;
+	struct request_sock *req;
 	int i;
 
 	tcp_delete_keepalive_timer(sk);
 
 	/* make all the listen_opt local to us */
-	write_lock_bh(&tp->syn_wait_lock);
-	tp->listen_opt = NULL;
-	write_unlock_bh(&tp->syn_wait_lock);
-	tp->accept_queue = tp->accept_queue_tail = NULL;
+	lopt = reqsk_queue_yank_listen_sk(&tp->accept_queue);
+	acc_req = reqsk_queue_yank_acceptq(&tp->accept_queue);
 
 	if (lopt->qlen) {
 		for (i = 0; i < TCP_SYNQ_HSIZE; i++) {
 			while ((req = lopt->syn_table[i]) != NULL) {
 				lopt->syn_table[i] = req->dl_next;
 				lopt->qlen--;
-				tcp_openreq_free(req);
+				reqsk_free(req);
 
 		/* Following specs, it would be better either to send FIN
 		 * (and enter FIN-WAIT-1, it is normal close)
@@ -574,7 +555,7 @@
 		sock_put(child);
 
 		sk_acceptq_removed(sk);
-		tcp_openreq_fastfree(req);
+		__reqsk_free(req);
 	}
 	BUG_TRAP(!sk->sk_ack_backlog);
 }
@@ -1345,7 +1326,7 @@
 
 		cleanup_rbuf(sk, copied);
 
-		if (tp->ucopy.task == user_recv) {
+		if (!sysctl_tcp_low_latency && tp->ucopy.task == user_recv) {
 			/* Install new reader */
 			if (!user_recv && !(flags & (MSG_TRUNC | MSG_PEEK))) {
 				user_recv = current;
@@ -1868,11 +1849,11 @@
 		prepare_to_wait_exclusive(sk->sk_sleep, &wait,
 					  TASK_INTERRUPTIBLE);
 		release_sock(sk);
-		if (!tp->accept_queue)
+		if (reqsk_queue_empty(&tp->accept_queue))
 			timeo = schedule_timeout(timeo);
 		lock_sock(sk);
 		err = 0;
-		if (tp->accept_queue)
+		if (!reqsk_queue_empty(&tp->accept_queue))
 			break;
 		err = -EINVAL;
 		if (sk->sk_state != TCP_LISTEN)
@@ -1895,7 +1876,6 @@
 struct sock *tcp_accept(struct sock *sk, int flags, int *err)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
-	struct open_request *req;
 	struct sock *newsk;
 	int error;
 
@@ -1906,37 +1886,31 @@
 	 */
 	error = -EINVAL;
 	if (sk->sk_state != TCP_LISTEN)
-		goto out;
+		goto out_err;
 
 	/* Find already established connection */
-	if (!tp->accept_queue) {
+	if (reqsk_queue_empty(&tp->accept_queue)) {
 		long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
 
 		/* If this is a non blocking socket don't sleep */
 		error = -EAGAIN;
 		if (!timeo)
-			goto out;
+			goto out_err;
 
 		error = wait_for_connect(sk, timeo);
 		if (error)
-			goto out;
+			goto out_err;
 	}
 
-	req = tp->accept_queue;
-	if ((tp->accept_queue = req->dl_next) == NULL)
-		tp->accept_queue_tail = NULL;
-
- 	newsk = req->sk;
-	sk_acceptq_removed(sk);
-	tcp_openreq_fastfree(req);
+	newsk = reqsk_queue_get_child(&tp->accept_queue, sk);
 	BUG_TRAP(newsk->sk_state != TCP_SYN_RECV);
-	release_sock(sk);
-	return newsk;
-
 out:
 	release_sock(sk);
+	return newsk;
+out_err:
+	newsk = NULL;
 	*err = error;
-	return NULL;
+	goto out;
 }
 
 /*
@@ -1953,6 +1927,25 @@
 		return tp->af_specific->setsockopt(sk, level, optname,
 						   optval, optlen);
 
+	/* This is a string value all the others are int's */
+	if (optname == TCP_CONGESTION) {
+		char name[TCP_CA_NAME_MAX];
+
+		if (optlen < 1)
+			return -EINVAL;
+
+		val = strncpy_from_user(name, optval,
+					min(TCP_CA_NAME_MAX-1, optlen));
+		if (val < 0)
+			return -EFAULT;
+		name[val] = 0;
+
+		lock_sock(sk);
+		err = tcp_set_congestion_control(tp, name);
+		release_sock(sk);
+		return err;
+	}
+
 	if (optlen < sizeof(int))
 		return -EINVAL;
 
@@ -2237,6 +2230,16 @@
 	case TCP_QUICKACK:
 		val = !tp->ack.pingpong;
 		break;
+
+	case TCP_CONGESTION:
+		if (get_user(len, optlen))
+			return -EFAULT;
+		len = min_t(unsigned int, len, TCP_CA_NAME_MAX);
+		if (put_user(len, optlen))
+			return -EFAULT;
+		if (copy_to_user(optval, tp->ca_ops->name, len))
+			return -EFAULT;
+		return 0;
 	default:
 		return -ENOPROTOOPT;
 	};
@@ -2250,7 +2253,7 @@
 
 
 extern void __skb_cb_too_small_for_tcp(int, int);
-extern void tcpdiag_init(void);
+extern struct tcp_congestion_ops tcp_reno;
 
 static __initdata unsigned long thash_entries;
 static int __init set_thash_entries(char *str)
@@ -2271,13 +2274,6 @@
 		__skb_cb_too_small_for_tcp(sizeof(struct tcp_skb_cb),
 					   sizeof(skb->cb));
 
-	tcp_openreq_cachep = kmem_cache_create("tcp_open_request",
-						   sizeof(struct open_request),
-					       0, SLAB_HWCACHE_ALIGN,
-					       NULL, NULL);
-	if (!tcp_openreq_cachep)
-		panic("tcp_init: Cannot alloc open_request cache.");
-
 	tcp_bucket_cachep = kmem_cache_create("tcp_bind_bucket",
 					      sizeof(struct tcp_bind_bucket),
 					      0, SLAB_HWCACHE_ALIGN,
@@ -2338,7 +2334,7 @@
 			(tcp_bhash_size * sizeof(struct tcp_bind_hashbucket));
 			order++)
 		;
-	if (order > 4) {
+	if (order >= 4) {
 		sysctl_local_port_range[0] = 32768;
 		sysctl_local_port_range[1] = 61000;
 		sysctl_tcp_max_tw_buckets = 180000;
@@ -2366,6 +2362,8 @@
 	printk(KERN_INFO "TCP: Hash tables configured "
 	       "(established %d bind %d)\n",
 	       tcp_ehash_size << 1, tcp_bhash_size);
+
+	tcp_register_congestion_control(&tcp_reno);
 }
 
 EXPORT_SYMBOL(tcp_accept);
@@ -2374,7 +2372,6 @@
 EXPORT_SYMBOL(tcp_disconnect);
 EXPORT_SYMBOL(tcp_getsockopt);
 EXPORT_SYMBOL(tcp_ioctl);
-EXPORT_SYMBOL(tcp_openreq_cachep);
 EXPORT_SYMBOL(tcp_poll);
 EXPORT_SYMBOL(tcp_read_sock);
 EXPORT_SYMBOL(tcp_recvmsg);
diff --git a/net/ipv4/tcp_bic.c b/net/ipv4/tcp_bic.c
new file mode 100644
index 0000000..ec38d45
--- /dev/null
+++ b/net/ipv4/tcp_bic.c
@@ -0,0 +1,331 @@
+/*
+ * Binary Increase Congestion control for TCP
+ *
+ * This is from the implementation of BICTCP in
+ * Lison-Xu, Kahaled Harfoush, and Injong Rhee.
+ *  "Binary Increase Congestion Control for Fast, Long Distance
+ *  Networks" in InfoComm 2004
+ * Available from:
+ *  http://www.csc.ncsu.edu/faculty/rhee/export/bitcp.pdf
+ *
+ * Unless BIC is enabled and congestion window is large
+ * this behaves the same as the original Reno.
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <net/tcp.h>
+
+
+#define BICTCP_BETA_SCALE    1024	/* Scale factor beta calculation
+					 * max_cwnd = snd_cwnd * beta
+					 */
+#define BICTCP_B		4	 /*
+					  * In binary search,
+					  * go to point (max+min)/N
+					  */
+
+static int fast_convergence = 1;
+static int max_increment = 32;
+static int low_window = 14;
+static int beta = 819;		/* = 819/1024 (BICTCP_BETA_SCALE) */
+static int low_utilization_threshold = 153;
+static int low_utilization_period = 2;
+static int initial_ssthresh = 100;
+static int smooth_part = 20;
+
+module_param(fast_convergence, int, 0644);
+MODULE_PARM_DESC(fast_convergence, "turn on/off fast convergence");
+module_param(max_increment, int, 0644);
+MODULE_PARM_DESC(max_increment, "Limit on increment allowed during binary search");
+module_param(low_window, int, 0644);
+MODULE_PARM_DESC(low_window, "lower bound on congestion window (for TCP friendliness)");
+module_param(beta, int, 0644);
+MODULE_PARM_DESC(beta, "beta for multiplicative increase");
+module_param(low_utilization_threshold, int, 0644);
+MODULE_PARM_DESC(low_utilization_threshold, "percent (scaled by 1024) for low utilization mode");
+module_param(low_utilization_period, int, 0644);
+MODULE_PARM_DESC(low_utilization_period, "if average delay exceeds then goto to low utilization mode (seconds)");
+module_param(initial_ssthresh, int, 0644);
+MODULE_PARM_DESC(initial_ssthresh, "initial value of slow start threshold");
+module_param(smooth_part, int, 0644);
+MODULE_PARM_DESC(smooth_part, "log(B/(B*Smin))/log(B/(B-1))+B, # of RTT from Wmax-B to Wmax");
+
+
+/* BIC TCP Parameters */
+struct bictcp {
+	u32	cnt;		/* increase cwnd by 1 after ACKs */
+	u32 	last_max_cwnd;	/* last maximum snd_cwnd */
+	u32	loss_cwnd;	/* congestion window at last loss */
+	u32	last_cwnd;	/* the last snd_cwnd */
+	u32	last_time;	/* time when updated last_cwnd */
+	u32	delay_min;	/* min delay */
+	u32	delay_max;	/* max delay */
+	u32	last_delay;
+	u8	low_utilization;/* 0: high; 1: low */
+	u32	low_utilization_start;	/* starting time of low utilization detection*/
+	u32	epoch_start;	/* beginning of an epoch */
+#define ACK_RATIO_SHIFT	4
+	u32	delayed_ack;	/* estimate the ratio of Packets/ACKs << 4 */
+};
+
+static inline void bictcp_reset(struct bictcp *ca)
+{
+	ca->cnt = 0;
+	ca->last_max_cwnd = 0;
+	ca->loss_cwnd = 0;
+	ca->last_cwnd = 0;
+	ca->last_time = 0;
+	ca->delay_min = 0;
+	ca->delay_max = 0;
+	ca->last_delay = 0;
+	ca->low_utilization = 0;
+	ca->low_utilization_start = 0;
+	ca->epoch_start = 0;
+	ca->delayed_ack = 2 << ACK_RATIO_SHIFT;
+}
+
+static void bictcp_init(struct tcp_sock *tp)
+{
+	bictcp_reset(tcp_ca(tp));
+	if (initial_ssthresh)
+		tp->snd_ssthresh = initial_ssthresh;
+}
+
+/*
+ * Compute congestion window to use.
+ */
+static inline void bictcp_update(struct bictcp *ca, u32 cwnd)
+{
+	if (ca->last_cwnd == cwnd &&
+	    (s32)(tcp_time_stamp - ca->last_time) <= HZ / 32)
+		return;
+
+	ca->last_cwnd = cwnd;
+	ca->last_time = tcp_time_stamp;
+
+	if (ca->epoch_start == 0) /* record the beginning of an epoch */
+		ca->epoch_start = tcp_time_stamp;
+
+	/* start off normal */
+	if (cwnd <= low_window) {
+		ca->cnt = cwnd;
+		return;
+	}
+
+	/* binary increase */
+	if (cwnd < ca->last_max_cwnd) {
+		__u32 	dist = (ca->last_max_cwnd - cwnd)
+			/ BICTCP_B;
+
+		if (dist > max_increment)
+			/* linear increase */
+			ca->cnt = cwnd / max_increment;
+		else if (dist <= 1U)
+			/* binary search increase */
+			ca->cnt = (cwnd * smooth_part) / BICTCP_B;
+		else
+			/* binary search increase */
+			ca->cnt = cwnd / dist;
+	} else {
+		/* slow start AMD linear increase */
+		if (cwnd < ca->last_max_cwnd + BICTCP_B)
+			/* slow start */
+			ca->cnt = (cwnd * smooth_part) / BICTCP_B;
+		else if (cwnd < ca->last_max_cwnd + max_increment*(BICTCP_B-1))
+			/* slow start */
+			ca->cnt = (cwnd * (BICTCP_B-1))
+				/ cwnd-ca->last_max_cwnd;
+		else
+			/* linear increase */
+			ca->cnt = cwnd / max_increment;
+	}
+
+	/* if in slow start or link utilization is very low */
+	if ( ca->loss_cwnd == 0 ||
+	     (cwnd > ca->loss_cwnd && ca->low_utilization)) {
+		if (ca->cnt > 20) /* increase cwnd 5% per RTT */
+			ca->cnt = 20;
+	}
+
+	ca->cnt = (ca->cnt << ACK_RATIO_SHIFT) / ca->delayed_ack;
+	if (ca->cnt == 0)			/* cannot be zero */
+		ca->cnt = 1;
+}
+
+
+/* Detect low utilization in congestion avoidance */
+static inline void bictcp_low_utilization(struct tcp_sock *tp, int flag)
+{
+	struct bictcp *ca = tcp_ca(tp);
+	u32 dist, delay;
+
+	/* No time stamp */
+	if (!(tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr) ||
+	     /* Discard delay samples right after fast recovery */
+	     tcp_time_stamp < ca->epoch_start + HZ ||
+	     /* this delay samples may not be accurate */
+	     flag == 0) {
+		ca->last_delay = 0;
+		goto notlow;
+	}
+
+	delay = ca->last_delay<<3;	/* use the same scale as tp->srtt*/
+	ca->last_delay = tcp_time_stamp - tp->rx_opt.rcv_tsecr;
+	if (delay == 0) 		/* no previous delay sample */
+		goto notlow;
+
+	/* first time call or link delay decreases */
+	if (ca->delay_min == 0 || ca->delay_min > delay) {
+		ca->delay_min = ca->delay_max = delay;
+		goto notlow;
+	}
+
+	if (ca->delay_max < delay)
+		ca->delay_max = delay;
+
+	/* utilization is low, if avg delay < dist*threshold
+	   for checking_period time */
+	dist = ca->delay_max - ca->delay_min;
+	if (dist <= ca->delay_min>>6 ||
+	    tp->srtt - ca->delay_min >=  (dist*low_utilization_threshold)>>10)
+		goto notlow;
+
+	if (ca->low_utilization_start == 0) {
+		ca->low_utilization = 0;
+		ca->low_utilization_start = tcp_time_stamp;
+	} else if ((s32)(tcp_time_stamp - ca->low_utilization_start)
+			> low_utilization_period*HZ) {
+		ca->low_utilization = 1;
+	}
+
+	return;
+
+ notlow:
+	ca->low_utilization = 0;
+	ca->low_utilization_start = 0;
+
+}
+
+static void bictcp_cong_avoid(struct tcp_sock *tp, u32 ack,
+			      u32 seq_rtt, u32 in_flight, int data_acked)
+{
+	struct bictcp *ca = tcp_ca(tp);
+
+	bictcp_low_utilization(tp, data_acked);
+
+	if (in_flight < tp->snd_cwnd)
+		return;
+
+	if (tp->snd_cwnd <= tp->snd_ssthresh) {
+		/* In "safe" area, increase. */
+		if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+			tp->snd_cwnd++;
+	} else {
+		bictcp_update(ca, tp->snd_cwnd);
+
+                /* In dangerous area, increase slowly.
+		 * In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd
+		 */
+		if (tp->snd_cwnd_cnt >= ca->cnt) {
+			if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+				tp->snd_cwnd++;
+			tp->snd_cwnd_cnt = 0;
+		} else
+			tp->snd_cwnd_cnt++;
+	}
+
+}
+
+/*
+ *	behave like Reno until low_window is reached,
+ *	then increase congestion window slowly
+ */
+static u32 bictcp_recalc_ssthresh(struct tcp_sock *tp)
+{
+	struct bictcp *ca = tcp_ca(tp);
+
+	ca->epoch_start = 0;	/* end of epoch */
+
+	/* in case of wrong delay_max*/
+	if (ca->delay_min > 0 && ca->delay_max > ca->delay_min)
+		ca->delay_max = ca->delay_min
+			+ ((ca->delay_max - ca->delay_min)* 90) / 100;
+
+	/* Wmax and fast convergence */
+	if (tp->snd_cwnd < ca->last_max_cwnd && fast_convergence)
+		ca->last_max_cwnd = (tp->snd_cwnd * (BICTCP_BETA_SCALE + beta))
+			/ (2 * BICTCP_BETA_SCALE);
+	else
+		ca->last_max_cwnd = tp->snd_cwnd;
+
+	ca->loss_cwnd = tp->snd_cwnd;
+
+
+	if (tp->snd_cwnd <= low_window)
+		return max(tp->snd_cwnd >> 1U, 2U);
+	else
+		return max((tp->snd_cwnd * beta) / BICTCP_BETA_SCALE, 2U);
+}
+
+static u32 bictcp_undo_cwnd(struct tcp_sock *tp)
+{
+	struct bictcp *ca = tcp_ca(tp);
+
+	return max(tp->snd_cwnd, ca->last_max_cwnd);
+}
+
+static u32 bictcp_min_cwnd(struct tcp_sock *tp)
+{
+	return tp->snd_ssthresh;
+}
+
+static void bictcp_state(struct tcp_sock *tp, u8 new_state)
+{
+	if (new_state == TCP_CA_Loss)
+		bictcp_reset(tcp_ca(tp));
+}
+
+/* Track delayed acknowledgement ratio using sliding window
+ * ratio = (15*ratio + sample) / 16
+ */
+static void bictcp_acked(struct tcp_sock *tp, u32 cnt)
+{
+	if (cnt > 0 && 	tp->ca_state == TCP_CA_Open) {
+		struct bictcp *ca = tcp_ca(tp);
+		cnt -= ca->delayed_ack >> ACK_RATIO_SHIFT;
+		ca->delayed_ack += cnt;
+	}
+}
+
+
+static struct tcp_congestion_ops bictcp = {
+	.init		= bictcp_init,
+	.ssthresh	= bictcp_recalc_ssthresh,
+	.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",
+};
+
+static int __init bictcp_register(void)
+{
+	BUG_ON(sizeof(struct bictcp) > TCP_CA_PRIV_SIZE);
+	return tcp_register_congestion_control(&bictcp);
+}
+
+static void __exit bictcp_unregister(void)
+{
+	tcp_unregister_congestion_control(&bictcp);
+}
+
+module_init(bictcp_register);
+module_exit(bictcp_unregister);
+
+MODULE_AUTHOR("Stephen Hemminger");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("BIC TCP");
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
new file mode 100644
index 0000000..4970d10
--- /dev/null
+++ b/net/ipv4/tcp_cong.c
@@ -0,0 +1,237 @@
+/*
+ * Plugable TCP congestion control support and newReno
+ * congestion control.
+ * Based on ideas from I/O scheduler suport and Web100.
+ *
+ * Copyright (C) 2005 Stephen Hemminger <shemminger@osdl.org>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <net/tcp.h>
+
+static DEFINE_SPINLOCK(tcp_cong_list_lock);
+static LIST_HEAD(tcp_cong_list);
+
+/* Simple linear search, don't expect many entries! */
+static struct tcp_congestion_ops *tcp_ca_find(const char *name)
+{
+	struct tcp_congestion_ops *e;
+
+	list_for_each_entry_rcu(e, &tcp_cong_list, list) {
+		if (strcmp(e->name, name) == 0)
+			return e;
+	}
+
+	return NULL;
+}
+
+/*
+ * Attach new congestion control algorthim to the list
+ * of available options.
+ */
+int tcp_register_congestion_control(struct tcp_congestion_ops *ca)
+{
+	int ret = 0;
+
+	/* all algorithms must implement ssthresh and cong_avoid ops */
+	if (!ca->ssthresh || !ca->cong_avoid || !ca->min_cwnd) {
+		printk(KERN_ERR "TCP %s does not implement required ops\n",
+		       ca->name);
+		return -EINVAL;
+	}
+
+	spin_lock(&tcp_cong_list_lock);
+	if (tcp_ca_find(ca->name)) {
+		printk(KERN_NOTICE "TCP %s already registered\n", ca->name);
+		ret = -EEXIST;
+	} else {
+		list_add_rcu(&ca->list, &tcp_cong_list);
+		printk(KERN_INFO "TCP %s registered\n", ca->name);
+	}
+	spin_unlock(&tcp_cong_list_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(tcp_register_congestion_control);
+
+/*
+ * Remove congestion control algorithm, called from
+ * the module's remove function.  Module ref counts are used
+ * to ensure that this can't be done till all sockets using
+ * that method are closed.
+ */
+void tcp_unregister_congestion_control(struct tcp_congestion_ops *ca)
+{
+	spin_lock(&tcp_cong_list_lock);
+	list_del_rcu(&ca->list);
+	spin_unlock(&tcp_cong_list_lock);
+}
+EXPORT_SYMBOL_GPL(tcp_unregister_congestion_control);
+
+/* Assign choice of congestion control. */
+void tcp_init_congestion_control(struct tcp_sock *tp)
+{
+	struct tcp_congestion_ops *ca;
+
+	if (tp->ca_ops != &tcp_init_congestion_ops)
+		return;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(ca, &tcp_cong_list, list) {
+		if (try_module_get(ca->owner)) {
+			tp->ca_ops = ca;
+			break;
+		}
+
+	}
+	rcu_read_unlock();
+
+	if (tp->ca_ops->init)
+		tp->ca_ops->init(tp);
+}
+
+/* Manage refcounts on socket close. */
+void tcp_cleanup_congestion_control(struct tcp_sock *tp)
+{
+	if (tp->ca_ops->release)
+		tp->ca_ops->release(tp);
+	module_put(tp->ca_ops->owner);
+}
+
+/* Used by sysctl to change default congestion control */
+int tcp_set_default_congestion_control(const char *name)
+{
+	struct tcp_congestion_ops *ca;
+	int ret = -ENOENT;
+
+	spin_lock(&tcp_cong_list_lock);
+	ca = tcp_ca_find(name);
+#ifdef CONFIG_KMOD
+	if (!ca) {
+		spin_unlock(&tcp_cong_list_lock);
+
+		request_module("tcp_%s", name);
+		spin_lock(&tcp_cong_list_lock);
+		ca = tcp_ca_find(name);
+	}
+#endif
+
+	if (ca) {
+		list_move(&ca->list, &tcp_cong_list);
+		ret = 0;
+	}
+	spin_unlock(&tcp_cong_list_lock);
+
+	return ret;
+}
+
+/* Get current default congestion control */
+void tcp_get_default_congestion_control(char *name)
+{
+	struct tcp_congestion_ops *ca;
+	/* We will always have reno... */
+	BUG_ON(list_empty(&tcp_cong_list));
+
+	rcu_read_lock();
+	ca = list_entry(tcp_cong_list.next, struct tcp_congestion_ops, list);
+	strncpy(name, ca->name, TCP_CA_NAME_MAX);
+	rcu_read_unlock();
+}
+
+/* Change congestion control for socket */
+int tcp_set_congestion_control(struct tcp_sock *tp, const char *name)
+{
+	struct tcp_congestion_ops *ca;
+	int err = 0;
+
+	rcu_read_lock();
+	ca = tcp_ca_find(name);
+	if (ca == tp->ca_ops)
+		goto out;
+
+	if (!ca)
+		err = -ENOENT;
+
+	else if (!try_module_get(ca->owner))
+		err = -EBUSY;
+
+	else {
+		tcp_cleanup_congestion_control(tp);
+		tp->ca_ops = ca;
+		if (tp->ca_ops->init)
+			tp->ca_ops->init(tp);
+	}
+ out:
+	rcu_read_unlock();
+	return err;
+}
+
+/*
+ * TCP Reno congestion control
+ * This is special case used for fallback as well.
+ */
+/* This is Jacobson's slow start and congestion avoidance.
+ * SIGCOMM '88, p. 328.
+ */
+void tcp_reno_cong_avoid(struct tcp_sock *tp, u32 ack, u32 rtt, u32 in_flight,
+			 int flag)
+{
+	if (in_flight < tp->snd_cwnd)
+		return;
+
+        if (tp->snd_cwnd <= tp->snd_ssthresh) {
+                /* In "safe" area, increase. */
+		if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+			tp->snd_cwnd++;
+	} else {
+                /* In dangerous area, increase slowly.
+		 * In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd
+		 */
+		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++;
+	}
+}
+EXPORT_SYMBOL_GPL(tcp_reno_cong_avoid);
+
+/* Slow start threshold is half the congestion window (min 2) */
+u32 tcp_reno_ssthresh(struct tcp_sock *tp)
+{
+	return max(tp->snd_cwnd >> 1U, 2U);
+}
+EXPORT_SYMBOL_GPL(tcp_reno_ssthresh);
+
+/* Lower bound on congestion window. */
+u32 tcp_reno_min_cwnd(struct tcp_sock *tp)
+{
+	return tp->snd_ssthresh/2;
+}
+EXPORT_SYMBOL_GPL(tcp_reno_min_cwnd);
+
+struct tcp_congestion_ops tcp_reno = {
+	.name		= "reno",
+	.owner		= THIS_MODULE,
+	.ssthresh	= tcp_reno_ssthresh,
+	.cong_avoid	= tcp_reno_cong_avoid,
+	.min_cwnd	= tcp_reno_min_cwnd,
+};
+
+/* Initial congestion control used (until SYN)
+ * really reno under another name so we can tell difference
+ * during tcp_set_default_congestion_control
+ */
+struct tcp_congestion_ops tcp_init_congestion_ops  = {
+	.name		= "",
+	.owner		= THIS_MODULE,
+	.ssthresh	= tcp_reno_ssthresh,
+	.cong_avoid	= tcp_reno_cong_avoid,
+	.min_cwnd	= tcp_reno_min_cwnd,
+};
+EXPORT_SYMBOL_GPL(tcp_init_congestion_ops);
diff --git a/net/ipv4/tcp_diag.c b/net/ipv4/tcp_diag.c
index 8faa894..f66945c 100644
--- a/net/ipv4/tcp_diag.c
+++ b/net/ipv4/tcp_diag.c
@@ -42,15 +42,8 @@
 
 static struct sock *tcpnl;
 
-
 #define TCPDIAG_PUT(skb, attrtype, attrlen) \
-({ int rtalen = RTA_LENGTH(attrlen);        \
-   struct rtattr *rta;                      \
-   if (skb_tailroom(skb) < RTA_ALIGN(rtalen)) goto nlmsg_failure; \
-   rta = (void*)__skb_put(skb, RTA_ALIGN(rtalen)); \
-   rta->rta_type = attrtype;                \
-   rta->rta_len = rtalen;                   \
-   RTA_DATA(rta); })
+	RTA_DATA(__RTA_PUT(skb, attrtype, attrlen))
 
 static int tcpdiag_fill(struct sk_buff *skb, struct sock *sk,
 			int ext, u32 pid, u32 seq, u16 nlmsg_flags)
@@ -61,7 +54,6 @@
 	struct nlmsghdr  *nlh;
 	struct tcp_info  *info = NULL;
 	struct tcpdiag_meminfo  *minfo = NULL;
-	struct tcpvegas_info *vinfo = NULL;
 	unsigned char	 *b = skb->tail;
 
 	nlh = NLMSG_PUT(skb, pid, seq, TCPDIAG_GETSOCK, sizeof(*r));
@@ -73,9 +65,11 @@
 		if (ext & (1<<(TCPDIAG_INFO-1)))
 			info = TCPDIAG_PUT(skb, TCPDIAG_INFO, sizeof(*info));
 		
-		if ((tcp_is_westwood(tp) || tcp_is_vegas(tp))
-		    && (ext & (1<<(TCPDIAG_VEGASINFO-1))))
-			vinfo = TCPDIAG_PUT(skb, TCPDIAG_VEGASINFO, sizeof(*vinfo));
+		if (ext & (1<<(TCPDIAG_CONG-1))) {
+			size_t len = strlen(tp->ca_ops->name);
+			strcpy(TCPDIAG_PUT(skb, TCPDIAG_CONG, len+1),
+			       tp->ca_ops->name);
+		}
 	}
 	r->tcpdiag_family = sk->sk_family;
 	r->tcpdiag_state = sk->sk_state;
@@ -166,23 +160,13 @@
 	if (info) 
 		tcp_get_info(sk, info);
 
-	if (vinfo) {
-		if (tcp_is_vegas(tp)) {
-			vinfo->tcpv_enabled = tp->vegas.doing_vegas_now;
-			vinfo->tcpv_rttcnt = tp->vegas.cntRTT;
-			vinfo->tcpv_rtt = jiffies_to_usecs(tp->vegas.baseRTT);
-			vinfo->tcpv_minrtt = jiffies_to_usecs(tp->vegas.minRTT);
-		} else {
-			vinfo->tcpv_enabled = 0;
-			vinfo->tcpv_rttcnt = 0;
-			vinfo->tcpv_rtt = jiffies_to_usecs(tp->westwood.rtt);
-			vinfo->tcpv_minrtt = jiffies_to_usecs(tp->westwood.rtt_min);
-		}
-	}
+	if (sk->sk_state < TCP_TIME_WAIT && tp->ca_ops->get_info)
+		tp->ca_ops->get_info(tp, ext, skb);
 
 	nlh->nlmsg_len = skb->tail - b;
 	return skb->len;
 
+rtattr_failure:
 nlmsg_failure:
 	skb_trim(skb, b - skb->data);
 	return -1;
@@ -455,9 +439,10 @@
 }
 
 static int tcpdiag_fill_req(struct sk_buff *skb, struct sock *sk,
-			    struct open_request *req,
+			    struct request_sock *req,
 			    u32 pid, u32 seq)
 {
+	const struct inet_request_sock *ireq = inet_rsk(req);
 	struct inet_sock *inet = inet_sk(sk);
 	unsigned char *b = skb->tail;
 	struct tcpdiagmsg *r;
@@ -482,9 +467,9 @@
 		tmo = 0;
 
 	r->id.tcpdiag_sport = inet->sport;
-	r->id.tcpdiag_dport = req->rmt_port;
-	r->id.tcpdiag_src[0] = req->af.v4_req.loc_addr;
-	r->id.tcpdiag_dst[0] = req->af.v4_req.rmt_addr;
+	r->id.tcpdiag_dport = ireq->rmt_port;
+	r->id.tcpdiag_src[0] = ireq->loc_addr;
+	r->id.tcpdiag_dst[0] = ireq->rmt_addr;
 	r->tcpdiag_expires = jiffies_to_msecs(tmo),
 	r->tcpdiag_rqueue = 0;
 	r->tcpdiag_wqueue = 0;
@@ -493,9 +478,9 @@
 #ifdef CONFIG_IP_TCPDIAG_IPV6
 	if (r->tcpdiag_family == AF_INET6) {
 		ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_src,
-			       &req->af.v6_req.loc_addr);
+			       &tcp6_rsk(req)->loc_addr);
 		ipv6_addr_copy((struct in6_addr *)r->id.tcpdiag_dst,
-			       &req->af.v6_req.rmt_addr);
+			       &tcp6_rsk(req)->rmt_addr);
 	}
 #endif
 	nlh->nlmsg_len = skb->tail - b;
@@ -513,7 +498,7 @@
 	struct tcpdiag_entry entry;
 	struct tcpdiagreq *r = NLMSG_DATA(cb->nlh);
 	struct tcp_sock *tp = tcp_sk(sk);
-	struct tcp_listen_opt *lopt;
+	struct listen_sock *lopt;
 	struct rtattr *bc = NULL;
 	struct inet_sock *inet = inet_sk(sk);
 	int j, s_j;
@@ -528,9 +513,9 @@
 
 	entry.family = sk->sk_family;
 
-	read_lock_bh(&tp->syn_wait_lock);
+	read_lock_bh(&tp->accept_queue.syn_wait_lock);
 
-	lopt = tp->listen_opt;
+	lopt = tp->accept_queue.listen_opt;
 	if (!lopt || !lopt->qlen)
 		goto out;
 
@@ -541,13 +526,15 @@
 	}
 
 	for (j = s_j; j < TCP_SYNQ_HSIZE; j++) {
-		struct open_request *req, *head = lopt->syn_table[j];
+		struct request_sock *req, *head = lopt->syn_table[j];
 
 		reqnum = 0;
 		for (req = head; req; reqnum++, req = req->dl_next) {
+			struct inet_request_sock *ireq = inet_rsk(req);
+
 			if (reqnum < s_reqnum)
 				continue;
-			if (r->id.tcpdiag_dport != req->rmt_port &&
+			if (r->id.tcpdiag_dport != ireq->rmt_port &&
 			    r->id.tcpdiag_dport)
 				continue;
 
@@ -555,16 +542,16 @@
 				entry.saddr =
 #ifdef CONFIG_IP_TCPDIAG_IPV6
 					(entry.family == AF_INET6) ?
-					req->af.v6_req.loc_addr.s6_addr32 :
+					tcp6_rsk(req)->loc_addr.s6_addr32 :
 #endif
-					&req->af.v4_req.loc_addr;
+					&ireq->loc_addr;
 				entry.daddr = 
 #ifdef CONFIG_IP_TCPDIAG_IPV6
 					(entry.family == AF_INET6) ?
-					req->af.v6_req.rmt_addr.s6_addr32 :
+					tcp6_rsk(req)->rmt_addr.s6_addr32 :
 #endif
-					&req->af.v4_req.rmt_addr;
-				entry.dport = ntohs(req->rmt_port);
+					&ireq->rmt_addr;
+				entry.dport = ntohs(ireq->rmt_port);
 
 				if (!tcpdiag_bc_run(RTA_DATA(bc),
 						    RTA_PAYLOAD(bc), &entry))
@@ -585,7 +572,7 @@
 	}
 
 out:
-	read_unlock_bh(&tp->syn_wait_lock);
+	read_unlock_bh(&tp->accept_queue.syn_wait_lock);
 
 	return err;
 }
diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c
new file mode 100644
index 0000000..36c51f8
--- /dev/null
+++ b/net/ipv4/tcp_highspeed.c
@@ -0,0 +1,181 @@
+/*
+ * Sally Floyd's High Speed TCP (RFC 3649) congestion control
+ *
+ * See http://www.icir.org/floyd/hstcp.html
+ *
+ * John Heffner <jheffner@psc.edu>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <net/tcp.h>
+
+
+/* From AIMD tables from RFC 3649 appendix B,
+ * with fixed-point MD scaled <<8.
+ */
+static const struct hstcp_aimd_val {
+        unsigned int cwnd;
+        unsigned int md;
+} hstcp_aimd_vals[] = {
+ {     38,  128, /*  0.50 */ },
+ {    118,  112, /*  0.44 */ },
+ {    221,  104, /*  0.41 */ },
+ {    347,   98, /*  0.38 */ },
+ {    495,   93, /*  0.37 */ },
+ {    663,   89, /*  0.35 */ },
+ {    851,   86, /*  0.34 */ },
+ {   1058,   83, /*  0.33 */ },
+ {   1284,   81, /*  0.32 */ },
+ {   1529,   78, /*  0.31 */ },
+ {   1793,   76, /*  0.30 */ },
+ {   2076,   74, /*  0.29 */ },
+ {   2378,   72, /*  0.28 */ },
+ {   2699,   71, /*  0.28 */ },
+ {   3039,   69, /*  0.27 */ },
+ {   3399,   68, /*  0.27 */ },
+ {   3778,   66, /*  0.26 */ },
+ {   4177,   65, /*  0.26 */ },
+ {   4596,   64, /*  0.25 */ },
+ {   5036,   62, /*  0.25 */ },
+ {   5497,   61, /*  0.24 */ },
+ {   5979,   60, /*  0.24 */ },
+ {   6483,   59, /*  0.23 */ },
+ {   7009,   58, /*  0.23 */ },
+ {   7558,   57, /*  0.22 */ },
+ {   8130,   56, /*  0.22 */ },
+ {   8726,   55, /*  0.22 */ },
+ {   9346,   54, /*  0.21 */ },
+ {   9991,   53, /*  0.21 */ },
+ {  10661,   52, /*  0.21 */ },
+ {  11358,   52, /*  0.20 */ },
+ {  12082,   51, /*  0.20 */ },
+ {  12834,   50, /*  0.20 */ },
+ {  13614,   49, /*  0.19 */ },
+ {  14424,   48, /*  0.19 */ },
+ {  15265,   48, /*  0.19 */ },
+ {  16137,   47, /*  0.19 */ },
+ {  17042,   46, /*  0.18 */ },
+ {  17981,   45, /*  0.18 */ },
+ {  18955,   45, /*  0.18 */ },
+ {  19965,   44, /*  0.17 */ },
+ {  21013,   43, /*  0.17 */ },
+ {  22101,   43, /*  0.17 */ },
+ {  23230,   42, /*  0.17 */ },
+ {  24402,   41, /*  0.16 */ },
+ {  25618,   41, /*  0.16 */ },
+ {  26881,   40, /*  0.16 */ },
+ {  28193,   39, /*  0.16 */ },
+ {  29557,   39, /*  0.15 */ },
+ {  30975,   38, /*  0.15 */ },
+ {  32450,   38, /*  0.15 */ },
+ {  33986,   37, /*  0.15 */ },
+ {  35586,   36, /*  0.14 */ },
+ {  37253,   36, /*  0.14 */ },
+ {  38992,   35, /*  0.14 */ },
+ {  40808,   35, /*  0.14 */ },
+ {  42707,   34, /*  0.13 */ },
+ {  44694,   33, /*  0.13 */ },
+ {  46776,   33, /*  0.13 */ },
+ {  48961,   32, /*  0.13 */ },
+ {  51258,   32, /*  0.13 */ },
+ {  53677,   31, /*  0.12 */ },
+ {  56230,   30, /*  0.12 */ },
+ {  58932,   30, /*  0.12 */ },
+ {  61799,   29, /*  0.12 */ },
+ {  64851,   28, /*  0.11 */ },
+ {  68113,   28, /*  0.11 */ },
+ {  71617,   27, /*  0.11 */ },
+ {  75401,   26, /*  0.10 */ },
+ {  79517,   26, /*  0.10 */ },
+ {  84035,   25, /*  0.10 */ },
+ {  89053,   24, /*  0.10 */ },
+};
+
+#define HSTCP_AIMD_MAX	ARRAY_SIZE(hstcp_aimd_vals)
+
+struct hstcp {
+	u32	ai;
+};
+
+static void hstcp_init(struct tcp_sock *tp)
+{
+	struct hstcp *ca = tcp_ca(tp);
+
+	ca->ai = 0;
+
+	/* Ensure the MD arithmetic works.  This is somewhat pedantic,
+	 * since I don't think we will see a cwnd this large. :) */
+	tp->snd_cwnd_clamp = min_t(u32, tp->snd_cwnd_clamp, 0xffffffff/128);
+}
+
+static void hstcp_cong_avoid(struct tcp_sock *tp, u32 adk, u32 rtt,
+			     u32 in_flight, int good)
+{
+	struct hstcp *ca = tcp_ca(tp);
+
+	if (in_flight < tp->snd_cwnd)
+		return;
+
+	if (tp->snd_cwnd <= tp->snd_ssthresh) {
+		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 &&
+			       ca->ai < HSTCP_AIMD_MAX)
+				ca->ai++;
+		} else if (tp->snd_cwnd < hstcp_aimd_vals[ca->ai].cwnd) {
+			while (tp->snd_cwnd > hstcp_aimd_vals[ca->ai].cwnd &&
+			       ca->ai > 0)
+				ca->ai--;
+		}
+
+		/* Do additive increase */
+		if (tp->snd_cwnd < tp->snd_cwnd_clamp) {
+			tp->snd_cwnd_cnt += ca->ai;
+			if (tp->snd_cwnd_cnt >= tp->snd_cwnd) {
+				tp->snd_cwnd++;
+				tp->snd_cwnd_cnt -= tp->snd_cwnd;
+			}
+		}
+	}
+}
+
+static u32 hstcp_ssthresh(struct tcp_sock *tp)
+{
+	struct hstcp *ca = tcp_ca(tp);
+
+	/* Do multiplicative decrease */
+	return max(tp->snd_cwnd - ((tp->snd_cwnd * hstcp_aimd_vals[ca->ai].md) >> 8), 2U);
+}
+
+
+static struct tcp_congestion_ops tcp_highspeed = {
+	.init		= hstcp_init,
+	.ssthresh	= hstcp_ssthresh,
+	.cong_avoid	= hstcp_cong_avoid,
+	.min_cwnd	= tcp_reno_min_cwnd,
+
+	.owner		= THIS_MODULE,
+	.name		= "highspeed"
+};
+
+static int __init hstcp_register(void)
+{
+	BUG_ON(sizeof(struct hstcp) > TCP_CA_PRIV_SIZE);
+	return tcp_register_congestion_control(&tcp_highspeed);
+}
+
+static void __exit hstcp_unregister(void)
+{
+	tcp_unregister_congestion_control(&tcp_highspeed);
+}
+
+module_init(hstcp_register);
+module_exit(hstcp_unregister);
+
+MODULE_AUTHOR("John Heffner");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("High Speed TCP");
diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c
new file mode 100644
index 0000000..4016827
--- /dev/null
+++ b/net/ipv4/tcp_htcp.c
@@ -0,0 +1,289 @@
+/*
+ * H-TCP congestion control. The algorithm is detailed in:
+ * R.N.Shorten, D.J.Leith:
+ *   "H-TCP: TCP for high-speed and long-distance networks"
+ *   Proc. PFLDnet, Argonne, 2004.
+ * http://www.hamilton.ie/net/htcp3.pdf
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <net/tcp.h>
+
+#define ALPHA_BASE	(1<<7)  /* 1.0 with shift << 7 */
+#define BETA_MIN	(1<<6)  /* 0.5 with shift << 7 */
+#define BETA_MAX	102	/* 0.8 with shift << 7 */
+
+static int use_rtt_scaling = 1;
+module_param(use_rtt_scaling, int, 0644);
+MODULE_PARM_DESC(use_rtt_scaling, "turn on/off RTT scaling");
+
+static int use_bandwidth_switch = 1;
+module_param(use_bandwidth_switch, int, 0644);
+MODULE_PARM_DESC(use_bandwidth_switch, "turn on/off bandwidth switcher");
+
+struct htcp {
+	u16	alpha;		/* Fixed point arith, << 7 */
+	u8	beta;           /* Fixed point arith, << 7 */
+	u8	modeswitch;     /* Delay modeswitch until we had at least one congestion event */
+	u8	ccount;		/* Number of RTTs since last congestion event */
+	u8	undo_ccount;
+	u16	packetcount;
+	u32	minRTT;
+	u32	maxRTT;
+	u32	snd_cwnd_cnt2;
+
+	u32	undo_maxRTT;
+	u32	undo_old_maxB;
+
+	/* Bandwidth estimation */
+	u32	minB;
+	u32	maxB;
+	u32	old_maxB;
+	u32	Bi;
+	u32	lasttime;
+};
+
+static inline void htcp_reset(struct htcp *ca)
+{
+	ca->undo_ccount = ca->ccount;
+	ca->undo_maxRTT = ca->maxRTT;
+	ca->undo_old_maxB = ca->old_maxB;
+
+	ca->ccount = 0;
+	ca->snd_cwnd_cnt2 = 0;
+}
+
+static u32 htcp_cwnd_undo(struct tcp_sock *tp)
+{
+	struct htcp *ca = tcp_ca(tp);
+	ca->ccount = ca->undo_ccount;
+	ca->maxRTT = ca->undo_maxRTT;
+	ca->old_maxB = ca->undo_old_maxB;
+	return max(tp->snd_cwnd, (tp->snd_ssthresh<<7)/ca->beta);
+}
+
+static inline void measure_rtt(struct tcp_sock *tp)
+{
+	struct htcp *ca = tcp_ca(tp);
+	u32 srtt = tp->srtt>>3;
+
+	/* keep track of minimum RTT seen so far, minRTT is zero at first */
+	if (ca->minRTT > srtt || !ca->minRTT)
+		ca->minRTT = srtt;
+
+	/* max RTT */
+	if (tp->ca_state == TCP_CA_Open && tp->snd_ssthresh < 0xFFFF && ca->ccount > 3) {
+		if (ca->maxRTT < ca->minRTT)
+			ca->maxRTT = ca->minRTT;
+		if (ca->maxRTT < srtt && srtt <= ca->maxRTT+HZ/50)
+			ca->maxRTT = srtt;
+	}
+}
+
+static void measure_achieved_throughput(struct tcp_sock *tp, u32 pkts_acked)
+{
+	struct htcp *ca = tcp_ca(tp);
+	u32 now = tcp_time_stamp;
+
+	/* achieved throughput calculations */
+	if (tp->ca_state != TCP_CA_Open && tp->ca_state != TCP_CA_Disorder) {
+		ca->packetcount = 0;
+		ca->lasttime = now;
+		return;
+	}
+
+	ca->packetcount += pkts_acked;
+
+	if (ca->packetcount >= tp->snd_cwnd - (ca->alpha>>7? : 1)
+			&& now - ca->lasttime >= ca->minRTT
+			&& ca->minRTT > 0) {
+		__u32 cur_Bi = ca->packetcount*HZ/(now - ca->lasttime);
+		if (ca->ccount <= 3) {
+			/* just after backoff */
+			ca->minB = ca->maxB = ca->Bi = cur_Bi;
+		} else {
+			ca->Bi = (3*ca->Bi + cur_Bi)/4;
+			if (ca->Bi > ca->maxB)
+				ca->maxB = ca->Bi;
+			if (ca->minB > ca->maxB)
+				ca->minB = ca->maxB;
+		}
+		ca->packetcount = 0;
+		ca->lasttime = now;
+	}
+}
+
+static inline void htcp_beta_update(struct htcp *ca, u32 minRTT, u32 maxRTT)
+{
+	if (use_bandwidth_switch) {
+		u32 maxB = ca->maxB;
+		u32 old_maxB = ca->old_maxB;
+		ca->old_maxB = ca->maxB;
+
+		if (!between(5*maxB, 4*old_maxB, 6*old_maxB)) {
+			ca->beta = BETA_MIN;
+			ca->modeswitch = 0;
+			return;
+		}
+	}
+
+	if (ca->modeswitch && minRTT > max(HZ/100, 1) && maxRTT) {
+		ca->beta = (minRTT<<7)/maxRTT;
+		if (ca->beta < BETA_MIN)
+			ca->beta = BETA_MIN;
+		else if (ca->beta > BETA_MAX)
+			ca->beta = BETA_MAX;
+	} else {
+		ca->beta = BETA_MIN;
+		ca->modeswitch = 1;
+	}
+}
+
+static inline void htcp_alpha_update(struct htcp *ca)
+{
+	u32 minRTT = ca->minRTT;
+	u32 factor = 1;
+	u32 diff = ca->ccount * minRTT; /* time since last backoff */
+
+	if (diff > HZ) {
+		diff -= HZ;
+		factor = 1+ ( 10*diff + ((diff/2)*(diff/2)/HZ) )/HZ;
+	}
+
+	if (use_rtt_scaling && minRTT) {
+		u32 scale = (HZ<<3)/(10*minRTT);
+		scale = min(max(scale, 1U<<2), 10U<<3); /* clamping ratio to interval [0.5,10]<<3 */
+		factor = (factor<<3)/scale;
+		if (!factor)
+			factor = 1;
+	}
+
+	ca->alpha = 2*factor*((1<<7)-ca->beta);
+	if (!ca->alpha)
+		ca->alpha = ALPHA_BASE;
+}
+
+/* After we have the rtt data to calculate beta, we'd still prefer to wait one
+ * rtt before we adjust our beta to ensure we are working from a consistent
+ * data.
+ *
+ * This function should be called when we hit a congestion event since only at
+ * that point do we really have a real sense of maxRTT (the queues en route
+ * were getting just too full now).
+ */
+static void htcp_param_update(struct tcp_sock *tp)
+{
+	struct htcp *ca = tcp_ca(tp);
+	u32 minRTT = ca->minRTT;
+	u32 maxRTT = ca->maxRTT;
+
+	htcp_beta_update(ca, minRTT, maxRTT);
+	htcp_alpha_update(ca);
+
+	/* add slowly fading memory for maxRTT to accommodate routing changes etc */
+	if (minRTT > 0 && maxRTT > minRTT)
+		ca->maxRTT = minRTT + ((maxRTT-minRTT)*95)/100;
+}
+
+static u32 htcp_recalc_ssthresh(struct tcp_sock *tp)
+{
+	struct htcp *ca = tcp_ca(tp);
+	htcp_param_update(tp);
+	return max((tp->snd_cwnd * ca->beta) >> 7, 2U);
+}
+
+static void htcp_cong_avoid(struct tcp_sock *tp, u32 ack, u32 rtt,
+			    u32 in_flight, int data_acked)
+{
+	struct htcp *ca = tcp_ca(tp);
+
+	if (in_flight < tp->snd_cwnd)
+		return;
+
+        if (tp->snd_cwnd <= tp->snd_ssthresh) {
+                /* In "safe" area, increase. */
+		if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+			tp->snd_cwnd++;
+	} else {
+		measure_rtt(tp);
+
+		/* keep track of number of round-trip times since last backoff event */
+		if (ca->snd_cwnd_cnt2++ > tp->snd_cwnd) {
+			ca->ccount++;
+			ca->snd_cwnd_cnt2 = 0;
+			htcp_alpha_update(ca);
+		}
+
+                /* In dangerous area, increase slowly.
+		 * In theory this is tp->snd_cwnd += alpha / tp->snd_cwnd
+		 */
+		if ((tp->snd_cwnd_cnt++ * ca->alpha)>>7 >= tp->snd_cwnd) {
+			if (tp->snd_cwnd < tp->snd_cwnd_clamp)
+				tp->snd_cwnd++;
+			tp->snd_cwnd_cnt = 0;
+			ca->ccount++;
+		}
+	}
+}
+
+/* Lower bound on congestion window. */
+static u32 htcp_min_cwnd(struct tcp_sock *tp)
+{
+	return tp->snd_ssthresh;
+}
+
+
+static void htcp_init(struct tcp_sock *tp)
+{
+	struct htcp *ca = tcp_ca(tp);
+
+	memset(ca, 0, sizeof(struct htcp));
+	ca->alpha = ALPHA_BASE;
+	ca->beta = BETA_MIN;
+}
+
+static void htcp_state(struct tcp_sock *tp, u8 new_state)
+{
+	switch (new_state) {
+	case TCP_CA_CWR:
+	case TCP_CA_Recovery:
+	case TCP_CA_Loss:
+		htcp_reset(tcp_ca(tp));
+		break;
+	}
+}
+
+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,
+	.pkts_acked	= measure_achieved_throughput,
+	.owner		= THIS_MODULE,
+	.name		= "htcp",
+};
+
+static int __init htcp_register(void)
+{
+	BUG_ON(sizeof(struct htcp) > TCP_CA_PRIV_SIZE);
+	BUILD_BUG_ON(BETA_MIN >= BETA_MAX);
+	if (!use_bandwidth_switch)
+		htcp.pkts_acked = NULL;
+	return tcp_register_congestion_control(&htcp);
+}
+
+static void __exit htcp_unregister(void)
+{
+	tcp_unregister_congestion_control(&htcp);
+}
+
+module_init(htcp_register);
+module_exit(htcp_unregister);
+
+MODULE_AUTHOR("Baruch Even");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("H-TCP");
diff --git a/net/ipv4/tcp_hybla.c b/net/ipv4/tcp_hybla.c
new file mode 100644
index 0000000..13a6634
--- /dev/null
+++ b/net/ipv4/tcp_hybla.c
@@ -0,0 +1,187 @@
+/*
+ * TCP HYBLA
+ *
+ * TCP-HYBLA Congestion control algorithm, based on:
+ *   C.Caini, R.Firrincieli, "TCP-Hybla: A TCP Enhancement
+ *   for Heterogeneous Networks",
+ *   International Journal on satellite Communications,
+ *				       September 2004
+ *    Daniele Lacamera
+ *    root at danielinux.net
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <net/tcp.h>
+
+/* Tcp Hybla structure. */
+struct hybla {
+	u8    hybla_en;
+	u32   snd_cwnd_cents; /* Keeps increment values when it is <1, <<7 */
+	u32   rho;	      /* Rho parameter, integer part  */
+	u32   rho2;	      /* Rho * Rho, integer part */
+	u32   rho_3ls;	      /* Rho parameter, <<3 */
+	u32   rho2_7ls;	      /* Rho^2, <<7	*/
+	u32   minrtt;	      /* Minimum smoothed round trip time value seen */
+};
+
+/* Hybla reference round trip time (default= 1/40 sec = 25 ms),
+   expressed in jiffies */
+static int rtt0 = 25;
+module_param(rtt0, int, 0644);
+MODULE_PARM_DESC(rtt0, "reference rout trip time (ms)");
+
+
+/* This is called to refresh values for hybla parameters */
+static inline void hybla_recalc_param (struct tcp_sock *tp)
+{
+	struct hybla *ca = tcp_ca(tp);
+
+	ca->rho_3ls = max_t(u32, tp->srtt / msecs_to_jiffies(rtt0), 8);
+	ca->rho = ca->rho_3ls >> 3;
+	ca->rho2_7ls = (ca->rho_3ls * ca->rho_3ls) << 1;
+	ca->rho2 = ca->rho2_7ls >>7;
+}
+
+static void hybla_init(struct tcp_sock *tp)
+{
+	struct hybla *ca = tcp_ca(tp);
+
+	ca->rho = 0;
+	ca->rho2 = 0;
+	ca->rho_3ls = 0;
+	ca->rho2_7ls = 0;
+	ca->snd_cwnd_cents = 0;
+	ca->hybla_en = 1;
+	tp->snd_cwnd = 2;
+	tp->snd_cwnd_clamp = 65535;
+
+	/* 1st Rho measurement based on initial srtt */
+	hybla_recalc_param(tp);
+
+	/* set minimum rtt as this is the 1st ever seen */
+	ca->minrtt = tp->srtt;
+	tp->snd_cwnd = ca->rho;
+}
+
+static void hybla_state(struct tcp_sock *tp, u8 ca_state)
+{
+	struct hybla *ca = tcp_ca(tp);
+
+	ca->hybla_en = (ca_state == TCP_CA_Open);
+}
+
+static inline u32 hybla_fraction(u32 odds)
+{
+	static const u32 fractions[] = {
+		128, 139, 152, 165, 181, 197, 215, 234,
+	};
+
+	return (odds < ARRAY_SIZE(fractions)) ? fractions[odds] : 128;
+}
+
+/* TCP Hybla main routine.
+ * This is the algorithm behavior:
+ *     o Recalc Hybla parameters if min_rtt has changed
+ *     o Give cwnd a new value based on the model proposed
+ *     o remember increments <1
+ */
+static void hybla_cong_avoid(struct tcp_sock *tp, u32 ack, u32 rtt,
+			    u32 in_flight, int flag)
+{
+	struct hybla *ca = tcp_ca(tp);
+	u32 increment, odd, rho_fractions;
+	int is_slowstart = 0;
+
+	/*  Recalculate rho only if this srtt is the lowest */
+	if (tp->srtt < ca->minrtt){
+		hybla_recalc_param(tp);
+		ca->minrtt = tp->srtt;
+	}
+
+	if (!ca->hybla_en)
+		return tcp_reno_cong_avoid(tp, ack, rtt, in_flight, flag);
+
+	if (in_flight < tp->snd_cwnd)
+		return;
+
+	if (ca->rho == 0)
+		hybla_recalc_param(tp);
+
+	rho_fractions = ca->rho_3ls - (ca->rho << 3);
+
+	if (tp->snd_cwnd < tp->snd_ssthresh) {
+		/*
+		 * slow start
+		 *      INC = 2^RHO - 1
+		 * This is done by splitting the rho parameter
+		 * into 2 parts: an integer part and a fraction part.
+		 * Inrement<<7 is estimated by doing:
+		 *	       [2^(int+fract)]<<7
+		 * that is equal to:
+		 *	       (2^int)	*  [(2^fract) <<7]
+		 * 2^int is straightly computed as 1<<int,
+		 * while we will use hybla_slowstart_fraction_increment() to
+		 * calculate 2^fract in a <<7 value.
+		 */
+		is_slowstart = 1;
+		increment = ((1 << ca->rho) * hybla_fraction(rho_fractions))
+			- 128;
+	} else {
+		/*
+		 * congestion avoidance
+		 * INC = RHO^2 / W
+		 * as long as increment is estimated as (rho<<7)/window
+		 * it already is <<7 and we can easily count its fractions.
+		 */
+		increment = ca->rho2_7ls / tp->snd_cwnd;
+		if (increment < 128)
+			tp->snd_cwnd_cnt++;
+	}
+
+	odd = increment % 128;
+	tp->snd_cwnd += increment >> 7;
+	ca->snd_cwnd_cents += odd;
+
+	/* check when fractions goes >=128 and increase cwnd by 1. */
+	while(ca->snd_cwnd_cents >= 128) {
+		tp->snd_cwnd++;
+		ca->snd_cwnd_cents -= 128;
+		tp->snd_cwnd_cnt = 0;
+	}
+
+	/* clamp down slowstart cwnd to ssthresh value. */
+	if (is_slowstart)
+		tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh);
+
+	tp->snd_cwnd = min_t(u32, tp->snd_cwnd, tp->snd_cwnd_clamp);
+}
+
+static struct tcp_congestion_ops tcp_hybla = {
+	.init		= hybla_init,
+	.ssthresh	= tcp_reno_ssthresh,
+	.min_cwnd	= tcp_reno_min_cwnd,
+	.cong_avoid	= hybla_cong_avoid,
+	.set_state	= hybla_state,
+
+	.owner		= THIS_MODULE,
+	.name		= "hybla"
+};
+
+static int __init hybla_register(void)
+{
+	BUG_ON(sizeof(struct hybla) > TCP_CA_PRIV_SIZE);
+	return tcp_register_congestion_control(&tcp_hybla);
+}
+
+static void __exit hybla_unregister(void)
+{
+	tcp_unregister_congestion_control(&tcp_hybla);
+}
+
+module_init(hybla_register);
+module_exit(hybla_unregister);
+
+MODULE_AUTHOR("Daniele Lacamera");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TCP Hybla");
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 5bad504..7bbbbc3 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -61,7 +61,6 @@
  *		Panu Kuhlberg:		Experimental audit of TCP (re)transmission
  *					engine. Lots of bugs are found.
  *		Pasi Sarolahti:		F-RTO for dealing with spurious RTOs
- *		Angelo Dell'Aera:	TCP Westwood+ support
  */
 
 #include <linux/config.h>
@@ -88,23 +87,9 @@
 int sysctl_tcp_max_orphans = NR_FILE;
 int sysctl_tcp_frto;
 int sysctl_tcp_nometrics_save;
-int sysctl_tcp_westwood;
-int sysctl_tcp_vegas_cong_avoid;
 
 int sysctl_tcp_moderate_rcvbuf = 1;
 
-/* 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
-int sysctl_tcp_vegas_alpha = 1<<V_PARAM_SHIFT;
-int sysctl_tcp_vegas_beta  = 3<<V_PARAM_SHIFT;
-int sysctl_tcp_vegas_gamma = 1<<V_PARAM_SHIFT;
-int sysctl_tcp_bic = 1;
-int sysctl_tcp_bic_fast_convergence = 1;
-int sysctl_tcp_bic_low_window = 14;
-int sysctl_tcp_bic_beta = 819;		/* = 819/1024 (BICTCP_BETA_SCALE) */
-
 #define FLAG_DATA		0x01 /* Incoming frame contained data.		*/
 #define FLAG_WIN_UPDATE		0x02 /* Incoming ACK was a window update.	*/
 #define FLAG_DATA_ACKED		0x04 /* This ACK acknowledged new data.		*/
@@ -333,15 +318,6 @@
 	tp->snd_cwnd_stamp = tcp_time_stamp;
 }
 
-static void init_bictcp(struct tcp_sock *tp)
-{
-	tp->bictcp.cnt = 0;
-
-	tp->bictcp.last_max_cwnd = 0;
-	tp->bictcp.last_cwnd = 0;
-	tp->bictcp.last_stamp = 0;
-}
-
 /* 5. Recalculate window clamp after socket hit its memory bounds. */
 static void tcp_clamp_window(struct sock *sk, struct tcp_sock *tp)
 {
@@ -558,45 +534,6 @@
 		tcp_grow_window(sk, tp, skb);
 }
 
-/* When starting a new connection, pin down the current choice of 
- * congestion algorithm.
- */
-void tcp_ca_init(struct tcp_sock *tp)
-{
-	if (sysctl_tcp_westwood) 
-		tp->adv_cong = TCP_WESTWOOD;
-	else if (sysctl_tcp_bic)
-		tp->adv_cong = TCP_BIC;
-	else if (sysctl_tcp_vegas_cong_avoid) {
-		tp->adv_cong = TCP_VEGAS;
-		tp->vegas.baseRTT = 0x7fffffff;
-		tcp_vegas_enable(tp);
-	} 
-}
-
-/* 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 inline void vegas_rtt_calc(struct tcp_sock *tp, __u32 rtt)
-{
-	__u32 vrtt = rtt + 1; /* Never allow zero rtt or baseRTT */
-
-	/* Filter to find propagation delay: */
-	if (vrtt < tp->vegas.baseRTT) 
-		tp->vegas.baseRTT = vrtt;
-
-	/* Find the min RTT during the last RTT to find
-	 * the current prop. delay + queuing delay:
-	 */
-	tp->vegas.minRTT = min(tp->vegas.minRTT, vrtt);
-	tp->vegas.cntRTT++;
-}
-
 /* Called to compute a smoothed rtt estimate. The data fed to this
  * routine either comes from timestamps, or from segments that were
  * known _not_ to have been retransmitted [see Karn/Partridge
@@ -606,13 +543,10 @@
  * To save cycles in the RFC 1323 implementation it was better to break
  * it up into three procedures. -- erics
  */
-static void tcp_rtt_estimator(struct tcp_sock *tp, __u32 mrtt)
+static void tcp_rtt_estimator(struct tcp_sock *tp, __u32 mrtt, u32 *usrtt)
 {
 	long m = mrtt; /* RTT */
 
-	if (tcp_vegas_enabled(tp))
-		vegas_rtt_calc(tp, mrtt);
-
 	/*	The following amusing code comes from Jacobson's
 	 *	article in SIGCOMM '88.  Note that rtt and mdev
 	 *	are scaled versions of rtt and mean deviation.
@@ -670,7 +604,8 @@
 		tp->rtt_seq = tp->snd_nxt;
 	}
 
-	tcp_westwood_update_rtt(tp, tp->srtt >> 3);
+	if (tp->ca_ops->rtt_sample)
+		tp->ca_ops->rtt_sample(tp, *usrtt);
 }
 
 /* Calculate rto without backoff.  This is the second half of Van Jacobson's
@@ -1185,8 +1120,8 @@
             tp->snd_una == tp->high_seq ||
             (tp->ca_state == TCP_CA_Loss && !tp->retransmits)) {
 		tp->prior_ssthresh = tcp_current_ssthresh(tp);
-		if (!tcp_westwood_ssthresh(tp))
-			tp->snd_ssthresh = tcp_recalc_ssthresh(tp);
+		tp->snd_ssthresh = tp->ca_ops->ssthresh(tp);
+		tcp_ca_event(tp, CA_EVENT_FRTO);
 	}
 
 	/* Have to clear retransmission markers here to keep the bookkeeping
@@ -1252,8 +1187,6 @@
 	tcp_set_ca_state(tp, TCP_CA_Loss);
 	tp->high_seq = tp->frto_highmark;
 	TCP_ECN_queue_cwr(tp);
-
-	init_bictcp(tp);
 }
 
 void tcp_clear_retrans(struct tcp_sock *tp)
@@ -1283,7 +1216,8 @@
 	if (tp->ca_state <= TCP_CA_Disorder || tp->snd_una == tp->high_seq ||
 	    (tp->ca_state == TCP_CA_Loss && !tp->retransmits)) {
 		tp->prior_ssthresh = tcp_current_ssthresh(tp);
-		tp->snd_ssthresh = tcp_recalc_ssthresh(tp);
+		tp->snd_ssthresh = tp->ca_ops->ssthresh(tp);
+		tcp_ca_event(tp, CA_EVENT_LOSS);
 	}
 	tp->snd_cwnd	   = 1;
 	tp->snd_cwnd_cnt   = 0;
@@ -1596,28 +1530,14 @@
 }
 
 /* Decrease cwnd each second ack. */
-
 static void tcp_cwnd_down(struct tcp_sock *tp)
 {
 	int decr = tp->snd_cwnd_cnt + 1;
-	__u32 limit;
-
-	/*
-	 * TCP Westwood
-	 * Here limit is evaluated as BWestimation*RTTmin (for obtaining it
-	 * in packets we use mss_cache). If sysctl_tcp_westwood is off
-	 * tcp_westwood_bw_rttmin() returns 0. In such case snd_ssthresh is
-	 * still used as usual. It prevents other strange cases in which
-	 * BWE*RTTmin could assume value 0. It should not happen but...
-	 */
-
-	if (!(limit = tcp_westwood_bw_rttmin(tp)))
-		limit = tp->snd_ssthresh/2;
 
 	tp->snd_cwnd_cnt = decr&1;
 	decr >>= 1;
 
-	if (decr && tp->snd_cwnd > limit)
+	if (decr && tp->snd_cwnd > tp->ca_ops->min_cwnd(tp))
 		tp->snd_cwnd -= decr;
 
 	tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp)+1);
@@ -1654,8 +1574,8 @@
 static void tcp_undo_cwr(struct tcp_sock *tp, int undo)
 {
 	if (tp->prior_ssthresh) {
-		if (tcp_is_bic(tp))
-			tp->snd_cwnd = max(tp->snd_cwnd, tp->bictcp.last_max_cwnd);
+		if (tp->ca_ops->undo_cwnd)
+			tp->snd_cwnd = tp->ca_ops->undo_cwnd(tp);
 		else
 			tp->snd_cwnd = max(tp->snd_cwnd, tp->snd_ssthresh<<1);
 
@@ -1767,11 +1687,9 @@
 
 static inline void tcp_complete_cwr(struct tcp_sock *tp)
 {
-	if (tcp_westwood_cwnd(tp)) 
-		tp->snd_ssthresh = tp->snd_cwnd;
-	else
-		tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh);
+	tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh);
 	tp->snd_cwnd_stamp = tcp_time_stamp;
+	tcp_ca_event(tp, CA_EVENT_COMPLETE_CWR);
 }
 
 static void tcp_try_to_open(struct sock *sk, struct tcp_sock *tp, int flag)
@@ -1946,7 +1864,7 @@
 		if (tp->ca_state < TCP_CA_CWR) {
 			if (!(flag&FLAG_ECE))
 				tp->prior_ssthresh = tcp_current_ssthresh(tp);
-			tp->snd_ssthresh = tcp_recalc_ssthresh(tp);
+			tp->snd_ssthresh = tp->ca_ops->ssthresh(tp);
 			TCP_ECN_queue_cwr(tp);
 		}
 
@@ -1963,7 +1881,7 @@
 /* Read draft-ietf-tcplw-high-performance before mucking
  * with this code. (Superceeds RFC1323)
  */
-static void tcp_ack_saw_tstamp(struct tcp_sock *tp, int flag)
+static void tcp_ack_saw_tstamp(struct tcp_sock *tp, u32 *usrtt, int flag)
 {
 	__u32 seq_rtt;
 
@@ -1983,13 +1901,13 @@
 	 * in window is lost... Voila.	 			--ANK (010210)
 	 */
 	seq_rtt = tcp_time_stamp - tp->rx_opt.rcv_tsecr;
-	tcp_rtt_estimator(tp, seq_rtt);
+	tcp_rtt_estimator(tp, seq_rtt, usrtt);
 	tcp_set_rto(tp);
 	tp->backoff = 0;
 	tcp_bound_rto(tp);
 }
 
-static void tcp_ack_no_tstamp(struct tcp_sock *tp, u32 seq_rtt, int flag)
+static void tcp_ack_no_tstamp(struct tcp_sock *tp, u32 seq_rtt, u32 *usrtt, int flag)
 {
 	/* We don't have a timestamp. Can only use
 	 * packets that are not retransmitted to determine
@@ -2003,338 +1921,29 @@
 	if (flag & FLAG_RETRANS_DATA_ACKED)
 		return;
 
-	tcp_rtt_estimator(tp, seq_rtt);
+	tcp_rtt_estimator(tp, seq_rtt, usrtt);
 	tcp_set_rto(tp);
 	tp->backoff = 0;
 	tcp_bound_rto(tp);
 }
 
 static inline void tcp_ack_update_rtt(struct tcp_sock *tp,
-				      int flag, s32 seq_rtt)
+				      int flag, s32 seq_rtt, u32 *usrtt)
 {
 	/* Note that peer MAY send zero echo. In this case it is ignored. (rfc1323) */
 	if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr)
-		tcp_ack_saw_tstamp(tp, flag);
+		tcp_ack_saw_tstamp(tp, usrtt, flag);
 	else if (seq_rtt >= 0)
-		tcp_ack_no_tstamp(tp, seq_rtt, flag);
+		tcp_ack_no_tstamp(tp, seq_rtt, usrtt, flag);
 }
 
-/*
- * Compute congestion window to use.
- *
- * This is from the implementation of BICTCP in
- * Lison-Xu, Kahaled Harfoush, and Injog Rhee.
- *  "Binary Increase Congestion Control for Fast, Long Distance
- *  Networks" in InfoComm 2004
- * Available from:
- *  http://www.csc.ncsu.edu/faculty/rhee/export/bitcp.pdf
- *
- * Unless BIC is enabled and congestion window is large
- * this behaves the same as the original Reno.
- */
-static inline __u32 bictcp_cwnd(struct tcp_sock *tp)
+static inline void tcp_cong_avoid(struct tcp_sock *tp, u32 ack, u32 rtt,
+				  u32 in_flight, int good)
 {
-	/* orignal Reno behaviour */
-	if (!tcp_is_bic(tp))
-		return tp->snd_cwnd;
-
-	if (tp->bictcp.last_cwnd == tp->snd_cwnd &&
-	   (s32)(tcp_time_stamp - tp->bictcp.last_stamp) <= (HZ>>5))
-		return tp->bictcp.cnt;
-
-	tp->bictcp.last_cwnd = tp->snd_cwnd;
-	tp->bictcp.last_stamp = tcp_time_stamp;
-      
-	/* start off normal */
-	if (tp->snd_cwnd <= sysctl_tcp_bic_low_window)
-		tp->bictcp.cnt = tp->snd_cwnd;
-
-	/* binary increase */
-	else if (tp->snd_cwnd < tp->bictcp.last_max_cwnd) {
-		__u32 	dist = (tp->bictcp.last_max_cwnd - tp->snd_cwnd)
-			/ BICTCP_B;
-
-		if (dist > BICTCP_MAX_INCREMENT)
-			/* linear increase */
-			tp->bictcp.cnt = tp->snd_cwnd / BICTCP_MAX_INCREMENT;
-		else if (dist <= 1U)
-			/* binary search increase */
-			tp->bictcp.cnt = tp->snd_cwnd * BICTCP_FUNC_OF_MIN_INCR
-				/ BICTCP_B;
-		else
-			/* binary search increase */
-			tp->bictcp.cnt = tp->snd_cwnd / dist;
-	} else {
-		/* slow start amd linear increase */
-		if (tp->snd_cwnd < tp->bictcp.last_max_cwnd + BICTCP_B)
-			/* slow start */
-			tp->bictcp.cnt = tp->snd_cwnd * BICTCP_FUNC_OF_MIN_INCR
-				/ BICTCP_B;
-		else if (tp->snd_cwnd < tp->bictcp.last_max_cwnd
-			 		+ BICTCP_MAX_INCREMENT*(BICTCP_B-1))
-			/* slow start */
-			tp->bictcp.cnt = tp->snd_cwnd * (BICTCP_B-1)
-				/ (tp->snd_cwnd-tp->bictcp.last_max_cwnd);
-		else
-			/* linear increase */
-			tp->bictcp.cnt = tp->snd_cwnd / BICTCP_MAX_INCREMENT;
-	}
-	return tp->bictcp.cnt;
-}
-
-/* This is Jacobson's slow start and congestion avoidance. 
- * SIGCOMM '88, p. 328.
- */
-static inline void reno_cong_avoid(struct tcp_sock *tp)
-{
-        if (tp->snd_cwnd <= tp->snd_ssthresh) {
-                /* In "safe" area, increase. */
-		if (tp->snd_cwnd < tp->snd_cwnd_clamp)
-			tp->snd_cwnd++;
-	} else {
-                /* In dangerous area, increase slowly.
-		 * In theory this is tp->snd_cwnd += 1 / tp->snd_cwnd
-		 */
-		if (tp->snd_cwnd_cnt >= bictcp_cwnd(tp)) {
-			if (tp->snd_cwnd < tp->snd_cwnd_clamp)
-				tp->snd_cwnd++;
-			tp->snd_cwnd_cnt=0;
-		} else
-			tp->snd_cwnd_cnt++;
-        }
+	tp->ca_ops->cong_avoid(tp, ack, rtt, in_flight, good);
 	tp->snd_cwnd_stamp = tcp_time_stamp;
 }
 
-/* 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.
- */
-static void vegas_cong_avoid(struct tcp_sock *tp, u32 ack, u32 seq_rtt)
-{
-	/* 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, tp->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.
-		 */
-		old_wnd = (tp->vegas.beg_snd_nxt - tp->vegas.beg_snd_una) /
-			tp->mss_cache_std;
-		old_snd_cwnd = tp->vegas.beg_snd_cwnd;
-
-		/* Save the extent of the current window so we can use this
-		 * at the end of the next RTT.
-		 */
-		tp->vegas.beg_snd_una  = tp->vegas.beg_snd_nxt;
-		tp->vegas.beg_snd_nxt  = tp->snd_nxt;
-		tp->vegas.beg_snd_cwnd = tp->snd_cwnd;
-
-		/* Take into account the current RTT sample too, to
-		 * decrease the impact of delayed acks. This double counts
-		 * this sample since we count it for the next window as well,
-		 * but that's not too awful, since we're taking the min,
-		 * rather than averaging.
-		 */
-		vegas_rtt_calc(tp, seq_rtt);
-
-		/* 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 (tp->vegas.cntRTT <= 2) {
-			/* We don't have enough RTT samples to do the Vegas
-			 * calculation, so we'll behave like Reno.
-			 */
-			if (tp->snd_cwnd > tp->snd_ssthresh)
-				tp->snd_cwnd++;
-		} else {
-			u32 rtt, target_cwnd, diff;
-
-			/* 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 = tp->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.
-			 */
-			target_cwnd = ((old_wnd * tp->vegas.baseRTT)
-				       << 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;
-
-			if (tp->snd_cwnd < tp->snd_ssthresh) {
-				/* Slow start.  */
-				if (diff > sysctl_tcp_vegas_gamma) {
-					/* Going too fast. Time to slow down
-					 * and switch to congestion avoidance.
-					 */
-					tp->snd_ssthresh = 2;
-
-					/* Set cwnd to match the actual rate
-					 * exactly:
-					 *   cwnd = (actual rate) * baseRTT
-					 * Then we add 1 because the integer
-					 * truncation robs us of full link
-					 * utilization.
-					 */
-					tp->snd_cwnd = min(tp->snd_cwnd,
-							   (target_cwnd >>
-							    V_PARAM_SHIFT)+1);
-
-				}
-			} else {
-				/* Congestion avoidance. */
-				u32 next_snd_cwnd;
-
-				/* Figure out where we would like cwnd
-				 * to be.
-				 */
-				if (diff > sysctl_tcp_vegas_beta) {
-					/* The old window was too fast, so
-					 * we slow down.
-					 */
-					next_snd_cwnd = old_snd_cwnd - 1;
-				} else if (diff < sysctl_tcp_vegas_alpha) {
-					/* We don't have enough extra packets
-					 * in the network, so speed up.
-					 */
-					next_snd_cwnd = old_snd_cwnd + 1;
-				} else {
-					/* Sending just as fast as we
-					 * should be.
-					 */
-					next_snd_cwnd = old_snd_cwnd;
-				}
-
-				/* Adjust cwnd upward or downward, toward the
-				 * desired value.
-				 */
-				if (next_snd_cwnd > tp->snd_cwnd)
-					tp->snd_cwnd++;
-				else if (next_snd_cwnd < tp->snd_cwnd)
-					tp->snd_cwnd--;
-			}
-		}
-
-		/* Wipe the slate clean for the next RTT. */
-		tp->vegas.cntRTT = 0;
-		tp->vegas.minRTT = 0x7fffffff;
-	}
-
-	/* The following code is executed for every ack we receive,
-	 * except for conditions checked in should_advance_cwnd()
-	 * before the call to tcp_cong_avoid(). Mainly this means that
-	 * we only execute this code if the ack actually acked some
-	 * data.
-	 */
-
-	/* If we are in slow start, increase our cwnd in response to this ACK.
-	 * (If we are not in slow start then we are in congestion avoidance,
-	 * and adjust our congestion window only once per RTT. See the code
-	 * above.)
-	 */
-	if (tp->snd_cwnd <= tp->snd_ssthresh) 
-		tp->snd_cwnd++;
-
-	/* to keep cwnd from growing without bound */
-	tp->snd_cwnd = min_t(u32, tp->snd_cwnd, tp->snd_cwnd_clamp);
-
-	/* Make sure that we are never so timid as to reduce our cwnd below
-	 * 2 MSS.
-	 *
-	 * Going below 2 MSS would risk huge delayed ACKs from our receiver.
-	 */
-	tp->snd_cwnd = max(tp->snd_cwnd, 2U);
-
-	tp->snd_cwnd_stamp = tcp_time_stamp;
-}
-
-static inline void tcp_cong_avoid(struct tcp_sock *tp, u32 ack, u32 seq_rtt)
-{
-	if (tcp_vegas_enabled(tp))
-		vegas_cong_avoid(tp, ack, seq_rtt);
-	else
-		reno_cong_avoid(tp);
-}
-
 /* Restart timer after forward progress on connection.
  * RFC2988 recommends to restart timer to now+rto.
  */
@@ -2415,13 +2024,18 @@
 
 
 /* Remove acknowledged frames from the retransmission queue. */
-static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
+static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p, s32 *seq_usrtt)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct sk_buff *skb;
 	__u32 now = tcp_time_stamp;
 	int acked = 0;
 	__s32 seq_rtt = -1;
+	struct timeval usnow;
+	u32 pkts_acked = 0;
+
+	if (seq_usrtt)
+		do_gettimeofday(&usnow);
 
 	while ((skb = skb_peek(&sk->sk_write_queue)) &&
 	       skb != sk->sk_send_head) {
@@ -2448,6 +2062,7 @@
 		 */
 		if (!(scb->flags & TCPCB_FLAG_SYN)) {
 			acked |= FLAG_DATA_ACKED;
+			++pkts_acked;
 		} else {
 			acked |= FLAG_SYN_ACKED;
 			tp->retrans_stamp = 0;
@@ -2461,6 +2076,10 @@
 				seq_rtt = -1;
 			} else if (seq_rtt < 0)
 				seq_rtt = now - scb->when;
+			if (seq_usrtt)
+				*seq_usrtt = (usnow.tv_sec - skb->stamp.tv_sec) * 1000000
+					+ (usnow.tv_usec - skb->stamp.tv_usec);
+
 			if (sacked & TCPCB_SACKED_ACKED)
 				tp->sacked_out -= tcp_skb_pcount(skb);
 			if (sacked & TCPCB_LOST)
@@ -2479,8 +2098,11 @@
 	}
 
 	if (acked&FLAG_ACKED) {
-		tcp_ack_update_rtt(tp, acked, seq_rtt);
+		tcp_ack_update_rtt(tp, acked, seq_rtt, seq_usrtt);
 		tcp_ack_packets_out(sk, tp);
+
+		if (tp->ca_ops->pkts_acked)
+			tp->ca_ops->pkts_acked(tp, pkts_acked);
 	}
 
 #if FASTRETRANS_DEBUG > 0
@@ -2624,257 +2246,6 @@
 	tp->frto_counter = (tp->frto_counter + 1) % 3;
 }
 
-/*
- * TCP Westwood+
- */
-
-/*
- * @init_westwood
- * This function initializes fields used in TCP Westwood+. We can't
- * get no information about RTTmin at this time so we simply set it to
- * TCP_WESTWOOD_INIT_RTT. This value was chosen to be too conservative
- * since in this way we're sure it will be updated in a consistent
- * way as soon as possible. It will reasonably happen within the first
- * RTT period of the connection lifetime.
- */
-
-static void init_westwood(struct sock *sk)
-{
-        struct tcp_sock *tp = tcp_sk(sk);
-
-        tp->westwood.bw_ns_est = 0;
-        tp->westwood.bw_est = 0;
-        tp->westwood.accounted = 0;
-        tp->westwood.cumul_ack = 0;
-        tp->westwood.rtt_win_sx = tcp_time_stamp;
-        tp->westwood.rtt = TCP_WESTWOOD_INIT_RTT;
-        tp->westwood.rtt_min = TCP_WESTWOOD_INIT_RTT;
-        tp->westwood.snd_una = tp->snd_una;
-}
-
-/*
- * @westwood_do_filter
- * Low-pass filter. Implemented using constant coeffients.
- */
-
-static inline __u32 westwood_do_filter(__u32 a, __u32 b)
-{
-	return (((7 * a) + b) >> 3);
-}
-
-static void westwood_filter(struct sock *sk, __u32 delta)
-{
-	struct tcp_sock *tp = tcp_sk(sk);
-
-	tp->westwood.bw_ns_est =
-		westwood_do_filter(tp->westwood.bw_ns_est, 
-				   tp->westwood.bk / delta);
-	tp->westwood.bw_est =
-		westwood_do_filter(tp->westwood.bw_est,
-				   tp->westwood.bw_ns_est);
-}
-
-/* 
- * @westwood_update_rttmin
- * It is used to update RTTmin. In this case we MUST NOT use
- * WESTWOOD_RTT_MIN minimum bound since we could be on a LAN!
- */
-
-static inline __u32 westwood_update_rttmin(const struct sock *sk)
-{
-	const struct tcp_sock *tp = tcp_sk(sk);
-	__u32 rttmin = tp->westwood.rtt_min;
-
-	if (tp->westwood.rtt != 0 &&
-	    (tp->westwood.rtt < tp->westwood.rtt_min || !rttmin))
-		rttmin = tp->westwood.rtt;
-
-	return rttmin;
-}
-
-/*
- * @westwood_acked
- * Evaluate increases for dk. 
- */
-
-static inline __u32 westwood_acked(const struct sock *sk)
-{
-	const struct tcp_sock *tp = tcp_sk(sk);
-
-	return tp->snd_una - tp->westwood.snd_una;
-}
-
-/*
- * @westwood_new_window
- * It evaluates if we are receiving data inside the same RTT window as
- * when we started.
- * Return value:
- * It returns 0 if we are still evaluating samples in the same RTT
- * window, 1 if the sample has to be considered in the next window.
- */
-
-static int westwood_new_window(const struct sock *sk)
-{
-	const struct tcp_sock *tp = tcp_sk(sk);
-	__u32 left_bound;
-	__u32 rtt;
-	int ret = 0;
-
-	left_bound = tp->westwood.rtt_win_sx;
-	rtt = max(tp->westwood.rtt, (u32) TCP_WESTWOOD_RTT_MIN);
-
-	/*
-	 * A RTT-window has passed. Be careful since if RTT is less than
-	 * 50ms we don't filter but we continue 'building the sample'.
-	 * This minimum limit was choosen since an estimation on small
-	 * time intervals is better to avoid...
-	 * Obvioulsy on a LAN we reasonably will always have
-	 * right_bound = left_bound + WESTWOOD_RTT_MIN
-         */
-
-	if ((left_bound + rtt) < tcp_time_stamp)
-		ret = 1;
-
-	return ret;
-}
-
-/*
- * @westwood_update_window
- * It updates RTT evaluation window if it is the right moment to do
- * it. If so it calls filter for evaluating bandwidth. 
- */
-
-static void __westwood_update_window(struct sock *sk, __u32 now)
-{
-	struct tcp_sock *tp = tcp_sk(sk);
-	__u32 delta = now - tp->westwood.rtt_win_sx;
-
-        if (delta) {
-		if (tp->westwood.rtt)
-			westwood_filter(sk, delta);
-
-		tp->westwood.bk = 0;
-		tp->westwood.rtt_win_sx = tcp_time_stamp;
-	}
-}
-
-
-static void westwood_update_window(struct sock *sk, __u32 now)
-{
-	if (westwood_new_window(sk)) 
-		__westwood_update_window(sk, now);
-}
-
-/*
- * @__tcp_westwood_fast_bw
- * It is called when we are in fast path. In particular it is called when
- * header prediction is successfull. In such case infact update is
- * straight forward and doesn't need any particular care.
- */
-
-static void __tcp_westwood_fast_bw(struct sock *sk, struct sk_buff *skb)
-{
-	struct tcp_sock *tp = tcp_sk(sk);
-
-	westwood_update_window(sk, tcp_time_stamp);
-
-	tp->westwood.bk += westwood_acked(sk);
-	tp->westwood.snd_una = tp->snd_una;
-	tp->westwood.rtt_min = westwood_update_rttmin(sk);
-}
-
-static inline void tcp_westwood_fast_bw(struct sock *sk, struct sk_buff *skb)
-{
-        if (tcp_is_westwood(tcp_sk(sk)))
-                __tcp_westwood_fast_bw(sk, skb);
-}
-
-
-/*
- * @westwood_dupack_update
- * It updates accounted and cumul_ack when receiving a dupack.
- */
-
-static void westwood_dupack_update(struct sock *sk)
-{
-	struct tcp_sock *tp = tcp_sk(sk);
-
-	tp->westwood.accounted += tp->mss_cache_std;
-	tp->westwood.cumul_ack = tp->mss_cache_std;
-}
-
-static inline int westwood_may_change_cumul(struct tcp_sock *tp)
-{
-	return (tp->westwood.cumul_ack > tp->mss_cache_std);
-}
-
-static inline void westwood_partial_update(struct tcp_sock *tp)
-{
-	tp->westwood.accounted -= tp->westwood.cumul_ack;
-	tp->westwood.cumul_ack = tp->mss_cache_std;
-}
-
-static inline void westwood_complete_update(struct tcp_sock *tp)
-{
-	tp->westwood.cumul_ack -= tp->westwood.accounted;
-	tp->westwood.accounted = 0;
-}
-
-/*
- * @westwood_acked_count
- * This function evaluates cumul_ack for evaluating dk in case of
- * delayed or partial acks.
- */
-
-static inline __u32 westwood_acked_count(struct sock *sk)
-{
-	struct tcp_sock *tp = tcp_sk(sk);
-
-	tp->westwood.cumul_ack = westwood_acked(sk);
-
-        /* If cumul_ack is 0 this is a dupack since it's not moving
-         * tp->snd_una.
-         */
-        if (!(tp->westwood.cumul_ack))
-                westwood_dupack_update(sk);
-
-        if (westwood_may_change_cumul(tp)) {
-		/* Partial or delayed ack */
-		if (tp->westwood.accounted >= tp->westwood.cumul_ack)
-			westwood_partial_update(tp);
-		else
-			westwood_complete_update(tp);
-	}
-
-	tp->westwood.snd_una = tp->snd_una;
-
-	return tp->westwood.cumul_ack;
-}
-
-
-/*
- * @__tcp_westwood_slow_bw
- * It is called when something is going wrong..even if there could
- * be no problems! Infact a simple delayed packet may trigger a
- * dupack. But we need to be careful in such case.
- */
-
-static void __tcp_westwood_slow_bw(struct sock *sk, struct sk_buff *skb)
-{
-	struct tcp_sock *tp = tcp_sk(sk);
-
-	westwood_update_window(sk, tcp_time_stamp);
-
-	tp->westwood.bk += westwood_acked_count(sk);
-	tp->westwood.rtt_min = westwood_update_rttmin(sk);
-}
-
-static inline void tcp_westwood_slow_bw(struct sock *sk, struct sk_buff *skb)
-{
-        if (tcp_is_westwood(tcp_sk(sk)))
-                __tcp_westwood_slow_bw(sk, skb);
-}
-
 /* This routine deals with incoming acks, but not outgoing ones. */
 static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
 {
@@ -2884,6 +2255,7 @@
 	u32 ack = TCP_SKB_CB(skb)->ack_seq;
 	u32 prior_in_flight;
 	s32 seq_rtt;
+	s32 seq_usrtt = 0;
 	int prior_packets;
 
 	/* If the ack is newer than sent or older than previous acks
@@ -2902,9 +2274,10 @@
 		 */
 		tcp_update_wl(tp, ack, ack_seq);
 		tp->snd_una = ack;
-		tcp_westwood_fast_bw(sk, skb);
 		flag |= FLAG_WIN_UPDATE;
 
+		tcp_ca_event(tp, CA_EVENT_FAST_ACK);
+
 		NET_INC_STATS_BH(LINUX_MIB_TCPHPACKS);
 	} else {
 		if (ack_seq != TCP_SKB_CB(skb)->end_seq)
@@ -2920,7 +2293,7 @@
 		if (TCP_ECN_rcv_ecn_echo(tp, skb->h.th))
 			flag |= FLAG_ECE;
 
-		tcp_westwood_slow_bw(sk,skb);
+		tcp_ca_event(tp, CA_EVENT_SLOW_ACK);
 	}
 
 	/* We passed data and got it acked, remove any soft error
@@ -2935,22 +2308,20 @@
 	prior_in_flight = tcp_packets_in_flight(tp);
 
 	/* See if we can take anything off of the retransmit queue. */
-	flag |= tcp_clean_rtx_queue(sk, &seq_rtt);
+	flag |= tcp_clean_rtx_queue(sk, &seq_rtt,
+				    tp->ca_ops->rtt_sample ? &seq_usrtt : NULL);
 
 	if (tp->frto_counter)
 		tcp_process_frto(sk, prior_snd_una);
 
 	if (tcp_ack_is_dubious(tp, flag)) {
 		/* Advanve CWND, if state allows this. */
-		if ((flag & FLAG_DATA_ACKED) &&
-		    (tcp_vegas_enabled(tp) || prior_in_flight >= tp->snd_cwnd) &&
-		    tcp_may_raise_cwnd(tp, flag))
-			tcp_cong_avoid(tp, ack, seq_rtt);
+		if ((flag & FLAG_DATA_ACKED) && tcp_may_raise_cwnd(tp, flag))
+			tcp_cong_avoid(tp, ack,  seq_rtt, prior_in_flight, 0);
 		tcp_fastretrans_alert(sk, prior_snd_una, prior_packets, flag);
 	} else {
-		if ((flag & FLAG_DATA_ACKED) && 
-		    (tcp_vegas_enabled(tp) || prior_in_flight >= tp->snd_cwnd))
-			tcp_cong_avoid(tp, ack, seq_rtt);
+		if ((flag & FLAG_DATA_ACKED))
+			tcp_cong_avoid(tp, ack, seq_rtt, prior_in_flight, 1);
 	}
 
 	if ((flag & FLAG_FORWARD_PROGRESS) || !(flag&FLAG_NOT_DUP))
@@ -4552,6 +3923,8 @@
 
 		tcp_init_metrics(sk);
 
+		tcp_init_congestion_control(tp);
+
 		/* Prevent spurious tcp_cwnd_restart() on first data
 		 * packet.
 		 */
@@ -4708,9 +4081,6 @@
 			if(tp->af_specific->conn_request(sk, skb) < 0)
 				return 1;
 
-			init_westwood(sk);
-			init_bictcp(tp);
-
 			/* Now we have several options: In theory there is 
 			 * nothing else in the frame. KA9Q has an option to 
 			 * send data with the syn, BSD accepts data with the
@@ -4732,9 +4102,6 @@
 		goto discard;
 
 	case TCP_SYN_SENT:
-		init_westwood(sk);
-		init_bictcp(tp);
-
 		queued = tcp_rcv_synsent_state_process(sk, skb, th, len);
 		if (queued >= 0)
 			return queued;
@@ -4816,7 +4183,7 @@
 				 */
 				if (tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr &&
 				    !tp->srtt)
-					tcp_ack_saw_tstamp(tp, 0);
+					tcp_ack_saw_tstamp(tp, 0, 0);
 
 				if (tp->rx_opt.tstamp_ok)
 					tp->advmss -= TCPOLEN_TSTAMP_ALIGNED;
@@ -4828,6 +4195,8 @@
 
 				tcp_init_metrics(sk);
 
+				tcp_init_congestion_control(tp);
+
 				/* Prevent spurious tcp_cwnd_restart() on
 				 * first data packet.
 				 */
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index dad98e4..ebf1123 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -36,7 +36,7 @@
  *					ACK bit.
  *		Andi Kleen :		Implemented fast path mtu discovery.
  *	     				Fixed many serious bugs in the
- *					open_request handling and moved
+ *					request_sock handling and moved
  *					most of it into the af independent code.
  *					Added tail drop and some other bugfixes.
  *					Added new listen sematics.
@@ -869,21 +869,23 @@
 	return (jhash_2words(raddr, (u32) rport, rnd) & (TCP_SYNQ_HSIZE - 1));
 }
 
-static struct open_request *tcp_v4_search_req(struct tcp_sock *tp,
-					      struct open_request ***prevp,
+static struct request_sock *tcp_v4_search_req(struct tcp_sock *tp,
+					      struct request_sock ***prevp,
 					      __u16 rport,
 					      __u32 raddr, __u32 laddr)
 {
-	struct tcp_listen_opt *lopt = tp->listen_opt;
-	struct open_request *req, **prev;
+	struct listen_sock *lopt = tp->accept_queue.listen_opt;
+	struct request_sock *req, **prev;
 
 	for (prev = &lopt->syn_table[tcp_v4_synq_hash(raddr, rport, lopt->hash_rnd)];
 	     (req = *prev) != NULL;
 	     prev = &req->dl_next) {
-		if (req->rmt_port == rport &&
-		    req->af.v4_req.rmt_addr == raddr &&
-		    req->af.v4_req.loc_addr == laddr &&
-		    TCP_INET_FAMILY(req->class->family)) {
+		const struct inet_request_sock *ireq = inet_rsk(req);
+
+		if (ireq->rmt_port == rport &&
+		    ireq->rmt_addr == raddr &&
+		    ireq->loc_addr == laddr &&
+		    TCP_INET_FAMILY(req->rsk_ops->family)) {
 			BUG_TRAP(!req->sk);
 			*prevp = prev;
 			break;
@@ -893,21 +895,13 @@
 	return req;
 }
 
-static void tcp_v4_synq_add(struct sock *sk, struct open_request *req)
+static void tcp_v4_synq_add(struct sock *sk, struct request_sock *req)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
-	struct tcp_listen_opt *lopt = tp->listen_opt;
-	u32 h = tcp_v4_synq_hash(req->af.v4_req.rmt_addr, req->rmt_port, lopt->hash_rnd);
+	struct listen_sock *lopt = tp->accept_queue.listen_opt;
+	u32 h = tcp_v4_synq_hash(inet_rsk(req)->rmt_addr, inet_rsk(req)->rmt_port, lopt->hash_rnd);
 
-	req->expires = jiffies + TCP_TIMEOUT_INIT;
-	req->retrans = 0;
-	req->sk = NULL;
-	req->dl_next = lopt->syn_table[h];
-
-	write_lock(&tp->syn_wait_lock);
-	lopt->syn_table[h] = req;
-	write_unlock(&tp->syn_wait_lock);
-
+	reqsk_queue_hash_req(&tp->accept_queue, h, req, TCP_TIMEOUT_INIT);
 	tcp_synq_added(sk);
 }
 
@@ -1050,7 +1044,7 @@
 	}
 
 	switch (sk->sk_state) {
-		struct open_request *req, **prev;
+		struct request_sock *req, **prev;
 	case TCP_LISTEN:
 		if (sock_owned_by_user(sk))
 			goto out;
@@ -1065,7 +1059,7 @@
 		 */
 		BUG_TRAP(!req->sk);
 
-		if (seq != req->snt_isn) {
+		if (seq != tcp_rsk(req)->snt_isn) {
 			NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
 			goto out;
 		}
@@ -1254,28 +1248,29 @@
 	tcp_tw_put(tw);
 }
 
-static void tcp_v4_or_send_ack(struct sk_buff *skb, struct open_request *req)
+static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req)
 {
-	tcp_v4_send_ack(skb, req->snt_isn + 1, req->rcv_isn + 1, req->rcv_wnd,
+	tcp_v4_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd,
 			req->ts_recent);
 }
 
 static struct dst_entry* tcp_v4_route_req(struct sock *sk,
-					  struct open_request *req)
+					  struct request_sock *req)
 {
 	struct rtable *rt;
-	struct ip_options *opt = req->af.v4_req.opt;
+	const struct inet_request_sock *ireq = inet_rsk(req);
+	struct ip_options *opt = inet_rsk(req)->opt;
 	struct flowi fl = { .oif = sk->sk_bound_dev_if,
 			    .nl_u = { .ip4_u =
 				      { .daddr = ((opt && opt->srr) ?
 						  opt->faddr :
-						  req->af.v4_req.rmt_addr),
-					.saddr = req->af.v4_req.loc_addr,
+						  ireq->rmt_addr),
+					.saddr = ireq->loc_addr,
 					.tos = RT_CONN_FLAGS(sk) } },
 			    .proto = IPPROTO_TCP,
 			    .uli_u = { .ports =
 				       { .sport = inet_sk(sk)->sport,
-					 .dport = req->rmt_port } } };
+					 .dport = ireq->rmt_port } } };
 
 	if (ip_route_output_flow(&rt, &fl, sk, 0)) {
 		IP_INC_STATS_BH(IPSTATS_MIB_OUTNOROUTES);
@@ -1291,12 +1286,13 @@
 
 /*
  *	Send a SYN-ACK after having received an ACK.
- *	This still operates on a open_request only, not on a big
+ *	This still operates on a request_sock only, not on a big
  *	socket.
  */
-static int tcp_v4_send_synack(struct sock *sk, struct open_request *req,
+static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req,
 			      struct dst_entry *dst)
 {
+	const struct inet_request_sock *ireq = inet_rsk(req);
 	int err = -1;
 	struct sk_buff * skb;
 
@@ -1310,14 +1306,14 @@
 		struct tcphdr *th = skb->h.th;
 
 		th->check = tcp_v4_check(th, skb->len,
-					 req->af.v4_req.loc_addr,
-					 req->af.v4_req.rmt_addr,
+					 ireq->loc_addr,
+					 ireq->rmt_addr,
 					 csum_partial((char *)th, skb->len,
 						      skb->csum));
 
-		err = ip_build_and_send_pkt(skb, sk, req->af.v4_req.loc_addr,
-					    req->af.v4_req.rmt_addr,
-					    req->af.v4_req.opt);
+		err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr,
+					    ireq->rmt_addr,
+					    ireq->opt);
 		if (err == NET_XMIT_CN)
 			err = 0;
 	}
@@ -1328,12 +1324,12 @@
 }
 
 /*
- *	IPv4 open_request destructor.
+ *	IPv4 request_sock destructor.
  */
-static void tcp_v4_or_free(struct open_request *req)
+static void tcp_v4_reqsk_destructor(struct request_sock *req)
 {
-	if (req->af.v4_req.opt)
-		kfree(req->af.v4_req.opt);
+	if (inet_rsk(req)->opt)
+		kfree(inet_rsk(req)->opt);
 }
 
 static inline void syn_flood_warning(struct sk_buff *skb)
@@ -1349,7 +1345,7 @@
 }
 
 /*
- * Save and compile IPv4 options into the open_request if needed.
+ * Save and compile IPv4 options into the request_sock if needed.
  */
 static inline struct ip_options *tcp_v4_save_options(struct sock *sk,
 						     struct sk_buff *skb)
@@ -1370,33 +1366,20 @@
 	return dopt;
 }
 
-/*
- * Maximum number of SYN_RECV sockets in queue per LISTEN socket.
- * One SYN_RECV socket costs about 80bytes on a 32bit machine.
- * It would be better to replace it with a global counter for all sockets
- * but then some measure against one socket starving all other sockets
- * would be needed.
- *
- * It was 128 by default. Experiments with real servers show, that
- * it is absolutely not enough even at 100conn/sec. 256 cures most
- * of problems. This value is adjusted to 128 for very small machines
- * (<=32Mb of memory) and to 1024 on normal or better ones (>=256Mb).
- * Further increasing requires to change hash table size.
- */
-int sysctl_max_syn_backlog = 256;
-
-struct or_calltable or_ipv4 = {
+struct request_sock_ops tcp_request_sock_ops = {
 	.family		=	PF_INET,
+	.obj_size	=	sizeof(struct tcp_request_sock),
 	.rtx_syn_ack	=	tcp_v4_send_synack,
-	.send_ack	=	tcp_v4_or_send_ack,
-	.destructor	=	tcp_v4_or_free,
+	.send_ack	=	tcp_v4_reqsk_send_ack,
+	.destructor	=	tcp_v4_reqsk_destructor,
 	.send_reset	=	tcp_v4_send_reset,
 };
 
 int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 {
+	struct inet_request_sock *ireq;
 	struct tcp_options_received tmp_opt;
-	struct open_request *req;
+	struct request_sock *req;
 	__u32 saddr = skb->nh.iph->saddr;
 	__u32 daddr = skb->nh.iph->daddr;
 	__u32 isn = TCP_SKB_CB(skb)->when;
@@ -1433,7 +1416,7 @@
 	if (sk_acceptq_is_full(sk) && tcp_synq_young(sk) > 1)
 		goto drop;
 
-	req = tcp_openreq_alloc();
+	req = reqsk_alloc(&tcp_request_sock_ops);
 	if (!req)
 		goto drop;
 
@@ -1461,10 +1444,10 @@
 
 	tcp_openreq_init(req, &tmp_opt, skb);
 
-	req->af.v4_req.loc_addr = daddr;
-	req->af.v4_req.rmt_addr = saddr;
-	req->af.v4_req.opt = tcp_v4_save_options(sk, skb);
-	req->class = &or_ipv4;
+	ireq = inet_rsk(req);
+	ireq->loc_addr = daddr;
+	ireq->rmt_addr = saddr;
+	ireq->opt = tcp_v4_save_options(sk, skb);
 	if (!want_cookie)
 		TCP_ECN_create_request(req, skb->h.th);
 
@@ -1523,20 +1506,20 @@
 
 		isn = tcp_v4_init_sequence(sk, skb);
 	}
-	req->snt_isn = isn;
+	tcp_rsk(req)->snt_isn = isn;
 
 	if (tcp_v4_send_synack(sk, req, dst))
 		goto drop_and_free;
 
 	if (want_cookie) {
-	   	tcp_openreq_free(req);
+	   	reqsk_free(req);
 	} else {
 		tcp_v4_synq_add(sk, req);
 	}
 	return 0;
 
 drop_and_free:
-	tcp_openreq_free(req);
+	reqsk_free(req);
 drop:
 	TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS);
 	return 0;
@@ -1548,9 +1531,10 @@
  * now create the new socket.
  */
 struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
-				  struct open_request *req,
+				  struct request_sock *req,
 				  struct dst_entry *dst)
 {
+	struct inet_request_sock *ireq;
 	struct inet_sock *newinet;
 	struct tcp_sock *newtp;
 	struct sock *newsk;
@@ -1570,11 +1554,12 @@
 
 	newtp		      = tcp_sk(newsk);
 	newinet		      = inet_sk(newsk);
-	newinet->daddr	      = req->af.v4_req.rmt_addr;
-	newinet->rcv_saddr    = req->af.v4_req.loc_addr;
-	newinet->saddr	      = req->af.v4_req.loc_addr;
-	newinet->opt	      = req->af.v4_req.opt;
-	req->af.v4_req.opt    = NULL;
+	ireq		      = inet_rsk(req);
+	newinet->daddr	      = ireq->rmt_addr;
+	newinet->rcv_saddr    = ireq->loc_addr;
+	newinet->saddr	      = ireq->loc_addr;
+	newinet->opt	      = ireq->opt;
+	ireq->opt	      = NULL;
 	newinet->mc_index     = tcp_v4_iif(skb);
 	newinet->mc_ttl	      = skb->nh.iph->ttl;
 	newtp->ext_header_len = 0;
@@ -1605,9 +1590,9 @@
 	struct iphdr *iph = skb->nh.iph;
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct sock *nsk;
-	struct open_request **prev;
+	struct request_sock **prev;
 	/* Find possible connection requests. */
-	struct open_request *req = tcp_v4_search_req(tp, &prev, th->source,
+	struct request_sock *req = tcp_v4_search_req(tp, &prev, th->source,
 						     iph->saddr, iph->daddr);
 	if (req)
 		return tcp_check_req(sk, skb, req, prev);
@@ -2063,6 +2048,7 @@
 	tp->mss_cache_std = tp->mss_cache = 536;
 
 	tp->reordering = sysctl_tcp_reordering;
+	tp->ca_ops = &tcp_init_congestion_ops;
 
 	sk->sk_state = TCP_CLOSE;
 
@@ -2085,6 +2071,8 @@
 
 	tcp_clear_xmit_timers(sk);
 
+	tcp_cleanup_congestion_control(tp);
+
 	/* Cleanup up the write buffer. */
   	sk_stream_writequeue_purge(sk);
 
@@ -2144,13 +2132,13 @@
 	++st->num;
 
 	if (st->state == TCP_SEQ_STATE_OPENREQ) {
-		struct open_request *req = cur;
+		struct request_sock *req = cur;
 
 	       	tp = tcp_sk(st->syn_wait_sk);
 		req = req->dl_next;
 		while (1) {
 			while (req) {
-				if (req->class->family == st->family) {
+				if (req->rsk_ops->family == st->family) {
 					cur = req;
 					goto out;
 				}
@@ -2159,17 +2147,17 @@
 			if (++st->sbucket >= TCP_SYNQ_HSIZE)
 				break;
 get_req:
-			req = tp->listen_opt->syn_table[st->sbucket];
+			req = tp->accept_queue.listen_opt->syn_table[st->sbucket];
 		}
 		sk	  = sk_next(st->syn_wait_sk);
 		st->state = TCP_SEQ_STATE_LISTENING;
-		read_unlock_bh(&tp->syn_wait_lock);
+		read_unlock_bh(&tp->accept_queue.syn_wait_lock);
 	} else {
 	       	tp = tcp_sk(sk);
-		read_lock_bh(&tp->syn_wait_lock);
-		if (tp->listen_opt && tp->listen_opt->qlen)
+		read_lock_bh(&tp->accept_queue.syn_wait_lock);
+		if (reqsk_queue_len(&tp->accept_queue))
 			goto start_req;
-		read_unlock_bh(&tp->syn_wait_lock);
+		read_unlock_bh(&tp->accept_queue.syn_wait_lock);
 		sk = sk_next(sk);
 	}
 get_sk:
@@ -2179,8 +2167,8 @@
 			goto out;
 		}
 	       	tp = tcp_sk(sk);
-		read_lock_bh(&tp->syn_wait_lock);
-		if (tp->listen_opt && tp->listen_opt->qlen) {
+		read_lock_bh(&tp->accept_queue.syn_wait_lock);
+		if (reqsk_queue_len(&tp->accept_queue)) {
 start_req:
 			st->uid		= sock_i_uid(sk);
 			st->syn_wait_sk = sk;
@@ -2188,7 +2176,7 @@
 			st->sbucket	= 0;
 			goto get_req;
 		}
-		read_unlock_bh(&tp->syn_wait_lock);
+		read_unlock_bh(&tp->accept_queue.syn_wait_lock);
 	}
 	if (++st->bucket < TCP_LHTABLE_SIZE) {
 		sk = sk_head(&tcp_listening_hash[st->bucket]);
@@ -2375,7 +2363,7 @@
 	case TCP_SEQ_STATE_OPENREQ:
 		if (v) {
 			struct tcp_sock *tp = tcp_sk(st->syn_wait_sk);
-			read_unlock_bh(&tp->syn_wait_lock);
+			read_unlock_bh(&tp->accept_queue.syn_wait_lock);
 		}
 	case TCP_SEQ_STATE_LISTENING:
 		if (v != SEQ_START_TOKEN)
@@ -2451,18 +2439,19 @@
 	memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops)); 
 }
 
-static void get_openreq4(struct sock *sk, struct open_request *req,
+static void get_openreq4(struct sock *sk, struct request_sock *req,
 			 char *tmpbuf, int i, int uid)
 {
+	const struct inet_request_sock *ireq = inet_rsk(req);
 	int ttd = req->expires - jiffies;
 
 	sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
 		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %p",
 		i,
-		req->af.v4_req.loc_addr,
+		ireq->loc_addr,
 		ntohs(inet_sk(sk)->sport),
-		req->af.v4_req.rmt_addr,
-		ntohs(req->rmt_port),
+		ireq->rmt_addr,
+		ntohs(ireq->rmt_port),
 		TCP_SYN_RECV,
 		0, 0, /* could print option size, but that is af dependent. */
 		1,    /* timers active (only the expire timer) */
@@ -2618,6 +2607,7 @@
 	.sysctl_rmem		= sysctl_tcp_rmem,
 	.max_header		= MAX_TCP_HEADER,
 	.obj_size		= sizeof(struct tcp_sock),
+	.rsk_prot		= &tcp_request_sock_ops,
 };
 
 
@@ -2660,7 +2650,6 @@
 EXPORT_SYMBOL(tcp_proc_unregister);
 #endif
 EXPORT_SYMBOL(sysctl_local_port_range);
-EXPORT_SYMBOL(sysctl_max_syn_backlog);
 EXPORT_SYMBOL(sysctl_tcp_low_latency);
 EXPORT_SYMBOL(sysctl_tcp_tw_reuse);
 
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index eea1a17..f42a284 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -684,7 +684,7 @@
  * Actually, we could lots of memory writes here. tp of listening
  * socket contains all necessary default parameters.
  */
-struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req, struct sk_buff *skb)
+struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, struct sk_buff *skb)
 {
 	/* allocate the newsk from the same slab of the master sock,
 	 * if not, at sk_free time we'll try to free it from the wrong
@@ -692,6 +692,8 @@
 	struct sock *newsk = sk_alloc(PF_INET, GFP_ATOMIC, sk->sk_prot, 0);
 
 	if(newsk != NULL) {
+		struct inet_request_sock *ireq = inet_rsk(req);
+		struct tcp_request_sock *treq = tcp_rsk(req);
 		struct tcp_sock *newtp;
 		struct sk_filter *filter;
 
@@ -703,7 +705,7 @@
 		tcp_sk(newsk)->bind_hash = NULL;
 
 		/* Clone the TCP header template */
-		inet_sk(newsk)->dport = req->rmt_port;
+		inet_sk(newsk)->dport = ireq->rmt_port;
 
 		sock_lock_init(newsk);
 		bh_lock_sock(newsk);
@@ -739,14 +741,14 @@
 		/* Now setup tcp_sock */
 		newtp = tcp_sk(newsk);
 		newtp->pred_flags = 0;
-		newtp->rcv_nxt = req->rcv_isn + 1;
-		newtp->snd_nxt = req->snt_isn + 1;
-		newtp->snd_una = req->snt_isn + 1;
-		newtp->snd_sml = req->snt_isn + 1;
+		newtp->rcv_nxt = treq->rcv_isn + 1;
+		newtp->snd_nxt = treq->snt_isn + 1;
+		newtp->snd_una = treq->snt_isn + 1;
+		newtp->snd_sml = treq->snt_isn + 1;
 
 		tcp_prequeue_init(newtp);
 
-		tcp_init_wl(newtp, req->snt_isn, req->rcv_isn);
+		tcp_init_wl(newtp, treq->snt_isn, treq->rcv_isn);
 
 		newtp->retransmits = 0;
 		newtp->backoff = 0;
@@ -772,13 +774,15 @@
 		newtp->frto_counter = 0;
 		newtp->frto_highmark = 0;
 
+		newtp->ca_ops = &tcp_reno;
+
 		tcp_set_ca_state(newtp, TCP_CA_Open);
 		tcp_init_xmit_timers(newsk);
 		skb_queue_head_init(&newtp->out_of_order_queue);
-		newtp->rcv_wup = req->rcv_isn + 1;
-		newtp->write_seq = req->snt_isn + 1;
+		newtp->rcv_wup = treq->rcv_isn + 1;
+		newtp->write_seq = treq->snt_isn + 1;
 		newtp->pushed_seq = newtp->write_seq;
-		newtp->copied_seq = req->rcv_isn + 1;
+		newtp->copied_seq = treq->rcv_isn + 1;
 
 		newtp->rx_opt.saw_tstamp = 0;
 
@@ -788,10 +792,8 @@
 		newtp->probes_out = 0;
 		newtp->rx_opt.num_sacks = 0;
 		newtp->urg_data = 0;
-		newtp->listen_opt = NULL;
-		newtp->accept_queue = newtp->accept_queue_tail = NULL;
-		/* Deinitialize syn_wait_lock to trap illegal accesses. */
-		memset(&newtp->syn_wait_lock, 0, sizeof(newtp->syn_wait_lock));
+		/* Deinitialize accept_queue to trap illegal accesses. */
+		memset(&newtp->accept_queue, 0, sizeof(newtp->accept_queue));
 
 		/* Back to base struct sock members. */
 		newsk->sk_err = 0;
@@ -808,18 +810,18 @@
 		newsk->sk_socket = NULL;
 		newsk->sk_sleep = NULL;
 
-		newtp->rx_opt.tstamp_ok = req->tstamp_ok;
-		if((newtp->rx_opt.sack_ok = req->sack_ok) != 0) {
+		newtp->rx_opt.tstamp_ok = ireq->tstamp_ok;
+		if((newtp->rx_opt.sack_ok = ireq->sack_ok) != 0) {
 			if (sysctl_tcp_fack)
 				newtp->rx_opt.sack_ok |= 2;
 		}
 		newtp->window_clamp = req->window_clamp;
 		newtp->rcv_ssthresh = req->rcv_wnd;
 		newtp->rcv_wnd = req->rcv_wnd;
-		newtp->rx_opt.wscale_ok = req->wscale_ok;
+		newtp->rx_opt.wscale_ok = ireq->wscale_ok;
 		if (newtp->rx_opt.wscale_ok) {
-			newtp->rx_opt.snd_wscale = req->snd_wscale;
-			newtp->rx_opt.rcv_wscale = req->rcv_wscale;
+			newtp->rx_opt.snd_wscale = ireq->snd_wscale;
+			newtp->rx_opt.rcv_wscale = ireq->rcv_wscale;
 		} else {
 			newtp->rx_opt.snd_wscale = newtp->rx_opt.rcv_wscale = 0;
 			newtp->window_clamp = min(newtp->window_clamp, 65535U);
@@ -842,8 +844,6 @@
 		if (newtp->ecn_flags&TCP_ECN_OK)
 			sock_set_flag(newsk, SOCK_NO_LARGESEND);
 
-		tcp_ca_init(newtp);
-
 		TCP_INC_STATS_BH(TCP_MIB_PASSIVEOPENS);
 	}
 	return newsk;
@@ -851,12 +851,12 @@
 
 /* 
  *	Process an incoming packet for SYN_RECV sockets represented
- *	as an open_request.
+ *	as a request_sock.
  */
 
 struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb,
-			   struct open_request *req,
-			   struct open_request **prev)
+			   struct request_sock *req,
+			   struct request_sock **prev)
 {
 	struct tcphdr *th = skb->h.th;
 	struct tcp_sock *tp = tcp_sk(sk);
@@ -881,7 +881,7 @@
 	}
 
 	/* Check for pure retransmitted SYN. */
-	if (TCP_SKB_CB(skb)->seq == req->rcv_isn &&
+	if (TCP_SKB_CB(skb)->seq == tcp_rsk(req)->rcv_isn &&
 	    flg == TCP_FLAG_SYN &&
 	    !paws_reject) {
 		/*
@@ -901,7 +901,7 @@
 		 * Enforce "SYN-ACK" according to figure 8, figure 6
 		 * of RFC793, fixed by RFC1122.
 		 */
-		req->class->rtx_syn_ack(sk, req, NULL);
+		req->rsk_ops->rtx_syn_ack(sk, req, NULL);
 		return NULL;
 	}
 
@@ -959,7 +959,7 @@
 	 * Invalid ACK: reset will be sent by listening socket
 	 */
 	if ((flg & TCP_FLAG_ACK) &&
-	    (TCP_SKB_CB(skb)->ack_seq != req->snt_isn+1))
+	    (TCP_SKB_CB(skb)->ack_seq != tcp_rsk(req)->snt_isn + 1))
 		return sk;
 
 	/* Also, it would be not so bad idea to check rcv_tsecr, which
@@ -970,10 +970,10 @@
 	/* RFC793: "first check sequence number". */
 
 	if (paws_reject || !tcp_in_window(TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq,
-					  req->rcv_isn+1, req->rcv_isn+1+req->rcv_wnd)) {
+					  tcp_rsk(req)->rcv_isn + 1, tcp_rsk(req)->rcv_isn + 1 + req->rcv_wnd)) {
 		/* Out of window: send ACK and drop. */
 		if (!(flg & TCP_FLAG_RST))
-			req->class->send_ack(skb, req);
+			req->rsk_ops->send_ack(skb, req);
 		if (paws_reject)
 			NET_INC_STATS_BH(LINUX_MIB_PAWSESTABREJECTED);
 		return NULL;
@@ -981,12 +981,12 @@
 
 	/* In sequence, PAWS is OK. */
 
-	if (tmp_opt.saw_tstamp && !after(TCP_SKB_CB(skb)->seq, req->rcv_isn+1))
+	if (tmp_opt.saw_tstamp && !after(TCP_SKB_CB(skb)->seq, tcp_rsk(req)->rcv_isn + 1))
 			req->ts_recent = tmp_opt.rcv_tsval;
 
-		if (TCP_SKB_CB(skb)->seq == req->rcv_isn) {
+		if (TCP_SKB_CB(skb)->seq == tcp_rsk(req)->rcv_isn) {
 			/* Truncate SYN, it is out of window starting
-			   at req->rcv_isn+1. */
+			   at tcp_rsk(req)->rcv_isn + 1. */
 			flg &= ~TCP_FLAG_SYN;
 		}
 
@@ -1003,8 +1003,8 @@
 			return NULL;
 
 		/* If TCP_DEFER_ACCEPT is set, drop bare ACK. */
-		if (tp->defer_accept && TCP_SKB_CB(skb)->end_seq == req->rcv_isn+1) {
-			req->acked = 1;
+		if (tp->defer_accept && TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) {
+			inet_rsk(req)->acked = 1;
 			return NULL;
 		}
 
@@ -1026,14 +1026,14 @@
 
 	listen_overflow:
 		if (!sysctl_tcp_abort_on_overflow) {
-			req->acked = 1;
+			inet_rsk(req)->acked = 1;
 			return NULL;
 		}
 
 	embryonic_reset:
 		NET_INC_STATS_BH(LINUX_MIB_EMBRYONICRSTS);
 		if (!(flg & TCP_FLAG_RST))
-			req->class->send_reset(skb);
+			req->rsk_ops->send_reset(skb);
 
 		tcp_synq_drop(sk, req, prev);
 		return NULL;
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index fa24e7a..0e17c24 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -111,8 +111,7 @@
 	u32 restart_cwnd = tcp_init_cwnd(tp, dst);
 	u32 cwnd = tp->snd_cwnd;
 
-	if (tcp_is_vegas(tp)) 
-		tcp_vegas_enable(tp);
+	tcp_ca_event(tp, CA_EVENT_CWND_RESTART);
 
 	tp->snd_ssthresh = tcp_current_ssthresh(tp);
 	restart_cwnd = min(restart_cwnd, cwnd);
@@ -280,6 +279,10 @@
 #define SYSCTL_FLAG_WSCALE	0x2
 #define SYSCTL_FLAG_SACK	0x4
 
+		/* If congestion control is doing timestamping */
+		if (tp->ca_ops->rtt_sample)
+			do_gettimeofday(&skb->stamp);
+
 		sysctl_flags = 0;
 		if (tcb->flags & TCPCB_FLAG_SYN) {
 			tcp_header_size = sizeof(struct tcphdr) + TCPOLEN_MSS;
@@ -304,17 +307,8 @@
 					    (tp->rx_opt.eff_sacks * TCPOLEN_SACK_PERBLOCK));
 		}
 		
-		/*
-		 * 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.
-		 */
-		if (tcp_is_vegas(tp) && tcp_packets_in_flight(tp) == 0)
-			tcp_vegas_enable(tp);
+		if (tcp_packets_in_flight(tp) == 0)
+			tcp_ca_event(tp, CA_EVENT_TX_START);
 
 		th = (struct tcphdr *) skb_push(skb, tcp_header_size);
 		skb->h.th = th;
@@ -521,6 +515,7 @@
 	 * skbs, which it never sent before. --ANK
 	 */
 	TCP_SKB_CB(buff)->when = TCP_SKB_CB(skb)->when;
+	buff->stamp = skb->stamp;
 
 	if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) {
 		tp->lost_out -= tcp_skb_pcount(skb);
@@ -1356,8 +1351,9 @@
  * Prepare a SYN-ACK.
  */
 struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst,
-				 struct open_request *req)
+				 struct request_sock *req)
 {
+	struct inet_request_sock *ireq = inet_rsk(req);
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct tcphdr *th;
 	int tcp_header_size;
@@ -1373,47 +1369,47 @@
 	skb->dst = dst_clone(dst);
 
 	tcp_header_size = (sizeof(struct tcphdr) + TCPOLEN_MSS +
-			   (req->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0) +
-			   (req->wscale_ok ? TCPOLEN_WSCALE_ALIGNED : 0) +
+			   (ireq->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0) +
+			   (ireq->wscale_ok ? TCPOLEN_WSCALE_ALIGNED : 0) +
 			   /* SACK_PERM is in the place of NOP NOP of TS */
-			   ((req->sack_ok && !req->tstamp_ok) ? TCPOLEN_SACKPERM_ALIGNED : 0));
+			   ((ireq->sack_ok && !ireq->tstamp_ok) ? TCPOLEN_SACKPERM_ALIGNED : 0));
 	skb->h.th = th = (struct tcphdr *) skb_push(skb, tcp_header_size);
 
 	memset(th, 0, sizeof(struct tcphdr));
 	th->syn = 1;
 	th->ack = 1;
 	if (dst->dev->features&NETIF_F_TSO)
-		req->ecn_ok = 0;
+		ireq->ecn_ok = 0;
 	TCP_ECN_make_synack(req, th);
 	th->source = inet_sk(sk)->sport;
-	th->dest = req->rmt_port;
-	TCP_SKB_CB(skb)->seq = req->snt_isn;
+	th->dest = ireq->rmt_port;
+	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;
 	th->seq = htonl(TCP_SKB_CB(skb)->seq);
-	th->ack_seq = htonl(req->rcv_isn + 1);
+	th->ack_seq = htonl(tcp_rsk(req)->rcv_isn + 1);
 	if (req->rcv_wnd == 0) { /* ignored for retransmitted syns */
 		__u8 rcv_wscale; 
 		/* Set this up on the first call only */
 		req->window_clamp = tp->window_clamp ? : dst_metric(dst, RTAX_WINDOW);
 		/* tcp_full_space because it is guaranteed to be the first packet */
 		tcp_select_initial_window(tcp_full_space(sk), 
-			dst_metric(dst, RTAX_ADVMSS) - (req->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0),
+			dst_metric(dst, RTAX_ADVMSS) - (ireq->tstamp_ok ? TCPOLEN_TSTAMP_ALIGNED : 0),
 			&req->rcv_wnd,
 			&req->window_clamp,
-			req->wscale_ok,
+			ireq->wscale_ok,
 			&rcv_wscale);
-		req->rcv_wscale = rcv_wscale; 
+		ireq->rcv_wscale = rcv_wscale; 
 	}
 
 	/* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */
 	th->window = htons(req->rcv_wnd);
 
 	TCP_SKB_CB(skb)->when = tcp_time_stamp;
-	tcp_syn_build_options((__u32 *)(th + 1), dst_metric(dst, RTAX_ADVMSS), req->tstamp_ok,
-			      req->sack_ok, req->wscale_ok, req->rcv_wscale,
+	tcp_syn_build_options((__u32 *)(th + 1), dst_metric(dst, RTAX_ADVMSS), ireq->tstamp_ok,
+			      ireq->sack_ok, ireq->wscale_ok, ireq->rcv_wscale,
 			      TCP_SKB_CB(skb)->when,
 			      req->ts_recent);
 
@@ -1448,7 +1444,6 @@
 		tp->window_clamp = dst_metric(dst, RTAX_WINDOW);
 	tp->advmss = dst_metric(dst, RTAX_ADVMSS);
 	tcp_initialize_rcv_mss(sk);
-	tcp_ca_init(tp);
 
 	tcp_select_initial_window(tcp_full_space(sk),
 				  tp->advmss - (tp->rx_opt.ts_recent_stamp ? tp->tcp_header_len - sizeof(struct tcphdr) : 0),
@@ -1502,7 +1497,6 @@
 	TCP_SKB_CB(buff)->end_seq = tp->write_seq;
 	tp->snd_nxt = tp->write_seq;
 	tp->pushed_seq = tp->write_seq;
-	tcp_ca_init(tp);
 
 	/* Send it off. */
 	TCP_SKB_CB(buff)->when = tcp_time_stamp;
diff --git a/net/ipv4/tcp_scalable.c b/net/ipv4/tcp_scalable.c
new file mode 100644
index 0000000..70e108e
--- /dev/null
+++ b/net/ipv4/tcp_scalable.c
@@ -0,0 +1,68 @@
+/* Tom Kelly's Scalable TCP
+ *
+ * See htt://www-lce.eng.cam.ac.uk/~ctk21/scalable/
+ *
+ * John Heffner <jheffner@sc.edu>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <net/tcp.h>
+
+/* These factors derived from the recommended values in the aer:
+ * .01 and and 7/8. We use 50 instead of 100 to account for
+ * delayed ack.
+ */
+#define TCP_SCALABLE_AI_CNT	50U
+#define TCP_SCALABLE_MD_SCALE	3
+
+static void tcp_scalable_cong_avoid(struct tcp_sock *tp, u32 ack, u32 rtt,
+				    u32 in_flight, int flag)
+{
+	if (in_flight < tp->snd_cwnd)
+		return;
+
+	if (tp->snd_cwnd <= tp->snd_ssthresh) {
+		tp->snd_cwnd++;
+	} else {
+		tp->snd_cwnd_cnt++;
+		if (tp->snd_cwnd_cnt > min(tp->snd_cwnd, TCP_SCALABLE_AI_CNT)){
+			tp->snd_cwnd++;
+			tp->snd_cwnd_cnt = 0;
+		}
+	}
+	tp->snd_cwnd = min_t(u32, tp->snd_cwnd, tp->snd_cwnd_clamp);
+	tp->snd_cwnd_stamp = tcp_time_stamp;
+}
+
+static u32 tcp_scalable_ssthresh(struct tcp_sock *tp)
+{
+	return max(tp->snd_cwnd - (tp->snd_cwnd>>TCP_SCALABLE_MD_SCALE), 2U);
+}
+
+
+static struct tcp_congestion_ops tcp_scalable = {
+	.ssthresh	= tcp_scalable_ssthresh,
+	.cong_avoid	= tcp_scalable_cong_avoid,
+	.min_cwnd	= tcp_reno_min_cwnd,
+
+	.owner		= THIS_MODULE,
+	.name		= "scalable",
+};
+
+static int __init tcp_scalable_register(void)
+{
+	return tcp_register_congestion_control(&tcp_scalable);
+}
+
+static void __exit tcp_scalable_unregister(void)
+{
+	tcp_unregister_congestion_control(&tcp_scalable);
+}
+
+module_init(tcp_scalable_register);
+module_exit(tcp_scalable_unregister);
+
+MODULE_AUTHOR("John Heffner");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Scalable TCP");
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
index 799ebe0..b127b44 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -464,11 +464,11 @@
 static void tcp_synack_timer(struct sock *sk)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
-	struct tcp_listen_opt *lopt = tp->listen_opt;
+	struct listen_sock *lopt = tp->accept_queue.listen_opt;
 	int max_retries = tp->syn_retries ? : sysctl_tcp_synack_retries;
 	int thresh = max_retries;
 	unsigned long now = jiffies;
-	struct open_request **reqp, *req;
+	struct request_sock **reqp, *req;
 	int i, budget;
 
 	if (lopt == NULL || lopt->qlen == 0)
@@ -513,8 +513,8 @@
 		while ((req = *reqp) != NULL) {
 			if (time_after_eq(now, req->expires)) {
 				if ((req->retrans < thresh ||
-				     (req->acked && req->retrans < max_retries))
-				    && !req->class->rtx_syn_ack(sk, req, NULL)) {
+				     (inet_rsk(req)->acked && req->retrans < max_retries))
+				    && !req->rsk_ops->rtx_syn_ack(sk, req, NULL)) {
 					unsigned long timeo;
 
 					if (req->retrans++ == 0)
@@ -527,13 +527,9 @@
 				}
 
 				/* Drop this request */
-				write_lock(&tp->syn_wait_lock);
-				*reqp = req->dl_next;
-				write_unlock(&tp->syn_wait_lock);
-				lopt->qlen--;
-				if (req->retrans == 0)
-					lopt->qlen_young--;
-				tcp_openreq_free(req);
+				tcp_synq_unlink(tp, req, reqp);
+				reqsk_queue_removed(&tp->accept_queue, req);
+				reqsk_free(req);
 				continue;
 			}
 			reqp = &req->dl_next;
diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c
new file mode 100644
index 0000000..9bd443d
--- /dev/null
+++ b/net/ipv4/tcp_vegas.c
@@ -0,0 +1,411 @@
+/*
+ * 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.
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/tcp_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
+static int alpha = 1<<V_PARAM_SHIFT;
+static int beta  = 3<<V_PARAM_SHIFT;
+static int gamma = 1<<V_PARAM_SHIFT;
+
+module_param(alpha, int, 0644);
+MODULE_PARM_DESC(alpha, "lower bound of packets in network (scale by 2)");
+module_param(beta, int, 0644);
+MODULE_PARM_DESC(beta, "upper bound of packets in network (scale by 2)");
+module_param(gamma, int, 0644);
+MODULE_PARM_DESC(gamma, "limit on increase (scale by 2)");
+
+
+/* Vegas variables */
+struct vegas {
+	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) */
+};
+
+/* 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 tcp_sock *tp)
+{
+	struct vegas *vegas = tcp_ca(tp);
+
+	/* 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 tcp_sock *tp)
+{
+	struct vegas *vegas = tcp_ca(tp);
+
+	vegas->doing_vegas_now = 0;
+}
+
+static void tcp_vegas_init(struct tcp_sock *tp)
+{
+	struct vegas *vegas = tcp_ca(tp);
+
+	vegas->baseRTT = 0x7fffffff;
+	vegas_enable(tp);
+}
+
+/* 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_vegas_rtt_calc(struct tcp_sock *tp, u32 usrtt)
+{
+	struct vegas *vegas = tcp_ca(tp);
+	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_vegas_state(struct tcp_sock *tp, u8 ca_state)
+{
+
+	if (ca_state == TCP_CA_Open)
+		vegas_enable(tp);
+	else
+		vegas_disable(tp);
+}
+
+/*
+ * 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_vegas_cwnd_event(struct tcp_sock *tp, enum tcp_ca_event event)
+{
+	if (event == CA_EVENT_CWND_RESTART ||
+	    event == CA_EVENT_TX_START)
+		tcp_vegas_init(tp);
+}
+
+static void tcp_vegas_cong_avoid(struct tcp_sock *tp, u32 ack,
+				 u32 seq_rtt, u32 in_flight, int flag)
+{
+	struct vegas *vegas = tcp_ca(tp);
+
+	if (!vegas->doing_vegas_now)
+		return tcp_reno_cong_avoid(tp, ack, seq_rtt, in_flight, flag);
+
+	/* 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.
+		 */
+		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;
+
+		/* Take into account the current RTT sample too, to
+		 * decrease the impact of delayed acks. This double counts
+		 * this sample since we count it for the next window as well,
+		 * but that's not too awful, since we're taking the min,
+		 * rather than averaging.
+		 */
+		tcp_vegas_rtt_calc(tp, seq_rtt*1000);
+
+		/* 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) {
+			/* We don't have enough RTT samples to do the Vegas
+			 * calculation, so we'll behave like Reno.
+			 */
+			if (tp->snd_cwnd > tp->snd_ssthresh)
+				tp->snd_cwnd++;
+		} else {
+			u32 rtt, target_cwnd, diff;
+
+			/* 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.
+			 */
+			target_cwnd = ((old_wnd * vegas->baseRTT)
+				       << 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;
+
+			if (tp->snd_cwnd < tp->snd_ssthresh) {
+				/* Slow start.  */
+				if (diff > gamma) {
+					/* Going too fast. Time to slow down
+					 * and switch to congestion avoidance.
+					 */
+					tp->snd_ssthresh = 2;
+
+					/* Set cwnd to match the actual rate
+					 * exactly:
+					 *   cwnd = (actual rate) * baseRTT
+					 * Then we add 1 because the integer
+					 * truncation robs us of full link
+					 * utilization.
+					 */
+					tp->snd_cwnd = min(tp->snd_cwnd,
+							   (target_cwnd >>
+							    V_PARAM_SHIFT)+1);
+
+				}
+			} else {
+				/* Congestion avoidance. */
+				u32 next_snd_cwnd;
+
+				/* Figure out where we would like cwnd
+				 * to be.
+				 */
+				if (diff > beta) {
+					/* The old window was too fast, so
+					 * we slow down.
+					 */
+					next_snd_cwnd = old_snd_cwnd - 1;
+				} else if (diff < alpha) {
+					/* We don't have enough extra packets
+					 * in the network, so speed up.
+					 */
+					next_snd_cwnd = old_snd_cwnd + 1;
+				} else {
+					/* Sending just as fast as we
+					 * should be.
+					 */
+					next_snd_cwnd = old_snd_cwnd;
+				}
+
+				/* Adjust cwnd upward or downward, toward the
+				 * desired value.
+				 */
+				if (next_snd_cwnd > tp->snd_cwnd)
+					tp->snd_cwnd++;
+				else if (next_snd_cwnd < tp->snd_cwnd)
+					tp->snd_cwnd--;
+			}
+		}
+
+		/* Wipe the slate clean for the next RTT. */
+		vegas->cntRTT = 0;
+		vegas->minRTT = 0x7fffffff;
+	}
+
+	/* The following code is executed for every ack we receive,
+	 * except for conditions checked in should_advance_cwnd()
+	 * before the call to tcp_cong_avoid(). Mainly this means that
+	 * we only execute this code if the ack actually acked some
+	 * data.
+	 */
+
+	/* If we are in slow start, increase our cwnd in response to this ACK.
+	 * (If we are not in slow start then we are in congestion avoidance,
+	 * and adjust our congestion window only once per RTT. See the code
+	 * above.)
+	 */
+	if (tp->snd_cwnd <= tp->snd_ssthresh)
+		tp->snd_cwnd++;
+
+	/* to keep cwnd from growing without bound */
+	tp->snd_cwnd = min_t(u32, tp->snd_cwnd, tp->snd_cwnd_clamp);
+
+	/* Make sure that we are never so timid as to reduce our cwnd below
+	 * 2 MSS.
+	 *
+	 * Going below 2 MSS would risk huge delayed ACKs from our receiver.
+	 */
+	tp->snd_cwnd = max(tp->snd_cwnd, 2U);
+}
+
+/* Extract info for Tcp socket info provided via netlink. */
+static void tcp_vegas_get_info(struct tcp_sock *tp, u32 ext,
+			       struct sk_buff *skb)
+{
+	const struct vegas *ca = tcp_ca(tp);
+	if (ext & (1<<(TCPDIAG_VEGASINFO-1))) {
+		struct tcpvegas_info *info;
+
+		info = RTA_DATA(__RTA_PUT(skb, TCPDIAG_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_vegas = {
+	.init		= tcp_vegas_init,
+	.ssthresh	= tcp_reno_ssthresh,
+	.cong_avoid	= tcp_vegas_cong_avoid,
+	.min_cwnd	= tcp_reno_min_cwnd,
+	.rtt_sample	= tcp_vegas_rtt_calc,
+	.set_state	= tcp_vegas_state,
+	.cwnd_event	= tcp_vegas_cwnd_event,
+	.get_info	= tcp_vegas_get_info,
+
+	.owner		= THIS_MODULE,
+	.name		= "vegas",
+};
+
+static int __init tcp_vegas_register(void)
+{
+	BUG_ON(sizeof(struct vegas) > TCP_CA_PRIV_SIZE);
+	tcp_register_congestion_control(&tcp_vegas);
+	return 0;
+}
+
+static void __exit tcp_vegas_unregister(void)
+{
+	tcp_unregister_congestion_control(&tcp_vegas);
+}
+
+module_init(tcp_vegas_register);
+module_exit(tcp_vegas_unregister);
+
+MODULE_AUTHOR("Stephen Hemminger");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TCP Vegas");
diff --git a/net/ipv4/tcp_westwood.c b/net/ipv4/tcp_westwood.c
new file mode 100644
index 0000000..ef82724
--- /dev/null
+++ b/net/ipv4/tcp_westwood.c
@@ -0,0 +1,259 @@
+/*
+ * TCP Westwood+
+ *
+ *	Angelo Dell'Aera:	TCP Westwood+ support
+ */
+
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/tcp_diag.h>
+#include <net/tcp.h>
+
+/* TCP Westwood structure */
+struct westwood {
+	u32    bw_ns_est;        /* first bandwidth estimation..not too smoothed 8) */
+	u32    bw_est;           /* bandwidth estimate */
+	u32    rtt_win_sx;       /* here starts a new evaluation... */
+	u32    bk;
+	u32    snd_una;          /* used for evaluating the number of acked bytes */
+	u32    cumul_ack;
+	u32    accounted;
+	u32    rtt;
+	u32    rtt_min;          /* minimum observed RTT */
+};
+
+
+/* TCP Westwood functions and constants */
+#define TCP_WESTWOOD_RTT_MIN   (HZ/20)	/* 50ms */
+#define TCP_WESTWOOD_INIT_RTT  (20*HZ)	/* maybe too conservative?! */
+
+/*
+ * @tcp_westwood_create
+ * This function initializes fields used in TCP Westwood+,
+ * it is called after the initial SYN, so the sequence numbers
+ * are correct but new passive connections we have no
+ * information about RTTmin at this time so we simply set it to
+ * TCP_WESTWOOD_INIT_RTT. This value was chosen to be too conservative
+ * since in this way we're sure it will be updated in a consistent
+ * way as soon as possible. It will reasonably happen within the first
+ * RTT period of the connection lifetime.
+ */
+static void tcp_westwood_init(struct tcp_sock *tp)
+{
+	struct westwood *w = tcp_ca(tp);
+
+	w->bk = 0;
+        w->bw_ns_est = 0;
+        w->bw_est = 0;
+        w->accounted = 0;
+        w->cumul_ack = 0;
+	w->rtt_min = w->rtt = TCP_WESTWOOD_INIT_RTT;
+	w->rtt_win_sx = tcp_time_stamp;
+	w->snd_una = tp->snd_una;
+}
+
+/*
+ * @westwood_do_filter
+ * Low-pass filter. Implemented using constant coefficients.
+ */
+static inline u32 westwood_do_filter(u32 a, u32 b)
+{
+	return (((7 * a) + b) >> 3);
+}
+
+static inline 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);
+}
+
+/*
+ * @westwood_pkts_acked
+ * Called after processing group of packets.
+ * but all westwood needs is the last sample of srtt.
+ */
+static void tcp_westwood_pkts_acked(struct tcp_sock *tp, u32 cnt)
+{
+	struct westwood *w = tcp_ca(tp);
+	if (cnt > 0)
+		w->rtt = tp->srtt >> 3;
+}
+
+/*
+ * @westwood_update_window
+ * It updates RTT evaluation window if it is the right moment to do
+ * it. If so it calls filter for evaluating bandwidth.
+ */
+static void westwood_update_window(struct tcp_sock *tp)
+{
+	struct westwood *w = tcp_ca(tp);
+	s32 delta = tcp_time_stamp - w->rtt_win_sx;
+
+	/*
+	 * See if a RTT-window has passed.
+	 * Be careful since if RTT is less than
+	 * 50ms we don't filter but we continue 'building the sample'.
+	 * This minimum limit was chosen since an estimation on small
+	 * time intervals is better to avoid...
+	 * Obviously on a LAN we reasonably will always have
+	 * right_bound = left_bound + WESTWOOD_RTT_MIN
+	 */
+	if (w->rtt && delta > max_t(u32, w->rtt, TCP_WESTWOOD_RTT_MIN)) {
+		westwood_filter(w, delta);
+
+		w->bk = 0;
+		w->rtt_win_sx = tcp_time_stamp;
+	}
+}
+
+/*
+ * @westwood_fast_bw
+ * It is called when we are in fast path. In particular it is called when
+ * header prediction is successful. In such case in fact update is
+ * straight forward and doesn't need any particular care.
+ */
+static inline void westwood_fast_bw(struct tcp_sock *tp)
+{
+	struct westwood *w = tcp_ca(tp);
+
+	westwood_update_window(tp);
+
+	w->bk += tp->snd_una - w->snd_una;
+	w->snd_una = tp->snd_una;
+	w->rtt_min = min(w->rtt, w->rtt_min);
+}
+
+/*
+ * @westwood_acked_count
+ * This function evaluates cumul_ack for evaluating bk in case of
+ * delayed or partial acks.
+ */
+static inline u32 westwood_acked_count(struct tcp_sock *tp)
+{
+	struct westwood *w = tcp_ca(tp);
+
+	w->cumul_ack = tp->snd_una - w->snd_una;
+
+        /* If cumul_ack is 0 this is a dupack since it's not moving
+         * tp->snd_una.
+         */
+        if (!w->cumul_ack) {
+		w->accounted += tp->mss_cache;
+		w->cumul_ack = tp->mss_cache;
+	}
+
+        if (w->cumul_ack > tp->mss_cache) {
+		/* Partial or delayed ack */
+		if (w->accounted >= w->cumul_ack) {
+			w->accounted -= w->cumul_ack;
+			w->cumul_ack = tp->mss_cache;
+		} else {
+			w->cumul_ack -= w->accounted;
+			w->accounted = 0;
+		}
+	}
+
+	w->snd_una = tp->snd_una;
+
+	return w->cumul_ack;
+}
+
+static inline u32 westwood_bw_rttmin(const struct tcp_sock *tp)
+{
+	struct westwood *w = tcp_ca(tp);
+	return max_t(u32, (w->bw_est * w->rtt_min) / tp->mss_cache, 2);
+}
+
+/*
+ * TCP Westwood
+ * Here limit is evaluated as Bw estimation*RTTmin (for obtaining it
+ * in packets we use mss_cache). Rttmin is guaranteed to be >= 2
+ * so avoids ever returning 0.
+ */
+static u32 tcp_westwood_cwnd_min(struct tcp_sock *tp)
+{
+	return westwood_bw_rttmin(tp);
+}
+
+static void tcp_westwood_event(struct tcp_sock *tp, enum tcp_ca_event event)
+{
+	struct westwood *w = tcp_ca(tp);
+
+	switch(event) {
+	case CA_EVENT_FAST_ACK:
+		westwood_fast_bw(tp);
+		break;
+
+	case CA_EVENT_COMPLETE_CWR:
+		tp->snd_cwnd = tp->snd_ssthresh = westwood_bw_rttmin(tp);
+		break;
+
+	case CA_EVENT_FRTO:
+		tp->snd_ssthresh = westwood_bw_rttmin(tp);
+		break;
+
+	case CA_EVENT_SLOW_ACK:
+		westwood_update_window(tp);
+		w->bk += westwood_acked_count(tp);
+		w->rtt_min = min(w->rtt, w->rtt_min);
+		break;
+
+	default:
+		/* don't care */
+		break;
+	}
+}
+
+
+/* Extract info for Tcp socket info provided via netlink. */
+static void tcp_westwood_info(struct tcp_sock *tp, u32 ext,
+			      struct sk_buff *skb)
+{
+	const struct westwood *ca = tcp_ca(tp);
+	if (ext & (1<<(TCPDIAG_VEGASINFO-1))) {
+		struct rtattr *rta;
+		struct tcpvegas_info *info;
+
+		rta = __RTA_PUT(skb, TCPDIAG_VEGASINFO, sizeof(*info));
+		info = RTA_DATA(rta);
+		info->tcpv_enabled = 1;
+		info->tcpv_rttcnt = 0;
+		info->tcpv_rtt = jiffies_to_usecs(ca->rtt);
+		info->tcpv_minrtt = jiffies_to_usecs(ca->rtt_min);
+	rtattr_failure:	;
+	}
+}
+
+
+static struct tcp_congestion_ops tcp_westwood = {
+	.init		= tcp_westwood_init,
+	.ssthresh	= tcp_reno_ssthresh,
+	.cong_avoid	= tcp_reno_cong_avoid,
+	.min_cwnd	= tcp_westwood_cwnd_min,
+	.cwnd_event	= tcp_westwood_event,
+	.get_info	= tcp_westwood_info,
+	.pkts_acked	= tcp_westwood_pkts_acked,
+
+	.owner		= THIS_MODULE,
+	.name		= "westwood"
+};
+
+static int __init tcp_westwood_register(void)
+{
+	BUG_ON(sizeof(struct westwood) > TCP_CA_PRIV_SIZE);
+	return tcp_register_congestion_control(&tcp_westwood);
+}
+
+static void __exit tcp_westwood_unregister(void)
+{
+	tcp_unregister_congestion_control(&tcp_westwood);
+}
+
+module_init(tcp_westwood_register);
+module_exit(tcp_westwood_unregister);
+
+MODULE_AUTHOR("Stephen Hemminger, Angelo Dell'Aera");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TCP Westwood+");
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index af2392a..66620a9 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -33,6 +33,7 @@
 	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;
@@ -51,10 +52,13 @@
 
 	/* DS disclosed */
 	top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos);
-	if (x->props.flags & XFRM_STATE_NOECN)
+
+	flags = x->props.flags;
+	if (flags & XFRM_STATE_NOECN)
 		IP_ECN_clear(top_iph);
 
-	top_iph->frag_off = iph->frag_off & htons(IP_DF);
+	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, 0);
 
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index 223a2e8..050611d 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -7,12 +7,20 @@
  *
  */
 
+#include <net/ip.h>
 #include <net/xfrm.h>
 #include <linux/pfkeyv2.h>
 #include <linux/ipsec.h>
 
 static struct xfrm_state_afinfo xfrm4_state_afinfo;
 
+static int xfrm4_init_flags(struct xfrm_state *x)
+{
+	if (ipv4_config.no_pmtu_disc)
+		x->props.flags |= XFRM_STATE_NOPMTUDISC;
+	return 0;
+}
+
 static void
 __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl,
 		     struct xfrm_tmpl *tmpl,
@@ -109,6 +117,7 @@
 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,
 	.find_acq		= __xfrm4_find_acq,
diff --git a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
index 413191f..e1fe360 100644
--- a/net/ipv4/xfrm4_tunnel.c
+++ b/net/ipv4/xfrm4_tunnel.c
@@ -84,7 +84,7 @@
 		handler->err_handler(skb, &arg);
 }
 
-static int ipip_init_state(struct xfrm_state *x, void *args)
+static int ipip_init_state(struct xfrm_state *x)
 {
 	if (!x->props.mode)
 		return -EINVAL;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 7744a25..a54d4ef 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -57,6 +57,7 @@
 #endif
 #include <linux/delay.h>
 #include <linux/notifier.h>
+#include <linux/string.h>
 
 #include <net/sock.h>
 #include <net/snmp.h>
@@ -131,7 +132,7 @@
 
 static int addrconf_ifdown(struct net_device *dev, int how);
 
-static void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags);
+static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags);
 static void addrconf_dad_timer(unsigned long data);
 static void addrconf_dad_completed(struct inet6_ifaddr *ifp);
 static void addrconf_rs_timer(unsigned long data);
@@ -372,6 +373,7 @@
 		ndev->regen_timer.data = (unsigned long) ndev;
 		if ((dev->flags&IFF_LOOPBACK) ||
 		    dev->type == ARPHRD_TUNNEL ||
+		    dev->type == ARPHRD_NONE ||
 		    dev->type == ARPHRD_SIT) {
 			printk(KERN_INFO
 				"Disabled Privacy Extensions on device %p(%s)\n",
@@ -491,7 +493,7 @@
 
 static struct inet6_ifaddr *
 ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
-	      int scope, unsigned flags)
+	      int scope, u32 flags)
 {
 	struct inet6_ifaddr *ifa = NULL;
 	struct rt6_info *rt;
@@ -694,7 +696,7 @@
 
 		if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
 			if (onlink == 0) {
-				ip6_del_rt(rt, NULL, NULL);
+				ip6_del_rt(rt, NULL, NULL, NULL);
 				rt = NULL;
 			} else if (!(rt->rt6i_flags & RTF_EXPIRES)) {
 				rt->rt6i_expires = expires;
@@ -1319,7 +1321,7 @@
 
 static void
 addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,
-		      unsigned long expires, unsigned flags)
+		      unsigned long expires, u32 flags)
 {
 	struct in6_rtmsg rtmsg;
 
@@ -1339,7 +1341,7 @@
 	if (dev->type == ARPHRD_SIT && (dev->flags&IFF_POINTOPOINT))
 		rtmsg.rtmsg_flags |= RTF_NONEXTHOP;
 
-	ip6_route_add(&rtmsg, NULL, NULL);
+	ip6_route_add(&rtmsg, NULL, NULL, NULL);
 }
 
 /* Create "default" multicast route to the interface */
@@ -1356,7 +1358,7 @@
 	rtmsg.rtmsg_ifindex = dev->ifindex;
 	rtmsg.rtmsg_flags = RTF_UP;
 	rtmsg.rtmsg_type = RTMSG_NEWROUTE;
-	ip6_route_add(&rtmsg, NULL, NULL);
+	ip6_route_add(&rtmsg, NULL, NULL, NULL);
 }
 
 static void sit_route_add(struct net_device *dev)
@@ -1373,7 +1375,7 @@
 	rtmsg.rtmsg_flags	= RTF_UP|RTF_NONEXTHOP;
 	rtmsg.rtmsg_ifindex	= dev->ifindex;
 
-	ip6_route_add(&rtmsg, NULL, NULL);
+	ip6_route_add(&rtmsg, NULL, NULL, NULL);
 }
 
 static void addrconf_add_lroute(struct net_device *dev)
@@ -1466,7 +1468,7 @@
 		if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
 			if (rt->rt6i_flags&RTF_EXPIRES) {
 				if (valid_lft == 0) {
-					ip6_del_rt(rt, NULL, NULL);
+					ip6_del_rt(rt, NULL, NULL, NULL);
 					rt = NULL;
 				} else {
 					rt->rt6i_expires = rt_expires;
@@ -2228,7 +2230,7 @@
 /*
  *	Duplicate Address Detection
  */
-static void addrconf_dad_start(struct inet6_ifaddr *ifp, int flags)
+static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags)
 {
 	struct inet6_dev *idev = ifp->idev;
 	struct net_device *dev = idev->dev;
@@ -2621,15 +2623,14 @@
 }
 
 static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
-			     u32 pid, u32 seq, int event)
+			     u32 pid, u32 seq, int event, unsigned int flags)
 {
 	struct ifaddrmsg *ifm;
 	struct nlmsghdr  *nlh;
 	struct ifa_cacheinfo ci;
 	unsigned char	 *b = skb->tail;
 
-	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm));
-	if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;
+	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
 	ifm = NLMSG_DATA(nlh);
 	ifm->ifa_family = AF_INET6;
 	ifm->ifa_prefixlen = ifa->prefix_len;
@@ -2671,15 +2672,14 @@
 }
 
 static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
-				u32 pid, u32 seq, int event)
+				u32 pid, u32 seq, int event, u16 flags)
 {
 	struct ifaddrmsg *ifm;
 	struct nlmsghdr  *nlh;
 	struct ifa_cacheinfo ci;
 	unsigned char	 *b = skb->tail;
 
-	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm));
-	if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;
+	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
 	ifm = NLMSG_DATA(nlh);
 	ifm->ifa_family = AF_INET6;	
 	ifm->ifa_prefixlen = 128;
@@ -2708,15 +2708,14 @@
 }
 
 static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca,
-				u32 pid, u32 seq, int event)
+				u32 pid, u32 seq, int event, unsigned int flags)
 {
 	struct ifaddrmsg *ifm;
 	struct nlmsghdr  *nlh;
 	struct ifa_cacheinfo ci;
 	unsigned char	 *b = skb->tail;
 
-	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*ifm));
-	if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;
+	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*ifm), flags);
 	ifm = NLMSG_DATA(nlh);
 	ifm->ifa_family = AF_INET6;	
 	ifm->ifa_prefixlen = 128;
@@ -2785,7 +2784,8 @@
 					continue;
 				if ((err = inet6_fill_ifaddr(skb, ifa, 
 				    NETLINK_CB(cb->skb).pid, 
-				    cb->nlh->nlmsg_seq, RTM_NEWADDR)) <= 0)
+				    cb->nlh->nlmsg_seq, RTM_NEWADDR,
+				    NLM_F_MULTI)) <= 0)
 					goto done;
 			}
 			/* temp addr */
@@ -2796,7 +2796,8 @@
 					continue;
 				if ((err = inet6_fill_ifaddr(skb, ifa, 
 				    NETLINK_CB(cb->skb).pid, 
-				    cb->nlh->nlmsg_seq, RTM_NEWADDR)) <= 0) 
+				    cb->nlh->nlmsg_seq, RTM_NEWADDR,
+				    NLM_F_MULTI)) <= 0) 
 					goto done;
 			}
 #endif
@@ -2809,7 +2810,8 @@
 					continue;
 				if ((err = inet6_fill_ifmcaddr(skb, ifmca, 
 				    NETLINK_CB(cb->skb).pid, 
-				    cb->nlh->nlmsg_seq, RTM_GETMULTICAST)) <= 0)
+				    cb->nlh->nlmsg_seq, RTM_GETMULTICAST,
+				    NLM_F_MULTI)) <= 0)
 					goto done;
 			}
 			break;
@@ -2821,7 +2823,8 @@
 					continue;
 				if ((err = inet6_fill_ifacaddr(skb, ifaca, 
 				    NETLINK_CB(cb->skb).pid, 
-				    cb->nlh->nlmsg_seq, RTM_GETANYCAST)) <= 0) 
+				    cb->nlh->nlmsg_seq, RTM_GETANYCAST,
+				    NLM_F_MULTI)) <= 0) 
 					goto done;
 			}
 			break;
@@ -2871,7 +2874,7 @@
 		netlink_set_err(rtnl, 0, RTMGRP_IPV6_IFADDR, ENOBUFS);
 		return;
 	}
-	if (inet6_fill_ifaddr(skb, ifa, 0, 0, event) < 0) {
+	if (inet6_fill_ifaddr(skb, ifa, current->pid, 0, event, 0) < 0) {
 		kfree_skb(skb);
 		netlink_set_err(rtnl, 0, RTMGRP_IPV6_IFADDR, EINVAL);
 		return;
@@ -2906,7 +2909,7 @@
 }
 
 static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, 
-			     u32 pid, u32 seq, int event)
+			     u32 pid, u32 seq, int event, unsigned int flags)
 {
 	struct net_device	*dev = idev->dev;
 	__s32			*array = NULL;
@@ -2917,8 +2920,7 @@
 	__u32			mtu = dev->mtu;
 	struct ifla_cacheinfo	ci;
 
-	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*r));
-	if (pid) nlh->nlmsg_flags |= NLM_F_MULTI;
+	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*r), flags);
 	r = NLMSG_DATA(nlh);
 	r->ifi_family = AF_INET6;
 	r->ifi_type = dev->type;
@@ -2985,7 +2987,7 @@
 		if ((idev = in6_dev_get(dev)) == NULL)
 			continue;
 		err = inet6_fill_ifinfo(skb, idev, NETLINK_CB(cb->skb).pid, 
-				cb->nlh->nlmsg_seq, RTM_NEWLINK);
+				cb->nlh->nlmsg_seq, RTM_NEWLINK, NLM_F_MULTI);
 		in6_dev_put(idev);
 		if (err <= 0)
 			break;
@@ -3007,7 +3009,7 @@
 		netlink_set_err(rtnl, 0, RTMGRP_IPV6_IFINFO, ENOBUFS);
 		return;
 	}
-	if (inet6_fill_ifinfo(skb, idev, 0, 0, event) < 0) {
+	if (inet6_fill_ifinfo(skb, idev, current->pid, 0, event, 0) < 0) {
 		kfree_skb(skb);
 		netlink_set_err(rtnl, 0, RTMGRP_IPV6_IFINFO, EINVAL);
 		return;
@@ -3017,18 +3019,15 @@
 }
 
 static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
-			struct prefix_info *pinfo, u32 pid, u32 seq, int event)
+			struct prefix_info *pinfo, u32 pid, u32 seq, 
+			int event, unsigned int flags)
 {
 	struct prefixmsg	*pmsg;
 	struct nlmsghdr 	*nlh;
 	unsigned char		*b = skb->tail;
 	struct prefix_cacheinfo	ci;
 
-	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*pmsg));
-	
-	if (pid) 
-		nlh->nlmsg_flags |= NLM_F_MULTI;
-	
+	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*pmsg), flags);
 	pmsg = NLMSG_DATA(nlh);
 	pmsg->prefix_family = AF_INET6;
 	pmsg->prefix_ifindex = idev->dev->ifindex;
@@ -3067,7 +3066,7 @@
 		netlink_set_err(rtnl, 0, RTMGRP_IPV6_PREFIX, ENOBUFS);
 		return;
 	}
-	if (inet6_fill_prefix(skb, idev, pinfo, 0, 0, event) < 0) {
+	if (inet6_fill_prefix(skb, idev, pinfo, current->pid, 0, event, 0) < 0) {
 		kfree_skb(skb);
 		netlink_set_err(rtnl, 0, RTMGRP_IPV6_PREFIX, EINVAL);
 		return;
@@ -3096,7 +3095,7 @@
 	switch (event) {
 	case RTM_NEWADDR:
 		dst_hold(&ifp->rt->u.dst);
-		if (ip6_ins_rt(ifp->rt, NULL, NULL))
+		if (ip6_ins_rt(ifp->rt, NULL, NULL, NULL))
 			dst_release(&ifp->rt->u.dst);
 		if (ifp->idev->cnf.forwarding)
 			addrconf_join_anycast(ifp);
@@ -3106,7 +3105,7 @@
 			addrconf_leave_anycast(ifp);
 		addrconf_leave_solict(ifp->idev, &ifp->addr);
 		dst_hold(&ifp->rt->u.dst);
-		if (ip6_del_rt(ifp->rt, NULL, NULL))
+		if (ip6_del_rt(ifp->rt, NULL, NULL, NULL))
 			dst_free(&ifp->rt->u.dst);
 		else
 			dst_release(&ifp->rt->u.dst);
@@ -3439,7 +3438,7 @@
 	 * by sysctl and we wouldn't want anyone to change it under our feet
 	 * (see SIOCSIFNAME).
 	 */	
-	dev_name = net_sysctl_strdup(dev_name);
+	dev_name = kstrdup(dev_name, GFP_KERNEL);
 	if (!dev_name)
 	    goto free;
 
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index e3ecf62..986fdfd 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -339,7 +339,7 @@
 	xfrm_state_put(x);
 }
 
-static int ah6_init_state(struct xfrm_state *x, void *args)
+static int ah6_init_state(struct xfrm_state *x)
 {
 	struct ah_data *ahp = NULL;
 	struct xfrm_algo_desc *aalg_desc;
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index 5d22ca3..6b72940 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -337,7 +337,7 @@
 	write_unlock_bh(&idev->lock);
 
 	dst_hold(&rt->u.dst);
-	if (ip6_ins_rt(rt, NULL, NULL))
+	if (ip6_ins_rt(rt, NULL, NULL, NULL))
 		dst_release(&rt->u.dst);
 
 	addrconf_join_solict(dev, &aca->aca_addr);
@@ -380,7 +380,7 @@
 	addrconf_leave_solict(idev, &aca->aca_addr);
 
 	dst_hold(&aca->aca_rt->u.dst);
-	if (ip6_del_rt(aca->aca_rt, NULL, NULL))
+	if (ip6_del_rt(aca->aca_rt, NULL, NULL, NULL))
 		dst_free(&aca->aca_rt->u.dst);
 	else
 		dst_release(&aca->aca_rt->u.dst);
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 65b9375..5229365 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -353,14 +353,14 @@
 	err = copied;
 
 	/* Reset and regenerate socket error */
-	spin_lock_irq(&sk->sk_error_queue.lock);
+	spin_lock_bh(&sk->sk_error_queue.lock);
 	sk->sk_err = 0;
 	if ((skb2 = skb_peek(&sk->sk_error_queue)) != NULL) {
 		sk->sk_err = SKB_EXT_ERR(skb2)->ee.ee_errno;
-		spin_unlock_irq(&sk->sk_error_queue.lock);
+		spin_unlock_bh(&sk->sk_error_queue.lock);
 		sk->sk_error_report(sk);
 	} else {
-		spin_unlock_irq(&sk->sk_error_queue.lock);
+		spin_unlock_bh(&sk->sk_error_queue.lock);
 	}
 
 out_free_skb:	
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index be7095d..324db62 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -296,7 +296,7 @@
 	kfree(esp);
 }
 
-static int esp6_init_state(struct xfrm_state *x, void *args)
+static int esp6_init_state(struct xfrm_state *x)
 {
 	struct esp_data *esp = NULL;
 
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 8e0f569..ff3ec98 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -277,8 +277,8 @@
 {
 	struct inet6_dev *idev = NULL;
 	struct ipv6hdr *hdr = skb->nh.ipv6h;
-	struct sock *sk = icmpv6_socket->sk;
-	struct ipv6_pinfo *np = inet6_sk(sk);
+	struct sock *sk;
+	struct ipv6_pinfo *np;
 	struct in6_addr *saddr = NULL;
 	struct dst_entry *dst;
 	struct icmp6hdr tmp_hdr;
@@ -358,6 +358,9 @@
 	if (icmpv6_xmit_lock())
 		return;
 
+	sk = icmpv6_socket->sk;
+	np = inet6_sk(sk);
+
 	if (!icmpv6_xrlim_allow(sk, type, &fl))
 		goto out;
 
@@ -423,9 +426,9 @@
 
 static void icmpv6_echo_reply(struct sk_buff *skb)
 {
-	struct sock *sk = icmpv6_socket->sk;
+	struct sock *sk;
 	struct inet6_dev *idev;
-	struct ipv6_pinfo *np = inet6_sk(sk);
+	struct ipv6_pinfo *np;
 	struct in6_addr *saddr = NULL;
 	struct icmp6hdr *icmph = (struct icmp6hdr *) skb->h.raw;
 	struct icmp6hdr tmp_hdr;
@@ -454,6 +457,9 @@
 	if (icmpv6_xmit_lock())
 		return;
 
+	sk = icmpv6_socket->sk;
+	np = inet6_sk(sk);
+
 	if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
 		fl.oif = np->mcast_oif;
 
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 405740b..1b354aa 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -394,7 +394,7 @@
  */
 
 static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
-    struct nlmsghdr *nlh)
+		struct nlmsghdr *nlh,  struct netlink_skb_parms *req)
 {
 	struct rt6_info *iter = NULL;
 	struct rt6_info **ins;
@@ -449,7 +449,7 @@
 	*ins = rt;
 	rt->rt6i_node = fn;
 	atomic_inc(&rt->rt6i_ref);
-	inet6_rt_notify(RTM_NEWROUTE, rt, nlh);
+	inet6_rt_notify(RTM_NEWROUTE, rt, nlh, req);
 	rt6_stats.fib_rt_entries++;
 
 	if ((fn->fn_flags & RTN_RTINFO) == 0) {
@@ -479,7 +479,8 @@
  *	with source addr info in sub-trees
  */
 
-int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
+int fib6_add(struct fib6_node *root, struct rt6_info *rt, 
+		struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
 {
 	struct fib6_node *fn;
 	int err = -ENOMEM;
@@ -552,7 +553,7 @@
 	}
 #endif
 
-	err = fib6_add_rt2node(fn, rt, nlh);
+	err = fib6_add_rt2node(fn, rt, nlh, req);
 
 	if (err == 0) {
 		fib6_start_gc(rt);
@@ -859,7 +860,7 @@
 }
 
 static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
-    struct nlmsghdr *nlh, void *_rtattr)
+    struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
 {
 	struct fib6_walker_t *w;
 	struct rt6_info *rt = *rtp;
@@ -915,11 +916,11 @@
 		if (atomic_read(&rt->rt6i_ref) != 1) BUG();
 	}
 
-	inet6_rt_notify(RTM_DELROUTE, rt, nlh);
+	inet6_rt_notify(RTM_DELROUTE, rt, nlh, req);
 	rt6_release(rt);
 }
 
-int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
+int fib6_del(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
 {
 	struct fib6_node *fn = rt->rt6i_node;
 	struct rt6_info **rtp;
@@ -944,7 +945,7 @@
 
 	for (rtp = &fn->leaf; *rtp; rtp = &(*rtp)->u.next) {
 		if (*rtp == rt) {
-			fib6_del_route(fn, rtp, nlh, _rtattr);
+			fib6_del_route(fn, rtp, nlh, _rtattr, req);
 			return 0;
 		}
 	}
@@ -1073,7 +1074,7 @@
 		res = c->func(rt, c->arg);
 		if (res < 0) {
 			w->leaf = rt;
-			res = fib6_del(rt, NULL, NULL);
+			res = fib6_del(rt, NULL, NULL, NULL);
 			if (res) {
 #if RT6_DEBUG >= 2
 				printk(KERN_DEBUG "fib6_clean_node: del failed: rt=%p@%p err=%d\n", rt, rt->rt6i_node, res);
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index b78a535..06e7cda 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -484,9 +484,6 @@
 	to->nf_bridge = from->nf_bridge;
 	nf_bridge_get(to->nf_bridge);
 #endif
-#ifdef CONFIG_NETFILTER_DEBUG
-	to->nf_debug = from->nf_debug;
-#endif
 #endif
 }
 
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 3b1c9fa..ba3b0c2 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -882,6 +882,7 @@
 	t->parms.hop_limit = p->hop_limit;
 	t->parms.encap_limit = p->encap_limit;
 	t->parms.flowinfo = p->flowinfo;
+	t->parms.link = p->link;
 	ip6ip6_tnl_link_config(t);
 	return 0;
 }
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
index 6cde531..423feb4 100644
--- a/net/ipv6/ipcomp6.c
+++ b/net/ipv6/ipcomp6.c
@@ -234,14 +234,9 @@
 	t->props.mode = 1;
 	memcpy(t->props.saddr.a6, x->props.saddr.a6, sizeof(struct in6_addr));
 
-	t->type = xfrm_get_type(IPPROTO_IPV6, t->props.family);
-	if (t->type == NULL)
+	if (xfrm_init_state(t))
 		goto error;
 
-	if (t->type->init_state(t, NULL))
-		goto error;
-
-	t->km.state = XFRM_STATE_VALID;
 	atomic_set(&t->tunnel_users, 1);
 
 out:
@@ -420,7 +415,7 @@
 	xfrm6_tunnel_free_spi((xfrm_address_t *)&x->props.saddr);
 }
 
-static int ipcomp6_init_state(struct xfrm_state *x, void *args)
+static int ipcomp6_init_state(struct xfrm_state *x)
 {
 	int err;
 	struct ipcomp_data *ipcd;
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 279ab86..f3ef4c3 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -423,11 +423,12 @@
 			psin6 = (struct sockaddr_in6 *)&greqs.gsr_group;
 			retv = ipv6_sock_mc_join(sk, greqs.gsr_interface,
 				&psin6->sin6_addr);
-			if (retv)
+			/* prior join w/ different source is ok */
+			if (retv && retv != -EADDRINUSE)
 				break;
 			omode = MCAST_INCLUDE;
 			add = 1;
-		} else /*IP_DROP_SOURCE_MEMBERSHIP */ {
+		} else /* MCAST_LEAVE_SOURCE_GROUP */ {
 			omode = MCAST_INCLUDE;
 			add = 0;
 		}
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index 393b6e6..562fcd1 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -188,6 +188,16 @@
 	if (!ipv6_addr_is_multicast(addr))
 		return -EINVAL;
 
+	read_lock_bh(&ipv6_sk_mc_lock);
+	for (mc_lst=np->ipv6_mc_list; mc_lst; mc_lst=mc_lst->next) {
+		if ((ifindex == 0 || mc_lst->ifindex == ifindex) &&
+		    ipv6_addr_equal(&mc_lst->addr, addr)) {
+			read_unlock_bh(&ipv6_sk_mc_lock);
+			return -EADDRINUSE;
+		}
+	}
+	read_unlock_bh(&ipv6_sk_mc_lock);
+
 	mc_lst = sock_kmalloc(sk, sizeof(struct ipv6_mc_socklist), GFP_KERNEL);
 
 	if (mc_lst == NULL)
@@ -349,6 +359,7 @@
 	struct ipv6_pinfo *inet6 = inet6_sk(sk);
 	struct ip6_sf_socklist *psl;
 	int i, j, rv;
+	int leavegroup = 0;
 	int err;
 
 	if (pgsr->gsr_group.ss_family != AF_INET6 ||
@@ -368,6 +379,7 @@
 
 	err = -EADDRNOTAVAIL;
 
+	read_lock_bh(&ipv6_sk_mc_lock);
 	for (pmc=inet6->ipv6_mc_list; pmc; pmc=pmc->next) {
 		if (pgsr->gsr_interface && pmc->ifindex != pgsr->gsr_interface)
 			continue;
@@ -401,6 +413,12 @@
 		if (rv)		/* source not found */
 			goto done;
 
+		/* special case - (INCLUDE, empty) == LEAVE_GROUP */
+		if (psl->sl_count == 1 && omode == MCAST_INCLUDE) {
+			leavegroup = 1;
+			goto done;
+		}
+
 		/* update the interface filter */
 		ip6_mc_del_src(idev, group, omode, 1, source, 1);
 
@@ -453,9 +471,12 @@
 	/* update the interface list */
 	ip6_mc_add_src(idev, group, omode, 1, source, 1);
 done:
+	read_unlock_bh(&ipv6_sk_mc_lock);
 	read_unlock_bh(&idev->lock);
 	in6_dev_put(idev);
 	dev_put(dev);
+	if (leavegroup)
+		return ipv6_sock_mc_drop(sk, pgsr->gsr_interface, group);
 	return err;
 }
 
@@ -1280,15 +1301,6 @@
 		return NULL;
 
 	skb_reserve(skb, LL_RESERVED_SPACE(dev));
-	if (dev->hard_header) {
-		unsigned char ha[MAX_ADDR_LEN];
-
-		ndisc_mc_map(&mld2_all_mcr, ha, dev, 1);
-		if (dev->hard_header(skb, dev, ETH_P_IPV6,ha,NULL,size) < 0) {
-			kfree_skb(skb);
-			return NULL;
-		}
-	}
 
 	if (ipv6_get_lladdr(dev, &addr_buf)) {
 		/* <draft-ietf-magma-mld-source-05.txt>:
@@ -1312,6 +1324,30 @@
 	return skb;
 }
 
+static inline int mld_dev_queue_xmit2(struct sk_buff *skb)
+{
+	struct net_device *dev = skb->dev;
+
+	if (dev->hard_header) {
+		unsigned char ha[MAX_ADDR_LEN];
+		int err;
+
+		ndisc_mc_map(&skb->nh.ipv6h->daddr, ha, dev, 1);
+		err = dev->hard_header(skb, dev, ETH_P_IPV6, ha, NULL, skb->len);
+		if (err < 0) {
+			kfree_skb(skb);
+			return err;
+		}
+	}
+	return dev_queue_xmit(skb);
+}
+
+static inline int mld_dev_queue_xmit(struct sk_buff *skb)
+{
+	return NF_HOOK(PF_INET6, NF_IP6_POST_ROUTING, skb, NULL, skb->dev,
+	               mld_dev_queue_xmit2);
+}
+
 static void mld_sendpack(struct sk_buff *skb)
 {
 	struct ipv6hdr *pip6 = skb->nh.ipv6h;
@@ -1329,7 +1365,7 @@
 	pmr->csum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen,
 		IPPROTO_ICMPV6, csum_partial(skb->h.raw, mldlen, 0));
 	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev,
-		dev_queue_xmit);
+		mld_dev_queue_xmit);
 	if (!err) {
 		ICMP6_INC_STATS(idev,ICMP6_MIB_OUTMSGS);
 		IP6_INC_STATS(IPSTATS_MIB_OUTMCASTPKTS);
@@ -1635,12 +1671,6 @@
 	}
 
 	skb_reserve(skb, LL_RESERVED_SPACE(dev));
-	if (dev->hard_header) {
-		unsigned char ha[MAX_ADDR_LEN];
-		ndisc_mc_map(snd_addr, ha, dev, 1);
-		if (dev->hard_header(skb, dev, ETH_P_IPV6, ha, NULL, full_len) < 0)
-			goto out;
-	}
 
 	if (ipv6_get_lladdr(dev, &addr_buf)) {
 		/* <draft-ietf-magma-mld-source-05.txt>:
@@ -1668,7 +1698,7 @@
 	idev = in6_dev_get(skb->dev);
 
 	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, skb->dev,
-		dev_queue_xmit);
+		mld_dev_queue_xmit);
 	if (!err) {
 		if (type == ICMPV6_MGM_REDUCTION)
 			ICMP6_INC_STATS(idev, ICMP6_MIB_OUTGROUPMEMBREDUCTIONS);
@@ -1682,10 +1712,6 @@
 	if (likely(idev != NULL))
 		in6_dev_put(idev);
 	return;
-
-out:
-	IP6_INC_STATS(IPSTATS_MIB_OUTDISCARDS);
-	kfree_skb(skb);
 }
 
 static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode,
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 7c291f4..7ae72d4 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -955,7 +955,7 @@
 			struct rt6_info *rt;
 			rt = rt6_get_dflt_router(saddr, dev);
 			if (rt)
-				ip6_del_rt(rt, NULL, NULL);
+				ip6_del_rt(rt, NULL, NULL, NULL);
 		}
 
 out:
@@ -1096,7 +1096,7 @@
 
 	if (rt && lifetime == 0) {
 		neigh_clone(neigh);
-		ip6_del_rt(rt, NULL, NULL);
+		ip6_del_rt(rt, NULL, NULL, NULL);
 		rt = NULL;
 	}
 
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index c735276..7303451 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -71,7 +71,6 @@
 /* Must have mutex */
 #define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0)
 #define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0)
-#include <linux/netfilter_ipv4/lockhelp.h>
 #include <linux/netfilter_ipv4/listhelp.h>
 
 #if 0
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index bfc3d01..c44685e 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -366,8 +366,6 @@
 		const char *level_string,
 		const char *prefix)
 {
-	struct ipv6hdr *ipv6h = skb->nh.ipv6h;
-
 	spin_lock_bh(&log_lock);
 	printk(level_string);
 	printk("%sIN=%s OUT=%s ",
@@ -377,39 +375,25 @@
 	if (in && !out) {
 		/* MAC logging for input chain only. */
 		printk("MAC=");
-		if (skb->dev && skb->dev->hard_header_len && skb->mac.raw != (void*)ipv6h) {
-			if (skb->dev->type != ARPHRD_SIT){
-			  int i;
-			  unsigned char *p = skb->mac.raw;
-			  for (i = 0; i < skb->dev->hard_header_len; i++,p++)
-				printk("%02x%c", *p,
-			       		i==skb->dev->hard_header_len - 1
-			       		? ' ':':');
-			} else {
-			  int i;
-			  unsigned char *p = skb->mac.raw;
-			  if ( p - (ETH_ALEN*2+2) > skb->head ){
-			    p -= (ETH_ALEN+2);
-			    for (i = 0; i < (ETH_ALEN); i++,p++)
-				printk("%02x%s", *p,
-					i == ETH_ALEN-1 ? "->" : ":");
-			    p -= (ETH_ALEN*2);
-			    for (i = 0; i < (ETH_ALEN); i++,p++)
-				printk("%02x%c", *p,
-					i == ETH_ALEN-1 ? ' ' : ':');
-			  }
-			  
-			  if ((skb->dev->addr_len == 4) &&
-			      skb->dev->hard_header_len > 20){
-			    printk("TUNNEL=");
-			    p = skb->mac.raw + 12;
-			    for (i = 0; i < 4; i++,p++)
-				printk("%3d%s", *p,
-					i == 3 ? "->" : ".");
-			    for (i = 0; i < 4; i++,p++)
-				printk("%3d%c", *p,
-					i == 3 ? ' ' : '.');
-			  }
+		if (skb->dev && skb->dev->hard_header_len &&
+		    skb->mac.raw != skb->nh.raw) {
+			unsigned char *p = skb->mac.raw;
+			int i;
+
+			if (skb->dev->type == ARPHRD_SIT &&
+			    (p -= ETH_HLEN) < skb->head)
+				p = NULL;
+
+			if (p != NULL)
+				for (i = 0; i < skb->dev->hard_header_len; i++)
+					printk("%02x", p[i]);
+			printk(" ");
+
+			if (skb->dev->type == ARPHRD_SIT) {
+				struct iphdr *iph = (struct iphdr *)skb->mac.raw;
+				printk("TUNNEL=%u.%u.%u.%u->%u.%u.%u.%u ",
+				       NIPQUAD(iph->saddr),
+				       NIPQUAD(iph->daddr));
 			}
 		} else
 			printk(" ");
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index 71407be..c2982ef 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -129,13 +129,15 @@
 	  .hook = ip6t_hook, 
 	  .pf = PF_INET6,
 	  .hooknum = NF_IP6_PRE_ROUTING,
-	  .priority = NF_IP6_PRI_FIRST
+	  .priority = NF_IP6_PRI_FIRST,
+	  .owner = THIS_MODULE,
 	},
 	{
 	  .hook = ip6t_hook, 
 	  .pf = PF_INET6, 
 	  .hooknum = NF_IP6_LOCAL_OUT,
-	  .priority = NF_IP6_PRI_FIRST
+	  .priority = NF_IP6_PRI_FIRST,
+	  .owner = THIS_MODULE,
 	},
 };
 
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 617645b..e2b848e 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -434,12 +434,12 @@
 	/* Clear queue. */
 	if (flags&MSG_PEEK) {
 		int clear = 0;
-		spin_lock_irq(&sk->sk_receive_queue.lock);
+		spin_lock_bh(&sk->sk_receive_queue.lock);
 		if (skb == skb_peek(&sk->sk_receive_queue)) {
 			__skb_unlink(skb, &sk->sk_receive_queue);
 			clear = 1;
 		}
-		spin_unlock_irq(&sk->sk_receive_queue.lock);
+		spin_unlock_bh(&sk->sk_receive_queue.lock);
 		if (clear)
 			kfree_skb(skb);
 	}
@@ -971,11 +971,11 @@
 			struct sk_buff *skb;
 			int amount = 0;
 
-			spin_lock_irq(&sk->sk_receive_queue.lock);
+			spin_lock_bh(&sk->sk_receive_queue.lock);
 			skb = skb_peek(&sk->sk_receive_queue);
 			if (skb != NULL)
 				amount = skb->tail - skb->h.raw;
-			spin_unlock_irq(&sk->sk_receive_queue.lock);
+			spin_unlock_bh(&sk->sk_receive_queue.lock);
 			return put_user(amount, (int __user *)arg);
 		}
 
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 3bf8a02..878789b 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -384,12 +384,13 @@
    be destroyed.
  */
 
-int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
+int ip6_ins_rt(struct rt6_info *rt, struct nlmsghdr *nlh,
+		void *_rtattr, struct netlink_skb_parms *req)
 {
 	int err;
 
 	write_lock_bh(&rt6_lock);
-	err = fib6_add(&ip6_routing_table, rt, nlh, _rtattr);
+	err = fib6_add(&ip6_routing_table, rt, nlh, _rtattr, req);
 	write_unlock_bh(&rt6_lock);
 
 	return err;
@@ -400,7 +401,7 @@
  */
 
 static struct rt6_info *rt6_cow(struct rt6_info *ort, struct in6_addr *daddr,
-				struct in6_addr *saddr)
+				struct in6_addr *saddr, struct netlink_skb_parms *req)
 {
 	int err;
 	struct rt6_info *rt;
@@ -432,7 +433,7 @@
 
 		dst_hold(&rt->u.dst);
 
-		err = ip6_ins_rt(rt, NULL, NULL);
+		err = ip6_ins_rt(rt, NULL, NULL, req);
 		if (err == 0)
 			return rt;
 
@@ -491,7 +492,8 @@
 		read_unlock_bh(&rt6_lock);
 
 		nrt = rt6_cow(rt, &skb->nh.ipv6h->daddr,
-			      &skb->nh.ipv6h->saddr);
+			      &skb->nh.ipv6h->saddr,
+			      &NETLINK_CB(skb));
 
 		dst_release(&rt->u.dst);
 		rt = nrt;
@@ -551,7 +553,7 @@
 		dst_hold(&rt->u.dst);
 		read_unlock_bh(&rt6_lock);
 
-		nrt = rt6_cow(rt, &fl->fl6_dst, &fl->fl6_src);
+		nrt = rt6_cow(rt, &fl->fl6_dst, &fl->fl6_src, NULL);
 
 		dst_release(&rt->u.dst);
 		rt = nrt;
@@ -598,7 +600,7 @@
 
 	if (rt) {
 		if (rt->rt6i_flags & RTF_CACHE)
-			ip6_del_rt(rt, NULL, NULL);
+			ip6_del_rt(rt, NULL, NULL, NULL);
 		else
 			dst_release(dst);
 	}
@@ -787,7 +789,8 @@
  *
  */
 
-int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr)
+int ip6_route_add(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, 
+		void *_rtattr, struct netlink_skb_parms *req)
 {
 	int err;
 	struct rtmsg *r;
@@ -974,7 +977,7 @@
 		rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&rt->u.dst));
 	rt->u.dst.dev = dev;
 	rt->rt6i_idev = idev;
-	return ip6_ins_rt(rt, nlh, _rtattr);
+	return ip6_ins_rt(rt, nlh, _rtattr, req);
 
 out:
 	if (dev)
@@ -986,7 +989,7 @@
 	return err;
 }
 
-int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr)
+int ip6_del_rt(struct rt6_info *rt, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
 {
 	int err;
 
@@ -994,7 +997,7 @@
 
 	rt6_reset_dflt_pointer(NULL);
 
-	err = fib6_del(rt, nlh, _rtattr);
+	err = fib6_del(rt, nlh, _rtattr, req);
 	dst_release(&rt->u.dst);
 
 	write_unlock_bh(&rt6_lock);
@@ -1002,7 +1005,7 @@
 	return err;
 }
 
-static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr)
+static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_rtattr, struct netlink_skb_parms *req)
 {
 	struct fib6_node *fn;
 	struct rt6_info *rt;
@@ -1029,7 +1032,7 @@
 			dst_hold(&rt->u.dst);
 			read_unlock_bh(&rt6_lock);
 
-			return ip6_del_rt(rt, nlh, _rtattr);
+			return ip6_del_rt(rt, nlh, _rtattr, req);
 		}
 	}
 	read_unlock_bh(&rt6_lock);
@@ -1136,11 +1139,11 @@
 	nrt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev);
 	nrt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_mtu(&nrt->u.dst));
 
-	if (ip6_ins_rt(nrt, NULL, NULL))
+	if (ip6_ins_rt(nrt, NULL, NULL, NULL))
 		goto out;
 
 	if (rt->rt6i_flags&RTF_CACHE) {
-		ip6_del_rt(rt, NULL, NULL);
+		ip6_del_rt(rt, NULL, NULL, NULL);
 		return;
 	}
 
@@ -1204,7 +1207,7 @@
 	   2. It is gatewayed route or NONEXTHOP route. Action: clone it.
 	 */
 	if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) {
-		nrt = rt6_cow(rt, daddr, saddr);
+		nrt = rt6_cow(rt, daddr, saddr, NULL);
 		if (!nrt->u.dst.error) {
 			nrt->u.dst.metrics[RTAX_MTU-1] = pmtu;
 			if (allfrag)
@@ -1232,7 +1235,7 @@
 		nrt->u.dst.metrics[RTAX_MTU-1] = pmtu;
 		if (allfrag)
 			nrt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
-		ip6_ins_rt(nrt, NULL, NULL);
+		ip6_ins_rt(nrt, NULL, NULL, NULL);
 	}
 
 out:
@@ -1305,7 +1308,7 @@
 
 	rtmsg.rtmsg_ifindex = dev->ifindex;
 
-	ip6_route_add(&rtmsg, NULL, NULL);
+	ip6_route_add(&rtmsg, NULL, NULL, NULL);
 	return rt6_get_dflt_router(gwaddr, dev);
 }
 
@@ -1323,7 +1326,7 @@
 
 			read_unlock_bh(&rt6_lock);
 
-			ip6_del_rt(rt, NULL, NULL);
+			ip6_del_rt(rt, NULL, NULL, NULL);
 
 			goto restart;
 		}
@@ -1349,10 +1352,10 @@
 		rtnl_lock();
 		switch (cmd) {
 		case SIOCADDRT:
-			err = ip6_route_add(&rtmsg, NULL, NULL);
+			err = ip6_route_add(&rtmsg, NULL, NULL, NULL);
 			break;
 		case SIOCDELRT:
-			err = ip6_route_del(&rtmsg, NULL, NULL);
+			err = ip6_route_del(&rtmsg, NULL, NULL, NULL);
 			break;
 		default:
 			err = -EINVAL;
@@ -1546,7 +1549,7 @@
 
 	if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
 		return -EINVAL;
-	return ip6_route_del(&rtmsg, nlh, arg);
+	return ip6_route_del(&rtmsg, nlh, arg, &NETLINK_CB(skb));
 }
 
 int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
@@ -1556,7 +1559,7 @@
 
 	if (inet6_rtm_to_rtmsg(r, arg, &rtmsg))
 		return -EINVAL;
-	return ip6_route_add(&rtmsg, nlh, arg);
+	return ip6_route_add(&rtmsg, nlh, arg, &NETLINK_CB(skb));
 }
 
 struct rt6_rtnl_dump_arg
@@ -1566,11 +1569,9 @@
 };
 
 static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
-			 struct in6_addr *dst,
-			 struct in6_addr *src,
-			 int iif,
-			 int type, u32 pid, u32 seq,
-			 struct nlmsghdr *in_nlh, int prefix)
+			 struct in6_addr *dst, struct in6_addr *src,
+			 int iif, int type, u32 pid, u32 seq,
+			 int prefix, unsigned int flags)
 {
 	struct rtmsg *rtm;
 	struct nlmsghdr  *nlh;
@@ -1584,11 +1585,7 @@
 		}
 	}
 
-	if (!pid && in_nlh) {
-		pid = in_nlh->nlmsg_pid;
-	}
-
-	nlh = NLMSG_PUT(skb, pid, seq, type, sizeof(*rtm));
+	nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*rtm), flags);
 	rtm = NLMSG_DATA(nlh);
 	rtm->rtm_family = AF_INET6;
 	rtm->rtm_dst_len = rt->rt6i_dst.plen;
@@ -1674,7 +1671,7 @@
 
 	return rt6_fill_node(arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE,
 		     NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq,
-		     NULL, prefix);
+		     prefix, NLM_F_MULTI);
 }
 
 static int fib6_dump_node(struct fib6_walker_t *w)
@@ -1822,7 +1819,7 @@
 			    &fl.fl6_dst, &fl.fl6_src,
 			    iif,
 			    RTM_NEWROUTE, NETLINK_CB(in_skb).pid,
-			    nlh->nlmsg_seq, nlh, 0);
+			    nlh->nlmsg_seq, 0, 0);
 	if (err < 0) {
 		err = -EMSGSIZE;
 		goto out_free;
@@ -1838,17 +1835,25 @@
 	goto out;	
 }
 
-void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh)
+void inet6_rt_notify(int event, struct rt6_info *rt, struct nlmsghdr *nlh, 
+			struct netlink_skb_parms *req)
 {
 	struct sk_buff *skb;
 	int size = NLMSG_SPACE(sizeof(struct rtmsg)+256);
+	u32 pid = current->pid;
+	u32 seq = 0;
 
+	if (req)
+		pid = req->pid;
+	if (nlh)
+		seq = nlh->nlmsg_seq;
+	
 	skb = alloc_skb(size, gfp_any());
 	if (!skb) {
 		netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, ENOBUFS);
 		return;
 	}
-	if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, 0, 0, nlh, 0) < 0) {
+	if (rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0) < 0) {
 		kfree_skb(skb);
 		netlink_set_err(rtnl, 0, RTMGRP_IPV6_ROUTE, EINVAL);
 		return;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 0f69e80..9dac7fd 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -65,7 +65,7 @@
 #include <linux/seq_file.h>
 
 static void	tcp_v6_send_reset(struct sk_buff *skb);
-static void	tcp_v6_or_send_ack(struct sk_buff *skb, struct open_request *req);
+static void	tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req);
 static void	tcp_v6_send_check(struct sock *sk, struct tcphdr *th, int len, 
 				  struct sk_buff *skb);
 
@@ -394,24 +394,26 @@
 	return c & (TCP_SYNQ_HSIZE - 1);
 }
 
-static struct open_request *tcp_v6_search_req(struct tcp_sock *tp,
-					      struct open_request ***prevp,
+static struct request_sock *tcp_v6_search_req(struct tcp_sock *tp,
+					      struct request_sock ***prevp,
 					      __u16 rport,
 					      struct in6_addr *raddr,
 					      struct in6_addr *laddr,
 					      int iif)
 {
-	struct tcp_listen_opt *lopt = tp->listen_opt;
-	struct open_request *req, **prev;  
+	struct listen_sock *lopt = tp->accept_queue.listen_opt;
+	struct request_sock *req, **prev;  
 
 	for (prev = &lopt->syn_table[tcp_v6_synq_hash(raddr, rport, lopt->hash_rnd)];
 	     (req = *prev) != NULL;
 	     prev = &req->dl_next) {
-		if (req->rmt_port == rport &&
-		    req->class->family == AF_INET6 &&
-		    ipv6_addr_equal(&req->af.v6_req.rmt_addr, raddr) &&
-		    ipv6_addr_equal(&req->af.v6_req.loc_addr, laddr) &&
-		    (!req->af.v6_req.iif || req->af.v6_req.iif == iif)) {
+		const struct tcp6_request_sock *treq = tcp6_rsk(req);
+
+		if (inet_rsk(req)->rmt_port == rport &&
+		    req->rsk_ops->family == AF_INET6 &&
+		    ipv6_addr_equal(&treq->rmt_addr, raddr) &&
+		    ipv6_addr_equal(&treq->loc_addr, laddr) &&
+		    (!treq->iif || treq->iif == iif)) {
 			BUG_TRAP(req->sk == NULL);
 			*prevp = prev;
 			return req;
@@ -906,9 +908,9 @@
 
 	icmpv6_err_convert(type, code, &err);
 
-	/* Might be for an open_request */
+	/* Might be for an request_sock */
 	switch (sk->sk_state) {
-		struct open_request *req, **prev;
+		struct request_sock *req, **prev;
 	case TCP_LISTEN:
 		if (sock_owned_by_user(sk))
 			goto out;
@@ -923,7 +925,7 @@
 		 */
 		BUG_TRAP(req->sk == NULL);
 
-		if (seq != req->snt_isn) {
+		if (seq != tcp_rsk(req)->snt_isn) {
 			NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS);
 			goto out;
 		}
@@ -957,9 +959,10 @@
 }
 
 
-static int tcp_v6_send_synack(struct sock *sk, struct open_request *req,
+static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req,
 			      struct dst_entry *dst)
 {
+	struct tcp6_request_sock *treq = tcp6_rsk(req);
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct sk_buff * skb;
 	struct ipv6_txoptions *opt = NULL;
@@ -969,19 +972,19 @@
 
 	memset(&fl, 0, sizeof(fl));
 	fl.proto = IPPROTO_TCP;
-	ipv6_addr_copy(&fl.fl6_dst, &req->af.v6_req.rmt_addr);
-	ipv6_addr_copy(&fl.fl6_src, &req->af.v6_req.loc_addr);
+	ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
+	ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr);
 	fl.fl6_flowlabel = 0;
-	fl.oif = req->af.v6_req.iif;
-	fl.fl_ip_dport = req->rmt_port;
+	fl.oif = treq->iif;
+	fl.fl_ip_dport = inet_rsk(req)->rmt_port;
 	fl.fl_ip_sport = inet_sk(sk)->sport;
 
 	if (dst == NULL) {
 		opt = np->opt;
 		if (opt == NULL &&
 		    np->rxopt.bits.srcrt == 2 &&
-		    req->af.v6_req.pktopts) {
-			struct sk_buff *pktopts = req->af.v6_req.pktopts;
+		    treq->pktopts) {
+			struct sk_buff *pktopts = treq->pktopts;
 			struct inet6_skb_parm *rxopt = IP6CB(pktopts);
 			if (rxopt->srcrt)
 				opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr*)(pktopts->nh.raw + rxopt->srcrt));
@@ -1008,10 +1011,10 @@
 		struct tcphdr *th = skb->h.th;
 
 		th->check = tcp_v6_check(th, skb->len,
-					 &req->af.v6_req.loc_addr, &req->af.v6_req.rmt_addr,
+					 &treq->loc_addr, &treq->rmt_addr,
 					 csum_partial((char *)th, skb->len, skb->csum));
 
-		ipv6_addr_copy(&fl.fl6_dst, &req->af.v6_req.rmt_addr);
+		ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
 		err = ip6_xmit(sk, skb, &fl, opt, 0);
 		if (err == NET_XMIT_CN)
 			err = 0;
@@ -1024,17 +1027,18 @@
 	return err;
 }
 
-static void tcp_v6_or_free(struct open_request *req)
+static void tcp_v6_reqsk_destructor(struct request_sock *req)
 {
-	if (req->af.v6_req.pktopts)
-		kfree_skb(req->af.v6_req.pktopts);
+	if (tcp6_rsk(req)->pktopts)
+		kfree_skb(tcp6_rsk(req)->pktopts);
 }
 
-static struct or_calltable or_ipv6 = {
+static struct request_sock_ops tcp6_request_sock_ops = {
 	.family		=	AF_INET6,
+	.obj_size	=	sizeof(struct tcp6_request_sock),
 	.rtx_syn_ack	=	tcp_v6_send_synack,
-	.send_ack	=	tcp_v6_or_send_ack,
-	.destructor	=	tcp_v6_or_free,
+	.send_ack	=	tcp_v6_reqsk_send_ack,
+	.destructor	=	tcp_v6_reqsk_destructor,
 	.send_reset	=	tcp_v6_send_reset
 };
 
@@ -1219,15 +1223,15 @@
 	tcp_tw_put(tw);
 }
 
-static void tcp_v6_or_send_ack(struct sk_buff *skb, struct open_request *req)
+static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req)
 {
-	tcp_v6_send_ack(skb, req->snt_isn+1, req->rcv_isn+1, req->rcv_wnd, req->ts_recent);
+	tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent);
 }
 
 
 static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
 {
-	struct open_request *req, **prev;
+	struct request_sock *req, **prev;
 	struct tcphdr *th = skb->h.th;
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct sock *nsk;
@@ -1260,21 +1264,13 @@
 	return sk;
 }
 
-static void tcp_v6_synq_add(struct sock *sk, struct open_request *req)
+static void tcp_v6_synq_add(struct sock *sk, struct request_sock *req)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
-	struct tcp_listen_opt *lopt = tp->listen_opt;
-	u32 h = tcp_v6_synq_hash(&req->af.v6_req.rmt_addr, req->rmt_port, lopt->hash_rnd);
+	struct listen_sock *lopt = tp->accept_queue.listen_opt;
+	u32 h = tcp_v6_synq_hash(&tcp6_rsk(req)->rmt_addr, inet_rsk(req)->rmt_port, lopt->hash_rnd);
 
-	req->sk = NULL;
-	req->expires = jiffies + TCP_TIMEOUT_INIT;
-	req->retrans = 0;
-	req->dl_next = lopt->syn_table[h];
-
-	write_lock(&tp->syn_wait_lock);
-	lopt->syn_table[h] = req;
-	write_unlock(&tp->syn_wait_lock);
-
+	reqsk_queue_hash_req(&tp->accept_queue, h, req, TCP_TIMEOUT_INIT);
 	tcp_synq_added(sk);
 }
 
@@ -1284,10 +1280,11 @@
  */
 static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
 {
+	struct tcp6_request_sock *treq;
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct tcp_options_received tmp_opt;
 	struct tcp_sock *tp = tcp_sk(sk);
-	struct open_request *req = NULL;
+	struct request_sock *req = NULL;
 	__u32 isn = TCP_SKB_CB(skb)->when;
 
 	if (skb->protocol == htons(ETH_P_IP))
@@ -1308,7 +1305,7 @@
 	if (sk_acceptq_is_full(sk) && tcp_synq_young(sk) > 1)
 		goto drop;
 
-	req = tcp_openreq_alloc();
+	req = reqsk_alloc(&tcp6_request_sock_ops);
 	if (req == NULL)
 		goto drop;
 
@@ -1321,28 +1318,28 @@
 	tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
 	tcp_openreq_init(req, &tmp_opt, skb);
 
-	req->class = &or_ipv6;
-	ipv6_addr_copy(&req->af.v6_req.rmt_addr, &skb->nh.ipv6h->saddr);
-	ipv6_addr_copy(&req->af.v6_req.loc_addr, &skb->nh.ipv6h->daddr);
+	treq = tcp6_rsk(req);
+	ipv6_addr_copy(&treq->rmt_addr, &skb->nh.ipv6h->saddr);
+	ipv6_addr_copy(&treq->loc_addr, &skb->nh.ipv6h->daddr);
 	TCP_ECN_create_request(req, skb->h.th);
-	req->af.v6_req.pktopts = NULL;
+	treq->pktopts = NULL;
 	if (ipv6_opt_accepted(sk, skb) ||
 	    np->rxopt.bits.rxinfo ||
 	    np->rxopt.bits.rxhlim) {
 		atomic_inc(&skb->users);
-		req->af.v6_req.pktopts = skb;
+		treq->pktopts = skb;
 	}
-	req->af.v6_req.iif = sk->sk_bound_dev_if;
+	treq->iif = sk->sk_bound_dev_if;
 
 	/* So that link locals have meaning */
 	if (!sk->sk_bound_dev_if &&
-	    ipv6_addr_type(&req->af.v6_req.rmt_addr) & IPV6_ADDR_LINKLOCAL)
-		req->af.v6_req.iif = tcp_v6_iif(skb);
+	    ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL)
+		treq->iif = tcp_v6_iif(skb);
 
 	if (isn == 0) 
 		isn = tcp_v6_init_sequence(sk,skb);
 
-	req->snt_isn = isn;
+	tcp_rsk(req)->snt_isn = isn;
 
 	if (tcp_v6_send_synack(sk, req, NULL))
 		goto drop;
@@ -1353,16 +1350,17 @@
 
 drop:
 	if (req)
-		tcp_openreq_free(req);
+		reqsk_free(req);
 
 	TCP_INC_STATS_BH(TCP_MIB_ATTEMPTFAILS);
 	return 0; /* don't send reset */
 }
 
 static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
-					  struct open_request *req,
+					  struct request_sock *req,
 					  struct dst_entry *dst)
 {
+	struct tcp6_request_sock *treq = tcp6_rsk(req);
 	struct ipv6_pinfo *newnp, *np = inet6_sk(sk);
 	struct tcp6_sock *newtcp6sk;
 	struct inet_sock *newinet;
@@ -1426,10 +1424,10 @@
 		goto out_overflow;
 
 	if (np->rxopt.bits.srcrt == 2 &&
-	    opt == NULL && req->af.v6_req.pktopts) {
-		struct inet6_skb_parm *rxopt = IP6CB(req->af.v6_req.pktopts);
+	    opt == NULL && treq->pktopts) {
+		struct inet6_skb_parm *rxopt = IP6CB(treq->pktopts);
 		if (rxopt->srcrt)
-			opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr*)(req->af.v6_req.pktopts->nh.raw+rxopt->srcrt));
+			opt = ipv6_invert_rthdr(sk, (struct ipv6_rt_hdr *)(treq->pktopts->nh.raw + rxopt->srcrt));
 	}
 
 	if (dst == NULL) {
@@ -1438,16 +1436,16 @@
 
 		memset(&fl, 0, sizeof(fl));
 		fl.proto = IPPROTO_TCP;
-		ipv6_addr_copy(&fl.fl6_dst, &req->af.v6_req.rmt_addr);
+		ipv6_addr_copy(&fl.fl6_dst, &treq->rmt_addr);
 		if (opt && opt->srcrt) {
 			struct rt0_hdr *rt0 = (struct rt0_hdr *) opt->srcrt;
 			ipv6_addr_copy(&final, &fl.fl6_dst);
 			ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
 			final_p = &final;
 		}
-		ipv6_addr_copy(&fl.fl6_src, &req->af.v6_req.loc_addr);
+		ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr);
 		fl.oif = sk->sk_bound_dev_if;
-		fl.fl_ip_dport = req->rmt_port;
+		fl.fl_ip_dport = inet_rsk(req)->rmt_port;
 		fl.fl_ip_sport = inet_sk(sk)->sport;
 
 		if (ip6_dst_lookup(sk, &dst, &fl))
@@ -1482,10 +1480,10 @@
 
 	memcpy(newnp, np, sizeof(struct ipv6_pinfo));
 
-	ipv6_addr_copy(&newnp->daddr, &req->af.v6_req.rmt_addr);
-	ipv6_addr_copy(&newnp->saddr, &req->af.v6_req.loc_addr);
-	ipv6_addr_copy(&newnp->rcv_saddr, &req->af.v6_req.loc_addr);
-	newsk->sk_bound_dev_if = req->af.v6_req.iif;
+	ipv6_addr_copy(&newnp->daddr, &treq->rmt_addr);
+	ipv6_addr_copy(&newnp->saddr, &treq->loc_addr);
+	ipv6_addr_copy(&newnp->rcv_saddr, &treq->loc_addr);
+	newsk->sk_bound_dev_if = treq->iif;
 
 	/* Now IPv6 options... 
 
@@ -1498,11 +1496,10 @@
 
 	/* Clone pktoptions received with SYN */
 	newnp->pktoptions = NULL;
-	if (req->af.v6_req.pktopts) {
-		newnp->pktoptions = skb_clone(req->af.v6_req.pktopts,
-					      GFP_ATOMIC);
-		kfree_skb(req->af.v6_req.pktopts);
-		req->af.v6_req.pktopts = NULL;
+	if (treq->pktopts != NULL) {
+		newnp->pktoptions = skb_clone(treq->pktopts, GFP_ATOMIC);
+		kfree_skb(treq->pktopts);
+		treq->pktopts = NULL;
 		if (newnp->pktoptions)
 			skb_set_owner_r(newnp->pktoptions, newsk);
 	}
@@ -2028,7 +2025,7 @@
 	sk->sk_state = TCP_CLOSE;
 
 	tp->af_specific = &ipv6_specific;
-
+	tp->ca_ops = &tcp_init_congestion_ops;
 	sk->sk_write_space = sk_stream_write_space;
 	sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
 
@@ -2050,7 +2047,7 @@
 
 /* Proc filesystem TCPv6 sock list dumping. */
 static void get_openreq6(struct seq_file *seq, 
-			 struct sock *sk, struct open_request *req, int i, int uid)
+			 struct sock *sk, struct request_sock *req, int i, int uid)
 {
 	struct in6_addr *dest, *src;
 	int ttd = req->expires - jiffies;
@@ -2058,8 +2055,8 @@
 	if (ttd < 0)
 		ttd = 0;
 
-	src = &req->af.v6_req.loc_addr;
-	dest = &req->af.v6_req.rmt_addr;
+	src = &tcp6_rsk(req)->loc_addr;
+	dest = &tcp6_rsk(req)->rmt_addr;
 	seq_printf(seq,
 		   "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X "
 		   "%02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %p\n",
@@ -2069,7 +2066,7 @@
 		   ntohs(inet_sk(sk)->sport),
 		   dest->s6_addr32[0], dest->s6_addr32[1],
 		   dest->s6_addr32[2], dest->s6_addr32[3],
-		   ntohs(req->rmt_port),
+		   ntohs(inet_rsk(req)->rmt_port),
 		   TCP_SYN_RECV,
 		   0,0, /* could print option size, but that is af dependent. */
 		   1,   /* timers active (only the expire timer) */  
@@ -2239,6 +2236,7 @@
 	.sysctl_rmem		= sysctl_tcp_rmem,
 	.max_header		= MAX_TCP_HEADER,
 	.obj_size		= sizeof(struct tcp6_sock),
+	.rsk_prot		= &tcp6_request_sock_ops,
 };
 
 static struct inet6_protocol tcpv6_protocol = {
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index e251d0b..eff050a 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -300,12 +300,12 @@
 	/* Clear queue. */
 	if (flags&MSG_PEEK) {
 		int clear = 0;
-		spin_lock_irq(&sk->sk_receive_queue.lock);
+		spin_lock_bh(&sk->sk_receive_queue.lock);
 		if (skb == skb_peek(&sk->sk_receive_queue)) {
 			__skb_unlink(skb, &sk->sk_receive_queue);
 			clear = 1;
 		}
-		spin_unlock_irq(&sk->sk_receive_queue.lock);
+		spin_unlock_bh(&sk->sk_receive_queue.lock);
 		if (clear)
 			kfree_skb(skb);
 	}
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index ffcadd6..60c26c8 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -466,7 +466,7 @@
 	return;
 }
 
-static int xfrm6_tunnel_init_state(struct xfrm_state *x, void *args)
+static int xfrm6_tunnel_init_state(struct xfrm_state *x)
 {
 	if (!x->props.mode)
 		return -EINVAL;
diff --git a/net/key/af_key.c b/net/key/af_key.c
index ce980aa..4879743 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -656,13 +656,18 @@
 	sa->sadb_sa_exttype = SADB_EXT_SA;
 	sa->sadb_sa_spi = x->id.spi;
 	sa->sadb_sa_replay = x->props.replay_window;
-	sa->sadb_sa_state = SADB_SASTATE_DYING;
-	if (x->km.state == XFRM_STATE_VALID && !x->km.dying)
-		sa->sadb_sa_state = SADB_SASTATE_MATURE;
-	else if (x->km.state == XFRM_STATE_ACQ)
+	switch (x->km.state) {
+	case XFRM_STATE_VALID:
+		sa->sadb_sa_state = x->km.dying ?
+			SADB_SASTATE_DYING : SADB_SASTATE_MATURE;
+		break;
+	case XFRM_STATE_ACQ:
 		sa->sadb_sa_state = SADB_SASTATE_LARVAL;
-	else if (x->km.state == XFRM_STATE_EXPIRED)
+		break;
+	default:
 		sa->sadb_sa_state = SADB_SASTATE_DEAD;
+		break;
+	}
 	sa->sadb_sa_auth = 0;
 	if (x->aalg) {
 		struct xfrm_algo_desc *a = xfrm_aalg_get_byname(x->aalg->alg_name, 0);
@@ -685,6 +690,8 @@
 		sa->sadb_sa_flags |= SADB_SAFLAGS_NOECN;
 	if (x->props.flags & XFRM_STATE_DECAP_DSCP)
 		sa->sadb_sa_flags |= SADB_SAFLAGS_DECAP_DSCP;
+	if (x->props.flags & XFRM_STATE_NOPMTUDISC)
+		sa->sadb_sa_flags |= SADB_SAFLAGS_NOPMTUDISC;
 
 	/* hard time */
 	if (hsc & 2) {
@@ -969,6 +976,8 @@
 		x->props.flags |= XFRM_STATE_NOECN;
 	if (sa->sadb_sa_flags & SADB_SAFLAGS_DECAP_DSCP)
 		x->props.flags |= XFRM_STATE_DECAP_DSCP;
+	if (sa->sadb_sa_flags & SADB_SAFLAGS_NOPMTUDISC)
+		x->props.flags |= XFRM_STATE_NOPMTUDISC;
 
 	lifetime = (struct sadb_lifetime*) ext_hdrs[SADB_EXT_LIFETIME_HARD-1];
 	if (lifetime != NULL) {
@@ -1091,17 +1100,11 @@
 		}
 	}
 
-	x->type = xfrm_get_type(proto, x->props.family);
-	if (x->type == NULL) {
-		err = -ENOPROTOOPT;
+	err = xfrm_init_state(x);
+	if (err)
 		goto out;
-	}
-	if (x->type->init_state(x, NULL)) {
-		err = -EINVAL;
-		goto out;
-	}
+
 	x->km.seq = hdr->sadb_msg_seq;
-	x->km.state = XFRM_STATE_VALID;
 	return x;
 
 out:
@@ -1240,13 +1243,78 @@
 	return 0;
 }
 
+static inline int event2poltype(int event)
+{
+	switch (event) {
+	case XFRM_MSG_DELPOLICY:
+		return SADB_X_SPDDELETE;
+	case XFRM_MSG_NEWPOLICY:
+		return SADB_X_SPDADD;
+	case XFRM_MSG_UPDPOLICY:
+		return SADB_X_SPDUPDATE;
+	case XFRM_MSG_POLEXPIRE:
+	//	return SADB_X_SPDEXPIRE;
+	default:
+		printk("pfkey: Unknown policy event %d\n", event);
+		break;
+	}
+
+	return 0;
+}
+
+static inline int event2keytype(int event)
+{
+	switch (event) {
+	case XFRM_MSG_DELSA:
+		return SADB_DELETE;
+	case XFRM_MSG_NEWSA:
+		return SADB_ADD;
+	case XFRM_MSG_UPDSA:
+		return SADB_UPDATE;
+	case XFRM_MSG_EXPIRE:
+		return SADB_EXPIRE;
+	default:
+		printk("pfkey: Unknown SA event %d\n", event);
+		break;
+	}
+
+	return 0;
+}
+
+/* ADD/UPD/DEL */
+static int key_notify_sa(struct xfrm_state *x, struct km_event *c)
+{
+	struct sk_buff *skb;
+	struct sadb_msg *hdr;
+	int hsc = 3;
+
+	if (c->event == XFRM_MSG_DELSA)
+		hsc = 0;
+
+	skb = pfkey_xfrm_state2msg(x, 0, hsc);
+
+	if (IS_ERR(skb))
+		return PTR_ERR(skb);
+
+	hdr = (struct sadb_msg *) skb->data;
+	hdr->sadb_msg_version = PF_KEY_V2;
+	hdr->sadb_msg_type = event2keytype(c->event);
+	hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto);
+	hdr->sadb_msg_errno = 0;
+	hdr->sadb_msg_reserved = 0;
+	hdr->sadb_msg_seq = c->seq;
+	hdr->sadb_msg_pid = c->pid;
+
+	pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL);
+
+	return 0;
+}
 
 static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
 {
-	struct sk_buff *out_skb;
-	struct sadb_msg *out_hdr;
 	struct xfrm_state *x;
 	int err;
+	struct km_event c;
 
 	xfrm_probe_algs();
 	
@@ -1254,6 +1322,7 @@
 	if (IS_ERR(x))
 		return PTR_ERR(x);
 
+	xfrm_state_hold(x);
 	if (hdr->sadb_msg_type == SADB_ADD)
 		err = xfrm_state_add(x);
 	else
@@ -1262,30 +1331,26 @@
 	if (err < 0) {
 		x->km.state = XFRM_STATE_DEAD;
 		xfrm_state_put(x);
-		return err;
+		goto out;
 	}
 
-	out_skb = pfkey_xfrm_state2msg(x, 0, 3);
-	if (IS_ERR(out_skb))
-		return  PTR_ERR(out_skb); /* XXX Should we return 0 here ? */
-
-	out_hdr = (struct sadb_msg *) out_skb->data;
-	out_hdr->sadb_msg_version = hdr->sadb_msg_version;
-	out_hdr->sadb_msg_type = hdr->sadb_msg_type;
-	out_hdr->sadb_msg_satype = pfkey_proto2satype(x->id.proto);
-	out_hdr->sadb_msg_errno = 0;
-	out_hdr->sadb_msg_reserved = 0;
-	out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
-	out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
-
-	pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, sk);
-
-	return 0;
+	if (hdr->sadb_msg_type == SADB_ADD)
+		c.event = XFRM_MSG_NEWSA;
+	else
+		c.event = XFRM_MSG_UPDSA;
+	c.seq = hdr->sadb_msg_seq;
+	c.pid = hdr->sadb_msg_pid;
+	km_state_notify(x, &c);
+out:
+	xfrm_state_put(x);
+	return err;
 }
 
 static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
 {
 	struct xfrm_state *x;
+	struct km_event c;
+	int err;
 
 	if (!ext_hdrs[SADB_EXT_SA-1] ||
 	    !present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
@@ -1301,13 +1366,19 @@
 		return -EPERM;
 	}
 	
-	xfrm_state_delete(x);
+	err = xfrm_state_delete(x);
+	if (err < 0) {
+		xfrm_state_put(x);
+		return err;
+	}
+
+	c.seq = hdr->sadb_msg_seq;
+	c.pid = hdr->sadb_msg_pid;
+	c.event = XFRM_MSG_DELSA;
+	km_state_notify(x, &c);
 	xfrm_state_put(x);
 
-	pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL, 
-			BROADCAST_ALL, sk);
-
-	return 0;
+	return err;
 }
 
 static int pfkey_get(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
@@ -1445,28 +1516,42 @@
 	return 0;
 }
 
+static int key_notify_sa_flush(struct km_event *c)
+{
+	struct sk_buff *skb;
+	struct sadb_msg *hdr;
+
+	skb = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_ATOMIC);
+	if (!skb)
+		return -ENOBUFS;
+	hdr = (struct sadb_msg *) skb_put(skb, sizeof(struct sadb_msg));
+	hdr->sadb_msg_satype = pfkey_proto2satype(c->data.proto);
+	hdr->sadb_msg_seq = c->seq;
+	hdr->sadb_msg_pid = c->pid;
+	hdr->sadb_msg_version = PF_KEY_V2;
+	hdr->sadb_msg_errno = (uint8_t) 0;
+	hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
+
+	pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL);
+
+	return 0;
+}
+
 static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
 {
 	unsigned proto;
-	struct sk_buff *skb_out;
-	struct sadb_msg *hdr_out;
+	struct km_event c;
 
 	proto = pfkey_satype2proto(hdr->sadb_msg_satype);
 	if (proto == 0)
 		return -EINVAL;
 
-	skb_out = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_KERNEL);
-	if (!skb_out)
-		return -ENOBUFS;
-
 	xfrm_state_flush(proto);
-
-	hdr_out = (struct sadb_msg *) skb_put(skb_out, sizeof(struct sadb_msg));
-	pfkey_hdr_dup(hdr_out, hdr);
-	hdr_out->sadb_msg_errno = (uint8_t) 0;
-	hdr_out->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
-
-	pfkey_broadcast(skb_out, GFP_KERNEL, BROADCAST_ALL, NULL);
+	c.data.proto = proto;
+	c.seq = hdr->sadb_msg_seq;
+	c.pid = hdr->sadb_msg_pid;
+	c.event = XFRM_MSG_FLUSHSA;
+	km_state_notify(NULL, &c);
 
 	return 0;
 }
@@ -1859,6 +1944,35 @@
 	hdr->sadb_msg_reserved = atomic_read(&xp->refcnt);
 }
 
+static int key_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c)
+{
+	struct sk_buff *out_skb;
+	struct sadb_msg *out_hdr;
+	int err;
+
+	out_skb = pfkey_xfrm_policy2msg_prep(xp);
+	if (IS_ERR(out_skb)) {
+		err = PTR_ERR(out_skb);
+		goto out;
+	}
+	pfkey_xfrm_policy2msg(out_skb, xp, dir);
+
+	out_hdr = (struct sadb_msg *) out_skb->data;
+	out_hdr->sadb_msg_version = PF_KEY_V2;
+
+	if (c->data.byid && c->event == XFRM_MSG_DELPOLICY)
+		out_hdr->sadb_msg_type = SADB_X_SPDDELETE2;
+	else
+		out_hdr->sadb_msg_type = event2poltype(c->event);
+	out_hdr->sadb_msg_errno = 0;
+	out_hdr->sadb_msg_seq = c->seq;
+	out_hdr->sadb_msg_pid = c->pid;
+	pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, NULL);
+out:
+	return 0;
+
+}
+
 static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
 {
 	int err;
@@ -1866,8 +1980,7 @@
 	struct sadb_address *sa;
 	struct sadb_x_policy *pol;
 	struct xfrm_policy *xp;
-	struct sk_buff *out_skb;
-	struct sadb_msg *out_hdr;
+	struct km_event c;
 
 	if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
 				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
@@ -1935,31 +2048,23 @@
 	    (err = parse_ipsecrequests(xp, pol)) < 0)
 		goto out;
 
-	out_skb = pfkey_xfrm_policy2msg_prep(xp);
-	if (IS_ERR(out_skb)) {
-		err =  PTR_ERR(out_skb);
-		goto out;
-	}
-
 	err = xfrm_policy_insert(pol->sadb_x_policy_dir-1, xp,
 				 hdr->sadb_msg_type != SADB_X_SPDUPDATE);
 	if (err) {
-		kfree_skb(out_skb);
-		goto out;
+		kfree(xp);
+		return err;
 	}
 
-	pfkey_xfrm_policy2msg(out_skb, xp, pol->sadb_x_policy_dir-1);
+	if (hdr->sadb_msg_type == SADB_X_SPDUPDATE)
+		c.event = XFRM_MSG_UPDPOLICY;
+	else 
+		c.event = XFRM_MSG_NEWPOLICY;
 
+	c.seq = hdr->sadb_msg_seq;
+	c.pid = hdr->sadb_msg_pid;
+
+	km_policy_notify(xp, pol->sadb_x_policy_dir-1, &c);
 	xfrm_pol_put(xp);
-
-	out_hdr = (struct sadb_msg *) out_skb->data;
-	out_hdr->sadb_msg_version = hdr->sadb_msg_version;
-	out_hdr->sadb_msg_type = hdr->sadb_msg_type;
-	out_hdr->sadb_msg_satype = 0;
-	out_hdr->sadb_msg_errno = 0;
-	out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
-	out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
-	pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, sk);
 	return 0;
 
 out:
@@ -1973,9 +2078,8 @@
 	struct sadb_address *sa;
 	struct sadb_x_policy *pol;
 	struct xfrm_policy *xp;
-	struct sk_buff *out_skb;
-	struct sadb_msg *out_hdr;
 	struct xfrm_selector sel;
+	struct km_event c;
 
 	if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
 				     ext_hdrs[SADB_EXT_ADDRESS_DST-1]) ||
@@ -2010,25 +2114,40 @@
 
 	err = 0;
 
+	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);
+
+	xfrm_pol_put(xp);
+	return err;
+}
+
+static int key_pol_get_resp(struct sock *sk, struct xfrm_policy *xp, struct sadb_msg *hdr, int dir)
+{
+	int err;
+	struct sk_buff *out_skb;
+	struct sadb_msg *out_hdr;
+	err = 0;
+
 	out_skb = pfkey_xfrm_policy2msg_prep(xp);
 	if (IS_ERR(out_skb)) {
 		err =  PTR_ERR(out_skb);
 		goto out;
 	}
-	pfkey_xfrm_policy2msg(out_skb, xp, pol->sadb_x_policy_dir-1);
+	pfkey_xfrm_policy2msg(out_skb, xp, dir);
 
 	out_hdr = (struct sadb_msg *) out_skb->data;
 	out_hdr->sadb_msg_version = hdr->sadb_msg_version;
-	out_hdr->sadb_msg_type = SADB_X_SPDDELETE;
+	out_hdr->sadb_msg_type = hdr->sadb_msg_type;
 	out_hdr->sadb_msg_satype = 0;
 	out_hdr->sadb_msg_errno = 0;
 	out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
 	out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
-	pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, sk);
+	pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk);
 	err = 0;
 
 out:
-	xfrm_pol_put(xp);
 	return err;
 }
 
@@ -2037,8 +2156,7 @@
 	int err;
 	struct sadb_x_policy *pol;
 	struct xfrm_policy *xp;
-	struct sk_buff *out_skb;
-	struct sadb_msg *out_hdr;
+	struct km_event c;
 
 	if ((pol = ext_hdrs[SADB_X_EXT_POLICY-1]) == NULL)
 		return -EINVAL;
@@ -2050,24 +2168,16 @@
 
 	err = 0;
 
-	out_skb = pfkey_xfrm_policy2msg_prep(xp);
-	if (IS_ERR(out_skb)) {
-		err =  PTR_ERR(out_skb);
-		goto out;
+	c.seq = hdr->sadb_msg_seq;
+	c.pid = hdr->sadb_msg_pid;
+	if (hdr->sadb_msg_type == SADB_X_SPDDELETE2) {
+		c.data.byid = 1;
+		c.event = XFRM_MSG_DELPOLICY;
+		km_policy_notify(xp, pol->sadb_x_policy_dir-1, &c);
+	} else {
+		err = key_pol_get_resp(sk, xp, hdr, pol->sadb_x_policy_dir-1);
 	}
-	pfkey_xfrm_policy2msg(out_skb, xp, pol->sadb_x_policy_dir-1);
 
-	out_hdr = (struct sadb_msg *) out_skb->data;
-	out_hdr->sadb_msg_version = hdr->sadb_msg_version;
-	out_hdr->sadb_msg_type = hdr->sadb_msg_type;
-	out_hdr->sadb_msg_satype = 0;
-	out_hdr->sadb_msg_errno = 0;
-	out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
-	out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
-	pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, sk);
-	err = 0;
-
-out:
 	xfrm_pol_put(xp);
 	return err;
 }
@@ -2102,22 +2212,34 @@
 	return xfrm_policy_walk(dump_sp, &data);
 }
 
-static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+static int key_notify_policy_flush(struct km_event *c)
 {
 	struct sk_buff *skb_out;
-	struct sadb_msg *hdr_out;
+	struct sadb_msg *hdr;
 
-	skb_out = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_KERNEL);
+	skb_out = alloc_skb(sizeof(struct sadb_msg) + 16, GFP_ATOMIC);
 	if (!skb_out)
 		return -ENOBUFS;
+	hdr = (struct sadb_msg *) skb_put(skb_out, sizeof(struct sadb_msg));
+	hdr->sadb_msg_seq = c->seq;
+	hdr->sadb_msg_pid = c->pid;
+	hdr->sadb_msg_version = PF_KEY_V2;
+	hdr->sadb_msg_errno = (uint8_t) 0;
+	hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
+	pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL);
+	return 0;
+
+}
+
+static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
+{
+	struct km_event c;
 
 	xfrm_policy_flush();
-
-	hdr_out = (struct sadb_msg *) skb_put(skb_out, sizeof(struct sadb_msg));
-	pfkey_hdr_dup(hdr_out, hdr);
-	hdr_out->sadb_msg_errno = (uint8_t) 0;
-	hdr_out->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
-	pfkey_broadcast(skb_out, GFP_KERNEL, BROADCAST_ALL, NULL);
+	c.event = XFRM_MSG_FLUSHPOLICY;
+	c.pid = hdr->sadb_msg_pid;
+	c.seq = hdr->sadb_msg_seq;
+	km_policy_notify(NULL, 0, &c);
 
 	return 0;
 }
@@ -2317,11 +2439,23 @@
 	}
 }
 
-static int pfkey_send_notify(struct xfrm_state *x, int hard)
+static int key_notify_policy_expire(struct xfrm_policy *xp, struct km_event *c)
+{
+	return 0;
+}
+
+static int key_notify_sa_expire(struct xfrm_state *x, struct km_event *c)
 {
 	struct sk_buff *out_skb;
 	struct sadb_msg *out_hdr;
-	int hsc = (hard ? 2 : 1);
+	int hard;
+	int hsc;
+
+	hard = c->data.hard;
+	if (hard)
+		hsc = 2;
+	else
+		hsc = 1;
 
 	out_skb = pfkey_xfrm_state2msg(x, 0, hsc);
 	if (IS_ERR(out_skb))
@@ -2340,6 +2474,44 @@
 	return 0;
 }
 
+static int pfkey_send_notify(struct xfrm_state *x, struct km_event *c)
+{
+	switch (c->event) {
+	case XFRM_MSG_EXPIRE:
+		return key_notify_sa_expire(x, c);
+	case XFRM_MSG_DELSA:
+	case XFRM_MSG_NEWSA:
+	case XFRM_MSG_UPDSA:
+		return key_notify_sa(x, c);
+	case XFRM_MSG_FLUSHSA:
+		return key_notify_sa_flush(c);
+	default:
+		printk("pfkey: Unknown SA event %d\n", c->event);
+		break;
+	}
+
+	return 0;
+}
+
+static int pfkey_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
+{
+	switch (c->event) {
+	case XFRM_MSG_POLEXPIRE:
+		return key_notify_policy_expire(xp, c);
+	case XFRM_MSG_DELPOLICY:
+	case XFRM_MSG_NEWPOLICY:
+	case XFRM_MSG_UPDPOLICY:
+		return key_notify_policy(xp, dir, c);
+	case XFRM_MSG_FLUSHPOLICY:
+		return key_notify_policy_flush(c);
+	default:
+		printk("pfkey: Unknown policy event %d\n", c->event);
+		break;
+	}
+
+	return 0;
+}
+
 static u32 get_acqseq(void)
 {
 	u32 res;
@@ -2856,6 +3028,7 @@
 	.acquire	= pfkey_send_acquire,
 	.compile_policy	= pfkey_compile_policy,
 	.new_mapping	= pfkey_send_new_mapping,
+	.notify_policy	= pfkey_send_policy_notify,
 };
 
 static void __exit ipsec_pfkey_exit(void)
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index e41ce45..fc456a7 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -315,8 +315,8 @@
 static void netlink_remove(struct sock *sk)
 {
 	netlink_table_grab();
-	nl_table[sk->sk_protocol].hash.entries--;
-	sk_del_node_init(sk);
+	if (sk_del_node_init(sk))
+		nl_table[sk->sk_protocol].hash.entries--;
 	if (nlk_sk(sk)->groups)
 		__sk_del_bind_node(sk);
 	netlink_table_ungrab();
@@ -429,7 +429,12 @@
 	err = netlink_insert(sk, pid);
 	if (err == -EADDRINUSE)
 		goto retry;
-	return 0;
+
+	/* If 2 threads race to autobind, that is fine.  */
+	if (err == -EBUSY)
+		err = 0;
+
+	return err;
 }
 
 static inline int netlink_capable(struct socket *sock, unsigned int flag) 
@@ -1095,8 +1100,7 @@
 		return 0;
 	}
 
-	nlh = __nlmsg_put(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, NLMSG_DONE, sizeof(int));
-	nlh->nlmsg_flags |= NLM_F_MULTI;
+	nlh = NLMSG_NEW_ANSWER(skb, cb, NLMSG_DONE, sizeof(len), NLM_F_MULTI);
 	memcpy(NLMSG_DATA(nlh), &len, sizeof(len));
 	skb_queue_tail(&sk->sk_receive_queue, skb);
 	sk->sk_data_ready(sk, skb->len);
@@ -1107,6 +1111,9 @@
 
 	netlink_destroy_callback(cb);
 	return 0;
+
+nlmsg_failure:
+	return -ENOBUFS;
 }
 
 int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
@@ -1178,7 +1185,7 @@
 	}
 
 	rep = __nlmsg_put(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
-			  NLMSG_ERROR, sizeof(struct nlmsgerr));
+			  NLMSG_ERROR, sizeof(struct nlmsgerr), 0);
 	errmsg = NLMSG_DATA(rep);
 	errmsg->error = err;
 	memcpy(&errmsg->msg, nlh, err ? nlh->nlmsg_len : sizeof(struct nlmsghdr));
diff --git a/net/rxrpc/krxiod.c b/net/rxrpc/krxiod.c
index 2b537f4..dada34a 100644
--- a/net/rxrpc/krxiod.c
+++ b/net/rxrpc/krxiod.c
@@ -138,7 +138,7 @@
 
 		_debug("### End Work");
 
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 
                 /* discard pending signals */
 		rxrpc_discard_my_signals();
diff --git a/net/rxrpc/krxsecd.c b/net/rxrpc/krxsecd.c
index 6020c89..1aadd02 100644
--- a/net/rxrpc/krxsecd.c
+++ b/net/rxrpc/krxsecd.c
@@ -107,7 +107,7 @@
 
 		_debug("### End Inbound Calls");
 
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 
                 /* discard pending signals */
 		rxrpc_discard_my_signals();
diff --git a/net/rxrpc/krxtimod.c b/net/rxrpc/krxtimod.c
index 249c2b0..3ac81cd 100644
--- a/net/rxrpc/krxtimod.c
+++ b/net/rxrpc/krxtimod.c
@@ -90,7 +90,7 @@
 			complete_and_exit(&krxtimod_dead, 0);
 		}
 
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 
 		/* discard pending signals */
 		rxrpc_discard_my_signals();
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index b094118..7bac249 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -405,7 +405,7 @@
 	---help---
 	  Size of the local stack variable used while evaluating the tree of
 	  ematches. Limits the depth of the tree, i.e. the number of
-	  encapsulated precedences. Every level requires 4 bytes of addtional
+	  encapsulated precedences. Every level requires 4 bytes of additional
 	  stack space.
 
 config NET_EMATCH_CMP
@@ -449,6 +449,19 @@
 	  To compile this code as a module, choose M here: the
 	  module will be called em_meta.
 
+config NET_EMATCH_TEXT
+	tristate "Textsearch"
+	depends on NET_EMATCH
+	select TEXTSEARCH
+	select TEXTSEARCH_KMP
+	select TEXTSEARCH_FSM
+	---help---
+	  Say Y here if you want to be ablt to classify packets based on
+	  textsearch comparisons.
+
+	  To compile this code as a module, choose M here: the
+	  module will be called em_text.
+
 config NET_CLS_ACT
 	bool "Packet ACTION"
 	depends on EXPERIMENTAL && NET_CLS && NET_QOS
diff --git a/net/sched/Makefile b/net/sched/Makefile
index eb3fe58..8f58cec 100644
--- a/net/sched/Makefile
+++ b/net/sched/Makefile
@@ -40,3 +40,4 @@
 obj-$(CONFIG_NET_EMATCH_NBYTE)	+= em_nbyte.o
 obj-$(CONFIG_NET_EMATCH_U32)	+= em_u32.o
 obj-$(CONFIG_NET_EMATCH_META)	+= em_meta.o
+obj-$(CONFIG_NET_EMATCH_TEXT)	+= em_text.o
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index cafcb08..9594206 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -428,15 +428,15 @@
 
 static int
 tca_get_fill(struct sk_buff *skb, struct tc_action *a, u32 pid, u32 seq,
-             unsigned flags, int event, int bind, int ref)
+             u16 flags, int event, int bind, int ref)
 {
 	struct tcamsg *t;
 	struct nlmsghdr *nlh;
 	unsigned char *b = skb->tail;
 	struct rtattr *x;
 
-	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*t));
-	nlh->nlmsg_flags = flags;
+	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*t), flags);
+
 	t = NLMSG_DATA(nlh);
 	t->tca_family = AF_UNSPEC;
 	
@@ -669,7 +669,7 @@
 }
 
 static int tcf_add_notify(struct tc_action *a, u32 pid, u32 seq, int event,
-                          unsigned flags)
+                          u16 flags)
 {
 	struct tcamsg *t;
 	struct nlmsghdr *nlh;
@@ -684,8 +684,7 @@
 
 	b = (unsigned char *)skb->tail;
 
-	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*t));
-	nlh->nlmsg_flags = flags;
+	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*t), flags);
 	t = NLMSG_DATA(nlh);
 	t->tca_family = AF_UNSPEC;
 	
@@ -881,7 +880,7 @@
 		link_p[RTM_GETACTION-RTM_BASE].dumpit = tc_dump_action;
 	}
 
-	printk("TC classifier action (bugs to netdev@oss.sgi.com cc "
+	printk("TC classifier action (bugs to netdev@vger.kernel.org cc "
 	       "hadi@cyberus.ca)\n");
 	return 0;
 }
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
index 56e66c3..1616bf5 100644
--- a/net/sched/cls_api.c
+++ b/net/sched/cls_api.c
@@ -322,14 +322,13 @@
 
 static int
 tcf_fill_node(struct sk_buff *skb, struct tcf_proto *tp, unsigned long fh,
-	      u32 pid, u32 seq, unsigned flags, int event)
+	      u32 pid, u32 seq, u16 flags, int event)
 {
 	struct tcmsg *tcm;
 	struct nlmsghdr  *nlh;
 	unsigned char	 *b = skb->tail;
 
-	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*tcm));
-	nlh->nlmsg_flags = flags;
+	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags);
 	tcm = NLMSG_DATA(nlh);
 	tcm->tcm_family = AF_UNSPEC;
 	tcm->tcm_ifindex = tp->q->dev->ifindex;
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c
index 0d2d441..dfb300b 100644
--- a/net/sched/cls_basic.c
+++ b/net/sched/cls_basic.c
@@ -261,6 +261,9 @@
 	rta = (struct rtattr *) b;
 	RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
 
+	if (f->res.classid)
+		RTA_PUT(skb, TCA_BASIC_CLASSID, sizeof(u32), &f->res.classid);
+
 	if (tcf_exts_dump(skb, &f->exts, &basic_ext_map) < 0 ||
 	    tcf_em_tree_dump(skb, &f->ematches, TCA_BASIC_EMATCHES) < 0)
 		goto rtattr_failure;
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c
index f1eeaf6..48bb23c 100644
--- a/net/sched/em_meta.c
+++ b/net/sched/em_meta.c
@@ -32,7 +32,7 @@
  * 	      +-----------+                           +-----------+
  * 	            |                                       |
  * 	            ---> meta_ops[INT][INDEV](...)          |
- *                            |                            |
+ *	                      |                             |
  * 	            -----------                             |
  * 	            V                                       V
  * 	      +-----------+                           +-----------+
@@ -70,6 +70,7 @@
 #include <net/dst.h>
 #include <net/route.h>
 #include <net/pkt_cls.h>
+#include <net/sock.h>
 
 struct meta_obj
 {
@@ -284,6 +285,214 @@
 }
 
 /**************************************************************************
+ * Socket Attributes
+ **************************************************************************/
+
+#define SKIP_NONLOCAL(skb)			\
+	if (unlikely(skb->sk == NULL)) {	\
+		*err = -1;			\
+		return;				\
+	}
+
+META_COLLECTOR(int_sk_family)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_family;
+}
+
+META_COLLECTOR(int_sk_state)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_state;
+}
+
+META_COLLECTOR(int_sk_reuse)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_reuse;
+}
+
+META_COLLECTOR(int_sk_bound_if)
+{
+	SKIP_NONLOCAL(skb);
+	/* No error if bound_dev_if is 0, legal userspace check */
+	dst->value = skb->sk->sk_bound_dev_if;
+}
+
+META_COLLECTOR(var_sk_bound_if)
+{
+	SKIP_NONLOCAL(skb);
+
+	 if (skb->sk->sk_bound_dev_if == 0) {
+		dst->value = (unsigned long) "any";
+		dst->len = 3;
+	 } else  {
+		struct net_device *dev;
+		
+		dev = dev_get_by_index(skb->sk->sk_bound_dev_if);
+		*err = var_dev(dev, dst);
+		if (dev)
+			dev_put(dev);
+	 }
+}
+
+META_COLLECTOR(int_sk_refcnt)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = atomic_read(&skb->sk->sk_refcnt);
+}
+
+META_COLLECTOR(int_sk_rcvbuf)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_rcvbuf;
+}
+
+META_COLLECTOR(int_sk_shutdown)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_shutdown;
+}
+
+META_COLLECTOR(int_sk_proto)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_protocol;
+}
+
+META_COLLECTOR(int_sk_type)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_type;
+}
+
+META_COLLECTOR(int_sk_rmem_alloc)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = atomic_read(&skb->sk->sk_rmem_alloc);
+}
+
+META_COLLECTOR(int_sk_wmem_alloc)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = atomic_read(&skb->sk->sk_wmem_alloc);
+}
+
+META_COLLECTOR(int_sk_omem_alloc)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = atomic_read(&skb->sk->sk_omem_alloc);
+}
+
+META_COLLECTOR(int_sk_rcv_qlen)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_receive_queue.qlen;
+}
+
+META_COLLECTOR(int_sk_snd_qlen)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_write_queue.qlen;
+}
+
+META_COLLECTOR(int_sk_wmem_queued)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_wmem_queued;
+}
+
+META_COLLECTOR(int_sk_fwd_alloc)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_forward_alloc;
+}
+
+META_COLLECTOR(int_sk_sndbuf)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_sndbuf;
+}
+
+META_COLLECTOR(int_sk_alloc)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_allocation;
+}
+
+META_COLLECTOR(int_sk_route_caps)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_route_caps;
+}
+
+META_COLLECTOR(int_sk_hashent)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_hashent;
+}
+
+META_COLLECTOR(int_sk_lingertime)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_lingertime / HZ;
+}
+
+META_COLLECTOR(int_sk_err_qlen)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_error_queue.qlen;
+}
+
+META_COLLECTOR(int_sk_ack_bl)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_ack_backlog;
+}
+
+META_COLLECTOR(int_sk_max_ack_bl)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_max_ack_backlog;
+}
+
+META_COLLECTOR(int_sk_prio)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_priority;
+}
+
+META_COLLECTOR(int_sk_rcvlowat)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_rcvlowat;
+}
+
+META_COLLECTOR(int_sk_rcvtimeo)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_rcvtimeo / HZ;
+}
+
+META_COLLECTOR(int_sk_sndtimeo)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_sndtimeo / HZ;
+}
+
+META_COLLECTOR(int_sk_sendmsg_off)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_sndmsg_off;
+}
+
+META_COLLECTOR(int_sk_write_pend)
+{
+	SKIP_NONLOCAL(skb);
+	dst->value = skb->sk->sk_write_pending;
+}
+
+/**************************************************************************
  * Meta value collectors assignment table
  **************************************************************************/
 
@@ -293,41 +502,75 @@
 			       struct meta_value *, struct meta_obj *, int *);
 };
 
+#define META_ID(name) TCF_META_ID_##name
+#define META_FUNC(name) { .get = meta_##name }
+
 /* Meta value operations table listing all meta value collectors and
  * assigns them to a type and meta id. */
 static struct meta_ops __meta_ops[TCF_META_TYPE_MAX+1][TCF_META_ID_MAX+1] = {
 	[TCF_META_TYPE_VAR] = {
-		[TCF_META_ID_DEV]	= { .get = meta_var_dev },
-		[TCF_META_ID_INDEV]	= { .get = meta_var_indev },
-		[TCF_META_ID_REALDEV]	= { .get = meta_var_realdev }
+		[META_ID(DEV)]			= META_FUNC(var_dev),
+		[META_ID(INDEV)]		= META_FUNC(var_indev),
+		[META_ID(REALDEV)]		= META_FUNC(var_realdev),
+		[META_ID(SK_BOUND_IF)] 		= META_FUNC(var_sk_bound_if),
 	},
 	[TCF_META_TYPE_INT] = {
-		[TCF_META_ID_RANDOM]	= { .get = meta_int_random },
-		[TCF_META_ID_LOADAVG_0]	= { .get = meta_int_loadavg_0 },
-		[TCF_META_ID_LOADAVG_1]	= { .get = meta_int_loadavg_1 },
-		[TCF_META_ID_LOADAVG_2]	= { .get = meta_int_loadavg_2 },
-		[TCF_META_ID_DEV]	= { .get = meta_int_dev },
-		[TCF_META_ID_INDEV]	= { .get = meta_int_indev },
-		[TCF_META_ID_REALDEV]	= { .get = meta_int_realdev },
-		[TCF_META_ID_PRIORITY]	= { .get = meta_int_priority },
-		[TCF_META_ID_PROTOCOL]	= { .get = meta_int_protocol },
-		[TCF_META_ID_SECURITY]	= { .get = meta_int_security },
-		[TCF_META_ID_PKTTYPE]	= { .get = meta_int_pkttype },
-		[TCF_META_ID_PKTLEN]	= { .get = meta_int_pktlen },
-		[TCF_META_ID_DATALEN]	= { .get = meta_int_datalen },
-		[TCF_META_ID_MACLEN]	= { .get = meta_int_maclen },
+		[META_ID(RANDOM)]		= META_FUNC(int_random),
+		[META_ID(LOADAVG_0)]		= META_FUNC(int_loadavg_0),
+		[META_ID(LOADAVG_1)]		= META_FUNC(int_loadavg_1),
+		[META_ID(LOADAVG_2)]		= META_FUNC(int_loadavg_2),
+		[META_ID(DEV)]			= META_FUNC(int_dev),
+		[META_ID(INDEV)]		= META_FUNC(int_indev),
+		[META_ID(REALDEV)]		= META_FUNC(int_realdev),
+		[META_ID(PRIORITY)]		= META_FUNC(int_priority),
+		[META_ID(PROTOCOL)]		= META_FUNC(int_protocol),
+		[META_ID(SECURITY)]		= META_FUNC(int_security),
+		[META_ID(PKTTYPE)]		= META_FUNC(int_pkttype),
+		[META_ID(PKTLEN)]		= META_FUNC(int_pktlen),
+		[META_ID(DATALEN)]		= META_FUNC(int_datalen),
+		[META_ID(MACLEN)]		= META_FUNC(int_maclen),
 #ifdef CONFIG_NETFILTER
-		[TCF_META_ID_NFMARK]	= { .get = meta_int_nfmark },
+		[META_ID(NFMARK)]		= META_FUNC(int_nfmark),
 #endif
-		[TCF_META_ID_TCINDEX]	= { .get = meta_int_tcindex },
+		[META_ID(TCINDEX)]		= META_FUNC(int_tcindex),
 #ifdef CONFIG_NET_CLS_ACT
-		[TCF_META_ID_TCVERDICT]	= { .get = meta_int_tcverd },
-		[TCF_META_ID_TCCLASSID]	= { .get = meta_int_tcclassid },
+		[META_ID(TCVERDICT)]		= META_FUNC(int_tcverd),
+		[META_ID(TCCLASSID)]		= META_FUNC(int_tcclassid),
 #endif
 #ifdef CONFIG_NET_CLS_ROUTE
-		[TCF_META_ID_RTCLASSID]	= { .get = meta_int_rtclassid },
+		[META_ID(RTCLASSID)]		= META_FUNC(int_rtclassid),
 #endif
-		[TCF_META_ID_RTIIF]	= { .get = meta_int_rtiif }
+		[META_ID(RTIIF)]		= META_FUNC(int_rtiif),
+		[META_ID(SK_FAMILY)]		= META_FUNC(int_sk_family),
+		[META_ID(SK_STATE)]		= META_FUNC(int_sk_state),
+		[META_ID(SK_REUSE)]		= META_FUNC(int_sk_reuse),
+		[META_ID(SK_BOUND_IF)]		= META_FUNC(int_sk_bound_if),
+		[META_ID(SK_REFCNT)]		= META_FUNC(int_sk_refcnt),
+		[META_ID(SK_RCVBUF)]		= META_FUNC(int_sk_rcvbuf),
+		[META_ID(SK_SNDBUF)]		= META_FUNC(int_sk_sndbuf),
+		[META_ID(SK_SHUTDOWN)]		= META_FUNC(int_sk_shutdown),
+		[META_ID(SK_PROTO)]		= META_FUNC(int_sk_proto),
+		[META_ID(SK_TYPE)]		= META_FUNC(int_sk_type),
+		[META_ID(SK_RMEM_ALLOC)]	= META_FUNC(int_sk_rmem_alloc),
+		[META_ID(SK_WMEM_ALLOC)]	= META_FUNC(int_sk_wmem_alloc),
+		[META_ID(SK_OMEM_ALLOC)]	= META_FUNC(int_sk_omem_alloc),
+		[META_ID(SK_WMEM_QUEUED)]	= META_FUNC(int_sk_wmem_queued),
+		[META_ID(SK_RCV_QLEN)]		= META_FUNC(int_sk_rcv_qlen),
+		[META_ID(SK_SND_QLEN)]		= META_FUNC(int_sk_snd_qlen),
+		[META_ID(SK_ERR_QLEN)]		= META_FUNC(int_sk_err_qlen),
+		[META_ID(SK_FORWARD_ALLOCS)]	= META_FUNC(int_sk_fwd_alloc),
+		[META_ID(SK_ALLOCS)]		= META_FUNC(int_sk_alloc),
+		[META_ID(SK_ROUTE_CAPS)]	= META_FUNC(int_sk_route_caps),
+		[META_ID(SK_HASHENT)]		= META_FUNC(int_sk_hashent),
+		[META_ID(SK_LINGERTIME)]	= META_FUNC(int_sk_lingertime),
+		[META_ID(SK_ACK_BACKLOG)]	= META_FUNC(int_sk_ack_bl),
+		[META_ID(SK_MAX_ACK_BACKLOG)]	= META_FUNC(int_sk_max_ack_bl),
+		[META_ID(SK_PRIO)]		= META_FUNC(int_sk_prio),
+		[META_ID(SK_RCVLOWAT)]		= META_FUNC(int_sk_rcvlowat),
+		[META_ID(SK_RCVTIMEO)]		= META_FUNC(int_sk_rcvtimeo),
+		[META_ID(SK_SNDTIMEO)]		= META_FUNC(int_sk_sndtimeo),
+		[META_ID(SK_SENDMSG_OFF)]	= META_FUNC(int_sk_sendmsg_off),
+		[META_ID(SK_WRITE_PENDING)]	= META_FUNC(int_sk_write_pend),
 	}
 };
 
@@ -396,9 +639,9 @@
 	/* Let gcc optimize it, the unlikely is not really based on
 	 * some numbers but jump free code for mismatches seems
 	 * more logical. */
-	if (unlikely(a == b))
+	if (unlikely(a->value == b->value))
 		return 0;
-	else if (a < b)
+	else if (a->value < b->value)
 		return -1;
 	else
 		return 1;
diff --git a/net/sched/em_text.c b/net/sched/em_text.c
new file mode 100644
index 0000000..873840d
--- /dev/null
+++ b/net/sched/em_text.c
@@ -0,0 +1,157 @@
+/*
+ * net/sched/em_text.c	Textsearch ematch
+ *
+ *		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.
+ *
+ * Authors:	Thomas Graf <tgraf@suug.ch>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/skbuff.h>
+#include <linux/textsearch.h>
+#include <linux/tc_ematch/tc_em_text.h>
+#include <net/pkt_cls.h>
+
+struct text_match
+{
+	u16			from_offset;
+	u16			to_offset;
+	u8			from_layer;
+	u8			to_layer;
+	struct ts_config	*config;
+};
+
+#define EM_TEXT_PRIV(m) ((struct text_match *) (m)->data)
+
+static int em_text_match(struct sk_buff *skb, struct tcf_ematch *m,
+			 struct tcf_pkt_info *info)
+{
+	struct text_match *tm = EM_TEXT_PRIV(m);
+	int from, to;
+	struct ts_state state;
+
+	from = tcf_get_base_ptr(skb, tm->from_layer) - skb->data;
+	from += tm->from_offset;
+
+	to = tcf_get_base_ptr(skb, tm->to_layer) - skb->data;
+	to += tm->to_offset;
+
+	return skb_find_text(skb, from, to, tm->config, &state) != UINT_MAX;
+}
+
+static int em_text_change(struct tcf_proto *tp, void *data, int len,
+			  struct tcf_ematch *m)
+{
+	struct text_match *tm;
+	struct tcf_em_text *conf = data;
+	struct ts_config *ts_conf;
+	int flags = 0;
+
+	printk("Configuring text: %s from %d:%d to %d:%d len %d\n", conf->algo, conf->from_offset,
+	    conf->from_layer, conf->to_offset, conf->to_layer, conf->pattern_len);
+
+	if (len < sizeof(*conf) || len < (sizeof(*conf) + conf->pattern_len))
+		return -EINVAL;
+
+	if (conf->from_layer > conf->to_layer)
+		return -EINVAL;
+
+	if (conf->from_layer == conf->to_layer &&
+	    conf->from_offset > conf->to_offset)
+		return -EINVAL;
+
+retry:
+	ts_conf = textsearch_prepare(conf->algo, (u8 *) conf + sizeof(*conf),
+				     conf->pattern_len, GFP_KERNEL, flags);
+
+	if (flags & TS_AUTOLOAD)
+		rtnl_lock();
+
+	if (IS_ERR(ts_conf)) {
+		if (PTR_ERR(ts_conf) == -ENOENT && !(flags & TS_AUTOLOAD)) {
+			rtnl_unlock();
+			flags |= TS_AUTOLOAD;
+			goto retry;
+		} else
+			return PTR_ERR(ts_conf);
+	} else if (flags & TS_AUTOLOAD) {
+		textsearch_destroy(ts_conf);
+		return -EAGAIN;
+	}
+
+	tm = kmalloc(sizeof(*tm), GFP_KERNEL);
+	if (tm == NULL) {
+		textsearch_destroy(ts_conf);
+		return -ENOBUFS;
+	}
+
+	tm->from_offset = conf->from_offset;
+	tm->to_offset   = conf->to_offset;
+	tm->from_layer  = conf->from_layer;
+	tm->to_layer    = conf->to_layer;
+	tm->config      = ts_conf;
+
+	m->datalen = sizeof(*tm);
+	m->data = (unsigned long) tm;
+
+	return 0;
+}
+
+static void em_text_destroy(struct tcf_proto *tp, struct tcf_ematch *m)
+{
+	textsearch_destroy(EM_TEXT_PRIV(m)->config);
+}
+
+static int em_text_dump(struct sk_buff *skb, struct tcf_ematch *m)
+{
+	struct text_match *tm = EM_TEXT_PRIV(m);
+	struct tcf_em_text conf;
+
+	strncpy(conf.algo, tm->config->ops->name, sizeof(conf.algo) - 1);
+	conf.from_offset = tm->from_offset;
+	conf.to_offset = tm->to_offset;
+	conf.from_layer = tm->from_layer;
+	conf.to_layer = tm->to_layer;
+	conf.pattern_len = textsearch_get_pattern_len(tm->config);
+	conf.pad = 0;
+
+	RTA_PUT_NOHDR(skb, sizeof(conf), &conf);
+	RTA_APPEND(skb, conf.pattern_len, textsearch_get_pattern(tm->config));
+	return 0;
+
+rtattr_failure:
+	return -1;
+}		
+
+static struct tcf_ematch_ops em_text_ops = {
+	.kind	  = TCF_EM_TEXT,
+	.change	  = em_text_change,
+	.match	  = em_text_match,
+	.destroy  = em_text_destroy,
+	.dump	  = em_text_dump,
+	.owner	  = THIS_MODULE,
+	.link	  = LIST_HEAD_INIT(em_text_ops.link)
+};
+
+static int __init init_em_text(void)
+{
+	return tcf_em_register(&em_text_ops);
+}
+
+static void __exit exit_em_text(void) 
+{
+	tcf_em_unregister(&em_text_ops);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_em_text);
+module_exit(exit_em_text);
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 07977f8..97c1c75 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -760,15 +760,14 @@
 }
 
 static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
-			 u32 pid, u32 seq, unsigned flags, int event)
+			 u32 pid, u32 seq, u16 flags, int event)
 {
 	struct tcmsg *tcm;
 	struct nlmsghdr  *nlh;
 	unsigned char	 *b = skb->tail;
 	struct gnet_dump d;
 
-	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*tcm));
-	nlh->nlmsg_flags = flags;
+	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags);
 	tcm = NLMSG_DATA(nlh);
 	tcm->tcm_family = AF_UNSPEC;
 	tcm->tcm_ifindex = q->dev->ifindex;
@@ -997,7 +996,7 @@
 
 static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q,
 			  unsigned long cl,
-			  u32 pid, u32 seq, unsigned flags, int event)
+			  u32 pid, u32 seq, u16 flags, int event)
 {
 	struct tcmsg *tcm;
 	struct nlmsghdr  *nlh;
@@ -1005,8 +1004,7 @@
 	struct gnet_dump d;
 	struct Qdisc_class_ops *cl_ops = q->ops->cl_ops;
 
-	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*tcm));
-	nlh->nlmsg_flags = flags;
+	nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*tcm), flags);
 	tcm = NLMSG_DATA(nlh);
 	tcm->tcm_family = AF_UNSPEC;
 	tcm->tcm_ifindex = q->dev->ifindex;
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index d8bd2a5..13e0e7b 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -31,7 +31,7 @@
 #endif
 
 
-#define PRIV(sch) qdisc_priv(sch)
+#define PRIV(sch) ((struct dsmark_qdisc_data *) qdisc_priv(sch))
 
 
 /*
@@ -55,24 +55,38 @@
 struct dsmark_qdisc_data {
 	struct Qdisc		*q;
 	struct tcf_proto	*filter_list;
-	__u8			*mask;	/* "owns" the array */
-	__u8			*value;
-	__u16			indices;
-	__u32			default_index;	/* index range is 0...0xffff */
+	u8			*mask;	/* "owns" the array */
+	u8			*value;
+	u16			indices;
+	u32			default_index;	/* index range is 0...0xffff */
 	int			set_tc_index;
 };
 
+static inline int dsmark_valid_indices(u16 indices)
+{
+	while (indices != 1) {
+		if (indices & 1)
+			return 0;
+		indices >>= 1;
+	}
+ 
+	return 1;
+}
+
+static inline int dsmark_valid_index(struct dsmark_qdisc_data *p, u16 index)
+{
+	return (index <= p->indices && index > 0);
+}
 
 /* ------------------------- Class/flow operations ------------------------- */
 
-
-static int dsmark_graft(struct Qdisc *sch,unsigned long arg,
-    struct Qdisc *new,struct Qdisc **old)
+static int dsmark_graft(struct Qdisc *sch, unsigned long arg,
+			struct Qdisc *new, struct Qdisc **old)
 {
 	struct dsmark_qdisc_data *p = PRIV(sch);
 
-	DPRINTK("dsmark_graft(sch %p,[qdisc %p],new %p,old %p)\n",sch,p,new,
-	    old);
+	DPRINTK("dsmark_graft(sch %p,[qdisc %p],new %p,old %p)\n",
+		sch, p, new, old);
 
 	if (new == NULL) {
 		new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
@@ -81,91 +95,95 @@
 	}
 
 	sch_tree_lock(sch);
-	*old = xchg(&p->q,new);
-	if (*old)
-		qdisc_reset(*old);
+	*old = xchg(&p->q, new);
+	qdisc_reset(*old);
 	sch->q.qlen = 0;
-	sch_tree_unlock(sch); /* @@@ move up ? */
+	sch_tree_unlock(sch);
+
         return 0;
 }
 
-
 static struct Qdisc *dsmark_leaf(struct Qdisc *sch, unsigned long arg)
 {
-	struct dsmark_qdisc_data *p = PRIV(sch);
-
-	return p->q;
+	return PRIV(sch)->q;
 }
 
-
-static unsigned long dsmark_get(struct Qdisc *sch,u32 classid)
+static unsigned long dsmark_get(struct Qdisc *sch, u32 classid)
 {
-	struct dsmark_qdisc_data *p __attribute__((unused)) = PRIV(sch);
+	DPRINTK("dsmark_get(sch %p,[qdisc %p],classid %x)\n",
+		sch, PRIV(sch), classid);
 
-	DPRINTK("dsmark_get(sch %p,[qdisc %p],classid %x)\n",sch,p,classid);
-	return TC_H_MIN(classid)+1;
+	return TC_H_MIN(classid) + 1;
 }
 
-
 static unsigned long dsmark_bind_filter(struct Qdisc *sch,
-    unsigned long parent, u32 classid)
+					unsigned long parent, u32 classid)
 {
-	return dsmark_get(sch,classid);
+	return dsmark_get(sch, classid);
 }
 
-
 static void dsmark_put(struct Qdisc *sch, unsigned long cl)
 {
 }
 
-
 static int dsmark_change(struct Qdisc *sch, u32 classid, u32 parent,
-    struct rtattr **tca, unsigned long *arg)
+			 struct rtattr **tca, unsigned long *arg)
 {
 	struct dsmark_qdisc_data *p = PRIV(sch);
 	struct rtattr *opt = tca[TCA_OPTIONS-1];
 	struct rtattr *tb[TCA_DSMARK_MAX];
+	int err = -EINVAL;
+	u8 mask = 0;
 
 	DPRINTK("dsmark_change(sch %p,[qdisc %p],classid %x,parent %x),"
-	    "arg 0x%lx\n",sch,p,classid,parent,*arg);
-	if (*arg > p->indices)
-		return -ENOENT;
+		"arg 0x%lx\n", sch, p, classid, parent, *arg);
+
+	if (!dsmark_valid_index(p, *arg)) {
+		err = -ENOENT;
+		goto rtattr_failure;
+	}
+
 	if (!opt || rtattr_parse_nested(tb, TCA_DSMARK_MAX, opt))
-		return -EINVAL;
-	if (tb[TCA_DSMARK_MASK-1]) {
-		if (!RTA_PAYLOAD(tb[TCA_DSMARK_MASK-1]))
-			return -EINVAL;
-		p->mask[*arg-1] = *(__u8 *) RTA_DATA(tb[TCA_DSMARK_MASK-1]);
-	}
-	if (tb[TCA_DSMARK_VALUE-1]) {
-		if (!RTA_PAYLOAD(tb[TCA_DSMARK_VALUE-1]))
-			return -EINVAL;
-		p->value[*arg-1] = *(__u8 *) RTA_DATA(tb[TCA_DSMARK_VALUE-1]);
-	}
-	return 0;
+		goto rtattr_failure;
+
+	if (tb[TCA_DSMARK_MASK-1])
+		mask = RTA_GET_U8(tb[TCA_DSMARK_MASK-1]);
+
+	if (tb[TCA_DSMARK_VALUE-1])
+		p->value[*arg-1] = RTA_GET_U8(tb[TCA_DSMARK_VALUE-1]);
+		
+	if (tb[TCA_DSMARK_MASK-1])
+		p->mask[*arg-1] = mask;
+
+	err = 0;
+
+rtattr_failure:
+	return err;
 }
 
-
-static int dsmark_delete(struct Qdisc *sch,unsigned long arg)
+static int dsmark_delete(struct Qdisc *sch, unsigned long arg)
 {
 	struct dsmark_qdisc_data *p = PRIV(sch);
 
-	if (!arg || arg > p->indices)
+	if (!dsmark_valid_index(p, arg))
 		return -EINVAL;
+	
 	p->mask[arg-1] = 0xff;
 	p->value[arg-1] = 0;
+
 	return 0;
 }
 
-
 static void dsmark_walk(struct Qdisc *sch,struct qdisc_walker *walker)
 {
 	struct dsmark_qdisc_data *p = PRIV(sch);
 	int i;
 
-	DPRINTK("dsmark_walk(sch %p,[qdisc %p],walker %p)\n",sch,p,walker);
+	DPRINTK("dsmark_walk(sch %p,[qdisc %p],walker %p)\n", sch, p, walker);
+
 	if (walker->stop)
 		return;
+
 	for (i = 0; i < p->indices; i++) {
 		if (p->mask[i] == 0xff && !p->value[i])
 			goto ignore;
@@ -180,26 +198,20 @@
         }
 }
 
-
 static struct tcf_proto **dsmark_find_tcf(struct Qdisc *sch,unsigned long cl)
 {
-	struct dsmark_qdisc_data *p = PRIV(sch);
-
-	return &p->filter_list;
+	return &PRIV(sch)->filter_list;
 }
 
-
 /* --------------------------- Qdisc operations ---------------------------- */
 
-
 static int dsmark_enqueue(struct sk_buff *skb,struct Qdisc *sch)
 {
 	struct dsmark_qdisc_data *p = PRIV(sch);
-	struct tcf_result res;
-	int result;
-	int ret = NET_XMIT_POLICED;
+	int err;
 
-	D2PRINTK("dsmark_enqueue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p);
+	D2PRINTK("dsmark_enqueue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
+
 	if (p->set_tc_index) {
 		/* FIXME: Safe with non-linear skbs? --RR */
 		switch (skb->protocol) {
@@ -216,17 +228,21 @@
 				break;
 		};
 	}
-	result = TC_POLICE_OK; /* be nice to gcc */
-	if (TC_H_MAJ(skb->priority) == sch->handle) {
+
+	if (TC_H_MAJ(skb->priority) == sch->handle)
 		skb->tc_index = TC_H_MIN(skb->priority);
-	} else {
-		result = tc_classify(skb,p->filter_list,&res);
-		D2PRINTK("result %d class 0x%04x\n",result,res.classid);
+	else {
+		struct tcf_result res;
+		int result = tc_classify(skb, p->filter_list, &res);
+
+		D2PRINTK("result %d class 0x%04x\n", result, res.classid);
+
 		switch (result) {
 #ifdef CONFIG_NET_CLS_POLICE
 			case TC_POLICE_SHOT:
 				kfree_skb(skb);
-				break;
+				sch->qstats.drops++;
+				return NET_XMIT_POLICED;
 #if 0
 			case TC_POLICE_RECLASSIFY:
 				/* FIXME: what to do here ??? */
@@ -243,43 +259,45 @@
 				break;
 		};
 	}
-	if (
-#ifdef CONFIG_NET_CLS_POLICE
-	    result == TC_POLICE_SHOT ||
-#endif
 
-	    ((ret = p->q->enqueue(skb,p->q)) != 0)) {
+	err = p->q->enqueue(skb,p->q);
+	if (err != NET_XMIT_SUCCESS) {
 		sch->qstats.drops++;
-		return ret;
+		return err;
 	}
+
 	sch->bstats.bytes += skb->len;
 	sch->bstats.packets++;
 	sch->q.qlen++;
-	return ret;
-}
 
+	return NET_XMIT_SUCCESS;
+}
 
 static struct sk_buff *dsmark_dequeue(struct Qdisc *sch)
 {
 	struct dsmark_qdisc_data *p = PRIV(sch);
 	struct sk_buff *skb;
-	int index;
+	u32 index;
 
-	D2PRINTK("dsmark_dequeue(sch %p,[qdisc %p])\n",sch,p);
+	D2PRINTK("dsmark_dequeue(sch %p,[qdisc %p])\n", sch, p);
+
 	skb = p->q->ops->dequeue(p->q);
-	if (!skb)
+	if (skb == NULL)
 		return NULL;
+
 	sch->q.qlen--;
-	index = skb->tc_index & (p->indices-1);
-	D2PRINTK("index %d->%d\n",skb->tc_index,index);
+
+	index = skb->tc_index & (p->indices - 1);
+	D2PRINTK("index %d->%d\n", skb->tc_index, index);
+
 	switch (skb->protocol) {
 		case __constant_htons(ETH_P_IP):
-			ipv4_change_dsfield(skb->nh.iph,
-			    p->mask[index],p->value[index]);
+			ipv4_change_dsfield(skb->nh.iph, p->mask[index],
+					    p->value[index]);
 			break;
 		case __constant_htons(ETH_P_IPV6):
-			ipv6_change_dsfield(skb->nh.ipv6h,
-			    p->mask[index],p->value[index]);
+			ipv6_change_dsfield(skb->nh.ipv6h, p->mask[index],
+					    p->value[index]);
 			break;
 		default:
 			/*
@@ -293,152 +311,162 @@
 				       htons(skb->protocol));
 			break;
 	};
+
 	return skb;
 }
 
-
 static int dsmark_requeue(struct sk_buff *skb,struct Qdisc *sch)
 {
-	int ret;
 	struct dsmark_qdisc_data *p = PRIV(sch);
+	int err;
 
-	D2PRINTK("dsmark_requeue(skb %p,sch %p,[qdisc %p])\n",skb,sch,p);
-        if ((ret = p->q->ops->requeue(skb, p->q)) == 0) {
-		sch->q.qlen++;
-		sch->qstats.requeues++;
-		return 0;
+	D2PRINTK("dsmark_requeue(skb %p,sch %p,[qdisc %p])\n", skb, sch, p);
+
+	err = p->q->ops->requeue(skb, p->q);
+	if (err != NET_XMIT_SUCCESS) {
+		sch->qstats.drops++;
+		return err;
 	}
-	sch->qstats.drops++;
-	return ret;
-}
 
+	sch->q.qlen++;
+	sch->qstats.requeues++;
+
+	return NET_XMIT_SUCCESS;
+}
 
 static unsigned int dsmark_drop(struct Qdisc *sch)
 {
 	struct dsmark_qdisc_data *p = PRIV(sch);
 	unsigned int len;
 	
-	DPRINTK("dsmark_reset(sch %p,[qdisc %p])\n",sch,p);
-	if (!p->q->ops->drop)
+	DPRINTK("dsmark_reset(sch %p,[qdisc %p])\n", sch, p);
+
+	if (p->q->ops->drop == NULL)
 		return 0;
-	if (!(len = p->q->ops->drop(p->q)))
-		return 0;
-	sch->q.qlen--;
+
+	len = p->q->ops->drop(p->q);
+	if (len)
+		sch->q.qlen--;
+
 	return len;
 }
 
-
-static int dsmark_init(struct Qdisc *sch,struct rtattr *opt)
+static int dsmark_init(struct Qdisc *sch, struct rtattr *opt)
 {
 	struct dsmark_qdisc_data *p = PRIV(sch);
 	struct rtattr *tb[TCA_DSMARK_MAX];
-	__u16 tmp;
+	int err = -EINVAL;
+	u32 default_index = NO_DEFAULT_INDEX;
+	u16 indices;
+	u8 *mask;
 
-	DPRINTK("dsmark_init(sch %p,[qdisc %p],opt %p)\n",sch,p,opt);
-	if (!opt ||
-	    rtattr_parse(tb,TCA_DSMARK_MAX,RTA_DATA(opt),RTA_PAYLOAD(opt)) < 0 ||
-	    !tb[TCA_DSMARK_INDICES-1] ||
-	    RTA_PAYLOAD(tb[TCA_DSMARK_INDICES-1]) < sizeof(__u16))
-                return -EINVAL;
-	p->indices = *(__u16 *) RTA_DATA(tb[TCA_DSMARK_INDICES-1]);
-	if (!p->indices)
-		return -EINVAL;
-	for (tmp = p->indices; tmp != 1; tmp >>= 1) {
-		if (tmp & 1)
-			return -EINVAL;
+	DPRINTK("dsmark_init(sch %p,[qdisc %p],opt %p)\n", sch, p, opt);
+
+	if (!opt || rtattr_parse_nested(tb, TCA_DSMARK_MAX, opt) < 0)
+		goto errout;
+
+	indices = RTA_GET_U16(tb[TCA_DSMARK_INDICES-1]);
+	if (!indices || !dsmark_valid_indices(indices))
+		goto errout;
+
+	if (tb[TCA_DSMARK_DEFAULT_INDEX-1])
+		default_index = RTA_GET_U16(tb[TCA_DSMARK_DEFAULT_INDEX-1]);
+
+	mask = kmalloc(indices * 2, GFP_KERNEL);
+	if (mask == NULL) {
+		err = -ENOMEM;
+		goto errout;
 	}
-	p->default_index = NO_DEFAULT_INDEX;
-	if (tb[TCA_DSMARK_DEFAULT_INDEX-1]) {
-		if (RTA_PAYLOAD(tb[TCA_DSMARK_DEFAULT_INDEX-1]) < sizeof(__u16))
-			return -EINVAL;
-		p->default_index =
-		    *(__u16 *) RTA_DATA(tb[TCA_DSMARK_DEFAULT_INDEX-1]);
-	}
-	p->set_tc_index = !!tb[TCA_DSMARK_SET_TC_INDEX-1];
-	p->mask = kmalloc(p->indices*2,GFP_KERNEL);
-	if (!p->mask)
-		return -ENOMEM;
-	p->value = p->mask+p->indices;
-	memset(p->mask,0xff,p->indices);
-	memset(p->value,0,p->indices);
-	if (!(p->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops)))
+
+	p->mask = mask;
+	memset(p->mask, 0xff, indices);
+
+	p->value = p->mask + indices;
+	memset(p->value, 0, indices);
+
+	p->indices = indices;
+	p->default_index = default_index;
+	p->set_tc_index = RTA_GET_FLAG(tb[TCA_DSMARK_SET_TC_INDEX-1]);
+
+	p->q = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
+	if (p->q == NULL)
 		p->q = &noop_qdisc;
-	DPRINTK("dsmark_init: qdisc %p\n",&p->q);
-	return 0;
-}
 
+	DPRINTK("dsmark_init: qdisc %p\n", p->q);
+
+	err = 0;
+errout:
+rtattr_failure:
+	return err;
+}
 
 static void dsmark_reset(struct Qdisc *sch)
 {
 	struct dsmark_qdisc_data *p = PRIV(sch);
 
-	DPRINTK("dsmark_reset(sch %p,[qdisc %p])\n",sch,p);
+	DPRINTK("dsmark_reset(sch %p,[qdisc %p])\n", sch, p);
 	qdisc_reset(p->q);
 	sch->q.qlen = 0;
 }
 
-
 static void dsmark_destroy(struct Qdisc *sch)
 {
 	struct dsmark_qdisc_data *p = PRIV(sch);
 	struct tcf_proto *tp;
 
-	DPRINTK("dsmark_destroy(sch %p,[qdisc %p])\n",sch,p);
+	DPRINTK("dsmark_destroy(sch %p,[qdisc %p])\n", sch, p);
+
 	while (p->filter_list) {
 		tp = p->filter_list;
 		p->filter_list = tp->next;
 		tcf_destroy(tp);
 	}
+
 	qdisc_destroy(p->q);
 	kfree(p->mask);
 }
 
-
 static int dsmark_dump_class(struct Qdisc *sch, unsigned long cl,
-    struct sk_buff *skb, struct tcmsg *tcm)
+			     struct sk_buff *skb, struct tcmsg *tcm)
 {
 	struct dsmark_qdisc_data *p = PRIV(sch);
-	unsigned char *b = skb->tail;
-	struct rtattr *rta;
+	struct rtattr *opts = NULL;
 
-	DPRINTK("dsmark_dump_class(sch %p,[qdisc %p],class %ld\n",sch,p,cl);
-	if (!cl || cl > p->indices)
+	DPRINTK("dsmark_dump_class(sch %p,[qdisc %p],class %ld\n", sch, p, cl);
+
+	if (!dsmark_valid_index(p, cl))
 		return -EINVAL;
-	tcm->tcm_handle = TC_H_MAKE(TC_H_MAJ(sch->handle),cl-1);
-	rta = (struct rtattr *) b;
-	RTA_PUT(skb,TCA_OPTIONS,0,NULL);
-	RTA_PUT(skb,TCA_DSMARK_MASK,1,&p->mask[cl-1]);
-	RTA_PUT(skb,TCA_DSMARK_VALUE,1,&p->value[cl-1]);
-	rta->rta_len = skb->tail-b;
-	return skb->len;
+
+	tcm->tcm_handle = TC_H_MAKE(TC_H_MAJ(sch->handle), cl-1);
+
+	opts = RTA_NEST(skb, TCA_OPTIONS);
+	RTA_PUT_U8(skb,TCA_DSMARK_MASK, p->mask[cl-1]);
+	RTA_PUT_U8(skb,TCA_DSMARK_VALUE, p->value[cl-1]);
+
+	return RTA_NEST_END(skb, opts);
 
 rtattr_failure:
-	skb_trim(skb,b-skb->data);
-	return -1;
+	return RTA_NEST_CANCEL(skb, opts);
 }
 
 static int dsmark_dump(struct Qdisc *sch, struct sk_buff *skb)
 {
 	struct dsmark_qdisc_data *p = PRIV(sch);
-	unsigned char *b = skb->tail;
-	struct rtattr *rta;
+	struct rtattr *opts = NULL;
 
-	rta = (struct rtattr *) b;
-	RTA_PUT(skb,TCA_OPTIONS,0,NULL);
-	RTA_PUT(skb,TCA_DSMARK_INDICES,sizeof(__u16),&p->indices);
-	if (p->default_index != NO_DEFAULT_INDEX) {
-		__u16 tmp = p->default_index;
+	opts = RTA_NEST(skb, TCA_OPTIONS);
+	RTA_PUT_U16(skb, TCA_DSMARK_INDICES, p->indices);
 
-		RTA_PUT(skb,TCA_DSMARK_DEFAULT_INDEX, sizeof(__u16), &tmp);
-	}
+	if (p->default_index != NO_DEFAULT_INDEX)
+		RTA_PUT_U16(skb, TCA_DSMARK_DEFAULT_INDEX, p->default_index);
+
 	if (p->set_tc_index)
-		RTA_PUT(skb, TCA_DSMARK_SET_TC_INDEX, 0, NULL);
-	rta->rta_len = skb->tail-b;
-	return skb->len;
+		RTA_PUT_FLAG(skb, TCA_DSMARK_SET_TC_INDEX);
+
+	return RTA_NEST_END(skb, opts);
 
 rtattr_failure:
-	skb_trim(skb,b-skb->data);
-	return -1;
+	return RTA_NEST_CANCEL(skb, opts);
 }
 
 static struct Qdisc_class_ops dsmark_class_ops = {
@@ -476,10 +504,13 @@
 {
 	return register_qdisc(&dsmark_qdisc_ops);
 }
+
 static void __exit dsmark_module_exit(void) 
 {
 	unregister_qdisc(&dsmark_qdisc_ops);
 }
+
 module_init(dsmark_module_init)
 module_exit(dsmark_module_exit)
+
 MODULE_LICENSE("GPL");
diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c
index 4888305..033083b 100644
--- a/net/sched/sch_fifo.c
+++ b/net/sched/sch_fifo.c
@@ -11,131 +11,38 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/bitops.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/socket.h>
-#include <linux/sockios.h>
-#include <linux/in.h>
 #include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h>
-#include <linux/inet.h>
 #include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/notifier.h>
-#include <net/ip.h>
-#include <net/route.h>
 #include <linux/skbuff.h>
-#include <net/sock.h>
 #include <net/pkt_sched.h>
 
 /* 1 band FIFO pseudo-"scheduler" */
 
 struct fifo_sched_data
 {
-	unsigned limit;
+	u32 limit;
 };
 
-static int
-bfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch)
+static int bfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch)
 {
 	struct fifo_sched_data *q = qdisc_priv(sch);
 
-	if (sch->qstats.backlog + skb->len <= q->limit) {
-		__skb_queue_tail(&sch->q, skb);
-		sch->qstats.backlog += skb->len;
-		sch->bstats.bytes += skb->len;
-		sch->bstats.packets++;
-		return 0;
-	}
-	sch->qstats.drops++;
-#ifdef CONFIG_NET_CLS_POLICE
-	if (sch->reshape_fail==NULL || sch->reshape_fail(skb, sch))
-#endif
-		kfree_skb(skb);
-	return NET_XMIT_DROP;
+	if (likely(sch->qstats.backlog + skb->len <= q->limit))
+		return qdisc_enqueue_tail(skb, sch);
+
+	return qdisc_reshape_fail(skb, sch);
 }
 
-static int
-bfifo_requeue(struct sk_buff *skb, struct Qdisc* sch)
-{
-	__skb_queue_head(&sch->q, skb);
-	sch->qstats.backlog += skb->len;
-	sch->qstats.requeues++;
-	return 0;
-}
-
-static struct sk_buff *
-bfifo_dequeue(struct Qdisc* sch)
-{
-	struct sk_buff *skb;
-
-	skb = __skb_dequeue(&sch->q);
-	if (skb)
-		sch->qstats.backlog -= skb->len;
-	return skb;
-}
-
-static unsigned int 
-fifo_drop(struct Qdisc* sch)
-{
-	struct sk_buff *skb;
-
-	skb = __skb_dequeue_tail(&sch->q);
-	if (skb) {
-		unsigned int len = skb->len;
-		sch->qstats.backlog -= len;
-		kfree_skb(skb);
-		return len;
-	}
-	return 0;
-}
-
-static void
-fifo_reset(struct Qdisc* sch)
-{
-	skb_queue_purge(&sch->q);
-	sch->qstats.backlog = 0;
-}
-
-static int
-pfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch)
+static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch)
 {
 	struct fifo_sched_data *q = qdisc_priv(sch);
 
-	if (sch->q.qlen < q->limit) {
-		__skb_queue_tail(&sch->q, skb);
-		sch->bstats.bytes += skb->len;
-		sch->bstats.packets++;
-		return 0;
-	}
-	sch->qstats.drops++;
-#ifdef CONFIG_NET_CLS_POLICE
-	if (sch->reshape_fail==NULL || sch->reshape_fail(skb, sch))
-#endif
-		kfree_skb(skb);
-	return NET_XMIT_DROP;
-}
+	if (likely(skb_queue_len(&sch->q) < q->limit))
+		return qdisc_enqueue_tail(skb, sch);
 
-static int
-pfifo_requeue(struct sk_buff *skb, struct Qdisc* sch)
-{
-	__skb_queue_head(&sch->q, skb);
-	sch->qstats.requeues++;
-	return 0;
-}
-
-
-static struct sk_buff *
-pfifo_dequeue(struct Qdisc* sch)
-{
-	return __skb_dequeue(&sch->q);
+	return qdisc_reshape_fail(skb, sch);
 }
 
 static int fifo_init(struct Qdisc *sch, struct rtattr *opt)
@@ -143,66 +50,59 @@
 	struct fifo_sched_data *q = qdisc_priv(sch);
 
 	if (opt == NULL) {
-		unsigned int limit = sch->dev->tx_queue_len ? : 1;
+		u32 limit = sch->dev->tx_queue_len ? : 1;
 
 		if (sch->ops == &bfifo_qdisc_ops)
-			q->limit = limit*sch->dev->mtu;
-		else	
-			q->limit = limit;
+			limit *= sch->dev->mtu;
+
+		q->limit = limit;
 	} else {
 		struct tc_fifo_qopt *ctl = RTA_DATA(opt);
-		if (opt->rta_len < RTA_LENGTH(sizeof(*ctl)))
+
+		if (RTA_PAYLOAD(opt) < sizeof(*ctl))
 			return -EINVAL;
+
 		q->limit = ctl->limit;
 	}
+
 	return 0;
 }
 
 static int fifo_dump(struct Qdisc *sch, struct sk_buff *skb)
 {
 	struct fifo_sched_data *q = qdisc_priv(sch);
-	unsigned char	 *b = skb->tail;
-	struct tc_fifo_qopt opt;
+	struct tc_fifo_qopt opt = { .limit = q->limit };
 
-	opt.limit = q->limit;
 	RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
-
 	return skb->len;
 
 rtattr_failure:
-	skb_trim(skb, b - skb->data);
 	return -1;
 }
 
 struct Qdisc_ops pfifo_qdisc_ops = {
-	.next		=	NULL,
-	.cl_ops		=	NULL,
 	.id		=	"pfifo",
 	.priv_size	=	sizeof(struct fifo_sched_data),
 	.enqueue	=	pfifo_enqueue,
-	.dequeue	=	pfifo_dequeue,
-	.requeue	=	pfifo_requeue,
-	.drop		=	fifo_drop,
+	.dequeue	=	qdisc_dequeue_head,
+	.requeue	=	qdisc_requeue,
+	.drop		=	qdisc_queue_drop,
 	.init		=	fifo_init,
-	.reset		=	fifo_reset,
-	.destroy	=	NULL,
+	.reset		=	qdisc_reset_queue,
 	.change		=	fifo_init,
 	.dump		=	fifo_dump,
 	.owner		=	THIS_MODULE,
 };
 
 struct Qdisc_ops bfifo_qdisc_ops = {
-	.next		=	NULL,
-	.cl_ops		=	NULL,
 	.id		=	"bfifo",
 	.priv_size	=	sizeof(struct fifo_sched_data),
 	.enqueue	=	bfifo_enqueue,
-	.dequeue	=	bfifo_dequeue,
-	.requeue	=	bfifo_requeue,
-	.drop		=	fifo_drop,
+	.dequeue	=	qdisc_dequeue_head,
+	.requeue	=	qdisc_requeue,
+	.drop		=	qdisc_queue_drop,
 	.init		=	fifo_init,
-	.reset		=	fifo_reset,
-	.destroy	=	NULL,
+	.reset		=	qdisc_reset_queue,
 	.change		=	fifo_init,
 	.dump		=	fifo_dump,
 	.owner		=	THIS_MODULE,
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 87e48a4..7683b34 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -243,31 +243,27 @@
    cheaper.
  */
 
-static int
-noop_enqueue(struct sk_buff *skb, struct Qdisc * qdisc)
+static int noop_enqueue(struct sk_buff *skb, struct Qdisc * qdisc)
 {
 	kfree_skb(skb);
 	return NET_XMIT_CN;
 }
 
-static struct sk_buff *
-noop_dequeue(struct Qdisc * qdisc)
+static struct sk_buff *noop_dequeue(struct Qdisc * qdisc)
 {
 	return NULL;
 }
 
-static int
-noop_requeue(struct sk_buff *skb, struct Qdisc* qdisc)
+static int noop_requeue(struct sk_buff *skb, struct Qdisc* qdisc)
 {
 	if (net_ratelimit())
-		printk(KERN_DEBUG "%s deferred output. It is buggy.\n", skb->dev->name);
+		printk(KERN_DEBUG "%s deferred output. It is buggy.\n",
+		       skb->dev->name);
 	kfree_skb(skb);
 	return NET_XMIT_CN;
 }
 
 struct Qdisc_ops noop_qdisc_ops = {
-	.next		=	NULL,
-	.cl_ops		=	NULL,
 	.id		=	"noop",
 	.priv_size	=	0,
 	.enqueue	=	noop_enqueue,
@@ -285,8 +281,6 @@
 };
 
 static struct Qdisc_ops noqueue_qdisc_ops = {
-	.next		=	NULL,
-	.cl_ops		=	NULL,
 	.id		=	"noqueue",
 	.priv_size	=	0,
 	.enqueue	=	noop_enqueue,
@@ -311,97 +305,87 @@
    generic prio+fifo combination.
  */
 
-static int
-pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc)
+#define PFIFO_FAST_BANDS 3
+
+static inline struct sk_buff_head *prio2list(struct sk_buff *skb,
+					     struct Qdisc *qdisc)
 {
 	struct sk_buff_head *list = qdisc_priv(qdisc);
-
-	list += prio2band[skb->priority&TC_PRIO_MAX];
-
-	if (list->qlen < qdisc->dev->tx_queue_len) {
-		__skb_queue_tail(list, skb);
-		qdisc->q.qlen++;
-		qdisc->bstats.bytes += skb->len;
-		qdisc->bstats.packets++;
-		return 0;
-	}
-	qdisc->qstats.drops++;
-	kfree_skb(skb);
-	return NET_XMIT_DROP;
+	return list + prio2band[skb->priority & TC_PRIO_MAX];
 }
 
-static struct sk_buff *
-pfifo_fast_dequeue(struct Qdisc* qdisc)
+static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc)
+{
+	struct sk_buff_head *list = prio2list(skb, qdisc);
+
+	if (skb_queue_len(list) < qdisc->dev->tx_queue_len) {
+		qdisc->q.qlen++;
+		return __qdisc_enqueue_tail(skb, qdisc, list);
+	}
+
+	return qdisc_drop(skb, qdisc);
+}
+
+static struct sk_buff *pfifo_fast_dequeue(struct Qdisc* qdisc)
 {
 	int prio;
 	struct sk_buff_head *list = qdisc_priv(qdisc);
-	struct sk_buff *skb;
 
-	for (prio = 0; prio < 3; prio++, list++) {
-		skb = __skb_dequeue(list);
+	for (prio = 0; prio < PFIFO_FAST_BANDS; prio++, list++) {
+		struct sk_buff *skb = __qdisc_dequeue_head(qdisc, list);
 		if (skb) {
 			qdisc->q.qlen--;
 			return skb;
 		}
 	}
+
 	return NULL;
 }
 
-static int
-pfifo_fast_requeue(struct sk_buff *skb, struct Qdisc* qdisc)
+static int pfifo_fast_requeue(struct sk_buff *skb, struct Qdisc* qdisc)
 {
-	struct sk_buff_head *list = qdisc_priv(qdisc);
-
-	list += prio2band[skb->priority&TC_PRIO_MAX];
-
-	__skb_queue_head(list, skb);
 	qdisc->q.qlen++;
-	qdisc->qstats.requeues++;
-	return 0;
+	return __qdisc_requeue(skb, qdisc, prio2list(skb, qdisc));
 }
 
-static void
-pfifo_fast_reset(struct Qdisc* qdisc)
+static void pfifo_fast_reset(struct Qdisc* qdisc)
 {
 	int prio;
 	struct sk_buff_head *list = qdisc_priv(qdisc);
 
-	for (prio=0; prio < 3; prio++)
-		skb_queue_purge(list+prio);
+	for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)
+		__qdisc_reset_queue(qdisc, list + prio);
+
+	qdisc->qstats.backlog = 0;
 	qdisc->q.qlen = 0;
 }
 
 static int pfifo_fast_dump(struct Qdisc *qdisc, struct sk_buff *skb)
 {
-	unsigned char	 *b = skb->tail;
-	struct tc_prio_qopt opt;
+	struct tc_prio_qopt opt = { .bands = PFIFO_FAST_BANDS };
 
-	opt.bands = 3; 
 	memcpy(&opt.priomap, prio2band, TC_PRIO_MAX+1);
 	RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
 	return skb->len;
 
 rtattr_failure:
-	skb_trim(skb, b - skb->data);
 	return -1;
 }
 
 static int pfifo_fast_init(struct Qdisc *qdisc, struct rtattr *opt)
 {
-	int i;
+	int prio;
 	struct sk_buff_head *list = qdisc_priv(qdisc);
 
-	for (i=0; i<3; i++)
-		skb_queue_head_init(list+i);
+	for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)
+		skb_queue_head_init(list + prio);
 
 	return 0;
 }
 
 static struct Qdisc_ops pfifo_fast_ops = {
-	.next		=	NULL,
-	.cl_ops		=	NULL,
 	.id		=	"pfifo_fast",
-	.priv_size	=	3 * sizeof(struct sk_buff_head),
+	.priv_size	=	PFIFO_FAST_BANDS * sizeof(struct sk_buff_head),
 	.enqueue	=	pfifo_fast_enqueue,
 	.dequeue	=	pfifo_fast_dequeue,
 	.requeue	=	pfifo_fast_requeue,
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 663843d..7ae6aa7 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -191,10 +191,6 @@
 	asoc->last_cwr_tsn = asoc->ctsn_ack_point;
 	asoc->unack_data = 0;
 
-	SCTP_DEBUG_PRINTK("myctsnap for %s INIT as 0x%x.\n",
-			  asoc->ep->debug_name,
-			  asoc->ctsn_ack_point);
-
 	/* ADDIP Section 4.1 Asconf Chunk Procedures
 	 *
 	 * When an endpoint has an ASCONF signaled change to be sent to the
@@ -211,6 +207,7 @@
 
 	/* Make an empty list of remote transport addresses.  */
 	INIT_LIST_HEAD(&asoc->peer.transport_addr_list);
+	asoc->peer.transport_count = 0;
 
 	/* RFC 2960 5.1 Normal Establishment of an Association
 	 *
@@ -288,6 +285,7 @@
 
 	asoc->base.malloced = 1;
 	SCTP_DBG_OBJCNT_INC(assoc);
+	SCTP_DEBUG_PRINTK("Created asoc %p\n", asoc);
 
 	return asoc;
 
@@ -356,6 +354,8 @@
 		sctp_transport_free(transport);
 	}
 
+	asoc->peer.transport_count = 0;
+
 	/* Free any cached ASCONF_ACK chunk. */
 	if (asoc->addip_last_asconf_ack)
 		sctp_chunk_free(asoc->addip_last_asconf_ack);
@@ -400,7 +400,7 @@
 	/* If the primary path is changing, assume that the
 	 * user wants to use this new path.
 	 */
-	if (transport->active)
+	if (transport->state != SCTP_INACTIVE)
 		asoc->peer.active_path = transport;
 
 	/*
@@ -428,10 +428,58 @@
 	transport->cacc.next_tsn_at_change = asoc->next_tsn;
 }
 
+/* Remove a transport from an association.  */
+void sctp_assoc_rm_peer(struct sctp_association *asoc,
+			struct sctp_transport *peer)
+{
+	struct list_head	*pos;
+	struct sctp_transport	*transport;
+
+	SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_rm_peer:association %p addr: ",
+				 " port: %d\n",
+				 asoc,
+				 (&peer->ipaddr),
+				 peer->ipaddr.v4.sin_port);
+
+	/* If we are to remove the current retran_path, update it
+	 * to the next peer before removing this peer from the list.
+	 */
+	if (asoc->peer.retran_path == peer)
+		sctp_assoc_update_retran_path(asoc);
+
+	/* Remove this peer from the list. */
+	list_del(&peer->transports);
+
+	/* Get the first transport of asoc. */
+	pos = asoc->peer.transport_addr_list.next;
+	transport = list_entry(pos, struct sctp_transport, transports);
+
+	/* Update any entries that match the peer to be deleted. */
+	if (asoc->peer.primary_path == peer)
+		sctp_assoc_set_primary(asoc, transport);
+	if (asoc->peer.active_path == peer)
+		asoc->peer.active_path = transport;
+	if (asoc->peer.last_data_from == peer)
+		asoc->peer.last_data_from = transport;
+
+	/* If we remove the transport an INIT was last sent to, set it to
+	 * NULL. Combined with the update of the retran path above, this
+	 * will cause the next INIT to be sent to the next available
+	 * transport, maintaining the cycle.
+	 */
+	if (asoc->init_last_sent_to == peer)
+		asoc->init_last_sent_to = NULL;
+
+	asoc->peer.transport_count--;
+
+	sctp_transport_free(peer);
+}
+
 /* Add a transport address to an association.  */
 struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
 					   const union sctp_addr *addr,
-					   int gfp)
+					   const int gfp,
+					   const int peer_state)
 {
 	struct sctp_transport *peer;
 	struct sctp_sock *sp;
@@ -442,14 +490,25 @@
 	/* AF_INET and AF_INET6 share common port field. */
 	port = addr->v4.sin_port;
 
+	SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_add_peer:association %p addr: ",
+				 " port: %d state:%s\n",
+				 asoc,
+				 addr,
+				 addr->v4.sin_port,
+				 peer_state == SCTP_UNKNOWN?"UNKNOWN":"ACTIVE");
+
 	/* Set the port if it has not been set yet.  */
 	if (0 == asoc->peer.port)
 		asoc->peer.port = port;
 
 	/* Check to see if this is a duplicate. */
 	peer = sctp_assoc_lookup_paddr(asoc, addr);
-	if (peer)
+	if (peer) {
+		if (peer_state == SCTP_ACTIVE &&
+		    peer->state == SCTP_UNKNOWN)
+		     peer->state = SCTP_ACTIVE;
 		return peer;
+	}
 
 	peer = sctp_transport_new(addr, gfp);
 	if (!peer)
@@ -516,8 +575,12 @@
 	/* Set the transport's RTO.initial value */
 	peer->rto = asoc->rto_initial;
 
+	/* Set the peer's active state. */
+	peer->state = peer_state;
+
 	/* Attach the remote transport to our asoc.  */
 	list_add_tail(&peer->transports, &asoc->peer.transport_addr_list);
+	asoc->peer.transport_count++;
 
 	/* If we do not yet have a primary path, set one.  */
 	if (!asoc->peer.primary_path) {
@@ -525,8 +588,9 @@
 		asoc->peer.retran_path = peer;
 	}
 
-	if (asoc->peer.active_path == asoc->peer.retran_path)
+	if (asoc->peer.active_path == asoc->peer.retran_path) {
 		asoc->peer.retran_path = peer;
+	}
 
 	return peer;
 }
@@ -537,37 +601,16 @@
 {
 	struct list_head	*pos;
 	struct list_head	*temp;
-	struct sctp_transport	*peer = NULL;
 	struct sctp_transport	*transport;
 
 	list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
 		transport = list_entry(pos, struct sctp_transport, transports);
 		if (sctp_cmp_addr_exact(addr, &transport->ipaddr)) {
-			peer = transport;
-			list_del(pos);
+			/* Do book keeping for removing the peer and free it. */
+			sctp_assoc_rm_peer(asoc, transport);
 			break;
 		}
 	}
-
-	/* The address we want delete is not in the association. */
-	if (!peer)
-		return;
-
-	/* Get the first transport of asoc. */ 
-	pos = asoc->peer.transport_addr_list.next;
-	transport = list_entry(pos, struct sctp_transport, transports);
-
-	/* Update any entries that match the peer to be deleted. */  
-	if (asoc->peer.primary_path == peer)
-		sctp_assoc_set_primary(asoc, transport);
-	if (asoc->peer.active_path == peer)
-		asoc->peer.active_path = transport;
-	if (asoc->peer.retran_path == peer)
-		asoc->peer.retran_path = transport;
-	if (asoc->peer.last_data_from == peer)
-		asoc->peer.last_data_from = transport;
-
-	sctp_transport_free(peer);
 }
 
 /* Lookup a transport by address. */
@@ -608,12 +651,12 @@
 	/* Record the transition on the transport.  */
 	switch (command) {
 	case SCTP_TRANSPORT_UP:
-		transport->active = SCTP_ACTIVE;
+		transport->state = SCTP_ACTIVE;
 		spc_state = SCTP_ADDR_AVAILABLE;
 		break;
 
 	case SCTP_TRANSPORT_DOWN:
-		transport->active = SCTP_INACTIVE;
+		transport->state = SCTP_INACTIVE;
 		spc_state = SCTP_ADDR_UNREACHABLE;
 		break;
 
@@ -643,7 +686,7 @@
 	list_for_each(pos, &asoc->peer.transport_addr_list) {
 		t = list_entry(pos, struct sctp_transport, transports);
 
-		if (!t->active)
+		if (t->state == SCTP_INACTIVE)
 			continue;
 		if (!first || t->last_time_heard > first->last_time_heard) {
 			second = first;
@@ -663,7 +706,7 @@
 	 * [If the primary is active but not most recent, bump the most
 	 * recently used transport.]
 	 */
-	if (asoc->peer.primary_path->active &&
+	if (asoc->peer.primary_path->state != SCTP_INACTIVE &&
 	    first != asoc->peer.primary_path) {
 		second = first;
 		first = asoc->peer.primary_path;
@@ -958,7 +1001,7 @@
 					   transports);
 			if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr))
 				sctp_assoc_add_peer(asoc, &trans->ipaddr,
-						    GFP_ATOMIC);
+						    GFP_ATOMIC, SCTP_ACTIVE);
 		}
 
 		asoc->ctsn_ack_point = asoc->next_tsn - 1;
@@ -998,7 +1041,7 @@
 
 		/* Try to find an active transport. */
 
-		if (t->active) {
+		if (t->state != SCTP_INACTIVE) {
 			break;
 		} else {
 			/* Keep track of the next transport in case
@@ -1019,6 +1062,40 @@
 	}
 
 	asoc->peer.retran_path = t;
+
+	SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association"
+				 " %p addr: ",
+				 " port: %d\n",
+				 asoc,
+				 (&t->ipaddr),
+				 t->ipaddr.v4.sin_port);
+}
+
+/* Choose the transport for sending a INIT packet.  */
+struct sctp_transport *sctp_assoc_choose_init_transport(
+	struct sctp_association *asoc)
+{
+	struct sctp_transport *t;
+
+	/* Use the retran path. If the last INIT was sent over the
+	 * retran path, update the retran path and use it.
+	 */
+	if (!asoc->init_last_sent_to) {
+		t = asoc->peer.active_path;
+	} else {
+		if (asoc->init_last_sent_to == asoc->peer.retran_path)
+			sctp_assoc_update_retran_path(asoc);
+		t = asoc->peer.retran_path;
+	}
+
+	SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association"
+				 " %p addr: ",
+				 " port: %d\n",
+				 asoc,
+				 (&t->ipaddr),
+				 t->ipaddr.v4.sin_port);
+
+	return t;
 }
 
 /* Choose the transport for sending a SHUTDOWN packet.  */
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 334f617..2ec0320 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -134,7 +134,6 @@
 	ep->last_key = ep->current_key = 0;
 	ep->key_changed_at = jiffies;
 
-	ep->debug_name = "unnamedEndpoint";
 	return ep;
 }
 
diff --git a/net/sctp/input.c b/net/sctp/input.c
index b719a77..339f7ac 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -178,6 +178,37 @@
 
 	asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport);
 
+	if (!asoc)
+		ep = __sctp_rcv_lookup_endpoint(&dest);
+
+	/* Retrieve the common input handling substructure. */
+	rcvr = asoc ? &asoc->base : &ep->base;
+	sk = rcvr->sk;
+
+	/*
+	 * If a frame arrives on an interface and the receiving socket is
+	 * bound to another interface, via SO_BINDTODEVICE, treat it as OOTB
+	 */
+	if (sk->sk_bound_dev_if && (sk->sk_bound_dev_if != af->skb_iif(skb)))
+	{
+		sock_put(sk);
+		if (asoc) {
+			sctp_association_put(asoc);
+			asoc = NULL;
+		} else {
+			sctp_endpoint_put(ep);
+			ep = NULL;
+		}
+		sk = sctp_get_ctl_sock();
+		ep = sctp_sk(sk)->ep;
+		sctp_endpoint_hold(ep);
+		sock_hold(sk);
+		rcvr = &ep->base;
+	}
+
+	if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)
+		goto discard_release;
+
 	/*
 	 * RFC 2960, 8.4 - Handle "Out of the blue" Packets.
 	 * An SCTP packet is called an "out of the blue" (OOTB)
@@ -187,22 +218,12 @@
 	 * packet belongs.
 	 */
 	if (!asoc) {
-		ep = __sctp_rcv_lookup_endpoint(&dest);
 		if (sctp_rcv_ootb(skb)) {
 			SCTP_INC_STATS_BH(SCTP_MIB_OUTOFBLUES);
 			goto discard_release;
 		}
 	}
 
-	/* Retrieve the common input handling substructure. */
-	rcvr = asoc ? &asoc->base : &ep->base;
-	sk = rcvr->sk;
-
-	if ((sk) && (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)) {
-		goto discard_release;
-	}
-
-
 	/* SCTP seems to always need a timestamp right now (FIXME) */
 	if (skb->stamp.tv_sec == 0) {
 		do_gettimeofday(&skb->stamp);
@@ -265,13 +286,11 @@
 
 discard_release:
 	/* Release any structures we may be holding. */
-	if (asoc) {
-		sock_put(asoc->base.sk);
+	sock_put(sk);
+	if (asoc)
 		sctp_association_put(asoc);
-	} else {
-		sock_put(ep->base.sk);
+	else
 		sctp_endpoint_put(ep);
-	}
 
 	goto discard_it;
 }
@@ -334,7 +353,7 @@
 
 	sctp_do_sm(SCTP_EVENT_T_OTHER,
 		   SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH),
-		   asoc->state, asoc->ep, asoc, NULL,
+		   asoc->state, asoc->ep, asoc, t,
 		   GFP_ATOMIC);
 
 }
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index c9d9ea0..c7e42d1 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -812,26 +812,23 @@
 	if (addr->sa.sa_family != AF_INET6)
 		af = sctp_get_af_specific(addr->sa.sa_family);
 	else {
-		struct sock *sk;
 		int type = ipv6_addr_type(&addr->v6.sin6_addr);
-		sk = sctp_opt2sk(opt);
-		if (type & IPV6_ADDR_LINKLOCAL) {
-			/* Note: Behavior similar to af_inet6.c:
-			 *  1) Overrides previous bound_dev_if
-			 *  2) Destructive even if bind isn't successful.
-			 */
+		struct net_device *dev;
 
-			if (addr->v6.sin6_scope_id)
-				sk->sk_bound_dev_if = addr->v6.sin6_scope_id;
-			if (!sk->sk_bound_dev_if)
+		if (type & IPV6_ADDR_LINKLOCAL) {
+			if (!addr->v6.sin6_scope_id)
 				return 0;
+			dev = dev_get_by_index(addr->v6.sin6_scope_id);
+			if (!dev)
+				return 0;
+			dev_put(dev);
 		}
 		af = opt->pf->af;
 	}
 	return af->available(addr, opt);
 }
 
-/* Verify that the provided sockaddr looks bindable.   Common verification,
+/* Verify that the provided sockaddr looks sendable.   Common verification,
  * has already been taken care of.
  */
 static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr)
@@ -842,19 +839,16 @@
 	if (addr->sa.sa_family != AF_INET6)
 		af = sctp_get_af_specific(addr->sa.sa_family);
 	else {
-		struct sock *sk;
 		int type = ipv6_addr_type(&addr->v6.sin6_addr);
-		sk = sctp_opt2sk(opt);
-		if (type & IPV6_ADDR_LINKLOCAL) {
-			/* Note: Behavior similar to af_inet6.c:
-			 *  1) Overrides previous bound_dev_if
-			 *  2) Destructive even if bind isn't successful.
-			 */
+		struct net_device *dev;
 
-			if (addr->v6.sin6_scope_id)
-				sk->sk_bound_dev_if = addr->v6.sin6_scope_id;
-			if (!sk->sk_bound_dev_if)
+		if (type & IPV6_ADDR_LINKLOCAL) {
+			if (!addr->v6.sin6_scope_id)
 				return 0;
+			dev = dev_get_by_index(addr->v6.sin6_scope_id);
+			if (!dev)
+				return 0;
+			dev_put(dev);
 		}
 		af = opt->pf->af;
 	}
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 1b2d4ad..4eb81a1 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -682,9 +682,9 @@
 
 		if (!new_transport) {
 			new_transport = asoc->peer.active_path;
-		} else if (!new_transport->active) {
-			/* If the chunk is Heartbeat or Heartbeat Ack, 
-			 * send it to chunk->transport, even if it's 
+		} else if (new_transport->state == SCTP_INACTIVE) {
+			/* If the chunk is Heartbeat or Heartbeat Ack,
+			 * send it to chunk->transport, even if it's
 			 * inactive.
 			 *
 			 * 3.3.6 Heartbeat Acknowledgement:
@@ -840,7 +840,8 @@
 			 * Otherwise, we want to use the active path.
 			 */
 			new_transport = chunk->transport;
-			if (!new_transport || !new_transport->active)
+			if (!new_transport ||
+			    new_transport->state == SCTP_INACTIVE)
 				new_transport = asoc->peer.active_path;
 
 			/* Change packets if necessary.  */
@@ -1454,7 +1455,7 @@
 			/* Mark the destination transport address as
 			 * active if it is not so marked.
 			 */
-			if (!transport->active) {
+			if (transport->state == SCTP_INACTIVE) {
 				sctp_assoc_control_transport(
 					transport->asoc,
 					transport,
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index e42fd8c..98d49ec9 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -132,14 +132,25 @@
 static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_common *epb)
 {
 	struct list_head *pos;
+	struct sctp_association *asoc;
 	struct sctp_sockaddr_entry *laddr;
-	union sctp_addr *addr;
+	struct sctp_transport *peer;
+	union sctp_addr *addr, *primary = NULL;
 	struct sctp_af *af;
 
+	if (epb->type == SCTP_EP_TYPE_ASSOCIATION) {
+	    asoc = sctp_assoc(epb);
+	    peer = asoc->peer.primary_path;
+	    primary = &peer->saddr;
+	}
+
 	list_for_each(pos, &epb->bind_addr.address_list) {
 		laddr = list_entry(pos, struct sctp_sockaddr_entry, list);
 		addr = (union sctp_addr *)&laddr->a;
 		af = sctp_get_af_specific(addr->sa.sa_family);
+		if (primary && af->cmp_addr(addr, primary)) {
+			seq_printf(seq, "*");
+		}
 		af->seq_dump_addr(seq, addr);
 	}
 }
@@ -149,17 +160,54 @@
 {
 	struct list_head *pos;
 	struct sctp_transport *transport;
-	union sctp_addr *addr;
+	union sctp_addr *addr, *primary;
 	struct sctp_af *af;
 
+	primary = &(assoc->peer.primary_addr);
 	list_for_each(pos, &assoc->peer.transport_addr_list) {
 		transport = list_entry(pos, struct sctp_transport, transports);
 		addr = (union sctp_addr *)&transport->ipaddr;
 		af = sctp_get_af_specific(addr->sa.sa_family);
+		if (af->cmp_addr(addr, primary)) {
+			seq_printf(seq, "*");
+		}
 		af->seq_dump_addr(seq, addr);
 	}
 }
 
+static void * sctp_eps_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	if (*pos > sctp_ep_hashsize)
+		return NULL;
+
+	if (*pos < 0)
+		*pos = 0;
+
+	if (*pos == 0)
+		seq_printf(seq, " ENDPT     SOCK   STY SST HBKT LPORT   UID INODE LADDRS\n");
+
+	++*pos;
+
+	return (void *)pos;
+}
+
+static void sctp_eps_seq_stop(struct seq_file *seq, void *v)
+{
+	return;
+}
+
+
+static void * sctp_eps_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	if (*pos > sctp_ep_hashsize)
+		return NULL;
+
+	++*pos;
+
+	return pos;
+}
+
+
 /* Display sctp endpoints (/proc/net/sctp/eps). */
 static int sctp_eps_seq_show(struct seq_file *seq, void *v)
 {
@@ -167,38 +215,50 @@
 	struct sctp_ep_common *epb;
 	struct sctp_endpoint *ep;
 	struct sock *sk;
-	int hash;
+	int    hash = *(int *)v;
 
-	seq_printf(seq, " ENDPT     SOCK   STY SST HBKT LPORT LADDRS\n");
-	for (hash = 0; hash < sctp_ep_hashsize; hash++) {
-		head = &sctp_ep_hashtable[hash];
-		read_lock(&head->lock);
-		for (epb = head->chain; epb; epb = epb->next) {
-			ep = sctp_ep(epb);
-			sk = epb->sk;
-			seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d ", ep, sk,
-				   sctp_sk(sk)->type, sk->sk_state, hash,
-				   epb->bind_addr.port);
-			sctp_seq_dump_local_addrs(seq, epb);
-			seq_printf(seq, "\n");
-		}
-		read_unlock(&head->lock);
+	if (hash > sctp_ep_hashsize)
+		return -ENOMEM;
+
+	head = &sctp_ep_hashtable[hash-1];
+	sctp_local_bh_disable();
+	read_lock(&head->lock);
+	for (epb = head->chain; epb; epb = epb->next) {
+		ep = sctp_ep(epb);
+		sk = epb->sk;
+		seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk,
+			   sctp_sk(sk)->type, sk->sk_state, hash-1,
+			   epb->bind_addr.port,
+			   sock_i_uid(sk), sock_i_ino(sk));
+
+		sctp_seq_dump_local_addrs(seq, epb);
+		seq_printf(seq, "\n");
 	}
+	read_unlock(&head->lock);
+	sctp_local_bh_enable();
 
 	return 0;
 }
 
+static struct seq_operations sctp_eps_ops = {
+	.start = sctp_eps_seq_start,
+	.next  = sctp_eps_seq_next,
+	.stop  = sctp_eps_seq_stop,
+	.show  = sctp_eps_seq_show,
+};
+
+
 /* Initialize the seq file operations for 'eps' object. */
 static int sctp_eps_seq_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, sctp_eps_seq_show, NULL);
+	return seq_open(file, &sctp_eps_ops);
 }
 
 static struct file_operations sctp_eps_seq_fops = {
 	.open	 = sctp_eps_seq_open,
 	.read	 = seq_read,
 	.llseek	 = seq_lseek,
-	.release = single_release,
+	.release = seq_release,
 };
 
 /* Set up the proc fs entry for 'eps' object. */
@@ -221,6 +281,40 @@
 	remove_proc_entry("eps", proc_net_sctp);
 }
 
+
+static void * sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	if (*pos > sctp_assoc_hashsize)
+		return NULL;
+
+	if (*pos < 0)
+		*pos = 0;
+
+	if (*pos == 0)
+		seq_printf(seq, " ASSOC     SOCK   STY SST ST HBKT ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT "
+				"RPORT LADDRS <-> RADDRS\n");
+
+	++*pos;
+
+	return (void *)pos;
+}
+
+static void sctp_assocs_seq_stop(struct seq_file *seq, void *v)
+{
+	return;
+}
+
+
+static void * sctp_assocs_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	if (*pos > sctp_assoc_hashsize)
+		return NULL;
+
+	++*pos;
+
+	return pos;
+}
+
 /* Display sctp associations (/proc/net/sctp/assocs). */
 static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
 {
@@ -228,43 +322,57 @@
 	struct sctp_ep_common *epb;
 	struct sctp_association *assoc;
 	struct sock *sk;
-	int hash;
+	int    hash = *(int *)v;
 
-	seq_printf(seq, " ASSOC     SOCK   STY SST ST HBKT LPORT RPORT "
-			"LADDRS <-> RADDRS\n");
-	for (hash = 0; hash < sctp_assoc_hashsize; hash++) {
-		head = &sctp_assoc_hashtable[hash];
-		read_lock(&head->lock);
-		for (epb = head->chain; epb; epb = epb->next) {
-			assoc = sctp_assoc(epb);
-			sk = epb->sk;
-			seq_printf(seq,
-				   "%8p %8p %-3d %-3d %-2d %-4d %-5d %-5d ",
-				   assoc, sk, sctp_sk(sk)->type, sk->sk_state,
-				   assoc->state, hash, epb->bind_addr.port,
-				   assoc->peer.port);
-			sctp_seq_dump_local_addrs(seq, epb);
-			seq_printf(seq, "<-> ");
-			sctp_seq_dump_remote_addrs(seq, assoc);
-			seq_printf(seq, "\n");
-		}
-		read_unlock(&head->lock);
+	if (hash > sctp_assoc_hashsize)
+		return -ENOMEM;
+
+	head = &sctp_assoc_hashtable[hash-1];
+	sctp_local_bh_disable();
+	read_lock(&head->lock);
+	for (epb = head->chain; epb; epb = epb->next) {
+		assoc = sctp_assoc(epb);
+		sk = epb->sk;
+		seq_printf(seq,
+			   "%8p %8p %-3d %-3d %-2d %-4d %4d %8d %8d %7d %5lu %-5d %5d ",
+			   assoc, sk, sctp_sk(sk)->type, sk->sk_state,
+			   assoc->state, hash-1, assoc->assoc_id,
+			   (sk->sk_rcvbuf - assoc->rwnd),
+			   assoc->sndbuf_used,
+			   sock_i_uid(sk), sock_i_ino(sk),
+			   epb->bind_addr.port,
+			   assoc->peer.port);
+
+		seq_printf(seq, " ");
+		sctp_seq_dump_local_addrs(seq, epb);
+		seq_printf(seq, "<-> ");
+		sctp_seq_dump_remote_addrs(seq, assoc);
+		seq_printf(seq, "\n");
 	}
+	read_unlock(&head->lock);
+	sctp_local_bh_enable();
 
 	return 0;
 }
 
+static struct seq_operations sctp_assoc_ops = {
+	.start = sctp_assocs_seq_start,
+	.next  = sctp_assocs_seq_next,
+	.stop  = sctp_assocs_seq_stop,
+	.show  = sctp_assocs_seq_show,
+};
+
 /* Initialize the seq file operations for 'assocs' object. */
 static int sctp_assocs_seq_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, sctp_assocs_seq_show, NULL);
+	return seq_open(file, &sctp_assoc_ops);
 }
 
 static struct file_operations sctp_assocs_seq_fops = {
 	.open	 = sctp_assocs_seq_open,
 	.read	 = seq_read,
 	.llseek	 = seq_lseek,
-	.release = single_release,
+	.release = seq_release,
 };
 
 /* Set up the proc fs entry for 'assocs' object. */
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 2e1f9c3..5135e1a 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -378,10 +378,13 @@
 {
 	int ret = inet_addr_type(addr->v4.sin_addr.s_addr);
 
-	/* FIXME: ip_nonlocal_bind sysctl support. */
 
-	if (addr->v4.sin_addr.s_addr != INADDR_ANY && ret != RTN_LOCAL)
+	if (addr->v4.sin_addr.s_addr != INADDR_ANY &&
+	   ret != RTN_LOCAL &&
+	   !sp->inet.freebind &&
+	   !sysctl_ip_nonlocal_bind)
 		return 0;
+
 	return 1;
 }
 
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 33ac8bf..5baed9b 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1830,7 +1830,7 @@
 	 * be a a better choice than any of the embedded addresses.
 	 */
 	if (peer_addr)
-		if(!sctp_assoc_add_peer(asoc, peer_addr, gfp))
+		if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE))
 			goto nomem;
 
 	/* Process the initialization parameters.  */
@@ -1841,6 +1841,14 @@
                         goto clean_up;
 	}
 
+	/* Walk list of transports, removing transports in the UNKNOWN state. */
+	list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
+		transport = list_entry(pos, struct sctp_transport, transports);
+		if (transport->state == SCTP_UNKNOWN) {
+			sctp_assoc_rm_peer(asoc, transport);
+		}
+	}
+
 	/* The fixed INIT headers are always in network byte
 	 * order.
 	 */
@@ -1906,7 +1914,8 @@
 	 * stream sequence number shall be set to 0.
 	 */
 
-	/* Allocate storage for the negotiated streams if it is not a temporary 	 * association.
+	/* Allocate storage for the negotiated streams if it is not a temporary
+ 	 * association.
 	 */
 	if (!asoc->temp) {
 		int assoc_id;
@@ -1952,6 +1961,9 @@
 		list_del_init(pos);
 		sctp_transport_free(transport);
 	}
+
+	asoc->peer.transport_count = 0;
+
 nomem:
 	return 0;
 }
@@ -1995,7 +2007,7 @@
 		af->from_addr_param(&addr, param.addr, asoc->peer.port, 0);
 		scope = sctp_scope(peer_addr);
 		if (sctp_in_scope(&addr, scope))
-			if (!sctp_assoc_add_peer(asoc, &addr, gfp))
+			if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_ACTIVE))
 				return 0;
 		break;
 
@@ -2396,7 +2408,7 @@
 	 	 * Due to Resource Shortage'.
 	 	 */
 
-		peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC);
+		peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_ACTIVE);
 		if (!peer)
 			return SCTP_ERROR_RSRC_LOW;
 
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index f65fa44..778639d 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -414,11 +414,13 @@
 	 */
 	asoc->overall_error_count++;
 
-	if (transport->active &&
+	if (transport->state != SCTP_INACTIVE &&
 	    (transport->error_count++ >= transport->max_retrans)) {
-		SCTP_DEBUG_PRINTK("transport_strike: transport "
-				  "IP:%d.%d.%d.%d failed.\n",
-				  NIPQUAD(transport->ipaddr.v4.sin_addr));
+		SCTP_DEBUG_PRINTK_IPADDR("transport_strike:association %p",
+					 " transport IP: port:%d failed.\n",
+					 asoc,
+					 (&transport->ipaddr),
+					 transport->ipaddr.v4.sin_port);
 		sctp_assoc_control_transport(asoc, transport,
 					     SCTP_TRANSPORT_DOWN,
 					     SCTP_FAILED_THRESHOLD);
@@ -593,7 +595,7 @@
 	/* Mark the destination transport address as active if it is not so
 	 * marked.
 	 */
-	if (!t->active)
+	if (t->state == SCTP_INACTIVE)
 		sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP,
 					     SCTP_HEARTBEAT_SUCCESS);
 
@@ -665,8 +667,11 @@
 
 	asoc->state = state;
 
+	SCTP_DEBUG_PRINTK("sctp_cmd_new_state: asoc %p[%s]\n",
+			  asoc, sctp_state_tbl[state]);
+
 	if (sctp_style(sk, TCP)) {
-		/* Change the sk->sk_state of a TCP-style socket that has 
+		/* Change the sk->sk_state of a TCP-style socket that has
 		 * sucessfully completed a connect() call.
 		 */
 		if (sctp_state(asoc, ESTABLISHED) && sctp_sstate(sk, CLOSED))
@@ -678,6 +683,16 @@
 			sk->sk_shutdown |= RCV_SHUTDOWN;
 	}
 
+	if (sctp_state(asoc, COOKIE_WAIT)) {
+		/* Reset init timeouts since they may have been
+		 * increased due to timer expirations.
+		 */
+		asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
+			asoc->ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT];
+		asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =
+			asoc->ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE];
+	}
+
 	if (sctp_state(asoc, ESTABLISHED) ||
 	    sctp_state(asoc, CLOSED) ||
 	    sctp_state(asoc, SHUTDOWN_RECEIVED)) {
@@ -1120,10 +1135,10 @@
 			 * to be executed only during failed attempts of
 			 * association establishment.
 			 */
-			if ((asoc->peer.retran_path != 
-			     asoc->peer.primary_path) && 
-			    (asoc->counters[SCTP_COUNTER_INIT_ERROR] > 0)) {
-				sctp_add_cmd_sf(commands, 
+			if ((asoc->peer.retran_path !=
+			     asoc->peer.primary_path) &&
+			    (asoc->init_err_counter > 0)) {
+				sctp_add_cmd_sf(commands,
 				                SCTP_CMD_FORCE_PRIM_RETRAN,
 						SCTP_NULL());
 			}
@@ -1237,18 +1252,67 @@
 				sctp_association_put(asoc);
 			break;
 
+		case SCTP_CMD_INIT_CHOOSE_TRANSPORT:
+			chunk = cmd->obj.ptr;
+			t = sctp_assoc_choose_init_transport(asoc);
+			asoc->init_last_sent_to = t;
+			chunk->transport = t;
+			t->init_sent_count++;
+			break;
+
 		case SCTP_CMD_INIT_RESTART:
 			/* Do the needed accounting and updates
 			 * associated with restarting an initialization
-			 * timer.
+			 * timer. Only multiply the timeout by two if
+			 * all transports have been tried at the current
+			 * timeout.
 			 */
-			asoc->counters[SCTP_COUNTER_INIT_ERROR]++;
-			asoc->timeouts[cmd->obj.to] *= 2;
-			if (asoc->timeouts[cmd->obj.to] >
+			t = asoc->init_last_sent_to;
+			asoc->init_err_counter++;
+
+			if (t->init_sent_count > (asoc->init_cycle + 1)) {
+				asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] *= 2;
+				if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] >
+				    asoc->max_init_timeo) {
+					asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
+						asoc->max_init_timeo;
+				}
+				asoc->init_cycle++;
+				SCTP_DEBUG_PRINTK(
+					"T1 INIT Timeout adjustment"
+					" init_err_counter: %d"
+					" cycle: %d"
+					" timeout: %d\n",
+					asoc->init_err_counter,
+					asoc->init_cycle,
+					asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]);
+			}
+
+			sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
+					SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
+			break;
+
+		case SCTP_CMD_COOKIEECHO_RESTART:
+			/* Do the needed accounting and updates
+			 * associated with restarting an initialization
+			 * timer. Only multiply the timeout by two if
+			 * all transports have been tried at the current
+			 * timeout.
+			 */
+			asoc->init_err_counter++;
+
+			asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] *= 2;
+			if (asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] >
 			    asoc->max_init_timeo) {
-				asoc->timeouts[cmd->obj.to] =
+				asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =
 					asoc->max_init_timeo;
 			}
+			SCTP_DEBUG_PRINTK(
+				"T1 COOKIE Timeout adjustment"
+				" init_err_counter: %d"
+				" timeout: %d\n",
+				asoc->init_err_counter,
+				asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]);
 
 			/* If we've sent any data bundled with
 			 * COOKIE-ECHO we need to resend.
@@ -1261,7 +1325,7 @@
 
 			sctp_add_cmd_sf(commands,
 					SCTP_CMD_TIMER_RESTART,
-					SCTP_TO(cmd->obj.to));
+					SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
 			break;
 
 		case SCTP_CMD_INIT_FAILED:
@@ -1273,12 +1337,13 @@
 					      subtype, chunk, cmd->obj.u32);
 			break;
 
-		case SCTP_CMD_COUNTER_INC:
-			asoc->counters[cmd->obj.counter]++;
+		case SCTP_CMD_INIT_COUNTER_INC:
+			asoc->init_err_counter++;
 			break;
 
-		case SCTP_CMD_COUNTER_RESET:
-			asoc->counters[cmd->obj.counter] = 0;
+		case SCTP_CMD_INIT_COUNTER_RESET:
+			asoc->init_err_counter = 0;
+			asoc->init_cycle = 0;
 			break;
 
 		case SCTP_CMD_REPORT_DUP:
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 8e01b8f..86073df 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -92,6 +92,17 @@
 					     sctp_cmd_seq_t *commands);
 static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk);
 
+static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
+					   __u16 error,
+					   const struct sctp_association *asoc,
+					   struct sctp_transport *transport);
+
+static sctp_disposition_t sctp_sf_violation_chunklen(
+				     const struct sctp_endpoint *ep,
+				     const struct sctp_association *asoc,
+				     const sctp_subtype_t type,
+				     void *arg,
+				     sctp_cmd_seq_t *commands);
 
 /* Small helper function that checks if the chunk length
  * is of the appropriate length.  The 'required_length' argument
@@ -533,6 +544,9 @@
 	sctp_add_cmd_sf(commands, SCTP_CMD_PEER_INIT,
 			SCTP_PEER_INIT(initchunk));
 
+	/* Reset init error count upon receipt of INIT-ACK.  */
+	sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL());
+
 	/* 5.1 C) "A" shall stop the T1-init timer and leave
 	 * COOKIE-WAIT state.  "A" shall then ... start the T1-cookie
 	 * timer, and enter the COOKIE-ECHOED state.
@@ -775,8 +789,7 @@
 	 * from the COOKIE-ECHOED state to the COOKIE-WAIT
 	 * state is performed.
 	 */
-	sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_RESET,
-	                SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR));
+	sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL());
 
 	/* RFC 2960 5.1 Normal Establishment of an Association
 	 *
@@ -1019,10 +1032,22 @@
 	link = sctp_assoc_lookup_paddr(asoc, &from_addr);
 
 	/* This should never happen, but lets log it if so.  */
-	if (!link) {
-		printk(KERN_WARNING
-		       "%s: Could not find address %d.%d.%d.%d\n",
-		       __FUNCTION__, NIPQUAD(from_addr.v4.sin_addr));
+	if (unlikely(!link)) {
+		if (from_addr.sa.sa_family == AF_INET6) {
+			printk(KERN_WARNING
+			       "%s association %p could not find address "
+			       "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
+			       __FUNCTION__,
+			       asoc,
+			       NIP6(from_addr.v6.sin6_addr));
+		} else {
+			printk(KERN_WARNING
+			       "%s association %p could not find address "
+			       "%u.%u.%u.%u\n",
+			       __FUNCTION__,
+			       asoc,
+			       NIPQUAD(from_addr.v4.sin_addr.s_addr));
+		}
 		return SCTP_DISPOSITION_DISCARD;
 	}
 
@@ -2095,9 +2120,7 @@
 	sctp_errhdr_t *err;
 	struct sctp_chunk *reply;
 	struct sctp_bind_addr *bp;
-	int attempts;
-
-	attempts = asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1;
+	int attempts = asoc->init_err_counter + 1;
 
 	if (attempts >= asoc->max_init_attempts) {
 		sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
@@ -2157,8 +2180,7 @@
 	/* Cast away the const modifier, as we want to just
 	 * rerun it through as a sideffect.
 	 */
-	sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_INC,
-			SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR));
+	sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_INC, SCTP_NULL());
 
 	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
 			SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
@@ -2281,8 +2303,7 @@
 	if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr))
 		error = ((sctp_errhdr_t *)chunk->skb->data)->cause;
 
- 	sctp_stop_t1_and_abort(commands, error);
-	return SCTP_DISPOSITION_ABORT;
+	return sctp_stop_t1_and_abort(commands, error, asoc, chunk->transport);
 }
 
 /*
@@ -2294,8 +2315,8 @@
 					void *arg,
 					sctp_cmd_seq_t *commands)
 {
-	sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR);
- 	return SCTP_DISPOSITION_ABORT;
+	return sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR, asoc,
+				      (struct sctp_transport *)arg);
 }
 
 /*
@@ -2318,8 +2339,12 @@
  *
  * This is common code called by several sctp_sf_*_abort() functions above.
  */
-void sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, __u16 error)
+static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
+					   __u16 error,
+					   const struct sctp_association *asoc,
+					   struct sctp_transport *transport)
 {
+	SCTP_DEBUG_PRINTK("ABORT received (INIT).\n");
 	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
 			SCTP_STATE(SCTP_STATE_CLOSED));
 	SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
@@ -2328,6 +2353,7 @@
 	/* CMD_INIT_FAILED will DELETE_TCB. */
 	sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
 			SCTP_U32(error));
+	return SCTP_DISPOSITION_ABORT;
 }
 
 /*
@@ -3672,7 +3698,8 @@
  *
  * Generate an  ABORT chunk and terminate the association.
  */
-sctp_disposition_t sctp_sf_violation_chunklen(const struct sctp_endpoint *ep,
+static sctp_disposition_t sctp_sf_violation_chunklen(
+				     const struct sctp_endpoint *ep,
 				     const struct sctp_association *asoc,
 				     const sctp_subtype_t type,
 				     void *arg,
@@ -3805,6 +3832,10 @@
 	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC,
 			SCTP_ASOC((struct sctp_association *) asoc));
 
+	/* Choose transport for INIT. */
+	sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT,
+			SCTP_CHUNK(repl));
+
 	/* After sending the INIT, "A" starts the T1-init timer and
 	 * enters the COOKIE-WAIT state.
 	 */
@@ -4589,7 +4620,7 @@
 }
 
 /*
- * sctp_sf_t1_timer_expire
+ * sctp_sf_t1_init_timer_expire
  *
  * Section: 4 Note: 2
  * Verification Tag:
@@ -4603,7 +4634,59 @@
  *     endpoint MUST abort the initialization process and report the
  *     error to SCTP user.
  *
- *   3) If the T1-cookie timer expires, the endpoint MUST retransmit
+ * Outputs
+ * (timers, events)
+ *
+ */
+sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep,
+					   const struct sctp_association *asoc,
+					   const sctp_subtype_t type,
+					   void *arg,
+					   sctp_cmd_seq_t *commands)
+{
+	struct sctp_chunk *repl = NULL;
+	struct sctp_bind_addr *bp;
+	int attempts = asoc->init_err_counter + 1;
+
+	SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n");
+
+	if (attempts < asoc->max_init_attempts) {
+		bp = (struct sctp_bind_addr *) &asoc->base.bind_addr;
+		repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0);
+		if (!repl)
+			return SCTP_DISPOSITION_NOMEM;
+
+		/* Choose transport for INIT. */
+		sctp_add_cmd_sf(commands, SCTP_CMD_INIT_CHOOSE_TRANSPORT,
+				SCTP_CHUNK(repl));
+
+		/* Issue a sideeffect to do the needed accounting. */
+		sctp_add_cmd_sf(commands, SCTP_CMD_INIT_RESTART,
+				SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
+
+		sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
+	} else {
+		SCTP_DEBUG_PRINTK("Giving up on INIT, attempts: %d"
+				  " max_init_attempts: %d\n",
+				  attempts, asoc->max_init_attempts);
+		sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
+				SCTP_U32(SCTP_ERROR_NO_ERROR));
+		return SCTP_DISPOSITION_DELETE_TCB;
+	}
+
+	return SCTP_DISPOSITION_CONSUME;
+}
+
+/*
+ * sctp_sf_t1_cookie_timer_expire
+ *
+ * Section: 4 Note: 2
+ * Verification Tag:
+ * Inputs
+ * (endpoint, asoc)
+ *
+ *  RFC 2960 Section 4 Notes
+ *  3) If the T1-cookie timer expires, the endpoint MUST retransmit
  *     COOKIE ECHO and re-start the T1-cookie timer without changing
  *     state.  This MUST be repeated up to 'Max.Init.Retransmits' times.
  *     After that, the endpoint MUST abort the initialization process and
@@ -4613,46 +4696,26 @@
  * (timers, events)
  *
  */
-sctp_disposition_t sctp_sf_t1_timer_expire(const struct sctp_endpoint *ep,
+sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep,
 					   const struct sctp_association *asoc,
 					   const sctp_subtype_t type,
 					   void *arg,
 					   sctp_cmd_seq_t *commands)
 {
-	struct sctp_chunk *repl;
-	struct sctp_bind_addr *bp;
-	sctp_event_timeout_t timer = (sctp_event_timeout_t) arg;
-	int timeout;
-	int attempts;
+	struct sctp_chunk *repl = NULL;
+	int attempts = asoc->init_err_counter + 1;
 
-	timeout = asoc->timeouts[timer];
-	attempts = asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1;
-	repl = NULL;
-
-	SCTP_DEBUG_PRINTK("Timer T1 expired.\n");
+	SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n");
 
 	if (attempts < asoc->max_init_attempts) {
-		switch (timer) {
-		case SCTP_EVENT_TIMEOUT_T1_INIT:
-			bp = (struct sctp_bind_addr *) &asoc->base.bind_addr;
-			repl = sctp_make_init(asoc, bp, GFP_ATOMIC, 0);
-			break;
-
-		case SCTP_EVENT_TIMEOUT_T1_COOKIE:
-			repl = sctp_make_cookie_echo(asoc, NULL);
-			break;
-
-		default:
-			BUG();
-			break;
-		};
-
+		repl = sctp_make_cookie_echo(asoc, NULL);
 		if (!repl)
-			goto nomem;
+			return SCTP_DISPOSITION_NOMEM;
 
 		/* Issue a sideeffect to do the needed accounting. */
-		sctp_add_cmd_sf(commands, SCTP_CMD_INIT_RESTART,
-				SCTP_TO(timer));
+		sctp_add_cmd_sf(commands, SCTP_CMD_COOKIEECHO_RESTART,
+				SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));
+
 		sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
 	} else {
 		sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
@@ -4661,9 +4724,6 @@
 	}
 
 	return SCTP_DISPOSITION_CONSUME;
-
-nomem:
-	return SCTP_DISPOSITION_NOMEM;
 }
 
 /* RFC2960 9.2 If the timer expires, the endpoint must re-send the SHUTDOWN
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index 8967846..75ef104 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -783,7 +783,8 @@
 	/* SCTP_STATE_COOKIE_WAIT */ \
 	{.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \
 	/* SCTP_STATE_COOKIE_ECHOED */ \
-	{.fn = sctp_sf_t1_timer_expire, .name = "sctp_sf_t1_timer_expire"}, \
+	{.fn = sctp_sf_t1_cookie_timer_expire, \
+	 .name = "sctp_sf_t1_cookie_timer_expire"}, \
 	/* SCTP_STATE_ESTABLISHED */ \
 	{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
 	/* SCTP_STATE_SHUTDOWN_PENDING */ \
@@ -802,7 +803,8 @@
 	/* SCTP_STATE_CLOSED */ \
 	{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
 	/* SCTP_STATE_COOKIE_WAIT */ \
-	{.fn = sctp_sf_t1_timer_expire, .name = "sctp_sf_t1_timer_expire"}, \
+	{.fn = sctp_sf_t1_init_timer_expire, \
+	 .name = "sctp_sf_t1_init_timer_expire"}, \
 	/* SCTP_STATE_COOKIE_ECHOED */ \
 	{.fn = sctp_sf_timer_ignore, .name = "sctp_sf_timer_ignore"}, \
 	/* SCTP_STATE_ESTABLISHED */ \
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 0b338ec..aad55dc 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -262,18 +262,18 @@
  *             sockaddr_in6 [RFC 2553]),
  *   addr_len - the size of the address structure.
  */
-SCTP_STATIC int sctp_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+SCTP_STATIC int sctp_bind(struct sock *sk, struct sockaddr *addr, int addr_len)
 {
 	int retval = 0;
 
 	sctp_lock_sock(sk);
 
-	SCTP_DEBUG_PRINTK("sctp_bind(sk: %p, uaddr: %p, addr_len: %d)\n",
-			  sk, uaddr, addr_len);
+	SCTP_DEBUG_PRINTK("sctp_bind(sk: %p, addr: %p, addr_len: %d)\n",
+			  sk, addr, addr_len);
 
 	/* Disallow binding twice. */
 	if (!sctp_sk(sk)->ep->base.bind_addr.port)
-		retval = sctp_do_bind(sk, (union sctp_addr *)uaddr,
+		retval = sctp_do_bind(sk, (union sctp_addr *)addr,
 				      addr_len);
 	else
 		retval = -EINVAL;
@@ -318,23 +318,27 @@
 	unsigned short snum;
 	int ret = 0;
 
-	SCTP_DEBUG_PRINTK("sctp_do_bind(sk: %p, newaddr: %p, len: %d)\n",
-			  sk, addr, len);
-
 	/* Common sockaddr verification. */
 	af = sctp_sockaddr_af(sp, addr, len);
-	if (!af)
+	if (!af) {
+		SCTP_DEBUG_PRINTK("sctp_do_bind(sk: %p, newaddr: %p, len: %d) EINVAL\n",
+				  sk, addr, len);
 		return -EINVAL;
+	}
+
+	snum = ntohs(addr->v4.sin_port);
+
+	SCTP_DEBUG_PRINTK_IPADDR("sctp_do_bind(sk: %p, new addr: ",
+				 ", port: %d, new port: %d, len: %d)\n",
+				 sk,
+				 addr,
+				 bp->port, snum,
+				 len);
 
 	/* PF specific bind() address verification. */
 	if (!sp->pf->bind_verify(sp, addr))
 		return -EADDRNOTAVAIL;
 
-	snum= ntohs(addr->v4.sin_port);
-
-	SCTP_DEBUG_PRINTK("sctp_do_bind: port: %d, new port: %d\n",
-			  bp->port, snum);
-
 	/* We must either be unbound, or bind to the same port.  */
 	if (bp->port && (snum != bp->port)) {
 		SCTP_DEBUG_PRINTK("sctp_do_bind:"
@@ -816,7 +820,8 @@
  *
  * Basically do nothing but copying the addresses from user to kernel
  * land and invoking either sctp_bindx_add() or sctp_bindx_rem() on the sk.
- * This is used for tunneling the sctp_bindx() request through sctp_setsockopt() * from userspace.
+ * This is used for tunneling the sctp_bindx() request through sctp_setsockopt()
+ * from userspace.
  *
  * We don't use copy_from_user() for optimization: we first do the
  * sanity checks (buffer size -fast- and access check-healthy
@@ -913,6 +918,243 @@
 	return err;
 }
 
+/* __sctp_connect(struct sock* sk, struct sockaddr *kaddrs, int addrs_size)
+ *
+ * Common routine for handling connect() and sctp_connectx().
+ * Connect will come in with just a single address.
+ */
+static int __sctp_connect(struct sock* sk,
+			  struct sockaddr *kaddrs,
+			  int addrs_size)
+{
+	struct sctp_sock *sp;
+	struct sctp_endpoint *ep;
+	struct sctp_association *asoc = NULL;
+	struct sctp_association *asoc2;
+	struct sctp_transport *transport;
+	union sctp_addr to;
+	struct sctp_af *af;
+	sctp_scope_t scope;
+	long timeo;
+	int err = 0;
+	int addrcnt = 0;
+	int walk_size = 0;
+	struct sockaddr *sa_addr;
+	void *addr_buf;
+
+	sp = sctp_sk(sk);
+	ep = sp->ep;
+
+	/* connect() cannot be done on a socket that is already in ESTABLISHED
+	 * state - UDP-style peeled off socket or a TCP-style socket that
+	 * is already connected.
+	 * It cannot be done even on a TCP-style listening socket.
+	 */
+	if (sctp_sstate(sk, ESTABLISHED) ||
+	    (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) {
+		err = -EISCONN;
+		goto out_free;
+	}
+
+	/* Walk through the addrs buffer and count the number of addresses. */
+	addr_buf = kaddrs;
+	while (walk_size < addrs_size) {
+		sa_addr = (struct sockaddr *)addr_buf;
+		af = sctp_get_af_specific(sa_addr->sa_family);
+
+		/* If the address family is not supported or if this address
+		 * causes the address buffer to overflow return EINVAL.
+		 */
+		if (!af || (walk_size + af->sockaddr_len) > addrs_size) {
+			err = -EINVAL;
+			goto out_free;
+		}
+
+		err = sctp_verify_addr(sk, (union sctp_addr *)sa_addr,
+				       af->sockaddr_len);
+		if (err)
+			goto out_free;
+
+		memcpy(&to, sa_addr, af->sockaddr_len);
+		to.v4.sin_port = ntohs(to.v4.sin_port);
+
+		/* Check if there already is a matching association on the
+		 * endpoint (other than the one created here).
+		 */
+		asoc2 = sctp_endpoint_lookup_assoc(ep, &to, &transport);
+		if (asoc2 && asoc2 != asoc) {
+			if (asoc2->state >= SCTP_STATE_ESTABLISHED)
+				err = -EISCONN;
+			else
+				err = -EALREADY;
+			goto out_free;
+		}
+
+		/* If we could not find a matching association on the endpoint,
+		 * make sure that there is no peeled-off association matching
+		 * the peer address even on another socket.
+		 */
+		if (sctp_endpoint_is_peeled_off(ep, &to)) {
+			err = -EADDRNOTAVAIL;
+			goto out_free;
+		}
+
+		if (!asoc) {
+			/* If a bind() or sctp_bindx() is not called prior to
+			 * an sctp_connectx() call, the system picks an
+			 * ephemeral port and will choose an address set
+			 * equivalent to binding with a wildcard address.
+			 */
+			if (!ep->base.bind_addr.port) {
+				if (sctp_autobind(sk)) {
+					err = -EAGAIN;
+					goto out_free;
+				}
+			}
+
+			scope = sctp_scope(&to);
+			asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL);
+			if (!asoc) {
+				err = -ENOMEM;
+				goto out_free;
+			}
+		}
+
+		/* Prime the peer's transport structures.  */
+		transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL,
+						SCTP_UNKNOWN);
+		if (!transport) {
+			err = -ENOMEM;
+			goto out_free;
+		}
+
+		addrcnt++;
+		addr_buf += af->sockaddr_len;
+		walk_size += af->sockaddr_len;
+	}
+
+	err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL);
+	if (err < 0) {
+		goto out_free;
+	}
+
+	err = sctp_primitive_ASSOCIATE(asoc, NULL);
+	if (err < 0) {
+		goto out_free;
+	}
+
+	/* Initialize sk's dport and daddr for getpeername() */
+	inet_sk(sk)->dport = htons(asoc->peer.port);
+	af = sctp_get_af_specific(to.sa.sa_family);
+	af->to_sk_daddr(&to, sk);
+
+	timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK);
+	err = sctp_wait_for_connect(asoc, &timeo);
+
+	/* Don't free association on exit. */
+	asoc = NULL;
+
+out_free:
+
+	SCTP_DEBUG_PRINTK("About to exit __sctp_connect() free asoc: %p"
+		          " kaddrs: %p err: %d\n",
+	                  asoc, kaddrs, err);
+	if (asoc)
+		sctp_association_free(asoc);
+	return err;
+}
+
+/* Helper for tunneling sctp_connectx() requests through sctp_setsockopt()
+ *
+ * API 8.9
+ * int sctp_connectx(int sd, struct sockaddr *addrs, int addrcnt);
+ *
+ * If sd is an IPv4 socket, the addresses passed must be IPv4 addresses.
+ * If the sd is an IPv6 socket, the addresses passed can either be IPv4
+ * or IPv6 addresses.
+ *
+ * A single address may be specified as INADDR_ANY or IN6ADDR_ANY, see
+ * Section 3.1.2 for this usage.
+ *
+ * addrs is a pointer to an array of one or more socket addresses. Each
+ * address is contained in its appropriate structure (i.e. struct
+ * sockaddr_in or struct sockaddr_in6) the family of the address type
+ * must be used to distengish the address length (note that this
+ * representation is termed a "packed array" of addresses). The caller
+ * specifies the number of addresses in the array with addrcnt.
+ *
+ * On success, sctp_connectx() returns 0. On failure, sctp_connectx() returns
+ * -1, and sets errno to the appropriate error code.
+ *
+ * For SCTP, the port given in each socket address must be the same, or
+ * sctp_connectx() will fail, setting errno to EINVAL.
+ *
+ * An application can use sctp_connectx to initiate an association with
+ * an endpoint that is multi-homed.  Much like sctp_bindx() this call
+ * allows a caller to specify multiple addresses at which a peer can be
+ * reached.  The way the SCTP stack uses the list of addresses to set up
+ * the association is implementation dependant.  This function only
+ * specifies that the stack will try to make use of all the addresses in
+ * the list when needed.
+ *
+ * Note that the list of addresses passed in is only used for setting up
+ * the association.  It does not necessarily equal the set of addresses
+ * the peer uses for the resulting association.  If the caller wants to
+ * find out the set of peer addresses, it must use sctp_getpaddrs() to
+ * retrieve them after the association has been set up.
+ *
+ * Basically do nothing but copying the addresses from user to kernel
+ * land and invoking either sctp_connectx(). This is used for tunneling
+ * the sctp_connectx() request through sctp_setsockopt() from userspace.
+ *
+ * We don't use copy_from_user() for optimization: we first do the
+ * sanity checks (buffer size -fast- and access check-healthy
+ * pointer); if all of those succeed, then we can alloc the memory
+ * (expensive operation) needed to copy the data to kernel. Then we do
+ * the copying without checking the user space area
+ * (__copy_from_user()).
+ *
+ * On exit there is no need to do sockfd_put(), sys_setsockopt() does
+ * it.
+ *
+ * sk        The sk of the socket
+ * addrs     The pointer to the addresses in user land
+ * addrssize Size of the addrs buffer
+ *
+ * Returns 0 if ok, <0 errno code on error.
+ */
+SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk,
+				      struct sockaddr __user *addrs,
+				      int addrs_size)
+{
+	int err = 0;
+	struct sockaddr *kaddrs;
+
+	SCTP_DEBUG_PRINTK("%s - sk %p addrs %p addrs_size %d\n",
+			  __FUNCTION__, sk, addrs, addrs_size);
+
+	if (unlikely(addrs_size <= 0))
+		return -EINVAL;
+
+	/* Check the user passed a healthy pointer.  */
+	if (unlikely(!access_ok(VERIFY_READ, addrs, addrs_size)))
+		return -EFAULT;
+
+	/* Alloc space for the address array in kernel memory.  */
+	kaddrs = (struct sockaddr *)kmalloc(addrs_size, GFP_KERNEL);
+	if (unlikely(!kaddrs))
+		return -ENOMEM;
+
+	if (__copy_from_user(kaddrs, addrs, addrs_size)) {
+		err = -EFAULT;
+	} else {
+		err = __sctp_connect(sk, kaddrs, addrs_size);
+	}
+
+	kfree(kaddrs);
+	return err;
+}
+
 /* API 3.1.4 close() - UDP Style Syntax
  * Applications use close() to perform graceful shutdown (as described in
  * Section 10.1 of [SCTP]) on ALL the associations currently represented
@@ -1095,7 +1337,7 @@
 	sp = sctp_sk(sk);
 	ep = sp->ep;
 
-	SCTP_DEBUG_PRINTK("Using endpoint: %s.\n", ep->debug_name);
+	SCTP_DEBUG_PRINTK("Using endpoint: %p.\n", ep);
 
 	/* We cannot send a message over a TCP-style listening socket. */
 	if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) {
@@ -1306,7 +1548,7 @@
 		}
 
 		/* Prime the peer's transport structures.  */
-		transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL);
+		transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, SCTP_UNKNOWN);
 		if (!transport) {
 			err = -ENOMEM;
 			goto out_free;
@@ -2208,6 +2450,12 @@
 					       optlen, SCTP_BINDX_REM_ADDR);
 		break;
 
+	case SCTP_SOCKOPT_CONNECTX:
+		/* 'optlen' is the size of the addresses buffer. */
+		retval = sctp_setsockopt_connectx(sk, (struct sockaddr __user *)optval,
+					       optlen);
+		break;
+
 	case SCTP_DISABLE_FRAGMENTS:
 		retval = sctp_setsockopt_disable_fragments(sk, optval, optlen);
 		break;
@@ -2283,112 +2531,29 @@
  *
  * len: the size of the address.
  */
-SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr,
+SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *addr,
 			     int addr_len)
 {
-	struct sctp_sock *sp;
-	struct sctp_endpoint *ep;
-	struct sctp_association *asoc;
-	struct sctp_transport *transport;
-	union sctp_addr to;
-	struct sctp_af *af;
-	sctp_scope_t scope;
-	long timeo;
 	int err = 0;
+	struct sctp_af *af;
 
 	sctp_lock_sock(sk);
 
-	SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d)\n",
-			  __FUNCTION__, sk, uaddr, addr_len);
+	SCTP_DEBUG_PRINTK("%s - sk: %p, sockaddr: %p, addr_len: %d\n",
+			  __FUNCTION__, sk, addr, addr_len);
 
-	sp = sctp_sk(sk);
-	ep = sp->ep;
-
-	/* connect() cannot be done on a socket that is already in ESTABLISHED
-	 * state - UDP-style peeled off socket or a TCP-style socket that
-	 * is already connected.
-	 * It cannot be done even on a TCP-style listening socket.
-	 */
-	if (sctp_sstate(sk, ESTABLISHED) ||
-	    (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING))) {
-		err = -EISCONN;
-		goto out_unlock;
+	/* Validate addr_len before calling common connect/connectx routine. */
+	af = sctp_get_af_specific(addr->sa_family);
+	if (!af || addr_len < af->sockaddr_len) {
+		err = -EINVAL;
+	} else {
+		/* Pass correct addr len to common routine (so it knows there
+		 * is only one address being passed.
+		 */
+		err = __sctp_connect(sk, addr, af->sockaddr_len);
 	}
 
-	err = sctp_verify_addr(sk, (union sctp_addr *)uaddr, addr_len);
-	if (err)
-		goto out_unlock;
-
-	if (addr_len > sizeof(to))
-		addr_len = sizeof(to);
-	memcpy(&to, uaddr, addr_len);
-	to.v4.sin_port = ntohs(to.v4.sin_port);
-
-	asoc = sctp_endpoint_lookup_assoc(ep, &to, &transport);
-	if (asoc) {
-		if (asoc->state >= SCTP_STATE_ESTABLISHED)
-			err = -EISCONN;
-		else
-			err = -EALREADY;
-		goto out_unlock;
-	}
-
-	/* If we could not find a matching association on the endpoint,
-	 * make sure that there is no peeled-off association matching the
-	 * peer address even on another socket.
-	 */
-	if (sctp_endpoint_is_peeled_off(ep, &to)) {
-		err = -EADDRNOTAVAIL;
-		goto out_unlock;
-	}
-
-	/* If a bind() or sctp_bindx() is not called prior to a connect()
-	 * call, the system picks an ephemeral port and will choose an address
-	 * set equivalent to binding with a wildcard address.
-	 */
-	if (!ep->base.bind_addr.port) {
-		if (sctp_autobind(sk)) {
-			err = -EAGAIN;
-			goto out_unlock;
-		}
-	}
-
-	scope = sctp_scope(&to);
-	asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL);
-	if (!asoc) {
-		err = -ENOMEM;
-		goto out_unlock;
-  	}
-
-	/* Prime the peer's transport structures.  */
-	transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL);
-	if (!transport) {
-		sctp_association_free(asoc);
-		goto out_unlock;
-	}
-	err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL);
-	if (err < 0) {
-		sctp_association_free(asoc);
-		goto out_unlock;
-	}
-
-	err = sctp_primitive_ASSOCIATE(asoc, NULL);
-	if (err < 0) {
-		sctp_association_free(asoc);
-		goto out_unlock;
-	}
-
-	/* Initialize sk's dport and daddr for getpeername() */
-	inet_sk(sk)->dport = htons(asoc->peer.port);
-	af = sctp_get_af_specific(to.sa.sa_family);
-	af->to_sk_daddr(&to, sk);
-
-	timeo = sock_sndtimeo(sk, sk->sk_socket->file->f_flags & O_NONBLOCK);
-	err = sctp_wait_for_connect(asoc, &timeo);
-
-out_unlock:
 	sctp_release_sock(sk);
-
 	return err;
 }
 
@@ -2677,12 +2842,15 @@
 	/* Map ipv4 address into v4-mapped-on-v6 address.  */
 	sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
 		(union sctp_addr *)&status.sstat_primary.spinfo_address);
-	status.sstat_primary.spinfo_state = transport->active;
+	status.sstat_primary.spinfo_state = transport->state;
 	status.sstat_primary.spinfo_cwnd = transport->cwnd;
 	status.sstat_primary.spinfo_srtt = transport->srtt;
 	status.sstat_primary.spinfo_rto = jiffies_to_msecs(transport->rto);
 	status.sstat_primary.spinfo_mtu = transport->pmtu;
 
+	if (status.sstat_primary.spinfo_state == SCTP_UNKNOWN)
+		status.sstat_primary.spinfo_state = SCTP_ACTIVE;
+
 	if (put_user(len, optlen)) {
 		retval = -EFAULT;
 		goto out;
@@ -2733,12 +2901,15 @@
 		return -EINVAL;
 
 	pinfo.spinfo_assoc_id = sctp_assoc2id(transport->asoc);
-	pinfo.spinfo_state = transport->active;
+	pinfo.spinfo_state = transport->state;
 	pinfo.spinfo_cwnd = transport->cwnd;
 	pinfo.spinfo_srtt = transport->srtt;
 	pinfo.spinfo_rto = jiffies_to_msecs(transport->rto);
 	pinfo.spinfo_mtu = transport->pmtu;
 
+	if (pinfo.spinfo_state == SCTP_UNKNOWN)
+		pinfo.spinfo_state = SCTP_ACTIVE;
+
 	if (put_user(len, optlen)) {
 		retval = -EFAULT;
 		goto out;
@@ -3591,7 +3762,8 @@
 	int retval = 0;
 	int len;
 
-	SCTP_DEBUG_PRINTK("sctp_getsockopt(sk: %p, ...)\n", sk);
+	SCTP_DEBUG_PRINTK("sctp_getsockopt(sk: %p... optname: %d)\n",
+			  sk, optname);
 
 	/* I can hardly begin to describe how wrong this is.  This is
 	 * so broken as to be worse than useless.  The API draft
@@ -4368,15 +4540,11 @@
 		 *  However, this function was corrent in any case. 8)
 		 */
 		if (flags & MSG_PEEK) {
-			unsigned long cpu_flags;
-
-			sctp_spin_lock_irqsave(&sk->sk_receive_queue.lock,
-					       cpu_flags);
+			spin_lock_bh(&sk->sk_receive_queue.lock);
 			skb = skb_peek(&sk->sk_receive_queue);
 			if (skb)
 				atomic_inc(&skb->users);
-			sctp_spin_unlock_irqrestore(&sk->sk_receive_queue.lock,
-						    cpu_flags);
+			spin_unlock_bh(&sk->sk_receive_queue.lock);
 		} else {
 			skb = skb_dequeue(&sk->sk_receive_queue);
 		}
@@ -4600,8 +4768,7 @@
 	return err;
 
 do_error:
-	if (asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1 >=
-					 	asoc->max_init_attempts)
+	if (asoc->init_err_counter + 1 >= asoc->max_init_attempts)
 		err = -ETIMEDOUT;
 	else
 		err = -ECONNREFUSED;
@@ -4686,6 +4853,7 @@
 	struct sctp_endpoint *newep = newsp->ep;
 	struct sk_buff *skb, *tmp;
 	struct sctp_ulpevent *event;
+	int flags = 0;
 
 	/* Migrate socket buffer sizes and all the socket level options to the
 	 * new socket.
@@ -4707,6 +4875,17 @@
 	sctp_sk(newsk)->bind_hash = pp;
 	inet_sk(newsk)->num = inet_sk(oldsk)->num;
 
+	/* Copy the bind_addr list from the original endpoint to the new
+	 * endpoint so that we can handle restarts properly
+	 */
+	if (assoc->peer.ipv4_address)
+		flags |= SCTP_ADDR4_PEERSUPP;
+	if (assoc->peer.ipv6_address)
+		flags |= SCTP_ADDR6_PEERSUPP;
+	sctp_bind_addr_copy(&newsp->ep->base.bind_addr,
+			     &oldsp->ep->base.bind_addr,
+			     SCTP_SCOPE_GLOBAL, GFP_KERNEL, flags);
+
 	/* Move any messages in the old socket's receive queue that are for the
 	 * peeled off association to the new socket's receive queue.
 	 */
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index f30882e..0ec0fde 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -83,7 +83,9 @@
 	peer->last_time_used = jiffies;
 	peer->last_time_ecne_reduced = jiffies;
 
-	peer->active = SCTP_ACTIVE;
+	peer->init_sent_count = 0;
+
+	peer->state = SCTP_ACTIVE;
 	peer->hb_allowed = 0;
 
 	/* Initialize the default path max_retrans.  */
diff --git a/net/socket.c b/net/socket.c
index cec0cb3..6f2a1788 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -81,6 +81,7 @@
 #include <linux/syscalls.h>
 #include <linux/compat.h>
 #include <linux/kmod.h>
+#include <linux/audit.h>
 
 #ifdef CONFIG_NET_RADIO
 #include <linux/wireless.h>		/* Note : will define WIRELESS_EXT */
@@ -226,7 +227,7 @@
 		return 0;
 	if(copy_from_user(kaddr,uaddr,ulen))
 		return -EFAULT;
-	return 0;
+	return audit_sockaddr(ulen, kaddr);
 }
 
 /**
@@ -382,9 +383,8 @@
 			goto out;
 		}
 
-		sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino);
+		this.len = sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino);
 		this.name = name;
-		this.len = strlen(name);
 		this.hash = SOCK_INODE(sock)->i_ino;
 
 		file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this);
@@ -1906,7 +1906,11 @@
 	/* copy_from_user should be SMP safe. */
 	if (copy_from_user(a, args, nargs[call]))
 		return -EFAULT;
-		
+
+	err = audit_socketcall(nargs[call]/sizeof(unsigned long), a);
+	if (err)
+		return err;
+
 	a0=a[0];
 	a1=a[1];
 	
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 9bcec9b..505e2d4 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -66,10 +66,10 @@
 	u32			flavor = pseudoflavor_to_flavor(pseudoflavor);
 
 	if (flavor >= RPC_AUTH_MAXFLAVOR || !(ops = auth_flavors[flavor]))
-		return NULL;
+		return ERR_PTR(-EINVAL);
 	auth = ops->create(clnt, pseudoflavor);
-	if (!auth)
-		return NULL;
+	if (IS_ERR(auth))
+		return auth;
 	if (clnt->cl_auth)
 		rpcauth_destroy(clnt->cl_auth);
 	clnt->cl_auth = auth;
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index a33b627..2f7b867 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -660,14 +660,16 @@
 {
 	struct gss_auth *gss_auth;
 	struct rpc_auth * auth;
+	int err = -ENOMEM; /* XXX? */
 
 	dprintk("RPC:      creating GSS authenticator for client %p\n",clnt);
 
 	if (!try_module_get(THIS_MODULE))
-		return NULL;
+		return ERR_PTR(err);
 	if (!(gss_auth = kmalloc(sizeof(*gss_auth), GFP_KERNEL)))
 		goto out_dec;
 	gss_auth->client = clnt;
+	err = -EINVAL;
 	gss_auth->mech = gss_mech_get_by_pseudoflavor(flavor);
 	if (!gss_auth->mech) {
 		printk(KERN_WARNING "%s: Pseudoflavor %d not found!",
@@ -675,9 +677,8 @@
 		goto err_free;
 	}
 	gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor);
-	/* FIXME: Will go away once privacy support is merged in */
-	if (gss_auth->service == RPC_GSS_SVC_PRIVACY)
-		gss_auth->service = RPC_GSS_SVC_INTEGRITY;
+	if (gss_auth->service == 0)
+		goto err_put_mech;
 	INIT_LIST_HEAD(&gss_auth->upcalls);
 	spin_lock_init(&gss_auth->lock);
 	auth = &gss_auth->rpc_auth;
@@ -687,15 +688,18 @@
 	auth->au_flavor = flavor;
 	atomic_set(&auth->au_count, 1);
 
-	if (rpcauth_init_credcache(auth, GSS_CRED_EXPIRE) < 0)
+	err = rpcauth_init_credcache(auth, GSS_CRED_EXPIRE);
+	if (err)
 		goto err_put_mech;
 
 	snprintf(gss_auth->path, sizeof(gss_auth->path), "%s/%s",
 			clnt->cl_pathname,
 			gss_auth->mech->gm_name);
 	gss_auth->dentry = rpc_mkpipe(gss_auth->path, clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
-	if (IS_ERR(gss_auth->dentry))
+	if (IS_ERR(gss_auth->dentry)) {
+		err = PTR_ERR(gss_auth->dentry);
 		goto err_put_mech;
+	}
 
 	return auth;
 err_put_mech:
@@ -704,7 +708,7 @@
 	kfree(gss_auth);
 out_dec:
 	module_put(THIS_MODULE);
-	return NULL;
+	return ERR_PTR(err);
 }
 
 static void
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 02bc029..f17e615 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -97,12 +97,13 @@
  * made to sleep too long.
  */
 struct rpc_clnt *
-rpc_create_client(struct rpc_xprt *xprt, char *servname,
+rpc_new_client(struct rpc_xprt *xprt, char *servname,
 		  struct rpc_program *program, u32 vers,
 		  rpc_authflavor_t flavor)
 {
 	struct rpc_version	*version;
 	struct rpc_clnt		*clnt = NULL;
+	struct rpc_auth		*auth;
 	int err;
 	int len;
 
@@ -157,10 +158,11 @@
 	if (err < 0)
 		goto out_no_path;
 
-	err = -ENOMEM;
-	if (!rpcauth_create(flavor, clnt)) {
+	auth = rpcauth_create(flavor, clnt);
+	if (IS_ERR(auth)) {
 		printk(KERN_INFO "RPC: Couldn't create auth handle (flavor %u)\n",
 				flavor);
+		err = PTR_ERR(auth);
 		goto out_no_auth;
 	}
 
@@ -178,6 +180,37 @@
 		kfree(clnt->cl_server);
 	kfree(clnt);
 out_err:
+	xprt_destroy(xprt);
+	return ERR_PTR(err);
+}
+
+/**
+ * Create an RPC client
+ * @xprt - pointer to xprt struct
+ * @servname - name of server
+ * @info - rpc_program
+ * @version - rpc_program version
+ * @authflavor - rpc_auth flavour to use
+ *
+ * Creates an RPC client structure, then pings the server in order to
+ * determine if it is up, and if it supports this program and version.
+ *
+ * This function should never be called by asynchronous tasks such as
+ * the portmapper.
+ */
+struct rpc_clnt *rpc_create_client(struct rpc_xprt *xprt, char *servname,
+		struct rpc_program *info, u32 version, rpc_authflavor_t authflavor)
+{
+	struct rpc_clnt *clnt;
+	int err;
+	
+	clnt = rpc_new_client(xprt, servname, info, version, authflavor);
+	if (IS_ERR(clnt))
+		return clnt;
+	err = rpc_ping(clnt, RPC_TASK_SOFT|RPC_TASK_NOINTR);
+	if (err == 0)
+		return clnt;
+	rpc_shutdown_client(clnt);
 	return ERR_PTR(err);
 }
 
@@ -208,6 +241,8 @@
 	rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
 	if (new->cl_auth)
 		atomic_inc(&new->cl_auth->au_count);
+	new->cl_pmap		= &new->cl_pmap_default;
+	rpc_init_wait_queue(&new->cl_pmap_default.pm_bindwait, "bindwait");
 	return new;
 out_no_clnt:
 	printk(KERN_INFO "RPC: out of memory in %s\n", __FUNCTION__);
@@ -296,6 +331,44 @@
 		rpc_destroy_client(clnt);
 }
 
+/**
+ * rpc_bind_new_program - bind a new RPC program to an existing client
+ * @old - old rpc_client
+ * @program - rpc program to set
+ * @vers - rpc program version
+ *
+ * Clones the rpc client and sets up a new RPC program. This is mainly
+ * of use for enabling different RPC programs to share the same transport.
+ * The Sun NFSv2/v3 ACL protocol can do this.
+ */
+struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *old,
+				      struct rpc_program *program,
+				      int vers)
+{
+	struct rpc_clnt *clnt;
+	struct rpc_version *version;
+	int err;
+
+	BUG_ON(vers >= program->nrvers || !program->version[vers]);
+	version = program->version[vers];
+	clnt = rpc_clone_client(old);
+	if (IS_ERR(clnt))
+		goto out;
+	clnt->cl_procinfo = version->procs;
+	clnt->cl_maxproc  = version->nrprocs;
+	clnt->cl_protname = program->name;
+	clnt->cl_prog     = program->number;
+	clnt->cl_vers     = version->number;
+	clnt->cl_stats    = program->stats;
+	err = rpc_ping(clnt, RPC_TASK_SOFT|RPC_TASK_NOINTR);
+	if (err != 0) {
+		rpc_shutdown_client(clnt);
+		clnt = ERR_PTR(err);
+	}
+out:	
+	return clnt;
+}
+
 /*
  * Default callback for async RPC calls
  */
@@ -305,38 +378,41 @@
 }
 
 /*
- *	Export the signal mask handling for aysnchronous code that
+ *	Export the signal mask handling for synchronous code that
  *	sleeps on RPC calls
  */
+#define RPC_INTR_SIGNALS (sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGKILL))
  
+static void rpc_save_sigmask(sigset_t *oldset, int intr)
+{
+	unsigned long	sigallow = 0;
+	sigset_t sigmask;
+
+	/* Block all signals except those listed in sigallow */
+	if (intr)
+		sigallow |= RPC_INTR_SIGNALS;
+	siginitsetinv(&sigmask, sigallow);
+	sigprocmask(SIG_BLOCK, &sigmask, oldset);
+}
+
+static inline void rpc_task_sigmask(struct rpc_task *task, sigset_t *oldset)
+{
+	rpc_save_sigmask(oldset, !RPC_TASK_UNINTERRUPTIBLE(task));
+}
+
+static inline void rpc_restore_sigmask(sigset_t *oldset)
+{
+	sigprocmask(SIG_SETMASK, oldset, NULL);
+}
+
 void rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset)
 {
-	unsigned long	sigallow = sigmask(SIGKILL);
-	unsigned long	irqflags;
-	
-	/* Turn off various signals */
-	if (clnt->cl_intr) {
-		struct k_sigaction *action = current->sighand->action;
-		if (action[SIGINT-1].sa.sa_handler == SIG_DFL)
-			sigallow |= sigmask(SIGINT);
-		if (action[SIGQUIT-1].sa.sa_handler == SIG_DFL)
-			sigallow |= sigmask(SIGQUIT);
-	}
-	spin_lock_irqsave(&current->sighand->siglock, irqflags);
-	*oldset = current->blocked;
-	siginitsetinv(&current->blocked, sigallow & ~oldset->sig[0]);
-	recalc_sigpending();
-	spin_unlock_irqrestore(&current->sighand->siglock, irqflags);
+	rpc_save_sigmask(oldset, clnt->cl_intr);
 }
 
 void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset)
 {
-	unsigned long	irqflags;
-	
-	spin_lock_irqsave(&current->sighand->siglock, irqflags);
-	current->blocked = *oldset;
-	recalc_sigpending();
-	spin_unlock_irqrestore(&current->sighand->siglock, irqflags);
+	rpc_restore_sigmask(oldset);
 }
 
 /*
@@ -354,26 +430,26 @@
 
 	BUG_ON(flags & RPC_TASK_ASYNC);
 
-	rpc_clnt_sigmask(clnt, &oldset);		
-
 	status = -ENOMEM;
 	task = rpc_new_task(clnt, NULL, flags);
 	if (task == NULL)
 		goto out;
 
+	/* Mask signals on RPC calls _and_ GSS_AUTH upcalls */
+	rpc_task_sigmask(task, &oldset);
+
 	rpc_call_setup(task, msg, 0);
 
 	/* Set up the call info struct and execute the task */
-	if (task->tk_status == 0)
+	if (task->tk_status == 0) {
 		status = rpc_execute(task);
-	else {
+	} else {
 		status = task->tk_status;
 		rpc_release_task(task);
 	}
 
+	rpc_restore_sigmask(&oldset);
 out:
-	rpc_clnt_sigunmask(clnt, &oldset);		
-
 	return status;
 }
 
@@ -394,8 +470,6 @@
 
 	flags |= RPC_TASK_ASYNC;
 
-	rpc_clnt_sigmask(clnt, &oldset);		
-
 	/* Create/initialize a new RPC task */
 	if (!callback)
 		callback = rpc_default_callback;
@@ -404,6 +478,9 @@
 		goto out;
 	task->tk_calldata = data;
 
+	/* Mask signals on GSS_AUTH upcalls */
+	rpc_task_sigmask(task, &oldset);		
+
 	rpc_call_setup(task, msg, 0);
 
 	/* Set up the call info struct and execute the task */
@@ -413,9 +490,8 @@
 	else
 		rpc_release_task(task);
 
+	rpc_restore_sigmask(&oldset);		
 out:
-	rpc_clnt_sigunmask(clnt, &oldset);		
-
 	return status;
 }
 
@@ -593,7 +669,7 @@
 		return;
 	printk(KERN_INFO "RPC: buffer allocation failed for task %p\n", task); 
 
-	if (RPC_IS_ASYNC(task) || !(task->tk_client->cl_intr && signalled())) {
+	if (RPC_IS_ASYNC(task) || !signalled()) {
 		xprt_release(task);
 		task->tk_action = call_reserve;
 		rpc_delay(task, HZ>>4);
@@ -957,7 +1033,9 @@
 	*p++ = htonl(clnt->cl_prog);	/* program number */
 	*p++ = htonl(clnt->cl_vers);	/* program version */
 	*p++ = htonl(task->tk_msg.rpc_proc->p_proc);	/* procedure */
-	return rpcauth_marshcred(task, p);
+	p = rpcauth_marshcred(task, p);
+	req->rq_slen = xdr_adjust_iovec(&req->rq_svec[0], p);
+	return p;
 }
 
 /*
@@ -986,10 +1064,11 @@
 			case RPC_AUTH_ERROR:
 				break;
 			case RPC_MISMATCH:
-				printk(KERN_WARNING "%s: RPC call version mismatch!\n", __FUNCTION__);
-				goto out_eio;
+				dprintk("%s: RPC call version mismatch!\n", __FUNCTION__);
+				error = -EPROTONOSUPPORT;
+				goto out_err;
 			default:
-				printk(KERN_WARNING "%s: RPC call rejected, unknown error: %x\n", __FUNCTION__, n);
+				dprintk("%s: RPC call rejected, unknown error: %x\n", __FUNCTION__, n);
 				goto out_eio;
 		}
 		if (--len < 0)
@@ -1040,23 +1119,26 @@
 	case RPC_SUCCESS:
 		return p;
 	case RPC_PROG_UNAVAIL:
-		printk(KERN_WARNING "RPC: call_verify: program %u is unsupported by server %s\n",
+		dprintk("RPC: call_verify: program %u is unsupported by server %s\n",
 				(unsigned int)task->tk_client->cl_prog,
 				task->tk_client->cl_server);
-		goto out_eio;
+		error = -EPFNOSUPPORT;
+		goto out_err;
 	case RPC_PROG_MISMATCH:
-		printk(KERN_WARNING "RPC: call_verify: program %u, version %u unsupported by server %s\n",
+		dprintk("RPC: call_verify: program %u, version %u unsupported by server %s\n",
 				(unsigned int)task->tk_client->cl_prog,
 				(unsigned int)task->tk_client->cl_vers,
 				task->tk_client->cl_server);
-		goto out_eio;
+		error = -EPROTONOSUPPORT;
+		goto out_err;
 	case RPC_PROC_UNAVAIL:
-		printk(KERN_WARNING "RPC: call_verify: proc %p unsupported by program %u, version %u on server %s\n",
+		dprintk("RPC: call_verify: proc %p unsupported by program %u, version %u on server %s\n",
 				task->tk_msg.rpc_proc,
 				task->tk_client->cl_prog,
 				task->tk_client->cl_vers,
 				task->tk_client->cl_server);
-		goto out_eio;
+		error = -EOPNOTSUPP;
+		goto out_err;
 	case RPC_GARBAGE_ARGS:
 		dprintk("RPC: %4d %s: server saw garbage\n", task->tk_pid, __FUNCTION__);
 		break;			/* retry */
@@ -1069,7 +1151,7 @@
 	task->tk_client->cl_stats->rpcgarbage++;
 	if (task->tk_garb_retry) {
 		task->tk_garb_retry--;
-		dprintk(KERN_WARNING "RPC %s: retrying %4d\n", __FUNCTION__, task->tk_pid);
+		dprintk("RPC %s: retrying %4d\n", __FUNCTION__, task->tk_pid);
 		task->tk_action = call_bind;
 		return NULL;
 	}
@@ -1083,3 +1165,30 @@
 	printk(KERN_WARNING "RPC %s: server reply was truncated.\n", __FUNCTION__);
 	goto out_retry;
 }
+
+static int rpcproc_encode_null(void *rqstp, u32 *data, void *obj)
+{
+	return 0;
+}
+
+static int rpcproc_decode_null(void *rqstp, u32 *data, void *obj)
+{
+	return 0;
+}
+
+static struct rpc_procinfo rpcproc_null = {
+	.p_encode = rpcproc_encode_null,
+	.p_decode = rpcproc_decode_null,
+};
+
+int rpc_ping(struct rpc_clnt *clnt, int flags)
+{
+	struct rpc_message msg = {
+		.rpc_proc = &rpcproc_null,
+	};
+	int err;
+	msg.rpc_cred = authnull_ops.lookup_cred(NULL, NULL, 0);
+	err = rpc_call_sync(clnt, &msg, flags);
+	put_rpccred(msg.rpc_cred);
+	return err;
+}
diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
index d0b1d2c..4e81f27 100644
--- a/net/sunrpc/pmap_clnt.c
+++ b/net/sunrpc/pmap_clnt.c
@@ -53,6 +53,9 @@
 			task->tk_pid, clnt->cl_server,
 			map->pm_prog, map->pm_vers, map->pm_prot);
 
+	/* Autobind on cloned rpc clients is discouraged */
+	BUG_ON(clnt->cl_parent != clnt);
+
 	spin_lock(&pmap_lock);
 	if (map->pm_binding) {
 		rpc_sleep_on(&map->pm_bindwait, task, NULL, NULL);
@@ -207,12 +210,10 @@
 	xprt->addr.sin_port = htons(RPC_PMAP_PORT);
 
 	/* printk("pmap: create clnt\n"); */
-	clnt = rpc_create_client(xprt, hostname,
+	clnt = rpc_new_client(xprt, hostname,
 				&pmap_program, RPC_PMAP_VERSION,
 				RPC_AUTH_UNIX);
-	if (IS_ERR(clnt)) {
-		xprt_destroy(xprt);
-	} else {
+	if (!IS_ERR(clnt)) {
 		clnt->cl_softrtry = 1;
 		clnt->cl_chatty   = 1;
 		clnt->cl_oneshot  = 1;
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index c06614d..2d9eb7f 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -290,7 +290,7 @@
 			return;
 		}
 	} else
-		wake_up(&task->u.tk_wait.waitq);
+		wake_up_bit(&task->tk_runstate, RPC_TASK_QUEUED);
 }
 
 /*
@@ -555,6 +555,38 @@
 }
 
 /*
+ * Helper that calls task->tk_exit if it exists and then returns
+ * true if we should exit __rpc_execute.
+ */
+static inline int __rpc_do_exit(struct rpc_task *task)
+{
+	if (task->tk_exit != NULL) {
+		lock_kernel();
+		task->tk_exit(task);
+		unlock_kernel();
+		/* If tk_action is non-null, we should restart the call */
+		if (task->tk_action != NULL) {
+			if (!RPC_ASSASSINATED(task)) {
+				/* Release RPC slot and buffer memory */
+				xprt_release(task);
+				rpc_free(task);
+				return 0;
+			}
+			printk(KERN_ERR "RPC: dead task tried to walk away.\n");
+		}
+	}
+	return 1;
+}
+
+static int rpc_wait_bit_interruptible(void *word)
+{
+	if (signal_pending(current))
+		return -ERESTARTSYS;
+	schedule();
+	return 0;
+}
+
+/*
  * This is the RPC `scheduler' (or rather, the finite state machine).
  */
 static int __rpc_execute(struct rpc_task *task)
@@ -566,8 +598,7 @@
 
 	BUG_ON(RPC_IS_QUEUED(task));
 
- restarted:
-	while (1) {
+	for (;;) {
 		/*
 		 * Garbage collection of pending timers...
 		 */
@@ -600,11 +631,12 @@
 		 * by someone else.
 		 */
 		if (!RPC_IS_QUEUED(task)) {
-			if (!task->tk_action)
+			if (task->tk_action != NULL) {
+				lock_kernel();
+				task->tk_action(task);
+				unlock_kernel();
+			} else if (__rpc_do_exit(task))
 				break;
-			lock_kernel();
-			task->tk_action(task);
-			unlock_kernel();
 		}
 
 		/*
@@ -624,44 +656,26 @@
 
 		/* sync task: sleep here */
 		dprintk("RPC: %4d sync task going to sleep\n", task->tk_pid);
-		if (RPC_TASK_UNINTERRUPTIBLE(task)) {
-			__wait_event(task->u.tk_wait.waitq, !RPC_IS_QUEUED(task));
-		} else {
-			__wait_event_interruptible(task->u.tk_wait.waitq, !RPC_IS_QUEUED(task), status);
+		/* Note: Caller should be using rpc_clnt_sigmask() */
+		status = out_of_line_wait_on_bit(&task->tk_runstate,
+				RPC_TASK_QUEUED, rpc_wait_bit_interruptible,
+				TASK_INTERRUPTIBLE);
+		if (status == -ERESTARTSYS) {
 			/*
 			 * When a sync task receives a signal, it exits with
 			 * -ERESTARTSYS. In order to catch any callbacks that
 			 * clean up after sleeping on some queue, we don't
 			 * break the loop here, but go around once more.
 			 */
-			if (status == -ERESTARTSYS) {
-				dprintk("RPC: %4d got signal\n", task->tk_pid);
-				task->tk_flags |= RPC_TASK_KILLED;
-				rpc_exit(task, -ERESTARTSYS);
-				rpc_wake_up_task(task);
-			}
+			dprintk("RPC: %4d got signal\n", task->tk_pid);
+			task->tk_flags |= RPC_TASK_KILLED;
+			rpc_exit(task, -ERESTARTSYS);
+			rpc_wake_up_task(task);
 		}
 		rpc_set_running(task);
 		dprintk("RPC: %4d sync task resuming\n", task->tk_pid);
 	}
 
-	if (task->tk_exit) {
-		lock_kernel();
-		task->tk_exit(task);
-		unlock_kernel();
-		/* If tk_action is non-null, the user wants us to restart */
-		if (task->tk_action) {
-			if (!RPC_ASSASSINATED(task)) {
-				/* Release RPC slot and buffer memory */
-				if (task->tk_rqstp)
-					xprt_release(task);
-				rpc_free(task);
-				goto restarted;
-			}
-			printk(KERN_ERR "RPC: dead task tries to walk away.\n");
-		}
-	}
-
 	dprintk("RPC: %4d exit() = %d\n", task->tk_pid, task->tk_status);
 	status = task->tk_status;
 
@@ -759,8 +773,6 @@
 
 	/* Initialize workqueue for async tasks */
 	task->tk_workqueue = rpciod_workqueue;
-	if (!RPC_IS_ASYNC(task))
-		init_waitqueue_head(&task->u.tk_wait.waitq);
 
 	if (clnt) {
 		atomic_inc(&clnt->cl_users);
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index d4f26bf..62a0734 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -41,7 +41,9 @@
 
 /* RPC client functions */
 EXPORT_SYMBOL(rpc_create_client);
+EXPORT_SYMBOL(rpc_new_client);
 EXPORT_SYMBOL(rpc_clone_client);
+EXPORT_SYMBOL(rpc_bind_new_program);
 EXPORT_SYMBOL(rpc_destroy_client);
 EXPORT_SYMBOL(rpc_shutdown_client);
 EXPORT_SYMBOL(rpc_release_client);
@@ -61,7 +63,6 @@
 
 /* Client transport */
 EXPORT_SYMBOL(xprt_create_proto);
-EXPORT_SYMBOL(xprt_destroy);
 EXPORT_SYMBOL(xprt_set_timeout);
 EXPORT_SYMBOL(xprt_udp_slot_table_entries);
 EXPORT_SYMBOL(xprt_tcp_slot_table_entries);
@@ -129,6 +130,10 @@
 EXPORT_SYMBOL(xdr_encode_pages);
 EXPORT_SYMBOL(xdr_inline_pages);
 EXPORT_SYMBOL(xdr_shift_buf);
+EXPORT_SYMBOL(xdr_encode_word);
+EXPORT_SYMBOL(xdr_decode_word);
+EXPORT_SYMBOL(xdr_encode_array2);
+EXPORT_SYMBOL(xdr_decode_array2);
 EXPORT_SYMBOL(xdr_buf_from_iov);
 EXPORT_SYMBOL(xdr_buf_subsegment);
 EXPORT_SYMBOL(xdr_buf_read_netobj);
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index bb2d99f..e9bd912 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -35,20 +35,24 @@
 	if (!(serv = (struct svc_serv *) kmalloc(sizeof(*serv), GFP_KERNEL)))
 		return NULL;
 	memset(serv, 0, sizeof(*serv));
+	serv->sv_name      = prog->pg_name;
 	serv->sv_program   = prog;
 	serv->sv_nrthreads = 1;
 	serv->sv_stats     = prog->pg_stats;
 	serv->sv_bufsz	   = bufsize? bufsize : 4096;
-	prog->pg_lovers = prog->pg_nvers-1;
 	xdrsize = 0;
-	for (vers=0; vers<prog->pg_nvers ; vers++)
-		if (prog->pg_vers[vers]) {
-			prog->pg_hivers = vers;
-			if (prog->pg_lovers > vers)
-				prog->pg_lovers = vers;
-			if (prog->pg_vers[vers]->vs_xdrsize > xdrsize)
-				xdrsize = prog->pg_vers[vers]->vs_xdrsize;
-		}
+	while (prog) {
+		prog->pg_lovers = prog->pg_nvers-1;
+		for (vers=0; vers<prog->pg_nvers ; vers++)
+			if (prog->pg_vers[vers]) {
+				prog->pg_hivers = vers;
+				if (prog->pg_lovers > vers)
+					prog->pg_lovers = vers;
+				if (prog->pg_vers[vers]->vs_xdrsize > xdrsize)
+					xdrsize = prog->pg_vers[vers]->vs_xdrsize;
+			}
+		prog = prog->pg_next;
+	}
 	serv->sv_xdrsize   = xdrsize;
 	INIT_LIST_HEAD(&serv->sv_threads);
 	INIT_LIST_HEAD(&serv->sv_sockets);
@@ -56,8 +60,6 @@
 	INIT_LIST_HEAD(&serv->sv_permsocks);
 	spin_lock_init(&serv->sv_lock);
 
-	serv->sv_name      = prog->pg_name;
-
 	/* Remove any stale portmap registrations */
 	svc_register(serv, 0, 0);
 
@@ -281,6 +283,7 @@
 	rqstp->rq_res.len = 0;
 	rqstp->rq_res.page_base = 0;
 	rqstp->rq_res.page_len = 0;
+	rqstp->rq_res.buflen = PAGE_SIZE;
 	rqstp->rq_res.tail[0].iov_len = 0;
 	/* tcp needs a space for the record length... */
 	if (rqstp->rq_prot == IPPROTO_TCP)
@@ -338,7 +341,10 @@
 		goto sendit;
 	}
 		
-	if (prog != progp->pg_prog)
+	for (progp = serv->sv_program; progp; progp = progp->pg_next)
+		if (prog == progp->pg_prog)
+			break;
+	if (progp == NULL)
 		goto err_bad_prog;
 
 	if (vers >= progp->pg_nvers ||
@@ -451,11 +457,7 @@
 	goto sendit;
 
 err_bad_prog:
-#ifdef RPC_PARANOIA
-	if (prog != 100227 || progp->pg_prog != 100003)
-		printk("svc: unknown program %d (me %d)\n", prog, progp->pg_prog);
-	/* else it is just a Solaris client seeing if ACLs are supported */
-#endif
+	dprintk("svc: unknown program %d\n", prog);
 	serv->sv_stats->rpcbadfmt++;
 	svc_putu32(resv, rpc_prog_unavail);
 	goto sendit;
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 2b99b40..d6baf6f 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -8,6 +8,7 @@
 #include <linux/err.h>
 #include <linux/seq_file.h>
 #include <linux/hash.h>
+#include <linux/string.h>
 
 #define RPCDBG_FACILITY	RPCDBG_AUTH
 
@@ -20,14 +21,6 @@
  */
 
 
-static char *strdup(char *s)
-{
-	char *rv = kmalloc(strlen(s)+1, GFP_KERNEL);
-	if (rv)
-		strcpy(rv, s);
-	return rv;
-}
-
 struct unix_domain {
 	struct auth_domain	h;
 	int	addr_changes;
@@ -55,7 +48,7 @@
 	if (new == NULL)
 		return NULL;
 	cache_init(&new->h.h);
-	new->h.name = strdup(name);
+	new->h.name = kstrdup(name, GFP_KERNEL);
 	new->h.flavour = RPC_AUTH_UNIX;
 	new->addr_changes = 0;
 	new->h.h.expiry_time = NEVER;
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 0590703..56db8f1 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1185,8 +1185,8 @@
 	arg->page_len = (pages-2)*PAGE_SIZE;
 	arg->len = (pages-1)*PAGE_SIZE;
 	arg->tail[0].iov_len = 0;
-	
-	try_to_freeze(PF_FREEZE);
+
+	try_to_freeze();
 	if (signalled())
 		return -EINTR;
 
@@ -1227,7 +1227,7 @@
 
 		schedule_timeout(timeout);
 
-		try_to_freeze(PF_FREEZE);
+		try_to_freeze();
 
 		spin_lock_bh(&serv->sv_lock);
 		remove_wait_queue(&rqstp->rq_wait, &wait);
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c
index 67b9f035..8a4d9c1 100644
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -176,21 +176,23 @@
 	xdr->buflen += len;
 }
 
-void
+ssize_t
 xdr_partial_copy_from_skb(struct xdr_buf *xdr, unsigned int base,
 			  skb_reader_t *desc,
 			  skb_read_actor_t copy_actor)
 {
 	struct page	**ppage = xdr->pages;
 	unsigned int	len, pglen = xdr->page_len;
+	ssize_t		copied = 0;
 	int		ret;
 
 	len = xdr->head[0].iov_len;
 	if (base < len) {
 		len -= base;
 		ret = copy_actor(desc, (char *)xdr->head[0].iov_base + base, len);
+		copied += ret;
 		if (ret != len || !desc->count)
-			return;
+			goto out;
 		base = 0;
 	} else
 		base -= len;
@@ -210,6 +212,17 @@
 	do {
 		char *kaddr;
 
+		/* ACL likes to be lazy in allocating pages - ACLs
+		 * are small by default but can get huge. */
+		if (unlikely(*ppage == NULL)) {
+			*ppage = alloc_page(GFP_ATOMIC);
+			if (unlikely(*ppage == NULL)) {
+				if (copied == 0)
+					copied = -ENOMEM;
+				goto out;
+			}
+		}
+
 		len = PAGE_CACHE_SIZE;
 		kaddr = kmap_atomic(*ppage, KM_SKB_SUNRPC_DATA);
 		if (base) {
@@ -225,14 +238,17 @@
 		}
 		flush_dcache_page(*ppage);
 		kunmap_atomic(kaddr, KM_SKB_SUNRPC_DATA);
+		copied += ret;
 		if (ret != len || !desc->count)
-			return;
+			goto out;
 		ppage++;
 	} while ((pglen -= len) != 0);
 copy_tail:
 	len = xdr->tail[0].iov_len;
 	if (base < len)
-		copy_actor(desc, (char *)xdr->tail[0].iov_base + base, len - base);
+		copied += copy_actor(desc, (char *)xdr->tail[0].iov_base + base, len - base);
+out:
+	return copied;
 }
 
 
@@ -616,12 +632,24 @@
 void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, uint32_t *p)
 {
 	struct kvec *iov = buf->head;
+	int scratch_len = buf->buflen - buf->page_len - buf->tail[0].iov_len;
 
+	BUG_ON(scratch_len < 0);
 	xdr->buf = buf;
 	xdr->iov = iov;
-	xdr->end = (uint32_t *)((char *)iov->iov_base + iov->iov_len);
-	buf->len = iov->iov_len = (char *)p - (char *)iov->iov_base;
-	xdr->p = p;
+	xdr->p = (uint32_t *)((char *)iov->iov_base + iov->iov_len);
+	xdr->end = (uint32_t *)((char *)iov->iov_base + scratch_len);
+	BUG_ON(iov->iov_len > scratch_len);
+
+	if (p != xdr->p && p != NULL) {
+		size_t len;
+
+		BUG_ON(p < xdr->p || p > xdr->end);
+		len = (char *)p - (char *)xdr->p;
+		xdr->p = p;
+		buf->len += len;
+		iov->iov_len += len;
+	}
 }
 EXPORT_SYMBOL(xdr_init_encode);
 
@@ -859,8 +887,34 @@
 	return status;
 }
 
-static int
-read_u32_from_xdr_buf(struct xdr_buf *buf, int base, u32 *obj)
+/* obj is assumed to point to allocated memory of size at least len: */
+int
+write_bytes_to_xdr_buf(struct xdr_buf *buf, int base, void *obj, int len)
+{
+	struct xdr_buf subbuf;
+	int this_len;
+	int status;
+
+	status = xdr_buf_subsegment(buf, &subbuf, base, len);
+	if (status)
+		goto out;
+	this_len = min(len, (int)subbuf.head[0].iov_len);
+	memcpy(subbuf.head[0].iov_base, obj, this_len);
+	len -= this_len;
+	obj += this_len;
+	this_len = min(len, (int)subbuf.page_len);
+	if (this_len)
+		_copy_to_pages(subbuf.pages, subbuf.page_base, obj, this_len);
+	len -= this_len;
+	obj += this_len;
+	this_len = min(len, (int)subbuf.tail[0].iov_len);
+	memcpy(subbuf.tail[0].iov_base, obj, this_len);
+out:
+	return status;
+}
+
+int
+xdr_decode_word(struct xdr_buf *buf, int base, u32 *obj)
 {
 	u32	raw;
 	int	status;
@@ -872,6 +926,14 @@
 	return 0;
 }
 
+int
+xdr_encode_word(struct xdr_buf *buf, int base, u32 obj)
+{
+	u32	raw = htonl(obj);
+
+	return write_bytes_to_xdr_buf(buf, base, &raw, sizeof(obj));
+}
+
 /* If the netobj starting offset bytes from the start of xdr_buf is contained
  * entirely in the head or the tail, set object to point to it; otherwise
  * try to find space for it at the end of the tail, copy it there, and
@@ -882,7 +944,7 @@
 	u32	tail_offset = buf->head[0].iov_len + buf->page_len;
 	u32	obj_end_offset;
 
-	if (read_u32_from_xdr_buf(buf, offset, &obj->len))
+	if (xdr_decode_word(buf, offset, &obj->len))
 		goto out;
 	obj_end_offset = offset + 4 + obj->len;
 
@@ -915,3 +977,219 @@
 out:
 	return -1;
 }
+
+/* Returns 0 on success, or else a negative error code. */
+static int
+xdr_xcode_array2(struct xdr_buf *buf, unsigned int base,
+		 struct xdr_array2_desc *desc, int encode)
+{
+	char *elem = NULL, *c;
+	unsigned int copied = 0, todo, avail_here;
+	struct page **ppages = NULL;
+	int err;
+
+	if (encode) {
+		if (xdr_encode_word(buf, base, desc->array_len) != 0)
+			return -EINVAL;
+	} else {
+		if (xdr_decode_word(buf, base, &desc->array_len) != 0 ||
+		    (unsigned long) base + 4 + desc->array_len *
+				    desc->elem_size > buf->len)
+			return -EINVAL;
+	}
+	base += 4;
+
+	if (!desc->xcode)
+		return 0;
+
+	todo = desc->array_len * desc->elem_size;
+
+	/* process head */
+	if (todo && base < buf->head->iov_len) {
+		c = buf->head->iov_base + base;
+		avail_here = min_t(unsigned int, todo,
+				   buf->head->iov_len - base);
+		todo -= avail_here;
+
+		while (avail_here >= desc->elem_size) {
+			err = desc->xcode(desc, c);
+			if (err)
+				goto out;
+			c += desc->elem_size;
+			avail_here -= desc->elem_size;
+		}
+		if (avail_here) {
+			if (!elem) {
+				elem = kmalloc(desc->elem_size, GFP_KERNEL);
+				err = -ENOMEM;
+				if (!elem)
+					goto out;
+			}
+			if (encode) {
+				err = desc->xcode(desc, elem);
+				if (err)
+					goto out;
+				memcpy(c, elem, avail_here);
+			} else
+				memcpy(elem, c, avail_here);
+			copied = avail_here;
+		}
+		base = buf->head->iov_len;  /* align to start of pages */
+	}
+
+	/* process pages array */
+	base -= buf->head->iov_len;
+	if (todo && base < buf->page_len) {
+		unsigned int avail_page;
+
+		avail_here = min(todo, buf->page_len - base);
+		todo -= avail_here;
+
+		base += buf->page_base;
+		ppages = buf->pages + (base >> PAGE_CACHE_SHIFT);
+		base &= ~PAGE_CACHE_MASK;
+		avail_page = min_t(unsigned int, PAGE_CACHE_SIZE - base,
+					avail_here);
+		c = kmap(*ppages) + base;
+
+		while (avail_here) {
+			avail_here -= avail_page;
+			if (copied || avail_page < desc->elem_size) {
+				unsigned int l = min(avail_page,
+					desc->elem_size - copied);
+				if (!elem) {
+					elem = kmalloc(desc->elem_size,
+						       GFP_KERNEL);
+					err = -ENOMEM;
+					if (!elem)
+						goto out;
+				}
+				if (encode) {
+					if (!copied) {
+						err = desc->xcode(desc, elem);
+						if (err)
+							goto out;
+					}
+					memcpy(c, elem + copied, l);
+					copied += l;
+					if (copied == desc->elem_size)
+						copied = 0;
+				} else {
+					memcpy(elem + copied, c, l);
+					copied += l;
+					if (copied == desc->elem_size) {
+						err = desc->xcode(desc, elem);
+						if (err)
+							goto out;
+						copied = 0;
+					}
+				}
+				avail_page -= l;
+				c += l;
+			}
+			while (avail_page >= desc->elem_size) {
+				err = desc->xcode(desc, c);
+				if (err)
+					goto out;
+				c += desc->elem_size;
+				avail_page -= desc->elem_size;
+			}
+			if (avail_page) {
+				unsigned int l = min(avail_page,
+					    desc->elem_size - copied);
+				if (!elem) {
+					elem = kmalloc(desc->elem_size,
+						       GFP_KERNEL);
+					err = -ENOMEM;
+					if (!elem)
+						goto out;
+				}
+				if (encode) {
+					if (!copied) {
+						err = desc->xcode(desc, elem);
+						if (err)
+							goto out;
+					}
+					memcpy(c, elem + copied, l);
+					copied += l;
+					if (copied == desc->elem_size)
+						copied = 0;
+				} else {
+					memcpy(elem + copied, c, l);
+					copied += l;
+					if (copied == desc->elem_size) {
+						err = desc->xcode(desc, elem);
+						if (err)
+							goto out;
+						copied = 0;
+					}
+				}
+			}
+			if (avail_here) {
+				kunmap(*ppages);
+				ppages++;
+				c = kmap(*ppages);
+			}
+
+			avail_page = min(avail_here,
+				 (unsigned int) PAGE_CACHE_SIZE);
+		}
+		base = buf->page_len;  /* align to start of tail */
+	}
+
+	/* process tail */
+	base -= buf->page_len;
+	if (todo) {
+		c = buf->tail->iov_base + base;
+		if (copied) {
+			unsigned int l = desc->elem_size - copied;
+
+			if (encode)
+				memcpy(c, elem + copied, l);
+			else {
+				memcpy(elem + copied, c, l);
+				err = desc->xcode(desc, elem);
+				if (err)
+					goto out;
+			}
+			todo -= l;
+			c += l;
+		}
+		while (todo) {
+			err = desc->xcode(desc, c);
+			if (err)
+				goto out;
+			c += desc->elem_size;
+			todo -= desc->elem_size;
+		}
+	}
+	err = 0;
+
+out:
+	if (elem)
+		kfree(elem);
+	if (ppages)
+		kunmap(*ppages);
+	return err;
+}
+
+int
+xdr_decode_array2(struct xdr_buf *buf, unsigned int base,
+		  struct xdr_array2_desc *desc)
+{
+	if (base >= buf->len)
+		return -EINVAL;
+
+	return xdr_xcode_array2(buf, base, desc, 0);
+}
+
+int
+xdr_encode_array2(struct xdr_buf *buf, unsigned int base,
+		  struct xdr_array2_desc *desc)
+{
+	if ((unsigned long) base + 4 + desc->array_len * desc->elem_size >
+	    buf->head->iov_len + buf->page_len + buf->tail->iov_len)
+		return -EINVAL;
+
+	return xdr_xcode_array2(buf, base, desc, 1);
+}
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index c74a6bb..269f217 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -569,8 +569,11 @@
 		if (xprt->sock != NULL)
 			schedule_delayed_work(&xprt->sock_connect,
 					RPC_REESTABLISH_TIMEOUT);
-		else
+		else {
 			schedule_work(&xprt->sock_connect);
+			if (!RPC_IS_ASYNC(task))
+				flush_scheduled_work();
+		}
 	}
 	return;
  out_write:
@@ -725,7 +728,8 @@
 		goto no_checksum;
 
 	desc.csum = csum_partial(skb->data, desc.offset, skb->csum);
-	xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_and_csum_bits);
+	if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_and_csum_bits) < 0)
+		return -1;
 	if (desc.offset != skb->len) {
 		unsigned int csum2;
 		csum2 = skb_checksum(skb, desc.offset, skb->len - desc.offset, 0);
@@ -737,7 +741,8 @@
 		return -1;
 	return 0;
 no_checksum:
-	xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits);
+	if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits) < 0)
+		return -1;
 	if (desc.count)
 		return -1;
 	return 0;
@@ -821,10 +826,15 @@
 {
 	if (len > desc->count)
 		len = desc->count;
-	if (skb_copy_bits(desc->skb, desc->offset, p, len))
+	if (skb_copy_bits(desc->skb, desc->offset, p, len)) {
+		dprintk("RPC:      failed to copy %zu bytes from skb. %zu bytes remain\n",
+				len, desc->count);
 		return 0;
+	}
 	desc->offset += len;
 	desc->count -= len;
+	dprintk("RPC:      copied %zu bytes from skb. %zu bytes remain\n",
+			len, desc->count);
 	return len;
 }
 
@@ -863,6 +873,8 @@
 static void
 tcp_check_recm(struct rpc_xprt *xprt)
 {
+	dprintk("RPC:      xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u, tcp_flags = %lx\n",
+			xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen, xprt->tcp_flags);
 	if (xprt->tcp_offset == xprt->tcp_reclen) {
 		xprt->tcp_flags |= XPRT_COPY_RECM;
 		xprt->tcp_offset = 0;
@@ -907,6 +919,7 @@
 	struct rpc_rqst *req;
 	struct xdr_buf *rcvbuf;
 	size_t len;
+	ssize_t r;
 
 	/* Find and lock the request corresponding to this xid */
 	spin_lock(&xprt->sock_lock);
@@ -927,15 +940,40 @@
 		len = xprt->tcp_reclen - xprt->tcp_offset;
 		memcpy(&my_desc, desc, sizeof(my_desc));
 		my_desc.count = len;
-		xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
+		r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
 					  &my_desc, tcp_copy_data);
-		desc->count -= len;
-		desc->offset += len;
+		desc->count -= r;
+		desc->offset += r;
 	} else
-		xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
+		r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied,
 					  desc, tcp_copy_data);
-	xprt->tcp_copied += len;
-	xprt->tcp_offset += len;
+
+	if (r > 0) {
+		xprt->tcp_copied += r;
+		xprt->tcp_offset += r;
+	}
+	if (r != len) {
+		/* Error when copying to the receive buffer,
+		 * usually because we weren't able to allocate
+		 * additional buffer pages. All we can do now
+		 * is turn off XPRT_COPY_DATA, so the request
+		 * will not receive any additional updates,
+		 * and time out.
+		 * Any remaining data from this record will
+		 * be discarded.
+		 */
+		xprt->tcp_flags &= ~XPRT_COPY_DATA;
+		dprintk("RPC:      XID %08x truncated request\n",
+				ntohl(xprt->tcp_xid));
+		dprintk("RPC:      xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n",
+				xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen);
+		goto out;
+	}
+
+	dprintk("RPC:      XID %08x read %Zd bytes\n",
+			ntohl(xprt->tcp_xid), r);
+	dprintk("RPC:      xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n",
+			xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen);
 
 	if (xprt->tcp_copied == req->rq_private_buf.buflen)
 		xprt->tcp_flags &= ~XPRT_COPY_DATA;
@@ -944,6 +982,7 @@
 			xprt->tcp_flags &= ~XPRT_COPY_DATA;
 	}
 
+out:
 	if (!(xprt->tcp_flags & XPRT_COPY_DATA)) {
 		dprintk("RPC: %4d received reply complete\n",
 				req->rq_task->tk_pid);
@@ -967,6 +1006,7 @@
 	desc->count -= len;
 	desc->offset += len;
 	xprt->tcp_offset += len;
+	dprintk("RPC:      discarded %Zu bytes\n", len);
 	tcp_check_recm(xprt);
 }
 
@@ -1064,8 +1104,7 @@
 	case TCP_SYN_RECV:
 		break;
 	default:
-		if (xprt_test_and_clear_connected(xprt))
-			rpc_wake_up_status(&xprt->pending, -ENOTCONN);
+		xprt_disconnect(xprt);
 		break;
 	}
  out:
@@ -1203,6 +1242,8 @@
 			list_add_tail(&req->rq_list, &xprt->recv);
 			spin_unlock_bh(&xprt->sock_lock);
 			xprt_reset_majortimeo(req);
+			/* Turn off autodisconnect */
+			del_singleshot_timer_sync(&xprt->timer);
 		}
 	} else if (!req->rq_bytes_sent)
 		return;
@@ -1333,8 +1374,6 @@
 		spin_lock(&xprt->xprt_lock);
 		do_xprt_reserve(task);
 		spin_unlock(&xprt->xprt_lock);
-		if (task->tk_rqstp)
-			del_timer_sync(&xprt->timer);
 	}
 }
 
@@ -1649,6 +1688,10 @@
 	rpc_wake_up(&xprt->backlog);
 	wake_up(&xprt->cong_wait);
 	del_timer_sync(&xprt->timer);
+
+	/* synchronously wait for connect worker to finish */
+	cancel_delayed_work(&xprt->sock_connect);
+	flush_scheduled_work();
 }
 
 /*
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 2a24b24..04bec04 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -29,6 +29,10 @@
  *	2000-11-14	Henner Eisen    Closing datalink from NETDEV_GOING_DOWN
  *	2002-10-06	Arnaldo C. Melo Get rid of cli/sti, move proc stuff to
  *					x25_proc.c, using seq_file
+ *	2005-04-02	Shaun Pereira	Selective sub address matching
+ *					with call user data
+ *	2005-04-15	Shaun Pereira	Fast select with no restriction on
+ *					response
  */
 
 #include <linux/config.h>
@@ -219,7 +223,8 @@
  *	Note: if a listening socket has cud set it must only get calls
  *	with matching cud.
  */
-static struct sock *x25_find_listener(struct x25_address *addr, struct x25_calluserdata *calluserdata)
+static struct sock *x25_find_listener(struct x25_address *addr,
+					struct sk_buff *skb)
 {
 	struct sock *s;
 	struct sock *next_best;
@@ -230,22 +235,23 @@
 
 	sk_for_each(s, node, &x25_list)
 		if ((!strcmp(addr->x25_addr,
-			     x25_sk(s)->source_addr.x25_addr) ||
-		     !strcmp(addr->x25_addr,
-			     null_x25_address.x25_addr)) &&
-		     s->sk_state == TCP_LISTEN) {
-
+			x25_sk(s)->source_addr.x25_addr) ||
+				!strcmp(addr->x25_addr,
+					null_x25_address.x25_addr)) &&
+					s->sk_state == TCP_LISTEN) {
 			/*
 			 * Found a listening socket, now check the incoming
 			 * call user data vs this sockets call user data
 			 */
-			if (x25_check_calluserdata(&x25_sk(s)->calluserdata, calluserdata)) {
-				sock_hold(s);
-				goto found;
-			}
-			if (x25_sk(s)->calluserdata.cudlength == 0) {
+			if(skb->len > 0 && x25_sk(s)->cudmatchlength > 0) {
+			 	if((memcmp(x25_sk(s)->calluserdata.cuddata,
+			 		skb->data,
+					x25_sk(s)->cudmatchlength)) == 0) {
+					sock_hold(s);
+					goto found;
+				 }
+			} else
 				next_best = s;
-			}
 		}
 	if (next_best) {
 		s = next_best;
@@ -497,6 +503,9 @@
 	x25->t23   = sysctl_x25_clear_request_timeout;
 	x25->t2    = sysctl_x25_ack_holdback_timeout;
 	x25->state = X25_STATE_0;
+	x25->cudmatchlength = 0;
+	x25->accptapprv = X25_DENY_ACCPT_APPRV;		/* normally no cud  */
+							/* on call accept   */
 
 	x25->facilities.winsize_in  = X25_DEFAULT_WINDOW_SIZE;
 	x25->facilities.winsize_out = X25_DEFAULT_WINDOW_SIZE;
@@ -545,6 +554,8 @@
 	x25->t2         = ox25->t2;
 	x25->facilities = ox25->facilities;
 	x25->qbitincl   = ox25->qbitincl;
+	x25->cudmatchlength = ox25->cudmatchlength;
+	x25->accptapprv = ox25->accptapprv;
 
 	x25_init_timers(sk);
 out:
@@ -822,7 +833,6 @@
 	struct x25_sock *makex25;
 	struct x25_address source_addr, dest_addr;
 	struct x25_facilities facilities;
-	struct x25_calluserdata calluserdata;
 	int len, rc;
 
 	/*
@@ -845,19 +855,10 @@
 	skb_pull(skb,len);
 
 	/*
-	 *	Incoming Call User Data.
-	 */
-	if (skb->len >= 0) {
-		memcpy(calluserdata.cuddata, skb->data, skb->len);
-		calluserdata.cudlength = skb->len;
-	}
-
-	skb_push(skb,len);
-
-	/*
 	 *	Find a listener for the particular address/cud pair.
 	 */
-	sk = x25_find_listener(&source_addr,&calluserdata);
+	sk = x25_find_listener(&source_addr,skb);
+	skb_push(skb,len);
 
 	/*
 	 *	We can't accept the Call Request.
@@ -900,11 +901,23 @@
 	makex25->neighbour     = nb;
 	makex25->facilities    = facilities;
 	makex25->vc_facil_mask = x25_sk(sk)->vc_facil_mask;
-	makex25->calluserdata  = calluserdata;
+	/* ensure no reverse facil on accept */
+	makex25->vc_facil_mask &= ~X25_MASK_REVERSE;
+	makex25->cudmatchlength = x25_sk(sk)->cudmatchlength;
 
-	x25_write_internal(make, X25_CALL_ACCEPTED);
+	/* Normally all calls are accepted immediatly */
+	if(makex25->accptapprv & X25_DENY_ACCPT_APPRV) {
+		x25_write_internal(make, X25_CALL_ACCEPTED);
+		makex25->state = X25_STATE_3;
+	}
 
-	makex25->state = X25_STATE_3;
+	/*
+	 *	Incoming Call User Data.
+	 */
+	if (skb->len >= 0) {
+		memcpy(makex25->calluserdata.cuddata, skb->data, skb->len);
+		makex25->calluserdata.cudlength = skb->len;
+	}
 
 	sk->sk_ack_backlog++;
 
@@ -1288,7 +1301,8 @@
 			if (facilities.throughput < 0x03 ||
 			    facilities.throughput > 0xDD)
 				break;
-			if (facilities.reverse && facilities.reverse != 1)
+			if (facilities.reverse &&
+				(facilities.reverse | 0x81)!= 0x81)
 				break;
 			x25->facilities = facilities;
 			rc = 0;
@@ -1325,6 +1339,44 @@
 			break;
 		}
 
+		case SIOCX25SCUDMATCHLEN: {
+			struct x25_subaddr sub_addr;
+			rc = -EINVAL;
+			if(sk->sk_state != TCP_CLOSE)
+				break;
+			rc = -EFAULT;
+			if (copy_from_user(&sub_addr, argp,
+					sizeof(sub_addr)))
+				break;
+		 	rc = -EINVAL;
+			if(sub_addr.cudmatchlength > X25_MAX_CUD_LEN)
+				break;
+			x25->cudmatchlength = sub_addr.cudmatchlength;
+			rc = 0;
+			break;
+		}
+
+		case SIOCX25CALLACCPTAPPRV: {
+			rc = -EINVAL;
+			if (sk->sk_state != TCP_CLOSE)
+				break;
+			x25->accptapprv = X25_ALLOW_ACCPT_APPRV;
+			rc = 0;
+			break;
+		}
+
+		case SIOCX25SENDCALLACCPT:  {
+			rc = -EINVAL;
+			if (sk->sk_state != TCP_ESTABLISHED)
+				break;
+			if (x25->accptapprv)	/* must call accptapprv above */
+				break;
+			x25_write_internal(sk, X25_CALL_ACCEPTED);
+			x25->state = X25_STATE_3;
+			rc = 0;
+			break;
+		}
+
  		default:
 			rc = dev_ioctl(cmd, argp);
 			break;
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c
index a21bdb9..54278b9 100644
--- a/net/x25/x25_facilities.c
+++ b/net/x25/x25_facilities.c
@@ -17,6 +17,8 @@
  *	X.25 001	Split from x25_subr.c
  *	mar/20/00	Daniela Squassoni Disabling/enabling of facilities 
  *					  negotiation.
+ *	apr/14/05	Shaun Pereira - Allow fast select with no restriction
+ *					on response.
  */
 
 #include <linux/kernel.h>
@@ -43,9 +45,31 @@
 		case X25_FAC_CLASS_A:
 			switch (*p) {
 			case X25_FAC_REVERSE:
-				facilities->reverse = p[1] & 0x01;
-				*vc_fac_mask |= X25_MASK_REVERSE;
-				break;
+				if((p[1] & 0x81) == 0x81) {
+					facilities->reverse = p[1] & 0x81;
+					*vc_fac_mask |= X25_MASK_REVERSE;
+					break;
+				}
+
+				if((p[1] & 0x01) == 0x01) {
+					facilities->reverse = p[1] & 0x01;
+					*vc_fac_mask |= X25_MASK_REVERSE;
+					break;
+				}
+
+				if((p[1] & 0x80) == 0x80) {
+					facilities->reverse = p[1] & 0x80;
+					*vc_fac_mask |= X25_MASK_REVERSE;
+					break;
+				}
+
+				if(p[1] == 0x00) {
+					facilities->reverse
+						= X25_DEFAULT_REVERSE;
+					*vc_fac_mask |= X25_MASK_REVERSE;
+					break;
+				}
+
 			case X25_FAC_THROUGHPUT:
 				facilities->throughput = p[1];
 				*vc_fac_mask |= X25_MASK_THROUGHPUT;
@@ -122,7 +146,7 @@
 
 	if (facilities->reverse && (facil_mask & X25_MASK_REVERSE)) {
 		*p++ = X25_FAC_REVERSE;
-		*p++ = !!facilities->reverse;
+		*p++ = facilities->reverse;
 	}
 
 	if (facilities->throughput && (facil_mask & X25_MASK_THROUGHPUT)) {
@@ -171,7 +195,7 @@
 	/*
 	 *	They want reverse charging, we won't accept it.
 	 */
-	if (theirs.reverse && ours->reverse) {
+	if ((theirs.reverse & 0x01 ) && (ours->reverse & 0x01)) {
 		SOCK_DEBUG(sk, "X.25: rejecting reverse charging request");
 		return -1;
 	}
diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c
index 183fea3..7fd872ad 100644
--- a/net/x25/x25_subr.c
+++ b/net/x25/x25_subr.c
@@ -19,6 +19,8 @@
  *	mar/20/00	Daniela Squassoni Disabling/enabling of facilities
  *					  negotiation.
  *	jun/24/01	Arnaldo C. Melo	  use skb_queue_purge, cleanups
+ *	apr/04/15	Shaun Pereira		Fast select with no
+ *						restriction on response.
  */
 
 #include <linux/kernel.h>
@@ -127,8 +129,12 @@
 			len += 1 + X25_ADDR_LEN + X25_MAX_FAC_LEN +
 			       X25_MAX_CUD_LEN;
 			break;
-		case X25_CALL_ACCEPTED:
-			len += 1 + X25_MAX_FAC_LEN + X25_MAX_CUD_LEN;
+		case X25_CALL_ACCEPTED: /* fast sel with no restr on resp */
+			if(x25->facilities.reverse & 0x80) {
+				len += 1 + X25_MAX_FAC_LEN + X25_MAX_CUD_LEN;
+			} else {
+				len += 1 + X25_MAX_FAC_LEN;
+			}
 			break;
 		case X25_CLEAR_REQUEST:
 		case X25_RESET_REQUEST:
@@ -203,9 +209,16 @@
 							x25->vc_facil_mask);
 			dptr    = skb_put(skb, len);
 			memcpy(dptr, facilities, len);
-			dptr = skb_put(skb, x25->calluserdata.cudlength);
-			memcpy(dptr, x25->calluserdata.cuddata,
-			       x25->calluserdata.cudlength);
+
+			/* fast select with no restriction on response
+				allows call user data. Userland must
+				ensure it is ours and not theirs */
+			if(x25->facilities.reverse & 0x80) {
+				dptr = skb_put(skb,
+					x25->calluserdata.cudlength);
+				memcpy(dptr, x25->calluserdata.cuddata,
+				       x25->calluserdata.cudlength);
+			}
 			x25->calluserdata.cudlength = 0;
 			break;
 
@@ -354,21 +367,3 @@
 	}
 }
 
-/*
- * Compare 2 calluserdata structures, used to find correct listening sockets
- * when call user data is used.
- */
-int x25_check_calluserdata(struct x25_calluserdata *ours, struct x25_calluserdata *theirs)
-{
-	int i;
-	if (ours->cudlength != theirs->cudlength)
-		return 0;
-
-	for (i=0;i<ours->cudlength;i++) {
-		if (ours->cuddata[i] != theirs->cuddata[i]) {
-			return 0;
-		}
-	}
-	return 1;
-}
-
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index d07f5ce..d65ed86 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -118,7 +118,6 @@
 	xfrm_policy_put_afinfo(afinfo);
 	return type;
 }
-EXPORT_SYMBOL(xfrm_get_type);
 
 int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, 
 		    unsigned short family)
@@ -216,8 +215,8 @@
 
 expired:
 	read_unlock(&xp->lock);
-	km_policy_expired(xp, dir, 1);
-	xfrm_policy_delete(xp, dir);
+	if (!xfrm_policy_delete(xp, dir))
+		km_policy_expired(xp, dir, 1);
 	xfrm_pol_put(xp);
 }
 
@@ -555,7 +554,7 @@
 	return NULL;
 }
 
-void xfrm_policy_delete(struct xfrm_policy *pol, int dir)
+int xfrm_policy_delete(struct xfrm_policy *pol, int dir)
 {
 	write_lock_bh(&xfrm_policy_lock);
 	pol = __xfrm_policy_unlink(pol, dir);
@@ -564,7 +563,9 @@
 		if (dir < XFRM_POLICY_MAX)
 			atomic_inc(&flow_cache_genid);
 		xfrm_policy_kill(pol);
+		return 0;
 	}
+	return -ENOENT;
 }
 
 int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol)
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index d11747c..9d206c2 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -50,7 +50,7 @@
 
 static int xfrm_state_gc_flush_bundles;
 
-static void __xfrm_state_delete(struct xfrm_state *x);
+static int __xfrm_state_delete(struct xfrm_state *x);
 
 static struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned short family);
 static void xfrm_state_put_afinfo(struct xfrm_state_afinfo *afinfo);
@@ -154,6 +154,7 @@
 			next = tmo;
 	}
 
+	x->km.dying = warn;
 	if (warn)
 		km_state_expired(x, 0);
 resched:
@@ -169,9 +170,8 @@
 		next = 2;
 		goto resched;
 	}
-	if (x->id.spi != 0)
+	if (!__xfrm_state_delete(x) && x->id.spi)
 		km_state_expired(x, 1);
-	__xfrm_state_delete(x);
 
 out:
 	spin_unlock(&x->lock);
@@ -215,8 +215,10 @@
 }
 EXPORT_SYMBOL(__xfrm_state_destroy);
 
-static void __xfrm_state_delete(struct xfrm_state *x)
+static int __xfrm_state_delete(struct xfrm_state *x)
 {
+	int err = -ESRCH;
+
 	if (x->km.state != XFRM_STATE_DEAD) {
 		x->km.state = XFRM_STATE_DEAD;
 		spin_lock(&xfrm_state_lock);
@@ -245,14 +247,21 @@
 		 * is what we are dropping here.
 		 */
 		atomic_dec(&x->refcnt);
+		err = 0;
 	}
+
+	return err;
 }
 
-void xfrm_state_delete(struct xfrm_state *x)
+int xfrm_state_delete(struct xfrm_state *x)
 {
+	int err;
+
 	spin_lock_bh(&x->lock);
-	__xfrm_state_delete(x);
+	err = __xfrm_state_delete(x);
 	spin_unlock_bh(&x->lock);
+
+	return err;
 }
 EXPORT_SYMBOL(xfrm_state_delete);
 
@@ -557,16 +566,18 @@
 
 	if (x->curlft.bytes >= x->lft.hard_byte_limit ||
 	    x->curlft.packets >= x->lft.hard_packet_limit) {
-		km_state_expired(x, 1);
-		if (!mod_timer(&x->timer, jiffies + XFRM_ACQ_EXPIRES*HZ))
+		x->km.state = XFRM_STATE_EXPIRED;
+		if (!mod_timer(&x->timer, jiffies))
 			xfrm_state_hold(x);
 		return -EINVAL;
 	}
 
 	if (!x->km.dying &&
 	    (x->curlft.bytes >= x->lft.soft_byte_limit ||
-	     x->curlft.packets >= x->lft.soft_packet_limit))
+	     x->curlft.packets >= x->lft.soft_packet_limit)) {
+		x->km.dying = 1;
 		km_state_expired(x, 0);
+	}
 	return 0;
 }
 EXPORT_SYMBOL(xfrm_state_check_expire);
@@ -796,34 +807,56 @@
 static struct list_head xfrm_km_list = LIST_HEAD_INIT(xfrm_km_list);
 static DEFINE_RWLOCK(xfrm_km_lock);
 
-static void km_state_expired(struct xfrm_state *x, int hard)
+void km_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
 {
 	struct xfrm_mgr *km;
 
-	if (hard)
-		x->km.state = XFRM_STATE_EXPIRED;
-	else
-		x->km.dying = 1;
-
 	read_lock(&xfrm_km_lock);
 	list_for_each_entry(km, &xfrm_km_list, list)
-		km->notify(x, hard);
+		if (km->notify_policy)
+			km->notify_policy(xp, dir, c);
 	read_unlock(&xfrm_km_lock);
+}
+
+void km_state_notify(struct xfrm_state *x, struct km_event *c)
+{
+	struct xfrm_mgr *km;
+	read_lock(&xfrm_km_lock);
+	list_for_each_entry(km, &xfrm_km_list, list)
+		if (km->notify)
+			km->notify(x, c);
+	read_unlock(&xfrm_km_lock);
+}
+
+EXPORT_SYMBOL(km_policy_notify);
+EXPORT_SYMBOL(km_state_notify);
+
+static void km_state_expired(struct xfrm_state *x, int hard)
+{
+	struct km_event c;
+
+	c.data.hard = hard;
+	c.event = XFRM_MSG_EXPIRE;
+	km_state_notify(x, &c);
 
 	if (hard)
 		wake_up(&km_waitq);
 }
 
+/*
+ * We send to all registered managers regardless of failure
+ * We are happy with one success
+*/
 static int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol)
 {
-	int err = -EINVAL;
+	int err = -EINVAL, acqret;
 	struct xfrm_mgr *km;
 
 	read_lock(&xfrm_km_lock);
 	list_for_each_entry(km, &xfrm_km_list, list) {
-		err = km->acquire(x, t, pol, XFRM_POLICY_OUT);
-		if (!err)
-			break;
+		acqret = km->acquire(x, t, pol, XFRM_POLICY_OUT);
+		if (!acqret)
+			err = acqret;
 	}
 	read_unlock(&xfrm_km_lock);
 	return err;
@@ -848,13 +881,11 @@
 
 void km_policy_expired(struct xfrm_policy *pol, int dir, int hard)
 {
-	struct xfrm_mgr *km;
+	struct km_event c;
 
-	read_lock(&xfrm_km_lock);
-	list_for_each_entry(km, &xfrm_km_list, list)
-		if (km->notify_policy)
-			km->notify_policy(pol, dir, hard);
-	read_unlock(&xfrm_km_lock);
+	c.data.hard = hard;
+	c.event = XFRM_MSG_POLEXPIRE;
+	km_policy_notify(pol, dir, &c);
 
 	if (hard)
 		wake_up(&km_waitq);
@@ -1024,6 +1055,43 @@
 }
 
 EXPORT_SYMBOL(xfrm_state_mtu);
+
+int xfrm_init_state(struct xfrm_state *x)
+{
+	struct xfrm_state_afinfo *afinfo;
+	int family = x->props.family;
+	int err;
+
+	err = -EAFNOSUPPORT;
+	afinfo = xfrm_state_get_afinfo(family);
+	if (!afinfo)
+		goto error;
+
+	err = 0;
+	if (afinfo->init_flags)
+		err = afinfo->init_flags(x);
+
+	xfrm_state_put_afinfo(afinfo);
+
+	if (err)
+		goto error;
+
+	err = -EPROTONOSUPPORT;
+	x->type = xfrm_get_type(x->id.proto, family);
+	if (x->type == NULL)
+		goto error;
+
+	err = x->type->init_state(x);
+	if (err)
+		goto error;
+
+	x->km.state = XFRM_STATE_VALID;
+
+error:
+	return err;
+}
+
+EXPORT_SYMBOL(xfrm_init_state);
  
 void __init xfrm_state_init(void)
 {
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 9750901..ecade48 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -249,17 +249,10 @@
 	if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1])))
 		goto error;
 
-	err = -ENOENT;
-	x->type = xfrm_get_type(x->id.proto, x->props.family);
-	if (x->type == NULL)
-		goto error;
-
-	err = x->type->init_state(x, NULL);
+	err = xfrm_init_state(x);
 	if (err)
 		goto error;
 
-	x->curlft.add_time = (unsigned long) xtime.tv_sec;
-	x->km.state = XFRM_STATE_VALID;
 	x->km.seq = p->seq;
 
 	return x;
@@ -277,6 +270,7 @@
 	struct xfrm_usersa_info *p = NLMSG_DATA(nlh);
 	struct xfrm_state *x;
 	int err;
+	struct km_event c;
 
 	err = verify_newsa_info(p, (struct rtattr **) xfrma);
 	if (err)
@@ -286,6 +280,7 @@
 	if (!x)
 		return err;
 
+	xfrm_state_hold(x);
 	if (nlh->nlmsg_type == XFRM_MSG_NEWSA)
 		err = xfrm_state_add(x);
 	else
@@ -294,14 +289,24 @@
 	if (err < 0) {
 		x->km.state = XFRM_STATE_DEAD;
 		xfrm_state_put(x);
+		goto out;
 	}
 
+	c.seq = nlh->nlmsg_seq;
+	c.pid = nlh->nlmsg_pid;
+	c.event = nlh->nlmsg_type;
+
+	km_state_notify(x, &c);
+out:
+	xfrm_state_put(x);
 	return err;
 }
 
 static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
 {
 	struct xfrm_state *x;
+	int err;
+	struct km_event c;
 	struct xfrm_usersa_id *p = NLMSG_DATA(nlh);
 
 	x = xfrm_state_lookup(&p->daddr, p->spi, p->proto, p->family);
@@ -313,10 +318,19 @@
 		return -EPERM;
 	}
 
-	xfrm_state_delete(x);
+	err = xfrm_state_delete(x);
+	if (err < 0) {
+		xfrm_state_put(x);
+		return err;
+	}
+
+	c.seq = nlh->nlmsg_seq;
+	c.pid = nlh->nlmsg_pid;
+	c.event = nlh->nlmsg_type;
+	km_state_notify(x, &c);
 	xfrm_state_put(x);
 
-	return 0;
+	return err;
 }
 
 static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
@@ -681,6 +695,7 @@
 {
 	struct xfrm_userpolicy_info *p = NLMSG_DATA(nlh);
 	struct xfrm_policy *xp;
+	struct km_event c;
 	int err;
 	int excl;
 
@@ -692,6 +707,10 @@
 	if (!xp)
 		return err;
 
+	/* shouldnt excl be based on nlh flags??
+	 * Aha! this is anti-netlink really i.e  more pfkey derived
+	 * in netlink excl is a flag and you wouldnt need
+	 * a type XFRM_MSG_UPDPOLICY - JHS */
 	excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY;
 	err = xfrm_policy_insert(p->dir, xp, excl);
 	if (err) {
@@ -699,6 +718,11 @@
 		return err;
 	}
 
+	c.event = nlh->nlmsg_type;
+	c.seq = nlh->nlmsg_seq;
+	c.pid = nlh->nlmsg_pid;
+	km_policy_notify(xp, p->dir, &c);
+
 	xfrm_pol_put(xp);
 
 	return 0;
@@ -816,6 +840,7 @@
 	struct xfrm_policy *xp;
 	struct xfrm_userpolicy_id *p;
 	int err;
+	struct km_event c;
 	int delete;
 
 	p = NLMSG_DATA(nlh);
@@ -843,6 +868,12 @@
 					      NETLINK_CB(skb).pid,
 					      MSG_DONTWAIT);
 		}
+	} else {
+		c.data.byid = p->index;
+		c.event = nlh->nlmsg_type;
+		c.seq = nlh->nlmsg_seq;
+		c.pid = nlh->nlmsg_pid;
+		km_policy_notify(xp, p->dir, &c);
 	}
 
 	xfrm_pol_put(xp);
@@ -852,15 +883,28 @@
 
 static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
 {
+	struct km_event c;
 	struct xfrm_usersa_flush *p = NLMSG_DATA(nlh);
 
 	xfrm_state_flush(p->proto);
+	c.data.proto = p->proto;
+	c.event = nlh->nlmsg_type;
+	c.seq = nlh->nlmsg_seq;
+	c.pid = nlh->nlmsg_pid;
+	km_state_notify(NULL, &c);
+
 	return 0;
 }
 
 static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
 {
+	struct km_event c;
+
 	xfrm_policy_flush();
+	c.event = nlh->nlmsg_type;
+	c.seq = nlh->nlmsg_seq;
+	c.pid = nlh->nlmsg_pid;
+	km_policy_notify(NULL, 0, &c);
 	return 0;
 }
 
@@ -1069,15 +1113,16 @@
 	return -1;
 }
 
-static int xfrm_send_state_notify(struct xfrm_state *x, int hard)
+static int xfrm_exp_state_notify(struct xfrm_state *x, struct km_event *c)
 {
 	struct sk_buff *skb;
+	int len = NLMSG_LENGTH(sizeof(struct xfrm_user_expire));
 
-	skb = alloc_skb(sizeof(struct xfrm_user_expire) + 16, GFP_ATOMIC);
+	skb = alloc_skb(len, GFP_ATOMIC);
 	if (skb == NULL)
 		return -ENOMEM;
 
-	if (build_expire(skb, x, hard) < 0)
+	if (build_expire(skb, x, c->data.hard) < 0)
 		BUG();
 
 	NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE;
@@ -1085,6 +1130,131 @@
 	return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC);
 }
 
+static int xfrm_notify_sa_flush(struct km_event *c)
+{
+	struct xfrm_usersa_flush *p;
+	struct nlmsghdr *nlh;
+	struct sk_buff *skb;
+	unsigned char *b;
+	int len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_flush));
+
+	skb = alloc_skb(len, GFP_ATOMIC);
+	if (skb == NULL)
+		return -ENOMEM;
+	b = skb->tail;
+
+	nlh = NLMSG_PUT(skb, c->pid, c->seq,
+			XFRM_MSG_FLUSHSA, sizeof(*p));
+	nlh->nlmsg_flags = 0;
+
+	p = NLMSG_DATA(nlh);
+	p->proto = c->data.proto;
+
+	nlh->nlmsg_len = skb->tail - b;
+
+	return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_SA, GFP_ATOMIC);
+
+nlmsg_failure:
+	kfree_skb(skb);
+	return -1;
+}
+
+static int inline xfrm_sa_len(struct xfrm_state *x)
+{
+	int l = 0;
+	if (x->aalg)
+		l += RTA_SPACE(sizeof(*x->aalg) + (x->aalg->alg_key_len+7)/8);
+	if (x->ealg)
+		l += RTA_SPACE(sizeof(*x->ealg) + (x->ealg->alg_key_len+7)/8);
+	if (x->calg)
+		l += RTA_SPACE(sizeof(*x->calg));
+	if (x->encap)
+		l += RTA_SPACE(sizeof(*x->encap));
+
+	return l;
+}
+
+static int xfrm_notify_sa(struct xfrm_state *x, struct km_event *c)
+{
+	struct xfrm_usersa_info *p;
+	struct xfrm_usersa_id *id;
+	struct nlmsghdr *nlh;
+	struct sk_buff *skb;
+	unsigned char *b;
+	int len = xfrm_sa_len(x);
+	int headlen;
+
+	headlen = sizeof(*p);
+	if (c->event == XFRM_MSG_DELSA) {
+		len += RTA_SPACE(headlen);
+		headlen = sizeof(*id);
+	}
+	len += NLMSG_SPACE(headlen);
+
+	skb = alloc_skb(len, GFP_ATOMIC);
+	if (skb == NULL)
+		return -ENOMEM;
+	b = skb->tail;
+
+	nlh = NLMSG_PUT(skb, c->pid, c->seq, c->event, headlen);
+	nlh->nlmsg_flags = 0;
+
+	p = NLMSG_DATA(nlh);
+	if (c->event == XFRM_MSG_DELSA) {
+		id = NLMSG_DATA(nlh);
+		memcpy(&id->daddr, &x->id.daddr, sizeof(id->daddr));
+		id->spi = x->id.spi;
+		id->family = x->props.family;
+		id->proto = x->id.proto;
+
+		p = RTA_DATA(__RTA_PUT(skb, XFRMA_SA, sizeof(*p)));
+	}
+
+	copy_to_user_state(x, p);
+
+	if (x->aalg)
+		RTA_PUT(skb, XFRMA_ALG_AUTH,
+			sizeof(*(x->aalg))+(x->aalg->alg_key_len+7)/8, x->aalg);
+	if (x->ealg)
+		RTA_PUT(skb, XFRMA_ALG_CRYPT,
+			sizeof(*(x->ealg))+(x->ealg->alg_key_len+7)/8, x->ealg);
+	if (x->calg)
+		RTA_PUT(skb, XFRMA_ALG_COMP, sizeof(*(x->calg)), x->calg);
+
+	if (x->encap)
+		RTA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap);
+
+	nlh->nlmsg_len = skb->tail - b;
+
+	return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_SA, GFP_ATOMIC);
+
+nlmsg_failure:
+rtattr_failure:
+	kfree_skb(skb);
+	return -1;
+}
+
+static int xfrm_send_state_notify(struct xfrm_state *x, struct km_event *c)
+{
+
+	switch (c->event) {
+	case XFRM_MSG_EXPIRE:
+		return xfrm_exp_state_notify(x, c);
+	case XFRM_MSG_DELSA:
+	case XFRM_MSG_UPDSA:
+	case XFRM_MSG_NEWSA:
+		return xfrm_notify_sa(x, c);
+	case XFRM_MSG_FLUSHSA:
+		return xfrm_notify_sa_flush(c);
+	default:
+		 printk("xfrm_user: Unknown SA event %d\n", c->event);
+		 break;
+	}
+
+	return 0;
+
+}
+
 static int build_acquire(struct sk_buff *skb, struct xfrm_state *x,
 			 struct xfrm_tmpl *xt, struct xfrm_policy *xp,
 			 int dir)
@@ -1218,7 +1388,7 @@
 	return -1;
 }
 
-static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, int hard)
+static int xfrm_exp_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
 {
 	struct sk_buff *skb;
 	size_t len;
@@ -1229,7 +1399,7 @@
 	if (skb == NULL)
 		return -ENOMEM;
 
-	if (build_polexpire(skb, xp, dir, hard) < 0)
+	if (build_polexpire(skb, xp, dir, c->data.hard) < 0)
 		BUG();
 
 	NETLINK_CB(skb).dst_groups = XFRMGRP_EXPIRE;
@@ -1237,6 +1407,103 @@
 	return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_EXPIRE, GFP_ATOMIC);
 }
 
+static int xfrm_notify_policy(struct xfrm_policy *xp, int dir, struct km_event *c)
+{
+	struct xfrm_userpolicy_info *p;
+	struct xfrm_userpolicy_id *id;
+	struct nlmsghdr *nlh;
+	struct sk_buff *skb;
+	unsigned char *b;
+	int len = RTA_SPACE(sizeof(struct xfrm_user_tmpl) * xp->xfrm_nr);
+	int headlen;
+
+	headlen = sizeof(*p);
+	if (c->event == XFRM_MSG_DELPOLICY) {
+		len += RTA_SPACE(headlen);
+		headlen = sizeof(*id);
+	}
+	len += NLMSG_SPACE(headlen);
+
+	skb = alloc_skb(len, GFP_ATOMIC);
+	if (skb == NULL)
+		return -ENOMEM;
+	b = skb->tail;
+
+	nlh = NLMSG_PUT(skb, c->pid, c->seq, c->event, headlen);
+
+	p = NLMSG_DATA(nlh);
+	if (c->event == XFRM_MSG_DELPOLICY) {
+		id = NLMSG_DATA(nlh);
+		memset(id, 0, sizeof(*id));
+		id->dir = dir;
+		if (c->data.byid)
+			id->index = xp->index;
+		else
+			memcpy(&id->sel, &xp->selector, sizeof(id->sel));
+
+		p = RTA_DATA(__RTA_PUT(skb, XFRMA_POLICY, sizeof(*p)));
+	}
+
+	nlh->nlmsg_flags = 0;
+
+	copy_to_user_policy(xp, p, dir);
+	if (copy_to_user_tmpl(xp, skb) < 0)
+		goto nlmsg_failure;
+
+	nlh->nlmsg_len = skb->tail - b;
+
+	return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_POLICY, GFP_ATOMIC);
+
+nlmsg_failure:
+rtattr_failure:
+	kfree_skb(skb);
+	return -1;
+}
+
+static int xfrm_notify_policy_flush(struct km_event *c)
+{
+	struct nlmsghdr *nlh;
+	struct sk_buff *skb;
+	unsigned char *b;
+	int len = NLMSG_LENGTH(0);
+
+	skb = alloc_skb(len, GFP_ATOMIC);
+	if (skb == NULL)
+		return -ENOMEM;
+	b = skb->tail;
+
+
+	nlh = NLMSG_PUT(skb, c->pid, c->seq, XFRM_MSG_FLUSHPOLICY, 0);
+
+	nlh->nlmsg_len = skb->tail - b;
+
+	return netlink_broadcast(xfrm_nl, skb, 0, XFRMGRP_POLICY, GFP_ATOMIC);
+
+nlmsg_failure:
+	kfree_skb(skb);
+	return -1;
+}
+
+static int xfrm_send_policy_notify(struct xfrm_policy *xp, int dir, struct km_event *c)
+{
+
+	switch (c->event) {
+	case XFRM_MSG_NEWPOLICY:
+	case XFRM_MSG_UPDPOLICY:
+	case XFRM_MSG_DELPOLICY:
+		return xfrm_notify_policy(xp, dir, c);
+	case XFRM_MSG_FLUSHPOLICY:
+		return xfrm_notify_policy_flush(c);
+	case XFRM_MSG_POLEXPIRE:
+		return xfrm_exp_policy_notify(xp, dir, c);
+	default:
+		printk("xfrm_user: Unknown Policy event %d\n", c->event);
+	}
+
+	return 0;
+
+}
+
 static struct xfrm_mgr netlink_mgr = {
 	.id		= "netlink",
 	.notify		= xfrm_send_state_notify,
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 352d531..76ba6be 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -176,10 +176,10 @@
 define rule_cc_o_c
 	$(if $($(quiet)cmd_checksrc),echo '  $($(quiet)cmd_checksrc)';)   \
 	$(cmd_checksrc)							  \
-	$(if $($(quiet)cmd_cc_o_c),echo '  $($(quiet)cmd_cc_o_c)';)	  \
+	$(if $($(quiet)cmd_cc_o_c),echo '  $(subst ','\'',$($(quiet)cmd_cc_o_c))';)  \
 	$(cmd_cc_o_c);							  \
 	$(cmd_modversions)						  \
-	scripts/basic/fixdep $(depfile) $@ '$(cmd_cc_o_c)' > $(@D)/.$(@F).tmp;  \
+	scripts/basic/fixdep $(depfile) $@ '$(subst ','\'',$(cmd_cc_o_c))' > $(@D)/.$(@F).tmp;  \
 	rm -f $(depfile);						  \
 	mv -f $(@D)/.$(@F).tmp $(@D)/.$(@F).cmd
 endef
diff --git a/scripts/basic/docproc.c b/scripts/basic/docproc.c
index 8ca7ecd..cb02baa 100644
--- a/scripts/basic/docproc.c
+++ b/scripts/basic/docproc.c
@@ -52,7 +52,7 @@
 FILEONLY *externalfunctions;
 FILEONLY *symbolsonly;
 
-typedef void FILELINE(char * file, signed char * line);
+typedef void FILELINE(char * file, char * line);
 FILELINE * singlefunctions;
 FILELINE * entity_system;
 
@@ -148,9 +148,9 @@
  * Files are separated by tabs.
  */
 void adddep(char * file)		   { printf("\t%s", file); }
-void adddep2(char * file, signed char * line)     { line = line; adddep(file); }
+void adddep2(char * file, char * line)     { line = line; adddep(file); }
 void noaction(char * line)		   { line = line; }
-void noaction2(char * file, signed char * line)   { file = file; line = line; }
+void noaction2(char * file, char * line)   { file = file; line = line; }
 
 /* Echo the line without further action */
 void printline(char * line)               { printf("%s", line); }
@@ -179,8 +179,8 @@
 			perror(real_filename);
 		}
 		while(fgets(line, MAXLINESZ, fp)) {
-			signed char *p;
-			signed char *e;
+			char *p;
+			char *e;
 			if (((p = strstr(line, "EXPORT_SYMBOL_GPL")) != 0) ||
                             ((p = strstr(line, "EXPORT_SYMBOL")) != 0)) {
 				/* Skip EXPORT_SYMBOL{_GPL} */
@@ -253,7 +253,7 @@
  * Call kernel-doc with the following parameters:
  * kernel-doc -docbook -function function1 [-function function2]
  */
-void singfunc(char * filename, signed char * line)
+void singfunc(char * filename, char * line)
 {
 	char *vec[200]; /* Enough for specific functions */
         int i, idx = 0;
@@ -290,7 +290,7 @@
 void parse_file(FILE *infile)
 {
 	char line[MAXLINESZ];
-	signed char * s;
+	char * s;
 	while(fgets(line, MAXLINESZ, infile)) {
 		if (line[0] == '!') {
 			s = line + 2;
diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c
index 7f42c5d..0b61bea 100644
--- a/scripts/basic/fixdep.c
+++ b/scripts/basic/fixdep.c
@@ -212,23 +212,23 @@
 		if (*p == '_')
 			*p = '/';
 		else
-			*p = tolower((unsigned char)*p);
+			*p = tolower((int)*p);
 	}
 	printf("    $(wildcard include/config/%s.h) \\\n", s);
 }
 
-void parse_config_file(signed char *map, size_t len)
+void parse_config_file(char *map, size_t len)
 {
 	int *end = (int *) (map + len);
 	/* start at +1, so that p can never be < map */
 	int *m   = (int *) map + 1;
-	signed char *p, *q;
+	char *p, *q;
 
 	for (; m < end; m++) {
-		if (*m == INT_CONF) { p = (signed char *) m  ; goto conf; }
-		if (*m == INT_ONFI) { p = (signed char *) m-1; goto conf; }
-		if (*m == INT_NFIG) { p = (signed char *) m-2; goto conf; }
-		if (*m == INT_FIG_) { p = (signed char *) m-3; goto conf; }
+		if (*m == INT_CONF) { p = (char *) m  ; goto conf; }
+		if (*m == INT_ONFI) { p = (char *) m-1; goto conf; }
+		if (*m == INT_NFIG) { p = (char *) m-2; goto conf; }
+		if (*m == INT_FIG_) { p = (char *) m-3; goto conf; }
 		continue;
 	conf:
 		if (p > map + len - 7)
@@ -291,9 +291,9 @@
 
 void parse_dep_file(void *map, size_t len)
 {
-	signed char *m = map;
-	signed char *end = m + len;
-	signed char *p;
+	char *m = map;
+	char *end = m + len;
+	char *p;
 	char s[PATH_MAX];
 
 	p = strchr(m, ':');
diff --git a/scripts/basic/split-include.c b/scripts/basic/split-include.c
index 60fc4d8..459c4527 100644
--- a/scripts/basic/split-include.c
+++ b/scripts/basic/split-include.c
@@ -104,7 +104,7 @@
     /* Read config lines. */
     while (fgets(line, buffer_size, fp_config))
     {
-	const signed char * str_config;
+	const char * str_config;
 	int is_same;
 	int itarget;
 
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 70e7264..bc20cab 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -31,14 +31,14 @@
 static int indent = 1;
 static int valid_stdin = 1;
 static int conf_cnt;
-static signed char line[128];
+static char line[128];
 static struct menu *rootEntry;
 
 static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n");
 
-static void strip(signed char *str)
+static void strip(char *str)
 {
-	signed char *p = str;
+	char *p = str;
 	int l;
 
 	while ((isspace(*p)))
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 2755c45..02f670c 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -27,10 +27,10 @@
 	NULL,
 };
 
-static char *conf_expand_value(const signed char *in)
+static char *conf_expand_value(const char *in)
 {
 	struct symbol *sym;
-	const signed char *src;
+	const char *src;
 	static char res_value[SYMBOL_MAXLENGTH];
 	char *dst, name[SYMBOL_MAXLENGTH];
 
diff --git a/scripts/kconfig/gconf.glade b/scripts/kconfig/gconf.glade
index 1e1736d..ace4706 100644
--- a/scripts/kconfig/gconf.glade
+++ b/scripts/kconfig/gconf.glade
@@ -432,8 +432,8 @@
 	  <child>
 	    <widget class="GtkScrolledWindow" id="scrolledwindow1">
 	      <property name="visible">True</property>
-	      <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
-	      <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+	      <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+	      <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
 	      <property name="shadow_type">GTK_SHADOW_IN</property>
 	      <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
 
@@ -466,8 +466,8 @@
 	      <child>
 		<widget class="GtkScrolledWindow" id="scrolledwindow2">
 		  <property name="visible">True</property>
-		  <property name="hscrollbar_policy">GTK_POLICY_ALWAYS</property>
-		  <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+		  <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+		  <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
 		  <property name="shadow_type">GTK_SHADOW_IN</property>
 		  <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
 
@@ -496,7 +496,7 @@
 		<widget class="GtkScrolledWindow" id="scrolledwindow3">
 		  <property name="visible">True</property>
 		  <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
-		  <property name="vscrollbar_policy">GTK_POLICY_ALWAYS</property>
+		  <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
 		  <property name="shadow_type">GTK_SHADOW_IN</property>
 		  <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
 
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index e5db10c..457bec2 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -20,6 +20,7 @@
 #include <string.h>
 #include <termios.h>
 #include <unistd.h>
+#include <locale.h>
 
 #define LKC_DIRECT_LINK
 #include "lkc.h"
@@ -254,8 +255,8 @@
 	"          USB$ => find all CONFIG_ symbols ending with USB\n"
 	"\n");
 
-static signed char buf[4096], *bufptr = buf;
-static signed char input_buf[4096];
+static char buf[4096], *bufptr = buf;
+static char input_buf[4096];
 static char filename[PATH_MAX+1] = ".config";
 static char *args[1024], **argptr = args;
 static int indent;
diff --git a/security/commoncap.c b/security/commoncap.c
index 849b8c3..04c12f5 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -149,7 +149,7 @@
 
 	if (bprm->e_uid != current->uid || bprm->e_gid != current->gid ||
 	    !cap_issubset (new_permitted, current->cap_permitted)) {
-		current->mm->dumpable = 0;
+		current->mm->dumpable = suid_dumpable;
 
 		if (unsafe & ~LSM_UNSAFE_PTRACE_CAP) {
 			if (!capable(CAP_SETUID)) {
diff --git a/security/dummy.c b/security/dummy.c
index b32eff1..6ff8875 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -130,7 +130,7 @@
 static void dummy_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
 {
 	if (bprm->e_uid != current->uid || bprm->e_gid != current->gid) {
-		current->mm->dumpable = 0;
+		current->mm->dumpable = suid_dumpable;
 
 		if ((unsafe & ~LSM_UNSAFE_PTRACE_CAP) && !capable(CAP_SETUID)) {
 			bprm->e_uid = current->uid;
diff --git a/security/keys/Makefile b/security/keys/Makefile
index ddb495d6..c392d75 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -7,8 +7,9 @@
 	keyring.o \
 	keyctl.o \
 	process_keys.o \
-	user_defined.o \
-	request_key.o
+	request_key.o \
+	request_key_auth.o \
+	user_defined.o
 
 obj-$(CONFIG_KEYS_COMPAT) += compat.o
 obj-$(CONFIG_PROC_FS) += proc.o
diff --git a/security/keys/compat.c b/security/keys/compat.c
index aff8b22..3303673 100644
--- a/security/keys/compat.c
+++ b/security/keys/compat.c
@@ -1,6 +1,6 @@
 /* compat.c: 32-bit compatibility syscall for 64-bit systems
  *
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
  * Written by David Howells (dhowells@redhat.com)
  *
  * This program is free software; you can redistribute it and/or
@@ -24,7 +24,7 @@
  * - if you can, you should call sys_keyctl directly
  */
 asmlinkage long compat_sys_keyctl(u32 option,
-			      u32 arg2, u32 arg3, u32 arg4, u32 arg5)
+				  u32 arg2, u32 arg3, u32 arg4, u32 arg5)
 {
 	switch (option) {
 	case KEYCTL_GET_KEYRING_ID:
@@ -71,6 +71,9 @@
 	case KEYCTL_NEGATE:
 		return keyctl_negate_key(arg2, arg3, arg4);
 
+	case KEYCTL_SET_REQKEY_KEYRING:
+		return keyctl_set_reqkey_keyring(arg2);
+
 	default:
 		return -EOPNOTSUPP;
 	}
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 67b2b93..46c8602 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -1,6 +1,6 @@
 /* internal.h: authentication token and access key management internal defs
  *
- * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2003-5 Red Hat, Inc. All Rights Reserved.
  * Written by David Howells (dhowells@redhat.com)
  *
  * This program is free software; you can redistribute it and/or
@@ -15,6 +15,16 @@
 #include <linux/key.h>
 #include <linux/key-ui.h>
 
+#if 0
+#define kenter(FMT, a...)	printk("==> %s("FMT")\n",__FUNCTION__ , ## a)
+#define kleave(FMT, a...)	printk("<== %s()"FMT"\n",__FUNCTION__ , ## a)
+#define kdebug(FMT, a...)	printk(FMT"\n" , ## a)
+#else
+#define kenter(FMT, a...)	do {} while(0)
+#define kleave(FMT, a...)	do {} while(0)
+#define kdebug(FMT, a...)	do {} while(0)
+#endif
+
 extern struct key_type key_type_dead;
 extern struct key_type key_type_user;
 
@@ -66,20 +76,46 @@
 					const char *description,
 					key_perm_t perm);
 
+extern struct key *keyring_search_instkey(struct key *keyring,
+					  key_serial_t target_id);
+
 typedef int (*key_match_func_t)(const struct key *, const void *);
 
 extern struct key *keyring_search_aux(struct key *keyring,
+				      struct task_struct *tsk,
 				      struct key_type *type,
 				      const void *description,
 				      key_match_func_t match);
 
-extern struct key *search_process_keyrings_aux(struct key_type *type,
-					       const void *description,
-					       key_match_func_t match);
+extern struct key *search_process_keyrings(struct key_type *type,
+					   const void *description,
+					   key_match_func_t match,
+					   struct task_struct *tsk);
 
 extern struct key *find_keyring_by_name(const char *name, key_serial_t bound);
 
 extern int install_thread_keyring(struct task_struct *tsk);
+extern int install_process_keyring(struct task_struct *tsk);
+
+extern struct key *request_key_and_link(struct key_type *type,
+					const char *description,
+					const char *callout_info,
+					struct key *dest_keyring);
+
+/*
+ * request_key authorisation
+ */
+struct request_key_auth {
+	struct key		*target_key;
+	struct task_struct	*context;
+	pid_t			pid;
+};
+
+extern struct key_type key_type_request_key_auth;
+extern struct key *request_key_auth_new(struct key *target,
+					struct key **_rkakey);
+
+extern struct key *key_get_instantiation_authkey(key_serial_t target_id);
 
 /*
  * keyctl functions
@@ -100,6 +136,7 @@
 extern long keyctl_instantiate_key(key_serial_t, const void __user *,
 				   size_t, key_serial_t);
 extern long keyctl_negate_key(key_serial_t, unsigned, key_serial_t);
+extern long keyctl_set_reqkey_keyring(int);
 
 
 /*
diff --git a/security/keys/key.c b/security/keys/key.c
index 59402c8..fb89f98 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -1,6 +1,6 @@
 /* key.c: basic authentication token and access key management
  *
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
  * Written by David Howells (dhowells@redhat.com)
  *
  * This program is free software; you can redistribute it and/or
@@ -294,7 +294,6 @@
 	}
 
 	atomic_set(&key->usage, 1);
-	rwlock_init(&key->lock);
 	init_rwsem(&key->sem);
 	key->type = type;
 	key->user = user;
@@ -308,7 +307,7 @@
 	key->payload.data = NULL;
 
 	if (!not_in_quota)
-		key->flags |= KEY_FLAG_IN_QUOTA;
+		key->flags |= 1 << KEY_FLAG_IN_QUOTA;
 
 	memset(&key->type_data, 0, sizeof(key->type_data));
 
@@ -359,7 +358,7 @@
 	key_check(key);
 
 	/* contemplate the quota adjustment */
-	if (delta != 0 && key->flags & KEY_FLAG_IN_QUOTA) {
+	if (delta != 0 && test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
 		spin_lock(&key->user->lock);
 
 		if (delta > 0 &&
@@ -392,7 +391,8 @@
 static int __key_instantiate_and_link(struct key *key,
 				      const void *data,
 				      size_t datalen,
-				      struct key *keyring)
+				      struct key *keyring,
+				      struct key *instkey)
 {
 	int ret, awaken;
 
@@ -405,27 +405,25 @@
 	down_write(&key_construction_sem);
 
 	/* can't instantiate twice */
-	if (!(key->flags & KEY_FLAG_INSTANTIATED)) {
+	if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
 		/* instantiate the key */
 		ret = key->type->instantiate(key, data, datalen);
 
 		if (ret == 0) {
 			/* mark the key as being instantiated */
-			write_lock(&key->lock);
-
 			atomic_inc(&key->user->nikeys);
-			key->flags |= KEY_FLAG_INSTANTIATED;
+			set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
 
-			if (key->flags & KEY_FLAG_USER_CONSTRUCT) {
-				key->flags &= ~KEY_FLAG_USER_CONSTRUCT;
+			if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags))
 				awaken = 1;
-			}
-
-			write_unlock(&key->lock);
 
 			/* and link it into the destination keyring */
 			if (keyring)
 				ret = __key_link(keyring, key);
+
+			/* disable the authorisation key */
+			if (instkey)
+				key_revoke(instkey);
 		}
 	}
 
@@ -446,19 +444,21 @@
 int key_instantiate_and_link(struct key *key,
 			     const void *data,
 			     size_t datalen,
-			     struct key *keyring)
+			     struct key *keyring,
+			     struct key *instkey)
 {
 	int ret;
 
 	if (keyring)
 		down_write(&keyring->sem);
 
-	ret = __key_instantiate_and_link(key, data, datalen, keyring);
+	ret = __key_instantiate_and_link(key, data, datalen, keyring, instkey);
 
 	if (keyring)
 		up_write(&keyring->sem);
 
 	return ret;
+
 } /* end key_instantiate_and_link() */
 
 EXPORT_SYMBOL(key_instantiate_and_link);
@@ -469,7 +469,8 @@
  */
 int key_negate_and_link(struct key *key,
 			unsigned timeout,
-			struct key *keyring)
+			struct key *keyring,
+			struct key *instkey)
 {
 	struct timespec now;
 	int ret, awaken;
@@ -486,26 +487,26 @@
 	down_write(&key_construction_sem);
 
 	/* can't instantiate twice */
-	if (!(key->flags & KEY_FLAG_INSTANTIATED)) {
+	if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
 		/* mark the key as being negatively instantiated */
-		write_lock(&key->lock);
-
 		atomic_inc(&key->user->nikeys);
-		key->flags |= KEY_FLAG_INSTANTIATED | KEY_FLAG_NEGATIVE;
+		set_bit(KEY_FLAG_NEGATIVE, &key->flags);
+		set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
 		now = current_kernel_time();
 		key->expiry = now.tv_sec + timeout;
 
-		if (key->flags & KEY_FLAG_USER_CONSTRUCT) {
-			key->flags &= ~KEY_FLAG_USER_CONSTRUCT;
+		if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags))
 			awaken = 1;
-		}
 
-		write_unlock(&key->lock);
 		ret = 0;
 
 		/* and link it into the destination keyring */
 		if (keyring)
 			ret = __key_link(keyring, key);
+
+		/* disable the authorisation key */
+		if (instkey)
+			key_revoke(instkey);
 	}
 
 	up_write(&key_construction_sem);
@@ -553,8 +554,10 @@
 	rb_erase(&key->serial_node, &key_serial_tree);
 	spin_unlock(&key_serial_lock);
 
+	key_check(key);
+
 	/* deal with the user's key tracking and quota */
-	if (key->flags & KEY_FLAG_IN_QUOTA) {
+	if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
 		spin_lock(&key->user->lock);
 		key->user->qnkeys--;
 		key->user->qnbytes -= key->quotalen;
@@ -562,7 +565,7 @@
 	}
 
 	atomic_dec(&key->user->nkeys);
-	if (key->flags & KEY_FLAG_INSTANTIATED)
+	if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
 		atomic_dec(&key->user->nikeys);
 
 	key_user_put(key->user);
@@ -631,9 +634,9 @@
 	goto error;
 
  found:
-	/* pretent doesn't exist if it's dead */
+	/* pretend it doesn't exist if it's dead */
 	if (atomic_read(&key->usage) == 0 ||
-	    (key->flags & KEY_FLAG_DEAD) ||
+	    test_bit(KEY_FLAG_DEAD, &key->flags) ||
 	    key->type == &key_type_dead)
 		goto not_found;
 
@@ -708,12 +711,9 @@
 
 	ret = key->type->update(key, payload, plen);
 
-	if (ret == 0) {
+	if (ret == 0)
 		/* updating a negative key instantiates it */
-		write_lock(&key->lock);
-		key->flags &= ~KEY_FLAG_NEGATIVE;
-		write_unlock(&key->lock);
-	}
+		clear_bit(KEY_FLAG_NEGATIVE, &key->flags);
 
 	up_write(&key->sem);
 
@@ -793,7 +793,7 @@
 	}
 
 	/* instantiate it and link it into the target keyring */
-	ret = __key_instantiate_and_link(key, payload, plen, keyring);
+	ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL);
 	if (ret < 0) {
 		key_put(key);
 		key = ERR_PTR(ret);
@@ -841,12 +841,9 @@
 		down_write(&key->sem);
 		ret = key->type->update(key, payload, plen);
 
-		if (ret == 0) {
+		if (ret == 0)
 			/* updating a negative key instantiates it */
-			write_lock(&key->lock);
-			key->flags &= ~KEY_FLAG_NEGATIVE;
-			write_unlock(&key->lock);
-		}
+			clear_bit(KEY_FLAG_NEGATIVE, &key->flags);
 
 		up_write(&key->sem);
 	}
@@ -892,10 +889,7 @@
 		goto error2;
 
 	atomic_inc(&key->user->nikeys);
-
-	write_lock(&key->lock);
-	key->flags |= KEY_FLAG_INSTANTIATED;
-	write_unlock(&key->lock);
+	set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
 
  error_k:
 	up_read(&key_types_sem);
@@ -922,9 +916,7 @@
 	/* make sure no one's trying to change or use the key when we mark
 	 * it */
 	down_write(&key->sem);
-	write_lock(&key->lock);
-	key->flags |= KEY_FLAG_REVOKED;
-	write_unlock(&key->lock);
+	set_bit(KEY_FLAG_REVOKED, &key->flags);
 	up_write(&key->sem);
 
 } /* end key_revoke() */
@@ -975,24 +967,33 @@
 	/* withdraw the key type */
 	list_del_init(&ktype->link);
 
-	/* need to withdraw all keys of this type */
+	/* mark all the keys of this type dead */
 	spin_lock(&key_serial_lock);
 
 	for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) {
 		key = rb_entry(_n, struct key, serial_node);
 
-		if (key->type != ktype)
-			continue;
+		if (key->type == ktype)
+			key->type = &key_type_dead;
+	}
 
-		write_lock(&key->lock);
-		key->type = &key_type_dead;
-		write_unlock(&key->lock);
+	spin_unlock(&key_serial_lock);
 
-		/* there shouldn't be anyone looking at the description or
-		 * payload now */
-		if (ktype->destroy)
-			ktype->destroy(key);
-		memset(&key->payload, 0xbd, sizeof(key->payload));
+	/* make sure everyone revalidates their keys */
+	synchronize_rcu();
+
+	/* we should now be able to destroy the payloads of all the keys of
+	 * this type with impunity */
+	spin_lock(&key_serial_lock);
+
+	for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) {
+		key = rb_entry(_n, struct key, serial_node);
+
+		if (key->type == ktype) {
+			if (ktype->destroy)
+				ktype->destroy(key);
+			memset(&key->payload, 0xbd, sizeof(key->payload));
+		}
 	}
 
 	spin_unlock(&key_serial_lock);
@@ -1037,4 +1038,5 @@
 
 	/* link the two root keyrings together */
 	key_link(&root_session_keyring, &root_user_keyring);
+
 } /* end key_init() */
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index dc0011b..fea2628 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -1,6 +1,6 @@
 /* keyctl.c: userspace keyctl operations
  *
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
  * Written by David Howells (dhowells@redhat.com)
  *
  * This program is free software; you can redistribute it and/or
@@ -49,6 +49,13 @@
 		goto error;
 	type[31] = '\0';
 
+	if (!type[0])
+		goto error;
+
+	ret = -EPERM;
+	if (type[0] == '.')
+		goto error;
+
 	ret = -EFAULT;
 	dlen = strnlen_user(_description, PAGE_SIZE - 1);
 	if (dlen <= 0)
@@ -82,7 +89,7 @@
 	}
 
 	/* find the target keyring (which must be writable) */
-	keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE);
+	keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
 	if (IS_ERR(keyring)) {
 		ret = PTR_ERR(keyring);
 		goto error3;
@@ -181,7 +188,7 @@
 	/* get the destination keyring if specified */
 	dest = NULL;
 	if (destringid) {
-		dest = lookup_user_key(destringid, 1, 0, KEY_WRITE);
+		dest = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE);
 		if (IS_ERR(dest)) {
 			ret = PTR_ERR(dest);
 			goto error3;
@@ -196,23 +203,15 @@
 	}
 
 	/* do the search */
-	key = request_key(ktype, description, callout_info);
+	key = request_key_and_link(ktype, description, callout_info, dest);
 	if (IS_ERR(key)) {
 		ret = PTR_ERR(key);
 		goto error5;
 	}
 
-	/* link the resulting key to the destination keyring */
-	if (dest) {
-		ret = key_link(dest, key);
-		if (ret < 0)
-			goto error6;
-	}
-
 	ret = key->serial;
 
- error6:
-	key_put(key);
+ 	key_put(key);
  error5:
 	key_type_put(ktype);
  error4:
@@ -237,7 +236,7 @@
 	struct key *key;
 	long ret;
 
-	key = lookup_user_key(id, create, 0, KEY_SEARCH);
+	key = lookup_user_key(NULL, id, create, 0, KEY_SEARCH);
 	if (IS_ERR(key)) {
 		ret = PTR_ERR(key);
 		goto error;
@@ -324,7 +323,7 @@
 	}
 
 	/* find the target key (which must be writable) */
-	key = lookup_user_key(id, 0, 0, KEY_WRITE);
+	key = lookup_user_key(NULL, id, 0, 0, KEY_WRITE);
 	if (IS_ERR(key)) {
 		ret = PTR_ERR(key);
 		goto error2;
@@ -352,7 +351,7 @@
 	struct key *key;
 	long ret;
 
-	key = lookup_user_key(id, 0, 0, KEY_WRITE);
+	key = lookup_user_key(NULL, id, 0, 0, KEY_WRITE);
 	if (IS_ERR(key)) {
 		ret = PTR_ERR(key);
 		goto error;
@@ -378,7 +377,7 @@
 	struct key *keyring;
 	long ret;
 
-	keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE);
+	keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
 	if (IS_ERR(keyring)) {
 		ret = PTR_ERR(keyring);
 		goto error;
@@ -404,13 +403,13 @@
 	struct key *keyring, *key;
 	long ret;
 
-	keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE);
+	keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
 	if (IS_ERR(keyring)) {
 		ret = PTR_ERR(keyring);
 		goto error;
 	}
 
-	key = lookup_user_key(id, 1, 0, KEY_LINK);
+	key = lookup_user_key(NULL, id, 1, 0, KEY_LINK);
 	if (IS_ERR(key)) {
 		ret = PTR_ERR(key);
 		goto error2;
@@ -438,13 +437,13 @@
 	struct key *keyring, *key;
 	long ret;
 
-	keyring = lookup_user_key(ringid, 0, 0, KEY_WRITE);
+	keyring = lookup_user_key(NULL, ringid, 0, 0, KEY_WRITE);
 	if (IS_ERR(keyring)) {
 		ret = PTR_ERR(keyring);
 		goto error;
 	}
 
-	key = lookup_user_key(id, 0, 0, 0);
+	key = lookup_user_key(NULL, id, 0, 0, 0);
 	if (IS_ERR(key)) {
 		ret = PTR_ERR(key);
 		goto error2;
@@ -475,16 +474,29 @@
 			 char __user *buffer,
 			 size_t buflen)
 {
-	struct key *key;
+	struct key *key, *instkey;
 	char *tmpbuf;
 	long ret;
 
-	key = lookup_user_key(keyid, 0, 1, KEY_VIEW);
+	key = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW);
 	if (IS_ERR(key)) {
+		/* viewing a key under construction is permitted if we have the
+		 * authorisation token handy */
+		if (PTR_ERR(key) == -EACCES) {
+			instkey = key_get_instantiation_authkey(keyid);
+			if (!IS_ERR(instkey)) {
+				key_put(instkey);
+				key = lookup_user_key(NULL, keyid, 0, 1, 0);
+				if (!IS_ERR(key))
+					goto okay;
+			}
+		}
+
 		ret = PTR_ERR(key);
 		goto error;
 	}
 
+okay:
 	/* calculate how much description we're going to return */
 	ret = -ENOMEM;
 	tmpbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
@@ -568,7 +580,7 @@
 		goto error2;
 
 	/* get the keyring at which to begin the search */
-	keyring = lookup_user_key(ringid, 0, 0, KEY_SEARCH);
+	keyring = lookup_user_key(NULL, ringid, 0, 0, KEY_SEARCH);
 	if (IS_ERR(keyring)) {
 		ret = PTR_ERR(keyring);
 		goto error2;
@@ -577,7 +589,7 @@
 	/* get the destination keyring if specified */
 	dest = NULL;
 	if (destringid) {
-		dest = lookup_user_key(destringid, 1, 0, KEY_WRITE);
+		dest = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE);
 		if (IS_ERR(dest)) {
 			ret = PTR_ERR(dest);
 			goto error3;
@@ -656,24 +668,23 @@
 	long ret;
 
 	/* find the key first */
-	key = lookup_user_key(keyid, 0, 0, 0);
+	key = lookup_user_key(NULL, keyid, 0, 0, 0);
 	if (!IS_ERR(key)) {
 		/* see if we can read it directly */
 		if (key_permission(key, KEY_READ))
 			goto can_read_key;
 
-		/* can't; see if it's searchable from this process's
-		 * keyrings */
-		ret = -ENOKEY;
-		if (key_permission(key, KEY_SEARCH)) {
-			/* okay - we do have search permission on the key
-			 * itself, but do we have the key? */
-			skey = search_process_keyrings_aux(key->type, key,
-							   keyctl_read_key_same);
-			if (!IS_ERR(skey))
-				goto can_read_key2;
-		}
+		/* we can't; see if it's searchable from this process's
+		 * keyrings
+		 * - we automatically take account of the fact that it may be
+		 *   dangling off an instantiation key
+		 */
+		skey = search_process_keyrings(key->type, key,
+					       keyctl_read_key_same, current);
+		if (!IS_ERR(skey))
+			goto can_read_key2;
 
+		ret = PTR_ERR(skey);
 		goto error2;
 	}
 
@@ -719,7 +730,7 @@
 	if (uid == (uid_t) -1 && gid == (gid_t) -1)
 		goto error;
 
-	key = lookup_user_key(id, 1, 1, 0);
+	key = lookup_user_key(NULL, id, 1, 1, 0);
 	if (IS_ERR(key)) {
 		ret = PTR_ERR(key);
 		goto error;
@@ -728,7 +739,6 @@
 	/* make the changes with the locks held to prevent chown/chown races */
 	ret = -EACCES;
 	down_write(&key->sem);
-	write_lock(&key->lock);
 
 	if (!capable(CAP_SYS_ADMIN)) {
 		/* only the sysadmin can chown a key to some other UID */
@@ -755,7 +765,6 @@
 	ret = 0;
 
  no_access:
-	write_unlock(&key->lock);
 	up_write(&key->sem);
 	key_put(key);
  error:
@@ -778,32 +787,25 @@
 	if (perm & ~(KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL))
 		goto error;
 
-	key = lookup_user_key(id, 1, 1, 0);
+	key = lookup_user_key(NULL, id, 1, 1, 0);
 	if (IS_ERR(key)) {
 		ret = PTR_ERR(key);
 		goto error;
 	}
 
-	/* make the changes with the locks held to prevent chown/chmod
-	 * races */
+	/* make the changes with the locks held to prevent chown/chmod races */
 	ret = -EACCES;
 	down_write(&key->sem);
-	write_lock(&key->lock);
 
-	/* if we're not the sysadmin, we can only chmod a key that we
-	 * own */
-	if (!capable(CAP_SYS_ADMIN) && key->uid != current->fsuid)
-		goto no_access;
+	/* if we're not the sysadmin, we can only change a key that we own */
+	if (capable(CAP_SYS_ADMIN) || key->uid == current->fsuid) {
+		key->perm = perm;
+		ret = 0;
+	}
 
-	/* changing the permissions mask */
-	key->perm = perm;
-	ret = 0;
-
- no_access:
-	write_unlock(&key->lock);
 	up_write(&key->sem);
 	key_put(key);
- error:
+error:
 	return ret;
 
 } /* end keyctl_setperm_key() */
@@ -818,7 +820,8 @@
 			    size_t plen,
 			    key_serial_t ringid)
 {
-	struct key *key, *keyring;
+	struct request_key_auth *rka;
+	struct key *instkey, *keyring;
 	void *payload;
 	long ret;
 
@@ -840,18 +843,21 @@
 			goto error2;
 	}
 
-	/* find the target key (which must be writable) */
-	key = lookup_user_key(id, 0, 1, KEY_WRITE);
-	if (IS_ERR(key)) {
-		ret = PTR_ERR(key);
+	/* find the instantiation authorisation key */
+	instkey = key_get_instantiation_authkey(id);
+	if (IS_ERR(instkey)) {
+		ret = PTR_ERR(instkey);
 		goto error2;
 	}
 
-	/* find the destination keyring if present (which must also be
-	 * writable) */
+	rka = instkey->payload.data;
+
+	/* find the destination keyring amongst those belonging to the
+	 * requesting task */
 	keyring = NULL;
 	if (ringid) {
-		keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE);
+		keyring = lookup_user_key(rka->context, ringid, 1, 0,
+					  KEY_WRITE);
 		if (IS_ERR(keyring)) {
 			ret = PTR_ERR(keyring);
 			goto error3;
@@ -859,11 +865,12 @@
 	}
 
 	/* instantiate the key and link it into a keyring */
-	ret = key_instantiate_and_link(key, payload, plen, keyring);
+	ret = key_instantiate_and_link(rka->target_key, payload, plen,
+				       keyring, instkey);
 
 	key_put(keyring);
  error3:
-	key_put(key);
+	key_put(instkey);
  error2:
 	kfree(payload);
  error:
@@ -878,21 +885,24 @@
  */
 long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
 {
-	struct key *key, *keyring;
+	struct request_key_auth *rka;
+	struct key *instkey, *keyring;
 	long ret;
 
-	/* find the target key (which must be writable) */
-	key = lookup_user_key(id, 0, 1, KEY_WRITE);
-	if (IS_ERR(key)) {
-		ret = PTR_ERR(key);
+	/* find the instantiation authorisation key */
+	instkey = key_get_instantiation_authkey(id);
+	if (IS_ERR(instkey)) {
+		ret = PTR_ERR(instkey);
 		goto error;
 	}
 
+	rka = instkey->payload.data;
+
 	/* find the destination keyring if present (which must also be
 	 * writable) */
 	keyring = NULL;
 	if (ringid) {
-		keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE);
+		keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
 		if (IS_ERR(keyring)) {
 			ret = PTR_ERR(keyring);
 			goto error2;
@@ -900,11 +910,11 @@
 	}
 
 	/* instantiate the key and link it into a keyring */
-	ret = key_negate_and_link(key, timeout, keyring);
+	ret = key_negate_and_link(rka->target_key, timeout, keyring, instkey);
 
 	key_put(keyring);
  error2:
-	key_put(key);
+	key_put(instkey);
  error:
 	return ret;
 
@@ -912,6 +922,44 @@
 
 /*****************************************************************************/
 /*
+ * set the default keyring in which request_key() will cache keys
+ * - return the old setting
+ */
+long keyctl_set_reqkey_keyring(int reqkey_defl)
+{
+	int ret;
+
+	switch (reqkey_defl) {
+	case KEY_REQKEY_DEFL_THREAD_KEYRING:
+		ret = install_thread_keyring(current);
+		if (ret < 0)
+			return ret;
+		goto set;
+
+	case KEY_REQKEY_DEFL_PROCESS_KEYRING:
+		ret = install_process_keyring(current);
+		if (ret < 0)
+			return ret;
+
+	case KEY_REQKEY_DEFL_DEFAULT:
+	case KEY_REQKEY_DEFL_SESSION_KEYRING:
+	case KEY_REQKEY_DEFL_USER_KEYRING:
+	case KEY_REQKEY_DEFL_USER_SESSION_KEYRING:
+	set:
+		current->jit_keyring = reqkey_defl;
+
+	case KEY_REQKEY_DEFL_NO_CHANGE:
+		return current->jit_keyring;
+
+	case KEY_REQKEY_DEFL_GROUP_KEYRING:
+	default:
+		return -EINVAL;
+	}
+
+} /* end keyctl_set_reqkey_keyring() */
+
+/*****************************************************************************/
+/*
  * the key control system call
  */
 asmlinkage long sys_keyctl(int option, unsigned long arg2, unsigned long arg3,
@@ -980,6 +1028,9 @@
 					 (unsigned) arg3,
 					 (key_serial_t) arg4);
 
+	case KEYCTL_SET_REQKEY_KEYRING:
+		return keyctl_set_reqkey_keyring(arg2);
+
 	default:
 		return -EOPNOTSUPP;
 	}
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index e2ab4f8..90a551e 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -1,6 +1,6 @@
 /* keyring.c: keyring handling
  *
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
  * Written by David Howells (dhowells@redhat.com)
  *
  * This program is free software; you can redistribute it and/or
@@ -132,10 +132,17 @@
 		(PAGE_SIZE - sizeof(*klist)) / sizeof(struct key);
 
 	ret = 0;
-	sklist = source->payload.subscriptions;
 
-	if (sklist && sklist->nkeys > 0) {
+	/* find out how many keys are currently linked */
+	rcu_read_lock();
+	sklist = rcu_dereference(source->payload.subscriptions);
+	max = 0;
+	if (sklist)
 		max = sklist->nkeys;
+	rcu_read_unlock();
+
+	/* allocate a new payload and stuff load with key links */
+	if (max > 0) {
 		BUG_ON(max > limit);
 
 		max = (max + 3) & ~3;
@@ -148,6 +155,10 @@
 		if (!klist)
 			goto error;
 
+		/* set links */
+		rcu_read_lock();
+		sklist = rcu_dereference(source->payload.subscriptions);
+
 		klist->maxkeys = max;
 		klist->nkeys = sklist->nkeys;
 		memcpy(klist->keys,
@@ -157,7 +168,9 @@
 		for (loop = klist->nkeys - 1; loop >= 0; loop--)
 			atomic_inc(&klist->keys[loop]->usage);
 
-		keyring->payload.subscriptions = klist;
+		rcu_read_unlock();
+
+		rcu_assign_pointer(keyring->payload.subscriptions, klist);
 		ret = 0;
 	}
 
@@ -192,7 +205,7 @@
 		write_unlock(&keyring_name_lock);
 	}
 
-	klist = keyring->payload.subscriptions;
+	klist = rcu_dereference(keyring->payload.subscriptions);
 	if (klist) {
 		for (loop = klist->nkeys - 1; loop >= 0; loop--)
 			key_put(klist->keys[loop]);
@@ -216,17 +229,20 @@
 		seq_puts(m, "[anon]");
 	}
 
-	klist = keyring->payload.subscriptions;
+	rcu_read_lock();
+	klist = rcu_dereference(keyring->payload.subscriptions);
 	if (klist)
 		seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys);
 	else
 		seq_puts(m, ": empty");
+	rcu_read_unlock();
 
 } /* end keyring_describe() */
 
 /*****************************************************************************/
 /*
  * read a list of key IDs from the keyring's contents
+ * - the keyring's semaphore is read-locked
  */
 static long keyring_read(const struct key *keyring,
 			 char __user *buffer, size_t buflen)
@@ -237,7 +253,7 @@
 	int loop, ret;
 
 	ret = 0;
-	klist = keyring->payload.subscriptions;
+	klist = rcu_dereference(keyring->payload.subscriptions);
 
 	if (klist) {
 		/* calculate how much data we could return */
@@ -292,7 +308,7 @@
 			    uid, gid, KEY_USR_ALL, not_in_quota);
 
 	if (!IS_ERR(keyring)) {
-		ret = key_instantiate_and_link(keyring, NULL, 0, dest);
+		ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL);
 		if (ret < 0) {
 			key_put(keyring);
 			keyring = ERR_PTR(ret);
@@ -310,17 +326,18 @@
  * - we only find keys on which we have search permission
  * - we use the supplied match function to see if the description (or other
  *   feature of interest) matches
- * - we readlock the keyrings as we search down the tree
+ * - we rely on RCU to prevent the keyring lists from disappearing on us
  * - we return -EAGAIN if we didn't find any matching key
  * - we return -ENOKEY if we only found negative matching keys
  */
 struct key *keyring_search_aux(struct key *keyring,
+			       struct task_struct *context,
 			       struct key_type *type,
 			       const void *description,
 			       key_match_func_t match)
 {
 	struct {
-		struct key *keyring;
+		struct keyring_list *keylist;
 		int kix;
 	} stack[KEYRING_SEARCH_MAX_DEPTH];
 
@@ -328,13 +345,15 @@
 	struct timespec now;
 	struct key *key;
 	long err;
-	int sp, psp, kix;
+	int sp, kix;
 
 	key_check(keyring);
 
+	rcu_read_lock();
+
 	/* top keyring must have search permission to begin the search */
 	key = ERR_PTR(-EACCES);
-	if (!key_permission(keyring, KEY_SEARCH))
+	if (!key_task_permission(keyring, context, KEY_SEARCH))
 		goto error;
 
 	key = ERR_PTR(-ENOTDIR);
@@ -347,11 +366,10 @@
 
 	/* start processing a new keyring */
  descend:
-	read_lock(&keyring->lock);
-	if (keyring->flags & KEY_FLAG_REVOKED)
+	if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
 		goto not_this_keyring;
 
-	keylist = keyring->payload.subscriptions;
+	keylist = rcu_dereference(keyring->payload.subscriptions);
 	if (!keylist)
 		goto not_this_keyring;
 
@@ -364,7 +382,7 @@
 			continue;
 
 		/* skip revoked keys and expired keys */
-		if (key->flags & KEY_FLAG_REVOKED)
+		if (test_bit(KEY_FLAG_REVOKED, &key->flags))
 			continue;
 
 		if (key->expiry && now.tv_sec >= key->expiry)
@@ -375,11 +393,11 @@
 			continue;
 
 		/* key must have search permissions */
-		if (!key_permission(key, KEY_SEARCH))
+		if (!key_task_permission(key, context, KEY_SEARCH))
 			continue;
 
 		/* we set a different error code if we find a negative key */
-		if (key->flags & KEY_FLAG_NEGATIVE) {
+		if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
 			err = -ENOKEY;
 			continue;
 		}
@@ -390,48 +408,37 @@
 	/* search through the keyrings nested in this one */
 	kix = 0;
  ascend:
-	while (kix < keylist->nkeys) {
+	for (; kix < keylist->nkeys; kix++) {
 		key = keylist->keys[kix];
 		if (key->type != &key_type_keyring)
-			goto next;
+			continue;
 
 		/* recursively search nested keyrings
 		 * - only search keyrings for which we have search permission
 		 */
 		if (sp >= KEYRING_SEARCH_MAX_DEPTH)
-			goto next;
+			continue;
 
-		if (!key_permission(key, KEY_SEARCH))
-			goto next;
-
-		/* evade loops in the keyring tree */
-		for (psp = 0; psp < sp; psp++)
-			if (stack[psp].keyring == keyring)
-				goto next;
+		if (!key_task_permission(key, context, KEY_SEARCH))
+			continue;
 
 		/* stack the current position */
-		stack[sp].keyring = keyring;
+		stack[sp].keylist = keylist;
 		stack[sp].kix = kix;
 		sp++;
 
 		/* begin again with the new keyring */
 		keyring = key;
 		goto descend;
-
-	next:
-		kix++;
 	}
 
 	/* the keyring we're looking at was disqualified or didn't contain a
 	 * matching key */
  not_this_keyring:
-	read_unlock(&keyring->lock);
-
 	if (sp > 0) {
 		/* resume the processing of a keyring higher up in the tree */
 		sp--;
-		keyring = stack[sp].keyring;
-		keylist = keyring->payload.subscriptions;
+		keylist = stack[sp].keylist;
 		kix = stack[sp].kix + 1;
 		goto ascend;
 	}
@@ -442,16 +449,9 @@
 	/* we found a viable match */
  found:
 	atomic_inc(&key->usage);
-	read_unlock(&keyring->lock);
-
-	/* unwind the keyring stack */
-	while (sp > 0) {
-		sp--;
-		read_unlock(&stack[sp].keyring->lock);
-	}
-
 	key_check(key);
  error:
+	rcu_read_unlock();
 	return key;
 
 } /* end keyring_search_aux() */
@@ -469,7 +469,11 @@
 			   struct key_type *type,
 			   const char *description)
 {
-	return keyring_search_aux(keyring, type, description, type->match);
+	if (!type->match)
+		return ERR_PTR(-ENOKEY);
+
+	return keyring_search_aux(keyring, current,
+				  type, description, type->match);
 
 } /* end keyring_search() */
 
@@ -489,15 +493,18 @@
 	struct key *key;
 	int loop;
 
-	klist = keyring->payload.subscriptions;
+	rcu_read_lock();
+
+	klist = rcu_dereference(keyring->payload.subscriptions);
 	if (klist) {
 		for (loop = 0; loop < klist->nkeys; loop++) {
 			key = klist->keys[loop];
 
 			if (key->type == ktype &&
-			    key->type->match(key, description) &&
+			    (!key->type->match ||
+			     key->type->match(key, description)) &&
 			    key_permission(key, perm) &&
-			    !(key->flags & KEY_FLAG_REVOKED)
+			    !test_bit(KEY_FLAG_REVOKED, &key->flags)
 			    )
 				goto found;
 		}
@@ -509,12 +516,58 @@
  found:
 	atomic_inc(&key->usage);
  error:
+	rcu_read_unlock();
 	return key;
 
 } /* end __keyring_search_one() */
 
 /*****************************************************************************/
 /*
+ * search for an instantiation authorisation key matching a target key
+ * - the RCU read lock must be held by the caller
+ * - a target_id of zero specifies any valid token
+ */
+struct key *keyring_search_instkey(struct key *keyring,
+				   key_serial_t target_id)
+{
+	struct request_key_auth *rka;
+	struct keyring_list *klist;
+	struct key *instkey;
+	int loop;
+
+	klist = rcu_dereference(keyring->payload.subscriptions);
+	if (klist) {
+		for (loop = 0; loop < klist->nkeys; loop++) {
+			instkey = klist->keys[loop];
+
+			if (instkey->type != &key_type_request_key_auth)
+				continue;
+
+			rka = instkey->payload.data;
+			if (target_id && rka->target_key->serial != target_id)
+				continue;
+
+			/* the auth key is revoked during instantiation */
+			if (!test_bit(KEY_FLAG_REVOKED, &instkey->flags))
+				goto found;
+
+			instkey = ERR_PTR(-EKEYREVOKED);
+			goto error;
+		}
+	}
+
+	instkey = ERR_PTR(-EACCES);
+	goto error;
+
+found:
+	atomic_inc(&instkey->usage);
+error:
+	return instkey;
+
+} /* end keyring_search_instkey() */
+
+/*****************************************************************************/
+/*
  * find a keyring with the specified name
  * - all named keyrings are searched
  * - only find keyrings with search permission for the process
@@ -540,7 +593,7 @@
 				    &keyring_name_hash[bucket],
 				    type_data.link
 				    ) {
-			if (keyring->flags & KEY_FLAG_REVOKED)
+			if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
 				continue;
 
 			if (strcmp(keyring->description, name) != 0)
@@ -579,7 +632,7 @@
 static int keyring_detect_cycle(struct key *A, struct key *B)
 {
 	struct {
-		struct key *subtree;
+		struct keyring_list *keylist;
 		int kix;
 	} stack[KEYRING_SEARCH_MAX_DEPTH];
 
@@ -587,20 +640,21 @@
 	struct key *subtree, *key;
 	int sp, kix, ret;
 
+	rcu_read_lock();
+
 	ret = -EDEADLK;
 	if (A == B)
-		goto error;
+		goto cycle_detected;
 
 	subtree = B;
 	sp = 0;
 
 	/* start processing a new keyring */
  descend:
-	read_lock(&subtree->lock);
-	if (subtree->flags & KEY_FLAG_REVOKED)
+	if (test_bit(KEY_FLAG_REVOKED, &subtree->flags))
 		goto not_this_keyring;
 
-	keylist = subtree->payload.subscriptions;
+	keylist = rcu_dereference(subtree->payload.subscriptions);
 	if (!keylist)
 		goto not_this_keyring;
 	kix = 0;
@@ -619,7 +673,7 @@
 				goto too_deep;
 
 			/* stack the current position */
-			stack[sp].subtree = subtree;
+			stack[sp].keylist = keylist;
 			stack[sp].kix = kix;
 			sp++;
 
@@ -632,13 +686,10 @@
 	/* the keyring we're looking at was disqualified or didn't contain a
 	 * matching key */
  not_this_keyring:
-	read_unlock(&subtree->lock);
-
 	if (sp > 0) {
 		/* resume the checking of a keyring higher up in the tree */
 		sp--;
-		subtree = stack[sp].subtree;
-		keylist = subtree->payload.subscriptions;
+		keylist = stack[sp].keylist;
 		kix = stack[sp].kix + 1;
 		goto ascend;
 	}
@@ -646,30 +697,36 @@
 	ret = 0; /* no cycles detected */
 
  error:
+	rcu_read_unlock();
 	return ret;
 
  too_deep:
 	ret = -ELOOP;
-	goto error_unwind;
+	goto error;
+
  cycle_detected:
 	ret = -EDEADLK;
- error_unwind:
-	read_unlock(&subtree->lock);
-
-	/* unwind the keyring stack */
-	while (sp > 0) {
-		sp--;
-		read_unlock(&stack[sp].subtree->lock);
-	}
-
 	goto error;
 
 } /* end keyring_detect_cycle() */
 
 /*****************************************************************************/
 /*
+ * dispose of a keyring list after the RCU grace period
+ */
+static void keyring_link_rcu_disposal(struct rcu_head *rcu)
+{
+	struct keyring_list *klist =
+		container_of(rcu, struct keyring_list, rcu);
+
+	kfree(klist);
+
+} /* end keyring_link_rcu_disposal() */
+
+/*****************************************************************************/
+/*
  * link a key into to a keyring
- * - must be called with the keyring's semaphore held
+ * - must be called with the keyring's semaphore write-locked
  */
 int __key_link(struct key *keyring, struct key *key)
 {
@@ -679,7 +736,7 @@
 	int ret;
 
 	ret = -EKEYREVOKED;
-	if (keyring->flags & KEY_FLAG_REVOKED)
+	if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))
 		goto error;
 
 	ret = -ENOTDIR;
@@ -710,9 +767,10 @@
 		/* there's sufficient slack space to add directly */
 		atomic_inc(&key->usage);
 
-		write_lock(&keyring->lock);
-		klist->keys[klist->nkeys++] = key;
-		write_unlock(&keyring->lock);
+		klist->keys[klist->nkeys] = key;
+		smp_wmb();
+		klist->nkeys++;
+		smp_wmb();
 
 		ret = 0;
 	}
@@ -723,6 +781,8 @@
 			max += klist->maxkeys;
 
 		ret = -ENFILE;
+		if (max > 65535)
+			goto error3;
 		size = sizeof(*klist) + sizeof(*key) * max;
 		if (size > PAGE_SIZE)
 			goto error3;
@@ -743,14 +803,13 @@
 
 		/* add the key into the new space */
 		atomic_inc(&key->usage);
-
-		write_lock(&keyring->lock);
-		keyring->payload.subscriptions = nklist;
 		nklist->keys[nklist->nkeys++] = key;
-		write_unlock(&keyring->lock);
+
+		rcu_assign_pointer(keyring->payload.subscriptions, nklist);
 
 		/* dispose of the old keyring list */
-		kfree(klist);
+		if (klist)
+			call_rcu(&klist->rcu, keyring_link_rcu_disposal);
 
 		ret = 0;
 	}
@@ -791,11 +850,26 @@
 
 /*****************************************************************************/
 /*
+ * dispose of a keyring list after the RCU grace period, freeing the unlinked
+ * key
+ */
+static void keyring_unlink_rcu_disposal(struct rcu_head *rcu)
+{
+	struct keyring_list *klist =
+		container_of(rcu, struct keyring_list, rcu);
+
+	key_put(klist->keys[klist->delkey]);
+	kfree(klist);
+
+} /* end keyring_unlink_rcu_disposal() */
+
+/*****************************************************************************/
+/*
  * unlink the first link to a key from a keyring
  */
 int key_unlink(struct key *keyring, struct key *key)
 {
-	struct keyring_list *klist;
+	struct keyring_list *klist, *nklist;
 	int loop, ret;
 
 	key_check(keyring);
@@ -819,31 +893,45 @@
 	ret = -ENOENT;
 	goto error;
 
- key_is_present:
+key_is_present:
+	/* we need to copy the key list for RCU purposes */
+	nklist = kmalloc(sizeof(*klist) + sizeof(*key) * klist->maxkeys,
+			 GFP_KERNEL);
+	if (!nklist)
+		goto nomem;
+	nklist->maxkeys = klist->maxkeys;
+	nklist->nkeys = klist->nkeys - 1;
+
+	if (loop > 0)
+		memcpy(&nklist->keys[0],
+		       &klist->keys[0],
+		       loop * sizeof(klist->keys[0]));
+
+	if (loop < nklist->nkeys)
+		memcpy(&nklist->keys[loop],
+		       &klist->keys[loop + 1],
+		       (nklist->nkeys - loop) * sizeof(klist->keys[0]));
+
 	/* adjust the user's quota */
 	key_payload_reserve(keyring,
 			    keyring->datalen - KEYQUOTA_LINK_BYTES);
 
-	/* shuffle down the key pointers
-	 * - it might be worth shrinking the allocated memory, but that runs
-	 *   the risk of ENOMEM as we would have to copy
-	 */
-	write_lock(&keyring->lock);
-
-	klist->nkeys--;
-	if (loop < klist->nkeys)
-		memcpy(&klist->keys[loop],
-		       &klist->keys[loop + 1],
-		       (klist->nkeys - loop) * sizeof(struct key *));
-
-	write_unlock(&keyring->lock);
+	rcu_assign_pointer(keyring->payload.subscriptions, nklist);
 
 	up_write(&keyring->sem);
-	key_put(key);
+
+	/* schedule for later cleanup */
+	klist->delkey = loop;
+	call_rcu(&klist->rcu, keyring_unlink_rcu_disposal);
+
 	ret = 0;
 
- error:
+error:
 	return ret;
+nomem:
+	ret = -ENOMEM;
+	up_write(&keyring->sem);
+	goto error;
 
 } /* end key_unlink() */
 
@@ -851,13 +939,32 @@
 
 /*****************************************************************************/
 /*
+ * dispose of a keyring list after the RCU grace period, releasing the keys it
+ * links to
+ */
+static void keyring_clear_rcu_disposal(struct rcu_head *rcu)
+{
+	struct keyring_list *klist;
+	int loop;
+
+	klist = container_of(rcu, struct keyring_list, rcu);
+
+	for (loop = klist->nkeys - 1; loop >= 0; loop--)
+		key_put(klist->keys[loop]);
+
+	kfree(klist);
+
+} /* end keyring_clear_rcu_disposal() */
+
+/*****************************************************************************/
+/*
  * clear the specified process keyring
  * - implements keyctl(KEYCTL_CLEAR)
  */
 int keyring_clear(struct key *keyring)
 {
 	struct keyring_list *klist;
-	int loop, ret;
+	int ret;
 
 	ret = -ENOTDIR;
 	if (keyring->type == &key_type_keyring) {
@@ -870,20 +977,15 @@
 			key_payload_reserve(keyring,
 					    sizeof(struct keyring_list));
 
-			write_lock(&keyring->lock);
-			keyring->payload.subscriptions = NULL;
-			write_unlock(&keyring->lock);
+			rcu_assign_pointer(keyring->payload.subscriptions,
+					   NULL);
 		}
 
 		up_write(&keyring->sem);
 
 		/* free the keys after the locks have been dropped */
-		if (klist) {
-			for (loop = klist->nkeys - 1; loop >= 0; loop--)
-				key_put(klist->keys[loop]);
-
-			kfree(klist);
-		}
+		if (klist)
+			call_rcu(&klist->rcu, keyring_clear_rcu_disposal);
 
 		ret = 0;
 	}
diff --git a/security/keys/proc.c b/security/keys/proc.c
index 91343b8..c55cf1f 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -140,7 +140,7 @@
 
 	now = current_kernel_time();
 
-	read_lock(&key->lock);
+	rcu_read_lock();
 
 	/* come up with a suitable timeout value */
 	if (key->expiry == 0) {
@@ -164,14 +164,17 @@
 			sprintf(xbuf, "%luw", timo / (60*60*24*7));
 	}
 
+#define showflag(KEY, LETTER, FLAG) \
+	(test_bit(FLAG,	&(KEY)->flags) ? LETTER : '-')
+
 	seq_printf(m, "%08x %c%c%c%c%c%c %5d %4s %06x %5d %5d %-9.9s ",
 		   key->serial,
-		   key->flags & KEY_FLAG_INSTANTIATED	? 'I' : '-',
-		   key->flags & KEY_FLAG_REVOKED	? 'R' : '-',
-		   key->flags & KEY_FLAG_DEAD		? 'D' : '-',
-		   key->flags & KEY_FLAG_IN_QUOTA	? 'Q' : '-',
-		   key->flags & KEY_FLAG_USER_CONSTRUCT	? 'U' : '-',
-		   key->flags & KEY_FLAG_NEGATIVE	? 'N' : '-',
+		   showflag(key, 'I', KEY_FLAG_INSTANTIATED),
+		   showflag(key, 'R', KEY_FLAG_REVOKED),
+		   showflag(key, 'D', KEY_FLAG_DEAD),
+		   showflag(key, 'Q', KEY_FLAG_IN_QUOTA),
+		   showflag(key, 'U', KEY_FLAG_USER_CONSTRUCT),
+		   showflag(key, 'N', KEY_FLAG_NEGATIVE),
 		   atomic_read(&key->usage),
 		   xbuf,
 		   key->perm,
@@ -179,11 +182,13 @@
 		   key->gid,
 		   key->type->name);
 
+#undef showflag
+
 	if (key->type->describe)
 		key->type->describe(key, m);
 	seq_putc(m, '\n');
 
-	read_unlock(&key->lock);
+	rcu_read_unlock();
 
 	return 0;
 
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 2eb0e47..9b0369c 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -1,6 +1,6 @@
 /* process_keys.c: management of a process's keyrings
  *
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
  * Written by David Howells (dhowells@redhat.com)
  *
  * This program is free software; you can redistribute it and/or
@@ -38,10 +38,9 @@
 	.serial		= 2,
 	.type		= &key_type_keyring,
 	.user		= &root_key_user,
-	.lock		= RW_LOCK_UNLOCKED,
 	.sem		= __RWSEM_INITIALIZER(root_user_keyring.sem),
 	.perm		= KEY_USR_ALL,
-	.flags		= KEY_FLAG_INSTANTIATED,
+	.flags		= 1 << KEY_FLAG_INSTANTIATED,
 	.description	= "_uid.0",
 #ifdef KEY_DEBUGGING
 	.magic		= KEY_DEBUG_MAGIC,
@@ -54,10 +53,9 @@
 	.serial		= 1,
 	.type		= &key_type_keyring,
 	.user		= &root_key_user,
-	.lock		= RW_LOCK_UNLOCKED,
 	.sem		= __RWSEM_INITIALIZER(root_session_keyring.sem),
 	.perm		= KEY_USR_ALL,
-	.flags		= KEY_FLAG_INSTANTIATED,
+	.flags		= 1 << KEY_FLAG_INSTANTIATED,
 	.description	= "_uid_ses.0",
 #ifdef KEY_DEBUGGING
 	.magic		= KEY_DEBUG_MAGIC,
@@ -167,7 +165,7 @@
 /*
  * make sure a process keyring is installed
  */
-static int install_process_keyring(struct task_struct *tsk)
+int install_process_keyring(struct task_struct *tsk)
 {
 	unsigned long flags;
 	struct key *keyring;
@@ -183,7 +181,7 @@
 			goto error;
 		}
 
-		/* attach or swap keyrings */
+		/* attach keyring */
 		spin_lock_irqsave(&tsk->sighand->siglock, flags);
 		if (!tsk->signal->process_keyring) {
 			tsk->signal->process_keyring = keyring;
@@ -229,12 +227,14 @@
 
 	/* install the keyring */
 	spin_lock_irqsave(&tsk->sighand->siglock, flags);
-	old = tsk->signal->session_keyring;
-	tsk->signal->session_keyring = keyring;
+	old = rcu_dereference(tsk->signal->session_keyring);
+	rcu_assign_pointer(tsk->signal->session_keyring, keyring);
 	spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
 
 	ret = 0;
 
+	/* we're using RCU on the pointer */
+	synchronize_rcu();
 	key_put(old);
  error:
 	return ret;
@@ -247,8 +247,6 @@
  */
 int copy_thread_group_keys(struct task_struct *tsk)
 {
-	unsigned long flags;
-
 	key_check(current->thread_group->session_keyring);
 	key_check(current->thread_group->process_keyring);
 
@@ -256,10 +254,10 @@
 	tsk->signal->process_keyring = NULL;
 
 	/* same session keyring */
-	spin_lock_irqsave(&current->sighand->siglock, flags);
+	rcu_read_lock();
 	tsk->signal->session_keyring =
-		key_get(current->signal->session_keyring);
-	spin_unlock_irqrestore(&current->sighand->siglock, flags);
+		key_get(rcu_dereference(current->signal->session_keyring));
+	rcu_read_unlock();
 
 	return 0;
 
@@ -349,9 +347,7 @@
 	/* update the ownership of the thread keyring */
 	if (tsk->thread_keyring) {
 		down_write(&tsk->thread_keyring->sem);
-		write_lock(&tsk->thread_keyring->lock);
 		tsk->thread_keyring->uid = tsk->fsuid;
-		write_unlock(&tsk->thread_keyring->lock);
 		up_write(&tsk->thread_keyring->sem);
 	}
 
@@ -366,9 +362,7 @@
 	/* update the ownership of the thread keyring */
 	if (tsk->thread_keyring) {
 		down_write(&tsk->thread_keyring->sem);
-		write_lock(&tsk->thread_keyring->lock);
 		tsk->thread_keyring->gid = tsk->fsgid;
-		write_unlock(&tsk->thread_keyring->lock);
 		up_write(&tsk->thread_keyring->sem);
 	}
 
@@ -382,13 +376,13 @@
  * - we return -EAGAIN if we didn't find any matching key
  * - we return -ENOKEY if we found only negative matching keys
  */
-struct key *search_process_keyrings_aux(struct key_type *type,
-					const void *description,
-					key_match_func_t match)
+struct key *search_process_keyrings(struct key_type *type,
+				    const void *description,
+				    key_match_func_t match,
+				    struct task_struct *context)
 {
-	struct task_struct *tsk = current;
-	unsigned long flags;
-	struct key *key, *ret, *err, *tmp;
+	struct request_key_auth *rka;
+	struct key *key, *ret, *err, *instkey;
 
 	/* 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;
@@ -402,9 +396,9 @@
 	err = ERR_PTR(-EAGAIN);
 
 	/* search the thread keyring first */
-	if (tsk->thread_keyring) {
-		key = keyring_search_aux(tsk->thread_keyring, type,
-					 description, match);
+	if (context->thread_keyring) {
+		key = keyring_search_aux(context->thread_keyring,
+					 context, type, description, match);
 		if (!IS_ERR(key))
 			goto found;
 
@@ -422,9 +416,9 @@
 	}
 
 	/* search the process keyring second */
-	if (tsk->signal->process_keyring) {
-		key = keyring_search_aux(tsk->signal->process_keyring,
-					 type, description, match);
+	if (context->signal->process_keyring) {
+		key = keyring_search_aux(context->signal->process_keyring,
+					 context, type, description, match);
 		if (!IS_ERR(key))
 			goto found;
 
@@ -441,52 +435,93 @@
 		}
 	}
 
-	/* search the session keyring last */
-	spin_lock_irqsave(&tsk->sighand->siglock, flags);
+	/* search the session keyring */
+	if (context->signal->session_keyring) {
+		rcu_read_lock();
+		key = keyring_search_aux(
+			rcu_dereference(context->signal->session_keyring),
+			context, type, description, match);
+		rcu_read_unlock();
 
-	tmp = tsk->signal->session_keyring;
-	if (!tmp)
-		tmp = tsk->user->session_keyring;
-	atomic_inc(&tmp->usage);
+		if (!IS_ERR(key))
+			goto found;
 
-	spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
-
-	key = keyring_search_aux(tmp, type, description, match);
-	key_put(tmp);
-	if (!IS_ERR(key))
-		goto found;
-
-	switch (PTR_ERR(key)) {
-	case -EAGAIN: /* no key */
-		if (ret)
+		switch (PTR_ERR(key)) {
+		case -EAGAIN: /* no key */
+			if (ret)
+				break;
+		case -ENOKEY: /* negative key */
+			ret = key;
 			break;
-	case -ENOKEY: /* negative key */
-		ret = key;
-		break;
-	default:
-		err = key;
-		break;
+		default:
+			err = key;
+			break;
+		}
+
+		/* if this process has a session keyring and that has an
+		 * instantiation authorisation key in the bottom level, then we
+		 * also search the keyrings of the process mentioned there */
+		if (context != current)
+			goto no_key;
+
+		rcu_read_lock();
+		instkey = __keyring_search_one(
+			rcu_dereference(context->signal->session_keyring),
+			&key_type_request_key_auth, NULL, 0);
+		rcu_read_unlock();
+
+		if (IS_ERR(instkey))
+			goto no_key;
+
+		rka = instkey->payload.data;
+
+		key = search_process_keyrings(type, description, match,
+					      rka->context);
+		key_put(instkey);
+
+		if (!IS_ERR(key))
+			goto found;
+
+		switch (PTR_ERR(key)) {
+		case -EAGAIN: /* no key */
+			if (ret)
+				break;
+		case -ENOKEY: /* negative key */
+			ret = key;
+			break;
+		default:
+			err = key;
+			break;
+		}
+	}
+	/* or search the user-session keyring */
+	else {
+		key = keyring_search_aux(context->user->session_keyring,
+					 context, type, description, match);
+		if (!IS_ERR(key))
+			goto found;
+
+		switch (PTR_ERR(key)) {
+		case -EAGAIN: /* no key */
+			if (ret)
+				break;
+		case -ENOKEY: /* negative key */
+			ret = key;
+			break;
+		default:
+			err = key;
+			break;
+		}
 	}
 
+
+no_key:
 	/* no key - decide on the error we're going to go for */
 	key = ret ? ret : err;
 
- found:
+found:
 	return key;
 
-} /* end search_process_keyrings_aux() */
-
-/*****************************************************************************/
-/*
- * search the process keyrings for the first matching key
- * - we return -EAGAIN if we didn't find any matching key
- * - we return -ENOKEY if we found only negative matching keys
- */
-struct key *search_process_keyrings(struct key_type *type,
-				    const char *description)
-{
-	return search_process_keyrings_aux(type, description, type->match);
-
 } /* end search_process_keyrings() */
 
 /*****************************************************************************/
@@ -495,72 +530,73 @@
  * - don't create special keyrings unless so requested
  * - partially constructed keys aren't found unless requested
  */
-struct key *lookup_user_key(key_serial_t id, int create, int partial,
-			    key_perm_t perm)
+struct key *lookup_user_key(struct task_struct *context, key_serial_t id,
+			    int create, int partial, key_perm_t perm)
 {
-	struct task_struct *tsk = current;
-	unsigned long flags;
 	struct key *key;
 	int ret;
 
+	if (!context)
+		context = current;
+
 	key = ERR_PTR(-ENOKEY);
 
 	switch (id) {
 	case KEY_SPEC_THREAD_KEYRING:
-		if (!tsk->thread_keyring) {
+		if (!context->thread_keyring) {
 			if (!create)
 				goto error;
 
-			ret = install_thread_keyring(tsk);
+			ret = install_thread_keyring(context);
 			if (ret < 0) {
 				key = ERR_PTR(ret);
 				goto error;
 			}
 		}
 
-		key = tsk->thread_keyring;
+		key = context->thread_keyring;
 		atomic_inc(&key->usage);
 		break;
 
 	case KEY_SPEC_PROCESS_KEYRING:
-		if (!tsk->signal->process_keyring) {
+		if (!context->signal->process_keyring) {
 			if (!create)
 				goto error;
 
-			ret = install_process_keyring(tsk);
+			ret = install_process_keyring(context);
 			if (ret < 0) {
 				key = ERR_PTR(ret);
 				goto error;
 			}
 		}
 
-		key = tsk->signal->process_keyring;
+		key = context->signal->process_keyring;
 		atomic_inc(&key->usage);
 		break;
 
 	case KEY_SPEC_SESSION_KEYRING:
-		if (!tsk->signal->session_keyring) {
+		if (!context->signal->session_keyring) {
 			/* always install a session keyring upon access if one
 			 * doesn't exist yet */
 			ret = install_session_keyring(
-			       tsk, tsk->user->session_keyring);
+			       context, context->user->session_keyring);
 			if (ret < 0)
 				goto error;
 		}
 
-		spin_lock_irqsave(&tsk->sighand->siglock, flags);
-		key = tsk->signal->session_keyring;
+		rcu_read_lock();
+		key = rcu_dereference(context->signal->session_keyring);
 		atomic_inc(&key->usage);
-		spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+		rcu_read_unlock();
 		break;
 
 	case KEY_SPEC_USER_KEYRING:
-		key = tsk->user->uid_keyring;
+		key = context->user->uid_keyring;
 		atomic_inc(&key->usage);
 		break;
 
 	case KEY_SPEC_USER_SESSION_KEYRING:
-		key = tsk->user->session_keyring;
+		key = context->user->session_keyring;
 		atomic_inc(&key->usage);
 		break;
 
@@ -580,7 +616,7 @@
 		break;
 	}
 
-	/* check the status and permissions */
+	/* check the status */
 	if (perm) {
 		ret = key_validate(key);
 		if (ret < 0)
@@ -588,11 +624,13 @@
 	}
 
 	ret = -EIO;
-	if (!partial && !(key->flags & KEY_FLAG_INSTANTIATED))
+	if (!partial && !test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
 		goto invalid_key;
 
+	/* check the permissions */
 	ret = -EACCES;
-	if (!key_permission(key, perm))
+
+	if (!key_task_permission(key, context, perm))
 		goto invalid_key;
 
  error:
@@ -615,7 +653,6 @@
 long join_session_keyring(const char *name)
 {
 	struct task_struct *tsk = current;
-	unsigned long flags;
 	struct key *keyring;
 	long ret;
 
@@ -625,9 +662,9 @@
 		if (ret < 0)
 			goto error;
 
-		spin_lock_irqsave(&tsk->sighand->siglock, flags);
-		ret = tsk->signal->session_keyring->serial;
-		spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+		rcu_read_lock();
+		ret = rcu_dereference(tsk->signal->session_keyring)->serial;
+		rcu_read_unlock();
 		goto error;
 	}
 
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 9705b1a..dfcd983 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -1,6 +1,6 @@
 /* request_key.c: request a key from userspace
  *
- * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
+ * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
  * Written by David Howells (dhowells@redhat.com)
  *
  * This program is free software; you can redistribute it and/or
@@ -13,6 +13,7 @@
 #include <linux/sched.h>
 #include <linux/kmod.h>
 #include <linux/err.h>
+#include <linux/keyctl.h>
 #include "internal.h"
 
 struct key_construction {
@@ -27,18 +28,26 @@
 /*
  * request userspace finish the construction of a key
  * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring> <info>"
- * - if callout_info is an empty string, it'll be rendered as a "-" instead
  */
 static int call_request_key(struct key *key,
 			    const char *op,
 			    const char *callout_info)
 {
 	struct task_struct *tsk = current;
-	unsigned long flags;
 	key_serial_t prkey, sskey;
+	struct key *session_keyring, *rkakey;
 	char *argv[10], *envp[3], uid_str[12], gid_str[12];
 	char key_str[12], keyring_str[3][12];
-	int i;
+	int ret, i;
+
+	kenter("{%d},%s,%s", key->serial, op, callout_info);
+
+	/* generate a new session keyring with an auth key in it */
+	session_keyring = request_key_auth_new(key, &rkakey);
+	if (IS_ERR(session_keyring)) {
+		ret = PTR_ERR(session_keyring);
+		goto error;
+	}
 
 	/* record the UID and GID */
 	sprintf(uid_str, "%d", current->fsuid);
@@ -55,17 +64,17 @@
 	if (tsk->signal->process_keyring)
 		prkey = tsk->signal->process_keyring->serial;
 
-	sskey = 0;
-	spin_lock_irqsave(&tsk->sighand->siglock, flags);
-	if (tsk->signal->session_keyring)
-		sskey = tsk->signal->session_keyring->serial;
-	spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
-
-
-	if (!sskey)
-		sskey = tsk->user->session_keyring->serial;
-
 	sprintf(keyring_str[1], "%d", prkey);
+
+	if (tsk->signal->session_keyring) {
+		rcu_read_lock();
+		sskey = rcu_dereference(tsk->signal->session_keyring)->serial;
+		rcu_read_unlock();
+	}
+	else {
+		sskey = tsk->user->session_keyring->serial;
+	}
+
 	sprintf(keyring_str[2], "%d", sskey);
 
 	/* set up a minimal environment */
@@ -84,11 +93,20 @@
 	argv[i++] = keyring_str[0];
 	argv[i++] = keyring_str[1];
 	argv[i++] = keyring_str[2];
-	argv[i++] = callout_info[0] ? (char *) callout_info : "-";
+	argv[i++] = (char *) callout_info;
 	argv[i] = NULL;
 
 	/* do it */
-	return call_usermodehelper(argv[0], argv, envp, 1);
+	ret = call_usermodehelper_keys(argv[0], argv, envp, session_keyring, 1);
+
+	/* dispose of the special keys */
+	key_revoke(rkakey);
+	key_put(rkakey);
+	key_put(session_keyring);
+
+ error:
+	kleave(" = %d", ret);
+	return ret;
 
 } /* end call_request_key() */
 
@@ -105,7 +123,9 @@
 	struct key_construction cons;
 	struct timespec now;
 	struct key *key;
-	int ret, negative;
+	int ret, negated;
+
+	kenter("%s,%s,%s", type->name, description, callout_info);
 
 	/* create a key and add it to the queue */
 	key = key_alloc(type, description,
@@ -113,9 +133,7 @@
 	if (IS_ERR(key))
 		goto alloc_failed;
 
-	write_lock(&key->lock);
-	key->flags |= KEY_FLAG_USER_CONSTRUCT;
-	write_unlock(&key->lock);
+	set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
 
 	cons.key = key;
 	list_add_tail(&cons.link, &key->user->consq);
@@ -130,7 +148,7 @@
 
 	/* if the key wasn't instantiated, then we want to give an error */
 	ret = -ENOKEY;
-	if (!(key->flags & KEY_FLAG_INSTANTIATED))
+	if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
 		goto request_failed;
 
 	down_write(&key_construction_sem);
@@ -139,12 +157,13 @@
 
 	/* also give an error if the key was negatively instantiated */
  check_not_negative:
-	if (key->flags & KEY_FLAG_NEGATIVE) {
+	if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
 		key_put(key);
 		key = ERR_PTR(-ENOKEY);
 	}
 
  out:
+	kleave(" = %p", key);
 	return key;
 
  request_failed:
@@ -152,24 +171,23 @@
 	 * - remove from construction queue
 	 * - mark the key as dead
 	 */
-	negative = 0;
+	negated = 0;
 	down_write(&key_construction_sem);
 
 	list_del(&cons.link);
 
-	write_lock(&key->lock);
-	key->flags &= ~KEY_FLAG_USER_CONSTRUCT;
-
 	/* check it didn't get instantiated between the check and the down */
-	if (!(key->flags & KEY_FLAG_INSTANTIATED)) {
-		key->flags |= KEY_FLAG_INSTANTIATED | KEY_FLAG_NEGATIVE;
-		negative = 1;
+	if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
+		set_bit(KEY_FLAG_NEGATIVE, &key->flags);
+		set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
+		negated = 1;
 	}
 
-	write_unlock(&key->lock);
+	clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags);
+
 	up_write(&key_construction_sem);
 
-	if (!negative)
+	if (!negated)
 		goto check_not_negative; /* surprisingly, the key got
 					  * instantiated */
 
@@ -178,13 +196,12 @@
 	key->expiry = now.tv_sec + key_negative_timeout;
 
 	if (current->signal->session_keyring) {
-		unsigned long flags;
 		struct key *keyring;
 
-		spin_lock_irqsave(&current->sighand->siglock, flags);
-		keyring = current->signal->session_keyring;
+		rcu_read_lock();
+		keyring = rcu_dereference(current->signal->session_keyring);
 		atomic_inc(&keyring->usage);
-		spin_unlock_irqrestore(&current->sighand->siglock, flags);
+		rcu_read_unlock();
 
 		key_link(keyring, key);
 		key_put(keyring);
@@ -220,6 +237,9 @@
 
 	DECLARE_WAITQUEUE(myself, current);
 
+	kenter("%s,%s,{%d},%s",
+	       type->name, description, user->uid, callout_info);
+
 	/* see if there's such a key under construction already */
 	down_write(&key_construction_sem);
 
@@ -236,6 +256,7 @@
 	/* see about getting userspace to construct the key */
 	key = __request_key_construction(type, description, callout_info);
  error:
+	kleave(" = %p", key);
 	return key;
 
 	/* someone else has the same key under construction
@@ -249,8 +270,10 @@
 	add_wait_queue(&request_key_conswq, &myself);
 
 	for (;;) {
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		if (!(ckey->flags & KEY_FLAG_USER_CONSTRUCT))
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (!test_bit(KEY_FLAG_USER_CONSTRUCT, &ckey->flags))
+			break;
+		if (signal_pending(current))
 			break;
 		schedule();
 	}
@@ -271,21 +294,83 @@
 
 /*****************************************************************************/
 /*
+ * link a freshly minted key to an appropriate destination keyring
+ */
+static void request_key_link(struct key *key, struct key *dest_keyring)
+{
+	struct task_struct *tsk = current;
+	struct key *drop = NULL;
+
+	kenter("{%d},%p", key->serial, dest_keyring);
+
+	/* find the appropriate keyring */
+	if (!dest_keyring) {
+		switch (tsk->jit_keyring) {
+		case KEY_REQKEY_DEFL_DEFAULT:
+		case KEY_REQKEY_DEFL_THREAD_KEYRING:
+			dest_keyring = tsk->thread_keyring;
+			if (dest_keyring)
+				break;
+
+		case KEY_REQKEY_DEFL_PROCESS_KEYRING:
+			dest_keyring = tsk->signal->process_keyring;
+			if (dest_keyring)
+				break;
+
+		case KEY_REQKEY_DEFL_SESSION_KEYRING:
+			rcu_read_lock();
+			dest_keyring = key_get(
+				rcu_dereference(tsk->signal->session_keyring));
+			rcu_read_unlock();
+			drop = dest_keyring;
+
+			if (dest_keyring)
+				break;
+
+		case KEY_REQKEY_DEFL_USER_SESSION_KEYRING:
+			dest_keyring = current->user->session_keyring;
+			break;
+
+		case KEY_REQKEY_DEFL_USER_KEYRING:
+			dest_keyring = current->user->uid_keyring;
+			break;
+
+		case KEY_REQKEY_DEFL_GROUP_KEYRING:
+		default:
+			BUG();
+		}
+	}
+
+	/* and attach the key to it */
+	key_link(dest_keyring, key);
+
+	key_put(drop);
+
+	kleave("");
+
+} /* end request_key_link() */
+
+/*****************************************************************************/
+/*
  * request a key
  * - search the process's keyrings
  * - check the list of keys being created or updated
- * - call out to userspace for a key if requested (supplementary info can be
- *   passed)
+ * - call out to userspace for a key if supplementary info was provided
+ * - cache the key in an appropriate keyring
  */
-struct key *request_key(struct key_type *type,
-			const char *description,
-			const char *callout_info)
+struct key *request_key_and_link(struct key_type *type,
+				 const char *description,
+				 const char *callout_info,
+				 struct key *dest_keyring)
 {
 	struct key_user *user;
 	struct key *key;
 
+	kenter("%s,%s,%s,%p",
+	       type->name, description, callout_info, dest_keyring);
+
 	/* search all the process keyrings for a key */
-	key = search_process_keyrings_aux(type, description, type->match);
+	key = search_process_keyrings(type, description, type->match, current);
 
 	if (PTR_ERR(key) == -EAGAIN) {
 		/* the search failed, but the keyrings were searchable, so we
@@ -296,12 +381,13 @@
 
 		/* - get hold of the user's construction queue */
 		user = key_user_lookup(current->fsuid);
-		if (!user) {
-			key = ERR_PTR(-ENOMEM);
-			goto error;
-		}
+		if (!user)
+			goto nomem;
 
-		for (;;) {
+		do {
+			if (signal_pending(current))
+				goto interrupted;
+
 			/* ask userspace (returns NULL if it waited on a key
 			 * being constructed) */
 			key = request_key_construction(type, description,
@@ -311,18 +397,46 @@
 
 			/* someone else made the key we want, so we need to
 			 * search again as it might now be available to us */
-			key = search_process_keyrings_aux(type, description,
-							  type->match);
-			if (PTR_ERR(key) != -EAGAIN)
-				break;
-		}
+			key = search_process_keyrings(type, description,
+						      type->match, current);
+
+		} while (PTR_ERR(key) == -EAGAIN);
 
 		key_user_put(user);
+
+		/* link the new key into the appropriate keyring */
+		if (!PTR_ERR(key))
+			request_key_link(key, dest_keyring);
 	}
 
- error:
+error:
+	kleave(" = %p", key);
 	return key;
 
+nomem:
+	key = ERR_PTR(-ENOMEM);
+	goto error;
+
+interrupted:
+	key_user_put(user);
+	key = ERR_PTR(-EINTR);
+	goto error;
+
+} /* end request_key_and_link() */
+
+/*****************************************************************************/
+/*
+ * request a key
+ * - search the process's keyrings
+ * - check the list of keys being created or updated
+ * - call out to userspace for a key if supplementary info was provided
+ */
+struct key *request_key(struct key_type *type,
+			const char *description,
+			const char *callout_info)
+{
+	return request_key_and_link(type, description, callout_info, NULL);
+
 } /* end request_key() */
 
 EXPORT_SYMBOL(request_key);
@@ -339,7 +453,8 @@
 	if (key) {
 		/* check it's still accessible */
 		ret = -EKEYREVOKED;
-		if (key->flags & (KEY_FLAG_REVOKED | KEY_FLAG_DEAD))
+		if (test_bit(KEY_FLAG_REVOKED, &key->flags) ||
+		    test_bit(KEY_FLAG_DEAD, &key->flags))
 			goto error;
 
 		/* check it hasn't expired */
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
new file mode 100644
index 0000000..f222646
--- /dev/null
+++ b/security/keys/request_key_auth.c
@@ -0,0 +1,180 @@
+/* request_key_auth.c: request key authorisation controlling key def
+ *
+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/err.h>
+#include <linux/seq_file.h>
+#include "internal.h"
+
+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_destroy(struct key *);
+
+/*
+ * the request-key authorisation key type definition
+ */
+struct key_type key_type_request_key_auth = {
+	.name		= ".request_key_auth",
+	.def_datalen	= sizeof(struct request_key_auth),
+	.instantiate	= request_key_auth_instantiate,
+	.describe	= request_key_auth_describe,
+	.destroy	= request_key_auth_destroy,
+};
+
+/*****************************************************************************/
+/*
+ * instantiate a request-key authorisation record
+ */
+static int request_key_auth_instantiate(struct key *key,
+					const void *data,
+					size_t datalen)
+{
+	struct request_key_auth *rka, *irka;
+	struct key *instkey;
+	int ret;
+
+	ret = -ENOMEM;
+	rka = kmalloc(sizeof(*rka), GFP_KERNEL);
+	if (rka) {
+		/* see if the calling process is already servicing the key
+		 * request of another process */
+		instkey = key_get_instantiation_authkey(0);
+		if (!IS_ERR(instkey)) {
+			/* it is - use that instantiation context here too */
+			irka = instkey->payload.data;
+			rka->context = irka->context;
+			rka->pid = irka->pid;
+			key_put(instkey);
+		}
+		else {
+			/* it isn't - use this process as the context */
+			rka->context = current;
+			rka->pid = current->pid;
+		}
+
+		rka->target_key = key_get((struct key *) data);
+		key->payload.data = rka;
+		ret = 0;
+	}
+
+	return ret;
+
+} /* end request_key_auth_instantiate() */
+
+/*****************************************************************************/
+/*
+ *
+ */
+static void request_key_auth_describe(const struct key *key,
+				      struct seq_file *m)
+{
+	struct request_key_auth *rka = key->payload.data;
+
+	seq_puts(m, "key:");
+	seq_puts(m, key->description);
+	seq_printf(m, " pid:%d", rka->pid);
+
+} /* end request_key_auth_describe() */
+
+/*****************************************************************************/
+/*
+ * destroy an instantiation authorisation token key
+ */
+static void request_key_auth_destroy(struct key *key)
+{
+	struct request_key_auth *rka = key->payload.data;
+
+	kenter("{%d}", key->serial);
+
+	key_put(rka->target_key);
+
+} /* end request_key_auth_destroy() */
+
+/*****************************************************************************/
+/*
+ * create a session keyring to be for the invokation of /sbin/request-key and
+ * stick an authorisation token in it
+ */
+struct key *request_key_auth_new(struct key *target, struct key **_rkakey)
+{
+	struct key *keyring, *rkakey = NULL;
+	char desc[20];
+	int ret;
+
+	kenter("%d,", target->serial);
+
+	/* allocate a new session keyring */
+	sprintf(desc, "_req.%u", target->serial);
+
+	keyring = keyring_alloc(desc, current->fsuid, current->fsgid, 1, NULL);
+	if (IS_ERR(keyring)) {
+		kleave("= %ld", PTR_ERR(keyring));
+		return keyring;
+	}
+
+	/* allocate the auth key */
+	sprintf(desc, "%x", target->serial);
+
+	rkakey = key_alloc(&key_type_request_key_auth, desc,
+			   current->fsuid, current->fsgid,
+			   KEY_USR_VIEW, 1);
+	if (IS_ERR(rkakey)) {
+		key_put(keyring);
+		kleave("= %ld", PTR_ERR(rkakey));
+		return rkakey;
+	}
+
+	/* construct and attach to the keyring */
+	ret = key_instantiate_and_link(rkakey, target, 0, keyring, NULL);
+	if (ret < 0) {
+		key_revoke(rkakey);
+		key_put(rkakey);
+		key_put(keyring);
+		kleave("= %d", ret);
+		return ERR_PTR(ret);
+	}
+
+	*_rkakey = rkakey;
+	kleave(" = {%d} ({%d})", keyring->serial, rkakey->serial);
+	return keyring;
+
+} /* end request_key_auth_new() */
+
+/*****************************************************************************/
+/*
+ * get the authorisation key for instantiation of a specific key if attached to
+ * the current process's keyrings
+ * - this key is inserted into a keyring and that is set as /sbin/request-key's
+ *   session keyring
+ * - a target_id of zero specifies any valid token
+ */
+struct key *key_get_instantiation_authkey(key_serial_t target_id)
+{
+	struct task_struct *tsk = current;
+	struct key *instkey;
+
+	/* we must have our own personal session keyring */
+	if (!tsk->signal->session_keyring)
+		return ERR_PTR(-EACCES);
+
+	/* and it must contain a suitable request authorisation key
+	 * - lock RCU against session keyring changing
+	 */
+	rcu_read_lock();
+
+	instkey = keyring_search_instkey(
+		rcu_dereference(tsk->signal->session_keyring), target_id);
+
+	rcu_read_unlock();
+	return instkey;
+
+} /* end key_get_instantiation_authkey() */
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c
index 8d65b3a..e446acb 100644
--- a/security/keys/user_defined.c
+++ b/security/keys/user_defined.c
@@ -42,12 +42,21 @@
 	.read		= user_read,
 };
 
+struct user_key_payload {
+	struct rcu_head	rcu;		/* RCU destructor */
+	unsigned short	datalen;	/* length of this data */
+	char		data[0];	/* actual data */
+};
+
+EXPORT_SYMBOL_GPL(key_type_user);
+
 /*****************************************************************************/
 /*
  * instantiate a user defined key
  */
 static int user_instantiate(struct key *key, const void *data, size_t datalen)
 {
+	struct user_key_payload *upayload;
 	int ret;
 
 	ret = -EINVAL;
@@ -58,13 +67,15 @@
 	if (ret < 0)
 		goto error;
 
-	/* attach the data */
 	ret = -ENOMEM;
-	key->payload.data = kmalloc(datalen, GFP_KERNEL);
-	if (!key->payload.data)
+	upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL);
+	if (!upayload)
 		goto error;
 
-	memcpy(key->payload.data, data, datalen);
+	/* attach the data */
+	upayload->datalen = datalen;
+	memcpy(upayload->data, data, datalen);
+	rcu_assign_pointer(key->payload.data, upayload);
 	ret = 0;
 
  error:
@@ -75,18 +86,25 @@
 /*****************************************************************************/
 /*
  * duplicate a user defined key
+ * - both keys' semaphores are locked against further modification
+ * - the new key cannot yet be accessed
  */
 static int user_duplicate(struct key *key, const struct key *source)
 {
+	struct user_key_payload *upayload, *spayload;
 	int ret;
 
 	/* just copy the payload */
 	ret = -ENOMEM;
-	key->payload.data = kmalloc(source->datalen, GFP_KERNEL);
+	upayload = kmalloc(sizeof(*upayload) + source->datalen, GFP_KERNEL);
+	if (upayload) {
+		spayload = rcu_dereference(source->payload.data);
+		BUG_ON(source->datalen != spayload->datalen);
 
-	if (key->payload.data) {
-		key->datalen = source->datalen;
-		memcpy(key->payload.data, source->payload.data, source->datalen);
+		upayload->datalen = key->datalen = spayload->datalen;
+		memcpy(upayload->data, spayload->data, key->datalen);
+
+		key->payload.data = upayload;
 		ret = 0;
 	}
 
@@ -96,40 +114,54 @@
 
 /*****************************************************************************/
 /*
+ * dispose of the old data from an updated user defined key
+ */
+static void user_update_rcu_disposal(struct rcu_head *rcu)
+{
+	struct user_key_payload *upayload;
+
+	upayload = container_of(rcu, struct user_key_payload, rcu);
+
+	kfree(upayload);
+
+} /* end user_update_rcu_disposal() */
+
+/*****************************************************************************/
+/*
  * update a user defined key
+ * - the key's semaphore is write-locked
  */
 static int user_update(struct key *key, const void *data, size_t datalen)
 {
-	void *new, *zap;
+	struct user_key_payload *upayload, *zap;
 	int ret;
 
 	ret = -EINVAL;
 	if (datalen <= 0 || datalen > 32767 || !data)
 		goto error;
 
-	/* copy the data */
+	/* construct a replacement payload */
 	ret = -ENOMEM;
-	new = kmalloc(datalen, GFP_KERNEL);
-	if (!new)
+	upayload = kmalloc(sizeof(*upayload) + datalen, GFP_KERNEL);
+	if (!upayload)
 		goto error;
 
-	memcpy(new, data, datalen);
+	upayload->datalen = datalen;
+	memcpy(upayload->data, data, datalen);
 
 	/* check the quota and attach the new data */
-	zap = new;
-	write_lock(&key->lock);
+	zap = upayload;
 
 	ret = key_payload_reserve(key, datalen);
 
 	if (ret == 0) {
 		/* attach the new data, displacing the old */
 		zap = key->payload.data;
-		key->payload.data = new;
+		rcu_assign_pointer(key->payload.data, upayload);
 		key->expiry = 0;
 	}
 
-	write_unlock(&key->lock);
-	kfree(zap);
+	call_rcu(&zap->rcu, user_update_rcu_disposal);
 
  error:
 	return ret;
@@ -152,13 +184,15 @@
  */
 static void user_destroy(struct key *key)
 {
-	kfree(key->payload.data);
+	struct user_key_payload *upayload = key->payload.data;
+
+	kfree(upayload);
 
 } /* end user_destroy() */
 
 /*****************************************************************************/
 /*
- * describe the user
+ * describe the user key
  */
 static void user_describe(const struct key *key, struct seq_file *m)
 {
@@ -171,18 +205,23 @@
 /*****************************************************************************/
 /*
  * read the key data
+ * - the key's semaphore is read-locked
  */
 static long user_read(const struct key *key,
 		      char __user *buffer, size_t buflen)
 {
-	long ret = key->datalen;
+	struct user_key_payload *upayload;
+	long ret;
+
+	upayload = rcu_dereference(key->payload.data);
+	ret = upayload->datalen;
 
 	/* we can return the data as is */
 	if (buffer && buflen > 0) {
-		if (buflen > key->datalen)
-			buflen = key->datalen;
+		if (buflen > upayload->datalen)
+			buflen = upayload->datalen;
 
-		if (copy_to_user(buffer, key->payload.data, buflen) != 0)
+		if (copy_to_user(buffer, upayload->data, buflen) != 0)
 			ret = -EFAULT;
 	}
 
diff --git a/security/seclvl.c b/security/seclvl.c
index 8a0ab0d..c8e87b2 100644
--- a/security/seclvl.c
+++ b/security/seclvl.c
@@ -155,7 +155,7 @@
 	struct seclvl_obj *obj = container_of(kobj, struct seclvl_obj, kobj);
 	struct seclvl_attribute *attribute =
 	    container_of(attr, struct seclvl_attribute, attr);
-	return (attribute->store ? attribute->store(obj, buf, len) : 0);
+	return attribute->store ? attribute->store(obj, buf, len) : -EIO;
 }
 
 static ssize_t
@@ -164,7 +164,7 @@
 	struct seclvl_obj *obj = container_of(kobj, struct seclvl_obj, kobj);
 	struct seclvl_attribute *attribute =
 	    container_of(attr, struct seclvl_attribute, attr);
-	return (attribute->show ? attribute->show(obj, buf) : 0);
+	return attribute->show ? attribute->show(obj, buf) : -EIO;
 }
 
 /**
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 85a6f66..4515024 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -242,7 +242,7 @@
 	avc_node_cachep = kmem_cache_create("avc_node", sizeof(struct avc_node),
 					     0, SLAB_PANIC, NULL, NULL);
 
-	audit_log(current->audit_context, "AVC INITIALIZED\n");
+	audit_log(current->audit_context, AUDIT_KERNEL, "AVC INITIALIZED\n");
 }
 
 int avc_get_hash_stats(char *page)
@@ -532,6 +532,7 @@
                u16 tclass, u32 requested,
                struct av_decision *avd, int result, struct avc_audit_data *a)
 {
+	struct task_struct *tsk = current;
 	struct inode *inode = NULL;
 	u32 denied, audited;
 	struct audit_buffer *ab;
@@ -549,12 +550,18 @@
 			return;
 	}
 
-	ab = audit_log_start(current->audit_context);
+	ab = audit_log_start(current->audit_context, AUDIT_AVC);
 	if (!ab)
 		return;		/* audit_panic has been called */
 	audit_log_format(ab, "avc:  %s ", denied ? "denied" : "granted");
 	avc_dump_av(ab, tclass,audited);
 	audit_log_format(ab, " for ");
+	if (a && a->tsk)
+		tsk = a->tsk;
+	if (tsk && tsk->pid) {
+		audit_log_format(ab, " pid=%d comm=", tsk->pid);
+		audit_log_untrustedstring(ab, tsk->comm);
+	}
 	if (a) {
 		switch (a->type) {
 		case AVC_AUDIT_DATA_IPC:
@@ -566,21 +573,18 @@
 		case AVC_AUDIT_DATA_FS:
 			if (a->u.fs.dentry) {
 				struct dentry *dentry = a->u.fs.dentry;
-				if (a->u.fs.mnt) {
-					audit_log_d_path(ab, "path=", dentry,
-							a->u.fs.mnt);
-				} else {
-					audit_log_format(ab, " name=%s",
-							 dentry->d_name.name);
-				}
+				if (a->u.fs.mnt)
+					audit_avc_path(dentry, a->u.fs.mnt);
+				audit_log_format(ab, " name=");
+				audit_log_untrustedstring(ab, dentry->d_name.name);
 				inode = dentry->d_inode;
 			} else if (a->u.fs.inode) {
 				struct dentry *dentry;
 				inode = a->u.fs.inode;
 				dentry = d_find_alias(inode);
 				if (dentry) {
-					audit_log_format(ab, " name=%s",
-							 dentry->d_name.name);
+					audit_log_format(ab, " name=");
+					audit_log_untrustedstring(ab, dentry->d_name.name);
 					dput(dentry);
 				}
 			}
@@ -623,22 +627,20 @@
 				case AF_UNIX:
 					u = unix_sk(sk);
 					if (u->dentry) {
-						audit_log_d_path(ab, "path=",
-							u->dentry, u->mnt);
+						audit_avc_path(u->dentry, u->mnt);
+						audit_log_format(ab, " name=");
+						audit_log_untrustedstring(ab, u->dentry->d_name.name);
 						break;
 					}
 					if (!u->addr)
 						break;
 					len = u->addr->len-sizeof(short);
 					p = &u->addr->name->sun_path[0];
+					audit_log_format(ab, " path=");
 					if (*p)
-						audit_log_format(ab,
-							"path=%*.*s", len,
-							len, p);
+						audit_log_untrustedstring(ab, p);
 					else
-						audit_log_format(ab,
-							"path=@%*.*s", len-1,
-							len-1, p+1);
+						audit_log_hex(ab, p, len);
 					break;
 				}
 			}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index aae1e79..17a1189 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1658,9 +1658,8 @@
 
 static void selinux_bprm_free_security(struct linux_binprm *bprm)
 {
-	struct bprm_security_struct *bsec = bprm->security;
+	kfree(bprm->security);
 	bprm->security = NULL;
-	kfree(bsec);
 }
 
 extern struct vfsmount *selinuxfs_mount;
@@ -1945,6 +1944,7 @@
 	} while (*in_end++);
 
 	copy_page(in_save, nosec_save);
+	free_page((unsigned long)nosec_save);
 out:
 	return rc;
 }
@@ -2476,6 +2476,17 @@
 		prot = reqprot;
 
 #ifndef CONFIG_PPC32
+	if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXECUTABLE) &&
+	   (vma->vm_start >= vma->vm_mm->start_brk &&
+	    vma->vm_end <= vma->vm_mm->brk)) {
+	    	/*
+		 * We are making an executable mapping in the brk region.
+		 * This has an additional execheap check.
+		 */
+		rc = task_has_perm(current, current, PROCESS__EXECHEAP);
+		if (rc)
+			return rc;
+	}
 	if (vma->vm_file != NULL && vma->anon_vma != NULL && (prot & PROT_EXEC)) {
 		/*
 		 * We are making executable a file mapping that has
@@ -2487,6 +2498,16 @@
 		if (rc)
 			return rc;
 	}
+	if (!vma->vm_file && (prot & PROT_EXEC) &&
+		vma->vm_start <= vma->vm_mm->start_stack &&
+		vma->vm_end >= vma->vm_mm->start_stack) {
+		/* Attempt to make the process stack executable.
+		 * This has an additional execstack check.
+		 */
+		rc = task_has_perm(current, current, PROCESS__EXECSTACK);
+		if (rc)
+			return rc;
+	}
 #endif
 
 	return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
@@ -3419,7 +3440,7 @@
 	err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm);
 	if (err) {
 		if (err == -EINVAL) {
-			audit_log(current->audit_context,
+			audit_log(current->audit_context, AUDIT_SELINUX_ERR,
 				  "SELinux:  unrecognized netlink message"
 				  " type=%hu for sclass=%hu\n",
 				  nlh->nlmsg_type, isec->sclass);
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
index 8928bb4d..1deb59e 100644
--- a/security/selinux/include/av_perm_to_string.h
+++ b/security/selinux/include/av_perm_to_string.h
@@ -70,6 +70,8 @@
    S_(SECCLASS_PROCESS, PROCESS__DYNTRANSITION, "dyntransition")
    S_(SECCLASS_PROCESS, PROCESS__SETCURRENT, "setcurrent")
    S_(SECCLASS_PROCESS, PROCESS__EXECMEM, "execmem")
+   S_(SECCLASS_PROCESS, PROCESS__EXECSTACK, "execstack")
+   S_(SECCLASS_PROCESS, PROCESS__EXECHEAP, "execheap")
    S_(SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue")
    S_(SECCLASS_MSG, MSG__SEND, "send")
    S_(SECCLASS_MSG, MSG__RECEIVE, "receive")
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
index bdfce4c..a78b5d5 100644
--- a/security/selinux/include/av_permissions.h
+++ b/security/selinux/include/av_permissions.h
@@ -465,6 +465,8 @@
 #define PROCESS__DYNTRANSITION                    0x00800000UL
 #define PROCESS__SETCURRENT                       0x01000000UL
 #define PROCESS__EXECMEM                          0x02000000UL
+#define PROCESS__EXECSTACK                        0x04000000UL
+#define PROCESS__EXECHEAP                         0x08000000UL
 
 #define IPC__CREATE                               0x00000001UL
 #define IPC__DESTROY                              0x00000002UL
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index b3adb48..92b057b 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -63,6 +63,8 @@
 	{ RTM_GETPREFIX,	NETLINK_ROUTE_SOCKET__NLMSG_READ  },
 	{ RTM_GETMULTICAST,	NETLINK_ROUTE_SOCKET__NLMSG_READ  },
 	{ RTM_GETANYCAST,	NETLINK_ROUTE_SOCKET__NLMSG_READ  },
+	{ RTM_GETNEIGHTBL,	NETLINK_ROUTE_SOCKET__NLMSG_READ  },
+	{ RTM_SETNEIGHTBL,	NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
 };
 
 static struct nlmsg_perm nlmsg_firewall_perms[] =
@@ -97,6 +99,7 @@
 	{ AUDIT_ADD,		NETLINK_AUDIT_SOCKET__NLMSG_WRITE    },
 	{ AUDIT_DEL,		NETLINK_AUDIT_SOCKET__NLMSG_WRITE    },
 	{ AUDIT_USER,		NETLINK_AUDIT_SOCKET__NLMSG_RELAY    },
+	{ AUDIT_SIGNAL_INFO,	NETLINK_AUDIT_SOCKET__NLMSG_READ     },
 };
 
 
@@ -141,8 +144,13 @@
 		break;
 
 	case SECCLASS_NETLINK_AUDIT_SOCKET:
-		err = nlmsg_perm(nlmsg_type, perm, nlmsg_audit_perms,
-				 sizeof(nlmsg_audit_perms));
+		if (nlmsg_type >= AUDIT_FIRST_USER_MSG &&
+		    nlmsg_type <= AUDIT_LAST_USER_MSG) {
+			*perm = NETLINK_AUDIT_SOCKET__NLMSG_RELAY;
+		} else {
+			err = nlmsg_perm(nlmsg_type, perm, nlmsg_audit_perms,
+					 sizeof(nlmsg_audit_perms));
+		}
 		break;
 
 	/* No messaging from userspace, or class unknown/unhandled */
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 0722156..8eb140d 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -951,8 +951,7 @@
 	u32 sid;
 
 	/* remove any existing files */
-	if (bool_pending_values)
-		kfree(bool_pending_values);
+	kfree(bool_pending_values);
 
 	sel_remove_bools(dir);
 
@@ -997,10 +996,8 @@
 out:
 	free_page((unsigned long)page);
 	if (names) {
-		for (i = 0; i < num; i++) {
-			if (names[i])
-				kfree(names[i]);
-		}
+		for (i = 0; i < num; i++)
+			kfree(names[i]);
 		kfree(names);
 	}
 	return ret;
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
index b534411..e2057f5 100644
--- a/security/selinux/ss/conditional.c
+++ b/security/selinux/ss/conditional.c
@@ -166,16 +166,14 @@
 
 void cond_policydb_destroy(struct policydb *p)
 {
-	if (p->bool_val_to_struct != NULL)
-		kfree(p->bool_val_to_struct);
+	kfree(p->bool_val_to_struct);
 	avtab_destroy(&p->te_cond_avtab);
 	cond_list_destroy(p->cond_list);
 }
 
 int cond_init_bool_indexes(struct policydb *p)
 {
-	if (p->bool_val_to_struct)
-		kfree(p->bool_val_to_struct);
+	kfree(p->bool_val_to_struct);
 	p->bool_val_to_struct = (struct cond_bool_datum**)
 		kmalloc(p->p_bools.nprim * sizeof(struct cond_bool_datum*), GFP_KERNEL);
 	if (!p->bool_val_to_struct)
@@ -185,8 +183,7 @@
 
 int cond_destroy_bool(void *key, void *datum, void *p)
 {
-	if (key)
-		kfree(key);
+	kfree(key);
 	kfree(datum);
 	return 0;
 }
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 14190ef..785c33c 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -590,17 +590,12 @@
 		hashtab_destroy(p->symtab[i].table);
 	}
 
-	for (i = 0; i < SYM_NUM; i++) {
-		if (p->sym_val_to_name[i])
-			kfree(p->sym_val_to_name[i]);
-	}
+	for (i = 0; i < SYM_NUM; i++)
+		kfree(p->sym_val_to_name[i]);
 
-	if (p->class_val_to_struct)
-		kfree(p->class_val_to_struct);
-	if (p->role_val_to_struct)
-		kfree(p->role_val_to_struct);
-	if (p->user_val_to_struct)
-		kfree(p->user_val_to_struct);
+	kfree(p->class_val_to_struct);
+	kfree(p->role_val_to_struct);
+	kfree(p->user_val_to_struct);
 
 	avtab_destroy(&p->te_avtab);
 
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 8449d66..922bb45 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -365,7 +365,7 @@
 		goto out;
 	if (context_struct_to_string(tcontext, &t, &tlen) < 0)
 		goto out;
-	audit_log(current->audit_context,
+	audit_log(current->audit_context, AUDIT_SELINUX_ERR,
 	          "security_validate_transition:  denied for"
 	          " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
 	          o, n, t, policydb.p_class_val_to_name[tclass-1]);
@@ -742,7 +742,7 @@
 		goto out;
 	if (context_struct_to_string(newcontext, &n, &nlen) < 0)
 		goto out;
-	audit_log(current->audit_context,
+	audit_log(current->audit_context, AUDIT_SELINUX_ERR,
 		  "security_compute_sid:  invalid context %s"
 		  " for scontext=%s"
 		  " tcontext=%s"
@@ -1705,11 +1705,9 @@
 err:
 	if (*names) {
 		for (i = 0; i < *len; i++)
-			if ((*names)[i])
-				kfree((*names)[i]);
+			kfree((*names)[i]);
 	}
-	if (*values)
-		kfree(*values);
+	kfree(*values);
 	goto out;
 }
 
diff --git a/sound/Kconfig b/sound/Kconfig
index 047d59e..ee794ae 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -42,6 +42,11 @@
 config SND
 	tristate "Advanced Linux Sound Architecture"
 	depends on SOUND
+	help
+	  Say 'Y' or 'M' to enable ALSA (Advanced Linux Sound Architecture),
+	  the new base sound system.
+
+	  For more information, see <http://www.alsa-project.org/>
 
 source "sound/core/Kconfig"
 
diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig
index cdacf4d..34c1740 100644
--- a/sound/arm/Kconfig
+++ b/sound/arm/Kconfig
@@ -14,5 +14,11 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-sa11xx-uda1341.
 
+config SND_ARMAACI
+	tristate "ARM PrimeCell PL041 AC Link support"
+	depends on SND && ARM_AMBA
+	select SND_PCM
+	select SND_AC97_CODEC
+
 endmenu
 
diff --git a/sound/arm/Makefile b/sound/arm/Makefile
index d7e7dc0..f74ec28 100644
--- a/sound/arm/Makefile
+++ b/sound/arm/Makefile
@@ -6,3 +6,6 @@
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-sa11xx-uda1341.o 
+
+obj-$(CONFIG_SND_ARMAACI)	+= snd-aaci.o
+snd-aaci-objs			:= aaci.o devdma.o
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
new file mode 100644
index 0000000..08cc3dd
--- /dev/null
+++ b/sound/arm/aaci.c
@@ -0,0 +1,968 @@
+/*
+ *  linux/sound/arm/aaci.c - ARM PrimeCell AACI PL041 driver
+ *
+ *  Copyright (C) 2003 Deep Blue Solutions Ltd, 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 version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  Documentation: ARM DDI 0173B
+ */
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware/amba.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/ac97_codec.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+
+#include "aaci.h"
+#include "devdma.h"
+
+#define DRIVER_NAME	"aaci-pl041"
+
+/*
+ * PM support is not complete.  Turn it off.
+ */
+#undef CONFIG_PM
+
+static void aaci_ac97_select_codec(struct aaci *aaci, ac97_t *ac97)
+{
+	u32 v, maincr = aaci->maincr | MAINCR_SCRA(ac97->num);
+
+	/*
+	 * Ensure that the slot 1/2 RX registers are empty.
+	 */
+	v = readl(aaci->base + AACI_SLFR);
+	if (v & SLFR_2RXV)
+		readl(aaci->base + AACI_SL2RX);
+	if (v & SLFR_1RXV)
+		readl(aaci->base + AACI_SL1RX);
+
+	writel(maincr, aaci->base + AACI_MAINCR);
+}
+
+/*
+ * P29:
+ *  The recommended use of programming the external codec through slot 1
+ *  and slot 2 data is to use the channels during setup routines and the
+ *  slot register at any other time.  The data written into slot 1, slot 2
+ *  and slot 12 registers is transmitted only when their corresponding
+ *  SI1TxEn, SI2TxEn and SI12TxEn bits are set in the AACI_MAINCR
+ *  register.
+ */
+static void aaci_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
+{
+	struct aaci *aaci = ac97->private_data;
+	u32 v;
+
+	if (ac97->num >= 4)
+		return;
+
+	down(&aaci->ac97_sem);
+
+	aaci_ac97_select_codec(aaci, ac97);
+
+	/*
+	 * P54: You must ensure that AACI_SL2TX is always written
+	 * to, if required, before data is written to AACI_SL1TX.
+	 */
+	writel(val << 4, aaci->base + AACI_SL2TX);
+	writel(reg << 12, aaci->base + AACI_SL1TX);
+
+	/*
+	 * Wait for the transmission of both slots to complete.
+	 */
+	do {
+		v = readl(aaci->base + AACI_SLFR);
+	} while (v & (SLFR_1TXB|SLFR_2TXB));
+
+	up(&aaci->ac97_sem);
+}
+
+/*
+ * Read an AC'97 register.
+ */
+static unsigned short aaci_ac97_read(ac97_t *ac97, unsigned short reg)
+{
+	struct aaci *aaci = ac97->private_data;
+	u32 v;
+
+	if (ac97->num >= 4)
+		return ~0;
+
+	down(&aaci->ac97_sem);
+
+	aaci_ac97_select_codec(aaci, ac97);
+
+	/*
+	 * Write the register address to slot 1.
+	 */
+	writel((reg << 12) | (1 << 19), aaci->base + AACI_SL1TX);
+
+	/*
+	 * Wait for the transmission to complete.
+	 */
+	do {
+		v = readl(aaci->base + AACI_SLFR);
+	} while (v & SLFR_1TXB);
+
+	/*
+	 * Give the AC'97 codec more than enough time
+	 * to respond. (42us = ~2 frames at 48kHz.)
+	 */
+	udelay(42);
+
+	/*
+	 * Wait for slot 2 to indicate data.
+	 */
+	do {
+		cond_resched();
+		v = readl(aaci->base + AACI_SLFR) & (SLFR_1RXV|SLFR_2RXV);
+	} while (v != (SLFR_1RXV|SLFR_2RXV));
+
+	v = readl(aaci->base + AACI_SL1RX) >> 12;
+	if (v == reg) {
+		v = readl(aaci->base + AACI_SL2RX) >> 4;
+	} else {
+		dev_err(&aaci->dev->dev,
+			"wrong ac97 register read back (%x != %x)\n",
+			v, reg);
+		v = ~0;
+	}
+
+	up(&aaci->ac97_sem);
+	return v;
+}
+
+static inline void aaci_chan_wait_ready(struct aaci_runtime *aacirun)
+{
+	u32 val;
+	int timeout = 5000;
+
+	do {
+		val = readl(aacirun->base + AACI_SR);
+	} while (val & (SR_TXB|SR_RXB) && timeout--);
+}
+
+
+
+/*
+ * Interrupt support.
+ */
+static void aaci_fifo_irq(struct aaci *aaci, u32 mask)
+{
+	if (mask & ISR_URINTR) {
+		writel(ICLR_TXUEC1, aaci->base + AACI_INTCLR);
+	}
+
+	if (mask & ISR_TXINTR) {
+		struct aaci_runtime *aacirun = &aaci->playback;
+		void *ptr;
+
+		if (!aacirun->substream || !aacirun->start) {
+			dev_warn(&aaci->dev->dev, "TX interrupt???");
+			writel(0, aacirun->base + AACI_IE);
+			return;
+		}
+
+		ptr = aacirun->ptr;
+		do {
+			unsigned int len = aacirun->fifosz;
+			u32 val;
+
+			if (aacirun->bytes <= 0) {
+				aacirun->bytes += aacirun->period;
+				aacirun->ptr = ptr;
+				spin_unlock(&aaci->lock);
+				snd_pcm_period_elapsed(aacirun->substream);
+				spin_lock(&aaci->lock);
+			}
+			if (!(aacirun->cr & TXCR_TXEN))
+				break;
+
+			val = readl(aacirun->base + AACI_SR);
+			if (!(val & SR_TXHE))
+				break;
+			if (!(val & SR_TXFE))
+				len >>= 1;
+
+			aacirun->bytes -= len;
+
+			/* writing 16 bytes at a time */
+			for ( ; len > 0; len -= 16) {
+				asm(
+					"ldmia	%0!, {r0, r1, r2, r3}\n\t"
+					"stmia	%1, {r0, r1, r2, r3}"
+					: "+r" (ptr)
+					: "r" (aacirun->fifo)
+					: "r0", "r1", "r2", "r3", "cc");
+
+				if (ptr >= aacirun->end)
+					ptr = aacirun->start;
+			}
+		} while (1);
+
+		aacirun->ptr = ptr;
+	}
+}
+
+static irqreturn_t aaci_irq(int irq, void *devid, struct pt_regs *regs)
+{
+	struct aaci *aaci = devid;
+	u32 mask;
+	int i;
+
+	spin_lock(&aaci->lock);
+	mask = readl(aaci->base + AACI_ALLINTS);
+	if (mask) {
+		u32 m = mask;
+		for (i = 0; i < 4; i++, m >>= 7) {
+			if (m & 0x7f) {
+				aaci_fifo_irq(aaci, m);
+			}
+		}
+	}
+	spin_unlock(&aaci->lock);
+
+	return mask ? IRQ_HANDLED : IRQ_NONE;
+}
+
+
+
+/*
+ * ALSA support.
+ */
+
+struct aaci_stream {
+	unsigned char codec_idx;
+	unsigned char rate_idx;
+};
+
+static struct aaci_stream aaci_streams[] = {
+	[ACSTREAM_FRONT] = {
+		.codec_idx	= 0,
+		.rate_idx	= AC97_RATES_FRONT_DAC,
+	},
+	[ACSTREAM_SURROUND] = {
+		.codec_idx	= 0,
+		.rate_idx	= AC97_RATES_SURR_DAC,
+	},
+	[ACSTREAM_LFE] = {
+		.codec_idx	= 0,
+		.rate_idx	= AC97_RATES_LFE_DAC,
+	},
+};
+
+static inline unsigned int aaci_rate_mask(struct aaci *aaci, int streamid)
+{
+	struct aaci_stream *s = aaci_streams + streamid;
+	return aaci->ac97_bus->codec[s->codec_idx]->rates[s->rate_idx];
+}
+
+static unsigned int rate_list[] = {
+	5512, 8000, 11025, 16000, 22050, 32000, 44100,
+	48000, 64000, 88200, 96000, 176400, 192000
+};
+
+/*
+ * Double-rate rule: we can support double rate iff channels == 2
+ *  (unimplemented)
+ */
+static int
+aaci_rule_rate_by_channels(snd_pcm_hw_params_t *p, snd_pcm_hw_rule_t *rule)
+{
+	struct aaci *aaci = rule->private;
+	unsigned int rate_mask = SNDRV_PCM_RATE_8000_48000|SNDRV_PCM_RATE_5512;
+	snd_interval_t *c = hw_param_interval(p, SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	switch (c->max) {
+	case 6:
+		rate_mask &= aaci_rate_mask(aaci, ACSTREAM_LFE);
+	case 4:
+		rate_mask &= aaci_rate_mask(aaci, ACSTREAM_SURROUND);
+	case 2:
+		rate_mask &= aaci_rate_mask(aaci, ACSTREAM_FRONT);
+	}
+
+	return snd_interval_list(hw_param_interval(p, rule->var),
+				 ARRAY_SIZE(rate_list), rate_list,
+				 rate_mask);
+}
+
+static snd_pcm_hardware_t aaci_hw_info = {
+	.info			= SNDRV_PCM_INFO_MMAP |
+				  SNDRV_PCM_INFO_MMAP_VALID |
+				  SNDRV_PCM_INFO_INTERLEAVED |
+				  SNDRV_PCM_INFO_BLOCK_TRANSFER |
+				  SNDRV_PCM_INFO_RESUME,
+
+	/*
+	 * ALSA doesn't support 18-bit or 20-bit packed into 32-bit
+	 * words.  It also doesn't support 12-bit at all.
+	 */
+	.formats		= SNDRV_PCM_FMTBIT_S16_LE,
+
+	/* should this be continuous or knot? */
+	.rates			= SNDRV_PCM_RATE_CONTINUOUS,
+	.rate_max		= 48000,
+	.rate_min		= 4000,
+	.channels_min		= 2,
+	.channels_max		= 6,
+	.buffer_bytes_max	= 64 * 1024,
+	.period_bytes_min	= 256,
+	.period_bytes_max	= PAGE_SIZE,
+	.periods_min		= 4,
+	.periods_max		= PAGE_SIZE / 16,
+};
+
+static int aaci_pcm_open(struct aaci *aaci, snd_pcm_substream_t *substream,
+			 struct aaci_runtime *aacirun)
+{
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	int ret;
+
+	aacirun->substream = substream;
+	runtime->private_data = aacirun;
+	runtime->hw = aaci_hw_info;
+
+	/*
+	 * FIXME: ALSA specifies fifo_size in bytes.  If we're in normal
+	 * mode, each 32-bit word contains one sample.  If we're in
+	 * compact mode, each 32-bit word contains two samples, effectively
+	 * halving the FIFO size.  However, we don't know for sure which
+	 * we'll be using at this point.  We set this to the lower limit.
+	 */
+	runtime->hw.fifo_size = aaci->fifosize * 2;
+
+	/*
+	 * Add rule describing hardware rate dependency
+	 * on the number of channels.
+	 */
+	ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+				  aaci_rule_rate_by_channels, aaci,
+				  SNDRV_PCM_HW_PARAM_CHANNELS,
+				  SNDRV_PCM_HW_PARAM_RATE, -1);
+	if (ret)
+		goto out;
+
+	ret = request_irq(aaci->dev->irq[0], aaci_irq, SA_SHIRQ|SA_INTERRUPT,
+			  DRIVER_NAME, aaci);
+	if (ret)
+		goto out;
+
+	return 0;
+
+ out:
+	return ret;
+}
+
+
+/*
+ * Common ALSA stuff
+ */
+static int aaci_pcm_close(snd_pcm_substream_t *substream)
+{
+	struct aaci *aaci = substream->private_data;
+	struct aaci_runtime *aacirun = substream->runtime->private_data;
+
+	WARN_ON(aacirun->cr & TXCR_TXEN);
+
+	aacirun->substream = NULL;
+	free_irq(aaci->dev->irq[0], aaci);
+
+	return 0;
+}
+
+static int aaci_pcm_hw_free(snd_pcm_substream_t *substream)
+{
+	struct aaci_runtime *aacirun = substream->runtime->private_data;
+
+	/*
+	 * This must not be called with the device enabled.
+	 */
+	WARN_ON(aacirun->cr & TXCR_TXEN);
+
+	if (aacirun->pcm_open)
+		snd_ac97_pcm_close(aacirun->pcm);
+	aacirun->pcm_open = 0;
+
+	/*
+	 * Clear out the DMA and any allocated buffers.
+	 */
+	devdma_hw_free(NULL, substream);
+
+	return 0;
+}
+
+static int aaci_pcm_hw_params(snd_pcm_substream_t *substream,
+			      struct aaci_runtime *aacirun,
+			      snd_pcm_hw_params_t *params)
+{
+	int err;
+
+	aaci_pcm_hw_free(substream);
+
+	err = devdma_hw_alloc(NULL, substream,
+			      params_buffer_bytes(params));
+	if (err < 0)
+		goto out;
+
+	err = snd_ac97_pcm_open(aacirun->pcm, params_rate(params),
+				params_channels(params),
+				aacirun->pcm->r[0].slots);
+	if (err)
+		goto out;
+
+	aacirun->pcm_open = 1;
+
+ out:
+	return err;
+}
+
+static int aaci_pcm_prepare(snd_pcm_substream_t *substream)
+{
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	struct aaci_runtime *aacirun = runtime->private_data;
+
+	aacirun->start	= (void *)runtime->dma_area;
+	aacirun->end	= aacirun->start + runtime->dma_bytes;
+	aacirun->ptr	= aacirun->start;
+	aacirun->period	=
+	aacirun->bytes	= frames_to_bytes(runtime, runtime->period_size);
+
+	return 0;
+}
+
+static snd_pcm_uframes_t aaci_pcm_pointer(snd_pcm_substream_t *substream)
+{
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	struct aaci_runtime *aacirun = runtime->private_data;
+	ssize_t bytes = aacirun->ptr - aacirun->start;
+
+	return bytes_to_frames(runtime, bytes);
+}
+
+static int aaci_pcm_mmap(snd_pcm_substream_t *substream, struct vm_area_struct *vma)
+{
+	return devdma_mmap(NULL, substream, vma);
+}
+
+
+/*
+ * Playback specific ALSA stuff
+ */
+static const u32 channels_to_txmask[] = {
+	[2] = TXCR_TX3 | TXCR_TX4,
+	[4] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8,
+	[6] = TXCR_TX3 | TXCR_TX4 | TXCR_TX7 | TXCR_TX8 | TXCR_TX6 | TXCR_TX9,
+};
+
+/*
+ * We can support two and four channel audio.  Unfortunately
+ * six channel audio requires a non-standard channel ordering:
+ *   2 -> FL(3), FR(4)
+ *   4 -> FL(3), FR(4), SL(7), SR(8)
+ *   6 -> FL(3), FR(4), SL(7), SR(8), C(6), LFE(9) (required)
+ *        FL(3), FR(4), C(6), SL(7), SR(8), LFE(9) (actual)
+ * This requires an ALSA configuration file to correct.
+ */
+static unsigned int channel_list[] = { 2, 4, 6 };
+
+static int
+aaci_rule_channels(snd_pcm_hw_params_t *p, snd_pcm_hw_rule_t *rule)
+{
+	struct aaci *aaci = rule->private;
+	unsigned int chan_mask = 1 << 0, slots;
+
+	/*
+	 * pcms[0] is the our 5.1 PCM instance.
+	 */
+	slots = aaci->ac97_bus->pcms[0].r[0].slots;
+	if (slots & (1 << AC97_SLOT_PCM_SLEFT)) {
+		chan_mask |= 1 << 1;
+		if (slots & (1 << AC97_SLOT_LFE))
+			chan_mask |= 1 << 2;
+	}
+
+	return snd_interval_list(hw_param_interval(p, rule->var),
+				 ARRAY_SIZE(channel_list), channel_list,
+				 chan_mask);
+}
+
+static int aaci_pcm_playback_open(snd_pcm_substream_t *substream)
+{
+	struct aaci *aaci = substream->private_data;
+	int ret;
+
+	/*
+	 * Add rule describing channel dependency.
+	 */
+	ret = snd_pcm_hw_rule_add(substream->runtime, 0,
+				  SNDRV_PCM_HW_PARAM_CHANNELS,
+				  aaci_rule_channels, aaci,
+				  SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+	if (ret)
+		return ret;
+
+	return aaci_pcm_open(aaci, substream, &aaci->playback);
+}
+
+static int aaci_pcm_playback_hw_params(snd_pcm_substream_t *substream,
+				       snd_pcm_hw_params_t *params)
+{
+	struct aaci *aaci = substream->private_data;
+	struct aaci_runtime *aacirun = substream->runtime->private_data;
+	unsigned int channels = params_channels(params);
+	int ret;
+
+	WARN_ON(channels >= ARRAY_SIZE(channels_to_txmask) ||
+		!channels_to_txmask[channels]);
+
+	ret = aaci_pcm_hw_params(substream, aacirun, params);
+
+	/*
+	 * Enable FIFO, compact mode, 16 bits per sample.
+	 * FIXME: double rate slots?
+	 */
+	if (ret >= 0) {
+		aacirun->cr = TXCR_FEN | TXCR_COMPACT | TXCR_TSZ16;
+		aacirun->cr |= channels_to_txmask[channels];
+
+		aacirun->fifosz	= aaci->fifosize * 4;
+		if (aacirun->cr & TXCR_COMPACT)
+			aacirun->fifosz >>= 1;
+	}
+	return ret;
+}
+
+static void aaci_pcm_playback_stop(struct aaci_runtime *aacirun)
+{
+	u32 ie;
+
+	ie = readl(aacirun->base + AACI_IE);
+	ie &= ~(IE_URIE|IE_TXIE);
+	writel(ie, aacirun->base + AACI_IE);
+	aacirun->cr &= ~TXCR_TXEN;
+	aaci_chan_wait_ready(aacirun);
+	writel(aacirun->cr, aacirun->base + AACI_TXCR);
+}
+
+static void aaci_pcm_playback_start(struct aaci_runtime *aacirun)
+{
+	u32 ie;
+
+	aaci_chan_wait_ready(aacirun);
+	aacirun->cr |= TXCR_TXEN;
+
+	ie = readl(aacirun->base + AACI_IE);
+	ie |= IE_URIE | IE_TXIE;
+	writel(ie, aacirun->base + AACI_IE);
+	writel(aacirun->cr, aacirun->base + AACI_TXCR);
+}
+
+static int aaci_pcm_playback_trigger(snd_pcm_substream_t *substream, int cmd)
+{
+	struct aaci *aaci = substream->private_data;
+	struct aaci_runtime *aacirun = substream->runtime->private_data;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&aaci->lock, flags);
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		aaci_pcm_playback_start(aacirun);
+		break;
+
+	case SNDRV_PCM_TRIGGER_RESUME:
+		aaci_pcm_playback_start(aacirun);
+		break;
+
+	case SNDRV_PCM_TRIGGER_STOP:
+		aaci_pcm_playback_stop(aacirun);
+		break;
+
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+		aaci_pcm_playback_stop(aacirun);
+		break;
+
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		break;
+
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		break;
+
+	default:
+		ret = -EINVAL;
+	}
+	spin_unlock_irqrestore(&aaci->lock, flags);
+
+	return ret;
+}
+
+static snd_pcm_ops_t aaci_playback_ops = {
+	.open		= aaci_pcm_playback_open,
+	.close		= aaci_pcm_close,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= aaci_pcm_playback_hw_params,
+	.hw_free	= aaci_pcm_hw_free,
+	.prepare	= aaci_pcm_prepare,
+	.trigger	= aaci_pcm_playback_trigger,
+	.pointer	= aaci_pcm_pointer,
+	.mmap		= aaci_pcm_mmap,
+};
+
+
+
+/*
+ * Power Management.
+ */
+#ifdef CONFIG_PM
+static int aaci_do_suspend(snd_card_t *card, unsigned int state)
+{
+	struct aaci *aaci = card->private_data;
+	if (aaci->card->power_state != SNDRV_CTL_POWER_D3cold) {
+		snd_pcm_suspend_all(aaci->pcm);
+		snd_power_change_state(aaci->card, SNDRV_CTL_POWER_D3cold);
+	}
+	return 0;
+}
+
+static int aaci_do_resume(snd_card_t *card, unsigned int state)
+{
+	struct aaci *aaci = card->private_data;
+	if (aaci->card->power_state != SNDRV_CTL_POWER_D0) {
+		snd_power_change_state(aaci->card, SNDRV_CTL_POWER_D0);
+	}
+	return 0;
+}
+
+static int aaci_suspend(struct amba_device *dev, u32 state)
+{
+	snd_card_t *card = amba_get_drvdata(dev);
+	return card ? aaci_do_suspend(card) : 0;
+}
+
+static int aaci_resume(struct amba_device *dev)
+{
+	snd_card_t *card = amba_get_drvdata(dev);
+	return card ? aaci_do_resume(card) : 0;
+}
+#else
+#define aaci_do_suspend		NULL
+#define aaci_do_resume		NULL
+#define aaci_suspend		NULL
+#define aaci_resume		NULL
+#endif
+
+
+static struct ac97_pcm ac97_defs[] __devinitdata = {
+	[0] = {		/* Front PCM */
+		.exclusive = 1,
+		.r = {
+			[0] = {
+				.slots	= (1 << AC97_SLOT_PCM_LEFT) |
+					  (1 << AC97_SLOT_PCM_RIGHT) |
+					  (1 << AC97_SLOT_PCM_CENTER) |
+					  (1 << AC97_SLOT_PCM_SLEFT) |
+					  (1 << AC97_SLOT_PCM_SRIGHT) |
+					  (1 << AC97_SLOT_LFE),
+			},
+		},
+	},
+	[1] = {	/* PCM in */
+		.stream = 1,
+		.exclusive = 1,
+		.r = {
+			[0] = {
+				.slots	= (1 << AC97_SLOT_PCM_LEFT) |
+					  (1 << AC97_SLOT_PCM_RIGHT),
+			},
+		},
+	},
+	[2] = {	/* Mic in */
+		.stream = 1,
+		.exclusive = 1,
+		.r = {
+			[0] = {
+				.slots	= (1 << AC97_SLOT_MIC),
+			},
+		},
+	}
+};
+
+static ac97_bus_ops_t aaci_bus_ops = {
+	.write	= aaci_ac97_write,
+	.read	= aaci_ac97_read,
+};
+
+static int __devinit aaci_probe_ac97(struct aaci *aaci)
+{
+	ac97_template_t ac97_template;
+	ac97_bus_t *ac97_bus;
+	ac97_t *ac97;
+	int ret;
+
+	/*
+	 * Assert AACIRESET for 2us
+	 */
+	writel(0, aaci->base + AACI_RESET);
+	udelay(2);
+	writel(RESET_NRST, aaci->base + AACI_RESET);
+
+	/*
+	 * Give the AC'97 codec more than enough time
+	 * to wake up. (42us = ~2 frames at 48kHz.)
+	 */
+	udelay(42);
+
+	ret = snd_ac97_bus(aaci->card, 0, &aaci_bus_ops, aaci, &ac97_bus);
+	if (ret)
+		goto out;
+
+	ac97_bus->clock = 48000;
+	aaci->ac97_bus = ac97_bus;
+
+	memset(&ac97_template, 0, sizeof(ac97_template_t));
+	ac97_template.private_data = aaci;
+	ac97_template.num = 0;
+	ac97_template.scaps = AC97_SCAP_SKIP_MODEM;
+
+	ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97);
+	if (ret)
+		goto out;
+
+	/*
+	 * Disable AC97 PC Beep input on audio codecs.
+	 */
+	if (ac97_is_audio(ac97))
+		snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x801e);
+
+	ret = snd_ac97_pcm_assign(ac97_bus, ARRAY_SIZE(ac97_defs), ac97_defs);
+	if (ret)
+		goto out;
+
+	aaci->playback.pcm = &ac97_bus->pcms[0];
+
+ out:
+	return ret;
+}
+
+static void aaci_free_card(snd_card_t *card)
+{
+	struct aaci *aaci = card->private_data;
+	if (aaci->base)
+		iounmap(aaci->base);
+}
+
+static struct aaci * __devinit aaci_init_card(struct amba_device *dev)
+{
+	struct aaci *aaci;
+	snd_card_t *card;
+
+	card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+			    THIS_MODULE, sizeof(struct aaci));
+	if (card == NULL)
+		return ERR_PTR(-ENOMEM);
+
+	card->private_free = aaci_free_card;
+	snd_card_set_pm_callback(card, aaci_do_suspend, aaci_do_resume, NULL);
+
+	strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver));
+	strlcpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname));
+	snprintf(card->longname, sizeof(card->longname),
+		 "%s at 0x%08lx, irq %d",
+		 card->shortname, dev->res.start, dev->irq[0]);
+
+	aaci = card->private_data;
+	init_MUTEX(&aaci->ac97_sem);
+	spin_lock_init(&aaci->lock);
+	aaci->card = card;
+	aaci->dev = dev;
+
+	/* Set MAINCR to allow slot 1 and 2 data IO */
+	aaci->maincr = MAINCR_IE | MAINCR_SL1RXEN | MAINCR_SL1TXEN |
+		       MAINCR_SL2RXEN | MAINCR_SL2TXEN;
+
+	return aaci;
+}
+
+static int __devinit aaci_init_pcm(struct aaci *aaci)
+{
+	snd_pcm_t *pcm;
+	int ret;
+
+	ret = snd_pcm_new(aaci->card, "AACI AC'97", 0, 1, 0, &pcm);
+	if (ret == 0) {
+		aaci->pcm = pcm;
+		pcm->private_data = aaci;
+		pcm->info_flags = 0;
+
+		strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));
+
+		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops);
+	}
+
+	return ret;
+}
+
+static unsigned int __devinit aaci_size_fifo(struct aaci *aaci)
+{
+	void *base = aaci->base + AACI_CSCH1;
+	int i;
+
+	writel(TXCR_FEN | TXCR_TSZ16 | TXCR_TXEN, base + AACI_TXCR);
+
+	for (i = 0; !(readl(base + AACI_SR) & SR_TXFF) && i < 4096; i++)
+		writel(0, aaci->base + AACI_DR1);
+
+	writel(0, base + AACI_TXCR);
+
+	/*
+	 * Re-initialise the AACI after the FIFO depth test, to
+	 * ensure that the FIFOs are empty.  Unfortunately, merely
+	 * disabling the channel doesn't clear the FIFO.
+	 */
+	writel(aaci->maincr & ~MAINCR_IE, aaci->base + AACI_MAINCR);
+	writel(aaci->maincr, aaci->base + AACI_MAINCR);
+
+	/*
+	 * If we hit 4096, we failed.  Go back to the specified
+	 * fifo depth.
+	 */
+	if (i == 4096)
+		i = 8;
+
+	return i;
+}
+
+static int __devinit aaci_probe(struct amba_device *dev, void *id)
+{
+	struct aaci *aaci;
+	int ret, i;
+
+	ret = amba_request_regions(dev, NULL);
+	if (ret)
+		return ret;
+
+	aaci = aaci_init_card(dev);
+	if (IS_ERR(aaci)) {
+		ret = PTR_ERR(aaci);
+		goto out;
+	}
+
+	aaci->base = ioremap(dev->res.start, SZ_4K);
+	if (!aaci->base) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/*
+	 * Playback uses AACI channel 0
+	 */
+	aaci->playback.base = aaci->base + AACI_CSCH1;
+	aaci->playback.fifo = aaci->base + AACI_DR1;
+
+	for (i = 0; i < 4; i++) {
+		void *base = aaci->base + i * 0x14;
+
+		writel(0, base + AACI_IE);
+		writel(0, base + AACI_TXCR);
+		writel(0, base + AACI_RXCR);
+	}
+
+	writel(0x1fff, aaci->base + AACI_INTCLR);
+	writel(aaci->maincr, aaci->base + AACI_MAINCR);
+
+	/*
+	 * Size the FIFOs.
+	 */
+	aaci->fifosize = aaci_size_fifo(aaci);
+
+	ret = aaci_probe_ac97(aaci);
+	if (ret)
+		goto out;
+
+	ret = aaci_init_pcm(aaci);
+	if (ret)
+		goto out;
+
+	ret = snd_card_register(aaci->card);
+	if (ret == 0) {
+		dev_info(&dev->dev, "%s, fifo %d\n", aaci->card->longname,
+			aaci->fifosize);
+		amba_set_drvdata(dev, aaci->card);
+		return ret;
+	}
+
+ out:
+	if (aaci)
+		snd_card_free(aaci->card);
+	amba_release_regions(dev);
+	return ret;
+}
+
+static int __devexit aaci_remove(struct amba_device *dev)
+{
+	snd_card_t *card = amba_get_drvdata(dev);
+
+	amba_set_drvdata(dev, NULL);
+
+	if (card) {
+		struct aaci *aaci = card->private_data;
+		writel(0, aaci->base + AACI_MAINCR);
+
+		snd_card_free(card);
+		amba_release_regions(dev);
+	}
+
+	return 0;
+}
+
+static struct amba_id aaci_ids[] = {
+	{
+		.id	= 0x00041041,
+		.mask	= 0x000fffff,
+	},
+	{ 0, 0 },
+};
+
+static struct amba_driver aaci_driver = {
+	.drv		= {
+		.name	= DRIVER_NAME,
+	},
+	.probe		= aaci_probe,
+	.remove		= __devexit_p(aaci_remove),
+	.suspend	= aaci_suspend,
+	.resume		= aaci_resume,
+	.id_table	= aaci_ids,
+};
+
+static int __init aaci_init(void)
+{
+	return amba_driver_register(&aaci_driver);
+}
+
+static void __exit aaci_exit(void)
+{
+	amba_driver_unregister(&aaci_driver);
+}
+
+module_init(aaci_init);
+module_exit(aaci_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ARM PrimeCell PL041 Advanced Audio CODEC Interface driver");
diff --git a/sound/arm/aaci.h b/sound/arm/aaci.h
new file mode 100644
index 0000000..d752e64
--- /dev/null
+++ b/sound/arm/aaci.h
@@ -0,0 +1,246 @@
+/*
+ *  linux/sound/arm/aaci.c - ARM PrimeCell AACI PL041 driver
+ *
+ *  Copyright (C) 2003 Deep Blue Solutions, Ltd, 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 version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef AACI_H
+#define AACI_H
+
+/*
+ * Control and status register offsets
+ *  P39.
+ */
+#define AACI_CSCH1	0x000
+#define AACI_CSCH2	0x014
+#define AACI_CSCH3	0x028
+#define AACI_CSCH4	0x03c
+
+#define AACI_RXCR	0x000	/* 29 bits Control Rx FIFO */
+#define AACI_TXCR	0x004	/* 17 bits Control Tx FIFO */
+#define AACI_SR		0x008	/* 12 bits Status */
+#define AACI_ISR	0x00c	/* 7 bits  Int Status */
+#define AACI_IE 	0x010	/* 7 bits  Int Enable */
+
+/*
+ * Other registers
+ */
+#define AACI_SL1RX	0x050
+#define AACI_SL1TX	0x054
+#define AACI_SL2RX	0x058
+#define AACI_SL2TX	0x05c
+#define AACI_SL12RX	0x060
+#define AACI_SL12TX	0x064
+#define AACI_SLFR	0x068	/* slot flags */
+#define AACI_SLISTAT	0x06c	/* slot interrupt status */
+#define AACI_SLIEN	0x070	/* slot interrupt enable */
+#define AACI_INTCLR	0x074	/* interrupt clear */
+#define AACI_MAINCR	0x078	/* main control */
+#define AACI_RESET	0x07c	/* reset control */
+#define AACI_SYNC	0x080	/* sync control */
+#define AACI_ALLINTS	0x084	/* all fifo interrupt status */
+#define AACI_MAINFR	0x088	/* main flag register */
+#define AACI_DR1	0x090	/* data read/written fifo 1 */
+#define AACI_DR2	0x0b0	/* data read/written fifo 2 */
+#define AACI_DR3	0x0d0	/* data read/written fifo 3 */
+#define AACI_DR4	0x0f0	/* data read/written fifo 4 */
+
+/*
+ * transmit fifo control register. P48
+ */
+#define TXCR_FEN	(1 << 16)	/* fifo enable */
+#define TXCR_COMPACT	(1 << 15)	/* compact mode */
+#define TXCR_TSZ16	(0 << 13)	/* 16 bits */
+#define TXCR_TSZ18	(1 << 13)	/* 18 bits */
+#define TXCR_TSZ20	(2 << 13)	/* 20 bits */
+#define TXCR_TSZ12	(3 << 13)	/* 12 bits */
+#define TXCR_TX12	(1 << 12)	/* transmits slot 12 */
+#define TXCR_TX11	(1 << 11)	/* transmits slot 12 */
+#define TXCR_TX10	(1 << 10)	/* transmits slot 12 */
+#define TXCR_TX9	(1 << 9)	/* transmits slot 12 */
+#define TXCR_TX8	(1 << 8)	/* transmits slot 12 */
+#define TXCR_TX7	(1 << 7)	/* transmits slot 12 */
+#define TXCR_TX6	(1 << 6)	/* transmits slot 12 */
+#define TXCR_TX5	(1 << 5)	/* transmits slot 12 */
+#define TXCR_TX4	(1 << 4)	/* transmits slot 12 */
+#define TXCR_TX3	(1 << 3)	/* transmits slot 12 */
+#define TXCR_TX2	(1 << 2)	/* transmits slot 12 */
+#define TXCR_TX1	(1 << 1)	/* transmits slot 12 */
+#define TXCR_TXEN	(1 << 0)	/* transmit enable */
+
+/*
+ * status register bits. P49
+ */
+#define SR_RXTOFE	(1 << 11)	/* rx timeout fifo empty */
+#define SR_TXTO		(1 << 10)	/* rx timeout fifo nonempty */
+#define SR_TXU		(1 << 9)	/* tx underrun */
+#define SR_RXO		(1 << 8)	/* rx overrun */
+#define SR_TXB		(1 << 7)	/* tx busy */
+#define SR_RXB		(1 << 6)	/* rx busy */
+#define SR_TXFF		(1 << 5)	/* tx fifo full */
+#define SR_RXFF		(1 << 4)	/* rx fifo full */
+#define SR_TXHE		(1 << 3)	/* tx fifo half empty */
+#define SR_RXHF		(1 << 2)	/* rx fifo half full */
+#define SR_TXFE		(1 << 1)	/* tx fifo empty */
+#define SR_RXFE		(1 << 0)	/* rx fifo empty */
+
+/*
+ * interrupt status register bits.
+ */
+#define ISR_RXTOFEINTR	(1 << 6)	/* rx fifo empty */
+#define ISR_URINTR	(1 << 5)	/* tx underflow */
+#define ISR_ORINTR	(1 << 4)	/* rx overflow */
+#define ISR_RXINTR	(1 << 3)	/* rx fifo */
+#define ISR_TXINTR	(1 << 2)	/* tx fifo intr */
+#define ISR_RXTOINTR	(1 << 1)	/* tx timeout */
+#define ISR_TXCINTR	(1 << 0)	/* tx complete */
+
+/*
+ * interrupt enable register bits.
+ */
+#define IE_RXTOIE	(1 << 6)
+#define IE_URIE		(1 << 5)
+#define IE_ORIE		(1 << 4)
+#define IE_RXIE		(1 << 3)
+#define IE_TXIE		(1 << 2)
+#define IE_RXTIE	(1 << 1)
+#define IE_TXCIE	(1 << 0)
+
+/*
+ * interrupt status. P51
+ */
+#define ISR_RXTOFE	(1 << 6)	/* rx timeout fifo empty */
+#define ISR_UR		(1 << 5)	/* tx fifo underrun */
+#define ISR_OR		(1 << 4)	/* rx fifo overrun */
+#define ISR_RX		(1 << 3)	/* rx interrupt status */
+#define ISR_TX		(1 << 2)	/* tx interrupt status */
+#define ISR_RXTO	(1 << 1)	/* rx timeout */
+#define ISR_TXC		(1 << 0)	/* tx complete */
+
+/*
+ * interrupt enable. P52
+ */
+#define IE_RXTOFE	(1 << 6)	/* rx timeout fifo empty */
+#define IE_UR		(1 << 5)	/* tx fifo underrun */
+#define IE_OR		(1 << 4)	/* rx fifo overrun */
+#define IE_RX		(1 << 3)	/* rx interrupt status */
+#define IE_TX		(1 << 2)	/* tx interrupt status */
+#define IE_RXTO		(1 << 1)	/* rx timeout */
+#define IE_TXC		(1 << 0)	/* tx complete */
+
+/*
+ * slot flag register bits. P56
+ */
+#define SLFR_RWIS	(1 << 13)	/* raw wake-up interrupt status */
+#define SLFR_RGPIOINTR	(1 << 12)	/* raw gpio interrupt */
+#define SLFR_12TXE	(1 << 11)	/* slot 12 tx empty */
+#define SLFR_12RXV	(1 << 10)	/* slot 12 rx valid */
+#define SLFR_2TXE	(1 << 9)	/* slot 2 tx empty */
+#define SLFR_2RXV	(1 << 8)	/* slot 2 rx valid */
+#define SLFR_1TXE	(1 << 7)	/* slot 1 tx empty */
+#define SLFR_1RXV	(1 << 6)	/* slot 1 rx valid */
+#define SLFR_12TXB	(1 << 5)	/* slot 12 tx busy */
+#define SLFR_12RXB	(1 << 4)	/* slot 12 rx busy */
+#define SLFR_2TXB	(1 << 3)	/* slot 2 tx busy */
+#define SLFR_2RXB	(1 << 2)	/* slot 2 rx busy */
+#define SLFR_1TXB	(1 << 1)	/* slot 1 tx busy */
+#define SLFR_1RXB	(1 << 0)	/* slot 1 rx busy */
+
+/*
+ * Interrupt clear register.
+ */
+#define ICLR_RXTOFEC4	(1 << 12)
+#define ICLR_RXTOFEC3	(1 << 11)
+#define ICLR_RXTOFEC2	(1 << 10)
+#define ICLR_RXTOFEC1	(1 << 9)
+#define ICLR_TXUEC4	(1 << 8)
+#define ICLR_TXUEC3	(1 << 7)
+#define ICLR_TXUEC2	(1 << 6)
+#define ICLR_TXUEC1	(1 << 5)
+#define ICLR_RXOEC4	(1 << 4)
+#define ICLR_RXOEC3	(1 << 3)
+#define ICLR_RXOEC2	(1 << 2)
+#define ICLR_RXOEC1	(1 << 1)
+#define ICLR_WISC	(1 << 0)
+
+/*
+ * Main control register bits. P62
+ */
+#define MAINCR_SCRA(x)	((x) << 10)	/* secondary codec reg access */
+#define MAINCR_DMAEN	(1 << 9)	/* dma enable */
+#define MAINCR_SL12TXEN	(1 << 8)	/* slot 12 transmit enable */
+#define MAINCR_SL12RXEN	(1 << 7)	/* slot 12 receive enable */
+#define MAINCR_SL2TXEN	(1 << 6)	/* slot 2 transmit enable */
+#define MAINCR_SL2RXEN	(1 << 5)	/* slot 2 receive enable */
+#define MAINCR_SL1TXEN	(1 << 4)	/* slot 1 transmit enable */
+#define MAINCR_SL1RXEN	(1 << 3)	/* slot 1 receive enable */
+#define MAINCR_LPM	(1 << 2)	/* low power mode */
+#define MAINCR_LOOPBK	(1 << 1)	/* loopback */
+#define MAINCR_IE	(1 << 0)	/* aaci interface enable */
+
+/*
+ * Reset register bits. P65
+ */
+#define RESET_NRST	(1 << 0)
+
+/*
+ * Sync register bits. P65
+ */
+#define SYNC_FORCE	(1 << 0)
+
+/*
+ * Main flag register bits. P66
+ */
+#define MAINFR_TXB	(1 << 1)	/* transmit busy */
+#define MAINFR_RXB	(1 << 0)	/* receive busy */
+
+
+
+struct aaci_runtime {
+	void			*base;
+	void			*fifo;
+
+	struct ac97_pcm		*pcm;
+	int			pcm_open;
+
+	u32			cr;
+	snd_pcm_substream_t	*substream;
+
+	/*
+	 * PIO support
+	 */
+	void			*start;
+	void			*end;
+	void			*ptr;
+	int			bytes;
+	unsigned int		period;
+	unsigned int		fifosz;
+};
+
+struct aaci {
+	struct amba_device	*dev;
+	snd_card_t		*card;
+	void			*base;
+	unsigned int		fifosize;
+
+	/* AC'97 */
+	struct semaphore	ac97_sem;
+	ac97_bus_t		*ac97_bus;
+
+	u32			maincr;
+	spinlock_t		lock;
+
+	struct aaci_runtime	playback;
+	struct aaci_runtime	capture;
+
+	snd_pcm_t		*pcm;
+};
+
+#define ACSTREAM_FRONT		0
+#define ACSTREAM_SURROUND	1
+#define ACSTREAM_LFE		2
+
+#endif
diff --git a/sound/arm/devdma.c b/sound/arm/devdma.c
new file mode 100644
index 0000000..60826a5
--- /dev/null
+++ b/sound/arm/devdma.c
@@ -0,0 +1,81 @@
+/*
+ *  linux/sound/arm/devdma.c
+ *
+ *  Copyright (C) 2003-2004 Russell King, 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 version 2 as
+ * published by the Free Software Foundation.
+ *
+ *  ARM DMA shim for ALSA.
+ */
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+
+#include "devdma.h"
+
+void devdma_hw_free(struct device *dev, snd_pcm_substream_t *substream)
+{
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	struct snd_dma_buffer *buf = runtime->dma_buffer_p;
+
+	if (runtime->dma_area == NULL)
+		return;
+
+	if (buf != &substream->dma_buffer) {
+		dma_free_coherent(buf->dev.dev, buf->bytes, buf->area, buf->addr);
+		kfree(runtime->dma_buffer_p);
+	}
+
+	snd_pcm_set_runtime_buffer(substream, NULL);
+}
+
+int devdma_hw_alloc(struct device *dev, snd_pcm_substream_t *substream, size_t size)
+{
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	struct snd_dma_buffer *buf = runtime->dma_buffer_p;
+	int ret = 0;
+
+	if (buf) {
+		if (buf->bytes >= size)
+			goto out;
+		devdma_hw_free(dev, substream);
+	}
+
+	if (substream->dma_buffer.area != NULL && substream->dma_buffer.bytes >= size) {
+		buf = &substream->dma_buffer;
+	} else {
+		buf = kmalloc(sizeof(struct snd_dma_buffer), GFP_KERNEL);
+		if (!buf)
+			goto nomem;
+
+		buf->dev.type = SNDRV_DMA_TYPE_DEV;
+		buf->dev.dev = dev;
+		buf->area = dma_alloc_coherent(dev, size, &buf->addr, GFP_KERNEL);
+		buf->bytes = size;
+		buf->private_data = NULL;
+
+		if (!buf->area)
+			goto free;
+	}
+	snd_pcm_set_runtime_buffer(substream, buf);
+	ret = 1;
+ out:
+	runtime->dma_bytes = size;
+	return ret;
+
+ free:
+	kfree(buf);
+ nomem:
+	return -ENOMEM;
+}
+
+int devdma_mmap(struct device *dev, snd_pcm_substream_t *substream, struct vm_area_struct *vma)
+{
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	return dma_mmap_coherent(dev, vma, runtime->dma_area, runtime->dma_addr, runtime->dma_bytes);
+}
diff --git a/sound/arm/devdma.h b/sound/arm/devdma.h
new file mode 100644
index 0000000..5a33b6b
--- /dev/null
+++ b/sound/arm/devdma.h
@@ -0,0 +1,3 @@
+void devdma_hw_free(struct device *dev, snd_pcm_substream_t *substream);
+int devdma_hw_alloc(struct device *dev, snd_pcm_substream_t *substream, size_t size);
+int devdma_mmap(struct device *dev, snd_pcm_substream_t *substream, struct vm_area_struct *vma);
diff --git a/sound/core/control.c b/sound/core/control.c
index f4ea6bf..227f3cf 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -215,7 +215,7 @@
  *
  * Returns the pointer of the newly generated instance, or NULL on failure.
  */
-snd_kcontrol_t *snd_ctl_new1(snd_kcontrol_new_t * ncontrol, void *private_data)
+snd_kcontrol_t *snd_ctl_new1(const snd_kcontrol_new_t * ncontrol, void *private_data)
 {
 	snd_kcontrol_t kctl;
 	unsigned int access;
@@ -1102,7 +1102,7 @@
 		}
 	}
 	up_read(&snd_ioctl_rwsem);
-	snd_printd("unknown ioctl = 0x%x\n", cmd);
+	snd_printdd("unknown ioctl = 0x%x\n", cmd);
 	return -ENOTTY;
 }
 
diff --git a/sound/core/info.c b/sound/core/info.c
index 31faffe..5e122bb 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -24,6 +24,7 @@
 #include <linux/vmalloc.h>
 #include <linux/time.h>
 #include <linux/smp_lock.h>
+#include <linux/string.h>
 #include <sound/core.h>
 #include <sound/minors.h>
 #include <sound/info.h>
@@ -754,7 +755,7 @@
 	entry = kcalloc(1, sizeof(*entry), GFP_KERNEL);
 	if (entry == NULL)
 		return NULL;
-	entry->name = snd_kmalloc_strdup(name, GFP_KERNEL);
+	entry->name = kstrdup(name, GFP_KERNEL);
 	if (entry->name == NULL) {
 		kfree(entry);
 		return NULL;
diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c
index f9e4ce4..1210796 100644
--- a/sound/core/info_oss.c
+++ b/sound/core/info_oss.c
@@ -22,6 +22,7 @@
 #include <sound/driver.h>
 #include <linux/slab.h>
 #include <linux/time.h>
+#include <linux/string.h>
 #include <sound/core.h>
 #include <sound/minors.h>
 #include <sound/info.h>
@@ -51,7 +52,7 @@
 			x = NULL;
 		}
 	} else {
-		x = snd_kmalloc_strdup(string, GFP_KERNEL);
+		x = kstrdup(string, GFP_KERNEL);
 		if (x == NULL) {
 			up(&strings);
 			return -ENOMEM;
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index 344a83f..dbc23e3 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -28,6 +28,7 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
+#include <asm/uaccess.h>
 #include <linux/dma-mapping.h>
 #include <linux/moduleparam.h>
 #include <asm/semaphore.h>
@@ -46,13 +47,6 @@
 #define SNDRV_CARDS	8
 #endif
 
-/* FIXME: so far only some PCI devices have the preallocation table */
-#ifdef CONFIG_PCI
-static int enable[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};
-module_param_array(enable, bool, NULL, 0444);
-MODULE_PARM_DESC(enable, "Enable cards to allocate buffers.");
-#endif
-
 /*
  */
 
@@ -451,9 +445,13 @@
 	list_for_each(p, &mem_list_head) {
 		mem = list_entry(p, struct snd_mem_list, list);
 		if (mem->id == id &&
-		    ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev))) {
+		    (mem->buffer.dev.dev == NULL || dmab->dev.dev == NULL ||
+		     ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev)))) {
+			struct device *dev = dmab->dev.dev;
 			list_del(p);
 			*dmab = mem->buffer;
+			if (dmab->dev.dev == NULL)
+				dmab->dev.dev = dev;
 			kfree(mem);
 			up(&list_mutex);
 			return dmab->bytes;
@@ -508,91 +506,13 @@
 }
 
 
-
-/*
- * allocation of buffers for pre-defined devices
- */
-
-#ifdef CONFIG_PCI
-/* FIXME: for pci only - other bus? */
-struct prealloc_dev {
-	unsigned short vendor;
-	unsigned short device;
-	unsigned long dma_mask;
-	unsigned int size;
-	unsigned int buffers;
-};
-
-#define HAMMERFALL_BUFFER_SIZE    (16*1024*4*(26+1)+0x10000)
-
-static struct prealloc_dev prealloc_devices[] __initdata = {
-	{
-		/* hammerfall */
-		.vendor = 0x10ee,
-		.device = 0x3fc4,
-		.dma_mask = 0xffffffff,
-		.size = HAMMERFALL_BUFFER_SIZE,
-		.buffers = 2
-	},
-	{
-		/* HDSP */
-		.vendor = 0x10ee,
-		.device = 0x3fc5,
-		.dma_mask = 0xffffffff,
-		.size = HAMMERFALL_BUFFER_SIZE,
-		.buffers = 2
-	},
-	{ }, /* terminator */
-};
-
-static void __init preallocate_cards(void)
-{
-	struct pci_dev *pci = NULL;
-	int card;
-
-	card = 0;
-
-	while ((pci = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pci)) != NULL) {
-		struct prealloc_dev *dev;
-		unsigned int i;
-		if (card >= SNDRV_CARDS)
-			break;
-		for (dev = prealloc_devices; dev->vendor; dev++) {
-			if (dev->vendor == pci->vendor && dev->device == pci->device)
-				break;
-		}
-		if (! dev->vendor)
-			continue;
-		if (! enable[card++]) {
-			printk(KERN_DEBUG "snd-page-alloc: skipping card %d, device %04x:%04x\n", card, pci->vendor, pci->device);
-			continue;
-		}
-			
-		if (pci_set_dma_mask(pci, dev->dma_mask) < 0 ||
-		    pci_set_consistent_dma_mask(pci, dev->dma_mask) < 0) {
-			printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", dev->dma_mask, dev->vendor, dev->device);
-			continue;
-		}
-		for (i = 0; i < dev->buffers; i++) {
-			struct snd_dma_buffer dmab;
-			memset(&dmab, 0, sizeof(dmab));
-			if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
-						dev->size, &dmab) < 0)
-				printk(KERN_WARNING "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", dev->size);
-			else
-				snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci));
-		}
-	}
-}
-#else
-#define preallocate_cards()	/* NOP */
-#endif
-
-
 #ifdef CONFIG_PROC_FS
 /*
  * proc file interface
  */
+#define SND_MEM_PROC_FILE	"driver/snd-page-alloc"
+struct proc_dir_entry *snd_mem_proc;
+
 static int snd_mem_proc_read(char *page, char **start, off_t off,
 			     int count, int *eof, void *data)
 {
@@ -621,6 +541,97 @@
 	up(&list_mutex);
 	return len;
 }
+
+/* FIXME: for pci only - other bus? */
+#ifdef CONFIG_PCI
+#define gettoken(bufp) strsep(bufp, " \t\n")
+
+static int snd_mem_proc_write(struct file *file, const char __user *buffer,
+			      unsigned long count, void *data)
+{
+	char buf[128];
+	char *token, *p;
+
+	if (count > ARRAY_SIZE(buf) - 1)
+		count = ARRAY_SIZE(buf) - 1;
+	if (copy_from_user(buf, buffer, count))
+		return -EFAULT;
+	buf[ARRAY_SIZE(buf) - 1] = '\0';
+
+	p = buf;
+	token = gettoken(&p);
+	if (! token || *token == '#')
+		return (int)count;
+	if (strcmp(token, "add") == 0) {
+		char *endp;
+		int vendor, device, size, buffers;
+		long mask;
+		int i, alloced;
+		struct pci_dev *pci;
+
+		if ((token = gettoken(&p)) == NULL ||
+		    (vendor = simple_strtol(token, NULL, 0)) <= 0 ||
+		    (token = gettoken(&p)) == NULL ||
+		    (device = simple_strtol(token, NULL, 0)) <= 0 ||
+		    (token = gettoken(&p)) == NULL ||
+		    (mask = simple_strtol(token, NULL, 0)) < 0 ||
+		    (token = gettoken(&p)) == NULL ||
+		    (size = memparse(token, &endp)) < 64*1024 ||
+		    size > 16*1024*1024 /* too big */ ||
+		    (token = gettoken(&p)) == NULL ||
+		    (buffers = simple_strtol(token, NULL, 0)) <= 0 ||
+		    buffers > 4) {
+			printk(KERN_ERR "snd-page-alloc: invalid proc write format\n");
+			return (int)count;
+		}
+		vendor &= 0xffff;
+		device &= 0xffff;
+
+		alloced = 0;
+		pci = NULL;
+		while ((pci = pci_find_device(vendor, device, pci)) != NULL) {
+			if (mask > 0 && mask < 0xffffffff) {
+				if (pci_set_dma_mask(pci, mask) < 0 ||
+				    pci_set_consistent_dma_mask(pci, mask) < 0) {
+					printk(KERN_ERR "snd-page-alloc: cannot set DMA mask %lx for pci %04x:%04x\n", mask, vendor, device);
+					return (int)count;
+				}
+			}
+			for (i = 0; i < buffers; i++) {
+				struct snd_dma_buffer dmab;
+				memset(&dmab, 0, sizeof(dmab));
+				if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+							size, &dmab) < 0) {
+					printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
+					return (int)count;
+				}
+				snd_dma_reserve_buf(&dmab, snd_dma_pci_buf_id(pci));
+			}
+			alloced++;
+		}
+		if (! alloced) {
+			for (i = 0; i < buffers; i++) {
+				struct snd_dma_buffer dmab;
+				memset(&dmab, 0, sizeof(dmab));
+				/* FIXME: We can allocate only in ZONE_DMA
+				 * without a device pointer!
+				 */
+				if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, NULL,
+							size, &dmab) < 0) {
+					printk(KERN_ERR "snd-page-alloc: cannot allocate buffer pages (size = %d)\n", size);
+					break;
+				}
+				snd_dma_reserve_buf(&dmab, (unsigned int)((vendor << 16) | device));
+			}
+		}
+	} else if (strcmp(token, "erase") == 0)
+		/* FIXME: need for releasing each buffer chunk? */
+		free_all_reserved_pages();
+	else
+		printk(KERN_ERR "snd-page-alloc: invalid proc cmd\n");
+	return (int)count;
+}
+#endif /* CONFIG_PCI */
 #endif /* CONFIG_PROC_FS */
 
 /*
@@ -630,15 +641,21 @@
 static int __init snd_mem_init(void)
 {
 #ifdef CONFIG_PROC_FS
-	create_proc_read_entry("driver/snd-page-alloc", 0, NULL, snd_mem_proc_read, NULL);
+	snd_mem_proc = create_proc_entry(SND_MEM_PROC_FILE, 0644, NULL);
+	if (snd_mem_proc) {
+		snd_mem_proc->read_proc = snd_mem_proc_read;
+#ifdef CONFIG_PCI
+		snd_mem_proc->write_proc = snd_mem_proc_write;
 #endif
-	preallocate_cards();
+	}
+#endif
 	return 0;
 }
 
 static void __exit snd_mem_exit(void)
 {
-	remove_proc_entry("driver/snd-page-alloc", NULL);
+	if (snd_mem_proc)
+		remove_proc_entry(SND_MEM_PROC_FILE, NULL);
 	free_all_reserved_pages();
 	if (snd_allocated_pages > 0)
 		printk(KERN_ERR "snd-malloc: Memory leak?  pages not freed = %li\n", snd_allocated_pages);
diff --git a/sound/core/memory.c b/sound/core/memory.c
index 20860fe..c1fb28e 100644
--- a/sound/core/memory.c
+++ b/sound/core/memory.c
@@ -184,6 +184,20 @@
 	snd_wrapper_vfree(obj);
 }
 
+char *snd_hidden_kstrdup(const char *s, int flags)
+{
+	int len;
+	char *buf;
+
+	if (!s) return NULL;
+
+	len = strlen(s) + 1;
+	buf = _snd_kmalloc(len, flags);
+	if (buf)
+		memcpy(buf, s, len);
+	return buf;
+}
+
 static void snd_memory_info_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer)
 {
 	snd_iprintf(buffer, "kmalloc: %li bytes\n", snd_alloc_kmalloc);
@@ -214,36 +228,9 @@
 	return 0;
 }
 
-#else
-
-#define _snd_kmalloc kmalloc
-
 #endif /* CONFIG_SND_DEBUG_MEMORY */
 
 /**
- * snd_kmalloc_strdup - copy the string
- * @string: the original string
- * @flags: allocation conditions, GFP_XXX
- *
- * Allocates a memory chunk via kmalloc() and copies the string to it.
- *
- * Returns the pointer, or NULL if no enoguh memory.
- */
-char *snd_kmalloc_strdup(const char *string, int flags)
-{
-	size_t len;
-	char *ptr;
-
-	if (!string)
-		return NULL;
-	len = strlen(string) + 1;
-	ptr = _snd_kmalloc(len, flags);
-	if (ptr)
-		memcpy(ptr, string, len);
-	return ptr;
-}
-
-/**
  * copy_to_user_fromio - copy data from mmio-space to user-space
  * @dst: the destination pointer on user-space
  * @src: the source pointer on mmio
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index 98ed9a9..98fc076 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -24,6 +24,7 @@
 #include <linux/smp_lock.h>
 #include <linux/slab.h>
 #include <linux/time.h>
+#include <linux/string.h>
 #include <sound/core.h>
 #include <sound/minors.h>
 #include <sound/control.h>
@@ -1137,7 +1138,7 @@
 			goto __unlock;
 		}
 		tbl->oss_id = ch;
-		tbl->name = snd_kmalloc_strdup(str, GFP_KERNEL);
+		tbl->name = kstrdup(str, GFP_KERNEL);
 		if (! tbl->name) {
 			kfree(tbl);
 			goto __unlock;
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 1a80502..de7444c 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -33,6 +33,7 @@
 #include <linux/time.h>
 #include <linux/vmalloc.h>
 #include <linux/moduleparam.h>
+#include <linux/string.h>
 #include <sound/core.h>
 #include <sound/minors.h>
 #include <sound/pcm.h>
@@ -125,17 +126,26 @@
 static long snd_pcm_oss_bytes(snd_pcm_substream_t *substream, long frames)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_pcm_uframes_t buffer_size = snd_pcm_lib_buffer_bytes(substream);
-	frames = frames_to_bytes(runtime, frames);
+	long buffer_size = snd_pcm_lib_buffer_bytes(substream);
+	long bytes = frames_to_bytes(runtime, frames);
 	if (buffer_size == runtime->oss.buffer_bytes)
-		return frames;
-	return (runtime->oss.buffer_bytes * frames) / buffer_size;
+		return bytes;
+#if BITS_PER_LONG >= 64
+	return runtime->oss.buffer_bytes * bytes / buffer_size;
+#else
+	{
+		u64 bsize = (u64)runtime->oss.buffer_bytes * (u64)bytes;
+		u32 rem;
+		div64_32(&bsize, buffer_size, &rem);
+		return (long)bsize;
+	}
+#endif
 }
 
 static long snd_pcm_alsa_frames(snd_pcm_substream_t *substream, long bytes)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_pcm_uframes_t buffer_size = snd_pcm_lib_buffer_bytes(substream);
+	long buffer_size = snd_pcm_lib_buffer_bytes(substream);
 	if (buffer_size == runtime->oss.buffer_bytes)
 		return bytes_to_frames(runtime, bytes);
 	return bytes_to_frames(runtime, (buffer_size * bytes) / runtime->oss.buffer_bytes);
@@ -464,7 +474,8 @@
 	sw_params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
 	sw_params->period_step = 1;
 	sw_params->sleep_min = 0;
-	sw_params->avail_min = 1;
+	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) ||
 	    (substream->oss.setup && substream->oss.setup->nosilence)) {
@@ -1527,12 +1538,15 @@
 			snd_pcm_oss_simulate_fill(substream, delay);
 		info.bytes = snd_pcm_oss_bytes(substream, runtime->status->hw_ptr) & INT_MAX;
 	} else {
-		delay = snd_pcm_oss_bytes(substream, delay) + fixup;
-		info.blocks = delay / runtime->oss.period_bytes;
-		if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+		delay = snd_pcm_oss_bytes(substream, delay);
+		if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+			info.blocks = (runtime->oss.buffer_bytes - delay - fixup) / runtime->oss.period_bytes;
 			info.bytes = (runtime->oss.bytes - delay) & INT_MAX;
-		else
+		} else {
+			delay += fixup;
+			info.blocks = delay / runtime->oss.period_bytes;
 			info.bytes = (runtime->oss.bytes + delay) & INT_MAX;
+		}
 	}
 	if (copy_to_user(_info, &info, sizeof(info)))
 		return -EFAULT;
@@ -2347,7 +2361,7 @@
 					for (setup1 = pstr->oss.setup_list; setup1->next; setup1 = setup1->next);
 					setup1->next = setup;
 				}
-				template.task_name = snd_kmalloc_strdup(task_name, GFP_KERNEL);
+				template.task_name = kstrdup(task_name, GFP_KERNEL);
 			} else {
 				buffer->error = -ENOMEM;
 			}
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
index 6bb3100..6430410 100644
--- a/sound/core/oss/pcm_plugin.c
+++ b/sound/core/oss/pcm_plugin.c
@@ -663,10 +663,7 @@
 		bitset_t *dstmask = bs;
 		int err;
 		bitset_one(dstmask, schannels);
-		if (plugin == NULL) {
-			bitset_and(client_vmask, dstmask, schannels);
-			return 0;
-		}
+
 		while (1) {
 			err = plugin->src_channels_mask(plugin, dstmask, &srcmask);
 			if (err < 0)
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 8d94325..9f4c920 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -451,6 +451,7 @@
 		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;
 		if (snd_info_register(entry) < 0) {
 			snd_info_free_entry(entry);
@@ -1048,7 +1049,6 @@
 EXPORT_SYMBOL(snd_pcm_format_name);
   /* pcm_native.c */
 EXPORT_SYMBOL(snd_pcm_link_rwlock);
-EXPORT_SYMBOL(snd_pcm_start);
 #ifdef CONFIG_PM
 EXPORT_SYMBOL(snd_pcm_suspend);
 EXPORT_SYMBOL(snd_pcm_suspend_all);
@@ -1068,6 +1068,7 @@
 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);
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 151fd99..c5bfd09 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1143,7 +1143,8 @@
 #define INT_MIN ((int)((unsigned int)INT_MAX+1))
 #endif
 
-void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params, snd_pcm_hw_param_t var)
+static void _snd_pcm_hw_param_any(snd_pcm_hw_params_t *params,
+				  snd_pcm_hw_param_t var)
 {
 	if (hw_is_mask(var)) {
 		snd_mask_any(hw_param_mask(params, var));
@@ -1160,6 +1161,7 @@
 	snd_BUG();
 }
 
+#if 0
 /**
  * snd_pcm_hw_param_any
  */
@@ -1169,6 +1171,7 @@
 	_snd_pcm_hw_param_any(params, var);
 	return snd_pcm_hw_refine(pcm, params);
 }
+#endif  /*  0  */
 
 void _snd_pcm_hw_params_any(snd_pcm_hw_params_t *params)
 {
@@ -1181,6 +1184,7 @@
 	params->info = ~0U;
 }
 
+#if 0
 /**
  * snd_pcm_hw_params_any
  *
@@ -1191,6 +1195,7 @@
 	_snd_pcm_hw_params_any(params);
 	return snd_pcm_hw_refine(pcm, params);
 }
+#endif  /*  0  */
 
 /**
  * snd_pcm_hw_param_value
@@ -1198,8 +1203,8 @@
  * Return the value for field PAR if it's fixed in configuration space 
  *  defined by PARAMS. Return -EINVAL otherwise
  */
-int snd_pcm_hw_param_value(const snd_pcm_hw_params_t *params,
-			   snd_pcm_hw_param_t var, int *dir)
+static int snd_pcm_hw_param_value(const snd_pcm_hw_params_t *params,
+				  snd_pcm_hw_param_t var, int *dir)
 {
 	if (hw_is_mask(var)) {
 		const snd_mask_t *mask = hw_param_mask_c(params, var);
@@ -1296,6 +1301,7 @@
 	return changed;
 }
 	
+#if 0
 /**
  * snd_pcm_hw_param_setinteger
  *
@@ -1317,9 +1323,10 @@
 	}
 	return 0;
 }
+#endif  /*  0  */
 
-int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params,
-			    snd_pcm_hw_param_t var)
+static int _snd_pcm_hw_param_first(snd_pcm_hw_params_t *params,
+				   snd_pcm_hw_param_t var)
 {
 	int changed;
 	if (hw_is_mask(var))
@@ -1345,9 +1352,9 @@
  * values > minimum. Reduce configuration space accordingly.
  * Return the minimum.
  */
-int snd_pcm_hw_param_first(snd_pcm_t *pcm, 
-			   snd_pcm_hw_params_t *params, 
-			   snd_pcm_hw_param_t var, int *dir)
+static int snd_pcm_hw_param_first(snd_pcm_t *pcm, 
+				  snd_pcm_hw_params_t *params, 
+				  snd_pcm_hw_param_t var, int *dir)
 {
 	int changed = _snd_pcm_hw_param_first(params, var);
 	if (changed < 0)
@@ -1359,8 +1366,8 @@
 	return snd_pcm_hw_param_value(params, var, dir);
 }
 
-int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params,
-			   snd_pcm_hw_param_t var)
+static int _snd_pcm_hw_param_last(snd_pcm_hw_params_t *params,
+				  snd_pcm_hw_param_t var)
 {
 	int changed;
 	if (hw_is_mask(var))
@@ -1386,9 +1393,9 @@
  * values < maximum. Reduce configuration space accordingly.
  * Return the maximum.
  */
-int snd_pcm_hw_param_last(snd_pcm_t *pcm, 
-			  snd_pcm_hw_params_t *params,
-			  snd_pcm_hw_param_t var, int *dir)
+static int snd_pcm_hw_param_last(snd_pcm_t *pcm, 
+				 snd_pcm_hw_params_t *params,
+				 snd_pcm_hw_param_t var, int *dir)
 {
 	int changed = _snd_pcm_hw_param_last(params, var);
 	if (changed < 0)
@@ -1437,8 +1444,9 @@
  * values < VAL. Reduce configuration space accordingly.
  * Return new minimum or -EINVAL if the configuration space is empty
  */
-int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
-			 snd_pcm_hw_param_t var, unsigned int val, int *dir)
+static int snd_pcm_hw_param_min(snd_pcm_t *pcm, snd_pcm_hw_params_t *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)
@@ -1451,8 +1459,9 @@
 	return snd_pcm_hw_param_value_min(params, var, dir);
 }
 
-int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params,
-			   snd_pcm_hw_param_t var, unsigned int val, int dir)
+static int _snd_pcm_hw_param_max(snd_pcm_hw_params_t *params,
+				 snd_pcm_hw_param_t var, unsigned int val,
+				 int dir)
 {
 	int changed;
 	int open = 0;
@@ -1490,8 +1499,9 @@
  *  values >= VAL + 1. Reduce configuration space accordingly.
  *  Return new maximum or -EINVAL if the configuration space is empty
  */
-int snd_pcm_hw_param_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *params,
-			  snd_pcm_hw_param_t var, unsigned int val, int *dir)
+static int snd_pcm_hw_param_max(snd_pcm_t *pcm, snd_pcm_hw_params_t *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)
@@ -2564,9 +2574,6 @@
 EXPORT_SYMBOL(snd_interval_refine);
 EXPORT_SYMBOL(snd_interval_list);
 EXPORT_SYMBOL(snd_interval_ratnum);
-EXPORT_SYMBOL(snd_interval_muldivk);
-EXPORT_SYMBOL(snd_interval_mulkdiv);
-EXPORT_SYMBOL(snd_interval_div);
 EXPORT_SYMBOL(_snd_pcm_hw_params_any);
 EXPORT_SYMBOL(_snd_pcm_hw_param_min);
 EXPORT_SYMBOL(_snd_pcm_hw_param_set);
@@ -2580,7 +2587,6 @@
 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_params);
 EXPORT_SYMBOL(snd_pcm_hw_constraints_init);
 EXPORT_SYMBOL(snd_pcm_hw_constraints_complete);
 EXPORT_SYMBOL(snd_pcm_hw_constraint_list);
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index f1d5f7a..9a174fb 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -204,6 +204,7 @@
 		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;
 		if (snd_info_register(entry) < 0) {
 			snd_info_free_entry(entry);
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
index 422b8db..1453743 100644
--- a/sound/core/pcm_misc.c
+++ b/sound/core/pcm_misc.c
@@ -270,22 +270,6 @@
 }
 
 /**
- * snd_pcm_format_cpu_endian - Check the PCM format is CPU-endian
- * @format: the format to check
- *
- * Returns 1 if the given PCM format is CPU-endian, 0 if
- * opposite, or a negative error code if endian not specified.
- */
-int snd_pcm_format_cpu_endian(snd_pcm_format_t format)
-{
-#ifdef SNDRV_LITTLE_ENDIAN
-	return snd_pcm_format_little_endian(format);
-#else
-	return snd_pcm_format_big_endian(format);
-#endif
-}
-
-/**
  * snd_pcm_format_width - return the bit-width of the format
  * @format: the format to check
  *
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index cad9bbd..10c2c98 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -337,8 +337,8 @@
 	return err;
 }
 
-int snd_pcm_hw_params(snd_pcm_substream_t *substream,
-		      snd_pcm_hw_params_t *params)
+static int snd_pcm_hw_params(snd_pcm_substream_t *substream,
+			     snd_pcm_hw_params_t *params)
 {
 	snd_pcm_runtime_t *runtime;
 	int err;
@@ -1368,43 +1368,32 @@
 	if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
 		return -EBADFD;
 
-	down_read(&snd_pcm_link_rwsem);
 	snd_power_lock(card);
 	if (runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
 		result = snd_power_wait(card, SNDRV_CTL_POWER_D0, substream->ffile);
-		if (result < 0)
-			goto _unlock;
+		if (result < 0) {
+			snd_power_unlock(card);
+			return result;
+		}
 	}
 
 	/* allocate temporary record for drain sync */
+	down_read(&snd_pcm_link_rwsem);
 	if (snd_pcm_stream_linked(substream)) {
 		drec = kmalloc(substream->group->count * sizeof(*drec), GFP_KERNEL);
 		if (! drec) {
-			result = -ENOMEM;
-			goto _unlock;
+			up_read(&snd_pcm_link_rwsem);
+			snd_power_unlock(card);
+			return -ENOMEM;
 		}
 	} else
 		drec = &drec_tmp;
 
-	snd_pcm_stream_lock_irq(substream);
-	/* resume pause */
-	if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
-		snd_pcm_pause(substream, 0);
-
-	/* pre-start/stop - all running streams are changed to DRAINING state */
-	result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0);
-	if (result < 0)
-		goto _end;
-
-	/* check streams with PLAYBACK & DRAINING */
+	/* count only playback streams */
 	num_drecs = 0;
 	snd_pcm_group_for_each(pos, substream) {
 		snd_pcm_substream_t *s = snd_pcm_group_substream_entry(pos);
 		runtime = s->runtime;
-		if (runtime->status->state != SNDRV_PCM_STATE_DRAINING) {
-			runtime->status->state = SNDRV_PCM_STATE_SETUP;
-			continue;
-		}
 		if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {
 			d = &drec[num_drecs++];
 			d->substream = s;
@@ -1418,9 +1407,21 @@
 				runtime->stop_threshold = runtime->buffer_size;
 		}
 	}
-
+	up_read(&snd_pcm_link_rwsem);
 	if (! num_drecs)
-		goto _end;
+		goto _error;
+
+	snd_pcm_stream_lock_irq(substream);
+	/* resume pause */
+	if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
+		snd_pcm_pause(substream, 0);
+
+	/* pre-start/stop - all running streams are changed to DRAINING state */
+	result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0);
+	if (result < 0) {
+		snd_pcm_stream_unlock_irq(substream);
+		goto _error;
+	}
 
 	for (;;) {
 		long tout;
@@ -1428,6 +1429,15 @@
 			result = -ERESTARTSYS;
 			break;
 		}
+		/* all finished? */
+		for (i = 0; i < num_drecs; i++) {
+			runtime = drec[i].substream->runtime;
+			if (runtime->status->state == SNDRV_PCM_STATE_DRAINING)
+				break;
+		}
+		if (i == num_drecs)
+			break; /* yes, all drained */
+
 		set_current_state(TASK_INTERRUPTIBLE);
 		snd_pcm_stream_unlock_irq(substream);
 		snd_power_unlock(card);
@@ -1444,15 +1454,11 @@
 			}
 			break;
 		}
-		/* all finished? */
-		for (i = 0; i < num_drecs; i++) {
-			runtime = drec[i].substream->runtime;
-			if (runtime->status->state == SNDRV_PCM_STATE_DRAINING)
-				break;
-		}
-		if (i == num_drecs)
-			break;
 	}
+
+	snd_pcm_stream_unlock_irq(substream);
+
+ _error:
 	for (i = 0; i < num_drecs; i++) {
 		d = &drec[i];
 		runtime = d->substream->runtime;
@@ -1460,13 +1466,9 @@
 		runtime->stop_threshold = d->stop_threshold;
 	}
 
- _end:
-	snd_pcm_stream_unlock_irq(substream);
 	if (drec != &drec_tmp)
 		kfree(drec);
- _unlock:
 	snd_power_unlock(card);
-	up_read(&snd_pcm_link_rwsem);
 
 	return result;
 }
diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
index 638cc14..1a7736c 100644
--- a/sound/core/seq/oss/seq_oss_synth.c
+++ b/sound/core/seq/oss/seq_oss_synth.c
@@ -325,14 +325,10 @@
 			}
 			snd_use_lock_free(&rec->use_lock);
 		}
-		if (info->sysex) {
-			kfree(info->sysex);
-			info->sysex = NULL;
-		}
-		if (info->ch) {
-			kfree(info->ch);
-			info->ch = NULL;
-		}
+		kfree(info->sysex);
+		info->sysex = NULL;
+		kfree(info->ch);
+		info->ch = NULL;
 	}
 	dp->synth_opened = 0;
 	dp->max_synthdev = 0;
@@ -418,14 +414,10 @@
 					  dp->file_mode) < 0) {
 			midi_synth_dev.opened--;
 			info->opened = 0;
-			if (info->sysex) {
-				kfree(info->sysex);
-				info->sysex = NULL;
-			}
-			if (info->ch) {
-				kfree(info->ch);
-				info->ch = NULL;
-			}
+			kfree(info->sysex);
+			info->sysex = NULL;
+			kfree(info->ch);
+			info->ch = NULL;
 		}
 		return;
 	}
diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
index e88967c..ea945a5 100644
--- a/sound/core/seq/seq_dummy.c
+++ b/sound/core/seq/seq_dummy.c
@@ -140,10 +140,7 @@
 static void
 dummy_free(void *private_data)
 {
-	snd_seq_dummy_port_t *p;
-
-	p = private_data;
-	kfree(p);
+	kfree(private_data);
 }
 
 /*
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
index 18247db..57be915 100644
--- a/sound/core/seq/seq_midi.c
+++ b/sound/core/seq/seq_midi.c
@@ -414,6 +414,8 @@
 	if (newclient)
 		synths[card->number] = client;
 	up(&register_mutex);
+	kfree(info);
+	kfree(port);
 	return 0;	/* success */
 
       __nomem:
diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c
index 21e5690..df1e2bb 100644
--- a/sound/core/seq/seq_midi_event.c
+++ b/sound/core/seq/seq_midi_event.c
@@ -171,11 +171,13 @@
 	spin_unlock_irqrestore(&dev->lock, flags);
 }
 
+#if 0
 void snd_midi_event_init(snd_midi_event_t *dev)
 {
 	snd_midi_event_reset_encode(dev);
 	snd_midi_event_reset_decode(dev);
 }
+#endif  /*  0  */
 
 void snd_midi_event_no_status(snd_midi_event_t *dev, int on)
 {
@@ -185,6 +187,7 @@
 /*
  * resize buffer
  */
+#if 0
 int snd_midi_event_resize_buffer(snd_midi_event_t *dev, int bufsize)
 {
 	unsigned char *new_buf, *old_buf;
@@ -204,6 +207,7 @@
 	kfree(old_buf);
 	return 0;
 }
+#endif  /*  0  */
 
 /*
  *  read bytes and encode to sequencer event if finished
@@ -517,8 +521,6 @@
  
 EXPORT_SYMBOL(snd_midi_event_new);
 EXPORT_SYMBOL(snd_midi_event_free);
-EXPORT_SYMBOL(snd_midi_event_resize_buffer);
-EXPORT_SYMBOL(snd_midi_event_init);
 EXPORT_SYMBOL(snd_midi_event_reset_encode);
 EXPORT_SYMBOL(snd_midi_event_reset_decode);
 EXPORT_SYMBOL(snd_midi_event_no_status);
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index 3afc7cc0..98de2e7 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -672,7 +672,8 @@
  * process a received queue-control event.
  * this function is exported for seq_sync.c.
  */
-void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int atomic, int hop)
+static void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev,
+					int atomic, int hop)
 {
 	switch (ev->type) {
 	case SNDRV_SEQ_EVENT_START:
diff --git a/sound/core/seq/seq_queue.h b/sound/core/seq/seq_queue.h
index b1bf551..ea3c542 100644
--- a/sound/core/seq/seq_queue.h
+++ b/sound/core/seq/seq_queue.h
@@ -111,7 +111,6 @@
 int snd_seq_queue_is_used(int queueid, int client);
 
 int snd_seq_control_queue(snd_seq_event_t *ev, int atomic, int hop);
-void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int atomic, int hop);
 
 /*
  * 64bit division - for sync stuff..
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c
index 753f1c0..a7f76fc 100644
--- a/sound/core/seq/seq_timer.c
+++ b/sound/core/seq/seq_timer.c
@@ -36,7 +36,8 @@
 
 #define SKEW_BASE	0x10000	/* 16bit shift */
 
-void snd_seq_timer_set_tick_resolution(seq_timer_tick_t *tick, int tempo, int ppq, int nticks)
+static void snd_seq_timer_set_tick_resolution(seq_timer_tick_t *tick,
+					      int tempo, int ppq, int nticks)
 {
 	if (tempo < 1000000)
 		tick->resolution = (tempo * 1000) / ppq;
diff --git a/sound/core/seq/seq_timer.h b/sound/core/seq/seq_timer.h
index 4c0872d..287ed68 100644
--- a/sound/core/seq/seq_timer.h
+++ b/sound/core/seq/seq_timer.h
@@ -64,8 +64,6 @@
 /* delete timer (destructor) */
 extern void snd_seq_timer_delete(seq_timer_t **tmr);
 
-void snd_seq_timer_set_tick_resolution(seq_timer_tick_t *tick, int tempo, int ppq, int nticks);
-
 /* */
 static inline void snd_seq_timer_update_tick(seq_timer_tick_t *tick, unsigned long resolution)
 {
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index 6b4e630..a66484b5 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -110,7 +110,7 @@
  * handler of a remote port which is attached to the virmidi via
  * SNDRV_VIRMIDI_SEQ_ATTACH.
  */
-/* exported */
+#if 0
 int snd_virmidi_receive(snd_rawmidi_t *rmidi, snd_seq_event_t *ev)
 {
 	snd_virmidi_dev_t *rdev;
@@ -118,6 +118,7 @@
 	rdev = rmidi->private_data;
 	return snd_virmidi_dev_receive_event(rdev, ev);
 }
+#endif  /*  0  */
 
 /*
  * event handler of virmidi port
@@ -384,7 +385,7 @@
 	info->client = client;
 	info->type = KERNEL_CLIENT;
 	sprintf(info->name, "%s %d-%d", rdev->rmidi->name, rdev->card->number, rdev->device);
-	snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &info);
+	snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, info);
 
 	/* create a port */
 	memset(pinfo, 0, sizeof(*pinfo));
@@ -405,7 +406,7 @@
 	pcallbacks.unuse = snd_virmidi_unuse;
 	pcallbacks.event_input = snd_virmidi_event_input;
 	pinfo->kernel = &pcallbacks;
-	err = snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, &pinfo);
+	err = snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, pinfo);
 	if (err < 0) {
 		snd_seq_delete_kernel_client(client);
 		rdev->client = -1;
@@ -548,4 +549,3 @@
 module_exit(alsa_virmidi_exit)
 
 EXPORT_SYMBOL(snd_virmidi_new);
-EXPORT_SYMBOL(snd_virmidi_receive);
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 88e0520..7612884 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -64,7 +64,7 @@
 
 static DECLARE_MUTEX(sound_mutex);
 
-extern struct class_simple *sound_class;
+extern struct class *sound_class;
 
 
 #ifdef CONFIG_KMOD
@@ -231,7 +231,7 @@
 		devfs_mk_cdev(MKDEV(major, minor), S_IFCHR | device_mode, "snd/%s", name);
 	if (card)
 		device = card->dev;
-	class_simple_device_add(sound_class, MKDEV(major, minor), device, name);
+	class_device_create(sound_class, MKDEV(major, minor), device, "%s", name);
 
 	up(&sound_mutex);
 	return 0;
@@ -263,7 +263,7 @@
 
 	if (strncmp(mptr->name, "controlC", 8) || card->number >= cards_limit) /* created in sound.c */
 		devfs_remove("snd/%s", mptr->name);
-	class_simple_device_remove(MKDEV(major, minor));
+	class_device_destroy(sound_class, MKDEV(major, minor));
 
 	list_del(&mptr->list);
 	up(&sound_mutex);
@@ -399,8 +399,8 @@
 EXPORT_SYMBOL(snd_hidden_kfree);
 EXPORT_SYMBOL(snd_hidden_vmalloc);
 EXPORT_SYMBOL(snd_hidden_vfree);
+EXPORT_SYMBOL(snd_hidden_kstrdup);
 #endif
-EXPORT_SYMBOL(snd_kmalloc_strdup);
 EXPORT_SYMBOL(copy_to_user_fromio);
 EXPORT_SYMBOL(copy_from_user_toio);
   /* init.c */
@@ -431,7 +431,6 @@
 EXPORT_SYMBOL(snd_device_new);
 EXPORT_SYMBOL(snd_device_register);
 EXPORT_SYMBOL(snd_device_free);
-EXPORT_SYMBOL(snd_device_free_all);
   /* isadma.c */
 #ifdef CONFIG_ISA
 EXPORT_SYMBOL(snd_dma_program);
diff --git a/sound/core/timer.c b/sound/core/timer.c
index fa762ca..cfaccd4 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -26,6 +26,7 @@
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/moduleparam.h>
+#include <linux/string.h>
 #include <sound/core.h>
 #include <sound/timer.h>
 #include <sound/control.h>
@@ -69,6 +70,7 @@
 	struct timespec tstamp;		/* trigger tstamp */
 	wait_queue_head_t qchange_sleep;
 	struct fasync_struct *fasync;
+	struct semaphore tread_sem;
 } snd_timer_user_t;
 
 /* list of timers */
@@ -99,7 +101,7 @@
 	timeri = kcalloc(1, sizeof(*timeri), GFP_KERNEL);
 	if (timeri == NULL)
 		return NULL;
-	timeri->owner = snd_kmalloc_strdup(owner, GFP_KERNEL);
+	timeri->owner = kstrdup(owner, GFP_KERNEL);
 	if (! timeri->owner) {
 		kfree(timeri);
 		return NULL;
@@ -844,7 +846,7 @@
 	return 0;
 }
 
-int snd_timer_unregister(snd_timer_t *timer)
+static int snd_timer_unregister(snd_timer_t *timer)
 {
 	struct list_head *p, *n;
 	snd_timer_instance_t *ti;
@@ -945,11 +947,6 @@
 	unsigned long correction;
 };
 
-unsigned int snd_timer_system_resolution(void)
-{
-	return 1000000000L / HZ;
-}
-
 static void snd_timer_s_function(unsigned long data)
 {
 	snd_timer_t *timer = (snd_timer_t *)data;
@@ -1208,6 +1205,7 @@
 		return -ENOMEM;
 	spin_lock_init(&tu->qlock);
 	init_waitqueue_head(&tu->qchange_sleep);
+	init_MUTEX(&tu->tread_sem);
 	tu->ticks = 1;
 	tu->queue_size = 128;
 	tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL);
@@ -1454,46 +1452,51 @@
 	snd_timer_user_t *tu;
 	snd_timer_select_t tselect;
 	char str[32];
-	int err;
+	int err = 0;
 	
 	tu = file->private_data;
-	if (tu->timeri)
+	down(&tu->tread_sem);
+	if (tu->timeri) {
 		snd_timer_close(tu->timeri);
-	if (copy_from_user(&tselect, _tselect, sizeof(tselect)))
-		return -EFAULT;
+		tu->timeri = NULL;
+	}
+	if (copy_from_user(&tselect, _tselect, sizeof(tselect))) {
+		err = -EFAULT;
+		goto __err;
+	}
 	sprintf(str, "application %i", current->pid);
 	if (tselect.id.dev_class != SNDRV_TIMER_CLASS_SLAVE)
 		tselect.id.dev_sclass = SNDRV_TIMER_SCLASS_APPLICATION;
 	if ((err = snd_timer_open(&tu->timeri, str, &tselect.id, current->pid)) < 0)
-		return err;
+		goto __err;
 
-	if (tu->queue) {
-		kfree(tu->queue);
-		tu->queue = NULL;
-	}
-	if (tu->tqueue) {
-		kfree(tu->tqueue);
-		tu->tqueue = NULL;
-	}
+	kfree(tu->queue);
+	tu->queue = NULL;
+	kfree(tu->tqueue);
+	tu->tqueue = NULL;
 	if (tu->tread) {
 		tu->tqueue = (snd_timer_tread_t *)kmalloc(tu->queue_size * sizeof(snd_timer_tread_t), GFP_KERNEL);
-		if (tu->tqueue == NULL) {
-			snd_timer_close(tu->timeri);
-			return -ENOMEM;
-		}
+		if (tu->tqueue == NULL)
+			err = -ENOMEM;
 	} else {
 		tu->queue = (snd_timer_read_t *)kmalloc(tu->queue_size * sizeof(snd_timer_read_t), GFP_KERNEL);
-		if (tu->queue == NULL) {
-			snd_timer_close(tu->timeri);
-			return -ENOMEM;
-		}
+		if (tu->queue == NULL)
+			err = -ENOMEM;
 	}
 	
-	tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST;
-	tu->timeri->callback = tu->tread ? snd_timer_user_tinterrupt : snd_timer_user_interrupt;
-	tu->timeri->ccallback = snd_timer_user_ccallback;
-	tu->timeri->callback_data = (void *)tu;
-	return 0;
+      	if (err < 0) {
+		snd_timer_close(tu->timeri);
+      		tu->timeri = NULL;
+      	} else {
+		tu->timeri->flags |= SNDRV_TIMER_IFLG_FAST;
+		tu->timeri->callback = tu->tread ? snd_timer_user_tinterrupt : snd_timer_user_interrupt;
+		tu->timeri->ccallback = snd_timer_user_ccallback;
+		tu->timeri->callback_data = (void *)tu;
+	}
+
+      __err:
+      	up(&tu->tread_sem);
+	return err;
 }
 
 static int snd_timer_user_info(struct file *file, snd_timer_info_t __user *_info)
@@ -1669,6 +1672,23 @@
 	return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0;
 }
 
+static int snd_timer_user_pause(struct file *file)
+{
+	int err;
+	snd_timer_user_t *tu;
+		
+	tu = file->private_data;
+	snd_assert(tu->timeri != NULL, return -ENXIO);
+	return (err = snd_timer_pause(tu->timeri)) < 0 ? err : 0;
+}
+
+enum {
+	SNDRV_TIMER_IOCTL_START_OLD = _IO('T', 0x20),
+	SNDRV_TIMER_IOCTL_STOP_OLD = _IO('T', 0x21),
+	SNDRV_TIMER_IOCTL_CONTINUE_OLD = _IO('T', 0x22),
+	SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23),
+};
+
 static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	snd_timer_user_t *tu;
@@ -1685,11 +1705,17 @@
 	{
 		int xarg;
 		
-		if (tu->timeri)		/* too late */
+		down(&tu->tread_sem);
+		if (tu->timeri)	{	/* too late */
+			up(&tu->tread_sem);
 			return -EBUSY;
-		if (get_user(xarg, p))
+		}
+		if (get_user(xarg, p)) {
+			up(&tu->tread_sem);
 			return -EFAULT;
+		}
 		tu->tread = xarg ? 1 : 0;
+		up(&tu->tread_sem);
 		return 0;
 	}
 	case SNDRV_TIMER_IOCTL_GINFO:
@@ -1707,11 +1733,17 @@
 	case SNDRV_TIMER_IOCTL_STATUS:
 		return snd_timer_user_status(file, argp);
 	case SNDRV_TIMER_IOCTL_START:
+	case SNDRV_TIMER_IOCTL_START_OLD:
 		return snd_timer_user_start(file);
 	case SNDRV_TIMER_IOCTL_STOP:
+	case SNDRV_TIMER_IOCTL_STOP_OLD:
 		return snd_timer_user_stop(file);
 	case SNDRV_TIMER_IOCTL_CONTINUE:
+	case SNDRV_TIMER_IOCTL_CONTINUE_OLD:
 		return snd_timer_user_continue(file);
+	case SNDRV_TIMER_IOCTL_PAUSE:
+	case SNDRV_TIMER_IOCTL_PAUSE_OLD:
+		return snd_timer_user_pause(file);
 	}
 	return -ENOTTY;
 }
@@ -1898,4 +1930,3 @@
 EXPORT_SYMBOL(snd_timer_global_register);
 EXPORT_SYMBOL(snd_timer_global_unregister);
 EXPORT_SYMBOL(snd_timer_interrupt);
-EXPORT_SYMBOL(snd_timer_system_resolution);
diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c
index 9fbc395..3de552d 100644
--- a/sound/core/timer_compat.c
+++ b/sound/core/timer_compat.c
@@ -106,8 +106,13 @@
 	case SNDRV_TIMER_IOCTL_SELECT:
 	case SNDRV_TIMER_IOCTL_PARAMS:
 	case SNDRV_TIMER_IOCTL_START:
+	case SNDRV_TIMER_IOCTL_START_OLD:
 	case SNDRV_TIMER_IOCTL_STOP:
+	case SNDRV_TIMER_IOCTL_STOP_OLD:
 	case SNDRV_TIMER_IOCTL_CONTINUE:
+	case SNDRV_TIMER_IOCTL_CONTINUE_OLD:
+	case SNDRV_TIMER_IOCTL_PAUSE:
+	case SNDRV_TIMER_IOCTL_PAUSE_OLD:
 	case SNDRV_TIMER_IOCTL_NEXT_DEVICE:
 		return snd_timer_user_ioctl(file, cmd, (unsigned long)argp);
 	case SNDRV_TIMER_IOCTL_INFO32:
diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c
index 9858717..af381b1 100644
--- a/sound/drivers/vx/vx_pcm.c
+++ b/sound/drivers/vx/vx_pcm.c
@@ -1264,14 +1264,10 @@
 {
 	vx_core_t *chip = pcm->private_data;
 	chip->pcm[pcm->device] = NULL;
-	if (chip->playback_pipes) {
-		kfree(chip->playback_pipes);
-		chip->playback_pipes = NULL;
-	}
-	if (chip->capture_pipes) {
-		kfree(chip->capture_pipes);
-		chip->capture_pipes = NULL;
-	}
+	kfree(chip->playback_pipes);
+	chip->playback_pipes = NULL;
+	kfree(chip->capture_pipes);
+	chip->capture_pipes = NULL;
 }
 
 /*
diff --git a/sound/i2c/tea6330t.c b/sound/i2c/tea6330t.c
index bb503e7..2da8d7f 100644
--- a/sound/i2c/tea6330t.c
+++ b/sound/i2c/tea6330t.c
@@ -266,8 +266,7 @@
 
 static void snd_tea6330_free(snd_i2c_device_t *device)
 {
-	tea6330t_t *tea = device->private_data;
-	kfree(tea);
+	kfree(device->private_data);
 }
                                         
 int snd_tea6330t_update_mixer(snd_card_t * card,
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index 3a3228b..148a856 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -179,6 +179,7 @@
 	select SND_RAWMIDI
 	select SND_CS4231_LIB
 	select SND_GUS_SYNTH
+	select ISAPNP
 	help
 	  Say Y here to include support for AMD InterWave based
 	  soundcards with a TEA6330T bass and treble regulator
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c
index 9fa7a78..563296d 100644
--- a/sound/isa/ad1816a/ad1816a.c
+++ b/sound/isa/ad1816a/ad1816a.c
@@ -83,6 +83,8 @@
 static struct pnp_card_device_id snd_ad1816a_pnpids[] = {
 	/* Analog Devices AD1815 */
 	{ .id = "ADS7150", .devs = { { .id = "ADS7150" }, { .id = "ADS7151" } } },
+	/* Analog Device AD1816? */
+	{ .id = "ADS7180", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
 	/* Analog Devices AD1816A - added by Kenneth Platz <kxp@atl.hp.com> */
 	{ .id = "ADS7181", .devs = { { .id = "ADS7180" }, { .id = "ADS7181" } } },
 	/* Analog Devices AD1816A - Aztech/Newcom SC-16 3D */
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index e745a54..39f4eff 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -349,8 +349,7 @@
 		pnp_init_resource_table(cfg);
 		if (mpu_port[dev] != SNDRV_AUTO_PORT)
 			pnp_resource_change(&cfg->port_resource[0], mpu_port[dev], 2);
-		if (mpu_irq[dev] != SNDRV_AUTO_IRQ && mpu_irq[dev] >= 0 &&
-		    pnp_irq_valid(pdev, 0))
+		if (mpu_irq[dev] != SNDRV_AUTO_IRQ && mpu_irq[dev] >= 0)
 			pnp_resource_change(&cfg->irq_resource[0], mpu_irq[dev], 1);
 		err = pnp_manual_config_dev(pdev, cfg, 0);
 		if (err < 0)
diff --git a/sound/isa/gus/gus_io.c b/sound/isa/gus/gus_io.c
index f0570f2..337b0e2 100644
--- a/sound/isa/gus/gus_io.c
+++ b/sound/isa/gus/gus_io.c
@@ -244,6 +244,8 @@
 	return res;
 }
 
+#if 0
+
 void snd_gf1_i_adlib_write(snd_gus_card_t * gus,
 		           unsigned char reg,
 		           unsigned char data)
@@ -265,6 +267,8 @@
 	spin_unlock_irqrestore(&gus->reg_lock, flags);
 }
 
+#endif  /*  0  */
+
 unsigned int snd_gf1_i_read_addr(snd_gus_card_t * gus,
 				 unsigned char reg, short w_16bit)
 {
@@ -329,6 +333,8 @@
 	return res;
 }
 
+#if 0
+
 void snd_gf1_pokew(snd_gus_card_t * gus, unsigned int addr, unsigned short data)
 {
 	unsigned long flags;
@@ -405,9 +411,7 @@
 	spin_unlock_irqrestore(&gus->reg_lock, flags);
 }
 
-/*
-
- */
+#endif  /*  0  */
 
 void snd_gf1_select_active_voices(snd_gus_card_t * gus)
 {
@@ -469,6 +473,8 @@
 		printk(" -%i- GF1  pan                    = 0x%x\n", voice, snd_gf1_i_read8(gus, 0x0c));
 }
 
+#if 0
+
 void snd_gf1_print_global_registers(snd_gus_card_t * gus)
 {
 	unsigned char global_mode = 0x00;
@@ -528,4 +534,6 @@
 	}
 }
 
+#endif  /*  0  */
+
 #endif
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
index 73f81c1..94bbd34 100644
--- a/sound/isa/gus/gus_main.c
+++ b/sound/isa/gus/gus_main.c
@@ -459,7 +459,6 @@
 EXPORT_SYMBOL(snd_gf1_look16);
 EXPORT_SYMBOL(snd_gf1_i_write8);
 EXPORT_SYMBOL(snd_gf1_i_look8);
-EXPORT_SYMBOL(snd_gf1_i_write16);
 EXPORT_SYMBOL(snd_gf1_i_look16);
 EXPORT_SYMBOL(snd_gf1_dram_addr);
 EXPORT_SYMBOL(snd_gf1_write_addr);
@@ -470,8 +469,6 @@
 EXPORT_SYMBOL(snd_gf1_free_voice);
 EXPORT_SYMBOL(snd_gf1_ctrl_stop);
 EXPORT_SYMBOL(snd_gf1_stop_voice);
-EXPORT_SYMBOL(snd_gf1_start);
-EXPORT_SYMBOL(snd_gf1_stop);
   /* gus_mixer.c */
 EXPORT_SYMBOL(snd_gf1_new_mixer);
   /* gus_pcm.c */
diff --git a/sound/isa/gus/gus_mem.c b/sound/isa/gus/gus_mem.c
index bfc2b91..5eb766d 100644
--- a/sound/isa/gus/gus_mem.c
+++ b/sound/isa/gus/gus_mem.c
@@ -21,6 +21,7 @@
 
 #include <sound/driver.h>
 #include <linux/slab.h>
+#include <linux/string.h>
 #include <sound/core.h>
 #include <sound/gus.h>
 #include <sound/info.h>
@@ -39,8 +40,8 @@
 	}
 }
 
-snd_gf1_mem_block_t *snd_gf1_mem_xalloc(snd_gf1_mem_t * alloc,
-				        snd_gf1_mem_block_t * block)
+static snd_gf1_mem_block_t *snd_gf1_mem_xalloc(snd_gf1_mem_t * alloc,
+					       snd_gf1_mem_block_t * block)
 {
 	snd_gf1_mem_block_t *pblock, *nblock;
 
@@ -105,8 +106,8 @@
 	return 0;
 }
 
-snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc,
-				      unsigned int address)
+static snd_gf1_mem_block_t *snd_gf1_mem_look(snd_gf1_mem_t * alloc,
+					     unsigned int address)
 {
 	snd_gf1_mem_block_t *block;
 
@@ -118,8 +119,8 @@
 	return NULL;
 }
 
-snd_gf1_mem_block_t *snd_gf1_mem_share(snd_gf1_mem_t * alloc,
-				       unsigned int *share_id)
+static snd_gf1_mem_block_t *snd_gf1_mem_share(snd_gf1_mem_t * alloc,
+					      unsigned int *share_id)
 {
 	snd_gf1_mem_block_t *block;
 
@@ -213,7 +214,7 @@
 	if (share_id != NULL)
 		memcpy(&block.share_id, share_id, sizeof(block.share_id));
 	block.owner = owner;
-	block.name = snd_kmalloc_strdup(name, GFP_KERNEL);
+	block.name = kstrdup(name, GFP_KERNEL);
 	nblock = snd_gf1_mem_xalloc(alloc, &block);
 	snd_gf1_mem_lock(alloc, 1);
 	return nblock;
@@ -253,13 +254,13 @@
 	if (gus->gf1.enh_mode) {
 		block.ptr = 0;
 		block.size = 1024;
-		block.name = snd_kmalloc_strdup("InterWave LFOs", GFP_KERNEL);
+		block.name = kstrdup("InterWave LFOs", GFP_KERNEL);
 		if (snd_gf1_mem_xalloc(alloc, &block) == NULL)
 			return -ENOMEM;
 	}
 	block.ptr = gus->gf1.default_voice_address;
 	block.size = 4;
-	block.name = snd_kmalloc_strdup("Voice default (NULL's)", GFP_KERNEL);
+	block.name = kstrdup("Voice default (NULL's)", GFP_KERNEL);
 	if (snd_gf1_mem_xalloc(alloc, &block) == NULL)
 		return -ENOMEM;
 #ifdef CONFIG_SND_DEBUG
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c
index 8995ad9..b75066a 100644
--- a/sound/isa/gus/gus_pcm.c
+++ b/sound/isa/gus/gus_pcm.c
@@ -656,8 +656,7 @@
 
 static void snd_gf1_pcm_playback_free(snd_pcm_runtime_t *runtime)
 {
-	gus_pcm_private_t * pcmp = runtime->private_data;
-	kfree(pcmp);
+	kfree(runtime->private_data);
 }
 
 static int snd_gf1_pcm_playback_open(snd_pcm_substream_t *substream)
diff --git a/sound/isa/gus/gus_reset.c b/sound/isa/gus/gus_reset.c
index b4e66f6..ef687ab 100644
--- a/sound/isa/gus/gus_reset.c
+++ b/sound/isa/gus/gus_reset.c
@@ -161,7 +161,8 @@
 #endif
 }
 
-void snd_gf1_clear_voices(snd_gus_card_t * gus, unsigned short v_min, unsigned short v_max)
+static void snd_gf1_clear_voices(snd_gus_card_t * gus, unsigned short v_min,
+				 unsigned short v_max)
 {
 	unsigned long flags;
 	unsigned int daddr;
diff --git a/sound/isa/gus/gus_synth.c b/sound/isa/gus/gus_synth.c
index 66552e6..f51c386 100644
--- a/sound/isa/gus/gus_synth.c
+++ b/sound/isa/gus/gus_synth.c
@@ -99,7 +99,8 @@
 	snd_seq_instr_list_free_cond(p->gus->gf1.ilist, &ifree, client, 0);
 }
  
-int snd_gus_synth_event_input(snd_seq_event_t *ev, int direct, void *private_data, int atomic, int hop)
+static int snd_gus_synth_event_input(snd_seq_event_t *ev, int direct,
+				     void *private_data, int atomic, int hop)
 {
 	snd_gus_port_t * p = (snd_gus_port_t *) private_data;
 	
diff --git a/sound/isa/gus/gus_tables.h b/sound/isa/gus/gus_tables.h
index ed8e9d8..4adf098 100644
--- a/sound/isa/gus/gus_tables.h
+++ b/sound/isa/gus/gus_tables.h
@@ -23,6 +23,8 @@
 
 #ifdef __GUS_TABLES_ALLOC__
 
+#if 0
+
 unsigned int snd_gf1_scale_table[SNDRV_GF1_SCALE_TABLE_SIZE] =
 {
       8372,      8870,      9397,      9956,     10548,     11175,
@@ -49,6 +51,8 @@
   12123977,  12844906
 };
 
+#endif  /*  0  */
+
 unsigned short snd_gf1_atten_table[SNDRV_GF1_ATTEN_TABLE_SIZE] = {
   4095 /* 0   */,1789 /* 1   */,1533 /* 2   */,1383 /* 3   */,1277 /* 4   */,
   1195 /* 5   */,1127 /* 6   */,1070 /* 7   */,1021 /* 8   */,978  /* 9   */,
diff --git a/sound/isa/gus/gus_volume.c b/sound/isa/gus/gus_volume.c
index b72bcfb..3d36f6c 100644
--- a/sound/isa/gus/gus_volume.c
+++ b/sound/isa/gus/gus_volume.c
@@ -55,6 +55,8 @@
 	return (e << 8) | m;
 }
 
+#if 0
+
 unsigned int snd_gf1_gvol_to_lvol_raw(unsigned short gf1_vol)
 {
 	unsigned int rvol;
@@ -108,6 +110,8 @@
 	return (range << 6) | (increment & 0x3f);
 }
 
+#endif  /*  0  */
+
 unsigned short snd_gf1_translate_freq(snd_gus_card_t * gus, unsigned int freq16)
 {
 	freq16 >>= 3;
@@ -120,6 +124,8 @@
 	return ((freq16 << 9) + (gus->gf1.playback_freq >> 1)) / gus->gf1.playback_freq;
 }
 
+#if 0
+
 short snd_gf1_compute_vibrato(short cents, unsigned short fc_register)
 {
 	static short vibrato_table[] =
@@ -208,3 +214,5 @@
 	}
 	return (unsigned short) fc;
 }
+
+#endif  /*  0  */
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index 33e2808..7bd95ce 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -6,7 +6,7 @@
 # Prompt user for primary drivers.
 config SOUND_BT878
 	tristate "BT878 audio dma"
-	depends on SOUND_PRIME!=n && SOUND
+	depends on SOUND_PRIME
 	---help---
 	  Audio DMA support for bt878 based grabber boards.  As you might have
 	  already noticed, bt878 is listed with two functions in /proc/pci.
@@ -22,7 +22,7 @@
 
 config SOUND_CMPCI
 	tristate "C-Media PCI (CMI8338/8738)"
-	depends on SOUND_PRIME!=n && SOUND && PCI
+	depends on SOUND_PRIME && PCI
 	help
 	  Say Y or M if you have a PCI sound card using the CMI8338
 	  or the CMI8738 chipset.  Data on these chips are available at
@@ -61,7 +61,7 @@
 
 config SOUND_EMU10K1
 	tristate "Creative SBLive! (EMU10K1)"
-	depends on SOUND_PRIME!=n && SOUND && PCI
+	depends on SOUND_PRIME && PCI
 	---help---
 	  Say Y or M if you have a PCI sound card using the EMU10K1 chipset,
 	  such as the Creative SBLive!, SB PCI512 or Emu-APS.
@@ -87,7 +87,7 @@
 
 config SOUND_FUSION
 	tristate "Crystal SoundFusion (CS4280/461x)"
-	depends on SOUND_PRIME!=n && SOUND
+	depends on SOUND_PRIME
 	help
 	  This module drives the Crystal SoundFusion devices (CS4280/46xx
 	  series) when wired as native sound drivers with AC97 codecs.  If
@@ -95,14 +95,14 @@
 
 config SOUND_CS4281
 	tristate "Crystal Sound CS4281"
-	depends on SOUND_PRIME!=n && SOUND
+	depends on SOUND_PRIME
 	help
 	  Picture and feature list at
 	  <http://www.pcbroker.com/crystal4281.html>.
 
 config SOUND_BCM_CS4297A
 	tristate "Crystal Sound CS4297a (for Swarm)"
-	depends on SOUND_PRIME!=n && SIBYTE_SWARM && SOUND
+	depends on SOUND_PRIME && SIBYTE_SWARM
 	help
 	  The BCM91250A has a Crystal CS4297a on synchronous serial
 	  port B (in addition to the DB-9 serial port).  Say Y or M
@@ -112,7 +112,7 @@
 
 config SOUND_ES1370
 	tristate "Ensoniq AudioPCI (ES1370)"
-	depends on SOUND_PRIME!=n && SOUND && PCI
+	depends on SOUND_PRIME && PCI
 	help
 	  Say Y or M if you have a PCI sound card utilizing the Ensoniq
 	  ES1370 chipset, such as Ensoniq's AudioPCI (non-97). To find
@@ -125,7 +125,7 @@
 
 config SOUND_ES1371
 	tristate "Creative Ensoniq AudioPCI 97 (ES1371)"
-	depends on SOUND_PRIME!=n && SOUND && PCI
+	depends on SOUND_PRIME && PCI
 	help
 	  Say Y or M if you have a PCI sound card utilizing the Ensoniq
 	  ES1371 chipset, such as Ensoniq's AudioPCI97. To find out if
@@ -138,7 +138,7 @@
 
 config SOUND_ESSSOLO1
 	tristate "ESS Technology Solo1" 
-	depends on SOUND_PRIME!=n && SOUND && PCI
+	depends on SOUND_PRIME && PCI
 	help
 	  Say Y or M if you have a PCI sound card utilizing the ESS Technology
 	  Solo1 chip. To find out if your sound card uses a
@@ -149,7 +149,7 @@
 
 config SOUND_MAESTRO
 	tristate "ESS Maestro, Maestro2, Maestro2E driver"
-	depends on SOUND_PRIME!=n && SOUND && PCI
+	depends on SOUND_PRIME && PCI
 	help
 	  Say Y or M if you have a sound system driven by ESS's Maestro line
 	  of PCI sound chips.  These include the Maestro 1, Maestro 2, and
@@ -158,28 +158,28 @@
 
 config SOUND_MAESTRO3
 	tristate "ESS Maestro3/Allegro driver (EXPERIMENTAL)"
-	depends on SOUND_PRIME!=n && SOUND && PCI && EXPERIMENTAL
+	depends on SOUND_PRIME && PCI && EXPERIMENTAL
 	help
 	  Say Y or M if you have a sound system driven by ESS's Maestro 3
 	  PCI sound chip.
 
 config SOUND_ICH
 	tristate "Intel ICH (i8xx) audio support"
-	depends on SOUND_PRIME!=n && PCI
+	depends on SOUND_PRIME && PCI
 	help
 	  Support for integral audio in Intel's I/O Controller Hub (ICH)
 	  chipset, as used on the 810/820/840 motherboards.
 
 config SOUND_HARMONY
 	tristate "PA Harmony audio driver"
-	depends on GSC_LASI && SOUND_PRIME!=n
+	depends on GSC_LASI && SOUND_PRIME
 	help
 	  Say 'Y' or 'M' to include support for Harmony soundchip
 	  on HP 712, 715/new and many other GSC based machines.
 
 config SOUND_SONICVIBES
 	tristate "S3 SonicVibes"
-	depends on SOUND_PRIME!=n && SOUND
+	depends on SOUND_PRIME
 	help
 	  Say Y or M if you have a PCI sound card utilizing the S3
 	  SonicVibes chipset. To find out if your sound card uses a
@@ -190,7 +190,7 @@
 
 config SOUND_VWSND
 	tristate "SGI Visual Workstation Sound"
-	depends on SOUND_PRIME!=n && X86_VISWS && SOUND
+	depends on SOUND_PRIME && X86_VISWS
 	help
 	  Say Y or M if you have an SGI Visual Workstation and you want to be
 	  able to use its on-board audio.  Read
@@ -199,18 +199,18 @@
 
 config SOUND_HAL2
 	tristate "SGI HAL2 sound (EXPERIMENTAL)"
-	depends on SOUND_PRIME!=n && SOUND && SGI_IP22 && 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.
 
 config SOUND_IT8172
 	tristate "IT8172G Sound"
-	depends on SOUND_PRIME!=n && (MIPS_ITE8172 || MIPS_IVR) && SOUND
+	depends on SOUND_PRIME && (MIPS_ITE8172 || MIPS_IVR)
 
 config SOUND_VRC5477
 	tristate "NEC Vrc5477 AC97 sound"
-	depends on SOUND_PRIME!=n && DDB5477 && SOUND
+	depends on SOUND_PRIME && DDB5477
 	help
 	  Say Y here to enable sound support for the NEC Vrc5477 chip, an
 	  integrated, multi-function controller chip for MIPS CPUs.  Works
@@ -218,15 +218,15 @@
 
 config SOUND_AU1000
 	tristate "Au1000 Sound"
-	depends on SOUND_PRIME!=n && (SOC_AU1000 || SOC_AU1100 || SOC_AU1500) && SOUND
+	depends on SOUND_PRIME && (SOC_AU1000 || SOC_AU1100 || SOC_AU1500)
 
 config SOUND_AU1550_AC97
 	tristate "Au1550 AC97 Sound"
-	depends on SOUND_PRIME!=n && SOC_AU1550 && SOUND
+	depends on SOUND_PRIME && SOC_AU1550
 
 config SOUND_TRIDENT
 	tristate "Trident 4DWave DX/NX, SiS 7018 or ALi 5451 PCI Audio Core"
-	depends on SOUND_PRIME!=n && SOUND
+	depends on SOUND_PRIME
 	---help---
 	  Say Y or M if you have a PCI sound card utilizing the Trident
 	  4DWave-DX/NX chipset or your mother board chipset has SiS 7018
@@ -267,7 +267,7 @@
 
 config SOUND_MSNDCLAS
 	tristate "Support for Turtle Beach MultiSound Classic, Tahiti, Monterey"
-	depends on SOUND_PRIME!=n && SOUND && (m || !STANDALONE)
+	depends on SOUND_PRIME && (m || !STANDALONE)
 	help
 	  Say M here if you have a Turtle Beach MultiSound Classic, Tahiti or
 	  Monterey (not for the Pinnacle or Fiji).
@@ -331,7 +331,7 @@
 
 config SOUND_MSNDPIN
 	tristate "Support for Turtle Beach MultiSound Pinnacle, Fiji"
-	depends on SOUND_PRIME!=n && SOUND && (m || !STANDALONE)
+	depends on SOUND_PRIME && (m || !STANDALONE)
 	help
 	  Say M here if you have a Turtle Beach MultiSound Pinnacle or Fiji.
 	  See <file:Documentation/sound/oss/MultiSound> for important information
@@ -492,7 +492,7 @@
 
 config SOUND_VIA82CXXX
 	tristate "VIA 82C686 Audio Codec"
-	depends on SOUND_PRIME!=n && PCI
+	depends on SOUND_PRIME && PCI
 	help
 	  Say Y here to include support for the audio codec found on VIA
 	  82Cxxx-based chips. Typically these are built into a motherboard.
@@ -512,7 +512,7 @@
 
 config SOUND_OSS
 	tristate "OSS sound modules"
-	depends on SOUND_PRIME!=n && SOUND
+	depends on SOUND_PRIME
 	help
 	  OSS is the Open Sound System suite of sound card drivers.  They make
 	  sound programming easier since they provide a common API.  Say Y or
@@ -1077,7 +1077,7 @@
 
 config SOUND_TVMIXER
 	tristate "TV card (bt848) mixer support"
-	depends on SOUND_PRIME!=n && SOUND && I2C
+	depends on SOUND_PRIME && I2C
 	help
 	  Support for audio mixer facilities on the BT848 TV frame-grabber
 	  card.
@@ -1088,11 +1088,11 @@
 
 config SOUND_ALI5455
 	tristate "ALi5455 audio support"
-	depends on SOUND_PRIME!=n && PCI
+	depends on SOUND_PRIME && PCI
 
 config SOUND_FORTE
 	tristate "ForteMedia FM801 driver"
-	depends on SOUND_PRIME!=n && PCI
+	depends on SOUND_PRIME && PCI
 	help
 	  Say Y or M if you want driver support for the ForteMedia FM801 PCI
 	  audio controller (Abit AU10, Genius Sound Maker, HP Workstation
@@ -1100,7 +1100,7 @@
 
 config SOUND_RME96XX
 	tristate "RME Hammerfall (RME96XX) support"
-	depends on SOUND_PRIME!=n && PCI
+	depends on SOUND_PRIME && PCI
 	help
 	  Say Y or M if you have a Hammerfall or Hammerfall light
 	  multichannel card from RME. If you want to access advanced
@@ -1108,11 +1108,11 @@
 
 config SOUND_AD1980
 	tristate "AD1980 front/back switch plugin"
-	depends on SOUND_PRIME!=n
+	depends on SOUND_PRIME
 
 config SOUND_SH_DAC_AUDIO
 	tristate "SuperH DAC audio support"
-	depends on SOUND_PRIME!=n && SOUND && CPU_SH3
+	depends on SOUND_PRIME && CPU_SH3
 
 config SOUND_SH_DAC_AUDIO_CHANNEL
 	int "    DAC channel"
diff --git a/sound/oss/ad1816.c b/sound/oss/ad1816.c
index 22dae5d..95586de 100644
--- a/sound/oss/ad1816.c
+++ b/sound/oss/ad1816.c
@@ -592,7 +592,7 @@
   {{reg_l, pola_l, pos_l, len_l}, {reg_r, pola_r, pos_r, len_r}}
 
 
-mixer_ent mix_devices[SOUND_MIXER_NRDEVICES][2] = {
+static mixer_ent mix_devices[SOUND_MIXER_NRDEVICES][2] = {
 MIX_ENT(SOUND_MIXER_VOLUME,	14, 1, 8, 5,	14, 1, 0, 5),
 MIX_ENT(SOUND_MIXER_BASS,	 0, 0, 0, 0,	 0, 0, 0, 0),
 MIX_ENT(SOUND_MIXER_TREBLE,	 0, 0, 0, 0,	 0, 0, 0, 0),
diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c
index 4384dac..7c835ab 100644
--- a/sound/oss/ad1848.c
+++ b/sound/oss/ad1848.c
@@ -2178,8 +2178,7 @@
 		
 	if (devc != NULL)
 	{
-		if(audio_devs[dev]->portc!=NULL)
-			kfree(audio_devs[dev]->portc);
+		kfree(audio_devs[dev]->portc);
 		release_region(devc->base, 4);
 
 		if (!share_dma)
diff --git a/sound/oss/ad1889.c b/sound/oss/ad1889.c
index b767c62..2cfd214 100644
--- a/sound/oss/ad1889.c
+++ b/sound/oss/ad1889.c
@@ -277,8 +277,7 @@
 
 	for (j = 0; j < AD_MAX_STATES; j++) {
 		dmabuf = &dev->state[j].dmabuf;
-		if (dmabuf->rawbuf != NULL) 
-			kfree(dmabuf->rawbuf);
+		kfree(dmabuf->rawbuf);
 	}
 
 	kfree(dev);
diff --git a/sound/oss/cmpci.c b/sound/oss/cmpci.c
index 34720e6..74dcca7 100644
--- a/sound/oss/cmpci.c
+++ b/sound/oss/cmpci.c
@@ -123,6 +123,7 @@
 #include <linux/smp_lock.h>
 #include <linux/bitops.h>
 #include <linux/wait.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/io.h>
 #include <asm/page.h>
@@ -3058,7 +3059,7 @@
 		return -ENODEV;
 	if (pcidev->irq == 0)
 		return -ENODEV;
-	i = pci_set_dma_mask(pcidev, 0xffffffff);
+	i = pci_set_dma_mask(pcidev, DMA_32BIT_MASK);
 	if (i) {
 		printk(KERN_WARNING "cmpci: architecture does not support 32bit PCI busmaster DMA\n");
 		return i;
diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c
index 5281b88..3310866 100644
--- a/sound/oss/dmasound/dmasound_awacs.c
+++ b/sound/oss/dmasound/dmasound_awacs.c
@@ -671,14 +671,10 @@
 	release_OF_resource(awacs_node, 1);
 	release_OF_resource(awacs_node, 2);
 
-	if (awacs_tx_cmd_space)
-		kfree(awacs_tx_cmd_space);
-	if (awacs_rx_cmd_space)
-		kfree(awacs_rx_cmd_space);
-	if (beep_dbdma_cmd_space)
-		kfree(beep_dbdma_cmd_space);
-	if (beep_buf)
-		kfree(beep_buf);
+	kfree(awacs_tx_cmd_space);
+	kfree(awacs_rx_cmd_space);
+	kfree(beep_dbdma_cmd_space);
+	kfree(beep_buf);
 #ifdef CONFIG_PMAC_PBOOK
 	pmu_unregister_sleep_notifier(&awacs_sleep_notifier);
 #endif
@@ -2301,8 +2297,7 @@
 #endif
 
 	if ((write_sq.max_count + 1) > number_of_tx_cmd_buffers) {
-		if (awacs_tx_cmd_space)
-			kfree(awacs_tx_cmd_space);
+		kfree(awacs_tx_cmd_space);
 		number_of_tx_cmd_buffers = 0;
 
 		/* we need nbufs + 1 (for the loop) and we should request + 1
@@ -2360,8 +2355,7 @@
 #endif
 
 	if ((read_sq.max_count+1) > number_of_rx_cmd_buffers ) {
-		if (awacs_rx_cmd_space)
-			kfree(awacs_rx_cmd_space);
+		kfree(awacs_rx_cmd_space);
 		number_of_rx_cmd_buffers = 0;
 
 		/* we need nbufs + 1 (for the loop) and we should request + 1 again
@@ -2805,7 +2799,7 @@
 	beep_buf = (short *) kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL);
 	if (beep_buf == NULL) {
 		printk(KERN_ERR "dmasound_pmac: no memory for beep buffer\n");
-		if( beep_dbdma_cmd_space ) kfree(beep_dbdma_cmd_space) ;
+		kfree(beep_dbdma_cmd_space) ;
 		return -ENOMEM ;
 	}
 	return 0 ;
diff --git a/sound/oss/emu10k1/midi.c b/sound/oss/emu10k1/midi.c
index 33dea3d..b40b5f9 100644
--- a/sound/oss/emu10k1/midi.c
+++ b/sound/oss/emu10k1/midi.c
@@ -523,10 +523,8 @@
 	card = midi_devs[dev]->devc;
 	emu10k1_mpuout_close(card);
 
-	if (card->seq_mididev) {
-		kfree(card->seq_mididev);
-		card->seq_mididev = NULL;
-	}
+	kfree(card->seq_mididev);
+	card->seq_mididev = NULL;
 }
 
 int emu10k1_seq_midi_out(int dev, unsigned char midi_byte)
diff --git a/sound/oss/emu10k1/passthrough.c b/sound/oss/emu10k1/passthrough.c
index 4094be5..4e3baca 100644
--- a/sound/oss/emu10k1/passthrough.c
+++ b/sound/oss/emu10k1/passthrough.c
@@ -213,8 +213,7 @@
 				sblive_writeptr(card, SPCS0 + i, 0, pt->old_spcs[i]);
 		}
 		pt->state = PT_STATE_INACTIVE;
-		if(pt->buf)
-			kfree(pt->buf);
+		kfree(pt->buf);
 	}
 }
 
diff --git a/sound/oss/es1370.c b/sound/oss/es1370.c
index 563a52f..8538085 100644
--- a/sound/oss/es1370.c
+++ b/sound/oss/es1370.c
@@ -156,6 +156,7 @@
 #include <linux/spinlock.h>
 #include <linux/gameport.h>
 #include <linux/wait.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/io.h>
 #include <asm/page.h>
@@ -2621,7 +2622,7 @@
 		return -ENODEV;
 	if (pcidev->irq == 0) 
 		return -ENODEV;
-	i = pci_set_dma_mask(pcidev, 0xffffffff);
+	i = pci_set_dma_mask(pcidev, DMA_32BIT_MASK);
 	if (i) {
 		printk(KERN_WARNING "es1370: architecture does not support 32bit PCI busmaster DMA\n");
 		return i;
diff --git a/sound/oss/es1371.c b/sound/oss/es1371.c
index c38ae1e..12a56d5 100644
--- a/sound/oss/es1371.c
+++ b/sound/oss/es1371.c
@@ -128,6 +128,7 @@
 #include <linux/ac97_codec.h>
 #include <linux/gameport.h>
 #include <linux/wait.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/io.h>
 #include <asm/page.h>
@@ -2862,7 +2863,7 @@
 		return -ENODEV;
 	if (pcidev->irq == 0) 
 		return -ENODEV;
-	i = pci_set_dma_mask(pcidev, 0xffffffff);
+	i = pci_set_dma_mask(pcidev, DMA_32BIT_MASK);
 	if (i) {
 		printk(KERN_WARNING "es1371: architecture does not support 32bit PCI busmaster DMA\n");
 		return i;
diff --git a/sound/oss/esssolo1.c b/sound/oss/esssolo1.c
index a682ab1..a4ecab2 100644
--- a/sound/oss/esssolo1.c
+++ b/sound/oss/esssolo1.c
@@ -104,6 +104,7 @@
 #include <linux/smp_lock.h>
 #include <linux/gameport.h>
 #include <linux/wait.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/io.h>
 #include <asm/page.h>
@@ -2346,7 +2347,7 @@
 	 * to 24 bits first, then 32 bits (playback only) if that fails.
 	 */
 	if (pci_set_dma_mask(pcidev, 0x00ffffff) &&
-	    pci_set_dma_mask(pcidev, 0xffffffff)) {
+	    pci_set_dma_mask(pcidev, DMA_32BIT_MASK)) {
 		printk(KERN_WARNING "solo1: architecture does not support 24bit or 32bit PCI busmaster DMA\n");
 		return -ENODEV;
 	}
diff --git a/sound/oss/maestro.c b/sound/oss/maestro.c
index 52d2db4..3dce504 100644
--- a/sound/oss/maestro.c
+++ b/sound/oss/maestro.c
@@ -2356,7 +2356,7 @@
 	}
 
 rec_return_free:
-	if(combbuf) kfree(combbuf);
+	kfree(combbuf);
 	return ret;
 }
 
diff --git a/sound/oss/mpu401.c b/sound/oss/mpu401.c
index b66f53f..0aac54c 100644
--- a/sound/oss/mpu401.c
+++ b/sound/oss/mpu401.c
@@ -1240,8 +1240,7 @@
 		p=mpu401_synth_operations[n];
 		sound_unload_mididev(n);
 		sound_unload_timerdev(hw_config->slots[2]);
-		if(p)
-			kfree(p);
+		kfree(p);
 	}
 }
 
diff --git a/sound/oss/nm256.h b/sound/oss/nm256.h
index eae7d99..21e07b5 100644
--- a/sound/oss/nm256.h
+++ b/sound/oss/nm256.h
@@ -128,9 +128,6 @@
     struct nm256_info *next_card;
 };
 
-/* Debug flag--bigger numbers mean more output. */
-extern int nm256_debug;
-
 /* The BIOS signature. */
 #define NM_SIGNATURE 0x4e4d0000
 /* Signature mask. */
@@ -284,7 +281,7 @@
 }
 
 /* Returns a non-zero value if we should use the coefficient cache. */
-extern int nm256_cachedCoefficients (struct nm256_info *card);
+static int nm256_cachedCoefficients (struct nm256_info *card);
 
 #endif
 
diff --git a/sound/oss/nm256_audio.c b/sound/oss/nm256_audio.c
index f9166e1..6697006 100644
--- a/sound/oss/nm256_audio.c
+++ b/sound/oss/nm256_audio.c
@@ -28,12 +28,13 @@
 #include <linux/delay.h>
 #include <linux/spinlock.h>
 #include "sound_config.h"
+
+static int nm256_debug;
+static int force_load;
+
 #include "nm256.h"
 #include "nm256_coeff.h"
 
-int nm256_debug;
-static int force_load;
-
 /* 
  * The size of the playback reserve.  When the playback buffer has less
  * than NM256_PLAY_WMARK_SIZE bytes to output, we request a new
@@ -138,7 +139,7 @@
 static int buffertop;
 
 /* Check to see if we're using the bank of cached coefficients. */
-int
+static int
 nm256_cachedCoefficients (struct nm256_info *card)
 {
     return usecache;
diff --git a/sound/oss/nm256_coeff.h b/sound/oss/nm256_coeff.h
index 0ceecc2..6fc07f3 100644
--- a/sound/oss/nm256_coeff.h
+++ b/sound/oss/nm256_coeff.h
@@ -4650,7 +4650,7 @@
     card->coeffsCurrent = 1;
 }
 
-void
+static void
 nm256_loadCoefficient (struct nm256_info *card, int which, int number)
 {
     static u16 addrs[3] = { 0x1c, 0x21c, 0x408 };
diff --git a/sound/oss/rme96xx.c b/sound/oss/rme96xx.c
index 76774bb..7609c68 100644
--- a/sound/oss/rme96xx.c
+++ b/sound/oss/rme96xx.c
@@ -807,7 +807,7 @@
                 struct page* page, *last_page;
 
                 page = virt_to_page(buf);
-                last_page = virt_to_page(buf + (1 << pg));
+                last_page = page + (1 << pg);
                 DBG(printk("setting reserved bit\n"));
                 while (page < last_page) {
 			SetPageReserved(page);
@@ -1750,9 +1750,7 @@
 
 
 static struct file_operations rme96xx_audio_fops = {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 	.owner	 = THIS_MODULE,
-#endif
 	.read	 = rme96xx_read,
 	.write	 = rme96xx_write,
 	.poll	 = rme96xx_poll,
@@ -1852,9 +1850,7 @@
 }
 
 static /*const*/ struct file_operations rme96xx_mixer_fops = {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 	.owner	 = THIS_MODULE,
-#endif
 	.ioctl	 = rme96xx_mixer_ioctl,
 	.open	 = rme96xx_mixer_open,
 	.release = rme96xx_mixer_release,
diff --git a/sound/oss/sb_common.c b/sound/oss/sb_common.c
index ce359e6..5f955e3 100644
--- a/sound/oss/sb_common.c
+++ b/sound/oss/sb_common.c
@@ -915,8 +915,8 @@
 	}
 	else
 		release_region(hw_config->io_base, 16);
-	if(detected_devc)
-		kfree(detected_devc);
+
+	kfree(detected_devc);
 }
 
 /*
diff --git a/sound/oss/soundcard.c b/sound/oss/soundcard.c
index de91c90..a686be9 100644
--- a/sound/oss/soundcard.c
+++ b/sound/oss/soundcard.c
@@ -73,7 +73,7 @@
 
 
 unsigned long seq_time = 0;	/* Time for /dev/sequencer */
-extern struct class_simple *sound_class;
+extern struct class *sound_class;
 
 /*
  * Table for configurable mixer volume handling
@@ -567,9 +567,9 @@
 		devfs_mk_cdev(MKDEV(SOUND_MAJOR, dev_list[i].minor),
 				S_IFCHR | dev_list[i].mode,
 				"sound/%s", dev_list[i].name);
-		class_simple_device_add(sound_class, 
-					MKDEV(SOUND_MAJOR, dev_list[i].minor),
-					NULL, "%s", dev_list[i].name);
+		class_device_create(sound_class,
+				    MKDEV(SOUND_MAJOR, dev_list[i].minor),
+				    NULL, "%s", dev_list[i].name);
 
 		if (!dev_list[i].num)
 			continue;
@@ -579,10 +579,9 @@
 						dev_list[i].minor + (j*0x10)),
 					S_IFCHR | dev_list[i].mode,
 					"sound/%s%d", dev_list[i].name, j);
-			class_simple_device_add(sound_class,
-					MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)),
-					NULL,
-					"%s%d", dev_list[i].name, j);
+			class_device_create(sound_class,
+					    MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)),
+					    NULL, "%s%d", dev_list[i].name, j);
 		}
 	}
 
@@ -598,12 +597,12 @@
 
 	for (i = 0; i < sizeof (dev_list) / sizeof *dev_list; i++) {
 		devfs_remove("sound/%s", dev_list[i].name);
-		class_simple_device_remove(MKDEV(SOUND_MAJOR, dev_list[i].minor));
+		class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor));
 		if (!dev_list[i].num)
 			continue;
 		for (j = 1; j < *dev_list[i].num; j++) {
 			devfs_remove("sound/%s%d", dev_list[i].name, j);
-			class_simple_device_remove(MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)));
+			class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)));
 		}
 	}
 	
diff --git a/sound/oss/sscape.c b/sound/oss/sscape.c
index 50ca646..9ed5211 100644
--- a/sound/oss/sscape.c
+++ b/sound/oss/sscape.c
@@ -991,7 +991,6 @@
 	unsigned i;
 	static	char code_file_name[23] = "/sndscape/sndscape.cox";
 	
-	int sscape_sb_enable		= 0;
 	int sscape_joystic_enable	= 0x7f;
 	int sscape_mic_enable		= 0;
 	int sscape_ext_midi		= 0;		
@@ -1015,14 +1014,9 @@
 	sscape_write( devc, 2, devc->ic_type == IC_ODIE ? 0x70 : 0x40);
 	sscape_write( devc, 3, ( devc -> dma << 4) | 0x80);
 
-	if ( sscape_sb_enable )
-		sscape_write (devc, 4, 0xF0 | (sb_irq << 2) | midi_irq);
-	else	
-		sscape_write (devc, 4, 0xF0 | (midi_irq<<2) | midi_irq);
+	sscape_write (devc, 4, 0xF0 | (midi_irq<<2) | midi_irq);
 
 	i = 0x10; //sscape_read(devc, 9) & (devc->ic_type == IC_ODIE ? 0xf0 : 0xc0);
-	if ( sscape_sb_enable )
-		i |= devc->ic_type == IC_ODIE ? 0x05 : 0x07;	    
 	if (sscape_joystic_enable) i |= 8;
 	
 	sscape_write (devc, 9, i);
diff --git a/sound/oss/v_midi.c b/sound/oss/v_midi.c
index 077b767..a7ef04f 100644
--- a/sound/oss/v_midi.c
+++ b/sound/oss/v_midi.c
@@ -39,8 +39,6 @@
  */
 
 
-void            (*midi_input_intr) (int dev, unsigned char data);
-
 static int v_midi_open (int dev, int mode,
 	      void            (*input) (int dev, unsigned char data),
 	      void            (*output) (int dev)
diff --git a/sound/oss/wavfront.c b/sound/oss/wavfront.c
index cce1278..b92ba89 100644
--- a/sound/oss/wavfront.c
+++ b/sound/oss/wavfront.c
@@ -151,11 +151,11 @@
 
 /*** Module-accessible parameters ***************************************/
 
-int wf_raw;     /* we normally check for "raw state" to firmware
-		   loading. if set, then during driver loading, the
-		   state of the board is ignored, and we reset the
-		   board and load the firmware anyway.
-		*/
+static int wf_raw;     /* we normally check for "raw state" to firmware
+			   loading. if set, then during driver loading, the
+			   state of the board is ignored, and we reset the
+			   board and load the firmware anyway.
+			*/
 		   
 static int fx_raw = 1; /* if this is zero, we'll leave the FX processor in
 		          whatever state it is when the driver is loaded.
@@ -2911,7 +2911,7 @@
 	return 0;
 }	
 
-void
+static void
 wffx_mute (int onoff)
     
 {
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 428efdb..6d7a00f 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -274,6 +274,19 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-hdsp.
 
+config SND_HDSPM
+	tristate "RME Hammerfall DSP MADI"
+	depends on SND
+	select SND_HWDEP
+	select SND_RAWMIDI
+	select SND_PCM
+	help
+	  Say Y here to include support for RME Hammerfall DSP MADI
+	  soundcards.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-hdspm.
+
 config SND_TRIDENT
 	tristate "Trident 4D-Wave DX/NX; SiS 7018"
 	depends on SND
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 0b024ec..a4b72cd 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -120,6 +120,7 @@
 { 0x414c4770, 0xfffffff0, "ALC203",		NULL,		NULL },
 { 0x434d4941, 0xffffffff, "CMI9738",		patch_cm9738,	NULL },
 { 0x434d4961, 0xffffffff, "CMI9739",		patch_cm9739,	NULL },
+{ 0x434d4969, 0xffffffff, "CMI9780",		patch_cm9780,	NULL },
 { 0x434d4978, 0xffffffff, "CMI9761",		patch_cm9761,	NULL },
 { 0x434d4982, 0xffffffff, "CMI9761",		patch_cm9761,	NULL },
 { 0x434d4983, 0xffffffff, "CMI9761",		patch_cm9761,	NULL },
@@ -149,7 +150,7 @@
 { 0x4e534331, 0xffffffff, "LM4549",		NULL,		NULL },
 { 0x4e534350, 0xffffffff, "LM4550",		NULL,		NULL },
 { 0x50534304, 0xffffffff, "UCB1400",		NULL,		NULL },
-{ 0x53494c20, 0xffffffe0, "Si3036,8",		NULL,		mpatch_si3036 },
+{ 0x53494c20, 0xffffffe0, "Si3036,8",		mpatch_si3036,	mpatch_si3036, AC97_MODEM_PATCH },
 { 0x54524102, 0xffffffff, "TR28022",		NULL,		NULL },
 { 0x54524106, 0xffffffff, "TR28026",		NULL,		NULL },
 { 0x54524108, 0xffffffff, "TR28028",		patch_tritech_tr28028,	NULL }, // added by xin jin [07/09/99]
@@ -462,12 +463,14 @@
 {
 	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
 	struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value;
-	unsigned short val;
+	unsigned short val, bitmask;
 	
+	for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
+		;
 	val = snd_ac97_read_cache(ac97, e->reg);
-	ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (e->mask - 1);
+	ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);
 	if (e->shift_l != e->shift_r)
-		ucontrol->value.enumerated.item[1] = (val >> e->shift_r) & (e->mask - 1);
+		ucontrol->value.enumerated.item[1] = (val >> e->shift_r) & (bitmask - 1);
 
 	return 0;
 }
@@ -477,17 +480,19 @@
 	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
 	struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value;
 	unsigned short val;
-	unsigned short mask;
+	unsigned short mask, bitmask;
 	
+	for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
+		;
 	if (ucontrol->value.enumerated.item[0] > e->mask - 1)
 		return -EINVAL;
 	val = ucontrol->value.enumerated.item[0] << e->shift_l;
-	mask = (e->mask - 1) << e->shift_l;
+	mask = (bitmask - 1) << e->shift_l;
 	if (e->shift_l != e->shift_r) {
 		if (ucontrol->value.enumerated.item[1] > e->mask - 1)
 			return -EINVAL;
 		val |= ucontrol->value.enumerated.item[1] << e->shift_r;
-		mask |= (e->mask - 1) << e->shift_r;
+		mask |= (bitmask - 1) << e->shift_r;
 	}
 	return snd_ac97_update_bits(ac97, e->reg, mask, val);
 }
@@ -658,14 +663,14 @@
 AC97_SINGLE("LFE Playback Volume", AC97_CENTER_LFE_MASTER, 8, 31, 1)
 };
 
-static const snd_kcontrol_new_t snd_ac97_controls_surround[2] = {
-AC97_DOUBLE("Surround Playback Switch", AC97_SURROUND_MASTER, 15, 7, 1, 1),
-AC97_DOUBLE("Surround Playback Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1),
-};
-
 static const snd_kcontrol_new_t snd_ac97_control_eapd =
 AC97_SINGLE("External Amplifier", AC97_POWERDOWN, 15, 1, 1);
 
+static const snd_kcontrol_new_t snd_ac97_controls_modem_switches[2] = {
+AC97_SINGLE("Off-hook Switch", AC97_GPIO_STATUS, 0, 1, 0),
+AC97_SINGLE("Caller ID Switch", AC97_GPIO_STATUS, 2, 1, 0)
+};
+
 /* change the existing EAPD control as inverted */
 static void set_inv_eapd(ac97_t *ac97, snd_kcontrol_t *kctl)
 {
@@ -1072,9 +1077,9 @@
 		unsigned short val;
 		snd_ac97_write(ac97, reg, 0x8080 | cbit[i] | (cbit[i] << 8));
 		val = snd_ac97_read(ac97, reg);
-		if (! *lo_max && (val & cbit[i]))
+		if (! *lo_max && (val & 0x7f) == cbit[i])
 			*lo_max = max[i];
-		if (! *hi_max && (val & (cbit[i] << 8)))
+		if (! *hi_max && ((val >> 8) & 0x7f) == cbit[i])
 			*hi_max = max[i];
 		if (*lo_max && *hi_max)
 			break;
@@ -1526,13 +1531,25 @@
 
 static int snd_ac97_modem_build(snd_card_t * card, ac97_t * ac97)
 {
-	/* TODO */
+	int err, idx;
+
 	//printk("AC97_GPIO_CFG = %x\n",snd_ac97_read(ac97,AC97_GPIO_CFG));
 	snd_ac97_write(ac97, AC97_GPIO_CFG, 0xffff & ~(AC97_GPIO_LINE1_OH));
 	snd_ac97_write(ac97, AC97_GPIO_POLARITY, 0xffff & ~(AC97_GPIO_LINE1_OH));
 	snd_ac97_write(ac97, AC97_GPIO_STICKY, 0xffff);
 	snd_ac97_write(ac97, AC97_GPIO_WAKEUP, 0x0);
 	snd_ac97_write(ac97, AC97_MISC_AFE, 0x0);
+
+	/* build modem switches */
+	for (idx = 0; idx < ARRAY_SIZE(snd_ac97_controls_modem_switches); idx++)
+		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_modem_switches[idx], ac97))) < 0)
+			return err;
+
+	/* build chip specific controls */
+	if (ac97->build_ops->build_specific)
+		if ((err = ac97->build_ops->build_specific(ac97)) < 0)
+			return err;
+
 	return 0;
 }
 
@@ -1872,7 +1889,11 @@
 			goto __access_ok;
 	}
 
-	snd_ac97_write(ac97, AC97_RESET, 0);	/* reset to defaults */
+	/* reset to defaults */
+	if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO))
+		snd_ac97_write(ac97, AC97_RESET, 0);
+	if (!(ac97->scaps & AC97_SCAP_SKIP_MODEM))
+		snd_ac97_write(ac97, AC97_EXTENDED_MID, 0);
 	if (bus->ops->wait)
 		bus->ops->wait(ac97);
 	else {
@@ -1964,21 +1985,21 @@
 		/* note: it's important to set the rate at first */
 		tmp = AC97_MEA_GPIO;
 		if (ac97->ext_mid & AC97_MEI_LINE1) {
-			snd_ac97_write_cache(ac97, AC97_LINE1_RATE, 12000);
+			snd_ac97_write_cache(ac97, AC97_LINE1_RATE, 8000);
 			tmp |= AC97_MEA_ADC1 | AC97_MEA_DAC1;
 		}
 		if (ac97->ext_mid & AC97_MEI_LINE2) {
-			snd_ac97_write_cache(ac97, AC97_LINE2_RATE, 12000);
+			snd_ac97_write_cache(ac97, AC97_LINE2_RATE, 8000);
 			tmp |= AC97_MEA_ADC2 | AC97_MEA_DAC2;
 		}
 		if (ac97->ext_mid & AC97_MEI_HANDSET) {
-			snd_ac97_write_cache(ac97, AC97_HANDSET_RATE, 12000);
+			snd_ac97_write_cache(ac97, AC97_HANDSET_RATE, 8000);
 			tmp |= AC97_MEA_HADC | AC97_MEA_HDAC;
 		}
-		snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp << 8));
+		snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0);
 		udelay(100);
 		/* nothing should be in powerdown mode */
-		snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xff00 & ~(tmp << 8));
+		snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0);
 		end_time = jiffies + (HZ / 10);
 		do {
 			if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp)
@@ -2521,11 +2542,11 @@
 		return result;
 	}
 
-	for (; quirk->vendor; quirk++) {
-		if (quirk->vendor != ac97->subsystem_vendor)
+	for (; quirk->subvendor; quirk++) {
+		if (quirk->subvendor != ac97->subsystem_vendor)
 			continue;
-		if ((! quirk->mask && quirk->device == ac97->subsystem_device) ||
-		    quirk->device == (quirk->mask & ac97->subsystem_device)) {
+		if ((! quirk->mask && quirk->subdevice == ac97->subsystem_device) ||
+		    quirk->subdevice == (quirk->mask & ac97->subsystem_device)) {
 			if (quirk->codec_id && quirk->codec_id != ac97->id)
 				continue;
 			snd_printdd("ac97 quirk for %s (%04x:%04x)\n", quirk->name, ac97->subsystem_vendor, ac97->subsystem_device);
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index 13c34a5..a15eb85 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -64,6 +64,116 @@
 	return ret;
 }
 
+/*
+ * shared line-in/mic controls
+ */
+static int ac97_enum_text_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo,
+			       const char **texts, unsigned int nums)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = nums;
+	if (uinfo->value.enumerated.item > nums - 1)
+		uinfo->value.enumerated.item = nums - 1;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int ac97_surround_jack_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	static const char *texts[] = { "Shared", "Independent" };
+	return ac97_enum_text_info(kcontrol, uinfo, texts, 2);
+}
+
+static int ac97_surround_jack_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.enumerated.item[0] = ac97->indep_surround;
+	return 0;
+}
+
+static int ac97_surround_jack_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+	unsigned char indep = !!ucontrol->value.enumerated.item[0];
+
+	if (indep != ac97->indep_surround) {
+		ac97->indep_surround = indep;
+		if (ac97->build_ops->update_jacks)
+			ac97->build_ops->update_jacks(ac97);
+		return 1;
+	}
+	return 0;
+}
+
+static int ac97_channel_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	static const char *texts[] = { "2ch", "4ch", "6ch" };
+	if (kcontrol->private_value)
+		return ac97_enum_text_info(kcontrol, uinfo, texts, 2); /* 4ch only */
+	return ac97_enum_text_info(kcontrol, uinfo, texts, 3);
+}
+
+static int ac97_channel_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.enumerated.item[0] = ac97->channel_mode;
+	return 0;
+}
+
+static int ac97_channel_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+	unsigned char mode = ucontrol->value.enumerated.item[0];
+
+	if (mode != ac97->channel_mode) {
+		ac97->channel_mode = mode;
+		if (ac97->build_ops->update_jacks)
+			ac97->build_ops->update_jacks(ac97);
+		return 1;
+	}
+	return 0;
+}
+
+#define AC97_SURROUND_JACK_MODE_CTL \
+	{ \
+		.iface	= SNDRV_CTL_ELEM_IFACE_MIXER, \
+		.name	= "Surround Jack Mode", \
+		.info = ac97_surround_jack_mode_info, \
+		.get = ac97_surround_jack_mode_get, \
+		.put = ac97_surround_jack_mode_put, \
+	}
+#define AC97_CHANNEL_MODE_CTL \
+	{ \
+		.iface	= SNDRV_CTL_ELEM_IFACE_MIXER, \
+		.name	= "Channel Mode", \
+		.info = ac97_channel_mode_info, \
+		.get = ac97_channel_mode_get, \
+		.put = ac97_channel_mode_put, \
+	}
+#define AC97_CHANNEL_MODE_4CH_CTL \
+	{ \
+		.iface	= SNDRV_CTL_ELEM_IFACE_MIXER, \
+		.name	= "Channel Mode", \
+		.info = ac97_channel_mode_info, \
+		.get = ac97_channel_mode_get, \
+		.put = ac97_channel_mode_put, \
+		.private_value = 1, \
+	}
+
+static inline int is_shared_linein(ac97_t *ac97)
+{
+	return ! ac97->indep_surround && ac97->channel_mode >= 1;
+}
+
+static inline int is_shared_micin(ac97_t *ac97)
+{
+	return ! ac97->indep_surround && ac97->channel_mode >= 2;
+}
+
+
 /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */
 
 /* It is possible to indicate to the Yamaha YMF753 the type of speakers being used. */
@@ -1390,6 +1500,16 @@
 				    AC97_AD198X_DMIX0 | AC97_AD198X_DMIX1, val);
 }
 
+static void ad1888_update_jacks(ac97_t *ac97)
+{
+	/* shared Line-In */
+	snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 12,
+			     is_shared_linein(ac97) ? 0 : 1 << 12);
+	/* shared Mic */
+	snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 11,
+			     is_shared_micin(ac97) ? 0 : 1 << 11);
+}
+
 static const snd_kcontrol_new_t snd_ac97_ad1888_controls[] = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -1406,8 +1526,8 @@
 		.get = snd_ac97_ad1888_downmix_get,
 		.put = snd_ac97_ad1888_downmix_put
 	},
-	AC97_SINGLE("Surround Jack as Input", AC97_AD_MISC, 12, 1, 0),
-	AC97_SINGLE("Center/LFE Jack as Input", AC97_AD_MISC, 11, 1, 0),
+	AC97_SURROUND_JACK_MODE_CTL,
+	AC97_CHANNEL_MODE_CTL,
 };
 
 static int patch_ad1888_specific(ac97_t *ac97)
@@ -1422,8 +1542,9 @@
 	.build_post_spdif = patch_ad198x_post_spdif,
 	.build_specific = patch_ad1888_specific,
 #ifdef CONFIG_PM
-	.resume = ad18xx_resume
+	.resume = ad18xx_resume,
 #endif
+	.update_jacks = ad1888_update_jacks,
 };
 
 int patch_ad1888(ac97_t * ac97)
@@ -1459,8 +1580,9 @@
 	.build_post_spdif = patch_ad198x_post_spdif,
 	.build_specific = patch_ad1980_specific,
 #ifdef CONFIG_PM
-	.resume = ad18xx_resume
+	.resume = ad18xx_resume,
 #endif
+	.update_jacks = ad1888_update_jacks,
 };
 
 int patch_ad1980(ac97_t * ac97)
@@ -1471,10 +1593,21 @@
 }
 
 static const snd_kcontrol_new_t snd_ac97_ad1985_controls[] = {
-	AC97_SINGLE("Center/LFE Jack as Mic", AC97_AD_SERIAL_CFG, 9, 1, 0),
 	AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0)
 };
 
+static void ad1985_update_jacks(ac97_t *ac97)
+{
+	/* shared Line-In */
+	snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 12,
+			     is_shared_linein(ac97) ? 0 : 1 << 12);
+	/* shared Mic */
+	snd_ac97_update_bits(ac97, AC97_AD_MISC, 1 << 11,
+			     is_shared_micin(ac97) ? 0 : 1 << 11);
+	snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 1 << 9,
+			     is_shared_micin(ac97) ? 0 : 1 << 9);
+}
+
 static int patch_ad1985_specific(ac97_t *ac97)
 {
 	int err;
@@ -1488,8 +1621,9 @@
 	.build_post_spdif = patch_ad198x_post_spdif,
 	.build_specific = patch_ad1985_specific,
 #ifdef CONFIG_PM
-	.resume = ad18xx_resume
+	.resume = ad18xx_resume,
 #endif
+	.update_jacks = ad1985_update_jacks,
 };
 
 int patch_ad1985(ac97_t * ac97)
@@ -1521,31 +1655,25 @@
 /*
  * realtek ALC65x/850 codecs
  */
-static int snd_ac97_alc650_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+static void alc650_update_jacks(ac97_t *ac97)
 {
-        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-        ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 1;
-        return 0;
-}
-
-static int snd_ac97_alc650_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
-        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-	int change, val;
-	val = !!(snd_ac97_read(ac97, AC97_ALC650_MULTICH) & (1 << 10));
-	change = (ucontrol->value.integer.value[0] != val);
-	if (change) {
-		/* disable/enable vref */
-		snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
-				     ucontrol->value.integer.value[0] ? (1 << 12) : 0);
-		/* turn on/off center-on-mic */
-		snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
-				     ucontrol->value.integer.value[0] ? (1 << 10) : 0);
-		/* GPIO0 high for mic */
-		snd_ac97_update_bits(ac97, AC97_ALC650_GPIO_STATUS, 0x100,
-				     ucontrol->value.integer.value[0] ? 0 : 0x100);
-        }
-        return change;
+	int shared;
+	
+	/* shared Line-In */
+	shared = is_shared_linein(ac97);
+	snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 9,
+			     shared ? (1 << 9) : 0);
+	/* update shared Mic */
+	shared = is_shared_micin(ac97);
+	/* disable/enable vref */
+	snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
+			     shared ? (1 << 12) : 0);
+	/* turn on/off center-on-mic */
+	snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
+			     shared ? (1 << 10) : 0);
+	/* GPIO0 high for mic */
+	snd_ac97_update_bits(ac97, AC97_ALC650_GPIO_STATUS, 0x100,
+			     shared ? 0 : 0x100);
 }
 
 static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
@@ -1558,8 +1686,8 @@
 	/* 6: Independent Master Volume Right */
 	/* 7: Independent Master Volume Left */
 	/* 8: reserved */
-	AC97_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0),
-	/* 10: mic, see below */
+	/* 9: Line-In/Surround share */
+	/* 10: Mic/CLFE share */
 	/* 11-13: in IEC958 controls */
 	AC97_SINGLE("Swap Surround Slot", AC97_ALC650_MULTICH, 14, 1, 0),
 #if 0 /* always set in patch_alc650 */
@@ -1570,14 +1698,8 @@
 	AC97_SINGLE("Center/LFE DAC Switch", AC97_ALC650_LFE_DAC_VOL, 15, 1, 1),
 	AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1),
 #endif
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Mic As Center/LFE",
-		.info = snd_ac97_info_volsw,
-		.get = snd_ac97_alc650_mic_get,
-		.put = snd_ac97_alc650_mic_put,
-		.private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
-	},
+	AC97_SURROUND_JACK_MODE_CTL,
+	AC97_CHANNEL_MODE_CTL,
 };
 
 static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc650[] = {
@@ -1601,7 +1723,8 @@
 }
 
 static struct snd_ac97_build_ops patch_alc650_ops = {
-	.build_specific	= patch_alc650_specific
+	.build_specific	= patch_alc650_specific,
+	.update_jacks = alc650_update_jacks
 };
 
 int patch_alc650(ac97_t * ac97)
@@ -1659,37 +1782,27 @@
 	return 0;
 }
 
-static int snd_ac97_alc655_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+static void alc655_update_jacks(ac97_t *ac97)
 {
-        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-        ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 1;
-        return 0;
-}
-
-static int snd_ac97_alc655_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
-        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-
+	int shared;
+	
+	/* shared Line-In */
+	shared = is_shared_linein(ac97);
+	ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 9,
+			      shared ? (1 << 9) : 0, 0);
+	/* update shared mic */
+	shared = is_shared_micin(ac97);
 	/* misc control; vrefout disable */
 	snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
-			     ucontrol->value.integer.value[0] ? (1 << 12) : 0);
-	return ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10,
-				     ucontrol->value.integer.value[0] ? (1 << 10) : 0,
-				     0);
+			     shared ? (1 << 12) : 0);
+	ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 10,
+			      shared ? (1 << 10) : 0, 0);
 }
 
-
 static const snd_kcontrol_new_t snd_ac97_controls_alc655[] = {
 	AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
-	AC97_PAGE_SINGLE("Line-In As Surround", AC97_ALC650_MULTICH, 9, 1, 0, 0),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Mic As Center/LFE",
-		.info = snd_ac97_info_volsw,
-		.get = snd_ac97_alc655_mic_get,
-		.put = snd_ac97_alc655_mic_put,
-		.private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
-	},
+	AC97_SURROUND_JACK_MODE_CTL,
+	AC97_CHANNEL_MODE_CTL,
 };
 
 static int alc655_iec958_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
@@ -1759,7 +1872,8 @@
 }
 
 static struct snd_ac97_build_ops patch_alc655_ops = {
-	.build_specific	= patch_alc655_specific
+	.build_specific	= patch_alc655_specific,
+	.update_jacks = alc655_update_jacks
 };
 
 int patch_alc655(ac97_t * ac97)
@@ -1798,63 +1912,33 @@
 #define AC97_ALC850_JACK_SELECT	0x76
 #define AC97_ALC850_MISC1	0x7a
 
-static int ac97_alc850_surround_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
+static void alc850_update_jacks(ac97_t *ac97)
 {
-        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-        ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 12) & 7) == 2;
-        return 0;
-}
-
-static int ac97_alc850_surround_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
-        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-
+	int shared;
+	
+	/* shared Line-In */
+	shared = is_shared_linein(ac97);
 	/* SURR 1kOhm (bit4), Amp (bit5) */
 	snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5),
-			     ucontrol->value.integer.value[0] ? (1<<5) : (1<<4));
+			     shared ? (1<<5) : (1<<4));
 	/* LINE-IN = 0, SURROUND = 2 */
-	return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12,
-				    ucontrol->value.integer.value[0] ? (2<<12) : (0<<12));
-}
-
-static int ac97_alc850_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
-        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-        ucontrol->value.integer.value[0] = ((ac97->regs[AC97_ALC850_JACK_SELECT] >> 4) & 7) == 2;
-        return 0;
-}
-
-static int ac97_alc850_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
-        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-
+	snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12,
+			     shared ? (2<<12) : (0<<12));
+	/* update shared mic */
+	shared = is_shared_micin(ac97);
 	/* Vref disable (bit12), 1kOhm (bit13) */
 	snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13),
-			     ucontrol->value.integer.value[0] ? (1<<12) : (1<<13));
+			     shared ? (1<<12) : (1<<13));
 	/* MIC-IN = 1, CENTER-LFE = 2 */
-	return snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,
-				    ucontrol->value.integer.value[0] ? (2<<4) : (1<<4));
+	snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4,
+			     shared ? (2<<4) : (1<<4));
 }
 
 static const snd_kcontrol_new_t snd_ac97_controls_alc850[] = {
 	AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Line-In As Surround",
-		.info = snd_ac97_info_volsw,
-		.get = ac97_alc850_surround_get,
-		.put = ac97_alc850_surround_put,
-		.private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
-	},
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Mic As Center/LFE",
-		.info = snd_ac97_info_volsw,
-		.get = ac97_alc850_mic_get,
-		.put = ac97_alc850_mic_put,
-		.private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
-	},
-
+	AC97_SINGLE("Mic Front Input Switch", AC97_ALC850_JACK_SELECT, 15, 1, 1),
+	AC97_SURROUND_JACK_MODE_CTL,
+	AC97_CHANNEL_MODE_CTL,
 };
 
 static int patch_alc850_specific(ac97_t *ac97)
@@ -1871,7 +1955,8 @@
 }
 
 static struct snd_ac97_build_ops patch_alc850_ops = {
-	.build_specific	= patch_alc850_specific
+	.build_specific	= patch_alc850_specific,
+	.update_jacks = alc850_update_jacks
 };
 
 int patch_alc850(ac97_t *ac97)
@@ -1911,9 +1996,17 @@
 /*
  * C-Media CM97xx codecs
  */
+static void cm9738_update_jacks(ac97_t *ac97)
+{
+	/* shared Line-In */
+	snd_ac97_update_bits(ac97, AC97_CM9738_VENDOR_CTRL, 1 << 10,
+			     is_shared_linein(ac97) ? (1 << 10) : 0);
+}
+
 static const snd_kcontrol_new_t snd_ac97_cm9738_controls[] = {
-	AC97_SINGLE("Line-In As Surround", AC97_CM9738_VENDOR_CTRL, 10, 1, 0),
 	AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0),
+	AC97_SURROUND_JACK_MODE_CTL,
+	AC97_CHANNEL_MODE_4CH_CTL,
 };
 
 static int patch_cm9738_specific(ac97_t * ac97)
@@ -1922,7 +2015,8 @@
 }
 
 static struct snd_ac97_build_ops patch_cm9738_ops = {
-	.build_specific	= patch_cm9738_specific
+	.build_specific	= patch_cm9738_specific,
+	.update_jacks = cm9738_update_jacks
 };
 
 int patch_cm9738(ac97_t * ac97)
@@ -1986,34 +2080,19 @@
 	/* BIT 8: SPD32 - 32bit SPDIF - not supported yet */
 };
 
-static int snd_ac97_cm9739_center_mic_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static void cm9739_update_jacks(ac97_t *ac97)
 {
-	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-	if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x1000)
-		ucontrol->value.integer.value[0] = 1;
-	else
-		ucontrol->value.integer.value[0] = 0;
-	return 0;
-}
-
-static int snd_ac97_cm9739_center_mic_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
-	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-	return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000,
-				    ucontrol->value.integer.value[0] ? 
-				    0x1000 : 0x2000);
+	/* shared Line-In */
+	snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 1 << 10,
+			     is_shared_linein(ac97) ? (1 << 10) : 0);
+	/* shared Mic */
+	snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000,
+			     is_shared_micin(ac97) ? 0x1000 : 0x2000);
 }
 
 static const snd_kcontrol_new_t snd_ac97_cm9739_controls[] = {
-	AC97_SINGLE("Line-In As Surround", AC97_CM9739_MULTI_CHAN, 10, 1, 0),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Mic As Center/LFE",
-		.info = snd_ac97_info_volsw,
-		.get = snd_ac97_cm9739_center_mic_get,
-		.put = snd_ac97_cm9739_center_mic_put,
-		.private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
-	},
+	AC97_SURROUND_JACK_MODE_CTL,
+	AC97_CHANNEL_MODE_CTL,
 };
 
 static int patch_cm9739_specific(ac97_t * ac97)
@@ -2028,7 +2107,8 @@
 
 static struct snd_ac97_build_ops patch_cm9739_ops = {
 	.build_specific	= patch_cm9739_specific,
-	.build_post_spdif = patch_cm9739_post_spdif
+	.build_post_spdif = patch_cm9739_post_spdif,
+	.update_jacks = cm9739_update_jacks
 };
 
 int patch_cm9739(ac97_t * ac97)
@@ -2087,71 +2167,97 @@
 }
 
 #define AC97_CM9761_MULTI_CHAN	0x64
+#define AC97_CM9761_FUNC	0x66
 #define AC97_CM9761_SPDIF_CTRL	0x6c
 
-static int snd_ac97_cm9761_linein_rear_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static void cm9761_update_jacks(ac97_t *ac97)
 {
-	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-	if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x0400)
-		ucontrol->value.integer.value[0] = 1;
-	else
-		ucontrol->value.integer.value[0] = 0;
-	return 0;
-}
-
-static int snd_ac97_cm9761_linein_rear_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
-	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-	unsigned short vals[2][2] = {
+	unsigned short surr_vals[2][2] = {
 		{ 0x0008, 0x0400 }, /* off, on */
 		{ 0x0000, 0x0408 }, /* off, on (9761-82 rev.B) */
 	};
-	return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x0408,
-				    vals[ac97->spec.dev_flags][!!ucontrol->value.integer.value[0]]);
-}
-
-static int snd_ac97_cm9761_center_mic_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
-	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-	if (ac97->regs[AC97_CM9739_MULTI_CHAN] & 0x1000)
-		ucontrol->value.integer.value[0] = 1;
-	else
-		ucontrol->value.integer.value[0] = 0;
-	if (ac97->spec.dev_flags) /* 9761-82 rev.B */
-		ucontrol->value.integer.value[0] = !ucontrol->value.integer.value[0];
-	return 0;
-}
-
-static int snd_ac97_cm9761_center_mic_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
-	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-	unsigned short vals[2][2] = {
+	unsigned short clfe_vals[2][2] = {
 		{ 0x2000, 0x1880 }, /* off, on */
 		{ 0x1000, 0x2880 }, /* off, on (9761-82 rev.B) */
 	};
-	return snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3880,
-				    vals[ac97->spec.dev_flags][!!ucontrol->value.integer.value[0]]);
+
+	/* shared Line-In */
+	snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x0408,
+			     surr_vals[ac97->spec.dev_flags][is_shared_linein(ac97)]);
+	/* shared Mic */
+	snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3880,
+			     clfe_vals[ac97->spec.dev_flags][is_shared_micin(ac97)]);
 }
 
 static const snd_kcontrol_new_t snd_ac97_cm9761_controls[] = {
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Line-In As Surround",
-		.info = snd_ac97_info_volsw,
-		.get = snd_ac97_cm9761_linein_rear_get,
-		.put = snd_ac97_cm9761_linein_rear_put,
-		.private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
-	},
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Mic As Center/LFE",
-		.info = snd_ac97_info_volsw,
-		.get = snd_ac97_cm9761_center_mic_get,
-		.put = snd_ac97_cm9761_center_mic_put,
-		.private_value = AC97_SINGLE_VALUE(0, 0, 1, 0) /* only mask needed */
-	},
+	AC97_SURROUND_JACK_MODE_CTL,
+	AC97_CHANNEL_MODE_CTL,
 };
 
+static int cm9761_spdif_out_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	static char *texts[] = { "AC-Link", "ADC", "SPDIF-In" };
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 3;
+	if (uinfo->value.enumerated.item > 2)
+		uinfo->value.enumerated.item = 2;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int cm9761_spdif_out_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+
+	if (ac97->regs[AC97_CM9761_FUNC] & 0x1)
+		ucontrol->value.enumerated.item[0] = 2; /* SPDIF-loopback */
+	else if (ac97->regs[AC97_CM9761_SPDIF_CTRL] & 0x2)
+		ucontrol->value.enumerated.item[0] = 1; /* ADC loopback */
+	else
+		ucontrol->value.enumerated.item[0] = 0; /* AC-link */
+	return 0;
+}
+
+static int cm9761_spdif_out_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+
+	if (ucontrol->value.enumerated.item[0] == 2)
+		return snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0x1);
+	snd_ac97_update_bits(ac97, AC97_CM9761_FUNC, 0x1, 0);
+	return snd_ac97_update_bits(ac97, AC97_CM9761_SPDIF_CTRL, 0x2,
+				    ucontrol->value.enumerated.item[0] == 1 ? 0x2 : 0);
+}
+
+static const char *cm9761_dac_clock[] = { "AC-Link", "SPDIF-In", "Both" };
+static const struct ac97_enum cm9761_dac_clock_enum =
+	AC97_ENUM_SINGLE(AC97_CM9761_SPDIF_CTRL, 9, 3, cm9761_dac_clock);
+
+static const snd_kcontrol_new_t snd_ac97_cm9761_controls_spdif[] = {
+	{ /* BIT 1: SPDIFS */
+		.iface	= SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name	= SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source",
+		.info = cm9761_spdif_out_source_info,
+		.get = cm9761_spdif_out_source_get,
+		.put = cm9761_spdif_out_source_put,
+	},
+	/* BIT 2: IG_SPIV */
+	AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Valid Switch", AC97_CM9761_SPDIF_CTRL, 2, 1, 0),
+	/* BIT 3: SPI2F */
+	AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Monitor", AC97_CM9761_SPDIF_CTRL, 3, 1, 0), 
+	/* BIT 4: SPI2SDI */
+	AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), AC97_CM9761_SPDIF_CTRL, 4, 1, 0),
+	/* BIT 9-10: DAC_CTL */
+	AC97_ENUM("DAC Clock Source", cm9761_dac_clock_enum),
+};
+
+static int patch_cm9761_post_spdif(ac97_t * ac97)
+{
+	return patch_build_controls(ac97, snd_ac97_cm9761_controls_spdif, ARRAY_SIZE(snd_ac97_cm9761_controls_spdif));
+}
+
 static int patch_cm9761_specific(ac97_t * ac97)
 {
 	return patch_build_controls(ac97, snd_ac97_cm9761_controls, ARRAY_SIZE(snd_ac97_cm9761_controls));
@@ -2159,7 +2265,8 @@
 
 static struct snd_ac97_build_ops patch_cm9761_ops = {
 	.build_specific	= patch_cm9761_specific,
-	.build_post_spdif = patch_cm9739_post_spdif /* hope it's identical... */
+	.build_post_spdif = patch_cm9761_post_spdif,
+	.update_jacks = cm9761_update_jacks
 };
 
 int patch_cm9761(ac97_t *ac97)
@@ -2193,24 +2300,25 @@
 	/* to be sure: we overwrite the ext status bits */
 	snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, 0x05c0);
 	/* Don't set 0x0200 here.  This results in the silent analog output */
-	snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0009);
+	snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0001); /* enable spdif-in */
 	ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
 
 	/* set-up multi channel */
 	/* bit 15: pc master beep off
-	 * bit 14: ??
+	 * bit 14: pin47 = EAPD/SPDIF
 	 * bit 13: vref ctl [= cm9739]
-	 * bit 12: center/mic [= cm9739] (reverted on rev B)
-	 * bit 11: ?? (mic/center/lfe) (reverted on rev B)
-	 * bit 10: suddound/line [= cm9739]
-	 * bit  9: mix 2 surround
-	 * bit  8: ?
-	 * bit  7: ?? (mic/center/lfe)
-	 * bit  4: ?? (front)
-	 * bit  3: ?? (line-in/rear share) (revereted with rev B)
-	 * bit  2: ?? (surround)
-	 * bit  1: front mic
-	 * bit  0: mic boost
+	 * bit 12: CLFE control (reverted on rev B)
+	 * bit 11: Mic/center share (reverted on rev B)
+	 * bit 10: suddound/line share
+	 * bit  9: Analog-in mix -> surround
+	 * bit  8: Analog-in mix -> CLFE
+	 * bit  7: Mic/LFE share (mic/center/lfe)
+	 * bit  5: vref select (9761A)
+	 * bit  4: front control
+	 * bit  3: surround control (revereted with rev B)
+	 * bit  2: front mic
+	 * bit  1: stereo mic
+	 * bit  0: mic boost level (0=20dB, 1=30dB)
 	 */
 
 #if 0
@@ -2230,6 +2338,47 @@
 	return 0;
 }
        
+#define AC97_CM9780_SIDE	0x60
+#define AC97_CM9780_JACK	0x62
+#define AC97_CM9780_MIXER	0x64
+#define AC97_CM9780_MULTI_CHAN	0x66
+#define AC97_CM9780_SPDIF	0x6c
+
+static const char *cm9780_ch_select[] = { "Front", "Side", "Center/LFE", "Rear" };
+static const struct ac97_enum cm9780_ch_select_enum =
+	AC97_ENUM_SINGLE(AC97_CM9780_MULTI_CHAN, 6, 4, cm9780_ch_select);
+static const snd_kcontrol_new_t cm9780_controls[] = {
+	AC97_DOUBLE("Side Playback Switch", AC97_CM9780_SIDE, 15, 7, 1, 1),
+	AC97_DOUBLE("Side Playback Volume", AC97_CM9780_SIDE, 8, 0, 31, 0),
+	AC97_ENUM("Side Playback Route", cm9780_ch_select_enum),
+};
+
+static int patch_cm9780_specific(ac97_t *ac97)
+{
+	return patch_build_controls(ac97, cm9780_controls, ARRAY_SIZE(cm9780_controls));
+}
+
+static struct snd_ac97_build_ops patch_cm9780_ops = {
+	.build_specific	= patch_cm9780_specific,
+	.build_post_spdif = patch_cm9761_post_spdif	/* identical with CM9761 */
+};
+
+int patch_cm9780(ac97_t *ac97)
+{
+	unsigned short val;
+
+	ac97->build_ops = &patch_cm9780_ops;
+
+	/* enable spdif */
+	if (ac97->ext_id & AC97_EI_SPDIF) {
+		ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
+		val = snd_ac97_read(ac97, AC97_CM9780_SPDIF);
+		val |= 0x1; /* SPDI_EN */
+		snd_ac97_write_cache(ac97, AC97_CM9780_SPDIF, val);
+	}
+
+	return 0;
+}
 
 /*
  * VIA VT1616 codec
@@ -2263,9 +2412,21 @@
 	return 0;
 }
 
+/*
+ */
+static void it2646_update_jacks(ac97_t *ac97)
+{
+	/* shared Line-In */
+	snd_ac97_update_bits(ac97, 0x76, 1 << 9,
+			     is_shared_linein(ac97) ? (1<<9) : 0);
+	/* shared Mic */
+	snd_ac97_update_bits(ac97, 0x76, 1 << 10,
+			     is_shared_micin(ac97) ? (1<<10) : 0);
+}
+
 static const snd_kcontrol_new_t snd_ac97_controls_it2646[] = {
-	AC97_SINGLE("Line-In As Surround", 0x76, 9, 1, 0),
-	AC97_SINGLE("Mic As Center/LFE", 0x76, 10, 1, 0),
+	AC97_SURROUND_JACK_MODE_CTL,
+	AC97_CHANNEL_MODE_CTL,
 };
 
 static const snd_kcontrol_new_t snd_ac97_spdif_controls_it2646[] = {
@@ -2285,7 +2446,8 @@
 }
 
 static struct snd_ac97_build_ops patch_it2646_ops = {
-	.build_specific	= patch_it2646_specific
+	.build_specific	= patch_it2646_specific,
+	.update_jacks = it2646_update_jacks
 };
 
 int patch_it2646(ac97_t * ac97)
@@ -2297,12 +2459,29 @@
 	return 0;
 }
 
-/* Si3036/8 specific registers */
+/*
+ * Si3036 codec
+ */
+
 #define AC97_SI3036_CHIP_ID     0x5a
+#define AC97_SI3036_LINE_CFG    0x5c
+
+static const snd_kcontrol_new_t snd_ac97_controls_si3036[] = {
+AC97_DOUBLE("Modem Speaker Volume", 0x5c, 14, 12, 3, 1)
+};
+
+static int patch_si3036_specific(ac97_t * ac97)
+{
+	return patch_build_controls(ac97, snd_ac97_controls_si3036, ARRAY_SIZE(snd_ac97_controls_si3036));
+}
+
+static struct snd_ac97_build_ops patch_si3036_ops = {
+	.build_specific	= patch_si3036_specific,
+};
 
 int mpatch_si3036(ac97_t * ac97)
 {
-	//printk("mpatch_si3036: chip id = %x\n", snd_ac97_read(ac97, 0x5a));
+	ac97->build_ops = &patch_si3036_ops;
 	snd_ac97_write_cache(ac97, 0x5c, 0xf210 );
 	snd_ac97_write_cache(ac97, 0x68, 0);
 	return 0;
diff --git a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h
index 6db51c9..7b7377d 100644
--- a/sound/pci/ac97/ac97_patch.h
+++ b/sound/pci/ac97/ac97_patch.h
@@ -54,6 +54,7 @@
 int patch_cm9738(ac97_t * ac97);
 int patch_cm9739(ac97_t * ac97);
 int patch_cm9761(ac97_t * ac97);
+int patch_cm9780(ac97_t * ac97);
 int patch_vt1616(ac97_t * ac97);
 int patch_it2646(ac97_t * ac97);
 int mpatch_si3036(ac97_t * ac97);
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index 984d5d4..eb5c36d 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -98,6 +98,8 @@
 #define ALI_LEF_CHANNEL		23
 #define ALI_SURR_LEFT_CHANNEL	26
 #define ALI_SURR_RIGHT_CHANNEL	25
+#define ALI_MODEM_IN_CHANNEL    21
+#define ALI_MODEM_OUT_CHANNEL   20
 
 #define	SNDRV_ALI_VOICE_TYPE_PCM	01
 #define SNDRV_ALI_VOICE_TYPE_OTH	02
@@ -122,7 +124,15 @@
 
 #define ALI_SCTRL		0x48
 #define   ALI_SPDIF_OUT_ENABLE		0x20
+#define   ALI_SCTRL_LINE_IN2		(1 << 9)
+#define   ALI_SCTRL_GPIO_IN2		(1 << 13)
+#define   ALI_SCTRL_LINE_OUT_EN 	(1 << 20)
+#define   ALI_SCTRL_GPIO_OUT_EN 	(1 << 23)
+#define   ALI_SCTRL_CODEC1_READY	(1 << 24)
+#define   ALI_SCTRL_CODEC2_READY	(1 << 25)
 #define ALI_AC97_GPIO		0x4c
+#define   ALI_AC97_GPIO_ENABLE		0x8000
+#define   ALI_AC97_GPIO_DATA_SHIFT	16
 #define ALI_SPDIF_CS		0x70
 #define ALI_SPDIF_CTRL		0x74
 #define   ALI_SPDIF_IN_FUNC_ENABLE	0x02
@@ -143,6 +153,7 @@
 	#define TARGET_REACHED		0x00008000
 	#define MIXER_OVERFLOW		0x00000800
 	#define MIXER_UNDERFLOW		0x00000400
+	#define GPIO_IRQ		0x01000000
 #define ALI_SBBL_SBCL           0xc0
 #define ALI_SBCTRL_SBE2R_SBDD   0xc4
 #define ALI_STIMER		0xc8
@@ -162,6 +173,9 @@
 
 #define ALI_REG(codec, x) ((codec)->port + x)
 
+#define MAX_CODECS 2
+
+
 typedef struct snd_stru_ali ali_t;
 typedef struct snd_ali_stru_voice snd_ali_voice_t;
 
@@ -245,7 +259,7 @@
 	struct pci_dev	*pci_m7101;
 
 	snd_card_t	*card;
-	snd_pcm_t	*pcm;
+	snd_pcm_t	*pcm[MAX_CODECS];
 	alidev_t	synth;
 	snd_ali_channel_control_t chregs;
 
@@ -255,8 +269,10 @@
 	unsigned int spurious_irq_count;
 	unsigned int spurious_irq_max_delta;
 
+	unsigned int num_of_codecs;
+
 	ac97_bus_t *ac97_bus;
-	ac97_t *ac97;
+	ac97_t *ac97[MAX_CODECS];
 	unsigned short	ac97_ext_id;
 	unsigned short	ac97_ext_status;
 
@@ -489,7 +505,12 @@
 	ali_t *codec = ac97->private_data;
 
 	snd_ali_printk("codec_write: reg=%xh data=%xh.\n", reg, val);
-	snd_ali_codec_poke(codec, 0, reg, val);
+	if(reg == AC97_GPIO_STATUS) {
+		outl((val << ALI_AC97_GPIO_DATA_SHIFT)|ALI_AC97_GPIO_ENABLE,
+			ALI_REG(codec, ALI_AC97_GPIO));
+		return;
+	}
+	snd_ali_codec_poke(codec, ac97->num, reg, val);
 	return ;
 }
 
@@ -499,7 +520,7 @@
 	ali_t *codec = ac97->private_data;
 
 	snd_ali_printk("codec_read reg=%xh.\n", reg);
-	return (snd_ali_codec_peek(codec, 0, reg));
+	return (snd_ali_codec_peek(codec, ac97->num, reg));
 }
 
 /*
@@ -1051,7 +1072,7 @@
 }
 
 
-static snd_ali_voice_t *snd_ali_alloc_voice(ali_t * codec, int type, int rec)
+static snd_ali_voice_t *snd_ali_alloc_voice(ali_t * codec, int type, int rec, int channel)
 {
 	snd_ali_voice_t *pvoice = NULL;
 	unsigned long flags;
@@ -1061,7 +1082,8 @@
 
 	spin_lock_irqsave(&codec->voice_alloc, flags);
 	if (type == SNDRV_ALI_VOICE_TYPE_PCM) {
-		idx = snd_ali_find_free_channel(codec,rec);
+		idx = channel > 0 ? snd_ali_alloc_pcm_channel(codec, channel) :
+			snd_ali_find_free_channel(codec,rec);
 		if(idx < 0) {
 			snd_printk("ali_alloc_voice: err.\n");
 			spin_unlock_irqrestore(&codec->voice_alloc, flags);
@@ -1297,7 +1319,7 @@
 
 	if (params_buffer_size(hw_params)/2 != params_period_size(hw_params)) {
 		if (evoice == NULL) {
-			evoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 0);
+			evoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 0, -1);
 			if (evoice == NULL)
 				return -ENOMEM;
 			pvoice->extra = evoice;
@@ -1328,13 +1350,13 @@
 	return 0;
 }
 
-static int snd_ali_capture_hw_params(snd_pcm_substream_t * substream,
+static int snd_ali_hw_params(snd_pcm_substream_t * substream,
 				 snd_pcm_hw_params_t * hw_params)
 {
 	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
 }
 
-static int snd_ali_capture_hw_free(snd_pcm_substream_t * substream)
+static int snd_ali_hw_free(snd_pcm_substream_t * substream)
 {
 	return snd_pcm_lib_free_pages(substream);
 }
@@ -1428,7 +1450,7 @@
 }
 
 
-static int snd_ali_capture_prepare(snd_pcm_substream_t * substream)
+static int snd_ali_prepare(snd_pcm_substream_t * substream)
 {
 	ali_t *codec = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
@@ -1446,11 +1468,13 @@
 
 	spin_lock_irqsave(&codec->reg_lock, flags);
 
-	snd_ali_printk("capture_prepare...\n");
+	snd_ali_printk("ali_prepare...\n");
 
 	snd_ali_enable_special_channel(codec,pvoice->number);
 
-	Delta = snd_ali_convert_rate(runtime->rate, 1);
+	Delta = (pvoice->number == ALI_MODEM_IN_CHANNEL ||
+		 pvoice->number == ALI_MODEM_OUT_CHANNEL) ? 
+		0x1000 : snd_ali_convert_rate(runtime->rate, pvoice->mode);
 
 	// Prepare capture intr channel
 	if (pvoice->number == ALI_SPDIF_IN_CHANNEL) {
@@ -1534,7 +1558,7 @@
 }
 
 
-static snd_pcm_uframes_t snd_ali_capture_pointer(snd_pcm_substream_t *substream)
+static snd_pcm_uframes_t snd_ali_pointer(snd_pcm_substream_t *substream)
 {
 	ali_t *codec = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
@@ -1616,7 +1640,8 @@
 	}
 }
 
-static int snd_ali_playback_open(snd_pcm_substream_t * substream)
+static int snd_ali_open(snd_pcm_substream_t * substream, int rec, int channel,
+		snd_pcm_hardware_t *phw)
 {
 	ali_t *codec = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
@@ -1624,7 +1649,7 @@
 	unsigned long flags = 0;
 
 	spin_lock_irqsave(&codec->reg_lock, flags);
-	pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 0);
+	pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, rec, channel);
 	if (pvoice == NULL) {
 		spin_unlock_irqrestore(&codec->reg_lock, flags);
 		return -EAGAIN;
@@ -1636,49 +1661,31 @@
 	runtime->private_data = pvoice;
 	runtime->private_free = snd_ali_pcm_free_substream;
 
-	runtime->hw = snd_ali_playback;
+	runtime->hw = *phw;
 	snd_pcm_set_sync(substream);
 	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);
 	return 0;
 }
 
+static int snd_ali_playback_open(snd_pcm_substream_t * substream)
+{
+	return snd_ali_open(substream, 0, -1, &snd_ali_playback);
+}
 
 static int snd_ali_capture_open(snd_pcm_substream_t * substream)
 {
-	ali_t *codec = snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_ali_voice_t *pvoice;
-	unsigned long flags;
-
-	spin_lock_irqsave(&codec->reg_lock, flags);
-	pvoice = snd_ali_alloc_voice(codec, SNDRV_ALI_VOICE_TYPE_PCM, 1);
-	if (pvoice == NULL) {
-		spin_unlock_irqrestore(&codec->reg_lock, flags);
-		return -EAGAIN;
-	}
-	pvoice->codec = codec;
-	spin_unlock_irqrestore(&codec->reg_lock, flags);
-
-	pvoice->substream = substream;
-	runtime->private_data = pvoice;
-	runtime->private_free = snd_ali_pcm_free_substream;
-	runtime->hw = snd_ali_capture;
-	snd_pcm_set_sync(substream);
-	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 64*1024);
-	return 0;
+	return snd_ali_open(substream, 1, -1, &snd_ali_capture);
 }
 
-
 static int snd_ali_playback_close(snd_pcm_substream_t * substream)
 {
 	return 0;
 }
 
-static int snd_ali_capture_close(snd_pcm_substream_t * substream)
+static int snd_ali_close(snd_pcm_substream_t * substream)
 {
 	ali_t *codec = snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_ali_voice_t *pvoice = (snd_ali_voice_t *) runtime->private_data;
+	snd_ali_voice_t *pvoice = (snd_ali_voice_t *) substream->runtime->private_data;
 
 	snd_ali_disable_special_channel(codec,pvoice->number);
 
@@ -1698,29 +1705,121 @@
 
 static snd_pcm_ops_t snd_ali_capture_ops = {
 	.open =		snd_ali_capture_open,
-	.close =	snd_ali_capture_close,
+	.close =	snd_ali_close,
 	.ioctl =	snd_ali_ioctl,
-	.hw_params =	snd_ali_capture_hw_params,
-	.hw_free =	snd_ali_capture_hw_free,
-	.prepare =	snd_ali_capture_prepare,
+	.hw_params =	snd_ali_hw_params,
+	.hw_free =	snd_ali_hw_free,
+	.prepare =	snd_ali_prepare,
 	.trigger =	snd_ali_trigger,
-	.pointer =	snd_ali_capture_pointer,
+	.pointer =	snd_ali_pointer,
+};
+
+/*
+ * Modem PCM
+ */
+
+static int snd_ali_modem_hw_params(snd_pcm_substream_t * substream,
+				 snd_pcm_hw_params_t * hw_params)
+{
+	ali_t *chip = snd_pcm_substream_chip(substream);
+	unsigned int modem_num = chip->num_of_codecs - 1;
+	snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_RATE, params_rate(hw_params));
+	snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_LEVEL, 0);
+	return snd_ali_hw_params(substream, hw_params);
+}
+
+static snd_pcm_hardware_t snd_ali_modem =
+{
+	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
+				 SNDRV_PCM_INFO_MMAP_VALID |
+				 SNDRV_PCM_INFO_RESUME |
+				 SNDRV_PCM_INFO_SYNC_START),
+	.formats =		SNDRV_PCM_FMTBIT_S16_LE,
+	.rates =		SNDRV_PCM_RATE_KNOT|SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_16000,
+	.rate_min =		8000,
+	.rate_max =		16000,
+	.channels_min =		1,
+	.channels_max =		1,
+	.buffer_bytes_max =	(256*1024),
+	.period_bytes_min =	64,
+	.period_bytes_max =	(256*1024),
+	.periods_min =		1,
+	.periods_max =		1024,
+	.fifo_size =		0,
+};
+
+static int snd_ali_modem_open(snd_pcm_substream_t * substream, int rec, int channel)
+{
+	static unsigned int rates [] = {8000,9600,12000,16000};
+	static snd_pcm_hw_constraint_list_t hw_constraint_rates = {
+		.count = ARRAY_SIZE(rates),
+		.list = rates,
+		.mask = 0,
+	};
+	int err = snd_ali_open(substream, rec, channel, &snd_ali_modem);
+	if (err)
+		return err;
+	return snd_pcm_hw_constraint_list(substream->runtime, 0,
+			SNDRV_PCM_HW_PARAM_RATE, &hw_constraint_rates);
+}
+
+static int snd_ali_modem_playback_open(snd_pcm_substream_t * substream)
+{
+	return snd_ali_modem_open(substream, 0, ALI_MODEM_OUT_CHANNEL);
+}
+
+static int snd_ali_modem_capture_open(snd_pcm_substream_t * substream)
+{
+	return snd_ali_modem_open(substream, 1, ALI_MODEM_IN_CHANNEL);
+}
+
+static snd_pcm_ops_t snd_ali_modem_playback_ops = {
+	.open =		snd_ali_modem_playback_open,
+	.close =	snd_ali_close,
+	.ioctl =	snd_pcm_lib_ioctl,
+	.hw_params =	snd_ali_modem_hw_params,
+	.hw_free =	snd_ali_hw_free,
+	.prepare =	snd_ali_prepare,
+	.trigger =	snd_ali_trigger,
+	.pointer =	snd_ali_pointer,
+};
+
+static snd_pcm_ops_t snd_ali_modem_capture_ops = {
+	.open =		snd_ali_modem_capture_open,
+	.close =	snd_ali_close,
+	.ioctl =	snd_pcm_lib_ioctl,
+	.hw_params =	snd_ali_modem_hw_params,
+	.hw_free =	snd_ali_hw_free,
+	.prepare =	snd_ali_prepare,
+	.trigger =	snd_ali_trigger,
+	.pointer =	snd_ali_pointer,
+};
+
+
+struct ali_pcm_description {
+	char *name;
+	unsigned int playback_num;
+	unsigned int capture_num;
+	snd_pcm_ops_t *playback_ops;
+	snd_pcm_ops_t *capture_ops;
 };
 
 
 static void snd_ali_pcm_free(snd_pcm_t *pcm)
 {
 	ali_t *codec = pcm->private_data;
-	codec->pcm = NULL;
+	codec->pcm[pcm->device] = NULL;
 }
 
-static int __devinit snd_ali_pcm(ali_t * codec, int device, snd_pcm_t ** rpcm)
+
+static int __devinit snd_ali_pcm(ali_t * codec, int device, struct ali_pcm_description *desc)
 {
 	snd_pcm_t *pcm;
 	int err;
 
-	if (rpcm) *rpcm = NULL;
-	err = snd_pcm_new(codec->card, "ALI 5451", device, ALI_CHANNELS, 1, &pcm);
+	err = snd_pcm_new(codec->card, desc->name, device,
+			  desc->playback_num, desc->capture_num, &pcm);
 	if (err < 0) {
 		snd_printk("snd_ali_pcm: err called snd_pcm_new.\n");
 		return err;
@@ -1728,20 +1827,36 @@
 	pcm->private_data = codec;
 	pcm->private_free = snd_ali_pcm_free;
 	pcm->info_flags = 0;
-	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ali_playback_ops);
-	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ali_capture_ops);
+	if (desc->playback_ops)
+		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, desc->playback_ops);
+	if (desc->capture_ops)
+		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, desc->capture_ops);
 
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
 					      snd_dma_pci_data(codec->pci), 64*1024, 128*1024);
 
 	pcm->info_flags = 0;
 	pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
-	strcpy(pcm->name, "ALI 5451");
-	codec->pcm = pcm;
-	if (rpcm) *rpcm = pcm;
+	strcpy(pcm->name, desc->name);
+	codec->pcm[0] = pcm;
 	return 0;
 }
 
+struct ali_pcm_description ali_pcms[] = {
+	{ "ALI 5451", ALI_CHANNELS, 1, &snd_ali_playback_ops, &snd_ali_capture_ops },
+	{ "ALI 5451 modem", 1, 1, &snd_ali_modem_playback_ops, &snd_ali_modem_capture_ops }
+};
+
+static int __devinit snd_ali_build_pcms(ali_t *codec)
+{
+	int i, err;
+	for(i = 0 ; i < codec->num_of_codecs && i < ARRAY_SIZE(ali_pcms) ; i++)
+		if((err = snd_ali_pcm(codec, i, &ali_pcms[i])) < 0)
+			return err;
+	return 0;
+}
+
+
 #define ALI5451_SPDIF(xname, xindex, value) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex,\
 .info = snd_ali5451_spdif_info, .get = snd_ali5451_spdif_get, \
@@ -1860,14 +1975,14 @@
 static void snd_ali_mixer_free_ac97(ac97_t *ac97)
 {
 	ali_t *codec = ac97->private_data;
-	codec->ac97 = NULL;
+	codec->ac97[ac97->num] = NULL;
 }
 
 static int __devinit snd_ali_mixer(ali_t * codec)
 {
 	ac97_template_t ac97;
 	unsigned int idx;
-	int err;
+	int i, err;
 	static ac97_bus_ops_t ops = {
 		.write = snd_ali_codec_write,
 		.read = snd_ali_codec_read,
@@ -1880,10 +1995,16 @@
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = codec;
 	ac97.private_free = snd_ali_mixer_free_ac97;
-	if ((err = snd_ac97_mixer(codec->ac97_bus, &ac97, &codec->ac97)) < 0) {
-		snd_printk("ali mixer creating error.\n");
+
+	for ( i = 0 ; i < codec->num_of_codecs ; i++) {
+		ac97.num = i;
+		if ((err = snd_ac97_mixer(codec->ac97_bus, &ac97, &codec->ac97[i])) < 0) {
+			snd_printk("ali mixer %d creating error.\n", i);
+			if(i == 0)
 		return err;
 	}
+	}
+
 	if (codec->spdif_support) {
 		for(idx = 0; idx < ARRAY_SIZE(snd_ali5451_mixer_spdif); idx++) {
 			err=snd_ctl_add(codec->card, snd_ctl_new1(&snd_ali5451_mixer_spdif[idx], codec));
@@ -1904,8 +2025,12 @@
 	if (! im)
 		return 0;
 
-	snd_pcm_suspend_all(chip->pcm);
-	snd_ac97_suspend(chip->ac97);
+	for(i = 0 ; i < chip->num_of_codecs ; i++) {
+		if (chip->pcm[i])
+			snd_pcm_suspend_all(chip->pcm[i]);
+		if(chip->ac97[i])
+			snd_ac97_suspend(chip->ac97[i]);
+	}
 
 	spin_lock_irq(&chip->reg_lock);
 	
@@ -1969,7 +2094,9 @@
 	
 	spin_unlock_irq(&chip->reg_lock);
 
-	snd_ac97_resume(chip->ac97);
+	for(i = 0 ; i < chip->num_of_codecs ; i++)
+		if(chip->ac97[i])
+			snd_ac97_resume(chip->ac97[i]);
 	
 	return 0;
 }
@@ -2036,11 +2163,37 @@
 		codec->spdif_mask = 0x00000002;
 	}
 
+	codec->num_of_codecs = 1;
+
+	/* secondary codec - modem */
+	if (inl(ALI_REG(codec, ALI_SCTRL)) & ALI_SCTRL_CODEC2_READY) {
+		codec->num_of_codecs++;
+		outl(inl(ALI_REG(codec, ALI_SCTRL)) |
+			(ALI_SCTRL_LINE_IN2|ALI_SCTRL_GPIO_IN2|ALI_SCTRL_LINE_OUT_EN),
+			ALI_REG(codec, ALI_SCTRL));
+	}
+
 	snd_ali_printk("chip initialize succeed.\n");
 	return 0;
 
 }
 
+/* proc for register dump */
+static void snd_ali_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buf)
+{
+	ali_t *codec = entry->private_data;
+	int i;
+	for(i = 0 ; i < 256 ; i+= 4)
+		snd_iprintf(buf, "%02x: %08x\n", i, inl(ALI_REG(codec, i)));
+}
+
+static void __devinit snd_ali_proc_init(ali_t *codec)
+{
+	snd_info_entry_t *entry;
+	if(!snd_card_proc_new(codec->card, "ali5451", &entry))
+		snd_info_set_text_ops(entry, codec, 1024, snd_ali_proc_read);
+}
+
 static int __devinit snd_ali_resources(ali_t *codec)
 {
 	int err;
@@ -2233,11 +2386,13 @@
 	}
 	
 	snd_ali_printk("pcm building ...\n");
-	if ((err = snd_ali_pcm(codec, 0, NULL)) < 0) {
+	if ((err = snd_ali_build_pcms(codec)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
 
+	snd_ali_proc_init(codec);
+
 	strcpy(card->driver, "ALI5451");
 	strcpy(card->shortname, "ALI 5451");
 	
@@ -2270,7 +2425,7 @@
 
 static int __init alsa_card_ali_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_ali_exit(void)
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index f1a5f57..ca28b22 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -367,7 +367,7 @@
 	if ((gcr_status & 0x40) && (chip->capture_substream)) /* capturing */
 		snd_pcm_period_elapsed(chip->capture_substream);
 	if ((gcr_status & 0x10) && (chip->rmidi)) /* MPU401 interrupt */
-		snd_mpu401_uart_interrupt(irq, chip->rmidi, regs);
+		snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs);
 	/* release the gcr */
 	outb(gcr_status, chip->alt_port + 0xe);
 	
@@ -777,7 +777,7 @@
 
 static int __init alsa_card_als4000_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_als4000_exit(void)
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 6b04c0a..cafab4a 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -1334,8 +1334,8 @@
 
 static struct ac97_quirk ac97_quirks[] __devinitdata = {
 	{
-		.vendor = 0x103c,
-		.device = 0x006b,
+		.subvendor = 0x103c,
+		.subdevice = 0x006b,
 		.name = "HP Pavilion ZV5030US",
 		.type = AC97_TUNE_MUTE_LED
 	},
@@ -1645,7 +1645,7 @@
 
 static int __init alsa_card_atiixp_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_atiixp_exit(void)
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index fb7cece..a6b4b8d 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -463,6 +463,11 @@
 static void snd_atiixp_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
 {
 	atiixp_t *chip = ac97->private_data;
+	if (reg == AC97_GPIO_STATUS) {
+		atiixp_write(chip, MODEM_OUT_GPIO,
+			(val << ATI_REG_MODEM_OUT_GPIO_DATA_SHIFT) | ATI_REG_MODEM_OUT_GPIO_EN);
+		return;
+	}
 	snd_atiixp_codec_write(chip, ac97->num, reg, val);
 }
 
@@ -663,44 +668,33 @@
 {
 	atiixp_t *chip = snd_pcm_substream_chip(substream);
 	atiixp_dma_t *dma = (atiixp_dma_t *)substream->runtime->private_data;
-	unsigned int reg = 0;
-	int i;
+	int err = 0;
 
 	snd_assert(dma->ops->enable_transfer && dma->ops->flush_dma, return -EINVAL);
 
-	if (cmd != SNDRV_PCM_TRIGGER_START && cmd != SNDRV_PCM_TRIGGER_STOP)
-		return -EINVAL;
-
 	spin_lock(&chip->reg_lock);
-
-	/* hook off/on: via GPIO_OUT */
-	for (i = 0; i < NUM_ATI_CODECS; i++) {
-		if (chip->ac97[i]) {
-			reg = snd_ac97_read(chip->ac97[i], AC97_GPIO_STATUS);
-			break;
-	}
-	}
-	if(cmd == SNDRV_PCM_TRIGGER_START)
-		reg |= AC97_GPIO_LINE1_OH;
-	else
-		reg &= ~AC97_GPIO_LINE1_OH;
-	reg = (reg << ATI_REG_MODEM_OUT_GPIO_DATA_SHIFT) | ATI_REG_MODEM_OUT_GPIO_EN ;
-	atiixp_write(chip, MODEM_OUT_GPIO, reg);
-
-	if (cmd == SNDRV_PCM_TRIGGER_START) {
+	switch(cmd) {
+	case SNDRV_PCM_TRIGGER_START:
 		dma->ops->enable_transfer(chip, 1);
 		dma->running = 1;
-	} else {
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
 		dma->ops->enable_transfer(chip, 0);
 		dma->running = 0;
+		break;
+	default:
+		err = -EINVAL;
+		break;
 	}
+	if (! err) {
 	snd_atiixp_check_bus_busy(chip);
 	if (cmd == SNDRV_PCM_TRIGGER_STOP) {
 		dma->ops->flush_dma(chip);
 		snd_atiixp_check_bus_busy(chip);
 	}
+	}
 	spin_unlock(&chip->reg_lock);
-	return 0;
+	return err;
 }
 
 
@@ -1332,7 +1326,7 @@
 
 static int __init alsa_card_atiixp_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_atiixp_exit(void)
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index 889b4a1..f6236c6 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -375,7 +375,7 @@
 // initialization of the module
 static int __init alsa_card_vortex_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 // clean up the module
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index b8ae534..72bba7b 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -1520,7 +1520,7 @@
 {
 	int err;
 	snd_azf3328_dbgcallenter();
-	err = pci_module_init(&driver);
+	err = pci_register_driver(&driver);
 	snd_azf3328_dbgcallleave();
 	return err;
 }
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 89a7ffe..defdc5a 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -918,7 +918,7 @@
 {
 	if (load_all)
 		driver.id_table = snd_bt87x_default_ids;
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_bt87x_exit(void)
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h
index deb0288..da09cab 100644
--- a/sound/pci/ca0106/ca0106.h
+++ b/sound/pci/ca0106/ca0106.h
@@ -1,7 +1,7 @@
 /*
  *  Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
  *  Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
- *  Version: 0.0.20
+ *  Version: 0.0.21
  *
  *  FEATURES currently supported:
  *    See ca0106_main.c for features.
@@ -45,6 +45,8 @@
  *    Added I2C and SPI registers. Filled in interrupt enable.
  *  0.0.20
  *    Added GPIO info for SB Live 24bit.
+ *  0.0.21
+ *   Implement support for Line-in capture on SB Live 24bit.
  *
  *
  *  This code was initally based on code from ALSA's emu10k1x.c which is:
@@ -152,7 +154,7 @@
 						 * bit 9 0 = Mute / 1 = Analog out.
 						 * bit 10 0 = Line-in / 1 = Mic-in.
 						 * bit 11 0 = ? / 1 = ?
-						 * bit 12 0 = ? / 1 = ?
+						 * bit 12 0 = 48 Khz / 1 = 96 Khz Analog out on SB Live 24bit.
 						 * bit 13 0 = ? / 1 = ?
 						 * bit 14 0 = Mute / 1 = Analog out
 						 * bit 15 0 = ? / 1 = ?
@@ -475,9 +477,56 @@
 						/* Causes interrupts based on timer intervals. */
 #define SPI			0x7a		/* SPI: Serial Interface Register */
 #define I2C_A			0x7b		/* I2C Address. 32 bit */
-#define I2C_0			0x7c		/* I2C Data Port 0. 32 bit */
-#define I2C_1			0x7d		/* I2C Data Port 1. 32 bit */
+#define I2C_D0			0x7c		/* I2C Data Port 0. 32 bit */
+#define I2C_D1			0x7d		/* I2C Data Port 1. 32 bit */
+//I2C values
+#define I2C_A_ADC_ADD_MASK	0x000000fe	//The address is a 7 bit address
+#define I2C_A_ADC_RW_MASK	0x00000001	//bit mask for R/W
+#define I2C_A_ADC_TRANS_MASK	0x00000010  	//Bit mask for I2c address DAC value
+#define I2C_A_ADC_ABORT_MASK	0x00000020	//Bit mask for I2C transaction abort flag
+#define I2C_A_ADC_LAST_MASK	0x00000040	//Bit mask for Last word transaction
+#define I2C_A_ADC_BYTE_MASK	0x00000080	//Bit mask for Byte Mode
 
+#define I2C_A_ADC_ADD		0x00000034	//This is the Device address for ADC 
+#define I2C_A_ADC_READ		0x00000001	//To perform a read operation
+#define I2C_A_ADC_START		0x00000100	//Start I2C transaction
+#define I2C_A_ADC_ABORT		0x00000200	//I2C transaction abort
+#define I2C_A_ADC_LAST		0x00000400	//I2C last transaction
+#define I2C_A_ADC_BYTE		0x00000800	//I2C one byte mode
+
+#define I2C_D_ADC_REG_MASK	0xfe000000  	//ADC address register 
+#define I2C_D_ADC_DAT_MASK	0x01ff0000  	//ADC data register
+
+#define ADC_TIMEOUT		0x00000007	//ADC Timeout Clock Disable
+#define ADC_IFC_CTRL		0x0000000b	//ADC Interface Control
+#define ADC_MASTER		0x0000000c	//ADC Master Mode Control
+#define ADC_POWER		0x0000000d	//ADC PowerDown Control
+#define ADC_ATTEN_ADCL		0x0000000e	//ADC Attenuation ADCL
+#define ADC_ATTEN_ADCR		0x0000000f	//ADC Attenuation ADCR
+#define ADC_ALC_CTRL1		0x00000010	//ADC ALC Control 1
+#define ADC_ALC_CTRL2		0x00000011	//ADC ALC Control 2
+#define ADC_ALC_CTRL3		0x00000012	//ADC ALC Control 3
+#define ADC_NOISE_CTRL		0x00000013	//ADC Noise Gate Control
+#define ADC_LIMIT_CTRL		0x00000014	//ADC Limiter Control
+#define ADC_MUX			0x00000015  	//ADC Mux offset
+
+#if 0
+/* FIXME: Not tested yet. */
+#define ADC_GAIN_MASK		0x000000ff	//Mask for ADC Gain
+#define ADC_ZERODB		0x000000cf	//Value to set ADC to 0dB
+#define ADC_MUTE_MASK		0x000000c0	//Mask for ADC mute
+#define ADC_MUTE		0x000000c0	//Value to mute ADC
+#define ADC_OSR			0x00000008	//Mask for ADC oversample rate select
+#define ADC_TIMEOUT_DISABLE	0x00000008	//Value and mask to disable Timeout clock
+#define ADC_HPF_DISABLE		0x00000100	//Value and mask to disable High pass filter
+#define ADC_TRANWIN_MASK	0x00000070	//Mask for Length of Transient Window
+#endif
+
+#define ADC_MUX_MASK		0x0000000f	//Mask for ADC Mux
+#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 */
 #define PCM_FRONT_CHANNEL 0
@@ -508,9 +557,18 @@
 	unsigned short running;
 };
 
+typedef struct {
+        u32 serial;
+        char * name;
+        int ac97;
+	int gpio_type;
+	int i2c_adc;
+} ca0106_details_t;
+
 // definition of the chip-specific record
 struct snd_ca0106 {
 	snd_card_t *card;
+	ca0106_details_t *details;
 	struct pci_dev *pci;
 
 	unsigned long port;
@@ -531,6 +589,7 @@
 	u32 spdif_bits[4];             /* s/pdif out setup */
 	int spdif_enable;
 	int capture_source;
+	int capture_mic_line_in;
 
 	struct snd_dma_buffer buffer;
 };
@@ -547,3 +606,6 @@
 				   unsigned int chn, 
 				   unsigned int data);
 
+int snd_ca0106_i2c_write(ca0106_t *emu, u32 reg, u32 value);
+
+
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 82533b4..95c2892 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -1,7 +1,7 @@
 /*
  *  Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
  *  Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
- *  Version: 0.0.22
+ *  Version: 0.0.23
  *
  *  FEATURES currently supported:
  *    Front, Rear and Center/LFE.
@@ -77,6 +77,8 @@
  *    Add SPDIF capture using optional digital I/O module for SB Live 24bit. (Analog capture does not yet work.)
  *  0.0.22
  *    Add support for MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97. From kiksen, bug #901
+ *  0.0.23
+ *    Implement support for Line-in capture on SB Live 24bit.
  *
  *  BUGS:
  *    Some stability problems when unloading the snd-ca0106 kernel module.
@@ -136,6 +138,7 @@
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
 #include <sound/core.h>
 #include <sound/initval.h>
 #include <sound/pcm.h>
@@ -161,18 +164,32 @@
 
 #include "ca0106.h"
 
-typedef struct {
-	u32 serial;
-	char * name;
-} ca0106_names_t;
-
-static ca0106_names_t ca0106_chip_names[] = {
-	 { 0x10021102, "AudigyLS [SB0310]"} , 
-	 { 0x10051102, "AudigyLS [SB0310b]"} , /* Unknown AudigyLS that also says SB0310 on it */
-	 { 0x10061102, "Live! 7.1 24bit [SB0410]"} , /* New Sound Blaster Live! 7.1 24bit. This does not have an AC97. 53SB041000001 */
-	 { 0x10071102, "Live! 7.1 24bit [SB0413]"} , /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97.  */
-	 { 0x10091462, "MSI K8N Diamond MB [SB0438]"}, /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */
-	 { 0, "AudigyLS [Unknown]" }
+static ca0106_details_t ca0106_chip_details[] = {
+	 /* AudigyLS[SB0310] */
+	 { .serial = 0x10021102,
+	   .name   = "AudigyLS [SB0310]",
+	   .ac97   = 1 } , 
+	 /* Unknown AudigyLS that also says SB0310 on it */
+	 { .serial = 0x10051102,
+	   .name   = "AudigyLS [SB0310b]",
+	   .ac97   = 1 } ,
+	 /* New Sound Blaster Live! 7.1 24bit. This does not have an AC97. 53SB041000001 */
+	 { .serial = 0x10061102,
+	   .name   = "Live! 7.1 24bit [SB0410]",
+	   .gpio_type = 1,
+	   .i2c_adc = 1 } ,
+	 /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97.  */
+	 { .serial = 0x10071102,
+	   .name   = "Live! 7.1 24bit [SB0413]",
+	   .gpio_type = 1,
+	   .i2c_adc = 1 } ,
+	 /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */
+	 { .serial = 0x10091462,
+	   .name   = "MSI K8N Diamond MB [SB0438]",
+	   .gpio_type = 1,
+	   .i2c_adc = 1 } ,
+	 { .serial = 0,
+	   .name   = "AudigyLS [Unknown]" }
 };
 
 /* hardware definition */
@@ -200,10 +217,10 @@
 				 SNDRV_PCM_INFO_INTERLEAVED |
 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
 				 SNDRV_PCM_INFO_MMAP_VALID),
-	.formats =		SNDRV_PCM_FMTBIT_S16_LE,
-	.rates =		SNDRV_PCM_RATE_48000,
-	.rate_min =		48000,
-	.rate_max =		48000,
+	.formats =		SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE,
+	.rates =		SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000,
+	.rate_min =		44100,
+	.rate_max =		192000,
 	.channels_min =		2,
 	.channels_max =		2,
 	.buffer_bytes_max =	((65536 - 64) * 8),
@@ -246,6 +263,62 @@
 	spin_unlock_irqrestore(&emu->emu_lock, flags);
 }
 
+int snd_ca0106_i2c_write(ca0106_t *emu,
+				u32 reg,
+				u32 value)
+{
+	u32 tmp;
+	int timeout=0;
+	int status;
+	int retry;
+	if ((reg > 0x7f) || (value > 0x1ff))
+	{
+                snd_printk("i2c_write: invalid values.\n");
+		return -EINVAL;
+	}
+
+	tmp = reg << 25 | value << 16;
+	/* Not sure what this I2C channel controls. */
+	/* snd_ca0106_ptr_write(emu, I2C_D0, 0, tmp); */
+
+	/* This controls the I2C connected to the WM8775 ADC Codec */
+	snd_ca0106_ptr_write(emu, I2C_D1, 0, tmp);
+
+	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 = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);
+		snd_ca0106_ptr_write(emu, I2C_A, 0, tmp);
+
+		/* Wait till the transaction ends */
+		while(1)
+		{
+			status = snd_ca0106_ptr_read(emu, I2C_A, 0);
+                	//snd_printk("I2C:status=0x%x\n", status);
+			timeout++;
+			if((status & I2C_A_ADC_START)==0)
+				break;
+
+			if(timeout>1000)
+				break;
+		}
+		//Read back and see if the transaction is successful
+		if((status & I2C_A_ADC_ABORT)==0)
+			break;
+	}
+
+	if(retry==10)
+	{
+                snd_printk("Writing to ADC failed!\n");
+		return -EINVAL;
+	}
+    
+    	return 0;
+}
+
+
 static void snd_ca0106_intr_enable(ca0106_t *emu, unsigned int intrenb)
 {
 	unsigned long flags;
@@ -259,11 +332,7 @@
 
 static void snd_ca0106_pcm_free_substream(snd_pcm_runtime_t *runtime)
 {
-	ca0106_pcm_t *epcm = runtime->private_data;
-  
-	if (epcm) {
-		kfree(epcm);
-	}
+	kfree(runtime->private_data);
 }
 
 /* open_playback callback */
@@ -538,6 +607,61 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	ca0106_pcm_t *epcm = runtime->private_data;
 	int channel = epcm->channel_id;
+	u32 hcfg_mask = HCFG_CAPTURE_S32_LE;
+	u32 hcfg_set = 0x00000000;
+	u32 hcfg;
+	u32 over_sampling=0x2;
+	u32 reg71_mask = 0x0000c000 ; /* Global. Set ADC rate. */
+	u32 reg71_set = 0;
+	u32 reg71;
+	
+        //snd_printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, periods=%u, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size, runtime->periods, frames_to_bytes(runtime, 1));
+        //snd_printk("dma_addr=%x, dma_area=%p, table_base=%p\n",runtime->dma_addr, runtime->dma_area, table_base);
+	//snd_printk("dma_addr=%x, dma_area=%p, dma_bytes(size)=%x\n",emu->buffer.addr, emu->buffer.area, emu->buffer.bytes);
+	/* reg71 controls ADC rate. */
+	switch (runtime->rate) {
+	case 44100:
+		reg71_set = 0x00004000;
+		break;
+        case 48000:
+		reg71_set = 0; 
+		break;
+	case 96000:
+		reg71_set = 0x00008000;
+		over_sampling=0xa;
+		break;
+	case 192000:
+		reg71_set = 0x0000c000; 
+		over_sampling=0xa;
+		break;
+	default:
+		reg71_set = 0; 
+		break;
+	}
+	/* Format is a global setting */
+	/* FIXME: Only let the first channel accessed set this. */
+	switch (runtime->format) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		hcfg_set = 0;
+		break;
+	case SNDRV_PCM_FORMAT_S32_LE:
+		hcfg_set = HCFG_CAPTURE_S32_LE;
+		break;
+	default:
+		hcfg_set = 0;
+		break;
+	}
+	hcfg = inl(emu->port + HCFG) ;
+	hcfg = (hcfg & ~hcfg_mask) | hcfg_set;
+	outl(hcfg, emu->port + HCFG);
+	reg71 = snd_ca0106_ptr_read(emu, 0x71, 0);
+	reg71 = (reg71 & ~reg71_mask) | reg71_set;
+	snd_ca0106_ptr_write(emu, 0x71, 0, reg71);
+        if (emu->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
+	        snd_ca0106_i2c_write(emu, ADC_MASTER, over_sampling); /* Adjust the over sampler to better suit the capture rate. */
+	}
+
+
         //printk("prepare:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size,  frames_to_bytes(runtime, 1));
 	snd_ca0106_ptr_write(emu, 0x13, channel, 0);
 	snd_ca0106_ptr_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
@@ -810,6 +934,7 @@
 
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = chip;
+	ac97.scaps = AC97_SCAP_NO_SPDIF;
 	return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
 }
 
@@ -993,6 +1118,7 @@
 					 ca0106_t **rchip)
 {
 	ca0106_t *chip;
+	ca0106_details_t *c;
 	int err;
 	int ch;
 	static snd_device_ops_t ops = {
@@ -1003,8 +1129,8 @@
   
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
-	if (pci_set_dma_mask(pci, 0xffffffffUL) < 0 ||
-	    pci_set_consistent_dma_mask(pci, 0xffffffffUL) < 0) {
+	if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 ||
+	    pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) {
 		printk(KERN_ERR "error to set 32bit mask DMA\n");
 		pci_disable_device(pci);
 		return -ENXIO;
@@ -1054,6 +1180,15 @@
 	printk(KERN_INFO "Model %04x Rev %08x Serial %08x\n", chip->model,
 	       chip->revision, chip->serial);
 #endif
+	strcpy(card->driver, "CA0106");
+	strcpy(card->shortname, "CA0106");
+
+	for (c=ca0106_chip_details; c->serial; c++) {
+		if (c->serial == chip->serial) break;
+	}
+	chip->details = c;
+	sprintf(card->longname, "%s at 0x%lx irq %i",
+		c->name, chip->port, chip->irq);
 
 	outl(0, chip->port + INTE);
 
@@ -1113,7 +1248,7 @@
 	//snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); /* OSS drivers set this. */
 	/* Analog or Digital output */
 	snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf);
-	snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000b0000); /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers */
+	snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000f0000); /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers. Use 0x000f0000 for surround71 */
 	chip->spdif_enable = 0; /* Set digital SPDIF output off */
 	chip->capture_source = 3; /* Set CAPTURE_SOURCE */
 	//snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */
@@ -1138,13 +1273,11 @@
         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->serial == 0x10061102) || 
-	    (chip->serial == 0x10071102) ||
-	    (chip->serial == 0x10091462)) { /* The SB0410 and SB0413 use GPIO differently. */
+        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 */
-		outl(0x005f4300, chip->port+GPIO); /* Analog */
+		outl(0x005f5301, chip->port+GPIO); /* Analog */
 	} else {
 		outl(0x0, chip->port+GPIO);
 		outl(0x005f03a3, chip->port+GPIO); /* Analog */
@@ -1157,6 +1290,10 @@
 	//outl(0x00000009, chip->port+HCFG);
 	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. */
+	}
+
 	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
 				  chip, &ops)) < 0) {
 		snd_ca0106_free(chip);
@@ -1172,7 +1309,6 @@
 	static int dev;
 	snd_card_t *card;
 	ca0106_t *chip;
-	ca0106_names_t *c;
 	int err;
 
 	if (dev >= SNDRV_CARDS)
@@ -1207,9 +1343,7 @@
 		snd_card_free(card);
 		return err;
 	}
-        if ((chip->serial != 0x10061102) && 
-	    (chip->serial != 0x10071102) && 
-	    (chip->serial != 0x10091462) ) { /* The SB0410 and SB0413 do not have an ac97 chip. */
+        if (chip->details->ac97 == 1) { /* The SB0410 and SB0413 do not have an AC97 chip. */
 		if ((err = snd_ca0106_ac97(chip)) < 0) {
 			snd_card_free(card);
 			return err;
@@ -1222,15 +1356,6 @@
 
 	snd_ca0106_proc_init(chip);
 
-	strcpy(card->driver, "CA0106");
-	strcpy(card->shortname, "CA0106");
-
-	for (c=ca0106_chip_names; c->serial; c++) {
-		if (c->serial == chip->serial) break;
-	}
-	sprintf(card->longname, "%s at 0x%lx irq %i",
-		c->name, chip->port, chip->irq);
-
 	if ((err = snd_card_register(card)) < 0) {
 		snd_card_free(card);
 		return err;
@@ -1267,7 +1392,7 @@
 {
 	int err;
 
-	if ((err = pci_module_init(&driver)) > 0)
+	if ((err = pci_register_driver(&driver)) > 0)
 		return err;
 
 	return 0;
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index 97bed1b..0e5e9ce 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -1,7 +1,7 @@
 /*
  *  Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
  *  Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
- *  Version: 0.0.16
+ *  Version: 0.0.17
  *
  *  FEATURES currently supported:
  *    See ca0106_main.c for features.
@@ -37,6 +37,8 @@
  *    Separated ca0106.c into separate functional .c files.
  *  0.0.16
  *    Modified Copyright message.
+ *  0.0.17
+ *    Implement Mic and Line in Capture.
  *
  *  This code was initally based on code from ALSA's emu10k1x.c which is:
  *  Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
@@ -113,7 +115,7 @@
 		} else {
 			/* Analog */
 			snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
-			snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000b0000);
+			snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000);
 			snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0,
 				snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000);
 			mask = inl(emu->port + GPIO) | 0x101;
@@ -183,6 +185,65 @@
 	.put =		snd_ca0106_capture_source_put
 };
 
+static int snd_ca0106_capture_mic_line_in_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+	static char *texts[2] = { "Line in", "Mic 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_get(snd_kcontrol_t * kcontrol,
+					snd_ctl_elem_value_t * ucontrol)
+{
+	ca0106_t *emu = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.enumerated.item[0] = emu->capture_mic_line_in;
+	return 0;
+}
+
+static int snd_ca0106_capture_mic_line_in_put(snd_kcontrol_t * kcontrol,
+					snd_ctl_elem_value_t * ucontrol)
+{
+	ca0106_t *emu = snd_kcontrol_chip(kcontrol);
+	unsigned int val;
+	int change = 0;
+	u32 tmp;
+
+	val = ucontrol->value.enumerated.item[0] ;
+	change = (emu->capture_mic_line_in != val);
+	if (change) {
+		emu->capture_mic_line_in = val;
+		if (val) {
+			snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* 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);
+		} else {
+			snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_PHONE); /* Mute input */
+			tmp = inl(emu->port+GPIO) & ~0x400;
+			outl(tmp, emu->port+GPIO);
+			snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN);
+		}
+	}
+        return change;
+}
+
+static snd_kcontrol_new_t snd_ca0106_capture_mic_line_in __devinitdata =
+{
+	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name =		"Mic/Line in Capture",
+	.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 int snd_ca0106_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
@@ -437,7 +498,7 @@
 static snd_kcontrol_new_t snd_ca0106_volume_control_analog_unknown =
 {
         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
-        .name =         "Analog Unknown Volume",
+        .name =         "Analog Side Volume",
         .info =         snd_ca0106_volume_info,
         .get =          snd_ca0106_volume_get_analog_unknown,
         .put =          snd_ca0106_volume_put_analog_unknown
@@ -620,10 +681,11 @@
 		return -ENOMEM;
 	if ((err = snd_ctl_add(card, kctl)))
 		return err;
-	if ((kctl = ctl_find(card, SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT))) != NULL) {
-		/* already defined by ac97, remove it */
-		/* FIXME: or do we need both controls? */
-		remove_ctl(card, SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT));
+	if (emu->details->i2c_adc == 1) {
+		if ((kctl = snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu)) == NULL)
+			return -ENOMEM;
+		if ((err = snd_ctl_add(card, kctl)))
+			return err;
 	}
 	if ((kctl = snd_ctl_new1(&snd_ca0106_spdif_control, emu)) == NULL)
 		return -ENOMEM;
diff --git a/sound/pci/ca0106/ca0106_proc.c b/sound/pci/ca0106/ca0106_proc.c
index afb7114..1c9cc82 100644
--- a/sound/pci/ca0106/ca0106_proc.c
+++ b/sound/pci/ca0106/ca0106_proc.c
@@ -1,7 +1,7 @@
 /*
  *  Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
  *  Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
- *  Version: 0.0.17
+ *  Version: 0.0.18
  *
  *  FEATURES currently supported:
  *    See ca0106_main.c for features.
@@ -39,7 +39,9 @@
  *    Modified Copyright message.
  *  0.0.17
  *    Add iec958 file in proc file system to show status of SPDIF in.
- *    
+ *  0.0.18
+ *    Implement support for Line-in capture on SB Live 24bit.
+ *
  *  This code was initally based on code from ALSA's emu10k1x.c which is:
  *  Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
  *
@@ -95,7 +97,7 @@
 };
 
 
-void snd_ca0106_proc_dump_iec958( snd_info_buffer_t *buffer, u32 value)
+static void snd_ca0106_proc_dump_iec958( snd_info_buffer_t *buffer, u32 value)
 {
 	int i;
 	u32 status[4];
@@ -407,6 +409,20 @@
         }
 }
 
+static void snd_ca0106_proc_i2c_write(snd_info_entry_t *entry, 
+				       snd_info_buffer_t * buffer)
+{
+	ca0106_t *emu = entry->private_data;
+        char line[64];
+        unsigned int reg, val;
+        while (!snd_info_get_line(buffer, line, sizeof(line))) {
+                if (sscanf(line, "%x %x", &reg, &val) != 2)
+                        continue;
+                if ((reg <= 0x7f) || (val <= 0x1ff)) {
+                        snd_ca0106_i2c_write(emu, reg, val);
+		}
+        }
+}
 
 int __devinit snd_ca0106_proc_init(ca0106_t * emu)
 {
@@ -418,6 +434,7 @@
 		snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read32);
 		entry->c.text.write_size = 64;
 		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);
@@ -427,6 +444,14 @@
 		snd_info_set_text_ops(entry, emu, 1024, snd_ca0106_proc_reg_read1);
 		entry->c.text.write_size = 64;
 		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;
+		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)) 
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index 113208f..b450338 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -519,40 +519,50 @@
 }
 
 /* bit operations for dword register */
-static void snd_cmipci_set_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag)
+static int snd_cmipci_set_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag)
 {
-	unsigned int val;
-	val = inl(cm->iobase + cmd);
+	unsigned int val, oval;
+	val = oval = inl(cm->iobase + cmd);
 	val |= flag;
+	if (val == oval)
+		return 0;
 	outl(val, cm->iobase + cmd);
+	return 1;
 }
 
-static void snd_cmipci_clear_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag)
+static int snd_cmipci_clear_bit(cmipci_t *cm, unsigned int cmd, unsigned int flag)
 {
-	unsigned int val;
-	val = inl(cm->iobase + cmd);
+	unsigned int val, oval;
+	val = oval = inl(cm->iobase + cmd);
 	val &= ~flag;
+	if (val == oval)
+		return 0;
 	outl(val, cm->iobase + cmd);
+	return 1;
 }
 
-#if 0 // not used
 /* bit operations for byte register */
-static void snd_cmipci_set_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag)
+static int snd_cmipci_set_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag)
 {
-	unsigned char val;
-	val = inb(cm->iobase + cmd);
+	unsigned char val, oval;
+	val = oval = inb(cm->iobase + cmd);
 	val |= flag;
+	if (val == oval)
+		return 0;
 	outb(val, cm->iobase + cmd);
+	return 1;
 }
 
-static void snd_cmipci_clear_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag)
+static int snd_cmipci_clear_bit_b(cmipci_t *cm, unsigned int cmd, unsigned char flag)
 {
-	unsigned char val;
-	val = inb(cm->iobase + cmd);
+	unsigned char val, oval;
+	val = oval = inb(cm->iobase + cmd);
 	val &= ~flag;
+	if (val == oval)
+		return 0;
 	outb(val, cm->iobase + cmd);
+	return 1;
 }
-#endif
 
 
 /*
@@ -2250,8 +2260,8 @@
 DEFINE_SWITCH_ARG(exchange_dac, CM_REG_MISC_CTRL, CM_XCHGDAC, CM_XCHGDAC, 0, 0);
 #endif
 DEFINE_BIT_SWITCH_ARG(fourch, CM_REG_MISC_CTRL, CM_N4SPK3D, 0, 0);
-DEFINE_BIT_SWITCH_ARG(line_rear, CM_REG_MIXER1, CM_SPK4, 1, 0);
-DEFINE_BIT_SWITCH_ARG(line_bass, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS, 0, 0);
+// DEFINE_BIT_SWITCH_ARG(line_rear, CM_REG_MIXER1, CM_SPK4, 1, 0);
+// DEFINE_BIT_SWITCH_ARG(line_bass, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS, 0, 0);
 // DEFINE_BIT_SWITCH_ARG(joystick, CM_REG_FUNCTRL1, CM_JYSTK_EN, 0, 0); /* now module option */
 DEFINE_SWITCH_ARG(modem, CM_REG_MISC_CTRL, CM_FLINKON|CM_FLINKOFF, CM_FLINKON, 0, 0);
 
@@ -2300,10 +2310,114 @@
 }
 
 
+static int snd_cmipci_line_in_mode_info(snd_kcontrol_t *kcontrol,
+					snd_ctl_elem_info_t *uinfo)
+{
+	cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+	static char *texts[3] = { "Line-In", "Rear Output", "Bass Output" };
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = cm->chip_version >= 39 ? 3 : 2;
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static inline unsigned int get_line_in_mode(cmipci_t *cm)
+{
+	unsigned int val;
+	if (cm->chip_version >= 39) {
+		val = snd_cmipci_read(cm, CM_REG_LEGACY_CTRL);
+		if (val & CM_LINE_AS_BASS)
+			return 2;
+	}
+	val = snd_cmipci_read_b(cm, CM_REG_MIXER1);
+	if (val & CM_SPK4)
+		return 1;
+	return 0;
+}
+
+static int snd_cmipci_line_in_mode_get(snd_kcontrol_t *kcontrol,
+				       snd_ctl_elem_value_t *ucontrol)
+{
+	cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+
+	spin_lock_irq(&cm->reg_lock);
+	ucontrol->value.enumerated.item[0] = get_line_in_mode(cm);
+	spin_unlock_irq(&cm->reg_lock);
+	return 0;
+}
+
+static int snd_cmipci_line_in_mode_put(snd_kcontrol_t *kcontrol,
+				       snd_ctl_elem_value_t *ucontrol)
+{
+	cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+	int change;
+
+	spin_lock_irq(&cm->reg_lock);
+	if (ucontrol->value.enumerated.item[0] == 2)
+		change = snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS);
+	else
+		change = snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_LINE_AS_BASS);
+	if (ucontrol->value.enumerated.item[0] == 1)
+		change |= snd_cmipci_set_bit_b(cm, CM_REG_MIXER1, CM_SPK4);
+	else
+		change |= snd_cmipci_clear_bit_b(cm, CM_REG_MIXER1, CM_SPK4);
+	spin_unlock_irq(&cm->reg_lock);
+	return change;
+}
+
+static int snd_cmipci_mic_in_mode_info(snd_kcontrol_t *kcontrol,
+				       snd_ctl_elem_info_t *uinfo)
+{
+	static char *texts[2] = { "Mic-In", "Center/LFE Output" };
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int snd_cmipci_mic_in_mode_get(snd_kcontrol_t *kcontrol,
+				      snd_ctl_elem_value_t *ucontrol)
+{
+	cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+	/* same bit as spdi_phase */
+	spin_lock_irq(&cm->reg_lock);
+	ucontrol->value.enumerated.item[0] = 
+		(snd_cmipci_read_b(cm, CM_REG_MISC) & CM_SPDIF_INVERSE) ? 1 : 0;
+	spin_unlock_irq(&cm->reg_lock);
+	return 0;
+}
+
+static int snd_cmipci_mic_in_mode_put(snd_kcontrol_t *kcontrol,
+				      snd_ctl_elem_value_t *ucontrol)
+{
+	cmipci_t *cm = snd_kcontrol_chip(kcontrol);
+	int change;
+
+	spin_lock_irq(&cm->reg_lock);
+	if (ucontrol->value.enumerated.item[0])
+		change = snd_cmipci_set_bit_b(cm, CM_REG_MISC, CM_SPDIF_INVERSE);
+	else
+		change = snd_cmipci_clear_bit_b(cm, CM_REG_MISC, CM_SPDIF_INVERSE);
+	spin_unlock_irq(&cm->reg_lock);
+	return change;
+}
+
 /* both for CM8338/8738 */
 static snd_kcontrol_new_t snd_cmipci_mixer_switches[] __devinitdata = {
 	DEFINE_MIXER_SWITCH("Four Channel Mode", fourch),
-	DEFINE_MIXER_SWITCH("Line-In As Rear", line_rear),
+	{
+		.name = "Line-In Mode",
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.info = snd_cmipci_line_in_mode_info,
+		.get = snd_cmipci_line_in_mode_get,
+		.put = snd_cmipci_line_in_mode_put,
+	},
 };
 
 /* for non-multichannel chips */
@@ -2341,10 +2455,15 @@
 
 /* only for model 039 or later */
 static snd_kcontrol_new_t snd_cmipci_extra_mixer_switches[] __devinitdata = {
-	DEFINE_MIXER_SWITCH("Line-In As Bass", line_bass),
 	DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel2),
 	DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase2),
-	DEFINE_MIXER_SWITCH("Mic As Center/LFE", spdi_phase), /* same bit as spdi_phase */
+	{
+		.name = "Mic-In Mode",
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.info = snd_cmipci_mic_in_mode_info,
+		.get = snd_cmipci_mic_in_mode_get,
+		.put = snd_cmipci_mic_in_mode_put,
+	}
 };
 
 /* card control switches */
@@ -2944,7 +3063,7 @@
 	
 static int __init alsa_card_cmipci_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_cmipci_exit(void)
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index 0b53f7c..eb3c52b 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -206,7 +206,10 @@
 
 #define BA0_PMCS		0x0344	/* Power Management Control/Status */
 #define BA0_CWPR		0x03e0	/* Configuration Write Protect */
+
 #define BA0_EPPMC		0x03e4	/* Extended PCI Power Management Control */
+#define BA0_EPPMC_FPDN		(1<<14) /* Full Power DowN */
+
 #define BA0_GPIOR		0x03e8	/* GPIO Pin Interface Register */
 
 #define BA0_SPMC		0x03ec	/* Serial Port Power Management Control (& ASDIN2 enable) */
@@ -1456,6 +1459,11 @@
 	int timeout;
 	int retry_count = 2;
 
+	/* Having EPPMC.FPDN=1 prevent proper chip initialisation */
+	tmp = snd_cs4281_peekBA0(chip, BA0_EPPMC);
+	if (tmp & BA0_EPPMC_FPDN)
+		snd_cs4281_pokeBA0(chip, BA0_EPPMC, tmp & ~BA0_EPPMC_FPDN);
+
       __retry:
 	tmp = snd_cs4281_peekBA0(chip, BA0_CFLR);
 	if (tmp != BA0_CFLR_DEFAULT) {
@@ -2119,7 +2127,7 @@
 	
 static int __init alsa_card_cs4281_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_cs4281_exit(void)
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index 25d6466..db212ec 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -171,7 +171,7 @@
 
 static int __init alsa_card_cs46xx_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_cs46xx_exit(void)
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 5f2ffb7..fd4c50c 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -1295,8 +1295,7 @@
 
 static void snd_cs46xx_pcm_free_substream(snd_pcm_runtime_t *runtime)
 {
-	cs46xx_pcm_t * cpcm = runtime->private_data;
-	kfree(cpcm);
+	kfree(runtime->private_data);
 }
 
 static int _cs46xx_playback_open_channel (snd_pcm_substream_t * substream,int pcm_channel_id)
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index 6446afe..2085a99 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -228,7 +228,7 @@
 
 static int __init alsa_card_emu10k1_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_emu10k1_exit(void)
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index c3c96f9..a341e75 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -170,7 +170,7 @@
 			SPCS_GENERATIONSTATUS | 0x00001200 |
 			0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
 
-	if (emu->audigy && emu->revision == 4) { /* audigy2 */
+	if (emu->card_capabilities->ca0151_chip) { /* audigy2 */
 		/* Hacks for Alice3 to work independent of haP16V driver */
 		u32 tmp;
 
@@ -189,7 +189,7 @@
 		/* Enabled Phased (8-channel) P16V playback */
 		outl(0x0201, emu->port + HCFG2);
 		/* Set playback routing. */
-		snd_emu10k1_ptr_write(emu, CAPTURE_P16V_SOURCE, 0, 78e4);
+		snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, 0x78e4);
 	}
 	if (emu->audigy && (emu->serial == 0x10011102) ) { /* audigy2 Value */
 		/* Hacks for Alice3 to work independent of haP16V driver */
@@ -600,7 +600,7 @@
 	if (emu->port)
 		pci_release_regions(emu->pci);
 	pci_disable_device(emu->pci);
-	if (emu->audigy && emu->revision == 4) /* P16V */	
+	if (emu->card_capabilities->ca0151_chip) /* P16V */	
 		snd_p16v_free(emu);
 	kfree(emu);
 	return 0;
@@ -612,21 +612,24 @@
 	return snd_emu10k1_free(emu);
 }
 
-/* vendor, device, subsystem, emu10k1_chip, emu10k2_chip, ca0102_chip, ca0108_chip, ca0151_chip, spk71, spdif_bug, ac97_chip, ecard, driver, name */
-
 static emu_chip_details_t emu_chip_details[] = {
 	/* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/
 	{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102,
 	 .driver = "Audigy2", .name = "Audigy 2 Value [SB0400]", 
+	 .id = "Audigy2",
 	 .emu10k2_chip = 1,
 	 .ca0108_chip = 1,
-	 .spk71 = 1} ,
+	 .spk71 = 1,
+	 .ac97_chip = 1} ,
 	{.vendor = 0x1102, .device = 0x0008, 
 	 .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]", 
+	 .id = "Audigy2",
 	 .emu10k2_chip = 1,
-	 .ca0108_chip = 1} ,
+	 .ca0108_chip = 1,
+	 .ac97_chip = 1} ,
 	{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102,
 	 .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]", 
+	 .id = "Audigy2",
 	 .emu10k2_chip = 1,
 	 .ca0102_chip = 1,
 	 .ca0151_chip = 1,
@@ -635,6 +638,7 @@
 	 .ac97_chip = 1} ,
 	{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102,
 	 .driver = "Audigy2", .name = "Audigy 2 ZS [SB0350]", 
+	 .id = "Audigy2",
 	 .emu10k2_chip = 1,
 	 .ca0102_chip = 1,
 	 .ca0151_chip = 1,
@@ -643,6 +647,7 @@
 	 .ac97_chip = 1} ,
 	{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20011102,
 	 .driver = "Audigy2", .name = "Audigy 2 ZS [2001]", 
+	 .id = "Audigy2",
 	 .emu10k2_chip = 1,
 	 .ca0102_chip = 1,
 	 .ca0151_chip = 1,
@@ -651,6 +656,7 @@
 	 .ac97_chip = 1} ,
 	{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10071102,
 	 .driver = "Audigy2", .name = "Audigy 2 [SB0240]", 
+	 .id = "Audigy2",
 	 .emu10k2_chip = 1,
 	 .ca0102_chip = 1,
 	 .ca0151_chip = 1,
@@ -659,35 +665,165 @@
 	 .ac97_chip = 1} ,
 	{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102,
 	 .driver = "Audigy2", .name = "Audigy 2 EX [1005]", 
+	 .id = "Audigy2",
 	 .emu10k2_chip = 1,
 	 .ca0102_chip = 1,
 	 .ca0151_chip = 1,
 	 .spdif_bug = 1} ,
 	{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102,
 	 .driver = "Audigy2", .name = "Audigy 2 Platinum [SB0240P]", 
+	 .id = "Audigy2",
 	 .emu10k2_chip = 1,
 	 .ca0102_chip = 1,
 	 .ca0151_chip = 1,
 	 .spk71 = 1,
 	 .spdif_bug = 1,
 	 .ac97_chip = 1} ,
-	{.vendor = 0x1102, .device = 0x0004,
-	 .driver = "Audigy", .name = "Audigy 1 or 2 [Unknown]", 
+	{.vendor = 0x1102, .device = 0x0004, .revision = 0x04,
+	 .driver = "Audigy2", .name = "Audigy 2 [Unknown]",
+	 .id = "Audigy2",
 	 .emu10k2_chip = 1,
 	 .ca0102_chip = 1,
-	 .spdif_bug = 1} ,
+	 .ca0151_chip = 1,
+	 .spdif_bug = 1,
+	 .ac97_chip = 1} ,
+	{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10020052,
+	 .driver = "Audigy", .name = "Audigy 1 ES [SB0160]", 
+	 .id = "Audigy",
+	 .emu10k2_chip = 1,
+	 .ca0102_chip = 1,
+	 .spdif_bug = 1,
+	 .ac97_chip = 1} ,
+	{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00531102,
+	 .driver = "Audigy", .name = "Audigy 1 [SB0090]", 
+	 .id = "Audigy",
+	 .emu10k2_chip = 1,
+	 .ca0102_chip = 1,
+	 .ac97_chip = 1} ,
+	{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00511102,
+	 .driver = "Audigy", .name = "Audigy 1 [SB0090]", 
+	 .id = "Audigy",
+	 .emu10k2_chip = 1,
+	 .ca0102_chip = 1,
+	 .ac97_chip = 1} ,
+	{.vendor = 0x1102, .device = 0x0004,
+	 .driver = "Audigy", .name = "Audigy 1 [Unknown]", 
+	 .id = "Audigy",
+	 .emu10k2_chip = 1,
+	 .ca0102_chip = 1,
+	 .ac97_chip = 1} ,
 	{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102,
 	 .driver = "EMU10K1", .name = "E-mu APS [4001]", 
+	 .id = "APS",
 	 .emu10k1_chip = 1,
 	 .ecard = 1} ,
+	{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102,
+	 .driver = "EMU10K1", .name = "SBLive! Player 5.1 [SB0060]", 
+	 .id = "Live",
+	 .emu10k1_chip = 1,
+	 .ac97_chip = 1,
+	 .sblive51 = 1} ,
 	{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102,
 	 .driver = "EMU10K1", .name = "SB Live 5.1", 
+	 .id = "Live",
+	 .emu10k1_chip = 1,
+	 .ac97_chip = 1,
+	 .sblive51 = 1} ,
+	{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80401102,
+	 .driver = "EMU10K1", .name = "SBLive! Platinum [CT4760P]", 
+	 .id = "Live",
 	 .emu10k1_chip = 1,
 	 .ac97_chip = 1} ,
+	{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00211102,
+	 .driver = "EMU10K1", .name = "SBLive! [CT4620]", 
+	 .id = "Live",
+	 .emu10k1_chip = 1,
+	 .ac97_chip = 1,
+	 .sblive51 = 1} ,
+	{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00201102,
+	 .driver = "EMU10K1", .name = "SBLive! Value [CT4670]", 
+	 .id = "Live",
+	 .emu10k1_chip = 1,
+	 .ac97_chip = 1,
+	 .sblive51 = 1} ,
+	{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80221102,
+	 .driver = "EMU10K1", .name = "SBLive! Value [CT4780]", 
+	 .id = "Live",
+	 .emu10k1_chip = 1,
+	 .ac97_chip = 1,
+	 .sblive51 = 1} ,
+	{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80231102,
+	 .driver = "EMU10K1", .name = "SB PCI512 [CT4790]", 
+	 .id = "Live",
+	 .emu10k1_chip = 1,
+	 .ac97_chip = 1,
+	 .sblive51 = 1} ,
+	{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80261102,
+	 .driver = "EMU10K1", .name = "SBLive! Value [CT4830]", 
+	 .id = "Live",
+	 .emu10k1_chip = 1,
+	 .ac97_chip = 1,
+	 .sblive51 = 1} ,
+	{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80311102,
+	 .driver = "EMU10K1", .name = "SBLive! Value [CT4831]", 
+	 .id = "Live",
+	 .emu10k1_chip = 1,
+	 .ac97_chip = 1,
+	 .sblive51 = 1} ,
+	{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80271102,
+	 .driver = "EMU10K1", .name = "SBLive! Value [CT4832]", 
+	 .id = "Live",
+	 .emu10k1_chip = 1,
+	 .ac97_chip = 1,
+	 .sblive51 = 1} ,
+	{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80511102,
+	 .driver = "EMU10K1", .name = "SBLive! Value [CT4850]", 
+	 .id = "Live",
+	 .emu10k1_chip = 1,
+	 .ac97_chip = 1,
+	 .sblive51 = 1} ,
+	{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80281102,
+	 .driver = "EMU10K1", .name = "SBLive! Value [CT4870]", 
+	 .id = "Live",
+	 .emu10k1_chip = 1,
+	 .ac97_chip = 1,
+	 .sblive51 = 1} ,
+	{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80321102,
+	 .driver = "EMU10K1", .name = "SBLive! Value [CT4871]", 
+	 .id = "Live",
+	 .emu10k1_chip = 1,
+	 .ac97_chip = 1,
+	 .sblive51 = 1} ,
+	{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102,
+	 .driver = "EMU10K1", .name = "SBLive! Value [SB0060]", 
+	 .id = "Live",
+	 .emu10k1_chip = 1,
+	 .ac97_chip = 1,
+	 .sblive51 = 1} ,
+	{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80691102,
+	 .driver = "EMU10K1", .name = "SBLive! Value [SB0101]", 
+	 .id = "Live",
+	 .emu10k1_chip = 1,
+	 .ac97_chip = 1,
+	 .sblive51 = 1} ,
+	{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806A1102,
+	 .driver = "EMU10K1", .name = "SBLive! Value [SB0103]", 
+	 .id = "Live",
+	 .emu10k1_chip = 1,
+	 .ac97_chip = 1,
+	 .sblive51 = 1} ,
+	{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806B1102,
+	 .driver = "EMU10K1", .name = "SBLive! [SB0105]", 
+	 .id = "Live",
+	 .emu10k1_chip = 1,
+	 .ac97_chip = 1,
+	 .sblive51 = 1} ,
 	{.vendor = 0x1102, .device = 0x0002,
 	 .driver = "EMU10K1", .name = "SB Live [Unknown]", 
+	 .id = "Live",
 	 .emu10k1_chip = 1,
-	 .ac97_chip = 1} ,
+	 .ac97_chip = 1,
+	 .sblive51 = 1} ,
 	{ } /* terminator */
 };
 
@@ -738,13 +874,15 @@
 	emu->revision = revision;
 	pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);
 	pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model);
-	emu->card_type = EMU10K1_CARD_CREATIVE;
 	snd_printdd("vendor=0x%x, device=0x%x, subsystem_vendor_id=0x%x, subsystem_id=0x%x\n",pci->vendor, pci->device, emu->serial, emu->model);
 
 	for (c = emu_chip_details; c->vendor; c++) {
 		if (c->vendor == pci->vendor && c->device == pci->device) {
-			if (c->subsystem == emu->serial) break;
-			if (c->subsystem == 0) break;
+			if (c->subsystem && c->subsystem != emu->serial)
+				continue;
+			if (c->revision && c->revision != emu->revision)
+				continue;
+			break;
 		}
 	}
 	if (c->vendor == 0) {
@@ -759,6 +897,23 @@
 	else
 		snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x\n", c->name, pci->vendor, pci->device, emu->serial);
 	
+	if (!*card->id && c->id) {
+		int i, n = 0;
+		strlcpy(card->id, c->id, sizeof(card->id));
+		for (;;) {
+			for (i = 0; i < snd_ecards_limit; i++) {
+				if (snd_cards[i] && !strcmp(snd_cards[i]->id, card->id))
+					break;
+			}
+			if (i >= snd_ecards_limit)
+				break;
+			n++;
+			if (n >= SNDRV_CARDS)
+				break;
+			snprintf(card->id, sizeof(card->id), "%s_%d", c->id, n);
+		}
+	}
+
 	is_audigy = emu->audigy = c->emu10k2_chip;
 
 	/* set the DMA transfer mask */
@@ -816,15 +971,6 @@
 
 	pci_set_master(pci);
 
-	if (c->ecard) {
-		emu->card_type = EMU10K1_CARD_EMUAPS;
-		emu->APS = 1;
-	}
-	if (! c->ac97_chip)
-		emu->no_ac97 = 1;
-	
-	emu->spk71 = c->spk71;
-	
 	emu->fx8010.fxbus_mask = 0x303f;
 	if (extin_mask == 0)
 		extin_mask = 0x3fcf;
@@ -833,7 +979,7 @@
 	emu->fx8010.extin_mask = extin_mask;
 	emu->fx8010.extout_mask = extout_mask;
 
-	if (emu->APS) {
+	if (emu->card_capabilities->ecard) {
 		if ((err = snd_emu10k1_ecard_init(emu)) < 0) {
 			snd_emu10k1_free(emu);
 			return err;
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 27dfd8d..e90c5ddd 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -361,10 +361,7 @@
 
 static void snd_emu10k1x_pcm_free_substream(snd_pcm_runtime_t *runtime)
 {
-	emu10k1x_pcm_t *epcm = runtime->private_data;
-  
-	if (epcm)
-		kfree(epcm);
+	kfree(runtime->private_data);
 }
 
 static void snd_emu10k1x_pcm_interrupt(emu10k1x_t *emu, emu10k1x_voice_t *voice)
@@ -1075,6 +1072,7 @@
 		snd_info_set_text_ops(entry, emu, 1024, snd_emu10k1x_proc_reg_read);
 		entry->c.text.write_size = 64;
 		entry->c.text.write = snd_emu10k1x_proc_reg_write;
+		entry->mode |= S_IWUSR;
 		entry->private_data = emu;
 	}
 	
@@ -1627,7 +1625,7 @@
 {
 	int err;
 
-	if ((err = pci_module_init(&driver)) > 0)
+	if ((err = pci_register_driver(&driver)) > 0)
 		return err;
 
 	return 0;
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index b9fa2e8..0529fb2 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -1077,7 +1077,7 @@
 	gpr += 2;
 	
 	/* PCM Side Playback (independent from stereo mix) */
-	if (emu->spk71) {
+	if (emu->card_capabilities->spk71) {
 		A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_SIDE));
 		A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_SIDE));
 		snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Side Playback Volume", gpr, 100);
@@ -1145,14 +1145,14 @@
 	A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_SPDIF_CD_L);
 	A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_SPDIF_CD_R);
 	snd_emu10k1_init_stereo_control(&controls[nctl++],
-					emu->no_ac97 ? "CD Playback Volume" : "Audigy CD Playback Volume",
+					emu->card_capabilities->ac97_chip ? "Audigy CD Playback Volume" : "CD Playback Volume",
 					gpr, 0);
 	gpr += 2;
 	/* Audigy CD Capture Volume */
 	A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_SPDIF_CD_L);
 	A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_SPDIF_CD_R);
 	snd_emu10k1_init_stereo_control(&controls[nctl++],
-					emu->no_ac97 ? "CD Capture Volume" : "Audigy CD Capture Volume",
+					emu->card_capabilities->ac97_chip ? "Audigy CD Capture Volume" : "CD Capture Volume",
 					gpr, 0);
 	gpr += 2;
 
@@ -1171,14 +1171,14 @@
 	A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_LINE2_L);
 	A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_LINE2_R);
 	snd_emu10k1_init_stereo_control(&controls[nctl++],
-					emu->no_ac97 ? "Line Playback Volume" : "Line2 Playback Volume",
+					emu->card_capabilities->ac97_chip ? "Line2 Playback Volume" : "Line Playback Volume",
 					gpr, 0);
 	gpr += 2;
 	/* Line2 Capture Volume */
 	A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_LINE2_L);
 	A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_LINE2_R);
 	snd_emu10k1_init_stereo_control(&controls[nctl++],
-					emu->no_ac97 ? "Line Capture Volume" : "Line2 Capture Volume",
+					emu->card_capabilities->ac97_chip ? "Line2 Capture Volume" : "Line Capture Volume",
 					gpr, 0);
 	gpr += 2;
         
@@ -1197,14 +1197,14 @@
 	A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AUX2_L);
 	A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AUX2_R);
 	snd_emu10k1_init_stereo_control(&controls[nctl++],
-					emu->no_ac97 ? "Aux Playback Volume" : "Aux2 Playback Volume",
+					emu->card_capabilities->ac97_chip ? "Aux2 Playback Volume" : "Aux Playback Volume",
 					gpr, 0);
 	gpr += 2;
 	/* Aux2 Capture Volume */
 	A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_AUX2_L);
 	A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_AUX2_R);
 	snd_emu10k1_init_stereo_control(&controls[nctl++],
-					emu->no_ac97 ? "Aux Capture Volume" : "Aux2 Capture Volume",
+					emu->card_capabilities->ac97_chip ? "Aux2 Capture Volume" : "Aux Capture Volume",
 					gpr, 0);
 	gpr += 2;
 	
@@ -1232,7 +1232,7 @@
 	snd_emu10k1_init_mono_control(&controls[nctl++], "LFE Playback Volume", gpr, 0);
 	gpr++;
 	
-	if (emu->spk71) {
+	if (emu->card_capabilities->spk71) {
 		/* Stereo Mix Side Playback */
 		A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_GPR(playback+6), A_GPR(gpr), A_GPR(stereo_mix));
 		A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_GPR(playback+7), A_GPR(gpr+1), A_GPR(stereo_mix+1));
@@ -1266,7 +1266,7 @@
 	A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 3), A_GPR(playback + 3), A_C_00000000, A_C_00000000); /* rear right */
 	A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), A_GPR(playback + 4), A_C_00000000, A_C_00000000); /* center */
 	A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), A_GPR(playback + 5), A_C_00000000, A_C_00000000); /* LFE */
-	if (emu->spk71) {
+	if (emu->card_capabilities->spk71) {
 		A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 6), A_GPR(playback + 6), A_C_00000000, A_C_00000000); /* side left */
 		A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 7), A_GPR(playback + 7), A_C_00000000, A_C_00000000); /* side right */
 	}
@@ -1359,7 +1359,7 @@
 	A_PUT_STEREO_OUTPUT(A_EXTOUT_AREAR_L, A_EXTOUT_AREAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS);
 	A_PUT_OUTPUT(A_EXTOUT_ACENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS);
 	A_PUT_OUTPUT(A_EXTOUT_ALFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS);
-	if (emu->spk71)
+	if (emu->card_capabilities->spk71)
 		A_PUT_STEREO_OUTPUT(A_EXTOUT_ASIDE_L, A_EXTOUT_ASIDE_R, playback+6 + SND_EMU10K1_PLAYBACK_CHANNELS);
 
 	/* headphone */
@@ -1982,22 +1982,27 @@
 		OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_MIC_CAP), GPR(capture + 2), C_00000000, C_00000000);
 
 	/* EFX capture - capture the 16 EXTINS */
-	OP(icode, &ptr, iACC3, FXBUS2(14), C_00000000, C_00000000, EXTIN(0));
-	OP(icode, &ptr, iACC3, FXBUS2(15), C_00000000, C_00000000, EXTIN(1));
-	OP(icode, &ptr, iACC3, FXBUS2(0), C_00000000, C_00000000, EXTIN(2));
-	OP(icode, &ptr, iACC3, FXBUS2(3), C_00000000, C_00000000, EXTIN(3));
-	/* Dont connect anything to FXBUS2 1 and 2.  These are shared with 
-	 * Center/LFE on the SBLive 5.1.  The kX driver only changes the 
-	 * routing when it detects an SBLive 5.1.
-	 *
-	 * Since only 14 of the 16 EXTINs are used, this is not a big problem.  
-	 * We route AC97L and R to FX capture 14 and 15, SPDIF CD in to FX capture 
-	 * 0 and 3, then the rest of the EXTINs to the corresponding FX capture 
-	 * channel.
-	 */
-	for (z = 4; z < 14; z++) {
-		OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z));
+	if (emu->card_capabilities->sblive51) {
+		/* On the Live! 5.1, FXBUS2(1) and FXBUS(2) are shared with EXTOUT_ACENTER
+		 * and EXTOUT_ALFE, so we can't connect inputs to them for multitrack recording.
+		 *
+		 * Since only 14 of the 16 EXTINs are used, this is not a big problem.  
+		 * We route AC97L and R to FX capture 14 and 15, SPDIF CD in to FX capture 
+		 * 0 and 3, then the rest of the EXTINs to the corresponding FX capture 
+		 * channel.  Multitrack recorders will still see the center/lfe output signal 
+		 * on the second and third channels.
+		 */
+		OP(icode, &ptr, iACC3, FXBUS2(14), C_00000000, C_00000000, EXTIN(0));
+		OP(icode, &ptr, iACC3, FXBUS2(15), C_00000000, C_00000000, EXTIN(1));
+		OP(icode, &ptr, iACC3, FXBUS2(0), C_00000000, C_00000000, EXTIN(2));
+		OP(icode, &ptr, iACC3, FXBUS2(3), C_00000000, C_00000000, EXTIN(3));
+		for (z = 4; z < 14; z++)
+			OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z));
+	} else {
+		for (z = 0; z < 16; z++)
+			OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z));
 	}
+	    
 
 	if (gpr > tmp) {
 		snd_BUG();
@@ -2128,7 +2133,6 @@
 	int res;
 
 	memset(info, 0, sizeof(info));
-	info->card = emu->card_type;
 	info->internal_tram_size = emu->fx8010.itram_size;
 	info->external_tram_size = emu->fx8010.etram_pages.bytes / 2;
 	fxbus = fxbuses;
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
index 044663d..6be82c5 100644
--- a/sound/pci/emu10k1/emumixer.c
+++ b/sound/pci/emu10k1/emumixer.c
@@ -68,6 +68,7 @@
 	return 0;
 }
 
+#if 0
 static int snd_audigy_spdif_output_rate_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
 	static char *texts[] = {"44100", "48000", "96000"};
@@ -152,6 +153,7 @@
 	.get =          snd_audigy_spdif_output_rate_get,
 	.put =          snd_audigy_spdif_output_rate_put
 };
+#endif
 
 static int snd_emu10k1_spdif_put(snd_kcontrol_t * kcontrol,
                                  snd_ctl_elem_value_t * ucontrol)
@@ -791,7 +793,7 @@
 		NULL
 	};
 
-	if (!emu->no_ac97) {
+	if (emu->card_capabilities->ac97_chip) {
 		ac97_bus_t *pbus;
 		ac97_template_t ac97;
 		static ac97_bus_ops_t ops = {
@@ -833,7 +835,7 @@
 		for (; *c; c++)
 			remove_ctl(card, *c);
 	} else {
-		if (emu->APS)
+		if (emu->card_capabilities->ecard)
 			strcpy(emu->card->mixername, "EMU APS");
 		else if (emu->audigy)
 			strcpy(emu->card->mixername, "SB Audigy");
@@ -918,7 +920,7 @@
 		mix->attn[0] = 0xffff;
 	}
 	
-	if (! emu->APS) { /* FIXME: APS has these controls? */
+	if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */
 		/* sb live! and audigy */
 		if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
 			return -ENOMEM;
@@ -935,18 +937,20 @@
 			return -ENOMEM;
 		if ((err = snd_ctl_add(card, kctl)))
 			return err;
+#if 0
 		if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL)
 			return -ENOMEM;
 		if ((err = snd_ctl_add(card, kctl)))
 			return err;
-	} else if (! emu->APS) {
+#endif
+	} else if (! emu->card_capabilities->ecard) {
 		/* sb live! */
 		if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
 			return -ENOMEM;
 		if ((err = snd_ctl_add(card, kctl)))
 			return err;
 	}
-	if (emu->audigy && emu->revision == 4) { /* P16V */
+	if (emu->card_capabilities->ca0151_chip) { /* P16V */
 		if ((err = snd_p16v_mixer(emu)))
 			return err;
 	}
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index d1c2a02..520b99a 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -262,7 +262,7 @@
  *
  * returns: cache invalidate size in samples
  */
-static int inline emu10k1_ccis(int stereo, int w_16)
+static inline int emu10k1_ccis(int stereo, int w_16)
 {
 	if (w_16) {
 		return stereo ? 24 : 26;
@@ -991,9 +991,7 @@
 
 static void snd_emu10k1_pcm_free_substream(snd_pcm_runtime_t *runtime)
 {
-	emu10k1_pcm_t *epcm = runtime->private_data;
-
-	kfree(epcm);
+	kfree(runtime->private_data);
 }
 
 static int snd_emu10k1_efx_playback_close(snd_pcm_substream_t * substream)
diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c
index d990d5e..cc22707 100644
--- a/sound/pci/emu10k1/emuproc.c
+++ b/sound/pci/emu10k1/emuproc.c
@@ -30,6 +30,7 @@
 #include <linux/init.h>
 #include <sound/core.h>
 #include <sound/emu10k1.h>
+#include "p16v.h"
 
 static void snd_emu10k1_proc_spdif_status(emu10k1_t * emu,
 					  snd_info_buffer_t * buffer,
@@ -44,28 +45,34 @@
 	unsigned int status, rate = 0;
 	
 	status = snd_emu10k1_ptr_read(emu, status_reg, 0);
-	if (rate_reg > 0)
-		rate = snd_emu10k1_ptr_read(emu, rate_reg, 0);
 
 	snd_iprintf(buffer, "\n%s\n", title);
 
-	snd_iprintf(buffer, "Professional Mode     : %s\n", (status & SPCS_PROFESSIONAL) ? "yes" : "no");
-	snd_iprintf(buffer, "Not Audio Data        : %s\n", (status & SPCS_NOTAUDIODATA) ? "yes" : "no");
-	snd_iprintf(buffer, "Copyright             : %s\n", (status & SPCS_COPYRIGHT) ? "yes" : "no");
-	snd_iprintf(buffer, "Emphasis              : %s\n", emphasis[(status & SPCS_EMPHASISMASK) >> 3]);
-	snd_iprintf(buffer, "Mode                  : %i\n", (status & SPCS_MODEMASK) >> 6);
-	snd_iprintf(buffer, "Category Code         : 0x%x\n", (status & SPCS_CATEGORYCODEMASK) >> 8);
-	snd_iprintf(buffer, "Generation Status     : %s\n", status & SPCS_GENERATIONSTATUS ? "original" : "copy");
-	snd_iprintf(buffer, "Source Mask           : %i\n", (status & SPCS_SOURCENUMMASK) >> 16);
-	snd_iprintf(buffer, "Channel Number        : %s\n", channel[(status & SPCS_CHANNELNUMMASK) >> 20]);
-	snd_iprintf(buffer, "Sample Rate           : %iHz\n", samplerate[(status & SPCS_SAMPLERATEMASK) >> 24]);
-	snd_iprintf(buffer, "Clock Accuracy        : %s\n", clkaccy[(status & SPCS_CLKACCYMASK) >> 28]);
+	if (status != 0xffffffff) {
+		snd_iprintf(buffer, "Professional Mode     : %s\n", (status & SPCS_PROFESSIONAL) ? "yes" : "no");
+		snd_iprintf(buffer, "Not Audio Data        : %s\n", (status & SPCS_NOTAUDIODATA) ? "yes" : "no");
+		snd_iprintf(buffer, "Copyright             : %s\n", (status & SPCS_COPYRIGHT) ? "yes" : "no");
+		snd_iprintf(buffer, "Emphasis              : %s\n", emphasis[(status & SPCS_EMPHASISMASK) >> 3]);
+		snd_iprintf(buffer, "Mode                  : %i\n", (status & SPCS_MODEMASK) >> 6);
+		snd_iprintf(buffer, "Category Code         : 0x%x\n", (status & SPCS_CATEGORYCODEMASK) >> 8);
+		snd_iprintf(buffer, "Generation Status     : %s\n", status & SPCS_GENERATIONSTATUS ? "original" : "copy");
+		snd_iprintf(buffer, "Source Mask           : %i\n", (status & SPCS_SOURCENUMMASK) >> 16);
+		snd_iprintf(buffer, "Channel Number        : %s\n", channel[(status & SPCS_CHANNELNUMMASK) >> 20]);
+		snd_iprintf(buffer, "Sample Rate           : %iHz\n", samplerate[(status & SPCS_SAMPLERATEMASK) >> 24]);
+		snd_iprintf(buffer, "Clock Accuracy        : %s\n", clkaccy[(status & SPCS_CLKACCYMASK) >> 28]);
 
-	if (rate_reg > 0) {
-		snd_iprintf(buffer, "S/PDIF Locked         : %s\n", rate & SRCS_SPDIFLOCKED ? "on" : "off");
-		snd_iprintf(buffer, "Rate Locked           : %s\n", rate & SRCS_RATELOCKED ? "on" : "off");
-		snd_iprintf(buffer, "Estimated Sample Rate : 0x%x\n", rate & SRCS_ESTSAMPLERATE);
+		if (rate_reg > 0) {
+			rate = snd_emu10k1_ptr_read(emu, rate_reg, 0);
+			snd_iprintf(buffer, "S/PDIF Valid          : %s\n", rate & SRCS_SPDIFVALID ? "on" : "off");
+			snd_iprintf(buffer, "S/PDIF Locked         : %s\n", rate & SRCS_SPDIFLOCKED ? "on" : "off");
+			snd_iprintf(buffer, "Rate Locked           : %s\n", rate & SRCS_RATELOCKED ? "on" : "off");
+			/* From ((Rate * 48000 ) / 262144); */
+			snd_iprintf(buffer, "Estimated Sample Rate : %d\n", ((rate & 0xFFFFF ) * 375) >> 11); 
+		}
+	} else {
+		snd_iprintf(buffer, "No signal detected.\n");
 	}
+
 }
 
 static void snd_emu10k1_proc_read(snd_info_entry_t *entry, 
@@ -182,7 +189,7 @@
 	
 	snd_iprintf(buffer, "EMU10K1\n\n");
 	snd_iprintf(buffer, "Card                  : %s\n",
-		    emu->audigy ? "Audigy" : (emu->APS ? "EMU APS" : "Creative"));
+		    emu->audigy ? "Audigy" : (emu->card_capabilities->ecard ? "EMU APS" : "Creative"));
 	snd_iprintf(buffer, "Internal TRAM (words) : 0x%x\n", emu->fx8010.itram_size);
 	snd_iprintf(buffer, "External TRAM (words) : 0x%x\n", (int)emu->fx8010.etram_pages.bytes / 2);
 	snd_iprintf(buffer, "\n");
@@ -223,15 +230,35 @@
 	snd_iprintf(buffer, "\nAll FX Outputs        :\n");
 	for (idx = 0; idx < (emu->audigy ? 64 : 32); idx++)
 		snd_iprintf(buffer, "  Output %02i [%s]\n", idx, outputs[idx]);
-	snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 0", SPCS0, -1);
-	snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 1", SPCS1, -1);
-	snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 2/3", SPCS2, -1);
-	snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF", CDCS, CDSRCS);
-	snd_emu10k1_proc_spdif_status(emu, buffer, "General purpose S/PDIF", GPSCS, GPSRCS);
+}
+
+static void snd_emu10k1_proc_spdif_read(snd_info_entry_t *entry, 
+				  snd_info_buffer_t * buffer)
+{
+	emu10k1_t *emu = entry->private_data;
+	snd_emu10k1_proc_spdif_status(emu, buffer, "CD-ROM S/PDIF In", CDCS, CDSRCS);
+	snd_emu10k1_proc_spdif_status(emu, buffer, "Optical or Coax S/PDIF In", GPSCS, GPSRCS);
+#if 0
 	val = snd_emu10k1_ptr_read(emu, ZVSRCS, 0);
 	snd_iprintf(buffer, "\nZoomed Video\n");
 	snd_iprintf(buffer, "Rate Locked           : %s\n", val & SRCS_RATELOCKED ? "on" : "off");
 	snd_iprintf(buffer, "Estimated Sample Rate : 0x%x\n", val & SRCS_ESTSAMPLERATE);
+#endif
+}
+
+static void snd_emu10k1_proc_rates_read(snd_info_entry_t *entry, 
+				  snd_info_buffer_t * buffer)
+{
+	static int samplerate[8] = { 44100, 48000, 96000, 192000, 4, 5, 6, 7 };
+	emu10k1_t *emu = entry->private_data;
+	unsigned int val, tmp, n;
+	val = snd_emu10k1_ptr20_read(emu, CAPTURE_RATE_STATUS, 0);
+	tmp = (val >> 16) & 0x8;
+	for (n=0;n<4;n++) {
+		tmp = val >> (16 + (n*4));
+		if (tmp & 0x8) snd_iprintf(buffer, "Channel %d: Rate=%d\n", n, samplerate[tmp & 0x7]);
+		else snd_iprintf(buffer, "Channel %d: No input\n", n);
+	}
 }
 
 static void snd_emu10k1_proc_acode_read(snd_info_entry_t *entry, 
@@ -500,32 +527,46 @@
 		snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_io_reg_read);
 		entry->c.text.write_size = 64;
 		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;
 		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;
 		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;
 		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;
 		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);
 
+	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);
+	}
+	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);
+	}
+
 	if (! snd_card_proc_new(emu->card, "voices", &entry))
 		snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_voices_read);
 
diff --git a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c
index b81a7ca..cd8460d 100644
--- a/sound/pci/emu10k1/irq.c
+++ b/sound/pci/emu10k1/irq.c
@@ -37,7 +37,7 @@
 	int handled = 0;
 
 	while ((status = inl(emu->port + IPR)) != 0) {
-		// printk("irq - status = 0x%x\n", status);
+		//printk("emu10k1 irq - status = 0x%x\n", status);
 		orig_status = status;
 		handled = 1;
 		if (status & IPR_PCIERROR) {
@@ -147,9 +147,36 @@
 				snd_emu10k1_intr_disable(emu, INTE_FXDSPENABLE);
 			status &= ~IPR_FXDSP;
 		}
+		if (status & IPR_P16V) {
+			while ((status2 = inl(emu->port + IPR2)) != 0) {
+				u32 mask = INTE2_PLAYBACK_CH_0_LOOP;  /* Full Loop */
+				emu10k1_voice_t *pvoice = &(emu->p16v_voices[0]);
+				emu10k1_voice_t *cvoice = &(emu->p16v_capture_voice);
+
+				//printk(KERN_INFO "status2=0x%x\n", status2);
+				orig_status2 = status2;
+				if(status2 & mask) {
+					if(pvoice->use) {
+						snd_pcm_period_elapsed(pvoice->epcm->substream);
+					} else { 
+						snd_printk(KERN_ERR "p16v: status: 0x%08x, mask=0x%08x, pvoice=%p, use=%d\n", status2, mask, pvoice, pvoice->use);
+					}
+				}
+				if(status2 & 0x110000) {
+					//printk(KERN_INFO "capture int found\n");
+					if(cvoice->use) {
+						//printk(KERN_INFO "capture period_elapsed\n");
+						snd_pcm_period_elapsed(cvoice->epcm->substream);
+					}
+				}
+				outl(orig_status2, emu->port + IPR2); /* ack all */
+			}
+			status &= ~IPR_P16V;
+		}
+
 		if (status) {
 			unsigned int bits;
-			//snd_printk(KERN_ERR "emu10k1: unhandled interrupt: 0x%08x\n", status);
+			snd_printk(KERN_ERR "emu10k1: unhandled interrupt: 0x%08x\n", status);
 			//make sure any interrupts we don't handle are disabled:
 			bits = INTE_FXDSPENABLE |
 				INTE_PCIERRORENABLE |
@@ -170,20 +197,5 @@
 		}
 		outl(orig_status, emu->port + IPR); /* ack all */
 	}
-	if (emu->audigy && emu->revision == 4) { /* P16V */	
-		while ((status2 = inl(emu->port + IPR2)) != 0) {
-			u32 mask = INTE2_PLAYBACK_CH_0_LOOP;  /* Full Loop */
-			emu10k1_voice_t *pvoice = &(emu->p16v_voices[0]);
-			orig_status2 = status2;
-			if(status2 & mask) {
-				if(pvoice->use) {
-					snd_pcm_period_elapsed(pvoice->epcm->substream);
-				} else { 
-					snd_printk(KERN_ERR "p16v: status: 0x%08x, mask=0x%08x, pvoice=%p, use=%d\n", status2, mask, pvoice, pvoice->use);
-				}
-			}
-			outl(orig_status2, emu->port + IPR2); /* ack all */
-		}
-	}
 	return IRQ_RETVAL(handled);
 }
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c
index d03cb2f..98f9801 100644
--- a/sound/pci/emu10k1/p16v.c
+++ b/sound/pci/emu10k1/p16v.c
@@ -1,7 +1,7 @@
 /*
  *  Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk>
  *  Driver p16v chips
- *  Version: 0.22
+ *  Version: 0.25
  *
  *  FEATURES currently supported:
  *    Output fixed at S32_LE, 2 channel to hw:0,0
@@ -41,7 +41,15 @@
  *    Integrated with snd-emu10k1 driver.
  *  0.22
  *    Removed #if 0 ... #endif
- *
+ *  0.23
+ *    Implement different capture rates.
+ *  0.24
+ *    Implement different capture source channels.
+ *    e.g. When HD Capture source is set to SPDIF,
+ *    setting HD Capture channel to 0 captures from CDROM digital input.
+ *    setting HD Capture channel to 1 captures from SPDIF in.
+ *  0.25
+ *    Include capture buffer sizes.
  *
  *  BUGS:
  *    Some stability problems when unloading the snd-p16v kernel module.
@@ -119,22 +127,41 @@
 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
 				 SNDRV_PCM_INFO_MMAP_VALID),
 	.formats =		SNDRV_PCM_FMTBIT_S32_LE, /* Only supports 24-bit samples padded to 32 bits. */
-	.rates =		SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 ,
-	.rate_min =		48000,
+	.rates =		SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, 
+	.rate_min =		44100,
 	.rate_max =		192000,
 	.channels_min =		8, 
 	.channels_max =		8,
-	.buffer_bytes_max =	(32*1024),
+	.buffer_bytes_max =	((65536 - 64) * 8),
 	.period_bytes_min =	64,
-	.period_bytes_max =	(16*1024),
+	.period_bytes_max =	(65536 - 64),
 	.periods_min =		2,
 	.periods_max =		8,
 	.fifo_size =		0,
 };
 
+static snd_pcm_hardware_t snd_p16v_capture_hw = {
+	.info =			(SNDRV_PCM_INFO_MMAP |
+				 SNDRV_PCM_INFO_INTERLEAVED |
+				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
+				 SNDRV_PCM_INFO_MMAP_VALID),
+	.formats =		SNDRV_PCM_FMTBIT_S32_LE,
+	.rates =		SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_44100, 
+	.rate_min =		44100,
+	.rate_max =		192000,
+	.channels_min =		2,
+	.channels_max =		2,
+	.buffer_bytes_max =	(65536 - 64),
+	.period_bytes_min =	64,
+	.period_bytes_max =	(65536 - 128) >> 1,  /* size has to be N*64 bytes */
+	.periods_min =		2,
+	.periods_max =		2,
+	.fifo_size =		0,
+};
+
 static void snd_p16v_pcm_free_substream(snd_pcm_runtime_t *runtime)
 {
-	snd_pcm_t *epcm = runtime->private_data;
+	emu10k1_pcm_t *epcm = runtime->private_data;
   
 	if (epcm) {
         	//snd_printk("epcm free: %p\n", epcm);
@@ -178,15 +205,63 @@
 
 	return 0;
 }
+/* open_capture callback */
+static int snd_p16v_pcm_open_capture_channel(snd_pcm_substream_t *substream, int channel_id)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	emu10k1_voice_t *channel = &(emu->p16v_capture_voice);
+	emu10k1_pcm_t *epcm;
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	int err;
+
+	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+	//snd_printk("epcm kcalloc: %p\n", epcm);
+
+	if (epcm == NULL)
+		return -ENOMEM;
+	epcm->emu = emu;
+	epcm->substream = substream;
+	//snd_printk("epcm device=%d, channel_id=%d\n", substream->pcm->device, channel_id);
+
+	runtime->private_data = epcm;
+	runtime->private_free = snd_p16v_pcm_free_substream;
+  
+	runtime->hw = snd_p16v_capture_hw;
+
+	channel->emu = emu;
+	channel->number = channel_id;
+
+	channel->use=1;
+	//snd_printk("p16v: open channel_id=%d, channel=%p, use=0x%x\n", channel_id, channel, channel->use);
+	//printk("open:channel_id=%d, chip=%p, channel=%p\n",channel_id, chip, channel);
+	//channel->interrupt = snd_p16v_pcm_channel_interrupt;
+	channel->epcm=epcm;
+	if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
+		return err;
+
+	return 0;
+}
+
 
 /* close callback */
 static int snd_p16v_pcm_close_playback(snd_pcm_substream_t *substream)
 {
 	emu10k1_t *emu = snd_pcm_substream_chip(substream);
 	//snd_pcm_runtime_t *runtime = substream->runtime;
-        //emu10k1_pcm_t *epcm = runtime->private_data;
-        emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use=0;
-/* FIXME: maybe zero others */
+	//emu10k1_pcm_t *epcm = runtime->private_data;
+	emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use=0;
+	/* FIXME: maybe zero others */
+	return 0;
+}
+
+/* close callback */
+static int snd_p16v_pcm_close_capture(snd_pcm_substream_t *substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	//snd_pcm_runtime_t *runtime = substream->runtime;
+	//emu10k1_pcm_t *epcm = runtime->private_data;
+	emu->p16v_capture_voice.use=0;
+	/* FIXME: maybe zero others */
 	return 0;
 }
 
@@ -195,36 +270,55 @@
 	return snd_p16v_pcm_open_playback_channel(substream, PCM_FRONT_CHANNEL);
 }
 
+static int snd_p16v_pcm_open_capture(snd_pcm_substream_t *substream)
+{
+	// Only using channel 0 for now, but the card has 2 channels.
+	return snd_p16v_pcm_open_capture_channel(substream, 0);
+}
+
 /* hw_params callback */
 static int snd_p16v_pcm_hw_params_playback(snd_pcm_substream_t *substream,
 				      snd_pcm_hw_params_t * hw_params)
 {
 	int result;
-        //snd_printk("hw_params alloc: substream=%p\n", substream);
 	result = snd_pcm_lib_malloc_pages(substream,
 					params_buffer_bytes(hw_params));
-        //snd_printk("hw_params alloc: result=%d\n", result);
-	//dump_stack();
 	return result;
 }
 
+/* hw_params callback */
+static int snd_p16v_pcm_hw_params_capture(snd_pcm_substream_t *substream,
+				      snd_pcm_hw_params_t * hw_params)
+{
+	int result;
+	result = snd_pcm_lib_malloc_pages(substream,
+					params_buffer_bytes(hw_params));
+	return result;
+}
+
+
 /* hw_free callback */
 static int snd_p16v_pcm_hw_free_playback(snd_pcm_substream_t *substream)
 {
 	int result;
-        //snd_printk("hw_params free: substream=%p\n", substream);
 	result = snd_pcm_lib_free_pages(substream);
-        //snd_printk("hw_params free: result=%d\n", result);
-	//dump_stack();
 	return result;
 }
 
+/* hw_free callback */
+static int snd_p16v_pcm_hw_free_capture(snd_pcm_substream_t *substream)
+{
+	int result;
+	result = snd_pcm_lib_free_pages(substream);
+	return result;
+}
+
+
 /* prepare playback callback */
 static int snd_p16v_pcm_prepare_playback(snd_pcm_substream_t *substream)
 {
 	emu10k1_t *emu = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	//emu10k1_pcm_t *epcm = runtime->private_data;
 	int channel = substream->pcm->device - emu->p16v_device_offset;
 	u32 *table_base = (u32 *)(emu->p16v_buffer.area+(8*16*channel));
 	u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
@@ -237,23 +331,21 @@
 	tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
         switch (runtime->rate) {
 	case 44100:
-	  snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x8000); /* FIXME: This will change the capture rate as well! */
-	  break;
-	case 48000:
-	  snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x0000); /* FIXME: This will change the capture rate as well! */
+	  snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x8080);
 	  break;
 	case 96000:
-	  snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x4000); /* FIXME: This will change the capture rate as well! */
+	  snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x4040);
 	  break;
 	case 192000:
-	  snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe000) | 0x2000); /* FIXME: This will change the capture rate as well! */
+	  snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x2020);
 	  break;
+	case 48000:
 	default:
-	  snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, 0x0000); /* FIXME: This will change the capture rate as well! */
+	  snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0xe0e0) | 0x0000);
 	  break;
 	}
 	/* FIXME: Check emu->buffer.size before actually writing to it. */
-        for(i=0; i < runtime->periods; i++) {
+	for(i=0; i < runtime->periods; i++) {
 		table_base[i*2]=runtime->dma_addr+(i*period_size_bytes);
 		table_base[(i*2)+1]=period_size_bytes<<16;
 	}
@@ -262,7 +354,8 @@
 	snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_SIZE, channel, (runtime->periods - 1) << 19);
 	snd_emu10k1_ptr20_write(emu, PLAYBACK_LIST_PTR, channel, 0);
 	snd_emu10k1_ptr20_write(emu, PLAYBACK_DMA_ADDR, channel, runtime->dma_addr);
-	snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
+	//snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, frames_to_bytes(runtime, runtime->period_size)<<16); // buffer size in bytes
+	snd_emu10k1_ptr20_write(emu, PLAYBACK_PERIOD_SIZE, channel, 0); // buffer size in bytes
 	snd_emu10k1_ptr20_write(emu, PLAYBACK_POINTER, channel, 0);
 	snd_emu10k1_ptr20_write(emu, 0x07, channel, 0x0);
 	snd_emu10k1_ptr20_write(emu, 0x08, channel, 0);
@@ -270,6 +363,41 @@
 	return 0;
 }
 
+/* prepare capture callback */
+static int snd_p16v_pcm_prepare_capture(snd_pcm_substream_t *substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	int channel = substream->pcm->device - emu->p16v_device_offset;
+	u32 tmp;
+	//printk("prepare capture:channel_number=%d, rate=%d, format=0x%x, channels=%d, buffer_size=%ld, period_size=%ld, frames_to_bytes=%d\n",channel, runtime->rate, runtime->format, runtime->channels, runtime->buffer_size, runtime->period_size,  frames_to_bytes(runtime, 1));
+	tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, channel);
+        switch (runtime->rate) {
+	case 44100:
+	  snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0800);
+	  break;
+	case 96000:
+	  snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0400);
+	  break;
+	case 192000:
+	  snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0200);
+	  break;
+	case 48000:
+	default:
+	  snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, channel, (tmp & ~0x0e00) | 0x0000);
+	  break;
+	}
+	/* FIXME: Check emu->buffer.size before actually writing to it. */
+	snd_emu10k1_ptr20_write(emu, 0x13, channel, 0);
+	snd_emu10k1_ptr20_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
+	snd_emu10k1_ptr20_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes
+	snd_emu10k1_ptr20_write(emu, CAPTURE_POINTER, channel, 0);
+	//snd_emu10k1_ptr20_write(emu, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC or Line in */
+	//snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<<channel));
+
+	return 0;
+}
+
 static void snd_p16v_intr_enable(emu10k1_t *emu, unsigned int intrenb)
 {
 	unsigned long flags;
@@ -345,6 +473,36 @@
 	return result;
 }
 
+/* trigger_capture callback */
+static int snd_p16v_pcm_trigger_capture(snd_pcm_substream_t *substream,
+                                   int cmd)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	emu10k1_pcm_t *epcm = runtime->private_data;
+	int channel = 0;
+	int result = 0;
+	u32 inte = INTE2_CAPTURE_CH_0_LOOP | INTE2_CAPTURE_CH_0_HALF_LOOP;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		snd_p16v_intr_enable(emu, inte);
+		snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0)|(0x100<<channel));
+		epcm->running = 1;
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & ~(0x100<<channel));
+		snd_p16v_intr_disable(emu, inte);
+		//snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) & ~(0x110000<<channel));
+		epcm->running = 0;
+		break;
+	default:
+		result = -EINVAL;
+		break;
+	}
+	return result;
+}
+
 /* pointer_playback callback */
 static snd_pcm_uframes_t
 snd_p16v_pcm_pointer_playback(snd_pcm_substream_t *substream)
@@ -370,6 +528,31 @@
 	return ptr;
 }
 
+/* pointer_capture callback */
+static snd_pcm_uframes_t
+snd_p16v_pcm_pointer_capture(snd_pcm_substream_t *substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	emu10k1_pcm_t *epcm = runtime->private_data;
+	snd_pcm_uframes_t ptr, ptr1, ptr2 = 0;
+	int channel = 0;
+
+	if (!epcm->running)
+		return 0;
+
+	ptr1 = snd_emu10k1_ptr20_read(emu, CAPTURE_POINTER, channel);
+	ptr2 = bytes_to_frames(runtime, ptr1);
+	ptr=ptr2;
+	if (ptr >= runtime->buffer_size) {
+		ptr -= runtime->buffer_size;
+		printk("buffer capture limited!\n");
+	}
+	//printk("ptr1 = 0x%lx, ptr2=0x%lx, ptr=0x%lx, buffer_size = 0x%x, period_size = 0x%x, bits=%d, rate=%d\n", ptr1, ptr2, ptr, (int)runtime->buffer_size, (int)runtime->period_size, (int)runtime->frame_bits, (int)runtime->rate);
+
+	return ptr;
+}
+
 /* operators */
 static snd_pcm_ops_t snd_p16v_playback_front_ops = {
 	.open =        snd_p16v_pcm_open_playback_front,
@@ -382,6 +565,18 @@
 	.pointer =     snd_p16v_pcm_pointer_playback,
 };
 
+static snd_pcm_ops_t snd_p16v_capture_ops = {
+	.open =        snd_p16v_pcm_open_capture,
+	.close =       snd_p16v_pcm_close_capture,
+	.ioctl =       snd_pcm_lib_ioctl,
+	.hw_params =   snd_p16v_pcm_hw_params_capture,
+	.hw_free =     snd_p16v_pcm_hw_free_capture,
+	.prepare =     snd_p16v_pcm_prepare_capture,
+	.trigger =     snd_p16v_pcm_trigger_capture,
+	.pointer =     snd_p16v_pcm_pointer_capture,
+};
+
+
 int snd_p16v_free(emu10k1_t *chip)
 {
 	// release the data
@@ -405,20 +600,22 @@
 	snd_pcm_t *pcm;
 	snd_pcm_substream_t *substream;
 	int err;
-        int capture=0;
+        int capture=1;
   
 	//snd_printk("snd_p16v_pcm called. device=%d\n", device);
 	emu->p16v_device_offset = device;
 	if (rpcm)
 		*rpcm = NULL;
-        //if (device == 0) capture=1; 
+
 	if ((err = snd_pcm_new(emu->card, "p16v", device, 1, capture, &pcm)) < 0)
 		return err;
   
 	pcm->private_data = emu;
 	pcm->private_free = snd_p16v_pcm_free;
-
+	// Single playback 8 channel device.
+	// Single capture 2 channel device.
 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_p16v_playback_front_ops);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_p16v_capture_ops);
 
 	pcm->info_flags = 0;
 	pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
@@ -431,7 +628,7 @@
 		if ((err = snd_pcm_lib_preallocate_pages(substream, 
 							 SNDRV_DMA_TYPE_DEV, 
 							 snd_dma_pci_data(emu->pci), 
-							 64*1024, 64*1024)) < 0) /* FIXME: 32*1024 for sound buffer, between 32and64 for Periods table. */
+							 ((65536 - 64) * 8), ((65536 - 64) * 8))) < 0) 
 			return err;
 		//snd_printk("preallocate playback substream: err=%d\n", err);
 	}
@@ -442,7 +639,7 @@
  		if ((err = snd_pcm_lib_preallocate_pages(substream, 
 	                                           SNDRV_DMA_TYPE_DEV, 
 	                                           snd_dma_pci_data(emu->pci), 
-	                                           64*1024, 64*1024)) < 0)
+	                                           65536 - 64, 65536 - 64)) < 0)
 			return err;
 		//snd_printk("preallocate capture substream: err=%d\n", err);
 	}
@@ -694,6 +891,106 @@
         .put =          snd_p16v_volume_put_spdif_rear
 };
 
+static int snd_p16v_capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+	static char *texts[8] = { "SPDIF", "I2S", "SRC48", "SRCMulti_SPDIF", "SRCMulti_I2S", "CDIF", "FX", "AC97" };
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 8;
+	if (uinfo->value.enumerated.item > 7)
+                uinfo->value.enumerated.item = 7;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int snd_p16v_capture_source_get(snd_kcontrol_t * kcontrol,
+					snd_ctl_elem_value_t * ucontrol)
+{
+	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.enumerated.item[0] = emu->p16v_capture_source;
+	return 0;
+}
+
+static int snd_p16v_capture_source_put(snd_kcontrol_t * kcontrol,
+					snd_ctl_elem_value_t * ucontrol)
+{
+	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+	unsigned int val;
+	int change = 0;
+	u32 mask;
+	u32 source;
+
+	val = ucontrol->value.enumerated.item[0] ;
+	change = (emu->p16v_capture_source != val);
+	if (change) {
+		emu->p16v_capture_source = val;
+		source = (val << 28) | (val << 24) | (val << 20) | (val << 16);
+		mask = snd_emu10k1_ptr20_read(emu, BASIC_INTERRUPT, 0) & 0xffff;
+		snd_emu10k1_ptr20_write(emu, BASIC_INTERRUPT, 0, source | mask);
+	}
+        return change;
+}
+
+static snd_kcontrol_new_t snd_p16v_capture_source __devinitdata =
+{
+	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name =		"HD Capture source",
+	.info =		snd_p16v_capture_source_info,
+	.get =		snd_p16v_capture_source_get,
+	.put =		snd_p16v_capture_source_put
+};
+
+static int snd_p16v_capture_channel_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+	static char *texts[4] = { "0", "1", "2", "3",  };
+
+	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_p16v_capture_channel_get(snd_kcontrol_t * kcontrol,
+					snd_ctl_elem_value_t * ucontrol)
+{
+	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.enumerated.item[0] = emu->p16v_capture_channel;
+	return 0;
+}
+
+static int snd_p16v_capture_channel_put(snd_kcontrol_t * kcontrol,
+					snd_ctl_elem_value_t * ucontrol)
+{
+	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+	unsigned int val;
+	int change = 0;
+	u32 tmp;
+
+	val = ucontrol->value.enumerated.item[0] ;
+	change = (emu->p16v_capture_channel != val);
+	if (change) {
+		emu->p16v_capture_channel = val;
+		tmp = snd_emu10k1_ptr20_read(emu, CAPTURE_P16V_SOURCE, 0) & 0xfffc;
+		snd_emu10k1_ptr20_write(emu, CAPTURE_P16V_SOURCE, 0, tmp | val);
+	}
+        return change;
+}
+
+static snd_kcontrol_new_t snd_p16v_capture_channel __devinitdata =
+{
+	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name =		"HD Capture channel",
+	.info =		snd_p16v_capture_channel_info,
+	.get =		snd_p16v_capture_channel_get,
+	.put =		snd_p16v_capture_channel_put
+};
+
 int snd_p16v_mixer(emu10k1_t *emu)
 {
         int err;
@@ -731,6 +1028,14 @@
                 return -ENOMEM;
         if ((err = snd_ctl_add(card, kctl)))
                 return err;
+        if ((kctl = snd_ctl_new1(&snd_p16v_capture_source, emu)) == NULL)
+                return -ENOMEM;
+        if ((err = snd_ctl_add(card, kctl)))
+                return err;
+        if ((kctl = snd_ctl_new1(&snd_p16v_capture_channel, emu)) == NULL)
+                return -ENOMEM;
+        if ((err = snd_ctl_add(card, kctl)))
+                return err;
         return 0;
 }
 
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index f910399..4e63498 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -2401,7 +2401,7 @@
 	
 static int __init alsa_card_ens137x_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_ens137x_exit(void)
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index b4ca8ad..b492777 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -1761,7 +1761,7 @@
 
 static int __init alsa_card_es1938_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_es1938_exit(void)
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index faf63ff..ea889b3 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -2559,6 +2559,7 @@
 	{ TYPE_MAESTRO2E, 0x103c },
 	{ TYPE_MAESTRO2E, 0x1179 },
 	{ TYPE_MAESTRO2E, 0x14c0 },	/* HP omnibook 4150 */
+	{ TYPE_MAESTRO2E, 0x1558 },
 };
 
 static struct ess_device_list mpu_blacklist[] __devinitdata = {
@@ -2795,7 +2796,7 @@
 
 static int __init alsa_card_es1968_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_es1968_exit(void)
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index 08e7c5a..ff10e63 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -195,6 +195,7 @@
 
 static struct pci_device_id snd_fm801_ids[] = {
 	{ 0x1319, 0x0801, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, },   /* FM801 */
+	{ 0x5213, 0x0510, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, },   /* Gallant Odyssey Sound 4 */
 	{ 0, }
 };
 
@@ -1468,7 +1469,7 @@
 
 static int __init alsa_card_fm801_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_fm801_exit(void)
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index 570a59d..bd8cb33 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
+snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o patch_sigmatel.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 9ed117a..e2cf023 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -49,8 +49,10 @@
 /* codec vendor labels */
 static struct hda_vendor_id hda_vendor_ids[] = {
 	{ 0x10ec, "Realtek" },
+	{ 0x11d4, "Analog Devices" },
 	{ 0x13f6, "C-Media" },
 	{ 0x434d, "C-Media" },
+	{ 0x8384, "SigmaTel" },
 	{} /* terminator */
 };
 
@@ -508,7 +510,7 @@
 	/* FIXME: support for multiple AFGs? */
 	codec->afg = look_for_afg_node(codec);
 	if (! codec->afg) {
-		snd_printk(KERN_ERR "hda_codec: no AFG node found\n");
+		snd_printdd("hda_codec: no AFG node found\n");
 		snd_hda_codec_free(codec);
 		return -ENODEV;
 	}
@@ -548,6 +550,9 @@
 void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stream_tag,
 				int channel_id, int format)
 {
+	if (! nid)
+		return;
+
 	snd_printdd("hda_codec_setup_stream: NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
 		    nid, stream_tag, channel_id, format);
 	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
@@ -561,9 +566,10 @@
  * amp access functions
  */
 
-#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + (idx) * 32 + (dir) * 64)
+/* FIXME: more better hash key? */
+#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + ((idx) << 16) + ((dir) << 24))
 #define INFO_AMP_CAPS	(1<<0)
-#define INFO_AMP_VOL	(1<<1)
+#define INFO_AMP_VOL(ch)	(1 << (1 + (ch)))
 
 /* initialize the hash table */
 static void init_amp_hash(struct hda_codec *codec)
@@ -622,28 +628,29 @@
 
 /*
  * read the current volume to info
- * if the cache exists, read from the cache.
+ * if the cache exists, read the cache value.
  */
-static void get_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
+static unsigned int get_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
 			 hda_nid_t nid, int ch, int direction, int index)
 {
 	u32 val, parm;
 
-	if (info->status & (INFO_AMP_VOL << ch))
-		return;
+	if (info->status & INFO_AMP_VOL(ch))
+		return info->vol[ch];
 
 	parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
 	parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
 	parm |= index;
 	val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, parm);
 	info->vol[ch] = val & 0xff;
-	info->status |= INFO_AMP_VOL << ch;
+	info->status |= INFO_AMP_VOL(ch);
+	return info->vol[ch];
 }
 
 /*
- * write the current volume in info to the h/w
+ * write the current volume in info to the h/w and update the cache
  */
-static void put_vol_mute(struct hda_codec *codec,
+static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
 			 hda_nid_t nid, int ch, int direction, int index, int val)
 {
 	u32 parm;
@@ -653,30 +660,34 @@
 	parm |= index << AC_AMP_SET_INDEX_SHIFT;
 	parm |= val;
 	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
+	info->vol[ch] = val;
 }
 
 /*
- * read/write AMP value.  The volume is between 0 to 0x7f, 0x80 = mute bit.
+ * read AMP value.  The volume is between 0 to 0x7f, 0x80 = mute bit.
  */
-int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int index)
+static int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int index)
 {
 	struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
 	if (! info)
 		return 0;
-	get_vol_mute(codec, info, nid, ch, direction, index);
-	return info->vol[ch];
+	return get_vol_mute(codec, info, nid, ch, direction, index);
 }
 
-int snd_hda_codec_amp_write(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int idx, int val)
+/*
+ * update the AMP value, mask = bit mask to set, val = the value
+ */
+static int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int idx, int mask, int val)
 {
 	struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
+
 	if (! info)
 		return 0;
-	get_vol_mute(codec, info, nid, ch, direction, idx);
+	val &= mask;
+	val |= get_vol_mute(codec, info, nid, ch, direction, idx) & ~mask;
 	if (info->vol[ch] == val && ! codec->in_resume)
 		return 0;
-	put_vol_mute(codec, nid, ch, direction, idx, val);
-	info->vol[ch] = val;
+	put_vol_mute(codec, info, nid, ch, direction, idx, val);
 	return 1;
 }
 
@@ -735,21 +746,15 @@
 	int chs = get_amp_channels(kcontrol);
 	int dir = get_amp_direction(kcontrol);
 	int idx = get_amp_index(kcontrol);
-	int val;
 	long *valp = ucontrol->value.integer.value;
 	int change = 0;
 
-	if (chs & 1) {
-		val = *valp & 0x7f;
-		val |= snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x80;
-		change = snd_hda_codec_amp_write(codec, nid, 0, dir, idx, val);
-		valp++;
-	}
-	if (chs & 2) {
-		val = *valp & 0x7f;
-		val |= snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x80;
-		change |= snd_hda_codec_amp_write(codec, nid, 1, dir, idx, val);
-	}
+	if (chs & 1)
+		change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
+						  0x7f, *valp);
+	if (chs & 2)
+		change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
+						   0x7f, valp[1]);
 	return change;
 }
 
@@ -788,21 +793,15 @@
 	int chs = get_amp_channels(kcontrol);
 	int dir = get_amp_direction(kcontrol);
 	int idx = get_amp_index(kcontrol);
-	int val;
 	long *valp = ucontrol->value.integer.value;
 	int change = 0;
 
-	if (chs & 1) {
-		val = snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x7f;
-		val |= *valp ? 0 : 0x80;
-		change = snd_hda_codec_amp_write(codec, nid, 0, dir, idx, val);
-		valp++;
-	}
-	if (chs & 2) {
-		val = snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x7f;
-		val |= *valp ? 0 : 0x80;
-		change = snd_hda_codec_amp_write(codec, nid, 1, dir, idx, val);
-	}
+	if (chs & 1)
+		change = snd_hda_codec_amp_update(codec, nid, 0, dir, idx,
+						  0x80, *valp ? 0 : 0x80);
+	if (chs & 2)
+		change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx,
+						   0x80, valp[1] ? 0 : 0x80);
 	return change;
 }
 
@@ -1448,10 +1447,6 @@
 		snd_assert(info->nid, return -EINVAL);
 		info->ops.prepare = hda_pcm_default_prepare;
 	}
-	if (info->ops.prepare == NULL) {
-		snd_assert(info->nid, return -EINVAL);
-		info->ops.prepare = hda_pcm_default_prepare;
-	}
 	if (info->ops.cleanup == NULL) {
 		snd_assert(info->nid, return -EINVAL);
 		info->ops.cleanup = hda_pcm_default_cleanup;
@@ -1525,12 +1520,12 @@
  *
  * If no entries are matching, the function returns a negative value.
  */
-int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config *tbl)
+int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_config *tbl)
 {
-	struct hda_board_config *c;
+	const struct hda_board_config *c;
 
 	if (codec->bus->modelname) {
-		for (c = tbl; c->modelname || c->pci_vendor; c++) {
+		for (c = tbl; c->modelname || c->pci_subvendor; c++) {
 			if (c->modelname &&
 			    ! strcmp(codec->bus->modelname, c->modelname)) {
 				snd_printd(KERN_INFO "hda_codec: model '%s' is selected\n", c->modelname);
@@ -1543,9 +1538,10 @@
 		u16 subsystem_vendor, subsystem_device;
 		pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
 		pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_ID, &subsystem_device);
-		for (c = tbl; c->modelname || c->pci_vendor; c++) {
-			if (c->pci_vendor == subsystem_vendor &&
-			    c->pci_device == subsystem_device)
+		for (c = tbl; c->modelname || c->pci_subvendor; c++) {
+			if (c->pci_subvendor == subsystem_vendor &&
+			    (! c->pci_subdevice /* all match */||
+			     (c->pci_subdevice == subsystem_device)))
 				return c->config;
 		}
 	}
@@ -1687,11 +1683,12 @@
 		snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format);
 	/* surrounds */
 	for (i = 1; i < mout->num_dacs; i++) {
-		if (i == HDA_REAR && chs == 2) /* copy front to rear */
-			snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, format);
-		else if (chs >= (i + 1) * 2) /* independent out */
+		if (chs >= (i + 1) * 2) /* independent out */
 			snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2,
 						   format);
+		else /* copy front */
+			snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0,
+						   format);
 	}
 	return 0;
 }
@@ -1717,6 +1714,105 @@
 	return 0;
 }
 
+/*
+ * Helper for automatic ping configuration
+ */
+/* parse all pin widgets and store the useful pin nids to cfg */
+int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg)
+{
+	hda_nid_t nid, nid_start;
+	int i, j, nodes;
+	short seq, sequences[4], assoc_line_out;
+
+	memset(cfg, 0, sizeof(*cfg));
+
+	memset(sequences, 0, sizeof(sequences));
+	assoc_line_out = 0;
+
+	nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid_start);
+	for (nid = nid_start; nid < nodes + nid_start; nid++) {
+		unsigned int wid_caps = snd_hda_param_read(codec, nid,
+							   AC_PAR_AUDIO_WIDGET_CAP);
+		unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+		unsigned int def_conf;
+		short assoc, loc;
+
+		/* read all default configuration for pin complex */
+		if (wid_type != AC_WID_PIN)
+			continue;
+		def_conf = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+		if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
+			continue;
+		loc = get_defcfg_location(def_conf);
+		switch (get_defcfg_device(def_conf)) {
+		case AC_JACK_LINE_OUT:
+		case AC_JACK_SPEAKER:
+			seq = get_defcfg_sequence(def_conf);
+			assoc = get_defcfg_association(def_conf);
+			if (! assoc)
+				continue;
+			if (! assoc_line_out)
+				assoc_line_out = assoc;
+			else if (assoc_line_out != assoc)
+				continue;
+			if (cfg->line_outs >= ARRAY_SIZE(cfg->line_out_pins))
+				continue;
+			cfg->line_out_pins[cfg->line_outs] = nid;
+			sequences[cfg->line_outs] = seq;
+			cfg->line_outs++;
+			break;
+		case AC_JACK_HP_OUT:
+			cfg->hp_pin = nid;
+			break;
+		case AC_JACK_MIC_IN:
+			if (loc == AC_JACK_LOC_FRONT)
+				cfg->input_pins[AUTO_PIN_FRONT_MIC] = nid;
+			else
+				cfg->input_pins[AUTO_PIN_MIC] = nid;
+			break;
+		case AC_JACK_LINE_IN:
+			if (loc == AC_JACK_LOC_FRONT)
+				cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid;
+			else
+				cfg->input_pins[AUTO_PIN_LINE] = nid;
+			break;
+		case AC_JACK_CD:
+			cfg->input_pins[AUTO_PIN_CD] = nid;
+			break;
+		case AC_JACK_AUX:
+			cfg->input_pins[AUTO_PIN_AUX] = nid;
+			break;
+		case AC_JACK_SPDIF_OUT:
+			cfg->dig_out_pin = nid;
+			break;
+		case AC_JACK_SPDIF_IN:
+			cfg->dig_in_pin = nid;
+			break;
+		}
+	}
+
+	/* sort by sequence */
+	for (i = 0; i < cfg->line_outs; i++)
+		for (j = i + 1; j < cfg->line_outs; j++)
+			if (sequences[i] > sequences[j]) {
+				seq = sequences[i];
+				sequences[i] = sequences[j];
+				sequences[j] = seq;
+				nid = cfg->line_out_pins[i];
+				cfg->line_out_pins[i] = cfg->line_out_pins[j];
+				cfg->line_out_pins[j] = nid;
+			}
+
+	/* Swap surround and CLFE: the association order is front/CLFE/surr/back */
+	if (cfg->line_outs >= 3) {
+		nid = cfg->line_out_pins[1];
+		cfg->line_out_pins[1] = cfg->line_out_pins[2];
+		cfg->line_out_pins[2] = nid;
+	}
+
+	return 0;
+}
+
 #ifdef CONFIG_PM
 /*
  * power management
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index c9e9dc9..5999156 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -75,6 +75,9 @@
 #define AC_VERB_GET_DIGI_CONVERT		0x0f0d
 #define AC_VERB_GET_VOLUME_KNOB_CONTROL		0x0f0f
 /* f10-f1a: GPIO */
+#define AC_VERB_GET_GPIO_DATA			0x0f15
+#define AC_VERB_GET_GPIO_MASK			0x0f16
+#define AC_VERB_GET_GPIO_DIRECTION		0x0f17
 #define AC_VERB_GET_CONFIG_DEFAULT		0x0f1c
 
 /*
@@ -97,6 +100,9 @@
 #define AC_VERB_SET_DIGI_CONVERT_1		0x70d
 #define AC_VERB_SET_DIGI_CONVERT_2		0x70e
 #define AC_VERB_SET_VOLUME_KNOB_CONTROL		0x70f
+#define AC_VERB_SET_GPIO_DATA			0x715
+#define AC_VERB_SET_GPIO_MASK			0x716
+#define AC_VERB_SET_GPIO_DIRECTION		0x717
 #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_0	0x71c
 #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1	0x71d
 #define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2	0x71e
@@ -176,16 +182,15 @@
 #define AC_PINCAP_OUT			(1<<4)	/* output capable */
 #define AC_PINCAP_IN			(1<<5)	/* input capable */
 #define AC_PINCAP_BALANCE		(1<<6)	/* balanced I/O capable */
-#define AC_PINCAP_VREF			(7<<8)
+#define AC_PINCAP_VREF			(0x37<<8)
 #define AC_PINCAP_VREF_SHIFT		8
 #define AC_PINCAP_EAPD			(1<<16)	/* EAPD capable */
-/* Vref status (used in pin cap and pin ctl) */
-#define AC_PIN_VREF_HIZ			(1<<0)	/* Hi-Z */
-#define AC_PIN_VREF_50			(1<<1)	/* 50% */
-#define AC_PIN_VREF_GRD			(1<<2)	/* ground */
-#define AC_PIN_VREF_80			(1<<4)	/* 80% */
-#define AC_PIN_VREF_100			(1<<5)	/* 100% */
-
+/* Vref status (used in pin cap) */
+#define AC_PINCAP_VREF_HIZ		(1<<0)	/* Hi-Z */
+#define AC_PINCAP_VREF_50		(1<<1)	/* 50% */
+#define AC_PINCAP_VREF_GRD		(1<<2)	/* ground */
+#define AC_PINCAP_VREF_80		(1<<4)	/* 80% */
+#define AC_PINCAP_VREF_100		(1<<5)	/* 100% */
 
 /* Amplifier capabilities */
 #define AC_AMPCAP_OFFSET		(0x7f<<0)  /* 0dB offset */
@@ -248,6 +253,11 @@
 
 /* Pin widget control - 8bit */
 #define AC_PINCTL_VREFEN		(0x7<<0)
+#define AC_PINCTL_VREF_HIZ		0	/* Hi-Z */
+#define AC_PINCTL_VREF_50		1	/* 50% */
+#define AC_PINCTL_VREF_GRD		2	/* ground */
+#define AC_PINCTL_VREF_80		4	/* 80% */
+#define AC_PINCTL_VREF_100		5	/* 100% */
 #define AC_PINCTL_IN_EN			(1<<5)
 #define AC_PINCTL_OUT_EN		(1<<6)
 #define AC_PINCTL_HP_EN			(1<<7)
@@ -255,7 +265,9 @@
 /* configuration default - 32bit */
 #define AC_DEFCFG_SEQUENCE		(0xf<<0)
 #define AC_DEFCFG_DEF_ASSOC		(0xf<<4)
+#define AC_DEFCFG_ASSOC_SHIFT		4
 #define AC_DEFCFG_MISC			(0xf<<8)
+#define AC_DEFCFG_MISC_SHIFT		8
 #define AC_DEFCFG_COLOR			(0xf<<12)
 #define AC_DEFCFG_COLOR_SHIFT		12
 #define AC_DEFCFG_CONN_TYPE		(0xf<<16)
@@ -413,7 +425,7 @@
 
 	/* codec linked list */
 	struct list_head codec_list;
-	struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS]; /* caddr -> codec */
+	struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS + 1]; /* caddr -> codec */
 
 	struct semaphore cmd_mutex;
 
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 69f7b6c..2d046ab 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -44,7 +44,7 @@
 	struct list_head list;
 };
 
-/* pathc-specific record */
+/* patch-specific record */
 struct hda_gspec {
 	struct hda_gnode *dac_node;	/* DAC node */
 	struct hda_gnode *out_pin_node;	/* Output pin (Line-Out) node */
@@ -68,8 +68,8 @@
 /*
  * retrieve the default device type from the default config value
  */
-#define get_defcfg_type(node) (((node)->def_cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
-#define get_defcfg_location(node) (((node)->def_cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
+#define defcfg_type(node) (((node)->def_cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
+#define defcfg_location(node) (((node)->def_cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
 
 /*
  * destructor
@@ -323,7 +323,7 @@
 		if (! (node->pin_caps & AC_PINCAP_OUT))
 			continue;
 		if (jack_type >= 0) {
-			if (jack_type != get_defcfg_type(node))
+			if (jack_type != defcfg_type(node))
 				continue;
 			if (node->wid_caps & AC_WCAP_DIGITAL)
 				continue; /* skip SPDIF */
@@ -418,15 +418,15 @@
  */
 static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl)
 {
-	unsigned int location = get_defcfg_location(node);
-	switch (get_defcfg_type(node)) {
+	unsigned int location = defcfg_location(node);
+	switch (defcfg_type(node)) {
 	case AC_JACK_LINE_IN:
 		if ((location & 0x0f) == AC_JACK_LOC_FRONT)
 			return "Front Line";
 		return "Line";
 	case AC_JACK_CD:
 		if (pinctl)
-			*pinctl |= AC_PIN_VREF_GRD;
+			*pinctl |= AC_PINCTL_VREF_GRD;
 		return "CD";
 	case AC_JACK_AUX:
 		if ((location & 0x0f) == AC_JACK_LOC_FRONT)
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 959953c..5e0cca3 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -51,6 +51,7 @@
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
 static char *model[SNDRV_CARDS];
+static int position_fix[SNDRV_CARDS];
 
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
@@ -60,12 +61,17 @@
 MODULE_PARM_DESC(enable, "Enable Intel HD audio interface.");
 module_param_array(model, charp, NULL, 0444);
 MODULE_PARM_DESC(model, "Use the given board model.");
+module_param_array(position_fix, int, NULL, 0444);
+MODULE_PARM_DESC(position_fix, "Fix DMA pointer (0 = FIFO size, 1 = none, 2 = POSBUF).");
 
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
 			 "{Intel, ICH6M},"
 			 "{Intel, ICH7},"
-			 "{Intel, ESB2}}");
+			 "{Intel, ESB2},"
+			 "{ATI, SB450},"
+			 "{VIA, VT8251},"
+			 "{VIA, VT8237A}}");
 MODULE_DESCRIPTION("Intel HDA driver");
 
 #define SFX	"hda-intel: "
@@ -150,7 +156,7 @@
 
 /* STATESTS int mask: SD2,SD1,SD0 */
 #define STATESTS_INT_MASK	0x07
-#define AZX_MAX_CODECS		3
+#define AZX_MAX_CODECS		4
 
 /* SD_CTL bits */
 #define SD_CTL_STREAM_RESET	0x01	/* stream reset bit */
@@ -183,6 +189,18 @@
 #define ICH6_MAX_CORB_ENTRIES	256
 #define ICH6_MAX_RIRB_ENTRIES	256
 
+/* position fix mode */
+enum {
+	POS_FIX_FIFO,
+	POS_FIX_NONE,
+	POS_FIX_POSBUF
+};
+
+/* Defines for ATI HD Audio support in SB450 south bridge */
+#define ATI_SB450_HDAUDIO_PCI_DEVICE_ID     0x437b
+#define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR   0x42
+#define ATI_SB450_HDAUDIO_ENABLE_SNOOP      0x02
+
 
 /*
  * Use CORB/RIRB for communication from/to codecs.
@@ -191,12 +209,6 @@
 #define USE_CORB_RIRB
 
 /*
- * Define this if use the position buffer instead of reading SD_LPIB
- * It's not used as default since SD_LPIB seems to give more accurate position
- */
-/* #define USE_POSBUF */
-
-/*
  */
 
 typedef struct snd_azx azx_t;
@@ -271,6 +283,10 @@
 	struct snd_dma_buffer bdl;
 	struct snd_dma_buffer rb;
 	struct snd_dma_buffer posbuf;
+
+	/* flags */
+	int position_fix;
+	unsigned int initialized: 1;
 };
 
 /*
@@ -638,7 +654,7 @@
  */
 static void azx_init_chip(azx_t *chip)
 {
-	unsigned char tcsel_reg;
+	unsigned char tcsel_reg, ati_misc_cntl2;
 
 	/* Clear bits 0-2 of PCI register TCSEL (at offset 0x44)
 	 * TCSEL == Traffic Class Select Register, which sets PCI express QOS
@@ -657,11 +673,20 @@
 	/* initialize the codec command I/O */
 	azx_init_cmd_io(chip);
 
-#ifdef USE_POSBUF
-	/* program the position buffer */
-	azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
-	azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
-#endif
+	if (chip->position_fix == POS_FIX_POSBUF) {
+		/* program the position buffer */
+		azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
+		azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
+	}
+
+	/* For ATI SB450 azalia HD audio, we need to enable snoop */
+	if (chip->pci->vendor == PCI_VENDOR_ID_ATI && 
+	    chip->pci->device == ATI_SB450_HDAUDIO_PCI_DEVICE_ID) {
+		pci_read_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, 
+				     &ati_misc_cntl2);
+		pci_write_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, 
+				      (ati_misc_cntl2 & 0xf8) | ATI_SB450_HDAUDIO_ENABLE_SNOOP);
+	}
 }
 
 
@@ -791,11 +816,12 @@
 	/* upper BDL address */
 	azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr));
 
-#ifdef USE_POSBUF
-	/* enable the position buffer */
-	if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
-		azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
-#endif
+	if (chip->position_fix == POS_FIX_POSBUF) {
+		/* enable the position buffer */
+		if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
+			azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
+	}
+
 	/* set the interrupt enable bits in the descriptor control register */
 	azx_sd_writel(azx_dev, SD_CTL, azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK);
 
@@ -1036,16 +1062,20 @@
 
 static snd_pcm_uframes_t azx_pcm_pointer(snd_pcm_substream_t *substream)
 {
+	struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
+	azx_t *chip = apcm->chip;
 	azx_dev_t *azx_dev = get_azx_dev(substream);
 	unsigned int pos;
 
-#ifdef USE_POSBUF
-	/* use the position buffer */
-	pos = *azx_dev->posbuf;
-#else
-	/* read LPIB */
-	pos = azx_sd_readl(azx_dev, SD_LPIB) + azx_dev->fifo_size;
-#endif
+	if (chip->position_fix == POS_FIX_POSBUF) {
+		/* use the position buffer */
+		pos = *azx_dev->posbuf;
+	} else {
+		/* read LPIB */
+		pos = azx_sd_readl(azx_dev, SD_LPIB);
+		if (chip->position_fix == POS_FIX_FIFO)
+			pos += azx_dev->fifo_size;
+	}
 	if (pos >= azx_dev->bufsize)
 		pos = 0;
 	return bytes_to_frames(substream->runtime, pos);
@@ -1155,9 +1185,8 @@
 		azx_dev_t *azx_dev = &chip->azx_dev[i];
 		azx_dev->bdl = (u32 *)(chip->bdl.area + off);
 		azx_dev->bdl_addr = chip->bdl.addr + off;
-#ifdef USE_POSBUF
-		azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8);
-#endif
+		if (chip->position_fix == POS_FIX_POSBUF)
+			azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8);
 		/* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
 		azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80);
 		/* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */
@@ -1207,7 +1236,7 @@
  */
 static int azx_free(azx_t *chip)
 {
-	if (chip->remap_addr) {
+	if (chip->initialized) {
 		int i;
 
 		for (i = 0; i < MAX_ICH6_DEV; i++)
@@ -1237,10 +1266,8 @@
 		snd_dma_free_pages(&chip->bdl);
 	if (chip->rb.area)
 		snd_dma_free_pages(&chip->rb);
-#ifdef USE_POSBUF
 	if (chip->posbuf.area)
 		snd_dma_free_pages(&chip->posbuf);
-#endif
 	pci_release_regions(chip->pci);
 	pci_disable_device(chip->pci);
 	kfree(chip);
@@ -1256,7 +1283,8 @@
 /*
  * constructor
  */
-static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **rchip)
+static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci,
+				int posfix, azx_t **rchip)
 {
 	azx_t *chip;
 	int err = 0;
@@ -1283,6 +1311,8 @@
 	chip->pci = pci;
 	chip->irq = -1;
 
+	chip->position_fix = posfix;
+
 	if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) {
 		kfree(chip);
 		pci_disable_device(pci);
@@ -1314,14 +1344,14 @@
 		snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
 		goto errout;
 	}
-#ifdef USE_POSBUF
-	/* allocate memory for the position buffer */
-	if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
-				       MAX_ICH6_DEV * 8, &chip->posbuf)) < 0) {
-		snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
-		goto errout;
+	if (chip->position_fix == POS_FIX_POSBUF) {
+		/* allocate memory for the position buffer */
+		if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+					       MAX_ICH6_DEV * 8, &chip->posbuf)) < 0) {
+			snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
+			goto errout;
+		}
 	}
-#endif
 	/* allocate CORB/RIRB */
 	if ((err = azx_alloc_cmd_io(chip)) < 0)
 		goto errout;
@@ -1332,6 +1362,8 @@
 	/* initialize chip */
 	azx_init_chip(chip);
 
+	chip->initialized = 1;
+
 	/* codec detection */
 	if (! chip->codec_mask) {
 		snd_printk(KERN_ERR SFX "no codecs found!\n");
@@ -1372,7 +1404,7 @@
 		return -ENOMEM;
 	}
 
-	if ((err = azx_create(card, pci, &chip)) < 0) {
+	if ((err = azx_create(card, pci, position_fix[dev], &chip)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
@@ -1424,6 +1456,9 @@
 	{ 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH6 */
 	{ 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH7 */
 	{ 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ESB2 */
+	{ 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ATI SB450 */
+	{ 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* VIA VT8251/VT8237A */
+	{ 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ALI 5461? */
 	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci, azx_ids);
@@ -1439,7 +1474,7 @@
 
 static int __init alsa_card_azx_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_azx_exit(void)
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 7c7b849..810cfd2 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -126,11 +126,11 @@
 struct hda_board_config {
 	const char *modelname;
 	int config;
-	unsigned short pci_vendor;
-	unsigned short pci_device;
+	unsigned short pci_subvendor;
+	unsigned short pci_subdevice;
 };
 
-int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config *tbl);
+int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_config *tbl);
 int snd_hda_add_new_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew);
 
 /*
@@ -158,4 +158,35 @@
 	struct work_struct work;
 };
 
+/*
+ * Helper for automatic ping configuration
+ */
+
+enum {
+	AUTO_PIN_MIC,
+	AUTO_PIN_FRONT_MIC,
+	AUTO_PIN_LINE,
+	AUTO_PIN_FRONT_LINE,
+	AUTO_PIN_CD,
+	AUTO_PIN_AUX,
+	AUTO_PIN_LAST
+};
+
+struct auto_pin_cfg {
+	int line_outs;
+	hda_nid_t line_out_pins[4]; /* sorted in the order of Front/Surr/CLFE/Side */
+	hda_nid_t hp_pin;
+	hda_nid_t input_pins[AUTO_PIN_LAST];
+	hda_nid_t dig_out_pin;
+	hda_nid_t dig_in_pin;
+};
+
+#define get_defcfg_connect(cfg) ((cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT)
+#define get_defcfg_association(cfg) ((cfg & AC_DEFCFG_DEF_ASSOC) >> AC_DEFCFG_ASSOC_SHIFT)
+#define get_defcfg_location(cfg) ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
+#define get_defcfg_sequence(cfg) (cfg & AC_DEFCFG_SEQUENCE)
+#define get_defcfg_device(cfg) ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
+
+int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *cfg);
+
 #endif /* __SOUND_HDA_LOCAL_H */
diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h
index cf6abce..a5de684 100644
--- a/sound/pci/hda/hda_patch.h
+++ b/sound/pci/hda/hda_patch.h
@@ -8,10 +8,13 @@
 extern struct hda_codec_preset snd_hda_preset_cmedia[];
 /* Analog Devices codecs */
 extern struct hda_codec_preset snd_hda_preset_analog[];
+/* SigmaTel codecs */
+extern struct hda_codec_preset snd_hda_preset_sigmatel[];
 
 static const struct hda_codec_preset *hda_preset_tables[] = {
 	snd_hda_preset_realtek,
 	snd_hda_preset_cmedia,
 	snd_hda_preset_analog,
+	snd_hda_preset_sigmatel,
 	NULL
 };
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index 4d5db7f..de1217b 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -68,21 +68,27 @@
 
 static void print_amp_vals(snd_info_buffer_t *buffer,
 			   struct hda_codec *codec, hda_nid_t nid,
-			   int dir, int stereo)
+			   int dir, int stereo, int indices)
 {
 	unsigned int val;
-	if (stereo) {
+	int i;
+
+	if (dir == HDA_OUTPUT)
+		dir = AC_AMP_GET_OUTPUT;
+	else
+		dir = AC_AMP_GET_INPUT;
+	for (i = 0; i < indices; i++) {
+		snd_iprintf(buffer, " [");
+		if (stereo) {
+			val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE,
+						 AC_AMP_GET_LEFT | dir | i);
+			snd_iprintf(buffer, "0x%02x ", val);
+		}
 		val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE,
-					  AC_AMP_GET_LEFT |
-					 (dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT :
-					  AC_AMP_GET_INPUT));
-		snd_iprintf(buffer, "0x%02x ", val);
+					 AC_AMP_GET_RIGHT | dir | i);
+		snd_iprintf(buffer, "0x%02x]", val);
 	}
-	val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE,
-				 AC_AMP_GET_RIGHT |
-				 (dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT :
-				  AC_AMP_GET_INPUT));
-	snd_iprintf(buffer, "0x%02x\n", val);
+	snd_iprintf(buffer, "\n");
 }
 
 static void print_pcm_caps(snd_info_buffer_t *buffer,
@@ -157,6 +163,7 @@
 static void print_pin_caps(snd_info_buffer_t *buffer,
 			   struct hda_codec *codec, hda_nid_t nid)
 {
+	static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" };
 	static char *jack_types[16] = {
 		"Line Out", "Speaker", "HP Out", "CD",
 		"SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
@@ -176,7 +183,8 @@
 		snd_iprintf(buffer, " HP");
 	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 at %s %s\n", caps,
+	snd_iprintf(buffer, "  Pin Default 0x%08x: [%s] %s at %s %s\n", caps,
+		    jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT],
 		    jack_types[(caps & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT],
 		    jack_locations[(caps >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3],
 		    get_jack_location(caps));
@@ -215,6 +223,9 @@
 		unsigned int wid_caps = snd_hda_param_read(codec, nid,
 							   AC_PAR_AUDIO_WIDGET_CAP);
 		unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+		int conn_len = 0; 
+		hda_nid_t conn[HDA_MAX_CONNECTIONS];
+
 		snd_iprintf(buffer, "Node 0x%02x [%s] wcaps 0x%x:", nid,
 			    get_wid_type_name(wid_type), wid_caps);
 		if (wid_caps & AC_WCAP_STEREO)
@@ -229,19 +240,23 @@
 			snd_iprintf(buffer, " Amp-Out");
 		snd_iprintf(buffer, "\n");
 
+		if (wid_caps & AC_WCAP_CONN_LIST)
+			conn_len = snd_hda_get_connections(codec, nid, conn,
+							   HDA_MAX_CONNECTIONS);
+
 		if (wid_caps & AC_WCAP_IN_AMP) {
 			snd_iprintf(buffer, "  Amp-In caps: ");
 			print_amp_caps(buffer, codec, nid, HDA_INPUT);
 			snd_iprintf(buffer, "  Amp-In vals: ");
 			print_amp_vals(buffer, codec, nid, HDA_INPUT,
-				       wid_caps & AC_WCAP_STEREO);
+				       wid_caps & AC_WCAP_STEREO, conn_len);
 		}
 		if (wid_caps & AC_WCAP_OUT_AMP) {
 			snd_iprintf(buffer, "  Amp-Out caps: ");
 			print_amp_caps(buffer, codec, nid, HDA_OUTPUT);
 			snd_iprintf(buffer, "  Amp-Out vals: ");
 			print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
-				       wid_caps & AC_WCAP_STEREO);
+				       wid_caps & AC_WCAP_STEREO, 1);
 		}
 
 		if (wid_type == AC_WID_PIN) {
@@ -265,14 +280,17 @@
 		}
 
 		if (wid_caps & AC_WCAP_CONN_LIST) {
-			hda_nid_t conn[HDA_MAX_CONNECTIONS];
-			int c, conn_len;
-			conn_len = snd_hda_get_connections(codec, nid, conn,
-							   HDA_MAX_CONNECTIONS);
+			int c, curr = -1;
+			if (conn_len > 1 && wid_type != AC_WID_AUD_MIX)
+				curr = snd_hda_codec_read(codec, nid, 0,
+					AC_VERB_GET_CONNECT_SEL, 0);
 			snd_iprintf(buffer, "  Connection: %d\n", conn_len);
 			snd_iprintf(buffer, "    ");
-			for (c = 0; c < conn_len; c++)
+			for (c = 0; c < conn_len; c++) {
 				snd_iprintf(buffer, " 0x%02x", conn[c]);
+				if (c == curr)
+					snd_iprintf(buffer, "*");
+			}
 			snd_iprintf(buffer, "\n");
 		}
 	}
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 75d2384..2fd05bb 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -1,5 +1,5 @@
 /*
- * HD audio interface patch for AD1986A
+ * HD audio interface patch for AD1981HD, AD1983, AD1986A
  *
  * Copyright (c) 2005 Takashi Iwai <tiwai@suse.de>
  *
@@ -27,13 +27,239 @@
 #include "hda_codec.h"
 #include "hda_local.h"
 
-struct ad1986a_spec {
+struct ad198x_spec {
 	struct semaphore amp_mutex;	/* PCM volume/mute control mutex */
 	struct hda_multi_out multiout;	/* playback */
+	hda_nid_t adc_nid;
+	const struct hda_input_mux *input_mux;
 	unsigned int cur_mux;		/* capture source */
+	unsigned int spdif_route;
+	snd_kcontrol_new_t *mixers;
+	const struct hda_verb *init_verbs;
 	struct hda_pcm pcm_rec[2];	/* PCM information */
 };
 
+/*
+ * input MUX handling (common part)
+ */
+static int ad198x_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct ad198x_spec *spec = codec->spec;
+
+	return snd_hda_input_mux_info(spec->input_mux, uinfo);
+}
+
+static int ad198x_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct ad198x_spec *spec = codec->spec;
+
+	ucontrol->value.enumerated.item[0] = spec->cur_mux;
+	return 0;
+}
+
+static int ad198x_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct ad198x_spec *spec = codec->spec;
+
+	return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
+				     spec->adc_nid, &spec->cur_mux);
+}
+
+/*
+ * initialization (common callbacks)
+ */
+static int ad198x_init(struct hda_codec *codec)
+{
+	struct ad198x_spec *spec = codec->spec;
+	snd_hda_sequence_write(codec, spec->init_verbs);
+	return 0;
+}
+
+static int ad198x_build_controls(struct hda_codec *codec)
+{
+	struct ad198x_spec *spec = codec->spec;
+	int err;
+
+	err = snd_hda_add_new_ctls(codec, spec->mixers);
+	if (err < 0)
+		return err;
+	if (spec->multiout.dig_out_nid)
+		err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
+	if (err < 0)
+		return err;
+	return 0;
+}
+
+/*
+ * Analog playback callbacks
+ */
+static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
+				    struct hda_codec *codec,
+				    snd_pcm_substream_t *substream)
+{
+	struct ad198x_spec *spec = codec->spec;
+	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+}
+
+static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+				       struct hda_codec *codec,
+				       unsigned int stream_tag,
+				       unsigned int format,
+				       snd_pcm_substream_t *substream)
+{
+	struct ad198x_spec *spec = codec->spec;
+	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
+						format, substream);
+}
+
+static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+				       struct hda_codec *codec,
+				       snd_pcm_substream_t *substream)
+{
+	struct ad198x_spec *spec = codec->spec;
+	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
+}
+
+/*
+ * Digital out
+ */
+static int ad198x_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
+					struct hda_codec *codec,
+					snd_pcm_substream_t *substream)
+{
+	struct ad198x_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
+}
+
+static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
+					 struct hda_codec *codec,
+					 snd_pcm_substream_t *substream)
+{
+	struct ad198x_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
+}
+
+/*
+ * Analog capture
+ */
+static int ad198x_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
+				      struct hda_codec *codec,
+				      unsigned int stream_tag,
+				      unsigned int format,
+				      snd_pcm_substream_t *substream)
+{
+	struct ad198x_spec *spec = codec->spec;
+	snd_hda_codec_setup_stream(codec, spec->adc_nid, stream_tag, 0, format);
+	return 0;
+}
+
+static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+				      struct hda_codec *codec,
+				      snd_pcm_substream_t *substream)
+{
+	struct ad198x_spec *spec = codec->spec;
+	snd_hda_codec_setup_stream(codec, spec->adc_nid, 0, 0, 0);
+	return 0;
+}
+
+
+/*
+ */
+static struct hda_pcm_stream ad198x_pcm_analog_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 6,
+	.nid = 0, /* fill later */
+	.ops = {
+		.open = ad198x_playback_pcm_open,
+		.prepare = ad198x_playback_pcm_prepare,
+		.cleanup = ad198x_playback_pcm_cleanup
+	},
+};
+
+static struct hda_pcm_stream ad198x_pcm_analog_capture = {
+	.substreams = 2,
+	.channels_min = 2,
+	.channels_max = 2,
+	.nid = 0, /* fill later */
+	.ops = {
+		.prepare = ad198x_capture_pcm_prepare,
+		.cleanup = ad198x_capture_pcm_cleanup
+	},
+};
+
+static struct hda_pcm_stream ad198x_pcm_digital_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	.nid = 0, /* fill later */
+	.ops = {
+		.open = ad198x_dig_playback_pcm_open,
+		.close = ad198x_dig_playback_pcm_close
+	},
+};
+
+static int ad198x_build_pcms(struct hda_codec *codec)
+{
+	struct ad198x_spec *spec = codec->spec;
+	struct hda_pcm *info = spec->pcm_rec;
+
+	codec->num_pcms = 1;
+	codec->pcm_info = info;
+
+	info->name = "AD198x Analog";
+	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_analog_playback;
+	info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->multiout.max_channels;
+	info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
+	info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad198x_pcm_analog_capture;
+	info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nid;
+
+	if (spec->multiout.dig_out_nid) {
+		info++;
+		codec->num_pcms++;
+		info->name = "AD198x Digital";
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
+		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
+	}
+
+	return 0;
+}
+
+static void ad198x_free(struct hda_codec *codec)
+{
+	kfree(codec->spec);
+}
+
+#ifdef CONFIG_PM
+static int ad198x_resume(struct hda_codec *codec)
+{
+	struct ad198x_spec *spec = codec->spec;
+
+	ad198x_init(codec);
+	snd_hda_resume_ctls(codec, spec->mixers);
+	snd_hda_resume_spdif_out(codec);
+	return 0;
+}
+#endif
+
+static struct hda_codec_ops ad198x_patch_ops = {
+	.build_controls = ad198x_build_controls,
+	.build_pcms = ad198x_build_pcms,
+	.init = ad198x_init,
+	.free = ad198x_free,
+#ifdef CONFIG_PM
+	.resume = ad198x_resume,
+#endif
+};
+
+
+/*
+ * AD1986A specific
+ */
+
 #define AD1986A_SPDIF_OUT	0x02
 #define AD1986A_FRONT_DAC	0x03
 #define AD1986A_SURR_DAC	0x04
@@ -68,7 +294,7 @@
 static int ad1986a_pcm_amp_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct ad1986a_spec *ad = codec->spec;
+	struct ad198x_spec *ad = codec->spec;
 
 	down(&ad->amp_mutex);
 	snd_hda_mixer_amp_volume_get(kcontrol, ucontrol);
@@ -79,7 +305,7 @@
 static int ad1986a_pcm_amp_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct ad1986a_spec *ad = codec->spec;
+	struct ad198x_spec *ad = codec->spec;
 	int i, change = 0;
 
 	down(&ad->amp_mutex);
@@ -92,12 +318,12 @@
 	return change;
 }
 
-#define ad1986a_pcm_amp_sw_info		snd_hda_mixer_amp_volume_info
+#define ad1986a_pcm_amp_sw_info		snd_hda_mixer_amp_switch_info
 
 static int ad1986a_pcm_amp_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct ad1986a_spec *ad = codec->spec;
+	struct ad198x_spec *ad = codec->spec;
 
 	down(&ad->amp_mutex);
 	snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
@@ -108,7 +334,7 @@
 static int ad1986a_pcm_amp_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct ad1986a_spec *ad = codec->spec;
+	struct ad198x_spec *ad = codec->spec;
 	int i, change = 0;
 
 	down(&ad->amp_mutex);
@@ -122,32 +348,6 @@
 }
 
 /*
- * input MUX handling
- */
-static int ad1986a_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
-{
-	return snd_hda_input_mux_info(&ad1986a_capture_source, uinfo);
-}
-
-static int ad1986a_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct ad1986a_spec *spec = codec->spec;
-
-	ucontrol->value.enumerated.item[0] = spec->cur_mux;
-	return 0;
-}
-
-static int ad1986a_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct ad1986a_spec *spec = codec->spec;
-
-	return snd_hda_input_mux_put(codec, &ad1986a_capture_source, ucontrol,
-				     AD1986A_ADC, &spec->cur_mux);
-}
-
-/*
  * mixers
  */
 static snd_kcontrol_new_t ad1986a_mixers[] = {
@@ -194,9 +394,9 @@
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Capture Source",
-		.info = ad1986a_mux_enum_info,
-		.get = ad1986a_mux_enum_get,
-		.put = ad1986a_mux_enum_put,
+		.info = ad198x_mux_enum_info,
+		.get = ad198x_mux_enum_get,
+		.put = ad198x_mux_enum_put,
 	},
 	HDA_CODEC_MUTE("Stereo Downmix Switch", 0x09, 0x0, HDA_OUTPUT),
 	{ } /* end */
@@ -241,183 +441,29 @@
 	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
 	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	/* HP Pin */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	/* Front, Surround, CLFE Pins */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	/* Mono Pin */
+	{0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	/* Mic Pin */
+	{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	/* Line, Aux, CD, Beep-In Pin */
+	{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	{0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	{0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	{0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
 	{ } /* end */
 };
 
 
-static int ad1986a_init(struct hda_codec *codec)
-{
-	snd_hda_sequence_write(codec, ad1986a_init_verbs);
-	return 0;
-}
-
-static int ad1986a_build_controls(struct hda_codec *codec)
-{
-	int err;
-
-	err = snd_hda_add_new_ctls(codec, ad1986a_mixers);
-	if (err < 0)
-		return err;
-	err = snd_hda_create_spdif_out_ctls(codec, AD1986A_SPDIF_OUT);
-	if (err < 0)
-		return err;
-	return 0;
-}
-
-/*
- * Analog playback callbacks
- */
-static int ad1986a_playback_pcm_open(struct hda_pcm_stream *hinfo,
-				     struct hda_codec *codec,
-				     snd_pcm_substream_t *substream)
-{
-	struct ad1986a_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
-}
-
-static int ad1986a_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
-					struct hda_codec *codec,
-					unsigned int stream_tag,
-					unsigned int format,
-					snd_pcm_substream_t *substream)
-{
-	struct ad1986a_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
-						format, substream);
-}
-
-static int ad1986a_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
-					struct hda_codec *codec,
-					snd_pcm_substream_t *substream)
-{
-	struct ad1986a_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
-}
-
-/*
- * Digital out
- */
-static int ad1986a_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
-					 struct hda_codec *codec,
-					 snd_pcm_substream_t *substream)
-{
-	struct ad1986a_spec *spec = codec->spec;
-	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
-}
-
-static int ad1986a_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
-					  struct hda_codec *codec,
-					  snd_pcm_substream_t *substream)
-{
-	struct ad1986a_spec *spec = codec->spec;
-	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
-}
-
-/*
- * Analog capture
- */
-static int ad1986a_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
-				       struct hda_codec *codec,
-				       unsigned int stream_tag,
-				       unsigned int format,
-				       snd_pcm_substream_t *substream)
-{
-	snd_hda_codec_setup_stream(codec, AD1986A_ADC, stream_tag, 0, format);
-	return 0;
-}
-
-static int ad1986a_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
-				       struct hda_codec *codec,
-				       snd_pcm_substream_t *substream)
-{
-	snd_hda_codec_setup_stream(codec, AD1986A_ADC, 0, 0, 0);
-	return 0;
-}
-
-
-/*
- */
-static struct hda_pcm_stream ad1986a_pcm_analog_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 6,
-	.nid = AD1986A_FRONT_DAC, /* NID to query formats and rates */
-	.ops = {
-		.open = ad1986a_playback_pcm_open,
-		.prepare = ad1986a_playback_pcm_prepare,
-		.cleanup = ad1986a_playback_pcm_cleanup
-	},
-};
-
-static struct hda_pcm_stream ad1986a_pcm_analog_capture = {
-	.substreams = 2,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = AD1986A_ADC, /* NID to query formats and rates */
-	.ops = {
-		.prepare = ad1986a_capture_pcm_prepare,
-		.cleanup = ad1986a_capture_pcm_cleanup
-	},
-};
-
-static struct hda_pcm_stream ad1986a_pcm_digital_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = AD1986A_SPDIF_OUT, 
-	.ops = {
-		.open = ad1986a_dig_playback_pcm_open,
-		.close = ad1986a_dig_playback_pcm_close
-	},
-};
-
-static int ad1986a_build_pcms(struct hda_codec *codec)
-{
-	struct ad1986a_spec *spec = codec->spec;
-	struct hda_pcm *info = spec->pcm_rec;
-
-	codec->num_pcms = 2;
-	codec->pcm_info = info;
-
-	info->name = "AD1986A Analog";
-	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad1986a_pcm_analog_playback;
-	info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1986a_pcm_analog_capture;
-	info++;
-
-	info->name = "AD1986A Digital";
-	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad1986a_pcm_digital_playback;
-
-	return 0;
-}
-
-static void ad1986a_free(struct hda_codec *codec)
-{
-	kfree(codec->spec);
-}
-
-#ifdef CONFIG_PM
-static int ad1986a_resume(struct hda_codec *codec)
-{
-	ad1986a_init(codec);
-	snd_hda_resume_ctls(codec, ad1986a_mixers);
-	snd_hda_resume_spdif_out(codec);
-	return 0;
-}
-#endif
-
-static struct hda_codec_ops ad1986a_patch_ops = {
-	.build_controls = ad1986a_build_controls,
-	.build_pcms = ad1986a_build_pcms,
-	.init = ad1986a_init,
-	.free = ad1986a_free,
-#ifdef CONFIG_PM
-	.resume = ad1986a_resume,
-#endif
-};
-
 static int patch_ad1986a(struct hda_codec *codec)
 {
-	struct ad1986a_spec *spec;
+	struct ad198x_spec *spec;
 
 	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
@@ -430,16 +476,323 @@
 	spec->multiout.num_dacs = ARRAY_SIZE(ad1986a_dac_nids);
 	spec->multiout.dac_nids = ad1986a_dac_nids;
 	spec->multiout.dig_out_nid = AD1986A_SPDIF_OUT;
+	spec->adc_nid = AD1986A_ADC;
+	spec->input_mux = &ad1986a_capture_source;
+	spec->mixers = ad1986a_mixers;
+	spec->init_verbs = ad1986a_init_verbs;
 
-	codec->patch_ops = ad1986a_patch_ops;
+	codec->patch_ops = ad198x_patch_ops;
 
 	return 0;
 }
 
 /*
+ * AD1983 specific
+ */
+
+#define AD1983_SPDIF_OUT	0x02
+#define AD1983_DAC		0x03
+#define AD1983_ADC		0x04
+
+static hda_nid_t ad1983_dac_nids[1] = { AD1983_DAC };
+
+static struct hda_input_mux ad1983_capture_source = {
+	.num_items = 4,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Line", 0x1 },
+		{ "Mix", 0x2 },
+		{ "Mix Mono", 0x3 },
+	},
+};
+
+/*
+ * SPDIF playback route
+ */
+static int ad1983_spdif_route_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	static char *texts[] = { "PCM", "ADC" };
+
+	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 ad1983_spdif_route_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct ad198x_spec *spec = codec->spec;
+
+	ucontrol->value.enumerated.item[0] = spec->spdif_route;
+	return 0;
+}
+
+static int ad1983_spdif_route_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct ad198x_spec *spec = codec->spec;
+
+	if (spec->spdif_route != ucontrol->value.enumerated.item[0]) {
+		spec->spdif_route = ucontrol->value.enumerated.item[0];
+		snd_hda_codec_write(codec, spec->multiout.dig_out_nid, 0,
+				    AC_VERB_SET_CONNECT_SEL, spec->spdif_route);
+		return 1;
+	}
+	return 0;
+}
+
+static snd_kcontrol_new_t ad1983_mixers[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 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("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("PC Speaker Playback Volume", 0x10, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x10, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Mic Boost", 0x0c, 0x0, HDA_OUTPUT),
+	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,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "IEC958 Playback Route",
+		.info = ad1983_spdif_route_info,
+		.get = ad1983_spdif_route_get,
+		.put = ad1983_spdif_route_put,
+	},
+	{ } /* end */
+};
+
+static struct hda_verb ad1983_init_verbs[] = {
+	/* Front, HP, Mono; mute as default */
+	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	/* Beep, PCM, Mic, Line-In: mute */
+	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	/* Front, HP selectors; from Mix */
+	{0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
+	/* Mono selector; from Mix */
+	{0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
+	/* Mic selector; Mic */
+	{0x0c, AC_VERB_SET_CONNECT_SEL, 0x0},
+	/* Line-in selector: Line-in */
+	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x0},
+	/* Mic boost: 0dB */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	/* Record selector: mic */
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	/* SPDIF route: PCM */
+	{0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
+	/* Front Pin */
+	{0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	/* HP Pin */
+	{0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	/* Mono Pin */
+	{0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	/* Mic Pin */
+	{0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	/* Line Pin */
+	{0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	{ } /* end */
+};
+
+static int patch_ad1983(struct hda_codec *codec)
+{
+	struct ad198x_spec *spec;
+
+	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	init_MUTEX(&spec->amp_mutex);
+	codec->spec = spec;
+
+	spec->multiout.max_channels = 2;
+	spec->multiout.num_dacs = ARRAY_SIZE(ad1983_dac_nids);
+	spec->multiout.dac_nids = ad1983_dac_nids;
+	spec->multiout.dig_out_nid = AD1983_SPDIF_OUT;
+	spec->adc_nid = AD1983_ADC;
+	spec->input_mux = &ad1983_capture_source;
+	spec->mixers = ad1983_mixers;
+	spec->init_verbs = ad1983_init_verbs;
+	spec->spdif_route = 0;
+
+	codec->patch_ops = ad198x_patch_ops;
+
+	return 0;
+}
+
+
+/*
+ * AD1981 HD specific
+ */
+
+#define AD1981_SPDIF_OUT	0x02
+#define AD1981_DAC		0x03
+#define AD1981_ADC		0x04
+
+static hda_nid_t ad1981_dac_nids[1] = { AD1981_DAC };
+
+/* 0x0c, 0x09, 0x0e, 0x0f, 0x19, 0x05, 0x18, 0x17 */
+static struct hda_input_mux ad1981_capture_source = {
+	.num_items = 7,
+	.items = {
+		{ "Front Mic", 0x0 },
+		{ "Line", 0x1 },
+		{ "Mix", 0x2 },
+		{ "Mix Mono", 0x3 },
+		{ "CD", 0x4 },
+		{ "Mic", 0x6 },
+		{ "Aux", 0x7 },
+	},
+};
+
+static snd_kcontrol_new_t ad1981_mixers[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x05, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x05, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x06, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x06, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x07, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x07, 1, 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("Front Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x13, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x13, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Aux Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Aux Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x1c, 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_MONO("PC Speaker Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("PC Speaker Playback Switch", 0x0d, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Front Mic Boost", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Boost", 0x18, 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 = "IEC958 Playback Route",
+		.info = ad1983_spdif_route_info,
+		.get = ad1983_spdif_route_get,
+		.put = ad1983_spdif_route_put,
+	},
+	{ } /* end */
+};
+
+static struct hda_verb ad1981_init_verbs[] = {
+	/* Front, HP, Mono; mute as default */
+	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	{0x06, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	/* Beep, PCM, Front Mic, Line, Rear Mic, Aux, CD-In: mute */
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	{0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	/* Front, HP selectors; from Mix */
+	{0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x06, AC_VERB_SET_CONNECT_SEL, 0x01},
+	/* Mono selector; from Mix */
+	{0x0b, AC_VERB_SET_CONNECT_SEL, 0x03},
+	/* Mic Mixer; select Front Mic */
+	{0x1e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	{0x1f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	/* Mic boost: 0dB */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	/* Record selector: Front mic */
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x0},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	/* SPDIF route: PCM */
+	{0x02, AC_VERB_SET_CONNECT_SEL, 0x0},
+	/* Front Pin */
+	{0x05, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	/* HP Pin */
+	{0x06, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	/* Mono Pin */
+	{0x07, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	/* Front & Rear Mic Pins */
+	{0x08, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	/* Line Pin */
+	{0x09, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	/* Digital Beep */
+	{0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* Line-Out as Input: disabled */
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	{ } /* end */
+};
+
+static int patch_ad1981(struct hda_codec *codec)
+{
+	struct ad198x_spec *spec;
+
+	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	init_MUTEX(&spec->amp_mutex);
+	codec->spec = spec;
+
+	spec->multiout.max_channels = 2;
+	spec->multiout.num_dacs = ARRAY_SIZE(ad1981_dac_nids);
+	spec->multiout.dac_nids = ad1981_dac_nids;
+	spec->multiout.dig_out_nid = AD1981_SPDIF_OUT;
+	spec->adc_nid = AD1981_ADC;
+	spec->input_mux = &ad1981_capture_source;
+	spec->mixers = ad1981_mixers;
+	spec->init_verbs = ad1981_init_verbs;
+	spec->spdif_route = 0;
+
+	codec->patch_ops = ad198x_patch_ops;
+
+	return 0;
+}
+
+
+/*
  * patch entries
  */
 struct hda_codec_preset snd_hda_preset_analog[] = {
+	{ .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 },
+	{ .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 },
 	{ .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a },
 	{} /* terminator */
 };
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index b7cc8e4..2d6e3e3 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -29,6 +29,7 @@
 #include <sound/core.h>
 #include "hda_codec.h"
 #include "hda_local.h"
+#define NUM_PINS	11
 
 
 /* board config type */
@@ -38,6 +39,7 @@
 	CMI_FULL,	/* back 6-jack + front-panel 2-jack */
 	CMI_FULL_DIG,	/* back 6-jack + front-panel 2-jack + digital I/O */
 	CMI_ALLOUT,	/* back 5-jack + front-panel 2-jack + digital out */
+	CMI_AUTO,	/* let driver guess it */
 };
 
 struct cmi_spec {
@@ -48,6 +50,8 @@
 
 	/* playback */
 	struct hda_multi_out multiout;
+	hda_nid_t dac_nids[4];		/* NID for each DAC */
+	int num_dacs;
 
 	/* capture */
 	hda_nid_t *adc_nids;
@@ -63,8 +67,30 @@
 	const struct cmi_channel_mode *channel_modes;
 
 	struct hda_pcm pcm_rec[2];	/* PCM information */
+
+	/* pin deafault configuration */
+	hda_nid_t pin_nid[NUM_PINS];
+	unsigned int def_conf[NUM_PINS];
+	unsigned int pin_def_confs;
+
+	/* multichannel pins */
+	hda_nid_t multich_pin[4];	/* max 8-channel */
+	struct hda_verb multi_init[9];	/* 2 verbs for each pin + terminator */
 };
 
+/* amp values */
+#define AMP_IN_MUTE(idx)	(0x7080 | ((idx)<<8))
+#define AMP_IN_UNMUTE(idx)	(0x7000 | ((idx)<<8))
+#define AMP_OUT_MUTE	0xb080
+#define AMP_OUT_UNMUTE	0xb000
+#define AMP_OUT_ZERO	0xb000
+/* pinctl values */
+#define PIN_IN		0x20
+#define PIN_VREF80	0x24
+#define PIN_VREF50	0x21
+#define PIN_OUT		0x40
+#define PIN_HP		0xc0
+
 /*
  * input MUX
  */
@@ -102,9 +128,9 @@
 /* 3-stack / 2 channel */
 static struct hda_verb cmi9880_ch2_init[] = {
 	/* set line-in PIN for input */
-	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
 	/* set mic PIN for input, also enable vref */
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
 	/* route front PCM (DAC1) to HP */
 	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
 	{}
@@ -113,9 +139,9 @@
 /* 3-stack / 6 channel */
 static struct hda_verb cmi9880_ch6_init[] = {
 	/* set line-in PIN for output */
-	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 	/* set mic PIN for output */
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 	/* route front PCM (DAC1) to HP */
 	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
 	{}
@@ -124,9 +150,9 @@
 /* 3-stack+front / 8 channel */
 static struct hda_verb cmi9880_ch8_init[] = {
 	/* set line-in PIN for output */
-	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 	/* set mic PIN for output */
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
 	/* route rear-surround PCM (DAC4) to HP */
 	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x03 },
 	{}
@@ -269,25 +295,27 @@
  */
 static struct hda_verb cmi9880_basic_init[] = {
 	/* port-D for line out (rear panel) */
-	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
 	/* port-E for HP out (front panel) */
-	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
 	/* route front PCM to HP */
 	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
 	/* port-A for surround (rear panel) */
-	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
 	/* port-G for CLFE (rear panel) */
-	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+	{ 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 },
 	/* port-H for side (rear panel) */
-	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+	{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 },
 	/* port-C for line-in (rear panel) */
-	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
 	/* port-B for mic-in (rear panel) with vref */
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
 	/* port-F for mic-in (front panel) with vref */
-	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
 	/* CD-in */
-	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
 	/* route front mic to ADC1/2 */
 	{ 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
 	{ 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
@@ -296,23 +324,27 @@
 
 static struct hda_verb cmi9880_allout_init[] = {
 	/* port-D for line out (rear panel) */
-	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
 	/* port-E for HP out (front panel) */
-	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
 	/* route front PCM to HP */
 	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
 	/* port-A for side (rear panel) */
-	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
 	/* port-G for CLFE (rear panel) */
-	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+	{ 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 },
+	/* port-H for side (rear panel) */
+	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
+	{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 },
 	/* port-C for surround (rear panel) */
-	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
 	/* port-B for mic-in (rear panel) with vref */
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
 	/* port-F for mic-in (front panel) with vref */
-	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
 	/* CD-in */
-	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
 	/* route front mic to ADC1/2 */
 	{ 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
 	{ 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
@@ -347,6 +379,81 @@
 	return 0;
 }
 
+/* fill in the multi_dac_nids table, which will decide
+   which audio widget to use for each channel */
+static int cmi9880_fill_multi_dac_nids(struct hda_codec *codec, const struct auto_pin_cfg *cfg)
+{
+	struct cmi_spec *spec = codec->spec;
+	hda_nid_t nid;
+	int assigned[4];
+	int i, j;
+
+	/* clear the table, only one c-media dac assumed here */
+	memset(spec->dac_nids, 0, sizeof(spec->dac_nids));
+	memset(assigned, 0, sizeof(assigned));
+	/* check the pins we found */
+	for (i = 0; i < cfg->line_outs; i++) {
+		nid = cfg->line_out_pins[i];
+		/* nid 0x0b~0x0e is hardwired to audio widget 0x3~0x6 */
+		if (nid >= 0x0b && nid <= 0x0e) {
+			spec->dac_nids[i] = (nid - 0x0b) + 0x03;
+			assigned[nid - 0x0b] = 1;
+		}
+	}
+	/* left pin can be connect to any audio widget */
+	for (i = 0; i < cfg->line_outs; i++) {
+		nid = cfg->line_out_pins[i];
+		if (nid <= 0x0e)
+			continue;
+		/* search for an empty channel */
+		for (j = 0; j < cfg->line_outs; j++) {
+			if (! assigned[j]) {
+				spec->dac_nids[i] = i + 0x03;
+				assigned[j] = 1;
+				break;
+			}
+		}
+	}
+	spec->num_dacs = cfg->line_outs;
+	return 0;
+}
+
+/* create multi_init table, which is used for multichannel initialization */
+static int cmi9880_fill_multi_init(struct hda_codec *codec, const struct auto_pin_cfg *cfg)
+{
+	struct cmi_spec *spec = codec->spec;
+	hda_nid_t nid;
+	int i, j, k, len;
+
+	/* clear the table, only one c-media dac assumed here */
+	memset(spec->multi_init, 0, sizeof(spec->multi_init));
+	for (j = 0, i = 0; i < cfg->line_outs; i++) {
+		hda_nid_t conn[4];
+		nid = cfg->line_out_pins[i];
+		/* set as output */
+		spec->multi_init[j].nid = nid;
+		spec->multi_init[j].verb = AC_VERB_SET_PIN_WIDGET_CONTROL;
+		spec->multi_init[j].param = PIN_OUT;
+		j++;
+		if (nid > 0x0e) {
+			/* set connection */
+			spec->multi_init[j].nid = nid;
+			spec->multi_init[j].verb = AC_VERB_SET_CONNECT_SEL;
+			spec->multi_init[j].param = 0;
+			/* find the index in connect list */
+			len = snd_hda_get_connections(codec, nid, conn, 4);
+			for (k = 0; k < len; k++)
+				if (conn[k] == spec->dac_nids[i]) {
+					spec->multi_init[j].param = j;
+					break;
+				}
+			j++;
+			break;
+		}
+	}
+	return 0;
+}
+
 static int cmi9880_init(struct hda_codec *codec)
 {
 	struct cmi_spec *spec = codec->spec;
@@ -354,6 +461,8 @@
 		snd_hda_sequence_write(codec, cmi9880_allout_init);
 	else
 		snd_hda_sequence_write(codec, cmi9880_basic_init);
+	if (spec->board_config == CMI_AUTO)
+		snd_hda_sequence_write(codec, spec->multi_init);
 	return 0;
 }
 
@@ -540,6 +649,7 @@
 	{ .modelname = "full", .config = CMI_FULL },
 	{ .modelname = "full_dig", .config = CMI_FULL_DIG },
 	{ .modelname = "allout", .config = CMI_ALLOUT },
+	{ .modelname = "auto", .config = CMI_AUTO },
 	{} /* terminator */
 };
 
@@ -564,10 +674,14 @@
 	codec->spec = spec;
 	spec->board_config = snd_hda_check_board_config(codec, cmi9880_cfg_tbl);
 	if (spec->board_config < 0) {
-		snd_printd(KERN_INFO "hda_codec: Unknown model for CMI9880\n");
-		spec->board_config = CMI_FULL_DIG; /* try everything */
+		snd_printdd(KERN_INFO "hda_codec: Unknown model for CMI9880\n");
+		spec->board_config = CMI_AUTO; /* try everything */
 	}
 
+	/* copy default DAC NIDs */
+	memcpy(spec->dac_nids, cmi9880_dac_nids, sizeof(spec->dac_nids));
+	spec->num_dacs = 4;
+
 	switch (spec->board_config) {
 	case CMI_MINIMAL:
 	case CMI_MIN_FP:
@@ -599,10 +713,58 @@
 		spec->input_mux = &cmi9880_no_line_mux;
 		spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
 		break;
+	case CMI_AUTO:
+		{
+		unsigned int port_e, port_f, port_g, port_h;
+		unsigned int port_spdifi, port_spdifo;
+		struct auto_pin_cfg cfg;
+
+		/* collect pin default configuration */
+		port_e = snd_hda_codec_read(codec, 0x0f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+		port_f = snd_hda_codec_read(codec, 0x10, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+		spec->front_panel = 1;
+		if (get_defcfg_connect(port_e) == AC_JACK_PORT_NONE ||
+		    get_defcfg_connect(port_f) == AC_JACK_PORT_NONE) {
+			port_g = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+			port_h = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+			spec->surr_switch = 1;
+			/* no front panel */
+			if (get_defcfg_connect(port_g) == AC_JACK_PORT_NONE ||
+			    get_defcfg_connect(port_h) == AC_JACK_PORT_NONE) {
+				/* no optional rear panel */
+				spec->board_config = CMI_MINIMAL;
+				spec->front_panel = 0;
+				spec->num_ch_modes = 2;
+			} else {
+				spec->board_config = CMI_MIN_FP;
+				spec->num_ch_modes = 3;
+			}
+			spec->channel_modes = cmi9880_channel_modes;
+			spec->input_mux = &cmi9880_basic_mux;
+			spec->multiout.max_channels = cmi9880_channel_modes[0].channels;
+		} else {
+			spec->input_mux = &cmi9880_basic_mux;
+			port_spdifi = snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+			port_spdifo = snd_hda_codec_read(codec, 0x12, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+			if (get_defcfg_connect(port_spdifo) != AC_JACK_PORT_NONE)
+				spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
+			if (get_defcfg_connect(port_spdifi) != AC_JACK_PORT_NONE)
+				spec->dig_in_nid = CMI_DIG_IN_NID;
+			spec->multiout.max_channels = 8;
+		}
+		snd_hda_parse_pin_def_config(codec, &cfg);
+		if (cfg.line_outs) {
+			spec->multiout.max_channels = cfg.line_outs * 2;
+			cmi9880_fill_multi_dac_nids(codec, &cfg);
+			cmi9880_fill_multi_init(codec, &cfg);
+		} else
+			snd_printd("patch_cmedia: cannot detect association in defcfg\n");
+		break;
+		}
 	}
 
-	spec->multiout.num_dacs = 4;
-	spec->multiout.dac_nids = cmi9880_dac_nids;
+	spec->multiout.num_dacs = spec->num_dacs;
+	spec->multiout.dac_nids = spec->dac_nids;
 
 	spec->adc_nids = cmi9880_adc_nids;
 
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 17c5062..bab8984 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -33,38 +33,73 @@
 
 /* ALC880 board config type */
 enum {
-	ALC880_MINIMAL,
 	ALC880_3ST,
 	ALC880_3ST_DIG,
 	ALC880_5ST,
 	ALC880_5ST_DIG,
 	ALC880_W810,
+	ALC880_Z71V,
+	ALC880_AUTO,
+	ALC880_6ST_DIG,
+	ALC880_F1734,
+	ALC880_ASUS,
+	ALC880_ASUS_DIG,
+	ALC880_ASUS_W1V,
+	ALC880_UNIWILL_DIG,
+#ifdef CONFIG_SND_DEBUG
+	ALC880_TEST,
+#endif
+	ALC880_MODEL_LAST /* last tag */
 };
 
+/* ALC260 models */
+enum {
+	ALC260_BASIC,
+	ALC260_HP,
+	ALC260_MODEL_LAST /* last tag */
+};
+
+/* amp values */
+#define AMP_IN_MUTE(idx)	(0x7080 | ((idx)<<8))
+#define AMP_IN_UNMUTE(idx)	(0x7000 | ((idx)<<8))
+#define AMP_OUT_MUTE	0xb080
+#define AMP_OUT_UNMUTE	0xb000
+#define AMP_OUT_ZERO	0xb000
+/* pinctl values */
+#define PIN_IN		0x20
+#define PIN_VREF80	0x24
+#define PIN_VREF50	0x21
+#define PIN_OUT		0x40
+#define PIN_HP		0xc0
+
 struct alc_spec {
 	/* codec parameterization */
-	unsigned int front_panel: 1;
-
-	snd_kcontrol_new_t* mixers[2];
+	snd_kcontrol_new_t *mixers[3];	/* mixer arrays */
 	unsigned int num_mixers;
 
-	struct hda_verb *init_verbs;
+	const struct hda_verb *init_verbs[3];	/* initialization verbs
+						 * don't forget NULL termination!
+						 */
+	unsigned int num_init_verbs;
 
-	char* stream_name_analog;
+	char *stream_name_analog;	/* analog PCM stream */
 	struct hda_pcm_stream *stream_analog_playback;
 	struct hda_pcm_stream *stream_analog_capture;
 
-	char* stream_name_digital;
+	char *stream_name_digital;	/* digital PCM stream */ 
 	struct hda_pcm_stream *stream_digital_playback;
 	struct hda_pcm_stream *stream_digital_capture;
 
 	/* playback */
-	struct hda_multi_out multiout;
+	struct hda_multi_out multiout;	/* playback set-up
+					 * max_channels, dacs must be set
+					 * dig_out_nid and hp_nid are optional
+					 */
 
 	/* capture */
 	unsigned int num_adc_nids;
 	hda_nid_t *adc_nids;
-	hda_nid_t dig_in_nid;
+	hda_nid_t dig_in_nid;		/* digital-in NID; optional */
 
 	/* capture source */
 	const struct hda_input_mux *input_mux;
@@ -75,61 +110,17 @@
 	int num_channel_mode;
 
 	/* PCM information */
-	struct hda_pcm pcm_rec[2];
+	struct hda_pcm pcm_rec[2];	/* used in alc_build_pcms() */
+
+	struct semaphore bind_mutex;	/* for bound controls */
+
+	/* dynamic controls, init_verbs and input_mux */
+	struct auto_pin_cfg autocfg;
+	unsigned int num_kctl_alloc, num_kctl_used;
+	snd_kcontrol_new_t *kctl_alloc;
+	struct hda_input_mux private_imux;
 };
 
-/* DAC/ADC assignment */
-
-static hda_nid_t alc880_dac_nids[4] = {
-	/* front, rear, clfe, rear_surr */
-	0x02, 0x05, 0x04, 0x03
-};
-
-static hda_nid_t alc880_w810_dac_nids[3] = {
-	/* front, rear/surround, clfe */
-	0x02, 0x03, 0x04
-};
-
-static hda_nid_t alc880_adc_nids[3] = {
-	/* ADC0-2 */
-	0x07, 0x08, 0x09,
-};
-
-#define ALC880_DIGOUT_NID	0x06
-#define ALC880_DIGIN_NID	0x0a
-
-static hda_nid_t alc260_dac_nids[1] = {
-	/* front */
-	0x02,
-};
-
-static hda_nid_t alc260_adc_nids[2] = {
-	/* ADC0-1 */
-	0x04, 0x05,
-};
-
-#define ALC260_DIGOUT_NID	0x03
-#define ALC260_DIGIN_NID	0x06
-
-static struct hda_input_mux alc880_capture_source = {
-	.num_items = 4,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Front Mic", 0x3 },
-		{ "Line", 0x2 },
-		{ "CD", 0x4 },
-	},
-};
-
-static struct hda_input_mux alc260_capture_source = {
-	.num_items = 4,
-	.items = {
-		{ "Mic", 0x0 },
-		{ "Front Mic", 0x1 },
-		{ "Line", 0x2 },
-		{ "CD", 0x4 },
-	},
-};
 
 /*
  * input MUX handling
@@ -160,6 +151,7 @@
 				     spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
 }
 
+
 /*
  * channel mode setting
  */
@@ -168,135 +160,18 @@
 	const struct hda_verb *sequence;
 };
 
-
-/*
- * channel source setting (2/6 channel selection for 3-stack)
- */
-
-/*
- * set the path ways for 2 channel output
- * need to set the codec line out and mic 1 pin widgets to inputs
- */
-static struct hda_verb alc880_threestack_ch2_init[] = {
-	/* set pin widget 1Ah (line in) for input */
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-	/* set pin widget 18h (mic1) for input, for mic also enable the vref */
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-	/* mute the output for Line In PW */
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
-	/* mute for Mic1 PW */
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
-	{ } /* end */
-};
-
-/*
- * 6ch mode
- * need to set the codec line out and mic 1 pin widgets to outputs
- */
-static struct hda_verb alc880_threestack_ch6_init[] = {
-	/* set pin widget 1Ah (line in) for output */
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	/* set pin widget 18h (mic1) for output */
-	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	/* unmute the output for Line In PW */
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
-	/* unmute for Mic1 PW */
-	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
-	/* for rear channel output using Line In 1
-	 * set select widget connection (nid = 0x12) - to summer node
-	 * for rear NID = 0x0f...offset 3 in connection list
-	 */
-	{ 0x12, AC_VERB_SET_CONNECT_SEL, 0x3 },
-	/* for Mic1 - retask for center/lfe */
-	/* set select widget connection (nid = 0x10) - to summer node for
-	 * front CLFE NID = 0x0e...offset 2 in connection list
-	 */
-	{ 0x10, AC_VERB_SET_CONNECT_SEL, 0x2 },
-	{ } /* end */
-};
-
-static struct alc_channel_mode alc880_threestack_modes[2] = {
-	{ 2, alc880_threestack_ch2_init },
-	{ 6, alc880_threestack_ch6_init },
-};
-
-
-/*
- * channel source setting (6/8 channel selection for 5-stack)
- */
-
-/* set the path ways for 6 channel output
- * need to set the codec line out and mic 1 pin widgets to inputs
- */
-static struct hda_verb alc880_fivestack_ch6_init[] = {
-	/* set pin widget 1Ah (line in) for input */
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
-	/* mute the output for Line In PW */
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
-	{ } /* end */
-};
-
-/* need to set the codec line out and mic 1 pin widgets to outputs */
-static struct hda_verb alc880_fivestack_ch8_init[] = {
-	/* set pin widget 1Ah (line in) for output */
-	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-	/* unmute the output for Line In PW */
-	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
-	/* output for surround channel output using Line In 1 */
-	/* set select widget connection (nid = 0x12) - to summer node
-	 * for surr_rear NID = 0x0d...offset 1 in connection list
-	 */
-	{ 0x12, AC_VERB_SET_CONNECT_SEL, 0x1 },
-	{ } /* end */
-};
-
-static struct alc_channel_mode alc880_fivestack_modes[2] = {
-	{ 6, alc880_fivestack_ch6_init },
-	{ 8, alc880_fivestack_ch8_init },
-};
-
-/*
- * channel source setting for W810 system
- *
- * W810 has rear IO for:
- * Front (DAC 02)
- * Surround (DAC 03)
- * Center/LFE (DAC 04)
- * Digital out (06)
- *
- * The system also has a pair of internal speakers, and a headphone jack.
- * These are both connected to Line2 on the codec, hence to DAC 02.
- * 
- * There is a variable resistor to control the speaker or headphone
- * volume. This is a hardware-only device without a software API.
- *
- * Plugging headphones in will disable the internal speakers. This is
- * implemented in hardware, not via the driver using jack sense. In
- * a similar fashion, plugging into the rear socket marked "front" will
- * disable both the speakers and headphones.
- *
- * For input, there's a microphone jack, and an "audio in" jack.
- * These may not do anything useful with this driver yet, because I
- * haven't setup any initialization verbs for these yet...
- */
-
-static struct alc_channel_mode alc880_w810_modes[1] = {
-	{ 6, NULL }
-};
-
-/*
- */
 static int alc880_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct alc_spec *spec = codec->spec;
+	int items = kcontrol->private_value ? (int)kcontrol->private_value : 2;
 
 	snd_assert(spec->channel_mode, return -ENXIO);
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
-	uinfo->value.enumerated.items = 2;
-	if (uinfo->value.enumerated.item >= 2)
-		uinfo->value.enumerated.item = 1;
+	uinfo->value.enumerated.items = items;
+	if (uinfo->value.enumerated.item >= items)
+		uinfo->value.enumerated.item = items - 1;
 	sprintf(uinfo->value.enumerated.name, "%dch",
 		spec->channel_mode[uinfo->value.enumerated.item].channels);
 	return 0;
@@ -306,10 +181,16 @@
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct alc_spec *spec = codec->spec;
+	int items = kcontrol->private_value ? (int)kcontrol->private_value : 2;
+	int i;
 
 	snd_assert(spec->channel_mode, return -ENXIO);
-	ucontrol->value.enumerated.item[0] =
-		(spec->multiout.max_channels == spec->channel_mode[0].channels) ? 0 : 1;
+	for (i = 0; i < items; i++) {
+		if (spec->multiout.max_channels == spec->channel_mode[i].channels) {
+			ucontrol->value.enumerated.item[0] = i;
+			break;
+		}
+	}
 	return 0;
 }
 
@@ -335,21 +216,149 @@
 
 
 /*
+ * bound volume controls
+ *
+ * bind multiple volumes (# indices, from 0)
  */
 
-/* 3-stack mode
- * Pin assignment: Front=0x14, Line-In/Rear=0x1a, Mic/CLFE=0x18, F-Mic=0x1b
- *                 HP=0x19
+#define AMP_VAL_IDX_SHIFT	19
+#define AMP_VAL_IDX_MASK	(0x0f<<19)
+
+static int alc_bind_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	unsigned long pval;
+
+	down(&spec->bind_mutex);
+	pval = kcontrol->private_value;
+	kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
+	snd_hda_mixer_amp_switch_info(kcontrol, uinfo);
+	kcontrol->private_value = pval;
+	up(&spec->bind_mutex);
+	return 0;
+}
+
+static int alc_bind_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	unsigned long pval;
+
+	down(&spec->bind_mutex);
+	pval = kcontrol->private_value;
+	kcontrol->private_value = pval & ~AMP_VAL_IDX_MASK; /* index 0 */
+	snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
+	kcontrol->private_value = pval;
+	up(&spec->bind_mutex);
+	return 0;
+}
+
+static int alc_bind_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	unsigned long pval;
+	int i, indices, change = 0;
+
+	down(&spec->bind_mutex);
+	pval = kcontrol->private_value;
+	indices = (pval & AMP_VAL_IDX_MASK) >> AMP_VAL_IDX_SHIFT;
+	for (i = 0; i < indices; i++) {
+		kcontrol->private_value = (pval & ~AMP_VAL_IDX_MASK) | (i << AMP_VAL_IDX_SHIFT);
+		change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
+	}
+	kcontrol->private_value = pval;
+	up(&spec->bind_mutex);
+	return change;
+}
+
+#define ALC_BIND_MUTE_MONO(xname, nid, channel, indices, direction) \
+	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
+	  .info = alc_bind_switch_info, \
+	  .get = alc_bind_switch_get, \
+	  .put = alc_bind_switch_put, \
+	  .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, indices, direction) }
+
+#define ALC_BIND_MUTE(xname,nid,indices,dir) ALC_BIND_MUTE_MONO(xname,nid,3,indices,dir)
+
+
+/*
+ * ALC880 3-stack model
+ *
+ * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
+ * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18, F-Mic = 0x1b
+ *                 HP = 0x19
  */
-static snd_kcontrol_new_t alc880_base_mixer[] = {
+
+static hda_nid_t alc880_dac_nids[4] = {
+	/* front, rear, clfe, rear_surr */
+	0x02, 0x05, 0x04, 0x03
+};
+
+static hda_nid_t alc880_adc_nids[3] = {
+	/* ADC0-2 */
+	0x07, 0x08, 0x09,
+};
+
+/* The datasheet says the node 0x07 is connected from inputs,
+ * but it shows zero connection in the real implementation on some devices.
+ */
+static hda_nid_t alc880_adc_nids_alt[2] = {
+	/* ADC1-2 */
+	0x08, 0x09,
+};
+
+#define ALC880_DIGOUT_NID	0x06
+#define ALC880_DIGIN_NID	0x0a
+
+static struct hda_input_mux alc880_capture_source = {
+	.num_items = 4,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Front Mic", 0x3 },
+		{ "Line", 0x2 },
+		{ "CD", 0x4 },
+	},
+};
+
+/* channel source setting (2/6 channel selection for 3-stack) */
+/* 2ch mode */
+static struct hda_verb alc880_threestack_ch2_init[] = {
+	/* set line-in to input, mute it */
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	/* set mic-in to input vref 80%, mute it */
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ } /* end */
+};
+
+/* 6ch mode */
+static struct hda_verb alc880_threestack_ch6_init[] = {
+	/* set line-in to output, unmute it */
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	/* set mic-in to output, unmute it */
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ } /* end */
+};
+
+static struct alc_channel_mode alc880_threestack_modes[2] = {
+	{ 2, alc880_threestack_ch2_init },
+	{ 6, alc880_threestack_ch6_init },
+};
+
+static snd_kcontrol_new_t alc880_three_stack_mixer[] = {
 	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
 	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Surround Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
 	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x18, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x18, 2, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
 	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
 	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
 	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
@@ -360,25 +369,7 @@
 	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, 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("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
-	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),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		/* The multiple "Capture Source" controls confuse alsamixer
-		 * So call somewhat different..
-		 * FIXME: the controls appear in the "playback" view!
-		 */
-		/* .name = "Capture Source", */
-		.name = "Input Source",
-		.count = 2,
-		.info = alc_mux_enum_info,
-		.get = alc_mux_enum_get,
-		.put = alc_mux_enum_put,
-	},
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Channel Mode",
@@ -389,70 +380,8 @@
 	{ } /* end */
 };
 
-/* 5-stack mode
- * Pin assignment: Front=0x14, Rear=0x17, CLFE=0x16
- *                 Line-In/Side=0x1a, Mic=0x18, F-Mic=0x1b, HP=0x19
- */
-static snd_kcontrol_new_t alc880_five_stack_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Surround Playback Switch", 0x17, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Side Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
-	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, 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("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
-	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),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		/* The multiple "Capture Source" controls confuse alsamixer
-		 * So call somewhat different..
-		 * FIXME: the controls appear in the "playback" view!
-		 */
-		/* .name = "Capture Source", */
-		.name = "Input Source",
-		.count = 2,
-		.info = alc_mux_enum_info,
-		.get = alc_mux_enum_get,
-		.put = alc_mux_enum_put,
-	},
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = alc880_ch_mode_info,
-		.get = alc880_ch_mode_get,
-		.put = alc880_ch_mode_put,
-	},
-	{ } /* end */
-};
-
-static snd_kcontrol_new_t alc880_w810_base_mixer[] = {
-	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+/* capture mixer elements */
+static snd_kcontrol_new_t alc880_capture_mixer[] = {
 	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),
@@ -475,7 +404,290 @@
 	{ } /* end */
 };
 
+/* capture mixer elements (in case NID 0x07 not available) */
+static snd_kcontrol_new_t alc880_capture_alt_mixer[] = {
+	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		/* The multiple "Capture Source" controls confuse alsamixer
+		 * So call somewhat different..
+		 * FIXME: the controls appear in the "playback" view!
+		 */
+		/* .name = "Capture Source", */
+		.name = "Input Source",
+		.count = 2,
+		.info = alc_mux_enum_info,
+		.get = alc_mux_enum_get,
+		.put = alc_mux_enum_put,
+	},
+	{ } /* end */
+};
+
+
+
 /*
+ * ALC880 5-stack model
+ *
+ * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d), Side = 0x02 (0xd)
+ * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
+ *                 Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
+ */
+
+/* additional mixers to alc880_three_stack_mixer */
+static snd_kcontrol_new_t alc880_five_stack_mixer[] = {
+	HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
+	{ } /* end */
+};
+
+/* channel source setting (6/8 channel selection for 5-stack) */
+/* 6ch mode */
+static struct hda_verb alc880_fivestack_ch6_init[] = {
+	/* set line-in to input, mute it */
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
+	{ } /* end */
+};
+
+/* 8ch mode */
+static struct hda_verb alc880_fivestack_ch8_init[] = {
+	/* set line-in to output, unmute it */
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
+	{ } /* end */
+};
+
+static struct alc_channel_mode alc880_fivestack_modes[2] = {
+	{ 6, alc880_fivestack_ch6_init },
+	{ 8, alc880_fivestack_ch8_init },
+};
+
+
+/*
+ * ALC880 6-stack model
+ *
+ * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e), Side = 0x05 (0x0f)
+ * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
+ *   Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
+ */
+
+static hda_nid_t alc880_6st_dac_nids[4] = {
+	/* front, rear, clfe, rear_surr */
+	0x02, 0x03, 0x04, 0x05
+};	
+
+static struct hda_input_mux alc880_6stack_capture_source = {
+	.num_items = 4,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Front Mic", 0x1 },
+		{ "Line", 0x2 },
+		{ "CD", 0x4 },
+	},
+};
+
+/* fixed 8-channels */
+static struct alc_channel_mode alc880_sixstack_modes[1] = {
+	{ 8, NULL },
+};
+
+static snd_kcontrol_new_t alc880_six_stack_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	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),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = alc880_ch_mode_info,
+		.get = alc880_ch_mode_get,
+		.put = alc880_ch_mode_put,
+	},
+	{ } /* end */
+};
+
+
+/*
+ * ALC880 W810 model
+ *
+ * W810 has rear IO for:
+ * Front (DAC 02)
+ * Surround (DAC 03)
+ * Center/LFE (DAC 04)
+ * Digital out (06)
+ *
+ * The system also has a pair of internal speakers, and a headphone jack.
+ * These are both connected to Line2 on the codec, hence to DAC 02.
+ * 
+ * There is a variable resistor to control the speaker or headphone
+ * volume. This is a hardware-only device without a software API.
+ *
+ * Plugging headphones in will disable the internal speakers. This is
+ * implemented in hardware, not via the driver using jack sense. In
+ * a similar fashion, plugging into the rear socket marked "front" will
+ * disable both the speakers and headphones.
+ *
+ * For input, there's a microphone jack, and an "audio in" jack.
+ * These may not do anything useful with this driver yet, because I
+ * haven't setup any initialization verbs for these yet...
+ */
+
+static hda_nid_t alc880_w810_dac_nids[3] = {
+	/* front, rear/surround, clfe */
+	0x02, 0x03, 0x04
+};
+
+/* fixed 6 channels */
+static struct alc_channel_mode alc880_w810_modes[1] = {
+	{ 6, NULL }
+};
+
+/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
+static snd_kcontrol_new_t alc880_w810_base_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	{ } /* end */
+};
+
+
+/*
+ * Z710V model
+ *
+ * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
+ * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?), Line = 0x1a
+ */
+
+static hda_nid_t alc880_z71v_dac_nids[1] = {
+	0x02
+};
+#define ALC880_Z71V_HP_DAC	0x03
+
+/* fixed 2 channels */
+static struct alc_channel_mode alc880_2_jack_modes[1] = {
+	{ 2, NULL }
+};
+
+static snd_kcontrol_new_t alc880_z71v_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+
+/* FIXME! */
+/*
+ * ALC880 F1734 model
+ *
+ * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
+ * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
+ */
+
+static hda_nid_t alc880_f1734_dac_nids[1] = {
+	0x03
+};
+#define ALC880_F1734_HP_DAC	0x02
+
+static snd_kcontrol_new_t alc880_f1734_mixer[] = {
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Internal Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE("Internal Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{ } /* end */
+};
+
+
+/* FIXME! */
+/*
+ * ALC880 ASUS model
+ *
+ * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
+ * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
+ *  Mic = 0x18, Line = 0x1a
+ */
+
+#define alc880_asus_dac_nids	alc880_w810_dac_nids	/* identical with w810 */
+#define alc880_asus_modes	alc880_threestack_modes	/* 2/6 channel mode */
+
+static snd_kcontrol_new_t alc880_asus_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = alc880_ch_mode_info,
+		.get = alc880_ch_mode_get,
+		.put = alc880_ch_mode_put,
+	},
+	{ } /* end */
+};
+
+/* FIXME! */
+/*
+ * ALC880 ASUS W1V model
+ *
+ * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
+ * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
+ *  Mic = 0x18, Line = 0x1a, Line2 = 0x1b
+ */
+
+/* additional mixers to alc880_asus_mixer */
+static snd_kcontrol_new_t alc880_asus_w1v_mixer[] = {
+	HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
+	HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
+	{ } /* end */
+};
+
+
+/*
+ * build control elements
  */
 static int alc_build_controls(struct hda_codec *codec)
 {
@@ -502,227 +714,297 @@
 	return 0;
 }
 
+
 /*
  * initialize the codec volumes, etc
  */
 
-static struct hda_verb alc880_init_verbs_three_stack[] = {
-	/* Line In pin widget for input */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-	/* CD pin widget for input */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-	/* Mic1 (rear panel) pin widget for input and vref at 80% */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-	/* Mic2 (front panel) pin widget for input and vref at 80% */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-	/* unmute amp left and right */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
-	/* set connection select to line in (default select for this ADC) */
-	{0x07, AC_VERB_SET_CONNECT_SEL, 0x02},
-	/* unmute front mixer amp left (volume = 0) */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-	/* mute pin widget amp left and right (no gain on this amp) */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-	/* unmute rear mixer amp left and right (volume = 0) */
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-	/* mute pin widget amp left and right (no gain on this amp) */
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-	/* unmute rear mixer amp left and right (volume = 0) */
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-	/* mute pin widget amp left and right (no gain on this amp) */
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+/*
+ * generic initialization of ADC, input mixers and output mixers
+ */
+static struct hda_verb alc880_volume_init_verbs[] = {
+	/*
+	 * Unmute ADC0-2 and set the default input to mic-in
+	 */
+	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 
-	/* using rear surround as the path for headphone output */
-	/* unmute rear surround mixer amp left and right (volume = 0) */
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-	/* PASD 3 stack boards use the Mic 2 as the headphone output */
-	/* need to program the selector associated with the Mic 2 pin widget to
-	 * surround path (index 0x01) for headphone output */
-	{0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
-	/* mute pin widget amp left and right (no gain on this amp) */
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-	/* need to retask the Mic 2 pin widget to output */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-
-	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer widget(nid=0x0B)
-	 * to support the input path of analog loopback
+	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
+	 * mixer widget
 	 * Note: PASD motherboards uses the Line In 2 as the input for front panel
 	 * mic (mic 2)
 	 */
-	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
-	/* unmute CD */
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
-	/* unmute Line In */
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
-	/* unmute Mic 1 */
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	/* unmute Line In 2 (for PASD boards Mic 2) */
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
+	/* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
 
-	/* Unmute input amps for the line out paths to support the output path of
-	 * analog loopback
-	 * the mixers on the output path has 2 inputs, one from the DAC and one
-	 * from the mixer
+	/*
+	 * Set up output mixers (0x0c - 0x0f)
 	 */
-	/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
-	/* Unmute Front out path */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	/* Unmute Surround (used as HP) out path */
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	/* Unmute C/LFE out path */
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */
-	/* Unmute rear Surround out path */
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	/* set vol=0 to output mixers */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	/* set up input amps for analog loopback */
+	/* Amp Indices: DAC = 0, mixer = 1 */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 
 	{ }
 };
 
-static struct hda_verb alc880_init_verbs_five_stack[] = {
-	/* Line In pin widget for input */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-	/* CD pin widget for input */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+/*
+ * 3-stack pin configuration:
+ * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
+ */
+static struct hda_verb alc880_pin_3stack_init_verbs[] = {
+	/*
+	 * preset connection lists of input pins
+	 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
+	 */
+	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
+	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+	{0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
+
+	/*
+	 * Set pin mode and muting
+	 */
+	/* set front pin widgets 0x14 for output */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 	/* Mic1 (rear panel) pin widget for input and vref at 80% */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-	/* Mic2 (front panel) pin widget for input and vref at 80% */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-	/* unmute amp left and right */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
-	/* set connection select to line in (default select for this ADC) */
-	{0x07, AC_VERB_SET_CONNECT_SEL, 0x02},
-	/* unmute front mixer amp left and right (volume = 0) */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-	/* mute pin widget amp left and right (no gain on this amp) */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-	/* five rear and clfe */
-	/* unmute rear mixer amp left and right (volume = 0)  */
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-	/* mute pin widget amp left and right (no gain on this amp) */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-	/* unmute clfe mixer amp left and right (volume = 0) */
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-	/* mute pin widget amp left and right (no gain on this amp) */
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-
-	/* using rear surround as the path for headphone output */
-	/* unmute rear surround mixer amp left and right (volume = 0) */
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-	/* PASD 3 stack boards use the Mic 2 as the headphone output */
-	/* need to program the selector associated with the Mic 2 pin widget to
-	 * surround path (index 0x01) for headphone output
-	 */
-	{0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
-	/* mute pin widget amp left and right (no gain on this amp) */
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-	/* need to retask the Mic 2 pin widget to output */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-
-	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer
-	 * widget(nid=0x0B) to support the input path of analog loopback
-	 */
-	/* Note: PASD motherboards uses the Line In 2 as the input for front panel mic (mic 2) */
-	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03*/
-	/* unmute CD */
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
-	/* unmute Line In */
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
-	/* unmute Mic 1 */
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	/* unmute Line In 2 (for PASD boards Mic 2) */
-	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
-
-	/* Unmute input amps for the line out paths to support the output path of
-	 * analog loopback
-	 * the mixers on the output path has 2 inputs, one from the DAC and
-	 * one from the mixer
-	 */
-	/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
-	/* Unmute Front out path */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	/* Unmute Surround (used as HP) out path */
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	/* Unmute C/LFE out path */
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */
-	/* Unmute rear Surround out path */
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Mic2 (as headphone out) for HP output */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Line In pin widget for input */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Line2 (as front mic) pin widget for input and vref at 80% */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* CD pin widget for input */
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
 
 	{ }
 };
 
-static struct hda_verb alc880_w810_init_verbs[] = {
-	/* front channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+/*
+ * 5-stack pin configuration:
+ * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
+ * line-in/side = 0x1a, f-mic = 0x1b
+ */
+static struct hda_verb alc880_pin_5stack_init_verbs[] = {
+	/*
+	 * preset connection lists of input pins
+	 * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
+	 */
+	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */
 
-	/* front channel selector/amp: input 1: capture mix: muted, (no volume selection) */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
+	/*
+	 * Set pin mode and muting
+	 */
+	/* set pin widgets 0x14-0x17 for output */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	/* unmute pins for output (no gain on this amp) */
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 
-	/* front channel selector/amp: output 0: unmuted, max volume */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	/* Mic1 (rear panel) pin widget for input and vref at 80% */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Mic2 (as headphone out) for HP output */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Line In pin widget for input */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Line2 (as front mic) pin widget for input and vref at 80% */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* CD pin widget for input */
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
 
-	/* front out pin: muted, (no volume selection)  */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	{ }
+};
 
-	/* front out pin: NOT headphone enable, out enable, vref disabled */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-
-
-	/* surround channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
-
-	/* surround channel selector/amp: input 1: capture mix: muted, (no volume selection) */
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
-
-	/* surround channel selector/amp: output 0: unmuted, max volume */
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-
-	/* surround out pin: muted, (no volume selection)  */
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-
-	/* surround out pin: NOT headphone enable, out enable, vref disabled */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-
-
-	/* c/lfe channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
-
-	/* c/lfe channel selector/amp: input 1: capture mix: muted, (no volume selection) */
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
-
-	/* c/lfe channel selector/amp: output 0: unmuted, max volume */
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-
-	/* c/lfe out pin: muted, (no volume selection)  */
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-
-	/* c/lfe out pin: NOT headphone enable, out enable, vref disabled */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-
-
+/*
+ * W810 pin configuration:
+ * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
+ */
+static struct hda_verb alc880_pin_w810_init_verbs[] = {
 	/* hphone/speaker input selector: front DAC */
 	{0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
 
-	/* hphone/speaker out pin: muted, (no volume selection)  */
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 
-	/* hphone/speaker out pin: NOT headphone enable, out enable, vref disabled */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
 
 	{ }
 };
 
+/*
+ * Z71V pin configuration:
+ * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
+ */
+static struct hda_verb alc880_pin_z71v_init_verbs[] = {
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+	{ }
+};
+
+/*
+ * 6-stack pin configuration:
+ * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18, f-mic = 0x19,
+ * line = 0x1a, HP = 0x1b
+ */
+static struct hda_verb alc880_pin_6stack_init_verbs[] = {
+	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
+
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	
+	{ }
+};
+
+/* FIXME! */
+/*
+ * F1734 pin configuration:
+ * HP = 0x14, speaker-out = 0x15, mic = 0x18
+ */
+static struct hda_verb alc880_pin_f1734_init_verbs[] = {
+	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
+	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+
+	{ }
+};
+
+/* FIXME! */
+/*
+ * ASUS pin configuration:
+ * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
+ */
+static struct hda_verb alc880_pin_asus_init_verbs[] = {
+	{0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
+	{0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
+	{0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
+
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	
+	{ }
+};
+
+/* Enable GPIO mask and set output */
+static struct hda_verb alc880_gpio1_init_verbs[] = {
+	{0x01, AC_VERB_SET_GPIO_MASK, 0x01},
+	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
+	{0x01, AC_VERB_SET_GPIO_DATA, 0x01},
+};
+
+/* Enable GPIO mask and set output */
+static struct hda_verb alc880_gpio2_init_verbs[] = {
+	{0x01, AC_VERB_SET_GPIO_MASK, 0x02},
+	{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x02},
+	{0x01, AC_VERB_SET_GPIO_DATA, 0x02},
+};
+
+
+/*
+ */
+
 static int alc_init(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
-	snd_hda_sequence_write(codec, spec->init_verbs);
+	unsigned int i;
+
+	for (i = 0; i < spec->num_init_verbs; i++)
+		snd_hda_sequence_write(codec, spec->init_verbs[i]);
 	return 0;
 }
 
@@ -736,9 +1018,8 @@
 	int i;
 
 	alc_init(codec);
-	for (i = 0; i < spec->num_mixers; i++) {
+	for (i = 0; i < spec->num_mixers; i++)
 		snd_hda_resume_ctls(codec, spec->mixers[i]);
-	}
 	if (spec->multiout.dig_out_nid)
 		snd_hda_resume_spdif_out(codec);
 	if (spec->dig_in_nid)
@@ -830,7 +1111,7 @@
 	.substreams = 1,
 	.channels_min = 2,
 	.channels_max = 8,
-	.nid = 0x02, /* NID to query formats and rates */
+	/* NID is set in alc_build_pcms */
 	.ops = {
 		.open = alc880_playback_pcm_open,
 		.prepare = alc880_playback_pcm_prepare,
@@ -842,7 +1123,7 @@
 	.substreams = 2,
 	.channels_min = 2,
 	.channels_max = 2,
-	.nid = 0x07, /* NID to query formats and rates */
+	/* NID is set in alc_build_pcms */
 	.ops = {
 		.prepare = alc880_capture_pcm_prepare,
 		.cleanup = alc880_capture_pcm_cleanup
@@ -878,7 +1159,9 @@
 
 	info->name = spec->stream_name_analog;
 	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
+	info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
 	info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
+	info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
 
 	info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
 	for (i = 0; i < spec->num_channel_mode; i++) {
@@ -906,7 +1189,18 @@
 
 static void alc_free(struct hda_codec *codec)
 {
-	kfree(codec->spec);
+	struct alc_spec *spec = codec->spec;
+	unsigned int i;
+
+	if (! spec)
+		return;
+
+	if (spec->kctl_alloc) {
+		for (i = 0; i < spec->num_kctl_used; i++)
+			kfree(spec->kctl_alloc[i].name);
+		kfree(spec->kctl_alloc);
+	}
+	kfree(spec);
 }
 
 /*
@@ -921,153 +1215,915 @@
 #endif
 };
 
+
+/*
+ * Test configuration for debugging
+ *
+ * Almost all inputs/outputs are enabled.  I/O pins can be configured via
+ * enum controls.
+ */
+#ifdef CONFIG_SND_DEBUG
+static hda_nid_t alc880_test_dac_nids[4] = {
+	0x02, 0x03, 0x04, 0x05
+};
+
+static struct hda_input_mux alc880_test_capture_source = {
+	.num_items = 5,
+	.items = {
+		{ "In-1", 0x0 },
+		{ "In-2", 0x1 },
+		{ "In-3", 0x2 },
+		{ "In-4", 0x3 },
+		{ "CD", 0x4 },
+	},
+};
+
+static struct alc_channel_mode alc880_test_modes[4] = {
+	{ 2, NULL },
+	{ 4, NULL },
+	{ 6, NULL },
+	{ 8, NULL },
+};
+
+static int alc_test_pin_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	static char *texts[] = {
+		"N/A", "Line Out", "HP Out",
+		"In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
+	};
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 8;
+	if (uinfo->value.enumerated.item >= 8)
+		uinfo->value.enumerated.item = 7;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int alc_test_pin_ctl_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
+	unsigned int pin_ctl, item = 0;
+
+	pin_ctl = snd_hda_codec_read(codec, nid, 0,
+				     AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+	if (pin_ctl & AC_PINCTL_OUT_EN) {
+		if (pin_ctl & AC_PINCTL_HP_EN)
+			item = 2;
+		else
+			item = 1;
+	} else if (pin_ctl & AC_PINCTL_IN_EN) {
+		switch (pin_ctl & AC_PINCTL_VREFEN) {
+		case AC_PINCTL_VREF_HIZ: item = 3; break;
+		case AC_PINCTL_VREF_50:  item = 4; break;
+		case AC_PINCTL_VREF_GRD: item = 5; break;
+		case AC_PINCTL_VREF_80:  item = 6; break;
+		case AC_PINCTL_VREF_100: item = 7; break;
+		}
+	}
+	ucontrol->value.enumerated.item[0] = item;
+	return 0;
+}
+
+static int alc_test_pin_ctl_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
+	static unsigned int ctls[] = {
+		0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,
+		AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,
+		AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,
+		AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD,
+		AC_PINCTL_IN_EN | AC_PINCTL_VREF_80,
+		AC_PINCTL_IN_EN | AC_PINCTL_VREF_100,
+	};
+	unsigned int old_ctl, new_ctl;
+
+	old_ctl = snd_hda_codec_read(codec, nid, 0,
+				     AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+	new_ctl = ctls[ucontrol->value.enumerated.item[0]];
+	if (old_ctl != new_ctl) {
+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl);
+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+				    ucontrol->value.enumerated.item[0] >= 3 ? 0xb080 : 0xb000);
+		return 1;
+	}
+	return 0;
+}
+
+static int alc_test_pin_src_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	static char *texts[] = {
+		"Front", "Surround", "CLFE", "Side"
+	};
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 4;
+	if (uinfo->value.enumerated.item >= 4)
+		uinfo->value.enumerated.item = 3;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int alc_test_pin_src_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
+	unsigned int sel;
+
+	sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
+	ucontrol->value.enumerated.item[0] = sel & 3;
+	return 0;
+}
+
+static int alc_test_pin_src_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
+	unsigned int sel;
+
+	sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
+	if (ucontrol->value.enumerated.item[0] != sel) {
+		sel = ucontrol->value.enumerated.item[0] & 3;
+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel);
+		return 1;
+	}
+	return 0;
+}
+
+#define PIN_CTL_TEST(xname,nid) {			\
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	\
+			.name = xname,		       \
+			.info = alc_test_pin_ctl_info, \
+			.get = alc_test_pin_ctl_get,   \
+			.put = alc_test_pin_ctl_put,   \
+			.private_value = nid	       \
+			}
+
+#define PIN_SRC_TEST(xname,nid) {			\
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	\
+			.name = xname,		       \
+			.info = alc_test_pin_src_info, \
+			.get = alc_test_pin_src_get,   \
+			.put = alc_test_pin_src_put,   \
+			.private_value = nid	       \
+			}
+
+static snd_kcontrol_new_t alc880_test_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
+	ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
+	ALC_BIND_MUTE("CLFE Playback Volume", 0x0e, 2, HDA_INPUT),
+	ALC_BIND_MUTE("Side Playback Volume", 0x0f, 2, HDA_INPUT),
+	PIN_CTL_TEST("Front Pin Mode", 0x14),
+	PIN_CTL_TEST("Surround Pin Mode", 0x15),
+	PIN_CTL_TEST("CLFE Pin Mode", 0x16),
+	PIN_CTL_TEST("Side Pin Mode", 0x17),
+	PIN_CTL_TEST("In-1 Pin Mode", 0x18),
+	PIN_CTL_TEST("In-2 Pin Mode", 0x19),
+	PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
+	PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
+	PIN_SRC_TEST("In-1 Pin Source", 0x18),
+	PIN_SRC_TEST("In-2 Pin Source", 0x19),
+	PIN_SRC_TEST("In-3 Pin Source", 0x1a),
+	PIN_SRC_TEST("In-4 Pin Source", 0x1b),
+	HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT),
+	HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT),
+	HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT),
+	HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Input Source",
+		.count = 2,
+		.info = alc_mux_enum_info,
+		.get = alc_mux_enum_get,
+		.put = alc_mux_enum_put,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = alc880_ch_mode_info,
+		.get = alc880_ch_mode_get,
+		.put = alc880_ch_mode_put,
+	},
+	{ } /* end */
+};
+
+static struct hda_verb alc880_test_init_verbs[] = {
+	/* Unmute inputs of 0x0c - 0x0f */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
+	/* Vol output for 0x0c-0x0f */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	/* Set output pins 0x14-0x17 */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	/* Unmute output pins 0x14-0x17 */
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* Set input pins 0x18-0x1c */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	/* Mute input pins 0x18-0x1b */
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* ADC set up */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* Analog input/passthru */
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	{ }
+};
+#endif
+
 /*
  */
 
 static struct hda_board_config alc880_cfg_tbl[] = {
 	/* Back 3 jack, front 2 jack */
 	{ .modelname = "3stack", .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe200, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe201, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe202, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe203, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe204, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe205, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe206, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe207, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe208, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe209, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe20a, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe20b, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe20c, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe20d, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe20e, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe20f, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe210, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe211, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe214, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe302, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe303, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe304, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe306, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe307, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe404, .config = ALC880_3ST },
-	{ .pci_vendor = 0x8086, .pci_device = 0xa101, .config = ALC880_3ST },
-	{ .pci_vendor = 0x107b, .pci_device = 0x3031, .config = ALC880_3ST },
-	{ .pci_vendor = 0x107b, .pci_device = 0x4036, .config = ALC880_3ST },
-	{ .pci_vendor = 0x107b, .pci_device = 0x4037, .config = ALC880_3ST },
-	{ .pci_vendor = 0x107b, .pci_device = 0x4038, .config = ALC880_3ST },
-	{ .pci_vendor = 0x107b, .pci_device = 0x4040, .config = ALC880_3ST },
-	{ .pci_vendor = 0x107b, .pci_device = 0x4041, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe200, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe201, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe202, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe203, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe204, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe205, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe206, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe207, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe208, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe209, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20a, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20b, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20c, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20d, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20e, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe20f, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe210, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe211, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe214, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe302, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe303, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe304, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe306, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe307, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe404, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xa101, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x3031, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4036, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4037, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4038, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST },
 
 	/* Back 3 jack, front 2 jack (Internal add Aux-In) */
-	{ .pci_vendor = 0x1025, .pci_device = 0xe310, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x1025, .pci_subdevice = 0xe310, .config = ALC880_3ST },
+	{ .pci_subvendor = 0x104d, .pci_subdevice = 0x81d6, .config = ALC880_3ST }, 
 
 	/* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
 	{ .modelname = "3stack-digout", .config = ALC880_3ST_DIG },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe308, .config = ALC880_3ST_DIG },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG },
 
 	/* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
-	{ .pci_vendor = 0x8086, .pci_device = 0xe305, .config = ALC880_3ST_DIG },
-	{ .pci_vendor = 0x8086, .pci_device = 0xd402, .config = ALC880_3ST_DIG },
-	{ .pci_vendor = 0x1025, .pci_device = 0xe309, .config = ALC880_3ST_DIG },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xd402, .config = ALC880_3ST_DIG },
+	{ .pci_subvendor = 0x1025, .pci_subdevice = 0xe309, .config = ALC880_3ST_DIG },
 
 	/* Back 5 jack, front 2 jack */
 	{ .modelname = "5stack", .config = ALC880_5ST },
-	{ .pci_vendor = 0x107b, .pci_device = 0x3033, .config = ALC880_5ST },
-	{ .pci_vendor = 0x107b, .pci_device = 0x4039, .config = ALC880_5ST },
-	{ .pci_vendor = 0x107b, .pci_device = 0x3032, .config = ALC880_5ST },
-	{ .pci_vendor = 0x103c, .pci_device = 0x2a09, .config = ALC880_5ST },
+	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x3033, .config = ALC880_5ST },
+	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x4039, .config = ALC880_5ST },
+	{ .pci_subvendor = 0x107b, .pci_subdevice = 0x3032, .config = ALC880_5ST },
+	{ .pci_subvendor = 0x103c, .pci_subdevice = 0x2a09, .config = ALC880_5ST },
+	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x814e, .config = ALC880_5ST },
 
 	/* Back 5 jack plus 1 SPDIF out jack, front 2 jack */
 	{ .modelname = "5stack-digout", .config = ALC880_5ST_DIG },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe224, .config = ALC880_5ST_DIG },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe400, .config = ALC880_5ST_DIG },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe401, .config = ALC880_5ST_DIG },
-	{ .pci_vendor = 0x8086, .pci_device = 0xe402, .config = ALC880_5ST_DIG },
-	{ .pci_vendor = 0x8086, .pci_device = 0xd400, .config = ALC880_5ST_DIG },
-	{ .pci_vendor = 0x8086, .pci_device = 0xd401, .config = ALC880_5ST_DIG },
-	{ .pci_vendor = 0x8086, .pci_device = 0xa100, .config = ALC880_5ST_DIG },
-	{ .pci_vendor = 0x1565, .pci_device = 0x8202, .config = ALC880_5ST_DIG },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe224, .config = ALC880_5ST_DIG },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe400, .config = ALC880_5ST_DIG },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe401, .config = ALC880_5ST_DIG },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xe402, .config = ALC880_5ST_DIG },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xd400, .config = ALC880_5ST_DIG },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xd401, .config = ALC880_5ST_DIG },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0xa100, .config = ALC880_5ST_DIG },
+	{ .pci_subvendor = 0x1565, .pci_subdevice = 0x8202, .config = ALC880_5ST_DIG },
+	{ .pci_subvendor = 0x1019, .pci_subdevice = 0xa880, .config = ALC880_5ST_DIG },
+	{ .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_5ST_DIG },
+	{ .pci_subvendor = 0x1695, .pci_subdevice = 0x400d, .config = ALC880_5ST_DIG },
+	{ .pci_subvendor = 0x0000, .pci_subdevice = 0x8086, .config = ALC880_5ST_DIG },
 
 	{ .modelname = "w810", .config = ALC880_W810 },
-	{ .pci_vendor = 0x161f, .pci_device = 0x203d, .config = ALC880_W810 },
+	{ .pci_subvendor = 0x161f, .pci_subdevice = 0x203d, .config = ALC880_W810 },
+
+	{ .modelname = "z71v", .config = ALC880_Z71V },
+	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_Z71V },
+
+	{ .modelname = "6statack-digout", .config = ALC880_6ST_DIG },
+	{ .pci_subvendor = 0x2668, .pci_subdevice = 0x8086, .config = ALC880_6ST_DIG },
+	{ .pci_subvendor = 0x8086, .pci_subdevice = 0x2668, .config = ALC880_6ST_DIG },
+	{ .pci_subvendor = 0x1462, .pci_subdevice = 0x1150, .config = ALC880_6ST_DIG },
+	{ .pci_subvendor = 0xe803, .pci_subdevice = 0x1019, .config = ALC880_6ST_DIG },
+
+	{ .modelname = "asus", .config = ALC880_ASUS },
+	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_ASUS_DIG },
+	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1973, .config = ALC880_ASUS_DIG },
+	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x19b3, .config = ALC880_ASUS_DIG },
+	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1113, .config = ALC880_ASUS_DIG },
+	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1993, .config = ALC880_ASUS },
+	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x10c3, .config = ALC880_ASUS_DIG },
+	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1133, .config = ALC880_ASUS },
+	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG },
+	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS },
+	{ .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V },
+
+	{ .modelname = "uniwill", .config = ALC880_UNIWILL_DIG },
+	{ .pci_subvendor = 0x1584, .pci_subdevice = 0x9050, .config = ALC880_UNIWILL_DIG },	
+
+	{ .modelname = "F1734", .config = ALC880_F1734 },
+	{ .pci_subvendor = 0x1734, .pci_subdevice = 0x107c, .config = ALC880_F1734 },
+
+#ifdef CONFIG_SND_DEBUG
+	{ .modelname = "test", .config = ALC880_TEST },
+#endif
 
 	{}
 };
 
+/*
+ * configuration template - to be copied to the spec instance
+ */
+struct alc_config_preset {
+	snd_kcontrol_new_t *mixers[4];
+	const struct hda_verb *init_verbs[4];
+	unsigned int num_dacs;
+	hda_nid_t *dac_nids;
+	hda_nid_t dig_out_nid;		/* optional */
+	hda_nid_t hp_nid;		/* optional */
+	unsigned int num_adc_nids;
+	hda_nid_t *adc_nids;
+	unsigned int num_channel_mode;
+	const struct alc_channel_mode *channel_mode;
+	const struct hda_input_mux *input_mux;
+};
+
+static struct alc_config_preset alc880_presets[] = {
+	[ALC880_3ST] = {
+		.mixers = { alc880_three_stack_mixer },
+		.init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
+		.dac_nids = alc880_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
+		.channel_mode = alc880_threestack_modes,
+		.input_mux = &alc880_capture_source,
+	},
+	[ALC880_3ST_DIG] = {
+		.mixers = { alc880_three_stack_mixer },
+		.init_verbs = { alc880_volume_init_verbs, alc880_pin_3stack_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
+		.dac_nids = alc880_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
+		.channel_mode = alc880_threestack_modes,
+		.input_mux = &alc880_capture_source,
+	},
+	[ALC880_5ST] = {
+		.mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer},
+		.init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
+		.dac_nids = alc880_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
+		.channel_mode = alc880_fivestack_modes,
+		.input_mux = &alc880_capture_source,
+	},
+	[ALC880_5ST_DIG] = {
+		.mixers = { alc880_three_stack_mixer, alc880_five_stack_mixer },
+		.init_verbs = { alc880_volume_init_verbs, alc880_pin_5stack_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_dac_nids),
+		.dac_nids = alc880_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
+		.channel_mode = alc880_fivestack_modes,
+		.input_mux = &alc880_capture_source,
+	},
+	[ALC880_6ST_DIG] = {
+		.mixers = { alc880_six_stack_mixer },
+		.init_verbs = { alc880_volume_init_verbs, alc880_pin_6stack_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
+		.dac_nids = alc880_6st_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
+		.channel_mode = alc880_sixstack_modes,
+		.input_mux = &alc880_6stack_capture_source,
+	},
+	[ALC880_W810] = {
+		.mixers = { alc880_w810_base_mixer },
+		.init_verbs = { alc880_volume_init_verbs, alc880_pin_w810_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
+		.dac_nids = alc880_w810_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
+		.channel_mode = alc880_w810_modes,
+		.input_mux = &alc880_capture_source,
+	},
+	[ALC880_Z71V] = {
+		.mixers = { alc880_z71v_mixer },
+		.init_verbs = { alc880_volume_init_verbs, alc880_pin_z71v_init_verbs,
+				alc880_gpio2_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
+		.dac_nids = alc880_z71v_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.hp_nid = 0x03,
+		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
+		.channel_mode = alc880_2_jack_modes,
+		.input_mux = &alc880_capture_source,
+	},
+	[ALC880_F1734] = {
+		.mixers = { alc880_f1734_mixer },
+		.init_verbs = { alc880_volume_init_verbs, alc880_pin_f1734_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),
+		.dac_nids = alc880_f1734_dac_nids,
+		.hp_nid = 0x02,
+		.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
+		.channel_mode = alc880_2_jack_modes,
+		.input_mux = &alc880_capture_source,
+	},
+	[ALC880_ASUS] = {
+		.mixers = { alc880_asus_mixer },
+		.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
+				alc880_gpio1_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+		.dac_nids = alc880_asus_dac_nids,
+		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
+		.channel_mode = alc880_asus_modes,
+		.input_mux = &alc880_capture_source,
+	},
+	[ALC880_ASUS_DIG] = {
+		.mixers = { alc880_asus_mixer },
+		.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
+				alc880_gpio1_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+		.dac_nids = alc880_asus_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
+		.channel_mode = alc880_asus_modes,
+		.input_mux = &alc880_capture_source,
+	},
+	[ALC880_ASUS_W1V] = {
+		.mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
+		.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs,
+				alc880_gpio1_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+		.dac_nids = alc880_asus_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
+		.channel_mode = alc880_asus_modes,
+		.input_mux = &alc880_capture_source,
+	},
+	[ALC880_UNIWILL_DIG] = {
+		.mixers = { alc880_asus_mixer },
+		.init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
+		.dac_nids = alc880_asus_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
+		.channel_mode = alc880_asus_modes,
+		.input_mux = &alc880_capture_source,
+	},
+#ifdef CONFIG_SND_DEBUG
+	[ALC880_TEST] = {
+		.mixers = { alc880_test_mixer },
+		.init_verbs = { alc880_test_init_verbs },
+		.num_dacs = ARRAY_SIZE(alc880_test_dac_nids),
+		.dac_nids = alc880_test_dac_nids,
+		.dig_out_nid = ALC880_DIGOUT_NID,
+		.num_channel_mode = ARRAY_SIZE(alc880_test_modes),
+		.channel_mode = alc880_test_modes,
+		.input_mux = &alc880_test_capture_source,
+	},
+#endif
+};
+
+/*
+ * Automatic parse of I/O pins from the BIOS configuration
+ */
+
+#define NUM_CONTROL_ALLOC	32
+#define NUM_VERB_ALLOC		32
+
+enum {
+	ALC_CTL_WIDGET_VOL,
+	ALC_CTL_WIDGET_MUTE,
+	ALC_CTL_BIND_MUTE,
+};
+static snd_kcontrol_new_t alc880_control_templates[] = {
+	HDA_CODEC_VOLUME(NULL, 0, 0, 0),
+	HDA_CODEC_MUTE(NULL, 0, 0, 0),
+	ALC_BIND_MUTE(NULL, 0, 0, 0),
+};
+
+/* add dynamic controls */
+static int add_control(struct alc_spec *spec, int type, const char *name, unsigned long val)
+{
+	snd_kcontrol_new_t *knew;
+
+	if (spec->num_kctl_used >= spec->num_kctl_alloc) {
+		int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
+
+		knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */
+		if (! knew)
+			return -ENOMEM;
+		if (spec->kctl_alloc) {
+			memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);
+			kfree(spec->kctl_alloc);
+		}
+		spec->kctl_alloc = knew;
+		spec->num_kctl_alloc = num;
+	}
+
+	knew = &spec->kctl_alloc[spec->num_kctl_used];
+	*knew = alc880_control_templates[type];
+	knew->name = kstrdup(name, GFP_KERNEL);
+	if (! knew->name)
+		return -ENOMEM;
+	knew->private_value = val;
+	spec->num_kctl_used++;
+	return 0;
+}
+
+#define alc880_is_fixed_pin(nid)	((nid) >= 0x14 && (nid) <= 0x17)
+#define alc880_fixed_pin_idx(nid)	((nid) - 0x14)
+#define alc880_is_multi_pin(nid)	((nid) >= 0x18)
+#define alc880_multi_pin_idx(nid)	((nid) - 0x18)
+#define alc880_is_input_pin(nid)	((nid) >= 0x18)
+#define alc880_input_pin_idx(nid)	((nid) - 0x18)
+#define alc880_idx_to_dac(nid)		((nid) + 0x02)
+#define alc880_dac_to_idx(nid)		((nid) - 0x02)
+#define alc880_idx_to_mixer(nid)	((nid) + 0x0c)
+#define alc880_idx_to_selector(nid)	((nid) + 0x10)
+#define ALC880_PIN_CD_NID		0x1c
+
+/* fill in the dac_nids table from the parsed pin configuration */
+static int alc880_auto_fill_dac_nids(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
+{
+	hda_nid_t nid;
+	int assigned[4];
+	int i, j;
+
+	memset(assigned, 0, sizeof(assigned));
+
+	/* check the pins hardwired to audio widget */
+	for (i = 0; i < cfg->line_outs; i++) {
+		nid = cfg->line_out_pins[i];
+		if (alc880_is_fixed_pin(nid)) {
+			int idx = alc880_fixed_pin_idx(nid);
+			spec->multiout.dac_nids[i] = alc880_dac_to_idx(idx);
+			assigned[idx] = 1;
+		}
+	}
+	/* left pins can be connect to any audio widget */
+	for (i = 0; i < cfg->line_outs; i++) {
+		nid = cfg->line_out_pins[i];
+		if (alc880_is_fixed_pin(nid))
+			continue;
+		/* search for an empty channel */
+		for (j = 0; j < cfg->line_outs; j++) {
+			if (! assigned[j]) {
+				spec->multiout.dac_nids[i] = alc880_idx_to_dac(j);
+				assigned[j] = 1;
+				break;
+			}
+		}
+	}
+	spec->multiout.num_dacs = cfg->line_outs;
+	return 0;
+}
+
+/* add playback controls from the parsed DAC table */
+static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
+{
+	char name[32];
+	static const char *chname[4] = { "Front", "Surround", NULL /*CLFE*/, "Side" };
+	hda_nid_t nid;
+	int i, err;
+
+	for (i = 0; i < cfg->line_outs; i++) {
+		if (! spec->multiout.dac_nids[i])
+			continue;
+		nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
+		if (i == 2) {
+			/* Center/LFE */
+			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Center Playback Volume",
+					       HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0)
+				return err;
+			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "LFE Playback Volume",
+					       HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0)
+				return err;
+			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Center Playback Switch",
+					       HDA_COMPOSE_AMP_VAL(nid, 1, 2, HDA_INPUT))) < 0)
+				return err;
+			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "LFE Playback Switch",
+					       HDA_COMPOSE_AMP_VAL(nid, 2, 2, HDA_INPUT))) < 0)
+				return err;
+		} else {
+			sprintf(name, "%s Playback Volume", chname[i]);
+			if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
+					       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
+				return err;
+			sprintf(name, "%s Playback Switch", chname[i]);
+			if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
+					       HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
+				return err;
+		}
+	}
+
+	return 0;
+}
+
+/* add playback controls for HP output */
+static int alc880_auto_create_hp_ctls(struct alc_spec *spec, hda_nid_t pin)
+{
+	hda_nid_t nid;
+	int err;
+
+	if (! pin)
+		return 0;
+
+	if (alc880_is_fixed_pin(pin)) {
+		nid = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
+		if (! spec->multiout.dac_nids[0]) {
+			/* use this as the primary output */
+			spec->multiout.dac_nids[0] = nid;
+			if (! spec->multiout.num_dacs)
+				spec->multiout.num_dacs = 1;
+		} else 
+			/* specify the DAC as the extra HP output */
+			spec->multiout.hp_nid = nid;
+		/* control HP volume/switch on the output mixer amp */
+		nid = alc880_idx_to_mixer(alc880_fixed_pin_idx(pin));
+		if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, "Headphone Playback Volume",
+				       HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0)
+			return err;
+		if ((err = add_control(spec, ALC_CTL_BIND_MUTE, "Headphone Playback Switch",
+				       HDA_COMPOSE_AMP_VAL(nid, 3, 2, HDA_INPUT))) < 0)
+			return err;
+	} else if (alc880_is_multi_pin(pin)) {
+		/* set manual connection */
+		if (! spec->multiout.dac_nids[0]) {
+			/* use this as the primary output */
+			spec->multiout.dac_nids[0] = alc880_idx_to_dac(alc880_multi_pin_idx(pin));
+			if (! spec->multiout.num_dacs)
+				spec->multiout.num_dacs = 1;
+		}
+		/* we have only a switch on HP-out PIN */
+		if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, "Headphone Playback Switch",
+				       HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT))) < 0)
+			return err;
+	}
+	return 0;
+}
+
+/* create input playback/capture controls for the given pin */
+static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, const char *ctlname)
+{
+	char name[32];
+	int err, idx;
+
+	sprintf(name, "%s Playback Volume", ctlname);
+	idx = alc880_input_pin_idx(pin);
+	if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
+			       HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0)
+		return err;
+	sprintf(name, "%s Playback Switch", ctlname);
+	if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
+			       HDA_COMPOSE_AMP_VAL(0x0b, 3, idx, HDA_INPUT))) < 0)
+		return err;
+	return 0;
+}
+
+/* create playback/capture controls for input pins */
+static int alc880_auto_create_analog_input_ctls(struct alc_spec *spec, const struct auto_pin_cfg *cfg)
+{
+	static char *labels[AUTO_PIN_LAST] = {
+		"Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
+	};
+	struct hda_input_mux *imux = &spec->private_imux;
+	int i, err;
+
+	for (i = 0; i < AUTO_PIN_LAST; i++) {
+		if (alc880_is_input_pin(cfg->input_pins[i])) {
+			err = new_analog_input(spec, cfg->input_pins[i], labels[i]);
+			if (err < 0)
+				return err;
+			imux->items[imux->num_items].label = labels[i];
+			imux->items[imux->num_items].index = alc880_input_pin_idx(cfg->input_pins[i]);
+			imux->num_items++;
+		}
+	}
+	return 0;
+}
+
+static void alc880_auto_set_output_and_unmute(struct hda_codec *codec, hda_nid_t nid, int pin_type,
+					      int dac_idx)
+{
+	/* set as output */
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+	/* need the manual connection? */
+	if (alc880_is_multi_pin(nid)) {
+		struct alc_spec *spec = codec->spec;
+		int idx = alc880_multi_pin_idx(nid);
+		snd_hda_codec_write(codec, alc880_idx_to_selector(idx), 0,
+				    AC_VERB_SET_CONNECT_SEL,
+				    alc880_dac_to_idx(spec->multiout.dac_nids[dac_idx]));
+	}
+}
+
+static void alc880_auto_init_multi_out(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	int i;
+
+	for (i = 0; i < spec->autocfg.line_outs; i++) {
+		hda_nid_t nid = spec->autocfg.line_out_pins[i];
+		alc880_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
+	}
+}
+
+static void alc880_auto_init_hp_out(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	hda_nid_t pin;
+
+	pin = spec->autocfg.hp_pin;
+	if (pin) /* connect to front */
+		alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
+}
+
+static void alc880_auto_init_analog_input(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	int i;
+
+	for (i = 0; i < AUTO_PIN_LAST; i++) {
+		hda_nid_t nid = spec->autocfg.input_pins[i];
+		if (alc880_is_input_pin(nid)) {
+			snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+					    i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN);
+			if (nid != ALC880_PIN_CD_NID)
+				snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+						    AMP_OUT_MUTE);
+		}
+	}
+}
+
+/* parse the BIOS configuration and set up the alc_spec */
+/* return 1 if successful, 0 if the proper config is not found, or a negative error code */
+static int alc880_parse_auto_config(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	int err;
+
+	if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg)) < 0)
+		return err;
+	if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0)
+		return err;
+	if (! spec->autocfg.line_outs && ! spec->autocfg.hp_pin)
+		return 0; /* can't find valid BIOS pin config */
+	if ((err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 ||
+	    (err = alc880_auto_create_hp_ctls(spec, spec->autocfg.hp_pin)) < 0 ||
+	    (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0)
+		return err;
+
+	spec->multiout.max_channels = spec->multiout.num_dacs * 2;
+
+	if (spec->autocfg.dig_out_pin)
+		spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
+	if (spec->autocfg.dig_in_pin)
+		spec->dig_in_nid = ALC880_DIGIN_NID;
+
+	if (spec->kctl_alloc)
+		spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
+
+	spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs;
+
+	spec->input_mux = &spec->private_imux;
+
+	return 1;
+}
+
+/* init callback for auto-configuration model -- overriding the default init */
+static int alc880_auto_init(struct hda_codec *codec)
+{
+	alc_init(codec);
+	alc880_auto_init_multi_out(codec);
+	alc880_auto_init_hp_out(codec);
+	alc880_auto_init_analog_input(codec);
+	return 0;
+}
+
+/*
+ * OK, here we have finally the patch for ALC880
+ */
+
 static int patch_alc880(struct hda_codec *codec)
 {
 	struct alc_spec *spec;
 	int board_config;
+	int i, err;
 
 	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
 		return -ENOMEM;
 
+	init_MUTEX(&spec->bind_mutex);
 	codec->spec = spec;
 
 	board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl);
-	if (board_config < 0) {
-		snd_printd(KERN_INFO "hda_codec: Unknown model for ALC880\n");
-		board_config = ALC880_MINIMAL;
+	if (board_config < 0 || board_config >= ALC880_MODEL_LAST) {
+		printk(KERN_INFO "hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...\n");
+		board_config = ALC880_AUTO;
 	}
 
-	switch (board_config) {
-	case ALC880_W810:
-		spec->mixers[spec->num_mixers] = alc880_w810_base_mixer;
-		spec->num_mixers++;
-		break;
-	case ALC880_5ST:
-	case ALC880_5ST_DIG:
-		spec->mixers[spec->num_mixers] = alc880_five_stack_mixer;
-		spec->num_mixers++;
-		break;
-	default:
-		spec->mixers[spec->num_mixers] = alc880_base_mixer;
-		spec->num_mixers++;
-		break;
+	if (board_config == ALC880_AUTO) {
+		/* automatic parse from the BIOS config */
+		err = alc880_parse_auto_config(codec);
+		if (err < 0) {
+			alc_free(codec);
+			return err;
+		} else if (! err) {
+			printk(KERN_INFO "hda_codec: Cannot set up configuration from BIOS.  Using 3-stack mode...\n");
+			board_config = ALC880_3ST;
+		}
 	}
 
-	switch (board_config) {
-	case ALC880_3ST_DIG:
-	case ALC880_5ST_DIG:
-	case ALC880_W810:
-		spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
-		break;
-	default:
-		break;
-	}
+	if (board_config != ALC880_AUTO) {
+		/* set up from the preset table */
+		const struct alc_config_preset *preset;
 
-	switch (board_config) {
-	case ALC880_3ST:
-	case ALC880_3ST_DIG:
-	case ALC880_5ST:
-	case ALC880_5ST_DIG:
-	case ALC880_W810:
-		spec->front_panel = 1;
-		break;
-	default:
-		break;
-	}
+		preset = &alc880_presets[board_config];
 
-	switch (board_config) {
-	case ALC880_5ST:
-	case ALC880_5ST_DIG:
-		spec->init_verbs = alc880_init_verbs_five_stack;
-		spec->channel_mode = alc880_fivestack_modes;
-		spec->num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes);
-		break;
-	case ALC880_W810:
-		spec->init_verbs = alc880_w810_init_verbs;
-		spec->channel_mode = alc880_w810_modes;
-		spec->num_channel_mode = ARRAY_SIZE(alc880_w810_modes);
-		break;
-	default:
-		spec->init_verbs = alc880_init_verbs_three_stack;
-		spec->channel_mode = alc880_threestack_modes;
-		spec->num_channel_mode = ARRAY_SIZE(alc880_threestack_modes);
-		break;
+		for (i = 0; preset->mixers[i]; i++) {
+			snd_assert(spec->num_mixers < ARRAY_SIZE(spec->mixers), break);
+			spec->mixers[spec->num_mixers++] = preset->mixers[i];
+		}
+		for (i = 0; preset->init_verbs[i]; i++) {
+			snd_assert(spec->num_init_verbs < ARRAY_SIZE(spec->init_verbs), break);
+			spec->init_verbs[spec->num_init_verbs++] = preset->init_verbs[i];
+		}
+
+		spec->channel_mode = preset->channel_mode;
+		spec->num_channel_mode = preset->num_channel_mode;
+
+		spec->multiout.max_channels = spec->channel_mode[0].channels;
+
+		spec->multiout.num_dacs = preset->num_dacs;
+		spec->multiout.dac_nids = preset->dac_nids;
+		spec->multiout.dig_out_nid = preset->dig_out_nid;
+		spec->multiout.hp_nid = preset->hp_nid;
+
+		spec->input_mux = preset->input_mux;
+
+		spec->num_adc_nids = preset->num_adc_nids;
+		spec->adc_nids = preset->adc_nids;
 	}
 
 	spec->stream_name_analog = "ALC880 Analog";
@@ -1078,34 +2134,64 @@
 	spec->stream_digital_playback = &alc880_pcm_digital_playback;
 	spec->stream_digital_capture = &alc880_pcm_digital_capture;
 
-	spec->multiout.max_channels = spec->channel_mode[0].channels;
-
-	switch (board_config) {
-	case ALC880_W810:
-		spec->multiout.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids);
-		spec->multiout.dac_nids = alc880_w810_dac_nids;
-		// No dedicated headphone socket - it's shared with built-in speakers.
-		break;
-	default:
-		spec->multiout.num_dacs = ARRAY_SIZE(alc880_dac_nids);
-		spec->multiout.dac_nids = alc880_dac_nids;
-		spec->multiout.hp_nid = 0x03; /* rear-surround NID */
-		break;
+	if (! spec->adc_nids && spec->input_mux) {
+		/* check whether NID 0x07 is valid */
+		unsigned int wcap = snd_hda_param_read(codec, alc880_adc_nids[0],
+						       AC_PAR_AUDIO_WIDGET_CAP);
+		wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
+		if (wcap != AC_WID_AUD_IN) {
+			spec->adc_nids = alc880_adc_nids_alt;
+			spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);
+			spec->mixers[spec->num_mixers] = alc880_capture_alt_mixer;
+			spec->num_mixers++;
+		} else {
+			spec->adc_nids = alc880_adc_nids;
+			spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
+			spec->mixers[spec->num_mixers] = alc880_capture_mixer;
+			spec->num_mixers++;
+		}
 	}
 
-	spec->input_mux = &alc880_capture_source;
-	spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
-	spec->adc_nids = alc880_adc_nids;
-
 	codec->patch_ops = alc_patch_ops;
+	if (board_config == ALC880_AUTO)
+		codec->patch_ops.init = alc880_auto_init;
 
 	return 0;
 }
 
+
 /*
  * ALC260 support
  */
 
+static hda_nid_t alc260_dac_nids[1] = {
+	/* front */
+	0x02,
+};
+
+static hda_nid_t alc260_adc_nids[1] = {
+	/* ADC0 */
+	0x04,
+};
+
+static hda_nid_t alc260_hp_adc_nids[1] = {
+	/* ADC1 */
+	0x05,
+};
+
+#define ALC260_DIGOUT_NID	0x03
+#define ALC260_DIGIN_NID	0x06
+
+static struct hda_input_mux alc260_capture_source = {
+	.num_items = 4,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Front Mic", 0x1 },
+		{ "Line", 0x2 },
+		{ "CD", 0x4 },
+	},
+};
+
 /*
  * This is just place-holder, so there's something for alc_build_pcms to look
  * at when it calculates the maximum number of channels. ALC260 has no mixer
@@ -1116,11 +2202,9 @@
 	{ 2, NULL },
 };
 
-snd_kcontrol_new_t alc260_base_mixer[] = {
+static snd_kcontrol_new_t alc260_base_mixer[] = {
 	HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
-	/* use LINE2 for the output */
-	/* HDA_CODEC_MUTE("Front Playback Switch", 0x0f, 0x0, HDA_OUTPUT), */
-	HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
 	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
 	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
 	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
@@ -1132,9 +2216,9 @@
 	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT),
 	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),
 	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
 	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
 	HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
 	{
@@ -1147,60 +2231,91 @@
 	{ } /* end */
 };
 
+static snd_kcontrol_new_t alc260_hp_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
+	HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Capture Source",
+		.info = alc_mux_enum_info,
+		.get = alc_mux_enum_get,
+		.put = alc_mux_enum_put,
+	},
+	{ } /* end */
+};
+
 static struct hda_verb alc260_init_verbs[] = {
 	/* Line In pin widget for input */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
 	/* CD pin widget for input */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
 	/* Mic1 (rear panel) pin widget for input and vref at 80% */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
 	/* Mic2 (front panel) pin widget for input and vref at 80% */
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
 	/* LINE-2 is used for line-out in rear */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
 	/* select line-out */
 	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
 	/* LINE-OUT pin */
-	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
 	/* enable HP */
-	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
 	/* enable Mono */
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	/* unmute amp left and right */
-	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	/* mute capture amp left and right */
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	/* set connection select to line in (default select for this ADC) */
 	{0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
-	/* unmute Line-Out mixer amp left and right (volume = 0) */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-	/* mute pin widget amp left and right (no gain on this amp) */
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-	/* unmute HP mixer amp left and right (volume = 0) */
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-	/* mute pin widget amp left and right (no gain on this amp) */
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	/* unmute Mono mixer amp left and right (volume = 0) */
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-	/* mute pin widget amp left and right (no gain on this amp) */
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-	/* mute LINE-2 out */
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	/* mute capture amp left and right */
+	{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	/* set connection select to line in (default select for this ADC) */
+	{0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
+	/* set vol=0 Line-Out mixer amp left and right */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	/* unmute pin widget amp left and right (no gain on this amp) */
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* set vol=0 HP mixer amp left and right */
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	/* unmute pin widget amp left and right (no gain on this amp) */
+	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* set vol=0 Mono mixer amp left and right */
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	/* unmute pin widget amp left and right (no gain on this amp) */
+	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
+	/* unmute LINE-2 out pin */
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
-	/* unmute CD */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
-	/* unmute Line In */
-	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
-	/* unmute Mic */
-	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	/* mute CD */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
+	/* mute Line In */
+	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
+	/* mute Mic */
+	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
 	/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
-	/* Unmute Front out path */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	/* Unmute Headphone out path */
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	/* Unmute Mono out path */
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	/* mute Front out path */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* mute Headphone out path */
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
+	/* mute Mono out path */
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 	{ }
 };
 
@@ -1208,30 +2323,52 @@
 	.substreams = 1,
 	.channels_min = 2,
 	.channels_max = 2,
-	.nid = 0x2,
 };
 
 static struct hda_pcm_stream alc260_pcm_analog_capture = {
 	.substreams = 1,
 	.channels_min = 2,
 	.channels_max = 2,
-	.nid = 0x4,
+};
+
+static struct hda_board_config alc260_cfg_tbl[] = {
+	{ .modelname = "hp", .config = ALC260_HP },
+	{ .pci_subvendor = 0x103c, .config = ALC260_HP },
+	{}
 };
 
 static int patch_alc260(struct hda_codec *codec)
 {
 	struct alc_spec *spec;
+	int board_config;
 
 	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
 	if (spec == NULL)
 		return -ENOMEM;
 
+	init_MUTEX(&spec->bind_mutex);
 	codec->spec = spec;
 
-	spec->mixers[spec->num_mixers] = alc260_base_mixer;
-	spec->num_mixers++;
+	board_config = snd_hda_check_board_config(codec, alc260_cfg_tbl);
+	if (board_config < 0 || board_config >= ALC260_MODEL_LAST) {
+		snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260\n");
+		board_config = ALC260_BASIC;
+	}
 
-	spec->init_verbs = alc260_init_verbs;
+	switch (board_config) {
+	case ALC260_HP:
+		spec->mixers[spec->num_mixers] = alc260_hp_mixer;
+		spec->num_mixers++;
+		break;
+	default:
+		spec->mixers[spec->num_mixers] = alc260_base_mixer;
+		spec->num_mixers++;
+		break;
+	}
+
+	spec->init_verbs[0] = alc260_init_verbs;
+	spec->num_init_verbs = 1;
+
 	spec->channel_mode = alc260_modes;
 	spec->num_channel_mode = ARRAY_SIZE(alc260_modes);
 
@@ -1244,14 +2381,23 @@
 	spec->multiout.dac_nids = alc260_dac_nids;
 
 	spec->input_mux = &alc260_capture_source;
-	spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
-	spec->adc_nids = alc260_adc_nids;
+	switch (board_config) {
+	case ALC260_HP:
+		spec->num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids);
+		spec->adc_nids = alc260_hp_adc_nids;
+		break;
+	default:
+		spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
+		spec->adc_nids = alc260_adc_nids;
+		break;
+	}
 
 	codec->patch_ops = alc_patch_ops;
 
 	return 0;
 }
 
+
 /*
  * ALC882 support
  *
@@ -1324,15 +2470,15 @@
  */
 static snd_kcontrol_new_t alc882_base_mixer[] = {
 	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
 	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
 	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
+	ALC_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Side Playback Switch", 0x17, 0x0, HDA_OUTPUT),
+	ALC_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
 	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
 	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
 	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
@@ -1364,89 +2510,80 @@
 
 static struct hda_verb alc882_init_verbs[] = {
 	/* Front mixer: unmute input/output amp left and right (volume = 0) */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 	/* Rear mixer */
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 	/* CLFE mixer */
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 	/* Side mixer */
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
 
-	/* Front Pin: to output mode */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	/* Front Pin: mute amp left and right (no volume) */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-	/* select Front mixer (0x0c, index 0) */
+	/* Front Pin: output 0 (0x0c) */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* Rear Pin */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	/* Rear Pin: mute amp left and right (no volume) */
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-	/* select Rear mixer (0x0d, index 1) */
+	/* Rear Pin: output 1 (0x0d) */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
-	/* CLFE Pin */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	/* CLFE Pin: mute amp left and right (no volume) */
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-	/* select CLFE mixer (0x0e, index 2) */
+	/* CLFE Pin: output 2 (0x0e) */
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 	{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
-	/* Side Pin */
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	/* Side Pin: mute amp left and right (no volume) */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-	/* select Side mixer (0x0f, index 3) */
+	/* Side Pin: output 3 (0x0f) */
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
-	/* Headphone Pin */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
-	/* Headphone Pin: mute amp left and right (no volume) */
-	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-	/* select Front mixer (0x0c, index 0) */
+	/* Mic (rear) pin: input vref at 80% */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Front Mic pin: input vref at 80% */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Line In pin: input */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
+	/* Line-2 In: Headphone output (output 0 - 0x0c) */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
 	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* Mic (rear) pin widget for input and vref at 80% */
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-	/* Front Mic pin widget for input and vref at 80% */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-	/* Line In pin widget for input */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
 	/* CD pin widget for input */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
 
 	/* FIXME: use matrix-type input source selection */
 	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
 	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
-	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
 	/* Input mixer2 */
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
-	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
 	/* Input mixer3 */
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
-	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
-	/* ADC1: unmute amp left and right */
-	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
-	/* ADC2: unmute amp left and right */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
-	/* ADC3: unmute amp left and right */
-	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
-
-	/* Unmute front loopback */
-	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	/* Unmute rear loopback */
-	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-	/* Mute CLFE loopback */
-	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
-	/* Unmute side loopback */
-	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
+	/* ADC1: mute amp left and right */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* ADC2: mute amp left and right */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* ADC3: mute amp left and right */
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
+	{0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
 
 	{ }
 };
@@ -1459,6 +2596,7 @@
 	if (spec == NULL)
 		return -ENOMEM;
 
+	init_MUTEX(&spec->bind_mutex);
 	codec->spec = spec;
 
 	spec->mixers[spec->num_mixers] = alc882_base_mixer;
@@ -1466,8 +2604,9 @@
 
 	spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
 	spec->dig_in_nid = ALC880_DIGIN_NID;
-	spec->front_panel = 1;
-	spec->init_verbs = alc882_init_verbs;
+	spec->init_verbs[0] = alc882_init_verbs;
+	spec->num_init_verbs = 1;
+
 	spec->channel_mode = alc882_ch_modes;
 	spec->num_channel_mode = ARRAY_SIZE(alc882_ch_modes);
 
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
new file mode 100644
index 0000000..013be2e
--- /dev/null
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -0,0 +1,666 @@
+/*
+ * Universal Interface for Intel High Definition Audio Codec
+ *
+ * HD audio interface patch for SigmaTel STAC92xx
+ *
+ * Copyright (c) 2005 Embedded Alley Solutions, Inc.
+ * <matt@embeddedalley.com>
+ *
+ * Based on patch_cmedia.c and patch_realtek.c
+ * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ *  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"
+
+#undef STAC_TEST
+
+struct sigmatel_spec {
+	/* playback */
+	struct hda_multi_out multiout;
+	hda_nid_t playback_nid;
+
+	/* capture */
+	hda_nid_t *adc_nids;
+	unsigned int num_adcs;
+	hda_nid_t *mux_nids;
+	unsigned int num_muxes;
+	hda_nid_t capture_nid;
+	hda_nid_t dig_in_nid;
+
+	/* power management*/
+	hda_nid_t *pstate_nids;
+	unsigned int num_pstates;
+
+	/* pin widgets */
+	hda_nid_t *pin_nids;
+	unsigned int num_pins;
+#ifdef STAC_TEST
+	unsigned int *pin_configs;
+#endif
+
+	/* codec specific stuff */
+	struct hda_verb *init;
+	snd_kcontrol_new_t *mixer;
+
+	/* capture source */
+	struct hda_input_mux input_mux;
+	char input_labels[HDA_MAX_NUM_INPUTS][16];
+	unsigned int cur_mux[2];
+
+	/* channel mode */
+	unsigned int num_ch_modes;
+	unsigned int cur_ch_mode;
+	const struct sigmatel_channel_mode *channel_modes;
+
+	struct hda_pcm pcm_rec[1];	/* PCM information */
+};
+
+static hda_nid_t stac9200_adc_nids[1] = {
+        0x03,
+};
+
+static hda_nid_t stac9200_mux_nids[1] = {
+        0x0c,
+};
+
+static hda_nid_t stac9200_dac_nids[1] = {
+        0x02,
+};
+
+static hda_nid_t stac9200_pstate_nids[3] = {
+	0x01, 0x02, 0x03,
+};
+
+static hda_nid_t stac9200_pin_nids[8] = {
+	0x08, 0x09, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
+};
+
+static hda_nid_t stac922x_adc_nids[2] = {
+        0x06, 0x07,
+};
+
+static hda_nid_t stac922x_mux_nids[2] = {
+        0x12, 0x13,
+};
+
+static hda_nid_t stac922x_dac_nids[4] = {
+        0x02, 0x03, 0x04, 0x05,
+};
+
+static hda_nid_t stac922x_pstate_nids[8] = {
+	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x11,
+};
+
+static hda_nid_t stac922x_pin_nids[10] = {
+	0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+	0x0f, 0x10, 0x11, 0x15, 0x1b,
+};
+
+static int stac92xx_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct sigmatel_spec *spec = codec->spec;
+	return snd_hda_input_mux_info(&spec->input_mux, uinfo);
+}
+
+static int stac92xx_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct sigmatel_spec *spec = codec->spec;
+	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+
+	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
+	return 0;
+}
+
+static int stac92xx_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct sigmatel_spec *spec = codec->spec;
+	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+
+	return snd_hda_input_mux_put(codec, &spec->input_mux, ucontrol,
+				     spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]);
+}
+
+static struct hda_verb stac9200_ch2_init[] = {
+	/* set dac0mux for dac converter */
+	{ 0x07, 0x701, 0x00},
+	{}
+};
+
+static struct hda_verb stac922x_ch2_init[] = {
+	/* set master volume and direct control */	
+	{ 0x16, 0x70f, 0xff},
+	{}
+};
+
+struct sigmatel_channel_mode {
+	unsigned int channels;
+	const struct hda_verb *sequence;
+};
+
+static snd_kcontrol_new_t stac9200_mixer[] = {
+	HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Input Source",
+		.count = 1,
+		.info = stac92xx_mux_enum_info,
+		.get = stac92xx_mux_enum_get,
+		.put = stac92xx_mux_enum_put,
+	},
+	HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Input Mux Volume", 0x0c, 0, HDA_OUTPUT),
+	{ } /* end */
+};
+
+static snd_kcontrol_new_t stac922x_mixer[] = {
+	HDA_CODEC_VOLUME("PCM Playback Volume", 0x2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("PCM Playback Switch", 0x2, 0x0, HDA_OUTPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Input Source",
+		.count = 1,
+		.info = stac92xx_mux_enum_info,
+		.get = stac92xx_mux_enum_get,
+		.put = stac92xx_mux_enum_put,
+	},
+	HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x17, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mux Capture Volume", 0x12, 0x0, HDA_OUTPUT),
+	{ } /* end */
+};
+
+static int stac92xx_build_controls(struct hda_codec *codec)
+{
+	struct sigmatel_spec *spec = codec->spec;
+	int err;
+
+	err = snd_hda_add_new_ctls(codec, spec->mixer);
+	if (err < 0)
+		return err;
+	if (spec->multiout.dig_out_nid) {
+		err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
+		if (err < 0)
+			return err;
+	}
+	if (spec->dig_in_nid) {
+		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
+		if (err < 0)
+			return err;
+	}
+	return 0;	
+}
+
+#ifdef STAC_TEST
+static unsigned int stac9200_pin_configs[8] = {
+	0x01c47010, 0x01447010, 0x0221401f, 0x01114010,
+	0x02a19020, 0x01a19021, 0x90100140, 0x01813122,
+};
+
+static unsigned int stac922x_pin_configs[14] = {
+	0x40000100, 0x40000100, 0x40000100, 0x01114010,
+	0x01813122, 0x40000100, 0x01447010, 0x01c47010,
+	0x40000100, 0x40000100,
+};
+
+static void stac92xx_set_config_regs(struct hda_codec *codec)
+{
+	int i;
+	struct sigmatel_spec *spec = codec->spec;
+	unsigned int pin_cfg;
+
+	for (i=0; i < spec->num_pins; i++) {
+		snd_hda_codec_write(codec, spec->pin_nids[i], 0,
+				    AC_VERB_SET_CONFIG_DEFAULT_BYTES_0,
+				    spec->pin_configs[i] & 0x000000ff);
+		snd_hda_codec_write(codec, spec->pin_nids[i], 0,
+				    AC_VERB_SET_CONFIG_DEFAULT_BYTES_1,
+				    (spec->pin_configs[i] & 0x0000ff00) >> 8);
+		snd_hda_codec_write(codec, spec->pin_nids[i], 0,
+				    AC_VERB_SET_CONFIG_DEFAULT_BYTES_2,
+				    (spec->pin_configs[i] & 0x00ff0000) >> 16);
+		snd_hda_codec_write(codec, spec->pin_nids[i], 0,
+				    AC_VERB_SET_CONFIG_DEFAULT_BYTES_3,
+				    spec->pin_configs[i] >> 24);
+		pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0,
+					     AC_VERB_GET_CONFIG_DEFAULT,
+					     0x00);	
+		printk("pin nid %2.2x pin config %8.8x\n", spec->pin_nids[i], pin_cfg);
+	}
+}
+#endif
+
+static int stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, unsigned int value)
+{
+	unsigned int pin_ctl;
+
+	pin_ctl = snd_hda_codec_read(codec, nid, 0,
+				     AC_VERB_GET_PIN_WIDGET_CONTROL,
+				     0x00);
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+			    pin_ctl | value);
+
+	return 0;
+}
+
+static int stac92xx_set_vref(struct hda_codec *codec, hda_nid_t nid)
+{
+	unsigned int vref_caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP) >> AC_PINCAP_VREF_SHIFT;
+	unsigned int vref_ctl = AC_PINCTL_VREF_HIZ;
+
+	if (vref_caps & AC_PINCAP_VREF_100)
+		vref_ctl = AC_PINCTL_VREF_100;
+	else if (vref_caps & AC_PINCAP_VREF_80)
+		vref_ctl = AC_PINCTL_VREF_80;
+	else if (vref_caps & AC_PINCAP_VREF_50)
+		vref_ctl = AC_PINCTL_VREF_50;
+	else if (vref_caps & AC_PINCAP_VREF_GRD)
+		vref_ctl = AC_PINCTL_VREF_GRD;
+
+	stac92xx_set_pinctl(codec, nid, vref_ctl);
+	
+	return 0;
+}
+
+/*
+ * retrieve the default device type from the default config value
+ */
+#define get_defcfg_type(cfg) ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
+#define get_defcfg_location(cfg) ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
+
+static int stac92xx_config_pin(struct hda_codec *codec, hda_nid_t nid, unsigned int pin_cfg)
+{
+	struct sigmatel_spec *spec = codec->spec;
+	u32 location = get_defcfg_location(pin_cfg);
+	char *label;
+	const char *type = NULL;
+	int ainput = 0;
+
+	switch(get_defcfg_type(pin_cfg)) {
+		case AC_JACK_HP_OUT:
+			/* Enable HP amp */
+			stac92xx_set_pinctl(codec, nid, AC_PINCTL_HP_EN);
+			/* Fall through */
+		case AC_JACK_SPDIF_OUT:
+		case AC_JACK_LINE_OUT:
+		case AC_JACK_SPEAKER:
+			/* Enable output */
+			stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
+			break;
+		case AC_JACK_SPDIF_IN:
+			stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
+			break;
+		case AC_JACK_MIC_IN:
+			if ((location & 0x0f) == AC_JACK_LOC_FRONT)
+				type = "Front Mic";
+			else
+				type = "Mic";
+			ainput = 1;
+			/* Set vref */
+			stac92xx_set_vref(codec, nid);
+			stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
+			break;
+		case AC_JACK_CD:
+			type = "CD";
+			ainput = 1;
+			stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
+			break;
+		case AC_JACK_LINE_IN:
+			if ((location & 0x0f) == AC_JACK_LOC_FRONT)
+				type = "Front Line";
+			else
+				type = "Line";
+			ainput = 1;
+			stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
+			break;
+		case AC_JACK_AUX:
+			if ((location & 0x0f) == AC_JACK_LOC_FRONT)
+				type = "Front Aux";
+			else
+				type = "Aux";
+			ainput = 1;
+			stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
+			break;
+	}
+
+	if (ainput) {
+		hda_nid_t con_lst[HDA_MAX_NUM_INPUTS];
+		int i, j, num_cons, index = -1;
+		if (!type)
+			type = "Input";
+		label = spec->input_labels[spec->input_mux.num_items];
+		strcpy(label, type);
+		spec->input_mux.items[spec->input_mux.num_items].label = label;
+		for (i=0; i<spec->num_muxes; i++) {
+			num_cons = snd_hda_get_connections(codec, spec->mux_nids[i], con_lst, HDA_MAX_NUM_INPUTS);
+			for (j=0; j<num_cons; j++)
+				if (con_lst[j] == nid) {
+					index = j;
+					break;
+				}
+			if (index >= 0)
+				break;
+		}
+		spec->input_mux.items[spec->input_mux.num_items].index = index;
+		spec->input_mux.num_items++;
+	}
+
+	return 0;
+}
+
+static int stac92xx_config_pins(struct hda_codec *codec)
+{
+	struct sigmatel_spec *spec = codec->spec;
+	int i;
+	unsigned int pin_cfg;
+
+	for (i=0; i < spec->num_pins; i++) {
+		/* Default to disabled */
+		snd_hda_codec_write(codec, spec->pin_nids[i], 0,
+				    AC_VERB_SET_PIN_WIDGET_CONTROL,
+				    0x00);
+
+		pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0,
+					     AC_VERB_GET_CONFIG_DEFAULT,
+					     0x00);
+		if (((pin_cfg & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT) == AC_JACK_PORT_NONE)
+			continue;	/* Move on */
+
+		stac92xx_config_pin(codec, spec->pin_nids[i], pin_cfg);
+	}
+
+	return 0;
+}
+
+static int stac92xx_init(struct hda_codec *codec)
+{
+	struct sigmatel_spec *spec = codec->spec;
+	int i;
+
+	for (i=0; i < spec->num_pstates; i++)
+		snd_hda_codec_write(codec, spec->pstate_nids[i], 0,
+				    AC_VERB_SET_POWER_STATE, 0x00);
+
+	mdelay(100);
+
+	snd_hda_sequence_write(codec, spec->init);
+
+#ifdef STAC_TEST
+	stac92xx_set_config_regs(codec);
+#endif
+
+	stac92xx_config_pins(codec);
+
+	return 0;
+}
+
+/*
+ * Analog playback callbacks
+ */
+static int stac92xx_playback_pcm_open(struct hda_pcm_stream *hinfo,
+				      struct hda_codec *codec,
+				      snd_pcm_substream_t *substream)
+{
+	struct sigmatel_spec *spec = codec->spec;
+	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+}
+
+static int stac92xx_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+					 struct hda_codec *codec,
+					 unsigned int stream_tag,
+					 unsigned int format,
+					 snd_pcm_substream_t *substream)
+{
+	struct sigmatel_spec *spec = codec->spec;
+	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
+						format, substream);
+}
+
+static int stac92xx_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+					struct hda_codec *codec,
+					snd_pcm_substream_t *substream)
+{
+	struct sigmatel_spec *spec = codec->spec;
+	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
+}
+
+/*
+ * Digital playback callbacks
+ */
+static int stac92xx_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
+					  struct hda_codec *codec,
+					  snd_pcm_substream_t *substream)
+{
+	struct sigmatel_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
+}
+
+static int stac92xx_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
+					   struct hda_codec *codec,
+					   snd_pcm_substream_t *substream)
+{
+	struct sigmatel_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
+}
+
+
+/*
+ * Analog capture callbacks
+ */
+static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
+					struct hda_codec *codec,
+					unsigned int stream_tag,
+					unsigned int format,
+					snd_pcm_substream_t *substream)
+{
+	struct sigmatel_spec *spec = codec->spec;
+
+	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
+                                   stream_tag, 0, format);
+	return 0;
+}
+
+static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+					struct hda_codec *codec,
+					snd_pcm_substream_t *substream)
+{
+	struct sigmatel_spec *spec = codec->spec;
+
+	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
+	return 0;
+}
+
+static struct hda_pcm_stream stac92xx_pcm_digital_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	/* NID is set in stac92xx_build_pcms */
+	.ops = {
+		.open = stac92xx_dig_playback_pcm_open,
+		.close = stac92xx_dig_playback_pcm_close
+	},
+};
+
+static struct hda_pcm_stream stac92xx_pcm_digital_capture = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	/* NID is set in stac92xx_build_pcms */
+};
+
+static struct hda_pcm_stream stac92xx_pcm_analog_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	.nid = 0x02, /* NID to query formats and rates */
+	.ops = {
+		.open = stac92xx_playback_pcm_open,
+		.prepare = stac92xx_playback_pcm_prepare,
+		.cleanup = stac92xx_playback_pcm_cleanup
+	},
+};
+
+static struct hda_pcm_stream stac92xx_pcm_analog_capture = {
+	.substreams = 2,
+	.channels_min = 2,
+	.channels_max = 2,
+	.nid = 0x06, /* NID to query formats and rates */
+	.ops = {
+		.prepare = stac92xx_capture_pcm_prepare,
+		.cleanup = stac92xx_capture_pcm_cleanup
+	},
+};
+
+static int stac92xx_build_pcms(struct hda_codec *codec)
+{
+	struct sigmatel_spec *spec = codec->spec;
+	struct hda_pcm *info = spec->pcm_rec;
+
+	codec->num_pcms = 1;
+	codec->pcm_info = info;
+
+	info->name = "STAC92xx";
+	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_analog_playback;
+	info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->playback_nid;
+	info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture;
+	info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->capture_nid;
+
+	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
+		codec->num_pcms++;
+		info++;
+		info->name = "STAC92xx Digital";
+		if (spec->multiout.dig_out_nid) {
+			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback;
+			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
+		}
+		if (spec->dig_in_nid) {
+			info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_digital_capture;
+			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
+		}
+	}
+
+	return 0;
+}
+
+static void stac92xx_free(struct hda_codec *codec)
+{
+	kfree(codec->spec);
+}
+
+static struct hda_codec_ops stac92xx_patch_ops = {
+	.build_controls = stac92xx_build_controls,
+	.build_pcms = stac92xx_build_pcms,
+	.init = stac92xx_init,
+	.free = stac92xx_free,
+};
+
+static int patch_stac9200(struct hda_codec *codec)
+{
+	struct sigmatel_spec *spec;
+
+	spec  = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	codec->spec = spec;
+
+	spec->multiout.max_channels = 2;
+	spec->multiout.num_dacs = 1;
+	spec->multiout.dac_nids = stac9200_dac_nids;
+	spec->multiout.dig_out_nid = 0x05;
+	spec->dig_in_nid = 0x04;
+	spec->adc_nids = stac9200_adc_nids;
+	spec->mux_nids = stac9200_mux_nids;
+	spec->num_muxes = 1;
+	spec->input_mux.num_items = 0;
+	spec->pstate_nids = stac9200_pstate_nids;
+	spec->num_pstates = 3;
+	spec->pin_nids = stac9200_pin_nids;
+#ifdef STAC_TEST
+	spec->pin_configs = stac9200_pin_configs;
+#endif
+	spec->num_pins = 8;
+	spec->init = stac9200_ch2_init;
+	spec->mixer = stac9200_mixer;
+	spec->playback_nid = 0x02;
+	spec->capture_nid = 0x03;
+
+	codec->patch_ops = stac92xx_patch_ops;
+
+	return 0;
+}
+
+static int patch_stac922x(struct hda_codec *codec)
+{
+	struct sigmatel_spec *spec;
+
+	spec  = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	codec->spec = spec;
+
+	spec->multiout.max_channels = 2;
+	spec->multiout.num_dacs = 4;
+	spec->multiout.dac_nids = stac922x_dac_nids;
+	spec->multiout.dig_out_nid = 0x08;
+	spec->dig_in_nid = 0x09;
+	spec->adc_nids = stac922x_adc_nids;
+	spec->mux_nids = stac922x_mux_nids;
+	spec->num_muxes = 2;
+	spec->input_mux.num_items = 0;
+	spec->pstate_nids = stac922x_pstate_nids;
+	spec->num_pstates = 8;
+	spec->pin_nids = stac922x_pin_nids;
+#ifdef STAC_TEST
+	spec->pin_configs = stac922x_pin_configs;
+#endif
+	spec->num_pins = 10;
+	spec->init = stac922x_ch2_init;
+	spec->mixer = stac922x_mixer;
+	spec->playback_nid = 0x02;
+	spec->capture_nid = 0x06;
+
+	codec->patch_ops = stac92xx_patch_ops;
+
+	return 0;
+}
+
+/*
+ * patch entries
+ */
+struct hda_codec_preset snd_hda_preset_sigmatel[] = {
+ 	{ .id = 0x83847690, .name = "STAC9200", .patch = patch_stac9200 },
+ 	{ .id = 0x83847882, .name = "STAC9220 A1", .patch = patch_stac922x },
+ 	{ .id = 0x83847680, .name = "STAC9221 A1", .patch = patch_stac922x },
+ 	{ .id = 0x83847880, .name = "STAC9220 A2", .patch = patch_stac922x },
+ 	{ .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 },
+	{} /* terminator */
+};
diff --git a/sound/pci/ice1712/amp.c b/sound/pci/ice1712/amp.c
index 7799517..289b0b5 100644
--- a/sound/pci/ice1712/amp.c
+++ b/sound/pci/ice1712/amp.c
@@ -30,16 +30,39 @@
 #include <sound/core.h>
 
 #include "ice1712.h"
+#include "envy24ht.h"
 #include "amp.h"
 
+static void wm_put(ice1712_t *ice, int reg, unsigned short val)
+{
+	unsigned short cval;
+	cval = (reg << 9) | val;
+	snd_vt1724_write_i2c(ice, WM_DEV, cval >> 8, cval & 0xff);
+}
 
 static int __devinit snd_vt1724_amp_init(ice1712_t *ice)
 {
+	static unsigned short wm_inits[] = {
+		WM_ATTEN_L,	0x0000,	/* 0 db */
+		WM_ATTEN_R,	0x0000,	/* 0 db */
+		WM_DAC_CTRL,	0x0008,	/* 24bit I2S */
+		WM_INT_CTRL,	0x0001, /* 24bit I2S */	
+	};
+
+	unsigned int i;
+
 	/* only use basic functionality for now */
 
 	ice->num_total_dacs = 2;	/* only PSDOUT0 is connected */
 	ice->num_total_adcs = 2;
 
+	/* Chaintech AV-710 has another codecs, which need initialization */
+	/* initialize WM8728 codec */
+	if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AV710) {
+		for (i = 0; i < ARRAY_SIZE(wm_inits); i += 2)
+			wm_put(ice, wm_inits[i], wm_inits[i+1]);
+	}
+
 	return 0;
 }
 
@@ -54,6 +77,13 @@
 /* entry point */
 struct snd_ice1712_card_info snd_vt1724_amp_cards[] __devinitdata = {
 	{
+		.subvendor = VT1724_SUBDEVICE_AV710,
+		.name = "Chaintech AV-710",
+		.model = "av710",
+		.chip_init = snd_vt1724_amp_init,
+		.build_controls = snd_vt1724_amp_add_controls,
+	},
+	{
 		.subvendor = VT1724_SUBDEVICE_AUDIO2000,
 		.name = "AMP Ltd AUDIO2000",
 		.model = "amp2000",
diff --git a/sound/pci/ice1712/amp.h b/sound/pci/ice1712/amp.h
index d58d433..a0fc89b 100644
--- a/sound/pci/ice1712/amp.h
+++ b/sound/pci/ice1712/amp.h
@@ -24,9 +24,23 @@
  *
  */      
 
-#define  AMP_AUDIO2000_DEVICE_DESC 	       "{AMP Ltd,AUDIO2000},"
+#define  AMP_AUDIO2000_DEVICE_DESC 	       "{AMP Ltd,AUDIO2000},"\
+					       "{Chaintech,AV-710},"
 
+#if 0
 #define VT1724_SUBDEVICE_AUDIO2000	0x12142417	/* Advanced Micro Peripherals Ltd AUDIO2000 */
+#else
+#define VT1724_SUBDEVICE_AUDIO2000	0x00030003	/* a dummy ID for AMP Audio2000 */
+#endif
+#define VT1724_SUBDEVICE_AV710		0x12142417	/* AV710 - the same ID with Audio2000! */
+
+/* WM8728 on I2C for AV710 */
+#define WM_DEV		0x36
+
+#define WM_ATTEN_L	0x00
+#define WM_ATTEN_R	0x01
+#define WM_DAC_CTRL	0x02
+#define WM_INT_CTRL	0x03
 
 extern struct snd_ice1712_card_info  snd_vt1724_amp_cards[];
 
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index 79fba6b..a2545a5 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -2748,7 +2748,7 @@
 
 static int __init alsa_card_ice1712_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_ice1712_exit(void)
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index 8bb1c58..5ad4728 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -373,6 +373,11 @@
 			unsigned short master[2];
 			unsigned short vol[8];
 		} aureon;
+		/* AC97 register cache for Phase28 */
+		struct phase28_spec {
+			unsigned short master[2];
+			unsigned short vol[8];
+		} phase28;
 		/* Hoontech-specific setting */
 		struct hoontech_spec {
 			unsigned char boxbits[4];
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 95500f0..79b5f12 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -2328,7 +2328,7 @@
 
 static int __init alsa_card_ice1724_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_ice1724_exit(void)
diff --git a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c
index d1f9083..5bf734b 100644
--- a/sound/pci/ice1712/phase.c
+++ b/sound/pci/ice1712/phase.c
@@ -45,6 +45,47 @@
 #include "envy24ht.h"
 #include "phase.h"
 
+/* WM8770 registers */
+#define WM_DAC_ATTEN		0x00	/* DAC1-8 analog attenuation */
+#define WM_DAC_MASTER_ATTEN	0x08	/* DAC master analog attenuation */
+#define WM_DAC_DIG_ATTEN	0x09	/* DAC1-8 digital attenuation */
+#define WM_DAC_DIG_MASTER_ATTEN	0x11	/* DAC master digital attenuation */
+#define WM_PHASE_SWAP		0x12	/* DAC phase */
+#define WM_DAC_CTRL1		0x13	/* DAC control bits */
+#define WM_MUTE			0x14	/* mute controls */
+#define WM_DAC_CTRL2		0x15	/* de-emphasis and zefo-flag */
+#define WM_INT_CTRL		0x16	/* interface control */
+#define WM_MASTER		0x17	/* master clock and mode */
+#define WM_POWERDOWN		0x18	/* power-down controls */
+#define WM_ADC_GAIN		0x19	/* ADC gain L(19)/R(1a) */
+#define WM_ADC_MUX		0x1b	/* input MUX */
+#define WM_OUT_MUX1		0x1c	/* output MUX */
+#define WM_OUT_MUX2		0x1e	/* output MUX */
+#define WM_RESET		0x1f	/* software reset */
+
+
+/*
+ * Logarithmic volume values for WM8770
+ * Computed as 20 * Log10(255 / x)
+ */
+static unsigned char wm_vol[256] = {
+	127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
+	23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
+	17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
+	13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
+	11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
+	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6,
+	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+	5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3,
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+	2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0
+};
+
+#define WM_VOL_MAX	(sizeof(wm_vol) - 1)
+#define WM_VOL_MUTE	0x8000
+
 static akm4xxx_t akm_phase22 __devinitdata = {
 	.type = SND_AK4524,
 	.num_dacs = 2,
@@ -124,6 +165,684 @@
 	0x00,	/* GPIO_STATE2 */
 };
 
+static unsigned char phase28_eeprom[] __devinitdata = {
+	0x0b,	/* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
+	0x80,	/* ACLINK: I2S */
+	0xfc,	/* I2S: vol, 96k, 24bit, 192k */
+	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 */
+};
+
+/*
+ * write data in the SPI mode
+ */
+static void phase28_spi_write(ice1712_t *ice, unsigned int cs, unsigned int data, int bits)
+{
+	unsigned int tmp;
+	int i;
+
+	tmp = snd_ice1712_gpio_read(ice);
+
+	snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RW|PHASE28_SPI_MOSI|PHASE28_SPI_CLK|
+					 PHASE28_WM_CS));
+	tmp |= PHASE28_WM_RW;
+	tmp &= ~cs;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(1);
+
+	for (i = bits - 1; i >= 0; i--) {
+		tmp &= ~PHASE28_SPI_CLK;
+		snd_ice1712_gpio_write(ice, tmp);
+		udelay(1);
+		if (data & (1 << i))
+			tmp |= PHASE28_SPI_MOSI;
+		else
+			tmp &= ~PHASE28_SPI_MOSI;
+		snd_ice1712_gpio_write(ice, tmp);
+		udelay(1);
+		tmp |= PHASE28_SPI_CLK;
+		snd_ice1712_gpio_write(ice, tmp);
+		udelay(1);
+	}
+
+	tmp &= ~PHASE28_SPI_CLK;
+	tmp |= cs;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(1);
+	tmp |= PHASE28_SPI_CLK;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(1);
+}
+
+/*
+ * get the current register value of WM codec
+ */
+static unsigned short wm_get(ice1712_t *ice, int reg)
+{
+	reg <<= 1;
+	return ((unsigned short)ice->akm[0].images[reg] << 8) |
+		ice->akm[0].images[reg + 1];
+}
+
+/*
+ * set the register value of WM codec
+ */
+static void wm_put_nocache(ice1712_t *ice, int reg, unsigned short val)
+{
+	phase28_spi_write(ice, PHASE28_WM_CS, (reg << 9) | (val & 0x1ff), 16);
+}
+
+/*
+ * set the register value of WM codec and remember it
+ */
+static void wm_put(ice1712_t *ice, int reg, unsigned short val)
+{
+	wm_put_nocache(ice, reg, val);
+	reg <<= 1;
+	ice->akm[0].images[reg] = val >> 8;
+	ice->akm[0].images[reg + 1] = val;
+}
+
+static void wm_set_vol(ice1712_t *ice, unsigned int index, unsigned short vol, unsigned short master)
+{
+	unsigned char nvol;
+
+	if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
+		nvol = 0;
+	else
+		nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
+
+	wm_put(ice, index, nvol);
+	wm_put_nocache(ice, index, 0x180 | nvol);
+}
+
+/*
+ * DAC mute control
+ */
+#define wm_pcm_mute_info	phase28_mono_bool_info
+
+static int wm_pcm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+
+	down(&ice->gpio_mutex);
+	ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
+	up(&ice->gpio_mutex);
+	return 0;
+}
+
+static int wm_pcm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned short nval, oval;
+	int change;
+
+	snd_ice1712_save_gpio_status(ice);
+	oval = wm_get(ice, WM_MUTE);
+	nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
+	if ((change = (nval != oval)))
+		wm_put(ice, WM_MUTE, nval);
+	snd_ice1712_restore_gpio_status(ice);
+
+	return change;
+}
+
+/*
+ * Master volume attenuation mixer control
+ */
+static int wm_master_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 2;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = WM_VOL_MAX;
+	return 0;
+}
+
+static int wm_master_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	int i;
+	for (i=0; i<2; i++)
+		ucontrol->value.integer.value[i] = ice->spec.phase28.master[i] & ~WM_VOL_MUTE;
+	return 0;
+}
+
+static int wm_master_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	int ch, change = 0;
+
+	snd_ice1712_save_gpio_status(ice);
+	for (ch = 0; ch < 2; ch++) {
+		if (ucontrol->value.integer.value[ch] != ice->spec.phase28.master[ch]) {
+			int dac;
+			ice->spec.phase28.master[ch] &= WM_VOL_MUTE;
+			ice->spec.phase28.master[ch] |= ucontrol->value.integer.value[ch];
+			for (dac = 0; dac < ice->num_total_dacs; dac += 2)
+				wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
+					   ice->spec.phase28.vol[dac + ch],
+					   ice->spec.phase28.master[ch]);
+			change = 1;
+		}
+	}
+	snd_ice1712_restore_gpio_status(ice);
+	return change;
+}
+
+static int __devinit phase28_init(ice1712_t *ice)
+{
+	static unsigned short wm_inits_phase28[] = {
+		/* These come first to reduce init pop noise */
+		0x1b, 0x044,		/* ADC Mux (AC'97 source) */
+		0x1c, 0x00B,		/* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
+		0x1d, 0x009,		/* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
+
+		0x18, 0x000,		/* All power-up */
+
+		0x16, 0x122,		/* I2S, normal polarity, 24bit */
+		0x17, 0x022,		/* 256fs, slave mode */
+		0x00, 0,		/* DAC1 analog mute */
+		0x01, 0,		/* DAC2 analog mute */
+		0x02, 0,		/* DAC3 analog mute */
+		0x03, 0,		/* DAC4 analog mute */
+		0x04, 0,		/* DAC5 analog mute */
+		0x05, 0,		/* DAC6 analog mute */
+		0x06, 0,		/* DAC7 analog mute */
+		0x07, 0,		/* DAC8 analog mute */
+		0x08, 0x100,		/* master analog mute */
+		0x09, 0xff,		/* DAC1 digital full */
+		0x0a, 0xff,		/* DAC2 digital full */
+		0x0b, 0xff,		/* DAC3 digital full */
+		0x0c, 0xff,		/* DAC4 digital full */
+		0x0d, 0xff,		/* DAC5 digital full */
+		0x0e, 0xff,		/* DAC6 digital full */
+		0x0f, 0xff,		/* DAC7 digital full */
+		0x10, 0xff,		/* DAC8 digital full */
+		0x11, 0x1ff,		/* master digital full */
+		0x12, 0x000,		/* phase normal */
+		0x13, 0x090,		/* unmute DAC L/R */
+		0x14, 0x000,		/* all unmute */
+		0x15, 0x000,		/* no deemphasis, no ZFLG */
+		0x19, 0x000,		/* -12dB ADC/L */
+		0x1a, 0x000,		/* -12dB ADC/R */
+		(unsigned short)-1
+	};
+
+	unsigned int tmp;
+	akm4xxx_t *ak;
+	unsigned short *p;
+	int i;
+
+	ice->num_total_dacs = 8;
+	ice->num_total_adcs = 2;
+
+	// Initialize analog chips
+	ak = ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+	if (!ak)
+		return -ENOMEM;
+	ice->akm_codecs = 1;
+
+	snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
+
+	/* reset the wm codec as the SPI mode */
+	snd_ice1712_save_gpio_status(ice);
+	snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RESET|PHASE28_WM_CS|PHASE28_HP_SEL));
+
+	tmp = snd_ice1712_gpio_read(ice);
+	tmp &= ~PHASE28_WM_RESET;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(1);
+	tmp |= PHASE28_WM_CS;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(1);
+	tmp |= PHASE28_WM_RESET;
+	snd_ice1712_gpio_write(ice, tmp);
+	udelay(1);
+
+	p = wm_inits_phase28;
+	for (; *p != (unsigned short)-1; p += 2)
+		wm_put(ice, p[0], p[1]);
+
+	snd_ice1712_restore_gpio_status(ice);
+
+	ice->spec.phase28.master[0] = WM_VOL_MUTE;
+	ice->spec.phase28.master[1] = WM_VOL_MUTE;
+	for (i = 0; i < ice->num_total_dacs; i++) {
+		ice->spec.phase28.vol[i] = WM_VOL_MUTE;
+		wm_set_vol(ice, i, ice->spec.phase28.vol[i], ice->spec.phase28.master[i % 2]);
+	}
+
+	return 0;
+}
+
+/*
+ * DAC volume attenuation mixer control
+ */
+static int wm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	int voices = kcontrol->private_value >> 8;
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = voices;
+	uinfo->value.integer.min = 0;		/* mute (-101dB) */
+	uinfo->value.integer.max = 0x7F;	/* 0dB */
+	return 0;
+}
+
+static int wm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	int i, ofs, voices;
+
+	voices = kcontrol->private_value >> 8;
+	ofs = kcontrol->private_value & 0xff;
+	for (i = 0; i < voices; i++)
+		ucontrol->value.integer.value[i] = ice->spec.phase28.vol[ofs+i] & ~WM_VOL_MUTE;
+	return 0;
+}
+
+static int wm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	int i, idx, ofs, voices;
+	int change = 0;
+
+	voices = kcontrol->private_value >> 8;
+	ofs = kcontrol->private_value & 0xff;
+	snd_ice1712_save_gpio_status(ice);
+	for (i = 0; i < voices; i++) {
+		idx  = WM_DAC_ATTEN + ofs + i;
+		if (ucontrol->value.integer.value[i] != ice->spec.phase28.vol[ofs+i]) {
+			ice->spec.phase28.vol[ofs+i] &= WM_VOL_MUTE;
+			ice->spec.phase28.vol[ofs+i] |= ucontrol->value.integer.value[i];
+			wm_set_vol(ice, idx, ice->spec.phase28.vol[ofs+i],
+				   ice->spec.phase28.master[i]);
+			change = 1;
+		}
+	}
+	snd_ice1712_restore_gpio_status(ice);
+	return change;
+}
+
+/*
+ * WM8770 mute control
+ */
+static int wm_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = kcontrol->private_value >> 8;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int wm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	int voices, ofs, i;
+
+	voices = kcontrol->private_value >> 8;
+	ofs = kcontrol->private_value & 0xFF;
+
+	for (i = 0; i < voices; i++)
+		ucontrol->value.integer.value[i] = (ice->spec.phase28.vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1;
+	return 0;
+}
+
+static int wm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	int change = 0, voices, ofs, i;
+
+	voices = kcontrol->private_value >> 8;
+	ofs = kcontrol->private_value & 0xFF;
+
+	snd_ice1712_save_gpio_status(ice);
+	for (i = 0; i < voices; i++) {
+		int val = (ice->spec.phase28.vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
+		if (ucontrol->value.integer.value[i] != val) {
+			ice->spec.phase28.vol[ofs + i] &= ~WM_VOL_MUTE;
+			ice->spec.phase28.vol[ofs + i] |=
+				ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
+			wm_set_vol(ice, ofs + i, ice->spec.phase28.vol[ofs + i],
+				   ice->spec.phase28.master[i]);
+			change = 1;
+		}
+	}
+	snd_ice1712_restore_gpio_status(ice);
+
+	return change;
+}
+
+/*
+ * WM8770 master mute control
+ */
+static int wm_master_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *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 wm_master_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.integer.value[0] = (ice->spec.phase28.master[0] & WM_VOL_MUTE) ? 0 : 1;
+	ucontrol->value.integer.value[1] = (ice->spec.phase28.master[1] & WM_VOL_MUTE) ? 0 : 1;
+	return 0;
+}
+
+static int wm_master_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	int change = 0, i;
+
+	snd_ice1712_save_gpio_status(ice);
+	for (i = 0; i < 2; i++) {
+		int val = (ice->spec.phase28.master[i] & WM_VOL_MUTE) ? 0 : 1;
+		if (ucontrol->value.integer.value[i] != val) {
+			int dac;
+			ice->spec.phase28.master[i] &= ~WM_VOL_MUTE;
+			ice->spec.phase28.master[i] |=
+				ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
+			for (dac = 0; dac < ice->num_total_dacs; dac += 2)
+				wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
+					   ice->spec.phase28.vol[dac + i],
+					   ice->spec.phase28.master[i]);
+			change = 1;
+		}
+	}
+	snd_ice1712_restore_gpio_status(ice);
+
+	return change;
+}
+
+/* digital master volume */
+#define PCM_0dB 0xff
+#define PCM_RES 128	/* -64dB */
+#define PCM_MIN (PCM_0dB - PCM_RES)
+static int wm_pcm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;		/* mute (-64dB) */
+	uinfo->value.integer.max = PCM_RES;	/* 0dB */
+	return 0;
+}
+
+static int wm_pcm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned short val;
+
+	down(&ice->gpio_mutex);
+	val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
+	val = val > PCM_MIN ? (val - PCM_MIN) : 0;
+	ucontrol->value.integer.value[0] = val;
+	up(&ice->gpio_mutex);
+	return 0;
+}
+
+static int wm_pcm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	unsigned short ovol, nvol;
+	int change = 0;
+
+	snd_ice1712_save_gpio_status(ice);
+	nvol = ucontrol->value.integer.value[0];
+	nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
+	ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
+	if (ovol != nvol) {
+		wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
+		wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
+		change = 1;
+	}
+	snd_ice1712_restore_gpio_status(ice);
+	return change;
+}
+
+/*
+ */
+static int phase28_mono_bool_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+/*
+ * Deemphasis
+ */
+#define phase28_deemp_info	phase28_mono_bool_info
+
+static int phase28_deemp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
+	return 0;
+}
+
+static int phase28_deemp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	int temp, temp2;
+	temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
+	if (ucontrol->value.integer.value[0])
+		temp |= 0xf;
+	else
+		temp &= ~0xf;
+	if (temp != temp2) {
+		wm_put(ice, WM_DAC_CTRL2, temp);
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * ADC Oversampling
+ */
+static int phase28_oversampling_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
+{
+	static char *texts[2] = { "128x", "64x"	};
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+
+        return 0;
+}
+
+static int phase28_oversampling_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+	ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
+	return 0;
+}
+
+static int phase28_oversampling_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	int temp, temp2;
+	ice1712_t *ice = snd_kcontrol_chip(kcontrol);
+
+	temp2 = temp = wm_get(ice, WM_MASTER);
+
+	if (ucontrol->value.enumerated.item[0])
+		temp |= 0x8;
+	else
+		temp &= ~0x8;
+
+	if (temp != temp2) {
+		wm_put(ice, WM_MASTER, temp);
+		return 1;
+	}
+	return 0;
+}
+
+static snd_kcontrol_new_t phase28_dac_controls[] __devinitdata = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Switch",
+		.info = wm_master_mute_info,
+		.get = wm_master_mute_get,
+		.put = wm_master_mute_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Volume",
+		.info = wm_master_vol_info,
+		.get = wm_master_vol_get,
+		.put = wm_master_vol_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Front Playback Switch",
+		.info = wm_mute_info,
+		.get = wm_mute_get,
+		.put = wm_mute_put,
+		.private_value = (2 << 8) | 0
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Front Playback Volume",
+		.info = wm_vol_info,
+		.get = wm_vol_get,
+		.put = wm_vol_put,
+		.private_value = (2 << 8) | 0
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Rear Playback Switch",
+		.info = wm_mute_info,
+		.get = wm_mute_get,
+		.put = wm_mute_put,
+		.private_value = (2 << 8) | 2
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Rear Playback Volume",
+		.info = wm_vol_info,
+		.get = wm_vol_get,
+		.put = wm_vol_put,
+		.private_value = (2 << 8) | 2
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Center Playback Switch",
+		.info = wm_mute_info,
+		.get = wm_mute_get,
+		.put = wm_mute_put,
+		.private_value = (1 << 8) | 4
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Center Playback Volume",
+		.info = wm_vol_info,
+		.get = wm_vol_get,
+		.put = wm_vol_put,
+		.private_value = (1 << 8) | 4
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "LFE Playback Switch",
+		.info = wm_mute_info,
+		.get = wm_mute_get,
+		.put = wm_mute_put,
+		.private_value = (1 << 8) | 5
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "LFE Playback Volume",
+		.info = wm_vol_info,
+		.get = wm_vol_get,
+		.put = wm_vol_put,
+		.private_value = (1 << 8) | 5
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Side Playback Switch",
+		.info = wm_mute_info,
+		.get = wm_mute_get,
+		.put = wm_mute_put,
+		.private_value = (2 << 8) | 6
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Side Playback Volume",
+		.info = wm_vol_info,
+		.get = wm_vol_get,
+		.put = wm_vol_put,
+		.private_value = (2 << 8) | 6
+	}
+};
+
+static snd_kcontrol_new_t wm_controls[] __devinitdata = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "PCM Playback Switch",
+		.info = wm_pcm_mute_info,
+		.get = wm_pcm_mute_get,
+		.put = wm_pcm_mute_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "PCM Playback Volume",
+		.info = wm_pcm_vol_info,
+		.get = wm_pcm_vol_get,
+		.put = wm_pcm_vol_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "DAC Deemphasis Switch",
+		.info = phase28_deemp_info,
+		.get = phase28_deemp_get,
+		.put = phase28_deemp_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "ADC Oversampling",
+		.info = phase28_oversampling_info,
+		.get = phase28_oversampling_get,
+		.put = phase28_oversampling_put
+	}
+};
+
+static int __devinit phase28_add_controls(ice1712_t *ice)
+{
+	unsigned int i, counts;
+	int err;
+
+	counts = ARRAY_SIZE(phase28_dac_controls);
+	for (i = 0; i < counts; i++) {
+		err = snd_ctl_add(ice->card, snd_ctl_new1(&phase28_dac_controls[i], ice));
+		if (err < 0)
+			return err;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
+		err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
+		if (err < 0)
+			return err;
+	}
+
+	return 0;
+}
+
 struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = {
 	{
 		.subvendor = VT1724_SUBDEVICE_PHASE22,
@@ -134,5 +853,14 @@
 		.eeprom_size = sizeof(phase22_eeprom),
 		.eeprom_data = phase22_eeprom,
 	},
+	{
+		.subvendor = VT1724_SUBDEVICE_PHASE28,
+		.name = "Terratec PHASE 28",
+		.model = "phase28",
+		.chip_init = phase28_init,
+		.build_controls = phase28_add_controls,
+		.eeprom_size = sizeof(phase28_eeprom),
+		.eeprom_data = phase28_eeprom,
+	},
 	{ } /* terminator */
 };
diff --git a/sound/pci/ice1712/phase.h b/sound/pci/ice1712/phase.h
index 6230cf1..13e841b 100644
--- a/sound/pci/ice1712/phase.h
+++ b/sound/pci/ice1712/phase.h
@@ -24,11 +24,28 @@
  *
  */      
 
-#define PHASE_DEVICE_DESC "{Terratec,Phase 22},"
+#define PHASE_DEVICE_DESC "{Terratec,Phase 22},"\
+                          "{Terratec,Phase 28},"
 
 #define VT1724_SUBDEVICE_PHASE22	0x3b155011
+#define VT1724_SUBDEVICE_PHASE28	0x3b154911
 
 /* entry point */
 extern struct snd_ice1712_card_info snd_vt1724_phase_cards[];
 
+/* PHASE28 GPIO bits */
+#define PHASE28_SPI_MISO	(1 << 21)
+#define PHASE28_WM_RESET	(1 << 20)
+#define PHASE28_SPI_CLK		(1 << 19)
+#define PHASE28_SPI_MOSI	(1 << 18)
+#define PHASE28_WM_RW		(1 << 17)
+#define PHASE28_AC97_RESET	(1 << 16)
+#define PHASE28_DIGITAL_SEL1	(1 << 15)
+#define PHASE28_HP_SEL		(1 << 14)
+#define PHASE28_WM_CS		(1 << 12)
+#define PHASE28_AC97_COMMIT	(1 << 11)
+#define PHASE28_AC97_ADDR	(1 << 10)
+#define PHASE28_AC97_DATA_LOW	(1 << 9)
+#define PHASE28_AC97_DATA_HIGH	(1 << 8)
+#define PHASE28_AC97_DATA_MASK	0xFF
 #endif /* __SOUND_PHASE */
diff --git a/sound/pci/ice1712/vt1720_mobo.c b/sound/pci/ice1712/vt1720_mobo.c
index 3bd9262..ab61e38 100644
--- a/sound/pci/ice1712/vt1720_mobo.c
+++ b/sound/pci/ice1712/vt1720_mobo.c
@@ -110,6 +110,15 @@
 		.eeprom_size = sizeof(k8x800_eeprom),
 		.eeprom_data = k8x800_eeprom,
 	},
+	{
+		.subvendor = VT1720_SUBDEVICE_SN25P,
+		.name = "Shuttle SN25P",
+		/* identical with k8x800 */
+		.chip_init = k8x800_init,
+		.build_controls = k8x800_add_controls,
+		.eeprom_size = sizeof(k8x800_eeprom),
+		.eeprom_data = k8x800_eeprom,
+	},
 	{ } /* terminator */
 };
 
diff --git a/sound/pci/ice1712/vt1720_mobo.h b/sound/pci/ice1712/vt1720_mobo.h
index f949eb8..0b1b0ee 100644
--- a/sound/pci/ice1712/vt1720_mobo.h
+++ b/sound/pci/ice1712/vt1720_mobo.h
@@ -27,12 +27,14 @@
 #define VT1720_MOBO_DEVICE_DESC        "{Albatron,K8X800 Pro II},"\
 				       "{Chaintech,ZNF3-150},"\
 				       "{Chaintech,ZNF3-250},"\
-				       "{Chaintech,9CJS},"
+				       "{Chaintech,9CJS},"\
+				       "{Shuttle,SN25P},"
 
 #define VT1720_SUBDEVICE_K8X800		0xf217052c
 #define VT1720_SUBDEVICE_ZNF3_150	0x0f2741f6
 #define VT1720_SUBDEVICE_ZNF3_250	0x0f2745f6
 #define VT1720_SUBDEVICE_9CJS		0x0f272327
+#define VT1720_SUBDEVICE_SN25P		0x97123650
 
 extern struct snd_ice1712_card_info  snd_vt1720_mobo_cards[];
 
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 8b33b12..cc16f95 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -1725,229 +1725,235 @@
 
 static struct ac97_quirk ac97_quirks[] __devinitdata = {
 	{
-		.vendor = 0x0e11,
-		.device = 0x008a,
+		.subvendor = 0x0e11,
+		.subdevice = 0x008a,
 		.name = "Compaq Evo W4000",	/* AD1885 */
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x0e11,
-		.device = 0x00b8,
+		.subvendor = 0x0e11,
+		.subdevice = 0x00b8,
 		.name = "Compaq Evo D510C",
 		.type = AC97_TUNE_HP_ONLY
 	},
         {
-		.vendor = 0x0e11,
-		.device = 0x0860,
+		.subvendor = 0x0e11,
+		.subdevice = 0x0860,
 		.name = "HP/Compaq nx7010",
 		.type = AC97_TUNE_MUTE_LED
         },
 	{
-		.vendor = 0x1014,
-		.device = 0x1f00,
+		.subvendor = 0x1014,
+		.subdevice = 0x1f00,
 		.name = "MS-9128",
 		.type = AC97_TUNE_ALC_JACK
 	},
 	{
-		.vendor = 0x1028,
-		.device = 0x00d8,
+		.subvendor = 0x1028,
+		.subdevice = 0x00d8,
 		.name = "Dell Precision 530",	/* AD1885 */
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x1028,
-		.device = 0x010d,
+		.subvendor = 0x1028,
+		.subdevice = 0x010d,
 		.name = "Dell",	/* which model?  AD1885 */
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x1028,
-		.device = 0x0126,
+		.subvendor = 0x1028,
+		.subdevice = 0x0126,
 		.name = "Dell Optiplex GX260",	/* AD1981A */
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x1028,
-		.device = 0x012c,
+		.subvendor = 0x1028,
+		.subdevice = 0x012c,
 		.name = "Dell Precision 650",	/* AD1981A */
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x1028,
-		.device = 0x012d,
+		.subvendor = 0x1028,
+		.subdevice = 0x012d,
 		.name = "Dell Precision 450",	/* AD1981B*/
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x1028,
-		.device = 0x0147,
+		.subvendor = 0x1028,
+		.subdevice = 0x0147,
 		.name = "Dell",	/* which model?  AD1981B*/
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x1028,
-		.device = 0x0163,
+		.subvendor = 0x1028,
+		.subdevice = 0x0163,
 		.name = "Dell Unknown",	/* STAC9750/51 */
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x103c,
-		.device = 0x006d,
+		.subvendor = 0x103c,
+		.subdevice = 0x006d,
 		.name = "HP zv5000",
 		.type = AC97_TUNE_MUTE_LED	/*AD1981B*/
 	},
 	{	/* FIXME: which codec? */
-		.vendor = 0x103c,
-		.device = 0x00c3,
+		.subvendor = 0x103c,
+		.subdevice = 0x00c3,
 		.name = "HP xw6000",
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x103c,
-		.device = 0x088c,
+		.subvendor = 0x103c,
+		.subdevice = 0x088c,
 		.name = "HP nc8000",
 		.type = AC97_TUNE_MUTE_LED
 	},
 	{
-		.vendor = 0x103c,
-		.device = 0x0890,
+		.subvendor = 0x103c,
+		.subdevice = 0x0890,
 		.name = "HP nc6000",
 		.type = AC97_TUNE_MUTE_LED
 	},
 	{
-		.vendor = 0x103c,
-		.device = 0x129d,
+		.subvendor = 0x103c,
+		.subdevice = 0x129d,
 		.name = "HP xw8000",
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x103c,
-		.device = 0x12f1,
+		.subvendor = 0x103c,
+		.subdevice = 0x12f1,
 		.name = "HP xw8200",	/* AD1981B*/
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x103c,
-		.device = 0x12f2,
+		.subvendor = 0x103c,
+		.subdevice = 0x12f2,
 		.name = "HP xw6200",
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x103c,
-		.device = 0x3008,
+		.subvendor = 0x103c,
+		.subdevice = 0x3008,
 		.name = "HP xw4200",	/* AD1981B*/
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x104d,
-		.device = 0x8197,
+		.subvendor = 0x104d,
+		.subdevice = 0x8197,
 		.name = "Sony S1XP",
 		.type = AC97_TUNE_INV_EAPD
 	},
  	{
-		.vendor = 0x1043,
-		.device = 0x80f3,
+		.subvendor = 0x1043,
+		.subdevice = 0x80f3,
 		.name = "ASUS ICH5/AD1985",
 		.type = AC97_TUNE_AD_SHARING
 	},
 	{
-		.vendor = 0x10cf,
-		.device = 0x11c3,
+		.subvendor = 0x10cf,
+		.subdevice = 0x11c3,
 		.name = "Fujitsu-Siemens E4010",
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x10cf,
-		.device = 0x1253,
+		.subvendor = 0x10cf,
+		.subdevice = 0x1225,
+		.name = "Fujitsu-Siemens T3010",
+		.type = AC97_TUNE_HP_ONLY
+	},
+	{
+		.subvendor = 0x10cf,
+		.subdevice = 0x1253,
 		.name = "Fujitsu S6210",	/* STAC9750/51 */
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x10f1,
-		.device = 0x2665,
+		.subvendor = 0x10f1,
+		.subdevice = 0x2665,
 		.name = "Fujitsu-Siemens Celsius",	/* AD1981? */
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x10f1,
-		.device = 0x2885,
+		.subvendor = 0x10f1,
+		.subdevice = 0x2885,
 		.name = "AMD64 Mobo",	/* ALC650 */
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x110a,
-		.device = 0x0056,
+		.subvendor = 0x110a,
+		.subdevice = 0x0056,
 		.name = "Fujitsu-Siemens Scenic",	/* AD1981? */
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x11d4,
-		.device = 0x5375,
+		.subvendor = 0x11d4,
+		.subdevice = 0x5375,
 		.name = "ADI AD1985 (discrete)",
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x1462,
-		.device = 0x5470,
+		.subvendor = 0x1462,
+		.subdevice = 0x5470,
 		.name = "MSI P4 ATX 645 Ultra",
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x1734,
-		.device = 0x0088,
+		.subvendor = 0x1734,
+		.subdevice = 0x0088,
 		.name = "Fujitsu-Siemens D1522",	/* AD1981 */
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x8086,
-		.device = 0x2000,
+		.subvendor = 0x8086,
+		.subdevice = 0x2000,
 		.mask = 0xfff0,
 		.name = "Intel ICH5/AD1985",
 		.type = AC97_TUNE_AD_SHARING
 	},
 	{
-		.vendor = 0x8086,
-		.device = 0x4000,
+		.subvendor = 0x8086,
+		.subdevice = 0x4000,
 		.mask = 0xfff0,
 		.name = "Intel ICH5/AD1985",
 		.type = AC97_TUNE_AD_SHARING
 	},
 	{
-		.vendor = 0x8086,
-		.device = 0x4856,
+		.subvendor = 0x8086,
+		.subdevice = 0x4856,
 		.name = "Intel D845WN (82801BA)",
 		.type = AC97_TUNE_SWAP_HP
 	},
 	{
-		.vendor = 0x8086,
-		.device = 0x4d44,
+		.subvendor = 0x8086,
+		.subdevice = 0x4d44,
 		.name = "Intel D850EMV2",	/* AD1885 */
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x8086,
-		.device = 0x4d56,
+		.subvendor = 0x8086,
+		.subdevice = 0x4d56,
 		.name = "Intel ICH/AD1885",
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x8086,
-		.device = 0x6000,
+		.subvendor = 0x8086,
+		.subdevice = 0x6000,
 		.mask = 0xfff0,
 		.name = "Intel ICH5/AD1985",
 		.type = AC97_TUNE_AD_SHARING
 	},
 	{
-		.vendor = 0x8086,
-		.device = 0xe000,
+		.subvendor = 0x8086,
+		.subdevice = 0xe000,
 		.mask = 0xfff0,
 		.name = "Intel ICH5/AD1985",
 		.type = AC97_TUNE_AD_SHARING
 	},
 #if 0 /* FIXME: this seems wrong on most boards */
 	{
-		.vendor = 0x8086,
-		.device = 0xa000,
+		.subvendor = 0x8086,
+		.subdevice = 0xa000,
 		.mask = 0xfff0,
 		.name = "Intel ICH5/AD1985",
 		.type = AC97_TUNE_HP_ONLY
@@ -2849,7 +2855,7 @@
 
 static int __init alsa_card_intel8x0_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_intel8x0_exit(void)
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index 67da096..bb758c7 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -35,7 +35,6 @@
 #include <sound/pcm.h>
 #include <sound/ac97_codec.h>
 #include <sound/info.h>
-#include <sound/control.h>
 #include <sound/initval.h>
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
@@ -292,60 +291,9 @@
 #endif
 	{ 0, }
 };
-static int snd_intel8x0m_switch_default_get(snd_kcontrol_t *kcontrol,
-					    snd_ctl_elem_value_t *ucontrol);
-static int snd_intel8x0m_switch_default_put(snd_kcontrol_t *kcontrol,
-					    snd_ctl_elem_value_t *ucontrol);
-static int snd_intel8x0m_switch_default_info(snd_kcontrol_t *kcontrol,
-					     snd_ctl_elem_info_t *uinfo);
-
-#define PRIVATE_VALUE_INITIALIZER(r,m) (((r) & 0xffff) << 16 | ((m) & 0xffff))
-#define PRIVATE_VALUE_MASK(control) ((control)->private_value & 0xffff)
-#define PRIVATE_VALUE_REG(control) (((control)->private_value >> 16) & 0xffff)
-
-static snd_kcontrol_new_t snd_intel8x0m_mixer_switches[] __devinitdata = {
-  { .name  = "Off-hook Switch",
-    .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-    .info  = snd_intel8x0m_switch_default_info,
-    .get   = snd_intel8x0m_switch_default_get,
-    .put   = snd_intel8x0m_switch_default_put,
-    .private_value = PRIVATE_VALUE_INITIALIZER(AC97_GPIO_STATUS,AC97_GPIO_LINE1_OH)
-  }
-};
 
 MODULE_DEVICE_TABLE(pci, snd_intel8x0m_ids);
 
-static int snd_intel8x0m_switch_default_info(snd_kcontrol_t *kcontrol,
-					     snd_ctl_elem_info_t *uinfo)
-{
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
-	uinfo->count = 1;
-	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = 1;
-	return 0;
-}
-
-static int snd_intel8x0m_switch_default_get(snd_kcontrol_t *kcontrol,
-					    snd_ctl_elem_value_t *ucontrol)
-{
-	unsigned short mask = PRIVATE_VALUE_MASK(kcontrol);
-	unsigned short reg = PRIVATE_VALUE_REG(kcontrol);
-	intel8x0_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned int status;
-	status = snd_ac97_read(chip->ac97, reg) & mask ? 1 : 0;
-	ucontrol->value.integer.value[0] = status;
-	return 0;
-}
-static int snd_intel8x0m_switch_default_put(snd_kcontrol_t *kcontrol,
-					    snd_ctl_elem_value_t *ucontrol)
-{
-	unsigned short mask = PRIVATE_VALUE_MASK(kcontrol);
-	unsigned short reg = PRIVATE_VALUE_REG(kcontrol);
-	intel8x0_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned short new_status = ucontrol->value.integer.value[0] ? mask : ~mask;
-	return snd_ac97_update_bits(chip->ac97, reg,
-				    mask, new_status);
-}
 /*
  *  Lowlevel I/O - busmaster
  */
@@ -500,6 +448,8 @@
 			res = 0xffff;
 		}
 	}
+	if (reg == AC97_GPIO_STATUS)
+		iagetword(chip, 0); /* clear semaphore */
 	return res;
 }
 
@@ -698,21 +648,6 @@
 	return bytes_to_frames(substream->runtime, ptr);
 }
 
-static int snd_intel8x0m_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
-{
-	/* hook off/on on start/stop */
-	/* Moved this to mixer control */
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		break;
-	case SNDRV_PCM_TRIGGER_STOP:
-		break;
-	default:
-		return -EINVAL;
-	}
-	return snd_intel8x0_pcm_trigger(substream,cmd);
-}
-
 static int snd_intel8x0m_pcm_prepare(snd_pcm_substream_t * substream)
 {
 	intel8x0_t *chip = snd_pcm_substream_chip(substream);
@@ -808,7 +743,7 @@
 	.hw_params =	snd_intel8x0_hw_params,
 	.hw_free =	snd_intel8x0_hw_free,
 	.prepare =	snd_intel8x0m_pcm_prepare,
-	.trigger =	snd_intel8x0m_pcm_trigger,
+	.trigger =	snd_intel8x0_pcm_trigger,
 	.pointer =	snd_intel8x0_pcm_pointer,
 };
 
@@ -819,7 +754,7 @@
 	.hw_params =	snd_intel8x0_hw_params,
 	.hw_free =	snd_intel8x0_hw_free,
 	.prepare =	snd_intel8x0m_pcm_prepare,
-	.trigger =	snd_intel8x0m_pcm_trigger,
+	.trigger =	snd_intel8x0_pcm_trigger,
 	.pointer =	snd_intel8x0_pcm_pointer,
 };
 
@@ -947,7 +882,6 @@
 	ac97_t *x97;
 	int err;
 	unsigned int glob_sta = 0;
-	unsigned int idx;
 	static ac97_bus_ops_t ops = {
 		.write = snd_intel8x0_codec_write,
 		.read = snd_intel8x0_codec_read,
@@ -983,10 +917,6 @@
 		chip->ichd[ICHD_MDMIN].ac97 = x97;
 		chip->ichd[ICHD_MDMOUT].ac97 = x97;
 	}
-	for (idx = 0; idx < ARRAY_SIZE(snd_intel8x0m_mixer_switches); idx++) {
-		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_intel8x0m_mixer_switches[idx], chip))) < 0)
-			goto __err;
-	}
 
 	chip->in_ac97_init = 0;
 	return 0;
@@ -1450,7 +1380,7 @@
 
 static int __init alsa_card_intel8x0m_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_intel8x0m_exit(void)
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index bb1de20..79d8eda 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -2541,7 +2541,7 @@
 
 static int __init alsa_card_korg1212_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_korg1212_exit(void)
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 2cf3308..096f151 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -779,6 +779,12 @@
 				   (e.g. for IrDA on Dell Inspirons) */
 };
 
+struct m3_hv_quirk {
+	u16 vendor, device, subsystem_vendor, subsystem_device;
+	u32 config;		/* ALLEGRO_CONFIG hardware volume bits */
+	int is_omnibook;	/* Do HP OmniBook GPIO magic? */
+};
+
 struct m3_list {
 	int curlen;
 	int mem_addr;
@@ -828,6 +834,7 @@
 
 	struct pci_dev *pci;
 	struct m3_quirk *quirk;
+	struct m3_hv_quirk *hv_quirk;
 
 	int dacs_active;
 	int timer_users;
@@ -851,6 +858,11 @@
 	m3_dma_t *substreams;
 
 	spinlock_t reg_lock;
+	spinlock_t ac97_lock;
+
+	snd_kcontrol_t *master_switch;
+	snd_kcontrol_t *master_volume;
+	struct tasklet_struct hwvol_tq;
 
 #ifdef CONFIG_PM
 	u16 *suspend_mem;
@@ -968,6 +980,71 @@
 	{ NULL }
 };
 
+/* These values came from the Windows driver. */
+static struct m3_hv_quirk m3_hv_quirk_list[] = {
+	/* Allegro chips */
+	{ 0x125D, 0x1988, 0x0E11, 0x002E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x0E11, 0x0094, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x0E11, 0xB112, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x0E11, 0xB114, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x103C, 0x0012, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x103C, 0x0018, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x103C, 0x001C, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x103C, 0x001D, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x103C, 0x001E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x107B, 0x3350, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x10F7, 0x8338, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x10F7, 0x833C, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x10F7, 0x833D, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x10F7, 0x833E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x10F7, 0x833F, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x13BD, 0x1018, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x13BD, 0x1019, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x13BD, 0x101A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x14FF, 0x0F03, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x14FF, 0x0F04, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x14FF, 0x0F05, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x156D, 0xB400, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x156D, 0xB795, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x156D, 0xB797, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x156D, 0xC700, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 },
+	{ 0x125D, 0x1988, 0x1033, 0x80F1, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+	{ 0x125D, 0x1988, 0x103C, 0x001A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, /* HP OmniBook 6100 */
+	{ 0x125D, 0x1988, 0x107B, 0x340A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+	{ 0x125D, 0x1988, 0x107B, 0x3450, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+	{ 0x125D, 0x1988, 0x109F, 0x3134, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+	{ 0x125D, 0x1988, 0x109F, 0x3161, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+	{ 0x125D, 0x1988, 0x144D, 0x3280, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+	{ 0x125D, 0x1988, 0x144D, 0x3281, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+	{ 0x125D, 0x1988, 0x144D, 0xC002, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+	{ 0x125D, 0x1988, 0x144D, 0xC003, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+	{ 0x125D, 0x1988, 0x1509, 0x1740, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+	{ 0x125D, 0x1988, 0x1610, 0x0010, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 },
+	{ 0x125D, 0x1988, 0x1042, 0x1042, HV_CTRL_ENABLE, 0 },
+	{ 0x125D, 0x1988, 0x107B, 0x9500, HV_CTRL_ENABLE, 0 },
+	{ 0x125D, 0x1988, 0x14FF, 0x0F06, HV_CTRL_ENABLE, 0 },
+	{ 0x125D, 0x1988, 0x1558, 0x8586, HV_CTRL_ENABLE, 0 },
+	{ 0x125D, 0x1988, 0x161F, 0x2011, HV_CTRL_ENABLE, 0 },
+	/* Maestro3 chips */
+	{ 0x125D, 0x1998, 0x103C, 0x000E, HV_CTRL_ENABLE, 0 },
+	{ 0x125D, 0x1998, 0x103C, 0x0010, HV_CTRL_ENABLE, 1 }, /* HP OmniBook 6000 */
+	{ 0x125D, 0x1998, 0x103C, 0x0011, HV_CTRL_ENABLE, 1 }, /* HP OmniBook 500 */
+	{ 0x125D, 0x1998, 0x103C, 0x001B, HV_CTRL_ENABLE, 0 },
+	{ 0x125D, 0x1998, 0x104D, 0x80A6, HV_CTRL_ENABLE, 0 },
+	{ 0x125D, 0x1998, 0x104D, 0x80AA, HV_CTRL_ENABLE, 0 },
+	{ 0x125D, 0x1998, 0x107B, 0x5300, HV_CTRL_ENABLE, 0 },
+	{ 0x125D, 0x1998, 0x110A, 0x1998, HV_CTRL_ENABLE, 0 },
+	{ 0x125D, 0x1998, 0x13BD, 0x1015, HV_CTRL_ENABLE, 0 },
+	{ 0x125D, 0x1998, 0x13BD, 0x101C, HV_CTRL_ENABLE, 0 },
+	{ 0x125D, 0x1998, 0x13BD, 0x1802, HV_CTRL_ENABLE, 0 },
+	{ 0x125D, 0x1998, 0x1599, 0x0715, HV_CTRL_ENABLE, 0 },
+	{ 0x125D, 0x1998, 0x5643, 0x5643, HV_CTRL_ENABLE, 0 },
+	{ 0x125D, 0x199A, 0x144D, 0x3260, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
+	{ 0x125D, 0x199A, 0x144D, 0x3261, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
+	{ 0x125D, 0x199A, 0x144D, 0xC000, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
+	{ 0x125D, 0x199A, 0x144D, 0xC001, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 },
+	{ 0 }
+};
 
 /*
  * lowlevel functions
@@ -1565,6 +1642,68 @@
 	}
 }
 
+static void snd_m3_update_hw_volume(unsigned long private_data)
+{
+	m3_t *chip = (m3_t *) private_data;
+	int x, val;
+	unsigned long flags;
+
+	/* Figure out which volume control button was pushed,
+	   based on differences from the default register
+	   values. */
+	x = inb(chip->iobase + SHADOW_MIX_REG_VOICE) & 0xee;
+
+	/* Reset the volume control registers. */
+	outb(0x88, chip->iobase + SHADOW_MIX_REG_VOICE);
+	outb(0x88, chip->iobase + HW_VOL_COUNTER_VOICE);
+	outb(0x88, chip->iobase + SHADOW_MIX_REG_MASTER);
+	outb(0x88, chip->iobase + HW_VOL_COUNTER_MASTER);
+
+	if (!chip->master_switch || !chip->master_volume)
+		return;
+
+	/* FIXME: we can't call snd_ac97_* functions since here is in tasklet. */
+	spin_lock_irqsave(&chip->ac97_lock, flags);
+
+	val = chip->ac97->regs[AC97_MASTER_VOL];
+	switch (x) {
+	case 0x88:
+		/* mute */
+		val ^= 0x8000;
+		chip->ac97->regs[AC97_MASTER_VOL] = val;
+		outw(val, chip->iobase + CODEC_DATA);
+		outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND);
+		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+			       &chip->master_switch->id);
+		break;
+	case 0xaa:
+		/* volume up */
+		if ((val & 0x7f) > 0)
+			val--;
+		if ((val & 0x7f00) > 0)
+			val -= 0x0100;
+		chip->ac97->regs[AC97_MASTER_VOL] = val;
+		outw(val, chip->iobase + CODEC_DATA);
+		outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND);
+		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+			       &chip->master_volume->id);
+		break;
+	case 0x66:
+		/* volume down */
+		if ((val & 0x7f) < 0x1f)
+			val++;
+		if ((val & 0x7f00) < 0x1f00)
+			val += 0x0100;
+		chip->ac97->regs[AC97_MASTER_VOL] = val;
+		outw(val, chip->iobase + CODEC_DATA);
+		outb(AC97_MASTER_VOL, chip->iobase + CODEC_COMMAND);
+		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+			       &chip->master_volume->id);
+		break;
+	}
+	spin_unlock_irqrestore(&chip->ac97_lock, flags);
+}
+
 static irqreturn_t
 snd_m3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
@@ -1576,7 +1715,10 @@
 
 	if (status == 0xff)
 		return IRQ_NONE;
-   
+
+	if (status & HV_INT_PENDING)
+		tasklet_hi_schedule(&chip->hwvol_tq);
+
 	/*
 	 * ack an assp int if its running
 	 * and has an int pending
@@ -1605,7 +1747,7 @@
 #endif
 
 	/* ack ints */
-	snd_m3_outw(chip, HOST_INT_STATUS, status);
+	outb(status, chip->iobase + HOST_INT_STATUS);
 
 	return IRQ_HANDLED;
 }
@@ -1842,24 +1984,32 @@
 snd_m3_ac97_read(ac97_t *ac97, unsigned short reg)
 {
 	m3_t *chip = ac97->private_data;
+	unsigned long flags;
+	unsigned short data;
 
 	if (snd_m3_ac97_wait(chip))
 		return 0xffff;
+	spin_lock_irqsave(&chip->ac97_lock, flags);
 	snd_m3_outb(chip, 0x80 | (reg & 0x7f), CODEC_COMMAND);
 	if (snd_m3_ac97_wait(chip))
 		return 0xffff;
-	return snd_m3_inw(chip, CODEC_DATA);
+	data = snd_m3_inw(chip, CODEC_DATA);
+	spin_unlock_irqrestore(&chip->ac97_lock, flags);
+	return data;
 }
 
 static void
 snd_m3_ac97_write(ac97_t *ac97, unsigned short reg, unsigned short val)
 {
 	m3_t *chip = ac97->private_data;
+	unsigned long flags;
 
 	if (snd_m3_ac97_wait(chip))
 		return;
+	spin_lock_irqsave(&chip->ac97_lock, flags);
 	snd_m3_outw(chip, val, CODEC_DATA);
 	snd_m3_outb(chip, reg & 0x7f, CODEC_COMMAND);
+	spin_unlock_irqrestore(&chip->ac97_lock, flags);
 }
 
 
@@ -1968,6 +2118,7 @@
 {
 	ac97_bus_t *pbus;
 	ac97_template_t ac97;
+	snd_ctl_elem_id_t id;
 	int err;
 	static ac97_bus_ops_t ops = {
 		.write = snd_m3_ac97_write,
@@ -1988,6 +2139,15 @@
 	schedule_timeout(HZ / 10);
 	snd_ac97_write(chip->ac97, AC97_PCM, 0);
 
+	memset(&id, 0, sizeof(id));
+	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+	strcpy(id.name, "Master Playback Switch");
+	chip->master_switch = snd_ctl_find_id(chip->card, &id);
+	memset(&id, 0, sizeof(id));
+	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+	strcpy(id.name, "Master Playback Volume");
+	chip->master_volume = snd_ctl_find_id(chip->card, &id);
+
 	return 0;
 }
 
@@ -2293,6 +2453,7 @@
 snd_m3_chip_init(m3_t *chip)
 {
 	struct pci_dev *pcidev = chip->pci;
+	unsigned long io = chip->iobase;
 	u32 n;
 	u16 w;
 	u8 t; /* makes as much sense as 'n', no? */
@@ -2303,8 +2464,27 @@
 	       DISABLE_LEGACY);
 	pci_write_config_word(pcidev, PCI_LEGACY_AUDIO_CTRL, w);
 
+	if (chip->hv_quirk && chip->hv_quirk->is_omnibook) {
+		/*
+		 * Volume buttons on some HP OmniBook laptops don't work
+		 * correctly. This makes them work for the most part.
+		 *
+		 * Volume up and down buttons on the laptop side work.
+		 * Fn+cursor_up (volme up) works.
+		 * Fn+cursor_down (volume down) doesn't work.
+		 * Fn+F7 (mute) works acts as volume up.
+		 */
+		outw(~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_MASK);
+		outw(inw(io + GPIO_DIRECTION) & ~(GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DIRECTION);
+		outw((GPI_VOL_DOWN|GPI_VOL_UP), io + GPIO_DATA);
+		outw(0xffff, io + GPIO_MASK);
+	}
 	pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n);
-	n &= REDUCED_DEBOUNCE;
+	n &= ~(HV_CTRL_ENABLE | REDUCED_DEBOUNCE | HV_BUTTON_FROM_GD);
+	if (chip->hv_quirk)
+		n |= chip->hv_quirk->config;
+	/* For some reason we must always use reduced debounce. */
+	n |= REDUCED_DEBOUNCE;
 	n |= PM_CTRL_ENABLE | CLK_DIV_BY_49 | USE_PCI_TIMING;
 	pci_write_config_dword(pcidev, PCI_ALLEGRO_CONFIG, n);
 
@@ -2332,6 +2512,12 @@
 
 	outb(RUN_ASSP, chip->iobase + ASSP_CONTROL_B); 
 
+	outb(0x00, io + HARDWARE_VOL_CTRL);
+	outb(0x88, io + SHADOW_MIX_REG_VOICE);
+	outb(0x88, io + HW_VOL_COUNTER_VOICE);
+	outb(0x88, io + SHADOW_MIX_REG_MASTER);
+	outb(0x88, io + HW_VOL_COUNTER_MASTER);
+
 	return 0;
 } 
 
@@ -2341,7 +2527,7 @@
 	unsigned long io = chip->iobase;
 
 	/* TODO: MPU401 not supported yet */
-	outw(ASSP_INT_ENABLE /*| MPU401_INT_ENABLE*/, io + HOST_INT_CTRL);
+	outw(ASSP_INT_ENABLE | HV_INT_ENABLE /*| MPU401_INT_ENABLE*/, io + HOST_INT_CTRL);
 	outb(inb(io + ASSP_CONTROL_C) | ASSP_HOST_INT_ENABLE,
 	     io + ASSP_CONTROL_C);
 }
@@ -2367,7 +2553,7 @@
 		kfree(chip->substreams);
 	}
 	if (chip->iobase) {
-		snd_m3_outw(chip, HOST_INT_CTRL, 0); /* disable ints */
+		outw(0, chip->iobase + HOST_INT_CTRL); /* disable ints */
 	}
 
 #ifdef CONFIG_PM
@@ -2486,7 +2672,7 @@
 	m3_t *chip;
 	int i, err;
 	struct m3_quirk *quirk;
-	u16 subsystem_vendor, subsystem_device;
+	struct m3_hv_quirk *hv_quirk;
 	static snd_device_ops_t ops = {
 		.dev_free =	snd_m3_dev_free,
 	};
@@ -2524,18 +2710,25 @@
 	chip->pci = pci;
 	chip->irq = -1;
 
-	pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
-	pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device);
-
 	for (quirk = m3_quirk_list; quirk->vendor; quirk++) {
-		if (subsystem_vendor == quirk->vendor &&
-		    subsystem_device == quirk->device) {
+		if (pci->subsystem_vendor == quirk->vendor &&
+		    pci->subsystem_device == quirk->device) {
 			printk(KERN_INFO "maestro3: enabled hack for '%s'\n", quirk->name);
 			chip->quirk = quirk;
 			break;
 		}
 	}
 
+	for (hv_quirk = m3_hv_quirk_list; hv_quirk->vendor; hv_quirk++) {
+		if (pci->vendor == hv_quirk->vendor &&
+		    pci->device == hv_quirk->device &&
+		    pci->subsystem_vendor == hv_quirk->subsystem_vendor &&
+		    pci->subsystem_device == hv_quirk->subsystem_device) {
+			chip->hv_quirk = hv_quirk;
+			break;
+		}
+	}
+
 	chip->external_amp = enable_amp;
 	if (amp_gpio >= 0 && amp_gpio <= 0x0f)
 		chip->amp_gpio = amp_gpio;
@@ -2593,6 +2786,9 @@
 		return err;
 	}
 
+	spin_lock_init(&chip->ac97_lock);
+	tasklet_init(&chip->hwvol_tq, snd_m3_update_hw_volume, (unsigned long)chip);
+
 	if ((err = snd_m3_mixer(chip)) < 0)
 		return err;
 
@@ -2702,7 +2898,7 @@
 	
 static int __init alsa_card_m3_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_m3_exit(void)
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index 65bb0f4..082c0d0 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -1431,7 +1431,7 @@
 
 static int __init alsa_card_mixart_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_mixart_exit(void)
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 356fbea..8a52091 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -1645,7 +1645,7 @@
 
 static int __init alsa_card_nm256_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_nm256_exit(void)
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index b96acd5..b7b554d 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -2031,7 +2031,7 @@
 
 static int __init alsa_card_rme32_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_rme32_exit(void)
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 8e26668..10c4f45 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -2437,7 +2437,7 @@
 
 static int __init alsa_card_rme96_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_rme96_exit(void)
diff --git a/sound/pci/rme9652/Makefile b/sound/pci/rme9652/Makefile
index 917374c..d2c294e 100644
--- a/sound/pci/rme9652/Makefile
+++ b/sound/pci/rme9652/Makefile
@@ -5,7 +5,9 @@
 
 snd-rme9652-objs := rme9652.o
 snd-hdsp-objs := hdsp.o
+snd-hdspm-objs := hdspm.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_RME9652) += snd-rme9652.o
 obj-$(CONFIG_SND_HDSP) += snd-hdsp.o
+obj-$(CONFIG_SND_HDSPM) +=snd-hdspm.o
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 12efbf0..a673cc4 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -559,18 +559,22 @@
 {
 	dmab->dev.type = SNDRV_DMA_TYPE_DEV;
 	dmab->dev.dev = snd_dma_pci_data(pci);
-	if (! snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
-		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
-					size, dmab) < 0)
-			return -ENOMEM;
+	if (snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
+		if (dmab->bytes >= size)
+			return 0;
 	}
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				size, dmab) < 0)
+		return -ENOMEM;
 	return 0;
 }
 
 static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
 {
-	if (dmab->area)
+	if (dmab->area) {
+		dmab->dev.dev = NULL; /* make it anonymous */
 		snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci));
+	}
 }
 
 
@@ -4912,19 +4916,9 @@
 		release_firmware(fw);
 		return -EINVAL;
 	}
-#ifdef SNDRV_BIG_ENDIAN
-	{
-		int i;
-		u32 *src = (u32*)fw->data;
-		for (i = 0; i < ARRAY_SIZE(hdsp->firmware_cache); i++, src++)
-			hdsp->firmware_cache[i] = ((*src & 0x000000ff) << 16) |
-				((*src & 0x0000ff00) << 8)  |
-				((*src & 0x00ff0000) >> 8)  |
-				((*src & 0xff000000) >> 16);
-	}
-#else
+
 	memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache));
-#endif
+
 	release_firmware(fw);
 		
 	hdsp->state |= HDSP_FirmwareCached;
@@ -5194,7 +5188,7 @@
 
 static int __init alsa_card_hdsp_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_hdsp_exit(void)
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
new file mode 100644
index 0000000..9e86d0e
--- /dev/null
+++ b/sound/pci/rme9652/hdspm.c
@@ -0,0 +1,3671 @@
+/*   -*- linux-c -*-
+ *
+ *   ALSA driver for RME Hammerfall DSP MADI audio interface(s)
+ *
+ *      Copyright (c) 2003 Winfried Ritsch (IEM)
+ *      code based on hdsp.c   Paul Davis
+ *                             Marcus Andersson
+ *                             Thomas Charbonnel
+ *
+ *   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/interrupt.h>
+#include <linux/moduleparam.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/info.h>
+#include <sound/asoundef.h>
+#include <sound/rawmidi.h>
+#include <sound/hwdep.h>
+#include <sound/initval.h>
+
+#include <sound/hdspm.h>
+
+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 */
+
+/* Disable precise pointer at start */
+static int precise_ptr[SNDRV_CARDS];
+
+/* Send all playback to line outs */
+static int line_outs_monitor[SNDRV_CARDS];
+
+/* Enable Analog Outs on Channel 63/64 by default */
+static int enable_monitor[SNDRV_CARDS];
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for RME HDSPM interface.");
+
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for RME HDSPM interface.");
+
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable/disable specific HDSPM soundcards.");
+
+module_param_array(precise_ptr, bool, NULL, 0444);
+MODULE_PARM_DESC(precise_ptr, "Enable precise pointer, or disable.");
+
+module_param_array(line_outs_monitor, bool, NULL, 0444);
+MODULE_PARM_DESC(line_outs_monitor,
+		 "Send playback streams to analog outs by default.");
+
+module_param_array(enable_monitor, bool, NULL, 0444);
+MODULE_PARM_DESC(enable_monitor,
+		 "Enable Analog Out on Channel 63/64 by default.");
+
+MODULE_AUTHOR
+      ("Winfried Ritsch <ritsch_AT_iem.at>, Paul Davis <paul@linuxaudiosystems.com>, "
+       "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>");
+MODULE_DESCRIPTION("RME HDSPM");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
+
+/* --- Write registers. --- 
+  These are defined as byte-offsets from the iobase value.  */
+
+#define HDSPM_controlRegister	     64
+#define HDSPM_interruptConfirmation  96
+#define HDSPM_control2Reg	     256  /* not in specs ???????? */
+#define HDSPM_midiDataOut0  	     352  /* just believe in old code */
+#define HDSPM_midiDataOut1  	     356
+
+/* DMA enable for 64 channels, only Bit 0 is relevant */
+#define HDSPM_outputEnableBase       512  /* 512-767  input  DMA */ 
+#define HDSPM_inputEnableBase        768  /* 768-1023 output DMA */
+
+/* 16 page addresses for each of the 64 channels DMA buffer in and out 
+   (each 64k=16*4k) Buffer must be 4k aligned (which is default i386 ????) */
+#define HDSPM_pageAddressBufferOut       8192
+#define HDSPM_pageAddressBufferIn        (HDSPM_pageAddressBufferOut+64*16*4)
+
+#define HDSPM_MADI_mixerBase    32768	/* 32768-65535 for 2x64x64 Fader */
+
+#define HDSPM_MATRIX_MIXER_SIZE  8192	/* = 2*64*64 * 4 Byte => 32kB */
+
+/* --- Read registers. ---
+   These are defined as byte-offsets from the iobase value */
+#define HDSPM_statusRegister    0
+#define HDSPM_statusRegister2  96
+
+#define HDSPM_midiDataIn0     360
+#define HDSPM_midiDataIn1     364
+
+/* status is data bytes in MIDI-FIFO (0-128) */
+#define HDSPM_midiStatusOut0  384	
+#define HDSPM_midiStatusOut1  388	
+#define HDSPM_midiStatusIn0   392	
+#define HDSPM_midiStatusIn1   396	
+
+
+/* the meters are regular i/o-mapped registers, but offset
+   considerably from the rest. the peak registers are reset
+   when read; the least-significant 4 bits are full-scale counters; 
+   the actual peak value is in the most-significant 24 bits.
+*/
+#define HDSPM_MADI_peakrmsbase 	4096	/* 4096-8191 2x64x32Bit Meters */
+
+/* --- Control Register bits --------- */
+#define HDSPM_Start                (1<<0) /* start engine */
+
+#define HDSPM_Latency0             (1<<1) /* buffer size = 2^n */
+#define HDSPM_Latency1             (1<<2) /* where n is defined */
+#define HDSPM_Latency2             (1<<3) /* by Latency{2,1,0} */
+
+#define HDSPM_ClockModeMaster      (1<<4) /* 1=Master, 0=Slave/Autosync */
+
+#define HDSPM_AudioInterruptEnable (1<<5) /* what do you think ? */
+
+#define HDSPM_Frequency0  (1<<6)  /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */
+#define HDSPM_Frequency1  (1<<7)  /* 0=32kHz/64kHz */
+#define HDSPM_DoubleSpeed (1<<8)  /* 0=normal speed, 1=double speed */
+#define HDSPM_QuadSpeed   (1<<31) /* quad speed bit, not implemented now */
+
+#define HDSPM_TX_64ch     (1<<10) /* Output 64channel MODE=1,
+				     56channelMODE=0 */
+
+#define HDSPM_AutoInp     (1<<11) /* Auto Input (takeover) == Safe Mode, 
+                                     0=off, 1=on  */
+
+#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax */
+#define HDSPM_InputSelect1 (1<<15) /* should be 0 */
+
+#define HDSPM_SyncRef0     (1<<16) /* 0=WOrd, 1=MADI */
+#define HDSPM_SyncRef1     (1<<17) /* should be 0 */
+
+#define HDSPM_clr_tms      (1<<19) /* clear track marker, do not use 
+                                      AES additional bits in
+				      lower 5 Audiodatabits ??? */
+
+#define HDSPM_Midi0InterruptEnable (1<<22)
+#define HDSPM_Midi1InterruptEnable (1<<23)
+
+#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */
+
+
+/* --- bit helper defines */
+#define HDSPM_LatencyMask    (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)
+#define HDSPM_FrequencyMask  (HDSPM_Frequency0|HDSPM_Frequency1)
+#define HDSPM_InputMask      (HDSPM_InputSelect0|HDSPM_InputSelect1)
+#define HDSPM_InputOptical   0
+#define HDSPM_InputCoaxial   (HDSPM_InputSelect0)
+#define HDSPM_SyncRefMask    (HDSPM_SyncRef0|HDSPM_SyncRef1)
+#define HDSPM_SyncRef_Word   0
+#define HDSPM_SyncRef_MADI   (HDSPM_SyncRef0)
+
+#define HDSPM_SYNC_FROM_WORD 0	/* Preferred sync reference */
+#define HDSPM_SYNC_FROM_MADI 1	/* choices - used by "pref_sync_ref" */
+
+#define HDSPM_Frequency32KHz    HDSPM_Frequency0
+#define HDSPM_Frequency44_1KHz  HDSPM_Frequency1
+#define HDSPM_Frequency48KHz   (HDSPM_Frequency1|HDSPM_Frequency0)
+#define HDSPM_Frequency64KHz   (HDSPM_DoubleSpeed|HDSPM_Frequency0)
+#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1)
+#define HDSPM_Frequency96KHz   (HDSPM_DoubleSpeed|HDSPM_Frequency1|HDSPM_Frequency0)
+
+/* --- for internal discrimination */
+#define HDSPM_CLOCK_SOURCE_AUTOSYNC          0	/* Sample Clock Sources */
+#define HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ    1
+#define HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ  2
+#define HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ    3
+#define HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ    4
+#define HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ  5
+#define HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ    6
+#define HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ   7
+#define HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ 8
+#define HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ   9
+
+/* Synccheck Status */
+#define HDSPM_SYNC_CHECK_NO_LOCK 0
+#define HDSPM_SYNC_CHECK_LOCK    1
+#define HDSPM_SYNC_CHECK_SYNC	 2
+
+/* AutoSync References - used by "autosync_ref" control switch */
+#define HDSPM_AUTOSYNC_FROM_WORD      0
+#define HDSPM_AUTOSYNC_FROM_MADI      1
+#define HDSPM_AUTOSYNC_FROM_NONE      2
+
+/* Possible sources of MADI input */
+#define HDSPM_OPTICAL 0		/* optical   */
+#define HDSPM_COAXIAL 1		/* BNC */
+
+#define hdspm_encode_latency(x)       (((x)<<1) & HDSPM_LatencyMask)
+#define hdspm_decode_latency(x)       (((x) & HDSPM_LatencyMask)>>1)
+
+#define hdspm_encode_in(x) (((x)&0x3)<<14)
+#define hdspm_decode_in(x) (((x)>>14)&0x3)
+
+/* --- control2 register bits --- */
+#define HDSPM_TMS             (1<<0)
+#define HDSPM_TCK             (1<<1)
+#define HDSPM_TDI             (1<<2)
+#define HDSPM_JTAG            (1<<3)
+#define HDSPM_PWDN            (1<<4)
+#define HDSPM_PROGRAM	      (1<<5)
+#define HDSPM_CONFIG_MODE_0   (1<<6)
+#define HDSPM_CONFIG_MODE_1   (1<<7)
+/*#define HDSPM_VERSION_BIT     (1<<8) not defined any more*/
+#define HDSPM_BIGENDIAN_MODE  (1<<9)
+#define HDSPM_RD_MULTIPLE     (1<<10)
+
+/* --- Status Register bits --- */
+#define HDSPM_audioIRQPending    (1<<0)	/* IRQ is high and pending */
+#define HDSPM_RX_64ch            (1<<1)	/* Input 64chan. MODE=1, 56chn. MODE=0 */
+#define HDSPM_AB_int             (1<<2)	/* InputChannel Opt=0, Coax=1 (like inp0) */
+#define HDSPM_madiLock           (1<<3)	/* MADI Locked =1, no=0 */
+
+#define HDSPM_BufferPositionMask 0x000FFC0 /* Bit 6..15 : h/w buffer pointer */
+                                           /* since 64byte accurate last 6 bits 
+                                              are not used */
+
+#define HDSPM_madiSync          (1<<18) /* MADI is in sync */
+#define HDSPM_DoubleSpeedStatus (1<<19) /* (input) card in double speed */
+
+#define HDSPM_madiFreq0         (1<<22)	/* system freq 0=error */
+#define HDSPM_madiFreq1         (1<<23)	/* 1=32, 2=44.1 3=48 */
+#define HDSPM_madiFreq2         (1<<24)	/* 4=64, 5=88.2 6=96 */
+#define HDSPM_madiFreq3         (1<<25)	/* 7=128, 8=176.4 9=192 */
+
+#define HDSPM_BufferID          (1<<26)	/* (Double)Buffer ID toggles with Interrupt */
+#define HDSPM_midi0IRQPending   (1<<30)	/* MIDI IRQ is pending  */
+#define HDSPM_midi1IRQPending   (1<<31)	/* and aktiv */
+
+/* --- status bit helpers */
+#define HDSPM_madiFreqMask  (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2|HDSPM_madiFreq3)
+#define HDSPM_madiFreq32    (HDSPM_madiFreq0)
+#define HDSPM_madiFreq44_1  (HDSPM_madiFreq1)
+#define HDSPM_madiFreq48    (HDSPM_madiFreq0|HDSPM_madiFreq1)
+#define HDSPM_madiFreq64    (HDSPM_madiFreq2)
+#define HDSPM_madiFreq88_2  (HDSPM_madiFreq0|HDSPM_madiFreq2)
+#define HDSPM_madiFreq96    (HDSPM_madiFreq1|HDSPM_madiFreq2)
+#define HDSPM_madiFreq128   (HDSPM_madiFreq0|HDSPM_madiFreq1|HDSPM_madiFreq2)
+#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3)
+#define HDSPM_madiFreq192   (HDSPM_madiFreq3|HDSPM_madiFreq0)
+
+/* Status2 Register bits */
+
+#define HDSPM_version0 (1<<0)	/* not realy defined but I guess */
+#define HDSPM_version1 (1<<1)	/* in former cards it was ??? */
+#define HDSPM_version2 (1<<2)
+
+#define HDSPM_wcLock (1<<3)	/* Wordclock is detected and locked */
+#define HDSPM_wcSync (1<<4)	/* Wordclock is in sync with systemclock */
+
+#define HDSPM_wc_freq0 (1<<5)	/* input freq detected via autosync  */
+#define HDSPM_wc_freq1 (1<<6)	/* 001=32, 010==44.1, 011=48, */
+#define HDSPM_wc_freq2 (1<<7)	/* 100=64, 101=88.2, 110=96, */
+/* missing Bit   for               111=128, 1000=176.4, 1001=192 */
+
+#define HDSPM_SelSyncRef0 (1<<8)	/* Sync Source in slave mode */
+#define HDSPM_SelSyncRef1 (1<<9)	/* 000=word, 001=MADI, */
+#define HDSPM_SelSyncRef2 (1<<10)	/* 111=no valid signal */
+
+#define HDSPM_wc_valid (HDSPM_wcLock|HDSPM_wcSync)
+
+#define HDSPM_wcFreqMask  (HDSPM_wc_freq0|HDSPM_wc_freq1|HDSPM_wc_freq2)
+#define HDSPM_wcFreq32    (HDSPM_wc_freq0)
+#define HDSPM_wcFreq44_1  (HDSPM_wc_freq1)
+#define HDSPM_wcFreq48    (HDSPM_wc_freq0|HDSPM_wc_freq1)
+#define HDSPM_wcFreq64    (HDSPM_wc_freq2)
+#define HDSPM_wcFreq88_2  (HDSPM_wc_freq0|HDSPM_wc_freq2)
+#define HDSPM_wcFreq96    (HDSPM_wc_freq1|HDSPM_wc_freq2)
+
+
+#define HDSPM_SelSyncRefMask       (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2)
+#define HDSPM_SelSyncRef_WORD      0
+#define HDSPM_SelSyncRef_MADI      (HDSPM_SelSyncRef0)
+#define HDSPM_SelSyncRef_NVALID    (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2)
+
+/* Mixer Values */
+#define UNITY_GAIN          32768	/* = 65536/2 */
+#define MINUS_INFINITY_GAIN 0
+
+/* PCI info */
+#ifndef PCI_VENDOR_ID_XILINX
+#define PCI_VENDOR_ID_XILINX		0x10ee
+#endif
+#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP
+#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5
+#endif
+#ifndef PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI
+#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6
+#endif
+
+
+/* Number of channels for different Speed Modes */
+#define MADI_SS_CHANNELS       64
+#define MADI_DS_CHANNELS       32
+#define MADI_QS_CHANNELS       16
+
+/* the size of a substream (1 mono data stream) */
+#define HDSPM_CHANNEL_BUFFER_SAMPLES  (16*1024)
+#define HDSPM_CHANNEL_BUFFER_BYTES    (4*HDSPM_CHANNEL_BUFFER_SAMPLES)
+
+/* the size of the area we need to allocate for DMA transfers. the
+   size is the same regardless of the number of channels, and
+   also the latency to use. 
+   for one direction !!!
+*/
+#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
+#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
+
+typedef struct _hdspm hdspm_t;
+typedef struct _hdspm_midi hdspm_midi_t;
+
+struct _hdspm_midi {
+	hdspm_t *hdspm;
+	int id;
+	snd_rawmidi_t *rmidi;
+	snd_rawmidi_substream_t *input;
+	snd_rawmidi_substream_t *output;
+	char istimer;		/* timer in use */
+	struct timer_list timer;
+	spinlock_t lock;
+	int pending;
+};
+
+struct _hdspm {
+        spinlock_t lock;
+        snd_pcm_substream_t *capture_substream;	 /* only one playback */
+        snd_pcm_substream_t *playback_substream; /* and/or capture stream */
+
+	char *card_name;	     /* for procinfo */
+	unsigned short firmware_rev; /* dont know if relevant */
+
+	int precise_ptr;	/* use precise pointers, to be tested */
+	int monitor_outs;	/* set up monitoring outs init flag */
+
+	u32 control_register;	/* cached value */
+	u32 control2_register;	/* cached value */
+
+	hdspm_midi_t midi[2];
+	struct tasklet_struct midi_tasklet;
+
+	size_t period_bytes;
+	unsigned char ss_channels;	/* channels of card in single speed */
+	unsigned char ds_channels;	/* Double Speed */
+	unsigned char qs_channels;	/* Quad Speed */
+
+	unsigned char *playback_buffer;	/* suitably aligned address */
+	unsigned char *capture_buffer;	/* suitably aligned address */
+
+	pid_t capture_pid;	/* process id which uses capture */
+	pid_t playback_pid;	/* process id which uses capture */
+	int running;		/* running status */
+
+	int last_external_sample_rate;	/* samplerate mystic ... */
+	int last_internal_sample_rate;
+	int system_sample_rate;
+
+	char *channel_map;	/* channel map for DS and Quadspeed */
+
+	int dev;		/* Hardware vars... */
+	int irq;
+	unsigned long port;
+	void __iomem *iobase;
+
+	int irq_count;		/* for debug */
+
+	snd_card_t *card;	/* one card */
+	snd_pcm_t *pcm;		/* has one pcm */
+	snd_hwdep_t *hwdep;	/* and a hwdep for additional ioctl */
+	struct pci_dev *pci;	/* and an pci info */
+
+	/* Mixer vars */
+	snd_kcontrol_t *playback_mixer_ctls[HDSPM_MAX_CHANNELS];	/* fast alsa mixer */
+	snd_kcontrol_t *input_mixer_ctls[HDSPM_MAX_CHANNELS];	/* but input to much, so not used */
+	hdspm_mixer_t *mixer;	/* full mixer accessable over mixer ioctl or hwdep-device */
+
+};
+
+/* These tables map the ALSA channels 1..N to the channels that we
+   need to use in order to find the relevant channel buffer. RME
+   refer to this kind of mapping as between "the ADAT channel and
+   the DMA channel." We index it using the logical audio channel,
+   and the value is the DMA channel (i.e. channel buffer number)
+   where the data for that channel can be read/written from/to.
+*/
+
+static char channel_map_madi_ss[HDSPM_MAX_CHANNELS] = {
+   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,
+   48, 49, 50, 51, 52, 53, 54, 55,
+   56, 57, 58, 59, 60, 61, 62, 63
+};
+
+static char channel_map_madi_ds[HDSPM_MAX_CHANNELS] = {
+  0, 2, 4, 6, 8, 10, 12, 14,
+  16, 18, 20, 22, 24, 26, 28, 30,
+  32, 34, 36, 38, 40, 42, 44, 46,
+  48, 50, 52, 54, 56, 58, 60, 62,
+  -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, -1, -1, -1, -1, -1
+};
+
+static char channel_map_madi_qs[HDSPM_MAX_CHANNELS] = {
+  0,   4,  8, 12, 16, 20, 24,  28,  
+  32, 36, 40, 44, 48, 52, 56,  60
+  -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, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1, 
+  -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+
+static struct pci_device_id snd_hdspm_ids[] = {
+	{
+	 .vendor = PCI_VENDOR_ID_XILINX,
+	 .device = PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI,
+	 .subvendor = PCI_ANY_ID,
+	 .subdevice = PCI_ANY_ID,
+	 .class = 0,
+	 .class_mask = 0,
+	 .driver_data = 0},
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, snd_hdspm_ids);
+
+/* prototypes */
+static int __devinit snd_hdspm_create_alsa_devices(snd_card_t * card,
+						   hdspm_t * hdspm);
+static int __devinit snd_hdspm_create_pcm(snd_card_t * card,
+					  hdspm_t * hdspm);
+
+static inline void snd_hdspm_initialize_midi_flush(hdspm_t * hdspm);
+static int hdspm_update_simple_mixer_controls(hdspm_t * hdspm);
+static int hdspm_autosync_ref(hdspm_t * hdspm);
+static int snd_hdspm_set_defaults(hdspm_t * hdspm);
+static void hdspm_set_sgbuf(hdspm_t * hdspm, struct snd_sg_buf *sgbuf,
+			     unsigned int reg, int channels);
+
+/* Write/read to/from HDSPM with Adresses in Bytes
+   not words but only 32Bit writes are allowed */
+
+static inline void hdspm_write(hdspm_t * hdspm, unsigned int reg,
+			       unsigned int val)
+{
+	writel(val, hdspm->iobase + reg);
+}
+
+static inline unsigned int hdspm_read(hdspm_t * hdspm, unsigned int reg)
+{
+	return readl(hdspm->iobase + reg);
+}
+
+/* for each output channel (chan) I have an Input (in) and Playback (pb) Fader 
+   mixer is write only on hardware so we have to cache him for read 
+   each fader is a u32, but uses only the first 16 bit */
+
+static inline int hdspm_read_in_gain(hdspm_t * hdspm, unsigned int chan,
+				     unsigned int in)
+{
+	if (chan > HDSPM_MIXER_CHANNELS || in > HDSPM_MIXER_CHANNELS)
+		return 0;
+
+	return hdspm->mixer->ch[chan].in[in];
+}
+
+static inline int hdspm_read_pb_gain(hdspm_t * hdspm, unsigned int chan,
+				     unsigned int pb)
+{
+	if (chan > HDSPM_MIXER_CHANNELS || pb > HDSPM_MIXER_CHANNELS)
+		return 0;
+	return hdspm->mixer->ch[chan].pb[pb];
+}
+
+static inline int hdspm_write_in_gain(hdspm_t * hdspm, unsigned int chan,
+				      unsigned int in, unsigned short data)
+{
+	if (chan >= HDSPM_MIXER_CHANNELS || in >= HDSPM_MIXER_CHANNELS)
+		return -1;
+
+	hdspm_write(hdspm,
+		    HDSPM_MADI_mixerBase +
+		    ((in + 128 * chan) * sizeof(u32)),
+		    (hdspm->mixer->ch[chan].in[in] = data & 0xFFFF));
+	return 0;
+}
+
+static inline int hdspm_write_pb_gain(hdspm_t * hdspm, unsigned int chan,
+				      unsigned int pb, unsigned short data)
+{
+	if (chan >= HDSPM_MIXER_CHANNELS || pb >= HDSPM_MIXER_CHANNELS)
+		return -1;
+
+	hdspm_write(hdspm,
+		    HDSPM_MADI_mixerBase +
+		    ((64 + pb + 128 * chan) * sizeof(u32)),
+		    (hdspm->mixer->ch[chan].pb[pb] = data & 0xFFFF));
+	return 0;
+}
+
+
+/* enable DMA for specific channels, now available for DSP-MADI */
+static inline void snd_hdspm_enable_in(hdspm_t * hdspm, int i, int v)
+{
+	hdspm_write(hdspm, HDSPM_inputEnableBase + (4 * i), v);
+}
+
+static inline void snd_hdspm_enable_out(hdspm_t * hdspm, int i, int v)
+{
+	hdspm_write(hdspm, HDSPM_outputEnableBase + (4 * i), v);
+}
+
+/* check if same process is writing and reading */
+static inline int snd_hdspm_use_is_exclusive(hdspm_t * hdspm)
+{
+	unsigned long flags;
+	int ret = 1;
+
+	spin_lock_irqsave(&hdspm->lock, flags);
+	if ((hdspm->playback_pid != hdspm->capture_pid) &&
+	    (hdspm->playback_pid >= 0) && (hdspm->capture_pid >= 0)) {
+		ret = 0;
+	}
+	spin_unlock_irqrestore(&hdspm->lock, flags);
+	return ret;
+}
+
+/* check for external sample rate */
+static inline int hdspm_external_sample_rate(hdspm_t * hdspm)
+{
+	unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+	unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
+	unsigned int rate_bits;
+	int rate = 0;
+
+	/* if wordclock has synced freq and wordclock is valid */
+	if ((status2 & HDSPM_wcLock) != 0 &&
+	    (status & HDSPM_SelSyncRef0) == 0) {
+
+		rate_bits = status2 & HDSPM_wcFreqMask;
+
+		switch (rate_bits) {
+		case HDSPM_wcFreq32:
+			rate = 32000;
+			break;
+		case HDSPM_wcFreq44_1:
+			rate = 44100;
+			break;
+		case HDSPM_wcFreq48:
+			rate = 48000;
+			break;
+		case HDSPM_wcFreq64:
+			rate = 64000;
+			break;
+		case HDSPM_wcFreq88_2:
+			rate = 88200;
+			break;
+		case HDSPM_wcFreq96:
+			rate = 96000;
+			break;
+			/* Quadspeed Bit missing ???? */
+		default:
+			rate = 0;
+			break;
+		}
+	}
+
+	/* if rate detected and Syncref is Word than have it, word has priority to MADI */
+	if (rate != 0
+	    && (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
+		return rate;
+
+	/* maby a madi input (which is taken if sel sync is madi) */
+	if (status & HDSPM_madiLock) {
+		rate_bits = status & HDSPM_madiFreqMask;
+
+		switch (rate_bits) {
+		case HDSPM_madiFreq32:
+			rate = 32000;
+			break;
+		case HDSPM_madiFreq44_1:
+			rate = 44100;
+			break;
+		case HDSPM_madiFreq48:
+			rate = 48000;
+			break;
+		case HDSPM_madiFreq64:
+			rate = 64000;
+			break;
+		case HDSPM_madiFreq88_2:
+			rate = 88200;
+			break;
+		case HDSPM_madiFreq96:
+			rate = 96000;
+			break;
+		case HDSPM_madiFreq128:
+			rate = 128000;
+			break;
+		case HDSPM_madiFreq176_4:
+			rate = 176400;
+			break;
+		case HDSPM_madiFreq192:
+			rate = 192000;
+			break;
+		default:
+			rate = 0;
+			break;
+		}
+	}
+	return rate;
+}
+
+/* Latency function */
+static inline void hdspm_compute_period_size(hdspm_t * hdspm)
+{
+	hdspm->period_bytes =
+	    1 << ((hdspm_decode_latency(hdspm->control_register) + 8));
+}
+
+static snd_pcm_uframes_t hdspm_hw_pointer(hdspm_t * hdspm)
+{
+	int position;
+
+	position = hdspm_read(hdspm, HDSPM_statusRegister);
+
+	if (!hdspm->precise_ptr) {
+		return (position & HDSPM_BufferID) ? (hdspm->period_bytes /
+						      4) : 0;
+	}
+
+	/* hwpointer comes in bytes and is 64Bytes accurate (by docu since PCI Burst)
+	   i have experimented that it is at most 64 Byte to much for playing 
+	   so substraction of 64 byte should be ok for ALSA, but use it only
+	   for application where you know what you do since if you come to
+	   near with record pointer it can be a disaster */
+
+	position &= HDSPM_BufferPositionMask;
+	position = ((position - 64) % (2 * hdspm->period_bytes)) / 4;
+
+	return position;
+}
+
+
+static inline void hdspm_start_audio(hdspm_t * s)
+{
+	s->control_register |= (HDSPM_AudioInterruptEnable | HDSPM_Start);
+	hdspm_write(s, HDSPM_controlRegister, s->control_register);
+}
+
+static inline void hdspm_stop_audio(hdspm_t * s)
+{
+	s->control_register &= ~(HDSPM_Start | HDSPM_AudioInterruptEnable);
+	hdspm_write(s, HDSPM_controlRegister, s->control_register);
+}
+
+/* should I silence all or only opened ones ? doit all for first even is 4MB*/
+static inline void hdspm_silence_playback(hdspm_t * hdspm)
+{
+	int i;
+	int n = hdspm->period_bytes;
+	void *buf = hdspm->playback_buffer;
+
+	snd_assert(buf != NULL, return);
+
+	for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
+		memset(buf, 0, n);
+		buf += HDSPM_CHANNEL_BUFFER_BYTES;
+	}
+}
+
+static int hdspm_set_interrupt_interval(hdspm_t * s, unsigned int frames)
+{
+	int n;
+
+	spin_lock_irq(&s->lock);
+
+	frames >>= 7;
+	n = 0;
+	while (frames) {
+		n++;
+		frames >>= 1;
+	}
+	s->control_register &= ~HDSPM_LatencyMask;
+	s->control_register |= hdspm_encode_latency(n);
+
+	hdspm_write(s, HDSPM_controlRegister, s->control_register);
+
+	hdspm_compute_period_size(s);
+
+	spin_unlock_irq(&s->lock);
+
+	return 0;
+}
+
+
+/* dummy set rate lets see what happens */
+static int hdspm_set_rate(hdspm_t * hdspm, int rate, int called_internally)
+{
+	int reject_if_open = 0;
+	int current_rate;
+	int rate_bits;
+	int not_set = 0;
+
+	/* ASSUMPTION: hdspm->lock is either set, or there is no need for
+	   it (e.g. during module initialization).
+	 */
+
+	if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
+
+	        /* SLAVE --- */ 
+		if (called_internally) {
+
+        	  /* request from ctl or card initialization 
+	             just make a warning an remember setting 
+		     for future master mode switching */
+    
+			snd_printk
+			    (KERN_WARNING "HDSPM: Warning: device is not running as a clock master.\n");
+			not_set = 1;
+		} else {
+
+			/* hw_param request while in AutoSync mode */
+			int external_freq =
+			    hdspm_external_sample_rate(hdspm);
+
+			if ((hdspm_autosync_ref(hdspm) ==
+			     HDSPM_AUTOSYNC_FROM_NONE)) {
+
+				snd_printk(KERN_WARNING "HDSPM: Detected no Externel Sync \n");
+				not_set = 1;
+
+			} else if (rate != external_freq) {
+
+				snd_printk
+				    (KERN_WARNING "HDSPM: Warning: No AutoSync source for requested rate\n");
+				not_set = 1;
+			}
+		}
+	}
+
+	current_rate = hdspm->system_sample_rate;
+
+	/* Changing between Singe, Double and Quad speed is not
+	   allowed if any substreams are open. This is because such a change
+	   causes a shift in the location of the DMA buffers and a reduction
+	   in the number of available buffers.
+
+	   Note that a similar but essentially insoluble problem exists for
+	   externally-driven rate changes. All we can do is to flag rate
+	   changes in the read/write routines.  
+	 */
+
+	switch (rate) {
+	case 32000:
+		if (current_rate > 48000) {
+			reject_if_open = 1;
+		}
+		rate_bits = HDSPM_Frequency32KHz;
+		break;
+	case 44100:
+		if (current_rate > 48000) {
+			reject_if_open = 1;
+		}
+		rate_bits = HDSPM_Frequency44_1KHz;
+		break;
+	case 48000:
+		if (current_rate > 48000) {
+			reject_if_open = 1;
+		}
+		rate_bits = HDSPM_Frequency48KHz;
+		break;
+	case 64000:
+		if (current_rate <= 48000) {
+			reject_if_open = 1;
+		}
+		rate_bits = HDSPM_Frequency64KHz;
+		break;
+	case 88200:
+		if (current_rate <= 48000) {
+			reject_if_open = 1;
+		}
+		rate_bits = HDSPM_Frequency88_2KHz;
+		break;
+	case 96000:
+		if (current_rate <= 48000) {
+			reject_if_open = 1;
+		}
+		rate_bits = HDSPM_Frequency96KHz;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (reject_if_open
+	    && (hdspm->capture_pid >= 0 || hdspm->playback_pid >= 0)) {
+		snd_printk
+		    (KERN_ERR "HDSPM: cannot change between single- and double-speed mode (capture PID = %d, playback PID = %d)\n",
+		     hdspm->capture_pid, hdspm->playback_pid);
+		return -EBUSY;
+	}
+
+	hdspm->control_register &= ~HDSPM_FrequencyMask;
+	hdspm->control_register |= rate_bits;
+	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+	if (rate > 64000)
+		hdspm->channel_map = channel_map_madi_qs;
+	else if (rate > 48000)
+		hdspm->channel_map = channel_map_madi_ds;
+	else 
+		hdspm->channel_map = channel_map_madi_ss;
+
+	hdspm->system_sample_rate = rate;
+
+	if (not_set != 0)
+		return -1;
+
+	return 0;
+}
+
+/* mainly for init to 0 on load */
+static void all_in_all_mixer(hdspm_t * hdspm, int sgain)
+{
+	int i, j;
+	unsigned int gain =
+	    (sgain > UNITY_GAIN) ? UNITY_GAIN : (sgain < 0) ? 0 : sgain;
+
+	for (i = 0; i < HDSPM_MIXER_CHANNELS; i++)
+		for (j = 0; j < HDSPM_MIXER_CHANNELS; j++) {
+			hdspm_write_in_gain(hdspm, i, j, gain);
+			hdspm_write_pb_gain(hdspm, i, j, gain);
+		}
+}
+
+/*----------------------------------------------------------------------------
+   MIDI
+  ----------------------------------------------------------------------------*/
+
+static inline unsigned char snd_hdspm_midi_read_byte (hdspm_t *hdspm, int id)
+{
+	/* the hardware already does the relevant bit-mask with 0xff */
+	if (id)
+		return hdspm_read(hdspm, HDSPM_midiDataIn1);
+	else
+		return hdspm_read(hdspm, HDSPM_midiDataIn0);
+}
+
+static inline void snd_hdspm_midi_write_byte (hdspm_t *hdspm, int id, int val)
+{
+	/* the hardware already does the relevant bit-mask with 0xff */
+	if (id)
+		return hdspm_write(hdspm, HDSPM_midiDataOut1, val);
+	else
+		return hdspm_write(hdspm, HDSPM_midiDataOut0, val);
+}
+
+static inline int snd_hdspm_midi_input_available (hdspm_t *hdspm, int id)
+{
+	if (id)
+		return (hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff);
+	else
+		return (hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff);
+}
+
+static inline int snd_hdspm_midi_output_possible (hdspm_t *hdspm, int id)
+{
+	int fifo_bytes_used;
+
+	if (id)
+		fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xff;
+	else
+		fifo_bytes_used = hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xff;
+
+	if (fifo_bytes_used < 128)
+		return  128 - fifo_bytes_used;
+	else
+		return 0;
+}
+
+static inline void snd_hdspm_flush_midi_input (hdspm_t *hdspm, int id)
+{
+	while (snd_hdspm_midi_input_available (hdspm, id))
+		snd_hdspm_midi_read_byte (hdspm, id);
+}
+
+static int snd_hdspm_midi_output_write (hdspm_midi_t *hmidi)
+{
+	unsigned long flags;
+	int n_pending;
+	int to_write;
+	int i;
+	unsigned char buf[128];
+
+	/* Output is not interrupt driven */
+		
+	spin_lock_irqsave (&hmidi->lock, flags);
+	if (hmidi->output) {
+		if (!snd_rawmidi_transmit_empty (hmidi->output)) {
+			if ((n_pending = snd_hdspm_midi_output_possible (hmidi->hdspm, hmidi->id)) > 0) {
+				if (n_pending > (int)sizeof (buf))
+					n_pending = sizeof (buf);
+				
+				if ((to_write = snd_rawmidi_transmit (hmidi->output, buf, n_pending)) > 0) {
+					for (i = 0; i < to_write; ++i) 
+						snd_hdspm_midi_write_byte (hmidi->hdspm, hmidi->id, buf[i]);
+				}
+			}
+		}
+	}
+	spin_unlock_irqrestore (&hmidi->lock, flags);
+	return 0;
+}
+
+static int snd_hdspm_midi_input_read (hdspm_midi_t *hmidi)
+{
+	unsigned char buf[128]; /* this buffer is designed to match the MIDI input FIFO size */
+	unsigned long flags;
+	int n_pending;
+	int i;
+
+	spin_lock_irqsave (&hmidi->lock, flags);
+	if ((n_pending = snd_hdspm_midi_input_available (hmidi->hdspm, hmidi->id)) > 0) {
+		if (hmidi->input) {
+			if (n_pending > (int)sizeof (buf)) {
+				n_pending = sizeof (buf);
+			}
+			for (i = 0; i < n_pending; ++i) {
+				buf[i] = snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id);
+			}
+			if (n_pending) {
+				snd_rawmidi_receive (hmidi->input, buf, n_pending);
+			}
+		} else {
+			/* flush the MIDI input FIFO */
+			while (n_pending--) {
+				snd_hdspm_midi_read_byte (hmidi->hdspm, hmidi->id);
+			}
+		}
+	}
+	hmidi->pending = 0;
+	if (hmidi->id) {
+		hmidi->hdspm->control_register |= HDSPM_Midi1InterruptEnable;
+	} else {
+		hmidi->hdspm->control_register |= HDSPM_Midi0InterruptEnable;
+	}
+	hdspm_write(hmidi->hdspm, HDSPM_controlRegister, hmidi->hdspm->control_register);
+	spin_unlock_irqrestore (&hmidi->lock, flags);
+	return snd_hdspm_midi_output_write (hmidi);
+}
+
+static void snd_hdspm_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
+{
+	hdspm_t *hdspm;
+	hdspm_midi_t *hmidi;
+	unsigned long flags;
+	u32 ie;
+
+	hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+	hdspm = hmidi->hdspm;
+	ie = hmidi->id ? HDSPM_Midi1InterruptEnable : HDSPM_Midi0InterruptEnable;
+	spin_lock_irqsave (&hdspm->lock, flags);
+	if (up) {
+		if (!(hdspm->control_register & ie)) {
+			snd_hdspm_flush_midi_input (hdspm, hmidi->id);
+			hdspm->control_register |= ie;
+		}
+	} else {
+		hdspm->control_register &= ~ie;
+	}
+
+	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+	spin_unlock_irqrestore (&hdspm->lock, flags);
+}
+
+static void snd_hdspm_midi_output_timer(unsigned long data)
+{
+	hdspm_midi_t *hmidi = (hdspm_midi_t *) data;
+	unsigned long flags;
+	
+	snd_hdspm_midi_output_write(hmidi);
+	spin_lock_irqsave (&hmidi->lock, flags);
+
+	/* this does not bump hmidi->istimer, because the
+	   kernel automatically removed the timer when it
+	   expired, and we are now adding it back, thus
+	   leaving istimer wherever it was set before.  
+	*/
+
+	if (hmidi->istimer) {
+		hmidi->timer.expires = 1 + jiffies;
+		add_timer(&hmidi->timer);
+	}
+
+	spin_unlock_irqrestore (&hmidi->lock, flags);
+}
+
+static void snd_hdspm_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
+{
+	hdspm_midi_t *hmidi;
+	unsigned long flags;
+
+	hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+	spin_lock_irqsave (&hmidi->lock, flags);
+	if (up) {
+		if (!hmidi->istimer) {
+			init_timer(&hmidi->timer);
+			hmidi->timer.function = snd_hdspm_midi_output_timer;
+			hmidi->timer.data = (unsigned long) hmidi;
+			hmidi->timer.expires = 1 + jiffies;
+			add_timer(&hmidi->timer);
+			hmidi->istimer++;
+		}
+	} else {
+		if (hmidi->istimer && --hmidi->istimer <= 0) {
+			del_timer (&hmidi->timer);
+		}
+	}
+	spin_unlock_irqrestore (&hmidi->lock, flags);
+	if (up)
+		snd_hdspm_midi_output_write(hmidi);
+}
+
+static int snd_hdspm_midi_input_open(snd_rawmidi_substream_t * substream)
+{
+	hdspm_midi_t *hmidi;
+
+	hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+	spin_lock_irq (&hmidi->lock);
+	snd_hdspm_flush_midi_input (hmidi->hdspm, hmidi->id);
+	hmidi->input = substream;
+	spin_unlock_irq (&hmidi->lock);
+
+	return 0;
+}
+
+static int snd_hdspm_midi_output_open(snd_rawmidi_substream_t * substream)
+{
+	hdspm_midi_t *hmidi;
+
+	hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+	spin_lock_irq (&hmidi->lock);
+	hmidi->output = substream;
+	spin_unlock_irq (&hmidi->lock);
+
+	return 0;
+}
+
+static int snd_hdspm_midi_input_close(snd_rawmidi_substream_t * substream)
+{
+	hdspm_midi_t *hmidi;
+
+	snd_hdspm_midi_input_trigger (substream, 0);
+
+	hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+	spin_lock_irq (&hmidi->lock);
+	hmidi->input = NULL;
+	spin_unlock_irq (&hmidi->lock);
+
+	return 0;
+}
+
+static int snd_hdspm_midi_output_close(snd_rawmidi_substream_t * substream)
+{
+	hdspm_midi_t *hmidi;
+
+	snd_hdspm_midi_output_trigger (substream, 0);
+
+	hmidi = (hdspm_midi_t *) substream->rmidi->private_data;
+	spin_lock_irq (&hmidi->lock);
+	hmidi->output = NULL;
+	spin_unlock_irq (&hmidi->lock);
+
+	return 0;
+}
+
+snd_rawmidi_ops_t snd_hdspm_midi_output =
+{
+	.open =		snd_hdspm_midi_output_open,
+	.close =	snd_hdspm_midi_output_close,
+	.trigger =	snd_hdspm_midi_output_trigger,
+};
+
+snd_rawmidi_ops_t snd_hdspm_midi_input =
+{
+	.open =		snd_hdspm_midi_input_open,
+	.close =	snd_hdspm_midi_input_close,
+	.trigger =	snd_hdspm_midi_input_trigger,
+};
+
+static int __devinit snd_hdspm_create_midi (snd_card_t *card, hdspm_t *hdspm, int id)
+{
+	int err;
+	char buf[32];
+
+	hdspm->midi[id].id = id;
+	hdspm->midi[id].rmidi = NULL;
+	hdspm->midi[id].input = NULL;
+	hdspm->midi[id].output = NULL;
+	hdspm->midi[id].hdspm = hdspm;
+	hdspm->midi[id].istimer = 0;
+	hdspm->midi[id].pending = 0;
+	spin_lock_init (&hdspm->midi[id].lock);
+
+	sprintf (buf, "%s MIDI %d", card->shortname, id+1);
+	if ((err = snd_rawmidi_new (card, buf, id, 1, 1, &hdspm->midi[id].rmidi)) < 0)
+		return err;
+
+	sprintf (hdspm->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1);
+	hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
+
+	snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdspm_midi_output);
+	snd_rawmidi_set_ops (hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_hdspm_midi_input);
+
+	hdspm->midi[id].rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
+		SNDRV_RAWMIDI_INFO_INPUT |
+		SNDRV_RAWMIDI_INFO_DUPLEX;
+
+	return 0;
+}
+
+
+static void hdspm_midi_tasklet(unsigned long arg)
+{
+	hdspm_t *hdspm = (hdspm_t *)arg;
+	
+	if (hdspm->midi[0].pending)
+		snd_hdspm_midi_input_read (&hdspm->midi[0]);
+	if (hdspm->midi[1].pending)
+		snd_hdspm_midi_input_read (&hdspm->midi[1]);
+} 
+
+
+/*-----------------------------------------------------------------------------
+  Status Interface
+  ----------------------------------------------------------------------------*/
+
+/* get the system sample rate which is set */
+
+#define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .access = SNDRV_CTL_ELEM_ACCESS_READ, \
+  .info = snd_hdspm_info_system_sample_rate, \
+  .get = snd_hdspm_get_system_sample_rate \
+}
+
+static int snd_hdspm_info_system_sample_rate(snd_kcontrol_t * kcontrol,
+					     snd_ctl_elem_info_t * uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	return 0;
+}
+
+static int snd_hdspm_get_system_sample_rate(snd_kcontrol_t * kcontrol,
+					    snd_ctl_elem_value_t *
+					    ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.enumerated.item[0] = hdspm->system_sample_rate;
+	return 0;
+}
+
+#define HDSPM_AUTOSYNC_SAMPLE_RATE(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, \
+  .name = xname, \
+  .index = xindex, \
+  .access = SNDRV_CTL_ELEM_ACCESS_READ, \
+  .info = snd_hdspm_info_autosync_sample_rate, \
+  .get = snd_hdspm_get_autosync_sample_rate \
+}
+
+static int snd_hdspm_info_autosync_sample_rate(snd_kcontrol_t * kcontrol,
+					       snd_ctl_elem_info_t * uinfo)
+{
+	static char *texts[] = { "32000", "44100", "48000",
+		"64000", "88200", "96000",
+		"128000", "176400", "192000",
+		"None"
+	};
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 10;
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item =
+		    uinfo->value.enumerated.items - 1;
+	strcpy(uinfo->value.enumerated.name,
+	       texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int snd_hdspm_get_autosync_sample_rate(snd_kcontrol_t * kcontrol,
+					      snd_ctl_elem_value_t *
+					      ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+	switch (hdspm_external_sample_rate(hdspm)) {
+	case 32000:
+		ucontrol->value.enumerated.item[0] = 0;
+		break;
+	case 44100:
+		ucontrol->value.enumerated.item[0] = 1;
+		break;
+	case 48000:
+		ucontrol->value.enumerated.item[0] = 2;
+		break;
+	case 64000:
+		ucontrol->value.enumerated.item[0] = 3;
+		break;
+	case 88200:
+		ucontrol->value.enumerated.item[0] = 4;
+		break;
+	case 96000:
+		ucontrol->value.enumerated.item[0] = 5;
+		break;
+	case 128000:
+		ucontrol->value.enumerated.item[0] = 6;
+		break;
+	case 176400:
+		ucontrol->value.enumerated.item[0] = 7;
+		break;
+	case 192000:
+		ucontrol->value.enumerated.item[0] = 8;
+		break;
+
+	default:
+		ucontrol->value.enumerated.item[0] = 9;
+	}
+	return 0;
+}
+
+#define HDSPM_SYSTEM_CLOCK_MODE(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .access = SNDRV_CTL_ELEM_ACCESS_READ, \
+  .info = snd_hdspm_info_system_clock_mode, \
+  .get = snd_hdspm_get_system_clock_mode, \
+}
+
+
+
+static int hdspm_system_clock_mode(hdspm_t * hdspm)
+{
+        /* Always reflect the hardware info, rme is never wrong !!!! */
+
+	if (hdspm->control_register & HDSPM_ClockModeMaster)
+		return 0;
+	return 1;
+}
+
+static int snd_hdspm_info_system_clock_mode(snd_kcontrol_t * kcontrol,
+					    snd_ctl_elem_info_t * uinfo)
+{
+	static char *texts[] = { "Master", "Slave" };
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item =
+		    uinfo->value.enumerated.items - 1;
+	strcpy(uinfo->value.enumerated.name,
+	       texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int snd_hdspm_get_system_clock_mode(snd_kcontrol_t * kcontrol,
+					   snd_ctl_elem_value_t * ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.enumerated.item[0] =
+	    hdspm_system_clock_mode(hdspm);
+	return 0;
+}
+
+#define HDSPM_CLOCK_SOURCE(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_PCM, \
+  .name = xname, \
+  .index = xindex, \
+  .info = snd_hdspm_info_clock_source, \
+  .get = snd_hdspm_get_clock_source, \
+  .put = snd_hdspm_put_clock_source \
+}
+
+static int hdspm_clock_source(hdspm_t * hdspm)
+{
+	if (hdspm->control_register & HDSPM_ClockModeMaster) {
+		switch (hdspm->system_sample_rate) {
+		case 32000:
+			return 1;
+		case 44100:
+			return 2;
+		case 48000:
+			return 3;
+		case 64000:
+			return 4;
+		case 88200:
+			return 5;
+		case 96000:
+			return 6;
+		case 128000:
+			return 7;
+		case 176400:
+			return 8;
+		case 192000:
+			return 9;
+		default:
+			return 3;
+		}
+	} else {
+		return 0;
+	}
+}
+
+static int hdspm_set_clock_source(hdspm_t * hdspm, int mode)
+{
+	int rate;
+	switch (mode) {
+
+	case HDSPM_CLOCK_SOURCE_AUTOSYNC:
+		if (hdspm_external_sample_rate(hdspm) != 0) {
+			hdspm->control_register &= ~HDSPM_ClockModeMaster;
+			hdspm_write(hdspm, HDSPM_controlRegister,
+				    hdspm->control_register);
+			return 0;
+		}
+		return -1;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
+		rate = 32000;
+		break;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
+		rate = 44100;
+		break;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
+		rate = 48000;
+		break;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
+		rate = 64000;
+		break;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
+		rate = 88200;
+		break;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
+		rate = 96000;
+		break;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ:
+		rate = 128000;
+		break;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ:
+		rate = 176400;
+		break;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ:
+		rate = 192000;
+		break;
+
+	default:
+		rate = 44100;
+	}
+	hdspm->control_register |= HDSPM_ClockModeMaster;
+	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+	hdspm_set_rate(hdspm, rate, 1);
+	return 0;
+}
+
+static int snd_hdspm_info_clock_source(snd_kcontrol_t * kcontrol,
+				       snd_ctl_elem_info_t * uinfo)
+{
+	static char *texts[] = { "AutoSync",
+		"Internal 32.0 kHz", "Internal 44.1 kHz",
+		    "Internal 48.0 kHz",
+		"Internal 64.0 kHz", "Internal 88.2 kHz",
+		    "Internal 96.0 kHz",
+		"Internal 128.0 kHz", "Internal 176.4 kHz",
+		    "Internal 192.0 kHz"
+	};
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 10;
+
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item =
+		    uinfo->value.enumerated.items - 1;
+
+	strcpy(uinfo->value.enumerated.name,
+	       texts[uinfo->value.enumerated.item]);
+
+	return 0;
+}
+
+static int snd_hdspm_get_clock_source(snd_kcontrol_t * kcontrol,
+				      snd_ctl_elem_value_t * ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.enumerated.item[0] = hdspm_clock_source(hdspm);
+	return 0;
+}
+
+static int snd_hdspm_put_clock_source(snd_kcontrol_t * kcontrol,
+				      snd_ctl_elem_value_t * ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+	int change;
+	int val;
+
+	if (!snd_hdspm_use_is_exclusive(hdspm))
+		return -EBUSY;
+	val = ucontrol->value.enumerated.item[0];
+	if (val < 0)
+		val = 0;
+	if (val > 6)
+		val = 6;
+	spin_lock_irq(&hdspm->lock);
+	if (val != hdspm_clock_source(hdspm))
+		change = (hdspm_set_clock_source(hdspm, val) == 0) ? 1 : 0;
+	else
+		change = 0;
+	spin_unlock_irq(&hdspm->lock);
+	return change;
+}
+
+#define HDSPM_PREF_SYNC_REF(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .info = snd_hdspm_info_pref_sync_ref, \
+  .get = snd_hdspm_get_pref_sync_ref, \
+  .put = snd_hdspm_put_pref_sync_ref \
+}
+
+static int hdspm_pref_sync_ref(hdspm_t * hdspm)
+{
+	/* Notice that this looks at the requested sync source,
+	   not the one actually in use.
+	 */
+	switch (hdspm->control_register & HDSPM_SyncRefMask) {
+	case HDSPM_SyncRef_Word:
+		return HDSPM_SYNC_FROM_WORD;
+	case HDSPM_SyncRef_MADI:
+		return HDSPM_SYNC_FROM_MADI;
+	}
+
+	return HDSPM_SYNC_FROM_WORD;
+}
+
+static int hdspm_set_pref_sync_ref(hdspm_t * hdspm, int pref)
+{
+	hdspm->control_register &= ~HDSPM_SyncRefMask;
+
+	switch (pref) {
+	case HDSPM_SYNC_FROM_MADI:
+		hdspm->control_register |= HDSPM_SyncRef_MADI;
+		break;
+	case HDSPM_SYNC_FROM_WORD:
+		hdspm->control_register |= HDSPM_SyncRef_Word;
+		break;
+	default:
+		return -1;
+	}
+	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+	return 0;
+}
+
+static int snd_hdspm_info_pref_sync_ref(snd_kcontrol_t * kcontrol,
+					snd_ctl_elem_info_t * uinfo)
+{
+	static char *texts[] = { "Word", "MADI" };
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+
+	uinfo->value.enumerated.items = 2;
+
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item =
+		    uinfo->value.enumerated.items - 1;
+	strcpy(uinfo->value.enumerated.name,
+	       texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int snd_hdspm_get_pref_sync_ref(snd_kcontrol_t * kcontrol,
+				       snd_ctl_elem_value_t * ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm);
+	return 0;
+}
+
+static int snd_hdspm_put_pref_sync_ref(snd_kcontrol_t * kcontrol,
+				       snd_ctl_elem_value_t * ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+	int change, max;
+	unsigned int val;
+
+	max = 2;
+
+	if (!snd_hdspm_use_is_exclusive(hdspm))
+		return -EBUSY;
+
+	val = ucontrol->value.enumerated.item[0] % max;
+
+	spin_lock_irq(&hdspm->lock);
+	change = (int) val != hdspm_pref_sync_ref(hdspm);
+	hdspm_set_pref_sync_ref(hdspm, val);
+	spin_unlock_irq(&hdspm->lock);
+	return change;
+}
+
+#define HDSPM_AUTOSYNC_REF(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .access = SNDRV_CTL_ELEM_ACCESS_READ, \
+  .info = snd_hdspm_info_autosync_ref, \
+  .get = snd_hdspm_get_autosync_ref, \
+}
+
+static int hdspm_autosync_ref(hdspm_t * hdspm)
+{
+	/* This looks at the autosync selected sync reference */
+	unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+
+	switch (status2 & HDSPM_SelSyncRefMask) {
+
+	case HDSPM_SelSyncRef_WORD:
+		return HDSPM_AUTOSYNC_FROM_WORD;
+
+	case HDSPM_SelSyncRef_MADI:
+		return HDSPM_AUTOSYNC_FROM_MADI;
+
+	case HDSPM_SelSyncRef_NVALID:
+		return HDSPM_AUTOSYNC_FROM_NONE;
+
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+static int snd_hdspm_info_autosync_ref(snd_kcontrol_t * kcontrol,
+				       snd_ctl_elem_info_t * uinfo)
+{
+	static char *texts[] = { "WordClock", "MADI", "None" };
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 3;
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item =
+		    uinfo->value.enumerated.items - 1;
+	strcpy(uinfo->value.enumerated.name,
+	       texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int snd_hdspm_get_autosync_ref(snd_kcontrol_t * kcontrol,
+				      snd_ctl_elem_value_t * ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.enumerated.item[0] = hdspm_pref_sync_ref(hdspm);
+	return 0;
+}
+
+#define HDSPM_LINE_OUT(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .info = snd_hdspm_info_line_out, \
+  .get = snd_hdspm_get_line_out, \
+  .put = snd_hdspm_put_line_out \
+}
+
+static int hdspm_line_out(hdspm_t * hdspm)
+{
+	return (hdspm->control_register & HDSPM_LineOut) ? 1 : 0;
+}
+
+
+static int hdspm_set_line_output(hdspm_t * hdspm, int out)
+{
+	if (out)
+		hdspm->control_register |= HDSPM_LineOut;
+	else
+		hdspm->control_register &= ~HDSPM_LineOut;
+	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+	return 0;
+}
+
+static int snd_hdspm_info_line_out(snd_kcontrol_t * kcontrol,
+				   snd_ctl_elem_info_t * uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int snd_hdspm_get_line_out(snd_kcontrol_t * kcontrol,
+				  snd_ctl_elem_value_t * ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+	spin_lock_irq(&hdspm->lock);
+	ucontrol->value.integer.value[0] = hdspm_line_out(hdspm);
+	spin_unlock_irq(&hdspm->lock);
+	return 0;
+}
+
+static int snd_hdspm_put_line_out(snd_kcontrol_t * kcontrol,
+				  snd_ctl_elem_value_t * ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+	int change;
+	unsigned int val;
+
+	if (!snd_hdspm_use_is_exclusive(hdspm))
+		return -EBUSY;
+	val = ucontrol->value.integer.value[0] & 1;
+	spin_lock_irq(&hdspm->lock);
+	change = (int) val != hdspm_line_out(hdspm);
+	hdspm_set_line_output(hdspm, val);
+	spin_unlock_irq(&hdspm->lock);
+	return change;
+}
+
+#define HDSPM_TX_64(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .info = snd_hdspm_info_tx_64, \
+  .get = snd_hdspm_get_tx_64, \
+  .put = snd_hdspm_put_tx_64 \
+}
+
+static int hdspm_tx_64(hdspm_t * hdspm)
+{
+	return (hdspm->control_register & HDSPM_TX_64ch) ? 1 : 0;
+}
+
+static int hdspm_set_tx_64(hdspm_t * hdspm, int out)
+{
+	if (out)
+		hdspm->control_register |= HDSPM_TX_64ch;
+	else
+		hdspm->control_register &= ~HDSPM_TX_64ch;
+	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+	return 0;
+}
+
+static int snd_hdspm_info_tx_64(snd_kcontrol_t * kcontrol,
+				snd_ctl_elem_info_t * uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int snd_hdspm_get_tx_64(snd_kcontrol_t * kcontrol,
+			       snd_ctl_elem_value_t * ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+	spin_lock_irq(&hdspm->lock);
+	ucontrol->value.integer.value[0] = hdspm_tx_64(hdspm);
+	spin_unlock_irq(&hdspm->lock);
+	return 0;
+}
+
+static int snd_hdspm_put_tx_64(snd_kcontrol_t * kcontrol,
+			       snd_ctl_elem_value_t * ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+	int change;
+	unsigned int val;
+
+	if (!snd_hdspm_use_is_exclusive(hdspm))
+		return -EBUSY;
+	val = ucontrol->value.integer.value[0] & 1;
+	spin_lock_irq(&hdspm->lock);
+	change = (int) val != hdspm_tx_64(hdspm);
+	hdspm_set_tx_64(hdspm, val);
+	spin_unlock_irq(&hdspm->lock);
+	return change;
+}
+
+#define HDSPM_C_TMS(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .info = snd_hdspm_info_c_tms, \
+  .get = snd_hdspm_get_c_tms, \
+  .put = snd_hdspm_put_c_tms \
+}
+
+static int hdspm_c_tms(hdspm_t * hdspm)
+{
+	return (hdspm->control_register & HDSPM_clr_tms) ? 1 : 0;
+}
+
+static int hdspm_set_c_tms(hdspm_t * hdspm, int out)
+{
+	if (out)
+		hdspm->control_register |= HDSPM_clr_tms;
+	else
+		hdspm->control_register &= ~HDSPM_clr_tms;
+	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+	return 0;
+}
+
+static int snd_hdspm_info_c_tms(snd_kcontrol_t * kcontrol,
+				snd_ctl_elem_info_t * uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int snd_hdspm_get_c_tms(snd_kcontrol_t * kcontrol,
+			       snd_ctl_elem_value_t * ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+	spin_lock_irq(&hdspm->lock);
+	ucontrol->value.integer.value[0] = hdspm_c_tms(hdspm);
+	spin_unlock_irq(&hdspm->lock);
+	return 0;
+}
+
+static int snd_hdspm_put_c_tms(snd_kcontrol_t * kcontrol,
+			       snd_ctl_elem_value_t * ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+	int change;
+	unsigned int val;
+
+	if (!snd_hdspm_use_is_exclusive(hdspm))
+		return -EBUSY;
+	val = ucontrol->value.integer.value[0] & 1;
+	spin_lock_irq(&hdspm->lock);
+	change = (int) val != hdspm_c_tms(hdspm);
+	hdspm_set_c_tms(hdspm, val);
+	spin_unlock_irq(&hdspm->lock);
+	return change;
+}
+
+#define HDSPM_SAFE_MODE(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .info = snd_hdspm_info_safe_mode, \
+  .get = snd_hdspm_get_safe_mode, \
+  .put = snd_hdspm_put_safe_mode \
+}
+
+static int hdspm_safe_mode(hdspm_t * hdspm)
+{
+	return (hdspm->control_register & HDSPM_AutoInp) ? 1 : 0;
+}
+
+static int hdspm_set_safe_mode(hdspm_t * hdspm, int out)
+{
+	if (out)
+		hdspm->control_register |= HDSPM_AutoInp;
+	else
+		hdspm->control_register &= ~HDSPM_AutoInp;
+	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+	return 0;
+}
+
+static int snd_hdspm_info_safe_mode(snd_kcontrol_t * kcontrol,
+				    snd_ctl_elem_info_t * uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int snd_hdspm_get_safe_mode(snd_kcontrol_t * kcontrol,
+				   snd_ctl_elem_value_t * ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+	spin_lock_irq(&hdspm->lock);
+	ucontrol->value.integer.value[0] = hdspm_safe_mode(hdspm);
+	spin_unlock_irq(&hdspm->lock);
+	return 0;
+}
+
+static int snd_hdspm_put_safe_mode(snd_kcontrol_t * kcontrol,
+				   snd_ctl_elem_value_t * ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+	int change;
+	unsigned int val;
+
+	if (!snd_hdspm_use_is_exclusive(hdspm))
+		return -EBUSY;
+	val = ucontrol->value.integer.value[0] & 1;
+	spin_lock_irq(&hdspm->lock);
+	change = (int) val != hdspm_safe_mode(hdspm);
+	hdspm_set_safe_mode(hdspm, val);
+	spin_unlock_irq(&hdspm->lock);
+	return change;
+}
+
+#define HDSPM_INPUT_SELECT(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .info = snd_hdspm_info_input_select, \
+  .get = snd_hdspm_get_input_select, \
+  .put = snd_hdspm_put_input_select \
+}
+
+static int hdspm_input_select(hdspm_t * hdspm)
+{
+	return (hdspm->control_register & HDSPM_InputSelect0) ? 1 : 0;
+}
+
+static int hdspm_set_input_select(hdspm_t * hdspm, int out)
+{
+	if (out)
+		hdspm->control_register |= HDSPM_InputSelect0;
+	else
+		hdspm->control_register &= ~HDSPM_InputSelect0;
+	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+	return 0;
+}
+
+static int snd_hdspm_info_input_select(snd_kcontrol_t * kcontrol,
+				       snd_ctl_elem_info_t * uinfo)
+{
+	static char *texts[] = { "optical", "coaxial" };
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item =
+		    uinfo->value.enumerated.items - 1;
+	strcpy(uinfo->value.enumerated.name,
+	       texts[uinfo->value.enumerated.item]);
+
+	return 0;
+}
+
+static int snd_hdspm_get_input_select(snd_kcontrol_t * kcontrol,
+				      snd_ctl_elem_value_t * ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+	spin_lock_irq(&hdspm->lock);
+	ucontrol->value.enumerated.item[0] = hdspm_input_select(hdspm);
+	spin_unlock_irq(&hdspm->lock);
+	return 0;
+}
+
+static int snd_hdspm_put_input_select(snd_kcontrol_t * kcontrol,
+				      snd_ctl_elem_value_t * ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+	int change;
+	unsigned int val;
+
+	if (!snd_hdspm_use_is_exclusive(hdspm))
+		return -EBUSY;
+	val = ucontrol->value.integer.value[0] & 1;
+	spin_lock_irq(&hdspm->lock);
+	change = (int) val != hdspm_input_select(hdspm);
+	hdspm_set_input_select(hdspm, val);
+	spin_unlock_irq(&hdspm->lock);
+	return change;
+}
+
+/*           Simple Mixer
+  deprecated since to much faders ???
+  MIXER interface says output (source, destination, value)
+   where source > MAX_channels are playback channels 
+   on MADICARD 
+  - playback mixer matrix: [channelout+64] [output] [value]
+  - input(thru) mixer matrix: [channelin] [output] [value]
+  (better do 2 kontrols for seperation ?)
+*/
+
+#define HDSPM_MIXER(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
+		 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+  .info = snd_hdspm_info_mixer, \
+  .get = snd_hdspm_get_mixer, \
+  .put = snd_hdspm_put_mixer \
+}
+
+static int snd_hdspm_info_mixer(snd_kcontrol_t * kcontrol,
+				snd_ctl_elem_info_t * uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 3;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 65535;
+	uinfo->value.integer.step = 1;
+	return 0;
+}
+
+static int snd_hdspm_get_mixer(snd_kcontrol_t * kcontrol,
+			       snd_ctl_elem_value_t * ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+	int source;
+	int destination;
+
+	source = ucontrol->value.integer.value[0];
+	if (source < 0)
+		source = 0;
+	else if (source >= 2 * HDSPM_MAX_CHANNELS)
+		source = 2 * HDSPM_MAX_CHANNELS - 1;
+
+	destination = ucontrol->value.integer.value[1];
+	if (destination < 0)
+		destination = 0;
+	else if (destination >= HDSPM_MAX_CHANNELS)
+		destination = HDSPM_MAX_CHANNELS - 1;
+
+	spin_lock_irq(&hdspm->lock);
+	if (source >= HDSPM_MAX_CHANNELS)
+		ucontrol->value.integer.value[2] =
+		    hdspm_read_pb_gain(hdspm, destination,
+				       source - HDSPM_MAX_CHANNELS);
+	else
+		ucontrol->value.integer.value[2] =
+		    hdspm_read_in_gain(hdspm, destination, source);
+
+	spin_unlock_irq(&hdspm->lock);
+
+	return 0;
+}
+
+static int snd_hdspm_put_mixer(snd_kcontrol_t * kcontrol,
+			       snd_ctl_elem_value_t * ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+	int change;
+	int source;
+	int destination;
+	int gain;
+
+	if (!snd_hdspm_use_is_exclusive(hdspm))
+		return -EBUSY;
+
+	source = ucontrol->value.integer.value[0];
+	destination = ucontrol->value.integer.value[1];
+
+	if (source < 0 || source >= 2 * HDSPM_MAX_CHANNELS)
+		return -1;
+	if (destination < 0 || destination >= HDSPM_MAX_CHANNELS)
+		return -1;
+
+	gain = ucontrol->value.integer.value[2];
+
+	spin_lock_irq(&hdspm->lock);
+
+	if (source >= HDSPM_MAX_CHANNELS)
+		change = gain != hdspm_read_pb_gain(hdspm, destination,
+						    source -
+						    HDSPM_MAX_CHANNELS);
+	else
+		change =
+		    gain != hdspm_read_in_gain(hdspm, destination, source);
+
+	if (change) {
+		if (source >= HDSPM_MAX_CHANNELS)
+			hdspm_write_pb_gain(hdspm, destination,
+					    source - HDSPM_MAX_CHANNELS,
+					    gain);
+		else
+			hdspm_write_in_gain(hdspm, destination, source,
+					    gain);
+	}
+	spin_unlock_irq(&hdspm->lock);
+
+	return change;
+}
+
+/* The simple mixer control(s) provide gain control for the
+   basic 1:1 mappings of playback streams to output
+   streams. 
+*/
+
+#define HDSPM_PLAYBACK_MIXER \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+  .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
+		 SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+  .info = snd_hdspm_info_playback_mixer, \
+  .get = snd_hdspm_get_playback_mixer, \
+  .put = snd_hdspm_put_playback_mixer \
+}
+
+static int snd_hdspm_info_playback_mixer(snd_kcontrol_t * kcontrol,
+					 snd_ctl_elem_info_t * uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 65536;
+	uinfo->value.integer.step = 1;
+	return 0;
+}
+
+static int snd_hdspm_get_playback_mixer(snd_kcontrol_t * kcontrol,
+					snd_ctl_elem_value_t * ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+	int channel;
+	int mapped_channel;
+
+	channel = ucontrol->id.index - 1;
+
+	snd_assert(channel >= 0
+		   || channel < HDSPM_MAX_CHANNELS, return -EINVAL);
+
+	if ((mapped_channel = hdspm->channel_map[channel]) < 0)
+		return -EINVAL;
+
+	spin_lock_irq(&hdspm->lock);
+	ucontrol->value.integer.value[0] =
+	    hdspm_read_pb_gain(hdspm, mapped_channel, mapped_channel);
+	spin_unlock_irq(&hdspm->lock);
+
+	/*    snd_printdd("get pb mixer index %d, channel %d, mapped_channel %d, value %d\n",
+	   ucontrol->id.index,        channel, mapped_channel,  ucontrol->value.integer.value[0]); 
+	 */
+
+	return 0;
+}
+
+static int snd_hdspm_put_playback_mixer(snd_kcontrol_t * kcontrol,
+					snd_ctl_elem_value_t * ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+	int change;
+	int channel;
+	int mapped_channel;
+	int gain;
+
+	if (!snd_hdspm_use_is_exclusive(hdspm))
+		return -EBUSY;
+
+	channel = ucontrol->id.index - 1;
+
+	snd_assert(channel >= 0
+		   || channel < HDSPM_MAX_CHANNELS, return -EINVAL);
+
+	if ((mapped_channel = hdspm->channel_map[channel]) < 0)
+		return -EINVAL;
+
+	gain = ucontrol->value.integer.value[0];
+
+	spin_lock_irq(&hdspm->lock);
+	change =
+	    gain != hdspm_read_pb_gain(hdspm, mapped_channel,
+				       mapped_channel);
+	if (change)
+		hdspm_write_pb_gain(hdspm, mapped_channel, mapped_channel,
+				    gain);
+	spin_unlock_irq(&hdspm->lock);
+	return change;
+}
+
+#define HDSPM_WC_SYNC_CHECK(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+  .info = snd_hdspm_info_sync_check, \
+  .get = snd_hdspm_get_wc_sync_check \
+}
+
+static int snd_hdspm_info_sync_check(snd_kcontrol_t * kcontrol,
+				     snd_ctl_elem_info_t * uinfo)
+{
+	static char *texts[] = { "No Lock", "Lock", "Sync" };
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 3;
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item =
+		    uinfo->value.enumerated.items - 1;
+	strcpy(uinfo->value.enumerated.name,
+	       texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int hdspm_wc_sync_check(hdspm_t * hdspm)
+{
+	int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+	if (status2 & HDSPM_wcLock) {
+		if (status2 & HDSPM_wcSync)
+			return 2;
+		else
+			return 1;
+	}
+	return 0;
+}
+
+static int snd_hdspm_get_wc_sync_check(snd_kcontrol_t * kcontrol,
+				       snd_ctl_elem_value_t * ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.enumerated.item[0] = hdspm_wc_sync_check(hdspm);
+	return 0;
+}
+
+
+#define HDSPM_MADI_SYNC_CHECK(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+  .info = snd_hdspm_info_sync_check, \
+  .get = snd_hdspm_get_madisync_sync_check \
+}
+
+static int hdspm_madisync_sync_check(hdspm_t * hdspm)
+{
+	int status = hdspm_read(hdspm, HDSPM_statusRegister);
+	if (status & HDSPM_madiLock) {
+		if (status & HDSPM_madiSync)
+			return 2;
+		else
+			return 1;
+	}
+	return 0;
+}
+
+static int snd_hdspm_get_madisync_sync_check(snd_kcontrol_t * kcontrol,
+					     snd_ctl_elem_value_t *
+					     ucontrol)
+{
+	hdspm_t *hdspm = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.enumerated.item[0] =
+	    hdspm_madisync_sync_check(hdspm);
+	return 0;
+}
+
+
+
+
+static snd_kcontrol_new_t snd_hdspm_controls[] = {
+
+	HDSPM_MIXER("Mixer", 0),
+/* 'Sample Clock Source' complies with the alsa control naming scheme */
+	HDSPM_CLOCK_SOURCE("Sample Clock Source", 0),
+
+	HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
+	HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
+	HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
+	HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
+/* 'External Rate' complies with the alsa control naming scheme */
+	HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
+	HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0),
+	HDSPM_MADI_SYNC_CHECK("MADI Sync Lock Status", 0),
+	HDSPM_LINE_OUT("Line Out", 0),
+	HDSPM_TX_64("TX 64 channels mode", 0),
+	HDSPM_C_TMS("Clear Track Marker", 0),
+	HDSPM_SAFE_MODE("Safe Mode", 0),
+	HDSPM_INPUT_SELECT("Input Select", 0),
+};
+
+static snd_kcontrol_new_t snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
+
+
+static int hdspm_update_simple_mixer_controls(hdspm_t * hdspm)
+{
+	int i;
+
+	for (i = hdspm->ds_channels; i < hdspm->ss_channels; ++i) {
+		if (hdspm->system_sample_rate > 48000) {
+			hdspm->playback_mixer_ctls[i]->vd[0].access =
+			    SNDRV_CTL_ELEM_ACCESS_INACTIVE |
+			    SNDRV_CTL_ELEM_ACCESS_READ |
+			    SNDRV_CTL_ELEM_ACCESS_VOLATILE;
+		} else {
+			hdspm->playback_mixer_ctls[i]->vd[0].access =
+			    SNDRV_CTL_ELEM_ACCESS_READWRITE |
+			    SNDRV_CTL_ELEM_ACCESS_VOLATILE;
+		}
+		snd_ctl_notify(hdspm->card, SNDRV_CTL_EVENT_MASK_VALUE |
+			       SNDRV_CTL_EVENT_MASK_INFO,
+			       &hdspm->playback_mixer_ctls[i]->id);
+	}
+
+	return 0;
+}
+
+
+static int snd_hdspm_create_controls(snd_card_t * card, hdspm_t * hdspm)
+{
+	unsigned int idx, limit;
+	int err;
+	snd_kcontrol_t *kctl;
+
+	/* add control list first */
+
+	for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls); idx++) {
+		if ((err =
+		     snd_ctl_add(card, kctl =
+				 snd_ctl_new1(&snd_hdspm_controls[idx],
+					      hdspm))) < 0) {
+			return err;
+		}
+	}
+
+	/* Channel playback mixer as default control 
+	   Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats to big for any alsamixer 
+	   they are accesible via special IOCTL on hwdep
+	   and the mixer 2dimensional mixer control */
+
+	snd_hdspm_playback_mixer.name = "Chn";
+	limit = HDSPM_MAX_CHANNELS;
+
+	/* The index values are one greater than the channel ID so that alsamixer
+	   will display them correctly. We want to use the index for fast lookup
+	   of the relevant channel, but if we use it at all, most ALSA software
+	   does the wrong thing with it ...
+	 */
+
+	for (idx = 0; idx < limit; ++idx) {
+		snd_hdspm_playback_mixer.index = idx + 1;
+		if ((err = snd_ctl_add(card,
+				       kctl =
+				       snd_ctl_new1
+				       (&snd_hdspm_playback_mixer,
+					hdspm)))) {
+			return err;
+		}
+		hdspm->playback_mixer_ctls[idx] = kctl;
+	}
+
+	return 0;
+}
+
+/*------------------------------------------------------------
+   /proc interface 
+ ------------------------------------------------------------*/
+
+static void
+snd_hdspm_proc_read(snd_info_entry_t * entry, snd_info_buffer_t * buffer)
+{
+	hdspm_t *hdspm = (hdspm_t *) entry->private_data;
+	unsigned int status;
+	unsigned int status2;
+	char *pref_sync_ref;
+	char *autosync_ref;
+	char *system_clock_mode;
+	char *clock_source;
+	char *insel;
+	char *syncref;
+	int x, x2;
+
+	status = hdspm_read(hdspm, HDSPM_statusRegister);
+	status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
+
+	snd_iprintf(buffer, "%s (Card #%d) Rev.%x Status2first3bits: %x\n",
+		    hdspm->card_name, hdspm->card->number + 1,
+		    hdspm->firmware_rev,
+		    (status2 & HDSPM_version0) |
+		    (status2 & HDSPM_version1) | (status2 &
+						  HDSPM_version2));
+
+	snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
+		    hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
+
+	snd_iprintf(buffer, "--- System ---\n");
+
+	snd_iprintf(buffer,
+		    "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
+		    status & HDSPM_audioIRQPending,
+		    (status & HDSPM_midi0IRQPending) ? 1 : 0,
+		    (status & HDSPM_midi1IRQPending) ? 1 : 0,
+		    hdspm->irq_count);
+	snd_iprintf(buffer,
+		    "HW pointer: id = %d, rawptr = %d (%d->%d) estimated= %ld (bytes)\n",
+		    ((status & HDSPM_BufferID) ? 1 : 0),
+		    (status & HDSPM_BufferPositionMask),
+		    (status & HDSPM_BufferPositionMask) % (2 *
+							   (int)hdspm->
+							   period_bytes),
+		    ((status & HDSPM_BufferPositionMask) -
+		     64) % (2 * (int)hdspm->period_bytes),
+		    (long) hdspm_hw_pointer(hdspm) * 4);
+
+	snd_iprintf(buffer,
+		    "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
+		    hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
+		    hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
+		    hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
+		    hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
+	snd_iprintf(buffer,
+		    "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, status2=0x%x\n",
+		    hdspm->control_register, hdspm->control2_register,
+		    status, status2);
+
+	snd_iprintf(buffer, "--- Settings ---\n");
+
+	x = 1 << (6 +
+		  hdspm_decode_latency(hdspm->
+				       control_register &
+				       HDSPM_LatencyMask));
+
+	snd_iprintf(buffer,
+		    "Size (Latency): %d samples (2 periods of %lu bytes)\n",
+		    x, (unsigned long) hdspm->period_bytes);
+
+	snd_iprintf(buffer, "Line out: %s,   Precise Pointer: %s\n",
+		    (hdspm->
+		     control_register & HDSPM_LineOut) ? "on " : "off",
+		    (hdspm->precise_ptr) ? "on" : "off");
+
+	switch (hdspm->control_register & HDSPM_InputMask) {
+	case HDSPM_InputOptical:
+		insel = "Optical";
+		break;
+	case HDSPM_InputCoaxial:
+		insel = "Coaxial";
+		break;
+	default:
+		insel = "Unkown";
+	}
+
+	switch (hdspm->control_register & HDSPM_SyncRefMask) {
+	case HDSPM_SyncRef_Word:
+		syncref = "WordClock";
+		break;
+	case HDSPM_SyncRef_MADI:
+		syncref = "MADI";
+		break;
+	default:
+		syncref = "Unkown";
+	}
+	snd_iprintf(buffer, "Inputsel = %s, SyncRef = %s\n", insel,
+		    syncref);
+
+	snd_iprintf(buffer,
+		    "ClearTrackMarker = %s, Transmit in %s Channel Mode, Auto Input %s\n",
+		    (hdspm->
+		     control_register & HDSPM_clr_tms) ? "on" : "off",
+		    (hdspm->
+		     control_register & HDSPM_TX_64ch) ? "64" : "56",
+		    (hdspm->
+		     control_register & HDSPM_AutoInp) ? "on" : "off");
+
+	switch (hdspm_clock_source(hdspm)) {
+	case HDSPM_CLOCK_SOURCE_AUTOSYNC:
+		clock_source = "AutoSync";
+		break;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
+		clock_source = "Internal 32 kHz";
+		break;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
+		clock_source = "Internal 44.1 kHz";
+		break;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
+		clock_source = "Internal 48 kHz";
+		break;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
+		clock_source = "Internal 64 kHz";
+		break;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
+		clock_source = "Internal 88.2 kHz";
+		break;
+	case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
+		clock_source = "Internal 96 kHz";
+		break;
+	default:
+		clock_source = "Error";
+	}
+	snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source);
+	if (!(hdspm->control_register & HDSPM_ClockModeMaster)) {
+		system_clock_mode = "Slave";
+	} else {
+		system_clock_mode = "Master";
+	}
+	snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode);
+
+	switch (hdspm_pref_sync_ref(hdspm)) {
+	case HDSPM_SYNC_FROM_WORD:
+		pref_sync_ref = "Word Clock";
+		break;
+	case HDSPM_SYNC_FROM_MADI:
+		pref_sync_ref = "MADI Sync";
+		break;
+	default:
+		pref_sync_ref = "XXXX Clock";
+		break;
+	}
+	snd_iprintf(buffer, "Preferred Sync Reference: %s\n",
+		    pref_sync_ref);
+
+	snd_iprintf(buffer, "System Clock Frequency: %d\n",
+		    hdspm->system_sample_rate);
+
+
+	snd_iprintf(buffer, "--- Status:\n");
+
+	x = status & HDSPM_madiSync;
+	x2 = status2 & HDSPM_wcSync;
+
+	snd_iprintf(buffer, "Inputs MADI=%s, WordClock=%s\n",
+		    (status & HDSPM_madiLock) ? (x ? "Sync" : "Lock") :
+		    "NoLock",
+		    (status2 & HDSPM_wcLock) ? (x2 ? "Sync" : "Lock") :
+		    "NoLock");
+
+	switch (hdspm_autosync_ref(hdspm)) {
+	case HDSPM_AUTOSYNC_FROM_WORD:
+		autosync_ref = "Word Clock";
+		break;
+	case HDSPM_AUTOSYNC_FROM_MADI:
+		autosync_ref = "MADI Sync";
+		break;
+	case HDSPM_AUTOSYNC_FROM_NONE:
+		autosync_ref = "Input not valid";
+		break;
+	default:
+		autosync_ref = "---";
+		break;
+	}
+	snd_iprintf(buffer,
+		    "AutoSync: Reference= %s, Freq=%d (MADI = %d, Word = %d)\n",
+		    autosync_ref, hdspm_external_sample_rate(hdspm),
+		    (status & HDSPM_madiFreqMask) >> 22,
+		    (status2 & HDSPM_wcFreqMask) >> 5);
+
+	snd_iprintf(buffer, "Input: %s, Mode=%s\n",
+		    (status & HDSPM_AB_int) ? "Coax" : "Optical",
+		    (status & HDSPM_RX_64ch) ? "64 channels" :
+		    "56 channels");
+
+	snd_iprintf(buffer, "\n");
+}
+
+static void __devinit snd_hdspm_proc_init(hdspm_t * hdspm)
+{
+	snd_info_entry_t *entry;
+
+	if (!snd_card_proc_new(hdspm->card, "hdspm", &entry))
+		snd_info_set_text_ops(entry, hdspm, 1024,
+				      snd_hdspm_proc_read);
+}
+
+/*------------------------------------------------------------
+   hdspm intitialize 
+ ------------------------------------------------------------*/
+
+static int snd_hdspm_set_defaults(hdspm_t * hdspm)
+{
+	unsigned int i;
+
+	/* ASSUMPTION: hdspm->lock is either held, or there is no need to
+	   hold it (e.g. during module initalization).
+	 */
+
+	/* set defaults:       */
+
+	hdspm->control_register = HDSPM_ClockModeMaster |	/* Master Cloack Mode on */
+	    hdspm_encode_latency(7) |	/* latency maximum = 8192 samples */
+	    HDSPM_InputCoaxial |	/* Input Coax not Optical */
+	    HDSPM_SyncRef_MADI |	/* Madi is syncclock */
+	    HDSPM_LineOut |	/* Analog output in */
+	    HDSPM_TX_64ch |	/* transmit in 64ch mode */
+	    HDSPM_AutoInp;	/* AutoInput chossing (takeover) */
+
+	/* ! HDSPM_Frequency0|HDSPM_Frequency1 = 44.1khz */
+	/* !  HDSPM_DoubleSpeed HDSPM_QuadSpeed = normal speed */
+	/* ! HDSPM_clr_tms = do not clear bits in track marks */
+
+	hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
+
+#ifdef SNDRV_BIG_ENDIAN
+	hdspm->control2_register = HDSPM_BIGENDIAN_MODE;
+#else
+	hdspm->control2_register = 0;
+#endif
+
+	hdspm_write(hdspm, HDSPM_control2Reg, hdspm->control2_register);
+	hdspm_compute_period_size(hdspm);
+
+	/* silence everything */
+
+	all_in_all_mixer(hdspm, 0 * UNITY_GAIN);
+
+	if (line_outs_monitor[hdspm->dev]) {
+
+		snd_printk(KERN_INFO "HDSPM: sending all playback streams to line outs.\n");
+
+		for (i = 0; i < HDSPM_MIXER_CHANNELS; i++) {
+			if (hdspm_write_pb_gain(hdspm, i, i, UNITY_GAIN))
+				return -EIO;
+		}
+	}
+
+	/* set a default rate so that the channel map is set up. */
+	hdspm->channel_map = channel_map_madi_ss;
+	hdspm_set_rate(hdspm, 44100, 1);
+
+	return 0;
+}
+
+
+/*------------------------------------------------------------
+   interupt 
+ ------------------------------------------------------------*/
+
+static irqreturn_t snd_hdspm_interrupt(int irq, void *dev_id,
+				       struct pt_regs *regs)
+{
+	hdspm_t *hdspm = (hdspm_t *) dev_id;
+	unsigned int status;
+	int audio;
+	int midi0;
+	int midi1;
+	unsigned int midi0status;
+	unsigned int midi1status;
+	int schedule = 0;
+
+	status = hdspm_read(hdspm, HDSPM_statusRegister);
+
+	audio = status & HDSPM_audioIRQPending;
+	midi0 = status & HDSPM_midi0IRQPending;
+	midi1 = status & HDSPM_midi1IRQPending;
+
+	if (!audio && !midi0 && !midi1)
+		return IRQ_NONE;
+
+	hdspm_write(hdspm, HDSPM_interruptConfirmation, 0);
+	hdspm->irq_count++;
+
+	midi0status = hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xff;
+	midi1status = hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xff;
+
+	if (audio) {
+
+		if (hdspm->capture_substream)
+			snd_pcm_period_elapsed(hdspm->pcm->
+					       streams
+					       [SNDRV_PCM_STREAM_CAPTURE].
+					       substream);
+
+		if (hdspm->playback_substream)
+			snd_pcm_period_elapsed(hdspm->pcm->
+					       streams
+					       [SNDRV_PCM_STREAM_PLAYBACK].
+					       substream);
+	}
+
+	if (midi0 && midi0status) {
+		/* we disable interrupts for this input until processing is done */
+		hdspm->control_register &= ~HDSPM_Midi0InterruptEnable;
+		hdspm_write(hdspm, HDSPM_controlRegister,
+			    hdspm->control_register);
+		hdspm->midi[0].pending = 1;
+		schedule = 1;
+	}
+	if (midi1 && midi1status) {
+		/* we disable interrupts for this input until processing is done */
+		hdspm->control_register &= ~HDSPM_Midi1InterruptEnable;
+		hdspm_write(hdspm, HDSPM_controlRegister,
+			    hdspm->control_register);
+		hdspm->midi[1].pending = 1;
+		schedule = 1;
+	}
+	if (schedule)
+		tasklet_hi_schedule(&hdspm->midi_tasklet);
+	return IRQ_HANDLED;
+}
+
+/*------------------------------------------------------------
+   pcm interface 
+  ------------------------------------------------------------*/
+
+
+static snd_pcm_uframes_t snd_hdspm_hw_pointer(snd_pcm_substream_t *
+					      substream)
+{
+	hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+	return hdspm_hw_pointer(hdspm);
+}
+
+static char *hdspm_channel_buffer_location(hdspm_t * hdspm,
+					   int stream, int channel)
+{
+	int mapped_channel;
+
+	snd_assert(channel >= 0
+		   || channel < HDSPM_MAX_CHANNELS, return NULL);
+
+	if ((mapped_channel = hdspm->channel_map[channel]) < 0)
+		return NULL;
+
+	if (stream == SNDRV_PCM_STREAM_CAPTURE) {
+		return hdspm->capture_buffer +
+		    mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
+	} else {
+		return hdspm->playback_buffer +
+		    mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
+	}
+}
+
+
+/* dont know why need it ??? */
+static int snd_hdspm_playback_copy(snd_pcm_substream_t * substream,
+				   int channel, snd_pcm_uframes_t pos,
+				   void __user *src, snd_pcm_uframes_t count)
+{
+	hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+	char *channel_buf;
+
+	snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4,
+		   return -EINVAL);
+
+	channel_buf = hdspm_channel_buffer_location(hdspm,
+						    substream->pstr->
+						    stream, channel);
+
+	snd_assert(channel_buf != NULL, return -EIO);
+
+	return copy_from_user(channel_buf + pos * 4, src, count * 4);
+}
+
+static int snd_hdspm_capture_copy(snd_pcm_substream_t * substream,
+				  int channel, snd_pcm_uframes_t pos,
+				  void __user *dst, snd_pcm_uframes_t count)
+{
+	hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+	char *channel_buf;
+
+	snd_assert(pos + count <= HDSPM_CHANNEL_BUFFER_BYTES / 4,
+		   return -EINVAL);
+
+	channel_buf = hdspm_channel_buffer_location(hdspm,
+						    substream->pstr->
+						    stream, channel);
+	snd_assert(channel_buf != NULL, return -EIO);
+	return copy_to_user(dst, channel_buf + pos * 4, count * 4);
+}
+
+static int snd_hdspm_hw_silence(snd_pcm_substream_t * substream,
+				int channel, snd_pcm_uframes_t pos,
+				snd_pcm_uframes_t count)
+{
+	hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+	char *channel_buf;
+
+	channel_buf =
+	    hdspm_channel_buffer_location(hdspm, substream->pstr->stream,
+					  channel);
+	snd_assert(channel_buf != NULL, return -EIO);
+	memset(channel_buf + pos * 4, 0, count * 4);
+	return 0;
+}
+
+static int snd_hdspm_reset(snd_pcm_substream_t * substream)
+{
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+	snd_pcm_substream_t *other;
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		other = hdspm->capture_substream;
+	else
+		other = hdspm->playback_substream;
+
+	if (hdspm->running)
+		runtime->status->hw_ptr = hdspm_hw_pointer(hdspm);
+	else
+		runtime->status->hw_ptr = 0;
+	if (other) {
+		struct list_head *pos;
+		snd_pcm_substream_t *s;
+		snd_pcm_runtime_t *oruntime = other->runtime;
+		snd_pcm_group_for_each(pos, substream) {
+			s = snd_pcm_group_substream_entry(pos);
+			if (s == other) {
+				oruntime->status->hw_ptr =
+				    runtime->status->hw_ptr;
+				break;
+			}
+		}
+	}
+	return 0;
+}
+
+static int snd_hdspm_hw_params(snd_pcm_substream_t * substream,
+			       snd_pcm_hw_params_t * params)
+{
+	hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+	int err;
+	int i;
+	pid_t this_pid;
+	pid_t other_pid;
+	struct snd_sg_buf *sgbuf;
+
+
+	spin_lock_irq(&hdspm->lock);
+
+	if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		this_pid = hdspm->playback_pid;
+		other_pid = hdspm->capture_pid;
+	} else {
+		this_pid = hdspm->capture_pid;
+		other_pid = hdspm->playback_pid;
+	}
+
+	if ((other_pid > 0) && (this_pid != other_pid)) {
+
+		/* The other stream is open, and not by the same
+		   task as this one. Make sure that the parameters
+		   that matter are the same.
+		 */
+
+		if (params_rate(params) != hdspm->system_sample_rate) {
+			spin_unlock_irq(&hdspm->lock);
+			_snd_pcm_hw_param_setempty(params,
+						   SNDRV_PCM_HW_PARAM_RATE);
+			return -EBUSY;
+		}
+
+		if (params_period_size(params) != hdspm->period_bytes / 4) {
+			spin_unlock_irq(&hdspm->lock);
+			_snd_pcm_hw_param_setempty(params,
+						   SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
+			return -EBUSY;
+		}
+
+	}
+	/* We're fine. */
+	spin_unlock_irq(&hdspm->lock);
+
+	/* how to make sure that the rate matches an externally-set one ?   */
+
+	spin_lock_irq(&hdspm->lock);
+	if ((err = hdspm_set_rate(hdspm, params_rate(params), 0)) < 0) {
+		spin_unlock_irq(&hdspm->lock);
+		_snd_pcm_hw_param_setempty(params,
+					   SNDRV_PCM_HW_PARAM_RATE);
+		return err;
+	}
+	spin_unlock_irq(&hdspm->lock);
+
+	if ((err =
+	     hdspm_set_interrupt_interval(hdspm,
+					  params_period_size(params))) <
+	    0) {
+		_snd_pcm_hw_param_setempty(params,
+					   SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
+		return err;
+	}
+
+	/* Memory allocation, takashi's method, dont know if we should spinlock  */
+	/* malloc all buffer even if not enabled to get sure */
+	/* malloc only needed bytes */
+	err =
+	    snd_pcm_lib_malloc_pages(substream,
+				     HDSPM_CHANNEL_BUFFER_BYTES *
+				     params_channels(params));
+	if (err < 0)
+		return err;
+
+	sgbuf = snd_pcm_substream_sgbuf(substream);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+
+		hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferOut,
+				params_channels(params));
+
+		for (i = 0; i < params_channels(params); ++i)
+			snd_hdspm_enable_out(hdspm, i, 1);
+
+		hdspm->playback_buffer =
+		    (unsigned char *) substream->runtime->dma_area;
+	} else {
+		hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferIn,
+				params_channels(params));
+
+		for (i = 0; i < params_channels(params); ++i)
+			snd_hdspm_enable_in(hdspm, i, 1);
+
+		hdspm->capture_buffer =
+		    (unsigned char *) substream->runtime->dma_area;
+	}
+	return 0;
+}
+
+static int snd_hdspm_hw_free(snd_pcm_substream_t * substream)
+{
+	int i;
+	hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+
+		/* params_channels(params) should be enough, 
+		   but to get sure in case of error */
+		for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
+			snd_hdspm_enable_out(hdspm, i, 0);
+
+		hdspm->playback_buffer = NULL;
+	} else {
+		for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
+			snd_hdspm_enable_in(hdspm, i, 0);
+
+		hdspm->capture_buffer = NULL;
+
+	}
+
+	snd_pcm_lib_free_pages(substream);
+
+	return 0;
+}
+
+static int snd_hdspm_channel_info(snd_pcm_substream_t * substream,
+				  snd_pcm_channel_info_t * info)
+{
+	hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+	int mapped_channel;
+
+	snd_assert(info->channel < HDSPM_MAX_CHANNELS, return -EINVAL);
+
+	if ((mapped_channel = hdspm->channel_map[info->channel]) < 0)
+		return -EINVAL;
+
+	info->offset = mapped_channel * HDSPM_CHANNEL_BUFFER_BYTES;
+	info->first = 0;
+	info->step = 32;
+	return 0;
+}
+
+static int snd_hdspm_ioctl(snd_pcm_substream_t * substream,
+			   unsigned int cmd, void *arg)
+{
+	switch (cmd) {
+	case SNDRV_PCM_IOCTL1_RESET:
+		{
+			return snd_hdspm_reset(substream);
+		}
+
+	case SNDRV_PCM_IOCTL1_CHANNEL_INFO:
+		{
+			snd_pcm_channel_info_t *info = arg;
+			return snd_hdspm_channel_info(substream, info);
+		}
+	default:
+		break;
+	}
+
+	return snd_pcm_lib_ioctl(substream, cmd, arg);
+}
+
+static int snd_hdspm_trigger(snd_pcm_substream_t * substream, int cmd)
+{
+	hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+	snd_pcm_substream_t *other;
+	int running;
+
+	spin_lock(&hdspm->lock);
+	running = hdspm->running;
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		running |= 1 << substream->stream;
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		running &= ~(1 << substream->stream);
+		break;
+	default:
+		snd_BUG();
+		spin_unlock(&hdspm->lock);
+		return -EINVAL;
+	}
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		other = hdspm->capture_substream;
+	else
+		other = hdspm->playback_substream;
+
+	if (other) {
+		struct list_head *pos;
+		snd_pcm_substream_t *s;
+		snd_pcm_group_for_each(pos, substream) {
+			s = snd_pcm_group_substream_entry(pos);
+			if (s == other) {
+				snd_pcm_trigger_done(s, substream);
+				if (cmd == SNDRV_PCM_TRIGGER_START)
+					running |= 1 << s->stream;
+				else
+					running &= ~(1 << s->stream);
+				goto _ok;
+			}
+		}
+		if (cmd == SNDRV_PCM_TRIGGER_START) {
+			if (!(running & (1 << SNDRV_PCM_STREAM_PLAYBACK))
+			    && substream->stream ==
+			    SNDRV_PCM_STREAM_CAPTURE)
+				hdspm_silence_playback(hdspm);
+		} else {
+			if (running &&
+			    substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+				hdspm_silence_playback(hdspm);
+		}
+	} else {
+		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+			hdspm_silence_playback(hdspm);
+	}
+      _ok:
+	snd_pcm_trigger_done(substream, substream);
+	if (!hdspm->running && running)
+		hdspm_start_audio(hdspm);
+	else if (hdspm->running && !running)
+		hdspm_stop_audio(hdspm);
+	hdspm->running = running;
+	spin_unlock(&hdspm->lock);
+
+	return 0;
+}
+
+static int snd_hdspm_prepare(snd_pcm_substream_t * substream)
+{
+	return 0;
+}
+
+static unsigned int period_sizes[] =
+    { 64, 128, 256, 512, 1024, 2048, 4096, 8192 };
+
+static snd_pcm_hardware_t snd_hdspm_playback_subinfo = {
+	.info = (SNDRV_PCM_INFO_MMAP |
+		 SNDRV_PCM_INFO_MMAP_VALID |
+		 SNDRV_PCM_INFO_NONINTERLEAVED |
+		 SNDRV_PCM_INFO_SYNC_START | SNDRV_PCM_INFO_DOUBLE),
+	.formats = SNDRV_PCM_FMTBIT_S32_LE,
+	.rates = (SNDRV_PCM_RATE_32000 |
+		  SNDRV_PCM_RATE_44100 |
+		  SNDRV_PCM_RATE_48000 |
+		  SNDRV_PCM_RATE_64000 |
+		  SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000),
+	.rate_min = 32000,
+	.rate_max = 96000,
+	.channels_min = 1,
+	.channels_max = HDSPM_MAX_CHANNELS,
+	.buffer_bytes_max =
+	    HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
+	.period_bytes_min = (64 * 4),
+	.period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
+	.periods_min = 2,
+	.periods_max = 2,
+	.fifo_size = 0
+};
+
+static snd_pcm_hardware_t snd_hdspm_capture_subinfo = {
+	.info = (SNDRV_PCM_INFO_MMAP |
+		 SNDRV_PCM_INFO_MMAP_VALID |
+		 SNDRV_PCM_INFO_NONINTERLEAVED |
+		 SNDRV_PCM_INFO_SYNC_START),
+	.formats = SNDRV_PCM_FMTBIT_S32_LE,
+	.rates = (SNDRV_PCM_RATE_32000 |
+		  SNDRV_PCM_RATE_44100 |
+		  SNDRV_PCM_RATE_48000 |
+		  SNDRV_PCM_RATE_64000 |
+		  SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000),
+	.rate_min = 32000,
+	.rate_max = 96000,
+	.channels_min = 1,
+	.channels_max = HDSPM_MAX_CHANNELS,
+	.buffer_bytes_max =
+	    HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
+	.period_bytes_min = (64 * 4),
+	.period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
+	.periods_min = 2,
+	.periods_max = 2,
+	.fifo_size = 0
+};
+
+static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = {
+	.count = ARRAY_SIZE(period_sizes),
+	.list = period_sizes,
+	.mask = 0
+};
+
+
+static int snd_hdspm_hw_rule_channels_rate(snd_pcm_hw_params_t * params,
+					   snd_pcm_hw_rule_t * rule)
+{
+	hdspm_t *hdspm = rule->private;
+	snd_interval_t *c =
+	    hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+	snd_interval_t *r =
+	    hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+
+	if (r->min > 48000) {
+		snd_interval_t t = {
+			.min = 1,
+			.max = hdspm->ds_channels,
+			.integer = 1,
+		};
+		return snd_interval_refine(c, &t);
+	} else if (r->max < 64000) {
+		snd_interval_t t = {
+			.min = 1,
+			.max = hdspm->ss_channels,
+			.integer = 1,
+		};
+		return snd_interval_refine(c, &t);
+	}
+	return 0;
+}
+
+static int snd_hdspm_hw_rule_rate_channels(snd_pcm_hw_params_t * params,
+					   snd_pcm_hw_rule_t * rule)
+{
+	hdspm_t *hdspm = rule->private;
+	snd_interval_t *c =
+	    hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
+	snd_interval_t *r =
+	    hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+
+	if (c->min <= hdspm->ss_channels) {
+		snd_interval_t t = {
+			.min = 32000,
+			.max = 48000,
+			.integer = 1,
+		};
+		return snd_interval_refine(r, &t);
+	} else if (c->max > hdspm->ss_channels) {
+		snd_interval_t t = {
+			.min = 64000,
+			.max = 96000,
+			.integer = 1,
+		};
+
+		return snd_interval_refine(r, &t);
+	}
+	return 0;
+}
+
+static int snd_hdspm_playback_open(snd_pcm_substream_t * substream)
+{
+	hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+
+	snd_printdd("Open device substream %d\n", substream->stream);
+
+	spin_lock_irq(&hdspm->lock);
+
+	snd_pcm_set_sync(substream);
+
+	runtime->hw = snd_hdspm_playback_subinfo;
+
+	if (hdspm->capture_substream == NULL)
+		hdspm_stop_audio(hdspm);
+
+	hdspm->playback_pid = current->pid;
+	hdspm->playback_substream = substream;
+
+	spin_unlock_irq(&hdspm->lock);
+
+	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
+
+	snd_pcm_hw_constraint_list(runtime, 0,
+				   SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+				   &hw_constraints_period_sizes);
+
+	snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+			    snd_hdspm_hw_rule_channels_rate, hdspm,
+			    SNDRV_PCM_HW_PARAM_RATE, -1);
+
+	snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+			    snd_hdspm_hw_rule_rate_channels, hdspm,
+			    SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+
+	return 0;
+}
+
+static int snd_hdspm_playback_release(snd_pcm_substream_t * substream)
+{
+	hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+
+	spin_lock_irq(&hdspm->lock);
+
+	hdspm->playback_pid = -1;
+	hdspm->playback_substream = NULL;
+
+	spin_unlock_irq(&hdspm->lock);
+
+	return 0;
+}
+
+
+static int snd_hdspm_capture_open(snd_pcm_substream_t * substream)
+{
+	hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+
+	spin_lock_irq(&hdspm->lock);
+	snd_pcm_set_sync(substream);
+	runtime->hw = snd_hdspm_capture_subinfo;
+
+	if (hdspm->playback_substream == NULL)
+		hdspm_stop_audio(hdspm);
+
+	hdspm->capture_pid = current->pid;
+	hdspm->capture_substream = substream;
+
+	spin_unlock_irq(&hdspm->lock);
+
+	snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
+	snd_pcm_hw_constraint_list(runtime, 0,
+				   SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+				   &hw_constraints_period_sizes);
+
+	snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+			    snd_hdspm_hw_rule_channels_rate, hdspm,
+			    SNDRV_PCM_HW_PARAM_RATE, -1);
+
+	snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+			    snd_hdspm_hw_rule_rate_channels, hdspm,
+			    SNDRV_PCM_HW_PARAM_CHANNELS, -1);
+	return 0;
+}
+
+static int snd_hdspm_capture_release(snd_pcm_substream_t * substream)
+{
+	hdspm_t *hdspm = snd_pcm_substream_chip(substream);
+
+	spin_lock_irq(&hdspm->lock);
+
+	hdspm->capture_pid = -1;
+	hdspm->capture_substream = NULL;
+
+	spin_unlock_irq(&hdspm->lock);
+	return 0;
+}
+
+static int snd_hdspm_hwdep_dummy_op(snd_hwdep_t * hw, struct file *file)
+{
+	/* we have nothing to initialize but the call is required */
+	return 0;
+}
+
+
+static int snd_hdspm_hwdep_ioctl(snd_hwdep_t * hw, struct file *file,
+				 unsigned int cmd, unsigned long arg)
+{
+	hdspm_t *hdspm = (hdspm_t *) hw->private_data;
+	struct sndrv_hdspm_mixer_ioctl mixer;
+	hdspm_config_info_t info;
+	hdspm_version_t hdspm_version;
+	struct sndrv_hdspm_peak_rms_ioctl rms;
+
+	switch (cmd) {
+
+		
+	case SNDRV_HDSPM_IOCTL_GET_PEAK_RMS:
+		if (copy_from_user(&rms, (void __user *)arg, sizeof(rms)))
+			return -EFAULT;
+		/* maybe there is a chance to memorymap in future so dont touch just copy */
+		if(copy_to_user_fromio((void __user *)rms.peak,
+				       hdspm->iobase+HDSPM_MADI_peakrmsbase,
+				       sizeof(hdspm_peak_rms_t)) != 0 )
+			return -EFAULT;
+
+		break;
+		
+
+	case SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO:
+
+		spin_lock_irq(&hdspm->lock);
+		info.pref_sync_ref =
+		    (unsigned char) hdspm_pref_sync_ref(hdspm);
+		info.wordclock_sync_check =
+		    (unsigned char) hdspm_wc_sync_check(hdspm);
+
+		info.system_sample_rate = hdspm->system_sample_rate;
+		info.autosync_sample_rate =
+		    hdspm_external_sample_rate(hdspm);
+		info.system_clock_mode =
+		    (unsigned char) hdspm_system_clock_mode(hdspm);
+		info.clock_source =
+		    (unsigned char) hdspm_clock_source(hdspm);
+		info.autosync_ref =
+		    (unsigned char) hdspm_autosync_ref(hdspm);
+		info.line_out = (unsigned char) hdspm_line_out(hdspm);
+		info.passthru = 0;
+		spin_unlock_irq(&hdspm->lock);
+		if (copy_to_user((void __user *) arg, &info, sizeof(info)))
+			return -EFAULT;
+		break;
+
+	case SNDRV_HDSPM_IOCTL_GET_VERSION:
+		hdspm_version.firmware_rev = hdspm->firmware_rev;
+		if (copy_to_user((void __user *) arg, &hdspm_version,
+				 sizeof(hdspm_version)))
+			return -EFAULT;
+		break;
+
+	case SNDRV_HDSPM_IOCTL_GET_MIXER:
+		if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer)))
+			return -EFAULT;
+		if (copy_to_user
+		    ((void __user *)mixer.mixer, hdspm->mixer, sizeof(hdspm_mixer_t)))
+			return -EFAULT;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static snd_pcm_ops_t snd_hdspm_playback_ops = {
+	.open = snd_hdspm_playback_open,
+	.close = snd_hdspm_playback_release,
+	.ioctl = snd_hdspm_ioctl,
+	.hw_params = snd_hdspm_hw_params,
+	.hw_free = snd_hdspm_hw_free,
+	.prepare = snd_hdspm_prepare,
+	.trigger = snd_hdspm_trigger,
+	.pointer = snd_hdspm_hw_pointer,
+	.copy = snd_hdspm_playback_copy,
+	.silence = snd_hdspm_hw_silence,
+	.page = snd_pcm_sgbuf_ops_page,
+};
+
+static snd_pcm_ops_t snd_hdspm_capture_ops = {
+	.open = snd_hdspm_capture_open,
+	.close = snd_hdspm_capture_release,
+	.ioctl = snd_hdspm_ioctl,
+	.hw_params = snd_hdspm_hw_params,
+	.hw_free = snd_hdspm_hw_free,
+	.prepare = snd_hdspm_prepare,
+	.trigger = snd_hdspm_trigger,
+	.pointer = snd_hdspm_hw_pointer,
+	.copy = snd_hdspm_capture_copy,
+	.page = snd_pcm_sgbuf_ops_page,
+};
+
+static int __devinit snd_hdspm_create_hwdep(snd_card_t * card,
+					    hdspm_t * hdspm)
+{
+	snd_hwdep_t *hw;
+	int err;
+
+	if ((err = snd_hwdep_new(card, "HDSPM hwdep", 0, &hw)) < 0)
+		return err;
+
+	hdspm->hwdep = hw;
+	hw->private_data = hdspm;
+	strcpy(hw->name, "HDSPM hwdep interface");
+
+	hw->ops.open = snd_hdspm_hwdep_dummy_op;
+	hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
+	hw->ops.release = snd_hdspm_hwdep_dummy_op;
+
+	return 0;
+}
+
+
+/*------------------------------------------------------------
+   memory interface 
+ ------------------------------------------------------------*/
+static int __devinit snd_hdspm_preallocate_memory(hdspm_t * hdspm)
+{
+	int err;
+	snd_pcm_t *pcm;
+	size_t wanted;
+
+	pcm = hdspm->pcm;
+
+	wanted = HDSPM_DMA_AREA_BYTES + 4096;	/* dont know why, but it works */
+
+	if ((err =
+	     snd_pcm_lib_preallocate_pages_for_all(pcm,
+	     					   SNDRV_DMA_TYPE_DEV_SG,
+						   snd_dma_pci_data(hdspm->pci),
+						   wanted,
+						   wanted)) < 0) {
+		snd_printdd("Could not preallocate %d  Bytes\n", wanted);
+
+		return err;
+	} else
+		snd_printdd(" Preallocated %d  Bytes\n", wanted);
+
+	return 0;
+}
+
+static int snd_hdspm_memory_free(hdspm_t * hdspm)
+{
+	snd_printdd("memory_free_for_all %p\n", hdspm->pcm);
+
+	snd_pcm_lib_preallocate_free_for_all(hdspm->pcm);
+	return 0;
+}
+
+
+static void hdspm_set_sgbuf(hdspm_t * hdspm, struct snd_sg_buf *sgbuf,
+			     unsigned int reg, int channels)
+{
+	int i;
+	for (i = 0; i < (channels * 16); i++)
+		hdspm_write(hdspm, reg + 4 * i,
+			    snd_pcm_sgbuf_get_addr(sgbuf,
+						   (size_t) 4096 * i));
+}
+
+/* ------------- ALSA Devices ---------------------------- */
+static int __devinit snd_hdspm_create_pcm(snd_card_t * card,
+					  hdspm_t * hdspm)
+{
+	snd_pcm_t *pcm;
+	int err;
+
+	if ((err = snd_pcm_new(card, hdspm->card_name, 0, 1, 1, &pcm)) < 0)
+		return err;
+
+	hdspm->pcm = pcm;
+	pcm->private_data = hdspm;
+	strcpy(pcm->name, hdspm->card_name);
+
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+			&snd_hdspm_playback_ops);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+			&snd_hdspm_capture_ops);
+
+	pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
+
+	if ((err = snd_hdspm_preallocate_memory(hdspm)) < 0)
+		return err;
+
+	return 0;
+}
+
+static inline void snd_hdspm_initialize_midi_flush(hdspm_t * hdspm)
+{
+	snd_hdspm_flush_midi_input(hdspm, 0);
+	snd_hdspm_flush_midi_input(hdspm, 1);
+}
+
+static int __devinit snd_hdspm_create_alsa_devices(snd_card_t * card,
+						   hdspm_t * hdspm)
+{
+	int err;
+
+	snd_printdd("Create card...\n");
+	if ((err = snd_hdspm_create_pcm(card, hdspm)) < 0)
+		return err;
+
+	if ((err = snd_hdspm_create_midi(card, hdspm, 0)) < 0)
+		return err;
+
+	if ((err = snd_hdspm_create_midi(card, hdspm, 1)) < 0)
+		return err;
+
+	if ((err = snd_hdspm_create_controls(card, hdspm)) < 0)
+		return err;
+
+	if ((err = snd_hdspm_create_hwdep(card, hdspm)) < 0)
+		return err;
+
+	snd_printdd("proc init...\n");
+	snd_hdspm_proc_init(hdspm);
+
+	hdspm->system_sample_rate = -1;
+	hdspm->last_external_sample_rate = -1;
+	hdspm->last_internal_sample_rate = -1;
+	hdspm->playback_pid = -1;
+	hdspm->capture_pid = -1;
+	hdspm->capture_substream = NULL;
+	hdspm->playback_substream = NULL;
+
+	snd_printdd("Set defaults...\n");
+	if ((err = snd_hdspm_set_defaults(hdspm)) < 0)
+		return err;
+
+	snd_printdd("Update mixer controls...\n");
+	hdspm_update_simple_mixer_controls(hdspm);
+
+	snd_printdd("Initializeing complete ???\n");
+
+	if ((err = snd_card_register(card)) < 0) {
+		snd_printk(KERN_ERR "HDSPM: error registering card\n");
+		return err;
+	}
+
+	snd_printdd("... yes now\n");
+
+	return 0;
+}
+
+static int __devinit snd_hdspm_create(snd_card_t * card, hdspm_t * hdspm,
+				      int precise_ptr, int enable_monitor)
+{
+	struct pci_dev *pci = hdspm->pci;
+	int err;
+	int i;
+
+	unsigned long io_extent;
+
+	hdspm->irq = -1;
+	hdspm->irq_count = 0;
+
+	hdspm->midi[0].rmidi = NULL;
+	hdspm->midi[1].rmidi = NULL;
+	hdspm->midi[0].input = NULL;
+	hdspm->midi[1].input = NULL;
+	hdspm->midi[0].output = NULL;
+	hdspm->midi[1].output = NULL;
+	spin_lock_init(&hdspm->midi[0].lock);
+	spin_lock_init(&hdspm->midi[1].lock);
+	hdspm->iobase = NULL;
+	hdspm->control_register = 0;
+	hdspm->control2_register = 0;
+
+	hdspm->playback_buffer = NULL;
+	hdspm->capture_buffer = NULL;
+
+	for (i = 0; i < HDSPM_MAX_CHANNELS; ++i)
+		hdspm->playback_mixer_ctls[i] = NULL;
+	hdspm->mixer = NULL;
+
+	hdspm->card = card;
+
+	spin_lock_init(&hdspm->lock);
+
+	tasklet_init(&hdspm->midi_tasklet,
+		     hdspm_midi_tasklet, (unsigned long) hdspm);
+
+	pci_read_config_word(hdspm->pci,
+			     PCI_CLASS_REVISION, &hdspm->firmware_rev);
+
+	strcpy(card->driver, "HDSPM");
+	strcpy(card->mixername, "Xilinx FPGA");
+	hdspm->card_name = "RME HDSPM MADI";
+
+	if ((err = pci_enable_device(pci)) < 0)
+		return err;
+
+	pci_set_master(hdspm->pci);
+
+	if ((err = pci_request_regions(pci, "hdspm")) < 0)
+		return err;
+
+	hdspm->port = pci_resource_start(pci, 0);
+	io_extent = pci_resource_len(pci, 0);
+
+	snd_printdd("grabbed memory region 0x%lx-0x%lx\n",
+		   hdspm->port, hdspm->port + io_extent - 1);
+
+
+	if ((hdspm->iobase = ioremap_nocache(hdspm->port, io_extent)) == NULL) {
+		snd_printk(KERN_ERR "HDSPM: unable to remap region 0x%lx-0x%lx\n",
+			   hdspm->port, hdspm->port + io_extent - 1);
+		return -EBUSY;
+	}
+	snd_printdd("remapped region (0x%lx) 0x%lx-0x%lx\n",
+		   (unsigned long)hdspm->iobase, hdspm->port,
+		   hdspm->port + io_extent - 1);
+
+	if (request_irq(pci->irq, snd_hdspm_interrupt,
+			SA_INTERRUPT | SA_SHIRQ, "hdspm",
+			(void *) hdspm)) {
+		snd_printk(KERN_ERR "HDSPM: unable to use IRQ %d\n", pci->irq);
+		return -EBUSY;
+	}
+
+	snd_printdd("use IRQ %d\n", pci->irq);
+
+	hdspm->irq = pci->irq;
+	hdspm->precise_ptr = precise_ptr;
+
+	hdspm->monitor_outs = enable_monitor;
+
+	snd_printdd("kmalloc Mixer memory of %d Bytes\n",
+		   sizeof(hdspm_mixer_t));
+	if ((hdspm->mixer =
+	     (hdspm_mixer_t *) kmalloc(sizeof(hdspm_mixer_t), GFP_KERNEL))
+	    == NULL) {
+		snd_printk(KERN_ERR "HDSPM: unable to kmalloc Mixer memory of %d Bytes\n",
+			   (int)sizeof(hdspm_mixer_t));
+		return err;
+	}
+
+	hdspm->ss_channels = MADI_SS_CHANNELS;
+	hdspm->ds_channels = MADI_DS_CHANNELS;
+	hdspm->qs_channels = MADI_QS_CHANNELS;
+
+	snd_printdd("create alsa devices.\n");
+	if ((err = snd_hdspm_create_alsa_devices(card, hdspm)) < 0)
+		return err;
+
+	snd_hdspm_initialize_midi_flush(hdspm);
+
+	return 0;
+}
+
+static int snd_hdspm_free(hdspm_t * hdspm)
+{
+
+	if (hdspm->port) {
+
+		/* stop th audio, and cancel all interrupts */
+		hdspm->control_register &=
+		    ~(HDSPM_Start | HDSPM_AudioInterruptEnable
+		      | HDSPM_Midi0InterruptEnable |
+		      HDSPM_Midi1InterruptEnable);
+		hdspm_write(hdspm, HDSPM_controlRegister,
+			    hdspm->control_register);
+	}
+
+	if (hdspm->irq >= 0)
+		free_irq(hdspm->irq, (void *) hdspm);
+
+
+	if (hdspm->mixer)
+		kfree(hdspm->mixer);
+
+	if (hdspm->iobase)
+		iounmap(hdspm->iobase);
+
+	snd_hdspm_memory_free(hdspm);
+
+	if (hdspm->port)
+		pci_release_regions(hdspm->pci);
+
+	pci_disable_device(hdspm->pci);
+	return 0;
+}
+
+static void snd_hdspm_card_free(snd_card_t * card)
+{
+	hdspm_t *hdspm = (hdspm_t *) card->private_data;
+
+	if (hdspm)
+		snd_hdspm_free(hdspm);
+}
+
+static int __devinit snd_hdspm_probe(struct pci_dev *pci,
+				     const struct pci_device_id *pci_id)
+{
+	static int dev;
+	hdspm_t *hdspm;
+	snd_card_t *card;
+	int err;
+
+	if (dev >= SNDRV_CARDS)
+		return -ENODEV;
+	if (!enable[dev]) {
+		dev++;
+		return -ENOENT;
+	}
+
+	if (!(card = snd_card_new(index[dev], id[dev],
+				  THIS_MODULE, sizeof(hdspm_t))))
+		return -ENOMEM;
+
+	hdspm = (hdspm_t *) card->private_data;
+	card->private_free = snd_hdspm_card_free;
+	hdspm->dev = dev;
+	hdspm->pci = pci;
+
+	if ((err =
+	     snd_hdspm_create(card, hdspm, precise_ptr[dev],
+			      enable_monitor[dev])) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+
+	strcpy(card->shortname, "HDSPM MADI");
+	sprintf(card->longname, "%s at 0x%lx, irq %d", hdspm->card_name,
+		hdspm->port, hdspm->irq);
+
+	if ((err = snd_card_register(card)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+
+	pci_set_drvdata(pci, card);
+
+	dev++;
+	return 0;
+}
+
+static void __devexit snd_hdspm_remove(struct pci_dev *pci)
+{
+	snd_card_free(pci_get_drvdata(pci));
+	pci_set_drvdata(pci, NULL);
+}
+
+static struct pci_driver driver = {
+	.name = "RME Hammerfall DSP MADI",
+	.id_table = snd_hdspm_ids,
+	.probe = snd_hdspm_probe,
+	.remove = __devexit_p(snd_hdspm_remove),
+};
+
+
+static int __init alsa_card_hdspm_init(void)
+{
+	return pci_register_driver(&driver);
+}
+
+static void __exit alsa_card_hdspm_exit(void)
+{
+	pci_unregister_driver(&driver);
+}
+
+module_init(alsa_card_hdspm_init)
+module_exit(alsa_card_hdspm_exit)
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index 69cd81e..f303740 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -303,18 +303,22 @@
 {
 	dmab->dev.type = SNDRV_DMA_TYPE_DEV;
 	dmab->dev.dev = snd_dma_pci_data(pci);
-	if (! snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
-		if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
-					size, dmab) < 0)
-			return -ENOMEM;
+	if (snd_dma_get_reserved_buf(dmab, snd_dma_pci_buf_id(pci))) {
+		if (dmab->bytes >= size)
+			return 0;
 	}
+	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
+				size, dmab) < 0)
+		return -ENOMEM;
 	return 0;
 }
 
 static void snd_hammerfall_free_buffer(struct snd_dma_buffer *dmab, struct pci_dev *pci)
 {
-	if (dmab->area)
+	if (dmab->area) {
+		dmab->dev.dev = NULL; /* make it anonymous */
 		snd_dma_reserve_buf(dmab, snd_dma_pci_buf_id(pci));
+	}
 }
 
 
@@ -2664,7 +2668,7 @@
 
 static int __init alsa_card_hammerfall_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_hammerfall_exit(void)
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index cfd2c5f..60ecb2b 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -1522,7 +1522,7 @@
 
 static int __init alsa_card_sonicvibes_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_sonicvibes_exit(void)
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index ad58e08..940d531 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -143,7 +143,8 @@
 			return err;
 		}
 	}
-	if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE,
+	if (trident->device != TRIDENT_DEVICE_ID_SI7018 &&
+	    (err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE,
 				       trident->midi_port, 1,
 				       trident->irq, 0, &trident->rmidi)) < 0) {
 		snd_card_free(card);
@@ -184,7 +185,7 @@
 
 static int __init alsa_card_trident_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_trident_exit(void)
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 9b4d74d..42c48f0 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -101,7 +101,7 @@
 module_param_array(ac97_quirk, charp, NULL, 0444);
 MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
 module_param_array(dxs_support, int, NULL, 0444);
-MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA)");
+MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA, 5 = enable any sample rate)");
 
 
 /* pci ids */
@@ -302,6 +302,7 @@
 #define VIA_DXS_DISABLE	2
 #define VIA_DXS_48K	3
 #define VIA_DXS_NO_VRA	4
+#define VIA_DXS_SRC	5
 
 
 /*
@@ -380,6 +381,7 @@
 	struct via_rate_lock rates[2]; /* playback and capture */
 	unsigned int dxs_fixed: 1;	/* DXS channel accepts only 48kHz */
 	unsigned int no_vra: 1;		/* no need to set VRA on DXS channels */
+	unsigned int dxs_src: 1;	/* use full SRC capabilities of DXS */
 	unsigned int spdif_on: 1;	/* only spdif rates work to external DACs */
 
 	snd_pcm_t *pcms[2];
@@ -489,10 +491,8 @@
 		snd_dma_free_pages(&dev->table);
 		dev->table.area = NULL;
 	}
-	if (dev->idx_table) {
-		kfree(dev->idx_table);
-		dev->idx_table = NULL;
-	}
+	kfree(dev->idx_table);
+	dev->idx_table = NULL;
 	return 0;
 }
 
@@ -924,15 +924,17 @@
 	via82xx_t *chip = snd_pcm_substream_chip(substream);
 	viadev_t *viadev = (viadev_t *)substream->runtime->private_data;
 	snd_pcm_runtime_t *runtime = substream->runtime;
+	int ac97_rate = chip->dxs_src ? 48000 : runtime->rate;
 	int rate_changed;
 	u32 rbits;
 
-	if ((rate_changed = via_lock_rate(&chip->rates[0], runtime->rate)) < 0)
+	if ((rate_changed = via_lock_rate(&chip->rates[0], ac97_rate)) < 0)
 		return rate_changed;
 	if (rate_changed) {
 		snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE,
 				  chip->no_vra ? 48000 : runtime->rate);
-		snd_ac97_set_rate(chip->ac97, AC97_SPDIF, runtime->rate);
+		snd_ac97_set_rate(chip->ac97, AC97_SPDIF,
+				  chip->no_vra ? 48000 : runtime->rate);
 	}
 	if (runtime->rate == 48000)
 		rbits = 0xfffff;
@@ -1074,6 +1076,12 @@
 		/* fixed DXS playback rate */
 		runtime->hw.rates = SNDRV_PCM_RATE_48000;
 		runtime->hw.rate_min = runtime->hw.rate_max = 48000;
+	} else if (chip->dxs_src && viadev->reg_offset < 0x40) {
+		/* use full SRC capabilities of DXS */
+		runtime->hw.rates = (SNDRV_PCM_RATE_CONTINUOUS |
+				     SNDRV_PCM_RATE_8000_48000);
+		runtime->hw.rate_min = 8000;
+		runtime->hw.rate_max = 48000;
 	} else if (! ratep->rate) {
 		int idx = viadev->direction ? AC97_RATES_ADC : AC97_RATES_FRONT_DAC;
 		runtime->hw.rates = chip->ac97->rates[idx];
@@ -1550,51 +1558,51 @@
 
 static struct ac97_quirk ac97_quirks[] = {
 	{
-		.vendor = 0x1106,
-		.device = 0x4161,
+		.subvendor = 0x1106,
+		.subdevice = 0x4161,
 		.codec_id = 0x56494161, /* VT1612A */
 		.name = "Soltek SL-75DRV5",
 		.type = AC97_TUNE_NONE
 	},
 	{	/* FIXME: which codec? */
-		.vendor = 0x1106,
-		.device = 0x4161,
+		.subvendor = 0x1106,
+		.subdevice = 0x4161,
 		.name = "ASRock K7VT2",
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x1019,
-		.device = 0x0a81,
+		.subvendor = 0x1019,
+		.subdevice = 0x0a81,
 		.name = "ECS K7VTA3",
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x1019,
-		.device = 0x0a85,
+		.subvendor = 0x1019,
+		.subdevice = 0x0a85,
 		.name = "ECS L7VMM2",
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
-		.vendor = 0x1849,
-		.device = 0x3059,
+		.subvendor = 0x1849,
+		.subdevice = 0x3059,
 		.name = "ASRock K7VM2",
 		.type = AC97_TUNE_HP_ONLY	/* VT1616 */
 	},
 	{
-		.vendor = 0x14cd,
-		.device = 0x7002,
+		.subvendor = 0x14cd,
+		.subdevice = 0x7002,
 		.name = "Unknown",
 		.type = AC97_TUNE_ALC_JACK
 	},
 	{
-		.vendor = 0x1071,
-		.device = 0x8590,
+		.subvendor = 0x1071,
+		.subdevice = 0x8590,
 		.name = "Mitac Mobo",
 		.type = AC97_TUNE_ALC_JACK
 	},
 	{
-		.vendor = 0x161f,
-		.device = 0x202b,
+		.subvendor = 0x161f,
+		.subdevice = 0x202b,
 		.name = "Arima Notebook",
 		.type = AC97_TUNE_HP_ONLY,
 	},
@@ -2132,8 +2140,8 @@
  * auto detection of DXS channel supports.
  */
 struct dxs_whitelist {
-	unsigned short vendor;
-	unsigned short device; 
+	unsigned short subvendor;
+	unsigned short subdevice; 
 	unsigned short mask; 
 	short action;	/* new dxs_support value */
 };
@@ -2141,38 +2149,44 @@
 static int __devinit check_dxs_list(struct pci_dev *pci)
 {
 	static struct dxs_whitelist whitelist[] = {
-		{ .vendor = 0x1005, .device = 0x4710, .action = VIA_DXS_ENABLE }, /* Avance Logic Mobo */
-		{ .vendor = 0x1019, .device = 0x0996, .action = VIA_DXS_48K },
-		{ .vendor = 0x1019, .device = 0x0a81, .action = VIA_DXS_NO_VRA }, /* ECS K7VTA3 v8.0 */
-		{ .vendor = 0x1019, .device = 0x0a85, .action = VIA_DXS_NO_VRA }, /* ECS L7VMM2 */
-		{ .vendor = 0x1025, .device = 0x0033, .action = VIA_DXS_NO_VRA }, /* Acer Inspire 1353LM */
-		{ .vendor = 0x1043, .device = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/
-		{ .vendor = 0x1043, .device = 0x80a1, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8-X */
-		{ .vendor = 0x1043, .device = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/ 
-		{ .vendor = 0x1071, .device = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */
-		{ .vendor = 0x10cf, .device = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */
-		{ .vendor = 0x1106, .device = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */
-		{ .vendor = 0x1106, .device = 0x4552, .action = VIA_DXS_NO_VRA }, /* QDI Kudoz 7X/600-6AL */
-		{ .vendor = 0x1106, .device = 0xaa01, .action = VIA_DXS_NO_VRA }, /* EPIA MII */
-		{ .vendor = 0x1297, .device = 0xa232, .action = VIA_DXS_ENABLE }, /* Shuttle ?? */
-		{ .vendor = 0x1297, .device = 0xc160, .action = VIA_DXS_ENABLE }, /* Shuttle SK41G */
-		{ .vendor = 0x1458, .device = 0xa002, .action = VIA_DXS_ENABLE }, /* Gigabyte GA-7VAXP */
-		{ .vendor = 0x1462, .device = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */
-		{ .vendor = 0x1462, .device = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */
-		{ .vendor = 0x1462, .device = 0x7023, .action = VIA_DXS_NO_VRA }, /* MSI K8T Neo2-FI */
-		{ .vendor = 0x1462, .device = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */
-		{ .vendor = 0x147b, .device = 0x1401, .action = VIA_DXS_ENABLE }, /* ABIT KD7(-RAID) */
-		{ .vendor = 0x147b, .device = 0x1411, .action = VIA_DXS_ENABLE }, /* ABIT VA-20 */
-		{ .vendor = 0x147b, .device = 0x1413, .action = VIA_DXS_ENABLE }, /* ABIT KV8 Pro */
-		{ .vendor = 0x147b, .device = 0x1415, .action = VIA_DXS_NO_VRA }, /* Abit AV8 */
-		{ .vendor = 0x14ff, .device = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */
-		{ .vendor = 0x1584, .device = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */
-		{ .vendor = 0x1584, .device = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */
-		{ .vendor = 0x161f, .device = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */
-		{ .vendor = 0x161f, .device = 0x2032, .action = VIA_DXS_48K }, /* m680x machines */
-		{ .vendor = 0x1631, .device = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */
-		{ .vendor = 0x1695, .device = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */
-		{ .vendor = 0x1849, .device = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */
+		{ .subvendor = 0x1005, .subdevice = 0x4710, .action = VIA_DXS_ENABLE }, /* Avance Logic Mobo */
+		{ .subvendor = 0x1019, .subdevice = 0x0996, .action = VIA_DXS_48K },
+		{ .subvendor = 0x1019, .subdevice = 0x0a81, .action = VIA_DXS_NO_VRA }, /* ECS K7VTA3 v8.0 */
+		{ .subvendor = 0x1019, .subdevice = 0x0a85, .action = VIA_DXS_NO_VRA }, /* ECS L7VMM2 */
+		{ .subvendor = 0x1025, .subdevice = 0x0033, .action = VIA_DXS_NO_VRA }, /* Acer Inspire 1353LM */
+		{ .subvendor = 0x1043, .subdevice = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/
+		{ .subvendor = 0x1043, .subdevice = 0x80a1, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8-X */
+		{ .subvendor = 0x1043, .subdevice = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/ 
+		{ .subvendor = 0x1043, .subdevice = 0x812a, .action = VIA_DXS_SRC    }, /* ASUS A8V Deluxe */ 
+		{ .subvendor = 0x1071, .subdevice = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */
+		{ .subvendor = 0x1071, .subdevice = 0x8399, .action = VIA_DXS_NO_VRA }, /* Umax AB 595T (VIA K8N800A - VT8237) */
+		{ .subvendor = 0x10cf, .subdevice = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */
+		{ .subvendor = 0x1106, .subdevice = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */
+		{ .subvendor = 0x1106, .subdevice = 0x4552, .action = VIA_DXS_NO_VRA }, /* QDI Kudoz 7X/600-6AL */
+		{ .subvendor = 0x1106, .subdevice = 0xaa01, .action = VIA_DXS_NO_VRA }, /* EPIA MII */
+		{ .subvendor = 0x1106, .subdevice = 0xc001, .action = VIA_DXS_SRC }, /* Insight P4-ITX */
+		{ .subvendor = 0x1297, .subdevice = 0xa232, .action = VIA_DXS_ENABLE }, /* Shuttle ?? */
+		{ .subvendor = 0x1297, .subdevice = 0xc160, .action = VIA_DXS_ENABLE }, /* Shuttle SK41G */
+		{ .subvendor = 0x1458, .subdevice = 0xa002, .action = VIA_DXS_ENABLE }, /* Gigabyte GA-7VAXP */
+		{ .subvendor = 0x1462, .subdevice = 0x0080, .action = VIA_DXS_SRC }, /* MSI K8T Neo-FIS2R */
+		{ .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 = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */
+		{ .subvendor = 0x147b, .subdevice = 0x1401, .action = VIA_DXS_ENABLE }, /* ABIT KD7(-RAID) */
+		{ .subvendor = 0x147b, .subdevice = 0x1411, .action = VIA_DXS_ENABLE }, /* ABIT VA-20 */
+		{ .subvendor = 0x147b, .subdevice = 0x1413, .action = VIA_DXS_ENABLE }, /* ABIT KV8 Pro */
+		{ .subvendor = 0x147b, .subdevice = 0x1415, .action = VIA_DXS_NO_VRA }, /* Abit AV8 */
+		{ .subvendor = 0x14ff, .subdevice = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */
+		{ .subvendor = 0x14ff, .subdevice = 0x0408, .action = VIA_DXS_NO_VRA }, /* Twinhead mobo */
+		{ .subvendor = 0x1584, .subdevice = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */
+		{ .subvendor = 0x1584, .subdevice = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */
+		{ .subvendor = 0x161f, .subdevice = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */
+		{ .subvendor = 0x161f, .subdevice = 0x2032, .action = VIA_DXS_48K }, /* m680x machines */
+		{ .subvendor = 0x1631, .subdevice = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */
+		{ .subvendor = 0x1695, .subdevice = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */
+		{ .subvendor = 0x1849, .subdevice = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */
+		{ .subvendor = 0x1919, .subdevice = 0x200a, .action = VIA_DXS_NO_VRA }, /* Soltek SL-K8Tpro-939 */
 		{ } /* terminator */
 	};
 	struct dxs_whitelist *w;
@@ -2182,14 +2196,14 @@
 	pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
 	pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device);
 
-	for (w = whitelist; w->vendor; w++) {
-		if (w->vendor != subsystem_vendor)
+	for (w = whitelist; w->subvendor; w++) {
+		if (w->subvendor != subsystem_vendor)
 			continue;
 		if (w->mask) {
-			if ((w->mask & subsystem_device) == w->device)
+			if ((w->mask & subsystem_device) == w->subdevice)
 				return w->action;
 		} else {
-			if (subsystem_device == w->device)
+			if (subsystem_device == w->subdevice)
 				return w->action;
 		}
 	}
@@ -2198,8 +2212,9 @@
 	 * not detected, try 48k rate only to be sure.
 	 */
 	printk(KERN_INFO "via82xx: Assuming DXS channels with 48k fixed sample rate.\n");
-	printk(KERN_INFO "         Please try dxs_support=1 or dxs_support=4 option\n");
+	printk(KERN_INFO "         Please try dxs_support=5 option\n");
 	printk(KERN_INFO "         and report if it works on your machine.\n");
+	printk(KERN_INFO "         For more details, read ALSA-Configuration.txt.\n");
 	return VIA_DXS_48K;
 };
 
@@ -2288,6 +2303,10 @@
 				chip->dxs_fixed = 1;
 			else if (dxs_support[dev] == VIA_DXS_NO_VRA)
 				chip->no_vra = 1;
+			else if (dxs_support[dev] == VIA_DXS_SRC) {
+				chip->no_vra = 1;
+				chip->dxs_src = 1;
+			}
 		}
 		if ((err = snd_via8233_init_misc(chip, dev)) < 0)
 			goto __error;
@@ -2334,7 +2353,7 @@
 
 static int __init alsa_card_via82xx_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_via82xx_exit(void)
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index ea5c6f6..5896d28 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -352,10 +352,8 @@
 		snd_dma_free_pages(&dev->table);
 		dev->table.area = NULL;
 	}
-	if (dev->idx_table) {
-		kfree(dev->idx_table);
-		dev->idx_table = NULL;
-	}
+	kfree(dev->idx_table);
+	dev->idx_table = NULL;
 	return 0;
 }
 
@@ -420,7 +418,10 @@
 {
 	via82xx_t *chip = ac97->private_data;
 	unsigned int xval;
-	
+	if(reg == AC97_GPIO_STATUS) {
+		outl(val, VIAREG(chip, GPI_STATUS));
+		return;
+	}	
 	xval = !ac97->num ? VIA_REG_AC97_CODEC_ID_PRIMARY : VIA_REG_AC97_CODEC_ID_SECONDARY;
 	xval <<= VIA_REG_AC97_CODEC_ID_SHIFT;
 	xval |= reg << VIA_REG_AC97_CMD_SHIFT;
@@ -544,25 +545,6 @@
 	return 0;
 }
 
-static int snd_via82xx_modem_pcm_trigger(snd_pcm_substream_t * substream, int cmd)
-{
-	via82xx_t *chip = snd_pcm_substream_chip(substream);
-	unsigned int val = 0;
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		val = snd_ac97_read(chip->ac97, AC97_GPIO_STATUS);
-		outl(val|AC97_GPIO_LINE1_OH, VIAREG(chip, GPI_STATUS));
-		break;
-	case SNDRV_PCM_TRIGGER_STOP:
-		val = snd_ac97_read(chip->ac97, AC97_GPIO_STATUS);
-		outl(val&~AC97_GPIO_LINE1_OH, VIAREG(chip, GPI_STATUS));
-		break;
-	default:
-		break;
-	}
-	return snd_via82xx_pcm_trigger(substream, cmd);
-}
-
 /*
  * pointer callbacks
  */
@@ -806,7 +788,7 @@
 	.hw_params =	snd_via82xx_hw_params,
 	.hw_free =	snd_via82xx_hw_free,
 	.prepare =	snd_via82xx_pcm_prepare,
-	.trigger =	snd_via82xx_modem_pcm_trigger,
+	.trigger =	snd_via82xx_pcm_trigger,
 	.pointer =	snd_via686_pcm_pointer,
 	.page =		snd_pcm_sgbuf_ops_page,
 };
@@ -819,7 +801,7 @@
 	.hw_params =	snd_via82xx_hw_params,
 	.hw_free =	snd_via82xx_hw_free,
 	.prepare =	snd_via82xx_pcm_prepare,
-	.trigger =	snd_via82xx_modem_pcm_trigger,
+	.trigger =	snd_via82xx_pcm_trigger,
 	.pointer =	snd_via686_pcm_pointer,
 	.page =		snd_pcm_sgbuf_ops_page,
 };
@@ -938,7 +920,7 @@
  *
  */
 
-static int __devinit snd_via82xx_chip_init(via82xx_t *chip)
+static int snd_via82xx_chip_init(via82xx_t *chip)
 {
 	unsigned int val;
 	int max_count;
@@ -1233,7 +1215,7 @@
 
 static int __init alsa_card_via82xx_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_via82xx_exit(void)
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index 4ffbb25..dca6bd2 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -260,7 +260,7 @@
 
 static int __init alsa_card_vx222_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_vx222_exit(void)
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index 9f3ef22..5b5b624 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -360,7 +360,7 @@
 
 static int __init alsa_card_ymfpci_init(void)
 {
-	return pci_module_init(&driver);
+	return pci_register_driver(&driver);
 }
 
 static void __exit alsa_card_ymfpci_exit(void)
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 05f1629..2ae7961 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -829,9 +829,7 @@
 
 static void snd_ymfpci_pcm_free_substream(snd_pcm_runtime_t *runtime)
 {
-	ymfpci_pcm_t *ypcm = runtime->private_data;
-	
-	kfree(ypcm);
+	kfree(runtime->private_data);
 }
 
 static int snd_ymfpci_playback_open_1(snd_pcm_substream_t * substream)
@@ -1421,17 +1419,15 @@
 
 static int snd_ymfpci_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
-	unsigned int mask = 1;
-
 	switch (kcontrol->private_value) {
 	case YDSXGR_SPDIFOUTCTRL: break;
 	case YDSXGR_SPDIFINCTRL: break;
 	default: return -EINVAL;
 	}
-	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 	uinfo->count = 1;
 	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = mask;
+	uinfo->value.integer.max = 1;
 	return 0;
 }
 
@@ -1439,7 +1435,7 @@
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
 	int reg = kcontrol->private_value;
-	unsigned int shift = 0, mask = 1, invert = 0;
+	unsigned int shift = 0, mask = 1;
 	
 	switch (kcontrol->private_value) {
 	case YDSXGR_SPDIFOUTCTRL: break;
@@ -1447,8 +1443,6 @@
 	default: return -EINVAL;
 	}
 	ucontrol->value.integer.value[0] = (snd_ymfpci_readl(chip, reg) >> shift) & mask;
-	if (invert)
-		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
 	return 0;
 }
 
@@ -1456,7 +1450,7 @@
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
 	int reg = kcontrol->private_value;
-	unsigned int shift = 0, mask = 1, invert = 0;
+	unsigned int shift = 0, mask = 1;
 	int change;
 	unsigned int val, oval;
 	
@@ -1466,8 +1460,6 @@
 	default: return -EINVAL;
 	}
 	val = (ucontrol->value.integer.value[0] & mask);
-	if (invert)
-		val = mask - val;
 	val <<= shift;
 	spin_lock_irq(&chip->reg_lock);
 	oval = snd_ymfpci_readl(chip, reg);
@@ -1487,14 +1479,13 @@
 static int snd_ymfpci_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
 	unsigned int reg = kcontrol->private_value;
-	unsigned int mask = 16383;
 
 	if (reg < 0x80 || reg >= 0xc0)
 		return -EINVAL;
-	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 	uinfo->count = 2;
 	uinfo->value.integer.min = 0;
-	uinfo->value.integer.max = mask;
+	uinfo->value.integer.max = 16383;
 	return 0;
 }
 
@@ -1502,7 +1493,7 @@
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
 	unsigned int reg = kcontrol->private_value;
-	unsigned int shift_left = 0, shift_right = 16, mask = 16383, invert = 0;
+	unsigned int shift_left = 0, shift_right = 16, mask = 16383;
 	unsigned int val;
 	
 	if (reg < 0x80 || reg >= 0xc0)
@@ -1512,10 +1503,6 @@
 	spin_unlock_irq(&chip->reg_lock);
 	ucontrol->value.integer.value[0] = (val >> shift_left) & mask;
 	ucontrol->value.integer.value[1] = (val >> shift_right) & mask;
-	if (invert) {
-		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
-		ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
-	}
 	return 0;
 }
 
@@ -1523,7 +1510,7 @@
 {
 	ymfpci_t *chip = snd_kcontrol_chip(kcontrol);
 	unsigned int reg = kcontrol->private_value;
-	unsigned int shift_left = 0, shift_right = 16, mask = 16383, invert = 0;
+	unsigned int shift_left = 0, shift_right = 16, mask = 16383;
 	int change;
 	unsigned int val1, val2, oval;
 	
@@ -1531,10 +1518,6 @@
 		return -EINVAL;
 	val1 = ucontrol->value.integer.value[0] & mask;
 	val2 = ucontrol->value.integer.value[1] & mask;
-	if (invert) {
-		val1 = mask - val1;
-		val2 = mask - val2;
-	}
 	val1 <<= shift_left;
 	val2 <<= shift_right;
 	spin_lock_irq(&chip->reg_lock);
diff --git a/sound/pcmcia/vx/vx_entry.c b/sound/pcmcia/vx/vx_entry.c
index 53d8172..332bbca 100644
--- a/sound/pcmcia/vx/vx_entry.c
+++ b/sound/pcmcia/vx/vx_entry.c
@@ -68,8 +68,7 @@
 	if (hw)
 		hw->card_list[vxp->index] = NULL;
 	chip->card = NULL;
-	if (chip->dev)
-		kfree(chip->dev);
+	kfree(chip->dev);
 
 	snd_vx_free_firmware(chip);
 	kfree(chip);
diff --git a/sound/sound_core.c b/sound/sound_core.c
index 30f75c9..21a69e0 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -65,7 +65,7 @@
 extern int msnd_pinnacle_init(void);
 #endif
 
-struct class_simple *sound_class;
+struct class *sound_class;
 EXPORT_SYMBOL(sound_class);
 
 /*
@@ -174,7 +174,7 @@
 
 	devfs_mk_cdev(MKDEV(SOUND_MAJOR, s->unit_minor),
 			S_IFCHR | mode, s->name);
-	class_simple_device_add(sound_class, MKDEV(SOUND_MAJOR, s->unit_minor),
+	class_device_create(sound_class, MKDEV(SOUND_MAJOR, s->unit_minor),
 				NULL, s->name+6);
 	return r;
 
@@ -198,7 +198,7 @@
 	spin_unlock(&sound_loader_lock);
 	if (p) {
 		devfs_remove(p->name);
-		class_simple_device_remove(MKDEV(SOUND_MAJOR, p->unit_minor));
+		class_device_destroy(sound_class, MKDEV(SOUND_MAJOR, p->unit_minor));
 		kfree(p);
 	}
 }
@@ -562,7 +562,7 @@
 	   empty */
 	unregister_chrdev(SOUND_MAJOR, "sound");
 	devfs_remove("sound");
-	class_simple_destroy(sound_class);
+	class_destroy(sound_class);
 }
 
 static int __init init_soundcore(void)
@@ -572,7 +572,7 @@
 		return -EBUSY;
 	}
 	devfs_mk_dir ("sound");
-	sound_class = class_simple_create(THIS_MODULE, "sound");
+	sound_class = class_create(THIS_MODULE, "sound");
 	if (IS_ERR(sound_class))
 		return PTR_ERR(sound_class);
 
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c
index 16f3b46..60d0b2c 100644
--- a/sound/synth/emux/emux.c
+++ b/sound/synth/emux/emux.c
@@ -22,6 +22,7 @@
 #include <linux/wait.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/string.h>
 #include <sound/core.h>
 #include <sound/emux_synth.h>
 #include <linux/init.h>
@@ -76,7 +77,7 @@
 	snd_assert(name != NULL, return -EINVAL);
 
 	emu->card = card;
-	emu->name = snd_kmalloc_strdup(name, GFP_KERNEL);
+	emu->name = kstrdup(name, GFP_KERNEL);
 	emu->voices = kcalloc(emu->max_voices, sizeof(snd_emux_voice_t), GFP_KERNEL);
 	if (emu->voices == NULL)
 		return -ENOMEM;
diff --git a/sound/synth/emux/emux_effect.c b/sound/synth/emux/emux_effect.c
index ec3fc1b..4764940 100644
--- a/sound/synth/emux/emux_effect.c
+++ b/sound/synth/emux/emux_effect.c
@@ -291,10 +291,8 @@
 void
 snd_emux_delete_effect(snd_emux_port_t *p)
 {
-	if (p->effect) {
-		kfree(p->effect);
-		p->effect = NULL;
-	}
+	kfree(p->effect);
+	p->effect = NULL;
 }
 
 void
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index 9329e99..f05d02f 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -6,6 +6,7 @@
 config SND_USB_AUDIO
 	tristate "USB Audio/MIDI driver"
 	depends on SND && USB
+	select SND_HWDEP
 	select SND_RAWMIDI
 	select SND_PCM
 	help
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 84b0bbd..a756950 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -98,7 +98,7 @@
 #define MAX_PACKS	10
 #define MAX_PACKS_HS	(MAX_PACKS * 8)	/* in high speed mode */
 #define MAX_URBS	5	/* max. 20ms long packets */
-#define SYNC_URBS	2	/* always two urbs for sync */
+#define SYNC_URBS	4	/* always four urbs for sync */
 #define MIN_PACKS_URB	1	/* minimum 1 packet per urb */
 
 typedef struct snd_usb_substream snd_usb_substream_t;
@@ -177,7 +177,7 @@
 	unsigned int nurbs;			/* # urbs */
 	snd_urb_ctx_t dataurb[MAX_URBS];	/* data urb table */
 	snd_urb_ctx_t syncurb[SYNC_URBS];	/* sync urb table */
-	char syncbuf[SYNC_URBS * MAX_PACKS * 4]; /* sync buffer; it's so small - let's get static */
+	char syncbuf[SYNC_URBS * 4];	/* sync buffer; it's so small - let's get static */
 	char *tmpbuf;			/* temporary buffer for playback */
 
 	u64 formats;			/* format bitmasks (all or'ed) */
@@ -251,17 +251,13 @@
 {
 	unsigned char *cp = urb->transfer_buffer;
 	snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
-	int i, offs;
 
-	urb->number_of_packets = ctx->packets;
 	urb->dev = ctx->subs->dev; /* we need to set this at each time */
-	for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4, cp += 4) {
-		urb->iso_frame_desc[i].length = 3;
-		urb->iso_frame_desc[i].offset = offs;
-		cp[0] = subs->freqn >> 2;
-		cp[1] = subs->freqn >> 10;
-		cp[2] = subs->freqn >> 18;
-	}
+	urb->iso_frame_desc[0].length = 3;
+	urb->iso_frame_desc[0].offset = 0;
+	cp[0] = subs->freqn >> 2;
+	cp[1] = subs->freqn >> 10;
+	cp[2] = subs->freqn >> 18;
 	return 0;
 }
 
@@ -277,18 +273,14 @@
 {
 	unsigned char *cp = urb->transfer_buffer;
 	snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
-	int i, offs;
 
-	urb->number_of_packets = ctx->packets;
 	urb->dev = ctx->subs->dev; /* we need to set this at each time */
-	for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4, cp += 4) {
-		urb->iso_frame_desc[i].length = 4;
-		urb->iso_frame_desc[i].offset = offs;
-		cp[0] = subs->freqn;
-		cp[1] = subs->freqn >> 8;
-		cp[2] = subs->freqn >> 16;
-		cp[3] = subs->freqn >> 24;
-	}
+	urb->iso_frame_desc[0].length = 4;
+	urb->iso_frame_desc[0].offset = 0;
+	cp[0] = subs->freqn;
+	cp[1] = subs->freqn >> 8;
+	cp[2] = subs->freqn >> 16;
+	cp[3] = subs->freqn >> 24;
 	return 0;
 }
 
@@ -418,15 +410,11 @@
 				     snd_pcm_runtime_t *runtime,
 				     struct urb *urb)
 {
-	int i, offs;
 	snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
 
-	urb->number_of_packets = ctx->packets;
 	urb->dev = ctx->subs->dev; /* we need to set this at each time */
-	for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4) {
-		urb->iso_frame_desc[i].length = 3;
-		urb->iso_frame_desc[i].offset = offs;
-	}
+	urb->iso_frame_desc[0].length = 3;
+	urb->iso_frame_desc[0].offset = 0;
 	return 0;
 }
 
@@ -440,15 +428,11 @@
 					snd_pcm_runtime_t *runtime,
 					struct urb *urb)
 {
-	int i, offs;
 	snd_urb_ctx_t *ctx = (snd_urb_ctx_t *)urb->context;
 
-	urb->number_of_packets = ctx->packets;
 	urb->dev = ctx->subs->dev; /* we need to set this at each time */
-	for (i = offs = 0; i < urb->number_of_packets; i++, offs += 4) {
-		urb->iso_frame_desc[i].length = 4;
-		urb->iso_frame_desc[i].offset = offs;
-	}
+	urb->iso_frame_desc[0].length = 4;
+	urb->iso_frame_desc[0].offset = 0;
 	return 0;
 }
 
@@ -462,31 +446,17 @@
 				    snd_pcm_runtime_t *runtime,
 				    struct urb *urb)
 {
-	int i;
-	unsigned int f, found;
-	unsigned char *cp = urb->transfer_buffer;
+	unsigned int f;
 	unsigned long flags;
 
-	found = 0;
-	for (i = 0; i < urb->number_of_packets; i++, cp += 4) {
-		if (urb->iso_frame_desc[i].status ||
-		    urb->iso_frame_desc[i].actual_length < 3)
-			continue;
-		f = combine_triple(cp) << 2;
-#if 0
-		if (f < subs->freqn - (subs->freqn>>3) || f > subs->freqmax) {
-			snd_printd(KERN_WARNING "requested frequency %d (%u,%03uHz) out of range (current nominal %d (%u,%03uHz))\n",
-				   f, f >> 14, (f & ((1 << 14) - 1) * 1000) / ((1 << 14) - 1),
-				   subs->freqn, subs->freqn >> 14, (subs->freqn & ((1 << 14) - 1) * 1000) / ((1 << 14) - 1));
-			continue;
+	if (urb->iso_frame_desc[0].status == 0 &&
+	    urb->iso_frame_desc[0].actual_length == 3) {
+		f = combine_triple((u8*)urb->transfer_buffer) << 2;
+		if (f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax) {
+			spin_lock_irqsave(&subs->lock, flags);
+			subs->freqm = f;
+			spin_unlock_irqrestore(&subs->lock, flags);
 		}
-#endif
-		found = f;
-	}
-	if (found) {
-		spin_lock_irqsave(&subs->lock, flags);
-		subs->freqm = found;
-		spin_unlock_irqrestore(&subs->lock, flags);
 	}
 
 	return 0;
@@ -502,22 +472,17 @@
 				       snd_pcm_runtime_t *runtime,
 				       struct urb *urb)
 {
-	int i;
-	unsigned int found;
-	unsigned char *cp = urb->transfer_buffer;
+	unsigned int f;
 	unsigned long flags;
 
-	found = 0;
-	for (i = 0; i < urb->number_of_packets; i++, cp += 4) {
-		if (urb->iso_frame_desc[i].status ||
-		    urb->iso_frame_desc[i].actual_length < 4)
-			continue;
-		found = combine_quad(cp) & 0x0fffffff;
-	}
-	if (found) {
-		spin_lock_irqsave(&subs->lock, flags);
-		subs->freqm = found;
-		spin_unlock_irqrestore(&subs->lock, flags);
+	if (urb->iso_frame_desc[0].status == 0 &&
+	    urb->iso_frame_desc[0].actual_length == 4) {
+		f = combine_quad((u8*)urb->transfer_buffer) & 0x0fffffff;
+		if (f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax) {
+			spin_lock_irqsave(&subs->lock, flags);
+			subs->freqm = f;
+			spin_unlock_irqrestore(&subs->lock, flags);
+		}
 	}
 
 	return 0;
@@ -600,6 +565,8 @@
 		/* set the buffer pointer */
 		urb->transfer_buffer = runtime->dma_area + subs->hwptr * stride;
 		subs->hwptr += offs;
+		if (subs->hwptr == runtime->buffer_size)
+			subs->hwptr = 0;
 	}
 	spin_unlock_irqrestore(&subs->lock, flags);
 	urb->transfer_buffer_length = offs * stride;
@@ -892,10 +859,8 @@
 		usb_free_urb(u->urb);
 		u->urb = NULL;
 	}
-	if (u->buf) {
-		kfree(u->buf);
-		u->buf = NULL;
-	}
+	kfree(u->buf);
+	u->buf = NULL;
 }
 
 /*
@@ -913,10 +878,8 @@
 		release_urb_ctx(&subs->dataurb[i]);
 	for (i = 0; i < SYNC_URBS; i++)
 		release_urb_ctx(&subs->syncurb[i]);
-	if (subs->tmpbuf) {
-		kfree(subs->tmpbuf);
-		subs->tmpbuf = NULL;
-	}
+	kfree(subs->tmpbuf);
+	subs->tmpbuf = NULL;
 	subs->nurbs = 0;
 }
 
@@ -1039,22 +1002,19 @@
 			snd_urb_ctx_t *u = &subs->syncurb[i];
 			u->index = i;
 			u->subs = subs;
-			u->packets = nrpacks;
-			u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
+			u->packets = 1;
+			u->urb = usb_alloc_urb(1, GFP_KERNEL);
 			if (! u->urb) {
 				release_substream_urbs(subs, 0);
 				return -ENOMEM;
 			}
-			u->urb->transfer_buffer = subs->syncbuf + i * nrpacks * 4;
-			u->urb->transfer_buffer_length = nrpacks * 4;
+			u->urb->transfer_buffer = subs->syncbuf + i * 4;
+			u->urb->transfer_buffer_length = 4;
 			u->urb->dev = subs->dev;
 			u->urb->pipe = subs->syncpipe;
 			u->urb->transfer_flags = URB_ISO_ASAP;
-			u->urb->number_of_packets = u->packets;
-			if (snd_usb_get_speed(subs->dev) == USB_SPEED_HIGH)
-				u->urb->interval = 8;
-			else
-				u->urb->interval = 1;
+			u->urb->number_of_packets = 1;
+			u->urb->interval = 1 << subs->syncinterval;
 			u->urb->context = u;
 			u->urb->complete = snd_usb_complete_callback(snd_complete_sync_urb);
 		}
@@ -1272,7 +1232,17 @@
 			subs->syncpipe = usb_rcvisocpipe(dev, ep);
 		else
 			subs->syncpipe = usb_sndisocpipe(dev, ep);
-		subs->syncinterval = get_endpoint(alts, 1)->bRefresh;
+		if (get_endpoint(alts, 1)->bLength >= USB_DT_ENDPOINT_AUDIO_SIZE &&
+		    get_endpoint(alts, 1)->bRefresh >= 1 &&
+		    get_endpoint(alts, 1)->bRefresh <= 9)
+			subs->syncinterval = get_endpoint(alts, 1)->bRefresh;
+		else if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
+			subs->syncinterval = 1;
+		else if (get_endpoint(alts, 1)->bInterval >= 1 &&
+			 get_endpoint(alts, 1)->bInterval <= 16)
+			subs->syncinterval = get_endpoint(alts, 1)->bInterval - 1;
+		else
+			subs->syncinterval = 3;
 	}
 
 	/* always fill max packet size */
@@ -1990,10 +1960,11 @@
 			snd_iprintf(buffer, "%d ", subs->dataurb[i].packets);
 		snd_iprintf(buffer, "]\n");
 		snd_iprintf(buffer, "    Packet Size = %d\n", subs->curpacksize);
-		snd_iprintf(buffer, "    Momentary freq = %u Hz\n",
+		snd_iprintf(buffer, "    Momentary freq = %u Hz (%#x.%04x)\n",
 			    snd_usb_get_speed(subs->dev) == USB_SPEED_FULL
 			    ? get_full_speed_hz(subs->freqm)
-			    : get_high_speed_hz(subs->freqm));
+			    : get_high_speed_hz(subs->freqm),
+			    subs->freqm >> 16, subs->freqm & 0xffff);
 	} else {
 		snd_iprintf(buffer, "  Status: Stop\n");
 	}
@@ -2183,17 +2154,15 @@
 /*
  * check if the device uses big-endian samples
  */
-static int is_big_endian_format(struct usb_device *dev, struct audioformat *fp)
+static int is_big_endian_format(snd_usb_audio_t *chip, struct audioformat *fp)
 {
-	/* M-Audio */
-	if (le16_to_cpu(dev->descriptor.idVendor) == 0x0763) {
-		/* Quattro: captured data only */
-		if (le16_to_cpu(dev->descriptor.idProduct) == 0x2001 &&
-		    fp->endpoint & USB_DIR_IN)
+	switch (chip->usb_id) {
+	case USB_ID(0x0763, 0x2001): /* M-Audio Quattro: captured data only */
+		if (fp->endpoint & USB_DIR_IN)
 			return 1;
-		/* Audiophile USB */
-		if (le16_to_cpu(dev->descriptor.idProduct) == 0x2003)
-			return 1;
+		break;
+	case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
+		return 1;
 	}
 	return 0;
 }
@@ -2207,7 +2176,7 @@
  * @format: the format tag (wFormatTag)
  * @fmt: the format type descriptor
  */
-static int parse_audio_format_i_type(struct usb_device *dev, struct audioformat *fp,
+static int parse_audio_format_i_type(snd_usb_audio_t *chip, struct audioformat *fp,
 				     int format, unsigned char *fmt)
 {
 	int pcm_format;
@@ -2220,12 +2189,12 @@
 	switch (format) {
 	case 0: /* some devices don't define this correctly... */
 		snd_printdd(KERN_INFO "%d:%u:%d : format type 0 is detected, processed as PCM\n",
-			    dev->devnum, fp->iface, fp->altsetting);
+			    chip->dev->devnum, fp->iface, fp->altsetting);
 		/* fall-through */
 	case USB_AUDIO_FORMAT_PCM:
 		if (sample_width > sample_bytes * 8) {
 			snd_printk(KERN_INFO "%d:%u:%d : sample bitwidth %d in over sample bytes %d\n",
-				   dev->devnum, fp->iface, fp->altsetting,
+				   chip->dev->devnum, fp->iface, fp->altsetting,
 				   sample_width, sample_bytes);
 		}
 		/* check the format byte size */
@@ -2234,13 +2203,13 @@
 			pcm_format = SNDRV_PCM_FORMAT_S8;
 			break;
 		case 2:
-			if (is_big_endian_format(dev, fp))
+			if (is_big_endian_format(chip, fp))
 				pcm_format = SNDRV_PCM_FORMAT_S16_BE; /* grrr, big endian!! */
 			else
 				pcm_format = SNDRV_PCM_FORMAT_S16_LE;
 			break;
 		case 3:
-			if (is_big_endian_format(dev, fp))
+			if (is_big_endian_format(chip, fp))
 				pcm_format = SNDRV_PCM_FORMAT_S24_3BE; /* grrr, big endian!! */
 			else
 				pcm_format = SNDRV_PCM_FORMAT_S24_3LE;
@@ -2250,14 +2219,14 @@
 			break;
 		default:
 			snd_printk(KERN_INFO "%d:%u:%d : unsupported sample bitwidth %d in %d bytes\n",
-				   dev->devnum, fp->iface, fp->altsetting, sample_width, sample_bytes);
+				   chip->dev->devnum, fp->iface,
+				   fp->altsetting, sample_width, sample_bytes);
 			break;
 		}
 		break;
 	case USB_AUDIO_FORMAT_PCM8:
 		/* Dallas DS4201 workaround */
-		if (le16_to_cpu(dev->descriptor.idVendor) == 0x04fa &&
-		    le16_to_cpu(dev->descriptor.idProduct) == 0x4201)
+		if (chip->usb_id == USB_ID(0x04fa, 0x4201))
 			pcm_format = SNDRV_PCM_FORMAT_S8;
 		else
 			pcm_format = SNDRV_PCM_FORMAT_U8;
@@ -2273,7 +2242,7 @@
 		break;
 	default:
 		snd_printk(KERN_INFO "%d:%u:%d : unsupported format type %d\n",
-			   dev->devnum, fp->iface, fp->altsetting, format);
+			   chip->dev->devnum, fp->iface, fp->altsetting, format);
 		break;
 	}
 	return pcm_format;
@@ -2290,13 +2259,13 @@
  * @offset: the start offset of descriptor pointing the rate type
  *          (7 for type I and II, 8 for type II)
  */
-static int parse_audio_format_rates(struct usb_device *dev, struct audioformat *fp,
+static int parse_audio_format_rates(snd_usb_audio_t *chip, struct audioformat *fp,
 				    unsigned char *fmt, int offset)
 {
 	int nr_rates = fmt[offset];
 	if (fmt[0] < offset + 1 + 3 * (nr_rates ? nr_rates : 2)) {
 		snd_printk(KERN_ERR "%d:%u:%d : invalid FORMAT_TYPE desc\n",
-				   dev->devnum, fp->iface, fp->altsetting);
+				   chip->dev->devnum, fp->iface, fp->altsetting);
 		return -1;
 	}
 
@@ -2343,7 +2312,7 @@
 /*
  * parse the format type I and III descriptors
  */
-static int parse_audio_format_i(struct usb_device *dev, struct audioformat *fp,
+static int parse_audio_format_i(snd_usb_audio_t *chip, struct audioformat *fp,
 				int format, unsigned char *fmt)
 {
 	int pcm_format;
@@ -2355,7 +2324,7 @@
 		 */
 		pcm_format = SNDRV_PCM_FORMAT_S16_LE;
 	} else {
-		pcm_format = parse_audio_format_i_type(dev, fp, format, fmt);
+		pcm_format = parse_audio_format_i_type(chip, fp, format, fmt);
 		if (pcm_format < 0)
 			return -1;
 	}
@@ -2363,16 +2332,16 @@
 	fp->channels = fmt[4];
 	if (fp->channels < 1) {
 		snd_printk(KERN_ERR "%d:%u:%d : invalid channels %d\n",
-			   dev->devnum, fp->iface, fp->altsetting, fp->channels);
+			   chip->dev->devnum, fp->iface, fp->altsetting, fp->channels);
 		return -1;
 	}
-	return parse_audio_format_rates(dev, fp, fmt, 7);
+	return parse_audio_format_rates(chip, fp, fmt, 7);
 }
 
 /*
  * prase the format type II descriptor
  */
-static int parse_audio_format_ii(struct usb_device *dev, struct audioformat *fp,
+static int parse_audio_format_ii(snd_usb_audio_t *chip, struct audioformat *fp,
 				 int format, unsigned char *fmt)
 {
 	int brate, framesize;
@@ -2387,7 +2356,7 @@
 		break;
 	default:
 		snd_printd(KERN_INFO "%d:%u:%d : unknown format tag 0x%x is detected.  processed as MPEG.\n",
-			   dev->devnum, fp->iface, fp->altsetting, format);
+			   chip->dev->devnum, fp->iface, fp->altsetting, format);
 		fp->format = SNDRV_PCM_FORMAT_MPEG;
 		break;
 	}
@@ -2396,10 +2365,10 @@
 	framesize = combine_word(&fmt[6]); /* fmt[6,7]: wSamplesPerFrame */
 	snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize);
 	fp->frame_size = framesize;
-	return parse_audio_format_rates(dev, fp, fmt, 8); /* fmt[8..] sample rates */
+	return parse_audio_format_rates(chip, fp, fmt, 8); /* fmt[8..] sample rates */
 }
 
-static int parse_audio_format(struct usb_device *dev, struct audioformat *fp,
+static int parse_audio_format(snd_usb_audio_t *chip, struct audioformat *fp,
 			      int format, unsigned char *fmt, int stream)
 {
 	int err;
@@ -2407,29 +2376,30 @@
 	switch (fmt[3]) {
 	case USB_FORMAT_TYPE_I:
 	case USB_FORMAT_TYPE_III:
-		err = parse_audio_format_i(dev, fp, format, fmt);
+		err = parse_audio_format_i(chip, fp, format, fmt);
 		break;
 	case USB_FORMAT_TYPE_II:
-		err = parse_audio_format_ii(dev, fp, format, fmt);
+		err = parse_audio_format_ii(chip, fp, format, fmt);
 		break;
 	default:
 		snd_printd(KERN_INFO "%d:%u:%d : format type %d is not supported yet\n",
-			   dev->devnum, fp->iface, fp->altsetting, fmt[3]);
+			   chip->dev->devnum, fp->iface, fp->altsetting, fmt[3]);
 		return -1;
 	}
 	fp->fmt_type = fmt[3];
 	if (err < 0)
 		return err;
 #if 1
-	/* FIXME: temporary hack for extigy */
+	/* FIXME: temporary hack for extigy/audigy 2 nx */
 	/* extigy apparently supports sample rates other than 48k
 	 * but not in ordinary way.  so we enable only 48k atm.
 	 */
-	if (le16_to_cpu(dev->descriptor.idVendor) == 0x041e && 
-	    le16_to_cpu(dev->descriptor.idProduct) == 0x3000) {
+	if (chip->usb_id == USB_ID(0x041e, 0x3000) ||
+	    chip->usb_id == USB_ID(0x041e, 0x3020)) {
 		if (fmt[3] == USB_FORMAT_TYPE_I &&
 		    stream == SNDRV_PCM_STREAM_PLAYBACK &&
-		    fp->rates != SNDRV_PCM_RATE_48000)
+		    fp->rates != SNDRV_PCM_RATE_48000 &&
+		    fp->rates != SNDRV_PCM_RATE_96000)
 			return -1; /* use 48k only */
 	}
 #endif
@@ -2528,40 +2498,35 @@
 
 		/* some quirks for attributes here */
 
-		/* workaround for AudioTrak Optoplay */
-		if (le16_to_cpu(dev->descriptor.idVendor) == 0x0a92 &&
-		    le16_to_cpu(dev->descriptor.idProduct) == 0x0053) {
+		switch (chip->usb_id) {
+		case USB_ID(0x0a92, 0x0053): /* AudioTrak Optoplay */
 			/* Optoplay sets the sample rate attribute although
 			 * it seems not supporting it in fact.
 			 */
 			fp->attributes &= ~EP_CS_ATTR_SAMPLE_RATE;
-		}
-
-		/* workaround for M-Audio Audiophile USB */
-		if (le16_to_cpu(dev->descriptor.idVendor) == 0x0763 &&
-		    le16_to_cpu(dev->descriptor.idProduct) == 0x2003) {
+			break;
+		case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */
+		case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
 			/* doesn't set the sample rate attribute, but supports it */
 			fp->attributes |= EP_CS_ATTR_SAMPLE_RATE;
-		}
-
+			break;
+		case USB_ID(0x047f, 0x0ca1): /* plantronics headset */
+		case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is
+						an older model 77d:223) */
 		/*
 		 * plantronics headset and Griffin iMic have set adaptive-in
 		 * although it's really not...
 		 */
-		if ((le16_to_cpu(dev->descriptor.idVendor) == 0x047f &&
-		     le16_to_cpu(dev->descriptor.idProduct) == 0x0ca1) ||
-		    /* Griffin iMic (note that there is an older model 77d:223) */
-		    (le16_to_cpu(dev->descriptor.idVendor) == 0x077d &&
-		     le16_to_cpu(dev->descriptor.idProduct) == 0x07af)) {
 			fp->ep_attr &= ~EP_ATTR_MASK;
 			if (stream == SNDRV_PCM_STREAM_PLAYBACK)
 				fp->ep_attr |= EP_ATTR_ADAPTIVE;
 			else
 				fp->ep_attr |= EP_ATTR_SYNC;
+			break;
 		}
 
 		/* ok, let's parse further... */
-		if (parse_audio_format(dev, fp, format, fmt, stream) < 0) {
+		if (parse_audio_format(chip, fp, format, fmt, stream) < 0) {
 			kfree(fp->rate_table);
 			kfree(fp);
 			continue;
@@ -2587,7 +2552,7 @@
  * disconnect streams
  * called from snd_usb_audio_disconnect()
  */
-static void snd_usb_stream_disconnect(struct list_head *head, struct usb_driver *driver)
+static void snd_usb_stream_disconnect(struct list_head *head)
 {
 	int idx;
 	snd_usb_stream_t *as;
@@ -2796,7 +2761,7 @@
 			.type = QUIRK_MIDI_FIXED_ENDPOINT,
 			.data = &ua25_ep
 		};
-		if (le16_to_cpu(chip->dev->descriptor.idProduct) == 0x002b)
+		if (chip->usb_id == USB_ID(0x0582, 0x002b))
 			return snd_usb_create_midi_interface(chip, iface,
 							     &ua700_quirk);
 		else
@@ -2959,6 +2924,25 @@
 	return 0;
 }
 
+static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev)
+{
+#if 0
+	/* TODO: enable this when high speed synchronization actually works */
+	u8 buf = 1;
+
+	snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), 0x2a,
+			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
+			0, 0, &buf, 1, 1000);
+	if (buf == 0) {
+		snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 0x29,
+				USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
+				1, 2000, NULL, 0, 1000);
+		return -ENODEV;
+	}
+#endif
+	return 0;
+}
+
 
 /*
  * audio-interface quirks
@@ -3015,8 +2999,8 @@
 	snd_usb_audio_t *chip = entry->private_data;
 	if (! chip->shutdown)
 		snd_iprintf(buffer, "%04x:%04x\n", 
-			    le16_to_cpu(chip->dev->descriptor.idVendor),
-			    le16_to_cpu(chip->dev->descriptor.idProduct));
+			    USB_ID_VENDOR(chip->usb_id),
+			    USB_ID_PRODUCT(chip->usb_id));
 }
 
 static void snd_usb_audio_create_proc(snd_usb_audio_t *chip)
@@ -3086,8 +3070,11 @@
 	chip->index = idx;
 	chip->dev = dev;
 	chip->card = card;
+	chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
+			      le16_to_cpu(dev->descriptor.idProduct));
 	INIT_LIST_HEAD(&chip->pcm_list);
 	INIT_LIST_HEAD(&chip->midi_list);
+	INIT_LIST_HEAD(&chip->mixer_list);
 
 	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
 		snd_usb_audio_free(chip);
@@ -3097,8 +3084,7 @@
 
 	strcpy(card->driver, "USB-Audio");
 	sprintf(component, "USB%04x:%04x",
-		le16_to_cpu(dev->descriptor.idVendor),
-		le16_to_cpu(dev->descriptor.idProduct));
+		USB_ID_VENDOR(chip->usb_id), USB_ID_PRODUCT(chip->usb_id));
 	snd_component_add(card, component);
 
 	/* retrieve the device string as shortname */
@@ -3110,8 +3096,8 @@
       			       card->shortname, sizeof(card->shortname)) <= 0) {
 			/* no name available from anywhere, so use ID */
 			sprintf(card->shortname, "USB Device %#04x:%#04x",
-				le16_to_cpu(dev->descriptor.idVendor),
-				le16_to_cpu(dev->descriptor.idProduct));
+				USB_ID_VENDOR(chip->usb_id),
+				USB_ID_PRODUCT(chip->usb_id));
 		}
 	}
 
@@ -3142,8 +3128,6 @@
 
 	snd_usb_audio_create_proc(chip);
 
-	snd_card_set_dev(card, &dev->dev);
-
 	*rchip = chip;
 	return 0;
 }
@@ -3169,21 +3153,28 @@
 	snd_usb_audio_t *chip;
 	struct usb_host_interface *alts;
 	int ifnum;
+	u32 id;
 
 	alts = &intf->altsetting[0];
 	ifnum = get_iface_desc(alts)->bInterfaceNumber;
+	id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
+		    le16_to_cpu(dev->descriptor.idProduct));
 
 	if (quirk && quirk->ifnum >= 0 && ifnum != quirk->ifnum)
 		goto __err_val;
 
 	/* SB Extigy needs special boot-up sequence */
 	/* if more models come, this will go to the quirk list. */
-	if (le16_to_cpu(dev->descriptor.idVendor) == 0x041e && 
-	    le16_to_cpu(dev->descriptor.idProduct) == 0x3000) {
+	if (id == USB_ID(0x041e, 0x3000)) {
 		if (snd_usb_extigy_boot_quirk(dev, intf) < 0)
 			goto __err_val;
 		config = dev->actconfig;
 	}
+	/* SB Audigy 2 NX needs its own boot-up magic, too */
+	if (id == USB_ID(0x041e, 0x3020)) {
+		if (snd_usb_audigy2nx_boot_quirk(dev) < 0)
+			goto __err_val;
+	}
 
 	/*
 	 * found a config.  now register to ALSA
@@ -3213,11 +3204,12 @@
 		}
 		for (i = 0; i < SNDRV_CARDS; i++)
 			if (enable[i] && ! usb_chip[i] &&
-			    (vid[i] == -1 || vid[i] == le16_to_cpu(dev->descriptor.idVendor)) &&
-			    (pid[i] == -1 || pid[i] == le16_to_cpu(dev->descriptor.idProduct))) {
+			    (vid[i] == -1 || vid[i] == USB_ID_VENDOR(id)) &&
+			    (pid[i] == -1 || pid[i] == USB_ID_PRODUCT(id))) {
 				if (snd_usb_audio_create(dev, i, quirk, &chip) < 0) {
 					goto __error;
 				}
+				snd_card_set_dev(chip->card, &intf->dev);
 				break;
 			}
 		if (! chip) {
@@ -3281,15 +3273,19 @@
 		snd_card_disconnect(card);
 		/* release the pcm resources */
 		list_for_each(p, &chip->pcm_list) {
-			snd_usb_stream_disconnect(p, &usb_audio_driver);
+			snd_usb_stream_disconnect(p);
 		}
 		/* release the midi resources */
 		list_for_each(p, &chip->midi_list) {
-			snd_usbmidi_disconnect(p, &usb_audio_driver);
+			snd_usbmidi_disconnect(p);
+		}
+		/* release mixer resources */
+		list_for_each(p, &chip->mixer_list) {
+			snd_usb_mixer_disconnect(p);
 		}
 		usb_chip[chip->index] = NULL;
 		up(&register_mutex);
-		snd_card_free_in_thread(card);
+		snd_card_free(card);
 	} else {
 		up(&register_mutex);
 	}
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index eecbf19..aedb42a 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -118,6 +118,11 @@
 /* maximum number of endpoints per interface */
 #define MIDI_MAX_ENDPOINTS 2
 
+/* handling of USB vendor/product ID pairs as 32-bit numbers */
+#define USB_ID(vendor, product) (((vendor) << 16) | (product))
+#define USB_ID_VENDOR(id) ((id) >> 16)
+#define USB_ID_PRODUCT(id) ((u16)(id))
+
 /*
  */
 
@@ -127,6 +132,7 @@
 	int index;
 	struct usb_device *dev;
 	snd_card_t *card;
+	u32 usb_id;
 	int shutdown;
 	int num_interfaces;
 
@@ -136,7 +142,7 @@
 	struct list_head midi_list;	/* list of midi interfaces */
 	int next_midi_device;
 
-	unsigned int ignore_ctl_error;	/* for mixer */
+	struct list_head mixer_list;	/* list of mixer interfaces */
 };
 
 /*
@@ -219,11 +225,12 @@
 int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout);
 
 int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif);
+void snd_usb_mixer_disconnect(struct list_head *p);
 
 int snd_usb_create_midi_interface(snd_usb_audio_t *chip, struct usb_interface *iface, const snd_usb_audio_quirk_t *quirk);
 void snd_usbmidi_input_stop(struct list_head* p);
 void snd_usbmidi_input_start(struct list_head* p);
-void snd_usbmidi_disconnect(struct list_head *p, struct usb_driver *driver);
+void snd_usbmidi_disconnect(struct list_head *p);
 
 /*
  * retrieve usb_interface descriptor from the host interface
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 5d32857..bee7006 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -912,7 +912,7 @@
 /*
  * Unlinks all URBs (must be done before the usb_device is deleted).
  */
-void snd_usbmidi_disconnect(struct list_head* p, struct usb_driver *driver)
+void snd_usbmidi_disconnect(struct list_head* p)
 {
 	snd_usb_midi_t* umidi;
 	int i;
@@ -955,88 +955,87 @@
  * such as internal control or synthesizer ports.
  */
 static struct {
-	__u16 vendor;
-	__u16 product;
+	u32 id;
 	int port;
 	const char *name_format;
 } snd_usbmidi_port_names[] = {
 	/* Roland UA-100 */
-	{0x0582, 0x0000, 2, "%s Control"},
+	{ USB_ID(0x0582, 0x0000), 2, "%s Control" },
 	/* Roland SC-8850 */
-	{0x0582, 0x0003, 0, "%s Part A"},
-	{0x0582, 0x0003, 1, "%s Part B"},
-	{0x0582, 0x0003, 2, "%s Part C"},
-	{0x0582, 0x0003, 3, "%s Part D"},
-	{0x0582, 0x0003, 4, "%s MIDI 1"},
-	{0x0582, 0x0003, 5, "%s MIDI 2"},
+	{ 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" },
 	/* Roland U-8 */
-	{0x0582, 0x0004, 0, "%s MIDI"},
-	{0x0582, 0x0004, 1, "%s Control"},
+	{ USB_ID(0x0582, 0x0004), 0, "%s MIDI" },
+	{ USB_ID(0x0582, 0x0004), 1, "%s Control" },
 	/* Roland SC-8820 */
-	{0x0582, 0x0007, 0, "%s Part A"},
-	{0x0582, 0x0007, 1, "%s Part B"},
-	{0x0582, 0x0007, 2, "%s MIDI"},
+	{ USB_ID(0x0582, 0x0007), 0, "%s Part A" },
+	{ USB_ID(0x0582, 0x0007), 1, "%s Part B" },
+	{ USB_ID(0x0582, 0x0007), 2, "%s MIDI" },
 	/* Roland SK-500 */
-	{0x0582, 0x000b, 0, "%s Part A"},
-	{0x0582, 0x000b, 1, "%s Part B"},
-	{0x0582, 0x000b, 2, "%s MIDI"},
+	{ USB_ID(0x0582, 0x000b), 0, "%s Part A" },
+	{ USB_ID(0x0582, 0x000b), 1, "%s Part B" },
+	{ USB_ID(0x0582, 0x000b), 2, "%s MIDI" },
 	/* Roland SC-D70 */
-	{0x0582, 0x000c, 0, "%s Part A"},
-	{0x0582, 0x000c, 1, "%s Part B"},
-	{0x0582, 0x000c, 2, "%s MIDI"},
+	{ USB_ID(0x0582, 0x000c), 0, "%s Part A" },
+	{ USB_ID(0x0582, 0x000c), 1, "%s Part B" },
+	{ USB_ID(0x0582, 0x000c), 2, "%s MIDI" },
 	/* Edirol UM-880 */
-	{0x0582, 0x0014, 8, "%s Control"},
+	{ USB_ID(0x0582, 0x0014), 8, "%s Control" },
 	/* Edirol SD-90 */
-	{0x0582, 0x0016, 0, "%s Part A"},
-	{0x0582, 0x0016, 1, "%s Part B"},
-	{0x0582, 0x0016, 2, "%s MIDI 1"},
-	{0x0582, 0x0016, 3, "%s MIDI 2"},
+	{ 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" },
 	/* Edirol UM-550 */
-	{0x0582, 0x0023, 5, "%s Control"},
+	{ USB_ID(0x0582, 0x0023), 5, "%s Control" },
 	/* Edirol SD-20 */
-	{0x0582, 0x0027, 0, "%s Part A"},
-	{0x0582, 0x0027, 1, "%s Part B"},
-	{0x0582, 0x0027, 2, "%s MIDI"},
+	{ USB_ID(0x0582, 0x0027), 0, "%s Part A" },
+	{ USB_ID(0x0582, 0x0027), 1, "%s Part B" },
+	{ USB_ID(0x0582, 0x0027), 2, "%s MIDI" },
 	/* Edirol SD-80 */
-	{0x0582, 0x0029, 0, "%s Part A"},
-	{0x0582, 0x0029, 1, "%s Part B"},
-	{0x0582, 0x0029, 2, "%s MIDI 1"},
-	{0x0582, 0x0029, 3, "%s MIDI 2"},
+	{ 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" },
 	/* Edirol UA-700 */
-	{0x0582, 0x002b, 0, "%s MIDI"},
-	{0x0582, 0x002b, 1, "%s Control"},
+	{ USB_ID(0x0582, 0x002b), 0, "%s MIDI" },
+	{ USB_ID(0x0582, 0x002b), 1, "%s Control" },
 	/* Roland VariOS */
-	{0x0582, 0x002f, 0, "%s MIDI"},
-	{0x0582, 0x002f, 1, "%s External MIDI"},
-	{0x0582, 0x002f, 2, "%s Sync"},
+	{ USB_ID(0x0582, 0x002f), 0, "%s MIDI" },
+	{ USB_ID(0x0582, 0x002f), 1, "%s External MIDI" },
+	{ USB_ID(0x0582, 0x002f), 2, "%s Sync" },
 	/* Edirol PCR */
-	{0x0582, 0x0033, 0, "%s MIDI"},
-	{0x0582, 0x0033, 1, "%s 1"},
-	{0x0582, 0x0033, 2, "%s 2"},
+	{ USB_ID(0x0582, 0x0033), 0, "%s MIDI" },
+	{ USB_ID(0x0582, 0x0033), 1, "%s 1" },
+	{ USB_ID(0x0582, 0x0033), 2, "%s 2" },
 	/* BOSS GS-10 */
-	{0x0582, 0x003b, 0, "%s MIDI"},
-	{0x0582, 0x003b, 1, "%s Control"},
+	{ USB_ID(0x0582, 0x003b), 0, "%s MIDI" },
+	{ USB_ID(0x0582, 0x003b), 1, "%s Control" },
 	/* Edirol UA-1000 */
-	{0x0582, 0x0044, 0, "%s MIDI"},
-	{0x0582, 0x0044, 1, "%s Control"},
+	{ USB_ID(0x0582, 0x0044), 0, "%s MIDI" },
+	{ USB_ID(0x0582, 0x0044), 1, "%s Control" },
 	/* Edirol UR-80 */
-	{0x0582, 0x0048, 0, "%s MIDI"},
-	{0x0582, 0x0048, 1, "%s 1"},
-	{0x0582, 0x0048, 2, "%s 2"},
+	{ USB_ID(0x0582, 0x0048), 0, "%s MIDI" },
+	{ USB_ID(0x0582, 0x0048), 1, "%s 1" },
+	{ USB_ID(0x0582, 0x0048), 2, "%s 2" },
 	/* Edirol PCR-A */
-	{0x0582, 0x004d, 0, "%s MIDI"},
-	{0x0582, 0x004d, 1, "%s 1"},
-	{0x0582, 0x004d, 2, "%s 2"},
+	{ USB_ID(0x0582, 0x004d), 0, "%s MIDI" },
+	{ USB_ID(0x0582, 0x004d), 1, "%s 1" },
+	{ USB_ID(0x0582, 0x004d), 2, "%s 2" },
 	/* M-Audio MidiSport 8x8 */
-	{0x0763, 0x1031, 8, "%s Control"},
-	{0x0763, 0x1033, 8, "%s Control"},
+	{ USB_ID(0x0763, 0x1031), 8, "%s Control" },
+	{ USB_ID(0x0763, 0x1033), 8, "%s Control" },
 	/* MOTU Fastlane */
-	{0x07fd, 0x0001, 0, "%s MIDI A"},
-	{0x07fd, 0x0001, 1, "%s MIDI B"},
+	{ USB_ID(0x07fd, 0x0001), 0, "%s MIDI A" },
+	{ USB_ID(0x07fd, 0x0001), 1, "%s MIDI B" },
 	/* Emagic Unitor8/AMT8/MT4 */
-	{0x086a, 0x0001, 8, "%s Broadcast"},
-	{0x086a, 0x0002, 8, "%s Broadcast"},
-	{0x086a, 0x0003, 4, "%s Broadcast"},
+	{ USB_ID(0x086a, 0x0001), 8, "%s Broadcast" },
+	{ USB_ID(0x086a, 0x0002), 8, "%s Broadcast" },
+	{ USB_ID(0x086a, 0x0003), 4, "%s Broadcast" },
 };
 
 static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi,
@@ -1044,7 +1043,6 @@
 				       snd_rawmidi_substream_t** rsubstream)
 {
 	int i;
-	__u16 vendor, product;
 	const char *name_format;
 
 	snd_rawmidi_substream_t* substream = snd_usbmidi_find_substream(umidi, stream, number);
@@ -1055,11 +1053,8 @@
 
 	/* TODO: read port name from jack descriptor */
 	name_format = "%s MIDI %d";
-	vendor = le16_to_cpu(umidi->chip->dev->descriptor.idVendor);
-	product = le16_to_cpu(umidi->chip->dev->descriptor.idProduct);
 	for (i = 0; i < ARRAY_SIZE(snd_usbmidi_port_names); ++i) {
-		if (snd_usbmidi_port_names[i].vendor == vendor &&
-		    snd_usbmidi_port_names[i].product == product &&
+		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;
@@ -1226,9 +1221,12 @@
 	struct usb_endpoint_descriptor* epd;
 	int i, out_eps = 0, in_eps = 0;
 
-	if (le16_to_cpu(umidi->chip->dev->descriptor.idVendor) == 0x0582)
+	if (USB_ID_VENDOR(umidi->chip->usb_id) == 0x0582)
 		snd_usbmidi_switch_roland_altsetting(umidi);
 
+	if (endpoint[0].out_ep || endpoint[0].in_ep)
+		return 0;	
+
 	intf = umidi->iface;
 	if (!intf || intf->num_altsetting < 1)
 		return -ENOENT;
diff --git a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
index 5f19069..e73c1c9 100644
--- a/sound/usb/usbmixer.c
+++ b/sound/usb/usbmixer.c
@@ -35,10 +35,11 @@
 #include <linux/usb.h>
 #include <sound/core.h>
 #include <sound/control.h>
+#include <sound/hwdep.h>
+#include <sound/info.h>
 
 #include "usbaudio.h"
 
-
 /*
  */
 
@@ -50,6 +51,31 @@
 typedef struct usb_mixer_elem_info usb_mixer_elem_info_t;
 
 
+struct usb_mixer_interface {
+	snd_usb_audio_t *chip;
+	unsigned int ctrlif;
+	struct list_head list;
+	unsigned int ignore_ctl_error;
+	struct urb *urb;
+	usb_mixer_elem_info_t **id_elems; /* array[256], indexed by unit id */
+
+	/* Sound Blaster remote control stuff */
+	enum {
+		RC_NONE,
+		RC_EXTIGY,
+		RC_AUDIGY2NX,
+	} rc_type;
+	unsigned long rc_hwdep_open;
+	u32 rc_code;
+	wait_queue_head_t rc_waitq;
+	struct urb *rc_urb;
+	struct usb_ctrlrequest *rc_setup_packet;
+	u8 rc_buffer[6];
+
+	u8 audigy2nx_leds[3];
+};
+
+
 struct usb_audio_term {
 	int id;
 	int type;
@@ -62,26 +88,26 @@
 
 struct usb_mixer_build {
 	snd_usb_audio_t *chip;
+	struct usb_mixer_interface *mixer;
 	unsigned char *buffer;
 	unsigned int buflen;
-	unsigned int ctrlif;
-	unsigned short vendor;
-	unsigned short product;
-	DECLARE_BITMAP(unitbitmap, 32*32);
+	DECLARE_BITMAP(unitbitmap, 256);
 	usb_audio_term_t oterm;
 	const struct usbmix_name_map *map;
+	const struct usbmix_selector_map *selector_map;
 };
 
 struct usb_mixer_elem_info {
-	snd_usb_audio_t *chip;
-	unsigned int ctrlif;
+	struct usb_mixer_interface *mixer;
+	usb_mixer_elem_info_t *next_id_elem; /* list of controls with same id */
+	snd_ctl_elem_id_t *elem_id;
 	unsigned int id;
 	unsigned int control;	/* CS or ICN (high byte) */
 	unsigned int cmask; /* channel mask bitmap: 0 = master */
 	int channels;
 	int val_type;
 	int min, max, res;
-	unsigned int initialized: 1;
+	u8 initialized;
 };
 
 
@@ -187,6 +213,21 @@
 	return 0;
 }
 
+/* get the mapped selector source name */
+static int check_mapped_selector_name(mixer_build_t *state, int unitid,
+				      int index, char *buf, int buflen)
+{
+	const struct usbmix_selector_map *p;
+
+	if (! state->selector_map)
+		return 0;
+	for (p = state->selector_map; p->id; p++) {
+		if (p->id == unitid && index < p->count)
+			return strlcpy(buf, p->names[index], buflen);
+	}
+	return 0;
+}
+
 /*
  * find an audio control unit with the given unit id
  */
@@ -301,16 +342,18 @@
 	int timeout = 10;
 
 	while (timeout-- > 0) {
-		if (snd_usb_ctl_msg(cval->chip->dev, usb_rcvctrlpipe(cval->chip->dev, 0),
+		if (snd_usb_ctl_msg(cval->mixer->chip->dev,
+				    usb_rcvctrlpipe(cval->mixer->chip->dev, 0),
 				    request,
 				    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    validx, cval->ctrlif | (cval->id << 8),
+				    validx, cval->mixer->ctrlif | (cval->id << 8),
 				    buf, val_len, 100) >= 0) {
 			*value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
 			return 0;
 		}
 	}
-	snd_printdd(KERN_ERR "cannot get ctl value: req = 0x%x, wValue = 0x%x, wIndex = 0x%x, type = %d\n", request, validx, cval->ctrlif | (cval->id << 8), cval->val_type);
+	snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
+		    request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type);
 	return -EINVAL;
 }
 
@@ -339,13 +382,15 @@
 	buf[0] = value_set & 0xff;
 	buf[1] = (value_set >> 8) & 0xff;
 	while (timeout -- > 0)
-		if (snd_usb_ctl_msg(cval->chip->dev, usb_sndctrlpipe(cval->chip->dev, 0),
+		if (snd_usb_ctl_msg(cval->mixer->chip->dev,
+				    usb_sndctrlpipe(cval->mixer->chip->dev, 0),
 				    request,
 				    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-				    validx, cval->ctrlif | (cval->id << 8),
+				    validx, cval->mixer->ctrlif | (cval->id << 8),
 				    buf, val_len, 100) >= 0)
 			return 0;
-	snd_printdd(KERN_ERR "cannot set ctl value: req = 0x%x, wValue = 0x%x, wIndex = 0x%x, type = %d, data = 0x%x/0x%x\n", request, validx, cval->ctrlif | (cval->id << 8), cval->val_type, buf[0], buf[1]);
+	snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n",
+		    request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type, buf[0], buf[1]);
 	return -EINVAL;
 }
 
@@ -385,16 +430,22 @@
  * if failed, give up and free the control instance.
  */
 
-static int add_control_to_empty(snd_card_t *card, snd_kcontrol_t *kctl)
+static int add_control_to_empty(mixer_build_t *state, snd_kcontrol_t *kctl)
 {
+	usb_mixer_elem_info_t *cval = kctl->private_data;
 	int err;
-	while (snd_ctl_find_id(card, &kctl->id))
+
+	while (snd_ctl_find_id(state->chip->card, &kctl->id))
 		kctl->id.index++;
-	if ((err = snd_ctl_add(card, kctl)) < 0) {
+	if ((err = snd_ctl_add(state->chip->card, kctl)) < 0) {
 		snd_printd(KERN_ERR "cannot add control (err = %d)\n", err);
 		snd_ctl_free_one(kctl);
+		return err;
 	}
-	return err;
+	cval->elem_id = &kctl->id;
+	cval->next_id_elem = state->mixer->id_elems[cval->id];
+	state->mixer->id_elems[cval->id] = cval;
+	return 0;
 }
 
 
@@ -572,10 +623,8 @@
 /* private_free callback */
 static void usb_mixer_elem_free(snd_kcontrol_t *kctl)
 {
-	if (kctl->private_data) {
-		kfree(kctl->private_data);
-		kctl->private_data = NULL;
-	}
+	kfree(kctl->private_data);
+	kctl->private_data = NULL;
 }
 
 
@@ -608,7 +657,8 @@
 		}
 		if (get_ctl_value(cval, GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 ||
 		    get_ctl_value(cval, GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) {
-			snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n", cval->id, cval->ctrlif, cval->control, cval->id);
+			snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n",
+				   cval->id, cval->mixer->ctrlif, cval->control, cval->id);
 			return -EINVAL;
 		}
 		if (get_ctl_value(cval, GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) {
@@ -668,7 +718,7 @@
 			if (cval->cmask & (1 << c)) {
 				err = get_cur_mix_value(cval, c + 1, &val);
 				if (err < 0) {
-					if (cval->chip->ignore_ctl_error) {
+					if (cval->mixer->ignore_ctl_error) {
 						ucontrol->value.integer.value[0] = cval->min;
 						return 0;
 					}
@@ -684,7 +734,7 @@
 		/* master channel */
 		err = get_cur_mix_value(cval, 0, &val);
 		if (err < 0) {
-			if (cval->chip->ignore_ctl_error) {
+			if (cval->mixer->ignore_ctl_error) {
 				ucontrol->value.integer.value[0] = cval->min;
 				return 0;
 			}
@@ -710,7 +760,7 @@
 			if (cval->cmask & (1 << c)) {
 				err = get_cur_mix_value(cval, c + 1, &oval);
 				if (err < 0) {
-					if (cval->chip->ignore_ctl_error)
+					if (cval->mixer->ignore_ctl_error)
 						return 0;
 					return err;
 				}
@@ -727,7 +777,7 @@
 	} else {
 		/* master channel */
 		err = get_cur_mix_value(cval, 0, &oval);
-		if (err < 0 && cval->chip->ignore_ctl_error)
+		if (err < 0 && cval->mixer->ignore_ctl_error)
 			return 0;
 		if (err < 0)
 			return err;
@@ -779,8 +829,7 @@
 		snd_printk(KERN_ERR "cannot malloc kcontrol\n");
 		return;
 	}
-	cval->chip = state->chip;
-	cval->ctrlif = state->ctrlif;
+	cval->mixer = state->mixer;
 	cval->id = unitid;
 	cval->control = control;
 	cval->cmask = ctl_mask;
@@ -855,16 +904,21 @@
 	/* note that detection between firmware 2.1.1.7 (N101) and later 2.1.1.21 */
 	/* is not very clear from datasheets */
 	/* I hope that the min value is -15360 for newer firmware --jk */
-	if (((state->vendor == 0x471 && (state->product == 0x104 || state->product == 0x105 || state->product == 0x101)) ||
-	     (state->vendor == 0x672 && state->product == 0x1041)) && !strcmp(kctl->id.name, "PCM Playback Volume") &&
-	     cval->min == -15616) {
-		snd_printk("USB Audio: using volume control quirk for the UDA1321/N101 chip\n");
-		cval->max = -256;
+	switch (state->chip->usb_id) {
+	case USB_ID(0x0471, 0x0101):
+	case USB_ID(0x0471, 0x0104):
+	case USB_ID(0x0471, 0x0105):
+	case USB_ID(0x0672, 0x1041):
+		if (!strcmp(kctl->id.name, "PCM Playback Volume") &&
+		    cval->min == -15616) {
+			snd_printk("using volume control quirk for the UDA1321/N101 chip\n");
+			cval->max = -256;
+		}
 	}
 
 	snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
 		    cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res);
-	add_control_to_empty(state->chip->card, kctl);
+	add_control_to_empty(state, kctl);
 }
 
 
@@ -947,8 +1001,7 @@
 	if (! cval)
 		return;
 
-	cval->chip = state->chip;
-	cval->ctrlif = state->ctrlif;
+	cval->mixer = state->mixer;
 	cval->id = unitid;
 	cval->control = in_ch + 1; /* based on 1 */
 	cval->val_type = USB_MIXER_S16;
@@ -979,7 +1032,7 @@
 
 	snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n",
 		    cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
-	add_control_to_empty(state->chip->card, kctl);
+	add_control_to_empty(state, kctl);
 }
 
 
@@ -1042,7 +1095,7 @@
 	int err, val;
 
 	err = get_cur_ctl_value(cval, cval->control << 8, &val);
-	if (err < 0 && cval->chip->ignore_ctl_error) {
+	if (err < 0 && cval->mixer->ignore_ctl_error) {
 		ucontrol->value.integer.value[0] = cval->min;
 		return 0;
 	}
@@ -1061,7 +1114,7 @@
 
 	err = get_cur_ctl_value(cval, cval->control << 8, &oval);
 	if (err < 0) {
-		if (cval->chip->ignore_ctl_error)
+		if (cval->mixer->ignore_ctl_error)
 			return 0;
 		return err;
 	}
@@ -1179,9 +1232,6 @@
 	}
 
 	type = combine_word(&dsc[4]);
-	if (! type)
-		return 0; /* undefined? */
-
 	for (info = list; info && info->type; info++)
 		if (info->type == type)
 			break;
@@ -1199,8 +1249,7 @@
 			snd_printk(KERN_ERR "cannot malloc kcontrol\n");
 			return -ENOMEM;
 		}
-		cval->chip = state->chip;
-		cval->ctrlif = state->ctrlif;
+		cval->mixer = state->mixer;
 		cval->id = unitid;
 		cval->control = valinfo->control;
 		cval->val_type = valinfo->val_type;
@@ -1241,7 +1290,7 @@
 
 		snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n",
 			    cval->id, kctl->id.name, cval->channels, cval->min, cval->max);
-		if ((err = add_control_to_empty(state->chip->card, kctl)) < 0)
+		if ((err = add_control_to_empty(state, kctl)) < 0)
 			return err;
 	}
 	return 0;
@@ -1289,7 +1338,7 @@
 
 	err = get_cur_ctl_value(cval, 0, &val);
 	if (err < 0) {
-		if (cval->chip->ignore_ctl_error) {
+		if (cval->mixer->ignore_ctl_error) {
 			ucontrol->value.enumerated.item[0] = 0;
 			return 0;
 		}
@@ -1308,7 +1357,7 @@
 
 	err = get_cur_ctl_value(cval, 0, &oval);
 	if (err < 0) {
-		if (cval->chip->ignore_ctl_error)
+		if (cval->mixer->ignore_ctl_error)
 			return 0;
 		return err;
 	}
@@ -1386,8 +1435,7 @@
 		snd_printk(KERN_ERR "cannot malloc kcontrol\n");
 		return -ENOMEM;
 	}
-	cval->chip = state->chip;
-	cval->ctrlif = state->ctrlif;
+	cval->mixer = state->mixer;
 	cval->id = unitid;
 	cval->val_type = USB_MIXER_U8;
 	cval->channels = 1;
@@ -1415,7 +1463,9 @@
 			kfree(cval);
 			return -ENOMEM;
 		}
-		if (check_input_term(state, desc[5 + i], &iterm) >= 0)
+		len = check_mapped_selector_name(state, unitid, i, namelist[i],
+						 MAX_ITEM_NAME_LEN);
+		if (! len && check_input_term(state, desc[5 + i], &iterm) >= 0)
 			len = get_term_name(state, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0);
 		if (! len)
 			sprintf(namelist[i], "Input %d", i);
@@ -1450,7 +1500,7 @@
 
 	snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n",
 		    cval->id, kctl->id.name, num_ins);
-	if ((err = add_control_to_empty(state->chip->card, kctl)) < 0)
+	if ((err = add_control_to_empty(state, kctl)) < 0)
 		return err;
 
 	return 0;
@@ -1493,41 +1543,55 @@
 	}
 }
 
+static void snd_usb_mixer_free(struct usb_mixer_interface *mixer)
+{
+	kfree(mixer->id_elems);
+	if (mixer->urb) {
+		kfree(mixer->urb->transfer_buffer);
+		usb_free_urb(mixer->urb);
+	}
+	if (mixer->rc_urb)
+		usb_free_urb(mixer->rc_urb);
+	kfree(mixer->rc_setup_packet);
+	kfree(mixer);
+}
+
+static int snd_usb_mixer_dev_free(snd_device_t *device)
+{
+	struct usb_mixer_interface *mixer = device->device_data;
+	snd_usb_mixer_free(mixer);
+	return 0;
+}
+
 /*
  * create mixer controls
  *
  * walk through all OUTPUT_TERMINAL descriptors to search for mixers
  */
-int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif)
+static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
 {
 	unsigned char *desc;
 	mixer_build_t state;
 	int err;
 	const struct usbmix_ctl_map *map;
-	struct usb_device_descriptor *dev = &chip->dev->descriptor;
-	struct usb_host_interface *hostif = &usb_ifnum_to_if(chip->dev, ctrlif)->altsetting[0];
+	struct usb_host_interface *hostif;
 
-	strcpy(chip->card->mixername, "USB Mixer");
-
+	hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0];
 	memset(&state, 0, sizeof(state));
-	state.chip = chip;
+	state.chip = mixer->chip;
+	state.mixer = mixer;
 	state.buffer = hostif->extra;
 	state.buflen = hostif->extralen;
-	state.ctrlif = ctrlif;
-	state.vendor = le16_to_cpu(dev->idVendor);
-	state.product = le16_to_cpu(dev->idProduct);
 
 	/* check the mapping table */
-	for (map = usbmix_ctl_maps; map->vendor; map++) {
-		if (map->vendor == state.vendor && map->product == state.product) {
+	for (map = usbmix_ctl_maps; map->id; map++) {
+		if (map->id == state.chip->usb_id) {
 			state.map = map->map;
-			chip->ignore_ctl_error = map->ignore_ctl_error;
+			state.selector_map = map->selector_map;
+			mixer->ignore_ctl_error = map->ignore_ctl_error;
 			break;
 		}
 	}
-#ifdef IGNORE_CTL_ERROR
-	chip->ignore_ctl_error = 1;
-#endif
 
 	desc = NULL;
 	while ((desc = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, desc, OUTPUT_TERMINAL)) != NULL) {
@@ -1543,3 +1607,393 @@
 	}
 	return 0;
 }
+
+static void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer,
+				    int unitid)
+{
+	usb_mixer_elem_info_t *info;
+
+	for (info = mixer->id_elems[unitid]; info; info = info->next_id_elem)
+		snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
+			       info->elem_id);
+}
+
+static void snd_usb_mixer_memory_change(struct usb_mixer_interface *mixer,
+					int unitid)
+{
+	if (mixer->rc_type == RC_NONE)
+		return;
+	/* unit ids specific to Extigy/Audigy 2 NX: */
+	switch (unitid) {
+	case 0: /* remote control */
+		mixer->rc_urb->dev = mixer->chip->dev;
+		usb_submit_urb(mixer->rc_urb, GFP_ATOMIC);
+		break;
+	case 4: /* digital in jack */
+	case 7: /* line in jacks */
+	case 19: /* speaker out jacks */
+	case 20: /* headphones out jack */
+		break;
+	default:
+		snd_printd(KERN_DEBUG "memory change in unknown unit %d\n", unitid);
+		break;
+	}
+}
+
+static void snd_usb_mixer_status_complete(struct urb *urb, struct pt_regs *regs)
+{
+	struct usb_mixer_interface *mixer = urb->context;
+
+	if (urb->status == 0) {
+		u8 *buf = urb->transfer_buffer;
+		int i;
+
+		for (i = urb->actual_length; i >= 2; buf += 2, i -= 2) {
+			snd_printd(KERN_DEBUG "status interrupt: %02x %02x\n",
+				   buf[0], buf[1]);
+			/* ignore any notifications not from the control interface */
+			if ((buf[0] & 0x0f) != 0)
+				continue;
+			if (!(buf[0] & 0x40))
+				snd_usb_mixer_notify_id(mixer, buf[1]);
+			else
+				snd_usb_mixer_memory_change(mixer, buf[1]);
+		}
+	}
+	if (urb->status != -ENOENT && urb->status != -ECONNRESET) {
+		urb->dev = mixer->chip->dev;
+		usb_submit_urb(urb, GFP_ATOMIC);
+	}
+}
+
+/* create the handler for the optional status interrupt endpoint */
+static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
+{
+	struct usb_host_interface *hostif;
+	struct usb_endpoint_descriptor *ep;
+	void *transfer_buffer;
+	int buffer_length;
+	unsigned int epnum;
+
+	hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0];
+	/* we need one interrupt input endpoint */
+	if (get_iface_desc(hostif)->bNumEndpoints < 1)
+		return 0;
+	ep = get_endpoint(hostif, 0);
+	if ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) != USB_DIR_IN ||
+	    (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
+		return 0;
+
+	epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+	buffer_length = le16_to_cpu(ep->wMaxPacketSize);
+	transfer_buffer = kmalloc(buffer_length, GFP_KERNEL);
+	if (!transfer_buffer)
+		return -ENOMEM;
+	mixer->urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!mixer->urb) {
+		kfree(transfer_buffer);
+		return -ENOMEM;
+	}
+	usb_fill_int_urb(mixer->urb, mixer->chip->dev,
+			 usb_rcvintpipe(mixer->chip->dev, epnum),
+			 transfer_buffer, buffer_length,
+			 snd_usb_mixer_status_complete, mixer, ep->bInterval);
+	usb_submit_urb(mixer->urb, GFP_KERNEL);
+	return 0;
+}
+
+static void snd_usb_soundblaster_remote_complete(struct urb *urb,
+						 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;
+	u32 code;
+
+	if (urb->status < 0 || urb->actual_length <= offset)
+		return;
+	code = mixer->rc_buffer[offset];
+	/* the Mute button actually changes the mixer control */
+	if (code == 13)
+		snd_usb_mixer_notify_id(mixer, 18);
+	mixer->rc_code = code;
+	wmb();
+	wake_up(&mixer->rc_waitq);
+}
+
+static int snd_usb_sbrc_hwdep_open(snd_hwdep_t *hw, struct file *file)
+{
+	struct usb_mixer_interface *mixer = hw->private_data;
+
+	if (test_and_set_bit(0, &mixer->rc_hwdep_open))
+		return -EBUSY;
+	return 0;
+}
+
+static int snd_usb_sbrc_hwdep_release(snd_hwdep_t *hw, struct file *file)
+{
+	struct usb_mixer_interface *mixer = hw->private_data;
+
+	clear_bit(0, &mixer->rc_hwdep_open);
+	smp_mb__after_clear_bit();
+	return 0;
+}
+
+static long snd_usb_sbrc_hwdep_read(snd_hwdep_t *hw, char __user *buf,
+				     long count, loff_t *offset)
+{
+	struct usb_mixer_interface *mixer = hw->private_data;
+	int err;
+	u32 rc_code;
+
+	if (count != 1 && count != 4)
+		return -EINVAL;
+	err = wait_event_interruptible(mixer->rc_waitq,
+				       (rc_code = xchg(&mixer->rc_code, 0)) != 0);
+	if (err == 0) {
+		if (count == 1)
+			err = put_user(rc_code, buf);
+		else
+			err = put_user(rc_code, (u32 __user *)buf);
+	}
+	return err < 0 ? err : count;
+}
+
+static unsigned int snd_usb_sbrc_hwdep_poll(snd_hwdep_t *hw, struct file *file,
+					    poll_table *wait)
+{
+	struct usb_mixer_interface *mixer = hw->private_data;
+
+	poll_wait(file, &mixer->rc_waitq, wait);
+	return mixer->rc_code ? POLLIN | POLLRDNORM : 0;
+}
+
+static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer)
+{
+	snd_hwdep_t *hwdep;
+	int err, len;
+
+	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:
+		return 0;
+	}
+
+	init_waitqueue_head(&mixer->rc_waitq);
+	err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep);
+	if (err < 0)
+		return err;
+	snprintf(hwdep->name, sizeof(hwdep->name),
+		 "%s remote control", mixer->chip->card->shortname);
+	hwdep->iface = SNDRV_HWDEP_IFACE_SB_RC;
+	hwdep->private_data = mixer;
+	hwdep->ops.read = snd_usb_sbrc_hwdep_read;
+	hwdep->ops.open = snd_usb_sbrc_hwdep_open;
+	hwdep->ops.release = snd_usb_sbrc_hwdep_release;
+	hwdep->ops.poll = snd_usb_sbrc_hwdep_poll;
+
+	mixer->rc_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!mixer->rc_urb)
+		return -ENOMEM;
+	mixer->rc_setup_packet = kmalloc(sizeof(*mixer->rc_setup_packet), GFP_KERNEL);
+	if (!mixer->rc_setup_packet) {
+		usb_free_urb(mixer->rc_urb);
+		mixer->rc_urb = NULL;
+		return -ENOMEM;
+	}
+	mixer->rc_setup_packet->bRequestType =
+		USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+	mixer->rc_setup_packet->bRequest = GET_MEM;
+	mixer->rc_setup_packet->wValue = cpu_to_le16(0);
+	mixer->rc_setup_packet->wIndex = cpu_to_le16(0);
+	mixer->rc_setup_packet->wLength = cpu_to_le16(len);
+	usb_fill_control_urb(mixer->rc_urb, mixer->chip->dev,
+			     usb_rcvctrlpipe(mixer->chip->dev, 0),
+			     (u8*)mixer->rc_setup_packet, mixer->rc_buffer, len,
+			     snd_usb_soundblaster_remote_complete, mixer);
+	return 0;
+}
+
+static int snd_audigy2nx_led_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int snd_audigy2nx_led_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
+	int index = kcontrol->private_value;
+
+	ucontrol->value.integer.value[0] = mixer->audigy2nx_leds[index];
+	return 0;
+}
+
+static int snd_audigy2nx_led_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
+	int index = kcontrol->private_value;
+	int value = ucontrol->value.integer.value[0];
+	int err, changed;
+
+	if (value > 1)
+		return -EINVAL;
+	changed = value != mixer->audigy2nx_leds[index];
+	err = snd_usb_ctl_msg(mixer->chip->dev,
+			      usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
+			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
+			      value, index + 2, NULL, 0, 100);
+	if (err < 0)
+		return err;
+	mixer->audigy2nx_leds[index] = value;
+	return changed;
+}
+
+static snd_kcontrol_new_t snd_audigy2nx_controls[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "CMSS LED Switch",
+		.info = snd_audigy2nx_led_info,
+		.get = snd_audigy2nx_led_get,
+		.put = snd_audigy2nx_led_put,
+		.private_value = 0,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Power LED Switch",
+		.info = snd_audigy2nx_led_info,
+		.get = snd_audigy2nx_led_get,
+		.put = snd_audigy2nx_led_put,
+		.private_value = 1,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Dolby Digital LED Switch",
+		.info = snd_audigy2nx_led_info,
+		.get = snd_audigy2nx_led_get,
+		.put = snd_audigy2nx_led_put,
+		.private_value = 2,
+	},
+};
+
+static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer)
+{
+	int i, err;
+
+	for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) {
+		err = snd_ctl_add(mixer->chip->card,
+				  snd_ctl_new1(&snd_audigy2nx_controls[i], mixer));
+		if (err < 0)
+			return err;
+	}
+	mixer->audigy2nx_leds[1] = 1; /* Power LED is on by default */
+	return 0;
+}
+
+static void snd_audigy2nx_proc_read(snd_info_entry_t *entry,
+				    snd_info_buffer_t *buffer)
+{
+	static const struct {
+		int unitid;
+		const char *name;
+	} jacks[] = {
+		{4,  "dig in "},
+		{7,  "line in"},
+		{19, "spk out"},
+		{20, "hph out"},
+	};
+	struct usb_mixer_interface *mixer = entry->private_data;
+	int i, err;
+	u8 buf[3];
+
+	snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname);
+	for (i = 0; i < ARRAY_SIZE(jacks); ++i) {
+		snd_iprintf(buffer, "%s: ", jacks[i].name);
+		err = snd_usb_ctl_msg(mixer->chip->dev,
+				      usb_rcvctrlpipe(mixer->chip->dev, 0),
+				      GET_MEM, USB_DIR_IN | USB_TYPE_CLASS |
+				      USB_RECIP_INTERFACE, 0,
+				      jacks[i].unitid << 8, buf, 3, 100);
+		if (err == 3 && buf[0] == 3)
+			snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]);
+		else
+			snd_iprintf(buffer, "?\n");
+	}
+}
+
+int snd_usb_create_mixer(snd_usb_audio_t *chip, int ctrlif)
+{
+	static snd_device_ops_t dev_ops = {
+		.dev_free = snd_usb_mixer_dev_free
+	};
+	struct usb_mixer_interface *mixer;
+	int err;
+
+	strcpy(chip->card->mixername, "USB Mixer");
+
+	mixer = kcalloc(1, sizeof(*mixer), GFP_KERNEL);
+	if (!mixer)
+		return -ENOMEM;
+	mixer->chip = chip;
+	mixer->ctrlif = ctrlif;
+#ifdef IGNORE_CTL_ERROR
+	mixer->ignore_ctl_error = 1;
+#endif
+	mixer->id_elems = kcalloc(256, sizeof(*mixer->id_elems), GFP_KERNEL);
+	if (!mixer->id_elems) {
+		kfree(mixer);
+		return -ENOMEM;
+	}
+
+	if ((err = snd_usb_mixer_controls(mixer)) < 0 ||
+	    (err = snd_usb_mixer_status_create(mixer)) < 0)
+		goto _error;
+
+	if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0)
+		goto _error;
+
+	if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020)) {
+		snd_info_entry_t *entry;
+
+		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_audigy2nx_proc_read);
+	}
+
+	err = snd_device_new(chip->card, SNDRV_DEV_LOWLEVEL, mixer, &dev_ops);
+	if (err < 0)
+		goto _error;
+	list_add(&mixer->list, &chip->mixer_list);
+	return 0;
+
+_error:
+	snd_usb_mixer_free(mixer);
+	return err;
+}
+
+void snd_usb_mixer_disconnect(struct list_head *p)
+{
+	struct usb_mixer_interface *mixer;
+	
+	mixer = list_entry(p, struct usb_mixer_interface, list);
+	if (mixer->urb)
+		usb_kill_urb(mixer->urb);
+	if (mixer->rc_urb)
+		usb_kill_urb(mixer->rc_urb);
+}
diff --git a/sound/usb/usbmixer_maps.c b/sound/usb/usbmixer_maps.c
index c69b4b0..f05500b 100644
--- a/sound/usb/usbmixer_maps.c
+++ b/sound/usb/usbmixer_maps.c
@@ -26,10 +26,16 @@
 	int control;
 };
 
+struct usbmix_selector_map {
+	int id;
+	int count;
+	const char **names;
+};
+
 struct usbmix_ctl_map {
-	int vendor;
-	int product;
+	u32 id;
 	const struct usbmix_name_map *map;
+	const struct usbmix_selector_map *selector_map;
 	int ignore_ctl_error;
 };
 
@@ -91,6 +97,96 @@
 	{ 0 } /* terminator */
 };
 
+/* Sound Blaster MP3+ controls mapping
+ * The default mixer channels have totally misleading names,
+ * e.g. no Master and fake PCM volume
+ *			Pavel Mihaylov <bin@bash.info>
+ */
+static struct usbmix_name_map mp3plus_map[] = {
+	/* 1: IT pcm */
+	/* 2: IT mic */
+	/* 3: IT line */
+	/* 4: IT digital in */
+	/* 5: OT digital out */
+	/* 6: OT speaker */
+	/* 7: OT pcm capture */
+	{ 8, "Capture Input Source" }, /* FU, default PCM Capture Source */
+		/* (Mic, Input 1 = Line input, Input 2 = Optical input) */
+	{ 9, "Master Playback" }, /* FU, default Speaker 1 */
+	/* { 10, "Mic Capture", 1 }, */ /* FU, Mic Capture */
+	/* { 10, "Mic Capture", 2 }, */ /* FU, Mic Capture */
+	{ 10, "Mic Boost", 7 }, /* FU, default Auto Gain Input */
+	{ 11, "Line Capture" }, /* FU, default PCM Capture */
+	{ 12, "Digital In Playback" }, /* FU, default PCM 1 */
+	/* { 13, "Mic Playback" }, */ /* FU, default Mic Playback */
+	{ 14, "Line Playback" }, /* FU, default Speaker */
+	/* 15: MU */
+	{ 0 } /* terminator */
+};
+
+/* Topology of SB Audigy 2 NX
+
+          +----------------------------->EU[27]--+
+          |                                      v
+          | +----------------------------------->SU[29]---->FU[22]-->Dig_OUT[24]
+          | |                                    ^
+USB_IN[1]-+------------+              +->EU[17]->+->FU[11]-+
+            |          v              |          v         |
+Dig_IN[4]---+->FU[6]-->MU[16]->FU[18]-+->EU[21]->SU[31]----->FU[30]->Hph_OUT[20]
+            |          ^              |                    |
+Lin_IN[7]-+--->FU[8]---+              +->EU[23]->FU[28]------------->Spk_OUT[19]
+          | |                                              v
+          +--->FU[12]------------------------------------->SU[14]--->USB_OUT[15]
+            |                                              ^
+            +->FU[13]--------------------------------------+
+*/
+static struct usbmix_name_map audigy2nx_map[] = {
+	/* 1: IT pcm playback */
+	/* 4: IT digital in */
+	{ 6, "Digital In Playback" }, /* FU */
+	/* 7: IT line in */
+	{ 8, "Line Playback" }, /* FU */
+	{ 11, "What-U-Hear Capture" }, /* FU */
+	{ 12, "Line Capture" }, /* FU */
+	{ 13, "Digital In Capture" }, /* FU */
+	{ 14, "Capture Source" }, /* SU */
+	/* 15: OT pcm capture */
+	/* 16: MU w/o controls */
+	{ 17, NULL }, /* DISABLED: EU (for what?) */
+	{ 18, "Master Playback" }, /* FU */
+	/* 19: OT speaker */
+	/* 20: OT headphone */
+	{ 21, NULL }, /* DISABLED: EU (for what?) */
+	{ 22, "Digital Out Playback" }, /* FU */
+	{ 23, NULL }, /* DISABLED: EU (for what?) */
+	/* 24: OT digital out */
+	{ 27, NULL }, /* DISABLED: EU (for what?) */
+	{ 28, "Speaker Playback" }, /* FU */
+	{ 29, "Digital Out Source" }, /* SU */
+	{ 30, "Headphone Playback" }, /* FU */
+	{ 31, "Headphone Source" }, /* SU */
+	{ 0 } /* terminator */
+};
+
+static struct usbmix_selector_map audigy2nx_selectors[] = {
+	{
+		.id = 14, /* Capture Source */
+		.count = 3,
+		.names = (const char*[]) {"Line", "Digital In", "What-U-Hear"}
+	},
+	{
+		.id = 29, /* Digital Out Source */
+		.count = 3,
+		.names = (const char*[]) {"Front", "PCM", "Digital In"}
+	},
+	{
+		.id = 31, /* Headphone Source */
+		.count = 2,
+		.names = (const char*[]) {"Front", "Side"}
+	},
+	{ 0 } /* terminator */
+};
+
 /* LineX FM Transmitter entry - needed to bypass controls bug */
 static struct usbmix_name_map linex_map[] = {
 	/* 1: IT pcm */
@@ -127,9 +223,29 @@
  */
 
 static struct usbmix_ctl_map usbmix_ctl_maps[] = {
-	{ 0x41e, 0x3000, extigy_map, 1 },
-	{ 0x8bb, 0x2702, linex_map, 1 },
-	{ 0xc45, 0x1158, justlink_map, 0 },
+	{
+		.id = USB_ID(0x041e, 0x3000),
+		.map = extigy_map,
+		.ignore_ctl_error = 1,
+	},
+	{
+		.id = USB_ID(0x041e, 0x3010),
+		.map = mp3plus_map,
+	},
+	{
+		.id = USB_ID(0x041e, 0x3020),
+		.map = audigy2nx_map,
+		.selector_map = audigy2nx_selectors,
+	},
+	{
+		.id = USB_ID(0x08bb, 0x2702),
+		.map = linex_map,
+		.ignore_ctl_error = 1,
+	},
+	{
+		.id = USB_ID(0x0c45, 0x1158),
+		.map = justlink_map,
+	},
 	{ 0 } /* terminator */
 };
 
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index 88bbd94..f513564 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -203,11 +203,28 @@
 	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
 		.vendor_name = "EDIROL",
 		.product_name = "UM-4",
-		.ifnum = 2,
-		.type = QUIRK_MIDI_FIXED_ENDPOINT,
-		.data = & (const snd_usb_midi_endpoint_info_t) {
-			.out_cables = 0x000f,
-			.in_cables  = 0x000f
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const snd_usb_audio_quirk_t[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_MIDI_FIXED_ENDPOINT,
+				.data = & (const snd_usb_midi_endpoint_info_t) {
+					.out_cables = 0x000f,
+					.in_cables  = 0x000f
+				}
+			},
+			{
+				.ifnum = -1
+			}
 		}
 	}
 },
@@ -216,11 +233,28 @@
 	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
 		.vendor_name = "Roland",
 		.product_name = "SC-8850",
-		.ifnum = 2,
-		.type = QUIRK_MIDI_FIXED_ENDPOINT,
-		.data = & (const snd_usb_midi_endpoint_info_t) {
-			.out_cables = 0x003f,
-			.in_cables  = 0x003f
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const snd_usb_audio_quirk_t[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_MIDI_FIXED_ENDPOINT,
+				.data = & (const snd_usb_midi_endpoint_info_t) {
+					.out_cables = 0x003f,
+					.in_cables  = 0x003f
+				}
+			},
+			{
+				.ifnum = -1
+			}
 		}
 	}
 },
@@ -229,11 +263,28 @@
 	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
 		.vendor_name = "Roland",
 		.product_name = "U-8",
-		.ifnum = 2,
-		.type = QUIRK_MIDI_FIXED_ENDPOINT,
-		.data = & (const snd_usb_midi_endpoint_info_t) {
-			.out_cables = 0x0005,
-			.in_cables  = 0x0005
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const snd_usb_audio_quirk_t[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_MIDI_FIXED_ENDPOINT,
+				.data = & (const snd_usb_midi_endpoint_info_t) {
+					.out_cables = 0x0005,
+					.in_cables  = 0x0005
+				}
+			},
+			{
+				.ifnum = -1
+			}
 		}
 	}
 },
@@ -242,11 +293,28 @@
 	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
 		.vendor_name = "EDIROL",
 		.product_name = "UM-2",
-		.ifnum = 2,
-		.type = QUIRK_MIDI_FIXED_ENDPOINT,
-		.data = & (const snd_usb_midi_endpoint_info_t) {
-			.out_cables = 0x0003,
-			.in_cables  = 0x0003
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const snd_usb_audio_quirk_t[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_MIDI_FIXED_ENDPOINT,
+				.data = & (const snd_usb_midi_endpoint_info_t) {
+					.out_cables = 0x0003,
+					.in_cables  = 0x0003
+				}
+			},
+			{
+				.ifnum = -1
+			}
 		}
 	}
 },
@@ -255,11 +323,28 @@
 	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
 		.vendor_name = "Roland",
 		.product_name = "SC-8820",
-		.ifnum = 2,
-		.type = QUIRK_MIDI_FIXED_ENDPOINT,
-		.data = & (const snd_usb_midi_endpoint_info_t) {
-			.out_cables = 0x0013,
-			.in_cables  = 0x0013
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const snd_usb_audio_quirk_t[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_MIDI_FIXED_ENDPOINT,
+				.data = & (const snd_usb_midi_endpoint_info_t) {
+					.out_cables = 0x0013,
+					.in_cables  = 0x0013
+				}
+			},
+			{
+				.ifnum = -1
+			}
 		}
 	}
 },
@@ -268,11 +353,28 @@
 	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
 		.vendor_name = "Roland",
 		.product_name = "PC-300",
-		.ifnum = 2,
-		.type = QUIRK_MIDI_FIXED_ENDPOINT,
-		.data = & (const snd_usb_midi_endpoint_info_t) {
-			.out_cables = 0x0001,
-			.in_cables  = 0x0001
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const snd_usb_audio_quirk_t[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_MIDI_FIXED_ENDPOINT,
+				.data = & (const snd_usb_midi_endpoint_info_t) {
+					.out_cables = 0x0001,
+					.in_cables  = 0x0001
+				}
+			},
+			{
+				.ifnum = -1
+			}
 		}
 	}
 },
@@ -281,11 +383,28 @@
 	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
 		.vendor_name = "EDIROL",
 		.product_name = "UM-1",
-		.ifnum = 2,
-		.type = QUIRK_MIDI_FIXED_ENDPOINT,
-		.data = & (const snd_usb_midi_endpoint_info_t) {
-			.out_cables = 0x0001,
-			.in_cables  = 0x0001
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const snd_usb_audio_quirk_t[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_MIDI_FIXED_ENDPOINT,
+				.data = & (const snd_usb_midi_endpoint_info_t) {
+					.out_cables = 0x0001,
+					.in_cables  = 0x0001
+				}
+			},
+			{
+				.ifnum = -1
+			}
 		}
 	}
 },
@@ -294,11 +413,28 @@
 	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
 		.vendor_name = "Roland",
 		.product_name = "SK-500",
-		.ifnum = 2,
-		.type = QUIRK_MIDI_FIXED_ENDPOINT,
-		.data = & (const snd_usb_midi_endpoint_info_t) {
-			.out_cables = 0x0013,
-			.in_cables  = 0x0013
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const snd_usb_audio_quirk_t[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_MIDI_FIXED_ENDPOINT,
+				.data = & (const snd_usb_midi_endpoint_info_t) {
+					.out_cables = 0x0013,
+					.in_cables  = 0x0013
+				}
+			},
+			{
+				.ifnum = -1
+			}
 		}
 	}
 },
@@ -421,11 +557,28 @@
 	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
 		.vendor_name = "EDIROL",
 		.product_name = "SD-90",
-		.ifnum = 2,
-		.type = QUIRK_MIDI_FIXED_ENDPOINT,
-		.data = & (const snd_usb_midi_endpoint_info_t) {
-			.out_cables = 0x000f,
-			.in_cables  = 0x000f
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const snd_usb_audio_quirk_t[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_MIDI_FIXED_ENDPOINT,
+				.data = & (const snd_usb_midi_endpoint_info_t) {
+					.out_cables = 0x000f,
+					.in_cables  = 0x000f
+				}
+			},
+			{
+				.ifnum = -1
+			}
 		}
 	}
 },
@@ -434,11 +587,28 @@
 	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
 		.vendor_name = "Roland",
 		.product_name = "MMP-2",
-		.ifnum = 2,
-		.type = QUIRK_MIDI_FIXED_ENDPOINT,
-		.data = & (const snd_usb_midi_endpoint_info_t) {
-			.out_cables = 0x0001,
-			.in_cables  = 0x0001
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = (const snd_usb_audio_quirk_t[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_MIDI_FIXED_ENDPOINT,
+				.data = & (const snd_usb_midi_endpoint_info_t) {
+					.out_cables = 0x0001,
+					.in_cables  = 0x0001
+				}
+			},
+			{
+				.ifnum = -1
+			}
 		}
 	}
 },
@@ -609,15 +779,33 @@
 	}
 },
 {
+	/*
+	 * This quirk is for the "Advanced Driver" mode.  If off, the GS-10
+	 * has ID 0x003c and is standard compliant, but has only 16-bit PCM
+	 * and no MIDI.
+	 */
 	USB_DEVICE_VENDOR_SPEC(0x0582, 0x003b),
 	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
 		.vendor_name = "BOSS",
 		.product_name = "GS-10",
-		.ifnum = 3,
-		.type = QUIRK_MIDI_FIXED_ENDPOINT,
-		.data = & (const snd_usb_midi_endpoint_info_t) {
-			.out_cables = 0x0003,
-			.in_cables  = 0x0003
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = & (const snd_usb_audio_quirk_t[]) {
+			{
+				.ifnum = 1,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = 3,
+				.type = QUIRK_MIDI_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = -1
+			}
 		}
 	}
 },
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
index b06a267..e6e6da1 100644
--- a/sound/usb/usx2y/usbusx2y.c
+++ b/sound/usb/usx2y/usbusx2y.c
@@ -1,6 +1,11 @@
 /*
  * usbusy2y.c - ALSA USB US-428 Driver
  *
+2005-04-14 Karsten Wiese
+	Version 0.8.7.2:
+	Call snd_card_free() instead of snd_card_free_in_thread() to prevent oops with dead keyboard symptom.
+	Tested ok with kernel 2.6.12-rc2.
+
 2004-12-14 Karsten Wiese
 	Version 0.8.7.1:
 	snd_pcm_open for rawusb pcm-devices now returns -EBUSY if called without rawusb's hwdep device being open.
@@ -143,7 +148,7 @@
 
 
 MODULE_AUTHOR("Karsten Wiese <annabellesgarden@yahoo.de>");
-MODULE_DESCRIPTION("TASCAM "NAME_ALLCAPS" Version 0.8.7.1");
+MODULE_DESCRIPTION("TASCAM "NAME_ALLCAPS" Version 0.8.7.2");
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{TASCAM(0x1604), "NAME_ALLCAPS"(0x8001)(0x8005)(0x8007) }}");
 
@@ -430,8 +435,6 @@
 	if (ptr) {
 		usX2Ydev_t* usX2Y = usX2Y((snd_card_t*)ptr);
 		struct list_head* p;
-		if (usX2Y->chip_status == USX2Y_STAT_CHIP_HUP)	// on 2.6.1 kernel snd_usbmidi_disconnect()
-			return;					// calls us back. better leave :-) .
 		usX2Y->chip.shutdown = 1;
 		usX2Y->chip_status = USX2Y_STAT_CHIP_HUP;
 		usX2Y_unlinkSeq(&usX2Y->AS04);
@@ -439,11 +442,11 @@
 		snd_card_disconnect((snd_card_t*)ptr);
 		/* release the midi resources */
 		list_for_each(p, &usX2Y->chip.midi_list) {
-			snd_usbmidi_disconnect(p, &snd_usX2Y_usb_driver);
+			snd_usbmidi_disconnect(p);
 		}
 		if (usX2Y->us428ctls_sharedmem) 
 			wake_up(&usX2Y->us428ctls_wait_queue_head);
-		snd_card_free_in_thread((snd_card_t*)ptr);
+		snd_card_free((snd_card_t*)ptr);
 	}
 }
 
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index 4c292e0..62dfd28 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -401,10 +401,8 @@
 	for (i = 0; i < NRURBS; i++)
 		usX2Y_urb_release(subs->urb + i, subs != subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]);
 
-	if (subs->tmpbuf) {
-		kfree(subs->tmpbuf);
-		subs->tmpbuf = NULL;
-	}
+	kfree(subs->tmpbuf);
+	subs->tmpbuf = NULL;
 }
 /*
  * initialize a substream's urbs